Java PathIterator-如何准确计算形状对象的中心?
我尝试使用PathIterator计算任何形状对象的中心,以便可以计算弯曲路径,但在找到标准1x1矩形的中心后,我的getCenter方法返回点:Java PathIterator-如何准确计算形状对象的中心?,java,shapes,centroid,path-iterator,Java,Shapes,Centroid,Path Iterator,我尝试使用PathIterator计算任何形状对象的中心,以便可以计算弯曲路径,但在找到标准1x1矩形的中心后,我的getCenter方法返回点: Point2D.Double[0.3333333333333333, 0.3333333333333333] 我的getCenter方法: shape = new Rectangle2D.Double(0, 0, 1, 1); public Point2D.Double getCenter() { Arr
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数组中有六个条目,而不是我预期的四个条目,因为输入图形对象是矩形2D.Double0,0,1,1。很明显,它比我想要的多解释了两次0点,我不明白为什么会这样。这是PathIterator.isDone方法的结果吗?我用错了吗?如果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]));
}
}
我不确定你是否用错了,但你没有说明问题的一个方面。PathIterator与其说代表一个几何图形,不如说代表一个在绘制时应该采用的路径。因此,它的点也代表了“笔”应该走的路径类型。例如,对于矩形,路径将生成以下线段: SEG_MOVETO 塞古·莱内托 塞古·莱内托 塞古·莱内托 塞古·莱内托 SEG_CLOSE 因为路径显然应该: 无论笔在哪里,都要移动,而不是画画。 将此路径与笔下一步绘制的内容隔开。 段的类型是currentSegment的返回值。如果只想捕获多边形上的点,可以检查“直线到”线段:
if(pi.currentSegment(arr) == PathIterator.SEG_LINETO) {
points.add(new Point2D.Double(arr[0], arr[1]));
}
这将适用于矩形等简单多边形。对于给定的矩形,它将返回[0.5,0.5],这是我假设您感兴趣的结果
另一方面,有些形状不是多边形,因此我会小心使用这种方法。正如前面所指出的,PathIterator返回不同类型的段。仅考虑SEG_LINETO中涉及的点时,应已获得令人满意的结果。然而,考虑到也可能有其他形状的SexGuthto和SeCube CuButo。使用展平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);
}
}
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);
}
}