OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimPolygon.cpp
Go to the documentation of this file.
1 //*****************************************************************************
2 // FILE: ossimPolygon.cpp
3 //
4 // License: LGPL
5 //
6 // AUTHOR: Oscar Kramer
7 //
8 // DESCRIPTION: Contains implementation of class
9 //
10 // LIMITATIONS: None.
11 //
12 //*****************************************************************************
13 // $Id: ossimPolygon.cpp 19682 2011-05-31 14:21:20Z dburken $
14 
16 #include <ossim/base/ossimLine.h>
17 #include <ossim/base/ossimCommon.h>
21 #include <ossim/base/ossimString.h>
22 #include <algorithm>
23 #include <iterator>
24 #include <sstream>
25 #include <iterator>
26 
27 static const char* NUMBER_VERTICES_KW = "number_vertices";
28 static const char* VERTEX_ORDER_KW = "order";
29 
30 static const int RECT_LEFT_EDGE = 0;
31 static const int RECT_TOP_EDGE = 1;
32 static const int RECT_RIGHT_EDGE = 2;
33 static const int RECT_BOTTOM_EDGE = 3;
34 
36  : theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN),
37  theVertexList(),
38  theCurrentVertex(0)
39 
40 {}
41 
42 ossimPolygon::ossimPolygon(const vector<ossimIpt>& polygon)
43  :theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN),
44  theVertexList(polygon.size()),
45  theCurrentVertex(0)
46 
47 {
48  // Assign std::vector<ossimIpt> list to std::vector<ossimDpt> theVertexList.
49  for (std::vector<ossimIpt>::size_type i = 0; i < polygon.size(); ++i)
50  {
51  theVertexList[i] = polygon[i];
52  }
53 }
54 
55 ossimPolygon::ossimPolygon(const vector<ossimGpt>& polygon)
56  :theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN),
57  theVertexList(polygon.size()),
58  theCurrentVertex(0)
59 
60 {
61  // Assign std::vector<ossimIpt> list to std::vector<ossimDpt> theVertexList.
62  for (std::vector<ossimGpt>::size_type i = 0; i < polygon.size(); ++i)
63  {
64  theVertexList[i] = polygon[i];
65  }
66 }
67 
68 
69 ossimPolygon::ossimPolygon(const vector<ossimDpt>& polygon)
70  :theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN),
71  theVertexList(polygon),
72  theCurrentVertex(0)
73 {
74 }
75 
76 //*****************************************************************************
77 // CONSTRUCTOR: ossimPolygon(int numVertices, const ossimDpt* vertex_array)
78 //
79 //*****************************************************************************
80 ossimPolygon::ossimPolygon(int numVertices, const ossimDpt* v)
81  : theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN),
82  theCurrentVertex(0)
83 
84 {
85  theVertexList.insert(theVertexList.begin(),
86  v, v+numVertices);
87 }
88 
89 //*****************************************************************************
90 // COPY CONSTRUCTOR: ossimPolygon(ossimPolygon)
91 //
92 //*****************************************************************************
94  :theCurrentVertex(0)
95 {
96  *this = polygon;
97 }
98 
99 //*****************************************************************************
100 // CONSTRUCTOR: ossimPolygon(p1, p2, p3, p4)
101 //
102 // Provided for convenience. Does not imply the polygon is limited to four
103 // vertices
104 //
105 //*****************************************************************************
107  ossimDpt v2,
108  ossimDpt v3,
109  ossimDpt v4)
110  : theOrderingType(OSSIM_VERTEX_ORDER_UNKNOWN),
111  theVertexList(4),
112  theCurrentVertex(0)
113 
114 {
115  theVertexList[0] = v1;
116  theVertexList[1] = v2;
117  theVertexList[2] = v3;
118  theVertexList[3] = v4;
119 }
120 
122 : theOrderingType(OSSIM_CLOCKWISE_ORDER),
123  theVertexList(4),
124  theCurrentVertex(0)
125 {
126  theVertexList[0] = rect.ul();
127  theVertexList[1] = rect.ur();
128  theVertexList[2] = rect.lr();
129  theVertexList[3] = rect.ll();
130 }
131 
133 : theOrderingType(OSSIM_CLOCKWISE_ORDER),
134 theVertexList(4),
135 theCurrentVertex(0)
136 {
137  theVertexList[0] = rect.ul();
138  theVertexList[1] = rect.ur();
139  theVertexList[2] = rect.lr();
140  theVertexList[3] = rect.ll();
141 }
142 
143 
144 //*****************************************************************************
145 // DESTRUCTOR: ~ossimPolygon
146 //
147 //*****************************************************************************
149 {
150 }
151 
152 
153 //*************************************************************************************************
155 //*************************************************************************************************
156 double ossimPolygon::area()const
157 {
158  double area = 0;
159  ossim_uint32 i=0;
160  ossim_uint32 j=0;
162 
163  for (i=0;i<size;i++)
164  {
165  j = (i + 1) % (int)size;
166  area += theVertexList[i].x * theVertexList[j].y;
167  area -= theVertexList[i].y * theVertexList[j].x;
168  }
169 
170  area /= 2;
171 
172  return area;
173 }
174 
176 {
177  int i = 0;
178  for(i = 0; i < (int)theVertexList.size(); ++i)
179  {
181  }
182 
183  if(compress&&theVertexList.size())
184  {
185  vector<ossimDpt> polyLine;
186 
187  polyLine.push_back(theVertexList[0]);
188  ossimDpt testPt = theVertexList[0];
189  for(i=1; i < (int)theVertexList.size(); ++i)
190  {
191  if(testPt!=theVertexList[i])
192  {
193  testPt = theVertexList[i];
194  polyLine.push_back(testPt);
195  }
196  }
197  if(polyLine.size() == 1)
198  {
199  polyLine.push_back(polyLine[0]);
200  }
201 
202  if(theVertexList.size() == 1)
203  {
204  polyLine.push_back(testPt);
205  }
206  theVertexList = polyLine;
207  theCurrentVertex = 0;
208  }
209 }
210 
212 {
213  int upper = (int)theVertexList.size();
214  ossimDpt result(0.0, 0.0);
215  int i = 0;
216 
217  if(!upper)
218  {
219  result.makeNan();
220  }
221  else
222  {
223  for(i = 0; i < upper; ++i)
224  {
225  result.x+=theVertexList[i].x;
226  result.y+=theVertexList[i].y;
227  }
228  result.x/=(double)upper;
229  result.y/=(double)upper;
230  }
231 
232  return result;
233 }
234 
236 {
237  int upper = (int)theVertexList.size();
238  int i = 0;
239 
240  for(i = 0; i < upper; ++i)
241  {
242  if(theVertexList[i].hasNans())
243  {
244  return true;
245  }
246  }
247 
248  return false;
249 }
250 
252  ossim_int32& minY,
253  ossim_int32& maxX,
254  ossim_int32& maxY)const
255 {
256  ossim_int32 npoly = (ossim_int32)theVertexList.size();
257  int i = 0;
258 
259  if(npoly)
260  {
261  minX = (ossim_int32)floor(theVertexList[0].x);
262  maxX = (ossim_int32)ceil(theVertexList[0].x);
263  minY = (ossim_int32)floor(theVertexList[0].y);
264  maxY = (ossim_int32)ceil(theVertexList[0].y);
265 
266  for(i =1; i < npoly; ++i)
267  {
268  minX = std::min((ossim_int32)floor(theVertexList[i].x),
269  (ossim_int32)minX);
270  maxX = std::max((ossim_int32)ceil(theVertexList[i].x),
271  (ossim_int32)maxX);
272  minY = std::min((ossim_int32)floor(theVertexList[i].y),
273  (ossim_int32)minY);
274  maxY = std::max((ossim_int32)ceil(theVertexList[i].y),
275  (ossim_int32)maxY);
276  }
277  }
278  else
279  {
280  minX = OSSIM_INT_NAN;
281  minY = OSSIM_INT_NAN;
282  maxX = OSSIM_INT_NAN;
283  maxY = OSSIM_INT_NAN;
284  }
285 }
286 
288  ossim_float64& minY,
289  ossim_float64& maxX,
290  ossim_float64& maxY) const
291 {
292  ossim_int32 npoly = (ossim_int32)theVertexList.size();
293  int i = 0;
294 
295  if(npoly)
296  {
297  minX = floor(theVertexList[0].x);
298  maxX = ceil(theVertexList[0].x);
299  minY = floor(theVertexList[0].y);
300  maxY = ceil(theVertexList[0].y);
301 
302  for(i =1; i < npoly; ++i)
303  {
304  minX = std::min<double>(floor(theVertexList[i].x), minX);
305  maxX = std::max<double>(ceil(theVertexList[i].x), maxX);
306  minY = std::min<double>(floor(theVertexList[i].y), minY);
307  maxY = std::max<double>(ceil(theVertexList[i].y), maxY);
308  }
309  }
310  else
311  {
312  minX = ossim::nan();
313  minY = ossim::nan();
314  maxX = ossim::nan();
315  maxY = ossim::nan();
316  }
317 }
318 
319 bool ossimPolygon::clipToRect(vector<ossimPolygon>& result,
320  const ossimDrect& rect)const
321 {
322  result.clear();
323  ossimPolyArea2d p1(*this);
324  ossimPolyArea2d p2(rect.ul(), rect.ur(), rect.lr(), rect.ll());
325 
326  p1&=p2;
327 
328  p1.getVisiblePolygons(result);
329 
330  return (result.size() > 0);
331 }
332 
333 //*****************************************************************************
334 // METHOD: ossimPolygon::clipLineSegment(p1, p2)
335 //
336 // Implements Cyrus-Beck clipping algorithm as described in:
337 // http://www.daimi.au.dk/~mbl/cgcourse/wiki/cyrus-beck_line-clipping_.html
338 //
339 // Clips the line segment defined by the two endpoints provided. The
340 // endpoints are modified as needed to represent the clipped line. Returns
341 // true if intersection present.
342 //
343 //*****************************************************************************
345 {
346  ossimDpt PQ (Q - P);
347  double tE = 0.0;
348  double tL = 1.0;
349  ossimLine edge, edgeE, edgeL;
350  bool intersected=false;
351  double num, denom, t;
352  ossim_uint32 npol = (ossim_uint32)theVertexList.size();
353 
354  checkOrdering();
355  //***
356  // clip the segment against each edge of the polygon
357  //***
358  ossim_uint32 i = 0;
359  ossim_uint32 j = 0;
360  for(i = 0, j = 1; i < npol;)
361  {
362  edge = ossimLine(theVertexList[i],
363  theVertexList[j]);
364 
365  ossimDpt normal = edge.normal();
366 
367  // Fix from CChuah@observera.com for counter clockwise polygons. (drb)
369  {
370  normal.x = -normal.x;
371  normal.y = -normal.y;
372  }
373 
374  denom = normal.x*PQ.x + normal.y*PQ.y;
375 
376  num = normal.x*(edge.theP1.x - P.x) + normal.y*(edge.theP1.y - P.y);
377 
378  if (denom < 0)
379  {
380  //***
381  // Appears to be entering:
382  //***
383  t = num / denom;
384  if (t > tE)
385  {
386  tE = t; //+ FLT_EPSILON;
387  edgeE = edge;
388  }
389  }
390  else if (denom > 0)
391  {
392  //***
393  // Appears to be leaving:
394  //***
395  t = num / denom;
396  if (t < tL)
397  {
398  tL = t;// - FLT_EPSILON;
399  edgeL = edge;
400  }
401  }
402 
403  ++i;
404  ++j;
405  j%=npol;
406  }
407 
408  //***
409  // Compute clipped end points:
410  //***
411  if(tL >= tE)
412  {
413  Q.x = P.x + tL*PQ.x;
414  Q.y = P.y + tL*PQ.y;
415  P.x += tE*PQ.x;
416  P.y += tE*PQ.y;
417  intersected = true;
418  }
419 
420  return intersected;
421 }
422 
427 bool ossimPolygon::isRectWithin(const ossimIrect &rect) const
428 {
429  if(isPointWithin(rect.ul()) &&
430  isPointWithin(rect.ur()) &&
431  isPointWithin(rect.ll()) &&
432  isPointWithin(rect.lr())) {
433  return true;
434  }
435  return false;
436 }
437 
439 {
440  if ( isPointWithin(rect.ul()) ||
441  isPointWithin(rect.ur()) ||
442  isPointWithin(rect.ll()) ||
443  isPointWithin(rect.lr()))
444  {
445  return true;
446  }
447  return false;
448 }
449 
454 bool ossimPolygon::isPolyWithin(const ossimPolygon &poly) const
455 {
456  bool ret=false;
457  int numvertex=poly.getNumberOfVertices();
458  if(getNumberOfVertices()>1 && numvertex) {
459  ret=true;
460  for(int v=0;v<numvertex;v++) {
461  if(!isPointWithin(poly[v])) {
462  ret=false;
463  break;
464  }
465  }
466  }
467  return ret;
468 }
469 
470 //*****************************************************************************
471 // METHOD: ossimPolygon::pointWithin(const ossimDpt& point)
472 //
473 // Returns TRUE if point is inside polygon.
474 //
475 //*****************************************************************************
476 bool ossimPolygon::isPointWithin(const ossimDpt& point) const
477 {
478 
479  int i, j, c = 0;
480  int npol = (int)theVertexList.size();
481 
482  for (i = 0, j = npol-1; i < npol; j = i++)
483  {
484  if ((((theVertexList[i].y <= point.y) && (point.y < theVertexList[j].y)) ||
485  ((theVertexList[j].y <= point.y) && (point.y < theVertexList[i].y))) &&
486  (point.x < (theVertexList[j].x - theVertexList[i].x) * (point.y - theVertexList[i].y) /
487  (theVertexList[j].y - theVertexList[i].y) + theVertexList[i].x))
488  {
489  c = !c;
490  }
491  }
492 
493  if(!c) // check if on if not within
494  {
495  for (i = 0, j = npol-1; i < npol; j = i++)
496  {
498  {
499  return true;
500  }
501  }
502  }
503 
504  return (c!=0);
505 }
506 
507 //*****************************************************************************
508 // METHOD: ossimPolygon::vertex(int)
509 //
510 // Returns the ossimDpt vertex given the index. Also initializes the current
511 // edge (theCurrentEdge) to the edge corresponding to the index.
512 //
513 //*****************************************************************************
514 bool ossimPolygon::vertex(int index, ossimDpt& tbd_vertex) const
515 {
516  if((index >= (int)theVertexList.size()) ||
517  (index < 0))
518  {
519  return false;
520  }
521 
522  tbd_vertex = theVertexList[index];
523  theCurrentVertex = index;
524 
525  return true;
526 }
527 
528 //*****************************************************************************
529 // METHOD: ossimPolygon::nextVertex()
530 //
531 // Assigns the ossimDpt tbd_vertex following the current vertex. The current
532 // vertex is initialized with a call to vertex(int), or after the last
533 // vertex is reached (initialized to theFirstEdge. Returns false if no vertex
534 // defined.
535 //
536 //*****************************************************************************
537 bool ossimPolygon::nextVertex(ossimDpt& tbd_vertex) const
538 {
541  {
542  return false;
543  }
544  tbd_vertex = theVertexList[theCurrentVertex];
545 
546  return true;
547 }
548 
549 //*****************************************************************************
550 // METHOD: operator=()
551 //
552 //*****************************************************************************
554 {
555  theCurrentVertex = 0;
556  theVertexList.resize(4);
557  theVertexList[0] = rect.ul();
558  theVertexList[1] = rect.ur();
559  theVertexList[2] = rect.lr();
560  theVertexList[3] = rect.ll();
561 
562  return *this;
563 }
564 
566 {
567  theCurrentVertex = 0;
568  theVertexList.resize(4);
569  theVertexList[0] = rect.ul();
570  theVertexList[1] = rect.ur();
571  theVertexList[2] = rect.lr();
572  theVertexList[3] = rect.ll();
573 
574  return *this;
575 }
576 
578 {
579  theVertexList = polygon.theVertexList;
582 
583  return *this;
584 }
585 
586 const ossimPolygon& ossimPolygon::operator= (const vector<ossimDpt>& vertexList)
587 {
588  theVertexList = vertexList;
589  theCurrentVertex = 0;
591 
592  return *this;
593 }
594 
595 const ossimPolygon& ossimPolygon::operator=(const vector<ossimIpt>& vertexList)
596 {
597  theVertexList.resize(vertexList.size());
598 
599  // Assign std::vector<ossimIpt> list to std::vector<ossimDpt> theVertexList.
600  for (std::vector<ossimIpt>::size_type i = 0; i < vertexList.size(); ++i)
601  {
602  theVertexList[i] = vertexList[i];
603  }
604 
605  theCurrentVertex = 0;
607 
608  return *this;
609 }
610 
611 const ossimPolygon& ossimPolygon::operator=(const vector<ossimGpt>& vertexList)
612 {
613  theVertexList.resize(vertexList.size());
614 
615  // Assign std::vector<ossimIpt> list to std::vector<ossimDpt> theVertexList.
616  for (std::vector<ossimIpt>::size_type i = 0; i < vertexList.size(); ++i)
617  {
618  theVertexList[i] = vertexList[i];
619  }
620 
621  theCurrentVertex = 0;
623 
624  return *this;
625 }
626 
627 //*****************************************************************************
628 // METHOD: operator==()
629 //
630 //*****************************************************************************
631 bool ossimPolygon::operator==(const ossimPolygon& polygon) const
632 {
633  if( (theVertexList.size() != polygon.theVertexList.size()))
634  {
635  return false;
636  }
637  if(!theVertexList.size() && polygon.theVertexList.size())
638  {
639  return true;
640  }
641 
642  return (theVertexList == polygon.theVertexList);
643 }
644 
646 {
647  ossim_uint32 upper = (ossim_uint32)theVertexList.size();
648  ossim_uint32 i = 0;
649  for(i = 0; i < upper; ++i)
650  {
651  theVertexList[i].x*=scale.x;
652  theVertexList[i].y*=scale.y;
653  }
654 
655  return *this;
656 }
657 
659 {
660  ossimPolygon result(*this);
661 
662  ossim_uint32 upper = (ossim_uint32)theVertexList.size();
663  ossim_uint32 i = 0;
664  for(i = 0; i < upper; ++i)
665  {
666  result.theVertexList[i].x*=scale.x;
667  result.theVertexList[i].y*=scale.y;
668  }
669 
670  return result;
671 }
672 
673 
675 {
676  std::reverse(theVertexList.begin(), theVertexList.end());
677 
679  {
681  }
683  {
685  }
686 
687 }
688 
689 //*****************************************************************************
690 // METHOD: ossimPolygon::print(ostream)
691 //
692 //*****************************************************************************
694 {
695  copy(theVertexList.begin(),
696  theVertexList.end(),
697  ostream_iterator<ossimDpt>(os, "\n"));
698 }
699 
700 
702 {
704  {
705  double areaValue = area();
706  if(areaValue > 0)
707  {
709  }
710  else if(areaValue <= 0)
711  {
713  }
714  }
715 
716  return theOrderingType;
717 }
718 
720  const ossimLine& segment,
721  const ossimDrect& rect,
722  int edge)
723 {
724  ossimLine edgeLine;
725  switch(edge)
726  {
727  case RECT_LEFT_EDGE:
728  {
729  edgeLine.theP1 = rect.ll();
730  edgeLine.theP2 = rect.ul();
731  break;
732  }
733  case RECT_TOP_EDGE:
734  {
735  edgeLine.theP1 = rect.ul();
736  edgeLine.theP2 = rect.ur();
737  break;
738  }
739  case RECT_RIGHT_EDGE:
740  {
741  edgeLine.theP1 = rect.ur();
742  edgeLine.theP2 = rect.lr();
743  break;
744  }
745  case RECT_BOTTOM_EDGE:
746  {
747  edgeLine.theP1 = rect.lr();
748  edgeLine.theP2 = rect.ll();
749  break;
750  }
751  }
752 
753  result = segment.intersectInfinite(edgeLine);
754 }
755 
757  const ossimDrect& rect,
758  int edge)const
759 {
760  switch(edge)
761  {
762  case RECT_LEFT_EDGE:
763  {
764  return (pt.x>rect.ul().x);
765  break;
766  }
767  case RECT_TOP_EDGE:
768  {
769  if(rect.orientMode() == OSSIM_LEFT_HANDED)
770  {
771  return (pt.y > rect.ul().y);
772  }
773  else
774  {
775  return (pt.y < rect.ul().y);
776  }
777  break;
778  }
779  case RECT_RIGHT_EDGE:
780  {
781  return (pt.x<rect.lr().x);
782 
783  break;
784  }
785  case RECT_BOTTOM_EDGE:
786  {
787  if(rect.orientMode() == OSSIM_LEFT_HANDED)
788  {
789  return (pt.y < rect.lr().y);
790  }
791  else
792  {
793  return (pt.y > rect.lr().y);
794  }
795  break;
796  }
797  }
798  return false;
799 }
800 
801 
803  const char* prefix)const
804 {
805  kwl.add(prefix,
807  "ossimPolygon",
808  true);
809  kwl.add(prefix,
810  NUMBER_VERTICES_KW,
811  static_cast<ossim_uint32>(theVertexList.size()),
812  true);
813  int i = 0;
814  for(i = 0; i < (int)theVertexList.size();++i)
815  {
816  ossimString vert = "v"+ossimString::toString(i);;
817  ossimString value = (ossimString::toString(theVertexList[i].x) + " " +
819  kwl.add(prefix,
820  vert.c_str(),
821  value.c_str(),
822  true);
823  }
824  ossimString order = "";
825 
826  switch(theOrderingType)
827  {
829  {
830  order = "unknown";
831  break;
832  }
834  {
835  order = "clockwise";
836  break;
837  }
839  {
840  order = "counter_clockwise";
841  break;
842  }
843  }
844  kwl.add(prefix,
845  VERTEX_ORDER_KW,
846  order,
847  true);
848 
849  return true;
850 }
851 
853  const char* prefix)
854 {
855  ossimString order = kwl.find(prefix, VERTEX_ORDER_KW);
856  const char* number_vertices = kwl.find(prefix, NUMBER_VERTICES_KW);
857  ossimString x,y;
858  if(order=="unknown")
859  {
861  }
862  else if(order =="clockwise")
863  {
865  }
866  else if(order =="counter_clockwise")
867  {
869  }
870 
871  theVertexList.clear();
872  int vertexCount = ossimString(number_vertices).toLong();
873  int i = 0;
874  for(i = 0; i < vertexCount; ++i)
875  {
876  ossimString v = kwl.find(prefix, (ossimString("v")+ossimString::toString(i)).c_str());
877  v = v.trim();
878 
879  istringstream vStream(v.string());
880  vStream >> x.string() >> y.string();
881  theVertexList.push_back(ossimDpt(x.toDouble(),y.toDouble()));
882  }
883 
884  return true;
885 }
886 
888 {
889  static const double MIN_STEP = (0.5)*M_PI/180.0;
890  double angle_step = M_PI/8.0; // initial rotation step size for min area search = 22.5 deg
891  double theta;
892  double best_theta = M_PI/4.0; // Initial guess is 45 deg orientation
893  double center_theta;
894  double cos_theta, sin_theta;
895  ossimPolygon rotatedPolygon(*this);
896  ossimDpt xlatedVertex;
897  ossimDpt rotatedVertex(0.0, 0.0);
898  double min_x, min_y, max_x, max_y;
899  double area;
900  double min_area = 1.0/DBL_EPSILON;
901  rotatedPolygon.theVertexList[0] = ossimDpt(0, 0); // first vertex always at origin
902  bool first_time = true;
903  ossimDrect best_rect;
904  static const bool TESTING = false;
905 
906  //***
907  // Loop to converge on best orientation angle for bounding polygon:
908  //***
909  while (angle_step > MIN_STEP)
910  {
911  //***
912  // Try four different rotations evenly centered about the current best guess:
913  //***
914  center_theta = best_theta;
915  for (int i=0; i<5; i++)
916  {
917  //***
918  // Check for i=2 (center angle) since already computed quantities for this in last iteration
919  // unless this is first time through:
920  //***
921  if ((i != 2) || (first_time))
922  {
923  theta = center_theta + (i - 2.0)*angle_step;
924  cos_theta = cos(theta);
925  sin_theta = sin(theta);
926  min_x = rotatedPolygon.theVertexList[0].x;
927  min_y = rotatedPolygon.theVertexList[0].y;
928  max_x = min_x;
929  max_y = min_y;
930 
931  //***
932  // Translate polygon to origin and rotate all vertices by current theta:
933  //***
934  for (unsigned int vertex=1; vertex < theVertexList.size(); vertex++)
935  {
936  xlatedVertex.x = theVertexList[vertex].x - theVertexList[0].x;
937  xlatedVertex.y = theVertexList[vertex].y - theVertexList[0].y;
938  rotatedVertex.x = cos_theta*xlatedVertex.x + sin_theta*xlatedVertex.y;
939  rotatedVertex.y = cos_theta*xlatedVertex.y - sin_theta*xlatedVertex.x;
940  rotatedPolygon.theVertexList[vertex] = rotatedVertex;
941 
942  //***
943  // Latch max and mins of bounding rect:
944  //***
945  if (min_x > rotatedVertex.x) min_x = rotatedVertex.x;
946  if (min_y > rotatedVertex.y) min_y = rotatedVertex.y;
947  if (max_x < rotatedVertex.x) max_x = rotatedVertex.x;
948  if (max_y < rotatedVertex.y) max_y = rotatedVertex.y;
949  }
950 
951  if (TESTING)
952  {
953  ossimDpt v1 (cos_theta*min_x - sin_theta*max_y + theVertexList[0].x,
954  cos_theta*max_y + sin_theta*min_x + theVertexList[0].y);
955  ossimDpt v2 (cos_theta*max_x - sin_theta*max_y + theVertexList[0].x,
956  cos_theta*max_y + sin_theta*max_x + theVertexList[0].y);
957  ossimDpt v3 (cos_theta*max_x - sin_theta*min_y + theVertexList[0].x,
958  cos_theta*min_y + sin_theta*max_x + theVertexList[0].y);
959  ossimDpt v4 (cos_theta*min_x - sin_theta*min_y + theVertexList[0].x,
960  cos_theta*min_y + sin_theta*min_x + theVertexList[0].y);
961  cout << v1.x << "\t" << v1.y << endl;
962  cout << v2.x << "\t" << v2.y << endl;
963  cout << v3.x << "\t" << v3.y << endl;
964  cout << v4.x << "\t" << v4.y << endl << endl;
965  }
966 
967  //***
968  // Establish bounding rect and area about rotated polygon:
969  //***
970  area = (max_x - min_x) * (max_y - min_y);
971  if (area < min_area)
972  {
973  best_theta = theta;
974  min_area = area;
975  best_rect = ossimDrect(min_x, max_y, max_x, min_y, OSSIM_RIGHT_HANDED);
976  }
977  } // end if (i != 2 || first_time)
978  } // end for-loop over surrounding rotations
979 
980  //***
981  // Adjust step size by half to repeat process:
982  //***
983  angle_step /= 2.0;
984  first_time = false;
985 
986  } // end while loop for convergence
987 
988  //***
989  // best_theta now contains optimum rotation of bounding rect. Need to apply reverse
990  // rotation and translation of best_rect:
991  //***
992  cos_theta = cos(best_theta);
993  sin_theta = sin(best_theta);
994  ossimDpt v1 (cos_theta*best_rect.ul().x - sin_theta*best_rect.ul().y + theVertexList[0].x,
995  cos_theta*best_rect.ul().y + sin_theta*best_rect.ul().x + theVertexList[0].y);
996  ossimDpt v2 (cos_theta*best_rect.ur().x - sin_theta*best_rect.ur().y + theVertexList[0].x,
997  cos_theta*best_rect.ur().y + sin_theta*best_rect.ur().x + theVertexList[0].y);
998  ossimDpt v3 (cos_theta*best_rect.lr().x - sin_theta*best_rect.lr().y + theVertexList[0].x,
999  cos_theta*best_rect.lr().y + sin_theta*best_rect.lr().x + theVertexList[0].y);
1000  ossimDpt v4 (cos_theta*best_rect.ll().x - sin_theta*best_rect.ll().y + theVertexList[0].x,
1001  cos_theta*best_rect.ll().y + sin_theta*best_rect.ll().x + theVertexList[0].y);
1002 
1003  if (TESTING)
1004  {
1005  cout << v1.x << "\t" << v1.y << endl;
1006  cout << v2.x << "\t" << v2.y << endl;
1007  cout << v3.x << "\t" << v3.y << endl;
1008  cout << v4.x << "\t" << v4.y << endl << endl;
1009  }
1010 
1011  //***
1012  // Assign return value rect:
1013  //***
1014  minRect.clear();
1015  minRect.addPoint(v1);
1016  minRect.addPoint(v2);
1017  minRect.addPoint(v3);
1018  minRect.addPoint(v4);
1019 
1020  // Make sure we are always returning a positive clockwise area.
1021  minRect.checkOrdering();
1023  minRect.reverseOrder();
1024  return;
1025 }
1026 
1032 {
1033  int numvertices=getNumberOfVertices();
1034  if(vertex>numvertices) {
1035  return;
1036  } else {
1037  vector<ossimDpt>::iterator it;
1038  int v=0;
1039  for(it=theVertexList.begin();it!=theVertexList.end();it++) {
1040  if(v++==vertex) {
1041  theVertexList.erase(it);
1042  break;
1043  }
1044  }
1045  }
1046 }
1047 
1053 {
1054  unsigned int numvertices=getNumberOfVertices();
1055  if (!numvertices)
1056  return;
1057 
1058  int smallest_vertex=-1,n1,n2;
1059  double smallest_area=1.0/DBL_EPSILON;
1060  ossimPolygon tmp;
1061 
1062  for(unsigned int v=0;v<numvertices;v++) {
1063  tmp.clear();
1064  if(v==0) {
1065  n1=numvertices-1;
1066  n2=1;
1067  } else if(v==numvertices-1) {
1068  n1=numvertices-2;
1069  n2=0;
1070  } else {
1071  n1=v-1;
1072  n2=v+1;
1073  }
1074 
1075  tmp.addPoint(theVertexList[n1]);
1076  tmp.addPoint(theVertexList[v]);
1077  tmp.addPoint(theVertexList[n2]);
1078 
1079  if(fabs(tmp.area())<smallest_area) {
1080  smallest_area=fabs(tmp.area());
1081  smallest_vertex=v;
1082  }
1083  }
1084  removeVertex(smallest_vertex);
1085 }
1086 
1087 
1089 {
1090  return theVertexList[index];
1091 }
1092 
1093 const ossimDpt& ossimPolygon::operator[](int index)const
1094 {
1095  return theVertexList[index];
1096 }
1097 
1099 {
1100  return getNumberOfVertices();
1101 }
1102 
1104 {
1105  return (ossim_uint32)theVertexList.size();
1106 }
1107 
1109 {
1110  ossim_int32 minX;
1111  ossim_int32 minY;
1112  ossim_int32 maxX;
1113  ossim_int32 maxY;
1114  getIntegerBounds(minX, minY, maxX, maxY);
1115  rect = ossimIrect(minX, minY, maxX, maxY);
1116 }
1117 
1119 {
1120  ossim_float64 minX;
1121  ossim_float64 minY;
1122  ossim_float64 maxX;
1123  ossim_float64 maxY;
1124  getFloatBounds(minX, minY, maxX, maxY);
1125  rect = ossimDrect(minX, minY, maxX, maxY);
1126 }
1127 
1129 {
1130  theVertexList.clear();
1132 }
1133 
1135 {
1136  theVertexList.push_back(pt);
1138 }
1139 
1140 void ossimPolygon::addPoint(double x, double y)
1141 {
1142  theVertexList.push_back(ossimDpt(x, y));
1144 }
1145 
1146 const vector<ossimDpt>& ossimPolygon::getVertexList()const
1147 {
1148  return theVertexList;
1149 }
1150 
1151  bool ossimPolygon::pointWithin(const ossimDpt& point) const
1152 {
1153  return isPointWithin(point);
1154 }
1155 
1157 {
1158  return ((*this)*=ossimDpt(scale, scale));
1159 }
1160 
1162 {
1163  return ((*this)*ossimDpt(scale, scale));
1164 }
1165 
1167 {
1168  theVertexList.resize(newSize);
1170  theCurrentVertex = 0;
1171 }
1172 
1174 {
1175  return theOrderingType;
1176 }
1177 
1178 bool ossimPolygon::operator!=(const ossimPolygon& compare_this) const
1179 {
1180  return !(*this == compare_this);
1181 }
1182 
1184 {
1185  polygon.print(os);
1186  return os;
1187 }
1188 
1195 {
1196  int numpts = (int)theVertexList.size();
1197  unsigned int next;
1198  double area=0,parea;
1199 
1200  centroid=ossimDpt(0,0);
1201  for(int i=0;i<numpts;i++) {
1202  if(i<numpts-1) {
1203  next=i+1;
1204  } else {
1205  next=0;
1206  }
1207  parea=theVertexList[i].x*theVertexList[next].y-theVertexList[next].x*theVertexList[i].y;
1208  area+=parea;
1209  centroid.x+=(theVertexList[i].x+theVertexList[next].x)*parea;
1210  centroid.y+=(theVertexList[i].y+theVertexList[next].y)*parea;
1211  }
1212  area=area/2.0;
1213  centroid=centroid/(area*6.0);
1214 }
1215 
1222 void ossimPolygon::fitCircleInsideVertex(ossimDpt &destPt, unsigned int vertex, double radius) const
1223 {
1224  ossim_uint32 num_vertices=(int)theVertexList.size(),n1,n2;
1225  ossimDpt side1,side2,bisection,currpt;
1226  double length_out,side1_side2_cross;
1227  bool concave=true;
1228 
1229  // don't be doing that dude.
1230  if(num_vertices<3 || vertex>=num_vertices) {
1231  destPt=ossimDpt(0,0);
1232  return;
1233  }
1234 
1235  if(vertex==0) {
1236  n1=num_vertices-1;
1237  n2=vertex+1;
1238  } else if(vertex==num_vertices-1) {
1239  n1=num_vertices-2;
1240  n2=0;
1241  } else {
1242  n1=vertex-1;
1243  n2=vertex+1;
1244  }
1245 
1246  currpt=theVertexList[vertex];
1247  // get the side vectors
1248  side1=theVertexList[n1]-currpt;
1249  side2=theVertexList[n2]-currpt;
1250 
1251  // normalize the sides
1252  side1 = side1/side1.length();
1253  side2 = side2/side2.length();
1254 
1255  side1_side2_cross=side1.x*side2.y-side2.x*side1.y;
1256 
1257  checkOrdering();
1259  if(side1_side2_cross<0)
1260  concave=false;
1261  } else { //clockwise
1262  if(side1_side2_cross>0)
1263  concave=false;
1264  }
1265 
1266  bisection = side1+side2;
1267  bisection = bisection/bisection.length();
1268 
1269  if(concave) {
1270  bisection=bisection*-1.0;
1271  length_out=radius;
1272  } else {
1273  double cos_theta=(side1.x*bisection.x+side1.y*bisection.y);
1274  length_out=radius/sqrt(1-cos_theta*cos_theta);
1275  }
1276  destPt=ossimDpt(currpt+bisection*length_out);
1277  return;
1278 }
1279 
1280 
1285 
1286 bool ossimPolygon::shrink(ossimPolygon &dest, double inset) const
1287 {
1288  int numpts = (int) theVertexList.size();
1289  ossimDpt pt;
1290 
1291  //don't let people shrink themselves, that isn't going to work
1292  if (&dest==this)
1293  return false;
1294 
1295  dest.clear();
1296  for(int i=0;i<numpts;i++)
1297  {
1298  fitCircleInsideVertex(pt,i,inset);
1299  dest.addPoint(pt);
1300  }
1301  if(isPolyWithin(dest))
1302  {
1303  return true;
1304  } else
1305  {
1306  //return an empty polygon
1307  dest=ossimPolygon();
1308  return false;
1309  }
1310 }
1311 
1312 
1313 
ossimDpt midPoint() const
ossim_uint32 x
ossimDpt theP1
Definition: ossimLine.h:77
ossimDpt & operator[](int index)
Represents serializable keyword/value map.
ossim_uint32 y
bool nextVertex(ossimDpt &tbd_vertex) const
METHOD: nextVertex() Assigns the ossimDpt tbd_vertex following the current vertex.
const char * find(const char *key) const
bool operator==(const ossimPolygon &compare_this) const
void removeSmallestContributingVertex()
METHOD: removeSmallestContributingVertex() Removes the vertex that contributes the smallest area to t...
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
const ossimDpt & ul() const
Definition: ossimDrect.h:339
void addPoint(const ossimDpt &pt)
double y
Definition: ossimDpt.h:165
void getFloatBounds(ossim_float64 &minX, ossim_float64 &minY, ossim_float64 &maxX, ossim_float64 &maxY) const
static ossimString toString(bool aValue)
Numeric to string methods.
bool shrink(ossimPolygon &dest, double inset) const
METHOD: shrink() Shrinks the current polygon by inset, return true if success.
#define OSSIM_INT_NAN
const ossimIpt & ul() const
Definition: ossimIrect.h:274
bool isRectWithin(const ossimIrect &rect) const
METHOD: isRectWithin() Returns true if all the corner points of the given rect fit within...
ossimVertexOrdering checkOrdering() const
ossimVertexOrdering getOrdering() const
void removeVertex(int vertex)
METHOD: remove() Removes the vertex from the polygon.
bool clipLineSegment(ossimDpt &p1, ossimDpt &p2) const
METHOD: clipLineSegment(p1, p2) Implements Cyrus-Beck clipping algorithm as described in: http://www...
const ossimIpt & ll() const
Definition: ossimIrect.h:277
bool isPolyWithin(const ossimPolygon &poly) const
METHOD: isPolyWithin() Returns true if all the vertices of the given polygon fit within.
bool vertex(int index, ossimDpt &tbd_vertex) const
METHOD: vertex(index) Returns the ossimDpt vertex given the index.
static const char * TYPE_KW
double length() const
Definition: ossimDpt.h:81
void getCentroid(ossimDpt &centroid) const
METHOD: getCentroid() Assigns the ossimDpt centroid the polygon.
ossimCoordSysOrientMode orientMode() const
Definition: ossimDrect.h:414
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
void getIntegerBounds(ossim_int32 &minX, ossim_int32 &minY, ossim_int32 &maxX, ossim_int32 &maxY) const
ossimDpt intersectInfinite(const ossimLine &line) const
Definition: ossimLine.cpp:20
ossimDpt normal() const
Definition: ossimLine.cpp:135
#define M_PI
ossimVertexOrdering
yy_size_t size
ossim_uint32 getVertexCount() const
bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
bool operator!=(const ossimPolygon &compare_this) const
bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
unsigned int ossim_uint32
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
void print(ostream &os) const
METHOD: print()
bool hasNans() const
will sequence through the polygon and check to see if any values are NAN
void intersectEdge(ossimDpt &result, const ossimLine &segment, const ossimDrect &rect, int edge)
ossimDpt theP2
Definition: ossimLine.h:78
const ossimIpt & lr() const
Definition: ossimIrect.h:276
bool rectIntersects(const ossimIrect &rect) const
METHOD: rectIntersects() Returns true if at least one corner points of the given rect is within...
#define DBL_EPSILON
bool pointWithin(const ossimDpt &point) const
METHOD: pointWithin(ossimDpt) Returns TRUE if point is inside polygon.
void reverseOrder()
void roundToIntegerBounds(bool compress=false)
const ossimIpt & ur() const
Definition: ossimIrect.h:275
void getBoundingRect(ossimIrect &rect) const
bool clipToRect(vector< ossimPolygon > &result, const ossimDrect &rect) const
Uses the ossimPolyArea2d class for the intersection.
const vector< ossimDpt > & getVertexList() const
ossim_uint32 getNumberOfVertices() const
long toLong() const
toLong&#39;s deprecated, please use the toInts...
#define max(a, b)
Definition: auxiliary.h:76
bool isPointWithin(const ossimDpt &point) const
const ossimDpt & ur() const
Definition: ossimDrect.h:340
double area() const
Returns polygon area. Negative indicates CW ordering of vertices (in right-handed coordinates) ...
ossim_int32 theCurrentVertex
Definition: ossimPolygon.h:251
double x
Definition: ossimDpt.h:164
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
void fitCircleInsideVertex(ossimDpt &destPt, unsigned int vertex, double radius) const
Assigns destPt the point that fits a circle of given radius inside the polygon vertex.
const ossimDpt & ll() const
Definition: ossimDrect.h:342
vector< ossimDpt > theVertexList
Definition: ossimPolygon.h:250
std::basic_istringstream< char > istringstream
Class for char input memory streams.
Definition: ossimIosFwd.h:32
void getMinimumBoundingRect(ossimPolygon &minRect) const
Initializes minRect with the minimum area rect (not-necessarily aligned with axes) that bounds this p...
const ossimPolygon & operator*=(const ossimDpt &scale)
void resize(ossim_uint32 newSize)
ossimVertexOrdering theOrderingType
Definition: ossimPolygon.h:249
const ossimDpt & lr() const
Definition: ossimDrect.h:341
bool isInsideEdge(const ossimDpt &pt, const ossimDrect &rect, int edge) const
bool getVisiblePolygons(vector< ossimPolygon > &polyList) const
void makeNan()
Definition: ossimDpt.h:65
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
ostream & operator<<(ostream &os, const ossimPolygon &polygon)
ossimPolygon operator*(const ossimDpt &scale) const
#define min(a, b)
Definition: auxiliary.h:75
int ossim_int32
const ossimPolygon & operator=(const ossimPolygon &copy_this)
OPERATORS: (Some are inlined at bottom)
const std::string & string() const
Definition: ossimString.h:414