From ba2f21143882eed1d2d0bcd57ab16826e234a173 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Tue, 18 Aug 2026 11:43:28 +0300 Subject: [PATCH] fix(tactical): remove label spam on terrain grid, refine realistic cliff gradient >= 28 deg, and soften overlay opacities --- apps/web/src/pages/TacticalDefenseView.tsx | 67 +++++++++++++--------- apps/web/src/utils/elevationService.ts | 51 ++++++++++++---- 2 files changed, 80 insertions(+), 38 deletions(-) diff --git a/apps/web/src/pages/TacticalDefenseView.tsx b/apps/web/src/pages/TacticalDefenseView.tsx index d61775b..2795a63 100644 --- a/apps/web/src/pages/TacticalDefenseView.tsx +++ b/apps/web/src/pages/TacticalDefenseView.tsx @@ -551,11 +551,11 @@ export const TacticalDefenseView: React.FC = () => { 'fill-opacity': [ 'match', ['get', 'layerType'], - 'cliff', 0.50, - 'urban', 0.28, - 'hazard', 0.32, - 'slope-sector', 0.18, - 0.2 + 'cliff', 0.38, + 'urban', 0.20, + 'hazard', 0.24, + 'slope-sector', 0.14, + 0.15 ] } }); @@ -566,18 +566,17 @@ export const TacticalDefenseView: React.FC = () => { source: 'tactical-terrain-spatial-src', filter: ['==', '$type', 'Polygon'], paint: { - 'line-color': ['get', 'color'], + 'line-color': [ + 'match', + ['get', 'layerType'], + 'cliff', '#ef4444', + 'rgba(255, 255, 255, 0.10)' + ], 'line-width': [ 'match', ['get', 'layerType'], - 'cliff', 3.5, - 2 - ], - 'line-dasharray': [ - 'match', - ['get', 'layerType'], - 'cliff', ['literal', [2, 1]], - ['literal', [3, 2]] + 'cliff', 1.8, + 0.4 ] } }); @@ -592,10 +591,10 @@ export const TacticalDefenseView: React.FC = () => { 'line-width': [ 'match', ['get', 'layerType'], - 'cliff', 4.5, - 'road', 4.5, - 'wadi', 3.5, - 3 + 'cliff', 3.5, + 'road', 4.0, + 'wadi', 3.0, + 2.5 ], 'line-dasharray': [ 'match', @@ -608,21 +607,37 @@ export const TacticalDefenseView: React.FC = () => { } }); + initialMap.addLayer({ + id: 'tactical-terrain-spatial-points', + type: 'circle', + source: 'tactical-terrain-spatial-src', + filter: ['==', '$type', 'Point'], + paint: { + 'circle-radius': 5, + 'circle-color': ['coalesce', ['get', 'color'], '#38bdf8'], + 'circle-stroke-width': 2, + 'circle-stroke-color': '#ffffff' + } + }); + initialMap.addLayer({ id: 'tactical-terrain-spatial-labels', type: 'symbol', source: 'tactical-terrain-spatial-src', + filter: ['all', ['==', '$type', 'Point'], ['has', 'title']], layout: { 'text-field': ['get', 'title'], - 'text-size': 11, + 'text-size': 12, 'text-font': ['Noto Sans Bold', 'Open Sans Bold'], - 'text-anchor': 'center', - 'symbol-placement': 'point' + 'text-anchor': 'bottom', + 'text-offset': [0, -0.6], + 'symbol-placement': 'point', + 'text-allow-overlap': false }, paint: { 'text-color': '#ffffff', 'text-halo-color': '#0f172a', - 'text-halo-width': 2 + 'text-halo-width': 2.5 } }); @@ -1674,14 +1689,14 @@ ${terrainResult.tacticalRecommendations.map((r, i) => `${i + 1}. ${r}`).join('\n
-
-
25°): ${terrainResult.slopeDistribution.cliffPercentage}%`} /> +
+
■ منبسط (<7°): {terrainResult.slopeDistribution.flatPercentage}% ■ متموج (7-15°): {terrainResult.slopeDistribution.moderatePercentage}% - ■ وعر (15-25°): {terrainResult.slopeDistribution.steepPercentage}% - ■ جروف صخرية (>25°): {terrainResult.slopeDistribution.cliffPercentage}% + ■ وعر (15-28°): {terrainResult.slopeDistribution.steepPercentage}% + ■ جروف صخرية (≥28°): {terrainResult.slopeDistribution.cliffPercentage}%
diff --git a/apps/web/src/utils/elevationService.ts b/apps/web/src/utils/elevationService.ts index 2a66376..ab57ec2 100644 --- a/apps/web/src/utils/elevationService.ts +++ b/apps/web/src/utils/elevationService.ts @@ -837,11 +837,11 @@ export async function calculateTerrainStudy( const p4 = [p4Coord.lng, p4Coord.lat]; // Military Grade Slope & Barrier Classification: - // - Flat (GO): < 7° - // - Rolling (SLOW-GO): 7° - 15° - // - Rugged / Steep (SEVERE SLOW-GO): 15° - 25° - // - Cliffs & Natural Rock Barriers (NO-GO): > 25° or vertical drop >= 12m - const isCliff = slopeDeg >= 25 || (slopeDeg >= 18 && localDrop >= 10) || localDrop >= 18; + // - Flat (GO): < 7° (< 12%) + // - Rolling (SLOW-GO): 7° - 15° (12% - 27%) + // - Rugged / Mountainous (SEVERE SLOW-GO): 15° - 28° (27% - 53%) + // - Natural Cliffs & Rock Escarpments (NO-GO): >= 28° (Physical vertical barrier) + const isCliff = slopeDeg >= 28; if (isCliff) { cliffCount++; @@ -850,18 +850,17 @@ export async function calculateTerrainStudy( lng: Number(cellCenterLng.toFixed(5)), dropMeters: localDrop, slopeDegrees: slopeDeg, - label: `🧗‍♂️ قاطع صخري وجرف حاد (سقوط ${localDrop}م - ميل ${slopeDeg}°)`, + label: `🧗‍♂️ جرف صخري حاد (${localDrop}م / ${slopeDeg}°)`, tacticalImpact: 'مانع طبيعي قطعي - غير قابل لاجتياز الدروع والآليات، يفرض ممرات إجبارية' }); - // Add prominent cliff barrier polygon & line + // Add cliff barrier polygon without title label spam spatialFeatures.push({ type: 'Feature', properties: { layerType: 'cliff', category: 'natural-obstacle', - color: '#dc2626', - title: `🧗‍♂️ قاطع صخري وجرف حاد (${localDrop}م / ${slopeDeg}°)`, + color: '#ef4444', slope: slopeDeg, drop: localDrop, elevation: cellElevAvg @@ -879,7 +878,6 @@ export async function calculateTerrainStudy( layerType: 'slope-sector', category: 'severe-slow-go', color: '#f97316', - title: `انحدار جبلي وعر (SEVERE SLOW-GO) [${slopeDeg}°]`, slope: slopeDeg, elevation: cellElevAvg }, @@ -896,7 +894,6 @@ export async function calculateTerrainStudy( layerType: 'slope-sector', category: 'slow-go', color: '#eab308', - title: `تضاريس متموجة (SLOW-GO) [${slopeDeg}°]`, slope: slopeDeg, elevation: cellElevAvg }, @@ -913,7 +910,6 @@ export async function calculateTerrainStudy( layerType: 'slope-sector', category: 'go', color: '#22c55e', - title: `ممر حركة منبسط (GO) [${slopeDeg}°]`, slope: slopeDeg, elevation: cellElevAvg }, @@ -926,6 +922,37 @@ export async function calculateTerrainStudy( } } + // Add Key Terrain POI Points (Only these will display text badges on the map) + spatialFeatures.push({ + type: 'Feature', + properties: { + category: 'peak', + layerType: 'poi', + title: `▲ أعلى قمة: ${highestPoint.elevation}م`, + elevation: highestPoint.elevation, + color: '#22c55e' + }, + geometry: { + type: 'Point', + coordinates: [highestPoint.lng, highestPoint.lat] + } + }); + + spatialFeatures.push({ + type: 'Feature', + properties: { + category: 'valley', + layerType: 'poi', + title: `▼ أخفض نقطة: ${lowestPoint.elevation}م`, + elevation: lowestPoint.elevation, + color: '#06b6d4' + }, + geometry: { + type: 'Point', + coordinates: [lowestPoint.lng, lowestPoint.lat] + } + }); + // 5. Statistics of Slope Distribution const totalCells = Math.max(1, slopeValues.length); const flatPct = Math.round((flatCount / totalCells) * 100);