NormalAttribT.cc 6.18 KB
Newer Older
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
/*===========================================================================*\
 *                                                                           *
 *                            OpenVolumeMesh                                 *
 *        Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen         *
 *                        www.openvolumemesh.org                             *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenVolumeMesh.                                     *
 *                                                                           *
 *  OpenVolumeMesh is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU Lesser General Public License as           *
 *  published by the Free Software Foundation, either version 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenVolumeMesh is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU Lesser General Public License for more details.                      *
 *                                                                           *
 *  You should have received a copy of the GNU LesserGeneral Public          *
 *  License along with OpenVolumeMesh.  If not,                              *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                         *
 *   $Date$                    *
 *   $LastChangedBy$                                                *
 *                                                                           *
\*===========================================================================*/

#define NORMALATTRIBT_CC

#include <set>

#include "NormalAttrib.hh"

#include "../Core/GeometryKernel.hh"

namespace OpenVolumeMesh {

53
54
template <class GeomKernelT>
NormalAttrib<GeomKernelT>::NormalAttrib(GeomKernelT& _kernel) :
55
kernel_(_kernel),
56
57
v_normals_(_kernel.template request_vertex_property<typename GeomKernelT::PointT>("vertex_normals")),
f_normals_(_kernel.template request_face_property<typename GeomKernelT::PointT>("face_normals")) {
58
59
60

}

61
62
template <class GeomKernelT>
NormalAttrib<GeomKernelT>::~NormalAttrib() {
63
64
65

}

66
67
template <class GeomKernelT>
void NormalAttrib<GeomKernelT>::update_vertex_normals() {
68

69
70
    if(!kernel_.has_face_bottom_up_incidences()) {
        std::cerr << "Error: update_vertex_normals() needs bottom-up incidences!" << std::endl;
71
72
73
74
75
76
77
78
79
80
81
        return;
    }

    // Compute face normals
    update_face_normals();

    for(VertexIter v_it = kernel_.v_iter(); v_it.valid(); ++v_it) {
        compute_vertex_normal(*v_it);
    }
}

82
83
template <class GeomKernelT>
void NormalAttrib<GeomKernelT>::update_face_normals() {
84

85
86
    if(!kernel_.has_face_bottom_up_incidences()) {
        std::cerr << "Error: update_normals() needs bottom-up incidences!" << std::endl;
87
88
89
        return;
    }

90
91
92
93
94
95
96
    for(FaceIter f_it = kernel_.f_iter(); f_it.valid(); ++f_it) {
        // Assume the face is planar, so just take the
        // first two edges
        compute_face_normal(*f_it);
    }
}

97
98
template <class GeomKernelT>
void NormalAttrib<GeomKernelT>::compute_vertex_normal(const VertexHandle& _vh) {
99
100
101
102
103
104
105
106
107
108
109
110

    std::set<FaceHandle> faces;
    for(VertexOHalfEdgeIter voh_it = kernel_.voh_iter(_vh);
            voh_it.valid(); ++voh_it) {

        for(HalfEdgeHalfFaceIter hehf_it = kernel_.hehf_iter(*voh_it);
                hehf_it.valid(); ++hehf_it) {
            if(kernel_.is_boundary(*hehf_it)) {
                faces.insert(kernel_.face_handle(*hehf_it));
            }
        }
    }
111
    typename GeomKernelT::PointT normal;
112
113
114
115
116
117
118
119
120
121
    for(std::set<FaceHandle>::const_iterator f_it = faces.begin();
            f_it != faces.end(); ++f_it) {
        normal += f_normals_[f_it->idx()];
    }

    normal.normalize();

    v_normals_[_vh.idx()] = normal;
}

122
123
template <class GeomKernelT>
void NormalAttrib<GeomKernelT>::compute_face_normal(const FaceHandle& _fh) {
124
125
126
127
128
129
130
131
132
133
134
135
136

    if(kernel_.face(_fh).halfedges().size() < 3) {
        std::cerr << "Warning: Degenerate face detected!" << std::endl;
        return;
    }

    // Always try to compute the outside normals
    HalfFaceHandle hfh = kernel_.is_boundary(kernel_.halfface_handle(_fh, 0)) ?
            kernel_.halfface_handle(_fh, 0) : kernel_.halfface_handle(_fh, 1);

    std::vector<HalfEdgeHandle> halfedges = kernel_.halfface(hfh).halfedges();
    std::vector<HalfEdgeHandle>::const_iterator he_it = halfedges.begin();

137
138
    typename GeomKernelT::PointT p1 = kernel_.vertex(kernel_.halfedge(*he_it).from_vertex());
    typename GeomKernelT::PointT p2 = kernel_.vertex(kernel_.halfedge(*he_it).to_vertex());
139
    ++he_it;
140
    typename GeomKernelT::PointT p3 = kernel_.vertex(kernel_.halfedge(*he_it).to_vertex());
141

142
    typename GeomKernelT::PointT n = (p1 - p2) % (p3 - p2);
143
144
145
146
147
148
    n.normalize();

    f_normals_[_fh.idx()] = n;
}

} // Namespace OpenVolumeMesh