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