Java:计算两个多边形相交部分的面积

计算多边形的面积

设多边形各顶点的坐标为:(x1, y1), (x2, y2), (x3, y3)……(xn, yn),则该多边形的面积为:
S = 1 2 ∑ n = 1 ∞ ( x n y n + 1 − x n + 1 y n ) S = 1 2 [ ( x 1 y 2 − x 2 y 1 ) + ( x 2 y 3 − x 3 y 2 ) + … … + ( x n y 1 − x 1 y n ) ] S=\frac 12 \sum_{n=1}^{\infty} {(x_{n}y_{n+1}-x_{n+1}y_{n})} \\ S=\frac 12 [(x_1y_2-x_2y_1)+(x_2y_3-x_3y_2)+……+(x_ny_1-x_1y_n)] S=21n=1(xnyn+1xn+1yn)S=21[(x1y2x2y1)+(x2y3x3y2)++(xny1x1yn)]
在这里插入图片描述
多边形各顶点与原点相连,构成多个三角形,将所有三角形的面积相加或相减,得到的结果就是多边形的面积。

  • 三角形的面积由两个向量的向量积的模计算得到: 1 2 ∣ ( x n y n + 1 − x n + 1 y n ) ∣ \frac 12 |(x_{n}y_{n+1}-x_{n+1}y_{n})| 21(xnyn+1xn+1yn)
  • 面积相加或相减由向量积的方向确定: 1 2 ( x n y n + 1 − x n + 1 y n ) \frac 12 (x_{n}y_{n+1}-x_{n+1}y_{n}) 21(xnyn+1xn+1yn)
package Polygon;

import java.awt.*;

/**
 * 计算多边形的面积
 */
public class PolygonArea {

    public static void main(String[] args) {

        Polygon polygon = new Polygon(new int[]{3,5,12,9,5}, new int[]{4,11,8,5,6}, 5);
        // 计算多边形的面积
        PolygonArea polygonArea = new PolygonArea();
        System.out.println("多边形的面积:" + polygonArea.getArea(polygon));
    }

    /**
     * 计算多边形的面积
     */
    public double getArea(Polygon polygon) {
        double Area = 0;  // 多边形的面积
        Integer Num = polygon.npoints;  // 顶点个数
        // 添加第一个顶点到末尾
        polygon.addPoint(polygon.xpoints[0], polygon.ypoints[0]);
        // 计算多边形的面积
        for (int i = 0; i < Num; i++) {
            Area += 0.5 * ((polygon.xpoints[i] * polygon.ypoints[i+1]) - (polygon.ypoints[i] * polygon.xpoints[i+1]));
        }
        return Math.abs(Area);
    }
}

在这里插入图片描述


计算两个多边形相交部分的面积

给出多边形PolygonA和多边形PolygonB,求两个多边形相交部分的面积。具体步骤如下:

  • 添加A位于B中的所有顶点:循环A的所有顶点,判断是否位于B中。
  • 添加B位于A中的所有顶点:循环B的所有顶点,判断是否位于A中。
  • 添加A与B每一条边的交点:判断边与边是否相交,相交则求交点。
  • 对多边形的顶点按逆时针方向进行排序。
  • 计算多边形InterPolygon的面积。
package Polygon;

import java.awt.*;
import java.awt.geom.Line2D;

import static java.lang.Math.max;
import static java.lang.Math.min;

/**
 * 计算两个多边形相交部分的面积
 */
public class InterPolygonArea {

    public static void main(String[] args) {

        Polygon polygonA = new Polygon(new int[]{0,2,2,0}, new int[]{0,0,2,2}, 4);
        Polygon polygonB = new Polygon(new int[]{1,3,3,1}, new int[]{0,0,1,1}, 4);
        // 计算两个多边形相交部分的面积
        InterPolygonArea interPolygonArea = new InterPolygonArea();
        System.out.println("两个多边形相交部分的面积:" + interPolygonArea.getInterArea(polygonA, polygonB));
    }

