MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/dem/special_functions.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines