diff --git a/src/BRepOffset/BRepOffset_Tool.cxx b/src/BRepOffset/BRepOffset_Tool.cxx index 638b476ae6..da2d9b0a11 100644 --- a/src/BRepOffset/BRepOffset_Tool.cxx +++ b/src/BRepOffset/BRepOffset_Tool.cxx @@ -2817,7 +2817,7 @@ static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S, const Standard_Boolean GlobalEnlargeVfirst, const Standard_Boolean GlobalEnlargeVlast) { - const Standard_Real coeff = 4.; + const Standard_Real coeff = 2.; const Standard_Real TolApex = 1.e-5; Standard_Boolean SurfaceChange = Standard_False; @@ -3200,7 +3200,8 @@ Standard_Boolean BRepOffset_Tool::EnLargeFace const Standard_Boolean UpdatePCurve, const Standard_Boolean enlargeU, const Standard_Boolean enlargeVfirst, - const Standard_Boolean enlargeVlast) + const Standard_Boolean enlargeVlast, + const Standard_Boolean UseInfini) { //--------------------------- // extension de la geometrie. @@ -3223,8 +3224,20 @@ Standard_Boolean BRepOffset_Tool::EnLargeFace } S->Bounds (US1,US2,VS1,VS2); - UU1 = VV1 = - infini; - UU2 = VV2 = infini; + if (UseInfini) + { + UU1 = VV1 = - infini; + UU2 = VV2 = infini; + } + else + { + Standard_Real FaceDU = UF2 - UF1; + Standard_Real FaceDV = VF2 - VF1; + UU1 = UF1 - FaceDU; + UU2 = UF2 + FaceDU; + VV1 = VF1 - FaceDV; + VV2 = VF2 + FaceDV; + } if (CanExtentSurface) { SurfaceChange = EnlargeGeometry( S, UU1, UU2, VV1, VV2, isVV1degen, isVV2degen, UF1, UF2, VF1, VF2, diff --git a/src/BRepOffset/BRepOffset_Tool.hxx b/src/BRepOffset/BRepOffset_Tool.hxx index b0609d5506..67e764a012 100644 --- a/src/BRepOffset/BRepOffset_Tool.hxx +++ b/src/BRepOffset/BRepOffset_Tool.hxx @@ -92,8 +92,15 @@ public: //! if is TRUE, update the pcurves of the //! edges of on the new surface.if the surface has been changed, //! Returns True if The Surface of has changed. - Standard_EXPORT static Standard_Boolean EnLargeFace (const TopoDS_Face& F, TopoDS_Face& NF, const Standard_Boolean ChangeGeom, const Standard_Boolean UpDatePCurve = Standard_False, const Standard_Boolean enlargeU = Standard_True, const Standard_Boolean enlargeVfirst = Standard_True, const Standard_Boolean enlargeVlast = Standard_True); - + Standard_EXPORT static Standard_Boolean EnLargeFace (const TopoDS_Face& F, + TopoDS_Face& NF, + const Standard_Boolean ChangeGeom, + const Standard_Boolean UpDatePCurve = Standard_False, + const Standard_Boolean enlargeU = Standard_True, + const Standard_Boolean enlargeVfirst = Standard_True, + const Standard_Boolean enlargeVlast = Standard_True, + const Standard_Boolean UseInfini = Standard_True); + Standard_EXPORT static void ExtentFace (const TopoDS_Face& F, TopTools_DataMapOfShapeShape& ConstShapes, TopTools_DataMapOfShapeShape& ToBuild, const TopAbs_State Side, const Standard_Real TolConf, TopoDS_Face& NF); //! Via the wire explorer store in for diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx new file mode 100644 index 0000000000..cf1be4cd4e --- /dev/null +++ b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx @@ -0,0 +1,781 @@ +// 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 +#include + + +static TopoDS_Edge MakeNewEdgeWithOldPcurvesOnNewSurfaces(const TopoDS_Edge& theEdge, + const TopoDS_Face& theOldFace1, + const TopoDS_Face& theNewFace1, + const TopoDS_Face& theOldFace2, + const TopoDS_Face& theNewFace2) +{ + TopoDS_Edge aNewEdge; + Standard_Real fpar, lpar; + BRep_Builder BB; + + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, fpar, lpar); + aNewEdge = BRepLib_MakeEdge(aCurve, aCurve->FirstParameter(), aCurve->LastParameter()); //??? + TopoDS_Vertex V1, V2; + TopExp::Vertices(aNewEdge, V1, V2); + aNewEdge.Free(Standard_True); + BB.Remove(aNewEdge, V1); + BB.Remove(aNewEdge, V2); + + Standard_Real Etol = BRep_Tool::Tolerance(theEdge); + Handle(Geom2d_Curve) aPCurve1 = BRep_Tool::CurveOnSurface(theEdge, theOldFace1, fpar, lpar); + BB.UpdateEdge(aNewEdge, aPCurve1, theNewFace1, Etol); + Handle(Geom2d_Curve) aPCurve2 = BRep_Tool::CurveOnSurface(theEdge, theOldFace2, fpar, lpar); + BB.UpdateEdge(aNewEdge, aPCurve2, theNewFace2, Etol); + + return aNewEdge; +} + +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& theTolReached) +{ + 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]; + theTolReached = sqrt(dist[imin]); +} + +static TopoDS_Edge GetGeneratedEdge(const TopoDS_Edge& anEdge, + const TopoDS_Face& aFace, + const TopoDS_Face& aNewFace) +{ + TopoDS_Edge aNewEdge; + + 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) + { + aNewEdge = TopoDS::Edge(ExploNew.Current()); + break; + } + } + + TopoDS_Vertex V1, V2; + TopExp::Vertices(aNewEdge, V1, V2); + BRep_Builder BB; + aNewEdge.Free(Standard_True); + BB.Remove(aNewEdge, V1); + BB.Remove(aNewEdge, V2); + return aNewEdge; +} + +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(); + const Standard_Integer aNbSamplesMax = 23; + Standard_Integer aNbSamples = Min(aNbSamplesMax, Max(aNbSamples1, aNbSamples2)); + const Standard_Real aTolAngle = M_PI/18; + + +// 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, aTolAngle, 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, + Standard_False); //not too big + 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.Swap(myFaceNewFace.FindIndex(aNeighborFace), myFaceNewFace.Extent()); + myFaceNewFace.RemoveLast(); + + myTangentEdges.Add(anEdge); + UpdatedConstEdges.Add(anEdge); + } + else + { + aNewEdge = MakeNewEdgeWithOldPcurvesOnNewSurfaces(anEdge, + aFace, aBoundedNewFace, + aNeighborFace, aBoundedNewNeighborFace); + myEdgeNewEdge.Bind(anEdge.Oriented(TopAbs_FORWARD), aNewEdge); + } + continue; + } + TopoDS_Vertex V1, V2; + TopExp::Vertices(aNewEdge, V1, V2); + aNewEdge.Free(Standard_True); + BB.Remove(aNewEdge, 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; + } + + Standard_Boolean IsSeamPrev = (myOrientedEdgeNewEdge.IsBound(thePrevEdge)); + Standard_Boolean IsSeamCur = (myOrientedEdgeNewEdge.IsBound(theCurEdge)); + + if ((myEdgeNewEdge.IsBound(thePrevEdge) || myOrientedEdgeNewEdge.IsBound(thePrevEdge)) && + (myEdgeNewEdge.IsBound(theCurEdge) || myOrientedEdgeNewEdge.IsBound(theCurEdge))) //two new edges: intersect + { + Standard_Real ParamOnPrev, ParamOnCur, TolProj; + gp_Pnt PntOnPrev, PntOnCur; + ProjectVertexOnNewEdge(theCurVertex, thePrevEdge, thePrevNewEdge, + ParamOnPrev, PntOnPrev, TolProj); + ProjectVertexOnNewEdge(theCurVertex, theCurEdge, theCurNewEdge, + ParamOnCur, PntOnCur, TolProj); + + Standard_Real TolReached; + gp_Pnt PntVtx = (CurNewVertex.IsNull())? + BRep_Tool::Pnt(theCurVertex) : BRep_Tool::Pnt(CurNewVertex); + 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< +#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_IndexedDataMapOfShapeListOfShape myEFmap; + +}; + + + + + + + +#endif // _BRepOffsetAPI_PatchFaces_HeaderFile diff --git a/src/BRepOffsetAPI/FILES b/src/BRepOffsetAPI/FILES index 4680ffd109..0d84a8f527 100644 --- a/src/BRepOffsetAPI/FILES +++ b/src/BRepOffsetAPI/FILES @@ -27,3 +27,5 @@ BRepOffsetAPI_SequenceOfSequenceOfShape.hxx BRepOffsetAPI_Sewing.hxx BRepOffsetAPI_ThruSections.cxx BRepOffsetAPI_ThruSections.hxx +BRepOffsetAPI_PatchFaces.cxx +BRepOffsetAPI_PatchFaces.hxx diff --git a/src/BRepTest/BRepTest_FeatureCommands.cxx b/src/BRepTest/BRepTest_FeatureCommands.cxx index a7431744c2..d27354fe39 100644 --- a/src/BRepTest/BRepTest_FeatureCommands.cxx +++ b/src/BRepTest/BRepTest_FeatureCommands.cxx @@ -54,6 +54,8 @@ #include #include +#include + #include #include #include @@ -2249,6 +2251,35 @@ static Standard_Integer BOSS(Draw_Interpretor& theCommands, return 1; } +//======================================================================= +//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 @@ -2395,4 +2426,6 @@ void BRepTest::FeatureCommands (Draw_Interpretor& theCommands) " Perform fillet on top and bottom edges of dprism :bossage dprism result radtop radbottom First/LastShape (1/2)", __FILE__,BOSS); + theCommands.Add("patchfaces", "patchfaces res shape face newface", + __FILE__,patchfaces,g); } diff --git a/src/TopExp/TopExp.cxx b/src/TopExp/TopExp.cxx index ff63bbe973..b011b50c7c 100644 --- a/src/TopExp/TopExp.cxx +++ b/src/TopExp/TopExp.cxx @@ -99,7 +99,55 @@ void TopExp::MapShapesAndAncestors } } +//======================================================================= +//function : MapShapesAndUniqueAncestors +//purpose : +//======================================================================= +void TopExp::MapShapesAndUniqueAncestors + (const TopoDS_Shape& S, + const TopAbs_ShapeEnum TS, + const TopAbs_ShapeEnum TA, + TopTools_IndexedDataMapOfShapeListOfShape& M, + const Standard_Boolean useOrientation) +{ + TopTools_ListOfShape empty; + + // visit ancestors + TopExp_Explorer exa(S,TA); + while (exa.More()) + { + // visit shapes + const TopoDS_Shape& anc = exa.Current(); + TopExp_Explorer exs(anc,TS); + while (exs.More()) + { + Standard_Integer index = M.FindIndex(exs.Current()); + if (index == 0) + index = M.Add(exs.Current(),empty); + TopTools_ListOfShape& aList = M(index); + // check if anc already exists in a list + TopTools_ListIteratorOfListOfShape it(aList); + for (; it.More(); it.Next()) + if (useOrientation? anc.IsEqual(it.Value()) : anc.IsSame(it.Value())) + break; + if (!it.More()) + aList.Append(anc); + exs.Next(); + } + exa.Next(); + } + + // visit shapes not under ancestors + TopExp_Explorer ex(S,TS,TA); + while (ex.More()) + { + Standard_Integer index = M.FindIndex(ex.Current()); + if (index == 0) + M.Add(ex.Current(),empty); + ex.Next(); + } +} //======================================================================= //function : FirstVertex diff --git a/src/TopExp/TopExp.hxx b/src/TopExp/TopExp.hxx index 25ccde43b8..34e45eee4a 100644 --- a/src/TopExp/TopExp.hxx +++ b/src/TopExp/TopExp.hxx @@ -66,6 +66,18 @@ public: //! Warning: The map is not cleared at first. Standard_EXPORT static void MapShapesAndAncestors (const TopoDS_Shape& S, const TopAbs_ShapeEnum TS, const TopAbs_ShapeEnum TA, TopTools_IndexedDataMapOfShapeListOfShape& M); + //! Stores in the map all the subshape of of + //! type for each one append to the list all + //! unique ancestors of type . For example map all + //! the edges and bind the list of faces. + //! useOrientation = True : taking account the ancestor orientation + //! Warning: The map is not cleared at first. + Standard_EXPORT static void MapShapesAndUniqueAncestors (const TopoDS_Shape& S, + const TopAbs_ShapeEnum TS, + const TopAbs_ShapeEnum TA, + TopTools_IndexedDataMapOfShapeListOfShape& M, + const Standard_Boolean useOrientation = Standard_False); + //! Returns the Vertex of orientation FORWARD in E. If //! there is none returns a Null Shape. //! CumOri = True : taking account the edge orientation diff --git a/tests/patchfaces/begin b/tests/patchfaces/begin new file mode 100644 index 0000000000..ed01a4a269 --- /dev/null +++ b/tests/patchfaces/begin @@ -0,0 +1,23 @@ +# To prevent loops limit to 10 minutes +cpulimit 100 +if { [array get Draw_Groups "TOPOLOGY Feature commands"] == "" } { + pload TOPTEST +} +if { [array get Draw_Groups "Shape Healing"] == "" } { + pload XSDRAW +} +if { [info exists imagedir] == 0 } { + set imagedir . +} +if { [info exists test_image ] == 0 } { + set test_image photo +} +proc PATCHFACES {i} { + uplevel #0 binrestore [locate_data_file shape_3_$i.bin] s + uplevel #0 tclean s + uplevel #0 removeloc s s + uplevel #0 explode s + uplevel #0 tcopy s_1 InitShape + + uplevel #0 patchfaces result s_1 s_2 s_3 +} diff --git a/tests/patchfaces/end b/tests/patchfaces/end new file mode 100644 index 0000000000..73b3acd4ea --- /dev/null +++ b/tests/patchfaces/end @@ -0,0 +1 @@ +puts "TEST COMPLETED" diff --git a/tests/patchfaces/grids.list b/tests/patchfaces/grids.list new file mode 100644 index 0000000000..55dee65f67 --- /dev/null +++ b/tests/patchfaces/grids.list @@ -0,0 +1 @@ +001 replace diff --git a/tests/patchfaces/parse.rules b/tests/patchfaces/parse.rules new file mode 100644 index 0000000000..95a93927e0 --- /dev/null +++ b/tests/patchfaces/parse.rules @@ -0,0 +1,2 @@ +FAILED /\bFaulty\b/ bad shape +OK /Relative error of mass computation/ message from vprops \ No newline at end of file diff --git a/tests/patchfaces/replace/end b/tests/patchfaces/replace/end new file mode 100644 index 0000000000..4e1132da15 --- /dev/null +++ b/tests/patchfaces/replace/end @@ -0,0 +1,2 @@ +checkshape result +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/patchfaces/replace/test_1 b/tests/patchfaces/replace/test_1 new file mode 100644 index 0000000000..9fc4b85992 --- /dev/null +++ b/tests/patchfaces/replace/test_1 @@ -0,0 +1 @@ +PATCHFACES 1 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_10 b/tests/patchfaces/replace/test_10 new file mode 100644 index 0000000000..4089cf808b --- /dev/null +++ b/tests/patchfaces/replace/test_10 @@ -0,0 +1 @@ +PATCHFACES 10 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_11 b/tests/patchfaces/replace/test_11 new file mode 100644 index 0000000000..a40a9b3cf3 --- /dev/null +++ b/tests/patchfaces/replace/test_11 @@ -0,0 +1 @@ +PATCHFACES 11 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_12 b/tests/patchfaces/replace/test_12 new file mode 100644 index 0000000000..0b094e3c01 --- /dev/null +++ b/tests/patchfaces/replace/test_12 @@ -0,0 +1 @@ +PATCHFACES 12 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_13 b/tests/patchfaces/replace/test_13 new file mode 100644 index 0000000000..8fcfcd37af --- /dev/null +++ b/tests/patchfaces/replace/test_13 @@ -0,0 +1 @@ +PATCHFACES 13 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_14 b/tests/patchfaces/replace/test_14 new file mode 100644 index 0000000000..247d4915a0 --- /dev/null +++ b/tests/patchfaces/replace/test_14 @@ -0,0 +1 @@ +PATCHFACES 14 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_15 b/tests/patchfaces/replace/test_15 new file mode 100644 index 0000000000..75b75d0657 --- /dev/null +++ b/tests/patchfaces/replace/test_15 @@ -0,0 +1 @@ +PATCHFACES 15 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_16 b/tests/patchfaces/replace/test_16 new file mode 100644 index 0000000000..2e9d2ae11a --- /dev/null +++ b/tests/patchfaces/replace/test_16 @@ -0,0 +1 @@ +PATCHFACES 16 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_17 b/tests/patchfaces/replace/test_17 new file mode 100644 index 0000000000..53762739db --- /dev/null +++ b/tests/patchfaces/replace/test_17 @@ -0,0 +1 @@ +PATCHFACES 17 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_18 b/tests/patchfaces/replace/test_18 new file mode 100644 index 0000000000..d15b5ab431 --- /dev/null +++ b/tests/patchfaces/replace/test_18 @@ -0,0 +1 @@ +PATCHFACES 18 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_19 b/tests/patchfaces/replace/test_19 new file mode 100644 index 0000000000..58b5d2c72f --- /dev/null +++ b/tests/patchfaces/replace/test_19 @@ -0,0 +1 @@ +PATCHFACES 19 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_2 b/tests/patchfaces/replace/test_2 new file mode 100644 index 0000000000..7c6e6e6876 --- /dev/null +++ b/tests/patchfaces/replace/test_2 @@ -0,0 +1 @@ +PATCHFACES 2 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_20 b/tests/patchfaces/replace/test_20 new file mode 100644 index 0000000000..4c8a8baa47 --- /dev/null +++ b/tests/patchfaces/replace/test_20 @@ -0,0 +1 @@ +PATCHFACES 20 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_21 b/tests/patchfaces/replace/test_21 new file mode 100644 index 0000000000..31ff03b3fc --- /dev/null +++ b/tests/patchfaces/replace/test_21 @@ -0,0 +1 @@ +PATCHFACES 21 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_22 b/tests/patchfaces/replace/test_22 new file mode 100644 index 0000000000..1472cf0d63 --- /dev/null +++ b/tests/patchfaces/replace/test_22 @@ -0,0 +1 @@ +PATCHFACES 22 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_23 b/tests/patchfaces/replace/test_23 new file mode 100644 index 0000000000..43e9544e53 --- /dev/null +++ b/tests/patchfaces/replace/test_23 @@ -0,0 +1 @@ +PATCHFACES 23 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_24 b/tests/patchfaces/replace/test_24 new file mode 100644 index 0000000000..bab81082a6 --- /dev/null +++ b/tests/patchfaces/replace/test_24 @@ -0,0 +1 @@ +PATCHFACES 24 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_25 b/tests/patchfaces/replace/test_25 new file mode 100644 index 0000000000..d11d3b564d --- /dev/null +++ b/tests/patchfaces/replace/test_25 @@ -0,0 +1 @@ +PATCHFACES 25 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_26 b/tests/patchfaces/replace/test_26 new file mode 100644 index 0000000000..0af9759422 --- /dev/null +++ b/tests/patchfaces/replace/test_26 @@ -0,0 +1 @@ +PATCHFACES 26 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_27 b/tests/patchfaces/replace/test_27 new file mode 100644 index 0000000000..defa2b09df --- /dev/null +++ b/tests/patchfaces/replace/test_27 @@ -0,0 +1 @@ +PATCHFACES 27 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_28 b/tests/patchfaces/replace/test_28 new file mode 100644 index 0000000000..7da11d2301 --- /dev/null +++ b/tests/patchfaces/replace/test_28 @@ -0,0 +1 @@ +PATCHFACES 28 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_29 b/tests/patchfaces/replace/test_29 new file mode 100644 index 0000000000..f16ed03dcd --- /dev/null +++ b/tests/patchfaces/replace/test_29 @@ -0,0 +1 @@ +PATCHFACES 29 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_3 b/tests/patchfaces/replace/test_3 new file mode 100644 index 0000000000..2db0a20cf0 --- /dev/null +++ b/tests/patchfaces/replace/test_3 @@ -0,0 +1 @@ +PATCHFACES 3 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_30 b/tests/patchfaces/replace/test_30 new file mode 100644 index 0000000000..d07f306628 --- /dev/null +++ b/tests/patchfaces/replace/test_30 @@ -0,0 +1 @@ +PATCHFACES 30 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_31 b/tests/patchfaces/replace/test_31 new file mode 100644 index 0000000000..b8ef5b5d17 --- /dev/null +++ b/tests/patchfaces/replace/test_31 @@ -0,0 +1 @@ +PATCHFACES 31 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_32 b/tests/patchfaces/replace/test_32 new file mode 100644 index 0000000000..c531a687e0 --- /dev/null +++ b/tests/patchfaces/replace/test_32 @@ -0,0 +1 @@ +PATCHFACES 32 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_33 b/tests/patchfaces/replace/test_33 new file mode 100644 index 0000000000..5ddf9519ce --- /dev/null +++ b/tests/patchfaces/replace/test_33 @@ -0,0 +1 @@ +PATCHFACES 33 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_34 b/tests/patchfaces/replace/test_34 new file mode 100644 index 0000000000..8f81bc0f47 --- /dev/null +++ b/tests/patchfaces/replace/test_34 @@ -0,0 +1 @@ +PATCHFACES 34 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_35 b/tests/patchfaces/replace/test_35 new file mode 100644 index 0000000000..cc9e8b6f7c --- /dev/null +++ b/tests/patchfaces/replace/test_35 @@ -0,0 +1 @@ +PATCHFACES 35 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_4 b/tests/patchfaces/replace/test_4 new file mode 100644 index 0000000000..4cf50d24b1 --- /dev/null +++ b/tests/patchfaces/replace/test_4 @@ -0,0 +1 @@ +PATCHFACES 4 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_5 b/tests/patchfaces/replace/test_5 new file mode 100644 index 0000000000..9436e03c4d --- /dev/null +++ b/tests/patchfaces/replace/test_5 @@ -0,0 +1 @@ +PATCHFACES 5 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_6 b/tests/patchfaces/replace/test_6 new file mode 100644 index 0000000000..447f5d0859 --- /dev/null +++ b/tests/patchfaces/replace/test_6 @@ -0,0 +1 @@ +PATCHFACES 6 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_7 b/tests/patchfaces/replace/test_7 new file mode 100644 index 0000000000..19d943456b --- /dev/null +++ b/tests/patchfaces/replace/test_7 @@ -0,0 +1 @@ +PATCHFACES 7 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_8 b/tests/patchfaces/replace/test_8 new file mode 100644 index 0000000000..8386ba18ca --- /dev/null +++ b/tests/patchfaces/replace/test_8 @@ -0,0 +1 @@ +PATCHFACES 8 \ No newline at end of file diff --git a/tests/patchfaces/replace/test_9 b/tests/patchfaces/replace/test_9 new file mode 100644 index 0000000000..75af863bad --- /dev/null +++ b/tests/patchfaces/replace/test_9 @@ -0,0 +1 @@ +PATCHFACES 9 \ No newline at end of file