Isis 3 Programmer Reference
LimitPolygonSeeder.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7
8#include <string>
9#include <vector>
10#include <cmath>
11#include <iomanip>
12
13#include <geos/util/TopologyException.h>
14
15#include "IException.h"
16#include "LimitPolygonSeeder.h"
17#include "PolygonTools.h"
18#include "Pvl.h"
19#include "PvlGroup.h"
20
21namespace Isis {
22
33
34
47 std::vector<geos::geom::Point *> LimitPolygonSeeder::Seed(const geos::geom::MultiPolygon *multiPoly) {
48
49 // Storage for the points to be returned
50 std::vector<geos::geom::Point *> points;
51
52 // Create some things we will need shortly
53 const geos::geom::Envelope *polyBoundBox = multiPoly->getEnvelopeInternal();
54
55 // Call the parents standardTests member
56 QString msg = StandardTests(multiPoly, polyBoundBox);
57 if(!msg.isEmpty()) {
58 return points;
59 }
60
61 // Do limit seeder specific tests to make sure this poly should be seeded
62 // (none for now)
63
64 int xSteps = 0;
65 int ySteps = 0;
66
67 // Test if X is major axis
68 if(fabs(polyBoundBox->getMaxX() - polyBoundBox->getMinX()) > fabs((polyBoundBox->getMaxY() - polyBoundBox->getMinY()))) {
69 xSteps = p_majorAxisPts;
70 ySteps = p_minorAxisPts;
71 }
72 else {
73 xSteps = p_minorAxisPts;
74 ySteps = p_majorAxisPts;
75 }
76
77 double xSpacing = (polyBoundBox->getMaxX() - polyBoundBox->getMinX()) / (xSteps);
78 double ySpacing = (polyBoundBox->getMaxY() - polyBoundBox->getMinY()) / (ySteps);
79
80 double realMinX = polyBoundBox->getMinX() + xSpacing / 2;
81 double realMinY = polyBoundBox->getMinY() + ySpacing / 2;
82 double maxY = polyBoundBox->getMaxY();
83 double maxX = polyBoundBox->getMaxX();
84
85 for(double y = realMinY; y < maxY; y += ySpacing) {
86 for(double x = realMinX; x < maxX; x += xSpacing) {
87 geos::geom::Geometry *gridSquarePolygon = GetMultiPolygon(x - xSpacing / 2.0, y - ySpacing / 2,
88 x + xSpacing / 2.0, y + ySpacing / 2, *multiPoly);
89
90 geos::geom::Point *centroid = gridSquarePolygon->getCentroid().release();
91
92 delete gridSquarePolygon;
93 if(centroid->isEmpty()) continue;
94
95 double gridCenterX = centroid->getX();
96 double gridCenterY = centroid->getY();
97 delete centroid;
98
99 geos::geom::Coordinate c(gridCenterX, gridCenterY);
100 points.push_back(Isis::globalFactory->createPoint(c).release());
101 }
102 }
103
104 return points;
105 }
106
121 geos::geom::Geometry *LimitPolygonSeeder::GetMultiPolygon(double dMinX, double dMinY,
122 double dMaxX, double dMaxY,
123 const geos::geom::MultiPolygon &orig) {
124 geos::geom::CoordinateSequence *points = new geos::geom::CoordinateSequence();
125
126 points->add(geos::geom::Coordinate(dMinX, dMinY));
127 points->add(geos::geom::Coordinate(dMaxX, dMinY));
128 points->add(geos::geom::Coordinate(dMaxX, dMaxY));
129 points->add(geos::geom::Coordinate(dMinX, dMaxY));
130 points->add(geos::geom::Coordinate(dMinX, dMinY));
131
132 std::unique_ptr<geos::geom::Polygon> poly = Isis::globalFactory->createPolygon(Isis::globalFactory->createLinearRing(*points));
133 geos::geom::Geometry *overlap = poly->intersection(&orig).release();
134
135 return overlap;
136 }
137
145 // Call the parents Parse method
147
148 // Pull parameters specific to this algorithm out
149 try {
150 // Get info from Algorithm group
151 PvlGroup &algo = pvl.findGroup("PolygonSeederAlgorithm", Pvl::Traverse);
152 PvlGroup &invalgo = invalidInput->findGroup("PolygonSeederAlgorithm",
154
155 // Set the spacing
156 p_majorAxisPts = 0;
157 if(algo.hasKeyword("MajorAxisPoints")) {
158 p_majorAxisPts = (int) algo["MajorAxisPoints"];
159 if(invalgo.hasKeyword("MajorAxisPoints")) {
160 invalgo.deleteKeyword("MajorAxisPoints");
161 }
162 }
163 else {
164 QString msg = "PVL for LimitPolygonSeeder must contain [MajorAxisPoints] in [";
165 msg += pvl.fileName() + "]";
166 throw IException(IException::User, msg, _FILEINFO_);
167 }
168
169 p_minorAxisPts = 0;
170 if(algo.hasKeyword("MinorAxisPoints")) {
171 p_minorAxisPts = (int) algo["MinorAxisPoints"];
172 if(invalgo.hasKeyword("MinorAxisPoints")) {
173 invalgo.deleteKeyword("MinorAxisPoints");
174 }
175 }
176 else {
177 QString msg = "PVL for LimitPolygonSeeder must contain [MinorAxisPoints] in [";
178 msg += pvl.fileName() + "]";
179 throw IException(IException::User, msg, _FILEINFO_);
180 }
181 }
182 catch(IException &e) {
183 QString msg = "Improper format for PolygonSeeder PVL [" + pvl.fileName() + "]";
184 throw IException(IException::User, msg, _FILEINFO_);
185 }
186
187 if(p_majorAxisPts < 1.0) {
188 IString msg = "Major axis points must be greater that 0.0 [(" + IString(p_majorAxisPts) + "]";
189 throw IException(IException::User, msg, _FILEINFO_);
190 }
191
192 if(p_minorAxisPts <= 0.0) {
193 IString msg = "Minor axis points must be greater that 0.0 [(" + IString(p_minorAxisPts) + "]";
194 throw IException(IException::User, msg, _FILEINFO_);
195 }
196 }
197
199 PvlGroup pluginInfo(grpName);
200
201 PvlKeyword name("Name", Algorithm());
202 PvlKeyword minThickness("MinimumThickness", toString(MinimumThickness()));
203 PvlKeyword minArea("MinimumArea", toString(MinimumArea()));
204 PvlKeyword majAxis("MajorAxisPoints", toString(p_majorAxisPts));
205 PvlKeyword minAxis("MinorAxisPoints", toString(p_minorAxisPts));
206
207 pluginInfo.addKeyword(name);
208 pluginInfo.addKeyword(minThickness);
209 pluginInfo.addKeyword(minArea);
210 pluginInfo.addKeyword(majAxis);
211 pluginInfo.addKeyword(minAxis);
212
213 return pluginInfo;
214 }
215
216}; // End of namespace Isis
217
218
230extern "C" Isis::PolygonSeeder *LimitPolygonSeederPlugin(Isis::Pvl &pvl) {
231 return new Isis::LimitPolygonSeeder(pvl);
232}
233
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
Adds specific functionality to C++ strings.
Definition IString.h:165
Seed points using a grid.
int p_majorAxisPts
Number of points to place on major axis.
LimitPolygonSeeder(Pvl &pvl)
Construct a LimitPolygonSeeder algorithm.
int p_minorAxisPts
Number of points to place on minor axis.
virtual PvlGroup PluginParameters(QString grpName)
Plugin parameters.
geos::geom::Geometry * GetMultiPolygon(double dMinX, double dMinY, double dMaxX, double dMaxY, const geos::geom::MultiPolygon &orig)
This method returns the overlap between the x/y range specified and the "orig" polygon.
virtual void Parse(Pvl &pvl)
Parse the LimitPolygonSeeder spicific parameters from the PVL.
std::vector< geos::geom::Point * > Seed(const geos::geom::MultiPolygon *mp)
Seed a polygon with points.
This class is used as the base class for all PolygonSeeder objects.
virtual void Parse(Pvl &pvl)
Initialize parameters in the PolygonSeeder class using a PVL specification.
Pvl * invalidInput
The Pvl passed in by the constructor minus what was used.
QString StandardTests(const geos::geom::MultiPolygon *multiPoly, const geos::geom::Envelope *polyBoundBox)
Check the polygon to see if it meets standard criteria.
double MinimumArea()
Return the minimum allowed area of the polygon.
double MinimumThickness()
Return the minimum allowed thickness of the polygon.
QString Algorithm() const
The name of the algorithm, read from the Name Keyword in the PolygonSeeder Pvl passed into the constr...
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition PvlObject.h:129
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211