OpendTect-6_4  6.4
valseriesevent.h
Go to the documentation of this file.
1 #ifndef valseriesevent_h
2 #define valseriesevent_h
3 
4 /*
5 ________________________________________________________________________
6 
7  (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
8  Author: Bert Bril
9  Date: May 2005
10  RCS: $Id$
11 ________________________________________________________________________
12 
13 */
14 
15 #include "algomod.h"
16 #include "enums.h"
17 #include "mathfunc.h"
18 #include "ptrman.h"
19 #include "ranges.h"
20 #include "samplingdata.h"
21 #include "valseries.h"
22 
24 {
25 public:
26  enum Type { None, Extr, Max, Min, ZC, ZCNegPos, ZCPosNeg,
27  GateMax, GateMin };
29 };
30 
31 
39 template <class VT,class PT>
41 {
42 public:
43 
44 
45  ValueSeriesEvent( VT v=mUdf(VT), PT p=mUdf(PT) )
46  { val = v; pos = p;}
47 
48  VT val;
49  PT pos;
50 };
51 
52 
64 template <class VT,class PT>
66 {
67 public:
69  int maxidx,
70  const SamplingData<PT>& s )
71  : vs_(v)
72  , maxidx_(maxidx)
73  , sd_(s)
74  , lastfound_(VSEvent::None) {}
75 
76  const ValueSeries<VT>& valueSeries() const { return vs_; }
77  const SamplingData<PT>& samplingData() const { return sd_; }
78 
80  int occ=1) const;
81  bool findEvents(TypeSet<PT>&,Interval<PT>,
83 
84  static ValueSeriesEvent<VT,PT> exactExtreme(VSEvent::Type,
85  int idxminus1,int idx0,int idx1,
86  VT vminus1,VT v0,VT v1,
87  const SamplingData<PT>&);
90 
91  VSEvent::Type lastFound() const { return lastfound_; }
93 
94 protected:
95 
98  int maxidx_;
100 
101  ValueSeriesEvent<VT,PT> getZC(const Interval<int>&,int,
102  VSEvent::Type) const;
103  ValueSeriesEvent<VT,PT> getExtreme(const Interval<int>&,int,
104  VSEvent::Type) const;
105  ValueSeriesEvent<VT,PT> getGateExtr(const Interval<int>&,bool) const;
106 
107 };
108 
109 
110 #undef mIncSampIdx
111 #define mIncSampIdx(idx) { \
112  idx += inc; \
113  if ( idx == sg.stop+inc ) \
114  return ValueSeriesEvent<VT,PT>( 0, mUdf(PT) ); }
115 #undef mDecrOccAtZero
116 #define mDecrOccAtZero(idx) { \
117  occ--; \
118  if ( occ < 1 ) \
119  return ValueSeriesEvent<VT,PT>( 0, sd_.atIndex(idx) ); }
120 
121 
122 template <class VT,class PT>
124  const Interval<int>& sg, int occ, VSEvent::Type evtype ) const
125 {
126  const int inc = sg.start < sg.stop ? 1 : -1;
127 
128  int idx = sg.start;
129  VT v0 = vs_.value( idx );
130  while ( v0 == 0 )
131  {
132  mDecrOccAtZero(idx)
133  mIncSampIdx(idx)
134  v0 = vs_.value( idx );
135  }
136 
137  int frompositive = v0 > 0;
138  const bool needtopos = evtype != VSEvent::ZCPosNeg;
139  const bool needtoneg = evtype != VSEvent::ZCNegPos;
140  for ( ; idx!=sg.stop+inc; idx+=inc )
141  {
142  VT v1 = vs_.value( idx );
143  while ( v1 == 0 )
144  {
145  mIncSampIdx(idx)
146  v0 = v1;
147  v1 = vs_.value( idx );
148  if ( v1 != 0 )
149  {
150  if ( ( (v1<0) != frompositive && needtoneg )
151  || ( (v1>0) != frompositive && needtopos ) )
152  mDecrOccAtZero(idx-inc)
153 
154  mIncSampIdx(idx)
155  v0 = v1; frompositive = v0 > 0;
156  v1 = vs_.value( idx );
157  }
158  }
159  // Here, both v0 and v1 are non-zero
160  // Now we can do the main thing:
161  const bool istopos = v0 < 0 && v1 > 0;
162  const bool istoneg = v0 > 0 && v1 < 0;
163  if ( ( istopos && needtopos ) || ( istoneg && needtoneg ) )
164  {
165  occ--;
166  if ( occ < 1 )
167  {
168  lastfound_ = istopos ? VSEvent::ZCNegPos
170  PT pos = idx - inc * (v1 / ( v1 - v0 ));
171  return ValueSeriesEvent<VT,PT>( 0, sd_.start + pos * sd_.step );
172  }
173  }
174  v0 = v1;
175  }
176 
177  return ValueSeriesEvent<VT,PT>( 0, mUdf(PT) );
178 }
179 
180 
181 template <class VT,class PT>
183  VSEvent::Type evtype, int idxm1, int idx0, int idx1,
184  VT vm1, VT v0, VT v1,
185  const SamplingData<PT>& sd )
186 {
187  if ( idxm1 > idx1 )
188  { Swap( idxm1, idx1 ); Swap( vm1, v1 ); }
189 
190  vm1 -= v0; v1 -= v0;
191  idxm1 -= idx0; idx1 -= idx0;
192 
193  vm1 /= idxm1; v1 /= idx1;
194 
195  VT a = (vm1 - v1) / (idxm1 - idx1);
196  VT b = 0;
197  PT relpos = 0;
198  if ( a != 0 )
199  {
200  b = vm1 - a * idxm1;
201  relpos = -b / (2*a);
202  }
203 
205  ret.val = (VT)(v0 + a * relpos * relpos + b * relpos);
206  ret.pos = sd.start + sd.step * (idx0 + relpos);
207  return ret;
208 }
209 
210 
211 template <class VT,class PT>
213  const Interval<int>& inpsg, bool needmax ) const
214 {
215  Interval<int> sg( inpsg );
216  sg.sort();
217 
218  // skip undefs at start
219  int curidx;
220  int extridx = sg.start; VT extrval = vs_.value( extridx );
221  for ( curidx=sg.start+1; mIsUdf(extrval) && curidx<=sg.stop; curidx++ )
222  { extridx = curidx; extrval = vs_.value( curidx ); }
223  if ( mIsUdf(extrval) )
224  return ValueSeriesEvent<VT,PT>();
225 
226  // find min/max
227  for ( ; curidx<=sg.stop; curidx++ )
228  {
229  const VT val = vs_.value( curidx );
230  if ( mIsUdf(val) ) continue;
231 
232  if ( (needmax && val > extrval) || (!needmax && val < extrval) )
233  { extridx = curidx; extrval = val; }
234  }
235 
236  // collect the data points around the extreme sample
237  VT v0 = extrval;
238  VT vm1 = extridx > sg.start ? vs_.value(extridx-1) : v0;
239  if ( mIsUdf(vm1) ) vm1 = v0;
240  VT v1 = extridx < sg.stop-1 ? vs_.value(extridx+1) : v0;
241  if ( mIsUdf(v1) ) v1 = v0;
242 
243  return exactExtreme( needmax ? VSEvent::Max : VSEvent::Min,
244  extridx-1, extridx, extridx+1, vm1, v0, v1, sd_ );
245 }
246 
247 
248 template <class VT,class PT>
250  const Interval<int>& sg, int occ, VSEvent::Type evtype ) const
251 {
252  const int inc = sg.start < sg.stop ? 1 : -1;
253  int idx0 = sg.start;
254  VT v0 = vs_.value( idx0 );
255  bool havevm1 = (inc > 0 && sg.start > 0) || (inc < 0 && sg.start < maxidx_);
256  VT vm1 = havevm1 ? vs_.value( sg.start - inc ) : v0;
257  if ( mIsUdf(vm1) ) vm1 = v0;
258  bool upw0 = v0 > vm1;
259  int idx1 = idx0;
260 
261  while ( true )
262  {
263  mIncSampIdx(idx1)
264 
265  VT v1 = vs_.value( idx1 );
266  if ( mIsUdf(v1) || v1 == v0 )
267  continue;
268 
269  const bool upw1 = v1 > v0;
270  bool ishit = havevm1 && !mIsUdf(v0) && upw0 != upw1;
271  if ( ishit )
272  {
273  const bool atmax = upw0 && !upw1;
274  ishit = (evtype != VSEvent::Min && atmax)
275  || (evtype != VSEvent::Max && !atmax);
276  if ( ishit )
277  {
278  lastfound_ = atmax ? VSEvent::Max : VSEvent::Min;
279  occ--;
280  }
281  }
282 
283  if ( occ < 1 )
284  return exactExtreme( evtype, idx0-inc, idx0, idx1,
285  vm1, v0, v1, sd_ );
286 
287  upw0 = upw1; idx0 = idx1; vm1 = v0; v0 = v1;
288  havevm1 = !mIsUdf(v0);
289  }
290 
291  // not reached, mIncSampIdx or exactExtreme return
292 }
293 
294 
295 template <class VT,class PT>
297  VSEvent::Type evtype, const Interval<PT>& pgin, int occ ) const
298 {
299  lastfound_ = evtype;
300  Interval<PT> pg( pgin );
301 
303  if ( occ < 1 )
304  {
305  pErrMsg("Weird request: less than first occ of event.");
306  return ev;
307  }
308 
309  if ( evtype == VSEvent::None )
310  return ev;
311 
312  const int inc = pg.start < pg.stop ? 1 : -1;
313  if ( pg.start < sd_.start )
314  { if ( inc < 0 ) return ev; pg.start = sd_.start; }
315  if ( pg.stop < sd_.start )
316  { if ( inc > 0 ) return ev; pg.stop = sd_.start; }
317 
318  const PT endpos = sd_.atIndex( maxidx_ );
319  if ( pg.start > endpos )
320  { if ( inc > 0 ) return ev; pg.start = endpos; }
321  if ( pg.stop > endpos )
322  { if ( inc < 0 ) return ev; pg.stop = endpos; }
323 
324  SampleGate sg;
325  if ( inc > 0 )
326  {
327  sg.start = (int)Math::Floor((pg.start-sd_.start)/sd_.step);
328  sg.stop = (int)Math::Ceil((pg.stop-sd_.start)/sd_.step);
329  }
330  else
331  {
332  sg.start = (int)Math::Ceil((pg.start-sd_.start)/sd_.step);
333  sg.stop = (int)Math::Floor((pg.stop-sd_.start)/sd_.step);
334  if ( evtype == VSEvent::ZCNegPos )
335  evtype = VSEvent::ZCPosNeg;
336  else if ( evtype == VSEvent::ZCPosNeg )
337  evtype = VSEvent::ZCNegPos;
338  }
339 
340  bool iszc = false;
341  if ( evtype==VSEvent::GateMax || evtype==VSEvent::GateMin )
342  return getGateExtr( sg, evtype == VSEvent::GateMax );
343  else if ( sg.start == sg.stop )
344  return ev;
345  else if ( evtype >= VSEvent::ZC && evtype <= VSEvent::ZCPosNeg )
346  iszc = true;
347 
348  while ( true )
349  {
350  if ( !iszc )
351  ev = getExtreme( sg, occ, evtype );
352  else
353  {
354  ev = getZC( sg, occ, evtype );
355  if ( inc < 0 )
356  lastfound_ = lastfound_ == VSEvent::ZCPosNeg
358  }
359  if ( mIsUdf(ev.pos) )
360  break;
361 
362  if ( ( inc > 0 && ev.pos < pg.start ) ||
363  ( inc < 0 && ev.pos > pg.start ) )
364  occ++;
365  else
366  break;
367  }
368 
369  return ev;
370 }
371 
372 
373 // Gives a TypeSet of all the events of a type making sure that there is an
374 // 'opposite'(with phase diff 180deg) event type between any two of them:
375 template <class VT,class PT>
377  Interval<PT> pg, VSEvent::Type evtype )
378 {
379  Interval<PT> curg( pg );
380  VSEvent::Type revtype = VSEvent::Min;
381  if ( evtype == VSEvent::Max )
382  revtype = VSEvent::Min;
383  else if ( evtype == VSEvent::Min )
384  revtype = VSEvent::Max;
385  else if ( evtype == VSEvent::ZCNegPos )
386  revtype = VSEvent::ZCPosNeg;
387  else if ( evtype == VSEvent::ZCPosNeg )
388  revtype = VSEvent::ZCNegPos;
389 
390  const bool isascending = pg.stop > pg.start;
391  posset.erase();
392  while ( isascending == (curg.stop>curg.start) )
393  {
394  ValueSeriesEvent<VT,PT> reqev = find( evtype, curg, 1 );
395  if ( mIsUdf(reqev.pos) ) break;
396 
397  posset += reqev.pos;
398  curg.start = reqev.pos + mCast(PT,1e-5);
399  ValueSeriesEvent<VT,PT> revev = find( revtype, curg, 1 );
400  if ( mIsUdf(revev.pos) ) break;
401 
402  curg.start = revev.pos + mCast(PT,1e-5);
403  }
404 
405  if ( !posset.size() ) return false;
406 
407  return true;
408 }
409 
410 
411 #undef mIncSampIdx
412 #undef mDecrOccAtZero
413 
414 #endif
#define mExpClass(module)
Definition: commondefs.h:160
#define mIsUdf(val)
Use mIsUdf to check for undefinedness of simple types.
Definition: undefval.h:287
T step
Definition: samplingdata.h:50
const SamplingData< PT > & samplingData() const
Definition: valseriesevent.h:77
float Ceil(float)
Definition: valseriesevent.h:26
#define mCast(tp, v)
Definition: commondefs.h:124
Definition: valseriesevent.h:26
Definition: valseriesevent.h:23
#define mIncSampIdx(idx)
Definition: valseriesevent.h:111
Definition: stattype.h:26
ValueSeriesEvent< VT, PT > getExtreme(const Interval< int > &, int, VSEvent::Type) const
Definition: valseriesevent.h:249
Definition: valseriesevent.h:26
#define mDeclareEnumUtils(enm)
Some utilities surrounding the often needed enum <-> string table.
Definition: enums.h:258
Interval of values.
Definition: commontypes.h:31
ValueSeriesEvent< VT, PT > find(VSEvent::Type, const Interval< PT > &, int occ=1) const
Definition: valseriesevent.h:296
FixedString None()
Definition: keystrs.h:90
VT val
Definition: valseriesevent.h:48
Definition: valseriesevent.h:27
Definition: valseriesevent.h:26
float Floor(float)
int maxidx_
Definition: valseriesevent.h:98
Set of (small) copyable elements.
Definition: commontypes.h:30
static ValueSeriesEvent< VT, PT > exactExtreme(VSEvent::Type, int idxminus1, int idx0, int idx1, VT vminus1, VT v0, VT v1, const SamplingData< PT > &)
Definition: valseriesevent.h:182
Definition: stattype.h:26
ValueSeriesEvent< VT, PT > getZC(const Interval< int > &, int, VSEvent::Type) const
Definition: valseriesevent.h:123
Event in value series.
Definition: valseriesevent.h:40
#define mDecrOccAtZero(idx)
Definition: valseriesevent.h:116
#define mUdf(type)
Use this macro to get the undefined for simple types.
Definition: undefval.h:272
ValueSeriesEvent< VT, PT > getGateExtr(const Interval< int > &, bool) const
Definition: valseriesevent.h:212
PT pos
Definition: valseriesevent.h:49
T start
Definition: samplingdata.h:49
const ValueSeries< VT > & valueSeries() const
Definition: valseriesevent.h:76
void Swap(T &a, T &b)
Definition: commondefs.h:36
Event finder in gate.
Definition: valseriesevent.h:65
const T * find(const ObjectSet< T > &os, const S &val)
Get const object in set.
Definition: objectset.h:183
Definition: valseriesevent.h:27
VSEvent::Type lastFound() const
Useful when finding Extr or ZC.
Definition: valseriesevent.h:91
size_type size() const
T stop
Definition: ranges.h:93
VSEvent::Type lastfound_
Definition: valseriesevent.h:99
Definition: valseriesevent.h:26
virtual void erase()
const ValueSeries< VT > & vs_
Definition: valseriesevent.h:96
T start
Definition: ranges.h:92
virtual void sort(bool asc=true)
Definition: ranges.h:585
#define mClass(module)
Definition: commondefs.h:164
#define pErrMsg(msg)
Definition: errmsg.h:60
Type
Definition: valseriesevent.h:26
bool findEvents(TypeSet< PT > &, Interval< PT >, VSEvent::Type)
Definition: valseriesevent.h:376
const SamplingData< PT > sd_
Definition: valseriesevent.h:97
ValueSeriesEvFinder(const ValueSeries< VT > &v, int maxidx, const SamplingData< PT > &s)
Definition: valseriesevent.h:68
ValueSeriesEvent(VT v=mUdf(VT), PT p=mUdf(PT))
Definition: valseriesevent.h:45
Definition: valseriesevent.h:26

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