A Simple and Efficient Algorithm to Generate Tangent Developable Surface from Two Intersections of Curved Surface

Mitsuhiro Itakura

Download this B2


Sec. 1: Introduction

Designing a developable surface is an interesting and challenging problem. Beside the obvious application for papermodels, it has industrial importance in the fields such as ship's hull design. In the literature, there are several studies on algorithms to generate such surfaces from a CAD data of fine triangular surface mesh. In this work I present a different strategy by which developable surface can be directry generated from two curves on two different planes, either parallel or non-parallel. This algorithm is especially useful when interpolating two intersections of a curved body and approximating the original surface by developable one.

Online references for mesh unfolding methods:


As you know, you can bend a piece of paper and make a cylinder, but you can't bend a piece of paper and make a sphere or a donut shape. Paper can't be bent in two different directions at the same time, and there is always one straight direction on a bent paper. Designing a papermodel is a process of finding this straight line direction on the subject's surface (or in case of no such direction, one must find the smallest curvature direction and segment the surface in that direction, balancing the workload and appearance). A class of curved surface which can be made by bending a paper is called "developable surface" in mathematics. There are three kinds of developable surface: cylinder, cone, and tangent developable surface. In the next section I'll exlain tangent developable surface.

Sec. 2: Generating Tangent developable from two curves

Tangent developable is a "ruled surface" and generated by sweeping a straight tangent line of some curve in 3D. Let us denote this curve in R^3 by \vec{r}(t), 0 \leq t \leq 1.
Tangent developable surface T(t,s) is generated from this curve as follows:
\vec{T}(t, s)=\vec{r}(t)+s \vec{v}(t) where \vec{v}= d\vec{r}(t)/dt is a tangent vector of the curve r(t) at t=t. As the name suggests, T(t,s) is a developable surface.
Suppose that we have two planar curves, \vec{r_1}(t) , 0 \leq t \leq 1 on a plane P1 and \vec{r_2}(t) , 0 \leq t \leq 1 on another plane P2. Furthermore, let us denote the tangent vectors of these curves by \vec{v_1}(t) and \vec{v_2}(t).
For the simplicity of argument, let us assume that P1 and P2 are parallel. Non-parallel case will be considered later.
Let us denote the direction of tangent vectors by \theta_i(t), which is an angle between v_i and some fixed reference vector \vec{e} lying in the planes P1 and P2. Furthermore, let us assume that \theta_i(t) monotonically increases, that is, d\theta_i(t)/dt \geq 0, and that the angle coinsides at both ends, namely \theta_1(0)=\theta_2(0), \theta_1(1)=\theta_2(1).

Under these assumptions, for any given point p1=r1(t1) on r1, one can always find a point p2=r2(t2) on r2 such that \theta_1(t1) = \theta_2(t2), that is, the tangent vectors on both points are parallel. A surface sweapt by lines between p1 and p2 for all such pairs is developable. This can be shown as follows.

It is always possible to re-define the curve r2(t) as r2(F(t)), where the function F(t) finds the point on r2 such that \theta_1(t) = \theta_2(F(t)). In this case v1(t) and v2(t) is always parallel. Now let us define the third curve r3 as follows:
\vec{r_3} = \vec{r_1}(t) - \vec{r_{12}}(t) \frac{\vec{v_1}(t)\cdot \vec{v_{12}}(t)}{ \vec{v_{12}}(t)^2}
where r12=r2-r1 and v12= v2-v1. It can be easily shown that the tangent vector of r3(t) passes through r1(t) and r2(t). Therefore the ruled surface between r1(t) and r2(t) is the tangent developable generated by r3(t), which is developable.

This condition can be stated in a more intuitive way. If two infinitesimal straigt line segments on two curves lie in a same plane, one can paste a thin strip of paper between them, without any "twist". Note that not all the ruled surface is developable, and iff a ruled surface can be broken down to twist-free thin strips, it is developable. In reality, however, materials allow small twist and one can generate mathematically-forbidden surfaces, like this: http://pepakuradesigner.blog99.fc2.com/blog-entry-33.html

Obviously, for the monotonically decreasing \theta case, the same kind of argument can be applied. In the following sections, the restrictions employed in this section for the simplicity of argument will be removed one by one, and the scheme will be generalized.

Sec. 3: Generalization: \theta_1(0) \neq \theta_2(0)


