Skip to content

Commit

Permalink
Use marchingsquares lib for turf-isoband and turf-isoline, fixes "fir…
Browse files Browse the repository at this point in the history
…st break" bug (#2527)

* Migrating isobands and isolines to use the third party marchingsquares library from NPM. This commit supercedes PR #1801 which is a few years old now. Resolves #1797 based on a test case mentioned in that issue (added to unit tests in isobands). Slight changes to resulting coordinates in most fixtures, though all fixtures verified visually using geojson.io

* Fixing turf-isolines to no longer ignore the first break passed. Where it looked like the unit tests have had a 0 break added as a work around e.g. 5 breaks but only 4 break properties, have removed the presumed workaround and reviewed test fixture output. Resolves #2129.

* Rolling back cloning workaround from commit d7c5322. This appears to have been unnecessary, possibly already having been fixed by adding linearRing: false to the isoContours call.
  • Loading branch information
smallsaucepan authored Nov 9, 2023
1 parent 6cb60c9 commit ef8b904
Show file tree
Hide file tree
Showing 23 changed files with 1,623 additions and 5,233 deletions.
53 changes: 20 additions & 33 deletions packages/turf-isobands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
} from "geojson";

import gridToMatrix from "./lib/grid-to-matrix";
import isoBands from "./lib/marchingsquares-isobands";
const { isoBands } = require("marchingsquares");

type GroupRingProps = { [prop: string]: string };
type GroupedRings =
Expand Down Expand Up @@ -163,20 +163,21 @@ function rescaleContours(
const scaleX = originalWidth / matrixWidth;
const scaleY = originalHeigth / matrixHeight;

const resize = (point: Position) => {
point[0] = point[0] * scaleX + x0;
point[1] = point[1] * scaleY + y0;
};

// resize and shift each point/line of the isobands
contours.forEach(function (contour) {
(contour.groupedRings as Position[][][]).forEach(function (lineRingSet) {
lineRingSet.forEach(function (lineRing) {
lineRing.forEach(resize);
});
});
return contours.map(function (contour) {
contour.groupedRings = (contour.groupedRings as Position[][][]).map(
function (lineRingSet) {
return lineRingSet.map(function (lineRing) {
return lineRing.map((point: Position) => [
point[0] * scaleX + x0,
point[1] * scaleY + y0,
]);
});
}
);

return contour;
});
return contours;
}

/* utility functions */
Expand All @@ -189,32 +190,18 @@ function rescaleContours(
* @returns {Array} array of the input LineString ordered by area
*/
function orderByArea(ringsCoords: Position[][]): Position[][] {
const ringsWithArea: { ring: Position[]; area: number }[] = [];
const areas: number[] = [];
ringsCoords.forEach(function (coords) {
// const poly = polygon([points]);
const ringArea = area(polygon([coords]));
// create an array of areas value
areas.push(ringArea);
const ringsWithArea = ringsCoords.map(function (coords) {
// associate each lineRing with its area
ringsWithArea.push({ ring: coords, area: ringArea });
return { ring: coords, area: area(polygon([coords])) };
});
areas.sort(function (a, b) {
ringsWithArea.sort(function (a, b) {
// bigger --> smaller
return b - a;
return b.area - a.area;
});
// create a new array of linearRings coordinates ordered by their area
const orderedByArea: Position[][] = [];
areas.forEach(function (area) {
for (let lr = 0; lr < ringsWithArea.length; lr++) {
if (ringsWithArea[lr].area === area) {
orderedByArea.push(ringsWithArea[lr].ring);
ringsWithArea.splice(lr, 1);
break;
}
}
return ringsWithArea.map(function (x) {
return x.ring;
});
return orderedByArea;
}

/**
Expand Down
Loading

0 comments on commit ef8b904

Please sign in to comment.