From: skl Date: Mon, 9 Apr 2007 13:10:07 +0000 (+0000) Subject: Implementation of PipeWithShellSections. X-Git-Tag: V3_2_6pre4~11 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=8ebac247f37b83838053f94bc25d7e1a0989c3ce;p=modules%2Fgeom.git Implementation of PipeWithShellSections. --- diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 33d31bbca..6eba34398 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -888,6 +888,29 @@ module GEOM in boolean theWithContact , in boolean theWithCorrection ); + /*! + * Create a shape by extrusion of the profile shape along + * the path shape. The path shape can be a shell or a face. + * the several profiles can be specified in the several locations of path. + * \param theSeqBases - list of Bases shape to be extruded. + * \param theSeqSubBases - list of corresponding subshapes of section shapes. + * \param theLocations - list of locations on the path corresponding + * specified list of the Bases shapes. Number of locations + * should be equal to number of bases or list of locations can be empty. + * \param thePath - Path shape to extrude the base shape along it. + * \param theWithContact - the mode defining that the section is translated to be in + * contact with the spine. + * \param - WithCorrection - defining that the section is rotated to be + * orthogonal to the spine tangent in the correspondent point + * \return New GEOM_Object, containing the created pipe. + */ + GEOM_Object MakePipeWithShellSections (in ListOfGO theSeqBases, + in ListOfGO theSeqSubBases, + in ListOfGO theLocations, + in GEOM_Object thePath, + in boolean theWithContact , + in boolean theWithCorrection ); + }; /*! diff --git a/idl/GEOM_Superv.idl b/idl/GEOM_Superv.idl index 75f67c8eb..074ff9e5a 100644 --- a/idl/GEOM_Superv.idl +++ b/idl/GEOM_Superv.idl @@ -177,6 +177,13 @@ module GEOM in boolean theWithContact , in boolean theWithCorrection ); + GEOM_Object MakePipeWithShellSections (in ListOfGO theSeqBases, + in ListOfGO theSeqSubBases, + in ListOfGO theLocations, + in GEOM_Object thePath, + in boolean theWithContact , + in boolean theWithCorrection ); + //-----------------------------------------------------------// // BooleanOperations // //-----------------------------------------------------------// diff --git a/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx b/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx index a4ed0e79e..de70f1259 100644 --- a/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx @@ -59,6 +59,7 @@ #include #include #include +#include #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC @@ -1091,17 +1092,18 @@ Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakeThruSections( } + //============================================================================= /*! * MakePipeWithDifferentSections */ //============================================================================= Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeWithDifferentSections( - const Handle(TColStd_HSequenceOfTransient)& theBases, - const Handle(TColStd_HSequenceOfTransient)& theLocations, - const Handle(GEOM_Object)& thePath, - bool theWithContact, - bool theWithCorrections) + const Handle(TColStd_HSequenceOfTransient)& theBases, + const Handle(TColStd_HSequenceOfTransient)& theLocations, + const Handle(GEOM_Object)& thePath, + bool theWithContact, + bool theWithCorrections) { Handle(GEOM_Object) anObj; SetErrorCode(KO); @@ -1232,3 +1234,165 @@ Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeWithDifferentSections( } + + +//============================================================================= +/*! + * MakePipeWithShellSections + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeWithShellSections( + const Handle(TColStd_HSequenceOfTransient)& theBases, + const Handle(TColStd_HSequenceOfTransient)& theSubBases, + const Handle(TColStd_HSequenceOfTransient)& theLocations, + const Handle(GEOM_Object)& thePath, + bool theWithContact, + bool theWithCorrections) +{ + Handle(GEOM_Object) anObj; + SetErrorCode(KO); + if(theBases.IsNull()) + return anObj; + + Standard_Integer nbBases = theBases->Length(); + + if (!nbBases) + return anObj; + + Standard_Integer nbSubBases = (theSubBases.IsNull() ? 0 :theSubBases->Length()); + + Standard_Integer nbLocs = (theLocations.IsNull() ? 0 :theLocations->Length()); + + //Add a new Pipe object + Handle(GEOM_Object) aPipeDS = GetEngine()->AddObject(GetDocID(), GEOM_PIPE); + + //Add a new Pipe function + + Handle(GEOM_Function) aFunction = + aPipeDS->AddFunction(GEOMImpl_PipeDriver::GetID(), PIPE_SHELL_SECTIONS); + if (aFunction.IsNull()) return anObj; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PipeDriver::GetID()) return anObj; + + //GEOMImpl_IPipeDiffSect aCI (aFunction); + GEOMImpl_IPipeShellSect aCI (aFunction); + + Handle(GEOM_Function) aRefPath = thePath->GetLastFunction(); + if(aRefPath.IsNull()) + return anObj; + + Handle(TColStd_HSequenceOfTransient) aSeqBases = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aSeqSubBases = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aSeqLocs = new TColStd_HSequenceOfTransient; + + Standard_Integer i =1; + for( ; i <= nbBases; i++) { + + Handle(Standard_Transient) anItem = theBases->Value(i); + if(anItem.IsNull()) + continue; + Handle(GEOM_Object) aBase = Handle(GEOM_Object)::DownCast(anItem); + if(aBase.IsNull()) + continue; + Handle(GEOM_Function) aRefBase = aBase->GetLastFunction(); + if(aRefBase.IsNull()) + continue; + + if( nbSubBases >= nbBases ) { + Handle(Standard_Transient) aSubItem = theSubBases->Value(i); + if(aSubItem.IsNull()) + continue; + Handle(GEOM_Object) aSubBase = Handle(GEOM_Object)::DownCast(aSubItem); + if(aSubBase.IsNull()) + continue; + Handle(GEOM_Function) aRefSubBase = aSubBase->GetLastFunction(); + if(aRefSubBase.IsNull()) + continue; + aSeqSubBases->Append(aRefSubBase); + } + + if(nbLocs) { + Handle(Standard_Transient) anItemLoc = theLocations->Value(i); + if(anItemLoc.IsNull()) + continue; + Handle(GEOM_Object) aLoc = Handle(GEOM_Object)::DownCast(anItemLoc); + if(aLoc.IsNull()) + continue; + Handle(GEOM_Function) aRefLoc = aLoc->GetLastFunction(); + if(aRefLoc.IsNull()) + continue; + aSeqLocs->Append(aRefLoc); + } + + aSeqBases->Append(aRefBase); + } + + if(!aSeqBases->Length()) + return anObj; + + aCI.SetBases(aSeqBases); + aCI.SetSubBases(aSeqSubBases); + aCI.SetLocations(aSeqLocs); + aCI.SetPath(aRefPath); + aCI.SetWithContactMode(theWithContact); + aCI.SetWithCorrectionMode(theWithCorrections); + + //Compute the Pipe value + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Pipe with shell sections driver failed"); + return anObj; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return anObj; + } + + //Make a Python command + GEOM::TPythonDump pyDump(aFunction); + pyDump << aPipeDS << " = geompy.MakePipeWithShellSections(["; + + for(i =1 ; i <= nbBases; i++) { + + Handle(Standard_Transient) anItem = theBases->Value(i); + if(anItem.IsNull()) + continue; + + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(anItem); + if(!anObj.IsNull()) { + pyDump<< anObj; + if(i < nbBases) + pyDump<<", "; + } + + } + + pyDump<< "], ["; + + for(i =1 ; i <= nbLocs; i++) { + + Handle(Standard_Transient) anItem = theLocations->Value(i); + if(anItem.IsNull()) + continue; + + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(anItem); + if(!anObj.IsNull()) { + pyDump<< anObj; + if(i < nbLocs) + pyDump<<", "; + } + } + + pyDump<< "], "<SetReferenceList(PIPEDS_LIST_BASES,theBases); } + { + _func->SetReferenceList(PIPEDS_LIST_BASES,theBases); + } Handle(TColStd_HSequenceOfTransient) GetBases () { Handle(TColStd_HSequenceOfTransient) aBases = _func->GetReferenceList(PIPEDS_LIST_BASES); return aBases; - } + } void SetLocations (const Handle(TColStd_HSequenceOfTransient)& theLocations) { _func->SetReferenceList(PIPEDS_LIST_LOCATIONS,theLocations); } diff --git a/src/GEOMImpl/GEOMImpl_IPipeShellSect.hxx b/src/GEOMImpl/GEOMImpl_IPipeShellSect.hxx new file mode 100644 index 000000000..590e83697 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_IPipeShellSect.hxx @@ -0,0 +1,55 @@ +// Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +//NOTE: This is an intreface to a function for the Pipe creation. + +#ifndef _GEOMImpl_IPIPESHELLSECT_HXX_ +#define _GEOMImpl_IPIPESHELLSECT_HXX_ + +#include "GEOM_Function.hxx" + +#ifndef _GEOMImpl_IPIPEDIFFSECT_HXX_ +#include "GEOMImpl_IPipeDiffSect.hxx" +#endif + +#define PIPEDS_LIST_SUBBASES 6 + + +class GEOMImpl_IPipeShellSect : public GEOMImpl_IPipeDiffSect +{ + public: + + GEOMImpl_IPipeShellSect(const Handle(GEOM_Function)& theFunction): + GEOMImpl_IPipeDiffSect(theFunction) {} + + void SetSubBases (const Handle(TColStd_HSequenceOfTransient)& theSubBases) + { + _func->SetReferenceList(PIPEDS_LIST_SUBBASES,theSubBases); + } + + Handle(TColStd_HSequenceOfTransient) GetSubBases () + { + Handle(TColStd_HSequenceOfTransient) aSubBases = + _func->GetReferenceList(PIPEDS_LIST_SUBBASES); + return aSubBases; + } + +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx index d0875f842..b14de152b 100644 --- a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx @@ -35,9 +35,13 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include #include @@ -47,6 +51,20 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include + //======================================================================= //function : GetID @@ -67,6 +85,834 @@ GEOMImpl_PipeDriver::GEOMImpl_PipeDriver() { } + +//======================================================================= +//function : FillForOtherEdges +//purpose : auxilary for CreatePipeForShellSections() +//======================================================================= +static bool FillForOtherEdges(const TopoDS_Shape& F1, + const TopoDS_Shape& E1, + const TopoDS_Shape& V1, + TopTools_IndexedDataMapOfShapeShape& FF) +{ + //cout<<"FillForOtherEdges"<GetBases(); + Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases(); + Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations(); + Standard_Boolean aWithContact = (aCIDS->GetWithContactMode()); + Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode()); + + Standard_Integer nbBases = aBasesObjs->Length(), + nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()), + nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length()); + + if( nbLocs != nbBases) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Number of sections is not equal to number of locations "); + } + if( nbSubBases && nbSubBases != nbBases) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections "); + } + + //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); + + TopTools_SequenceOfShape VLocs; + for(i=1; i<=nbBases; i++) { + Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i); + if(anItemLoc.IsNull()) + continue; + Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc); + TopoDS_Shape aShapeLoc = aRefLoc->GetValue(); + if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX) + continue; + VLocs.Append(aShapeLoc); + } + nbLocs = VLocs.Length(); + if( nbLocs != nbBases) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("One of location shapes is not a vertex"); + } + // split wire path by location points + TColgp_SequenceOfPnt PLocs; + for(i=1; i<=nbLocs; i++) { + TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i)); + PLocs.Append(BRep_Tool::Pnt(V)); + } + TopTools_SequenceOfShape Edges; + TopTools_SequenceOfShape Wires; + TopExp_Explorer anExp; + for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { + Edges.Append(anExp.Current()); + } + ShapeAnalysis_Edge sae; + TopoDS_Edge edge = TopoDS::Edge(Edges.First()); + double tol = BRep_Tool::Tolerance(edge); + TopoDS_Vertex VF = sae.FirstVertex(edge); + gp_Pnt PF = BRep_Tool::Pnt(VF); + //cout<<"PF("< tol ) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise + ("First location shapes is not coincided with first vertex of aWirePath"); + } + edge = TopoDS::Edge(Edges.Last()); + tol = BRep_Tool::Tolerance(edge); + TopoDS_Vertex VL = sae.LastVertex(edge); + gp_Pnt PL = BRep_Tool::Pnt(VL); + if( PL.Distance(PLocs.Last()) > tol ) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise + ("Last location shapes is not coincided with last vertex of aWirePath"); + } + int jcurr = 2; + TopTools_SequenceOfShape tmpEdges; + for(i=1; i<=Edges.Length() && jcurr0 && + PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) { + double param = PPC.Parameter(1); + gp_Pnt PC1; + C->D0(param,PC1); + // split current edge + Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param); + Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp); + TopoDS_Edge E1,E2; + if(PC1.Distance(P1)Value(i); + if(anItem1.IsNull()) + continue; + Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1); + if(aRefBase1.IsNull()) + continue; + TopoDS_Shape aShBase1 = aRefBase1->GetValue(); + if(aShBase1.IsNull()) + continue; + TopAbs_ShapeEnum aType1 = aShBase1.ShapeType(); + // 2 section + Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1); + if(anItem2.IsNull()) + continue; + Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2); + if(aRefBase2.IsNull()) + continue; + TopoDS_Shape aShBase2 = aRefBase2->GetValue(); + if(aShBase2.IsNull()) + continue; + TopAbs_ShapeEnum aType2 = aShBase2.ShapeType(); + + //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep"); + + bool OkSec = ( aType1==TopAbs_SHELL || aType1==TopAbs_FACE ) && + ( aType2==TopAbs_SHELL || aType2==TopAbs_FACE ); + if( !OkSec ) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("One of section shapes has invalid type"); + } + + bool CreateFewSolids = false; + // compare sections + TopExp_Explorer anExp; + Standard_Integer nbf1 = 0; + for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + nbf1++; + } + Standard_Integer nbf2 = 0; + for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + nbf2++; + } + if(nbf1==nbf2) { + CreateFewSolids = true; + } + + if(!CreateFewSolids) { + // we can create only one solid + TopoDS_Shape aWire1, aWire2; + // prepare aWire1 + if(aType1==TopAbs_SHELL) { + // create wire as boundary contour if shell is no closed + // get free boundary shapes + ShapeAnalysis_FreeBounds anAnalizer( aShBase1 ); + TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); + //TopExp_Explorer anExp; + Standard_Integer NbWires = 0; + for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { + NbWires++; + aWire1 = anExp.Current(); + } + if(NbWires!=1) { + // bad case + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Bad shell is used as section "); + } + } + else { // aType1==TopAbs_FACE + TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE); + aWire1 = aExpW.Current(); + } + // prepare aWire2 + if(aType2==TopAbs_SHELL) { + // create wire as boundary contour if shell is no closed + // get free boundary shapes + ShapeAnalysis_FreeBounds anAnalizer( aShBase2 ); + TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); + //TopExp_Explorer anExp; + Standard_Integer NbWires = 0; + for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { + NbWires++; + aWire2 = anExp.Current(); + } + if(NbWires!=1) { + // bad case + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Bad shell is used as section "); + } + } + else { // aType2==TopAbs_FACE + TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE); + aWire2 = aExpW.Current(); + } + // make pipe using aWire1 and aWire2 + if( !aWire1.IsNull() && !aWire2.IsNull() ) { + //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); + BRepOffsetAPI_MakePipeShell aBuilder(WPath); + aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), + aWithContact, aWithCorrect); + aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), + aWithContact, aWithCorrect); + if(!aBuilder.IsReady()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); + } + aBuilder.Build(); + TopoDS_Shape aShape = aBuilder.Shape(); + TopoDS_Shell aShell; + B.MakeShell(aShell); + for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + B.Add(aShell,anExp.Current()); + } + for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + B.Add(aShell,anExp.Current()); + } + for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + B.Add(aShell,anExp.Current()); + } + // make sewing for this shell + Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; + aSewing->SetTolerance(Precision::Confusion()); + aSewing->SetFaceMode(Standard_True); + aSewing->SetFloatingEdgesMode(Standard_False); + aSewing->SetNonManifoldMode(Standard_False); + for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + aSewing->Add(anExp.Current()); + } + aSewing->Perform(); + const TopoDS_Shape aSewShape = aSewing->SewedShape(); + if( aSewShape.ShapeType() == TopAbs_SHELL ) { + aShell = TopoDS::Shell(aSewShape); + if(BRep_Tool::IsClosed(aShell)) { + TopoDS_Solid aSolid; + B.MakeSolid(aSolid); + B.Add(aSolid,aShell); + B.Add(aComp,aSolid); + } + else { + B.Add(aComp,aShell); + } + } + else { + B.Add(aComp,aShell); + } + } + } + else { + // main block - creation few solids (for each pair of faces) + TopTools_MapOfShape aFaces1,aFaces2; + for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) + aFaces1.Add(anExp.Current()); + for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) + aFaces2.Add(anExp.Current()); + // creating map of edge faces + TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1; + TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1); + TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2; + TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2); + + // constuct map face->face + TopTools_IndexedDataMapOfShapeShape FF; + TopoDS_Shape FS1,FS2; + if(nbSubBases==0) { + // find edge the most distant from location point + // (this edge is not shared by two faces) + double maxdist = 0.; + TopoDS_Shape E1; + TopoDS_Vertex V11,V21; + for(j=1; j<=aMapEdgeFaces1.Extent(); j++) { + TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j); + const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp); + if(aList.Extent()>1) + continue; + TopExp_Explorer expv; + expv.Init( tmp, TopAbs_VERTEX ); + TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current()); + expv.Next(); + TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current()); + gp_Pnt P1 = BRep_Tool::Pnt(V1); + gp_Pnt P2 = BRep_Tool::Pnt(V2); + double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2); + if(dist>maxdist) { + E1 = tmp; + V11 = V1; + V21 = V2; + TopTools_ListIteratorOfListOfShape anIter(aList); + FS1 = anIter.Value(); + maxdist = dist; + } + } + // main direction for comparing + gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1)); + // find corresponding edge from next section + double minang = PI; + gp_Pnt P11 = BRep_Tool::Pnt(V11); + gp_Pnt P21 = BRep_Tool::Pnt(V21); + TopoDS_Shape E2; + TopoDS_Vertex V12,V22; + for(j=1; j<=aMapEdgeFaces2.Extent(); j++) { + TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j); + const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp); + if(aList.Extent()>1) + continue; + TopExp_Explorer expv; + expv.Init( tmp, TopAbs_VERTEX ); + TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current()); + expv.Next(); + TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current()); + gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp); + gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp); + double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21); + double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11); + TopoDS_Vertex V1,V2; + gp_Pnt P1,P2; + if(d1>d2) { + V1 = V2tmp; P1 = P2tmp; + V2 = V1tmp; P2 = P1tmp; + } + else { + V1 = V1tmp; P1 = P1tmp; + V2 = V2tmp; P2 = P2tmp; + } + gp_Vec Vec1(P11,P1); + gp_Vec Vec2(P21,P2); + double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM)); + if(angValue(i); + if(anItem.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); + if(aRefBase.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + TopoDS_Shape aSh = aRefBase->GetValue(); + if(aSh.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + if(aSh.ShapeType()!=TopAbs_FACE) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + FS1 = aSh; + } + { // 2 section + Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1); + if(anItem.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); + if(aRefBase.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + TopoDS_Shape aSh = aRefBase->GetValue(); + if(aSh.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + if(aSh.ShapeType()!=TopAbs_FACE) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + FS2 = aSh; + } + + if( !aFaces1.Contains(FS1) || !aFaces2.Contains(FS2) ) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + + FF.Add(FS1,FS2); + + // add pairs of edges to FF + bool stat = FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)), + TopoDS::Vertex(VLocs(i+1)), WPath, FF); + if( !stat ) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Can not create correct pipe"); + } + } + + FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI); + + + // make pipe for each pair of faces + //BRepTools::Write(WPath,"/dn02/users_Linux/skl/work/Bugs/14857/wpath.brep"); + for(j=1; j<=FF.Extent(); j++) { + TopoDS_Shape F1 = FF.FindKey(j); + if( F1.ShapeType() != TopAbs_FACE ) + continue; + TopoDS_Shape F2 = FF.FindFromIndex(j); + TopExp_Explorer aExpW1(F1,TopAbs_WIRE); + TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current()); + TopExp_Explorer aExpW2(F2,TopAbs_WIRE); + TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current()); + // make pipe using aWire1 and aWire2 + if( !aWire1.IsNull() && !aWire2.IsNull() ) { + BRepOffsetAPI_MakePipeShell aBuilder(WPath); + aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), + aWithContact, aWithCorrect); + aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), + aWithContact, aWithCorrect); + if(!aBuilder.IsReady()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); + } + aBuilder.Build(); + TopoDS_Shape aShape = aBuilder.Shape(); + TopoDS_Shell aShell; + B.MakeShell(aShell); + //int nbf=0; + for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + //nbf++; + //cout<<"nbf="<SetTolerance(Precision::Confusion()); + aSewing->SetFaceMode(Standard_True); + aSewing->SetFloatingEdgesMode(Standard_False); + aSewing->SetNonManifoldMode(Standard_False); + for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + aSewing->Add(anExp.Current()); + } + aSewing->Perform(); + const TopoDS_Shape aSewShape = aSewing->SewedShape(); + if( aSewShape.ShapeType() == TopAbs_SHELL ) { + aShell = TopoDS::Shell(aSewShape); + if(BRep_Tool::IsClosed(aShell)) { + TopoDS_Solid aSolid; + B.MakeSolid(aSolid); + B.Add(aSolid,aShell); + B.Add(aComp,aSolid); + } + else { + B.Add(aComp,aShell); + } + } + else { + B.Add(aComp,aShell); + } + } + } + + } + } + + return aComp; +} + + //======================================================================= //function : Execute //purpose : @@ -81,6 +927,8 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const aCI = new GEOMImpl_IPipe(aFunction); else if(aType == PIPE_DIFFERENT_SECTIONS) aCI = new GEOMImpl_IPipeDiffSect(aFunction); + else if(aType == PIPE_SHELL_SECTIONS) + aCI = new GEOMImpl_IPipeShellSect(aFunction); else return 0; @@ -88,8 +936,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const TopoDS_Shape aShapePath = aRefPath->GetValue(); - if (aShapePath.IsNull()) - { + if (aShapePath.IsNull()) { cout<<"Driver : path is null"<GetBase(); @@ -167,8 +1012,31 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const //if for section was specified face with a few wires then a few // pipes were build and make solid - if(aTypeBase == TopAbs_FACE) + Standard_Boolean NeedCreateSolid = Standard_False; + if(aTypeBase == TopAbs_SHELL) { + // create wire as boundary contour if shell is no closed + // get free boundary shapes + ShapeAnalysis_FreeBounds anAnalizer( aShapeBase ); + TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); + TopExp_Explorer anExp; + TopoDS_Shape aWire; + Standard_Integer NbWires = 0; + for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { + NbWires++; + aWire = anExp.Current(); + } + if(NbWires!=1) { + // bad case + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Bad shell is used as section "); + } + NeedCreateSolid = Standard_True; + aSeqFaces.Append(aShapeBase); + aSeqBases.Append(aWire); + } + else if(aTypeBase == TopAbs_FACE) { + NeedCreateSolid = Standard_True; //for case one path should be used other type function aSeqFaces.Append(aShapeBase); TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE); @@ -178,8 +1046,9 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const aSeqBases.Append(aWireProf); } } - else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) + else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) { aSeqBases.Append(aShapeBase); + } else if(aTypeBase == TopAbs_EDGE) { TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase); @@ -252,6 +1121,12 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const aShape = aComp; } } + + //building pipe with shell sections + else if (aType == PIPE_SHELL_SECTIONS) { + aShape = CreatePipeForShellSections(aWirePath,aCI); + } + if (aShape.IsNull()) return 0; BRepCheck_Analyzer ana (aShape, Standard_False); @@ -309,3 +1184,4 @@ const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Ha return _anOtherObject ; } + diff --git a/src/GEOMImpl/GEOMImpl_PipeDriver.hxx b/src/GEOMImpl/GEOMImpl_PipeDriver.hxx index 888b2cd5d..b57defc89 100644 --- a/src/GEOMImpl/GEOMImpl_PipeDriver.hxx +++ b/src/GEOMImpl/GEOMImpl_PipeDriver.hxx @@ -48,6 +48,7 @@ #include #endif + class Standard_Transient; class Handle_Standard_Type; class Handle(TFunction_Driver); @@ -136,22 +137,25 @@ public: if (anAddress) Standard::Free((Standard_Address&)anAddress); } - // Methods PUBLIC - // -Standard_EXPORT GEOMImpl_PipeDriver(); -Standard_EXPORT virtual Standard_Integer Execute(TFunction_Logbook& log) const; -Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {} -Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; } -Standard_EXPORT static const Standard_GUID& GetID(); -Standard_EXPORT ~GEOMImpl_PipeDriver() {}; - - - // Type management - // -Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_PipeDriver_Type_(); -Standard_EXPORT const Handle(Standard_Type)& DynamicType() const { return STANDARD_TYPE(GEOMImpl_PipeDriver) ; } -Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const { return (STANDARD_TYPE(GEOMImpl_PipeDriver) == AType || TFunction_Driver::IsKind(AType)); } - + // Methods PUBLIC + // + Standard_EXPORT GEOMImpl_PipeDriver(); + Standard_EXPORT virtual Standard_Integer Execute(TFunction_Logbook& log) const; + Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {} + Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const + { return Standard_True; } + Standard_EXPORT static const Standard_GUID& GetID(); + Standard_EXPORT ~GEOMImpl_PipeDriver() {}; + + + // Type management + // + Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_PipeDriver_Type_(); + Standard_EXPORT const Handle(Standard_Type)& DynamicType() const + { return STANDARD_TYPE(GEOMImpl_PipeDriver) ; } + Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const + { return (STANDARD_TYPE(GEOMImpl_PipeDriver) == AType || + TFunction_Driver::IsKind(AType)); } }; diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index 897873d09..2e0170267 100755 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -162,6 +162,7 @@ #define PIPE_BASE_PATH 1 #define PIPE_DIFFERENT_SECTIONS 2 +#define PIPE_SHELL_SECTIONS 3 #define THRUSECTIONS_RULED 1 #define THRUSECTIONS_SMOOTHED 2 diff --git a/src/GEOM_I/GEOM_I3DPrimOperations_i.cc b/src/GEOM_I/GEOM_I3DPrimOperations_i.cc index 561d24512..83a98e3a4 100644 --- a/src/GEOM_I/GEOM_I3DPrimOperations_i.cc +++ b/src/GEOM_I/GEOM_I3DPrimOperations_i.cc @@ -582,3 +582,80 @@ GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::MakePipeWithDifferentSections(co return GetObject(anObject); } + + +//============================================================================= +/*! + * MakePipeWithShellSections + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::MakePipeWithShellSections + (const GEOM::ListOfGO& theBases, + const GEOM::ListOfGO& theSubBases, + const GEOM::ListOfGO& theLocations, + GEOM::GEOM_Object_ptr thePath, + CORBA::Boolean theWithContact, + CORBA::Boolean theWithCorrections) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + Handle(TColStd_HSequenceOfTransient) aSeqBases = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aSeqSubBases = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aSeqLocations = new TColStd_HSequenceOfTransient; + int ind=0, aNbBases=0, aNbSubBases=0, aNbLocs=0; + + //Get the shapes + aNbBases = theBases.length(); + aNbSubBases = theSubBases.length(); + aNbLocs = theLocations.length(); + + if( aNbLocs && aNbBases != aNbLocs) + return aGEOMObject._retn(); + + Handle(GEOM_Object) aPath = GetOperations()->GetEngine()->GetObject + (thePath->GetStudyID(), thePath->GetEntry()); + if(aPath.IsNull()) + return aGEOMObject._retn(); + + for (ind = 0; ind < aNbBases; ind++) { + if (theBases[ind] == NULL) continue; + Handle(GEOM_Object) aBase = GetOperations()->GetEngine()-> + GetObject(theBases[ind]->GetStudyID(), theBases[ind]->GetEntry()); + if(aBase.IsNull()) + continue; + if(aNbLocs) { + Handle(GEOM_Object) aLoc = GetOperations()->GetEngine()->GetObject + (theLocations[ind]->GetStudyID(), theLocations[ind]->GetEntry()); + if(aLoc.IsNull()) + continue; + aSeqLocations->Append(aLoc); + } + aSeqBases->Append(aBase); + + if(aNbSubBases>=aNbBases) { + Handle(GEOM_Object) aSubBase = GetOperations()->GetEngine()-> + GetObject(theSubBases[ind]->GetStudyID(), theSubBases[ind]->GetEntry()); + if(aSubBase.IsNull()) { + aSeqSubBases->Clear(); + aNbSubBases = 0; + continue; + } + aSeqSubBases->Append(aSubBase); + } + + } + if(!aSeqBases->Length()) + return aGEOMObject._retn(); + + // Make pipe + Handle(GEOM_Object) anObject = + GetOperations()->MakePipeWithShellSections(aSeqBases, aSeqSubBases, + aSeqLocations, aPath, + theWithContact, theWithCorrections); + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} diff --git a/src/GEOM_I/GEOM_I3DPrimOperations_i.hh b/src/GEOM_I/GEOM_I3DPrimOperations_i.hh index 97c6f16cb..a9cae2c0b 100644 --- a/src/GEOM_I/GEOM_I3DPrimOperations_i.hh +++ b/src/GEOM_I/GEOM_I3DPrimOperations_i.hh @@ -105,6 +105,13 @@ class GEOM_I3DPrimOperations_i : CORBA::Boolean theWithContact, CORBA::Boolean theWithCorrections); + GEOM::GEOM_Object_ptr MakePipeWithShellSections(const GEOM::ListOfGO& theBases, + const GEOM::ListOfGO& theSubBases, + const GEOM::ListOfGO& theLocations, + GEOM::GEOM_Object_ptr thePath, + CORBA::Boolean theWithContact, + CORBA::Boolean theWithCorrections); + ::GEOMImpl_I3DPrimOperations* GetOperations() { return (::GEOMImpl_I3DPrimOperations*)GetImpl(); } }; diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.cc b/src/GEOM_I_Superv/GEOM_Superv_i.cc index c67fb1735..24b2f0f11 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.cc +++ b/src/GEOM_I_Superv/GEOM_Superv_i.cc @@ -978,11 +978,12 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeThruSections(const GEOM::ListOfGO& theS //============================================================================= // MakePipe: //============================================================================= -GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithDifferentSections(const GEOM::ListOfGO& theBases, - const GEOM::ListOfGO& theLocations, - GEOM::GEOM_Object_ptr thePath, - CORBA::Boolean theWithContact, - CORBA::Boolean theWithCorrections) +GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithDifferentSections + (const GEOM::ListOfGO& theBases, + const GEOM::ListOfGO& theLocations, + GEOM::GEOM_Object_ptr thePath, + CORBA::Boolean theWithContact, + CORBA::Boolean theWithCorrections) { beginService( " GEOM_Superv_i::MakePipeWithDifferentSections" ); MESSAGE("GEOM_Superv_i::MakePipeWithDifferentSections"); @@ -991,6 +992,31 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithDifferentSections(const GEOM::L endService( " GEOM_Superv_i::MakePipeWithDifferentSections" ); return anObj; } + + +//============================================================================= +// MakePipe: +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_Superv_i::MakePipeWithShellSections + (const GEOM::ListOfGO& theBases, + const GEOM::ListOfGO& theSubBases, + const GEOM::ListOfGO& theLocations, + GEOM::GEOM_Object_ptr thePath, + CORBA::Boolean theWithContact, + CORBA::Boolean theWithCorrections) +{ + beginService( " GEOM_Superv_i::MakePipeWithShellSections" ); + MESSAGE("GEOM_Superv_i::MakePipeWithShellSections"); + get3DPrimOp(); + GEOM::GEOM_Object_ptr anObj = + my3DPrimOp->MakePipeWithShellSections(theBases, theSubBases, + theLocations, thePath, + theWithContact, theWithCorrections); + endService( " GEOM_Superv_i::MakePipeWithShellSections" ); + return anObj; +} + + //============================================================================= // MakeFuse: //============================================================================= diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.hh b/src/GEOM_I_Superv/GEOM_Superv_i.hh index 1d8f5b94c..3ec66530b 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.hh +++ b/src/GEOM_I_Superv/GEOM_Superv_i.hh @@ -237,6 +237,13 @@ public: CORBA::Boolean theWithContact, CORBA::Boolean theWithCorrections); + GEOM::GEOM_Object_ptr MakePipeWithShellSections(const GEOM::ListOfGO& theBases, + const GEOM::ListOfGO& theSubBases, + const GEOM::ListOfGO& theLocations, + GEOM::GEOM_Object_ptr thePath, + CORBA::Boolean theWithContact, + CORBA::Boolean theWithCorrections); + //-----------------------------------------------------------// // BooleanOperations // //-----------------------------------------------------------// diff --git a/src/GEOM_SWIG/geompy.py b/src/GEOM_SWIG/geompy.py index 119e2d976..ce42e671b 100644 --- a/src/GEOM_SWIG/geompy.py +++ b/src/GEOM_SWIG/geompy.py @@ -740,6 +740,32 @@ def MakePipeWithDifferentSections(theSeqBases, theLocations,thePath,theWithConta print "MakePipeWithDifferentSections : ", PrimOp.GetErrorCode() return anObj +## Create a shape by extrusion of the profile shape along +# the path shape. The path shape can be a shell or a face. +# the several profiles can be specified in the several locations of path. +# @param theSeqBases - list of Bases shape to be extruded. +# @param theSeqSubBases - list of corresponding subshapes of section shapes. +# @param theLocations - list of locations on the path corresponding +# specified list of the Bases shapes. Number of locations +# should be equal to number of bases or list of locations can be empty. +# @param thePath - Path shape to extrude the base shape along it. +# @param theWithContact - the mode defining that the section is translated to be in +# contact with the spine. +# @param - WithCorrection - defining that the section is rotated to be +# orthogonal to the spine tangent in the correspondent point +# @return New GEOM_Object, containing the created solids. +# +# Example: see GEOM_TestAll.py +def MakePipeWithShellSections(theSeqBases, theSeqSubBases, + theLocations, thePath, + theWithContact, theWithCorrection): + anObj = PrimOp.MakePipeWithShellSections(theSeqBases, theSeqSubBases, + theLocations, thePath, + theWithContact, theWithCorrection) + if PrimOp.IsDone() == 0: + print "MakePipeWithShellSections : ", PrimOp.GetErrorCode() + return anObj + # ----------------------------------------------------------------------------- # Create base shapes # -----------------------------------------------------------------------------