    /**
     * 计算两个多边形相交部分的面积
     */
    public double getInterArea(Polygon polygon1, Polygon polygon2) {
        Polygon InterPolygon = new Polygon();  // 两个多边形相交部分
        Integer Num1 = polygon1.npoints;  // 多边形A的顶点个数
        Integer Num2 = polygon2.npoints;  // 多边形B的顶点个数

        // 添加A位于B中的所有顶点:循环A的所有顶点,判断是否位于B中
        System.out.println("添加A位于B中的所有顶点:");
        for (int i = 0; i < Num1; i++) {
            if(polygon2.contains(polygon1.xpoints[i], polygon1.ypoints[i])) {
                InterPolygon.addPoint(polygon1.xpoints[i], polygon1.ypoints[i]);
                System.out.println("(" + polygon1.xpoints[i] + ", " + polygon1.ypoints[i] + ")");
            }
        }

        // 添加B位于A中的所有顶点:循环B的所有顶点,判断是否位于A中
        System.out.println("添加B位于A中的所有顶点:");
        for (int i = 0; i < Num2; i++) {
            if(polygon1.contains(polygon2.xpoints[i], polygon2.ypoints[i])) {
                InterPolygon.addPoint(polygon2.xpoints[i], polygon2.ypoints[i]);
                System.out.println("(" + polygon2.xpoints[i] + ", " + polygon2.ypoints[i] + ")");
            }
        }

        // 添加第一个顶点到末尾
        polygon1.addPoint(polygon1.xpoints[0], polygon1.ypoints[0]);
        polygon2.addPoint(polygon2.xpoints[0], polygon2.ypoints[0]);
        // 添加A与B每一条边的交点:判断边与边是否相交,相交则求交点
        System.out.println("添加A与B每一条边的交点:");
        boolean flag = false;  // false为不相交,true为相交
        for (int i = 0; i < Num1; i++) {
            for (int j = 0; j < Num2; j++) {
                // 判断多边形A的边(x1,y1)→(x2,y2)和多边形B的边(x3,y3)→(x4,y4)是否相交
                double x1 = polygon1.xpoints[i], y1 = polygon1.ypoints[i];
                double x2 = polygon1.xpoints[i+1], y2 = polygon1.ypoints[i+1];
                double x3 = polygon2.xpoints[j], y3 = polygon2.ypoints[j];
                double x4 = polygon2.xpoints[j+1], y4 = polygon2.ypoints[j+1];
                // flag = Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4);
                flag = isInterLines(x1, y1, x2, y2, x3, y3, x4, y4);
                // 相交则求交点,并添加
                if (flag) {
                    Point interSection = getInterSection(x1, y1, x2, y2, x3, y3, x4, y4);
                    InterPolygon.addPoint(interSection.x, interSection.y);
                    System.out.println("(" + interSection.x + ", " + interSection.y + ")");
                }
            }
        }

        System.out.println("两个多边形相交部分的顶点(排序前):");
        for (int i = 0; i < InterPolygon.npoints; i++) {
            System.out.println("(" + InterPolygon.xpoints[i] + ", " + InterPolygon.ypoints[i] + ")");
        }

        // 对多边形的顶点按逆时针方向进行排序
        PolygonSort polygonSort = new PolygonSort();
        Polygon interPolygon = polygonSort.PolygonClockwiseSort(InterPolygon);
        System.out.println("对多边形的顶点按逆时针方向进行排序:");
        for (int i = 0; i < interPolygon.npoints; i++) {
            System.out.println("(" + interPolygon.xpoints[i] + ", " + interPolygon.ypoints[i] + ")");
        }
        
        // 计算两个多边形相交部分的面积
        PolygonArea polygonArea = new PolygonArea();
        return polygonArea.getArea(interPolygon);
    }

    /**
     * 判断两个线段是否相交
     */
    public boolean isInterLines(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
        // 快速排斥实验:判断两条线段在x以及y坐标的投影是否有重合
        if (max(x3, x4) < min(x1, x2) || max(x1, x2) < min(x3, x4)
                || max(y3, y4) < min(y1, y2) || max(y1, y2) < min(y3, y4)){
            return false;
        }
        else {
            // 跨立实验(不考虑线段端点作为交点):点A和点B分别在线段CD两侧,点C和点D分别在线段AB两侧
            // 满足条件:(A-B)×(B−D)∗(A−B)×(C−B)<0 && (A−D)×(C−D)∗(B−D)×(C−D)<0
            if (((x2-x1)*(y4-y2) - (x4-x2)*(y2-y1)) * ((x2-x1)*(y3-y2) - (x3-x2)*(y2-y1)) < 0
                    && ((x4-x1)*(y4-y3) - (x4-x3)*(y4-y1)) * ((x4-x2)*(y4-y3) - (x4-x3)*(y4-y2)) < 0) {
                return true;
            }
            return false;
        }
    }

    /**
     * 计算两个相交线段的交点
     */
    public Point getInterSection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
        double b1 = (y2 - y1) * x1 + (x1 - x2) * y1;
        double b2 = (y4 - y3) * x3 + (x3 - x4) * y3;
        double D = (x2 - x1) * (y4 - y3) - (x4 - x3) * (y2 - y1);
        double D1 = b2 * (x2 - x1) - b1 * (x4 - x3);
        double D2 = b2 * (y2 - y1) - b1 * (y4 - y3);
        Point point = new Point();
        point.setLocation(D1 / D, D2 / D);
        return point;
    }
}

在这里插入图片描述


参考:

  • https://blog.csdn.net/sfw673306004/article/details/103801376
  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值