diff --git a/src/ol/geom/flat/orient.js b/src/ol/geom/flat/orient.js index ab95816fed..28b4acdec9 100644 --- a/src/ol/geom/flat/orient.js +++ b/src/ol/geom/flat/orient.js @@ -14,110 +14,19 @@ import {coordinates as reverseCoordinates} from './reverse.js'; * @return {boolean} Is clockwise. */ export function linearRingIsClockwise(flatCoordinates, offset, end, stride) { - // https://stackoverflow.com/a/1180256/2389327 - // https://en.wikipedia.org/wiki/Curve_orientation#Orientation_of_a_simple_polygon - if ((end - offset) / stride >= 3) { - const minVertex = findCornerVertex(flatCoordinates, offset, end, stride); - // Orientation matrix: - // [ 1 xa ya ] - // O = | 1 xb yb | - // [ 1 xc yc ] - const previousVertex = findUniqueVertex( - flatCoordinates, - offset, - 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; + // http://tinyurl.com/clockwise-method + // https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp + let edge = 0; + let x1 = flatCoordinates[end - stride]; + let y1 = flatCoordinates[end - stride + 1]; + for (; offset < end; offset += stride) { + const x2 = flatCoordinates[offset]; + const y2 = flatCoordinates[offset + 1]; + edge += (x2 - x1) * (y2 + y1); + x1 = x2; + y1 = y2; } -} - -/** - * Finds the next unique vertex in forward or backward direction of a ring. - * @param {Array} 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} 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; + return edge === 0 ? undefined : edge > 0; } /**