0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[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 under
9 // the terms of the GNU Lesser General Public License 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 <NCollection_Vector.hxx>
39 #include <StdFail_NotDone.hxx>
40
41 #include <algorithm>
42 namespace
43 {
44
45   static void Decomposition(const TopoDS_Shape&         S,
46                             TopTools_IndexedMapOfShape& MapV,
47                             TopTools_IndexedMapOfShape& MapE,
48                             TopTools_IndexedMapOfShape& MapF)
49   {
50     MapV.Clear();
51     MapE.Clear();
52     MapF.Clear();
53     TopExp::MapShapes(S,TopAbs_VERTEX,MapV);
54     TopExp::MapShapes(S,TopAbs_EDGE,MapE);
55     TopExp::MapShapes(S,TopAbs_FACE,MapF);
56   }
57
58   static void BoxCalculation(const TopTools_IndexedMapOfShape& Map,
59                              Bnd_SeqOfBox&                     SBox)
60   {
61     for (Standard_Integer i = 1; i <= Map.Extent(); i++)
62     {
63       Bnd_Box box;
64       BRepBndLib::Add(Map(i), box);
65       SBox.Append(box);
66     }
67   }
68
69   inline Standard_Real DistanceInitiale(const TopoDS_Vertex V1,
70                                         const TopoDS_Vertex V2)
71   {
72     return (BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V2)));
73   }
74
75   //! Pair of objects to check extrema.
76   struct BRepExtrema_CheckPair
77   {
78     Standard_Integer Index1;   //!< Index of the 1st sub-shape
79     Standard_Integer Index2;   //!< Index of the 2nd sub-shape
80     Standard_Real    Distance; //!< Distance between sub-shapes
81
82     //! Uninitialized constructor for collection.
83     BRepExtrema_CheckPair()
84     : Index1(0),
85       Index2(0),
86       Distance(0.0)
87     {
88     }
89
90     //! Creates new pair of sub-shapes.
91     BRepExtrema_CheckPair (Standard_Integer theIndex1,
92                            Standard_Integer theIndex2,
93                            Standard_Real    theDistance)
94     : Index1   (theIndex1),
95       Index2   (theIndex2),
96       Distance (theDistance) {}
97   };
98
99   // Used by std::sort function
100   static Standard_Boolean BRepExtrema_CheckPair_Comparator (const BRepExtrema_CheckPair& theLeft,
101                                                             const BRepExtrema_CheckPair& theRight)
102   {
103     return (theLeft.Distance < theRight.Distance);
104   }
105 }
106
107 //=======================================================================
108 //function : DistanceMapMap
109 //purpose  : 
110 //=======================================================================
111
112 void BRepExtrema_DistShapeShape::DistanceMapMap (const TopTools_IndexedMapOfShape& theMap1,
113                                                  const TopTools_IndexedMapOfShape& theMap2,
114                                                  const Bnd_SeqOfBox&               theLBox1,
115                                                  const Bnd_SeqOfBox&               theLBox2)
116 {
117   NCollection_Vector<BRepExtrema_CheckPair> aPairList;
118   const Standard_Integer aCount1 = theMap1.Extent();
119   const Standard_Integer aCount2 = theMap2.Extent();
120   for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1)
121   {
122     for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2)
123     {
124       const Bnd_Box& aBox1 = theLBox1.Value (anIdx1);
125       const Bnd_Box& aBox2 = theLBox2.Value (anIdx2);
126       if (aBox1.IsVoid()
127        || aBox2.IsVoid())
128       {
129         continue;
130       }
131
132       const Standard_Real aDist = aBox1.Distance (aBox2);
133       if (aDist < myDistRef - myEps || fabs (aDist - myDistRef) < myEps)
134       {
135         aPairList.Append (BRepExtrema_CheckPair (anIdx1, anIdx2, aDist));
136       }
137     }
138   }
139
140   std::stable_sort(aPairList.begin(), aPairList.end(), BRepExtrema_CheckPair_Comparator);
141
142   for (NCollection_Vector<BRepExtrema_CheckPair>::Iterator aPairIter (aPairList);
143        aPairIter.More(); aPairIter.Next())
144   {
145     const BRepExtrema_CheckPair& aPair = aPairIter.Value();
146     if (aPair.Distance > myDistRef + myEps)
147     {
148       break; // early search termination
149     }
150
151     const Bnd_Box& aBox1 = theLBox1.Value (aPair.Index1);
152     const Bnd_Box& aBox2 = theLBox2.Value (aPair.Index2);
153
154     const TopoDS_Shape& aShape1 = theMap1 (aPair.Index1);
155     const TopoDS_Shape& aShape2 = theMap2 (aPair.Index2);
156
157     BRepExtrema_DistanceSS aDistTool (aShape1, aShape2, aBox1, aBox2, myDistRef, myEps);
158     if (aDistTool.IsDone())
159     {
160       if (aDistTool.DistValue() < myDistRef - myEps)
161       {
162         mySolutionsShape1.Clear();
163         mySolutionsShape2.Clear();
164
165         BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
166         BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
167
168         mySolutionsShape1.Append (aSeq1);
169         mySolutionsShape2.Append (aSeq2);
170
171         myDistRef = aDistTool.DistValue();
172       }
173       else if (fabs (aDistTool.DistValue() - myDistRef) < myEps)
174       {
175         BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
176         BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
177
178         mySolutionsShape1.Append (aSeq1);
179         mySolutionsShape2.Append (aSeq2);
180
181         if (myDistRef > aDistTool.DistValue())
182         {
183           myDistRef = aDistTool.DistValue();
184         }
185       }
186     }
187   }
188 }
189
190 //=======================================================================
191 //function : BRepExtrema_DistShapeShape
192 //purpose  : 
193 //=======================================================================
194
195 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape()
196 : myDistRef (0.0),
197   myIsDone (Standard_False),
198   myInnerSol (Standard_False),
199   myEps (Precision::Confusion()),
200   myIsInitS1 (Standard_False),
201   myIsInitS2 (Standard_False),
202   myFlag (Extrema_ExtFlag_MINMAX),
203   myAlgo (Extrema_ExtAlgo_Grad)
204 {
205   //
206 }
207
208 //=======================================================================
209 //function : BRepExtrema_DistShapeShape
210 //purpose  : 
211 //=======================================================================
212 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
213                                                        const TopoDS_Shape& Shape2,
214                                                        const Extrema_ExtFlag F,
215                                                        const Extrema_ExtAlgo A)
216 : myDistRef (0.0),
217   myIsDone (Standard_False),
218   myInnerSol (Standard_False),
219   myEps (Precision::Confusion()),
220   myIsInitS1 (Standard_False),
221   myIsInitS2 (Standard_False),
222   myFlag (F),
223   myAlgo (A)
224 {
225   LoadS1(Shape1);
226   LoadS2(Shape2);
227   Perform();
228 }
229
230 //=======================================================================
231 //function : BRepExtrema_DistShapeShape
232 //purpose  : 
233 //=======================================================================
234
235 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
236                                                        const TopoDS_Shape& Shape2,
237                                                        const Standard_Real theDeflection,
238                                                        const Extrema_ExtFlag F,
239                                                        const Extrema_ExtAlgo A)
240 : myDistRef (0.0),
241   myIsDone (Standard_False),
242   myInnerSol (Standard_False),
243   myEps (theDeflection),
244   myIsInitS1 (Standard_False),
245   myIsInitS2 (Standard_False),
246   myFlag (F),
247   myAlgo (A)
248 {
249   LoadS1(Shape1);
250   LoadS2(Shape2);
251   Perform();
252 }
253
254 //=======================================================================
255 //function : LoadS1
256 //purpose  : 
257 //=======================================================================
258
259 void BRepExtrema_DistShapeShape::LoadS1 (const TopoDS_Shape& Shape1)
260 {
261   myShape1 = Shape1;
262   myIsInitS1 = Standard_False;
263   Decomposition (Shape1, myMapV1, myMapE1, myMapF1);
264 }
265
266 //=======================================================================
267 //function : LoadS2
268 //purpose  : 
269 //=======================================================================
270
271 void BRepExtrema_DistShapeShape::LoadS2 (const TopoDS_Shape& Shape2)
272 {
273   myShape2 = Shape2;
274   myIsInitS2 = Standard_False;
275   Decomposition (Shape2, myMapV2, myMapE2, myMapF2);
276 }
277
278 //=======================================================================
279 //function : Perform
280 //purpose  : 
281 //=======================================================================
282
283 Standard_Boolean BRepExtrema_DistShapeShape::Perform()
284 {
285   myIsDone=Standard_False;
286   myInnerSol=Standard_False;
287   mySolutionsShape1.Clear();
288   mySolutionsShape2.Clear();
289
290   if ( myShape1.IsNull() || myShape2.IsNull() )
291     return Standard_False;
292
293   TopoDS_Vertex V;
294   const Standard_Real tol = 0.001;
295
296   // Treatment of solids
297   const TopAbs_ShapeEnum Type1 = myShape1.ShapeType();
298   if ((Type1==TopAbs_SOLID) || (Type1 == TopAbs_COMPSOLID))
299   {
300     BRepClass3d_SolidClassifier Classi(myShape1);
301     const Standard_Integer nbv2 = myMapV2.Extent();
302     Standard_Integer nbv1 = 0;
303     while ( (nbv1<nbv2) && (!myInnerSol) )
304     {
305       nbv1++;
306       V = TopoDS::Vertex(myMapV2(nbv1));
307       const gp_Pnt &P = BRep_Tool::Pnt(V);
308       Classi.Perform(P,tol);
309       if (Classi.State()==TopAbs_IN)
310       {
311         myInnerSol = Standard_True;
312         myDistRef = 0.;
313         myIsDone = Standard_True; 
314         BRepExtrema_SolutionElem Sol(0,P,BRepExtrema_IsVertex,V);
315         mySolutionsShape1.Append(Sol);
316         mySolutionsShape2.Append(Sol);
317       }  
318     }
319   }
320   
321   const TopAbs_ShapeEnum Type2 = myShape2.ShapeType();
322   if (((Type2==TopAbs_SOLID) || (Type2==TopAbs_COMPSOLID)) && (!myInnerSol))
323   {
324     BRepClass3d_SolidClassifier Classi(myShape2);
325     const Standard_Integer nbv1 = myMapV1.Extent();
326     Standard_Integer nbv2 = 0;
327     while ( (nbv2<nbv1) && (!myInnerSol) )
328     {
329       nbv2++;
330       V = TopoDS::Vertex(myMapV1(nbv2));
331       const gp_Pnt &P = BRep_Tool::Pnt(V);
332       Classi.Perform(P,tol);
333       if (Classi.State()==TopAbs_IN) {
334         myInnerSol = Standard_True;
335         myDistRef = 0;
336         myIsDone = Standard_True; 
337         BRepExtrema_SolutionElem Sol (0,P,BRepExtrema_IsVertex,V);
338         mySolutionsShape1.Append(Sol);
339         mySolutionsShape2.Append(Sol);
340       }
341     }
342   }
343
344   if (!myInnerSol)
345   {
346     if (!myIsInitS1) // rebuild cached data for 1st shape
347     {
348       myBV1.Clear();
349       myBE1.Clear();
350       myBF1.Clear();
351
352       BoxCalculation (myMapV1, myBV1);
353       BoxCalculation (myMapE1, myBE1);
354       BoxCalculation (myMapF1, myBF1);
355
356       myIsInitS1 = Standard_True;
357     }
358
359     if (!myIsInitS2) // rebuild cached data for 2nd shape
360     {
361       myBV2.Clear();
362       myBE2.Clear();
363       myBF2.Clear();
364
365       BoxCalculation (myMapV2, myBV2);
366       BoxCalculation (myMapE2, myBE2);
367       BoxCalculation (myMapF2, myBF2);
368
369       myIsInitS2 = Standard_True;
370     }
371
372     if (myMapV1.Extent() && myMapV2.Extent())
373     {
374       TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
375       TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
376       myDistRef = DistanceInitiale(V1, V2);
377     }
378     else
379       myDistRef= 1.e30; //szv:!!!
380
381     DistanceMapMap (myMapV1, myMapV2, myBV1, myBV2);
382     DistanceMapMap (myMapV1, myMapE2, myBV1, myBE2);
383     DistanceMapMap (myMapE1, myMapV2, myBE1, myBV2);
384     DistanceMapMap (myMapV1, myMapF2, myBV1, myBF2);
385     DistanceMapMap (myMapF1, myMapV2, myBF1, myBV2);
386     DistanceMapMap (myMapE1, myMapE2, myBE1, myBE2);
387     DistanceMapMap (myMapE1, myMapF2, myBE1, myBF2);
388     DistanceMapMap (myMapF1, myMapE2, myBF1, myBE2);
389
390     if (fabs (myDistRef) > myEps)
391     {
392       DistanceMapMap (myMapF1, myMapF2, myBF1, myBF2);
393     }
394     
395     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:03 2001 Begin
396     Standard_Integer i = 1;
397     for (; i <= mySolutionsShape1.Length(); i++)
398       if (mySolutionsShape1.Value(i).Dist() > myDistRef + myEps)
399       {
400         mySolutionsShape1.Remove(i);
401         mySolutionsShape2.Remove(i);
402       }
403     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:04 2001 End
404     myIsDone = ( mySolutionsShape1.Length() > 0 );
405   }
406   return myIsDone;
407 }
408
409 //=======================================================================
410 //function : Value
411 //purpose  : 
412 //=======================================================================
413
414 Standard_Real BRepExtrema_DistShapeShape::Value() const 
415
416   if (!myIsDone)
417     throw StdFail_NotDone("BRepExtrema_DistShapeShape::Value: There's no solution ");
418
419   return myDistRef;
420 }
421
422 //=======================================================================
423 //function : SupportOnShape1
424 //purpose  : 
425 //=======================================================================
426
427 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape1(const Standard_Integer N) const
428
429   if (!myIsDone)
430     throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape1: There's no solution ");
431
432   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
433   switch (sol.SupportKind())
434   {
435     case BRepExtrema_IsVertex : return sol.Vertex();
436     case BRepExtrema_IsOnEdge : return sol.Edge();
437     case BRepExtrema_IsInFace : return sol.Face();
438   }
439   return TopoDS_Shape();
440 }
441
442 //=======================================================================
443 //function : SupportOnShape2
444 //purpose  : 
445 //=======================================================================
446
447 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape2(const Standard_Integer N) const 
448
449   if (!myIsDone)
450     throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape2: There's no solution ");
451
452   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
453   switch (sol.SupportKind())
454   {
455     case BRepExtrema_IsVertex : return sol.Vertex();
456     case BRepExtrema_IsOnEdge : return sol.Edge();
457     case BRepExtrema_IsInFace : return sol.Face();
458   }
459   return TopoDS_Shape();
460 }
461
462 //=======================================================================
463 //function : ParOnEdgeS1
464 //purpose  : 
465 //=======================================================================
466
467 void BRepExtrema_DistShapeShape::ParOnEdgeS1(const Standard_Integer N, Standard_Real& t) const 
468
469   if (!myIsDone)
470     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS1: There's no solution");
471
472   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
473   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
474     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS1: ParOnEdgeS1 is impossible without EDGE");
475
476   sol.EdgeParameter(t);
477 }
478
479 //=======================================================================
480 //function : ParOnEdgeS2
481 //purpose  : 
482 //=======================================================================
483
484 void BRepExtrema_DistShapeShape::ParOnEdgeS2(const Standard_Integer N,  Standard_Real& t) const 
485
486   if (!myIsDone)
487     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS2: There's no solution");
488
489   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
490   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
491     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS2: ParOnEdgeS2 is impossible without EDGE");
492  
493   sol.EdgeParameter(t);
494 }
495
496 //=======================================================================
497 //function : ParOnFaceS1
498 //purpose  : 
499 //=======================================================================
500
501 void BRepExtrema_DistShapeShape::ParOnFaceS1(const Standard_Integer N,  Standard_Real& u,  Standard_Real& v) const 
502
503   if (!myIsDone)
504     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS1: There's no solution");
505
506   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
507   if (sol.SupportKind() != BRepExtrema_IsInFace)
508     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS1: ParOnFaceS1 is impossible without FACE");
509   
510   sol.FaceParameter(u, v);
511 }
512
513 //=======================================================================
514 //function : ParOnFaceS2
515 //purpose  : 
516 //=======================================================================
517
518 void BRepExtrema_DistShapeShape::ParOnFaceS2(const Standard_Integer N,  Standard_Real& u, Standard_Real& v) const 
519
520   if (!myIsDone)
521     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS2: There's no solution");
522
523   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
524   if (sol.SupportKind() != BRepExtrema_IsInFace)
525     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS2:ParOnFaceS2 is impossible without FACE ");
526   
527   sol.FaceParameter(u, v);
528 }
529
530 //=======================================================================
531 //function : Dump
532 //purpose  : 
533 //=======================================================================
534
535 void BRepExtrema_DistShapeShape::Dump(Standard_OStream& o) const 
536 {
537   Standard_Integer i;
538   Standard_Real r1,r2;
539   
540   o<< "the distance  value is :  " << Value()<<std::endl;
541   o<< "the number of solutions is :"<<NbSolution()<<std::endl;
542   o<<std::endl;
543   for (i=1;i<=NbSolution();i++)
544   {
545     o<<"solution number "<<i<<": "<< std::endl;
546     o<<"the type of the solution on the first shape is " <<Standard_Integer( SupportTypeShape1(i)) <<std::endl; 
547     o<<"the type of the solution on the second shape is "<<Standard_Integer( SupportTypeShape2(i))<< std::endl;
548     o<< "the coordinates of  the point on the first shape are: "<<std::endl; 
549     o<<"X=" <<PointOnShape1(i).X()<<" Y=" <<PointOnShape1(i).Y()<<" Z="<<PointOnShape1(i).Z()<<std::endl;
550     o<< "the coordinates of  the point on the second shape are: "<<std::endl; 
551     o<<"X="<< PointOnShape2(i).X()<< " Y="<<PointOnShape2(i).Y()<<" Z="<< PointOnShape2(i).Z()<<std::endl;
552     
553     switch (SupportTypeShape1(i))
554     {
555       case BRepExtrema_IsVertex:
556         break;
557       case BRepExtrema_IsOnEdge:
558         ParOnEdgeS1(i,r1);
559         o << "parameter on the first edge :  t= " << r1 << std::endl;
560         break;
561       case BRepExtrema_IsInFace:
562         ParOnFaceS1(i,r1,r2);
563         o << "parameters on the first face :  u= " << r1 << " v=" <<  r2 << std::endl;
564         break;
565     }
566     switch (SupportTypeShape2(i))
567     {
568       case BRepExtrema_IsVertex:
569         break;
570       case BRepExtrema_IsOnEdge:
571         ParOnEdgeS2(i,r1);
572         o << "parameter on the second edge : t=" << r1 << std::endl;
573         break;
574       case BRepExtrema_IsInFace:
575         ParOnFaceS2(i,r1,r2);
576         o << "parameters on the second face : u= " << r1 << " v=" <<  r2 << std::endl;
577         break;
578     }
579     o<<std::endl;
580   } 
581 }