001: /***********************************************************************************************
002: * Copyright 2002 (C) Nathaniel G. Auvil. All Rights Reserved.
003: *
004: * Redistribution and use of this software and associated documentation ("Software"), with or
005: * without modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain copyright statements and notices.
008: * Redistributions must also contain a copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
011: * conditions and the following disclaimer in the documentation and/or other materials
012: * provided with the distribution.
013: *
014: * 3. The name "jCharts" or "Nathaniel G. Auvil" must not be used to endorse or promote
015: * products derived from this Software without prior written permission of Nathaniel G.
016: * Auvil. For written permission, please contact nathaniel_auvil@users.sourceforge.net
017: *
018: * 4. Products derived from this Software may not be called "jCharts" nor may "jCharts" appear
019: * in their names without prior written permission of Nathaniel G. Auvil. jCharts is a
020: * registered trademark of Nathaniel G. Auvil.
021: *
022: * 5. Due credit should be given to the jCharts Project (http://jcharts.sourceforge.net/).
023: *
024: * THIS SOFTWARE IS PROVIDED BY Nathaniel G. Auvil AND CONTRIBUTORS ``AS IS'' AND ANY
025: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
026: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
027: * jCharts OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
028: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
029: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
030: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT LIABILITY, OR TORT
031: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
032: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
033: ************************************************************************************************/package org.krysalis.jcharts.nonAxisChart;
034:
035: import org.krysalis.jcharts.Chart;
036: import org.krysalis.jcharts.chartData.interfaces.IPieChartDataSet;
037: import org.krysalis.jcharts.chartData.processors.PieChartDataProcessor;
038: import org.krysalis.jcharts.imageMap.CircleMapArea;
039: import org.krysalis.jcharts.imageMap.ImageMap;
040: import org.krysalis.jcharts.imageMap.PolyMapArea;
041: import org.krysalis.jcharts.properties.ChartProperties;
042: import org.krysalis.jcharts.properties.LegendAreaProperties;
043: import org.krysalis.jcharts.properties.LegendProperties;
044: import org.krysalis.jcharts.properties.PieChart3DProperties;
045: import org.krysalis.jcharts.test.HTMLChartTestable;
046: import org.krysalis.jcharts.test.HTMLGenerator;
047: import org.krysalis.jcharts.types.PieLabelType;
048:
049: import java.awt.*;
050: import java.awt.font.FontRenderContext;
051: import java.awt.geom.Arc2D;
052: import java.awt.geom.Line2D;
053:
054: /*************************************************************************************
055: * PieChart3D was originally in jCharts 0.2.0 but mysteriously left until 1.0.0
056: *
057: * @author Nathaniel Auvil
058: * @version $Id: PieChart3D.java,v 1.9 2003/09/03 02:39:09 nathaniel_auvil Exp $
059: * @since 1.0.0
060: ************************************************************************************/
061: public class PieChart3D extends Chart implements HTMLChartTestable {
062: private float pieX;
063: private float pieY;
064:
065: private float pie3dWidth;
066: private float pie3dHeight;
067: private static final float RATIO = 0.5f;
068:
069: private float diameter = 0;
070:
071: private IPieChartDataSet iPieChartDataSet;
072: private PieChartDataProcessor pieChartDataProcessor;
073:
074: private PieLabels pieLabels;
075:
076: /************************************************************************************************
077: * Constructor
078: *
079: * @param iPieChartDataSet
080: * @param legendProperties
081: * @param chartProperties general chart properties
082: * @param pixelWidth
083: * @param pixelHeight
084: ************************************************************************************************/
085: public PieChart3D(IPieChartDataSet iPieChartDataSet,
086: LegendProperties legendProperties,
087: ChartProperties chartProperties, int pixelWidth,
088: int pixelHeight) {
089: super (legendProperties, chartProperties, pixelWidth,
090: pixelHeight);
091: this .iPieChartDataSet = iPieChartDataSet;
092: }
093:
094: /************************************************************************************************
095: * Draws the chart
096: *
097: ************************************************************************************************/
098: protected void renderChart() {
099: PieChart3DProperties properties = (PieChart3DProperties) this .iPieChartDataSet
100: .getChartTypeProperties();
101: FontRenderContext fontRenderContext = super .getGraphics2D()
102: .getFontRenderContext();
103:
104: this .pieChartDataProcessor = new PieChartDataProcessor(
105: this .iPieChartDataSet);
106: this .pieChartDataProcessor.processData();
107:
108: //---cache calcs used more than once
109: float edgePaddingTimesTwo = super .getChartProperties()
110: .getEdgePadding() * 2;
111: float halfImageWidth = super .getImageWidth() / 2;
112: float halfImageHeight = super .getImageHeight() / 2;
113:
114: //---render the TITLE. If no title, this will return zero.
115: float chartTitleHeightPlusPadding = super .renderChartTitle(
116: this .iPieChartDataSet.getChartTitle(),
117: fontRenderContext);
118:
119: //---figure out what size is needed to hold all the components of the pie chart, then size the pie accordingly
120: float widthAvailable = super .getImageWidth()
121: - edgePaddingTimesTwo;
122:
123: float heightAvailable = super .getImageHeight()
124: - edgePaddingTimesTwo;
125: heightAvailable -= chartTitleHeightPlusPadding;
126: heightAvailable -= properties.getDepth();
127:
128: //---take labels sizing into consideration if needed.
129: if (!properties.getPieLabelType()
130: .equals(PieLabelType.NO_LABELS)) {
131: this .pieLabels = new PieLabels(properties,
132: this .iPieChartDataSet, fontRenderContext);
133:
134: //---if there is only one item in pie, label will be below plot so width is not a concern
135: if (iPieChartDataSet.getNumberOfDataItems() != 1) {
136: widthAvailable -= this .pieLabels
137: .getWidestLabelTimesTwo();
138: widthAvailable -= (properties.getTickLength() * 2);
139: }
140:
141: heightAvailable -= this .pieLabels.getTallestLabelTimesTwo();
142: heightAvailable -= (properties.getTickLength() * 2);
143: }
144:
145: //---if there is a legend...
146: if (this .getLegend() != null) {
147: float legendX = 0f;
148: float legendY = 0f;
149:
150: //---calculate all the legend rendering coordinates and positions.
151: this .getLegend().calculateDrawingValues(iPieChartDataSet);
152:
153: //---adjust width and height based on the Legend size.
154: if ((this .getLegend().getLegendProperties().getPlacement() == LegendAreaProperties.RIGHT)
155: || (this .getLegend().getLegendProperties()
156: .getPlacement() == LegendAreaProperties.LEFT)) {
157: widthAvailable -= this .getLegend().getWidth();
158: widthAvailable -= this .getLegend()
159: .getLegendProperties().getChartPadding();
160:
161: //---diameter of pie will be at least one pixel, even if the legend takes up the whole image.
162: //---this will keep the renderer from blowing up.
163: this .diameter = Math.max(widthAvailable, 1.0f);
164:
165: //---make sure we do not make the pie diameter taller than the image
166: this .diameter = Math
167: .min(this .diameter, heightAvailable);
168:
169: this .pie3dWidth = this .diameter;
170: this .pie3dHeight = this .pie3dWidth * RATIO;
171:
172: /*
173: this.pie3dWidth= 200;
174: this.pie3dHeight= 200;
175: */
176:
177: //---calculate the entire width of everything to be drawn so can center everything
178: float plotWidth = this .diameter;
179: plotWidth += this .getLegend().getWidth();
180: plotWidth += this .getLegend().getLegendProperties()
181: .getChartPadding();
182: if (this .pieLabels != null) {
183: plotWidth += (this .pieLabels.getWidestLabel() * 2);
184: plotWidth += (properties.getTickLength() * 2);
185: }
186:
187: if (this .getLegend().getLegendProperties()
188: .getPlacement() == LegendAreaProperties.RIGHT) {
189: //---pie's diameter may not fill image width as may be image height constrained.
190: this .pieX = halfImageWidth - (plotWidth / 2);
191:
192: if (this .pieLabels != null) {
193: this .pieX += this .pieLabels.getWidestLabel();
194: this .pieX += properties.getTickLength();
195: legendX += this .pieLabels.getWidestLabel();
196: legendX += properties.getTickLength();
197: }
198:
199: //---position legend based on the pie position
200: legendX += this .pieX + this .diameter;
201: legendX += this .getLegend().getLegendProperties()
202: .getChartPadding();
203: } else {
204: legendX = halfImageWidth - (plotWidth / 2);
205:
206: if (this .pieLabels != null) {
207: this .pieX = legendX;
208: this .pieX += this .getLegend().getWidth();
209: this .pieX += this .getLegend()
210: .getLegendProperties()
211: .getChartPadding();
212: this .pieX += this .pieLabels.getWidestLabel();
213: this .pieX += properties.getTickLength();
214: }
215: }
216:
217: //---center the legend vertically
218: legendY = halfImageHeight
219: - (this .getLegend().getHeight() / 2);
220:
221: //---center the pie vertically
222: this .pieY = halfImageHeight
223: - ((this .pie3dHeight + properties.getDepth()) / 2);
224: }
225: //---else the legend is either under or on top of the pie
226: else {
227: heightAvailable -= this .getLegend().getHeight();
228: heightAvailable -= this .getLegend()
229: .getLegendProperties().getChartPadding();
230:
231: //---diameter of pie will be at least one pixel, even if the legend takes up the whole image.
232: //---this will keep the renderer from blowing up.
233: this .diameter = Math.max(heightAvailable, 1.0f);
234:
235: //---make sure we do not make the pie diameter wider than the image
236: this .diameter = Math.min(this .diameter, widthAvailable);
237:
238: this .pie3dWidth = this .diameter;
239: this .pie3dHeight = this .pie3dWidth * RATIO;
240:
241: if (this .getLegend().getLegendProperties()
242: .getPlacement() == LegendAreaProperties.BOTTOM) {
243: this .pieY = super .getChartProperties()
244: .getEdgePadding();
245: this .pieY += chartTitleHeightPlusPadding;
246:
247: if (this .pieLabels != null) {
248: //---adds label height from top of pie
249: this .pieY += this .pieLabels.getTallestLabel();
250: this .pieY += properties.getTickLength();
251:
252: //---add label hight from bottom of pie
253: legendY += this .pieLabels.getTallestLabel();
254: legendY += properties.getTickLength();
255: }
256:
257: legendY += this .pieY;
258: legendY += this .pie3dHeight;
259: legendY += this .getLegend().getLegendProperties()
260: .getChartPadding();
261: legendY += properties.getDepth();
262: } else {
263: legendY = super .getChartProperties()
264: .getEdgePadding();
265: legendY += chartTitleHeightPlusPadding;
266:
267: this .pieY = legendY;
268: this .pieY += this .getLegend().getHeight();
269: this .pieY += this .getLegend().getLegendProperties()
270: .getChartPadding();
271:
272: if (this .pieLabels != null) {
273: //---adds label height from top of pie
274: this .pieY += this .pieLabels.getTallestLabel();
275: this .pieY += properties.getTickLength();
276: }
277: }
278:
279: //---center the legend horizontally
280: legendX = halfImageWidth
281: - (this .getLegend().getWidth() / 2);
282:
283: //---center the pie horizontally
284: this .pieX = halfImageWidth - (this .diameter / 2);
285: }
286:
287: super .getLegend().setX(legendX);
288: super .getLegend().setY(legendY);
289: super .getLegend().render();
290:
291: }
292: //---else, the Legend is NULL
293: else {
294: //---diameter of pie will be at least one pixel, even if the legend takes up the whole image.
295: //---this will keep the renderer from blowing up.
296: this .diameter = Math.max(widthAvailable, 1.0f);
297:
298: //---make sure we do not make the pie diameter taller than the image
299: this .diameter = Math.min(this .diameter, heightAvailable);
300:
301: this .pie3dWidth = this .diameter;
302: this .pie3dHeight = this .pie3dWidth * RATIO;
303:
304: //---if there is no legend, fill the image with the pie
305: //this.diameter = Math.min( heightAvailable, widthAvailable );
306:
307: float halfDiameter = (this .diameter + properties.getDepth()) / 2;
308:
309: //---center the pie horizontally
310: this .pieX = halfImageWidth - halfDiameter;
311:
312: //---center the pie vertically
313: //this.pieY = halfImageHeight - halfDiameter;
314:
315: this .pieY = halfImageHeight
316: - ((this .pie3dHeight + properties.getDepth()) / 2);
317: }
318:
319: //---IMAGE MAP setup
320: //---if we are saving all the coordinates for an ImageMap, create the ImageMap Object as we
321: //--- know how many area elements there are.
322: if (super .getGenerateImageMapFlag()) {
323: ImageMap imageMap = new ImageMap(iPieChartDataSet
324: .getNumberOfDataItems());
325: super .setImageMap(imageMap);
326: }
327:
328: PieChart3D.render(this );
329: }
330:
331: /************************************************************************************************
332: * Implement the method to render the Chart.
333: *
334: * @param pieChart3D
335: ************************************************************************************************/
336: static void render(PieChart3D pieChart3D) {
337: Graphics2D g2d = pieChart3D.getGraphics2D();
338: PieChart3DProperties properties = (PieChart3DProperties) pieChart3D.iPieChartDataSet
339: .getChartTypeProperties();
340:
341: //---the following only for Image Map-----------------------------
342: //---IMAGE MAP
343: //---number of subdivisions to break each slice into to 'fill' slice
344: int subdivisions = 3;
345: float halfDiameter = 0;
346: float xPieMiddle = 0;
347: float yPieMiddle = 0;
348: float imageMapPoints[][] = null;
349: if (pieChart3D.getImageMap() != null) {
350: halfDiameter = (float) (pieChart3D.diameter / 2.0);
351: xPieMiddle = halfDiameter + pieChart3D.pieX;
352: yPieMiddle = halfDiameter + pieChart3D.pieY;
353: imageMapPoints = new float[pieChart3D.iPieChartDataSet
354: .getNumberOfDataItems()
355: * (subdivisions + 1)][2];
356: }
357:
358: //---get the starting degree
359: float currentDegrees = properties.getZeroDegreeOffset();
360:
361: double percentageOfPie = 0;
362:
363: //---if only one item in chart, just draw border around outside.
364: //---if do a draw of the arc, will get a line in the pie as arc has a start and end.
365: if (pieChart3D.iPieChartDataSet.getNumberOfDataItems() == 1) {
366: Arc2D.Double arc = new Arc2D.Double(pieChart3D.pieX,
367: pieChart3D.pieY + properties.getDepth(),
368: pieChart3D.diameter, pieChart3D.diameter,
369: currentDegrees, 360, Arc2D.OPEN);
370:
371: //---fake 3d loop will slide pie up the image to give illusion of 3D.
372: for (int i = properties.getDepth(); i >= 0; i--) {
373: g2d.setPaint(pieChart3D.iPieChartDataSet.getPaint(0));
374: g2d.fill(arc);
375:
376: if (i == properties.getDepth() || i == 0) {
377: properties.getBorderChartStroke().draw(g2d, arc);
378: }
379:
380: arc.y -= 1;
381: }
382:
383: //---if only a single value use a circle map
384: //---IMAGE MAP
385: if (pieChart3D.getImageMap() != null) {
386: CircleMapArea circleMapArea = new CircleMapArea(
387: xPieMiddle, yPieMiddle,
388: pieChart3D.iPieChartDataSet.getValue(0), null,
389: pieChart3D.iPieChartDataSet.getLegendLabel(0));
390: circleMapArea.setRadius((int) pieChart3D.diameter);
391: pieChart3D.getImageMap().addImageMapArea(circleMapArea);
392: }
393:
394: // System.out.println( pieChart3D.pieLabels.getTextTag( 0 ).getText() );
395:
396: float x = pieChart3D.pieX
397: + (pieChart3D.diameter / 2)
398: - (pieChart3D.pieLabels.getTextTag(0).getWidth() / 2);
399: float y = pieChart3D.pieY - properties.getTickLength();
400: // System.out.println( "x=" + x );
401: // System.out.println( "y=" + y );
402:
403: properties.getValueLabelFont().setupGraphics2D(g2d);
404: g2d.drawString(
405: pieChart3D.pieLabels.getTextTag(0).getText(), x, y);
406: } else {
407: Arc2D.Double arc = new Arc2D.Double(pieChart3D.pieX,
408: pieChart3D.pieY + properties.getDepth(),
409: pieChart3D.pie3dWidth, pieChart3D.pie3dHeight,
410: currentDegrees, 360, Arc2D.PIE);
411:
412: //---draw the center line in case people are using transparent paint
413: Line2D.Float line = new Line2D.Float();
414: line.x1 = pieChart3D.pieX + (pieChart3D.pie3dWidth / 2);
415: line.y1 = pieChart3D.pieY + (pieChart3D.pie3dHeight / 2);
416: line.x2 = line.x1;
417: line.y2 = line.y1 + properties.getDepth();
418: properties.getBorderChartStroke().draw(g2d, line);
419:
420: //---fake 3d loop will slide pie up the image to give illusion of 3D.
421: for (int slider = properties.getDepth(); slider >= 0; slider--) {
422: currentDegrees = properties.getZeroDegreeOffset();
423:
424: //---IMAGE MAP
425: int mapCounter = 0;
426:
427: for (int i = 0; i < pieChart3D.iPieChartDataSet
428: .getNumberOfDataItems(); i++) {
429: percentageOfPie = pieChart3D.pieChartDataProcessor
430: .getPercentageOfPie(i);
431:
432: arc.setAngleStart(currentDegrees);
433: arc.setAngleExtent(percentageOfPie);
434:
435: //---set the color, and fill the pie piece.
436: g2d.setPaint(pieChart3D.iPieChartDataSet
437: .getPaint(i));
438: g2d.fill(arc);
439:
440: //---renders borders
441: drawFraming(slider, properties, g2d, arc,
442: currentDegrees);
443:
444: //---if we are going to display labels
445: if (pieChart3D.pieLabels != null && slider == 0) {
446: //---get the angle the center of slice
447: double sliceCenterDegrees = (currentDegrees)
448: + percentageOfPie / 2;
449:
450: if (sliceCenterDegrees > 360) {
451: sliceCenterDegrees -= 360;
452: }
453:
454: // double sliceCenterRadians = Math.toRadians( sliceCenterDegrees );
455:
456: /*
457:
458: >a2 := a * a;
459: >b2 := b * b;
460: >sin2 := Sqr (Sin(theta));
461: >cos2 := Sqr(Cos(theta));
462: >r = Sqrt( a2 * b2 / (a2 * sin2 + b2 * cos2) );
463: */
464: /*
465: double a2 = pieChart3D.pie3dWidth * pieChart3D.pie3dWidth;
466: double b2 = pieChart3D.pie3dHeight * pieChart3D.pie3dHeight;
467: double sin2 = Math.pow( Math.sin( sliceCenterRadians ), 2 );
468: double cos2 = Math.pow( Math.cos( sliceCenterRadians ), 2 );
469: double radius = pieChart3D.pie3dWidth * pieChart3D.pie3dHeight / Math.sqrt( ( a2 * sin2 + b2 * cos2 ) );
470: radius /= 2;
471:
472:
473: //r= (ab) / ( sqrt( a^2 sin^2 theta + b^2 cos^2 theta ) )
474:
475: //---compute the cos and sin of the label angle.
476: double cosOfLabel = Math.cos( sliceCenterRadians );
477: double sinOfLabel = Math.sin( sliceCenterRadians );
478:
479: //halfDiameter = (float) ( pieChart3D.diameter / 2.0 );
480:
481:
482: //---start point of the label border line.
483: float borderXstart = (float) ( cosOfLabel * radius );
484: float borderYstart = (float) -( sinOfLabel * radius );
485:
486: //---end point of the label border line.
487: float borderXend = (float) ( cosOfLabel * ( radius + properties.getTickLength() ) );
488: float borderYend = (float) -( sinOfLabel * ( radius + properties.getTickLength() ) );
489: */
490:
491: xPieMiddle = (float) arc.x
492: + pieChart3D.pie3dWidth / 2;
493: yPieMiddle = (float) arc.y
494: + pieChart3D.pie3dHeight / 2;
495:
496: Arc2D.Double circle = new Arc2D.Double(
497: pieChart3D.pieX, pieChart3D.pieY,
498: pieChart3D.pie3dWidth,
499: pieChart3D.pie3dHeight, currentDegrees,
500: percentageOfPie / 2, Arc2D.PIE);
501: Arc2D.Double circle2 = new Arc2D.Double(
502: pieChart3D.pieX
503: - properties.getTickLength(),
504: pieChart3D.pieY
505: - properties.getTickLength(),
506: pieChart3D.pie3dWidth
507: + properties.getTickLength()
508: * 2, pieChart3D.pie3dHeight
509: + properties.getTickLength()
510: * 2, currentDegrees,
511: percentageOfPie / 2, Arc2D.PIE);
512:
513: //---draw the line out from middle of slice
514: properties.getBorderChartStroke().draw(
515: g2d,
516: new Line2D.Float(circle.getEndPoint(),
517: circle2.getEndPoint()));
518:
519: float borderXend = (float) circle2
520: .getEndPoint().getX();
521: float borderYend = (float) circle2
522: .getEndPoint().getY();
523:
524: properties.getValueLabelFont().setupGraphics2D(
525: g2d);
526:
527: float labelY = borderYend;
528: if (sliceCenterDegrees > 60
529: && sliceCenterDegrees < 120) {
530: labelY -= pieChart3D.pieLabels
531: .getTextTag(i).getFontDescent();
532: } else if (sliceCenterDegrees > 240
533: && sliceCenterDegrees < 300) {
534: labelY += pieChart3D.pieLabels
535: .getTextTag(i).getFontAscent();
536: }
537:
538: if (sliceCenterDegrees > 180
539: && sliceCenterDegrees < 360) {
540: labelY += properties.getDepth();
541: }
542:
543: if (sliceCenterDegrees > 90
544: && sliceCenterDegrees < 270) {
545: g2d.drawString(pieChart3D.pieLabels
546: .getTextTag(i).getText(),
547: borderXend
548: - pieChart3D.pieLabels
549: .getTextTag(i)
550: .getWidth()
551: - properties
552: .getTickLength(),
553: labelY);
554: } else {
555: g2d.drawString(pieChart3D.pieLabels
556: .getTextTag(i).getText(),
557: borderXend
558: + properties
559: .getTickLength(),
560: labelY);
561: }
562: }
563:
564: //---if we are generating an image map...
565: //---IMAGE MAP
566: if (pieChart3D.getImageMap() != null) {
567: //---increment a separate amount to minimize rounding errors.
568: double workDegrees = currentDegrees;
569:
570: //---compute the cos and sin of the bodrder angle.
571: double cosOfBorder;
572: double sinOfBorder;
573: double splitDegree = percentageOfPie
574: / subdivisions;
575:
576: for (int j = 0; j <= subdivisions; j++) {
577: cosOfBorder = Math.cos(Math
578: .toRadians(workDegrees));
579: sinOfBorder = Math.sin(Math
580: .toRadians(workDegrees));
581:
582: //---end point of the slice border line.
583: imageMapPoints[mapCounter][0] = xPieMiddle
584: + (float) (cosOfBorder * halfDiameter);
585: imageMapPoints[mapCounter][1] = yPieMiddle
586: + (float) -(sinOfBorder * halfDiameter);
587:
588: //DEBUG to make sure calculating points correctly
589: //g2d.setPaint( Color.red );
590: //g2d.fillRect( (int) imageMapPoints[ mapCounter ][ 0 ], (int) imageMapPoints[ mapCounter ][ 1 ], 6, 6 );
591:
592: mapCounter++;
593: workDegrees += splitDegree;
594: }
595: }
596:
597: currentDegrees += percentageOfPie;
598: }
599:
600: //---if we are generating an image map...
601: //---IMAGE MAP
602: if (pieChart3D.getImageMap() != null) {
603: //---each slice has 3 + subdivision slices...
604: //int counter= pieChart3D.iPieChartDataSet.getNumberOfDataItems() * ( 3 + subdivisions );
605: int counter = 0;
606:
607: //---for each data item
608: for (int i = 0; i < pieChart3D.iPieChartDataSet
609: .getNumberOfDataItems(); i++) {
610: int coordinateCounter = 0;
611:
612: //---there are three points plus some number of subdivisions...
613: PolyMapArea polyMapArea = new PolyMapArea(
614: 3 + subdivisions,
615: pieChart3D.iPieChartDataSet.getValue(i),
616: null, pieChart3D.iPieChartDataSet
617: .getLegendLabel(i));
618: polyMapArea.addCoordinate(coordinateCounter++,
619: xPieMiddle, yPieMiddle);
620:
621: //---include the first border point, plus the subdivisions
622: for (int h = 0; h <= subdivisions; h++) {
623: polyMapArea.addCoordinate(
624: coordinateCounter++,
625: imageMapPoints[counter][0],
626: imageMapPoints[counter][1]);
627: counter++;
628: }
629:
630: //---if this is the last slice, add the first calculated map point
631: if ((i + 1) == pieChart3D.iPieChartDataSet
632: .getNumberOfDataItems()) {
633: polyMapArea.addCoordinate(
634: coordinateCounter,
635: imageMapPoints[0][0],
636: imageMapPoints[0][1]);
637: }
638: //---else add the next calculated point
639: else {
640: polyMapArea.addCoordinate(
641: coordinateCounter,
642: imageMapPoints[counter][0],
643: imageMapPoints[counter][1]);
644: }
645:
646: pieChart3D.getImageMap().addImageMapArea(
647: polyMapArea);
648: }
649: }
650:
651: //---slide the pie up one pixel
652: arc.y -= 1;
653: }
654:
655: /*
656: //---draw the edges of the pie
657: line.x1= pieChart3D.pieX - 1;
658: line.x2= line.x1;
659: g2d.draw( line );
660: line.x1= pieChart3D.pieX + pieChart3D.pie3dWidth + 1;
661: line.x2= line.x1;
662: g2d.draw( line );
663: */
664:
665: }
666: }
667:
668: /****************************************************************************************
669: *
670: * @param slider
671: * @param properties
672: * @param g2d
673: * @param arc
674: * @param currentDegrees
675: ****************************************************************************************/
676: private static void drawFraming(int slider,
677: PieChart3DProperties properties, Graphics2D g2d,
678: Arc2D.Double arc, float currentDegrees) {
679: //---draw the top borders of the pie, and draw the bottom in case there are transparent Paints
680: if (slider == properties.getDepth() || slider == 0) {
681: properties.getBorderChartStroke().draw(g2d, arc);
682:
683: //---draw the vertical borders
684: //---in case there are translucent Paints, need to draw the backside borders before the chart.
685: if (slider == properties.getDepth()) {
686: if (currentDegrees > 0 && currentDegrees < 180) {
687: properties.getBorderChartStroke().draw(
688: g2d,
689: new Line2D.Double(arc.getStartPoint()
690: .getX(),
691: arc.getStartPoint().getY(), arc
692: .getStartPoint().getX(),
693: arc.getStartPoint().getY()
694: - properties.getDepth()));
695: }
696: } else if (slider == 0) {
697: if (currentDegrees == 0
698: || (currentDegrees >= 180 && currentDegrees < 360)) {
699: properties.getBorderChartStroke().draw(
700: g2d,
701: new Line2D.Double(arc.getStartPoint()
702: .getX(),
703: arc.getStartPoint().getY(), arc
704: .getStartPoint().getX(),
705: arc.getStartPoint().getY()
706: + properties.getDepth()));
707: }
708: }
709: }
710: }
711:
712: /**********************************************************************************************
713: * Enables the testing routines to display the contents of this Object. Override Chart
714: * implementation as PieCharts use AreaProperties directly rather than a child.
715: *
716: * @param htmlGenerator
717: * @param imageFileName
718: **********************************************************************************************/
719: public void toHTML(HTMLGenerator htmlGenerator, String imageFileName) {
720: if (this.getLegend() != null) {
721: htmlGenerator.chartTableRowStart();
722: this.getLegend().toHTML(htmlGenerator);
723: htmlGenerator.chartTableRowEnd();
724: }
725:
726: htmlGenerator.chartTableEnd();
727: }
728:
729: }
|