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

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