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

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