/********************************************************************** * * GEOS - Geometry Engine Open Source * http://geos.osgeo.org * * Copyright (C) 2013 Sandro Santilli * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * ********************************************************************** * * Last port: algorithm/Centroid.java r728 (JTS-0.13+) * **********************************************************************/ #pragma once #include #include // for composition #include // for std::unique_ptr // Forward declarations namespace geos { namespace geom { class Geometry; class Polygon; class CoordinateSequence; } } namespace geos { namespace algorithm { // geos::algorithm /** \brief * Computes the centroid of a [Geometry](@ref geom::Geometry) of any dimension. * * If the geometry is nomimally of higher dimension, but contains only * components having a lower effective dimension (i.e. zero length or area), * the centroid will be computed appropriately. * * ### Algorithm # * * - **Dimension = 2** - Based on the usual algorithm for calculating * the centroid as a weighted sum of the centroids * of a decomposition of the area into (possibly overlapping) triangles. * The algorithm has been extended to handle holes and multi-polygons. * See http://www.faqs.org/faqs/graphics/algorithms-faq/ * for further details of the basic approach. * - **Dimension = 1** - Computes the average of the midpoints * of all line segments weighted by the segment length. * - **Dimension = 0** - Compute the average coordinate over all points. * * If the input geometries are empty, a `null` Coordinate is returned. * */ class GEOS_DLL Centroid { public: /** \brief * Computes the centroid point of a geometry. * * @param geom the geometry to use * @param cent will be set to the centroid point, if any * * @return `true` if a centroid could be computed, * `false` otherwise (empty geom) */ static bool getCentroid(const geom::Geometry& geom, geom::CoordinateXY& cent); /** \brief * Creates a new instance for computing the centroid of a geometry */ Centroid(const geom::Geometry& geom) : areasum2(0.0), totalLength(0.0), ptCount(0) { add(geom); } /** \brief * Gets the computed centroid. * * @param cent will be set to the centroid point, if any * * @return `true` if a centroid could be computed, * `false` otherwise (empty geom) */ bool getCentroid(geom::CoordinateXY& cent) const; private: std::unique_ptr areaBasePt; geom::CoordinateXY triangleCent3; geom::CoordinateXY cg3; geom::CoordinateXY lineCentSum; geom::CoordinateXY ptCentSum; double areasum2; double totalLength; int ptCount; /** * Adds a Geometry to the centroid total. * * @param geom the geometry to add */ void add(const geom::Geometry& geom); void setAreaBasePoint(const geom::CoordinateXY& basePt); void add(const geom::Polygon& poly); void addShell(const geom::CoordinateSequence& pts); void addHole(const geom::CoordinateSequence& pts); void addTriangle(const geom::CoordinateXY& p0, const geom::CoordinateXY& p1, const geom::CoordinateXY& p2, bool isPositiveArea); /** * Computes three times the centroid of the triangle p1-p2-p3. * The factor of 3 is * left in to permit division to be avoided until later. */ static void centroid3(const geom::CoordinateXY& p1, const geom::CoordinateXY& p2, const geom::CoordinateXY& p3, geom::CoordinateXY& c); /** * Returns twice the signed area of the triangle p1-p2-p3. * The area is positive if the triangle is oriented CCW, and negative if CW. */ static double area2(const geom::CoordinateXY& p1, const geom::CoordinateXY& p2, const geom::CoordinateXY& p3); /** * Adds the line segments defined by an array of coordinates * to the linear centroid accumulators. * * @param pts an array of {@link Coordinate}s */ void addLineSegments(const geom::CoordinateSequence& pts); /** * Adds a point to the point centroid accumulator. * @param pt a {@link Coordinate} */ void addPoint(const geom::CoordinateXY& pt); }; } // namespace geos::algorithm } // namespace geos