mirror of https://github.com/CGAL/cgal
Merge branch 'Point_set_processing_3-Point_set_structuring-GF-old' into Point_set_processing_3-Point_set_structuring-GF
This commit is contained in:
commit
9fa12bf982
|
|
@ -192,7 +192,9 @@ The second example presents a class that enables to traverse the
|
|||
surface represented in a 2D triangulation data structure where
|
||||
the faces are connected with the facets of underlying 3D Delaunay triangulation.
|
||||
The third example shows how to get outliers and the boundaries of
|
||||
the surface.
|
||||
the surface. The last example shows how to combine this algorithm with
|
||||
two \cgal algorithms in order to reconstruct surfaces with sharp
|
||||
features.
|
||||
|
||||
\subsection AFSR_Example_function Examples for Global Function
|
||||
|
||||
|
|
@ -267,6 +269,42 @@ It returns an iterator range type \link Advancing_front_surface_reconstruction::
|
|||
|
||||
\cgalExample{Advancing_front_surface_reconstruction/boundaries.cpp}
|
||||
|
||||
\subsection AFSR_Example_sharp_features Example for Sharp Features
|
||||
|
||||
The priority queue used by the advancing front surface reconstruction
|
||||
algorithm can be modified to achieve robustness to sharp edges and
|
||||
provide piecewise-planar or hybrid reconstruction as described in
|
||||
\cgalCite{cgal:la-srpss-13}. Two other algorithms available in \cgal
|
||||
must be applied first as a preprocessing to the point set:
|
||||
|
||||
- \ref Chapter_Point_Set_Shape_Detection "Shape detection": detect planar sections of the input.
|
||||
|
||||
- \ref Point_set_processing_3Structuring "Point set structuring":
|
||||
resample the planar sections and edges and corners detected among
|
||||
them.
|
||||
|
||||
\cgalFigureBegin{figAFSRstruct,structured_example.png}
|
||||
Comparison of advancing front output.
|
||||
|
||||
- Top: input point set and raw advancing front reconstruction
|
||||
|
||||
- Bottom: structured point set and advancing front reconstruction with
|
||||
structure-dependent priority functor
|
||||
|
||||
\cgalFigureEnd
|
||||
|
||||
The quality of the reconstruction can be significantly improved thanks
|
||||
to point set structuring when dealing with shapes with sharp features,
|
||||
as shown on the previous figure. The following example shows how to
|
||||
define a priority functor that favors structurally coherent facets and
|
||||
makes the advancing front algorithm robust to sharp features.
|
||||
|
||||
|
||||
\cgalExample{Advancing_front_surface_reconstruction/reconstruction_structured.cpp}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -10,3 +10,5 @@ Triangulation_3
|
|||
Number_types
|
||||
Surface_mesh
|
||||
Polyhedron
|
||||
Point_set_shape_detection_3
|
||||
Point_set_processing_3
|
||||
|
|
@ -3,4 +3,5 @@
|
|||
\example Advancing_front_surface_reconstruction/reconstruction_class.cpp
|
||||
\example Advancing_front_surface_reconstruction/reconstruction_surface_mesh.cpp
|
||||
\example Advancing_front_surface_reconstruction/boundaries.cpp
|
||||
\example Advancing_front_surface_reconstruction/reconstruction_structured.cpp
|
||||
*/
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,185 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Point_with_normal_3.h>
|
||||
#include <CGAL/Shape_detection_3.h>
|
||||
#include <CGAL/structure_point_set.h>
|
||||
#include <CGAL/Delaunay_triangulation_3.h>
|
||||
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
#include <CGAL/IO/read_xyz_points.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef std::pair<Kernel::Point_3, Kernel::Vector_3> Point_with_normal;
|
||||
typedef std::vector<Point_with_normal> Pwn_vector;
|
||||
typedef CGAL::First_of_pair_property_map<Point_with_normal> Point_map;
|
||||
typedef CGAL::Second_of_pair_property_map<Point_with_normal> Normal_map;
|
||||
|
||||
// Efficient RANSAC types
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC_traits
|
||||
<Kernel, Pwn_vector, Point_map, Normal_map> Traits;
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC<Traits> Efficient_ransac;
|
||||
typedef CGAL::Shape_detection_3::Plane<Traits> Plane;
|
||||
|
||||
// Point set structuring type
|
||||
typedef CGAL::Point_set_with_structure<Traits> Structure;
|
||||
|
||||
// Advancing front types
|
||||
typedef CGAL::Advancing_front_surface_reconstruction_vertex_base_3<Kernel> LVb;
|
||||
typedef CGAL::Advancing_front_surface_reconstruction_cell_base_3<Kernel> LCb;
|
||||
typedef CGAL::Triangulation_data_structure_3<LVb,LCb> Tds;
|
||||
typedef CGAL::Delaunay_triangulation_3<Kernel,Tds> Triangulation_3;
|
||||
typedef Triangulation_3::Vertex_handle Vertex_handle;
|
||||
|
||||
typedef CGAL::cpp11::array<std::size_t,3> Facet;
|
||||
|
||||
|
||||
// Functor to init the advancing front algorithm with indexed points
|
||||
struct On_the_fly_pair{
|
||||
const Pwn_vector& points;
|
||||
typedef std::pair<Point, std::size_t> result_type;
|
||||
|
||||
On_the_fly_pair(const Pwn_vector& points) : points(points) {}
|
||||
|
||||
result_type
|
||||
operator()(std::size_t i) const
|
||||
{
|
||||
return result_type(points[i].first,i);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialized priority functor that favor structure coherence
|
||||
template <typename Structure>
|
||||
struct Priority_with_structure_coherence {
|
||||
|
||||
Structure& structure;
|
||||
double bound;
|
||||
|
||||
Priority_with_structure_coherence(Structure& structure,
|
||||
double bound)
|
||||
: structure (structure), bound (bound)
|
||||
{}
|
||||
|
||||
template <typename AdvancingFront, typename Cell_handle>
|
||||
double operator() (AdvancingFront& adv, Cell_handle& c,
|
||||
const int& index) const
|
||||
{
|
||||
// If perimeter > bound, return infinity so that facet is not used
|
||||
if (bound != 0)
|
||||
{
|
||||
double d = 0;
|
||||
d = sqrt(squared_distance(c->vertex((index+1)%4)->point(),
|
||||
c->vertex((index+2)%4)->point()));
|
||||
if(d>bound) return adv.infinity();
|
||||
d += sqrt(squared_distance(c->vertex((index+2)%4)->point(),
|
||||
c->vertex((index+3)%4)->point()));
|
||||
if(d>bound) return adv.infinity();
|
||||
d += sqrt(squared_distance(c->vertex((index+1)%4)->point(),
|
||||
c->vertex((index+3)%4)->point()));
|
||||
if(d>bound) return adv.infinity();
|
||||
}
|
||||
|
||||
Facet f = {{ c->vertex ((index + 1) % 4)->info (),
|
||||
c->vertex ((index + 2) % 4)->info (),
|
||||
c->vertex ((index + 3) % 4)->info () }};
|
||||
|
||||
// facet_coherence takes values between -1 and 3, 3 being the most
|
||||
// coherent and -1 being incoherent. Smaller weight means higher
|
||||
// priority.
|
||||
double weight = 100. * (5 - structure.facet_coherence (f));
|
||||
|
||||
return weight * adv.smallest_radius_delaunay_sphere (c, index);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Advancing front type
|
||||
typedef CGAL::Advancing_front_surface_reconstruction
|
||||
<Triangulation_3,
|
||||
Priority_with_structure_coherence<Structure> >
|
||||
Reconstruction;
|
||||
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
// Points with normals.
|
||||
Pwn_vector points;
|
||||
|
||||
const char* fname = (argc>1) ? argv[1] : "data/cube.pwn";
|
||||
// Loading point set from a file.
|
||||
std::ifstream stream(fname);
|
||||
|
||||
if (!stream ||
|
||||
!CGAL::read_xyz_points_and_normals(stream,
|
||||
std::back_inserter(points),
|
||||
Point_map(),
|
||||
Normal_map()))
|
||||
{
|
||||
std::cerr << "Error: cannot read file" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::cerr << "Shape detection... ";
|
||||
|
||||
Efficient_ransac ransac;
|
||||
ransac.set_input(points);
|
||||
ransac.add_shape_factory<Plane>(); // Only planes are useful for stucturing
|
||||
|
||||
// Default RANSAC parameters
|
||||
Efficient_ransac::Parameters op;
|
||||
op.probability = 0.05;
|
||||
op.min_points = 100;
|
||||
op.epsilon = (argc>2 ? boost::lexical_cast<double>(argv[2]) : 0.002);
|
||||
op.cluster_epsilon = (argc>3 ? boost::lexical_cast<double>(argv[3]) : 0.02);
|
||||
op.normal_threshold = 0.7;
|
||||
|
||||
ransac.detect(op); // Plane detection
|
||||
|
||||
std::cerr << "done\nPoint set structuring... ";
|
||||
|
||||
Pwn_vector structured_pts;
|
||||
Structure pss (points.begin (), points.end (), ransac,
|
||||
op.cluster_epsilon); // Same parameter as RANSAC
|
||||
|
||||
for (std::size_t i = 0; i < pss.size(); ++ i)
|
||||
structured_pts.push_back (pss[i]);
|
||||
|
||||
std::cerr << "done\nAdvancing front... ";
|
||||
|
||||
std::vector<std::size_t> point_indices(boost::counting_iterator<std::size_t>(0),
|
||||
boost::counting_iterator<std::size_t>(structured_pts.size()));
|
||||
|
||||
Triangulation_3 dt (boost::make_transform_iterator(point_indices.begin(), On_the_fly_pair(structured_pts)),
|
||||
boost::make_transform_iterator(point_indices.end(), On_the_fly_pair(structured_pts)));
|
||||
|
||||
|
||||
Priority_with_structure_coherence<Structure> priority (pss,
|
||||
1000. * op.cluster_epsilon); // Avoid too large facets
|
||||
Reconstruction R(dt, priority);
|
||||
R.run ();
|
||||
|
||||
std::cerr << "done\nWriting result... ";
|
||||
|
||||
std::vector<Facet> output;
|
||||
CGAL::write_triple_indices (std::back_inserter (output), R);
|
||||
|
||||
std::ofstream f ("out.off");
|
||||
f << "OFF\n" << structured_pts.size () << " " << output.size() << " 0\n"; // Header
|
||||
for (std::size_t i = 0; i < structured_pts.size (); ++ i)
|
||||
f << structured_pts[i].first << std::endl;
|
||||
for (std::size_t i = 0; i < output.size (); ++ i)
|
||||
f << "3 "
|
||||
<< output[i][0] << " "
|
||||
<< output[i][1] << " "
|
||||
<< output[i][2] << std::endl;
|
||||
std::cerr << "all done\n" << std::endl;
|
||||
|
||||
f.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -21,6 +21,8 @@
|
|||
% ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
@article{ cgal:afh-pdecm-02,
|
||||
author = "P. K. Agarwal and E. Flato and D. Halperin",
|
||||
title = "Polygon Decomposition for Efficient Construction of {Minkowski} Sums",
|
||||
|
|
@ -1060,6 +1062,15 @@ note = {\url{ttp://hal.inria.fr/inria-00090522}}
|
|||
annote = {map,generalized map},
|
||||
}
|
||||
|
||||
@INPROCEEDINGS{cgal:la-srpss-13,
|
||||
author = {Lafarge, Florent and Alliez, Pierre},
|
||||
title = {Surface reconstruction through point set structuring},
|
||||
booktitle = {Proc. of Eurographics},
|
||||
year = {2013},
|
||||
address = {Girona, Spain}
|
||||
}
|
||||
|
||||
|
||||
@inproceedings{ cgal:lt-fmeps-98,
|
||||
author = "Peter Lindstrom and Greg Turk",
|
||||
title = "Fast and memory efficient polygonal simplification",
|
||||
|
|
|
|||
|
|
@ -184,6 +184,9 @@ and <code>src/</code> directories).
|
|||
<li>New function <code>CGAL::read_ply_custom_points()</code> that
|
||||
allows the user to read any additional point attribute from a PLY
|
||||
input point set.</li>
|
||||
<li> <code>CGAL::structure_point_set()</code>: new algorithm that
|
||||
takes advantage of detected planes to produce a structured point
|
||||
set (with flat regions, sharp edges and vertices).</li>
|
||||
</ul>
|
||||
<h3>Point Set Shape Detection</h3>
|
||||
<ul>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
- `CGAL::compute_vcm()`
|
||||
- `CGAL::vcm_estimate_normals()`
|
||||
- `CGAL::vcm_is_on_feature_edge()`
|
||||
- `CGAL::structure_point_set()`
|
||||
- `CGAL::write_off_points()`
|
||||
- `CGAL::write_ply_points()`
|
||||
- `CGAL::write_xyz_points()`
|
||||
|
|
|
|||
|
|
@ -408,6 +408,60 @@ points that are on sharp edges:
|
|||
\cgalExample{Point_set_processing_3/edges_example.cpp}
|
||||
|
||||
|
||||
\section Point_set_processing_3Structuring Structuring
|
||||
|
||||
The function `structure_point_set()` generates a structured version of the
|
||||
input point set. It requires that a shape detection algorithm is first applied
|
||||
to the point set (see \ref Chapter_Point_Set_Shape_Detection). It is based on
|
||||
the article \cgalCite{cgal:la-srpss-13}.
|
||||
|
||||
- __Planes__: inliers of each detected plane are replaced by sets of
|
||||
noise-free points sampled at the vertices of a regular grid: this is
|
||||
achieved by filling an occupancy grid aligned on the principal
|
||||
components of the inlier sets with a spacing lower than \f$\sqrt{2}\f$
|
||||
times the user-defined tolerance.
|
||||
|
||||
- __Creases__: adjacencies between 2 planes are detected and regularly
|
||||
resampled on an occupancy array along the edge with a spacing equal to
|
||||
twice the user-defined tolerance.
|
||||
|
||||
- __Corners__: 3-cycles are detected from the primitive adjacency
|
||||
graph and sampled using the exact intersection point of the 3 planes
|
||||
(provided it exists and remains in the given tolerance). These corners
|
||||
are also locally clustered to former corners of degree higher than 3.
|
||||
|
||||
|
||||
This algorithm is well suited to point sets sampled on surfaces with
|
||||
planar sections and sharp edges.
|
||||
|
||||
\cgalFigureBegin{Point_set_processing_3figstructuring,structuring.png}
|
||||
Point set structuring. Left: input raw point set. Right: structured point set.
|
||||
\cgalFigureEnd
|
||||
|
||||
Structure information of points can be used to perform feature
|
||||
preserving reconstruction (see
|
||||
\ref AFSR_Example_sharp_features "Advancing Front Surface Reconstruction"
|
||||
for example). More specifically, the class storing a point set with
|
||||
structure provides the user with a method
|
||||
`Point_set_with_structure::facet_coherence()` that estimates if a
|
||||
triplet of points form a coherent facet.
|
||||
|
||||
\cgalFigureBegin{Point_set_processing_3figstructuring, structuring_coherence.png}
|
||||
(a) Input point set (and structured output); (b) output with many
|
||||
incoherent facets; (c) output with all facets coherent. i, j and k
|
||||
each corresponds to a primitive index.
|
||||
\cgalFigureEnd
|
||||
|
||||
|
||||
|
||||
\subsection Point_set_processing_3Example_9 Example
|
||||
|
||||
The following example applies shape detection followed by structuring to a
|
||||
point set:
|
||||
\cgalExample{Point_set_processing_3/structuring_example.cpp}
|
||||
|
||||
|
||||
|
||||
\section Point_set_processing_3ImplementationHistory Implementation History
|
||||
|
||||
Pierre Alliez and Laurent Saboret contributed the initial component. Nader Salman contributed the grid simplification.
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ Bounding_volumes
|
|||
Principal_component_analysis
|
||||
Jet_fitting_3
|
||||
Solver_interface
|
||||
|
||||
Point_set_shape_detection_3
|
||||
Advancing_front_surface_reconstruction
|
||||
|
|
|
|||
|
|
@ -12,4 +12,5 @@
|
|||
\example Point_set_processing_3/bilateral_smooth_point_set_example.cpp
|
||||
\example Point_set_processing_3/edge_aware_upsample_point_set_example.cpp
|
||||
\example Point_set_processing_3/edges_example.cpp
|
||||
\example Point_set_processing_3/structuring_example.cpp
|
||||
*/
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
|
|
@ -55,6 +55,7 @@ if ( CGAL_FOUND )
|
|||
create_single_source_cgal_program( "remove_outliers_example.cpp" )
|
||||
create_single_source_cgal_program( "wlop_simplify_and_regularize_point_set_example.cpp" )
|
||||
create_single_source_cgal_program( "edge_aware_upsample_point_set_example.cpp" )
|
||||
create_single_source_cgal_program( "structuring_example.cpp" )
|
||||
|
||||
# Use Eigen or BLAS and LAPACK (optional)
|
||||
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,70 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/IO/read_xyz_points.h>
|
||||
#include <CGAL/IO/write_xyz_points.h>
|
||||
#include <CGAL/Point_with_normal_3.h>
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <CGAL/Shape_detection_3.h>
|
||||
|
||||
#include <CGAL/structure_point_set.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
// Type declarations
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef std::pair<Kernel::Point_3, Kernel::Vector_3> Point_with_normal;
|
||||
typedef std::vector<Point_with_normal> Pwn_vector;
|
||||
typedef CGAL::First_of_pair_property_map<Point_with_normal> Point_map;
|
||||
typedef CGAL::Second_of_pair_property_map<Point_with_normal> Normal_map;
|
||||
|
||||
// Efficient RANSAC types
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC_traits
|
||||
<Kernel, Pwn_vector, Point_map, Normal_map> Traits;
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC<Traits> Efficient_ransac;
|
||||
typedef CGAL::Shape_detection_3::Plane<Traits> Plane;
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
// Points with normals.
|
||||
Pwn_vector points;
|
||||
|
||||
// Loading point set from a file.
|
||||
std::ifstream stream(argc>1 ? argv[1] : "data/cube.pwn");
|
||||
|
||||
if (!stream ||
|
||||
!CGAL::read_xyz_points_and_normals(stream,
|
||||
std::back_inserter(points),
|
||||
Point_map(),
|
||||
Normal_map()))
|
||||
{
|
||||
std::cerr << "Error: cannot read file cube.pwn" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::cerr << points.size() << " point(s) read." << std::endl;
|
||||
|
||||
// Shape detection
|
||||
Efficient_ransac ransac;
|
||||
ransac.set_input(points);
|
||||
ransac.add_shape_factory<Plane>();
|
||||
ransac.detect();
|
||||
|
||||
Pwn_vector structured_pts;
|
||||
|
||||
CGAL::structure_point_set (points.begin (), points.end (), // input points
|
||||
std::back_inserter (structured_pts),
|
||||
ransac, // shape detection engine
|
||||
0.015); // epsilon for structuring points
|
||||
|
||||
std::cerr << structured_pts.size ()
|
||||
<< " structured point(s) generated." << std::endl;
|
||||
|
||||
std::ofstream out ("out.pwn");
|
||||
CGAL::write_xyz_points_and_normals (out, structured_pts.begin(), structured_pts.end(),
|
||||
Point_map(), Normal_map());
|
||||
out.close();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -43,6 +43,7 @@ if ( CGAL_FOUND )
|
|||
create_single_source_cgal_program( "wlop_simplify_and_regularize_test.cpp" )
|
||||
create_single_source_cgal_program( "bilateral_smoothing_test.cpp" )
|
||||
create_single_source_cgal_program( "edge_aware_upsample_test.cpp" )
|
||||
create_single_source_cgal_program( "structuring_test.cpp" )
|
||||
|
||||
# Use Eigen or BLAS and LAPACK (optional)
|
||||
find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Point_with_normal_3.h>
|
||||
#include <CGAL/property_map.h>
|
||||
|
||||
#include <CGAL/Shape_detection_3.h>
|
||||
#include <CGAL/structure_point_set.h>
|
||||
|
||||
#include <CGAL/Random.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef Kernel::Vector_3 Vector;
|
||||
typedef Kernel::Plane_3 Plane;
|
||||
typedef std::pair<Point, Vector> Point_with_normal;
|
||||
typedef std::vector<Point_with_normal> Pwn_vector;
|
||||
typedef CGAL::First_of_pair_property_map<Point_with_normal> Point_map;
|
||||
typedef CGAL::Second_of_pair_property_map<Point_with_normal> Normal_map;
|
||||
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC_traits
|
||||
<Kernel, Pwn_vector, Point_map, Normal_map> Traits;
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC<Traits> Efficient_ransac;
|
||||
|
||||
typedef CGAL::Point_set_with_structure<Traits> Points_with_structure;
|
||||
|
||||
template <typename OutputIterator>
|
||||
void generate_random_points (const Point& origin, const Vector& base1, const Vector& base2,
|
||||
std::size_t nb_pts, OutputIterator output)
|
||||
{
|
||||
Vector normal = CGAL::cross_product (base1, base2);
|
||||
normal = normal / std::sqrt (normal * normal);
|
||||
|
||||
for (std::size_t i = 0; i < nb_pts; ++ i)
|
||||
{
|
||||
Point point = origin
|
||||
+ CGAL::get_default_random().get_double() * base1
|
||||
+ CGAL::get_default_random().get_double() * base2;
|
||||
|
||||
*(output ++) = std::make_pair (point, normal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Vector vx (1., 0., 0.),
|
||||
vy (0., 1., 0.),
|
||||
vz (0., 0., 1.);
|
||||
|
||||
Efficient_ransac ransac;
|
||||
ransac.add_shape_factory<CGAL::Shape_detection_3::Plane<Traits> >();
|
||||
|
||||
const std::size_t nb_pts = 1000;
|
||||
|
||||
Efficient_ransac::Parameters op;
|
||||
op.probability = 0.05;
|
||||
op.min_points = nb_pts / 2;
|
||||
op.epsilon = 0.02;
|
||||
op.cluster_epsilon = 0.05;
|
||||
op.normal_threshold = 0.8;
|
||||
|
||||
Pwn_vector points;
|
||||
|
||||
generate_random_points (Point (0., 0., 0.), vx, vy,
|
||||
5000, std::back_inserter (points));
|
||||
generate_random_points (Point (0., 0., 0.), vx, vz,
|
||||
5000, std::back_inserter (points));
|
||||
generate_random_points (Point (0., 0., 0.), vy, vz,
|
||||
5000, std::back_inserter (points));
|
||||
generate_random_points (Point (0., 0., 1.), vx, vy,
|
||||
5000, std::back_inserter (points));
|
||||
generate_random_points (Point (0., 1., 0.), vx, vz,
|
||||
5000, std::back_inserter (points));
|
||||
generate_random_points (Point (1., 0., 0.), vy, vz,
|
||||
5000, std::back_inserter (points));
|
||||
|
||||
|
||||
ransac.set_input(points);
|
||||
ransac.detect(op);
|
||||
|
||||
Points_with_structure pss (points.begin(), points.end(), ransac, op.cluster_epsilon);
|
||||
|
||||
std::vector<Point> vertices;
|
||||
|
||||
for (std::size_t i = 0; i < pss.size(); ++ i)
|
||||
if (pss.adjacency (i).size () == 3)
|
||||
vertices.push_back (pss.point (i));
|
||||
|
||||
if (vertices.size () != 8)
|
||||
{
|
||||
std::cerr << "Error: 8 point should have been structural vertices." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::vector<Point> ground_truth;
|
||||
ground_truth.push_back (Point (0., 0., 0.));
|
||||
ground_truth.push_back (Point (0., 0., 1.));
|
||||
ground_truth.push_back (Point (0., 1., 0.));
|
||||
ground_truth.push_back (Point (0., 1., 1.));
|
||||
ground_truth.push_back (Point (1., 0., 0.));
|
||||
ground_truth.push_back (Point (1., 0., 1.));
|
||||
ground_truth.push_back (Point (1., 1., 0.));
|
||||
ground_truth.push_back (Point (1., 1., 1.));
|
||||
std::vector<bool> found (ground_truth.size(), false);
|
||||
std::size_t nb_found = 0;
|
||||
|
||||
for (std::size_t i = 0; i < vertices.size(); ++ i)
|
||||
for (std::size_t j = 0; j < ground_truth.size(); ++ j)
|
||||
{
|
||||
if (found[j])
|
||||
continue;
|
||||
|
||||
if (CGAL::squared_distance (ground_truth[j], vertices[i]) < 1e-6)
|
||||
{
|
||||
found[j] = true;
|
||||
++ nb_found;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nb_found != ground_truth.size())
|
||||
{
|
||||
std::cerr << "Error: the following vert(ex/ices) was/were not found:" << std::endl;
|
||||
for (std::size_t i = 0; i < ground_truth.size(); ++ i)
|
||||
if (!(found[i]))
|
||||
std::cerr << " * " << ground_truth[i] << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -46,6 +46,8 @@ namespace CGAL {
|
|||
class InputPointMap,
|
||||
class InputNormalMap>
|
||||
struct Efficient_RANSAC_traits {
|
||||
///
|
||||
typedef Gt Base_kernel;
|
||||
///
|
||||
typedef typename Gt::FT FT;
|
||||
///
|
||||
|
|
@ -55,8 +57,12 @@ namespace CGAL {
|
|||
///
|
||||
typedef typename Gt::Sphere_3 Sphere_3;
|
||||
///
|
||||
typedef typename Gt::Segment_3 Segment_3;
|
||||
///
|
||||
typedef typename Gt::Line_3 Line_3;
|
||||
///
|
||||
typedef typename Gt::Line_2 Line_2;
|
||||
///
|
||||
typedef typename Gt::Circle_2 Circle_2;
|
||||
///
|
||||
typedef typename Gt::Plane_3 Plane_3;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,16 @@ namespace CGAL {
|
|||
m_normal = this->cross_pdct(
|
||||
this->constr_vec(p2, p1), this->constr_vec(p3, p1));
|
||||
|
||||
// Check if normal orientation is consistent
|
||||
std::size_t nb_correct = 0,
|
||||
nb_total = (indices.size () > 100) ? 100 : indices.size ();
|
||||
for (std::size_t i = 0; i < nb_total; ++ i)
|
||||
if (this->normal (indices[i]) * m_normal > 0)
|
||||
++ nb_correct;
|
||||
if (nb_correct < nb_total / 2)
|
||||
m_normal = -m_normal;
|
||||
|
||||
|
||||
FT length = CGAL::sqrt(this->sqlen(m_normal));
|
||||
|
||||
// Are the points almost singular?
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
#include "Scene_points_with_normal_item.h"
|
||||
#include "Scene_polygon_soup_item.h"
|
||||
#include "Scene_polyhedron_item.h"
|
||||
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
#include <CGAL/Three/Scene_group_item.h>
|
||||
|
||||
#include <CGAL/Random.h>
|
||||
|
||||
|
|
@ -12,6 +14,8 @@
|
|||
#include <CGAL/Delaunay_triangulation_2.h>
|
||||
#include <CGAL/Alpha_shape_2.h>
|
||||
|
||||
#include <CGAL/structure_point_set.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
|
|
@ -20,9 +24,25 @@
|
|||
#include <QMessageBox>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/function_output_iterator.hpp>
|
||||
|
||||
#include "ui_Point_set_shape_detection_plugin.h"
|
||||
|
||||
|
||||
struct build_from_pair
|
||||
{
|
||||
Point_set& m_pts;
|
||||
|
||||
build_from_pair (Point_set& pts) : m_pts (pts) { }
|
||||
|
||||
void operator() (const std::pair<Point_set::Point, Point_set::Vector>& pair)
|
||||
{
|
||||
m_pts.push_back (Point_set::Point_with_normal (pair.first, pair.second));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic_kernel;
|
||||
typedef Epic_kernel::Point_3 Point;
|
||||
//typedef CGAL::Point_with_normal_3<Epic_kernel> Point_with_normal;
|
||||
|
|
@ -101,6 +121,7 @@ public:
|
|||
bool generate_alpha() const { return m_generate_alpha->isChecked(); }
|
||||
bool generate_subset() const { return !(m_do_not_generate_subset->isChecked()); }
|
||||
bool regularize() const { return m_regularize->isChecked(); }
|
||||
bool generate_structured() const { return m_generate_structured->isChecked(); }
|
||||
};
|
||||
|
||||
void Polyhedron_demo_point_set_shape_detection_plugin::on_actionDetect_triggered() {
|
||||
|
|
@ -128,7 +149,13 @@ void Polyhedron_demo_point_set_shape_detection_plugin::on_actionDetect_triggered
|
|||
Point_set_demo_point_set_shape_detection_dialog dialog;
|
||||
if(!dialog.exec())
|
||||
return;
|
||||
|
||||
|
||||
scene->setSelectedItem(-1);
|
||||
Scene_group_item *subsets_item = new Scene_group_item(QString("%1 (RANSAC subsets)").arg(item->name()));
|
||||
subsets_item->setExpanded(false);
|
||||
Scene_group_item *planes_item = new Scene_group_item(QString("%1 (RANSAC planes)").arg(item->name()));
|
||||
planes_item->setExpanded(false);
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
|
||||
|
|
@ -241,7 +268,9 @@ void Polyhedron_demo_point_set_shape_detection_plugin::on_actionDetect_triggered
|
|||
poly_item->setName(QString("%1%2_alpha_shape").arg(QString::fromStdString(ss.str()))
|
||||
.arg (QString::number (shape->indices_of_assigned_points().size())));
|
||||
poly_item->setRenderingMode (Flat);
|
||||
|
||||
scene->addItem(poly_item);
|
||||
scene->changeGroup(poly_item, planes_item);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<CGAL::Shape_detection_3::Cone<Traits> *>(shape.get()))
|
||||
|
|
@ -259,13 +288,50 @@ void Polyhedron_demo_point_set_shape_detection_plugin::on_actionDetect_triggered
|
|||
point_item->set_has_normals(true);
|
||||
point_item->setRenderingMode(item->renderingMode());
|
||||
if (dialog.generate_subset())
|
||||
scene->addItem(point_item);
|
||||
{
|
||||
scene->addItem(point_item);
|
||||
scene->changeGroup(point_item, subsets_item);
|
||||
}
|
||||
else
|
||||
delete point_item;
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
if (dialog.generate_subset())
|
||||
scene->addItem(subsets_item);
|
||||
else
|
||||
delete subsets_item;
|
||||
|
||||
if (dialog.generate_alpha())
|
||||
scene->addItem(planes_item);
|
||||
else
|
||||
delete planes_item;
|
||||
|
||||
if (dialog.generate_structured ())
|
||||
{
|
||||
std::cout << "Structuring point set... ";
|
||||
|
||||
Scene_points_with_normal_item *pts_full = new Scene_points_with_normal_item;
|
||||
CGAL::structure_point_set (points->begin (), points->end (),
|
||||
boost::make_function_output_iterator (build_from_pair ((*(pts_full->point_set())))),
|
||||
shape_detection,
|
||||
op.cluster_epsilon);
|
||||
if (pts_full->point_set ()->empty ())
|
||||
delete pts_full;
|
||||
else
|
||||
{
|
||||
pts_full->point_set ()->unselect_all();
|
||||
pts_full->setName(tr("%1 (structured)").arg(item->name()));
|
||||
pts_full->set_has_normals(true);
|
||||
pts_full->setRenderingMode(PointsPlusNormals);
|
||||
pts_full->setColor(Qt::blue);
|
||||
scene->addItem (pts_full);
|
||||
}
|
||||
std::cerr << "done" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// Updates scene
|
||||
scene->itemChanged(index);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>369</width>
|
||||
<height>317</height>
|
||||
<width>444</width>
|
||||
<height>347</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
<string>Cylinder</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -158,7 +158,7 @@
|
|||
<number>2</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
|
|
@ -217,7 +217,14 @@
|
|||
<string>Regularize planes</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_generate_structured">
|
||||
<property name="text">
|
||||
<string>Generate structured point cloud</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include <CGAL/mst_orient_normals.h>
|
||||
#include <CGAL/Scale_space_surface_reconstruction_3.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction.h>
|
||||
#include <CGAL/Shape_detection_3.h>
|
||||
#include <CGAL/structure_point_set.h>
|
||||
|
||||
#include "ui_Surface_reconstruction_plugin.h"
|
||||
|
||||
|
|
@ -38,6 +40,18 @@ typedef CGAL::Parallel_tag Concurrency_tag;
|
|||
typedef CGAL::Sequential_tag Concurrency_tag;
|
||||
#endif
|
||||
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef Kernel::Vector_3 Vector;
|
||||
// types for K nearest neighbors search
|
||||
typedef CGAL::Search_traits_3<Kernel> Tree_traits;
|
||||
typedef CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
||||
typedef Neighbor_search::Tree Tree;
|
||||
typedef Neighbor_search::iterator Search_iterator;
|
||||
|
||||
typedef CGAL::Scale_space_surface_reconstruction_3<Kernel> ScaleSpace;
|
||||
typedef CGAL::cpp11::array<std::size_t,3> Facet;
|
||||
|
||||
|
||||
|
||||
// Poisson reconstruction method:
|
||||
// Reconstructs a surface mesh from a point set and returns it as a polyhedron.
|
||||
|
|
@ -84,21 +98,68 @@ struct Radius {
|
|||
// delaunay sphere
|
||||
return adv.smallest_radius_delaunay_sphere (c, index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Structuring>
|
||||
struct Priority_with_structure_coherence {
|
||||
|
||||
Structuring& structuring;
|
||||
double bound;
|
||||
|
||||
Priority_with_structure_coherence(Structuring& structuring,
|
||||
double bound)
|
||||
: structuring (structuring), bound (bound)
|
||||
{}
|
||||
|
||||
template <typename AdvancingFront, typename Cell_handle>
|
||||
double operator() (AdvancingFront& adv, Cell_handle& c,
|
||||
const int& index) const
|
||||
{
|
||||
// If perimeter > bound, return infinity so that facet is not used
|
||||
if (bound != 0)
|
||||
{
|
||||
double d = 0;
|
||||
d = sqrt(squared_distance(c->vertex((index+1)%4)->point(),
|
||||
c->vertex((index+2)%4)->point()));
|
||||
if(d>bound) return adv.infinity();
|
||||
d += sqrt(squared_distance(c->vertex((index+2)%4)->point(),
|
||||
c->vertex((index+3)%4)->point()));
|
||||
if(d>bound) return adv.infinity();
|
||||
d += sqrt(squared_distance(c->vertex((index+1)%4)->point(),
|
||||
c->vertex((index+3)%4)->point()));
|
||||
if(d>bound) return adv.infinity();
|
||||
}
|
||||
|
||||
Facet f = {{ c->vertex ((index + 1) % 4)->info (),
|
||||
c->vertex ((index + 2) % 4)->info (),
|
||||
c->vertex ((index + 3) % 4)->info () }};
|
||||
|
||||
double weight = 100. * (5 - structuring.facet_coherence (f));
|
||||
|
||||
return weight * adv.smallest_radius_delaunay_sphere (c, index);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct On_the_fly_pair{
|
||||
const Point_set& points;
|
||||
typedef std::pair<Point, std::size_t> result_type;
|
||||
|
||||
On_the_fly_pair(const Point_set& points) : points(points) {}
|
||||
|
||||
result_type
|
||||
operator()(std::size_t i) const
|
||||
{
|
||||
return result_type(points[i].position(),i);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
namespace SurfaceReconstruction
|
||||
{
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef Kernel::Vector_3 Vector;
|
||||
// types for K nearest neighbors search
|
||||
typedef CGAL::Search_traits_3<Kernel> Tree_traits;
|
||||
typedef CGAL::Orthogonal_k_neighbor_search<Tree_traits> Neighbor_search;
|
||||
typedef Neighbor_search::Tree Tree;
|
||||
typedef Neighbor_search::iterator Search_iterator;
|
||||
|
||||
typedef CGAL::Scale_space_surface_reconstruction_3<Kernel> ScaleSpace;
|
||||
|
||||
template <typename OutputIterator>
|
||||
void generate_scales (OutputIterator out,
|
||||
|
|
@ -410,6 +471,19 @@ namespace SurfaceReconstruction
|
|||
points.end ());
|
||||
}
|
||||
|
||||
struct build_from_pair
|
||||
{
|
||||
Point_set& m_pts;
|
||||
|
||||
build_from_pair (Point_set& pts) : m_pts (pts) { }
|
||||
|
||||
void operator() (const std::pair<Point_set::Point, Point_set::Vector>& pair)
|
||||
{
|
||||
m_pts.push_back (Point_set::Point_with_normal (pair.first, pair.second));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -434,6 +508,7 @@ public:
|
|||
if (buttonAdvancing->isChecked ()) return 1;
|
||||
if (buttonScaleSpace->isChecked ()) return 2;
|
||||
if (buttonPoisson->isChecked ()) return 3;
|
||||
if (buttonRANSAC->isChecked ()) return 4;
|
||||
return -1;
|
||||
}
|
||||
bool boundaries () const { return m_boundaries->isChecked (); }
|
||||
|
|
@ -452,7 +527,12 @@ public:
|
|||
double distance () const { return m_inputDistance->value (); }
|
||||
bool two_passes () const { return m_inputTwoPasses->isChecked (); }
|
||||
bool do_not_fill_holes () const { return m_doNotFillHoles->isChecked (); }
|
||||
double connectivity_tolerance () const { return m_connectivityTolerance->value (); }
|
||||
double noise_tolerance () const { return m_noiseTolerance->value (); }
|
||||
unsigned int min_size_subset () const { return m_minSizeSubset->value (); }
|
||||
bool generate_structured () const { return m_generateStructured->isChecked (); }
|
||||
QString solver () const { return m_inputSolver->currentText (); }
|
||||
|
||||
};
|
||||
|
||||
#include <CGAL/Scale_space_surface_reconstruction_3.h>
|
||||
|
|
@ -480,6 +560,7 @@ public:
|
|||
void advancing_front_reconstruction (const Polyhedron_demo_surface_reconstruction_plugin_dialog& dialog);
|
||||
void scale_space_reconstruction (const Polyhedron_demo_surface_reconstruction_plugin_dialog& dialog);
|
||||
void poisson_reconstruction (const Polyhedron_demo_surface_reconstruction_plugin_dialog& dialog);
|
||||
void ransac_reconstruction (const Polyhedron_demo_surface_reconstruction_plugin_dialog& dialog);
|
||||
|
||||
//! Applicate for Point_sets with normals.
|
||||
bool applicable(QAction*) const {
|
||||
|
|
@ -525,6 +606,9 @@ void Polyhedron_demo_surface_reconstruction_plugin::on_actionSurfaceReconstructi
|
|||
case 3:
|
||||
poisson_reconstruction (dialog);
|
||||
break;
|
||||
case 4:
|
||||
ransac_reconstruction (dialog);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Error: unkown method." << std::endl;
|
||||
return;
|
||||
|
|
@ -870,5 +954,138 @@ void Polyhedron_demo_surface_reconstruction_plugin::poisson_reconstruction
|
|||
}
|
||||
}
|
||||
|
||||
void Polyhedron_demo_surface_reconstruction_plugin::ransac_reconstruction
|
||||
(const Polyhedron_demo_surface_reconstruction_plugin_dialog& dialog)
|
||||
{
|
||||
CGAL::Random rand(time(0));
|
||||
|
||||
const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
||||
Scene_points_with_normal_item* point_set_item =
|
||||
qobject_cast<Scene_points_with_normal_item*>(scene->item(index));
|
||||
|
||||
if(point_set_item)
|
||||
{
|
||||
// Gets point set
|
||||
Point_set* points = point_set_item->point_set();
|
||||
if(!points) return;
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
CGAL::Timer global_timer;
|
||||
global_timer.start();
|
||||
|
||||
CGAL::Timer local_timer;
|
||||
|
||||
if (!(point_set_item->has_normals()))
|
||||
{
|
||||
local_timer.start();
|
||||
|
||||
std::cerr << "Estimation of normal vectors... ";
|
||||
|
||||
CGAL::jet_estimate_normals<Concurrency_tag>(points->begin(), points->end(),
|
||||
CGAL::make_normal_of_point_with_normal_pmap(Point_set::value_type()),
|
||||
12);
|
||||
local_timer.stop();
|
||||
point_set_item->set_has_normals (true);
|
||||
point_set_item->setRenderingMode(PointsPlusNormals);
|
||||
|
||||
std::cerr << "done in " << local_timer.time() << " second(s)" << std::endl;
|
||||
local_timer.reset();
|
||||
}
|
||||
|
||||
typedef CGAL::Identity_property_map<Point_set::Point_with_normal> PointPMap;
|
||||
typedef CGAL::Normal_of_point_with_normal_pmap<Point_set::Geom_traits> NormalPMap;
|
||||
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC_traits<Kernel, Point_set, PointPMap, NormalPMap> Traits;
|
||||
typedef CGAL::Shape_detection_3::Efficient_RANSAC<Traits> Shape_detection;
|
||||
|
||||
local_timer.start();
|
||||
Shape_detection shape_detection;
|
||||
shape_detection.set_input(*points);
|
||||
|
||||
shape_detection.add_shape_factory<CGAL::Shape_detection_3::Plane<Traits> >();
|
||||
|
||||
Shape_detection::Parameters op;
|
||||
op.probability = 0.05;
|
||||
op.min_points = dialog.min_size_subset();
|
||||
op.epsilon = dialog.noise_tolerance();
|
||||
op.cluster_epsilon = dialog.connectivity_tolerance();
|
||||
op.normal_threshold = 0.7;
|
||||
|
||||
shape_detection.detect(op);
|
||||
local_timer.stop();
|
||||
std::cout << shape_detection.shapes().size() << " plane(s) found in "
|
||||
<< local_timer.time() << " second(s)" << std::endl;
|
||||
local_timer.reset();
|
||||
|
||||
std::cout << "Structuring point set... " << std::endl;
|
||||
typedef CGAL::Point_set_with_structure<Traits> Structuring;
|
||||
|
||||
local_timer.start();
|
||||
Structuring structuring (points->begin (), points->end (),
|
||||
shape_detection,
|
||||
op.cluster_epsilon);
|
||||
|
||||
Scene_points_with_normal_item *structured = new Scene_points_with_normal_item;
|
||||
for (std::size_t i = 0; i < structuring.size(); ++ i)
|
||||
structured->point_set()->push_back (Point_set::Point_with_normal (structuring.point(i),
|
||||
structuring.normal(i)));
|
||||
|
||||
local_timer.stop ();
|
||||
std::cerr << structured->point_set()->size() << " point(s) generated in "
|
||||
<< local_timer.time() << std::endl;
|
||||
local_timer.reset();
|
||||
typedef CGAL::Advancing_front_surface_reconstruction_vertex_base_3<Kernel> LVb;
|
||||
typedef CGAL::Advancing_front_surface_reconstruction_cell_base_3<Kernel> LCb;
|
||||
|
||||
typedef CGAL::Triangulation_data_structure_3<LVb,LCb> Tds;
|
||||
typedef CGAL::Delaunay_triangulation_3<Kernel,Tds> Triangulation_3;
|
||||
|
||||
typedef CGAL::Advancing_front_surface_reconstruction<Triangulation_3,
|
||||
Priority_with_structure_coherence<Structuring> > Reconstruction;
|
||||
|
||||
std::cerr << "Reconstructing... ";
|
||||
local_timer.start();
|
||||
std::vector<std::size_t> point_indices(boost::counting_iterator<std::size_t>(0),
|
||||
boost::counting_iterator<std::size_t>(structured->point_set()->size()));
|
||||
|
||||
Triangulation_3 dt (boost::make_transform_iterator(point_indices.begin(), On_the_fly_pair(*(structured->point_set()))),
|
||||
boost::make_transform_iterator(point_indices.end(), On_the_fly_pair(*(structured->point_set()))));
|
||||
|
||||
|
||||
Priority_with_structure_coherence<Structuring> priority (structuring, 10. * op.cluster_epsilon);
|
||||
Reconstruction R(dt, priority);
|
||||
|
||||
R.run (5., 0.52);
|
||||
|
||||
Scene_polyhedron_item* reco_item = new Scene_polyhedron_item(Polyhedron());
|
||||
Polyhedron& P = * const_cast<Polyhedron*>(reco_item->polyhedron());
|
||||
CGAL::AFSR::construct_polyhedron(P, R);
|
||||
local_timer.stop();
|
||||
std::cerr << "done in " << local_timer.time() << " second(s)" << std::endl;
|
||||
|
||||
if (dialog.generate_structured ())
|
||||
{
|
||||
structured->setName(tr("%1 (structured)").arg(point_set_item->name()));
|
||||
structured->set_has_normals(true);
|
||||
structured->setRenderingMode(PointsPlusNormals);
|
||||
structured->setColor(Qt::blue);
|
||||
scene->addItem (structured);
|
||||
}
|
||||
else
|
||||
delete structured;
|
||||
|
||||
reco_item->setName(tr("%1 (RANSAC-based reconstruction)").arg(scene->item(index)->name()));
|
||||
reco_item->setColor(Qt::magenta);
|
||||
reco_item->setRenderingMode(FlatPlusEdges);
|
||||
scene->addItem(reco_item);
|
||||
|
||||
std::cerr << "All done in " << global_timer.time() << " seconds." << std::endl;
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "Surface_reconstruction_plugin.moc"
|
||||
|
|
|
|||
|
|
@ -6,391 +6,536 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>423</width>
|
||||
<height>723</height>
|
||||
<width>787</width>
|
||||
<height>566</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Surface Reconstruction</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="5" column="0">
|
||||
<widget class="QFrame" name="frameScaleSpace">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Average Neighborhood Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="m_neighbors">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Size of Sample to Estimate Neighborhood</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="m_samples">
|
||||
<property name="maximum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>200</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Iterations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="m_iterations">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="m_genShells">
|
||||
<property name="text">
|
||||
<string>Generate separate shells</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="m_forceManifold">
|
||||
<property name="text">
|
||||
<string>Force manifold output</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="m_genSmooth">
|
||||
<property name="text">
|
||||
<string>Smoothed version</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="buttonAuto">
|
||||
<property name="text">
|
||||
<string>Select method and parameters automatically</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameAuto">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_boundaries">
|
||||
<property name="text">
|
||||
<string>Output surface has boundaries</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_interpolate">
|
||||
<property name="text">
|
||||
<string>Output surface must pass exactly through input points</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="buttonScaleSpace">
|
||||
<property name="text">
|
||||
<string>Scale space reconstruction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameScaleSpace">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Average neighborhood size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="m_neighbors">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Size of sample to estimate neighborhood</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="m_samples">
|
||||
<property name="maximum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>200</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Iterations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="m_iterations">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="m_genShells">
|
||||
<property name="text">
|
||||
<string>Generate separate shells</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="m_forceManifold">
|
||||
<property name="text">
|
||||
<string>Force manifold output</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="m_genSmooth">
|
||||
<property name="text">
|
||||
<string>Smoothed version</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="buttonPoisson">
|
||||
<property name="text">
|
||||
<string>Poisson reconstruction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="framePoisson">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Min triangle angle:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_inputAngle">
|
||||
<property name="suffix">
|
||||
<string> °</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>30.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>20.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Max triangle size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_inputRadius">
|
||||
<property name="suffix">
|
||||
<string> * average spacing</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Approximation error:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_inputDistance">
|
||||
<property name="suffix">
|
||||
<string> * average spacing</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.250000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Solver:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="m_inputSolver">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Name of the sparse solver"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="m_inputTwoPasses">
|
||||
<property name="text">
|
||||
<string>Perform two passes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="m_doNotFillHoles">
|
||||
<property name="text">
|
||||
<string>Do not fill holes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QFrame" name="frameAuto">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_boundaries">
|
||||
<property name="text">
|
||||
<string>Output surface has boundaries</string>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="buttonAdvancing">
|
||||
<property name="text">
|
||||
<string>Advancing front reconstruction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameAdvancing">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Longest edge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_longestEdge">
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Radius ratio bound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Beta angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_radiusRatioBound">
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_betaAngle">
|
||||
<property name="suffix">
|
||||
<string>°</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>150.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>30.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="buttonRANSAC">
|
||||
<property name="text">
|
||||
<string>RANSAC-based Feature-preserving reconstruction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameRANSAC">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_interpolate">
|
||||
<property name="text">
|
||||
<string>Output surface must pass exactly through input points</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QRadioButton" name="buttonScaleSpace">
|
||||
<property name="text">
|
||||
<string>Scale Space Reconstruction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="buttonAuto">
|
||||
<property name="text">
|
||||
<string>Select Method and Parameters Automatically</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QFrame" name="frameAdvancing">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Longest Edge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_longestEdge">
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Radius Ratio Bound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Beta Angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_radiusRatioBound">
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_betaAngle">
|
||||
<property name="suffix">
|
||||
<string>°</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>150.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>30.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QRadioButton" name="buttonPoisson">
|
||||
<property name="text">
|
||||
<string>Poisson Reconstruction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="buttonAdvancing">
|
||||
<property name="text">
|
||||
<string>Advancing Front Reconstruction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QFrame" name="framePoisson">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Min Triangle Angle:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_inputAngle">
|
||||
<property name="suffix">
|
||||
<string> °</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>30.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>20.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Max Triangle Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_inputRadius">
|
||||
<property name="suffix">
|
||||
<string> * average spacing</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Approximation Error:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_inputDistance">
|
||||
<property name="suffix">
|
||||
<string> * average spacing</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.250000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Solver:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="m_inputSolver">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Name of the sparse solver"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="m_inputTwoPasses">
|
||||
<property name="text">
|
||||
<string>Perform two passes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="m_doNotFillHoles">
|
||||
<property name="text">
|
||||
<string>Do not fill holes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="m_generateStructured">
|
||||
<property name="text">
|
||||
<string>Generate structured point set</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="connectivityToleranceLabel">
|
||||
<property name="text">
|
||||
<string>Connectivity tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_connectivityTolerance">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="noiseToleranceLabel">
|
||||
<property name="text">
|
||||
<string>Noise tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="m_noiseTolerance">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="minimumSizeOfSubsetLabel">
|
||||
<property name="text">
|
||||
<string>Minimum size of subset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="m_minSizeSubset">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000000000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
@ -492,5 +637,21 @@
|
|||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonRANSAC</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>frameRANSAC</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>587</x>
|
||||
<y>266</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>587</x>
|
||||
<y>350</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
|||
Loading…
Reference in New Issue