frontend/src/models/GeometryMapping.ts

133 lines
3.7 KiB
TypeScript

import { pond } from "protobuf-ts/pond";
// interface properties {
// exclusion: boolean;
// field: string;
// main: boolean;
// color: string;
// }
interface geoJSONGeometry {
coordinates: any[];
type: string;
}
/**
* GeometryMapping is a geoJSON structure that React-map-gl's map layers needs in order to draw the shape on the map
*/
export class GeometryMapping {
public type: "Feature" = "Feature";
public geometry: geoJSONGeometry = {
coordinates: [],
type: ""
};
public static geoJSON(shape: string, shapes: pond.Shape[], holes?: pond.Shape[]) {
let gm = new GeometryMapping();
gm.geometry = getGeometry(shape, shapes, holes);
return gm;
}
}
//helper function to build the correct geometry for the desired shape
export function getGeometry(
shape: string,
shapes: pond.Shape[],
holes?: pond.Shape[]
): { coordinates: any[]; type: string } {
let geo: geoJSONGeometry = {
coordinates: [],
type: shape
};
switch (shape) {
case "LineString":
if (shapes[0]) {
shapes[0].points.forEach(point => {
geo.coordinates.push([point.longitude, point.latitude]);
});
}
break;
case "Polygon":
if (shapes[0]) {
let shapeArray: any[] = [];
shapes[0].points.forEach(point => {
shapeArray.push([point.longitude, point.latitude]);
});
geo.coordinates.push(shapeArray);
}
if (holes) {
holes.forEach(hole => {
let holeArray: any[] = [];
hole.points.forEach(point => {
holeArray.push([point.longitude, point.latitude]);
});
geo.coordinates.push(holeArray);
});
}
break;
case "MultiPolygon":
//this is an array of polygons (one polygon is an array of shapes, the first being the border, and all subsequent shapes being holes in that border)
shapes.forEach(shape => {
let polygon: any[] = [];
let shapeArray: any[] = [];
shape.points.forEach(point => {
shapeArray.push([point.longitude, point.latitude]);
});
polygon.push(shapeArray);
//just note JD and CNH dont do holes in their fields so this part will be UNTESTED until handling drawing multi polygons for our fields
if (holes) {
let holeArray: any[] = [];
holes.forEach(hole => {
if (hole.key === shape.key) {
hole.points.forEach(point => {
holeArray.push([point.longitude, point.latitude]);
});
}
polygon.push(holeArray);
});
}
geo.coordinates.push(polygon);
});
break;
default:
break;
}
return geo;
}
/**
* takes in a 2D array of numbers an builds then into a shape object that can be added to either the holes or shapes of geoData
* @param coordinates an array of number pairs
* @returns pond.shape object using that array
*/
export function shapeFromCoords(coordinates: number[][]): pond.Shape {
let shape = pond.Shape.create();
coordinates.forEach(pair => {
shape.points.push(
pond.Coordinates.create({
longitude: pair[0],
latitude: pair[1]
})
);
});
return shape;
}
export function coordDistance(lat1: number, long1: number, lat2: number, long2: number) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2 - lat1); // deg2rad below
var dLon = deg2rad(long2 - long1);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg: number) {
return deg * (Math.PI / 180);
}