1 34 35 package org.krysalis.jcharts.nonAxisChart; 36 37 38 import java.awt.Color ; 39 import java.awt.Graphics2D ; 40 import java.awt.Paint ; 41 import java.awt.Polygon ; 42 import java.awt.Rectangle ; 43 import java.awt.RenderingHints ; 44 import java.awt.font.FontRenderContext ; 45 import java.awt.geom.Point2D ; 46 import java.awt.geom.Rectangle2D ; 47 48 import org.krysalis.jcharts.Chart; 49 import org.krysalis.jcharts.chartData.interfaces.IRadarChartDataSet; 50 import org.krysalis.jcharts.chartData.processors.RadarChartDataProcessor; 51 import org.krysalis.jcharts.properties.ChartProperties; 52 import org.krysalis.jcharts.properties.LegendProperties; 53 import org.krysalis.jcharts.properties.RadarChartProperties; 54 import org.krysalis.jcharts.properties.util.ChartFont; 55 56 57 64 65 public class RadarChart 66 extends Chart 67 { 68 69 private IRadarChartDataSet iRadarChartDataSet; 70 private RadarChartDataProcessor radarChartDataProcessor; 71 private RadarChartProperties props; 72 private double radius, step; 73 private Point2D center; 74 75 private double scaleMax, scaleIncrement; 77 78 private static final int DEFAULT_NR_OF_INCREMENTS = 10; 80 81 82 91 public RadarChart( IRadarChartDataSet iRadarChartDataSet, 92 LegendProperties legendProperties, 93 ChartProperties chartProperties, 94 int pixelWidth, 95 int pixelHeight ) 96 { 97 super( legendProperties, chartProperties, pixelWidth, pixelHeight ); 98 this.iRadarChartDataSet = iRadarChartDataSet; 99 props = (RadarChartProperties) iRadarChartDataSet.getChartTypeProperties(); 100 if( props == null ) 101 { 102 props = new RadarChartProperties(); 103 } 104 } 105 106 107 111 protected void renderChart() 112 { 113 Graphics2D g2d = getGraphics2D(); 114 115 g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); 117 118 119 121 FontRenderContext fontRenderContext = super.getGraphics2D(). 122 getFontRenderContext(); 123 124 float chartTitleHeight = super.renderChartTitle( this.iRadarChartDataSet. 126 getChartTitle(), fontRenderContext ); 127 128 this.radarChartDataProcessor = new RadarChartDataProcessor( this.iRadarChartDataSet ); 129 this.radarChartDataProcessor.processData(); 130 131 if( Double.isNaN( props.getScaleMaxValue() ) ) 133 this.scaleMax = radarChartDataProcessor.getMaxValue(); 134 else 135 scaleMax = props.getScaleMaxValue(); 136 137 if( Double.isNaN( props.getScaleIncrement() ) ) 139 this.scaleIncrement = scaleMax / DEFAULT_NR_OF_INCREMENTS; 140 else 141 scaleIncrement = props.getScaleIncrement(); 142 143 Rectangle chartSpace = new Rectangle ( getImageWidth(), getImageHeight() ); 145 146 center = new Point2D.Double ( 147 chartSpace.getWidth() / 2 - chartSpace.getX(), 148 chartSpace.getHeight() / 2 - chartSpace.getY() ); 149 radius = Math.min( chartSpace.getWidth(), chartSpace.getHeight() ); 150 radius = ( radius - ( radius * 10 ) / 100 ) / 2; 151 step = 2 * Math.PI / iRadarChartDataSet.getNumberOfDataItems(); 152 153 if( props.getShowGridLines() ) 154 { 155 drawGridLines( g2d ); 156 } 157 drawAxis( g2d ); 158 drawRadar( g2d ); 159 } 160 161 162 private void drawRadar( 163 Graphics2D g ) 164 { 165 166 for( int dataset = 0; dataset < iRadarChartDataSet.getNumberOfDataSets(); 167 dataset++ ) 168 { 169 170 double currentValue; 171 double previousValue = scaleValue( iRadarChartDataSet.getValue( dataset, 172 iRadarChartDataSet.getNumberOfDataItems() - 173 1 ) ); 174 175 Paint paint = iRadarChartDataSet.getPaint( dataset ); 176 177 for( int di = 0; di < iRadarChartDataSet.getNumberOfDataItems(); di++ ) 178 { 179 currentValue = previousValue; 180 previousValue = scaleValue( iRadarChartDataSet.getValue( dataset, di ) ); 181 g.setPaint( paint ); 182 183 int c0 = (int) Math.round( center.getX() ); 184 int c1 = (int) Math.round( center.getY() ); 185 int x0 = getX( di + 1, previousValue ); 186 int y0 = getY( di + 1, previousValue ); 187 int x1 = getX( di, currentValue ); 188 int y1 = getY( di, currentValue ); 189 190 if( props.getFillRadar() ) 191 { 192 Polygon p = new Polygon (); 193 p.addPoint( c0, c1 ); 194 p.addPoint( x0, y0 ); 195 p.addPoint( x1, y1 ); 196 if( paint instanceof Color ) 198 { 199 Color color = (Color ) paint; 200 g.setPaint( new Color ( color.getRed(), color.getGreen(), 201 color.getBlue(), 100 ) ); 202 } 203 g.fillPolygon( p ); 204 g.setPaint( paint ); 205 } 206 g.drawLine( x0, y0, x1, y1 ); 207 } 208 } 209 } 210 211 212 private void drawGridLines( Graphics2D g ) 213 { 214 g.setColor( Color.lightGray ); 215 for( int di = 0; di < iRadarChartDataSet.getNumberOfDataItems(); 216 di++ ) 217 { 218 for( double i = scaleIncrement; i <= scaleMax; i += scaleIncrement ) 219 { 220 double pos = scaleValue( i ); 221 g.drawLine( 222 getX( di + 1, pos ), 223 getY( di + 1, pos ), 224 getX( di, pos ), 225 getY( di, pos ) ); 226 } 227 } 228 } 229 230 231 private void drawAxis( Graphics2D g ) 232 { 233 g.setColor( Color.darkGray ); 234 for( int index = 0; index < iRadarChartDataSet.getNumberOfDataItems(); 235 index++ ) 236 { 237 String label = iRadarChartDataSet.getAxisLabel( index ); 238 g.drawLine( 239 (int) center.getX(), 240 (int) center.getY(), 241 getX( index, 1 ), 242 getY( index, 1 ) ); 243 244 Rectangle2D bounds = g.getFontMetrics().getStringBounds( label, g ); 245 246 ChartFont cfont = props.getTitleChartFont(); 248 if( cfont != null ) 249 { 250 g.setFont( cfont.getFont() ); 251 252 } 253 g.drawString( 254 label, 255 (int) ( getX( index + 1, 1 ) - bounds.getWidth() / 2 ), 256 getY( index + 1, 1 ) ); 257 } 258 259 g.setColor( Color.darkGray ); 261 g.setFont( ChartFont.DEFAULT_AXIS_VALUE.getFont() ); 262 int selectedLine = (int) iRadarChartDataSet.getNumberOfDataItems() / 2; 263 for( double i = scaleIncrement; i <= scaleMax; i += scaleIncrement ) 264 { 265 double pos = scaleValue( i ); 266 Rectangle2D bounds = g.getFont().getStringBounds( "1", 267 g.getFontRenderContext() ); 268 g.drawString( props.getGridLabelFormat().format( i ), 269 getX( selectedLine, pos ), 270 (int) Math.round( getY( selectedLine, pos ) + bounds.getHeight() ) ); 271 } 272 273 } 274 275 276 private int getX( int dataset, double factor ) 277 { 278 return (int) Math.round( center.getX() + radius * factor * Math.sin( step * dataset ) ); 279 } 280 281 282 private int getY( int dataset, double factor ) 283 { 284 return (int) Math.round( center.getY() + radius * factor * Math.cos( step * dataset ) ); 285 } 286 287 288 private double scaleValue( double value ) 289 { 290 if( value > scaleMax ) 291 value = scaleMax; 292 if( scaleMax == 0 ) 293 return 0; 294 return value / scaleMax; 295 } 296 297 } 298 | Popular Tags |