1 \documentclass{scrartcl
}
2 \usepackage{amsmath,amssymb,mathtools
}
3 \usepackage[english
]{babel
}
5 % Allow to build the PDF with either lualatex (preferred) or pdflatex
10 \usepackage[T1]{fontenc}
11 \usepackage[utf8
]{inputenc}
15 \title{Handcraft algorithm
}
16 \subtitle{A disjointed algorithm for offsetting cubic Bézier curves
}
17 \author{Nicola Fontana
}
18 \date{February
25,
2009}
20 \setlength\parindent{0pt
}
21 \setlength\parskip{6pt
}
28 This is basically the transcription of the algorithm used by the
29 ADG canvas on its early development phases. This algorithm has been
30 superseded in recent releases by BAIOCA. It is included here for
31 completeness and historical reasons.
34 Given a cubic Bézier primitive, it must be found the approximated
35 Bézier curve parallel to the original one at a specific distance
36 (the so called "offset curve"). The four points needed to build
37 the new curve must be returned.
39 To solve the offset problem, a custom algorithm is used. First, the
40 resulting curve MUST have the same slope at the start and end point.
41 These constraints are not sufficient to resolve the system, so I let
42 the curve pass thought a given point (r, known and got from the
43 original curve) at a given time (m, now hardcoded to
0.5).
45 Firstly, some useful variables are defined:
49 v_0 &=
\text{unitvector
}(
\text{p
[1]} -
\text{p
[0]})
\times \text{offset
} \\
50 v_3 &=
\text{unitvector
}(
\text{p
[3]} -
\text{p
[2]})
\times \text{offset
} \\
51 p_0 &=
\text{p
[0]} +
\text{normal
}(v_0) \\
52 p_3 &=
\text{p
[3]} +
\text{normal
}(v_3) \\
56 The resulting curve must have the same slopes than the original
57 one at the start and end points. Forcing the same slopes means:
63 where $k_0$ is an arbitrary factor. Decomposing for $x$ and $y$:
67 p_
{1x
} = p_
{0x
} + k_0 v_
{0x
} \\
68 p_
{1y
} = p_
{0y
} + k_0 v_
{0y
} \\
72 and doing the same for the end point:
76 p_
{2x
} = p_
{3x
} + k_3 v_
{3x
} \\
77 p_
{2y
} = p_
{3y
} + k_3 v_
{3y
} \\
81 This does not give a resolvable system though. The curve will be
82 interpolated by forcing its path to pass throught $r$ when
83 \textit{time
} is $m$, where $
0 \leq m
\leq 1$. Knowing the function of
87 C(t) = (
1-t)^
3p_0 +
3t(
1-t)^
2p_1 +
3t^
2(
1-t)p_2 + t^
3p_3.
90 and forcing $t = m$ and $C(t) = r$:
94 r &= (
1-m)^
3 p_0 +
3m(
1-m)^
2 p_1 +
3m^
2 (
1-m) p_2 + m^
3 p_3 \\
95 (
1-m) p_1 + m p_2 &=
\frac{r - (
1-m)^
3p_0 - m^
3p_3
}{3m (
1-m)
} \\
99 brings to the final system:
103 p_
{1x
} = p_
{0x
} + k_0 v_
{0x
} \\
104 p_
{1y
} = p_
{0y
} + k_0 v_
{0y
} \\
105 p_
{2x
} = p_
{3x
} + k_3 v_
{3x
} \\
106 p_
{2y
} = p_
{3y
} + k_3 v_
{3y
} \\
107 (
1-m) p_
{1x
} + m p_
{2x
} =
\frac{r_x - (
1-m)^
3 p_
{0x
} - m^
3 p_
{3x
}}{3m (
1-m)
} \\
108 (
1-m) p_
{1y
} + m p_
{2y
} =
\frac{r_y - (
1-m)^
3 p_
{0y
} - m^
3 p_
{3y
}}{3m (
1-m)
} \\
112 Substituting and resolving for $k_0$ and $k_3$:
116 (
1-m) k_0 v_
{0x
} + m k_3 v_
{3x
} =
\frac{r_x - (
1-m)^
3 p_
{0x
} - m^
3 p_
{3x
}}{3m (
1-m)
} - (
1-m) p_
{0x
} - m p_
{3x
} \\
117 (
1-m) k_0 v_
{0y
} + m k_3 v_
{3y
} =
\frac{r_y - (
1-m)^
3 p_
{0y
} - m^
3 p_
{3y
}}{3m (
1-m)
} - (
1-m) p_
{0y
} - m p_
{3y
} \\
123 (
1-m) k_0 v_
{0x
} + m k_3 v_
{3x
} =
\frac{r_x - (
1-m)^
2 (
1+
2m) p_
{0x
} - m^
2 (
3-
2m) p_
{3x
}}{3m (
1-m)
} \\
124 (
1-m) k_0 v_
{0y
} + m k_3 v_
{3y
} =
\frac{r_y - (
1-m)^
2 (
1+
2m) p_
{0y
} - m^
2 (
3-
2m) p_
{3y
}}{3m (
1-m)
} \\
131 s =
\frac{r - (
1-m)^
2(
1+
2m) p_0 - m^
2(
3-
2m) p_3
}{3m (
1 - m)
}
134 reduces the above to this final equations:
138 s_x = (
1-m) k_0 v_
{0x
} + m k_3 v_
{3x
} \\
139 s_y = (
1-m) k_0 v_
{0y
} + m k_3 v_
{3y
} \\
143 If $v_
{0x
} \ne;
0$, the system can be resolved for $k_0$ and $k_3$
144 calculated accordingly:
148 k_0 =
\frac{s_x - m k_3 v_
{3x
}}{(
1-m) v_
{0x
}} \\
149 s_y =
\frac{(s_x - m k_3 v_
{3x
}) v_
{0y
}}{v_
{0x
}} + m k_3 v_
{3y
} \\
155 k_0 =
\frac{s_x - m k_3 v_
{3x
}}{(
1-m) v_
{0x
}} \\
156 s_y -
\frac{s_x v_
{0y
}}{v_
{0x
}} = k_3 m (v_
{3y
} -
\frac{v_
{3x
} v_
{0y
}}{v_
{0x
}}) \\
162 k_0 =
\frac{s_x - m k_3 v_
{3x
}}{(
1-m) v_
{0x
}} \\
163 k_3 =
\frac{s_y - s_x
\frac{v_
{0y
}}{v_
{0x
}}}{m (v_
{3y
} - v_
{3x
} \frac{v_
{0y
}}{v_
{0x
}})
} \\
167 Otherwise, if $v_
{3x
} \ne 0$, the system can be solved for $k_3$ and $k_0$
168 calculated accordingly:
172 k_3 =
\frac{s_x - (
1-m) k_0 v_
{0x
}}{m v_
{3x
}} \\
173 s_y = (
1-m) k_0 v_
{0y
} +
\frac{[s_x - (
1-m) k_0 v_
{0x
}] v_
{3y
}}{v_
{3x
}} \\
179 k_3 =
\frac{s_x - (
1-m) k_0 v_
{0x
}}{m v_
{3x
}} \\
180 k_0 (
1-m) (v_
{0y
} - k_0 v_
{0x
} \frac{v_
{3y
}}{v_
{3x
}}) = s_y - s_x
\frac{v_
{3y
}}{v_
{3x
}} \\
186 k_3 =
\frac{s_x - (
1-m) k_0 v_
{0x
}}{m v_
{3x
}} \\
187 k_0 =
\frac{s_y - s_x
\frac{v_
{3y
}}{v_
{3x
}}}{(
1-m) (v_
{0y
} - v_
{0x
} \frac{v_
{3y
}}{v_
{3x
}})
} \\
191 The whole process must be guarded against division by
0 exceptions.
192 If either $v_
{0x
}$ and $v_
{3x
}$ are
0, the first equation will be
193 inconsistent. More in general, the
194 $v_
{0x
} \times v_
{3y
} = v_
{3x
} \times v_
{3y
}$ condition must be avoided. This is
195 the first situation to avoid, in which case an alternative approach