annotate src/Modules/Output/Graphics/GraphicsView.cc @ 227:73c6d61440ad

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