OpendTect-6_4  6.4
polygon.h
Go to the documentation of this file.
1 #ifndef polygon_h
2 #define polygon_h
3 
4 /*+
5 ________________________________________________________________________
6 
7  (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
8  Author: J.C. Glas
9  Date: Dec 2006
10  RCS: $Id$
11 ________________________________________________________________________
12 
13 -*/
14 
15 #include "coord.h"
16 #include "typeset.h"
17 #include "iopar.h"
18 #include "bufstring.h"
19 #include "bendpointfinder.h"
20 #include <math.h>
21 
26 template <class T>
28 {
29 public:
31  : closed_(true), udf_(Geom::Point2D<T>::udf())
32  , xrg_(mUdf(T),mUdf(T)), yrg_(mUdf(T),mUdf(T)) {}
33 
35  : poly_(plg), closed_(true)
36  , udf_(Geom::Point2D<T>::udf())
37  , xrg_(mUdf(T),mUdf(T)), yrg_(mUdf(T),mUdf(T)) {}
38 
39  void erase();
40  bool isEmpty() const { return poly_.isEmpty(); }
41 
42  int size() const { return poly_.size(); }
43  bool validIdx(int idx) const { return poly_.validIdx(idx); }
44  void setEmpty() { erase(); }
45 
46  void add(const Geom::Point2D<T>& vtx);
47  void remove(int idx);
48  void insert(int idx,const Geom::Point2D<T>& vtx);
49 
50  bool isInside(const Geom::Point2D<T>&,
51  bool inclborder,T eps) const;
52 
53  int isInside(const ODPolygon& testpoly,T eps=0) const;
54  /* 0: testpoly fully outside (borders don't touch)
55  2: testpoly fully inside (borders don't touch)
56  1: all intermediate cases */
57 
58  bool segmentMeetsBorder(const Geom::Point2D<T>& pt1,
59  const Geom::Point2D<T>& pt2,T eps) const;
60  bool windowOverlaps(const Interval<T>& xrange,
61  const Interval<T>& yrange,T eps) const;
62 
63  // defined for closed polygon
64  const Geom::Point2D<T>& getVertex(int idx) const;
65  const Geom::Point2D<T>& nextVertex(int idx) const;
66  const Geom::Point2D<T>& prevVertex(int idx) const;
67 
68  void setClosed( bool yn ) { closed_ = yn; }
69  bool isClosed() const { return closed_; }
70  void setUdf( Geom::Point2D<T> pt ) { udf_ = pt; }
71  Geom::Point2D<T> getUdf() const { return udf_; }
72  const TypeSet<Geom::Point2D<T> >& data() const { return poly_; }
73 
74  Interval<T> getRange(bool of_x) const;
75  void getData(bool of_x,TypeSet<T>&) const;
76 
77  void removeZeroLengths();
78  bool isUTurn(int idx) const;
79  bool isSelfIntersecting() const;
80 
81  void convexHull();
82  void keepBendPoints(float eps);
83 
84  // not for self-intersecting polygons
85  double area() const { return fabs(sgnArea2<double>()/2.0); }
86  bool clockwise() const { return sgnArea2<T>()<0; }
87  bool anticlockwise() const { return sgnArea2<T>()>0; }
88 
89  void reverse();
90 
91  double distTo(const Geom::Point2D<T>& refpt,int* segmentidxptr=0,
92  double* fractionptr=0) const;
93 
94  double maxDistToBorderEstimate(double maxrelerr=0.001) const;
95 
96  bool operator==(const ODPolygon<T>&) const;
97  bool operator>( const ODPolygon<T>& plg ) const
98  { return poly_.size()>plg.size(); }
99 
100 protected:
101 
102  static int doSegmentsMeet( const Geom::Point2D<T>& p1,
103  const Geom::Point2D<T>& p2,
104  const Geom::Point2D<T>& q1,
105  const Geom::Point2D<T>& q2,
106  T eps );
107 
108  static bool isOnSegment( const Geom::Point2D<T>& pt,
109  const Geom::Point2D<T>& pt0,
110  const Geom::Point2D<T>& pt1,
111  T eps );
112  static bool isOnHalfLine( const Geom::Point2D<T>& point,
113  const Geom::Point2D<T>& dirvec,
114  const Geom::Point2D<T>& endvec,
115  T eps );
116 
117  static bool isEdgeCrossing( const Geom::Point2D<T>& raydir,
118  const Geom::Point2D<T>& raysrc,
119  const Geom::Point2D<T>& vtx1,
120  const Geom::Point2D<T>& vtx2 );
121 
122  static bool isOnLine( const Geom::Point2D<T>& point,
123  const Geom::Point2D<T>& dirvec,
124  const Geom::Point2D<T>& posvec,
125  T eps );
126 
127  static bool isRightOfLine( const Geom::Point2D<T>& point,
128  const Geom::Point2D<T>& dirvec,
129  const Geom::Point2D<T>& posvec );
130 
131  static bool doCoincide( const Geom::Point2D<T>& point1,
132  const Geom::Point2D<T>& point2,
133  T eps=mDefEps );
134 
135  static double sgnDistToLine( const Geom::Point2D<T>& point,
136  const Geom::Point2D<T>& dirvec,
137  const Geom::Point2D<T>& posvec );
138 
139  template <class ST> ST sgnArea2() const;
140 
141  static double distToSegment( const Geom::Point2D<T>& p1,
142  const Geom::Point2D<T>& p2,
143  const Geom::Point2D<T>& refpt,
144  double* fractionptr=0 );
145 
147  bool closed_;
149 
150  mutable Interval<T> xrg_;
151  mutable Interval<T> yrg_;
152 };
153 
154 
155 template <class T> inline
156 bool ODPolygon<T>::operator==( const ODPolygon<T>& poly ) const
157 {
158  if ( data() != poly.data() ) return false;
159  return true;
160 }
161 
162 
163 template <class T> inline
164 void ODPolygon<T>::getData( bool forx, TypeSet<T>& ts ) const
165 {
166  for ( int idx=0; idx<size(); idx++ )
167  {
168  const Geom::Point2D<T>& vtx = poly_[idx];
169  ts += forx ? vtx.x : vtx.y;
170  }
171 }
172 
173 
174 template <class T> inline
175 void fillPar( IOPar& iop, const ODPolygon<T>& poly, const char* inpkey )
176 {
177  const BufferString keywd( inpkey ); const char* key = keywd.buf();
178  iop.setYN( IOPar::compKey(key,"Closed"), poly.isClosed() );
179  iop.set( IOPar::compKey(key,"Undef"), poly.getUdf().x, poly.getUdf().y );
180  TypeSet<T> ts; poly.getData( true, ts );
181  iop.set( IOPar::compKey(key,"Data.X"), ts );
182  ts.erase(); poly.getData( false, ts );
183  iop.set( IOPar::compKey(key,"Data.Y"), ts );
184 }
185 
186 
187 template <class T> inline
188 void usePar( const IOPar& iop, ODPolygon<T>& poly, const char* inpkey )
189 {
190  const BufferString keywd( inpkey ); const char* key = keywd.buf();
191  bool yn = false; iop.getYN( IOPar::compKey(key,"Closed"), yn );
192  poly.setClosed( yn );
193  Geom::Point2D<T> pt; iop.get( IOPar::compKey(key,"Undef"), pt.x, pt.y );
194  poly.setUdf( pt );
195 
196  if ( !iop.find( IOPar::compKey(key,"Data.X") )
197  || !iop.find( IOPar::compKey(key,"Data.Y") ) )
198  return;
199 
200  poly.setEmpty(); TypeSet<T> tsx, tsy;
201  iop.get( IOPar::compKey(key,"Data.X"), tsx );
202  iop.get( IOPar::compKey(key,"Data.Y"), tsy );
203  const int sz = tsx.size() > tsy.size() ? tsy.size() : tsx.size();
204  for ( int idx=0; idx<sz; idx++ )
205  poly.add( Geom::Point2D<T>(tsx[idx],tsy[idx]) );
206 }
207 
208 
209 template <class T> inline
210 void ODPolygon<T>::insert( int idx, const Geom::Point2D<T>& vtx )
211 {
212  if ( idx>=0 && idx<=size() )
213  poly_.insert( idx, vtx );
214  xrg_.set( mUdf(T), mUdf(T) );
215  yrg_.set( mUdf(T), mUdf(T) );
216 }
217 
218 
219 template <class T> inline
221 {
222  poly_.erase();
223  xrg_.set( mUdf(T), mUdf(T) );
224  yrg_.set( mUdf(T), mUdf(T) );
225 }
226 
227 
228 template <class T> inline
230 {
231  poly_+=vtx;
232  xrg_.set( mUdf(T), mUdf(T) );
233  yrg_.set( mUdf(T), mUdf(T) );
234 }
235 
236 
237 template <class T> inline
238 void ODPolygon<T>::remove( int idx )
239 {
240  if ( poly_.validIdx(idx) )
241  poly_.removeSingle( idx );
242  xrg_.set( mUdf(T), mUdf(T) );
243  yrg_.set( mUdf(T), mUdf(T) );
244 }
245 
246 
247 template <class T> inline
249 { return poly_.validIdx(idx) ? poly_[idx] : udf_; }
250 
251 
252 template <class T> inline
254 { return getVertex( idx+1<size() ? idx+1 : 0 ); }
255 
256 
257 template <class T> inline
259 { return getVertex( idx ? idx-1 : size()-1 ); }
260 
261 
262 template <class T> inline
264 {
265  if ( poly_.isEmpty() ) return Interval<T>( udf_.x, udf_.y );
266  Geom::Point2D<T> vtx0 = poly_[0];
267  Interval<T> ret = forx ? xrg_ : yrg_;
268  if ( !mIsUdf(ret.start) && !mIsUdf(ret.stop) )
269  return ret;
270  ret.start = ret.stop = forx ? vtx0.x : vtx0.y;
271  for ( int idx=1; idx<size(); idx++ )
272  {
273  const Geom::Point2D<T>& vtx = poly_[idx];
274  const T val = forx ? vtx.x : vtx.y;
275  if ( val < ret.start ) ret.start = val;
276  else if ( val > ret.stop ) ret.stop = val;
277  }
278  if ( forx )
279  xrg_ = ret;
280  else
281  yrg_ = ret;
282  return ret;
283 }
284 
285 
286 template <class T> inline
288  bool inclborder, T eps ) const
289 {
290  const T abseps = eps<0 ? -eps : eps;
291  if ( (!mIsUdf(xrg_.start) && !mIsUdf(xrg_.stop) &&
292  (xrg_.start>point.x+abseps || xrg_.stop<point.x-abseps)) ||
293  (!mIsUdf(yrg_.start) && !mIsUdf(yrg_.stop) &&
294  (yrg_.start>point.y+abseps || yrg_.stop<point.y-abseps)) )
295  return false;
296 
297  const Geom::Point2D<T> arbitrarydir( 1, 0 );
298 
299  bool nrcrossingsodd = false;
300  for ( int idx=0; idx<size(); idx++ )
301  {
302  const Geom::Point2D<T>& vtxcurr = poly_[idx];
303  const Geom::Point2D<T>& vtxnext = nextVertex( idx );
304 
305  if ( isOnSegment(point, vtxcurr, vtxnext, eps) )
306  return inclborder;
307  if ( isEdgeCrossing(arbitrarydir, point, vtxcurr, vtxnext) )
308  nrcrossingsodd = !nrcrossingsodd;
309  }
310 
311  return nrcrossingsodd;
312 }
313 
314 
315 template <class T> inline
317  const Geom::Point2D<T>& pt2,
318  T eps ) const
319 {
320  for ( int idx=0; idx<size(); idx++ )
321  {
322  const Geom::Point2D<T>& vtxcurr = poly_[idx];
323  const Geom::Point2D<T>& vtxnext = nextVertex( idx );
324 
325  if ( doSegmentsMeet(pt1, pt2, vtxcurr, vtxnext, eps) )
326  return true;
327  }
328 
329  return false;
330 }
331 
332 
333 template <class T> inline
335  const Interval<T>& yrange,
336  T eps ) const
337 {
338  ODPolygon window;
339  window.add( Geom::Point2D<T>(xrange.start, yrange.start) );
340  window.add( Geom::Point2D<T>(xrange.stop, yrange.start) );
341  window.add( Geom::Point2D<T>(xrange.stop, yrange.stop) );
342  window.add( Geom::Point2D<T>( xrange.start, yrange.stop) );
343 
344  return isInside( window, eps );
345 }
346 
347 
348 template <class T> inline
349 int ODPolygon<T>::isInside( const ODPolygon& testpoly, T eps ) const
350 {
351  if ( isEmpty() || testpoly.isEmpty() )
352  return 0;
353 
354  for ( int idx=0; idx<size(); idx++ )
355  {
356  const Geom::Point2D<T>& vtxcurr = poly_[idx];
357  const Geom::Point2D<T>& vtxnext = nextVertex( idx );
358 
359  if ( testpoly.segmentMeetsBorder(vtxcurr, vtxnext, eps) )
360  return 1;
361  }
362 
363  if ( isInside(testpoly.poly_[0], false, eps) )
364  return 2;
365 
366  return testpoly.isInside(poly_[0], false, eps) ? 1 : 0;
367 }
368 
369 
370 template <class T> inline
372 {
373  const int startidx = isClosed() ? size()-1 : size()-2;
374  for ( int idx=startidx; idx>=0; idx-- )
375  {
376  if ( poly_[idx]==nextVertex(idx) && size()>1 )
377  remove(idx);
378  }
379 }
380 
381 
382 template <class T> inline
383 bool ODPolygon<T>::isUTurn( int idx ) const
384 {
385  if ( !validIdx(idx) || ( !isClosed() && (idx==0 || idx==size()-1) ) )
386  return false;
387 
388  const Geom::Point2D<T>& vec1 = prevVertex(idx) - poly_[idx];
389  const Geom::Point2D<T>& vec2 = nextVertex(idx) - poly_[idx];
390 
391  return vec1.x*vec2.y-vec1.y*vec2.x==0 && vec1.x*vec2.x+vec1.y*vec2.y>0;
392 }
393 
394 
395 template <class T> inline
397 {
398  ODPolygon<T> plg = *this;
399  plg.removeZeroLengths();
400 
401  const int stopidx = plg.isClosed() ? plg.size() : plg.size()-1;
402  for ( int idx=0; idx<stopidx; idx++ )
403  {
404  if ( plg.isUTurn(idx) )
405  return true;
406 
407  const Geom::Point2D<T>& vtxcurr = plg.poly_[idx];
408  const Geom::Point2D<T>& vtxnext = plg.nextVertex( idx );
409 
410  for ( int idy=0; idy<stopidx; idy++ )
411  {
412  const int dif = abs( idx-idy );
413  if ( dif<=1 || dif>=plg.size()-1 )
414  continue;
415 
416  const Geom::Point2D<T>& pt1 = plg.poly_[idy];
417  const Geom::Point2D<T>& pt2 = plg.nextVertex( idy );
418 
419  if ( vtxcurr==pt1 || vtxcurr==pt2 )
420  return true;
421 
422  if ( isEdgeCrossing(vtxnext-vtxcurr, vtxcurr, pt1, pt2) &&
423  isEdgeCrossing(vtxcurr-vtxnext, vtxnext, pt1, pt2) )
424  return true;
425  }
426  }
427  return false;
428 }
429 
430 
431 template <class T> inline
433  const Geom::Point2D<T>& p2,
434  const Geom::Point2D<T>& q1,
435  const Geom::Point2D<T>& q2,
436  T eps )
437 {
438  if ( isOnSegment(p1, q1, q2, eps) || isOnSegment(p2, q1, q2, eps) ||
439  isOnSegment(q1, p1, p2, eps) || isOnSegment(q2, p1, p2, eps) )
440  return 1;
441 
442  if ( p1==p2 || q1==q2 || !isEdgeCrossing(p2-p1, p1, q1, q2) ||
443  !isEdgeCrossing(p1-p2, p2, q1, q2) )
444  return 0;
445 
446  return 2;
447 }
448 
449 
450 template <class T> inline
452  const Geom::Point2D<T>& pt0,
453  const Geom::Point2D<T>& pt1,
454  T eps )
455 {
456  return isOnHalfLine( pt, pt1-pt0, pt0, eps ) &&
457  isOnHalfLine( pt, pt0-pt1, pt1, eps );
458 }
459 
460 
461 template <class T> inline
463  const Geom::Point2D<T>& dirvec,
464  const Geom::Point2D<T>& endvec,
465  T eps )
466 {
467  if ( doCoincide(point, endvec, eps) )
468  return true;
469  if ( !isOnLine(point, dirvec, endvec, eps) )
470  return false;
471  const Geom::Point2D<T> rot90dirvec( -dirvec.y, dirvec.x );
472  return isRightOfLine( point, rot90dirvec, endvec );
473 }
474 
475 
476 template <class T> inline
478  const Geom::Point2D<T>& raysrc,
479  const Geom::Point2D<T>& vtx1,
480  const Geom::Point2D<T>& vtx2 )
481 {
482  const bool vtx1right = isRightOfLine( vtx1, raydir, raysrc );
483  const bool vtx2right = isRightOfLine( vtx2, raydir, raysrc );
484 
485  if ( vtx1right && !vtx2right )
486  return !isRightOfLine( raysrc, vtx2-vtx1, vtx1 );
487  if ( !vtx1right && vtx2right )
488  return !isRightOfLine( raysrc, vtx1-vtx2, vtx2 );
489  return false;
490 }
491 
492 
493 template <class T> inline
495  const Geom::Point2D<T>& dirvec,
496  const Geom::Point2D<T>& posvec,
497  T eps )
498 {
499  const double signeddist = sgnDistToLine( point, dirvec, posvec );
500  return signeddist * signeddist <= eps * eps;
501 }
502 
503 template <class T> inline
505  const Geom::Point2D<T>& dirvec,
506  const Geom::Point2D<T>& posvec )
507 {
508  return sgnDistToLine( point, dirvec, posvec ) > 0;
509 }
510 
511 
512 template <class T> inline
514  const Geom::Point2D<T>& point2,
515  T eps )
516 {
517  return point1.sqDistTo( point2 ) <= eps * eps;
518 }
519 
520 
521 template <class T> inline
523  const Geom::Point2D<T>& dirvec,
524  const Geom::Point2D<T>& posvec )
525 {
526  const double nolinedist = 0;
527 
528  const double dirveclen = dirvec.distTo( Geom::Point2D<T>(0,0) );
529  if ( mIsZero(dirveclen, mDefEps) )
530  return nolinedist;
531  const double substpointinlineeqn =
532  dirvec.y * ( point.x - posvec.x )-dirvec.x * ( point.y - posvec.y );
533  return substpointinlineeqn / dirveclen;
534 }
535 
536 
537 template <class T>
538 template <class ST> inline
540 {
541  ST area2 = 0;
542 
543  const Geom::Point2D<T>& pt0 = poly_[0];
544  for ( int idx=1; idx<size()-1; idx++ )
545  {
546  const Geom::Point2D<T>& pt1 = poly_[idx];
547  const Geom::Point2D<T>& pt2 = nextVertex( idx );
548  area2 += (ST) ( (pt1.x-pt0.x) * (pt2.y-pt0.y) -
549  (pt2.x-pt0.x) * (pt1.y-pt0.y) );
550  }
551 
552  return area2;
553 }
554 
555 
556 template <class T> inline
558 {
559  // Code based on the Graham scan algorithm (1972)
560 
561  setClosed( true );
562  if ( size()<2 )
563  return;
564 
565  // Find guaranteed vertex of the convex hull to become pivot
566  Geom::Point2D<T> pivot = poly_[0];
567  for ( int idx=1; idx<size(); idx++ )
568  {
569  const Geom::Point2D<T>& vtx = poly_[idx];
570  if ( vtx.x<pivot.x || (vtx.x==pivot.x && vtx.y<pivot.y) )
571  pivot = vtx;
572  }
573 
574  // Remove all pivot copies
575  for ( int idx=size()-1; idx>=0; idx-- )
576  {
577  if ( pivot == poly_[idx] )
578  //poly_.removeSingle( idx, false );
579  poly_.removeSingle( idx );
580  }
581 
582  // Angular sort of all pivot-to-point segments
583  for ( int idx=size()-2; idx>=0; idx-- )
584  {
585  const Geom::Point2D<T>& vtx = poly_[idx];
586  for ( int idy=size()-1; idy>idx; idy-- )
587  {
588  const Geom::Point2D<T>& vty = poly_[idy];
589  const double dist = sgnDistToLine( vty, vtx-pivot, pivot );
590 
591  if ( dist > 0 )
592  continue;
593 
594  if ( dist < 0 )
595  poly_.insert( idy+1, vtx );
596  else if ( pivot.sqDistTo(vtx) > pivot.sqDistTo(vty) )
597  poly_[idy] = vtx;
598 
599  poly_.removeSingle( idx );
600  break;
601  }
602  }
603 
604  // Expand convex hull incrementally by backward removal of inner points
605  for ( int idx=size()-3; idx>=0; idx-- )
606  {
607  const Geom::Point2D<T>& vtx = poly_[idx];
608  while ( idx<size()-2 )
609  {
610  const Geom::Point2D<T>& vty = poly_[idx+1];
611  const Geom::Point2D<T>& vtz = poly_[idx+2];
612  if ( isRightOfLine(vtz, vty-vtx, vtx) )
613  break;
614 
615  poly_.removeSingle( idx+1 );
616  }
617  }
618 
619  poly_ += pivot;
620 
621  xrg_.set( mUdf(T), mUdf(T) );
622  yrg_.set( mUdf(T), mUdf(T) );
623 }
624 
625 
626 template <class T> inline
628 {
629  const int sz = poly_.size();
630  for ( int idx=0; idx<sz/2-1; idx++ )
631  {
632  Geom::Point2D<T> temp = poly_[idx];
633  poly_[idx] = poly_[sz-1-idx];
634  poly_[sz-1-idx] = temp;
635  }
636 
637  xrg_.set( mUdf(T), mUdf(T) );
638  yrg_.set( mUdf(T), mUdf(T) );
639 }
640 
641 
642 template <class T> inline
644  const Geom::Point2D<T>& p2,
645  const Geom::Point2D<T>& refpt,
646  double* fractionptr )
647 {
648  double frac = 0;
649 
650  if ( p1 != p2 )
651  {
652  const Geom::Point2D<T> dif = p2 - p1;
653  const double numerator = dif.x*(refpt.x-p1.x) + dif.y*(refpt.y-p1.y);
654  frac = numerator / (dif.x*dif.x + dif.y*dif.y);
655 
656  if ( frac < 0 )
657  frac = 0;
658  if ( frac > 1 )
659  frac = 1;
660  }
661 
662  if ( fractionptr )
663  *fractionptr = frac;
664 
665  const Geom::Point2D<T> pointonseg( (T)(p1.x * (1-frac) + p2.x * frac),
666  (T)(p1.y * (1-frac) + p2.y * frac) );
667  return refpt.distTo( pointonseg );
668 }
669 
670 
671 template <class T> inline
673  int* segmentidxptr, double* fractionptr ) const
674 {
675  const int sz = size();
676  if ( !sz )
677  return mUdf(double);
678 
679  double mindist = MAXDOUBLE;
680 
681  for ( int idx=(isClosed() ? sz-1 : sz-2); idx>=0; idx-- )
682  {
683  const Geom::Point2D<T>& pt1 = getVertex( idx );
684  const Geom::Point2D<T>& pt2 = nextVertex( idx );
685  double frac;
686  const double dist = distToSegment( pt1, pt2, refpt, &frac );
687 
688  if ( mindist >= dist )
689  {
690  mindist = dist;
691  if ( segmentidxptr )
692  *segmentidxptr = idx;
693  if ( fractionptr )
694  *fractionptr = frac;
695  }
696  }
697 
698  return mindist;
699 }
700 
701 
702 template <class T> inline
703 double ODPolygon<T>::maxDistToBorderEstimate( double maxrelerr ) const
704 {
705  if ( maxrelerr <= 0.0 )
706  return mUdf(double);
707 
708  if ( size() < 3 )
709  return isEmpty() ? mUdf(double) : 0.0;
710 
711  const double upperbound = mMIN( 0.5 * getRange(true).width(),
712  0.5 * getRange(false).width() );
713  if ( !upperbound )
714  return 0.0;
715 
716  ODPolygon<double> poly;
717  for ( int idx=0; idx<size(); idx++ )
718  {
719  const Geom::Point2D<T>& pt = getVertex(idx);
720  poly.add( Geom::Point2D<double>(pt.x, pt.y) );
721  }
722 
723  double maxdist = 0.0;
724  for ( int idx=0; idx<poly.size(); idx++ )
725  {
726  Geom::Point2D<double> curpt =
727  (poly.prevVertex(idx)+poly.getVertex(idx)+poly.nextVertex(idx)) / 3;
728 
729  if ( !poly.isInside(curpt, false, mDefEps) )
730  continue;
731 
732  double curdist = poly.distTo( curpt );
733  double gamma = 0.1 * upperbound;
734 
735  for ( int step=0; step<100; step++ )
736  {
737  if ( curdist > maxdist )
738  maxdist = curdist;
739 
740  // Gradient ascent
741  Geom::Point2D<double> pt1 = curpt;
742  Geom::Point2D<double> pt2 = curpt;
743  const double delta = 0.0001 * upperbound;
744  pt1.x += delta;
745  pt2.y += delta;
746  const double dist1 = poly.distTo( pt1 );
747  const double dist2 = poly.distTo( pt2 );
748  Geom::Point2D<double> nextpt( dist1-curdist, dist2-curdist );
749  nextpt *= gamma/delta;
750  nextpt += curpt;
751 
752  if ( !poly.isInside(nextpt, false, mDefEps) )
753  {
754  gamma *= 0.5;
755  continue;
756  }
757 
758  double nextdist = poly.distTo( nextpt );
759 
760  if ( nextdist <= curdist )
761  {
762  gamma *= 0.5;
763 
764  if ( curpt.distTo(nextpt) <= 2*maxrelerr*curdist )
765  break;
766  }
767 
768  curpt = nextpt;
769  curdist = nextdist;
770  }
771  }
772  return maxdist;
773 }
774 
775 
776 template <class T> inline
778 {
779  removeZeroLengths();
780 
781  const int sz = size();
782  if ( sz < 3 )
783  return;
784 
785  const int extra = closed_ ? 1 : 0;
786 
787  TypeSet<Coord> coords;
788  for ( int idx=-extra; idx<sz+extra; idx++ )
789  {
790  const Geom::Point2D<T>& vtx = getVertex( (sz+idx)%sz );
791  coords += Coord( vtx.x, vtx.y );
792  }
793 
794  BendPointFinder2D finder( coords, eps );
795  finder.execute();
796  const TypeSet<int>& bendpoints = finder.bendPoints();
797 
798  int bpidx = bendpoints.size()-extra-1;
799  if ( bpidx<0 )
800  return;
801 
802  for ( int vtxidx=sz-1; vtxidx>=0; vtxidx-- )
803  {
804  if ( bpidx>=0 && vtxidx==bendpoints[bpidx]-extra )
805  bpidx--;
806  else
807  remove( vtxidx );
808  }
809 
810  if ( closed_ && poly_.size()>1 && poly_.first() != poly_.last() )
811  poly_ += poly_.first();
812 }
813 
814 #endif
const Geom::Point2D< T > & getVertex(int idx) const
Definition: polygon.h:248
bool isInside(const Geom::Point2D< T > &, bool inclborder, T eps) const
Definition: polygon.h:287
void remove(int idx)
Definition: polygon.h:238
#define mIsUdf(val)
Use mIsUdf to check for undefinedness of simple types.
Definition: undefval.h:287
void erase()
Definition: polygon.h:220
static bool isEdgeCrossing(const Geom::Point2D< T > &raydir, const Geom::Point2D< T > &raysrc, const Geom::Point2D< T > &vtx1, const Geom::Point2D< T > &vtx2)
Definition: polygon.h:477
void keepBendPoints(float eps)
Definition: polygon.h:777
bool isEmpty() const
Definition: polygon.h:40
bool clockwise() const
Definition: polygon.h:86
bool operator==(const ArrayNDInfo &a1, const ArrayNDInfo &a2)
Definition: arrayndinfo.h:53
const TypeSet< int > & bendPoints() const
Definition: bendpointfinder.h:33
static bool doCoincide(const Geom::Point2D< T > &point1, const Geom::Point2D< T > &point2, T eps=mDefEps)
Definition: polygon.h:513
bool windowOverlaps(const Interval< T > &xrange, const Interval< T > &yrange, T eps) const
Definition: polygon.h:334
Interval< T > getRange(bool of_x) const
Definition: polygon.h:263
#define mIsZero(x, eps)
Definition: commondefs.h:53
bool closed_
Definition: polygon.h:147
void convexHull()
Definition: polygon.h:557
void usePar(const IOPar &iop, ODPolygon< T > &poly, const char *inpkey)
Definition: polygon.h:188
void getData(bool of_x, TypeSet< T > &) const
Definition: polygon.h:164
static bool isOnLine(const Geom::Point2D< T > &point, const Geom::Point2D< T > &dirvec, const Geom::Point2D< T > &posvec, T eps)
Definition: polygon.h:494
Interval< T > yrg_
Definition: polygon.h:151
static bool isRightOfLine(const Geom::Point2D< T > &point, const Geom::Point2D< T > &dirvec, const Geom::Point2D< T > &posvec)
Definition: polygon.h:504
(Closed) sequence of connected 2-D coordinates.
Definition: polygon.h:27
const Geom::Point2D< T > & nextVertex(int idx) const
Definition: polygon.h:253
Used to find bendpoints in set of XY Coordinates.
Definition: bendpointfinder.h:82
TypeSet< Geom::Point2D< T > > poly_
Definition: polygon.h:146
void setUdf(Geom::Point2D< T > pt)
Definition: polygon.h:70
Geom::Point2D< T > udf_
Definition: polygon.h:148
double distTo(const Geom::Point2D< T > &refpt, int *segmentidxptr=0, double *fractionptr=0) const
Definition: polygon.h:672
T sqDistTo(const Point2D< T > &) const
Definition: geometry.h:379
A cartesian coordinate in 2D space.
Definition: coord.h:25
bool get(const char *, int &) const
ODPolygon(const TypeSet< Geom::Point2D< T > > &plg)
Definition: polygon.h:34
double distTo(const Point2D< T > &) const
Definition: geometry.h:374
static const char * compKey(const char *, const char *)
The composite key: (a,b) -> a.b.
void add(const Geom::Point2D< T > &vtx)
Definition: polygon.h:229
void setClosed(bool yn)
Definition: polygon.h:68
#define mMIN(x, y)
Definition: commondefs.h:49
Interval of values.
Definition: commontypes.h:31
double area() const
Definition: polygon.h:85
bool validIdx(int idx) const
Definition: polygon.h:43
bool segmentMeetsBorder(const Geom::Point2D< T > &pt1, const Geom::Point2D< T > &pt2, T eps) const
Definition: polygon.h:316
bool operator>(const ODPolygon< T > &plg) const
Definition: polygon.h:97
Set of (small) copyable elements.
Definition: commontypes.h:30
Generalized set of parameters of the keyword-value type.
Definition: iopar.h:47
#define mUdf(type)
Use this macro to get the undefined for simple types.
Definition: undefval.h:272
T y
Definition: geometry.h:67
bool execute()
Definition: paralleltask.h:71
const char * find(const char *) const
returns null if not found
bool isClosed() const
Definition: polygon.h:69
bool anticlockwise() const
Definition: polygon.h:87
void removeZeroLengths()
Definition: polygon.h:371
void setYN(const char *, bool)
void fillPar(IOPar &iop, const ODPolygon< T > &poly, const char *inpkey)
Definition: polygon.h:175
#define mDefEps
Definition: commondefs.h:58
const char * buf() const
Definition: odstring.h:47
static double distToSegment(const Geom::Point2D< T > &p1, const Geom::Point2D< T > &p2, const Geom::Point2D< T > &refpt, double *fractionptr=0)
Definition: polygon.h:643
static bool isOnSegment(const Geom::Point2D< T > &pt, const Geom::Point2D< T > &pt0, const Geom::Point2D< T > &pt1, T eps)
Definition: polygon.h:451
bool isUTurn(int idx) const
Definition: polygon.h:383
size_type size() const
T stop
Definition: ranges.h:93
OD::String with its own variable length buffer. The buffer has a guaranteed minimum size...
Definition: bufstring.h:40
bool isSelfIntersecting() const
Definition: polygon.h:396
void insert(int idx, const Geom::Point2D< T > &vtx)
Definition: polygon.h:210
T x
Definition: geometry.h:66
int size() const
Definition: polygon.h:42
void reverse()
Definition: polygon.h:627
bool operator==(const ODPolygon< T > &) const
Definition: polygon.h:156
virtual void erase()
const Geom::Point2D< T > & prevVertex(int idx) const
Definition: polygon.h:258
static int doSegmentsMeet(const Geom::Point2D< T > &p1, const Geom::Point2D< T > &p2, const Geom::Point2D< T > &q1, const Geom::Point2D< T > &q2, T eps)
Definition: polygon.h:432
static double sgnDistToLine(const Geom::Point2D< T > &point, const Geom::Point2D< T > &dirvec, const Geom::Point2D< T > &posvec)
Definition: polygon.h:522
T start
Definition: ranges.h:92
Interval< T > xrg_
Definition: polygon.h:150
ODPolygon()
Definition: polygon.h:30
Geom::Point2D< T > getUdf() const
Definition: polygon.h:71
const TypeSet< Geom::Point2D< T > > & data() const
Definition: polygon.h:72
ST sgnArea2() const
Definition: polygon.h:539
#define MAXDOUBLE
Definition: commondefs.h:107
Definition: geometry.h:19
#define mClass(module)
Definition: commondefs.h:164
Basic point class.
Definition: geometry.h:27
bool isEmpty(const NLAModel *mdl)
void set(const char *ky, const char *val)
double maxDistToBorderEstimate(double maxrelerr=0.001) const
Definition: polygon.h:703
void setEmpty()
Definition: polygon.h:44
static bool isOnHalfLine(const Geom::Point2D< T > &point, const Geom::Point2D< T > &dirvec, const Geom::Point2D< T > &endvec, T eps)
Definition: polygon.h:462
bool getYN(const char *, bool &) const

Generated at for the OpendTect seismic interpretation project. Copyright (C): dGB Beheer B. V. 2019