-
Notifications
You must be signed in to change notification settings - Fork 946
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
squareGrid result is only square in the unit of degree #2638
Comments
Example please. What are the coordinates of your square grid? Are you sure this is a turf issue and not the behavior of your map client? |
Firstly, thank you for your reply. As shown in the code below, distance and distance1 are not equal. Is there a problem with my understanding?The current calculation should not be related to the map engine, I am using Cesium. Looking forward to your criticism and correction.
|
@lxydft you are right, the distance in miles between your example points, in the X and Y direction, are not the same. But I do believe they are the same distance apart in Here is some additional log statements for your code to demonstrate: console.log(JSON.stringify(arr[0]))
console.log(JSON.stringify(arr[1]))
console.log(JSON.stringify(arr[2]))
console.log("distanceDeg1", arr[0][1] - arr[1][1])
console.log("distanceDeg2", arr[1][0] - arr[2][0]) Output:
The distance in degrees between your two example points in degrees is approximately the same, to within 13 decimal points which is very small. But calling turf.distance on those points produces a variable distance in miles. I believe this has to do with the haversine formula used by turf.distance and the nature of how a distance of 0.72 degrees is different in miles for longitude and latitude depending on where the points are on the Earth. I can leave this ticket open for documentation to be improved. I don't have a good answer on how to produce what you want. perhaps you can study how turfSquare works (it actually calls turfRectangle) -- turf/packages/turf-square-grid/index.ts Line 45 in a8038d0
See https://github.com/Turfjs/turf/blob/master/packages/turf-rectangle-grid/index.ts There are some past issues where people have found this function to not behave as expected: |
Here's a link that explains a little more about the variation in distance between longitude and latitude depending on where you are on earth -- https://www.usgs.gov/faqs/how-much-distance-does-a-degree-minute-and-second-cover-your-maps |
Thank you very much for your reply. I used a square grid mainly for the convenience of obtaining squares for some calculations. I remember that in previous versions, rectangular grids could be used to obtain squares. I couldn't find the code and could only find some screenshots. I thought I deleted this method in the 7.0 version of the document, but I just tested it and it still works. However, the current results cannot obtain a square in either miles or kilometers. So I think this method may cause a lot of trouble for users if it is only a square in the dimension of degree. I will continue to monitor it. |
@lxydft I wonder if [rhumbDestination](https://turfjs.org/docs/api/rhumbDestination might be able to be used to create what I think you want, equidistance measured in a fixed length unit. |
Okay, I think the behavior you are looking for @lxydft was actually lost in this PR, back in 2021 -- https://github.com/Turfjs/turf/pull/2106/files#, where for reasons explained better there, Turf switched from calculating cellSide using turf.distance, to using turf.convertLength. This may have been done to optimize for certain use cases, while not realizing the impact to others. Pre-2021 Codeconst rectangleGrid = (
bbox,
cellWidth,
cellHeight,
options
) => {
// Containers
const results = [];
const west = bbox[0];
const south = bbox[1];
const east = bbox[2];
const north = bbox[3];
const xFraction = cellWidth / turf.distance([west, south], [east, south], options);
const cellWidthDeg = xFraction * (east - west);
const yFraction =
cellHeight / turf.distance([west, south], [west, north], options);
const cellHeightDeg = yFraction * (north - south);
// rows & columns
const bboxWidth = east - west;
const bboxHeight = north - south;
const columns = Math.floor(bboxWidth / cellWidthDeg);
const rows = Math.floor(bboxHeight / cellHeightDeg);
// if the grid does not fill the bbox perfectly, center it.
const deltaX = (bboxWidth - columns * cellWidthDeg) / 2;
const deltaY = (bboxHeight - rows * cellHeightDeg) / 2;
// iterate over columns & rows
let currentX = west + deltaX;
for (let column = 0; column < columns; column++) {
let currentY = south + deltaY;
for (let row = 0; row < rows; row++) {
const cellPoly = turf.polygon(
[
[
[currentX, currentY],
[currentX, currentY + cellHeightDeg],
[currentX + cellWidthDeg, currentY + cellHeightDeg],
[currentX + cellWidthDeg, currentY],
[currentX, currentY],
],
],
options.properties
);
if (options.mask) {
if (turf.intersect(options.mask, cellPoly)) {
results.push(cellPoly);
}
} else {
results.push(cellPoly);
}
currentY += cellHeightDeg;
}
currentX += cellWidthDeg;
}
return turf.featureCollection(results);
}
//// EXAMPLE CODE ////
let squareGrid = rectangleGrid([-95, 30 ,-85, 40], 50, 50, {
units:'miles'
});
let arr = squareGrid.features[0].geometry.coordinates[0]
let from = turf.point(arr[0]);
let to = turf.point(arr[1]);
let options = {units: 'miles'};
let pointDistance = turf.distance(from, to, options);
console.log(JSON.stringify(arr[0]))
console.log(JSON.stringify(arr[1]))
console.log(JSON.stringify(arr[2]))
console.log("distanceDeg1", arr[0][1] - arr[1][1])
console.log("distanceDeg2", arr[1][0] - arr[2][0])
let from1 = turf.point(arr[1]);
let to1 = turf.point(arr[2]);
let distance1 = turf.distance(from1, to1, options);
console.log(pointDistance,distance1);
return turf.featureCollection([squareGrid, from, to, from1, to1]); Produces nearly equal cellSides in miles
Turf 7.0 Almost exactly equal cellSides by degrees only, regardless of units passed. More accurate but optimizes for degrees.
The best way forward might be to acknowledge if necessary, that there is no one size fits all, and have it use different algorithms under the hood based on the units passed. |
That doesn't sound ideal. It wouldn't be great if the results change drastically depending on the units used. Looking at #2106 I get the feeling rectangle-grid was working ok, except for when people tried to do it over massive areas. Perhaps we look at reverting the calculation method and direct some effort toward making that work in a wider variety of circumstances. |
Keeping this issue open for visibility. The current behavior of rectangle-grid and square-grid is now at least a little better documented (visible once the 7.1.0 API docs are published). But the current behavior of these functions is not optimal. A code workaround can be found above to get the behavior in 6.4.0 and prior, where the distance between grid cell sides will match the length and unit passed. Discussion has at least started about next steps, feedback welcome there - #2640 |
Please provide the following when reporting an issue:
.geojson
).The text was updated successfully, but these errors were encountered: