From d0e77f8bfd7c1c39ba411f1e647712916f1e00e7 Mon Sep 17 00:00:00 2001 From: emv Date: Fri, 25 Mar 2016 08:58:57 +0300 Subject: [PATCH] Old implementation of the offset algorithm has been added alongside the new one (version from 28/10/2015). New key has been added to the offsetparameter command to choose the version of the algorithm (old version is default). --- src/BRepOffset/BRepOffset.cdl | 1 + src/BRepOffset/BRepOffset_MakeOffsetOld.cdl | 254 ++ src/BRepOffset/BRepOffset_MakeOffsetOld.cxx | 4557 +++++++++++++++++++ src/BRepTest/BRepTest_FeatureCommands.cxx | 77 +- 4 files changed, 4871 insertions(+), 18 deletions(-) create mode 100644 src/BRepOffset/BRepOffset_MakeOffsetOld.cdl create mode 100644 src/BRepOffset/BRepOffset_MakeOffsetOld.cxx diff --git a/src/BRepOffset/BRepOffset.cdl b/src/BRepOffset/BRepOffset.cdl index 2147e086ba..9d29348dcc 100644 --- a/src/BRepOffset/BRepOffset.cdl +++ b/src/BRepOffset/BRepOffset.cdl @@ -76,6 +76,7 @@ is end Error; class MakeOffset; + class MakeOffsetOld; --class Loop; diff --git a/src/BRepOffset/BRepOffset_MakeOffsetOld.cdl b/src/BRepOffset/BRepOffset_MakeOffsetOld.cdl new file mode 100644 index 0000000000..ba88546707 --- /dev/null +++ b/src/BRepOffset/BRepOffset_MakeOffsetOld.cdl @@ -0,0 +1,254 @@ +-- Created on: 1995-10-26 +-- Created by: Yves FRICAUD +-- Copyright (c) 1995-1999 Matra Datavision +-- Copyright (c) 1999-2014 OPEN CASCADE SAS +-- +-- This file is part of Open CASCADE Technology software library. +-- +-- This library is free software; you can redistribute it and/or modify it under +-- the terms of the GNU Lesser General Public License version 2.1 as published +-- by the Free Software Foundation, with special exception defined in the file +-- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +-- distribution for complete text of the license and disclaimer of any warranty. +-- +-- Alternatively, this file may be used under the terms of Open CASCADE +-- commercial license or contractual agreement. + +-- Modified by skv - Tue Mar 15 16:17:37 2005 +-- Add methods for supporting history. + +class MakeOffsetOld from BRepOffset + + ---Purpose: + +uses + Image from BRepAlgo, + AsDes from BRepAlgo, + Analyse from BRepOffset, + Mode from BRepOffset, + DataMapOfShapeOffset from BRepOffset, + Error from BRepOffset, + Inter3d from BRepOffset, + DataMapOfShapeReal from TopTools, + Shape from TopoDS, + JoinType from GeomAbs, + Face from TopoDS, + Edge from TopoDS, + MapOfShape from TopTools, + IndexedMapOfShape from TopTools, + ListOfShape from TopTools, + DataMapOfShapeShape from TopTools, + IndexedDataMapOfShapeListOfShape from TopTools, + MakeLoops from BRepOffset + +is + + Create; + + Create ( S : Shape from TopoDS; + Offset : Real from Standard; + Tol : Real from Standard; + Mode : Mode from BRepOffset = BRepOffset_Skin; + Intersection : Boolean from Standard = Standard_False; + SelfInter : Boolean from Standard = Standard_False; + Join : JoinType from GeomAbs = GeomAbs_Arc; + Thickening : Boolean from Standard = Standard_False; + RemoveIntEdges : Boolean from Standard = Standard_False; + RemoveInvalidFaces: Boolean from Standard = Standard_False) + returns MakeOffsetOld from BRepOffset; + +---Category: Initialization. + + Initialize (me : in out; + S : Shape from TopoDS; + Offset : Real from Standard; + Tol : Real from Standard; + Mode : Mode from BRepOffset = BRepOffset_Skin; + Intersection : Boolean from Standard = Standard_False; + SelfInter : Boolean from Standard = Standard_False; + Join : JoinType from GeomAbs = GeomAbs_Arc; + Thickening : Boolean from Standard = Standard_False; + RemoveIntEdges : Boolean from Standard = Standard_False; + RemoveInvalidFaces: Boolean from Standard = Standard_False) + is static; + + Clear (me : in out) + is static; + + AddFace (me : in out; F : Face from TopoDS) is static; + ---Purpose: Add Closing Faces, has to be in the initial + -- shape S. + + SetOffsetOnFace (me : in out; + F : Face from TopoDS; + Off : Real from Standard) is static; + ---Purpose: set the offset on the Face + + +---Category: Computation. + + MakeOffsetShape (me : in out) is static; + + MakeThickSolid (me : in out) is static; + +---Category: Querying. + + GetAnalyse(me) + ---C++: return const & + returns Analyse from BRepOffset + is static; + + IsDone (me) returns Boolean from Standard + is static; + + Shape (me) + ---C++: return const & + returns Shape from TopoDS + is static; + + Error (me) returns Error from BRepOffset; + ---Purpose: returns information if IsDone() = FALSE. + + + OffsetFacesFromShapes (me) + ---Purpose: Returns containing links between initials + -- shapes and offset faces. + ---C++: return const & + returns Image from BRepAlgo + is static; + +-- Modified by skv - Tue Mar 15 16:17:37 2005 Begin +-- Query offset join type. + + GetJoinType(me) + ---Purpose: Returns myJoin. + returns JoinType from GeomAbs + is static; + +-- Add methods for supporting history. + + OffsetEdgesFromShapes (me) + ---Purpose: Returns containing links between initials + -- shapes and offset edges. + ---C++: return const & + returns Image from BRepAlgo + is static; + +-- Modified by skv - Tue Mar 15 16:17:37 2005 End + + ClosingFaces (me) + ---Purpose: Returns the list of closing faces stores by AddFace + ---C++: return const & + returns IndexedMapOfShape from TopTools + is static; + +---Category: private methods + + BuildOffsetByArc ( me : in out ) + is static private; + + BuildOffsetByInter ( me : in out ) + is static private; + + BuildSplitsOfFaces (me:in out; + theLF : ListOfShape from TopTools; + theAsDes : AsDes from BRepAlgo; + theOrMap : out IndexedDataMapOfShapeListOfShape from TopTools; + theImage : out Image from BRepAlgo; + theLFail : out ListOfShape from TopTools; + bLimited : Boolean from Standard) + is static private; + ---Purpose: + -- Building splits of the offset faces by the section curves + -- between the neighboring faces. + + SelfInter (me : in out ; + Modif : in out MapOfShape from TopTools) + is static private; + + Intersection3D (me : in out; + Inter : in out Inter3d from BRepOffset) + is static private; + + Intersection2D ( me : in out ; + Modif : IndexedMapOfShape from TopTools; + NewEdges : IndexedMapOfShape from TopTools) + is static private; + + MakeLoops ( me : in out ; + Modif : in out IndexedMapOfShape from TopTools) + is static private; + + MakeLoopsOnContext ( me : in out ; + Modif : in out MapOfShape from TopTools) + is static private; + + MakeFaces ( me : in out ; + Modif : in out IndexedMapOfShape from TopTools) + is static private; + + MakeShells (me : in out ) + is static private; + + SelectShells (me : in out) + is static private; + + EncodeRegularity( me : in out) + is static private; + + MakeSolid (me : in out) + is static private; + + ToContext (me : in out; + MapSF : in out DataMapOfShapeOffset from BRepOffset) + is static private; + + UpdateFaceOffset (me: in out) + ---Purpose: Private method use to update the map face<->offset + is static private; + + CorrectConicalFaces (me: in out) + ---Purpose: Private method used to correct degenerated edges on conical faces + is static private; + + MakeMissingWalls (me: in out) + ---Purpose: Private method used to build walls for thickening the shell + is static private; + + RemoveInternalEdges (me: in out) + ---Purpose: Removes INTERNAL edges from the faces + is static private; + +fields + + myOffset : Real from Standard; + myTol : Real from Standard; + myShape : Shape from TopoDS; -- Initial + myMode : Mode from BRepOffset; + myInter : Boolean from Standard; + mySelfInter : Boolean from Standard; + myJoin : JoinType from GeomAbs; + myThickening : Boolean from Standard; + myRemoveIntEdges : Boolean from Standard; + myRemoveInvalidFaces : Boolean from Standard; + + myFaceOffset : DataMapOfShapeReal from TopTools; + + myFaces : IndexedMapOfShape from TopTools; + myAnalyse : Analyse from BRepOffset; + + myOffsetShape : Shape from TopoDS; -- Result + myInitOffsetFace : Image from BRepAlgo; + myInitOffsetEdge : Image from BRepAlgo; + myImageOffset : Image from BRepAlgo; + myWalls : ListOfShape from TopTools; + myAsDes : AsDes from BRepAlgo; + + myDone : Boolean from Standard; + myError : Error from BRepOffset; + + myMakeLoops : MakeLoops from BRepOffset; + + myIsPlanar : Boolean from Standard; + +end MakeOffsetOld; diff --git a/src/BRepOffset/BRepOffset_MakeOffsetOld.cxx b/src/BRepOffset/BRepOffset_MakeOffsetOld.cxx new file mode 100644 index 0000000000..586e55d3ff --- /dev/null +++ b/src/BRepOffset/BRepOffset_MakeOffsetOld.cxx @@ -0,0 +1,4557 @@ +// Created on: 1995-10-27 +// Created by: Yves FRICAUD +// Copyright (c) 1995-1999 Matra Datavision +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +// Modified by skv - Tue Mar 15 16:20:43 2005 +// Add methods for supporting history. + +// Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + + +// POP for NT +#include + +#ifdef DRAW + +#include +#endif +#ifdef OCCT_DEBUG +#include +//#define DEB_VERB + Standard_Boolean AffichInt2dOld = Standard_False; + Standard_Boolean AffichOffCOld = Standard_False; + Standard_Boolean ChronBuildOld = Standard_False; + Standard_Integer NbAEOld = 0; + Standard_Integer NbAFOld = 0; + Standard_Integer NVPOld = 0; + Standard_Integer NVMOld = 0; + Standard_Integer NVNOld = 0; + static OSD_Chronometer ClockOld; + char nameOl[100]; + + + + +//======================================================================= +//function : DEBVerticesControlOld +//purpose : +//======================================================================= + +static void DEBVerticesControlOld (const TopTools_IndexedMapOfShape& NewEdges, + Handle(BRepAlgo_AsDes) AsDes) +{ + TopTools_ListOfShape LVP; + TopTools_ListIteratorOfListOfShape it1LE ; + TopTools_ListIteratorOfListOfShape it2LE ; + + Standard_Integer i; + for (i = 1; i <= NewEdges.Extent(); i++) { + const TopoDS_Edge& NE = TopoDS::Edge(NewEdges(i)); + if (AsDes->HasDescendant(NE)) { + for (it1LE.Initialize(AsDes->Descendant(NE)); it1LE.More(); it1LE.Next()) { + if (AsDes->Ascendant(it1LE.Value()).Extent() < 3) { + LVP.Append(it1LE.Value()); + cout <<"Vertex on at least 3 edges."<Ascendant(it1LE.Value()).Extent() > 3) { + cout <<"Vertex on more than 3 edges."< i) { + TopoDS_Shape V2 = it2.Value(); + gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(V2)); + if (!V1.IsSame(V2)) { + Standard_Real dist = P1.Distance(P2); + if (dist < distmin) distmin = dist; + if (dist < TolConf) { + Standard_Real UV2; + TopoDS_Edge EWE2; + const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2); + TopTools_ListIteratorOfListOfShape itAsDes; + for (itAsDes.Initialize(EdgeWithV2); itAsDes.More(); itAsDes.Next()) { + EWE2 = TopoDS::Edge(itAsDes.Value()); + TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_INTERNAL); + UV2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2); + aLocalShape = V1.Oriented(TopAbs_INTERNAL) ; + B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol); +// UV2 = +// BRep_Tool::Parameter(TopoDS::Vertex(),EWE2); +// B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)), +// UV2,EWE2,Tol); + } + AsDes->Replace(V2,V1); + } + } + } + j++; + } + i++; + cout <<" distmin between VP : "<Clear(); + myDone = Standard_False; +} + +//======================================================================= +//function : AddFace +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::AddFace(const TopoDS_Face& F) { + myFaces.Add(F); + //------------- + // MAJ SD. + //------------- + myInitOffsetFace.SetRoot (F) ; + myInitOffsetFace.Bind (F,F); + myImageOffset.SetRoot (F) ; +} + +//======================================================================= +//function : SetOffsetOnFace +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::SetOffsetOnFace(const TopoDS_Face& F, + const Standard_Real Off) +{ + if ( myFaceOffset.IsBound(F)) myFaceOffset.UnBind(F); + myFaceOffset.Bind(F,Off); +} + +//======================================================================= +//function : MakeOffsetShape +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::MakeOffsetShape() +{ + myDone = Standard_False; + // + // check if shape consists of only planar faces + myIsPlanar = IsPlanar(myShape); + //------------------------------------------ + // Construction of myShape without caps. + //------------------------------------------ + RemoveCorks (myShape,myFaces); + + if (! IsConnectedShell(myShape)) + Standard_ConstructionError::Raise("BRepOffset_MakeOffsetOld : Incorrect set of faces to remove, the remaining shell is not connected"); + + if (Abs(myOffset) < myTol) return; + + TopAbs_State Side = TopAbs_IN; + if (myOffset < 0.) Side = TopAbs_OUT; + // ------------ + // Preanalyse. + // ------------ + EvalMax(myShape,myTol); + if (myTol > Abs(myOffset*0.5)) { + Standard_ConstructionError::Raise("BRepOffset_MakeOffsetOld : Tol > Offset"); + } + Standard_Real TolAngle = 4*ASin(myTol/Abs(myOffset*0.5)); + myAnalyse.Perform(myShape,TolAngle); + //--------------------------------------------------- + // Construction of Offset from preanalysis. + //--------------------------------------------------- + //---------------------------- + // MaJ of SD Face - Offset + //---------------------------- + UpdateFaceOffset(); + + if (myJoin == GeomAbs_Arc) + BuildOffsetByArc(); + else if (myJoin == GeomAbs_Intersection) + BuildOffsetByInter(); + //----------------- + // Auto unwinding. + //----------------- + // if (mySelfInter) SelfInter(Modif); + //----------------- + // Intersection 3d . + //----------------- + + + //if (!Intersection3D()) { + BRepOffset_Inter3d Inter(myAsDes,Side,myTol); + Intersection3D (Inter); + //----------------- + // Intersection2D + //----------------- + TopTools_IndexedMapOfShape& Modif = Inter.TouchedFaces(); + TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges(); + + if (!Modif.IsEmpty()) Intersection2D (Modif,NewEdges); + //------------------------------------------------------- + // Unwinding 2D and reconstruction of modified faces + //---------------------------------------------------- + MakeLoops (Modif); + //----------------------------------------------------- + // Reconstruction of non modified faces sharing + // reconstructed edges + //------------------------------------------------------ + if (!Modif.IsEmpty()) MakeFaces (Modif); + //} + + + // + if (myThickening) + MakeMissingWalls(); + + //------------------------- + // Construction of shells. + //------------------------- + MakeShells (); + //-------------- + // Unwinding 3D. + //-------------- + SelectShells (); + //---------------------------------- + // Remove INTERNAL edges if necessasry + //---------------------------------- + if (myRemoveIntEdges) { + RemoveInternalEdges(); + } + //---------------------------------- + // Coding of regularities. + //---------------------------------- + EncodeRegularity(); + //---------------------- + // Creation of solids. + //---------------------- + MakeSolid (); + + //----------------------------- + // MAJ Tolerance edge and Vertex + // ---------------------------- + if (!myOffsetShape.IsNull()) { + UpdateTolerance (myOffsetShape,myFaces); + BRepLib::UpdateTolerances( myOffsetShape ); + } + + CorrectConicalFaces(); + + myDone = Standard_True; +} + +//======================================================================= +//function : MakeThickSolid +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::MakeThickSolid() +{ + //-------------------------------------------------------------- + // Construction of shell parallel to shell (initial without cap). + //-------------------------------------------------------------- + MakeOffsetShape (); + + //-------------------------------------------------------------------- + // Construction of a solid with the initial shell, parallel shell + // limited by caps. + //-------------------------------------------------------------------- + if (!myFaces.IsEmpty()) { + TopoDS_Solid Res; + TopExp_Explorer exp; + BRep_Builder B; + Standard_Integer NbF = myFaces.Extent(); + + B.MakeSolid(Res); + + BRepTools_Quilt Glue; + for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) { + NbF++; + Glue.Add (exp.Current()); + } + Standard_Boolean YaResult = 0; + if (!myOffsetShape.IsNull()) + { + for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next()) + { + YaResult = 1; + Glue.Add (exp.Current().Reversed()); + } +#ifdef OCCT_DEBUG + if(YaResult == 0) + { + cout << "OffsetShape does not contain a FACES." << endl; + } +#endif + } +#ifdef OCCT_DEBUG + else + { + cout << "OffsetShape is null!" << endl; + } +#endif + + if (YaResult == 0) + { + myDone = Standard_False; + return; + } + + myOffsetShape = Glue.Shells(); + for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) { + B.Add(Res,exp.Current()); + } + Res.Closed(Standard_True); + myOffsetShape = Res; + + // Test of Validity of the result of thick Solid + // more face than the initial solid. + + Standard_Integer NbOF = 0; + for (exp.Init(myOffsetShape,TopAbs_FACE);exp.More(); exp.Next()) { + NbOF++; + } + if (NbOF <= NbF) { + myDone = Standard_False; + return; + } + } + + if (myOffset > 0 ) myOffsetShape.Reverse(); + + myDone = Standard_True; +} + +//======================================================================= +//function : IsDone +//purpose : +//======================================================================= +Standard_Boolean BRepOffset_MakeOffsetOld::IsDone() const +{ + return myDone; +} + +//======================================================================= +//function : Error +//purpose : +//======================================================================= +BRepOffset_Error BRepOffset_MakeOffsetOld::Error() const +{ + return myError; +} + +//======================================================================= +//function : Shape +//purpose : +//======================================================================= +const TopoDS_Shape& BRepOffset_MakeOffsetOld::Shape() const +{ + return myOffsetShape; +} + +//======================================================================= +//function : BuildOffsetByInter +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::BuildOffsetByInter() +{ +#ifdef OCCT_DEBUG + if ( ChronBuildOld) { + cout << " CONSTRUCTION OF OFFSETS :" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + + BRepOffset_DataMapOfShapeOffset MapSF; + TopTools_MapOfShape Done; + Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False; + //-------------------------------------------------------- + // Construction of faces parallel to initial faces + //-------------------------------------------------------- + TopExp_Explorer Exp; + TopTools_ListOfShape LF; + TopTools_ListIteratorOfListOfShape itLF; + + BRepLib::SortFaces(myShape,LF); + + TopTools_DataMapOfShapeShape ShapeTgt; + for (itLF.Initialize(LF); itLF.More(); itLF.Next()) { + const TopoDS_Face& F = TopoDS::Face(itLF.Value()); + Standard_Real CurOffset = myOffset; + if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F); + BRepOffset_Offset OF(F,CurOffset,ShapeTgt,OffsetOutside,myJoin); + TopTools_ListOfShape Let; + myAnalyse.Edges(F,BRepOffset_Tangent,Let); + TopTools_ListIteratorOfListOfShape itl(Let); + + for ( ; itl.More(); itl.Next()) { + const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value()); + if ( !ShapeTgt.IsBound(Cur)) { + TopoDS_Shape aLocalShape = OF.Generated(Cur); + const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape); +// const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur)); + ShapeTgt.Bind(Cur,OF.Generated(Cur)); + TopoDS_Vertex V1,V2,OV1,OV2; + TopExp::Vertices (Cur,V1,V2); + TopExp::Vertices (OTE,OV1,OV2); + TopTools_ListOfShape LE; + if (!ShapeTgt.IsBound(V1)) { + myAnalyse.Edges(V1,BRepOffset_Tangent,LE); + const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1); + if (LE.Extent() == LA.Extent()) + ShapeTgt.Bind(V1,OV1); + } + if (!ShapeTgt.IsBound(V2)) { + LE.Clear(); + myAnalyse.Edges(V2,BRepOffset_Tangent,LE); + const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2); + if (LE.Extent() == LA.Extent()) + ShapeTgt.Bind(V2,OV2); + } + } + } + MapSF.Bind(F,OF); + } + //-------------------------------------------------------------------- + // MES : Map of OffsetShape -> Extended Shapes. + // Build : Map of Initial SS -> OffsetShape build by Inter. + // can be an edge or a compound of edges + //--------------------------------------------------------------------- + TopTools_DataMapOfShapeShape MES; + TopTools_DataMapOfShapeShape Build; + TopTools_ListOfShape Failed; + TopAbs_State Side = TopAbs_IN; + Handle(BRepAlgo_AsDes) AsDes = new BRepAlgo_AsDes(); + + //------------------------------------------------------------------- + // Extension of faces and calculation of new edges of intersection. + //------------------------------------------------------------------- + Standard_Boolean ExtentContext = 0; + if (myOffset > 0) ExtentContext = 1; + + BRepOffset_Inter3d Inter3 (AsDes,Side,myTol); + // Intersection between parallel faces + Inter3.ConnexIntByInt(myShape,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar); + // Intersection with caps. + Inter3.ContextIntByInt(myFaces,ExtentContext,MapSF,myAnalyse,MES,Build,Failed,myIsPlanar); + + + //--------------------------------------------------------------------------------- + // Extension of neighbor edges of new edges and intersection between neighbors. + //-------------------------------------------------------------------------------- + Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes(); + for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) { + const TopoDS_Face& FI = TopoDS::Face(Exp.Current()); + Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(FI); + BRepOffset_Inter2d::ConnexIntByInt (FI, MapSF(FI), MES, Build, + AsDes, AsDes2d, myOffset, aCurrFaceTol); + } + //----------------------------------------------------------- + // Great restriction of new edges and update of AsDes. + //------------------------------------------ ---------------- + TopTools_IndexedMapOfShape NewEdges; + TopExp_Explorer Exp2,ExpC; + TopoDS_Shape NE; + TopoDS_Edge TNE; + TopoDS_Face NF; + TopTools_IndexedDataMapOfShapeListOfShape anOrigins; + + for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) { + const TopoDS_Face& FI = TopoDS::Face(Exp.Current()); + NF = MapSF(FI).Face(); + if (MES.IsBound(NF)) { + NF = TopoDS::Face(MES(NF)); + } + // + TopTools_MapOfShape View; + TopTools_IndexedMapOfShape VEmap; + Standard_Integer i, aNb; + // + TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE , VEmap); + TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap); + // + aNb = VEmap.Extent(); + for (i = 1; i <= aNb; ++i) { + const TopoDS_Shape& aS = VEmap(i); + if (!View.Add(aS)) { + continue; + } + // + if (Build.IsBound(aS)) { + NE = Build(aS); + if (NE.ShapeType() == TopAbs_EDGE) { + if (anOrigins.Contains(NE)) { + anOrigins.ChangeFromKey(NE).Append(aS); + } + else { + TopTools_ListOfShape aLSx; + aLSx.Append(aS); + anOrigins.Add(NE, aLSx); + } + // + if (NewEdges.Add(NE)) { + TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes); + } + } + else { + //------------------------------------------------------------ + // The Intersections are on several edges. + // The pieces without intersections with neighbors + // are removed from AsDes. + //------------------------------------------------------------ + for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) { + TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current()); + if (NewEdges.Add(NEC)) { + NEC.Free(Standard_True); + if (anOrigins.Contains(NEC)) { + anOrigins.ChangeFromKey(NEC).Append(aS); + } + else { + TopTools_ListOfShape aLSx; + aLSx.Append(aS); + anOrigins.Add(NEC, aLSx); + } + // + if (!AsDes2d->Descendant(NEC).IsEmpty()) { + TrimEdge (NEC,AsDes2d,AsDes); + } + else { + if (AsDes->HasAscendant(NEC)) { + AsDes->Remove(NEC); + } + } + } + } + } + } + else { + if (aS.ShapeType() != TopAbs_EDGE) { + continue; + } + // + NE = MapSF(FI).Generated(aS); + //// modified by jgv, 19.12.03 for OCC4455 //// + NE.Orientation(aS.Orientation()); + if (anOrigins.Contains(NE)) { + anOrigins.ChangeFromKey(NE).Append(aS); + } + else { + TopTools_ListOfShape aLSx; + aLSx.Append(aS); + anOrigins.Add(NE, aLSx); + } + // + if (MES.IsBound(NE)) { + NE = MES(NE); + NE.Orientation(aS.Orientation()); + if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} + } + AsDes->Add(NF,NE); + } + } + } + + //--------------------------------- + // Intersection 2D on // + //--------------------------------- + TopTools_ListOfShape LFE; + BRepAlgo_Image IMOE; + for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) { + const TopoDS_Shape& FI = Exp.Current(); + const TopoDS_Shape& OFI = MapSF(FI).Face(); + if (MES.IsBound(OFI)) { + const TopoDS_Face& NF = TopoDS::Face(MES(OFI)); + LFE.Append(NF); + IMOE.SetRoot(NF); + // + if (anOrigins.Contains(NF)) { + anOrigins.ChangeFromKey(NF).Append(FI); + } + else { + TopTools_ListOfShape aLSx; + aLSx.Append(FI); + anOrigins.Add(NF, aLSx); + } + } + } + + TopTools_ListIteratorOfListOfShape itLFE(LFE); + for (; itLFE.More(); itLFE.Next()) { + const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value()); + Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF); + BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol); + } + //---------------------------------------------- + // Intersections 2d on caps. + //---------------------------------------------- + Standard_Integer i; + for (i = 1; i <= myFaces.Extent(); i++) { + const TopoDS_Face& Cork = TopoDS::Face(myFaces(i)); + Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork); + BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol); + } + + //------------------------------- + // Unwinding of extended Faces. + //------------------------------- + // + if ((myJoin == GeomAbs_Intersection) && myInter) { + TopTools_ListOfShape aLFailed; + BuildSplitsOfFaces(LFE, AsDes, anOrigins, IMOE, aLFailed, Standard_False); + if (aLFailed.Extent()) { + myMakeLoops.Build(aLFailed, AsDes, IMOE); + } + } + else { + myMakeLoops.Build(LFE, AsDes, IMOE); + } + // +#ifdef OCCT_DEBUG + TopTools_IndexedMapOfShape COES; +#endif + //--------------------------- + // MAJ SD. for faces // + //--------------------------- + for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) { + const TopoDS_Shape& FI = Exp.Current(); + myInitOffsetFace.SetRoot(FI); + TopoDS_Face OF = MapSF(FI).Face(); + if (MES.IsBound(OF)) { + OF = TopoDS::Face(MES(OF)); + if (IMOE.HasImage(OF)) { + const TopTools_ListOfShape& LOFE = IMOE.Image(OF); + myInitOffsetFace.Bind(FI,LOFE); + for (itLF.Initialize(LOFE); itLF.More(); itLF.Next()) { + const TopoDS_Shape& OFE = itLF.Value(); + myImageOffset.SetRoot(OFE); +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AF_%d",NbAFOld++); + DBRep::Set(nameOld,OFE); + } +#endif + TopTools_MapOfShape View; + for (Exp2.Init(OFE.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + Exp2.More(); Exp2.Next()) { + const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current()); + + myAsDes->Add (OFE,COE); +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AE_%d",NbAEOld++); + DBRep::Set(nameOld,COE); + COES.Add(COE); + } +#endif + if (View.Add(COE)){ + if (!myAsDes->HasDescendant(COE)) { + TopoDS_Vertex CV1,CV2; + TopExp::Vertices(COE,CV1,CV2); + if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD)); + if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED)); + } + } + } + } + } + else { + /*myInitOffsetFace.Bind(FI,OF); + myImageOffset.SetRoot(OF); +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AF_%d",NbAFOld++); + DBRep::Set(nameOld,OF); + } +#endif + const TopTools_ListOfShape& LE = AsDes->Descendant(OF); + for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) { + const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value()); + if (IMOE.HasImage(OE)) { + const TopTools_ListOfShape& LOE = IMOE.Image(OE); + TopTools_ListIteratorOfListOfShape itLOE(LOE); + for (; itLOE.More(); itLOE.Next()) { + TopoDS_Shape aLocalShape = itLOE.Value().Oriented(OE.Orientation()); + const TopoDS_Edge& COE = TopoDS::Edge(aLocalShape); +// const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value().Oriented(OE.Orientation())); + myAsDes->Add(OF,COE); +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AE_%d",NbAEOld++); + DBRep::Set(nameOld,COE); + COES.Add(COE); + } +#endif + + if (!myAsDes->HasDescendant(COE)) { + TopoDS_Vertex CV1,CV2; + TopExp::Vertices(COE,CV1,CV2); + if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD)); + if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED)); + } + } + } + else { + myAsDes->Add(OF,OE); +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AE_%d",NbAEOld++); + DBRep::Set(nameOld,OE); + COES.Add(OE); + } +#endif + + const TopTools_ListOfShape& LV = AsDes->Descendant(OE); + myAsDes->Add(OE,LV); + } + }*/ + } + } + else { + myInitOffsetFace.Bind(FI,OF); + myImageOffset.SetRoot(OF); + TopTools_MapOfShape View; + for (Exp2.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + Exp2.More(); Exp2.Next()) { + + const TopoDS_Edge& COE = TopoDS::Edge(Exp2.Current()); + myAsDes->Add (OF,COE); +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AE_%d",NbAEOld++); + DBRep::Set(nameOld,COE); + COES.Add(COE); + } +#endif + + if (View.Add(Exp2.Current())) { + if (!myAsDes->HasDescendant(COE)) { + TopoDS_Vertex CV1,CV2; + TopExp::Vertices(COE,CV1,CV2); + if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD)); + if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED)); + } + } + } + } + } + // Modified by skv - Tue Mar 15 16:20:43 2005 + // Add methods for supporting history. + TopTools_MapOfShape aMapEdges; + + for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) { + const TopoDS_Shape& aFaceRef = Exp.Current(); + + Exp2.Init(aFaceRef.Oriented(TopAbs_FORWARD), TopAbs_EDGE); + + for (; Exp2.More(); Exp2.Next()) { + const TopoDS_Shape& anEdgeRef = Exp2.Current(); + + if (aMapEdges.Add(anEdgeRef)) { + myInitOffsetEdge.SetRoot(anEdgeRef); + if (Build.IsBound(anEdgeRef)) { + TopoDS_Shape aNewShape = Build(anEdgeRef); + + if (aNewShape.ShapeType() == TopAbs_EDGE) { + if (IMOE.HasImage(aNewShape)) { + const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewShape); + + myInitOffsetEdge.Bind (anEdgeRef, aListNewE); + } else + myInitOffsetEdge.Bind (anEdgeRef, aNewShape); + } else { // aNewShape != TopAbs_EDGE + TopTools_ListOfShape aListNewEdge; + + for (ExpC.Init(aNewShape, TopAbs_EDGE); ExpC.More(); ExpC.Next()) { + const TopoDS_Shape &aResEdge = ExpC.Current(); + + if (IMOE.HasImage(aResEdge)) { + const TopTools_ListOfShape& aListNewE = IMOE.Image(aResEdge); + TopTools_ListIteratorOfListOfShape aNewEIter(aListNewE); + + for (; aNewEIter.More(); aNewEIter.Next()) + aListNewEdge.Append(aNewEIter.Value()); + } else + aListNewEdge.Append(aResEdge); + } + + myInitOffsetEdge.Bind (anEdgeRef, aListNewEdge); + } + } + else { // Free boundary. + TopoDS_Shape aNewEdge = MapSF(aFaceRef).Generated(anEdgeRef); + + if (MES.IsBound(aNewEdge)) + aNewEdge = MES(aNewEdge); + + if (IMOE.HasImage(aNewEdge)) { + const TopTools_ListOfShape& aListNewE = IMOE.Image(aNewEdge); + + myInitOffsetEdge.Bind (anEdgeRef, aListNewE); + } else + myInitOffsetEdge.Bind (anEdgeRef, aNewEdge); + } + } + } + } +// Modified by skv - Tue Mar 15 16:20:43 2005 + + //--------------------------- + // MAJ SD. for caps + //--------------------------- + //TopTools_MapOfShape View; + for (i = 1; i <= myFaces.Extent(); i++) { + const TopoDS_Shape& Cork = myFaces(i); + const TopTools_ListOfShape& LE = AsDes->Descendant(Cork); + for (itLF.Initialize(LE) ; itLF.More(); itLF.Next()) { + const TopoDS_Edge& OE = TopoDS::Edge(itLF.Value()); + if (IMOE.HasImage(OE)) { + const TopTools_ListOfShape& LOE = IMOE.Image(OE); + TopTools_ListIteratorOfListOfShape itLOE(LOE); + for (; itLOE.More(); itLOE.Next()) { + const TopoDS_Edge& COE = TopoDS::Edge(itLOE.Value()); + myAsDes->Add(Cork,COE.Oriented(OE.Orientation())) ; +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AE_%d",NbAEOld++); + DBRep::Set(nameOld,COE); + COES.Add(COE); + } +#endif + + if (!myAsDes->HasDescendant(COE)) { + TopoDS_Vertex CV1,CV2; + TopExp::Vertices(COE,CV1,CV2); + if (!CV1.IsNull()) myAsDes->Add(COE,CV1.Oriented(TopAbs_FORWARD)); + if (!CV2.IsNull()) myAsDes->Add(COE,CV2.Oriented(TopAbs_REVERSED)); + } + } + } + else { + myAsDes->Add(Cork,OE); + if (AsDes->HasDescendant(OE)) { + myAsDes->Add(OE,AsDes->Descendant(OE)); + } +#ifdef DRAW + if (AffichInt2dOld) { + sprintf(nameOld,"AE_%d",NbAEOld++); + DBRep::Set(nameOld,OE); + COES.Add(OE); + } +#endif + } + } + } + +#ifdef OCCT_DEBUG + DEBVerticesControlOld (COES,myAsDes); + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : BuildSplitsOfFaces +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::BuildSplitsOfFaces + (const TopTools_ListOfShape& theLF, + const Handle(BRepAlgo_AsDes)& theAsDes, + TopTools_IndexedDataMapOfShapeListOfShape& theOrigins, + BRepAlgo_Image& theImage, + TopTools_ListOfShape& theLFailed, + const Standard_Boolean bLimited) +{ + BOPCol_ListOfShape aLS; + BOPCol_ListIteratorOfListOfShape aIt; + TopTools_ListIteratorOfListOfShape aItLF, aItLE, aItLE1; + TopTools_DataMapOfShapeListOfShape anEImages; + BRep_Builder aBB; + TopoDS_Compound aFaces; + // + aBB.MakeCompound(aFaces); + // + // firstly it is necessary to fuse all the edges + Handle(IntTools_Context) aCtx = new IntTools_Context(); + // + aItLF.Initialize(theLF); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Shape& aF = aItLF.Value(); + // + const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF); + aItLE.Initialize(aLE); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value(); + if (BRep_Tool::Degenerated(aE)) { + continue; + } + // + if (IsMicroEdge(aE, aCtx)) { + continue; + } + // + aLS.Append(aE); + } + } + // + if (aLS.Extent() > 1) { + BOPAlgo_Builder aGFE; + // + aGFE.SetArguments(aLS); + aGFE.Perform(); + if (aGFE.ErrorStatus() == 0) { + // fill map with edges images + aIt.Initialize(aLS); + for (; aIt.More(); aIt.Next()) { + const TopoDS_Shape& aE = aIt.Value(); + // + const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE); + if (aLEIm.Extent()) { + anEImages.Bind(aE, aLEIm); + } + } + // + UpdateOrigins(theOrigins, aGFE); + } + } + // + // now we can split the faces + aItLF.Initialize(theLF); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value(); + // + // the offset face + aLS.Clear(); + aLS.Append(aF.Oriented(TopAbs_FORWARD)); + // + Standard_Integer iCountE = 0; + TopTools_MapOfShape aMFE; + TopExp_Explorer aExp(aF, TopAbs_EDGE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Shape& aE = aExp.Current(); + if (anEImages.IsBound(aE)) { + const TopTools_ListOfShape& aLEIm = anEImages.Find(aE); + aItLE.Initialize(aLEIm); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aEIm = aItLE.Value(); + aMFE.Add(aEIm); + } + } + else { + aMFE.Add(aE); + } + } + // + // the edges by which the offset face should be split + const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF); + aItLE.Initialize(aLE); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value(); + if (BRep_Tool::Degenerated(aE)) { + continue; + } + // + if (anEImages.IsBound(aE)) { + const TopTools_ListOfShape& aLEIm = anEImages.Find(aE); + aItLE1.Initialize(aLEIm); + for (; aItLE1.More(); aItLE1.Next()) { + const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aItLE1.Value(); + // check for micro edge + if (IsMicroEdge(aEIm, aCtx)) { + continue; + } + // + aLS.Append(aEIm); + if (!aMFE.Contains(aEIm)) { + ++iCountE; + } + } + } + else { + if (IsMicroEdge(aE, aCtx)) { + continue; + } + aLS.Append(aE); + if (!aMFE.Contains(aE)) { + ++iCountE; + } + } + } + // + TopTools_ListOfShape aLFImages; + // + // split the face by the edges + if (!iCountE) { + if (bLimited) { + aLFImages.Append(aF); + theImage.Bind(aF, aLFImages); + aBB.Add(aFaces, aF); + } + continue; + } + // + BOPAlgo_Builder aGF; + // + aGF.SetArguments(aLS); + aGF.Perform(); + if (aGF.ErrorStatus()) { + theLFailed.Append(aF); + continue; + } + // + // splits of the offset shape + aLFImages = aGF.Modified(aF); + if (aLFImages.IsEmpty()) { + theLFailed.Append(aF); + continue; + } + // + TopTools_MapOfShape aME; + // collect images of Edges + aItLE.Initialize(aLE); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aE = aItLE.Value(); + if (anEImages.IsBound(aE)) { + TopTools_MapOfShape aMFence; + TopTools_ListOfShape aLEImNew; + Standard_Boolean bModif = Standard_False; + // + TopTools_ListOfShape& aLEIm = anEImages.ChangeFind(aE); + aItLE1.Initialize(aLEIm); + for (; aItLE1.More(); aItLE1.Next()) { + const TopoDS_Shape& aEIm = aItLE1.Value(); + const TopTools_ListOfShape& aLEImIm = aGF.Modified(aEIm); + if (aLEImIm.Extent()) { + bModif = Standard_True; + TopTools_ListIteratorOfListOfShape aItLEIm(aLEImIm); + for (; aItLEIm.More(); aItLEIm.Next()) { + const TopoDS_Shape& aEImIm = aItLEIm.Value(); + if (aMFence.Add(aEImIm)) { + aLEImNew.Append(aEImIm); + aME.Add(aEImIm); + } + } + } + else { + aLEImNew.Append(aEIm); + aME.Add(aEIm); + } + } + // + if (bModif) { + aLEIm.Assign(aLEImNew); + } + } + else { + const TopTools_ListOfShape& aLEIm = aGF.Modified(aE); + if (aLEIm.Extent()) { + anEImages.Bind(aE, aLEIm); + TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm); + for (; aItLEIm.More(); aItLEIm.Next()) { + const TopoDS_Shape& aEIm = aItLEIm.Value(); + aME.Add(aEIm); + } + } + else { + aME.Add(aE); + } + } + } + // + if (!bLimited) { + // + // to overcome the often errors in trimming edges it is + // better to remove first the faces containing the boundaries + // of the extended surfaces; + Standard_Boolean bKeep; + aItLE.Initialize(aLFImages); + for (; aItLE.More();) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLE.Value(); + // + aExp.Init(aFIm, TopAbs_EDGE); + for (bKeep = Standard_True; aExp.More() && bKeep; aExp.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current(); + // + if (BRep_Tool::Degenerated(aE)) { + continue; + } + // + bKeep = aME.Contains(aE); + } + // + if (bKeep) { + aItLE.Next(); + } + else { + aLFImages.Remove(aItLE); + } + } + // + UpdateOrigins(theOrigins, aGF); + // + if (aLFImages.Extent() >= 1) { + TopTools_ListOfShape aLFKeep; + // + // check offset faces on the coincidence of the + // bi-normal directions with the original faces + CheckBiNormals(aLFImages, aF, theOrigins, aLFKeep, myRemoveInvalidFaces); + // + // limit the face + if (aLFImages.Extent() > 1) { + TopTools_ListOfShape aLFTmp = aLFImages; + aLFImages.Clear(); + // + SortFaces(aLFTmp, aLFImages, Standard_True); + } + // + if (aLFKeep.Extent()) { + TopTools_MapOfShape aMFence; + aItLE.Initialize(aLFImages); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aFIm = aItLE.Value(); + aMFence.Add(aFIm); + } + // + aItLE.Initialize(aLFKeep); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aFIm = aItLE.Value(); + if (aMFence.Add(aFIm)) { + aLFImages.Append(aFIm); + } + } + } + } + } + // + // Fill history for faces + if (aLFImages.Extent()) { + theImage.Bind(aF, aLFImages); + } + else { + BRepAdaptor_Surface aBAS(aF, Standard_False); + if (aBAS.GetType() != GeomAbs_Plane) { + theLFailed.Append(aF); + } + } + // + aItLE.Initialize(aLFImages); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aFIm = aItLE.Value(); + aBB.Add(aFaces, aFIm); + } + } + // + // fill history for edges + TopTools_IndexedMapOfShape aMFE; + TopExp::MapShapes(aFaces, TopAbs_EDGE, aMFE); + // + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(anEImages); + for (; aItEIm.More(); aItEIm.Next()) { + const TopoDS_Shape& aE = aItEIm.Key(); + const TopTools_ListOfShape& aLEIm = aItEIm.Value(); + // + Standard_Boolean bHasImage = theImage.HasImage(aE); + aItLE.Initialize(aLEIm); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Shape& aEIm = aItLE.Value(); + if (aMFE.Contains(aEIm)) { + if (bHasImage) { + theImage.Add(aE, aEIm); + } + else { + theImage.Bind(aE, aEIm); + bHasImage = Standard_True; + } + } + } + } +} + +//======================================================================= +//function : BuildOffsetByArc +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::BuildOffsetByArc() +{ +#ifdef OCCT_DEBUG + if ( ChronBuildOld) { + cout << " CONSTRUCTION OF OFFSETS :" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + + BRepOffset_DataMapOfShapeOffset MapSF; + TopTools_MapOfShape Done; + Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False; + //-------------------------------------------------------- + // Construction of faces parallel to initial faces + //-------------------------------------------------------- + TopExp_Explorer Exp; + TopTools_ListOfShape LF; + TopTools_ListIteratorOfListOfShape itLF; + + BRepLib::SortFaces(myShape,LF); + + TopTools_DataMapOfShapeShape EdgeTgt; + for (itLF.Initialize(LF); itLF.More(); itLF.Next()) { + const TopoDS_Face& F = TopoDS::Face(itLF.Value()); + Standard_Real CurOffset = myOffset; + if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F); + BRepOffset_Offset OF(F,CurOffset,EdgeTgt,OffsetOutside,myJoin); + TopTools_ListOfShape Let; + myAnalyse.Edges(F,BRepOffset_Tangent,Let); + TopTools_ListIteratorOfListOfShape itl(Let); + + for ( ; itl.More(); itl.Next()) { + const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value()); + if ( !EdgeTgt.IsBound(Cur)) { + TopoDS_Shape aLocalShape = OF.Generated(Cur); + const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape); +// const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur)); + EdgeTgt.Bind(Cur,OF.Generated(Cur)); + TopoDS_Vertex V1,V2,OV1,OV2; + TopExp::Vertices (Cur,V1,V2); + TopExp::Vertices (OTE,OV1,OV2); + TopTools_ListOfShape LE; + if (!EdgeTgt.IsBound(V1)) { + myAnalyse.Edges(V1,BRepOffset_Tangent,LE); + const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1); + if (LE.Extent() == LA.Extent()) + EdgeTgt.Bind(V1,OV1); + } + if (!EdgeTgt.IsBound(V2)) { + LE.Clear(); + myAnalyse.Edges(V2,BRepOffset_Tangent,LE); + const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2); + if (LE.Extent() == LA.Extent()) + EdgeTgt.Bind(V2,OV2); + } + } + } + MapSF.Bind(F,OF); + } + //-------------------------------------------------------- + // Construction of tubes on edge. + //-------------------------------------------------------- + BRepOffset_Type OT = BRepOffset_Convex; + if (myOffset < 0.) OT = BRepOffset_Concave; + + for (Exp.Init(myShape,TopAbs_EDGE); Exp.More(); Exp.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(Exp.Current()); + if (Done.Add(E)) { + const TopTools_ListOfShape& Anc = myAnalyse.Ancestors(E); + if (Anc.Extent() == 2) { + const BRepOffset_ListOfInterval& L = myAnalyse.Type(E); + if (!L.IsEmpty() && L.First().Type() == OT) { + Standard_Real CurOffset = myOffset; + if ( myFaceOffset.IsBound(Anc.First())) + CurOffset = myFaceOffset(Anc.First()); + TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E); + TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape); + aLocalShape = MapSF(Anc.Last()).Generated(E); + TopoDS_Edge EOn2 = TopoDS::Edge(aLocalShape); +// TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E)); +// TopoDS_Edge EOn2 = TopoDS::Edge(MapSF(Anc.Last()) .Generated(E)); + // find if exits tangent edges in the original shape + TopoDS_Edge E1f, E1l; + TopoDS_Vertex V1f, V1l; + TopExp::Vertices(E,V1f,V1l); + TopTools_ListOfShape TangE; + myAnalyse.TangentEdges(E,V1f,TangE); + // find if the pipe on the tangent edges are soon created. + TopTools_ListIteratorOfListOfShape itl(TangE); + Standard_Boolean Find = Standard_False; + for ( ; itl.More() && !Find; itl.Next()) { + if ( MapSF.IsBound(itl.Value())) { + TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1f); + E1f = TopoDS::Edge(aLocalShape); +// E1f = TopoDS::Edge(MapSF(itl.Value()).Generated(V1f)); + Find = Standard_True; + } + } + TangE.Clear(); + myAnalyse.TangentEdges(E,V1l,TangE); + // find if the pipe on the tangent edges are soon created. + itl.Initialize(TangE); + Find = Standard_False; + for ( ; itl.More() && !Find; itl.Next()) { + if ( MapSF.IsBound(itl.Value())) { + TopoDS_Shape aLocalShape = MapSF(itl.Value()).Generated(V1l); + E1l = TopoDS::Edge(aLocalShape); +// E1l = TopoDS::Edge(MapSF(itl.Value()).Generated(V1l)); + Find = Standard_True; + } + } + BRepOffset_Offset OF (E,EOn1,EOn2,CurOffset,E1f, E1l); + MapSF.Bind(E,OF); + } + } + else { + // ---------------------- + // free border. + // ---------------------- + TopoDS_Shape aLocalShape = MapSF(Anc.First()).Generated(E); + TopoDS_Edge EOn1 = TopoDS::Edge(aLocalShape); +/// TopoDS_Edge EOn1 = TopoDS::Edge(MapSF(Anc.First()).Generated(E)); + myInitOffsetEdge.SetRoot(E); // skv: supporting history. + myInitOffsetEdge.Bind (E,EOn1); + } + } + } + + //-------------------------------------------------------- + // Construction of spheres on vertex. + //-------------------------------------------------------- + Done.Clear(); + TopTools_ListIteratorOfListOfShape it; + + for (Exp.Init(myShape,TopAbs_VERTEX); Exp.More(); Exp.Next()) { + const TopoDS_Vertex& V = TopoDS::Vertex (Exp.Current()); + if (Done.Add(V)) { + const TopTools_ListOfShape& LA = myAnalyse.Ancestors(V); + TopTools_ListOfShape LE; + myAnalyse.Edges(V,OT,LE); + + if (LE.Extent() >= 3 && LE.Extent() == LA.Extent()) { + TopTools_ListOfShape LOE; + //-------------------------------------------------------- + // Return connected edges on tubes. + //-------------------------------------------------------- + for (it.Initialize(LE) ; it.More(); it.Next()) { + LOE.Append(MapSF(it.Value()).Generated(V).Reversed()); + } + //---------------------- + // construction sphere. + //----------------------- + const TopTools_ListOfShape& LLA = myAnalyse.Ancestors(LA.First()); + const TopoDS_Shape& FF = LLA.First(); + Standard_Real CurOffset = myOffset; + if ( myFaceOffset.IsBound(FF)) + CurOffset = myFaceOffset(FF); + + BRepOffset_Offset OF(V,LOE,CurOffset); + MapSF.Bind(V,OF); + } + //-------------------------------------------------------------- + // Particular processing if V is at least a free border. + //------------------------------------------------------------- + TopTools_ListOfShape LBF; + myAnalyse.Edges(V,BRepOffset_FreeBoundary,LBF); + if (!LBF.IsEmpty()) { + Standard_Boolean First = Standard_True; + for (it.Initialize(LE) ; it.More(); it.Next()) { + if (First) { + myInitOffsetEdge.SetRoot(V); // skv: supporting history. + myInitOffsetEdge.Bind(V,MapSF(it.Value()).Generated(V)); + First = Standard_False; + } + else { + myInitOffsetEdge.Add(V,MapSF(it.Value()).Generated(V)); + } + } + } + } + } + + //------------------------------------------------------------ + // Extension of parallel faces to the context. + // Extended faces are ordered in DS and removed from MapSF. + //------------------------------------------------------------ + if (!myFaces.IsEmpty()) ToContext (MapSF); + + //------------------------------------------------------ + // MAJ SD. + //------------------------------------------------------ + BRepOffset_Type RT = BRepOffset_Concave; + if (myOffset < 0.) RT = BRepOffset_Convex; + BRepOffset_DataMapIteratorOfDataMapOfShapeOffset It(MapSF); + for ( ; It.More(); It.Next()) { + const TopoDS_Shape& SI = It.Key(); + const BRepOffset_Offset& SF = It.Value(); + if (SF.Status() == BRepOffset_Reversed || + SF.Status() == BRepOffset_Degenerated ) { + //------------------------------------------------ + // Degenerated or returned faces are not stored. + //------------------------------------------------ + continue; + } + + const TopoDS_Face& OF = It.Value().Face(); + myInitOffsetFace.Bind (SI,OF); + myInitOffsetFace.SetRoot (SI); // Initial<-> Offset + myImageOffset.SetRoot (OF); // FaceOffset root of images + + if (SI.ShapeType() == TopAbs_FACE) { + for (Exp.Init(SI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + Exp.More(); Exp.Next()) { + //-------------------------------------------------------------------- + // To each face are associatedthe edges that restrict that + // The edges that do not generate tubes or are not tangent + // to two faces are removed. + //-------------------------------------------------------------------- + const TopoDS_Edge& E = TopoDS::Edge(Exp.Current()); + const BRepOffset_ListOfInterval& L = myAnalyse.Type(E); + if (!L.IsEmpty() && L.First().Type() != RT) { + TopAbs_Orientation OO = E.Orientation(); + TopoDS_Shape aLocalShape = It.Value().Generated(E); + TopoDS_Edge OE = TopoDS::Edge(aLocalShape); +// TopoDS_Edge OE = TopoDS::Edge(It.Value().Generated(E)); + myAsDes->Add (OF,OE.Oriented(OO)); + } + } + } + else { + for (Exp.Init(OF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + Exp.More(); Exp.Next()) { + myAsDes->Add (OF,Exp.Current()); + } + } + } + +#ifdef OCCT_DEBUG + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : SelfInter +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::SelfInter(TopTools_MapOfShape& /*Modif*/) +{ +#ifdef OCCT_DEBUG + if ( ChronBuildOld) { + cout << " AUTODEBOUCLAGE:" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + + Standard_NotImplemented::Raise(); + +#ifdef OCCT_DEBUG + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : ToContext +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::ToContext (BRepOffset_DataMapOfShapeOffset& MapSF) +{ + TopTools_DataMapOfShapeShape Created; + TopTools_DataMapOfShapeShape MEF; + TopTools_IndexedMapOfShape FacesToBuild; + TopTools_ListIteratorOfListOfShape itl; + TopExp_Explorer exp; + +// TopAbs_State Side = TopAbs_IN; +// if (myOffset < 0.) Side = TopAbs_OUT; + + TopAbs_State Side = TopAbs_OUT; + + /* + Standard_Integer i; + for (i = 1; i <= myFaces.Extent(); i++) { + const TopoDS_Face& CF = TopoDS::Face(myFaces(i)); + for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + exp.More(); exp.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); + if (!myAnalyse.HasAncestor(E)) { + //---------------------------------------------------------------- + // The edges of context faces that are not in the initial shape + // can appear in the result. + //---------------------------------------------------------------- + //myAsDes->Add(CF,E); + } + } + } + */ + + //-------------------------------------------------------- + // Determine the edges and faces reconstructed by + // intersection. + //--------------------------------------------------------- + Standard_Integer j; + for (j = 1; j <= myFaces.Extent(); j++) { + const TopoDS_Face& CF = TopoDS::Face(myFaces(j)); + for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + exp.More(); exp.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); + if (myAnalyse.HasAncestor(E)) { + const TopTools_ListOfShape& LEA = myAnalyse.Ancestors(E); + for (itl.Initialize(LEA); itl.More(); itl.Next()) { + const BRepOffset_Offset& OF = MapSF(itl.Value()); + FacesToBuild.Add(itl.Value()); + MEF.Bind(OF.Generated(E),CF); + } + TopoDS_Vertex V[2]; + TopExp::Vertices(E,V[0],V[1]); + for (Standard_Integer i = 0; i < 2; i++) { + const TopTools_ListOfShape& LVA = myAnalyse.Ancestors(V[i]); + for ( itl.Initialize(LVA); itl.More(); itl.Next()) { + const TopoDS_Edge& EV = TopoDS::Edge(itl.Value()); + if (MapSF.IsBound(EV)) { + const BRepOffset_Offset& OF = MapSF(EV); + FacesToBuild.Add(EV); + MEF.Bind(OF.Generated(V[i]),CF); + } + } + } + } + } + } + //--------------------------- + // Reconstruction of faces. + //--------------------------- + TopoDS_Face F,NF; + BRepOffset_Type RT = BRepOffset_Concave; + if (myOffset < 0.) RT = BRepOffset_Convex; + TopoDS_Shape OE,NE; + TopAbs_Orientation Or; + + for (j = 1; j <= FacesToBuild.Extent(); j++) { + const TopoDS_Shape& S = FacesToBuild(j); + BRepOffset_Offset BOF; + BOF = MapSF(S); + F = TopoDS::Face(BOF.Face()); + BRepOffset_Tool::ExtentFace(F,Created,MEF,Side,myTol,NF); + MapSF.UnBind(S); + //-------------- + // MAJ SD. + //-------------- + myInitOffsetFace.Bind (S,NF); + myInitOffsetFace.SetRoot (S); // Initial<-> Offset + myImageOffset.SetRoot (NF); + + if (S.ShapeType() == TopAbs_FACE) { + for (exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + exp.More(); exp.Next()) { + + const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); + const BRepOffset_ListOfInterval& L = myAnalyse.Type(E); + OE = BOF.Generated(E); + Or = E.Orientation(); + OE.Orientation(Or); + if (!L.IsEmpty() && L.First().Type() != RT) { + if (Created.IsBound(OE)) { + NE = Created(OE); + if (NE.Orientation() == TopAbs_REVERSED) + NE.Orientation(TopAbs::Reverse(Or)); + else + NE.Orientation(Or); + myAsDes->Add(NF,NE); + } + else { + myAsDes->Add(NF,OE); + } + } + } + } + else { + //------------------ + // Tube + //--------------------- + for (exp.Init(NF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); + exp.More(); exp.Next()) { + myAsDes->Add (NF,exp.Current()); + } + } + MapSF.UnBind(S); + } + + //------------------ + // MAJ free borders + //------------------ + TopTools_DataMapIteratorOfDataMapOfShapeShape itc; + for (itc.Initialize(Created); itc.More(); itc.Next()) { + OE = itc.Key(); + NE = itc.Value(); + if (myInitOffsetEdge.IsImage(OE)) { + TopoDS_Shape E = myInitOffsetEdge.ImageFrom (OE); + Or = myInitOffsetEdge.Image(E).First().Orientation(); + if (NE.Orientation() == TopAbs_REVERSED) + NE.Orientation(TopAbs::Reverse(Or)); + else + NE.Orientation(Or); + myInitOffsetEdge.Remove(OE); + myInitOffsetEdge.Bind(E,NE); + } + } +} + +//======================================================================= +//function : UpdateFaceOffset +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::UpdateFaceOffset() +{ + TopTools_MapOfShape M; + TopTools_DataMapOfShapeReal CopiedMap; + CopiedMap.Assign(myFaceOffset); + TopTools_DataMapIteratorOfDataMapOfShapeReal it(CopiedMap); + + BRepOffset_Type RT = BRepOffset_Convex; + if (myOffset < 0.) RT = BRepOffset_Concave; + + for ( ; it.More(); it.Next()) { + const TopoDS_Face& F = TopoDS::Face(it.Key()); + Standard_Real CurOffset = CopiedMap(F); + if ( !M.Add(F)) continue; + TopoDS_Compound Co; + BRep_Builder Build; + Build.MakeCompound(Co); + TopTools_MapOfShape Dummy; + Build.Add(Co,F); + if (myJoin == GeomAbs_Arc) + myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent,RT); + else + myAnalyse.AddFaces(F,Co,Dummy,BRepOffset_Tangent); + + TopExp_Explorer exp(Co,TopAbs_FACE); + for (; exp.More(); exp.Next()) { + const TopoDS_Face& FF = TopoDS::Face(exp.Current()); + if ( !M.Add(FF)) continue; + if ( myFaceOffset.IsBound(FF)) + myFaceOffset.UnBind(FF); + myFaceOffset.Bind(FF,CurOffset); + } + } +} + +//======================================================================= +//function : CorrectConicalFaces +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::CorrectConicalFaces() +{ + TopTools_SequenceOfShape Cones; + TopTools_SequenceOfShape Circs; + TopTools_SequenceOfShape Seams; + Standard_Real TolApex = 1.e-5; + + Standard_Integer i; + + TopTools_DataMapOfShapeListOfShape FacesOfCone; + //TopTools_DataMapOfShapeShape DegEdges; + TopExp_Explorer Explo( myOffsetShape, TopAbs_FACE ); + if (myJoin == GeomAbs_Arc) + { + for (; Explo.More(); Explo.Next()) + { + TopoDS_Face aFace = TopoDS::Face( Explo.Current() ); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface( aFace ); + //if (aSurf->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface)) + //aSurf = (Handle(Geom_OffsetSurface)::DownCast(aSurf))->BasisSurface(); //??? + + TopTools_IndexedMapOfShape Emap; + TopExp::MapShapes( aFace, TopAbs_EDGE, Emap ); + for (i = 1; i <= Emap.Extent(); i++) + { + TopoDS_Edge anEdge = TopoDS::Edge( Emap(i) ); + //Standard_Real f, l; + //Handle(Geom_Curve) theCurve = BRep_Tool::Curve( anEdge, f, l ); + //Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &anEdge.TShape()); + if (BRep_Tool::Degenerated(anEdge)) + { + //Check if anEdge is a really degenerated edge or not + BRepAdaptor_Curve BACurve(anEdge, aFace); + gp_Pnt Pfirst, Plast, Pmid; + Pfirst = BACurve.Value(BACurve.FirstParameter()); + Plast = BACurve.Value(BACurve.LastParameter()); + Pmid = BACurve.Value((BACurve.FirstParameter()+BACurve.LastParameter())/2.); + if (Pfirst.Distance(Plast) <= TolApex && + Pfirst.Distance(Pmid) <= TolApex) + continue; + //Cones.Append( aFace ); + //Circs.Append( anEdge ); + //TopoDS_Vertex Vdeg = TopExp::FirstVertex( anEdge ); + TopoDS_Edge OrEdge = + TopoDS::Edge( myInitOffsetEdge.Root( anEdge) ); + TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge ); + if ( FacesOfCone.IsBound(VF) ) + { + //add a face to the existing list + TopTools_ListOfShape& aFaces = FacesOfCone.ChangeFind(VF); + aFaces.Append (aFace); + //DegEdges.Bind(aFace, anEdge); + } + else + { + //the vertex is not in the map => create a new key and items + TopTools_ListOfShape aFaces; + aFaces.Append (aFace); + FacesOfCone.Bind(VF, aFaces); + //DegEdges.Bind(aFace, anEdge); + } + } + } //for (i = 1; i <= Emap.Extent(); i++) + } //for (; fexp.More(); fexp.Next()) + } //if (myJoin == GeomAbs_Arc) + + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Cone(FacesOfCone); + BRep_Builder BB; + TopLoc_Location L; + for (; Cone.More(); Cone.Next() ) { + gp_Sphere theSphere; + Handle(Geom_SphericalSurface) aSphSurf; + TopoDS_Wire SphereWire; + BB.MakeWire(SphereWire); + TopoDS_Vertex anApex = TopoDS::Vertex(Cone.Key()); + const TopTools_ListOfShape& Faces = Cone.Value(); //FacesOfCone(anApex); + TopTools_ListIteratorOfListOfShape itFaces(Faces); + Standard_Boolean isFirstFace = Standard_True; + gp_Pnt FirstPoint; + TopoDS_Vertex theFirstVertex, CurFirstVertex; + for (; itFaces.More(); itFaces.Next()) + { + TopoDS_Face aFace = TopoDS::Face(itFaces.Value()); //TopoDS::Face(Faces.First()); + TopoDS_Edge DegEdge; // = TopoDS::Edge(DegEdges(aFace)); + for (Explo.Init(aFace, TopAbs_EDGE); Explo.More(); Explo.Next()) + { + DegEdge = TopoDS::Edge(Explo.Current()); + if (BRep_Tool::Degenerated(DegEdge)) + { + TopoDS_Edge OrEdge = TopoDS::Edge( myInitOffsetEdge.Root( DegEdge) ); + TopoDS_Vertex VF = TopExp::FirstVertex( OrEdge ); + if (VF.IsSame(anApex)) + break; + } + } + TopoDS_Shape aLocalDegShape = DegEdge.Oriented(TopAbs_FORWARD); + TopoDS_Edge CurEdge = TopoDS::Edge(aLocalDegShape); + BB.Degenerated(CurEdge, Standard_False); + BB.SameRange(CurEdge, Standard_False); + BB.SameParameter(CurEdge, Standard_False); + gp_Pnt fPnt, lPnt, mPnt; + GetEdgePoints(CurEdge, aFace, fPnt, mPnt, lPnt); + Standard_Real f, l; + BRep_Tool::Range(CurEdge, f, l); + if (isFirstFace) + { + gp_Vec aVec1(fPnt, mPnt); + gp_Vec aVec2(fPnt, lPnt); + gp_Vec aNorm = aVec1.Crossed(aVec2); + gp_Pnt theApex = BRep_Tool::Pnt(anApex); + gp_Vec ApexToFpnt(theApex, fPnt); + gp_Vec Ydir = aNorm ^ ApexToFpnt; + gp_Vec Xdir = Ydir ^ aNorm; + //Xdir.Rotate(gp_Ax1(theApex, aNorm), -f); + gp_Ax2 anAx2(theApex, gp_Dir(aNorm), gp_Dir(Xdir)); + theSphere.SetRadius(myOffset); + theSphere.SetPosition(gp_Ax3(anAx2) /*gp_Ax3(theApex, gp_Dir(aNorm))*/); + aSphSurf = new Geom_SphericalSurface(theSphere); + FirstPoint = fPnt; + theFirstVertex = BRepLib_MakeVertex(fPnt); + CurFirstVertex = theFirstVertex; + } + + TopoDS_Vertex v1, v2, FirstVert, EndVert; + TopExp::Vertices(CurEdge, v1, v2); + FirstVert = CurFirstVertex; + if (lPnt.Distance(FirstPoint) <= Precision::Confusion()) + EndVert = theFirstVertex; + else + EndVert = BRepLib_MakeVertex(lPnt); + CurEdge.Free( Standard_True ); + BB.Remove(CurEdge, v1); + BB.Remove(CurEdge, v2); + BB.Add(CurEdge, FirstVert.Oriented(TopAbs_FORWARD)); + BB.Add(CurEdge, EndVert.Oriented(TopAbs_REVERSED)); + //take the curve from sphere an put it to the edge + Standard_Real Uf, Vf, Ul, Vl; + ElSLib::Parameters( theSphere, fPnt, Uf, Vf ); + ElSLib::Parameters( theSphere, lPnt, Ul, Vl ); + if (Abs(Ul) <= Precision::Confusion()) + Ul = 2.*M_PI; + Handle(Geom_Curve) aCurv = aSphSurf->VIso(Vf); + /* + if (!isFirstFace) + { + gp_Circ aCircle = (Handle(Geom_Circle)::DownCast(aCurv))->Circ(); + if (Abs(Uf - f) > Precision::Confusion()) + { + aCircle.Rotate(aCircle.Axis(), f - Uf); + aCurv = new Geom_Circle(aCircle); + } + } + */ + Handle(Geom_TrimmedCurve) aTrimCurv = new Geom_TrimmedCurve(aCurv, Uf, Ul); + BB.UpdateEdge(CurEdge, aTrimCurv, Precision::Confusion()); + BB.Range(CurEdge, Uf, Ul, Standard_True); + Handle(Geom2d_Line) theLin2d = new Geom2d_Line( gp_Pnt2d( 0., Vf ), gp::DX2d() ); + Handle(Geom2d_TrimmedCurve) theTrimLin2d = new Geom2d_TrimmedCurve(theLin2d, Uf, Ul); + BB.UpdateEdge(CurEdge, theTrimLin2d, aSphSurf, L, Precision::Confusion()); + BB.Range(CurEdge, aSphSurf, L, Uf, Ul); + BRepLib::SameParameter(CurEdge); + BB.Add(SphereWire, CurEdge); + //Modifying correspondent edges in aFace: substitute vertices common with CurEdge + BRepAdaptor_Curve2d BAc2d(CurEdge, aFace); + gp_Pnt2d fPnt2d, lPnt2d; + fPnt2d = BAc2d.Value(BAc2d.FirstParameter()); + lPnt2d = BAc2d.Value(BAc2d.LastParameter()); + TopTools_IndexedMapOfShape Emap; + TopExp::MapShapes(aFace, TopAbs_EDGE, Emap); + TopoDS_Edge EE [2]; + Standard_Integer j = 0, k; + for (k = 1; k <= Emap.Extent(); k++) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(k)); + if (!BRep_Tool::Degenerated(anEdge)) + { + TopoDS_Vertex V1, V2; + TopExp::Vertices(anEdge, V1, V2); + if (V1.IsSame(v1) || V2.IsSame(v1)) + EE[j++] = anEdge; + } + } + for (k = 0; k < j; k++) + { + TopoDS_Shape aLocalShape = EE[k].Oriented(TopAbs_FORWARD); + TopoDS_Edge Eforward = TopoDS::Edge(aLocalShape); + Eforward.Free(Standard_True); + TopoDS_Vertex V1, V2; + TopExp::Vertices( Eforward, V1, V2 ); + BRepAdaptor_Curve2d EEc( Eforward, aFace ); + gp_Pnt2d p2d1, p2d2; + p2d1 = EEc.Value(EEc.FirstParameter()); + p2d2 = EEc.Value(EEc.LastParameter()); + if (V1.IsSame(v1)) + { + TopoDS_Vertex NewV = (p2d1.Distance(fPnt2d) <= Precision::Confusion())? + FirstVert : EndVert; + BB.Remove( Eforward, V1 ); + BB.Add( Eforward, NewV.Oriented(TopAbs_FORWARD) ); + } + else + { + TopoDS_Vertex NewV = (p2d2.Distance(fPnt2d) <= Precision::Confusion())? + FirstVert : EndVert; + BB.Remove( Eforward, V2 ); + BB.Add( Eforward, NewV.Oriented(TopAbs_REVERSED) ); + } + } + + isFirstFace = Standard_False; + CurFirstVertex = EndVert; + } + //Building new spherical face + Standard_Real Ufirst = RealLast(), Ulast = RealFirst(); + gp_Pnt2d p2d1, p2d2; + TopTools_ListOfShape EdgesOfWire; + TopoDS_Iterator itw(SphereWire); + for (; itw.More(); itw.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value()); + EdgesOfWire.Append(anEdge); + Standard_Real f, l; + Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aSphSurf, L, f, l); + p2d1 = aC2d->Value(f); + p2d2 = aC2d->Value(l); + if (p2d1.X() < Ufirst) + Ufirst = p2d1.X(); + if (p2d1.X() > Ulast) + Ulast = p2d1.X(); + if (p2d2.X() < Ufirst) + Ufirst = p2d2.X(); + if (p2d2.X() > Ulast) + Ulast = p2d2.X(); + } + TopTools_ListOfShape NewEdges; + TopoDS_Edge FirstEdge; + TopTools_ListIteratorOfListOfShape itl(EdgesOfWire); + for (; itl.More(); itl.Next()) + { + FirstEdge = TopoDS::Edge(itl.Value()); + Standard_Real f, l; + Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(FirstEdge, aSphSurf, L, f, l); + p2d1 = aC2d->Value(f); + p2d2 = aC2d->Value(l); + if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion()) + { + EdgesOfWire.Remove(itl); + break; + } + } + NewEdges.Append(FirstEdge); + TopoDS_Vertex Vf1, CurVertex; + TopExp::Vertices(FirstEdge, Vf1, CurVertex); + itl.Initialize(EdgesOfWire); + while (itl.More()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); + TopoDS_Vertex V1, V2; + TopExp::Vertices(anEdge, V1, V2); + if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex)) + { + NewEdges.Append(anEdge); + CurVertex = (V1.IsSame(CurVertex))? V2 : V1; + EdgesOfWire.Remove(itl); + } + else + itl.Next(); + } + + Standard_Real Vfirst, Vlast; + if (p2d1.Y() > 0.) + { + Vfirst = p2d1.Y(); Vlast = M_PI/2.; + } + else + { + Vfirst = -M_PI/2.; Vlast = p2d1.Y(); + } + TopoDS_Face NewSphericalFace = BRepLib_MakeFace(aSphSurf, Ufirst, Ulast, Vfirst, Vlast, Precision::Confusion()); + TopoDS_Edge OldEdge; + for (Explo.Init(NewSphericalFace, TopAbs_EDGE); Explo.More(); Explo.Next()) + { + OldEdge = TopoDS::Edge(Explo.Current()); + if (!BRep_Tool::Degenerated(OldEdge)) + { + BRepAdaptor_Curve2d BAc2d(OldEdge, NewSphericalFace); + p2d1 = BAc2d.Value(BAc2d.FirstParameter()); + p2d2 = BAc2d.Value(BAc2d.LastParameter()); + if (Abs(p2d1.X() - Ufirst) <= Precision::Confusion() && + Abs(p2d2.X() - Ulast) <= Precision::Confusion()) + break; + } + } + TopoDS_Vertex V1, V2; + TopExp::Vertices(OldEdge, V1, V2); + TopTools_ListOfShape LV1, LV2; + LV1.Append(Vf1); + LV2.Append(CurVertex); + BRepTools_Substitution theSubstitutor; + theSubstitutor.Substitute(V1, LV1); + if (!V1.IsSame(V2)) + theSubstitutor.Substitute(V2, LV2); + theSubstitutor.Substitute(OldEdge, NewEdges); + theSubstitutor.Build(NewSphericalFace); + if (theSubstitutor.IsCopied(NewSphericalFace)) + { + const TopTools_ListOfShape& listSh = theSubstitutor.Copy(NewSphericalFace); + NewSphericalFace = TopoDS::Face(listSh.First()); + } + + //Adding NewSphericalFace to the shell + Explo.Init( myOffsetShape, TopAbs_SHELL ); + TopoDS_Shape theShell = Explo.Current(); + theShell.Free( Standard_True ); + BB.Add( theShell, NewSphericalFace ); + } + + if (myShape.ShapeType() == TopAbs_SOLID || myThickening) + { + Explo.Init( myOffsetShape, TopAbs_SHELL ); + + if (Explo.More()) { + TopoDS_Shape theShell = Explo.Current(); + theShell.Closed( Standard_True ); + } + + Standard_Integer NbShell = 0; + TopoDS_Compound NC; + TopoDS_Shape S1; + BB.MakeCompound (NC); + + for (Explo.Init(myOffsetShape,TopAbs_SHELL); Explo.More(); Explo.Next()) { + const TopoDS_Shell& Sh = TopoDS::Shell(Explo.Current()); + NbShell++; + if (Sh.Closed()) { + TopoDS_Solid Sol; + BB.MakeSolid (Sol); + BB.Add (Sol,Sh); + Sol.Closed(Standard_True); + BB.Add (NC,Sol); + if (NbShell == 1) S1 = Sol; + } + else { + BB.Add (NC,Sh); + if (NbShell == 1) S1 = Sh; + } + } + if (NbShell == 1) myOffsetShape = S1; + else myOffsetShape = NC; + } +} + +//======================================================================= +//function : Intersection3D +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::Intersection3D(BRepOffset_Inter3d& Inter) +{ +#ifdef OCCT_DEBUG + if (ChronBuildOld) { + cout << " INTERSECTION 3D:" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + TopTools_ListOfShape OffsetFaces; // list of faces // created. + MakeList (OffsetFaces, myInitOffsetFace, myFaces); + + if (!myFaces.IsEmpty()) { + Standard_Boolean InSide = (myOffset < 0.); // Temporary + // it is necessary to calculate Inside taking account of the concavity or convexity of edges + // between the cap and the part. + + if (myJoin == GeomAbs_Arc) + Inter.ContextIntByArc (myFaces,InSide,myAnalyse,myInitOffsetFace,myInitOffsetEdge); + } + if (myInter) { + //------------- + //Complete. + //------------- + Inter.CompletInt (OffsetFaces,myInitOffsetFace); + TopTools_IndexedMapOfShape& NewEdges = Inter.NewEdges(); + if (myJoin == GeomAbs_Intersection) { + BRepOffset_Tool::CorrectOrientation (myShape,NewEdges,myAsDes,myInitOffsetFace,myOffset); + } + } + else { + //-------------------------------- + // Only between neighbor faces. + //-------------------------------- + Inter.ConnexIntByArc(OffsetFaces,myShape,myAnalyse,myInitOffsetFace); + } +#ifdef OCCT_DEBUG + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : Intersection2D +//purpose : +//======================================================================= + +void BRepOffset_MakeOffsetOld::Intersection2D(const TopTools_IndexedMapOfShape& Modif, + const TopTools_IndexedMapOfShape& NewEdges) +{ +#ifdef OCCT_DEBUG + if (ChronBuildOld) { + cout << " INTERSECTION 2D:" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + //-------------------------------------------------------- + // calculate intersections2d on faces concerned by + // intersection3d + //--------------------------------------------------------- + //TopTools_MapIteratorOfMapOfShape it(Modif); + //----------------------------------------------- + // Intersection of edges 2 by 2. + //----------------------------------------------- + Standard_Integer i; + for (i = 1; i <= Modif.Extent(); i++) { + const TopoDS_Face& F = TopoDS::Face(Modif(i)); + Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(F); + BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,aCurrFaceTol); + } + +#ifdef OCCT_DEBUG + if (AffichInt2dOld) { + DEBVerticesControlOld (NewEdges,myAsDes); + } + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : MakeLoops +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::MakeLoops(TopTools_IndexedMapOfShape& Modif) +{ +#ifdef OCCT_DEBUG + if (ChronBuildOld) { + cout << " DEBOUCLAGE 2D:" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + //TopTools_MapIteratorOfMapOfShape it(Modif); + TopTools_ListOfShape LF,LC; + //----------------------------------------- + // unwinding of faces // modified. + //----------------------------------------- + Standard_Integer i; + for (i = 1; i <= Modif.Extent(); i++) { + if (!myFaces.Contains(Modif(i))) + LF.Append(Modif(i)); + } + // + if ((myJoin == GeomAbs_Intersection) && myInter) { + TopTools_ListOfShape aLFailed; + TopTools_IndexedDataMapOfShapeListOfShape anOr; + BuildSplitsOfFaces(LF, myAsDes, anOr, myImageOffset, aLFailed, Standard_True); + if (aLFailed.Extent()) { + myMakeLoops.Build(aLFailed, myAsDes, myImageOffset); + } + } + else { + myMakeLoops.Build(LF,myAsDes,myImageOffset); + } + //----------------------------------------- + // unwinding of caps. + //----------------------------------------- + for (i = 1; i <= myFaces.Extent(); i++) + LC.Append(myFaces(i)); + + Standard_Boolean InSide = 1; + if (myOffset > 0 ) InSide = 0; + myMakeLoops.BuildOnContext(LC,myAnalyse,myAsDes,myImageOffset,InSide); + +#ifdef OCCT_DEBUG + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : MakeFaces +//purpose : Reconstruction of topologically unchanged faces that +// share edges that were reconstructed. +//======================================================================= +void BRepOffset_MakeOffsetOld::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/) +{ +#ifdef OCCT_DEBUG + if (ChronBuildOld) { + cout << " RECONSTRUCTION OF FACES:" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + TopTools_ListIteratorOfListOfShape itr; + const TopTools_ListOfShape& Roots = myInitOffsetFace.Roots(); + TopTools_ListOfShape LOF; + TopTools_MapOfShape aMFence; + //---------------------------------- + // Loop on all faces //. + //---------------------------------- + for (itr.Initialize(Roots); itr.More(); itr.Next()) { + TopoDS_Face F = TopoDS::Face(myInitOffsetFace.Image(itr.Value()).First()); + if (!myImageOffset.HasImage(F) && aMFence.Add(F)) { + LOF.Append(F); + } + } + // + if ((myJoin == GeomAbs_Intersection) && myInter) { + TopTools_ListOfShape aLFailed; + TopTools_IndexedDataMapOfShapeListOfShape anOr; + BuildSplitsOfFaces(LOF, myAsDes, anOr, myImageOffset, aLFailed, Standard_True); + if (aLFailed.Extent()) { + myMakeLoops.Build(aLFailed, myAsDes, myImageOffset); + } + } + else { + myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset); + } + // +#ifdef OCCT_DEBUG + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : MakeMissingWalls +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::MakeMissingWalls () +{ + TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary) + TopTools_DataMapOfShapeShape MapEF; //Edges of contours: edge + face + Standard_Real OffsetVal = Abs(myOffset); + + FillContours(myShape, myAnalyse, Contours, MapEF); + + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(Contours); + for (; iter.More(); iter.Next()) + { + TopoDS_Vertex StartVertex = TopoDS::Vertex(iter.Key()); + TopoDS_Edge StartEdge; + const TopTools_ListOfShape& aContour = iter.Value(); + TopTools_ListIteratorOfListOfShape itl(aContour); + Standard_Boolean FirstStep = Standard_True; + TopoDS_Edge PrevEdge; + TopoDS_Vertex PrevVertex = StartVertex; + for (; itl.More(); itl.Next()) + { + TopoDS_Edge anEdge = TopoDS::Edge(itl.Value()); + if (!myInitOffsetEdge.HasImage(anEdge)) + continue; + //if (BRep_Tool::Degenerated(anEdge)) + //continue; + TopoDS_Face aFace = TopoDS::Face(MapEF(anEdge)); + //TopoDS_Edge OE = TopoDS::Edge(myInitOffsetEdge.Image(anEdge).First()); + TopTools_ListOfShape LOE, LOE2; + myInitOffsetEdge.LastImage( anEdge, LOE ); + myImageOffset.LastImage( LOE.Last(), LOE2 ); + TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() ); + //////////////////////////////////////////////////////////////////////// + TopoDS_Vertex V1, V2, V3, V4; + TopExp::Vertices(anEdge, V1, V2/*, Standard_True*/); + TopExp::Vertices(OE, V4, V3/*, Standard_True*/); + Standard_Boolean ToReverse = Standard_False; + if (!V1.IsSame(PrevVertex)) + { + TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx; + aVtx = V3; V3 = V4; V4 = aVtx; + ToReverse = Standard_True; + } + //Temporary + //anEdge.Reverse(); + OE.Orientation(TopAbs::Reverse(anEdge.Orientation())); + TopoDS_Edge E3, E4; + if (FirstStep) + { + E4 = BRepLib_MakeEdge( V1, V4 ); + StartEdge = E4; + } + else + E4 = PrevEdge; + Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2))); + if (V2.IsSame(StartVertex) && !ArcOnV2) + E3 = StartEdge; + else + E3 = BRepLib_MakeEdge( V2, V3 ); + E4.Reverse(); + TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD); + const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge); + Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD); + Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD); + BRep_Builder BB; + TopoDS_Wire theWire; + BB.MakeWire(theWire); + if (ToReverse) + { + BB.Add(theWire, anEdge.Reversed()); + BB.Add(theWire, E3.Reversed()); + BB.Add(theWire, OE.Reversed()); + BB.Add(theWire, E4.Reversed()); + } + else + { + BB.Add(theWire, anEdge); + BB.Add(theWire, E3); + BB.Add(theWire, OE); + BB.Add(theWire, E4); + } + BRepLib::BuildCurves3d( theWire, myTol ); + theWire.Closed(Standard_True); + TopoDS_Face NewFace; + Handle(Geom_Surface) theSurf; + BRepAdaptor_Curve BAcurve(anEdge); + BRepAdaptor_Curve BAcurveOE(OE); + Standard_Real fpar = BAcurve.FirstParameter(); + Standard_Real lpar = BAcurve.LastParameter(); + gp_Pnt PonE = BAcurve.Value(fpar); + gp_Pnt PonOE = BAcurveOE.Value(fpar); + gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE ); + Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2; + Standard_Boolean IsPlanar = Standard_False; + if (BAcurve.GetType() == GeomAbs_Circle && + BAcurveOE.GetType() == GeomAbs_Circle) + { + gp_Circ aCirc = BAcurve.Circle(); + gp_Circ aCircOE = BAcurveOE.Circle(); + gp_Lin anAxisLine(aCirc.Axis()); + gp_Dir CircAxisDir = aCirc.Axis().Direction(); + if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) && + anAxisLine.Contains(aCircOE.Location(), Precision::Confusion())) + { //cylinder, plane or cone + if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder + theSurf = GC_MakeCylindricalSurface(aCirc).Value(); + else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane + IsPlanar = Standard_True; + // + gp_Pnt PonEL = BAcurve.Value(lpar); + if (PonEL.Distance(PonE) <= Precision::PConfusion()) { + Standard_Boolean bIsHole; + TopoDS_Edge aE1, aE2; + TopoDS_Wire aW1, aW2; + Handle(Geom_Plane) aPL; + IntTools_FClass2d aClsf; + // + if (aCirc.Radius()>aCircOE.Radius()) { + aE1 = anEdge; + aE2 = OE; + } else { + aE1 = OE; + aE2 = anEdge; + } + // + BB.MakeWire(aW1); + BB.Add(aW1, aE1); + BB.MakeWire(aW2); + BB.Add(aW2, aE2); + // + aPL = new Geom_Plane(aCirc.Location(), CircAxisDir); + for (Standard_Integer i = 0; i < 2; ++i) { + TopoDS_Wire& aW = (i==0) ? aW1 : aW2; + TopoDS_Edge& aE = (i==0) ? aE1 : aE2; + // + TopoDS_Face aFace; + BB.MakeFace(aFace, aPL, Precision::Confusion()); + BB.Add (aFace, aW); + aClsf.Init(aFace, Precision::Confusion()); + bIsHole=aClsf.IsHole(); + if ((bIsHole && !i) || (!bIsHole && i)) { + aW.Nullify(); + BB.MakeWire(aW); + BB.Add(aW, aE.Reversed()); + } + } + // + BB.MakeFace(NewFace, aPL, Precision::Confusion()); + BB.Add(NewFace, aW1); + BB.Add(NewFace, aW2); + } + } + else //case of cone + { + gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(), + aCirc.Radius(), aCircOE.Radius()); + gp_Ax3 theAx3(aCirc.Position()); + if (CircAxisDir * theCone.Axis().Direction() < 0.) + { + theAx3.ZReverse(); + CircAxisDir.Reverse(); + } + theCone.SetPosition(theAx3); + theSurf = new Geom_ConicalSurface(theCone); + } + if (!IsPlanar) { + TopLoc_Location Loc; + EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.)); + BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion()); + Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.; + OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.)); + BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion()); + aLine2d = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff)); + aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff)); + if (E3.IsSame(E4)) + { + if (Coeff > 0.) + BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion()); + else + { + BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion()); + theWire.Nullify(); + BB.MakeWire(theWire); + BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED)); + BB.Add(theWire, E4); + BB.Add(theWire, OE.Oriented(TopAbs_FORWARD)); + BB.Add(theWire, E3); + theWire.Closed(Standard_True); + } + } + else + { + BB.SameParameter(E3, Standard_False); + BB.SameRange(E3, Standard_False); + BB.SameParameter(E4, Standard_False); + BB.SameRange(E4, Standard_False); + BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion()); + BB.Range(E3, theSurf, Loc, 0., OffsetVal); + BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion()); + BB.Range(E4, theSurf, Loc, 0., OffsetVal); + } + NewFace = BRepLib_MakeFace(theSurf, theWire); + } + } //cylinder or cone + } //if both edges are arcs of circles + if (NewFace.IsNull()) + { + BRepLib_MakeFace MF(theWire, Standard_True); //Only plane + if (MF.Error() == BRepLib_FaceDone) + { + NewFace = MF.Face(); + IsPlanar = Standard_True; + } + else //Extrusion (by thrusections) + { + Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar); + Handle(Geom_TrimmedCurve) TrEdgeCurve = + new Geom_TrimmedCurve( EdgeCurve, fpar, lpar ); + Standard_Real fparOE, lparOE; + Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE); + Handle(Geom_TrimmedCurve) TrOffsetCurve = + new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE ); + GeomFill_Generator ThrusecGenerator; + ThrusecGenerator.AddCurve( TrEdgeCurve ); + ThrusecGenerator.AddCurve( TrOffsetCurve ); + ThrusecGenerator.Perform( Precision::PConfusion() ); + theSurf = ThrusecGenerator.Surface(); + //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir ); + Standard_Real Uf, Ul, Vf, Vl; + theSurf->Bounds(Uf, Ul, Vf, Vl); + TopLoc_Location Loc; + EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.)); + BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion()); + OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.)); + BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion()); + Standard_Real UonV1 = (ToReverse)? Ul : Uf; + Standard_Real UonV2 = (ToReverse)? Uf : Ul; + aLine2d = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.)); + aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.)); + if (E3.IsSame(E4)) + { + BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion()); + Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf ); + BB.UpdateEdge(E3, BSplC34, Precision::Confusion()); + BB.Range(E3, Vf, Vl); + } + else + { + BB.SameParameter(E3, Standard_False); + BB.SameRange(E3, Standard_False); + BB.SameParameter(E4, Standard_False); + BB.SameRange(E4, Standard_False); + BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion()); + BB.Range(E3, theSurf, Loc, Vf, Vl); + BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion()); + BB.Range(E4, theSurf, Loc, Vf, Vl); + Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 ); + BB.UpdateEdge(E3, BSplC3, Precision::Confusion()); + BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve + Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 ); + BB.UpdateEdge(E4, BSplC4, Precision::Confusion()); + BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve + } + NewFace = BRepLib_MakeFace(theSurf, theWire); + } + } + if (!IsPlanar) + { + Standard_Real fparOE = BAcurveOE.FirstParameter(); + Standard_Real lparOE = BAcurveOE.LastParameter(); + TopLoc_Location Loc; + if (Abs(fpar - fparOE) > Precision::Confusion()) + { + const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4; + gp_Pnt2d fp2d = EdgeLine2d->Value(fpar); + gp_Pnt2d fp2dOE = OELine2d->Value(fparOE); + aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value(); + Handle(Geom_Curve) aCurve; + Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE); + Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar ); + GeomAdaptor_Surface GAsurf( theSurf ); + Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d ); + Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf ); + Adaptor3d_CurveOnSurface ConS( HC2d, HSurf ); + Standard_Real max_deviation = 0., average_deviation; + GeomLib::BuildCurve3d(Precision::Confusion(), + ConS, FirstPar, LastPar, + aCurve, max_deviation, average_deviation); + BB.UpdateEdge( anE4, aCurve, max_deviation ); + BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation ); + BB.Range( anE4, FirstPar, LastPar ); + } + if (Abs(lpar - lparOE) > Precision::Confusion()) + { + const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3; + gp_Pnt2d lp2d = EdgeLine2d->Value(lpar); + gp_Pnt2d lp2dOE = OELine2d->Value(lparOE); + aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value(); + Handle(Geom_Curve) aCurve; + Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE); + Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar ); + GeomAdaptor_Surface GAsurf( theSurf ); + Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d ); + Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf ); + Adaptor3d_CurveOnSurface ConS( HC2d, HSurf ); + Standard_Real max_deviation = 0., average_deviation; + GeomLib::BuildCurve3d(Precision::Confusion(), + ConS, FirstPar, LastPar, + aCurve, max_deviation, average_deviation); + BB.UpdateEdge( anE3, aCurve, max_deviation ); + BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation ); + BB.Range( anE3, FirstPar, LastPar ); + } + } + BRepLib::SameParameter(NewFace); + BRepTools::Update(NewFace); + myWalls.Append(NewFace); + if (ArcOnV2) + { + TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First()); + TopoDS_Vertex arcV1, arcV2; + TopExp::Vertices(anArc, arcV1, arcV2); + Standard_Boolean ArcReverse = Standard_False; + if (!arcV1.IsSame(V3)) + { + TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx; + ArcReverse = Standard_True; + } + TopoDS_Edge EA1, EA2; + //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed()); + EA1 = E3; + EA1.Reverse(); + if (ToReverse) + EA1.Reverse(); + ////////////////////////////////////////////////////// + if (V2.IsSame(StartVertex)) + EA2 = StartEdge; + else + EA2 = BRepLib_MakeEdge( V2, arcV2 ); + anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) ); + if (EA1.Orientation() == TopAbs_REVERSED) + anArc.Reverse(); + EA2.Orientation(TopAbs::Reverse(EA1.Orientation())); + TopoDS_Wire arcWire; + BB.MakeWire(arcWire); + BB.Add(arcWire, EA1); + BB.Add(arcWire, anArc); + BB.Add(arcWire, EA2); + BRepLib::BuildCurves3d( arcWire, myTol ); + arcWire.Closed(Standard_True); + TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True); + BRepTools::Update(arcFace); + myWalls.Append(arcFace); + TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD); + const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2); + PrevEdge = CEA2; + PrevVertex = V2; + } + else + { + PrevEdge = E3; + PrevVertex = V2; + } + FirstStep = Standard_False; + } + } +} + +//======================================================================= +//function : MakeShells +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::MakeShells() +{ +#ifdef OCCT_DEBUG + if (ChronBuildOld) { + cout << " RECONSTRUCTION OF SHELLS:" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + + //if ((myJoin == GeomAbs_Intersection) && myInter) { + // + // make shells using MakerVolume algorithm + // + TopTools_IndexedDataMapOfShapeListOfShape anOrigins; + // + BOPCol_ListOfShape aLSF; + const TopTools_ListOfShape& R = myImageOffset.Roots(); + TopTools_ListIteratorOfListOfShape it(R); + // + for (; it.More(); it.Next()) { + TopTools_ListOfShape Image; + myImageOffset.LastImage(it.Value(),Image); + TopTools_ListIteratorOfListOfShape it2(Image); + for (; it2.More(); it2.Next()) { + const TopoDS_Shape& aF = it2.Value(); + aLSF.Append(aF); + // + if (anOrigins.Contains(aF)) { + anOrigins.ChangeFromKey(aF).Append(it.Value()); + } + else { + TopTools_ListOfShape aLOr; + aLOr.Append(it.Value()); + anOrigins.Add(aF, aLOr); + } + } + } + // + if (myThickening) { + TopExp_Explorer Explo(myShape, TopAbs_FACE); + for (; Explo.More(); Explo.Next()) { + const TopoDS_Shape& aF = Explo.Current(); + aLSF.Append(aF); + } + // + it.Initialize(myWalls); + for (; it.More(); it.Next()) { + const TopoDS_Shape& aF = it.Value(); + aLSF.Append(aF); + } + } + // + Standard_Boolean bDone = Standard_False; + // build all possible solids + /*if (!myThickening && !myFaces.IsEmpty()) { + TopExp_Explorer Explo(myShape, TopAbs_FACE); + for (; Explo.More(); Explo.Next()) { + const TopoDS_Shape& aF = Explo.Current(); + aLSF.Append(aF); + } + }*/ + // + Standard_Boolean bFaces = !myFaces.IsEmpty(); + // + if ((myJoin == GeomAbs_Intersection) && myInter) { + Standard_Integer i, aNb; + TopTools_ListIteratorOfListOfShape aItLS, aItLS1; + BRep_Builder aBB; + // + TopoDS_Compound aCSF; + aBB.MakeCompound(aCSF); + // + BOPAlgo_Builder aGF; + // + aGF.SetArguments(aLSF); + aGF.Perform(); + bDone = (aGF.ErrorStatus() == 0); + if (bDone) { + const TopoDS_Shape& aR = aGF.Shape(); + TopExp_Explorer aExp(aR, TopAbs_FACE); + aLSF.Clear(); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Shape& aF = aExp.Current(); + aLSF.Append(aF); + aBB.Add(aCSF, aF); + } + // + bDone = ((myOffset > 0) || !bFaces); + if (bDone) { + UpdateOrigins(anOrigins, aGF); + // + BOPAlgo_MakerVolume aMV1; + // + aMV1.AddArgument(aCSF); + aMV1.SetIntersect(Standard_False); + // + if (bFaces) { + aNb = myFaces.Extent(); + for (i = 1; i <= aNb; ++i) { + const TopoDS_Shape& aFEx = myFaces(i); + aMV1.AddArgument(aFEx); + } + aMV1.SetIntersect(Standard_True); + } + // + aMV1.Perform(); + bDone = (aMV1.ErrorStatus() == 0); + if (bDone) { + // + TopoDS_Shape aResult = aMV1.Shape(); + // + TopTools_IndexedMapOfShape aMFResult; + TopExp::MapShapes(aResult, TopAbs_FACE, aMFResult); + // + // check the result + Standard_Boolean bGood = Standard_True; + if (myRemoveInvalidFaces) { + BOPCol_ListIteratorOfListOfShape aItLSF(aLSF); + for (; aItLSF.More(); aItLSF.Next()) { + const TopoDS_Shape& aFx = aItLSF.Value(); + if (!aMFResult.Contains(aFx)) { + const TopTools_ListOfShape& aLFMx = aMV1.Modified(aFx); + if (aLFMx.IsEmpty()) { + bGood = Standard_False; + break; + } + } + } + } + // + TopoDS_Compound aShells; + // + aBB.MakeCompound(aShells); + // + if (!bGood) { + myOffsetShape = aShells; + } + else { + // collect images of the faces + TopTools_MapOfShape aMFaces; + aNb = myFaces.Extent(); + for (i = 1; i <= aNb; ++i) { + const TopoDS_Shape& aFEx = myFaces(i); + const TopTools_ListOfShape& aLFEx = aMV1.Modified(aFEx); + if (!aLFEx.IsEmpty()) { + aItLS.Initialize(aLFEx); + for (; aItLS.More(); aItLS.Next()) { + const TopoDS_Face& aFExIm = *(TopoDS_Face*)&aItLS.Value(); + aMFaces.Add(aFExIm); + } + } + else { + aMFaces.Add(aFEx); + } + } + // + if (aResult.ShapeType() == TopAbs_COMPOUND) { + // collect faces attached to only one solid + BOPCol_IndexedDataMapOfShapeListOfShape aMFS; + BOPCol_ListOfShape aLSF2; + // + BOPTools::MapShapesAndAncestors(aResult, TopAbs_FACE, TopAbs_SOLID, aMFS); + aNb = aMFS.Extent(); + bDone = (aNb > 0); + // + if (bDone) { + for (i = 1; i <= aNb; ++i) { + const BOPCol_ListOfShape& aLSx = aMFS(i); + if (aLSx.Extent() == 1) { + const TopoDS_Shape& aFx = aMFS.FindKey(i); + aLSF2.Append(aFx); + } + } + // + // make solids from the new list + BOPAlgo_MakerVolume aMV2; + // + aMV2.SetArguments(aLSF2); + aMV2.SetIntersect(Standard_False); + // + aMV2.Perform(); + bDone = (aMV2.ErrorStatus() == 0); + if (bDone) { + aResult = aMV2.Shape(); + if (aResult.ShapeType() == TopAbs_COMPOUND) { + BOPCol_ListOfShape aLSF3; + // + aExp.Init(aResult, TopAbs_FACE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current(); + // + // check orientation + if (!anOrigins.Contains(aF)) { + aLSF3.Append(aF); + continue; + } + // + const TopTools_ListOfShape& aLFOr = anOrigins.FindFromKey(aF); + aItLS.Initialize(aLFOr); + for (; aItLS.More(); aItLS.Next()) { + const TopoDS_Face& aFOr = *(TopoDS_Face*)&aItLS.Value(); + // + if (CheckNormals(aF, aFOr)) { + aLSF3.Append(aF); + break; + } + } + } + // + // make solid containing most outer faces + BOPAlgo_MakerVolume aMV3; + // + aMV3.SetArguments(aLSF3); + aMV3.SetIntersect(Standard_False); + // + aMV3.Perform(); + bDone = (aMV3.ErrorStatus() == 0); + if (bDone) { + aResult = aMV3.Shape(); + } + } + } + } + } + // + TopExp_Explorer aExp(aResult, TopAbs_SHELL); + bDone = aExp.More(); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Shell& aSh = *(TopoDS_Shell*)&aExp.Current(); + // + TopoDS_Shell aShellNew; + if (bFaces) { + aBB.MakeShell(aShellNew); + // + TopExp_Explorer aExp(aSh, TopAbs_FACE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Face& aFSh = *(TopoDS_Face*)&aExp.Current(); + if (!aMFaces.Contains(aFSh)) { + aBB.Add(aShellNew, aFSh); + } + } + } + else { + aShellNew = aSh; + } + // + aBB.Add(aShells, aShellNew); + } + myOffsetShape = aShells; + } + } + } + } + } + // + if (!bDone) { + BRepTools_Quilt Glue; + BOPCol_ListIteratorOfListOfShape aItLS; + // + aItLS.Initialize(aLSF); + for (; aItLS.More(); aItLS.Next()) { + const TopoDS_Shape& aF = aItLS.Value(); + Glue.Add(aF); + } + myOffsetShape = Glue.Shells(); + } +} + +//======================================================================= +//function : MakeSolid +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::MakeSolid () +{ + if (myOffsetShape.IsNull()) return; + +// Modified by skv - Mon Apr 4 18:17:27 2005 Begin +// Supporting history. + UpdateInitOffset (myInitOffsetFace,myImageOffset,myOffsetShape, TopAbs_FACE); + UpdateInitOffset (myInitOffsetEdge,myImageOffset,myOffsetShape, TopAbs_EDGE); +// Modified by skv - Mon Apr 4 18:17:27 2005 End + TopExp_Explorer exp; + BRep_Builder B; + Standard_Integer NbShell = 0; + TopoDS_Compound NC; + TopoDS_Shape S1; + B.MakeCompound (NC); + + for (exp.Init(myOffsetShape,TopAbs_SHELL); exp.More(); exp.Next()) { + TopoDS_Shell Sh = TopoDS::Shell(exp.Current()); + if (myThickening && myOffset > 0.) + Sh.Reverse(); + NbShell++; + if (Sh.Closed()) { + TopoDS_Solid Sol; + B.MakeSolid (Sol); + B.Add (Sol,Sh); + Sol.Closed(Standard_True); + B.Add (NC,Sol); + if (NbShell == 1) S1 = Sol; + } + else { + B.Add (NC,Sh); + if (NbShell == 1) S1 = Sh; + } + } + if (NbShell == 1) myOffsetShape = S1; + else myOffsetShape = NC; +} + +//======================================================================= +//function : SelectShells +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::SelectShells () +{ + TopTools_MapOfShape FreeEdges; + TopExp_Explorer exp(myShape,TopAbs_EDGE); + //------------------------------------------------------------- + // FreeEdges all edges that can have free border in the + // parallel shell + // 1 - free borders of myShape . + //------------------------------------------------------------- + for ( ; exp.More(); exp.Next()) { + const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); + const TopTools_ListOfShape& LA = myAnalyse.Ancestors(E); + if (LA.Extent() < 2) { + if (myAnalyse.Type(E).First().Type() == BRepOffset_FreeBoundary) { + FreeEdges.Add(E); + } + } + } + // myShape has free borders and there are no caps + // no unwinding 3d. + if (!FreeEdges.IsEmpty() && myFaces.IsEmpty()) return; + + myOffsetShape = BRepOffset_Tool::Deboucle3D(myOffsetShape,FreeEdges); +} + +//======================================================================= +//function : OffsetFacesFromShapes +//purpose : +//======================================================================= +const BRepAlgo_Image& BRepOffset_MakeOffsetOld::OffsetFacesFromShapes() const +{ + return myInitOffsetFace; +} + +// Modified by skv - Tue Mar 15 16:20:43 2005 Begin + +//======================================================================= +//function : GetJoinType +//purpose : Query offset join type. +//======================================================================= +GeomAbs_JoinType BRepOffset_MakeOffsetOld::GetJoinType() const +{ + return myJoin; +} + +//======================================================================= +//function : OffsetEdgesFromShapes +//purpose : +//======================================================================= +const BRepAlgo_Image& BRepOffset_MakeOffsetOld::OffsetEdgesFromShapes() const +{ + return myInitOffsetEdge; +} + +// Modified by skv - Tue Mar 15 16:20:43 2005 End + +//======================================================================= +//function : ClosingFaces +//purpose : +//======================================================================= +const TopTools_IndexedMapOfShape& BRepOffset_MakeOffsetOld::ClosingFaces () const +{ + return myFaces; +} + +//======================================================================= +//function : EncodeRegularity +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::EncodeRegularity () +{ +#ifdef OCCT_DEBUG + if (ChronBuildOld) { + cout << " CODING OF REGULARITIES:" << endl; + ClockOld.Reset(); + ClockOld.Start(); + } +#endif + + if (myOffsetShape.IsNull()) return; + // find edges G1 in the result + TopExp_Explorer exp(myOffsetShape,TopAbs_EDGE); + + BRep_Builder B; + TopTools_MapOfShape MS; + + for ( ; exp.More(); exp.Next()) { + TopoDS_Edge OE = TopoDS::Edge(exp.Current()); + BRepLib::BuildCurve3d(OE,myTol); + TopoDS_Edge ROE = OE; + + if ( !MS.Add(OE)) continue; + + if ( myImageOffset.IsImage(OE)) + ROE = TopoDS::Edge(myImageOffset.Root(OE)); + + const TopTools_ListOfShape& LofOF = myAsDes->Ascendant(ROE); + + if (LofOF.Extent() != 2) { +#ifdef OCCT_DEBUG_VERB + cout << " Edge shared by " << LofOF.Extent() << " Faces" << endl; +#endif + continue; + } + + const TopoDS_Face& F1 = TopoDS::Face(LofOF.First()); + const TopoDS_Face& F2 = TopoDS::Face(LofOF.Last() ); + + if ( F1.IsNull() || F2.IsNull()) + continue; + + const TopoDS_Shape& Root1 = myInitOffsetFace.Root(F1); + const TopoDS_Shape& Root2 = myInitOffsetFace.Root(F2); + + TopAbs_ShapeEnum Type1 = Root1.ShapeType(); + TopAbs_ShapeEnum Type2 = Root2.ShapeType(); + + if (F1.IsSame(F2)) { + if (BRep_Tool::IsClosed(OE,F1)) { + // Temporary Debug for the Bench. + // Check with YFR. + // In mode intersection, the edges are not coded in myInitOffsetEdge + // so, manage case by case + // Note DUB; for Hidden parts, it is NECESSARY to code CN + // Analytic Surfaces. + if (myJoin == GeomAbs_Intersection) { + BRepAdaptor_Surface BS(F1,Standard_False); + GeomAbs_SurfaceType SType = BS.GetType(); + if (SType == GeomAbs_Cylinder || + SType == GeomAbs_Cone || + SType == GeomAbs_Sphere || + SType == GeomAbs_Torus ) { + B.Continuity(OE,F1,F1,GeomAbs_CN); + } + else { + // See YFR : MaJ of myInitOffsetFace + } + } + else if (myInitOffsetEdge.IsImage(ROE)) { + if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) { + const TopoDS_Face& FRoot = TopoDS::Face(Root1); + const TopoDS_Edge& EI = TopoDS::Edge(myInitOffsetEdge.ImageFrom(ROE)); + GeomAbs_Shape Conti = BRep_Tool::Continuity(EI,FRoot,FRoot); + if (Conti == GeomAbs_CN) { + B.Continuity(OE,F1,F1,GeomAbs_CN); + } + else if ( Conti > GeomAbs_C0) { + B.Continuity(OE,F1,F1,GeomAbs_G1); + } + } + } + } + continue; + } + + + // code regularities G1 between : + // - sphere and tube : one root is a vertex, the other is an edge + // and the vertex is included in the edge + // - face and tube : one root is a face, the other an edge + // and the edge is included in the face + // - face and face : if two root faces are tangent in + // the initial shape, they will be tangent in the offset shape + // - tube and tube : if 2 edges generating tubes are + // tangents, the 2 will be tangent either. + if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_VERTEX) { + TopoDS_Vertex V1,V2; + TopExp::Vertices(TopoDS::Edge(Root1), V1, V2); + if ( V1.IsSame(Root2) || V2.IsSame(Root2)) { + B.Continuity(OE,F1,F2,GeomAbs_G1); + } + } + else if ( Type1 == TopAbs_VERTEX && Type2 == TopAbs_EDGE) { + TopoDS_Vertex V1,V2; + TopExp::Vertices(TopoDS::Edge(Root2), V1, V2); + if ( V1.IsSame(Root1) || V2.IsSame(Root1)) { + B.Continuity(OE,F1,F2,GeomAbs_G1); + } + } + else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_EDGE) { + TopExp_Explorer exp2(Root1,TopAbs_EDGE); + for ( ; exp2.More(); exp2.Next()) { + if ( exp2.Current().IsSame(Root2)) { + B.Continuity(OE,F1,F2,GeomAbs_G1); + break; + } + } + } + else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE) { + TopExp_Explorer exp2(Root2,TopAbs_EDGE); + for ( ; exp2.More(); exp2.Next()) { + if ( exp2.Current().IsSame(Root1)) { + B.Continuity(OE,F1,F2,GeomAbs_G1); + break; + } + } + } + else if ( Type1 == TopAbs_FACE && Type2 == TopAbs_FACE) { + // if two root faces are tangent in + // the initial shape, they will be tangent in the offset shape + TopTools_ListOfShape LE,LV; + BRepOffset_Tool::HasCommonShapes(TopoDS::Face(Root1), + TopoDS::Face(Root2), + LE,LV); + if ( LE.Extent() == 1) { + const TopoDS_Edge& Ed = TopoDS::Edge(LE.First()); + if ( myAnalyse.HasAncestor(Ed)) { + const BRepOffset_ListOfInterval& LI = myAnalyse.Type(Ed); + if (LI.Extent() == 1 && + LI.First().Type() == BRepOffset_Tangent) { + B.Continuity(OE,F1,F2,GeomAbs_G1); + } + } + } + } + else if ( Type1 == TopAbs_EDGE && Type2 == TopAbs_EDGE) { + TopTools_ListOfShape LV; + TopExp_Explorer exp1,exp2; + for (exp1.Init(Root1,TopAbs_VERTEX); exp1.More(); exp1.Next()) { + TopExp_Explorer exp2(F2,TopAbs_EDGE); + for (exp2.Init(Root2,TopAbs_VERTEX); exp2.More(); exp2.Next()) { + if (exp1.Current().IsSame(exp2.Current())) { + LV.Append(exp1.Current()); + } + } + } + if ( LV.Extent() == 1) { + TopTools_ListOfShape LEdTg; + myAnalyse.TangentEdges(TopoDS::Edge(Root1), + TopoDS::Vertex(LV.First()), + LEdTg); + TopTools_ListIteratorOfListOfShape it(LEdTg); + for (; it.More(); it.Next()) { + if ( it.Value().IsSame(Root2)) { + B.Continuity(OE,F1,F2,GeomAbs_G1); + break; + } + } + } + } + } + +#ifdef OCCT_DEBUG + if ( ChronBuildOld) ClockOld.Show(); +#endif +} + +//======================================================================= +//function : RemoveInternalEdges +//purpose : +//======================================================================= +void BRepOffset_MakeOffsetOld::RemoveInternalEdges() +{ + Standard_Boolean bRemoveWire, bRemoveEdge; + TopExp_Explorer aExpF, aExpW, aExpE; + TopTools_IndexedDataMapOfShapeListOfShape aDMELF; + // + TopExp::MapShapesAndAncestors(myOffsetShape, TopAbs_EDGE, TopAbs_FACE, aDMELF); + // + aExpF.Init(myOffsetShape, TopAbs_FACE); + for (; aExpF.More(); aExpF.Next()) { + TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current(); + // + TopTools_ListOfShape aLIW; + // + aExpW.Init(aF, TopAbs_WIRE); + for (; aExpW.More(); aExpW.Next()) { + TopoDS_Wire& aW = *(TopoDS_Wire*)&aExpW.Current(); + // + bRemoveWire = Standard_True; + TopTools_ListOfShape aLIE; + // + aExpE.Init(aW, TopAbs_EDGE); + for (; aExpE.More(); aExpE.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current(); + if (aE.Orientation() != TopAbs_INTERNAL) { + bRemoveWire = Standard_False; + continue; + } + // + const TopTools_ListOfShape& aLF = aDMELF.FindFromKey(aE); + bRemoveEdge = (aLF.Extent() == 1); + if (bRemoveEdge) { + aLIE.Append(aE); + } + else { + bRemoveWire = Standard_False; + } + } + // + if (bRemoveWire) { + aLIW.Append(aW); + } + else if (aLIE.Extent()) { + RemoveShapes(aW, aLIE); + } + } + // + if (aLIW.Extent()) { + RemoveShapes(aF, aLIW); + } + } +} + +//======================================================================= +// static methods implementation +//======================================================================= + +//======================================================================= +//function : RemoveShapes +//purpose : Removes the shapes from the shape +//======================================================================= +void RemoveShapes(TopoDS_Shape& theS, + const TopTools_ListOfShape& theLS) +{ + BRep_Builder aBB; + // + Standard_Boolean bFree = theS.Free(); + theS.Free(Standard_True); + // + TopTools_ListIteratorOfListOfShape aIt(theLS); + for (; aIt.More(); aIt.Next()) { + const TopoDS_Shape& aSI = aIt.Value(); + aBB.Remove(theS, aSI); + } + // + theS.Free(bFree); +} + +//======================================================================= +//function : UpDateTolerance +//purpose : +//======================================================================= +void UpdateTolerance (TopoDS_Shape& S, + const TopTools_IndexedMapOfShape& Faces) +{ + BRep_Builder B; + TopTools_MapOfShape View; + TopoDS_Vertex V[2]; + + // The edges of caps are not modified. + Standard_Integer j; + for (j = 1; j <= Faces.Extent(); j++) { + const TopoDS_Shape& F = Faces(j); + TopExp_Explorer Exp; + for (Exp.Init(F,TopAbs_EDGE); Exp.More(); Exp.Next()) { + View.Add(Exp.Current()); + } + } + + TopExp_Explorer Exp; + for (Exp.Init(S,TopAbs_EDGE); Exp.More(); Exp.Next()) { + TopoDS_Edge E = TopoDS::Edge(Exp.Current()); + if (View.Add(E)) { + Handle(BRepCheck_Edge) EdgeCorrector = new BRepCheck_Edge(E); + Standard_Real Tol = EdgeCorrector->Tolerance(); + B.UpdateEdge (E,Tol); + + // Update the vertices. + TopExp::Vertices(E,V[0],V[1]); + + for (Standard_Integer i = 0 ; i <=1 ; i++) { + if (View.Add(V[i])) { + Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(V[i].TShape()); + TV->Tolerance(0.); + Handle(BRepCheck_Vertex) VertexCorrector = new BRepCheck_Vertex(V[i]); + B.UpdateVertex (V[i],VertexCorrector->Tolerance()); + // use the occasion to clean the vertices. + (TV->ChangePoints()).Clear(); + } + B.UpdateVertex(V[i],Tol); + } + } + } +} + +//======================================================================= +//function : FindParameter +//purpose : +//======================================================================= +Standard_Boolean FindParameter(const TopoDS_Vertex& V, + const TopoDS_Edge& E, + Standard_Real& U) +{ + // Search the vertex in the edge + + Standard_Boolean rev = Standard_False; + TopoDS_Shape VF; + TopAbs_Orientation orient = TopAbs_INTERNAL; + + TopoDS_Iterator itv(E.Oriented(TopAbs_FORWARD)); + + // if the edge has no vertices + // and is degenerated use the vertex orientation + // RLE, june 94 + + if (!itv.More() && BRep_Tool::Degenerated(E)) { + orient = V.Orientation(); + } + + while (itv.More()) { + const TopoDS_Shape& Vcur = itv.Value(); + if (V.IsSame(Vcur)) { + if (VF.IsNull()) { + VF = Vcur; + } + else { + rev = E.Orientation() == TopAbs_REVERSED; + if (Vcur.Orientation() == V.Orientation()) { + VF = Vcur; + } + } + } + itv.Next(); + } + + if (!VF.IsNull()) orient = VF.Orientation(); + + Standard_Real f,l; + + if (orient == TopAbs_FORWARD) { + BRep_Tool::Range(E,f,l); + //return (rev) ? l : f; + U = (rev) ? l : f; + return Standard_True; + } + + else if (orient == TopAbs_REVERSED) { + BRep_Tool::Range(E,f,l); + //return (rev) ? f : l; + U = (rev) ? f : l; + return Standard_True; + } + + else { + TopLoc_Location L; + const Handle(Geom_Curve)& C = BRep_Tool::Curve(E,L,f,l); + L = L.Predivided(V.Location()); + if (!C.IsNull() || BRep_Tool::Degenerated(E)) { + BRep_ListIteratorOfListOfPointRepresentation itpr + ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points()); + + while (itpr.More()) { + const Handle(BRep_PointRepresentation)& pr = itpr.Value(); + if (pr->IsPointOnCurve(C,L)) { + Standard_Real p = pr->Parameter(); + Standard_Real res = p;// SVV 4 nov 99 - to avoid warnings on Linux + if (!C.IsNull()) { + // Closed curves RLE 16 june 94 + if (Precision::IsNegativeInfinite(f)) + { + //return pr->Parameter();//p; + U = pr->Parameter(); + return Standard_True; + } + if (Precision::IsPositiveInfinite(l)) + { + //return pr->Parameter();//p; + U = pr->Parameter(); + return Standard_True; + } + gp_Pnt Pf = C->Value(f).Transformed(L.Transformation()); + gp_Pnt Pl = C->Value(l).Transformed(L.Transformation()); + Standard_Real tol = BRep_Tool::Tolerance(V); + if (Pf.Distance(Pl) < tol) { + if (Pf.Distance(BRep_Tool::Pnt(V)) < tol) { + if (V.Orientation() == TopAbs_FORWARD) res = f;//p = f; + else res = l;//p = l; + } + } + } + //return res;//p; + U = res; + return Standard_True; + } + itpr.Next(); + } + } + else { + // no 3d curve !! + // let us try with the first pcurve + Handle(Geom2d_Curve) PC; + Handle(Geom_Surface) S; + BRep_Tool::CurveOnSurface(E,PC,S,L,f,l); + L = L.Predivided(V.Location()); + BRep_ListIteratorOfListOfPointRepresentation itpr + ((*((Handle(BRep_TVertex)*) &V.TShape()))->Points()); + + while (itpr.More()) { + const Handle(BRep_PointRepresentation)& pr = itpr.Value(); + if (pr->IsPointOnCurveOnSurface(PC,S,L)) { + Standard_Real p = pr->Parameter(); + // Closed curves RLE 16 june 94 + if (PC->IsClosed()) { + if ((p == PC->FirstParameter()) || + (p == PC->LastParameter())) { + if (V.Orientation() == TopAbs_FORWARD) p = PC->FirstParameter(); + else p = PC->LastParameter(); + } + } + //return p; + U = p; + return Standard_True; + } + itpr.Next(); + } + } + } + + //Standard_NoSuchObject::Raise("BRep_Tool:: no parameter on edge"); + return Standard_False; +} + +//======================================================================= +//function : GetEdgePoints +//purpose : gets the first, last and middle points of the edge +//======================================================================= +void GetEdgePoints(const TopoDS_Edge& anEdge, + const TopoDS_Face& aFace, + gp_Pnt& fPnt, gp_Pnt& mPnt, + gp_Pnt& lPnt) +{ + Standard_Real f, l; + Handle(Geom2d_Curve) theCurve = BRep_Tool::CurveOnSurface( anEdge, aFace, f, l ); + gp_Pnt2d fPnt2d = theCurve->Value(f); + gp_Pnt2d lPnt2d = theCurve->Value(l); + gp_Pnt2d mPnt2d = theCurve->Value(0.5*(f + l)); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + fPnt = aSurf->Value(fPnt2d.X(),fPnt2d.Y()); + lPnt = aSurf->Value(lPnt2d.X(),lPnt2d.Y()); + mPnt = aSurf->Value(mPnt2d.X(), mPnt2d.Y()); +} + +//======================================================================= +//function : FillContours +//purpose : fills free boundary contours and faces connected (MapEF) +//======================================================================= +void FillContours(const TopoDS_Shape& aShape, + const BRepOffset_Analyse& Analyser, + TopTools_DataMapOfShapeListOfShape& Contours, + TopTools_DataMapOfShapeShape& MapEF) +{ + TopTools_ListOfShape Edges; + + TopExp_Explorer Explo(aShape, TopAbs_FACE); + BRepTools_WireExplorer Wexp; + + for (; Explo.More(); Explo.Next()) + { + TopoDS_Face aFace = TopoDS::Face(Explo.Current()); + TopoDS_Iterator itf(aFace); + for (; itf.More(); itf.Next()) + { + TopoDS_Wire aWire = TopoDS::Wire(itf.Value()); + for (Wexp.Init(aWire, aFace); Wexp.More(); Wexp.Next()) + { + TopoDS_Edge anEdge = Wexp.Current(); + if (BRep_Tool::Degenerated(anEdge)) + continue; + const BRepOffset_ListOfInterval& Lint = Analyser.Type(anEdge); + if (!Lint.IsEmpty() && Lint.First().Type() == BRepOffset_FreeBoundary) + { + MapEF.Bind(anEdge, aFace); + Edges.Append(anEdge); + } + } + } + } + + TopTools_ListIteratorOfListOfShape itl; + while (!Edges.IsEmpty()) + { + TopoDS_Edge StartEdge = TopoDS::Edge(Edges.First()); + Edges.RemoveFirst(); + TopoDS_Vertex StartVertex, CurVertex; + TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True); + TopTools_ListOfShape aContour; + aContour.Append(StartEdge); + while (!CurVertex.IsSame(StartVertex)) + for (itl.Initialize(Edges); itl.More(); itl.Next()) + { + TopoDS_Edge anEdge = TopoDS::Edge(itl.Value()); + TopoDS_Vertex V1, V2; + TopExp::Vertices(anEdge, V1, V2); + if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex)) + { + aContour.Append(anEdge); + CurVertex = (V1.IsSame(CurVertex))? V2 : V1; + Edges.Remove(itl); + break; + } + } + Contours.Bind(StartVertex, aContour); + } +} + +//======================================================================= +//function : RemoveCorks +//purpose : +//======================================================================= +void RemoveCorks (TopoDS_Shape& S, + TopTools_IndexedMapOfShape& Faces) +{ + TopoDS_Compound SS; + BRep_Builder B; + B.MakeCompound (SS); + //----------------------------------------------------- + // Construction of a shape without caps. + // and Orientation of caps as in shape S. + //----------------------------------------------------- + TopExp_Explorer exp(S,TopAbs_FACE); + for (; exp.More(); exp.Next()) { + const TopoDS_Shape& Cork = exp.Current(); + if (!Faces.Contains(Cork)) { + B.Add(SS,Cork); + } + else { + //Faces.Remove (Cork); + //begin instead of Remove// + TopoDS_Shape LastShape = Faces(Faces.Extent()); + Faces.RemoveLast(); + if (Faces.FindIndex(Cork) != 0) + Faces.Substitute(Faces.FindIndex(Cork), LastShape); + //end instead of Remove // + Faces.Add(Cork); // to reset it with proper orientation. + } + } + S = SS; +#ifdef DRAW + if ( AffichOffCOld) + DBRep::Set("myInit", SS); +#endif + +} + +//======================================================================= +//function : IsConnectedShell +//purpose : +//======================================================================= +Standard_Boolean IsConnectedShell( const TopoDS_Shape& S ) +{ + BRepTools_Quilt Glue; + Glue.Add( S ); + + TopoDS_Shape SS = Glue.Shells(); + TopExp_Explorer Explo( SS, TopAbs_SHELL ); + Explo.Next(); + if (Explo.More()) + return Standard_False; + + return Standard_True; +} + +//======================================================================= +//function : MakeList +//purpose : +//======================================================================= +void MakeList (TopTools_ListOfShape& OffsetFaces, + const BRepAlgo_Image& myInitOffsetFace, + const TopTools_IndexedMapOfShape& myFaces) +{ + TopTools_ListIteratorOfListOfShape itLOF(myInitOffsetFace.Roots()); + for ( ; itLOF.More(); itLOF.Next()) { + const TopoDS_Shape& Root = itLOF.Value(); + if (myInitOffsetFace.HasImage(Root)) { + if (!myFaces.Contains(Root)) { + OffsetFaces.Append(myInitOffsetFace.Image(Root).First()); + } + } + } +} + +//======================================================================= +//function : EvalMax +//purpose : +//======================================================================= +void EvalMax(const TopoDS_Shape& S, + Standard_Real& Tol) +{ + TopExp_Explorer exp; + for (exp.Init(S,TopAbs_VERTEX); exp.More(); exp.Next()) { + const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current()); + Standard_Real TolV = BRep_Tool::Tolerance(V); + if (TolV > Tol) Tol = TolV; + } + //Patch + Tol *= 5.; +} + +//======================================================================= +//function : TrimEdge +//purpose : Trim the edge of the largest of descendants in AsDes2d. +// Order in AsDes two vertices that have trimmed the edge. +//======================================================================= +void TrimEdge(TopoDS_Edge& NE, + const Handle(BRepAlgo_AsDes)& AsDes2d, + Handle(BRepAlgo_AsDes)& AsDes) +{ + Standard_Real aSameParTol = Precision::Confusion(); + + TopoDS_Vertex V1,V2; + Standard_Real U = 0.; + Standard_Real UMin = Precision::Infinite(); + Standard_Real UMax = -UMin; + + const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE); + // + Standard_Boolean bTrim = Standard_False; + // + if (LE.Extent() > 1) { + TopTools_ListIteratorOfListOfShape it (LE); + for (; it.More(); it.Next()) { + TopoDS_Vertex V = TopoDS::Vertex(it.Value()); + if (NE.Orientation() == TopAbs_REVERSED) + V.Reverse(); + //V.Orientation(TopAbs_INTERNAL); + if (!FindParameter(V, NE, U)) { + Standard_Real f, l; + Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l); + gp_Pnt thePoint = BRep_Tool::Pnt(V); + GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve); + if (Projector.NbPoints() == 0) + Standard_ConstructionError::Raise("BRepOffset_MakeOffsetOld::TrimEdge no projection"); + U = Projector.LowerDistanceParameter(); + } + if (U < UMin) { + UMin = U; V1 = V; + } + if (U > UMax) { + UMax = U; V2 = V; + } + } + // + if (V1.IsNull() || V2.IsNull()) { + Standard_ConstructionError::Raise("BRepOffset_MakeOffsetOld::TrimEdge"); + } + if (!V1.IsSame(V2)) { + NE.Free( Standard_True ); + BRep_Builder B; + TopAbs_Orientation Or = NE.Orientation(); + NE.Orientation(TopAbs_FORWARD); + TopoDS_Vertex VF,VL; + TopExp::Vertices (NE,VF,VL); + B.Remove(NE,VF); + B.Remove(NE,VL); + B.Add (NE,V1.Oriented(TopAbs_FORWARD)); + B.Add (NE,V2.Oriented(TopAbs_REVERSED)); + B.Range(NE,UMin,UMax); + NE.Orientation(Or); + AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD)); + AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED)); + BRepLib::SameParameter(NE, aSameParTol, Standard_True); + // + bTrim = Standard_True; + } + } + // + if (!bTrim) { + if (!BRep_Tool::Degenerated(NE)) { + BRepAdaptor_Curve aBAC(NE); + if (!aBAC.IsClosed()) { + if (AsDes->HasAscendant(NE)) { + AsDes->Remove(NE); + } + } + } + } +} + +//======================================================================= +//function : SortFaces +//purpose : +//======================================================================= +void SortFaces(const TopTools_ListOfShape& theLIm, + TopTools_ListOfShape& theLFImages, + const Standard_Boolean bKeepFirst) +{ + Standard_Integer bKeep; // 1 - keep; -1 - remove + Standard_Boolean bFlag; + TopTools_IndexedDataMapOfShapeListOfShape aDMELF; + TopTools_ListOfShape aLFKeep, aLFLeft, aLFTmp; + TopTools_MapOfShape aMV; + TopTools_ListIteratorOfListOfShape aItLF; + TopExp_Explorer aExp; + // + aLFLeft = theLIm; + // + bKeep = bKeepFirst ? 1 : -1; + for (;;) { + aLFTmp = aLFLeft; + // + aLFLeft.Clear(); + aLFKeep.Clear(); + aDMELF.Clear(); + // + // map list of images edge - faces + aItLF.Initialize(aLFTmp); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); + TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF); + } + // + // find images that have edge attached to only one face + aItLF.Initialize(aLFTmp); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); + aExp.Init(aFIm, TopAbs_EDGE); + for (bFlag = Standard_False; aExp.More(); aExp.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current(); + const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE); + if (aLEF.Extent() == 1) { + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(aE, aV1, aV2); + aMV.Add(aV1); + aMV.Add(aV2); + // + bFlag = Standard_True; + } + } + // + if (bFlag) { + aLFKeep.Append(aFIm); + } + else { + aLFLeft.Append(aFIm); + } + } + // + // map shapes left for processing + aDMELF.Clear(); + aLFTmp = aLFLeft; + aLFLeft.Clear(); + // + aItLF.Initialize(aLFTmp); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); + TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF); + } + // + // find outer edges and check if they touch the first part of edges + aItLF.Initialize(aLFTmp); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); + aExp.Init(aFIm, TopAbs_EDGE); + for (bFlag = Standard_False; aExp.More() && !bFlag; aExp.Next()) { + const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current(); + const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE); + if (aLEF.Extent() == 1) { + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(aE, aV1, aV2); + // + bFlag = aMV.Contains(aV1) || aMV.Contains(aV2); + } + } + // + if (bFlag) { + aLFKeep.Append(aFIm); + } + else { + aLFLeft.Append(aFIm); + } + } + // + if (bKeep == 1) { + // aLFKeep should be kept + // aLFLeft left for further processing + aItLF.Initialize(aLFKeep); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); + theLFImages.Append(aFIm); + } + } + // + if (aLFLeft.IsEmpty()) { + break; + } + // + bKeep *= -1; + } +} + +//======================================================================= +//function : FindShape +//purpose : +//======================================================================= +Standard_Boolean FindShape(const TopoDS_Shape& theSWhat, + const TopoDS_Shape& theSWhere, + TopoDS_Shape& theRes) +{ + Standard_Boolean bFound = Standard_False; + TopAbs_ShapeEnum aType = theSWhat.ShapeType(); + TopExp_Explorer aExp(theSWhere, aType); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Shape& aS = aExp.Current(); + if (aS.IsSame(theSWhat)) { + theRes = aS; + bFound = Standard_True; + break; + } + } + return bFound; +} + +//======================================================================= +//function : UpdateOrigins +//purpose : +//======================================================================= +void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins, + BOPAlgo_Builder& theGF) +{ + TopTools_ListOfShape aLSTmp; + TopTools_MapOfShape aMFence; + BOPCol_ListIteratorOfListOfShape aItA; + TopTools_ListIteratorOfListOfShape aIt, aIt1; + // + const BOPCol_ListOfShape& aLSU = theGF.Arguments(); + aItA.Initialize(aLSU); + for (; aItA.More(); aItA.Next()) { + const TopoDS_Shape& aS = aItA.Value(); + // + if (!theOrigins.Contains(aS)) { + continue; + } + // + const TopTools_ListOfShape& aLSIm = theGF.Modified(aS); + if (aLSIm.IsEmpty()) { + continue; + } + // + const TopTools_ListOfShape& aLS = theOrigins.FindFromKey(aS); + // + aIt.Initialize(aLSIm); + for (; aIt.More(); aIt.Next()) { + const TopoDS_Shape& aSIm = aIt.Value(); + // + if (!theOrigins.Contains(aSIm)) { + theOrigins.Add(aSIm, aLS); + continue; + } + // + aMFence.Clear(); + // + TopTools_ListOfShape& aLS1 = theOrigins.ChangeFromKey(aSIm); + aLSTmp.Assign(aLS1); + // + aLS1.Clear(); + aIt1.Initialize(aLSTmp); + for (; aIt1.More(); aIt1.Next()) { + const TopoDS_Shape& aS1 = aIt1.Value(); + if (aMFence.Add(aS1)) { + aLS1.Append(aS1); + } + } + // + aIt1.Initialize(aLS); + for (; aIt1.More(); aIt1.Next()) { + const TopoDS_Shape& aS1 = aIt1.Value(); + if (aMFence.Add(aS1)) { + aLS1.Append(aS1); + } + } + } + } +} + +//======================================================================= +//function : IsMicroEdge +//purpose : +//======================================================================= +Standard_Boolean IsMicroEdge(const TopoDS_Edge& theEdge, + const Handle(IntTools_Context)& theCtx) +{ + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(theEdge, aV1, aV2); + Standard_Boolean bNull = aV1.IsNull() || aV2.IsNull(); + if (bNull) { + return Standard_False; + } + // + Standard_Boolean bMicro; + Standard_Real aT1, aT2; + IntTools_ShrunkRange aSR; + // + BRepAdaptor_Curve aBAC(theEdge); + // + aT1 = BRep_Tool::Parameter(aV1, theEdge); + aT2 = BRep_Tool::Parameter(aV2, theEdge); + if (aT2 < aT1) { + Standard_Real aTmp = aT1; + aT1 = aT2; + aT2 = aTmp; + } + // + aSR.SetContext(theCtx); + aSR.SetData(theEdge, aT1, aT2, aV1, aV2); + aSR.Perform(); + bMicro = (aSR.ErrorStatus() != 0); + if (!bMicro) { + Standard_Real anEps, aTS1, aTS2, aTolV1, aTolV2; + // + aTolV1 = BRep_Tool::Tolerance(aV1); + aTolV2 = BRep_Tool::Tolerance(aV2); + // + anEps = aBAC.Resolution(aTolV1 + aTolV2); + if (anEps < 1.e-8) { + anEps = 1.e-8; + } + // + aSR.ShrunkRange(aTS1, aTS2); + bMicro = (aTS2 - aTS1) <= anEps; + } + // + if (bMicro) { + if (aBAC.GetType() == GeomAbs_Line) { + BRep_Builder aBB; + Standard_Real aLen = CPnts_AbscissaPoint::Length(aBAC); + // + aBB.UpdateVertex(aV1, aLen/2.); + aBB.UpdateVertex(aV2, aLen/2.); + } + } + // + return bMicro; +} + +//======================================================================= +//function : ComputeBiNormal +//purpose : +//======================================================================= +Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF, + const TopoDS_Edge& theE, + gp_Dir& theDB) +{ + Standard_Boolean bDone = Standard_False; + Standard_Real aT1, aT2, aTm; + // + const Handle(Geom2d_Curve)& aC2d = + BRep_Tool::CurveOnSurface(theE, theF, aT1, aT2); + if (aC2d.IsNull()) { + return bDone; + } + // + gp_Pnt2d aP2dNear; + gp_Pnt aP, aPNear; + // + const Handle(Geom_Curve)& aC3d = + BRep_Tool::Curve(theE, aT1, aT2); + // + aTm = (aT1 + aT2) * 0.5; + aP = aC3d->Value(aTm); + // + BOPTools_AlgoTools3D::PointNearEdge(theE, theF, aTm, 1.e-5, aP2dNear, aPNear); + // + gp_Vec aVB(aP, aPNear); + theDB = gp_Dir(aVB); + return !bDone; +} + +//======================================================================= +//function : CheckBiNormals +//purpose : +//======================================================================= +Standard_Boolean CheckBiNormals + (const TopoDS_Face& aFIm, + const TopoDS_Face& aFOr, + const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins, + const TopTools_MapOfShape& theMFence, + Standard_Boolean& bKeep, + Standard_Boolean& bRemove, + const Standard_Boolean RemoveInvalidFaces) +{ + Standard_Boolean bChecked; + Standard_Integer aNbEdgesChecked; + Standard_Real anAngle; + TopTools_IndexedMapOfShape aMEInv; + // + aNbEdgesChecked = 0; + // + const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm); + TopExp_Explorer aExp(aWIm, TopAbs_EDGE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current(); + // + if (BRep_Tool::Degenerated(aEIm)) { + continue; + } + // + if (!theOrigins.Contains(aEIm)) { + continue; + } + // + const TopTools_ListOfShape& aLEOr = theOrigins.FindFromKey(aEIm); + const TopoDS_Shape& aSOr = aLEOr.First(); + if (aSOr.ShapeType() != TopAbs_EDGE) { + continue; + } + // + if (aLEOr.Extent() > 1) { + TopTools_MapOfShape aME, aMV; + Standard_Integer aNbE, aNbV; + // + TopTools_ListIteratorOfListOfShape aItLS(aLEOr); + for (; aItLS.More(); aItLS.Next()) { + const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aItLS.Value(); + aME.Add(aEOr); + // + TopExp_Explorer aExpE(aEOr, TopAbs_VERTEX); + for (; aExpE.More(); aExpE.Next()) { + const TopoDS_Shape& aV = aExpE.Current(); + aMV.Add(aV); + } + } + // + aNbV = aMV.Extent(); + aNbE = aME.Extent(); + // + if ((aNbE > 1) && (aNbV == 2*aNbE)) { + continue; + } + } + // + if (!RemoveInvalidFaces) { + if (theMFence.Contains(aEIm)) { + bChecked = Standard_True; + bKeep = Standard_True; + bRemove = Standard_False; + return bChecked; + } + } + // + const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aLEOr.First(); + // + TopoDS_Edge aEOrF; + if (!FindShape(aEOr, aFOr, aEOrF)) { + continue; + } + // + // compute bi-normal for face aFIm on the edge aEIm + gp_Dir aDB1; + if (!ComputeBiNormal(aFIm, aEIm, aDB1)) { + continue; + } + // + // compute bi-normal for face aFOr on the edge aEOrF + gp_Dir aDB2; + if (!ComputeBiNormal(aFOr, aEOrF, aDB2)) { + continue; + } + // + ++aNbEdgesChecked; + // + anAngle = aDB1.Angle(aDB2); + if (Abs(anAngle - M_PI) < 1.e-4) { + aMEInv.Add(aEIm); + } + } + // + bChecked = (aNbEdgesChecked > 0); + if (!bChecked) { + return bChecked; + } + // + // decide whether to remove the split face or not + bKeep = Standard_True; + bRemove = Standard_False; + // + Standard_Integer aNb = aMEInv.Extent(); + if (aNb == 0) { + return bChecked; + } + // + if (aNb == aNbEdgesChecked) { + bKeep = Standard_False; + bRemove = Standard_True; + } + // + if (!bRemove) { + for (Standard_Integer i = 1; i <= aNb; ++i) { + const TopoDS_Shape& aE = aMEInv(i); + if (theMFence.Contains(aE)) { + bKeep = Standard_False; + bRemove = Standard_True; + break; + } + } + } + // + return bChecked; +} + +//======================================================================= +//function : CheckBiNormals +//purpose : +//======================================================================= +void CheckBiNormals + (TopTools_ListOfShape& theLFImages, + const TopoDS_Face& theF, + const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins, + TopTools_ListOfShape& theLFKeep, + const Standard_Boolean RemoveInvalidFaces) +{ + Standard_Boolean bChecked, bKeep, bRem; + Standard_Integer i, aNb; + TopTools_ListOfShape aLFKeep; + TopTools_MapOfShape aMEToKeep; + TopTools_IndexedDataMapOfShapeListOfShape aDMELF; + TopTools_ListIteratorOfListOfShape aItLF; + // + // collect outer edges + aItLF.Initialize(theLFImages); + for (; aItLF.More(); aItLF.Next()) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); + TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF); + } + // + aNb = aDMELF.Extent(); + for (i = 1; i <= aNb; ++i) { + const TopTools_ListOfShape& aLF = aDMELF(i); + if (aLF.Extent() == 1) { + const TopoDS_Shape& aE = aDMELF.FindKey(i); + aMEToKeep.Add(aE); + } + } + // + const TopoDS_Face& aFOr = *(TopoDS_Face*)&theOrigins.FindFromKey(theF).First(); + // + aItLF.Initialize(theLFImages); + for (; aItLF.More(); ) { + const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value(); + // + bChecked = CheckBiNormals(aFIm, aFOr, theOrigins, aMEToKeep, bKeep, bRem, RemoveInvalidFaces); + // + if (bChecked) { + if (bRem) { + theLFImages.Remove(aItLF); + } + else { + if (bKeep) { + theLFKeep.Append(aFIm); + } + aItLF.Next(); + } + } + else { + aItLF.Next(); + } + } +} + +//======================================================================= +//function : CheckNormals +//purpose : +//======================================================================= +Standard_Boolean CheckNormals(const TopoDS_Face& theFIm, + const TopoDS_Face& theFOr) +{ + + Standard_Real aUMin, aUMax, aVMin, aVMax, aU, aV, anAngle; + gp_Pnt aP; + gp_Vec aVecU, aVecV, aVNIm, aVNOr; + Standard_Boolean bIsCollinear; + // + BRepAdaptor_Surface aSFIm(theFIm), aSFOr(theFOr); + // + aUMin = aSFIm.FirstUParameter(); + aUMax = aSFIm.LastUParameter(); + aVMin = aSFIm.FirstVParameter(); + aVMax = aSFIm.LastVParameter(); + // + aU = (aUMin + aUMax) * 0.5; + if (Precision::IsInfinite(aUMin) && + Precision::IsInfinite(aUMax)) { + aU = 0.; + } + else if (Precision::IsInfinite(aUMin) && + !Precision::IsInfinite(aUMax)) { + aU = aUMax; + } + else if (!Precision::IsInfinite(aUMin) && + Precision::IsInfinite(aUMax)) { + aU = aUMin; + } + // + aV = (aVMin + aVMax) * 0.5; + if (Precision::IsInfinite(aVMin) && + Precision::IsInfinite(aVMax)) { + aV = 0.; + } + else if (Precision::IsInfinite(aVMin) && + !Precision::IsInfinite(aVMax)) { + aV = aVMax; + } + else if (!Precision::IsInfinite(aVMin) && + Precision::IsInfinite(aVMax)) { + aV = aVMin; + } + // + aSFIm.D1(aU, aV, aP, aVecU, aVecV); + aVNIm = aVecU.Crossed(aVecV); + if (theFIm.Orientation() == TopAbs_REVERSED) { + aVNIm.Reverse(); + } + // + aSFOr.D1(aU, aV, aP, aVecU, aVecV); + aVNOr = aVecU.Crossed(aVecV); + if (theFOr.Orientation() == TopAbs_REVERSED) { + aVNOr.Reverse(); + } + // + anAngle = aVNIm.Angle(aVNOr); + bIsCollinear = (anAngle < Precision::Confusion()); + return bIsCollinear; +} + +//======================================================================= +//function : UpdateInitOffset +//purpose : Update and cleaning of myInitOffset +//======================================================================= +void UpdateInitOffset(BRepAlgo_Image& myInitOffset, + BRepAlgo_Image& myImageOffset, + const TopoDS_Shape& myOffsetShape, + const TopAbs_ShapeEnum &theShapeType) // skv +{ + BRepAlgo_Image NIOF; + const TopTools_ListOfShape& Roots = myInitOffset.Roots(); + TopTools_ListIteratorOfListOfShape it(Roots); + for (; it.More(); it.Next()) { + NIOF.SetRoot (it.Value()); + } + for (it.Initialize(Roots); it.More(); it.Next()) { + const TopoDS_Shape& SI = it.Value(); + TopTools_ListOfShape LI; + TopTools_ListOfShape L1; + myInitOffset.LastImage(SI,L1); + TopTools_ListIteratorOfListOfShape itL1(L1); + for (; itL1.More(); itL1.Next()) { + const TopoDS_Shape& O1 = itL1.Value(); + TopTools_ListOfShape L2; + myImageOffset.LastImage(O1,L2); + LI.Append(L2); + } + NIOF.Bind(SI,LI); + } +// Modified by skv - Mon Apr 4 18:17:27 2005 Begin +// Supporting history. +// NIOF.Filter(myOffsetShape,TopAbs_FACE); + NIOF.Filter(myOffsetShape, theShapeType); +// Modified by skv - Mon Apr 4 18:17:27 2005 End + myInitOffset = NIOF; +} +//======================================================================= +//function : IsPlanar +//purpose : +//======================================================================= +Standard_Boolean IsPlanar(const TopoDS_Shape& theS) +{ + TopExp_Explorer aExp(theS, TopAbs_FACE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current(); + BRepAdaptor_Surface aBAS(aF, Standard_False); + if (aBAS.GetType() != GeomAbs_Plane) { + break; + } + } + return !aExp.More(); +} \ No newline at end of file diff --git a/src/BRepTest/BRepTest_FeatureCommands.cxx b/src/BRepTest/BRepTest_FeatureCommands.cxx index 0278b40cb1..fbab3f47a0 100644 --- a/src/BRepTest/BRepTest_FeatureCommands.cxx +++ b/src/BRepTest/BRepTest_FeatureCommands.cxx @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include @@ -902,6 +904,7 @@ Standard_Integer offsetshape(Draw_Interpretor& , } static BRepOffset_MakeOffset TheOffset; +static BRepOffset_MakeOffsetOld TheOffsetOld; static Standard_Real TheRadius; static Standard_Boolean theYaBouchon; static Standard_Real TheTolerance = Precision::Confusion(); @@ -909,12 +912,13 @@ static Standard_Boolean TheInter = Standard_False; static GeomAbs_JoinType TheJoin = GeomAbs_Arc; static Standard_Boolean RemoveIntEdges = Standard_False; static Standard_Boolean RemoveInvalidFaces = Standard_False; +static Standard_Boolean UseNewOffsetAPI = Standard_False; Standard_Integer offsetparameter(Draw_Interpretor& di, Standard_Integer n, const char** a) { if ( n == 1 ) { - di << " OffsetParameter Tol Inter(c/p) JoinType(a/i/t) [RemoveInternalEdges(r/k) RemoveInvalidFaces(r/k)] " << "\n"; + di << " OffsetParameter Tol Inter(c/p) JoinType(a/i/t) [RemoveInternalEdges(r/k) RemoveInvalidFaces(r/k) UseNewOffsetAPI(n/o)] " << "\n"; di << " Current Values" << "\n"; di << " --> Tolerance : " << TheTolerance << "\n"; di << " --> TheInter : "; @@ -947,6 +951,13 @@ Standard_Integer offsetparameter(Draw_Interpretor& di, else { di << "Keep"; } + di << "\n" << " --> Version of the Offset API : "; + if (UseNewOffsetAPI) { + di << "New"; + } + else { + di << "Old"; + } di << "\n"; // return 0; @@ -962,7 +973,8 @@ Standard_Integer offsetparameter(Draw_Interpretor& di, else if ( !strcmp(a[3],"t")) TheJoin = GeomAbs_Tangent; // RemoveIntEdges = (n >= 5) ? !strcmp(a[4], "r") : Standard_False; - RemoveInvalidFaces = (n == 6) ? !strcmp(a[5], "r") : Standard_False; + RemoveInvalidFaces = (n >= 6) ? !strcmp(a[5], "r") : Standard_False; + UseNewOffsetAPI = (n == 7) ? !strcmp(a[6], "n") : Standard_False; // return 0; } @@ -983,16 +995,26 @@ Standard_Integer offsetload(Draw_Interpretor& , Standard_Real Of = Draw::Atof(a[2]); TheRadius = Of; // Standard_Boolean Inter = Standard_True; - - TheOffset.Initialize(S,Of,TheTolerance,BRepOffset_Skin,TheInter,0,TheJoin, - Standard_False, RemoveIntEdges, RemoveInvalidFaces); + if (UseNewOffsetAPI) { + TheOffset.Initialize(S,Of,TheTolerance,BRepOffset_Skin,TheInter,0,TheJoin, + Standard_False, RemoveIntEdges, RemoveInvalidFaces); + } + else { + TheOffsetOld.Initialize(S,Of,TheTolerance,BRepOffset_Skin,TheInter,0,TheJoin, + Standard_False, RemoveIntEdges, RemoveInvalidFaces); + } //------------------------------------------ // recuperation et chargement des bouchons. //---------------------------------------- for (Standard_Integer i = 3 ; i < n; i++) { TopoDS_Shape SF = DBRep::Get(a[i],TopAbs_FACE); if (!SF.IsNull()) { - TheOffset.AddFace(TopoDS::Face(SF)); + if (UseNewOffsetAPI) { + TheOffset.AddFace(TopoDS::Face(SF)); + } + else { + TheOffsetOld.AddFace(TopoDS::Face(SF)); + } } } if (n < 4) theYaBouchon = Standard_False; //B.MakeOffsetShape(); @@ -1015,7 +1037,12 @@ Standard_Integer offsetonface(Draw_Interpretor&, Standard_Integer n, const char* TopoDS_Shape SF = DBRep::Get(a[i],TopAbs_FACE); if (!SF.IsNull()) { Standard_Real Of = Draw::Atof(a[i+1]); - TheOffset.SetOffsetOnFace(TopoDS::Face(SF),Of); + if (UseNewOffsetAPI) { + TheOffset.SetOffsetOnFace(TopoDS::Face(SF),Of); + } + else { + TheOffsetOld.SetOffsetOnFace(TopoDS::Face(SF),Of); + } } } @@ -1032,20 +1059,34 @@ Standard_Integer offsetperform(Draw_Interpretor& theCommands, { if ( theNArg < 2) return 1; - if (theYaBouchon) - TheOffset.MakeThickSolid (); - else - TheOffset.MakeOffsetShape(); + if (UseNewOffsetAPI) { + if (theYaBouchon) + TheOffset.MakeThickSolid (); + else + TheOffset.MakeOffsetShape(); - if(TheOffset.IsDone()) - { - DBRep::Set(a[1],TheOffset.Shape()); + if(TheOffset.IsDone()) { + DBRep::Set(a[1],TheOffset.Shape()); } - else - { - theCommands << "ERROR. offsetperform operation not done."; - return 1; + else { + theCommands << "ERROR. offsetperform operation not done."; + return 1; } + } + else { + if (theYaBouchon) + TheOffsetOld.MakeThickSolid (); + else + TheOffsetOld.MakeOffsetShape(); + + if(TheOffsetOld.IsDone()) { + DBRep::Set(a[1],TheOffsetOld.Shape()); + } + else { + theCommands << "ERROR. offsetperform operation not done."; + return 1; + } + } return 0; } -- 2.39.5