mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
Changes: class BOPAlgo_WireSplitter static function: Standard_Boolean RefineAngle2D(const TopoDS_Vertex& aV, const TopoDS_Edge& aE, const TopoDS_Face& myFace, const Standard_Real aA1, const Standard_Real aA2, Standard_Real& aA) The contents of Domain 2D for the straight line has been changed. class BOPTools_AlgoTools2D method: void BOPTools_AlgoTools2D::AdjustPCurveOnFace (const TopoDS_Face& aF, const Standard_Real aFirst, const Standard_Real aLast, const Handle(Geom2d_Curve)& aC2D, Handle(Geom2d_Curve)& aC2DA) The treatment of cylindrical surfaces has been changed taking into account existing values of tolerances of the edges. Test cases for issue CR25163
1078 lines
29 KiB
C++
1078 lines
29 KiB
C++
// Created by: Peter KURNEV
|
|
// 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 <BOPAlgo_WireSplitter.ixx>
|
|
|
|
#include <Precision.hxx>
|
|
|
|
#include <gp_Pnt2d.hxx>
|
|
#include <gp_Vec2d.hxx>
|
|
#include <gp_Dir2d.hxx>
|
|
|
|
#include <Geom_Surface.hxx>
|
|
#include <Geom_Plane.hxx>
|
|
#include <Geom_RectangularTrimmedSurface.hxx>
|
|
#include <Geom2d_Curve.hxx>
|
|
#include <Geom2d_Line.hxx>
|
|
#include <GeomAdaptor_Surface.hxx>
|
|
#include <Geom2dAdaptor_Curve.hxx>
|
|
|
|
#include <Geom2dInt_GInter.hxx>
|
|
#include <IntRes2d_Domain.hxx>
|
|
#include <IntRes2d_IntersectionPoint.hxx>
|
|
|
|
#include <TopLoc_Location.hxx>
|
|
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
|
|
#include <TopTools_ShapeMapHasher.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
|
|
#include <BRepAdaptor_Surface.hxx>
|
|
|
|
#include <BOPCol_ListOfShape.hxx>
|
|
#include <BOPCol_SequenceOfShape.hxx>
|
|
#include <BOPCol_SequenceOfPnt2d.hxx>
|
|
#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
|
|
#include <BOPCol_SequenceOfReal.hxx>
|
|
#include <BOPCol_DataMapOfShapeInteger.hxx>
|
|
#include <BOPCol_MapOfShape.hxx>
|
|
|
|
#include <BOPTools_AlgoTools2D.hxx>
|
|
|
|
typedef NCollection_DataMap \
|
|
<TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher> \
|
|
BOPCol_DataMapOfShapeBoolean;
|
|
//
|
|
|
|
static
|
|
Standard_Real Angle (const gp_Dir2d& aDir2D);
|
|
|
|
static
|
|
Standard_Real Angle2D (const TopoDS_Vertex& aV,
|
|
const TopoDS_Edge& anEdge,
|
|
const TopoDS_Face& myFace,
|
|
const GeomAdaptor_Surface& aGAS,
|
|
const Standard_Boolean aFlag);
|
|
|
|
static
|
|
void GetNextVertex(const TopoDS_Vertex& aV,
|
|
const TopoDS_Edge& aE,
|
|
TopoDS_Vertex& aV1);
|
|
|
|
static
|
|
Standard_Real AngleIn(const TopoDS_Edge& aEIn,
|
|
const BOPAlgo_ListOfEdgeInfo& aLEInfo);
|
|
|
|
static
|
|
Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo);
|
|
|
|
static
|
|
gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
|
|
const TopoDS_Face& aF);
|
|
|
|
static
|
|
gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
|
|
const TopoDS_Edge& aE1,
|
|
const TopoDS_Face& aF);
|
|
|
|
static
|
|
Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
|
|
const Standard_Real aAngleOut);
|
|
|
|
static
|
|
void Path (const GeomAdaptor_Surface& aGAS,
|
|
const TopoDS_Face& myFace,
|
|
const TopoDS_Vertex& aVa,
|
|
const TopoDS_Edge& aEOuta,
|
|
BOPAlgo_EdgeInfo& anEdgeInfo,
|
|
BOPCol_SequenceOfShape& aLS,
|
|
BOPCol_SequenceOfShape& aVertVa,
|
|
BOPCol_SequenceOfPnt2d& aCoordVa,
|
|
BOPTools_ConnexityBlock& aCB,
|
|
BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap,
|
|
BOPCol_DataMapOfShapeBoolean aVertMap);
|
|
|
|
static
|
|
Standard_Real Angle (const gp_Dir2d& aDir2D);
|
|
|
|
static
|
|
Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
|
|
const GeomAdaptor_Surface& aGAS);
|
|
|
|
|
|
|
|
static
|
|
Standard_Real UTolerance2D (const TopoDS_Vertex& aV,
|
|
const GeomAdaptor_Surface& aGAS);
|
|
static
|
|
Standard_Real VTolerance2D (const TopoDS_Vertex& aV,
|
|
const GeomAdaptor_Surface& aGAS);
|
|
|
|
static
|
|
void RefineAngles(const TopoDS_Face& myFace,
|
|
const BOPCol_ListOfShape&,
|
|
BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo&);
|
|
|
|
|
|
static
|
|
void RefineAngles(const TopoDS_Vertex& ,
|
|
const TopoDS_Face& ,
|
|
const BOPCol_MapOfShape& ,
|
|
BOPAlgo_ListOfEdgeInfo& );
|
|
|
|
static
|
|
Standard_Boolean RefineAngle2D(const TopoDS_Vertex& ,
|
|
const TopoDS_Edge& ,
|
|
const TopoDS_Face& ,
|
|
const Standard_Real ,
|
|
const Standard_Real ,
|
|
Standard_Real& );
|
|
|
|
//=======================================================================
|
|
//function : SplitBlock
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
|
|
BOPTools_ConnexityBlock& aCB)
|
|
{
|
|
Standard_Boolean bNothingToDo, bIsClosed, bIsIN;
|
|
Standard_Integer aIx, aNb, i, aCntIn, aCntOut;
|
|
Standard_Real aAngle;
|
|
TopAbs_Orientation aOr;
|
|
TopoDS_Iterator aItS;
|
|
TopoDS_Vertex aVV;
|
|
TopoDS_Shape aV1;
|
|
BOPCol_ListIteratorOfListOfShape aIt;
|
|
BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
|
|
//
|
|
BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo mySmartMap(100);
|
|
BOPCol_DataMapOfShapeBoolean aVertMap;
|
|
//
|
|
const BOPCol_ListOfShape& myEdges=aCB.Shapes();
|
|
//
|
|
// 1.Filling mySmartMap
|
|
BOPTools_AlgoTools2D::BuildPCurveForEdgesOnPlane(myEdges, myFace);
|
|
//
|
|
aIt.Initialize(myEdges);
|
|
for(; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge *)&aIt.Value());
|
|
if (!BOPTools_AlgoTools2D::HasCurveOnSurface (aE, myFace)) {
|
|
continue;
|
|
}
|
|
//
|
|
bIsClosed = BRep_Tool::Degenerated(aE) ||
|
|
BRep_Tool::IsClosed(aE, myFace);
|
|
//
|
|
aItS.Initialize(aE);
|
|
for(i = 0; aItS.More(); aItS.Next(), ++i) {
|
|
const TopoDS_Shape& aV = aItS.Value();
|
|
aIx = mySmartMap.FindIndex(aV);
|
|
if (!aIx) {
|
|
BOPAlgo_ListOfEdgeInfo aLEIx;
|
|
aIx = mySmartMap.Add(aV, aLEIx);
|
|
}
|
|
//
|
|
BOPAlgo_ListOfEdgeInfo& aLEI = mySmartMap(aIx);
|
|
BOPAlgo_EdgeInfo aEI;
|
|
//
|
|
aEI.SetEdge(aE);
|
|
aOr = aV.Orientation();
|
|
bIsIN = (aOr == TopAbs_REVERSED);
|
|
aEI.SetInFlag(bIsIN);
|
|
aLEI.Append(aEI);
|
|
//
|
|
if (!i) {
|
|
aV1 = aV;
|
|
} else {
|
|
bIsClosed = bIsClosed || aV1.IsSame(aV);
|
|
}
|
|
//
|
|
if (aVertMap.IsBound(aV)) {
|
|
if (bIsClosed) {
|
|
aVertMap.ChangeFind(aV) = bIsClosed;
|
|
}
|
|
} else {
|
|
aVertMap.Bind(aV, bIsClosed);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
aNb=mySmartMap.Extent();
|
|
//
|
|
bNothingToDo=Standard_True;
|
|
for (i=1; i<=aNb; i++) {
|
|
aCntIn=0;
|
|
aCntOut=0;
|
|
const BOPAlgo_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
|
|
BOPAlgo_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
|
|
for (; anIt.More(); anIt.Next()) {
|
|
const BOPAlgo_EdgeInfo& aEI=anIt.Value();
|
|
if (aEI.IsIn()) {
|
|
aCntIn++;
|
|
}
|
|
else {
|
|
aCntOut++;
|
|
}
|
|
}
|
|
if (aCntIn!=1 || aCntOut!=1) {
|
|
bNothingToDo=Standard_False;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Each vertex has one edge In and one - Out. Good. But it is not enought
|
|
// to consider that nothing to do with this. We must check edges on TShape
|
|
// coinsidence. If there are such edges there is something to do with.
|
|
if (bNothingToDo) {
|
|
Standard_Integer aNbE, aNbMapEE;
|
|
Standard_Boolean bFlag;
|
|
//
|
|
BOPCol_IndexedDataMapOfShapeListOfShape aMapEE(100);
|
|
aNbE=myEdges.Extent();
|
|
//
|
|
aIt.Initialize(myEdges);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aE = aIt.Value();
|
|
if (!aMapEE.Contains(aE)) {
|
|
BOPCol_ListOfShape aLEx;
|
|
aLEx.Append(aE);
|
|
aMapEE.Add(aE, aLEx);
|
|
}
|
|
else {
|
|
BOPCol_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
|
|
aLEx.Append(aE);
|
|
}
|
|
}
|
|
//
|
|
bFlag=Standard_True;
|
|
aNbMapEE=aMapEE.Extent();
|
|
for (i=1; i<=aNbMapEE; ++i) {
|
|
const BOPCol_ListOfShape& aLEx=aMapEE(i);
|
|
aNbE=aLEx.Extent();
|
|
if (aNbE==1) {// usual case
|
|
continue;
|
|
}
|
|
else if (aNbE==2){
|
|
const TopoDS_Shape& aE1=aLEx.First();
|
|
const TopoDS_Shape& aE2=aLEx.Last();
|
|
if (aE1.IsSame(aE2)) {
|
|
bFlag=Standard_False;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
bFlag=Standard_False;
|
|
break;
|
|
}
|
|
}
|
|
bNothingToDo=bNothingToDo && bFlag;
|
|
} // if (bNothingToDo) {
|
|
if (bNothingToDo) {
|
|
TopoDS_Wire aW;
|
|
//
|
|
BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
|
|
BOPAlgo_WireSplitter::MakeWire(aLECB, aW);
|
|
BOPCol_ListOfShape& aLoops=aCB.ChangeLoops();
|
|
aLoops.Append(aW);
|
|
//
|
|
return;
|
|
}
|
|
//
|
|
// 3. Angles in mySmartMap
|
|
BRepAdaptor_Surface aBAS(myFace);
|
|
const GeomAdaptor_Surface& aGAS=aBAS.Surface();
|
|
//
|
|
for (i=1; i<=aNb; i++) {
|
|
const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&mySmartMap.FindKey(i)));
|
|
const BOPAlgo_ListOfEdgeInfo& aLEI= mySmartMap(i);
|
|
|
|
aItLEI.Initialize(aLEI);
|
|
for (; aItLEI.More(); aItLEI.Next()) {
|
|
BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
|
|
const TopoDS_Edge& aE=aEI.Edge();
|
|
//
|
|
aVV = aV;
|
|
bIsIN = aEI.IsIn();
|
|
aOr = bIsIN ? TopAbs_REVERSED : TopAbs_FORWARD;
|
|
aVV.Orientation(aOr);
|
|
aAngle = Angle2D(aVV, aE, myFace, aGAS, bIsIN);
|
|
aEI.SetAngle(aAngle);
|
|
}
|
|
}// for (i=1; i<=aNb; i++) {
|
|
//
|
|
//Theme: The treatment p-curves convergent in node.
|
|
//The refining the angles of p-curves taking into account
|
|
//bounging curves if exist.
|
|
RefineAngles(myFace, myEdges, mySmartMap);
|
|
//
|
|
// 4. Do
|
|
//
|
|
Standard_Boolean bIsOut, bIsNotPassed;
|
|
BOPCol_SequenceOfShape aLS, aVertVa;
|
|
BOPCol_SequenceOfPnt2d aCoordVa;
|
|
//
|
|
for (i=1; i<=aNb; ++i) {
|
|
const TopoDS_Vertex& aVa=(*(TopoDS_Vertex *)(&mySmartMap.FindKey(i)));
|
|
const BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(i);
|
|
aItLEI.Initialize(aLEI);
|
|
for (; aItLEI.More(); aItLEI.Next()) {
|
|
BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
|
|
const TopoDS_Edge& aEOuta=aEI.Edge();
|
|
//
|
|
bIsOut=!aEI.IsIn();
|
|
bIsNotPassed=!aEI.Passed();
|
|
if (bIsOut && bIsNotPassed) {
|
|
//
|
|
aLS.Clear();
|
|
aVertVa.Clear();
|
|
aCoordVa.Clear();
|
|
//
|
|
Path(aGAS, myFace, aVa, aEOuta, aEI, aLS,
|
|
aVertVa, aCoordVa, aCB, mySmartMap, aVertMap);
|
|
}
|
|
}
|
|
}// for (i=1; i<=aNb; ++i) {
|
|
}
|
|
//=======================================================================
|
|
// function: Path
|
|
// purpose:
|
|
//=======================================================================
|
|
void Path (const GeomAdaptor_Surface& aGAS,
|
|
const TopoDS_Face& myFace,
|
|
const TopoDS_Vertex& aVFirst,
|
|
const TopoDS_Edge& aEFirst,
|
|
BOPAlgo_EdgeInfo& aEIFirst,
|
|
BOPCol_SequenceOfShape& aLS,
|
|
BOPCol_SequenceOfShape& aVertVa,
|
|
BOPCol_SequenceOfPnt2d& aCoordVa,
|
|
BOPTools_ConnexityBlock& aCB,
|
|
BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap,
|
|
BOPCol_DataMapOfShapeBoolean aVertMap)
|
|
|
|
{
|
|
Standard_Integer i, j, aNb, aNbj;
|
|
Standard_Real anAngleIn, anAngleOut, anAngle, aMinAngle;
|
|
Standard_Real aTol2D, aTol2D2, aD2, aTwoPI;
|
|
Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
|
|
Standard_Boolean bIsClosed;
|
|
TopoDS_Vertex aVa, aVb;
|
|
TopoDS_Edge aEOuta;
|
|
BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
|
|
//
|
|
aVa = aVFirst;
|
|
aEOuta = aEFirst;
|
|
BOPAlgo_EdgeInfo* anEdgeInfo = &aEIFirst;
|
|
//
|
|
aTwoPI = M_PI + M_PI;
|
|
//
|
|
// append block
|
|
//
|
|
for (;;) {
|
|
// Do not escape through edge from which you enter
|
|
aNb=aLS.Length();
|
|
if (aNb==1) {
|
|
const TopoDS_Shape& anEPrev=aLS(aNb);
|
|
if (anEPrev.IsSame(aEOuta)) {
|
|
return;
|
|
}
|
|
}
|
|
//
|
|
anEdgeInfo->SetPassed(Standard_True);
|
|
aLS.Append(aEOuta);
|
|
aVertVa.Append(aVa);
|
|
|
|
TopoDS_Vertex pVa=aVa;
|
|
pVa.Orientation(TopAbs_FORWARD);
|
|
gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
|
|
aCoordVa.Append(aPa);
|
|
|
|
GetNextVertex (pVa, aEOuta, aVb);
|
|
|
|
gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
|
|
|
|
const BOPAlgo_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
|
|
//
|
|
aTol2D = 2.*Tolerance2D(aVb, aGAS);
|
|
aTol2D2 = aTol2D * aTol2D;
|
|
//
|
|
bIsClosed = aVertMap.Find(aVb);
|
|
//
|
|
aNb=aLS.Length();
|
|
if (aNb>0) {
|
|
//
|
|
BOPCol_ListOfShape aBuf;
|
|
//
|
|
for (i=aNb; i>0; --i) {
|
|
const TopoDS_Shape& aVPrev=aVertVa(i);
|
|
const gp_Pnt2d& aPaPrev=aCoordVa(i);
|
|
const TopoDS_Shape& aEPrev=aLS(i);
|
|
|
|
aBuf.Append(aEPrev);
|
|
|
|
anIsSameV = aVPrev.IsSame(aVb);
|
|
anIsSameV2d = anIsSameV;
|
|
if (anIsSameV) {
|
|
if(bIsClosed) {
|
|
aD2 = aPaPrev.SquareDistance(aPb);
|
|
anIsSameV2d = aD2 < aTol2D2;
|
|
if (anIsSameV2d) {
|
|
Standard_Real udist = fabs(aPaPrev.X() - aPb.X());
|
|
Standard_Real vdist = fabs(aPaPrev.Y() - aPb.Y());
|
|
Standard_Real aTolU = 2.*UTolerance2D(aVb, aGAS);
|
|
Standard_Real aTolV = 2.*VTolerance2D(aVb, aGAS);
|
|
//
|
|
if((udist > aTolU) || (vdist > aTolV)) {
|
|
anIsSameV2d = Standard_False;
|
|
}
|
|
}
|
|
}
|
|
}//if (anIsSameV) {
|
|
//
|
|
if (anIsSameV && anIsSameV2d) {
|
|
Standard_Integer iPriz;
|
|
iPriz=1;
|
|
if (aBuf.Extent()==2) {
|
|
if(aBuf.First().IsSame(aBuf.Last())) {
|
|
iPriz=0;
|
|
}
|
|
}
|
|
if (iPriz) {
|
|
TopoDS_Wire aW;
|
|
BOPAlgo_WireSplitter::MakeWire(aBuf, aW);
|
|
aCB.ChangeLoops().Append(aW);
|
|
}
|
|
//
|
|
aNbj=i-1;
|
|
if (aNbj<1) {
|
|
//
|
|
aLS.Clear();
|
|
aVertVa.Clear();
|
|
aCoordVa.Clear();
|
|
//
|
|
return;
|
|
}
|
|
//
|
|
BOPCol_SequenceOfShape aLSt, aVertVat;
|
|
BOPCol_SequenceOfPnt2d aCoordVat;
|
|
//
|
|
aVb=(*(TopoDS_Vertex *)(&aVertVa(i)));
|
|
//
|
|
for (j=1; j<=aNbj; ++j) {
|
|
aLSt.Append(aLS(j));
|
|
aVertVat.Append(aVertVa(j));
|
|
aCoordVat.Append(aCoordVa(j));
|
|
}
|
|
//
|
|
aLS.Clear();
|
|
aVertVa.Clear();
|
|
aCoordVa.Clear();
|
|
|
|
aLS=aLSt;
|
|
aVertVa=aVertVat;
|
|
aCoordVa=aCoordVat;
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// aEOutb
|
|
BOPAlgo_EdgeInfo *pEdgeInfo=NULL;
|
|
//
|
|
anAngleIn = AngleIn(aEOuta, aLEInfo);
|
|
aMinAngle = 100.;
|
|
anIsFound = Standard_False;
|
|
Standard_Integer aCurIndexE = 0;
|
|
anIt.Initialize(aLEInfo);
|
|
for (; anIt.More(); anIt.Next()) {
|
|
BOPAlgo_EdgeInfo& anEI=anIt.ChangeValue();
|
|
const TopoDS_Edge& aE=anEI.Edge();
|
|
anIsOut=!anEI.IsIn();
|
|
anIsNotPassed=!anEI.Passed();
|
|
//
|
|
if (anIsOut && anIsNotPassed) {
|
|
aCurIndexE++;
|
|
//
|
|
// Is there one way to go out of the vertex
|
|
// we have to use it only.
|
|
Standard_Integer iCnt;
|
|
iCnt=NbWaysOut (aLEInfo);
|
|
//
|
|
if (!iCnt) {
|
|
// no way to go . (Error)
|
|
return;
|
|
}
|
|
//
|
|
if (iCnt==1) {
|
|
// the one and only way to go out .
|
|
pEdgeInfo=&anEI;
|
|
anIsFound=Standard_True;
|
|
break;
|
|
}
|
|
//
|
|
if (aE.IsSame(aEOuta)) {
|
|
anAngle = aTwoPI;
|
|
} else {
|
|
//check 2d distance
|
|
if (bIsClosed) {
|
|
gp_Pnt2d aP2Dx;
|
|
//
|
|
aP2Dx = Coord2dVf(aE, myFace);
|
|
//
|
|
aD2 = aP2Dx.SquareDistance(aPb);
|
|
if (aD2 > aTol2D2){
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
// Look for minimal angle and make the choice.
|
|
anAngleOut=anEI.Angle();
|
|
anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
|
|
}
|
|
if (anAngle < aMinAngle) {
|
|
aMinAngle=anAngle;
|
|
pEdgeInfo=&anEI;
|
|
anIsFound=Standard_True;
|
|
}
|
|
}
|
|
} // for (; anIt.More(); anIt.Next())
|
|
//
|
|
if (!anIsFound) {
|
|
// no way to go . (Error)
|
|
return;
|
|
}
|
|
//
|
|
aVa = aVb;
|
|
aEOuta = pEdgeInfo->Edge();
|
|
anEdgeInfo = pEdgeInfo;
|
|
}
|
|
}
|
|
//=======================================================================
|
|
// function: ClockWiseAngle
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
|
|
const Standard_Real aAngleOut)
|
|
{
|
|
Standard_Real aTwoPi=M_PI+M_PI;
|
|
Standard_Real dA, A1, A2, AIn, AOut ;
|
|
|
|
AIn=aAngleIn;
|
|
AOut=aAngleOut;
|
|
if (AIn >= aTwoPi) {
|
|
AIn=AIn-aTwoPi;
|
|
}
|
|
|
|
if (AOut >= aTwoPi) {
|
|
AOut=AOut-aTwoPi;
|
|
}
|
|
|
|
A1=AIn+M_PI;
|
|
|
|
if (A1 >= aTwoPi) {
|
|
A1=A1-aTwoPi;
|
|
}
|
|
|
|
A2=AOut;
|
|
|
|
dA=A1-A2;
|
|
if (dA <= 0.) {
|
|
dA=aTwoPi+dA;
|
|
}
|
|
//xx
|
|
//else if (dA <= 1.e-15) {
|
|
else if (dA <= 1.e-14) {
|
|
dA=aTwoPi;
|
|
}
|
|
return dA;
|
|
}
|
|
//=======================================================================
|
|
// function: Coord2d
|
|
// purpose:
|
|
//=======================================================================
|
|
gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
|
|
const TopoDS_Edge& aE1,
|
|
const TopoDS_Face& aF)
|
|
{
|
|
Standard_Real aT, aFirst, aLast;
|
|
Handle(Geom2d_Curve) aC2D;
|
|
gp_Pnt2d aP2D1;
|
|
//
|
|
aT=BRep_Tool::Parameter (aV1, aE1, aF);
|
|
aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
|
|
aC2D->D0 (aT, aP2D1);
|
|
//
|
|
return aP2D1;
|
|
}
|
|
//=======================================================================
|
|
// function: Coord2dVf
|
|
// purpose:
|
|
//=======================================================================
|
|
gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
|
|
const TopoDS_Face& aF)
|
|
{
|
|
Standard_Real aCoord=99.;
|
|
gp_Pnt2d aP2D1(aCoord, aCoord);
|
|
TopoDS_Iterator aIt;
|
|
//
|
|
aIt.Initialize(aE);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aVx=aIt.Value();
|
|
if (aVx.Orientation()==TopAbs_FORWARD) {
|
|
|
|
const TopoDS_Vertex& aVxx=(*(TopoDS_Vertex *)(&aVx));// TopoDS::Vertex(aVx);
|
|
aP2D1=Coord2d(aVxx, aE, aF);
|
|
return aP2D1;
|
|
}
|
|
}
|
|
return aP2D1;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: NbWaysOut
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
|
|
{
|
|
Standard_Boolean bIsOut, bIsNotPassed;
|
|
Standard_Integer iCnt=0;
|
|
BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
|
|
//
|
|
anIt.Initialize(aLEInfo);
|
|
for (; anIt.More(); anIt.Next()) {
|
|
const BOPAlgo_EdgeInfo& anEI=anIt.Value();
|
|
//
|
|
bIsOut=!anEI.IsIn();
|
|
bIsNotPassed=!anEI.Passed();
|
|
if (bIsOut && bIsNotPassed) {
|
|
iCnt++;
|
|
}
|
|
}
|
|
return iCnt;
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: AngleIn
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Real AngleIn(const TopoDS_Edge& aEIn,
|
|
const BOPAlgo_ListOfEdgeInfo& aLEInfo)
|
|
{
|
|
Standard_Real anAngleIn;
|
|
Standard_Boolean anIsIn;
|
|
BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
|
|
|
|
anIt.Initialize(aLEInfo);
|
|
for (; anIt.More(); anIt.Next()) {
|
|
const BOPAlgo_EdgeInfo& anEdgeInfo=anIt.Value();
|
|
const TopoDS_Edge& aE=anEdgeInfo.Edge();
|
|
anIsIn=anEdgeInfo.IsIn();
|
|
//
|
|
if (anIsIn && aE==aEIn) {
|
|
anAngleIn=anEdgeInfo.Angle();
|
|
return anAngleIn;
|
|
}
|
|
}
|
|
anAngleIn=0.;
|
|
return anAngleIn;
|
|
}
|
|
//=======================================================================
|
|
// function: GetNextVertex
|
|
// purpose:
|
|
//=======================================================================
|
|
void GetNextVertex(const TopoDS_Vertex& aV,
|
|
const TopoDS_Edge& aE,
|
|
TopoDS_Vertex& aV1)
|
|
{
|
|
TopoDS_Iterator aIt;
|
|
//
|
|
aIt.Initialize(aE);
|
|
for (; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aVx=aIt.Value();
|
|
if (!aVx.IsEqual(aV)) {
|
|
aV1=(*(TopoDS_Vertex *)(&aVx));
|
|
return ;
|
|
}
|
|
}
|
|
aV1=aV;
|
|
}
|
|
//=======================================================================
|
|
// function: Angle2D
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Real Angle2D (const TopoDS_Vertex& aV,
|
|
const TopoDS_Edge& anEdge,
|
|
const TopoDS_Face& myFace,
|
|
const GeomAdaptor_Surface& aGAS,
|
|
const Standard_Boolean bIsIN)
|
|
{
|
|
Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
|
|
gp_Pnt2d aPV, aPV1;
|
|
gp_Vec2d aV2D;
|
|
Handle(Geom2d_Curve) aC2D;
|
|
//
|
|
aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
|
|
if (Precision::IsInfinite(aTV)) {
|
|
return 0.;
|
|
}
|
|
//
|
|
BOPTools_AlgoTools2D::CurveOnSurface (anEdge, myFace, aC2D,
|
|
aFirst, aLast, aToler);
|
|
dt=2.*Tolerance2D(aV, aGAS);
|
|
//
|
|
//for case chl/927/r9
|
|
aTX=0.05*(aLast - aFirst);//aTX=0.25*(aLast - aFirst);
|
|
if (aTX < 5.e-5) {
|
|
aTX = 5.e-5;
|
|
}
|
|
if(dt > aTX) {
|
|
// to save direction of the curve as much as it possible
|
|
// in the case of big tolerances
|
|
dt = aTX;
|
|
}
|
|
//
|
|
GeomAbs_CurveType aType;
|
|
Geom2dAdaptor_Curve aGAC2D(aC2D);
|
|
aType=aGAC2D.GetType();
|
|
if (aType==GeomAbs_BSplineCurve || aType==GeomAbs_BezierCurve) {
|
|
dt=1.1*dt;
|
|
}
|
|
if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
|
|
aTV1=aTV + dt;
|
|
}
|
|
else {
|
|
aTV1=aTV - dt;
|
|
}
|
|
//
|
|
aC2D->D0 (aTV1, aPV1);
|
|
aC2D->D0 (aTV, aPV);
|
|
//
|
|
aV2D = bIsIN ? gp_Vec2d(aPV1, aPV) : gp_Vec2d(aPV, aPV1);
|
|
//
|
|
gp_Dir2d aDir2D(aV2D);
|
|
anAngle=Angle(aDir2D);
|
|
//
|
|
return anAngle;
|
|
}
|
|
//=======================================================================
|
|
// function: Angle
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Real Angle (const gp_Dir2d& aDir2D)
|
|
{
|
|
gp_Dir2d aRefDir(1., 0.);
|
|
Standard_Real anAngle;
|
|
|
|
anAngle = aRefDir.Angle(aDir2D);
|
|
if (anAngle < 0.)
|
|
anAngle += M_PI + M_PI;
|
|
return anAngle;
|
|
}
|
|
//=======================================================================
|
|
// function: Tolerance2D
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
|
|
const GeomAdaptor_Surface& aGAS)
|
|
{
|
|
Standard_Real aTol2D, anUr, aVr, aTolV3D;
|
|
GeomAbs_SurfaceType aType;
|
|
//
|
|
aType=aGAS.GetType();
|
|
aTolV3D=BRep_Tool::Tolerance(aV);
|
|
|
|
anUr=aGAS.UResolution(aTolV3D);
|
|
aVr =aGAS.VResolution(aTolV3D);
|
|
aTol2D=(aVr>anUr) ? aVr : anUr;
|
|
//
|
|
if (aTol2D < aTolV3D) {
|
|
aTol2D=aTolV3D;
|
|
}
|
|
if (aType==GeomAbs_BSplineSurface) {
|
|
aTol2D=1.1*aTol2D;
|
|
}
|
|
//
|
|
return aTol2D;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UTolerance2D
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Real UTolerance2D (const TopoDS_Vertex& aV,
|
|
const GeomAdaptor_Surface& aGAS)
|
|
{
|
|
const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV);
|
|
const Standard_Real anUr = aGAS.UResolution(aTolV3D);
|
|
//
|
|
return anUr;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : VTolerance2D
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Real VTolerance2D (const TopoDS_Vertex& aV,
|
|
const GeomAdaptor_Surface& aGAS)
|
|
{
|
|
const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV);
|
|
const Standard_Real anVr = aGAS.VResolution(aTolV3D);
|
|
//
|
|
return anVr;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : RefineAngles
|
|
//purpose :
|
|
//=======================================================================
|
|
void RefineAngles(const TopoDS_Face& myFace,
|
|
const BOPCol_ListOfShape& myEdges,
|
|
BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap)
|
|
{
|
|
Standard_Integer aNb, i;
|
|
BOPCol_DataMapOfShapeInteger aMSI;
|
|
BOPCol_DataMapIteratorOfDataMapOfShapeInteger aItMSI;
|
|
BOPCol_MapOfShape aMBE;
|
|
BOPCol_ListIteratorOfListOfShape aIt;
|
|
//
|
|
// 1. Boundary Edges
|
|
aIt.Initialize(myEdges);
|
|
for(; aIt.More(); aIt.Next()) {
|
|
const TopoDS_Shape& aE=aIt.Value();
|
|
if(aMSI.IsBound(aE)) {
|
|
Standard_Integer& iCnt=aMSI.ChangeFind(aE);
|
|
++iCnt;
|
|
}
|
|
else {
|
|
Standard_Integer iCnt=1;
|
|
aMSI.Bind(aE, iCnt);
|
|
}
|
|
}
|
|
//
|
|
aItMSI.Initialize(aMSI);
|
|
for(; aItMSI.More(); aItMSI.Next()) {
|
|
Standard_Integer iCnt;
|
|
//
|
|
const TopoDS_Shape& aE=aItMSI.Key();
|
|
iCnt=aItMSI.Value();
|
|
if (iCnt==1) {
|
|
aMBE.Add(aE);
|
|
}
|
|
|
|
}
|
|
//
|
|
aMSI.Clear();
|
|
//
|
|
aNb=mySmartMap.Extent();
|
|
for (i=1; i<=aNb; ++i) {
|
|
const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&mySmartMap.FindKey(i));
|
|
BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(i);
|
|
//
|
|
RefineAngles(aV, myFace, aMBE, aLEI);
|
|
}
|
|
}
|
|
//=======================================================================
|
|
typedef NCollection_DataMap \
|
|
<TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> \
|
|
BOPCol_DataMapOfShapeReal;
|
|
typedef BOPCol_DataMapOfShapeReal::Iterator \
|
|
BOPCol_DataMapIteratorOfDataMapOfShapeReal;
|
|
//
|
|
//=======================================================================
|
|
//function : RefineAngles
|
|
//purpose :
|
|
//=======================================================================
|
|
void RefineAngles(const TopoDS_Vertex& aV,
|
|
const TopoDS_Face& myFace,
|
|
const BOPCol_MapOfShape& aMBE,
|
|
BOPAlgo_ListOfEdgeInfo& aLEI)
|
|
{
|
|
Standard_Boolean bIsIn, bIsBoundary, bRefined;
|
|
Standard_Integer iCntBnd, iCntInt;
|
|
Standard_Real aA, aA1, aA2;
|
|
BOPCol_DataMapOfShapeReal aDMSR;
|
|
BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
|
|
//
|
|
aA1=0.;
|
|
aA2=0.;
|
|
iCntBnd=0;
|
|
iCntInt=0;
|
|
aItLEI.Initialize(aLEI);
|
|
for (; aItLEI.More(); aItLEI.Next()) {
|
|
BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
|
|
const TopoDS_Edge& aE=aEI.Edge();
|
|
bIsIn=aEI.IsIn();
|
|
aA=aEI.Angle();
|
|
//
|
|
if (aMBE.Contains(aE)) {
|
|
++iCntBnd;
|
|
if (!bIsIn) {
|
|
aA1=aA;
|
|
}
|
|
else {
|
|
aA2=aA+M_PI;
|
|
}
|
|
}
|
|
else {
|
|
++iCntInt;
|
|
}
|
|
}
|
|
//
|
|
if (iCntBnd!=2) {
|
|
return;
|
|
}
|
|
//
|
|
aItLEI.Initialize(aLEI);
|
|
for (; aItLEI.More(); aItLEI.Next()) {
|
|
BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
|
|
const TopoDS_Edge& aE=aEI.Edge();
|
|
//
|
|
bIsBoundary=aMBE.Contains(aE);
|
|
bIsIn=aEI.IsIn();
|
|
if (bIsBoundary || bIsIn) {
|
|
continue;
|
|
}
|
|
//
|
|
aA=aEI.Angle();
|
|
if (aA>aA1 && aA<aA2) {
|
|
continue;
|
|
}
|
|
//
|
|
bRefined=RefineAngle2D(aV, aE, myFace, aA1, aA2, aA);
|
|
if (bRefined) {
|
|
aDMSR.Bind(aE, aA);
|
|
}
|
|
else if (iCntInt == 2) {
|
|
aA = (aA <= aA1) ? (aA1 + Precision::Angular()) :
|
|
(aA2 - Precision::Angular());
|
|
aDMSR.Bind(aE, aA);
|
|
}
|
|
}
|
|
|
|
if (aDMSR.IsEmpty()) {
|
|
return;
|
|
}
|
|
//
|
|
// update Angles
|
|
aItLEI.Initialize(aLEI);
|
|
for (; aItLEI.More(); aItLEI.Next()) {
|
|
BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
|
|
const TopoDS_Edge& aE=aEI.Edge();
|
|
//
|
|
bIsIn=aEI.IsIn();
|
|
if (!aDMSR.IsBound(aE)) {
|
|
continue;
|
|
}
|
|
//
|
|
aA=aDMSR.Find(aE);
|
|
if (bIsIn) {
|
|
aA=aA+M_PI;
|
|
}
|
|
//
|
|
aEI.SetAngle(aA);
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : RefineAngle2D
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean RefineAngle2D(const TopoDS_Vertex& aV,
|
|
const TopoDS_Edge& aE,
|
|
const TopoDS_Face& myFace,
|
|
const Standard_Real aA1,
|
|
const Standard_Real aA2,
|
|
Standard_Real& aA)
|
|
{
|
|
Standard_Boolean bRet;
|
|
Standard_Integer i, j, aNbP;
|
|
Standard_Real aTV, aTol, aT1, aT2, dT, aAngle, aT, aTOp;
|
|
Standard_Real aTolInt, aAi, aXi, aYi, aT1j, aT2j, aT1max, aT2max, aCf;
|
|
gp_Pnt2d aPV, aP, aP1, aP2;
|
|
Handle(Geom2d_Curve) aC2D;
|
|
Handle(Geom2d_Line) aLi;
|
|
Geom2dAdaptor_Curve aGAC1, aGAC2;
|
|
Geom2dInt_GInter aGInter;
|
|
IntRes2d_Domain aDomain1, aDomain2;
|
|
//
|
|
bRet=Standard_True;
|
|
aCf=0.01;
|
|
aTolInt=1.e-10;
|
|
//
|
|
BOPTools_AlgoTools2D::CurveOnSurface(aE, myFace, aC2D, aT1, aT2, aTol);
|
|
//
|
|
aTV=BRep_Tool::Parameter (aV, aE, myFace);
|
|
aC2D->D0(aTV, aPV);
|
|
//
|
|
aTOp = (fabs(aTV-aT1) < fabs(aTV-aT2)) ? aT2 : aT1;
|
|
//
|
|
aGAC1.Load(aC2D, aT1, aT2);
|
|
aC2D->D0(aT1, aP1);
|
|
aC2D->D0(aT2, aP2);
|
|
aDomain1.SetValues(aP1, aT1, aTolInt, aP2, aT2, aTolInt);
|
|
//
|
|
for (i=0; i<2; ++i) {
|
|
aAi=(!i) ? aA1 : aA2;
|
|
aXi=cos(aAi);
|
|
aYi=sin(aAi);
|
|
gp_Dir2d aDiri(aXi, aYi);
|
|
aLi=new Geom2d_Line(aPV, aDiri);
|
|
//
|
|
aGAC2.Load(aLi);
|
|
//
|
|
aGInter.Perform(aGAC1, aDomain1, aGAC2, aDomain2, aTolInt, aTolInt);
|
|
if (!aGInter.IsDone()) {
|
|
continue;
|
|
}
|
|
//
|
|
aNbP=aGInter.NbPoints();
|
|
if (aNbP<2) {
|
|
continue;
|
|
}
|
|
//
|
|
aT1max=aTV;
|
|
aT2max=-1.;
|
|
for (j=1; j<=aNbP; ++j) {
|
|
const IntRes2d_IntersectionPoint& aIPj=aGInter.Point(j);
|
|
aT1j=aIPj.ParamOnFirst();
|
|
aT2j=aIPj.ParamOnSecond();
|
|
//
|
|
if (aT2j > aT2max) {
|
|
aT2max=aT2j;
|
|
aT1max=aT1j;
|
|
}
|
|
}
|
|
//
|
|
dT = aTOp - aT1max;
|
|
//
|
|
aT=aT1max + aCf*dT;
|
|
aC2D->D0(aT, aP);
|
|
gp_Vec2d aV2D(aPV, aP);
|
|
gp_Dir2d aDir2D(aV2D);
|
|
//
|
|
aAngle=Angle(aDir2D);
|
|
if (aAngle>aA1 && aAngle<aA2) {
|
|
aA=aAngle;
|
|
return bRet;
|
|
}
|
|
}// for (i=0; i<2; ++i) {
|
|
return !bRet;
|
|
}
|