OpenCPN Partial API docs
Loading...
Searching...
No Matches
iirfilter.cpp
1
2#include "wx/wxprec.h"
3
4#ifndef WX_PRECOMP
5#include "wx/wx.h"
6#endif // precompiled headers
7
8#include "iirfilter.h"
9#include <cmath>
10
11#include <wx/math.h>
12
13iirfilter::iirfilter(double fc, int tp) {
14 wxASSERT(tp == IIRFILTER_TYPE_DEG || tp == IIRFILTER_TYPE_LINEAR ||
15 tp == IIRFILTER_TYPE_RAD);
16 setFC(fc);
17 type = tp;
18 reset();
19}
20
21double iirfilter::filter(double data) {
22 if (!std::isnan(data) && !std::isnan(b1)) {
23 if (std::isnan(accum)) accum = 0.0;
24 switch (type) {
25 case IIRFILTER_TYPE_LINEAR:
26 accum = accum * b1 + a0 * data;
27 break;
28
29 case IIRFILTER_TYPE_DEG:
30 unwrapDeg(data);
31 accum = accum * b1 + a0 * (oldDeg + 360.0 * wraps);
32 break;
33
34 case IIRFILTER_TYPE_RAD:
35 unwrapRad(data);
36 accum = accum * b1 + a0 * (oldRad + 2.0 * M_PI * wraps);
37 break;
38
39 default:
40 wxASSERT(false);
41 }
42 } else
43 accum = data;
44 return get();
45}
46
47void iirfilter::reset(double a) {
48 accum = a;
49 oldDeg = NAN;
50 oldRad = NAN;
51 wraps = 0;
52}
53
54void iirfilter::setFC(double fc) {
55 if (std::isnan(fc) || fc <= 0.0)
56 a0 = b1 = NAN; // NAN means no filtering will be done
57 else {
58 reset();
59 b1 = exp(-2.0 * 3.1415926535897932384626433832795 * fc);
60 a0 = 1 - b1;
61 }
62}
63
64void iirfilter::setType(int tp) {
65 wxASSERT(tp == IIRFILTER_TYPE_DEG || tp == IIRFILTER_TYPE_LINEAR ||
66 tp == IIRFILTER_TYPE_RAD);
67 type = tp;
68}
69
70double iirfilter::getFc(void) {
71 if (std::isnan(b1)) return 0.0;
72 double fc = log(b1) / (-2.0 * 3.1415926535897932384626433832795);
73 return fc;
74}
75
76int iirfilter::getType(void) { return type; }
77
78double iirfilter::get(void) {
79 if (std::isnan(accum)) return accum;
80 double res = accum;
81 switch (type) {
82 case IIRFILTER_TYPE_DEG:
83 while (res < 0) res += 360.0;
84 while (res > 360) res -= 360.0;
85 break;
86
87 case IIRFILTER_TYPE_RAD:
88 while (res < 0) res += 2.0 * M_PI;
89 while (res > 2.0 * M_PI) res -= 2.0 * M_PI;
90 break;
91 }
92 return res;
93}
94
95void iirfilter::unwrapDeg(double deg) {
96 if (deg - oldDeg > 180) {
97 wraps--;
98 } else if (deg - oldDeg < -180) {
99 wraps++;
100 }
101 oldDeg = deg;
102}
103
104void iirfilter::unwrapRad(double rad) {
105 if (rad - oldRad > M_PI) {
106 wraps--;
107 } else if (rad - oldRad < M_PI) {
108 wraps++;
109 }
110 oldRad = rad;
111}