X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_GlueDriver.cxx;h=7ba7a22700e212221ab4bd44eb1dcf5df79be4cd;hb=e403b95e1b6f4613dcf9564c3d720d25dbcde8ef;hp=e41b48ccbc4895584aebd62deb47cd0f84e4a4dd;hpb=d3dd282390888d7dc091ba2c2ffe7923bd7458e6;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_GlueDriver.cxx b/src/GEOMImpl/GEOMImpl_GlueDriver.cxx index e41b48ccb..7ba7a2270 100644 --- a/src/GEOMImpl/GEOMImpl_GlueDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_GlueDriver.cxx @@ -1,313 +1,326 @@ - -using namespace std; -#include "GEOMImpl_GlueDriver.hxx" -#include "GEOMImpl_IGlue.hxx" -#include "GEOMImpl_Types.hxx" -#include "GEOM_Function.hxx" - -#include -#include -#include -#include -#include -#include +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 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 +// + +#include + +#include +#include +#include + +#include +#include + +#include +#include "GEOMAlgo_Gluer1.hxx" +#include "GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx" +#include "GEOMAlgo_CoupleOfShapes.hxx" +#include "GEOMAlgo_ListOfCoupleOfShapes.hxx" + +#include "utilities.h" + +#include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include +#include #include -#include -#include -#include +#include + #include -#include +#include + +#define MSG_BAD_TOLERANCE "Tolerance is too big" +#define MSG_BAD_ARG_SHAPE "Argument shape is not a compound of hexahedral solids" //======================================================================= -//function : GetID +//function : GEOMImpl_GlueDriver //purpose : //======================================================================= -const Standard_GUID& GEOMImpl_GlueDriver::GetID() +GEOMImpl_GlueDriver::GEOMImpl_GlueDriver() { - static Standard_GUID aGlueDriver("FF1BBB63-5D14-4df2-980B-3A668264EA16"); - return aGlueDriver; } - //======================================================================= -//function : GEOMImpl_GlueDriver +//function : GetID //purpose : //======================================================================= -GEOMImpl_GlueDriver::GEOMImpl_GlueDriver() +const Standard_GUID& GEOMImpl_GlueDriver::GetID() { + static Standard_GUID aGlueDriver("FF1BBB63-5D14-4df2-980B-3A668264EA16"); + return aGlueDriver; } //======================================================================= -//function : FindSameFace -//purpose : for GLUE_FACES +//function : GlueFacesWithWarnings +//purpose : //======================================================================= -static TopoDS_Face FindSameFace (const TopoDS_Shape& aShape, - const TopoDS_Face& F, - const double tol3d) +TopoDS_Shape GEOMImpl_GlueDriver::GlueFacesWithWarnings (const TopoDS_Shape& theShape, + const Standard_Real theTolerance, + const Standard_Boolean doKeepNonSolids, + TCollection_AsciiString& theWarning) const { - TopoDS_Face aFace; - bool isSame = false; - for (TopExp_Explorer exf (aShape, TopAbs_FACE); exf.More(); exf.Next()) { - // test a face - int nbFound = 0; - aFace = TopoDS::Face(exf.Current()); - TopTools_ListOfShape liste1; - TopTools_ListOfShape liste2; - for (TopExp_Explorer exp (aFace, TopAbs_VERTEX); exp.More(); exp.Next()) { - const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current()); - liste1.Append(V); - } - for (TopExp_Explorer exp (F, TopAbs_VERTEX); exp.More(); exp.Next()) { - const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current()); - liste2.Append(V); - } - isSame = false; - if (liste1.Extent() == liste2.Extent()) - { - TopTools_ListIteratorOfListOfShape it1 (liste1); - isSame = true; - for (; it1.More(); it1.Next()) + Standard_Integer iErr, iWrn; + TopoDS_Shape aRes; + GEOMAlgo_Gluer aGluer; + + aGluer.SetShape(theShape); + aGluer.SetTolerance(theTolerance); + aGluer.SetCheckGeometry(Standard_True); + aGluer.SetKeepNonSolids(doKeepNonSolids); + + aGluer.Perform(); + + iErr = aGluer.ErrorStatus(); + if (iErr) { + switch (iErr) { + case 2: + Standard_Failure::Raise("No vertices found in source shape"); + break; + case 3: + case 4: + Standard_Failure::Raise(MSG_BAD_TOLERANCE " or " MSG_BAD_ARG_SHAPE); + break; + case 5: + Standard_Failure::Raise("Source shape is Null"); + break; + case 6: + Standard_Failure::Raise("Result shape is Null"); + break; + case 100: + Standard_Failure::Raise(MSG_BAD_TOLERANCE); + break; + case 101: + case 102: + Standard_Failure::Raise(MSG_BAD_ARG_SHAPE); + break; + case 200: + Standard_Failure::Raise("Error occured during check of geometric coincidence"); + break; + default: { - bool foundSamePoint = false; - gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1.Value())); - TopTools_ListIteratorOfListOfShape it2 (liste2); - for (; it2.More(); it2.Next()) { - gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2.Value())); - double d = P1.Distance(P2); - if (d < tol3d) { - nbFound++; - // found Same Point : P1 - foundSamePoint = true; - break; - } - } - isSame = isSame && foundSamePoint; - if (! isSame) break; // a vertex does not correspond : not same face + // description of all errors see in GEOMAlgo_Gluer.cxx + TCollection_AsciiString aMsg ("Error in GEOMAlgo_Gluer with code "); + aMsg += TCollection_AsciiString(iErr); + Standard_Failure::Raise(aMsg.ToCString()); + break; } } - if (isSame) { - // Found Same Face - break; // a face corresponding to F is found - } + return aRes; } - if (!isSame) aFace.Nullify(); // return null face - return aFace; -} -//======================================================================= -//function : FindSameEdge -//purpose : for GLUE_FACES -//======================================================================= -static TopoDS_Edge FindSameEdge (const TopoDS_Face& nf, - TopoDS_Edge& Eold, - const double tol3d) -{ - TopoDS_Face newFace = TopoDS::Face(nf.Oriented(TopAbs_REVERSED)); - TopoDS_Vertex VFirst, VLast; - TopExp::Vertices(Eold, VFirst, VLast); - gp_Pnt Pf = BRep_Tool::Pnt(VFirst); - gp_Pnt Pl = BRep_Tool::Pnt(VLast); - TopoDS_Edge Enew; - for (TopExp_Explorer ee (newFace, TopAbs_EDGE); ee.More(); ee.Next()) { - const TopoDS_Edge& E = TopoDS::Edge(ee.Current()); - TopoDS_Vertex VFn, VLn; - TopExp::Vertices(E, VFn, VLn); - gp_Pnt Pfn = BRep_Tool::Pnt(VFn); - gp_Pnt Pln = BRep_Tool::Pnt(VLn); - double dff = Pf.Distance(Pfn); - double dfl = Pf.Distance(Pln); - double dlf = Pl.Distance(Pfn); - double dll = Pl.Distance(Pln); - if ((dff < tol3d) && (dll SetPrecision(Precision::Confusion()); + aSfs->Perform(); + aRes = aSfs->Shape(); + + + // Fill history to be used by GetInPlace functionality + TopTools_IndexedMapOfShape aResIndices; + TopExp::MapShapes(aRes, aResIndices); + + Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); + + // history for all argument shapes + TDF_LabelSequence aLabelSeq; + aFunction->GetDependency(aLabelSeq); + Standard_Integer nbArg = aLabelSeq.Length(); + + for (Standard_Integer iarg = 1; iarg <= nbArg; iarg++) { + + TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg); + + Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel); + TopoDS_Shape anArgumentShape = anArgumentObject->GetValue(); + + TopTools_IndexedMapOfShape anArgumentIndices; + TopExp::MapShapes(anArgumentShape, anArgumentIndices); + Standard_Integer nbArgumentEntities = anArgumentIndices.Extent(); + + // Find corresponding label in history + TDF_Label anArgumentHistoryLabel = + aFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_True); + + for (Standard_Integer ie = 1; ie <= nbArgumentEntities; ie++) { + TopoDS_Shape anEntity = anArgumentIndices.FindKey(ie); + const TopTools_ListOfShape& aModified = aGluer.Modified(anEntity); + Standard_Integer nbModified = aModified.Extent(); + + if (nbModified > 0) { + TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(ie, Standard_True); + Handle(TDataStd_IntegerArray) anAttr = + TDataStd_IntegerArray::Set(aWhatHistoryLabel, 1, nbModified); + + TopTools_ListIteratorOfListOfShape itM (aModified); + for (int im = 1; itM.More(); itM.Next(), ++im) { + int id = aResIndices.FindIndex(itM.Value()); + anAttr->SetValue(im, id); + } + } + } + } + + return aRes; } + //======================================================================= //function : GlueFaces //purpose : //======================================================================= TopoDS_Shape GEOMImpl_GlueDriver::GlueFaces (const TopoDS_Shape& theShape, - const Standard_Real theTolerance) + const Standard_Real theTolerance, + const Standard_Boolean doKeepNonSolids) { - // prendre un premier shell dans la liste des shells - // initialiser un compshell avec ce shell - // tant qu'il reste des shells dans la liste - // chercher un shell qui a des faces en commun avec le compshell - // creer un BRepTools_Quilt - // recenser les faces communes issues du compshell, les ajouter au quilt - // recenser les faces restantes du shell a inclure, les ajouter au quilt - // recenser les edges en double, a remplacer - // pour chaque paire d'edge - // tester l'orientation relative des aretes - // bind dans le quilt de Eold.Forward et Enew.Forward (ou reverse) - // recuperer le nouveau shell - // l'incorporer dans le compshell - // appliquer BRepTools_SameParameter au compshell - // (rendre parametres 2D des edges identiques aux parametres 3D) - - TopoDS_Shape aShape; - - TopoDS_Compound C; - BRep_Builder bu; - bu.MakeCompound(C); // empty compound; - TopTools_ListOfShape shellList; - for (TopExp_Explorer exp (theShape, TopAbs_SHELL); exp.More(); exp.Next()) { - const TopoDS_Shell& S = TopoDS::Shell(exp.Current()); - shellList.Append(S); - } - TopTools_ListIteratorOfListOfShape its (shellList); - if (!its.More()) { - Standard_ConstructionError::Raise("Glue aborted : no shell in shape"); - } - - TopoDS_Shell S = TopoDS::Shell(its.Value()); - bu.Add(C, S); // add first shell to compound - shellList.Remove(its); - bool shellAdded = true; - bool bigTolerance = false; - - while ((shellList.Extent() > 0) && shellAdded) { - shellAdded = false; - its.Initialize(shellList); - for (; its.More(); its.Next()) { - S = TopoDS::Shell(its.Value()); - - // compare tolerance with shape's size - Bnd_Box aBox; - BRepBndLib::Add(S, aBox); - Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax; - aBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); - Standard_Real aTolerance = theTolerance; - if (aBox.IsXThin(100. * aTolerance)) - aTolerance = 0.01 * (Xmax - Xmin); - if (aBox.IsYThin(100. * aTolerance)) - aTolerance = 0.01 * (Ymax - Ymin); - if (aBox.IsZThin(100. * aTolerance)) - aTolerance = 0.01 * (Zmax - Zmin); - if (theTolerance > aTolerance) - bigTolerance = true; - - bool isConnected = false; - TopTools_ListOfShape newEdges; // common edges from new compound - TopTools_ListOfShape oldEdges; // common edges from face to add - TopoDS_Compound CFN; - TopoDS_Compound CFO; - bu.MakeCompound(CFN); // empty compound for new faces - bu.MakeCompound(CFO); // empty compound for old faces - - for (TopExp_Explorer exp (S, TopAbs_FACE); exp.More(); exp.Next()) { - // try to find corresponding face in new compound - TopoDS_Face F = TopoDS::Face(exp.Current()); - TopoDS_Face newFace = FindSameFace(C,F,aTolerance); - if (! newFace.IsNull()) - { - // face found - isConnected = true; - bu.Add(CFN, newFace); // common faces from new compound - for (TopExp_Explorer ee (F, TopAbs_EDGE); ee.More(); ee.Next()) { - // find edge pair - TopoDS_Edge Eold = TopoDS::Edge(ee.Current()); - TopoDS_Edge Enew = FindSameEdge(newFace, Eold, aTolerance); - if (Enew.IsNull()) { - Standard_ConstructionError::Raise("Glue aborted : no same edge in same face"); - } - oldEdges.Append(Eold); - newEdges.Append(Enew); - } - } else { - bu.Add(CFO, F); // not common faces from shell to add - } - } - if (isConnected) { - // some faces found - shellAdded = true; - BRepTools_Quilt glue; - glue.Add(CFN); - TopTools_ListIteratorOfListOfShape ito (oldEdges); - TopTools_ListIteratorOfListOfShape itn (newEdges); - for (; ito.More(); ito.Next()) { - // bind - glue.Bind(TopoDS::Edge(ito.Value()), TopoDS::Edge(itn.Value())); - itn.Next(); - } - glue.Add(CFO); - TopoDS_Compound newc = TopoDS::Compound(glue.Shells()); - for (TopExp_Explorer exs (newc, TopAbs_SHELL); exs.More(); exs.Next()) { - TopoDS_Shell NS = TopoDS::Shell(exs.Current()); - bu.Add(C, NS); - } - shellList.Remove(its); - // remove shell from list + Standard_Integer iErr, iWrn; + TopoDS_Shape aRes; + GEOMAlgo_Gluer aGluer; + + aGluer.SetShape(theShape); + aGluer.SetTolerance(theTolerance); + aGluer.SetCheckGeometry(Standard_True); + aGluer.SetKeepNonSolids(doKeepNonSolids); + + aGluer.Perform(); + + iErr = aGluer.ErrorStatus(); + if (iErr) { + switch (iErr) { + case 2: + Standard_Failure::Raise("No vertices found in source shape"); + break; + case 5: + Standard_Failure::Raise("Source shape is Null"); + break; + case 6: + Standard_Failure::Raise("Result shape is Null"); + break; + case 200: + Standard_Failure::Raise("Error occured during check of geometric coincidence"); + break; + default: + { + // description of all errors see in GEOMAlgo_Gluer.cxx + TCollection_AsciiString aMsg ("Error in GEOMAlgo_Gluer with code "); + aMsg += TCollection_AsciiString(iErr); + Standard_Failure::Raise(aMsg.ToCString()); break; } } + return aRes; } - if (shellList.Extent() > 0) { - TCollection_AsciiString aMsg - ("Some shapes can not be glued with others, because they are too far from them."); - if (bigTolerance) { - aMsg += "\n\nWarning: The tolerance is too big for some sub-shapes, 1% of sub-shape size is given instead."; + iWrn = aGluer.WarningStatus(); + if (iWrn) { + switch (iWrn) { + case 1: + MESSAGE("Some shapes can not be glued by faces"); + break; + default: + // description of all warnings see in GEOMAlgo_Gluer.cxx + MESSAGE("Warning in GEOMAlgo_Gluer with code " << iWrn); + break; } - Standard_ConstructionError::Raise(aMsg.ToCString()); } - TopExp_Explorer exp (C, TopAbs_SHELL); - Standard_Integer ish = 0; - TopoDS_Compound Res; - TopoDS_Solid Sol; - BRep_Builder B; - B.MakeCompound(Res); - - for (; exp.More(); exp.Next()) { - TopoDS_Shape Sh = exp.Current(); - B.MakeSolid(Sol); - B.Add(Sol,Sh); - BRepClass3d_SolidClassifier SC(Sol); - SC.PerformInfinitePoint(1.E-6); // cf. BRepFill_Confusion() - BRepFill_Evolved.cxx - if (SC.State() == TopAbs_IN) { - B.MakeSolid(Sol); - B.Add(Sol,Sh.Reversed()); - } - B.Add(Res,Sol); - ish++; + aRes = aGluer.Result(); + + return aRes; +} + + +//======================================================================= +//function : GlueFacesByList +//purpose : +//======================================================================= +TopoDS_Shape GEOMImpl_GlueDriver::GlueFacesByList (const TopoDS_Shape& theShape, + const Standard_Real theTolerance, + const Standard_Boolean doKeepNonSolids, + const TopTools_MapOfShape& aFaces) +{ + TopoDS_Shape aRes; + + GEOMAlgo_Gluer1 aGluer; + GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS; + GEOMAlgo_CoupleOfShapes aCS; + GEOMAlgo_ListOfCoupleOfShapes aLCS; + + aGluer.SetShape(theShape); + aGluer.SetTolerance(theTolerance); + aGluer.SetKeepNonSolids(doKeepNonSolids); + aGluer.Perform(); + Standard_Integer iErr = aGluer.ErrorStatus(); + if (iErr) return aRes; + + TopTools_ListOfShape listShape; + const GEOMAlgo_ListOfCoupleOfShapes& aLCSG = aGluer.GluedFaces(); + // Access to faces + aItCS.Initialize(aLCSG); + for (; aItCS.More(); aItCS.Next()) { + const GEOMAlgo_CoupleOfShapes& aCSG = aItCS.Value(); + const TopoDS_Shape& aF1 = aCSG.Shape1(); + const TopoDS_Shape& aF2 = aCSG.Shape2(); + if( aFaces.Contains(aF1) || aFaces.Contains(aF2) ) + continue; + aCS.SetShapes(aF1,aF2); + aLCS.Append(aCS); } - if (ish == 1) { - aShape = Sol; - } else { - aShape = Res; + + //cout<<"aLCS.Extent() = "<0) { + aGluer.SetFacesToUnglue(aLCS); + aGluer.UnglueFaces(); + iErr = aGluer.ErrorStatus(); + if (iErr) return aRes; } - BRepLib::SameParameter(aShape, 1.E-5, Standard_True); - return aShape; + aRes = aGluer.Result(); + + return aRes; } + //======================================================================= //function : Execute //purpose : @@ -321,18 +334,39 @@ Standard_Integer GEOMImpl_GlueDriver::Execute(TFunction_Logbook& log) const Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; + TCollection_AsciiString aWrn; - if (aType == GLUE_FACES) { - Handle(GEOM_Function) aRefBase = aCI.GetBase(); - TopoDS_Shape aShapeBase = aRefBase->GetValue(); - if (aShapeBase.IsNull()) { - Standard_NullObject::Raise("Shape for gluing is null"); - } + Handle(GEOM_Function) aRefBase = aCI.GetBase(); + TopoDS_Shape aShapeBase = aRefBase->GetValue(); + if (aShapeBase.IsNull()) { + Standard_NullObject::Raise("Shape for gluing is null"); + } + + Standard_Real tol3d = aCI.GetTolerance(); - Standard_Real tol3d = aCI.GetTolerance(); - aShape = GlueFaces(aShapeBase, tol3d); + Standard_Boolean aKeepNonSolids = aCI.GetKeepNonSolids(); - } else { + if (aType == GLUE_FACES) { + aShape = GlueFacesWithWarnings(aShapeBase, tol3d, aKeepNonSolids, aWrn); + } + else { // aType == GLUE_FACES_BY_LIST + Handle(TColStd_HSequenceOfTransient) SF = aCI.GetFaces(); + TopTools_MapOfShape aFaces; + int i=1; + for( ; i <= SF->Length(); i++) { + Handle(Standard_Transient) anItem = SF->Value(i); + if(anItem.IsNull()) + continue; + Handle(GEOM_Function) aRefSh = Handle(GEOM_Function)::DownCast(anItem); + if(aRefSh.IsNull()) + continue; + TopoDS_Shape aFace = aRefSh->GetValue(); + if(aFace.IsNull()) + continue; + if(!aFaces.Contains(aFace)) + aFaces.Add(aFace); + } + aShape = GlueFacesByList(aShapeBase, tol3d, aKeepNonSolids, aFaces); } if (aShape.IsNull()) return 0; @@ -341,10 +375,13 @@ Standard_Integer GEOMImpl_GlueDriver::Execute(TFunction_Logbook& log) const log.SetTouched(Label()); + if (!aWrn.IsEmpty()) { + Standard_Failure::Raise(aWrn.ToCString()); + } + return 1; } - //======================================================================= //function : GEOMImpl_GlueDriver_Type_ //purpose : @@ -362,10 +399,10 @@ Standard_EXPORT Handle_Standard_Type& GEOMImpl_GlueDriver_Type_() static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_GlueDriver", - sizeof(GEOMImpl_GlueDriver), - 1, - (Standard_Address)_Ancestors, - (Standard_Address)NULL); + sizeof(GEOMImpl_GlueDriver), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; }