如何在任何线条周围绘制轮廓

| 所以我有一条由n个点组成的任意曲线(请参见图1中的示例) 我想在这条线周围画一个轮廓(见图2),所以我需要计算周围多边形的点。 我从在线路上执行膨胀开始,但是这行不通-见图3 有关如何执行此操作的任何建议? 我怀疑要计算每个线段的法线,以用于平移下面的新线以及在其当前位置上方平移新线,然后将每条新线扩展到无穷大并将点定义为交点?     
已邀请:
首先将每条线复制两次,在每侧一次,距离每条原始线的宽度的一半。这样就可以在图像中显示绿线。然后,您需要按顺序(编号)访问它们并处理松散的一端。 当线不相交(2-3、6-7和12-13)时,添加线连接(蓝色)。直线连接可以是仅连接点的斜角连接(2-3),也可以是延长线直到它们相遇(6-7)的斜角连接,也可以是曲线连接的圆角连接。 直线相交时,仅取相交点(蓝点)即可。 在线的末端,您需要添加一个端盖(也为蓝色)。端盖可以是通过连接点而制成的对接盖(8-9),也可以是在连接线之前稍稍延伸一点的突出盖(1-16),也可以是圆盖(未显示)。 最终结果是一个多边形(如果包含圆角连接,则为路径),然后可以对其进行描边或填充。     
我想出了一种方法来计算一条线的轮廓点。对于原始线的每个点,您必须为轮廓计算2个点: 对于原始线的每个线段(2个点之间),您必须计算其法线向量(红色) 对于每个点,添加上一条和下一条线段的法线。这将产生一个新的向量(绿色) 将新矢量除以值kl + 1,其中kl是法向矢量的点积。您将获得蓝色矢量。然后将此向量添加到当前点及其相反的向量上,您将获得当前点的2个轮廓点 上面的颜色对应于此图像。   我已经用C编写了此函数,但是我使用了Accelerate Framework,因此它不太容易阅读。您可以在此处找到源代码,并在此处找到运行演示的视频。     
在渲染它们之前创建所有线条。 当您这样做时,它们应该重叠,如下所示: 很明显,我画的那些是经过修剪的,可以揭示轮廓。     
如果具有线段的点,则可以轻松地为每个线段创建两条平行线,并计算它们与下一条线(而不是线段)相交的连接点。该站点应为您提供计算超快速交叉口所需的一切: http://www.math.niu.edu/~rusin/known-math/95/line_segs     
这是我在Objective-C中正在执行的一些代码(即使有时会出现故障,我也不知道为什么,让我知道它对您的影响...): 它会占用折线的每个边,然后在当前边的垂直线的右侧创建第一个数组(以与折线,CCW或CW相同的方式),然后在左侧创建第二个数组。 对于每个边缘,它会测试2条无限直线(因为您的边缘是线段)相交的点。 最后,它以所需的顺序添加每个点以制作一个多边形
- (hOzPolygon2D *) convertToPolygonWithWidth:(double) polyWidth
{

double shift = polyWidth / 2.;

NSMutableArray *tempEdgesRight = [[[NSMutableArray alloc] init] autorelease];
NSMutableArray *tempEdgesLeft = [[[NSMutableArray alloc] init] autorelease];

NSMutableArray *tempPolyPoints = [[[NSMutableArray alloc] init] autorelease];

// Move your points on the right by half the desired width

// My edges are already computed in a NSArray* called edges, 
// but you can use pairs of vectors and adapt all this

for (hOzEdge2D *edge in edges) {

hOzVector2 v = hOzVector2([[edge pointB] x] - [[edge pointA] x], [[edge pointB] y] - [[edge pointA] y]);
double mag = sqrt (v.x * v.x + v.y * v.y);
v.x = v.x / mag;
v.y = v.y / mag;

double temp = v.x;
v.x = v.y;
v.y = -temp;

hOzPoint2D *newPointA = [[hOzPoint2D alloc] init];
[newPointA setX:([[edge pointA] x] + v.x * shift)];
[newPointA setY:([[edge pointA] y] + v.y * shift)];

hOzPoint2D *newPointB = [[hOzPoint2D alloc] init];
[newPointB setX:([[edge pointB] x] + v.x * shift)];
[newPointB setY:([[edge pointB] y] + v.y * shift)];

[tempEdgesRight addObject:[hOzEdge2D edge2DWithPointA:newPointA pointB:newPointB]];

}

// With the same polyline, move on the left

for (int j = [edges count] - 1; j >= 0; j--) {

hOzVector2 v = hOzVector2([[[edges objectAtIndex:j] pointB] x] - [[[edges objectAtIndex:j] pointA] x], [[[edges objectAtIndex:j] pointB] y] - [[[edges objectAtIndex:j] pointA] y]);
double mag = sqrt (v.x * v.x + v.y * v.y);
v.x = v.x / mag;
v.y = v.y / mag;

double temp = v.x;
v.x = v.y;
v.y = -temp;

hOzPoint2D *newPointA = [[hOzPoint2D alloc] init];
[newPointA setX:([[[edges objectAtIndex:j] pointB] x] - v.x * shift)];
[newPointA setY:([[[edges objectAtIndex:j] pointB] y] - v.y * shift)];

hOzPoint2D *newPointB = [[hOzPoint2D alloc] init];
[newPointB setX:([[[edges objectAtIndex:j] pointA] x] - v.x * shift)];
[newPointB setY:([[[edges objectAtIndex:j] pointA] y] - v.y * shift)];

[tempEdgesLeft addObject:[hOzEdge2D edge2DWithPointA:newPointA pointB:newPointB]];

}



// Add the static points and the intersection points to a points array that will define your polygon

[tempPolyPoints addObject:[[tempEdgesRight objectAtIndex:0] pointA]];  // The first point of the right array

for (int k = 0; k < [tempEdgesRight count] - 1; k++) {

// For this function, see the link below in the answer

hOzPoint2D *inter = [[tempEdgesRight objectAtIndex:k] getIntersectionWithStraight:[tempEdgesRight objectAtIndex:k+1]];   

if (inter == nil) {    // if the edges are parallel, we insert a known point
    [tempPolyPoints addObject:[[tempEdgesRight objectAtIndex:k] pointB]];
} else {
    [tempPolyPoints addObject:inter];
}
}

[tempPolyPoints addObject:[[tempEdgesRight lastObject] pointB]];    // The last point of the right array

[tempPolyPoints addObject:[[tempEdgesLeft objectAtIndex:0] pointA]];

// Then the left array, same thing

for (int k = 0; k < [tempEdgesLeft count] - 1; k++) {
hOzPoint2D *inter = [[tempEdgesLeft objectAtIndex:k] getIntersectionWithStraight:[tempEdgesLeft objectAtIndex:k+1]];

if (inter == nil) {
    [tempPolyPoints addObject:[[tempEdgesLeft objectAtIndex:k] pointB]];
} else {
    [tempPolyPoints addObject:inter];
}
}

[tempPolyPoints addObject:[[tempEdgesLeft lastObject] pointB]];

// Create your polygon with this new ordered points array.
hOzPolygon2D *poly = [hOzPolygon2D polygon2DWithArrayOfPoints:tempPolyPoints];

return poly;

}
以下是有关使用C代码的交点的说明:http://alienryderflex.com/intersect/     

要回复问题请先登录注册