计算封闭多边形中的内部等分线

时间:2019-06-06 12:12:58

标签: geometry angle

我有一个逆时针定向的多边形。我试图找出每个相邻边的平分线。我想出了一个解决方案,但我想知道这是否是最有效的方法...

我需要检查内角。是比pi大还是小。我需要这样做,因为我需要翻转传入的矢量或传出的矢量。

问题基本上是:有没有一种更有效的方法来确定内角是否大于pi(或180度)?

我现在用javascript编写的过程是这样的:

export const getBisectors = (polygon) => {
    //get bisectors, including length based on the unit normal vectors of the edges (inward)
    let bisectors = [];
    let prevPoint = polygon[polygon.length - 1];

    polygon.forEach((p, i) => {
        let nextPoint = i === polygon.length - 1 ? polygon[0] : polygon[i + 1];

        //vector going to p
        let v1 = normalizeVector({ x: p.x - prevPoint.x, y : p.y - prevPoint.y });
        let radIn = Math.acos(v1.x);
        if (v1.y < 0) radIn = TwoPI - radIn;

        // vector to next point
        let v2 = normalizeVector({ x: nextPoint.x - p.x, y : nextPoint.y - p.y });
        let radOut = Math.acos(v2.x);
        if (v2.y < 0) radOut = TwoPI - radOut;

        let rotation = radIn - radOut;
        if (rotation < 0) rotation += TwoPI; 

        if (rotation > Math.PI) {
            //invert outgoing
            v2 = multiply(v2, -1);
        } else {
            //invert incoming
            v1 = multiply(v1, -1);
        }
        let bisector = addVectors(v1, v2);

        bisectors.push({bisector: bisector, p : p  });
        prevPoint = p;
    });
    return bisectors;
}

部分回答后,我使用以下方法结束了

export const getIntersection = (p1, v1, p2, v2) => {
    //find s
    //p1 + s * v1 == p2 + t * v2
    var denominator = cross(v1, v2);

    if (Math.abs(denominator) < epsilon) {
        return p1;
    }

    var s = (p2.x * v2.y + p1.y * v2.x - p2.y * v2.x - p1.x * v2.y) / denominator;
    return {x : p1.x + s * v1.x, y : p1.y + s * v1.y};
}

function getBisector(prevPoint, point, nextPoint) {
    let v1 = { x: point.x - prevPoint.x, y : point.y - prevPoint.y };
    let n1 = normalizeVector( { x: v1.y, y : -( v1.x ) } )
    let n2 = normalizeVector( { x: (nextPoint.y - point.y), y : -(nextPoint.x - point.x) } )

    let bisector = addVectors(n1, n2);    
    let i = getIntersection(point, bisector, addVectors(prevPoint, n1), v1);

    return {x : i.x - point.x, y : i.y - point.y};
}

和一些示例: bisectors 5-shape

enter image description here

2 个答案:

答案 0 :(得分:1)

enter image description here

为每对相邻边创建方向矢量并构建单位法线。我使用了左法线-适用于CCW多边形,图片显示angle > Pi,较小角度的计算结果相同。

a = P[i] - P[i-1]
b = P[i+1] - P[i]

na = (-a.y, a.x)  //left normal
na = na / Length(na)

nb = (-b.y, b.x)   
nb = nb / Length(nb)

bisector = na + nb  

如果需要使顶点偏移d

bis = bisector / Length(bisector)

将等分线的长度设为所需的距离

l = d / Sqrt(1 + dotproduct(na,nb))

找到偏移的多边形顶点:

P' = P + l * bis

答案 1 :(得分:1)

Content-Type application/x-www-form-urlencoded
POST https://login.microsoftonline.com/domain/oauth2/v2.0/token
BODY client_id=clientidguid&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=clientsecret&grant_type=client_credentials

Etit::这里是生成内部平分线的更快代码,而无需使用任何法线:我测试过的Matlab代码。它生成指向多边形内部的等分线。

let v1 = normalizeVector({ x: p.x - prevPoint.x, y : p.y - prevPoint.y });
let v2 = normalizeVector({ x: nextPoint.x - p.x, y : nextPoint.y - p.y });

k = v1.x * v2.y - v1.y * v2.x;

if (k < 0){
   //the angle is greater than pi, invert outgoing, 
   //ready to get interior bisector 
   v2 = multiply(v2, -1);  
}
else{
   //the angle is less than pi, invert incoming, 
   v1 = multiply(v1, -1);
}

bisector = normalizeVector({ x: v1.x + v2.x, y : v1.y + v2.y });

用您的符号表示:

function  B = bisectors(P)

   %P is 2 x n matrix, column P(:,j) is a vertex of a polygon in the plane,
   %P is the ordered set of vertices of the polygon

   [~,n] = size(P); 
   B = zeros(2,n);

   for j=1:n

       if j == 1
          v_in = P(:,1) - P(:,n);
          v_out = P(:,2) - P(:,1);
       elseif j == n
          v_in = P(:,j) - P(:,j-1);
          v_out = P(:,1) - P(:,j);
       else
          v_in = P(:,j) - P(:,j-1);
          v_out = P(:,j+1) - P(:,j);
       end

       v_in = v_in/sqrt(v_in'*v_in); %normalize edge-vector
       v_out = v_out/sqrt(v_out'*v_out); %normalize edge-vector

       % bisector of the complementary angle at the vertex j, 
       % pointing counter clockwise and displacing the vertex so that
       % the resulting polygon is 1 unit inwards in normal direction:
       bisector = v_in + v_out; 
       bisector = bisector/abs(bisector'*v_in);

       % 90 degree counter clockwise rotation of complementary bisector:
       B(1,j) = - bisector(2);
       B(2,j) = bisector(1);

   end

end

此函数返回与上一个函数相同长度的平分线,而无需额外的getIntersection函数。