Loading files
4f95ecaa3This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1995-12-12
// 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.
// Modified by dpf, Fri Dec 19 15:31:03 1997
// Processing of closing in 2d.
// modified by eap Tue Dec 18 14:14:25 2001 (bug OCC23)
// Check self-intersection in case of closed edge
// modified by eap Fri Dec 21 17:36:55 2001 (bug OCC35)
// Closed2d() added
// Modified by skv - Wed Jul 23 12:22:20 2003 OCC1764
#include <Bnd_Box2d.hxx>
#include <NCollection_Array1.hxx>
#include <BndLib_Add2dCurve.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepCheck.hxx>
#include <BRepCheck_Status.hxx>
#include <NCollection_List.hxx>
#include <NCollection_Shared.hxx>
#include <BRepCheck_Wire.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <ElCLib.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <Geom_Curve.hxx>
#include <gp_Lin.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <IntRes2d_Domain.hxx>
#include <IntRes2d_Intersection.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <IntRes2d_Transition.hxx>
#include <Precision.hxx>
#include <Standard_Type.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.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_ShapeMapHasher.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_IndexedDataMap.hxx>
#include <NCollection_IndexedMap.hxx>
#include <NCollection_Map.hxx>
#include <cstdio>
IMPLEMENT_STANDARD_RTTIEXT(BRepCheck_Wire, BRepCheck_Result)
static void Propagate(const NCollection_IndexedDataMap<TopoDS_Shape,
NCollection_List<TopoDS_Shape>,
TopTools_ShapeMapHasher>&,
const TopoDS_Shape&, // edge
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher>&); // mapofedge
static TopAbs_Orientation GetOrientation(
const NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher>&,
const TopoDS_Edge&);
static void ChoixUV(const TopoDS_Vertex&,
const TopoDS_Edge&,
const TopoDS_Face&,
NCollection_List<TopoDS_Shape>&);
// 20/03/02 akm vvv (OCC234)
// static
// bool CheckLoopOrientation( const TopoDS_Vertex&,
// const TopoDS_Edge&,
// const TopoDS_Edge&,
// const TopoDS_Face&,
// NCollection_List<TopoDS_Shape>&);
// 20/03/02 akm ^^^
inline bool IsOriented(const TopoDS_Shape& S)
{
return (S.Orientation() == TopAbs_FORWARD || S.Orientation() == TopAbs_REVERSED);
}
static void CurveDirForParameter(const Geom2dAdaptor_Curve& aC2d,
const double aPrm,
gp_Pnt2d& Pnt,
gp_Vec2d& aVec2d);
// Modified by Sergey KHROMOV - Thu Jun 20 11:21:51 2002 OCC325 Begin
static bool IsClosed2dForPeriodicFace(const TopoDS_Face& theFace,
const gp_Pnt2d& theP1,
const gp_Pnt2d& theP2,
const TopoDS_Vertex& theVertex);
static bool GetPnt2d(const TopoDS_Vertex& theVertex,
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
gp_Pnt2d& aPnt);
// Modified by Sergey KHROMOV - Wed May 22 10:44:08 2002 End
//=================================================================================================
BRepCheck_Wire::BRepCheck_Wire(const TopoDS_Wire& W)
: myCdone(false),
myCstat(BRepCheck_NoError),
myGctrl(false)
{
Init(W);
}
//=================================================================================================
void BRepCheck_Wire::Minimum()
{
myCdone = false;
myGctrl = true;
if (!myMin)
{
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aNewList =
new NCollection_Shared<NCollection_List<BRepCheck_Status>>();
NCollection_List<BRepCheck_Status>& lst = **myMap.Bound(myShape, aNewList);
// check that the wire is "connex"
TopExp_Explorer exp(myShape, TopAbs_EDGE);
int nbedge = 0;
myMapVE.Clear();
// fill myMapVE
for (; exp.More(); exp.Next())
{
nbedge++;
TopExp_Explorer expv;
for (expv.Init(exp.Current(), TopAbs_VERTEX); expv.More(); expv.Next())
{
const TopoDS_Shape& vtx = expv.Current();
int index = myMapVE.FindIndex(vtx);
if (index == 0)
{
NCollection_List<TopoDS_Shape> theListOfShape;
index = myMapVE.Add(vtx, theListOfShape);
}
myMapVE(index).Append(exp.Current());
}
}
// wire must have at least one edge
if (nbedge == 0)
{
BRepCheck::Add(lst, BRepCheck_EmptyWire);
}
// check if all edges are connected through vertices
else if (nbedge >= 2)
{
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> mapE;
exp.ReInit();
Propagate(myMapVE, exp.Current(), mapE);
for (exp.ReInit(); exp.More(); exp.Next())
{
if (!mapE.Contains(exp.Current()))
{
BRepCheck::Add(lst, BRepCheck_NotConnected);
break;
}
}
}
if (lst.IsEmpty())
{
lst.Append(BRepCheck_NoError);
}
myMapVE.Clear();
myMin = true;
}
}
//=================================================================================================
void BRepCheck_Wire::InContext(const TopoDS_Shape& S)
{
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
{
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
if (myIsParallel)
{
aLock.lock();
}
if (myMap.IsBound(S))
{
return;
}
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aNewList =
new NCollection_Shared<NCollection_List<BRepCheck_Status>>();
aHList = *myMap.Bound(S, aNewList);
}
NCollection_List<BRepCheck_Status>& lst = *aHList;
// check if my wire is in <S>
TopExp_Explorer exp(S, TopAbs_WIRE);
for (; exp.More(); exp.Next())
{
if (exp.Current().IsSame(myShape))
{
break;
}
}
if (!exp.More())
{
BRepCheck::Add(lst, BRepCheck_SubshapeNotInShape);
return;
}
BRepCheck_Status st = BRepCheck_NoError;
TopAbs_ShapeEnum styp = S.ShapeType();
switch (styp)
{
case TopAbs_FACE: {
TopoDS_Edge ed1, ed2;
if (myGctrl)
{
st = SelfIntersect(TopoDS::Face(S), ed1, ed2, true);
}
if (st != BRepCheck_NoError)
{
break;
}
st = Closed();
if (st != BRepCheck_NoError)
{
break;
}
st = Orientation(TopoDS::Face(S));
if (st != BRepCheck_NoError)
{
break;
}
st = Closed2d(TopoDS::Face(S));
break;
}
default: {
break;
}
}
if (st != BRepCheck_NoError)
{
BRepCheck::Add(lst, st);
}
if (lst.IsEmpty())
{
lst.Append(BRepCheck_NoError);
}
}
//=================================================================================================
void BRepCheck_Wire::Blind()
{
if (!myBlind)
{
// nothing more that the minimum
myBlind = true;
}
}
//=================================================================================================
BRepCheck_Status BRepCheck_Wire::Closed(const bool Update)
{
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
{
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
if (myIsParallel)
{
aLock.lock();
}
aHList = myMap(myShape);
}
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
if (myCdone)
{
if (Update)
{
BRepCheck::Add(aStatusList, myCstat);
}
return myCstat;
}
myCdone = true;
NCollection_List<BRepCheck_Status>::Iterator itl(aStatusList);
if (itl.Value() != BRepCheck_NoError)
{
myCstat = itl.Value();
return myCstat; // already saved
}
myCstat = BRepCheck_NoError;
TopExp_Explorer exp, expv;
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> mapS;
NCollection_DataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher> Cradoc;
myMapVE.Clear();
// Checks if the oriented edges of the wire give a "closed" wire,
// i-e if each oriented vertex on oriented edges is found 2 times...
// myNbori = 0;
for (exp.Init(myShape, TopAbs_EDGE); exp.More(); exp.Next())
{
if (IsOriented(exp.Current()))
{
// myNbori++;
if (!Cradoc.IsBound(exp.Current()))
{
NCollection_List<TopoDS_Shape> theListOfShape;
Cradoc.Bind(exp.Current(), theListOfShape);
}
Cradoc(exp.Current()).Append(exp.Current());
mapS.Add(exp.Current());
for (expv.Init(exp.Current(), TopAbs_VERTEX); expv.More(); expv.Next())
{
if (IsOriented(expv.Current()))
{
int index = myMapVE.FindIndex(expv.Current());
if (index == 0)
{
NCollection_List<TopoDS_Shape> theListOfShape1;
index = myMapVE.Add(expv.Current(), theListOfShape1);
}
myMapVE(index).Append(exp.Current());
}
}
}
}
int theNbori = mapS.Extent();
if (theNbori >= 2)
{
mapS.Clear();
for (exp.ReInit(); exp.More(); exp.Next())
{
if (IsOriented(exp.Current()))
{
break;
}
}
Propagate(myMapVE, exp.Current(), mapS);
}
if (theNbori != mapS.Extent())
{
myCstat = BRepCheck_NotConnected;
if (Update)
{
BRepCheck::Add(aStatusList, myCstat);
}
return myCstat;
}
// Checks the number of occurrence of an edge : maximum 2, and in this
// case, one time FORWARD and one time REVERSED
bool yabug = false;
for (NCollection_DataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher>::
Iterator itdm(Cradoc);
itdm.More();
itdm.Next())
{
if (itdm.Value().Extent() >= 3)
{
yabug = true;
}
else if (itdm.Value().Extent() == 2)
{
if (itdm.Value().First().Orientation() == itdm.Value().Last().Orientation())
{
yabug = true;
}
}
if (yabug)
{
myCstat = BRepCheck_RedundantEdge;
if (Update)
{
BRepCheck::Add(aStatusList, myCstat);
}
return myCstat;
}
}
for (int i = 1; i <= myMapVE.Extent(); i++)
{
if (myMapVE(i).Extent() % 2 != 0)
{
myCstat = BRepCheck_NotClosed;
if (Update)
{
BRepCheck::Add(aStatusList, myCstat);
}
return myCstat;
}
}
if (Update)
{
BRepCheck::Add(aStatusList, myCstat);
}
return myCstat;
}
//=======================================================================
// function : IsDistanceIn3DTolerance
// purpose : Return true if distance between thePnt_f and
// thePnt_l is not more, than aTol3d
//=======================================================================
bool IsDistanceIn3DTolerance(const gp_Pnt& thePnt_f, const gp_Pnt& thePnt_l, const double aTol3d)
{
double Dist = thePnt_f.Distance(thePnt_l);
return Dist < aTol3d;
}
//=================================================================================================
static bool IsDistanceIn2DTolerance(const BRepAdaptor_Surface& aFaceSurface,
const gp_Pnt2d& thePnt,
const gp_Pnt2d& thePntRef,
const double aTol3d,
#ifdef OCCT_DEBUG
const bool PrintWarnings = true)
#else
const bool = true)
#endif
{
double dumax = 0.01 * (aFaceSurface.LastUParameter() - aFaceSurface.FirstUParameter());
double dvmax = 0.01 * (aFaceSurface.LastVParameter() - aFaceSurface.FirstVParameter());
double dumin = std::abs(thePnt.X() - thePntRef.X());
double dvmin = std::abs(thePnt.Y() - thePntRef.Y());
if ((dumin < dumax) && (dvmin < dvmax))
{
return true;
}
#ifdef OCCT_DEBUG
if (PrintWarnings)
{
std::cout << std::endl;
std::cout << "--------Function IsDistanceIn2DTolerance(...)----------" << std::endl;
std::cout << "--- BRepCheck Wire: Not closed in 2D" << std::endl;
std::cout << "*****************************************************" << std::endl;
std::cout << "*dumin = " << dumin << "; dumax = " << dumax << std::endl;
std::cout << "* dvmin = " << dvmin << "; dvmax = " << dvmax << std::endl;
std::cout << "* (dumin > dumax) or (dvmin > dvmax)." << std::endl;
std::cout << "*****************************************************" << std::endl;
std::cout << std::endl;
std::cout << "UFirst = " << aFaceSurface.FirstUParameter();
std::cout << "; ULast = " << aFaceSurface.LastUParameter() << std::endl;
std::cout << "VFirst = " << aFaceSurface.FirstVParameter();
std::cout << "; VLast = " << aFaceSurface.LastVParameter() << std::endl;
}
#endif
dumax = aFaceSurface.UResolution(aTol3d);
dvmax = aFaceSurface.VResolution(aTol3d);
gp_Pnt aP;
gp_Vec aDU, aDV;
double um = (thePnt.X() + thePntRef.X()) / 2.;
double vm = (thePnt.Y() + thePntRef.Y()) / 2.;
aFaceSurface.D1(um, vm, aP, aDU, aDV);
double aMDU = aDU.Magnitude();
if (aMDU > Precision::Confusion())
{
dumax = std::max((aTol3d / aMDU), dumax);
}
double aMDV = aDV.Magnitude();
if (aMDV > Precision::Confusion())
{
dvmax = std::max((aTol3d / aMDV), dvmax);
}
#ifdef OCCT_DEBUG
if (PrintWarnings)
{
std::cout << "aTol3d = " << aTol3d << "; URes = " << dumax << "; VRes = " << dvmax << std::endl;
std::cout << "thePnt(" << thePnt.X() << "; " << thePnt.Y() << ")" << std::endl;
std::cout << "thePntRef(" << thePntRef.X() << "; " << thePntRef.Y() << ")" << std::endl;
}
#endif
double aTol2d = 2 * std::max(dumax, dvmax);
#ifdef OCCT_DEBUG
if ((aTol2d <= 0.0) && (PrintWarnings))
{
std::cout << "BRepCheck_Wire : UResolution and VResolution = 0.0 (Face too small ?)"
<< std::endl;
std::cout.flush();
}
#endif
double Dist = std::max(dumin, dvmin);
return Dist < aTol2d;
}
//=================================================================================================
BRepCheck_Status BRepCheck_Wire::Closed2d(const TopoDS_Face& theFace, const bool Update)
{
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
{
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
if (myIsParallel)
{
aLock.lock();
}
aHList = myMap(myShape);
}
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
// 3d closure checked too
BRepCheck_Status aClosedStat = Closed();
if (aClosedStat != BRepCheck_NoError)
{
if (Update)
{
BRepCheck::Add(aStatusList, aClosedStat);
}
return aClosedStat;
}
// 20/03/02 akm vvv : (OCC234) Hence this method will be used to check
// both periodic and non-periodic faces
// // this check is for periodic faces
BRepAdaptor_Surface aFaceSurface(theFace, false);
// if (!aFaceSurface.IsUPeriodic() && !aFaceSurface.IsVPeriodic())
// {
// if (Update)
// BRepCheck::Add(myMap(myShape),aClosedStat);
// return aClosedStat;
// }
// 20/03/02 akm ^^^
// count edges having FORWARD or REVERSED orientation
int aNbOrirntedEdges = 0;
TopExp_Explorer anEdgeExp(myShape, TopAbs_EDGE);
for (; anEdgeExp.More(); anEdgeExp.Next())
{
if (IsOriented(anEdgeExp.Current()))
{
aNbOrirntedEdges++;
}
}
if (aNbOrirntedEdges == 0)
{
if (Update)
{
BRepCheck::Add(aStatusList, aClosedStat);
}
return aClosedStat;
}
// all those edges must form a closed 2d contour and be found by WireExplorer
int aNbFoundEdges = 0;
BRepTools_WireExplorer aWireExp(TopoDS::Wire(myShape), theFace);
TopoDS_Edge aFirstEdge = aWireExp.Current();
TopoDS_Vertex aFirstVertex = aWireExp.CurrentVertex();
TopoDS_Edge aLastEdge;
for (; aWireExp.More(); aWireExp.Next())
{
aNbFoundEdges++;
aLastEdge = aWireExp.Current();
}
if (aNbFoundEdges != aNbOrirntedEdges)
{
aClosedStat = BRepCheck_NotClosed;
if (Update)
{
BRepCheck::Add(aStatusList, aClosedStat);
}
return aClosedStat;
}
// Check distance between 2d ends of first and last edges
// Modified by Sergey KHROMOV - Mon May 13 12:42:10 2002 Begin
// First check if first and last edges are infinite:
double aF;
double aL;
bool isFirstInfinite = false;
bool isLastInfinite = false;
TopAbs_Orientation anOri;
anOri = aFirstEdge.Orientation();
BRep_Tool::Range(aFirstEdge, aF, aL);
if ((anOri == TopAbs_FORWARD && Precision::IsNegativeInfinite(aF))
|| (anOri == TopAbs_REVERSED && Precision::IsPositiveInfinite(aL)))
{
isFirstInfinite = true;
}
anOri = aLastEdge.Orientation();
BRep_Tool::Range(aLastEdge, aF, aL);
if ((anOri == TopAbs_FORWARD && Precision::IsPositiveInfinite(aL))
|| (anOri == TopAbs_REVERSED && Precision::IsNegativeInfinite(aF)))
{
isLastInfinite = true;
}
if (isFirstInfinite && isLastInfinite)
{
if (Update)
{
BRepCheck::Add(aStatusList, aClosedStat);
}
return aClosedStat;
}
else if (aFirstVertex.IsNull())
{
aClosedStat = BRepCheck_NotClosed;
if (Update)
{
BRepCheck::Add(aStatusList, aClosedStat);
}
return aClosedStat;
}
// Modified by Sergey KHROMOV - Mon May 13 12:42:10 2002 End
gp_Pnt2d aP_first, aP_last, aP_temp; // ends of prev edge, next edge, bidon
// get last point
BRep_Tool::UVPoints(aLastEdge, theFace, aP_temp, aP_last);
if (aLastEdge.Orientation() == TopAbs_REVERSED)
{
aP_last = aP_temp;
}
// Modified by Sergey KHROMOV - Mon Apr 22 10:36:33 2002 Begin
// double aTol, aUResol, aVResol;
// // find 2d tolerance
// aTol = BRep_Tool::Tolerance(aFirstVertex);
// aUResol = 2*aFaceSurface.UResolution(aTol);
// aVResol = 2*aFaceSurface.VResolution(aTol);
// get first point
if (aFirstEdge.Orientation() == TopAbs_REVERSED)
{
BRep_Tool::UVPoints(aFirstEdge, theFace, aP_temp, aP_first);
}
else
{
BRep_Tool::UVPoints(aFirstEdge, theFace, aP_first, aP_temp);
}
// Modified by Sergey KHROMOV - Thu Jun 20 10:55:42 2002 OCC325 Begin
// Check 2d distance for periodic faces with seam edge
if (!IsClosed2dForPeriodicFace(theFace, aP_first, aP_last, aFirstVertex))
{
aClosedStat = BRepCheck_NotClosed;
if (Update)
{
BRepCheck::Add(aStatusList, aClosedStat);
}
return aClosedStat;
}
// Modified by Sergey KHROMOV - Thu Jun 20 10:58:05 2002 End
// check distance
// double dfUDist=std::abs(p.X()-p1.X());
// double dfVDist=std::abs(p.Y()-p1.Y());
// if (dfUDist > aUResol || dfVDist > aVResol)
// {
double aTol3d =
std::max(BRep_Tool::Tolerance(aFirstVertex), BRep_Tool::Tolerance(aWireExp.CurrentVertex()));
gp_Pnt aPntRef = BRep_Tool::Pnt(aFirstVertex);
gp_Pnt aPnt = BRep_Tool::Pnt(aWireExp.CurrentVertex());
if (!(IsDistanceIn2DTolerance(aFaceSurface, aP_first, aP_last, aTol3d)))
{
aClosedStat = BRepCheck_NotClosed;
}
if (!IsDistanceIn3DTolerance(aPntRef, aPnt, aTol3d))
{
aClosedStat = BRepCheck_NotClosed;
}
if (Update)
{
BRepCheck::Add(aStatusList, aClosedStat);
}
return aClosedStat;
}
//=================================================================================================
BRepCheck_Status BRepCheck_Wire::Orientation(const TopoDS_Face& F, const bool Update)
{
BRepCheck_Status theOstat = Closed();
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
{
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
if (myIsParallel)
{
aLock.lock();
}
aHList = myMap(myShape);
}
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
if (theOstat != BRepCheck_NotClosed && theOstat != BRepCheck_NoError)
{
if (Update)
{
BRepCheck::Add(aStatusList, theOstat);
}
return theOstat;
}
theOstat = BRepCheck_NoError;
TopoDS_Vertex VF, VL;
TopAbs_Orientation orient, ortmp = TopAbs_FORWARD;
NCollection_List<TopoDS_Shape> ledge, ListOfPassedEdge;
TopExp_Explorer exp, vte;
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> mapS;
TopoDS_Edge theEdge, theRef;
// Checks the orientation of the edges
for (exp.Init(myShape, TopAbs_EDGE); exp.More(); exp.Next())
{
const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
orient = edg.Orientation();
if (IsOriented(edg))
{
mapS.Add(edg);
theEdge = edg;
theRef = edg;
for (vte.Init(edg, TopAbs_VERTEX); vte.More(); vte.Next())
{
TopAbs_Orientation vto = vte.Current().Orientation();
if (vto == TopAbs_FORWARD)
{
VF = TopoDS::Vertex(vte.Current());
}
else if (vto == TopAbs_REVERSED)
{
VL = TopoDS::Vertex(vte.Current());
}
if (!VF.IsNull() && !VL.IsNull())
{
break;
}
}
if (VF.IsNull() && VL.IsNull())
{
theOstat = BRepCheck_InvalidDegeneratedFlag;
}
break;
}
}
if (theOstat == BRepCheck_NoError)
{
int Index = 1;
int nbOriNoDegen = myMapVE.Extent();
// Modified by Sergey KHROMOV - Tue May 21 17:12:45 2002 Begin
bool isGoFwd = true;
if (VL.IsNull())
{
isGoFwd = false;
}
// Modified by Sergey KHROMOV - Tue May 21 17:12:45 2002 End
while (Index < nbOriNoDegen)
{
ledge.Clear();
ListOfPassedEdge.Clear();
// find edges that make a chain on VL if !VL.IsNull
// otherwise on VF.
int ind;
if (!VL.IsNull())
{
ind = myMapVE.FindIndex(VL);
}
else if (!VF.IsNull())
{
ind = myMapVE.FindIndex(VF);
}
else
{
theOstat = BRepCheck_InvalidDegeneratedFlag;
break;
}
for (NCollection_List<TopoDS_Shape>::Iterator itls(myMapVE(ind)); itls.More(); itls.Next())
{
const TopoDS_Edge& edg = TopoDS::Edge(itls.Value());
orient = edg.Orientation();
if (mapS.Contains(edg))
{
ortmp = GetOrientation(mapS, edg);
}
// Add to list already passed outcoming edges
if (mapS.Contains(edg) && ortmp == orient && !edg.IsSame(theEdge))
{
for (vte.Init(edg, TopAbs_VERTEX); vte.More(); vte.Next())
{
TopAbs_Orientation vto = vte.Current().Orientation();
if (!VL.IsNull())
{
if (vto == TopAbs_FORWARD && VL.IsSame(vte.Current()))
{
ListOfPassedEdge.Append(edg);
break;
}
}
else // VF is not null
{
if (vto == TopAbs_REVERSED && VF.IsSame(vte.Current()))
{
ListOfPassedEdge.Append(edg);
break;
}
}
}
}
if (!mapS.Contains(edg) || ortmp != orient)
{
for (vte.Init(edg, TopAbs_VERTEX); vte.More(); vte.Next())
{
TopAbs_Orientation vto = vte.Current().Orientation();
if (!VL.IsNull())
{
if (vto == TopAbs_FORWARD && VL.IsSame(vte.Current()))
{
// If the processing is in 2d (face not null) or
// if the edge is not degenerated it is added
if (!F.IsNull() || !BRep_Tool::Degenerated(edg))
{
ledge.Append(edg);
}
break;
}
}
else
{ // VF is not null
if (vto == TopAbs_REVERSED && VF.IsSame(vte.Current()))
{
// // If the processing is in 2d (face not null) or
// if the edge is not degenerated it is added
if (!F.IsNull() || !BRep_Tool::Degenerated(edg))
{
ledge.Append(edg);
}
break;
}
}
}
}
}
int nbconnex = ledge.Extent();
bool Changedesens = false;
if (nbconnex == 0)
{
if (myCstat == BRepCheck_NotClosed)
{
if (VL.IsNull())
{
if (Update)
{
BRepCheck::Add(aStatusList, theOstat);
}
return theOstat; // leave
}
else
{
Index--; // because after Index++ and if there is no chain,
VL.Nullify(); // chain on VF is forced
theEdge = theRef;
Changedesens = true;
}
}
else
{
theOstat = BRepCheck_BadOrientationOfSubshape;
if (Update)
{
BRepCheck::Add(aStatusList, theOstat);
}
return theOstat;
}
}
// JAG 03/07 else if (nbconnex >= 2 && !F.IsNull()) // Try to see in 2d
else if (!F.IsNull())
{ // Try to see in 2d
TopoDS_Vertex pivot;
if (!VL.IsNull())
{
pivot = VL;
}
else
{
pivot = VF;
}
ChoixUV(pivot, theEdge, F, ledge);
nbconnex = ledge.Extent();
// 20/03/02 akm vvv : (OCC234) - The 2d exploration of wire with necessary
// checks is performed in Closed2d, here it's useless
// if (nbconnex == 1 && !CheckLoopOrientation( pivot, theEdge,
// TopoDS::Edge(ledge.First()), F, ListOfPassedEdge ))
// {
// theOstat = BRepCheck_BadOrientationOfSubshape;
// if (Update)
// BRepCheck::Add(myMap(myShape),theOstat);
// return theOstat;
// }
// 20/03/02 akm ^^^
}
if (nbconnex >= 2)
{
theOstat = BRepCheck_BadOrientationOfSubshape;
if (Update)
{
BRepCheck::Add(aStatusList, theOstat);
}
return theOstat;
}
else if (nbconnex == 1)
{
// offset the vertex
for (vte.Init(ledge.First(), TopAbs_VERTEX); vte.More(); vte.Next())
{
TopAbs_Orientation vto = vte.Current().Orientation();
if (!VL.IsNull())
{
if (vto == TopAbs_REVERSED)
{
VL = TopoDS::Vertex(vte.Current());
break;
}
}
else
{ // VF is not null
if (vto == TopAbs_FORWARD)
{
VF = TopoDS::Vertex(vte.Current());
break;
}
}
}
mapS.Add(ledge.First());
theEdge = TopoDS::Edge(ledge.First());
if (!vte.More())
{
if (!VL.IsNull())
{
VL.Nullify();
}
else
{
VF.Nullify();
}
}
}
else if (!Changedesens)
{ // nbconnex == 0
theOstat = BRepCheck_NotClosed;
if (Update)
{
BRepCheck::Add(aStatusList, theOstat);
}
return theOstat;
}
// Check the closure of the wire in 2d (not done in Closed())
TopoDS_Vertex aVRef;
bool isCheckClose = false;
if (isGoFwd && !VF.IsNull())
{
aVRef = VF;
isCheckClose = true;
}
else if (!isGoFwd && !VL.IsNull())
{
aVRef = VL;
isCheckClose = true;
}
// if (Index==1 && myCstat!=BRepCheck_NotClosed &&
// !VF.IsNull() && !F.IsNull()) {
if (Index == 1 && myCstat != BRepCheck_NotClosed && isCheckClose && !F.IsNull())
{
ledge.Clear();
// ind = myMapVE.FindIndex(VF);
ind = myMapVE.FindIndex(aVRef);
for (NCollection_List<TopoDS_Shape>::Iterator itlsh(myMapVE(ind)); itlsh.More();
itlsh.Next())
{
const TopoDS_Edge& edg = TopoDS::Edge(itlsh.Value());
orient = edg.Orientation();
if (!theRef.IsSame(edg))
{
for (vte.Init(edg, TopAbs_VERTEX); vte.More(); vte.Next())
{
TopAbs_Orientation vto = vte.Current().Orientation();
// if (vto == TopAbs_REVERSED && VF.IsSame(vte.Current())) {
if (vto == TopAbs_REVERSED && aVRef.IsSame(vte.Current()))
{
ledge.Append(edg);
break;
}
}
}
}
// ChoixUV(VF, theRef, F, ledge);
ChoixUV(aVRef, theRef, F, ledge);
if (ledge.Extent() == 0)
{
theOstat = BRepCheck_NotClosed;
if (Update)
{
BRepCheck::Add(aStatusList, theOstat);
}
return theOstat;
}
}
// End control closure 2d
Index++;
}
}
if (Update)
{
BRepCheck::Add(aStatusList, theOstat);
}
return theOstat;
}
//=================================================================================================
BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F,
TopoDS_Edge& retE1,
TopoDS_Edge& retE2,
const bool Update)
{
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
{
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
if (myIsParallel)
{
aLock.lock();
}
aHList = myMap(myShape);
}
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
int i, j, Nbedges;
double first1, last1, first2, last2, tolint;
gp_Pnt2d pfirst1, plast1, pfirst2, plast2;
gp_Pnt P3d, P3d2;
occ::handle<BRepAdaptor_Surface> HS;
Geom2dAdaptor_Curve C1, C2;
Geom2dInt_GInter Inter;
IntRes2d_Domain myDomain1;
NCollection_IndexedMap<TopoDS_Shape> EMap;
NCollection_Map<TopoDS_Shape> auxmape;
//
//-- check with proper tolerances if there is no
//-- point in the tolerance of a vertex.
tolint = 1.e-10;
HS = new BRepAdaptor_Surface();
HS->Initialize(F, false);
//
for (TopoDS_Iterator Iter1(myShape); Iter1.More(); Iter1.Next())
{
if (Iter1.Value().ShapeType() == TopAbs_EDGE)
{
EMap.Add(Iter1.Value());
}
}
//
Nbedges = EMap.Extent();
if (!Nbedges)
{
if (Update)
{
BRepCheck::Add(aStatusList, BRepCheck_EmptyWire);
}
return (BRepCheck_EmptyWire);
}
//
IntRes2d_Domain* tabDom = new IntRes2d_Domain[Nbedges];
NCollection_Array1<occ::handle<Geom2d_Curve>> tabCur(1, Nbedges);
NCollection_Array1<Bnd_Box2d> boxes(1, Nbedges);
//
for (i = 1; i <= Nbedges; i++)
{
const TopoDS_Edge& E1 = TopoDS::Edge(EMap.FindKey(i));
if (i == 1)
{
occ::handle<Geom2d_Curve> pcu = BRep_Tool::CurveOnSurface(E1, F, first1, last1);
if (pcu.IsNull())
{
retE1 = E1;
if (Update)
{
BRepCheck::Add(aStatusList, BRepCheck_SelfIntersectingWire);
}
delete[] tabDom;
return (BRepCheck_SelfIntersectingWire);
}
//
C1.Load(pcu);
// To avoid exception in Segment if C1 is BSpline - IFV
if (!C1.IsPeriodic())
{
if (C1.FirstParameter() > first1)
{
first1 = C1.FirstParameter();
}
if (C1.LastParameter() < last1)
{
last1 = C1.LastParameter();
}
}
//
BRep_Tool::UVPoints(E1, F, pfirst1, plast1);
myDomain1.SetValues(pfirst1, first1, tolint, plast1, last1, tolint);
//
BndLib_Add2dCurve::Add(C1, first1, last1, Precision::PConfusion(), boxes(i));
} // if (i == 1) {
else
{
C1.Load(tabCur(i));
myDomain1 = tabDom[i - 1];
}
//
// Self intersect of C1
Inter.Perform(C1, myDomain1, tolint, tolint);
//
if (Inter.IsDone())
{
int nbp = Inter.NbPoints();
// int nbs = Inter.NbSegments();
//
for (int p = 1; p <= nbp; p++)
{
const IntRes2d_IntersectionPoint& IP = Inter.Point(p);
const IntRes2d_Transition& Tr1 = IP.TransitionOfFirst();
const IntRes2d_Transition& Tr2 = IP.TransitionOfSecond();
if (Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() == IntRes2d_Middle)
{
//-- Checking of points with true tolerances (ie Tol in 3d)
//-- If the point of intersection is within the tolerance of a vertex
//-- this intersection is considered correct (no error)
bool localok = false;
double f, l;
TopLoc_Location L;
const occ::handle<Geom_Curve> ConS = BRep_Tool::Curve(E1, L, f, l);
if (!ConS.IsNull())
{
//-- try to test in 3d. (ParamOnSecond gives the same result)
P3d = ConS->Value(IP.ParamOnFirst());
P3d.Transform(L.Transformation());
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
}
else
{
gp_Pnt2d aP2d = C1.Value(IP.ParamOnFirst());
P3d = HS->Value(aP2d.X(), aP2d.Y());
}
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
TopExp_Explorer ExplVtx;
for (ExplVtx.Init(E1, TopAbs_VERTEX); !localok && ExplVtx.More(); ExplVtx.Next())
{
gp_Pnt p3dvtt;
double tolvtt, p3dvttDistanceP3d;
//
const TopoDS_Vertex& vtt = TopoDS::Vertex(ExplVtx.Current());
p3dvtt = BRep_Tool::Pnt(vtt);
tolvtt = BRep_Tool::Tolerance(vtt);
tolvtt = tolvtt * tolvtt;
p3dvttDistanceP3d = p3dvtt.SquareDistance(P3d);
if (p3dvttDistanceP3d <= tolvtt)
{
localok = true;
}
}
if (!localok)
{
retE1 = E1;
if (Update)
{
BRepCheck::Add(aStatusList, BRepCheck_SelfIntersectingWire);
}
delete[] tabDom;
#ifdef OCCT_DEBUG
static int numpoint = 0;
std::cout << "point p" << ++numpoint << " " << P3d.X() << " " << P3d.Y() << " "
<< P3d.Z() << std::endl;
std::cout.flush();
#endif
return (BRepCheck_SelfIntersectingWire);
}
}
}
} // if(Inter.IsDone()) {
//
for (j = i + 1; j <= Nbedges; j++)
{
const TopoDS_Edge& E2 = TopoDS::Edge(EMap.FindKey(j));
if (i == 1)
{
tabCur(j) = BRep_Tool::CurveOnSurface(E2, F, first2, last2);
if (!tabCur(j).IsNull() && last2 > first2)
{
C2.Load(tabCur(j));
// To avoid exception in Segment if C2 is BSpline - IFV
if (!C2.IsPeriodic())
{
if (C2.FirstParameter() > first2)
{
first2 = C2.FirstParameter();
}
if (C2.LastParameter() < last2)
{
last2 = C2.LastParameter();
}
}
//
BRep_Tool::UVPoints(E2, F, pfirst2, plast2);
tabDom[j - 1].SetValues(pfirst2, first2, tolint, plast2, last2, tolint);
BndLib_Add2dCurve::Add(C2, first2, last2, Precision::PConfusion(), boxes(j));
}
else
{
delete[] tabDom;
#ifdef OCCT_DEBUG
std::cout << "BRepCheck_NoCurveOnSurface or BRepCheck_InvalidRange" << std::endl;
std::cout.flush();
#endif
if (tabCur(j).IsNull())
{
return (BRepCheck_NoCurveOnSurface);
}
return (BRepCheck_InvalidRange);
}
} // if (i == 1) {
else
{
C2.Load(tabCur(j));
}
//
if (boxes(i).IsOut(boxes(j)))
{
continue;
}
// modified by NIZNHY-PKV Fri Oct 29 10:09:01 2010f
if (E1.IsSame(E2))
{
continue;
}
// modified by NIZNHY-PKV Fri Oct 29 10:09:02 2010t
//
//-- ************************************************************
//-- ******* I n t e r s e c t i o n C 1 and C 2 ********
//-- ************************************************************
Inter.Perform(C1, myDomain1, C2, tabDom[j - 1], tolint, tolint);
//
if (Inter.IsDone())
{
int nbp, nbs;
double IP_ParamOnFirst, IP_ParamOnSecond;
IntRes2d_Transition Tr1, Tr2;
NCollection_List<TopoDS_Shape> CommonVertices;
NCollection_List<TopoDS_Shape>::Iterator itl;
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> Vmap;
//
TopoDS_Iterator it(E1);
for (; it.More(); it.Next())
{
Vmap.Add(it.Value());
}
//
it.Initialize(E2);
for (; it.More(); it.Next())
{
const TopoDS_Shape& V = it.Value();
if (Vmap.Contains(V))
{
CommonVertices.Append(V);
}
}
//
nbp = Inter.NbPoints();
nbs = Inter.NbSegments();
IP_ParamOnFirst = 0.;
IP_ParamOnSecond = 0.;
//
//// **** Points of intersection **** ////
for (int p = 1; p <= nbp; p++)
{
const IntRes2d_IntersectionPoint& IP = Inter.Point(p);
IP_ParamOnFirst = IP.ParamOnFirst();
IP_ParamOnSecond = IP.ParamOnSecond();
Tr1 = IP.TransitionOfFirst();
Tr2 = IP.TransitionOfSecond();
if (Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() == IntRes2d_Middle)
{
//-- Checking of points with true tolerances (ie Tol in 3d)
//-- If the point of intersection is within the tolerance of a vertex
//-- this intersection is considered correct (no error)
bool localok = false;
double f1, l1, f2, l2;
TopLoc_Location L, L2;
//
const occ::handle<Geom_Curve> ConS = BRep_Tool::Curve(E1, L, f1, l1);
const occ::handle<Geom_Curve> ConS2 = BRep_Tool::Curve(E2, L2, f2, l2);
// gka protect against working out of edge range
if (f1 - IP_ParamOnFirst > ::Precision::PConfusion()
|| IP_ParamOnFirst - l1 > ::Precision::PConfusion()
|| f2 - IP_ParamOnSecond > ::Precision::PConfusion()
|| IP_ParamOnSecond - l2 > ::Precision::PConfusion())
{
continue;
}
double tolvtt = 0.;
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
if (!ConS.IsNull())
{
P3d = ConS->Value(IP_ParamOnFirst);
P3d.Transform(L.Transformation());
}
else
{
gp_Pnt2d aP2d = C1.Value(IP_ParamOnFirst);
P3d = HS->Value(aP2d.X(), aP2d.Y());
}
//
if (!ConS2.IsNull())
{
P3d2 = ConS2->Value(IP_ParamOnSecond);
P3d2.Transform(L2.Transformation());
}
else
{
gp_Pnt2d aP2d = C2.Value(IP_ParamOnSecond);
P3d2 = HS->Value(aP2d.X(), aP2d.Y());
}
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
itl.Initialize(CommonVertices);
for (; itl.More(); itl.Next())
{
double p3dvttDistanceP3d, p3dvttDistanceP3d2;
gp_Pnt p3dvtt;
//
const TopoDS_Vertex& vtt = TopoDS::Vertex(itl.Value());
p3dvtt = BRep_Tool::Pnt(vtt);
tolvtt = BRep_Tool::Tolerance(vtt);
tolvtt = 1.1 * tolvtt;
tolvtt = tolvtt * tolvtt;
p3dvttDistanceP3d = p3dvtt.SquareDistance(P3d);
p3dvttDistanceP3d2 = p3dvtt.SquareDistance(P3d2);
//
if (p3dvttDistanceP3d <= tolvtt && p3dvttDistanceP3d2 <= tolvtt)
{
localok = true;
break;
}
}
//-- --------------------------------------------------------
//-- Check maximum yawn between 2 edges
//--
//-- Check distance from edges to the curve joining
//-- the point of intersection with vertex (if exists)
if (!localok && !CommonVertices.IsEmpty())
{
#ifdef OCCT_DEBUG
std::cout << "\n------------------------------------------------------\n"
<< std::endl;
std::cout << "\n--- BRepCheck Wire: AutoIntersection Phase1 -> Erreur \n"
<< std::endl;
#endif
double distauvtxleplusproche, VParaOnEdge1, VParaOnEdge2;
gp_Pnt VertexLePlusProche;
//
VParaOnEdge1 = 0.;
VParaOnEdge2 = 0.;
distauvtxleplusproche = RealLast();
// Find the nearest common vertex
itl.Initialize(CommonVertices);
for (; itl.More(); itl.Next())
{
double disptvtx;
gp_Pnt p3dvtt;
//
const TopoDS_Vertex& vtt = TopoDS::Vertex(itl.Value());
p3dvtt = BRep_Tool::Pnt(vtt);
disptvtx = P3d.Distance(p3dvtt);
if (disptvtx < distauvtxleplusproche)
{
VertexLePlusProche = p3dvtt;
distauvtxleplusproche = disptvtx;
VParaOnEdge1 = BRep_Tool::Parameter(vtt, E1);
VParaOnEdge2 = BRep_Tool::Parameter(vtt, E2);
}
// eap: case of closed edge
else if (IsEqual(distauvtxleplusproche, disptvtx))
{
double newVParaOnEdge1 = BRep_Tool::Parameter(vtt, E1);
double newVParaOnEdge2 = BRep_Tool::Parameter(vtt, E2);
if (std::abs(IP_ParamOnFirst - VParaOnEdge1)
+ std::abs(IP_ParamOnSecond - VParaOnEdge2)
> std::abs(IP_ParamOnFirst - newVParaOnEdge1)
+ std::abs(IP_ParamOnSecond - newVParaOnEdge2))
{
VertexLePlusProche = p3dvtt;
VParaOnEdge1 = newVParaOnEdge1;
VParaOnEdge2 = newVParaOnEdge2;
}
}
}
// Patch: extraordinar situation (e.g. tolerance(v) == 0.)
// Modified by skv - Wed Jul 23 12:28:11 2003 OCC1764 Begin
// if (VertexLePlusProche.Distance( P3d ) <= gp::Resolution())
if (VertexLePlusProche.Distance(P3d) <= gp::Resolution()
|| VertexLePlusProche.Distance(P3d2) <= gp::Resolution())
{
// Modified by skv - Wed Jul 23 12:28:12 2003 OCC1764 End
localok = true;
}
else
{
gp_Lin Lig(VertexLePlusProche, gp_Vec(VertexLePlusProche, P3d));
double du1 = 0.1 * (IP_ParamOnFirst - VParaOnEdge1);
double du2 = 0.1 * (IP_ParamOnSecond - VParaOnEdge2);
double maxd1 = 0., maxd2 = 0.;
int k;
localok = true;
double tole1 = BRep_Tool::Tolerance(E1);
for (k = 2; localok && k < 9; k++)
{
double u = VParaOnEdge1 + k * du1; // check if it works
gp_Pnt P1;
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
if (!ConS.IsNull())
{
P1 = ConS->Value(u);
P1.Transform(L.Transformation());
}
else
{
gp_Pnt2d aP2d = C1.Value(u);
P1 = HS->Value(aP2d.X(), aP2d.Y());
}
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
double d1 = Lig.Distance(P1);
if (d1 > maxd1)
{
maxd1 = d1;
}
if (d1 > tole1 * 2.0)
{
localok = false;
}
}
//-- same for edge2
// Modified by skv - Wed Jul 23 12:22:20 2003 OCC1764 Begin
gp_Dir aTmpDir(P3d2.XYZ().Subtracted(VertexLePlusProche.XYZ()));
Lig.SetDirection(aTmpDir);
// Modified by skv - Wed Jul 23 12:22:23 2003 OCC1764 End
double tole2 = BRep_Tool::Tolerance(E2);
for (k = 2; localok && k < 9; k++)
{
double u = VParaOnEdge2 + k * du2; // check if it works
gp_Pnt P2;
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
if (!ConS2.IsNull())
{
P2 = ConS2->Value(u);
P2.Transform(L2.Transformation());
}
else
{
gp_Pnt2d aP2d = C2.Value(u);
P2 = HS->Value(aP2d.X(), aP2d.Y());
}
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
double d2 = Lig.Distance(P2);
if (d2 > maxd2)
{
maxd2 = d2;
}
if (d2 > tole2 * 2.0)
{
localok = false;
}
}
#ifdef OCCT_DEBUG
if (localok)
{
printf("--- BRepCheck Wire: AutoIntersection Phase2 -> Bon \n");
printf("--- distance Point Vertex : %10.7g (tol %10.7g)\n",
distauvtxleplusproche,
tolvtt);
printf("--- Erreur Max sur E1 : %10.7g Tol_Edge:%10.7g\n", maxd1, tole1);
printf("--- Erreur Max sur E2 : %10.7g Tol_Edge:%10.7g\n", maxd2, tole2);
fflush(stdout);
}
else
{
printf("--- BRepCheck Wire: AutoIntersection Phase2 -> Erreur \n");
printf("--- distance Point Vertex : %10.7g (tol %10.7g)\n",
distauvtxleplusproche,
tolvtt);
printf("--- Erreur Max sur E1 : %10.7g Tol_Edge:%10.7g\n", maxd1, tole1);
printf("--- Erreur Max sur E2 : %10.7g Tol_Edge:%10.7g\n", maxd2, tole2);
fflush(stdout);
}
#endif
} // end of else (construction of the line Lig)
} // end of if (localok == false && !CommonVertices.IsEmpty())
//
if (!localok)
{
retE1 = E1;
retE2 = E2;
if (Update)
{
BRepCheck::Add(aStatusList, BRepCheck_SelfIntersectingWire);
}
#ifdef OCCT_DEBUG
static int numpoint1 = 0;
std::cout << "point p" << ++numpoint1 << " " << P3d.X() << " " << P3d.Y() << " "
<< P3d.Z() << std::endl;
std::cout.flush();
#endif
delete[] tabDom;
return (BRepCheck_SelfIntersectingWire);
} //-- localok == False
} // end of if(Tr1.PositionOnCurve() == IntRes2d_Middle || Tr2.PositionOnCurve() ==
// IntRes2d_Middle)
} // end of for (int p=1; p <= nbp; p++)
////
//// **** Segments of intersection **** ////
for (int s = 1; s <= nbs; ++s)
{
const IntRes2d_IntersectionSegment& Seg = Inter.Segment(s);
if (Seg.HasFirstPoint() && Seg.HasLastPoint())
{
bool localok;
int k;
IntRes2d_IntersectionPoint PSeg[2];
IntRes2d_Position aPCR1, aPCR2;
//
localok = false;
PSeg[0] = Seg.FirstPoint();
PSeg[1] = Seg.LastPoint();
// At least one of extremities of the segment must be inside
// the tolerance of a common vertex
for (k = 0; k < 2; ++k)
{
IP_ParamOnFirst = PSeg[k].ParamOnFirst();
IP_ParamOnSecond = PSeg[k].ParamOnSecond();
Tr1 = PSeg[k].TransitionOfFirst();
Tr2 = PSeg[k].TransitionOfSecond();
aPCR1 = Tr1.PositionOnCurve();
aPCR2 = Tr2.PositionOnCurve();
//
if (aPCR1 != IntRes2d_Middle && aPCR2 != IntRes2d_Middle)
{
GeomAbs_CurveType aCT1, aCT2;
// ZZ
aCT1 = C1.GetType();
aCT2 = C2.GetType();
if (aCT1 == GeomAbs_Line && aCT2 == GeomAbs_Line)
{
// check for the two lines coincidence
double aPAR_T, aT11, aT12, aT21, aT22, aT1m, aT2m;
double aD2, aTolE1, aTolE2, aTol2;
gp_Lin2d aL1, aL2;
gp_Pnt2d aP1m;
//
aPAR_T = 0.43213918;
//
aTolE1 = BRep_Tool::Tolerance(E1);
aTolE2 = BRep_Tool::Tolerance(E2);
aTol2 = aTolE1 + aTolE2;
aTol2 = aTol2 * aTol2;
//
aL1 = C1.Line();
aL2 = C2.Line();
//
aT11 = PSeg[0].ParamOnFirst();
aT12 = PSeg[1].ParamOnFirst();
aT21 = PSeg[0].ParamOnSecond();
aT22 = PSeg[1].ParamOnSecond();
//
aT1m = (1. - aPAR_T) * aT11 + aPAR_T * aT12;
aP1m = C1.Value(aT1m);
//
aD2 = aL2.SquareDistance(aP1m);
if (aD2 < aTol2)
{
aT2m = ElCLib::Parameter(aL2, aP1m);
if (aT2m > aT21 && aT2m < aT22)
{
const gp_Dir2d& aDir1 = aL1.Direction();
const gp_Dir2d& aDir2 = aL2.Direction();
if (aDir1.IsParallel(aDir2, Precision::Angular()))
{
localok = false;
break; // from for (k = 0; k < 2; ++k){...
}
} // if (aT2m>aT21 && aT2m<aT22) {
} // if (aD2<aTol2) {
} // if (aCT1==GeomAbs_Line && aCT2==GeomAbs_Line) {
// ZZ
localok = true;
break;
}
//
double f, l, tolvtt;
TopLoc_Location L, L2;
const occ::handle<Geom_Curve>& ConS = BRep_Tool::Curve(E1, L, f, l);
const occ::handle<Geom_Curve>& ConS2 = BRep_Tool::Curve(E2, L2, f, l);
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 Begin
if (!ConS.IsNull())
{
P3d = ConS->Value(IP_ParamOnFirst);
P3d.Transform(L.Transformation());
}
else
{
gp_Pnt2d aP2d = C1.Value(IP_ParamOnFirst);
P3d = HS->Value(aP2d.X(), aP2d.Y());
}
if (!ConS2.IsNull())
{
P3d2 = ConS2->Value(IP_ParamOnSecond);
P3d2.Transform(L2.Transformation());
}
else
{
gp_Pnt2d aP2d = C2.Value(IP_ParamOnSecond);
P3d2 = HS->Value(aP2d.X(), aP2d.Y());
}
// Modified by Sergey KHROMOV - Mon Apr 15 12:34:22 2002 End
itl.Initialize(CommonVertices);
for (; itl.More(); itl.Next())
{
double p3dvttDistanceP3d, p3dvttDistanceP3d2;
gp_Pnt p3dvtt;
//
const TopoDS_Vertex& vtt = TopoDS::Vertex(itl.Value());
p3dvtt = BRep_Tool::Pnt(vtt);
tolvtt = BRep_Tool::Tolerance(vtt);
tolvtt = 1.1 * tolvtt;
tolvtt = tolvtt * tolvtt;
p3dvttDistanceP3d = p3dvtt.SquareDistance(P3d);
p3dvttDistanceP3d2 = p3dvtt.SquareDistance(P3d2);
if (p3dvttDistanceP3d <= tolvtt && p3dvttDistanceP3d2 <= tolvtt)
{
localok = true;
break;
}
}
if (localok)
{
break;
}
} // end of for (k = 0; k < 2; k++)
//
if (!localok)
{
retE1 = E1;
retE2 = E2;
if (Update)
{
BRepCheck::Add(aStatusList, BRepCheck_SelfIntersectingWire);
}
#ifdef OCCT_DEBUG
static int numpoint1 = 0;
std::cout << "point p" << ++numpoint1 << " " << P3d.X() << " " << P3d.Y() << " "
<< P3d.Z() << std::endl;
std::cout.flush();
#endif
delete[] tabDom;
return (BRepCheck_SelfIntersectingWire);
} //-- localok == False
} // end of if(Seg.HasFirstPoint() && Seg.HasLastPoint())
} // end of for (int s = 1; s <= nbs; p++)
} //-- Inter.IsDone()
} // end of for( j = i+1; j<=Nbedges; j++)
} // end of for(i = 1; i <= Nbedges; i++)
//
delete[] tabDom;
if (Update)
{
BRepCheck::Add(aStatusList, BRepCheck_NoError);
}
//
return (BRepCheck_NoError);
}
//=================================================================================================
void BRepCheck_Wire::SetStatus(const BRepCheck_Status theStatus)
{
BRepCheck::Add(*myMap(myShape), theStatus);
}
//=================================================================================================
void BRepCheck_Wire::GeometricControls(const bool B)
{
if (myGctrl != B)
{
if (B)
{
myCdone = false;
}
myGctrl = B;
}
}
//=================================================================================================
bool BRepCheck_Wire::GeometricControls() const
{
return myGctrl;
}
//=======================================================================
// function : Propagate
// purpose : fill <mapE> with edges connected to <edg> through vertices
// contained in <mapVE>
//=======================================================================
static void Propagate(const NCollection_IndexedDataMap<TopoDS_Shape,
NCollection_List<TopoDS_Shape>,
TopTools_ShapeMapHasher>& mapVE,
const TopoDS_Shape& edg,
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher>& mapE)
{
NCollection_List<TopoDS_Shape> currentEdges;
currentEdges.Append(edg);
do
{
NCollection_List<TopoDS_Shape> nextEdges;
NCollection_List<TopoDS_Shape>::Iterator itrc(currentEdges);
for (; itrc.More(); itrc.Next())
{
const TopoDS_Shape& Edge = itrc.Value();
if (!mapE.Contains(Edge))
{
mapE.Add(Edge);
}
TopExp_Explorer ex(Edge, TopAbs_VERTEX);
for (; ex.More(); ex.Next())
{
const TopoDS_Vertex& vtx = TopoDS::Vertex(ex.Current());
int indv = mapVE.FindIndex(vtx);
if (indv != 0)
{
const NCollection_List<TopoDS_Shape>& edges = mapVE(indv);
NCollection_List<TopoDS_Shape>::Iterator itl(edges);
for (; itl.More(); itl.Next())
{
const TopoDS_Shape& E = itl.Value();
if (!Edge.IsSame(E) && !mapE.Contains(E))
{
mapE.Add(E);
nextEdges.Append(E);
}
}
}
}
}
currentEdges = nextEdges;
} while (!currentEdges.IsEmpty());
}
//=================================================================================================
static TopAbs_Orientation GetOrientation(
const NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher>& mapE,
const TopoDS_Edge& edg)
{
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher>::Iterator itm(mapE);
for (; itm.More(); itm.Next())
{
if (itm.Key().IsSame(edg))
{
break;
}
}
return itm.Key().Orientation();
}
//=======================================================================
// function : ChoixUV
// purpose : For vertex theVertex given function find an edge along
// that we should go further.
//=======================================================================
void ChoixUV(const TopoDS_Vertex& theVertex,
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
NCollection_List<TopoDS_Shape>& theLOfShape)
{
NCollection_List<TopoDS_Shape>::Iterator It(theLOfShape);
while (It.More())
{
if (theEdge.IsSame(It.Value()))
{
theLOfShape.Remove(It);
}
else
{
It.Next();
}
}
double aTol3d = BRep_Tool::Tolerance(theVertex);
int anIndex = 0, anIndMin = 0;
TopoDS_Edge anEFound;
gp_Pnt2d aPntRef, aPnt;
gp_Vec2d aDerRef, aDer;
double aMinAngle, aMaxAngle, anAngle;
double a_gpResolution = gp::Resolution();
TopAbs_Orientation aVOrientation, anEdgOrientation;
double aParam = 0.0, aFirstParam = 0.0, aLastParam = 0.0, aParPiv = 0.0;
BRepAdaptor_Surface aFaceSurface(theFace, false); // no restriction
occ::handle<Geom2d_Curve> C2d =
BRep_Tool::CurveOnSurface(theEdge, theFace, aFirstParam, aLastParam);
if (C2d.IsNull())
{ // JAG 10.12.96
return;
}
aVOrientation = theVertex.Orientation();
anEdgOrientation = theEdge.Orientation();
aParPiv = (aVOrientation == anEdgOrientation) ? aFirstParam : aLastParam;
aMinAngle = RealLast();
aMaxAngle = RealFirst();
CurveDirForParameter(C2d, aParPiv, aPntRef, aDerRef);
if (aVOrientation != anEdgOrientation)
{
aDerRef.Reverse();
}
It.Initialize(theLOfShape);
for (; It.More(); It.Next())
{
anIndex++;
const TopoDS_Edge& anE = TopoDS::Edge(It.Value());
C2d = BRep_Tool::CurveOnSurface(anE, theFace, aFirstParam, aLastParam);
if (C2d.IsNull())
{
continue;
}
Geom2dAdaptor_Curve aCA(C2d);
aParam = (aVOrientation != anE.Orientation()) ? aFirstParam : aLastParam;
aPnt = aCA.Value(aParam);
if (!IsDistanceIn2DTolerance(aFaceSurface, aPnt, aPntRef, aTol3d, false))
{
continue;
}
CurveDirForParameter(aCA, aParam, aPnt, aDer);
if (aVOrientation == anE.Orientation())
{
aDer.Reverse();
}
if ((aDerRef.Magnitude() <= a_gpResolution) || (aDer.Magnitude() <= a_gpResolution))
{
// Vector length is too small
continue;
}
anAngle = -aDerRef.Angle(aDer);
if (anAngle < 0.)
{
anAngle += 2. * M_PI;
}
if (theFace.Orientation() == TopAbs_FORWARD)
{
if (anAngle < aMinAngle)
{
anIndMin = anIndex;
aMinAngle = anAngle;
}
}
else // theFace.Orientation() != TopAbs_FORWARD
{
if (anAngle > aMaxAngle)
{
anIndMin = anIndex;
aMaxAngle = anAngle;
}
}
} // end of for
// Update edge
if (anIndMin == 0)
{
if (theLOfShape.Extent() == 1)
{
bool IsFound = true; // all right
anEFound = TopoDS::Edge(theLOfShape.First());
if (anEFound.IsNull() || BRep_Tool::Degenerated(theEdge) || BRep_Tool::Degenerated(anEFound))
{
IsFound = false; // bad
}
else if (!IsDistanceIn2DTolerance(aFaceSurface, aPnt, aPntRef, aTol3d))
{
IsFound = false; // bad
}
else
// clousureness in 3D
{
// IsDistanceIn3DTolerance
BRepAdaptor_Curve bcEdg(theEdge, theFace);
BRepAdaptor_Curve bcEvois(anEFound, theFace);
gp_Pnt pEdg = bcEdg.Value(aParPiv);
gp_Pnt pEFound = bcEvois.Value(aParam);
IsFound = IsDistanceIn3DTolerance(pEdg, pEFound, aTol3d);
}
if (!IsFound)
{
theLOfShape.Clear();
}
} // if (theLOfShape.Extent() == 1)
else // if (anIndMin == 0)
{
theLOfShape.Clear();
}
}
else
{
anIndex = 1;
while (anIndex < anIndMin)
{
theLOfShape.RemoveFirst();
anIndex++;
}
It.Initialize(theLOfShape);
It.Next();
while (It.More())
{
theLOfShape.Remove(It);
}
}
} // End of function
//=================================================================================================
void CurveDirForParameter(const Geom2dAdaptor_Curve& aC2d,
const double aPrm,
gp_Pnt2d& Pnt,
gp_Vec2d& aVec2d)
{
double aTol = gp::Resolution();
int i;
aC2d.D1(aPrm, Pnt, aVec2d);
//
if (aVec2d.Magnitude() <= aTol)
{
for (i = 2; i <= 100; i++)
{
aVec2d = aC2d.DN(aPrm, i);
if (aVec2d.Magnitude() > aTol)
{
break;
}
}
}
}
// Modified by Sergey KHROMOV - Wed May 22 10:44:06 2002 OCC325 Begin
//=======================================================================
// function : GetPnts2d
// purpose : this function returns the parametric points of theVertex on theFace.
// If theVertex is a start and end vertex of theEdge hasSecondPnt
// becomes true and aPnt2 returns the second parametric point.
// Returns true if paraametric points are successfully found.
//=======================================================================
static bool GetPnt2d(const TopoDS_Vertex& theVertex,
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
gp_Pnt2d& aPnt)
{
occ::handle<Geom2d_Curve> aPCurve;
double aFPar;
double aLPar;
double aParOnEdge;
TopoDS_Vertex aFirstVtx;
TopoDS_Vertex aLastVtx;
TopExp::Vertices(theEdge, aFirstVtx, aLastVtx);
if (!theVertex.IsSame(aFirstVtx) && !theVertex.IsSame(aLastVtx))
{
return false;
}
aPCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, aFPar, aLPar);
if (aPCurve.IsNull())
{
return false;
}
aParOnEdge = BRep_Tool::Parameter(theVertex, theEdge);
aPnt = aPCurve->Value(aParOnEdge);
return true;
}
//=======================================================================
// function : Closed2dForPeriodicFace
// purpose : Checks the distance between first point of the first edge
// and last point of the last edge in 2d for periodic face.
//=======================================================================
static bool IsClosed2dForPeriodicFace(const TopoDS_Face& theFace,
const gp_Pnt2d& theP1,
const gp_Pnt2d& theP2,
const TopoDS_Vertex& theVertex)
{
// Check 2d distance for periodic faces with seam edge.
// Searching for seam edges
NCollection_List<TopoDS_Shape> aSeamEdges;
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> NotSeams;
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> ClosedEdges;
TopExp_Explorer anExp(theFace, TopAbs_EDGE);
for (; anExp.More(); anExp.Next())
{
TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
if (NotSeams.Contains(anEdge))
{
continue;
}
if (!IsOriented(anEdge) || !BRep_Tool::IsClosed(anEdge, theFace))
{
NotSeams.Add(anEdge);
continue;
}
if (!ClosedEdges.Add(anEdge))
{
aSeamEdges.Append(anEdge);
}
}
if (aSeamEdges.Extent() == 0)
{
return true;
}
// check if theVertex lies on one of the seam edges
BRepAdaptor_Surface aFaceSurface(theFace, false);
double aTol = BRep_Tool::Tolerance(theVertex);
double aUResol = aFaceSurface.UResolution(aTol);
double aVResol = aFaceSurface.VResolution(aTol);
double aVicinity = std::sqrt(aUResol * aUResol + aVResol * aVResol);
double aDistP1P2 = theP1.Distance(theP2);
NCollection_List<TopoDS_Shape>::Iterator anIter(aSeamEdges);
for (; anIter.More(); anIter.Next())
{
TopoDS_Edge aSeamEdge = TopoDS::Edge(anIter.Value());
anExp.Init(aSeamEdge, TopAbs_VERTEX);
for (; anExp.More(); anExp.Next())
{
const TopoDS_Shape& aVtx = anExp.Current();
// We found an edge. Check the distance between two given points
// to be lower than the computed tolerance.
if (IsOriented(aVtx) && aVtx.IsSame(theVertex))
{
gp_Pnt2d aPnt1;
gp_Pnt2d aPnt2;
double a2dTol;
if (!GetPnt2d(theVertex, aSeamEdge, theFace, aPnt1))
{
continue;
}
aSeamEdge = TopoDS::Edge(aSeamEdge.Reversed());
if (!GetPnt2d(theVertex, aSeamEdge, theFace, aPnt2))
{
continue;
}
a2dTol = aPnt1.Distance(aPnt2) * 1.e-2;
a2dTol = std::max(a2dTol, aVicinity);
if (aDistP1P2 > a2dTol)
{
return false;
}
}
}
}
return true;
}
// Modified by Sergey KHROMOV - Thu Jun 20 10:58:05 2002 End