计算几个三角形的重心

时间:2015-10-27 19:10:58

标签: java computational-geometry

我无法解决如何解决这个问题。我创建了3个三角形:

enter image description here

我有所有单个三角形的XY坐标。我想计算重心,如果它们如图所示放在一起,但只使用填充的部分,并且无论它们在哪里交叉,你都不计算质量两次。我怎样才能在java中这样做呢?

我能以某种方式将这些组合成某种物体中的1种,然后对每个区域进行数值计算并找到中间地带,还是有更好的方法?

2 个答案:

答案 0 :(得分:0)

将形状转换为单个多边形(要计算两个交点)。

然后使用centroid formula作为多边形。

另一种选择是用相同的颜色填充所有三角形(通过多边形或种子填充),然后种子填充结果区域,同时在运行中累积X和Y坐标。

答案 1 :(得分:0)

首先,您必须确定实际想要计算重心的内容。显然,当三角形相交(并且重叠区域不应计算两次)时,您不是计算三角形的重心,而是计算它们交叉区域的重心。

幸运的是,可以使用Area类轻松计算这样的交叉区域。根据一条评论,您已经有Area描述这个区域。

因此,计算此区域的重心的一个选项是计算Area的所有边界点的平均值。

请注意,这只适用于Area没有漏洞的情况。

否则,您必须计算Area的面积。

这是一个可能的实现:

import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class CenterOfGravity
{
    public static void main(String[] args)
    {
        Path2D p0 = new Path2D.Double();
        p0.moveTo(100, 100);
        p0.lineTo(200, 100);
        p0.lineTo(150,  50);
        p0.closePath();

        Path2D p1 = new Path2D.Double();
        p1.moveTo(150, 100);
        p1.lineTo(250, 100);
        p1.lineTo(200,  50);
        p1.closePath();

        Area a = new Area();
        a.add(new Area(p0));
        a.intersect(new Area(p1));

        Point2D cog = computeCenterOfGravity(a);
        System.out.println(cog);
    }

    private static Point2D computeCenterOfGravity(Shape shape)
    {
        return computeAverage(computePoints(shape, 1.0));
    }

    private static Point2D computeAverage(
        Collection<? extends Point2D> points)
    {
        double x = 0;
        double y = 0;
        for (Point2D point : points)
        {
            x += point.getX();
            y += point.getY();
        }
        if (!points.isEmpty())
        {
            x /= points.size();
            y /= points.size();
        }
        return new Point2D.Double(x, y);
    }

    public static List<Point2D> computePoints(
        Shape shape, double flatness)
    {
        List<Point2D> result = new ArrayList<Point2D>();
        PathIterator pi = shape.getPathIterator(null, flatness);
        double[] coords = new double[6];
        while (!pi.isDone())
        {
            int segment = pi.currentSegment(coords);
            switch (segment)
            {
                case PathIterator.SEG_MOVETO:
                case PathIterator.SEG_LINETO:
                    result.add(new Point2D.Double(coords[0], coords[1]));
                    break;

                case PathIterator.SEG_CLOSE:
                    break;

                case PathIterator.SEG_QUADTO:
                case PathIterator.SEG_CUBICTO:
                default:
                    throw new AssertionError(
                        "Invalid segment in flattened path!");
            }
            pi.next();
        }
        return result;
    }

}