创建相邻三角形的算法


14

我有一个系统,您可以单击一次以在场景中放置节点。当您放置3个节点时,它将形成一个三角形。当您放置任何将来的节点时,它将通过将该节点连接到最近的2个现有节点来创建一个新的三角形。

这在大多数情况下都可以正常工作,但是在接近三角形的锐角附近使用时存在缺陷,因为两个最近节点之一通常不应该使用。

例如,请参见下图。品红色三角形是第一个放置的三角形。如果然后单击标记为X的位置,则得到的是蓝色叠加层所在的新三角形。我想要的是一个绿色覆盖的新三角形。(在此示例中,即与洋红色对称。澄清:绿色和洋红色三角形不重叠-绿色在蓝色一个下方延伸到最左侧的节点)

实际和期望行为的示例

创建新三角形时如何确定要使用哪个2个现有顶点,以使三角形不会像这样叠加?

编辑:搜索最近的边缘会得到更好的结果,但不是完美的结果。考虑这种情况:

在此处输入图片说明

“最近边缘”测试含糊不清,可以返回AB或AC(因为两者的最接近X的点都在A处)。期望的结果将是AC,以形成没有重叠边的ACX三角形。我如何确保这个结果?(如果可能的话,我宁愿不必作为决胜局进行单独的边缘重叠测试,因为考虑到浮点精度问题,我担心最接近的边缘测试不一定会发现2是等距的。)


查看最后放置的5个顶点并选择最接近新放置的顶点的2个顶点是否足够好?我会为您指出三角带的算法(codercorner.com/Strips.htm),但这些算法通常只使用最后两个或最后三个跳过一个。
罗伊(Roy T.)

1
绿色三角形是否与洋红色三角形重叠?目的是什么?用户是否需要控制在何处以及如何创建三角形,还是可以接受点云的三角剖分?
bummzack 2012年

要将其放在图上下文中,本质上是要连接节点,而没有任何边重叠?(假设洋红色/绿色三角形共享一条边)
MichaelHouse

Roy T:否-正如我认为的示例所示,仅选择最接近的2个是错误的。不清楚吗?Bummzack-绿色的与洋红色的不重叠。目的是制作这些三角形的网格或图形。用户确实需要控制,是的。字节56-是的,没有边缘可以交叉。
Kylotan

2
用户会实际看到各个三角形吗?还是将成为一个连续的表面?
bummzack 2012年

Answers:


11

而不是找到到节点的最小距离,而是找到到边缘(即,由节点定义的线段)的最小距离

然后,如果最近的点是一个顶点(您将不得不使用一些浮点epsilon **测试),则比较从新点到该顶点的直线与连接到该顶点的每个边之间的角度。选择具有最小绝对角度的一个:

MinAngle(newPoint, vertex, edge1, edge2)
{
   newEdgeUnit = norm(newPoint - vertex); // don't actually need to normalize this
   edge1Unit = norm(edge1 - vertex);      // you probably have these from your dist to line tests
   edge2Unit = norm(edge2 - vertex);

   edge1Dot = dot(edge1Unit, newEdgeUnit);
   edge2Dot = dot(edge2Unit, newEdgeUnit);

   // you can simply compare dot products to find the minimum absolute angle
   if (edge1Dot > edge2Dot) return edge1;     // set up this way so you can generalize to an array
   return edge2;
}

**为避免添加退化的三角形,这可能会破坏epsilon测试,您可能希望在每个顶点周围放置一个不允许添加点的区域(例如,在上面使用的epsil的若干倍内不允许出现点)。


3
+1-这是恕我直言,这是比其他答案更直接的答案,并且更有可能提供正确的结果。分段距离也很容易通过智能方案计算。
史蒂文·斯塔德尼基

同意,这是一种更清洁的方法。如果我想更多的话,我可能会得出以下
结论

啊,好近!但是,就像Byte56的答案和Jimmy的图一样,有时有2个等距的边,其中之一违反了约束。我已经更新了我的问题。
Kylotan

@Kylotan也许在这种情况下,只需检查哪个重叠并采用另一个选项即可?查找共享所选边的三角形,并检查新三角形是否与现有边在同一边。
凯文·里德

