Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
QtHistogramWidget.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 // Based on QtHistogram by hc
43 
44 #include "QtHistogramWidget.hh"
45 
46 #include <QPainter>
47 
48 namespace ACG {
49 namespace QtWidgets {
50 
51 QtHistogramWidget::QtHistogramWidget(QWidget *parent)
52  : QWidget(parent),
53  color_(QColor::fromRgbF(0.518, 0.573, 0.643, 1.0))
54 {}
55 
56 QtHistogramWidget::~QtHistogramWidget() = default;
57 
58 void QtHistogramWidget::setHistogram(std::unique_ptr<Histogram> histogram) {
59  histogram_ = std::move(histogram);
60  this->update();
61 }
62 
63 void QtHistogramWidget::setColorCoder(std::unique_ptr<IColorCoder> color_coder) {
64  color_coder_ = std::move(color_coder);
65  this->update();
66 }
67 
68 void QtHistogramWidget::paintEvent(QPaintEvent *event) {
69  if (!histogram_) {
70  QWidget::paintEvent(event);
71  return;
72  }
73 
74  /*
75  * Analyze histogram/
76  */
77  const std::vector<size_t> &bins = histogram_->getBins();
78  const std::vector<double> &bin_widths = histogram_->getBinWidths();
79  const double total_width = histogram_->getTotalWidth();
80 
81  const size_t hist_max = *std::max_element(bins.begin(), bins.end());
82 
83  /*
84  * Establish regions
85  */
86  const qreal labelHeight = 16;
87  QRectF paint_rect = this->contentsRect();
88  QRectF bargraph_rect = paint_rect;
89  bargraph_rect.setBottom(bargraph_rect.bottom() - labelHeight);
90  QRectF label_rect = paint_rect;
91  label_rect.setTop(bargraph_rect.bottom());
92  QPainter painter(this);
93 
94  /*
95  * Painter attributes.
96  */
97  painter.setRenderHint(QPainter::Antialiasing);
98  painter.setFont(this->font());
99 
100  const qreal avg_width = bargraph_rect.width() / bins.size();
101  const qreal gap = (avg_width > 8) ? 1.0 : 0.0;
102  const qreal label_gap = 4;
103  const qreal y_scale = bargraph_rect.height() / hist_max;
104 
105  const qreal total_gap = (bins.size() - 1) * gap;
106  const qreal total_barwidth = bargraph_rect.width() - total_gap;
107 
108  QRectF barRect;
109  /*
110  * Draw.
111  */
112  double cumulative_width = 0.0;
113  qreal xpos = 0;
114  qreal lastLabelX = label_rect.left();
115  const size_t n_bins = bins.size();
116  for (size_t idx = 0; idx < n_bins; ++idx) {
117  const double bin_width = bin_widths[idx];
118  const qreal bar_width = total_barwidth * (bin_width / total_width);
119  // Bar
120  painter.setPen(Qt::NoPen);
121  // relative position t in [0..1] for the middle of the current bin
122  const double t = (cumulative_width + bin_width/2) / total_width;
123  cumulative_width += bin_width;
124 
125  painter.setBrush(getColor(t));
126 
127  barRect.setWidth(bar_width - gap);
128  barRect.setHeight(y_scale * bins[idx]);
129  barRect.moveBottomLeft(bargraph_rect.bottomLeft() + QPoint(xpos, 0));
130 
131  if (gap > 0.0)
132  painter.drawRoundedRect(barRect, 3, 3, Qt::AbsoluteSize);
133  else
134  painter.drawRect(barRect);
135 
136  // Label
137  painter.setPen(Qt::black);
138  qreal labelX = 0;
139  QString labelText;
140  switch (histogram_->getLabelType()) {
141  case Histogram::LabelType::PerBin:
142  labelX = barRect.center().x();
143  labelText = histogram_->getBinLabel(idx);
144  break;
145  case Histogram::LabelType::PerBoundary:
146  labelX = barRect.x();
147  labelText = histogram_->getBoundaryLabel(idx);
148  break;
149  }
150  QRectF labelBB = painter.boundingRect(
151  QRectF(labelX - (label_distance_/2), label_rect.y(),
152  label_distance_, label_rect.height()),
153  Qt::AlignHCenter | Qt::AlignBottom, labelText);
154 
155  if (labelBB.left() >= lastLabelX + label_gap) {
156  painter.drawText(labelBB, Qt::AlignHCenter | Qt::AlignBottom,
157  labelText);
158  lastLabelX = labelBB.right();
159  }
160  xpos += bar_width;
161  }
162  // TODO: draw last perBoundary label?
163 }
164 
165 
166 
167 QColor QtHistogramWidget::getColor(double val)
168 {
169  if (color_coder_) {
170  return color_coder_->color_qcolor(val);
171  } else {
172  return color_;
173  }
174 }
175 
176 }
177 }
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51