在Java中结合区域时舍入不准确? [英] Rounding Inaccuracies When Combining Areas in Java?

查看:151
本文介绍了在Java中结合区域时舍入不准确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Java中使用 Areas



我的测试程序绘制三个随机三角形并将它们结合以形成一个或多个多边形。在 Areas .add()编辑在一起后,我使用 PathIterator

有时候, Area 对象不会像他们应该那样组合。 ..正如你在我发布的最后一张图片中看到的那样,额外的边缘将被绘制出来。



我认为问题是由四舍五入在Java的 Area 类中有错误(当我调试测试程序时, Area 显示 PathIterator ),但我不认为Java提供任何其他方式来组合形状。



任何解决方案?

>

示例代码和图片

  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;


面积= new Area();
ArrayList< Line2D.Double> areaSegments = new ArrayList< Line2D.Double>();

AreaTest(){
Path2D.Double triangle = new Path2D.Double();
Random random = new Random();

//绘制三个随机三角形
(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(新区域(三角形));
}

//注意:我们存储double []而不是Point2D.Double
ArrayList< double []> areaPoints = new ArrayList< double []>();
double [] coords = new double [6];

for(PathIterator pi = area.getPathIterator(null);!pi.isDone(); pi.next()){

//由于区域由直线
int type = pi.currentSegment(coords);
//我们记录一个{segment type,x coord,y coord}的双数组$ {
double [] pathIteratorCoords = {type,coords [0],coords [1]};
areaPoints.add(pathIteratorCoords);
}

double [] start = new double [3]; //记录每个多边形的起始位置
for(int i = 0; i< areaPoints.size(); i ++){
//如果我们不在最后一点,返回一行从这一点到下一个
double [] currentElement = areaPoints.get(i);

//我们需要一个默认值来防止我们到达ArrayList的末尾
double [] nextElement = {-1,-1,-1};
if(i< areaPoints.size() - 1){
nextElement = areaPoints.get(i + 1);
}

//使行
if(currentElement [0] == PathIterator.SEG_MOVETO){
start = currentElement; //记录多边形在哪里开始关闭它
}

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); //将JFrame放在屏幕上
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);


public void paint(Graphics g){
//填充区域
Graphics2D g2d =(Graphics2D)g;
g.setColor(Color.lightGray);
g2d.fill(area);

//逐行绘制边框
g.setColor(Color.black); (Line2D.Double line:areaSegments){
g2d.draw(line);




public static void main(String [] args){
new AreaTest();


$ / code>

成功案例:



失败的案例:

解决方案

这里:

  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(新区域(三角形));



$ b $ p
$ b

实际上你在第一个循环中添加了
1三角形
2个三角形在第二个循环中
3个三角形在第三个循环中

这是您的不准确之处。试试看看你的问题是否仍然存在。

  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(新区域(三角形));
triangle.reset();
}

请注意每个循环后重置的路径。



编辑:解释更多错误来自这里的三条路径,您尝试合并。这使得它明显可能出现错误。








I'm working with Areas in Java.

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.

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.

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.

Any solutions?

Example code and images:

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();
    }
}

A successful case:

A failing case:

解决方案

Here:

    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));
    }       

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.

EDIT: 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