MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/dem/distance.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_DISTANCE_H
00021 #define MECHSYS_DEM_DISTANCE_H
00022 
00023 // MechSys
00024 #include <mechsys/dem/edge.h>
00025 #include <mechsys/dem/face.h>
00026 #include <mechsys/dem/cylinder.h>
00027 
00028 inline void Distance (Vec3_t const & V, Edge const & E, Vec3_t & Xi, Vec3_t & Xf)
00029 {
00030     double t = (dot(V,E.dL)-dot((*E.X0),E.dL))/(dot(E.dL,E.dL));
00031     Xi = V;
00032     if      (t<0) Xf = (*E.X0);
00033     else if (t>1) Xf = (*E.X1);
00034     else          Xf = (*E.X0) + E.dL*t;
00035 }
00036 
00037 inline void Distance (Edge const & E, Vec3_t const & V, Vec3_t & Xi, Vec3_t & Xf)
00038 {
00039     Distance (V,E,Xf,Xi);
00040 }
00041 
00042 inline void Distance (Edge const & E0, Edge const & E1, Vec3_t & Xi, Vec3_t & Xf)
00043 {
00044     double a = dot(E0.dL, (*E0.X0)-(*E1.X0));
00045     double b = dot(E1.dL, (*E0.X0)-(*E1.X0));
00046     double c = dot(E0.dL, E0.dL);
00047     double d = dot(E1.dL, E1.dL);
00048     double e = dot(E0.dL, E1.dL);
00049     double t = (c*b-e*a)/(c*d-e*e);
00050     double s = (e*b-a*d)/(c*d-e*e);
00051     
00052     if ((s>0) && (s<1) && (t>0) && (t<1)) 
00053     {
00054         Xi = (*E0.X0)+E0.dL*s;
00055         Xf = (*E1.X0)+E1.dL*t;
00056     }
00057     else 
00058     {
00059         Vec3_t xi1,xf1;
00060         Vec3_t xi2,xf2;
00061         Vec3_t xi3,xf3;
00062         Vec3_t xi4,xf4;
00063         Distance ((*E0.X0),E1,xi1,xf1);
00064         Distance ((*E0.X1),E1,xi2,xf2);
00065         Distance ((*E1.X0),E0,xf3,xi3);
00066         Distance ((*E1.X1),E0,xf4,xi4);
00067         double l1 = norm(xf1-xi1);
00068         double l2 = norm(xf2-xi2);
00069         double l3 = norm(xf3-xi3);
00070         double l4 = norm(xf4-xi4);
00071         if ((l1<=l2) && (l1<=l3) && (l1<=l4))
00072         {   
00073             Xi = xi1;
00074             Xf = xf1;
00075         }
00076         if ((l2<=l1) && (l2<=l3) && (l2<=l4)) 
00077         {   
00078             Xi = xi2;
00079             Xf = xf2;
00080         }
00081         if ((l3<=l1) && (l3<=l2) && (l3<=l4)) 
00082         {   
00083             Xi = xi3;
00084             Xf = xf3;
00085         }
00086         if ((l4<=l1) && (l4<=l2) && (l4<=l3)) 
00087         {   
00088             Xi = xi4;
00089             Xf = xf4;
00090         }
00091     }
00092 }
00093 
00094 inline void Distance (Vec3_t const & V, Face const & F, Vec3_t & Xi, Vec3_t & Xf)
00095 {
00096     // find the normal to face
00097     Vec3_t nor = cross(F.Edges[0]->dL, F.Edges[1]->dL);
00098     nor = nor/norm(nor);
00099 
00100     // find the projection
00101     double a   = dot(*F.Edges[0]->X0-V, F.Edges[0]->dL);
00102     double b   = dot(F.Edges[0]->dL   , F.Edges[0]->dL);
00103     double c   = dot(F.Edges[0]->dL   , F.Edges[1]->dL);
00104     double d   = dot(*F.Edges[0]->X0-V, F.Edges[1]->dL);
00105     double f   = dot(F.Edges[1]->dL   , F.Edges[1]->dL);
00106     double s   = (c*d-a*f)/(b*f-c*c);
00107     double t   = (a*c-b*d)/(b*f-c*c);
00108     Vec3_t pro = *F.Edges[0]->X0 + s*F.Edges[0]->dL + t*F.Edges[1]->dL;
00109 
00110     // check if vertex is inside
00111     bool inside = true;
00112     for (size_t i=0; i<F.Edges.Size(); i++) 
00113     {
00114         Vec3_t tmp = pro-*F.Edges[i]->X0;
00115         if (dot(cross(F.Edges[i]->dL,tmp),nor)<0) inside = false;
00116     }
00117 
00118     // get Xi, Xf
00119     if (inside)
00120     {
00121         Xi = V;
00122         Xf = pro;
00123     }
00124     else // compare V against each edge
00125     {
00126         Distance (V, (*F.Edges[0]), pro, nor); // pro=Xi, nor=Xf
00127         double lt = norm(nor-pro);
00128         double ld = lt;
00129         Xi = pro;
00130         Xf = nor;
00131         for (size_t i=1; i<F.Edges.Size(); i++) 
00132         {
00133             Distance (V, (*F.Edges[i]), pro, nor);
00134             lt = norm(nor-pro);
00135             if (lt<ld)
00136             {
00137                 Xi = pro;
00138                 Xf = nor;
00139                 ld = lt;
00140             }
00141         }
00142     }
00143 }
00144 
00145 inline void Distance (Face const & F, Vec3_t const & V, Vec3_t & Xi, Vec3_t & Xf)
00146 {
00147     Distance (V,F,Xf,Xi);
00148 }
00149 
00150 inline void Distance (Vec3_t const & V0, Vec3_t const & V1, Vec3_t & Xi, Vec3_t & Xf)
00151 {
00152     Xi = V0;
00153     Xf = V1;
00154 }
00155 
00156 inline void Distance (Vec3_t const & V0, Torus const & T1, Vec3_t & Xi, Vec3_t & Xf)
00157 {
00158     Xi = V0;
00159     double theta1 = atan(dot(Xi-*T1.X0,*T1.X2-*T1.X0)/dot(Xi-*T1.X0,*T1.X1-*T1.X0));
00160     double theta2 = theta1 + M_PI;
00161     Vec3_t P1,P2;
00162     P1 = *T1.X0 + cos(theta1)*(*T1.X1-*T1.X0) + sin(theta1)*(*T1.X2-*T1.X0);
00163     P2 = *T1.X0 + cos(theta2)*(*T1.X1-*T1.X0) + sin(theta2)*(*T1.X2-*T1.X0);
00164     double dist1 = norm(Xi-P1);
00165     double dist2 = norm(Xi-P2);
00166     if (dist1<dist2) Xf = P1;
00167     else             Xf = P2;
00168 }
00169 
00170 inline void Distance (Torus const & T1, Vec3_t const & V0, Vec3_t & Xi, Vec3_t & Xf)
00171 {
00172     Distance (V0,T1,Xf,Xi);
00173 }
00174 
00175 inline void Distance (Vec3_t const & V0, Cylinder const & C1, Vec3_t & Xi, Vec3_t & Xf)
00176 {
00177     Xi = V0;
00178     Vec3_t xn,yn;
00179     xn = *C1.T1->X1-*C1.T1->X0;
00180     yn = *C1.T1->X2-*C1.T1->X0;
00181     xn/= norm(xn);
00182     yn/= norm(yn);
00183     double theta1 = atan(dot(Xi-*C1.T1->X0,yn)/dot(Xi-*C1.T1->X0,xn));
00184     double theta2 = theta1 + M_PI;
00185     double DR  = C1.T1->R - C1.T0->R;
00186     Vec3_t DX  = *C1.T1->X0-*C1.T0->X0;
00187     double DX2 = dot(DX,DX);
00188     Vec3_t DV  = V0-*C1.T0->X0;
00189     double DVDX = dot(DX,DV);
00190     double s1,s2;
00191     s1 = (DVDX + DR*dot(DV,cos(theta1)*xn+sin(theta1)*yn) - C1.T0->R*DR)/(DX2+DR*DR);
00192     s2 = (DVDX + DR*dot(DV,cos(theta2)*xn+sin(theta2)*yn) - C1.T0->R*DR)/(DX2+DR*DR);
00193     if (s1>1.0) s1 = 1.0;
00194     if (s1<0.0) s1 = 0.0;
00195     if (s2>1.0) s2 = 1.0;
00196     if (s2<0.0) s2 = 0.0;
00197     Vec3_t P1,P2;
00198     P1 = C1.X0 + s1*DX + (C1.T0->R + s1*DR)*(cos(theta1)*xn+sin(theta1)*yn);
00199     P2 = C1.X0 + s1*DX + (C1.T0->R + s2*DR)*(cos(theta2)*xn+sin(theta2)*yn);
00200     double dist1 = norm(Xi-P1);
00201     double dist2 = norm(Xi-P2);
00202     if (dist1<dist2) Xf = P1;
00203     else             Xf = P2;
00204 }
00205 
00206 inline void Distance (Cylinder const & C1, Vec3_t const & V0, Vec3_t & Xi, Vec3_t & Xf)
00207 {
00208     Distance (V0,C1,Xf,Xi);
00209 }
00210 
00211 inline double Distance (Edge const & E, Vec3_t const & V)
00212 {
00213     Vec3_t Xi,Xf;
00214     Distance (E,V,Xi,Xf);
00215     return norm(Xf-Xi);
00216 }
00217 
00218 inline double Distance (Vec3_t const & V, Edge const & E)
00219 {
00220     return Distance (E,V);
00221 }
00222 
00223 inline double Distance (Edge const & E0, Edge const & E1)
00224 {
00225     Vec3_t Xi,Xf;
00226     Distance (E0,E1,Xi,Xf);
00227     return norm(Xf-Xi);
00228 }
00229 
00230 inline double Distance (Face const & F, Vec3_t const & V)
00231 {
00232     Vec3_t Xi,Xf;
00233     Distance (F,V,Xi,Xf);
00234     return norm(Xf-Xi);
00235 }
00236 
00237 inline double Distance (Vec3_t const & V, Face const & F)
00238 {
00239     return Distance (F,V);
00240 }
00241 
00242 inline double Distance (Vec3_t const & V0, Vec3_t const & V1)
00243 {
00244     return norm(V1-V0);
00245 }
00246 
00247 inline double Distance (Vec3_t const & V0, Torus const & T1)
00248 {
00249     Vec3_t Xi,Xf;
00250     Distance (V0,T1,Xi,Xf);
00251     return norm(Xf-Xi);
00252 }
00253 
00254 inline double Distance (Torus const & T1, Vec3_t const & V0)
00255 {
00256     Vec3_t Xi,Xf;
00257     Distance (T1,V0,Xi,Xf);
00258     return norm(Xf-Xi);
00259 }
00260 
00261 inline double Distance (Vec3_t const & V0, Cylinder const & C1)
00262 {
00263     Vec3_t Xi,Xf;
00264     Distance (C1,V0,Xi,Xf);
00265     return norm(Xf-Xi);
00266 }
00267 
00268 inline double Distance (Cylinder const & C1, Vec3_t const & V0)
00269 {
00270     Vec3_t Xi,Xf;
00271     Distance (C1,V0,Xi,Xf);
00272     return norm(Xf-Xi);
00273 }
00274 #endif // MECHSYS_DEM_DISTANCE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines