00001 /*************************************************************************** 00002 * Copyright (C) 2007 by Pablo Diaz-Gutierrez * 00003 * pablo@ics.uci.edu * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU Library General Public License as * 00007 * published by the Free Software Foundation; either version 2 of the * 00008 * License, or (at your option) any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU Library General Public * 00016 * License along with this program; if not, write to the * 00017 * Free Software Foundation, Inc., * 00018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00019 ***************************************************************************/ 00020 00021 #ifdef _WIN32 00022 #pragma warning(disable:4786) 00023 #endif 00024 00025 #include <cassert> 00026 #include "face.h" 00027 #include "vertex.h" 00028 #include "halfedge.h" 00029 00030 using namespace std; 00031 using namespace Geometry; 00032 using namespace HE; 00033 00034 00035 Vector3Df Face::normal() const 00036 { 00037 //static Vector3Df prev(1,0,0); // $$$ Hack to prevent problems with degenerate normals... 00038 Vector3Df N(0,0,0); 00039 #if 0 // We can still compute the normal of a hole... Let the application decide its use. 00040 if (hole()) 00041 return N; 00042 #endif 00043 00044 const_edge_circulator e = begin(); 00045 const_edge_circulator sentinel = e; 00046 do 00047 { 00048 Vector3Df v(- (*e)->tangent()); 00049 ++e; 00050 Vector3Df v2((*e)->tangent()); 00051 float a = v.angle(v2); 00052 Vector3Df n = v2 ^ v; 00053 N += a*n; 00054 } while (e != sentinel) ; 00055 00056 N.normalize(); 00057 #if 1 00058 return N; 00059 #else 00060 if (!isnan(N[0]) && !isnan(N[1]) && !isnan(N[2])) 00061 { 00062 prevN = N; 00063 return N; 00064 } 00065 else 00066 { 00067 return prevN; 00068 } 00069 #endif 00070 } 00071 00072 Vector3Df Face::centroid() const 00073 { 00074 Vector3Df C(0,0,0); 00075 00076 const_edge_circulator e = begin(); 00077 const_edge_circulator sentinel = e; 00078 int n = 0; 00079 do 00080 { 00081 n++; 00082 C += (*e)->dst()->position(); 00083 ++e; 00084 } while (e != sentinel) ; 00085 00086 return C / n; 00087 } 00088 00089 00090 ostream& HE::operator<< (ostream& out, const Face& f) 00091 { 00092 out << '[' << (int)f.edge() << (f.hole() ? ", hole" : ", solid") << ", " << f.size() << " verts: "; 00093 00094 Face::const_edge_circulator e = f.begin(); 00095 const Face::const_edge_circulator sentinel = e; 00096 do 00097 { 00098 const Vertex* v = (*e)->dst(); 00099 if (v) 00100 out << ' ' << v->index(); 00101 else 00102 out << " NULL"; 00103 ++e; 00104 } while (sentinel != e) ; 00105 00106 return out << ']'; 00107 } 00108 00109 int Face::size() const 00110 { 00111 Face::const_edge_circulator e = begin(); 00112 Face::const_edge_circulator sentinel = e; 00113 int n(0); 00114 do 00115 { 00116 n++; 00117 ++e; 00118 } while (sentinel != e) ; 00119 00120 return n; 00121 } 00122 00123 bool Face::contains(const HalfEdge* he) const 00124 { 00125 Face::const_edge_circulator e = begin(); 00126 Face::const_edge_circulator sentinel = e; 00127 do 00128 { 00129 if (*e == he) 00130 return true; 00131 ++e; 00132 } while (sentinel != e) ; 00133 00134 return false; 00135 } 00136 00137 bool Face::contains(const Vertex* v) const 00138 { 00139 Face::const_edge_circulator e = begin(); 00140 Face::const_edge_circulator sentinel = e; 00141 do 00142 { 00143 if ((*e)->dst() == v) 00144 return true; 00145 ++e; 00146 } while (sentinel != e) ; 00147 00148 return false; 00149 } 00150 00151 const HalfEdge* Face::fromVertex(int v) const 00152 { 00153 Face::const_edge_circulator e = begin(); 00154 Face::const_edge_circulator sentinel = e; 00155 do 00156 { 00157 if ((*e)->dst()->index() == v) 00158 return (*e)->next(); 00159 ++e; 00160 } while (sentinel != e) ; 00161 00162 return 0; 00163 } 00164 00165 const HalfEdge* Face::toVertex(int v) const 00166 { 00167 Face::const_edge_circulator e = begin(); 00168 Face::const_edge_circulator sentinel = e; 00169 do 00170 { 00171 if ((*e)->dst()->index() == v) 00172 return *e; 00173 ++e; 00174 } while (sentinel != e) ; 00175 00176 return 0; 00177 } 00178 00179 const HalfEdge* Face::fromVertex(Vertex* v) const 00180 { 00181 return fromVertex(v->index()); 00182 } 00183 00184 const HalfEdge* Face::toVertex(Vertex* v) const 00185 { 00186 return toVertex(v->index()); 00187 } 00188 00189 void HE::Face::edge_circulator::operator++() 00190 { 00191 _here = _here->next(); 00192 } 00193 00194 void HE::Face::const_edge_circulator::operator++() 00195 { 00196 _here = _here->next(); 00197 } 00198