1 // computes the normal vector for facets, assuming they are triangles
2 // (or at least reasonably planar convex polygons), and the normal
3 // vector for vertices by accumulating the normal vectors of all
4 // incident facets. All normal vectors are normalized, which requires
5 // sqrt computations. Therefore we use the Simple_cartesian<double>
6 // kernel, which is also a natural choice in graphics. Note that the
7 // normals computed are therefore not exact.
8 
9 #include <CGAL/Simple_cartesian.h>
10 #include <CGAL/Polyhedron_3.h>
11 #include <iostream>
12 #include <algorithm>
13 
14 // Two functors to compute the normals:  We assume the
15 // Simple_cartesian<double> Kernel here and use its global functions.
16 
17 struct Facet_normal {
18     template <class Facet>
operator ()Facet_normal19     void operator()( Facet& f) {
20         typename Facet::Halfedge_handle h = f.halfedge();
21         typename Facet::Normal_3 normal = CGAL::cross_product(
22           h->next()->vertex()->point() - h->vertex()->point(),
23           h->next()->next()->vertex()->point() - h->next()->vertex()->point());
24         f.normal() = normal / std::sqrt( normal * normal);
25     }
26 };
27 
28 struct Vertex_normal {
29     template <class Vertex>
operator ()Vertex_normal30     void operator()( Vertex& v) {
31         typename Vertex::Normal_3 normal = CGAL::NULL_VECTOR;
32         typedef typename Vertex::Halfedge_around_vertex_const_circulator Circ;
33         Circ c = v.vertex_begin();
34         Circ d = c;
35         CGAL_For_all( c, d) {
36             if ( ! c->is_border())
37                 normal = normal + c->facet()->normal();
38         }
39         v.normal() = normal / std::sqrt( normal * normal);
40     }
41 };
42 
43 // A redefined items class for the Polyhedron_3 with a refined vertex
44 // class that contains a member for the normal vector and a refined
45 // facet with a normal vector instead of the plane equation (this is
46 // an alternative solution instead of using Polyhedron_traits_with_normals_3).
47 
48 template <class Refs, class T, class P, class Norm>
49 class My_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, T, P> {
50     Norm  norm;
51 public:
My_vertex()52     My_vertex() {} // repeat mandatory constructors
My_vertex(const P & pt)53     My_vertex( const P& pt)
54       : CGAL::HalfedgeDS_vertex_base<Refs, T, P>(pt)
55     {
56       //initialization of the normal
57       norm= CGAL::NULL_VECTOR;
58     }
59     typedef Norm Normal_3;
normal()60     Normal_3&       normal()       { return norm; }
normal() const61     const Normal_3& normal() const { return norm; }
62 };
63 
64 template <class Refs, class T, class Norm>
65 class My_facet : public CGAL::HalfedgeDS_face_base<Refs, T> {
66     Norm  norm;
67 public:
68     // no constructors to repeat, since only default constructor mandatory
69     typedef Norm Normal_3;
normal()70     Normal_3&       normal()       { return norm; }
normal() const71     const Normal_3& normal() const { return norm; }
72 };
73 
74 struct My_items : public CGAL::Polyhedron_items_3 {
75     template <class Refs, class Traits>
76     struct Vertex_wrapper {
77         typedef typename Traits::Point_3  Point;
78         typedef typename Traits::Vector_3 Normal;
79         typedef My_vertex<Refs, CGAL::Tag_true, Point, Normal> Vertex;
80     };
81     template <class Refs, class Traits>
82     struct Face_wrapper {
83         typedef typename Traits::Vector_3 Normal;
84         typedef My_facet<Refs, CGAL::Tag_true, Normal> Face;
85     };
86 };
87 
88 // Tie all types together and a small main function using it.
89 
90 typedef CGAL::Simple_cartesian<double>                 Kernel;
91 typedef Kernel::Point_3                                Point_3;
92 typedef CGAL::Polyhedron_3<Kernel, My_items>           Polyhedron;
93 typedef Polyhedron::Vertex_iterator                    Vertex_iterator;
94 
main()95 int main() {
96     Point_3 p( 1, 0, 0);
97     Point_3 q( 0, 1, 0);
98     Point_3 r( 0, 0, 1);
99     Point_3 s( 0, 0, 0);
100     Polyhedron P;
101     P.make_tetrahedron( p, q, r, s);
102     std::for_each( P.facets_begin(),   P.facets_end(),   Facet_normal());
103     std::for_each( P.vertices_begin(), P.vertices_end(), Vertex_normal());
104     CGAL::IO::set_pretty_mode( std::cout);
105     for ( Vertex_iterator i = P.vertices_begin(); i != P.vertices_end(); ++i)
106         std::cout << i->normal() << std::endl;
107     return 0;
108 }
109