From cf71da057110f4d3cfdf542ff4d31bb4884d2119 Mon Sep 17 00:00:00 2001 From: srn Date: Mon, 27 Nov 2006 08:29:59 +0000 Subject: [PATCH] SRN: Implemented method GetSame that seacrhes a shape equal to the given subshape in the main shape. --- idl/GEOM_Gen.idl | 10 + src/GEOMImpl/GEOMImpl_IShapesOperations.cxx | 334 ++++++++++++++++++++ src/GEOMImpl/GEOMImpl_IShapesOperations.hxx | 9 + src/GEOM_I/GEOM_IShapesOperations_i.cc | 36 +++ src/GEOM_I/GEOM_IShapesOperations_i.hh | 3 + 5 files changed, 392 insertions(+) diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 3538eadbf..43904c69f 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -1249,6 +1249,16 @@ module GEOM */ GEOM_Object GetInPlace (in GEOM_Object theShapeWhere, in GEOM_Object theShapeWhat); + + /*! + * Get sub-shape of theShapeWhere, which are + * coincident with \a theShapeWhat that can either SOLID, FACE, EDGE or VERTEX. + * \param theShapeWhere Shape to find sub-shapes of. + * \param theShapeWhat Shape, specifying what to find. + * \return found sub-shape. + */ + GEOM_Object GetSame (in GEOM_Object theShapeWhere, + in GEOM_Object theShapeWhat); }; /*! diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index 67e8f4362..f9e44d18a 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -54,6 +54,7 @@ #include #include +#include #include #include #include @@ -65,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +85,7 @@ #include #include +#include #include #include @@ -2400,3 +2404,333 @@ bool GEOMImpl_IShapesOperations::CheckTriangulation (const TopoDS_Shape& aShape) return true; } + +#define MAX_TOLERANCE 1.e-7 + + +//======================================================================= +//function : isSameEdge +//purpose : Returns True if two edges coincide +//======================================================================= +static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2) +{ + TopoDS_Vertex V11, V12, V21, V22; + TopExp::Vertices(theEdge1, V11, V12); + TopExp::Vertices(theEdge2, V21, V22); + gp_Pnt P11 = BRep_Tool::Pnt(V11); + gp_Pnt P12 = BRep_Tool::Pnt(V12); + gp_Pnt P21 = BRep_Tool::Pnt(V21); + gp_Pnt P22 = BRep_Tool::Pnt(V22); + bool coincide = false; + + //Check that ends of edges coincide + if(P11.Distance(P21) <= MAX_TOLERANCE) { + if(P12.Distance(P22) <= MAX_TOLERANCE) coincide = true; + } + else if(P11.Distance(P22) <= MAX_TOLERANCE) { + if(P12.Distance(P21) <= MAX_TOLERANCE) coincide = true; + } + + if(!coincide) return false; + + double U11, U12, U21, U22; + Handle(Geom_Curve) C1 = BRep_Tool::Curve(theEdge1, U11, U12); + Handle(Geom_Curve) C2 = BRep_Tool::Curve(theEdge2, U21, U22); + if(C1->DynamicType() == C2->DynamicType()) return true; + + //Check that both edges has the same geometry + double range = U12-U11; + double U = U11+ range/3.0; + gp_Pnt P1 = C1->Value(U); //Compute a point on one third of the edge's length + U = U11+range*2.0/3.0; + gp_Pnt P2 = C1->Value(U); //Compute a point on two thirds of the edge's length + + if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) || U < U21 || U > U22) + return false; + + if(P1.Distance(C2->Value(U)) > MAX_TOLERANCE) return false; + + if(!GeomLib_Tool::Parameter(C2, P2, MAX_TOLERANCE, U) || U < U21 || U > U22) + return false; + + if(P2.Distance(C2->Value(U)) > MAX_TOLERANCE) return false; + + return true; +} + +#include +//======================================================================= +//function : isSameFace +//purpose : Returns True if two faces coincide +//======================================================================= +static bool isSameFace(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2) +{ + TopExp_Explorer E(theFace1, TopAbs_EDGE); + TopTools_ListOfShape LS1, LS2; + for(; E.More(); E.Next()) LS1.Append(E.Current()); + + E.Init(theFace2, TopAbs_EDGE); + for(; E.More(); E.Next()) LS2.Append(E.Current()); + + //Compare the number of edges in the faces + if(LS1.Extent() != LS2.Extent()) return false; + + double aMin = RealFirst(), aMax = RealLast(); + double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax; + double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin; + + for(E.Init(theFace1, TopAbs_VERTEX); E.More(); E.Next()) { + gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); + if(P.X() < xminB1) xminB1 = P.X(); + if(P.Y() < yminB1) yminB1 = P.Y(); + if(P.Z() < zminB1) zminB1 = P.Z(); + if(P.X() > xmaxB1) xmaxB1 = P.X(); + if(P.Y() > ymaxB1) ymaxB1 = P.Y(); + if(P.Z() > zmaxB1) zmaxB1 = P.Z(); + } + + for(E.Init(theFace2, TopAbs_VERTEX); E.More(); E.Next()) { + gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); + if(P.X() < xminB2) xminB2 = P.X(); + if(P.Y() < yminB2) yminB2 = P.Y(); + if(P.Z() < zminB2) zminB2 = P.Z(); + if(P.X() > xmaxB2) xmaxB2 = P.X(); + if(P.Y() > ymaxB2) ymaxB2 = P.Y(); + if(P.Z() > zmaxB2) zmaxB2 = P.Z(); + } + + //cout << "Face1 = " << xminB1 << " " << yminB1 << " " << zminB1 << " " << xmaxB1 << " " << ymaxB1 << " " << zmaxB1 << endl; + //cout << "Face2 = " << xminB2 << " " << yminB2 << " " << zminB2 << " " << xmaxB2 << " " << ymaxB2 << " " << zmaxB2 << endl; + + //Compare the bounding boxes of both faces + if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE) + return false; + + if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE) + return false; + + /* + TopTools_ListIteratorOfListOfShape LSI2t(LS2); + for(; LSI2t.More(); LSI2t.Next()) { + TopoDS_Shape aValue = LSI2t.Value(); + cout << (int)((void*)(aValue.TShape()->This()))<< endl; + } + */ + + //Check that each edge of the Face1 has a counterpart in the Face2 + TopTools_MapOfOrientedShape aMap; + TopTools_ListIteratorOfListOfShape LSI1(LS1); + for(; LSI1.More(); LSI1.Next()) { + TopoDS_Edge E = TopoDS::Edge(LSI1.Value()); + bool isFound = false; + TopTools_ListIteratorOfListOfShape LSI2(LS2); + for(; LSI2.More(); LSI2.Next()) { + TopoDS_Shape aValue = LSI2.Value(); + if(aMap.Contains(aValue)) continue; //To avoid checking already found edge several times + if(isSameEdge(E, TopoDS::Edge(aValue))) { + aMap.Add(aValue); + isFound = true; + break; + } + } + if(!isFound) return false; + } + + Handle(Geom_Surface) S1 = BRep_Tool::Surface(theFace1); + Handle(Geom_Surface) S2 = BRep_Tool::Surface(theFace2); + if(S1->DynamicType() == S2->DynamicType()) { + return true; + } + else { //Check if there a coincidence of two surfaces at least in two points + double U11, U12, V11, V12, U21, U22, V21, V22; + BRepTools::UVBounds(theFace1, U11, U12, V11, V12); + BRepTools::UVBounds(theFace2, U21, U22, V21, V22); + + double rangeU = U12-U11; + double rangeV = V12-V11; + double U = U11 + rangeU/3.0; + double V = V11 + rangeV/3.0; + gp_Pnt P1 = S1->Value(U, V); + U = U11+rangeU*2.0/3.0; + V = V11+rangeV*2.0/3.0; + gp_Pnt P2 = S1->Value(U, V); + + if(!GeomLib_Tool::Parameters(S2, P1, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22) + return false; + + if(P1.Distance(S2->Value(U,V)) > MAX_TOLERANCE) return false; + + if(!GeomLib_Tool::Parameters(S2, P2, MAX_TOLERANCE, U, V) || U < U21 || U > U22 || V < V21 || V > V22) + return false; + + if(P2.Distance(S2->Value(U, V)) > MAX_TOLERANCE) return false; + } + + return true; +} + +//======================================================================= +//function : isSameSolid +//purpose : Returns True if two solids coincide +//======================================================================= +bool isSameSolid(const TopoDS_Solid& theSolid1, const TopoDS_Solid& theSolid2) +{ + TopExp_Explorer E(theSolid1, TopAbs_FACE); + TopTools_ListOfShape LS1, LS2; + for(; E.More(); E.Next()) LS1.Append(E.Current()); + E.Init(theSolid2, TopAbs_FACE); + for(; E.More(); E.Next()) LS2.Append(E.Current()); + + if(LS1.Extent() != LS2.Extent()) return false; + + double aMin = RealFirst(), aMax = RealLast(); + double xminB1=aMax, yminB1=aMax, zminB1=aMax, xminB2=aMax, yminB2=aMax, zminB2=aMax; + double xmaxB1=aMin, ymaxB1=aMin, zmaxB1=aMin, xmaxB2=aMin, ymaxB2=aMin, zmaxB2=aMin; + + for(E.Init(theSolid1, TopAbs_VERTEX); E.More(); E.Next()) { + gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); + if(P.X() < xminB1) xminB1 = P.X(); + if(P.Y() < yminB1) yminB1 = P.Y(); + if(P.Z() < zminB1) zminB1 = P.Z(); + if(P.X() > xmaxB1) xmaxB1 = P.X(); + if(P.Y() > ymaxB1) ymaxB1 = P.Y(); + if(P.Z() > zmaxB1) zmaxB1 = P.Z(); + } + + for(E.Init(theSolid2, TopAbs_VERTEX); E.More(); E.Next()) { + gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); + if(P.X() < xminB2) xminB2 = P.X(); + if(P.Y() < yminB2) yminB2 = P.Y(); + if(P.Z() < zminB2) zminB2 = P.Z(); + if(P.X() > xmaxB2) xmaxB2 = P.X(); + if(P.Y() > ymaxB2) ymaxB2 = P.Y(); + if(P.Z() > zmaxB2) zmaxB2 = P.Z(); + } + + //Compare the bounding boxes of both solids + if(gp_Pnt(xminB1, yminB1, zminB1).Distance(gp_Pnt(xminB2, yminB2, zminB2)) > MAX_TOLERANCE) + return false; + + if(gp_Pnt(xmaxB1, ymaxB1, zmaxB1).Distance(gp_Pnt(xmaxB2, ymaxB2, zmaxB2)) > MAX_TOLERANCE) + return false; + + //Check that each face of the Solid1 has a counterpart in the Solid2 + TopTools_MapOfOrientedShape aMap; + TopTools_ListIteratorOfListOfShape LSI1(LS1); + for(; LSI1.More(); LSI1.Next()) { + TopoDS_Face F = TopoDS::Face(LSI1.Value()); + bool isFound = false; + TopTools_ListIteratorOfListOfShape LSI2(LS2); + for(; LSI2.More(); LSI2.Next()) { + if(aMap.Contains(LSI2.Value())) continue; //To avoid checking already found faces several times + if(isSameFace(F, TopoDS::Face(LSI2.Value()))) { + aMap.Add(LSI2.Value()); + isFound = true; + break; + } + } + if(!isFound) return false; + } + + return true; +} + +//======================================================================= +//function : GetSame +//purpose : +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object)& theShapeWhere, + const Handle(GEOM_Object)& theShapeWhat) +{ + SetErrorCode(KO); + if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL; + + TopoDS_Shape aWhere = theShapeWhere->GetValue(); + TopoDS_Shape aWhat = theShapeWhat->GetValue(); + + if (aWhere.IsNull() || aWhat.IsNull()) return NULL; + + int anIndex = -1; + bool isFound = false; + TopoDS_Shape aSubShape; + TopTools_MapOfShape aMap; + + switch(aWhat.ShapeType()) { + case TopAbs_VERTEX: { + gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat)); + TopExp_Explorer E(aWhere, TopAbs_VERTEX); + for(; E.More(); E.Next()) { + gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current())); + if(P.Distance(P2) < MAX_TOLERANCE) { + aSubShape = E.Current(); + break; + } + } + break; + } + case TopAbs_FACE: { + TopoDS_Face aFace = TopoDS::Face(aWhat); + TopExp_Explorer E(aWhere, TopAbs_FACE); + for(; E.More(); E.Next()) { + if(!aMap.Add(E.Current())) continue; + if(isSameFace(aFace, TopoDS::Face(E.Current()))) { + aSubShape = E.Current(); + isFound = true; + break; + } + } + break; + } + case TopAbs_EDGE: { + TopoDS_Edge anEdge = TopoDS::Edge(aWhat); + TopExp_Explorer E(aWhere, TopAbs_EDGE); + for(; E.More(); E.Next()) { + if(!aMap.Add(E.Current())) continue; + if(isSameEdge(anEdge, TopoDS::Edge(E.Current()))) { + aSubShape = E.Current(); + isFound = true; + break; + } + } + break; + } + case TopAbs_SOLID: { + TopoDS_Solid aSolid = TopoDS::Solid(aWhat); + TopExp_Explorer E(aWhere, TopAbs_SOLID); + for(; E.More(); E.Next()) { + if(!aMap.Add(E.Current())) continue; + if(isSameSolid(aSolid, TopoDS::Solid(E.Current()))) { + aSubShape = E.Current(); + isFound = true; + break; + } + } + break; + } + default: + return NULL; + } + + if(isFound) { + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aWhere, anIndices); + if (anIndices.Contains(aSubShape)) + anIndex = anIndices.FindIndex(aSubShape); + } + + if(anIndex < 0) return NULL; + + Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); + + anArray->SetValue(1, anIndex); + + Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, anArray); + Handle(GEOM_Function) aFunction = aResult->GetLastFunction(); + + GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetSame(" + << theShapeWhere << ", " << theShapeWhat << ")"; + + SetErrorCode(OK); + + return aResult; +} diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx index f24d1d03c..546f7867f 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx @@ -194,6 +194,15 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations { Standard_EXPORT static void SortShapes (TopTools_ListOfShape& SL); + /*! + * \brief Searches a shape equal to theWhat in the context of theWhere + * \param theShapeWhere - a context shap + * \param theShapeWhat - a sample shape + * \retval Handle(GEOM_Object) - found shape + */ + Standard_EXPORT Handle(GEOM_Object) GetSame(const Handle(GEOM_Object)& theShapeWhere, + const Handle(GEOM_Object)& theShapeWhat); + private: Handle(GEOM_Object) MakeShape (list theShapes, const Standard_Integer theObjectType, diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.cc b/src/GEOM_I/GEOM_IShapesOperations_i.cc index 23afcacbe..41a5bfc01 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.cc +++ b/src/GEOM_I/GEOM_IShapesOperations_i.cc @@ -1152,3 +1152,39 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::GetInPlace return GetObject(anObject); } + +//============================================================================= +/*! + * GetSame + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::GetSame + (GEOM::GEOM_Object_ptr theShapeWhere, + GEOM::GEOM_Object_ptr theShapeWhat) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + if (theShapeWhere == NULL || + theShapeWhat == NULL) return aGEOMObject._retn(); + + //Get the reference objects + Handle(GEOM_Object) aShapeWhere = GetOperations()->GetEngine()->GetObject + (theShapeWhere->GetStudyID(), theShapeWhere->GetEntry()); + Handle(GEOM_Object) aShapeWhat = GetOperations()->GetEngine()->GetObject + (theShapeWhat->GetStudyID(), theShapeWhat->GetEntry()); + + if (aShapeWhere.IsNull() || + aShapeWhat.IsNull()) return aGEOMObject._retn(); + + //Get Shapes in place of aShapeWhat + Handle(GEOM_Object) anObject = + GetOperations()->GetSame(aShapeWhere, aShapeWhat); + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.hh b/src/GEOM_I/GEOM_IShapesOperations_i.hh index 3cbb9b3d2..58551a5b1 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.hh +++ b/src/GEOM_I/GEOM_IShapesOperations_i.hh @@ -157,6 +157,9 @@ class GEOM_IShapesOperations_i : GEOM::GEOM_Object_ptr GetInPlace (GEOM::GEOM_Object_ptr theShapeWhere, GEOM::GEOM_Object_ptr theShapeWhat); + GEOM::GEOM_Object_ptr GetSame (GEOM::GEOM_Object_ptr theShapeWhere, + GEOM::GEOM_Object_ptr theShapeWhat); + ::GEOMImpl_IShapesOperations* GetOperations() { return (::GEOMImpl_IShapesOperations*)GetImpl(); } }; -- 2.39.2