1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-03 14:10:33 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
oan
a552a72514 0033866: Foundation Classes - BVH::SurfaceCalculator::Area() fails to calculate area of transformed box
Use absolute values of intermediate calculations to compute surface area of a box, so they do not diminish each other.
2025-01-30 15:35:15 +00:00
17 changed files with 27 additions and 246 deletions

View File

@@ -38,17 +38,17 @@ If HTML documentation is not available in your package, you can:
- **Generate together with sources:** You need to have CMake and 1.8.4 (or above) installed on your system. Enable `BUILD_DOC_Overview` CMake parameter and set the path to Doxygen `3RDPARTY_DOXYGEN_EXECUTABLE`. Then build ALL or only `Overview`. - **Generate together with sources:** You need to have CMake and 1.8.4 (or above) installed on your system. Enable `BUILD_DOC_Overview` CMake parameter and set the path to Doxygen `3RDPARTY_DOXYGEN_EXECUTABLE`. Then build ALL or only `Overview`.
- **Read documentation in source plain text (Markdown) format** found in the subfolder `dox` or [GitHub Wiki](https://github.com/Open-Cascade-SAS/OCCT/wiki). - **Read documentation in source plain text (Markdown) format** found in the subfolder `dox` or [GitHub Wiki](https://github.com/Open-Cascade-SAS/OCCT/wiki).
See [dox/build/build_documentation/building_documentation.md](dox/build/build_documentation/building_documentation.md) or [Building Documentation](https://dev.opencascade.org/doc/occt-7.8.0/overview/html/build_upgrade__building_documentation.html) for details. See `dox/dev_guides/documentation/documentation.md` or [Building Documentation](https://dev.opencascade.org/doc/occt-7.8.0/overview/html/build_upgrade__building_documentation.html) for details.
## Building ## Building
In most cases, you need to rebuild OCCT on your platform (OS, compiler) before using it in your project to ensure binary compatibility. In most cases, you need to rebuild OCCT on your platform (OS, compiler) before using it in your project to ensure binary compatibility.
Consult the file [dox/build/build_occt/building_occt.md](dox/build/build_occt/building_occt.md) or [Building OCCT](https://dev.opencascade.org/doc/overview/html/build_upgrade__building_occt.html) or [Building OCCT Wiki](https://github.com/Open-Cascade-SAS/OCCT/wiki/build_upgrade) for instructions on building OCCT from sources on supported platforms. Consult the file `dox/dev_guides/building/building.md` or [Building OCCT](https://dev.opencascade.org/doc/overview/html/build_upgrade__building_occt.html) or [Building OCCT Wiki](https://github.com/Open-Cascade-SAS/OCCT/wiki/build_upgrade) for instructions on building OCCT from sources on supported platforms.
## Version ## Version
The current version of OCCT can be found in the file [`src/Standard/Standard_Version.hxx`](src/Standard/Standard_Version.hxx). The current version of OCCT can be found in the file `src/Standard/Standard_Version.hxx`.
## Development ## Development

View File

@@ -119,12 +119,6 @@ static TopoDS_Wire WireFromList(TopTools_ListOfShape& Edges)
break; break;
} }
} }
if (!itl.More())
{
Message::SendWarning() << "Warning: WireFromList: can't find the next edge. The wire is not "
"complete, some edges are lost.";
break;
}
BB.Add(aWire, anEdge); BB.Add(aWire, anEdge);
Edges.Remove(itl); Edges.Remove(itl);
} }
@@ -563,13 +557,6 @@ void BRepFill_Filling::Build()
myTolAng, myTolAng,
myTolCurv, myTolCurv,
myAnisotropie)); myAnisotropie));
if (myBoundary.IsEmpty())
{
myIsDone = Standard_False;
return;
}
TopoDS_Edge CurEdge; TopoDS_Edge CurEdge;
TopoDS_Face CurFace; TopoDS_Face CurFace;
Standard_Integer i, j; Standard_Integer i, j;

