/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2016, by Object Refinery Limited. All rights reserved. * * http://www.object-refinery.com/orsoncharts/index.html * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package com.orsoncharts.renderer.category; import com.orsoncharts.Range; import com.orsoncharts.data.category.CategoryDataset3D; import com.orsoncharts.data.DataUtils; import com.orsoncharts.data.Values3D; import com.orsoncharts.graphics3d.Dimension3D; import com.orsoncharts.graphics3d.World; import com.orsoncharts.plot.CategoryPlot3D; import com.orsoncharts.Chart3DFactory; import com.orsoncharts.data.KeyedValues3DItemKey; import com.orsoncharts.graphics3d.Object3D; import com.orsoncharts.graphics3d.Offset3D; import com.orsoncharts.label.ItemLabelPositioning; /** * A renderer that can be used with the {@link CategoryPlot3D} class to create * 3D stacked bar charts from data in a {@link CategoryDataset3D}. The * {@code createStackedBarChart()} method in the {@link Chart3DFactory} * class will construct a chart that uses this renderer. Here is a sample: * <div> * <object id="ABC" data="../../../../doc-files/StackedBarChart3DDemo1.svg" * type="image/svg+xml" width="500" height="359"></object> * </div> * (refer to {@code StackedBarChart3DDemo1.java} for the code to generate * the above chart). * <br><br> * There is a factory method to create a chart using this renderer - see * {@link Chart3DFactory#createStackedBarChart(String, String, CategoryDataset3D, String, String, String)}. * <br><br> * NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class StackedBarRenderer3D extends BarRenderer3D { /** * Creates a default constructor. */ public StackedBarRenderer3D() { super(); setItemLabelPositioning(ItemLabelPositioning.FRONT_AND_BACK); setItemLabelOffsets(new Offset3D(0.0, 0.0, -1.0)); } /** * Returns the range of values that will be required on the value axis * to see all the data from the dataset. We override the method to * account for the bars from each series being stacked on top of one * another. * * @param data the data ({@code null} not permitted). * * @return The range (possibly {@code null}) */ @Override public Range findValueRange(Values3D<? extends Number> data) { return DataUtils.findStackedValueRange(data); } /** * Constructs and places one item from the specified dataset into the given * world. This method will be called by the {@link CategoryPlot3D} class * while iterating over the items in the dataset. * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param row the row index. * @param column the column index. * @param world the world ({@code null} not permitted). * @param dimensions the plot dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override @SuppressWarnings("unchecked") public void composeItem(CategoryDataset3D dataset, int series, int row, int column, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { double value = dataset.getDoubleValue(series, row, column); if (Double.isNaN(value)) { return; } double[] stack = DataUtils.stackSubTotal(dataset, getBase(), series, row, column); double lower = stack[1]; if (value < 0.0) { lower = stack[0]; } double upper = lower + value; composeItem(upper, lower, dataset, series, row, column, world, dimensions, xOffset, yOffset, zOffset); } @Override protected void drawItemLabels(World world, CategoryDataset3D dataset, KeyedValues3DItemKey itemKey, double xw, double yw, double zw, double basew, boolean inverted) { ItemLabelPositioning positioning = getItemLabelPositioning(); if (getItemLabelGenerator() != null) { String label = getItemLabelGenerator().generateItemLabel(dataset, itemKey.getSeriesKey(), itemKey.getRowKey(), itemKey.getColumnKey()); if (label != null) { Dimension3D dimensions = getPlot().getDimensions(); double dx = getItemLabelOffsets().getDX(); double dy = getItemLabelOffsets().getDY() * dimensions.getHeight(); double dz = getItemLabelOffsets().getDZ() * getBarZWidth(); if (positioning.equals(ItemLabelPositioning.CENTRAL)) { double yy = yw; if (inverted) { yy = basew; dy = -dy; } Object3D labelObj = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw, false, true); labelObj.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj); } else if (positioning.equals( ItemLabelPositioning.FRONT_AND_BACK)) { double yy = (yw + basew) / 2.0; Object3D labelObj1 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw + dz, false, false); labelObj1.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj1); Object3D labelObj2 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw - dz, true, false); labelObj2.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj2); } } } } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StackedBarRenderer3D)) { return false; } return super.equals(obj); } }