File failed to load: https://isis.astrogeology.usgs.gov/9.0.0/Object/assets/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
ProcessGroundPolygons.cpp
1
5
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ProcessGroundPolygons.h"
8
9#include <vector>
10
11#include "geos/geom/CoordinateSequence.h"
12#include "geos/geom/LineString.h"
13#include "geos/io/WKTWriter.h"
14
15#include "Application.h"
16#include "BoxcarCachingAlgorithm.h"
17#include "IException.h"
18#include "PolygonTools.h"
19#include "Projection.h"
20
21using namespace std;
22namespace Isis {
23
24 ProcessGroundPolygons::ProcessGroundPolygons() {
25 p_groundMap = NULL;
26 }
27
28
39 void ProcessGroundPolygons::Rasterize(std::vector<double> &lat,
40 std::vector<double> &lon,
41 std::vector<double> &values) {
42
43 // Decide if we need to split the poly on the 360 boundry
44 // Yes, we can do this better. The lat and lon vectors should be passed in as polygons, but
45 // for now this is reusing older code.
46 bool crosses = false;
47 for (unsigned int i = 0; i < lon.size() - 1; i++) {
48 if (fabs(lon[i] - lon[i+1]) > 180.0) {
49 crosses = true;
50 break;
51 }
52 }
53
54 if (crosses) {
55 // Make a polygon from the lat/lon vectors and split it on 360
56 geos::geom::CoordinateSequence pts;
57 for (unsigned int i = 0; i < lat.size(); i++) {
58 pts.add(geos::geom::Coordinate(lon[i], lat[i]));
59 }
60 pts.add(geos::geom::Coordinate(lon[0], lat[0]));
61
62 geos::geom::Polygon *crossingPoly = Isis::globalFactory->createPolygon(
63 globalFactory->createLinearRing(pts)).release();
64
65 geos::geom::MultiPolygon *splitPoly = NULL;
66 try {
67 splitPoly = PolygonTools::SplitPolygonOn360(crossingPoly);
68 }
69 // Ignore any pixel footprints that could not be split. This should only be pixels
70 // that contain the pole.
71 catch (IException &) {
72 // See leading comment
73 }
74
75 delete crossingPoly;
76
77 if (splitPoly != NULL) {
78 // Process the polygons in the split multipolygon as if we were still using the lat/lon vectors
79 for (unsigned int g = 0; g < splitPoly->getNumGeometries(); ++g) {
80 const geos::geom::Polygon *poly =
81 dynamic_cast<const geos::geom::Polygon *>(splitPoly->getGeometryN(g));
82
83 geos::geom::CoordinateSequence *llcoords =
84 poly->getExteriorRing()->getCoordinates().release();
85
86 // Move each coordinate in the exterior ring of this lat/lon polygon to vectors
87 // Ignore any holes in the polygon
88 std::vector<double> tlat;
89 std::vector<double> tlon;
90 for (unsigned int cord = 0; cord < llcoords->getSize() - 1; ++cord) {
91 tlon.push_back(llcoords->getAt(cord).x);
92 tlat.push_back(llcoords->getAt(cord).y);
93 }
94
95 Convert(tlat, tlon);
96 ProcessPolygons::Rasterize(p_samples, p_lines, values);
97 }
98 delete splitPoly;
99 }
100 }
101 else {
102 Convert(lat, lon);
103 ProcessPolygons::Rasterize(p_samples, p_lines, values);
104 }
105 }
106
107
108
109
121geos::geom::Geometry* ProcessGroundPolygons::Vectorize(std::vector<double> &lat,
122 std::vector<double> &lon)
123 //std::vector<double> &values)
124 {
125
126
127
128 // Decide if we need to split the poly on the 360 boundry
129 // Yes, we can do this better. The lat and lon vectors should be passed in as polygons, but
130 // for now this is reusing older code.
131 bool crosses = false;
132 for (unsigned int i = 0; i < lon.size() - 1; i++) {
133 if (fabs(lon[i] - lon[i+1]) > 180.0) {
134 crosses = true;
135 break;
136 }
137 }
138
139
140 if (crosses) {
141 // Make a polygon from the lat/lon vectors and split it on 360
142 geos::geom::CoordinateSequence pts;
143 for (unsigned int i = 0; i < lat.size(); i++) {
144 pts.add(geos::geom::Coordinate(lon[i], lat[i]));
145 }
146 pts.add(geos::geom::Coordinate(lon[0], lat[0]));
147
148 geos::geom::Polygon *crossingPoly = Isis::globalFactory->createPolygon(
149 globalFactory->createLinearRing(pts)).release();
150
151 geos::geom::MultiPolygon *splitPoly = NULL;
152 try {
153 splitPoly = PolygonTools::SplitPolygonOn360(crossingPoly);
154 }
155 // Ignore any pixel footprints that could not be split. This should only be pixels
156 // that contain the pole.
157 catch (IException &) {
158 // See leading comment
159 }
160
161 delete crossingPoly;
162
163 if (splitPoly != NULL) {
164 // Process the polygons in the split multipolygon as if we were still using the lat/lon vectors
165 for (unsigned int g = 0; g < splitPoly->getNumGeometries(); ++g) {
166 const geos::geom::Polygon *poly =
167 dynamic_cast<const geos::geom::Polygon *>(splitPoly->getGeometryN(g));
168
169 geos::geom::CoordinateSequence *llcoords =
170 poly->getExteriorRing()->getCoordinates().release();
171
172 // Move each coordinate in the exterior ring of this lat/lon polygon to vectors
173 // Ignore any holes in the polygon
174 std::vector<double> tlat;
175 std::vector<double> tlon;
176 for (unsigned int cord = 0; cord < llcoords->getSize() - 1; ++cord) {
177 tlon.push_back(llcoords->getAt(cord).x);
178 tlat.push_back(llcoords->getAt(cord).y);
179 }
180
181 }
182 return splitPoly;
183 }
184 }
185 else { // if does not crosses
186
187 // Make a polygon from the lat/lon vectors and split it on 360
188 geos::geom::CoordinateSequence pts;
189 for (unsigned int i = 0; i < lat.size(); i++) {
190 pts.add(geos::geom::Coordinate(lon[i], lat[i]));
191 }
192 pts.add(geos::geom::Coordinate(lon[0], lat[0]));
193
194 geos::geom::Polygon *singlePoly = Isis::globalFactory->createPolygon(
195 globalFactory->createLinearRing(pts)).release();
196
197 return singlePoly;
198 }
199 return nullptr;
200}
201
212 void ProcessGroundPolygons::Rasterize(std::vector<double> &lat,
213 std::vector<double> &lon,
214 int &band, double &value) {
215
216 Convert(lat, lon);
217 ProcessPolygons::Rasterize(p_samples, p_lines, band, value);
218 }
219
220
228 void ProcessGroundPolygons::Convert(std::vector<double> &lat,
229 std::vector<double> &lon) {
230
231 p_samples.clear();
232 p_lines.clear();
233
234 for (unsigned int i = 0; i < lat.size(); i++) {
235 if (p_groundMap->SetUniversalGround(lat[i], lon[i])) {
236 p_samples.push_back(p_groundMap->Sample());
237 p_lines.push_back(p_groundMap->Line());
238 }
239 }
240 }
241
242
251
252 if(p_groundMap != NULL) {
253 delete p_groundMap;
254 }
255
257 }
258
259
267
268 if(p_groundMap != NULL) {
269 delete p_groundMap;
270 }
271
273 }
274
275
284 const QString &avgFileName,
285 const QString &countFileName) {
286 /*We need a ground map for converting lat/long to line/sample see Convert()*/
287 Cube cube(cubeStr, "r");
288 p_groundMap = new UniversalGroundMap(cube);
289 ProcessPolygons::AppendOutputCube(avgFileName, countFileName);
290
291 }
292
293
303 void ProcessGroundPolygons::SetStatCubes(const QString &avgFileName,
304 const QString &countFileName,
306 QString &cubeStr) {
307 /*We need a ground map for converting lat/long to line/sample see Convert()*/
308 Cube cube(cubeStr);
309 p_groundMap = new UniversalGroundMap(cube);
310
311 /*setup input cube to transfer projection or camera labels*/
312 CubeAttributeInput inAtts;
313 Isis::Process::SetInputCube(cubeStr, inAtts, 0);
314 int nBands = this->InputCubes[0]->bandCount();
315 int nLines = this->InputCubes[0]->lineCount();
316 int nSamples = this->InputCubes[0]->sampleCount();
317
318 this->Process::SetOutputCube(avgFileName, outAtts, nSamples, nLines, nBands);
319 this->Process::SetOutputCube(countFileName, outAtts, nSamples, nLines, nBands);
320
321 OutputCubes[0]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
322 OutputCubes[1]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
323
325
326 }
327
328
338 void ProcessGroundPolygons::SetStatCubes(const QString &parameter,
339 QString &cube) {
340
341 QString avgString =
345
346 FileName file(avgString);
347 QString path = file.path();
348 QString filename = file.baseName();
349 QString countString = path + "/" + filename + "-count-";
350
351 SetStatCubes(avgString, countString, atts, cube);
352
353 }
354
355
363 void ProcessGroundPolygons::SetStatCubes(const QString &parameter,
364 Isis::Pvl &map, int bands) {
365
366 QString avgString =
370
371 FileName file(avgString);
372 QString path = file.path();
373 QString filename = file.baseName();
374 QString countString = path + "/" + filename + "-count-";
375
376 SetStatCubes(avgString, countString, atts, map, bands);
377
378 }
379
380
395 void ProcessGroundPolygons::SetStatCubes(const QString &avgFileName,
396 const QString &countFileName,
398 Isis::Pvl &map, int bands) {
399 int samples, lines;
400
401 Projection *proj = ProjectionFactory::CreateForCube(map, samples, lines,
402 false);
403
404 this->ProcessPolygons::SetStatCubes(avgFileName, countFileName, atts,
405 samples, lines, bands);
406
407 OutputCubes[0]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
408 OutputCubes[1]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
409
410 /*Write the pvl group to the cube files.*/
411
412 PvlGroup group = map.findGroup("Mapping", Pvl::Traverse);
413
414 OutputCubes[0]->putGroup(group);
415 OutputCubes[1]->putGroup(group);
416
417 // If there is an alpha cube in the label passed, attach to output cubes
418 if (map.hasGroup("AlphaCube")) {
419 PvlGroup alpha = map.findGroup("AlphaCube", Pvl::Traverse);
420 OutputCubes[0]->putGroup(alpha);
421 OutputCubes[1]->putGroup(alpha);
422 }
423
424 /*We need a ground map for converting lat/long to line/sample see Convert()*/
425 p_groundMap = new UniversalGroundMap(*OutputCubes[0]);
426
427 delete proj;
428 }
429
430} /* end namespace isis*/
431
static UserInterface & GetUserInterface()
Returns the UserInterface object.
This algorithm is designed for applications that jump around between a couple of spots in the cube wi...
Manipulate and parse attributes of input cube filenames.
Manipulate and parse attributes of output cube filenames.
IO Handler for Isis Cubes.
Definition Cube.h:168
File name manipulation and expansion.
Definition FileName.h:100
QString path() const
Returns the path of the file name.
Definition FileName.cpp:103
QString baseName() const
Returns the name of the file without the path and without extensions.
Definition FileName.cpp:145
Isis exception class.
Definition IException.h:91
static geos::geom::MultiPolygon * SplitPolygonOn360(const geos::geom::Polygon *inPoly)
If the cube crosses the 0/360 boundary and does not include a pole, this will divide the polygon into...
void Convert(std::vector< double > &lat, std::vector< double > &lon)
Converts lat/long to line/sample using the universal ground map object.
void AppendOutputCube(QString &cube, const QString &avgFileName, const QString &countFileName="")
This gives the option to append to the cube.
geos::geom::Geometry * Vectorize(std::vector< double > &lat, std::vector< double > &lon)
This method gets called from the application with the lat/lon vertices of a polygon.
void Finalize()
This method cleans up any open outputcube files and deletes the pointer to the universal ground map i...
void EndProcess()
This method cleans up any open outputcube files and deletes the pointer to the universal ground map i...
void SetStatCubes(const QString &parameter, QString &cube)
This is a method that is called directly from the application.
void Rasterize(std::vector< double > &lat, std::vector< double > &lon, std::vector< double > &values)
This method gets called from the application with the lat/lon vertices of a polygon along with a vect...
std::vector< Isis::Cube * > InputCubes
A vector of pointers to opened Cube objects.
Definition Process.h:185
virtual Isis::Cube * SetOutputCube(const QString &parameter)
Allocates a user-specified output cube whose size matches the first input cube.
Definition Process.cpp:163
std::vector< Isis::Cube * > OutputCubes
A vector of pointers to allocated Cube objects.
Definition Process.h:191
virtual Isis::Cube * SetInputCube(const QString &parameter, const int requirements=0)
Opens an input cube specified by the user and verifies requirements are met.
Definition Process.cpp:139
void ClearInputCubes()
Close owned input cubes from the list and clear the list.
Definition Process.cpp:614
Isis::Cube * AppendOutputCube(const QString &avgFileName, const QString &countFileName="")
This gives the option to append to the cube.
void Rasterize(std::vector< double > &samples, std::vector< double > &lines, std::vector< double > &values)
void SetStatCubes(const QString &parameter, const int nsamps, const int nlines, int nbands=1)
void Finalize()
Cleans up by closing cubes and freeing memory for owned cubes.
static Isis::Projection * CreateForCube(Isis::Pvl &label, int &ns, int &nl, bool sizeMatch=true)
This method creates a map projection for a cube given a label.
Base class for Map Projections.
Definition Projection.h:155
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
bool hasGroup(const QString &name) const
Returns a boolean value based on whether the object has the specified group or not.
Definition PvlObject.h:210
@ 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
Universal Ground Map.
QString GetCubeName(const QString &paramName, QString extension="") const
Retrieves of a value for a parameter of type "cubename".
Definition IsisAml.cpp:724
Isis::CubeAttributeOutput & GetOutputAttribute(const QString &paramName)
Gets the attributes for an output cube.
Definition IsisAml.cpp:2105
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.