【问题标题】:Implementing an automatic line segment scaling algorithm实现自动线段缩放算法
【发布时间】:2020-08-02 21:49:05
【问题描述】:

我收到以下几点作为输入:

Point A(200 ; 400)
Point B(400 ; 400)
Point C(400 ; 200)
Point D(600 ; 200)
Point E(700 ; 500)
Point F(500 ; 700)
Point G(200 ; 600)

这些点构成了要绘制的线段 AB、BC、CD、DE、EF、FG 和 GA 那样:

现在我的任务是编写一个自动缩放算法,基于 确定实际段长度的最接近的数字:

因为我必须自己决定限制条件,所以我决定尽力而为 保持角度完整。首先,我确定最长的段以便 建立一个比例(即“标记长度 6”= 250px,然后标记 长度 1 ~= 41.7)。

然后我处理下一个更短的片段,从它的中心重新调整它,然后应用 相同的向量翻译到它的邻居。

这是我现在能得到的最好的输出:

但是这种方法最终会陷入无限循环,或者说真的不准确 在其他情况下,尤其是当线条是手绘且不完美时 直。

是否有众所周知的算法来解决这种情况?我没有任何线索 在搜索一些几何库(如 GEOS)时从哪里开始, libigl, ...

【问题讨论】:

  • 我不确定我是否理解。预期的输出究竟是什么?缩放不是简单地将所有段乘以一个常数因子吗?如果是这种情况,那么您通过说-Point A 坐标平移所有点(即您移动到局部坐标),然后将所有点乘以常数 C,最后您通过+Point A 坐标平移回来(即您移动回全局坐标)坐标)。如果您希望缩放以Point A 以外的其他点为中心,则只需选择一个。所有点的算术平均值也是一个有效的选择。无论哪种方式,您都需要知道中心在哪里。
  • 如果你保留角度,我看不出这会如何工作。例如:取一个正方形并将对边重新缩放为 6 和 3。
  • @freakish 假设有人在绘制平面图,然后在纸上没有足够的空间来绘制矩形,迫使自己绘制正方形。他们所能做的就是通过标记来定义段的长度。这是预期和已经实现的一个简单示例,当然,当所有段都被标记时,我不必处理这种情况:imgur.com/a/A4y1N63
  • @Botje 你好,见上图(一次只能通知一个人)

标签: c++ algorithm math geometry linear-algebra


【解决方案1】:

如果你深入研究它,这是一个非常困难的问题。通过乘以一个常数来进行简单的缩放是没有问题的,因为这会改变形状、角度等......

对于放大和缩小多边形是使用在垂直方向上向内/向外移动边并随后修复连接点的最佳技术。但请注意这里的一些基础知识非常困难:

您的问题在此之上增加了未知的边长。非常类似于纸盒切割 SW 技术(但更简单)。所以从我的角度来看,你应该:

  1. 用极坐标编码对多边形进行编码

    所以不仅使用笛卡尔坐标系,还使用极坐标系。多边形被编码为一组连接线(循环)。每一行都需要这个信息:

    float angle;
    float length;
    int flag;
    float x0,y0,x1,y1; // computed endpoints for rendering
    

    angle 可以由atan2(y1-y0,x1-x0) 计算,长度很明显sqrt((x1-x0)^2+(y1-y0)^2)。该标志可以存储哪些值是最终的(测量的)。

  2. 设置测量值

    所以改变你知道的边的长度并相应地设置它们的标志

  3. 再次重新计算端点

    line[i].x0=line[i-1].x1;
    line[i].y0=line[i-1].y1;
    line[i].x1=line[i].lengths*cos(line[i].angle);
    line[i].y1=line[i].lengths*sin(line[i].angle);
    

    第一行的x0,y0 将是多边形的原点。为了计算一条线,必须计算前一段,并且必须设置实际线的所有值。因此,计算所有可以计算的行,并在无法计算更多行时停止。

    如果您没有关于上一行的位置信息,您应该将其标记为浮动位置并盲目选择一些(如(0,0))。

  4. 合身

    会有一堆未计算的线(具有未设置的实际长度/角度)。如果计算出之前和之后的行,您可以简单地使用他们的x0,y0,x1,y1

    如果您计算了一行并且下一行被标记为浮动,则重新计算它及其所有追随者,直到未计算或命中同一行。

    真正的问题将是一组连接的未计算线。对于那些您可以通过乘以常数 + translate 或更改第一行和最后一行的长度直到它们加入计算部分来进行缩放。取决于您要保留的形状的哪些属性。

正如你所见,这不是一件容易的事,而且很可能会有一些我忘记处理的边缘情况。

可缩放的纸盒几何形状基于缩放方程。线的每个维度都由字符串而不是数字定义,并且它可以使用极坐标和笛卡尔(可切换)线表示。字符串可以包含数字、预定义的大小常数或等式。这样,只需更改几个系数(通常是盒子的高度、宽度、深度、纸张厚度),整个形状就可以重新缩放,而无需任何拟合。但是创建这样的几何图形并不是一件容易的事。有用于 BoxMaker 之类的制盒机(切割和划线/嵌入绘图仪)的软件,但这些机器通常需要连接昂贵的机器才能运行,并且不是免费使用的。

如果您想改为这种方式,则需要实现表达式评估,请参阅:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多