UNPKG

@seasketch/geoprocessing

Version:

Geoprocessing and reporting framework for SeaSketch 2.0

128 lines 7.6 kB
import { describe, test, expect } from "vitest"; import { overlapPolygonArea } from "./overlapPolygonArea.js"; import { area } from "@turf/turf"; import squareFix from "../testing/fixtures/squareSketches.js"; import skFix from "../testing/fixtures/sketches.js"; import { firstMatchingMetric } from "../metrics/index.js"; import { testWithinPerc } from "../testing/index.js"; describe("overlapPolygonArea", () => { test("function is present", () => { expect(typeof overlapPolygonArea).toBe("function"); }); test("overlapPolygonArea - sketch polygon fully inside", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.insideTwoByPolySketch); expect(metrics[0].value).toBeCloseTo(area(squareFix.insideTwoByPolySketch)); }); test("overlapPolygonArea - two overlapping features should not affect result", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly, squareFix.twoByPoly], squareFix.insideTwoByPolySketch); expect(metrics[0].value).toBeCloseTo(area(squareFix.insideTwoByPolySketch)); }); test("overlapPolygonArea - sketch collection with overlapping sketches should not count overlapping area", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.overlapCollection, { includeChildMetrics: false }); const expectedArea = area(squareFix.insideTwoByPolySketch) + area(squareFix.halfInsideTwoBySketchPoly) / 2; expect(metrics[0].value).toBeCloseTo(expectedArea); }); test("overlapPolygonArea - sketch collection with overlapping sketches will double count if allowed", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.overlapCollection, { includeChildMetrics: false, solveOverlap: false }); const expectedArea = area(squareFix.insideTwoByPolySketch) + area(squareFix.halfInsideTwoBySketchPoly); expect(metrics[0].value).toBeCloseTo(expectedArea); }); test("overlapPolygonArea - sketch polygon fully inside - truncation", async () => { const metricsNoTruncation = await overlapPolygonArea("test", [squareFix.tiny], squareFix.insideTwoByPolySketch, { truncate: false, }); expect(metricsNoTruncation[0].value).toBe(0.012_364_345_868_141_814); const metricsTruncation = await overlapPolygonArea("test", [squareFix.tiny], squareFix.insideTwoByPolySketch, { truncate: true, }); expect(metricsTruncation[0].value).toBe(0.012_364); const metricsTruncationDefault = await overlapPolygonArea("test", [squareFix.tiny], squareFix.insideTwoByPolySketch); expect(metricsTruncationDefault[0].value).toBe(0.012_364); }); test("overlapPolygonArea - sketch multipolygon fully inside", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.insideTwoByMultipolySketch); expect(metrics[0].value).toBeCloseTo(area(squareFix.insideTwoByMultipolySketch)); }); test("overlapPolygonArea - multipolygon both arguments", async () => { const metrics = await overlapPolygonArea("test", [squareFix.insideTwoByMultipolySketch], squareFix.insideTwoByMultipolySketch); expect(metrics[0].value).toBeCloseTo(area(squareFix.insideTwoByMultipolySketch)); }); test.skip("overlapPolygonArea - sketch polygon half inside", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.halfInsideTwoBySketchPoly); expect(metrics.length).toEqual(1); // overlap should be ~50% of original sketch area const areaOf2 = area(squareFix.halfInsideTwoBySketchPoly); const percDiff = (metrics[0].value / (areaOf2 * 0.5)) % 1; expect(percDiff).toBeCloseTo(0); }); test("overlapPolygonArea - should not count holes", async () => { // console.log(JSON.stringify(sk.holeBlPoly)); const metrics = await overlapPolygonArea("test", [skFix.wholePoly], skFix.holeBlPoly); // 3487699295400.2056 qgis area result // 3473074014471.342 turf is close expect(metrics.length).toEqual(1); // const wholeArea = area(sk.wholePoly); // console.log("wholeArea", wholeArea); const holeArea = area(skFix.holeBlPoly); // console.log("holeArea", holeArea); const overlapArea = metrics[0].value; // console.log("overlapArea", overlapArea); const percDiff = Math.abs(overlapArea - holeArea) / holeArea; // console.log("percDiff", percDiff); expect(percDiff).toBeGreaterThan(0); expect(percDiff).toBeLessThan(1); }); test("overlapPolygonArea - sketch polygon fully outside should have zero area", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.outsideTwoByPolyTopRightSketch); expect(metrics.length).toEqual(1); expect(metrics[0].value).toBe(0); }); test("overlapPolygonArea - mixed poly sketch collection fully inside", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.mixedPolySketchCollection); expect(metrics.length).toBe(3); const ids = [ squareFix.mixedCollectionId, ...squareFix.mixedPolySketchCollection.features.map((sk) => sk.properties.id), ]; const areas = [ area(squareFix.mixedPolySketchCollection), ...squareFix.mixedPolySketchCollection.features.map((sk) => area(sk)), ]; const percs = [0.5, 1, 1]; // the poly and multipoly overlap 100% so overlapPolygonArea area should be half for (const [index, curSketchId] of ids.entries()) { // console.log("index", index); testWithinPerc(firstMatchingMetric(metrics, (m) => m.sketchId === curSketchId).value, areas[index] * percs[index]); } }); test("overlapPolygonArea - sketch collection half inside", async () => { const metrics = await overlapPolygonArea("test", [squareFix.twoByPoly], squareFix.sketchCollection); expect(metrics.length).toBe(4); const ids = [ squareFix.collectionId, ...squareFix.sketchCollection.features.map((sk) => sk.properties.id), ]; const areas = [ area(squareFix.sketchCollection), ...squareFix.sketchCollection.features.map((sk) => area(sk)), ]; const percs = [0.5, 1, 0.5, 0]; // expected percentage of sketch to overlap for (const [index, curSketchId] of ids.entries()) { testWithinPerc(firstMatchingMetric(metrics, (m) => m.sketchId === curSketchId).value, areas[index] * percs[index]); } }); /** * Zero polygon geometry sketch is generated by functions like clipToGeography in place of creating a null geometry * sketch, because turf and other libraries types don't handle null geometry well. With * a null geometry, toolbox functions will see that it has no overlap with any sketches (unless planning is occuring on null island) */ test("overlapPolygonArea - test that zero geometry sketch returns zero value metric", async () => { const metrics = await overlapPolygonArea("test", [skFix.topRightPoly], skFix.zero); expect(metrics.length).toBe(1); for (const metric of metrics) { expect(metric.value).toBe(0); } }); }); //# sourceMappingURL=overlapPolygonArea.test.js.map