p3 = GetVertex( theEdg2.FirstNode() ).Coord();
p4 = GetVertex( theEdg2.LastNode() ).Coord();
+ Standard_Real aIntParams[2];
return BRepMesh_GeomTool::IntSegSeg(p1, p2, p3, p4,
- isConsiderEndPointTouch, isConsiderPointOnEdge, theIntPnt);
+ isConsiderEndPointTouch, isConsiderPointOnEdge, theIntPnt, aIntParams);
}
//=============================================================================
#include <OSD_Parallel.hxx>
#include <BRepMesh_GeomTool.hxx>
-namespace
-{
- const Standard_Real MaxTangentAngle = 5. * M_PI / 180.;
-
- //! Functor to be used to fill segments and bounding box tree in parallel.
- class SegmentsFiller
- {
- public:
- //! Constructor.
- SegmentsFiller(const IMeshData::IFaceHandle& theDFace,
- Handle(BRepMesh_FaceChecker::ArrayOfSegments)& theWiresSegments,
- Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& theWiresBndBoxTree)
- : myDFace(theDFace),
- myWiresSegments(theWiresSegments),
- myWiresBndBoxTree(theWiresBndBoxTree)
- {
- myWiresSegments = new BRepMesh_FaceChecker::ArrayOfSegments (0, myDFace->WiresNb() - 1);
- myWiresBndBoxTree = new BRepMesh_FaceChecker::ArrayOfBndBoxTree (0, myDFace->WiresNb() - 1);
- }
-
- //! Performs initialization of wire with the given index.
- void operator()(const Standard_Integer theWireIndex) const
- {
- const IMeshData::IWireHandle& aDWire = myDFace->GetWire(theWireIndex);
-
- Handle(NCollection_IncAllocator) aTmpAlloc1 = new NCollection_IncAllocator();
-
- Handle(BRepMesh_FaceChecker::Segments) aSegments =
- new BRepMesh_FaceChecker::Segments(aDWire->EdgesNb(), aTmpAlloc1);
- Handle(IMeshData::BndBox2dTree) aBndBoxTree = new IMeshData::BndBox2dTree(aTmpAlloc1);
-
- myWiresSegments ->ChangeValue(theWireIndex) = aSegments;
- myWiresBndBoxTree->ChangeValue(theWireIndex) = aBndBoxTree;
-
- Handle(NCollection_IncAllocator) aTmpAlloc2 = new NCollection_IncAllocator();
- IMeshData::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree, aTmpAlloc2);
-
- for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
- {
- // TODO: check 2d wire for consistency.
-
- const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge(aEdgeIt);
- const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
-
- for (Standard_Integer aPointIt = 1; aPointIt < aPCurve->ParametersNb(); ++aPointIt)
- {
- gp_Pnt2d& aPnt1 = aPCurve->GetPoint(aPointIt - 1);
- gp_Pnt2d& aPnt2 = aPCurve->GetPoint(aPointIt);
-
- Bnd_Box2d aBox;
- aBox.Add(aPnt1);
- aBox.Add(aPnt2);
- aBox.Enlarge(Precision::Confusion());
-
- aBndBoxTreeFiller.Add(aSegments->Size(), aBox);
- aSegments->Append(BRepMesh_FaceChecker::Segment(aDEdge, &aPnt1, &aPnt2));
- }
- }
-
- aBndBoxTreeFiller.Fill();
- }
-
- private:
-
- SegmentsFiller (const SegmentsFiller& theOther);
-
- void operator=(const SegmentsFiller& theOther);
-
- private:
-
- const IMeshData::IFaceHandle& myDFace;
- Handle(BRepMesh_FaceChecker::ArrayOfSegments)& myWiresSegments;
- Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& myWiresBndBoxTree;
- };
-
- //! Selector.
- //! Used to identify segments with overlapped bounding boxes.
- class BndBox2dTreeSelector : public IMeshData::BndBox2dTree::Selector
- {
- public:
- //! Constructor.
- BndBox2dTreeSelector(const Standard_Real theTolerance)
- : myMaxLoopSize(M_PI * theTolerance * theTolerance),
- mySelfSegmentIndex(-1),
- myIndices(256, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
- {
- }
-
- //! Sets working set of segments.
- void SetSegments(const Handle(BRepMesh_FaceChecker::Segments)& theSegments)
- {
- mySegments = theSegments;
- }
-
- //! Resets current selector.
- void Reset(const BRepMesh_FaceChecker::Segment* theSegment,
- const Standard_Integer theSelfSegmentIndex)
- {
- myIndices.Clear();
-
- mySelfSegmentIndex = theSelfSegmentIndex;
- mySegment = theSegment;
-
- myBox.SetVoid();
- myBox.Add(*mySegment->Point1);
- myBox.Add(*mySegment->Point2);
- myBox.Enlarge(Precision::Confusion());
- }
-
- //! Indicates should the given box be rejected or not.
- virtual Standard_Boolean Reject(const Bnd_Box2d& theBox) const
- {
- return myBox.IsOut(theBox);
- }
-
- //! Accepts segment with the given index in case if it fits conditions.
- virtual Standard_Boolean Accept(const Standard_Integer& theSegmentIndex)
- {
- const BRepMesh_FaceChecker::Segment& aSegment = mySegments->Value(theSegmentIndex);
-
- gp_Pnt2d aIntPnt;
- const BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
- mySegment->Point1->XY(), mySegment->Point2->XY(),
- aSegment.Point1->XY(), aSegment.Point2->XY(),
- Standard_False, Standard_False, aIntPnt);
-
- if (aIntStatus == BRepMesh_GeomTool::Cross)
- {
- const Standard_Real aAngle = gp_Vec2d(mySegment->Point1->XY(), mySegment->Point2->XY()).Angle(
- gp_Vec2d(aSegment.Point1->XY(), aSegment.Point2->XY()));
-
- if (Abs(aAngle) < MaxTangentAngle)
- {
- return Standard_False;
- }
-
- if (mySelfSegmentIndex != -1)
- {
- gp_XY aPrevVec;
- Standard_Real aSumS = 0.;
- const gp_XY& aRefPnt = aIntPnt.Coord();
- for (Standard_Integer i = mySelfSegmentIndex; i < theSegmentIndex; ++i)
- {
- const BRepMesh_FaceChecker::Segment& aCurrSegment = mySegments->Value(i);
- gp_XY aCurVec = aCurrSegment.Point2->XY() - aRefPnt;
-
- if (aCurVec.SquareModulus() < gp::Resolution())
- continue;
-
- if (aPrevVec.SquareModulus() > gp::Resolution())
- aSumS += aPrevVec ^ aCurVec;
-
- aPrevVec = aCurVec;
- }
-
- if (Abs(aSumS / 2.) < myMaxLoopSize)
- {
- return Standard_False;
- }
- }
-
- myIndices.Append(theSegmentIndex);
- return Standard_True;
- }
-
- return Standard_False;
- }
-
- //! Returns indices of intersecting segments.
- const IMeshData::VectorOfInteger& Indices() const
- {
- return myIndices;
- }
-
- private:
-
- Standard_Real myMaxLoopSize;
- Standard_Integer mySelfSegmentIndex;
- Handle(BRepMesh_FaceChecker::Segments) mySegments;
- const BRepMesh_FaceChecker::Segment* mySegment;
- Bnd_Box2d myBox;
- IMeshData::VectorOfInteger myIndices;
- };
-}
-
//=======================================================================
//function : Constructor
//purpose :
BRepMesh_FaceChecker::BRepMesh_FaceChecker(
const IMeshData::IFaceHandle& theFace,
const IMeshTools_Parameters& theParameters)
- : myDFace(theFace),
- myParameters(theParameters)
+ : BRepMesh_SegmentedFace (theFace, theParameters)
{
}
//=======================================================================
Standard_Boolean BRepMesh_FaceChecker::Perform()
{
- myIntersectingEdges = new IMeshData::MapOfIEdgePtr;
collectSegments();
+ myIntersectingEdges = new IMeshData::MapOfIEdgePtr;
+ myWiresIntersectingEdges = new ArrayOfMapOfIEdgePtr(0, myDFace->WiresNb() - 1);
+
OSD_Parallel::For(0, myDFace->WiresNb(), *this, !isParallel());
collectResult();
- myWiresBndBoxTree.Nullify();
- myWiresSegments.Nullify();
+ myWiresBndBoxTree .Nullify();
+ myWiresSegments .Nullify();
myWiresIntersectingEdges.Nullify();
return myIntersectingEdges->IsEmpty();
}
-//=======================================================================
-//function : collectSegments
-//purpose :
-//=======================================================================
-void BRepMesh_FaceChecker::collectSegments()
-{
- SegmentsFiller aSegmentsFiller(myDFace, myWiresSegments, myWiresBndBoxTree);
- OSD_Parallel::For(0, myDFace->WiresNb(), aSegmentsFiller, !isParallel());
-
- myWiresIntersectingEdges = new ArrayOfMapOfIEdgePtr(0, myDFace->WiresNb() - 1);
-}
-
//=======================================================================
//function : perform
//purpose :
//=======================================================================
void BRepMesh_FaceChecker::perform(const Standard_Integer theWireIndex) const
{
- const Handle(Segments)& aSegments1 = myWiresSegments->Value(theWireIndex);
+ const Handle(Segments)& aSegments1 = myWiresSegments ->Value (theWireIndex);
Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myWiresIntersectingEdges->ChangeValue(theWireIndex);
- // TODO: Tolerance is set to twice value of face deflection in order to fit regressions.
- BndBox2dTreeSelector aSelector(2 * myDFace->GetDeflection());
+ BRepMesh_SegmentedFace::BndBox2dTreeSelector aSelector (Standard_False);
for (Standard_Integer aWireIt = theWireIndex; aWireIt < myDFace->WiresNb(); ++aWireIt)
{
const Handle(IMeshData::BndBox2dTree)& aBndBoxTree2 = myWiresBndBoxTree->Value(aWireIt);
- const Handle(Segments)& aSegments2 = myWiresSegments->Value(aWireIt);
+ const Handle(Segments)& aSegments2 = myWiresSegments ->Value(aWireIt);
aSelector.SetSegments(aSegments2);
for (Standard_Integer aSegmentIt = 0; aSegmentIt < aSegments1->Size(); ++aSegmentIt)
{
- const BRepMesh_FaceChecker::Segment& aSegment1 = aSegments1->Value(aSegmentIt);
+ const BRepMesh_SegmentedFace::Segment& aSegment1 = aSegments1->Value(aSegmentIt);
aSelector.Reset(&aSegment1, (aWireIt == theWireIndex) ? aSegmentIt : -1);
if (aBndBoxTree2->Select(aSelector) != 0)
{
const IMeshData::VectorOfInteger& aSegments = aSelector.Indices();
for (Standard_Integer aSelIt = 0; aSelIt < aSegments.Size(); ++aSelIt)
{
- const BRepMesh_FaceChecker::Segment& aSegment2 = aSegments2->Value(aSegments(aSelIt));
+ const BRepMesh_SegmentedFace::Segment& aSegment2 = aSegments2->Value(aSegments(aSelIt));
aIntersections->Add(aSegment2.EdgePtr);
}
}
#ifndef _BRepMesh_FaceChecker_HeaderFile
#define _BRepMesh_FaceChecker_HeaderFile
-#include <IMeshTools_Parameters.hxx>
-#include <Standard_Transient.hxx>
-#include <IMeshData_Face.hxx>
-#include <Standard_Type.hxx>
-#include <NCollection_Shared.hxx>
+#include <BRepMesh_SegmentedFace.hxx>
//! Auxiliary class checking wires of target face for self-intersections.
//! Explodes wires of discrete face on sets of segments using tessellation
//! data stored in model. Each segment is then checked for intersection with
//! other ones. All collisions are registerd and returned as result of check.
-class BRepMesh_FaceChecker : public Standard_Transient
+class BRepMesh_FaceChecker : public BRepMesh_SegmentedFace
{
public: //! @name mesher API
- //! Identifies segment inside face.
- struct Segment
- {
- IMeshData::IEdgePtr EdgePtr;
- gp_Pnt2d* Point1; // \ Use explicit pointers to points instead of accessing
- gp_Pnt2d* Point2; // / using indices.
-
- Segment()
- : Point1(NULL)
- , Point2(NULL)
- {
- }
-
- Segment(const IMeshData::IEdgePtr& theEdgePtr,
- gp_Pnt2d* thePoint1,
- gp_Pnt2d* thePoint2)
- : EdgePtr(theEdgePtr)
- , Point1(thePoint1)
- , Point2(thePoint2)
- {
- }
- };
-
- typedef NCollection_Shared<NCollection_Vector<Segment> > Segments;
- typedef NCollection_Shared<NCollection_Array1<Handle(Segments)> > ArrayOfSegments;
- typedef NCollection_Shared<NCollection_Array1<Handle(IMeshData::BndBox2dTree)> > ArrayOfBndBoxTree;
typedef NCollection_Shared<NCollection_Array1<Handle(IMeshData::MapOfIEdgePtr)> > ArrayOfMapOfIEdgePtr;
-
//! Default constructor
Standard_EXPORT BRepMesh_FaceChecker(const IMeshData::IFaceHandle& theFace,
const IMeshTools_Parameters& theParameters);
perform(theWireIndex);
}
- DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceChecker, Standard_Transient)
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceChecker, BRepMesh_SegmentedFace)
private:
- //! Returns True in case if check can be performed in parallel mode.
- inline Standard_Boolean isParallel() const
- {
- return (myParameters.InParallel && myDFace->WiresNb() > 1);
- }
-
- //! Collects face segments.
- void collectSegments();
-
//! Collects intersecting edges.
void collectResult();
private:
- IMeshData::IFaceHandle myDFace;
- const IMeshTools_Parameters& myParameters;
-
- Handle(ArrayOfSegments) myWiresSegments;
- Handle(ArrayOfBndBoxTree) myWiresBndBoxTree;
Handle(ArrayOfMapOfIEdgePtr) myWiresIntersectingEdges;
Handle(IMeshData::MapOfIEdgePtr) myIntersectingEdges;
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// 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_FaceIntersectionsSplitter.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+BRepMesh_FaceIntersectionsSplitter::BRepMesh_FaceIntersectionsSplitter(
+ const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters)
+ : BRepMesh_SegmentedFace (theFace, theParameters)
+{
+}
+
+//=======================================================================
+//function : Destructor
+//purpose :
+//=======================================================================
+BRepMesh_FaceIntersectionsSplitter::~BRepMesh_FaceIntersectionsSplitter()
+{
+}
+
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_FaceIntersectionsSplitter::Perform()
+{
+ for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt)
+ {
+ Standard_Boolean isSplit = Standard_True;
+ while (isSplit)
+ {
+ collectSegments();
+
+ isSplit = perform(aWireIt);
+
+ myWiresSegments .Nullify();
+ myWiresBndBoxTree.Nullify();
+ }
+ }
+
+ return Standard_False;
+}
+
+//=======================================================================
+//function : perform
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_FaceIntersectionsSplitter::perform(
+ const Standard_Integer theWireIndex)
+{
+ const Handle(Segments)& aSegments1 = myWiresSegments->Value (theWireIndex);
+
+ BRepMesh_SegmentedFace::BndBox2dTreeSelector aSelector (Standard_True);
+ for (Standard_Integer aWireIt = theWireIndex; aWireIt < myDFace->WiresNb(); ++aWireIt)
+ {
+ const Handle(IMeshData::BndBox2dTree)& aBndBoxTree2 = myWiresBndBoxTree->Value(aWireIt);
+ const Handle(Segments)& aSegments2 = myWiresSegments ->Value(aWireIt);
+
+ aSelector.SetSegments(aSegments2);
+ for (Standard_Integer aSegmentIt = 0; aSegmentIt < aSegments1->Size(); ++aSegmentIt)
+ {
+ const BRepMesh_SegmentedFace::Segment& aSegment1 = aSegments1->Value(aSegmentIt);
+ aSelector.Reset(&aSegment1, (aWireIt == theWireIndex) ? aSegmentIt : -1);
+ if (aBndBoxTree2->Select(aSelector) != 0)
+ {
+ const IMeshData::VectorOfInteger& aSegments = aSelector.Indices();
+ const BRepMesh_SegmentedFace::VectorOfIntersectionParams& aIntParams = aSelector.IntParams();
+ for (Standard_Integer aSelIt = 0; aSelIt < aSegments.Size(); ++aSelIt)
+ {
+ const BRepMesh_SegmentedFace::Segment& aSegment2 = aSegments2->Value(aSegments(aSelIt));
+
+ //aIntersections->Add(aSegment1.EdgePtr);
+ //aIntersections->Add(aSegment2.EdgePtr);
+ }
+
+ //return Standard_False;
+ }
+ }
+ }
+
+ return Standard_False;
+}
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// 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_FaceIntersectionsSplitter_HeaderFile
+#define _BRepMesh_FaceIntersectionsSplitter_HeaderFile
+
+#include <BRepMesh_SegmentedFace.hxx>
+
+//! Auxiliary class splitting intersecting segments of wires of target face.
+//! Explodes wires of discrete face on sets of segments using tessellation
+//! data stored in model. Each segment is then checked for intersection with
+//! other ones and split on intersection point.
+class BRepMesh_FaceIntersectionsSplitter : public BRepMesh_SegmentedFace
+{
+public: //! @name mesher API
+
+ //! Default constructor
+ Standard_EXPORT BRepMesh_FaceIntersectionsSplitter(
+ const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Destructor
+ Standard_EXPORT virtual ~BRepMesh_FaceIntersectionsSplitter();
+
+ //! Performs split of intersecting segments of wires of the face.
+ //! @return True if there is no intersection, False elsewhere.
+ Standard_EXPORT Standard_Boolean Perform();
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceIntersectionsSplitter, BRepMesh_SegmentedFace)
+
+private:
+
+ //! Splits wire with the given index at first intersection point with others.
+ Standard_Boolean perform(const Standard_Integer theWireIndex);
+
+private:
+
+ BRepMesh_FaceIntersectionsSplitter (const BRepMesh_FaceIntersectionsSplitter& theOther);
+
+ void operator=(const BRepMesh_FaceIntersectionsSplitter& theOther);
+};
+
+#endif
const gp_XY& theEndPnt2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnSegment,
- gp_Pnt2d& theIntPnt)
+ gp_Pnt2d& theIntPnt,
+ Standard_Real (&theParamOnSegment)[2])
{
Standard_Integer aPointHash[] = {
classifyPoint(theStartPnt1, theEndPnt1, theStartPnt2),
else if ( aPosHash == 2 )
return BRepMesh_GeomTool::Glued;
- Standard_Real aParam[2];
IntFlag aIntFlag = IntLinLin(theStartPnt1, theEndPnt1,
- theStartPnt2, theEndPnt2, theIntPnt.ChangeCoord(), aParam);
+ theStartPnt2, theEndPnt2, theIntPnt.ChangeCoord(), theParamOnSegment);
if (aIntFlag == BRepMesh_GeomTool::NoIntersection)
return BRepMesh_GeomTool::NoIntersection;
const Standard_Real aEndPrec = 1 - aPrec;
for (Standard_Integer i = 0; i < 2; ++i)
{
- if(aParam[i] < aPrec || aParam[i] > aEndPrec )
+ if(theParamOnSegment[i] < aPrec || theParamOnSegment[i] > aEndPrec )
return BRepMesh_GeomTool::NoIntersection;
}
const gp_XY& theEndPnt2,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnSegment,
- gp_Pnt2d& theIntPnt);
+ gp_Pnt2d& theIntPnt,
+ Standard_Real (&theParamOnSegment)[2]);
//! Compute deflection of the given segment.
static Standard_Real SquareDeflectionOfSegment(
#include <BRepMesh_Deflection.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <BRepMesh_FaceChecker.hxx>
+#include <BRepMesh_FaceIntersectionsSplitter.hxx>
#include <BRepMesh_EdgeDiscret.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Wire.hxx>
{
const IMeshData::IFaceHandle aDFace = aFaceIt.Key();
aDFace->SetStatus(IMeshData_SelfIntersectingWire);
- aDFace->SetStatus(IMeshData_Failure);
+
+ BRepMesh_FaceIntersectionsSplitter aSplitter (aDFace, myParameters);
+ if (!aSplitter.Perform())
+ {
+ aDFace->SetStatus(IMeshData_Failure);
+ }
}
}
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// 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_SegmentedFace.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <OSD_Parallel.hxx>
+
+namespace
+{
+ //! Functor to be used to fill segments and bounding box tree in parallel.
+ class SegmentsFiller
+ {
+ public:
+ //! Constructor.
+ SegmentsFiller(const IMeshData::IFaceHandle& theDFace,
+ Handle(BRepMesh_SegmentedFace::ArrayOfSegments)& theWiresSegments,
+ Handle(BRepMesh_SegmentedFace::ArrayOfBndBoxTree)& theWiresBndBoxTree)
+ : myDFace(theDFace),
+ myWiresSegments(theWiresSegments),
+ myWiresBndBoxTree(theWiresBndBoxTree)
+ {
+ myWiresSegments = new BRepMesh_SegmentedFace::ArrayOfSegments (0, myDFace->WiresNb() - 1);
+ myWiresBndBoxTree = new BRepMesh_SegmentedFace::ArrayOfBndBoxTree (0, myDFace->WiresNb() - 1);
+ }
+
+ //! Performs initialization of wire with the given index.
+ void operator()(const Standard_Integer theWireIndex) const
+ {
+ const IMeshData::IWireHandle& aDWire = myDFace->GetWire(theWireIndex);
+
+ Handle(NCollection_IncAllocator) aTmpAlloc1 = new NCollection_IncAllocator();
+
+ Handle(BRepMesh_SegmentedFace::Segments) aSegments =
+ new BRepMesh_SegmentedFace::Segments(aDWire->EdgesNb(), aTmpAlloc1);
+ Handle(IMeshData::BndBox2dTree) aBndBoxTree = new IMeshData::BndBox2dTree(aTmpAlloc1);
+
+ myWiresSegments ->ChangeValue(theWireIndex) = aSegments;
+ myWiresBndBoxTree->ChangeValue(theWireIndex) = aBndBoxTree;
+
+ Handle(NCollection_IncAllocator) aTmpAlloc2 = new NCollection_IncAllocator();
+ IMeshData::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree, aTmpAlloc2);
+
+ for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
+ {
+ // TODO: check 2d wire for consistency.
+
+ const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge(aEdgeIt);
+ const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
+
+ for (Standard_Integer aPointIt = 1; aPointIt < aPCurve->ParametersNb(); ++aPointIt)
+ {
+ gp_Pnt2d& aPnt1 = aPCurve->GetPoint(aPointIt - 1);
+ gp_Pnt2d& aPnt2 = aPCurve->GetPoint(aPointIt);
+
+ Bnd_Box2d aBox;
+ aBox.Add(aPnt1);
+ aBox.Add(aPnt2);
+ aBox.Enlarge(Precision::Confusion());
+
+ aBndBoxTreeFiller.Add(aSegments->Size(), aBox);
+ aSegments->Append(BRepMesh_SegmentedFace::Segment(
+ aDEdge, aPCurve.get(),
+ &aPnt1, aPointIt - 1,
+ &aPnt2, aPointIt));
+ }
+ }
+
+ aBndBoxTreeFiller.Fill();
+ }
+
+ private:
+
+ SegmentsFiller (const SegmentsFiller& theOther);
+
+ void operator=(const SegmentsFiller& theOther);
+
+ private:
+
+ const IMeshData::IFaceHandle& myDFace;
+ Handle(BRepMesh_SegmentedFace::ArrayOfSegments)& myWiresSegments;
+ Handle(BRepMesh_SegmentedFace::ArrayOfBndBoxTree)& myWiresBndBoxTree;
+ };
+}
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+BRepMesh_SegmentedFace::BndBox2dTreeSelector::BndBox2dTreeSelector(
+ const Standard_Boolean isCollectIntersectionParams)
+ : myCollectIntersectionParams (isCollectIntersectionParams)
+ , mySelfSegmentIndex(-1)
+ , myIndices(256, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
+{
+}
+
+//=======================================================================
+//function : Reset
+//purpose :
+//=======================================================================
+void BRepMesh_SegmentedFace::BndBox2dTreeSelector::Reset(
+ const BRepMesh_SegmentedFace::Segment* theSegment,
+ const Standard_Integer theSelfSegmentIndex)
+{
+ myIndices .Clear();
+ myIntParams.Clear();
+
+ mySelfSegmentIndex = theSelfSegmentIndex;
+ mySegment = theSegment;
+
+ myBox.SetVoid();
+ myBox.Add(*mySegment->Point1);
+ myBox.Add(*mySegment->Point2);
+ myBox.Enlarge(Precision::Confusion());
+}
+
+//=======================================================================
+//function : Reject
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_SegmentedFace::BndBox2dTreeSelector::Reject(
+ const Bnd_Box2d& theBox) const
+{
+ return myBox.IsOut(theBox);
+}
+
+//=======================================================================
+//function : Accept
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_SegmentedFace::BndBox2dTreeSelector::Accept(
+ const Standard_Integer& theSegmentIndex)
+{
+ const BRepMesh_SegmentedFace::Segment& aSegment = mySegments->Value(theSegmentIndex);
+
+ IntersectionParams aIntNode;
+ aIntNode.Type = BRepMesh_GeomTool::IntSegSeg(
+ mySegment->Point1->XY(), mySegment->Point2->XY(),
+ aSegment .Point1->XY(), aSegment .Point2->XY(),
+ Standard_False, Standard_False,
+ aIntNode.Point, aIntNode.Params);
+
+ if (aIntNode.Type == BRepMesh_GeomTool::Cross ||
+ aIntNode.Type == BRepMesh_GeomTool::PointOnSegment ||
+ aIntNode.Type == BRepMesh_GeomTool::Glued)
+ {
+
+ myIndices.Append(theSegmentIndex);
+
+ if (myCollectIntersectionParams)
+ {
+ myIntParams.Append(aIntNode);
+ }
+ return Standard_True;
+ }
+
+ return Standard_False;
+}
+
+
+
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+BRepMesh_SegmentedFace::BRepMesh_SegmentedFace(
+ const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters)
+ : myDFace (theFace),
+ myParameters(theParameters)
+{
+}
+
+//=======================================================================
+//function : Destructor
+//purpose :
+//=======================================================================
+BRepMesh_SegmentedFace::~BRepMesh_SegmentedFace()
+{
+}
+
+//=======================================================================
+//function : collectSegments
+//purpose :
+//=======================================================================
+void BRepMesh_SegmentedFace::collectSegments()
+{
+ SegmentsFiller aSegmentsFiller(myDFace, myWiresSegments, myWiresBndBoxTree);
+ OSD_Parallel::For(0, myDFace->WiresNb(), aSegmentsFiller, !isParallel());
+}
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// 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_SegmentedFace_HeaderFile
+#define _BRepMesh_SegmentedFace_HeaderFile
+
+#include <IMeshTools_Parameters.hxx>
+#include <Standard_Transient.hxx>
+#include <IMeshData_Face.hxx>
+#include <Standard_Type.hxx>
+#include <NCollection_Shared.hxx>
+#include <BRepMesh_GeomTool.hxx>
+
+//! Auxiliary class providing common functionality for exploding wires of
+//! discrete face on sets of segments using tessellation data stored in model.
+class BRepMesh_SegmentedFace : public Standard_Transient
+{
+public: //! @name mesher API
+
+ //! Identifies segment inside face.
+ //! Uses explicit pointers to points instead of accessing using indices.
+ struct Segment
+ {
+ IMeshData::IEdgePtr EdgePtr;
+ IMeshData::IPCurvePtr PCurvePtr;
+ gp_Pnt2d* Point1;
+ Standard_Integer Param1;
+ gp_Pnt2d* Point2;
+ Standard_Integer Param2;
+
+ Segment()
+ : EdgePtr (NULL)
+ , PCurvePtr(NULL)
+ , Point1 (NULL)
+ , Param1 (0)
+ , Point2 (NULL)
+ , Param2 (0)
+ {
+ }
+
+ Segment(const IMeshData::IEdgePtr& theEdgePtr,
+ const IMeshData::IPCurvePtr& thePCurvePtr,
+ gp_Pnt2d* thePoint1,
+ const Standard_Integer theParam1,
+ gp_Pnt2d* thePoint2,
+ const Standard_Integer theParam2)
+ : EdgePtr (theEdgePtr)
+ , PCurvePtr(thePCurvePtr)
+ , Point1 (thePoint1)
+ , Param1 (theParam1)
+ , Point2 (thePoint2)
+ , Param2 (theParam2)
+ {
+ }
+ };
+
+ //! Keeps parameters of intersection of two segments.
+ //! Params are in range relative to distance between points of corresponding segment.
+ struct IntersectionParams
+ {
+ BRepMesh_GeomTool::IntFlag Type;
+ gp_Pnt2d Point;
+ Standard_Real Params[2];
+ };
+
+ typedef NCollection_Vector<IntersectionParams> VectorOfIntersectionParams;
+ typedef NCollection_Shared<NCollection_Vector<Segment> > Segments;
+ typedef NCollection_Shared<NCollection_Array1<Handle(Segments)> > ArrayOfSegments;
+ typedef NCollection_Shared<NCollection_Array1<Handle(IMeshData::BndBox2dTree)> > ArrayOfBndBoxTree;
+
+
+ //! Default constructor
+ Standard_EXPORT BRepMesh_SegmentedFace(const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Destructor
+ Standard_EXPORT virtual ~BRepMesh_SegmentedFace();
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_SegmentedFace, Standard_Transient)
+
+protected:
+
+ //! Returns True in case if check can be performed in parallel mode.
+ inline Standard_Boolean isParallel() const
+ {
+ return (myParameters.InParallel && myDFace->WiresNb() > 1);
+ }
+
+ //! Collects face segments.
+ void collectSegments();
+
+private:
+
+ BRepMesh_SegmentedFace (const BRepMesh_SegmentedFace& theOther);
+
+ void operator=(const BRepMesh_SegmentedFace& theOther);
+
+protected:
+
+ //! Selector.
+ //! Used to identify segments with overlapped bounding boxes.
+ class BndBox2dTreeSelector : public IMeshData::BndBox2dTree::Selector
+ {
+ public:
+ //! Constructor.
+ BndBox2dTreeSelector(const Standard_Boolean isCollectIntersectionParams);
+
+ //! Sets working set of segments.
+ inline void SetSegments(const Handle(BRepMesh_SegmentedFace::Segments)& theSegments)
+ {
+ mySegments = theSegments;
+ }
+
+ //! Returns indices of intersecting segments.
+ inline const IMeshData::VectorOfInteger& Indices() const
+ {
+ return myIndices;
+ }
+
+ //! Returns intersection parameters.
+ inline const BRepMesh_SegmentedFace::VectorOfIntersectionParams& IntParams() const
+ {
+ return myIntParams;
+ }
+
+ //! Resets current selector.
+ void Reset(const BRepMesh_SegmentedFace::Segment* theSegment,
+ const Standard_Integer theSelfSegmentIndex);
+
+ //! Indicates should the given box be rejected or not.
+ virtual Standard_Boolean Reject(const Bnd_Box2d& theBox) const;
+
+ //! Accepts segment with the given index in case if it fits conditions.
+ virtual Standard_Boolean Accept(const Standard_Integer& theSegmentIndex);
+
+ private:
+
+ Standard_Boolean myCollectIntersectionParams;
+ Standard_Integer mySelfSegmentIndex;
+ Handle(BRepMesh_SegmentedFace::Segments) mySegments;
+ const BRepMesh_SegmentedFace::Segment* mySegment;
+ Bnd_Box2d myBox;
+ IMeshData::VectorOfInteger myIndices;
+ BRepMesh_SegmentedFace::VectorOfIntersectionParams myIntParams;
+ };
+
+protected:
+
+ IMeshData::IFaceHandle myDFace;
+ const IMeshTools_Parameters& myParameters;
+
+ Handle(ArrayOfSegments) myWiresSegments;
+ Handle(ArrayOfBndBoxTree) myWiresBndBoxTree;
+
+};
+
+#endif
BRepMesh_EdgeTessellationExtractor.hxx
BRepMesh_FaceChecker.cxx
BRepMesh_FaceChecker.hxx
+BRepMesh_FaceIntersectionsSplitter.cxx
+BRepMesh_FaceIntersectionsSplitter.hxx
BRepMesh_FaceDiscret.cxx
BRepMesh_FaceDiscret.hxx
BRepMesh_FactoryError.hxx
BRepMesh_PairOfIndex.hxx
BRepMesh_PluginEntryType.hxx
BRepMesh_PluginMacro.hxx
+BRepMesh_SegmentedFace.cxx
+BRepMesh_SegmentedFace.hxx
BRepMesh_SelectorOfDataStructureOfDelaun.cxx
BRepMesh_SelectorOfDataStructureOfDelaun.hxx
BRepMesh_ShapeTool.cxx
const size_t MEMORY_BLOCK_SIZE_HUGE = 512 * 1024;
#endif
- typedef IMeshData_Edge* IEdgePtr;
- typedef IMeshData_Face* IFacePtr;
+ typedef IMeshData_Edge* IEdgePtr;
+ typedef IMeshData_PCurve* IPCurvePtr;
+ typedef IMeshData_Face* IFacePtr;
typedef Handle(IMeshData_Edge) IEdgeHandle;
typedef Handle(IMeshData_Wire) IWireHandle;
aIntFlag = BRepMesh_GeomTool::IntSegSeg(
aRefPnts[0], aRefPnts[1], aRefPnts[2], aRefPnts[3],
- Standard_False, Standard_False, aIntPnt);
+ Standard_False, Standard_False, aIntPnt, aParams);
aDiff = aIntPnt.Distance(gp::Origin2d());
if (aIntFlag != BRepMesh_GeomTool::Cross || aDiff > Precision::PConfusion())