2016-06-07 7 views
2

많은 2D 부동 소수점 폴리곤으로 작업합니다. 나는 다른 것을 뺄 필요가있는 유스 케이스를 생각해 냈습니다. 그래서 java.awt.geom.Area를 사용할 것이라고 생각했습니다. 내가 네 점과 지역 객체 생성 :개체 복제 지점이 java.awt.geom.Area입니까?

SEG_MOVETO, 150.0, 0.0 
SEG_LINETO, 100.0, 50.0 
SEG_LINETO, 99.99999999999973, 54.24264068711893 
SEG_LINETO, 99.99999999999974, 54.24264068711893 
SEG_LINETO, 151.41421356237308, 2.8284271247461112 
SEG_LINETO, 150.0, 0.0 
SEG_CLOSE, 150.0, 0.0 

참고 거의 동일에게 :

100.0, 50.0 
150.0, 0.0 
151.41421356237308, 2.8284271247461112 
99.99999999999973, 54.242640687118936 

그리고 지역을 만들 때 나는 그 점을 주문하는 방법의 독립을, 나는 다음 다시 얻을 이중 99.99999999999973, 54.24264068711893 좌표입니다.

피하는 방법에 대한 단서를 가장 환영합니다. 여기에 코드입니다 :

import java.awt.geom.Area; 
import java.awt.geom.Path2D; 
import java.awt.geom.PathIterator; 

class Main { 
    public static final void main(String args[]) { 
     double[] myPoly = {100.0, 50.0, 150.0, 0.0, 151.41421356237308, 2.8284271247461112, 99.99999999999973, 54.242640687118936}; 
     final Area myArea = makeArea(myPoly); 
     System.out.println(areaToString(myArea)); 
    } 

    private static Area makeArea(double coords[]) { 
     final Path2D path = new Path2D.Double(); 
     path.moveTo(coords[0], coords[1]); 
     for (int i = 2; i < coords.length; i+=2) { 
      path.lineTo(coords[i], coords[i+1]); 
     } 
     path.closePath(); 
     return new Area(path); 
    } 

    private static String areaToString(final Area area) { 
     final StringBuffer out = new StringBuffer("Area [\n"); 
     double []pt = new double[6]; 
     for (PathIterator pi = area.getPathIterator(null); !pi.isDone(); pi.next()) { 
      int type = pi.currentSegment(pt); 
      out.append(type).append(", ").append(pt[0]).append(", ").append(pt[1]).append("\n"); 
     } 
     return out.append(']').toString(); 
    } 
} 

답변

0

당신이 그 값을 자세히 보면, 당신은 99.99999999999973 및 99.99999999999974 서로의 일 unit of least precision (ULP) 내에 있다는 것을 발견 할 것이다. 이것은 부동 소수점 숫자에 공통적 인 문제입니다. 모든 번호를 정확히 나타낼 수는 없습니다.

비슷한 방법으로 내용을 변경하고 직접 Path2D 개체를 인쇄하면 복제가 수행되지 않습니다.

javadoc of Area 상태

영역 원래 윤곽이 간단하고 분명한 경우에도 동일한 형상을 설명하기 위해 더 많은 경로 세그먼트를 취할 수있다. Area 클래스가 경로에서 수행해야하는 분석은 인간이 인식하는 것과 동일한 "단순하고 분명한"개념을 반영하지 않을 수 있습니다.

그래서 전체적으로 영역은 Path 객체를 최적화하여 볼 수있는 아티팩트를 도입합니다. 필자는 Area의 소스 코드를 파헤 치지 않고 경로의 특정 분해가 얼마나 정확하게 선택되었는지 알아 냈습니다.

+0

정확히이 경우 javadoc 영역의 총알이 작성된 것처럼 보입니다. 그래도 Area 객체가 하나의 ULP 내에있는 점을 삽입한다는 것은 이상한 것 같습니다. 어쨌든, 단점은 만약 당신이 연속적인'Area.subtract()'와 같은 객체를 사용하면 중복 된 것이 축적된다는 것입니다. C'est la vie. 방금 다각형으로 영역을 변환 할 때 dups를 필터링하는 코드를 작성했습니다. 팁 고마워. –

+0

부동 소수점 숫자를 사용할 때 종종 이러한 문제가 발생합니다. Area가 내부 계산을 수행하고 정확도 손실로 인해 포인트가 더 이상 일치하지 않으며 경로가 분할된다고 추측합니다. 더 나은 인쇄를 위해 서로의 특정 ULP 내에있는 점을 결합하는 경로를 다시 구성하고자 할 수 있습니다. – Polygnome