-
Notifications
You must be signed in to change notification settings - Fork 986
Description
Hi,
when creating a buffer around a LineString which has the same start vertex and the same end vertex the calculated inner buffer is wrong under special circumstances.
Here is a minimal code example which reproduces the wrong buffer. The first test case is a closed LineString which has a hole when creating a buffer of 500 meters. The second test case is a slightly different closed LineString which has no hole when creating a buffer of 500 meters around it. The third test case is a different example with a buffer of 2000 meters and an even bigger hole in the which shouldnt belong there.
import { buffer } from "@turf/turf";
import { LineString } from "geojson";
import { expect, it } from "vitest";
const bufferOptions: Parameters<typeof buffer>[2] = {
units: "meters",
steps: 0,
};
it.each<[string, LineString, number, number]>([
[
"Corridor with buffer should have hole",
{
type: "LineString",
coordinates: [
[11.9864449, 52.9652597],
[12.0249011, 52.9771682],
[12.0622777, 52.9652798],
[11.9864449, 52.9652597],
],
},
500,
2,
],
[
"Corridor with buffer shouldn't have hole",
{
type: "LineString",
coordinates: [
[11.9864449, 52.9652597],
[12.0243343, 52.9740445],
[12.0622777, 52.9652798],
[11.9864449, 52.9652597],
],
},
500,
1,
],
[
"Corridor with buffer shouldn't have hole",
{
type: "LineString",
coordinates: [
[12.4102822, 53.6462527],
[12.3735781, 53.6041575],
[12.4513151, 53.615602],
[12.4102822, 53.6462527],
],
},
2000,
1,
],
])("$1", (_name, lineString, radius, numRings) => {
const corridor = buffer(lineString, radius, bufferOptions)!;
expect(corridor.geometry.coordinates.length).toEqual(numRings);
});
The first test case where a hole is expected.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[11.9864449, 52.9652597],
[12.0249011, 52.9771682],
[12.0622777, 52.9652798],
[11.9864449, 52.9652597]
]
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[11.986452128660401, 52.960763100408464],
[12.062277041615708, 52.9607831983179],
[12.063684519759718, 52.960863761914545],
[12.065041550468617, 52.96110271332033],
[12.066299470082624, 52.96149148385769],
[12.067413166027833, 52.96201613211102],
[12.068342693716165, 52.96265784346482],
[12.069054708826204, 52.96339360433853],
[12.069523663664947, 52.964197027024746],
[12.069732724654596, 52.965039295637716],
[12.069674377879451, 52.96589019932362],
[12.069350700726773, 52.966719215730365],
[12.068773289577013, 52.96749660590088],
[12.067962845823466, 52.96819448130805],
[12.066948434788726, 52.96878780471482],
[12.065766443910471, 52.969255288887574],
[12.028387364746067, 52.981144782741886],
[12.02706246923208, 52.98147236900115],
[12.025658060755003, 52.98164164428673],
[12.02422580470309, 52.9816463812231],
[12.022818391870915, 52.98148640554473],
[12.021487598272255, 52.98116760251265],
[11.983028781062549, 52.96925800051954],
[11.98183337337055, 52.96879600437097],
[11.980804897063242, 52.96820602234372],
[11.979980573410897, 52.96750941060336],
[11.979390229493612, 52.96673138398435],
[11.979055219500575, 52.96590010282219],
[11.978987653405312, 52.965045653317176],
[11.979189960718271, 52.96419895840421],
[11.979654804815691, 52.96339065858894],
[11.980365350622026, 52.96265000326192],
[11.98129587564726, 52.96200379258628],
[11.982412702011077, 52.96147540819164],
[11.983675415562319, 52.96108396766854],
[11.985038327928422, 52.960843633365506],
[11.986452128660401, 52.960763100408464]
],
[
[12.017333025212631, 52.96977031465849],
[12.024854857987961, 52.972098339869596],
[12.032165528799508, 52.96977419741604],
[12.017333025212631, 52.96977031465849]
]
]
}
}
]
}
The second test case where no hole is expected. Also noteworthy is that the calculated hole is kind of mirrored/inverted.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[11.9864449, 52.9652597],
[12.0243343, 52.9740445],
[12.0622777, 52.9652798],
[11.9864449, 52.9652597]
]
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[11.986452128633372, 52.96076310040846],
[12.062277041642751, 52.96078319831792],
[12.063747133387176, 52.96087116589199],
[12.065159692119654, 52.961131780607424],
[12.066459409642427, 52.961554838473894],
[12.067595392214091, 52.96212377488877],
[12.068523152296521, 52.96281631269754],
[12.06920635040717, 52.9636053338648],
[12.069618218935268, 52.964459940742934],
[12.069742612068522, 52.96534666549963],
[12.069574640466282, 52.966230780442125],
[12.069120865462224, 52.96707765798852],
[12.068399044770057, 52.96785412704424],
[12.067437439235782, 52.96852977263269],
[12.066273707440773, 52.9690781278045],
[12.064953431224962, 52.96947771103499],
[12.027006887787016, 52.978243262558884],
[12.025691007582523, 52.978466269277284],
[12.024329654362797, 52.978541100948505],
[12.022968456852539, 52.97846524941931],
[12.02165303855271, 52.9782412570257],
[11.983760505127004, 52.96945560395751],
[11.98244121918252, 52.9690550948594],
[11.98127873731212, 52.96850596750384],
[11.980318580480697, 52.967829728048024],
[11.979598340679749, 52.96705285978615],
[11.979146209448798, 52.96620578538327],
[11.978979875485422, 52.965321674977176],
[11.979105834283425, 52.9644351469261],
[11.97951913648318, 52.963580912149034],
[11.980203584371624, 52.9627924151678],
[11.981132368418002, 52.9621005250386],
[11.98226911856279, 52.961532327360345],
[11.983569328854063, 52.961110064552784],
[11.984982099561302, 52.960850265772564],
[11.986452128633372, 52.96076310040846]
],
[
[12.02669255276277, 52.96977297957135],
[12.024339275254995, 52.96922781769787],
[12.021982645144059, 52.96977173037168],
[12.02669255276277, 52.96977297957135]
]
]
}
}
]
}
The third test case where no hole is expected. Here the wrong inner hole is better visible.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[12.4102822, 53.6462527],
[12.3735781, 53.6041575],
[12.4513151, 53.615602],
[12.4102822, 53.6462527]
]
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[12.434048190429264, 53.65743746814345],
[12.429841883642712, 53.66000497984985],
[12.424860610473045, 53.66202802983935],
[12.419301649861998, 53.66342645795963],
[12.413385247348295, 53.66414484704941],
[12.407345864483649, 53.664154726539344],
[12.401422854912267, 53.66345570488502],
[12.39585094299714, 53.6620754851424],
[12.390850889294208, 53.6600687630567],
[12.386620719209533, 53.657515052124324],
[12.383327867230836, 53.654515523282534],
[12.346643469754003, 53.612412084962976],
[12.344493313764195, 53.60922861559079],
[12.343400950658962, 53.605860882939936],
[12.34340584950627, 53.602431354553005],
[12.344507568178525, 53.59906471542497],
[12.346665807473236, 53.595883334947686],
[12.349801911479396, 53.593002822243626],
[12.353801754574436, 53.5905278308667],
[12.358519906166206, 53.58854826426606],
[12.363784919542637, 53.58713601848681],
[12.369405552340158, 53.586342378911134],
[12.37517769431382, 53.58619616415882],
[12.380891754152904, 53.58670268341412],
[12.45859860683452, 53.59814245377081],
[12.464295404451546, 53.59934778948034],
[12.469475927693365, 53.601200132664594],
[12.473934034403996, 53.60362580403688],
[12.477492233375447, 53.60652830501132],
[12.480008747692269, 53.60979214611756],
[12.481383174732379, 53.61328743223641],
[12.481560515172976, 53.616875024194066],
[12.480533405695052, 53.62041207287481],
[12.478342459767518, 53.62375770648294],
[12.475074695439954, 53.6267786446326],
[12.434048190429264, 53.65743746814345]
],
[
[12.415680155344077, 53.61330297239273],
[12.398237388931744, 53.62632681525116],
[12.431292590222798, 53.63119037277658],
[12.415680155344077, 53.61330297239273]
]
]
}
}
]
}
Latest Turf version is used which was 7.2.0 at the time of filing this bug report.
It may be related to #2920.