![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand * 00004 * Copyright (C) 2009 Sergio Galindo * 00005 * * 00006 * This program is free software: you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation, either version 3 of the License, or * 00009 * any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00018 ************************************************************************/ 00019 00020 #ifndef MECHSYS_DEM_SPECIAL_H 00021 #define MECHSYS_DEM_SPECIAL_H 00022 00023 // MechSys 00024 #include <mechsys/dem/distance.h> 00025 00026 // Stl 00027 #include <algorithm> 00028 00029 00030 inline void PolyhedraMP(Array<Vec3_t> & V, Array<Array <int> > & F, double & vol, Vec3_t & CM, Mat3_t & It) // Calculate mass properties of general polyhedra 00031 { 00032 vol = 0.0; 00033 CM = 0.0,0.0,0.0; 00034 It(0,0) = 0.0; 00035 It(1,1) = 0.0; 00036 It(2,2) = 0.0; 00037 It(1,0) = 0.0; 00038 It(2,0) = 0.0; 00039 It(2,1) = 0.0; 00040 It(0,1) = 0.0; 00041 It(0,2) = 0.0; 00042 It(1,2) = 0.0; 00043 Array<Face*> Faces; 00044 for (size_t i=0; i<F.Size(); i++) 00045 { 00046 Array<Vec3_t*> verts(F[i].Size()); 00047 for (size_t j=0; j<F[i].Size(); ++j) verts[j] = (&V[F[i][j]]); 00048 Faces.Push (new Face(verts)); 00049 } 00050 for (size_t i=0;i<F.Size();i++) 00051 { 00052 Vec3_t V0; 00053 Faces[i]->Centroid(V0); 00054 for (size_t j=0;j<Faces[i]->Edges.Size();j++) 00055 { 00056 Vec3_t V1 = *Faces[i]->Edges[j]->X0; 00057 Vec3_t V2 = *Faces[i]->Edges[(j+1)%Faces[i]->Edges.Size()]->X0; 00058 Vec3_t d = cross(Vec3_t(V1-V0),Vec3_t(V2-V0)); 00059 vol += d(2)*(f1(2,V0,V1,V2))/6; 00060 CM += Vec3_t(d(0)*f2(0,V0,V1,V2),d(1)*f2(1,V0,V1,V2),d(2)*f2(2,V0,V1,V2))/24.0; 00061 It(0,0) += (d(1)*f3(1,V0,V1,V2)+d(2)*f3(2,V0,V1,V2))/60.0; 00062 It(1,1) += (d(0)*f3(0,V0,V1,V2)+d(2)*f3(2,V0,V1,V2))/60.0; 00063 It(2,2) += (d(1)*f3(1,V0,V1,V2)+d(0)*f3(0,V0,V1,V2))/60.0; 00064 It(1,0) -= d(0)*(V0(1)*g0(0,V0,V1,V2)+V1(1)*g1(0,V0,V1,V2)+V2(1)*g2(0,V0,V1,V2))/120.0; 00065 It(2,1) -= d(1)*(V0(2)*g0(1,V0,V1,V2)+V1(2)*g1(1,V0,V1,V2)+V2(2)*g2(1,V0,V1,V2))/120.0; 00066 It(0,2) -= d(2)*(V0(0)*g0(2,V0,V1,V2)+V1(0)*g1(2,V0,V1,V2)+V2(0)*g2(2,V0,V1,V2))/120.0; 00067 } 00068 } 00069 CM/=vol; 00070 It(0,0) -= (CM(1)*CM(1)+CM(2)*CM(2))*vol; 00071 It(1,1) -= (CM(0)*CM(0)+CM(2)*CM(2))*vol; 00072 It(2,2) -= (CM(0)*CM(0)+CM(1)*CM(1))*vol; 00073 It(1,0) += CM(0)*CM(1)*vol; 00074 It(0,2) += CM(0)*CM(2)*vol; 00075 It(2,1) += CM(2)*CM(1)*vol; 00076 It(0,1) = It(1,0); 00077 It(2,0) = It(0,2); 00078 It(1,2) = It(2,1); 00079 00080 } 00081 00082 inline void Erosion(Array<Vec3_t> & V, Array<Array<int> > & E, Array<Array <int> > & F, double R) // Mathematical morphology erosion 00083 { 00084 if (V.Size()<=3) throw new Fatal("There are no enough vertices to work with"); 00085 Array<Face*> Faces; 00086 for (size_t i=0; i<F.Size(); i++) 00087 { 00088 Array<Vec3_t*> verts(F[i].Size()); 00089 for (size_t j=0; j<F[i].Size(); ++j) verts[j] = (&V[F[i][j]]); 00090 Faces.Push (new Face(verts)); 00091 } 00092 Array<Vec3_t> Normal(3); 00093 Array<Array <int> > VFlist; 00094 Array<Vec3_t> Vtemp; 00095 //First each trio of faces is moved inward and the intersection is checked 00096 for (size_t i=0; i<F.Size()-2; i++) 00097 { 00098 Normal[0] = cross(Faces[i]->Edges[0]->dL,Faces[i]->Edges[1]->dL); 00099 Normal[0] = Normal[0]/norm(Normal[0]); 00100 Normal[0] = *Faces[i]->Edges[0]->X0 - R*Normal[0]; 00101 for (size_t j=i+1; j<F.Size()-1; j++) 00102 { 00103 Normal[1] = cross(Faces[j]->Edges[0]->dL,Faces[j]->Edges[1]->dL); 00104 Normal[1] = Normal[1]/norm(Normal[1]); 00105 Normal[1] = *Faces[j]->Edges[0]->X0 - R*Normal[1]; 00106 for (size_t k=j+1; k<F.Size(); k++) 00107 { 00108 Normal[2] = cross(Faces[k]->Edges[0]->dL,Faces[k]->Edges[1]->dL); 00109 Normal[2] = Normal[2]/norm(Normal[2]); 00110 Normal[2] = *Faces[k]->Edges[0]->X0 - R*Normal[2]; 00111 Mat_t M(9,9); 00112 Vec_t X(9),B(9); 00113 for (size_t l = 0;l<9;l++) 00114 { 00115 for (size_t m = 0;m<9;m++) 00116 { 00117 M(l,m) = 0; 00118 } 00119 X(l) = 0; 00120 B(l) = 0; 00121 } 00122 M(0,0) = Faces[i]->Edges[0]->dL(0); 00123 M(0,1) = Faces[i]->Edges[1]->dL(0); 00124 M(0,6) = -1; 00125 M(1,0) = Faces[i]->Edges[0]->dL(1); 00126 M(1,1) = Faces[i]->Edges[1]->dL(1); 00127 M(1,7) = -1; 00128 M(2,0) = Faces[i]->Edges[0]->dL(2); 00129 M(2,1) = Faces[i]->Edges[1]->dL(2); 00130 M(2,8) = -1; 00131 M(3,2) = Faces[j]->Edges[0]->dL(0); 00132 M(3,3) = Faces[j]->Edges[1]->dL(0); 00133 M(3,6) = -1; 00134 M(4,2) = Faces[j]->Edges[0]->dL(1); 00135 M(4,3) = Faces[j]->Edges[1]->dL(1); 00136 M(4,7) = -1; 00137 M(5,2) = Faces[j]->Edges[0]->dL(2); 00138 M(5,3) = Faces[j]->Edges[1]->dL(2); 00139 M(5,8) = -1; 00140 M(6,4) = Faces[k]->Edges[0]->dL(0); 00141 M(6,5) = Faces[k]->Edges[1]->dL(0); 00142 M(6,6) = -1; 00143 M(7,4) = Faces[k]->Edges[0]->dL(1); 00144 M(7,5) = Faces[k]->Edges[1]->dL(1); 00145 M(7,7) = -1; 00146 M(8,4) = Faces[k]->Edges[0]->dL(2); 00147 M(8,5) = Faces[k]->Edges[1]->dL(2); 00148 M(8,8) = -1; 00149 B(0) = -Normal[0](0); 00150 B(1) = -Normal[0](1); 00151 B(2) = -Normal[0](2); 00152 B(3) = -Normal[1](0); 00153 B(4) = -Normal[1](1); 00154 B(5) = -Normal[1](2); 00155 B(6) = -Normal[2](0); 00156 B(7) = -Normal[2](1); 00157 B(8) = -Normal[2](2); 00158 try { Sol(M,B,X); } 00159 catch (Fatal * fatal) { continue; } 00160 Vec3_t Inter; 00161 Inter(0) = X(6); 00162 Inter(1) = X(7); 00163 Inter(2) = X(8); 00164 bool inside = true; 00165 for (size_t l = 0;l<F.Size();l++) 00166 { 00167 Vec3_t ct(0,0,0); 00168 for (size_t m = 0;m<Faces[l]->Edges.Size();m++) 00169 { 00170 ct += *Faces[l]->Edges[m]->X0; 00171 } 00172 ct /= Faces[l]->Edges.Size(); 00173 Vec3_t temp = Inter - ct; 00174 Vec3_t N = cross(Faces[l]->Edges[0]->dL,Faces[l]->Edges[1]->dL); 00175 if (dot(temp,N)>0) inside = false; 00176 } 00177 if (inside) 00178 { 00179 bool belong = true; 00180 for (size_t l = 0;l<F.Size();l++) 00181 { 00182 if ((Distance(Inter,*Faces[l])<R)&&(l!=i)&&(l!=j)&&(l!=k)) 00183 { 00184 belong = false; 00185 } 00186 } 00187 if (belong) 00188 { 00189 Vtemp.Push(Inter); 00190 Array<int> VFlistaux(0); 00191 VFlistaux.Push(i); 00192 VFlistaux.Push(j); 00193 VFlistaux.Push(k); 00194 VFlist.Push(VFlistaux); 00195 } 00196 } 00197 } 00198 } 00199 } 00200 V = Vtemp; 00201 if (V.Size()<=3) throw new Fatal("The erosion gave too few vertices to build a convex hull, try a smaller erosion parameter"); 00202 // cm will be a point inside the polyhedron 00203 Vec3_t cm(0,0,0); 00204 for (size_t i = 0; i < V.Size(); i++) 00205 { 00206 cm += V[i]; 00207 } 00208 cm /=V.Size(); 00209 // Here the edges are constructed cheking if the vertices share a face 00210 E.Resize(0); 00211 for (size_t i = 0; i < V.Size()-1; i++) 00212 { 00213 for (size_t j = i+1; j < V.Size(); j++) 00214 { 00215 // Since a pair of vertices share two faces then the edge is created only for the first one found 00216 bool first = true; 00217 for (size_t k = 0; k < 3; k++) 00218 { 00219 // Checking if vertex i and j share face k 00220 if (VFlist[j].Find(VFlist[i][k])!=-1) 00221 { 00222 if (!first) 00223 { 00224 Array<int> Eaux(2); 00225 Eaux[0] = i; 00226 Eaux[1] = j; 00227 E.Push(Eaux); 00228 } 00229 first = false; 00230 } 00231 } 00232 } 00233 } 00234 // Creating faces, in order to do this we assume that the number of eroded faces is lees or equal to the number 00235 // of original faces. If a vertex belongs to th eoriginal and eroded face is pushed. 00236 Array<Array <int> > Ftemp; 00237 Array <int> Faux; 00238 for (size_t i = 0;i < F.Size();i++) 00239 { 00240 Faux.Resize(0); 00241 for (size_t j = 0;j<V.Size();j++) 00242 { 00243 if (VFlist[j].Find(i)!=-1) 00244 { 00245 Faux.Push(j); 00246 } 00247 } 00248 if(Faux.Size()!=0) Ftemp.Push(Faux); 00249 } 00250 00251 //Now the vertices are ordered to ensure the the normal vector points outwars 00252 for (size_t i=0;i<Ftemp.Size();i++) 00253 { 00254 Array<double> Angles(Ftemp[i].Size()); 00255 Vec3_t ct(0,0,0); 00256 for (size_t j = 0;j<Ftemp[i].Size();j++) 00257 { 00258 ct += V[Ftemp[i][j]]; 00259 } 00260 ct /= Ftemp[i].Size(); 00261 Vec3_t axis = V[Ftemp[i][0]] - ct; 00262 Vec3_t inward = cm - ct; 00263 Angles[0]=0.0; 00264 for (size_t j = 1;j<Ftemp[i].Size();j++) 00265 { 00266 Vec3_t t1 = V[Ftemp[i][j]] - ct; 00267 double arg = dot(axis,t1)/(norm(axis)*norm(t1)); 00268 if (arg> 1.0) arg= 1.0; 00269 if (arg<-1.0) arg=-1.0; 00270 Angles[j] = acos(arg); 00271 Vec3_t t2 = cross(axis,t1); 00272 if (dot(t2,inward)>0) Angles[j] = 2*M_PI - Angles[j]; 00273 } 00274 bool swap = false; 00275 while (!swap) 00276 { 00277 swap = true; 00278 for (size_t j=0;j<Ftemp[i].Size()-1;j++) 00279 { 00280 if (Angles[j]>Angles[j+1]) 00281 { 00282 double temp1 = Angles[j]; 00283 Angles[j] = Angles[j+1]; 00284 Angles[j+1] = temp1; 00285 int temp2 = Ftemp[i][j]; 00286 Ftemp[i][j] = Ftemp[i][j+1]; 00287 Ftemp[i][j+1] = temp2; 00288 swap = false; 00289 } 00290 } 00291 } 00292 } 00293 F = Ftemp; 00294 } 00295 00296 #endif //MECHSYS_DEM_SPECIAL_H 00297