29#include "KDChartRingPainter.h"
33#include <tqvaluestack.h>
37#define DEGTORAD(d) (d)*M_PI/180
53KDChartPainter( params )
83 uint chart = paint2nd ? 1 : 0;
85 TQRect ourClipRect( _dataRect );
87 const TQWMatrix & world = painter->worldMatrix();
88 ourClipRect = world.mapRect( ourClipRect );
89 ourClipRect.setTop(ourClipRect.top()-1);
90 ourClipRect.setLeft(ourClipRect.left()-1);
91 ourClipRect.setBottom(ourClipRect.bottom()+1);
92 ourClipRect.setRight(ourClipRect.right()+1);
93 painter->setClipRect( ourClipRect );
95 uint datasetStart, datasetEnd;
96 if ( params()->neverUsedSetChartSourceMode()
97 || !params()->findDataset( KDChartParams::DataEntry,
101 uint maxRow, maxRowMinus1;
111 maxRowMinus1 = maxRow - 1;
113 datasetStart = paint2nd ? maxRow
115 datasetEnd = paint2nd ? maxRow
116 : ( ( KDChartParams::NoType
117 == params()->additionalChartType() )
121 uint datasetNum = abs( (
int)( datasetEnd - datasetStart ) + 1 );
126 if ( params()->numValues() != -1 )
127 _numValues = params()->numValues();
132 _size = TQMIN( _dataRect.width(), _dataRect.height() );
135 if ( params()->explode() ) {
136 double doubleSize = ( double ) _size;
137 doubleSize /= ( 1.0 + params()->explodeFactor() * 2 );
138 _size = ( int ) doubleSize;
141 int x = ( _dataRect.width() == _size ) ? 0 : ( ( _dataRect.width() - _size ) / 2 );
142 int y = ( _dataRect.height() == _size ) ? 0 : ( ( _dataRect.height() - _size ) / 2 );
143 _position = TQRect( x, y, _size, _size );
144 _position.moveBy( _dataRect.left(), _dataRect.top() );
148 TQMemArray<double> rowsums;
149 double totalSum = 0.0;
150 rowsums.resize( datasetEnd+1 );
151 for(
int d1 = (
int)datasetStart; d1 <= (int)datasetEnd; d1++ ) {
152 rowsums[d1] = data->rowAbsSum( d1 );
153 totalSum += rowsums[d1];
156 TQMemArray<int> ringthicknesses;
157 ringthicknesses.resize( datasetEnd+1 );
160 int ringthickness = _size / ( datasetNum * 2 );
163 if( ringthickness > ( _size/10 ) )
164 ringthickness = _size / 10;
166 for(
int d2 = (
int)datasetStart; d2 <= (int)datasetEnd; d2++ )
167 if( params()->relativeRingThickness() ) {
170 ringthicknesses[d2] = (uint)floor( (rowsums[d2] / totalSum) *
171 ( 2.0 * (
double)ringthickness ) + 0.5 );
173 ringthicknesses[d2] = ringthickness;
176 int currentouterradius = _size/2;
179 for(
int dataset = (
int)datasetStart; dataset <= (int)datasetEnd; dataset++ ) {
180 double sectorsPerValue = 5760.0 / rowsums[dataset];
182 double currentstartpos = (double)params()->ringStart() * 16.0;
185 for(
int value = 0; value < _numValues; value++ ) {
187 double cellValue = 0.0;
188 if( data->
cellCoord( dataset, value, vValY, 1 ) &&
189 TQVariant::Double == vValY.type() ){
190 cellValue = fabs( vValY.toDouble() );
196 TQValueList<int> explodeList = params()->explodeValues();
197 bool explode = params()->explode() &&
198 ( dataset == (int)datasetStart ) &&
199 ( ( explodeList.count() == 0 ) ||
200 ( explodeList.find( value ) != explodeList.end() ) );
202 drawOneSegment( painter,
204 currentouterradius-ringthicknesses[dataset],
206 sectorsPerValue * cellValue,
207 dataset, value, chart, explode, regions );
209 currentstartpos += sectorsPerValue * cellValue;
211 currentouterradius -= ringthicknesses[dataset];
217void KDChartRingPainter::drawOneSegment( TQPainter* painter,
229 if( angles == 5760.0 )
232 painter->setPen( TQPen( params()->outlineDataColor(),
233 params()->outlineDataLineWidth() ) );
234 painter->setBrush( params()->dataColor( value ) );
236 uint outerRadius2 = outerRadius * 2;
237 uint innerRadius2 = innerRadius * 2;
239 TQRect drawPosition = _position;
242 double explodeAngle = ( startAngle + angles / 2.0 ) / 16.0;
243 double explodeAngleRad = DEGTORAD( explodeAngle );
244 double cosAngle = cos( explodeAngleRad );
245 double sinAngle = -sin( explodeAngleRad );
248 double explodeFactor = 0.0;
250 if( !explodeFactors.contains( value ) )
253 explodeFactor = explodeFactors[value];
255 double explodeX = explodeFactor * _size * cosAngle;
256 double explodeY = explodeFactor * _size * sinAngle;
257 drawPosition.moveBy(
static_cast<int>( explodeX ),
static_cast<int>( explodeY ) );
260 TQRect outerRect( drawPosition.x() +
261 ( drawPosition.width() - outerRadius2 ) / 2,
263 ( drawPosition.height() - outerRadius2 ) / 2,
264 outerRadius2, outerRadius2 );
265 TQRect innerRect( drawPosition.x() +
266 ( drawPosition.width() - innerRadius2 ) / 2,
268 ( drawPosition.height() - innerRadius2 ) / 2,
269 innerRadius2, innerRadius2 );
272 TQPointArray innerArc;
273 makeArc( innerArc, innerRect, startAngle, angles );
276 TQPointArray outerArc;
277 makeArc( outerArc, outerRect, startAngle, angles );
281 uint innerArcPoints = innerArc.size();
282 uint outerArcPoints = outerArc.size();
283 innerArc.resize( innerArcPoints + outerArcPoints );
284 for (
int i = outerArcPoints - 1; i >= 0; i-- ) {
285 innerArc.setPoint( innerArcPoints+outerArcPoints-i-1,
286 outerArc.point( i ) );
289 painter->drawPolygon( innerArc );
291 KDChartDataRegion* datReg =
new KDChartDataRegion( dataset,
296 const int aA =
static_cast<int>( startAngle );
297 const int aM =
static_cast<int>( startAngle + angles / 2.0 );
298 const int aZ =
static_cast<int>( startAngle + angles );
300 datReg->points[ KDChartEnums::PosTopLeft ]
301 = pointOnCircle( outerRect, aZ );
302 datReg->points[ KDChartEnums::PosTopCenter ]
303 = pointOnCircle( outerRect, aM );
304 datReg->points[ KDChartEnums::PosTopRight ]
305 = pointOnCircle( outerRect, aA );
307 datReg->points[ KDChartEnums::PosBottomLeft ]
308 = pointOnCircle( innerRect, aZ );
309 datReg->points[ KDChartEnums::PosBottomCenter ]
310 = pointOnCircle( innerRect, aM );
311 datReg->points[ KDChartEnums::PosBottomRight ]
312 = pointOnCircle( innerRect, aA );
314 datReg->points[ KDChartEnums::PosCenterLeft ]
315 = TQPoint( ( datReg->points[ KDChartEnums::PosTopLeft ].x()
316 + datReg->points[ KDChartEnums::PosBottomLeft ].x() ) / 2,
317 ( datReg->points[ KDChartEnums::PosTopLeft ].y()
318 + datReg->points[ KDChartEnums::PosBottomLeft ].y() ) / 2 );
319 datReg->points[ KDChartEnums::PosCenter ]
320 = TQPoint( ( datReg->points[ KDChartEnums::PosTopCenter ].x()
321 + datReg->points[ KDChartEnums::PosBottomCenter ].x() ) / 2,
322 ( datReg->points[ KDChartEnums::PosTopCenter ].y()
323 + datReg->points[ KDChartEnums::PosBottomCenter ].y() ) / 2 );
324 datReg->points[ KDChartEnums::PosCenterRight ]
325 = TQPoint( ( datReg->points[ KDChartEnums::PosTopRight ].x()
326 + datReg->points[ KDChartEnums::PosBottomRight ].x() ) / 2,
327 ( datReg->points[ KDChartEnums::PosTopRight ].y()
328 + datReg->points[ KDChartEnums::PosBottomRight ].y() ) / 2 );
356 datReg->startAngle =
static_cast<int>( startAngle );
357 datReg->angleLen =
static_cast<int>( angles );
358 regions->append( datReg );
378 return TQObject::tr(
"Item " ) + TQString::number( dataset + 1 );
Header for all common chart parameters.
The collection class used by KD Chart to store data region information.
Bundles the display parameters of a chart.
ExplodeFactorsMap explodeFactors() const
Returns the list of explode factors.
double explodeFactor() const
Returns the default explode factor, i.e., the explode factor used for those segments which should be ...
virtual ~KDChartRingPainter()
Destructor.
virtual void paintData(TQPainter *painter, KDChartTableDataBase *data, bool paint2nd, KDChartDataRegionList *regions=0)
Paints the actual data area.
virtual TQString fallbackLegendText(uint dataset) const
This method is a specialization that returns a fallback legend text appropriate for rings where the f...
KDChartRingPainter(KDChartParams *params)
Constructor.
virtual uint numLegendFallbackTexts(KDChartTableDataBase *data) const
This methods returns the number of elements to be shown in the legend in case fallback texts are used...
KD Chart's build-in table data for an easy way of storing data values.
virtual uint usedCols() const
Returns the number of cols in the table that actually contain data.
virtual bool cellCoord(uint _row, uint _col, TQVariant &_value, int coordinate=1) const =0
Returns one of the coordinate data value(s) stored in a cell.
virtual uint usedRows() const
Returns the number of rows in the table that actually contain data.