Mercurial > hg > svgui
comparison layer/Colour3DPlotLayer.cpp @ 98:2be85befe873
* Reorder plugin output querying so as to cope with plugins whose number of
values per output varies depending on the initialise parameters
* Make the colour 3D plot layer tolerably efficient with very dense models
* Allow export of colour 3D plot layers
author | Chris Cannam |
---|---|
date | Wed, 10 May 2006 16:34:03 +0000 |
parents | 45ba0b381c5d |
children | 571805759a66 |
comparison
equal
deleted
inserted
replaced
97:a0e7edf9703a | 98:2be85befe873 |
---|---|
117 int | 117 int |
118 Colour3DPlotLayer::getVerticalScaleWidth(View *v, QPainter &paint) const | 118 Colour3DPlotLayer::getVerticalScaleWidth(View *v, QPainter &paint) const |
119 { | 119 { |
120 if (!m_model) return 0; | 120 if (!m_model) return 0; |
121 | 121 |
122 QString sampleText("123"); | 122 QString sampleText = QString("[%1]").arg(m_model->getYBinCount()); |
123 int tw = paint.fontMetrics().width(sampleText); | 123 int tw = paint.fontMetrics().width(sampleText); |
124 bool another = false; | |
124 | 125 |
125 for (size_t i = 0; i < m_model->getYBinCount(); ++i) { | 126 for (size_t i = 0; i < m_model->getYBinCount(); ++i) { |
126 if (m_model->getBinName(i).length() > sampleText.length()) { | 127 if (m_model->getBinName(i).length() > sampleText.length()) { |
127 sampleText = m_model->getBinName(i); | 128 sampleText = m_model->getBinName(i); |
129 another = true; | |
128 } | 130 } |
129 } | 131 } |
130 if (sampleText != "123") { | 132 if (another) { |
131 tw = std::max(tw, paint.fontMetrics().width(sampleText)); | 133 tw = std::max(tw, paint.fontMetrics().width(sampleText)); |
132 } | 134 } |
133 | 135 |
134 return tw + 13; | 136 return tw + 13; |
135 } | 137 } |
140 if (!m_model) return; | 142 if (!m_model) return; |
141 | 143 |
142 int h = rect.height(), w = rect.width(); | 144 int h = rect.height(), w = rect.width(); |
143 float binHeight = float(v->height()) / m_model->getYBinCount(); | 145 float binHeight = float(v->height()) / m_model->getYBinCount(); |
144 | 146 |
145 // int textHeight = paint.fontMetrics().height(); | 147 int count = v->height() / paint.fontMetrics().height(); |
146 // int toff = -textHeight + paint.fontMetrics().ascent() + 2; | 148 int step = m_model->getYBinCount() / count; |
149 if (step == 0) step = 1; | |
147 | 150 |
148 for (size_t i = 0; i < m_model->getYBinCount(); ++i) { | 151 for (size_t i = 0; i < m_model->getYBinCount(); ++i) { |
152 | |
153 if ((i % step) != 0) continue; | |
149 | 154 |
150 int y0 = v->height() - (i * binHeight) - 1; | 155 int y0 = v->height() - (i * binHeight) - 1; |
151 | 156 |
152 QString text = m_model->getBinName(i); | 157 QString text = m_model->getBinName(i); |
153 if (text == "") text = QString("[%1]").arg(i + 1); | 158 if (text == "") text = QString("[%1]").arg(i + 1); |
154 | 159 |
155 paint.drawLine(0, y0, w, y0); | 160 paint.drawLine(0, y0, w, y0); |
156 | 161 |
157 int cy = y0 - binHeight/2; | 162 int cy = y0 - (step * binHeight)/2; |
158 int ty = cy + paint.fontMetrics().ascent()/2; | 163 int ty = cy + paint.fontMetrics().ascent()/2; |
159 | 164 |
160 // int tx = w - 10 - paint.fontMetrics().width(text); | |
161 paint.drawText(10, ty, text); | 165 paint.drawText(10, ty, text); |
162 } | 166 } |
163 } | 167 } |
164 | 168 |
165 void | 169 void |
186 10, QColor(120, 120, 120)); | 190 10, QColor(120, 120, 120)); |
187 } | 191 } |
188 return; | 192 return; |
189 } | 193 } |
190 | 194 |
191 long startFrame = v->getStartFrame(); | |
192 int zoomLevel = v->getZoomLevel(); | |
193 | |
194 size_t modelStart = m_model->getStartFrame(); | 195 size_t modelStart = m_model->getStartFrame(); |
195 size_t modelEnd = m_model->getEndFrame(); | 196 size_t modelEnd = m_model->getEndFrame(); |
196 size_t modelWindow = m_model->getWindowSize(); | 197 size_t modelWindow = m_model->getWindowSize(); |
197 | 198 |
198 size_t cacheWidth = (modelEnd - modelStart) / modelWindow + 1; | 199 size_t cacheWidth = (modelEnd - modelStart) / modelWindow + 1; |
210 | 211 |
211 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8); | 212 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8); |
212 | 213 |
213 m_cache->setNumColors(256); | 214 m_cache->setNumColors(256); |
214 DenseThreeDimensionalModel::BinValueSet values; | 215 DenseThreeDimensionalModel::BinValueSet values; |
215 /* | |
216 for (int pixel = 0; pixel < 256; ++pixel) { | |
217 int hue = 256 - pixel; | |
218 // int hue = 220 - pixel; | |
219 // if (hue < 0) hue += 360; | |
220 QColor color = QColor::fromHsv(hue, pixel/2 + 128, pixel); | |
221 m_cache->setColor(pixel, qRgb(color.red(), color.green(), color.blue())); | |
222 } | |
223 */ | |
224 | 216 |
225 float min = m_model->getMinimumLevel(); | 217 float min = m_model->getMinimumLevel(); |
226 float max = m_model->getMaximumLevel(); | 218 float max = m_model->getMaximumLevel(); |
227 | 219 |
228 if (max == min) max = min + 1.0; | 220 if (max == min) max = min + 1.0; |
229 | 221 |
230 // int min = lrintf(m_model->getMinimumLevel()); | |
231 // int max = lrintf(m_model->getMaximumLevel()); | |
232 for (int value = 0; value < 256; ++value) { | 222 for (int value = 0; value < 256; ++value) { |
233 // int spread = ((value - min) * 256) / (max - min); | |
234 // int hue = 256 - spread; | |
235 // QColor color = QColor::fromHsv(hue, spread/2 + 128, spread); | |
236 int hue = 256 - value; | 223 int hue = 256 - value; |
237 QColor colour = QColor::fromHsv(hue, value/2 + 128, value); | 224 QColor colour = QColor::fromHsv(hue, value/2 + 128, value); |
238 m_cache->setColor(value, qRgba(colour.red(), colour.green(), colour.blue(), 80)); | 225 m_cache->setColor(value, qRgba(colour.red(), colour.green(), colour.blue(), 80)); |
239 // std::cerr << "Colour3DPlotLayer: Index " << value << ": hue " << hue << std::endl; | |
240 } | 226 } |
241 | 227 |
242 m_cache->fill(min); | 228 m_cache->fill(min); |
243 | 229 |
244 for (size_t f = modelStart; f <= modelEnd; f += modelWindow) { | 230 for (size_t f = modelStart; f <= modelEnd; f += modelWindow) { |
249 for (size_t y = 0; y < m_model->getYBinCount(); ++y) { | 235 for (size_t y = 0; y < m_model->getYBinCount(); ++y) { |
250 | 236 |
251 float value = min; | 237 float value = min; |
252 if (y < values.size()) value = values[y]; | 238 if (y < values.size()) value = values[y]; |
253 | 239 |
254 //!!! divide-by-zero! | |
255 int pixel = int(((value - min) * 256) / (max - min)); | 240 int pixel = int(((value - min) * 256) / (max - min)); |
256 | 241 if (pixel < 0) pixel = 0; |
257 if (pixel == 256) pixel = 255; | 242 if (pixel > 255) pixel = 255; |
258 | 243 |
259 m_cache->setPixel(f / modelWindow, y, pixel); | 244 m_cache->setPixel(f / modelWindow, y, pixel); |
260 } | 245 } |
261 } | 246 } |
262 } | 247 } |
263 | 248 |
249 if (m_model->getYBinCount() >= v->height()) { | |
250 paintDense(v, paint, rect); | |
251 return; | |
252 } | |
253 | |
264 int x0 = rect.left(); | 254 int x0 = rect.left(); |
265 int x1 = rect.right() + 1; | 255 int x1 = rect.right() + 1; |
266 | 256 |
267 // int y0 = rect.top(); | |
268 // int y1 = rect.bottom(); | |
269 int w = x1 - x0; | 257 int w = x1 - x0; |
270 int h = v->height(); | 258 int h = v->height(); |
271 | 259 |
272 // The cache is from the model's start frame to the model's end | 260 // The cache is from the model's start frame to the model's end |
273 // frame at the model's window increment frames per pixel. We | 261 // frame at the model's window increment frames per pixel. We |
307 if (w < 1) w = 1; | 295 if (w < 1) w = 1; |
308 | 296 |
309 bool showLabel = (w > 10 && | 297 bool showLabel = (w > 10 && |
310 paint.fontMetrics().width("0.000000") < w - 3 && | 298 paint.fontMetrics().width("0.000000") < w - 3 && |
311 paint.fontMetrics().height() < (h / sh)); | 299 paint.fontMetrics().height() < (h / sh)); |
312 | 300 |
313 for (int sy = 0; sy < sh; ++sy) { | 301 for (int sy = 0; sy < sh; ++sy) { |
314 | 302 |
315 int ry0 = h - (sy * h) / sh - 1; | 303 int ry0 = h - (sy * h) / sh - 1; |
316 int ry1 = h - ((sy + 1) * h) / sh - 2; | |
317 QRgb pixel = qRgb(255, 255, 255); | 304 QRgb pixel = qRgb(255, 255, 255); |
318 if (sx >= 0 && sx < m_cache->width() && | 305 if (sx >= 0 && sx < m_cache->width() && |
319 sy >= 0 && sy < m_cache->height()) { | 306 sy >= 0 && sy < m_cache->height()) { |
320 pixel = m_cache->pixel(sx, sy); | 307 pixel = m_cache->pixel(sx, sy); |
321 } | 308 } |
340 paint.drawRect(r); | 327 paint.drawRect(r); |
341 | 328 |
342 if (showLabel) { | 329 if (showLabel) { |
343 if (sx >= 0 && sx < m_cache->width() && | 330 if (sx >= 0 && sx < m_cache->width() && |
344 sy >= 0 && sy < m_cache->height()) { | 331 sy >= 0 && sy < m_cache->height()) { |
345 int dv = m_cache->pixelIndex(sx, sy); | |
346 float value = m_model->getBinValue(fx, sy); | 332 float value = m_model->getBinValue(fx, sy); |
347 sprintf(labelbuf, "%06f", value); | 333 sprintf(labelbuf, "%06f", value); |
348 QString text(labelbuf); | 334 QString text(labelbuf); |
349 paint.setPen(Qt::white); | 335 paint.setPen(Qt::white); |
350 paint.drawText(rx0 + 2, | 336 paint.drawText(rx0 + 2, |
352 text); | 338 text); |
353 } | 339 } |
354 } | 340 } |
355 } | 341 } |
356 } | 342 } |
357 | 343 } |
358 /* | 344 |
359 QRect targetRect(x0, 0, w, h); | 345 void |
360 QRect sourceRect(sx0, 0, sw, sh); | 346 Colour3DPlotLayer::paintDense(View *v, QPainter &paint, QRect rect) const |
361 | 347 { |
362 QImage scaled(w, h, QImage::Format_RGB32); | 348 long startFrame = v->getStartFrame(); |
363 | 349 int zoomLevel = v->getZoomLevel(); |
364 for (int x = 0; x < w; ++x) { | 350 |
365 for (int y = 0; y < h; ++y) { | 351 size_t modelStart = m_model->getStartFrame(); |
366 | 352 size_t modelEnd = m_model->getEndFrame(); |
367 | 353 size_t modelWindow = m_model->getWindowSize(); |
368 | 354 |
369 int sx = sx0 + (x * sw) / w; | 355 int x0 = rect.left(); |
370 int sy = sh - (y * sh) / h - 1; | 356 int x1 = rect.right() + 1; |
371 // std::cerr << "Colour3DPlotLayer::paint: sx " << sx << ", sy " << sy << ", cache w " << m_cache->width() << ", cache h " << m_cache->height() << std::endl; | 357 |
372 if (sx >= 0 && sy >= 0 && | 358 int w = x1 - x0; |
373 sx < m_cache->width() && sy < m_cache->height()) { | 359 int h = v->height(); |
374 scaled.setPixel(x, y, m_cache->pixel(sx, sy)); | 360 int sh = m_model->getYBinCount(); |
375 } else { | 361 |
376 scaled.setPixel(x, y, qRgba(255, 255, 255, 80)); | 362 QImage img(w, h, QImage::Format_RGB32); |
377 } | 363 |
378 } | 364 for (int x = x0; x < x1; ++x) { |
379 } | 365 |
380 | 366 float sx0 = (float(v->getFrameForX(x)) - modelStart) / modelWindow; |
381 paint.drawImage(x0, 0, scaled); | 367 float sx1 = (float(v->getFrameForX(x+1)) - modelStart) / modelWindow; |
382 */ | 368 |
369 int sx0i = int(sx0 + 0.001); | |
370 int sx1i = int(sx1); | |
371 | |
372 for (int y = 0; y < h; ++y) { | |
373 | |
374 float sy0 = (float(h - y - 1) * sh) / h; | |
375 float sy1 = (float(h - y) * sh) / h; | |
376 | |
377 int sy0i = int(sy0 + 0.001); | |
378 int sy1i = int(sy1); | |
379 | |
380 float mag = 0.0, div = 0.0; | |
381 | |
382 for (int sx = sx0i; sx <= sx1i; ++sx) { | |
383 | |
384 if (sx < 0 || sx >= m_cache->width()) continue; | |
385 | |
386 for (int sy = sy0i; sy <= sy1i; ++sy) { | |
387 | |
388 if (sy < 0 || sy >= m_cache->height()) continue; | |
389 | |
390 float prop = 1.0; | |
391 if (sx == sx0i) prop *= (sx + 1) - sx0; | |
392 if (sx == sx1i) prop *= sx1 - sx; | |
393 if (sy == sy0i) prop *= (sy + 1) - sy0; | |
394 if (sy == sy1i) prop *= sy1 - sy; | |
395 | |
396 mag += prop * m_cache->pixelIndex(sx, sy); | |
397 div += prop; | |
398 } | |
399 } | |
400 | |
401 if (div != 0) mag /= div; | |
402 if (mag < 0) mag = 0; | |
403 if (mag > 255) mag = 255; | |
404 | |
405 img.setPixel(x - x0, y, m_cache->color(int(mag + 0.001))); | |
406 } | |
407 } | |
408 | |
409 paint.drawImage(x0, 0, img); | |
383 } | 410 } |
384 | 411 |
385 bool | 412 bool |
386 Colour3DPlotLayer::snapToFeatureFrame(View *v, int &frame, | 413 Colour3DPlotLayer::snapToFeatureFrame(View *v, int &frame, |
387 size_t &resolution, | 414 size_t &resolution, |