USGS

Isis 3.0 Object Programmers' Reference

Home

ProcessGroundPolygons.cpp
1 #include "ProcessGroundPolygons.h"
2 
3 #include <vector>
4 
5 #include "geos/geom/CoordinateSequence.h"
6 #include "geos/geom/CoordinateArraySequence.h"
7 #include "geos/geom/LineString.h"
8 #include "geos/geosAlgorithm.h"
9 
10 #include "Application.h"
11 #include "BoxcarCachingAlgorithm.h"
12 #include "IException.h"
13 #include "PolygonTools.h"
14 #include "Projection.h"
15 
16 using namespace std;
17 namespace Isis {
18 
19  ProcessGroundPolygons::ProcessGroundPolygons() {
20  p_groundMap = NULL;
21  }
22 
23 
34  void ProcessGroundPolygons::Rasterize(std::vector<double> &lat,
35  std::vector<double> &lon,
36  std::vector<double> &values) {
37 
38  // Decide if we need to split the poly on the 360 boundry
39  // Yes, we can do this better. The lat and lon vectors should be passed in as polygons, but
40  // for now this is reusing older code.
41  bool crosses = false;
42  for (unsigned int i = 0; i < lon.size() - 1; i++) {
43  if (fabs(lon[i] - lon[i+1]) > 180.0) {
44  crosses = true;
45  break;
46  }
47  }
48 
49  if (crosses) {
50  // Make a polygon from the lat/lon vectors and split it on 360
51  geos::geom::CoordinateSequence *pts = new geos::geom::CoordinateArraySequence();
52  for (unsigned int i = 0; i < lat.size(); i++) {
53  pts->add(geos::geom::Coordinate(lon[i], lat[i]));
54  }
55  pts->add(geos::geom::Coordinate(lon[0], lat[0]));
56 
57  geos::geom::Polygon *crossingPoly = Isis::globalFactory.createPolygon(
58  globalFactory.createLinearRing(pts), NULL);
59 
60  geos::geom::MultiPolygon *splitPoly = NULL;
61  try {
62  splitPoly = PolygonTools::SplitPolygonOn360(crossingPoly);
63  }
64  // Ignore any pixel footprints that could not be split. This should only be pixels
65  // that contain the pole.
66  catch (IException &) {
67  // See leading comment
68  }
69 
70  delete crossingPoly;
71 
72  if (splitPoly != NULL) {
73  // Process the polygons in the split multipolygon as if we were still using the lat/lon vectors
74  for (unsigned int g = 0; g < splitPoly->getNumGeometries(); ++g) {
75  const geos::geom::Polygon *poly =
76  dynamic_cast<const geos::geom::Polygon *>(splitPoly->getGeometryN(g));
77 
78  geos::geom::CoordinateSequence *llcoords = poly->getExteriorRing()->getCoordinates();
79 
80  // Move each coordinate in the exterior ring of this lat/lon polygon to vectors
81  // Ignore any holes in the polygon
82  std::vector<double> tlat;
83  std::vector<double> tlon;
84  for (unsigned int cord = 0; cord < llcoords->getSize() - 1; ++cord) {
85  tlon.push_back(llcoords->getAt(cord).x);
86  tlat.push_back(llcoords->getAt(cord).y);
87  }
88 
89  Convert(tlat, tlon);
90  ProcessPolygons::Rasterize(p_samples, p_lines, values);
91  }
92  delete splitPoly;
93  }
94  }
95  else {
96  Convert(lat, lon);
97  ProcessPolygons::Rasterize(p_samples, p_lines, values);
98  }
99  }
100 
101 
112  void ProcessGroundPolygons::Rasterize(std::vector<double> &lat,
113  std::vector<double> &lon,
114  int &band, double &value) {
115 
116  Convert(lat, lon);
117  ProcessPolygons::Rasterize(p_samples, p_lines, band, value);
118  }
119 
120 
128  void ProcessGroundPolygons::Convert(std::vector<double> &lat,
129  std::vector<double> &lon) {
130 
131  p_samples.clear();
132  p_lines.clear();
133 
134  for (unsigned int i = 0; i < lat.size(); i++) {
135  if (p_groundMap->SetUniversalGround(lat[i], lon[i])) {
136  p_samples.push_back(p_groundMap->Sample());
137  p_lines.push_back(p_groundMap->Line());
138  }
139  }
140  }
141 
142 
150  void ProcessGroundPolygons::EndProcess() {
151 
152  if(p_groundMap != NULL) {
153  delete p_groundMap;
154  }
155 
156  ProcessPolygons::EndProcess();
157  }
158 
159 
166  void ProcessGroundPolygons::Finalize() {
167 
168  if(p_groundMap != NULL) {
169  delete p_groundMap;
170  }
171 
172  ProcessPolygons::Finalize();
173  }
174 
175 
183  void ProcessGroundPolygons::AppendOutputCube(QString &cubeStr,
184  const QString &avgFileName,
185  const QString &countFileName) {
186  /*We need a ground map for converting lat/long to line/sample see Convert()*/
187  Cube cube(cubeStr, "r");
188  p_groundMap = new UniversalGroundMap(cube);
189  ProcessPolygons::AppendOutputCube(avgFileName, countFileName);
190 
191  }
192 
193 
203  void ProcessGroundPolygons::SetStatCubes(const QString &avgFileName,
204  const QString &countFileName,
205  Isis::CubeAttributeOutput &outAtts,
206  QString &cubeStr) {
207  /*We need a ground map for converting lat/long to line/sample see Convert()*/
208  Cube cube(cubeStr);
209  p_groundMap = new UniversalGroundMap(cube);
210 
211  /*setup input cube to transfer projection or camera labels*/
212  CubeAttributeInput inAtts;
213  Isis::Process::SetInputCube(cubeStr, inAtts, 0);
214  int nBands = this->InputCubes[0]->bandCount();
215  int nLines = this->InputCubes[0]->lineCount();
216  int nSamples = this->InputCubes[0]->sampleCount();
217 
218  this->Process::SetOutputCube(avgFileName, outAtts, nSamples, nLines, nBands);
219  this->Process::SetOutputCube(countFileName, outAtts, nSamples, nLines, nBands);
220 
221  OutputCubes[0]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
222  OutputCubes[1]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
223 
224  ClearInputCubes();
225 
226  }
227 
228 
238  void ProcessGroundPolygons::SetStatCubes(const QString &parameter,
239  QString &cube) {
240 
241  QString avgString =
242  Application::GetUserInterface().GetFileName(parameter);
243  CubeAttributeOutput atts =
244  Application::GetUserInterface().GetOutputAttribute(parameter);
245 
246  FileName file(avgString);
247  QString path = file.path();
248  QString filename = file.baseName();
249  QString countString = path + "/" + filename + "-count-";
250 
251  SetStatCubes(avgString, countString, atts, cube);
252 
253  }
254 
255 
263  void ProcessGroundPolygons::SetStatCubes(const QString &parameter,
264  Isis::Pvl &map, int bands) {
265 
266  QString avgString =
267  Application::GetUserInterface().GetFileName(parameter);
268  CubeAttributeOutput atts =
269  Application::GetUserInterface().GetOutputAttribute(parameter);
270 
271  FileName file(avgString);
272  QString path = file.path();
273  QString filename = file.baseName();
274  QString countString = path + "/" + filename + "-count-";
275 
276  SetStatCubes(avgString, countString, atts, map, bands);
277 
278  }
279 
280 
290  void ProcessGroundPolygons::SetStatCubes(const QString &avgFileName,
291  const QString &countFileName,
293  Isis::Pvl &map, int bands) {
294  int samples, lines;
295 
296  Projection *proj = ProjectionFactory::CreateForCube(map, samples, lines,
297  false);
298 
299  this->ProcessPolygons::SetStatCubes(avgFileName, countFileName, atts,
300  samples, lines, bands);
301 
302  OutputCubes[0]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
303  OutputCubes[1]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
304 
305  /*Write the pvl group to the cube files.*/
306 
307  PvlGroup group = map.findGroup("Mapping", Pvl::Traverse);
308 
309  OutputCubes[0]->putGroup(group);
310  OutputCubes[1]->putGroup(group);
311 
312  /*We need a ground map for converting lat/long to line/sample see Convert()*/
313  p_groundMap = new UniversalGroundMap(*OutputCubes[0]);
314 
315  delete proj;
316  }
317 
318 } /* end namespace isis*/
319