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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified: Mps(10-04-97) portage WNT
19 #include <BRepExtrema_DistShapeShape.hxx>
21 #include <Standard_OStream.hxx>
22 #include <TopTools_IndexedMapOfShape.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Bnd_Box.hxx>
26 #include <BRepExtrema_DistanceSS.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>
45 static void Decomposition(const TopoDS_Shape& S,
46 TopTools_IndexedMapOfShape& MapV,
47 TopTools_IndexedMapOfShape& MapE,
48 TopTools_IndexedMapOfShape& MapF)
53 TopExp::MapShapes(S,TopAbs_VERTEX,MapV);
54 TopExp::MapShapes(S,TopAbs_EDGE,MapE);
55 TopExp::MapShapes(S,TopAbs_FACE,MapF);
58 static void BoxCalculation(const TopTools_IndexedMapOfShape& Map,
61 for (Standard_Integer i = 1; i <= Map.Extent(); i++)
64 BRepBndLib::Add(Map(i), box);
69 inline Standard_Real DistanceInitiale(const TopoDS_Vertex V1,
70 const TopoDS_Vertex V2)
72 return (BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V2)));
75 //! Pair of objects to check extrema.
76 struct BRepExtrema_CheckPair
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
82 //! Uninitialized constructor for collection.
83 BRepExtrema_CheckPair()
90 //! Creates new pair of sub-shapes.
91 BRepExtrema_CheckPair (Standard_Integer theIndex1,
92 Standard_Integer theIndex2,
93 Standard_Real theDistance)
96 Distance (theDistance) {}
99 // Used by std::sort function
100 static Standard_Boolean BRepExtrema_CheckPair_Comparator (const BRepExtrema_CheckPair& theLeft,
101 const BRepExtrema_CheckPair& theRight)
103 return (theLeft.Distance < theRight.Distance);
107 //=======================================================================
108 //function : DistanceMapMap
110 //=======================================================================
112 Standard_Boolean BRepExtrema_DistShapeShape::DistanceMapMap (const TopTools_IndexedMapOfShape& theMap1,
113 const TopTools_IndexedMapOfShape& theMap2,
114 const Bnd_SeqOfBox& theLBox1,
115 const Bnd_SeqOfBox& theLBox2,
116 const Message_ProgressRange& theRange)
118 NCollection_Vector<BRepExtrema_CheckPair> aPairList;
119 const Standard_Integer aCount1 = theMap1.Extent();
120 const Standard_Integer aCount2 = theMap2.Extent();
122 Message_ProgressScope aTwinScope(theRange, NULL, 1.0);
123 Message_ProgressRange aBoxRange(aTwinScope.Next(0.3));
124 Message_ProgressScope aBoxScope(aBoxRange, NULL, aCount1);
126 for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1)
129 if (!aBoxScope.More())
131 return Standard_False;
133 for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2)
135 const Bnd_Box& aBox1 = theLBox1.Value (anIdx1);
136 const Bnd_Box& aBox2 = theLBox2.Value (anIdx2);
143 const Standard_Real aDist = aBox1.Distance (aBox2);
144 if (aDist < myDistRef - myEps || fabs (aDist - myDistRef) < myEps)
146 aPairList.Append (BRepExtrema_CheckPair (anIdx1, anIdx2, aDist));
150 std::stable_sort(aPairList.begin(), aPairList.end(), BRepExtrema_CheckPair_Comparator);
151 Message_ProgressRange aDistRange(aTwinScope.Next(0.7));
152 Message_ProgressScope aDistScope(aDistRange, NULL, aPairList.Size());
153 for (NCollection_Vector<BRepExtrema_CheckPair>::Iterator aPairIter (aPairList);
154 aPairIter.More(); aPairIter.Next())
157 if (!aDistScope.More())
159 return Standard_False;
161 const BRepExtrema_CheckPair& aPair = aPairIter.Value();
162 if (aPair.Distance > myDistRef + myEps)
164 break; // early search termination
167 const Bnd_Box& aBox1 = theLBox1.Value (aPair.Index1);
168 const Bnd_Box& aBox2 = theLBox2.Value (aPair.Index2);
170 const TopoDS_Shape& aShape1 = theMap1 (aPair.Index1);
171 const TopoDS_Shape& aShape2 = theMap2 (aPair.Index2);
173 BRepExtrema_DistanceSS aDistTool (aShape1, aShape2, aBox1, aBox2, myDistRef, myEps);
174 if (aDistTool.IsDone())
176 if (aDistTool.DistValue() < myDistRef - myEps)
178 mySolutionsShape1.Clear();
179 mySolutionsShape2.Clear();
181 BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
182 BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
184 mySolutionsShape1.Append (aSeq1);
185 mySolutionsShape2.Append (aSeq2);
187 myDistRef = aDistTool.DistValue();
189 else if (fabs (aDistTool.DistValue() - myDistRef) < myEps)
191 BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
192 BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
194 mySolutionsShape1.Append (aSeq1);
195 mySolutionsShape2.Append (aSeq2);
197 if (myDistRef > aDistTool.DistValue())
199 myDistRef = aDistTool.DistValue();
204 return Standard_True;
207 //=======================================================================
208 //function : DistanceVertVert
210 //=======================================================================
212 Standard_Boolean BRepExtrema_DistShapeShape::DistanceVertVert(const TopTools_IndexedMapOfShape& theMap1,
213 const TopTools_IndexedMapOfShape& theMap2,
214 const Message_ProgressRange& theRange)
216 const Standard_Integer aCount1 = theMap1.Extent();
217 const Standard_Integer aCount2 = theMap2.Extent();
219 Message_ProgressScope aScope(theRange, NULL, aCount1);
221 for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1)
226 return Standard_False;
228 const TopoDS_Vertex& aVertex1 = TopoDS::Vertex(theMap1.FindKey(anIdx1));
229 const gp_Pnt aPoint1 = BRep_Tool::Pnt(aVertex1);
230 for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2)
232 const TopoDS_Vertex& aVertex2 = TopoDS::Vertex(theMap2.FindKey(anIdx2));
233 const gp_Pnt aPoint2 = BRep_Tool::Pnt(aVertex2);
235 const Standard_Real aDist = aPoint1.Distance(aPoint2);
236 if (aDist < myDistRef - myEps)
238 mySolutionsShape1.Clear();
239 mySolutionsShape2.Clear();
241 const BRepExtrema_SolutionElem Sol1(aDist, aPoint1, BRepExtrema_IsVertex, aVertex1);
242 const BRepExtrema_SolutionElem Sol2(aDist, aPoint2, BRepExtrema_IsVertex, aVertex2);
243 mySolutionsShape1.Append(Sol1);
244 mySolutionsShape2.Append(Sol2);
248 else if (fabs(aDist - myDistRef) < myEps)
250 const BRepExtrema_SolutionElem Sol1(aDist, aPoint1, BRepExtrema_IsVertex, aVertex1);
251 const BRepExtrema_SolutionElem Sol2(aDist, aPoint2, BRepExtrema_IsVertex, aVertex2);
252 mySolutionsShape1.Append(Sol1);
253 mySolutionsShape2.Append(Sol2);
255 if (myDistRef > aDist)
262 return Standard_True;
265 //=======================================================================
266 //function : BRepExtrema_DistShapeShape
268 //=======================================================================
270 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape()
272 myIsDone (Standard_False),
273 myInnerSol (Standard_False),
274 myEps (Precision::Confusion()),
275 myIsInitS1 (Standard_False),
276 myIsInitS2 (Standard_False),
277 myFlag (Extrema_ExtFlag_MINMAX),
278 myAlgo (Extrema_ExtAlgo_Grad)
283 //=======================================================================
284 //function : BRepExtrema_DistShapeShape
286 //=======================================================================
287 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
288 const TopoDS_Shape& Shape2,
289 const Extrema_ExtFlag F,
290 const Extrema_ExtAlgo A,
291 const Message_ProgressRange& theRange)
293 myIsDone (Standard_False),
294 myInnerSol (Standard_False),
295 myEps (Precision::Confusion()),
296 myIsInitS1 (Standard_False),
297 myIsInitS2 (Standard_False),
306 //=======================================================================
307 //function : BRepExtrema_DistShapeShape
309 //=======================================================================
311 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
312 const TopoDS_Shape& Shape2,
313 const Standard_Real theDeflection,
314 const Extrema_ExtFlag F,
315 const Extrema_ExtAlgo A,
316 const Message_ProgressRange& theRange)
318 myIsDone (Standard_False),
319 myInnerSol (Standard_False),
320 myEps (theDeflection),
321 myIsInitS1 (Standard_False),
322 myIsInitS2 (Standard_False),
331 //=======================================================================
334 //=======================================================================
336 void BRepExtrema_DistShapeShape::LoadS1 (const TopoDS_Shape& Shape1)
339 myIsInitS1 = Standard_False;
340 Decomposition (Shape1, myMapV1, myMapE1, myMapF1);
343 //=======================================================================
346 //=======================================================================
348 void BRepExtrema_DistShapeShape::LoadS2 (const TopoDS_Shape& Shape2)
351 myIsInitS2 = Standard_False;
352 Decomposition (Shape2, myMapV2, myMapE2, myMapF2);
355 //=======================================================================
356 //function : SolidTreatment
358 //=======================================================================
359 Standard_Boolean BRepExtrema_DistShapeShape::SolidTreatment(const TopoDS_Shape& theShape,
360 const TopTools_IndexedMapOfShape& theMap,
361 const Message_ProgressRange& theRange)
363 BRepClass3d_SolidClassifier aClassifier(theShape);
364 const Standard_Real aTolerance = 0.001;
365 Message_ProgressScope aScope(theRange, NULL, theMap.Extent());
366 for (Standard_Integer i = 1; i < theMap.Extent(); ++i)
371 return Standard_False;
373 const TopoDS_Vertex& aVertex = TopoDS::Vertex(theMap(i));
374 const gp_Pnt& aPnt = BRep_Tool::Pnt(aVertex);
375 aClassifier.Perform(aPnt, aTolerance);
376 if (aClassifier.State() == TopAbs_IN)
378 myInnerSol = Standard_True;
380 myIsDone = Standard_True;
381 BRepExtrema_SolutionElem Sol(0, aPnt, BRepExtrema_IsVertex, aVertex);
382 mySolutionsShape1.Append(Sol);
383 mySolutionsShape2.Append(Sol);
387 return Standard_True;
390 //=======================================================================
393 //=======================================================================
395 Standard_Boolean BRepExtrema_DistShapeShape::Perform(const Message_ProgressRange& theRange)
397 myIsDone=Standard_False;
398 myInnerSol=Standard_False;
399 mySolutionsShape1.Clear();
400 mySolutionsShape2.Clear();
402 if ( myShape1.IsNull() || myShape2.IsNull() )
403 return Standard_False;
405 // Treatment of solids
406 Standard_Boolean anIsSolid1 = (myShape1.ShapeType() == TopAbs_SOLID) ||
407 (myShape1.ShapeType() == TopAbs_COMPSOLID);
408 Standard_Boolean anIsSolid2 = (myShape2.ShapeType() == TopAbs_SOLID) ||
409 (myShape2.ShapeType() == TopAbs_COMPSOLID);
410 Standard_Integer aRootStepsNum = 9; // By num of DistanceMapMap calls
411 aRootStepsNum = anIsSolid1 ? aRootStepsNum+1 : aRootStepsNum;
412 aRootStepsNum = anIsSolid2 ? aRootStepsNum+1 : aRootStepsNum;
413 Message_ProgressScope aRootScope(theRange, "calculating distance", aRootStepsNum);
417 if (!SolidTreatment(myShape1, myMapV2, aRootScope.Next()))
419 return Standard_False;
423 if (anIsSolid2 && (!myInnerSol))
425 if(!SolidTreatment(myShape2, myMapV1, aRootScope.Next()))
427 return Standard_False;
433 if (!myIsInitS1) // rebuild cached data for 1st shape
439 BoxCalculation (myMapV1, myBV1);
440 BoxCalculation (myMapE1, myBE1);
441 BoxCalculation (myMapF1, myBF1);
443 myIsInitS1 = Standard_True;
446 if (!myIsInitS2) // rebuild cached data for 2nd shape
452 BoxCalculation (myMapV2, myBV2);
453 BoxCalculation (myMapE2, myBE2);
454 BoxCalculation (myMapF2, myBF2);
456 myIsInitS2 = Standard_True;
459 if (myMapV1.Extent() && myMapV2.Extent())
461 TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
462 TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
463 myDistRef = DistanceInitiale(V1, V2);
466 myDistRef= 1.e30; //szv:!!!
468 if(!DistanceVertVert(myMapV1, myMapV2, aRootScope.Next()))
470 return Standard_False;
472 if(!DistanceMapMap (myMapV1, myMapE2, myBV1, myBE2, aRootScope.Next()))
474 return Standard_False;
476 if(!DistanceMapMap (myMapE1, myMapV2, myBE1, myBV2, aRootScope.Next()))
478 return Standard_False;
480 if(!DistanceMapMap (myMapV1, myMapF2, myBV1, myBF2, aRootScope.Next()))
482 return Standard_False;
484 if(!DistanceMapMap (myMapF1, myMapV2, myBF1, myBV2, aRootScope.Next()))
486 return Standard_False;
488 if(!DistanceMapMap (myMapE1, myMapE2, myBE1, myBE2, aRootScope.Next()))
490 return Standard_False;
492 if(!DistanceMapMap (myMapE1, myMapF2, myBE1, myBF2, aRootScope.Next()))
494 return Standard_False;
496 if(!DistanceMapMap (myMapF1, myMapE2, myBF1, myBE2, aRootScope.Next()))
498 return Standard_False;
501 if (fabs (myDistRef) > myEps)
503 if(!DistanceMapMap (myMapF1, myMapF2, myBF1, myBF2, aRootScope.Next()))
505 return Standard_False;
509 // Modified by Sergey KHROMOV - Tue Mar 6 11:55:03 2001 Begin
510 Standard_Integer i = 1;
511 for (; i <= mySolutionsShape1.Length(); i++)
512 if (mySolutionsShape1.Value(i).Dist() > myDistRef + myEps)
514 mySolutionsShape1.Remove(i);
515 mySolutionsShape2.Remove(i);
517 // Modified by Sergey KHROMOV - Tue Mar 6 11:55:04 2001 End
518 myIsDone = ( mySolutionsShape1.Length() > 0 );
524 //=======================================================================
527 //=======================================================================
529 Standard_Real BRepExtrema_DistShapeShape::Value() const
532 throw StdFail_NotDone("BRepExtrema_DistShapeShape::Value: There's no solution ");
537 //=======================================================================
538 //function : SupportOnShape1
540 //=======================================================================
542 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape1(const Standard_Integer N) const
545 throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape1: There's no solution ");
547 const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
548 switch (sol.SupportKind())
550 case BRepExtrema_IsVertex : return sol.Vertex();
551 case BRepExtrema_IsOnEdge : return sol.Edge();
552 case BRepExtrema_IsInFace : return sol.Face();
554 return TopoDS_Shape();
557 //=======================================================================
558 //function : SupportOnShape2
560 //=======================================================================
562 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape2(const Standard_Integer N) const
565 throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape2: There's no solution ");
567 const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
568 switch (sol.SupportKind())
570 case BRepExtrema_IsVertex : return sol.Vertex();
571 case BRepExtrema_IsOnEdge : return sol.Edge();
572 case BRepExtrema_IsInFace : return sol.Face();
574 return TopoDS_Shape();
577 //=======================================================================
578 //function : ParOnEdgeS1
580 //=======================================================================
582 void BRepExtrema_DistShapeShape::ParOnEdgeS1(const Standard_Integer N, Standard_Real& t) const
585 throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS1: There's no solution");
587 const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
588 if (sol.SupportKind() != BRepExtrema_IsOnEdge)
589 throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS1: ParOnEdgeS1 is impossible without EDGE");
591 sol.EdgeParameter(t);
594 //=======================================================================
595 //function : ParOnEdgeS2
597 //=======================================================================
599 void BRepExtrema_DistShapeShape::ParOnEdgeS2(const Standard_Integer N, Standard_Real& t) const
602 throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS2: There's no solution");
604 const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
605 if (sol.SupportKind() != BRepExtrema_IsOnEdge)
606 throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS2: ParOnEdgeS2 is impossible without EDGE");
608 sol.EdgeParameter(t);
611 //=======================================================================
612 //function : ParOnFaceS1
614 //=======================================================================
616 void BRepExtrema_DistShapeShape::ParOnFaceS1(const Standard_Integer N, Standard_Real& u, Standard_Real& v) const
619 throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS1: There's no solution");
621 const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
622 if (sol.SupportKind() != BRepExtrema_IsInFace)
623 throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS1: ParOnFaceS1 is impossible without FACE");
625 sol.FaceParameter(u, v);
628 //=======================================================================
629 //function : ParOnFaceS2
631 //=======================================================================
633 void BRepExtrema_DistShapeShape::ParOnFaceS2(const Standard_Integer N, Standard_Real& u, Standard_Real& v) const
636 throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS2: There's no solution");
638 const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
639 if (sol.SupportKind() != BRepExtrema_IsInFace)
640 throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS2:ParOnFaceS2 is impossible without FACE ");
642 sol.FaceParameter(u, v);
645 //=======================================================================
648 //=======================================================================
650 void BRepExtrema_DistShapeShape::Dump(Standard_OStream& o) const
655 o<< "the distance value is : " << Value()<<std::endl;
656 o<< "the number of solutions is :"<<NbSolution()<<std::endl;
658 for (i=1;i<=NbSolution();i++)
660 o<<"solution number "<<i<<": "<< std::endl;
661 o<<"the type of the solution on the first shape is " <<Standard_Integer( SupportTypeShape1(i)) <<std::endl;
662 o<<"the type of the solution on the second shape is "<<Standard_Integer( SupportTypeShape2(i))<< std::endl;
663 o<< "the coordinates of the point on the first shape are: "<<std::endl;
664 o<<"X=" <<PointOnShape1(i).X()<<" Y=" <<PointOnShape1(i).Y()<<" Z="<<PointOnShape1(i).Z()<<std::endl;
665 o<< "the coordinates of the point on the second shape are: "<<std::endl;
666 o<<"X="<< PointOnShape2(i).X()<< " Y="<<PointOnShape2(i).Y()<<" Z="<< PointOnShape2(i).Z()<<std::endl;
668 switch (SupportTypeShape1(i))
670 case BRepExtrema_IsVertex:
672 case BRepExtrema_IsOnEdge:
674 o << "parameter on the first edge : t= " << r1 << std::endl;
676 case BRepExtrema_IsInFace:
677 ParOnFaceS1(i,r1,r2);
678 o << "parameters on the first face : u= " << r1 << " v=" << r2 << std::endl;
681 switch (SupportTypeShape2(i))
683 case BRepExtrema_IsVertex:
685 case BRepExtrema_IsOnEdge:
687 o << "parameter on the second edge : t=" << r1 << std::endl;
689 case BRepExtrema_IsInFace:
690 ParOnFaceS2(i,r1,r2);
691 o << "parameters on the second face : u= " << r1 << " v=" << r2 << std::endl;