1.java 2D主要绘图类描述(jdk1.5)
Graphics2D //主要绘图对象,每种图形都要通过该对象来绘制
Rectangle2D //长方形对象
Point2D //点对象
Line2D //线对象
Arc2D.Double //弧形对象
Ellipse2D //椭圆对象
Polygon //多边形对象
Paint //油漆桶对象,用来定义颜色
Stroke //画笔对象,主要用于描绘轮廓,定义线条样式
Area //几何建模对象(含几何并交差运算等方法)
GeneralPath //路径对象
1.1 sample demo eg:
/**
* 利用路径对象绘制平面图
*/
// GeneralPath bar3dRight = new GeneralPath();
// bar3dRight.moveTo((float) 100.0, (float) 100.0);
// bar3dRight.lineTo((float) 200.0, (float) 200.0);
// bar3dRight.lineTo((float) 300.0, (float) 100.0);
// bar3dRight.lineTo((float) 100.0, (float) 100.0);
// bar3dRight.closePath();
// 填充四边形的颜色
// if (itemPaint instanceof Color) {
// g2.setPaint(((Color) itemPaint).darker());
// }
/**
* 长方形对象加路径对象绘制3D柱状图
*/
//正视图
Rectangle2D r2d = new Rectangle2D.Double(
100.0, //x
100.0, //y
30.0, //width
200.0 //hight
);
//右视图
GeneralPath bar3dRight = new GeneralPath();
bar3dRight.moveTo((float) 130.0, (float) 100.0);
bar3dRight.lineTo((float) 150.0, (float) 90.0);
bar3dRight.lineTo((float) 150.0, (float) 290.0);
bar3dRight.lineTo((float) 130.0, (float) 300.0);
bar3dRight.closePath();
//俯视图
GeneralPath bar3dTop = new GeneralPath();
bar3dTop.moveTo((float) 100.0, (float) 100.0);
bar3dTop.lineTo((float) 130.0, (float) 100.0);
bar3dTop.lineTo((float) 150.0, (float) 90.0);
bar3dTop.lineTo((float) 120.0, (float) 90.0);
bar3dTop.closePath();
Paint barpaint = Color.PINK; // 实体颜色
Paint outlinepaint = Color.DARK_GRAY; // 轮廓线颜色
float dash1[] = { 10.0f };
// 虚线条描边
// Stroke stroke = new BasicStroke(1.0f,
// BasicStroke.CAP_BUTT,
// BasicStroke.JOIN_MITER,
// 10.0f, dash1, 0.0f);
// 实线条描边,宽度1.0f
Stroke stroke = new BasicStroke(1.0f);
// g2.setColor(Color.PINK);
// 先设置实体颜色
g2.setPaint(barpaint);
g2.setStroke(stroke);
g2.fill(r2d);
g2.fill(bar3dRight);
g2.fill(bar3dTop);
// 实体填充进绘图对象以后,在设置轮廓线颜色(其实是上面三个实体以外的所有图形的颜色)
g2.setPaint(outlinepaint);
g2.draw(r2d);
g2.draw(bar3dRight);
g2.draw(bar3dTop);
/**
* 利用椭圆对象绘制椭圆
*/
Ellipse2D ellipse2D = new Ellipse2D.Double(200.0, // x
100.0, // y
200.0, // width
200.0 // hight
);
Paint ellipsepaint = Color.blue;
g2.setPaint(ellipsepaint);
g2.fill(ellipse2D);
g2.draw(ellipse2D);
/**
* 利用弧形对象绘制弧形
*/
Arc2D.Double arc = new Arc2D.Double(350.0, // x
100.0, // y
200.0, // width
200.0, // hight
0.0, // start angle
90.0, // arc angle
Arc2D.PIE // pie:3.1415926
);
Arc2D.Double arc2 = new Arc2D.Double(350.0, // x
100.0, // y
200.0, // width
200.0, // hight
-60.0, // start angle
90.0, // arc angle
Arc2D.PIE // pie:3.1415926
);
Paint arcpaint1 = Color.GREEN;
Paint arcpaint2 = Color.RED;
// 设置透明度
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
0.3f));
g2.setPaint(arcpaint1);
g2.fill(arc);
g2.draw(arc);
g2.setPaint(arcpaint2);
g2.fill(arc2);
g2.draw(arc2);
/**
* 图形的几何运算
*/
// Area a = new Area(arc);
// Area b = new Area(arc2);
// ab交差运算,去掉两个图形相交的部分得到的图形
// a.exclusiveOr(b);
// a交b运算
// a.intersect(b);
// a减去b运算,即差运算
// a.subtract(b);
// a并b运算
// a.add(b);
// g2.setPaint(arcpaint2);
// g2.fill(a);
// g2.draw(a);
/**
* 利用jfreechart的TextBox对象绘制文本框
*/
// 设置透明度为1,也就是不透明了
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
1.0f));
TextBox textBox = new TextBox("java" // 想要显示的字符串
);
textBox.draw(g2, // 绘图对象
(float) 550.0, // x坐标
(float) 100.0, // y坐标
RectangleAnchor.CENTER // 对齐方式
);
Line2D.Double line = new Line2D.Double(522.0, // 线的第一个点的x坐标
100.0, // 线的第一个点的y坐标
500.0, // 线的第二个点的x坐标
120.0 // 线的第二个点的y坐标
);
g2.draw(line);
/**
* 写字
*/
// 字体设置
Font font = new Font(null, // 字体
Font.ITALIC + Font.BOLD, // 样式(这里设置了两种样式,黑体+斜体)
10); // 大小
g2.setFont(font);
Paint arcpaint3 = Color.BLACK;
g2.setPaint(arcpaint3);
g2.drawString("delphi", // 要写的字符串
550, // x坐标
150 // y坐标
);
/**
* 利用多边形对象绘制多边形
*/
int []xs = new int[] { 600, 620,
640, 620 };
int []ys = new int[] { 100,
100, 150,
150};
Polygon polygon = new Polygon(
xs, //多边形x坐标点的数组
ys, //多边形y坐标点的数组
4 //数组大小
);
g2.setPaint(java.awt.Color.lightGray);
g2.fill(polygon);
g2.draw(polygon);
/**
* 画网格线
*/
for(double i=0.0; i<450.0; i+=30.0){
// 网格线样式
Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke(0.5f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL,
0.0f,
new float[] {2.0f, 2.0f},
0.0f);
Line2D.Double gridline = new Line2D.Double(0.0,i+30.0,700.0,i+30.0);
g2.setPaint(Color.GRAY);
g2.setStroke(DEFAULT_GRIDLINE_STROKE);
g2.draw(gridline);
}
2.柱状图2D和3D是通过CategoryPlot的renderer属性来区别的
BarRenderer //2DBarRenderer
BarRenderer3D //3DBarRenderer
CategoryPlot plot = new CategoryPlot(
dataset, categoryAxis, valueAxis, renderer
);
3.3D饼图的绘制函数(现在的注释还不够全面,也可能存在错误)
/**
* Draws the plot on a Java 2D graphics device (such as the screen or a
* printer). This method is called by the {@link org.jfree.chart.JFreeChart}
* class, you don't normally need to call it yourself.
*
* @param g2
* the graphics device.
* @param plotArea
* the area within which the plot should be drawn.
* @param anchor
* the anchor point.
* @param parentState
* the state from the parent plot, if there is one.
* @param info
* collects info about the drawing (<code>null</code>
* permitted).
*/
public void draw(Graphics2D g2, Rectangle2D plotArea, Point2D anchor,
PlotState parentState, PlotRenderingInfo info) {
// adjust for insets...
RectangleInsets insets = getInsets();
insets.trim(plotArea);
Rectangle2D originalPlotArea = (Rectangle2D) plotArea.clone();
if (info != null) {
info.setPlotArea(plotArea);
info.setDataArea(plotArea);
}
Shape savedClip = g2.getClip();
g2.clip(plotArea);
// adjust the plot area by the interior spacing value
double gapPercent = getInteriorGap();
double labelPercent = 0.0;
if (getLabelGenerator() != null) {
labelPercent = getLabelGap() + getMaximumLabelWidth()
+ getLabelLinkMargin();
}
// 水平方向的间隙
double gapHorizontal = plotArea.getWidth()
* (gapPercent + labelPercent);
// 垂直方向的间隙
double gapVertical = plotArea.getHeight() * gapPercent;
// x坐标大小
double linkX = plotArea.getX() + gapHorizontal / 2;
// y坐标大小
double linkY = plotArea.getY() + gapVertical / 2;
// 图形宽度
double linkW = plotArea.getWidth() - gapHorizontal;
// 图形高度
double linkH = plotArea.getHeight() - gapVertical;
// make the link area a square if the pie chart is to be circular...
if (isCircular()) { // is circular?
double min = Math.min(linkW, linkH) / 2;
linkX = (linkX + linkX + linkW) / 2 - min;
linkY = (linkY + linkY + linkH) / 2 - min;
linkW = 2 * min;
linkH = 2 * min;
}
PiePlotState state = initialise(g2, plotArea, this, null, info);
// the explode area defines the max circle/ellipse for the exploded pie
// sections.
// it is defined by shrinking the linkArea by the linkMargin factor.
double hh = linkW * getLabelLinkMargin();
double vv = linkH * getLabelLinkMargin();
Rectangle2D explodeArea = new Rectangle2D.Double(linkX + hh / 2.0,
linkY + vv / 2.0, linkW - hh, linkH - vv);
state.setExplodedPieArea(explodeArea);
// the pie area defines the circle/ellipse for regular pie sections.
// it is defined by shrinking the explodeArea by the explodeMargin
// factor.
double maximumExplodePercent = getMaximumExplodePercent();
double percent = maximumExplodePercent / (1.0 + maximumExplodePercent);
double h1 = explodeArea.getWidth() * percent;
double v1 = explodeArea.getHeight() * percent;
Rectangle2D pieArea = new Rectangle2D.Double(explodeArea.getX() + h1
/ 2.0, explodeArea.getY() + v1 / 2.0, explodeArea.getWidth()
- h1, explodeArea.getHeight() - v1);
// 定义3D椭圆的高度
int depth = (int) (pieArea.getHeight() * this.depthFactor);
// the link area defines the dog-leg point for the linking lines to
// the labels
Rectangle2D linkArea = new Rectangle2D.Double(linkX, linkY, linkW,
linkH - depth);
state.setLinkArea(linkArea);
state.setPieArea(pieArea);
// 定义椭圆中心点
state.setPieCenterX(pieArea.getCenterX());
state.setPieCenterY(pieArea.getCenterY() - depth / 2.0);
// 定义椭圆宽的半径
state.setPieWRadius(pieArea.getWidth() / 2.0);
// 定义椭圆高的半径
state.setPieHRadius((pieArea.getHeight() - depth) / 2.0);
// 画背景长方形(500*300)区域
drawBackground(g2, plotArea);
// 获取外面传进来3D饼图的数据源
PieDataset dataset = getDataset();
// 如果数据源为空则直接返回,整个图表就一个背景长方形没有数据图形
if (DatasetUtilities.isEmptyOrNull(getDataset())) {
drawNoDataMessage(g2, plotArea);
g2.setClip(savedClip);
drawOutline(g2, plotArea);
return;
}
/**
* 如果数据源的主键的个数大于图形区域的宽度,则在图形上显示"Too many elements" 数据源示例如下: final
* DefaultPieDataset result = new DefaultPieDataset();
* result.setValue("Java", new Double(43.2));
* result.setValue("VisualBasic", new Double(10.0));
* result.setValue("C/C++", new Double(17.5));
* result.setValue("PHP", new Double(32.5));
* result.setValue("Perl", new Double(1.0));
* return result;
* 这个数据源的主键的个数为5
*/
if (dataset.getKeys().size() > plotArea.getWidth()) {
String text = "Too many elements";
Font sfont = new Font("dialog", Font.BOLD, 10);
g2.setFont(sfont);
FontMetrics fm = g2.getFontMetrics(sfont);
int stringWidth = fm.stringWidth(text);
g2
.drawString(text, (int) (plotArea.getX() + (plotArea
.getWidth() - stringWidth) / 2), (int) (plotArea
.getY() + (plotArea.getHeight() / 2)));
return;
}
// if we are drawing a perfect circle, we need to readjust the top left
// coordinates of the drawing area for the arcs to arrive at this
// effect.
// 如果我们画的是一个圆形那只要知道图形的左边距,上边距,和直径
if (isCircular()) {
// 圆形半径(取宽高中的小的那个数的一半)
double min = Math.min(plotArea.getWidth(), plotArea.getHeight()) / 2;
plotArea = new Rectangle2D.Double(
plotArea.getCenterX() - min, //左边距(新的图形的中心点x坐标)
plotArea.getCenterY() - min, //上边距(新的图形的中心点y坐标)
2 * min, //直径(图形的宽度)
2 * min //直径(图形的高度)
);
}
// 获取数据源主键列表
List sectionKeys = dataset.getKeys();
// 如果数据源主键列表为空,退出
if (sectionKeys.size() == 0) {
return;
}
// establish the coordinates of the top left corner of the drawing area
//确定pieArea区域的中心点
double arcX = pieArea.getX();
double arcY = pieArea.getY();
// g2.clip(clipArea);
Composite originalComposite = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
getForegroundAlpha()));
//把数据源每个主键对应的值加起来
double totalValue = DatasetUtilities.calculatePieDatasetTotal(dataset);
//遍历列表的时候用到
double runningTotal = 0;
//如果高度<0退出
if (depth < 0) {
return; // if depth is negative don't draw anything
}
//弧形的列表(用于添加主键的值对应的弧形)
ArrayList arcList = new ArrayList();
//定义一个弧行
Arc2D.Double arc;
//定义油漆桶,用来填充颜色
Paint paint;
Paint outlinePaint;
//用于描绘轮廓的样式
Stroke outlineStroke;
//遍历取出主键的值对应的弧形放到弧形列表
Iterator iterator = sectionKeys.iterator();
while (iterator.hasNext()) {
// 取出主键的值
Comparable currentKey = (Comparable) iterator.next();
Number dataValue = dataset.getValue(currentKey);
// 如果主键的值为空,则弧形为空
if (dataValue == null) {
arcList.add(null);
continue;
}
// 如果主键的值<=0,则弧形为空
double value = dataValue.doubleValue();
if (value <= 0) {
arcList.add(null);
continue;
}
//弧形的开始角度(从该角度算起,相当于360度的0度)
double startAngle = getStartAngle();
//方向
double direction = getDirection().getFactor();
//角度大小1(该主键对应的弧形的开始角度)
double angle1 = startAngle + (direction * (runningTotal * 360))
/ totalValue;
//角度大小2(该主键对应的弧形的结束角度)
double angle2 = startAngle
+ (direction * (runningTotal + value) * 360) / totalValue;
//如果弧形的角度大小<0.00001则该弧形为空
if (Math.abs(angle2 - angle1) > getMinimumArcAngleToDraw()) {
arcList.add(new Arc2D.Double(arcX, arcY + depth, pieArea
.getWidth(), pieArea.getHeight() - depth, angle1,
angle2 - angle1, Arc2D.PIE));
} else {
arcList.add(null);
}
//转入下个弧形(主键对应的图形)
runningTotal += value;
}
//取出剪裁的图形(500*300)
Shape oldClip = g2.getClip();
//3D饼图中上面的椭圆
Ellipse2D top = new Ellipse2D.Double(pieArea.getX(), pieArea.getY(),
pieArea.getWidth(), pieArea.getHeight() - depth);
// 3D饼图中底部的椭圆
Ellipse2D bottom = new Ellipse2D.Double(pieArea.getX(), pieArea.getY()
+ depth, pieArea.getWidth(), pieArea.getHeight() - depth);
//底部的长方形
Rectangle2D lower = new Rectangle2D.Double(top.getX(),
top.getCenterY(), pieArea.getWidth(), bottom.getMaxY()
- top.getCenterY());
//上部的长方形
Rectangle2D upper = new Rectangle2D.Double(pieArea.getX(), top.getY(),
pieArea.getWidth(), bottom.getCenterY() - top.getY());
// Area几何建模对象
Area a = new Area(top);
a.add(new Area(lower));
Area b = new Area(bottom);
b.add(new Area(upper));
Area pie = new Area(a);
// 通过几何建模对象对上面的图形进行交叉运算
pie.intersect(b);
Area front = new Area(pie);
// 相减运算
front.subtract(new Area(top));
Area back = new Area(pie);
// 相减运算
back.subtract(new Area(bottom));
// draw the bottom circle
int[] xs;
int[] ys;
outlinePaint = getSectionOutlinePaint(0);
arc = new Arc2D.Double(arcX, arcY + depth, pieArea.getWidth(), pieArea
.getHeight()
- depth, 0, 360, Arc2D.PIE);
// 画出3D饼图下部的椭圆的弧形和有该图形的高度组成的多边形
int categoryCount = arcList.size();
for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {
//取出弧形
arc = (Arc2D.Double) arcList.get(categoryIndex);
if (arc == null) {
continue;
}
paint = getSectionPaint(categoryIndex);
outlinePaint = getSectionOutlinePaint(categoryIndex);
outlineStroke = getSectionOutlineStroke(categoryIndex);
g2.setPaint(paint);
//填充弧形
g2.fill(arc);
g2.setPaint(outlinePaint);
g2.setStroke(outlineStroke);
//绘制弧形
g2.draw(arc);
g2.setPaint(paint);
//取得弧形的开始点
Point2D p1 = arc.getStartPoint();
// 定义多边形(弧形的高度组成的图形)
xs = new int[] { (int) arc.getCenterX(), (int) arc.getCenterX(),
(int) p1.getX(), (int) p1.getX() };
ys = new int[] { (int) arc.getCenterY(),
(int) arc.getCenterY() - depth, (int) p1.getY() - depth,
(int) p1.getY() };
Polygon polygon = new Polygon(
xs, //多边形x坐标点的数组
ys, //多边形y坐标点的数组
4 //数组大小
);
g2.setPaint(java.awt.Color.lightGray);
g2.fill(polygon);
g2.setPaint(outlinePaint);
g2.setStroke(outlineStroke);
//绘制该多边形
g2.draw(polygon);
g2.setPaint(paint);
}
g2.setPaint(Color.gray);
g2.fill(back);
g2.fill(front);
// cycle through once drawing only the sides at the back...
// 描出背部的边
int cat = 0;
iterator = arcList.iterator();
while (iterator.hasNext()) {
Arc2D segment = (Arc2D) iterator.next();
if (segment != null) {
paint = getSectionPaint(cat);
outlinePaint = getSectionOutlinePaint(cat);
outlineStroke = getSectionOutlineStroke(cat);
drawSide(g2, pieArea, segment, front, back, paint,
outlinePaint, outlineStroke, false, true);
}
cat++;
}
// cycle through again drawing only the sides at the front...
// 描出前面的边
cat = 0;
iterator = arcList.iterator();
while (iterator.hasNext()) {
Arc2D segment = (Arc2D) iterator.next();
if (segment != null) {
paint = getSectionPaint(cat);
outlinePaint = getSectionOutlinePaint(cat);
outlineStroke = getSectionOutlineStroke(cat);
drawSide(g2, pieArea, segment, front, back, paint,
outlinePaint, outlineStroke, true, false);
}
cat++;
}
g2.setClip(oldClip);
// 画出3D饼图上部的椭圆的弧形和相关的标签链接和底部的说明(tooltip)
Arc2D upperArc;
for (int sectionIndex = 0; sectionIndex < categoryCount; sectionIndex++) {
//取出弧形
arc = (Arc2D.Double) arcList.get(sectionIndex);
if (arc == null) {
continue;
}
//定义3D饼图上部的椭圆的弧形
upperArc = new Arc2D.Double(arcX, arcY, pieArea.getWidth(), pieArea
.getHeight()
- depth,
arc.getAngleStart(), //开始角度
arc.getAngleExtent(), //角度大小
Arc2D.PIE);
//g2图形对象所需的油漆桶
paint = getSectionPaint(sectionIndex);
//g2图形对象所需的轮廓油漆桶
outlinePaint = getSectionOutlinePaint(sectionIndex);
//g2图形对象所需的轮廓样式
outlineStroke = getSectionOutlineStroke(sectionIndex);
g2.setPaint(paint);
//往g2图形对象中填充弧形
g2.fill(upperArc);
g2.setStroke(outlineStroke);
g2.setPaint(outlinePaint);
//绘制弧形
g2.draw(upperArc);
// 为该部分弧形添加说明栏(tooltip)和url链接
Comparable currentKey = (Comparable) sectionKeys.get(sectionIndex);
if (info != null) {
EntityCollection entities = info.getOwner()
.getEntityCollection();
if (entities != null) {
String tip = null;
PieToolTipGenerator tipster = getToolTipGenerator();
if (tipster != null) {
// @mgs: using the method's return value was missing
tip = tipster.generateToolTip(dataset, currentKey);
}
String url = null;
if (getURLGenerator() != null) {
url = getURLGenerator().generateURL(dataset,
currentKey, getPieIndex());
}
PieSectionEntity entity = new PieSectionEntity(upperArc,
dataset, getPieIndex(), sectionIndex, currentKey,
tip, url);
entities.add(entity);
}
}
List keys = dataset.getKeys();
//绘制标签的长方形
Rectangle2D adjustedPlotArea = new Rectangle2D.Double(
originalPlotArea.getX(), originalPlotArea.getY(),
originalPlotArea.getWidth(), originalPlotArea.getHeight()
- depth);
//绘制标签(如:Perl=1的Textbox)
drawLabels(g2, keys, totalValue, adjustedPlotArea, linkArea, state);
}
g2.setClip(savedClip);
g2.setComposite(originalComposite);
//绘制轮廓
drawOutline(g2, originalPlotArea);
}
4.3D柱状图的绘制函数(现在的注释还不够全面,也可能存在错误)
/**
* Draws a 3D bar to represent one data item.
*
* @param g2 the graphics device.
* @param state the renderer state.
* @param dataArea the area for plotting the data.
* @param plot the plot.
* @param domainAxis the domain axis.
* @param rangeAxis the range axis.
* @param dataset the dataset.
* @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,
Rectangle2D dataArea,
CategoryPlot plot,
CategoryAxis domainAxis,
ValueAxis rangeAxis,
CategoryDataset dataset,
int row,
int column,
int pass) {
// check the value we are plotting...
Number dataValue = dataset.getValue(row, column);
if (dataValue == null) {
return;
}
double value = dataValue.doubleValue();
Rectangle2D adjusted = new Rectangle2D.Double(
dataArea.getX(),
dataArea.getY() + getYOffset(),
dataArea.getWidth() - getXOffset(),
dataArea.getHeight() - getYOffset()
);
PlotOrientation orientation = plot.getOrientation();
double barW0 = calculateBarW0(
plot, orientation, adjusted, domainAxis, state, row, column
);
double[] barL0L1 = calculateBarL0L1(value);
if (barL0L1 == null) {
return; // the bar is not visible
}
RectangleEdge edge = plot.getRangeAxisEdge();
double transL0 = rangeAxis.valueToJava2D(barL0L1[0], adjusted, edge);
double transL1 = rangeAxis.valueToJava2D(barL0L1[1], adjusted, edge);
double barL0 = Math.min(transL0, transL1);
double barLength = Math.abs(transL1 - transL0);
// draw the bar...
//柱子的正视图
Rectangle2D bar = null;
if (orientation == PlotOrientation.HORIZONTAL) {
bar = new Rectangle2D.Double(
barL0, barW0, barLength, state.getBarWidth()
);
}
else {
bar = new Rectangle2D.Double(
barW0, barL0, state.getBarWidth(), barLength
);
}
Paint itemPaint = getItemPaint(row, column);
g2.setPaint(itemPaint);
g2.fill(bar);
// 柱子的俯视图上的四个点的x坐标值
double x0 = bar.getMinX();
double x1 = x0 + getXOffset(); //x0+12
double x2 = bar.getMaxX();
double x3 = x2 + getXOffset(); //x2+12
// 柱子的右视图上的四个点的y坐标值
double y0 = bar.getMinY() - getYOffset(); //正视图的最小y值-8
double y1 = bar.getMinY();
double y2 = bar.getMaxY() - getYOffset(); //正视图的最大y值-8
double y3 = bar.getMaxY();
GeneralPath bar3dRight = null;
GeneralPath bar3dTop = null;
// 柱子的右视图
if (barLength > 0.0) {
bar3dRight = new GeneralPath();
bar3dRight.moveTo((float) x2, (float) y3);
bar3dRight.lineTo((float) x2, (float) y1);
bar3dRight.lineTo((float) x3, (float) y0);
bar3dRight.lineTo((float) x3, (float) y2);
bar3dRight.closePath();
if (itemPaint instanceof Color) {
g2.setPaint(((Color) itemPaint).darker());
}
g2.fill(bar3dRight);
}
// 柱子的俯视图
bar3dTop = new GeneralPath();
bar3dTop.moveTo((float) x0, (float) y1);
bar3dTop.lineTo((float) x1, (float) y0);
bar3dTop.lineTo((float) x3, (float) y0);
bar3dTop.lineTo((float) x2, (float) y1);
bar3dTop.closePath();
g2.fill(bar3dTop);
//绘制3D柱状图
if (isDrawBarOutline()
&& state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
g2.setStroke(getItemOutlineStroke(row, column));
g2.setPaint(getItemOutlinePaint(row, column));
g2.draw(bar);
if (bar3dRight != null) {
g2.draw(bar3dRight);
}
if (bar3dTop != null) {
g2.draw(bar3dTop);
}
}
//绘制标签
CategoryItemLabelGenerator generator
= getItemLabelGenerator(row, column);
if (generator != null && isItemLabelVisible(row, column)) {
drawItemLabel(
g2, dataset, row, column, plot, generator, bar, (value < 0.0)
);
}
// add an item entity, if this information is being collected
EntityCollection entities = state.getEntityCollection();
if (entities != null) {
GeneralPath barOutline = new GeneralPath();
barOutline.moveTo((float) x0, (float) y3);
barOutline.lineTo((float) x0, (float) y1);
barOutline.lineTo((float) x1, (float) y0);
barOutline.lineTo((float) x3, (float) y0);
barOutline.lineTo((float) x3, (float) y2);
barOutline.lineTo((float) x2, (float) y3);
barOutline.closePath();
addItemEntity(entities, dataset, row, column, barOutline);
}
}