/** * @module ol/geom/flat/interiorpoint */ import {ascending} from '../../array.js'; import {linearRingsContainsXY} from './contains.js'; /** * Calculates a point that is likely to lie in the interior of the linear rings. * Inspired by JTS's com.vividsolutions.jts.geom.Geometry#getInteriorPoint. * @param {Array} flatCoordinates Flat coordinates. * @param {number} offset Offset. * @param {Array} ends Ends. * @param {number} stride Stride. * @param {Array} flatCenters Flat centers. * @param {number} flatCentersOffset Flat center offset. * @param {Array} [dest] Destination. * @return {Array} Destination point as XYM coordinate, where M is the * length of the horizontal intersection that the point belongs to. */ export function getInteriorPointOfArray( flatCoordinates, offset, ends, stride, flatCenters, flatCentersOffset, dest ) { let i, ii, x, x1, x2, y1, y2; const y = flatCenters[flatCentersOffset + 1]; /** @type {Array} */ const intersections = []; // Calculate intersections with the horizontal line for (let r = 0, rr = ends.length; r < rr; ++r) { const end = ends[r]; x1 = flatCoordinates[end - stride]; y1 = flatCoordinates[end - stride + 1]; for (i = offset; i < end; i += stride) { x2 = flatCoordinates[i]; y2 = flatCoordinates[i + 1]; if ((y <= y1 && y2 <= y) || (y1 <= y && y <= y2)) { x = ((y - y1) / (y2 - y1)) * (x2 - x1) + x1; intersections.push(x); } x1 = x2; y1 = y2; } } // Find the longest segment of the horizontal line that has its center point // inside the linear ring. let pointX = NaN; let maxSegmentLength = -Infinity; intersections.sort(ascending); x1 = intersections[0]; for (i = 1, ii = intersections.length; i < ii; ++i) { x2 = intersections[i]; const segmentLength = Math.abs(x2 - x1); if (segmentLength > maxSegmentLength) { x = (x1 + x2) / 2; if (linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y)) { pointX = x; maxSegmentLength = segmentLength; } } x1 = x2; } if (isNaN(pointX)) { // There is no horizontal line that has its center point inside the linear // ring. Use the center of the the linear ring's extent. pointX = flatCenters[flatCentersOffset]; } if (dest) { dest.push(pointX, y, maxSegmentLength); return dest; } return [pointX, y, maxSegmentLength]; } /** * @param {Array} flatCoordinates Flat coordinates. * @param {number} offset Offset. * @param {Array>} endss Endss. * @param {number} stride Stride. * @param {Array} flatCenters Flat centers. * @return {Array} Interior points as XYM coordinates, where M is the * length of the horizontal intersection that the point belongs to. */ export function getInteriorPointsOfMultiArray( flatCoordinates, offset, endss, stride, flatCenters ) { let interiorPoints = []; for (let i = 0, ii = endss.length; i < ii; ++i) { const ends = endss[i]; interiorPoints = getInteriorPointOfArray( flatCoordinates, offset, ends, stride, flatCenters, 2 * i, interiorPoints ); offset = ends[ends.length - 1]; } return interiorPoints; }