1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0024968: Impove BRepMesh_Classifier to cope with intersection of huge number of wires

BRepMesh_Classifier: Two-pass approach for intersection check with possibility to run it in parallel mode.
First pass - bounding boxes of segments are checked for overlapping;
Second pass - intersection point is calculated in case if overlapping is detected.

Make NCollection_UBTree::ChangeLastNode() exported due to compilation error on Linux platform.
Reason: method does not depend on template parameters, so it should be available.

Revert previous change and try to use another trick for Linux

Fix compilation warning on MacOS: remove redundant constant
Fix regressions: do not consider insignificant loops in case of self intersections on the same wire.
More sugar solution for compilation errors on NCollection_EBTree on Linux

Test cases for issue CR24968
This commit is contained in:
oan 2014-07-10 14:40:36 +04:00 committed by apn
parent 0e9d3b83b8
commit 01a6e62bc2
29 changed files with 1454 additions and 3460 deletions

View File

@ -89,6 +89,7 @@ is enumeration DegreeOfFreedom is
imported VertexInspector from BRepMesh;
imported VertexCellFilter from BRepMesh;
imported VectorOfVertex from BRepMesh;
imported WireInterferenceChecker from BRepMesh;
imported EdgeChecker from BRepMesh;
imported FaceChecker from BRepMesh;
@ -149,11 +150,6 @@ is enumeration DegreeOfFreedom is
class IndexedMapOfVertex instantiates IndexedMap from TCollection
(Vertex from BRepMesh, VertexHasher from BRepMesh);
class BiPoint;
class Array1OfBiPoint instantiates Array1 from TCollection(BiPoint from BRepMesh);
private class FastDiscretFace;
class FastDiscret;
@ -165,8 +161,9 @@ is enumeration DegreeOfFreedom is
FaceAttribute from BRepMesh,
ShapeMapHasher from TopTools);
private class Classifier;
imported Classifier from BRepMesh;
imported ClassifierPtr; -- smart pointer on Classifier
imported WireChecker from BRepMesh;
imported IncrementalMesh from BRepMesh;

View File

@ -1,44 +0,0 @@
-- Created on: 1997-09-18
-- Created by: Christophe MARION
-- Copyright (c) 1997-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.
class BiPoint from BRepMesh
uses
Address from Standard,
Real from Standard,
Integer from Standard
is
Create
returns BiPoint from BRepMesh;
---C++: inline
Create(X1,Y1,X2,Y2 : Real from Standard)
returns BiPoint from BRepMesh;
Indices(me) returns Address from Standard
---C++: inline
is static;
Coordinates(me) returns Address from Standard
---C++: inline
is static;
fields
myIndices : Integer from Standard[2];
myCoordinates : Real from Standard[6];
end BiPoint;

View File

@ -1,46 +0,0 @@
// Created on: 1997-09-18
// Created by: Christophe MARION
// Copyright (c) 1997-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.
//#define No_Exception
#include <BRepMesh_BiPoint.ixx>
#define PntX1 myCoordinates[0]
#define PntY1 myCoordinates[1]
#define PntX2 myCoordinates[2]
#define PntY2 myCoordinates[3]
#define VectX myCoordinates[4]
#define VectY myCoordinates[5]
#define MinSg myIndices[0]
#define MaxSg myIndices[1]
//=======================================================================
//function : BRepMesh_BiPoint
//purpose :
//=======================================================================
BRepMesh_BiPoint::BRepMesh_BiPoint (const Standard_Real X1,
const Standard_Real Y1,
const Standard_Real X2,
const Standard_Real Y2)
{
PntX1 = X1;
PntY1 = Y1;
PntX2 = X2;
PntY2 = Y2;
}

View File

@ -1,41 +0,0 @@
// Created on: 1997-09-18
// Created by: Christophe MARION
// Copyright (c) 1997-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.
//=======================================================================
//function : BRepMesh_BiPoint
//purpose :
//=======================================================================
inline BRepMesh_BiPoint::BRepMesh_BiPoint ()
{
}
//=======================================================================
//function : Indices
//purpose :
//=======================================================================
inline Standard_Address BRepMesh_BiPoint::Indices () const
{ return (Standard_Address)myIndices; }
//=======================================================================
//function : Coordinates
//purpose :
//=======================================================================
inline Standard_Address BRepMesh_BiPoint::Coordinates () const
{ return (Standard_Address)myCoordinates; }

View File

@ -1,74 +0,0 @@
-- Created on: 1997-06-26
-- Created by: Laurent PAINNOT
-- Copyright (c) 1997-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.
private class Classifier from BRepMesh
uses
Pnt2d from gp,
SequenceOfPnt2d from TColgp,
Face from TopoDS,
State from TopAbs,
SequenceOfInteger from TColStd,
SeqOfPtr from BRepTopAdaptor,
DataMapOfShapePairOfPolygon from BRepMesh,
IndexedMapOfInteger from TColStd,
IndexedMapOfVertex from BRepMesh,
Status from BRepMesh,
DataStructureOfDelaun from BRepMesh
is
Create (theFace : Face from TopoDS;
theTolUV : Real from Standard;
theEdges : DataMapOfShapePairOfPolygon from BRepMesh;
theMap : IndexedMapOfInteger from TColStd;
theStructure : DataStructureOfDelaun from BRepMesh;
theUmin, theUmax, theVmin, theVmax : Real from Standard)
returns Classifier from BRepMesh;
Perform(me; thePoint: Pnt2d from gp)
returns State from TopAbs;
State (me)
returns Status from BRepMesh;
---C++: inline
Destroy(me: in out);
---C++: alias ~
AnalizeWire (me : in out;
theSeqPnt2d : in SequenceOfPnt2d from TColgp;
theUmin, theUmax, theVmin, theVmax: in Real from Standard)
is private;
-- Private method called from constructor after some (piece of) wire
-- has been explored and put into <theSeqPnt2d>.
-- Here it is triangulated if it is a hole and anyway added to the bulk.
fields
myTabClass : SeqOfPtr from BRepTopAdaptor;
myTabOrient : SequenceOfInteger from TColStd;
myTolUV : Real from Standard;
myFace : Face from TopoDS;
myState : Status from BRepMesh;
end Classifier from BRepMesh;

View File

