Search code examples
mathtransformationsurfaceflatten

Flatten curved surface


I am trying to compute a panoramic projection for dental imaging purpose.

I have a rectangle surface "curved" in one direction by a piecewise function. If we look at it from the top, it looks like a regular piecewise function.

The "piecewise linear function" is just defined by a set of 3D points. All the points are in the same plane. The plane where all the 3D points sit is orthogonal to the curved surface

(see the green line in the top-left window)

enter image description here

I am looking for the proper way to "flatten" it. (non linear transform)

The flat surface should have the same "length" as the curved one. (it is not a classic orthogonal projection)

Ultimately, I will use the "flat surface" as a canvas to display the information of interest.

(Bottom window)

enter image description here

Best,


Solution

  • I see it like this:

    img

    I would:

    1. take 3 consequent points P0,P1,P2 from your curve
    2. compute 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|
      

      so A,B is just P0 +/- V0 and C,D is P1 +/- V1. In the cross product Use any vector non parallel with U0,U1 I chose (0,0,1) but in case it si parallel chose any other...

    3. make the ABCD a recangle

      So compute A'B'C'D' for example

      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
      

      Where sizex,sizey is the size of rectangle segment. You can also use |U0|,|V0| but in that case the start x will be integrated curve length.

    4. compute transformation between ABCD and A'B'C'D'

      so for each pixel P inside ABCD compute (x,y) inside A'B'C'D'. Thex` is easy:

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

      y is tricky and need some tweaking to suite your needs (so the result is smooth to your liking). For starters try simple approach (will lead to seams between segments)

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

      Now just copy the pixel at position P into your target image at position (x,y)

      To make this more smooth you can make V interpolated between V0,V1 dependent on the dot(P-P0,U0)/(|P-P0|*|U0|) so it will change seamlessly.

      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|
      

      If you need help with determining if point is inside then pixel P is inside if

      dot(P-P0,U0)/(|P-P0|*U0) = <0.0,1.0>
      
    5. loop #1 for all segments of the curve

      step by single sample point of curve (not by 3 ...)