RALPH R. MARTIN, Cardiff University
We define the optimisation problem in terms of minimising an energy function ${\prosedeflabel{computation}{{E}}}(x)$, where $x$ represents the linkage configuration and geometric parameters of the transforming pop-up . For simplicity of presentation, we leave the dependence on $x$ implicit in the following.
Ensuring freedom from collisions is enforced as a hard constraint. Given a configuration $x$, we first check for collision during transformation, and if detected, we give the energy function ${\proselabel{computation}{{E}}}$ a value certain to be greater than the energy for any non-colliding configuration. Our implementation uses the OBB-tree algorithm [Gottschalk et al. 1996] for collision detection, like other recent mechanical modeling works such as [Zhu et al. 2012]. Optionally, to avoid collision with the ground, we add a dummy ground patch of large enough area to enclose the design, and include it during collision checking. Users may choose whether to enable this option or not: if the goal is to place the pop-up inside a book, this option should be enabled, but if the goal is to make a free-standing pop-up, it is unnecessary.
If there is no collision, the energy function ${\proselabel{computation}{{E}}}$ is defined as the sum of a shape term and a flip term:
$$\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\argmin}{arg\,min}
\begin{align*}
\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, 'E', 'computation', 'def', false, '')", "id":"computation-E", "sym":"E", "func":"computation", "localFunc":"", "type":"def", "case":"equation"} }{ {\mathit{E}} } & = \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$λ_s$', 'computation', 'use', false, '')", "id":"computation-$λ_s$", "sym":"$λ_s$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {λ_s} }\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$E_s$', 'computation', 'use', false, '')", "id":"computation-$E_s$", "sym":"$E_s$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {E_s} } + \left( 1 - \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$λ_s$', 'computation', 'use', false, '')", "id":"computation-$λ_s$", "sym":"$λ_s$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {λ_s} } \right)\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$E_f$', 'computation', 'use', false, '')", "id":"computation-$E_f$", "sym":"$E_f$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {E_f} }\\\eqlabel{ {"onclick":"event.stopPropagation(); onClickEq(this, 'computation', ['$E_f$', '$λ_s$', '$E_s$', 'E'], false, [], [], 'RSA9IGAkzrtfcyRgYCRFX3MkYCArICgxIC0gYCTOu19zJGApYCRFX2YkYA==');"} }{}
\end{align*}
\tag{1}\label{1}$$
The shape term ${\prosedeflabel{computation}{{E_s}}}$ represents the shape constraint , i.e. it favors shapes of pop-up for which the untransformed and transformed states are good matches to the user given patterns. The flip term ${\prosedeflabel{computation}{{E_f}}}$ represents the flip constraint, penalizing any patch areas which do not flip and are visible in both untransformed and transformed states . ${\prosedeflabel{computation}{{λ_s}}}$ is a weight to control the relative contributions of the two terms, and is set to 0.4 .
Shape term. The shape term accounts for how well the pop-up in the untransformed and transformed states ${\proselabel{computation}{{S_1}}}$ and ${\proselabel{computation}{{S_2}}}$ match the shapes of the user given source and target patterns ${\proselabel{computation}{{U_1}}}$ and ${\proselabel{computation}{{U_2}}}$. The shape matching cost is defined in terms of a contour matching cost and an area matching cost:
$$\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\argmin}{arg\,min}
\begin{align*}
\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$E_s$', 'computation', 'def', false, '')", "id":"computation-$E_s$", "sym":"$E_s$", "func":"computation", "localFunc":"", "type":"def", "case":"equation"} }{ {E_s} } & = \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$E_c$', 'computation', 'use', false, '')", "id":"computation-$E_c$", "sym":"$E_c$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {E_c} } + \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$E_a$', 'computation', 'use', false, '')", "id":"computation-$E_a$", "sym":"$E_a$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {E_a} }\\\eqlabel{ {"onclick":"event.stopPropagation(); onClickEq(this, 'computation', ['$E_c$', '$E_a$', '$E_s$'], false, [], [], 'YCRFX3MkYCA9IGAkRV9jJGAgKyBgJEVfYSRg');"} }{}
\end{align*}
\tag{2}\label{2}$$
The contour matching cost is computed using the shape context method [Belongie et al. 2002], and is given by:
$$\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\argmin}{arg\,min}
\begin{align*}
\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$E_c$', 'computation', 'def', false, '')", "id":"computation-$E_c$", "sym":"$E_c$", "func":"computation", "localFunc":"", "type":"def", "case":"equation"} }{ {E_c} } & = \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, 'D', 'computation', 'use', false, '')", "id":"computation-D", "sym":"D", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {\mathit{D}} }\left( \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$S_1$', 'computation', 'use', false, '')", "id":"computation-$S_1$", "sym":"$S_1$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {S_1} },\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$U_1$', 'computation', 'use', false, '')", "id":"computation-$U_1$", "sym":"$U_1$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {U_1} } \right) + \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, 'D', 'computation', 'use', false, '')", "id":"computation-D", "sym":"D", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {\mathit{D}} }\left( \idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$S_2$', 'computation', 'use', false, '')", "id":"computation-$S_2$", "sym":"$S_2$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {S_2} },\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$U_2$', 'computation', 'use', false, '')", "id":"computation-$U_2$", "sym":"$U_2$", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {U_2} } \right)\\\eqlabel{ {"onclick":"event.stopPropagation(); onClickEq(this, 'computation', ['D', '$S_2$', '$S_1$', '$U_1$', '$U_2$', '$E_c$'], false, [], [], 'YCRFX2MkYCA9IEQoYCRTXzEkYCwgYCRVXzEkYCkgKyBEKGAkU18yJGAsIGAkVV8yJGAp');"} }{}
\end{align*}
\tag{3}\label{3}$$
where ${\proselabel{computation}{{D}}}(·)$ denotes the shape context matching cost. In our implementation, we sample 100 points on each contour to perform this computation.
The area matching cost measures the difference of region coverage between the pop-up and user given patterns. It is computed as:
$${\proselabel{computation}{{E_a}}} = \sum_i {\prosedeflabel{computation}{{\lambda_a}}} ||S_i \setminus U_i|| + (1-\lambda_a)||U_i \setminus S_i||\tag{4}\label{4}$$
where \ is the set difference operator, $∥ · ∥$ denotes the normalized area of a region, i.e. its area divided by the sum of the areas of all patches, and ${\prosedeflabel{computation}{{\lambda_a}}}$ is a relative weight. $S_i \setminus U_i$ are redundant regions, i.e. regions covered by the pop-up but not covered by the user given pattern. $U_i \setminus S_i$ are unrepresented regions, i.e. regions covered by the user given pattern but not covered by the pop-up. Redundant regions are relatively unimportant, since the later patch refinement step can crop them. However, unrepresented regions will show the ground patch as they will not be included in the transforming pop-up. Hence, in our implementation, we set ${\prosedeflabel{computation}{{\lambda_a}}} = 0.1$ to more strongly penalize unrepresented regions.
Flip term. Since visible regions in untransformed and transformed states are painted with source and target pattern textures respectively, to avoid conflicts in texture painting, we should minimise regions which are visible in both untransformed and transformed states which do not show different sides of the paper. The flip term is simply defined as the sum of the areas of all regions which violate this constraint (again normalized as in Equation 4):
$$\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\argmin}{arg\,min}
\begin{align*}
\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, '$E_f$', 'computation', 'def', false, '')", "id":"computation-$E_f$", "sym":"$E_f$", "func":"computation", "localFunc":"", "type":"def", "case":"equation"} }{ {E_f} } & = \sum_{\mathit{i}} \left\|\idlabel{ {"onclick":"event.stopPropagation(); onClickSymbol(this, 'R', 'computation', 'use', false, '')", "id":"computation-R", "sym":"R", "func":"computation", "localFunc":"", "type":"use", "case":"equation"} }{ {\mathit{R}} }_{ \mathit{i} }\right\|\\\eqlabel{ {"onclick":"event.stopPropagation(); onClickEq(this, 'computation', ['R', '$E_f$'], false, [], [], 'YCRFX2YkYCA9IHN1bV9pIHx8Ul9pfHw=');"} }{}
\end{align*}
\tag{5}\label{5}$$
where ${\prosedeflabel{computation}{{R}}}_i$ is any region of a patch which is visible from the same side in both states .