001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2022, by David Gilbert. All rights reserved. 006 * 007 * https://github.com/jfree/orson-charts 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package org.jfree.chart3d; 034 035import org.jfree.chart3d.axis.CategoryAxis3D; 036import org.jfree.chart3d.axis.LabelOrientation; 037import org.jfree.chart3d.axis.NumberAxis3D; 038import org.jfree.chart3d.axis.StandardCategoryAxis3D; 039import org.jfree.chart3d.axis.ValueAxis3D; 040import org.jfree.chart3d.data.PieDataset3D; 041import org.jfree.chart3d.data.Range; 042import org.jfree.chart3d.data.category.CategoryDataset3D; 043import org.jfree.chart3d.data.function.Function3D; 044import org.jfree.chart3d.data.xyz.XYZDataset; 045import org.jfree.chart3d.data.xyz.XYZSeriesCollection; 046import org.jfree.chart3d.internal.Args; 047import org.jfree.chart3d.legend.ColorScaleLegendBuilder; 048import org.jfree.chart3d.plot.CategoryPlot3D; 049import org.jfree.chart3d.plot.PiePlot3D; 050import org.jfree.chart3d.plot.XYZPlot; 051import org.jfree.chart3d.renderer.category.AreaRenderer3D; 052import org.jfree.chart3d.renderer.category.BarRenderer3D; 053import org.jfree.chart3d.renderer.category.CategoryRenderer3D; 054import org.jfree.chart3d.renderer.category.LineRenderer3D; 055import org.jfree.chart3d.renderer.category.StackedBarRenderer3D; 056import org.jfree.chart3d.renderer.xyz.BarXYZRenderer; 057import org.jfree.chart3d.renderer.xyz.LineXYZRenderer; 058import org.jfree.chart3d.renderer.xyz.ScatterXYZRenderer; 059import org.jfree.chart3d.renderer.xyz.SurfaceRenderer; 060import org.jfree.chart3d.renderer.xyz.XYZRenderer; 061import org.jfree.chart3d.style.ChartStyle; 062import org.jfree.chart3d.style.StandardChartStyle; 063 064/** 065 * Utility methods for constructing common chart types. Charts can be 066 * assembled piece-wise, but usually it is simpler to use the methods in this 067 * class then customise the resulting chart as necessary. 068 */ 069public class Chart3DFactory { 070 071 /** 072 * Private constructor prevents instantiation which is unnecessary. 073 */ 074 private Chart3DFactory() { 075 // no need to instantiate this ever 076 } 077 078 /** The chart style that will be used when creating a new chart. */ 079 static ChartStyle defaultStyle = new StandardChartStyle(); 080 081 /** 082 * Returns a new instance of the default chart style (so that, by default, 083 * all charts will have an independent style instance). 084 * 085 * @return The default chart style (never {@code null}). 086 * 087 * @since 1.2 088 */ 089 public static ChartStyle getDefaultChartStyle() { 090 return defaultStyle.clone(); 091 } 092 093 /** 094 * Sets the style that will be used when creating new charts. 095 * 096 * @param style the style ({@code null} not permitted). 097 * 098 * @since 1.2 099 */ 100 public static void setDefaultChartStyle(ChartStyle style) { 101 Args.nullNotPermitted(style, "style"); 102 defaultStyle = style.clone(); 103 } 104 105 /** 106 * Creates and returns a pie chart based on the supplied dataset. The 107 * chart returned by this method will be constructed using a 108 * {@link PiePlot3D} instance (so it is safe to cast the result of 109 * {@code chart.getPlot()}). 110 * <br><br> 111 * For reference, here is a sample pie chart: 112 * <div> 113 * <img src="../../../../doc-files/PieChart3DDemo1.svg" 114 * alt="PieChart3DDemo1.svg" width="500" height="359"> 115 * </div> 116 * 117 * @param title the chart title ({@code null} permitted). 118 * @param subtitle the chart subtitle ({@code null} permitted). 119 * @param dataset the dataset ({@code null} not permitted). 120 * 121 * @return A pie chart (never {@code null}). 122 */ 123 public static Chart3D createPieChart(String title, String subtitle, 124 PieDataset3D<? extends Comparable> dataset) { 125 PiePlot3D plot = new PiePlot3D(dataset); 126 return new Chart3D(title, subtitle, plot); 127 } 128 129 /** 130 * Creates and returns a bar chart based on the supplied dataset. The chart 131 * returned by this method will be constructed with a 132 * {@link CategoryPlot3D} using a {@link BarRenderer3D} (so it is 133 * safe to cast the plot and/or renderer to customise attributes that are 134 * specific to those subclasses). 135 * <br><br> 136 * For reference, here is a sample bar chart: 137 * <div> 138 * <img src="../../../../doc-files/BarChart3DDemo1.svg" 139 * alt="BarChart3DDemo1.svg" width="500" height="359"> 140 * </div> 141 * 142 * @param title the chart title ({@code null} permitted). 143 * @param subtitle the chart subtitle ({@code null} permitted). 144 * @param dataset the dataset ({@code null} not permitted). 145 * @param rowAxisLabel the row axis label ({@code null} permitted). 146 * @param columnAxisLabel the column axis label ({@code null} 147 * permitted). 148 * @param valueAxisLabel the value axis label ({@code null} permitted). 149 * 150 * @return A bar chart (never {@code null}). 151 */ 152 public static Chart3D createBarChart(String title, String subtitle, 153 CategoryDataset3D dataset, String rowAxisLabel, 154 String columnAxisLabel, String valueAxisLabel) { 155 StandardCategoryAxis3D rowAxis 156 = new StandardCategoryAxis3D(rowAxisLabel); 157 rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 158 CategoryAxis3D columnAxis = new StandardCategoryAxis3D(columnAxisLabel); 159 NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 160 new Range(0.0, 1.0)); 161 valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 162 CategoryRenderer3D renderer = new BarRenderer3D(); 163 CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, 164 rowAxis, columnAxis, valueAxis); 165 return new Chart3D(title, subtitle, plot); 166 } 167 168 /** 169 * Creates and returns a stacked bar chart based on the supplied dataset. 170 * The chart returned by this method will be constructed with a 171 * {@link CategoryPlot3D} using a {@link StackedBarRenderer3D} (so it is 172 * safe to cast the plot and/or renderer to customise attributes that 173 * are specific to those subclasses). 174 * <br><br> 175 * For reference, here is a sample stacked bar chart: 176 * <div> 177 * <img src="../../../../doc-files/StackedBarChart3DDemo1.svg" 178 * alt="StackedBarChart3DDemo1.svg" width="500" height="359"> 179 * </div> 180 * 181 * @param title the chart title ({@code null} permitted). 182 * @param subtitle the chart subtitle ({@code null} permitted). 183 * @param dataset the dataset ({@code null} not permitted). 184 * @param rowAxisLabel the row axis label ({@code null} permitted). 185 * @param columnAxisLabel the column axis label ({@code null} permitted). 186 * @param valueAxisLabel the value axis label ({@code null} permitted). 187 * 188 * @return A stacked bar chart (never {@code null}). 189 */ 190 public static Chart3D createStackedBarChart(String title, String subtitle, 191 CategoryDataset3D dataset, String rowAxisLabel, 192 String columnAxisLabel, String valueAxisLabel) { 193 StandardCategoryAxis3D rowAxis 194 = new StandardCategoryAxis3D(rowAxisLabel); 195 rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 196 CategoryAxis3D columnAxis = new StandardCategoryAxis3D(columnAxisLabel); 197 NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 198 new Range(0.0, 1.0)); 199 valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 200 CategoryRenderer3D renderer = new StackedBarRenderer3D(); 201 CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, 202 columnAxis, valueAxis); 203 return new Chart3D(title, subtitle, plot); 204 } 205 206 /** 207 * Creates and returns an area chart based on the supplied dataset. The 208 * chart returned by this method will be constructed with a 209 * {@link CategoryPlot3D} using an {@link AreaRenderer3D} (so it is safe 210 * to cast the plot and/or renderer to customise attributes that are 211 * specific to those subclasses). 212 * <br><br> 213 * For reference, here is a sample area chart: 214 * <div> 215 * <img src="../../../../doc-files/AreaChart3DDemo1.svg" 216 * alt="AreaChart3DDemo1.svg" width="500" height="359"> 217 * </div> 218 * 219 * @param title the chart title ({@code null} permitted). 220 * @param subtitle the chart subtitle ({@code null} permitted). 221 * @param dataset the dataset ({@code null} not permitted). 222 * @param rowAxisLabel the row axis label ({@code null} permitted). 223 * @param columnAxisLabel the column axis label ({@code null} permitted). 224 * @param valueAxisLabel the value axis label ({@code null} permitted). 225 * 226 * @return An area chart (never {@code null}). 227 */ 228 public static Chart3D createAreaChart(String title, String subtitle, 229 CategoryDataset3D dataset, String rowAxisLabel, 230 String columnAxisLabel, String valueAxisLabel) { 231 StandardCategoryAxis3D rowAxis 232 = new StandardCategoryAxis3D(rowAxisLabel); 233 rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 234 StandardCategoryAxis3D columnAxis = new StandardCategoryAxis3D( 235 columnAxisLabel); 236 columnAxis.setFirstCategoryHalfWidth(true); 237 columnAxis.setLastCategoryHalfWidth(true); 238 NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 239 new Range(0.0, 1.0)); 240 valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 241 CategoryRenderer3D renderer = new AreaRenderer3D(); 242 CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, 243 columnAxis, valueAxis); 244 return new Chart3D(title, subtitle, plot); 245 } 246 247 /** 248 * Creates and returns a line chart based on the supplied dataset. The 249 * chart returned by this method will be constructed with a 250 * {@link CategoryPlot3D} using a {@link LineRenderer3D} (so it is safe 251 * to cast the plot and/or renderer to customise attributes that are 252 * specific to those subclasses). 253 * <br><br> 254 * For reference, here is a sample line chart: 255 * <div> 256 * <img src="../../../../doc-files/LineChart3DDemo1.svg" 257 * alt="LineChart3DDemo1.svg" width="500" height="359"> 258 * </div> 259 * 260 * @param title the chart title ({@code null} permitted). 261 * @param subtitle the chart subtitle ({@code null} permitted). 262 * @param dataset the dataset ({@code null} not permitted). 263 * @param rowAxisLabel the row axis label ({@code null} permitted). 264 * @param columnAxisLabel the column axis label ({@code null} permitted). 265 * @param valueAxisLabel the value axis label ({@code null} permitted). 266 * 267 * @return A line chart (never {@code null}). 268 */ 269 public static Chart3D createLineChart(String title, String subtitle, 270 CategoryDataset3D dataset, String rowAxisLabel, 271 String columnAxisLabel, String valueAxisLabel) { 272 StandardCategoryAxis3D rowAxis 273 = new StandardCategoryAxis3D(rowAxisLabel); 274 rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 275 StandardCategoryAxis3D columnAxis 276 = new StandardCategoryAxis3D(columnAxisLabel); 277 columnAxis.setFirstCategoryHalfWidth(true); 278 columnAxis.setLastCategoryHalfWidth(true); 279 NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 280 new Range(0.0, 1.0)); 281 valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 282 CategoryRenderer3D renderer = new LineRenderer3D(); 283 CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, 284 columnAxis, valueAxis); 285 return new Chart3D(title, subtitle, plot); 286 } 287 288 /** 289 * Creates and returns a scatter plot based on the supplied dataset 290 * (containing one or more series of {@code (x, y, z)} values). The 291 * chart returned by this method will be constructed with an 292 * {@link XYZPlot} using a {@link ScatterXYZRenderer} (so it is safe 293 * to cast the plot and/or renderer to customise attributes that are 294 * specific to those subclasses). 295 * <br><br> 296 * For reference, here is a sample scatter chart: 297 * <div> 298 * <img src="../../../../doc-files/ScatterPlot3DDemo1.svg" 299 * alt="ScatterPlot3DDemo1.svg" width="564" height="351"> 300 * </div> 301 * 302 * @param title the chart title ({@code null} permitted). 303 * @param subtitle the chart subtitle ({@code null} permitted). 304 * @param dataset the dataset ({@code null} not permitted). 305 * @param xAxisLabel the x-axis label ({@code null} permitted). 306 * @param yAxisLabel the y-axis label ({@code null} permitted). 307 * @param zAxisLabel the z-axis label ({@code null} permitted). 308 * 309 * @return The chart. 310 */ 311 public static Chart3D createScatterChart(String title, String subtitle, 312 XYZDataset dataset, String xAxisLabel, String yAxisLabel, 313 String zAxisLabel) { 314 NumberAxis3D xAxis = new NumberAxis3D(xAxisLabel); 315 NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); 316 yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 317 NumberAxis3D zAxis = new NumberAxis3D(zAxisLabel); 318 XYZRenderer renderer = new ScatterXYZRenderer(); 319 XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis); 320 return new Chart3D(title, subtitle, plot); 321 } 322 323 /** 324 * Creates a surface chart for the specified function. 325 * <br><br> 326 * For reference, here is a sample surface chart: 327 * <div> 328 * <img src="../../../../doc-files/SurfaceRendererDemo2.svg" 329 * alt="SurfaceRendererDemo2.svg" width="562" height="408"> 330 * </div> 331 * 332 * @param title the chart title ({@code null} permitted). 333 * @param subtitle the chart subtitle ({@code null} permitted). 334 * @param function the function ({@code null} not permitted). 335 * @param xAxisLabel the x-axis label ({@code null} permitted). 336 * @param yAxisLabel the y-axis label ({@code null} permitted). 337 * @param zAxisLabel the z-axis label ({@code null} permitted). 338 * 339 * @return The chart. 340 * 341 * @since 1.1 342 */ 343 public static Chart3D createSurfaceChart(String title, String subtitle, 344 Function3D function, String xAxisLabel, String yAxisLabel, 345 String zAxisLabel) { 346 NumberAxis3D xAxis = new NumberAxis3D(xAxisLabel); 347 NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); 348 yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 349 NumberAxis3D zAxis = new NumberAxis3D(zAxisLabel); 350 XYZRenderer renderer = new SurfaceRenderer(function); 351 // we pass an empty dataset because the plot must have a non-null 352 // dataset, but the renderer never looks at it... 353 XYZPlot plot = new XYZPlot(new XYZSeriesCollection(), renderer, xAxis, 354 yAxis, zAxis); 355 356 Chart3D chart = new Chart3D(title, subtitle, plot); 357 chart.setLegendBuilder(new ColorScaleLegendBuilder()); 358 return chart; 359 } 360 361 /** 362 * Creates and returns a bar chart based on the supplied dataset (this is 363 * for special cases, most general cases will be covered by the 364 * {@link #createBarChart(String, String, CategoryDataset3D, String, String, String) } 365 * method). The chart returned by this method will be constructed with an 366 * {@link XYZPlot} using a {@link BarXYZRenderer} (so it is safe 367 * to cast the plot and/or renderer to customise attributes that are 368 * specific to those subclasses). 369 * <br><br> 370 * For reference, here is a sample XYZ bar chart: 371 * <div> 372 * <img src="../../../../doc-files/XYZBarChart3DDemo1.svg" 373 * alt="XYZBarChart3DDemo1.svg" width="500" height="359"> 374 * </div> 375 * 376 * @param title the chart title ({@code null} permitted). 377 * @param subtitle the chart subtitle ({@code null} permitted). 378 * @param dataset the dataset ({@code null} not permitted). 379 * @param xAxisLabel the x-axis label ({@code null} permitted). 380 * @param yAxisLabel the y-axis label ({@code null} permitted). 381 * @param zAxisLabel the z-axis label ({@code null} permitted). 382 * 383 * @return The chart. 384 */ 385 public static Chart3D createXYZBarChart(String title, String subtitle, 386 XYZDataset dataset, String xAxisLabel, String yAxisLabel, 387 String zAxisLabel) { 388 ValueAxis3D xAxis = new NumberAxis3D(xAxisLabel); 389 NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); 390 yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 391 ValueAxis3D zAxis = new NumberAxis3D(zAxisLabel); 392 XYZRenderer renderer = new BarXYZRenderer(); 393 XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis); 394 return new Chart3D(title, subtitle, plot); 395 } 396 397 /** 398 * Creates and returns a line chart based on the supplied dataset. The 399 * chart returned by this method will be constructed with an 400 * {@link XYZPlot} using a {@link LineXYZRenderer} (so it is safe 401 * to cast the plot and/or renderer to customise attributes that are 402 * specific to those subclasses). 403 * 404 * @param title the chart title ({@code null} permitted). 405 * @param subtitle the chart subtitle ({@code null} permitted). 406 * @param dataset the dataset ({@code null} not permitted). 407 * @param xAxisLabel the x-axis label ({@code null} permitted). 408 * @param yAxisLabel the y-axis label ({@code null} permitted). 409 * @param zAxisLabel the z-axis label ({@code null} permitted). 410 * 411 * @return The chart. 412 * 413 * @since 1.5 414 */ 415 public static Chart3D createXYZLineChart(String title, String subtitle, 416 XYZDataset dataset, String xAxisLabel, String yAxisLabel, 417 String zAxisLabel) { 418 ValueAxis3D xAxis = new NumberAxis3D(xAxisLabel); 419 NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); 420 yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); 421 ValueAxis3D zAxis = new NumberAxis3D(zAxisLabel); 422 XYZRenderer renderer = new LineXYZRenderer(); 423 XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis); 424 return new Chart3D(title, subtitle, plot); 425 } 426}