Go to the documentation of this file.00001 #ifndef VCG_SYMMETRY_H
00002 #define VCG_SYMMETRY_H
00003
00004 #include <vcg/space/plane3.h>
00005 #include <vcg/space/index/grid_static_ptr.h>
00006 #include <vcg/complex/algorithms/closest.h>
00007 #include <vcg/complex/algorithms/create/platonic.h>
00008 #include <vcg/complex/algorithms/point_sampling.h>
00009
00010 namespace vcg {
00011 namespace tri {
00012
00013
00014
00015
00016
00017 template <class TriMeshType>
00018 class ExtrinsicPlaneSymmetry
00019 {
00020 typedef typename TriMeshType::VertexType VertexType;
00021 typedef typename TriMeshType::FaceType FaceType;
00022 typedef typename TriMeshType::CoordType CoordType;
00023 typedef typename TriMeshType::ScalarType ScalarType;
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 TriMeshType &tri_mesh;
00043
00044 CoordType AlignZeroTr;
00045
00046 std::vector<std::vector< ScalarType > > Weight;
00047
00048 std::vector<std::vector<std::pair<CoordType,CoordType> > > VotingPos;
00049
00050 std::vector<ScalarType> Votes;
00051
00052
00053
00054 TriMeshType *sphere;
00055
00056 typename vcg::GridStaticPtr<FaceType,ScalarType> GridSph;
00057
00058 ScalarType RadiusInterval;
00059 ScalarType MaxRadius;
00060 int radiusSph;
00061
00062 std::vector<std::pair<ScalarType,int> > SortedPlanes;
00063 std::vector<vcg::Plane3<ScalarType> > SymmetricPlanes;
00064
00065 int Bucket(const vcg::Plane3<ScalarType> &Pl)
00066 {
00067 ScalarType Offset=Pl.Offset();
00068 CoordType Direction=Pl.Direction();
00069 Direction.Normalize();
00071 int OffsetI=floor((Offset/RadiusInterval)+0.5);
00072 assert(OffsetI<radiusSph);
00074 ScalarType MaxD=sphere->bbox.Diag();
00075 ScalarType MinD;
00076 CoordType ClosePt;
00077 FaceType *choosen=NULL;
00078 choosen=vcg::tri::GetClosestFaceBase(*sphere,GridSph,Direction,MaxD,MinD,ClosePt);
00079 assert(choosen!=NULL);
00080 int IndexF=choosen-&(sphere->face[0]);
00082 int OffsetRadius=OffsetI * (sphere->face.size());
00083 return(OffsetRadius+IndexF);
00084 }
00085
00086 void Elect(CoordType p0,CoordType p1)
00087 {
00088 CoordType AvP=(p0+p1)/2.0;
00089 AvP-=AlignZeroTr;
00090 CoordType Direction=p0-p1;
00091 Direction.Normalize();
00092 vcg::Plane3<ScalarType> Pl;
00093 Pl.Init(AvP,Direction);
00094
00095 if (Pl.Offset()<0)
00096 {
00097 ScalarType Off=Pl.Offset();
00098 CoordType Dir=Pl.Direction();
00099 Pl.Set(-Dir,-Off);
00100 }
00101 int index=Bucket(Pl);
00102 assert(index>=0);
00103 assert(index<(int)Votes.size());
00104 ScalarType VoteValue=1;
00105 Votes[index]+=VoteValue;
00106 Weight[index].push_back(VoteValue);
00107 VotingPos[index].push_back(std::pair<CoordType,CoordType> (p0,p1));
00108 }
00109
00110 vcg::Plane3<ScalarType> GetInterpolatedPlane(int &Index)
00111 {
00113 CoordType AvDir=CoordType(0,0,0);
00114 ScalarType WSum=0;
00115 ScalarType AvOffset=0;
00116 for (size_t i=0;i<VotingPos[Index].size();i++)
00117 {
00118 CoordType p0=VotingPos[Index][i].first;
00119 CoordType p1=VotingPos[Index][i].second;
00120 ScalarType W=Weight[Index][i];
00121 CoordType Dir=(p0-p1);
00122 Dir.Normalize();
00123
00124 CoordType AvP=(p0+p1)/2.0;
00125 ScalarType Offset=AvP*Dir;
00126
00127
00128 if (Offset<0)
00129 {
00130 Offset=-Offset;
00131 Dir=-Dir;
00132 }
00133
00134 AvDir+=(Dir*W);
00135 AvOffset+=(Offset*W);
00136 WSum+=W;
00137 }
00138 AvDir.Normalize();
00139 AvOffset/=WSum;
00140 vcg::Plane3<ScalarType> Pl;
00141 Pl.Set(AvDir,AvOffset);
00142 return Pl;
00143 }
00144
00145 vcg::Plane3<ScalarType> GetBasePlane(int &Index)
00146 {
00148 int OffsetIndex=Index/sphere->face.size();
00149 ScalarType OffsetVal=OffsetIndex*RadiusInterval;
00150 int DirectionIndex=Index % sphere->face.size();
00151 CoordType PlaneDirection=(sphere->face[DirectionIndex].P(0)+
00152 sphere->face[DirectionIndex].P(1)+
00153 sphere->face[DirectionIndex].P(2))/3.0;
00154 PlaneDirection.Normalize();
00155 CoordType CenterPl=PlaneDirection*OffsetVal;
00156 CenterPl+=AlignZeroTr;
00157 vcg::Plane3<ScalarType> RetPl;
00158 RetPl.Init(CenterPl,PlaneDirection);
00159 return RetPl;
00160 }
00161
00162 void InitSymmetricPlanes(const int SubN=4)
00163 {
00164 assert(SortedPlanes.size()>0);
00165 SymmetricPlanes.clear();
00166 int BestN=pow((ScalarType)2,(ScalarType)SubN);
00167 if (BestN>=(int)SortedPlanes.size())BestN=SortedPlanes.size()-1;
00168 for (size_t j=SortedPlanes.size()-1;j>SortedPlanes.size()-1-SubN;j--)
00169 {
00170 int Index=SortedPlanes[j].second;
00171 SymmetricPlanes.push_back(GetInterpolatedPlane(Index));
00172 }
00173 }
00174
00175
00176 public:
00177
00178 void GetPlanes(std::vector<vcg::Plane3<ScalarType> > &Planes,int Num)
00179 {
00180 if (SymmetricPlanes.size()==0)return;
00181
00182 for (int i=0;i<Num;i++)
00183 Planes.push_back(SymmetricPlanes[i]);
00184 }
00185
00186 void Init(bool OnlyBorder=false,
00187 int SubDirections=4,
00188 int NumberBestPlanes=16)
00189 {
00190 if (OnlyBorder)
00191 {
00192 vcg::tri::UpdateTopology<TriMeshType>::FaceFace(tri_mesh);
00193 vcg::tri::UpdateFlags<TriMeshType>::FaceBorderFromFF(tri_mesh);
00194 vcg::tri::UpdateFlags<TriMeshType>::VertexBorderFromFaceBorder(tri_mesh);
00195 }
00196 AlignZeroTr=tri_mesh.bbox.Center();
00197
00199 if (sphere!=NULL)
00200 sphere->Clear();
00201 else
00202 sphere=new TriMeshType();
00203
00204
00205 vcg::tri::Sphere<TriMeshType>(*sphere,SubDirections);
00206 vcg::tri::UpdateBounding<TriMeshType>::Box(*sphere);
00207
00209 GridSph.Set(sphere->face.begin(),sphere->face.end());
00210
00212 ScalarType MaxRadius=tri_mesh.bbox.Diag()/2;
00213 int AreaSph=sphere->fn;
00214 radiusSph=ceil(sqrt((ScalarType)AreaSph/4.0*M_PI));
00215 RadiusInterval=MaxRadius/(ScalarType)radiusSph;
00216
00218 Votes.resize(radiusSph*sphere->fn,0);
00219
00220 Weight.resize(radiusSph*sphere->fn);
00221 VotingPos.resize(radiusSph*sphere->fn);
00222
00224 for (size_t i=0;i<tri_mesh.vert.size();i++)
00225 for (size_t j=i+1;j<tri_mesh.vert.size();j++)
00226 {
00227 VertexType *v0=&tri_mesh.vert[i];
00228 VertexType *v1=&tri_mesh.vert[j];
00229 if ((OnlyBorder)&&(!((v0->IsB())&&(v1->IsB()))))continue;
00230 Elect(v0->P(),v1->P());
00231 }
00232
00233 SortedPlanes.resize(Votes.size());
00234 for (size_t i=0;i<Votes.size();i++)
00235 SortedPlanes[i]=std::pair<ScalarType,int>(Votes[i],i);
00236
00237 std::sort(SortedPlanes.begin(),SortedPlanes.end());
00238
00239 InitSymmetricPlanes(NumberBestPlanes);
00240
00241 }
00242
00243 ExtrinsicPlaneSymmetry(TriMeshType &_tri_mesh):tri_mesh(_tri_mesh)
00244 {
00245 sphere=NULL;
00246 RadiusInterval=-1;
00247 radiusSph=-1;
00248 }
00249
00250 };
00251
00252 }
00253 }
00254 #endif