我有一个由中心点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;
问题是,此计算会导致边框厚度不均匀,如下图所示:
Image of non-uniform border drawn around some of my polygons
答案 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);
}