geos/include/geos/algorithm/Centroid.h

160 строки
4.7 KiB
C++

/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2013 Sandro Santilli <strk@kbt.io>
*
* 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+)
*
**********************************************************************/
#ifndef GEOS_ALGORITHM_CENTROID_H
#define GEOS_ALGORITHM_CENTROID_H
#include <geos/export.h>
#include <geos/geom/Coordinate.h> // for composition
#include <memory> // 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::Coordinate& 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::Coordinate& cent) const;
private:
std::unique_ptr<geom::Coordinate> areaBasePt;
geom::Coordinate triangleCent3;
geom::Coordinate cg3;
geom::Coordinate lineCentSum;
geom::Coordinate 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::Coordinate& basePt);
void add(const geom::Polygon& poly);
void addShell(const geom::CoordinateSequence& pts);
void addHole(const geom::CoordinateSequence& pts);
void addTriangle(const geom::Coordinate& p0, const geom::Coordinate& p1, const geom::Coordinate& 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::Coordinate& p1, const geom::Coordinate& p2, const geom::Coordinate& p3,
geom::Coordinate& 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::Coordinate& p1, const geom::Coordinate& p2, const geom::Coordinate& 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::Coordinate& pt);
};
} // namespace geos::algorithm
} // namespace geos
#endif // GEOS_ALGORITHM_CENTROID_H