OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimPotraceTool.cpp
Go to the documentation of this file.
1 //**************************************************************************************************
2 //
3 // OSSIM Open Source Geospatial Data Processing Library
4 // See top level LICENSE.txt file for license information
5 //
6 //**************************************************************************************************
7 
16 #include <sstream>
17 
18 using namespace std;
19 
21  "Computes vector representation of input raster image.";
22 
23 static const string MODE_KW = "mode";
24 static const string ALPHAMAX_KW = "alphamax";
25 static const string TURDSIZE_KW = "turdsize";
26 
28 : m_mode (LINESTRING),
29  m_alphamax (1.0),
30  m_turdSize (4),
31  m_outputToConsole(false),
32  m_maskBitmap (0),
33  m_productBitmap (0)
34 {
35 }
36 
38 {
39  delete m_productBitmap;
40  if (m_maskBitmap)
41  delete m_maskBitmap;
42 }
43 
45 {
46  // Add global usage options. Don't include ossimChipProcUtil options as not appropriate.
48 
49  // Set the general usage:
51  ossimString usageString = ap.getApplicationName();
52  usageString += " potrace [options] <input-raster-file> [<output-vector-file>]";
53  au->setCommandLineUsage(usageString);
54 
55  // Set the command line options:
56  au->addCommandLineOption("--alphamax <float>",
57  "set the corner threshold parameter. The default value is 1. The smaller this value, the "
58  "more sharp corners will be produced. If this parameter is 0, then no smoothing will be "
59  "performed and the output is a polygon. If this parameter is greater than 1.3, then all "
60  "corners are suppressed and the output is completely smooth");
61  au->addCommandLineOption("--mode polygon|linestring",
62  "Specifies whether to represent foreground-background boundary as polygons or line-strings"
63  ". Polygons are closed regions surrounding either null or non-null pixels. Most viewers "
64  "will represent polygons as solid blobs. Line-strings only outline the boundary but do not"
65  " maintain sense of \"insideness\"");
66  au->addCommandLineOption("--mask <filename>",
67  "Use the raster file provided as a mask to exclude any vertices found within 1 pixel of "
68  "a null mask pixel. Implies linestring mode since polygons may not be closed. The mask "
69  "should be a single-band image, but if multi-band, only band 0 will be referenced.");
70  au->addCommandLineOption("--turdsize <int>", "suppress speckles of up to this many pixels.");
71 }
72 
74 {
75  string ts1;
77 
78  if (!ossimTool::initialize(ap))
79  return false;
80 
81  if ( ap.read("--alphamax", sp1))
82  m_kwl.addPair(ALPHAMAX_KW, ts1);
83 
84  if ( ap.read("--mode", sp1))
85  m_kwl.addPair(MODE_KW, ts1);
86 
87  if ( ap.read("--mask", sp1))
88  {
89  // Mask handled as a second image source:
90  ostringstream key;
92  m_kwl.addPair( key.str(), ts1 );
93  }
94 
95  if ( ap.read("--turdsize", sp1))
96  m_kwl.addPair(TURDSIZE_KW, ts1);
97 
99  return true;
100 }
101 
103 {
104  ossimString value;
105  ostringstream xmsg;
106 
107  // Don't copy KWL if member KWL passed in:
108  if (&kwl != &m_kwl)
109  {
110  // Start with clean options keyword list.
111  m_kwl.clear();
112  m_kwl.addList( kwl, true );
113  }
114 
115  value = m_kwl.findKey(ALPHAMAX_KW);
116  if (!value.empty())
117  m_alphamax = value.toDouble();
118 
119  value = m_kwl.findKey(TURDSIZE_KW);
120  if (!value.empty())
121  m_turdSize = value.toInt();
122 
123  value = m_kwl.findKey(MODE_KW);
124  if (value.contains("polygon"))
125  m_mode = POLYGON;
126  else if (value.contains("linestring"))
127  m_mode = LINESTRING;
128  else if (!value.empty())
129  {
130  xmsg <<"ossimPotraceTool:"<<__LINE__<<" Unallowed mode requested: <"<<value<<">."
131  <<endl;
132  throw ossimException(xmsg.str());
133  }
134 
136 }
137 
139 {
140  // Nothing to do.
141 }
142 
144 {
145  // Do nothing and avoid ossimChipProcUtil from doing its standard stuff.
146 }
147 
149 {
150  ostringstream xmsg;
151 
152  if (m_imgLayers.empty() || !m_geom.valid())
153  {
154  xmsg<<"ossimPotraceTool:"<<__LINE__<<" Null input image list encountered! ";
155  throw ossimException(xmsg.str());
156  }
157 
158  // Generate bitmap for input image:
160 
161  // If there is a mask, generate a bitmap for it as well:
162  m_maskBitmap = 0;
163  if (m_imgLayers.size() == 2)
164  {
166  m_mode = LINESTRING;
167  }
168 
169  // Perform vectorization:
170  potrace_param_t* potraceParam = potrace_param_default();
171  potraceParam->turdsize = m_turdSize;
172  potraceParam->alphamax = m_alphamax;
173  potrace_state_t* potraceOutput = potrace_trace(potraceParam, m_productBitmap);
174  if (!potraceOutput)
175  {
176  xmsg <<"ossimPotraceTool:"<<__LINE__<<" Null pointer returned from potrace_trace!";
177  throw ossimException(xmsg.str());
178  }
179 
180  if (m_mode == LINESTRING)
181  transformLineStrings(potraceOutput);
182  else
183  transformPolygons(potraceOutput);
184 
185  // Write to output vector file:
186  if (!writeGeoJSON(potraceOutput->plist))
187  return false;
188 
189  // Release memory:
190  //potrace_state_free(potraceOutput);
191  //free(potraceBitmap->map);
192  free(potraceParam);
193 
194  return true;
195 }
196 
198 {
199  // This is a fairly complex process because potrace assumes all paths are closed, i.e., the
200  // last vertex of a path is the same as the first. For linestring mode, this is not always
201  // true since the path may hit the border or masked region, in which case it needs to be
202  // split into two or more paths.
203 
204  ossimIrect rect;
205  m_geom->getBoundingRect(rect);
206  rect.expand(ossimIpt(-1,-1));
207 
208  // Vector coordinates are in image space. Need geom to convert to geographic lat/lon:
209  potrace_path_t* path = potraceOutput->plist;
210  potrace_path_t* pathToDelete;
211  ossimDpt imgPt;
212  vector<Path*> originalPaths;
213  vector<Path*> adjustedPaths;
214 
215  // Populate the std::vector with original list of potrace paths:
216  while (path)
217  {
218  //cout << "\nProcessing path "<<(long)path<<endl;
219  if (path->curve.n > 0)
220  {
221  // Start by converting all paths to C++ data structures:
222  Path* p = new Path;
223  for (int segment=0; segment<path->curve.n; ++segment)
224  {
225  //cout << " Processing segment "<<segment;
226  p->addPotraceCurve(path->curve, segment);
227  }
228  originalPaths.push_back(p);
229  }
230  potrace_path_t* delete_this_path = path;
231  path = path->next;
232  free(delete_this_path); // Don't need old path anymore
233  }
234 
235  // All paths are now represented by line segments in convenient C++ vector structure. Now
236  // need to filter out masked points, splitting up paths as they encounter the masked regions:
237  for (size_t i=0; i<originalPaths.size(); ++i)
238  {
239  Path* original = originalPaths[i];
240  bool outside = false;
241 
242  //cout << "\nProcessing originalPath["<<i<<"] with numVertices="<<original->vertices.size()<<endl;
243  Path* adjusted = 0;
244  for (size_t v=0; v<original->vertices.size(); ++v)
245  {
246  imgPt = original->vertices[v];
247  if ( rect.pointWithin(imgPt) && !pixelIsMasked(imgPt, m_maskBitmap))
248  {
249  if (!adjusted)
250  {
251  adjusted = new Path;
252  adjustedPaths.push_back(adjusted);
253  //cout << " Creating adjusted="<<(long)adjusted<<endl;
254  }
255  adjusted->vertices.push_back(imgPt);
256  //cout << " Adding to adjusted, imgPt:"<<imgPt<<endl;
257 
258  if (outside)
259  {
260  // Coming in from the outside, so not closed:
261  adjusted->closed = false;
262  outside = false;
263  }
264  }
265  else if (!outside)
266  {
267  // Just went outside. Close this adjusted path and start a new one:
268  //cout << " Hit outside, end of adjusted:"<<(long)adjusted<<endl;
269  if (adjusted)
270  adjusted->closed = false;
271  adjusted = 0;
272  outside = true;
273  }
274  }
275  }
276 
277  // The adjustedPaths list contains only vertices inside the ROI. Now need to move back into
278  // potrace space to prepare potrace data structures for geojson output:
279  ossimGpt gndPt;
280  potrace_path_t* previous_path = 0;
281  vector<Path*>::iterator path_iter = adjustedPaths.begin();
282  while (path_iter != adjustedPaths.end())
283  {
284  // Don't bother with single-vertex "paths":
285  Path* adjusted = *path_iter;
286  if (adjusted->vertices.size() < 3)
287  {
288  ++path_iter;
289  continue;
290  }
291 
292  // Convert image point vertices to ground points and repopulate using potrace
293  // datastructures:
294  //cout << "\nProcessing adjustedPaths["<<i<<"] with numVertices="<<adjusted->vertices.size()<<endl;
295  path = new potrace_path_t;
296  //cout << " Created potrace path:"<<(long)path<<endl;
297  if (previous_path)
298  previous_path->next = path;
299  else
300  potraceOutput->plist = path;
301 
302  int num_segments = (adjusted->vertices.size()+1)/2;
303  path->curve.n = num_segments;
304  path->curve.c = new potrace_dpoint_t[num_segments][3];
305  path->curve.tag = new int[num_segments];
306  path->area = 1;
307  path->sign = 1;
308  path->sibling = 0;
309  path->childlist = 0;
310  path->priv = 0;
311  path->next = 0;
312 
313  // Loop to transfer the vertices to the potrace structure, transforming to lat, lon:
314  int segment = 0;
315  int adj_v = 0;
316  while (adj_v < adjusted->vertices.size())
317  {
318  path->curve.tag[segment] = POTRACE_CORNER;
319 
320  // Transform:
321  imgPt = adjusted->vertices[adj_v++];
322  m_geom->localToWorld(imgPt, gndPt);
323  path->curve.c[segment][1].x = gndPt.lon;
324  path->curve.c[segment][1].y = gndPt.lat;
325  //cout << " Inserted ["<<adj_v-1<<"], imgPt:"<<imgPt<<" --> ("<<gndPt.lon<<", "<<gndPt.lat<<")"<<endl;
326 
327  if (adj_v == adjusted->vertices.size())
328  {
329  //cout << " Inserted above as last"<<endl;
330 
331  path->curve.c[segment][2].x = gndPt.lon;
332  path->curve.c[segment][2].y = gndPt.lat;
333  }
334  else
335  {
336  imgPt = adjusted->vertices[adj_v++];
337  m_geom->localToWorld(imgPt, gndPt);
338  path->curve.c[segment][2].x = gndPt.lon;
339  path->curve.c[segment][2].y = gndPt.lat;
340  //cout << " Inserted ["<<adj_v-1<<"], imgPt:"<<imgPt<<" --> ("<<gndPt.lon<<", "<<gndPt.lat<<")"<<endl;
341  }
342 
343  // Mark the last point as a line segment endpoint to avoid closure:
344  if (adj_v == adjusted->vertices.size() && !adjusted->closed)
345  path->curve.tag[segment] = POTRACE_ENDPOINT;
346 
347  //cout << " Finished segment:"<<segment<<", tag="<<path->curve.tag[segment]<<endl;
348  ++segment;
349  }
350  previous_path = path;
351 
352  // Don't need the adjusted path anymore:
353  delete adjusted;
354  adjusted = 0;
355  ++path_iter;
356  }
357 }
358 
360 {
361  // Vector coordinates are in image space. Need geom to convert to geographic lat/lon:
362  potrace_path_t* path = potraceOutput->plist;
363  ossimDpt imgPt;
364  ossimGpt gndPt;
365  while (path)
366  {
367  for (int segment=0; segment<path->curve.n;)
368  {
369  //cout << "\nWorking on path="<<(long)path<<" segment="<<segment<<", tag="<<path->curve.tag[segment]<<endl;
370  // Convert up to 3 possible vertices per segment
371  for (int v=0; v<3; ++v)
372  {
373  if ((v == 0) && (path->curve.tag[segment] == POTRACE_CORNER))
374  {
375  //cout << "Hit corner"<<endl;
376  continue;
377  }
378 
379  imgPt.x = path->curve.c[segment][v].x;
380  imgPt.y = path->curve.c[segment][v].y;
381  //cout << "imgPt["<<v<<"] = "<<imgPt<<endl;
382 
383  m_geom->localToWorld(imgPt, gndPt);
384  path->curve.c[segment][v].x = gndPt.lon;
385  path->curve.c[segment][v].y = gndPt.lat;
386  }
387  ++segment;
388  }
389  path = path->next;
390  }
391 }
392 
394 {
395  ostringstream value;
396  value << "polygon|linestring (optional, defaults to polygon)";
397  kwl.addPair(MODE_KW, value.str());
398 
399  value.clear();
400  value<<"<float> (optional, defaults to "<<m_alphamax<<")";
401  kwl.addPair(ALPHAMAX_KW, value.str());
402 
403  value.clear();
404  value<<"<int> (optional, defaults to "<<m_turdSize<<")";
405  kwl.addPair(TURDSIZE_KW, value.str());
406 
407  kwl.add("image_file0", "<input-raster-file>");
408  kwl.add("image_file1", "<mask-file> (optional)");
409  kwl.add(ossimKeywordNames::OUTPUT_FILE_KW, "<output-vector-file>");
410 }
411 
413 {
414  potrace_bitmap_t* potraceBitmap = new potrace_bitmap_t;
415 
416  // Determine output bitmap size to even word boundary:
417  ossimIrect rect;
418  raster->getImageGeometry()->getBoundingRect(rect);
419  potraceBitmap->w = rect.width();
420  potraceBitmap->h = rect.height();
421  int pixelsPerWord = 8 * sizeof(int*);
422  potraceBitmap->dy = (int) ceil((double)rect.width()/pixelsPerWord);
423 
424  // Allocate the bitmap memory:
425  unsigned long bufLength = potraceBitmap->dy*potraceBitmap->h;
426  potraceBitmap->map = new potrace_word[bufLength];
427 
428  // Prepare to sequence over all input image tiles and fill the bitmap image:
430  ossimRefPtr<ossimImageData> tile = sequencer->getNextTile();
431  double null_pix = tile->getNullPix(0);
432  unsigned long offset=0;
433  ossimIpt pt_ul, pt, pt_lr;
434 
435  // Loop to fill bitmap buffer:
436  while (tile.valid())
437  {
438  pt_ul = tile->getOrigin();
439  pt_lr.x = pt_ul.x + tile->getWidth();
440  pt_lr.y = pt_ul.y + tile->getHeight();
441  if (pt_lr.x > rect.lr().x)
442  pt_lr.x = rect.lr().x;
443  if (pt_lr.y > rect.lr().y)
444  pt_lr.y = rect.lr().y;
445 
446  // Nested loops over all pixels in input tile:
447  for (pt.y=pt_ul.y; pt.y < pt_lr.y; ++pt.y)
448  {
449  offset = pt_ul.x/pixelsPerWord + pt.y*potraceBitmap->dy;
450  for (pt.x=pt_ul.x; pt.x<pt_lr.x; )
451  {
452  // Loop to pack a word buffer with pixel on (non-null) or off bit in proper positions:
453  unsigned long wordBuf = 0;
454  for (int bitpos=pixelsPerWord-1; bitpos>=0; --bitpos)
455  {
456  unsigned long pixel = (tile->getPix(pt) != null_pix) ? 1 : 0;
457  wordBuf |= pixel << bitpos;
458  ++pt.x;
459  if (pt.x >= pt_lr.x)
460  break;
461  }
462  potraceBitmap->map[offset++] = wordBuf;
463  }
464  }
465 
466  tile = sequencer->getNextTile();
467  }
468 
469 #if 0
470  FILE* pbm = fopen("TEMP.pbm", "w");
471  potrace_writepbm(pbm, potraceBitmap);
472 #endif
473 
474  return potraceBitmap;
475 }
476 
477 bool ossimPotraceTool::pixelIsMasked(const ossimIpt& image_pt, potrace_bitmap_t* bitmap) const
478 {
479  if (bitmap == 0)
480  return false;
481 
482  int pixelsPerWord = 8 * sizeof(int*);
483  unsigned long offset = image_pt.x/pixelsPerWord + image_pt.y*bitmap->dy;
484  int shift = pixelsPerWord - (image_pt.x % pixelsPerWord) - 1;
485  unsigned long wordBuf = bitmap->map[offset];
486  unsigned long shifted = wordBuf >> shift;
487  shifted = shifted & 1;
488  if (shifted == 0)
489  return true;
490  return false;
491 }
492 
494 {
495  ostringstream xmsg;
496 
497  FILE* outFile = fopen(m_productFilename.chars(), "w");
498  if (!outFile)
499  {
500  xmsg <<"ossimPotraceTool:"<<__LINE__<<" Could not open output file <"<<m_productFilename
501  <<"> for writing.";
502  throw ossimException(xmsg.str());
503  }
504 
505  potrace_geojson(outFile, vectorList, (int) (m_mode == POLYGON));
506  fclose(outFile);
507 
509  {
510  ifstream vectorFile (m_productFilename.chars());
511  if (vectorFile.fail())
512  {
513  xmsg <<"ossimPotraceTool:"<<__LINE__<<" Error encountered opening temporary vector file at: "
514  "<"<<m_productFilename<<">.";
515  throw ossimException(xmsg.str());
516  }
517 
518  *m_consoleStream << vectorFile.rdbuf();
519  vectorFile.close();
520  }
521 
522  return true;
523 }
524 
526 {
527  vertices.clear();
528 }
529 
530 
532 {
533  potrace_dpoint_t *c = curve.c[segment];
534  if (curve.tag[segment] == POTRACE_CORNER)
535  {
536  // Just add next connected line segment
537  ossimDpt v1 (c[1].x, c[1].y);
538  ossimDpt v2 (c[2].x, c[2].y);
539  vertices.push_back(v1);
540  vertices.push_back(v2);
541  //cout <<" Added corners v1:"<<v1<<endl;
542  //cout <<" v2:"<<v2<<endl;
543  }
544  else
545  {
546  // Need to convert bezier curve representation to line segments:
547  ossimDpt v0;
548  ossimDpt v1 (c[0].x, c[0].y);
549  ossimDpt v2 (c[1].x, c[1].y);
550  ossimDpt v3 (c[2].x, c[2].y);
551 
552  // Need the first vertex from the previous segment if available:
553  if (segment == 0)
554  v0 = v1;
555  else
556  {
557  c = curve.c[segment-1];
558  v0.x = c[2].x;
559  v0.y = c[2].y;
560  }
561  //cout <<" Processing curve v0:"<<v0<<endl;
562  //cout <<" v1:"<<v1<<endl;
563  //cout <<" v2:"<<v2<<endl;
564  //cout <<" v3:"<<v3<<endl;
565 
566  // Now loop to extract line segments from bezier curve:
567  double step, t, s;
568  ossimDpt vertex;
569  step = 1.0 / 8.0;
570  t = step;
571  for (int i=0; i<8; i++)
572  {
573  s = 1.0 - t;
574  vertex.x = s*s*s*v0.x + 3*(s*s*t)*v1.x + 3*(t*t*s)*v2.x + t*t*t*v3.x;
575  vertex.y = s*s*s*v0.y + 3*(s*s*t)*v1.y + 3*(t*t*s)*v2.y + t*t*t*v3.y;
576  vertices.push_back(vertex);
577  t += step;
578  //cout <<" added vertex:"<<vertex<<endl;
579  }
580  }
581 }
582 
int potrace_geojson(FILE *fout, potrace_path_t *plist, int as_polygons)
virtual ossim_uint32 getWidth() const
ossim_uint32 x
virtual void getKwlTemplate(ossimKeywordlist &kwl)
Assigns a template keywordlist to string for initializing derived classes.
virtual bool initialize(ossimArgumentParser &ap)
Initial method to be ran prior to execute.
std::string getApplicationName() const
return the application name, as specified by argv[0]
void addCommandLineOption(const ossimString &option, const ossimString &explanation)
static const char * DESCRIPTION
ossimRefPtr< ossimImageGeometry > m_geom
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
static const char * OUTPUT_FILE_KW
Represents serializable keyword/value map.
const std::string & findKey(const std::string &key) const
Find methods that take std::string(s).
ossim_uint32 y
std::basic_ifstream< char > ifstream
Class for char input file streams.
Definition: ossimIosFwd.h:44
potrace_bitmap_t * m_maskBitmap
bool valid() const
Definition: ossimRefPtr.h:75
virtual void setUsage(ossimArgumentParser &ap)
Initializes the aurgument parser with expected parameters and options.
bool read(const std::string &str)
search for an occurance of a string in the argument list, on sucess remove that occurance from the li...
void getBoundingRect(ossimIrect &bounding_rect) const
Get the bounding rect of (0, 0) to (imageSize.x-1, imageSize.y-1).
potrace_bitmap_t * convertToBitmap(ossimImageSource *handler)
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
bool contains(char aChar) const
Definition: ossimString.h:58
virtual ossimRefPtr< ossimImageData > getNextTile(ossim_uint32 resLevel=0)
void addList(const ossimKeywordlist &src, bool overwrite=true)
struct potrace_path_s * childlist
Definition: potracelib.h:93
ossimKeywordlist m_kwl
Definition: ossimTool.h:148
virtual ossim_uint32 getHeight() const
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
double alphamax
Definition: potracelib.h:38
void setCommandLineUsage(const ossimString &explanation)
virtual ossim_float64 getPix(const ossimIpt &position, ossim_uint32 band=0) const
Will return the pixel at location position.
virtual void initProcessingChain()
Derived classes initialize their custom chains here.
void potrace_writepbm(FILE *fout, potrace_bitmap_t *bm)
ossimApplicationUsage * getApplicationUsage()
potrace_state_t * potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm)
const ossimIrect & expand(const ossimIpt &padding)
Definition: ossimIrect.cpp:308
potrace_word * map
Definition: potracelib.h:58
struct potrace_bitmap_s potrace_bitmap_t
Definition: potracelib.h:60
unsigned long potrace_word
Definition: potracelib.h:49
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
#define POTRACE_CORNER
Definition: potracelib.h:73
struct potrace_path_s * next
Definition: potracelib.h:91
ossimFilename m_productFilename
ossim_float64 lon
Definition: ossimGpt.h:266
virtual void setUsage(ossimArgumentParser &ap)
Initializes the aurgument parser with expected parameters and options.
Definition: ossimTool.cpp:41
bool localToWorld(const ossimDpt &local_pt, ossimGpt &world_pt) const
Exposes the 3D projection from image to world coordinates.
void processRemainingArgs(ossimArgumentParser &ap)
Intended to be called after derived class has picked off its own options from the parser...
virtual const ossim_float64 * getNullPix() const
const char * chars() const
For backward compatibility.
Definition: ossimString.h:77
#define POTRACE_ENDPOINT
Definition: potracelib.h:74
double toDouble() const
std::vector< ossimRefPtr< ossimSingleImageChain > > m_imgLayers
struct potrace_privpath_s * priv
Definition: potracelib.h:96
virtual bool initialize(ossimArgumentParser &ap)
Initial method to be ran prior to execute.
virtual bool initialize(ossimArgumentParser &ap)
Initializes from command line arguments.
Definition: ossimTool.cpp:58
const ossimIpt & lr() const
Definition: ossimIrect.h:276
std::vector< ossimDpt > vertices
std::ostream * m_consoleStream
Definition: ossimTool.h:149
void addPotraceCurve(potrace_curve_t &curve, int segment)
ossim_uint32 width() const
Definition: ossimIrect.h:500
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if not defined...
bool pixelIsMasked(const ossimIpt &image_pt, potrace_bitmap_t *bitmap) const
virtual void finalizeChain()
Called after initProcessingChain() to append common items to the processing chain.
void transformLineStrings(potrace_state_t *pathTree)
ossim_int32 y
Definition: ossimIpt.h:142
virtual bool execute()
Performs the actual product write.
void transformPolygons(potrace_state_t *pathTree)
double x
Definition: ossimDpt.h:164
struct potrace_path_s * sibling
Definition: potracelib.h:94
bool empty() const
Definition: ossimString.h:411
potrace_bitmap_t * m_productBitmap
ossim_int32 x
Definition: ossimIpt.h:141
ossim_float64 lat
Definition: ossimGpt.h:265
virtual ~ossimPotraceTool()
struct potrace_path_s potrace_path_t
Definition: potracelib.h:98
potrace_param_t * potrace_param_default(void)
potrace_path_t * plist
Definition: potracelib.h:108
static const char * IMAGE_FILE_KW
bool writeGeoJSON(potrace_path_t *vectorList)
virtual const ossimIpt & getOrigin() const
potrace_dpoint_t(* c)[3]
Definition: potracelib.h:80
int toInt() const
potrace_curve_t curve
Definition: potracelib.h:89
bool pointWithin(const ossimIpt &pt) const
Definition: ossimIrect.h:729