Suppose that \theta_1(0) \leq \theta_2(0), and \theta_1(t_1) = \theta_2(0). In this case, one can apply the procedure in Sec.2 to a portion of r1, r1(t_1 \leq t \leq 1) and entire curve of r2(t). For the rest portion of r1, one can generate a "cone" by sweeping a line between this portion and a tip point r2(0). This surface is developable, obviously.
Likewise, if \theta_1(1) \neq \theta_2(1), the same kind of procedure can be applied to this end.

Sec. 4: Generalization: Not monotonical case

Suppose that there are inflection points in r1 and r2, where the sign of d\theta_i(t)/dt changes. In this case, the curves can be divided into segments r1a, r1b, r1c, ... and r2a, r2b, r2c, ..., segmented by these inflection points.
Suppose that the sign of d\theta_i(t)/dt coinsides on both sides, r1a and r2a, r1b and r2b, and so on.
In this case we can apply the procedure of Sec.2 and Sec.3 to each pair of segments. Therefore, if r1 and r2 has the same number of inflection points, a developable ruled surface can be generated between r1 and r2.


Sec. 5: Implementing the Algorithm

  • Step 0: Distribute many points on r1 and r2 (approximately) evenly. The number of points may differ on r1 and r2. Let us denote the number of points by N1 and N2, and each point by r_1(t_i) and r_2(t_i). Calculate \theta_i(t) (taking care of branch-cut) and its delivative (curvature) k(t) = d\theta /dt at each point. For each point on each curve, assign segment index as follows: Start from t=0 point with segment index 0. If the sign of k(t) at i'th point is the same as that of (i-1)'th point, copy the segment index of the i-1 to i'th point. If not, increase the index by 1 and assign it to i. If the point is the last one at the end, increase its index by 1.
  • Step 1: Let v1 and v2 be the first point on r1 and r2, respectively. Connect v1 and v2.
  • Step 2: Begin Loop. If both v1 and v2 are at the end, exit
  • Step 3: Compare the segment index of v1 and v2. If they are different, move forward the point (v1 or v2) which has the smaller index, to the next point on the curve. Connect v1 and v2. Goto Step 2.
  • Step 3': Compare \theta times the sign of k(t), at v1 and v2. Move forward the point (v1 or v2) which has the smaller value, to the next point on the curve. Connect v1 and v2. Goto Step 2.


Sec. 6: Generalization: Non-parallel case

If the two planes P1 and P2 is non-parallel, there must be a line of intersection of these two planes. Let us define this line as Y-axis, and lines perpendicular to Y-axis on P1 and P2 as X1-axis and X2-axis, respectively. Furthermore, let us denote unit vectors of these axis by \vec{e}_Y, \vec{e}_{X1} and \vec{e}_{X2}, respectively.
The tangent line of r1 and r2 intersects with the Y-axis at some point. Let us denote these points by C1 and C2, respectively. If C1 and C2 coincide, the infinitesimal line segments at r1 and r2 lie in a same plane and one can define the third curve r3 like the parallel case. Therefore if we use the Y-coordinate of C1 and C2 instead of \theta in Step 3', developable surface is generated. Note that the sign of dC_i/dt coincides with that of curvature, so one can use the same segmentation as in the parallel case.


Sec. 7: Actual Implementation

Most of 2D and 3D drawing tools, such as Inkscape and Blender, support Bezier curve. Bezier curve is a parametric curve (X(t), Y(t)), X and Y being cubic polynomial of t. I have coded a routine which reads SVG file and extracts a data of curve with certain ID, and generate a rail in 3D space. The input file for generating a surface looks like:

BEZ b1: curves.svg b1
BEZ b2: curves.svg b2
POS p1: 0 0 0.3
POS p2: 0 1 0.3
RAIL r1: b1 vx vz p1
RAIL r2: b2 vx vz p2
SURF s: r1 r2
UNFOLD s: 1 1

The code reads curves.svg and finds Bezier curve data ID'd as b1 and b2, then generates rail r1 which is defined as  \vec{p1} + X(t) \vec{e}_x X(t) + Y(t) \vec{e}_z Y(t) and so on. Then a developable surface is generated between two rails r1 and r2, and the code unfolds the surface and print it in an output SVG file at position (1,1).
After that, I edit the SVG file to add texture etc.

Future plan

I'm looking for a geek who can port my code (written in C++) to blender plugin. It will include thin triangle mesh generation between two Bezier rails and unfolding them, and output to SVG file. If you are interested, please contact me. I'll creare a Sourceforge project and join you to the devteam.