java计算四边形中心点和两条线段交点算法

Posted 洛阳泰山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java计算四边形中心点和两条线段交点算法相关的知识,希望对你有一定的参考价值。

需求

  已知四边形的四个点位,求四边形的中心点,即求四边形两条对角线的交点即为中心点。

先来复习下三角形面积公式: 已知三角形三点a(x,y) b(x,y) c(x,y), 三角形面积为: 

double triArea=( (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x) ) /2 ;  

 因为 两向量叉乘==两向量构成的平行四边形(以两向量为邻边)的面积 , 所以上面的公式也不难理解. 
而且由于向量是有方向的, 所以面积也是有方向的, 通常我们以逆时针为正, 顺时针为负数. 

如果"线段ab和点c构成的三角形面积"与"线段ab和点d构成的三角形面积" 构成的三角形面积的正负符号相异, 
那么点c和点d位于线段ab两侧.

图中虚线所示的三角形, 缠绕方向(三边的定义顺序)不同, 所以面积的正负符号不同. 

下面还是先看代码: 
由于我们只要判断符号即可, 所以前面的三角形面积公式我们就不需要后面的 除以2 了. 

java计算两条线段的交点完整代码


import lombok.AllArgsConstructor;
import lombok.Data;

import java.math.BigDecimal;

public class Test 


    @Data
    @AllArgsConstructor
    static class Point
        private BigDecimal x;
        private BigDecimal y;
    

    public static void main(String[] args) 
        Point p1=getPoint(3630940.601591212,39438876);
        Point p2=getPoint(3630272.41274585,39441716);
        Point p3=getPoint(3630016.340373975,39441636);
        Point p4=getPoint(3630652.5201728526,39438848);
        Point point=segmentsInstr(p1,p3,p4,p2);
        if(point==null)
            System.out.print("未相交");
        else
            System.out.print("相交于:"+point.toString());
        
    

    public  static Point getPoint(double a,double b)
        BigDecimal aa=BigDecimal.valueOf(a);
        BigDecimal bb=BigDecimal.valueOf(b);
        return new Point(aa,bb);
    


    private static  Point segmentsInstr(Point a, Point b, Point c, Point d)
        // 三角形abc 面积的2倍
        BigDecimal acxPoor=a.getX().subtract(c.getX());
        BigDecimal bcyPoor=b.getY().subtract(c.getY());
        BigDecimal acyPoor=a.getY().subtract(c.getY());
        BigDecimal bcxPoor=a.getX().subtract(c.getX());
        BigDecimal adxPoor=a.getX().subtract(d.getX());
        BigDecimal bdyPoor=b.getY().subtract(d.getY());
        BigDecimal adyPoor=a.getY().subtract(d.getY());
        BigDecimal bdxPoor=b.getX().subtract(d.getX());
        BigDecimal acx_bcy=acxPoor.multiply(bcyPoor);
        BigDecimal acy_bcx=acyPoor.multiply(bcxPoor);
        BigDecimal adx_bdy=adxPoor.multiply(bdyPoor);
        BigDecimal ady_bdx=adyPoor.multiply(bdxPoor);
        BigDecimal area_abc=acx_bcy.subtract(acy_bcx);
        // 三角形abd 面积的2倍
        BigDecimal area_abd=adx_bdy.subtract(ady_bdx);
        // 面积符号相同则两点在线段同侧,不相交 (对点在线段上的情况,本例当作不相交处理);

        BigDecimal area_abc_abd=area_abc.multiply(area_abd);
       if ( area_abc_abd.compareTo(BigDecimal.valueOf(0))==1 ) 
           System.out.println(666);
          return null;
        
        BigDecimal caxPoor=c.getX().subtract(a.getX());
        BigDecimal dayPoor=d.getY().subtract(a.getY());
        BigDecimal cayPoor=c.getY().subtract(a.getY());
        BigDecimal daxPoor=d.getX().subtract(a.getX());
        BigDecimal cax_day=caxPoor.multiply(dayPoor);
        BigDecimal cay_dax=cayPoor.multiply(daxPoor);
        // 三角形cda 面积的2倍
        BigDecimal area_cda=cax_day.subtract(cay_dax);
        // 三角形cdb 面积的2倍
        // 注意: 这里有一个小优化.不需要再用公式计算面积,而是通过已知的三个面积加减得出.
        BigDecimal area_cda_abd=area_cda.add(area_abc);
        BigDecimal area_cdb=area_cda_abd.subtract(area_abd);
        BigDecimal area_cda_cdb=area_cda.multiply(area_cdb);
        if (area_cda_cdb.compareTo(BigDecimal.valueOf(0))==1 ) 
            return null;
        
        BigDecimal area_abd_abc=area_abd.subtract(area_abc);
        //计算交点坐标
        BigDecimal t = area_cda.divide(area_abd_abc,3,BigDecimal.ROUND_HALF_UP);
        BigDecimal bax=b.getX().subtract(a.getX());
        BigDecimal dx=t.multiply(bax);
        BigDecimal bay=b.getY().subtract(a.getY());
        BigDecimal dy=t.multiply(bay);
        BigDecimal x=a.getX().add(dx);
        BigDecimal y=a.getY().add(dy);
        return new Point(x,y);

    

控制台输出结果

 

以上是关于java计算四边形中心点和两条线段交点算法的主要内容,如果未能解决你的问题,请参考以下文章

java 计算线的方位角和两条直线的交点

求两条线段交点zz

3.2 多边形的交点 [点/多边形 内/外 测试]

光线投射算法(如何计算一个坐标点是不是在一个多边形内)

poj 2826 题解

Liang-Barsky算法