@ -14,565 +14,21 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BRepMesh_Classifier.ixx>
#include <BRepMesh_Classifier.hxx>
// Kernel
#include <Precision.hxx>
#include <Standard_ErrorHandler.hxx>
#include <TColStd_ListOfTransient.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_DataMapOfIntegerInteger.hxx>
#include <ElCLib.hxx>
// Geometry
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <TColgp_SequenceOfPnt2d.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <Geom2dInt_Geom2dCurveTool.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_BezierCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
// Topology
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <BRepAdaptor_Curve2d.hxx>
#include <TopAbs_Orientation.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS.hxx>
#include <CSLib_Class2d.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
// BRepMesh
#include <BRepMesh_Vertex.hxx>
#include <BRepMesh_Array1OfBiPoint.hxx>
#include <BRepMesh_PairOfPolygon.hxx>
static const Standard_Real PARALL_COND = Sin(M_PI/3.0);
static const Standard_Real RESOLUTION = 1.0E-16;
// Real mesh is created in the grid 10E5x10E5, so intersection
// should be cheched with double of discretization.
static const Standard_Real MIN_DIST = 2.E-5;
#include <TColgp_Array1OfPnt2d.hxx>
//=======================================================================
//function : AnalizeWire
//function : Constructor
//purpose :
//=======================================================================
void BRepMesh_Classifier::AnalizeWire (const TColgp_SequenceOfPnt2d& theSeqPnt2d,
const Standard_Real theUmin, const Standard_Real theUmax,
const Standard_Real theVmin, const Standard_Real theVmax)
BRepMesh_Classifier::BRepMesh_Classifier()
{
const Standard_Integer aNbPnts = theSeqPnt2d.Length();
if (aNbPnts < 2)
return;
// Accumulate angle
TColgp_Array1OfPnt2d aPClass(1, aNbPnts);
Standard_Real anAngle = 0.0;
gp_Pnt2d p1 = theSeqPnt2d(1), p2 = theSeqPnt2d(2), p3;
aPClass(1) = p1;
aPClass(2) = p2;
for (Standard_Integer i = 1; i <= aNbPnts; i++)
{
Standard_Integer ii = i + 2;
if (ii > aNbPnts)
{
p3 = aPClass(ii - aNbPnts);
}
else
{
p3 = theSeqPnt2d.Value(ii);
aPClass(ii) = p3;
}
gp_Vec2d A(p1,p2), B(p2,p3);
if (A.SquareMagnitude() > 1.e-16 && B.SquareMagnitude() > 1.e-16)
{
const Standard_Real aCurAngle = A.Angle(B);
const Standard_Real aCurAngleAbs = Abs(aCurAngle);
// Check if vectors are opposite
if (aCurAngleAbs > Precision::Angular() && (M_PI - aCurAngleAbs) > Precision::Angular())
{
anAngle += aCurAngle;
p1 = p2;
}
}
p2 = p3;
}
// Check for zero angle - treat self intersecting wire as outer
if (Abs(anAngle) < Precision::Angular())
anAngle = 0.0;
myTabClass.Append( (void *)new CSLib_Class2d(aPClass, myTolUV, myTolUV,
theUmin, theVmin, theUmax, theVmax) );
myTabOrient.Append( ((anAngle < 0.0) ? 0 : 1) );
}
//=======================================================================
//function : triangle2Area
//purpose : calculating area under triangle
//=======================================================================
inline static Standard_Real triangle2Area(const gp_XY& p1, const gp_XY& p2)
{
return p1.Crossed(p2);
}
//=======================================================================
//function : getSegmentParams
//purpose : extracting segment attributes
//=======================================================================
static Standard_Real getSegmentParams(const BRepMesh_Array1OfBiPoint& theBiPoints,
const Standard_Integer Index,
Standard_Real& x11,
Standard_Real& y11,
Standard_Real& x12,
Standard_Real& y12,
Standard_Real& A,
Standard_Real& B,
Standard_Real& C)
{
Standard_Real *aCoordinates;
aCoordinates = ((Standard_Real*)(theBiPoints(Index).Coordinates()));
x11 = aCoordinates[0];
y11 = aCoordinates[1];
x12 = aCoordinates[2];
y12 = aCoordinates[3];
A = aCoordinates[5];
B = -aCoordinates[4];
C = - x11*A - y11*B;
return A*A+B*B;
}
//=======================================================================
//function : checkWiresIntersection
//purpose : finding intersection.
// If the intersection is found return Standard_True
//=======================================================================
static Standard_Boolean checkWiresIntersection(const Standard_Integer theFirstWireId,
const Standard_Integer theSecondWireId,
Standard_Integer* const theFirstOuterSegmentId,
Standard_Integer theLastOuterSegmentId,
const TColStd_SequenceOfInteger& theWireLength,
const BRepMesh_Array1OfBiPoint& theBiPoints,
const Standard_Boolean findNextIntersection = Standard_False,
const Standard_Boolean isFirstSegment = Standard_False,
Standard_Integer* const theFirstInnerSegmentId = 0)
{
Standard_Real A1, B1, C1, A2, B2, C2, AB, BC, CA, xc, yc;
Standard_Real mu1, d, mu2;
Standard_Integer ik = *theFirstOuterSegmentId, jk;
Standard_Real x11, x12, y11, y12, x21, x22, y21, y22;
// Calculate bounds for first wire
Standard_Integer ikEnd = theLastOuterSegmentId;
Standard_Boolean isFirst = Standard_True;
if ( findNextIntersection )
isFirst = isFirstSegment;
// Calculate bounds for second wire
Standard_Integer jkStart = 0, jkEnd = 0;
for (jk = 1; jk <= theSecondWireId; jk++)
{
jkStart = jkEnd + 1;
jkEnd += theWireLength(jk);
}
// total area under polygon (area of loop)
Standard_Real aLoopArea = 0.0;
// area under first triangles of polygon
Standard_Real aFirstTriangleArea = 0.0;
// contains coordinates of the end point of segment if first intersection point is finding
// or coordinates of the intersecting point if second intersection point is finding
gp_XY aStartPoint;
for (; ik <= ikEnd; ik++)
{
mu1 = getSegmentParams(theBiPoints, ik, x11, y11, x12, y12, A1, B1, C1);
// for second intersection point we must count the area from first intersection point
if ( !findNextIntersection )
{
aLoopArea = 0.0;
aStartPoint.SetCoord(x12, y12);
}
//for theFirstWireId == theSecondWireId the algorithm check current wire on selfintersection
if ( findNextIntersection && theFirstInnerSegmentId && isFirst)
jk = *theFirstInnerSegmentId;
else if (theSecondWireId == theFirstWireId)
jk = ik + 2;
else
jk = jkStart;
// Explore second wire
Standard_Boolean aFirstPass = Standard_True;
for (; jk <= jkEnd; jk++)
{
// don't check end's segment of the wire on selfrestriction
if ( theSecondWireId == theFirstWireId && isFirst && jk == ikEnd )
continue;
mu2 = getSegmentParams(theBiPoints, jk, x21, y21, x22, y22, A2, B2, C2);
gp_XY p2(x21, y21), p3(x22, y22);
//different segments may have common vertex (see OCC287 bug for example)
AB = A1*B2 - A2*B1;
//check on minimal of distance between current segment and points of another linear segments - OCC319
d = A1*x22 + B1*y22 + C1;
Standard_Real dTol = MIN_DIST*MIN_DIST;
if(theFirstWireId != theSecondWireId && // if compared wires are different &&
AB*AB > PARALL_COND*PARALL_COND*mu1*mu2 && // angle between two segments greater then PARALL_COND &&
d*d < dTol*mu1 && // distance between vertex of the segment and other one's less then MIN_DIST
(x22-x11)*(x22-x12) < 0.0 && (y22-y11)*(y22-y12) < 0.0)
{
// if we finding the second intersection we must return Standard_False for setting
// self-intersection result flag
if ( findNextIntersection )
return Standard_False;
// we can step here when finding first intersection, return self-intersection flag
return Standard_True;
}
if( aFirstPass )
aFirstTriangleArea = triangle2Area(aStartPoint, p2);
Standard_Real aTmpArea = triangle2Area(p2, p3);
//look for intersection of two linear segments
if(Abs(AB) <= RESOLUTION)
{
aLoopArea += aTmpArea;
continue; //current segments seem parallel - no intersection
}
//calculate coordinates of point of the intersection
BC = B1*C2 - B2*C1; xc = BC/AB;
CA = C1*A2 - C2*A1; yc = CA/AB;
// remember current intersection point and area of first triangle
if( findNextIntersection && ik == *theFirstOuterSegmentId && jk == *theFirstInnerSegmentId )
{
aStartPoint.SetCoord(xc, yc);
continue;
}
//check on belonging of intersection point to the both of segments
Standard_Boolean isOnLines = Standard_True;
Standard_Real dd[2][4] = { {(xc-x11), (xc-x12), (xc-x21), (xc-x22)}, //dX
{(yc-y11), (yc-y12), (yc-y21), (yc-y22)} }; //dY
for( Standard_Integer i = 0; i < 2; i++ )
{
if ( dd[i][0] * dd[i][1] > RESOLUTION || dd[i][2] * dd[i][3] > RESOLUTION )
{
isOnLines = Standard_False;
break;
}
}
// check the intersection point is on the ends of segments
if ( isOnLines )
{
for( Standard_Integer i = 0; i < 2; i++ )
{
// if it's the last segment and intersection point lies at the end
if ( ( jk == jkEnd ||
// dX && dY
// or when the start or the end point of the first segment
(Abs(dd[0][0]) < MIN_DIST && Abs(dd[1][0]) < MIN_DIST) ||
(Abs(dd[0][1]) < MIN_DIST && Abs(dd[1][1]) < MIN_DIST)) &&
// is equal to one of the end points of the second
(Abs(dd[0][i+2]) < MIN_DIST && Abs(dd[1][i+2]) < MIN_DIST))
{
// no intersection
isOnLines = Standard_False;
aLoopArea = aTmpArea = 0.0;
aFirstPass = Standard_True;
break;
}
}
}
if( isOnLines )
{
p3.SetX(xc); p3.SetY(yc);
aLoopArea += aFirstTriangleArea; // First triangle area
aLoopArea += triangle2Area(p2, p3);
aLoopArea += triangle2Area(p3, aStartPoint); // Last triangle area
if( Abs(aLoopArea)/2 > M_PI*MIN_DIST )
{
if ( findNextIntersection )
{
// intersection is found, but Standard_False returns, because area is too much
return Standard_False;
}
if ( checkWiresIntersection(theFirstWireId, theSecondWireId, &ik, ikEnd, theWireLength,
theBiPoints, Standard_True, isFirst, &jk) )
{
// small crossing is not intersection, continue cheching
aLoopArea = aTmpArea = 0.0;
aFirstPass = Standard_True;
}
else
{
// if we found only one intersection
return Standard_True;
}
}
else if ( findNextIntersection )
{
// small intersection, skip double checking
*theFirstOuterSegmentId = ik;
*theFirstInnerSegmentId = jk + 1;
return Standard_True;
}
}
if ( aFirstPass )
aFirstPass = Standard_False;
aLoopArea += aTmpArea;
}
if ( isFirst )
isFirst = Standard_False;
}
return Standard_False;
}
//=======================================================================
//function : BRepMesh_Classifier
//purpose :
//=======================================================================
BRepMesh_Classifier::BRepMesh_Classifier(const TopoDS_Face& theFace,
const Standard_Real theTolUV,
const BRepMesh_DataMapOfShapePairOfPolygon& theEdges,
const TColStd_IndexedMapOfInteger& theMap,
const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax)
: myTolUV( theTolUV ),
myFace ( theFace ),
myState( BRepMesh_NoError )
{
//-- impasse sur les surfs definies sur plus d une periode
//-- once definition
myFace.Orientation(TopAbs_FORWARD);
TColgp_SequenceOfPnt2d aWirePoints, aWire;
TColStd_SequenceOfInteger aWireLength;
TopoDS_Iterator aFaceExplorer;
for(aFaceExplorer.Initialize(myFace); aFaceExplorer.More(); aFaceExplorer.Next())
{
if(aFaceExplorer.Value().ShapeType() != TopAbs_WIRE)
continue;
// For each wire we create a data map, linking vertices (only
// the ends of edges) with their positions in the sequence of
// all 2d points from this wire.
// When we meet some vertex for the second time - the piece
// of sequence is treated for a HOLE and quits the sequence.
// Actually, we must unbind the vertices belonging to the
// loop from the map, but since they can't appear twice on the
// valid wire, leave them for a little speed up.
Standard_Integer aNbEdges = 0;
Standard_Integer aFirstIndex = 0, aLastIndex = 0;
Standard_Boolean isFalseWire = Standard_False;
TColgp_SequenceOfPnt2d aSeqPnt2d;
TColStd_DataMapOfIntegerInteger aNodeInSeq;
// Start traversing the wire
BRepTools_WireExplorer aWireExplorer;
for (aWireExplorer.Init(TopoDS::Wire( aFaceExplorer.Value() ), myFace); aWireExplorer.More(); aWireExplorer.Next())
{
TopoDS_Edge anEdge = aWireExplorer.Current();
TopAbs_Orientation anOrient = anEdge.Orientation();
if (anOrient != TopAbs_FORWARD && anOrient != TopAbs_REVERSED)
continue;
if (theEdges.IsBound(anEdge))
{
// Retrieve polygon
// Define the direction for adding points to aSeqPnt2d
Standard_Integer aIdxFirst, aIdxLast, aIdxIncr;
const BRepMesh_PairOfPolygon& aPair = theEdges.Find(anEdge);
Handle(Poly_PolygonOnTriangulation) aNOD;
if (anOrient == TopAbs_FORWARD)
{
aNOD = aPair.First();
aIdxFirst = 1;
aIdxLast = aNOD->NbNodes();
aIdxIncr = 1;
}
else
{
aNOD = aPair.Last();
aIdxFirst = aNOD->NbNodes();
aIdxLast = 1;
aIdxIncr = -1;
}
const TColStd_Array1OfInteger& anIndices = aNOD->Nodes();
// anIndexFirst and anIndexLast are the indices of first and last
// vertices of the edge in IndexedMap <Str>
const Standard_Integer anIndexFirst = theMap.FindKey( anIndices(aIdxFirst) );
const Standard_Integer anIndexLast = theMap.FindKey( anIndices(aIdxLast) );
if (anIndexLast == anIndexFirst && (aIdxLast - aIdxFirst) == aIdxIncr)
{
// case of continuous set of degenerated edges
aLastIndex = anIndexLast;
continue;
}
// If there's a gap between edges -> raise <isFalseWire> flag
if (aNbEdges)
{
if (anIndexFirst != aLastIndex)
{
isFalseWire = Standard_True;
break;
}
}
else
aFirstIndex = anIndexFirst;
aLastIndex = anIndexLast;
// Record first vertex (to detect loops)
aNodeInSeq.Bind(anIndexFirst, (aSeqPnt2d.Length() + 1));
// Add vertices in sequence
for (Standard_Integer i = aIdxFirst; i != aIdxLast; i += aIdxIncr)
{
Standard_Integer anIndex = ((i == aIdxFirst) ? anIndexFirst : theMap.FindKey( anIndices(i) ));
gp_Pnt2d aPnt( theStructure->GetNode(anIndex).Coord() );
aSeqPnt2d.Append(aPnt);
}
// Now, is there a loop?
if (aNodeInSeq.IsBound(anIndexLast))
{
// Yes, treat it separately as a hole
// 1. Divide points into main wire and a loop
const Standard_Integer aIdxWireStart = aNodeInSeq(anIndexLast);
if(aIdxWireStart < aSeqPnt2d.Length())
{
aSeqPnt2d.Split(aIdxWireStart, aWire);
// 2. Proceed the loop
//AnalizeWire(aLoop, Umin, Umax, Vmin, Vmax, aWirePoints, aWireLength, NbBiPoint);
aWireLength.Append( aWire.Length() );
aWirePoints.Append( aWire );
}
}
aNbEdges++;
}
}
if (aNbEdges)
{
// Isn't it open?
if (isFalseWire || (aFirstIndex != aLastIndex) || aSeqPnt2d.Length() > 1)
{
myState = BRepMesh_OpenWire;
return;
}
}
}
const Standard_Integer aNbWires = aWireLength.Length();
Standard_Integer aNbBiPoint = aWirePoints.Length();
BRepMesh_Array1OfBiPoint aBiPoints(0, aNbBiPoint);
BRepMesh_BiPoint *aBiPoint = &(aBiPoints.ChangeValue(1));
// Fill array of segments (bi-points)
Standard_Integer k = 1;
for (Standard_Integer i = 1; i <= aNbWires; i++)
{
Standard_Real x1 = 0., y1 = 0., x2, y2, aXstart = 0., aYstart = 0.;
const Standard_Integer aLen = aWireLength(i) + 1;
for (Standard_Integer j = 1; j <= aLen; j++)
{
// Obtain last point of the segment
if (j == aLen)
{
x2 = aXstart;
y2 = aYstart;
}
else
{
const gp_Pnt2d& aPnt = aWirePoints(k);
k++;
x2 = aPnt.X();
y2 = aPnt.Y();
}
// Build segment (bi-point)
if (j == 1)
{
aXstart = x2;
aYstart = y2;
}
else
{
Standard_Real *aCoordinates1 = ((Standard_Real*)(aBiPoint->Coordinates()));
aBiPoint++;
aCoordinates1[0] = x1;
aCoordinates1[1] = y1;
aCoordinates1[2] = x2;
aCoordinates1[3] = y2;
aCoordinates1[4] = x2 - x1;
aCoordinates1[5] = y2 - y1;
}
x1 = x2;
y1 = y2;
}
}
// Search the intersection
// Explore first wire
Standard_Integer ikEnd = 0;
for(Standard_Integer i = 1; i <= aNbWires; i++)
{
Standard_Integer ik = ikEnd + 1;
ikEnd += aWireLength(i);
// Explore second wire
for (Standard_Integer j = i; j <= aNbWires; j++)
{
if ( checkWiresIntersection(i, j, &ik, ikEnd, aWireLength, aBiPoints) )
{
myState = BRepMesh_SelfIntersectingWire;
return;
}
}
}
// Find holes
for (Standard_Integer i = aNbWires; i >= 1; i--)
{
aNbBiPoint = aWirePoints.Length() - aWireLength(i) + 1;
aWirePoints.Split(aNbBiPoint, aWire);
AnalizeWire(aWire, theUmin, theUmax, theVmin, theVmax);
}
}
//=======================================================================
//function : Perform
//purpose :
@ -591,7 +47,7 @@ TopAbs_State BRepMesh_Classifier::Perform(const gp_Pnt2d& thePoint) const
isOut = Standard_True;
}
else
isOut = myTabOrient(i)? (aCur == -1) : (aCur == 1);
isOut = myTabOrient(i) ? (aCur == -1) : (aCur == 1);
if (isOut)
return TopAbs_OUT;
@ -600,6 +56,69 @@ TopAbs_State BRepMesh_Classifier::Perform(const gp_Pnt2d& thePoint) const
return TopAbs_IN;
}
//=======================================================================
//function : RegisterWire
//purpose :
//=======================================================================
void BRepMesh_Classifier::RegisterWire(
const NCollection_Sequence<gp_Pnt2d>& theWire,
const Standard_Real theTolUV,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax)
{
const Standard_Integer aNbPnts = theWire.Length();
if (aNbPnts < 2)
return;
// Accumulate angle
TColgp_Array1OfPnt2d aPClass(1, aNbPnts);
Standard_Real anAngle = 0.0;
gp_Pnt2d p1 = theWire(1), p2 = theWire(2), p3;
aPClass(1) = p1;
aPClass(2) = p2;
const Standard_Real aAngTol = Precision::Angular();
const Standard_Real aSqConfusion =
Precision::PConfusion() * Precision::PConfusion();
for (Standard_Integer i = 1; i <= aNbPnts; i++)
{
Standard_Integer ii = i + 2;
if (ii > aNbPnts)
{
p3 = aPClass(ii - aNbPnts);
}
else
{
p3 = theWire.Value(ii);
aPClass(ii) = p3;
}
gp_Vec2d A(p1,p2), B(p2,p3);
if (A.SquareMagnitude() > aSqConfusion &&
B.SquareMagnitude() > aSqConfusion)
{
const Standard_Real aCurAngle = A.Angle(B);
const Standard_Real aCurAngleAbs = Abs(aCurAngle);
// Check if vectors are opposite
if (aCurAngleAbs > aAngTol && (M_PI - aCurAngleAbs) > aAngTol)
{
anAngle += aCurAngle;
p1 = p2;
}
}
p2 = p3;
}
// Check for zero angle - treat self intersecting wire as outer
if (Abs(anAngle) < aAngTol)
anAngle = 0.0;
myTabClass.Append( (void *)new CSLib_Class2d(aPClass,
theTolUV, theTolUV, theUmin, theVmin, theUmax, theVmax) );
myTabOrient.Append( !(anAngle < 0.0) );
}
//=======================================================================
//function : Destroy
@ -616,4 +135,7 @@ void BRepMesh_Classifier::Destroy()
myTabClass(i) = NULL;
}
}
myTabClass.Clear();
myTabOrient.Clear();
}

