1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-07-15 12:35:51 +03:00
occt/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx
msv c7b59798ca 0024826: Wrapping of parallelisation algorithms
Simple primitives to parallelize loops type "for" and "foreach" were implemented. The primitives encapsulates complete logic for creating and managing parallel context of loops. Moreover the primitives may be a wrapper for some primitives from 3rd-party library - TBB.

To use it is necessary to implement TBB like interface which is based on functors. For example:

Class Functor
{
public:
  void operator() ([proccesing instance]) const
  {
    //...
  }
};

In the body of the operator () should be implemented thread-safe logic of computations that can be performed in parallel context. If parallelized loop iterates on the collections with direct access by index (such as Vector, Array), it is more efficient to use the primitive ParallelFor (because it has no critical section).

All parts of  OCC code which are using tbb were changed on new primitives.

0024826: Wrapping of parallelisation algorithms

Small fix.
2015-02-05 15:51:05 +03:00

135 lines
4.9 KiB
C++

// 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 <BRepMesh_GeomTool.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;
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
const BRepMesh::Array1OfSegmentsTree& theWires,
BRepMesh_Status* theStatus,
Standard_Mutex* theMutex)
: myWires (theWires),
myStatus(theStatus),
myMutex (theMutex)
{
}
//=======================================================================
//function : Checker's body
//purpose :
//=======================================================================
void BRepMesh_WireInterferenceChecker::operator ()(
const Standard_Integer& theWireId) const
{
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
const BRepMesh::SegmentsTree& aWireSegTree1 = myWires(theWireId);
const BRepMesh::HArray1OfSegments& aWireSegments1 = aWireSegTree1.first;
const BRepMesh::HBndBox2dTree& aWireBoxTree1 = aWireSegTree1.second;
for (Standard_Integer aWireIt = theWireId; aWireIt <= myWires.Upper(); ++aWireIt)
{
// Break execution in case if flag was raised by another thread.
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
const BRepMesh::SegmentsTree& aWireSegTree2 =
isSelfIntCheck ? aWireSegTree1 : myWires(aWireIt);
const BRepMesh::HArray1OfSegments& aWireSegments2 = aWireSegTree2.first;
const BRepMesh::HBndBox2dTree& aWireBoxTree2 = aWireSegTree2.second;
BRepMesh_WireChecker::BndBox2dTreeSelector aSelector (aWireSegments2->Size());
Standard_Integer aSegmentId1 = aWireSegments1->Lower();
for (; aSegmentId1 <= aWireSegments1->Upper(); ++aSegmentId1)
{
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
aSelector.Clear();
aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
if (isSelfIntCheck)
aSelector.SetSkippedIndex(aSegmentId1);
if (aWireBoxTree2->Select(aSelector) == 0)
continue;
const BRepMesh::Segment& aSegment1 = aWireSegments1->Value(aSegmentId1);
const BRepMesh::Array1OfInteger& aSelected = aSelector.Indices();
const Standard_Integer aSelectedNb = aSelector.IndicesNb();
for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
{
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
const Standard_Integer aSegmentId2 = aSelected(aBndIt);
const BRepMesh::Segment& aSegment2 = aWireSegments2->Value(aSegmentId2);
gp_Pnt2d aIntPnt;
BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
aSegment1.StartPnt, aSegment1.EndPnt,
aSegment2.StartPnt, aSegment2.EndPnt,
Standard_False, Standard_False,
aIntPnt);
if (aIntStatus == BRepMesh_GeomTool::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::Segment& aSeg = aWireSegments1->Value(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;
}
Standard_Mutex::Sentry aSentry(myMutex);
*myStatus = BRepMesh_SelfIntersectingWire;
return;
}
}
}
}
}