add data remove after filtering

This commit is contained in:
Sébastien Loriot 2018-09-24 14:32:44 +02:00
parent add74d7a5e
commit 2ad5f03a70
20 changed files with 51892 additions and 16 deletions

View File

@ -18,7 +18,7 @@ The output is a triangle soup and can be built into a polygon surface mesh.
Given an input surface triangle mesh, %VSA leverages a discrete clustering algorithm to approximate it by a set of local simple shapes referred to as proxies. Each cluster is represented as a connected set of triangles of the input mesh, and the output mesh is constructed by generating a surface triangle mesh which approximates the clusters.
The approximation error is one-sided, defined between the clusters and their associated proxies. Two error metrics (\f$ \mathcal{L}^2 \f$, \f$ \mathcal{L}^{2,1} \f$) for planar proxies are provided via the classes `CGAL::Surface_mesh_approximation::L2_metric_plane_proxy` and `CGAL::Surface_mesh_approximation::L21_metric_plane_proxy`, and the algorithm design is generic to other user-defined metrics. The current proxies are planes or vectors, however the algorithm design is generic for future extensions to non-planar proxies \cgalCite{cgal:ywly-vmsqs-12}\cgalCite{cgal:wk-srhvs-05}. The default \f$ \mathcal{L}^{2,1} \f$ metric is recommended in terms of computation and visual perception \cgalCite{cgal:cad-vsa-04}. A brief background about <em>%Proxy</em> and <em>%ErrorMetric</em> is provided in Section \ref sma_background.
\cgalFigureBegin{Approximation_teaser, teaser.png}
\cgalFigureBegin{Approximation_teaser, teaser.jpg}
Variational shape approximation on two models with the \f$ \mathcal{L}^{2,1} \f$ error metric and planar proxies. From left to right: partition of the input surface triangle mesh, anchor vertices and edges, and output triangle mesh. The partition is optimized via discrete clustering of the input triangles, so as to minimize the approximation error from the clusters to the planar proxies (not shown).
\cgalFigureEnd
@ -44,7 +44,7 @@ Workflow of the approximation process in the free function.
Figure \cgalFigureRef{iterations} depicts several Lloyd \cgalCite{cgal:l-lsqp-82} clustering iterations on the plane-sphere model with planar proxies and the \f$ \mathcal{L}^{2,1} \f$ metric. We plot the fitting error against each iteration. After 8 iterations, the error barely changes. Based on this observation, we consider that the clustering converges if the error change between the current and previous iteration is lower than a user-specified threshold (indicated by two green dash lines).
\cgalFigureBegin{iterations, iterations.png}
\cgalFigureBegin{iterations, iterations.jpg}
Discrete Lloyd iterations on the plane-sphere model with planar proxies and the \f$ \mathcal{L}^{2,1} \f$ metric: (left) random seeding of 6 proxies; (center) after one iteration; (right) after 8 iterations, the regions settle. The red lines depict the proxy normals drawn at the seed faces.
\cgalFigureEnd
@ -69,7 +69,7 @@ and the remaining error is added to the next proxy error in order to keep the to
Figure \cgalFigureRef{seeding_method} depicts different seeding methods. Random initialization randomly selects a set of input triangle faces as proxy seeds. While it is very fast, the subsequent clustering process can be entrapped in a bad local minimum, especially on shapes with regions surrounded by sharp creases (left closeup). Incremental initialization adds the proxies one by one at the most distorted region. It can thus be slow due to the large number of interleaved relaxation iterations. Hierarchical initialization (selected by default) repeatedly doubles the number of proxies in a hierarchical refinement sequence, so as to generate clustering regions with evenly distributed fitting errors. Time consumption is typically in-between the former two. Statistics and comparisons are available in Section \ref sma_perf.
\cgalFigureBegin{seeding_method, seeding_method.png}
\cgalFigureBegin{seeding_method, seeding_method.jpg}
Different seeding methods on the sphere-cube model. From left to right: initial partition (\f$ \mathcal{L}^{2,1} \f$ metrics and 20 proxies), add 5 proxy seeds (red faces) with random, incremental and hierarchical methods respectively.
\cgalFigureEnd
@ -83,7 +83,7 @@ As depicted by Figure \cgalFigureRef{nb_proxies}, specifying a minimum error dro
To balance between performance and speed, we recommend using hierarchical seeding and specifying both stopping criteria.
\cgalFigureBegin{nb_proxies, nb_proxies.png}
\cgalFigureBegin{nb_proxies, nb_proxies.jpg}
Using different number of proxies to approximate the plane-sphere model. From left to right: 8, 14, 20 proxies. We plot right the error against the number of proxies.
\cgalFigureEnd
@ -96,7 +96,7 @@ For interactive use, the approach can yield better approximations of the geometr
- <b>Adding</b>. Adding one or more proxies to further reduce the approximation error. As for the seeding process, addition can be performed incrementally or hierarchically, as shown in Figure \cgalFigureRef{seeding_method}.
- <b>Teleporting</b>. A teleportation operator is a combination of merging and adding proxies: merging the pair of adjacent regions and adding a proxy seed to the worst region. More specifically, the pair of regions whose merging realizes the smallest error after merging and local re-fitting, is selected for merging. In practice, the teleport operation can temporarily either decrease or increase the total approximation error. We provide an optional heuristic to evaluate if the teleportation is worth it by verifying whether the error increase induced by a (simulated) deletion is smaller than half of the error of the worst region. If this test fails, no teleportation is judged necessary.
\cgalFigureBegin{operations, operations.png}
\cgalFigureBegin{operations, operations.jpg}
Operations on the sphere-cube union model. Upper row: merging (9 proxies) and the reverse bisection splitting (10 partitions) on the confined region. Lower row: one teleportation operation of merging and adding a face seed, the sphere is approximated with one more proxy.
\cgalFigureEnd
@ -124,7 +124,7 @@ Optionally, \f$ d \f$ can be measured as the ratio of the chord length:
\f[ d = d / \Vert(\mathbf{a}, \mathbf{b})\Vert. \f]
Also, we can add a dihedral angle weight \f$ sin(\mathbf{N}_i,\mathbf{N}_j) \f$ to the distance measurement, where \f$ \mathbf{N}_i,\mathbf{N}_j \f$ are the normals of the proxies separated by the chord \f$ (\mathbf{a}, \mathbf{b}) \f$. If the angle between proxy \f$ P_i \f$ and \f$ P_j \f$ is rather small, then a coarse approximation will do as it does not add geometric information on the shape. Trivial chords (less than 4 edges) are not subdivided if they are non-circular. In case of circular chords, additional anchors maybe added to maintain the topology even if they are trivial, as detailed in Section \ref sma_anchors_additional.
\cgalFigureBegin{chord, chord.png}
\cgalFigureBegin{chord, chord.jpg}
Varying the chord error. From left to right: clustering partition, and meshing with decreasing absolute chord error 5, 3 and 1 without dihedral angle weight. The boundaries of the partition (red lines) are approximated with increasing accuracy.
\cgalFigureEnd
@ -132,7 +132,7 @@ Varying the chord error. From left to right: clustering partition, and meshing w
For a boundary cycle without any anchor such as the hole depicted Figure \cgalFigureRef{operations}, we first add a starting anchor to the boundary. We then subdivide this circular chord to ensure that every boundary cycle has at least 2 anchors (i.e., every chord is connecting 2 different anchors, Figure \cgalFigureRef{anchors}). Finally, we add additional anchors to ensure that at least three anchor vertices are generated on every boundary cycle.
\cgalFigureBegin{anchors, anchors.png}
\cgalFigureBegin{anchors, anchors.jpg}
Adding anchors. From left to right: starting from a partition (grey) with a hole (while) and two encircled regions (green and blue), we add a starting anchor (orange disk) to the boundary cycle (red dash line) without any anchor (2nd), subdivide the circular chord (3rd, the number indicates the level of recursion) and add anchors to the boundary cycle with less than 2 anchors (4th, red dash lines).
\cgalFigureEnd
@ -145,7 +145,7 @@ The first image of Figure \cgalFigureRef{triangulation} depicts how the Delaunay
In a first step, we start a flooding of the interior of the region, coloring the vertices according to their closest anchor vertex. We then only flood the boundary of a region so that every vertex on it is colored depending on the closest anchor vertex. This enforces the constrained edges by forcing the boundary to be in it.
\cgalFigureBegin{triangulation, triangulation.png}
\cgalFigureBegin{triangulation, triangulation.jpg}
Discrete constrained triangulation on a sphere model. The triangulation process first floods the inner vertices (red arrows, 2nd) to simulate the Voronoi diagram. It then constructs constrained edges between anchor vertices, by flooding along the boundary edges (red arrows, 3rd). Finally, triangles (red hollow triangle, 4th) are formed by connecting the source anchors (black arrows, 4th) of the faces where 3 Voronoi cells meet (red solid triangle, 4th).
\cgalFigureEnd
@ -154,7 +154,7 @@ After each clustering region is triangulated, the final anchor positions are rec
In \cgalFigureRef{meshing}, the bear model is approximated through \f$ \mathcal{L}^{2,1} \f$ metric and the final number of proxies is determined by monitoring the error drop.
The anchor points (black) are attached to the corresponding vertex on the mesh (white). The red lines connecting the anchor points approximate the boundary of each region.
\cgalFigureBegin{meshing, meshing.png}
\cgalFigureBegin{meshing, meshing.jpg}
Meshing the bear model with decreasing target error drop.
From left to right, the target error drop are 6\%, 4\% and 2\% to the initial error respectively, the output mesh densifies. Notice the boundary subdivision in the black rectangle area.
\cgalFigureEnd
@ -205,7 +205,7 @@ The class interface `CGAL::Variational_shape_approximation` offers a flexible me
\subsection sma_example4 Customized Proxy and Error Metric
\cgalFigureBegin{vsa_metric_comparison, vsa_metric_comparison_200_30.png}
\cgalFigureBegin{vsa_metric_comparison, vsa_metric_comparison_200_30.jpg}
Comparison of different error metrics on the bear model, with 200 proxies and hierarchical seeding. From left to right: \f$ \mathcal{L}^{2,1} \f$ metric, \f$ \mathcal{L}^2 \f$ metric and custom compact metric.
\cgalFigureEnd

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- 由 Microsoft Visio, SVG Export 生成 workflow.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
width="3.826in" height="3.93434in" viewBox="0 0 275.472 283.272" xml:space="preserve" color-interpolation-filters="sRGB"
class="st12">
<style type="text/css">
<![CDATA[
.st1 {stroke:#000000;stroke-width:1}
.st2 {fill:#000000;font-family:Calibri;font-size:1.00001em;font-weight:bold}
.st3 {fill:none;stroke:#000000;stroke-width:0.75}
.st4 {font-size:1em}
.st5 {visibility:visible}
.st6 {fill:none;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22}
.st7 {fill:#5b9bd5;filter:url(#filter_2);font-family:Calibri;font-size:1.00001em;font-weight:bold;opacity:0.219608}
.st8 {fill:none;stroke:#000000;stroke-width:0.25}
.st9 {marker-end:url(#mrkr4-36);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
.st10 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.28409090909091}
.st11 {fill:none;stroke:none;stroke-width:0.25}
.st12 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
]]>
</style>
<defs id="Markers">
<g id="lend4">
<path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"/>
</g>
<marker id="mrkr4-36" class="st10" refX="-7.04" orient="auto" markerUnits="strokeWidth" overflow="visible">
<use xlink:href="#lend4" transform="scale(-3.52,-3.52) "/>
</marker>
</defs>
<defs id="Filters">
<filter id="filter_2">
<feGaussianBlur stdDeviation="2"/>
</filter>
</defs>
<g>
<title>页-1</title>
<g id="group37-1" transform="translate(27.3932,-18.75)">
<title>工作表.37</title>
<g id="shape34-2" transform="translate(-120.28,53.8701) rotate(-90) scale(-1,1)">
<title>侧边大括号</title>
<desc>seeding</desc>
<path d="M0 276.19 A7.0865 7.0865 -180 0 0 7.09 283.27 L58.46 283.27 A7.0865 7.0865 0 0 1 65.55 290.36 A7.0865 7.0865
0 0 1 72.64 283.27 L124.02 283.27 A7.0865 7.0865 -180 0 0 131.1 276.19" class="st1"/>
<text x="301.17" y="69.15" transform="rotate(-90) scale(-1,1)" class="st2">seeding</text> </g>
<g id="shape1-6" transform="translate(36.3963,-208.189)">
<title>圆角矩形</title>
<desc>start #proxies = 1</desc>
<path d="M18.79 283.27 L82.49 283.27 A18.7913 18.7913 -180 0 0 101.28 264.48 A18.7913 18.7913 -180 0 0 82.49 245.69
L18.79 245.69 A18.7913 18.7913 -180 0 0 0 264.48 A18.7913 18.7913 -180 0 0 18.79 283.27 Z" class="st3"/>
<text x="38.99" y="260.88" class="st2">start <tspan x="20.69" dy="1.2em" class="st4">#</tspan>proxies = 1</text> </g>
<g id="shape2-10" transform="translate(55.3857,-5.68434E-014)">
<title>圆角矩形.2</title>
<desc>end</desc>
<path d="M9.34 283.27 L53.96 283.27 A9.33629 9.33629 -180 0 0 63.3 273.94 A9.33629 9.33629 -180 0 0 53.96 264.6 L9.34
264.6 A9.33629 9.33629 -180 0 0 0 273.94 A9.33629 9.33629 -180 0 0 9.34 283.27 Z" class="st3"/>
<text x="22.19" y="277.54" class="st2">end</text> </g>
<g id="shape4-13" transform="translate(23.7367,-149.55)">
<title>矩形</title>
<desc>add proxy seeds #proxies += k</desc>
<g id="shadow4-14" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st5">
<rect x="0" y="245.689" width="126.596" height="37.5831" class="st6"/>
<text x="22.96" y="260.88" class="st7">add proxy seeds <tspan x="30.52" dy="1.2em" class="st4">#</tspan>proxies += k</text> </g>
<rect x="0" y="245.689" width="126.596" height="37.5831" class="st8"/>
<text x="22.96" y="260.88" class="st2">add proxy seeds <tspan x="30.52" dy="1.2em" class="st4">#</tspan>proxies += k</text> </g>
<g id="shape6-23" transform="translate(42.7261,-84.8192)">
<title>菱形</title>
<desc>stop criteria</desc>
<g id="shadow6-24" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st5">
<path d="M44.31 283.27 L88.62 268.54 L44.31 253.81 L0 268.54 L44.31 283.27 Z" class="st6"/>
<text x="14.25" y="272.14" class="st7">stop criteria</text> </g>
<path d="M44.31 283.27 L88.62 268.54 L44.31 253.81 L0 268.54 L44.31 283.27 Z" class="st8"/>
<text x="14.25" y="272.14" class="st2">stop criteria</text> </g>
<g id="shape11-31" transform="translate(79.948,-208.189)">
<title>动态连接线</title>
<path d="M7.09 283.27 L7.09 297.29" class="st9"/>
</g>
<g id="shape13-37" transform="translate(79.948,-149.55)">
<title>动态连接线.13</title>
<path d="M7.09 283.27 L7.09 311.5" class="st9"/>
</g>
<g id="shape15-42" transform="translate(79.948,-84.8192)">
<title>动态连接线.15</title>
<path d="M7.09 283.27 L7.09 299.97" class="st9"/>
</g>
<g id="shape17-47" transform="translate(42.7261,-99.5492)">
<title>动态连接线.17</title>
<path d="M0 283.27 L-29.62 283.27 L-29.62 214.48 L-26.03 214.48" class="st9"/>
</g>
<g id="shape19-52" transform="translate(68.0453,-65.5139)">
<title>工作表.19</title>
<desc>yes</desc>
<rect x="0" y="260.942" width="63.2979" height="22.3301" class="st11"/>
<text x="23.39" y="275.71" class="st2">yes</text> </g>
<g id="shape20-55" transform="translate(1.47882E-013,-83.0967)">
<title>工作表.20</title>
<desc>no</desc>
<rect x="0" y="260.942" width="56.1769" height="22.3301" class="st11"/>
<text x="21.64" y="275.71" class="st2">no</text> </g>
<g id="shape22-58" transform="translate(72.0122,-124.064)">
<title>工作表.22</title>
<desc>relaxation</desc>
<rect x="0" y="260.942" width="90.98" height="22.3301" class="st11"/>
<text x="20.18" y="275.71" class="st2">relaxation</text> </g>
<g id="shape27-61" transform="translate(30.0665,-42.4096)">
<title>矩形.27</title>
<desc>clustering iteration</desc>
<g id="shadow27-62" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st5">
<rect x="0" y="264.599" width="113.936" height="18.6729" class="st6"/>
<text x="9.57" y="277.54" class="st7">clustering iteration</text> </g>
<rect x="0" y="264.599" width="113.936" height="18.6729" class="st8"/>
<text x="9.57" y="277.54" class="st2">clustering iteration</text> </g>
<g id="shape28-69" transform="translate(79.948,-42.4096)">
<title>动态连接线.28</title>
<path d="M7.09 283.27 L7.09 299.97" class="st9"/>
</g>
<g id="shape36-74" transform="translate(-120.28,198.791) rotate(-90) scale(-1,1)">
<title>侧边大括号.36</title>
<desc>clustering</desc>
<path d="M0 276.19 A7.0865 7.0865 -180 0 0 7.09 283.27 L19.84 283.27 A7.0865 7.0865 0 0 1 26.93 290.36 A7.0865 7.0865
0 0 1 34.02 283.27 L51.02 283.27 A7.0865 7.0865 -180 0 0 58.11 276.19" class="st1"/>
<text x="295.99" y="30.53" transform="rotate(-90) scale(-1,1)" class="st2">clustering</text> </g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ int main()
{
// read input surface triangle mesh
Polyhedron input;
std::ifstream file("data/mask.off");
std::ifstream file("data/bear.off");
file >> input;
// output indexed triangle mesh

View File

@ -18,7 +18,7 @@ int main()
{
// read input surface triangle mesh
Polyhedron input;
std::ifstream file("data/mask.off");
std::ifstream file("data/bear.off");
file >> input;
// output indexed triangles
@ -46,7 +46,7 @@ int main()
if (CGAL::is_closed(mesh) && (!CGAL::Polygon_mesh_processing::is_outward_oriented(mesh)))
CGAL::Polygon_mesh_processing::reverse_face_orientations(mesh);
std::ofstream out("mask-dump.off");
std::ofstream out("dump.off");
out << mesh;
out.close();
}

View File

@ -20,7 +20,7 @@ int main()
{
// reads input surface triangle mesh
Polyhedron input;
std::ifstream file("data/mask.off");
std::ifstream file("data/bear.off");
if (!file || !(file >> input) || input.empty()) {
std::cerr << "Invalid off file." << std::endl;
return EXIT_FAILURE;

View File

@ -17,7 +17,7 @@ int main()
{
// reads input mesh
Polyhedron input;
std::ifstream file("data/mask.off");
std::ifstream file("data/bear.off");
file >> input;
Face_index_map fidx_map;

View File

@ -14,7 +14,7 @@ int main()
{
// read input surface triangle mesh
Polyhedron input;
std::ifstream file("data/mask.off");
std::ifstream file("data/bear.off");
file >> input;
// The output will be an indexed triangle mesh