如何围绕任何线条绘制轮廓

发布于 2024-10-31 17:52:14 字数 275 浏览 4 评论 0原文

在此处输入图像描述

n 个点组成的任意线(参见图 1 中所示的示例)

所以我有一条由我想要的 围绕这条线绘制轮廓(见图 2),因此我需要计算周围多边形的点。

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

关于如何执行此操作有什么建议吗?

我怀疑计算每条线段的法线,用于平移其当前位置下方的新线和上方的新线,然后将每条新线延伸至无穷大并将点定义为交点?

enter image description here

So I have a arbitary line (See an example shown in fig 1) made up of n points

I want to draw an outline around this line (see fig 2) so I need to calculate the points of the surrounding polygon.

I started by performing a dilation on the line but this wont work - see figure 3

Any suggestions on how to do this?

I suspect calculating the normal of each line segment for use in translating the new line below and a new line above its current position and then extending each new line to infinity and defining the points as the intersections?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

独留℉清风醉 2024-11-07 17:52:14

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

line Outlined

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

当两条线相交时,只需取交点(蓝点)即可。

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

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

First duplicate each line twice, once on each side at a distance of half the width you want from each original line. That gives you the green lines in the image. Then you need to visit them in order (numbered) and deal with the loose ends.

line outlining

When the lines don't meet (2-3, 6-7 and 12-13) you add a line join (in blue). A line join can be a bevel join (2-3) by just connecting the points, or a miter join by extending the lines until they meet (6-7) or a round join by making a curve.

When the lines do meet, just take the intersection point (blue dots).

At the line ends, you need to add an end cap (also in blue). An end cap can be a butt cap (8-9) by connecting the points, a projecting cap (1-16) by extending the lines a little before connecting them, or a round cap (not shown).

The end result is a polygon (or path if it includes round joins) that you can then stroke or fill.

淡水深流 2024-11-07 17:52:14

我找到了一种计算直线轮廓点的方法。对于原始直线的每个点,您必须计算轮廓的 2 个点:

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

上面的颜色对应于图像
输入图片这里的描述

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

I have figured out a way to calculate the outline points of a line. For each point of the original line you will have to compute 2 points for the outline:

  1. for each line segment of the original line (between 2 points) you have to compute its normal vector (red)
  2. for each point, add the normals of the previous and next line segment. This produces a new vector (green)
  3. divide the new vector with the value: kl+1 , where kl is the dot product of the normal vectors. You'll get the blue vector. Then add this vector on the current point and its opposite vector and you'll get the 2 outline points for the current point

The colors above correspond to this image.
enter image description here

I have programmed this function in C, but I used Accelerate Framework so it's not very easy to read. You can find the source code here and a video running the demo here.

苯莒 2024-11-07 17:52:14

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

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

显然,我画的那些是那些进行修剪,露出轮廓。

Create all the lines before you render them.

When you do, they should overlap, like this: enter image description here

The ones I drew, obviously, are the ones that get trimmed which would reveal the outline.

深居我梦 2024-11-07 17:52:14

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

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

If you have the points of the line segments, you can easily create two parallel lines to each segment and calculate the connection point where they intersect with the next if they were lines (and not line segments). This site should give you all you need to calculate super fast intersections:

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

笑,眼淚并存 2024-11-07 17:52:14

