📄 stackedcylinderrenderer.java
字号:
if (baseIndex < 0)
{
result.add(new Object[] { null, new Double(base) });
baseIndex = 0;
}
negBase = negBase + v; // '+' because v is negative
result.add(0, new Object[] { new Integer(-s),
new Double(negBase) });
baseIndex++;
}
}
// System.out.println("this StackedCylinder createStackedValueList.");
return result;
}
/**
* Draws the visual representation of one data item from the chart (in fact,
* this method does nothing until it reaches the last item for each
* category, at which point it draws all the items for that category).
*
* @param g2
* the graphics device.
* @param state
* the renderer state.
* @param dataArea
* the plot area.
* @param plot
* the plot.
* @param domainAxis
* the domain (category) axis.
* @param rangeAxis
* the range (value) axis.
* @param dataset
* the data.
* @param row
* the row index (zero-based).
* @param column
* the column index (zero-based).
* @param pass
* the pass index.
*/
public void drawItem(
Graphics2D g2,
CategoryItemRendererState state, //An object that retains temporary state information for a CategoryItemRenderer
Rectangle2D dataArea,
CategoryPlot plot,
CategoryAxis domainAxis,
ValueAxis rangeAxis,
CategoryDataset dataset,
int row,
int column,
int pass)
{
// wait till we are at the last item for the row then draw the
// whole stack at once
if (row < dataset.getRowCount() - 1)
{
return;
}
Comparable category = dataset.getColumnKey(column); //列主键
List values = createStackedValueList(
dataset,
dataset.getColumnKey(column),//列主键
getBase(), //基线
this.renderAsPercentages);//列百分比标志
Rectangle2D adjusted = new Rectangle2D.Double(
dataArea.getX(),
dataArea.getY() + getYOffset(),
dataArea.getWidth() - getXOffset(),
dataArea.getHeight() - getYOffset());
PlotOrientation orientation = plot.getOrientation();
// handle rendering separately for the two plot orientations...
if (orientation == PlotOrientation.HORIZONTAL)
{
drawStackHorizontal(values, category, g2, state, adjusted, plot,
domainAxis, rangeAxis, dataset);
} else
{
drawStackVertical(values, category, g2, state, adjusted, plot,
domainAxis, rangeAxis, dataset);
}
}
/**
* Draws a stack of bars for one category, with a horizontal orientation.
*
* @param values
* the value list.
* @param category
* the category.
* @param g2
* the graphics device.
* @param state
* the state. //An object that retains temporary state information for a CategoryItemRenderer
* @param dataArea
* the data area (adjusted for the 3D effect).
* @param plot
* the plot.
* @param domainAxis
* the domain axis.
* @param rangeAxis
* the range axis.
* @param dataset
* the dataset.
*
* @since 1.0.4
*/
protected void drawStackHorizontal(
List values,
Comparable category, //列主键
Graphics2D g2,
CategoryItemRendererState state,
Rectangle2D dataArea,
CategoryPlot plot,
CategoryAxis domainAxis,
ValueAxis rangeAxis,
CategoryDataset dataset)
{
System.out.println("into the StackedCylinder drawStackHorizontal.");
int column = dataset.getColumnIndex(category);
/**
* CategoryAxis //An axis that displays categories.
* CategoryAxis.getCategoryMiddle() //Returns the middle coordinate for the specified category.
*/
double barX0 = domainAxis.getCategoryMiddle(column, dataset
.getColumnCount(), dataArea, plot.getDomainAxisEdge())
- state.getBarWidth() / 2.0; //获取中间坐标减去宽度的一半,回到开始x坐标
double barW = state.getBarWidth();
// a list to store the series index and bar region, so we can draw
// all the labels at the end...
List itemLabelList = new ArrayList();
// draw the blocks
boolean inverted = rangeAxis.isInverted();
int blockCount = values.size() - 1; //一列的分块总数
for (int k = 0; k < blockCount; k++)
{
int index = (inverted ? blockCount - k - 1 : k);
Object[] prev = (Object[]) values.get(index);
Object[] curr = (Object[]) values.get(index + 1);
int series = 0;
if (curr[0] == null)
{
series = -((Integer) prev[0]).intValue();
}
else
{
series = ((Integer) curr[0]).intValue();
if (series < 0)
{
series = -((Integer) prev[0]).intValue();
}
}
/**
* ValueAxis.valueToJava2D
* Converts a data value to a coordinate in Java2D space,
* assuming that the axis runs along one edge of the specified dataArea.
* 前一个坐标 List values[] have Object[](index,基线值+stackValue)
*/
double v0 = ((Double) prev[1]).doubleValue();
double vv0 = rangeAxis.valueToJava2D(v0, dataArea, plot
.getRangeAxisEdge());
double v1 = ((Double) curr[1]).doubleValue();
double vv1 = rangeAxis.valueToJava2D(v1, dataArea, plot
.getRangeAxisEdge());
Shape[] faces = createHorizontalBlock(barX0, barW, vv0, vv1,
inverted);//x轴开始坐标,bar宽度,
// Shape[] faces = createHorizontalBlockCylinded(barX0, barW, vv0, vv1);
/**
* getItemPaint(int row, int column) //extends class AbstractRenderer
* Returns the paint used to fill data items as they are drawn.
*/
Paint fillPaint = getItemPaint(series, column);
Paint outlinePaint = getItemOutlinePaint(series, column);
g2.setStroke(getItemOutlineStroke(series, column));
for (int f = 0; f < 6; f++) //draw cubical six faces
{
g2.setPaint(fillPaint);
g2.fill(faces[f]);
g2.setPaint(outlinePaint);
g2.draw(faces[f]);
}
/**
* GeneralPath.getBoundes2D()
* Returns the bounding box of the path
* faces[5] is front
*/
itemLabelList.add(new Object[] { new Integer(series),
faces[5].getBounds2D(),
BooleanUtilities.valueOf(v0 < getBase()) });
// add an item entity, if this information is being collected
EntityCollection entities = state.getEntityCollection();
if (entities != null)
{
addItemEntity(entities, dataset, series, column, faces[5]);
}
}
/**
* itemLableList storage every block information
*/
for (int i = 0; i < itemLabelList.size(); i++)
{
Object[] record = (Object[]) itemLabelList.get(i);
int series = ((Integer) record[0]).intValue();
Rectangle2D bar = (Rectangle2D) record[1];
boolean neg = ((Boolean) record[2]).booleanValue(); //is negative
// getItemLabelGenerator(int row, int column)
// Returns the item label generator for a data item.
CategoryItemLabelGenerator generator = getItemLabelGenerator(
series, column);
if (generator != null && isItemLabelVisible(series, column))
{
drawItemLabel(g2, dataset, series, column, plot, generator,
bar, neg);
}
}
}
/**
* Creates an array of shapes representing the six sides of a block in a
* horizontal stack.
*
* @param x0
* left edge of bar (in Java2D space).
* @param width
* the width of the bar (in Java2D units).
* @param y0
* the base of the block (in Java2D space).
* @param y1
* the top of the block (in Java2D space).
* @param inverted
* a flag indicating whether or not the block is inverted (this
* changes the order of the faces of the block).
*
* @return The sides of the block.
*/
private Shape[] createHorizontalBlock(double x0, double width, double y0,
double y1, boolean inverted)// x轴开始坐标,bar宽度,前一个y轴基线点,当前y轴基线点
{
Shape[] result = new Shape[6];
/**
* Point2D : The Double class defines a point specified in double precision.
* The Point2D class defines a point representing a location in (x, y) coordinate space.
* This class is only the abstract superclass for all objects that store a 2D coordinate.
* The actual storage representation of the coordinates is left to the subclass.
*/
Point2D p00 = new Point2D.Double(y0, x0);
Point2D p01 = new Point2D.Double(y0, x0 + width);
Point2D p02 = new Point2D.Double(p01.getX() + getXOffset(), p01.getY()
- getYOffset());
Point2D p03 = new Point2D.Double(p00.getX() + getXOffset(), p00.getY()
- getYOffset());
Point2D p0 = new Point2D.Double(y1, x0);
Point2D p1 = new Point2D.Double(y1, x0 + width);
Point2D p2 = new Point2D.Double(p1.getX() + getXOffset(), p1.getY()
- getYOffset());
Point2D p3 = new Point2D.Double(p0.getX() + getXOffset(), p0.getY()
- getYOffset());
/**
* The GeneralPath class represents a geometric path
* constructed from straight lines, and quadratic
* and cubic (Bézier) curves. It can contain multiple subpaths.
*/
GeneralPath bottom = new GeneralPath(); //底部
bottom.moveTo((float) p1.getX(), (float) p1.getY());
bottom.lineTo((float) p01.getX(), (float) p01.getY());
bottom.lineTo((float) p02.getX(), (float) p02.getY());
bottom.lineTo((float) p2.getX(), (float) p2.getY());
bottom.closePath();
GeneralPath top = new GeneralPath(); //顶部
top.moveTo((float) p0.getX(), (float) p0.getY());
top.lineTo((float) p00.getX(), (float) p00.getY());
top.lineTo((float) p03.getX(), (float) p03.getY());
top.lineTo((float) p3.getX(), (float) p3.getY());
top.closePath();
GeneralPath back = new GeneralPath(); //
back.moveTo((float) p2.getX(), (float) p2.getY());
back.lineTo((float) p02.getX(), (float) p02.getY());
back.lineTo((float) p03.getX(), (float) p03.getY());
back.lineTo((float) p3.getX(), (float) p3.getY());
back.closePath();
GeneralPath front = new GeneralPath();
front.moveTo((float) p0.getX(), (float) p0.getY());
front.lineTo((float) p1.getX(), (float) p1.getY());
front.lineTo((float) p01.getX(), (float) p01.getY());
front.lineTo((float) p00.getX(), (float) p00.getY());
front.closePath();
GeneralPath left = new GeneralPath();
left.moveTo((float) p0.getX(), (float) p0.getY());
left.lineTo((float) p1.getX(), (float) p1.getY());
left.lineTo((float) p2.getX(), (float) p2.getY());
left.lineTo((float) p3.getX(), (float) p3.getY());
left.closePath();
GeneralPath right = new GeneralPath();
right.moveTo((float) p00.getX(), (float) p00.getY());
right.lineTo((float) p01.getX(), (float) p01.getY());
right.lineTo((float) p02.getX(), (float) p02.getY());
right.lineTo((float) p03.getX(), (float) p03.getY());
right.closePath();
result[0] = bottom;
result[1] = back;
if (inverted)
{
result[2] = right;
result[3] = left;
} else
{
result[2] = left;
result[3] = right;
}
result[4] = top;
result[5] = front;
return result;
}
/**
* Draws a stack of bars for one category, with a vertical orientation.
*
* @param values
* the value list.
* @param category
* the category.
* @param g2
* the graphics device.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -