mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
"endl" manipulator for Message_Messenger is renamed to "Message_EndLine". The following entities from std namespace are now used with std:: explicitly specified (from Standard_Stream.hxx): std::istream,std::ostream,std::ofstream,std::ifstream,std::fstream, std::filebuf,std::streambuf,std::streampos,std::ios,std::cout,std::cerr, std::cin,std::endl,std::ends,std::flush,std::setw,std::setprecision, std::hex,std::dec.
1638 lines
47 KiB
C++
1638 lines
47 KiB
C++
// Created on: 1995-06-27
|
|
// Created by: Jacques GOUSSARD
|
|
// 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.
|
|
|
|
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepAdaptor_Surface.hxx>
|
|
#include <BRepClass_FaceExplorer.hxx>
|
|
#include <BRepLib_MakeFace.hxx>
|
|
#include <BRepLib_MakeWire.hxx>
|
|
#include <BRepTools.hxx>
|
|
#include <BRepTools_WireExplorer.hxx>
|
|
#include <BRepTopAdaptor_FClass2d.hxx>
|
|
#include <Geom2d_Curve.hxx>
|
|
#include <gp_Dir2d.hxx>
|
|
#include <gp_Pnt2d.hxx>
|
|
#include <gp_Vec2d.hxx>
|
|
#include <LocOpe.hxx>
|
|
#include <LocOpe_SplitShape.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Standard_ConstructionError.hxx>
|
|
#include <Standard_ErrorHandler.hxx>
|
|
#include <Standard_NoSuchObject.hxx>
|
|
#include <StdFail_NotDone.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Face.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
|
|
#include <TopTools_DataMapOfShapeInteger.hxx>
|
|
#include <TopTools_DataMapOfShapeListOfShape.hxx>
|
|
#include <TopTools_DataMapOfShapeShape.hxx>
|
|
#include <TopTools_IndexedMapOfShape.hxx>
|
|
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
|
#include <TopTools_ListOfShape.hxx>
|
|
#include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
|
|
#include <TopTools_MapIteratorOfMapOfShape.hxx>
|
|
#include <TopTools_MapOfOrientedShape.hxx>
|
|
#include <TopTools_MapOfShape.hxx>
|
|
#include <ShapeAnalysis_Edge.hxx>
|
|
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
|
|
|
|
#include <Geom_Surface.hxx>
|
|
|
|
static Standard_Boolean IsInside(const TopoDS_Face&,
|
|
const TopoDS_Wire&,
|
|
const TopoDS_Wire&);
|
|
|
|
static Standard_Boolean IsInside(const TopoDS_Face&,
|
|
const TopoDS_Wire&);
|
|
|
|
static void GetDirection(const TopoDS_Edge&,
|
|
const TopoDS_Face&,
|
|
gp_Pnt2d&,
|
|
gp_Vec2d&,
|
|
Standard_Boolean isFirstEnd);
|
|
|
|
static Standard_Boolean ChoixUV(const TopoDS_Edge&,
|
|
const TopoDS_Face&,
|
|
const TopTools_IndexedMapOfShape&,
|
|
TopoDS_Edge&,
|
|
gp_Pnt2d&,
|
|
gp_Vec2d&);
|
|
|
|
static TopoDS_Shape ChooseDirection(const TopoDS_Shape&,
|
|
const TopoDS_Vertex&,
|
|
const TopoDS_Face&,
|
|
const TopTools_ListOfShape&);
|
|
|
|
inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2,
|
|
const BRepAdaptor_Surface& theBAS)//const Standard_Real tol)
|
|
{
|
|
Standard_Boolean isSame = Standard_True;
|
|
if(theBAS.IsUPeriodic())
|
|
isSame = (fabs(P1.X() - P2.X()) < theBAS.UPeriod() *0.5);
|
|
if(theBAS.IsVPeriodic())
|
|
isSame = (isSame && (fabs(P1.Y() - P2.Y()) < theBAS.VPeriod() *0.5));
|
|
return isSame;
|
|
//return P1.SquareDistance(P2) < tol * tol; //IFV
|
|
}
|
|
|
|
|
|
|
|
//=======================================================================
|
|
//function : Init
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void LocOpe_SplitShape::Init(const TopoDS_Shape& S)
|
|
{
|
|
myDone = Standard_False;
|
|
myShape = S;
|
|
myDblE.Clear();
|
|
myMap.Clear();
|
|
Put(myShape);
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : CanSplit
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LocOpe_SplitShape::CanSplit(const TopoDS_Edge& E) const
|
|
{
|
|
if (myDone) {
|
|
return Standard_False;
|
|
}
|
|
if (myMap.IsEmpty()) {
|
|
return Standard_False;
|
|
}
|
|
|
|
if (!myMap.IsBound(E)) {
|
|
return Standard_False;
|
|
}
|
|
|
|
// On verifie que l`edge n`appartient pas a un wire deja reconstruit
|
|
TopExp_Explorer exp;
|
|
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMap);
|
|
for (; itm.More(); itm.Next()) {
|
|
if (itm.Key().ShapeType() == TopAbs_WIRE && !itm.Value().IsEmpty()) {
|
|
for (exp.Init(itm.Key(),TopAbs_EDGE); exp.More(); exp.Next()) {
|
|
if (exp.Current().IsSame(E)) {
|
|
return Standard_False;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
|
|
const Standard_Real P,
|
|
const TopoDS_Edge& E)
|
|
{
|
|
if (!CanSplit(E)) {
|
|
return;
|
|
}
|
|
|
|
BRep_Builder B;
|
|
TopTools_ListOfShape& le = myMap(E);
|
|
if (le.IsEmpty()) {
|
|
le.Append(E);
|
|
}
|
|
TopTools_ListIteratorOfListOfShape itl(le);
|
|
Standard_Real f,l;
|
|
TopTools_ListOfShape aNewList;
|
|
for (; itl.More(); itl.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
|
|
BRep_Tool::Range(edg,f,l);
|
|
if (P > f + Precision::PConfusion() && P < l - Precision::PConfusion()) {
|
|
break;
|
|
|
|
}
|
|
aNewList.Append(edg);
|
|
}
|
|
if (!itl.More()) {
|
|
return;
|
|
}
|
|
TopoDS_Edge edg = TopoDS::Edge(itl.Value());
|
|
le.Remove(itl);
|
|
if (V.Orientation() == TopAbs_FORWARD ||
|
|
V.Orientation() == TopAbs_REVERSED) {
|
|
|
|
edg.Orientation(TopAbs_FORWARD);
|
|
TopoDS_Vertex aCurV1, aCurV2;
|
|
TopExp::Vertices(edg, aCurV1, aCurV2);
|
|
Standard_Real aPar1 = BRep_Tool::Parameter(aCurV1,edg);
|
|
|
|
Standard_Real aPar2 = BRep_Tool::Parameter(aCurV2,edg);
|
|
|
|
TopoDS_Shape aLocalShape = edg.EmptyCopied();
|
|
TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
|
|
aLocalShape = edg.EmptyCopied();
|
|
TopoDS_Edge E2 = TopoDS::Edge(aLocalShape);
|
|
// TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied());
|
|
// TopoDS_Edge E2 = TopoDS::Edge(edg.EmptyCopied());
|
|
E1.Orientation(TopAbs_FORWARD);
|
|
E2.Orientation(TopAbs_FORWARD);
|
|
TopoDS_Vertex newVtx = V;
|
|
Standard_Real aTolSplitV = BRep_Tool::Tolerance(V);
|
|
|
|
aCurV1.Orientation(TopAbs_FORWARD);
|
|
|
|
B.Add(E1,aCurV1);
|
|
//for degenerated edges tolerance of vertices should be set to maximal value
|
|
//from tolerance of the vertex of the edge and tolerance of splitting vertex
|
|
Standard_Real aTolV1 = ( BRep_Tool::Degenerated(edg) ?
|
|
Max(BRep_Tool::Tolerance(aCurV1), aTolSplitV) : BRep_Tool::Tolerance(aCurV1));
|
|
|
|
B.UpdateVertex(aCurV1,aPar1,E1, aTolV1);
|
|
newVtx.Orientation(TopAbs_REVERSED);
|
|
B.Add(E1,newVtx);
|
|
B.UpdateVertex(newVtx,P,E1,BRep_Tool::Tolerance(V));
|
|
newVtx.Orientation(TopAbs_FORWARD);
|
|
B.Add(E2,newVtx);
|
|
B.UpdateVertex(newVtx,P,E2,BRep_Tool::Tolerance(V));
|
|
|
|
aCurV2.Orientation(TopAbs_REVERSED);
|
|
B.Add(E2,aCurV2);
|
|
|
|
//for degenerated edges tolerance of vertices should be set to maximal value
|
|
//from tolerance of the vertex of the edge and tolerance of splitting vertex
|
|
Standard_Real aTolV2 = ( BRep_Tool::Degenerated(edg) ? aTolV1 : BRep_Tool::Tolerance(aCurV2));
|
|
B.UpdateVertex(aCurV2,aPar2,E2,aTolV2);
|
|
|
|
aNewList.Append(E1);
|
|
aNewList.Append(E2);
|
|
for (; itl.More(); itl.Next())
|
|
{
|
|
const TopoDS_Edge& edg1 = TopoDS::Edge(itl.Value());
|
|
aNewList.Append(edg1);
|
|
}
|
|
myMap.UnBind(E);
|
|
myMap.Bind(E, aNewList);
|
|
|
|
}
|
|
else {
|
|
TopoDS_Shape aLocalShape = edg.EmptyCopied();
|
|
TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
|
|
|
|
TopExp_Explorer exp;
|
|
for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
|
|
|
|
const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
|
|
f = BRep_Tool::Parameter(vtx,edg);
|
|
B.Add(E1,vtx);
|
|
B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx));
|
|
}
|
|
B.Add(E1,V);
|
|
B.UpdateVertex(V,P,E1,BRep_Tool::Tolerance(V));
|
|
le.Append(E1);
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose : adds the list of wires on the face <F>
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
|
|
const TopoDS_Face& F)
|
|
{
|
|
|
|
if (myDone) {
|
|
return Standard_False;
|
|
}
|
|
|
|
TopTools_ListOfShape& lf = myMap(F);
|
|
if (lf.IsEmpty()) {
|
|
Rebuild(F);
|
|
}
|
|
|
|
// On cherche la face descendante de F qui continent le wire
|
|
lf = myMap(F);
|
|
TopTools_ListIteratorOfListOfShape itl(lf);
|
|
TopoDS_Vertex Vfirst,Vlast;
|
|
|
|
BRepTools::Update(F);
|
|
|
|
TopTools_ListOfShape aLInside;
|
|
for (; itl.More(); itl.Next())
|
|
{
|
|
const TopoDS_Face& fac = TopoDS::Face(itl.Value());
|
|
TopTools_ListIteratorOfListOfShape itwires(Lwires);
|
|
for (; itwires.More(); itwires.Next())
|
|
{
|
|
const TopoDS_Wire& aWire = TopoDS::Wire(itwires.Value());
|
|
if (IsInside(fac, aWire))
|
|
{
|
|
aLInside.Append(aWire);
|
|
|
|
}
|
|
}
|
|
if(aLInside.Extent())
|
|
break;
|
|
}
|
|
if (!aLInside.Extent() || !itl.More()) {
|
|
return Standard_False;
|
|
}
|
|
|
|
TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
|
|
FaceRef.Orientation(TopAbs_FORWARD);
|
|
lf.Remove(itl);
|
|
|
|
TopTools_ListOfShape NewWires;
|
|
|
|
TopTools_DataMapOfShapeInteger SectionsTimes;
|
|
for (itl.Initialize(aLInside); itl.More(); itl.Next())
|
|
SectionsTimes.Bind(itl.Value(), 2);
|
|
|
|
TopTools_ListOfShape BreakVertices;
|
|
TopTools_ListOfShape BreakOnWires;
|
|
|
|
TopTools_DataMapOfShapeShape VerWireMap;
|
|
Standard_Integer i;
|
|
TopExp_Explorer ExploF, ExploW;
|
|
for (itl.Initialize(aLInside); itl.More(); itl.Next())
|
|
{
|
|
const TopoDS_Wire& aSection = TopoDS::Wire(itl.Value());
|
|
TopoDS_Vertex Ver [2];
|
|
TopExp::Vertices(aSection, Ver[0], Ver[1]);
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
if (VerWireMap.IsBound(Ver[i]))
|
|
continue;
|
|
for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
|
|
{
|
|
const TopoDS_Shape& aWire = ExploF.Current();
|
|
TopoDS_Shape aVer;
|
|
for (ExploW.Init(aWire, TopAbs_VERTEX); ExploW.More(); ExploW.Next())
|
|
{
|
|
aVer = ExploW.Current();
|
|
if (aVer.IsSame(Ver[i]))
|
|
break;
|
|
}
|
|
if (aVer.IsSame(Ver[i]))
|
|
{
|
|
VerWireMap.Bind(aVer, aWire);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TopTools_DataMapOfShapeListOfShape VerSecMap;
|
|
for (itl.Initialize(aLInside); itl.More(); itl.Next())
|
|
{
|
|
const TopoDS_Wire& aWire = TopoDS::Wire(itl.Value());
|
|
TopoDS_Vertex V1, V2;
|
|
TopExp::Vertices(aWire, V1, V2);
|
|
TopTools_ListOfShape LW1, LW2;
|
|
if (!VerSecMap.IsBound(V1))
|
|
VerSecMap.Bind(V1, LW1);
|
|
VerSecMap(V1).Append(aWire);
|
|
if (!VerSecMap.IsBound(V2))
|
|
VerSecMap.Bind(V2, LW2);
|
|
VerSecMap(V2).Append(aWire);
|
|
}
|
|
|
|
//TopTools_IndexedDataMapOfShapeShape InnerTouchingWiresOnVertex;
|
|
|
|
TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
|
|
TopoDS_Wire CurWire = outerW;
|
|
BRepLib_MakeWire *MW;
|
|
MW = new BRepLib_MakeWire();
|
|
BRepTools_WireExplorer wexp(CurWire, FaceRef);
|
|
for (;;)
|
|
{
|
|
TopoDS_Vertex theStartVertex = wexp.CurrentVertex(), CurVertex;
|
|
TopoDS_Edge CurEdge = wexp.Current();
|
|
TopoDS_Edge LastEdge = CurEdge;
|
|
MW->Add(CurEdge);
|
|
TopoDS_Wire aSectionWire;
|
|
TopoDS_Vertex aBreakVertex;
|
|
wexp.Next();
|
|
if (!wexp.More())
|
|
wexp.Init(CurWire, FaceRef);
|
|
for (;;)
|
|
{
|
|
if (MW->Wire().Closed())
|
|
break;
|
|
CurVertex = wexp.CurrentVertex();
|
|
if (VerSecMap.IsBound(CurVertex))
|
|
{
|
|
TopoDS_Shape aLocalWire = ChooseDirection(LastEdge, CurVertex, FaceRef, VerSecMap(CurVertex));
|
|
aSectionWire = TopoDS::Wire(aLocalWire);
|
|
break;
|
|
}
|
|
CurEdge = wexp.Current();
|
|
MW->Add(CurEdge);
|
|
LastEdge = CurEdge;
|
|
wexp.Next();
|
|
if (!wexp.More())
|
|
wexp.Init(CurWire, FaceRef);
|
|
}
|
|
if (MW->Wire().Closed())
|
|
{
|
|
NewWires.Append(MW->Wire());
|
|
theStartVertex = TopoDS::Vertex(BreakVertices.First());
|
|
BreakVertices.RemoveFirst();
|
|
CurWire = TopoDS::Wire(BreakOnWires.First());
|
|
BreakOnWires.RemoveFirst();
|
|
wexp.Init(CurWire, FaceRef);
|
|
while (!wexp.CurrentVertex().IsSame(theStartVertex))
|
|
wexp.Next();
|
|
MW = new BRepLib_MakeWire();
|
|
continue;
|
|
}
|
|
aBreakVertex = CurVertex;
|
|
BreakVertices.Append(aBreakVertex);
|
|
BreakOnWires.Append(CurWire);
|
|
for (;;)
|
|
{
|
|
MW->Add(aSectionWire);
|
|
(SectionsTimes(aSectionWire))--;
|
|
if (SectionsTimes(aSectionWire) == 0)
|
|
SectionsTimes.UnBind(aSectionWire);
|
|
if (MW->Wire().Closed())
|
|
{
|
|
NewWires.Append(MW->Wire());
|
|
if (SectionsTimes.IsEmpty())
|
|
break;
|
|
theStartVertex = TopoDS::Vertex(BreakVertices.First());
|
|
BreakVertices.RemoveFirst();
|
|
CurWire = TopoDS::Wire(BreakOnWires.First());
|
|
BreakOnWires.RemoveFirst();
|
|
wexp.Init(CurWire, FaceRef);
|
|
while (!wexp.CurrentVertex().IsSame(theStartVertex))
|
|
wexp.Next();
|
|
MW = new BRepLib_MakeWire();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
TopoDS_Vertex V1, V2, aStartVertex;
|
|
TopExp::Vertices(aSectionWire, V1, V2);
|
|
aStartVertex = (V1.IsSame(aBreakVertex))? V2 : V1;
|
|
CurWire = TopoDS::Wire(VerWireMap(aStartVertex));
|
|
|
|
wexp.Init(CurWire, FaceRef);
|
|
while (!wexp.CurrentVertex().IsSame(aStartVertex))
|
|
wexp.Next();
|
|
|
|
const TopTools_ListOfShape& Lsections = VerSecMap(aStartVertex);
|
|
if (Lsections.Extent() == 1)
|
|
break;
|
|
|
|
//else: choose the way
|
|
TopoDS_Wire NextSectionWire =
|
|
TopoDS::Wire((aSectionWire.IsSame(Lsections.First()))? Lsections.Last() : Lsections.First());
|
|
|
|
Standard_Integer Times = 0;
|
|
TopTools_DataMapIteratorOfDataMapOfShapeShape itVW(VerWireMap);
|
|
for (; itVW.More(); itVW.Next())
|
|
if (itVW.Value().IsSame(CurWire))
|
|
Times++;
|
|
if (Times == 1) //it is inner touching wire
|
|
{
|
|
//InnerTouchingWiresOnVertex.Bind(aWire, aStartVertex);
|
|
}
|
|
else
|
|
{
|
|
//we have to choose the direction
|
|
TopoDS_Edge aStartEdge = wexp.Current();
|
|
TopTools_ListOfShape Ldirs;
|
|
Ldirs.Append(aStartEdge);
|
|
Ldirs.Append(NextSectionWire);
|
|
TopoDS_Shape theDirection = ChooseDirection(aSectionWire, aStartVertex, FaceRef, Ldirs);
|
|
if (theDirection.IsSame(aStartEdge))
|
|
break;
|
|
}
|
|
aSectionWire = NextSectionWire;
|
|
aBreakVertex = aStartVertex;
|
|
} //end of else (MW is not closed)
|
|
} //end of for (;;) (loop on section wires)
|
|
if (SectionsTimes.IsEmpty())
|
|
break;
|
|
} //end of global for (;;)
|
|
|
|
TopTools_ListOfShape NewFaces;
|
|
BRep_Builder BB;
|
|
for (itl.Initialize(NewWires); itl.More(); itl.Next())
|
|
{
|
|
TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
|
|
TopoDS_Face aNewFace = TopoDS::Face(aLocalFace);
|
|
aNewFace.Orientation(TopAbs_FORWARD);
|
|
BB.Add(aNewFace, itl.Value());
|
|
NewFaces.Append(aNewFace);
|
|
}
|
|
|
|
//Inserting holes
|
|
TopTools_ListOfShape Holes;
|
|
for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
|
|
{
|
|
const TopoDS_Shape& aWire = ExploF.Current();
|
|
ExploW.Init(aWire, TopAbs_EDGE);
|
|
TopoDS_Shape anEdge = ExploW.Current();
|
|
Standard_Boolean found = Standard_False;
|
|
for (itl.Initialize(NewWires); itl.More(); itl.Next())
|
|
{
|
|
const TopoDS_Shape& aNewWire = itl.Value();
|
|
for (ExploW.Init(aNewWire, TopAbs_EDGE); ExploW.More(); ExploW.Next())
|
|
{
|
|
if (anEdge.IsSame(ExploW.Current()))
|
|
{
|
|
found = Standard_True;
|
|
break;
|
|
}
|
|
}
|
|
if (found)
|
|
break;
|
|
}
|
|
if (!found)
|
|
Holes.Append(aWire);
|
|
}
|
|
TopTools_ListIteratorOfListOfShape itlNewF;
|
|
for (itl.Initialize(Holes); itl.More(); itl.Next())
|
|
{
|
|
const TopoDS_Wire& aHole = TopoDS::Wire(itl.Value());
|
|
for (itlNewF.Initialize(NewFaces); itlNewF.More(); itlNewF.Next())
|
|
{
|
|
TopoDS_Face& aNewFace = TopoDS::Face(itlNewF.Value());
|
|
if (IsInside(aNewFace, aHole))
|
|
{
|
|
BB.Add(aNewFace, aHole);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Update "myMap"
|
|
lf.Append(NewFaces);
|
|
|
|
//Update of descendants of wires
|
|
for (ExploF.Init(F, TopAbs_WIRE); ExploF.More(); ExploF.Next())
|
|
{
|
|
TopTools_ListOfShape& ls = myMap(ExploF.Current());
|
|
ls.Clear();
|
|
}
|
|
///////////////////
|
|
|
|
// JAG 10.11.95 Codage des regularites
|
|
for (itl.Initialize(aLInside); itl.More(); itl.Next())
|
|
for (ExploW.Init(itl.Value(), TopAbs_EDGE); ExploW.More(); ExploW.Next())
|
|
{
|
|
const TopoDS_Edge& edg = TopoDS::Edge(ExploW.Current());
|
|
if (!BRep_Tool::HasContinuity(edg,F,F)) {
|
|
BB.Continuity(edg,F,F,GeomAbs_CN);
|
|
}
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LocOpe_SplitShape::Add(const TopoDS_Wire& W,
|
|
const TopoDS_Face& F)
|
|
{
|
|
|
|
if (myDone) {
|
|
return Standard_False;
|
|
}
|
|
|
|
|
|
TopExp_Explorer exp;
|
|
TopTools_ListOfShape& lf = myMap(F);
|
|
if (lf.IsEmpty()) {
|
|
Rebuild(F);
|
|
}
|
|
try {
|
|
OCC_CATCH_SIGNALS
|
|
if (!LocOpe::Closed(W,F)) {
|
|
if(!AddOpenWire(W,F))
|
|
return Standard_False;
|
|
}
|
|
else {
|
|
if(!AddClosedWire(W,F))
|
|
return Standard_False;
|
|
}
|
|
} catch (Standard_Failure const&) {
|
|
#ifdef OCCT_DEBUG
|
|
std::cout << "Warning: SpliShape internal problem detected, some faces may be lost. Check input edges/wires" <<std::endl;
|
|
#endif
|
|
return Standard_False;
|
|
}
|
|
// JAG 10.11.95 Codage des regularites
|
|
BRep_Builder B;
|
|
for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
if (!BRep_Tool::HasContinuity(edg,F,F)) {
|
|
B.Continuity(edg,F,F,GeomAbs_CN);
|
|
}
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
|
|
|
|
//=======================================================================
|
|
//function : AddClosedWire
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
|
|
const TopoDS_Face& F)
|
|
{
|
|
TopExp_Explorer exp;
|
|
|
|
// On cherche la face descendante de F qui continent le wire
|
|
TopTools_ListOfShape& lf = myMap(F);
|
|
TopTools_ListIteratorOfListOfShape itl(lf);
|
|
TopoDS_Wire outerW;
|
|
for (; itl.More(); itl.Next()) {
|
|
const TopoDS_Face& fac = TopoDS::Face(itl.Value());
|
|
|
|
if (IsInside(fac,W)) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
if (!itl.More()) {
|
|
return Standard_False;
|
|
}
|
|
|
|
BRep_Builder B;
|
|
|
|
TopAbs_Orientation orWire = W.Orientation();
|
|
TopoDS_Shape aLocalFace = F.EmptyCopied();
|
|
TopoDS_Face newFace = TopoDS::Face(aLocalFace);
|
|
// TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
|
|
newFace.Orientation(TopAbs_FORWARD);
|
|
B.Add(newFace,W);
|
|
// GProp_GProps GP;
|
|
// BRepGProp::SurfaceProperties (newFace,GP);
|
|
// if (GP.Mass() < 0) {
|
|
BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
|
|
if (classif.PerformInfinitePoint() == TopAbs_IN) {
|
|
//le wire donne defini un trou
|
|
aLocalFace = F.EmptyCopied();
|
|
newFace = TopoDS::Face(aLocalFace);
|
|
// newFace = TopoDS::Face(F.EmptyCopied());
|
|
newFace.Orientation(TopAbs_FORWARD);
|
|
orWire = TopAbs::Reverse(orWire);
|
|
B.Add(newFace,W.Oriented(orWire));
|
|
}
|
|
|
|
TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
|
|
FaceRef.Orientation(TopAbs_FORWARD);
|
|
lf.Remove(itl);
|
|
|
|
aLocalFace = FaceRef.EmptyCopied();
|
|
TopoDS_Face newRef = TopoDS::Face(aLocalFace);
|
|
// TopoDS_Face newRef = TopoDS::Face(FaceRef.EmptyCopied());
|
|
newRef.Orientation(TopAbs_FORWARD);
|
|
|
|
// On suppose que les edges du wire ont des courbes 2d.
|
|
// Comme on ne change pas de surface de base, pas besoin d`UpdateEdge.
|
|
|
|
for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
|
|
exp.More(); exp.Next()) {
|
|
const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
|
|
if (IsInside(F,wir,W)) {
|
|
B.Add(newFace,wir);
|
|
}
|
|
else {
|
|
B.Add(newRef,wir);
|
|
}
|
|
}
|
|
B.Add(newRef,W.Oriented(TopAbs::Reverse(orWire)));
|
|
lf.Append(newRef);
|
|
lf.Append(newFace);
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : checkOverlapping
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
static Standard_Boolean checkOverlapping(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2,
|
|
const TopoDS_Face& theFace)
|
|
{
|
|
|
|
BRepAdaptor_Surface anAdS(theFace,Standard_False );
|
|
|
|
Standard_Real MaxTol = (BRep_Tool::Tolerance(theEdge1) + BRep_Tool::Tolerance(theEdge2));
|
|
|
|
Standard_Real aMaxTol2d = Max(anAdS.UResolution(MaxTol),anAdS.VResolution(MaxTol));
|
|
Standard_Real aTolAng = M_PI/180.;
|
|
Geom2dAPI_ProjectPointOnCurve proj;
|
|
Standard_Real aF1, aL1,aF2, aL2;
|
|
|
|
Handle(Geom2d_Curve) aCrv1 = BRep_Tool::CurveOnSurface(theEdge1, theFace, aF1, aL1);
|
|
Handle(Geom2d_Curve) aCrv2 = BRep_Tool::CurveOnSurface(theEdge2, theFace, aF2, aL2);
|
|
Standard_Integer j =1, nbP = 4;
|
|
Standard_Real aStep = ( aL2 - aF2)/nbP;
|
|
for( ; j < nbP; j++)
|
|
{
|
|
Standard_Real par2 = aF2 + aStep * j;
|
|
gp_Pnt2d aP2d;
|
|
gp_Vec2d aV2;
|
|
aCrv2->D1(par2, aP2d, aV2);
|
|
|
|
proj.Init(aP2d,aCrv1, aF1, aL1);
|
|
//check intermediate points
|
|
if(!proj.NbPoints() || proj.LowerDistance() > aMaxTol2d)
|
|
return Standard_False;
|
|
Standard_Real par1 = proj.LowerDistanceParameter();
|
|
gp_Pnt2d aP2d1;
|
|
gp_Vec2d aV1;
|
|
aCrv1->D1(par1, aP2d1, aV1);
|
|
|
|
if( !aV1.IsParallel(aV2, aTolAng))
|
|
return Standard_False;
|
|
}
|
|
return Standard_True;
|
|
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : AddOpenWire
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
|
|
const TopoDS_Face& F)
|
|
{
|
|
// On cherche la face descendante de F qui continent le wire
|
|
TopTools_ListOfShape& lf = myMap(F);
|
|
TopTools_ListIteratorOfListOfShape itl(lf);
|
|
TopoDS_Vertex Vfirst,Vlast;
|
|
|
|
BRepTools::Update(F);
|
|
|
|
Standard_Real tolf, toll, tol1;
|
|
|
|
TopoDS_Shape aLocalShape = W.Oriented(TopAbs_FORWARD);
|
|
TopExp::Vertices(TopoDS::Wire(aLocalShape),Vfirst,Vlast);
|
|
|
|
tolf = BRep_Tool::Tolerance(Vfirst);
|
|
toll = BRep_Tool::Tolerance(Vlast);
|
|
tol1 = Max(tolf, toll);
|
|
|
|
|
|
TopExp_Explorer exp,exp2;
|
|
|
|
TopoDS_Wire wfirst,wlast;
|
|
for (; itl.More(); itl.Next()) {
|
|
TopoDS_Face fac = TopoDS::Face(itl.Value());
|
|
if (!IsInside(fac,W)) {
|
|
continue;
|
|
}
|
|
|
|
fac.Orientation(TopAbs_FORWARD);
|
|
Standard_Boolean ffound = Standard_False;
|
|
Standard_Boolean lfound = Standard_False;
|
|
for (exp.Init(fac,TopAbs_WIRE); exp.More(); exp.Next()) {
|
|
const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
|
|
for (exp2.Init(wir,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
|
|
if (!ffound && exp2.Current().IsSame(Vfirst)) {
|
|
ffound = Standard_True;
|
|
wfirst = wir;
|
|
}
|
|
else if (!lfound && exp2.Current().IsSame(Vlast)) {
|
|
lfound = Standard_True;
|
|
wlast = wir;
|
|
}
|
|
if (ffound && lfound) {
|
|
break;
|
|
}
|
|
}
|
|
if (exp2.More()) {
|
|
break;
|
|
}
|
|
}
|
|
if (exp.More()) {
|
|
break;
|
|
}
|
|
}
|
|
if (!itl.More()) {
|
|
return Standard_False;
|
|
}
|
|
|
|
TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
|
|
FaceRef.Orientation(TopAbs_FORWARD);
|
|
lf.Remove(itl);
|
|
BRep_Builder B;
|
|
|
|
BRepAdaptor_Surface BAS(FaceRef, Standard_False);
|
|
|
|
Standard_Boolean IsPeriodic = BAS.IsUPeriodic() || BAS.IsVPeriodic();
|
|
|
|
tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
|
|
|
|
if (wfirst.IsSame(wlast)) {
|
|
// on cree 2 faces en remplacement de itl.Value()
|
|
// Essai JAG
|
|
TopTools_ListOfShape WiresFirst;
|
|
for (exp.Init(wfirst,TopAbs_EDGE); exp.More(); exp.Next()) {
|
|
if (BRep_Tool::IsClosed(TopoDS::Edge(exp.Current()),FaceRef)) {
|
|
myDblE.Add(exp.Current());
|
|
}
|
|
WiresFirst.Append(exp.Current());
|
|
}
|
|
|
|
TopAbs_Orientation orient;
|
|
TopoDS_Wire newW1,newW2;
|
|
B.MakeWire(newW1);
|
|
newW1.Orientation(TopAbs_FORWARD);
|
|
B.MakeWire(newW2);
|
|
newW2.Orientation(TopAbs_FORWARD);
|
|
|
|
Standard_Integer nbE = 0;
|
|
for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
|
|
exp.More(); exp.Next()) {
|
|
nbE++;
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
orient = edg.Orientation();
|
|
WiresFirst.Append(edg);
|
|
WiresFirst.Append(edg.Oriented(TopAbs::Reverse(orient)));
|
|
myDblE.Add(edg);
|
|
}
|
|
|
|
TopTools_IndexedMapOfShape PossE;
|
|
TopTools_MapOfOrientedShape MapE;
|
|
TopoDS_Vertex vdeb,vfin;
|
|
Standard_Integer nbPoss;
|
|
|
|
// On recherche l`edge contenant Vlast
|
|
TopoDS_Edge LastEdge;
|
|
gp_Pnt2d pfirst,plast;
|
|
gp_Vec2d dlast;
|
|
Handle(Geom2d_Curve) C2d;
|
|
Standard_Real f,l;
|
|
|
|
for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
|
|
exp.More(); exp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
|
|
if (exp2.Current().IsSame(Vfirst)) {
|
|
break;
|
|
}
|
|
}
|
|
if (exp2.More()) {
|
|
LastEdge = edg;
|
|
LastEdge.Orientation(edg.Orientation());
|
|
break;
|
|
}
|
|
}
|
|
|
|
TopoDS_Shape aLocalFace = FaceRef.Oriented(wfirst.Orientation());
|
|
C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l);
|
|
|
|
if (LastEdge.Orientation() == TopAbs_FORWARD) {
|
|
pfirst = C2d->Value(f);
|
|
}
|
|
else {
|
|
pfirst = C2d->Value(l);
|
|
}
|
|
|
|
for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
|
|
exp.More(); exp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
if( nbE>1 && edg.IsSame(LastEdge) )
|
|
continue;
|
|
for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
|
|
if (exp2.Current().IsSame(Vlast)) {
|
|
break;
|
|
}
|
|
}
|
|
if (exp2.More()) {
|
|
LastEdge = edg;
|
|
LastEdge.Orientation(edg.Orientation());
|
|
break;
|
|
}
|
|
}
|
|
aLocalFace = FaceRef.Oriented(wfirst.Orientation());
|
|
GetDirection(LastEdge, TopoDS::Face(aLocalFace),plast , dlast, Standard_False);
|
|
|
|
Standard_Boolean cond = Standard_True;
|
|
|
|
if(IsPeriodic) {
|
|
|
|
cond = !(Vfirst.IsSame(Vlast) && SameUV(pfirst,plast,BAS));
|
|
}
|
|
else {
|
|
cond = !(Vfirst.IsSame(Vlast));
|
|
}
|
|
|
|
while (cond) {
|
|
PossE.Clear();
|
|
|
|
// On enchaine par la fin
|
|
TopTools_ListIteratorOfListOfShape lexp(WiresFirst);
|
|
for (; lexp.More(); lexp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value());
|
|
|
|
orient = edg.Orientation();
|
|
TopExp::Vertices(edg,vdeb,vfin);
|
|
|
|
if ((orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) ||
|
|
(orient == TopAbs_REVERSED && Vlast.IsSame(vfin)))
|
|
PossE.Add(edg);
|
|
}
|
|
nbPoss = PossE.Extent();
|
|
if (nbPoss == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
TopoDS_Edge aNextEdge;
|
|
if (nbPoss == 1) {
|
|
aNextEdge = TopoDS::Edge (PossE.FindKey (1));
|
|
TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation());
|
|
GetDirection(aNextEdge, TopoDS::Face(aLocalFaceTemp),plast , dlast, Standard_False);
|
|
|
|
}
|
|
else if (nbPoss > 1) {
|
|
// Faire choix en U,V...
|
|
TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation());
|
|
|
|
if(!ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE,
|
|
aNextEdge, plast, dlast))
|
|
return Standard_False;
|
|
|
|
}
|
|
|
|
if (nbPoss >= 1) {
|
|
if (aNextEdge.IsNull())
|
|
{
|
|
// loop is not closed. Split is not possible
|
|
return Standard_False;
|
|
}
|
|
|
|
if (MapE.Contains(aNextEdge))
|
|
break;
|
|
B.Add(newW1, aNextEdge);
|
|
MapE.Add(aNextEdge);
|
|
LastEdge = aNextEdge;
|
|
|
|
if (LastEdge.Orientation() == TopAbs_FORWARD) {
|
|
Vlast = TopExp::LastVertex(LastEdge);
|
|
}
|
|
else {
|
|
Vlast = TopExp::FirstVertex(LastEdge);
|
|
}
|
|
|
|
toll = BRep_Tool::Tolerance(Vlast);
|
|
tol1 = Max(tolf, toll);
|
|
|
|
}
|
|
//MODIFICATION PIERRE SMEYERS : si pas de possibilite, on sort avec erreur
|
|
else{
|
|
std::cout<<"erreur Spliter : pas de chainage du wire"<<std::endl;
|
|
return Standard_False;
|
|
}
|
|
//fin MODIF.
|
|
|
|
tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
|
|
|
|
}
|
|
|
|
Standard_Integer nbAddBound =0;
|
|
TopTools_ListIteratorOfListOfShape lexp(WiresFirst);
|
|
TopoDS_Shape anE1, anE2;
|
|
for (; lexp.More(); lexp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value());
|
|
if (!MapE.Contains(edg)) {
|
|
B.Add(newW2,edg);
|
|
MapE.Add(edg);
|
|
nbAddBound++;
|
|
if(anE1.IsNull())
|
|
anE1 = edg;
|
|
else
|
|
anE2 = edg;
|
|
|
|
}
|
|
}
|
|
//check overlapping edges for second face
|
|
if(nbAddBound <2)
|
|
return Standard_False;
|
|
if(nbAddBound ==2 && !anE1.IsNull() && !anE2.IsNull())
|
|
{
|
|
if(checkOverlapping(TopoDS::Edge(anE1), TopoDS::Edge(anE2),FaceRef ))
|
|
return Standard_False;
|
|
|
|
}
|
|
|
|
nbAddBound =0;
|
|
|
|
TopoDS_Shape anE11, anE12;
|
|
TopoDS_Iterator anItE(newW1, Standard_False);
|
|
for( ; anItE.More(); anItE.Next())
|
|
{
|
|
if( anItE.Value().ShapeType() != TopAbs_EDGE)
|
|
continue;
|
|
nbAddBound++;
|
|
if(anE11.IsNull())
|
|
anE11 = anItE.Value();
|
|
else
|
|
anE12 = anItE.Value();
|
|
|
|
}
|
|
//check overlapping edges for first face
|
|
if(nbAddBound <2)
|
|
return Standard_False;
|
|
if(nbAddBound ==2 && !anE11.IsNull() && !anE12.IsNull())
|
|
{
|
|
if(checkOverlapping(TopoDS::Edge(anE11), TopoDS::Edge(anE12), FaceRef))
|
|
return Standard_False;
|
|
|
|
}
|
|
|
|
TopoDS_Face newF1,newF2;
|
|
aLocalFace = FaceRef.EmptyCopied();
|
|
newF1 = TopoDS::Face(aLocalFace);
|
|
newF1.Orientation(TopAbs_FORWARD);
|
|
aLocalFace = FaceRef.EmptyCopied();
|
|
newF2 = TopoDS::Face(aLocalFace);
|
|
newF2.Orientation(TopAbs_FORWARD);
|
|
|
|
// modifs JAG 97.05.28
|
|
|
|
B.Add(newF1,newW1);
|
|
B.Add(newF2,newW2);
|
|
for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); exp.More(); exp.Next()) {
|
|
const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
|
|
if (!wir.IsSame(wfirst)) {
|
|
if (IsInside(newF1, wir)) {
|
|
B.Add(newF1,wir);
|
|
}
|
|
else if (IsInside(newF2, wir)) {
|
|
B.Add(newF2,wir);
|
|
}
|
|
else {
|
|
// Ce wire est ni dans newF2 ni dans newF1
|
|
// Peut etre faut il construire une troisieme face
|
|
std::cout << "WARNING: LocOpe_SPlitShape : Ce wire est ni dans newF2 ni dans newF1" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
lf.Append(newF1);
|
|
lf.Append(newF2);
|
|
|
|
// Mise a jour des descendants des wires
|
|
for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
|
|
TopTools_ListOfShape& ls = myMap(exp.Current());
|
|
itl.Initialize(ls);
|
|
for (; itl.More(); itl.Next()) {
|
|
if (itl.Value().IsSame(wfirst)) {
|
|
break;
|
|
}
|
|
}
|
|
if (itl.More()) { // on a trouve le wire
|
|
ls.Remove(itl);
|
|
ls.Append(newW1);
|
|
ls.Append(newW2);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// on ne cree qu`une seule face
|
|
TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
|
|
TopoDS_Wire newWire;
|
|
TopoDS_Face newFace;
|
|
B.MakeWire(newWire);
|
|
newWire.Orientation(TopAbs_FORWARD);
|
|
TopAbs_Orientation orient,orRelat;
|
|
|
|
if (wfirst.Orientation() == wlast.Orientation()) {
|
|
orRelat = TopAbs_FORWARD;
|
|
}
|
|
else {
|
|
orRelat = TopAbs_REVERSED;
|
|
}
|
|
|
|
if (wlast.IsSame(outerW)) {
|
|
wlast = wfirst;
|
|
wfirst = outerW;
|
|
}
|
|
|
|
// Edges de wfirst
|
|
for (exp.Init(wfirst.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
|
|
exp.More(); exp.Next()) {
|
|
B.Add(newWire,TopoDS::Edge(exp.Current()));
|
|
}
|
|
|
|
// Edges de wlast
|
|
for (exp.Init(wlast.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
|
|
exp.More(); exp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
orient = TopAbs::Compose(edg.Orientation(),orRelat);
|
|
B.Add(newWire,edg.Oriented(orient));
|
|
}
|
|
|
|
|
|
// Edges du wire ajoute, et dans les 2 sens
|
|
for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
|
|
exp.More(); exp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
orient = edg.Orientation();
|
|
B.Add(newWire,edg.Oriented(orient));
|
|
B.Add(newWire,edg.Oriented(TopAbs::Reverse(orient)));
|
|
myDblE.Add(edg.Oriented(orient));
|
|
}
|
|
|
|
// on refait une face
|
|
|
|
TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
|
|
newFace = TopoDS::Face(aLocalFace);
|
|
// newFace = TopoDS::Face(FaceRef.EmptyCopied());
|
|
FaceRef.Orientation(TopAbs_FORWARD);
|
|
for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
|
|
exp.More(); exp.Next()) {
|
|
const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
|
|
if (wir.IsSame(wfirst)) {
|
|
B.Add(newFace,newWire.Oriented(wir.Orientation()));
|
|
}
|
|
else if (!wir.IsSame(wlast)) {
|
|
B.Add(newFace,wir);
|
|
}
|
|
}
|
|
lf.Append(newFace);
|
|
|
|
// Mise a jour des descendants des wires
|
|
for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
|
|
TopTools_ListOfShape& ls = myMap(exp.Current());
|
|
itl.Initialize(ls);
|
|
Standard_Boolean touch = Standard_False;
|
|
while (itl.More()) {
|
|
if (itl.Value().IsSame(wfirst) || itl.Value().IsSame(wlast)) {
|
|
ls.Remove(itl);
|
|
touch = Standard_True;
|
|
}
|
|
else {
|
|
itl.Next();
|
|
}
|
|
}
|
|
if (touch) {
|
|
ls.Append(newWire);
|
|
}
|
|
|
|
}
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : LeftOf
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopTools_ListOfShape& LocOpe_SplitShape::LeftOf(const TopoDS_Wire& W,
|
|
const TopoDS_Face& F)
|
|
{
|
|
if (myShape.IsNull()) {
|
|
throw Standard_NoSuchObject();
|
|
}
|
|
|
|
TopExp_Explorer exp,expw,expf;
|
|
exp.Init(myShape,TopAbs_FACE);
|
|
for (; exp.More(); exp.Next()) {
|
|
if (exp.Current().IsSame(F)) {
|
|
break;
|
|
}
|
|
}
|
|
if (!exp.More()) {
|
|
throw Standard_NoSuchObject();
|
|
}
|
|
myLeft.Clear();
|
|
|
|
const TopoDS_Face& theFace = TopoDS::Face(exp.Current());
|
|
TopAbs_Orientation orFace = theFace.Orientation();
|
|
TopTools_ListIteratorOfListOfShape itl,itl2;
|
|
|
|
for (expw.Init(W,TopAbs_EDGE); expw.More(); expw.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(expw.Current());
|
|
for (itl.Initialize(myMap(theFace)); itl.More(); itl.Next()) {
|
|
TopoDS_Face fac = TopoDS::Face(itl.Value());
|
|
fac.Orientation(orFace);
|
|
for (expf.Init(fac,TopAbs_EDGE); expf.More(); expf.Next()) {
|
|
const TopoDS_Edge& edgbis = TopoDS::Edge(expf.Current());
|
|
if (edgbis.IsSame(edg) &&
|
|
edgbis.Orientation() == edg.Orientation()) {
|
|
for (itl2.Initialize(myLeft); itl2.More(); itl2.Next()) {
|
|
if (itl2.Value().IsSame(fac)) {
|
|
break;
|
|
}
|
|
}
|
|
if (!itl2.More()) { // la face n`est pas deja presente
|
|
myLeft.Append(fac);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (expf.More()) { // face found
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return myLeft;
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : DescendantShapes
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
const TopTools_ListOfShape& LocOpe_SplitShape::DescendantShapes
|
|
(const TopoDS_Shape& S)
|
|
{
|
|
if (!myDone) {
|
|
Rebuild(myShape);
|
|
myDone = Standard_True;
|
|
}
|
|
#ifdef OCCT_DEBUG
|
|
if (!myDblE.IsEmpty()) {
|
|
std::cout << "Le shape comporte des faces invalides" << std::endl;
|
|
}
|
|
#endif
|
|
return myMap(S);
|
|
}
|
|
|
|
|
|
|
|
//=======================================================================
|
|
//function : Put
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void LocOpe_SplitShape::Put(const TopoDS_Shape& S)
|
|
{
|
|
if (!myMap.IsBound(S)) {
|
|
TopTools_ListOfShape thelist;
|
|
myMap.Bind(S, thelist);
|
|
if (S.ShapeType() != TopAbs_VERTEX) {
|
|
for(TopoDS_Iterator theIterator(S);theIterator.More();
|
|
theIterator.Next()) {
|
|
Put(theIterator.Value());
|
|
}
|
|
}
|
|
else {
|
|
myMap(S).Append(S);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void updateToleraces(const TopoDS_Face& theFace, const TopTools_DataMapOfShapeListOfShape& theMap)
|
|
{
|
|
TopExp_Explorer aExpE(theFace, TopAbs_EDGE);
|
|
for (; aExpE.More(); aExpE.Next())
|
|
{
|
|
if (!theMap.IsBound(aExpE.Current()))
|
|
continue;
|
|
const TopTools_ListOfShape& lEdges = theMap(aExpE.Current());
|
|
if (lEdges.Extent() <= 1)
|
|
continue;
|
|
|
|
TopTools_ListIteratorOfListOfShape itrE(lEdges);
|
|
ShapeAnalysis_Edge aSae;
|
|
|
|
for (; itrE.More(); itrE.Next())
|
|
{
|
|
TopoDS_Edge aCurE = TopoDS::Edge(itrE.Value());
|
|
Standard_Real amaxdev = 0.;
|
|
if (aSae.CheckSameParameter(aCurE, theFace, amaxdev))
|
|
{
|
|
BRep_Builder aB;
|
|
aB.UpdateEdge(aCurE, amaxdev);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
//=======================================================================
|
|
//function : Rebuild
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean LocOpe_SplitShape::Rebuild(const TopoDS_Shape& S)
|
|
|
|
{
|
|
if (S.ShapeType() == TopAbs_FACE)
|
|
updateToleraces(TopoDS::Face(S), myMap);
|
|
TopTools_ListIteratorOfListOfShape itr(myMap(S));
|
|
if (itr.More()) {
|
|
if (itr.Value().IsSame(S)) {
|
|
return Standard_False;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
Standard_Boolean rebuild = Standard_False;
|
|
TopoDS_Iterator it;
|
|
for(it.Initialize(S); it.More(); it.Next()) {
|
|
rebuild = Rebuild(it.Value()) || rebuild;
|
|
}
|
|
|
|
if (rebuild) {
|
|
BRep_Builder B;
|
|
TopoDS_Shape result = S.EmptyCopied();
|
|
TopAbs_Orientation orient;
|
|
for(it.Initialize(S); it.More(); it.Next()) {
|
|
orient = it.Value().Orientation();
|
|
for (itr.Initialize(myMap(it.Value())); itr.More(); itr.Next()) {
|
|
B.Add(result,itr.Value().Oriented(orient));
|
|
}
|
|
}
|
|
// Assign "Closed" flag for Wires and Shells only
|
|
if (result.ShapeType() == TopAbs_WIRE || result.ShapeType() == TopAbs_SHELL)
|
|
result.Closed (BRep_Tool::IsClosed(result));
|
|
myMap(S).Append(result);
|
|
}
|
|
else {
|
|
myMap(S).Append(S);
|
|
}
|
|
return rebuild;
|
|
}
|
|
|
|
|
|
|
|
//=======================================================================
|
|
//function : IsInside
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
static Standard_Boolean IsInside(const TopoDS_Face& F,
|
|
const TopoDS_Wire& W1,
|
|
const TopoDS_Wire& W2)
|
|
{
|
|
// Attention, c`est tres boeuf !!!!
|
|
BRep_Builder B;
|
|
TopoDS_Shape aLocalShape = F.EmptyCopied();
|
|
TopoDS_Face newFace = TopoDS::Face(aLocalShape);
|
|
// TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
|
|
|
|
//TopAbs_Orientation orWire = W2.Orientation();
|
|
|
|
newFace.Orientation(TopAbs_FORWARD);
|
|
B.Add(newFace,W2);
|
|
// GProp_GProps GP;
|
|
// BRepGProp::SurfaceProperties(newFace,GP);
|
|
// if (GP.Mass() < 0) {
|
|
BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
|
|
Standard_Boolean Reversed = Standard_False;
|
|
if (classif.PerformInfinitePoint() == TopAbs_IN) {
|
|
//le wire donne defini un trou
|
|
// newFace = TopoDS::Face(F.EmptyCopied());
|
|
// newFace.Orientation(TopAbs_FORWARD);
|
|
// orWire = TopAbs::Reverse(orWire);
|
|
// B.Add(newFace,W2.Oriented(orWire));
|
|
Reversed = Standard_True;
|
|
}
|
|
|
|
// Standard_Real U,V;
|
|
TopExp_Explorer exp(W1,TopAbs_EDGE);
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
TopExp_Explorer exp2(edg,TopAbs_VERTEX);
|
|
const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
|
|
Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
|
|
Standard_Real f,l;
|
|
Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
|
|
if(C2d.IsNull()) {
|
|
#ifdef OCCT_DEBUG
|
|
std::cout << "Edge is not on surface" <<std::endl;
|
|
#endif
|
|
return Standard_False;
|
|
}
|
|
gp_Pnt2d pt2d(C2d->Value(prm));
|
|
// BRepClass_FaceClassifier classif(newFace,pt2d,Precision::PConfusion());
|
|
// return (classif.State() == TopAbs_IN);
|
|
if (!Reversed) {
|
|
return (classif.Perform(pt2d) == TopAbs_IN);
|
|
}
|
|
else {
|
|
return (classif.Perform(pt2d) == TopAbs_OUT);
|
|
}
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : IsInside
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
static Standard_Boolean IsInside(const TopoDS_Face& F,
|
|
const TopoDS_Wire& W)
|
|
{
|
|
// Attention, c`est tres boeuf !!!!
|
|
TopExp_Explorer exp(W,TopAbs_EDGE);
|
|
for( ; exp.More(); exp.Next()) {
|
|
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
|
|
// TopExp_Explorer exp2(edg,TopAbs_VERTEX);
|
|
// const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
|
|
// Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
|
|
Standard_Real f,l,prm;
|
|
Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
|
|
if (!Precision::IsNegativeInfinite(f) &&
|
|
!Precision::IsPositiveInfinite(l)) {
|
|
prm = (f+l)/2.;
|
|
}
|
|
else {
|
|
if (Precision::IsNegativeInfinite(f) &&
|
|
Precision::IsPositiveInfinite(l)){
|
|
prm = 0.;
|
|
}
|
|
else if (Precision::IsNegativeInfinite(f)) {
|
|
prm = l-1.;
|
|
}
|
|
else {
|
|
prm = f+1.;
|
|
}
|
|
}
|
|
|
|
gp_Pnt2d pt2d(C2d->Value(prm));
|
|
// BRepClass_FaceClassifier classif(F,pt2d,Precision::PConfusion());
|
|
// return (classif.State() != TopAbs_OUT);
|
|
BRepTopAdaptor_FClass2d classif(F,Precision::PConfusion());
|
|
TopAbs_State stat = classif.Perform(pt2d);
|
|
// return (classif.Perform(pt2d) != TopAbs_OUT);
|
|
if(stat == TopAbs_OUT) return Standard_False;
|
|
|
|
if(stat == TopAbs_ON) {
|
|
Standard_Integer nbPnt =10;
|
|
Standard_Integer nbOut =0,nbIn =0,nbOn=0;
|
|
Standard_Integer j =1;
|
|
for( ; j<= nbPnt ; j++)
|
|
{
|
|
//check neighbouring point
|
|
//prm = .66 * prm + .34 * l;
|
|
prm = f + (l-f)/nbPnt*(j-1);
|
|
pt2d = C2d->Value(prm);
|
|
stat = classif.Perform(pt2d);
|
|
if(stat == TopAbs_OUT )
|
|
nbOut++;
|
|
else if(stat == TopAbs_IN)
|
|
nbIn++;
|
|
else
|
|
nbOn++;
|
|
}
|
|
if(nbOut > nbIn + nbOn)
|
|
return Standard_False;
|
|
}
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetDirection
|
|
//purpose :
|
|
//=======================================================================
|
|
static void GetDirection(const TopoDS_Edge& theEdge,
|
|
const TopoDS_Face& theFace,
|
|
gp_Pnt2d& thePnt,
|
|
gp_Vec2d& theDir,
|
|
Standard_Boolean isFirstEnd)
|
|
{
|
|
Standard_Real aFirst, aLast;
|
|
Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface (theEdge, theFace, aFirst, aLast);
|
|
|
|
TopAbs_Orientation anOr = theEdge.Orientation();
|
|
TopoDS_Vertex aVtx;
|
|
Standard_Boolean takeFirst = ((anOr == TopAbs_FORWARD && isFirstEnd) ||
|
|
(anOr == TopAbs_REVERSED && !isFirstEnd));
|
|
|
|
Standard_Real dpar = (aLast - aFirst)*0.01;
|
|
gp_Pnt2d aP2d;
|
|
if (takeFirst)
|
|
{
|
|
aC2d->D0 (aFirst, thePnt);
|
|
gp_Pnt2d aNextPnt = aC2d->Value(aFirst + dpar);
|
|
theDir = gp_Vec2d(thePnt, aNextPnt);
|
|
}
|
|
|
|
else
|
|
{
|
|
aC2d->D0 (aLast, thePnt);
|
|
gp_Pnt2d aPrevPnt = aC2d->Value(aLast - dpar);
|
|
theDir = gp_Vec2d( aPrevPnt, thePnt );
|
|
}
|
|
if(anOr == TopAbs_REVERSED)
|
|
theDir.Reverse();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ChoixUV
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
Standard_Boolean ChoixUV(const TopoDS_Edge& Last,
|
|
const TopoDS_Face& F,
|
|
const TopTools_IndexedMapOfShape& Poss,
|
|
TopoDS_Edge& theResEdge,
|
|
gp_Pnt2d& plst,
|
|
gp_Vec2d& dlst)
|
|
{
|
|
gp_Pnt2d p2d;
|
|
gp_Vec2d v2d;
|
|
gp_Pnt aPCur, aPlst;
|
|
|
|
BRepAdaptor_Surface surf(F,Standard_False); // no restriction
|
|
surf.D0 (plst.X(), plst.Y(), aPlst);
|
|
|
|
gp_Dir2d ref2d(dlst);
|
|
|
|
Handle(Geom2d_Curve) C2d;
|
|
|
|
|
|
Standard_Integer index = 0, imin=0;
|
|
Standard_Real angmax = -M_PI, ang;
|
|
|
|
for (index = 1; index <= Poss.Extent(); index++) {
|
|
TopoDS_Edge anEdge = TopoDS::Edge (Poss.FindKey (index));
|
|
|
|
GetDirection(anEdge, F, p2d, v2d, Standard_True);
|
|
if(!SameUV(plst,p2d,surf))
|
|
continue;
|
|
|
|
surf.D0 (p2d.X(), p2d.Y(), aPCur);
|
|
|
|
if (!Last.IsSame(anEdge)) {
|
|
ang = ref2d.Angle(gp_Dir2d(v2d));
|
|
}
|
|
else {
|
|
ang = -M_PI;
|
|
}
|
|
|
|
if ( (ang > angmax)) {
|
|
imin = index;
|
|
angmax = ang;
|
|
}
|
|
}
|
|
|
|
if (imin)
|
|
{
|
|
theResEdge = TopoDS::Edge (Poss.FindKey (imin));
|
|
GetDirection(theResEdge, F, plst, dlst, Standard_False);
|
|
}
|
|
|
|
return imin != 0;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ChooseDirection
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
static TopoDS_Shape ChooseDirection(const TopoDS_Shape& RefDir,
|
|
const TopoDS_Vertex& RefVertex,
|
|
const TopoDS_Face& theFace,
|
|
const TopTools_ListOfShape& Ldirs)
|
|
{
|
|
TopExp_Explorer Explo(RefDir, TopAbs_EDGE);
|
|
TopoDS_Edge RefEdge;
|
|
TopoDS_Vertex V1, V2;
|
|
TopAbs_Orientation anOr = TopAbs_FORWARD;
|
|
for (; Explo.More(); Explo.Next())
|
|
{
|
|
RefEdge = TopoDS::Edge(Explo.Current());
|
|
TopExp::Vertices(RefEdge, V1, V2);
|
|
if (V1.IsSame(RefVertex))
|
|
{
|
|
anOr = TopAbs_REVERSED;
|
|
break;
|
|
}
|
|
else if (V2.IsSame(RefVertex))
|
|
{
|
|
anOr = TopAbs_FORWARD;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Standard_Real RefFirst, RefLast;
|
|
Handle(Geom2d_Curve) RefCurve = BRep_Tool::CurveOnSurface(RefEdge, theFace, RefFirst, RefLast);
|
|
gp_Pnt2d RefPnt;
|
|
gp_Vec2d RefVec;
|
|
|
|
//Standard_Real RefPar = (RefEdge.Orientation() == TopAbs_FORWARD)? RefLast : RefFirst;
|
|
Standard_Real RefPar = (anOr == TopAbs_FORWARD)? RefLast : RefFirst;
|
|
RefCurve->D1(RefPar, RefPnt, RefVec);
|
|
if (anOr == TopAbs_FORWARD)
|
|
RefVec.Reverse();
|
|
|
|
Handle(Geom2d_Curve) aCurve;
|
|
Standard_Real aFirst, aLast, aPar;
|
|
gp_Vec2d aVec;
|
|
Standard_Real MinAngle = RealLast(), anAngle;
|
|
TopoDS_Shape TargetDir;
|
|
TopTools_ListIteratorOfListOfShape itl(Ldirs);
|
|
for (; itl.More(); itl.Next())
|
|
{
|
|
const TopoDS_Shape& aShape = itl.Value();
|
|
TopoDS_Edge anEdge;
|
|
for (Explo.Init(aShape, TopAbs_EDGE); Explo.More(); Explo.Next())
|
|
{
|
|
anEdge = TopoDS::Edge(Explo.Current());
|
|
TopExp::Vertices(anEdge, V1, V2);
|
|
if (V1.IsSame(RefVertex))
|
|
{
|
|
anOr = TopAbs_FORWARD;
|
|
break;
|
|
}
|
|
else if (V2.IsSame(RefVertex))
|
|
{
|
|
anOr = TopAbs_REVERSED;
|
|
break;
|
|
}
|
|
}
|
|
aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, aFirst, aLast);
|
|
aPar = (anOr == TopAbs_FORWARD)? aFirst : aLast;
|
|
aCurve->D1(aPar, RefPnt, aVec);
|
|
if (anOr == TopAbs_REVERSED)
|
|
aVec.Reverse();
|
|
anAngle = aVec.Angle(RefVec);
|
|
if (anAngle < 0.)
|
|
anAngle += 2.*M_PI;
|
|
|
|
if (anAngle < MinAngle)
|
|
{
|
|
MinAngle = anAngle;
|
|
TargetDir = aShape;
|
|
}
|
|
}
|
|
|
|
return TargetDir;
|
|
}
|