Return to simpler and less efficient winding order algorithm
This commit is contained in:
+12
-103
@@ -14,110 +14,19 @@ import {coordinates as reverseCoordinates} from './reverse.js';
|
|||||||
* @return {boolean} Is clockwise.
|
* @return {boolean} Is clockwise.
|
||||||
*/
|
*/
|
||||||
export function linearRingIsClockwise(flatCoordinates, offset, end, stride) {
|
export function linearRingIsClockwise(flatCoordinates, offset, end, stride) {
|
||||||
// https://stackoverflow.com/a/1180256/2389327
|
// http://tinyurl.com/clockwise-method
|
||||||
// https://en.wikipedia.org/wiki/Curve_orientation#Orientation_of_a_simple_polygon
|
// https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
|
||||||
if ((end - offset) / stride >= 3) {
|
let edge = 0;
|
||||||
const minVertex = findCornerVertex(flatCoordinates, offset, end, stride);
|
let x1 = flatCoordinates[end - stride];
|
||||||
// Orientation matrix:
|
let y1 = flatCoordinates[end - stride + 1];
|
||||||
// [ 1 xa ya ]
|
for (; offset < end; offset += stride) {
|
||||||
// O = | 1 xb yb |
|
const x2 = flatCoordinates[offset];
|
||||||
// [ 1 xc yc ]
|
const y2 = flatCoordinates[offset + 1];
|
||||||
const previousVertex = findUniqueVertex(
|
edge += (x2 - x1) * (y2 + y1);
|
||||||
flatCoordinates,
|
x1 = x2;
|
||||||
offset,
|
y1 = y2;
|
||||||
end,
|
|
||||||
stride,
|
|
||||||
minVertex,
|
|
||||||
-1
|
|
||||||
);
|
|
||||||
const nextVertex = findUniqueVertex(
|
|
||||||
flatCoordinates,
|
|
||||||
offset,
|
|
||||||
end,
|
|
||||||
stride,
|
|
||||||
minVertex,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
const aX = flatCoordinates[previousVertex];
|
|
||||||
const aY = flatCoordinates[previousVertex + 1];
|
|
||||||
const bX = flatCoordinates[minVertex];
|
|
||||||
const bY = flatCoordinates[minVertex + 1];
|
|
||||||
const cX = flatCoordinates[nextVertex];
|
|
||||||
const cY = flatCoordinates[nextVertex + 1];
|
|
||||||
const determinant =
|
|
||||||
bX * cY + aX * bY + aY * cX - (aY * bX + bY * cX + aX * cY);
|
|
||||||
|
|
||||||
return determinant < 0;
|
|
||||||
}
|
}
|
||||||
}
|
return edge === 0 ? undefined : edge > 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the next unique vertex in forward or backward direction of a ring.
|
|
||||||
* @param {Array<number>} flatCoordinates Flat coordinates.
|
|
||||||
* @param {number} offset Offset.
|
|
||||||
* @param {number} end End.
|
|
||||||
* @param {number} stride Stride.
|
|
||||||
* @param {number} start Start vertex.
|
|
||||||
* @param {number} direction 1 for forward, -1 for backward.
|
|
||||||
* @return {number} vertex Index of the found vertex.
|
|
||||||
*/
|
|
||||||
function findUniqueVertex(
|
|
||||||
flatCoordinates,
|
|
||||||
offset,
|
|
||||||
end,
|
|
||||||
stride,
|
|
||||||
start,
|
|
||||||
direction
|
|
||||||
) {
|
|
||||||
let previousX, previousY, x, y;
|
|
||||||
let i = start;
|
|
||||||
while (x === previousX && y === previousY) {
|
|
||||||
previousX = flatCoordinates[i];
|
|
||||||
previousY = flatCoordinates[i + 1];
|
|
||||||
i += direction * stride;
|
|
||||||
if (i >= end) {
|
|
||||||
i = offset;
|
|
||||||
} else if (i < offset) {
|
|
||||||
i = end - stride;
|
|
||||||
}
|
|
||||||
x = flatCoordinates[i];
|
|
||||||
y = flatCoordinates[i + 1];
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find vertex along one edge of bounding box.
|
|
||||||
* In this case, we find smallest y; in case of tie also smallest x.
|
|
||||||
* @param {Array<number>} flatCoordinates Flat coordinates.
|
|
||||||
* @param {number} offset Offset.
|
|
||||||
* @param {number} end End.
|
|
||||||
* @param {number} stride Stride.
|
|
||||||
* @return {number} Corner vertex.
|
|
||||||
*/
|
|
||||||
function findCornerVertex(flatCoordinates, offset, end, stride) {
|
|
||||||
let iMinVertex = -1;
|
|
||||||
let minY = Infinity;
|
|
||||||
let minXAtMinY = Infinity;
|
|
||||||
for (let i = offset; i < end; i += stride) {
|
|
||||||
const x = flatCoordinates[i];
|
|
||||||
const y = flatCoordinates[i + 1];
|
|
||||||
if (y > minY) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y == minY) {
|
|
||||||
if (x >= minXAtMinY) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Minimum so far.
|
|
||||||
iMinVertex = i;
|
|
||||||
minY = y;
|
|
||||||
minXAtMinY = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return iMinVertex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user