3.2 Data Structures
3.2.1 Generation of Basic Primitives
3.2.1.2 Point Clouds (Pointshells)
The point cloud or pointshell P of a triangle mesh T is obtained from its previously gener- ated voxelmap V by projecting the surface voxel centers (C) on their respective (closest) triangles. Additionally, normal vectors pointing inwards the object are computed. The primitive pointshell consists basically in the set P:
P = {(P, n)1, . . . , (P, n)i, . . . , (P, n)NP} = {(P, n)i} NP
i=1, (3.6)
with (P, n) ∈ R3+3 being the pair point-normal and N
P the total amount of pairs or
pointshell points.
Figure3.2(d) illustrates the steps necessary for generating such a set P. Similarly as in the voxelmap generation, all triangles are traversed, visiting all surface voxels within the triangle bounding box. Given a voxel center C ∈ R3, its projection P onto the
triangle is computed with quadratic programming, as explained below. There exists a closed-form analytical solution to it and the approach has been shown to be up to 37% faster than using algebraic projections [Sag08].
In order to obtain the analytical expression of the projected point P , first, a point rT on the triangle with vertices {T1, T2, T3} is expressed in the local triangle coordinates
(u1, u2) [Ebe99]: rT(u1, u2) = r0+ u1r1+ u2r2= T1+ u1(T2− T1) + u2(T3− T1) subject to 0 ≤ u1 ≤ 1 0 ≤ u2 ≤ 1 u1+ u2≤ 1. (3.7)
The quadratic function that defines the squared distance between C and and rT is:
q(u1, u2) = krT(u1, u2) − Ck2. (3.8)
The value of q is minimum on the projection point P , which leads to the formulation of the quadratic programming problem:
min q(u1, u2) = a1u21+ 2a2u1u2+ a3u22+ 2a4u1+ 2a5u2+ a6 subject to g1(u1, u2) = u1 ≥ 0 g2(u1, u2) = u2 ≥ 0 g3(u1, u2) = 1 − u1− u2 ≥ 0, (3.9)
where all ai values are easily obtainable scalars:
a1= kr1k2, a2 = r1Tr2, a3 = kr2k2,
a4 = rT1(r0− C), a5= rT2(r0− C), a6 = kr0− Ck2.
(3.10) Note that only u1 and u2 are unknown in (3.10). Their solution values (u∗1, u∗2) yield
the projection point P = rT(u∗1, u∗2)and its distance to the voxel center C:
»
q(u∗1, u∗2). In order to obtain them, the Karush-Kuhn-Tucker (KKT) conditions are applied to (3.10). This results in the following nonlinear system with five equations and five unknowns (variables u1, u2 and the Lagrange multipliers λi, ∀i ∈ {1, 2, 3}):
(
∇q(u1, u2) −Piλi∇gi(u1, u2) = 0
λigi = 0.
(3.11) This system in (3.11) yields the set of seven solutions shown in Table 3.1. One corresponds to a point on the triangle and the other six to points on the boundary: three on each of the edges and three on each of the vertices. The real solution from the set of seven is the one which fulfills the conditions in (3.7) and additionally leads to real λi ≥ 0. This projection method is a backbone function or tool used in several data
Table 3.1: List of seven solutions to the system in (3.11). Each of them corresponds to one point inside the triangle or at the boundary (edges or vertices). The values of ai are parameters defined using the vertices of the triangle (see (3.10)). With this set, a general closed-form solution is given to the problem of projecting any point on any triangle (parametrized as in (3.7)).
u1 u2 λ1 λ2 λ3 rT a2aa5−a3a4 3a1−a22 a2a4−a5a1 a3a1−a22 0 0 0 v1 −aa4 1 0 0 2(a5a1−a2a4) a1 0 v2 a42a−a3−a5+a2 2−a1−a3 a4−a5−a2+a1 −2a2+a1+a3 0 0
2(a2(a4+a5+a2)−a3(a1+a4)−a5a1) −2a2+a1+a3 v3 0 −aa5 3 2(a3a4−a2a5) a3 0 0 T1 0 0 2a4 2a5 0 T2 1 0 0 2(a2+ a5− a1− a4) −2(a1+ a4) T3 0 1 2(a2+ a4− a3− a5) 0 2(a5− a3)
The pointshell generation is performed in two phases. In the first one, all the projected points are computed using the presented optimization method, but only the projected points that lie inside the triangle are stored into the structure of the pointshell, tagging the surface voxels to which they belong to as projected. The rest of the boundary-points are stored separately, indexing also the voxel from which they were projected. Adding a point Pi to the pointshell P requires also checking that the new point is at least
half a voxel size (s/2) away from any other added point. To that purpose, a support structure which matches surface voxels and projected points is used. Therefore, instead of checking each candidate point against all other added points (quadratic complexity), only the added points linked to the surface voxels surrounding the candidate point are checked.
In the second phase, all the separately stored boundary points are traversed checking whether their origin voxels were already tagged as projected. If not, the boundary point is added to the pointshell, tagging its origin voxel as projected; otherwise, the point is rejected.
After generating pointshell points, the next step consists in computing the inwards pointing normal vector n associated to each one. This is in part motivated by the fact that normal vectors generated by CAD programs point sometimes in the wrong direction. The normal vectors are obtained analyzing the neighborhood NV of the pointshell
point Pi in the voxelmap (see (3.5)). Setting the origin in the voxel where the point is
located, all the vectors that go from this origin voxel center Ci to each of the neighbor
voxel centers Cj are weighted by their voxel value increment (vi → vj) and summed
has inner (positive) and outer (negative) layers which increase their absolute value as they get away from the surface layer. Since Pi lies within the voxel with center Ci, its
gradient is approximated with the gradient of the voxel center, i. e., ∇v(Pi) ' ∇v(Ci).
The normal vector ni of the pointshell point Pi is the normalized value of the gradient
∇v(Pi): ∇v(Pi) ' ∇v(Ci) = ∇vi = X vj∈NV(Pi) ∆vij∆Cij = X vj∈NV(Pi) (vj− vi)(Cj− Ci), n(Pi) ' n(Ci) = ni = ∇v(Pi) k∇v(Pi)k . (3.12) The computation of the gradient and the normal summarized in Section 3.12 is an- other backbone function or tool used in other steps during the enhancements of the data structures.
After all normal vectors have been computed, the pointshell P is complete. Its associated voxelmap and the support structure that matches surface voxels and projected points are destroyed. Therefore, unlike the voxelmap, such a resulting point cloud is at this stage an unstructured point soup without any topological information that relates neighboring points.
As in the case of the primitive voxelmap, the generation complexity is worst case O(n + m), with n being the number of voxels and m the number of triangles. Usual gen- eration times last about few seconds for desktop-sized objects (e. g., with s = 5 mm and around 8000 poinsthell points). However, the time required for computing a pointshell will always be longer than the one of a voxelmap alone, since a voxelized structure has to be computed prior to the point cloud. Given that the number of points strongly in- fluences the computation time during online collision queries, only smaller (desktop-size) objects are represented with pointshells, leaving voxelmaps for larger ones. Additionally, while primitive voxelmaps can represent arbitrarily complex objects (their memory foot- print being the limit), pointshells can model correctly only watertight voxelmaps. Even if an object is non-watertight, it might lead to a watertight voxelmap in case the voxel size s is bigger than the holes of the object. However, if the geometry is a thin shell, it has no inner regions (i. e., all v ≤ 0), thus, no correct inwards pointing normal vec- tors can be computed at the surface as defined in (3.12). Therefore, non-watertight thin shells cannot be modeled as pointshells, but only as voxelmaps. This issue is revisited in Chapter4.
As with the voxelmaps, pointshell data structures can be saved into files for later use; file size ranges usually from few kilobytes to few (less than ten) megabytes – ASCII
encoding is used, without compression, for human readability. Exemplary computation time, file size, and snapshots with varied resolutions are provided in [SHPH08] and in Fig- ure3.16. Finally, note that AppendixBreports relevant implementation and performance issues related to the primitive data structures introduced in this section.