View File

@ -0,0 +1,79 @@
// Created on: 2014-06-03
// Created by: Oleg AGASHIN
// Copyright (c) 1997-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.
#ifndef _BRepMesh_Classifier_HeaderFile
#define _BRepMesh_Classifier_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <BRepTopAdaptor_SeqOfPtr.hxx>
#include <TColStd_SequenceOfBoolean.hxx>
#include <TopAbs_State.hxx>
#include <NCollection_Sequence.hxx>
class gp_Pnt2d;
class TColgp_SequenceOfPnt2d;
//! Auxilary class contains information about correctness of discretized
//! face and used for classification of points regarding face internals.
class BRepMesh_Classifier
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor.
Standard_EXPORT BRepMesh_Classifier();
//! Destructor.
~BRepMesh_Classifier()
{
Destroy();
}
//! Method is called on destruction.
//! Clears internal data structures.
Standard_EXPORT void Destroy();
//! Performs classification of the given point regarding to face internals.
//! \param thePoint Point in parametric space to be classified.
//! \return
Standard_EXPORT TopAbs_State Perform(const gp_Pnt2d& thePoint) const;
//! Registers wire specified by sequence of points for
//! further classification of points.
//! \param theWire Wire to be registered. Specified by sequence of points.
//! \param theTolUV Tolerance to be used for calculations in parametric space.
//! \param theUmin Lower U boundary of the face in parametric space.
//! \param theUmax Upper U boundary of the face in parametric space.
//! \param theVmin Lower V boundary of the face in parametric space.
//! \param theVmax Upper V boundary of the face in parametric space.
void RegisterWire(
const NCollection_Sequence<gp_Pnt2d>& theWire,
const Standard_Real theTolUV,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax);
private:
BRepTopAdaptor_SeqOfPtr myTabClass;
TColStd_SequenceOfBoolean myTabOrient;
};
#endif

View File

@ -1,24 +0,0 @@
// Created on: 2003-11-05
// Created by: Open CASCADE Support
// Copyright (c) 2003-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.
//=======================================================================
//function : State
//purpose :
//=======================================================================
inline BRepMesh_Status BRepMesh_Classifier::State() const
{
return myState;
}

View File

@ -16,9 +16,9 @@
#ifndef BRepMesh_ClassifierPtr_HeaderFile
#define BRepMesh_ClassifierPtr_HeaderFile
#include <BRepMesh_Classifier.hxx>
#include <NCollection_Handle.hxx>
class BRepMesh_Classifier;
typedef NCollection_Handle<BRepMesh_Classifier> BRepMesh_ClassifierPtr;
#endif

View File

