2 // C++ : Gestion des cylindres
4 // Copyright (C) 2009-2013 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"
26 #include "HexDocument.hxx"
32 bool is_out (double val, double orig, double lg);
34 // ======================================================== Constructeur
35 Cylinder::Cylinder(Vertex* b, Vector* v, double r, double h)
36 : EltBase (b->dad(), EL_CYLINDER)
43 if (el_root->debug ())
45 Echo ("---------------------------------- AddCylinder");
46 HexDisplay (c_radius);
47 HexDisplay (c_height);
53 if (c_base==NULL || c_dir==NULL || el_root==NULL)
57 double tol = el_root->getTolerance ();
58 double norme = c_dir ->getNorm ();
59 if (c_radius <= tol || c_height <= tol || norme <= tol)
63 // ======================================================== rdiffers
64 bool rdiffers (double v1, double v2)
69 // ======================================================== norme
70 double norme (double px, double py, double pz)
72 double res = sqrt (px*px + py*py + pz*pz);
75 // ======================================================== interCylinder
76 /// Intersection de 2 droites (c1,v1) et (c2,v2)
77 /// Le point M(x,yz) est solutions de 2 equations :
79 /// (c2,m) vectoriel v2 = 0
81 /// x = xc1 + k * xv1 (1)
82 /// y = yc1 + k * yv1 (2)
83 /// z = zc1 + k * zv1 (3)
84 /// (x-xc2) * yv2 - (y-yc2) * xv2 = 0 (4)
85 /// (z-zc2) * yv2 - (y-yc2) * zv2 = 0 (5)
86 /// (x-xc2) * zv2 - (z-zc2) * xv2 = 0 (6)
88 /// En substituant les (x,y,z)
90 /// (k*xv1+xc1-xc2) * yv2 - (k*yv1+yc1-yc2) * xv2 = 0 (4)
91 /// (k*zv1+zc1-zc2) * yv2 - (k*yv1+yc1-yc2) * zv2 = 0 (5)
92 /// (k*xv1+xc1-xc2) * zv2 - (k*zv1+zc1-zc2) * xv2 = 0 (6)
94 /// k * (xv1*yv2 - yv1*xv2) + (xc1-xc2) * yv2 - (yc1-yc2) * xv2 = 0 (4)
95 /// k * dxy - nxy = 0 (4)
96 /// k * dzy - nzy = 0 (5)
97 /// k * dxz - nxz = 0 (6)
99 /// nxy = (xc2-xc1) * yv2 - (yc2-yc1) * xv2
100 /// dxy = xv1*yv2 - yv1*xv2
102 // ======================================================== interCylinder
103 Vertex* Cylinder::interCylinder(Cylinder* small, bool& left, bool& right)
106 int ier = interCylinder (small, left, right, orig);
110 Vertex* sol = new Vertex (c_base->dad(), orig[0], orig[1], orig[2]);
114 // ======================================================== interCylinder
115 int Cylinder::interCylinder (Cylinder* small, bool& left, bool& right,
119 if (el_root->debug ())
121 Echo ("---------------------------------- interCylinders");
122 PutData (this->c_radius);
123 PutData (small->c_radius);
124 PutData (this->c_height);
125 PutData (small->c_height);
126 HexDump (this->c_base);
127 HexDump (small->c_base);
128 HexDump (this->c_dir);
129 HexDump (small->c_dir);
132 double norm1 = c_dir->getNorm();
133 double norm2 = small->c_dir->getNorm();
135 double xc1 = c_base->getX();
136 double yc1 = c_base->getY();
137 double zc1 = c_base->getZ();
139 double xc2 = small->c_base->getX();
140 double yc2 = small->c_base->getY();
141 double zc2 = small->c_base->getZ();
143 double xv1 = c_dir->getDx()/norm1;
144 double yv1 = c_dir->getDy()/norm1;
145 double zv1 = c_dir->getDz()/norm1;
147 double xv2 = small->c_dir->getDx()/norm2;
148 double yv2 = small->c_dir->getDy()/norm2;
149 double zv2 = small->c_dir->getDz()/norm2;
151 double nxyz [DIM3] = { (xc2-xc1) * yv2 - (yc2-yc1) * xv2,
152 (zc2-zc1) * yv2 - (yc2-yc1) * zv2,
153 (xc2-xc1) * zv2 - (zc2-zc1) * xv2 };
155 double dxyz [DIM3] = { xv1*yv2 - yv1*xv2,
160 for (int dd=0 ; dd<DIM3 ; dd++)
162 // dxyz!=0 : calcul de lambda
163 if (rdiffers (dxyz [dd], ZEROR))
165 double kk = nxyz [dd] / dxyz[dd];
172 // Solutions incompatibles
173 else if (rdiffers (kk, lambda))
175 cout << "*** InterCylinders : Solutions incompatibles " << endl;
178 // equation O*lamda = 0 : ignoree
181 // dxyz=0 et nxyz!=0 : Pas de solution
182 else if (rdiffers (nxyz [dd], ZEROR))
184 cout << "*** InterCylinders : intersection vide " << endl;
189 // Aucune solution trouvee
193 cout << "*** InterCylinders : intersection non trouvee " << endl;
196 // Intersection des droites
197 orig [dir_x] = xc1 + lambda*xv1;
198 orig [dir_y] = yc1 + lambda*yv1;
199 orig [dir_z] = zc1 + lambda*zv1;
201 Real3 base1, dir1, extr1;
202 Real3 base2, dir2, extr2;
204 this ->c_base->getPoint (base1);
205 small->c_base->getPoint (base2);
207 this ->c_dir->getCoord (dir1);
208 small->c_dir->getCoord (dir2);
210 for (int dd=dir_x ; dd<=dir_z ; dd++)
212 extr1 [dd] = base1[dd] + dir1[dd]*this ->c_height/norm1;
213 extr2 [dd] = base2[dd] + dir2[dd]*small->c_height/norm2;
216 double dbase1 = calc_distance (orig, base1);
217 double dbase2 = calc_distance (orig, base2);
218 double dextr1 = calc_distance (orig, extr1);
219 double dextr2 = calc_distance (orig, extr2);
221 double dmin2 = std::min (dbase2, dextr2);
222 double dmax2 = std::max (dbase2, dextr2);
223 double dmax1 = std::max (dbase1, dextr1);
225 // Appartenance axe petit cylindre
226 if (dmax2 > small->c_height + c_radius)
228 cout << "*** InterCylinders : Petit cylindre trop court" << endl;
229 cout << "*** Intersection = (" << orig[0] << ", " << orig[1]
230 << ", " << orig[2] << " )" << endl;
231 cout << "*** distance = " << dmin2
232 << " > gros rayon + longueur "
233 << small->c_height + c_radius << endl;
243 left = dbase2 > c_radius*coeff;
244 right = dextr2 > c_radius*coeff;
245 // Le gros cylindre doit depasser le petit
246 if (dmax1 > c_height-coeff*small->c_radius)
248 cout << "*** InterCylinders : Gros cylindre trop court" << endl;
249 cout << "*** Intersection = (" << orig[0] << ", " << orig[1]
250 << ", " << orig[2] << " )" << endl;
251 cout << "*** distance maximale = " << dmax1 << endl;
256 if (el_root->debug ())
264 // ======================================================== is_out
265 bool is_out (double val, double v1, double v2)
268 return (val < v1-Epsil || val > v2+Epsil) ;
271 return (val < v2-Epsil || val > v1+Epsil) ;
274 return fabs (val - v1)>Epsil;
276 // ========================================================= saveXml
277 void Cylinder::saveXml (XmlWriter* xml)
281 xml->openMark ("Cylinder");
282 xml->addAttribute ("c_base", c_base->getName (buffer));
283 xml->addAttribute ("c_dir", c_dir->getName (buffer));
284 xml->addAttribute ("c_radius", c_radius);
285 xml->addAttribute ("c_height", c_height);