View File

@@ -773,7 +773,6 @@ void BRepLib_MakeEdge::Init(const Handle(Geom_Curve)& CC,
} }
B.Range(E, p1, p2); B.Range(E, p1, p2);
B.Degenerated(E, degenerated); B.Degenerated(E, degenerated);
E.Closed(closed);
myError = BRepLib_EdgeDone; myError = BRepLib_EdgeDone;
Done(); Done();

View File

@@ -1899,9 +1899,9 @@ Standard_Boolean BRepOffset_Tool::TryProject(const TopoDS_Face& F1,
{ {
BRepLib::BuildCurve3d(CurE, BRep_Tool::Tolerance(CurE)); BRepLib::BuildCurve3d(CurE, BRep_Tool::Tolerance(CurE));
C = BRep_Tool::Curve(CurE, L, f, l); C = BRep_Tool::Curve(CurE, L, f, l);
if (C.IsNull()) // not 3d curve, can be degenerated, need to skip if (C.IsNull())
{ {
continue; return Standard_False;
} }
} }
C = new Geom_TrimmedCurve(C, f, l); C = new Geom_TrimmedCurve(C, f, l);

View File

@@ -515,16 +515,15 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewPolygon(const TopoDS_Edg
Standard_Real aFirst, aLast; Standard_Real aFirst, aLast;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aFirst, aLast); Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aFirst, aLast);
Handle(Geom_Curve) aNewCurve = newCurve(myMap, theEdge, aFirst, aLast); Handle(Geom_Curve) aNewCurve = newCurve(myMap, theEdge, aFirst, aLast);
if (aCurve.IsNull() || aNewCurve.IsNull()) // skip processing degenerated edges if (!aCurve.IsNull() && !aNewCurve.IsNull()) // skip processing degenerated edges
{ {
return Standard_False; TColStd_Array1OfReal& aParams = thePoly->ChangeParameters();
} for (Standard_Integer anInd = aParams.Lower(); anInd <= aParams.Upper(); ++anInd)
TColStd_Array1OfReal& aParams = thePoly->ChangeParameters(); {
for (Standard_Integer anInd = aParams.Lower(); anInd <= aParams.Upper(); ++anInd) Standard_Real& aParam = aParams(anInd);
{ gp_Pnt aPoint = aCurve->Value(aParam);
Standard_Real& aParam = aParams(anInd); newParameter(aPoint, aNewCurve, aFirst, aLast, aTol, aParam);
gp_Pnt aPoint = aCurve->Value(aParam); }
newParameter(aPoint, aNewCurve, aFirst, aLast, aTol, aParam);
} }
} }
return Standard_True; return Standard_True;

View File