@ -56,9 +56,8 @@ const Standard_Real AngDeviation1Deg = M_PI/180.;
const Standard_Real AngDeviation90Deg = 90 * AngDeviation1Deg;
const Standard_Real Angle2PI = 2 * M_PI;
const Standard_Real Precision = Precision::PConfusion();
const Standard_Real EndPrecision = 1 - Precision;
const Standard_Real Precision2 = Precision * Precision;
const Standard_Real Precision = Precision::PConfusion();
const Standard_Real Precision2 = Precision * Precision;
const gp_XY SortingDirection(M_SQRT1_2, M_SQRT1_2);
//=======================================================================
@ -1060,10 +1059,11 @@ Standard_Boolean BRepMesh_Delaun::checkIntersection(
continue;
gp_Pnt2d anIntPnt;
IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
isConsiderEndPointTouch, isConsiderPointOnEdge, anIntPnt );
BRepMesh_WireInterferenceChecker::IntFlag aIntFlag =
intSegSeg( theLink, aPolyLink, isConsiderEndPointTouch,
isConsiderPointOnEdge, anIntPnt );
if ( aIntFlag != BRepMesh_Delaun::NoIntersection )
if ( aIntFlag != BRepMesh_WireInterferenceChecker::NoIntersection )
return Standard_False;
}
}
@ -1535,16 +1535,16 @@ void BRepMesh_Delaun::meshPolygon( TColStd_SequenceOfInteger& thePoly
};
gp_Pnt2d anIntPnt;
IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
Standard_False, Standard_True, anIntPnt );
BRepMesh_WireInterferenceChecker::IntFlag aIntFlag = intSegSeg( *aCurEdge,
*aNextEdge, Standard_False, Standard_True, anIntPnt );
if ( aIntFlag == BRepMesh_Delaun::NoIntersection )
if ( aIntFlag == BRepMesh_WireInterferenceChecker::NoIntersection )
continue;
Standard_Boolean isRemoveFromFirst = Standard_False;
Standard_Boolean isAddReplacingEdge = Standard_True;
Standard_Integer aIndexToRemoveTo = aNextPolyIt;
if ( aIntFlag == BRepMesh_Delaun::Cross )
if ( aIntFlag == BRepMesh_WireInterferenceChecker::Cross )
{
Standard_Real aLoopArea = polyArea( thePolygon, aPolyIt + 1, aNextPolyIt );
gp_Vec2d aVec1( anIntPnt, aCurPnts [1] );
@ -1586,7 +1586,7 @@ void BRepMesh_Delaun::meshPolygon( TColStd_SequenceOfInteger& thePoly
theSkipped->Add( Abs( thePolygon( aSkippedLinkIt ) ) );
}
}
else if ( aIntFlag == BRepMesh_Delaun::PointOnEdge )
else if ( aIntFlag == BRepMesh_WireInterferenceChecker::PointOnSegment )
{
// Indentify chopping link
Standard_Boolean isFirstChopping = Standard_False;
@ -1657,7 +1657,7 @@ void BRepMesh_Delaun::meshPolygon( TColStd_SequenceOfInteger& thePoly
thePolygon, thePolyBoxes );
}
}
else if ( aIntFlag == BRepMesh_Delaun::Glued )
else if ( aIntFlag == BRepMesh_WireInterferenceChecker::Glued )
{
if ( aCurNodes[1] == aNextNodes[0] )
{
@ -1666,7 +1666,7 @@ void BRepMesh_Delaun::meshPolygon( TColStd_SequenceOfInteger& thePoly
}
// TODO: Non-adjacent glued links within the polygon
}
else if ( aIntFlag == BRepMesh_Delaun::Same )
else if ( aIntFlag == BRepMesh_WireInterferenceChecker::Same )
{
processLoop( aPolyIt, aNextPolyIt, thePolygon, thePolyBoxes );
@ -1843,10 +1843,11 @@ void BRepMesh_Delaun::meshSimplePolygon( TColStd_SequenceOfInteger& thePolyg
// intersection is possible...
gp_Pnt2d anIntPnt;
IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
Standard_False, Standard_False, anIntPnt );
BRepMesh_WireInterferenceChecker::IntFlag aIntFlag =
intSegSeg( aCheckLink, aPolyLink, Standard_False,
Standard_False, anIntPnt );
if( aIntFlag != BRepMesh_Delaun::NoIntersection )
if( aIntFlag != BRepMesh_WireInterferenceChecker::NoIntersection )
{
isIntersect = Standard_True;
break;
@ -2274,54 +2275,16 @@ Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId
( aDistance[0] <= 0. && aDistance[1] <= 0. && aDistance[2] <= 0. ) ) );
}
//=============================================================================
//function : classifyPoint
//purpose : Classifies the point in case of coincidence of two vectors.
// Returns zero value if point is out of segment and non zero
// value if point is between the first and the second point of segment.
// thePoint1 - the start point of a segment (base point)
// thePoint2 - the end point of a segment
// thePointToCheck - the point to classify
//=============================================================================
Standard_Integer BRepMesh_Delaun::classifyPoint( const gp_XY& thePoint1,
const gp_XY& thePoint2,
const gp_XY& thePointToCheck ) const
{
gp_XY aP1 = thePoint2 - thePoint1;
gp_XY aP2 = thePointToCheck - thePoint1;
Standard_Real aDist = Abs( aP1 ^ aP2 );
if ( aDist >= Precision )
{
aDist = ( aDist * aDist ) / aP1.SquareModulus();
if ( aDist >= Precision2 )
return 0; //out
}
gp_XY aMult = aP1.Multiplied( aP2 );
if ( aMult.X() < 0.0 || aMult.Y() < 0.0 )
return 0; //out
if ( aP1.SquareModulus() < aP2.SquareModulus() )
return 0; //out
if ( thePointToCheck.IsEqual( thePoint1, Precision ) ||
thePointToCheck.IsEqual( thePoint2, Precision ) )
return -1; //coinsides with an end point
return 1;
}
//=============================================================================
//function : intSegSeg
//purpose : Checks intersection between the two segments.
//=============================================================================
BRepMesh_Delaun::IntFlag BRepMesh_Delaun::intSegSeg( const BRepMesh_Edge& theEdg1,
const BRepMesh_Edge& theEdg2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
gp_Pnt2d& theIntPnt) const
BRepMesh_WireInterferenceChecker::IntFlag BRepMesh_Delaun::intSegSeg(
const BRepMesh_Edge& theEdg1,
const BRepMesh_Edge& theEdg2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
gp_Pnt2d& theIntPnt) const
{
gp_XY p1, p2, p3, p4;
p1 = GetVertex( theEdg1.FirstNode() ).Coord();
@ -2329,113 +2292,8 @@ BRepMesh_Delaun::IntFlag BRepMesh_Delaun::intSegSeg( const BRepMesh_Edge& theE
p3 = GetVertex( theEdg2.FirstNode() ).Coord();
p4 = GetVertex( theEdg2.LastNode() ).Coord();
Standard_Integer aPoint1 = classifyPoint( p1, p2, p3 );
Standard_Integer aPoint2 = classifyPoint( p1, p2, p4 );
Standard_Integer aPoint3 = classifyPoint( p3, p4, p1 );
Standard_Integer aPoint4 = classifyPoint( p3, p4, p2 );
// Consider case when edges have shared vertex
if ( isConsiderEndPointTouch )
{
if ( aPoint1 < 0 || aPoint2 < 0 )
return BRepMesh_Delaun::EndPointTouch;
}
Standard_Integer aPosHash =
aPoint1 + aPoint2 + aPoint3 + aPoint4;
/*=========================================*/
/* 1) hash code == 1:
0+
/
0 1/ 0
+======+==========+
2) hash code == 2:
0 1 1 0
a) +----+========+---+
0 1 1 0
b) +-------+===+=====+
*/
/*=========================================*/
if ( aPosHash == 1 )
{
return isConsiderPointOnEdge ?
BRepMesh_Delaun::PointOnEdge :
BRepMesh_Delaun::NoIntersection;
}
else if ( aPosHash == 2 )
return BRepMesh_Delaun::Glued;
gp_XY aVec1 = p2 - p1;
gp_XY aVec2 = p4 - p3;
gp_XY aVecStartPoints = p3 - p1;
Standard_Real aCrossD1D2 = aVec1 ^ aVec2;
Standard_Real aCrossD1D3 = aVecStartPoints ^ aVec2;
// is edgegs codirectional
if ( Abs( aCrossD1D2 ) < Precision )
{
// just a parallel case?
if( Abs( aCrossD1D3 ) < Precision )
{
/*=========================================*/
/* Here the following cases are possible:
1) hash code == -4:
-1 -1
+=================+
-1 -1
2) hash code == -2:
0 -1 0
+--------+========+
-1
3) hash code == -1:
0 1 -1
+--------+========+
-1
4) hash code == 0:
0 0 0 0
+------+ +=======+
0 0 0 0
*/
/*=========================================*/
if ( aPosHash < -2 )
return BRepMesh_Delaun::Same;
else if ( aPosHash == -1 )
return BRepMesh_Delaun::Glued;
return BRepMesh_Delaun::NoIntersection;
}
else
return BRepMesh_Delaun::NoIntersection;
}
Standard_Real aPar = aCrossD1D3 / aCrossD1D2;
// inrersects out of first segment range
if( aPar < Precision || aPar > EndPrecision )
return BRepMesh_Delaun::NoIntersection;
Standard_Real aCrossD2D3 = aVecStartPoints.Reversed() ^ aVec1;
aPar = aCrossD2D3 / -aCrossD1D2;
// inrersects out of second segment range
if( aPar < Precision || aPar > EndPrecision )
return BRepMesh_Delaun::NoIntersection;
theIntPnt = p3 + aPar * aVec2;
return BRepMesh_Delaun::Cross;
return BRepMesh_WireInterferenceChecker::Intersect(p1, p2, p3, p4,
isConsiderEndPointTouch, isConsiderPointOnEdge, theIntPnt);
}
//=============================================================================

View File

@ -25,6 +25,7 @@
#include <BRepMesh_MapOfIntegerInteger.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <NCollection_Sequence.hxx>
#include <BRepMesh_WireInterferenceChecker.hxx>
class Bnd_B2d;
class Bnd_Box2d;
@ -119,16 +120,6 @@ public:
private:
enum IntFlag
{
NoIntersection,
Cross,
EndPointTouch,
PointOnEdge,
Glued,
Same
};
enum ReplaceFlag
{
Replace,
@ -305,21 +296,13 @@ private:
Standard_Real theSqModulus[3],
Standard_Integer& theEdgeOn) const;
//! Classifies the point in case of coincidence of two vectors.
//! @param thePoint1 the start point of a segment (base point)
//! @param thePoint2 the end point of a segment
//! @param thePointToCheck the point to classify
//! @returns zero value if point is out of segment and non zero value if point is between the first and the second point of segment
Standard_Integer classifyPoint (const gp_XY& thePoint1,
const gp_XY& thePoint2,
const gp_XY& thePointToCheck) const;
//! Checks intersection between the two segments.
IntFlag intSegSeg (const BRepMesh_Edge& theEdge1,
const BRepMesh_Edge& theEdge2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
gp_Pnt2d& theIntPnt) const;
BRepMesh_WireInterferenceChecker::IntFlag intSegSeg (
const BRepMesh_Edge& theEdge1,
const BRepMesh_Edge& theEdge2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
gp_Pnt2d& theIntPnt) const;
//! Returns area of the loop of the given polygon defined by indices of its start and end links.
Standard_Real polyArea (const TColStd_SequenceOfInteger& thePolygon,

View File

@ -67,24 +67,26 @@ uses Boolean from Standard,
is
Create (defle : Real from Standard;
angle : Real from Standard;
B : Box from Bnd;
withShare : Boolean from Standard=Standard_True;
inshape : Boolean from Standard=Standard_False;
relative : Boolean from Standard=Standard_False;
shapetrigu: Boolean from Standard=Standard_False)
Create (defle : Real from Standard;
angle : Real from Standard;
B : Box from Bnd;
withShare : Boolean from Standard=Standard_True;
inshape : Boolean from Standard=Standard_False;
relative : Boolean from Standard=Standard_False;
shapetrigu : Boolean from Standard=Standard_False;
isInParallel: Boolean from Standard=Standard_False)
returns FastDiscret from BRepMesh;
Create (defle : Real from Standard;
shape : Shape from TopoDS;
B : Box from Bnd;
angle : Real from Standard;
withShare : Boolean from Standard=Standard_True;
inshape : Boolean from Standard=Standard_False;
relative : Boolean from Standard=Standard_False;
shapetrigu: Boolean from Standard=Standard_False)
Create (defle : Real from Standard;
shape : Shape from TopoDS;
B : Box from Bnd;
angle : Real from Standard;
withShare : Boolean from Standard=Standard_True;
inshape : Boolean from Standard=Standard_False;
relative : Boolean from Standard=Standard_False;
shapetrigu : Boolean from Standard=Standard_False;
isInParallel: Boolean from Standard=Standard_False)
---Purpose: if the boolean <relative> is True, the
-- deflection used for the polygonalisation of
-- each edge will be <defle> * Size of Edge.

View File

@ -20,6 +20,8 @@
#include <BRepMesh_FaceAttribute.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_ClassifierPtr.hxx>
#include <BRepMesh_Classifier.hxx>
#include <BRepMesh_WireChecker.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <BRepMesh_PairOfPolygon.hxx>
#include <BRepMesh_DataMapOfShapePairOfPolygon.hxx>
@ -126,11 +128,12 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real theDefle,
const Standard_Boolean theWithShare,
const Standard_Boolean theInshape,
const Standard_Boolean theRelative,
const Standard_Boolean theShapetrigu) :
myAngle (theAngl),
const Standard_Boolean theShapetrigu,
const Standard_Boolean isInParallel)
: myAngle (theAngl),
myDeflection (theDefle),
myWithShare (theWithShare),
myInParallel (Standard_False),
myInParallel (isInParallel),
myNbLocat (0),
myRelative (theRelative),
myShapetrigu (theShapetrigu),
@ -153,11 +156,12 @@ BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real theDefle,
const Standard_Boolean theWithShare,
const Standard_Boolean theInshape,
const Standard_Boolean theRelative,
const Standard_Boolean theShapetrigu):
myAngle (theAngl),
const Standard_Boolean theShapetrigu,
const Standard_Boolean isInParallel)
: myAngle (theAngl),
myDeflection (theDefle),
myWithShare (theWithShare),
myInParallel (Standard_False),
myInParallel (isInParallel),
myNbLocat (0),
myRelative (theRelative),
myShapetrigu (theShapetrigu),
@ -493,59 +497,59 @@ void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface,
Standard_Integer nbVertices = myVemap.Extent();
const Standard_Real tolclass = Precision::PConfusion(); //0.03*Max(myumax-myumin, myvmax-myvmin);
BRepMesh_ClassifierPtr classifier (
new BRepMesh_Classifier(face, tolclass, myInternaledges, myVemap,
myStructure, myumin, myumax, myvmin, myvmax) );
myFacestate = classifier->State();
if (myFacestate == BRepMesh_SelfIntersectingWire)
BRepMesh_ClassifierPtr classifier = new BRepMesh_Classifier;
{
Standard_Integer nbmaill = 0;
Standard_Real eps = Precision::Confusion();
while (nbmaill < 5 && myFacestate != BRepMesh_ReMesh)
BRepMesh_WireChecker aDFaceChecker(face,
tolclass, myInternaledges, myVemap, myStructure,
myumin, myumax, myvmin, myvmax, myInParallel);
aDFaceChecker.ReCompute(classifier);
myFacestate = aDFaceChecker.Status();
if (myFacestate == BRepMesh_SelfIntersectingWire)
{
nbmaill++;
//clear the structure of links
myStructure.Nullify();
myStructure = new BRepMesh_DataStructureOfDelaun(anAlloc);
myVemap.Clear();
myLocation2d.Clear();
myInternaledges.Clear();
Standard_Integer j1;
for(j1 = 1; j1 <= aShSeq.Length(); j1++)
Standard_Integer nbmaill = 0;
Standard_Real eps = Precision::Confusion();
while (nbmaill < 5 && myFacestate != BRepMesh_ReMesh)
{
const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
if (myEdges.IsBound(edge))
nbmaill++;
//clear the structure of links
myStructure.Nullify();
myStructure = new BRepMesh_DataStructureOfDelaun(anAlloc);
myVemap.Clear();
myLocation2d.Clear();
myInternaledges.Clear();
Standard_Integer j1;
for(j1 = 1; j1 <= aShSeq.Length(); j1++)
{
myEdges.UnBind(edge);
myInternaledges.UnBind(edge);
const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
if (myEdges.IsBound(edge))
{
myEdges.UnBind(edge);
myInternaledges.UnBind(edge);
}
}
for( j1 = 1; j1 <= aShSeq.Length(); j1++)
{
const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
defedge = myMapdefle(edge) / 3.;
defedge = Max(defedge, eps);
myMapdefle.Bind(edge, defedge);
const Handle(Geom2d_Curve)& C = aCSeq.Value(j1);
Add(edge, face, gFace, C, theAncestors, defedge, aFSeq.Value(j1), aLSeq.Value(j1));
}
}
for( j1 = 1; j1 <= aShSeq.Length(); j1++)
{
const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
defedge = myMapdefle(edge) / 3.;
defedge = Max(defedge, eps);
myMapdefle.Bind(edge, defedge);
const Handle(Geom2d_Curve)& C = aCSeq.Value(j1);
Add(edge, face, gFace, C, theAncestors, defedge, aFSeq.Value(j1), aLSeq.Value(j1));
}
classifier.Nullify();
classifier = new BRepMesh_Classifier(face, tolclass, myInternaledges, myVemap,
myStructure, myumin, myumax, myvmin, myvmax);
if (classifier->State() == BRepMesh_NoError)
{
myFacestate = BRepMesh_ReMesh;
aDFaceChecker.ReCompute(classifier);
if (aDFaceChecker.Status() == BRepMesh_NoError)
{
myFacestate = BRepMesh_ReMesh;
}
nbVertices = myVemap.Extent();
}
nbVertices = myVemap.Extent();
}
}

