mirror of
git://f0xx.org/ac/ac-be-hub
synced 2026-08-09 20:59:23 +03:00
fix(globe3d=11): geographic mercator land with full lon wrap
Ortho hub SVG only covers one fitted hemisphere — left empty on rotate. Sample mercator-flat by lon/lat with U-wrap and inner_sy lat compress. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
* globe3d=8: hub SVG ellipse trace (breaks under rotation — deprecated).
|
||||
* globe3d=9: v4 sphere grid only (thin E–W + N–S) — proper rotation baseline.
|
||||
* globe3d=10: v4 visible-arc → screen ellipse (hub ry), disk-clipped.
|
||||
* globe3d=11: v10 grid + ortho hub land + affine flat-plate wrap fallback.
|
||||
* globe3d=11: v10 grid + geographic mercator-flat land (360° U-wrap).
|
||||
*/
|
||||
export const GLOBE_VIEW = { imgW: 1920, imgH: 1080, cx: 720, cy: 560, r: 322, rim: 330 };
|
||||
|
||||
@@ -27,6 +27,8 @@ const CONTINENT_INNER_TX = 223.66088631984587;
|
||||
const CONTINENT_INNER_TY = 238.0;
|
||||
const CONTINENT_INNER_SX = 1.2408477842003853;
|
||||
const CONTINENT_INNER_SY = 1.2408477842003853;
|
||||
/** Map plate center longitude (extract_red_polygons.py CENTER_LON). */
|
||||
const MERCATOR_LON_CENTER = (12 * Math.PI) / 180;
|
||||
const RASTER_SCALE = 2;
|
||||
const AXIS_STEPS = 160;
|
||||
const SPHERE_AXIS_STEPS = 180;
|
||||
@@ -948,11 +950,13 @@ function sampleFlatPlateFromHub(mercFlat, hpX, hpY) {
|
||||
return sampleImageDataBilinearWrapU(mercFlat.data, mercFlat.w, mercFlat.h, sx, sy);
|
||||
}
|
||||
|
||||
/** Sphere tex → mercator-flat plate (lon offset + inverse Mercator Y). */
|
||||
/** Sphere tex → mercator-flat plate (lon center + inverse Mercator Y). */
|
||||
function sampleMercFlatFromTex(mercFlat, tex) {
|
||||
const ll = texLonLat(tex);
|
||||
const lon = wrapLon(ll.lon + (12 * Math.PI) / 180);
|
||||
return sampleMercFlat(mercFlat, lon, ll.lat);
|
||||
const lon = wrapLon(ll.lon + MERCATOR_LON_CENTER);
|
||||
const lat =
|
||||
Math.max(-1.52, Math.min(1.52, ll.lat / CONTINENT_INNER_SY));
|
||||
return sampleMercFlat(mercFlat, lon, lat);
|
||||
}
|
||||
|
||||
function isLandPixel(r, g, b, a) {
|
||||
@@ -1063,19 +1067,13 @@ function sampleLandRgbaMercator(mercFlat, tex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** globe3d=11 — ortho hub (reference N–S) + wrapped flat-plate fallback. */
|
||||
function sampleLandVisibleHemisphere(continents, mercFlat, tex) {
|
||||
/** globe3d=11 — geographic mercator wrap (360°); z > LIMB_Z only. */
|
||||
function sampleLandVisibleHemisphere(mercFlat, tex) {
|
||||
if (tex.z <= LIMB_Z) {
|
||||
return null;
|
||||
}
|
||||
const ortho = sampleHub(continents, tex);
|
||||
if (isSolidContinentPixel(ortho[0], ortho[1], ortho[2], ortho[3])) {
|
||||
return hubContinentRgba(ortho);
|
||||
}
|
||||
const hpX = GLOBE_VIEW.cx + tex.x * GLOBE_VIEW.r;
|
||||
const hpY = GLOBE_VIEW.cy - tex.y * GLOBE_VIEW.r;
|
||||
const flat = sampleFlatPlateFromHub(mercFlat, hpX, hpY);
|
||||
if (flat && isHubContinentPixel(flat[0], flat[1], flat[2], flat[3])) {
|
||||
const flat = sampleMercFlatFromTex(mercFlat, tex);
|
||||
if (isHubContinentPixel(flat[0], flat[1], flat[2], flat[3])) {
|
||||
return hubContinentRgba(flat);
|
||||
}
|
||||
return null;
|
||||
@@ -1291,7 +1289,7 @@ export async function mountHubGlobe(stage, opts) {
|
||||
cy,
|
||||
r,
|
||||
fillDiskRegion(ctx, cx, cy, r, rotation, function (tex) {
|
||||
const l = sampleLandVisibleHemisphere(continents, mercFlat, tex);
|
||||
const l = sampleLandVisibleHemisphere(mercFlat, tex);
|
||||
return l || [0, 0, 0, 0];
|
||||
})
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user