diff --git a/src/svg/renderer.ts b/src/svg/renderer.ts index 48f9399..39402aa 100644 --- a/src/svg/renderer.ts +++ b/src/svg/renderer.ts @@ -377,8 +377,11 @@ function drawBezierRoute( /** * Coastline: routes edge-to-edge, fills one side with water. - * waterSide is stored on the feature: 1 = CW side, -1 = CCW side. - * This is stable across rotations — no heuristic needed. + * waterSide is stored on the feature: 1 or -1. + * + * Key fix: normalize edge pair order so CW distance from e1→e2 + * is always the SHORT way (≤3 steps). This makes waterSide=1 + * consistently mean "the short/concave side" at every rotation. */ function drawCoastlineFeature( ctx: CanvasRenderingContext2D, @@ -397,16 +400,25 @@ function drawCoastlineFeature( for (const pair of pairs) { if (pair.length === 2) { - const p1 = edgeMidpoints[pair[0]]; - const p2 = edgeMidpoints[pair[1]]; + // Normalize order: ensure CW distance from e1→e2 is ≤3 + let e1 = pair[0]; + let e2 = pair[1]; + const cwDist = ((e2 - e1) + 6) % 6; + if (cwDist > 3) { + // Swap so the short CW arc is from e1 to e2 + [e1, e2] = [e2, e1]; + } + + const p1 = edgeMidpoints[e1]; + const p2 = edgeMidpoints[e2]; const cp = { x: cx, y: cy }; - // Fill the water side using the explicit waterSide value + // Fill the water side ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.quadraticCurveTo(cp.x, cp.y, p2.x, p2.y); - const waterVerts = getVerticesOnSide(pair[0], pair[1], waterSide, vertices); + const waterVerts = getVerticesOnSide(e1, e2, waterSide, vertices); for (const v of waterVerts) { ctx.lineTo(v.x, v.y); }