View File

@ -25,6 +25,7 @@
#include <BRepMesh_DataMapIteratorOfDataMapOfShapePairOfPolygon.hxx>
#include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
#include <BRepMesh_ClassifierPtr.hxx>
#include <BRepMesh_Classifier.hxx>
#include <BRep_Builder.hxx>
#include <BRep_PointRepresentation.hxx>
#include <BRep_TVertex.hxx>

View File

@ -109,10 +109,10 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
//function : BRepMesh_IncrementalMesh
//purpose :
//=======================================================================
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (const TopoDS_Shape& theShape,
const Standard_Real theDeflection,
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (const TopoDS_Shape& theShape,
const Standard_Real theDeflection,
const Standard_Boolean theRelative,
const Standard_Real theAngle,
const Standard_Real theAngle,
const Standard_Boolean theInParallel)
: myRelative (theRelative),
myInParallel (theInParallel)
@ -215,12 +215,13 @@ void BRepMesh_IncrementalMesh::Perform()
}
//
myMesh = new BRepMesh_FastDiscret(myDeflection,
myAngle,
aBox,
Standard_True,
Standard_True,
myRelative,
Standard_True);
myAngle,
aBox,
Standard_True,
Standard_True,
myRelative,
Standard_True,
myInParallel);
//
Update(myShape);
}
@ -519,7 +520,7 @@ void BRepMesh_IncrementalMesh::Update(const TopoDS_Face& F)
TopoDS_Face F2 = TopoDS::Face(it.Value());
if (!MShape.Contains(F2)) {
MShape.Add(F2);
T = BRep_Tool::Triangulation(F2, l);
T = BRep_Tool::Triangulation(F2, l);
if (!T.IsNull()) {
#ifdef DEB_MESH
cout <<"triangulation a refaire" <<endl;

View File

@ -0,0 +1,423 @@
// Created on: 2014-06-03
// Created by: Oleg AGASHIN
// Copyright (c) 1997-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 <BRepMesh_WireChecker.hxx>
#include <Precision.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <gp_Pnt2d.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <TopAbs_Orientation.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Iterator.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <BRepMesh_PairOfPolygon.hxx>
#include <BRepMesh_DataMapOfShapePairOfPolygon.hxx>
#include <TColStd_SequenceOfInteger.hxx>
#include <TColStd_IndexedMapOfInteger.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_Classifier.hxx>
#include <BRepMesh_WireInterferenceChecker.hxx>
#ifdef HAVE_TBB
// paralleling using Intel TBB
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#endif
//=======================================================================
//function : Selector::Constructor
//purpose :
//=======================================================================
BRepMesh_WireChecker::BndBox2dTreeSelector::BndBox2dTreeSelector(
const Standard_Integer theReservedSize)
: mySkippedIndex(-1),
myIndices(0, theReservedSize - 1),
myIndicesNb(0)
{
}
//=======================================================================
//function : Reject
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Reject(
const Bnd_Box2d& theBox2D) const
{
return myBox2D.IsOut(theBox2D);
}
//=======================================================================
//function : Accept
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Accept(
const Standard_Integer& theIndex)
{
if (theIndex <= mySkippedIndex)
return Standard_False;
myIndices(myIndicesNb++) = theIndex;
return Standard_True;
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void BRepMesh_WireChecker::BndBox2dTreeSelector::Clear()
{
mySkippedIndex = -1;
myIndicesNb = 0;
}
//=======================================================================
//function : SetBox
//purpose :
//=======================================================================
void BRepMesh_WireChecker::BndBox2dTreeSelector::SetBox(
const Bnd_Box2d& theBox2D)
{
myBox2D = theBox2D;
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void BRepMesh_WireChecker::BndBox2dTreeSelector::SetSkippedIndex(
const Standard_Integer theIndex)
{
mySkippedIndex = theIndex;
}
//=======================================================================
//function : Indices
//purpose :
//=======================================================================
const BRepMesh_WireChecker::ArrayOfInteger&
BRepMesh_WireChecker::BndBox2dTreeSelector::Indices() const
{
return myIndices;
}
//=======================================================================
//function : IndicesNb
//purpose :
//=======================================================================
Standard_Integer BRepMesh_WireChecker::BndBox2dTreeSelector::IndicesNb() const
{
return myIndicesNb;
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_WireChecker::BRepMesh_WireChecker(
const TopoDS_Face& theFace,
const Standard_Real theTolUV,
const BRepMesh_DataMapOfShapePairOfPolygon& theEdges,
const TColStd_IndexedMapOfInteger& theVertexMap,
const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax,
const Standard_Boolean isInParallel)
: myTolUV(theTolUV),
myEdges(theEdges),
myVertexMap(theVertexMap),
myStructure(theStructure),
myUmin(theUmin),
myUmax(theUmax),
myVmin(theVmin),
myVmax(theVmax),
myStatus(BRepMesh_NoError),
myIsInParallel(isInParallel)
{
TopoDS_Face aFace = theFace;
aFace.Orientation(TopAbs_FORWARD);
TopoDS_Iterator aFaceExplorer(aFace);
for (; aFaceExplorer.More(); aFaceExplorer.Next())
{
const TopoDS_Shape& aWire = aFaceExplorer.Value();
if (aWire.ShapeType() != TopAbs_WIRE)
continue;
myWiresEdges.push_back(ListOfEdges());
ListOfEdges& aEdges = myWiresEdges.back();
// Start traversing the wires
BRepTools_WireExplorer aWireExplorer(TopoDS::Wire(aWire), aFace);
for (; aWireExplorer.More(); aWireExplorer.Next())
{
const TopoDS_Edge& aEdge = aWireExplorer.Current();
TopAbs_Orientation aOrient = aEdge.Orientation();
if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED)
continue;
aEdges.Append(aEdge);
}
if (aEdges.IsEmpty())
myWiresEdges.pop_back();
}
}
//=======================================================================
//function : ReCompute
//purpose :
//=======================================================================
void BRepMesh_WireChecker::ReCompute(BRepMesh_ClassifierPtr& theClassifier)
{
if (theClassifier.IsNull())
return;
theClassifier->Destroy();
myStatus = BRepMesh_NoError;
SeqOfDWires aDWires;
if (!collectDiscretizedWires(aDWires))
return;
const Standard_Integer aNbWires = aDWires.size();
std::vector<SegmentsTree> aWiresBiPoints(aNbWires);
fillSegmentsTree(aDWires, aWiresBiPoints);
#ifdef HAVE_TBB
Standard_Mutex aWireMutex;
BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints,
&myStatus, &aWireMutex);
if (myIsInParallel && aNbWires > 1)
{
// check wires in parallel threads using TBB
tbb::parallel_for(tbb::blocked_range<Standard_Integer>(0, aNbWires),
aIntChecker);
}
else
{
#else
BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus);
#endif
for (Standard_Integer i = 0; i < aNbWires; ++i)
aIntChecker(i);
#ifdef HAVE_TBB
}
#endif
if (myStatus == BRepMesh_SelfIntersectingWire)
return;
// Find holes
SeqOfDWires::iterator aDWiresIt = aDWires.begin();
for (; aDWiresIt != aDWires.end(); ++aDWiresIt)
{
const SeqOfPnt2d& aDWire = *aDWiresIt;
theClassifier->RegisterWire(aDWire, myTolUV, myUmin, myUmax, myVmin, myVmax);
}
}
//=======================================================================
//function : collectDiscretizedWires
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires(
SeqOfDWires& theDWires)
{
// TODO: Collect disretized wires in parallel
SeqOfWireEdges::iterator aWireIt = myWiresEdges.begin();
for(; aWireIt != myWiresEdges.end(); ++aWireIt)
{
const ListOfEdges& aEdges = *aWireIt;
// For each wire we create a data map, linking vertices (only
// the ends of edges) with their positions in the sequence of
// all 2d points from this wire.
// When we meet some vertex for the second time - the piece
// of sequence is treated for a HOLE and quits the sequence.
// Actually, we must unbind the vertices belonging to the
// loop from the map, but since they can't appear twice on the
// valid wire, leave them for a little speed up.
SeqOfPnt2d aSeqPnt2d;
DataMapIntInt aNodeInSeq;
Standard_Integer aFirstIndex = 0, aLastIndex = 0;
// Start traversing the wire
ListOfEdges::Iterator aEdgeIt(aEdges);
for (; aEdgeIt.More(); aEdgeIt.Next())
{
const TopoDS_Edge& aEdge = aEdgeIt.Value();
TopAbs_Orientation aOrient = aEdge.Orientation();
if (!myEdges.IsBound(aEdge))
continue;
// Retrieve polygon
// Define the direction for adding points to aSeqPnt2d
Standard_Integer aStartId, aEndId, aIncrement;
const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge);
Handle(Poly_PolygonOnTriangulation) aNOD;
if (aOrient == TopAbs_FORWARD)
{
aNOD = aPair.First();
aStartId = 1;
aEndId = aNOD->NbNodes();
aIncrement = 1;
}
else
{
aNOD = aPair.Last();
aStartId = aNOD->NbNodes();
aEndId = 1;
aIncrement = -1;
}
const TColStd_Array1OfInteger& aIndices = aNOD->Nodes();
const Standard_Integer aFirstVertexId = myVertexMap.FindKey(aIndices(aStartId));
const Standard_Integer aLastVertexId = myVertexMap.FindKey(aIndices(aEndId) );
if (aFirstVertexId == aLastVertexId && (aEndId - aStartId) == aIncrement)
{
// case of continuous set of degenerated edges
aLastIndex = aLastVertexId;
continue;
}
if (aFirstIndex != 0)
{
if (aFirstVertexId != aLastIndex)
{
// there's a gap between edges
myStatus = BRepMesh_OpenWire;
return Standard_False;
}
}
else
aFirstIndex = aFirstVertexId;
aLastIndex = aLastVertexId;
// Record first vertex (to detect loops)
aNodeInSeq.Bind(aFirstVertexId, (aSeqPnt2d.Length() + 1));
// Add vertices in sequence
for (Standard_Integer i = aStartId; i != aEndId; i += aIncrement)
{
Standard_Integer aIndex = ((i == aStartId) ?
aFirstVertexId :
myVertexMap.FindKey(aIndices(i)));
aSeqPnt2d.Append(gp_Pnt2d(myStructure->GetNode(aIndex).Coord()));
}
// Now, is there a loop?
if (aNodeInSeq.IsBound(aLastVertexId))
{
// Yes, treat it separately as a hole
// Divide points into main wire and a loop
const Standard_Integer aIdxWireStart = aNodeInSeq(aLastVertexId);
if(aIdxWireStart < aSeqPnt2d.Length())
{
theDWires.push_back(SeqOfPnt2d());
SeqOfPnt2d& aWire = theDWires.back();
aSeqPnt2d.Split(aIdxWireStart, aWire);
}
}
}
if (aFirstIndex == 0)
continue;
// Isn't wire open?
if (aFirstIndex != aLastIndex || aSeqPnt2d.Length() > 1)
{
myStatus = BRepMesh_OpenWire;
return Standard_False;
}
}
return Standard_True;
}
//=======================================================================
//function : fillSegmentsTree
//purpose :
//=======================================================================
void BRepMesh_WireChecker::fillSegmentsTree(
const SeqOfDWires& theDWires,
std::vector<SegmentsTree>& theWiresSegmentsTree)
{
const Standard_Integer aNbWires = theDWires.size();
for (Standard_Integer aWireIt = 0; aWireIt < aNbWires; ++aWireIt)
{
const SeqOfPnt2d& aWire = theDWires[aWireIt];
const Standard_Integer aWireLen = aWire.Size();
HArrayOfSegments aWireSegments = new ArrayOfSegments(aWireLen);
HBndBox2dTree aBndBoxTree = new BndBox2dTree;
BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree);
Standard_Real x1 = 0., y1 = 0., aXstart = 0., aYstart = 0.;
for (Standard_Integer aPntIt = 0; aPntIt <= aWireLen; ++aPntIt)
{
Standard_Real x2, y2;
// Obtain last point of the segment
if (aPntIt == aWireLen)
{
x2 = aXstart;
y2 = aYstart;
}
else
{
const gp_Pnt2d& aPnt = aWire(aPntIt + 1);
x2 = aPnt.X();
y2 = aPnt.Y();
}
// Build segment (bi-point)
if (aPntIt == 0)
{
aXstart = x2;
aYstart = y2;
}
else
{
gp_Pnt2d aStartPnt(x1, y1);
gp_Pnt2d aEndPnt(x2, y2);
const Standard_Integer aPointId = aPntIt - 1;
Segment& aSegment = aWireSegments->at(aPointId);
aSegment.StartPnt = aStartPnt.XY();
aSegment.EndPnt = aEndPnt.XY();
Bnd_Box2d aBox;
aBox.Add(aStartPnt);
aBox.Add( aEndPnt);
aBndBoxTreeFiller.Add(aPointId, aBox);
}
x1 = x2;
y1 = y2;
}
aBndBoxTreeFiller.Fill();
SegmentsTree& aSegmentsTree = theWiresSegmentsTree[aWireIt];
aSegmentsTree.first = aWireSegments;
aSegmentsTree.second = aBndBoxTree;
}
}

