001/* ===========================================================
002 * Orson Charts : a 3D chart library for the Java(tm) platform
003 * ===========================================================
004 * 
005 * (C)opyright 2013-2016, by Object Refinery Limited.  All rights reserved.
006 * 
007 * http://www.object-refinery.com/orsoncharts/index.html
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 com.orsoncharts;
034
035import com.orsoncharts.axis.CategoryAxis3D;
036import com.orsoncharts.axis.LabelOrientation;
037import com.orsoncharts.axis.StandardCategoryAxis3D;
038import com.orsoncharts.axis.NumberAxis3D;
039import com.orsoncharts.axis.ValueAxis3D;
040import com.orsoncharts.data.category.CategoryDataset3D;
041import com.orsoncharts.data.PieDataset3D;
042import com.orsoncharts.data.function.Function3D;
043import com.orsoncharts.data.xyz.XYZDataset;
044import com.orsoncharts.data.xyz.XYZSeriesCollection;
045import com.orsoncharts.legend.ColorScaleLegendBuilder;
046import com.orsoncharts.plot.CategoryPlot3D;
047import com.orsoncharts.plot.PiePlot3D;
048import com.orsoncharts.plot.XYZPlot;
049import com.orsoncharts.renderer.xyz.BarXYZRenderer;
050import com.orsoncharts.renderer.xyz.XYZRenderer;
051import com.orsoncharts.renderer.category.AreaRenderer3D;
052import com.orsoncharts.renderer.category.BarRenderer3D;
053import com.orsoncharts.renderer.category.CategoryRenderer3D;
054import com.orsoncharts.renderer.category.LineRenderer3D;
055import com.orsoncharts.renderer.category.StackedBarRenderer3D;
056import com.orsoncharts.renderer.xyz.LineXYZRenderer;
057import com.orsoncharts.renderer.xyz.ScatterXYZRenderer;
058import com.orsoncharts.renderer.xyz.SurfaceRenderer;
059import com.orsoncharts.style.ChartStyle;
060import com.orsoncharts.style.StandardChartStyle;
061import com.orsoncharts.util.ArgChecks;
062
063/**
064 * Utility methods for constructing common chart types.  Charts can be 
065 * assembled piece-wise, but usually it is simpler to use the methods in this
066 * class then customise the resulting chart as necessary.
067 */
068public class Chart3DFactory {
069    
070    /**
071     * Private constructor prevents instantiation which is unnecessary.
072     */
073    private Chart3DFactory() {
074        // no need to instantiate this ever
075    }
076    
077    /** The chart style that will be used when creating a new chart. */
078    static ChartStyle defaultStyle = new StandardChartStyle();
079    
080    /**
081     * Returns a new instance of the default chart style (so that, by default,
082     * all charts will have an independent style instance).
083     * 
084     * @return The default chart style (never {@code null}).
085     * 
086     * @since 1.2
087     */
088    public static ChartStyle getDefaultChartStyle() {
089        return defaultStyle.clone();
090    }
091    
092    /**
093     * Sets the style that will be used when creating new charts.
094     * 
095     * @param style  the style ({@code null} not permitted).
096     * 
097     * @since 1.2
098     */
099    public static void setDefaultChartStyle(ChartStyle style) {
100        ArgChecks.nullNotPermitted(style, "style");
101        defaultStyle = style.clone();    
102    }
103    
104    /**
105     * Creates and returns a pie chart based on the supplied dataset.  The 
106     * chart returned by this method will be constructed using a  
107     * {@link PiePlot3D} instance (so it is safe to cast the result of
108     * {@code chart.getPlot()}).
109     * <br><br>
110     * For reference, here is a sample pie chart:
111     * <div>
112     * <object id="ABC" data="../../doc-files/PieChart3DDemo1.svg"  
113     * type="image/svg+xml" width="500" height="359"> 
114     * </object>
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     * <object id="ABC" data="../../doc-files/BarChart3DDemo1.svg"  
139     * type="image/svg+xml" width="500" height="359"> 
140     * </object>
141     * </div>
142     * 
143     * @param title  the chart title ({@code null} permitted).
144     * @param subtitle  the chart subtitle ({@code null} permitted).
145     * @param dataset  the dataset ({@code null} not permitted).
146     * @param rowAxisLabel  the row axis label ({@code null} permitted).
147     * @param columnAxisLabel  the column axis label ({@code null} 
148     *     permitted).
149     * @param valueAxisLabel  the value axis label ({@code null} permitted).
150     * 
151     * @return A bar chart (never {@code null}). 
152     */
153    public static Chart3D createBarChart(String title, String subtitle,
154            CategoryDataset3D dataset, String rowAxisLabel, 
155            String columnAxisLabel, String valueAxisLabel) {
156        StandardCategoryAxis3D rowAxis 
157                = new StandardCategoryAxis3D(rowAxisLabel);
158        rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
159        CategoryAxis3D columnAxis = new StandardCategoryAxis3D(columnAxisLabel);
160        NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 
161                new Range(0.0, 1.0));
162        valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
163        CategoryRenderer3D renderer = new BarRenderer3D();
164        CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, 
165                rowAxis, columnAxis, valueAxis);
166        return new Chart3D(title, subtitle, plot);
167    }
168    
169    /**
170     * Creates and returns a stacked bar chart based on the supplied dataset.
171     * The chart returned by this method will be constructed with a 
172     * {@link CategoryPlot3D} using a {@link StackedBarRenderer3D} (so it is
173     * safe to cast the plot and/or renderer to customise attributes that
174     * are specific to those subclasses).
175     * <br><br>
176     * For reference, here is a sample stacked bar chart:
177     * <div>
178     * <object id="ABC" data="../../doc-files/StackedBarChart3DDemo1.svg"  
179     * type="image/svg+xml" width="500" height="359"> 
180     * </object>
181     * </div>
182     * 
183     * @param title  the chart title ({@code null} permitted).
184     * @param subtitle  the chart subtitle ({@code null} permitted).
185     * @param dataset  the dataset ({@code null} not permitted).
186     * @param rowAxisLabel  the row axis label ({@code null} permitted).
187     * @param columnAxisLabel  the column axis label ({@code null} permitted).
188     * @param valueAxisLabel  the value axis label ({@code null} permitted).
189     * 
190     * @return A stacked bar chart (never {@code null}). 
191     */
192    public static Chart3D createStackedBarChart(String title, String subtitle,
193            CategoryDataset3D dataset, String rowAxisLabel, 
194            String columnAxisLabel, String valueAxisLabel) {
195        StandardCategoryAxis3D rowAxis 
196                = new StandardCategoryAxis3D(rowAxisLabel);
197        rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
198        CategoryAxis3D columnAxis = new StandardCategoryAxis3D(columnAxisLabel);
199        NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 
200                new Range(0.0, 1.0));
201        valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
202        CategoryRenderer3D renderer = new StackedBarRenderer3D();
203        CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, 
204                columnAxis, valueAxis);
205        return new Chart3D(title, subtitle, plot);
206    }
207    
208    /**
209     * Creates and returns an area chart based on the supplied dataset.  The 
210     * chart returned by this method will be constructed with a 
211     * {@link CategoryPlot3D} using an {@link AreaRenderer3D} (so it is safe 
212     * to cast the plot and/or renderer to customise attributes that are 
213     * specific to those subclasses).
214     * <br><br>
215     * For reference, here is a sample area chart:
216     * <div>
217     * <object id="ABC" data="../../doc-files/AreaChart3DDemo1.svg"  
218     * type="image/svg+xml" width="500" height="359"> 
219     * </object>
220     * </div>
221     * 
222     * @param title  the chart title ({@code null} permitted).
223     * @param subtitle  the chart subtitle ({@code null} permitted).
224     * @param dataset  the dataset ({@code null} not permitted).
225     * @param rowAxisLabel  the row axis label ({@code null} permitted).
226     * @param columnAxisLabel  the column axis label ({@code null} permitted).
227     * @param valueAxisLabel  the value axis label ({@code null} permitted).
228     * 
229     * @return An area chart (never {@code null}). 
230     */
231    public static Chart3D createAreaChart(String title, String subtitle,
232            CategoryDataset3D dataset, String rowAxisLabel, 
233            String columnAxisLabel, String valueAxisLabel) {     
234        StandardCategoryAxis3D rowAxis 
235                = new StandardCategoryAxis3D(rowAxisLabel);
236        rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
237        StandardCategoryAxis3D columnAxis = new StandardCategoryAxis3D(
238                columnAxisLabel);
239        columnAxis.setFirstCategoryHalfWidth(true);
240        columnAxis.setLastCategoryHalfWidth(true);
241        NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 
242                new Range(0.0, 1.0));
243        valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
244        CategoryRenderer3D renderer = new AreaRenderer3D();
245        CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, 
246                columnAxis, valueAxis);
247        return new Chart3D(title, subtitle, plot);
248    }
249    
250    /**
251     * Creates and returns a line chart based on the supplied dataset.  The 
252     * chart returned by this method will be constructed with a 
253     * {@link CategoryPlot3D} using a {@link LineRenderer3D} (so it is safe
254     * to cast the plot and/or renderer to customise attributes that are
255     * specific to those subclasses).
256     * <br><br>
257     * For reference, here is a sample line chart:
258     * <div>
259     * <object id="ABC" data="../../doc-files/LineChart3DDemo1.svg"  
260     * type="image/svg+xml" width="500" height="359"> 
261     * </object>
262     * </div>
263     * 
264     * @param title  the chart title ({@code null} permitted).
265     * @param subtitle  the chart subtitle ({@code null} permitted).
266     * @param dataset  the dataset ({@code null} not permitted).
267     * @param rowAxisLabel  the row axis label ({@code null} permitted).
268     * @param columnAxisLabel  the column axis label ({@code null} permitted).
269     * @param valueAxisLabel  the value axis label ({@code null} permitted).
270     * 
271     * @return A line chart (never {@code null}).
272     */
273    public static Chart3D createLineChart(String title, String subtitle,
274            CategoryDataset3D dataset, String rowAxisLabel, 
275            String columnAxisLabel, String valueAxisLabel) {
276        StandardCategoryAxis3D rowAxis 
277                = new StandardCategoryAxis3D(rowAxisLabel);
278        rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
279        StandardCategoryAxis3D columnAxis 
280                = new StandardCategoryAxis3D(columnAxisLabel);
281        columnAxis.setFirstCategoryHalfWidth(true);
282        columnAxis.setLastCategoryHalfWidth(true);
283        NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, 
284                new Range(0.0, 1.0));
285        valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
286        CategoryRenderer3D renderer = new LineRenderer3D();
287        CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, 
288                columnAxis, valueAxis);
289        return new Chart3D(title, subtitle, plot);
290    }
291    
292    /**
293     * Creates and returns a scatter plot based on the supplied dataset 
294     * (containing one or more series of {@code (x, y, z)} values).  The 
295     * chart returned by this method will be constructed with an 
296     * {@link XYZPlot} using a {@link ScatterXYZRenderer}  (so it is safe
297     * to cast the plot and/or renderer to customise attributes that are
298     * specific to those subclasses).
299     * <br><br>
300     * For reference, here is a sample scatter chart:
301     * <div>
302     * <object id="ABC" data="../../doc-files/ScatterPlot3DDemo1.svg"  
303     * type="image/svg+xml" width="564" height="351"> 
304     * </object>
305     * </div>
306     * 
307     * @param title  the chart title ({@code null} permitted).
308     * @param subtitle  the chart subtitle ({@code null} permitted).
309     * @param dataset  the dataset ({@code null} not permitted).
310     * @param xAxisLabel  the x-axis label ({@code null} permitted).
311     * @param yAxisLabel  the y-axis label ({@code null} permitted).
312     * @param zAxisLabel  the z-axis label ({@code null} permitted).
313     * 
314     * @return The chart. 
315     */
316    public static Chart3D createScatterChart(String title, String subtitle, 
317            XYZDataset dataset, String xAxisLabel, String yAxisLabel, 
318            String zAxisLabel) {
319        NumberAxis3D xAxis = new NumberAxis3D(xAxisLabel);
320        NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel);
321        yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
322        NumberAxis3D zAxis = new NumberAxis3D(zAxisLabel);
323        XYZRenderer renderer = new ScatterXYZRenderer();
324        XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis);
325        return new Chart3D(title, subtitle, plot);
326    }
327    
328    /**
329     * Creates a surface chart for the specified function.
330     * <br><br>
331     * For reference, here is a sample surface chart:
332     * <div>
333     * <object id="SurfaceRenderer3DDemo2" data="../../doc-files/SurfaceRendererDemo2.svg"  
334     * type="image/svg+xml" width="562" height="408"> 
335     * </object>
336     * </div>
337     * 
338     * @param title  the chart title ({@code null} permitted).
339     * @param subtitle  the chart subtitle ({@code null} permitted).
340     * @param function  the function ({@code null} not permitted).
341     * @param xAxisLabel  the x-axis label ({@code null} permitted).
342     * @param yAxisLabel  the y-axis label ({@code null} permitted).
343     * @param zAxisLabel  the z-axis label ({@code null} permitted).
344     * 
345     * @return The chart.
346     * 
347     * @since 1.1
348     */
349    public static Chart3D createSurfaceChart(String title, String subtitle, 
350            Function3D function, String xAxisLabel, String yAxisLabel, 
351            String zAxisLabel) {
352        NumberAxis3D xAxis = new NumberAxis3D(xAxisLabel);
353        NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel);
354        yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
355        NumberAxis3D zAxis = new NumberAxis3D(zAxisLabel);
356        XYZRenderer renderer = new SurfaceRenderer(function);
357        // we pass an empty dataset because the plot must have a non-null
358        // dataset, but the renderer never looks at it...
359        XYZPlot plot = new XYZPlot(new XYZSeriesCollection(), renderer, xAxis, 
360                yAxis, zAxis);
361        
362        Chart3D chart = new Chart3D(title, subtitle, plot);
363        chart.setLegendBuilder(new ColorScaleLegendBuilder());
364        return chart;
365    }
366    
367    /**
368     * Creates and returns a bar chart based on the supplied dataset (this is 
369     * for special cases, most general cases will be covered by the 
370     * {@link #createBarChart(String, String, CategoryDataset3D, String, String, String) }
371     * method). The chart returned by this method will be constructed with an 
372     * {@link XYZPlot} using a {@link BarXYZRenderer}  (so it is safe
373     * to cast the plot and/or renderer to customise attributes that are
374     * specific to those subclasses).
375     * <br><br>
376     * For reference, here is a sample XYZ bar chart:
377     * <div>
378     * <object id="ABC" data="../../doc-files/XYZBarChart3DDemo1.svg"  
379     * type="image/svg+xml" width="500" height="359"> 
380     * </object>
381     * </div>
382     * 
383     * @param title  the chart title ({@code null} permitted).
384     * @param subtitle  the chart subtitle ({@code null} permitted).
385     * @param dataset  the dataset ({@code null} not permitted).
386     * @param xAxisLabel  the x-axis label ({@code null} permitted).
387     * @param yAxisLabel  the y-axis label ({@code null} permitted).
388     * @param zAxisLabel  the z-axis label ({@code null} permitted).
389     * 
390     * @return The chart. 
391     */
392    public static Chart3D createXYZBarChart(String title, String subtitle, 
393            XYZDataset dataset, String xAxisLabel, String yAxisLabel, 
394            String zAxisLabel) {
395        ValueAxis3D xAxis = new NumberAxis3D(xAxisLabel);
396        NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel);
397        yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
398        ValueAxis3D zAxis = new NumberAxis3D(zAxisLabel);
399        XYZRenderer renderer = new BarXYZRenderer();
400        XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis);
401        return new Chart3D(title, subtitle, plot);
402    }
403
404    /**
405     * Creates and returns a line chart based on the supplied dataset. The 
406     * chart returned by this method will be constructed with an 
407     * {@link XYZPlot} using a {@link LineXYZRenderer}  (so it is safe
408     * to cast the plot and/or renderer to customise attributes that are
409     * specific to those subclasses).
410     * 
411     * @param title  the chart title ({@code null} permitted).
412     * @param subtitle  the chart subtitle ({@code null} permitted).
413     * @param dataset  the dataset ({@code null} not permitted).
414     * @param xAxisLabel  the x-axis label ({@code null} permitted).
415     * @param yAxisLabel  the y-axis label ({@code null} permitted).
416     * @param zAxisLabel  the z-axis label ({@code null} permitted).
417     * 
418     * @return The chart. 
419     * 
420     * @since 1.5
421     */
422    public static Chart3D createXYZLineChart(String title, String subtitle, 
423            XYZDataset dataset, String xAxisLabel, String yAxisLabel, 
424            String zAxisLabel) {
425        ValueAxis3D xAxis = new NumberAxis3D(xAxisLabel);
426        NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel);
427        yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR);
428        ValueAxis3D zAxis = new NumberAxis3D(zAxisLabel);
429        XYZRenderer renderer = new LineXYZRenderer();
430        XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis);
431        return new Chart3D(title, subtitle, plot);
432    }
433}