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,