0024428: Implementation of LGPL license
[occt.git] / src / BRepExtrema / BRepExtrema_DistShapeShape.cxx
1 // Created on: 1996-04-22
2 // Created by: Herve LOUESSARD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified: Mps(10-04-97) portage WNT
18
19 #include <BRepExtrema_DistShapeShape.hxx>
20
21 #include <Standard_OStream.hxx>
22 #include <TopTools_IndexedMapOfShape.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Bnd_Box.hxx>
25 #include <TopExp.hxx>
26 #include <BRepExtrema_DistanceSS.hxx>
27 #include <TopoDS.hxx>
28 #include <TopAbs.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <TopAbs_ShapeEnum.hxx>
33 #include <Precision.hxx>
34 #include <Bnd_SeqOfBox.hxx>
35 #include <BRepExtrema_UnCompatibleShape.hxx>
36 #include <BRep_Tool.hxx>
37 #include <BRepClass3d_SolidClassifier.hxx>
38 #include <StdFail_NotDone.hxx>
39
40 static void Decomposition(const TopoDS_Shape&         S,
41                           TopTools_IndexedMapOfShape& MapV,
42                           TopTools_IndexedMapOfShape& MapE,
43                           TopTools_IndexedMapOfShape& MapF)
44 {
45   MapV.Clear();
46   MapE.Clear();
47   MapF.Clear();
48   TopExp::MapShapes(S,TopAbs_VERTEX,MapV);
49   TopExp::MapShapes(S,TopAbs_EDGE,MapE);
50   TopExp::MapShapes(S,TopAbs_FACE,MapF);
51 }
52
53 static void BoxCalculation(const TopTools_IndexedMapOfShape& Map,
54                            Bnd_SeqOfBox&                     SBox)
55
56   for (Standard_Integer i = 1; i <= Map.Extent(); i++)
57   {
58     Bnd_Box box;
59     BRepBndLib::Add(Map(i), box);
60     SBox.Append(box);
61   }
62 }
63
64 inline Standard_Real DistanceInitiale(const TopoDS_Vertex V1,
65                                       const TopoDS_Vertex V2)
66 {
67   return (BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V2)));
68
69
70 //=======================================================================
71 //function : DistanceMapMap
72 //purpose  : 
73 //=======================================================================
74
75 void BRepExtrema_DistShapeShape::DistanceMapMap(const TopTools_IndexedMapOfShape& Map1,
76                                                 const TopTools_IndexedMapOfShape& Map2,
77                                                 const Bnd_SeqOfBox&               LBox1,
78                                                 const Bnd_SeqOfBox&               LBox2)
79 {
80   Standard_Integer i, j;
81   BRepExtrema_SeqOfSolution seq1, seq2;
82
83   const Standard_Integer n1 = Map1.Extent();
84   const Standard_Integer n2 = Map2.Extent();
85   for (i = 1; i <= n1; i++)
86   {
87     const Bnd_Box &box1 = LBox1.Value(i);
88     const TopoDS_Shape &S1 = Map1(i);
89     for (j = 1; j <= n2; j++)
90     {
91       const Bnd_Box &box2= LBox2.Value(j);
92       const TopoDS_Shape &S2 = Map2(j);
93
94       BRepExtrema_DistanceSS  dist(S1,S2,box1,box2,myDistRef,myEps);
95       if (dist.IsDone()) {
96         if(dist.DistValue() < (myDistRef-myEps))
97         {
98           mySolutionsShape1.Clear();
99           mySolutionsShape2.Clear();
100           seq1= dist.Seq1Value();
101           seq2= dist.Seq2Value();
102           mySolutionsShape1.Append(seq1);
103           mySolutionsShape2.Append(seq2);
104           myDistRef=dist.DistValue();
105         }
106         else if(fabs(dist.DistValue()-myDistRef) < myEps)
107         {
108           seq1= dist.Seq1Value();
109           seq2= dist.Seq2Value();
110           mySolutionsShape1.Append(seq1);
111           mySolutionsShape2.Append(seq2);
112           if (myDistRef > dist.DistValue())
113             myDistRef=dist.DistValue();
114         }
115       }
116     }
117   }
118 }
119
120 //=======================================================================
121 //function : BRepExtrema_DistShapeShape
122 //purpose  : 
123 //=======================================================================
124
125 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape()
126 : myDistRef(0.),
127   myIsDone(Standard_False),
128   myInnerSol(Standard_False),
129   myEps(Precision::Confusion()),
130   myFlag(Extrema_ExtFlag_MINMAX),
131   myAlgo(Extrema_ExtAlgo_Grad)
132 {
133 }
134
135 //=======================================================================
136 //function : BRepExtrema_DistShapeShape
137 //purpose  : 
138 //=======================================================================
139 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
140                                                        const TopoDS_Shape& Shape2,
141                                                        const Extrema_ExtFlag F,
142                                                        const Extrema_ExtAlgo A)
143 : myDistRef(0.),
144   myIsDone(Standard_False),
145   myInnerSol(Standard_False),
146   myEps(Precision::Confusion()),
147   myFlag(F),
148   myAlgo(A)
149 {
150   LoadS1(Shape1);
151   LoadS2(Shape2);
152   Perform();
153 }
154
155 //=======================================================================
156 //function : BRepExtrema_DistShapeShape
157 //purpose  : 
158 //=======================================================================
159
160 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
161                                                        const TopoDS_Shape& Shape2,
162                                                        const Standard_Real theDeflection,
163                                                        const Extrema_ExtFlag F,
164                                                        const Extrema_ExtAlgo A)
165 : myDistRef(0.),
166   myIsDone(Standard_False),
167   myInnerSol(Standard_False),
168   myEps(theDeflection),
169   myFlag(F),
170   myAlgo(A)
171 {
172   LoadS1(Shape1);
173   LoadS2(Shape2);
174   Perform();
175 }
176
177 //=======================================================================
178 //function : LoadS1
179 //purpose  : 
180 //=======================================================================
181
182 void BRepExtrema_DistShapeShape::LoadS1(const TopoDS_Shape& Shape1)
183 {
184   myShape1 = Shape1;
185   Decomposition(Shape1, myMapV1, myMapE1, myMapF1);
186 }
187
188 //=======================================================================
189 //function : LoadS2
190 //purpose  : 
191 //=======================================================================
192
193 void BRepExtrema_DistShapeShape::LoadS2(const TopoDS_Shape& Shape2)
194 {
195   myShape2 = Shape2;
196   Decomposition(Shape2, myMapV2, myMapE2, myMapF2);
197 }
198
199 //=======================================================================
200 //function : Perform
201 //purpose  : 
202 //=======================================================================
203
204 Standard_Boolean BRepExtrema_DistShapeShape::Perform()
205 {
206   myIsDone=Standard_False;
207   myInnerSol=Standard_False;
208   mySolutionsShape1.Clear();
209   mySolutionsShape2.Clear();
210
211   if ( myShape1.IsNull() || myShape2.IsNull() )
212     return Standard_False;
213
214   TopoDS_Vertex V;
215   Bnd_SeqOfBox BV1, BV2, BE1, BE2, BF1, BF2;
216   const Standard_Real tol = 0.001;
217
218   // Treatment of solids
219   const TopAbs_ShapeEnum Type1 = myShape1.ShapeType();
220   if ((Type1==TopAbs_SOLID) || (Type1 == TopAbs_COMPSOLID))
221   {
222     BRepClass3d_SolidClassifier Classi(myShape1);
223     const Standard_Integer nbv2 = myMapV2.Extent();
224     Standard_Integer nbv1 = 0;
225     while ( (nbv1<nbv2) && (!myInnerSol) )
226     {
227       nbv1++;
228       V = TopoDS::Vertex(myMapV2(nbv1));
229       const gp_Pnt &P = BRep_Tool::Pnt(V);
230       Classi.Perform(P,tol);
231       if (Classi.State()==TopAbs_IN)
232       {
233         myInnerSol = Standard_True;
234         myDistRef = 0.;
235         myIsDone = Standard_True; 
236         BRepExtrema_SolutionElem Sol(0,P,BRepExtrema_IsVertex,V);
237         mySolutionsShape1.Append(Sol);
238         mySolutionsShape2.Append(Sol);
239       }  
240     }
241   }
242   
243   const TopAbs_ShapeEnum Type2 = myShape2.ShapeType();
244   if (((Type2==TopAbs_SOLID) || (Type2==TopAbs_COMPSOLID)) && (!myInnerSol))
245   {
246     BRepClass3d_SolidClassifier Classi(myShape2);
247     const Standard_Integer nbv1 = myMapV1.Extent();
248     Standard_Integer nbv2 = 0;
249     while ( (nbv2<nbv1) && (!myInnerSol) )
250     {
251       nbv2++;
252       V = TopoDS::Vertex(myMapV1(nbv2));
253       const gp_Pnt &P = BRep_Tool::Pnt(V);
254       Classi.Perform(P,tol);
255       if (Classi.State()==TopAbs_IN) {
256         myInnerSol = Standard_True;
257         myDistRef = 0;
258         myIsDone = Standard_True; 
259         BRepExtrema_SolutionElem Sol (0,P,BRepExtrema_IsVertex,V);
260         mySolutionsShape1.Append(Sol);
261         mySolutionsShape2.Append(Sol);
262       }
263     }
264   }
265   
266   if (!myInnerSol)
267   {
268     BoxCalculation(myMapV1,BV1);
269     BoxCalculation(myMapE1,BE1);
270     BoxCalculation(myMapF1,BF1);
271     BoxCalculation(myMapV2,BV2);
272     BoxCalculation(myMapE2,BE2);
273     BoxCalculation(myMapF2,BF2);
274     
275     if (myMapV1.Extent() && myMapV2.Extent())
276     {
277       TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
278       TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
279       myDistRef = DistanceInitiale(V1, V2);
280     }
281     else
282       myDistRef= 1.e30; //szv:!!!
283
284     DistanceMapMap(myMapV1, myMapV2, BV1, BV2);
285     DistanceMapMap(myMapV1, myMapE2, BV1, BE2);
286     DistanceMapMap(myMapE1, myMapV2, BE1, BV2);
287     DistanceMapMap(myMapV1, myMapF2, BV1, BF2);
288     DistanceMapMap(myMapF1, myMapV2, BF1, BV2);
289     DistanceMapMap(myMapE1, myMapE2, BE1, BE2);
290     DistanceMapMap(myMapE1, myMapF2, BE1, BF2);
291     DistanceMapMap(myMapF1, myMapE2, BF1, BE2);
292
293     if( (fabs(myDistRef)) > myEps )
294       DistanceMapMap(myMapF1,myMapF2,BF1,BF2);
295     
296     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:03 2001 Begin
297     Standard_Integer i = 1;
298     for (; i <= mySolutionsShape1.Length(); i++)
299       if (mySolutionsShape1.Value(i).Dist() > myDistRef + myEps)
300       {
301         mySolutionsShape1.Remove(i);
302         mySolutionsShape2.Remove(i);
303       }
304     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:04 2001 End
305     myIsDone = ( mySolutionsShape1.Length() > 0 );
306   }
307   return myIsDone;
308 }
309
310 //=======================================================================
311 //function : Value
312 //purpose  : 
313 //=======================================================================
314
315 Standard_Real BRepExtrema_DistShapeShape::Value() const 
316
317   if (!myIsDone)
318     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::Value: There's no solution ");
319
320   return myDistRef;
321 }
322
323 //=======================================================================
324 //function : SupportOnShape1
325 //purpose  : 
326 //=======================================================================
327
328 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape1(const Standard_Integer N) const
329
330   if (!myIsDone)
331     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::SupportOnShape1: There's no solution ");
332
333   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
334   switch (sol.SupportKind())
335   {
336     case BRepExtrema_IsVertex : return sol.Vertex();
337     case BRepExtrema_IsOnEdge : return sol.Edge();
338     case BRepExtrema_IsInFace : return sol.Face();
339   }
340   return TopoDS_Shape();
341 }
342
343 //=======================================================================
344 //function : SupportOnShape2
345 //purpose  : 
346 //=======================================================================
347
348 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape2(const Standard_Integer N) const 
349
350   if (!myIsDone)
351     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::SupportOnShape2: There's no solution ");
352
353   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
354   switch (sol.SupportKind())
355   {
356     case BRepExtrema_IsVertex : return sol.Vertex();
357     case BRepExtrema_IsOnEdge : return sol.Edge();
358     case BRepExtrema_IsInFace : return sol.Face();
359   }
360   return TopoDS_Shape();
361 }
362
363 //=======================================================================
364 //function : ParOnEdgeS1
365 //purpose  : 
366 //=======================================================================
367
368 void BRepExtrema_DistShapeShape::ParOnEdgeS1(const Standard_Integer N, Standard_Real& t) const 
369
370   if (!myIsDone)
371     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnEdgeS1: There's no solution");
372
373   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
374   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
375     BRepExtrema_UnCompatibleShape::Raise
376       ("BRepExtrema_DistShapeShape::ParOnEdgeS1: ParOnEdgeS1 is impossible without EDGE");
377
378   sol.EdgeParameter(t);
379 }
380
381 //=======================================================================
382 //function : ParOnEdgeS2
383 //purpose  : 
384 //=======================================================================
385
386 void BRepExtrema_DistShapeShape::ParOnEdgeS2(const Standard_Integer N,  Standard_Real& t) const 
387
388   if (!myIsDone)
389     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnEdgeS2: There's no solution");
390
391   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
392   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
393     BRepExtrema_UnCompatibleShape::Raise
394       ("BRepExtrema_DistShapeShape::ParOnEdgeS2: ParOnEdgeS2 is impossible without EDGE");
395  
396   sol.EdgeParameter(t);
397 }
398
399 //=======================================================================
400 //function : ParOnFaceS1
401 //purpose  : 
402 //=======================================================================
403
404 void BRepExtrema_DistShapeShape::ParOnFaceS1(const Standard_Integer N,  Standard_Real& u,  Standard_Real& v) const 
405
406   if (!myIsDone)
407     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnFaceS1: There's no solution");
408
409   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
410   if (sol.SupportKind() != BRepExtrema_IsInFace)
411     BRepExtrema_UnCompatibleShape::Raise
412       ("BRepExtrema_DistShapeShape::ParOnFaceS1: ParOnFaceS1 is impossible without FACE");
413   
414   sol.FaceParameter(u, v);
415 }
416
417 //=======================================================================
418 //function : ParOnFaceS2
419 //purpose  : 
420 //=======================================================================
421
422 void BRepExtrema_DistShapeShape::ParOnFaceS2(const Standard_Integer N,  Standard_Real& u, Standard_Real& v) const 
423
424   if (!myIsDone)
425     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnFaceS2: There's no solution");
426
427   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
428   if (sol.SupportKind() != BRepExtrema_IsInFace)
429     BRepExtrema_UnCompatibleShape::Raise
430       ("BRepExtrema_DistShapeShape::ParOnFaceS2:ParOnFaceS2 is impossible without FACE ");
431   
432   sol.FaceParameter(u, v);
433 }
434
435 //=======================================================================
436 //function : Dump
437 //purpose  : 
438 //=======================================================================
439
440 void BRepExtrema_DistShapeShape::Dump(Standard_OStream& o) const 
441 {
442   Standard_Integer i;
443   Standard_Real r1,r2;
444   
445   o<< "the distance  value is :  " << Value()<<endl;
446   o<< "the number of solutions is :"<<NbSolution()<<endl;
447   o<<endl;
448   for (i=1;i<=NbSolution();i++)
449   {
450     o<<"solution number "<<i<<": "<< endl;
451     o<<"the type of the solution on the first shape is " <<Standard_Integer( SupportTypeShape1(i)) <<endl; 
452     o<<"the type of the solution on the second shape is "<<Standard_Integer( SupportTypeShape2(i))<< endl;
453     o<< "the coordinates of  the point on the first shape are: "<<endl; 
454     o<<"X=" <<PointOnShape1(i).X()<<" Y=" <<PointOnShape1(i).Y()<<" Z="<<PointOnShape1(i).Z()<<endl;
455     o<< "the coordinates of  the point on the second shape are: "<<endl; 
456     o<<"X="<< PointOnShape2(i).X()<< " Y="<<PointOnShape2(i).Y()<<" Z="<< PointOnShape2(i).Z()<<endl;
457     
458     switch (SupportTypeShape1(i))
459     {
460       case BRepExtrema_IsVertex:
461         break;
462       case BRepExtrema_IsOnEdge:
463         ParOnEdgeS1(i,r1);
464         o << "parameter on the first edge :  t= " << r1 << endl;
465         break;
466       case BRepExtrema_IsInFace:
467         ParOnFaceS1(i,r1,r2);
468         o << "parameters on the first face :  u= " << r1 << " v=" <<  r2 << endl;
469         break;
470     }
471     switch (SupportTypeShape2(i))
472     {
473       case BRepExtrema_IsVertex:
474         break;
475       case BRepExtrema_IsOnEdge:
476         ParOnEdgeS2(i,r1);
477         o << "parameter on the second edge : t=" << r1 << endl;
478         break;
479       case BRepExtrema_IsInFace:
480         ParOnFaceS2(i,r1,r2);
481         o << "parameters on the second face : u= " << r1 << " v=" <<  r2 << endl;
482         break;
483     }
484     o<<endl;
485   } 
486 }