I reconstruct a 3D surface mesh using the advancing front surface reconstruction and would like to refine it. How can I achieve this?
This is part of the code used for surface reconstruction with refinement by passing through a file:
#include <CGAL/Advancing_front_surface_reconstruction.h>
#include <CGAL/compute_average_spacing.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/Triangulation_data_structure_3.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Polygon_mesh_processing/refine.h>
#include <CGAL/Polygon_mesh_processing/fair.h>
typedef CGAL::Advancing_front_surface_reconstruction<> Reconstruction;
typedef Reconstruction::Triangulation_3 Triangulation_3;
typedef Reconstruction::Triangulation_data_structure_2 TDS_2;
typedef Reconstruction::Outlier_range Outlier_range;
typedef Reconstruction::Boundary_range Boundary_range;
typedef Reconstruction::Vertex_on_boundary_range Vertex_on_boundary_range;
typedef Reconstruction::Vertex_handle Vertex_handle;
typedef CGAL::Polyhedron_3<CGALMesher::Kernel> Polyhedron;
typedef CGAL::Surface_mesh<CGALMesher::Point> Mesh;
typedef CGAL::cpp11::array<std::size_t,3> Facet;
struct Construct {
Mesh& mesh;
template<typename PointIterator>
Construct(Mesh& mesh, PointIterator b, PointIterator e) : mesh(mesh) {
for (; b != e; ++b) {
boost::graph_traits<Mesh>::vertex_descriptor v;
v = add_vertex(mesh);
mesh.point(v) = *b;
}
}
Construct& operator=(const Facet f) {
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Mesh>::vertices_size_type size_type;
mesh.add_face(vertex_descriptor(static_cast<size_type>(f[0])),
vertex_descriptor(static_cast<size_type>(f[1])),
vertex_descriptor(static_cast<size_type>(f[2])));
return *this;
}
Construct&
operator*() {
return *this;
}
Construct&
operator++() {
return *this;
}
Construct operator++(int) {
return *this;
}
};
void CGALMesher::AdvancingFrontMesher(std::vector<Point>& points) {
Mesh m;
Construct construct(m,points.begin(),points.end());
CGAL::advancing_front_surface_reconstruction(points.begin(), points.end(), construct);
std::ofstream mesh_off("mesh.off");
mesh_off << m;
mesh_off.close();
std::ifstream input("mesh.off");
Polyhedron poly;
if ( !input || !(input >> poly) || poly.empty() ) {
std::cerr << "Not a valid off file." << std::endl;
}
input.close();
std::vector<Polyhedron::Facet_handle> new_facets;
std::vector<Polyhedron::Vertex_handle> new_vertices;
CGAL::Polygon_mesh_processing::refine(poly,
faces(poly),
std::back_inserter(new_facets),
std::back_inserter(new_vertices),
CGAL::Polygon_mesh_processing::parameters::density_control_factor(3));
std::ofstream refined_off("refined.off");
refined_off << poly;
refined_off.close();
std::cout << "Refinement added " << new_vertices.size() << " vertices." << std::endl;
}
Once you extracted a polyhedral surface out of the reconstruction algorithm, you can use the refine() function from the polygon mesh processing package. There is also the possibility to use the fair().
More drastically, you can use remeshing algorithm like this one. In CGAL 4.8, there will also be the function isotropic_remeshing() that is already available in the master branch.
Related
I tried to overload operator== for std::pair<int, int> so that only the first element of the pair would matter. Then, I'd like to use std::find to look for a particular element in std::vector<std::pair<int, int>>, using the overloaded operator==. But, it seems that, std::find is not using my overloaded operator==, though it is working in a simple comparison statement.
I expect the following code to output:
1
1
1
but I get:
1
1
0
Run on Linux, gcc 11.3:
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
typedef pair<int, int> p_int_t;
bool operator==(const p_int_t& p1, const p_int_t& p2)
{
return p1.first == p2.first;
}
int main()
{
vector<p_int_t> v;
v.push_back({1, 2});
v.push_back({1, 3});
p_int_t p(1, 4);
cout << (v[0] == p) << endl;
cout << (v[1] == p) << endl;
cout << (find(v.begin(), v.end(), p) != v.end()) << endl;
return 0;
}
The compiler does not select the free standing comparison operator because the type p_int_t is an alias, and it is not defined in the std namespace as std:: pair is. In other words, the compiler is looking for an operator with this signature: std::operator==(const std::pair<int, int>&, const std::pair<int, int>&); and finds it in algorithm.
You could declare your operator in the std namespace, which works, but is not recommended, or define p_int_t as a class, as in:
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
struct p_int_t : pair<int, int> {
using pair<int, int>::pair; // for c++=11 and later
p_int_t() : pair() {} // for c++98
p_int_t(int x, int y) : pair(x, y) {} // for c++98
friend bool operator==(const p_int_t& p1, const p_int_t& p2) {
return p1.first == p2.first;
}
};
int main() {
vector<p_int_t> v;
v.push_back({1, 2});
v.push_back({1, 3});
p_int_t p(1, 4);
cout << (v[0] == p) << endl;
cout << (v[1] == p) << endl;
cout << (find(v.begin(), v.end(), p) != v.end()) << endl;
return 0;
}
Code can be found here: https://godbolt.org/z/5dfPaaoMz
Having to redefine constructors is quite cumbersome, but you can also use std::find_if(), as in:
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
typedef pair<int, int> p_int_t;
struct compare_first {
p_int_t p;
compare_first(p_int_t x) : p(x) {}
bool operator()(const p_int_t& x) { return x.first == p.first; }
};
int main() {
vector<p_int_t> v;
v.push_back({1, 2});
v.push_back({1, 3});
p_int_t p(1, 4);
cout << (find_if(v.begin(), v.end(), compare_first(p)) != v.end()) << endl;
// or for c++11 or later...
cout << (find_if(v.begin(), v.end(), [&p](const p_int_t& x) { return p.first == x.first; }) != v.end()) << endl;
return 0;
}
Code here: https://godbolt.org/z/r87hdrrK9
I am trying to use CGAL to perform some simple 2D CSG operations. Here is an example of an intersection of two polygons.
The actual problem is tracking down the origin (marked with color) of each segment in resulting polygon.
I would like to know if that is possible, maybe with some hacking on the CGAL itself. Any suggestion will be highly appreciated.
Unfortunately, there is no out-of-the-box way doing it. However, it doesn't require too much (famous last words...). You need to do two things described below. The first is supported by the API. The second is not, so you will need to patch a source file. A simple example is provided further bellow. Notice that the data you need, that is, the specification of the origin of each edge, ends up in a 2D arrangement data structure. If you want to obtain the polygons with this data, you need to extract them from the arrangement. You can obtain the header pgn_print.h, used in the example, from the 2D-Arrangement book.
Use an instance of CGAL::Polygon_set_2<Kernel, Container, Dcel>, where the Dcel is substituted with an extended Dcel, the halfedge of which is extended with a label that indicates the origin of the halfedge (i.e., first polygon, second polygon, or both in case of an overlap).
Patch the header file Boolean_set_operations_2/Gps_base_functor.h. In particular, add to the body of the three functions called create_edge() statements that set the label of the resulting halfedges according to their origin:
void create_edge(Halfedge_const_handle h1, Halfedge_const_handle h2,
Halfedge_handle h)
{
h->set_label(3);
h->twin()->set_label(3);
}
void create_edge(Halfedge_const_handle h1, Face_const_handle f2,
Halfedge_handle h)
{
h->set_label(1);
h->twin()->set_label(1);
}
void create_edge(Face_const_handle f1, Halfedge_const_handle h2,
Halfedge_handle h)
{
h->set_label(2);
h->twin()->set_label(2);
}
#include <list>
#include <vector>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/Polygon_set_2.h>
#include "pgn_print.h"
/*! Extend the arrangement halfedge */
template <typename X_monotone_curve_2>
class Arr_labeled_halfedge :
public CGAL::Arr_halfedge_base<X_monotone_curve_2>
{
private:
unsigned m_label;
public:
Arr_labeled_halfedge() : m_label(0) {}
unsigned label() const { return m_label; }
void set_label(unsigned label) { m_label = label; }
virtual void assign(const Arr_labeled_halfedge& he)
{
CGAL::Arr_halfedge_base<X_monotone_curve_2>::assign(he);
m_label = he.m_label;
}
};
template <typename Traits>
class Arr_labeled_dcel :
public CGAL::Arr_dcel_base<CGAL::Arr_vertex_base<typename Traits::Point_2>,
Arr_labeled_halfedge<typename Traits::
X_monotone_curve_2>,
CGAL::Gps_face_base>
{
public:
Arr_labeled_dcel() {}
};
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef CGAL::Polygon_2<Kernel> Polygon_2;
typedef CGAL::Polygon_with_holes_2<Kernel> Polygon_with_holes_2;
typedef std::vector<Point_2> Container;
typedef CGAL::Gps_segment_traits_2<Kernel, Container> Traits_2;
typedef Arr_labeled_dcel<Traits_2> Dcel;
typedef CGAL::Polygon_set_2<Kernel, Container, Dcel> Polygon_set_2;
typedef std::list<Polygon_with_holes_2> Pwh_list_2;
typedef Polygon_set_2::Arrangement_2 Arrangement_2;
typedef Arrangement_2::Edge_const_iterator Edge_const_iterator;
void print_result(const Polygon_set_2& S)
{
std::cout << "The result contains " << S.number_of_polygons_with_holes()
<< " components:" << std::endl;
Pwh_list_2 res;
S.polygons_with_holes(std::back_inserter(res));
for (Pwh_list_2::const_iterator hit = res.begin(); hit != res.end(); ++hit) {
std::cout << "--> ";
print_polygon_with_holes(*hit);
}
const Arrangement_2& arr = S.arrangement();
for (Edge_const_iterator it = arr.edges_begin(); it != arr.edges_end(); ++it) {
std::cout << it->curve()
<< ", " << it->label()
<< std::endl;
}
}
int main()
{
// Construct the two input polygons.
Polygon_2 P;
P.push_back(Point_2(0, 0));
P.push_back(Point_2(5, 0));
P.push_back(Point_2(3.5, 1.5));
P.push_back(Point_2(2.5, 0.5));
P.push_back(Point_2(1.5, 1.5));
std::cout << "P = "; print_polygon(P);
Polygon_2 Q;
Q.push_back(Point_2(0, 2));
Q.push_back(Point_2(1.5, 0.5));
Q.push_back(Point_2(2.5, 1.5));
Q.push_back(Point_2(3.5, 0.5));
Q.push_back(Point_2(5, 2));
std::cout << "Q = "; print_polygon(Q);
// Compute the union of P and Q.
Polygon_set_2 intersection_set;
intersection_set.insert(P);
intersection_set.intersection(Q);
print_result(intersection_set);
// Compute the intersection of P and Q.
Polygon_set_2 union_set;
union_set.insert(P);
union_set.join(Q);
print_result(union_set);
return 0;
}
I'm trying to build a triangulation (or mesh) of 2D figure. But it fails for some figures, because bad triangles are produced. These triangles are built by points which lie at the one line. I identify these triangles by the area.
Does anybody know how to fix it?
my code:
#include <iostream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_conformer_2.h>
#include <CGAL/Delaunay_mesher_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include <CGAL/Delaunay_mesh_size_criteria_2.h>
#include <CGAL/Constrained_triangulation_plus_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
typedef CGAL::Delaunay_mesh_face_base_2<K> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds, CGAL::Exact_predicates_tag> CDT;
typedef CGAL::Constrained_triangulation_plus_2<CDT> CDT_plus;
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT_plus> Criteria;
typedef CGAL::Delaunay_mesher_2<CDT_plus, Criteria> Mesher;
typedef CDT::Vertex_handle Vertex_handle;
typedef CDT::Point Point;
void some_function()
{
CDT_plus cdt;
Point hp[6];
hp[0] = Point(0.500000091410, 0.486455788882);
hp[1] = Point(-0.334032111870, 0.486455788837);
hp[2] = Point(-0.500000091424, 0.120965046601);
hp[3] = Point(-0.500000091430, 0.008971885303);
hp[4] = Point(0.482938375290, -0.486030074474);
hp[5] = Point(0.500000091434, -0.448457168454);
for (int i = 0; i < 6; ++i)
{
cdt.insert_constraint(hp[i], hp[i + 1 < 6 ? i + 1 : 0]);
}
Mesher mesher(cdt, Criteria(0.125, 0.3));
int i = 0;
mesher.refine_mesh();
for (CDT::Finite_faces_iterator it = mesher.triangulation().finite_faces_begin(); it != mesher.triangulation().finite_faces_end(); it++)
{
CDT::Triangle trr = cdt.triangle(it);
if (trr.area()< 1e-12)
{
cout << "i am very saaad" << endl;
}
}
}
I found a phenomenon, CGAL AABB tree Constructor function is very very slow for std::vector.
Here is a minimal test code:
Point a(1.0, 0.0, 0.0);
Point b(0.0, 1.0, 0.0);
Point c(0.0, 0.0, 1.0);
std::vector<Triangle> triangles;
for (size_t I=0;I<245000;I++)
{
triangles.push_back(Triangle(a,b,c));
}
// constructs AABB tree
MyTree tree(triangles.begin(),triangles.end());
245000 Primitive, not built, run much slower. I find source:
template<typename Tr>
template<typename ConstPrimitiveIterator, typename ... T>
void AABB_tree<Tr>::insert(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond,
T ... t)
{
set_shared_data(t...);
while(first != beyond)
{
m_primitives.push_back(Primitive(first,t...));
++first;
}
m_need_build = true;
}
I suspect vector push_back function will reallocate memory, but I'm not sure is the reason, So I tried this code:
template<typename Tr>
template<typename ConstPrimitiveIterator, typename ... T>
void AABB_tree<Tr>::insert(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond,
T ... t)
{
set_shared_data(t...);
m_primitives.assign(beyond-first,first);//pre allcate promitives
size_t Index = 0;
while(first != beyond)
{
m_primitives[Index] = Primitive(first,t...);
++first;
++Index;
}
m_need_build = true;
}
The problem solves! I need more advices, and I think this needs to be updated to CGAL source?
==================14-9-18 update ===============
I make an simple test:
#include <iostream>
#include <list>
#include "boost/timer/timer.hpp"
#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_triangle_primitive.h>
#include <CGAL/Polyhedron_3.h>
typedef CGAL::Simple_cartesian<double> K;
typedef K::FT FT;
typedef K::Ray_3 Ray;
typedef K::Line_3 Line;
typedef K::Point_3 Point;
typedef K::Triangle_3 Triangle;
typedef std::vector<Triangle>::iterator Iterator;
typedef CGAL::AABB_triangle_primitive<K, Iterator> Primitive;
typedef CGAL::AABB_traits<K, Primitive> AABB_triangle_traits;
typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
int main()
{
Point a(1.0, 0.0, 0.0);
Point b(0.0, 1.0, 0.0);
Point c(0.0, 0.0, 1.0);
std::vector<Triangle> triangles;
for (size_t I=0;I<245000;I++)
{
triangles.push_back(Triangle(a,b,c));
}
#define TIMER_SECOND boost::timer::nanosecond_type(1000000000LL)
auto first = triangles.begin();
auto beyond = triangles.end();
boost::timer::cpu_timer CountTimer;
//Test 1
std::vector<Primitive> TestV1;
CountTimer.start();
while(first != beyond)
{
TestV1.push_back(Primitive(first));
++first;
}
std::cout << "Test1 Time:" << CountTimer.elapsed().wall << std::endl;
//Test 2
first = triangles.begin();
beyond = triangles.end();
std::vector<Primitive> TestV2;
CountTimer.start();
TestV2.reserve(std::distance(first,beyond));
while(first != beyond)
{
TestV2.push_back(Primitive(first));
++first;
}
std::cout << "Test2 Time:" << CountTimer.elapsed().wall << std::endl;
system("pause");
return EXIT_SUCCESS;
}
in release mode:
Test1 Time:3426459
Test2 Time:926136
in debug mode:
Test1 Time:503719044580
Test2 Time:224280791
I'm not able to make this code work using fellowed convention of header includes.
help.cpp
#include <iostream>
#include "basicMath.h"
using namespace std;
int main() {
int arr[4]={0,1,2,3};
int k=0;
int m=3;
//permutations call
perm(arr,k,m);
return 0;
}
BasicMath.h
#ifndef BASICMATH_H_
#define BASICMATH_H_
template<class T>
void Swap ( T& a, T& b );
template<class T1>
void perm ( T1 arr[], int k, int m);
#endif /* BASICMATH_H_ */
BasicMath.cpp
#include <iostream>
#include "basicMath.h"
using namespace std;
template<class T>
void Swap ( T& a, T& b )
{
T temp;
b=temp;
b=a;
a=temp;
}
template<class T1>
void perm ( T1 arr[], int k, int m)
{
//base case
cout << "Call: " << arr[0] << arr[1] << arr[2] << arr[3] << "\t" << k << "\t" << m << "\n";
if (k==m) {
for (int i=0;i<=m;i++) {
cout << arr[i];
}
cout << endl;
} else {
for (int i=k;i<=m;i++) {
swap(arr[k],arr[i]);
perm(arr,k+1,m);
swap(arr[k],arr[i]);
}
}
}
IF I replace the #include "basicMath.h" by #include "basicMath.cpp" Then program works.
Please help. New to Eclipse Project using headers and src.
Thanks in Adv.
The "simple" answer is that you can't put the implementation of a template function into a .cpp file.
See http://www.parashift.com/c++-faq/templates-defn-vs-decl.html