![]() |
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_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