View File

@ -0,0 +1,167 @@
// Created on: 2014-06-03
// Created by: Oleg AGASHIN
// Copyright (c) 1997-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.
#ifndef _BRepMesh_WireChecker_HeaderFile
#define _BRepMesh_WireChecker_HeaderFile
#include <Standard.hxx>
#include <TopoDS_Face.hxx>
#include <BRepMesh_Status.hxx>
#include <Handle_BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_ClassifierPtr.hxx>
#include <NCollection_Sequence.hxx>
#include <NCollection_List.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_EBTree.hxx>
#include <NCollection_UBTreeFiller.hxx>
#include <NCollection_Handle.hxx>
#include <NCollection_Array1.hxx>
#include <TopoDS_Edge.hxx>
#include <Bnd_Box2d.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_XY.hxx>
#include <vector>
class BRepMesh_DataMapOfShapePairOfPolygon;
class TColStd_IndexedMapOfInteger;
class BRepMesh_DataStructureOfDelaun;
//! Auxilary class intended to check correctness of discretized face.
//! In particular, checks boundaries of discretized face for self
//! intersections and gaps.
class BRepMesh_WireChecker
{
public:
//! Structure keeping parameters of segment.
struct Segment
{
gp_XY StartPnt;
gp_XY EndPnt;
};
typedef NCollection_EBTree<Standard_Integer, Bnd_Box2d> BndBox2dTree;
typedef NCollection_UBTreeFiller<Standard_Integer, Bnd_Box2d> BndBox2dTreeFiller;
typedef NCollection_Array1<Standard_Integer> ArrayOfInteger;
typedef std::vector<Segment> ArrayOfSegments;
typedef NCollection_Handle<ArrayOfSegments> HArrayOfSegments;
typedef NCollection_Handle<BndBox2dTree> HBndBox2dTree;
typedef std::pair<HArrayOfSegments, HBndBox2dTree> SegmentsTree;
//! Selector.
//! Used to identify segments with overlapped bounding boxes.
//! Note that instance of selector can be used only once due to
//! unextentable array of indices.
class BndBox2dTreeSelector : public BndBox2dTree::Selector
{
public:
Standard_EXPORT BndBox2dTreeSelector(const Standard_Integer theReservedSize);
Standard_EXPORT virtual Standard_Boolean Reject(const Bnd_Box2d& theBox2D) const;
Standard_EXPORT virtual Standard_Boolean Accept(const Standard_Integer& theIndex);
Standard_EXPORT void Clear();
Standard_EXPORT void SetBox(const Bnd_Box2d& theBox2D);
Standard_EXPORT void SetSkippedIndex(const Standard_Integer theIndex);
Standard_EXPORT const ArrayOfInteger& Indices() const;
Standard_EXPORT Standard_Integer IndicesNb() const;
protected:
Bnd_Box2d myBox2D;
Standard_Integer mySkippedIndex;
ArrayOfInteger myIndices;
Standard_Integer myIndicesNb;
};
private:
typedef NCollection_List<TopoDS_Edge> ListOfEdges;
typedef std::vector<ListOfEdges> SeqOfWireEdges;
typedef NCollection_Sequence<gp_Pnt2d> SeqOfPnt2d;
typedef std::vector<SeqOfPnt2d> SeqOfDWires;
typedef NCollection_DataMap<Standard_Integer, Standard_Integer> DataMapIntInt;
typedef std::pair<Standard_Integer, gp_XY> PairIntPnt;
public:
//! Constructor.
//! \param theFace Face to be checked.
//! \param theTolUV Tolerance to be used for calculations in parametric space.
//! \param theEdges Map of edges with associated polygon on triangulation.
//! \param theVertexMap Map of face vertices.
//! \param theStructure Discretized representation of face in parametric space.
//! \param theUmin Lower U boundary of the face in parametric space.
//! \param theUmax Upper U boundary of the face in parametric space.
//! \param theVmin Lower V boundary of the face in parametric space.
//! \param theVmax Upper V boundary of the face in parametric space.
Standard_EXPORT BRepMesh_WireChecker(
const TopoDS_Face& theFace,
const Standard_Real theTolUV,
const BRepMesh_DataMapOfShapePairOfPolygon& theEdges,
const TColStd_IndexedMapOfInteger& theVertexMap,
const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax,
const Standard_Boolean isInParallel);
//! Recompute data using parameters passed in constructor.
//! \param[out] theClassifier Classifier to be updated using calculated data.
Standard_EXPORT void ReCompute(BRepMesh_ClassifierPtr& theClassifier);
//! Returns status of the check.
inline BRepMesh_Status Status() const
{
return myStatus;
}
private:
//! Collects disñrete wires.
//! \param[out] theDWires sequence of discretized wires to be filled.
//! \return TRUE on success, FALSE in case of open wire.
Standard_Boolean collectDiscretizedWires(SeqOfDWires& theDWires);
//! Fills array of BiPoints for corresponding wire.
//! \param theDWires Sequence of wires to be processed.
//! \param theWiresSegmentsTree Array of segments with corresponding
//! bounding boxes trees to be filled.
void fillSegmentsTree(
const SeqOfDWires& theDWires,
std::vector<SegmentsTree>& theWiresSegmentsTree);
//! Assignment operator.
void operator =(BRepMesh_WireChecker& /*theOther*/)
{
}
private:
const Standard_Real myTolUV;
const BRepMesh_DataMapOfShapePairOfPolygon& myEdges;
const TColStd_IndexedMapOfInteger& myVertexMap;
const Handle(BRepMesh_DataStructureOfDelaun)& myStructure;
const Standard_Real myUmin;
const Standard_Real myUmax;
const Standard_Real myVmin;
const Standard_Real myVmax;
BRepMesh_Status myStatus;
SeqOfWireEdges myWiresEdges;
Standard_Boolean myIsInParallel;
};
#endif

