在 Java 中组合区域时舍入不准确? [英] Rounding Inaccuracies When Combining Areas in Java?
问题描述
我正在 Java 中使用 Areas
.
I'm working with Areas
in Java.
我的测试程序绘制了三个随机三角形并将它们组合成一个或多个多边形.在 Areas
被 .add()
编在一起后,我使用 PathIterator
来追踪边缘.
My test program draws three random triangles and combines them to form one or more polygons. After the Areas
are .add()
ed together, I use PathIterator
to trace the edges.
然而,有时 Area
对象不会按照它们应该的方式组合......正如您在我发布的最后一张图片中看到的那样,会绘制额外的边缘.
Sometimes, however, the Area
objects will not combine as they should... and as you can see in the last image I posted, extra edges will be drawn.
我认为问题是由于Java的Area
类中的舍入不准确引起的(当我调试测试程序时,Area
显示了差距在使用 PathIterator
之前),但我认为 Java 没有提供任何其他方式来组合形状.
I think the problem is caused by rounding inaccuracies in Java's Area
class (when I debug the test program, the Area
shows the gaps before the PathIterator
is used), but I don't think Java provides any other way to combine shapes.
有什么解决办法吗?
示例代码和图片:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
public class AreaTest extends JFrame{
private static final long serialVersionUID = -2221432546854106311L;
Area area = new Area();
ArrayList<Line2D.Double> areaSegments = new ArrayList<Line2D.Double>();
AreaTest() {
Path2D.Double triangle = new Path2D.Double();
Random random = new Random();
// Draw three random triangles
for (int i = 0; i < 3; i++) {
triangle.moveTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.lineTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.lineTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.closePath();
area.add(new Area(triangle));
}
// Note: we're storing double[] and not Point2D.Double
ArrayList<double[]> areaPoints = new ArrayList<double[]>();
double[] coords = new double[6];
for (PathIterator pi = area.getPathIterator(null); !pi.isDone(); pi.next()) {
// Because the Area is composed of straight lines
int type = pi.currentSegment(coords);
// We record a double array of {segment type, x coord, y coord}
double[] pathIteratorCoords = {type, coords[0], coords[1]};
areaPoints.add(pathIteratorCoords);
}
double[] start = new double[3]; // To record where each polygon starts
for (int i = 0; i < areaPoints.size(); i++) {
// If we're not on the last point, return a line from this point to the next
double[] currentElement = areaPoints.get(i);
// We need a default value in case we've reached the end of the ArrayList
double[] nextElement = {-1, -1, -1};
if (i < areaPoints.size() - 1) {
nextElement = areaPoints.get(i + 1);
}
// Make the lines
if (currentElement[0] == PathIterator.SEG_MOVETO) {
start = currentElement; // Record where the polygon started to close it later
}
if (nextElement[0] == PathIterator.SEG_LINETO) {
areaSegments.add(
new Line2D.Double(
currentElement[1], currentElement[2],
nextElement[1], nextElement[2]
)
);
} else if (nextElement[0] == PathIterator.SEG_CLOSE) {
areaSegments.add(
new Line2D.Double(
currentElement[1], currentElement[2],
start[1], start[2]
)
);
}
}
setSize(new Dimension(500, 500));
setLocationRelativeTo(null); // To center the JFrame on screen
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
}
public void paint(Graphics g) {
// Fill the area
Graphics2D g2d = (Graphics2D) g;
g.setColor(Color.lightGray);
g2d.fill(area);
// Draw the border line by line
g.setColor(Color.black);
for (Line2D.Double line : areaSegments) {
g2d.draw(line);
}
}
public static void main(String[] args) {
new AreaTest();
}
}
成功案例:
失败案例:
推荐答案
这里:
for (int i = 0; i < 3; i++) {
triangle.moveTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.lineTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.lineTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.closePath();
area.add(new Area(triangle));
}
你实际上是在添加第一个循环中的 1 个三角形第二个循环中的 2 个三角形第三个循环中的3个三角形
you are adding in fact 1 triangle in the first loop 2 triangles in the second loop 3 triangles in the third loop
这就是您的不准确之处.试试这个,看看你的问题是否仍然存在.
This is where your inaccuracies come from. Try this and see if your problem still persists.
for (int i = 0; i < 3; i++) {
triangle.moveTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.lineTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.lineTo(random.nextInt(400) + 50, random.nextInt(400) + 50);
triangle.closePath();
area.add(new Area(triangle));
triangle.reset();
}
注意每次循环后路径重置.
Note the path reset after each loop.
更多地解释不准确之处来自您尝试组合的三个路径.这使得可能出现错误的位置一目了然.
to explain more where the inaccuracies come from here the three paths you try to combine. Which makes it obvious where errors might arise.
这篇关于在 Java 中组合区域时舍入不准确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!