utils/polyline/calculate-centroid.js

"use strict";
/**
 * @namespace geometryUtils
 * @description Utilities for geometric calculations, including centroid calculation and polyline conversion.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateCentroid = calculateCentroid;
exports.convertRingsToPolyline = convertRingsToPolyline;
/**
 * @memberof geometryUtils
 */
/**
 * Calculates the centroid of a closed polyline.
 *
 * @memberof geometryUtils
 * @function calculateCentroid
 * @param {Polyline} polyline - An array of points representing the polyline.
 * @returns {Point2d|null} The centroid as a Point2d, or `null` if the polyline is invalid.
 * @throws {Error} Throws an error if the polyline has fewer than 3 vertices.
 * @example
 * const polyline = [
 *   { x: 0, y: 0 },
 *   { x: 4, y: 0 },
 *   { x: 4, y: 3 },
 *   { x: 0, y: 3 },
 *   { x: 0, y: 0 }
 * ];
 * const centroid = calculateCentroid(polyline);
 * console.log(centroid); // { x: 2, y: 1.5 }
 */
function calculateCentroid(polyline) {
    let centroidX = 0;
    let centroidY = 0;
    let signedArea = 0;
    let x0, y0, x1, y1, a;
    const numVerts = polyline.length;
    if (numVerts < 3) {
        return null;
    }
    // Calculate area and centroid
    for (let i = 0; i < numVerts - 1; i++) {
        x0 = polyline[i].x;
        y0 = polyline[i].y;
        x1 = polyline[i + 1].x;
        y1 = polyline[i + 1].y;
        a = x0 * y1 - x1 * y0;
        signedArea += a;
        centroidX += (x0 + x1) * a;
        centroidY += (y0 + y1) * a;
    }
    // Close the polygon by connecting the last point to the first
    x0 = polyline[numVerts - 1].x;
    y0 = polyline[numVerts - 1].y;
    x1 = polyline[0].x;
    y1 = polyline[0].y;
    a = x0 * y1 - x1 * y0;
    signedArea += a;
    centroidX += (x0 + x1) * a;
    centroidY += (y0 + y1) * a;
    signedArea *= 0.5;
    centroidX /= 6.0 * signedArea;
    centroidY /= 6.0 * signedArea;
    return {
        x: centroidX || 0,
        y: centroidY || 0
    };
}
/**
 * Converts a rings array to a Polyline format.
 *
 * @memberof geometryUtils
 * @function convertRingsToPolyline
 * @param {number[][][]} rings - An array representing rings of points in the form [[[x, y], [x, y], ...]].
 * @returns {Polyline} A Polyline array with points in `{x, y}` format.
 * @throws {Error} Throws an error if the input is invalid.
 * @example
 * const rings = [
 *   [
 *     [0, 0],
 *     [4, 0],
 *     [4, 3],
 *     [0, 3],
 *     [0, 0]
 *   ]
 * ];
 * const polyline = convertRingsToPolyline(rings);
 * console.log(polyline);
 * // Output: [{ x: 0, y: 0 }, { x: 4, y: 0 }, { x: 4, y: 3 }, { x: 0, y: 3 }, { x: 0, y: 0 }]
 */
function convertRingsToPolyline(rings) {
    if (!rings || !Array.isArray(rings) || rings.length === 0) {
        throw new Error("Invalid rings data: Expected a non-empty array.");
    }
    return rings[0].map(([x, y]) => {
        if (typeof x !== 'number' || typeof y !== 'number') {
            throw new Error("Invalid point format: Expected an array of [x, y] numbers.");
        }
        return { x, y };
    });
}
// Example usage
/**
const geometry = {
    rings: [
        [
            [2653639.5557742715, 760547.43011811376],
            [2653692.8054461926, 760546.05479001999],
            [2653741.0846456736, 760544.71030183136],
            [2653762.3566273004, 760242.97769029438]
        ]
    ]
};

// Convert rings to polyline format and calculate the centroid
const polyline = convertRingsToPolyline(geometry.rings);
const centroid = calculateCentroid(polyline);
console.log("Centroid:", centroid);
*/