java - 在 PPTX 中绘制圆弧
问题描述
我想使用 Apache POI 绘制弧线。为此,尚不清楚我需要哪个 API 来设置用于绘图的点。
protected void draw(final XMLSlideShow ppt, final XSLFGroupShape containerGroupShape) {
final XSLFFreeformShape shape = containerGroupShape.createFreeform();
// Positioning
double x = container.toPptX(pos.getX());
double y = container.toPptY(pos.getY());
double w = container.toPpt(pos.getW());
double h = container.toPpt(pos.getH());
// Set shape type & anchor
shape.setShapeType(ShapeType.ARC);
shape.setAnchor(new Rectangle2D.Double(x, y, w, h));
shape.setFillColor(toAwtColor(fillColor));
shape.setLineColor(toAwtColor(strokeColor));
// Which API do I need here?
Path2D.Double gp = new Path2D.Double();
gp.moveTo(0, 0);
gp.lineTo(10, 10);
gp.closePath();
shape.setPath(gp);
}
(注意:这是负责在 pptx 文件中创建弧的方法)
我知道 Polygons 使用Path2D.Double
,但是那种不起作用(或者我的示例数据是错误的?)。我什至尝试查看 VCS 存储库,但我没有运气找到任何使用弧形的测试用例
有人知道弧数据(起始角度、弧长)是如何配置的吗?
编辑:
为避免将来混淆:
- 我不知道如何描述曲线。我不只是通过 2 个点来描述曲线。
- 上面的代码是我正在测试的示例,但不起作用
解决方案
如前所述,您可以创建XSLFSimpleShape类型ShapeType.ARC
。那里的默认弧是锚点描述的矩形中的四分之一圆。或者您使用路径创建自由形式的形状。但是你不能同时做这两个。
如果您创建一个默认值ShapeType.ARC
并查看它,PowerPoint
您将看到两个用于设置开始和结束角度的手柄。操作它们,然后保存文件,然后简单地解压缩*.pptx
文件并查看/ppt/slides/slide1.xml
. 在那里你会发现
<a:avLst>
<a:gd name="adj1" fmla="val [startAngle]"/>
<a:gd name="adj2" fmla="val [endAngle]"/>
</a:avLst>
所以我们需要AvLst
which 是 a CTGeomGuideList
,然后我们可以以编程方式操作这两个句柄(调整)。
另外我们必须知道的唯一一件事是开始角度和结束角度的可能值是多少。一些测试设置导致 0 点位于 3 点钟位置,整圈为 21,600,000。所以6点钟位置是5,400,000,9点钟位置是10,800,000,12点钟位置是16,200,000。这些值与整个圆的大小无关,如果矩形不是正方形,那么这些值甚至是正确的,因此弧是椭圆的。
下面的代码展示了如何使用它来绘制弧线ShapeType.ARC
。
它还展示了如何XSLFFreeformShape
用于绘制圆弧。这里最简单的方法是绘制贝塞尔弧,因为java.awt.geom.Path2D.Double已经提供了创建贝塞尔路径的方法。
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.sl.usermodel.*;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuideList;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
import java.awt.Rectangle;
import java.awt.Color;
import java.awt.geom.Path2D;
import java.awt.geom.Path2D.Double;
public class CreatePPTXArcShape {
private static XSLFAutoShape createArcShape(XSLFSlide slide, Rectangle positionAndSize,
int startAngle, int endAngle, Color color) {
XSLFAutoShape arcShape = ((XSLFSlide)slide).createAutoShape();
arcShape.setShapeType(ShapeType.ARC);
arcShape.setLineColor(color);
arcShape.setAnchor(positionAndSize);
startAngle = startAngle % 360;
endAngle = endAngle % 360;
XmlObject xmlObject = arcShape.getXmlObject();
CTShape ctShape = (CTShape)xmlObject;
CTGeomGuideList ctGeomGuideList = ctShape.getSpPr().getPrstGeom().getAvLst();
CTGeomGuide ctGeomGuide = ctGeomGuideList.addNewGd();
ctGeomGuide.setName("adj1");
ctGeomGuide.setFmla("val " + (21600000/360*startAngle));
ctGeomGuide = ctGeomGuideList.addNewGd();
ctGeomGuide.setName("adj2");
ctGeomGuide.setFmla("val " + (21600000/360*endAngle));
return arcShape;
}
public static void main(String[] args) throws Exception {
SlideShow slideShow = new XMLSlideShow();
Slide slide = slideShow.createSlide();
XSLFAutoShape arcShape;
//circle arcs
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(100, 100, 100, 100),
0, 90, Color.BLUE); //0 degrees = 3 o'clock position, 90 degrees = 6 o'clock position,
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(150, 100, 100, 100),
180, 0, Color.BLUE); //180 degrees = 9 o'clock position
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(200, 100, 100, 100),
270, 90, Color.BLUE); //270 degrees = 12 o'clock position
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(300, 100, 100, 100),
180+45, 270+45, Color.BLUE);
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(400, 100, 100, 100),
0, 359, Color.BLUE);
//elliptic arcs
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(100, 250, 100, 50),
0, 90, Color.BLUE);
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(150, 250, 100, 50),
180, 0, Color.BLUE);
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(200, 250, 100, 50),
270, 90, Color.BLUE);
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(300, 250, 100, 50),
180+45, 270+45, Color.BLUE);
arcShape = createArcShape((XSLFSlide)slide, new Rectangle(400, 250, 100, 50),
0, 359, Color.BLUE);
//Bézier freeform arcs
XSLFFreeformShape bezierShape = ((XSLFSlide)slide).createFreeform();
bezierShape.setLineColor(Color.BLUE);
Path2D.Double path = new Path2D.Double();
path.moveTo(100d, 400d); // x = 100px from left of slide, y = 400px from top of slide
path.curveTo(100d, 400d, 150d, 600d, 200d, 400d); // y of middle point is greater than y of baseline => arc downwards
bezierShape.setPath(path);
bezierShape = ((XSLFSlide)slide).createFreeform();
bezierShape.setLineColor(Color.BLUE);
path = new Path2D.Double();
path.moveTo(300d, 400d);
path.curveTo(300d, 400d, 350d, 200d, 400d, 400d); // y of middle point is less than y of baseline => arc upwards
bezierShape.setPath(path);
FileOutputStream out = new FileOutputStream("CreatePPTXArcShape.pptx");
slideShow.write(out);
out.close();
}
}
推荐阅读
- matlab - 在 Matlab 中为图形添加图例
- azure - Azure Synapse Workspace:脚本在哪里发布?
- c++ - Arduino MEGA - 为什么我的定时器中断在第一次运行时不正确?
- grafana - Grafana/InfluxDB:查询在面板中工作,而不是在变量中
- visual-studio-code - Z3-OCaml 不工作:未绑定模块 Z3 Merlin
- python - 使用 Pandas pd.read_excel 函数的 VBA 的 xldown 的 Python 版本
- github - Visual Studio 代码要求进行 github 身份验证
- github - 如何在 github 操作中修复管道
- docker - Visual Studio 2022 无法在 docker 上启动应用程序
- android - 当设备旋转时,React Native 组件不居中