From e178d2fa1657c9eafeb50ab5f79418a593f1960d Mon Sep 17 00:00:00 2001 From: jgv Date: Wed, 16 Aug 2017 13:56:00 +0300 Subject: [PATCH] 0029003: Implementation of the algorithm for replacing faces in shape with new faces based on other surfaces Implementation of the algorithm for replacing faces in shape with new faces based on other surfaces - BRepOffsetAPI_PatchFaces. The algorithm runs the steps similar to 3d Offset algorithm for Join type Intersection (intersection of the faces with neighbors for trimming of the faces by the adjacent faces). --- .../BRepOffsetAPI_PatchFaces.cxx | 746 ++++++++++++++++++ .../BRepOffsetAPI_PatchFaces.hxx | 100 +++ src/BRepTest/BRepTest_FeatureCommands.cxx | 35 + 3 files changed, 881 insertions(+) create mode 100644 src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx create mode 100644 src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx 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); } -- 2.39.5