我正在尝试使用PathIterator来计算任何Shape对象的中心,以便可以考虑弯曲路径,但是在找到标准1x1矩形的中心后,我的getCenter()方法返回点:
Point2D.Double[0.3333333333333333, 0.3333333333333333]
我的getCenter()方法:
shape = new Rectangle2D.Double(0, 0, 1, 1);
public Point2D.Double getCenter()
{
ArrayList<Point2D.Double> points = new ArrayList<Point2D.Double>();
double[] arr = new double[6];
for(PathIterator pi = shape.getPathIterator(null); !pi.isDone(); pi.next())
{
pi.currentSegment(arr);
points.add(new Point2D.Double(arr[0], arr[1]));
}
double cX = 0;
double cY = 0;
for(Point2D.Double p : points)
{
cX += p.x;
cY += p.y;
}
System.out.println(points.toString());
return new Point2D.Double(cX / points.size(), cY / points.size());
}
我发现在打印points.toString()时,我在控制台中得到了这个:
[Point2D.Double[0.0, 0.0], Point2D.Double[1.0, 0.0], Point2D.Double[1.0, 1.0], Point2D.Double[0.0, 1.0], Point2D.Double[0.0, 0.0], Point2D.Double[0.0, 0.0]]
我注意到点数组中有六个条目,而不是我期望的四个条目,因为输入的Shape对象是Rectangle2D.Double(0,0,1,1)。显然,它比我想要的多两倍(0,0),我很困惑为什么会这样。它是PathIterator.isDone()方法的结果吗?我使用不正确吗?如果PathIterator不能解决我的问题会怎样?
答案 0 :(得分:0)
PathIterator定义了不同类型的细分,你应该注意这个事实。您的示例中有6个段,因为它还会返回SEG_MOVETO段(定义子路径的起点)和SEG_CLOSE(子路径末尾)。如果你只想获得形状线的端点,你应该改变你的代码:
for(PathIterator pi = shape.getPathIterator(null); !pi.isDone(); pi.next())
{
if(pi.currentSegment(arr) == PathIterator.SEG_LINETO) {
points.add(new Point2D.Double(arr[0], arr[1]));
}
}
答案 1 :(得分:0)
我不确定你是否正在使用 ,但你没有考虑PathIterator的一个方面。 PathIterator并不代表几何形状,而是绘制时应该采用的路径。所以它的要点也代表了“笔”应该采用的路径类型。例如,对于Rectangle,路径将生成以下段:
SEG_MOVETO
SEG_LINETO
SEG_LINETO
SEG_LINETO
SEG_LINETO
SEG_CLOSE
因为显然道路应该:
段的类型是currentSegment
的返回值。如果您只想捕获多边形上的点,则可以检查“行到”段:
if(pi.currentSegment(arr) == PathIterator.SEG_LINETO) {
points.add(new Point2D.Double(arr[0], arr[1]));
}
这适用于像Rectangle这样的简单多边形。对于给定的Rectangle,它将返回[0.5,0.5],这是我假设您感兴趣的结果。
另一方面,有些形状不是多边形,所以我会小心这种方法。
答案 2 :(得分:0)
正如已经指出的那样,PathIterator返回不同类型的段。只考虑SEG_LINETO中涉及的要点时,您应该已经获得了满意的结果。但是,请考虑其他形状中也可能存在SEG_QUADTO和SEG_CUBICTO。使用展平 PathIterator可以轻松避免这些问题:使用
创建PathIterator时PathIterator pi = shape.getPathIterator(null, flatness);
具有适当的平整度,那么它只包含直线段。
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
public class ShapeCenter
{
public static void main(String[] args)
{
System.out.println(computeCenter(new Ellipse2D.Double(-10,-10,20,20)));
System.out.println(computeCenter(new Rectangle2D.Double(0,0,1,1)));
}
public static Point2D computeCenter(Shape shape)
{
final double flatness = 0.1;
PathIterator pi = shape.getPathIterator(null, flatness);
double coords[] = new double[6];
double sumX = 0;
double sumY = 0;
int numPoints = 0;
while (!pi.isDone())
{
int s = pi.currentSegment(coords);
switch (s)
{
case PathIterator.SEG_MOVETO:
// Ignore
break;
case PathIterator.SEG_LINETO:
sumX += coords[0];
sumY += coords[1];
numPoints++;
break;
case PathIterator.SEG_CLOSE:
// Ignore
break;
case PathIterator.SEG_QUADTO:
throw new AssertionError(
"SEG_QUADTO in flattening path iterator");
case PathIterator.SEG_CUBICTO:
throw new AssertionError(
"SEG_CUBICTO in flattening path iterator");
}
pi.next();
}
double x = sumX / numPoints;
double y = sumY / numPoints;
return new Point2D.Double(x,y);
}
}