diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx new file mode 100644 index 0000000000..959110d33d --- /dev/null +++ b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx @@ -0,0 +1,746 @@ +// Created on: 2012-08-06 +// Created by: jgv@ROLEX +// Copyright (c) 2012-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. + + +#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 + +static void UpdateEdgeByProjectionOfPCurve(TopoDS_Edge& anEdge, + const TopoDS_Face& aNewFace, + const TopoDS_Face& aBoundedNewFace) +{ + BRep_Builder BB; + Standard_Real fpar, lpar; + + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge,fpar,lpar); + + Handle(Geom_Surface) NewSurf = BRep_Tool::Surface(aNewFace); + Handle(ShapeAnalysis_Surface) SAS = new ShapeAnalysis_Surface(NewSurf); + ShapeConstruct_ProjectCurveOnSurface aToolProj; + aToolProj.Init(SAS, Precision::Confusion()); + Handle(Geom2d_Curve) NewPCurve; + aToolProj.Perform(aCurve,fpar,lpar,NewPCurve); + Standard_Real TolReached = SAS->Gap(); + //BB.UpdateEdge(anEdge, NullPCurve, aFace, 0.); + BB.UpdateEdge(anEdge, NewPCurve, aBoundedNewFace, TolReached); + TopoDS_Vertex V1, V2; + TopExp::Vertices(anEdge, V1, V2); + BB.UpdateVertex(V1, TolReached); + BB.UpdateVertex(V2, TolReached); +} + +static void ProjectVertexOnNewEdge(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge, + const TopoDS_Edge& theNewEdge, + Standard_Real& theParam, + gp_Pnt& thePnt) +{ + Standard_Real ParamOnEdge = BRep_Tool::Parameter(theVertex, theEdge); + BRepAdaptor_Curve BAcurve(theEdge); + BRepAdaptor_Curve BAnewcurve(theNewEdge); + gp_Pnt PointOnEdge = BAcurve.Value(ParamOnEdge); + Extrema_ExtPC Projector(PointOnEdge, BAnewcurve); + Standard_Real Param[4], dist[4]; + gp_Pnt Pnt[4]; + Param[1] = BAnewcurve.FirstParameter(); + Param[2] = BAnewcurve.LastParameter(); + Projector.TrimmedSquareDistances(dist[1], dist[2], Pnt[1], Pnt[2]); + dist[3] = RealLast(); + if (Projector.IsDone() && Projector.NbExt() > 0) + { + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= Projector.NbExt(); i++) + if (Projector.SquareDistance(i) < Projector.SquareDistance(imin)) + imin = i; + Param[3] = Projector.Point(imin).Parameter(); + dist[3] = Projector.SquareDistance(imin); + Pnt[3] = Projector.Point(imin).Value(); + } + + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= 3; i++) + if (dist[i] < dist[imin]) + imin = i; + + theParam = Param[imin]; + thePnt = Pnt[imin]; +} + +static TopoDS_Edge GetGeneratedEdge(const TopoDS_Edge& anEdge, + const TopoDS_Face& aFace, + const TopoDS_Face& aNewFace) +{ + TopoDS_Edge NewEdge; + + TopExp_Explorer Explo(aFace, TopAbs_EDGE); + TopExp_Explorer ExploNew(aNewFace, TopAbs_EDGE); + for (; Explo.More(); Explo.Next(),ExploNew.Next()) + { + const TopoDS_Shape& EdgeInFace = Explo.Current(); + //const TopoDS_Shape& EdgeInNewFace = ExploNew.Current(); + if (anEdge == EdgeInFace) + { + NewEdge = TopoDS::Edge(ExploNew.Current()); + break; + } + } + return NewEdge; +} + +static TopAbs_Orientation OrientationInEdge(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge) +{ + TopoDS_Vertex V1, V2; + TopExp::Vertices(theEdge, V1, V2); + if (theVertex.IsSame(V1)) + return TopAbs_FORWARD; + + return TopAbs_REVERSED; +} + +static Standard_Boolean EdgeContains(const TopoDS_Edge& theEdge, + const TopoDS_Vertex& theVertex) +{ + TopoDS_Iterator ite(theEdge); + for (; ite.More(); ite.Next()) + if (theVertex.IsSame(ite.Value())) + return Standard_True; + + return Standard_False; +} + + +static Standard_Boolean IsTangentFaces(const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace1, + const TopoDS_Face& theFace2, + const GeomAbs_Shape Order) +{ + if (Order == GeomAbs_G1 && + BRep_Tool::Continuity( theEdge, theFace1, theFace2 ) != GeomAbs_C0) + return Standard_True; + + Standard_Real TolC0 = Max(0.001, 1.5*BRep_Tool::Tolerance(theEdge)); + + Standard_Real aFirst; + Standard_Real aLast; + +// Obtaining of pcurves of edge on two faces. + const Handle(Geom2d_Curve) aC2d1 = BRep_Tool::CurveOnSurface + (theEdge, theFace1, aFirst, aLast); + const Handle(Geom2d_Curve) aC2d2 = BRep_Tool::CurveOnSurface + (theEdge, theFace2, aFirst, aLast); + if (aC2d1.IsNull() || aC2d2.IsNull()) + return Standard_False; + +// Obtaining of two surfaces from adjacent faces. + Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(theFace1); + Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(theFace2); + + if (aSurf1.IsNull() || aSurf2.IsNull()) + return Standard_False; + +// Computation of the number of samples on the edge. + BRepAdaptor_Surface aBAS1(theFace1); + BRepAdaptor_Surface aBAS2(theFace2); + Handle(BRepAdaptor_HSurface) aBAHS1 = new BRepAdaptor_HSurface(aBAS1); + Handle(BRepAdaptor_HSurface) aBAHS2 = new BRepAdaptor_HSurface(aBAS2); + Handle(BRepTopAdaptor_TopolTool) aTool1 = new BRepTopAdaptor_TopolTool(aBAHS1); + Handle(BRepTopAdaptor_TopolTool) aTool2 = new BRepTopAdaptor_TopolTool(aBAHS2); + Standard_Integer aNbSamples1 = aTool1->NbSamples(); + Standard_Integer aNbSamples2 = aTool2->NbSamples(); + Standard_Integer aNbSamples = Max(aNbSamples1, aNbSamples2); + + +// Computation of the continuity. + Standard_Real aPar; + Standard_Real aDelta = (aLast - aFirst)/(aNbSamples - 1); + Standard_Integer i, nbNotDone = 0; + + for (i = 1, aPar = aFirst; i <= aNbSamples; i++, aPar += aDelta) { + if (i == aNbSamples) aPar = aLast; + + LocalAnalysis_SurfaceContinuity aCont(aC2d1, aC2d2, aPar, + aSurf1, aSurf2, Order, + 0.001, TolC0, 0.1, 0.1, 0.1); + if (!aCont.IsDone()) + { + nbNotDone++; + continue; + } + + if (Order == GeomAbs_G1) + { + if (!aCont.IsG1()) + return Standard_False; + } + else if (!aCont.IsG2()) + return Standard_False; + } + + if (nbNotDone == aNbSamples) + return Standard_False; + + return Standard_True; +} + +//======================================================================= +//function : BRepOffsetAPI_PatchFaces +//purpose : Constructor +//======================================================================= + +BRepOffsetAPI_PatchFaces::BRepOffsetAPI_PatchFaces(const TopoDS_Shape& theShape) +{ + myInitialShape = theShape; +} + +//======================================================================= +//function : SetOffsetFace +//purpose : +//======================================================================= +void BRepOffsetAPI_PatchFaces::AddPatchFace(const TopoDS_Face& theFace, + const TopoDS_Face& thePatchFace) +{ + // Check the orientation of the patch face and make + // it oriented the same way as original + TopoDS_Face aFace = TopoDS::Face(theFace.Oriented(TopAbs_FORWARD)); + TopoDS_Face aPatchFace = TopoDS::Face(thePatchFace.Oriented(TopAbs_FORWARD)); + + Handle(IntTools_Context) aCtx = new IntTools_Context; + Standard_Boolean bToReverse = BOPTools_AlgoTools::IsSplitToReverse(aFace, aPatchFace, aCtx); + TopoDS_Face anOrientedPatchFace = bToReverse ? TopoDS::Face(aPatchFace.Reversed()) : aPatchFace; + myFacePatchFace.Add(aFace, anOrientedPatchFace); +} + +//======================================================================= +//function : Build +//purpose : +//======================================================================= + +void BRepOffsetAPI_PatchFaces::Build() +{ + TopExp::MapShapesAndUniqueAncestors(myInitialShape, TopAbs_EDGE, TopAbs_FACE, myEFmap); + + //Draft filling of + for (Standard_Integer i = 1; i <= myFacePatchFace.Extent(); i++) + { + const TopoDS_Face& aFace = TopoDS::Face(myFacePatchFace.FindKey(i)); + const TopoDS_Shape& aPatchFace = myFacePatchFace(i); + myFaceNewFace.Add(aFace, aPatchFace); + TopExp_Explorer Explo(aFace, TopAbs_EDGE); + for (; Explo.More(); Explo.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); + const TopTools_ListOfShape& Lfaces = myEFmap.FindFromKey(anEdge); + TopoDS_Face aNeighborFace = (aFace.IsSame(Lfaces.First()))? + TopoDS::Face(Lfaces.Last()) : TopoDS::Face(Lfaces.First()); + if (myFacePatchFace.Contains(aNeighborFace)) + continue; + if (myFaceNewFace.Contains(aNeighborFace)) + continue; + Standard_Boolean IsTangentEdge = IsTangentFaces(anEdge, aFace, aNeighborFace, GeomAbs_G1); + if (IsTangentEdge) + { + myTangentEdges.Add(anEdge); + continue; + } + + aNeighborFace.Orientation(TopAbs_FORWARD); + TopoDS_Face aNewFace; + BRepOffset_Tool::EnLargeFace(aNeighborFace, aNewFace, + Standard_True,Standard_True,Standard_True,Standard_True,Standard_True); + myFaceNewFace.Add(aNeighborFace, aNewFace); + } + } + + //Make draft intersection edges: draft filling of + BRep_Builder BB; + TopTools_MapOfShape UpdatedConstEdges; + for (Standard_Integer i = 1; i <= myFaceNewFace.Extent(); i++) + { + TopoDS_Face aFace = TopoDS::Face(myFaceNewFace.FindKey(i)); + TopoDS_Face aNewFace = TopoDS::Face(myFaceNewFace(i)); + TopoDS_Face aBoundedNewFace; + if (myNewFaceBoundedFace.IsBound(aNewFace)) + aBoundedNewFace = TopoDS::Face(myNewFaceBoundedFace(aNewFace)); + else + { + aBoundedNewFace = TopoDS::Face(aNewFace.EmptyCopied()); + myNewFaceBoundedFace.Bind(aNewFace, aBoundedNewFace); + } + + TopoDS_Iterator itf(aFace); + for (; itf.More(); itf.Next()) + { + const TopoDS_Wire& aWire = TopoDS::Wire(itf.Value()); + TopoDS_Wire F_Wire = TopoDS::Wire(aWire.Oriented(TopAbs_FORWARD)); + BRepTools_WireExplorer wexp(F_Wire, aFace); + for (; wexp.More(); wexp.Next()) + { + TopoDS_Edge anEdge = wexp.Current(); + Standard_Boolean ToReverse = Standard_False; + TopoDS_Edge aNewEdge; + if (myEdgeNewEdge.IsBound(anEdge)) + //aNewEdge = TopoDS::Edge(myEdgeNewEdge(anEdge)); + continue; + + Handle(Geom2d_Curve) NullPCurve; + Standard_Real fpar, lpar; + + const TopTools_ListOfShape& Lfaces = myEFmap.FindFromKey(anEdge); + if (Lfaces.Extent() == 1) //seam edge + { + cout< smooth edge"< smooth edge"< ? + //myFaceNewFace.RemoveKey(aNeighborFace); + + myTangentEdges.Add(anEdge); + UpdatedConstEdges.Add(anEdge); + } + else + { + Handle(Geom2d_Curve) aPCurve1 = BRep_Tool::CurveOnSurface(anEdge, aFace, fpar, lpar); + //BB.UpdateEdge(anEdge, NullPCurve, aFace, 0.); + BB.UpdateEdge(anEdge, aPCurve1, aBoundedNewFace, 0.); + Handle(Geom2d_Curve) aPCurve2 = BRep_Tool::CurveOnSurface(anEdge, aNeighborFace, fpar, lpar); + //BB.UpdateEdge(anEdge, NullPCurve, aNeighborFace, 0.); + BB.UpdateEdge(anEdge, aPCurve2, aBoundedNewNeighborFace, 0.); + + //aNewEdge = anEdge; + mySmoothEdges.Add(anEdge); + } + continue; + } + TopoDS_Vertex V1, V2; + TopExp::Vertices(aNewEdge, V1, V2); + aNewEdge.Free(Standard_True); + BB.Remove(aNewEdge, V1); + if (!V2.IsSame(V1)) + BB.Remove(aNewEdge, V2); + aNewEdge.Orientation(TopAbs_FORWARD); + + //Make pcurves on new surfaces + Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(aNewEdge, aNewFace, fpar, lpar); + BB.UpdateEdge(aNewEdge, NullPCurve, aNewFace, 0.); + BB.UpdateEdge(aNewEdge, PCurve1, aBoundedNewFace, 0.); + Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(aNewEdge, aNewNeighborFace, fpar, lpar); + BB.UpdateEdge(aNewEdge, NullPCurve, aNewNeighborFace, 0.); + BB.UpdateEdge(aNewEdge, PCurve2, aBoundedNewNeighborFace, 0.); + + //Check orientation of new edge + BRepAdaptor_Curve BAcurve(anEdge); + BRepAdaptor_Curve BAnewcurve(aNewEdge); + gp_Pnt FirstPnt, FirstNewPnt; + gp_Vec DirOnCurve, DirOnNewCurve; + BAcurve.D1(BAcurve.FirstParameter(), FirstPnt, DirOnCurve); + Standard_Real ParamOnNewEdge = BAnewcurve.FirstParameter(); + Extrema_ExtPC Projector(FirstPnt, BAnewcurve); + if (!Projector.IsDone() || Projector.NbExt() == 0) + { + cout< 0) + { + Standard_Integer indmin = 1; + for (Standard_Integer ind = 2; ind <= Projector.NbExt(); ind++) + if (Projector.SquareDistance(ind) < Projector.SquareDistance(indmin)) + indmin = ind; + ParamOnNewEdge = Projector.Point(indmin).Parameter(); + } + BAnewcurve.D1(ParamOnNewEdge, FirstNewPnt, DirOnNewCurve); + Standard_Real ScalProd = DirOnCurve * DirOnNewCurve; + if (ScalProd < 0.) + ToReverse = Standard_True; + + myEdgeNewEdge.Bind(anEdge.Oriented(TopAbs_FORWARD), + (ToReverse)? aNewEdge.Oriented(TopAbs_REVERSED) : aNewEdge); + } //intersect + else //borders on constant face: change surface of pcurve on existing edge + { + Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, aFace, fpar, lpar); + //BB.UpdateEdge(anEdge, NullPCurve, aFace, 0.); + BB.UpdateEdge(anEdge, aPCurve, aBoundedNewFace, 0.); + + aNewEdge = anEdge; + } + } //for (; wexp.More(); wexp.Next()) + } //for (; itf.More(); itf.Next()) + } //for (Standard_Integer i = 1; i <= myFaceNewFace.Extent(); i++) + + //Intersect edges and make new wires + for (Standard_Integer i = 1; i <= myFaceNewFace.Extent(); i++) + { + TopoDS_Face aFace = TopoDS::Face(myFaceNewFace.FindKey(i)); + TopoDS_Shape aNewFace = myFaceNewFace(i); + TopoDS_Face aBoundedNewFace = TopoDS::Face(myNewFaceBoundedFace(aNewFace)); + + TopoDS_Iterator itf(aFace); + for (; itf.More(); itf.Next()) + { + const TopoDS_Wire& aWire = TopoDS::Wire(itf.Value()); + TopAbs_Orientation aWireOr = aWire.Orientation(); + + TopoDS_Wire aNewWire; + BB.MakeWire(aNewWire); + + TopoDS_Wire F_Wire = TopoDS::Wire(aWire.Oriented(TopAbs_FORWARD)); + BRepTools_WireExplorer wexp(F_Wire, aFace); + TopoDS_Vertex CurVertex = wexp.CurrentVertex(); + TopoDS_Edge FirstEdge = wexp.Current(); + TopoDS_Edge FirstNewEdge = FirstEdge; + if (myOrientedEdgeNewEdge.IsBound(FirstEdge)) + FirstNewEdge = TopoDS::Edge(myOrientedEdgeNewEdge(FirstEdge)); + else if (myEdgeNewEdge.IsBound(FirstEdge)) + FirstNewEdge = TopoDS::Edge(myEdgeNewEdge(FirstEdge)); + TopoDS_Edge CurEdge, PrevEdge = FirstEdge; + TopoDS_Edge CurNewEdge, PrevNewEdge = FirstNewEdge; + wexp.Next(); + if (!wexp.More() && //only one edge in wire + !myVertexNewVertex.IsBound(CurVertex)) + { + TopoDS_Vertex CurNewVertex; + if (myVertexNewVertex.IsBound(CurVertex)) + CurNewVertex = TopoDS::Vertex(myVertexNewVertex(CurVertex)); + + if (myEdgeNewEdge.IsBound(FirstEdge))//new edge: update + { + Standard_Real fpar, lpar; + BRep_Tool::Range(FirstEdge, fpar, lpar); + BB.Range(FirstNewEdge, fpar, lpar); + BRepAdaptor_Curve BAcurve(FirstNewEdge); + gp_Pnt FirstPnt = BAcurve.Value(BAcurve.FirstParameter()); + if (CurNewVertex.IsNull()) + CurNewVertex = BRepLib_MakeVertex(FirstPnt); + BB.Add(FirstNewEdge, CurNewVertex); + BB.Add(FirstNewEdge, CurNewVertex.Oriented(TopAbs_REVERSED)); + myVertexNewVertex.Bind(CurVertex, CurNewVertex); + } + } + for (; wexp.More(); wexp.Next()) + { + CurEdge = wexp.Current(); + if (myOrientedEdgeNewEdge.IsBound(CurEdge)) + CurNewEdge = TopoDS::Edge(myOrientedEdgeNewEdge(CurEdge)); + else if (myEdgeNewEdge.IsBound(CurEdge)) + CurNewEdge = TopoDS::Edge(myEdgeNewEdge(CurEdge)); + else + CurNewEdge = CurEdge; + CurVertex = wexp.CurrentVertex(); + UpdateEdgesAndVertex(PrevEdge, PrevNewEdge, + CurEdge, CurNewEdge, + CurVertex); + if (!PrevEdge.IsSame(PrevNewEdge) && + PrevEdge.Orientation() == TopAbs_REVERSED) + PrevNewEdge.Reverse(); + BB.Add(aNewWire, PrevNewEdge); + + PrevEdge = CurEdge; + PrevNewEdge = CurNewEdge; + } + CurEdge = FirstEdge; + CurNewEdge = FirstNewEdge; + CurVertex = wexp.CurrentVertex(); + UpdateEdgesAndVertex(PrevEdge, PrevNewEdge, + CurEdge, CurNewEdge, + CurVertex); + if (!PrevEdge.IsSame(PrevNewEdge) && + PrevEdge.Orientation() == TopAbs_REVERSED) + PrevNewEdge.Reverse(); + BB.Add(aNewWire, PrevNewEdge); + + aNewWire.Orientation(aWireOr); + BB.Add(aBoundedNewFace, aNewWire); + } //for (; itf.More(); itf.Next()) (iterator on face) + } + + //Assemble resulting shape + TopoDS_Solid aSolid; + BB.MakeSolid(aSolid); + TopoDS_Shell aShell; + BB.MakeShell(aShell); + TopExp_Explorer Explo(myInitialShape, TopAbs_FACE); + for (; Explo.More(); Explo.Next()) + { + const TopoDS_Shape& aFace = Explo.Current(); + TopoDS_Shape aBoundedNewFace; + if (myFaceNewFace.Contains(aFace)) + { + const TopoDS_Shape& aNewFace = myFaceNewFace.FindFromKey(aFace); + aBoundedNewFace = myNewFaceBoundedFace(aNewFace); + if (aFace.Orientation() == TopAbs_REVERSED) + aBoundedNewFace.Reverse(); + } + else + aBoundedNewFace = aFace; + BB.Add(aShell, aBoundedNewFace); + } + BB.Add(aSolid, aShell); + + ShapeFix_Shape Fixer(aSolid); + Fixer.Perform(); + + myShape = Fixer.Shape(); + //myShape = aSolid; + + Done(); +} + +void BRepOffsetAPI_PatchFaces::UpdateEdgesAndVertex(const TopoDS_Edge& thePrevEdge, + TopoDS_Edge& thePrevNewEdge, + const TopoDS_Edge& theCurEdge, + TopoDS_Edge& theCurNewEdge, + TopoDS_Vertex& theCurVertex) +{ + BRep_Builder BB; + + TopoDS_Vertex CurNewVertex; + if (myVertexNewVertex.IsBound(theCurVertex)) + CurNewVertex = TopoDS::Vertex(myVertexNewVertex(theCurVertex)); + else + { + Standard_Boolean IsConstVertex = (!(myEdgeNewEdge.IsBound(thePrevEdge) || myOrientedEdgeNewEdge.IsBound(thePrevEdge)) || + !(myEdgeNewEdge.IsBound(theCurEdge) || myOrientedEdgeNewEdge.IsBound(theCurEdge))); + if (IsConstVertex) + CurNewVertex = theCurVertex; + } + + if ((myEdgeNewEdge.IsBound(thePrevEdge) || myOrientedEdgeNewEdge.IsBound(thePrevEdge)) && + (myEdgeNewEdge.IsBound(theCurEdge) || myOrientedEdgeNewEdge.IsBound(theCurEdge))) //two new edges: intersect + { + Standard_Real ParamOnPrev, ParamOnCur; + gp_Pnt PntOnPrev, PntOnCur; + ProjectVertexOnNewEdge(theCurVertex, thePrevEdge, thePrevNewEdge, + ParamOnPrev, PntOnPrev); + ProjectVertexOnNewEdge(theCurVertex, theCurEdge, theCurNewEdge, + ParamOnCur, PntOnCur); + + Standard_Real TolReached; + gp_Pnt PntVtx = BRep_Tool::Pnt(theCurVertex); + TolReached = PntOnPrev.Distance(PntOnCur); + Standard_Real DistVtoPrev = PntVtx.Distance(PntOnPrev); + Standard_Real DistVtoCur = PntVtx.Distance(PntOnCur); + TolReached = Max(TolReached, DistVtoPrev); + TolReached = Max(TolReached, DistVtoCur); + + BRepExtrema_ExtCC ExtrEE(thePrevNewEdge, theCurNewEdge); + if (!ExtrEE.IsDone() || ExtrEE.NbExt() == 0) + { + cout< 0) + { + Standard_Integer indmin = 1; + for (Standard_Integer ind = 2; ind <= Projector.NbExt(); ind++) + if (Projector.SquareDistance(ind) < Projector.SquareDistance(indmin)) + indmin = ind; + ParamOnNewEdge = Projector.Point(indmin).Parameter(); + Standard_Real TolReached = sqrt(Projector.SquareDistance(indmin)); + BB.UpdateVertex(theCurVertex, TolReached); + } + if (!EdgeContains(NewEdge, CurNewVertex)) + PutVertexToEdge(CurNewVertex, theCurVertex, NewEdge, ModifiedEdge, ParamOnNewEdge); + } //else (one constant edge: project point onto curve) + else //two constant edges + { + //nothing ? + } +} + + +void BRepOffsetAPI_PatchFaces::PutVertexToEdge(const TopoDS_Vertex& theVertex, + const TopoDS_Vertex& theProVertex, + TopoDS_Edge& theEdge, + const TopoDS_Edge& theProEdge, + const Standard_Real theParamOnEdge) +{ + BRep_Builder BB; + + TopAbs_Orientation anOr = OrientationInEdge(theProVertex, theProEdge); + if (myEdgeNewEdge.IsBound(theProEdge) && + myEdgeNewEdge(theProEdge).Orientation() == TopAbs_REVERSED) + anOr = TopAbs::Reverse(anOr); + + TopoDS_Shape F_Edge = theEdge.Oriented(TopAbs_FORWARD); + F_Edge.Free(Standard_True); + BB.Add(F_Edge, theVertex.Oriented(anOr)); + Standard_Real fpar, lpar; + BRep_Tool::Range(theEdge, fpar, lpar); + if (anOr == TopAbs_FORWARD) + BB.Range(theEdge, theParamOnEdge, lpar); + else + BB.Range(theEdge, fpar, theParamOnEdge); +} diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx new file mode 100644 index 0000000000..731d645fa7 --- /dev/null +++ b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx @@ -0,0 +1,100 @@ +// Created on: 2012-08-06 +// Created by: jgv@ROLEX +// Copyright (c) 2012-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. + +#ifndef _BRepOffsetAPI_PatchFaces_HeaderFile +#define _BRepOffsetAPI_PatchFaces_HeaderFile + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +class TopoDS_Shape; + + +//! Describes functions to replace some faces in a shape +//! by patches +class BRepOffsetAPI_PatchFaces : public BRepBuilderAPI_MakeShape +{ +public: + + DEFINE_STANDARD_ALLOC + + + //! General constructor. + Standard_EXPORT BRepOffsetAPI_PatchFaces(const TopoDS_Shape& aShape); + + //! Adds the patch face for the face in the shape. + Standard_EXPORT void AddPatchFace (const TopoDS_Face& theFace, const TopoDS_Face& thePatchFace); + + Standard_EXPORT virtual void Build() Standard_OVERRIDE; + + + + +protected: + + + + + +private: + + + Standard_EXPORT void UpdateEdgesAndVertex(const TopoDS_Edge& thePrevEdge, + TopoDS_Edge& thePrevNewEdge, + const TopoDS_Edge& theCurEdge, + TopoDS_Edge& theCurNewEdge, + TopoDS_Vertex& theCurVertex); + + Standard_EXPORT void PutVertexToEdge(const TopoDS_Vertex& theVertex, + const TopoDS_Vertex& theProVertex, + TopoDS_Edge& theEdge, + const TopoDS_Edge& theProEdge, + const Standard_Real theParamOnEdge); + + + TopoDS_Shape myInitialShape; + + TopTools_IndexedDataMapOfShapeShape myFacePatchFace; + TopTools_IndexedDataMapOfShapeShape myFaceNewFace; + TopTools_DataMapOfShapeShape myNewFaceBoundedFace; + TopTools_DataMapOfShapeShape myEdgeNewEdge; + TopTools_DataMapOfOrientedShapeShape myOrientedEdgeNewEdge; + TopTools_DataMapOfShapeShape myVertexNewVertex; + TopTools_MapOfShape myTangentEdges; + TopTools_MapOfShape mySmoothEdges; + + TopTools_IndexedDataMapOfShapeListOfShape myEFmap; + +}; + + + + + + + +#endif // _BRepOffsetAPI_PatchFaces_HeaderFile diff --git a/src/BRepTest/BRepTest_FeatureCommands.cxx b/src/BRepTest/BRepTest_FeatureCommands.cxx index 4dfa14a06a..74fb655bf8 100644 --- a/src/BRepTest/BRepTest_FeatureCommands.cxx +++ b/src/BRepTest/BRepTest_FeatureCommands.cxx @@ -62,6 +62,8 @@ #include #include +#include + #include #include @@ -2287,6 +2289,36 @@ static Standard_Integer ComputeSimpleOffset(Draw_Interpretor& theCommands, return 0; } +//======================================================================= +//function : patchfaces +//purpose : +//======================================================================= +static Standard_Integer patchfaces(Draw_Interpretor& /*di*/, + Standard_Integer n, const char** a) +{ + if (n < 5) return 1; + + TopoDS_Shape aShape = DBRep::Get(a[2]); + if (aShape.IsNull()) return 1; + + TopoDS_Shape aLocalFace = DBRep::Get(a[3], TopAbs_FACE); + if (aLocalFace.IsNull()) return 1; + TopoDS_Face aFace = TopoDS::Face(aLocalFace); + + TopoDS_Shape aLocalNewFace = DBRep::Get(a[4], TopAbs_FACE); + if (aLocalNewFace.IsNull()) return 1; + TopoDS_Face aNewFace = TopoDS::Face(aLocalNewFace); + + BRepOffsetAPI_PatchFaces Builder(aShape); + Builder.AddPatchFace(aFace, aNewFace); + Builder.Build(); + + TopoDS_Shape Result = Builder.Shape(); + DBRep::Set(a[1], Result); + + return 0; +} + //======================================================================= //function : FeatureCommands //purpose : @@ -2435,4 +2467,7 @@ void BRepTest::FeatureCommands (Draw_Interpretor& theCommands) theCommands.Add("offsetshapesimple", "offsetshapesimple result shape offsetvalue [solid] [tolerance=1e-7]", __FILE__, ComputeSimpleOffset); + + theCommands.Add("patchfaces", "patchfaces res shape face newface", + __FILE__,patchfaces,g); }