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