压平曲面

Flatten curved surface

我正在尝试计算用于牙科成像的全景投影。

我通过分段函数在一个方向上有一个矩形表面 "curved"。如果我们从顶部看它,它看起来像一个常规的分段函数。

"piecewise linear function" 只是由一组 3D 点定义。 所有的点都在同一个平面上。所有 3D 点所在的平面与曲面正交

(见左上角的绿线window)

我正在寻找 "flatten" 它的正确方法。 (非线性变换)

平面应该和曲面一样"length"。 (不是经典的正交投影)

最终,我将使用"flat surface"作为canvas显示感兴趣的信息。

(底部window)

最佳,

我是这样看的:

我会:

  1. 从曲线中取 3 个后续点 P0,P1,P2
  2. 计算U0,V0,U1,V1

    U0 = P1-P0
    U1 = P2-P1
    V0 = cross(U0,(0,0,1)); V0=half_height/|V0|
    V1 = cross(U1,(0,0,1)); V1=half_height/|V1|
    

    所以 A,B 就是 P0 +/- V0C,D 就是 P1 +/- V1。在叉积中使用与 U0,U1 不平行的任何向量我选择了 (0,0,1) 但如果它平行选择任何其他...

  3. 使 ABCD 重新排列

    所以计算A'B'C'D'例如

    A'.x = B'.x = index_of(P0) * sizex
    C'.x = D'.x = index_of(P0) * sizex + sizex
    A'.y = D'.y = sizey
    B'.y = C'.y = 0
    

    其中sizex,sizey是矩形段的大小。您也可以使用 |U0|,|V0|,但在这种情况下,起点 x 将是综合曲线长度。

  4. 计算ABCDA'B'C'D'

    之间的转换

    所以对于 ABCD 内的每个像素 P 计算 A'B'C'D'. Thex` 内的 (x,y) 很容易:

    x = A'.x + dot(P-P0,U0)/|P-P0|
    

    y 很棘手,需要进行一些调整以满足您的需求(因此结果很顺畅,符合您的喜好)。对于初学者尝试简单的方法(将导致段之间的接缝)

    y = (A'.y+B'.y)/2 + dot(P-P),V0)/|P-P0|
    

    现在只需将位置 P 的像素复制到目标图像的位置 (x,y)

    为了使这更平滑,您可以使 V 根据 dot(P-P0,U0)/(|P-P0|*|U0|)V0,V1 之间进行插值,这样它将无缝更改。

    t = dot(P-P0,U0)/(|P-P0|*|U0|)
    V = V0 + (V1-V0)*t
    y = (A'.y+B'.y)/2 + dot(P-P),V)/|P-P0|
    

    如果您需要帮助确定点是否在内部,则像素 P 在内部 if

    dot(P-P0,U0)/(|P-P0|*U0) = <0.0,1.0>
    
  5. 曲线所有段的循环#1

    按曲线的单个样本点步进(不是按 3 ...)