133 lines
3.7 KiB
TypeScript
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);
|
|
}
|