/*===========================================================================*\ * * * 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 . * * * \*===========================================================================*/ #define NORMALATTRIBT_CC #include #include "NormalAttrib.hh" #include "../Core/GeometryKernel.hh" namespace OpenVolumeMesh { template NormalAttrib::NormalAttrib(GeomKernelT& _kernel) : kernel_(_kernel), v_normals_(_kernel.template request_vertex_property("vertex_normals", typename GeomKernelT::PointT(0.0))), f_normals_(_kernel.template request_face_property("face_normals", typename GeomKernelT::PointT(0.0))) { } template NormalAttrib::~NormalAttrib() { } template void NormalAttrib::update_vertex_normals() { if(!kernel_.has_face_bottom_up_incidences()) { std::cerr << "Error: update_vertex_normals() needs bottom-up incidences!" << std::endl; return; } // Compute face normals update_face_normals(); for(VertexIter v_it = kernel_.v_iter(); v_it.valid(); ++v_it) { compute_vertex_normal(*v_it); } } template void NormalAttrib::update_face_normals() { if(!kernel_.has_face_bottom_up_incidences()) { std::cerr << "Error: update_normals() needs bottom-up incidences!" << std::endl; return; } 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); } } template void NormalAttrib::compute_vertex_normal(const VertexHandle& _vh) { std::set halffaces; 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)) { halffaces.insert(*hehf_it); } } } typename GeomKernelT::PointT normal = typename GeomKernelT::PointT(0.0); for(std::set::const_iterator hf_it = halffaces.begin(); hf_it != halffaces.end(); ++hf_it) { normal += (*this)[*hf_it]; } normal.normalize(); v_normals_[_vh] = normal; } template void NormalAttrib::compute_face_normal(const FaceHandle& _fh) { if(kernel_.face(_fh).halfedges().size() < 3) { std::cerr << "Warning: Degenerate face detected!" << std::endl; return; } const std::vector& halfedges = kernel_.face(_fh).halfedges(); std::vector::const_iterator he_it = halfedges.begin(); typename GeomKernelT::PointT p1 = kernel_.vertex(kernel_.halfedge(*he_it).from_vertex()); typename GeomKernelT::PointT p2 = kernel_.vertex(kernel_.halfedge(*he_it).to_vertex()); ++he_it; typename GeomKernelT::PointT p3 = kernel_.vertex(kernel_.halfedge(*he_it).to_vertex()); typename GeomKernelT::PointT n = (p2 - p1) % (p3 - p2); n.normalize(); f_normals_[_fh] = n; } } // Namespace OpenVolumeMesh