计算线段交点-----向量法

一、概述

题目来源于leetcode。

二、思路

先通过快速排斥试验判断以线段为对角线的矩形是否相交,不相交则无交点;
再判断线段是否跨立;
再判断是否共线,并计算交点;
线段相交,根据三角形面积和定比分点公式计算交点坐标。

三、代码

/**
 * @param {number[]} start1
 * @param {number[]} end1
 * @param {number[]} start2
 * @param {number[]} end2
 * @return {number[]}
 */
var intersection = function (start1, end1, start2, end2) {    
    let P1 = new Point(start1);
    let P2 = new Point(end1);
    let Q1 = new Point(start2);
    let Q2 = new Point(end2);
    let arr = [];
  //先通过快速排斥试验判断以线段为对角线的矩形是否相交,不相交则无交点;
if (Math.max(P1.x, P2.x) < Math.min(Q1.x, Q2.x) || Math.max(Q1.x, Q2.x) < Math.min(P1.x, P2.x) || Math.max(P1.y, P2.y) < Math.min(Q1.y, Q2.y) || Math.max(Q1.y, Q2.y) < Math.min(P1.y, P2.y)) { return []; } let Q1P1=getLine(Q1,P1); let Q1P2=getLine(Q1,P2); let Q1Q2=getLine(Q1,Q2); let P1P2=getLine(P1,P2); let P1Q1=getLine(P1,Q1); let P1Q2=getLine(P1,Q2); let P2Q2=getLine(P2,Q2);
//再判断线段是否跨立; let crossV
=vectorCross(Q1P1,Q1Q2)*vectorCross(Q1P2,Q1Q2); let crossV2=vectorCross(P1Q1,P1P2)*vectorCross(P1Q2,P1P2); if(crossV>0||crossV2>0){ return []; }
  //再判断是否共线,并计算交点;
if(vectorCross(Q1P1,P1Q2)===0||vectorCross(Q1P2,P2Q2)===0||vectorCross(Q1P2,P2Q2)===0){//共线 let isQ1inP1P2=isPointInLine(P1,P2,Q1); if(isQ1inP1P2){ arr=update(Q1.x,Q1.y,arr); } let isQ2inP1P2=isPointInLine(P1,P2,Q2); if(isQ2inP1P2){ arr=update(Q2.x,Q2.y,arr); } let isP1inQ1Q2=isPointInLine(Q1,Q2,P1); if(isP1inQ1Q2){ arr=update(P1.x,P1.y,arr); } let isP2inQ1Q2=isPointInLine(Q1,Q2,P2); if(isP2inQ1Q2){ arr=update(P2.x,P2.y,arr); } }else{
     //线段相交,根据三角形面积和定比分点公式计算交点坐标。 let s1
=Math.abs(vectorCross(Q1Q2,Q1P2))*0.5; let s2=Math.abs(vectorCross(Q1Q2,Q1P1))*0.5; let lamda=s1/s2; let x,y; x=(P2.x+lamda*P1.x)/(1+lamda); y=(P2.y+lamda*P1.y)/(1+lamda); arr=[x,y]; } return arr; }; var Point = function (p) { this.x = p[0]; this.y = p[1]; } var vectorCross=function(v1,v2){ return v1[0]*v2[1]-v2[0]*v1[1]; } //点p在线段point1——point2上,且是有交点的前提下 var isPointInLine=function(point1,point2,p){ let minX=min(point1.x,point2.x); let minY=min(point1.y,point2.y); let maxX=max(point1.x,point2.x); let maxY=max(point1.y,point2.y); if(p.x>=minX&&p.x<=maxX&&p.y>=minY&&p.y<=maxY&&vectorCross(getLine(point1,p),getLine(p,point2))===0){ return true; } return false; } var update=function(x,y,arr){//获取坐标最小的点 if(arr.length===0||x<arr[0]||(x===arr[0]&&y<arr[1])){ arr=[x,y]; } return arr; } var min=function(a,b){ return Math.min(a,b); } var max=function(a,b){ return Math.max(a,b); } var getLine=function(Q1,P1){ let Q1P1=[P1.x-Q1.x,P1.y-Q1.y]; return Q1P1; }

 

posted on 2022-01-10 16:34  苹果园dog  阅读(565)  评论(0编辑  收藏  举报

导航