OpendTect  6.3
polylinend.h
Go to the documentation of this file.
1 #pragma once
2 
3 /*+
4 ________________________________________________________________________
5 
6  (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
7  Author: J.C. Glas
8  Date: Dec 2006
9 ________________________________________________________________________
10 
11 -*/
12 
13 #include "math.h"
14 #include "typeset.h"
15 
16 
22 template <class T>
23 mClass(Algo) PolyLineND : public TypeSet<T>
24 {
25 public:
26  PolyLineND(bool closed=false)
27  : closed_( closed ) {}
28 
29  PolyLineND(const TypeSet<T>& coords,bool closed=false)
30  : TypeSet<T>( coords )
31  , closed_( closed ) {}
32 
33  void setClosed(bool yn) { closed_ = yn; }
34  bool isClosed() const { return closed_; }
35 
36  double distTo(const T& pt,int* segmentidxptr=0,
37  double* fractionptr=0) const;
38 
39  T closestPoint(const T& pt) const;
40 
41  double arcLength(int idx,double frac=0.0) const;
42  double arcLength(const T& pt) const;
43  double arcLength() const;
44 
45  T getPoint(int idx,double frac=0.0) const;
46  T getPoint(double arclen) const;
47 
48 protected:
49 
50  int nextIdx(int) const;
51  bool closed_;
52 };
53 
54 
55 template <class T> inline
56 int PolyLineND<T>::nextIdx( int idx ) const
57 {
58  if ( idx<0 || idx>=this->size() || !(*this)[idx].isDefined() )
59  return mUdf(int);
60 
61  int idy = idx + 1;
62  if ( idy>=this->size() || !(*this)[idy].isDefined() )
63  {
64  while ( (--idy)>=0 && (*this)[idy].isDefined() ) ;
65 
66  idy++;
67 
68  if ( !closed_ && idy!=idx )
69  return mUdf(int);
70  }
71 
72  return idy;
73 }
74 
75 
88 #define mUpdateMinDist( dist, idx, frac ) \
89  if ( dist<mindist ) \
90  { \
91  mindist = dist; \
92  if ( segmentidxptr ) \
93  *segmentidxptr = idx; \
94  if ( fractionptr ) \
95  *fractionptr = frac; \
96  }
97 
98 template <class T> inline
99 double PolyLineND<T>::distTo( const T& pt, int* segmentidxptr,
100  double* fractionptr ) const
101 {
102  double mindist = MAXDOUBLE;
103 
104  for ( int idx=0; idx<this->size(); idx++ )
105  {
106  const int idy = nextIdx( idx );
107  if ( mIsUdf(idy) )
108  continue;
109 
110  const double a2 = pt.sqDistTo( (*this)[idx] );
111  const double b2 = pt.sqDistTo( (*this)[idy] );
112  const double c2 = (*this)[idx].sqDistTo( (*this)[idy] );
113 
114  if ( c2<=0.0 || b2>=a2+c2 )
115  {
116  const double a = Math::Sqrt( a2 );
117  mUpdateMinDist( a, idx, 0.0 );
118  }
119  else if ( a2 >= b2+c2 )
120  {
121  const double b = Math::Sqrt( b2 );
122  mUpdateMinDist( b, idx, 1.0 );
123  }
124  else
125  {
126  const double c = Math::Sqrt( c2 );
127  const double d = (a2+c2-b2) / (2*c);
128  const double h = (a2-d*d)>0 ? Math::Sqrt(a2-d*d) : 0.0;
129  mUpdateMinDist( h, idx, d/c );
130  }
131  }
132 
133  return mindist==MAXDOUBLE ? mUdf(double) : mindist;
134 }
135 
136 
137 template <class T> inline
138 T PolyLineND<T>::closestPoint( const T& pt ) const
139 {
140  int idx = 0;
141  double frac = 0;
142  if ( mIsUdf( distTo(pt,&idx,&frac) ) )
143  return T::udf();
144 
145  const int idy = nextIdx( idx );
146  if ( mIsUdf(idy) )
147  return T::udf();
148 
149  return (*this)[idx]*(1.0-frac) + (*this)[idy]*frac;
150 }
151 
152 
153 template <class T> inline
154 double PolyLineND<T>::arcLength( int index, double frac ) const
155 {
156  if ( index<0 || index>=this->size() || frac<0.0 || frac>1.0 )
157  return mUdf(double);
158 
159  double arclen = 0.0;
160 
161  for ( int idx=0; idx<=index; idx++ )
162  {
163  const int idy = nextIdx( idx );
164  if ( mIsUdf(idy) )
165  continue;
166 
167  const double len = (*this)[idx].template distTo<double>( (*this)[idy] );
168  if ( idx==index )
169  return arclen + len * frac;
170 
171  arclen += len;
172  }
173 
174  return arclen;
175 }
176 
177 
178 template <class T> inline
179 double PolyLineND<T>::arcLength( const T& pt ) const
180 {
181  int idx = 0;
182  double frac = 0;
183  if ( mIsUdf( distTo(pt,&idx,&frac) ) )
184  return mUdf(double);
185 
186  return arcLength( idx, frac );
187 }
188 
189 
190 template <class T> inline
192 {
193  return arcLength( this->size()-1, 1.0 );
194 }
195 
196 
197 template <class T> inline
198 T PolyLineND<T>::getPoint( int idx, double frac ) const
199 {
200  if ( idx<0 || idx>=this->size() || frac<0.0 || frac>1.0 )
201  return T::udf();
202 
203  if ( frac == 0.0 )
204  return (*this)[idx];
205 
206  if ( frac==1.0 && !(*this)[idx].isDefined() )
207  return getPoint( idx+1, 0.0 );
208 
209  const int idy = nextIdx( idx );
210  if ( mIsUdf(idy) )
211  return T::udf();
212 
213  return (*this)[idx]*(1.0-frac) + (*this)[idy]*frac;
214 }
215 
216 
217 template <class T> inline
218 T PolyLineND<T>::getPoint( double arclen ) const
219 {
220  if ( arclen<0.0 )
221  return T::udf();
222 
223  for ( int idx=0; idx<this->size(); idx++ )
224  {
225  const int idy = nextIdx( idx );
226  if ( mIsUdf(idy) )
227  continue;
228 
229  const double len = (*this)[idx].template distTo<double>( (*this)[idy] );
230  if ( arclen <= len )
231  {
232  const double frac = arclen / len;
233  return (*this)[idx]*(1.0-frac) + (*this)[idy]*frac;
234  }
235 
236  arclen -= len;
237  }
238 
239  return T::udf();
240 }
#define mIsUdf(val)
Use mIsUdf to check for undefinedness of simple types.
Definition: undefval.h:285
bool closed_
Definition: polylinend.h:51
#define mUpdateMinDist(dist, idx, frac)
Point-to-segment distance:
Definition: polylinend.h:88
T closestPoint(const T &pt) const
Definition: polylinend.h:138
PolyLineND(bool closed=false)
Definition: polylinend.h:26
Set of (small) copyable elements.
Definition: commontypes.h:26
double arcLength() const
Definition: polylinend.h:191
#define mUdf(type)
Use this macro to get the undefined for simple types.
Definition: undefval.h:270
(Closed) sequence(s) of connected n-D coordinates. Undefined coordinates separate consecutive sequenc...
Definition: polylinend.h:23
T getPoint(int idx, double frac=0.0) const
Definition: polylinend.h:198
bool isClosed() const
Definition: polylinend.h:34
double distTo(const T &pt, int *segmentidxptr=0, double *fractionptr=0) const
Definition: polylinend.h:99
int nextIdx(int) const
Definition: polylinend.h:56
#define MAXDOUBLE
Definition: commondefs.h:103
#define mClass(module)
Definition: commondefs.h:161
PolyLineND(const TypeSet< T > &coords, bool closed=false)
Definition: polylinend.h:29
float Sqrt(float)
void setClosed(bool yn)
Definition: polylinend.h:33

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