2 // C++ : Gestion des cylindres
4 // Copyright (C) 2009-2012 CEA/DEN, EDF R&D
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "HexCylinder.hxx"
23 #include "HexVertex.hxx"
24 #include "HexVector.hxx"
25 #include "HexXmlWriter.hxx"
31 bool is_out (double val, double orig, double lg);
33 // ======================================================== Constructeur
34 Cylinder::Cylinder(Vertex* b, Vector* v, double r, double h)
42 if (el_root->debug ())
44 Echo ("---------------------------------- AddCylinder");
45 HexDisplay (c_radius);
46 HexDisplay (c_height);
52 // ======================================================== rdiffers
53 bool rdiffers (double v1, double v2)
58 // ======================================================== norme
59 double norme (double px, double py, double pz)
61 double res = sqrt (px*px + py*py + pz*pz);
64 // ======================================================== interCylinder
65 /// Intersection de 2 droites (c1,v1) et (c2,v2)
66 /// Le point M(x,yz) est solutions de 2 equations :
68 /// (c2,m) vectoriel v2 = 0
70 /// x = xc1 + k * xv1 (1)
71 /// y = yc1 + k * yv1 (2)
72 /// z = zc1 + k * zv1 (3)
73 /// (x-xc2) * yv2 - (y-yc2) * xv2 = 0 (4)
74 /// (z-zc2) * yv2 - (y-yc2) * zv2 = 0 (5)
75 /// (x-xc2) * zv2 - (z-zc2) * xv2 = 0 (6)
77 /// En substituant les (x,y,z)
79 /// (k*xv1+xc1-xc2) * yv2 - (k*yv1+yc1-yc2) * xv2 = 0 (4)
80 /// (k*zv1+zc1-zc2) * yv2 - (k*yv1+yc1-yc2) * zv2 = 0 (5)
81 /// (k*xv1+xc1-xc2) * zv2 - (k*zv1+zc1-zc2) * xv2 = 0 (6)
83 /// k * (xv1*yv2 - yv1*xv2) + (xc1-xc2) * yv2 - (yc1-yc2) * xv2 = 0 (4)
84 /// k * dxy - nxy = 0 (4)
85 /// k * dzy - nzy = 0 (5)
86 /// k * dxz - nxz = 0 (6)
88 /// nxy = (xc2-xc1) * yv2 - (yc2-yc1) * xv2
89 /// dxy = xv1*yv2 - yv1*xv2
91 // ======================================================== interCylinder
92 Vertex* Cylinder::interCylinder (Cylinder* small, bool& left, bool& right)
95 int ier = interCylinder (small, left, right, orig);
99 Vertex* sol = new Vertex (c_base->dad(), orig[0], orig[1], orig[2]);
103 // ======================================================== interCylinder
104 int Cylinder::interCylinder (Cylinder* small, bool& left, bool& right,
108 if (el_root->debug ())
110 Echo ("---------------------------------- interCylinders");
111 PutData (this->c_radius);
112 PutData (small->c_radius);
113 PutData (this->c_height);
114 PutData (small->c_height);
115 HexDump (this->c_base);
116 HexDump (small->c_base);
117 HexDump (this->c_dir);
118 HexDump (small->c_dir);
121 double norm1 = c_dir->getNorm();
122 double norm2 = small->c_dir->getNorm();
124 double xc1 = c_base->getX();
125 double yc1 = c_base->getY();
126 double zc1 = c_base->getZ();
128 double xc2 = small->c_base->getX();
129 double yc2 = small->c_base->getY();
130 double zc2 = small->c_base->getZ();
132 double xv1 = c_dir->getDx()/norm1;
133 double yv1 = c_dir->getDy()/norm1;
134 double zv1 = c_dir->getDz()/norm1;
136 double xv2 = small->c_dir->getDx()/norm2;
137 double yv2 = small->c_dir->getDy()/norm2;
138 double zv2 = small->c_dir->getDz()/norm2;
140 double nxyz [DIM3] = { (xc2-xc1) * yv2 - (yc2-yc1) * xv2,
141 (zc2-zc1) * yv2 - (yc2-yc1) * zv2,
142 (xc2-xc1) * zv2 - (zc2-zc1) * xv2 };
144 double dxyz [DIM3] = { xv1*yv2 - yv1*xv2,
149 for (int dd=0 ; dd<DIM3 ; dd++)
151 // dxyz!=0 : calcul de lambda
152 if (rdiffers (dxyz [dd], ZEROR))
154 double kk = nxyz [dd] / dxyz[dd];
161 // Solutions incompatibles
162 else if (rdiffers (kk, lambda))
164 cout << "*** InterCylinders : Solutions incompatibles " << endl;
167 // equation O*lamda = 0 : ignoree
170 // dxyz=0 et nxyz!=0 : Pas de solution
171 else if (rdiffers (nxyz [dd], ZEROR))
173 cout << "*** InterCylinders : intersection vide " << endl;
178 // Aucune solution trouvee
182 cout << "*** InterCylinders : intersection non trouvee " << endl;
185 // Intersection des droites
186 orig [dir_x] = xc1 + lambda*xv1;
187 orig [dir_y] = yc1 + lambda*yv1;
188 orig [dir_z] = zc1 + lambda*zv1;
190 Real3 base1, dir1, extr1;
191 Real3 base2, dir2, extr2;
193 this ->c_base->getPoint (base1);
194 small->c_base->getPoint (base2);
196 this ->c_dir->getCoord (dir1);
197 small->c_dir->getCoord (dir2);
199 for (int dd=dir_x ; dd<=dir_z ; dd++)
201 extr1 [dd] = base1[dd] + dir1[dd]*this ->c_height/norm1;
202 extr2 [dd] = base2[dd] + dir2[dd]*small->c_height/norm2;
205 double dbase1 = calc_distance (orig, base1);
206 double dbase2 = calc_distance (orig, base2);
207 double dextr1 = calc_distance (orig, extr1);
208 double dextr2 = calc_distance (orig, extr2);
210 double dmin2 = std::min (dbase2, dextr2);
211 double dmax2 = std::max (dbase2, dextr2);
212 double dmax1 = std::max (dbase1, dextr1);
214 // Appartenance axe petit cylindre
215 if (dmax2 > small->c_height + c_radius)
217 cout << "*** InterCylinders : Petit cylindre trop court" << endl;
218 cout << "*** Intersection = (" << orig[0] << ", " << orig[1]
219 << ", " << orig[2] << " )" << endl;
220 cout << "*** distance = " << dmin2
221 << " > gros rayon + longueur "
222 << small->c_height + c_radius << endl;
232 left = dbase2 > c_radius*coeff;
233 right = dextr2 > c_radius*coeff;
234 // Le gros cylindre doit depasser le petit
235 if (dmax1 > c_height-coeff*small->c_radius)
237 cout << "*** InterCylinders : Gros cylindre trop court" << endl;
238 cout << "*** Intersection = (" << orig[0] << ", " << orig[1]
239 << ", " << orig[2] << " )" << endl;
240 cout << "*** distance maximale = " << dmax1 << endl;
245 if (el_root->debug ())
253 // ======================================================== is_out
254 bool is_out (double val, double v1, double v2)
257 return (val < v1-Epsil || val > v2+Epsil) ;
260 return (val < v2-Epsil || val > v1+Epsil) ;
263 return fabs (val - v1)>Epsil;
265 // ========================================================= saveXml
266 void Cylinder::saveXml (XmlWriter* xml)
270 xml->openMark ("Cylinder");
271 xml->addAttribute ("c_base", c_base->getName (buffer));
272 xml->addAttribute ("c_dir", c_dir->getName (buffer));
273 xml->addAttribute ("c_radius", c_radius);
274 xml->addAttribute ("c_height", c_height);