View File

@ -0,0 +1,345 @@
// Created on: 2014-06-18
// Created by: Oleg AGASHIN
// Copyright (c) 2011-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 <BRepMesh_WireInterferenceChecker.hxx>
#include <Precision.hxx>
// TODO: remove this variable after implementation of LoopChecker2d.
static const Standard_Real MIN_LOOP_S = 2 * M_PI * 2.E-5;
#ifdef HAVE_TBB
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
const std::vector<BRepMesh_WireChecker::SegmentsTree>& theWires,
BRepMesh_Status* theStatus,
Standard_Mutex* theMutex)
: myWires(&theWires.front()),
myWiresNb(theWires.size()),
myStatus(theStatus),
myMutex(theMutex)
{
}
//=======================================================================
//function : Checker's body
//purpose :
//=======================================================================
void BRepMesh_WireInterferenceChecker::operator ()(
const tbb::blocked_range<Standard_Integer>& theWireRange) const
{
for (Standard_Integer i = theWireRange.begin(); i != theWireRange.end(); ++i)
this->operator ()(i);
}
#else
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
const std::vector<BRepMesh_WireChecker::SegmentsTree>& theWires,
BRepMesh_Status* theStatus)
: myWires(&theWires.front()),
myWiresNb(theWires.size()),
myStatus(theStatus)
{
}
#endif
//=======================================================================
//function : Checker's body
//purpose :
//=======================================================================
void BRepMesh_WireInterferenceChecker::operator ()(
const Standard_Integer& theWireId) const
{
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
const BRepMesh_WireChecker::SegmentsTree& aWireSegTree1 = myWires[theWireId];
const BRepMesh_WireChecker::Segment* aWireSegments1 = &aWireSegTree1.first->front();
const BRepMesh_WireChecker::HBndBox2dTree& aWireBoxTree1 = aWireSegTree1.second;
const Standard_Integer aWireLen1 = aWireSegTree1.first->size();
for (Standard_Integer aWireIt = theWireId; aWireIt < myWiresNb; ++aWireIt)
{
#ifdef HAVE_TBB
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
#endif
const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
const BRepMesh_WireChecker::SegmentsTree& aWireSegTree2 =
isSelfIntCheck ? aWireSegTree1 : myWires[aWireIt];
const BRepMesh_WireChecker::Segment* aWireSegments2 = &aWireSegTree2.first->front();
const BRepMesh_WireChecker::HBndBox2dTree& aWireBoxTree2 = aWireSegTree2.second;
BRepMesh_WireChecker::BndBox2dTreeSelector aSelector(aWireSegTree2.first->size());
for (Standard_Integer aSegmentId1 = 0; aSegmentId1 < aWireLen1; ++aSegmentId1)
{
#ifdef HAVE_TBB
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
#endif
aSelector.Clear();
aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
if (isSelfIntCheck)
aSelector.SetSkippedIndex(aSegmentId1);
if (aWireBoxTree2->Select(aSelector) == 0)
continue;
const BRepMesh_WireChecker::Segment& aSegment1 = aWireSegments1[aSegmentId1];
const BRepMesh_WireChecker::ArrayOfInteger& aSelected = aSelector.Indices();
const Standard_Integer aSelectedNb = aSelector.IndicesNb();
for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
{
#ifdef HAVE_TBB
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
#endif
const Standard_Integer aSegmentId2 = aSelected(aBndIt);
const BRepMesh_WireChecker::Segment& aSegment2 = aWireSegments2[aSegmentId2];
gp_Pnt2d aIntPnt;
BRepMesh_WireInterferenceChecker::IntFlag aIntStatus = Intersect(
aSegment1.StartPnt, aSegment1.EndPnt,
aSegment2.StartPnt, aSegment2.EndPnt,
Standard_False, Standard_False,
aIntPnt);
if (aIntStatus == Cross)
{
// TODO: remove this block after implementation of LoopChecker2d.
if (isSelfIntCheck)
{
gp_XY aPrevVec;
Standard_Real aSumS = 0.;
const gp_XY& aRefPnt = aIntPnt.Coord();
for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i)
{
const BRepMesh_WireChecker::Segment& aSeg = aWireSegments1[i];
gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
if (aCurVec.SquareModulus() < gp::Resolution())
continue;
if (aPrevVec.SquareModulus() > gp::Resolution())
aSumS += aPrevVec ^ aCurVec;
aPrevVec = aCurVec;
}
if (Abs(aSumS / 2.) < MIN_LOOP_S)
continue;
}
#ifdef HAVE_TBB
Standard_Mutex::Sentry aSentry(myMutex);
#endif
*myStatus = BRepMesh_SelfIntersectingWire;
return;
}
}
}
}
}
//=============================================================================
//function : Intersect
//purpose :
//=============================================================================
BRepMesh_WireInterferenceChecker::IntFlag
BRepMesh_WireInterferenceChecker::Intersect(
const gp_XY& theStartPnt1,
const gp_XY& theEndPnt1,
const gp_XY& theStartPnt2,
const gp_XY& theEndPnt2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnSegment,
gp_Pnt2d& theIntPnt)
{
Standard_Integer aPointHash[] = {
classifyPoint(theStartPnt1, theEndPnt1, theStartPnt2),
classifyPoint(theStartPnt1, theEndPnt1, theEndPnt2 ),
classifyPoint(theStartPnt2, theEndPnt2, theStartPnt1),
classifyPoint(theStartPnt2, theEndPnt2, theEndPnt1 )
};
// Consider case when edges have shared vertex
if ( isConsiderEndPointTouch )
{
if ( aPointHash[0] < 0 || aPointHash[1] < 0 )
return BRepMesh_WireInterferenceChecker::EndPointTouch;
}
Standard_Integer aPosHash =
aPointHash[0] + aPointHash[1] + aPointHash[2] + aPointHash[3];
/*=========================================*/
/* 1) hash code == 1:
0+
/
0 1/ 0
+======+==========+
2) hash code == 2:
0 1 1 0
a) +----+========+---+
0 1 1 0
b) +-------+===+=====+
*/
/*=========================================*/
if ( aPosHash == 1 )
{
if (isConsiderPointOnSegment)
{
if (aPointHash[0] == 1)
theIntPnt = theStartPnt1;
else if (aPointHash[1] == 1)
theIntPnt = theEndPnt1;
else if (aPointHash[2] == 1)
theIntPnt = theStartPnt2;
else
theIntPnt = theEndPnt2;
return BRepMesh_WireInterferenceChecker::PointOnSegment;
}
return BRepMesh_WireInterferenceChecker::NoIntersection;
}
else if ( aPosHash == 2 )
return BRepMesh_WireInterferenceChecker::Glued;
gp_XY aVec1 = theEndPnt1 - theStartPnt1;
gp_XY aVec2 = theEndPnt2 - theStartPnt2;
gp_XY aVecStartPoints = theStartPnt2 - theStartPnt1;
Standard_Real aCrossD1D2 = aVec1 ^ aVec2;
Standard_Real aCrossD1D3 = aVecStartPoints ^ aVec2;
const Standard_Real aPrec = Precision::PConfusion();
// Are edgegs codirectional
if ( Abs( aCrossD1D2 ) < aPrec )
{
// Just a parallel case?
if( Abs( aCrossD1D3 ) < aPrec )
{
/*=========================================*/
/* Here the following cases are possible:
1) hash code == -4:
-1 -1
+=================+
-1 -1
2) hash code == -2:
0 -1 0
+--------+========+
-1
3) hash code == -1:
0 1 -1
+--------+========+
-1
4) hash code == 0:
0 0 0 0
+------+ +=======+
0 0 0 0
*/
/*=========================================*/
if ( aPosHash < -2 )
return BRepMesh_WireInterferenceChecker::Same;
else if ( aPosHash == -1 )
return BRepMesh_WireInterferenceChecker::Glued;
return BRepMesh_WireInterferenceChecker::NoIntersection;
}
else
return BRepMesh_WireInterferenceChecker::NoIntersection;
}
Standard_Real aPar = aCrossD1D3 / aCrossD1D2;
const Standard_Real aEndPrec = 1 - aPrec;
// Intersection is out of first segment range
if( aPar < aPrec || aPar > aEndPrec )
return BRepMesh_WireInterferenceChecker::NoIntersection;
Standard_Real aCrossD2D3 = aVecStartPoints.Reversed() ^ aVec1;
aPar = aCrossD2D3 / -aCrossD1D2;
// Intersection is out of second segment range
if( aPar < aPrec || aPar > aEndPrec )
return BRepMesh_WireInterferenceChecker::NoIntersection;
theIntPnt = theStartPnt2 + aPar * aVec2;
return BRepMesh_WireInterferenceChecker::Cross;
}
//=============================================================================
//function : classifyPoint
//purpose :
//=============================================================================
Standard_Integer BRepMesh_WireInterferenceChecker::classifyPoint(
const gp_XY& thePoint1,
const gp_XY& thePoint2,
const gp_XY& thePointToCheck)
{
gp_XY aP1 = thePoint2 - thePoint1;
gp_XY aP2 = thePointToCheck - thePoint1;
const Standard_Real aPrec = Precision::PConfusion();
const Standard_Real aSqPrec = aPrec * aPrec;
Standard_Real aDist = Abs(aP1 ^ aP2);
if (aDist > aPrec)
{
aDist = (aDist * aDist) / aP1.SquareModulus();
if (aDist > aSqPrec)
return 0; //out
}
gp_XY aMult = aP1.Multiplied(aP2);
if ( aMult.X() < 0.0 || aMult.Y() < 0.0 )
return 0; //out
if (aP1.SquareModulus() < aP2.SquareModulus())
return 0; //out
if (thePointToCheck.IsEqual(thePoint1, aPrec) ||
thePointToCheck.IsEqual(thePoint2, aPrec))
{
return -1; //coinsides with an end point
}
return 1;
}

