Symptom
At high zoom in point mode over a dense cluster (e.g. Pyla-Koutsopetria, Cyprus), the explorer renders yellow and orange dots that visually match the Smithsonian source color in the legend. These dots are not actually Smithsonian samples — they're OpenContext samples whose translucent point primitives accumulate to yellow under WebGL blending when ~500+ stack at the same screen pixel.
Users naturally assume yellow = Smithsonian (per the legend) and the data is wrong. Reality: the data is correct, but the source-color encoding has been silently overloaded by density.
Reproduction
URL: https://isamples.org/explorer.html?search=pottery+Cyprus#v=1&lat=34.9836&lng=33.7064&alt=292&mode=point
Five red dots at moderate density. Two-to-three dots that look yellow or orange. Click one of the yellow dots → popup shows "Object 5506-41 / OpenContext" (not Smithsonian).
Evidence
Within 5 km of this view, the source-of-truth parquet (samples_map_lite) has 23,313 samples, 100% OpenContext, zero Smithsonian. Verified by direct DuckDB query against data.isamples.org. The H3 cluster summaries at res 4/6/8 also show OpenContext-dominant for every cell in the area.
In the live Cesium scene, all 4,391 visible samplePoints have RGBA = (0.863, 0.224, 0.071, 0.90) — exact OpenContext #DC3912. The h3Points collection has show=false. So nothing rendering at this view is anything other than OpenContext red.
Yet WebGL readPixels at the dense bucket centers returns yellow.
Density-vs-pixel-color correlation (live measurement):
| samples stacked at this 5px bucket |
rendered RGB |
hex |
appearance |
| 104 |
(220, 57, 18) |
#DC3912 |
exact OpenContext red |
| 141 |
(223, 58, 18) |
#DF3A12 |
red |
| 224 |
(255, 69, 22) |
#FF4516 |
red-orange (R saturates) |
| 384 |
(255, 119, 37) |
#FF7725 |
orange |
| 392 |
(255, 185, 58) |
#FFB93A |
orange-yellow |
| 564 |
(255, 174, 55) |
#FFAE37 |
orange-yellow |
| 647 |
(255, 255, 82) |
#FFFF52 |
pure yellow |
| 754 |
(255, 233, 74) |
#FFE94A |
yellow |
R saturates first (only takes ~2 stacks). G keeps accumulating from the 0.22 component until it also clamps near ~600 stacks. B stays low. Result: source-color drift along the red→orange→yellow axis purely as a function of stacking density.
The reproduction URL parks the camera in a 9,555-sample H3 res-8 cell — guaranteed to over-stack.
Mechanism
PointPrimitiveCollection.blendOption = OPAQUE_AND_TRANSLUCENT with disableDepthTestDistance set (issue #185 workaround) means all 4,391 translucent point quads render in submission order at the same depth. Cesium's translucent-point shader appears to accumulate color channel-wise; with pixelSize: 6 scaled to ~48px by scaleByDistance(1e2, 8, 2e5, 3) at alt=292m, the discs heavily overlap and the per-channel saturation drifts the perceived hue.
Why it matters
- False source attribution. Users with a quick glance and the legend in hand will read yellow as Smithsonian, especially in Cyprus where there are zero Smithsonian samples. This is a correctness problem dressed as a rendering problem.
- Affects every dense site. Pyla-Koutsopetria, Polis, Catalhöyük — anywhere a single H3 res-8 cell holds thousands of samples, you'll see this.
- Worse for OpenContext than other sources. SESAR (#3366CC, blue) and GEOME (#109618, green) have lower green/red components and would saturate differently. The exact failure mode is OpenContext → yellow because of where #DC3912 sits in RGB space.
Suggested fixes
(Pick one, or a combination; all are localized to explorer.qmd L2441-2467.)
- (A) Auto-cluster threshold. When the per-pixel stacking exceeds a threshold (say >50 stacks per pixel anywhere on screen), force-promote back to cluster mode and surface a phase message ("Cluster mode for clarity — zoom further to see individual samples"). Effort: small.
- (B) Opaque point fill. Drop the
.withAlpha(0.9) to .withAlpha(1.0). With fully opaque points, depth-test-disabled overlap will paint the front-most color rather than accumulate — preserves source-color truth at the cost of "I can't see what's behind." Effort: one line.
- (C) Smaller pixelSize at high zoom. The
NearFarScalar(1e2, 8, …) scales to 8× at 100 m altitude, making 6 px → 48 px. Capping the scale at 3-4× would still keep dots visible but reduce overlap area dramatically. Effort: tune one number.
- (D) Density-aware fragment shader. Custom point appearance that limits how many overlapping discs contribute to a pixel — proper fix, larger effort.
(B) is the cheapest sanity check; (A) is the most user-friendly. (C) is a good compromise.
Out of scope
- The popup click-through resolves correctly (picks a real OpenContext sample by Z-order). The bug is purely visual.
- Cluster mode (
h3Points) is unaffected — dominant_source is a single discrete value per cell.
Cross-refs
Acceptance
- Yellow dots at Pyla-Koutsopetria (the reproduction URL) read as OpenContext red, or
- A clear UI signal explains that the view is too dense for individual rendering, with appropriate fallback (cluster mode or capped-stack warning).
Symptom
At high zoom in point mode over a dense cluster (e.g. Pyla-Koutsopetria, Cyprus), the explorer renders yellow and orange dots that visually match the Smithsonian source color in the legend. These dots are not actually Smithsonian samples — they're OpenContext samples whose translucent point primitives accumulate to yellow under WebGL blending when ~500+ stack at the same screen pixel.
Users naturally assume yellow = Smithsonian (per the legend) and the data is wrong. Reality: the data is correct, but the source-color encoding has been silently overloaded by density.
Reproduction
URL: https://isamples.org/explorer.html?search=pottery+Cyprus#v=1&lat=34.9836&lng=33.7064&alt=292&mode=point
Five red dots at moderate density. Two-to-three dots that look yellow or orange. Click one of the yellow dots → popup shows "Object 5506-41 / OpenContext" (not Smithsonian).
Evidence
Within 5 km of this view, the source-of-truth parquet (
samples_map_lite) has 23,313 samples, 100% OpenContext, zero Smithsonian. Verified by direct DuckDB query againstdata.isamples.org. The H3 cluster summaries at res 4/6/8 also show OpenContext-dominant for every cell in the area.In the live Cesium scene, all 4,391 visible
samplePointshave RGBA = (0.863, 0.224, 0.071, 0.90) — exact OpenContext#DC3912. Theh3Pointscollection hasshow=false. So nothing rendering at this view is anything other than OpenContext red.Yet WebGL
readPixelsat the dense bucket centers returns yellow.Density-vs-pixel-color correlation (live measurement):
#DC3912#DF3A12#FF4516#FF7725#FFB93A#FFAE37#FFFF52#FFE94AR saturates first (only takes ~2 stacks). G keeps accumulating from the 0.22 component until it also clamps near ~600 stacks. B stays low. Result: source-color drift along the red→orange→yellow axis purely as a function of stacking density.
The reproduction URL parks the camera in a
9,555-sampleH3 res-8 cell — guaranteed to over-stack.Mechanism
PointPrimitiveCollection.blendOption = OPAQUE_AND_TRANSLUCENTwithdisableDepthTestDistanceset (issue #185 workaround) means all 4,391 translucent point quads render in submission order at the same depth. Cesium's translucent-point shader appears to accumulate color channel-wise; withpixelSize: 6scaled to ~48px byscaleByDistance(1e2, 8, 2e5, 3)at alt=292m, the discs heavily overlap and the per-channel saturation drifts the perceived hue.Why it matters
Suggested fixes
(Pick one, or a combination; all are localized to
explorer.qmdL2441-2467.).withAlpha(0.9)to.withAlpha(1.0). With fully opaque points, depth-test-disabled overlap will paint the front-most color rather than accumulate — preserves source-color truth at the cost of "I can't see what's behind." Effort: one line.NearFarScalar(1e2, 8, …)scales to 8× at 100 m altitude, making 6 px → 48 px. Capping the scale at 3-4× would still keep dots visible but reduce overlap area dramatically. Effort: tune one number.(B) is the cheapest sanity check; (A) is the most user-friendly. (C) is a good compromise.
Out of scope
h3Points) is unaffected —dominant_sourceis a single discrete value per cell.Cross-refs
Acceptance