Isis 3 Programmer Reference
ProcessPolygons.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ProcessPolygons.h"
8#include "PolygonTools.h"
9#include "Application.h"
10#include "BoxcarCachingAlgorithm.h"
11#include "SpecialPixel.h"
12
13#include "geos/geom/CoordinateSequence.h"
14#include "geos/geom/Coordinate.h"
15#include "geos/geom/Envelope.h"
16#include "geos/geom/LineString.h"
17#include "geos/geom/Geometry.h"
18#include "geos/geom/Point.h"
19#include "geos/geom/prep/PreparedGeometryFactory.h"
20#include "geos/geom/prep/PreparedPolygon.h"
21#include "geos/util/IllegalArgumentException.h"
22#include "geos/operation/overlay/snap/GeometrySnapper.h"
23
24using namespace std;
25namespace Isis {
26
27 ProcessPolygons::ProcessPolygons() {
28 m_useCenter = true;
29 m_average = NULL;
30 m_count = NULL;
31 m_imagePoly = NULL;
32 }
33
34
35
43 void ProcessPolygons::Rasterize(std::vector<double> &samples,
44 std::vector<double> &lines,
45 std::vector<double> &values) {
46
47 m_sampleVertices = samples;
48 m_lineVertices = lines;
49 m_dns = values;
50 FillPolygon(0);
51 }
52
53
54
64 void ProcessPolygons::Rasterize(std::vector<double> &samples,
65 std::vector<double> &lines,
66 int &band, double &value) {
67
68 m_sampleVertices = samples;
69 m_lineVertices = lines;
70 m_band = band;
71 m_dns.clear();
72 m_dns.push_back(value);
73
74 FillPolygon(1);
75 }
76
77
89
90 // Create a sample/line polygon for the input pixel vertices
91 geos::geom::CoordinateSequence pts;
92 for (unsigned int i = 0; i < m_sampleVertices.size(); i++) {
93 pts.add(geos::geom::Coordinate(m_sampleVertices[i], m_lineVertices[i]));
94 }
95 pts.add(geos::geom::Coordinate(m_sampleVertices[0], m_lineVertices[0]));
96
97 try {
98 // Create a polygon from the pixel vertices. This polygon may have spikes or other
99 // problems such as multiple polygons. Despike, then make sure we have a single polygon.
100 // Do not rasterize pixel if despiking fails or there are multiple polygons.
101 geos::geom::Polygon *spikedPixelPoly = Isis::globalFactory->createPolygon(
102 globalFactory->createLinearRing(pts)).release();
103
104 const geos::geom::Polygon *projectedInputPixelPoly;
105
106 if (spikedPixelPoly->isValid()) {
107 projectedInputPixelPoly = spikedPixelPoly;
108 }
109 else {
110 geos::geom::MultiPolygon *despikedPixelPoly;
111 try {
112 despikedPixelPoly = PolygonTools::Despike(spikedPixelPoly);
113 }
114 catch (IException &e) {
115 delete spikedPixelPoly;
116 return;
117 }
118
119 try {
120 despikedPixelPoly = PolygonTools::Despike(spikedPixelPoly);
121 }
122 catch (IException &e) {
123 delete spikedPixelPoly;
124 return;
125 }
126
127 if (despikedPixelPoly->getNumGeometries() > 1) return;
128 projectedInputPixelPoly =
129 dynamic_cast<const geos::geom::Polygon *>(despikedPixelPoly->getGeometryN(0));
130 }
131
132 /* If there is not an intersecting polygon, there is no reason to go on.*/
133 if (!projectedInputPixelPoly->intersects(m_imagePoly)) return;
134
135 geos::geom::MultiPolygon *intersectPoly = PolygonTools::MakeMultiPolygon(
136 m_imagePoly->intersection(projectedInputPixelPoly).release());
137 geos::geom::prep::PreparedPolygon *preparedPoly =
138 new geos::geom::prep::PreparedPolygon(intersectPoly);
139 const geos::geom::Envelope *envelope = intersectPoly->getEnvelopeInternal();
140
141 // Go thru each coord. in the envelope and ask if it is within the polygon
142 for (double x = floor(envelope->getMinX()); x <= ceil(envelope->getMaxX()); x++) {
143 if (x == 0) continue;
144
145 for (double y = floor(envelope->getMinY()); y <= ceil(envelope->getMaxY()); y++) {
146 if (y == 0) continue;
147
148 bool contains;
149
150 if (m_useCenter) {
151 geos::geom::Coordinate c(x, y);
152 geos::geom::Point *p = Isis::globalFactory->createPoint(c).release();
153 contains = preparedPoly->contains(p);
154 delete p;
155 }
156 else {
157 geos::geom::CoordinateSequence tpts;
158 tpts.add(geos::geom::Coordinate(x - 0.5, y - 0.5));
159 tpts.add(geos::geom::Coordinate(x + 0.5, y - 0.5));
160 tpts.add(geos::geom::Coordinate(x + 0.5, y + 0.5));
161 tpts.add(geos::geom::Coordinate(x - 0.5, y + 0.5));
162 tpts.add(geos::geom::Coordinate(x - 0.5, y - 0.5));
163
164 geos::geom::Polygon *outPixelFootPrint = Isis::globalFactory->createPolygon(
165 globalFactory->createLinearRing(tpts)).release();
166 contains = preparedPoly->intersects(outPixelFootPrint);
167 delete outPixelFootPrint;
168 }
169
170 if (contains) {
171
172 // Read spectral noodle from samp, line position
173 m_average->SetBasePosition((int)(x + 0.5), (int)(y + 0.5), 1);
174 this->OutputCubes[0]->read(*m_average);
175 m_count->SetBasePosition((int)(x + 0.5), (int)(y + 0.5), 1);
176 this->OutputCubes[1]->read(*m_count);
177
178 // Process each band in the buffer
179 for (unsigned int i = 0; i < m_dns.size(); i++) {
180
181 int band;
182 if (Flag == 0) {
183 band = i;
184 }
185 else {
186 band = m_band - 1;
187 }
188
189 double inputDn = m_dns[i];
190
191 // The input dn is good
192 if (IsValidPixel(inputDn)) {
193 if (IsValidPixel((*m_average)[band])) {
194 double currentCount = (*m_count)[band];
195 double newCount = ++((*m_count)[band]);
196 double currentAverage = (*m_average)[band];
197 (*m_average)[band] = ((currentAverage * currentCount) + inputDn) / newCount;
198 }
199 else {
200 (*m_average)[band] = inputDn;
201 (*m_count)[band] = 1;
202 }
203 }
204
205 // The input dn is special
206 else {
207 if (((*m_average)[band] == Isis::Null) || (inputDn != Null)) {
208 (*m_average)[band] = inputDn;
209 }
210 }
211
212 } /*End for each band*/
213
214 // Write spectral noodles back out to average and count cubes
215 this->OutputCubes[0]->write(*m_average);
216 this->OutputCubes[1]->write(*m_count);
217
218 } /*End if (contains)*/
219
220 } /*End for y*/
221
222 } /*End for x*/
223
224 delete projectedInputPixelPoly;
225 delete intersectPoly;
226 delete preparedPoly;
227
228 } /*end try*/
229
230 catch(geos::util::IllegalArgumentException *ill) {
231 QString msg = "ERROR! geos exception 1 [";
232 msg += (QString)ill->what() + "]";
233 delete ill;
234 throw IException(IException::Programmer, msg, _FILEINFO_);
235 }/*end catch*/
236
237 }
238
239
245
246 delete m_imagePoly;
247 delete m_average;
248 delete m_count;
250 }
251
252
258
259 delete m_imagePoly;
260 delete m_average;
261 delete m_count;
263 }
264
265
275 const QString &countFileName) {
276
277 FileName *file = new FileName(avgFileName);
278 QString path = file->path();
279 QString filename = file->baseName();
280 QString extension = file->extension();
281
282 /*Open the average file with read/write permission*/
283 Cube *averageCube = new Cube();
284 averageCube->open(avgFileName, "rw");
285 AddOutputCube(averageCube);
286
287 /*Now open the count file with read/write permission*/
288 Cube *countCube = new Cube();
289
290 if (countFileName == "") {
291 /*if the countFileName was set to nothing, then we use the default count
292 file name.*/
293 QString openFile = path + "/" + filename + "-count-." + extension;
294 countCube->open(openFile, "rw");
295
296 }
297 else {
298 countCube->open(countFileName, "rw");
299 }
300
301 AddOutputCube(countCube);
302 return countCube;
303 }
304
305
306
316 void ProcessPolygons::SetStatCubes(const QString &avgFileName, const
317 QString &countFileName,
319 const int nsamps, const int nlines,
320 const int nbands) {
321
322 this->Process::SetOutputCube(avgFileName, atts, nsamps, nlines, nbands);
323 this->Process::SetOutputCube(countFileName, atts, nsamps, nlines, nbands);
324
325 OutputCubes[0]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
326 OutputCubes[1]->addCachingAlgorithm(new BoxcarCachingAlgorithm());
327
328 geos::geom::CoordinateSequence imagePts;
329
330 imagePts.add(geos::geom::Coordinate(0.0, 0.0));
331 imagePts.add(geos::geom::Coordinate(0.0, this->OutputCubes[0]->lineCount()));
332 imagePts.add(geos::geom::Coordinate(this->OutputCubes[0]->sampleCount(),
333 this->OutputCubes[0]->lineCount()));
334 imagePts.add(geos::geom::Coordinate(this->OutputCubes[0]->sampleCount(), 0.0));
335 imagePts.add(geos::geom::Coordinate(0.0, 0.0));
336
337 m_imagePoly = Isis::globalFactory->createPolygon(
338 globalFactory->createLinearRing(imagePts)).release();
339
340 m_average = new Brick(*this->OutputCubes[0], 1, 1, nbands);
341 m_count = new Brick(*this->OutputCubes[1], 1, 1, nbands);
342 }
343
344
345
354 void ProcessPolygons::SetStatCubes(const QString &parameter,
355 const int nsamps, const int nlines,
356 const int nbands) {
357
358 QString avgString =
359 Application::GetUserInterface().GetCubeName(parameter);
360
362 Application::GetUserInterface().GetOutputAttribute(parameter);
363
364 FileName *file = new FileName(avgString);
365 QString path = file->path();
366 QString filename = file->baseName();
367 QString countString = path + "/" + filename + "-count";
368 SetStatCubes(avgString, countString, atts, nsamps, nlines, nbands);
369
370 }
371
372
379 void ProcessPolygons::SetIntersectAlgorithm(const bool useCenter) {
380 m_useCenter = useCenter;
381 }
382
383
384} /* end namespace isis*/
385
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...
Buffer for containing a three dimensional section of an image.
Definition Brick.h:45
void SetBasePosition(const int start_sample, const int start_line, const int start_band)
This method is used to set the base position of the shape buffer.
Definition Brick.h:120
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
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
static geos::geom::MultiPolygon * Despike(const geos::geom::Geometry *geom)
This method attempts to convert the geom to a MultiPolygon and then despike it.
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
virtual void EndProcess()
End the processing sequence and cleans up by closing cubes, freeing memory, etc.
Definition Process.cpp:462
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 void Finalize()
Cleans up by closing cubes and freeing memory for owned cubes.
Definition Process.cpp:471
void SetIntersectAlgorithm(const bool useCenter)
Sets the algorithm for how output pixels are rasterized.
void FillPolygon(int Flag)
This method does the actuall reading and writing to the cube file.
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.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
bool IsValidPixel(const double d)
Returns if the input pixel is valid.
const double Null
Value for an Isis Null pixel.
Namespace for the standard library.