This functionallity is implemented in such a way to have
a satisfactory performance.
-\n <b>TUI Commands:</b> <em>[Xmin,Xmax, Ymin,Ymax, Zmin,Zmax] = geompy.BoundingBox(Shape)</em>,
-<em>BBox = geompy.MakeBoundingBox(Shape)</em>, where \em Shape
-is the shape for which the bounding box is computed.
+\n <b>TUI Commands:</b> <em>[Xmin,Xmax, Ymin,Ymax, Zmin,Zmax] = geompy.BoundingBox(Shape, precise)</em>,
+<em>BBox = geompy.MakeBoundingBox(Shape, precise)</em>, where \em Shape
+is the shape for which the bounding box is computed. \em precise TRUE
+ for precise computation; FALSE for fast one. Default value is False.
See also a \ref tui_bounding_box_page "TUI example".
/*!
* \brief Get parameters of bounding box of the given shape
* \param theShape Shape to obtain bounding box of.
+ * \param precise TRUE for precise computation; FALSE for fast one.
* \param Xmin,Xmax Output. Limits of shape along OX axis.
* \param Ymin,Ymax Output. Limits of shape along OY axis.
* \param Zmin,Zmax Output. Limits of shape along OZ axis.
* \return Returns parameters of bounding box through the last six arguments.
*/
void GetBoundingBox (in GEOM_Object theShape,
+ in boolean precise,
out double Xmin, out double Xmax,
out double Ymin, out double Ymax,
out double Zmin, out double Zmax);
/*!
* \brief Get bounding box of the given shape
* \param theShape Shape to obtain bounding box of.
+ * \param precise TRUE for precise computation; FALSE for fast one.
* \return New GEOM_Object, containing the created bounding box.
*/
- GEOM_Object MakeBoundingBox (in GEOM_Object theShape);
+ GEOM_Object MakeBoundingBox (in GEOM_Object theShape,
+ in boolean precise);
/*!
* \brief Get min and max tolerances of sub-shapes of theShape
#include <ShapeAnalysis.hxx>
#include <ShapeAnalysis_Surface.hxx>
-#include <ShapeFix_Shape.hxx>
#include <GeomAPI_IntSS.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAbs_SurfaceType.hxx>
-#include <Geom_BezierSurface.hxx>
-#include <Geom_BSplineSurface.hxx>
-#include <Geom_Circle.hxx>
-#include <Geom_ConicalSurface.hxx>
-#include <Geom_CylindricalSurface.hxx>
#include <Geom_Line.hxx>
-#include <Geom_OffsetSurface.hxx>
-#include <Geom_Plane.hxx>
-#include <Geom_RectangularTrimmedSurface.hxx>
-#include <Geom_SphericalSurface.hxx>
#include <Geom_Surface.hxx>
-#include <Geom_SurfaceOfLinearExtrusion.hxx>
-#include <Geom_SurfaceOfRevolution.hxx>
-#include <Geom_ToroidalSurface.hxx>
#include <GeomLProp_CLProps.hxx>
#include <GeomLProp_SLProps.hxx>
//=============================================================================
void GEOMImpl_IMeasureOperations::GetBoundingBox
(Handle(GEOM_Object) theShape,
+ const Standard_Boolean precise,
Standard_Real& Xmin, Standard_Real& Xmax,
Standard_Real& Ymin, Standard_Real& Ymax,
Standard_Real& Zmin, Standard_Real& Zmax)
BRepTools::Clean(aShape);
BRepBndLib::Add(aShape, B);
+
+ if (precise) {
+ if (!GEOMUtils::PreciseBoundingBox(aShape, B)) {
+ SetErrorCode("GetBoundingBox Error: Bounding box cannot be precised");
+ return;
+ }
+ }
+
B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
}
catch (Standard_Failure) {
*/
//=============================================================================
Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
- (Handle(GEOM_Object) theShape)
+ (Handle(GEOM_Object) theShape,
+ const Standard_Boolean precise)
{
SetErrorCode(KO);
Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GetDocID(), GEOM_BOX);
//Add a new BoundingBox function
+ const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE);
Handle(GEOM_Function) aFunction =
- aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), BND_BOX_MEASURE);
+ aBnd->AddFunction(GEOMImpl_MeasureDriver::GetID(), aType);
if (aFunction.IsNull()) return NULL;
//Check if the function is set correctly
}
//Make a Python command
- GEOM::TPythonDump(aFunction) << aBnd << " = geompy.MakeBoundingBox(" << theShape << ")";
+ GEOM::TPythonDump aPd(aFunction);
+
+ aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
+
+ if (precise) {
+ aPd << ", True";
+ }
+
+ aPd << ")";
SetErrorCode(OK);
return aBnd;
return res;
}
-//=======================================================================
-//function : CheckSingularCase
-//purpose : auxilary for GetMinDistance()
-// workaround for bugs 19899, 19908 and 19910 from Mantis
-//=======================================================================
-static double CheckSingularCase(const TopoDS_Shape& aSh1,
- const TopoDS_Shape& aSh2,
- gp_Pnt& Ptmp1, gp_Pnt& Ptmp2)
-{
- bool IsChange1 = false;
- double AddDist1 = 0.0;
- TopExp_Explorer anExp;
- TopoDS_Shape tmpSh1, tmpSh2;
- int nbf = 0;
- for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
- nbf++;
- tmpSh1 = anExp.Current();
- }
- if(nbf==1) {
- TopoDS_Shape sh = aSh1;
- while(sh.ShapeType()==TopAbs_COMPOUND) {
- TopoDS_Iterator it(sh);
- sh = it.Value();
- }
- Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
- if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
- S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
- if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
- // non solid case
- double U1,U2,V1,V2;
- // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
- //S->Bounds(U1,U2,V1,V2); changed by
- ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh1),U1,U2,V1,V2);
- // end of changes for 020677 (dmv)
- Handle(Geom_RectangularTrimmedSurface) TrS1 =
- new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
- Handle(Geom_RectangularTrimmedSurface) TrS2 =
- new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
- BRep_Builder B;
- TopoDS_Face F1,F2;
- TopoDS_Compound Comp;
- B.MakeCompound(Comp);
- B.MakeFace(F1,TrS1,1.e-7);
- B.Add(Comp,F1);
- B.MakeFace(F2,TrS2,1.e-7);
- B.Add(Comp,F2);
- Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
- sfs->Init(Comp);
- sfs->SetPrecision(1.e-6);
- sfs->SetMaxTolerance(1.0);
- sfs->Perform();
- tmpSh1 = sfs->Shape();
- IsChange1 = true;
- }
- else {
- if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
- Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
- gp_Pnt PC = SS->Location();
- BRep_Builder B;
- TopoDS_Vertex V;
- B.MakeVertex(V,PC,1.e-7);
- tmpSh1 = V;
- AddDist1 = SS->Radius();
- IsChange1 = true;
- }
- else {
- Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
- gp_Ax3 ax3 = TS->Position();
- Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
- BRep_Builder B;
- TopoDS_Edge E;
- B.MakeEdge(E,C,1.e-7);
- tmpSh1 = E;
- AddDist1 = TS->MinorRadius();
- IsChange1 = true;
- }
- }
- }
- else
- tmpSh1 = aSh1;
- }
- else
- tmpSh1 = aSh1;
- bool IsChange2 = false;
- double AddDist2 = 0.0;
- nbf = 0;
- for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
- nbf++;
- tmpSh2 = anExp.Current();
- }
- if(nbf==1) {
- TopoDS_Shape sh = aSh2;
- while(sh.ShapeType()==TopAbs_COMPOUND) {
- TopoDS_Iterator it(sh);
- sh = it.Value();
- }
- Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
- if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
- S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
- if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
- // non solid case
- double U1,U2,V1,V2;
- //S->Bounds(U1,U2,V1,V2);
- ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh2),U1,U2,V1,V2);
- Handle(Geom_RectangularTrimmedSurface) TrS1 =
- new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
- Handle(Geom_RectangularTrimmedSurface) TrS2 =
- new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
- BRep_Builder B;
- TopoDS_Face F1,F2;
- TopoDS_Compound Comp;
- B.MakeCompound(Comp);
- B.MakeFace(F1,TrS1,1.e-7);
- B.Add(Comp,F1);
- B.MakeFace(F2,TrS2,1.e-7);
- B.Add(Comp,F2);
- Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
- sfs->Init(Comp);
- sfs->SetPrecision(1.e-6);
- sfs->SetMaxTolerance(1.0);
- sfs->Perform();
- tmpSh2 = sfs->Shape();
- IsChange2 = true;
- }
- else {
- if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
- Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
- gp_Pnt PC = SS->Location();
- BRep_Builder B;
- TopoDS_Vertex V;
- B.MakeVertex(V,PC,1.e-7);
- tmpSh2 = V;
- AddDist2 = SS->Radius();
- IsChange2 = true;
- }
- else if( S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
- Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
- gp_Ax3 ax3 = TS->Position();
- Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
- BRep_Builder B;
- TopoDS_Edge E;
- B.MakeEdge(E,C,1.e-7);
- tmpSh2 = E;
- AddDist2 = TS->MinorRadius();
- IsChange2 = true;
- }
- }
- }
- else
- tmpSh2 = aSh2;
- }
- else
- tmpSh2 = aSh2;
-
- if( !IsChange1 && !IsChange2 )
- return -2.0;
-
- BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2);
- if (dst.IsDone()) {
- double MinDist = 1.e9;
- gp_Pnt PMin1, PMin2, P1, P2;
- for (int i = 1; i <= dst.NbSolution(); i++) {
- P1 = dst.PointOnShape1(i);
- P2 = dst.PointOnShape2(i);
- Standard_Real Dist = P1.Distance(P2);
- if (MinDist > Dist) {
- MinDist = Dist;
- PMin1 = P1;
- PMin2 = P2;
- }
- }
- if(MinDist<1.e-7) {
- Ptmp1 = PMin1;
- Ptmp2 = PMin2;
- }
- else {
- gp_Dir aDir(gp_Vec(PMin1,PMin2));
- if( MinDist > (AddDist1+AddDist2) ) {
- Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
- PMin1.Y() + aDir.Y()*AddDist1,
- PMin1.Z() + aDir.Z()*AddDist1 );
- Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
- PMin2.Y() - aDir.Y()*AddDist2,
- PMin2.Z() - aDir.Z()*AddDist2 );
- return (MinDist - AddDist1 - AddDist2);
- }
- else {
- if( AddDist1 > 0 ) {
- Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
- PMin1.Y() + aDir.Y()*AddDist1,
- PMin1.Z() + aDir.Z()*AddDist1 );
- Ptmp2 = Ptmp1;
- }
- else {
- Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
- PMin2.Y() - aDir.Y()*AddDist2,
- PMin2.Z() - aDir.Z()*AddDist2 );
- Ptmp1 = Ptmp2;
- }
- }
- }
- double res = MinDist - AddDist1 - AddDist2;
- if(res<0.) res = 0.0;
- return res;
- }
- return -2.0;
-}
-/* old variant
-static bool CheckSingularCase(const TopoDS_Shape& aSh1,
- const TopoDS_Shape& aSh2,
- gp_Pnt& Ptmp)
-{
- TopExp_Explorer anExp;
- TopoDS_Shape tmpSh1, tmpSh2;
- int nbf = 0;
- for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
- nbf++;
- tmpSh1 = anExp.Current();
- }
- if(nbf==1) {
- Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
- if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
- S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
- nbf = 0;
- for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
- nbf++;
- tmpSh2 = anExp.Current();
- Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
- GeomAPI_IntSS ISS(S1,S2,1.e-7);
- if(ISS.IsDone()) {
- for(int i=1; i<=ISS.NbLines(); i++) {
- Handle(Geom_Curve) C3d = ISS.Line(i);
- BRep_Builder B;
- TopoDS_Edge E;
- B.MakeEdge(E,C3d,1.e-7);
- BRepExtrema_DistShapeShape dst(tmpSh2,E);
- if (dst.IsDone()) {
- gp_Pnt PMin1, PMin2, P1, P2;
- double MinDist = 1.e9;
- for (int i = 1; i <= dst.NbSolution(); i++) {
- P1 = dst.PointOnShape1(i);
- P2 = dst.PointOnShape2(i);
- Standard_Real Dist = P1.Distance(P2);
- if (MinDist > Dist) {
- MinDist = Dist;
- Ptmp = P1;
- }
- }
- if(MinDist<1.e-7)
- return true;
- }
- }
- }
- }
- }
- }
- nbf = 0;
- for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
- nbf++;
- tmpSh1 = anExp.Current();
- }
- if(nbf==1) {
- Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
- if( S1->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
- S1->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
- nbf = 0;
- for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
- nbf++;
- tmpSh2 = anExp.Current();
- Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
- GeomAPI_IntSS ISS(S1,S2,1.e-7);
- if(ISS.IsDone()) {
- for(int i=1; i<=ISS.NbLines(); i++) {
- Handle(Geom_Curve) C3d = ISS.Line(i);
- BRep_Builder B;
- TopoDS_Edge E;
- B.MakeEdge(E,C3d,1.e-7);
- BRepExtrema_DistShapeShape dst(tmpSh2,E);
- if (dst.IsDone()) {
- gp_Pnt P1,P2;
- double MinDist = 1.e9;
- for (int i = 1; i <= dst.NbSolution(); i++) {
- P1 = dst.PointOnShape1(i);
- P2 = dst.PointOnShape2(i);
- Standard_Real Dist = P1.Distance(P2);
- if (MinDist > Dist) {
- MinDist = Dist;
- Ptmp = P1;
- }
- }
- if(MinDist<1.e-7)
- return true;
- }
- }
- }
- }
- }
- }
- return false;
-}
-*/
-
//=============================================================================
/*!
* GetMinDistance
OCC_CATCH_SIGNALS;
#endif
- // Issue 0020231: A min distance bug with torus and vertex.
- // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs
-
- // which of shapes consists of only one vertex?
- TopExp_Explorer exp1(aShape1,TopAbs_VERTEX), exp2(aShape2,TopAbs_VERTEX);
- TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape();
- TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape();
- exp1.Next(); exp2.Next();
- if ( exp1.More() ) V1.Nullify();
- if ( exp2.More() ) V2.Nullify();
- // vertex and container of solids
- TopoDS_Shape V = V1.IsNull() ? V2 : V1;
- TopoDS_Shape S = V1.IsNull() ? aShape1 : aShape2;
- if ( !V.IsNull() ) {
- // classify vertex against solids
- gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) );
- for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) {
- BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6);
- if ( classifier.State() == TopAbs_IN ) {
- p.Coord(X1, Y1, Z1);
- p.Coord(X2, Y2, Z2);
- SetErrorCode(OK);
- return 0.0;
- }
- }
- }
- // End Issue 0020231
+ gp_Pnt aPnt1, aPnt2;
- // skl 30.06.2008
- // additional workaround for bugs 19899, 19908 and 19910 from Mantis
- gp_Pnt Ptmp1, Ptmp2;
- double dist = CheckSingularCase(aShape1, aShape2, Ptmp1, Ptmp2);
- if (dist > -1.0) {
- Ptmp1.Coord(X1, Y1, Z1);
- Ptmp2.Coord(X2, Y2, Z2);
- SetErrorCode(OK);
- return dist;
- }
+ MinDist = GEOMUtils::GetMinDistance(aShape1, aShape2, aPnt1, aPnt2);
- BRepExtrema_DistShapeShape dst (aShape1, aShape2);
- if (dst.IsDone()) {
- gp_Pnt PMin1, PMin2, P1, P2;
-
- for (int i = 1; i <= dst.NbSolution(); i++) {
- P1 = dst.PointOnShape1(i);
- P2 = dst.PointOnShape2(i);
-
- Standard_Real Dist = P1.Distance(P2);
- if (MinDist > Dist) {
- MinDist = Dist;
- PMin1 = P1;
- PMin2 = P2;
- }
- }
-
- PMin1.Coord(X1, Y1, Z1);
- PMin2.Coord(X2, Y2, Z2);
+ if (MinDist >= 0.0) {
+ aPnt1.Coord(X1, Y1, Z1);
+ aPnt2.Coord(X2, Y2, Z2);
+ } else {
+ return MinDist;
}
}
catch (Standard_Failure) {
// skl 30.06.2008
// additional workaround for bugs 19899, 19908 and 19910 from Mantis
gp_Pnt P1, P2;
- double dist = CheckSingularCase(aShape1, aShape2, P1, P2);
+ double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1, P2);
if (dist > -1.0) {
nbSolutions = 1;
Standard_Real& Ix , Standard_Real& Iy , Standard_Real& Iz);
Standard_EXPORT void GetBoundingBox (Handle(GEOM_Object) theShape,
+ const Standard_Boolean precise,
Standard_Real& Xmin, Standard_Real& Xmax,
Standard_Real& Ymin, Standard_Real& Ymax,
Standard_Real& Zmin, Standard_Real& Zmax);
- Standard_EXPORT Handle(GEOM_Object) GetBoundingBox (Handle(GEOM_Object) theShape);
+ Standard_EXPORT Handle(GEOM_Object) GetBoundingBox (Handle(GEOM_Object) theShape,
+ const Standard_Boolean precise);
Standard_EXPORT void GetTolerance (Handle(GEOM_Object) theShape,
Standard_Real& FaceMin, Standard_Real& FaceMax,
gp_Pnt aCenterMass = aPos.Location();
aShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
}
- else if (aType == BND_BOX_MEASURE)
+ else if (aType == BND_BOX_MEASURE || aType == BND_BOX_MEASURE_PRECISE)
{
Handle(GEOM_Function) aRefBase = aCI.GetBase();
TopoDS_Shape aShapeBase = aRefBase->GetValue();
Bnd_Box B;
BRepBndLib::Add(aShapeBase, B);
+ if (aType == BND_BOX_MEASURE_PRECISE) {
+ if (!GEOMUtils::PreciseBoundingBox(aShapeBase, B)) {
+ Standard_NullObject::Raise("Bounding box cannot be precised");
+ }
+ }
+
Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
// Measures
#define CDG_MEASURE 1
#define BND_BOX_MEASURE 2
+#define BND_BOX_MEASURE_PRECISE 3
#define VECTOR_FACE_NORMALE 4
#define VERTEX_BY_INDEX 5
#include <BRepGProp.hxx>
#include <BRepTools.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
+
+#include <BRepBuilderAPI_MakeFace.hxx>
+
#include <Bnd_Box.hxx>
#include <TopAbs.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_Array1OfShape.hxx>
+#include <Geom_Circle.hxx>
#include <Geom_Surface.hxx>
#include <Geom_Plane.hxx>
+#include <Geom_SphericalSurface.hxx>
+#include <Geom_ToroidalSurface.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
#include <GeomLProp_CLProps.hxx>
#include <GeomLProp_SLProps.hxx>
#include <gp_Pln.hxx>
#include <gp_Lin.hxx>
+#include <ShapeAnalysis.hxx>
+#include <ShapeFix_Shape.hxx>
+
#include <vector>
#include <Standard_Failure.hxx>
return aResult;
}
+
+//=======================================================================
+//function : PreciseBoundingBox
+//purpose :
+//=======================================================================
+Standard_Boolean GEOMUtils::PreciseBoundingBox
+ (const TopoDS_Shape &theShape, Bnd_Box &theBox)
+{
+ Standard_Real aBound[6];
+
+ theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
+
+ Standard_Integer i;
+ const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]), // XMid
+ 0.5*(aBound[3] + aBound[2]), // YMid
+ 0.5*(aBound[5] + aBound[4])); // ZMid
+ const gp_XYZ aSize(aBound[1] - aBound[0], // DX
+ aBound[3] - aBound[2], // DY
+ aBound[5] - aBound[4]); // DZ
+ const gp_Pnt aPnt[6] =
+ {
+ gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin
+ gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax
+ gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin
+ gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax
+ gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin
+ gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4])) // ZMax
+ };
+ const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() };
+ const Standard_Real aPlnSize[3] =
+ {
+ 0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes
+ 0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes
+ 0.5*Max(aSize.X(), aSize.Y()) // ZMin, ZMax planes
+ };
+ gp_Pnt aPMin[2];
+
+ for (i = 0; i < 6; i++) {
+ const Standard_Integer iHalf = i/2;
+ const gp_Pln aPln(aPnt[i], aDir[iHalf]);
+ BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf],
+ -aPlnSize[iHalf], aPlnSize[iHalf]);
+
+ if (!aMkFace.IsDone()) {
+ return Standard_False;
+ }
+
+ TopoDS_Shape aFace = aMkFace.Shape();
+
+ // Get minimal distance between planar face and shape.
+ Standard_Real aMinDist =
+ GEOMUtils::GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]);
+
+ if (aMinDist < 0.) {
+ return Standard_False;
+ }
+
+ aBound[i] = aPMin[1].Coord(iHalf + 1);
+ }
+
+ // Update Bounding box with the new values.
+ theBox.SetVoid();
+ theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : GetMinDistanceSingular
+//purpose :
+//=======================================================================
+double GEOMUtils::GetMinDistanceSingular(const TopoDS_Shape& aSh1,
+ const TopoDS_Shape& aSh2,
+ gp_Pnt& Ptmp1, gp_Pnt& Ptmp2)
+{
+ bool IsChange1 = false;
+ double AddDist1 = 0.0;
+ TopExp_Explorer anExp;
+ TopoDS_Shape tmpSh1, tmpSh2;
+ int nbf = 0;
+ for ( anExp.Init( aSh1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+ nbf++;
+ tmpSh1 = anExp.Current();
+ }
+ if(nbf==1) {
+ TopoDS_Shape sh = aSh1;
+ while(sh.ShapeType()==TopAbs_COMPOUND) {
+ TopoDS_Iterator it(sh);
+ sh = it.Value();
+ }
+ Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh1));
+ if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
+ S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
+ if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
+ // non solid case
+ double U1,U2,V1,V2;
+ // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88
+ //S->Bounds(U1,U2,V1,V2); changed by
+ ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh1),U1,U2,V1,V2);
+ // end of changes for 020677 (dmv)
+ Handle(Geom_RectangularTrimmedSurface) TrS1 =
+ new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
+ Handle(Geom_RectangularTrimmedSurface) TrS2 =
+ new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
+ BRep_Builder B;
+ TopoDS_Face F1,F2;
+ TopoDS_Compound Comp;
+ B.MakeCompound(Comp);
+ B.MakeFace(F1,TrS1,1.e-7);
+ B.Add(Comp,F1);
+ B.MakeFace(F2,TrS2,1.e-7);
+ B.Add(Comp,F2);
+ Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
+ sfs->Init(Comp);
+ sfs->SetPrecision(1.e-6);
+ sfs->SetMaxTolerance(1.0);
+ sfs->Perform();
+ tmpSh1 = sfs->Shape();
+ IsChange1 = true;
+ }
+ else {
+ if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
+ Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
+ gp_Pnt PC = SS->Location();
+ BRep_Builder B;
+ TopoDS_Vertex V;
+ B.MakeVertex(V,PC,1.e-7);
+ tmpSh1 = V;
+ AddDist1 = SS->Radius();
+ IsChange1 = true;
+ }
+ else {
+ Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
+ gp_Ax3 ax3 = TS->Position();
+ Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
+ BRep_Builder B;
+ TopoDS_Edge E;
+ B.MakeEdge(E,C,1.e-7);
+ tmpSh1 = E;
+ AddDist1 = TS->MinorRadius();
+ IsChange1 = true;
+ }
+ }
+ }
+ else
+ tmpSh1 = aSh1;
+ }
+ else
+ tmpSh1 = aSh1;
+ bool IsChange2 = false;
+ double AddDist2 = 0.0;
+ nbf = 0;
+ for ( anExp.Init( aSh2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
+ nbf++;
+ tmpSh2 = anExp.Current();
+ }
+ if(nbf==1) {
+ TopoDS_Shape sh = aSh2;
+ while(sh.ShapeType()==TopAbs_COMPOUND) {
+ TopoDS_Iterator it(sh);
+ sh = it.Value();
+ }
+ Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(tmpSh2));
+ if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
+ S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
+ if( sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE ) {
+ // non solid case
+ double U1,U2,V1,V2;
+ //S->Bounds(U1,U2,V1,V2);
+ ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(tmpSh2),U1,U2,V1,V2);
+ Handle(Geom_RectangularTrimmedSurface) TrS1 =
+ new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2);
+ Handle(Geom_RectangularTrimmedSurface) TrS2 =
+ new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2);
+ BRep_Builder B;
+ TopoDS_Face F1,F2;
+ TopoDS_Compound Comp;
+ B.MakeCompound(Comp);
+ B.MakeFace(F1,TrS1,1.e-7);
+ B.Add(Comp,F1);
+ B.MakeFace(F2,TrS2,1.e-7);
+ B.Add(Comp,F2);
+ Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
+ sfs->Init(Comp);
+ sfs->SetPrecision(1.e-6);
+ sfs->SetMaxTolerance(1.0);
+ sfs->Perform();
+ tmpSh2 = sfs->Shape();
+ IsChange2 = true;
+ }
+ else {
+ if( S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
+ Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S);
+ gp_Pnt PC = SS->Location();
+ BRep_Builder B;
+ TopoDS_Vertex V;
+ B.MakeVertex(V,PC,1.e-7);
+ tmpSh2 = V;
+ AddDist2 = SS->Radius();
+ IsChange2 = true;
+ }
+ else if( S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) ) {
+ Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S);
+ gp_Ax3 ax3 = TS->Position();
+ Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius());
+ BRep_Builder B;
+ TopoDS_Edge E;
+ B.MakeEdge(E,C,1.e-7);
+ tmpSh2 = E;
+ AddDist2 = TS->MinorRadius();
+ IsChange2 = true;
+ }
+ }
+ }
+ else
+ tmpSh2 = aSh2;
+ }
+ else
+ tmpSh2 = aSh2;
+
+ if( !IsChange1 && !IsChange2 )
+ return -2.0;
+
+ BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2);
+ if (dst.IsDone()) {
+ double MinDist = 1.e9;
+ gp_Pnt PMin1, PMin2, P1, P2;
+ for (int i = 1; i <= dst.NbSolution(); i++) {
+ P1 = dst.PointOnShape1(i);
+ P2 = dst.PointOnShape2(i);
+ Standard_Real Dist = P1.Distance(P2);
+ if (MinDist > Dist) {
+ MinDist = Dist;
+ PMin1 = P1;
+ PMin2 = P2;
+ }
+ }
+ if(MinDist<1.e-7) {
+ Ptmp1 = PMin1;
+ Ptmp2 = PMin2;
+ }
+ else {
+ gp_Dir aDir(gp_Vec(PMin1,PMin2));
+ if( MinDist > (AddDist1+AddDist2) ) {
+ Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
+ PMin1.Y() + aDir.Y()*AddDist1,
+ PMin1.Z() + aDir.Z()*AddDist1 );
+ Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
+ PMin2.Y() - aDir.Y()*AddDist2,
+ PMin2.Z() - aDir.Z()*AddDist2 );
+ return (MinDist - AddDist1 - AddDist2);
+ }
+ else {
+ if( AddDist1 > 0 ) {
+ Ptmp1 = gp_Pnt( PMin1.X() + aDir.X()*AddDist1,
+ PMin1.Y() + aDir.Y()*AddDist1,
+ PMin1.Z() + aDir.Z()*AddDist1 );
+ Ptmp2 = Ptmp1;
+ }
+ else {
+ Ptmp2 = gp_Pnt( PMin2.X() - aDir.X()*AddDist2,
+ PMin2.Y() - aDir.Y()*AddDist2,
+ PMin2.Z() - aDir.Z()*AddDist2 );
+ Ptmp1 = Ptmp2;
+ }
+ }
+ }
+ double res = MinDist - AddDist1 - AddDist2;
+ if(res<0.) res = 0.0;
+ return res;
+ }
+ return -2.0;
+}
+
+//=======================================================================
+//function : GetMinDistance
+//purpose :
+//=======================================================================
+Standard_Real GEOMUtils::GetMinDistance
+ (const TopoDS_Shape& theShape1,
+ const TopoDS_Shape& theShape2,
+ gp_Pnt& thePnt1, gp_Pnt& thePnt2)
+{
+ Standard_Real aResult = 1.e9;
+
+ // Issue 0020231: A min distance bug with torus and vertex.
+ // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs
+
+ // which of shapes consists of only one vertex?
+ TopExp_Explorer exp1(theShape1,TopAbs_VERTEX), exp2(theShape2,TopAbs_VERTEX);
+ TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape();
+ TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape();
+ exp1.Next(); exp2.Next();
+ if ( exp1.More() ) V1.Nullify();
+ if ( exp2.More() ) V2.Nullify();
+ // vertex and container of solids
+ TopoDS_Shape V = V1.IsNull() ? V2 : V1;
+ TopoDS_Shape S = V1.IsNull() ? theShape1 : theShape2;
+ if ( !V.IsNull() ) {
+ // classify vertex against solids
+ gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) );
+ for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) {
+ BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6);
+ if ( classifier.State() == TopAbs_IN ) {
+ thePnt1 = p;
+ thePnt2 = p;
+ return 0.0;
+ }
+ }
+ }
+ // End Issue 0020231
+
+ // skl 30.06.2008
+ // additional workaround for bugs 19899, 19908 and 19910 from Mantis
+ double dist = GEOMUtils::GetMinDistanceSingular
+ (theShape1, theShape2, thePnt1, thePnt2);
+
+ if (dist > -1.0) {
+ return dist;
+ }
+
+ BRepExtrema_DistShapeShape dst (theShape1, theShape2);
+ if (dst.IsDone()) {
+ gp_Pnt P1, P2;
+
+ for (int i = 1; i <= dst.NbSolution(); i++) {
+ P1 = dst.PointOnShape1(i);
+ P2 = dst.PointOnShape2(i);
+
+ Standard_Real Dist = P1.Distance(P2);
+ if (aResult > Dist) {
+ aResult = Dist;
+ thePnt1 = P1;
+ thePnt2 = P2;
+ }
+ }
+ }
+
+ return aResult;
+}
#include <functional>
+class Bnd_Box;
+
inline Standard_Boolean IsEqual (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
{
return S1.IsSame(S2);
Standard_EXPORT static TopoDS_Shape GetEdgeNearPoint (const TopoDS_Shape& theShape,
const TopoDS_Vertex& thePoint);
+ /*!
+ * \brief Compute precise bounding box of the shape based on the rough bounding box.
+ *
+ * \param theShape the shape.
+ * \param theBox rough bounding box on input; precise bounding box on output.
+ * \retval Standard_True in case of success; Standard_False otherwise.
+ */
+ Standard_EXPORT static Standard_Boolean PreciseBoundingBox
+ (const TopoDS_Shape &theShape, Bnd_Box &theBox);
+
+ /*!
+ * \brief Computes minumal distance between two shapes for singular cases
+ * (workaround for bugs 19899, 19908 and 19910 from Mantis).
+ *
+ * \param aSh1 the first shape
+ * \param aSh2 the second shape
+ * \param Ptmp1 the output result point on the first shape
+ * \param Ptmp2 the output result point on the second shape
+ * \retval negative value if it is not a singular case; actual distance for singular case.
+ */
+ Standard_EXPORT static Standard_Real GetMinDistanceSingular
+ (const TopoDS_Shape& aSh1,
+ const TopoDS_Shape& aSh2,
+ gp_Pnt& Ptmp1, gp_Pnt& Ptmp2);
+
+ /*!
+ * \brief Computes minumal distance between two shapes.
+ *
+ * \param theShape1 the first shape
+ * \param theShape2 the second shape
+ * \param thePnt1 the output result point on the first shape
+ * \param thePnt2 the output result point on the second shape
+ * \retval negative value in case of failure; otherwise the real distance.
+ */
+ Standard_EXPORT static Standard_Real GetMinDistance
+ (const TopoDS_Shape& theShape1,
+ const TopoDS_Shape& theShape2,
+ gp_Pnt& thePnt1, gp_Pnt& thePnt2);
+
};
#endif
*/
//=============================================================================
void GEOM_IMeasureOperations_i::GetBoundingBox (GEOM::GEOM_Object_ptr theShape,
+ CORBA::Boolean precise,
CORBA::Double& Xmin, CORBA::Double& Xmax,
CORBA::Double& Ymin, CORBA::Double& Ymax,
CORBA::Double& Zmin, CORBA::Double& Zmax)
if (aShape.IsNull()) return;
// Get shape parameters
- GetOperations()->GetBoundingBox(aShape, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
+ GetOperations()->GetBoundingBox
+ (aShape, precise, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
}
//=============================================================================
*/
//=============================================================================
GEOM::GEOM_Object_ptr GEOM_IMeasureOperations_i::MakeBoundingBox
- (GEOM::GEOM_Object_ptr theShape)
+ (GEOM::GEOM_Object_ptr theShape,
+ CORBA::Boolean precise)
{
GEOM::GEOM_Object_var aGEOMObject;
if (aShape.IsNull()) return aGEOMObject._retn();
// Make Box - bounding box of theShape
- Handle(GEOM_Object) anObject = GetOperations()->GetBoundingBox(aShape);
+ Handle(GEOM_Object) anObject =
+ GetOperations()->GetBoundingBox(aShape, precise);
if (!GetOperations()->IsDone() || anObject.IsNull())
return aGEOMObject._retn();
CORBA::Double& Ix , CORBA::Double& Iy , CORBA::Double& Iz);
void GetBoundingBox (GEOM::GEOM_Object_ptr theShape,
+ CORBA::Boolean precise,
CORBA::Double& Xmin, CORBA::Double& Xmax,
CORBA::Double& Ymin, CORBA::Double& Ymax,
CORBA::Double& Zmin, CORBA::Double& Zmax);
- GEOM::GEOM_Object_ptr MakeBoundingBox (GEOM::GEOM_Object_ptr theShape);
+ GEOM::GEOM_Object_ptr MakeBoundingBox (GEOM::GEOM_Object_ptr theShape,
+ CORBA::Boolean precise);
void GetTolerance (GEOM::GEOM_Object_ptr theShape,
CORBA::Double& FaceMin, CORBA::Double& FaceMax,
## Get parameters of bounding box of the given shape
# @param theShape Shape to obtain bounding box of.
+ # @param precise TRUE for precise computation; FALSE for fast one.
# @return [Xmin,Xmax, Ymin,Ymax, Zmin,Zmax]
# Xmin,Xmax: Limits of shape along OX axis.
# Ymin,Ymax: Limits of shape along OY axis.
# Zmin,Zmax: Limits of shape along OZ axis.
#
# @ref tui_measurement_tools_page "Example"
- def BoundingBox (self, theShape):
+ def BoundingBox (self, theShape, precise=False):
"""
Get parameters of bounding box of the given shape
Parameters:
theShape Shape to obtain bounding box of.
+ precise TRUE for precise computation; FALSE for fast one.
Returns:
[Xmin,Xmax, Ymin,Ymax, Zmin,Zmax]
Zmin,Zmax: Limits of shape along OZ axis.
"""
# Example: see GEOM_TestMeasures.py
- aTuple = self.MeasuOp.GetBoundingBox(theShape)
+ aTuple = self.MeasuOp.GetBoundingBox(theShape, precise)
RaiseIfFailed("GetBoundingBox", self.MeasuOp)
return aTuple
## Get bounding box of the given shape
# @param theShape Shape to obtain bounding box of.
+ # @param precise TRUE for precise computation; FALSE for fast one.
# @param theName Object name; when specified, this parameter is used
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
# @return New GEOM.GEOM_Object, containing the created box.
#
# @ref tui_measurement_tools_page "Example"
- def MakeBoundingBox (self, theShape, theName=None):
+ def MakeBoundingBox (self, theShape, precise=False, theName=None):
"""
Get bounding box of the given shape
Parameters:
theShape Shape to obtain bounding box of.
+ precise TRUE for precise computation; FALSE for fast one.
theName Object name; when specified, this parameter is used
for result publication in the study. Otherwise, if automatic
publication is switched on, default value is used for result name.
New GEOM.GEOM_Object, containing the created box.
"""
# Example: see GEOM_TestMeasures.py
- anObj = self.MeasuOp.MakeBoundingBox(theShape)
+ anObj = self.MeasuOp.MakeBoundingBox(theShape, precise)
RaiseIfFailed("MakeBoundingBox", self.MeasuOp)
self._autoPublish(anObj, theName, "bndbox")
return anObj
return false;
GEOM::GEOM_IMeasureOperations_var anOper = GEOM::GEOM_IMeasureOperations::_narrow(getOperation());
- anOper->GetBoundingBox(myObj, theXmin, theXmax, theYmin, theYmax, theZmin, theZmax);
+ anOper->GetBoundingBox(myObj, true, theXmin, theXmax, theYmin, theYmax, theZmin, theZmax);
return anOper->IsDone();
}
bool MeasureGUI_BndBoxDlg::execute (ObjectList& objects)
{
GEOM::GEOM_IMeasureOperations_var anOper = GEOM::GEOM_IMeasureOperations::_narrow(getOperation());
- GEOM::GEOM_Object_var anObj = anOper->MakeBoundingBox(myObj);
+ GEOM::GEOM_Object_var anObj = anOper->MakeBoundingBox(myObj, true);
if (!anObj->_is_nil())
objects.push_back(anObj._retn());
// recompute myAng and myStep (Mantis issue 0021718)
GEOM::GEOM_IMeasureOperations_var anOper = getGeomEngine()->GetIMeasureOperations(getStudyId());
double Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
- anOper->GetBoundingBox(myBase.get(), Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
+ anOper->GetBoundingBox(myBase.get(), true, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (anOper->IsDone()) {
// angular step
double diag = sqrt((Xmax-Xmin)*(Xmax-Xmin) + (Ymax-Ymin)*(Ymax-Ymin));
// recompute myStepU (Mantis issue 0021718)
GEOM::GEOM_IMeasureOperations_var anOper = getGeomEngine()->GetIMeasureOperations(getStudyId());
double Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
- anOper->GetBoundingBox(myBase.get(), Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
+ anOper->GetBoundingBox(myBase.get(), true, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (anOper->IsDone()) {
myStepU = floor(1.5 * (Xmax - Xmin));
GroupPoints->SpinBox_DX->setValue(myStepU);
// recompute myStepU and myStepV (Mantis issue 0021718)
GEOM::GEOM_IMeasureOperations_var anOper = getGeomEngine()->GetIMeasureOperations(getStudyId());
double Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
- anOper->GetBoundingBox(myBase.get(), Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
+ anOper->GetBoundingBox(myBase.get(), true, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax);
if (anOper->IsDone()) {
myStepU = floor(1.5 * (Xmax - Xmin));
myStepV = floor(1.5 * (Ymax - Ymin));