这是我在 Objective-C 中编写的一些代码,它正在执行此操作(即使有时有错误,我不知道为什么,让我知道它对您来说如何......):

  • 它获取折线的每个边缘,然后创建第一个数组位于当前边缘的垂直方向上,位于右侧(与折线、CCW 或 CW 的方式相同),然后是左侧的第二个数组。
  • 对于每条边,它都会测试两条无限直线(因为您的边是线段)应该相交的点。
  • 最后,它按照所需的顺序添加每个点以形成多边形

    -(hOzPolygon2D *)convertToPolygonWithWidth:(double)polyWidth
    {
    
    双移=polyWidth/2。;
    
    NSMutableArray *tempEdgesRight = [[[NSMutableArray alloc] init] autorelease];
    NSMutableArray *tempEdgesLeft = [[[NSMutableArray alloc] init] autorelease];
    
    NSMutableArray *tempPolyPoints = [[[NSMutableArray alloc] init] autorelease];
    
    // 将右侧的点移动所需宽度的一半
    
    // 我的边已经在 NSArray* 中计算出来,称为edges, 
    // 但你可以使用向量对并调整所有这些
    
    for (hOzEdge2D *边中的边) {
    
    hOzVector2 v = hOzVector2([[边缘点B] x] - [[边缘点A] x], [[边缘点B] y] - [[边缘点A] y]);
    双倍磁力 = sqrt (vx * vx + vy * vy);
    vx = vx / mag;
    vy = vy / mag;
    
    双温度 = vx;
    vx = vy;
    vy = -温度;
    
    hOzPoint2D *newPointA = [[hOzPoint2D alloc] init];
    [newPointA setX:([[边缘点A] x] + vx * shift)];
    [newPointA setY:([[边缘点A] y] + vy * shift)];
    
    hOzPoint2D *newPointB = [[hOzPoint2D alloc] init];
    [newPointB setX:([[边缘点B] x] + vx * shift)];
    [newPointB setY:([[边缘点B] y] + vy * shift)];
    
    [tempEdgesRight addObject:[hOzEdge2D edge2DWithPointA:newPointA pointB:newPointB]];
    
    }
    
    // 同一条折线,向左移动
    
    for (int j = [边数] - 1; j >= 0; j--) {
    
    hOzVector2 v = hOzVector2([[[边缘 objectAtIndex:j] pointB] x] - [[[边缘 objectAtIndex:j] pointA] x], [[[边缘 objectAtIndex:j] pointB] y] - [[[边缘 objectAtIndex: j]A点]y]);
    双倍磁力 = sqrt (vx * vx + vy * vy);
    vx = vx / mag;
    vy = vy / mag;
    
    双温度 = vx;
    vx = vy;
    vy = -温度;
    
    hOzPoint2D *newPointA = [[hOzPoint2D alloc] init];
    [newPointA setX:([[[边缘 objectAtIndex:j] pointB] x] - vx * 移位)];
    [newPointA setY:([[[边缘 objectAtIndex:j] pointB] y] - vy * 移位)];
    
    hOzPoint2D *newPointB = [[hOzPoint2D alloc] init];
    [newPointB setX:([[[边缘 objectAtIndex:j] pointA] x] - vx * 移位)];
    [newPointB setY:([[[边缘 objectAtIndex:j] pointA] y] - vy * 移位)];
    
    [tempEdgesLeft addObject:[hOzEdge2D edge2DWithPointA:newPointA pointB:newPointB]];
    
    }
    
    
    
    // 将静态点和交点添加到将定义多边形的点数组中
    
    [tempPolyPoints addObject:[[tempEdgesRight objectAtIndex:0] pointA]]; // 右侧数组的第一个点
    
    for (int k = 0; k < [tempEdgesRight 计数] - 1; k++) {
    
    // 对于这个函数,请参阅答案中下面的链接
    
    hOzPoint2D *inter = [[tempEdgesRight objectAtIndex:k] getIntersectionWithStraight:[tempEdgesRight objectAtIndex:k+1]];   
    
    if (inter == nil) { // 如果边平行,我们插入一个已知点
        [tempPolyPoints addObject:[[tempEdgesRight objectAtIndex:k] pointB]];
    } 别的 {
        [tempPolyPoints addObject:inter];
    }
    }
    
    [tempPolyPoints addObject:[[tempEdgesRight lastObject] pointB]]; // 右侧数组的最后一个点
    
    [tempPolyPoints addObject:[[tempEdgesLeft objectAtIndex:0] pointA]];
    
    // 然后是左边的数组,同样的事情
    
    for (int k = 0; k < [tempEdgesLeft 计数] - 1; k++) {
    hOzPoint2D *inter = [[tempEdgesLeft objectAtIndex:k] getIntersectionWithStraight:[tempEdgesLeft objectAtIndex:k+1]];
    
    if (inter == nil) {
        [tempPolyPoints addObject:[[tempEdgesLeft objectAtIndex:k] pointB]];
    } 别的 {
        [tempPolyPoints addObject:inter];
    }
    }
    
    [tempPolyPoints addObject:[[tempEdgesLeft lastObject] pointB]];
    
    // 使用这个新的有序点数组创建多边形。
    hOzPolygon2D *poly = [hOzPolygon2D Polygon2DWithArrayOfPoints:tempPolyPoints];
    
    返回聚;
    
    }
    

以下是对交点的一些解释,使用 C 代码:http://alienryderflex.com/intersect/

Here is some code of mine in Objective-C that's doing it (even if it's sometimes buggy, I don't know why, let me know how it goes for you...) :

  • it takes each edge of your polyline, then create a first array on the perpendicular of the current edge, on the right (to be in the same way of your polyline, CCW or CW), then a second array on the left.
  • for each edge it tests the point where the 2 infinite straight lines (as your edges are segments) should intersect.
  • finally it adds each point in the desired order to make a polygon

    - (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;
    
    }
    

Here is some explanation for the intersection point, with C code : http://alienryderflex.com/intersect/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文