From 2c061402f5a110904d37518ea34616441fbf850c Mon Sep 17 00:00:00 2001 From: cignoni Date: Thu, 19 Feb 2004 13:11:06 +0000 Subject: [PATCH] Initial commit --- vcg/complex/trimesh/base.h | 440 +++++++++++++ vcg/complex/trimesh/compute.h | 115 ++++ vcg/complex/trimesh/geodesic.h | 1050 ++++++++++++++++++++++++++++++++ vcg/complex/trimesh/platonic.h | 518 ++++++++++++++++ vcg/simplex/face/with/fa.h | 14 + vcg/simplex/face/with/fc.h | 14 + vcg/simplex/face/with/fn.h | 14 + 7 files changed, 2165 insertions(+) create mode 100644 vcg/complex/trimesh/base.h create mode 100644 vcg/complex/trimesh/compute.h create mode 100644 vcg/complex/trimesh/geodesic.h create mode 100644 vcg/complex/trimesh/platonic.h create mode 100644 vcg/simplex/face/with/fa.h create mode 100644 vcg/simplex/face/with/fc.h create mode 100644 vcg/simplex/face/with/fn.h diff --git a/vcg/complex/trimesh/base.h b/vcg/complex/trimesh/base.h new file mode 100644 index 00000000..ede3a0d1 --- /dev/null +++ b/vcg/complex/trimesh/base.h @@ -0,0 +1,440 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#pragma warning( disable : 4804 ) + +/* +People should subclass his vertex class from these one... +*/ + +#ifndef __VCG_MESH +#define __VCG_MESH + +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include +#include + +namespace vcg { + +/** Class Mesh. + This is class for definition of a mesh. + @param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type. + @param STL_FACE_CONT (Template Parameter) Specifies the type of the faces container any the face type. + */ +template < class STL_VERT_CONT, class STL_FACE_CONT > +class Mesh{ + public: + /// The face container + typedef STL_FACE_CONT face_container; + /// The face container + typedef STL_VERT_CONT vertex_container; + /// The vertex type + typedef typename STL_VERT_CONT::value_type MVTYPE; + /// The face type + typedef typename STL_FACE_CONT::value_type MFTYPE; + /// The scalar type + typedef typename MVTYPE::scalar_type MCTYPE; + /// The type of the vectors + typedef typename MFTYPE::vectorial_type vectorial_type; + /// The type of the scalars + typedef MCTYPE scalar_type; + /// The vertex type + typedef MVTYPE vertex_type; + /// Tipo vertice originario + typedef typename MVTYPE::vertex_base vertex_base; + /// The face type + typedef MFTYPE face_type; + /// The type of vertex iterator + typedef typename STL_VERT_CONT::iterator vertex_iterator; + /// The type of face iterator + typedef typename STL_FACE_CONT::iterator face_iterator; + /// The type of constant vertex iterator + typedef typename STL_VERT_CONT::const_iterator const_vertex_iterator; + /// The type of constant face iterator + typedef typename STL_FACE_CONT::const_iterator const_face_iterator; + /// The vertex pointer type + typedef MVTYPE * vertex_pointer; + /// The face pointer type + typedef MFTYPE * face_pointer; + /// The type of the constant vertex pointer + typedef const MVTYPE * const_vertex_pointer; + /// The type of the constant face pointer + typedef const MFTYPE * const_face_pointer; + /// The vertex base pointer type + typedef typename MVTYPE::vertex_base * vertex_base_pointer; + /// The type of the constant vertex base pointer + typedef const typename MVTYPE::vertex_base * const_vertex_base_pointer; + /// The face base pointer type + typedef typename MFTYPE::face_base face_base; + typedef typename MFTYPE::face_base * face_base_pointer; + /// The type of the constant face base pointer + typedef const typename MFTYPE::face_base * const_face_base_pointer; + /// The mesh type + typedef Mesh MMTYPE; + /// The edge type for FF topology + typedef FEdgePosB fedgepos_type; + /// The edge type for VF topology + typedef VEdgePosB vedgepos_type; + /// The half edge type + typedef HEdgePosB hedgepos_type; + /// The half edge type with the normal + typedef HEdgePosBN hedgeposn_type; + /// The ear type + typedef Ear ear_type; + /// The Box3 type + typedef Box3 BOX_TYPE; + + /// Set of vertices + STL_VERT_CONT vert; + /// Real number of vertices + int vn; + /// Set of faces + STL_FACE_CONT face; + /// Real number of faces + int fn; + /// Bounding box of the mesh + Box3 bbox; + /// Internal status + int status; + + /// Nomi di textures + vector textures; + vector normalmaps; + + /// La camera + Camera camera; + + /// Il colore della mesh +private: + ColorUB c; +public: + + inline const ColorUB & C() const + { + return c; + } + + inline ColorUB & C() + { + return c; + } + + + /// Default constructor + Mesh() + { + fn = vn = 0; + imark = 0; + } + + inline int MemUsed() const + { + return sizeof(MMTYPE)+sizeof(MVTYPE)*vert.size()+sizeof(MFTYPE)*face.size(); + } + + inline int MemNeeded() const + { + return sizeof(MMTYPE)+sizeof(MVTYPE)*vn+sizeof(MFTYPE)*fn; + } + + + +/// Function to destroy the mesh +MMTYPE & Clear() +{ + vert.clear(); + face.clear(); + textures.clear(); + normalmaps.clear(); + vn = 0; + fn = 0; + return *this; +} + +/* Funzioni di info sulle caratteristiche della mesh */ + +static bool HasPerVertexNormal() { return bool(vertex_type::OBJ_TYPE & (vertex_type::OBJ_TYPE_N)); } +static bool HasPerVertexColor() { return bool(vertex_type::OBJ_TYPE & (vertex_type::OBJ_TYPE_C)); } +static bool HasPerVertexMark() { return bool(vertex_type::OBJ_TYPE & (vertex_type::OBJ_TYPE_M)); } +static bool HasPerVertexQuality() { return bool(vertex_type::OBJ_TYPE & (vertex_type::OBJ_TYPE_Q)); } +static bool HasPerVertexTexture() { return bool(vertex_type::OBJ_TYPE & (vertex_type::OBJ_TYPE_T)); } + +static bool HasPerFaceColor() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_C)); } +static bool HasPerFaceNormal() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_N)); } +static bool HasPerFaceMark() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_M)); } +static bool HasPerFaceQuality() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_Q)); } + +static bool HasPerWedgeColor() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_WC)); } +static bool HasPerWedgeNormal() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_WN)); } +static bool HasPerWedgeTexture() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_WT)); } + +static bool HasFFTopology() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_A)) || HasSTopology(); } +static bool HasVFTopology() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_V)) || HasSTopology(); } +static bool HasSTopology() { return bool(face_type::OBJ_TYPE & (face_type::OBJ_TYPE_S)); } +static bool HasTopology() { return HasFFTopology() || HasVFTopology(); } + + + + +/// Initialize the imark-system of the faces +void InitFaceIMark() +{ + face_iterator f; + + for(f=face.begin();f!=face.end();++f) + if( !(*f).IsDeleted() && (*f).IsR() && (*f).IsW() ) + (*f).InitIMark(); +} + +/// Initialize the imark-system of the vertices +void InitVertexIMark() +{ + vertex_iterator vi; + + for(vi=vert.begin();vi!=vert.end();++vi) + if( !(*vi).IsDeleted() && (*vi).IsRW() ) + (*vi).InitIMark(); +} + +// Warning assignament should take a const mesh in input +/** Assignment operator for mesh. The mesh content is losed. +*/ +inline MMTYPE & operator = (MMTYPE & m ) +{ + Clear(); + SelectedMerge(m,true); + return *this; +} +/// The incremental mark +int imark; + +/** Check if the vertex incremental mark matches the one of the mesh. + @param v Vertex pointer +*/ +inline bool IsMarked( MVTYPE * const v ) const { return v->IMark() == imark; } +/** Check if the face incremental mark matches the one of the mesh. + @param v Face pointer +*/ +inline bool IsMarked( MFTYPE * const f ) const { return f->IMark() == imark; } +/** Set the vertex incremental mark of the vertex to the one of the mesh. + @param v Vertex pointer +*/ +inline void Mark( MVTYPE * const v ) const { v->IMark() = imark; } +/** Set the face incremental mark of the vertex to the one of the mesh. + @param v Vertex pointer +*/ +inline void Mark( MFTYPE * const f ) const { f->IMark() = imark; } +/// Unmark the mesh +inline void UnMarkAll() { ++imark; } + + +/** Function to add n vertices to the mesh. The second parameter hold a vector of + pointers to pointer to elements of the mesh that should be updated after a + possible vector realloc. + @param n Il numero di vertici che si vuole aggiungere alla mesh. + @param local_var Vettore di variabili locali che rappresentano puntatori a vertici. + restituisce l'iteratore al primo elemento aggiunto. +*/ +vertex_iterator AddVertices(int n, vector &local_var) +{ + vertex_iterator oldbegin, newbegin; + oldbegin = vert.begin(); + vertex_iterator last=vert.end(); + if(vert.empty()) last=0; // if the vector is empty we cannot find the last valid element + else --last; + unsigned int siz=0; +#ifdef __STL_CONFIG_H +if(last!=0) distance(vert.begin(),last,siz); +#else +if(last!=0) siz=distance(vert.begin(),last); +#endif + for(int i=0; i local_var; + return AddVertices(n,local_var); +} + +/** Function to add n faces to the mesh. + @param n Il numero di facce che si vuole aggiungere alla mesh +*/ +face_iterator AddFaces(int n) +{ + vector local_var; + return AddFaces(n,local_var); +} +/** Function to add n faces to the mesh. + NOTA: Aggiorna fn; + The second parameter hold a vector of + pointers to pointer to elements of the mesh that should be updated after a + possible vector realloc. + @param n Facce da aggiungere + @param local_var Vettore di variabili locali che rappresentano puntatori a facce, occorre, + perche' questi valori siano consistenti, aggiornarli ogni qual volta venga eseguito un resize + del contenitore delle facce. +*/ +face_iterator AddFaces(int n, vector &local_var) +{ + face_iterator oldbegin, newbegin; + oldbegin = face.begin(); + face_iterator last=face.end(); + if(face.empty()) last=0; + else last--; + + unsigned int siz=0; +#ifdef __STL_CONFIG_H + if(last!=0) distance(face.begin(),last,siz); +#else + if(last!=0) siz=distance(face.begin(),last); +#endif + MFTYPE dum; + dum.Supervisor_Flags()=0; + for(int i=0; i::iterator jit; + for(jit=local_var.begin(); jit!=local_var.end(); ++jit) + if((**jit) !=0 ) **jit = **jit-&*oldbegin+&*newbegin; + + // deve restituire l'iteratore alla prima faccia aggiunta; + if(last!=0) + { + last = face.begin(); + advance(last,siz+1); + } + else last=face.begin(); + } + else // + { assert(newbegin == oldbegin); + // se non e'cambiato lo spazio (vector abbastanza grande o lista) + if(last==0) last = face.begin(); // se il vettore era vuoto si restituisce begin + else advance(last,1); // altrimenti il primo dopo quello che era in precedenza l'ultimo valido. + } + + return last; + +} + + +/// Calcolo del volume di una mesh chiusa +scalar_type Volume() +{ + + face_iterator f; + int j,k; + scalar_type V = 0; + vectorial_type T,N,B; + + for(f = face.begin(); f!=face.end(); ++f) + { + for(j = 0; j < 3; ++j) + { + /*calcolo tangente, normale e binormale (6 volte)*/ + k = (j+1)%3; + T = (*f).V(k)->P() - (*f).V(j)->P(); + T.Normalize(); + T = ( (*f).V( k )->P() - (*f).V(j)->P() ) ^ + ( (*f).V((k+1)%3)->P() - (*f).V(j)->P() ) ; + B.Normalize(); + N = T ^ B; + + vectorial_type pj = (*f).V(j)->P(); + vectorial_type pk = (*f).V(k)->P(); + + + V += (pj* T )*(pj*N)*(pj*B); + V += (pk*(-T))*(pk*N)*(pk*B); + } + } + return V/6; +} + + +}; // end class Mesh + + +} // end namespace + + +#endif + diff --git a/vcg/complex/trimesh/compute.h b/vcg/complex/trimesh/compute.h new file mode 100644 index 00000000..55b31c03 --- /dev/null +++ b/vcg/complex/trimesh/compute.h @@ -0,0 +1,115 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +template +class TriMeshCompute +{ +public: +static void FaceNormalRW(ComputeMeshType &m, bool normalize=false) +{ + if( !m.HasPerFaceNormal()) return; + + face_iterator f; + bool cn = true; + + if(normalize) + { + for(f=m.face.begin();f!=m.face.end();++f) + if( !(*f).IsD() && (*f).IsRW() ) + { + for(int j=0; j<(*f).size(); ++j) + if( !(*f).V(j)->IsR()) cn = false; + if( cn ) (*f).ComputeNormalizedNormal(); + cn = true; + } + } + else + { + for(f=m.face.begin();f!=m.face.end();++f) + if( !(*f).IsD() && (*f).IsRW() ) + { + for(int j=0; j<(*f).size(); ++j) + if( !(*f).V(j)->IsR()) cn = false; + + if( cn ) + (*f).ComputeNormal(); + cn = true; + } + } +} + + +static void NormalizedFaceNormal(ComputeMeshType &m) +{ + ComputeFaceNormal(true); +} + + +/// Calculates the vertex normal +static void NormalizedVertexNormal(ComputeMeshType &m) +{ + VertexNormal(true); +} +/// Calculates the vertex normal +static void VertexNormal(ComputeMeshType &m, bool normalize=false) +{ + if( m.HasPerVertexNormal()) + { + vertex_iterator vi; + + for(vi=vert.begin();vi!=vert.end();++vi) + if( !(*vi).IsDeleted() && (*vi).IsRW() ) + (*vi).Normal() = vectorial_type(0,0,0); + + face_iterator f; + + for(f=face.begin();f!=face.end();++f) + if( !(*f).IsDeleted() && (*f).IsR() ) + { + vectorial_type t = (*f).Normal(); + + for(int j=0; j<(*f).size(); ++j) + if( !(*f).V(j)->IsD() && (*f).V(j)->IsR() && (*f).V(j)->IsW() ) + (*f).V(j)->Normal() += t; + } + if(normalize) + for(vi=vert.begin();vi!=vert.end();++vi) + if( !(*vi).IsDeleted() && (*vi).IsRW() ) + (*vi).Normal().Normalize(); + } +} +void ComputeE() +{ + face_iterator f; + + for(f = face.begin(); f!=face.end(); ++f) + (*f).ComputeE(); +} + +}; // end class diff --git a/vcg/complex/trimesh/geodesic.h b/vcg/complex/trimesh/geodesic.h new file mode 100644 index 00000000..474901e0 --- /dev/null +++ b/vcg/complex/trimesh/geodesic.h @@ -0,0 +1,1050 @@ +/*#*************************************************************************** + * Geodesic.h o o * + * o o * + * Visual Computing Group _ O _ * + * IEI Institute, CNUCE Institute, CNR Pisa \/)\/ * + * /\/| * + * Copyright(C) 1999 by Paolo Cignoni, | * + * All rights reserved. \ * + * * + * Permission to use, copy, modify, distribute and sell this software and * + * its documentation for any purpose is hereby granted without fee, provided * + * that the above copyright notice appear in all copies and that both that * + * copyright notice and this permission notice appear in supporting * + * documentation. the author makes no representations about the suitability * + * of this software for any purpose. It is provided "as is" without express * + * or implied warranty. * + * * + ***************************************************************************#*/ +/*#************************************************************************** + History + + 2002 Apr 01 First Working release copiata, ripulita e templatata dal plyvcg(pc) + Dic 27 Aggiunta classe Geo. First release (gano) + 2003 Jan 10 Aggiunto controllo IsD() in ComputeGeodesicQuality() (pc) + Feb 02 Cambiato l'algoritmo e aggiunta FindPath + May 05 Corretti un po' di bug sui casi limite e templatata la BuildSP + Aggiunta SelectRegion + May 13 Variazioni alla SelectRegion per la selezione di triangoli + in casi limite (longobardi) + May 19 Corretto baco in BuildSP, aggiunto template, ripulito un po' (gano) + July 3 *** aggiornati i tipi di meshPos alla nuova versione + aggiunta SelectRegionFF (gano) + 16 Aggiunto namespace + Nov 14 Corretto bug nella ComputeGeodesicQuality. (pc) + *#**************************************************************************/ + +#ifndef __VCG_GEODESIC__ +#define __VCG_GEODESIC__ + +namespace vcg { + +template +class VQualityHeap +{ +public: + float q; + MESH::vertex_pointer p; + inline VQualityHeap( MESH::vertex_pointer np ) + { + q = np->Q(); + p = np; + } + // Attenzione il minore e' maggiore + inline bool operator < ( const VQualityHeap & vq ) const { return q > vq.q; } + inline bool operator == ( const VQualityHeap & vq ) const { return q == vq.q; } + inline bool operator > ( const VQualityHeap & vq ) const { return q < vq.q; } + inline bool operator != ( const VQualityHeap & vq ) const { return q != vq.q; } + inline bool operator <= ( const VQualityHeap & vq ) const { return q >= vq.q; } + inline bool operator >= ( const VQualityHeap & vq ) const { return q <= vq.q; } + inline bool is_valid() const { return q==p->Q(); } +}; + +// Calcola la qualita' come distanza geodesica dal bordo della mesh. +// Robusta funziona anche per mesh non manifold. +// La qualita' memorizzata indica la distanza assoluta dal bordo della mesh. +// Nota prima del 13/11/03 in alcuni casi rari SPT andava in loop perche' poteva capitare +// che per approx numeriche ben strane pw->Q() > pv->Q()+d ma durante la memorizzazione +// della nuova distanza essa rimanesse uguale a prima. Patchato rimettendo i vertici nello +// heap solo se migliorano la distanza di un epsilon == 1/100000 della mesh diag. + +template +void ComputeGeodesicQuality(MESH &m, bool per_face ) // R1 +{ + //Requirements + assert(m.HasVFTopology()); + assert(m.HasPerVertexQuality()); + if(per_face) assert(m.HasPerFaceQuality()); + + vector > heap; + MESH::vertex_iterator v; + MESH::face_iterator f; + int j; + + m.VFTopology(); // Creazione adiacenza vertici + m.ComputeBorderFlagVF(); // Marco gli edge di bordo + + for(v=m.vert.begin();v!=m.vert.end();++v) + (*v).Q() = -1; + for(f=m.face.begin();f!=m.face.end();++f) // Inserisco nell'heap i v di bordo + if(!(*f).IsD()) + for(j=0;j<3;++j) + if( (*f).IsB(j) ) + { + for(int k=0;k<2;++k) + { + MESH::vertex_pointer pv = (*f).V((j+k)%3); + if( pv->Q()==-1 ) + { + pv->Q() = 0; + heap.push_back(VQualityHeap(pv)); + } + } + } + + const MESH::scalar_type loc_eps=m.bbox.Diag()/MESH::scalar_type(100000); + while( heap.size()!=0 ) // Shortest path tree + { + MESH::vertex_pointer pv; + pop_heap(heap.begin(),heap.end()); + if( ! heap.back().is_valid() ) + { + heap.pop_back(); + continue; + } + pv = heap.back().p; + heap.pop_back(); + MESH::vedgepos_type x; + for( x.f = pv->Fp(), x.z = pv->Zp(); x.f!=0; x.NextF() ) + { + for(int k=0;k<2;++k) + { + MESH::vertex_pointer pw; + float d; + if(k==0) pw = x.f->V1(x.z); + else pw = x.f->V2(x.z); + d = Distance(pv->P(),pw->P()); + if( pw->Q()==-1 || pw->Q() > pv->Q()+d + loc_eps) + { + pw->Q() = pv->Q()+d; + heap.push_back(VQualityHeap(pw)); + push_heap(heap.begin(),heap.end()); + } + } + } + } + + for(v=m.vert.begin();v!=m.vert.end();++v) + if(v->Q()==-1) + v->Q() = 0; + + if(per_face) + { + for(f=m.face.begin();f!=m.face.end();++f) + (*f).Q() = ((*f).V(0)->Q() + (*f).V(1)->Q() + (*f).V(2)->Q())/3; + } +} + + + + + +// ************************************** classe GEo +// first release +// Modo d'uso +// Geo geo(m); //dichiare e definisce +// m.VFTopology(); +// geo.FartestPoint(....);//dato un insieme di punti a distanza 0 trova +// // il punto piu'lontano sulla superficie (una versione ritorna anche il +// // cammino) +// +// geo.FindPath(...); // determina il cammino minimo tra due vertici +// m.ComputeVBorderFlag(); (SOLO SE SI USA MostInternal) +// geo.MostInternal(....);// punto piu'lontano dal bordo: invoca FartestPoint passando +// // tutti i vertici di bordo come insieme di partenza. +// // NB: questa fa la stessa cosa di ComputeGeodesicQuality +// // ma non scrive sul campo qualita' del vertice +// +// +// ***************************************** + +template +class Geo{ + + public: + + Geo( TMESH & m):TD(m.vert),TDP(m.vert),TDS(m.vert),TDF(m.face),M(m) + {lessThan.pt = this;} + ~Geo(){} + + TMESH &M; + template + struct TempData{ + TempData(){} + TempData(const double & d_){d=d_;visited=false;} + double d; + bool visited; + }; + + template + struct TempDataPath{ + TempDataPath(){} + TempDataPath(const TMESH::vertex_pointer & parent_){parent = parent_;} + TMESH::vertex_pointer parent; + }; + + template + struct TempDataSource{ + TempDataSource(){} + TempDataSource(const TMESH::vertex_pointer & source_){source = source_;} + TMESH::vertex_pointer source; + }; + + TempData_vect > TD; + TempData_vect > TDP; + TempData_vect > TDS; + + + template + struct pred: public binary_function{ + PT * pt; + bool operator()(const VERTEX_POINTER& v0, const VERTEX_POINTER& v1) const + {return (pt->TD[v0].d > pt->TD[v1].d);} + }; + + pred > lessThan; + + template + struct VPath{ + VPath(VERTEX_POINTER v0,VERTEX_POINTER v1, double dist):pathLenght(dist){ + sources[0] = v0;sources[1] = v1; + } + VERTEX_POINTER sources[2]; + double pathLenght; + }; + + typedef typename VPath Path; + + template + TMESH::vertex_pointer BuildSP( + deque &path, + vector & _frontier, + double & max_distance + ) + { + TMESH::vertex_pointer curr=NULL,fartest=NULL,pw1; + bool isLeaf; + Path shortestPath(NULL,NULL,-1.0); + TMESH::vertex_pointer sources[2]; + assert(!CONNECT_TWO_SOURCES || (_frontier.size()==2)); + + if(CONNECT_TWO_SOURCES){ + if( _frontier.size() != 2) return (TMESH::vertex_pointer)0; + if( _frontier[0] == _frontier[1]) return (TMESH::vertex_pointer)0; + sources[0] = _frontier[0]; + sources[1] = _frontier[1]; + } + + vector frontier; + frontier.clear(); + + //Requirements + assert(M.HasVFTopology()); + + if(M.vn==0) return NULL; + + list children; + bool toQueue; + + TD.Start(TempData(-1.0)); + + if(RETURN_PATH) + TDP.Start(TempDataPath(NULL)); + + list::iterator is; + deque leaves; + vector > expansion; + + vector ::const_iterator ifr; + TMESH::vedgepos_type x;int k; + TMESH::vertex_pointer pw; + + for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr){ + TD[*ifr].visited= true; + TD[*ifr].d = 0.0; + } + if(CONNECT_TWO_SOURCES){ + TDS.Start(TempDataSource(NULL)); + for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr) + TDS[*ifr].source= (*ifr); + } + + for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr) + { + if(RETURN_PATH) + TDP[*ifr].parent=NULL; + // determina la distanza dei vertici della fan + + for( x.f = (*ifr)->Fp(), x.z = (*ifr)->Zp(); x.f!=0; x.NextF() ) + for(k=0;k<2;++k) + { + if(k==0) pw = x.f->V1(x.z); + else pw = x.f->V2(x.z); + + + + if(SKIP_SELECTED) + if(pw->IsS()) + continue; + + if(CONNECT_TWO_SOURCES) + { + if( (TDS[pw].source != NULL)&&(TDS[pw].source!= TDS[*ifr].source)){ + double l = TD[pw].d + Distance((*ifr)->cP(),pw->cP()); + if( (shortestPath.pathLenght== -1)||(l < shortestPath.pathLenght)) + shortestPath = Path((*ifr),pw,l ); + } + } + + if(TD[pw].d ==-1){ + TD[pw].d = Distance(pw->cP(),(*ifr)->cP()); + frontier.push_back(pw); + + if(RETURN_PATH) + if(!TD[pw].visited) + TDP[pw].parent= (*ifr); + + if(CONNECT_TWO_SOURCES) + TDS[pw].source = (*ifr); + + } + } + } + + if(CONNECT_TWO_SOURCES) + if(shortestPath.pathLenght != -1) + goto found; + + + double curr_d,d_curr = 0.0; + max_distance=0.0; + + make_heap(frontier.begin(),frontier.end(),lessThan); + while(!frontier.empty()){ + expansion.clear(); + pop_heap(frontier.begin(),frontier.end(),lessThan); + curr = frontier.back(); + frontier.pop_back(); + d_curr = TD[curr].d; + TD[curr].visited=true; + + if(CONNECT_TWO_SOURCES) + { + double otherDist; + + if(shortestPath.pathLenght!= -1) + { + if( TDS[curr].source == TDS[shortestPath.sources[0]].source) + otherDist = TD[shortestPath.sources[1]].d; + else + otherDist = TD[shortestPath.sources[0]].d; + + if (d_curr > shortestPath.pathLenght-otherDist) + continue; + } + } + isLeaf = (!FARTEST_ON_BORDER || curr->IsB()); + + TMESH::vedgepos_type x;int k; + + for( x.f = curr->Fp(), x.z = curr->Zp(); x.f!=0; x.NextF() ) + for(k=0;k<2;++k) + { + if(k==0) { + pw = x.f->V1(x.z); + pw1=x.f->V2(x.z); + } + else { + pw = x.f->V2(x.z); + pw1=x.f->V1(x.z); + } + const double & d_pw1 = TD[pw1].d; + + if(SKIP_SELECTED) + if(pw->IsS()) + continue; + + if((TD[pw].visited && + (!CONNECT_TWO_SOURCES || (TDS[pw].source == TDS[curr].source)))) + continue; + + if(CONNECT_TWO_SOURCES){ + if( (TDS[pw].source!=TDS[curr].source) && (TDS[pw].source!=NULL)&& (TDS[curr].source!=NULL)){ + double l = TD[curr].d+ TD[pw].d + Distance(curr->cP(),pw->cP()); + if( (shortestPath.pathLenght == -1) || (shortestPath.pathLenght > l) ) + shortestPath = Path(curr,pw,l); + continue; + } + if( (TDS[pw1].source!=TDS[curr].source) && (TDS[pw1].source!=NULL)&& (TDS[curr].source!=NULL)){ + double l = TD[curr].d+ TD[pw1].d + Distance(curr->cP(),pw1->cP()); + if( (shortestPath.pathLenght == -1) || (shortestPath.pathLenght > l) ) + shortestPath = Path(curr,pw1,l); + + continue; + } + } + if((!TD[pw1].visited ) ||(d_pw1 == 0.0) ) + continue; + +#ifdef _DEBUG + if(CONNECT_TWO_SOURCES){ + assert(TDS[pw1].source == TDS[curr].source); + assert((TDP[curr].parent == NULL) || TDS[curr].source == TDS[TDP[curr].parent].source); + } + assert( TD[pw1].d != -1); + assert( TD[pw1].d != 0.0); + assert( (curr!=pw) && (pw!=pw1) && (pw1 != curr)); + assert(d_pw1!=-1.0); +#endif + + //************** calcolo della distanza di pw in base alle distanze note di pw1 e curr + //************** sapendo che (curr,pw,pw1) e'una faccia della mesh + //************** (vedi figura in file distance.gif) + Point3 w_c = pw->cP()- curr->cP(); + Point3 w_w1 = pw->cP()- pw1->cP(); + Point3 w1_c = pw1->cP()- curr->cP(); + + double ew_c = (w_c).Norm(); + double ew_w1 = (w_w1).Norm(); + double ec_w1 = (w1_c).Norm(); + double alpha,alpha_, beta,beta_,theta,h,delta,s,a,b; + + alpha = acos((w_c*w1_c)/(ew_c*ec_w1)); + s = (d_curr + d_pw1+ec_w1)/2; + a = s/ec_w1; + b = a*s; + alpha_ = 2*acos ( min(1.0,sqrt( (b- a* d_pw1)/d_curr))); + + if ( alpha+alpha_ > M_PI){ + curr_d = d_curr + ew_c; + }else + { + beta_ = 2*acos ( min(1.0,sqrt( (b- a* d_curr)/d_pw1))); + beta = acos((w_w1)*(-w1_c)/(ew_w1*ec_w1)); + + if ( beta+beta_ > M_PI){ + curr_d = d_pw1 + ew_w1; + } + else + { + theta = M_PI-alpha-alpha_; + delta = cos(theta)* ew_c; + h = sin(theta)* ew_c; + curr_d = sqrt( pow(h,2)+ pow(d_curr + delta,2)); + } + } + //************************************************************************************** + + toQueue = (TD[(pw)].d==-1); + + if(toQueue){// se non e'gia' in coda ce lo mette + if(RETURN_PATH)//aggiorna il puntatore al genitore se richiesto + { + if(( TD[curr].d + ew_c) < (d_pw1 + ew_w1)) + TDP[(pw)].parent = curr; + else + TDP[(pw)].parent = pw1; + assert(curr_d!=0.0); + } + + if(CONNECT_TWO_SOURCES) + TDS[pw].source = TDS[TDP[pw].parent].source; + + expansion.push_back(pair(pw,curr_d)); + isLeaf =false; + }else{ + if( TD[pw].d > curr_d ) + { + if(RETURN_PATH) + if(( d_curr + ew_c) < (d_pw1 + ew_w1)) + TDP[(pw)].parent = curr; + else + TDP[(pw)].parent = pw1; + + TD[(pw)].d = curr_d; + if(CONNECT_TWO_SOURCES) + TDS[pw].source = TDS[curr].source; + + assert(!((TD[pw].visited && (TDS[pw].source != TDS[curr].source)))); + + isLeaf =false; + } + } + } + + if(isLeaf){ + if(d_curr > max_distance){ + max_distance = d_curr; + fartest = curr; + } + } + + vector > ::iterator i; + + for(i = expansion.begin(); i!= expansion.end(); ++i){ + if(TD[(*i).first].d== -1.0){ + TD[(*i).first].d = (*i).second; + frontier.push_back((*i).first); + push_heap(frontier.begin(),frontier.end(),lessThan); + } + } + }// end while: la frontiera e'vuota + + + if(CONNECT_TWO_SOURCES) + if(shortestPath.pathLenght == -1)// i path non si sono incontrati + return NULL; + +found: +// scrivi le distanze sul campo qualita' (nn: farlo parametrico) + TMESH::vertex_iterator vi; + for(vi = M.vert.begin(); vi != M.vert.end(); ++vi) + (*vi).Q() = TD[&(*vi)].d; + + if(RETURN_PATH) + { + TMESH::vertex_pointer s; + if(CONNECT_TWO_SOURCES) + { + curr = shortestPath.sources[0]; + pw = shortestPath.sources[1]; + + if(TDS[curr].source != sources[0]) swap(curr,pw); + + // curr e' il vertice estremo di una sorgente + // pw quello dell'altra + max_distance = TD[curr].d+ TD[pw].d + Distance(curr->cP(),pw->cP()); + s = TDS[pw].source; + while(pw!=NULL){// pw->Q() = 2.0 *max_distance; + assert(TDS[pw].source == s); + path.push_front(pw); + pw = TDP[pw].parent; + } + s=TDS[curr].source; + } + while(curr!=NULL){ + //curr->Q() = max_distance; + assert(!CONNECT_TWO_SOURCES || (TDS[curr].source == s)); + path.push_back(curr); + curr = TDP[curr].parent; + } + } + + TD.Stop(); + TDP.Stop(); + TDS.Stop(); + return CONNECT_TWO_SOURCES? 0 : fartest; +} + +// SelectRegion: dato un vertice esegue una visita di superficie. +// Un ramo della visita si ferma quando incontra un vertice marcato S(elected) +// Serve per selecionare delle regioni delimitate da liste di vertici gia' definite +template +bool SelectRegion(int iter,STL_CONT_VERT & frontier, STL_CONT_FACE & result ) { + //result.clear(); + int i =0 ; + TMESH::vertex_pointer curr=NULL; + if (!USE_FLAG_V) + TD.Start(TempData(-1.0)); + + //Requirements + assert(M.HasVFTopology()); + + if(M.vn==0) return false; + + + bool toQueue; + TMESH::EdgePos x;int k; + TMESH::vertex_pointer pw; + + while((!frontier.empty())&&( LIMITED?(iSetV(); + else + TD[curr].visited = true; + + for( x.f = curr->Fp(), x.z = curr->Zp(); x.f!=0; x.NextF() ) + for(k=0;k<2;++k) + { + if(k==0) pw = x.f->V1(x.z); + else pw = x.f->V2(x.z); + + if(!(x.f)->IsS()) + result.push_back(x.f); + + if(!pw->IsV() && !pw->IsS()) + frontier.push_back(pw); + } + } + + if (!USE_FLAG_V) + TD.Stop(); + + return frontier.empty(); + +} + +// versione temporanea: data una faccia e un vertice seleziona la regione +// procedendo per adiacenze faccia-faccia + +struct TempDataFace{ + TempDataFace():front(0){} + TempDataFace(const short int & _front):front(_front){} + short int front; + bool IsV(const int &i){ + return (front & (1< TDF; + +// versione rozza: non fa region growing, se si limita il numero di iterazioni +// puo'terminare con un insieme di facce a genus diverso da zero +template +bool SelectRegionFF(int iter,STL_CONT_FACE & frontier, STL_CONT_FACE & result ) { + //result.clear(); + int i =0, h=0 ; + TDF.Start(TempDataFace(0)); + + TMESH::face_pointer curr= NULL; + + if (!USE_FLAG_V) + TD.Start(TempData(-1.0)); + //Requirements + assert(M.HasFFTopology()); + + if(M.vn==0) return false; + + bool toQueue; + TMESH::vedgepos_type x;int k; + TMESH::vertex_pointer pw; + + while((!frontier.empty())&&( LIMITED?(iSetV(); + for(h = 0; h<3;++h){ + TMESH::face_type* iii =(TMESH::face_type* )curr->F(h); + TempDataFace & tdf = TDF[iii]; + if( !tdf.IsV(curr->Z(h)) && (curr->F(h) != curr)){ + if(!(curr->F(h))->IsS()) { + result.push_back((TMESH::face_type* )curr->F(h)); + frontier.push_back((TMESH::face_type* )curr->F(h)); + } + tdf.SetV(curr->Z(h)); + } + } + } + + TDF.Stop(); + return frontier.empty(); + } + + +// multiple sorgenti - no max iter +template +bool SelectRegion(STL_CONT_VERT & frontier, STL_CONT_FACE & result){ + return SelectRegion + (STL_CONT_VERT & frontier, STL_CONT_FACE & result ); + } + +// multiple sorgenti - max iter +template +bool SelectRegion(STL_CONT_VERT & frontier, STL_CONT_FACE & result, int iter){ + return SelectRegion + (iter,STL_CONT_VERT & frontier, STL_CONT_FACE & result); + } + +// singola sorgente - max iter +template +bool SelectRegion(const TMESH::vertex_pointer & v0, STL_CONT_FACE & result, int iter) { + + STL_CONT_VERT frontier; + frontier.push_back(v0); + return SelectRegion( iter, frontier,result); + } + +// singola sorgente - no max iter +template +bool SelectRegion(const TMESH::vertex_pointer & v0, STL_CONT_FACE & result) { + + STL_CONT_VERT frontier; + frontier.push_back(v0); + return SelectRegion( 0, frontier,result); + } + + +template +struct cp{ + cp(){}; + cp(TMESH::vertex_pointer v0_,TMESH::vertex_pointer v1_):v0(v0_),v1(v1_){}; + TMESH::vertex_pointer v0,v1; + const bool operator != (const cp & other)const { + return ( ( v0 != other.v0) || ( v1 != other.v1)); + } + + const bool operator < (const cp & other)const { + return ( ( v0 == other.v0)? ( v1 < other.v1):v0 < other.v0); + } + }; + +set > connected; +bool AreConn(TMESH::vertex_pointer v0,TMESH::vertex_pointer v1){ + return (connected.find(cp(v0,v1))!=connected.end()); + } +void Conn(TMESH::vertex_pointer v0,TMESH::vertex_pointer v1){ + connected.insert(cp(v0,v1)); + connected.insert(cp(v1,v0)); + } + + +void Delaunay( + deque &path, + vector & _frontier) + { + TMESH::vertex_pointer s; + bool isLeaf,found=false; + vector frontier; + frontier.clear(); + //Requirements + assert(M.HasVFTopology()); + TMESH::vertex_iterator ii; + list children; + TMESH::vertex_pointer curr = NULL,fartest,pw1; + bool toQueue; + + TD.Start(TempData(-1.0)); + TDP.Start(TempDataPath(NULL)); + + list::iterator is; + deque leaves; + vector > expansion; + + vector ::const_iterator ifr; + TMESH::EdgePos x;int k; + TMESH::vertex_pointer pw; + + for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr){ + TD[*ifr].visited= true; + TD[*ifr].d = 0.0; + } + + TDS.Start(TempDataSource(NULL)); + for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr) + TDS[*ifr].source= (*ifr); + + for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr) + { + + TDP[*ifr].parent=NULL; + // determina la distanza dei vertici della fan + for( x.f = (*ifr)->Fp(), x.z = (*ifr)->Zp(); x.f!=0; x.NextF() ) + for(k=0;k<2;++k) + { + if(k==0) pw = x.f->V1(x.z); + else pw = x.f->V2(x.z); + + if(TD[pw].d ==-1){ + TD[pw].d = Distance(pw->cP(),(*ifr)->cP()); + frontier.push_back(pw); + + if(TD[pw].visited) + TDP[pw].parent= (*ifr); + TDS[pw].source = (*ifr); + } + } + } + + make_heap(frontier.begin(),frontier.end(),lessThan); + double curr_d,d_curr = 0.0; + + vector:: iterator iv; + while(!frontier.empty()){ + + expansion.clear(); + + pop_heap(frontier.begin(),frontier.end(),lessThan); + curr = frontier.back(); + frontier.pop_back(); + d_curr = TD[curr].d; + TD[curr].visited=true; + + isLeaf = true; + + TMESH::EdgePos x;int k; + + for( x.f = curr->Fp(), x.z = curr->Zp(); x.f!=0; x.NextF() ) + for(k=0;k<2;++k) + { + if(k==0) { + pw = x.f->V1(x.z); + pw1=x.f->V2(x.z); + } + else { + pw = x.f->V2(x.z); + pw1=x.f->V1(x.z); + } + const double & d_pw1 = TD[pw1].d; + + if((!TD[pw1].visited ) ||(d_pw1 == 0.0) || + (TD[pw].visited && (TDS[pw].source == TDS[curr].source)) + ) + continue; + + if( (TDS[pw].source!=TDS[curr].source) && (TDS[pw].source!=NULL)&& (TDS[curr].source!=NULL) + ) + if(AreConn(TDS[pw].source,TDS[curr].source)) continue; + else + found=true; + + if( (TDS[pw1].source!=TDS[curr].source) && (TDS[pw1].source!=NULL)&& (TDS[curr].source!=NULL)) + { + if(AreConn(TDS[pw1].source,TDS[curr].source)) + continue; + else + { + pw = pw1; + found = true; + } + } + if(found){ + s = TDS[pw].source; + TMESH::vertex_pointer v0 = pw,v1=curr; + while(v0!=NULL){ + //v0->Q() = 2.0; + assert(TDS[v0].source == s); + path.push_front(v0); + v0 = TDP[v0].parent; + } + + s=TDS[v1].source; + while(v1!=NULL){ + //v1->Q() = 10; + assert(TDS[v1].source == s); + path.push_back(v1); + v1 = TDP[v1].parent; + } + Conn(TDS[pw].source,TDS[curr].source); + assert(AreConn(TDS[pw].source,TDS[curr].source)); + found = false; + continue; + } + + + assert(TDS[pw1].source == TDS[curr].source); + assert((TDP[curr].parent == NULL) || TDS[curr].source == TDS[TDP[curr].parent].source); + assert( TD[pw1].d != -1); + assert( TD[pw1].d != 0.0); + assert( (curr!=pw) && (pw!=pw1) && (pw1 != curr)); + assert(d_pw1!=-1.0); + + //************** calcolo della distanza di pw in base alle distanze note di pw1 e curr + //************** sapendo che (curr,pw,pw1) e'una faccia della mesh + //************** (vedi figura in file distance.gif) + Point3 w_c = pw->cP()- curr->cP(); + Point3 w_w1 = pw->cP()- pw1->cP(); + Point3 w1_c = pw1->cP()- curr->cP(); + + double ew_c = (w_c).Norm(); + double ew_w1 = (w_w1).Norm(); + double ec_w1 = (w1_c).Norm(); + double alpha,alpha_, beta,beta_,theta_c,theta,h,delta,s,a,b; + + alpha = acos((w_c*w1_c)/(ew_c*ec_w1)); + s = (d_curr + d_pw1+ec_w1)/2; + a = s/ec_w1; + b = a*s; + alpha_ = 2*acos ( min(1.0,sqrt( (b- a* d_pw1)/d_curr))); + + if ( alpha+alpha_ > M_PI){ + curr_d = d_curr + ew_c; + }else + { + beta_ = 2*acos ( min(1.0,sqrt( (b- a* d_curr)/d_pw1))); + beta = acos((w_w1)*(-w1_c)/(ew_w1*ec_w1)); + + if ( beta+beta_ > M_PI){ + curr_d = d_pw1 + ew_w1; + } + else + { + theta = M_PI-alpha-alpha_; + delta = cos(theta)* ew_c; + h = sin(theta)* ew_c; + curr_d = sqrt( pow(h,2)+ pow(d_curr + delta,2)); + } + } + //************************************************************************************** + + toQueue = (TD[(pw)].d==-1); + + if(toQueue){// se non e'gia' in coda ce lo mette + if(( TD[curr].d + ew_c) < (d_pw1 + ew_w1)) + TDP[(pw)].parent = curr; + else + TDP[(pw)].parent = pw1; + assert(curr_d!=0.0); + TDS[pw].source = TDS[curr].source; + + expansion.push_back(pair(pw,curr_d)); + isLeaf =false; + }else{ + if( TD[(pw)].d > curr_d ) + { + if(( d_curr + ew_c) < (d_pw1 + ew_w1)) + TDP[(pw)].parent = curr; + else + TDP[(pw)].parent = pw1; + + TD[(pw)].d = curr_d; + TDS[pw].source = TDS[curr].source; + isLeaf =false; + } + } + + vector > ::iterator i; + // unique(expansion.begin(),expansion.end()); + for(i = expansion.begin(); i!= expansion.end(); ++i){ + if(TD[(*i).first].d== -1.0){ + TD[(*i).first].d = (*i).second; + frontier.push_back((*i).first); + push_heap(frontier.begin(),frontier.end(),lessThan); + } + } + } +}// end while +// scrivi le distanze sul campo qualita' (nn: farlo parametrico) +/* +TMESH::vertex_iterator vi; + for(vi = M.vert.begin(); vi != M.vert.end(); ++vi) + (*vi).Q() = TD[&(*vi)].d; + */ + + + TD.Stop(); + TDP.Stop(); + TDS.Stop; + +} +public: +template +void FartestPoint( vector & fro,//insieme di vertici da cui trovare le distanze + TMESH::vertex_pointer & fartest, //punto piu'lontano + double & distance){ //distaza geodesica + deque _; + fartest = BuildSP (_,fro,distancee); + } +template +void FartestPoint( vector & fro, //insieme di vertici da cui trovare le distanze + TMESH::vertex_pointer & fartest, //punto piu'lontano + double & distance, //distaza geodesica + deque & path){// ritorna esplicitamente il cammino minimo + vector _; + fartest = BuildSP(path,fro,distance); + } +template +void FartestBPoint( vector & fro, //insieme di vertici da cui trovare le distanze + TMESH::vertex_pointer & fartest, //punto piu'lontano + double & distance, //distaza geodesica + deque & path){// ritorna esplicitamente il cammino minimo + vector _; + fartest = BuildSP(path,fro,distance); + } +template +void FartestBPoint( vector & fro, //insieme di vertici da cui trovare le distanze + TMESH::vertex_pointer & fartest, //punto piu'lontano + double & distance){ //distaza geodesica + deque _; + fartest = BuildSP(_,fro,distance); + } + +template +void FindPath( const TMESH::vertex_pointer & v0, //vertice di partenza + const TMESH::vertex_pointer & v1, //vertice cercato + deque & path, + double & dist) + { + vector fro; + fro.push_back(v0); + fro.push_back(v1); + BuildSP(path,fro,dist); + + // v0 = fro[0]; + // v1 = fro[1]; + } + +template +bool MostInternal( TMESH::vertex_pointer & v0, //ritorna il vertice piu'lontano da ogni punto sul bordo + TMESH::vertex_pointer & v1, // ritorna il vertice di bordo piu'vicino a v0 + double & distance, // distanza geodesica tra v0 e v1 + deque & path)// ritorna il path tra i due + { + vector border_vertices; + + TMESH::vertex_iterator ii; + double maxDistance = 0.0; + + for(ii = M.vert.begin(); ii != M.vert.end();++ii) + if((*ii).IsB()) + border_vertices.push_back(&(*ii)); + + if(border_vertices.empty()) return false; + + vector _; + + BuildSP(path,border_vertices,distance); + + if(path.empty()) return false; + v0 = *path.begin(); + v1 = path.back(); + return true; + } + +template +bool MostInternal( TMESH::vertex_pointer & v0, //ritorna il vertice piu'lontano da ogni punto sul bordo + TMESH::vertex_pointer & v1, // ritorna il vertice di bordo piu'vicino a v0 + double & distance// distanza geodesica tra v0 e v1 + ) + { + vector border_vertices; + deque path; + TMESH::vertex_iterator ii; + double maxDistance = 0.0; + + for(ii = M.vert.begin(); ii != M.vert.end();++ii) + if((*ii).IsB()) + border_vertices.push_back(&(*ii)); + + if(border_vertices.empty()) return false; + BuildSP(path,border_vertices,distance); + if(path.empty()) return false; + v0 = *path.begin(); + v1 = path.back(); + return true; + } + +}; +} +#endif \ No newline at end of file diff --git a/vcg/complex/trimesh/platonic.h b/vcg/complex/trimesh/platonic.h new file mode 100644 index 00000000..99770800 --- /dev/null +++ b/vcg/complex/trimesh/platonic.h @@ -0,0 +1,518 @@ +/*#*************************************************************************** + * VertexBase.h o o * + * o o * + * Visual Computing Group _ O _ * + * IEI Institute, CNUCE Institute, CNR Pisa \/)\/ * + * /\/| * + * Copyright(C) 1999 by Paolo Cignoni, Claudio Rocchini | * + * All rights reserved. \ * + * * + * Permission to use, copy, modify, distribute and sell this software and * + * its documentation for any purpose is hereby granted without fee, provided * + * that the above copyright notice appear in all copies and that both that * + * copyright notice and this permission notice appear in supporting * + * documentation. the author makes no representations about the suitability * + * of this software for any purpose. It is provided "as is" without express * + * or implied warranty. * + * * + *****************************************************************************/ + +/**************************************************************************** + History + + 2000 Jul 23 First Working release (only the tetrahedron) + 30 Added Octahedron + Aug 4 Added Icosahedron + Nov 22 Added Hexahedron (cube) + 2001 Apr 19 Added HalfOctahedron + 20 Added Square + May 16 Added Sphere Function (CR) (PC) + " Cone " " " + " Box (CR) + Jul 09 Aggiunta Build (CR) +****************************************************************************/ + + +#ifndef __VCGLIB_PLATONIC +#define __VCGLIB_PLATONIC + +#include + +template +void Tetrahedron(MESH_TYPE &in) +{ + in.vn=4; + in.fn=4; + in.vert.clear(); + in.face.clear(); + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + tp=MESH_TYPE::vectorial_type ( 1, 1, 1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1, 1,-1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1,-1, 1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 1,-1,-1); tv.P()=tp; in.vert.push_back(tv); + + vector index(in.vn); + + MESH_TYPE::face_type f;f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void Octahedron(MESH_TYPE &in) +{ + in.vn=6; + in.fn=8; + in.vert.clear(); + in.face.clear(); + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + tp=MESH_TYPE::vectorial_type ( 1, 0, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0, 1, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0, 0, 1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1, 0, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0,-1, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0, 0,-1); tv.P()=tp; in.vert.push_back(tv); + + vector index(in.vn); + + MESH_TYPE::face_type f;f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void Icosahedron(MESH_TYPE &in) +{ + MESH_TYPE::scalar_type L=(Sqrt(5.0)+1.0)/2.0; + MESH_TYPE::vectorial_type vv[12]={ + MESH_TYPE::vectorial_type ( 0, L, 1), + MESH_TYPE::vectorial_type ( 0, L,-1), + MESH_TYPE::vectorial_type ( 0,-L, 1), + MESH_TYPE::vectorial_type ( 0,-L,-1), + + MESH_TYPE::vectorial_type ( L, 1, 0), + MESH_TYPE::vectorial_type ( L,-1, 0), + MESH_TYPE::vectorial_type (-L, 1, 0), + MESH_TYPE::vectorial_type (-L,-1, 0), + + MESH_TYPE::vectorial_type ( 1, 0, L), + MESH_TYPE::vectorial_type (-1, 0, L), + MESH_TYPE::vectorial_type ( 1, 0,-L), + MESH_TYPE::vectorial_type (-1, 0,-L) + }; + + int ff[20][3]={ + {1,0,4},{0,1,6},{2,3,5},{3,2,7}, + {4,5,10},{5,4,8},{6,7,9},{7,6,11}, + {8,9,2},{9,8,0},{10,11,1},{11,10,3}, + {0,8,4},{0,6,9},{1,4,10},{1,11,6}, + {2,5,8},{2,9,7},{3,10,5},{3,7,11} + }; + + in.vn=12; + in.fn=20; + in.vert.clear(); + in.face.clear(); + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + for(int i=0;i index(in.vn); + + MESH_TYPE::face_type f;f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void Hexahedron(MESH_TYPE &in) +{ + in.vn=8; + in.fn=12; + in.vert.clear(); + in.face.clear(); + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + tp=MESH_TYPE::vectorial_type (-1,-1,-1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 1,-1,-1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1, 1,-1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 1, 1,-1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1,-1, 1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 1,-1, 1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1, 1, 1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 1, 1, 1); tv.P()=tp; in.vert.push_back(tv); + + vector index(in.vn); + + MESH_TYPE::face_type f;f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void HalfOctahedron(MESH_TYPE &in) +{ + in.vn=5; + in.fn=4; + in.vert.clear(); + in.face.clear(); + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + tp=MESH_TYPE::vectorial_type ( 1, 0, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0, 1, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0, 0, 1); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1, 0, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0,-1, 0); tv.P()=tp; in.vert.push_back(tv); + + vector index(in.vn); + + MESH_TYPE::face_type f;f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void Square(MESH_TYPE &in) +{ + in.vn=4; + in.fn=2; + in.vert.clear(); + in.face.clear(); + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + tp=MESH_TYPE::vectorial_type ( 1, 0, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0, 1, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (-1, 0, 0); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type ( 0,-1, 0); tv.P()=tp; in.vert.push_back(tv); + + vector index(in.vn); + + MESH_TYPE::face_type f;f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void Sphere(MESH_TYPE &in, const int subdiv = 3 ) +{ + Icosahedron(in); + in.ComputeBorderFlag(); + int lastsize = 0; + for(int i=0;i >(in,MidPoint(),0); + MESH_TYPE::vertex_iterator vi; + + for(vi = in.vert.begin()+lastsize;vi!=in.vert.end();++vi) + vi->P().Normalize(); + + lastsize = in.vert.size(); + } +} + + + /// r1 = raggio 1, r2 = raggio2, h = altezza (asse y) +template +void Cone( MESH_TYPE & in, + const MESH_TYPE::scalar_type r1, + const MESH_TYPE::scalar_type r2, + const MESH_TYPE::scalar_type h ) +{ + const int D = 24; + int i,b1,b2; + + if(r1==0 || r2==0) + { + in.vn=D+2; + in.fn=D*2; + } + else + { + in.vn=D*2+2; + in.fn=D*4; + } + + in.vert.clear(); + in.face.clear(); + + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + + tp=MESH_TYPE::vectorial_type ( 0,-h/2,0 ); + tv.P()=tp; + in.vert.push_back(tv); + + tp=MESH_TYPE::vectorial_type ( 0, h/2,0 ); + tv.P()=tp; + in.vert.push_back(tv); + + b1 = b2 = 2; + + if(r1!=0) + { + for(i=0;i index(in.vn); + + MESH_TYPE::face_type f; + f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void Box(MESH_TYPE &in, const MESH_TYPE::BOX_TYPE & bb ) +{ + in.vn=8; + in.fn=12; + in.vert.clear(); + in.face.clear(); + MESH_TYPE::vertex_type tv;tv.Supervisor_Flags()=0; + MESH_TYPE::vectorial_type tp; + tp=MESH_TYPE::vectorial_type (bb.min[0],bb.min[1],bb.min[2]); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (bb.max[0],bb.min[1],bb.min[2]); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (bb.min[0],bb.max[1],bb.min[2]); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (bb.max[0],bb.max[1],bb.min[2]); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (bb.min[0],bb.min[1],bb.max[2]); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (bb.max[0],bb.min[1],bb.max[2]); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (bb.min[0],bb.max[1],bb.max[2]); tv.P()=tp; in.vert.push_back(tv); + tp=MESH_TYPE::vectorial_type (bb.max[0],bb.max[1],bb.max[2]); tv.P()=tp; in.vert.push_back(tv); + + vector index(in.vn); + + MESH_TYPE::face_type f;f.Supervisor_Flags()=0; + + MESH_TYPE::vertex_iterator vi; + int j; + for(j=0,vi=in.vert.begin();j +void Build( M & in, const V & v, const F & f) +{ + in.vn = v.size(); + in.fn = f.size(); + + in.vert.clear(); + in.face.clear(); + + V::const_iterator vi; + + M::vertex_type tv; + tv.Supervisor_Flags()=0; + + for(vi=v.begin();vi!=v.end();++vi) + { + tv.P() = M::vectorial_type( + (M::scalar_type)(*vi).Ext(0), + (M::scalar_type)(*vi).Ext(1), + (M::scalar_type)(*vi).Ext(2) + ); + in.vert.push_back(tv); + } + + vector index(in.vn); + M::vertex_iterator j; + int k; + for(k=0,j=in.vert.begin();j!=in.vert.end();++j,++k) + index[k] = &*j; + + F::const_iterator fi; + + M::face_type ft; + ft.Supervisor_Flags()=0; + + for(fi=f.begin();fi!=f.end();++fi) + { + assert( (*fi)[0]>=0 ); + assert( (*fi)[1]>=0 ); + assert( (*fi)[2]>=0 ); + assert( (*fi)[0] + +#undef FACE_TYPE + +#undef __VCGLIB_FACE_FA + +#endif \ No newline at end of file diff --git a/vcg/simplex/face/with/fc.h b/vcg/simplex/face/with/fc.h new file mode 100644 index 00000000..4933330f --- /dev/null +++ b/vcg/simplex/face/with/fc.h @@ -0,0 +1,14 @@ +#ifndef __VCGLIB_FACE_FC_TYPE +#define __VCGLIB_FACE_FC_TYPE + +#define FACE_TYPE FaceFC + +#define __VCGLIB_FACE_FC + +#include + +#undef FACE_TYPE + +#undef __VCGLIB_FACE_FC + +#endif \ No newline at end of file diff --git a/vcg/simplex/face/with/fn.h b/vcg/simplex/face/with/fn.h new file mode 100644 index 00000000..439ccfb5 --- /dev/null +++ b/vcg/simplex/face/with/fn.h @@ -0,0 +1,14 @@ +#ifndef __VCGLIB_FACE_FN_TYPE +#define __VCGLIB_FACE_FN_TYPE + +#define FACE_TYPE FaceFN + +#define __VCGLIB_FACE_FN + +#include + +#undef FACE_TYPE + +#undef __VCGLIB_FACE_FN + +#endif \ No newline at end of file