File: polyhedron_prog_vertex_normal.cpp

package info (click to toggle)
cgal 4.5-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 69,700 kB
  • ctags: 118,537
  • sloc: cpp: 571,870; ansic: 110,997; sh: 725; python: 92; makefile: 87
file content (103 lines) | stat: -rw-r--r-- 3,932 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// computes the normal vector for facets, assuming they are triangles
// (or at least reasonably planar convex polygons), and the normal
// vector for vertices by accumulating the normal vectors of all
// incident facets. All normal vectors are normalized, which requires
// sqrt computations. Therefore we use the Simple_cartesian<double>
// kernel, which is also a natural choice in graphics. Note that the
// normals computed are therefore not exact.

#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <iostream>
#include <algorithm>

// Two functors to compute the normals:  We assume the
// Simple_cartesian<double> Kernel here and use its global functions.

struct Facet_normal {
    template <class Facet>
    void operator()( Facet& f) {
        typename Facet::Halfedge_handle h = f.halfedge();
        typename Facet::Normal_3 normal = CGAL::cross_product(
          h->next()->vertex()->point() - h->vertex()->point(),
          h->next()->next()->vertex()->point() - h->next()->vertex()->point());
        f.normal() = normal / std::sqrt( normal * normal);
    }
};

struct Vertex_normal {
    template <class Vertex>
    void operator()( Vertex& v) {
        typename Vertex::Normal_3 normal = CGAL::NULL_VECTOR;
        typedef typename Vertex::Halfedge_around_vertex_const_circulator Circ;
        Circ c = v.vertex_begin();
        Circ d = c;
        CGAL_For_all( c, d) {
            if ( ! c->is_border())
                normal = normal + c->facet()->normal();
        }
        v.normal() = normal / std::sqrt( normal * normal);
    }
};

// A redefined items class for the Polyhedron_3 with a refined vertex
// class that contains a member for the normal vector and a refined
// facet with a normal vector instead of the plane equation (this is
// an alternative solution instead of using Polyhedron_traits_with_normals_3).

template <class Refs, class T, class P, class Norm>
class My_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, T, P> {
    Norm  norm;
public:
    My_vertex() {} // repeat mandatory constructors
    My_vertex( const P& pt) : CGAL::HalfedgeDS_vertex_base<Refs, T, P>(pt) {}
    typedef Norm Normal_3;
    Normal_3&       normal()       { return norm; }
    const Normal_3& normal() const { return norm; }
};

template <class Refs, class T, class Norm>
class My_facet : public CGAL::HalfedgeDS_face_base<Refs, T> {
    Norm  norm;
public:
    // no constructors to repeat, since only default constructor mandatory
    typedef Norm Normal_3;
    Normal_3&       normal()       { return norm; }
    const Normal_3& normal() const { return norm; }
};

struct My_items : public CGAL::Polyhedron_items_3 {
    template <class Refs, class Traits>
    struct Vertex_wrapper {
        typedef typename Traits::Point_3  Point;
        typedef typename Traits::Vector_3 Normal;
        typedef My_vertex<Refs, CGAL::Tag_true, Point, Normal> Vertex;
    };
    template <class Refs, class Traits>
    struct Face_wrapper {
        typedef typename Traits::Vector_3 Normal;
        typedef My_facet<Refs, CGAL::Tag_true, Normal> Face;
    };
};

// Tie all types together and a small main function using it.

typedef CGAL::Simple_cartesian<double>                 Kernel;
typedef Kernel::Point_3                                Point_3;
typedef CGAL::Polyhedron_3<Kernel, My_items>           Polyhedron;
typedef Polyhedron::Vertex_iterator                    Vertex_iterator;

int main() {
    Point_3 p( 1, 0, 0);
    Point_3 q( 0, 1, 0);
    Point_3 r( 0, 0, 1);
    Point_3 s( 0, 0, 0);
    Polyhedron P;
    P.make_tetrahedron( p, q, r, s);
    std::for_each( P.facets_begin(),   P.facets_end(),   Facet_normal());
    std::for_each( P.vertices_begin(), P.vertices_end(), Vertex_normal());
    CGAL::set_pretty_mode( std::cout);
    for ( Vertex_iterator i = P.vertices_begin(); i != P.vertices_end(); ++i)
        std::cout << i->normal() << std::endl;
    return 0;
}