View File

@ -0,0 +1,114 @@
// Created on: 2014-06-18
// Created by: Oleg AGASHIN
// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _BRepMesh_WireInterferenceChecker_HeaderFile
#define _BRepMesh_WireInterferenceChecker_HeaderFile
#include <Standard.hxx>
#include <Standard_Mutex.hxx>
#include <BRepMesh_WireChecker.hxx>
#include <BRepMesh_Status.hxx>
#ifdef HAVE_TBB
// paralleling using Intel TBB
#include <tbb/blocked_range.h>
#endif
//! Auxilary class implementing functionality for
//! checking interference between two discretized wires.
class BRepMesh_WireInterferenceChecker
{
public:
//! Enumerates states of segments intersection check.
enum IntFlag
{
NoIntersection,
Cross,
EndPointTouch,
PointOnSegment,
Glued,
Same
};
#ifdef HAVE_TBB
//! Constructor
//! \param theWires wires that should be checked.
//! \param theStatus shared flag to set status of the check.
//! \param theMutex shared mutex for parallel processing.
BRepMesh_WireInterferenceChecker(
const std::vector<BRepMesh_WireChecker::SegmentsTree>& theWires,
BRepMesh_Status* theStatus,
Standard_Mutex* theMutex);
//! Checker's body.
//! \param theWireRange range of wires to be checked.
void operator ()(const tbb::blocked_range<Standard_Integer>& theWireRange) const;
#else
//! Constructor
//! \param theWires wires that should be checked.
//! \param theStatus shared flag to set status of the check.
BRepMesh_WireInterferenceChecker(
const std::vector<BRepMesh_WireChecker::SegmentsTree>& theWires,
BRepMesh_Status* theStatus);
#endif
//! Checker's body.
//! \param theWireId Id of discretized wire to be checked.
void operator ()(const Standard_Integer& theWireId) const;
//! Checks intersection between the two segments.
//! \param theStartPnt1 start point of first segment.
//! \param theEndPnt1 end point of first segment.
//! \param theStartPnt2 start point of second segment.
//! \param theEndPnt2 end point of second segment.
//! \param isConsiderEndPointTouch if TRUE EndPointTouch status will be
//! returned in case if segments are touching by end points, if FALSE
//! returns NoIntersection flag.
//! \param isConsiderPointOnSegment if TRUE PointOnSegment status will be
//! returned in case if end point of one segment lies onto another one,
//! if FALSE returns NoIntersection flag.
//! \param[out] theIntPnt point of intersection.
//! \return status of intersection check.
static IntFlag Intersect(const gp_XY& theStartPnt1,
const gp_XY& theEndPnt1,
const gp_XY& theStartPnt2,
const gp_XY& theEndPnt2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnSegment,
gp_Pnt2d& theIntPnt);
private:
//! Classifies the point in case of coincidence of two vectors.
//! \param thePoint1 the start point of a segment (base point).
//! \param thePoint2 the end point of a segment.
//! \param thePointToCheck the point to classify.
//! \return zero value if point is out of segment and non zero value
//! if point is between the first and the second point of segment.
static Standard_Integer classifyPoint (const gp_XY& thePoint1,
const gp_XY& thePoint2,
const gp_XY& thePointToCheck);
private:
const BRepMesh_WireChecker::SegmentsTree* myWires;
Standard_Integer myWiresNb;
BRepMesh_Status* myStatus;
#ifdef HAVE_TBB
Standard_Mutex* myMutex;
#endif
};
#endif

View File

@ -2,7 +2,13 @@ BRepMesh_PluginEntryType.hxx
BRepMesh_PluginMacro.hxx
BRepMesh_Triangle.hxx
BRepMesh_Triangle.cxx
BRepMesh_Classifier.hxx
BRepMesh_Classifier.cxx
BRepMesh_ClassifierPtr.hxx
BRepMesh_WireInterferenceChecker.hxx
BRepMesh_WireInterferenceChecker.cxx
BRepMesh_WireChecker.hxx
BRepMesh_WireChecker.cxx
BRepMesh_CellFilter.hxx
BRepMesh_Delaun.hxx
BRepMesh_Delaun.cxx

View File

@ -117,7 +117,7 @@ Standard_Boolean NCollection_EBTree<TheObjType,TheBndType>::Add
UBTree::Add (theObj, theBnd);
// Update the map
TreeNode& aNewNode = ChangeLastNode();
TreeNode& aNewNode = this->ChangeLastNode();
myObjNodeMap.Bind (theObj, &aNewNode);
// If the new node is not the root (has a parent) check the neighbour node
if (!aNewNode.IsRoot()) {

View File

@ -0,0 +1,45 @@
puts "=========="
puts "OCC24968"
puts "=========="
puts ""
#####################################
# Impove BRepMesh_Classifier to cope with intersection of huge number of wires
#####################################
restore [locate_data_file bug24968_Shape_1.brep] result
tclean result
dchrono h reset
dchrono h start
incmesh result 0.1 0
dchrono h stop
set info [dchrono h show]
regexp {CPU user time: ([-0-9.+eE]+) seconds} ${info} full cpu_time
if { [regexp {Debug mode} [dversion]] } {
if { [regexp {Windows} [dversion]] } {
set max_time 100
} else {
set max_time 250
}
} else {
if { [regexp {Windows} [dversion]] } {
set max_time 100
} else {
set max_time 250
}
}
if { ${cpu_time} > ${max_time} } {
puts "Error : meshing is slow"
} else {
puts "OK: meshing is quite fast"
}
vinit
vdisplay result
vfit
vsetdispmode 1
set only_screen 1

View File

@ -0,0 +1,45 @@
puts "=========="
puts "OCC24968"
puts "=========="
puts ""
#####################################
# Impove BRepMesh_Classifier to cope with intersection of huge number of wires
#####################################
restore [locate_data_file bug24968_Shape_1.brep] result
tclean result
dchrono h reset
dchrono h start
incmesh result 0.1 1
dchrono h stop
set info [dchrono h show]
regexp {CPU user time: ([-0-9.+eE]+) seconds} ${info} full cpu_time
if { [regexp {Debug mode} [dversion]] } {
if { [regexp {Windows} [dversion]] } {
set max_time 100
} else {
set max_time 250
}
} else {
if { [regexp {Windows} [dversion]] } {
set max_time 100
} else {
set max_time 250
}
}
if { ${cpu_time} > ${max_time} } {
puts "Error : meshing is slow"
} else {
puts "OK: meshing is quite fast"
}
vinit
vdisplay result
vfit
vsetdispmode 1
set only_screen 1

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
set TheFileName shading_014.brep
if { [string compare $command "shading"] == 0 } {
set bug_freenodes "OCC22687"
set nbfreenodes(All) 1
}
###if { [string compare $command "shading"] == 0 } {
### set bug_freenodes "OCC22687"
### set nbfreenodes(All) 1
###}

View File

@ -4,6 +4,11 @@ if { [string compare $command "shading"] == 0 } {
set nbfreenodes(All) 1
} else {
set bug_freelinks "OCC23105"
set nbfree(ALL) 4
### set nbfree(ALL) 4
if { [string compare $command "mesh"] == 0 } {
set nbfree(ALL) 8
} else {
set nbfree(ALL) 2
}
set nbfreenodes(All) 4
}

View File

@ -9,14 +9,15 @@ if {[array get env os_type] != ""} {
set os $env(os_type)
}
if { [string compare $command "shading"] == 0 } {
set nbt 14
### set nbt 14
set nbt 9
set nbn 83
if {
[string compare $os "Mandriva2008"] == 0
|| [string compare $os "Debian40"] == 0
|| [string compare $os "Debian60-64"] == 0
} {
set nbl 19
set nbfree($os) $nbl
### set nbl 19
### set nbfree($os) $nbl
## else
## set nbl 17
}
@ -34,11 +35,12 @@ set nbfreenodes($os) $nbn
set nbfreenodes($os) $nbn
} else {
set bug_withouttri "OCC23105"
set nbt 14
### set nbt 14
set nbt 8
set nbn 60
## set nbl 2
set nbl 3
set nbwithouttri($os) $nbt
## set nbfree($os) $nbl
set nbfree($os) $nbl
set nbfreenodes($os) $nbn
}
}

View File

@ -11,8 +11,8 @@ if { [string compare $command "shading"] == 0 } {
set rel_tol 1.3
set nbwithouttri(ALL) 6
set nbfreenodes(ALL) 1
set bug_freelinks "OCC22687"
set nbfree(ALL) 2
### set bug_freelinks "OCC22687"
### set nbfree(ALL) 2
} else {
set nbfreenodes(ALL) 2
set nbwithouttri(ALL) 5
@ -30,7 +30,7 @@ if { [string compare $command "mesh"] == 0 } {
}
set nbfree($os) $nb
}
if { [string compare $command "shading"] == 0 } {
set bug_freelinks "OCC22687"
set nbfree(ALL) 2
}
###if { [string compare $command "shading"] == 0 } {
### set bug_freelinks "OCC22687"
### set nbfree(ALL) 2
###}

View File

@ -1,13 +1,13 @@
set TheFileName shading_wrongshape_029.brep
set bug_withouttri "OCC22687"
set nbwithouttri(All) 1
set bug_freelinks "OCC22687"
if { [string compare $command "shading"] == 0 } {
set bug_freenodes "OCC23105"
set nbfreenodes(ALL) 2
set nbfree(ALL) 12
} else {
set bug_freenodes "OCC23105"
set nbfreenodes(ALL) 2
set nbfree(ALL) 8
}
###set bug_withouttri "OCC22687"
###set nbwithouttri(All) 1
###set bug_freelinks "OCC22687"
###if { [string compare $command "shading"] == 0 } {
### set bug_freenodes "OCC23105"
### set nbfreenodes(ALL) 2
### set nbfree(ALL) 12
###} else {
### set bug_freenodes "OCC23105"
### set nbfreenodes(ALL) 2
### set nbfree(ALL) 8
###}