    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}