@@ -427,11 +427,11 @@ struct SurfaceCalculator<T, 2>
{ {
static T Area(const typename BVH_Box<T, 2>::BVH_VecNt& theSize) static T Area(const typename BVH_Box<T, 2>::BVH_VecNt& theSize)
{ {
const T anArea = theSize.x() * theSize.y(); const T anArea = std::abs (theSize.x() * theSize.y());
if (anArea < std::numeric_limits<T>::epsilon()) if (anArea < std::numeric_limits<T>::epsilon())
{ {
return theSize.x() + theSize.y(); return std::abs (theSize.x()) + std::abs (theSize.y());
} }
return anArea; return anArea;
@@ -444,12 +444,14 @@ struct SurfaceCalculator<T, 3>
static T Area(const typename BVH_Box<T, 3>::BVH_VecNt& theSize) static T Area(const typename BVH_Box<T, 3>::BVH_VecNt& theSize)
{ {
const T anArea = const T anArea =
(theSize.x() * theSize.y() + theSize.x() * theSize.z() + theSize.z() * theSize.y()) (std::abs (theSize.x() * theSize.y()) +
std::abs (theSize.x() * theSize.z()) +
std::abs (theSize.z() * theSize.y()))
* static_cast<T>(2.0); * static_cast<T>(2.0);
if (anArea < std::numeric_limits<T>::epsilon()) if (anArea < std::numeric_limits<T>::epsilon())
{ {
return theSize.x() + theSize.y() + theSize.z(); return std::abs (theSize.x()) + std::abs (theSize.y()) + std::abs (theSize.z());
} }
return anArea; return anArea;
@@ -462,12 +464,14 @@ struct SurfaceCalculator<T, 4>
static T Area(const typename BVH_Box<T, 4>::BVH_VecNt& theSize) static T Area(const typename BVH_Box<T, 4>::BVH_VecNt& theSize)
{ {
const T anArea = const T anArea =
(theSize.x() * theSize.y() + theSize.x() * theSize.z() + theSize.z() * theSize.y()) (std::abs (theSize.x() * theSize.y()) +
std::abs (theSize.x() * theSize.z()) +
std::abs (theSize.z() * theSize.y()))
* static_cast<T>(2.0); * static_cast<T>(2.0);
if (anArea < std::numeric_limits<T>::epsilon()) if (anArea < std::numeric_limits<T>::epsilon())
{ {
return theSize.x() + theSize.y() + theSize.z(); return std::abs (theSize.x()) + std::abs (theSize.y()) + std::abs (theSize.z());
} }
return anArea; return anArea;

View File

@@ -439,7 +439,7 @@ void GeomPlate_BuildAveragePlane::BasePlan(const gp_Vec& OZ)
|| ((Abs(n1) <= myTol) && (Abs(n3) <= myTol))) || ((Abs(n1) <= myTol) && (Abs(n3) <= myTol)))
{ {
myOX.SetCoord(V3(1), V3(2), V3(3)); myOX.SetCoord(V3(1), V3(2), V3(3));
myOY = OZ ^ myOX; myOY.SetCoord(0, 0, 0);
} }
else else
{ {

View File

@@ -195,11 +195,8 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_Surface)& S1,
aProjectedCurve.FirstParameter(), aProjectedCurve.FirstParameter(),
aProjectedCurve.LastParameter()); aProjectedCurve.LastParameter());
Geom2dInt_GInter Intersector(AC, Precision::Confusion(), Precision::Confusion()); Geom2dInt_GInter Intersector(AC, Precision::Confusion(), Precision::Confusion());
if (Intersector.IsDone() if (Intersector.IsDone() && Intersector.IsEmpty())
&& (Intersector.IsEmpty() || (AC.IsClosed() && Intersector.NbPoints() == 1)))
{
break; break;
}
} }
Standard_FALLTHROUGH Standard_FALLTHROUGH
default: { default: {

View File

@@ -66,9 +66,6 @@
#include <TDataStd_Name.hxx> #include <TDataStd_Name.hxx>
#include <AppCont_Function.hxx> #include <AppCont_Function.hxx>
#include <math_ComputeKronrodPointsAndWeights.hxx> #include <math_ComputeKronrodPointsAndWeights.hxx>
#include <STEPCAFControl_Writer.hxx>
#include <STEPCAFControl_Controller.hxx>
#include <ShapeAnalysis_ShapeContents.hxx>
#include <limits> #include <limits>
@@ -4926,155 +4923,6 @@ static Standard_Integer OCC33048(Draw_Interpretor&, Standard_Integer, const char
return 0; return 0;
} }
//=================================================================================================
static Standard_Integer OCC33657_1(Draw_Interpretor&, Standard_Integer, const char**)
{
STEPCAFControl_Controller::Init();
// Checking constructors working in parallel.
OSD_Parallel::For(0, 1000, [](int) {
STEPCAFControl_Reader aReader;
aReader.SetColorMode(true);
STEPCAFControl_Writer aWriter;
aWriter.SetDimTolMode(true);
});
return 0;
}
//=================================================================================================
static Standard_Integer OCC33657_2(Draw_Interpretor& theDI,
Standard_Integer theArgC,
const char** theArgV)
{
if (theArgC < 2)
{
theDI << "Use: " << theArgV[0] << " file\n";
return 1;
}
STEPCAFControl_Controller::Init();
// Checking readers working in parallel.
OSD_Parallel::For(0, 100, [&](int) {
STEPControl_Reader aReader;
aReader.ReadFile(theArgV[1], DESTEP_Parameters{});
aReader.TransferRoots();
});
return 0;
}
//=================================================================================================
static Standard_Integer OCC33657_3(Draw_Interpretor&, Standard_Integer, const char**)
{
STEPCAFControl_Controller::Init();
const TopoDS_Shape aShape = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape();
// Checking writers working in parallel.
OSD_Parallel::For(0, 100, [&](int) {
STEPControl_Writer aWriter;
aWriter.Transfer(aShape, STEPControl_StepModelType::STEPControl_AsIs, DESTEP_Parameters{});
std::ostringstream aStream;
aWriter.WriteStream(aStream);
});
return 0;
}
//=================================================================================================
static Standard_Integer OCC33657_4(Draw_Interpretor& theDI,
Standard_Integer theArgC,
const char** theArgV)
{
if (theArgC < 2)
{
theDI << "Use: " << theArgV[0] << " file\n";
return 1;
}
STEPCAFControl_Controller::Init();
// Acquire shape to write/read.
STEPControl_Reader aReader;
aReader.ReadFile(theArgV[1], DESTEP_Parameters{});
aReader.TransferRoots();
TopoDS_Shape aSourceShape = aReader.OneShape();
// Analyzer to compare the shape with the the same shape after write-read sequence.
ShapeAnalysis_ShapeContents aSourceAnalyzer;
aSourceAnalyzer.Perform(aSourceShape);
// Flag is set to false if any error is detected.
// Reads and writes to the flag are performed exclusively in relaxed memory order
// in order to avoid inter-thread syncronization that can potentially omit some problems.
std::atomic_bool anErrorOccurred(false);
OSD_Parallel::For(0, 100, [&](int) {
if (anErrorOccurred.load(std::memory_order_relaxed))
{
return;
}
// Writing.
STEPControl_Writer aWriter;
aWriter.Transfer(aSourceShape,
STEPControl_StepModelType::STEPControl_AsIs,
DESTEP_Parameters{});
std::stringstream aStream;
aWriter.WriteStream(aStream);
// Reading.
STEPControl_Reader aReader;
aReader.ReadStream("", DESTEP_Parameters{}, aStream);
aReader.TransferRoots();
const TopoDS_Shape aResultShape = aReader.OneShape();
ShapeAnalysis_ShapeContents aResultAnalyzer;
aResultAnalyzer.Perform(aResultShape);
// Making sure that shape is unchanged.
if (aSourceAnalyzer.NbSolids() != aResultAnalyzer.NbSolids())
{
theDI << "Error: Wrong number of solids in the result shape.\nExpected: "
<< aSourceAnalyzer.NbSolids() << "\nActual" << aResultAnalyzer.NbSolids() << "\n";
anErrorOccurred.store(true, std::memory_order_relaxed);
}
if (aSourceAnalyzer.NbShells() != aResultAnalyzer.NbShells())
{
theDI << "Error: Wrong number of shells in the result shape.\nExpected: "
<< aSourceAnalyzer.NbShells() << "\nActual" << aResultAnalyzer.NbShells() << "\n";
anErrorOccurred.store(true, std::memory_order_relaxed);
}
if (aSourceAnalyzer.NbFaces() != aResultAnalyzer.NbFaces())
{
theDI << "Error: Wrong number of faces in the result shape.\nExpected: "
<< aSourceAnalyzer.NbFaces() << "\nActual" << aResultAnalyzer.NbFaces() << "\n";
anErrorOccurred.store(true, std::memory_order_relaxed);
}
if (aSourceAnalyzer.NbWires() != aResultAnalyzer.NbWires())
{
theDI << "Error: Wrong number of wires in the result shape.\nExpected: "
<< aSourceAnalyzer.NbWires() << "\nActual" << aResultAnalyzer.NbWires() << "\n";
anErrorOccurred.store(true, std::memory_order_relaxed);
}
if (aSourceAnalyzer.NbEdges() != aResultAnalyzer.NbEdges())
{
theDI << "Error: Wrong number of edges in the result shape.\nExpected: "
<< aSourceAnalyzer.NbEdges() << "\nActual" << aResultAnalyzer.NbEdges() << "\n";
anErrorOccurred.store(true, std::memory_order_relaxed);
}
if (aSourceAnalyzer.NbVertices() != aResultAnalyzer.NbVertices())
{
theDI << "Error: Wrong number of vertices in the result shape.\nExpected: "
<< aSourceAnalyzer.NbVertices() << "\nActual" << aResultAnalyzer.NbVertices() << "\n";
anErrorOccurred.store(true, std::memory_order_relaxed);
}
});
return anErrorOccurred;
}
//======================================================================= //=======================================================================
// function : QACheckBends // function : QACheckBends
// purpose : // purpose :
@@ -5435,30 +5283,5 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands)
OCC26441, OCC26441,
group); group);
theCommands.Add(
"OCC33657_1",
"Check performance of STEPCAFControl_Reader/Writer constructors in multithreading environment.",
__FILE__,
OCC33657_1,
group);
theCommands.Add("OCC33657_2",
"Check performance of STEPControl_Reader in multithreading environment.",
__FILE__,
OCC33657_2,
group);
theCommands.Add("OCC33657_3",
"Check performance of STEPControl_Writer in multithreading environment.",
__FILE__,
OCC33657_3,
group);
theCommands.Add("OCC33657_4",
"Check performance of STEPControl_Reader/Writer in multithreading environment.",
__FILE__,
OCC33657_4,
group);
return; return;
} }

