Mercurial > hg > aimc
comparison trunk/src/Modules/Output/Graphics/GraphicsView.cc @ 398:3ee03a6b95a0
- All \t to two spaces (style guide compliance)
author | tomwalters |
---|---|
date | Fri, 15 Oct 2010 05:46:53 +0000 |
parents | 7a573750b186 |
children | 7bfed53caacf |
comparison
equal
deleted
inserted
replaced
397:7a573750b186 | 398:3ee03a6b95a0 |
---|---|
19 | 19 |
20 #include "Output/GraphicsView.h" | 20 #include "Output/GraphicsView.h" |
21 #include "Output/GraphicsOutputDevice.h" | 21 #include "Output/GraphicsOutputDevice.h" |
22 | 22 |
23 GraphicsView::GraphicsView(Parameters *parameters) : Module(parameters) { | 23 GraphicsView::GraphicsView(Parameters *parameters) : Module(parameters) { |
24 module_description_ = ""; | 24 module_description_ = ""; |
25 module_identifier_ = "graphics"; | 25 module_identifier_ = "graphics"; |
26 module_type_ = "output"; | 26 module_type_ = "output"; |
27 module_version_ = "$Id: $"; | 27 module_version_ = "$Id: $"; |
28 | 28 |
29 m_pDev = NULL; | 29 m_pDev = NULL; |
30 m_bPlotLabels = false; | 30 m_bPlotLabels = false; |
31 m_pAxisX = new GraphAxisSpec(); | 31 m_pAxisX = new GraphAxisSpec(); |
32 AIM_ASSERT(m_pAxisX); | 32 AIM_ASSERT(m_pAxisX); |
33 m_pAxisY = new GraphAxisSpec(); | 33 m_pAxisY = new GraphAxisSpec(); |
34 AIM_ASSERT(m_pAxisY); | 34 AIM_ASSERT(m_pAxisY); |
35 m_pAxisFreq = new GraphAxisSpec(); | 35 m_pAxisFreq = new GraphAxisSpec(); |
36 AIM_ASSERT(m_pAxisFreq); | 36 AIM_ASSERT(m_pAxisFreq); |
37 | 37 |
38 m_pAxisY->Initialize(m_pParam, | 38 m_pAxisY->Initialize(m_pParam, |
39 _S("graph.y"), | 39 _S("graph.y"), |
40 -1, | 40 -1, |
41 1, | 41 1, |
42 Scale::SCALE_LINEAR); | 42 Scale::SCALE_LINEAR); |
43 m_fMarginLeft = m_pParam->GetFloat(_S("graph.margin.left")); | 43 m_fMarginLeft = m_pParam->GetFloat(_S("graph.margin.left")); |
44 m_fMarginRight = m_pParam->GetFloat(_S("graph.margin.right")); | 44 m_fMarginRight = m_pParam->GetFloat(_S("graph.margin.right")); |
45 m_fMarginTop = m_pParam->GetFloat(_S("graph.margin.top")); | 45 m_fMarginTop = m_pParam->GetFloat(_S("graph.margin.top")); |
46 m_fMarginBottom = m_pParam->GetFloat(_S("graph.margin.bottom")); | 46 m_fMarginBottom = m_pParam->GetFloat(_S("graph.margin.bottom")); |
47 m_bPlotLabels = m_pParam->GetBool(_S("graph.plotlabels")); | 47 m_bPlotLabels = m_pParam->GetBool(_S("graph.plotlabels")); |
48 | 48 |
49 const char *sGraphType = m_pParam->GetString(_S("graph.type")); | 49 const char *sGraphType = m_pParam->GetString(_S("graph.type")); |
50 if (strcmp(sGraphType, _S("line"))==0) | 50 if (strcmp(sGraphType, _S("line"))==0) |
51 m_iGraphType = GraphTypeLine; | 51 m_iGraphType = GraphTypeLine; |
52 else if (strcmp(sGraphType, _S("colormap"))==0) | 52 else if (strcmp(sGraphType, _S("colormap"))==0) |
53 m_iGraphType = GraphTypeColormap; | 53 m_iGraphType = GraphTypeColormap; |
54 else if (strcmp(sGraphType, _S("none"))==0) | 54 else if (strcmp(sGraphType, _S("none"))==0) |
55 m_iGraphType = GraphTypeNone; | 55 m_iGraphType = GraphTypeNone; |
56 else { | 56 else { |
57 ret = false; | 57 ret = false; |
58 AIM_ERROR(_T("Unrecognized graph type: '%s'"), sGraphType); | 58 AIM_ERROR(_T("Unrecognized graph type: '%s'"), sGraphType); |
59 } | 59 } |
60 | 60 |
61 if (strcmp(m_pParam->GetString(_S("graph.mindistance")),"auto") == 0) | 61 if (strcmp(m_pParam->GetString(_S("graph.mindistance")),"auto") == 0) |
62 // -1 means detect later, based on type and Fire() argument | 62 // -1 means detect later, based on type and Fire() argument |
63 m_fMinPlotDistance = -1; | 63 m_fMinPlotDistance = -1; |
64 else | 64 else |
65 m_fMinPlotDistance = m_pParam->GetFloat(_S("graph.mindistance")); | 65 m_fMinPlotDistance = m_pParam->GetFloat(_S("graph.mindistance")); |
66 | 66 |
67 } | 67 } |
68 | 68 |
69 GraphicsView::~GraphicsView() { | 69 GraphicsView::~GraphicsView() { |
70 DELETE_IF_NONNULL(m_pAxisX); | 70 DELETE_IF_NONNULL(m_pAxisX); |
71 DELETE_IF_NONNULL(m_pAxisY); | 71 DELETE_IF_NONNULL(m_pAxisY); |
72 DELETE_IF_NONNULL(m_pAxisFreq); | 72 DELETE_IF_NONNULL(m_pAxisFreq); |
73 } | 73 } |
74 | 74 |
75 bool | 75 bool |
76 | 76 |
77 bool GraphicsView::InitializeInternal(const SignalBank &bank) { | 77 bool GraphicsView::InitializeInternal(const SignalBank &bank) { |
78 if (!m_pDev) { | 78 if (!m_pDev) { |
79 LOG_ERROR("Output device not connected"); | 79 LOG_ERROR("Output device not connected"); |
80 return false; | 80 return false; |
81 } | 81 } |
82 | 82 |
83 float y_min = bank.centre_frequency(0); | 83 float y_min = bank.centre_frequency(0); |
84 float y_max = bank.centre_frequency(bank.channel_count() - 1); | 84 float y_max = bank.centre_frequency(bank.channel_count() - 1); |
85 if (!m_pAxisFreq->Initialize(m_pParam, | 85 if (!m_pAxisFreq->Initialize(m_pParam, |
86 "graph.freq", | 86 "graph.freq", |
87 y_min, | 87 y_min, |
88 y_max, | 88 y_max, |
89 Scale::SCALE_ERB)) { | 89 Scale::SCALE_ERB)) { |
90 LOG_ERROR(""); | 90 LOG_ERROR(""); |
91 return false; | 91 return false; |
92 } | 92 } |
93 | 93 |
94 float x_min = 0.0; | 94 float x_min = 0.0; |
95 float x_max = 1000.0 * bank.buffer_length() / bank.sample_rate(); | 95 float x_max = 1000.0 * bank.buffer_length() / bank.sample_rate(); |
96 if (!m_pAxisX->Initialize(m_pParam, | 96 if (!m_pAxisX->Initialize(m_pParam, |
97 "graph.x", | 97 "graph.x", |
98 x_min, | 98 x_min, |
99 x_max, | 99 x_max, |
100 Scale::SCALE_LINEAR)) { | 100 Scale::SCALE_LINEAR)) { |
101 LOG_ERROR(""); | 101 LOG_ERROR(""); |
102 return false; | 102 return false; |
103 } | 103 } |
104 | 104 |
105 /* Inform graphics output of maximum number of vertices between | 105 /* Inform graphics output of maximum number of vertices between |
106 * gBegin*() and gEnd(), for any type of plot. Colormap needs most. | 106 * gBegin*() and gEnd(), for any type of plot. Colormap needs most. |
107 */ | 107 */ |
108 if (!m_pDev->Initialize(MAX(10, bank.buffer_length() * 2 + 2))) { | 108 if (!m_pDev->Initialize(MAX(10, bank.buffer_length() * 2 + 2))) { |
109 LOG_ERROR(""); | 109 LOG_ERROR(""); |
110 return false; | 110 return false; |
111 } | 111 } |
112 } | 112 } |
113 | 113 |
114 void GraphicsView::Process(const SignalBank &bank) { | 114 void GraphicsView::Process(const SignalBank &bank) { |
115 float height = 1.0 / bank.channel_count(); | 115 float height = 1.0 / bank.channel_count(); |
116 float heightMinMargin = height * (1.0f - m_fMarginBottom - m_fMarginTop); | 116 float heightMinMargin = height * (1.0f - m_fMarginBottom - m_fMarginTop); |
117 float xScaling = 1.0f; | 117 float xScaling = 1.0f; |
118 | 118 |
119 m_pDev->gGrab(); | 119 m_pDev->gGrab(); |
120 PlotAxes(bank); | 120 PlotAxes(bank); |
121 m_pDev->gColor3f(1.0f, 1.0f, 0.8f); | 121 m_pDev->gColor3f(1.0f, 1.0f, 0.8f); |
122 for (int i = 0; i < bank.channel_count(); i++) { | 122 for (int i = 0; i < bank.channel_count(); i++) { |
123 float yOffs = bank.centre_frequency(i); | 123 float yOffs = bank.centre_frequency(i); |
124 yOffs = m_pAxisFreq->m_pScale->FromLinearScaled(yOffs) + 0.5f; | 124 yOffs = m_pAxisFreq->m_pScale->FromLinearScaled(yOffs) + 0.5f; |
125 /* Don't plot below zero and stop when above 1, since yOffs is | 125 /* Don't plot below zero and stop when above 1, since yOffs is |
126 * monotonically increasing. Because of rounding errors, we need | 126 * monotonically increasing. Because of rounding errors, we need |
127 * to check for yOffs < -1e-6 instead of yOffs < 0. */ | 127 * to check for yOffs < -1e-6 instead of yOffs < 0. */ |
128 if (yOffs < -1e-6) | 128 if (yOffs < -1e-6) |
129 continue; | 129 continue; |
130 if (yOffs > 1) | 130 if (yOffs > 1) |
131 break; | 131 break; |
132 | 132 |
133 // Scale to single channel graphing. | 133 // Scale to single channel graphing. |
134 yOffs = yOffs * (1.0f - height) + height / 2.0; | 134 yOffs = yOffs * (1.0f - height) + height / 2.0; |
135 yOffs = yOffs * (1.0f - m_fMarginTop - m_fMarginBottom) + m_fMarginBottom; | 135 yOffs = yOffs * (1.0f - m_fMarginTop - m_fMarginBottom) + m_fMarginBottom; |
136 PlotData(bank[i], yOffs, heightMinMargin, xScaling); | 136 PlotData(bank[i], yOffs, heightMinMargin, xScaling); |
137 } | 137 } |
138 m_pDev->gRelease(); | 138 m_pDev->gRelease(); |
139 } | 139 } |
140 | 140 |
141 void GraphicsView::SetAxisScale(Scale::ScaleType iHori, | 141 void GraphicsView::SetAxisScale(Scale::ScaleType iHori, |
142 Scale::ScaleType iVert, | 142 Scale::ScaleType iVert, |
143 Scale::ScaleType iFreq) { | 143 Scale::ScaleType iFreq) { |
144 AIM_ASSERT(m_pAxisX); | 144 AIM_ASSERT(m_pAxisX); |
145 AIM_ASSERT(m_pAxisY); | 145 AIM_ASSERT(m_pAxisY); |
146 AIM_ASSERT(m_pAxisFreq); | 146 AIM_ASSERT(m_pAxisFreq); |
147 m_pAxisX->SetDisplayScale(iHori); | 147 m_pAxisX->SetDisplayScale(iHori); |
148 m_pAxisY->SetDisplayScale(iVert); | 148 m_pAxisY->SetDisplayScale(iVert); |
149 m_pAxisFreq->SetDisplayScale(iFreq); | 149 m_pAxisFreq->SetDisplayScale(iFreq); |
150 } | 150 } |
151 | 151 |
152 void GraphicsView::BeginDataStrip() { | 152 void GraphicsView::BeginDataStrip() { |
153 m_iPrevValEqual=0; | 153 m_iPrevValEqual=0; |
154 m_bFirstPoint=true; | 154 m_bFirstPoint=true; |
155 switch(m_iGraphType) { | 155 switch(m_iGraphType) { |
156 case GraphTypeLine: | 156 case GraphTypeLine: |
157 m_pDev->gBeginLineStrip(); | 157 m_pDev->gBeginLineStrip(); |
158 break; | 158 break; |
159 case GraphTypeColormap: | 159 case GraphTypeColormap: |
160 m_pDev->gBeginQuadStrip(); | 160 m_pDev->gBeginQuadStrip(); |
161 break; | 161 break; |
162 case GraphTypeNone: | 162 case GraphTypeNone: |
163 // Nothing: just for testing computation overhead of graphing | 163 // Nothing: just for testing computation overhead of graphing |
164 break; | 164 break; |
165 } | 165 } |
166 } | 166 } |
167 | 167 |
168 void GraphicsView::PlotDataPoint(float x, | 168 void GraphicsView::PlotDataPoint(float x, |
169 float y, | 169 float y, |
170 float val, | 170 float val, |
171 float height, | 171 float height, |
172 bool isLast) { | 172 bool isLast) { |
173 AIM_ASSERT(m_pDev); | 173 AIM_ASSERT(m_pDev); |
174 | 174 |
175 /* Reduce the number of points plotted by eliminating duplicate values: | 175 /* Reduce the number of points plotted by eliminating duplicate values: |
176 * | 176 * |
177 * oooo o--o | 177 * oooo o--o |
178 * o / o | 178 * o / o |
179 * oooo ooo => o--o o--o | 179 * oooo ooo => o--o o--o |
180 * oooo ooo o--o o-o | 180 * oooo ooo o--o o-o |
181 * | 181 * |
182 * with 'o' points that are plotted, and '-' by the graphics output | 182 * with 'o' points that are plotted, and '-' by the graphics output |
183 * device interpolated points. We could be smarter and include | 183 * device interpolated points. We could be smarter and include |
184 * first-order interpolation, but we leave that as an exercise for | 184 * first-order interpolation, but we leave that as an exercise for |
185 * the reader. Please send your patches :) | 185 * the reader. Please send your patches :) |
186 * | 186 * |
187 * So, we don't draw points that are too close to the previous value. | 187 * So, we don't draw points that are too close to the previous value. |
188 * But if the value changes (or it's the last point), we must draw the | 188 * But if the value changes (or it's the last point), we must draw the |
189 * previous point too. | 189 * previous point too. |
190 */ | 190 */ |
191 if (!m_bFirstPoint | 191 if (!m_bFirstPoint |
192 && !isLast | 192 && !isLast |
193 && fabs(m_fPrevVal-val) < m_fMinPlotDistance) { | 193 && fabs(m_fPrevVal-val) < m_fMinPlotDistance) { |
194 m_iPrevValEqual++; | 194 m_iPrevValEqual++; |
195 // Don't set m_fPrevVal to avoid not catching slow changes | 195 // Don't set m_fPrevVal to avoid not catching slow changes |
196 m_fPrevX = x; | 196 m_fPrevX = x; |
197 m_fPrevY = y; | 197 m_fPrevY = y; |
198 m_fPrevHeight = height; | 198 m_fPrevHeight = height; |
199 return; | 199 return; |
200 } else { | 200 } else { |
201 if (m_iPrevValEqual > 0) { | 201 if (m_iPrevValEqual > 0) { |
202 // Draw previous point | 202 // Draw previous point |
203 PlotDataPointDirect(m_fPrevX, m_fPrevY, m_fPrevVal, m_fPrevHeight); | 203 PlotDataPointDirect(m_fPrevX, m_fPrevY, m_fPrevVal, m_fPrevHeight); |
204 } | 204 } |
205 m_iPrevValEqual = 0; | 205 m_iPrevValEqual = 0; |
206 m_fPrevVal = val; | 206 m_fPrevVal = val; |
207 m_bFirstPoint = false; | 207 m_bFirstPoint = false; |
208 } | 208 } |
209 PlotDataPointDirect(x, y, val, height); | 209 PlotDataPointDirect(x, y, val, height); |
210 } | 210 } |
211 | 211 |
212 void GraphicsView::PlotDataPointDirect(float x, | 212 void GraphicsView::PlotDataPointDirect(float x, |
213 float y, | 213 float y, |
214 float val, | 214 float val, |
215 float height) { | 215 float height) { |
216 // Draw it in the right way | 216 // Draw it in the right way |
217 switch(m_iGraphType) { | 217 switch(m_iGraphType) { |
218 case GraphTypeLine: | 218 case GraphTypeLine: |
219 m_pDev->gVertex2f(x, y + val * height); | 219 m_pDev->gVertex2f(x, y + val * height); |
220 break; | 220 break; |
221 case GraphTypeColormap: | 221 case GraphTypeColormap: |
222 //! \todo make it a real colormap instead of grayscale | 222 //! \todo make it a real colormap instead of grayscale |
223 m_pDev->gColor3f(val + 0.5, val + 0.5, val + 0.5); | 223 m_pDev->gColor3f(val + 0.5, val + 0.5, val + 0.5); |
224 m_pDev->gVertex2f(x, y - height / 2); | 224 m_pDev->gVertex2f(x, y - height / 2); |
225 m_pDev->gVertex2f(x, y + height / 2); | 225 m_pDev->gVertex2f(x, y + height / 2); |
226 break; | 226 break; |
227 case GraphTypeNone: | 227 case GraphTypeNone: |
228 // Nothing: just for testing computation overhead of graphing | 228 // Nothing: just for testing computation overhead of graphing |
229 break; | 229 break; |
230 default: | 230 default: |
231 // Shouldn't happen | 231 // Shouldn't happen |
232 AIM_ASSERT(0); | 232 AIM_ASSERT(0); |
233 } | 233 } |
234 } | 234 } |