Improvements to tree size measurements

This commit is contained in:
2026-07-07 21:43:04 -05:00
parent 07c6a9e390
commit da6371b53f
4 changed files with 169 additions and 64 deletions
+66 -2
View File
@@ -1,7 +1,7 @@
import { collectGeoJSON, offset, pointsFromLngLat } from "./geometry.js";
import { getFeatureType, listFeatureTypeSchemas } from "./feature-types.js";
export const YARD_SCHEMA_VERSION = 2;
export const YARD_SCHEMA_VERSION = 3;
class YardFeature {
constructor(kind, geometryType, name, details = {}) {
@@ -286,7 +286,7 @@ export class FlowerBed extends PolygonFeature {
export class Plant extends PointFeature {
constructor(name = "Plant", details = {}, kind = "plant") {
super(kind, name, details);
super(kind, name, normalizePlantDetails(details));
}
}
@@ -324,6 +324,65 @@ export class Tree extends Plant {
}
}
function normalizePlantDetails(details) {
const {
canopyDiameter,
height,
measurements = [],
...restDetails
} = details;
const normalizedMeasurements = normalizePlantMeasurements(measurements);
if (!normalizedMeasurements.length && hasPlantSizeMeasurement(details)) {
normalizedMeasurements.push(
normalizePlantMeasurement({
canopyDiameter,
height,
}),
);
}
const latestMeasurement = normalizedMeasurements.at(-1);
return {
...restDetails,
...(normalizedMeasurements.length ? { measurements: normalizedMeasurements } : {}),
...(latestMeasurement?.canopyDiameter !== undefined
? { canopyDiameter: latestMeasurement.canopyDiameter }
: {}),
...(latestMeasurement?.height !== undefined
? { height: latestMeasurement.height }
: {}),
};
}
function normalizePlantMeasurements(measurements) {
if (!Array.isArray(measurements)) {
throw new Error("Plant measurements must be an array");
}
return measurements.map(normalizePlantMeasurement);
}
function normalizePlantMeasurement(measurement) {
if (!measurement || typeof measurement !== "object") {
throw new Error("Plant measurement entries must be objects");
}
const { canopyDiameter, height, measuredDate, ...restMeasurement } = measurement;
return {
...restMeasurement,
...(measuredDate ? { measuredDate } : {}),
...(canopyDiameter !== undefined ? { canopyDiameter } : {}),
...(height !== undefined ? { height } : {}),
};
}
function hasPlantSizeMeasurement(details) {
return details.canopyDiameter !== undefined || details.height !== undefined;
}
export class Sprinkler extends PointFeature {
constructor(name = "Sprinkler", details = {}) {
super("sprinkler", name, details);
@@ -337,6 +396,11 @@ export function collectYardData(features, groups = []) {
plantedDate: "date",
removedDate: "date",
};
collection.measurementFields = {
measuredDate: "date",
canopyDiameter: "number",
height: "number",
};
collection.featureTypes = listFeatureTypeSchemas();
collection.groups = groups.map((group) => ({
id: group.id,