function calculateLandmassCoverage(footprintGeoJSON, worldTopology) {
const countries = topojson.feature(worldTopology, worldTopology.objects.countries);
const landCoverage = [];
footprintGeoJSON.features.forEach(footprintFeature => {
const elevationAngle = footprintFeature.properties.elevationAngle;
let totalLandArea = 0;
let coveredCountries = [];
const footprintCoords = footprintFeature.geometry.coordinates[0];
countries.features.forEach(country => {
let isIntersecting = false;
let intersectionArea = 0;
if (country.geometry.type === "Polygon") {
const countryCoords = country.geometry.coordinates[0];
isIntersecting = countryCoords.some(coord =>
isPointInPolygon(coord, footprintCoords)
);
if (isIntersecting) {
intersectionArea = calculatePolygonIntersectionArea(
countryCoords, footprintCoords, country.properties.NAME || "Unknown"
);
}
} else if (country.geometry.type === "MultiPolygon") {
country.geometry.coordinates.forEach(polygon => {
const polyCoords = polygon[0];
const polyIntersects = polyCoords.some(coord =>
isPointInPolygon(coord, footprintCoords)
);
if (polyIntersects) {
isIntersecting = true;
intersectionArea += calculatePolygonIntersectionArea(
polyCoords, footprintCoords, country.properties.NAME || "Unknown"
);
}
});
}
// Also check if any footprint vertices are inside the country
if (!isIntersecting) {
isIntersecting = footprintCoords.some(coord => {
if (country.geometry.type === "Polygon") {
return isPointInPolygon(coord, country.geometry.coordinates[0]);
} else if (country.geometry.type === "MultiPolygon") {
return country.geometry.coordinates.some(polygon =>
isPointInPolygon(coord, polygon[0])
);
}
return false;
});
// If footprint point is inside country, estimate coverage
if (isIntersecting) {
intersectionArea = estimateCountryFootprintOverlap(country, footprintCoords);
}
}
if (isIntersecting) {
coveredCountries.push({
name: country.properties.NAME || country.properties.name || "Unknown",
iso: country.properties.ISO_A3 || country.properties.iso_a3 || "N/A",
areaKm2: Math.round(intersectionArea)
});
totalLandArea += intersectionArea;
}
});
landCoverage.push({
elevationAngle,
coveredCountries,
countryCount: coveredCountries.length,
totalLandAreaKm2: Math.round(totalLandArea),
footprintAreaKm2: Math.round(calculatePolygonAreaKm2(footprintCoords))
});
});
return landCoverage;
}
// Calculate approximate intersection area between two polygons
// Get polygon bounding box [minLon, minLat, maxLon, maxLat]
// Calculate rectangle area in km² using spherical geometry
// Estimate overlap area when footprint vertices are inside country