10

在此处输入图像描述

所以我有一条由 n 个点组成的任意线(参见图 1 中的示例)

我想围绕这条线画一个轮廓(见图 2),所以我需要计算周围多边形的点。

我首先在线上执行扩张,但这不起作用 - 见图 3

关于如何做到这一点的任何建议?

我怀疑计算每条线段的法线以用于翻译下面的新线和高于其当前位置的新线,然后将每条新线延伸到无穷大并将点定义为交点?

4

5 回答 5

7

首先将每条线复制两次,每边复制一次,距离每条原始线所需宽度的一半。这会给你图像中的绿线。然后您需要按顺序(编号)访问它们并处理松散的末端。

线轮廓

当线不相遇(2-3、6-7 和 12-13)时,您添加线连接(蓝色)。线连接可以是仅通过连接点的斜角连接(2-3),也可以是通过延长线直到它们相遇 (6-7) 的斜接连接或通过制作曲线的圆形连接

当线条相遇时,只需取交点(蓝点)。

在线路末端,您需要添加一个端盖(也是蓝色的)。通过连接点,端盖可以是对接盖(8-9),通过在连接它们之前稍微延长线的突出盖(1-16),或圆形盖(未显示)。

最终结果是一个多边形(或路径,如果它包括圆形连接),然后您可以对其进行描边或填充。

于 2011-04-13T00:05:48.973 回答
5

我想出了一种计算线条轮廓点的方法。对于原始线的每个点,您必须为轮廓计算 2 个点:

  1. 对于原始线的每个线段(2点之间),您必须计算其法线向量(红色)
  2. 对于每个点,添加上一条和下一条线段的法线。这会产生一个新的向量(绿色)
  3. 将新向量除以以下值: k l+1 ,其中 k l 是法线向量的点积。你会得到蓝色的矢量。然后将此向量添加到当前点及其相反向量上,您将获得当前点的 2 个轮廓点

上面的颜色对应这张图片在此处输入图像描述

我已经用 C 编写了这个函数,但是我使用了 Accelerate Framework,所以它不是很容易阅读。您可以在此处找到源代码,并此处找到运行演示的视频。

于 2011-09-12T21:13:34.457 回答
0

在渲染它们之前创建所有线条。

当你这样做时,它们应该重叠,如下所示:在此处输入图像描述

很明显,我画的那些是被修剪过的,会露出轮廓的。

于 2011-04-12T21:30:14.690 回答
0

这是我在 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/

于 2013-04-09T18:13:09.073 回答
0

如果您有线段的点,则可以轻松地为每个线段创建两条平行线,并计算它们与下一条线(而不是线段)相交的连接点。该站点应该为您提供计算超快速交叉口所需的一切:

http://www.math.niu.edu/~rusin/known-math/95/line_segs

于 2011-04-12T22:50:25.063 回答