OCC22322 Improvement extrema Additional integration
[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     while ( (nbv1<nbv2) && (!myInnerSol) )
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   }
232   
233   const TopAbs_ShapeEnum Type2 = myShape2.ShapeType();
234   if (((Type2==TopAbs_SOLID) || (Type2==TopAbs_COMPSOLID)) && (!myInnerSol))
235   {
236     BRepClass3d_SolidClassifier Classi(myShape2);
237     const Standard_Integer nbv1 = myMapV1.Extent();
238     Standard_Integer nbv2 = 0;
239     while ( (nbv2<nbv1) && (!myInnerSol) )
240     {
241       nbv2++;
242       V = TopoDS::Vertex(myMapV1(nbv2));
243       const gp_Pnt &P = BRep_Tool::Pnt(V);
244       Classi.Perform(P,tol);
245       if (Classi.State()==TopAbs_IN) {
246         myInnerSol = Standard_True;
247         myDistRef = 0;
248         myIsDone = Standard_True; 
249         BRepExtrema_SolutionElem Sol (0,P,BRepExtrema_IsVertex,V);
250         mySolutionsShape1.Append(Sol);
251         mySolutionsShape2.Append(Sol);
252       }
253     }
254   }
255   
256   if (!myInnerSol)
257   {
258     BoxCalculation(myMapV1,BV1);
259     BoxCalculation(myMapE1,BE1);
260     BoxCalculation(myMapF1,BF1);
261     BoxCalculation(myMapV2,BV2);
262     BoxCalculation(myMapE2,BE2);
263     BoxCalculation(myMapF2,BF2);
264     
265     if (myMapV1.Extent() && myMapV2.Extent())
266     {
267       TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
268       TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
269       myDistRef = DistanceInitiale(V1, V2);
270     }
271     else
272       myDistRef= 1.e30; //szv:!!!
273
274     DistanceMapMap(myMapV1, myMapV2, BV1, BV2);
275     DistanceMapMap(myMapV1, myMapE2, BV1, BE2);
276     DistanceMapMap(myMapE1, myMapV2, BE1, BV2);
277     DistanceMapMap(myMapV1, myMapF2, BV1, BF2);
278     DistanceMapMap(myMapF1, myMapV2, BF1, BV2);
279     DistanceMapMap(myMapE1, myMapE2, BE1, BE2);
280     DistanceMapMap(myMapE1, myMapF2, BE1, BF2);
281     DistanceMapMap(myMapF1, myMapE2, BF1, BE2);
282
283     if( (fabs(myDistRef)) > myEps )
284       DistanceMapMap(myMapF1,myMapF2,BF1,BF2);
285     
286     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:03 2001 Begin
287     Standard_Integer i = 1;
288     for (; i <= mySolutionsShape1.Length(); i++)
289       if (mySolutionsShape1.Value(i).Dist() > myDistRef + myEps)
290       {
291         mySolutionsShape1.Remove(i);
292         mySolutionsShape2.Remove(i);
293       }
294     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:04 2001 End
295     myIsDone = ( mySolutionsShape1.Length() > 0 );
296   }
297   return myIsDone;
298 }
299
300 //=======================================================================
301 //function : Value
302 //purpose  : 
303 //=======================================================================
304
305 Standard_Real BRepExtrema_DistShapeShape::Value() const 
306
307   if (!myIsDone)
308     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::Value: There's no solution ");
309
310   return myDistRef;
311 }
312
313 //=======================================================================
314 //function : SupportOnShape1
315 //purpose  : 
316 //=======================================================================
317
318 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape1(const Standard_Integer N) const
319
320   if (!myIsDone)
321     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::SupportOnShape1: There's no solution ");
322
323   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
324   switch (sol.SupportKind())
325   {
326     case BRepExtrema_IsVertex : return sol.Vertex();
327     case BRepExtrema_IsOnEdge : return sol.Edge();
328     case BRepExtrema_IsInFace : return sol.Face();
329   }
330   return TopoDS_Shape();
331 }
332
333 //=======================================================================
334 //function : SupportOnShape2
335 //purpose  : 
336 //=======================================================================
337
338 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape2(const Standard_Integer N) const 
339
340   if (!myIsDone)
341     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::SupportOnShape2: There's no solution ");
342
343   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
344   switch (sol.SupportKind())
345   {
346     case BRepExtrema_IsVertex : return sol.Vertex();
347     case BRepExtrema_IsOnEdge : return sol.Edge();
348     case BRepExtrema_IsInFace : return sol.Face();
349   }
350   return TopoDS_Shape();
351 }
352
353 //=======================================================================
354 //function : ParOnEdgeS1
355 //purpose  : 
356 //=======================================================================
357
358 void BRepExtrema_DistShapeShape::ParOnEdgeS1(const Standard_Integer N, Standard_Real& t) const 
359
360   if (!myIsDone)
361     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnEdgeS1: There's no solution");
362
363   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
364   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
365     BRepExtrema_UnCompatibleShape::Raise
366       ("BRepExtrema_DistShapeShape::ParOnEdgeS1: ParOnEdgeS1 is impossible without EDGE");
367
368   sol.EdgeParameter(t);
369 }
370
371 //=======================================================================
372 //function : ParOnEdgeS2
373 //purpose  : 
374 //=======================================================================
375
376 void BRepExtrema_DistShapeShape::ParOnEdgeS2(const Standard_Integer N,  Standard_Real& t) const 
377
378   if (!myIsDone)
379     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnEdgeS2: There's no solution");
380
381   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
382   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
383     BRepExtrema_UnCompatibleShape::Raise
384       ("BRepExtrema_DistShapeShape::ParOnEdgeS2: ParOnEdgeS2 is impossible without EDGE");
385  
386   sol.EdgeParameter(t);
387 }
388
389 //=======================================================================
390 //function : ParOnFaceS1
391 //purpose  : 
392 //=======================================================================
393
394 void BRepExtrema_DistShapeShape::ParOnFaceS1(const Standard_Integer N,  Standard_Real& u,  Standard_Real& v) const 
395
396   if (!myIsDone)
397     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnFaceS1: There's no solution");
398
399   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
400   if (sol.SupportKind() != BRepExtrema_IsInFace)
401     BRepExtrema_UnCompatibleShape::Raise
402       ("BRepExtrema_DistShapeShape::ParOnFaceS1: ParOnFaceS1 is impossible without FACE");
403   
404   sol.FaceParameter(u, v);
405 }
406
407 //=======================================================================
408 //function : ParOnFaceS2
409 //purpose  : 
410 //=======================================================================
411
412 void BRepExtrema_DistShapeShape::ParOnFaceS2(const Standard_Integer N,  Standard_Real& u, Standard_Real& v) const 
413
414   if (!myIsDone)
415     StdFail_NotDone::Raise("BRepExtrema_DistShapeShape::ParOnFaceS2: There's no solution");
416
417   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
418   if (sol.SupportKind() != BRepExtrema_IsInFace)
419     BRepExtrema_UnCompatibleShape::Raise
420       ("BRepExtrema_DistShapeShape::ParOnFaceS2:ParOnFaceS2 is impossible without FACE ");
421   
422   sol.FaceParameter(u, v);
423 }
424
425 //=======================================================================
426 //function : Dump
427 //purpose  : 
428 //=======================================================================
429
430 void BRepExtrema_DistShapeShape::Dump(Standard_OStream& o) const 
431 {
432   Standard_Integer i;
433   Standard_Real r1,r2;
434   
435   o<< "the distance  value is :  " << Value()<<endl;
436   o<< "the number of solutions is :"<<NbSolution()<<endl;
437   o<<endl;
438   for (i=1;i<=NbSolution();i++)
439   {
440     o<<"solution number "<<i<<": "<< endl;
441     o<<"the type of the solution on the first shape is " <<Standard_Integer( SupportTypeShape1(i)) <<endl; 
442     o<<"the type of the solution on the second shape is "<<Standard_Integer( SupportTypeShape2(i))<< endl;
443     o<< "the coordinates of  the point on the first shape are: "<<endl; 
444     o<<"X=" <<PointOnShape1(i).X()<<" Y=" <<PointOnShape1(i).Y()<<" Z="<<PointOnShape1(i).Z()<<endl;
445     o<< "the coordinates of  the point on the second shape are: "<<endl; 
446     o<<"X="<< PointOnShape2(i).X()<< " Y="<<PointOnShape2(i).Y()<<" Z="<< PointOnShape2(i).Z()<<endl;
447     
448     switch (SupportTypeShape1(i))
449     {
450       case BRepExtrema_IsOnEdge:
451         ParOnEdgeS1(i,r1);
452         o << "parameter on the first edge :  t= " << r1 << endl;
453         break;
454       case BRepExtrema_IsInFace:
455         ParOnFaceS1(i,r1,r2);
456         o << "parameters on the first face :  u= " << r1 << " v=" <<  r2 << endl;
457         break;
458     }
459     switch (SupportTypeShape2(i))
460     {
461       case BRepExtrema_IsOnEdge:
462         ParOnEdgeS2(i,r1);
463         o << "parameter on the second edge : t=" << r1 << endl;
464         break;
465       case BRepExtrema_IsInFace:
466         ParOnFaceS2(i,r1,r2);
467         o << "parameters on the second face : u= " << r1 << " v=" <<  r2 << endl;
468         break;
469     }
470     o<<endl;
471   } 
472 }