mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-09-03 14:10:33 +03:00
Compare commits
14 Commits
V7_8_1
...
CR0_v720_F
Author | SHA1 | Date | |
---|---|---|---|
|
fdbfdb571a | ||
|
8c8ccd1d84 | ||
|
cadb9817be | ||
|
b17bbb8566 | ||
|
48a3db93cf | ||
|
570c74d4f7 | ||
|
4dff80e12a | ||
|
8289ec43e5 | ||
|
eea519f643 | ||
|
efb8681bfc | ||
|
34b2e62bd6 | ||
|
8c2adc035d | ||
|
a829053aed | ||
|
f109d88899 |
@@ -68,6 +68,7 @@ FILE_TO_LIST ("adm/RESOURCES" RESOURCES)
|
||||
foreach (CurrentResource ${RESOURCES})
|
||||
get_filename_component (CurrentResource_FileName "${CurrentResource}" NAME)
|
||||
if ("${CurrentResource_FileName}" STREQUAL TObj.msg OR
|
||||
"${CurrentResource_FileName}" STREQUAL BOPAlgo.msg OR
|
||||
"${CurrentResource_FileName}" STREQUAL Units.dat OR
|
||||
"${CurrentResource}" STREQUAL XSMessage OR
|
||||
"${CurrentResource}" STREQUAL SHMessage OR
|
||||
|
@@ -67,3 +67,12 @@ Warning: Removal of internal boundaries among Faces has failed
|
||||
|
||||
.BOPAlgo_AlertRemovalOfIBForEdgesFailed
|
||||
Warning: Removal of internal boundaries among Edges has failed
|
||||
|
||||
.BOPAlgo_AlertIntersectionOfPairOfShapesFailed
|
||||
Warning: Intersection of pair of shapes has failed
|
||||
|
||||
.BOPAlgo_AlertBuildingPCurveFailed
|
||||
Warning: Building 2D curve of edge on face has failed
|
||||
|
||||
.BOPAlgo_AlertAcquiredSelfIntersection
|
||||
Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered
|
||||
|
@@ -78,4 +78,14 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertShellSplitterFailed)
|
||||
//! Some edges are too small and have no valid range
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertTooSmallEdge)
|
||||
|
||||
//! Intersection of pair of shapes has failed
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertIntersectionOfPairOfShapesFailed)
|
||||
|
||||
//! Building 2D curve of edge on face has failed
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertBuildingPCurveFailed)
|
||||
|
||||
//! Some sub-shapes of some of the argument become connected through
|
||||
//! other shapes and the argument became self-interfered
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertAcquiredSelfIntersection)
|
||||
|
||||
#endif // _BOPAlgo_Alerts_HeaderFile
|
||||
|
@@ -69,4 +69,13 @@ static const char BOPAlgo_BOPAlgo_msg[] =
|
||||
"Warning: Removal of internal boundaries among Faces has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertRemovalOfIBForEdgesFailed\n"
|
||||
"Warning: Removal of internal boundaries among Edges has failed\n";
|
||||
"Warning: Removal of internal boundaries among Edges has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertIntersectionOfPairOfShapesFailed\n"
|
||||
"Warning: Intersection of pair of shapes has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertBuildingPCurveFailed\n"
|
||||
"Warning: Building 2D curve of edge on face has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertAcquiredSelfIntersection\n"
|
||||
"Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered\n";
|
||||
|
@@ -294,6 +294,8 @@ void BOPAlgo_PaveFiller::PerformInternal()
|
||||
//
|
||||
UpdateBlocksWithSharedVertices();
|
||||
//
|
||||
myDS->RefineFaceInfoIn();
|
||||
//
|
||||
MakeSplitEdges();
|
||||
if (HasErrors()) {
|
||||
return;
|
||||
|
@@ -87,13 +87,19 @@ class TopoDS_Face;
|
||||
//! - *Gluing options* - allows to speed up the calculation on the special
|
||||
//! cases, in which some sub-shapes are coincide.<br>
|
||||
//!
|
||||
//! The algorithm returns the following Warning statuses:<br>
|
||||
//! - *BOPAlgo_AlertSelfInterferingShape* - in case some of the argument shapes are self-interfering shapes;<br>
|
||||
//! - *BOPAlgo_AlertTooSmallEdge* - in case some edges of the input shapes have no valid range;<br>
|
||||
//! The algorithm returns the following Warning statuses:
|
||||
//! - *BOPAlgo_AlertSelfInterferingShape* - in case some of the argument shapes are self-interfering shapes;
|
||||
//! - *BOPAlgo_AlertTooSmallEdge* - in case some edges of the input shapes have no valid range;
|
||||
//! - *BOPAlgo_AlertNotSplittableEdge* - in case some edges of the input shapes has such a small
|
||||
//! valid range so it cannot be split;<br>
|
||||
//! valid range so it cannot be split;
|
||||
//! - *BOPAlgo_AlertBadPositioning* - in case the positioning of the input shapes leads to creation
|
||||
//! of small edges.<br>
|
||||
//! of small edges;
|
||||
//! - *BOPAlgo_AlertIntersectionOfPairOfShapesFailed* - in case intersection of some of the
|
||||
//! sub-shapes has failed;
|
||||
//! - *BOPAlgo_AlertAcquiredSelfIntersection* - in case some sub-shapes of the argument become connected
|
||||
//! through other shapes;
|
||||
//! - *BOPAlgo_AlertBuildingPCurveFailed* - in case building 2D curve for some of the edges
|
||||
//! on the faces has failed.
|
||||
//!
|
||||
//! The algorithm returns the following Error alerts:
|
||||
//! - *BOPAlgo_AlertTooFewArguments* - in case there are no enough arguments to
|
||||
@@ -290,6 +296,7 @@ protected:
|
||||
BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDMExEdges,
|
||||
BOPCol_DataMapOfIntegerInteger& theDMNewSD,
|
||||
const BOPCol_IndexedMapOfShape& theMicroEdges,
|
||||
const BOPCol_IndexedMapOfShape& theVertsOnRejectedPB,
|
||||
const BOPCol_BaseAllocator& theAllocator);
|
||||
|
||||
Standard_EXPORT void FindPaveBlocks (const Standard_Integer theV, const Standard_Integer theF, BOPDS_ListOfPaveBlock& theLPB);
|
||||
@@ -474,6 +481,8 @@ protected:
|
||||
//! In case self-interference is found the warning is added.
|
||||
Standard_EXPORT void CheckSelfInterference();
|
||||
|
||||
//! Adds the warning about failed intersection of pair of sub-shapes
|
||||
Standard_EXPORT void AddIntersectionFailedWarning(const TopoDS_Shape& theS1, const TopoDS_Shape& theS2);
|
||||
|
||||
BOPCol_ListOfShape myArguments;
|
||||
BOPDS_PDS myDS;
|
||||
|
@@ -112,7 +112,8 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
|
||||
}
|
||||
//
|
||||
if (aLE.Extent() > 1) {
|
||||
// Add warning
|
||||
// Add the acquired self-interference warning:
|
||||
// The same common block contains several edges from one argument
|
||||
TopoDS_Compound aWC;
|
||||
aBB.MakeCompound(aWC);
|
||||
//
|
||||
@@ -122,7 +123,7 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
|
||||
aBB.Add(aWC, aE1);
|
||||
}
|
||||
//
|
||||
AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
|
||||
AddWarning (new BOPAlgo_AlertAcquiredSelfIntersection (aWC));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,7 +169,8 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
|
||||
for (j = 1; j <= aNbC; ++j) {
|
||||
const BOPCol_IndexedMapOfShape& aMCS = aMCSI(j);
|
||||
if (aMCS.Extent() > 1) {
|
||||
// Add self-interference warning
|
||||
// Add acquired self-interference warning:
|
||||
// Several faces from one argument contain the same vertex or edge
|
||||
TopoDS_Compound aWC;
|
||||
aBB.MakeCompound(aWC);
|
||||
//
|
||||
@@ -177,7 +179,7 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
|
||||
const TopoDS_Shape& aSx = aMCS(iS);
|
||||
aBB.Add(aWC, aSx);
|
||||
}
|
||||
AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
|
||||
AddWarning (new BOPAlgo_AlertAcquiredSelfIntersection (aWC));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
#include <BOPAlgo_PaveFiller.hxx>
|
||||
#include <BOPAlgo_Alerts.hxx>
|
||||
#include <BOPAlgo_Tools.hxx>
|
||||
#include <BOPCol_NCVector.hxx>
|
||||
#include <BOPCol_Parallel.hxx>
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <BOPDS_PaveBlock.hxx>
|
||||
#include <BOPDS_VectorOfInterfVE.hxx>
|
||||
#include <BOPTools_AlgoTools.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <IntTools_Context.hxx>
|
||||
@@ -110,7 +112,16 @@ class BOPAlgo_VertexEdge : public BOPAlgo_Algo {
|
||||
//
|
||||
virtual void Perform() {
|
||||
BOPAlgo_Algo::UserBreak();
|
||||
myFlag=myContext->ComputeVE (myV, myE, myT, myTolVNew, myFuzzyValue);
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
myFlag=myContext->ComputeVE (myV, myE, myT, myTolVNew, myFuzzyValue);
|
||||
}
|
||||
catch (Standard_Failure)
|
||||
{
|
||||
AddError(new BOPAlgo_AlertIntersectionFailed);
|
||||
}
|
||||
};
|
||||
//
|
||||
protected:
|
||||
@@ -267,6 +278,11 @@ void BOPAlgo_PaveFiller::IntersectVE
|
||||
for (i = 0; i < aNbVE; ++i) {
|
||||
const BOPAlgo_VertexEdge& aVESolver = aVVE(i);
|
||||
if (aVESolver.Flag() != 0) {
|
||||
if (aVESolver.HasErrors())
|
||||
{
|
||||
// Warn about failed intersection of sub-shapes
|
||||
AddIntersectionFailedWarning(aVESolver.Vertex(), aVESolver.Edge());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//
|
||||
@@ -491,3 +507,19 @@ void BOPAlgo_PaveFiller::SplitPaveBlocks(const BOPCol_MapOfInteger& theMEdges,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function: AddIntersectionFailedWarning
|
||||
// purpose:
|
||||
//=======================================================================
|
||||
void BOPAlgo_PaveFiller::AddIntersectionFailedWarning(const TopoDS_Shape& theS1,
|
||||
const TopoDS_Shape& theS2)
|
||||
{
|
||||
// Create the warn shape
|
||||
TopoDS_Compound aWC;
|
||||
BRep_Builder().MakeCompound(aWC);
|
||||
BRep_Builder().Add(aWC, theS1);
|
||||
BRep_Builder().Add(aWC, theS2);
|
||||
// Add the warning
|
||||
AddWarning(new BOPAlgo_AlertIntersectionOfPairOfShapesFailed(aWC));
|
||||
}
|
@@ -93,7 +93,16 @@ class BOPAlgo_EdgeEdge :
|
||||
//
|
||||
virtual void Perform() {
|
||||
BOPAlgo_Algo::UserBreak();
|
||||
IntTools_EdgeEdge::Perform();
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
IntTools_EdgeEdge::Perform();
|
||||
}
|
||||
catch (Standard_Failure)
|
||||
{
|
||||
AddError(new BOPAlgo_AlertIntersectionFailed);
|
||||
}
|
||||
}
|
||||
//
|
||||
protected:
|
||||
@@ -229,7 +238,11 @@ void BOPAlgo_PaveFiller::PerformEE()
|
||||
Bnd_Box aBB1, aBB2;
|
||||
//
|
||||
BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge(k);
|
||||
if (!anEdgeEdge.IsDone()) {
|
||||
if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors()) {
|
||||
// Warn about failed intersection of sub-shapes
|
||||
const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
|
||||
const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
|
||||
AddIntersectionFailedWarning(aE1, aE2);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
#include <BOPAlgo_PaveFiller.hxx>
|
||||
#include <BOPAlgo_Alerts.hxx>
|
||||
#include <BOPAlgo_SectionAttribute.hxx>
|
||||
#include <BOPCol_MapOfInteger.hxx>
|
||||
#include <BOPCol_NCVector.hxx>
|
||||
@@ -107,7 +108,16 @@ class BOPAlgo_VertexFace : public BOPAlgo_Algo {
|
||||
//
|
||||
virtual void Perform() {
|
||||
BOPAlgo_Algo::UserBreak();
|
||||
myFlag=myContext->ComputeVF(myV, myF, myT1, myT2, myTolVNew, myFuzzyValue);
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
myFlag=myContext->ComputeVF(myV, myF, myT1, myT2, myTolVNew, myFuzzyValue);
|
||||
}
|
||||
catch (Standard_Failure)
|
||||
{
|
||||
AddError(new BOPAlgo_AlertIntersectionFailed);
|
||||
}
|
||||
}
|
||||
//
|
||||
protected:
|
||||
@@ -212,7 +222,12 @@ void BOPAlgo_PaveFiller::PerformVF()
|
||||
const BOPAlgo_VertexFace& aVertexFace=aVVF(k);
|
||||
//
|
||||
iFlag=aVertexFace.Flag();
|
||||
if (iFlag) {
|
||||
if (iFlag != 0) {
|
||||
if (aVertexFace.HasErrors())
|
||||
{
|
||||
// Warn about failed intersection of sub-shapes
|
||||
AddIntersectionFailedWarning(aVertexFace.Vertex(), aVertexFace.Face());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//
|
||||
|
@@ -103,7 +103,16 @@ class BOPAlgo_EdgeFace :
|
||||
//
|
||||
virtual void Perform() {
|
||||
BOPAlgo_Algo::UserBreak();
|
||||
IntTools_EdgeFace::Perform();
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
IntTools_EdgeFace::Perform();
|
||||
}
|
||||
catch (Standard_Failure)
|
||||
{
|
||||
AddError(new BOPAlgo_AlertIntersectionFailed);
|
||||
}
|
||||
}
|
||||
//
|
||||
protected:
|
||||
@@ -258,7 +267,9 @@ void BOPAlgo_PaveFiller::PerformEF()
|
||||
//
|
||||
for (k=0; k < aNbEdgeFace; ++k) {
|
||||
BOPAlgo_EdgeFace& aEdgeFace=aVEdgeFace(k);
|
||||
if (!aEdgeFace.IsDone()) {
|
||||
if (!aEdgeFace.IsDone() || aEdgeFace.HasErrors()) {
|
||||
// Warn about failed intersection of sub-shapes
|
||||
AddIntersectionFailedWarning(aEdgeFace.Edge(), aEdgeFace.Face());
|
||||
continue;
|
||||
}
|
||||
//
|
||||
|
@@ -144,7 +144,16 @@ class BOPAlgo_FaceFace :
|
||||
//
|
||||
virtual void Perform() {
|
||||
BOPAlgo_Algo::UserBreak();
|
||||
IntTools_FaceFace::Perform(myF1, myF2);
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
IntTools_FaceFace::Perform(myF1, myF2);
|
||||
}
|
||||
catch (Standard_Failure)
|
||||
{
|
||||
AddError(new BOPAlgo_AlertIntersectionFailed);
|
||||
}
|
||||
}
|
||||
//
|
||||
protected:
|
||||
@@ -263,10 +272,12 @@ void BOPAlgo_PaveFiller::PerformFF()
|
||||
for (k = 0; k < aNbFaceFace; ++k) {
|
||||
BOPAlgo_FaceFace& aFaceFace = aVFaceFace(k);
|
||||
aFaceFace.Indices(nF1, nF2);
|
||||
if (!aFaceFace.IsDone()) {
|
||||
if (!aFaceFace.IsDone() || aFaceFace.HasErrors()) {
|
||||
BOPDS_InterfFF& aFF = aFFs.Append1();
|
||||
aFF.SetIndices(nF1, nF2);
|
||||
aFF.Init(0, 0);
|
||||
// Warn about failed intersection of faces
|
||||
AddIntersectionFailedWarning(aFaceFace.Face1(), aFaceFace.Face2());
|
||||
continue;
|
||||
}
|
||||
//
|
||||
@@ -373,6 +384,7 @@ void BOPAlgo_PaveFiller::MakeBlocks()
|
||||
BOPCol_DataMapOfIntegerListOfInteger aDMBV(100, aAllocator);
|
||||
BOPCol_DataMapIteratorOfDataMapOfIntegerReal aItMV;
|
||||
BOPCol_IndexedMapOfShape aMicroEdges(100, aAllocator);
|
||||
BOPCol_IndexedMapOfShape aVertsOnRejectedPB;
|
||||
//
|
||||
for (i=0; i<aNbFF; ++i) {
|
||||
//
|
||||
@@ -557,6 +569,19 @@ void BOPAlgo_PaveFiller::MakeBlocks()
|
||||
if (!bInBothFaces) {
|
||||
aMPBAdd.Add(aPBOut);
|
||||
PreparePostTreatFF(i, j, aPBOut, aMSCPB, aMVI, aLPBC);
|
||||
// Try fusing the vertices of the existing pave block
|
||||
// with the vertices put on the real section curve (except
|
||||
// for technological vertices, which will be removed)
|
||||
Standard_Integer nVOut1, nVOut2;
|
||||
aPBOut->Indices(nVOut1, nVOut2);
|
||||
if (nV1 != nVOut1 && nV1 != nVOut2 && !aMVBounds.Contains(nV1))
|
||||
{
|
||||
aVertsOnRejectedPB.Add(aV1);
|
||||
}
|
||||
if (nV2 != nVOut1 && nV2 != nVOut2 && !aMVBounds.Contains(nV2))
|
||||
{
|
||||
aVertsOnRejectedPB.Add(aV2);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -639,7 +664,7 @@ void BOPAlgo_PaveFiller::MakeBlocks()
|
||||
//
|
||||
// post treatment
|
||||
MakeSDVerticesFF(aDMVLV, aDMNewSD);
|
||||
PostTreatFF(aMSCPB, aDMExEdges, aDMNewSD, aMicroEdges, aAllocator);
|
||||
PostTreatFF(aMSCPB, aDMExEdges, aDMNewSD, aMicroEdges, aVertsOnRejectedPB, aAllocator);
|
||||
if (HasErrors()) {
|
||||
return;
|
||||
}
|
||||
@@ -697,6 +722,7 @@ void BOPAlgo_PaveFiller::PostTreatFF
|
||||
BOPDS_DataMapOfPaveBlockListOfPaveBlock& aDMExEdges,
|
||||
BOPCol_DataMapOfIntegerInteger& aDMNewSD,
|
||||
const BOPCol_IndexedMapOfShape& theMicroEdges,
|
||||
const BOPCol_IndexedMapOfShape& theVertsOnRejectedPB,
|
||||
const Handle(NCollection_BaseAllocator)& theAllocator)
|
||||
{
|
||||
Standard_Integer aNbS = theMSCPB.Extent();
|
||||
@@ -724,8 +750,9 @@ void BOPAlgo_PaveFiller::PostTreatFF
|
||||
BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
|
||||
//
|
||||
Standard_Integer aNbME = theMicroEdges.Extent();
|
||||
Standard_Integer aNbVOnRPB = theVertsOnRejectedPB.Extent();
|
||||
// 0
|
||||
if (aNbS==1 && (aNbME == 0)) {
|
||||
if (aNbS==1 && (aNbME == 0) && (aNbVOnRPB == 0)) {
|
||||
const TopoDS_Shape& aS=theMSCPB.FindKey(1);
|
||||
const BOPDS_CoupleOfPaveBlocks &aCPB=theMSCPB.FindFromIndex(1);
|
||||
//
|
||||
@@ -824,6 +851,20 @@ void BOPAlgo_PaveFiller::PostTreatFF
|
||||
aBB.UpdateVertex(aVerts[1], aTolV2 + aDist);
|
||||
}
|
||||
}
|
||||
|
||||
// Add vertices put on the real section curves to unify them with the
|
||||
// vertices of the edges, by which these sections curves have been rejected
|
||||
for (Standard_Integer i = 1; i <= aNbVOnRPB; ++i)
|
||||
{
|
||||
TopoDS_Shape aVer = theVertsOnRejectedPB(i);
|
||||
Standard_Integer iVer = myDS->Index(aVer);
|
||||
const Standard_Integer* pSD = aDMNewSD.Seek(iVer);
|
||||
if (pSD)
|
||||
aVer = myDS->Shape(*pSD);
|
||||
|
||||
if (anAddedSD.Add(aVer))
|
||||
aLS.Append(aVer);
|
||||
}
|
||||
//
|
||||
// 2 Fuse shapes
|
||||
aPF.SetProgressIndicator(myProgressIndicator);
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <BOPAlgo_PaveFiller.hxx>
|
||||
#include <BOPAlgo_Alerts.hxx>
|
||||
#include <BOPAlgo_SectionAttribute.hxx>
|
||||
#include <BOPAlgo_Tools.hxx>
|
||||
#include <BOPCol_IndexedMapOfShape.hxx>
|
||||
@@ -241,28 +242,37 @@ class BOPAlgo_MPC : public BOPAlgo_Algo {
|
||||
}
|
||||
//
|
||||
virtual void Perform() {
|
||||
Standard_Integer iErr;
|
||||
//
|
||||
iErr=1;
|
||||
if (!myEz.IsNull()) {
|
||||
TopoDS_Edge aSpz;
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
Standard_Integer iErr;
|
||||
//
|
||||
BOPTools_AlgoTools::MakeSplitEdge(myEz,myV1, myT1,
|
||||
myV2, myT2, aSpz);
|
||||
iErr=1;
|
||||
if (!myEz.IsNull()) {
|
||||
TopoDS_Edge aSpz;
|
||||
//
|
||||
BOPTools_AlgoTools::MakeSplitEdge(myEz,myV1, myT1,
|
||||
myV2, myT2, aSpz);
|
||||
//
|
||||
iErr=
|
||||
BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz,
|
||||
myE,
|
||||
myF,
|
||||
myContext);
|
||||
}
|
||||
//
|
||||
iErr=
|
||||
BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz,
|
||||
myE,
|
||||
myF,
|
||||
myContext);
|
||||
if (iErr) {
|
||||
BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF, myContext);
|
||||
}
|
||||
//
|
||||
if (myFlag) {
|
||||
UpdateVertices(myE, myF);
|
||||
}
|
||||
}
|
||||
//
|
||||
if (iErr) {
|
||||
BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF, myContext);
|
||||
}
|
||||
//
|
||||
if (myFlag) {
|
||||
UpdateVertices(myE, myF);
|
||||
catch (Standard_Failure)
|
||||
{
|
||||
AddError(new BOPAlgo_AlertBuildingPCurveFailed(TopoDS_Shape()));
|
||||
}
|
||||
}
|
||||
//
|
||||
@@ -676,6 +686,20 @@ void BOPAlgo_PaveFiller::MakePCurves()
|
||||
//======================================================
|
||||
BOPAlgo_MPCCnt::Perform(myRunParallel, aVMPC, myContext);
|
||||
//======================================================
|
||||
|
||||
// Add warnings of the failed projections
|
||||
Standard_Integer aNb = aVMPC.Extent();
|
||||
for (i = 0; i < aNb; ++i)
|
||||
{
|
||||
if (aVMPC(i).HasErrors())
|
||||
{
|
||||
TopoDS_Compound aWC;
|
||||
BRep_Builder().MakeCompound(aWC);
|
||||
BRep_Builder().Add(aWC, aVMPC(i).Edge());
|
||||
BRep_Builder().Add(aWC, aVMPC(i).Face());
|
||||
AddWarning(new BOPAlgo_AlertBuildingPCurveFailed(aWC));
|
||||
}
|
||||
}
|
||||
}
|
||||
//=======================================================================
|
||||
//function : UpdateVertices
|
||||
|
@@ -1418,6 +1418,44 @@ void BOPDS_DS::RefineFaceInfoOn()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : RefineFaceInfoIn
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BOPDS_DS::RefineFaceInfoIn()
|
||||
{
|
||||
for (Standard_Integer i = 0; i < myNbSourceShapes; ++i)
|
||||
{
|
||||
const BOPDS_ShapeInfo& aSI = ShapeInfo(i);
|
||||
if (aSI.ShapeType() != TopAbs_FACE)
|
||||
continue;
|
||||
|
||||
if (!aSI.HasReference())
|
||||
continue;
|
||||
|
||||
BOPDS_FaceInfo& aFI = ChangeFaceInfo(i);
|
||||
|
||||
const BOPDS_IndexedMapOfPaveBlock& aMPBOn = aFI.PaveBlocksOn();
|
||||
BOPDS_IndexedMapOfPaveBlock& aMPBIn = aFI.ChangePaveBlocksIn();
|
||||
|
||||
if (aMPBIn.IsEmpty() || aMPBOn.IsEmpty())
|
||||
continue;
|
||||
|
||||
BOPDS_IndexedMapOfPaveBlock aMPBInNew;
|
||||
|
||||
const Standard_Integer aNbPBIn = aMPBIn.Extent();
|
||||
for (Standard_Integer j = 1; j <= aNbPBIn; ++j)
|
||||
{
|
||||
if (!aMPBOn.Contains(aMPBIn(j)))
|
||||
aMPBInNew.Add(aMPBIn(j));
|
||||
}
|
||||
|
||||
if (aMPBInNew.Extent() < aNbPBIn)
|
||||
aMPBIn = aMPBInNew;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AloneVertices
|
||||
//purpose :
|
||||
|
@@ -302,6 +302,9 @@ Standard_EXPORT virtual ~BOPDS_DS();
|
||||
//! ++
|
||||
Standard_EXPORT void RefineFaceInfoOn();
|
||||
|
||||
//! Removes faces with state ON from the
|
||||
//! list of IN-faces
|
||||
Standard_EXPORT void RefineFaceInfoIn();
|
||||
|
||||
//! Returns information about ON/IN subshapes of the given faces.
|
||||
//! @param theMVOnIn the indices of ON/IN vertices from both faces
|
||||
|
@@ -235,6 +235,8 @@ Standard_Integer bopcheck (Draw_Interpretor& di,
|
||||
//
|
||||
aTimer.Stop();
|
||||
//
|
||||
BOPTest::ReportAlerts(aChecker);
|
||||
//
|
||||
iErr=aChecker.HasErrors();
|
||||
//
|
||||
const BOPDS_DS& aDS=*(aChecker.PDS());
|
||||
|
@@ -46,6 +46,7 @@
|
||||
#include <GeomAdaptor_HSurface.hxx>
|
||||
#include <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomInt.hxx>
|
||||
#include <GeomLib.hxx>
|
||||
#include <GeomProjLib.hxx>
|
||||
#include <gp.hxx>
|
||||
#include <gp_Cylinder.hxx>
|
||||
@@ -667,12 +668,25 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace
|
||||
}
|
||||
//
|
||||
TolReached2d=aTolR;
|
||||
//
|
||||
|
||||
// Adjust curve for periodic surface
|
||||
Handle(Geom2d_Curve) aC2DA;
|
||||
BOPTools_AlgoTools2D::AdjustPCurveOnSurf (*pBAS, aT1, aT2, aC2D, aC2DA);
|
||||
//
|
||||
aC2D=aC2DA;
|
||||
//
|
||||
aC2D = aC2DA;
|
||||
|
||||
// Make sure that the range of the 2D curve is sufficient for representation of the 3D curve.
|
||||
Standard_Real aTCFirst = aC2D->FirstParameter();
|
||||
Standard_Real aTCLast = aC2D->LastParameter();
|
||||
if ((aTCFirst - aT1) > Precision::PConfusion() ||
|
||||
(aT2 - aTCLast ) > Precision::PConfusion())
|
||||
{
|
||||
if (aTCFirst < aT1) aTCFirst = aT1;
|
||||
if (aTCLast > aT2) aTCLast = aT2;
|
||||
|
||||
GeomLib::SameRange(Precision::PConfusion(), aC2D,
|
||||
aTCFirst, aTCLast, aT1, aT2, aC2D);
|
||||
}
|
||||
|
||||
// compute the appropriate tolerance for the edge
|
||||
Handle(Geom_Surface) aS = pBAS->Surface().Surface();
|
||||
aS = Handle(Geom_Surface)::DownCast(aS->Transformed(pBAS->Trsf()));
|
||||
|
@@ -102,40 +102,6 @@ static Standard_Boolean UpdateMap(const TopoDS_Shape& theKey,
|
||||
return !found;
|
||||
}
|
||||
|
||||
static void ReverseModifiedEdges(TopoDS_Shape& aShape,
|
||||
TopTools_MapOfShape& Emap)
|
||||
{
|
||||
TopExp_Explorer Explo(aShape, TopAbs_FACE);
|
||||
BRep_Builder BB;
|
||||
|
||||
for (; Explo.More(); Explo.Next())
|
||||
{
|
||||
TopoDS_Shape aFace = Explo.Current();
|
||||
TopoDS_Iterator itf(aFace);
|
||||
for (; itf.More(); itf.Next())
|
||||
{
|
||||
TopoDS_Shape aWire = itf.Value();
|
||||
TopTools_ListOfShape Ledges;
|
||||
TopoDS_Iterator itw(aWire);
|
||||
for (; itw.More(); itw.Next())
|
||||
Ledges.Append(itw.Value());
|
||||
|
||||
aWire.Free(Standard_True);
|
||||
TopTools_ListIteratorOfListOfShape itl(Ledges);
|
||||
for (; itl.More(); itl.Next())
|
||||
BB.Remove(aWire, itl.Value());
|
||||
|
||||
for (itl.Initialize(Ledges); itl.More(); itl.Next())
|
||||
{
|
||||
TopoDS_Shape anEdge = itl.Value();
|
||||
if (Emap.Contains(anEdge))
|
||||
anEdge.Reverse();
|
||||
BB.Add(aWire, anEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateTolFromTopOrBottomPCurve(const TopoDS_Face& aFace,
|
||||
TopoDS_Edge& anEdge)
|
||||
{
|
||||
@@ -739,9 +705,6 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
|
||||
result = MkSw.Shape();
|
||||
UpdateMap(TheS.Located(myProfile.Location()), result, myGenMap);
|
||||
myErrorOnSurf = MkSw.ErrorOnSurface();
|
||||
//Correct <myFirst> and <myLast>
|
||||
ReverseModifiedEdges(myFirst, myReversedEdges);
|
||||
ReverseModifiedEdges(myLast, myReversedEdges);
|
||||
|
||||
// Labeling of elements
|
||||
if (mySections.IsNull()) {
|
||||
|
@@ -583,28 +583,15 @@ void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
|
||||
//=======================================================================
|
||||
void BRepFill_PipeShell::DeleteProfile(const TopoDS_Shape& Profile)
|
||||
{
|
||||
Standard_Boolean isVertex = (Profile.ShapeType() == TopAbs_VERTEX);
|
||||
|
||||
Standard_Boolean Trouve=Standard_False;
|
||||
Standard_Integer ii;
|
||||
for (ii=1; ii<=mySeq.Length() && !Trouve; ii++) {
|
||||
Standard_Boolean found = Standard_False;
|
||||
const TopoDS_Wire& aWire = mySeq.Value(ii).Wire();
|
||||
if (isVertex)
|
||||
{
|
||||
TopExp_Explorer Explo(aWire, TopAbs_VERTEX);
|
||||
for (; Explo.More(); Explo.Next())
|
||||
if (Profile.IsSame(Explo.Current()))
|
||||
found = Standard_True;
|
||||
}
|
||||
else if (Profile.IsSame(aWire))
|
||||
found = Standard_True;
|
||||
|
||||
if (found)
|
||||
{
|
||||
Trouve = Standard_True;
|
||||
mySeq.Remove(ii);
|
||||
}
|
||||
const TopoDS_Shape& aSection = mySeq.Value(ii).OriginalShape();
|
||||
if (Profile.IsSame(aSection))
|
||||
{
|
||||
Trouve = Standard_True;
|
||||
mySeq.Remove(ii);
|
||||
}
|
||||
}
|
||||
|
||||
if (Trouve) mySection.Nullify();
|
||||
@@ -705,7 +692,7 @@ void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
|
||||
//function : Build
|
||||
//purpose : Construct the Shell and the history
|
||||
//=======================================================================
|
||||
Standard_Boolean BRepFill_PipeShell::Build()
|
||||
Standard_Boolean BRepFill_PipeShell::Build()
|
||||
{
|
||||
Standard_Boolean Ok;
|
||||
Standard_Real FirstS, LastS;
|
||||
@@ -759,8 +746,9 @@ void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
|
||||
MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
|
||||
MkSw.SetAngularControl(angmin, angmax);
|
||||
MkSw.SetForceApproxC1(myForceApproxC1);
|
||||
MkSw.SetBounds(TopoDS::Wire(myFirst),
|
||||
TopoDS::Wire(myLast));
|
||||
MkSw.SetBounds(TopoDS::Wire(myFirst),
|
||||
TopoDS::Wire(myLast));
|
||||
|
||||
GeomAbs_Shape theContinuity = GeomAbs_C2;
|
||||
if (myTrihedron == GeomFill_IsDiscreteTrihedron)
|
||||
theContinuity = GeomAbs_C0;
|
||||
@@ -914,13 +902,9 @@ const TopoDS_Shape& BRepFill_PipeShell::LastShape() const
|
||||
//function : Generated
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
// void BRepFill_PipeShell::Generated(const TopoDS_Shape& ,
|
||||
// TopTools_ListOfShape& )
|
||||
void BRepFill_PipeShell::Generated(const TopoDS_Shape& theShape,
|
||||
TopTools_ListOfShape& theList)
|
||||
{
|
||||
// throw Standard_NotImplemented("Generated:Pas Fait");
|
||||
|
||||
theList.Clear();
|
||||
|
||||
if(myGenMap.IsBound(theShape)) {
|
||||
@@ -1197,9 +1181,6 @@ void BRepFill_PipeShell::Place(const BRepFill_Section& Sec,
|
||||
Sec.WithCorrection());
|
||||
TopoDS_Wire TmpWire = Sec.Wire();
|
||||
aTrsf = Place.Transformation();
|
||||
//TopLoc_Location Loc2(Place.Transformation()), Loc1;
|
||||
//Loc1 = TmpWire.Location();
|
||||
//W.Location(Loc2.Multiplied(Loc1));
|
||||
//Transform the copy
|
||||
W = TopoDS::Wire(BRepBuilderAPI_Transform(TmpWire, aTrsf, Standard_True));
|
||||
////////////////////////////////////
|
||||
@@ -1240,37 +1221,40 @@ void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep)
|
||||
TopoDS_Iterator itw;
|
||||
for (indw = 1; indw <= mySeq.Length(); indw++)
|
||||
{
|
||||
const TopoDS_Wire& aSection = mySeq(indw).Wire();
|
||||
const TopoDS_Shape& Section = mySeq(indw).OriginalShape();
|
||||
TopoDS_Wire aSection;
|
||||
Standard_Boolean IsPunctual = mySeq(indw).IsPunctual();
|
||||
if (IsPunctual)
|
||||
{
|
||||
//for punctual sections (first or last)
|
||||
//we take all the wires generated along the path
|
||||
TopExp_Explorer Explo(aSection, TopAbs_VERTEX);
|
||||
const TopoDS_Shape& VerSection = Explo.Current();
|
||||
|
||||
TopTools_ListOfShape Elist;
|
||||
for (Standard_Integer i = 1; i <= anUEdges->UpperRow(); i++)
|
||||
for (Standard_Integer j = 1; j <= anUEdges->UpperCol(); j++)
|
||||
Elist.Append(anUEdges->Value(i,j));
|
||||
myGenMap.Bind(VerSection, Elist);
|
||||
myGenMap.Bind(Section, Elist);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
aSection = TopoDS::Wire(Section);
|
||||
//Take the real index of section on the path
|
||||
Standard_Integer IndOfW = myIndOfSec(indw);
|
||||
const TopoDS_Wire& theWire = TopoDS::Wire(WSeq(IndOfW));
|
||||
BRepTools_WireExplorer wexp_sec(aSection);
|
||||
for (inde = 1; wexp_sec.More(); wexp_sec.Next())
|
||||
{
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge(wexp_sec.Current());
|
||||
const TopoDS_Edge& anOriginalEdge = TopoDS::Edge(wexp_sec.Current());
|
||||
TopoDS_Edge anEdge = TopoDS::Edge(mySeq(indw).ModifiedShape(anOriginalEdge));
|
||||
if (BRep_Tool::Degenerated(anEdge))
|
||||
continue;
|
||||
|
||||
TopoDS_Shell aShell;
|
||||
BB.MakeShell(aShell);
|
||||
TopoDS_Vertex aVertex [2];
|
||||
TopExp::Vertices(anEdge, aVertex[0], aVertex[1]);
|
||||
TopExp::Vertices(anOriginalEdge, aVertex[0], aVertex[1]);
|
||||
Standard_Integer SignOfAnEdge =
|
||||
(anEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
|
||||
(anOriginalEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
|
||||
|
||||
//For each non-degenerated inde-th edge of <aSection>
|
||||
//we find inde-th edge in <theWire>
|
||||
@@ -1422,7 +1406,7 @@ void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep)
|
||||
|
||||
TopTools_ListOfShape ListShell;
|
||||
ListShell.Append(aShell);
|
||||
myGenMap.Bind(anEdge, ListShell);
|
||||
myGenMap.Bind(anOriginalEdge, ListShell);
|
||||
////////////////////////
|
||||
|
||||
inde++;
|
||||
|
@@ -168,6 +168,10 @@ public:
|
||||
Standard_EXPORT void Simulate (const Standard_Integer NumberOfSection, TopTools_ListOfShape& Sections);
|
||||
|
||||
//! Builds the resulting shape (redefined from MakeShape).
|
||||
//! If theIsToCheckValidity == FALSE then BRepFill_Sweep algorithm
|
||||
//! is allowed to create invalid faces (having self-interferences).
|
||||
//! It is considered for them that such faces will be processed and
|
||||
//! fixed by the high-level algorithms
|
||||
Standard_EXPORT Standard_Boolean Build();
|
||||
|
||||
//! Transform the sweeping Shell in Solid.
|
||||
|
@@ -22,6 +22,9 @@
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <ShapeUpgrade_RemoveLocations.hxx>
|
||||
|
||||
BRepFill_Section::BRepFill_Section() :islaw(0),
|
||||
ispunctual(0),
|
||||
@@ -41,12 +44,19 @@ BRepFill_Section::BRepFill_Section(const TopoDS_Shape& Profile,
|
||||
contact(WithContact),
|
||||
correction(WithCorrection)
|
||||
{
|
||||
if (Profile.ShapeType() == TopAbs_WIRE)
|
||||
wire = TopoDS::Wire(Profile);
|
||||
else if (Profile.ShapeType() == TopAbs_VERTEX)
|
||||
myOriginalShape = Profile;
|
||||
|
||||
ShapeUpgrade_RemoveLocations RemLoc;
|
||||
RemLoc.SetRemoveLevel(TopAbs_COMPOUND);
|
||||
RemLoc.Remove(Profile);
|
||||
TopoDS_Shape aProfile = RemLoc.GetResult();
|
||||
|
||||
if (aProfile.ShapeType() == TopAbs_WIRE)
|
||||
wire = TopoDS::Wire(aProfile);
|
||||
else if (aProfile.ShapeType() == TopAbs_VERTEX)
|
||||
{
|
||||
ispunctual = Standard_True;
|
||||
TopoDS_Vertex aVertex = TopoDS::Vertex(Profile);
|
||||
TopoDS_Vertex aVertex = TopoDS::Vertex(aProfile);
|
||||
BRep_Builder BB;
|
||||
|
||||
TopoDS_Edge DegEdge;
|
||||
@@ -67,3 +77,58 @@ void BRepFill_Section::Set(const Standard_Boolean IsLaw)
|
||||
{
|
||||
islaw = IsLaw;
|
||||
}
|
||||
|
||||
TopoDS_Shape BRepFill_Section::ModifiedShape(const TopoDS_Shape& theShape) const
|
||||
{
|
||||
TopoDS_Shape aModifiedShape;
|
||||
|
||||
switch (theShape.ShapeType())
|
||||
{
|
||||
case TopAbs_WIRE:
|
||||
if (theShape.IsSame(myOriginalShape))
|
||||
aModifiedShape = wire;
|
||||
break;
|
||||
case TopAbs_EDGE:
|
||||
{
|
||||
TopoDS_Iterator itor(myOriginalShape);
|
||||
TopoDS_Iterator itw(wire);
|
||||
for (; itor.More(); itor.Next(),itw.Next())
|
||||
{
|
||||
const TopoDS_Shape& anOriginalEdge = itor.Value();
|
||||
const TopoDS_Shape& anEdge = itw.Value();
|
||||
if (anOriginalEdge.IsSame(theShape))
|
||||
{
|
||||
aModifiedShape = anEdge;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TopAbs_VERTEX:
|
||||
if (theShape.IsSame(myOriginalShape))
|
||||
{
|
||||
TopExp_Explorer Explo(wire, TopAbs_VERTEX);
|
||||
aModifiedShape = Explo.Current();
|
||||
}
|
||||
else
|
||||
{
|
||||
TopExp_Explorer ExpOrig(myOriginalShape, TopAbs_VERTEX);
|
||||
TopExp_Explorer ExpWire(wire, TopAbs_VERTEX);
|
||||
for (; ExpOrig.More(); ExpOrig.Next(),ExpWire.Next())
|
||||
{
|
||||
const TopoDS_Shape& anOriginalVertex = ExpOrig.Current();
|
||||
const TopoDS_Shape& aVertex = ExpWire.Current();
|
||||
if (anOriginalVertex.IsSame(theShape))
|
||||
{
|
||||
aModifiedShape = aVertex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return aModifiedShape;
|
||||
}
|
||||
|
@@ -43,10 +43,14 @@ public:
|
||||
|
||||
Standard_EXPORT void Set (const Standard_Boolean IsLaw);
|
||||
|
||||
const TopoDS_Shape& OriginalShape() const;
|
||||
|
||||
const TopoDS_Wire& Wire() const;
|
||||
|
||||
const TopoDS_Vertex& Vertex() const;
|
||||
|
||||
Standard_EXPORT TopoDS_Shape ModifiedShape(const TopoDS_Shape& theShape) const;
|
||||
|
||||
Standard_Boolean IsLaw() const;
|
||||
|
||||
Standard_Boolean IsPunctual() const;
|
||||
@@ -68,6 +72,7 @@ private:
|
||||
|
||||
|
||||
|
||||
TopoDS_Shape myOriginalShape;
|
||||
TopoDS_Wire wire;
|
||||
TopoDS_Vertex vertex;
|
||||
Standard_Boolean islaw;
|
||||
|
@@ -14,6 +14,11 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
inline const TopoDS_Shape& BRepFill_Section::OriginalShape() const
|
||||
{
|
||||
return myOriginalShape;
|
||||
}
|
||||
|
||||
inline const TopoDS_Wire& BRepFill_Section::Wire() const
|
||||
{
|
||||
return wire;
|
||||
|
@@ -366,6 +366,56 @@ static Standard_Boolean SameParameter(TopoDS_Edge& E,
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
static void CorrectSameParameter(TopoDS_Edge& theEdge,
|
||||
const TopoDS_Face& theFace1,
|
||||
const TopoDS_Face& theFace2)
|
||||
{
|
||||
if (BRep_Tool::Degenerated(theEdge))
|
||||
return;
|
||||
|
||||
Standard_Real fpar, lpar;
|
||||
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, fpar, lpar);
|
||||
|
||||
Standard_Boolean PCurveExists [2] = {Standard_False, Standard_False};
|
||||
BRepAdaptor_Curve BAcurve [2];
|
||||
|
||||
if (!theFace1.IsNull())
|
||||
{
|
||||
PCurveExists[0] = Standard_True;
|
||||
BAcurve[0].Initialize(theEdge, theFace1);
|
||||
}
|
||||
if (!theFace1.IsNull() &&
|
||||
theFace1.IsSame(theFace2))
|
||||
theEdge.Reverse();
|
||||
if (!theFace2.IsNull())
|
||||
{
|
||||
PCurveExists[1] = Standard_True;
|
||||
BAcurve[1].Initialize(theEdge, theFace2);
|
||||
}
|
||||
|
||||
Standard_Real MaxSqDist = 0.;
|
||||
const Standard_Integer NCONTROL = 23;
|
||||
Standard_Real delta = (lpar - fpar)/NCONTROL;
|
||||
|
||||
for (Standard_Integer i = 0; i <= NCONTROL; i++)
|
||||
{
|
||||
Standard_Real aParam = fpar + i*delta;
|
||||
gp_Pnt aPnt = aCurve->Value(aParam);
|
||||
for (Standard_Integer j = 0; j < 2; j++)
|
||||
if (PCurveExists[j])
|
||||
{
|
||||
gp_Pnt aPntFromFace = BAcurve[j].Value(aParam);
|
||||
Standard_Real aSqDist = aPnt.SquareDistance(aPntFromFace);
|
||||
if (aSqDist > MaxSqDist)
|
||||
MaxSqDist = aSqDist;
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Real aTol = sqrt(MaxSqDist);
|
||||
BRep_Builder BB;
|
||||
BB.UpdateEdge(theEdge, aTol);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//Objet : Orientate an edge of natural restriction
|
||||
// : General
|
||||
@@ -666,7 +716,7 @@ static TopoDS_Edge BuildEdge(Handle(Geom_Curve)& C3d,
|
||||
// P2 = BT.Pnt(VL);
|
||||
P2 = BRep_Tool::Pnt(VL);
|
||||
// Tol2 = BT.Tolerance(VF);
|
||||
Tol2 = BRep_Tool::Tolerance(VF);
|
||||
Tol2 = BRep_Tool::Tolerance(VL);
|
||||
Tol = Max(Tol1, Tol2);
|
||||
|
||||
if (VF.IsSame(VL) ||
|
||||
@@ -809,24 +859,44 @@ static Standard_Boolean Filling(const TopoDS_Shape& EF,
|
||||
Prof1 = BRep_Tool::Curve(E1, f1, l1);
|
||||
// Prof2 = BT.Curve(E2, f2, l2);
|
||||
Prof2 = BRep_Tool::Curve(E2, f2, l2);
|
||||
gp_Pnt P1, P2, P;
|
||||
gp_Pnt2d p1, p2;
|
||||
gp_Trsf Tf;
|
||||
Tf.SetTransformation(Axe);
|
||||
|
||||
// Choose the angle of opening
|
||||
P1 = Prof1->Value((f1+l1)/2);
|
||||
P2 = Prof2->Value((f2+l2)/2);
|
||||
P1.Transform(Tf);
|
||||
P2.Transform(Tf);
|
||||
p1.SetCoord(P1.Z(), P1.X());
|
||||
p2.SetCoord(P2.Z(), P2.X());
|
||||
gp_Vec2d v1(gp::Origin2d(), p1);
|
||||
gp_Vec2d v2(gp::Origin2d(), p2);
|
||||
if (v1.Magnitude() <= gp::Resolution() ||
|
||||
v2.Magnitude() <= gp::Resolution())
|
||||
// Indeed, both Prof1 and Prof2 are the same curves but in different positions
|
||||
|
||||
gp_Pnt P1, P2, P;
|
||||
|
||||
// Choose the angle of opening
|
||||
gp_Trsf aTf;
|
||||
aTf.SetTransformation(Axe);
|
||||
|
||||
// Choose the furthest point from the "center of revolution"
|
||||
// to provide correct angle measurement.
|
||||
const Standard_Real aPrm[] = {f1, 0.5*(f1 + l1), l1};
|
||||
const gp_Pnt aP1[] = {Prof1->Value(aPrm[0]).Transformed(aTf),
|
||||
Prof1->Value(aPrm[1]).Transformed(aTf),
|
||||
Prof1->Value(aPrm[2]).Transformed(aTf)};
|
||||
|
||||
Standard_Integer aMaxIdx = -1;
|
||||
Standard_Real aMaxDist = RealFirst();
|
||||
for (Standard_Integer i = 0; i < 3; i++)
|
||||
{
|
||||
const Standard_Real aDist = aP1[i].X()*aP1[i].X() + aP1[i].Z()*aP1[i].Z();
|
||||
if (aDist > aMaxDist)
|
||||
{
|
||||
aMaxDist = aDist;
|
||||
aMaxIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
const gp_Pnt aP2 = Prof2->Value(aPrm[aMaxIdx]).Transformed(aTf);
|
||||
const gp_Vec2d aV1(aP1[aMaxIdx].Z(), aP1[aMaxIdx].X());
|
||||
const gp_Vec2d aV2(aP2.Z(), aP2.X());
|
||||
if (aV1.SquareMagnitude() <= gp::Resolution() ||
|
||||
aV2.SquareMagnitude() <= gp::Resolution())
|
||||
{
|
||||
return Standard_False;
|
||||
Angle = v1.Angle(v2);
|
||||
}
|
||||
|
||||
Angle = aV1.Angle(aV2);
|
||||
|
||||
gp_Ax1 axe(Axe.Location(), Axe.YDirection());
|
||||
|
||||
@@ -837,14 +907,14 @@ static Standard_Boolean Filling(const TopoDS_Shape& EF,
|
||||
|
||||
Handle(Geom_SurfaceOfRevolution) Rev =
|
||||
new (Geom_SurfaceOfRevolution) (Prof1, axe);
|
||||
|
||||
|
||||
Handle(Geom_Surface) Surf =
|
||||
new (Geom_RectangularTrimmedSurface) (Rev, 0, Angle, f1, l1);
|
||||
|
||||
// Control the direction of the rotation
|
||||
Standard_Boolean ToReverseResult = Standard_False;
|
||||
gp_Vec d1u;
|
||||
d1u = Surf->DN(0, (f1+l1)/2, 1, 0);
|
||||
d1u = Surf->DN(0, aPrm[aMaxIdx], 1, 0);
|
||||
if (d1u.Angle(TangentOnPart1) > M_PI/2) { //Invert everything
|
||||
ToReverseResult = Standard_True;
|
||||
/*
|
||||
@@ -1135,19 +1205,40 @@ static Standard_Boolean Filling(const TopoDS_Shape& EF,
|
||||
B.MakeEdge(Aux2);
|
||||
|
||||
// Set the orientation
|
||||
gp_Vec D1U, D1V, N1, N2;
|
||||
C1->D0( (f1+l1)/2, P2d);
|
||||
Surf->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
|
||||
N1 = D1U^D1V;
|
||||
|
||||
// Provide correct normals computation
|
||||
// (the normal will be computed not in
|
||||
// singularity point definitely).
|
||||
Angle = RealFirst();
|
||||
for (Standard_Integer i = 0; i < 3; i++)
|
||||
{
|
||||
gp_Vec D1U, D1V, N1, N2;
|
||||
C1->D0(aPrm[i], P2d);
|
||||
Surf->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
|
||||
N1 = D1U^D1V;
|
||||
|
||||
if (N1.SquareMagnitude() < Precision::SquareConfusion())
|
||||
continue;
|
||||
|
||||
// C1 = BT.CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
|
||||
C1 = BRep_Tool::CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
|
||||
C1->D0(aPrm[i], P2d);
|
||||
Handle(BRepAdaptor_HSurface) AS = new BRepAdaptor_HSurface(TopoDS::Face(F1));
|
||||
AS->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
|
||||
N2 = D1U^D1V;
|
||||
|
||||
if (N2.SquareMagnitude() < Precision::SquareConfusion())
|
||||
continue;
|
||||
|
||||
Angle = N1.Angle(N2);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// C1 = BT.CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
|
||||
C1 = BRep_Tool::CurveOnSurface(E1, TopoDS::Face(F1), f2, l2);
|
||||
C1->D0( (f1+l1)/2, P2d);
|
||||
Handle(BRepAdaptor_HSurface) AS = new BRepAdaptor_HSurface(TopoDS::Face(F1));
|
||||
AS->D1(P2d.X(), P2d.Y(), P, D1U, D1V);
|
||||
N2 = D1U^D1V;
|
||||
|
||||
if ( (F1.Orientation() == TopAbs_REVERSED) ^ (N1.Angle(N2)>M_PI/2) )
|
||||
if (Angle == RealFirst())
|
||||
return Standard_False;
|
||||
|
||||
if ( (F1.Orientation() == TopAbs_REVERSED) ^ (Angle>M_PI/2))
|
||||
Result.Orientation(TopAbs_REVERSED);
|
||||
else Result.Orientation(TopAbs_FORWARD);
|
||||
|
||||
@@ -1661,6 +1752,60 @@ static Standard_Boolean IsDegen(const Handle(Geom_Surface)& S,
|
||||
return B;
|
||||
}
|
||||
|
||||
static void ReverseEdgeInFirstOrLastWire(TopoDS_Shape& theWire,
|
||||
const TopoDS_Shape& theEdge)
|
||||
{
|
||||
TopoDS_Shape EdgeToReverse;
|
||||
TopoDS_Iterator itw(theWire);
|
||||
|
||||
for (; itw.More(); itw.Next())
|
||||
{
|
||||
const TopoDS_Shape& anEdge = itw.Value();
|
||||
if (anEdge.IsSame(theEdge))
|
||||
{
|
||||
EdgeToReverse = anEdge;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EdgeToReverse.IsNull())
|
||||
{
|
||||
BRep_Builder BB;
|
||||
theWire.Free(Standard_True);
|
||||
BB.Remove(theWire, EdgeToReverse);
|
||||
EdgeToReverse.Reverse();
|
||||
BB.Add(theWire, EdgeToReverse);
|
||||
}
|
||||
}
|
||||
|
||||
static void ReverseModifiedEdges(TopoDS_Wire& theWire,
|
||||
const TopTools_MapOfShape& theEmap)
|
||||
{
|
||||
if (theEmap.IsEmpty())
|
||||
return;
|
||||
|
||||
TopoDS_Iterator itw(theWire);
|
||||
BRep_Builder BB;
|
||||
|
||||
TopTools_ListOfShape Ledges;
|
||||
for (; itw.More(); itw.Next())
|
||||
Ledges.Append(itw.Value());
|
||||
|
||||
theWire.Free(Standard_True);
|
||||
TopTools_ListIteratorOfListOfShape itl(Ledges);
|
||||
for (; itl.More(); itl.Next())
|
||||
BB.Remove(theWire, itl.Value());
|
||||
|
||||
for (itl.Initialize(Ledges); itl.More(); itl.Next())
|
||||
{
|
||||
TopoDS_Shape anEdge = itl.Value();
|
||||
if (theEmap.Contains(anEdge))
|
||||
anEdge.Reverse();
|
||||
BB.Add(theWire, anEdge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=======================================================================
|
||||
//function : Constructeur
|
||||
//purpose :
|
||||
@@ -1670,8 +1815,6 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
|
||||
const Standard_Boolean WithKPart) :
|
||||
isDone(Standard_False),
|
||||
KPart(WithKPart)
|
||||
|
||||
|
||||
{
|
||||
mySec = Section;
|
||||
myLoc = Location;
|
||||
@@ -1947,11 +2090,12 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
|
||||
BRep_Builder B;
|
||||
Standard_Integer NbPath = ILast - IFirst;
|
||||
Standard_Integer NbLaw = mySec->NbLaw();
|
||||
Standard_Boolean uclose, vclose, constSection, hasdegen = Standard_False;
|
||||
Standard_Boolean uclose, vclose, global_vclose, constSection, hasdegen = Standard_False;
|
||||
constSection = mySec->IsConstant();
|
||||
uclose = mySec->IsUClosed();
|
||||
vclose = (mySec->IsVClosed() && myLoc->IsClosed()) &&
|
||||
(NbPath == myLoc->NbLaw()) && (myLoc->IsG1(0, myTol3d)>= 0);
|
||||
global_vclose = (myLoc->IsClosed()) && (myLoc->IsG1(0, myTol3d)>= 0);
|
||||
Error = 0.;
|
||||
|
||||
// (1) Construction of all surfaces
|
||||
@@ -2064,6 +2208,10 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
|
||||
Standard_Boolean exuv, singu, singv;
|
||||
Handle(Geom_Surface) S;
|
||||
|
||||
//Correct <FirstShape> and <LastShape>: reverse modified edges
|
||||
ReverseModifiedEdges(FirstShape, ReversedEdges);
|
||||
ReverseModifiedEdges(LastShape, ReversedEdges);
|
||||
|
||||
// (2.0) return preexisting Edges and vertices
|
||||
TopoDS_Edge E;
|
||||
TColStd_Array1OfBoolean IsBuilt(1, NbLaw);
|
||||
@@ -2293,7 +2441,6 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
|
||||
|
||||
|
||||
// ---------- Creation of Vertex and edge ------------
|
||||
ReversedEdges.Clear();
|
||||
for (ipath=1, IPath=IFirst; ipath<=NbPath;
|
||||
ipath++, IPath++) {
|
||||
for (isec=1; isec <=NbLaw; isec++) {
|
||||
@@ -2496,7 +2643,10 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
|
||||
TopoDS::Edge(VEdge(isec, ipath)),
|
||||
ReversedEdges);
|
||||
if (ReversedEdges.Contains(VEdge(isec, ipath)))
|
||||
{
|
||||
ReverseEdgeInFirstOrLastWire(FirstShape, VEdge(isec, ipath));
|
||||
StartEdges(isec).Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2524,7 +2674,10 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
|
||||
myTol3d);
|
||||
else
|
||||
{
|
||||
if (ipath != NbPath || vclose)
|
||||
if (ipath != NbPath ||
|
||||
vclose ||
|
||||
(global_vclose && ILast == myLoc->NbLaw()+1))
|
||||
|
||||
UpdateEdge(TopoDS::Edge(VEdge(isec, ipath+1)),
|
||||
S, exuv, VLast);
|
||||
else //ipath == NbPath && !vclose => rebuild last edge
|
||||
@@ -2536,6 +2689,8 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section,
|
||||
RebuildTopOrBottomEdge(aNewLastEdge,
|
||||
TopoDS::Edge(VEdge(isec, ipath+1)),
|
||||
ReversedEdges);
|
||||
if (ReversedEdges.Contains(VEdge(isec, ipath+1)))
|
||||
ReverseEdgeInFirstOrLastWire(LastShape, VEdge(isec, ipath+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2877,6 +3032,30 @@ void BRepFill_Sweep::Build(TopTools_MapOfShape& ReversedEdges,
|
||||
}
|
||||
}
|
||||
|
||||
//Ensure Same Parameter on U-edges
|
||||
for (ii = myUEdges->LowerRow(); ii <= myUEdges->UpperRow(); ii++)
|
||||
{
|
||||
if (mySec->IsUClosed() && ii == myUEdges->UpperRow())
|
||||
continue;
|
||||
for (jj = myUEdges->LowerCol(); jj <= myUEdges->UpperCol(); jj++)
|
||||
{
|
||||
TopoDS_Edge anEdge = TopoDS::Edge(myUEdges->Value(ii, jj));
|
||||
if (anEdge.IsNull())
|
||||
continue;
|
||||
TopoDS_Face Face1, Face2;
|
||||
Standard_Integer i1 = ii-1, i2 = ii;
|
||||
if (i1 == 0 && mySec->IsUClosed())
|
||||
i1 = myFaces->UpperRow();
|
||||
if (i2 > myFaces->UpperRow())
|
||||
i2 = 0;
|
||||
if (i1 != 0)
|
||||
Face1 = TopoDS::Face(myFaces->Value(i1, jj));
|
||||
if (i2 != 0)
|
||||
Face2 = TopoDS::Face(myFaces->Value(i2, jj));
|
||||
CorrectSameParameter(anEdge, Face1, Face2);
|
||||
}
|
||||
}
|
||||
|
||||
for (ii = 1; ii <= NbLaw; ii++)
|
||||
for (jj = 1; jj <= NbPath; jj++)
|
||||
{
|
||||
@@ -3083,7 +3262,7 @@ TopoDS_Shape BRepFill_Sweep::Tape(const Standard_Integer Index) const
|
||||
}
|
||||
}
|
||||
|
||||
BRepFill_TrimShellCorner aTrim(aFaces, AxeOfBisPlane, aPlaneF);
|
||||
BRepFill_TrimShellCorner aTrim(aFaces, Transition, AxeOfBisPlane);
|
||||
aTrim.AddBounds(Bounds);
|
||||
aTrim.AddUEdges(aUEdges);
|
||||
aTrim.Perform();
|
||||
@@ -3172,7 +3351,8 @@ TopoDS_Shape BRepFill_Sweep::Tape(const Standard_Integer Index) const
|
||||
// Filling
|
||||
B = Filling(It1.Value(), myFaces->Value(ii, I1),
|
||||
It2.Value(), myFaces->Value(ii, I2),
|
||||
myVEdgesModified, myTol3d, Axe, T1, Bord1, Bord2, FF);
|
||||
myVEdgesModified, myTol3d, Axe, T1,
|
||||
Bord1, Bord2, FF);
|
||||
|
||||
if (B) {
|
||||
myAuxShape.Append(FF);
|
||||
|
@@ -80,7 +80,7 @@ public:
|
||||
//! to be C0.
|
||||
Standard_EXPORT void SetForceApproxC1 (const Standard_Boolean ForceApproxC1);
|
||||
|
||||
//! Build the Sweeep Surface
|
||||
//! Build the Sweep Surface
|
||||
//! Transition define Transition strategy
|
||||
//! Approx define Approximation Strategy
|
||||
//! - GeomFill_Section : The composed Function Location X Section
|
||||
@@ -118,13 +118,6 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Standard_EXPORT Standard_Boolean CorrectApproxParameters();
|
||||
|
||||
Standard_EXPORT Standard_Boolean BuildWire (const BRepFill_TransitionStyle Transition);
|
||||
@@ -142,6 +135,13 @@ private:
|
||||
Standard_EXPORT void RebuildTopOrBottomEdge (const TopoDS_Edge& aNewEdge, TopoDS_Edge& anEdge, TopTools_MapOfShape& ReversedEdges) const;
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
|
||||
Standard_Boolean isDone;
|
||||
Standard_Boolean KPart;
|
||||
Standard_Real myTol3d;
|
||||
@@ -168,7 +168,6 @@ private:
|
||||
TopoDS_Wire FirstShape;
|
||||
TopoDS_Wire LastShape;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <BRepFill_TrimShellCorner.hxx>
|
||||
#include <BRepLib_MakeEdge.hxx>
|
||||
#include <BRepLib_MakeWire.hxx>
|
||||
#include <BRepLib_MakeVertex.hxx>
|
||||
#include <BRepTools_ReShape.hxx>
|
||||
#include <gce_MakeLin.hxx>
|
||||
#include <GCPnts_UniformAbscissa.hxx>
|
||||
@@ -63,6 +64,23 @@
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
#include <TopTools_MapOfShape.hxx>
|
||||
#include <TopTools_SequenceOfShape.hxx>
|
||||
#include <BRepExtrema_ExtCC.hxx>
|
||||
|
||||
static TopoDS_Edge FindEdgeCloseToBisectorPlane(const TopoDS_Vertex& theVertex,
|
||||
TopoDS_Compound& theComp,
|
||||
const gp_Ax1& theAxis);
|
||||
|
||||
static Standard_Boolean FindMiddleEdges(const TopoDS_Vertex& theVertex1,
|
||||
const TopoDS_Vertex& theVertex2,
|
||||
const gp_Ax1& theAxis,
|
||||
TopoDS_Compound& theComp,
|
||||
TopTools_ListOfShape& theElist);
|
||||
|
||||
static Standard_Boolean FindCommonVertex(const TopoDS_Edge& theFirstEdge,
|
||||
const TopoDS_Edge& theLastEdge,
|
||||
const TopoDS_Vertex& theFirstVertex,
|
||||
const TopoDS_Vertex& theLastVertex,
|
||||
TopoDS_Vertex& theCommonVertex);
|
||||
|
||||
static Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theEIndex1,
|
||||
@@ -71,24 +89,6 @@ static Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS,
|
||||
Standard_Real& theParamOnE1,
|
||||
Standard_Real& theParamOnE2);
|
||||
|
||||
static Standard_Boolean MakeFacesNonSec(const Standard_Integer theIndex,
|
||||
const Handle(TopTools_HArray2OfShape)& theUEdges,
|
||||
const Handle(TopTools_HArray2OfShape)& theBounds,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2,
|
||||
TopTools_DataMapOfShapeListOfShape& theHistMap);
|
||||
|
||||
static Standard_Boolean MakeFacesSec(const Standard_Integer theIndex,
|
||||
const Handle(TopTools_HArray2OfShape)& theUEdges,
|
||||
const Handle(TopTools_HArray2OfShape)& theBounds,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2,
|
||||
const Standard_Integer theSSInterfIndex,
|
||||
const gp_Ax2& AxeOfBisPlane,
|
||||
TopTools_DataMapOfShapeListOfShape& theHistMap);
|
||||
|
||||
static Standard_Boolean SplitUEdges(const Handle(TopTools_HArray2OfShape)& theUEdges,
|
||||
const BOPDS_PDS& theDS,
|
||||
TopTools_DataMapOfShapeListOfShape& theHistMap);
|
||||
@@ -186,55 +186,27 @@ static Standard_Real ComputeAveragePlaneAndMaxDeviation(const TopoDS_Shape& aWir
|
||||
gp_Pln& thePlane,
|
||||
Standard_Boolean& IsSingular);
|
||||
|
||||
static Standard_Boolean ChooseSection(const TopoDS_Shape& Comp,
|
||||
const gp_Ax2& bis,
|
||||
TopoDS_Shape& resWire,
|
||||
gp_Pln& resPlane,
|
||||
Standard_Boolean& IsSingular);
|
||||
static void UpdateSectionEdge(TopoDS_Edge& theEdge,
|
||||
const TopoDS_Vertex& theConstVertex,
|
||||
TopoDS_Vertex& theVertex,
|
||||
const Standard_Real theParam);
|
||||
|
||||
|
||||
// ===========================================================================================
|
||||
// function: Constructor
|
||||
// purpose:
|
||||
// ===========================================================================================
|
||||
BRepFill_TrimShellCorner::BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces,
|
||||
const gp_Ax2& theAxeOfBisPlane,
|
||||
const TopoDS_Face& theSecPlane) :
|
||||
myAxeOfBisPlane(theAxeOfBisPlane),
|
||||
myDone(Standard_False),
|
||||
myHasSection(Standard_False)
|
||||
const BRepFill_TransitionStyle theTransition,
|
||||
const gp_Ax2& theAxeOfBisPlane) :
|
||||
myTransition(theTransition),
|
||||
myAxeOfBisPlane(theAxeOfBisPlane),
|
||||
myDone(Standard_False),
|
||||
myHasSection(Standard_False)
|
||||
{
|
||||
myFaces = new TopTools_HArray2OfShape(theFaces->LowerRow(), theFaces->UpperRow(),
|
||||
theFaces->LowerCol(), theFaces->UpperCol());
|
||||
myFaces->ChangeArray2() = theFaces->Array2();
|
||||
mySecPln = theSecPlane;
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
// function: Constructor
|
||||
// purpose:
|
||||
// ===========================================================================================
|
||||
BRepFill_TrimShellCorner::BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces,
|
||||
const gp_Ax2& theAxeOfBisPlane,
|
||||
const TopoDS_Wire& theSpine,
|
||||
const TopoDS_Face& theSecPlane):
|
||||
myAxeOfBisPlane(theAxeOfBisPlane),
|
||||
myDone(Standard_False),
|
||||
myHasSection(Standard_False)
|
||||
{
|
||||
myFaces = new TopTools_HArray2OfShape(theFaces->LowerRow(), theFaces->UpperRow(),
|
||||
theFaces->LowerCol(), theFaces->UpperCol());
|
||||
myFaces->ChangeArray2() = theFaces->Array2();
|
||||
mySpine = theSpine;
|
||||
mySecPln = theSecPlane;
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
// function: SetSpine
|
||||
// purpose:
|
||||
// ===========================================================================================
|
||||
void BRepFill_TrimShellCorner::SetSpine(const TopoDS_Wire& theSpine)
|
||||
{
|
||||
mySpine = theSpine;
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
@@ -351,14 +323,13 @@ void BRepFill_TrimShellCorner::Perform()
|
||||
}
|
||||
|
||||
if(!bhassec) {
|
||||
if(!MakeFacesNonSec(ii, myUEdges, myBounds, theDS, anIndex1, anIndex2, myHistMap)) {
|
||||
if(!MakeFacesNonSec(ii, theDS, anIndex1, anIndex2)) {
|
||||
myHistMap.Clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!MakeFacesSec(ii, myUEdges, myBounds, theDS, anIndex1, anIndex2,
|
||||
i, myAxeOfBisPlane, myHistMap)) {
|
||||
if(!MakeFacesSec(ii, theDS, anIndex1, anIndex2, i)) {
|
||||
myHistMap.Clear();
|
||||
return;
|
||||
}
|
||||
@@ -403,23 +374,21 @@ void BRepFill_TrimShellCorner::Modified(const TopoDS_Shape& theShape,
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// static function: MakeFacesNonSec
|
||||
// purpose:
|
||||
// function: MakeFacesNonSec
|
||||
// purpose: Updates <myHistMap> by new faces in the case when old faces do not intersect
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
Standard_Boolean MakeFacesNonSec(const Standard_Integer theIndex,
|
||||
const Handle(TopTools_HArray2OfShape)& theUEdges,
|
||||
const Handle(TopTools_HArray2OfShape)& theBounds,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2,
|
||||
TopTools_DataMapOfShapeListOfShape& theHistMap)
|
||||
Standard_Boolean
|
||||
BRepFill_TrimShellCorner::MakeFacesNonSec(const Standard_Integer theIndex,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2)
|
||||
{
|
||||
Standard_Boolean bHasNewEdge = Standard_False;
|
||||
TopoDS_Edge aNewEdge;
|
||||
|
||||
BRep_Builder aBB;
|
||||
const TopoDS_Shape& aE1 = theBounds->Value(theIndex, 1);
|
||||
const TopoDS_Shape& aE2 = theBounds->Value(theIndex, 2);
|
||||
const TopoDS_Shape& aE1 = myBounds->Value(theIndex, 1);
|
||||
const TopoDS_Shape& aE2 = myBounds->Value(theIndex, 2);
|
||||
|
||||
// search common vertex between bounds. begin
|
||||
TopoDS_Vertex aCommonVertex;
|
||||
@@ -439,20 +408,20 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI
|
||||
Standard_Integer ueit = 0, eindex = 0;
|
||||
|
||||
for(ueit = 1, eindex = theIndex; ueit <= 2; ueit++, eindex++) {
|
||||
const TopoDS_Shape& aShape1 = theUEdges->Value(eindex, theUEdges->LowerCol());
|
||||
const TopoDS_Shape& aShape2 = theUEdges->Value(eindex, theUEdges->UpperCol());
|
||||
const TopoDS_Shape& aShape1 = myUEdges->Value(eindex, myUEdges->LowerCol());
|
||||
const TopoDS_Shape& aShape2 = myUEdges->Value(eindex, myUEdges->UpperCol());
|
||||
TopoDS_Edge aUE1 = TopoDS::Edge(aShape1);
|
||||
TopoDS_Edge aUE2 = TopoDS::Edge(aShape2);
|
||||
|
||||
if(theHistMap.IsBound(aShape1)) {
|
||||
const TopTools_ListOfShape& lst = theHistMap.Find(aShape1);
|
||||
if (myHistMap.IsBound(aShape1)) {
|
||||
const TopTools_ListOfShape& lst = myHistMap.Find(aShape1);
|
||||
|
||||
if(!lst.IsEmpty())
|
||||
aUE1 = TopoDS::Edge(lst.First());
|
||||
}
|
||||
|
||||
if(theHistMap.IsBound(aShape2)) {
|
||||
const TopTools_ListOfShape& lst = theHistMap.Find(aShape2);
|
||||
if (myHistMap.IsBound(aShape2)) {
|
||||
const TopTools_ListOfShape& lst = myHistMap.Find(aShape2);
|
||||
|
||||
if(!lst.IsEmpty())
|
||||
aUE2 = TopoDS::Edge(lst.First());
|
||||
@@ -499,11 +468,11 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI
|
||||
aBB.MakeCompound(aComp);
|
||||
|
||||
for(ueit = 1, eindex = theIndex; ueit <= 2; ueit++, eindex++) {
|
||||
const TopoDS_Shape& aShape = theUEdges->Value(eindex, theUEdges->LowerCol() + fit - 1);
|
||||
const TopoDS_Shape& aShape = myUEdges->Value(eindex, myUEdges->LowerCol() + fit - 1);
|
||||
TopoDS_Shape aUE = aShape;
|
||||
|
||||
if(theHistMap.IsBound(aShape)) {
|
||||
const TopTools_ListOfShape& lst = theHistMap.Find(aShape);
|
||||
if(myHistMap.IsBound(aShape)) {
|
||||
const TopTools_ListOfShape& lst = myHistMap.Find(aShape);
|
||||
|
||||
if(!lst.IsEmpty())
|
||||
aUE = TopoDS::Edge(lst.First());
|
||||
@@ -638,7 +607,7 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI
|
||||
aNewFace.Orientation(aFaceOri);
|
||||
TopTools_ListOfShape atmpList;
|
||||
atmpList.Append(aNewFace);
|
||||
theHistMap.Bind(aFace, atmpList);
|
||||
myHistMap.Bind(aFace, atmpList);
|
||||
|
||||
anExpE.Init(aFace, TopAbs_EDGE);
|
||||
|
||||
@@ -648,7 +617,7 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI
|
||||
if(aNewValue.IsNull() || aNewValue.IsSame(anExpE.Current()))
|
||||
continue;
|
||||
|
||||
if(theHistMap.IsBound(anExpE.Current()))
|
||||
if (myHistMap.IsBound(anExpE.Current()))
|
||||
continue;
|
||||
TopTools_ListOfShape aListOfNewEdge;
|
||||
TopExp_Explorer anExpE2(aNewValue, TopAbs_EDGE);
|
||||
@@ -656,7 +625,7 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI
|
||||
for(; anExpE2.More(); anExpE2.Next()) {
|
||||
aListOfNewEdge.Append(anExpE2.Current());
|
||||
}
|
||||
theHistMap.Bind(anExpE.Current(), aListOfNewEdge);
|
||||
myHistMap.Bind(anExpE.Current(), aListOfNewEdge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,18 +633,15 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// static function: MakeFacesSec
|
||||
// purpose:
|
||||
// function: MakeFacesSec
|
||||
// purpose: Updates <myHistMap> by new faces in the case when old faces intersect each other
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
Standard_Boolean MakeFacesSec(const Standard_Integer theIndex,
|
||||
const Handle(TopTools_HArray2OfShape)& theUEdges,
|
||||
const Handle(TopTools_HArray2OfShape)& theBounds,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2,
|
||||
const Standard_Integer theSSInterfIndex,
|
||||
const gp_Ax2& AxeOfBisPlane,
|
||||
TopTools_DataMapOfShapeListOfShape& theHistMap)
|
||||
Standard_Boolean
|
||||
BRepFill_TrimShellCorner::MakeFacesSec(const Standard_Integer theIndex,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2,
|
||||
const Standard_Integer theSSInterfIndex)
|
||||
{
|
||||
const BOPDS_VectorOfInterfFF& aFFs = theDS->InterfFF();
|
||||
const BOPDS_InterfFF& aFFi = aFFs(theSSInterfIndex);
|
||||
@@ -687,10 +653,30 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde
|
||||
if(!FilterSectionEdges(aBCurves, aSecPlane, theDS, aSecEdges))
|
||||
return Standard_False;
|
||||
|
||||
//Extract vertices on the intersection of correspondent U-edges
|
||||
const TopoDS_Shape& LeftE1 = myUEdges->Value(theIndex, 1);
|
||||
const TopoDS_Shape& LeftE2 = myUEdges->Value(theIndex, 2);
|
||||
const TopoDS_Shape& RightE1 = myUEdges->Value(theIndex+1, 1);
|
||||
const TopoDS_Shape& RightE2 = myUEdges->Value(theIndex+1, 2);
|
||||
|
||||
Standard_Integer IndexOfLeftE1 = theDS->Index(LeftE1);
|
||||
Standard_Integer IndexOfLeftE2 = theDS->Index(LeftE2);
|
||||
Standard_Integer IndexOfRightE1 = theDS->Index(RightE1);
|
||||
Standard_Integer IndexOfRightE2 = theDS->Index(RightE2);
|
||||
|
||||
TopoDS_Vertex FirstVertex, LastVertex;
|
||||
Standard_Real ParamOnLeftE1, ParamOnLeftE2, ParamOnRightE1, ParamOnRightE2;
|
||||
FindCommonVertex(theDS, IndexOfLeftE1, IndexOfLeftE2,
|
||||
FirstVertex, ParamOnLeftE1, ParamOnLeftE2);
|
||||
FindCommonVertex(theDS, IndexOfRightE1, IndexOfRightE2,
|
||||
LastVertex, ParamOnRightE1, ParamOnRightE2);
|
||||
|
||||
TopoDS_Shape SecWire;
|
||||
gp_Pln SecPlane;
|
||||
Standard_Boolean IsSingular;
|
||||
Standard_Boolean WireFound = ChooseSection( aSecEdges, AxeOfBisPlane, SecWire, SecPlane, IsSingular );
|
||||
Standard_Boolean WireFound = ChooseSection(aSecEdges,
|
||||
FirstVertex, LastVertex,
|
||||
SecWire, SecPlane, IsSingular );
|
||||
|
||||
if(WireFound) {
|
||||
//aSecEdges = SecWire;
|
||||
@@ -715,19 +701,19 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde
|
||||
TopAbs_Orientation aFaceOri = aFace.Orientation();
|
||||
TopoDS_Face aFaceF = aFace;
|
||||
aFaceF.Orientation(TopAbs_FORWARD);
|
||||
TopoDS_Edge aBoundEdge = TopoDS::Edge(theBounds->Value(theIndex, theBounds->LowerCol() +fit));
|
||||
TopoDS_Edge aBoundEdge = TopoDS::Edge(myBounds->Value(theIndex, myBounds->LowerCol() +fit));
|
||||
Standard_Integer aBoundEdgeIndex = theDS->Index(aBoundEdge);
|
||||
TopoDS_Edge aUE1;
|
||||
TopoDS_Edge aUE2;
|
||||
|
||||
if(!GetUEdges(theIndex, fit, theUEdges, aBoundEdge, aFaceF, aUE1, aUE2))
|
||||
if(!GetUEdges(theIndex, fit, myUEdges, aBoundEdge, aFaceF, aUE1, aUE2))
|
||||
return Standard_False;
|
||||
|
||||
TopoDS_Edge aUE1old = aUE1;
|
||||
TopoDS_Edge aUE2old = aUE2;
|
||||
|
||||
if(theHistMap.IsBound(aUE1)) {
|
||||
const TopTools_ListOfShape& lst = theHistMap.Find(aUE1);
|
||||
if (myHistMap.IsBound(aUE1)) {
|
||||
const TopTools_ListOfShape& lst = myHistMap.Find(aUE1);
|
||||
|
||||
if(!lst.IsEmpty()) {
|
||||
const TopoDS_Shape& anEdge = lst.First().Oriented(aUE1.Orientation());
|
||||
@@ -738,8 +724,8 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde
|
||||
}
|
||||
}
|
||||
|
||||
if(theHistMap.IsBound(aUE2)) {
|
||||
const TopTools_ListOfShape& lst = theHistMap.Find(aUE2);
|
||||
if (myHistMap.IsBound(aUE2)) {
|
||||
const TopTools_ListOfShape& lst = myHistMap.Find(aUE2);
|
||||
|
||||
if(!lst.IsEmpty()) {
|
||||
const TopoDS_Shape& anEdge = lst.First().Oriented(aUE2.Orientation());
|
||||
@@ -757,12 +743,12 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde
|
||||
Standard_Boolean isPave1OnUEdge = Standard_True;
|
||||
|
||||
if(FindFromUEdge(aUE1old, aUE2old, aUE1, aUE2, aFace, aSecEdges, fit, aBoundEdge, aBoundEdgeIndex,
|
||||
theDS, theHistMap, aCompOfSecEdges, aListOfWireEdges, aPave1, isPave1OnUEdge)) {
|
||||
theDS, myHistMap, aCompOfSecEdges, aListOfWireEdges, aPave1, isPave1OnUEdge)) {
|
||||
TopTools_ListOfShape aSecondListOfEdges;
|
||||
Standard_Boolean bisSectionFound = Standard_False;
|
||||
|
||||
if(!FindFromVEdge(aPave1, isPave1OnUEdge, aUE1old, aUE2old, aFace, aCompOfSecEdges, fit, aBoundEdge,
|
||||
aBoundEdgeIndex, theDS, theHistMap, aSecondListOfEdges, bisSectionFound)) {
|
||||
aBoundEdgeIndex, theDS, myHistMap, aSecondListOfEdges, bisSectionFound)) {
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
@@ -792,7 +778,7 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde
|
||||
aNewFace.Orientation(aFaceOri);
|
||||
TopTools_ListOfShape atmpList;
|
||||
atmpList.Append(aNewFace);
|
||||
theHistMap.Bind(aFace, atmpList);
|
||||
myHistMap.Bind(aFace, atmpList);
|
||||
|
||||
TopExp_Explorer anExpE(aFace, TopAbs_EDGE);
|
||||
|
||||
@@ -802,7 +788,7 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde
|
||||
if(aNewValue.IsNull() || aNewValue.IsSame(anExpE.Current()))
|
||||
continue;
|
||||
|
||||
if(theHistMap.IsBound(anExpE.Current()))
|
||||
if (myHistMap.IsBound(anExpE.Current()))
|
||||
continue;
|
||||
TopTools_ListOfShape aListOfNewEdge;
|
||||
TopExp_Explorer anExpE2(aNewValue, TopAbs_EDGE);
|
||||
@@ -810,12 +796,240 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde
|
||||
for(; anExpE2.More(); anExpE2.Next()) {
|
||||
aListOfNewEdge.Append(anExpE2.Current());
|
||||
}
|
||||
theHistMap.Bind(anExpE.Current(), aListOfNewEdge);
|
||||
myHistMap.Bind(anExpE.Current(), aListOfNewEdge);
|
||||
}
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ChooseSection
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean BRepFill_TrimShellCorner::ChooseSection(const TopoDS_Shape& Comp,
|
||||
const TopoDS_Vertex& theFirstVertex,
|
||||
const TopoDS_Vertex& theLastVertex,
|
||||
TopoDS_Shape& resWire,
|
||||
gp_Pln& resPlane,
|
||||
Standard_Boolean& IsSingular)
|
||||
{
|
||||
IsSingular = Standard_False;
|
||||
|
||||
Standard_Integer ind, i, j;
|
||||
BRep_Builder BB;
|
||||
|
||||
if (myTransition == BRepFill_Right &&
|
||||
!theFirstVertex.IsNull() &&
|
||||
!theLastVertex.IsNull()) //the case where section wire goes from
|
||||
//its known first vertex to its known last vertex
|
||||
{
|
||||
TopoDS_Wire NewWire;
|
||||
BB.MakeWire(NewWire);
|
||||
|
||||
TopoDS_Compound OldComp;
|
||||
BB.MakeCompound( OldComp );
|
||||
TopoDS_Iterator iter( Comp );
|
||||
for (; iter.More(); iter.Next())
|
||||
BB.Add( OldComp, iter.Value() );
|
||||
|
||||
TopoDS_Edge FirstEdge = FindEdgeCloseToBisectorPlane(theFirstVertex,
|
||||
OldComp,
|
||||
myAxeOfBisPlane.Axis());
|
||||
iter.Initialize(OldComp);
|
||||
if (!iter.More())
|
||||
{
|
||||
iter.Initialize(Comp);
|
||||
BB.Add( OldComp, iter.Value() );
|
||||
}
|
||||
TopoDS_Edge LastEdge = FindEdgeCloseToBisectorPlane(theLastVertex,
|
||||
OldComp,
|
||||
myAxeOfBisPlane.Axis());
|
||||
|
||||
BB.Add(NewWire, FirstEdge);
|
||||
|
||||
if (!FirstEdge.IsSame(LastEdge))
|
||||
{
|
||||
TopoDS_Vertex aCommonVertex;
|
||||
Standard_Boolean CommonVertexExists = FindCommonVertex(FirstEdge, LastEdge,
|
||||
theFirstVertex, theLastVertex,
|
||||
aCommonVertex);
|
||||
if (CommonVertexExists)
|
||||
BB.Add(NewWire, LastEdge);
|
||||
else
|
||||
{
|
||||
TopoDS_Vertex Vertex1, Vertex2, V1, V2;
|
||||
TopExp::Vertices(FirstEdge, V1, V2);
|
||||
Vertex1 = (theFirstVertex.IsSame(V1))? V2 : V1;
|
||||
TopExp::Vertices(LastEdge, V1, V2);
|
||||
Vertex2 = (theLastVertex.IsSame(V1))? V2 : V1;
|
||||
|
||||
TopTools_ListOfShape MiddleEdges;
|
||||
if (FindMiddleEdges(Vertex1, Vertex2, myAxeOfBisPlane.Axis(), OldComp, MiddleEdges))
|
||||
{
|
||||
TopTools_ListIteratorOfListOfShape itl(MiddleEdges);
|
||||
for (; itl.More(); itl.Next())
|
||||
BB.Add(NewWire, itl.Value());
|
||||
BB.Add(NewWire, LastEdge);
|
||||
}
|
||||
else
|
||||
{
|
||||
//trim <FirstEdge> and <LastEdge> in the points of extrema
|
||||
//these points become new vertex with centre between them
|
||||
BRepExtrema_ExtCC Extrema(FirstEdge, LastEdge);
|
||||
if (Extrema.IsDone() && Extrema.NbExt() > 0)
|
||||
{
|
||||
Standard_Integer imin = 1;
|
||||
for (i = 2; i <= Extrema.NbExt(); i++)
|
||||
if (Extrema.SquareDistance(i) < Extrema.SquareDistance(imin))
|
||||
imin = i;
|
||||
|
||||
Standard_Real aMinDist = sqrt(Extrema.SquareDistance(imin));
|
||||
Standard_Real ParamOnFirstEdge = Extrema.ParameterOnE1(imin);
|
||||
Standard_Real ParamOnLastEdge = Extrema.ParameterOnE2(imin);
|
||||
gp_Pnt PointOnFirstEdge = Extrema.PointOnE1(imin);
|
||||
gp_Pnt PointOnLastEdge = Extrema.PointOnE2(imin);
|
||||
gp_Pnt MidPnt((PointOnFirstEdge.XYZ() + PointOnLastEdge.XYZ())/2);
|
||||
aCommonVertex = BRepLib_MakeVertex(MidPnt);
|
||||
BB.UpdateVertex(aCommonVertex, 1.001*aMinDist/2);
|
||||
|
||||
UpdateSectionEdge(FirstEdge, theFirstVertex, aCommonVertex, ParamOnFirstEdge);
|
||||
UpdateSectionEdge(LastEdge, theLastVertex, aCommonVertex, ParamOnLastEdge);
|
||||
|
||||
BB.Add(NewWire, LastEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resWire = NewWire;
|
||||
resPlane = gp_Pln(myAxeOfBisPlane);
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//General case: try to find continuous section closest to bisector plane
|
||||
TopoDS_Compound OldComp;
|
||||
BRep_Builder B;
|
||||
B.MakeCompound( OldComp );
|
||||
TopoDS_Iterator iter( Comp );
|
||||
for (; iter.More(); iter.Next())
|
||||
B.Add( OldComp, iter.Value() );
|
||||
|
||||
Standard_Boolean anError = Standard_False;
|
||||
//TopoDS_Wire NewWire [2];
|
||||
TopTools_SequenceOfShape Wseq;
|
||||
for (;;)
|
||||
{
|
||||
TopExp_Explorer explo( OldComp, TopAbs_EDGE );
|
||||
if (!explo.More())
|
||||
break;
|
||||
TopoDS_Edge FirstEdge = TopoDS::Edge( explo.Current() );
|
||||
TopoDS_Wire NewWire = BRepLib_MakeWire( FirstEdge );
|
||||
B.Remove( OldComp, FirstEdge );
|
||||
if (NewWire.Closed())
|
||||
{
|
||||
Wseq.Append(NewWire);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
TopoDS_Vertex Extremity [2];
|
||||
TopExp::Vertices( NewWire, Extremity[0], Extremity[1] );
|
||||
if (Extremity[0].IsNull() || Extremity[1].IsNull())
|
||||
{
|
||||
anError = Standard_True;
|
||||
break;
|
||||
}
|
||||
TopTools_IndexedDataMapOfShapeListOfShape VEmap;
|
||||
TopExp::MapShapesAndAncestors( OldComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap );
|
||||
TopTools_ListOfShape Vedges [2];
|
||||
for (j = 0; j < 2; j++)
|
||||
if (VEmap.Contains( Extremity[j] ))
|
||||
Vedges[j] = VEmap.FindFromKey( Extremity[j] );
|
||||
if (Vedges[0].IsEmpty() && Vedges[1].IsEmpty())
|
||||
//no more edges in OldComp to continue NewWire
|
||||
break;
|
||||
Standard_Boolean Modified = Standard_False;
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
if (Vedges[j].Extent() == 1)
|
||||
{
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge( Vedges[j].First() );
|
||||
NewWire = BRepLib_MakeWire( NewWire, anEdge );
|
||||
B.Remove( OldComp, anEdge );
|
||||
Modified = Standard_True;
|
||||
}
|
||||
}
|
||||
if (!Modified) //only multiple connections
|
||||
{
|
||||
ind = (Vedges[0].IsEmpty())? 1 : 0;
|
||||
TopTools_SequenceOfShape Edges;
|
||||
TopTools_ListIteratorOfListOfShape itl( Vedges[ind] );
|
||||
for (; itl.More(); itl.Next())
|
||||
Edges.Append( itl.Value() );
|
||||
Standard_Integer theind=0;
|
||||
Standard_Real MinDeviation = RealLast();
|
||||
for (j = 1; j <= Edges.Length(); j++)
|
||||
{
|
||||
TopoDS_Wire aWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(j)) );
|
||||
gp_Pln aPlane;
|
||||
Standard_Boolean issing;
|
||||
Standard_Real Deviation = ComputeAveragePlaneAndMaxDeviation( aWire, aPlane, issing );
|
||||
if (Deviation < MinDeviation)
|
||||
{
|
||||
MinDeviation = Deviation;
|
||||
theind = j;
|
||||
}
|
||||
}
|
||||
NewWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(theind)) );
|
||||
B.Remove( OldComp, Edges(theind) );
|
||||
}
|
||||
if (NewWire.Closed())
|
||||
break;
|
||||
}
|
||||
Wseq.Append(NewWire);
|
||||
if (anError)
|
||||
break;
|
||||
}
|
||||
|
||||
Standard_Real MinAngle = RealLast();
|
||||
TopExp_Explorer Explo( OldComp, TopAbs_EDGE );
|
||||
if (!anError && !Explo.More()) //wires are built successfully and compound <OldComp> is empty
|
||||
{
|
||||
if (Wseq.Length() == 1) //only one wire => it becomes result
|
||||
{
|
||||
resWire = Wseq.First();
|
||||
ComputeAveragePlaneAndMaxDeviation( resWire, resPlane, IsSingular );
|
||||
return Standard_True;
|
||||
}
|
||||
else //we must choose the wire which average plane is closest to bisector plane
|
||||
{ //(check angle between axes)
|
||||
for (i = 1; i <= Wseq.Length(); i++)
|
||||
{
|
||||
TopoDS_Wire aWire = TopoDS::Wire( Wseq(i) );
|
||||
gp_Pln aPln;
|
||||
Standard_Boolean issing;
|
||||
ComputeAveragePlaneAndMaxDeviation( aWire, aPln, issing );
|
||||
if (issing)
|
||||
continue;
|
||||
|
||||
Standard_Real Angle = aPln.Axis().Angle( myAxeOfBisPlane.Axis() );
|
||||
if (Angle > M_PI/2)
|
||||
Angle = M_PI - Angle;
|
||||
|
||||
if (Angle < MinAngle)
|
||||
{
|
||||
MinAngle = Angle;
|
||||
resWire = aWire;
|
||||
resPlane = aPln;
|
||||
}
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
// static function: SplitUEdges
|
||||
@@ -966,13 +1180,15 @@ Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS,
|
||||
continue;
|
||||
|
||||
IntTools_CommonPrt aCP = aEE.CommonPart();
|
||||
if(aCP.Type() == TopAbs_VERTEX) {
|
||||
if(aCP.Type() == TopAbs_VERTEX)
|
||||
{
|
||||
theCommonVertex = *(TopoDS_Vertex*)&theDS->Shape(aEE.IndexNew());
|
||||
if (theEIndex1 == aEE.Index1()) {
|
||||
|
||||
if (theEIndex1 == aEE.Index1())
|
||||
IntTools_Tools::VertexParameters(aCP, theParamOnE1, theParamOnE2);
|
||||
} else {
|
||||
else
|
||||
IntTools_Tools::VertexParameters(aCP, theParamOnE2, theParamOnE1);
|
||||
}
|
||||
|
||||
//
|
||||
bvertexfound = Standard_True;
|
||||
break;
|
||||
@@ -2004,147 +2220,182 @@ static Standard_Real ComputeAveragePlaneAndMaxDeviation(const TopoDS_Shape& aWir
|
||||
return MaxDeviation;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ChooseSection
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static Standard_Boolean ChooseSection(const TopoDS_Shape& Comp,
|
||||
const gp_Ax2& bis,
|
||||
TopoDS_Shape& resWire,
|
||||
gp_Pln& resPlane,
|
||||
Standard_Boolean& IsSingular)
|
||||
|
||||
static void UpdateSectionEdge(TopoDS_Edge& theEdge,
|
||||
const TopoDS_Vertex& theConstVertex,
|
||||
TopoDS_Vertex& theVertex,
|
||||
const Standard_Real theParam)
|
||||
{
|
||||
IsSingular = Standard_False;
|
||||
Standard_Real TolDeviation = 0.01; //, TolConf = 1.e-4, TolAng = 1.e-5;
|
||||
TopoDS_Edge F_Edge = theEdge;
|
||||
F_Edge.Orientation(TopAbs_FORWARD);
|
||||
|
||||
TopAbs_Orientation OrOfVertex;
|
||||
TopoDS_Vertex V1, V2, AnotherVertex;
|
||||
TopExp::Vertices(F_Edge, V1, V2);
|
||||
if (theConstVertex.IsSame(V1))
|
||||
{
|
||||
//OrOfConst = TopAbs_FORWARD;
|
||||
OrOfVertex = TopAbs_REVERSED;
|
||||
AnotherVertex = V2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//OrOfConst = TopAbs_REVERSED;
|
||||
OrOfVertex = TopAbs_FORWARD;
|
||||
AnotherVertex = V1;
|
||||
}
|
||||
|
||||
// Standard_Integer N = 100;
|
||||
Standard_Integer ind, i, j;
|
||||
BRep_Builder BB;
|
||||
Standard_Real fpar, lpar;
|
||||
BRep_Tool::Range(F_Edge, fpar, lpar);
|
||||
if (OrOfVertex == TopAbs_FORWARD)
|
||||
fpar = theParam;
|
||||
else
|
||||
lpar = theParam;
|
||||
BB.Range(F_Edge, fpar, lpar);
|
||||
|
||||
//Simplest case
|
||||
TopoDS_Compound OldComp;
|
||||
BRep_Builder B;
|
||||
B.MakeCompound( OldComp );
|
||||
TopoDS_Iterator iter( Comp );
|
||||
for (; iter.More(); iter.Next())
|
||||
B.Add( OldComp, iter.Value() );
|
||||
|
||||
Standard_Boolean anError = Standard_False;
|
||||
//TopoDS_Wire NewWire [2];
|
||||
TopTools_SequenceOfShape Wseq;
|
||||
for (;;)
|
||||
{
|
||||
TopExp_Explorer explo( OldComp, TopAbs_EDGE );
|
||||
if (!explo.More())
|
||||
break;
|
||||
TopoDS_Edge FirstEdge = TopoDS::Edge( explo.Current() );
|
||||
TopoDS_Wire NewWire = BRepLib_MakeWire( FirstEdge );
|
||||
B.Remove( OldComp, FirstEdge );
|
||||
if (NewWire.Closed())
|
||||
{
|
||||
Wseq.Append(NewWire);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
TopoDS_Vertex Extremity [2];
|
||||
TopExp::Vertices( NewWire, Extremity[0], Extremity[1] );
|
||||
if (Extremity[0].IsNull() || Extremity[1].IsNull())
|
||||
{
|
||||
anError = Standard_True;
|
||||
break;
|
||||
}
|
||||
TopTools_IndexedDataMapOfShapeListOfShape VEmap;
|
||||
TopExp::MapShapesAndAncestors( OldComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap );
|
||||
TopTools_ListOfShape Vedges [2];
|
||||
for (j = 0; j < 2; j++)
|
||||
if (VEmap.Contains( Extremity[j] ))
|
||||
Vedges[j] = VEmap.FindFromKey( Extremity[j] );
|
||||
if (Vedges[0].IsEmpty() && Vedges[1].IsEmpty())
|
||||
//no more edges in OldComp to continue NewWire
|
||||
break;
|
||||
Standard_Boolean Modified = Standard_False;
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
if (Vedges[j].Extent() == 1)
|
||||
{
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge( Vedges[j].First() );
|
||||
NewWire = BRepLib_MakeWire( NewWire, anEdge );
|
||||
B.Remove( OldComp, anEdge );
|
||||
Modified = Standard_True;
|
||||
}
|
||||
}
|
||||
if (!Modified) //only multiple connections
|
||||
{
|
||||
ind = (Vedges[0].IsEmpty())? 1 : 0;
|
||||
TopTools_SequenceOfShape Edges;
|
||||
TopTools_ListIteratorOfListOfShape itl( Vedges[ind] );
|
||||
for (; itl.More(); itl.Next())
|
||||
Edges.Append( itl.Value() );
|
||||
Standard_Integer theind=0;
|
||||
Standard_Real MinDeviation = RealLast();
|
||||
for (j = 1; j <= Edges.Length(); j++)
|
||||
{
|
||||
TopoDS_Wire aWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(j)) );
|
||||
gp_Pln aPlane;
|
||||
Standard_Boolean issing;
|
||||
Standard_Real Deviation = ComputeAveragePlaneAndMaxDeviation( aWire, aPlane, issing );
|
||||
if (Deviation < MinDeviation)
|
||||
{
|
||||
MinDeviation = Deviation;
|
||||
theind = j;
|
||||
}
|
||||
}
|
||||
NewWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(theind)) );
|
||||
B.Remove( OldComp, Edges(theind) );
|
||||
}
|
||||
if (NewWire.Closed())
|
||||
break;
|
||||
}
|
||||
Wseq.Append(NewWire);
|
||||
if (anError)
|
||||
break;
|
||||
}
|
||||
|
||||
Standard_Real Deviation=0.;
|
||||
Standard_Real MinAngle = RealLast();
|
||||
TopExp_Explorer Explo( OldComp, TopAbs_EDGE );
|
||||
if (!anError && !Explo.More())
|
||||
{
|
||||
if (Wseq.Length() == 1)
|
||||
{
|
||||
resWire = Wseq.First();
|
||||
Deviation = ComputeAveragePlaneAndMaxDeviation( resWire, resPlane, IsSingular );
|
||||
return Standard_True;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1; i <= Wseq.Length(); i++)
|
||||
{
|
||||
TopoDS_Wire aWire = TopoDS::Wire( Wseq(i) );
|
||||
gp_Pln aPln;
|
||||
Standard_Boolean issing;
|
||||
Standard_Real aDeviation =
|
||||
ComputeAveragePlaneAndMaxDeviation( aWire, aPln, issing );
|
||||
if (issing)
|
||||
continue;
|
||||
|
||||
Standard_Real Angle = aPln.Axis().Angle( bis.Axis() );
|
||||
if (Angle > M_PI/2)
|
||||
Angle = M_PI - Angle;
|
||||
|
||||
if (Angle < MinAngle)
|
||||
{
|
||||
MinAngle = Angle;
|
||||
resWire = aWire;
|
||||
resPlane = aPln;
|
||||
Deviation = aDeviation;
|
||||
}
|
||||
}
|
||||
if (Deviation <= TolDeviation)
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
return Standard_False;
|
||||
//end of simplest case
|
||||
F_Edge.Free(Standard_True);
|
||||
BB.Remove(F_Edge, AnotherVertex);
|
||||
theVertex.Orientation(OrOfVertex);
|
||||
BB.Add(F_Edge, theVertex);
|
||||
}
|
||||
|
||||
//Finds the edge connected to <theVertex> in the compound <theComp>
|
||||
//that is closest to bisector plane angularly.
|
||||
//Removes found edge from <theComp>
|
||||
//<theAxis> is the axis of bisector plane
|
||||
static TopoDS_Edge FindEdgeCloseToBisectorPlane(const TopoDS_Vertex& theVertex,
|
||||
TopoDS_Compound& theComp,
|
||||
const gp_Ax1& theAxis)
|
||||
{
|
||||
TopTools_IndexedDataMapOfShapeListOfShape VEmap;
|
||||
TopExp::MapShapesAndAncestors( theComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap );
|
||||
|
||||
TopoDS_Edge MinEdge;
|
||||
if (!VEmap.Contains(theVertex))
|
||||
return MinEdge;
|
||||
|
||||
BRep_Builder BB;
|
||||
|
||||
const TopTools_ListOfShape& Edges = VEmap.FindFromKey(theVertex);
|
||||
if (Edges.Extent() == 1)
|
||||
MinEdge = TopoDS::Edge(Edges.First());
|
||||
else
|
||||
{
|
||||
TopTools_ListIteratorOfListOfShape itl(Edges);
|
||||
Standard_Real MinAngle = RealLast();
|
||||
for (; itl.More(); itl.Next())
|
||||
{
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
|
||||
TopoDS_Wire aWire;
|
||||
BB.MakeWire(aWire);
|
||||
BB.Add(aWire, anEdge);
|
||||
gp_Pln aPln;
|
||||
Standard_Boolean issing;
|
||||
ComputeAveragePlaneAndMaxDeviation( aWire, aPln, issing );
|
||||
Standard_Real anAngle;
|
||||
if (issing) //edge is a segment of line
|
||||
{
|
||||
//<anAngle> is angle between <anEdge> and its projection on bisector plane
|
||||
BRepAdaptor_Curve BAcurve(anEdge);
|
||||
gp_Pnt FirstPnt = BAcurve.Value(BAcurve.FirstParameter());
|
||||
gp_Pnt LastPnt = BAcurve.Value(BAcurve.LastParameter());
|
||||
gp_Vec EdgeVec(FirstPnt, LastPnt);
|
||||
gp_Ax1 EdgeAxis(FirstPnt, EdgeVec);
|
||||
anAngle = EdgeAxis.Direction().Angle(theAxis.Direction());
|
||||
if (anAngle > M_PI/2)
|
||||
anAngle = M_PI - anAngle;
|
||||
anAngle = M_PI/2 - anAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
anAngle = aPln.Axis().Angle( theAxis );
|
||||
if (anAngle > M_PI/2)
|
||||
anAngle = M_PI - anAngle;
|
||||
}
|
||||
|
||||
if (anAngle < MinAngle)
|
||||
{
|
||||
MinAngle = anAngle;
|
||||
MinEdge = anEdge;
|
||||
}
|
||||
}
|
||||
} //else (more than one edge)
|
||||
|
||||
BB.Remove(theComp, MinEdge);
|
||||
return MinEdge;
|
||||
}
|
||||
|
||||
static Standard_Boolean FindMiddleEdges(const TopoDS_Vertex& theVertex1,
|
||||
const TopoDS_Vertex& theVertex2,
|
||||
const gp_Ax1& theAxis,
|
||||
TopoDS_Compound& theComp,
|
||||
TopTools_ListOfShape& theElist)
|
||||
{
|
||||
TopTools_IndexedDataMapOfShapeListOfShape VEmap;
|
||||
TopExp::MapShapesAndAncestors( theComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap );
|
||||
if (VEmap.IsEmpty())
|
||||
return Standard_False;
|
||||
|
||||
if (!VEmap.Contains(theVertex1) ||
|
||||
!VEmap.Contains(theVertex2))
|
||||
return Standard_False;
|
||||
|
||||
TopoDS_Vertex CurVertex = theVertex1;
|
||||
for (;;)
|
||||
{
|
||||
TopoDS_Edge CurEdge;
|
||||
|
||||
CurEdge = FindEdgeCloseToBisectorPlane(CurVertex, theComp, theAxis);
|
||||
if (CurEdge.IsNull())
|
||||
return Standard_False;
|
||||
|
||||
TopoDS_Vertex V1, V2;
|
||||
TopExp::Vertices(CurEdge, V1, V2);
|
||||
CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
|
||||
|
||||
theElist.Append(CurEdge);
|
||||
if (CurVertex.IsSame(theVertex2))
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
|
||||
static Standard_Boolean FindCommonVertex(const TopoDS_Edge& theFirstEdge,
|
||||
const TopoDS_Edge& theLastEdge,
|
||||
const TopoDS_Vertex& theFirstVertex,
|
||||
const TopoDS_Vertex& theLastVertex,
|
||||
TopoDS_Vertex& theCommonVertex)
|
||||
{
|
||||
if (!theFirstVertex.IsSame(theLastVertex))
|
||||
{
|
||||
Standard_Boolean CommonVertexExists = TopExp::CommonVertex(theFirstEdge,
|
||||
theLastEdge,
|
||||
theCommonVertex);
|
||||
return CommonVertexExists;
|
||||
}
|
||||
|
||||
TopoDS_Vertex V1, V2, V3, V4;
|
||||
TopExp::Vertices(theFirstEdge, V1, V2);
|
||||
TopExp::Vertices(theLastEdge, V3, V4);
|
||||
|
||||
if (V1.IsSame(theFirstVertex))
|
||||
{
|
||||
if (V2.IsSame(V3) ||
|
||||
V2.IsSame(V4))
|
||||
{
|
||||
theCommonVertex = V2;
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (V1.IsSame(V3) ||
|
||||
V1.IsSame(V4))
|
||||
{
|
||||
theCommonVertex = V1;
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_False;
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
#include <BRepFill_TransitionStyle.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
@@ -28,13 +29,14 @@
|
||||
#include <Standard_Boolean.hxx>
|
||||
#include <TopTools_DataMapOfShapeListOfShape.hxx>
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
#include <BOPDS_PDS.hxx>
|
||||
class gp_Ax2;
|
||||
class TopoDS_Face;
|
||||
class TopoDS_Wire;
|
||||
class TopoDS_Shape;
|
||||
|
||||
|
||||
|
||||
//! Trims sets of faces in the corner to make proper parts of pipe
|
||||
class BRepFill_TrimShellCorner
|
||||
{
|
||||
public:
|
||||
@@ -42,12 +44,13 @@ public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
|
||||
Standard_EXPORT BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, const gp_Ax2& theAxeOfBisPlane, const TopoDS_Face& theSecPlane);
|
||||
|
||||
Standard_EXPORT BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, const gp_Ax2& theAxeOfBisPlane, const TopoDS_Wire& theSpine, const TopoDS_Face& theSecPlane);
|
||||
|
||||
Standard_EXPORT void SetSpine (const TopoDS_Wire& theSpine);
|
||||
|
||||
//! Constructor: takes faces to intersect,
|
||||
//! type of transition (it can be RightCorner or RoundCorner)
|
||||
//! and axis of bisector plane
|
||||
Standard_EXPORT BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces,
|
||||
const BRepFill_TransitionStyle theTransition,
|
||||
const gp_Ax2& theAxeOfBisPlane);
|
||||
|
||||
Standard_EXPORT void AddBounds (const Handle(TopTools_HArray2OfShape)& Bounds);
|
||||
|
||||
Standard_EXPORT void AddUEdges (const Handle(TopTools_HArray2OfShape)& theUEdges);
|
||||
@@ -71,13 +74,29 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
Standard_Boolean MakeFacesSec(const Standard_Integer theIndex,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2,
|
||||
const Standard_Integer theSSInterfIndex);
|
||||
|
||||
Standard_Boolean MakeFacesNonSec(const Standard_Integer theIndex,
|
||||
const BOPDS_PDS& theDS,
|
||||
const Standard_Integer theFaceIndex1,
|
||||
const Standard_Integer theFaceIndex2);
|
||||
|
||||
Standard_Boolean ChooseSection(const TopoDS_Shape& Comp,
|
||||
const TopoDS_Vertex& theFirstVertex,
|
||||
const TopoDS_Vertex& theLastVertex,
|
||||
TopoDS_Shape& resWire,
|
||||
gp_Pln& resPlane,
|
||||
Standard_Boolean& IsSingular);
|
||||
|
||||
|
||||
BRepFill_TransitionStyle myTransition;
|
||||
gp_Ax2 myAxeOfBisPlane;
|
||||
TopoDS_Shape myShape1;
|
||||
TopoDS_Shape myShape2;
|
||||
TopoDS_Wire mySpine;
|
||||
TopoDS_Face mySecPln;
|
||||
Handle(TopTools_HArray2OfShape) myBounds;
|
||||
Handle(TopTools_HArray2OfShape) myUEdges;
|
||||
Handle(TopTools_HArray2OfShape) myFaces;
|
||||
|
1794
src/BRepFill/BRepFill_Voluved.cxx
Normal file
1794
src/BRepFill/BRepFill_Voluved.cxx
Normal file
File diff suppressed because it is too large
Load Diff
120
src/BRepFill/BRepFill_Voluved.hxx
Normal file
120
src/BRepFill/BRepFill_Voluved.hxx
Normal file
@@ -0,0 +1,120 @@
|
||||
// Created on: 2018-03-14
|
||||
// Created by: Nikolai BUKHALOV
|
||||
// Copyright (c) 1999-2018 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 _BRepFill_Voluved_HeaderFile
|
||||
#define _BRepFill_Voluved_HeaderFile
|
||||
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopTools_IndexedMapOfShape.hxx>
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
class BOPAlgo_MakerVolume;
|
||||
class TopoDS_Face;
|
||||
|
||||
//! Constructs an evolved volume from a spine (wire or face)
|
||||
//! and a profile ( wire).
|
||||
class BRepFill_Voluved
|
||||
{
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
Standard_EXPORT BRepFill_Voluved() :myErrorStatus(BRepFill_Voluved_Empty),
|
||||
myFuzzyValue(0.0),
|
||||
myIsParallel(Standard_True)
|
||||
{
|
||||
}
|
||||
|
||||
Standard_EXPORT void Perform(const TopoDS_Wire& theSpine, const TopoDS_Wire& theProfile, const Standard_Real theTolerance, const Standard_Boolean theSolidReq = Standard_True);
|
||||
|
||||
Standard_Boolean IsDone(unsigned int* theErrorCode = 0) const
|
||||
{
|
||||
if (theErrorCode)
|
||||
*theErrorCode = myErrorStatus;
|
||||
|
||||
return (myErrorStatus == BRepFill_Voluved_OK);
|
||||
}
|
||||
|
||||
//! returns the resulting shape.
|
||||
const TopoDS_Shape& Shape() const
|
||||
{
|
||||
return myResult;
|
||||
}
|
||||
|
||||
//! Triggers computation mode between Parallel/Single-thread
|
||||
void SetRunParallel(Standard_Boolean theValue)
|
||||
{
|
||||
myIsParallel = theValue;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Standard_EXPORT void PerformSweep();
|
||||
|
||||
Standard_EXPORT void GetLids();
|
||||
|
||||
Standard_EXPORT void BuildSolid();
|
||||
|
||||
Standard_EXPORT void RemoveExcessSolids(const TopTools_ListOfShape& theLSplits,
|
||||
TopoDS_Shape& theShape,
|
||||
TopTools_ListOfShape& theArgsList,
|
||||
BOPAlgo_MakerVolume& theMV);
|
||||
|
||||
Standard_EXPORT void ExtractOuterSolid(TopoDS_Shape& theShape,
|
||||
TopTools_ListOfShape& theArgsList);
|
||||
|
||||
Standard_EXPORT void GetSpineAndProfile(const TopoDS_Wire& theSpine,
|
||||
const TopoDS_Wire& theProfile);
|
||||
|
||||
Standard_EXPORT Standard_Boolean CheckSingularityAndAdd(const TopoDS_Face& theF,
|
||||
const Standard_Real theFuzzyToler,
|
||||
TopTools_ListOfShape& theListOfFaces,
|
||||
TopTools_ListOfShape& theListOfSplits) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
BRepFill_Voluved_Empty = 0,
|
||||
BRepFill_Voluved_NotPlanarSpine,
|
||||
BRepFill_Voluved_SweepError,
|
||||
BRepFill_Voluved_NoLids,
|
||||
BRepFill_Voluved_NotSolid,
|
||||
BRepFill_Voluved_NotVolume,
|
||||
BRepFill_Voluved_OK = UINT_MAX
|
||||
} myErrorStatus;
|
||||
|
||||
TopoDS_Wire mySpine;
|
||||
TopoDS_Wire myProfile;
|
||||
TopoDS_Shape myPipeShell;
|
||||
TopoDS_Compound myTopBottom; // Lids can be split on several faces
|
||||
TopoDS_Shape myResult;
|
||||
Standard_Real myFuzzyValue;
|
||||
Standard_Boolean myIsParallel;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _BRepFill_Voluved_HeaderFile
|
@@ -83,3 +83,5 @@ BRepFill_TrimShellCorner.hxx
|
||||
BRepFill_TrimSurfaceTool.cxx
|
||||
BRepFill_TrimSurfaceTool.hxx
|
||||
BRepFill_TypeOfContact.hxx
|
||||
BRepFill_Voluved.cxx
|
||||
BRepFill_Voluved.hxx
|
@@ -120,7 +120,7 @@ void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
|
||||
aFaces.push_back(aFace);
|
||||
}
|
||||
|
||||
OSD_Parallel::ForEach(aFaces.begin(), aFaces.end(), *this, !myParameters.InParallel);
|
||||
OSD_Parallel::ForEach(aFaces.begin(), aFaces.end(), *this, !myParameters.InParallel, (Standard_Integer )aFaces.size());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -234,7 +234,7 @@ void BRepMesh_IncrementalMesh::update()
|
||||
update(aFaceIt.Value());
|
||||
|
||||
// Mesh faces
|
||||
OSD_Parallel::ForEach(myFaces.begin(), myFaces.end(), *myMesh, !myParameters.InParallel);
|
||||
OSD_Parallel::ForEach(myFaces.begin(), myFaces.end(), *myMesh, !myParameters.InParallel, myFaces.Size());
|
||||
|
||||
commit();
|
||||
clear();
|
||||
|
@@ -22,6 +22,8 @@
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
|
||||
//=======================================================================
|
||||
//function : BRepOffsetAPI_MakeEvolved
|
||||
@@ -43,19 +45,31 @@ BRepOffsetAPI_MakeEvolved::BRepOffsetAPI_MakeEvolved(const TopoDS_Wire& Spin
|
||||
const Standard_Boolean AxeProf,
|
||||
const Standard_Boolean Solid,
|
||||
const Standard_Boolean ProfOnSpine,
|
||||
const Standard_Real Tol)
|
||||
const Standard_Boolean theIsVolume,
|
||||
const Standard_Real Tol,
|
||||
const Standard_Boolean theRunInParallel)
|
||||
{
|
||||
gp_Ax3 Axis(gp_Pnt(0.,0.,0.),
|
||||
gp_Dir(0.,0.,1.),
|
||||
gp_Dir(1.,0.,0.));
|
||||
if (theIsVolume)
|
||||
{
|
||||
myVolume.SetRunParallel(theRunInParallel);
|
||||
myVolume.Perform(Spine, Profil, Tol);
|
||||
}
|
||||
else
|
||||
{
|
||||
gp_Ax3 Axis(gp_Pnt(0., 0., 0.),
|
||||
gp_Dir(0., 0., 1.),
|
||||
gp_Dir(1., 0., 0.));
|
||||
|
||||
if ( !AxeProf) {
|
||||
Standard_Boolean POS;
|
||||
BRepFill::Axe(Spine,Profil,Axis,POS,Tol);
|
||||
if (ProfOnSpine && !POS) return;
|
||||
if (!AxeProf)
|
||||
{
|
||||
Standard_Boolean POS;
|
||||
BRepFill::Axe(Spine, Profil, Axis, POS, Max(Tol, Precision::Confusion()));
|
||||
if (ProfOnSpine && !POS) return;
|
||||
}
|
||||
|
||||
myEvolved.Perform(Spine, Profil, Axis, Join, Solid);
|
||||
}
|
||||
|
||||
myEvolved.Perform(Spine,Profil,Axis,Join,Solid);
|
||||
Build();
|
||||
Done();
|
||||
}
|
||||
@@ -72,20 +86,33 @@ BRepOffsetAPI_MakeEvolved::BRepOffsetAPI_MakeEvolved(const TopoDS_Face& Spin
|
||||
const Standard_Boolean AxeProf,
|
||||
const Standard_Boolean Solid,
|
||||
const Standard_Boolean ProfOnSpine,
|
||||
const Standard_Real Tol)
|
||||
const Standard_Boolean theIsVolume,
|
||||
const Standard_Real Tol,
|
||||
const Standard_Boolean theRunInParallel)
|
||||
{
|
||||
gp_Ax3 Axis(gp_Pnt(0.,0.,0.),
|
||||
gp_Dir(0.,0.,1.),
|
||||
gp_Dir(1.,0.,0.));
|
||||
if (theIsVolume)
|
||||
{
|
||||
myVolume.SetRunParallel(theRunInParallel);
|
||||
myVolume.Perform(TopoDS::Wire(TopoDS_Iterator(Spine).Value()), Profil, Tol);
|
||||
}
|
||||
else
|
||||
{
|
||||
gp_Ax3 Axis(gp_Pnt(0., 0., 0.),
|
||||
gp_Dir(0., 0., 1.),
|
||||
gp_Dir(1., 0., 0.));
|
||||
|
||||
if ( !AxeProf) {
|
||||
Standard_Boolean POS;
|
||||
BRepFill::Axe(Spine,Profil,Axis,POS,Tol);
|
||||
if (ProfOnSpine && !POS) return;
|
||||
if (!AxeProf)
|
||||
{
|
||||
Standard_Boolean POS;
|
||||
BRepFill::Axe(Spine, Profil, Axis, POS, Max(Tol, Precision::Confusion()));
|
||||
if (ProfOnSpine && !POS) return;
|
||||
}
|
||||
|
||||
myEvolved.Perform(Spine, Profil, Axis, Join, Solid);
|
||||
}
|
||||
|
||||
myEvolved.Perform(Spine,Profil,Axis,Join,Solid);
|
||||
Build();
|
||||
Done();
|
||||
}
|
||||
|
||||
|
||||
@@ -107,8 +134,16 @@ const BRepFill_Evolved& BRepOffsetAPI_MakeEvolved::Evolved() const
|
||||
|
||||
void BRepOffsetAPI_MakeEvolved::Build()
|
||||
{
|
||||
myShape = myEvolved.Shape();
|
||||
if (myEvolved.IsDone()) Done();
|
||||
if (myEvolved.IsDone())
|
||||
{
|
||||
myShape = myEvolved.Shape();
|
||||
}
|
||||
else if (myVolume.IsDone())
|
||||
{
|
||||
myShape = myVolume.Shape();
|
||||
}
|
||||
|
||||
Done();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
#include <BRepFill_Evolved.hxx>
|
||||
#include <BRepFill_Voluved.hxx>
|
||||
#include <BRepBuilderAPI_MakeShape.hxx>
|
||||
#include <GeomAbs_JoinType.hxx>
|
||||
#include <Standard_Boolean.hxx>
|
||||
@@ -66,7 +67,7 @@ public:
|
||||
|
||||
Standard_EXPORT BRepOffsetAPI_MakeEvolved();
|
||||
|
||||
Standard_EXPORT BRepOffsetAPI_MakeEvolved(const TopoDS_Wire& Spine, const TopoDS_Wire& Profil, const GeomAbs_JoinType Join = GeomAbs_Arc, const Standard_Boolean AxeProf = Standard_True, const Standard_Boolean Solid = Standard_False, const Standard_Boolean ProfOnSpine = Standard_False, const Standard_Real Tol = 0.0000001);
|
||||
Standard_EXPORT BRepOffsetAPI_MakeEvolved(const TopoDS_Wire& Spine, const TopoDS_Wire& Profil, const GeomAbs_JoinType Join/* = GeomAbs_Arc*/, const Standard_Boolean AxeProf/* = Standard_True*/, const Standard_Boolean Solid/* = Standard_False*/, const Standard_Boolean ProfOnSpine/* = Standard_False*/, const Standard_Boolean theIsVolume, const Standard_Real Tol/* = Precision::Confusion()*/, const Standard_Boolean theRunInParallel);
|
||||
|
||||
//! These constructors construct an evolved shape by sweeping the profile
|
||||
//! Profile along the spine Spine.
|
||||
@@ -88,7 +89,7 @@ public:
|
||||
//! axis passing along the vertex and the normal to the
|
||||
//! plane of the spine. At present, this is the only
|
||||
//! construction type implemented.
|
||||
Standard_EXPORT BRepOffsetAPI_MakeEvolved(const TopoDS_Face& Spine, const TopoDS_Wire& Profil, const GeomAbs_JoinType Join = GeomAbs_Arc, const Standard_Boolean AxeProf = Standard_True, const Standard_Boolean Solid = Standard_False, const Standard_Boolean ProfOnSpine = Standard_False, const Standard_Real Tol = 0.0000001);
|
||||
Standard_EXPORT BRepOffsetAPI_MakeEvolved(const TopoDS_Face& Spine, const TopoDS_Wire& Profil, const GeomAbs_JoinType Join/* = GeomAbs_Arc*/, const Standard_Boolean AxeProf/* = Standard_True*/, const Standard_Boolean Solid/* = Standard_False*/, const Standard_Boolean ProfOnSpine/* = Standard_False*/, const Standard_Boolean theIsVolume, const Standard_Real Tol/* = Precision::Confusion()*/, const Standard_Boolean theRunInParallel);
|
||||
|
||||
Standard_EXPORT const BRepFill_Evolved& Evolved() const;
|
||||
|
||||
@@ -118,9 +119,8 @@ protected:
|
||||
private:
|
||||
|
||||
|
||||
|
||||
BRepFill_Evolved myEvolved;
|
||||
|
||||
BRepFill_Voluved myVolume;
|
||||
|
||||
};
|
||||
|
||||
|
@@ -33,8 +33,6 @@
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
BRepOffsetAPI_MakePipeShell::BRepOffsetAPI_MakePipeShell(const TopoDS_Wire& Spine)
|
||||
|
||||
|
||||
{
|
||||
myPipe = new (BRepFill_PipeShell) (Spine);
|
||||
SetTolerance();
|
||||
|
@@ -211,7 +211,7 @@ public:
|
||||
//! discontinuities are treated like round
|
||||
//! corner. The corner is treated as rotation
|
||||
//! of the profile around an axis which
|
||||
//! passes through the point of the spine?s
|
||||
//! passes through the point of the spine's
|
||||
//! fracture. This axis is based on cross
|
||||
//! product of directions tangent to the
|
||||
//! adjacent segments of the spine at their common point.
|
||||
@@ -276,7 +276,6 @@ private:
|
||||
|
||||
Handle(BRepFill_PipeShell) myPipe;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@@ -237,33 +237,93 @@ Standard_Integer evolved(Draw_Interpretor& di, Standard_Integer n, const char**
|
||||
|
||||
if ( n < 4 ) return 1;
|
||||
Standard_Boolean IsAFace = Standard_False;
|
||||
Standard_Boolean Solid = (!strcmp(a[0],"evolvedsolid"));
|
||||
Standard_Boolean Solid = Standard_False;
|
||||
Standard_Boolean isVolume = Standard_False;
|
||||
Standard_Boolean hasToComputeAxes = Standard_False;
|
||||
Standard_Real aTolerance = 0.0;
|
||||
TopoDS_Shape Base;
|
||||
TopoDS_Wire Prof;
|
||||
Standard_Boolean isParallel = Standard_True;
|
||||
|
||||
for (Standard_Integer i = 2; i < n; i++)
|
||||
{
|
||||
if (a[i][0] != '-')
|
||||
{
|
||||
di << "Error: wrong option!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(a[i], "-solid"))
|
||||
{
|
||||
Solid = Standard_True;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(a[i], "-stm"))
|
||||
{
|
||||
isParallel = Standard_False;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (a[i][1])
|
||||
{
|
||||
case 's':
|
||||
{
|
||||
Base = DBRep::Get(a[++i], TopAbs_WIRE, Standard_False);
|
||||
if (Base.IsNull())
|
||||
{
|
||||
Base = DBRep::Get(a[i], TopAbs_FACE, Standard_False);
|
||||
IsAFace = Standard_True;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
{
|
||||
Prof = TopoDS::Wire(DBRep::Get(a[++i], TopAbs_WIRE, Standard_False));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
{
|
||||
isVolume = Standard_True;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
{
|
||||
hasToComputeAxes = Standard_True;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
{
|
||||
aTolerance = Draw::Atof(a[++i]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
di << "Error: Unknown option!\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TopoDS_Shape Base = DBRep::Get(a[2],TopAbs_WIRE,Standard_False);
|
||||
if ( Base.IsNull()) {
|
||||
Base = DBRep::Get(a[2],TopAbs_FACE,Standard_False);
|
||||
IsAFace = Standard_True;
|
||||
if (Base.IsNull() || Prof.IsNull())
|
||||
{
|
||||
di << "Error: Null-shapes are not allowed\n";
|
||||
return 1;
|
||||
}
|
||||
if ( Base.IsNull()) return 1;
|
||||
|
||||
TopoDS_Shape InpuTShape(DBRep::Get(a[3],TopAbs_WIRE,Standard_False));
|
||||
TopoDS_Wire Prof = TopoDS::Wire(InpuTShape);
|
||||
// TopoDS_Wire Prof =
|
||||
// TopoDS::Wire(DBRep::Get(a[3],TopAbs_WIRE,Standard_False));
|
||||
if ( Prof.IsNull()) return 1;
|
||||
TopoDS_Shape Volevo = IsAFace ? BRepOffsetAPI_MakeEvolved(TopoDS::Face(Base),
|
||||
Prof, GeomAbs_Arc, !hasToComputeAxes,
|
||||
Solid, Standard_False, isVolume,
|
||||
aTolerance, isParallel) :
|
||||
BRepOffsetAPI_MakeEvolved(TopoDS::Wire(Base),
|
||||
Prof, GeomAbs_Arc, !hasToComputeAxes,
|
||||
Solid, Standard_False, isVolume,
|
||||
aTolerance, isParallel);
|
||||
|
||||
if (IsAFace) {
|
||||
TopoDS_Shape Volevo
|
||||
= BRepOffsetAPI_MakeEvolved(TopoDS::Face(Base),Prof,GeomAbs_Arc,n == 4,Solid);
|
||||
DBRep::Set(a[1],Volevo);
|
||||
}
|
||||
else {
|
||||
TopoDS_Shape Volevo
|
||||
= BRepOffsetAPI_MakeEvolved(TopoDS::Wire(Base),Prof,GeomAbs_Arc,n == 4,Solid);
|
||||
DBRep::Set(a[1],Volevo);
|
||||
}
|
||||
DBRep::Set(a[1],Volevo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -785,7 +845,11 @@ static Standard_Integer buildsweep(Draw_Interpretor& di,
|
||||
Sweep->SetTransitionMode(Transition);
|
||||
}
|
||||
// Reading solid ?
|
||||
if ((n>cur) && (!strcmp(a[cur],"-S")) ) mksolid = Standard_True;
|
||||
if ((n > cur) && (!strcmp(a[cur], "-S")))
|
||||
{
|
||||
mksolid = Standard_True;
|
||||
++cur;
|
||||
}
|
||||
|
||||
// Calcul le resultat
|
||||
Sweep->Build();
|
||||
@@ -979,10 +1043,6 @@ void BRepTest::SweepCommands(Draw_Interpretor& theCommands)
|
||||
"evolved , no args to get help",
|
||||
__FILE__,evolved,g);
|
||||
|
||||
theCommands.Add("evolvedsolid",
|
||||
"evolved , no args to get help",
|
||||
__FILE__,evolved,g);
|
||||
|
||||
theCommands.Add("pruled",
|
||||
"pruled result Edge1/Wire1 Edge2/Wire2",
|
||||
__FILE__,pruled,g);
|
||||
|
2705
src/BRepTest/QABugs_20.cxx
Normal file
2705
src/BRepTest/QABugs_20.cxx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -595,6 +595,14 @@ proc checkprops {shape args} {
|
||||
if { $m == 0 } {
|
||||
puts "Error : The command is not valid. The $prop is 0."
|
||||
}
|
||||
# Provide comparation with negative value
|
||||
if { [expr $mass*$m ] < 0.0 } {
|
||||
# Value and expected value have different sign
|
||||
puts "Error : The $prop of result shape is $m"
|
||||
} else {
|
||||
set mass [expr abs($mass)]
|
||||
set m [expr abs($m)]
|
||||
}
|
||||
if { $mass > 0 } {
|
||||
puts "The expected $prop is $mass"
|
||||
}
|
||||
|
@@ -66,9 +66,10 @@ namespace
|
||||
|
||||
//! Auxiliary method to convert FT_Vector to gp_XY
|
||||
static gp_XY readFTVec (const FT_Vector& theVec,
|
||||
const Standard_Real theScaleUnits)
|
||||
const Standard_Real theScaleUnits,
|
||||
const Standard_Real theWidthScaling = 1.0)
|
||||
{
|
||||
return gp_XY (theScaleUnits * Standard_Real(theVec.x) / 64.0, theScaleUnits * Standard_Real(theVec.y) / 64.0);
|
||||
return gp_XY (theScaleUnits * Standard_Real(theVec.x) * theWidthScaling / 64.0, theScaleUnits * Standard_Real(theVec.y) / 64.0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -265,7 +266,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
|
||||
TopLoc_Location aLoc;
|
||||
TopoDS_Face aFaceDraft;
|
||||
myBuilder.MakeFace (aFaceDraft, mySurface, myPrecision);
|
||||
TopoDS_Compound aFaceCompDraft;
|
||||
|
||||
// Get orientation is useless since it doesn't retrieve any in-font information and just computes orientation.
|
||||
// Because it fails in some cases - leave this to ShapeFix.
|
||||
@@ -277,7 +278,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
const short anEndIndex = anOutline.contours[aContour];
|
||||
const short aPntsNb = (anEndIndex - aStartIndex) + 1;
|
||||
aStartIndex = anEndIndex + 1;
|
||||
if (aPntsNb < 3)
|
||||
if (aPntsNb < 3 && !myIsSingleLine)
|
||||
{
|
||||
// closed contour can not be constructed from < 3 points
|
||||
continue;
|
||||
@@ -286,10 +287,11 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
BRepBuilderAPI_MakeWire aWireMaker;
|
||||
|
||||
gp_XY aPntPrev;
|
||||
gp_XY aPntCurr = readFTVec (aPntList[aPntsNb - 1], myScaleUnits);
|
||||
gp_XY aPntNext = readFTVec (aPntList[0], myScaleUnits);
|
||||
gp_XY aPntCurr = readFTVec (aPntList[aPntsNb - 1], myScaleUnits, myWidthScaling);
|
||||
gp_XY aPntNext = readFTVec (aPntList[0], myScaleUnits, myWidthScaling);
|
||||
|
||||
Standard_Integer aLinePnts = (FT_CURVE_TAG(aTags[aPntsNb - 1]) == FT_Curve_Tag_On) ? 1 : 0;
|
||||
bool isLineSeg = !myIsSingleLine
|
||||
&& FT_CURVE_TAG(aTags[aPntsNb - 1]) == FT_Curve_Tag_On;
|
||||
gp_XY aPntLine1 = aPntCurr;
|
||||
|
||||
// see http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-6.html
|
||||
@@ -298,15 +300,15 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
{
|
||||
aPntPrev = aPntCurr;
|
||||
aPntCurr = aPntNext;
|
||||
aPntNext = readFTVec (aPntList[(aPntId + 1) % aPntsNb], myScaleUnits);
|
||||
aPntNext = readFTVec (aPntList[(aPntId + 1) % aPntsNb], myScaleUnits, myWidthScaling);
|
||||
|
||||
// process tags
|
||||
if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_On)
|
||||
{
|
||||
if (aLinePnts < 1)
|
||||
if (!isLineSeg)
|
||||
{
|
||||
aPntLine1 = aPntCurr;
|
||||
aLinePnts = 1;
|
||||
isLineSeg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -315,7 +317,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
if (aLen <= myPrecision)
|
||||
{
|
||||
aPntLine1 = aPntCurr;
|
||||
aLinePnts = 1;
|
||||
isLineSeg = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -339,7 +341,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
}
|
||||
else if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_Conic)
|
||||
{
|
||||
aLinePnts = 0;
|
||||
isLineSeg = false;
|
||||
gp_XY aPntPrev2 = aPntPrev;
|
||||
gp_XY aPntNext2 = aPntNext;
|
||||
|
||||
@@ -378,11 +380,11 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
else if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_Cubic
|
||||
&& FT_CURVE_TAG(aTags[(aPntId + 1) % aPntsNb]) == FT_Curve_Tag_Cubic)
|
||||
{
|
||||
aLinePnts = 0;
|
||||
isLineSeg = false;
|
||||
my4Poles.SetValue (1, aPntPrev);
|
||||
my4Poles.SetValue (2, aPntCurr);
|
||||
my4Poles.SetValue (3, aPntNext);
|
||||
my4Poles.SetValue (4, gp_Pnt2d(readFTVec (aPntList[(aPntId + 2) % aPntsNb], myScaleUnits)));
|
||||
my4Poles.SetValue (4, gp_Pnt2d(readFTVec (aPntList[(aPntId + 2) % aPntsNb], myScaleUnits, myWidthScaling)));
|
||||
Handle(Geom2d_BezierCurve) aBezier = new Geom2d_BezierCurve (my4Poles);
|
||||
if (myIsCompositeCurve)
|
||||
{
|
||||
@@ -411,7 +413,8 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
|
||||
const gp_Pnt2d aFirstPnt = aDraft2d->StartPoint();
|
||||
const gp_Pnt2d aLastPnt = aDraft2d->EndPoint();
|
||||
if (!aFirstPnt.IsEqual (aLastPnt, myPrecision))
|
||||
if (!myIsSingleLine
|
||||
&& !aFirstPnt.IsEqual (aLastPnt, myPrecision))
|
||||
{
|
||||
Handle(Geom2d_TrimmedCurve) aLine = GCE2d_MakeSegment (aLastPnt, aFirstPnt);
|
||||
myConcatMaker.Add (aLine, myPrecision);
|
||||
@@ -438,7 +441,8 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
TopExp::Vertices (aWireMaker.Wire(), aFirstV, aLastV);
|
||||
gp_Pnt aFirstPoint = BRep_Tool::Pnt (aFirstV);
|
||||
gp_Pnt aLastPoint = BRep_Tool::Pnt (aLastV);
|
||||
if (!aFirstPoint.IsEqual (aLastPoint, myPrecision))
|
||||
if (!myIsSingleLine
|
||||
&& !aFirstPoint.IsEqual (aLastPoint, myPrecision))
|
||||
{
|
||||
aWireMaker.Add (BRepLib_MakeEdge (aFirstV, aLastV));
|
||||
}
|
||||
@@ -450,31 +454,64 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
}
|
||||
|
||||
TopoDS_Wire aWireDraft = aWireMaker.Wire();
|
||||
//if (anOrient == FT_ORIENTATION_FILL_LEFT)
|
||||
//{
|
||||
// According to the TrueType specification, clockwise contours must be filled
|
||||
aWireDraft.Reverse();
|
||||
//}
|
||||
myBuilder.Add (aFaceDraft, aWireDraft);
|
||||
if (!myIsSingleLine)
|
||||
{
|
||||
//if (anOrient == FT_ORIENTATION_FILL_LEFT)
|
||||
//{
|
||||
// According to the TrueType specification, clockwise contours must be filled
|
||||
aWireDraft.Reverse();
|
||||
//}
|
||||
if (aFaceDraft.IsNull())
|
||||
{
|
||||
myBuilder.MakeFace (aFaceDraft, mySurface, myPrecision);
|
||||
}
|
||||
myBuilder.Add (aFaceDraft, aWireDraft);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aFaceCompDraft.IsNull())
|
||||
{
|
||||
myBuilder.MakeCompound (aFaceCompDraft);
|
||||
}
|
||||
myBuilder.Add (aFaceCompDraft, aWireDraft);
|
||||
}
|
||||
}
|
||||
|
||||
myFixer.Init (aFaceDraft);
|
||||
myFixer.Perform();
|
||||
theShape = myFixer.Result();
|
||||
if (!theShape.IsNull()
|
||||
&& theShape.ShapeType() != TopAbs_FACE)
|
||||
if (!aFaceDraft.IsNull())
|
||||
{
|
||||
// shape fix can not fix orientation within the single call
|
||||
TopoDS_Compound aComp;
|
||||
myBuilder.MakeCompound (aComp);
|
||||
for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
|
||||
myFixer.Init (aFaceDraft);
|
||||
myFixer.Perform();
|
||||
TopoDS_Shape aFixResult = myFixer.Result();
|
||||
if (!aFixResult.IsNull()
|
||||
&& aFixResult.ShapeType() != TopAbs_FACE)
|
||||
{
|
||||
TopoDS_Face aFace = TopoDS::Face (aFaceIter.Current());
|
||||
myFixer.Init (aFace);
|
||||
myFixer.Perform();
|
||||
myBuilder.Add (aComp, myFixer.Result());
|
||||
// shape fix can not fix orientation within the single call
|
||||
if (aFaceCompDraft.IsNull())
|
||||
{
|
||||
myBuilder.MakeCompound (aFaceCompDraft);
|
||||
}
|
||||
for (TopExp_Explorer aFaceIter (aFixResult, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
|
||||
{
|
||||
TopoDS_Face aFace = TopoDS::Face (aFaceIter.Current());
|
||||
myFixer.Init (aFace);
|
||||
myFixer.Perform();
|
||||
myBuilder.Add (aFaceCompDraft, myFixer.Result());
|
||||
}
|
||||
theShape = aFaceCompDraft;
|
||||
}
|
||||
theShape = aComp;
|
||||
else if (!aFaceCompDraft.IsNull())
|
||||
{
|
||||
myBuilder.Add (aFaceCompDraft, aFixResult);
|
||||
theShape = aFaceCompDraft;
|
||||
}
|
||||
else
|
||||
{
|
||||
theShape = aFixResult;
|
||||
}
|
||||
}
|
||||
else if (!aFaceCompDraft.IsNull())
|
||||
{
|
||||
theShape = aFaceCompDraft;
|
||||
}
|
||||
|
||||
myCache.Bind (theChar, theShape);
|
||||
|
@@ -29,12 +29,14 @@ IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
|
||||
: myFTLib (theFTLib),
|
||||
myFTFace (NULL),
|
||||
myPointSize (0U),
|
||||
myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
|
||||
myKernAdvance(new FT_Vector()),
|
||||
myUChar (0U)
|
||||
: myFTLib (theFTLib),
|
||||
myFTFace (NULL),
|
||||
myPointSize (0U),
|
||||
myWidthScaling(1.0),
|
||||
myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
|
||||
myIsSingleLine(false),
|
||||
myKernAdvance (new FT_Vector()),
|
||||
myUChar (0U)
|
||||
{
|
||||
if (myFTLib.IsNull())
|
||||
{
|
||||
@@ -118,9 +120,12 @@ bool Font_FTFont::Init (const NCollection_String& theFontName,
|
||||
{
|
||||
Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
|
||||
const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
|
||||
Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
|
||||
return !aRequestedFont.IsNull()
|
||||
&& Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
|
||||
if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize))
|
||||
{
|
||||
myIsSingleLine = aRequestedFont->IsSingleStrokeFont();
|
||||
return Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@@ -263,12 +268,19 @@ float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
|
||||
|| FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
|
||||
FT_Pos aKerningX = 0;
|
||||
if (theUCharNext != 0
|
||||
&& FT_HAS_KERNING (myFTFace) != 0)
|
||||
{
|
||||
return fromFTPoints<float> (myFTFace->glyph->advance.x);
|
||||
const FT_UInt aCharCurr = FT_Get_Char_Index (myFTFace, myUChar);
|
||||
const FT_UInt aCharNext = FT_Get_Char_Index (myFTFace, theUCharNext);
|
||||
if (aCharCurr != 0 && aCharNext != 0
|
||||
&& FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, myKernAdvance) == 0)
|
||||
{
|
||||
aKerningX = myKernAdvance->x;
|
||||
}
|
||||
}
|
||||
return fromFTPoints<float> (myKernAdvance->x + myFTFace->glyph->advance.x);
|
||||
return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x + aKerningX);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@@ -282,12 +294,19 @@ float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
|
||||
|| FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
|
||||
FT_Pos aKerningY = 0;
|
||||
if (theUCharNext != 0
|
||||
&& FT_HAS_KERNING (myFTFace) != 0)
|
||||
{
|
||||
return fromFTPoints<float> (myFTFace->glyph->advance.y);
|
||||
const FT_UInt aCharCurr = FT_Get_Char_Index (myFTFace, myUChar);
|
||||
const FT_UInt aCharNext = FT_Get_Char_Index (myFTFace, theUCharNext);
|
||||
if (aCharCurr != 0 && aCharNext != 0
|
||||
&& FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, myKernAdvance) == 0)
|
||||
{
|
||||
aKerningY = myKernAdvance->y;
|
||||
}
|
||||
}
|
||||
return fromFTPoints<float> (myKernAdvance->y + myFTFace->glyph->advance.y);
|
||||
return fromFTPoints<float> (myFTFace->glyph->advance.y + aKerningY);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@@ -73,6 +73,13 @@ public:
|
||||
const unsigned int thePointSize,
|
||||
const unsigned int theResolution);
|
||||
|
||||
//! Return TRUE if this is single-stroke (one-line) font, FALSE by default.
|
||||
//! Such fonts define single-line glyphs instead of closed contours, so that they are rendered incorrectly by normal software.
|
||||
bool IsSingleStrokeFont() const { return myIsSingleLine; }
|
||||
|
||||
//! Set if this font should be rendered as single-stroke (one-line).
|
||||
void SetSingleStrokeFont (bool theIsSingleLine) { myIsSingleLine = theIsSingleLine; }
|
||||
|
||||
//! Release currently loaded font.
|
||||
Standard_EXPORT virtual void Release();
|
||||
|
||||
@@ -100,6 +107,13 @@ public:
|
||||
return myPointSize;
|
||||
}
|
||||
|
||||
//! Setup glyph scaling along X-axis.
|
||||
//! By default glyphs are not scaled (scaling factor = 1.0)
|
||||
void SetWidthScaling (const float theScaleFactor)
|
||||
{
|
||||
myWidthScaling = theScaleFactor;
|
||||
}
|
||||
|
||||
//! Compute advance to the next character with kerning applied when applicable.
|
||||
//! Assuming text rendered horizontally.
|
||||
Standard_EXPORT float AdvanceX (const Standard_Utf32Char theUCharNext);
|
||||
@@ -154,15 +168,17 @@ protected:
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Font_FTLibrary) myFTLib; //!< handle to the FT library object
|
||||
FT_Face myFTFace; //!< FT face object
|
||||
NCollection_String myFontPath; //!< font path
|
||||
unsigned int myPointSize; //!< point size set by FT_Set_Char_Size
|
||||
int32_t myLoadFlags; //!< default load flags
|
||||
Handle(Font_FTLibrary) myFTLib; //!< handle to the FT library object
|
||||
FT_Face myFTFace; //!< FT face object
|
||||
NCollection_String myFontPath; //!< font path
|
||||
unsigned int myPointSize; //!< point size set by FT_Set_Char_Size
|
||||
float myWidthScaling; //!< scale glyphs along X-axis
|
||||
int32_t myLoadFlags; //!< default load flags
|
||||
bool myIsSingleLine; //!< single stroke font flag, FALSE by default
|
||||
|
||||
Image_PixMap myGlyphImg; //!< cached glyph plane
|
||||
FT_Vector* myKernAdvance; //!< buffer variable
|
||||
Standard_Utf32Char myUChar; //!< currently loaded unicode character
|
||||
Image_PixMap myGlyphImg; //!< cached glyph plane
|
||||
FT_Vector* myKernAdvance; //!< buffer variable
|
||||
Standard_Utf32Char myUChar; //!< currently loaded unicode character
|
||||
|
||||
public:
|
||||
|
||||
|
@@ -49,7 +49,8 @@ static const Font_FontMgr_FontAliasMapNode Font_FontMgr_MapOfFontsAliases[] =
|
||||
{ "Symbol" , "Symbol" , Font_FA_Regular },
|
||||
{ "ZapfDingbats" , "WingDings" , Font_FA_Regular },
|
||||
{ "Rock" , "Arial" , Font_FA_Regular },
|
||||
{ "Iris" , "Lucida Console" , Font_FA_Regular }
|
||||
{ "Iris" , "Lucida Console" , Font_FA_Regular },
|
||||
{ "NSimSun" , "SimSun" , Font_FA_Regular }
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
|
||||
@@ -218,6 +219,8 @@ static Handle(Font_SystemFont) checkFont (const Handle(Font_FTLibrary)& theFTLib
|
||||
Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (aFontFace->family_name);
|
||||
Handle(TCollection_HAsciiString) aFontPath = new TCollection_HAsciiString (theFontPath);
|
||||
aResult = new Font_SystemFont (aFontName, anAspect, aFontPath);
|
||||
// automatically identify some known single-line fonts
|
||||
aResult->SetSingleStrokeFont (aFontName->String().StartsWith ("OLF "));
|
||||
}
|
||||
|
||||
FT_Done_Face (aFontFace);
|
||||
|
@@ -13,126 +13,113 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// Updated:
|
||||
|
||||
#include <Font_SystemFont.hxx>
|
||||
|
||||
#include <OSD_Path.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
#include <TCollection_HAsciiString.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Font_SystemFont,Standard_Transient)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Font_SystemFont, Standard_Transient)
|
||||
|
||||
Font_SystemFont::Font_SystemFont():
|
||||
MyFontName(),
|
||||
MyFontAspect(Font_FA_Undefined),
|
||||
MyFaceSize(-1),
|
||||
MyVerification(Standard_False)
|
||||
// =======================================================================
|
||||
// function : Font_SystemFont
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Font_SystemFont::Font_SystemFont()
|
||||
: myFontAspect (Font_FA_Undefined),
|
||||
myFaceSize (-1),
|
||||
myIsSingleLine (Standard_False),
|
||||
myIsDefined (Standard_False)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
Font_SystemFont::Font_SystemFont( const Handle(TCollection_HAsciiString)& FontName,
|
||||
const Font_FontAspect FontAspect,
|
||||
const Handle(TCollection_HAsciiString)& FilePath ):
|
||||
MyFontName(FontName),
|
||||
MyFontAspect(FontAspect),
|
||||
MyFaceSize(-1),
|
||||
MyFilePath(FilePath),
|
||||
MyVerification(Standard_True)
|
||||
// =======================================================================
|
||||
// function : Font_SystemFont
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Font_SystemFont::Font_SystemFont (const Handle(TCollection_HAsciiString)& theFontName,
|
||||
const Font_FontAspect theFontAspect,
|
||||
const Handle(TCollection_HAsciiString)& theFilePath)
|
||||
: myFontName (theFontName),
|
||||
myFontAspect (theFontAspect),
|
||||
myFaceSize (-1),
|
||||
myFilePath (theFilePath),
|
||||
myIsSingleLine (Standard_False),
|
||||
myIsDefined (Standard_True)
|
||||
{
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Font_SystemFont
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Font_SystemFont::Font_SystemFont (const Handle(TCollection_HAsciiString)& theXLFD,
|
||||
const Handle(TCollection_HAsciiString)& theFilePath) :
|
||||
MyFontAspect(Font_FA_Regular),
|
||||
MyFaceSize(-1),
|
||||
MyFilePath(theFilePath)
|
||||
const Handle(TCollection_HAsciiString)& theFilePath)
|
||||
: myFontAspect (Font_FA_Regular),
|
||||
myFaceSize (-1),
|
||||
myFilePath (theFilePath),
|
||||
myIsSingleLine (Standard_False),
|
||||
myIsDefined (Standard_True)
|
||||
{
|
||||
MyVerification = Standard_True;
|
||||
if (theXLFD.IsNull())
|
||||
if (theXLFD.IsNull()
|
||||
|| theXLFD->IsEmpty())
|
||||
{
|
||||
MyVerification = Standard_False; // empty font description handler
|
||||
}
|
||||
if (theXLFD->IsEmpty())
|
||||
{
|
||||
MyVerification = Standard_False; // empty font description
|
||||
myIsDefined = Standard_False;
|
||||
return;
|
||||
}
|
||||
|
||||
if (MyVerification)
|
||||
myFontName = theXLFD->Token ("-", 2);
|
||||
const TCollection_AsciiString& aXLFD = theXLFD->String();
|
||||
|
||||
// Getting font size for fixed size fonts
|
||||
if (aXLFD.Search ("-0-0-0-0-") >= 0)
|
||||
{
|
||||
MyFontName = theXLFD->Token ("-", 2);
|
||||
TCollection_AsciiString aXLFD (theXLFD->ToCString());
|
||||
myFaceSize = -1; // Scalable font
|
||||
}
|
||||
else
|
||||
{
|
||||
myFaceSize = aXLFD.Token ("-", 7).IntegerValue();
|
||||
}
|
||||
|
||||
// Getting font size for fixed size fonts
|
||||
if (aXLFD.Search ("-0-0-0-0-") >= 0)
|
||||
MyFaceSize = -1; // Scalable font
|
||||
else
|
||||
//TODO catch exeption
|
||||
MyFaceSize = aXLFD.Token ("-", 7).IntegerValue();
|
||||
|
||||
// Detect font aspect
|
||||
if (aXLFD.Token ("-", 3).IsEqual ("bold") &&
|
||||
(aXLFD.Token ("-", 4).IsEqual ("i") || aXLFD.Token ("-", 4).IsEqual ("o")))
|
||||
{
|
||||
MyFontAspect = Font_FA_BoldItalic;
|
||||
}
|
||||
else if (aXLFD.Token ("-", 3).IsEqual ("bold"))
|
||||
{
|
||||
MyFontAspect = Font_FA_Bold;
|
||||
}
|
||||
else if (aXLFD.Token ("-", 4).IsEqual ("i") || aXLFD.Token ("-", 4).IsEqual ("o"))
|
||||
{
|
||||
MyFontAspect = Font_FA_Italic;
|
||||
}
|
||||
// Detect font aspect
|
||||
if (aXLFD.Token ("-", 3).IsEqual ("bold")
|
||||
&& (aXLFD.Token ("-", 4).IsEqual ("i")
|
||||
|| aXLFD.Token ("-", 4).IsEqual ("o")))
|
||||
{
|
||||
myFontAspect = Font_FA_BoldItalic;
|
||||
}
|
||||
else if (aXLFD.Token ("-", 3).IsEqual ("bold"))
|
||||
{
|
||||
myFontAspect = Font_FA_Bold;
|
||||
}
|
||||
else if (aXLFD.Token ("-", 4).IsEqual ("i")
|
||||
|| aXLFD.Token ("-", 4).IsEqual ("o"))
|
||||
{
|
||||
myFontAspect = Font_FA_Italic;
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Boolean Font_SystemFont::IsValid() const{
|
||||
if ( !MyVerification)
|
||||
return Standard_False;
|
||||
|
||||
if ( MyFontAspect == Font_FA_Undefined )
|
||||
return Standard_False;
|
||||
|
||||
if ( MyFontName->IsEmpty() || !MyFontName->IsAscii() )
|
||||
return Standard_False;
|
||||
|
||||
OSD_Path path;
|
||||
return path.IsValid( MyFilePath->String() );
|
||||
}
|
||||
|
||||
Handle(TCollection_HAsciiString) Font_SystemFont::FontPath() const{
|
||||
return MyFilePath;
|
||||
}
|
||||
|
||||
Handle(TCollection_HAsciiString) Font_SystemFont::FontName() const{
|
||||
return MyFontName;
|
||||
}
|
||||
|
||||
Font_FontAspect Font_SystemFont::FontAspect() const{
|
||||
return MyFontAspect;
|
||||
}
|
||||
|
||||
Standard_Integer Font_SystemFont::FontHeight() const {
|
||||
return MyFaceSize;
|
||||
}
|
||||
|
||||
Standard_Boolean Font_SystemFont::IsEqual(const Handle(Font_SystemFont)& theOtherFont) const
|
||||
// =======================================================================
|
||||
// function : IsValid
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Boolean Font_SystemFont::IsValid() const
|
||||
{
|
||||
if (!MyFontName->IsSameString (theOtherFont->FontName(), Standard_False))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if (MyFontAspect != theOtherFont->FontAspect())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
if (MyFaceSize != theOtherFont->FontHeight())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
return myIsDefined
|
||||
&& myFontAspect != Font_FA_Undefined
|
||||
&& !myFontName->IsEmpty()
|
||||
&& OSD_Path::IsValid (myFilePath->String());
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : IsEqual
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Boolean Font_SystemFont::IsEqual (const Handle(Font_SystemFont)& theOtherFont) const
|
||||
{
|
||||
return myFontName->IsSameString (myFontName, Standard_False)
|
||||
&& myFontAspect == theOtherFont->myFontAspect
|
||||
&& myFaceSize == theOtherFont->myFaceSize;
|
||||
}
|
||||
|
@@ -25,76 +25,60 @@
|
||||
#include <Standard_Transient.hxx>
|
||||
class TCollection_HAsciiString;
|
||||
|
||||
|
||||
class Font_SystemFont;
|
||||
DEFINE_STANDARD_HANDLE(Font_SystemFont, Standard_Transient)
|
||||
|
||||
//! Structure for store of Font System Information
|
||||
//! This class stores information about the font, which is merely a file path and cached metadata about the font.
|
||||
class Font_SystemFont : public Standard_Transient
|
||||
{
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(Font_SystemFont, Standard_Transient)
|
||||
public:
|
||||
|
||||
|
||||
//! Creates empty font object
|
||||
//! Creates an empty font object.
|
||||
Standard_EXPORT Font_SystemFont();
|
||||
|
||||
//! Creates a new font object.
|
||||
Standard_EXPORT Font_SystemFont (const Handle(TCollection_HAsciiString)& theFontName,
|
||||
const Font_FontAspect theFontAspect,
|
||||
const Handle(TCollection_HAsciiString)& theFilePath);
|
||||
|
||||
//! Creates a font object and initialize class fields with values taken from XLFD (X Logical Font Description)
|
||||
Standard_EXPORT Font_SystemFont (const Handle(TCollection_HAsciiString)& theXLFD,
|
||||
const Handle(TCollection_HAsciiString)& theFilePath);
|
||||
|
||||
//! Returns font family name.
|
||||
const Handle(TCollection_HAsciiString)& FontName() const { return myFontName; }
|
||||
|
||||
//! Creates Font object initialized with <FontName> as name
|
||||
//! <FontAspect>.... TODO
|
||||
Standard_EXPORT Font_SystemFont(const Handle(TCollection_HAsciiString)& theFontName, const Font_FontAspect theFontAspect, const Handle(TCollection_HAsciiString)& theFilePath);
|
||||
//! Returns font file path.
|
||||
const Handle(TCollection_HAsciiString)& FontPath() const { return myFilePath; }
|
||||
|
||||
//! Creates Font object and initialize class fields with
|
||||
//! values taken from XLFD (X Logical Font Description)
|
||||
Standard_EXPORT Font_SystemFont(const Handle(TCollection_HAsciiString)& theXLFD, const Handle(TCollection_HAsciiString)& theFilePath);
|
||||
|
||||
//! Returns font family name
|
||||
Standard_EXPORT Handle(TCollection_HAsciiString) FontName() const;
|
||||
|
||||
//! Returns font file path
|
||||
//! Level: Public
|
||||
Standard_EXPORT Handle(TCollection_HAsciiString) FontPath() const;
|
||||
|
||||
//! Returns font aspect
|
||||
//! Level: Public
|
||||
Standard_EXPORT Font_FontAspect FontAspect() const;
|
||||
|
||||
//! Returns font height
|
||||
//! If returned value is equal -1 it means that font is resizable
|
||||
//! Level: Public
|
||||
Standard_EXPORT Standard_Integer FontHeight() const;
|
||||
//! Returns font aspect.
|
||||
Font_FontAspect FontAspect() const { return myFontAspect; }
|
||||
|
||||
//! Returns font height.
|
||||
//! If returned value is equal -1 it means that font is resizable.
|
||||
Standard_Integer FontHeight() const { return myFaceSize; }
|
||||
|
||||
Standard_EXPORT Standard_Boolean IsValid() const;
|
||||
|
||||
//! Return true if the FontName, FontAspect and FontSize are the same.
|
||||
//! Level: Public
|
||||
Standard_EXPORT Standard_Boolean IsEqual (const Handle(Font_SystemFont)& theOtherFont) const;
|
||||
|
||||
//! Return TRUE if this is single-stroke (one-line) font, FALSE by default.
|
||||
//! Such fonts define single-line glyphs instead of closed contours, so that they are rendered incorrectly by normal software.
|
||||
Standard_Boolean IsSingleStrokeFont() const { return myIsSingleLine; }
|
||||
|
||||
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(Font_SystemFont,Standard_Transient)
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
//! Set if this font should be rendered as single-stroke (one-line).
|
||||
void SetSingleStrokeFont (Standard_Boolean theIsSingleLine) { myIsSingleLine = theIsSingleLine; }
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Handle(TCollection_HAsciiString) MyFontName;
|
||||
Font_FontAspect MyFontAspect;
|
||||
Standard_Integer MyFaceSize;
|
||||
Handle(TCollection_HAsciiString) MyFilePath;
|
||||
Standard_Boolean MyVerification;
|
||||
|
||||
Handle(TCollection_HAsciiString) myFontName;
|
||||
Font_FontAspect myFontAspect;
|
||||
Standard_Integer myFaceSize;
|
||||
Handle(TCollection_HAsciiString) myFilePath;
|
||||
Standard_Boolean myIsSingleLine; //!< single stroke font flag, FALSE by default
|
||||
Standard_Boolean myIsDefined;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DEFINE_STANDARD_HANDLE(Font_SystemFont, Standard_Transient)
|
||||
|
||||
#endif // _Font_SystemFont_HeaderFile
|
||||
|
@@ -229,13 +229,16 @@ void Geom_ConicalSurface::SetSemiAngle (const Standard_Real Ang) {
|
||||
//function : Apex
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Pnt Geom_ConicalSurface::Apex () const
|
||||
Pnt Geom_ConicalSurface::Apex(Standard_Real* const theVParametr) const
|
||||
{
|
||||
|
||||
XYZ Coord = Position().Direction().XYZ();
|
||||
Coord.Multiply (-radius / Tan (semiAngle));
|
||||
Coord.Add (Position().Location().XYZ());
|
||||
|
||||
if (theVParametr)
|
||||
*theVParametr = -radius / Sin(semiAngle);
|
||||
|
||||
return Pnt (Coord);
|
||||
}
|
||||
|
||||
|
@@ -179,7 +179,9 @@ public:
|
||||
//! side of the axis of revolution of this cone if the
|
||||
//! half-angle at the apex is positive, and on the positive
|
||||
//! side of the "main Axis" if the half-angle is negative.
|
||||
Standard_EXPORT gp_Pnt Apex() const;
|
||||
//! If theVParametr != 0 (points on the real variable) then it will store
|
||||
//! the V-parameter of the apex.
|
||||
Standard_EXPORT gp_Pnt Apex(Standard_Real* const theVParametr = 0L) const;
|
||||
|
||||
|
||||
//! The conical surface is infinite in the V direction so
|
||||
|
@@ -53,6 +53,7 @@
|
||||
#include <CSLib.hxx>
|
||||
#include <CSLib_NormalStatus.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
#include <Extrema_ECC.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
@@ -74,16 +75,19 @@
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_ConicalSurface.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_Hyperbola.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_OffsetCurve.hxx>
|
||||
#include <Geom_OffsetSurface.hxx>
|
||||
#include <Geom_Parabola.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <Geom_RectangularTrimmedSurface.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomAdaptor_HSurface.hxx>
|
||||
#include <GeomAdaptor_Surface.hxx>
|
||||
#include <GeomConvert.hxx>
|
||||
@@ -962,14 +966,7 @@ void GeomLib::SameRange(const Standard_Real Tolerance,
|
||||
else
|
||||
{ // On segmente le resultat
|
||||
Handle(Geom2d_TrimmedCurve) TC;
|
||||
Handle(Geom2d_Curve) aCCheck = CurvePtr;
|
||||
|
||||
if(aCCheck->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
|
||||
{
|
||||
aCCheck = Handle(Geom2d_TrimmedCurve)::DownCast(aCCheck)->BasisCurve();
|
||||
}
|
||||
|
||||
if(aCCheck->IsPeriodic())
|
||||
if (CurvePtr->IsPeriodic())
|
||||
{
|
||||
TC = new Geom2d_TrimmedCurve( CurvePtr, FirstOnCurve, LastOnCurve );
|
||||
}
|
||||
@@ -2737,12 +2734,148 @@ Standard_Boolean GeomLib::IsBzVClosed (const Handle(Geom_BezierSurface)& S,
|
||||
return CompareWeightPoles(aPF, 0, aPL, 0, Tol2);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AllowExtendUParameter
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean GeomLib::IsUTrimAllowed(const GeomAdaptor_Surface& theS,
|
||||
const Standard_Real theNewUFirst,
|
||||
const Standard_Real theNewULast)
|
||||
{
|
||||
const Handle(Geom_Surface) &aSurf = theS.Surface();
|
||||
|
||||
Standard_Real anIsoParameter = theS.FirstVParameter();
|
||||
if (Precision::IsInfinite(anIsoParameter))
|
||||
anIsoParameter = theS.LastVParameter();
|
||||
|
||||
if (Precision::IsInfinite(anIsoParameter))
|
||||
anIsoParameter = 0.0;
|
||||
|
||||
Handle(Geom_Curve) aC = aSurf->VIso(anIsoParameter);
|
||||
|
||||
if (aC->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
|
||||
{
|
||||
// In order to obtain the default curve's work range
|
||||
aC = Handle(Geom_TrimmedCurve)::DownCast(aC)->BasisCurve();
|
||||
}
|
||||
|
||||
return (IsTrimAllowed(aC, theNewUFirst, theNewULast));
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AllowExtendVParameter
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean GeomLib::IsVTrimAllowed(const GeomAdaptor_Surface& theS,
|
||||
const Standard_Real theNewVFirst,
|
||||
const Standard_Real theNewVLast)
|
||||
{
|
||||
const GeomAbs_SurfaceType aSType = theS.GetType();
|
||||
|
||||
const Handle(Geom_Surface) &aSurf = theS.Surface();
|
||||
|
||||
if (aSType == GeomAbs_OffsetSurface)
|
||||
{
|
||||
const Handle(Geom_OffsetSurface) aOS = Handle(Geom_OffsetSurface)::DownCast(aSurf);
|
||||
return IsVTrimAllowed(GeomAdaptor_Surface(aOS->BasisSurface()),
|
||||
theNewVFirst, theNewVLast);
|
||||
}
|
||||
|
||||
Standard_Real anIsoParameter = theS.FirstUParameter();
|
||||
if (Precision::IsInfinite(anIsoParameter))
|
||||
anIsoParameter = theS.LastUParameter();
|
||||
|
||||
if (Precision::IsInfinite(anIsoParameter))
|
||||
anIsoParameter = 0.0;
|
||||
|
||||
Handle(Geom_Curve) aC = aSurf->UIso(anIsoParameter);
|
||||
|
||||
if (aC.IsNull())
|
||||
return Standard_False;
|
||||
|
||||
if (aC->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
|
||||
{
|
||||
// In order to obtain the default curve's work range
|
||||
aC = Handle(Geom_TrimmedCurve)::DownCast(aC)->BasisCurve();
|
||||
}
|
||||
|
||||
if (!IsTrimAllowed(aC, theNewVFirst, theNewVLast))
|
||||
return Standard_False;
|
||||
|
||||
switch (aSType)
|
||||
{
|
||||
case GeomAbs_OtherSurface:
|
||||
return Standard_True;
|
||||
case GeomAbs_Sphere:
|
||||
{
|
||||
if ((theNewVFirst < -M_PI_2) || (theNewVLast > M_PI_2))
|
||||
{
|
||||
// After extending, the surface isoline will go
|
||||
// through the sphere pole
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GeomAbs_Cone:
|
||||
{
|
||||
const Handle(Geom_ConicalSurface) aCone = Handle(Geom_ConicalSurface)::DownCast(aSurf);
|
||||
Standard_Real anApexPrm = 0.0;
|
||||
aCone->Apex(&anApexPrm);
|
||||
|
||||
if ((anApexPrm - theNewVFirst)*(theNewVLast - anApexPrm) > 0.0)
|
||||
{
|
||||
// The new boundaries intersect the cone apex
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GeomAbs_SurfaceOfRevolution:
|
||||
{
|
||||
const Handle(Adaptor3d_HCurve) aCurv = theS.BasisCurve();
|
||||
|
||||
const Standard_Real aParTol = aCurv->Resolution(Precision::Confusion());
|
||||
|
||||
const Standard_Real aParF = theNewVFirst + aParTol,
|
||||
aParL = theNewVLast - aParTol;
|
||||
|
||||
const Handle(Geom_Line) aL = new Geom_Line(theS.AxeOfRevolution());
|
||||
const GeomAdaptor_Curve aLin(aL);
|
||||
|
||||
Extrema_ECC anExtr(aCurv->Curve(), aLin);
|
||||
anExtr.Perform();
|
||||
if (anExtr.IsDone() && anExtr.NbExt() > 0)
|
||||
{
|
||||
Extrema_POnCurv aP1, aP2;
|
||||
for (Standard_Integer i = 1; i <= anExtr.NbExt(); i++)
|
||||
{
|
||||
if (anExtr.SquareDistance(i) > Precision::SquareConfusion())
|
||||
continue;
|
||||
|
||||
anExtr.Points(i, aP1, aP2);
|
||||
if ((aParF < aP1.Parameter()) && (aP1.Parameter() < aParL))
|
||||
{
|
||||
// After extending, the surface isoline will go
|
||||
// through the pole (singular point like pole of sphere)
|
||||
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : CompareWeightPoles
|
||||
//purpose : Checks if thePoles1(i)*theW1(i) is equal to thePoles2(i)*theW2(i)
|
||||
// with tolerance theTol.
|
||||
// It is necessary for not rational B-splines and Bezier curves
|
||||
// to set theW1 and theW2 adresses to zero.
|
||||
// to set theW1 and theW2 addresses to zero.
|
||||
//=======================================================================
|
||||
static Standard_Boolean CompareWeightPoles(const TColgp_Array1OfPnt& thePoles1,
|
||||
const TColStd_Array1OfReal* const theW1,
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <Standard_Boolean.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
@@ -34,6 +35,7 @@ class gp_Ax2;
|
||||
class Geom2d_Curve;
|
||||
class gp_GTrsf2d;
|
||||
class Adaptor3d_CurveOnSurface;
|
||||
class GeomAdaptor_Surface;
|
||||
class Geom_BoundedCurve;
|
||||
class gp_Pnt;
|
||||
class gp_Vec;
|
||||
@@ -54,7 +56,6 @@ class GeomLib_Tool;
|
||||
class GeomLib_PolyFunc;
|
||||
class GeomLib_LogSample;
|
||||
|
||||
|
||||
//! Geom Library. This package provides an
|
||||
//! implementation of functions for basic computation
|
||||
//! on geometric entity from packages Geom and Geom2d.
|
||||
@@ -193,6 +194,71 @@ public:
|
||||
Standard_EXPORT static void IsClosed(const Handle(Geom_Surface)& S, const Standard_Real Tol,
|
||||
Standard_Boolean& isUClosed, Standard_Boolean& isVClosed);
|
||||
|
||||
//! This method determines if the ends of the given curve are
|
||||
//! coincided with given tolerance.
|
||||
//! This is a template-method. Therefore, it can be applied to
|
||||
//! 2D- and 3D-curve and to Adaptor-HCurve.
|
||||
template <typename TypeCurve>
|
||||
Standard_EXPORT static Standard_Boolean IsClosed(const Handle(TypeCurve)& theCurve,
|
||||
const Standard_Real theTol)
|
||||
{
|
||||
const Standard_Real aFPar = theCurve->FirstParameter(),
|
||||
aLPar = theCurve->LastParameter();
|
||||
|
||||
if (Precision::IsInfinite(aFPar) || Precision::IsInfinite(aLPar))
|
||||
return Standard_False;
|
||||
|
||||
return (theCurve->Value(aFPar).SquareDistance(theCurve->Value(aLPar)) < theTol*theTol);
|
||||
}
|
||||
|
||||
//! Returns TRUE if theCurve will keep its validity for OCCT-algorithms
|
||||
//! after its trimming in range [theNewFPar, theNewLPar].
|
||||
//! This is a template-method. Therefore, it can be applied to
|
||||
//! 2D- and 3D-curve.
|
||||
//! Using trimmed curves or Adaptor_HCurves is possible but undesirable
|
||||
//! because theCurve must be parametrized in its default work-range
|
||||
//! in order for this method to work correctly.
|
||||
template <typename TypeCurve>
|
||||
Standard_EXPORT static Standard_Boolean IsTrimAllowed(const Handle(TypeCurve)& theCurve,
|
||||
const Standard_Real theNewFPar,
|
||||
const Standard_Real theNewLPar)
|
||||
{
|
||||
Standard_Real aFPar = theCurve->FirstParameter(),
|
||||
aLPar = theCurve->LastParameter();
|
||||
|
||||
if ((aFPar <= theNewFPar) && (theNewLPar <= aLPar) && (theNewFPar < theNewLPar))
|
||||
{
|
||||
//New boundaries are in the current ones
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
if (!theCurve->IsPeriodic())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
const Standard_Real aPeriod = theCurve->Period();
|
||||
|
||||
if ((theNewLPar - theNewFPar - aPeriod) > Epsilon(aPeriod))
|
||||
return Standard_False;
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//! Returns TRUE if theS will keep its validity for OCCT-algorithms
|
||||
//! after its trimming in range [theNewUFirst, theNewULast] along U-direction
|
||||
Standard_EXPORT static Standard_Boolean
|
||||
IsUTrimAllowed(const GeomAdaptor_Surface& theS,
|
||||
const Standard_Real theNewUFirst,
|
||||
const Standard_Real theNewULast);
|
||||
|
||||
//! Returns TRUE if theS will keep its validity for OCCT-algorithms
|
||||
//! after its trimming in range [theNewVFirst, theNewVLast] along V-direction
|
||||
Standard_EXPORT static Standard_Boolean
|
||||
IsVTrimAllowed(const GeomAdaptor_Surface& theS,
|
||||
const Standard_Real theNewVFirst,
|
||||
const Standard_Real theNewVLast);
|
||||
|
||||
//! Returns true if the poles of U1 isoline and the poles of
|
||||
//! U2 isoline of surface are identical according to tolerance criterion.
|
||||
//! For rational surfaces Weights(i)*Poles(i) are checked.
|
||||
|
@@ -41,10 +41,12 @@ extern "C"
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default : 4244)
|
||||
|
@@ -687,7 +687,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
}
|
||||
//
|
||||
Standard_Boolean Arrive, DejaReparti;
|
||||
const Standard_Integer RejectIndexMAX = 250000;
|
||||
const Standard_Integer RejectIndexMAX = 25000;
|
||||
Standard_Integer IncKey, RejectIndex;
|
||||
gp_Pnt pf,pl;
|
||||
//
|
||||
@@ -736,6 +736,12 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
Arrive = Standard_False;
|
||||
while(!Arrive) //010
|
||||
{
|
||||
if (line->NbPoints() >= RejectIndexMAX)
|
||||
{
|
||||
Arrive = Standard_True;
|
||||
break;
|
||||
}
|
||||
|
||||
aPrevStatus = aStatus;
|
||||
|
||||
LevelOfIterWithoutAppend++;
|
||||
@@ -745,7 +751,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
if(DejaReparti) {
|
||||
break;
|
||||
}
|
||||
RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
LevelOfIterWithoutAppend = 0;
|
||||
}
|
||||
//
|
||||
@@ -872,7 +878,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
Param(2)=SvParam[1];
|
||||
Param(3)=SvParam[2];
|
||||
Param(4)=SvParam[3];
|
||||
RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
}
|
||||
else //009
|
||||
{
|
||||
@@ -903,7 +909,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
Arrive=Standard_True;
|
||||
}
|
||||
|
||||
RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
LevelOfEmptyInmyIntersectionOn2S++;
|
||||
//
|
||||
if(LevelOfEmptyInmyIntersectionOn2S>10)
|
||||
@@ -1036,7 +1042,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
case IntWalk_ArretSurPointPrecedent:
|
||||
{
|
||||
Arrive = Standard_False;
|
||||
RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
break;
|
||||
}
|
||||
case IntWalk_PasTropGrand:
|
||||
@@ -1046,7 +1052,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
Param(3)=SvParam[2];
|
||||
Param(4)=SvParam[3];
|
||||
|
||||
if(LevelOfIterWithoutAppend > 5)
|
||||
if ((LevelOfIterWithoutAppend > 5) && (aPrevStatus != IntWalk_StepTooSmall))
|
||||
{
|
||||
for (Standard_Integer i = 0; i < 4; i++)
|
||||
{
|
||||
@@ -1240,7 +1246,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
|
||||
if (aStatus == IntWalk_ArretSurPoint)
|
||||
{
|
||||
RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1321,13 +1327,13 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
|
||||
//
|
||||
LevelOfIterWithoutAppend=0;
|
||||
RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
}
|
||||
else
|
||||
{
|
||||
//fail framing divides the step
|
||||
Arrive = Standard_False;
|
||||
RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
NoTestDeflection = Standard_True;
|
||||
ChoixIso = SauvChoixIso;
|
||||
}
|
||||
@@ -1582,7 +1588,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
}
|
||||
}
|
||||
|
||||
RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
|
||||
if(Arrive &&
|
||||
myIntersectionOn2S.IsDone() && !myIntersectionOn2S.IsEmpty() &&
|
||||
@@ -1603,7 +1609,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
|
||||
//echec framing on border; division of step
|
||||
Arrive = Standard_False;
|
||||
NoTestDeflection = Standard_True;
|
||||
RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
|
||||
RepartirOuDiviser(aStatus, DejaReparti, ChoixIso, Arrive);
|
||||
}
|
||||
}//$$$ end framing on border (!close)
|
||||
}//004 fin TestArret return Arrive = True
|
||||
@@ -2769,16 +2775,17 @@ SeekAdditionalPoints( const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
return isPrecise;
|
||||
}
|
||||
|
||||
void IntWalk_PWalking::
|
||||
RepartirOuDiviser(Standard_Boolean& DejaReparti,
|
||||
IntImp_ConstIsoparametric& ChoixIso,
|
||||
Standard_Boolean& Arrive)
|
||||
|
||||
// at the neighborhood of a point, there is a fail of marching
|
||||
// it is required to divide the steps to try to continue
|
||||
// if the step is too small if we are on border
|
||||
// restart in another direction if it was not done, otherwise stop
|
||||
|
||||
//=======================================================================
|
||||
//function : RepartirOuDiviser
|
||||
//purpose : at the neighborhood of a point, there is a fail of marching
|
||||
// it is required to divide the steps to try to continue
|
||||
// if the step is too small if we are on border
|
||||
// restart in another direction if it was not done, otherwise stop
|
||||
//=======================================================================
|
||||
void IntWalk_PWalking::RepartirOuDiviser(const IntWalk_StatusDeflection& theCurrentStatus,
|
||||
Standard_Boolean& DejaReparti,
|
||||
IntImp_ConstIsoparametric& ChoixIso,
|
||||
Standard_Boolean& Arrive)
|
||||
{
|
||||
// Standard_Integer i;
|
||||
if (Arrive) { //restart in the other direction
|
||||
@@ -2821,11 +2828,12 @@ RepartirOuDiviser(Standard_Boolean& DejaReparti,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( pasuv[0]*0.5 < ResoU1
|
||||
&& pasuv[1]*0.5 < ResoV1
|
||||
&& pasuv[2]*0.5 < ResoU2
|
||||
&& pasuv[3]*0.5 < ResoV2
|
||||
) {
|
||||
if ((theCurrentStatus == IntWalk_StepTooSmall) ||
|
||||
(pasuv[0] * 0.5 < ResoU1
|
||||
&& pasuv[1] * 0.5 < ResoV1
|
||||
&& pasuv[2] * 0.5 < ResoU2
|
||||
&& pasuv[3] * 0.5 < ResoV2))
|
||||
{
|
||||
if (!previoustg) {
|
||||
tglast = Standard_True; // IS IT ENOUGH ????
|
||||
}
|
||||
|
@@ -130,7 +130,10 @@ public:
|
||||
|
||||
Standard_EXPORT Standard_Boolean TestArret (const Standard_Boolean DejaReparti, TColStd_Array1OfReal& Param, IntImp_ConstIsoparametric& ChoixIso);
|
||||
|
||||
Standard_EXPORT void RepartirOuDiviser (Standard_Boolean& DejaReparti, IntImp_ConstIsoparametric& ChoixIso, Standard_Boolean& Arrive);
|
||||
Standard_EXPORT void RepartirOuDiviser(const IntWalk_StatusDeflection& theCurrentStatus,
|
||||
Standard_Boolean& DejaReparti,
|
||||
IntImp_ConstIsoparametric& ChoixIso,
|
||||
Standard_Boolean& Arrive);
|
||||
|
||||
void AddAPoint (Handle(IntSurf_LineOn2S)& line, const IntSurf_PntOn2S& POn2S);
|
||||
|
||||
|
@@ -117,7 +117,7 @@ LocOpe_DPrism::LocOpe_DPrism(const TopoDS_Face& Spine,
|
||||
|
||||
myProfile = BRepLib_MakeWire(myProfile1,myProfile2,myProfile3);
|
||||
|
||||
myDPrism.Perform(mySpine,myProfile,gp::XOY());
|
||||
myDPrism.Perform(mySpine,myProfile,gp::XOY(), GeomAbs_Arc, Standard_False);
|
||||
|
||||
|
||||
if (myDPrism.IsDone()) {
|
||||
@@ -370,7 +370,7 @@ LocOpe_DPrism::LocOpe_DPrism(const TopoDS_Face& Spine,
|
||||
myProfile1 = BRepLib_MakeEdge(Vert4, Vert1);
|
||||
|
||||
myProfile = BRepLib_MakeWire(myProfile1,myProfile2,myProfile3);
|
||||
myDPrism.Perform(mySpine,myProfile,gp::XOY());
|
||||
myDPrism.Perform(mySpine,myProfile,gp::XOY(), GeomAbs_Arc, Standard_False);
|
||||
|
||||
|
||||
if (myDPrism.IsDone()) {
|
||||
|
@@ -57,6 +57,8 @@ OSD_OpenMode.hxx
|
||||
OSD_OSDError.hxx
|
||||
OSD_Parallel.cxx
|
||||
OSD_Parallel.hxx
|
||||
OSD_Parallel_TBB.cxx
|
||||
OSD_Parallel_Threads.cxx
|
||||
OSD_Path.cxx
|
||||
OSD_Path.hxx
|
||||
OSD_PerfMeter.cxx
|
||||
@@ -83,6 +85,8 @@ OSD_SingleProtection.hxx
|
||||
OSD_SysType.hxx
|
||||
OSD_Thread.cxx
|
||||
OSD_Thread.hxx
|
||||
OSD_ThreadPool.cxx
|
||||
OSD_ThreadPool.hxx
|
||||
OSD_ThreadFunction.hxx
|
||||
OSD_Timer.cxx
|
||||
OSD_Timer.hxx
|
||||
|
@@ -104,7 +104,10 @@ public:
|
||||
//! user's code. Refer to Foundation Classes User's Guide for further details.
|
||||
//!
|
||||
Standard_EXPORT static void SetSignal (const Standard_Boolean theFloatingSignal = Standard_True);
|
||||
|
||||
|
||||
//! Return floating signal catching value previously set by SetSignal().
|
||||
Standard_EXPORT static Standard_Boolean ToCatchFloatingSignals();
|
||||
|
||||
//! Commands the process to sleep for a number of seconds.
|
||||
Standard_EXPORT static void SecSleep (const Standard_Integer aDelay);
|
||||
|
||||
|
@@ -14,25 +14,25 @@
|
||||
#ifndef OSD_Parallel_HeaderFile
|
||||
#define OSD_Parallel_HeaderFile
|
||||
|
||||
#include <OSD_Thread.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <Standard_NotImplemented.hxx>
|
||||
#include <Standard_Atomic.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/parallel_for_each.h>
|
||||
#include <tbb/blocked_range.h>
|
||||
#endif
|
||||
|
||||
//! @class OSD_Parallel
|
||||
//! @brief Simplifies code parallelization.
|
||||
//! @brief Simple tool for code parallelization.
|
||||
//!
|
||||
//! The Class provides an interface of parallel processing "for" and "foreach" loops.
|
||||
//! These 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.
|
||||
//! OSD_Parallel class provides simple interface for parallel processing of
|
||||
//! tasks that can be formulated in terms of "for" or "foreach" loops.
|
||||
//!
|
||||
//! To use this tool it is necessary to:
|
||||
//! - organize the data to be processed in a collection accessible by
|
||||
//! iteration (usually array or vector);
|
||||
//! - implement a functor class providing operator () accepting iterator
|
||||
//! (or index in array) that does the job;
|
||||
//! - call either For() or ForEach() providing begin and end iterators and
|
||||
//! a functor object.
|
||||
//!
|
||||
//! Iterators should satisfy requirements of STL forward iterator.
|
||||
//! Functor
|
||||
//!
|
||||
//! @code
|
||||
//! class Functor
|
||||
@@ -45,268 +45,290 @@
|
||||
//! };
|
||||
//! @endcode
|
||||
//!
|
||||
//! 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).
|
||||
//! The operator () should be implemented in a thread-safe way so that
|
||||
//! the same functor object can process different data items in parallel threads.
|
||||
//!
|
||||
//! Iteration by index (For) is expected to be more efficient than using iterators
|
||||
//! (ForEach).
|
||||
//!
|
||||
//! Implementation uses TBB if OCCT is built with support of TBB; otherwise it
|
||||
//! uses ad-hoc parallelization tool. In general, if TBB is available, it is
|
||||
//! more efficient to use it directly instead of using OSD_Parallel.
|
||||
|
||||
class OSD_Parallel
|
||||
{
|
||||
//! Auxiliary class which ensures exclusive
|
||||
//! access to iterators of processed data pool.
|
||||
template <typename Value>
|
||||
class Range
|
||||
private:
|
||||
|
||||
//! Interface class defining API for polymorphic wrappers over iterators.
|
||||
//! Intended to add polymorphic behaviour to For and ForEach functionality
|
||||
//! for arbitrary objects and eliminate dependency on template parameters.
|
||||
class IteratorInterface
|
||||
{
|
||||
public: //! @name public methods
|
||||
public:
|
||||
virtual ~IteratorInterface() {}
|
||||
|
||||
typedef Value Iterator;
|
||||
//! Returns true if iterators wrapped by this and theOther are equal
|
||||
virtual bool IsEqual (const IteratorInterface& theOther) const = 0;
|
||||
|
||||
//! Constructor
|
||||
Range(const Value& theBegin, const Value& theEnd)
|
||||
: myBegin(theBegin),
|
||||
myEnd (theEnd),
|
||||
myIt (theBegin)
|
||||
{
|
||||
}
|
||||
//! Increments wrapped iterator
|
||||
virtual void Increment () = 0;
|
||||
|
||||
//! Returns const link on the first element.
|
||||
inline const Value& Begin() const
|
||||
{
|
||||
return myBegin;
|
||||
}
|
||||
|
||||
//! Returns const link on the last element.
|
||||
inline const Value& End() const
|
||||
{
|
||||
return myEnd;
|
||||
}
|
||||
|
||||
//! Returns first non processed element or end.
|
||||
//! Thread-safe method.
|
||||
inline Iterator It() const
|
||||
{
|
||||
Standard_Mutex::Sentry aMutex( myMutex );
|
||||
return ( myIt != myEnd ) ? myIt++ : myEnd;
|
||||
}
|
||||
|
||||
private: //! @name private methods
|
||||
|
||||
//! Empty copy constructor
|
||||
Range(const Range& theCopy);
|
||||
|
||||
//! Empty copy operator.
|
||||
Range& operator=(const Range& theCopy);
|
||||
|
||||
private: //! @name private fields
|
||||
|
||||
const Value& myBegin; //!< Fisrt element of range.
|
||||
const Value& myEnd; //!< Last element of range.
|
||||
mutable Value myIt; //!< First non processed element of range.
|
||||
mutable Standard_Mutex myMutex; //!< Access controller for the first non processed element.
|
||||
//! Returns new instance of the wrapper containing copy
|
||||
//! of the wrapped iterator.
|
||||
virtual IteratorInterface* Clone() const = 0;
|
||||
};
|
||||
|
||||
//! Auxiliary wrapper class for thread function.
|
||||
template <typename Functor, typename InputIterator>
|
||||
class Task
|
||||
//! Implementation of polymorphic iterator wrapper suitable for basic
|
||||
//! types as well as for std iterators.
|
||||
//! Wraps instance of actual iterator type Type.
|
||||
template<class Type>
|
||||
class IteratorWrapper : public IteratorInterface
|
||||
{
|
||||
public: //! @name public methods
|
||||
public:
|
||||
IteratorWrapper() {}
|
||||
IteratorWrapper(const Type& theValue) : myValue(theValue) {}
|
||||
|
||||
//! Constructor.
|
||||
Task(const Functor& thePerformer, Range<InputIterator>& theRange)
|
||||
: myPerformer(thePerformer),
|
||||
myRange (theRange)
|
||||
virtual bool IsEqual (const IteratorInterface& theOther) const Standard_OVERRIDE
|
||||
{
|
||||
return myValue == dynamic_cast<const IteratorWrapper<Type>&>(theOther).myValue;
|
||||
}
|
||||
|
||||
//! Method is executed in the context of thread,
|
||||
//! so this method defines the main calculations.
|
||||
static Standard_Address RunWithIterator(Standard_Address theTask)
|
||||
virtual void Increment () Standard_OVERRIDE
|
||||
{
|
||||
Task<Functor, InputIterator>& aTask =
|
||||
*( static_cast< Task<Functor, InputIterator>* >(theTask) );
|
||||
|
||||
const Range<InputIterator>& aData( aTask.myRange );
|
||||
typename Range<InputIterator>::Iterator i = aData.It();
|
||||
|
||||
for ( ; i != aData.End(); i = aData.It() )
|
||||
{
|
||||
aTask.myPerformer(*i);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
++myValue;
|
||||
}
|
||||
|
||||
//! Method is executed in the context of thread,
|
||||
//! so this method defines the main calculations.
|
||||
static Standard_Address RunWithIndex(Standard_Address theTask)
|
||||
virtual IteratorInterface* Clone() const Standard_OVERRIDE
|
||||
{
|
||||
Task<Functor, InputIterator>& aTask =
|
||||
*( static_cast< Task<Functor, Standard_Integer>* >(theTask) );
|
||||
|
||||
const Range<Standard_Integer>& aData( aTask.myRange );
|
||||
Standard_Integer i = aData.It();
|
||||
|
||||
for ( ; i < aData.End(); i = aData.It())
|
||||
{
|
||||
aTask.myPerformer(i);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return new IteratorWrapper<Type>(myValue);
|
||||
}
|
||||
|
||||
private: //! @name private methods
|
||||
const Type& Value() const { return myValue; }
|
||||
|
||||
//! Empty copy constructor.
|
||||
Task(const Task& theCopy);
|
||||
|
||||
//! Empty copy operator.
|
||||
Task& operator=(const Task& theCopy);
|
||||
|
||||
private: //! @name private fields
|
||||
|
||||
const Functor& myPerformer; //!< Link on functor.
|
||||
const Range<InputIterator>& myRange; //!< Link on processed data block.
|
||||
private:
|
||||
Type myValue;
|
||||
};
|
||||
|
||||
public: //! @name public methods
|
||||
protected:
|
||||
// Note: UniversalIterator and FunctorInterface are made protected to be
|
||||
// accessible from specialization using threads (non-TBB).
|
||||
|
||||
//! Returns number of logical proccesrs.
|
||||
Standard_EXPORT static Standard_Integer NbLogicalProcessors();
|
||||
//! Fixed-type iterator, implementing STL forward iterator interface, used for
|
||||
//! iteration over objects subject to parallel processing.
|
||||
//! It stores pointer to instance of polymorphic iterator inheriting from
|
||||
//! IteratorInterface, which contains actual type-specific iterator.
|
||||
class UniversalIterator :
|
||||
// Note that TBB requires that value_type of iterator be copyable,
|
||||
// thus we use its own type for that
|
||||
public std::iterator<std::forward_iterator_tag, UniversalIterator, ptrdiff_t, UniversalIterator*, UniversalIterator&>
|
||||
{
|
||||
public:
|
||||
UniversalIterator() {}
|
||||
|
||||
UniversalIterator(IteratorInterface* theOther)
|
||||
: myPtr(theOther)
|
||||
{
|
||||
}
|
||||
|
||||
UniversalIterator(const UniversalIterator& theOther)
|
||||
: myPtr (theOther.myPtr->Clone())
|
||||
{
|
||||
}
|
||||
|
||||
UniversalIterator& operator= (const UniversalIterator& theOther)
|
||||
{
|
||||
myPtr.reset (theOther.myPtr->Clone());
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!= (const UniversalIterator& theOther) const
|
||||
{
|
||||
return ! myPtr->IsEqual (*theOther.myPtr);
|
||||
}
|
||||
|
||||
bool operator== (const UniversalIterator& theOther) const
|
||||
{
|
||||
return myPtr->IsEqual (*theOther.myPtr);
|
||||
}
|
||||
|
||||
UniversalIterator& operator++()
|
||||
{
|
||||
myPtr->Increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniversalIterator operator++(int)
|
||||
{
|
||||
UniversalIterator aValue(*this);
|
||||
myPtr->Increment();
|
||||
return aValue;
|
||||
}
|
||||
|
||||
const UniversalIterator& operator* () const { return *this; }
|
||||
UniversalIterator& operator* () { return *this; }
|
||||
|
||||
const UniversalIterator* operator->() const { return this; }
|
||||
UniversalIterator* operator->() { return this; }
|
||||
|
||||
// type cast to actual iterator
|
||||
template <typename Iterator>
|
||||
const Iterator& DownCast () const
|
||||
{
|
||||
return dynamic_cast<OSD_Parallel::IteratorWrapper<Iterator>*>(myPtr.get())->Value();
|
||||
}
|
||||
|
||||
private:
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||
std::auto_ptr<IteratorInterface> myPtr;
|
||||
#else
|
||||
std::unique_ptr<IteratorInterface> myPtr;
|
||||
#endif
|
||||
};
|
||||
|
||||
//! Interface class representing functor object.
|
||||
//! Intended to add polymorphic behavour to For and ForEach functionality
|
||||
//! enabling execution of arbitrary function in parallel mode.
|
||||
class FunctorInterface
|
||||
{
|
||||
public:
|
||||
virtual ~FunctorInterface() {}
|
||||
|
||||
virtual void operator () (UniversalIterator& theIterator) const = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
//! Wrapper for functors manipulating on std iterators.
|
||||
template<class Iterator, class Functor>
|
||||
class FunctorWrapperIter : public FunctorInterface
|
||||
{
|
||||
public:
|
||||
FunctorWrapperIter (const Functor& theFunctor)
|
||||
: myFunctor(theFunctor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE
|
||||
{
|
||||
const Iterator& anIt = theIterator.DownCast<Iterator>();
|
||||
myFunctor(*anIt);
|
||||
}
|
||||
|
||||
private:
|
||||
FunctorWrapperIter (const FunctorWrapperIter&);
|
||||
void operator = (const FunctorWrapperIter&);
|
||||
const Functor& myFunctor;
|
||||
};
|
||||
|
||||
//! Wrapper for functors manipulating on integer index.
|
||||
template<class Functor>
|
||||
class FunctorWrapperInt : public FunctorInterface
|
||||
{
|
||||
public:
|
||||
FunctorWrapperInt (const Functor& theFunctor)
|
||||
: myFunctor(theFunctor)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE
|
||||
{
|
||||
Standard_Integer anIndex = theIterator.DownCast<Standard_Integer>();
|
||||
myFunctor(anIndex);
|
||||
}
|
||||
|
||||
private:
|
||||
FunctorWrapperInt (const FunctorWrapperInt&);
|
||||
void operator = (const FunctorWrapperInt&);
|
||||
const Functor& myFunctor;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
//! Simple primitive for parallelization of "foreach" loops, e.g.:
|
||||
//! @code
|
||||
//! for (std::iterator anIter = theBegin; anIter != theEnd; ++anIter) {}
|
||||
//! @endcode
|
||||
//! Implementation of framework-dependent functionality should be provided by
|
||||
//! forEach_impl function defined in opencascade::parallel namespace.
|
||||
//! @param theBegin the first index (incusive)
|
||||
//! @param theEnd the last index (exclusive)
|
||||
//! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}" performing task for specified iterator position
|
||||
//! @param isForceSingleThreadExecution if true, then no threads will be created
|
||||
template <typename InputIterator, typename Functor>
|
||||
static void ForEach( InputIterator theBegin,
|
||||
InputIterator theEnd,
|
||||
const Functor& theFunctor,
|
||||
const Standard_Boolean isForceSingleThreadExecution
|
||||
= Standard_False );
|
||||
//! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}"
|
||||
//! performing task for the specified iterator position
|
||||
//! @param theNbItems number of items passed by iterator, -1 if unknown
|
||||
Standard_EXPORT static void forEach (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems);
|
||||
|
||||
//! Simple primitive for parallelization of "for" loops, e.g.:
|
||||
public: //! @name public methods
|
||||
|
||||
//! Returns number of logical proccesrs.
|
||||
Standard_EXPORT static Standard_Integer NbLogicalProcessors();
|
||||
|
||||
//! Simple primitive for parallelization of "foreach" loops, equivalent to:
|
||||
//! @code
|
||||
//! for (int anIter = theBegin; anIter < theEnd; ++anIter) {}
|
||||
//! for (auto anIter = theBegin; anIter != theEnd; ++anIter) {
|
||||
//! theFunctor(*anIter);
|
||||
//! }
|
||||
//! @endcode
|
||||
//! @param theBegin the first index (incusive)
|
||||
//! @param theEnd the last index (exclusive)
|
||||
//! @param theFunctor functor providing an interface "void operator(int theIndex){}" performing task for specified index
|
||||
//! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}"
|
||||
//! performing task for specified iterator position
|
||||
//! @param isForceSingleThreadExecution if true, then no threads will be created
|
||||
//! @param theNbItems number of items passed by iterator, -1 if unknown
|
||||
template <typename InputIterator, typename Functor>
|
||||
static void ForEach(InputIterator theBegin,
|
||||
InputIterator theEnd,
|
||||
const Functor& theFunctor,
|
||||
const Standard_Boolean isForceSingleThreadExecution = Standard_False,
|
||||
Standard_Integer theNbItems = -1)
|
||||
{
|
||||
if (isForceSingleThreadExecution || theNbItems == 1)
|
||||
{
|
||||
for (InputIterator it(theBegin); it != theEnd; ++it)
|
||||
theFunctor(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniversalIterator aBegin(new IteratorWrapper<InputIterator>(theBegin));
|
||||
UniversalIterator aEnd (new IteratorWrapper<InputIterator>(theEnd));
|
||||
FunctorWrapperIter<InputIterator,Functor> aFunctor (theFunctor);
|
||||
forEach(aBegin, aEnd, aFunctor, theNbItems);
|
||||
}
|
||||
}
|
||||
|
||||
//! Simple primitive for parallelization of "for" loops, equivalent to:
|
||||
//! @code
|
||||
//! for (int anIter = theBegin; anIter != theEnd; ++anIter) {
|
||||
//! theFunctor(anIter);
|
||||
//! }
|
||||
//! @endcode
|
||||
//! @param theBegin the first index (incusive)
|
||||
//! @param theEnd the last index (exclusive)
|
||||
//! @param theFunctor functor providing an interface "void operator(int theIndex){}"
|
||||
//! performing task for specified index
|
||||
//! @param isForceSingleThreadExecution if true, then no threads will be created
|
||||
template <typename Functor>
|
||||
static void For( const Standard_Integer theBegin,
|
||||
const Standard_Integer theEnd,
|
||||
const Functor& theFunctor,
|
||||
const Standard_Boolean isForceSingleThreadExecution
|
||||
= Standard_False );
|
||||
static void For(const Standard_Integer theBegin,
|
||||
const Standard_Integer theEnd,
|
||||
const Functor& theFunctor,
|
||||
const Standard_Boolean isForceSingleThreadExecution = Standard_False)
|
||||
{
|
||||
if (isForceSingleThreadExecution || (theEnd - theBegin) == 1)
|
||||
{
|
||||
for (Standard_Integer it (theBegin); it != theEnd; ++it)
|
||||
theFunctor(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniversalIterator aBegin(new IteratorWrapper<Standard_Integer>(theBegin));
|
||||
UniversalIterator aEnd (new IteratorWrapper<Standard_Integer>(theEnd));
|
||||
FunctorWrapperInt<Functor> aFunctor (theFunctor);
|
||||
forEach(aBegin, aEnd, aFunctor, theEnd - theBegin);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//=======================================================================
|
||||
//function : OSD_Parallel::Range::It
|
||||
//purpose : Template concretization.
|
||||
//=======================================================================
|
||||
template<> inline Standard_Integer OSD_Parallel::Range<Standard_Integer>::It() const
|
||||
{
|
||||
return Standard_Atomic_Increment( reinterpret_cast<volatile int*>(&myIt) ) - 1;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ParallelForEach
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
template <typename InputIterator, typename Functor>
|
||||
void OSD_Parallel::ForEach( InputIterator theBegin,
|
||||
InputIterator theEnd,
|
||||
const Functor& theFunctor,
|
||||
const Standard_Boolean isForceSingleThreadExecution )
|
||||
{
|
||||
if ( isForceSingleThreadExecution )
|
||||
{
|
||||
for ( InputIterator it(theBegin); it != theEnd; ++it )
|
||||
theFunctor(*it);
|
||||
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_TBB
|
||||
{
|
||||
try
|
||||
{
|
||||
tbb::parallel_for_each(theBegin, theEnd, theFunctor);
|
||||
}
|
||||
catch ( tbb::captured_exception& anException )
|
||||
{
|
||||
throw Standard_NotImplemented(anException.what());
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
Range<InputIterator> aData(theBegin, theEnd);
|
||||
Task<Functor, InputIterator> aTask(theFunctor, aData);
|
||||
|
||||
const Standard_Integer aNbThreads = OSD_Parallel::NbLogicalProcessors();
|
||||
NCollection_Array1<OSD_Thread> aThreads(0, aNbThreads - 1);
|
||||
|
||||
for ( Standard_Integer i = 0; i < aNbThreads; ++i )
|
||||
{
|
||||
OSD_Thread& aThread = aThreads(i);
|
||||
aThread.SetFunction(&Task<Functor, InputIterator>::RunWithIterator);
|
||||
aThread.Run(&aTask);
|
||||
}
|
||||
|
||||
for ( Standard_Integer i = 0; i < aNbThreads; ++i )
|
||||
aThreads(i).Wait();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ParallelFor
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
template <typename Functor>
|
||||
void OSD_Parallel::For( const Standard_Integer theBegin,
|
||||
const Standard_Integer theEnd,
|
||||
const Functor& theFunctor,
|
||||
const Standard_Boolean isForceSingleThreadExecution )
|
||||
{
|
||||
if ( isForceSingleThreadExecution )
|
||||
{
|
||||
for ( Standard_Integer i = theBegin; i < theEnd; ++i )
|
||||
theFunctor(i);
|
||||
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_TBB
|
||||
{
|
||||
try
|
||||
{
|
||||
tbb::parallel_for( theBegin, theEnd, theFunctor );
|
||||
}
|
||||
catch ( tbb::captured_exception& anException )
|
||||
{
|
||||
throw Standard_NotImplemented(anException.what());
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
Range<Standard_Integer> aData(theBegin, theEnd);
|
||||
Task<Functor, Standard_Integer> aTask(theFunctor, aData);
|
||||
|
||||
const Standard_Integer aNbThreads = OSD_Parallel::NbLogicalProcessors();
|
||||
NCollection_Array1<OSD_Thread> aThreads(0, aNbThreads - 1);
|
||||
|
||||
for ( Standard_Integer i = 0; i < aNbThreads; ++i )
|
||||
{
|
||||
OSD_Thread& aThread = aThreads(i);
|
||||
aThread.SetFunction(&Task<Functor, Standard_Integer>::RunWithIndex);
|
||||
aThread.Run(&aTask);
|
||||
}
|
||||
|
||||
for ( Standard_Integer i = 0; i < aNbThreads; ++i )
|
||||
aThreads(i).Wait();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
48
src/OSD/OSD_Parallel_TBB.cxx
Normal file
48
src/OSD/OSD_Parallel_TBB.cxx
Normal file
@@ -0,0 +1,48 @@
|
||||
// Created on: 2014-08-19
|
||||
// Created by: Alexander Zaikin
|
||||
// Copyright (c) 1996-1999 Matra Datavision
|
||||
// Copyright (c) 2013-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.
|
||||
|
||||
// Version of parallel executor used when TBB is available
|
||||
#ifdef HAVE_TBB
|
||||
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <Standard_ProgramError.hxx>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/parallel_for_each.h>
|
||||
#include <tbb/blocked_range.h>
|
||||
|
||||
//=======================================================================
|
||||
//function : forEach
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void OSD_Parallel::forEach (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems)
|
||||
{
|
||||
(void )theNbItems;
|
||||
try
|
||||
{
|
||||
tbb::parallel_for_each(theBegin, theEnd, theFunctor);
|
||||
}
|
||||
catch (tbb::captured_exception& anException)
|
||||
{
|
||||
throw Standard_ProgramError(anException.what());
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_TBB */
|
159
src/OSD/OSD_Parallel_Threads.cxx
Normal file
159
src/OSD/OSD_Parallel_Threads.cxx
Normal file
@@ -0,0 +1,159 @@
|
||||
// Created on: 2014-08-19
|
||||
// Created by: Alexander Zaikin
|
||||
// Copyright (c) 1996-1999 Matra Datavision
|
||||
// Copyright (c) 2013-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.
|
||||
|
||||
// Version of parallel executor used when TBB is not available
|
||||
#ifndef HAVE_TBB
|
||||
|
||||
#include <OSD_Parallel.hxx>
|
||||
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <OSD_Thread.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Class implementing tools for parallel processing
|
||||
//! using threads (when TBB is not available);
|
||||
//! it is derived from OSD_Parallel to get access to
|
||||
//! Iterator and FunctorInterface nested types.
|
||||
class OSD_Parallel_Threads : public OSD_ThreadPool, public OSD_Parallel
|
||||
{
|
||||
public:
|
||||
//! Auxiliary class which ensures exclusive
|
||||
//! access to iterators of processed data pool.
|
||||
class Range
|
||||
{
|
||||
public: //! @name public methods
|
||||
|
||||
//! Constructor
|
||||
Range(const OSD_Parallel::UniversalIterator& theBegin,
|
||||
const OSD_Parallel::UniversalIterator& theEnd)
|
||||
: myBegin(theBegin),
|
||||
myEnd(theEnd),
|
||||
myIt(theBegin)
|
||||
{
|
||||
}
|
||||
|
||||
//! Returns const link on the first element.
|
||||
inline const OSD_Parallel::UniversalIterator& Begin() const
|
||||
{
|
||||
return myBegin;
|
||||
}
|
||||
|
||||
//! Returns const link on the last element.
|
||||
inline const OSD_Parallel::UniversalIterator& End() const
|
||||
{
|
||||
return myEnd;
|
||||
}
|
||||
|
||||
//! Returns first non processed element or end.
|
||||
//! Thread-safe method.
|
||||
inline OSD_Parallel::UniversalIterator It() const
|
||||
{
|
||||
Standard_Mutex::Sentry aMutex(myMutex);
|
||||
return (myIt != myEnd) ? myIt++ : myEnd;
|
||||
}
|
||||
|
||||
private: //! @name private methods
|
||||
|
||||
//! Empty copy constructor
|
||||
Range(const Range& theCopy);
|
||||
|
||||
//! Empty copy operator.
|
||||
Range& operator=(const Range& theCopy);
|
||||
|
||||
private: //! @name private fields
|
||||
|
||||
const OSD_Parallel::UniversalIterator& myBegin; //!< Fisrt element of range.
|
||||
const OSD_Parallel::UniversalIterator& myEnd; //!< Last element of range.
|
||||
mutable OSD_Parallel::UniversalIterator myIt; //!< First non processed element of range.
|
||||
mutable Standard_Mutex myMutex; //!< Access controller for the first non processed element.
|
||||
};
|
||||
|
||||
//! Auxiliary wrapper class for thread function.
|
||||
class Task : public JobInterface
|
||||
{
|
||||
public: //! @name public methods
|
||||
|
||||
//! Constructor.
|
||||
Task(const OSD_Parallel::FunctorInterface& thePerformer, Range& theRange)
|
||||
: myPerformer(thePerformer),
|
||||
myRange(theRange)
|
||||
{
|
||||
}
|
||||
|
||||
//! Method is executed in the context of thread,
|
||||
//! so this method defines the main calculations.
|
||||
virtual void Perform (int ) Standard_OVERRIDE
|
||||
{
|
||||
for (OSD_Parallel::UniversalIterator anIter = myRange.It(); anIter != myRange.End(); anIter = myRange.It())
|
||||
{
|
||||
myPerformer (anIter);
|
||||
}
|
||||
}
|
||||
|
||||
private: //! @name private methods
|
||||
|
||||
//! Empty copy constructor.
|
||||
Task(const Task& theCopy);
|
||||
|
||||
//! Empty copy operator.
|
||||
Task& operator=(const Task& theCopy);
|
||||
|
||||
private: //! @name private fields
|
||||
const FunctorInterface& myPerformer; //!< Link on functor
|
||||
const Range& myRange; //!< Link on processed data block
|
||||
};
|
||||
|
||||
//! Launcher specialization.
|
||||
class UniversalLauncher : public Launcher
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
UniversalLauncher (OSD_ThreadPool& thePool, int theMaxThreads = -1)
|
||||
: Launcher (thePool, theMaxThreads) {}
|
||||
|
||||
//! Primitive for parallelization of "for" loops.
|
||||
void Perform (OSD_Parallel::UniversalIterator& theBegin,
|
||||
OSD_Parallel::UniversalIterator& theEnd,
|
||||
const OSD_Parallel::FunctorInterface& theFunctor)
|
||||
{
|
||||
Range aData (theBegin, theEnd);
|
||||
Task aJob (theFunctor, aData);
|
||||
perform (aJob);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : forEach
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void OSD_Parallel::forEach (UniversalIterator& theBegin,
|
||||
UniversalIterator& theEnd,
|
||||
const FunctorInterface& theFunctor,
|
||||
Standard_Integer theNbItems)
|
||||
{
|
||||
const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
|
||||
const Standard_Integer aNbThreads = theNbItems != -1 ? Min (theNbItems, aThreadPool->NbDefaultThreadsToLaunch()) : -1;
|
||||
OSD_Parallel_Threads::UniversalLauncher aLauncher (*aThreadPool, aNbThreads);
|
||||
aLauncher.Perform (theBegin, theEnd, theFunctor);
|
||||
}
|
||||
|
||||
#endif /* ! HAVE_TBB */
|
401
src/OSD/OSD_ThreadPool.cxx
Normal file
401
src/OSD/OSD_ThreadPool.cxx
Normal file
@@ -0,0 +1,401 @@
|
||||
// Created by: Kirill Gavrilov
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
|
||||
#include <OSD.hxx>
|
||||
#include <Standard_Atomic.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(OSD_ThreadPool, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Lock
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OSD_ThreadPool::EnumeratedThread::Lock()
|
||||
{
|
||||
return Standard_Atomic_CompareAndSwap (&myUsageCounter, 0, 1);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Free
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::EnumeratedThread::Free()
|
||||
{
|
||||
Standard_Atomic_CompareAndSwap (&myUsageCounter, 1, 0);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : WakeUp
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::EnumeratedThread::WakeUp (JobInterface* theJob, bool theToCatchFpe)
|
||||
{
|
||||
myJob = theJob;
|
||||
myToCatchFpe = theToCatchFpe;
|
||||
if (myIsSelfThread)
|
||||
{
|
||||
if (theJob != NULL)
|
||||
{
|
||||
OSD_ThreadPool::performJob (myFailure, myJob, myThreadIndex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
myWakeEvent.Set();
|
||||
if (theJob != NULL && !myIsStarted)
|
||||
{
|
||||
myIsStarted = true;
|
||||
Run (this);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : WaitIdle
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::EnumeratedThread::WaitIdle()
|
||||
{
|
||||
if (!myIsSelfThread)
|
||||
{
|
||||
myIdleEvent.Wait();
|
||||
myIdleEvent.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : DefaultPool
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
const Handle(OSD_ThreadPool)& OSD_ThreadPool::DefaultPool (int theNbThreads)
|
||||
{
|
||||
static const Handle(OSD_ThreadPool) THE_GLOBAL_POOL = new OSD_ThreadPool (theNbThreads);
|
||||
return THE_GLOBAL_POOL;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OSD_ThreadPool
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
OSD_ThreadPool::OSD_ThreadPool (int theNbThreads)
|
||||
: myNbDefThreads (0),
|
||||
myShutDown (false)
|
||||
{
|
||||
Init (theNbThreads);
|
||||
myNbDefThreads = NbThreads();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : IsInUse
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OSD_ThreadPool::IsInUse()
|
||||
{
|
||||
for (NCollection_Array1<EnumeratedThread>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More(); aThreadIter.Next())
|
||||
{
|
||||
EnumeratedThread& aThread = aThreadIter.ChangeValue();
|
||||
if (!aThread.Lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
aThread.Free();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::Init (int theNbThreads)
|
||||
{
|
||||
const int aNbThreads = Max (0, (theNbThreads > 0 ? theNbThreads : OSD_Parallel::NbLogicalProcessors()) - 1);
|
||||
if (myThreads.Size() == aNbThreads)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// release old threads
|
||||
if (!myThreads.IsEmpty())
|
||||
{
|
||||
NCollection_Array1<EnumeratedThread*> aLockThreads (myThreads.Lower(), myThreads.Upper());
|
||||
aLockThreads.Init (NULL);
|
||||
int aThreadIndex = myThreads.Lower();
|
||||
for (NCollection_Array1<EnumeratedThread>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More(); aThreadIter.Next())
|
||||
{
|
||||
EnumeratedThread& aThread = aThreadIter.ChangeValue();
|
||||
if (!aThread.Lock())
|
||||
{
|
||||
for (NCollection_Array1<EnumeratedThread*>::Iterator aLockThreadIter (aLockThreads);
|
||||
aLockThreadIter.More() && aLockThreadIter.Value() != NULL; aLockThreadIter.Next())
|
||||
{
|
||||
aLockThreadIter.ChangeValue()->Free();
|
||||
}
|
||||
throw Standard_ProgramError ("Error: active ThreadPool is reinitialized");
|
||||
}
|
||||
aLockThreads.SetValue (aThreadIndex++, &aThread);
|
||||
}
|
||||
}
|
||||
release();
|
||||
|
||||
myShutDown = false;
|
||||
if (aNbThreads > 0)
|
||||
{
|
||||
myThreads.Resize (0, aNbThreads - 1, false);
|
||||
int aLastThreadIndex = 0;
|
||||
for (NCollection_Array1<EnumeratedThread>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More(); aThreadIter.Next())
|
||||
{
|
||||
EnumeratedThread& aThread = aThreadIter.ChangeValue();
|
||||
aThread.myPool = this;
|
||||
aThread.myThreadIndex = aLastThreadIndex++;
|
||||
aThread.SetFunction (&OSD_ThreadPool::EnumeratedThread::runThread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NCollection_Array1<EnumeratedThread> anEmpty;
|
||||
myThreads.Move (anEmpty);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~OSD_ThreadPool
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
OSD_ThreadPool::~OSD_ThreadPool()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : release
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::release()
|
||||
{
|
||||
if (myThreads.IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
myShutDown = true;
|
||||
for (NCollection_Array1<EnumeratedThread>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More(); aThreadIter.Next())
|
||||
{
|
||||
aThreadIter.ChangeValue().WakeUp (NULL, false);
|
||||
aThreadIter.ChangeValue().Wait();
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : perform
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::Launcher::perform (JobInterface& theJob)
|
||||
{
|
||||
run (theJob);
|
||||
wait();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : run
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::Launcher::run (JobInterface& theJob)
|
||||
{
|
||||
bool toCatchFpe = OSD::ToCatchFloatingSignals();
|
||||
for (NCollection_Array1<EnumeratedThread*>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More() && aThreadIter.Value() != NULL; aThreadIter.Next())
|
||||
{
|
||||
aThreadIter.ChangeValue()->WakeUp (&theJob, toCatchFpe);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : wait
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::Launcher::wait()
|
||||
{
|
||||
int aNbFailures = 0;
|
||||
for (NCollection_Array1<EnumeratedThread*>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More() && aThreadIter.Value() != NULL; aThreadIter.Next())
|
||||
{
|
||||
aThreadIter.ChangeValue()->WaitIdle();
|
||||
if (!aThreadIter.Value()->myFailure.IsNull())
|
||||
{
|
||||
++aNbFailures;
|
||||
}
|
||||
}
|
||||
if (aNbFailures == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TCollection_AsciiString aFailures;
|
||||
for (NCollection_Array1<EnumeratedThread*>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More() && aThreadIter.Value() != NULL; aThreadIter.Next())
|
||||
{
|
||||
if (!aThreadIter.Value()->myFailure.IsNull())
|
||||
{
|
||||
if (aNbFailures == 1)
|
||||
{
|
||||
aThreadIter.Value()->myFailure->Reraise();
|
||||
}
|
||||
|
||||
if (!aFailures.IsEmpty())
|
||||
{
|
||||
aFailures += "\n";
|
||||
}
|
||||
aFailures += aThreadIter.Value()->myFailure->GetMessageString();
|
||||
}
|
||||
}
|
||||
|
||||
aFailures = TCollection_AsciiString("Multiple exceptions:\n") + aFailures;
|
||||
throw Standard_ProgramError (aFailures.ToCString());
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : performJob
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::performJob (Handle(Standard_Failure)& theFailure,
|
||||
OSD_ThreadPool::JobInterface* theJob,
|
||||
int theThreadIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
theJob->Perform (theThreadIndex);
|
||||
}
|
||||
catch (Standard_Failure const& aFailure)
|
||||
{
|
||||
TCollection_AsciiString aMsg = TCollection_AsciiString (aFailure.DynamicType()->Name())
|
||||
+ ": " + aFailure.GetMessageString();
|
||||
theFailure = new Standard_ProgramError (aMsg.ToCString());
|
||||
}
|
||||
catch (std::exception& anStdException)
|
||||
{
|
||||
TCollection_AsciiString aMsg = TCollection_AsciiString (typeid(anStdException).name())
|
||||
+ ": " + anStdException.what();
|
||||
theFailure = new Standard_ProgramError (aMsg.ToCString());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
theFailure = new Standard_ProgramError ("Error: Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : performThread
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::EnumeratedThread::performThread()
|
||||
{
|
||||
OSD::SetSignal (false);
|
||||
for (;;)
|
||||
{
|
||||
myWakeEvent.Wait();
|
||||
myWakeEvent.Reset();
|
||||
if (myPool->myShutDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
myFailure.Nullify();
|
||||
if (myJob != NULL)
|
||||
{
|
||||
OSD::SetSignal (myToCatchFpe);
|
||||
OSD_ThreadPool::performJob (myFailure, myJob, myThreadIndex);
|
||||
myJob = NULL;
|
||||
}
|
||||
myIdleEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : runThread
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Address OSD_ThreadPool::EnumeratedThread::runThread (Standard_Address theTask)
|
||||
{
|
||||
EnumeratedThread* aThread = static_cast<EnumeratedThread*>(theTask);
|
||||
aThread->performThread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Launcher
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
OSD_ThreadPool::Launcher::Launcher (OSD_ThreadPool& thePool, Standard_Integer theMaxThreads)
|
||||
: mySelfThread (true),
|
||||
myNbThreads (0)
|
||||
{
|
||||
const int aNbThreads = theMaxThreads > 0
|
||||
? Min (theMaxThreads, thePool.NbThreads())
|
||||
: (theMaxThreads < 0
|
||||
? Max (thePool.NbDefaultThreadsToLaunch(), 1)
|
||||
: 1);
|
||||
myThreads.Resize (0, aNbThreads - 1, false);
|
||||
myThreads.Init (NULL);
|
||||
if (aNbThreads > 1)
|
||||
{
|
||||
for (NCollection_Array1<EnumeratedThread>::Iterator aThreadIter (thePool.myThreads);
|
||||
aThreadIter.More(); aThreadIter.Next())
|
||||
{
|
||||
if (aThreadIter.ChangeValue().Lock())
|
||||
{
|
||||
myThreads.SetValue (myNbThreads, &aThreadIter.ChangeValue());
|
||||
// make thread index to fit into myThreads range
|
||||
aThreadIter.ChangeValue().myThreadIndex = myNbThreads;
|
||||
if (++myNbThreads == aNbThreads - 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// self thread should be executed last
|
||||
myThreads.SetValue (myNbThreads, &mySelfThread);
|
||||
mySelfThread.myThreadIndex = myNbThreads;
|
||||
++myNbThreads;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Release
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OSD_ThreadPool::Launcher::Release()
|
||||
{
|
||||
for (NCollection_Array1<EnumeratedThread*>::Iterator aThreadIter (myThreads);
|
||||
aThreadIter.More() && aThreadIter.Value() != NULL; aThreadIter.Next())
|
||||
{
|
||||
if (aThreadIter.Value() != &mySelfThread)
|
||||
{
|
||||
aThreadIter.Value()->Free();
|
||||
}
|
||||
}
|
||||
|
||||
NCollection_Array1<EnumeratedThread*> anEmpty;
|
||||
myThreads.Move (anEmpty);
|
||||
myNbThreads = 0;
|
||||
}
|
301
src/OSD/OSD_ThreadPool.hxx
Normal file
301
src/OSD/OSD_ThreadPool.hxx
Normal file
@@ -0,0 +1,301 @@
|
||||
// Created by: Kirill Gavrilov
|
||||
// Copyright (c) 2017 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS.
|
||||
//
|
||||
// This software is furnished in accordance with the terms and conditions
|
||||
// of the contract and with the inclusion of this copyright notice.
|
||||
// This software or any other copy thereof may not be provided or otherwise
|
||||
// be made available to any third party.
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef _OSD_ThreadPool_HeaderFile
|
||||
#define _OSD_ThreadPool_HeaderFile
|
||||
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <OSD_Thread.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <Standard_Atomic.hxx>
|
||||
#include <Standard_Condition.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
|
||||
//! Class defining a thread pool for executing algorithms in multi-threaded mode.
|
||||
//! Thread pool allocates requested amount of threads and keep them alive
|
||||
//! (in sleep mode when unused) during thread pool lifetime.
|
||||
//! The same pool can be used by multiple consumers,
|
||||
//! including nested multi-threading algorithms and concurrent threads:
|
||||
//! - Thread pool can be used either by multi-threaded algorithm by creating OSD_ThreadPool::Launcher.
|
||||
//! The functor performing a job takes two parameters - Thread Index and Data Index:
|
||||
//! void operator(int theThreadIndex, int theDataIndex){}
|
||||
//! Multi-threaded algorithm may rely on Thread Index for allocating thread-local variables in array form,
|
||||
//! since the Thread Index is guaranteed to be within range OSD_ThreadPool::Lower() and OSD_ThreadPool::Upper().
|
||||
//! - Default thread pool (OSD_ThreadPool::DefaultPool()) can be used in general case,
|
||||
//! but application may prefer creating a dedicated pool for better control.
|
||||
//! - Default thread pool allocates the amount of threads considering concurrency
|
||||
//! level of the system (amount of logical processors).
|
||||
//! This can be overridden during OSD_ThreadPool construction or by calling OSD_ThreadPool::Init()
|
||||
//! (the pool should not be used!).
|
||||
//! - OSD_ThreadPool::Launcher reserves specific amount of threads from the pool for executing multi-threaded Job.
|
||||
//! Normally, single Launcher instance will occupy all threads available in thread pool,
|
||||
//! so that nested multi-threaded algorithms (within the same thread)
|
||||
//! and concurrent threads trying to use the same thread pool will run sequentially.
|
||||
//! This behavior is affected by OSD_ThreadPool::NbDefaultThreadsToLaunch() parameter
|
||||
//! and Launcher constructor, so that single Launcher instance will occupy not all threads
|
||||
//! in the pool allowing other threads to be used concurrently.
|
||||
//! - OSD_ThreadPool::Launcher locks thread one-by-one from thread pool in a thread-safe way.
|
||||
//! - Each working thread catches exceptions occurred during job execution, and Launcher will
|
||||
//! throw Standard_Failure in a caller thread on completed execution.
|
||||
class OSD_ThreadPool : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(OSD_ThreadPool, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Return (or create) a default thread pool.
|
||||
//! Number of threads argument will be considered only when called first time.
|
||||
Standard_EXPORT static const Handle(OSD_ThreadPool)& DefaultPool (int theNbThreads = -1);
|
||||
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
//! Application may consider specifying more threads than actually
|
||||
//! available (OSD_Parallel::NbLogicalProcessors()) and set up NbDefaultThreadsToLaunch() to a smaller value
|
||||
//! so that concurrent threads will be able using single Thread Pool instance more efficiently.
|
||||
//! @param theNbThreads threads number to be created by pool
|
||||
//! (if -1 is specified then OSD_Parallel::NbLogicalProcessors() will be used)
|
||||
Standard_EXPORT OSD_ThreadPool (int theNbThreads = -1);
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~OSD_ThreadPool();
|
||||
|
||||
//! Return TRUE if at least 2 threads are available (including self-thread).
|
||||
bool HasThreads() const { return NbThreads() >= 2; }
|
||||
|
||||
//! Return the lower thread index.
|
||||
int LowerThreadIndex() const { return 0; }
|
||||
|
||||
//! Return the upper thread index (last index is reserved for self-thread).
|
||||
int UpperThreadIndex() const { return LowerThreadIndex() + myThreads.Size(); }
|
||||
|
||||
//! Return the number of threads; >= 1.
|
||||
int NbThreads() const { return myThreads.Size() + 1; }
|
||||
|
||||
//! Return maximum number of threads to be locked by a single Launcher object by default;
|
||||
//! the entire thread pool size is returned by default.
|
||||
int NbDefaultThreadsToLaunch() const { return myNbDefThreads; }
|
||||
|
||||
//! Set maximum number of threads to be locked by a single Launcher object by default.
|
||||
//! Should be set BEFORE first usage.
|
||||
void SetNbDefaultThreadsToLaunch (int theNbThreads) { myNbDefThreads = theNbThreads; }
|
||||
|
||||
//! Checks if thread pools has active consumers.
|
||||
Standard_EXPORT bool IsInUse();
|
||||
|
||||
//! Reinitialize the thread pool with a different number of threads.
|
||||
//! Should be called only with no active jobs, or exception Standard_ProgramError will be thrown!
|
||||
Standard_EXPORT void Init (int theNbThreads);
|
||||
|
||||
protected:
|
||||
|
||||
//! Thread function interface.
|
||||
class JobInterface
|
||||
{
|
||||
public:
|
||||
virtual void Perform (int theThreadIndex) = 0;
|
||||
};
|
||||
|
||||
//! Thread with back reference to thread pool and thread index in it.
|
||||
class EnumeratedThread : public OSD_Thread
|
||||
{
|
||||
friend class OSD_ThreadPool;
|
||||
public:
|
||||
EnumeratedThread (bool theIsSelfThread = false)
|
||||
: myPool (NULL), myJob (NULL), myWakeEvent (false),
|
||||
myIdleEvent (false), myThreadIndex (0), myUsageCounter(0),
|
||||
myIsStarted (false), myToCatchFpe (false),
|
||||
myIsSelfThread (theIsSelfThread) {}
|
||||
|
||||
//! Occupy this thread for thread pool launcher.
|
||||
//! @return TRUE on success, or FALSE if thread has been already occupied
|
||||
Standard_EXPORT bool Lock();
|
||||
|
||||
//! Release this thread for thread pool launcher; should be called only after successful OccupyThread().
|
||||
Standard_EXPORT void Free();
|
||||
|
||||
//! Wake up the thread.
|
||||
Standard_EXPORT void WakeUp (JobInterface* theJob, bool theToCatchFpe);
|
||||
|
||||
//! Wait the thread going into Idle state (finished jobs).
|
||||
Standard_EXPORT void WaitIdle();
|
||||
|
||||
private:
|
||||
|
||||
//! Method is executed in the context of thread.
|
||||
void performThread();
|
||||
|
||||
//! Method is executed in the context of thread.
|
||||
static Standard_Address runThread (Standard_Address theTask);
|
||||
|
||||
private:
|
||||
OSD_ThreadPool* myPool;
|
||||
JobInterface* myJob;
|
||||
Handle(Standard_Failure) myFailure;
|
||||
Standard_Condition myWakeEvent;
|
||||
Standard_Condition myIdleEvent;
|
||||
int myThreadIndex;
|
||||
volatile int myUsageCounter;
|
||||
bool myIsStarted;
|
||||
bool myToCatchFpe;
|
||||
bool myIsSelfThread;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//! Launcher object locking a subset of threads (or all threads)
|
||||
//! in a thread pool to perform parallel execution of the job.
|
||||
class Launcher
|
||||
{
|
||||
public:
|
||||
//! Lock specified number of threads from the thread pool.
|
||||
//! If thread pool is already locked by another user,
|
||||
//! Launcher will lock as many threads as possible
|
||||
//! (if none will be locked, then single threaded execution will be done).
|
||||
//! @param thePool thread pool to lock the threads
|
||||
//! @param theMaxThreads number of threads to lock;
|
||||
//! -1 specifies that default number of threads
|
||||
//! to be used OSD_ThreadPool::NbDefaultThreadsToLaunch()
|
||||
Standard_EXPORT Launcher (OSD_ThreadPool& thePool, int theMaxThreads = -1);
|
||||
|
||||
//! Release threads.
|
||||
~Launcher() { Release(); }
|
||||
|
||||
//! Return TRUE if at least 2 threads have been locked for parallel execution (including self-thread);
|
||||
//! otherwise, the functor will be executed within the caller thread.
|
||||
bool HasThreads() const { return myNbThreads >= 2; }
|
||||
|
||||
//! Return amount of locked threads; >= 1.
|
||||
int NbThreads() const { return myNbThreads; }
|
||||
|
||||
//! Return the lower thread index.
|
||||
int LowerThreadIndex() const { return 0; }
|
||||
|
||||
//! Return the upper thread index (last index is reserved for the self-thread).
|
||||
int UpperThreadIndex() const { return LowerThreadIndex() + myNbThreads - 1; }
|
||||
|
||||
//! Simple primitive for parallelization of "for" loops, e.g.:
|
||||
//! @code
|
||||
//! for (int anIter = theBegin; anIter < theEnd; ++anIter) {}
|
||||
//! @endcode
|
||||
//! @param theBegin the first data index (inclusive)
|
||||
//! @param theEnd the last data index (exclusive)
|
||||
//! @param theFunctor functor providing an interface
|
||||
//! "void operator(int theThreadIndex, int theDataIndex){}" performing task for specified index
|
||||
template<typename Functor>
|
||||
void Perform (int theBegin, int theEnd, const Functor& theFunctor)
|
||||
{
|
||||
JobRange aData (theBegin, theEnd);
|
||||
Job<Functor> aJob (theFunctor, aData);
|
||||
perform (aJob);
|
||||
}
|
||||
|
||||
//! Release threads before Launcher destruction.
|
||||
Standard_EXPORT void Release();
|
||||
|
||||
protected:
|
||||
|
||||
//! Execute job.
|
||||
Standard_EXPORT void perform (JobInterface& theJob);
|
||||
|
||||
//! Initialize job and start threads.
|
||||
Standard_EXPORT void run (JobInterface& theJob);
|
||||
|
||||
//! Wait threads execution.
|
||||
Standard_EXPORT void wait();
|
||||
|
||||
private:
|
||||
Launcher (const Launcher& theCopy);
|
||||
Launcher& operator=(const Launcher& theCopy);
|
||||
|
||||
private:
|
||||
NCollection_Array1<EnumeratedThread*> myThreads; //!< array of locked threads (including self-thread)
|
||||
EnumeratedThread mySelfThread;
|
||||
int myNbThreads; //!< amount of locked threads
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
//! Auxiliary class which ensures exclusive access to iterators of processed data pool.
|
||||
class JobRange
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
JobRange (const int& theBegin, const int& theEnd) : myBegin(theBegin), myEnd (theEnd), myIt (theBegin) {}
|
||||
|
||||
//! Returns const link on the first element.
|
||||
const int& Begin() const { return myBegin; }
|
||||
|
||||
//! Returns const link on the last element.
|
||||
const int& End() const { return myEnd; }
|
||||
|
||||
//! Returns first non processed element or end.
|
||||
//! Thread-safe method.
|
||||
int It() const { return Standard_Atomic_Increment (reinterpret_cast<volatile int*>(&myIt)) - 1; }
|
||||
|
||||
private:
|
||||
JobRange (const JobRange& theCopy);
|
||||
JobRange& operator=(const JobRange& theCopy);
|
||||
|
||||
private:
|
||||
const int& myBegin; //!< First element of range
|
||||
const int& myEnd; //!< Last element of range
|
||||
mutable int myIt; //!< First non processed element of range
|
||||
};
|
||||
|
||||
//! Auxiliary wrapper class for thread function.
|
||||
template<typename FunctorT> class Job : public JobInterface
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
Job (const FunctorT& thePerformer, JobRange& theRange)
|
||||
: myPerformer (thePerformer), myRange (theRange) {}
|
||||
|
||||
//! Method is executed in the context of thread.
|
||||
virtual void Perform (int theThreadIndex) Standard_OVERRIDE
|
||||
{
|
||||
for (Standard_Integer anIter = myRange.It(); anIter < myRange.End(); anIter = myRange.It())
|
||||
{
|
||||
myPerformer (theThreadIndex, anIter);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Job (const Job& theCopy);
|
||||
Job& operator=(const Job& theCopy);
|
||||
|
||||
private: //! @name private fields
|
||||
const FunctorT& myPerformer; //!< Link on functor
|
||||
const JobRange& myRange; //!< Link on processed data block
|
||||
};
|
||||
|
||||
//! Release threads.
|
||||
void release();
|
||||
|
||||
//! Perform the job and catch exceptions.
|
||||
static void performJob (Handle(Standard_Failure)& theFailure,
|
||||
OSD_ThreadPool::JobInterface* theJob,
|
||||
int theThreadIndex);
|
||||
|
||||
private:
|
||||
|
||||
NCollection_Array1<EnumeratedThread> myThreads; //!< array of defined threads (excluding self-thread)
|
||||
int myNbDefThreads; //!< maximum number of threads to be locked by a single Launcher by default
|
||||
bool myShutDown; //!< flag to shut down (destroy) the thread pool
|
||||
|
||||
};
|
||||
|
||||
#endif // _OSD_ThreadPool_HeaderFile
|
@@ -17,6 +17,17 @@
|
||||
#include <Standard_DivideByZero.hxx>
|
||||
#include <Standard_Overflow.hxx>
|
||||
|
||||
static Standard_THREADLOCAL Standard_Boolean fFltExceptions = Standard_False;
|
||||
|
||||
//=======================================================================
|
||||
//function : ToCatchFloatingSignals
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean OSD::ToCatchFloatingSignals()
|
||||
{
|
||||
return fFltExceptions;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
//---------------------------- Windows NT System --------------------------------
|
||||
|
||||
@@ -53,7 +64,7 @@
|
||||
#include <Standard_ProgramError.hxx>
|
||||
#include <Standard_Mutex.hxx>
|
||||
|
||||
#include <OSD_WNT_1.hxx>
|
||||
#include <OSD_WNT.hxx>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <eh.h>
|
||||
@@ -65,10 +76,8 @@
|
||||
#include <float.h>
|
||||
|
||||
static Standard_Boolean fCtrlBrk;
|
||||
#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
|
||||
|
||||
static Standard_Boolean fMsgBox;
|
||||
static Standard_Boolean fFltExceptions;
|
||||
static Standard_Boolean fDbgLoaded;
|
||||
|
||||
// used to forbid simultaneous execution of setting / executing handlers
|
||||
static Standard_Mutex THE_SIGNAL_MUTEX;
|
||||
@@ -76,13 +85,20 @@ static Standard_Mutex THE_SIGNAL_MUTEX;
|
||||
static LONG __fastcall _osd_raise ( DWORD, LPSTR );
|
||||
static BOOL WINAPI _osd_ctrl_break_handler ( DWORD );
|
||||
|
||||
#ifndef OCCT_UWP
|
||||
#if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
|
||||
static Standard_Boolean fDbgLoaded;
|
||||
static LONG _osd_debug ( void );
|
||||
#endif
|
||||
|
||||
//# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW )
|
||||
# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
|
||||
|
||||
#ifdef OCC_CONVERT_SIGNALS
|
||||
#define THROW_OR_JUMP(Type,Message) Type::NewInstance(Message)->Jump()
|
||||
#else
|
||||
#define THROW_OR_JUMP(Type,Message) throw Type(Message)
|
||||
#endif
|
||||
|
||||
//=======================================================================
|
||||
//function : CallHandler
|
||||
//purpose :
|
||||
@@ -148,7 +164,8 @@ static LONG CallHandler (DWORD dwExceptionCode,
|
||||
break ;
|
||||
case STATUS_NO_MEMORY:
|
||||
// cout << "CallHandler : STATUS_NO_MEMORY:" << endl ;
|
||||
throw OSD_Exception_STATUS_NO_MEMORY ( "MEMORY ALLOCATION ERROR ( no room in the process heap )" );
|
||||
THROW_OR_JUMP (OSD_Exception_STATUS_NO_MEMORY, "MEMORY ALLOCATION ERROR ( no room in the process heap )");
|
||||
break;
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
// cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << endl ;
|
||||
StringCchPrintfW (buffer, _countof(buffer), L"%s%s%s0x%.8p%s%s%s", L"ACCESS VIOLATION",
|
||||
@@ -227,7 +244,7 @@ static LONG CallHandler (DWORD dwExceptionCode,
|
||||
_fpreset();
|
||||
_clearfp();
|
||||
|
||||
#ifndef OCCT_UWP
|
||||
#if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
|
||||
MessageBeep ( MB_ICONHAND );
|
||||
int aChoice = ::MessageBoxW (0, buffer, L"OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
|
||||
if (aChoice == IDRETRY)
|
||||
@@ -287,7 +304,7 @@ static void SIGWntHandler (int signum, int sub_code)
|
||||
break ;
|
||||
default:
|
||||
cout << "SIGWntHandler(default) -> throw Standard_NumericError(\"Floating Point Error\");" << endl;
|
||||
throw Standard_NumericError("Floating Point Error");
|
||||
THROW_OR_JUMP (Standard_NumericError, "Floating Point Error");
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
@@ -309,7 +326,6 @@ static void SIGWntHandler (int signum, int sub_code)
|
||||
DebugBreak ();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
//=======================================================================
|
||||
//function : TranslateSE
|
||||
@@ -342,7 +358,6 @@ static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
|
||||
// option and unless user sets his own exception handler with
|
||||
// ::SetUnhandledExceptionFilter().
|
||||
//=======================================================================
|
||||
#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
|
||||
static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
|
||||
{
|
||||
DWORD dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
|
||||
@@ -351,7 +366,6 @@ static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
|
||||
lpXP->ExceptionRecord->ExceptionInformation[1],
|
||||
lpXP->ExceptionRecord->ExceptionInformation[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//=======================================================================
|
||||
//function : SetSignal
|
||||
@@ -359,11 +373,8 @@ static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
|
||||
//=======================================================================
|
||||
void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
|
||||
{
|
||||
#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
|
||||
Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
|
||||
#if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
|
||||
|
||||
OSD_Environment env ("CSF_DEBUG_MODE");
|
||||
TCollection_AsciiString val = env.Value();
|
||||
if (!env.Failed())
|
||||
@@ -380,7 +391,7 @@ void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
|
||||
// when user's code is compiled with /EHs
|
||||
// Replaces the existing top-level exception filter for all existing and all future threads
|
||||
// in the calling process
|
||||
aPreviousFilter = ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
|
||||
::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
|
||||
#endif // NTDDI_WIN10_TH2
|
||||
|
||||
// Signal handlers will only be used when the method ::raise() will be used
|
||||
@@ -410,7 +421,6 @@ void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
|
||||
else {
|
||||
_controlfp (_OSD_FPX, _OSD_FPX); // JR add :
|
||||
}
|
||||
#endif
|
||||
} // end OSD :: SetSignal
|
||||
|
||||
//============================================================================
|
||||
@@ -422,7 +432,7 @@ void OSD::ControlBreak () {
|
||||
throw OSD_Exception_CTRL_BREAK ( "*** INTERRUPT ***" );
|
||||
}
|
||||
} // end OSD :: ControlBreak
|
||||
#if !defined(__MINGW32__) && !defined(__CYGWIN32__)
|
||||
|
||||
#ifndef OCCT_UWP
|
||||
//============================================================================
|
||||
//==== _osd_ctrl_break_handler
|
||||
@@ -437,6 +447,7 @@ static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
|
||||
return TRUE;
|
||||
} // end _osd_ctrl_break_handler
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
//==== _osd_raise
|
||||
//============================================================================
|
||||
@@ -447,54 +458,54 @@ static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
|
||||
switch (dwCode)
|
||||
{
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
throw OSD_Exception_ACCESS_VIOLATION(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_ACCESS_VIOLATION, msg);
|
||||
break;
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||
throw OSD_Exception_ARRAY_BOUNDS_EXCEEDED(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_ARRAY_BOUNDS_EXCEEDED, msg);
|
||||
break;
|
||||
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||
throw Standard_ProgramError(msg);
|
||||
THROW_OR_JUMP (Standard_ProgramError, msg);
|
||||
break;
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
throw OSD_Exception_ILLEGAL_INSTRUCTION(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_ILLEGAL_INSTRUCTION, msg);
|
||||
break;
|
||||
case EXCEPTION_IN_PAGE_ERROR:
|
||||
throw OSD_Exception_IN_PAGE_ERROR(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_IN_PAGE_ERROR, msg);
|
||||
break;
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
throw Standard_DivideByZero(msg);
|
||||
THROW_OR_JUMP (Standard_DivideByZero, msg);
|
||||
break;
|
||||
case EXCEPTION_INT_OVERFLOW:
|
||||
throw OSD_Exception_INT_OVERFLOW(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_INT_OVERFLOW, msg);
|
||||
break;
|
||||
case EXCEPTION_INVALID_DISPOSITION:
|
||||
throw OSD_Exception_INVALID_DISPOSITION(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_INVALID_DISPOSITION, msg);
|
||||
break;
|
||||
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
||||
throw OSD_Exception_NONCONTINUABLE_EXCEPTION(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_NONCONTINUABLE_EXCEPTION, msg);
|
||||
break;
|
||||
case EXCEPTION_PRIV_INSTRUCTION:
|
||||
throw OSD_Exception_PRIV_INSTRUCTION(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_PRIV_INSTRUCTION, msg);
|
||||
break;
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
throw OSD_Exception_STACK_OVERFLOW(msg);
|
||||
THROW_OR_JUMP (OSD_Exception_STACK_OVERFLOW, msg);
|
||||
break;
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||
throw Standard_DivideByZero(msg);
|
||||
THROW_OR_JUMP (Standard_DivideByZero, msg);
|
||||
break;
|
||||
case EXCEPTION_FLT_STACK_CHECK:
|
||||
case EXCEPTION_FLT_OVERFLOW:
|
||||
throw Standard_Overflow(msg);
|
||||
THROW_OR_JUMP (Standard_Overflow, msg);
|
||||
break;
|
||||
case EXCEPTION_FLT_UNDERFLOW:
|
||||
throw Standard_Underflow(msg);
|
||||
THROW_OR_JUMP (Standard_Underflow, msg);
|
||||
break;
|
||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||
case STATUS_FLOAT_MULTIPLE_TRAPS:
|
||||
case STATUS_FLOAT_MULTIPLE_FAULTS:
|
||||
throw Standard_NumericError(msg);
|
||||
THROW_OR_JUMP (Standard_NumericError, msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -502,10 +513,10 @@ static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
} // end _osd_raise
|
||||
|
||||
#if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
|
||||
//============================================================================
|
||||
//==== _osd_debug
|
||||
//============================================================================
|
||||
#ifndef OCCT_UWP
|
||||
LONG _osd_debug ( void ) {
|
||||
|
||||
LONG action ;
|
||||
@@ -588,10 +599,9 @@ LONG _osd_debug ( void ) {
|
||||
return action ;
|
||||
|
||||
} // end _osd_debug
|
||||
#endif /* ! OCCT_UWP && ! __CYGWIN__ && ! __MINGW32__ */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#else /* ! _WIN32 */
|
||||
|
||||
//---------- All Systems except Windows NT : ----------------------------------
|
||||
|
||||
@@ -616,7 +626,6 @@ LONG _osd_debug ( void ) {
|
||||
#ifdef __linux__
|
||||
#include <cfenv>
|
||||
//#include <fenv.h>
|
||||
static Standard_Boolean fFltExceptions = Standard_False;
|
||||
#endif
|
||||
|
||||
// variable signalling that Control-C has been pressed (SIGINT signal)
|
||||
@@ -635,7 +644,7 @@ typedef void (* SIG_PFV) (int);
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
#else
|
||||
# ifdef SA_SIGINFO
|
||||
# ifdef SA_SIGINFO
|
||||
# ifndef _AIX
|
||||
# include <sys/siginfo.h>
|
||||
# endif
|
||||
@@ -866,11 +875,11 @@ static void SegvHandler(const int theSignal,
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
//==== SetSignal
|
||||
//==== SetSignal
|
||||
//==== Set the differents signals:
|
||||
//============================================================================
|
||||
|
||||
void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
{
|
||||
struct sigaction act, oact;
|
||||
int stat = 0;
|
||||
@@ -932,7 +941,7 @@ void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
#endif
|
||||
|
||||
//==== Always detected the signal "SIGFPE" =================================
|
||||
stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
|
||||
stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
|
||||
if (stat) {
|
||||
#ifdef OCCT_DEBUG
|
||||
cerr << "sigaction does not work !!! KO " << endl;
|
||||
@@ -941,38 +950,38 @@ void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
}
|
||||
|
||||
//==== Detected the only the "free" signals ================================
|
||||
sigaction(SIGHUP,&act,&oact); // ...... hangup
|
||||
sigaction(SIGHUP,&act,&oact); // ...... hangup
|
||||
|
||||
#ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGHUP,&oact,&oact);
|
||||
#endif
|
||||
|
||||
sigaction(SIGINT,&act,&oact); // ...... interrupt
|
||||
sigaction(SIGINT,&act,&oact); // ...... interrupt
|
||||
|
||||
#ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGINT,&oact,&oact);
|
||||
#endif
|
||||
|
||||
|
||||
sigaction(SIGQUIT,&act,&oact); // ...... quit
|
||||
|
||||
#ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGQUIT,&oact,&oact);
|
||||
#endif
|
||||
|
||||
sigaction(SIGILL,&act,&oact); // ...... illegal instruction
|
||||
sigaction(SIGILL,&act,&oact); // ...... illegal instruction
|
||||
|
||||
#ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGILL,&oact,&oact);
|
||||
#endif
|
||||
|
||||
sigaction(SIGBUS,&act,&oact); // ...... bus error
|
||||
sigaction(SIGBUS,&act,&oact); // ...... bus error
|
||||
|
||||
#ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGBUS,&oact,&oact);
|
||||
#endif
|
||||
|
||||
@@ -980,7 +989,7 @@ void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
|
||||
|
||||
# ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGSYS,&oact,&oact);
|
||||
# endif
|
||||
#endif
|
||||
@@ -989,7 +998,7 @@ void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
|
||||
|
||||
# ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGTRAP,&oact,&oact);
|
||||
# endif
|
||||
#endif
|
||||
@@ -1004,7 +1013,7 @@ void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
|
||||
|
||||
#ifdef OBJS
|
||||
if(oact.sa_handler)
|
||||
if(oact.sa_handler)
|
||||
sigaction(SIGSEGV,&oact,&oact);
|
||||
#endif
|
||||
#if defined(__osf__) || defined(DECOSF1)
|
||||
@@ -1012,7 +1021,7 @@ void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
action.sa_handler = SIG_IGN;
|
||||
action.sa_mask = 0;
|
||||
action.sa_flags = 0;
|
||||
|
||||
|
||||
if (sigaction (SIGFPE, &action, &prev_action) == -1) {
|
||||
perror ("sigaction");
|
||||
exit (1);
|
||||
@@ -1022,14 +1031,14 @@ void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//==== ControlBreak
|
||||
//==== ControlBreak
|
||||
//============================================================================
|
||||
|
||||
void OSD :: ControlBreak ()
|
||||
void OSD :: ControlBreak ()
|
||||
{
|
||||
if ( fCtrlBrk ) {
|
||||
fCtrlBrk = Standard_False;
|
||||
throw OSD_Exception_CTRL_BREAK("*** INTERRUPT ***");
|
||||
throw OSD_Exception_CTRL_BREAK ("*** INTERRUPT ***");
|
||||
}
|
||||
}
|
||||
|
||||
|
471
src/OpenGl/OpenGl_AVIWriter.cxx
Normal file
471
src/OpenGl/OpenGl_AVIWriter.cxx
Normal file
@@ -0,0 +1,471 @@
|
||||
// Created on: 2007-04-15
|
||||
// Created by: Alexey MORENOV & Alexander GRIGORIEV
|
||||
// Copyright (c) 2007-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 <OpenGl_AVIWriter.hxx>
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "vfw32.lib")
|
||||
#endif
|
||||
|
||||
OpenGl_AVIWriter* OpenGl_AVIWriter::MyAVIWriterInstance = 0L;
|
||||
|
||||
OpenGl_AVIWriter * OpenGl_AVIWriter::GetInstance()
|
||||
{
|
||||
return MyAVIWriterInstance;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : OpenGl_AVIWriter
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_EXPORT OpenGl_AVIWriter::OpenGl_AVIWriter
|
||||
(const wchar_t * theFileName,
|
||||
DWORD dwCodec /* = mmioFOURCC('M','P','G','4') */,
|
||||
Standard_Integer theFrameRate /* = 25 */)
|
||||
: myhHeap (0L),
|
||||
myhWindow (0L),
|
||||
myhAviDC (0L),
|
||||
mylpBits (0L),
|
||||
mylSample (0L),
|
||||
mypAviFile (0L),
|
||||
mypAviStream (0L),
|
||||
mypAviCompressedStream(0L),
|
||||
myFileName (0L),
|
||||
myIsAllowRecord (Standard_False),
|
||||
myAppendFuncSelector(1) //0=Dummy 1=FirstTime 2=Usual
|
||||
{
|
||||
::AVIFileInit();
|
||||
if (theFileName != 0L && theFileName[0] != L'\0') {
|
||||
|
||||
const size_t aLen = wcslen(theFileName) + 1;
|
||||
myFileName = new wchar_t [aLen];
|
||||
memcpy(myFileName, theFileName, aLen * sizeof(wchar_t));
|
||||
myErrMsg = "Method Succeeded";
|
||||
|
||||
pAppendFrame[0]= &OpenGl_AVIWriter::AppendDummy;
|
||||
pAppendFrame[1]= &OpenGl_AVIWriter::AppendFrameFirstTime;
|
||||
pAppendFrame[2]= &OpenGl_AVIWriter::AppendFrameUsual;
|
||||
|
||||
pAppendFrameBits[0]=&OpenGl_AVIWriter::AppendDummyBits;
|
||||
pAppendFrameBits[1]=&OpenGl_AVIWriter::AppendFrameBitsFirstTime;
|
||||
pAppendFrameBits[2]=&OpenGl_AVIWriter::AppendFrameBitsUsual;
|
||||
|
||||
MyAVIWriterInstance = this;
|
||||
|
||||
ZeroMemory(&myAviStreamInfo,sizeof(AVISTREAMINFOW));
|
||||
myAviStreamInfo.fccType = streamtypeVIDEO;
|
||||
myAviStreamInfo.fccHandler = dwCodec;
|
||||
myAviStreamInfo.dwScale = 1;
|
||||
myAviStreamInfo.dwRate = theFrameRate; // Frames Per Second;
|
||||
myAviStreamInfo.dwQuality = 100;/*//-1; // Default Quality*/
|
||||
|
||||
ZeroMemory(&myAviCompressOptions,sizeof(AVICOMPRESSOPTIONS));
|
||||
myAviCompressOptions.fccType = streamtypeVIDEO;
|
||||
myAviCompressOptions.fccHandler = myAviStreamInfo.fccHandler;
|
||||
myAviCompressOptions.dwFlags =
|
||||
AVICOMPRESSF_KEYFRAMES|AVICOMPRESSF_VALID|AVICOMPRESSF_DATARATE;
|
||||
myAviCompressOptions.dwKeyFrameEvery = 1;
|
||||
myAviCompressOptions.dwBytesPerSecond = 125000;
|
||||
myAviCompressOptions.dwQuality = 100;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ~OpenGl_AVIWriter
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_EXPORT OpenGl_AVIWriter::~OpenGl_AVIWriter(void)
|
||||
{
|
||||
ReleaseMemory();
|
||||
AVIFileExit();
|
||||
if (myFileName)
|
||||
delete [] myFileName;
|
||||
MyAVIWriterInstance = 0L;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : StartRecording
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void OpenGl_AVIWriter::StartRecording(const HANDLE hWin)
|
||||
{
|
||||
if (hWin != NULL)
|
||||
myhWindow = hWin;
|
||||
myIsAllowRecord = Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : StopRecording
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void OpenGl_AVIWriter::StopRecording()
|
||||
{
|
||||
myIsAllowRecord = Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ReleaseMemory
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void OpenGl_AVIWriter::ReleaseMemory()
|
||||
{
|
||||
myAppendFuncSelector=0; //Point to DummyFunction
|
||||
|
||||
if (myhAviDC)
|
||||
{
|
||||
DeleteDC(myhAviDC);
|
||||
myhAviDC=NULL;
|
||||
}
|
||||
if (mypAviCompressedStream)
|
||||
{
|
||||
AVIStreamRelease(mypAviCompressedStream);
|
||||
mypAviCompressedStream=NULL;
|
||||
}
|
||||
if (mypAviStream)
|
||||
{
|
||||
AVIStreamRelease(mypAviStream);
|
||||
mypAviStream=NULL;
|
||||
}
|
||||
if (mypAviFile)
|
||||
{
|
||||
AVIFileRelease(mypAviFile);
|
||||
mypAviFile=NULL;
|
||||
}
|
||||
if (mylpBits)
|
||||
{
|
||||
HeapFree(myhHeap,HEAP_NO_SERIALIZE,mylpBits);
|
||||
mylpBits=NULL;
|
||||
}
|
||||
if (myhHeap)
|
||||
{
|
||||
HeapDestroy(myhHeap);
|
||||
myhHeap=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetErrorMessage
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void OpenGl_AVIWriter::SetErrorMessage(const char * theErrorMessage)
|
||||
{
|
||||
myErrMsg = theErrorMessage;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : InitMovieCreation
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::InitMovieCreation (int nFrameWidth,
|
||||
int nFrameHeight,
|
||||
int nBitsPerPixel)
|
||||
{
|
||||
int nMaxWidth=GetSystemMetrics(SM_CXSCREEN),
|
||||
nMaxHeight=GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
myhAviDC = CreateCompatibleDC(NULL);
|
||||
if (myhAviDC == NULL)
|
||||
{
|
||||
SetErrorMessage("Unable to Create Compatible DC");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (nFrameWidth > nMaxWidth)
|
||||
nMaxWidth= nFrameWidth;
|
||||
if (nFrameHeight > nMaxHeight)
|
||||
nMaxHeight = nFrameHeight;
|
||||
|
||||
myhHeap = HeapCreate(HEAP_NO_SERIALIZE, nMaxWidth*nMaxHeight*4, 0);
|
||||
if (myhHeap == NULL)
|
||||
{
|
||||
SetErrorMessage("Unable to Create Heap");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
mylpBits = HeapAlloc(myhHeap, HEAP_ZERO_MEMORY|HEAP_NO_SERIALIZE,
|
||||
nMaxWidth*nMaxHeight*4);
|
||||
if (mylpBits == NULL)
|
||||
{
|
||||
SetErrorMessage("Unable to Allocate Memory on Heap");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
hr = ::AVIFileOpenW(&mypAviFile, myFileName, OF_CREATE|OF_WRITE, NULL);
|
||||
if (!hr == AVIERR_OK)
|
||||
{
|
||||
SetErrorMessage("Unable to Create the Movie File");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
myAviStreamInfo.dwSuggestedBufferSize = nMaxWidth * nMaxHeight * 4;
|
||||
SetRect(&myAviStreamInfo.rcFrame, 0, 0, nFrameWidth, nFrameHeight);
|
||||
wcsncpy(myAviStreamInfo.szName, L"Video Stream", 64);
|
||||
|
||||
if (FAILED(AVIFileCreateStreamW(mypAviFile, &mypAviStream, &myAviStreamInfo)))
|
||||
{
|
||||
SetErrorMessage("Unable to Create Video Stream in the Movie File");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (FAILED(AVIMakeCompressedStream(&mypAviCompressedStream,
|
||||
mypAviStream,
|
||||
&myAviCompressOptions,
|
||||
NULL)))
|
||||
{
|
||||
// One reason this error might occur is if you are using a Codec that is not
|
||||
// available on your system. Check the mmioFOURCC() code you are using and
|
||||
// make sure you have that codec installed properly on your machine.
|
||||
SetErrorMessage("Unable to Create Compressed Stream: "
|
||||
"Check your CODEC options");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
BITMAPINFO bmpInfo;
|
||||
ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
|
||||
bmpInfo.bmiHeader.biPlanes = 1;
|
||||
bmpInfo.bmiHeader.biWidth = nFrameWidth;
|
||||
bmpInfo.bmiHeader.biHeight = nFrameHeight;
|
||||
bmpInfo.bmiHeader.biCompression = BI_RGB;
|
||||
bmpInfo.bmiHeader.biBitCount = static_cast<WORD>(nBitsPerPixel);
|
||||
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmpInfo.bmiHeader.biSizeImage = (bmpInfo.bmiHeader.biWidth *
|
||||
bmpInfo.bmiHeader.biHeight*
|
||||
bmpInfo.bmiHeader.biBitCount)/8;
|
||||
|
||||
if (FAILED(AVIStreamSetFormat(mypAviCompressedStream,
|
||||
0,
|
||||
(LPVOID)&bmpInfo,
|
||||
bmpInfo.bmiHeader.biSize)))
|
||||
{
|
||||
// One reason this error might occur is if your bitmap does not meet
|
||||
// the Codec requirements.
|
||||
// For example,
|
||||
// your bitmap is 32bpp while the Codec supports only 16 or 24 bpp; Or
|
||||
// your bitmap is 274 * 258 size, while the Codec supports only sizes
|
||||
// that are powers of 2; etc...
|
||||
// Possible solution to avoid this is: make your bitmap suit the codec
|
||||
// requirements, or Choose a codec that is suitable for your bitmap.
|
||||
SetErrorMessage("Unable to Set Video Stream Format");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK; // Everything went Fine
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendFrameFirstTime
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendFrameFirstTime(HBITMAP hBitmap)
|
||||
{
|
||||
BITMAP Bitmap;
|
||||
GetObject(hBitmap, sizeof(BITMAP), &Bitmap);
|
||||
|
||||
if (SUCCEEDED(InitMovieCreation(Bitmap.bmWidth,
|
||||
Bitmap.bmHeight,
|
||||
Bitmap.bmBitsPixel)))
|
||||
{
|
||||
myAppendFuncSelector = 2; //Point to the UsualAppend Function
|
||||
return AppendFrameUsual(hBitmap);
|
||||
}
|
||||
|
||||
ReleaseMemory();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendFrameUsual
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendFrameUsual(HBITMAP hBitmap)
|
||||
{
|
||||
BITMAPINFO bmpInfo;
|
||||
|
||||
bmpInfo.bmiHeader.biBitCount=0;
|
||||
bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
|
||||
|
||||
GetDIBits(myhAviDC,hBitmap,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);
|
||||
|
||||
bmpInfo.bmiHeader.biCompression=BI_RGB;
|
||||
|
||||
GetDIBits(myhAviDC,
|
||||
hBitmap,
|
||||
0,
|
||||
bmpInfo.bmiHeader.biHeight,
|
||||
mylpBits,
|
||||
&bmpInfo,
|
||||
DIB_RGB_COLORS);
|
||||
|
||||
if (FAILED(AVIStreamWrite(mypAviCompressedStream,
|
||||
mylSample++,
|
||||
1,
|
||||
mylpBits,
|
||||
bmpInfo.bmiHeader.biSizeImage,
|
||||
0,
|
||||
NULL,
|
||||
NULL)))
|
||||
{
|
||||
SetErrorMessage("Unable to Write Video Stream to the output Movie File");
|
||||
ReleaseMemory();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendDummy
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendDummy(HBITMAP)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendNewFrame
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendNewFrame(HBITMAP hBitmap)
|
||||
{
|
||||
return (this->*pAppendFrame[myAppendFuncSelector])((HBITMAP)hBitmap);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendNewFrame
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendNewFrame(int nWidth,
|
||||
int nHeight,
|
||||
LPVOID pBits,
|
||||
int nBitsPerPixel)
|
||||
{
|
||||
return (this->*pAppendFrameBits[myAppendFuncSelector])(nWidth,
|
||||
nHeight,
|
||||
pBits,
|
||||
nBitsPerPixel);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendFrameFirstTime
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendFrameBitsFirstTime(int nWidth,
|
||||
int nHeight,
|
||||
LPVOID pBits,
|
||||
int nBitsPerPixel)
|
||||
{
|
||||
if (SUCCEEDED(InitMovieCreation(nWidth, nHeight, nBitsPerPixel)))
|
||||
{
|
||||
myAppendFuncSelector=2; //Point to the UsualAppend Function
|
||||
return AppendFrameBitsUsual(nWidth, nHeight, pBits, nBitsPerPixel);
|
||||
}
|
||||
ReleaseMemory();
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendFrameUsual
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendFrameBitsUsual(int nWidth,
|
||||
int nHeight,
|
||||
LPVOID pBits,
|
||||
int nBitsPerPixel)
|
||||
{
|
||||
DWORD dwSize=nWidth*nHeight*nBitsPerPixel/8;
|
||||
|
||||
if (FAILED(AVIStreamWrite(mypAviCompressedStream,
|
||||
mylSample++,
|
||||
1,
|
||||
pBits,
|
||||
dwSize,
|
||||
0,
|
||||
NULL,
|
||||
NULL)))
|
||||
{
|
||||
SetErrorMessage("Unable to Write Video Stream to the output Movie File");
|
||||
ReleaseMemory();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AppendDummy
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
HRESULT OpenGl_AVIWriter::AppendDummyBits(int /*nWidth*/,
|
||||
int /*nHeight*/,
|
||||
LPVOID /*pBits*/,
|
||||
int /*nBitsPerPixel*/)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AviWriter
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void OpenGl_AVIWriter_AVIWriter(void * pp,
|
||||
int nWidth,
|
||||
int nHeight,
|
||||
int nBitsPerPixel)
|
||||
{
|
||||
OpenGl_AVIWriter * anInst = OpenGl_AVIWriter::GetInstance();
|
||||
if (anInst != 0L)
|
||||
if (anInst->IsRecording())
|
||||
{
|
||||
anInst->AppendNewFrame(nWidth, nHeight, pp, nBitsPerPixel);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AllowWriting
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean OpenGl_AVIWriter_AllowWriting(void * hWin)
|
||||
{
|
||||
Standard_Boolean aResult(Standard_False);
|
||||
const OpenGl_AVIWriter * anInst = OpenGl_AVIWriter::GetInstance();
|
||||
if (anInst != 0L) {
|
||||
if (hWin == NULL || anInst->HWindow() == hWin)
|
||||
aResult = static_cast<Standard_Boolean> (anInst->IsRecording());
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
#endif
|
191
src/OpenGl/OpenGl_AVIWriter.hxx
Normal file
191
src/OpenGl/OpenGl_AVIWriter.hxx
Normal file
@@ -0,0 +1,191 @@
|
||||
// Created on: 2007-04-15
|
||||
// Created by: Alexey MORENOV & Alexander GRIGORIEV
|
||||
// Copyright (c) 2007-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 __OPENGL_AVIWRITER_H
|
||||
#define __OPENGL_AVIWRITER_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <Standard_Macro.hxx>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(OCCT_UWP)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vfw.h>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
/**
|
||||
* Class providing the API to record AVI files using a codec installed in the
|
||||
* system -- Only on Windows NT/2k/XP/Vista platform under MS Visual Studio.
|
||||
* The following tasks are supported:
|
||||
* <ol>
|
||||
*
|
||||
* <li>Creation of AVI data stream: launched by the constructor.
|
||||
* The constructor accepts the filename, FOURCC video code and the frame rate
|
||||
* setting as parameters.
|
||||
* The default codec name used here is MPG4. To use a different codec, pass
|
||||
* its FOURCC value as the input parameter for dwCodec.
|
||||
* For example,
|
||||
* <ul>
|
||||
* <li>pass mmioFOURCC('D','I','V','X') to use DIVX codec, or</li>
|
||||
* <li>pass mmioFOURCC('I','V','5','0') to use IV50 codec etc...</li>
|
||||
* </ul>
|
||||
* Also, you can pass just 0 to avoid the codecs altogether. In that case,
|
||||
* the frames would be saved as they are without any compression; However,
|
||||
* the output movie file size would be very huge in that case.
|
||||
*
|
||||
* Finally, make sure you have the codec installed on the machine before
|
||||
* passing its Fourcc here.
|
||||
* </li>
|
||||
* <li>
|
||||
* Start the recording: call the method StartRecording(). This method should be
|
||||
* called at least once; execution of the constructor does not begin the
|
||||
* process.
|
||||
* </li>
|
||||
* <li>
|
||||
* Stop the recording: call the method StopRecording(). Can be omitted if the
|
||||
* next to execute would be the destructor.
|
||||
* </li>
|
||||
* <li>
|
||||
* Close the AVI file and exit the process of recording. This is done
|
||||
* automatically by the destructor.
|
||||
* </li>
|
||||
* </ol>
|
||||
*/
|
||||
class OpenGl_AVIWriter
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor. Initializes the internal data structures, prepares for the
|
||||
* creation of an AVI stream when the first frame is ready to be captured.
|
||||
* @param theFileName
|
||||
* Name of the output movie file to create.
|
||||
* @param theCodec
|
||||
* FourCC of the Video Codec to be used for compression
|
||||
* @param theFrameRate
|
||||
* The Frames Per Second (FPS) setting to be used for the movie
|
||||
*/
|
||||
Standard_EXPORT OpenGl_AVIWriter(const wchar_t * theFileName,
|
||||
DWORD theCodec = mmioFOURCC('M','P','G','4'),
|
||||
Standard_Integer theFrameRate = 25);
|
||||
|
||||
/**
|
||||
* Destructor: closes the movie file and flushes all the frames
|
||||
*/
|
||||
Standard_EXPORT ~OpenGl_AVIWriter ();
|
||||
|
||||
/**
|
||||
* Begin the recording.
|
||||
*/
|
||||
Standard_EXPORT void StartRecording(const HANDLE hWin = NULL);
|
||||
|
||||
/**
|
||||
* Stop the recording (can be restarted using StartRecording()).
|
||||
*/
|
||||
Standard_EXPORT void StopRecording ();
|
||||
|
||||
/**
|
||||
* Query the state of recording.
|
||||
*/
|
||||
Standard_Boolean IsRecording () const { return myIsAllowRecord; }
|
||||
|
||||
/**
|
||||
* Returns the last error message, if any.
|
||||
*/
|
||||
const TCollection_AsciiString& GetLastErrorMessage() const
|
||||
{ return myErrMsg; }
|
||||
|
||||
/**
|
||||
* Get the instance of AVI Writer class.
|
||||
*/
|
||||
static Standard_EXPORT OpenGl_AVIWriter * GetInstance ();
|
||||
|
||||
/**
|
||||
* Get the Window handle that contains the actual OpenGl context.
|
||||
*/
|
||||
HANDLE HWindow () const
|
||||
{ return myhWindow; }
|
||||
|
||||
/// Inserts the given HBitmap into the movie as a new Frame at the end.
|
||||
HRESULT AppendNewFrame(HBITMAP hBitmap);
|
||||
|
||||
/// Inserts the given bitmap bits into the movie as a new Frame at the end.
|
||||
/// The width, height and nBitsPerPixel are the width, height and bits per pixel
|
||||
/// of the bitmap pointed to by the input pBits.
|
||||
HRESULT AppendNewFrame(int nWidth,
|
||||
int nHeight,
|
||||
LPVOID pBits,
|
||||
int nBitsPerPixel);
|
||||
|
||||
private:
|
||||
|
||||
void call_avi();
|
||||
|
||||
private:
|
||||
static OpenGl_AVIWriter * MyAVIWriterInstance;
|
||||
Standard_Boolean myIsAllowRecord;
|
||||
|
||||
BYTE * mypBits;
|
||||
UINT myWidth;
|
||||
UINT myHeight;
|
||||
|
||||
HDC myhAviDC;
|
||||
HANDLE myhHeap;
|
||||
HANDLE myhWindow; // window containing the OGL context
|
||||
LPVOID mylpBits; // Useful to hold the bitmap content if any
|
||||
LONG mylSample; // Keeps track of the current Frame Index
|
||||
PAVIFILE mypAviFile;
|
||||
PAVISTREAM mypAviStream;
|
||||
PAVISTREAM mypAviCompressedStream;
|
||||
AVISTREAMINFOW myAviStreamInfo;
|
||||
AVICOMPRESSOPTIONS myAviCompressOptions;
|
||||
wchar_t * myFileName; // Holds the Output Movie File Name
|
||||
TCollection_AsciiString myErrMsg; // Holds the Last Error Message, if any
|
||||
|
||||
int myAppendFuncSelector; //0=Dummy 1=FirstTime 2=Usual
|
||||
|
||||
HRESULT AppendFrameFirstTime(HBITMAP );
|
||||
HRESULT AppendFrameUsual(HBITMAP);
|
||||
HRESULT AppendDummy(HBITMAP);
|
||||
HRESULT (OpenGl_AVIWriter::*pAppendFrame[3])(HBITMAP hBitmap);
|
||||
|
||||
HRESULT AppendFrameBitsFirstTime(int, int, LPVOID,int );
|
||||
HRESULT AppendFrameBitsUsual(int, int, LPVOID,int );
|
||||
HRESULT AppendDummyBits(int, int, LPVOID,int );
|
||||
HRESULT (OpenGl_AVIWriter::*pAppendFrameBits[3])(int, int, LPVOID, int);
|
||||
|
||||
/// Takes care of creating the memory, streams, compression options etc.
|
||||
/// required for the movie
|
||||
HRESULT InitMovieCreation(int nFrameWidth,int nFrameHeight,int nBitsPerPixel);
|
||||
|
||||
/// Takes care of releasing the memory and movie related handles
|
||||
void ReleaseMemory();
|
||||
|
||||
/// Sets the Error Message
|
||||
void SetErrorMessage(const char * theErrMsg);
|
||||
};
|
||||
|
||||
Standard_EXPORT void OpenGl_AVIWriter_AVIWriter(void * pp,
|
||||
int nWidth,
|
||||
int nHeight,
|
||||
int nBitsPerPixel);
|
||||
|
||||
Standard_EXPORT Standard_Boolean OpenGl_AVIWriter_AllowWriting(void * hWin);
|
||||
|
||||
#endif // _MSC_VER
|
||||
#endif
|
@@ -39,6 +39,10 @@
|
||||
#include <OpenGl_Structure.hxx>
|
||||
#include <OpenGl_ArbFBO.hxx>
|
||||
|
||||
#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
|
||||
#include <OpenGl_AVIWriter.hxx>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Format Frame Buffer format for logging messages.
|
||||
@@ -523,6 +527,24 @@ void OpenGl_View::Redraw()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
|
||||
if (OpenGl_AVIWriter_AllowWriting(myWindow->PlatformWindow()->NativeHandle()))
|
||||
{
|
||||
GLint params[4];
|
||||
glGetIntegerv(GL_VIEWPORT, params);
|
||||
int nWidth = params[2] & ~0x7;
|
||||
int nHeight = params[3] & ~0x7;
|
||||
|
||||
const int nBitsPerPixel = 24;
|
||||
GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
|
||||
OpenGl_AVIWriter_AVIWriter(aDumpData, nWidth, nHeight, nBitsPerPixel);
|
||||
delete[] aDumpData;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
|
||||
&& myRenderParams.IsGlobalIlluminationEnabled)
|
||||
{
|
||||
|
546
src/Poly/Poly_IBuffer.cxx
Normal file
546
src/Poly/Poly_IBuffer.cxx
Normal file
@@ -0,0 +1,546 @@
|
||||
// File: Poly_IBuffer.cxx
|
||||
// Created: 15.06.07 08:32
|
||||
// Author: Alexander GRIGORIEV
|
||||
// Copyright: Open CASCADE 2007
|
||||
|
||||
#include <Poly_IBuffer.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <Standard_ProgramError.hxx>
|
||||
|
||||
#pragma warning(disable:4291)
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Poly_IBuffer, Standard_Transient)
|
||||
|
||||
static const Standard_Size INDEXLEN = 10;
|
||||
#ifdef _DEBUG
|
||||
int Poly_IBuffer::GlobalCount = 0;
|
||||
#endif
|
||||
|
||||
//=======================================================================
|
||||
//function : GetZ
|
||||
//purpose : local function
|
||||
//=======================================================================
|
||||
|
||||
inline Standard_Real GetZ (const Poly_IBuffer::Interval& theInt,
|
||||
const Standard_Real theX)
|
||||
{
|
||||
return (theInt.XZ(0).Y() + (theInt.XZ(1).Y() - theInt.XZ(0).Y()) *
|
||||
(theX - theInt.XZ(0).X()) / (theInt.XZ(1).X() - theInt.XZ(0).X()));
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Poly_IBuffer
|
||||
//purpose : Constructor
|
||||
//=======================================================================
|
||||
|
||||
Poly_IBuffer::Poly_IBuffer (const Poly_IBuffer::Interval& theInterval,
|
||||
const Standard_Real theTol,
|
||||
const Handle(NCollection_BaseAllocator)& theAlloc)
|
||||
{
|
||||
Init (theInterval, theTol, theAlloc);
|
||||
#ifdef _DEBUG
|
||||
myCount = GlobalCount++;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Init
|
||||
//purpose : Initialization, to be used after the default constructor.
|
||||
//=======================================================================
|
||||
|
||||
void Poly_IBuffer::Init (const Interval& theInterval,
|
||||
const Standard_Real theTol,
|
||||
const Handle(NCollection_BaseAllocator)& theAlloc)
|
||||
{
|
||||
clearIntervals();
|
||||
myTol = theTol;
|
||||
if (theAlloc.IsNull())
|
||||
myAllocator = new NCollection_IncAllocator(1000);
|
||||
else
|
||||
myAllocator = theAlloc;
|
||||
|
||||
myMinOrd = Precision::Infinite();
|
||||
myMaxOrd = -Precision::Infinite();
|
||||
myNIntervals = 1;
|
||||
|
||||
// Create the first interval covering all possible X coordinates
|
||||
Interval * pInt = &theInterval.Clone(myAllocator);
|
||||
// Create the index array
|
||||
myIndex = static_cast <PInterval *>
|
||||
(myAllocator->Allocate((INDEXLEN+1) * sizeof(PInterval)));
|
||||
const Standard_Real anXmin = theInterval.XZ(0).X();
|
||||
const Standard_Real aXstep = (theInterval.XZ(1).X() - anXmin) / INDEXLEN;
|
||||
for (Standard_Size i = 0; i <= INDEXLEN; i++) {
|
||||
myIndex[i].X = Standard_Real (anXmin + i*aXstep);
|
||||
myIndex[i].Int = pInt;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ~Poly_IBuffer
|
||||
//purpose : Destructor
|
||||
//=======================================================================
|
||||
|
||||
Poly_IBuffer::~Poly_IBuffer ()
|
||||
{
|
||||
clearIntervals();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Clone
|
||||
//purpose : Create a copy of the given Interval in the given allocator.
|
||||
//=======================================================================
|
||||
|
||||
Poly_IBuffer::Interval& Poly_IBuffer::Interval::Clone
|
||||
(const Handle(NCollection_BaseAllocator)& theAlloc,
|
||||
Poly_IBuffer::Interval * theDest) const
|
||||
{
|
||||
if (theDest == 0L)
|
||||
theDest = new (theAlloc) Interval(myXZ[0], myXZ[1], 0UL);
|
||||
else {
|
||||
theDest->myXZ[0] = myXZ[0];
|
||||
theDest->myXZ[1] = myXZ[1];
|
||||
theDest->myNext = 0L;
|
||||
theDest->myModID = 0UL;
|
||||
theDest->U.myModX = RealLast();
|
||||
}
|
||||
return * theDest;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : NewRejectID
|
||||
//purpose : Generator of unique Reject ID values.
|
||||
//=======================================================================
|
||||
|
||||
unsigned long Poly_IBuffer::Interval::NewRejectID ()
|
||||
{
|
||||
static unsigned long aValue(0UL);
|
||||
aValue += 4;
|
||||
return aValue;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : IsIntersect
|
||||
//purpose : Check for intersection, returns the intersection point abscissa.
|
||||
// @return
|
||||
// True if a modification or removal is required. The decision is based
|
||||
// on 2 lower bits of myRejectID value:
|
||||
// - 0 : remove this interval;
|
||||
// - 1 : keep the lower abscisse part, remove the upper part;
|
||||
// - 2 : keep the upper abscisse part, remove the lower part;
|
||||
// - 3 : remove the middle.
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Poly_IBuffer::Interval::IsIntersect
|
||||
(const Poly_IBuffer::Interval& theInt,
|
||||
const Standard_Real theTol,
|
||||
const unsigned long theRejectID)
|
||||
{
|
||||
Standard_Boolean aRes(Standard_False);
|
||||
Standard_Integer aResult (-1);
|
||||
Standard_Real anAbscisse (Precision::Infinite());
|
||||
const Standard_Real anXtol[2] = {
|
||||
myXZ[0].X() + theTol,
|
||||
myXZ[1].X() - theTol
|
||||
};
|
||||
if (theInt.myXZ[0].X() < anXtol[1] && theInt.myXZ[1].X() > anXtol[0]) {
|
||||
const gp_XY aVec[3] = {
|
||||
gp_XY(theInt.myXZ[0] - myXZ[0]),
|
||||
gp_XY(myXZ[1] - myXZ[0]),
|
||||
gp_XY(theInt.myXZ[1] - theInt.myXZ[0])
|
||||
};
|
||||
const Standard_Real aDirProd = aVec[1] ^ aVec[2];
|
||||
if (aDirProd > Precision::Intersection()) {
|
||||
// Intersection coefficients
|
||||
const Standard_Real fInter[2] = {
|
||||
(aVec[0] ^ aVec[2]) / aDirProd,
|
||||
(aVec[0] ^ aVec[1]) / aDirProd
|
||||
};
|
||||
anAbscisse = (myXZ[1].X() * fInter[0] + myXZ[0].X() * (1.-fInter[0]));
|
||||
if (anAbscisse > anXtol[0] && fInter[1] > 0.)
|
||||
if (anAbscisse < anXtol[1] && fInter[1] < 1.) {
|
||||
if (theInt.myXZ[0].X() < anXtol[0])
|
||||
aResult = 2; // keep upper abscissa
|
||||
else {
|
||||
anAbscisse = theInt.myXZ[0].X();
|
||||
aResult = 3;
|
||||
}
|
||||
} else {
|
||||
if (theInt.myXZ[0].X() > anXtol[0]) {
|
||||
anAbscisse = theInt.myXZ[0].X();
|
||||
if (theInt.myXZ[1].X() > anXtol[1])
|
||||
aResult = 1; // keep lower abscissa
|
||||
else
|
||||
aResult = 3;
|
||||
} else
|
||||
if (theInt.myXZ[1].X() > anXtol[1])
|
||||
aResult = 0; // remove
|
||||
else {
|
||||
anAbscisse = theInt.myXZ[1].X();
|
||||
aResult = 2; // keep upper abscissa
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Standard_Real fInter[2] = { 2., -1. };
|
||||
if (aDirProd < -Precision::Intersection()) {
|
||||
// Intersection coefficients
|
||||
fInter[0] = (aVec[0] ^ aVec[2]) / aDirProd;
|
||||
fInter[1] = (aVec[0] ^ aVec[1]) / aDirProd;
|
||||
anAbscisse = (myXZ[1].X() * fInter[0] + myXZ[0].X() * (1.-fInter[0]));
|
||||
} else if (GetZ (theInt, myXZ[0].X()) < myXZ[0].Y())
|
||||
anAbscisse = theInt.myXZ[0].X();
|
||||
|
||||
if (anAbscisse < anXtol[1] &&
|
||||
fInter[1] < 1.-Precision::Intersection())
|
||||
if (anAbscisse > anXtol[0] &&
|
||||
fInter[1] > Precision::Intersection())
|
||||
{
|
||||
if (theInt.myXZ[1].X() > anXtol[1])
|
||||
aResult = 1; // keep lower abscissa
|
||||
else
|
||||
aResult = 3;
|
||||
} else {
|
||||
if (theInt.myXZ[0].X() > anXtol[0]) {
|
||||
anAbscisse = theInt.myXZ[0].X();
|
||||
if (theInt.myXZ[1].X() > anXtol[1])
|
||||
aResult = 1; // keep lower abscissa
|
||||
else
|
||||
aResult = 3;
|
||||
} else
|
||||
if (theInt.myXZ[1].X() > anXtol[1]) {
|
||||
aResult = 0; // remove
|
||||
aRes = Standard_True;
|
||||
} else {
|
||||
anAbscisse = theInt.myXZ[1].X();
|
||||
aResult = 2; //keep upper abscissa
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aResult >= 0) {
|
||||
myModID = theRejectID + aResult;
|
||||
U.myModX = anAbscisse;
|
||||
aRes = Standard_True;
|
||||
}
|
||||
return aRes;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Trim
|
||||
//purpose : Shorten the interval to the new value of Xmax.
|
||||
//=======================================================================
|
||||
|
||||
void Poly_IBuffer::Interval::Trim (const Standard_Real theX,
|
||||
const Standard_Integer theMode)
|
||||
{
|
||||
const Standard_Real aZ = GetZ(* this, theX);
|
||||
switch (theMode) {
|
||||
case 3:
|
||||
myModID = 0UL;
|
||||
case 1:
|
||||
Standard_ProgramError_Raise_if
|
||||
(theX - myXZ[0].X() < Precision::Confusion() || theX > myXZ[1].X(),
|
||||
"Trim error");
|
||||
myXZ[1].SetCoord(theX, aZ);
|
||||
break;
|
||||
case 2:
|
||||
Standard_ProgramError_Raise_if
|
||||
(theX < myXZ[0].X() || myXZ[1].X() - theX < Precision::Confusion(),
|
||||
"Trim error");
|
||||
myXZ[0].SetCoord(theX, aZ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : AddInterval
|
||||
//purpose : Add one interval to buffer.
|
||||
//=======================================================================
|
||||
|
||||
Poly_IBuffer::Interval * Poly_IBuffer::AddInterval
|
||||
(const Poly_IBuffer::Interval& theInterval,
|
||||
Poly_IBuffer::Interval * theStart)
|
||||
{
|
||||
// Variables:
|
||||
// aLastModified: Newly created interval in the buffer. It is returned by
|
||||
// this method so that it can be passed as theStart
|
||||
// for the next call (next interval).
|
||||
// aInt: Currently checked/processed interval
|
||||
// aBracket[0,1]: The first and the last in the chain of intervals where
|
||||
// the modification can be done, used for local optimisation.
|
||||
// pLastInt: The last non-modified interval. This pointer is used to set
|
||||
// pLastInt->Next() to the newly created interval.
|
||||
// isWaiting: True if there have been removed intervals, to be replaced by
|
||||
// a new interval.
|
||||
// aFirst.Int: Same as pLastInt. probably we can get rid of pLastInt
|
||||
// aFirst.X: Beginning of the new interval
|
||||
|
||||
Interval * aLastModified = 0L, * aStart;
|
||||
if (theStart == 0L)
|
||||
aStart = const_cast <Interval *>(myIndex[0].Int);
|
||||
else
|
||||
aStart = theStart;
|
||||
Interval * anInt = aStart;
|
||||
Interval * aBracket[2] = { 0L, 0L };
|
||||
unsigned long aRejectID = Interval::NewRejectID();
|
||||
Interval * pLastInt = theStart;
|
||||
|
||||
// Identify the intervals that should be modified
|
||||
for (; anInt; anInt = anInt->Next()) {
|
||||
if (anInt->XZ(0).X() > theInterval.XZ(1).X() - myTol)
|
||||
break;
|
||||
if (anInt->IsIntersect (theInterval, myTol, aRejectID)) {
|
||||
if (aBracket[0] == 0L)
|
||||
aBracket[0] = anInt;
|
||||
aBracket[1] = anInt->Next();
|
||||
const long aModMode = anInt->GetModificationID() - aRejectID;
|
||||
if (aModMode == 3L) {
|
||||
Interval& aNewInt = anInt->Clone(myAllocator);
|
||||
anInt->Trim (anInt->GetModificationAbscisse(), aModMode);
|
||||
aNewInt.myXZ[0] = anInt->XZ(1);
|
||||
aNewInt.myNext = anInt->Next();
|
||||
anInt->myNext = &aNewInt;
|
||||
myNIntervals++;
|
||||
}
|
||||
} else if (aBracket[0] == 0L)
|
||||
pLastInt = anInt;
|
||||
}
|
||||
|
||||
// Modify the intervals
|
||||
Standard_Boolean isWaiting (Standard_False);
|
||||
PInterval aFirst;
|
||||
aFirst.Int = theStart;
|
||||
aFirst.X = aStart->XZ(0).X();
|
||||
for (anInt = aBracket[0]; anInt; anInt = anInt->Next()) {
|
||||
const unsigned long aCurrentID = anInt->GetModificationID();
|
||||
if ((aCurrentID & ~0x3) != aRejectID) {
|
||||
if (isWaiting) {
|
||||
const Standard_Real anX[2] = {
|
||||
aFirst.X,
|
||||
anInt->XZ(0).X()
|
||||
};
|
||||
aLastModified = addInt (theInterval, anX, aFirst.Int);
|
||||
if (aStart == 0L)
|
||||
aStart = aLastModified;
|
||||
aLastModified->myNext = anInt;
|
||||
aFirst.Int = anInt;
|
||||
isWaiting = Standard_False;
|
||||
}
|
||||
if (anInt == aBracket[1])
|
||||
break;
|
||||
pLastInt = anInt;
|
||||
} else {
|
||||
const long aModMode = aCurrentID - aRejectID;
|
||||
switch (aModMode) {
|
||||
case 0:
|
||||
if (aStart == anInt)
|
||||
aStart = 0L;
|
||||
if (isWaiting == Standard_False) {
|
||||
aFirst.Int = pLastInt;
|
||||
aFirst.X = anInt->XZ(0).X();
|
||||
isWaiting = Standard_True;
|
||||
}
|
||||
myNHoles++;
|
||||
break;
|
||||
case 1:
|
||||
aFirst.X = anInt->GetModificationAbscisse();
|
||||
aFirst.Int = anInt;
|
||||
anInt->Trim (aFirst.X, 1);
|
||||
pLastInt = anInt;
|
||||
isWaiting = Standard_True;
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
if (isWaiting)
|
||||
isWaiting = Standard_False;
|
||||
else {
|
||||
aFirst.Int = pLastInt;
|
||||
aFirst.X = anInt->XZ(0).X();
|
||||
}
|
||||
anInt->Trim (anInt->GetModificationAbscisse(), 2);
|
||||
const Standard_Real anX[2] = {
|
||||
aFirst.X,
|
||||
anInt->GetModificationAbscisse()
|
||||
};
|
||||
aLastModified = addInt (theInterval, anX, aFirst.Int);
|
||||
if (aStart == 0L)
|
||||
aStart = aLastModified;
|
||||
aLastModified->myNext = anInt;
|
||||
aFirst.Int = anInt;
|
||||
pLastInt = anInt;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Standard_ProgramError::Raise ("Poly_IBuffer::AddInterval");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isWaiting) {
|
||||
const Standard_Real anX[2] = {
|
||||
aFirst.X,
|
||||
myIndex[INDEXLEN].X
|
||||
};
|
||||
aLastModified = addInt (theInterval, anX, aFirst.Int);
|
||||
}
|
||||
return aLastModified;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : CloseBuffer
|
||||
//purpose : Called after all additions of intervals
|
||||
//=======================================================================
|
||||
|
||||
void Poly_IBuffer::CloseBuffer (const Standard_Boolean isFiltering)
|
||||
{
|
||||
const Standard_Real aConf2 =
|
||||
0.01 * Precision::Confusion() * Precision::Confusion();
|
||||
const Standard_Real aTol2 = myTol * myTol;
|
||||
Interval * pPrev = 0L, * pInt = const_cast<Interval *>(myIndex[0].Int);
|
||||
if (pInt) {
|
||||
pInt->U.myPrev = 0L;
|
||||
pInt->myModID = 0UL;
|
||||
pPrev = pInt;
|
||||
pInt = pInt->Next();
|
||||
}
|
||||
while (pInt) {
|
||||
if (isFiltering &&
|
||||
(pPrev->myXZ[1] - pInt->myXZ[0]).SquareModulus() < aConf2)
|
||||
{
|
||||
const gp_XY aV0 = pInt->myXZ[1] - pPrev->myXZ[0];
|
||||
const Standard_Real aL0 = aV0.SquareModulus();
|
||||
if (aL0 > aConf2) {
|
||||
const Standard_Real aVProd = aV0 ^ (pPrev->myXZ[1] - pPrev->myXZ[0]);
|
||||
if (aVProd * aVProd / aL0 < aTol2) {
|
||||
// extend pPrev to take place of pInt
|
||||
pPrev->myXZ[1] = pInt->myXZ[1];
|
||||
pPrev->myNext = pInt->Next();
|
||||
pInt = pInt->Next();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
pInt->U.myPrev = pPrev;
|
||||
pInt->myModID = 0UL;
|
||||
pPrev = pInt;
|
||||
pInt = pInt->Next();
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : addInt
|
||||
//purpose : Internal method, called from AddInterval()
|
||||
//=======================================================================
|
||||
|
||||
Poly_IBuffer::Interval * Poly_IBuffer::addInt
|
||||
(const Poly_IBuffer::Interval& theInterval,
|
||||
const Standard_Real theX[2],
|
||||
const Poly_IBuffer::Interval * thePrevious)
|
||||
{
|
||||
const gp_XY aXZ[2] = {
|
||||
gp_XY(theX[0], GetZ (theInterval, theX[0])),
|
||||
gp_XY(theX[1], GetZ (theInterval, theX[1]))
|
||||
};
|
||||
Interval& aNewInt = theInterval.Clone(myAllocator);
|
||||
aNewInt.myXZ[0] = aXZ[0];
|
||||
aNewInt.myXZ[1] = aXZ[1];
|
||||
myNIntervals++;
|
||||
if (thePrevious)
|
||||
const_cast<Interval *>(thePrevious)->myNext = &aNewInt;
|
||||
else {
|
||||
myIndex[0].Int = &aNewInt;
|
||||
if (myMinOrd > aXZ[0].Y())
|
||||
myMinOrd = aXZ[0].Y();
|
||||
if (myMaxOrd < aXZ[0].Y())
|
||||
myMaxOrd = aXZ[0].Y();
|
||||
}
|
||||
if (myMinOrd > aXZ[1].Y())
|
||||
myMinOrd = aXZ[1].Y();
|
||||
if (myMaxOrd < aXZ[1].Y())
|
||||
myMaxOrd = aXZ[1].Y();
|
||||
return &aNewInt;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : clearIntervals
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Poly_IBuffer::clearIntervals ()
|
||||
{
|
||||
if (myAllocator.IsNull() == Standard_False)
|
||||
{
|
||||
Interval * anInt = const_cast <Interval *>(myIndex[0].Int);
|
||||
while (anInt) {
|
||||
Interval * anInt0 = anInt;
|
||||
anInt = anInt->Next();
|
||||
anInt0->Interval::~Interval();
|
||||
myAllocator->Free(anInt0);
|
||||
}
|
||||
myAllocator->Free (myIndex);
|
||||
}
|
||||
myIndex = 0L;
|
||||
myNIntervals = 0;
|
||||
myNHoles = 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Dump
|
||||
//purpose : Debug facility.
|
||||
//=======================================================================
|
||||
|
||||
void Poly_IBuffer::Dump (Standard_OStream& theStream)
|
||||
{
|
||||
const Interval * anInt = First();
|
||||
int aCount(0);
|
||||
for (; anInt; anInt = anInt->Next()) {
|
||||
char buf[256];
|
||||
// if (anInt->XZ(0).Y() > Precision::Infinite() * 0.1 &&
|
||||
// anInt->XZ(1).Y() > Precision::Infinite() * 0.1)
|
||||
// continue;
|
||||
sprintf (buf, "%03d (%9.5f %9.5f) - (%9.5f %9.5f)", ++aCount,
|
||||
anInt->XZ(0).X(), anInt->XZ(0).Y(),
|
||||
anInt->XZ(1).X(), anInt->XZ(1).Y());
|
||||
theStream << buf << endl;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : DebugPolyline
|
||||
//purpose : Debug facility.
|
||||
//=======================================================================
|
||||
|
||||
void Poly_IBuffer::DebugPolyline (Standard_OStream& theStream,
|
||||
const Standard_Real theY)
|
||||
{
|
||||
static int aTestCount (0);
|
||||
const Interval * anInt = First();
|
||||
Standard_Real aLastVal[2] = { Precision::Infinite(), Precision::Infinite() };
|
||||
Standard_Boolean isStarted (Standard_True);
|
||||
std::streamsize oldPrec = theStream.precision(8);
|
||||
for (; anInt; anInt = anInt->Next()) {
|
||||
if (anInt->XZ(0).Y() > Precision::Infinite() * 0.1 &&
|
||||
anInt->XZ(1).Y() > Precision::Infinite() * 0.1)
|
||||
{
|
||||
if (isStarted == Standard_False) {
|
||||
theStream << endl;
|
||||
isStarted = Standard_True;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (isStarted) {
|
||||
theStream << "polyline ibuf" << aTestCount++;
|
||||
isStarted = Standard_False;
|
||||
}
|
||||
if (fabs(anInt->XZ(0).X() - aLastVal[0]) > Precision::Confusion() ||
|
||||
fabs(anInt->XZ(0).Y() - aLastVal[1]) > Precision::Confusion())
|
||||
theStream << " " << anInt->XZ(0).X() << ' '
|
||||
<< theY << ' ' << anInt->XZ(0).Y() << ' ';
|
||||
theStream << " " << anInt->XZ(1).X() << ' '
|
||||
<< theY << ' ' << anInt->XZ(1).Y() << ' ';
|
||||
aLastVal[0] = anInt->XZ(1).X();
|
||||
aLastVal[1] = anInt->XZ(1).Y();
|
||||
}
|
||||
theStream.precision(oldPrec);
|
||||
theStream << endl;
|
||||
}
|
253
src/Poly/Poly_IBuffer.hxx
Normal file
253
src/Poly/Poly_IBuffer.hxx
Normal file
@@ -0,0 +1,253 @@
|
||||
// File: Poly_IBuffer.hxx
|
||||
// Created: 15.06.07 08:08
|
||||
// Author: Alexander GRIGORIEV
|
||||
// Copyright: Open CASCADE 2007
|
||||
|
||||
|
||||
#ifndef Poly_IBuffer_HeaderFile
|
||||
#define Poly_IBuffer_HeaderFile
|
||||
|
||||
#include <NCollection_List.hxx>
|
||||
#include <gp_XY.hxx>
|
||||
#include <Standard_DefineHandle.hxx>
|
||||
|
||||
DEFINE_STANDARD_HANDLE (Poly_IBuffer, Standard_Transient)
|
||||
|
||||
typedef NCollection_List<Handle(Poly_IBuffer)> Poly_ListOfIBuffer;
|
||||
|
||||
//! Interval buffer to build outline curve on a set of polygons.
|
||||
class Poly_IBuffer: public Standard_Transient
|
||||
{
|
||||
public:
|
||||
class Interval
|
||||
{
|
||||
public:
|
||||
// ---------- PUBLIC METHODS ----------
|
||||
Interval (const gp_XY& theXZfirst,
|
||||
const gp_XY& theXZlast,
|
||||
const unsigned long theModID = 0UL);
|
||||
|
||||
/**
|
||||
* Allocator-based operator new for dynamic allocations
|
||||
*/
|
||||
DEFINE_NCOLLECTION_ALLOC
|
||||
|
||||
/**
|
||||
* Create a copy of the given Interval in the given allocator.
|
||||
* If theDest==NULL then a new instance is created.
|
||||
*/
|
||||
Standard_EXPORT virtual Interval&
|
||||
Clone (const Handle(NCollection_BaseAllocator)&,
|
||||
Interval * theDest = NULL) const;
|
||||
|
||||
/**
|
||||
* Query the abscisse of the interval.
|
||||
*/
|
||||
const gp_XY& XZ (const Standard_Integer ind) const;
|
||||
|
||||
/**
|
||||
* Query the interval for modification.
|
||||
*/
|
||||
gp_XY& XZ (const Standard_Integer ind);
|
||||
|
||||
/**
|
||||
* Shorten the interval to the new value of Xmax.
|
||||
*/
|
||||
Standard_EXPORT void Trim (const Standard_Real theX,
|
||||
const Standard_Integer theMode);
|
||||
/**
|
||||
* Query the previous interval in the buffer.
|
||||
*/
|
||||
Interval * Previous () const;
|
||||
|
||||
/**
|
||||
* Query the next interval in the buffer.
|
||||
*/
|
||||
Interval * Next () const;
|
||||
|
||||
/**
|
||||
* Query the RejectID indicating the modification status of the interval
|
||||
*/
|
||||
unsigned long GetModificationID () const;
|
||||
|
||||
/**
|
||||
* Query the abscisse value required for modification.
|
||||
*/
|
||||
Standard_Real GetModificationAbscisse() const;
|
||||
|
||||
/**
|
||||
* Set the modification ID.
|
||||
*/
|
||||
void SetModificationID (const unsigned long theValue);
|
||||
|
||||
/**
|
||||
* Check for intersection, returns the intersection point abscissa.
|
||||
* @return
|
||||
* True if a modification or removal is required. The decision is based
|
||||
* on 2 lower bits of myRejectID value:
|
||||
* - 0 : remove this interval;
|
||||
* - 1 : keep the lower abscisse part, remove the upper part;
|
||||
* - 2 : keep the upper abscisse part, remove the lower part;
|
||||
* - 3 : remove the middle.
|
||||
* @param theInt
|
||||
* The other interval that may intersect this one.
|
||||
* @param theTol
|
||||
* Tolerance of intersection: smaller intersections are neglected.
|
||||
* @param theRejectID
|
||||
* Base ID that is stored in the interval with the corresponding
|
||||
* modification status.
|
||||
*/
|
||||
Standard_EXPORT Standard_Boolean
|
||||
IsIntersect (const Interval& theInt,
|
||||
const Standard_Real theTol,
|
||||
const unsigned long theRejectID);
|
||||
/**
|
||||
* Generator of unique Reject ID values.
|
||||
*/
|
||||
static Standard_EXPORT unsigned long
|
||||
NewRejectID ();
|
||||
|
||||
private:
|
||||
// ---------- PRIVATE FIELDS ----------
|
||||
Interval * myNext;
|
||||
gp_XY myXZ[2];
|
||||
union {
|
||||
Standard_Real myModX;
|
||||
Interval * myPrev;
|
||||
} U;
|
||||
unsigned long myModID;
|
||||
friend class Poly_IBuffer;
|
||||
};
|
||||
|
||||
public:
|
||||
// ---------- PUBLIC METHODS ----------
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
Poly_IBuffer ();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Standard_EXPORT Poly_IBuffer
|
||||
(const Interval& theInterval,
|
||||
const Standard_Real theTol,
|
||||
const Handle(NCollection_BaseAllocator)& theAlloc = 0L);
|
||||
|
||||
/**
|
||||
* Get the next IBuffer in the list.
|
||||
*/
|
||||
//inline const Poly_IBuffer& YNext() const
|
||||
//{ return * myNext; }
|
||||
inline const Poly_IBuffer *& YNext()
|
||||
{ return myNext; }
|
||||
|
||||
/**
|
||||
* Get the previous IBuffer in the list.
|
||||
*/
|
||||
//inline const Poly_IBuffer& YPrevious() const
|
||||
//{ return * myPrevious; }
|
||||
inline const Poly_IBuffer *& YPrevious()
|
||||
{ return myPrevious; }
|
||||
|
||||
inline const Standard_Real MyY() const
|
||||
{ return myY; }
|
||||
|
||||
/**
|
||||
* Set myY value.
|
||||
*/
|
||||
inline void SetY (const Standard_Real theY)
|
||||
{ myY = theY; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
inline int MyCount()
|
||||
{ return myCount; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialization, to be used after the default constructor.
|
||||
*/
|
||||
Standard_EXPORT void Init
|
||||
(const Interval& theInterval,
|
||||
const Standard_Real theTol,
|
||||
const Handle(NCollection_BaseAllocator)& theAlloc = 0L);
|
||||
|
||||
Standard_EXPORT ~Poly_IBuffer ();
|
||||
|
||||
Standard_EXPORT Interval *
|
||||
AddInterval (const Interval& theInterval,
|
||||
Interval * theStart = 0L);
|
||||
|
||||
/**
|
||||
* Called when all intervals are added, just before extraction of data.
|
||||
* This method sets the values 'myPrev' in all Intervals. Can be omittred
|
||||
* if the method Previous() is not to be called afterwards.
|
||||
* @param isFiltering
|
||||
* If True then the method would merge the intervals that form a straight
|
||||
* line. It can lead to loss of data attached to intervals, use this only
|
||||
* when you are only interested in geometry of intervals.
|
||||
*/
|
||||
Standard_EXPORT void CloseBuffer (const Standard_Boolean isFiltering
|
||||
= Standard_False);
|
||||
|
||||
const Interval * First () const;
|
||||
|
||||
void GetOrdinateExtents (Standard_Real& theMin,
|
||||
Standard_Real& theMax) const;
|
||||
/**
|
||||
* Debug facility.
|
||||
*/
|
||||
Standard_EXPORT void Dump (Standard_OStream& theStream);
|
||||
|
||||
/**
|
||||
* Debug facility.
|
||||
*/
|
||||
Standard_EXPORT void DebugPolyline (Standard_OStream& theStream,
|
||||
const Standard_Real theY = 1.);
|
||||
|
||||
protected:
|
||||
// ---------- PROTECTED METHODS ----------
|
||||
|
||||
typedef struct {
|
||||
Standard_Real X;
|
||||
const Interval * Int;
|
||||
} PInterval;
|
||||
|
||||
Interval * addInt (const Interval& theInterval,
|
||||
const Standard_Real theX[2],
|
||||
const Interval * thePrevious);
|
||||
void clearIntervals();
|
||||
|
||||
private:
|
||||
Poly_IBuffer (const Poly_IBuffer& theOther);
|
||||
Poly_IBuffer& operator = (const Poly_IBuffer& theOther);
|
||||
|
||||
private:
|
||||
// ---------- PRIVATE FIELDS ----------
|
||||
|
||||
Handle(NCollection_BaseAllocator) myAllocator;
|
||||
Standard_Real myTol;
|
||||
Standard_Real myMinOrd;
|
||||
Standard_Real myMaxOrd;
|
||||
Standard_Size myNIntervals;
|
||||
Standard_Size myNHoles;
|
||||
PInterval * myIndex;
|
||||
//Next IBuffer in the list
|
||||
const Poly_IBuffer* myNext;
|
||||
//Previous IBuffer in the list
|
||||
const Poly_IBuffer* myPrevious;
|
||||
Standard_Real myY;
|
||||
#ifdef _DEBUG
|
||||
int myCount;
|
||||
static int GlobalCount;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Declaration of CASCADE RTTI
|
||||
DEFINE_STANDARD_RTTIEXT (Poly_IBuffer, Standard_Transient)
|
||||
};
|
||||
|
||||
#include <Poly_IBuffer.lxx>
|
||||
|
||||
#endif
|
87
src/Poly/Poly_IBuffer.lxx
Normal file
87
src/Poly/Poly_IBuffer.lxx
Normal file
@@ -0,0 +1,87 @@
|
||||
// File: Poly_IBuffer.lxx
|
||||
// Created: 15.06.07 07:56
|
||||
// Author: Alexander GRIGORIEV
|
||||
// Copyright: Open CASCADE 2007
|
||||
|
||||
//! Constructor.
|
||||
inline Poly_IBuffer::Interval::Interval (const gp_XY& theXZfirst,
|
||||
const gp_XY& theXZlast,
|
||||
const unsigned long theModID)
|
||||
: myNext (0L),
|
||||
myModID (theModID)
|
||||
{
|
||||
U.myModX = RealLast();
|
||||
myXZ[0] = theXZfirst;
|
||||
myXZ[1] = theXZlast;
|
||||
}
|
||||
|
||||
//! Query the beginning (ind==0) or end (ind == 1) of the interval.
|
||||
inline const gp_XY& Poly_IBuffer::Interval::XZ (const Standard_Integer i) const
|
||||
{
|
||||
return myXZ[i&0x1];
|
||||
}
|
||||
|
||||
//! Query the beginning (ind==0) or end (ind == 1) of the interval for modif
|
||||
inline gp_XY& Poly_IBuffer::Interval::XZ (const Standard_Integer i)
|
||||
{
|
||||
return myXZ[i&0x1];
|
||||
}
|
||||
|
||||
//! Query the next interval in the buffer.
|
||||
inline Poly_IBuffer::Interval * Poly_IBuffer::Interval::Next () const
|
||||
{
|
||||
return myNext;
|
||||
}
|
||||
|
||||
//! Query the previous interval in the buffer.
|
||||
inline Poly_IBuffer::Interval * Poly_IBuffer::Interval::Previous () const
|
||||
{
|
||||
return U.myPrev;
|
||||
}
|
||||
|
||||
//! Set the modification ID.
|
||||
inline void Poly_IBuffer::Interval::SetModificationID
|
||||
(const unsigned long theValue)
|
||||
{
|
||||
myModID = theValue;
|
||||
}
|
||||
|
||||
//! Query the RejectID field indicating the modification status of the interval
|
||||
inline unsigned long Poly_IBuffer::Interval::GetModificationID () const
|
||||
{
|
||||
return myModID;
|
||||
}
|
||||
|
||||
//! Query the abscisse value required for modification.
|
||||
inline Standard_Real Poly_IBuffer::Interval::GetModificationAbscisse() const
|
||||
{
|
||||
return U.myModX;
|
||||
}
|
||||
|
||||
//! Returns the head of the list of intervals.
|
||||
/** Other intervals can be obtained by iterative calling Next() of each
|
||||
* returned interval.
|
||||
*/
|
||||
inline const Poly_IBuffer::Interval * Poly_IBuffer::First () const
|
||||
{
|
||||
return myIndex ? myIndex[0].Int : 0L;
|
||||
}
|
||||
|
||||
//! Default constructor
|
||||
inline Poly_IBuffer::Poly_IBuffer()
|
||||
: myTol (0.),
|
||||
myMinOrd (0.),
|
||||
myMaxOrd (0.),
|
||||
myNIntervals(0),
|
||||
myNHoles (0),
|
||||
myIndex (0L)
|
||||
{}
|
||||
|
||||
//! Get extents of the buffer along the ordinate, excepting the
|
||||
//! artificial intervals at infinite ordinate
|
||||
inline void Poly_IBuffer::GetOrdinateExtents (Standard_Real& theMin,
|
||||
Standard_Real& theMax) const
|
||||
{
|
||||
theMin = myMinOrd;
|
||||
theMax = myMaxOrd;
|
||||
}
|
@@ -370,11 +370,6 @@ void SelectMgr_SelectionManager::Activate (const Handle(SelectMgr_SelectableObje
|
||||
|
||||
if (myGlobal.Contains (theObject))
|
||||
{
|
||||
const Standard_Integer aGlobalSelMode = theObject->GlobalSelectionMode();
|
||||
if (theMode != aGlobalSelMode && theSelector->IsActive (theObject, aGlobalSelMode))
|
||||
{
|
||||
theSelector->Deactivate (theObject->Selection (aGlobalSelMode));
|
||||
}
|
||||
theSelector->Activate (theObject->Selection (theMode));
|
||||
}
|
||||
else
|
||||
|
@@ -11,6 +11,8 @@ Standard_Byte.hxx
|
||||
Standard_Character.hxx
|
||||
Standard_CLocaleSentry.cxx
|
||||
Standard_CLocaleSentry.hxx
|
||||
Standard_Condition.cxx
|
||||
Standard_Condition.hxx
|
||||
Standard_ConstructionError.hxx
|
||||
Standard_Copy.tcl
|
||||
Standard_CString.cxx
|
||||
@@ -79,9 +81,9 @@ Standard_Real.hxx
|
||||
Standard_ShortReal.cxx
|
||||
Standard_ShortReal.hxx
|
||||
Standard_Size.hxx
|
||||
Standard_SStream.cxx
|
||||
Standard_SStream.hxx
|
||||
Standard_Stream.hxx
|
||||
Standard_Strtod.cxx
|
||||
Standard_ThreadId.hxx
|
||||
Standard_Time.hxx
|
||||
Standard_TooManyUsers.hxx
|
||||
@@ -92,7 +94,8 @@ Standard_Type.hxx
|
||||
Standard_TypeDef.hxx
|
||||
Standard_TypeMismatch.hxx
|
||||
Standard_Underflow.hxx
|
||||
Standard_UUID.cxx
|
||||
Standard_UUID.hxx
|
||||
Standard_values.h
|
||||
Standard_Version.hxx
|
||||
Standard_WarningsDisable.hxx
|
||||
Standard_WarningsRestore.hxx
|
@@ -35,6 +35,14 @@ inline int Standard_Atomic_Increment (volatile int* theValue);
|
||||
//! and returns resulting decremented value.
|
||||
inline int Standard_Atomic_Decrement (volatile int* theValue);
|
||||
|
||||
//! Perform an atomic compare and swap.
|
||||
//! That is, if the current value of *theValue is theOldValue, then write theNewValue into *theValue.
|
||||
//! @param theValue pointer to variable to modify
|
||||
//! @param theOldValue expected value to perform modification
|
||||
//! @param theNewValue new value to set in case if *theValue was equal to theOldValue
|
||||
//! @return TRUE if theNewValue has been set to *theValue
|
||||
inline bool Standard_Atomic_CompareAndSwap (volatile int* theValue, int theOldValue, int theNewValue);
|
||||
|
||||
// Platform-dependent implementation
|
||||
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
// gcc explicitly defines the macros __GCC_HAVE_SYNC_COMPARE_AND_SWAP_*
|
||||
@@ -55,16 +63,23 @@ int Standard_Atomic_Decrement (volatile int* theValue)
|
||||
return __sync_sub_and_fetch (theValue, 1);
|
||||
}
|
||||
|
||||
bool Standard_Atomic_CompareAndSwap (volatile int* theValue, int theOldValue, int theNewValue)
|
||||
{
|
||||
return __sync_val_compare_and_swap (theValue, theOldValue, theNewValue) == theOldValue;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
extern "C" {
|
||||
long _InterlockedIncrement (volatile long* lpAddend);
|
||||
long _InterlockedDecrement (volatile long* lpAddend);
|
||||
long _InterlockedCompareExchange (long volatile* Destination, long Exchange, long Comparand);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) && ! defined(__INTEL_COMPILER)
|
||||
// force intrinsic instead of WinAPI calls
|
||||
#pragma intrinsic (_InterlockedIncrement)
|
||||
#pragma intrinsic (_InterlockedDecrement)
|
||||
#pragma intrinsic (_InterlockedCompareExchange)
|
||||
#endif
|
||||
|
||||
// WinAPI function or MSVC intrinsic
|
||||
@@ -80,6 +95,11 @@ int Standard_Atomic_Decrement (volatile int* theValue)
|
||||
return _InterlockedDecrement (reinterpret_cast<volatile long*>(theValue));
|
||||
}
|
||||
|
||||
bool Standard_Atomic_CompareAndSwap (volatile int* theValue, int theOldValue, int theNewValue)
|
||||
{
|
||||
return _InterlockedCompareExchange (reinterpret_cast<volatile long*>(theValue), theNewValue, theOldValue) == theOldValue;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
// use atomic operations provided by MacOS
|
||||
|
||||
@@ -95,6 +115,11 @@ int Standard_Atomic_Decrement (volatile int* theValue)
|
||||
return OSAtomicDecrement32Barrier (theValue);
|
||||
}
|
||||
|
||||
bool Standard_Atomic_CompareAndSwap (volatile int* theValue, int theOldValue, int theNewValue)
|
||||
{
|
||||
return OSAtomicCompareAndSwapInt (theOldValue, theNewValue, theValue);
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
|
||||
// Atomic operations that were exported by the C library didn't
|
||||
@@ -114,34 +139,9 @@ int Standard_Atomic_Decrement (volatile int* theValue)
|
||||
return __atomic_dec (theValue) - 1; // analog of __sync_fetch_and_sub
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
|
||||
// use x86 / x86_64 inline assembly (compatibility with alien compilers / old GCC)
|
||||
|
||||
inline int Standard_Atomic_Add (volatile int* theValue, int theVal)
|
||||
bool Standard_Atomic_CompareAndSwap (volatile int* theValue, int theOldValue, int theNewValue)
|
||||
{
|
||||
// C equivalent:
|
||||
// *theValue += theVal;
|
||||
// return *theValue;
|
||||
|
||||
int previous;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"lock xadd %0,%1"
|
||||
: "=q"(previous), "=m"(*theValue) //output
|
||||
: "0"(theVal), "m"(*theValue) //input
|
||||
: "memory" //clobbers
|
||||
);
|
||||
return previous + theVal;
|
||||
}
|
||||
|
||||
int Standard_Atomic_Increment (volatile int* theValue)
|
||||
{
|
||||
return Standard_Atomic_Add (theValue, 1);
|
||||
}
|
||||
|
||||
int Standard_Atomic_Decrement (volatile int* theValue)
|
||||
{
|
||||
return Standard_Atomic_Add (theValue, -1);
|
||||
return __atomic_cmpxchg (theOldValue, theNewValue, theValue) == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -159,6 +159,16 @@ int Standard_Atomic_Decrement (volatile int* theValue)
|
||||
return --(*theValue);
|
||||
}
|
||||
|
||||
bool Standard_Atomic_CompareAndSwap (volatile int* theValue, int theOldValue, int theNewValue)
|
||||
{
|
||||
if (*theValue == theOldValue)
|
||||
{
|
||||
*theValue = theNewValue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif //_Standard_Atomic_HeaderFile
|
||||
|
207
src/Standard/Standard_Condition.cxx
Normal file
207
src/Standard/Standard_Condition.cxx
Normal file
@@ -0,0 +1,207 @@
|
||||
// Created by: Kirill Gavrilov
|
||||
// Copyright (c) 2018 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.
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "Standard_Condition.hxx"
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifndef _WIN32
|
||||
//! clock_gettime() wrapper.
|
||||
static void conditionGetRealTime (struct timespec& theTime)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
struct timeval aTime;
|
||||
gettimeofday (&aTime, NULL);
|
||||
theTime.tv_sec = aTime.tv_sec;
|
||||
theTime.tv_nsec = aTime.tv_usec * 1000;
|
||||
#else
|
||||
clock_gettime (CLOCK_REALTIME, &theTime);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Standard_Condition
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Condition::Standard_Condition (bool theIsSet)
|
||||
#ifdef _WIN32
|
||||
: myEvent((void* )::CreateEvent (0, true, theIsSet, NULL))
|
||||
#else
|
||||
: myFlag (theIsSet)
|
||||
#endif
|
||||
{
|
||||
#ifndef _WIN32
|
||||
pthread_mutex_init(&myMutex, 0);
|
||||
pthread_cond_init (&myCond, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Standard_Condition
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Condition::~Standard_Condition()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::CloseHandle ((HANDLE )myEvent);
|
||||
#else
|
||||
pthread_mutex_destroy(&myMutex);
|
||||
pthread_cond_destroy (&myCond);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Set
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Standard_Condition::Set()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::SetEvent ((HANDLE )myEvent);
|
||||
#else
|
||||
pthread_mutex_lock(&myMutex);
|
||||
myFlag = true;
|
||||
pthread_cond_broadcast(&myCond);
|
||||
pthread_mutex_unlock (&myMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Reset
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Standard_Condition::Reset()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::ResetEvent ((HANDLE )myEvent);
|
||||
#else
|
||||
pthread_mutex_lock (&myMutex);
|
||||
myFlag = false;
|
||||
pthread_mutex_unlock (&myMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Wait
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Standard_Condition::Wait()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::WaitForSingleObject ((HANDLE )myEvent, INFINITE);
|
||||
#else
|
||||
pthread_mutex_lock (&myMutex);
|
||||
if (!myFlag)
|
||||
{
|
||||
pthread_cond_wait (&myCond, &myMutex);
|
||||
}
|
||||
pthread_mutex_unlock (&myMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Wait
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Standard_Condition::Wait (int theTimeMilliseconds)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (::WaitForSingleObject ((HANDLE )myEvent, (DWORD )theTimeMilliseconds) != WAIT_TIMEOUT);
|
||||
#else
|
||||
bool isSignalled = true;
|
||||
pthread_mutex_lock (&myMutex);
|
||||
if (!myFlag)
|
||||
{
|
||||
struct timespec aNow;
|
||||
struct timespec aTimeout;
|
||||
conditionGetRealTime (aNow);
|
||||
aTimeout.tv_sec = (theTimeMilliseconds / 1000);
|
||||
aTimeout.tv_nsec = (theTimeMilliseconds - aTimeout.tv_sec * 1000) * 1000000;
|
||||
if (aTimeout.tv_nsec > 1000000000)
|
||||
{
|
||||
aTimeout.tv_sec += 1;
|
||||
aTimeout.tv_nsec -= 1000000000;
|
||||
}
|
||||
aTimeout.tv_sec += aNow.tv_sec;
|
||||
aTimeout.tv_nsec += aNow.tv_nsec;
|
||||
isSignalled = (pthread_cond_timedwait (&myCond, &myMutex, &aTimeout) != ETIMEDOUT);
|
||||
}
|
||||
pthread_mutex_unlock (&myMutex);
|
||||
return isSignalled;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Check
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Standard_Condition::Check()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (::WaitForSingleObject ((HANDLE )myEvent, (DWORD )0) != WAIT_TIMEOUT);
|
||||
#else
|
||||
bool isSignalled = true;
|
||||
pthread_mutex_lock (&myMutex);
|
||||
if (!myFlag)
|
||||
{
|
||||
struct timespec aNow;
|
||||
struct timespec aTimeout;
|
||||
conditionGetRealTime (aNow);
|
||||
aTimeout.tv_sec = aNow.tv_sec;
|
||||
aTimeout.tv_nsec = aNow.tv_nsec + 100;
|
||||
isSignalled = (pthread_cond_timedwait (&myCond, &myMutex, &aTimeout) != ETIMEDOUT);
|
||||
}
|
||||
pthread_mutex_unlock (&myMutex);
|
||||
return isSignalled;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : CheckReset
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Standard_Condition::CheckReset()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const bool wasSignalled = (::WaitForSingleObject ((HANDLE )myEvent, (DWORD )0) != WAIT_TIMEOUT);
|
||||
::ResetEvent ((HANDLE )myEvent);
|
||||
return wasSignalled;
|
||||
#else
|
||||
pthread_mutex_lock (&myMutex);
|
||||
bool wasSignalled = myFlag;
|
||||
if (!myFlag)
|
||||
{
|
||||
struct timespec aNow;
|
||||
struct timespec aTimeout;
|
||||
conditionGetRealTime (aNow);
|
||||
aTimeout.tv_sec = aNow.tv_sec;
|
||||
aTimeout.tv_nsec = aNow.tv_nsec + 100;
|
||||
wasSignalled = (pthread_cond_timedwait (&myCond, &myMutex, &aTimeout) != ETIMEDOUT);
|
||||
}
|
||||
myFlag = false;
|
||||
pthread_mutex_unlock (&myMutex);
|
||||
return wasSignalled;
|
||||
#endif
|
||||
}
|
80
src/Standard/Standard_Condition.hxx
Normal file
80
src/Standard/Standard_Condition.hxx
Normal file
@@ -0,0 +1,80 @@
|
||||
// Created by: Kirill Gavrilov
|
||||
// Copyright (c) 2018 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 _Standard_Condition_HeaderFile
|
||||
#define _Standard_Condition_HeaderFile
|
||||
|
||||
#include <Standard.hxx>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
//! This is boolean flag intended for communication between threads.
|
||||
//! One thread sets this flag to TRUE to indicate some event happened
|
||||
//! and another thread either waits this event or checks periodically its state to perform job.
|
||||
//!
|
||||
//! This class provides interface similar to WinAPI Event objects.
|
||||
class Standard_Condition
|
||||
{
|
||||
public:
|
||||
|
||||
//! Default constructor.
|
||||
//! @param theIsSet Initial flag state
|
||||
Standard_EXPORT Standard_Condition (bool theIsSet);
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT ~Standard_Condition();
|
||||
|
||||
//! Set event into signaling state.
|
||||
Standard_EXPORT void Set();
|
||||
|
||||
//! Reset event (unset signaling state)
|
||||
Standard_EXPORT void Reset();
|
||||
|
||||
//! Wait for Event (infinity).
|
||||
Standard_EXPORT void Wait();
|
||||
|
||||
//! Wait for signal requested time.
|
||||
//! @param theTimeMilliseconds wait limit in milliseconds
|
||||
//! @return true if get event
|
||||
Standard_EXPORT bool Wait (int theTimeMilliseconds);
|
||||
|
||||
//! Do not wait for signal - just test it state.
|
||||
//! @return true if get event
|
||||
Standard_EXPORT bool Check();
|
||||
|
||||
//! Method perform two steps at-once - reset the event object
|
||||
//! and returns true if it was in signaling state.
|
||||
//! @return true if event object was in signaling state.
|
||||
Standard_EXPORT bool CheckReset();
|
||||
|
||||
#ifdef _WIN32
|
||||
//! Access native HANDLE to Event object.
|
||||
void* getHandle() const { return myEvent; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
void* myEvent;
|
||||
#else
|
||||
pthread_mutex_t myMutex;
|
||||
pthread_cond_t myCond;
|
||||
bool myFlag;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // _Standard_Condition_HeaderFile
|
@@ -58,23 +58,6 @@ static void deallocate_message(Standard_CString aMessage)
|
||||
}
|
||||
}
|
||||
|
||||
// Define Standard_THREADLOCAL modifier as C++11 thread_local keyword where it is available.
|
||||
#if defined(__clang__)
|
||||
// CLang version: standard CLang > 3.3 or XCode >= 8 (but excluding 32-bit ARM)
|
||||
// Note: this has to be in separate #if to avoid failure of preprocessor on other platforms
|
||||
#if __has_feature(cxx_thread_local)
|
||||
#define Standard_THREADLOCAL thread_local
|
||||
#else
|
||||
#define Standard_THREADLOCAL
|
||||
#endif
|
||||
#elif (defined(__INTEL_COMPILER) && __INTEL_COMPILER > 1400) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1900) /* MSVC++ >= 14 */ || \
|
||||
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) /* GCC >= 4.8 */
|
||||
#define Standard_THREADLOCAL thread_local
|
||||
#else
|
||||
#define Standard_THREADLOCAL
|
||||
#endif
|
||||
|
||||
// ******************************************************************
|
||||
// Standard_Failure *
|
||||
// ******************************************************************
|
||||
|
@@ -393,10 +393,22 @@ Standard_Integer Standard_GUID::Hash(const Standard_Integer Upper) const
|
||||
throw Standard_RangeError("Standard_GUID::Hash: Try to apply HashCode method with negative or null argument.");
|
||||
}
|
||||
|
||||
char sguid[Standard_GUID_SIZE_ALLOC];
|
||||
ToCString(sguid);
|
||||
|
||||
return ::HashCode(sguid,Upper);
|
||||
// ==== AGV 16/12/2012: More optimal hash function ===
|
||||
//char sguid[Standard_GUID_SIZE_ALLOC];
|
||||
//ToCString(sguid);
|
||||
//return ::HashCode(sguid,Upper);
|
||||
// ===================================================
|
||||
unsigned int aHash = ((static_cast<unsigned int>(my8b6) << 24) |
|
||||
(static_cast<unsigned int>(my8b5) << 16) |
|
||||
(static_cast<unsigned int>(my8b4) << 8) |
|
||||
(static_cast<unsigned int>(my8b3)));
|
||||
aHash = (aHash ^ (aHash >> 11)) & 0x07ffffff;
|
||||
aHash = (aHash * 31 + ((static_cast<unsigned int>(my8b2) << 24) |
|
||||
(static_cast<unsigned int>(my8b1) << 16) |
|
||||
(static_cast<unsigned int>(my16b3)))) & 0x07ffffff;
|
||||
aHash = (aHash * 31 + ((static_cast<unsigned int>(my16b2) << 16) |
|
||||
(static_cast<unsigned int>(my16b1)))) & 0x07ffffff;
|
||||
return (aHash * 31 + my32b) % Upper;
|
||||
}
|
||||
|
||||
Standard_Boolean Standard_GUID::IsEqual(const Standard_GUID& aGuid1,const Standard_GUID& aGuid2)
|
||||
|
@@ -12,13 +12,21 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// Purpose: This file is intended to be the first file #included to any
|
||||
// Open CASCADE source. It defines platform-specific pre-processor
|
||||
// macros necessary for correct compilation of Open CASCADE code
|
||||
//! @file
|
||||
//! This file is intended to be the first file included to any
|
||||
//! Open CASCADE source. It defines platform-specific pre-processor
|
||||
//! macros necessary for correct compilation of Open CASCADE code.
|
||||
|
||||
#ifndef _Standard_Macro_HeaderFile
|
||||
# define _Standard_Macro_HeaderFile
|
||||
|
||||
//! @def Standard_OVERRIDE
|
||||
//! Should be used in declarations of virtual methods overriden in the
|
||||
//! derived classes, to cause compilation error in the case if that virtual
|
||||
//! function disappears or changes its signature in the base class.
|
||||
//!
|
||||
//! Expands to C++11 keyword "override" on compilers that are known to
|
||||
//! suppot it; empty in other cases.
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201100L)
|
||||
// part of C++11 standard
|
||||
#define Standard_OVERRIDE override
|
||||
@@ -29,16 +37,69 @@
|
||||
#define Standard_OVERRIDE
|
||||
#endif
|
||||
|
||||
// Macro for marking variables / functions as possibly unused
|
||||
// so that compiler will not emit redundant "unused" warnings.
|
||||
//! @def Standard_FALLTHROUGH
|
||||
//! Should be used in a switch statement immediately before a case label,
|
||||
//! if code associated with the previous case label may fall through to that
|
||||
//! next label (i.e. does not end with "break" or "return" etc.).
|
||||
//! This macro indicates that the fall through is intentional and should not be
|
||||
//! diagnosed by a compiler that warns on fallthrough.
|
||||
//!
|
||||
//! Expands to C++17 attribute statement "[[fallthrough]];" on compilers that
|
||||
//! declare support of C++17, or to "__attribute__((fallthrough));" on
|
||||
//! GCC 7+.
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201703L)
|
||||
// part of C++17 standard
|
||||
#define Standard_FALLTHROUGH [[fallthrough]];
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 7)
|
||||
// gcc 7+
|
||||
#define Standard_FALLTHROUGH __attribute__((fallthrough));
|
||||
#else
|
||||
#define Standard_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
//! @def Standard_UNUSED
|
||||
//! Macro for marking variables / functions as possibly unused
|
||||
//! so that compiler will not emit redundant "unused" warnings.
|
||||
//!
|
||||
//! Expands to "__attribute__((unused))" on GCC and CLang.
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define Standard_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define Standard_UNUSED
|
||||
#endif
|
||||
|
||||
// Macro Standard_DEPRECATED("message") can be used to declare a method deprecated.
|
||||
// If OCCT_NO_DEPRECATED is defined, Standard_DEPRECATED is defined empty.
|
||||
//! @def Standard_THREADLOCAL
|
||||
//! Define Standard_THREADLOCAL modifier as C++11 thread_local keyword where it is available.
|
||||
#if defined(__clang__)
|
||||
// CLang version: standard CLang > 3.3 or XCode >= 8 (but excluding 32-bit ARM)
|
||||
// Note: this has to be in separate #if to avoid failure of preprocessor on other platforms
|
||||
#if __has_feature(cxx_thread_local)
|
||||
#define Standard_THREADLOCAL thread_local
|
||||
#endif
|
||||
#elif defined(__INTEL_COMPILER)
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900 && __INTEL_COMPILER > 1400)
|
||||
// requires msvcrt vc14+ (Visual Studio 2015+)
|
||||
#define Standard_THREADLOCAL thread_local
|
||||
#elif (!defined(_MSC_VER) && __INTEL_COMPILER > 1500)
|
||||
#define Standard_THREADLOCAL thread_local
|
||||
#endif
|
||||
#elif (defined(_MSC_VER) && _MSC_VER >= 1900)
|
||||
// msvcrt coming with vc14+ (VS2015+)
|
||||
#define Standard_THREADLOCAL thread_local
|
||||
#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
|
||||
// GCC >= 4.8
|
||||
#define Standard_THREADLOCAL thread_local
|
||||
#endif
|
||||
|
||||
#ifndef Standard_THREADLOCAL
|
||||
#define Standard_THREADLOCAL
|
||||
#endif
|
||||
|
||||
//! @def Standard_DEPRECATED("message")
|
||||
//! Can be used in declaration of a method or a class to mark it as deprecated.
|
||||
//! Use of such method or class will cause compiler warning (if supported by
|
||||
//! compiler and unless disabled).
|
||||
//! If macro OCCT_NO_DEPRECATED is defined, Standard_DEPRECATED is defined empty.
|
||||
#ifdef OCCT_NO_DEPRECATED
|
||||
#define Standard_DEPRECATED(theMsg)
|
||||
#else
|
||||
@@ -53,9 +114,14 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Disable warnings about deprecated features.
|
||||
// This is useful for sections of code kept for backward compatibility and scheduled for removal.
|
||||
|
||||
//! @def Standard_DISABLE_DEPRECATION_WARNINGS
|
||||
//! Disables warnings on use of deprecated features (see Standard_DEPRECATED),
|
||||
//! from the current point till appearance of Standard_ENABLE_DEPRECATION_WARNINGS macro.
|
||||
//! This is useful for sections of code kept for backward compatibility and scheduled for removal.
|
||||
//!
|
||||
//! @def Standard_ENABLE_DEPRECATION_WARNINGS
|
||||
//! Enables warnings on use of deprecated features previously disabled by
|
||||
//! Standard_DISABLE_DEPRECATION_WARNINGS.
|
||||
#if defined(__ICL) || defined (__INTEL_COMPILER)
|
||||
#define Standard_DISABLE_DEPRECATION_WARNINGS __pragma(warning(push)) __pragma(warning(disable:1478))
|
||||
#define Standard_ENABLE_DEPRECATION_WARNINGS __pragma(warning(pop))
|
||||
@@ -72,6 +138,13 @@
|
||||
#define Standard_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
//! @def OCCT_NO_RVALUE_REFERENCE
|
||||
//! Disables methods and constructors that use rvalue references
|
||||
//! (C++11 move semantics) not supported by obsolete compilers.
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||
#define OCCT_NO_RVALUE_REFERENCE
|
||||
#endif
|
||||
|
||||
# ifdef _WIN32
|
||||
|
||||
// We must be careful including windows.h: it is really poisonous stuff!
|
||||
@@ -118,7 +191,15 @@
|
||||
|
||||
#endif
|
||||
|
||||
# if defined(_WIN32) && !defined(HAVE_NO_DLL)
|
||||
//! @def Standard_EXPORT
|
||||
//! This macro should be used in declarations of public methods
|
||||
//! to ensure that they are exported from DLL on Windows and thus
|
||||
//! can be called from other (dependent) libraries or applications.
|
||||
//!
|
||||
//! If macro OCCT_STATIC_BUILD is defined, then Standard_EXPORT
|
||||
//! is set to empty.
|
||||
|
||||
# if defined(_WIN32) && !defined(OCCT_STATIC_BUILD) && !defined(HAVE_NO_DLL)
|
||||
|
||||
//======================================================
|
||||
// Windows-specific definitions
|
||||
@@ -167,21 +248,9 @@
|
||||
|
||||
# endif /* _WIN32 */
|
||||
|
||||
//======================================================
|
||||
// Other
|
||||
//======================================================
|
||||
|
||||
# ifndef __Standard_API
|
||||
# if !defined(_WIN32) || defined(__Standard_DLL) || defined(__FSD_DLL) || defined(__MMgt_DLL) || defined(__OSD_DLL) || defined(__Plugin_DLL) || defined(__Quantity_DLL) || defined(__Resource_DLL) || defined(__SortTools_DLL) || defined(__StdFail_DLL) || defined(__Storage_DLL) || defined(__TColStd_DLL) || defined(__TCollection_DLL) || defined(__TShort_DLL) || defined(__Units_DLL) || defined(__UnitsAPI_DLL) || defined(__Dico_DLL)
|
||||
# define __Standard_API Standard_EXPORT
|
||||
# define __Standard_APIEXTERN Standard_EXPORTEXTERN
|
||||
# else
|
||||
# define __Standard_API Standard_IMPORT
|
||||
# define __Standard_APIEXTERN Standard_IMPORT
|
||||
# endif // __Standard_DLL
|
||||
# endif // __Standard_API
|
||||
|
||||
// Support of Universal Windows Platform
|
||||
//! @def OCCT_UWP
|
||||
//! This macro is defined on Windows platform in the case if the code
|
||||
//! is being compiled for UWP (Universal Windows Platform).
|
||||
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP
|
||||
#define OCCT_UWP
|
||||
#else
|
||||
|
@@ -54,7 +54,7 @@ void StdSelect_Shape::Compute(const Handle(PrsMgr_PresentationManager3d)& /*PM*/
|
||||
else
|
||||
StdPrs_WFShape::Add (P, mysh, myDrawer);
|
||||
}
|
||||
else if (aMode==0)
|
||||
else
|
||||
StdPrs_WFShape::Add (P, mysh, myDrawer);
|
||||
}
|
||||
|
||||
|
@@ -117,7 +117,7 @@ public:
|
||||
|
||||
//! Adds an Attribute to the current label. Raises if
|
||||
//! there is already one.
|
||||
Standard_EXPORT void AddAttribute (const Handle(TDF_Attribute)& anAttribute, const Standard_Boolean append = Standard_False) const;
|
||||
Standard_EXPORT void AddAttribute (const Handle(TDF_Attribute)& anAttribute, const Standard_Boolean append = Standard_True) const;
|
||||
|
||||
//! Forgets an Attribute from the current label,
|
||||
//! setting its forgotten status true and its valid
|
||||
|
@@ -285,17 +285,17 @@ void TDataXtd_Presentation::SetMode(const Standard_Integer theMode)
|
||||
//function : SetSelectionMode
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void TDataXtd_Presentation::SetSelectionMode(const Standard_Integer theSelectionMode)
|
||||
void TDataXtd_Presentation::SetSelectionMode(const Standard_Integer theSelectionMode, const Standard_Boolean theTransaction)
|
||||
{
|
||||
if (! myHasOwnSelectionMode || mySelectionMode != theSelectionMode)
|
||||
{
|
||||
Backup();
|
||||
if (theTransaction)
|
||||
Backup();
|
||||
mySelectionMode = theSelectionMode;
|
||||
myHasOwnSelectionMode = Standard_True;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=======================================================================
|
||||
//function : MaterialIndex
|
||||
//purpose :
|
||||
|
@@ -114,7 +114,12 @@ public:
|
||||
|
||||
Standard_EXPORT void SetMode(const Standard_Integer theMode);
|
||||
|
||||
Standard_EXPORT void SetSelectionMode(const Standard_Integer theSelectionMode);
|
||||
//! Sets selection mode.
|
||||
//! If "theTransaction" flag is OFF, modification of the attribute doesn't influence the transaction mechanism
|
||||
//! (the attribute doesn't participate in undo/redo because of this modification).
|
||||
//! Certainly, if any other data of the attribute is modified (display mode, color, ...),
|
||||
//! the attribute will be included into undo/redo.
|
||||
Standard_EXPORT void SetSelectionMode(const Standard_Integer theSelectionMode, const Standard_Boolean theTransaction = Standard_True);
|
||||
|
||||
Standard_EXPORT Standard_Integer MaterialIndex() const;
|
||||
|
||||
|
@@ -591,11 +591,16 @@ Standard_Boolean TPrsStd_AISPresentation::HasOwnSelectionMode() const
|
||||
//function : SetSelectionMode
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void TPrsStd_AISPresentation::SetSelectionMode(const Standard_Integer theSelectionMode)
|
||||
void TPrsStd_AISPresentation::SetSelectionMode(const Standard_Integer theSelectionMode, const Standard_Boolean theTransaction)
|
||||
{
|
||||
Backup();
|
||||
getData()->SetSelectionMode (theSelectionMode);
|
||||
AISUpdate();
|
||||
if (theTransaction)
|
||||
Backup();
|
||||
getData()->SetSelectionMode (theSelectionMode, theTransaction);
|
||||
|
||||
if ( myAIS.IsNull() )
|
||||
AISUpdate();
|
||||
else
|
||||
ActivateSelectionMode();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -800,7 +805,7 @@ void TPrsStd_AISPresentation::AISUpdate()
|
||||
if ( !(anObj == myAIS) )
|
||||
{
|
||||
if ( !aContext.IsNull() )
|
||||
aContext->Remove (myAIS, Standard_True);
|
||||
aContext->Remove (myAIS, Standard_False);
|
||||
|
||||
// Driver has built new AIS.
|
||||
myAIS = anObj;
|
||||
@@ -871,36 +876,7 @@ void TPrsStd_AISPresentation::AISUpdate()
|
||||
myAIS->SetDisplayMode(aMode);
|
||||
}
|
||||
|
||||
if ( !aContext.IsNull() && IsDisplayed() )
|
||||
aContext->Redisplay(myAIS, Standard_False);
|
||||
|
||||
if (HasOwnSelectionMode()) {
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
TColStd_ListOfInteger anActivatedModes;
|
||||
aContext->ActivatedModes (myAIS, anActivatedModes);
|
||||
Standard_Boolean isActivated = Standard_False;
|
||||
Standard_Integer aSelectionMode = SelectionMode();
|
||||
if (aSelectionMode == -1)
|
||||
{
|
||||
aContext->Deactivate(myAIS);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TColStd_ListIteratorOfListOfInteger aModeIter (anActivatedModes); aModeIter.More(); aModeIter.Next())
|
||||
{
|
||||
if (aModeIter.Value() == aSelectionMode)
|
||||
{
|
||||
isActivated = Standard_True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isActivated)
|
||||
aContext->Activate (myAIS, aSelectionMode, Standard_False);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ActivateSelectionMode();
|
||||
}
|
||||
|
||||
if (IsDisplayed() && !aContext.IsNull())
|
||||
@@ -1013,3 +989,40 @@ Handle(AIS_InteractiveContext) TPrsStd_AISPresentation::getAISContext() const
|
||||
|
||||
return Handle_AIS_InteractiveContext();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ActivateSelectionMode
|
||||
//purpose : Activates selection mode of the interactive object.
|
||||
// It is called internally on change of selection mode and AISUpdate().
|
||||
//=======================================================================
|
||||
void TPrsStd_AISPresentation::ActivateSelectionMode()
|
||||
{
|
||||
if (!myAIS.IsNull() && HasOwnSelectionMode())
|
||||
{
|
||||
Handle(AIS_InteractiveContext) aContext = getAISContext();
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
TColStd_ListOfInteger anActivatedModes;
|
||||
aContext->ActivatedModes (myAIS, anActivatedModes);
|
||||
Standard_Boolean isActivated = Standard_False;
|
||||
Standard_Integer aSelectionMode = SelectionMode();
|
||||
if (aSelectionMode == -1)
|
||||
{
|
||||
aContext->Deactivate(myAIS);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TColStd_ListIteratorOfListOfInteger aModeIter (anActivatedModes); aModeIter.More(); aModeIter.Next())
|
||||
{
|
||||
if (aModeIter.Value() == aSelectionMode)
|
||||
{
|
||||
isActivated = Standard_True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isActivated)
|
||||
aContext->Activate (myAIS, aSelectionMode, Standard_False);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -157,8 +157,13 @@ public:
|
||||
Standard_EXPORT void UnsetMode();
|
||||
|
||||
Standard_EXPORT Standard_Integer SelectionMode() const;
|
||||
|
||||
Standard_EXPORT void SetSelectionMode (const Standard_Integer theSelectionMode);
|
||||
|
||||
//! Sets selection mode.
|
||||
//! If "theTransaction" flag is OFF, modification of the attribute doesn't influence the transaction mechanism
|
||||
//! (the attribute doesn't participate in undo/redo because of this modification).
|
||||
//! Certainly, if any other data of the attribute is modified (display mode, color, ...),
|
||||
//! the attribute will be included into undo/redo.
|
||||
Standard_EXPORT void SetSelectionMode (const Standard_Integer theSelectionMode, const Standard_Boolean theTransaction = Standard_True);
|
||||
|
||||
Standard_EXPORT Standard_Boolean HasOwnSelectionMode() const;
|
||||
|
||||
@@ -197,6 +202,10 @@ protected:
|
||||
private:
|
||||
|
||||
Handle(AIS_InteractiveContext) getAISContext() const;
|
||||
|
||||
//! Activates selection mode of the interactive object.
|
||||
//! It is called internally on change of selection mode and AISUpdate().
|
||||
void ActivateSelectionMode();
|
||||
|
||||
//! Updates AIS_InteractiveObject stored in the attribute
|
||||
//! and applies the visualization settings
|
||||
@@ -209,7 +218,6 @@ private:
|
||||
//! the viewer; If <remove> = True then AISObject is removed
|
||||
//! from AIS_InteractiveContext instead of simple erasing in the viewer
|
||||
Standard_EXPORT void AISErase (const Standard_Boolean remove = Standard_False);
|
||||
|
||||
private:
|
||||
Handle(AIS_InteractiveObject) myAIS;
|
||||
};
|
||||
|
@@ -134,6 +134,7 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
|
||||
TopoDS_Shape aTestedShape;
|
||||
aTestedShape.TShape (aShape.TShape());
|
||||
aTestedShape.Orientation (isReverse ? TopAbs_REVERSED : TopAbs_FORWARD);
|
||||
Standard_Boolean isTessellate (Standard_False);
|
||||
switch (ShapeType[i]) {
|
||||
case TopAbs_FACE:
|
||||
{
|
||||
@@ -147,6 +148,16 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
|
||||
break;
|
||||
}
|
||||
|
||||
if (aTri.IsNull())
|
||||
isTessellate = Standard_True;
|
||||
// Check the existing deflection
|
||||
else if (aTri->Deflection() > aDeflection+ Precision::Confusion())
|
||||
isTessellate = Standard_True;
|
||||
if (isTessellate) {
|
||||
// Triangulate the face by the standard OCC mesher
|
||||
BRepMesh_IncrementalMesh IM (aFace, aDeflection, Standard_False, theDeflAngle);
|
||||
aTri = BRep_Tool::Triangulation (aFace, aLoc);
|
||||
}
|
||||
if (aTri.IsNull() == Standard_False) {
|
||||
TopoDS_Shape aTestedShapeRev = aTestedShape;
|
||||
aTestedShapeRev.Orientation (isReverse ?
|
||||
@@ -179,6 +190,8 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
|
||||
{
|
||||
const TopoDS_Edge& aEdge = TopoDS::Edge (aShape);
|
||||
if (aEdge.IsNull() == Standard_False) {
|
||||
Handle(Poly_Polygon3D) aPol = BRep_Tool::Polygon3D (aEdge, aLoc);
|
||||
|
||||
if (aRelMap.IsBound (aTestedShape)) {
|
||||
aTShapeNode = aRelMap(aTestedShape);
|
||||
break;
|
||||
@@ -191,34 +204,53 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
|
||||
aTShapeNode = aRelMap(aTestedShape);
|
||||
break;
|
||||
}
|
||||
|
||||
if (aPol.IsNull())
|
||||
isTessellate = Standard_True;
|
||||
// Check the existing deflection
|
||||
else if (aPol->Deflection() > aDeflection+ Precision::Confusion()
|
||||
&& BRep_Tool::IsGeometric(aEdge))
|
||||
isTessellate = Standard_True;
|
||||
|
||||
if (isTessellate && BRep_Tool::IsGeometric(aEdge)) {
|
||||
//try to find PolygonOnTriangulation
|
||||
Handle(Poly_PolygonOnTriangulation) aPT;
|
||||
Handle(Poly_Triangulation) aT;
|
||||
TopLoc_Location aL;
|
||||
|
||||
//try to find PolygonOnTriangulation
|
||||
Handle(Poly_PolygonOnTriangulation) aPT;
|
||||
Handle(Poly_Triangulation) aT;
|
||||
TopLoc_Location aL;
|
||||
BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL);
|
||||
Standard_Boolean found = Standard_False;
|
||||
Standard_Integer j = 1;
|
||||
for (;;) {
|
||||
BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL, j);
|
||||
|
||||
// If PolygonOnTriangulation was found -> get the Polygon3D
|
||||
Handle(Poly_Polygon3D) aPol;
|
||||
if(!aPT.IsNull() && !aT.IsNull() && aPT->HasParameters()) {
|
||||
BRepAdaptor_Curve aCurve(aEdge);
|
||||
Handle(TColStd_HArray1OfReal) aPrs = aPT->Parameters();
|
||||
Standard_Integer nbNodes = aPT->NbNodes();
|
||||
TColgp_Array1OfPnt arrNodes(1, nbNodes);
|
||||
TColStd_Array1OfReal arrUVNodes(1, nbNodes);
|
||||
if (aPT.IsNull() || aT.IsNull()) break;
|
||||
|
||||
for(Standard_Integer j = 1; j <= nbNodes; j++) {
|
||||
arrUVNodes(j) = aPrs->Value(aPrs->Lower() + j - 1);
|
||||
arrNodes(j) = aCurve.Value(arrUVNodes(j));
|
||||
if (aPT->Deflection() <= aDeflection + Precision::Confusion()
|
||||
&& aPT->HasParameters())
|
||||
{
|
||||
found = Standard_True;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
|
||||
aPol->Deflection (aPT->Deflection());
|
||||
}
|
||||
else {
|
||||
aPol = BRep_Tool::Polygon3D(aEdge, aL);
|
||||
|
||||
if(found) {
|
||||
|
||||
// If polygon was not found -> generate it
|
||||
if (aPol.IsNull()) {
|
||||
BRepAdaptor_Curve aCurve(aEdge);
|
||||
Handle(TColStd_HArray1OfReal) aPrs = aPT->Parameters();
|
||||
Standard_Integer nbNodes = aPT->NbNodes();
|
||||
TColgp_Array1OfPnt arrNodes(1, nbNodes);
|
||||
TColStd_Array1OfReal arrUVNodes(1, nbNodes);
|
||||
|
||||
for(Standard_Integer j = 1; j <= nbNodes; j++) {
|
||||
arrUVNodes(j) = aPrs->Value(aPrs->Lower() + j - 1);
|
||||
arrNodes(j) = aCurve.Value(arrUVNodes(j));
|
||||
}
|
||||
aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
|
||||
aPol->Deflection (aPT->Deflection());
|
||||
}
|
||||
else{
|
||||
|
||||
BRepAdaptor_Curve aCurve(aEdge);
|
||||
const Standard_Real aFirst = aCurve.FirstParameter();
|
||||
const Standard_Real aLast = aCurve.LastParameter();
|
||||
@@ -236,11 +268,10 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
|
||||
aPol = new Poly_Polygon3D(arrNodes, arrUVNodes);
|
||||
aPol->Deflection (aDeflection);
|
||||
}
|
||||
|
||||
BRep_Builder aBld;
|
||||
aBld.UpdateEdge (aEdge, aPol);
|
||||
}
|
||||
|
||||
if (aPol.IsNull())
|
||||
continue;
|
||||
|
||||
aTShapeNode = polToIndexedLineSet (aPol);
|
||||
myScene.AddNode (aTShapeNode, Standard_False);
|
||||
// Bind the converted face
|
||||
|
@@ -256,7 +256,10 @@ Standard_Integer XmlMDF::ReadSubTree (const XmlObjMgt_Element& theElement,
|
||||
if (isBound)
|
||||
tAtt = Handle(TDF_Attribute)::DownCast(theRelocTable.Find(anID));
|
||||
else
|
||||
{
|
||||
tAtt = driver -> NewEmpty();
|
||||
tAtt->SetID();
|
||||
}
|
||||
if (tAtt->Label().IsNull())
|
||||
theLabel.AddAttribute (tAtt);
|
||||
else
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <XmlObjMgt.hxx>
|
||||
#include <XmlObjMgt_Document.hxx>
|
||||
#include <XmlObjMgt_Persistent.hxx>
|
||||
#include <XmlLDrivers.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(XmlMDataStd_ExtStringArrayDriver,XmlMDF_ADriver)
|
||||
IMPLEMENT_DOMSTRING (FirstIndexString, "first")
|
||||
@@ -238,39 +239,46 @@ void XmlMDataStd_ExtStringArrayDriver::Paste (const Handle(TDF_Attribute)& theSo
|
||||
|
||||
// Find a separator.
|
||||
Standard_Boolean found(Standard_True);
|
||||
// Preferrable symbols for the separator: - _ . : ^ ~
|
||||
// Don't use a space as a separator: XML low-level parser sometimes "eats" it.
|
||||
// This improvement was defined in the version 8.
|
||||
// So, if the user wants to save the document under the 7th or earlier versions,
|
||||
// don't apply this improvement.
|
||||
Standard_Character c = '-';
|
||||
static Standard_Character aPreferable[] = "-_.:^~";
|
||||
for (i = 0; found && aPreferable[i]; i++)
|
||||
if (XmlLDrivers::StorageVersion() > 7)
|
||||
{
|
||||
c = aPreferable[i];
|
||||
found = Contains(aExtStringArray, TCollection_ExtendedString(c));
|
||||
}
|
||||
// If all prefferable symbols exist in the array,
|
||||
// try to use any other simple symbols.
|
||||
if (found)
|
||||
{
|
||||
c = '!';
|
||||
while (found && c < '~')
|
||||
// Preferrable symbols for the separator: - _ . : ^ ~
|
||||
// Don't use a space as a separator: XML low-level parser sometimes "eats" it.
|
||||
Standard_Character c = '-';
|
||||
static Standard_Character aPreferable[] = "-_.:^~";
|
||||
for (i = 0; found && aPreferable[i]; i++)
|
||||
{
|
||||
found = Standard_False;
|
||||
#ifdef _DEBUG
|
||||
TCollection_AsciiString cseparator(c); // deb
|
||||
#endif
|
||||
TCollection_ExtendedString separator(c);
|
||||
found = Contains(aExtStringArray, separator);
|
||||
if (found)
|
||||
c = aPreferable[i];
|
||||
found = Contains(aExtStringArray, TCollection_ExtendedString(c));
|
||||
}
|
||||
// If all prefferable symbols exist in the array,
|
||||
// try to use any other simple symbols.
|
||||
if (found)
|
||||
{
|
||||
c = '!';
|
||||
while (found && c < '~')
|
||||
{
|
||||
c++;
|
||||
// Skip forbidden symbols for XML.
|
||||
while (c < '~' && (c == '&' || c == '<'))
|
||||
found = Standard_False;
|
||||
#ifdef _DEBUG
|
||||
TCollection_AsciiString cseparator(c); // deb
|
||||
#endif
|
||||
TCollection_ExtendedString separator(c);
|
||||
found = Contains(aExtStringArray, separator);
|
||||
if (found)
|
||||
{
|
||||
c++;
|
||||
// Skip forbidden symbols for XML.
|
||||
while (c < '~' && (c == '&' || c == '<'))
|
||||
{
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}// check doc version
|
||||
|
||||
if (found)
|
||||
{
|
||||
|
@@ -165,15 +165,19 @@ void math_NewtonMinimum::Perform(math_MultipleVarFunctionWithHessian& F,
|
||||
Standard_Real aMult = RealLast();
|
||||
for(Standard_Integer anIdx = 1; anIdx <= myLeft.Upper(); anIdx++)
|
||||
{
|
||||
const Standard_Real anAbsStep = Abs(TheStep(anIdx));
|
||||
if (anAbsStep < gp::Resolution())
|
||||
continue;
|
||||
|
||||
if (suivant->Value(anIdx) < myLeft(anIdx))
|
||||
{
|
||||
Standard_Real aValue = Abs(precedent->Value(anIdx) - myLeft(anIdx)) / Abs(TheStep(anIdx));
|
||||
Standard_Real aValue = Abs(precedent->Value(anIdx) - myLeft(anIdx)) / anAbsStep;
|
||||
aMult = Min (aValue, aMult);
|
||||
}
|
||||
|
||||
if (suivant->Value(anIdx) > myRight(anIdx))
|
||||
{
|
||||
Standard_Real aValue = Abs(precedent->Value(anIdx) - myRight(anIdx)) / Abs(TheStep(anIdx));
|
||||
Standard_Real aValue = Abs(precedent->Value(anIdx) - myRight(anIdx)) / anAbsStep;
|
||||
aMult = Min (aValue, aMult);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,8 @@ puts ""
|
||||
# (case 11)
|
||||
######################################################
|
||||
|
||||
puts "TODO 29663 ALL: Faulty shapes in variables faulty_1 to faulty_4"
|
||||
|
||||
restore [locate_data_file OCC1477-1.brep] s1
|
||||
restore [locate_data_file OCC1477-2.brep] s2
|
||||
|
||||
|
@@ -8,7 +8,7 @@ checkshape b
|
||||
restore [locate_data_file pro19424b.brep] p
|
||||
checkshape p
|
||||
|
||||
if [catch {evolved result b p o } catch_result] {
|
||||
if [catch {evolved result -s b -p p -a } catch_result] {
|
||||
puts "Faulty PRO19424 : function EVOLVED works wrongly"
|
||||
} else {
|
||||
puts "PRO19424 OK: function EVOLVED works properly"
|
||||
|
@@ -8,4 +8,4 @@ puts ""
|
||||
|
||||
restore [locate_data_file OCC26470-ClosedWire.brep] a
|
||||
restore [locate_data_file OCC26470-wprof1.brep] b
|
||||
evolved res a b o
|
||||
evolved res -s a -p b -a
|
||||
|
@@ -8,5 +8,5 @@ puts ""
|
||||
|
||||
restore [locate_data_file OCC26470-ClosedWire.brep] a
|
||||
restore [locate_data_file OCC26470-wprof2.brep] b
|
||||
evolved res a b o
|
||||
evolved res -s a -p b -a
|
||||
checkshape res
|
||||
|
@@ -13,7 +13,8 @@ explode Box E
|
||||
|
||||
blend Fillet Box 1 Box_1 1 Box_2 1 Box_3 1 Box_4 1 Box_5 1 Box_6 1 Box_7 1 Box_8 1 Box_9 1 Box_10 1 Box_11 1 Box_12
|
||||
|
||||
if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck Fillet]] == 1 } {
|
||||
set bug_info [string trim [bopcheck Fillet]]
|
||||
if {$bug_info != "This shape seems to be OK."} {
|
||||
puts "Error : result of blend fails the bopcheck"
|
||||
}
|
||||
|
||||
|
34
tests/bugs/modalg_7/bug29073
Normal file
34
tests/bugs/modalg_7/bug29073
Normal file
@@ -0,0 +1,34 @@
|
||||
puts "======="
|
||||
puts "0029073"
|
||||
puts "======="
|
||||
puts ""
|
||||
##################################################
|
||||
# Regression: General Cut produces invalid shape
|
||||
##################################################
|
||||
|
||||
brestore [locate_data_file bug29073_M6.brep] b1
|
||||
brestore [locate_data_file bug29073_Shell.brep] b2
|
||||
|
||||
bclearobjects
|
||||
bcleartools
|
||||
baddobjects b1
|
||||
baddtools b2
|
||||
bfillds
|
||||
|
||||
# check the result of SECTION
|
||||
bbop rsec 4
|
||||
checknbshapes rsec -edge 1 -vertex 2
|
||||
|
||||
# check the result of GF
|
||||
bbuild rgf
|
||||
checkshape rgf
|
||||
checkprops rgf -s 163.708 -v 115.912
|
||||
checknbshapes rgf -wire 25 -face 24 -shell 3 -solid 1
|
||||
|
||||
# check the CUT
|
||||
bbop result 3
|
||||
checkshape result
|
||||
checkprops result -s 0.000713987
|
||||
checknbshapes result -wire 1 -face 1
|
||||
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
26
tests/bugs/modalg_7/bug29204
Normal file
26
tests/bugs/modalg_7/bug29204
Normal file
@@ -0,0 +1,26 @@
|
||||
puts "============"
|
||||
puts "OCC29204"
|
||||
puts "============"
|
||||
puts ""
|
||||
##################################################################################
|
||||
# BRepOffsetAPI_MakePipeShell produces invalid result and raises exception in Draw
|
||||
##################################################################################
|
||||
|
||||
restore [locate_data_file bug29204_sweep_spine.brep] sp
|
||||
restore [locate_data_file bug29204_sweep_profile.brep] pr
|
||||
|
||||
mksweep sp
|
||||
addsweep pr
|
||||
buildsweep result -C -S
|
||||
|
||||
checkshape result
|
||||
|
||||
checknbshapes result -solid 1 -shell 1 -face 28 -wire 28 -edge 64 -vertex 36 -shape 158
|
||||
|
||||
set tolres [checkmaxtol result]
|
||||
|
||||
if { ${tolres} > 0.001} {
|
||||
puts "Error: bad tolerance of result"
|
||||
}
|
||||
|
||||
checkprops result -v 1.16577e+007
|
28
tests/bugs/modalg_7/bug29663
Normal file
28
tests/bugs/modalg_7/bug29663
Normal file
@@ -0,0 +1,28 @@
|
||||
puts "========"
|
||||
puts "OCC29663"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# Exception in BRepFill_PipeShell algorithm
|
||||
#################################################
|
||||
|
||||
restore [locate_data_file bug29523_cut_extrudewire08.brep] sw
|
||||
restore [locate_data_file bug29523_cut_toolwire08.brep] tw
|
||||
|
||||
mksweep sw
|
||||
addsweep tw
|
||||
|
||||
if { [catch {buildsweep rr -R} catch_result] } {
|
||||
puts "Faulty OCC29663"
|
||||
}
|
||||
|
||||
fixshape result rr
|
||||
|
||||
checkshape result
|
||||
checkprops result -s 2.14316e+011
|
||||
|
||||
checkmaxtol result -ref 0.070055357229360987
|
||||
|
||||
checknbshapes result -shell 1 -face 201 -wire 201
|
||||
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
@@ -10,7 +10,8 @@ puts ""
|
||||
|
||||
restore [locate_data_file bug25693_path3035.brep] result
|
||||
|
||||
if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck result]] == 1 } {
|
||||
set bug_info [string trim [bopcheck result]]
|
||||
if {$bug_info != "This shape seems to be OK."} {
|
||||
puts "Error : Wire of BSplines fails bopcheck"
|
||||
}
|
||||
|
||||
|
@@ -12,11 +12,13 @@ restore [locate_data_file bug25693_path3039.brep] path3039
|
||||
|
||||
prism Extrude_path3039 path3039 0 0 50
|
||||
|
||||
if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck path3039]] == 1 } {
|
||||
set log1 [string trim [bopcheck path3039]]
|
||||
if {$log1 != "This shape seems to be OK."} {
|
||||
puts "Error : bad shape"
|
||||
}
|
||||
|
||||
if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck Extrude_path3039]] == 1 } {
|
||||
set log2 [string trim [bopcheck Extrude_path3039]]
|
||||
if {$log2 != "This shape seems to be OK."} {
|
||||
puts "Error : Wire of BSplines fails bopcheck"
|
||||
}
|
||||
|
||||
|
13
tests/evolved/begin
Normal file
13
tests/evolved/begin
Normal file
@@ -0,0 +1,13 @@
|
||||
# To prevent loops limit to 10 minutes
|
||||
cpulimit 60
|
||||
|
||||
if { [array get Draw_Groups "TOPOLOGY Feature commands"] == "" } {
|
||||
pload TOPTEST
|
||||
}
|
||||
|
||||
if { [info exists imagedir] == 0 } {
|
||||
set imagedir .
|
||||
}
|
||||
if { [info exists test_image ] == 0 } {
|
||||
set test_image photo
|
||||
}
|
2
tests/evolved/end
Normal file
2
tests/evolved/end
Normal file
@@ -0,0 +1,2 @@
|
||||
# to end a test script
|
||||
puts "TEST COMPLETED"
|
1
tests/evolved/evolved/begin
Normal file
1
tests/evolved/evolved/begin
Normal file
@@ -0,0 +1 @@
|
||||
set subgroup evolved
|
11
tests/evolved/evolved/bug26470_1
Normal file
11
tests/evolved/evolved/bug26470_1
Normal file
@@ -0,0 +1,11 @@
|
||||
puts "========"
|
||||
puts "OCC26470"
|
||||
puts "========"
|
||||
puts ""
|
||||
##################################################
|
||||
# BRepFill_Evolved: exception and invalid result
|
||||
##################################################
|
||||
|
||||
restore [locate_data_file OCC26470-ClosedWire.brep] a
|
||||
restore [locate_data_file OCC26470-wprof1.brep] b
|
||||
evolved res -s a -p b -a
|
12
tests/evolved/evolved/bug26470_2
Normal file
12
tests/evolved/evolved/bug26470_2
Normal file
@@ -0,0 +1,12 @@
|
||||
puts "========"
|
||||
puts "OCC26470"
|
||||
puts "========"
|
||||
puts ""
|
||||
##################################################
|
||||
# BRepFill_Evolved: exception and invalid result
|
||||
##################################################
|
||||
|
||||
restore [locate_data_file OCC26470-ClosedWire.brep] a
|
||||
restore [locate_data_file OCC26470-wprof2.brep] b
|
||||
evolved res -s a -p b -a
|
||||
checkshape res
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user