计算围绕多边形

时间:2016-04-19 15:25:58

标签: android opengl-es border polygon vertex

我有一个由中心点C和外顶点数组定义的多边形(V 0 ,V 1 ,..,V n )以CCW顺序输入。对于每个顶点V i ,我知道顶点V (i-1)%n ,V i 和V (i + 1)%n ,我可以将矢量从C归一化到V i 。我也可以通过任何给定的向量转换顶点。我的多边形的外顶点可以作为我边框的内顶点,所以我只需要知道如何计算边框的外顶点。

这是我尝试的内容:



public static Vertex[] calculateOuterVerticesForBorder(Polygon polygon, float borderThickness) {

  int outerVertexCount = polygon.outerVertexCount;

  Vertex[] bOuterVertices = new Vertex[outerVertexCount];

  for (int i = 0; i < outerVertexCount; i++) {
    Vertex pOuterVertex = polygon.outerVertices[i];
    float pOuterVertexAngle = polygon.outerVertexAngles[i];
    Vector pVectorNorm = new Vector(polygon.center, pOuterVertex).toLength(borderThickness);
    //Here I should probably make some adjustment to pVectorNorm based on the 
    //outer vertex angle, or perhaps the angle from C to Vi to V(i+1)
    Vertex bOuterVertex = new Translation(vectorNorm).transform(pOuterVertex);
    bOuterVertices[i] = bOuterVertex;
  }

  return bOuterVertices;
}
&#13;
&#13;
&#13;

问题是,此计算会导致边框厚度不均匀,如下图所示:

Image of non-uniform border drawn around some of my polygons

1 个答案:

答案 0 :(得分:0)

您需要做的是计算在顶点处连接的两条线之间的中间角。然后沿着该角度向量扩展边界borderThickness距离,然后将该点添加到包含&#34; border&#34;的列表中。多边形。

我建议的代码看起来像这样:

//This math is weird, but it basically just returns a boolean value: 
//are these three points convex or concave, using counterclockwise ordering?
boolean isConvex(Vertex previousVertex, Vertex currentVertex, Vertex nextVertex) {
    return
        (
        previousVertex.x * (nextVertex.y - currentVertex.y) +
        currentVertex.x * (previousVertex.y - nextVertex.y) +
        nextVertex.x * (currentVertex.y - previousVertex.y)
        ) < 0;
}

Vertex getBorderVertex(Vertex previousVertex, Vertex currentVertex, Vertex nextVertex, float borderDistance) {
    //I'm using the word "vector" here to distinguish numbers which are directions, 
    //whereas "vertex" refers to a point. Mathematically, there's no difference.
    Vector line1 = Vector(currentVertex.x - previousVertex.x, currentVertex.y - previousVertex.y);
    //normalize == make the length equal to 1
    line1 = normalize(line1);
    Vector line2 = Vector(currentVertex.x - nextVertex.x, currentVertex.y - nextVertex.y);
    line2 = normalize(line2);

    //We really shouldn't have joints that are just straight lines 
    //(especially because floating point numbers are imprecise), 
    //but we want the formula to be generic enough to handle this edge case (pun intended)

    //The Dot Product is the same as the dot product algorithm you learned in primary school geometry.
    float dotProduct = line1.dot(line2);
    if(dotProduct == 1 || dotProduct == -1) {
        Vector normalVector = Vector(line1.y, -line1.x);
        normalVector = normalVector.multiply(borderDistance);
        return Vertex(currentVertex.x + normalVector.x, currentVertex.y + normalVector.y);
    }
    Vector halfwayLine = line1.plus(line2);

    //We want the algorithm to work correctly regardless of whether it's a concave joint 
    //or a convex joint. If it's concave, we need to reverse the direction.
    if(!isConvex(previousVertex, currentVertex, nextVertex)) 
        halfwayLine = halfwayLine.multiply(-1);

    halfwayLine = normalize(halfwayLine);
    halfwayLine = halfwayLine.multiply(borderDistance);
    return Vertex(currentVertex.x + halfwayLine.x, currentVertex.y, halfwayLine.y);
}

然后您的程序可以调用所有这些代码,如下所示:

for(int vertexIndex = 0; vertexIndex < outerVertexCount; vertexIndex++) {
    //The weird math here is only because modulos of negative values can 
    //return negative numbers in some programming languages. If you know for certain 
    //that the modulo function will only return positive numbers, then you can remove 
    //the addition of outerVertexCount to the previousVertex index.
    Vertex previousVertex = polygon.outerVertices[(vertexIndex + outerVertexCount - 1) % outerVertexCount];
    Vertex currentVertex = polygon.outerVertices[vertexIndex];
    Vertex nextVertex = polygon.outerVertices[(vertexIndex + 1) % outerVertexCount];

    bOuterVertices[vertexIndex] = getBorderVertex(previousVertex, currentVertex, nextVertex, borderThickness);
}