20 #include "KChartLeveyJenningsGrid.h" 22 #include "KChartLeveyJenningsDiagram.h" 23 #include "KChartPaintContext.h" 24 #include "KChartPainterSaver_p.h" 25 #include "KChartPrintingParameters.h" 26 #include "KChartMath_p.h" 33 qreal fastPow10(
int x );
37 Q_ASSERT_X ( rawDataDimensions.
count() == 2,
"CartesianGrid::calculateGrid",
38 "Error: calculateGrid() expects a list with exactly two entries." );
41 Q_ASSERT_X ( plane,
"LeveyJenningsGrid::calculateGrid",
42 "Error: PaintContext::calculatePlane() called, but no cartesian plane set." );
48 const QPointF translatedBottomLeft( plane->translateBack( plane->geometry().bottomLeft() ) );
49 const QPointF translatedTopRight( plane->translateBack( plane->geometry().topRight() ) );
51 if ( l.first().isCalculated
52 && plane->autoAdjustGridToZoom()
53 && plane->axesCalcModeX() == CartesianCoordinatePlane::Linear
54 && plane->zoomFactorX() > 1.0 )
56 l.first().start = translatedBottomLeft.x();
57 l.first().end = translatedTopRight.x();
62 if ( dimX.stepWidth ) {
65 = calculateGridXY( l.last(),
Qt::Vertical,
false, false );
67 if ( plane->autoAdjustGridToZoom()
68 && plane->axesCalcModeY() == CartesianCoordinatePlane::Linear
69 && plane->zoomFactorY() > 1.0 )
71 l.last().start = translatedBottomLeft.y();
72 l.last().end = translatedTopRight.y();
76 = calculateGridXY( l.last(),
Qt::Vertical,
false, false );
77 if ( dimY.stepWidth ) {
78 l.first().start = dimX.start;
79 l.first().end = dimX.end;
80 l.first().stepWidth = dimX.stepWidth;
81 l.first().subStepWidth = dimX.subStepWidth;
82 l.last().start = minMaxY.start;
83 l.last().end = minMaxY.end;
84 l.last().stepWidth = dimY.stepWidth;
89 if ( dimY.subStepWidth == 0 )
90 l.last().subStepWidth = dimY.stepWidth/2;
92 l.last().subStepWidth = dimY.subStepWidth;
102 #if defined ( Q_WS_WIN) 103 #define trunc(x) ((int)(x)) 109 bool adjustLower,
bool adjustUpper )
const 112 if ( dim.isCalculated && dim.start != dim.end ) {
114 if ( dim.stepWidth == 0.0 ) {
116 switch ( dim.sequence ) {
117 case KChartEnums::GranularitySequence_10_20:
118 granularities << 1.0 << 2.0;
120 case KChartEnums::GranularitySequence_10_50:
121 granularities << 1.0 << 5.0;
123 case KChartEnums::GranularitySequence_25_50:
124 granularities << 2.5 << 5.0;
126 case KChartEnums::GranularitySequence_125_25:
127 granularities << 1.25 << 2.5;
129 case KChartEnums::GranularitySequenceIrregular:
130 granularities << 1.0 << 1.25 << 2.0 << 2.5 << 5.0;
135 dim.start, dim.end, granularities, orientation,
136 dim.stepWidth, dim.subStepWidth,
137 adjustLower, adjustUpper );
142 dim.stepWidth = dim.stepWidth ? dim.stepWidth : 1.0;
147 static void calculateSteps(
149 int minSteps,
int maxSteps,
151 qreal& steps, qreal& stepWidth,
152 bool adjustLower,
bool adjustUpper )
159 const int lastIdx = list.
count()-1;
160 for (
int i = 0; i <= lastIdx; ++i ) {
161 const qreal testStepWidth = list.
at(lastIdx - i) * fastPow10( power );
163 qreal start = qMin( start_, end_ );
164 qreal
end = qMax( start_, end_ );
169 const qreal testDistance = qAbs(end - start);
170 const qreal testSteps = testDistance / testStepWidth;
173 if ( (minSteps <= testSteps) && (testSteps <= maxSteps)
174 && ( (steps == 0.0) || (testDistance <= distance) ) ) {
176 stepWidth = testStepWidth;
177 distance = testDistance;
183 void LeveyJenningsGrid::calculateStepWidth(
184 qreal start_, qreal end_,
187 qreal& stepWidth, qreal& subStepWidth,
188 bool adjustLower,
bool adjustUpper )
const 190 Q_UNUSED( orientation );
192 Q_ASSERT_X ( granularities.
count(),
"CartesianGrid::calculateStepWidth",
193 "Error: The list of GranularitySequence values is empty." );
195 std::sort(list.
begin(), list.
end());
197 const qreal start = qMin( start_, end_);
198 const qreal end = qMax( start_, end_);
199 const qreal distance = end - start;
203 const int minSteps = 2;
204 const int maxSteps = 12;
208 while ( list.
last() * fastPow10( power ) < distance ) {
213 const int count = list.
count();
215 for (
int i = 0; i < count; ++i )
216 testList << list.
at(i) * 0.1;
221 calculateSteps( start, end, testList, minSteps, maxSteps, power,
223 adjustLower, adjustUpper );
225 }
while ( steps == 0.0 );
232 if ( subStepWidth == 0.0 ) {
233 if ( stepWidth == list.first() * fastPow10( power ) ) {
234 subStepWidth = list.last() * fastPow10( power-1 );
236 }
else if ( stepWidth == list.first() * fastPow10( power-1 ) ) {
237 subStepWidth = list.last() * fastPow10( power-2 );
240 qreal smallerStepWidth = list.first();
241 for (
int i = 1; i < list.count(); ++i ) {
242 if ( stepWidth == list.at( i ) * fastPow10( power ) ) {
243 subStepWidth = smallerStepWidth * fastPow10( power );
246 if ( stepWidth == list.at( i ) * fastPow10( power-1 ) ) {
247 subStepWidth = smallerStepWidth * fastPow10( power-1 );
250 smallerStepWidth = list.at( i );
262 PainterSaver p( context->painter() );
264 mPlane->sharedAxisMasterPlane( context->painter() ) );
265 Q_ASSERT_X ( plane,
"LeveyJenningsGrid::drawGrid",
266 "Bad function call: PaintContext::coodinatePlane() NOT a Levey Jennings plane." );
279 Q_ASSERT_X ( mDataDimensions.
count() == 2,
"CartesianGrid::drawGrid",
280 "Error: updateData did not return exactly two dimensions." );
290 if ( dimX.start == 0.0 && dimX.end == 0.0 )
291 dimX.end += plane->geometry().width();
304 QPointF topLeft = plane->translate(
QPointF( dimX.start, meanValue - 2 * standardDeviation ) );
305 QPointF bottomRight = plane->translate(
QPointF( dimX.end, meanValue + 2 * standardDeviation ) );
306 context->painter()->
fillRect(
QRectF( topLeft,
QSizeF( bottomRight.
x() - topLeft.
x(), bottomRight.
y() - topLeft.
y() ) ),
307 gridAttrs.rangeBrush( LeveyJenningsGridAttributes::NormalRange ) );
310 topLeft = plane->translate(
QPointF( dimX.start, meanValue + 2 * standardDeviation ) );
311 bottomRight = plane->translate(
QPointF( dimX.end, meanValue + 3 * standardDeviation ) );
312 context->painter()->
fillRect(
QRectF( topLeft,
QSizeF( bottomRight.
x() - topLeft.
x(), bottomRight.
y() - topLeft.
y() ) ),
313 gridAttrs.rangeBrush( LeveyJenningsGridAttributes::CriticalRange ) );
315 topLeft = plane->translate(
QPointF( dimX.start, meanValue - 2 * standardDeviation ) );
316 bottomRight = plane->translate(
QPointF( dimX.end, meanValue - 3 * standardDeviation ) );
317 context->painter()->
fillRect(
QRectF( topLeft,
QSizeF( bottomRight.
x() - topLeft.
x(), bottomRight.
y() - topLeft.
y() ) ),
318 gridAttrs.rangeBrush( LeveyJenningsGridAttributes::CriticalRange ) );
321 topLeft = plane->translate(
QPointF( dimX.start, meanValue + 3 * standardDeviation ) );
322 bottomRight = plane->translate(
QPointF( dimX.end, meanValue + 4 * standardDeviation ) );
323 context->painter()->
fillRect(
QRectF( topLeft,
QSizeF( bottomRight.
x() - topLeft.
x(), bottomRight.
y() - topLeft.
y() ) ),
324 gridAttrs.rangeBrush( LeveyJenningsGridAttributes::OutOfRange ) );
326 topLeft = plane->translate(
QPointF( dimX.start, meanValue - 3 * standardDeviation ) );
327 bottomRight = plane->translate(
QPointF( dimX.end, meanValue - 4 * standardDeviation ) );
328 context->painter()->
fillRect(
QRectF( topLeft,
QSizeF( bottomRight.
x() - topLeft.
x(), bottomRight.
y() - topLeft.
y() ) ),
329 gridAttrs.rangeBrush( LeveyJenningsGridAttributes::OutOfRange ) );
332 if ( gridAttrs.isGridVisible( LeveyJenningsGridAttributes::Expected ) )
334 context->painter()->
setPen( gridAttrs.gridPen( LeveyJenningsGridAttributes::Expected ) );
335 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, meanValue ) ),
336 plane->translate(
QPointF( dimX.end, meanValue ) ) );
337 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, meanValue + 2 * standardDeviation ) ),
338 plane->translate(
QPointF( dimX.end, meanValue + 2 * standardDeviation ) ) );
339 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, meanValue + 3 * standardDeviation ) ),
340 plane->translate(
QPointF( dimX.end, meanValue + 3 * standardDeviation ) ) );
341 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, meanValue + 4 * standardDeviation ) ),
342 plane->translate(
QPointF( dimX.end, meanValue + 4 * standardDeviation ) ) );
343 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, meanValue - 2 * standardDeviation ) ),
344 plane->translate(
QPointF( dimX.end, meanValue - 2 * standardDeviation ) ) );
345 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, meanValue - 3 * standardDeviation ) ),
346 plane->translate(
QPointF( dimX.end, meanValue - 3 * standardDeviation ) ) );
347 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, meanValue - 4 * standardDeviation ) ),
348 plane->translate(
QPointF( dimX.end, meanValue - 4 * standardDeviation ) ) );
352 if ( gridAttrs.isGridVisible( LeveyJenningsGridAttributes::Calculated ) )
354 context->painter()->
setPen( gridAttrs.gridPen( LeveyJenningsGridAttributes::Calculated ) );
355 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, calcMeanValue ) ),
356 plane->translate(
QPointF( dimX.end, calcMeanValue ) ) );
357 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, calcMeanValue + 2 * calcStandardDeviation ) ),
358 plane->translate(
QPointF( dimX.end, calcMeanValue + 2 * calcStandardDeviation ) ) );
359 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, calcMeanValue + 3 * calcStandardDeviation ) ),
360 plane->translate(
QPointF( dimX.end, calcMeanValue + 3 * calcStandardDeviation ) ) );
361 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, calcMeanValue - 2 * calcStandardDeviation ) ),
362 plane->translate(
QPointF( dimX.end, calcMeanValue - 2 * calcStandardDeviation ) ) );
363 context->painter()->
drawLine( plane->translate(
QPointF( dimX.start, calcMeanValue - 3 * calcStandardDeviation ) ),
364 plane->translate(
QPointF( dimX.end, calcMeanValue - 3 * calcStandardDeviation ) ) );
Helper class for one dimension of data, e.g.
Levey Jennings coordinate plane This is actually nothing real more than a plain cartesian coordinate ...
void fillRect(const QRectF &rectangle, const QBrush &brush)
static bool isBoundariesValid(const QRectF &r)
Checks whether both coordinates of r are valid according to isValueValid.
LeveyDiagram defines a Levey Jennings chart.
const T & at(int i) const const
void drawLine(const QLineF &line)
int count(const T &value) const const
void drawGrid(PaintContext *context) override
Doing the actual drawing.
Stores information about painting diagrams.
void setPen(const QColor &color)
DataDimensionsList updateData(AbstractCoordinatePlane *plane)
Returns the cached result of data calculation.
float calculatedMeanValue() const
Returns the calculated mean values over all QC values.
A set of attributes controlling the appearance of grids.
int distance(const GeoCoordinates &coord1, const GeoCoordinates &coord2)
static void adjustLowerUpperRange(qreal &start, qreal &end, qreal stepWidth, bool adjustLower, bool adjustUpper)
Adjusts start and/or end so that they are a multiple of stepWidth.
const QList< QKeySequence > & end()
float calculatedStandardDeviation() const
Returns the calculated standard deviation over all QC values.
float expectedStandardDeviation() const
Returns the expected standard deviation over all QC values.
float expectedMeanValue() const
Returns the expected mean values over all QC values.