@Kylotan您确保三角形始终具有相同的绕组吗?如果是,则可以排除法线指向新顶点的边缘(使用点积)。
bummzack 2012年

6

放置第一个三角形后,放置新顶点时,您将始终生成两个新边。新三角形的第三条边将始终是与先前三角形的共享边。如果可以找到确定共享边的方法,则可以知道要连接到哪些顶点,但这是最困难的部分。我相信一种方法可以通过从新顶点到生成的最后三个边中的每个边的中心(或可能是最近的3个边)画一条线来实现。

在此处输入图片说明

如果从顶点到边缘中心的线没有与其他两个边缘中的任何一条交叉,则您拥有共享的边缘。共享边将告诉您将新顶点连接到的两个顶点。

吉米(Jimmy)提出了一个关于新三角形将在何处模糊的观点:

模棱两可的三角形

这将使您有机会在两个有效三角形之间进行选择。决胜局可能是哪个中心点最近。

考虑到您的更新,虽然更复杂,但是当您有两个有效的三角形时,我的解决方案只会导致平局。使用此方法,第二个示例图像将产生所需的结果。

在此处输入图片说明


可能有这样一种情况,其中两条线不与边相交(当X更靠近顶点而不是边时)
Jimmy 2012年

@吉米,你能画出这样的情况吗?
MichaelHouse


啊,是的,那么您有两个选择放置三角形的位置!任何一方都可以。也许您可以和到中心的距离最短的人打成一片。
MichaelHouse

@Kylotan这个解决方案行不通吗?您在对Jeff的评论中提到Jimmy的图像有两种情况,一种违反了约束条件,但这不是事实。在吉米的图像中,这两种情况都可以使用我的方法产生有效的三角形。
MichaelHouse

1

拥有洋红色三角形ABC之后,您将合并一个新的顶点X。我认为很明显,将从D开始有两条线不会与三角形ABC的任何边之间相交。

这两行可能是AX&BX,BX&CX或AX&CX。然后,您可以将您的问题视为“两行相交”的经典问题吗?然后,您可以按照以下任何一种方法来检查这对线中的哪条不与任何ABC三角形边缘相交。因此,您将拥有新三角形的两个新边。


这看起来不错,但是您所说的方式似乎是假设仅存在一个三角形。如何将其推广到许多人?
Kylotan

哼...如果您的X和三角形ABC是固定的,我想只有一个,不是吗?
2012年

系统为第二个节点之后的每个节点创建一个新的三角形。
Kylotan '07年

抱歉,我误解了你的问题。让我看看如何将其扩展到许多三角形。
2012年

好吧,我想您可以搜索到X的两个最接近的顶点,这些顶点在连接到X时不交叉任何边缘吗?
bummzack 2012年

1

确定您是否处于明确区域之一(下面的1、2、3)非常容易:将三角形的每个边视为2D平面,然后测试新点位于该平面的哪一侧。如果您在其中两个的内部,但在一个的外部,则该一个对应于为新三角形贡献两个顶点的三角形的边缘。

三角形的沃罗诺伊地区

如果您在一个内部,而在两个外部,则处于模棱两可的情况,其中三角形到新点的最近部分是一个角。在这种情况下,您可以从相对边的中点(您位于其中的那一个)和最近的顶点(由您外面的两个平面共享的那一个)的中点形成一个2D平面。您可以选择一条边,具体取决于新点位于该平面的哪一侧。

请注意,在2D模式下进行平面测试的方式与在3D模式下进行测试的方式相同:用平面法线(在2D模式下,这是直线的垂直线)将矢量从平面上的任意点指向您的点。

(顺便说一下,此图中洋红色分隔的区域称为Voronoi区域;它们是包含最接近三角形的特定特征(边或顶点)的点的空间区域。编辑:我在这里的术语实际上不是完全正确,这不是沃罗诺伊地区。)


我现在还不清楚如何将其推广到场景中的多个三角形-特别是如果最近的要素是一个可以被多个三角形共享的顶点。
Kylotan

@Kylotan只需对所有三角形运行算法,然后选择整体最近的特征。无论如何,您都需要一些打破常规的逻辑。如果最后得到的最近特征是共享顶点,那么您应该只在一个三角形的边缘区域(#1,#2,#3),那么也许您可以选择那个?
约翰·卡尔斯贝克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.