View File

@@ -31,7 +31,6 @@
#include <Standard_ErrorHandler.hxx> #include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx> #include <Standard_Failure.hxx>
#include <Standard_Mutex.hxx>
#include <Message.hxx> #include <Message.hxx>
#include <Message_Messenger.hxx> #include <Message_Messenger.hxx>
@@ -47,11 +46,6 @@
#define CHRONOMESURE #define CHRONOMESURE
#endif #endif
namespace
{
static Standard_Mutex THE_GLOBAL_READ_MUTEX;
}
void StepFile_Interrupt(Standard_CString theErrorMessage, const Standard_Boolean theIsFail) void StepFile_Interrupt(Standard_CString theErrorMessage, const Standard_Boolean theIsFail)
{ {
if (theErrorMessage == NULL) if (theErrorMessage == NULL)
@@ -119,8 +113,7 @@ static Standard_Integer StepFile_Read(const char* the
sout << " ... STEP File Read ...\n"; sout << " ... STEP File Read ...\n";
Standard_Mutex::Sentry aLocker(THE_GLOBAL_READ_MUTEX); Standard_Integer nbhead, nbrec, nbpar;
Standard_Integer nbhead, nbrec, nbpar;
aFileDataModel.GetFileNbR(&nbhead, &nbrec, &nbpar); // renvoi par lex/yacc aFileDataModel.GetFileNbR(&nbhead, &nbrec, &nbpar); // renvoi par lex/yacc
Handle(StepData_StepReaderData) undirec = Handle(StepData_StepReaderData) undirec =
// clang-format off // clang-format off

View File

@@ -32,9 +32,6 @@
IMPLEMENT_STANDARD_RTTIEXT(XSControl_WorkSession, IFSelect_WorkSession) IMPLEMENT_STANDARD_RTTIEXT(XSControl_WorkSession, IFSelect_WorkSession)
// Initializing static mutex.
Standard_Mutex XSControl_WorkSession::myGlobalMutex;
//================================================================================================= //=================================================================================================
XSControl_WorkSession::XSControl_WorkSession() XSControl_WorkSession::XSControl_WorkSession()
@@ -70,7 +67,6 @@ void XSControl_WorkSession::ClearData(const Standard_Integer mode)
Standard_Boolean XSControl_WorkSession::SelectNorm(const Standard_CString normname) Standard_Boolean XSControl_WorkSession::SelectNorm(const Standard_CString normname)
{ {
const Standard_Mutex::Sentry aMutexLock(myGlobalMutex);
// Old norm and results // Old norm and results
myTransferReader->Clear(-1); myTransferReader->Clear(-1);
// ???? En toute rigueur, menage a faire dans XWS : virer les items // ???? En toute rigueur, menage a faire dans XWS : virer les items
@@ -428,7 +424,6 @@ Standard_Integer XSControl_WorkSession::TransferReadRoots(const Message_Progress
Handle(Interface_InterfaceModel) XSControl_WorkSession::NewModel() Handle(Interface_InterfaceModel) XSControl_WorkSession::NewModel()
{ {
const Standard_Mutex::Sentry aMutexLock(myGlobalMutex);
Handle(Interface_InterfaceModel) newmod; Handle(Interface_InterfaceModel) newmod;
if (myController.IsNull()) if (myController.IsNull())
return newmod; return newmod;
@@ -451,8 +446,7 @@ IFSelect_ReturnStatus XSControl_WorkSession::TransferWriteShape(
const Standard_Boolean compgraph, const Standard_Boolean compgraph,
const Message_ProgressRange& theProgress) const Message_ProgressRange& theProgress)
{ {
const Standard_Mutex::Sentry aMutexLock(myGlobalMutex); IFSelect_ReturnStatus status;
IFSelect_ReturnStatus status;
if (myController.IsNull()) if (myController.IsNull())
return IFSelect_RetError; return IFSelect_RetError;
const Handle(Interface_InterfaceModel)& model = Model(); const Handle(Interface_InterfaceModel)& model = Model();

View File

@@ -196,14 +196,11 @@ private:
//! Clears binders //! Clears binders
Standard_EXPORT void ClearBinders(); Standard_EXPORT void ClearBinders();
private:
Handle(XSControl_Controller) myController; Handle(XSControl_Controller) myController;
Handle(XSControl_TransferReader) myTransferReader; Handle(XSControl_TransferReader) myTransferReader;
Handle(XSControl_TransferWriter) myTransferWriter; Handle(XSControl_TransferWriter) myTransferWriter;
XSControl_WorkSessionMap myContext; XSControl_WorkSessionMap myContext;
Handle(XSControl_Vars) myVars; Handle(XSControl_Vars) myVars;
static Standard_Mutex myGlobalMutex; //!< Mutex to prevent data races during reading and writing.
}; };
#endif // _XSControl_WorkSession_HeaderFile #endif // _XSControl_WorkSession_HeaderFile

View File

@@ -1,5 +1,4 @@
pload XDE pload XDE
pload QAcommands
set subgroup step set subgroup step

View File

@@ -1,3 +0,0 @@
# Check performance of STEPCAFControl_Reader/Writer constructors in multithreading environment.
# If no crash occures, its fine.
OCC33657_1

View File

@@ -1,3 +0,0 @@
# Check performance of STEPControl_Reader in multithreading environment.
# If no crash occures, its fine.
OCC33657_2 [locate_data_file bug21802_as1-oc-214.stp]

View File

@@ -1,3 +0,0 @@
# Check performance of STEPControl_Writer in multithreading environment.
# If no crash occures, its fine.
OCC33657_1

View File

@@ -1,2 +0,0 @@
# Check performance of STEPControl_Reader/Writer in multithreading environment.
OCC33657_4 [locate_data_file bug21802_as1-oc-214.stp]