1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include <Standard_Stream.hxx>
25 #include <GEOMUtils.hxx>
27 #include <Basics_OCCTVersion.hxx>
29 #include <utilities.h>
31 #include <Utils_ExceptHandlers.hxx>
34 #include <BRepMesh_IncrementalMesh.hxx>
36 #include <BRepExtrema_DistShapeShape.hxx>
38 #include <BRep_Builder.hxx>
39 #include <BRep_Tool.hxx>
40 #include <BRepBndLib.hxx>
41 #include <BRepGProp.hxx>
42 #include <BRepTools.hxx>
44 #include <BRepClass3d_SolidClassifier.hxx>
46 #include <BRepBuilderAPI_MakeFace.hxx>
48 #include <Bnd_Box.hxx>
53 #include <TopoDS_Edge.hxx>
54 #include <TopoDS_Face.hxx>
55 #include <TopoDS_Shape.hxx>
56 #include <TopoDS_Vertex.hxx>
57 #include <TopoDS_Compound.hxx>
58 #include <TopoDS_Iterator.hxx>
59 #include <TopExp_Explorer.hxx>
60 #include <TopTools_MapOfShape.hxx>
61 #include <TopTools_ListOfShape.hxx>
62 #include <TopTools_ListIteratorOfListOfShape.hxx>
63 #include <TopTools_Array1OfShape.hxx>
65 #include <Geom_Circle.hxx>
66 #include <Geom_Surface.hxx>
67 #include <Geom_Plane.hxx>
68 #include <Geom_SphericalSurface.hxx>
69 #include <Geom_ToroidalSurface.hxx>
70 #include <Geom_RectangularTrimmedSurface.hxx>
72 #include <GeomLProp_CLProps.hxx>
73 #include <GeomLProp_SLProps.hxx>
75 #include <GProp_GProps.hxx>
76 #include <GProp_PrincipalProps.hxx>
78 #include <TColStd_Array1OfReal.hxx>
83 #include <ShapeAnalysis.hxx>
84 #include <ShapeFix_Shape.hxx>
86 #include <ProjLib.hxx>
92 #include <Standard_Failure.hxx>
93 #include <Standard_NullObject.hxx>
94 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
96 #define STD_SORT_ALGO 1
100 //=======================================================================
101 //function : GetPosition
103 //=======================================================================
104 gp_Ax3 GetPosition (const TopoDS_Shape& theShape)
108 if (theShape.IsNull())
112 aResult.Transform(theShape.Location().Transformation());
113 if (theShape.ShapeType() == TopAbs_FACE) {
114 Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape));
115 if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) {
116 Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS);
117 gp_Pln aPln = aGPlane->Pln();
118 aResult = aPln.Position();
119 // In case of reverse orinetation of the face invert the plane normal
120 // (the face's normal does not mathc the plane's normal in this case)
121 if(theShape.Orientation() == TopAbs_REVERSED)
123 gp_Dir Vx = aResult.XDirection();
124 gp_Dir N = aResult.Direction().Mirrored(Vx);
125 gp_Pnt P = aResult.Location();
126 aResult = gp_Ax3(P, N, Vx);
134 TopAbs_ShapeEnum aShType = theShape.ShapeType();
136 if (aShType == TopAbs_VERTEX) {
137 aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
140 if (aShType == TopAbs_COMPOUND) {
141 aShType = GetTypeOfSimplePart(theShape);
144 GProp_GProps aSystem;
145 if (aShType == TopAbs_EDGE || aShType == TopAbs_WIRE)
146 BRepGProp::LinearProperties(theShape, aSystem);
147 else if (aShType == TopAbs_FACE || aShType == TopAbs_SHELL)
148 BRepGProp::SurfaceProperties(theShape, aSystem);
150 BRepGProp::VolumeProperties(theShape, aSystem);
152 aPnt = aSystem.CentreOfMass();
155 aResult.SetLocation(aPnt);
160 //=======================================================================
161 //function : GetVector
163 //=======================================================================
164 gp_Vec GetVector (const TopoDS_Shape& theShape,
165 Standard_Boolean doConsiderOrientation)
167 if (theShape.IsNull())
168 Standard_NullObject::Raise("Null shape is given for a vector");
170 if (theShape.ShapeType() != TopAbs_EDGE)
171 Standard_TypeMismatch::Raise("Invalid shape is given, must be a vector or an edge");
173 TopoDS_Edge anE = TopoDS::Edge(theShape);
175 TopoDS_Vertex V1, V2;
176 TopExp::Vertices(anE, V1, V2, doConsiderOrientation);
178 if (V1.IsNull() || V2.IsNull())
179 Standard_NullObject::Raise("Invalid edge is given, it must have two points");
181 gp_Vec aV (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
182 if (aV.Magnitude() < gp::Resolution()) {
183 Standard_ConstructionError::Raise("Vector of zero length is given");
189 //=======================================================================
190 //function : ShapeToDouble
191 //purpose : used by CompareShapes::operator()
192 //=======================================================================
193 std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting)
195 // Computing of CentreOfMass
199 if (S.ShapeType() == TopAbs_VERTEX) {
200 GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
201 Len = (double)S.Orientation();
205 // BEGIN: fix for Mantis issue 0020842
207 BRepGProp::LinearProperties(S, GPr);
210 if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
211 BRepGProp::LinearProperties(S, GPr);
213 else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
214 BRepGProp::SurfaceProperties(S, GPr);
217 BRepGProp::VolumeProperties(S, GPr);
220 // END: fix for Mantis issue 0020842
221 GPoint = GPr.CentreOfMass();
225 double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
226 return std::make_pair(dMidXYZ, Len);
229 //=======================================================================
230 //function : CompareShapes::operator()
231 //purpose : used by std::sort(), called from SortShapes()
232 //=======================================================================
233 bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
234 const TopoDS_Shape& theShape2)
236 if (!myMap.IsBound(theShape1)) {
237 myMap.Bind(theShape1, ShapeToDouble(theShape1, myIsOldSorting));
240 if (!myMap.IsBound(theShape2)) {
241 myMap.Bind(theShape2, ShapeToDouble(theShape2, myIsOldSorting));
244 std::pair<double, double> val1 = myMap.Find(theShape1);
245 std::pair<double, double> val2 = myMap.Find(theShape2);
247 double tol = Precision::Confusion();
248 bool exchange = Standard_False;
250 double dMidXYZ = val1.first - val2.first;
251 if (dMidXYZ >= tol) {
252 exchange = Standard_True;
254 else if (Abs(dMidXYZ) < tol) {
255 double dLength = val1.second - val2.second;
256 if (dLength >= tol) {
257 exchange = Standard_True;
259 else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
261 // equal values possible on shapes such as two halves of a sphere and
262 // a membrane inside the sphere
264 BRepBndLib::Add(theShape1, box1);
265 if (!box1.IsVoid()) {
266 BRepBndLib::Add(theShape2, box2);
267 Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
268 if (dSquareExtent >= tol) {
269 exchange = Standard_True;
271 else if (Abs(dSquareExtent) < tol) {
272 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
273 box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
274 val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
275 box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
276 val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
277 if ((val1 - val2) >= tol) {
278 exchange = Standard_True;
285 //return val1 < val2;
289 //=======================================================================
290 //function : SortShapes
292 //=======================================================================
293 void SortShapes (TopTools_ListOfShape& SL,
294 const Standard_Boolean isOldSorting)
297 std::vector<TopoDS_Shape> aShapesVec;
298 aShapesVec.reserve(SL.Extent());
300 TopTools_ListIteratorOfListOfShape it (SL);
301 for (; it.More(); it.Next()) {
302 aShapesVec.push_back(it.Value());
306 CompareShapes shComp (isOldSorting);
307 std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
308 //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp);
310 std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
311 for (; anIter != aShapesVec.end(); ++anIter) {
315 // old implementation
316 Standard_Integer MaxShapes = SL.Extent();
317 TopTools_Array1OfShape aShapes (1,MaxShapes);
318 TColStd_Array1OfInteger OrderInd(1,MaxShapes);
319 TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z;
320 TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z;
322 // Computing of CentreOfMass
323 Standard_Integer Index;
326 TopTools_ListIteratorOfListOfShape it(SL);
327 for (Index=1; it.More(); Index++)
329 TopoDS_Shape S = it.Value();
330 SL.Remove( it ); // == it.Next()
332 OrderInd.SetValue (Index, Index);
333 if (S.ShapeType() == TopAbs_VERTEX) {
334 GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S ));
335 Length.SetValue( Index, (Standard_Real) S.Orientation());
338 // BEGIN: fix for Mantis issue 0020842
340 BRepGProp::LinearProperties (S, GPr);
343 if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
344 BRepGProp::LinearProperties (S, GPr);
346 else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
347 BRepGProp::SurfaceProperties(S, GPr);
350 BRepGProp::VolumeProperties(S, GPr);
353 // END: fix for Mantis issue 0020842
354 GPoint = GPr.CentreOfMass();
355 Length.SetValue(Index, GPr.Mass());
357 MidXYZ.SetValue(Index, GPoint.X()*999.0 + GPoint.Y()*99.0 + GPoint.Z()*0.9);
358 //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl;
362 Standard_Integer aTemp;
363 Standard_Boolean exchange, Sort = Standard_True;
364 Standard_Real tol = Precision::Confusion();
367 Sort = Standard_False;
368 for (Index=1; Index < MaxShapes; Index++)
370 exchange = Standard_False;
371 Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1));
372 Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1));
373 if ( dMidXYZ >= tol ) {
374 // cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1))
375 // << " d: " << dMidXYZ << endl;
376 exchange = Standard_True;
378 else if ( Abs(dMidXYZ) < tol && dLength >= tol ) {
379 // cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1))
380 // << " d: " << dLength << endl;
381 exchange = Standard_True;
383 else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol &&
384 aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) {
386 // equal values possible on shapes such as two halves of a sphere and
387 // a membrane inside the sphere
389 BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 );
390 if ( box1.IsVoid() ) continue;
391 BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 );
392 Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
393 if ( dSquareExtent >= tol ) {
394 // cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl;
395 exchange = Standard_True;
397 else if ( Abs(dSquareExtent) < tol ) {
398 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
399 box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
400 val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
401 box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
402 val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9;
403 //exchange = val1 > val2;
404 if ((val1 - val2) >= tol) {
405 exchange = Standard_True;
407 //cout << "box: " << val1<<" > "<<val2 << endl;
413 // cout << "exchange " << Index << " & " << Index+1 << endl;
414 aTemp = OrderInd(Index);
415 OrderInd(Index) = OrderInd(Index+1);
416 OrderInd(Index+1) = aTemp;
417 Sort = Standard_True;
422 for (Index=1; Index <= MaxShapes; Index++)
423 SL.Append( aShapes( OrderInd(Index) ));
427 //=======================================================================
428 //function : CompsolidToCompound
430 //=======================================================================
431 TopoDS_Shape CompsolidToCompound (const TopoDS_Shape& theCompsolid)
433 if (theCompsolid.ShapeType() != TopAbs_COMPSOLID) {
437 TopoDS_Compound aCompound;
439 B.MakeCompound(aCompound);
441 TopTools_MapOfShape mapShape;
442 TopoDS_Iterator It (theCompsolid, Standard_True, Standard_True);
444 for (; It.More(); It.Next()) {
445 TopoDS_Shape aShape_i = It.Value();
446 if (mapShape.Add(aShape_i)) {
447 B.Add(aCompound, aShape_i);
454 //=======================================================================
455 //function : AddSimpleShapes
457 //=======================================================================
458 void AddSimpleShapes (const TopoDS_Shape& theShape, TopTools_ListOfShape& theList)
460 if (theShape.ShapeType() != TopAbs_COMPOUND &&
461 theShape.ShapeType() != TopAbs_COMPSOLID) {
462 theList.Append(theShape);
466 TopTools_MapOfShape mapShape;
467 TopoDS_Iterator It (theShape, Standard_True, Standard_True);
469 for (; It.More(); It.Next()) {
470 TopoDS_Shape aShape_i = It.Value();
471 if (mapShape.Add(aShape_i)) {
472 if (aShape_i.ShapeType() == TopAbs_COMPOUND ||
473 aShape_i.ShapeType() == TopAbs_COMPSOLID) {
474 AddSimpleShapes(aShape_i, theList);
476 theList.Append(aShape_i);
482 //=======================================================================
483 //function : CheckTriangulation
485 //=======================================================================
486 bool CheckTriangulation (const TopoDS_Shape& aShape)
488 bool isTriangulation = true;
490 TopExp_Explorer exp (aShape, TopAbs_FACE);
493 TopLoc_Location aTopLoc;
494 Handle(Poly_Triangulation) aTRF;
495 aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
497 isTriangulation = false;
500 else // no faces, try edges
502 TopExp_Explorer expe (aShape, TopAbs_EDGE);
506 TopLoc_Location aLoc;
507 Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
509 isTriangulation = false;
513 if (!isTriangulation) {
514 // calculate deflection
515 Standard_Real aDeviationCoefficient = 0.001;
518 BRepBndLib::Add(aShape, B);
519 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
520 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
522 Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
523 Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
524 Standard_Real aHLRAngle = 0.349066;
526 BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
532 //=======================================================================
533 //function : GetTypeOfSimplePart
535 //=======================================================================
536 TopAbs_ShapeEnum GetTypeOfSimplePart (const TopoDS_Shape& theShape)
538 TopAbs_ShapeEnum aType = theShape.ShapeType();
539 if (aType == TopAbs_VERTEX) return TopAbs_VERTEX;
540 else if (aType == TopAbs_EDGE || aType == TopAbs_WIRE) return TopAbs_EDGE;
541 else if (aType == TopAbs_FACE || aType == TopAbs_SHELL) return TopAbs_FACE;
542 else if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID) return TopAbs_SOLID;
543 else if (aType == TopAbs_COMPOUND) {
544 // Only the iType of the first shape in the compound is taken into account
545 TopoDS_Iterator It (theShape, Standard_False, Standard_False);
547 return GetTypeOfSimplePart(It.Value());
553 //=======================================================================
554 //function : GetEdgeNearPoint
556 //=======================================================================
557 TopoDS_Shape GetEdgeNearPoint (const TopoDS_Shape& theShape,
558 const TopoDS_Vertex& thePoint)
560 TopoDS_Shape aResult;
562 // 1. Explode the shape on edges
563 TopTools_MapOfShape mapShape;
564 Standard_Integer nbEdges = 0;
565 TopExp_Explorer exp (theShape, TopAbs_EDGE);
566 for (; exp.More(); exp.Next()) {
567 if (mapShape.Add(exp.Current())) {
573 Standard_NullObject::Raise("Given shape contains no edges");
576 Standard_Integer ind = 1;
577 TopTools_Array1OfShape anEdges (1, nbEdges);
578 TColStd_Array1OfReal aDistances (1, nbEdges);
579 for (exp.Init(theShape, TopAbs_EDGE); exp.More(); exp.Next()) {
580 if (mapShape.Add(exp.Current())) {
581 TopoDS_Shape anEdge = exp.Current();
582 anEdges(ind) = anEdge;
584 // 2. Classify the point relatively each edge
585 BRepExtrema_DistShapeShape aDistTool (thePoint, anEdges(ind));
586 if (!aDistTool.IsDone())
587 Standard_ConstructionError::Raise("Cannot find a distance from the given point to one of edges");
589 aDistances(ind) = aDistTool.Value();
594 // 3. Define edge, having minimum distance to the point
595 Standard_Real nearest = RealLast(), nbFound = 0;
596 Standard_Real prec = Precision::Confusion();
597 for (ind = 1; ind <= nbEdges; ind++) {
598 if (Abs(aDistances(ind) - nearest) < prec) {
601 else if (aDistances(ind) < nearest) {
602 nearest = aDistances(ind);
603 aResult = anEdges(ind);
610 Standard_ConstructionError::Raise("Multiple edges near the given point are found");
612 else if (nbFound == 0) {
613 Standard_ConstructionError::Raise("There are no edges near the given point");
621 //=======================================================================
622 //function : PreciseBoundingBox
624 //=======================================================================
625 Standard_Boolean PreciseBoundingBox
626 (const TopoDS_Shape &theShape, Bnd_Box &theBox)
628 Standard_Real aBound[6];
630 theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
633 const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]), // XMid
634 0.5*(aBound[3] + aBound[2]), // YMid
635 0.5*(aBound[5] + aBound[4])); // ZMid
636 const gp_XYZ aSize(aBound[1] - aBound[0], // DX
637 aBound[3] - aBound[2], // DY
638 aBound[5] - aBound[4]); // DZ
639 const gp_Pnt aPnt[6] =
641 gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin
642 gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax
643 gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin
644 gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax
645 gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin
646 gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4])) // ZMax
648 const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() };
649 const Standard_Real aPlnSize[3] =
651 0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes
652 0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes
653 0.5*Max(aSize.X(), aSize.Y()) // ZMin, ZMax planes
657 for (i = 0; i < 6; i++) {
658 const Standard_Integer iHalf = i/2;
659 const gp_Pln aPln(aPnt[i], aDir[iHalf]);
660 BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf],
661 -aPlnSize[iHalf], aPlnSize[iHalf]);
663 if (!aMkFace.IsDone()) {
664 return Standard_False;
667 TopoDS_Shape aFace = aMkFace.Shape();
669 // Get minimal distance between planar face and shape.
670 Standard_Real aMinDist =
671 GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]);
674 return Standard_False;
677 aBound[i] = aPMin[1].Coord(iHalf + 1);
680 // Update Bounding box with the new values.
682 theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
684 return Standard_True;
687 //=======================================================================
688 // function : ModifyShape
689 // purpose : This function constructs and returns modified shape
690 // from the original one for singular cases.
691 // It is used for the method GetMinDistanceSingular.
693 // \param theShape the original shape
694 // \param theModifiedShape output parameter. The modified shape.
695 // \param theAddDist output parameter. The added distance for modified shape.
696 // \retval true if the shape is modified; false otherwise.
699 //=======================================================================
700 Standard_Boolean ModifyShape(const TopoDS_Shape &theShape,
701 TopoDS_Shape &theModifiedShape,
702 Standard_Real &theAddDist)
704 Standard_Boolean isModified = Standard_False;
705 TopExp_Explorer anExp;
709 theModifiedShape.Nullify();
711 for ( anExp.Init( theShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
713 theModifiedShape = anExp.Current();
716 TopoDS_Shape sh = theShape;
717 while(sh.ShapeType()==TopAbs_COMPOUND) {
718 TopoDS_Iterator it(sh);
721 Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(theModifiedShape));
722 if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
723 S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ||
725 const Standard_Boolean isShell =
726 (sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE);
728 if( isShell || S->IsUPeriodic() ) {
729 // non solid case or any periodic surface (Mantis 22454).
731 // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
732 //S->Bounds(U1,U2,V1,V2); changed by
733 ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(theModifiedShape),U1,U2,V1,V2);
734 // end of changes for 020677 (dmv)
735 Handle(Geom_RectangularTrimmedSurface) TrS1 =
736 new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
737 Handle(Geom_RectangularTrimmedSurface) TrS2 =
738 new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
741 TopoDS_Shape aMShape;
744 B.MakeCompound(TopoDS::Compound(aMShape));
746 B.MakeShell(TopoDS::Shell(aMShape));
749 B.MakeFace(F1,TrS1,1.e-7);
751 B.MakeFace(F2,TrS2,1.e-7);
753 Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
756 // The original shape is a solid.
760 B.Add(aSolid, aMShape);
765 sfs->SetPrecision(1.e-6);
766 sfs->SetMaxTolerance(1.0);
768 theModifiedShape = sfs->Shape();
769 isModified = Standard_True;
772 if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
773 Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
774 gp_Pnt PC = SS->Location();
777 B.MakeVertex(V,PC,1.e-7);
778 theModifiedShape = V;
779 theAddDist = SS->Radius();
780 isModified = Standard_True;
783 Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
784 gp_Ax3 ax3 = TS->Position();
785 Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
788 B.MakeEdge(E,C,1.e-7);
789 theModifiedShape = E;
790 theAddDist = TS->MinorRadius();
791 isModified = Standard_True;
795 theModifiedShape = theShape;
799 theModifiedShape = theShape;
804 //=======================================================================
805 //function : GetMinDistanceSingular
807 //=======================================================================
808 double GetMinDistanceSingular(const TopoDS_Shape& aSh1,
809 const TopoDS_Shape& aSh2,
810 gp_Pnt& Ptmp1, gp_Pnt& Ptmp2)
814 Standard_Real AddDist1 = 0.;
815 Standard_Real AddDist2 = 0.;
816 Standard_Boolean IsChange1 = ModifyShape(aSh1, tmpSh1, AddDist1);
817 Standard_Boolean IsChange2 = ModifyShape(aSh2, tmpSh2, AddDist2);
819 if( !IsChange1 && !IsChange2 )
822 BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2);
824 double MinDist = 1.e9;
825 gp_Pnt PMin1, PMin2, P1, P2;
826 for (int i = 1; i <= dst.NbSolution(); i++) {
827 P1 = dst.PointOnShape1(i);
828 P2 = dst.PointOnShape2(i);
829 Standard_Real Dist = P1.Distance(P2);
830 if (MinDist > Dist) {
841 gp_Dir aDir(gp_Vec(PMin1,PMin2));
842 if( MinDist > (AddDist1+AddDist2) ) {
843 Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
844 PMin1.Y() + aDir.Y()*AddDist1,
845 PMin1.Z() + aDir.Z()*AddDist1 );
846 Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
847 PMin2.Y() - aDir.Y()*AddDist2,
848 PMin2.Z() - aDir.Z()*AddDist2 );
849 return (MinDist - AddDist1 - AddDist2);
853 Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
854 PMin1.Y() + aDir.Y()*AddDist1,
855 PMin1.Z() + aDir.Z()*AddDist1 );
859 Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
860 PMin2.Y() - aDir.Y()*AddDist2,
861 PMin2.Z() - aDir.Z()*AddDist2 );
866 double res = MinDist - AddDist1 - AddDist2;
867 if(res<0.) res = 0.0;
873 //=======================================================================
874 //function : GetMinDistance
876 //=======================================================================
877 Standard_Real GetMinDistance
878 (const TopoDS_Shape& theShape1,
879 const TopoDS_Shape& theShape2,
880 gp_Pnt& thePnt1, gp_Pnt& thePnt2)
882 Standard_Real aResult = 1.e9;
884 // Issue 0020231: A min distance bug with torus and vertex.
885 // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs
887 // which of shapes consists of only one vertex?
888 TopExp_Explorer exp1(theShape1,TopAbs_VERTEX), exp2(theShape2,TopAbs_VERTEX);
889 TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape();
890 TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape();
891 exp1.Next(); exp2.Next();
892 if ( exp1.More() ) V1.Nullify();
893 if ( exp2.More() ) V2.Nullify();
894 // vertex and container of solids
895 TopoDS_Shape V = V1.IsNull() ? V2 : V1;
896 TopoDS_Shape S = V1.IsNull() ? theShape1 : theShape2;
898 // classify vertex against solids
899 gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) );
900 for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) {
901 BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6);
902 if ( classifier.State() == TopAbs_IN ) {
912 // additional workaround for bugs 19899, 19908 and 19910 from Mantis
913 double dist = GetMinDistanceSingular
914 (theShape1, theShape2, thePnt1, thePnt2);
920 BRepExtrema_DistShapeShape dst (theShape1, theShape2);
924 for (int i = 1; i <= dst.NbSolution(); i++) {
925 P1 = dst.PointOnShape1(i);
926 P2 = dst.PointOnShape2(i);
928 Standard_Real Dist = P1.Distance(P2);
929 if (aResult > Dist) {
940 //=======================================================================
941 // function : ConvertClickToPoint()
942 // purpose : Returns the point clicked in 3D view
943 //=======================================================================
944 gp_Pnt ConvertClickToPoint( int x, int y, Handle(V3d_View) aView )
946 V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
947 aView->Eye( XEye, YEye, ZEye );
949 aView->At( XAt, YAt, ZAt );
950 gp_Pnt EyePoint( XEye, YEye, ZEye );
951 gp_Pnt AtPoint( XAt, YAt, ZAt );
953 gp_Vec EyeVector( EyePoint, AtPoint );
954 gp_Dir EyeDir( EyeVector );
956 gp_Pln PlaneOfTheView = gp_Pln( AtPoint, EyeDir );
957 Standard_Real X, Y, Z;
958 aView->Convert( x, y, X, Y, Z );
959 gp_Pnt ConvertedPoint( X, Y, Z );
961 gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project( PlaneOfTheView, ConvertedPoint );
962 gp_Pnt ResultPoint = ElSLib::Value( ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(), PlaneOfTheView );
966 //=======================================================================
967 // function : ConvertTreeToString()
968 // purpose : Returns the string representation of dependency tree
969 //=======================================================================
970 void ConvertTreeToString( const TreeModel &tree,
971 std::string &treeStr )
973 TreeModel::const_iterator i;
974 for ( i = tree.begin(); i != tree.end(); ++i ) {
975 treeStr.append( i->first );
976 treeStr.append( "-" );
977 std::vector<LevelInfo> upLevelList = i->second.first;
978 treeStr.append( "upward" );
979 treeStr.append( "{" );
980 for( std::vector<LevelInfo>::iterator j = upLevelList.begin();
981 j != upLevelList.end(); ++j ) {
982 LevelInfo level = (*j);
983 LevelInfo::iterator upIter;
984 for ( upIter = level.begin(); upIter != level.end(); ++upIter ) {
985 treeStr.append( upIter->first );
986 for ( std::vector<std::string>::iterator k = upIter->second.begin();
987 k != upIter->second.end(); ++k ) {
988 treeStr.append( "_" );
989 treeStr.append( *k );
991 treeStr.append( upIter++ == level.end() ? ";" : "," );
995 treeStr.append( "}" );
996 std::vector<LevelInfo> downLevelList = i->second.second;
997 treeStr.append( "downward" );
998 treeStr.append( "{" );
999 for( std::vector<LevelInfo>::iterator j = downLevelList.begin();
1000 j != downLevelList.end(); ++j ) {
1001 LevelInfo level = (*j);
1002 LevelInfo::iterator downIter;
1003 for ( downIter = level.begin(); downIter != level.end(); ++downIter ) {
1004 treeStr.append( downIter->first );
1005 for ( std::vector<std::string>::iterator k = downIter->second.begin();
1006 k != downIter->second.end(); ++k ) {
1007 treeStr.append( "_" );
1008 treeStr.append( *k );
1010 treeStr.append( downIter++ == level.end() ? ";" : "," );
1014 treeStr.append("}");
1018 LevelsList parseWard( const std::string& theData, std::size_t& theCursor )
1020 std::size_t indexStart = theData.find( "{", theCursor ) + 1;
1021 std::size_t indexEnd = theData.find( "}", indexStart );
1023 std::string ward = theData.substr( indexStart, indexEnd - indexStart );
1024 std::stringstream ss(ward);
1026 std::vector<std::string> levelsListStr;
1027 while ( std::getline( ss, substr, ';' ) ) {
1028 if ( !substr.empty() )
1029 levelsListStr.push_back( substr );
1031 LevelsList levelsListData;
1032 for( int level = 0; level < levelsListStr.size(); level++ ) {
1033 std::cout<<" Level" << level + 1 << ":" << std::endl;
1034 std::vector<std::string> namesListStr;
1035 ss.str( levelsListStr[level] );
1036 while ( std::getline( ss, substr, ',' ) ) {
1037 if ( !substr.empty() )
1038 namesListStr.push_back( substr );
1040 LevelInfo levelInfoData;
1041 for( int node = 0; node < namesListStr.size(); node++ ) {
1042 std::vector<std::string> linksListStr;
1043 ss.str( namesListStr[node] );
1044 while ( std::getline( ss, substr, '_' ) ) {
1045 if ( !substr.empty() )
1046 linksListStr.push_back( substr );
1048 std::string nodeItem = linksListStr[0];
1049 if( !nodeItem.empty() ) {
1050 NodeLinks linksListData;
1051 std::cout<<" " << nodeItem << " - ";
1052 for( int link = 1; link < linksListStr.size(); link++ ) {
1053 std::string linkItem = linksListStr[link];
1054 linksListData.push_back( linkItem );
1055 std::cout << linkItem << ", ";
1057 levelInfoData[nodeItem] = linksListData;
1058 std::cout << std::endl;
1061 levelsListData.push_back(levelInfoData);
1064 theCursor = indexEnd + 1;
1065 return levelsListData;
1068 //=======================================================================
1069 // function : ConvertStringToTree()
1070 // purpose : Returns the dependency tree
1071 //=======================================================================
1072 void ConvertStringToTree( const std::string &theData,
1075 std::size_t cursor = 0;
1077 while( theData.find('-',cursor) != std::string::npos ) //find next selected object
1079 std::size_t objectIndex = theData.find( '-', cursor );
1080 std::string objectEntry = theData.substr( cursor, objectIndex - cursor );
1081 std::cout<<"\n\nMainObject = " << objectEntry <<std::endl;
1082 cursor = objectIndex;
1084 std::size_t upwardIndexBegin = theData.find("{",cursor) + 1;
1085 std::size_t upwardIndexFinish = theData.find("}",upwardIndexBegin);
1086 std::cout<<" Upward:" << std::endl ;
1087 LevelsList upwardList = parseWard( theData, cursor );
1089 std::cout<<" Downward:" << std::endl;
1090 LevelsList downwardList = parseWard( theData, cursor );
1092 tree[objectEntry] = std::pair<LevelsList,LevelsList>( upwardList, downwardList );
1096 } //namespace GEOMUtils