diff --git a/public/js/app.js b/public/js/app.js index bea3dd4..a259e33 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -980,33 +980,22 @@ const pts = [start, end].slice().sort((a, b) => a[0] - b[0] || a[1] - b[1]); const isForward = (start[0] === pts[0][0] && start[1] === pts[0][1]); - // Geometry metrics for intersection avoidance - const dx = end[0] - start[0]; - const dy = end[1] - start[1]; - const dist = Math.sqrt(dx * dx + dy * dy); - const midLat = (start[1] + end[1]) / 2; - - // 1. Layering: Longer lines curve more to "loop over" shorter lines - const baseHeight = 0.15 + Math.min(0.45, dist / 400); - - // 2. Directionality: Bias curves toward the poles (North or South) to spread out global traffic - // Eastward (isForward) + North (midLat > 0) -> + curveness (Left/North) - // Westward (!isForward) + North (midLat > 0) -> - curveness (Right/North) - const poleDir = (midLat >= 0 ? 1 : -1); - const dirFactor = poleDir * (isForward ? 1 : -1); - - // 3. Jitter: Deterministic hash to avoid perfect overlap of close paths - const pathSeed = pts[0][0] + pts[0][1] * 2 + pts[1][0] * 3 + pts[1][1] * 4; - const curveJitter = (Math.abs(Math.sin(pathSeed)) * 0.1) - 0.05; - - // Calculate final curveness: layer by distance + spread group + bias toward poles - let finalCurve = 0; - const step = Math.min(0.2, 0.4 / Math.ceil(count / 2)); - const magnitude = baseHeight + (Math.floor(i / 2) * step); - const spread = (i % 2 === 0) ? magnitude : -magnitude; + // Calculate a stable seed for this unique pair of coordinates + // This ensures that different paths (e.g., A-B vs C-D) always have slightly different curvatures + const pathHash = Math.abs(Math.sin(pts[0][0] * 12.9898 + pts[0][1] * 78.233 + pts[1][0] * 43.123 + pts[1][1] * 21.312)); - // Combining all factors: dirFactor makes i=0 always point toward its respective pole - finalCurve = (dirFactor * spread) + curveJitter; + // Base curvature: 0.12 - 0.25 (depends on distance and geographical coordinates) + const dist = Math.sqrt(Math.pow(end[0] - start[0], 2) + Math.pow(end[1] - start[1], 2)); + const baseCurve = 0.12 + Math.min(0.08, dist / 1000) + (pathHash * 0.05); + + // Eye-pattern spreading: + // A->B and B->A will always take opposite sides of the path. + // Multiple connections between the same points will spread outward. + const spreadIndex = Math.floor(i / 2); + const spreadSign = (i % 2 === 0 ? 1 : -1); + const spreadFactor = spreadSign * (1 + spreadIndex * 0.5); + + const finalCurve = baseCurve * spreadFactor * (isForward ? 1 : -1); finalSeries.push({ type: 'lines',