got the field on the map and the setting the initial bounding box

This commit is contained in:
csawatzky 2025-08-20 16:02:43 -06:00
parent 399f449ca4
commit 96958c12a0
3 changed files with 80 additions and 57 deletions

View file

@ -94,59 +94,12 @@ export default function FieldList() {
return totalAcres; return totalAcres;
}; };
// const fieldList = (fields: Field[]) => {
// return fields.map((field, index) => (
// <TableRow key={index}>
// <TableCell>{field.fieldName()}</TableCell>
// <TableCell>{field.landLoc()}</TableCell>
// <TableCell>
// {field.crop() === pond.Grain.GRAIN_CUSTOM
// ? field.customType()
// : GrainDescriber(field.crop()).name}
// </TableCell>
// <TableCell>{field.calculateAcres()}</TableCell>
// <TableCell>
// {field.permissions.includes(pond.Permission.PERMISSION_WRITE) && (
// <Button
// variant="contained"
// color="primary"
// onClick={() => {
// setFieldForPlan(field);
// setOpenHarvestSettings(true);
// }}>
// New Crop Plan
// </Button>
// )}
// </TableCell>
// </TableRow>
// ));
// }
// const fieldTable = (fields: Field[]) => {
// return (
// <TableContainer component={Paper}>
// <Table style={{ minWidth: 1000 }}>
// <TableHead>
// <TableRow>
// <TableCell>Field Name</TableCell>
// <TableCell>Land Location</TableCell>
// <TableCell>Main Crop Type</TableCell>
// <TableCell>Acres ({calcTotalAcres(fields)} Total)</TableCell>
// <TableCell>Create New Plan</TableCell>
// </TableRow>
// </TableHead>
// <TableBody>{fieldList(fields)}</TableBody>
// </Table>
// </TableContainer>
// )
// }
const columns: Column<Field>[] = [ const columns: Column<Field>[] = [
{ {
title: "View", title: "View",
render: row => { render: row => {
return ( return (
<Box height={200} width={200}> <Box margin={1} height={200} width={200}>
<FieldMinimap field={row} /> <FieldMinimap field={row} />
</Box> </Box>
) )
@ -184,10 +137,9 @@ const columns: Column<Field>[] = [
columns={columns} columns={columns}
rows={fields} rows={fields}
setPage={()=>{}} setPage={()=>{}}
hidePagination
handleRowsPerPageChange={()=>{}} handleRowsPerPageChange={()=>{}}
page={0} page={0}
pageSize={10} pageSize={1}
total={fields.length} total={fields.length}
/> />
) )

View file

@ -1,24 +1,58 @@
import { Box } from "@mui/material"; import { CircularProgress } from "@mui/material";
import { Field } from "models"; import { Field } from "models";
import { useRef } from "react"; import { useEffect, useState } from "react";
import Map, { MapRef } from "react-map-gl/mapbox"; import Map from "react-map-gl/mapbox";
import 'mapbox-gl/dist/mapbox-gl.css'; import 'mapbox-gl/dist/mapbox-gl.css';
import GeoMapLayer from "maps/mapLayers/geoMapLayer";
import { Feature, FeatureCollection } from "geojson";
import { GeometryMapping } from "models/GeometryMapping";
interface Props { interface Props {
field?: Field field: Field
} }
export default function FieldMinimap(props: Props) { export default function FieldMinimap(props: Props) {
const { field } = props const { field } = props
const MAPBOX_TOKEN = import.meta.env.VITE_MAPBOX_ACCESS_TOKEN; const MAPBOX_TOKEN = import.meta.env.VITE_MAPBOX_ACCESS_TOKEN;
const [geoCollection, setGeoCollection] = useState<FeatureCollection>();
useEffect(()=>{
let fieldData = field.settings.fieldGeoData
if(fieldData){
let fieldFeature = GeometryMapping.geoJSON(fieldData.geoShape, fieldData.shapes, fieldData.holes) as Feature;
fieldFeature.id = fieldData.objectKey;
fieldFeature.properties = {
title: fieldData.title,
objectKey: fieldData.objectKey,
fill: fieldData.colour,
lineWidth: fieldData.geoShape === "LineString" ? 5 : 2,
origin: fieldData.origin
};
let collection: FeatureCollection = {
type: "FeatureCollection",
features: [fieldFeature]
};
setGeoCollection(collection);
}
},[field])
return ( return geoCollection ?
(
<Map <Map
initialViewState={{
bounds: field.fieldBounds(.001)
}}
style={{width: "100%", height: "100%"}} style={{width: "100%", height: "100%"}}
mapboxAccessToken={MAPBOX_TOKEN} mapboxAccessToken={MAPBOX_TOKEN}
mapStyle="mapbox://styles/mapbox/satellite-streets-v11" mapStyle="mapbox://styles/mapbox/satellite-streets-v11"
>
<GeoMapLayer
objectCollection={geoCollection}
setInteractiveLayers={()=>{}}
/> />
</Map>
) )
:
(<CircularProgress />)
} }

View file

@ -5,6 +5,7 @@ import area from "@turf/area";
import { Feature } from "geojson"; import { Feature } from "geojson";
import { GeometryMapping } from "./GeometryMapping"; import { GeometryMapping } from "./GeometryMapping";
import GrainDescriber from "grain/GrainDescriber"; import GrainDescriber from "grain/GrainDescriber";
import { LngLat, LngLatBounds } from "mapbox-gl";
export class Field { export class Field {
public settings: pond.FieldSettings = pond.FieldSettings.create(); public settings: pond.FieldSettings = pond.FieldSettings.create();
@ -152,6 +153,42 @@ export class Field {
return coords; return coords;
} }
/**
* Returns a LngLatBounds object containing the southwest and northeast corners of a box to contain the field, spacing can also be provided
* to pad the sides of the bounding area
* @param spacing - an optional paramater that will expand the bounding area by the given long lat amount
* @returns LngLatBounds - an object containing the southwest and northeast coordinates of a bounding box
*/
public fieldBounds(spacing?: number): LngLatBounds {
let minLong = 0;
let minLat = 0;
let maxLong = 0;
let maxLat = 0;
if (this.settings.fieldGeoData) {
this.settings.fieldGeoData.shapes.forEach(shape => {
shape.points.forEach(pair => {
if (pair.longitude < minLong || minLong === 0) minLong = pair.longitude;
if (pair.longitude > maxLong || maxLong === 0) maxLong = pair.longitude;
if (pair.latitude < minLat || minLat === 0) minLat = pair.latitude;
if (pair.latitude > maxLat || maxLat === 0) maxLat = pair.latitude;
});
});
}
// let southWest = [minLong,minLat]
// let northEast = [maxLong,maxLat]
if(spacing){
minLong = minLong - spacing
minLat = minLat - spacing
maxLong = maxLong + spacing
maxLat = maxLat + spacing
}
return new LngLatBounds(
new LngLat(minLong, minLat),
new LngLat(maxLong, maxLat)
);
// return[southWest, northEast]
}
public grainName(): string { public grainName(): string {
if (this.grain() !== pond.Grain.GRAIN_INVALID) { if (this.grain() !== pond.Grain.GRAIN_INVALID) {
if (this.grain() === pond.Grain.GRAIN_CUSTOM) { if (this.grain() === pond.Grain.GRAIN_CUSTOM) {