-
Notifications
You must be signed in to change notification settings - Fork 362
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add MinimumAreaRectangle, a bounding rectangle algorithm.
Port of locationtech/jts#977 This adds a MinimumAreaRectangle class implementing the standard "rotating-calipers` algorithm for computing a Minimum-Area Rectangle. MinimumDiameter.getMinimumRectangle was previously used for this, but it does not always compute the Minimum-Area Rectangle. It is kept available, for backwards compatibility. Also, it computes the Minimum-Width Rectangle, which may be useful. The CAPI GEOSMinimumRotatedRectangle is now bound to MinimumAreaRectangle rather than MinimumDiameter.getMinimumRectangle
- Loading branch information
Showing
15 changed files
with
1,148 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
/********************************************************************** | ||
* | ||
* GEOS - Geometry Engine Open Source | ||
* http://geos.osgeo.org | ||
* | ||
* Copyright (C) 2023 Paul Ramsey <[email protected]> | ||
* | ||
* 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. | ||
* | ||
**********************************************************************/ | ||
|
||
#pragma once | ||
|
||
#include <geos/export.h> | ||
|
||
#include <vector> | ||
#include <memory> | ||
|
||
// Forward declarations | ||
namespace geos { | ||
namespace geom { | ||
class CoordinateSequence; | ||
class CoordinateXY; | ||
class Geometry; | ||
class GeometryFactory; | ||
class LineSegment; | ||
class LineString; | ||
class Polygon; | ||
} | ||
} | ||
|
||
using geos::geom::CoordinateSequence; | ||
using geos::geom::CoordinateXY; | ||
using geos::geom::Geometry; | ||
using geos::geom::GeometryFactory; | ||
using geos::geom::LineSegment; | ||
using geos::geom::LineString; | ||
using geos::geom::Polygon; | ||
|
||
|
||
namespace geos { | ||
namespace algorithm { // geos::algorithm | ||
|
||
|
||
/** | ||
* Computes the minimum-area rectangle enclosing a Geometry. | ||
* Unlike the Envelope, the rectangle may not be axis-parallel. | ||
* | ||
* The first step in the algorithm is computing the convex hull of the Geometry. | ||
* If the input Geometry is known to be convex, a hint can be supplied to | ||
* avoid this computation. | ||
* | ||
* In degenerate cases the minimum enclosing geometry | ||
* may be a LineString or a Point. | ||
* | ||
* The minimum-area enclosing rectangle does not necessarily | ||
* have the minimum possible width. | ||
* Use MinimumDiameter to compute this. | ||
* | ||
* @see MinimumDiameter | ||
* @see ConvexHull | ||
* | ||
*/ | ||
class GEOS_DLL MinimumAreaRectangle { | ||
|
||
private: | ||
|
||
// Members | ||
const Geometry* m_inputGeom; | ||
bool m_isConvex; | ||
|
||
// Methods | ||
std::unique_ptr<Geometry> getMinimumRectangle(); | ||
|
||
std::unique_ptr<Geometry> computeConvex(const Geometry* convexGeom); | ||
|
||
/** | ||
* Computes the minimum-area rectangle for a convex ring of Coordinate. | ||
* | ||
* This algorithm uses the "dual rotating calipers" technique. | ||
* Performance is linear in the number of segments. | ||
* | ||
* @param ring the convex ring to scan | ||
*/ | ||
std::unique_ptr<Polygon> computeConvexRing(const CoordinateSequence* ring); | ||
|
||
std::size_t findFurthestVertex( | ||
const CoordinateSequence* pts, | ||
const LineSegment& baseSeg, | ||
std::size_t startIndex, | ||
int orient); | ||
|
||
bool isFurtherOrEqual(double d1, double d2, int orient); | ||
|
||
static double orientedDistance( | ||
const LineSegment& seg, | ||
const CoordinateXY& p, | ||
int orient); | ||
|
||
static std::size_t getNextIndex( | ||
const CoordinateSequence* ring, | ||
std::size_t index); | ||
|
||
/** | ||
* Creates a line of maximum extent from the provided vertices | ||
* @param pts the vertices | ||
* @param factory the geometry factory | ||
* @return the line of maximum extent | ||
*/ | ||
static std::unique_ptr<LineString> computeMaximumLine( | ||
const CoordinateSequence* pts, | ||
const GeometryFactory* factory); | ||
|
||
|
||
public: | ||
|
||
/** | ||
* Compute a minimum-area rectangle for a given Geometry. | ||
* | ||
* @param inputGeom a Geometry | ||
*/ | ||
MinimumAreaRectangle(const Geometry* inputGeom) | ||
: m_inputGeom(inputGeom) | ||
, m_isConvex(false) | ||
{}; | ||
|
||
/** | ||
* Compute a minimum rectangle for a Geometry, | ||
* with a hint if the geometry is convex | ||
* (e.g. a convex Polygon or LinearRing, | ||
* or a two-point LineString, or a Point). | ||
* | ||
* @param inputGeom a Geometry which is convex | ||
* @param isConvex true if the input geometry is convex | ||
*/ | ||
MinimumAreaRectangle(const Geometry* inputGeom, bool isConvex) | ||
: m_inputGeom(inputGeom) | ||
, m_isConvex(isConvex) | ||
{}; | ||
|
||
/** | ||
* Gets the minimum-area rectangular Polygon which encloses the input geometry. | ||
* If the convex hull of the input is degenerate (a line or point) | ||
* a LineString or Point is returned. | ||
* | ||
* @param geom the geometry | ||
* @return the minimum rectangle enclosing the geometry | ||
*/ | ||
static std::unique_ptr<Geometry> getMinimumRectangle(const Geometry* geom); | ||
|
||
}; | ||
|
||
|
||
} // namespace geos::algorithm | ||
} // namespace geos | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
* GEOS - Geometry Engine Open Source | ||
* http://geos.osgeo.org | ||
* | ||
* Copyright (C) 2023 Paul Ramsey <[email protected]> | ||
* Copyright (C) 2005-2006 Refractions Research Inc. | ||
* Copyright (C) 2001-2002 Vivid Solutions Inc. | ||
* | ||
|
@@ -11,10 +12,6 @@ | |
* by the Free Software Foundation. | ||
* See the COPYING file for more information. | ||
* | ||
********************************************************************** | ||
* | ||
* Last port: algorithm/MinimumDiameter.java r966 | ||
* | ||
**********************************************************************/ | ||
|
||
#pragma once | ||
|
@@ -53,12 +50,16 @@ namespace algorithm { // geos::algorithm | |
* | ||
* This class can also be used to compute a line segment representing | ||
* the minimum diameter, the supporting line segment of the minimum diameter, | ||
* and a minimum rectangle enclosing the input geometry. | ||
* and a minimum-width rectangle of the input geometry. | ||
* This rectangle will have width equal to the minimum diameter, and have | ||
* one side parallel to the supporting segment. | ||
* | ||
* @see ConvexHull | ||
* In degenerate cases the rectangle may be a LineString or a Point. | ||
* (Note that this may not be the enclosing rectangle with minimum area; | ||
* use MinimumAreaRectangle to compute this.) | ||
* | ||
* @see ConvexHull | ||
* @see MinimumAreaRectangle | ||
*/ | ||
class GEOS_DLL MinimumDiameter { | ||
private: | ||
|
@@ -75,7 +76,7 @@ class GEOS_DLL MinimumDiameter { | |
void computeWidthConvex(const geom::Geometry* geom); | ||
|
||
/** | ||
* Compute the width information for a ring of {@link geom::Coordinate}s. | ||
* Compute the width information for a ring of Coordinate. | ||
* Leaves the width information in the instance variables. | ||
* | ||
* @param pts | ||
|
@@ -127,7 +128,7 @@ class GEOS_DLL MinimumDiameter { | |
double getLength(); | ||
|
||
/** \brief | ||
* Gets the {@link geom::Coordinate} forming one end of the minimum diameter. | ||
* Gets the geom::Coordinate forming one end of the minimum diameter. | ||
* | ||
* @return a coordinate forming one end of the minimum diameter | ||
*/ | ||
|
@@ -148,23 +149,26 @@ class GEOS_DLL MinimumDiameter { | |
std::unique_ptr<geom::LineString> getDiameter(); | ||
|
||
/** \brief | ||
* Gets the minimum rectangular Polygon which encloses the input geometry. | ||
* Gets the rectangular Polygon which encloses the input geometry | ||
* and is based on the minimum diameter supporting segment. | ||
* | ||
* The rectangle has width equal to the minimum diameter, and a longer | ||
* length. If the convex hill of the input is degenerate (a line or point) | ||
* a LineString or Point is returned. | ||
* The minimum rectangle can be used as an extremely generalized | ||
* representation for the given geometry. | ||
* This is not necessarily the rectangle with minimum area. | ||
* Use MinimumAreaRectangle to compute this. | ||
* | ||
* @return the minimum rectangle enclosing the input (or a line or point if degenerate) | ||
* @return the the minimum-width rectangle enclosing the geometry | ||
* @see MinimumAreaRectangle | ||
*/ | ||
std::unique_ptr<geom::Geometry> getMinimumRectangle(); | ||
|
||
/** \brief | ||
* Gets the minimum rectangle enclosing a geometry. | ||
* | ||
* @param geom the geometry | ||
* @return the minimum rectangle enclosing the geometry | ||
* @return a rectangle enclosing the input (or a line or point if degenerate) | ||
* @see MinimumAreaRectangle | ||
*/ | ||
static std::unique_ptr<geom::Geometry> getMinimumRectangle(geom::Geometry* geom); | ||
|
||
|
Oops, something went wrong.