mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-27 00:58:59 +08:00
Testing - Migration QADraw tests to GTests (#1235)
- Removed multiple legacy DRAW test scripts and several QABugs DRAW command implementations. - Added new GTest suites covering the migrated regressions in ModelingData/ModelingAlgorithms/FoundationClasses/DataExchange/ApplicationFramework. - Updated multiple `FILES.cmake` lists to compile/link the new tests; introduced an additional `STEPControl_Writer::SetShapeFixParameters()` overload.
This commit is contained in:
@@ -507,3 +507,31 @@ TEST_F(TObj_ObjectTest, FindObject_ByName)
|
||||
ASSERT_FALSE(aFound.IsNull());
|
||||
EXPECT_EQ(anObj.get(), aFound.get());
|
||||
}
|
||||
|
||||
// OCC31320: TObj - method TObj_Object::GetFatherObject() is not protected against deleted object
|
||||
// After detaching a parent object, GetFatherObject() on its child must return null.
|
||||
TEST_F(TObj_ObjectTest, OCC31320_GetFatherObject_ReturnsNull_AfterParentDetach)
|
||||
{
|
||||
// Create the parent object inside the model partition.
|
||||
myModel->OpenCommand();
|
||||
occ::handle<TObj_TestObject> aParent = createObject();
|
||||
ASSERT_FALSE(aParent.IsNull());
|
||||
myModel->CommitCommand();
|
||||
|
||||
// Create a child object on a sub-label of the parent's child collection.
|
||||
myModel->OpenCommand();
|
||||
TDF_Label aChildLabel = aParent->GetChildLabel().NewChild();
|
||||
occ::handle<TObj_TestObject> aChild = new TObj_TestObject(aChildLabel);
|
||||
ASSERT_FALSE(aChild.IsNull());
|
||||
myModel->CommitCommand();
|
||||
|
||||
// Detach the parent - this is what the original bug was about.
|
||||
myModel->OpenCommand();
|
||||
EXPECT_TRUE(aParent->Detach());
|
||||
myModel->CommitCommand();
|
||||
|
||||
// After the parent is detached its TObj attributes are gone,
|
||||
// so GetFatherObject() traversing up must return null, not crash.
|
||||
occ::handle<TObj_Object> aFather = aChild->GetFatherObject();
|
||||
EXPECT_TRUE(aFather.IsNull());
|
||||
}
|
||||
|
||||
@@ -16,4 +16,5 @@ set(OCCT_TKDESTEP_GTests_FILES
|
||||
StepTidy_VectorReducer_Test.cxx
|
||||
StepToTopoDS_TranslateFace_Test.cxx
|
||||
StepTransientReplacements_Test.cxx
|
||||
STEPCAFControl_Controller_Test.cxx
|
||||
)
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <sstream>
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
#include <TDF_Label.hxx>
|
||||
#include <DESTEP_Parameters.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Quantity_Color.hxx>
|
||||
#include <ShapeAnalysis_ShapeContents.hxx>
|
||||
#include <STEPCAFControl_Controller.hxx>
|
||||
#include <STEPCAFControl_Reader.hxx>
|
||||
#include <STEPCAFControl_Writer.hxx>
|
||||
#include <STEPControl_Reader.hxx>
|
||||
#include <STEPControl_StepModelType.hxx>
|
||||
#include <STEPControl_Writer.hxx>
|
||||
#include <TDataStd_Name.hxx>
|
||||
#include <TDocStd_Document.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <XCAFDoc_ColorTool.hxx>
|
||||
#include <XCAFDoc_DocumentTool.hxx>
|
||||
#include <XCAFDoc_ShapeTool.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
|
||||
// Test OCC33657 (case 1): STEPCAFControl_Reader and STEPCAFControl_Writer constructors
|
||||
// can be created and destroyed in parallel without crashing.
|
||||
TEST(STEPCAFControl_ControllerTest, OCC33657_ParallelConstructors)
|
||||
{
|
||||
STEPCAFControl_Controller::Init();
|
||||
EXPECT_NO_FATAL_FAILURE(OSD_Parallel::For(0, 1000, [](int) {
|
||||
STEPCAFControl_Reader aReader;
|
||||
aReader.SetColorMode(true);
|
||||
STEPCAFControl_Writer aWriter;
|
||||
aWriter.SetDimTolMode(true);
|
||||
}));
|
||||
}
|
||||
|
||||
// Test OCC33657 (case 3): STEPControl_Writer can write in parallel to in-memory buffers.
|
||||
// Each thread creates its own shape and writer to avoid shared-state issues.
|
||||
TEST(STEPCAFControl_ControllerTest, OCC33657_ParallelWritersToBuffer)
|
||||
{
|
||||
STEPCAFControl_Controller::Init();
|
||||
std::atomic<bool> allOk{true};
|
||||
EXPECT_NO_FATAL_FAILURE(OSD_Parallel::For(0, 100, [&](int) {
|
||||
const TopoDS_Shape aShape = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape();
|
||||
STEPControl_Writer aWriter;
|
||||
aWriter.SetShapeFixParameters(DESTEP_Parameters::GetDefaultShapeFixParameters());
|
||||
aWriter.Transfer(aShape, STEPControl_StepModelType::STEPControl_AsIs, DESTEP_Parameters{});
|
||||
std::ostringstream aStream;
|
||||
aWriter.WriteStream(aStream);
|
||||
if (aStream.str().empty())
|
||||
allOk = false;
|
||||
}));
|
||||
EXPECT_TRUE(allOk);
|
||||
}
|
||||
|
||||
// Test OCC33657 (case 2): STEPControl_Reader can read a STEP stream in parallel without crashing.
|
||||
TEST(STEPCAFControl_ControllerTest, OCC33657_ParallelReadersFromStream)
|
||||
{
|
||||
STEPCAFControl_Controller::Init();
|
||||
|
||||
// Write a box to a STEP stream once, then read it in parallel.
|
||||
const TopoDS_Shape aShape = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape();
|
||||
STEPControl_Writer aWriter;
|
||||
aWriter.Transfer(aShape, STEPControl_StepModelType::STEPControl_AsIs, DESTEP_Parameters{});
|
||||
std::ostringstream anOutStream;
|
||||
aWriter.WriteStream(anOutStream);
|
||||
const std::string aStepContent = anOutStream.str();
|
||||
ASSERT_FALSE(aStepContent.empty()) << "STEP content should not be empty";
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(OSD_Parallel::For(0, 100, [&](int) {
|
||||
std::istringstream anInStream(aStepContent);
|
||||
STEPControl_Reader aReader;
|
||||
aReader.ReadStream("", DESTEP_Parameters{}, anInStream);
|
||||
aReader.TransferRoots();
|
||||
}));
|
||||
}
|
||||
|
||||
// Test OCC33657 (case 4): STEPControl_Writer and STEPControl_Reader work in parallel
|
||||
// and produce a shape with the same topology as the source.
|
||||
TEST(STEPCAFControl_ControllerTest, OCC33657_ParallelReadersAndWriters)
|
||||
{
|
||||
STEPCAFControl_Controller::Init();
|
||||
|
||||
// Acquire source shape and analyze its topology.
|
||||
const TopoDS_Shape aSourceShape = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape();
|
||||
ShapeAnalysis_ShapeContents aSourceAnalyzer;
|
||||
aSourceAnalyzer.Perform(aSourceShape);
|
||||
|
||||
std::atomic<bool> allOk{true};
|
||||
EXPECT_NO_FATAL_FAILURE(OSD_Parallel::For(0, 100, [&](int) {
|
||||
if (!allOk.load(std::memory_order_relaxed))
|
||||
return;
|
||||
|
||||
// Write source shape to a per-thread stream.
|
||||
STEPControl_Writer aWriter;
|
||||
aWriter.Transfer(aSourceShape,
|
||||
STEPControl_StepModelType::STEPControl_AsIs,
|
||||
DESTEP_Parameters{});
|
||||
std::ostringstream anOutStream;
|
||||
aWriter.WriteStream(anOutStream);
|
||||
|
||||
// Read it back and compare topology counts.
|
||||
std::istringstream anInStream(anOutStream.str());
|
||||
STEPControl_Reader aReader;
|
||||
aReader.ReadStream("", DESTEP_Parameters{}, anInStream);
|
||||
aReader.TransferRoots();
|
||||
const TopoDS_Shape aResultShape = aReader.OneShape();
|
||||
|
||||
ShapeAnalysis_ShapeContents aResultAnalyzer;
|
||||
aResultAnalyzer.Perform(aResultShape);
|
||||
|
||||
if (aSourceAnalyzer.NbSolids() != aResultAnalyzer.NbSolids()
|
||||
|| aSourceAnalyzer.NbShells() != aResultAnalyzer.NbShells()
|
||||
|| aSourceAnalyzer.NbFaces() != aResultAnalyzer.NbFaces()
|
||||
|| aSourceAnalyzer.NbWires() != aResultAnalyzer.NbWires()
|
||||
|| aSourceAnalyzer.NbEdges() != aResultAnalyzer.NbEdges()
|
||||
|| aSourceAnalyzer.NbVertices() != aResultAnalyzer.NbVertices())
|
||||
{
|
||||
allOk.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
}));
|
||||
EXPECT_TRUE(allOk);
|
||||
}
|
||||
|
||||
// Test OCC23951: STEPCAFControl_Writer can write an XCAF document with a box
|
||||
// whose visibility is set to false. Verifies the write completes successfully.
|
||||
TEST(STEPCAFControl_ControllerTest, OCC23951_WriteDocumentWithVisibility)
|
||||
{
|
||||
STEPCAFControl_Controller::Init();
|
||||
|
||||
occ::handle<TDocStd_Document> aDoc = new TDocStd_Document("dummy");
|
||||
const TopoDS_Shape aBox = BRepPrimAPI_MakeBox(1, 1, 1).Shape();
|
||||
|
||||
occ::handle<XCAFDoc_ShapeTool> aShapeTool = XCAFDoc_DocumentTool::ShapeTool(aDoc->Main());
|
||||
TDF_Label aLab1 = aShapeTool->NewShape();
|
||||
aShapeTool->SetShape(aLab1, aBox);
|
||||
TDataStd_Name::Set(aLab1, "Box1");
|
||||
|
||||
Quantity_Color aYellow(Quantity_NOC_YELLOW);
|
||||
XCAFDoc_DocumentTool::ColorTool(aDoc->Main())->SetColor(aLab1, aYellow, XCAFDoc_ColorGen);
|
||||
XCAFDoc_DocumentTool::ColorTool(aDoc->Main())->SetVisibility(aLab1, false);
|
||||
|
||||
STEPCAFControl_Writer aWriter;
|
||||
ASSERT_TRUE(aWriter.Transfer(aDoc)) << "Transfer failed";
|
||||
|
||||
std::ostringstream aStream;
|
||||
const IFSelect_ReturnStatus aStatus = aWriter.WriteStream(aStream);
|
||||
EXPECT_EQ(aStatus, IFSelect_RetDone) << "WriteStream did not return RetDone";
|
||||
EXPECT_FALSE(aStream.str().empty()) << "Written STEP stream should not be empty";
|
||||
|
||||
// Verify yellow color and INVISIBILITY entity are encoded in the STEP stream.
|
||||
// STEP writes predefined colors using DRAUGHTING_PRE_DEFINED_COLOUR, not COLOUR_RGB.
|
||||
const std::string aContent = aStream.str();
|
||||
EXPECT_NE(aContent.find("DRAUGHTING_PRE_DEFINED_COLOUR('yellow')"), std::string::npos)
|
||||
<< "Yellow DRAUGHTING_PRE_DEFINED_COLOUR entity not found in STEP stream";
|
||||
EXPECT_NE(aContent.find("INVISIBILITY"), std::string::npos)
|
||||
<< "INVISIBILITY entity not found in STEP stream";
|
||||
|
||||
// Read back the written stream into an XCAF document and verify shape topology.
|
||||
std::istringstream anInStream(aContent);
|
||||
occ::handle<TDocStd_Document> aReadDoc = new TDocStd_Document("dummy");
|
||||
STEPCAFControl_Reader aCafReader;
|
||||
aCafReader.SetColorMode(true);
|
||||
ASSERT_EQ(aCafReader.ReadStream("", anInStream), IFSelect_RetDone)
|
||||
<< "ReadStream failed on written STEP content";
|
||||
ASSERT_TRUE(aCafReader.Transfer(aReadDoc)) << "Transfer to XCAF document failed";
|
||||
|
||||
occ::handle<XCAFDoc_ShapeTool> aReadShapeTool = XCAFDoc_DocumentTool::ShapeTool(aReadDoc->Main());
|
||||
NCollection_Sequence<TDF_Label> aRoots;
|
||||
aReadShapeTool->GetFreeShapes(aRoots);
|
||||
ASSERT_FALSE(aRoots.IsEmpty()) << "No shapes in read-back document";
|
||||
const TopoDS_Shape aResult = aReadShapeTool->GetShape(aRoots.First());
|
||||
ASSERT_FALSE(aResult.IsNull()) << "Read-back shape should not be null";
|
||||
|
||||
ShapeAnalysis_ShapeContents aSourceAnalyzer;
|
||||
aSourceAnalyzer.Perform(aBox);
|
||||
ShapeAnalysis_ShapeContents aResultAnalyzer;
|
||||
aResultAnalyzer.Perform(aResult);
|
||||
EXPECT_EQ(aResultAnalyzer.NbSolids(), aSourceAnalyzer.NbSolids()) << "Solid count mismatch";
|
||||
EXPECT_EQ(aResultAnalyzer.NbFaces(), aSourceAnalyzer.NbFaces()) << "Face count mismatch";
|
||||
EXPECT_EQ(aResultAnalyzer.NbEdges(), aSourceAnalyzer.NbEdges()) << "Edge count mismatch";
|
||||
EXPECT_EQ(aResultAnalyzer.NbVertices(), aSourceAnalyzer.NbVertices()) << "Vertex count mismatch";
|
||||
|
||||
// Verify yellow color is present on faces of the read-back shape.
|
||||
occ::handle<XCAFDoc_ColorTool> aColorTool = XCAFDoc_DocumentTool::ColorTool(aReadDoc->Main());
|
||||
bool aFoundColor = false;
|
||||
Quantity_Color aReadColor;
|
||||
for (TopExp_Explorer anFaceExp(aResult, TopAbs_FACE); anFaceExp.More(); anFaceExp.Next())
|
||||
{
|
||||
if (aColorTool->GetColor(anFaceExp.Current(), XCAFDoc_ColorSurf, aReadColor)
|
||||
|| aColorTool->GetColor(anFaceExp.Current(), XCAFDoc_ColorGen, aReadColor))
|
||||
{
|
||||
aFoundColor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!aFoundColor)
|
||||
{
|
||||
// If not found on faces, try on the solid shape itself
|
||||
aFoundColor = aColorTool->GetColor(aResult, XCAFDoc_ColorGen, aReadColor)
|
||||
|| aColorTool->GetColor(aResult, XCAFDoc_ColorSurf, aReadColor);
|
||||
}
|
||||
EXPECT_TRUE(aFoundColor) << "Yellow color not found on read-back shape";
|
||||
if (aFoundColor)
|
||||
{
|
||||
EXPECT_NEAR(aReadColor.Red(), aYellow.Red(), 0.05) << "Color red channel mismatch";
|
||||
EXPECT_NEAR(aReadColor.Green(), aYellow.Green(), 0.05) << "Color green channel mismatch";
|
||||
EXPECT_NEAR(aReadColor.Blue(), aYellow.Blue(), 0.05) << "Color blue channel mismatch";
|
||||
}
|
||||
}
|
||||
|
||||
// Test OCC23950: STEPCAFControl_Writer writes vertex names when vertex mode is SingleVertex.
|
||||
// Verifies that the STEP stream contains the expected "Point1" name.
|
||||
TEST(STEPCAFControl_ControllerTest, OCC23950_WriteDocumentWithVertexName)
|
||||
{
|
||||
STEPCAFControl_Controller::Init();
|
||||
|
||||
occ::handle<TDocStd_Document> aDoc = new TDocStd_Document("dummy");
|
||||
const TopoDS_Shape aVertex = BRepBuilderAPI_MakeVertex(gp_Pnt(75, 0, 0));
|
||||
const gp_Trsf aTrsf;
|
||||
const TopLoc_Location aLoc(aTrsf);
|
||||
|
||||
occ::handle<XCAFDoc_ShapeTool> aShapeTool = XCAFDoc_DocumentTool::ShapeTool(aDoc->Main());
|
||||
|
||||
TDF_Label aLab1 = aShapeTool->NewShape();
|
||||
aShapeTool->SetShape(aLab1, aVertex);
|
||||
TDataStd_Name::Set(aLab1, "Point1");
|
||||
|
||||
TDF_Label aAssemblyLabel = aShapeTool->NewShape();
|
||||
TDataStd_Name::Set(aAssemblyLabel, "ASSEMBLY");
|
||||
|
||||
const TDF_Label aComponentLabel = aShapeTool->AddComponent(aAssemblyLabel, aLab1, aLoc);
|
||||
aShapeTool->UpdateAssemblies();
|
||||
|
||||
Quantity_Color aYellow(Quantity_NOC_YELLOW);
|
||||
XCAFDoc_DocumentTool::ColorTool(aDoc->Main())
|
||||
->SetColor(aComponentLabel, aYellow, XCAFDoc_ColorGen);
|
||||
XCAFDoc_DocumentTool::ColorTool(aDoc->Main())->SetVisibility(aComponentLabel, false);
|
||||
|
||||
// Enable writing of individual vertex names
|
||||
DESTEP_Parameters aParams;
|
||||
aParams.WriteVertexMode = DESTEP_Parameters::WriteMode_VertexMode_SingleVertex;
|
||||
|
||||
STEPCAFControl_Writer aWriter;
|
||||
ASSERT_TRUE(aWriter.Transfer(aDoc, aParams)) << "Transfer failed";
|
||||
|
||||
std::ostringstream aStream;
|
||||
const IFSelect_ReturnStatus aStatus = aWriter.WriteStream(aStream);
|
||||
ASSERT_EQ(aStatus, IFSelect_RetDone) << "WriteStream did not return RetDone";
|
||||
|
||||
const std::string aContent = aStream.str();
|
||||
EXPECT_FALSE(aContent.empty()) << "Written STEP stream should not be empty";
|
||||
EXPECT_NE(aContent.find("Point1"), std::string::npos)
|
||||
<< "Vertex name 'Point1' not found in STEP stream";
|
||||
|
||||
// Verify yellow color and INVISIBILITY entity are encoded in the STEP stream.
|
||||
// STEP writes predefined colors using DRAUGHTING_PRE_DEFINED_COLOUR, not COLOUR_RGB.
|
||||
EXPECT_NE(aContent.find("DRAUGHTING_PRE_DEFINED_COLOUR('yellow')"), std::string::npos)
|
||||
<< "Yellow DRAUGHTING_PRE_DEFINED_COLOUR entity not found in STEP stream";
|
||||
EXPECT_NE(aContent.find("INVISIBILITY"), std::string::npos)
|
||||
<< "INVISIBILITY entity not found in STEP stream";
|
||||
|
||||
// Read back the written stream into an XCAF document and verify vertex position.
|
||||
std::istringstream anInStream(aContent);
|
||||
occ::handle<TDocStd_Document> aReadDoc = new TDocStd_Document("dummy");
|
||||
STEPCAFControl_Reader aCafReader;
|
||||
aCafReader.SetColorMode(true);
|
||||
ASSERT_EQ(aCafReader.ReadStream("", anInStream), IFSelect_RetDone)
|
||||
<< "ReadStream failed on written STEP content";
|
||||
ASSERT_TRUE(aCafReader.Transfer(aReadDoc)) << "Transfer to XCAF document failed";
|
||||
|
||||
occ::handle<XCAFDoc_ShapeTool> aReadShapeTool = XCAFDoc_DocumentTool::ShapeTool(aReadDoc->Main());
|
||||
NCollection_Sequence<TDF_Label> aRoots;
|
||||
aReadShapeTool->GetFreeShapes(aRoots);
|
||||
ASSERT_FALSE(aRoots.IsEmpty()) << "No shapes in read-back document";
|
||||
const TopoDS_Shape aRootShape = aReadShapeTool->GetShape(aRoots.First());
|
||||
ASSERT_FALSE(aRootShape.IsNull()) << "Read-back shape should not be null";
|
||||
|
||||
TopExp_Explorer anExp(aRootShape, TopAbs_VERTEX);
|
||||
ASSERT_TRUE(anExp.More()) << "No vertex found in read-back shape";
|
||||
const gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
|
||||
EXPECT_NEAR(aPnt.X(), 75.0, Precision::Confusion()) << "Vertex X coordinate mismatch";
|
||||
EXPECT_NEAR(aPnt.Y(), 0.0, Precision::Confusion()) << "Vertex Y coordinate mismatch";
|
||||
EXPECT_NEAR(aPnt.Z(), 0.0, Precision::Confusion()) << "Vertex Z coordinate mismatch";
|
||||
}
|
||||
@@ -228,6 +228,17 @@ void STEPControl_Writer::SetShapeFixParameters(XSAlgo_ShapeProcessor::ParameterM
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void STEPControl_Writer::SetShapeFixParameters(const DE_ShapeFixParameters& theParameters)
|
||||
{
|
||||
XSAlgo_ShapeProcessor::ParameterMap anAdditionalParameters;
|
||||
if (occ::handle<Transfer_ActorOfFinderProcess> anActor = GetActor())
|
||||
{
|
||||
anActor->SetShapeFixParameters(theParameters, anAdditionalParameters);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
void STEPControl_Writer::SetShapeFixParameters(
|
||||
const DE_ShapeFixParameters& theParameters,
|
||||
const XSAlgo_ShapeProcessor::ParameterMap& theAdditionalParameters)
|
||||
|
||||
@@ -142,6 +142,11 @@ public:
|
||||
//! @param theParameters the parameters for shape processing.
|
||||
Standard_EXPORT void SetShapeFixParameters(XSAlgo_ShapeProcessor::ParameterMap&& theParameters);
|
||||
|
||||
//! Sets parameters for shape processing.
|
||||
//! Parameters from @p theParameters are converted and stored in the internal map.
|
||||
//! @param theParameters the parameters for shape processing.
|
||||
Standard_EXPORT void SetShapeFixParameters(const DE_ShapeFixParameters& theParameters);
|
||||
|
||||
//! Sets parameters for shape processing.
|
||||
//! Parameters from @p theParameters are copied to the internal map.
|
||||
//! Parameters from @p theAdditionalParameters are copied to the internal map
|
||||
@@ -150,7 +155,7 @@ public:
|
||||
//! @param theAdditionalParameters the additional parameters for shape processing.
|
||||
Standard_EXPORT void SetShapeFixParameters(
|
||||
const DE_ShapeFixParameters& theParameters,
|
||||
const XSAlgo_ShapeProcessor::ParameterMap& theAdditionalParameters = {});
|
||||
const XSAlgo_ShapeProcessor::ParameterMap& theAdditionalParameters);
|
||||
|
||||
//! Returns parameters for shape processing that was set by SetParameters() method.
|
||||
//! @return the parameters for shape processing. Empty map if no parameters were set.
|
||||
|
||||
@@ -14,7 +14,6 @@ set(OCCT_QABugs_FILES
|
||||
QABugs_9.cxx
|
||||
QABugs_10.cxx
|
||||
QABugs_11.cxx
|
||||
QABugs_12.cxx
|
||||
QABugs_13.cxx
|
||||
QABugs_14.cxx
|
||||
QABugs_16.cxx
|
||||
|
||||
@@ -27,7 +27,6 @@ void QABugs::Commands(Draw_Interpretor& theCommands)
|
||||
QABugs::Commands_9(theCommands);
|
||||
QABugs::Commands_10(theCommands);
|
||||
QABugs::Commands_11(theCommands);
|
||||
QABugs::Commands_12(theCommands);
|
||||
QABugs::Commands_13(theCommands);
|
||||
QABugs::Commands_14(theCommands);
|
||||
QABugs::Commands_16(theCommands);
|
||||
|
||||
@@ -49,8 +49,6 @@ public:
|
||||
|
||||
Standard_EXPORT static void Commands_11(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void Commands_12(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void Commands_13(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void Commands_14(Draw_Interpretor& DI);
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||
|
||||
#include <BRepAlgoAPI_Fuse.hxx>
|
||||
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
@@ -39,10 +37,11 @@
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <Standard_ErrorHandler.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
|
||||
#include <BRepAlgoAPI_Fuse.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <ShapeUpgrade_UnifySameDomain.hxx>
|
||||
|
||||
static int OCC426(Draw_Interpretor& di, int argc, const char** argv)
|
||||
@@ -478,247 +477,24 @@ int performTriangulation(const TopoDS_Shape& aShape, Draw_Interpretor& di)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeCone.hxx>
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static int OCC822_1(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " name1 name2 result\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
|
||||
gp_Pnt P1(0, 0, 0);
|
||||
gp_Dir D1(gp_Dir::D::Z);
|
||||
gp_Ax2 A1(P1, D1);
|
||||
|
||||
BRepPrimAPI_MakeCylinder cylMakerIn(A1, 40, 110);
|
||||
BRepPrimAPI_MakeCylinder cylMakerOut(A1, 50, 100);
|
||||
TopoDS_Shape cylIn = cylMakerIn.Shape();
|
||||
TopoDS_Shape cylOut = cylMakerOut.Shape();
|
||||
|
||||
gp_Pnt P2(0, 0, 0);
|
||||
gp_Dir D2(gp_Dir::D::NZ);
|
||||
gp_Ax2 A2(P2, D2);
|
||||
|
||||
BRepPrimAPI_MakeCone conMakerIn(A2, 40, 60, 110);
|
||||
BRepPrimAPI_MakeCone conMakerOut(A2, 50, 70, 100);
|
||||
TopoDS_Shape conIn = conMakerIn.Shape();
|
||||
TopoDS_Shape conOut = conMakerOut.Shape();
|
||||
|
||||
di << "All primitives created..... Creating Boolean\n";
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
di << "theIn = BRepAlgoAPI_Fuse(cylIn, conIn)\n";
|
||||
di << "theOut = BRepAlgoAPI_Fuse(cylOut, conOut)\n";
|
||||
di << "theRes = BRepAlgoAPI_Cut(theOut, theIn)\n";
|
||||
TopoDS_Shape theIn = BRepAlgoAPI_Fuse(cylIn, conIn).Shape();
|
||||
TopoDS_Shape theOut = BRepAlgoAPI_Fuse(cylOut, conOut).Shape();
|
||||
TopoDS_Shape theRes = BRepAlgoAPI_Cut(theOut, theIn).Shape();
|
||||
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], theIn);
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], theOut);
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], theRes);
|
||||
di << "Booleans Created ! Triangulating !\n";
|
||||
|
||||
performTriangulation(theRes, di);
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
di << "*********************************************************\n";
|
||||
di << "***** ******\n";
|
||||
di << "***** Standard_Failure : Exception in Shoe Function *****\n";
|
||||
di << "***** ******\n";
|
||||
di << "*********************************************************\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
|
||||
//=======================================================================
|
||||
// OCC822_2
|
||||
//=======================================================================
|
||||
|
||||
static int OCC822_2(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " name1 name2 result\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
|
||||
gp_Dir xDir(gp_Dir::D::X);
|
||||
gp_Dir zDir(gp_Dir::D::Z);
|
||||
gp_Pnt cen1(0, 0, 0);
|
||||
gp_Ax2 cor1(cen1, zDir, xDir);
|
||||
BRepPrimAPI_MakeBox boxMaker(cor1, 100, 100, 100);
|
||||
TopoDS_Shape box = boxMaker.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], box);
|
||||
|
||||
BRepPrimAPI_MakeSphere sphereMaker(gp_Pnt(100.0, 50.0, 50.0), 25.0);
|
||||
TopoDS_Shape sph = sphereMaker.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], sph);
|
||||
|
||||
di << "All primitives created..... Creating Cut Objects\n";
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
di << "fuse = BRepAlgoAPI_Fuse(box, sph)\n";
|
||||
TopoDS_Shape fuse = BRepAlgoAPI_Fuse(box, sph).Shape();
|
||||
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], fuse);
|
||||
di << "Object Created ! Now Triangulating !";
|
||||
|
||||
performTriangulation(fuse, di);
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
di << "*********************************************************\n";
|
||||
di << "***** ******\n";
|
||||
di << "***** Standard_Failure : Exception in HSP Function ******\n";
|
||||
di << "***** ******\n";
|
||||
di << "*********************************************************\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// OCC823
|
||||
//=======================================================================
|
||||
|
||||
static int OCC823(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " name1 name2 result\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
double size = 0.001;
|
||||
|
||||
gp_Pnt P1(40, 50, 0);
|
||||
gp_Dir D1(100, 0, 0);
|
||||
gp_Ax2 A1(P1, D1);
|
||||
BRepPrimAPI_MakeCylinder mkCyl1(A1, 20, 100);
|
||||
TopoDS_Shape cyl1 = mkCyl1.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], cyl1);
|
||||
|
||||
gp_Pnt P2(100, 50, size);
|
||||
gp_Dir D2(0, size, 80);
|
||||
gp_Ax2 A2(P2, D2);
|
||||
BRepPrimAPI_MakeCylinder mkCyl2(A2, 20, 80);
|
||||
TopoDS_Shape cyl2 = mkCyl2.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], cyl2);
|
||||
|
||||
di << "All primitives created..... Creating Boolean\n";
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
di << "fuse = BRepAlgoAPI_Fuse(cyl2, cyl1)\n";
|
||||
TopoDS_Shape fuse = BRepAlgoAPI_Fuse(cyl2, cyl1).Shape();
|
||||
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], fuse);
|
||||
di << "Fuse Created ! Triangulating !\n";
|
||||
|
||||
performTriangulation(fuse, di);
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
di << "*********************************************************\n";
|
||||
di << "***** ******\n";
|
||||
di << "***** Standard_Failure : Exception in TEE Function ******\n";
|
||||
di << "***** ******\n";
|
||||
di << "*********************************************************\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// OCC824
|
||||
//=======================================================================
|
||||
|
||||
static int OCC824(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " name1 name2 result\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
|
||||
gp_Pnt P1(100, 0, 0);
|
||||
gp_Dir D1(gp_Dir::D::NX);
|
||||
gp_Ax2 A1(P1, D1);
|
||||
BRepPrimAPI_MakeCylinder mkCyl(A1, 20, 100);
|
||||
TopoDS_Shape cyl = mkCyl.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], cyl);
|
||||
|
||||
BRepPrimAPI_MakeSphere sphere(P1, 20.0);
|
||||
TopoDS_Shape sph = sphere.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], sph);
|
||||
|
||||
di << "All primitives created..... Creating Boolean\n";
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
di << "fuse = BRepAlgoAPI_Fuse(cyl, sph)\n";
|
||||
TopoDS_Shape fuse = BRepAlgoAPI_Fuse(cyl, sph).Shape();
|
||||
|
||||
di << "Fuse Created ! Triangulating !\n";
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], fuse);
|
||||
|
||||
performTriangulation(fuse, di);
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
di << "*********************************************************\n";
|
||||
di << "***** ******\n";
|
||||
di << "***** Standard_Failure : Exception in YOU Function ******\n";
|
||||
di << "***** ******\n";
|
||||
di << "*********************************************************\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <NCollection_Array2.hxx>
|
||||
#include <GeomConvert.hxx>
|
||||
#include <Geom_BezierSurface.hxx>
|
||||
@@ -822,206 +598,12 @@ static int OCC825(Draw_Interpretor& di, int argc, const char** argv)
|
||||
// OCC826
|
||||
//=======================================================================
|
||||
|
||||
static int OCC826(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " name1 name2 result\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
|
||||
double x1 = 181.82808;
|
||||
double x2 = 202.39390;
|
||||
double y1 = 31.011970;
|
||||
double y2 = 123.06856;
|
||||
|
||||
BRepBuilderAPI_MakePolygon W1;
|
||||
W1.Add(gp_Pnt(x1, y1, 0));
|
||||
W1.Add(gp_Pnt(x2, y1, 0));
|
||||
W1.Add(gp_Pnt(x2, y2, 0));
|
||||
W1.Add(gp_Pnt(x1, y2, 0));
|
||||
W1.Add(gp_Pnt(x1, y1, 0));
|
||||
|
||||
bool myFalse = false;
|
||||
TopoDS_Face F1 = BRepBuilderAPI_MakeFace(W1.Wire(), myFalse);
|
||||
|
||||
gp_Pnt P1(0, 0, 0);
|
||||
gp_Dir D1(0, 30, 0);
|
||||
gp_Ax1 A1(P1, D1);
|
||||
double angle1 = 360 * (M_PI / 180.0);
|
||||
TopoDS_Shape rev = BRepPrimAPI_MakeRevol(F1, A1, angle1);
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], rev);
|
||||
|
||||
BRepPrimAPI_MakeSphere sphere(gp_Pnt(166.373, 77.0402, 96.0555), 23.218586);
|
||||
TopoDS_Shape sph = sphere.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], sph);
|
||||
|
||||
di << "All primitives created..... Creating Boolean\n";
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
di << "fuse = BRepAlgoAPI_Fuse(rev, sph)\n";
|
||||
TopoDS_Shape fuse = BRepAlgoAPI_Fuse(rev, sph).Shape();
|
||||
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], fuse);
|
||||
di << "Fuse Created ! Triangulating !\n";
|
||||
performTriangulation(fuse, di);
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
di << "*********************************************************\n";
|
||||
di << "***** ******\n";
|
||||
di << "***** Standard_Failure : Exception in SPH Function ******\n";
|
||||
di << "***** ******\n";
|
||||
di << "*********************************************************\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <BRepPrimAPI_MakeTorus.hxx>
|
||||
|
||||
//=======================================================================
|
||||
// OCC827
|
||||
//=======================================================================
|
||||
|
||||
static int OCC827(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 6)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " name1 name2 name3 result1 result2\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
|
||||
BRepBuilderAPI_MakePolygon W1;
|
||||
W1.Add(gp_Pnt(10, 0, 0));
|
||||
W1.Add(gp_Pnt(20, 0, 0));
|
||||
W1.Add(gp_Pnt(20, 0, 50));
|
||||
W1.Add(gp_Pnt(10, 0, 50));
|
||||
W1.Add(gp_Pnt(10, 0, 0));
|
||||
|
||||
bool myFalse = false;
|
||||
TopoDS_Face F1 = BRepBuilderAPI_MakeFace(W1.Wire(), myFalse);
|
||||
|
||||
gp_Pnt P1(0, 0, 0);
|
||||
gp_Dir D1(0, 0, 30);
|
||||
gp_Ax1 A1(P1, D1);
|
||||
double angle1 = 360 * (M_PI / 180.0);
|
||||
TopoDS_Shape rev = BRepPrimAPI_MakeRevol(F1, A1, angle1);
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], rev);
|
||||
|
||||
gp_Pnt P2(0, 0, 50);
|
||||
gp_Dir D2(0, 0, 30);
|
||||
gp_Ax2 A2(P2, D2);
|
||||
double majRad = 15;
|
||||
double minRad = 5;
|
||||
BRepPrimAPI_MakeTorus Torus1(A2, majRad, minRad);
|
||||
TopoDS_Shape tor1 = Torus1.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], tor1);
|
||||
|
||||
gp_Pnt P3(0, 0, 10);
|
||||
gp_Dir D3(0, 0, 30);
|
||||
gp_Ax2 A3(P3, D3);
|
||||
BRepPrimAPI_MakeTorus Torus2(A3, majRad, minRad);
|
||||
TopoDS_Shape tor2 = Torus2.Shape();
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], tor2);
|
||||
|
||||
di << "All primitives created..... Creating Boolean\n";
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
|
||||
di << "Fuse1 = BRepAlgoAPI_Fuse(tor1, rev)\n";
|
||||
TopoDS_Shape fuse1 = BRepAlgoAPI_Fuse(tor1, rev).Shape();
|
||||
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], fuse1);
|
||||
di << "Fuse1 Created ! Creating Fuse 2\n";
|
||||
|
||||
di << "Fuse2 = BRepAlgoAPI_Fuse(tor2, fuse1)\n";
|
||||
TopoDS_Shape fuse2 = BRepAlgoAPI_Fuse(tor2, fuse1).Shape();
|
||||
|
||||
if (index < argc)
|
||||
DBRep::Set(argv[index++], fuse2);
|
||||
di << "Fuse2 Created ! Triangulating !\n";
|
||||
|
||||
performTriangulation(fuse2, di);
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
di << "*********************************************************\n";
|
||||
di << "***** ******\n";
|
||||
di << "***** Standard_Failure : Exception in REV Function ******\n";
|
||||
di << "***** ******\n";
|
||||
di << "*********************************************************\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// performBlend
|
||||
//=======================================================================
|
||||
|
||||
int performBlend(const TopoDS_Shape& aShape, double rad, TopoDS_Shape& bShape, Draw_Interpretor& di)
|
||||
{
|
||||
int status = 0;
|
||||
TopoDS_Shape newShape;
|
||||
NCollection_IndexedDataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher>
|
||||
edgemap;
|
||||
TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_SOLID, edgemap);
|
||||
di << "Blending All Edges: No. of Edges: " << edgemap.Extent() << "\n";
|
||||
ChFi3d_FilletShape FShape = ChFi3d_Rational;
|
||||
BRepFilletAPI_MakeFillet blend(aShape, FShape);
|
||||
for (int i = 1; i <= edgemap.Extent(); i++)
|
||||
{
|
||||
TopoDS_Edge edg = TopoDS::Edge(edgemap.FindKey(i));
|
||||
if (!edg.IsNull())
|
||||
blend.Add(rad, edg);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
blend.Build();
|
||||
if (!blend.HasResult() || blend.Shape().IsNull())
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
if (status)
|
||||
{
|
||||
di << "*******************************************************\n";
|
||||
di << "****** *******\n";
|
||||
di << "****** Blending Failed (Radius = " << rad << ") *******\n";
|
||||
di << "****** *******\n";
|
||||
di << "*******************************************************\n";
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Blending successfully performed on all Edges: \n\n";
|
||||
}
|
||||
bShape = blend.Shape();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <GC_MakeSegment.hxx>
|
||||
|
||||
@@ -1138,13 +720,7 @@ void QABugs::Commands_10(Draw_Interpretor& theCommands)
|
||||
group);
|
||||
theCommands.Add("OCC486", "Use : OCC486 surf x y z du dv ", __FILE__, OCC486, group);
|
||||
theCommands.Add("OCC712", "OCC712 draftAngle slabThick", __FILE__, OCC712, group);
|
||||
theCommands.Add("OCC822_1", "OCC822_1 name1 name2 result", __FILE__, OCC822_1, group);
|
||||
theCommands.Add("OCC822_2", "OCC822_2 name1 name2 result", __FILE__, OCC822_2, group);
|
||||
theCommands.Add("OCC823", "OCC823 name1 name2 result", __FILE__, OCC823, group);
|
||||
theCommands.Add("OCC824", "OCC824 name1 name2 result", __FILE__, OCC824, group);
|
||||
theCommands.Add("OCC825", "OCC825 name1 name2 name3 name4 name5", __FILE__, OCC825, group);
|
||||
theCommands.Add("OCC826", "OCC826 name1 name2 result", __FILE__, OCC826, group);
|
||||
theCommands.Add("OCC827", "OCC827 name1 name2 name3 result1 result2", __FILE__, OCC827, group);
|
||||
theCommands.Add("OCC828", "OCC828 redius shape result ", __FILE__, OCC828, group);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1252,63 +1252,6 @@ static int OCC369(Draw_Interpretor& di, int argc, const char** argv)
|
||||
#include <math_Matrix.hxx>
|
||||
#include <math_Vector.hxx>
|
||||
|
||||
static int OCC524(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 9)
|
||||
{
|
||||
di << "Usage : " << argv[0]
|
||||
<< " LowerVector UpperVector InitialValueVector LowerRowMatrix UpperRowMatrix "
|
||||
"LowerColMatrix UpperColMatrix InitialValueMatrix\n";
|
||||
return 1;
|
||||
}
|
||||
int LowerVector = Draw::Atoi(argv[1]);
|
||||
int UpperVector = Draw::Atoi(argv[2]);
|
||||
double InitialValueVector = Draw::Atof(argv[3]);
|
||||
int LowerRowMatrix = Draw::Atoi(argv[4]);
|
||||
int UpperRowMatrix = Draw::Atoi(argv[5]);
|
||||
int LowerColMatrix = Draw::Atoi(argv[6]);
|
||||
int UpperColMatrix = Draw::Atoi(argv[7]);
|
||||
double InitialValueMatrix = Draw::Atof(argv[8]);
|
||||
|
||||
math_Vector Vector1(LowerVector, UpperVector);
|
||||
math_Vector Vector2(LowerVector, UpperVector);
|
||||
|
||||
math_Vector Vector(LowerVector, UpperVector, InitialValueVector);
|
||||
math_Matrix Matrix(LowerRowMatrix,
|
||||
UpperRowMatrix,
|
||||
LowerColMatrix,
|
||||
UpperColMatrix,
|
||||
InitialValueMatrix);
|
||||
|
||||
// Vector.Dump(std::cout);
|
||||
// std::cout<<std::endl;
|
||||
|
||||
// Matrix.Dump(std::cout);
|
||||
// std::cout<<std::endl;
|
||||
|
||||
Vector1.Multiply(Vector, Matrix);
|
||||
|
||||
// Vector1.Dump(std::cout);
|
||||
Standard_SStream aSStream1;
|
||||
Vector1.Dump(aSStream1);
|
||||
di << aSStream1;
|
||||
di << "\n";
|
||||
|
||||
if (Matrix.RowNumber() > 1)
|
||||
{
|
||||
Matrix(Matrix.LowerRow() + 1, Matrix.LowerCol()) += 1.;
|
||||
}
|
||||
Vector2.TMultiply(Vector, Matrix);
|
||||
|
||||
// Vector2.Dump(std::cout);
|
||||
Standard_SStream aSStream2;
|
||||
Vector2.Dump(aSStream2);
|
||||
di << aSStream2;
|
||||
di << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <GeomPlate_BuildPlateSurface.hxx>
|
||||
|
||||
//=================================================================================================
|
||||
@@ -1967,50 +1910,6 @@ static int OCC5739_UniAbs(Draw_Interpretor& di, int argc, const char** argv)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int OCC6046(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " nb_of_vectors size\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int nb = Draw::Atoi(argv[1]);
|
||||
int sz = Draw::Atoi(argv[2]);
|
||||
double val = 10;
|
||||
math_Vector** pv = new math_Vector*[nb];
|
||||
|
||||
di << "creating " << nb << " vectors " << sz << " elements each...\n";
|
||||
int i;
|
||||
for (i = 0; i < nb; i++)
|
||||
{
|
||||
pv[i] = new math_Vector(1, sz, val);
|
||||
if ((i % (nb / 10)) == 0)
|
||||
{
|
||||
di << " " << i;
|
||||
// std::cout.flush();
|
||||
di << "\n";
|
||||
}
|
||||
}
|
||||
di << " done\n";
|
||||
di << "deleting them ...\n";
|
||||
for (i = 0; i < nb; i++)
|
||||
{
|
||||
delete pv[i];
|
||||
if ((i % (nb / 10)) == 0)
|
||||
{
|
||||
di << " " << i;
|
||||
// std::cout.flush();
|
||||
di << "\n";
|
||||
}
|
||||
}
|
||||
di << " done\n";
|
||||
|
||||
delete[] pv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC5698(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
@@ -2845,99 +2744,6 @@ static int OCC10138(Draw_Interpretor& di, int argc, const char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC7639(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
bool IsEvenArgc = true;
|
||||
IsEvenArgc = argc % 2 == 0;
|
||||
|
||||
if (argc < 3 || IsEvenArgc)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " index1 value1 ... [indexN valueN]\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i, aValue, aPosition;
|
||||
NCollection_DynamicArray<int> vec;
|
||||
for (i = 0; i < argc - 1; i++)
|
||||
{
|
||||
i++;
|
||||
aValue = Draw::Atoi(argv[i]);
|
||||
aPosition = Draw::Atoi(argv[i + 1]);
|
||||
vec.SetValue(aValue, aPosition);
|
||||
}
|
||||
NCollection_DynamicArray<int>::Iterator it(vec);
|
||||
int j;
|
||||
for (j = 0; it.More(); it.Next(), j++)
|
||||
{
|
||||
// di << it.Value() << "\n";
|
||||
di << j << " " << it.Value() << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC8797(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 1)
|
||||
{
|
||||
di << "Usage : " << argv[0] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
gp_Pnt point(0.0, 0.0, 0.0);
|
||||
|
||||
NCollection_Array1<gp_Pnt> poles(0, 6);
|
||||
poles(0) = point;
|
||||
|
||||
point.SetCoord(1.0, 1.0, 0.0);
|
||||
poles(1) = point;
|
||||
|
||||
point.SetCoord(2.0, 1.0, 0.0);
|
||||
poles(2) = point;
|
||||
|
||||
point.SetCoord(3.0, 0.0, 0.0);
|
||||
poles(3) = point;
|
||||
|
||||
point.SetCoord(4.0, 1.0, 0.0);
|
||||
poles(4) = point;
|
||||
|
||||
point.SetCoord(5.0, 1.0, 0.0);
|
||||
poles(5) = point;
|
||||
|
||||
point.SetCoord(6.0, 0.0, 0.0);
|
||||
poles(6) = point;
|
||||
|
||||
NCollection_Array1<double> knots(0, 2);
|
||||
knots(0) = 0.0;
|
||||
knots(1) = 0.5;
|
||||
knots(2) = 1.0;
|
||||
|
||||
NCollection_Array1<int> multi(0, 2);
|
||||
multi(0) = 4;
|
||||
multi(1) = 3;
|
||||
multi(2) = 4;
|
||||
|
||||
occ::handle<Geom_BSplineCurve> spline = new Geom_BSplineCurve(poles, knots, multi, 3);
|
||||
|
||||
// length!! 1.
|
||||
double l_abcissa, l_gprop;
|
||||
GeomAdaptor_Curve adaptor_spline(spline);
|
||||
GCPnts_AbscissaPoint temp;
|
||||
l_abcissa = GCPnts_AbscissaPoint::Length(adaptor_spline);
|
||||
std::cout << "Length Spline(abcissa_Pnt): " << l_abcissa << std::endl;
|
||||
|
||||
// length!! 2.
|
||||
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline);
|
||||
GProp_GProps prop;
|
||||
BRepGProp::LinearProperties(edge, prop);
|
||||
l_gprop = prop.Mass();
|
||||
std::cout << "Length Spline(GProp_GProps): " << l_gprop << std::endl;
|
||||
|
||||
std::cout << "Difference (abcissa_Pnt<->GProp_GProps): " << l_gprop - l_abcissa << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC7068(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 1)
|
||||
@@ -3075,26 +2881,6 @@ int OCC14376(Draw_Interpretor& di, int argc, const char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC15489(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " A B C\n";
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
gp_Lin2d aLin2d(Draw::Atof(argv[1]), Draw::Atof(argv[2]), Draw::Atof(argv[3]));
|
||||
gp_Pnt2d anOrigin = aLin2d.Location();
|
||||
di << "X_0 = " << anOrigin.X() << " Y_0 = " << anOrigin.Y() << "\n";
|
||||
}
|
||||
catch (Standard_ConstructionError const&)
|
||||
{
|
||||
di << argv[0] << " Exception: Sqrt(A*A + B*B) <= Resolution from gp\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC15755(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
@@ -4925,12 +4711,6 @@ void QABugs::Commands_11(Draw_Interpretor& theCommands)
|
||||
OCC24,
|
||||
group);
|
||||
theCommands.Add("OCC369", "OCC369 Shape", __FILE__, OCC369, group);
|
||||
theCommands.Add("OCC524",
|
||||
"OCC524 LowerVector UpperVector InitialValueVector LowerRowMatrix UpperRowMatrix "
|
||||
"LowerColMatrix UpperColMatrix InitialValueMatrix",
|
||||
__FILE__,
|
||||
OCC524,
|
||||
group);
|
||||
// theCommands.Add("OCC578", "OCC578 shape1 shape2 shape3", __FILE__, OCC578, group);
|
||||
theCommands.Add("OCC578", "OCC578 shape1 shape2 shape3", __FILE__, OCC578, group);
|
||||
theCommands.Add("OCC708",
|
||||
@@ -4978,7 +4758,6 @@ void QABugs::Commands_11(Draw_Interpretor& theCommands)
|
||||
|
||||
theCommands.Add("OCC1077", "OCC1077 result", __FILE__, OCC1077, group);
|
||||
theCommands.Add("OCC5739", "OCC5739 name shape step", __FILE__, OCC5739_UniAbs, group);
|
||||
theCommands.Add("OCC6046", "OCC6046 nb_of_vectors size", __FILE__, OCC6046, group);
|
||||
theCommands.Add("OCC5698", "OCC5698 wire", __FILE__, OCC5698, group);
|
||||
theCommands.Add("OCC6143", "OCC6143 catching signals", __FILE__, OCC6143, group);
|
||||
theCommands.Add("OCC30762", "OCC30762 printing backtrace", __FILE__, OCC30762, group);
|
||||
@@ -4986,8 +4765,6 @@ void QABugs::Commands_11(Draw_Interpretor& theCommands)
|
||||
theCommands.Add("OCC7372", "OCC7372", __FILE__, OCC7372, group);
|
||||
theCommands.Add("OCC8169", "OCC8169 edge1 edge2 plane", __FILE__, OCC8169, group);
|
||||
theCommands.Add("OCC10138", "OCC10138 lower upper", __FILE__, OCC10138, group);
|
||||
theCommands.Add("OCC7639", "OCC7639 index1 value1 ... [indexN valueN]", __FILE__, OCC7639, group);
|
||||
theCommands.Add("OCC8797", "OCC8797", __FILE__, OCC8797, group);
|
||||
theCommands.Add("OCC7068", "OCC7068", __FILE__, OCC7068, group);
|
||||
theCommands.Add("OCC11457",
|
||||
"OCC11457 polygon lastedge x1 y1 z1 x2 y2 z2 ...",
|
||||
@@ -5000,7 +4777,6 @@ void QABugs::Commands_11(Draw_Interpretor& theCommands)
|
||||
OCC13963,
|
||||
group);
|
||||
theCommands.Add("OCC14376", "OCC14376 shape [deflection]", __FILE__, OCC14376, group);
|
||||
theCommands.Add("OCC15489", "OCC15489 A B C", __FILE__, OCC15489, group);
|
||||
theCommands.Add("OCC15755", "OCC15755 file shape", __FILE__, OCC15755, group);
|
||||
theCommands.Add("OCC16782", "OCC16782 file.std file.xml file.cbf", __FILE__, OCC16782, group);
|
||||
theCommands.Add("OCC12584", "OCC12584 [mode = 0/1/2]", __FILE__, OCC12584, group);
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
// Created on: 2002-10-24
|
||||
// Created by: Michael KUZMITCHEV
|
||||
// Copyright (c) 2002-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 <QABugs.hxx>
|
||||
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <DBRep.hxx>
|
||||
#include <AIS_InteractiveContext.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gce_MakeCirc.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <GC_MakeArcOfCircle.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <BRepOffsetAPI_ThruSections.hxx>
|
||||
|
||||
//=======================================================================
|
||||
// OCC895
|
||||
//=======================================================================
|
||||
static int OCC895(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc < 2 || argc > 5)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " result [angle [reverse [order]]]\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const double rad = 1.0;
|
||||
const double angle = (argc > 2) ? Draw::Atof(argv[2]) : 0.0;
|
||||
const int reverse = (argc > 3) ? Draw::Atoi(argv[3]) : 0;
|
||||
const int order = (argc > 4) ? Draw::Atoi(argv[4]) : 0;
|
||||
|
||||
// Make a wire from the first arc for ThruSections.
|
||||
//
|
||||
// This arc is rotated 5 degrees about the Z axis.
|
||||
// I don't know why, but if we don't rotate it,
|
||||
// the final shell is not twisted.
|
||||
gp_Pnt center1(0, 10, 0);
|
||||
gp_Ax2 axis1 =
|
||||
reverse ? gp_Ax2(center1, gp::DY(), gp::DZ()) : gp_Ax2(center1, -gp::DY(), gp::DX());
|
||||
if (std::abs(angle) > gp::Resolution())
|
||||
axis1.Rotate(gp_Ax1(center1, gp::DZ()), angle * M_PI / 180.0);
|
||||
|
||||
gce_MakeCirc makeCirc1(axis1, rad);
|
||||
if (!makeCirc1.IsDone())
|
||||
return 1;
|
||||
gp_Circ circ1 = makeCirc1.Value();
|
||||
GC_MakeArcOfCircle makeArc1(circ1, 0, M_PI / 2, true);
|
||||
if (!makeArc1.IsDone())
|
||||
return 1;
|
||||
occ::handle<Geom_TrimmedCurve> arc1 = makeArc1.Value();
|
||||
|
||||
// Create wire 1
|
||||
BRepBuilderAPI_MakeEdge makeEdge1(arc1, arc1->StartPoint(), arc1->EndPoint());
|
||||
if (!makeEdge1.IsDone())
|
||||
return 1;
|
||||
TopoDS_Edge edge1 = makeEdge1.Edge();
|
||||
BRepBuilderAPI_MakeWire makeWire1;
|
||||
makeWire1.Add(edge1);
|
||||
if (!makeWire1.IsDone())
|
||||
return 1;
|
||||
TopoDS_Wire wire1 = makeWire1.Wire();
|
||||
|
||||
// Make a wire from the second arc for ThruSections.
|
||||
gp_Pnt center2(10, 0, 0);
|
||||
gp_Ax2 axis2(center2, -gp::DX(), gp::DZ());
|
||||
|
||||
gce_MakeCirc makeCirc2(axis2, rad);
|
||||
if (!makeCirc2.IsDone())
|
||||
return 1;
|
||||
gp_Circ circ2 = makeCirc2.Value();
|
||||
GC_MakeArcOfCircle makeArc2(circ2, 0, M_PI / 2, true);
|
||||
if (!makeArc2.IsDone())
|
||||
return 1;
|
||||
occ::handle<Geom_TrimmedCurve> arc2 = makeArc2.Value();
|
||||
|
||||
// Create wire 2
|
||||
BRepBuilderAPI_MakeEdge makeEdge2(arc2, arc2->StartPoint(), arc2->EndPoint());
|
||||
if (!makeEdge2.IsDone())
|
||||
return 1;
|
||||
TopoDS_Edge edge2 = makeEdge2.Edge();
|
||||
BRepBuilderAPI_MakeWire makeWire2;
|
||||
makeWire2.Add(edge2);
|
||||
if (!makeWire2.IsDone())
|
||||
return 1;
|
||||
TopoDS_Wire wire2 = makeWire2.Wire();
|
||||
|
||||
BRepOffsetAPI_ThruSections thruSect(false, true);
|
||||
if (order)
|
||||
{
|
||||
thruSect.AddWire(wire1);
|
||||
thruSect.AddWire(wire2);
|
||||
}
|
||||
else
|
||||
{
|
||||
thruSect.AddWire(wire2);
|
||||
thruSect.AddWire(wire1);
|
||||
}
|
||||
thruSect.Build();
|
||||
if (!thruSect.IsDone())
|
||||
return 1;
|
||||
TopoDS_Shape myShape = thruSect.Shape();
|
||||
|
||||
DBRep::Set(argv[1], myShape);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QABugs::Commands_12(Draw_Interpretor& theCommands)
|
||||
{
|
||||
const char* group = "QABugs";
|
||||
|
||||
theCommands.Add("OCC895", "OCC895 result [angle [reverse [order]]]", __FILE__, OCC895, group);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -783,215 +783,6 @@ static int OCC544(Draw_Interpretor& di, int argc, const char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
#include <BRepAlgoAPI_Common.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
static int OCC817(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " result mesh_delta\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
constexpr double delt = 5.0 * Precision::Confusion();
|
||||
double mesh_delt = Draw::Atof(argv[2]);
|
||||
if (mesh_delt <= 0.0)
|
||||
{
|
||||
di << "Error: mesh_delta must be positive value\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create outer box solid
|
||||
gp_Pnt P(0, 0, 0);
|
||||
TopoDS_Solid fullSolid = BRepPrimAPI_MakeBox(P, 30.0, 30.0, 30.0).Solid();
|
||||
|
||||
// Create inner box solid
|
||||
P.SetX(10);
|
||||
P.SetY(10);
|
||||
P.SetZ(10);
|
||||
TopoDS_Solid internalSolid = BRepPrimAPI_MakeBox(P, 10.0, 10.0, 10.0).Solid();
|
||||
|
||||
// Cut inner from outer
|
||||
di << "BRepAlgoAPI_Cut cut( fullSolid, internalSolid )\n";
|
||||
BRepAlgoAPI_Cut cut(fullSolid, internalSolid);
|
||||
if (!cut.IsDone())
|
||||
{
|
||||
di << "Error: Could not cut volumes\n";
|
||||
return -1;
|
||||
}
|
||||
const TopoDS_Shape& cut_shape = cut.Shape();
|
||||
|
||||
// see if we have a solid
|
||||
int found_solid = 0;
|
||||
TopoDS_Solid cutSolid;
|
||||
TopExp_Explorer Ex;
|
||||
for (Ex.Init(cut_shape, TopAbs_SOLID); Ex.More(); Ex.Next())
|
||||
{
|
||||
TopoDS_Solid sol = TopoDS::Solid(Ex.Current());
|
||||
if (!sol.IsNull())
|
||||
{
|
||||
cutSolid = sol;
|
||||
found_solid++;
|
||||
}
|
||||
}
|
||||
if (found_solid != 1)
|
||||
{
|
||||
di << "Error: Cut operation produced " << found_solid << " solids\n";
|
||||
return -1;
|
||||
}
|
||||
DBRep::Set(argv[1], cutSolid);
|
||||
|
||||
// Calculate initial volume
|
||||
GProp_GProps volumeVProps;
|
||||
BRepGProp::VolumeProperties(cutSolid, volumeVProps);
|
||||
di << "Info: Original volume = " << volumeVProps.Mass() << "\n";
|
||||
|
||||
//
|
||||
// build bounding box and calculate bounds for initial mesh
|
||||
//
|
||||
Bnd_Box bndBox;
|
||||
BRepBndLib::Add(cutSolid, bndBox);
|
||||
double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
|
||||
bndBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
|
||||
Xmin -= delt;
|
||||
Ymin -= delt;
|
||||
Zmin -= delt;
|
||||
Xmax += delt;
|
||||
Ymax += delt;
|
||||
Zmax += delt;
|
||||
di << "Info: Bounds\n (" << Xmin << "," << Ymin << "," << Zmin << ")\n (" << Xmax << "," << Ymax
|
||||
<< "," << Zmax << ")\n";
|
||||
|
||||
// grid the bounding box
|
||||
int NumXsubvolumes = (int)((Xmax - Xmin) / mesh_delt);
|
||||
if (NumXsubvolumes <= 0)
|
||||
NumXsubvolumes = 1;
|
||||
int NumYsubvolumes = (int)((Ymax - Ymin) / mesh_delt);
|
||||
if (NumYsubvolumes <= 0)
|
||||
NumYsubvolumes = 1;
|
||||
int NumZsubvolumes = (int)((Zmax - Zmin) / mesh_delt);
|
||||
if (NumZsubvolumes <= 0)
|
||||
NumZsubvolumes = 1;
|
||||
const double StepX = (Xmax - Xmin) / NumXsubvolumes;
|
||||
const double StepY = (Ymax - Ymin) / NumYsubvolumes;
|
||||
const double StepZ = (Zmax - Zmin) / NumZsubvolumes;
|
||||
const int NumSubvolumes = NumXsubvolumes * NumYsubvolumes * NumZsubvolumes;
|
||||
di << "Info: NumSubvolumesX = " << NumXsubvolumes << "\n";
|
||||
di << "Info: NumSubvolumesY = " << NumYsubvolumes << "\n";
|
||||
di << "Info: NumSubvolumesZ = " << NumZsubvolumes << "\n";
|
||||
di << "Info: NumSubvolumes = " << NumSubvolumes << "\n";
|
||||
|
||||
//
|
||||
// construct initial mesh of cutSolid
|
||||
//
|
||||
NCollection_Array1<TopoDS_Shape> SubvolumeSolid(0, NumSubvolumes - 1);
|
||||
NCollection_Array1<double> SubvolumeVol(0, NumSubvolumes - 1);
|
||||
double accumulatedVolume = 0.0;
|
||||
int i, j, k, l = 0;
|
||||
double x = Xmin;
|
||||
for (i = 0; i < NumXsubvolumes; i++)
|
||||
{
|
||||
double y = Ymin;
|
||||
for (j = 0; j < NumYsubvolumes; j++)
|
||||
{
|
||||
double z = Zmin;
|
||||
for (k = 0; k < NumZsubvolumes; k++)
|
||||
{
|
||||
P.SetX(x);
|
||||
P.SetY(y);
|
||||
P.SetZ(z);
|
||||
TopoDS_Shape aSubvolume = BRepPrimAPI_MakeBox(P, StepX, StepY, StepZ).Solid();
|
||||
di << "Info: box b_" << l << " " << P.X() << " " << P.Y() << " " << P.Z() << " " << StepX
|
||||
<< " " << StepY << " " << StepZ << "\n";
|
||||
if (aSubvolume.IsNull())
|
||||
{
|
||||
di << "Error: could not construct subvolume " << l << "\n";
|
||||
return 1;
|
||||
}
|
||||
SubvolumeSolid.SetValue(l, aSubvolume);
|
||||
GProp_GProps subvolumeVProps;
|
||||
BRepGProp::VolumeProperties(SubvolumeSolid(l), subvolumeVProps);
|
||||
const double vol = subvolumeVProps.Mass();
|
||||
di << "Info: original subvolume " << l << " volume = " << vol << "\n";
|
||||
SubvolumeVol.SetValue(l, vol);
|
||||
accumulatedVolume += vol;
|
||||
l++;
|
||||
z += StepZ;
|
||||
}
|
||||
y += StepY;
|
||||
}
|
||||
x += StepX;
|
||||
}
|
||||
di << "Info: Accumulated mesh volume = " << accumulatedVolume << "\n";
|
||||
|
||||
//
|
||||
// trim mesh to cutSolid
|
||||
//
|
||||
accumulatedVolume = 0.0;
|
||||
for (l = 0; l < NumSubvolumes; l++)
|
||||
{
|
||||
TopoDS_Shape copySolid = BRepBuilderAPI_Copy(cutSolid).Shape();
|
||||
|
||||
// perform common
|
||||
di << "BRepAlgoAPI_Common common(copySolid/*cutSolid*/, SubvolumeSolid(l))\n";
|
||||
BRepAlgoAPI_Common common(copySolid /*cutSolid*/, SubvolumeSolid(l));
|
||||
if (!common.IsDone())
|
||||
{
|
||||
di << "Error: could not construct a common solid " << l << "\n";
|
||||
return 1;
|
||||
}
|
||||
const TopoDS_Shape& aCommonShape = common.Shape();
|
||||
|
||||
// see if we have a solid
|
||||
found_solid = 0;
|
||||
TopoDS_Shape commonShape;
|
||||
//////////for (Ex.Init(common.Shape(), TopAbs_SOLID); Ex.More(); Ex.Next())
|
||||
for (Ex.Init(aCommonShape, TopAbs_SOLID); Ex.More(); Ex.Next())
|
||||
{
|
||||
TopoDS_Solid sol = TopoDS::Solid(Ex.Current());
|
||||
if (!sol.IsNull())
|
||||
{
|
||||
commonShape = sol;
|
||||
found_solid++;
|
||||
}
|
||||
}
|
||||
if (found_solid != 1)
|
||||
{
|
||||
di << "Info: Common operation " << l << " produced " << found_solid << " solids\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
SubvolumeSolid.SetValue(l, commonShape);
|
||||
GProp_GProps subvolumeVProps;
|
||||
BRepGProp::VolumeProperties(SubvolumeSolid(l), subvolumeVProps);
|
||||
const double vol = subvolumeVProps.Mass();
|
||||
const bool err = (vol > SubvolumeVol(l)) || (vol <= 0.0);
|
||||
// std::cout << (err? "ERROR" : "Info") << ": final subvolume " << l << " volume = " << vol <<
|
||||
// std::endl;
|
||||
if (err)
|
||||
di << "ERROR: final subvolume " << l << " volume = " << vol << "\n";
|
||||
else
|
||||
di << "Info: final subvolume " << l << " volume = " << vol << "\n";
|
||||
accumulatedVolume += vol;
|
||||
if (err)
|
||||
{
|
||||
char astr[80];
|
||||
Sprintf(astr, "e_%d", l);
|
||||
DBRep::Set(astr, commonShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
di << "Info: Accumulated meshed volume = " << accumulatedVolume << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QABugs::Commands_13(Draw_Interpretor& theCommands)
|
||||
{
|
||||
const char* group = "QABugs";
|
||||
@@ -1001,15 +792,11 @@ void QABugs::Commands_13(Draw_Interpretor& theCommands)
|
||||
__FILE__,
|
||||
OCC332bug,
|
||||
group);
|
||||
//////theCommands.Add("OCC544", "OCC544 [[[[[wT [[[[d1 [[[d2 [[R [length]]]]]", __FILE__, OCC544,
|
||||
/// group);
|
||||
theCommands.Add("OCC544",
|
||||
"OCC544 [[[[[wT [[[[d1 [[[d2 [[R [length ]]]]]",
|
||||
__FILE__,
|
||||
OCC544,
|
||||
group);
|
||||
//////theCommands.Add("OCC817", "OCC817 result mesh_delta", __FILE__, OCC817, group);
|
||||
theCommands.Add("OCC817", "OCC817 result mesh_delta ", __FILE__, OCC817, group);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,13 +25,6 @@
|
||||
#include <AIS_Shape.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2dGcc_QualifiedCurve.hxx>
|
||||
#include <Geom2dGcc_Circ2d2TanRad.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
@@ -64,54 +57,6 @@
|
||||
#include <TDF_Label.hxx>
|
||||
#include <TDataStd_Expression.hxx>
|
||||
|
||||
static int BUC60897(Draw_Interpretor& di, int /*argc*/, const char** /*argv*/)
|
||||
{
|
||||
char abuf[16];
|
||||
|
||||
occ::handle<Geom2d_Line> aLine = new Geom2d_Line(gp_Pnt2d(100, 0), gp_Dir2d(gp_Dir2d::D::NX));
|
||||
Sprintf(abuf, "line");
|
||||
const char* st = abuf;
|
||||
DrawTrSurf::Set(st, aLine);
|
||||
|
||||
NCollection_Array1<gp_Pnt2d> aPoints(1, 3);
|
||||
aPoints.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoints.SetValue(2, gp_Pnt2d(50, 50));
|
||||
aPoints.SetValue(3, gp_Pnt2d(0, 100));
|
||||
occ::handle<Geom2d_BezierCurve> aCurve = new Geom2d_BezierCurve(aPoints);
|
||||
Sprintf(abuf, "curve");
|
||||
DrawTrSurf::Set(st, aCurve);
|
||||
|
||||
Geom2dAdaptor_Curve aCLine(aLine);
|
||||
Geom2dAdaptor_Curve aCCurve(aCurve);
|
||||
Geom2dGcc_QualifiedCurve aQualifCurve1(aCLine, GccEnt_outside);
|
||||
Geom2dGcc_QualifiedCurve aQualifCurve2(aCCurve, GccEnt_outside);
|
||||
Geom2dGcc_Circ2d2TanRad aGccCirc2d(aQualifCurve1, aQualifCurve2, 10, 1e-7);
|
||||
if (!aGccCirc2d.IsDone())
|
||||
{
|
||||
di << "Faulty: can not create a circle.\n";
|
||||
return 1;
|
||||
}
|
||||
for (int i = 1; i <= aGccCirc2d.NbSolutions(); i++)
|
||||
{
|
||||
gp_Circ2d aCirc2d = aGccCirc2d.ThisSolution(i);
|
||||
di << "circle : X " << aCirc2d.Location().X() << " Y " << aCirc2d.Location().Y() << " R "
|
||||
<< aCirc2d.Radius();
|
||||
double aTmpR1, aTmpR2;
|
||||
gp_Pnt2d aPnt2d1, aPnt2d2;
|
||||
aGccCirc2d.Tangency1(i, aTmpR1, aTmpR2, aPnt2d1);
|
||||
aGccCirc2d.Tangency2(i, aTmpR1, aTmpR2, aPnt2d2);
|
||||
di << "\ntangency1 : X " << aPnt2d1.X() << " Y " << aPnt2d1.Y();
|
||||
di << "\ntangency2 : X " << aPnt2d2.X() << " Y " << aPnt2d2.Y() << "\n";
|
||||
|
||||
Sprintf(abuf, "circle_%d", i);
|
||||
occ::handle<Geom2d_Curve> circ_res = new Geom2d_Circle(aCirc2d);
|
||||
DrawTrSurf::Set(st, circ_res);
|
||||
}
|
||||
|
||||
di << "done\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int BUC60889(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 10)
|
||||
@@ -1045,7 +990,6 @@ void QABugs::Commands_14(Draw_Interpretor& theCommands)
|
||||
{
|
||||
const char* group = "QABugs";
|
||||
|
||||
theCommands.Add("BUC60897", "BUC60897", __FILE__, BUC60897, group);
|
||||
theCommands.Add("BUC60889",
|
||||
"BUC60889 point_1 point_2 name_of_edge bndbox_X1 bndbox_Y1 bndbox_Z1 bndbox_X2 "
|
||||
"bndbox_Y2 bndbox_Z2",
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <GProp_PrincipalProps.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
|
||||
#include <OSD_Path.hxx>
|
||||
#include <Standard_ProgramError.hxx>
|
||||
@@ -374,34 +374,6 @@ static int OCC295(Draw_Interpretor& di, int argc, const char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int OCC49(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " name\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
TopoDS_Shape S = DBRep::Get(argv[1]);
|
||||
if (S.IsNull())
|
||||
return 0;
|
||||
|
||||
GProp_GProps G;
|
||||
BRepGProp::VolumeProperties(S, G);
|
||||
GProp_PrincipalProps Pr = G.PrincipalProperties();
|
||||
bool Result = Pr.HasSymmetryAxis();
|
||||
if (Result)
|
||||
{
|
||||
di << "1\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "0\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC405(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 4)
|
||||
@@ -690,7 +662,6 @@ void QABugs::Commands_16(Draw_Interpretor& theCommands)
|
||||
theCommands.Add("BUC60972", "BUC60972 edge edge plane val text ", __FILE__, BUC60972, group);
|
||||
theCommands.Add("OCC218", "OCC218 name plane Xlabel Ylabel", __FILE__, OCC218bug, group);
|
||||
theCommands.Add("OCC295", "OCC295 edge_result edge1 edge2", __FILE__, OCC295, group);
|
||||
theCommands.Add("OCC49", "OCC49 name", __FILE__, OCC49, group);
|
||||
theCommands.Add("OCC405",
|
||||
"OCC405 edge_result edge1 edge2; merge two edges",
|
||||
__FILE__,
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#include <Geom2dGcc_Lin2d2Tan.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <ChFi3d_FilletShape.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2dGcc_QCurve.hxx>
|
||||
@@ -466,72 +469,6 @@ static int OCC566(Draw_Interpretor& di, int n, const char** a)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static int OCC570(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
di << "Usage: " << argv[0] << " result\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
BRepPrimAPI_MakeBox mkBox(100., 100., 100.);
|
||||
TopoDS_Shape aBox = mkBox.Shape();
|
||||
|
||||
TopExp_Explorer aExp;
|
||||
aExp.Init(aBox, TopAbs_WIRE);
|
||||
if (aExp.More())
|
||||
{
|
||||
TopoDS_Shape aWire = aExp.Current();
|
||||
|
||||
aExp.Init(aWire, TopAbs_EDGE);
|
||||
TopoDS_Edge e1 = TopoDS::Edge(aExp.Current());
|
||||
aExp.Next();
|
||||
TopoDS_Edge e2 = TopoDS::Edge(aExp.Current());
|
||||
aExp.Next();
|
||||
TopoDS_Edge e3 = TopoDS::Edge(aExp.Current());
|
||||
aExp.Next();
|
||||
TopoDS_Edge e4 = TopoDS::Edge(aExp.Current());
|
||||
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
BRepFilletAPI_MakeFillet mkFillet(aBox);
|
||||
mkFillet.SetContinuity(GeomAbs_C1, .001);
|
||||
|
||||
// Setup variable fillet data
|
||||
NCollection_Array1<gp_Pnt2d> t_pnt(1, 4);
|
||||
t_pnt.SetValue(1, gp_Pnt2d(0.0, 5.0));
|
||||
t_pnt.SetValue(2, gp_Pnt2d(0.3, 15.0));
|
||||
t_pnt.SetValue(3, gp_Pnt2d(0.7, 15.0));
|
||||
t_pnt.SetValue(4, gp_Pnt2d(1.0, 5.0));
|
||||
|
||||
// HERE:
|
||||
// It is impossible to build fillet if at least one edge
|
||||
// with variable radius is added!!! If all are constant, everything is ok.
|
||||
mkFillet.Add(t_pnt, e1);
|
||||
mkFillet.Add(5.0, e2);
|
||||
mkFillet.Add(t_pnt, e3);
|
||||
mkFillet.Add(5.0, e4);
|
||||
|
||||
mkFillet.Build();
|
||||
TopoDS_Shape aFinalShape = mkFillet.Shape();
|
||||
|
||||
DBRep::Set(argv[1], aFinalShape);
|
||||
}
|
||||
catch (Standard_Failure const&)
|
||||
{
|
||||
di << argv[0] << ": Exception in fillet\n";
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <Law_Interpol.hxx>
|
||||
|
||||
static double tesp = 1.e-4;
|
||||
@@ -703,169 +640,6 @@ static int OCC606(Draw_Interpretor& di, int n, const char** a)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static int OCC813(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " U V\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* str;
|
||||
double U = Draw::Atof(argv[1]);
|
||||
double V = Draw::Atof(argv[2]);
|
||||
|
||||
// Between ellipse and point:
|
||||
|
||||
occ::handle<Geom_Ellipse> ell =
|
||||
new Geom_Ellipse(gp_Ax2(gp_Pnt(1262.224429, 425.040878, 363.609716),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560)),
|
||||
150,
|
||||
100);
|
||||
occ::handle<Geom_Plane> plne =
|
||||
new Geom_Plane(gp_Ax3(gp_Ax2(gp_Pnt(1262.224429, 425.040878, 363.609716),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560))));
|
||||
|
||||
occ::handle<AIS_InteractiveContext> aContext = ViewerTest::GetAISContext();
|
||||
|
||||
gp_Pnt2d pt2d(U, V);
|
||||
gp_Pln pln = plne->Pln();
|
||||
|
||||
str = "OCC813_pnt";
|
||||
DrawTrSurf::Set(str, pt2d);
|
||||
|
||||
occ::handle<Geom2d_Curve> curve2d = GeomAPI::To2d(ell, pln);
|
||||
Geom2dAdaptor_Curve acur(curve2d);
|
||||
Geom2dGcc_QualifiedCurve qcur(acur, GccEnt_outside);
|
||||
|
||||
str = "OCC813_ell";
|
||||
DrawTrSurf::Set(str, curve2d);
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
occ::handle<AIS_Shape> aisp =
|
||||
new AIS_Shape(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(curve2d, pln)).Edge());
|
||||
aContext->Display(aisp, false);
|
||||
}
|
||||
|
||||
// This does not give any solutions.
|
||||
Geom2dGcc_Lin2d2Tan lintan(qcur, pt2d, 0.1);
|
||||
di << "OCC813 nb of solutions = " << lintan.NbSolutions() << "\n";
|
||||
|
||||
char abuf[16];
|
||||
const char* st = abuf;
|
||||
|
||||
int i;
|
||||
for (i = 1; i <= lintan.NbSolutions(); i++)
|
||||
{
|
||||
Sprintf(abuf, "lintan_%d", i);
|
||||
occ::handle<Geom2d_Line> glin = new Geom2d_Line(lintan.ThisSolution(i));
|
||||
DrawTrSurf::Set(st, glin);
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
occ::handle<AIS_Shape> aisp =
|
||||
new AIS_Shape(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(glin, pln)).Edge());
|
||||
aContext->Display(aisp, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
aContext->UpdateCurrentViewer();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static int OCC814(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
di << "Usage : " << argv[0] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* str;
|
||||
|
||||
// Between Ellipse and Circle:
|
||||
|
||||
occ::handle<Geom_Circle> cir = new Geom_Circle(gp_Ax2(gp_Pnt(823.687192, 502.366825, 478.960440),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560)),
|
||||
50);
|
||||
occ::handle<Geom_Ellipse> ell =
|
||||
new Geom_Ellipse(gp_Ax2(gp_Pnt(1262.224429, 425.040878, 363.609716),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560)),
|
||||
150,
|
||||
100);
|
||||
occ::handle<Geom_Plane> plne =
|
||||
new Geom_Plane(gp_Ax3(gp_Ax2(gp_Pnt(1262.224429, 425.040878, 363.609716),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560))));
|
||||
|
||||
occ::handle<AIS_InteractiveContext> aContext = ViewerTest::GetAISContext();
|
||||
|
||||
gp_Pln pln = plne->Pln();
|
||||
occ::handle<Geom2d_Curve> curve2d = GeomAPI::To2d(ell, pln);
|
||||
occ::handle<Geom2d_Curve> fromcurve2d = GeomAPI::To2d(cir, pln);
|
||||
|
||||
str = "OCC814_cir";
|
||||
DrawTrSurf::Set(str, curve2d);
|
||||
str = "OCC814_ell";
|
||||
DrawTrSurf::Set(str, fromcurve2d);
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
occ::handle<AIS_Shape> aisp =
|
||||
new AIS_Shape(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(curve2d, pln)).Edge());
|
||||
aContext->Display(aisp, false);
|
||||
}
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
occ::handle<AIS_Shape> aisp =
|
||||
new AIS_Shape(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(fromcurve2d, pln)).Edge());
|
||||
aContext->Display(aisp, false);
|
||||
}
|
||||
|
||||
Geom2dAdaptor_Curve acur(curve2d), afromcur(fromcurve2d);
|
||||
|
||||
Geom2dGcc_QualifiedCurve qcur(acur, GccEnt_outside);
|
||||
Geom2dGcc_QualifiedCurve qfromcur(afromcur, GccEnt_outside);
|
||||
|
||||
// This does not give any solutions.
|
||||
Geom2dGcc_Lin2d2Tan lintan(qcur, qfromcur, 0.1);
|
||||
di << "OCC814 nb of solutions = " << lintan.NbSolutions() << "\n";
|
||||
|
||||
char abuf[16];
|
||||
const char* st = abuf;
|
||||
|
||||
int i;
|
||||
for (i = 1; i <= lintan.NbSolutions(); i++)
|
||||
{
|
||||
Sprintf(abuf, "lintan_%d", i);
|
||||
occ::handle<Geom2d_Line> glin = new Geom2d_Line(lintan.ThisSolution(i));
|
||||
DrawTrSurf::Set(st, glin);
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
occ::handle<AIS_Shape> aisp =
|
||||
new AIS_Shape(BRepBuilderAPI_MakeEdge(GeomAPI::To3d(glin, pln)).Edge());
|
||||
aContext->Display(aisp, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aContext.IsNull())
|
||||
{
|
||||
aContext->UpdateCurrentViewer();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <ShapeFix_Wire.hxx>
|
||||
|
||||
//=================================================================================================
|
||||
@@ -1061,88 +835,6 @@ static int OCCN1(Draw_Interpretor& di, int argc, const char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <BRepAlgoAPI_Section.hxx>
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static int OCCN2(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc > 2)
|
||||
{
|
||||
di << "Usage : " << argv[0] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
occ::handle<AIS_InteractiveContext> aContext = ViewerTest::GetAISContext();
|
||||
if (aContext.IsNull())
|
||||
{
|
||||
di << "use 'vinit' command before " << argv[0] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
BRepPrimAPI_MakeCylinder cylinder(50, 200);
|
||||
TopoDS_Shape cylinder_sh = cylinder.Shape();
|
||||
|
||||
BRepPrimAPI_MakeSphere sphere(gp_Pnt(60, 0, 100), 50);
|
||||
TopoDS_Shape sphere_sh = sphere.Shape();
|
||||
|
||||
di << "BRepAlgoAPI_Section section(cylinder_sh, sphere_sh)\n";
|
||||
BRepAlgoAPI_Section section(cylinder_sh, sphere_sh);
|
||||
if (!section.IsDone())
|
||||
{
|
||||
di << "Error performing intersection: not done.\n";
|
||||
}
|
||||
const TopoDS_Shape& shape = section.Shape();
|
||||
|
||||
DBRep::Set("OCCN2_cylinder", cylinder_sh);
|
||||
DBRep::Set("OCCN2_sphere", sphere_sh);
|
||||
DBRep::Set("OCCN2_section", shape);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
|
||||
static int OCC2569(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
occ::handle<AIS_InteractiveContext> aContext = ViewerTest::GetAISContext();
|
||||
if (aContext.IsNull())
|
||||
{
|
||||
di << "use 'vinit' command before " << argv[0] << "\n";
|
||||
return 1;
|
||||
}
|
||||
if (argc != 3)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " nbpoles result\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
int poles = Draw::Atoi(argv[1]);
|
||||
|
||||
NCollection_Array1<gp_Pnt> arr(1, poles);
|
||||
for (int i = 1; i <= poles; i++)
|
||||
arr.SetValue(i, gp_Pnt(i + 10, i * 2 + 20, i * 3 + 45));
|
||||
|
||||
occ::handle<Geom_BezierCurve> bez = new Geom_BezierCurve(arr);
|
||||
if (bez.IsNull())
|
||||
{
|
||||
di << "\n The curve is not created.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "\n Degree = " << bez->Degree() << "\n";
|
||||
}
|
||||
TopoDS_Edge sh = BRepBuilderAPI_MakeEdge(bez).Edge();
|
||||
occ::handle<AIS_Shape> ais = new AIS_Shape(sh);
|
||||
aContext->Display(ais, true);
|
||||
DrawTrSurf::Set(argv[2], bez);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <TopTools_ShapeMapHasher.hxx>
|
||||
#include <NCollection_IndexedMap.hxx>
|
||||
#include <TopExp.hxx>
|
||||
@@ -1357,7 +1049,6 @@ void QABugs::Commands_17(Draw_Interpretor& theCommands)
|
||||
__FILE__,
|
||||
OCC566,
|
||||
group);
|
||||
theCommands.Add("OCC570", "OCC570 result", __FILE__, OCC570, group);
|
||||
|
||||
theCommands.Add("OCC570mkevol",
|
||||
"OCC570mkevol result object (then use updatevol) [R/Q/P]; mkevol",
|
||||
@@ -1382,8 +1073,6 @@ void QABugs::Commands_17(Draw_Interpretor& theCommands)
|
||||
|
||||
theCommands.Add("OCC606", "OCC606 result shape [-t]", __FILE__, OCC606, group);
|
||||
|
||||
theCommands.Add("OCC813", "OCC813 U V", __FILE__, OCC813, group);
|
||||
theCommands.Add("OCC814", "OCC814", __FILE__, OCC814, group);
|
||||
theCommands.Add("OCC884", "OCC884 result shape [toler [maxtoler]]", __FILE__, OCC884, group);
|
||||
|
||||
theCommands.Add("OCCN1",
|
||||
@@ -1391,10 +1080,6 @@ void QABugs::Commands_17(Draw_Interpretor& theCommands)
|
||||
__FILE__,
|
||||
OCCN1,
|
||||
group);
|
||||
theCommands.Add("OCCN2", "OCCN2", __FILE__, OCCN2, group);
|
||||
|
||||
theCommands.Add("OCC2569", "OCC2569 nbpoles result", __FILE__, OCC2569, group);
|
||||
|
||||
theCommands.Add("OCC1642",
|
||||
"OCC1642 FinalWare FinalFace InitWare InitFace shape FixReorder FixDegenerated "
|
||||
"FixConnected FixSelfIntersection",
|
||||
|
||||
@@ -18,16 +18,11 @@
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <DBRep.hxx>
|
||||
#include <AIS_InteractiveContext.hxx>
|
||||
#include <AIS_Shape.hxx>
|
||||
|
||||
#include <V3d_View.hxx>
|
||||
|
||||
#include <TDocStd_Application.hxx>
|
||||
#include <TDocStd_Document.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
|
||||
#include <Resource_Manager.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <BRepTools_WireExplorer.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
@@ -37,9 +32,6 @@
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <GCPnts_UniformAbscissa.hxx>
|
||||
#include <GeomAdaptor_Curve.hxx>
|
||||
#include <Standard_Assert.hxx>
|
||||
|
||||
#define DEFAULT_COLOR Quantity_NOC_GOLDENROD
|
||||
|
||||
static int OCC267(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
@@ -68,71 +60,6 @@ static int OCC267(Draw_Interpretor& di, int argc, const char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC181(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 5)
|
||||
{
|
||||
di << "ERROR OCC181: Usage : " << argv[0] << " FileName path1 path2 verbose=0/1\n";
|
||||
return 1;
|
||||
}
|
||||
const char* aFileName = argv[1];
|
||||
const char* aDir1 = argv[2];
|
||||
const char* aDir2 = argv[3];
|
||||
int verboseInt = Draw::Atoi(argv[4]);
|
||||
|
||||
bool verboseBool = false;
|
||||
if (verboseInt != 0)
|
||||
{
|
||||
verboseBool = true;
|
||||
}
|
||||
|
||||
TCollection_AsciiString Env1, Env2, CSF_ = "set env(CSF_";
|
||||
Env1 = CSF_ + aFileName + "UserDefaults) " + aDir1;
|
||||
Env2 = CSF_ + aFileName + "UserDefaults) " + aDir2;
|
||||
|
||||
di.Eval(Env1.ToCString());
|
||||
|
||||
Resource_Manager aManager(aFileName, verboseBool);
|
||||
|
||||
di.Eval(Env2.ToCString());
|
||||
|
||||
bool aStatus = aManager.Save();
|
||||
|
||||
if (aStatus)
|
||||
{
|
||||
di << "\nOCC181 : Status = TRUE\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "\nOCC181 : Status = FALSE\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OCC27849(Draw_Interpretor& di, int argc, const char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
di << "Usage : " << argv[0] << " <environment variable name> <resource name>\n";
|
||||
return 1;
|
||||
}
|
||||
const char* aEnvName = argv[1];
|
||||
const char* aResName = argv[2];
|
||||
|
||||
Resource_Manager aManager(aEnvName);
|
||||
if (aManager.Find(aResName))
|
||||
{
|
||||
di << aManager.Value(aResName);
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Error: could not find resource " << aResName;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double delta_percent(double a, double b)
|
||||
{
|
||||
double result;
|
||||
@@ -262,12 +189,6 @@ void QABugs::Commands_18(Draw_Interpretor& theCommands)
|
||||
const char* group = "QABugs";
|
||||
|
||||
theCommands.Add("OCC267", "OCC267 DOC path", __FILE__, OCC267, group);
|
||||
theCommands.Add("OCC181", "OCC181 FileName path1 path2 verbose=0/1", __FILE__, OCC181, group);
|
||||
theCommands.Add("OCC27849",
|
||||
"OCC27849 <resource env name> <resource name>",
|
||||
__FILE__,
|
||||
OCC27849,
|
||||
group);
|
||||
theCommands.Add("OCC367",
|
||||
"OCC367 shape step goodX goodY goodZ percent_tolerance",
|
||||
__FILE__,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -50,6 +50,8 @@ set(OCCT_TKMath_GTests_FILES
|
||||
gp_Pln_Test.cxx
|
||||
gp_Pnt_Test.cxx
|
||||
gp_Pnt2d_Test.cxx
|
||||
gp_Quaternion_Test.cxx
|
||||
gp_Torus_Test.cxx
|
||||
gp_Trsf_Test.cxx
|
||||
gp_Vec_Test.cxx
|
||||
gp_Vec2d_Test.cxx
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <gp_Lin2d.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_ConstructionError.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -109,3 +112,26 @@ TEST(gp_LinTest, Transform)
|
||||
gp_Lin aTransformed = aLin.Transformed(aTrsf);
|
||||
EXPECT_NEAR(aTransformed.Location().Z(), 10.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
// OCC15489: gp_Lin2d construction from implicit line equation A*x + B*y + C = 0.
|
||||
// The constructor must throw Standard_ConstructionError when the direction
|
||||
// vector is zero (sqrt(A*A + B*B) <= gp::Resolution()).
|
||||
|
||||
TEST(gp_Lin2dTest, ConstructFromEquation_ZeroDirection_ThrowsException)
|
||||
{
|
||||
// A=0, B=0 -> direction vector is zero -> must throw
|
||||
#ifndef No_Exception
|
||||
EXPECT_THROW(gp_Lin2d(0.0, 0.0, 1.0), Standard_ConstructionError);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(gp_Lin2dTest, ConstructFromEquation_ValidCoefficients_CorrectOrigin)
|
||||
{
|
||||
// A=1e-20, B=-1, C=2 gives the line 1e-20 * x - y + 2 = 0
|
||||
// Origin (closest point to global origin on the line) must be
|
||||
// X_0 ~= -1.9999999999999999e-20, Y_0 ~= 2
|
||||
const gp_Lin2d aLin2d(1e-20, -1.0, 2.0);
|
||||
const gp_Pnt2d anOrigin = aLin2d.Location();
|
||||
EXPECT_NEAR(anOrigin.X(), -1.9999999999999999e-20, 1e-25);
|
||||
EXPECT_NEAR(anOrigin.Y(), 2.0, 0.001);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Mat.hxx>
|
||||
#include <gp_Quaternion.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <gp_XYZ.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// Test OCC25574: gp_Quaternion Euler angle conversion is consistent and correct
|
||||
// for all supported Euler sequences, including YawPitchRoll.
|
||||
TEST(gp_QuaternionTest, OCC25574_EulerAnglesConsistency)
|
||||
{
|
||||
const char* aNames[] = {"Extrinsic_XYZ", "Extrinsic_XZY", "Extrinsic_YZX", "Extrinsic_YXZ",
|
||||
"Extrinsic_ZXY", "Extrinsic_ZYX", "Intrinsic_XYZ", "Intrinsic_XZY",
|
||||
"Intrinsic_YZX", "Intrinsic_YXZ", "Intrinsic_ZXY", "Intrinsic_ZYX",
|
||||
"Extrinsic_XYX", "Extrinsic_XZX", "Extrinsic_YZY", "Extrinsic_YXY",
|
||||
"Extrinsic_ZYZ", "Extrinsic_ZXZ", "Intrinsic_XYX", "Intrinsic_XZX",
|
||||
"Intrinsic_YZY", "Intrinsic_YXY", "Intrinsic_ZXZ", "Intrinsic_ZYZ"};
|
||||
|
||||
gp_Quaternion aQuat;
|
||||
aQuat.Set(0.06766916507860499, 0.21848101129786085, 0.11994599260380681, 0.9660744746954637);
|
||||
|
||||
gp_Mat aRinv = aQuat.GetMatrix().Inverted();
|
||||
gp_Mat aI;
|
||||
aI.SetIdentity();
|
||||
|
||||
// Check round-trip consistency: GetEulerAngles then SetEulerAngles should reproduce the matrix
|
||||
for (int i = gp_Extrinsic_XYZ; i <= gp_Intrinsic_ZYZ; i++)
|
||||
{
|
||||
double alpha, beta, gamma;
|
||||
aQuat.GetEulerAngles(gp_EulerSequence(i), alpha, beta, gamma);
|
||||
|
||||
gp_Quaternion aQuat2;
|
||||
aQuat2.SetEulerAngles(gp_EulerSequence(i), alpha, beta, gamma);
|
||||
|
||||
gp_Mat aR = aQuat2.GetMatrix();
|
||||
gp_Mat aDiff = aR * aRinv - aI;
|
||||
EXPECT_LE(aDiff.Determinant(), 1e-5)
|
||||
<< "Round-trip failed for Euler sequence " << aNames[i - gp_Extrinsic_XYZ];
|
||||
}
|
||||
}
|
||||
|
||||
// Test OCC25574: Each Euler angle rotation around a named axis should not change
|
||||
// a point lying on that axis.
|
||||
TEST(gp_QuaternionTest, OCC25574_EulerAxisRotationPreservesAxis)
|
||||
{
|
||||
const char* aNames[] = {"Extrinsic_XYZ", "Extrinsic_XZY", "Extrinsic_YZX", "Extrinsic_YXZ",
|
||||
"Extrinsic_ZXY", "Extrinsic_ZYX", "Intrinsic_XYZ", "Intrinsic_XZY",
|
||||
"Intrinsic_YZX", "Intrinsic_YXZ", "Intrinsic_ZXY", "Intrinsic_ZYX",
|
||||
"Extrinsic_XYX", "Extrinsic_XZX", "Extrinsic_YZY", "Extrinsic_YXY",
|
||||
"Extrinsic_ZYZ", "Extrinsic_ZXZ", "Intrinsic_XYX", "Intrinsic_XZX",
|
||||
"Intrinsic_YZY", "Intrinsic_YXY", "Intrinsic_ZXZ", "Intrinsic_ZYZ"};
|
||||
|
||||
for (int i = gp_Extrinsic_XYZ; i <= gp_Intrinsic_ZYZ; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
// Determine axis index from the sequence name (X=0, Y=1, Z=2)
|
||||
const int anAxis = aNames[i - gp_Extrinsic_XYZ][10 + j] - 'X';
|
||||
ASSERT_GE(anAxis, 0);
|
||||
ASSERT_LE(anAxis, 2);
|
||||
|
||||
// 90-degree rotation around the j-th axis of the sequence
|
||||
double anAngles[3] = {0., 0., 0.};
|
||||
anAngles[j] = 0.5 * M_PI;
|
||||
|
||||
gp_Quaternion q2;
|
||||
q2.SetEulerAngles(gp_EulerSequence(i), anAngles[0], anAngles[1], anAngles[2]);
|
||||
|
||||
// Unit vector on the rotation axis
|
||||
gp_XYZ v(0., 0., 0.);
|
||||
v.SetCoord(anAxis + 1, 1.);
|
||||
|
||||
gp_Trsf aT;
|
||||
aT.SetRotation(q2);
|
||||
gp_XYZ v2 = v;
|
||||
aT.Transforms(v2);
|
||||
|
||||
EXPECT_LE((v - v2).SquareModulus(), Precision::SquareConfusion())
|
||||
<< "Rotation around axis should not move a point on that axis. Sequence: "
|
||||
<< aNames[i - gp_Extrinsic_XYZ] << ", angle index: " << j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test OCC25574: Extrinsic and intrinsic Euler sequences produce compatible matrices.
|
||||
TEST(gp_QuaternionTest, OCC25574_ExtrinsicIntrinsicCorrespondence)
|
||||
{
|
||||
const double alpha = 0.1517461713131;
|
||||
const double beta = 1.5162198410141;
|
||||
const double gamma = 1.9313156236541;
|
||||
|
||||
const gp_EulerSequence aPairs[][2] = {{gp_Extrinsic_XYZ, gp_Intrinsic_ZYX},
|
||||
{gp_Extrinsic_XZY, gp_Intrinsic_YZX},
|
||||
{gp_Extrinsic_YZX, gp_Intrinsic_XZY},
|
||||
{gp_Extrinsic_YXZ, gp_Intrinsic_ZXY},
|
||||
{gp_Extrinsic_ZXY, gp_Intrinsic_YXZ},
|
||||
{gp_Extrinsic_ZYX, gp_Intrinsic_XYZ}};
|
||||
const char* aPairNames[] = {"XYZ/ZYX", "XZY/YZX", "YZX/XZY", "YXZ/ZXY", "ZXY/YXZ", "ZYX/XYZ"};
|
||||
|
||||
gp_Quaternion aQuat;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
aQuat.SetEulerAngles(aPairs[i][0], alpha, beta, gamma);
|
||||
|
||||
double alpha2, beta2, gamma2;
|
||||
aQuat.GetEulerAngles(aPairs[i][1], gamma2, beta2, alpha2);
|
||||
|
||||
EXPECT_NEAR(alpha, alpha2, 1e-5) << "alpha mismatch for pair " << aPairNames[i];
|
||||
EXPECT_NEAR(beta, beta2, 1e-5) << "beta mismatch for pair " << aPairNames[i];
|
||||
EXPECT_NEAR(gamma, gamma2, 1e-5) << "gamma mismatch for pair " << aPairNames[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Test OCC25574 (YawPitchRoll): applying three sequential rotations and recovering
|
||||
// angles via gp_YawPitchRoll must reproduce the original angles.
|
||||
TEST(gp_QuaternionTest, OCC25574_YawPitchRollRoundTrip)
|
||||
{
|
||||
const gp_Ax2 aWorld;
|
||||
const double aAlpha = 0.0;
|
||||
const double aBeta = -35.0 / 180.0 * M_PI;
|
||||
const double aGamma = 90.0 / 180.0 * M_PI;
|
||||
|
||||
// Build the rotated frame step by step (yaw-pitch-roll convention)
|
||||
const gp_Quaternion aRotZ(aWorld.Direction(), aAlpha);
|
||||
const gp_Vec aRotY = aRotZ.Multiply(aWorld.YDirection());
|
||||
const gp_Vec aRotX = aRotZ.Multiply(aWorld.XDirection());
|
||||
|
||||
const gp_Quaternion aRotYaw(aRotY, aBeta);
|
||||
const gp_Vec aRotZ2 = aRotYaw.Multiply(aWorld.Direction());
|
||||
const gp_Vec aRotX2 = aRotYaw.Multiply(aRotX);
|
||||
|
||||
const gp_Quaternion aRotRoll(aRotX2, aGamma);
|
||||
const gp_Vec aRotZ3 = aRotRoll.Multiply(aRotZ2);
|
||||
|
||||
const gp_Ax2 aResult(gp_Pnt(0., 0., 0.), aRotZ3, aRotX2);
|
||||
|
||||
gp_Trsf aTransformation;
|
||||
aTransformation.SetDisplacement(gp_Ax2(), aResult);
|
||||
|
||||
double aComputedAlpha, aComputedBeta, aComputedGamma;
|
||||
aTransformation.GetRotation().GetEulerAngles(gp_YawPitchRoll,
|
||||
aComputedAlpha,
|
||||
aComputedBeta,
|
||||
aComputedGamma);
|
||||
|
||||
EXPECT_NEAR(aAlpha, aComputedAlpha, 1e-5) << "YawPitchRoll alpha mismatch";
|
||||
EXPECT_NEAR(aBeta, aComputedBeta, 1e-5) << "YawPitchRoll beta mismatch";
|
||||
EXPECT_NEAR(aGamma, aComputedGamma, 1e-5) << "YawPitchRoll gamma mismatch";
|
||||
}
|
||||
|
||||
// Test OCC25574 (issue 25946): gp_Intrinsic_ZYX and gp_Extrinsic_XYZ yield the
|
||||
// same Euler angles in reversed order.
|
||||
TEST(gp_QuaternionTest, OCC25574_IntrinsicZYX_vs_ExtrinsicXYZ)
|
||||
{
|
||||
gp_Quaternion aQuat;
|
||||
aQuat.Set(0.06766916507860499, 0.21848101129786085, 0.11994599260380681, 0.9660744746954637);
|
||||
|
||||
double aAlpha, aBeta, aGamma;
|
||||
aQuat.GetEulerAngles(gp_Intrinsic_ZYX, aAlpha, aBeta, aGamma);
|
||||
|
||||
double aAlpha2, aBeta2, aGamma2;
|
||||
aQuat.GetEulerAngles(gp_Extrinsic_XYZ, aAlpha2, aBeta2, aGamma2);
|
||||
|
||||
EXPECT_NEAR(aAlpha, aGamma2, 1e-5) << "Intrinsic ZYX alpha should equal Extrinsic XYZ gamma";
|
||||
EXPECT_NEAR(aBeta, aBeta2, 1e-5) << "beta should match";
|
||||
EXPECT_NEAR(aGamma, aAlpha2, 1e-5) << "Intrinsic ZYX gamma should equal Extrinsic XYZ alpha";
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <Geom_ToroidalSurface.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Torus.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// Test OCC26746: gp_Torus::Coefficients() computes correct implicit equation coefficients.
|
||||
// Verifies that evaluating the 35-coefficient polynomial at many points on the torus surface
|
||||
// gives values close to zero within tolerance.
|
||||
TEST(gp_TorusTest, OCC26746_CoefficientsCorrect)
|
||||
{
|
||||
// Torus constructed from the original Draw script:
|
||||
// torus tr 55.52514413 2.070076585 73.83409062
|
||||
// 0.37231784651136368 0.58886674834874120 0.71736697293527607
|
||||
// 0.80682335496555135 0.17666016102759910 -0.56376170618524390
|
||||
// 87.08479625 23.14682176
|
||||
const gp_Ax3 anAx3(gp_Pnt(55.52514413, 2.070076585, 73.83409062),
|
||||
gp_Dir(0.37231784651136368, 0.58886674834874120, 0.71736697293527607),
|
||||
gp_Dir(0.80682335496555135, 0.17666016102759910, -0.56376170618524390));
|
||||
|
||||
Handle(Geom_ToroidalSurface) aTorus = new Geom_ToroidalSurface(anAx3, 87.08479625, 23.14682176);
|
||||
|
||||
const double aTolerance = 3.0e-7;
|
||||
const int aNbPtsMax = 5;
|
||||
const int aLowIndex = 5;
|
||||
const double aStep = 2.0 * M_PI / aNbPtsMax;
|
||||
|
||||
NCollection_Array1<double> aCoeffs(aLowIndex, aLowIndex + 34);
|
||||
aTorus->Torus().Coefficients(aCoeffs);
|
||||
|
||||
double aUPar = 0.0;
|
||||
for (int aUind = 0; aUind <= aNbPtsMax; aUind++)
|
||||
{
|
||||
double aVPar = 0.0;
|
||||
for (int aVind = 0; aVind <= aNbPtsMax; aVind++)
|
||||
{
|
||||
const gp_Pnt aPt = aTorus->Value(aUPar, aVPar);
|
||||
const double aX1 = aPt.X();
|
||||
const double aX2 = aX1 * aX1;
|
||||
const double aX3 = aX2 * aX1;
|
||||
const double aX4 = aX2 * aX2;
|
||||
const double aY1 = aPt.Y();
|
||||
const double aY2 = aY1 * aY1;
|
||||
const double aY3 = aY2 * aY1;
|
||||
const double aY4 = aY2 * aY2;
|
||||
const double aZ1 = aPt.Z();
|
||||
const double aZ2 = aZ1 * aZ1;
|
||||
const double aZ3 = aZ2 * aZ1;
|
||||
const double aZ4 = aZ2 * aZ2;
|
||||
|
||||
int i = aLowIndex;
|
||||
|
||||
double aDelta = aCoeffs(i++) * aX4;
|
||||
aDelta += aCoeffs(i++) * aY4;
|
||||
aDelta += aCoeffs(i++) * aZ4;
|
||||
aDelta += aCoeffs(i++) * aX3 * aY1;
|
||||
aDelta += aCoeffs(i++) * aX3 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aY3 * aX1;
|
||||
aDelta += aCoeffs(i++) * aY3 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aZ3 * aX1;
|
||||
aDelta += aCoeffs(i++) * aZ3 * aY1;
|
||||
aDelta += aCoeffs(i++) * aX2 * aY2;
|
||||
aDelta += aCoeffs(i++) * aX2 * aZ2;
|
||||
aDelta += aCoeffs(i++) * aY2 * aZ2;
|
||||
aDelta += aCoeffs(i++) * aX2 * aY1 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aX1 * aY2 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aX1 * aY1 * aZ2;
|
||||
aDelta += aCoeffs(i++) * aX3;
|
||||
aDelta += aCoeffs(i++) * aY3;
|
||||
aDelta += aCoeffs(i++) * aZ3;
|
||||
aDelta += aCoeffs(i++) * aX2 * aY1;
|
||||
aDelta += aCoeffs(i++) * aX2 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aY2 * aX1;
|
||||
aDelta += aCoeffs(i++) * aY2 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aZ2 * aX1;
|
||||
aDelta += aCoeffs(i++) * aZ2 * aY1;
|
||||
aDelta += aCoeffs(i++) * aX1 * aY1 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aX2;
|
||||
aDelta += aCoeffs(i++) * aY2;
|
||||
aDelta += aCoeffs(i++) * aZ2;
|
||||
aDelta += aCoeffs(i++) * aX1 * aY1;
|
||||
aDelta += aCoeffs(i++) * aX1 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aY1 * aZ1;
|
||||
aDelta += aCoeffs(i++) * aX1;
|
||||
aDelta += aCoeffs(i++) * aY1;
|
||||
aDelta += aCoeffs(i++) * aZ1;
|
||||
aDelta += aCoeffs(i++);
|
||||
|
||||
EXPECT_NEAR(aDelta, 0.0, aTolerance)
|
||||
<< "Torus coefficient equation not satisfied at (u=" << aUPar << ", v=" << aVPar
|
||||
<< "), delta=" << aDelta;
|
||||
|
||||
aVPar = (aVind == aNbPtsMax) ? 2.0 * M_PI : aVPar + aStep;
|
||||
}
|
||||
|
||||
aVPar = 0.0;
|
||||
aUPar = (aUind == aNbPtsMax) ? 2.0 * M_PI : aUPar + aStep;
|
||||
}
|
||||
}
|
||||
@@ -163,3 +163,18 @@ TEST(gp_Vec2dTest, SetLinearForm)
|
||||
EXPECT_NEAR(aResult.X(), 2.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aResult.Y(), 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(gp_Vec2dTest, OCC26750_IsNormal_NegativeAngle)
|
||||
{
|
||||
// OCC26750: gp_Vec2d::IsNormal() returned FALSE when the angle is -PI/2 (not only +PI/2).
|
||||
const gp_Vec2d aVec1(1.0, 0.0);
|
||||
const gp_Vec2d aVec2(0.0, -1.0); // -90 degrees
|
||||
EXPECT_TRUE(aVec1.IsNormal(aVec2, Precision::Angular()))
|
||||
<< "Vectors at -90 degrees should be recognized as normal";
|
||||
|
||||
// Verify gp_Dir2d as well
|
||||
const gp_Dir2d aD1(gp_Dir2d::D::X);
|
||||
const gp_Dir2d aD2(gp_Dir2d::D::NY);
|
||||
EXPECT_TRUE(aD1.IsNormal(aD2, Precision::Angular()))
|
||||
<< "Direction X and direction -Y should be recognized as normal";
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <math_GlobOptMin.hxx>
|
||||
#include <math_MultipleVarFunction.hxx>
|
||||
#include <math_MultipleVarFunctionWithHessian.hxx>
|
||||
#include <math_Matrix.hxx>
|
||||
#include <math_Vector.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -100,6 +102,71 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// Branin function: standard global optimization benchmark with 3 global minima.
|
||||
// f(x,y) = a*(y - b*x^2 + c*x - r)^2 + s*(1-t)*cos(x) + s
|
||||
// Standard parameters: a=1, b=5.1/(4pi^2), c=5/pi, r=6, s=10, t=1/(8pi)
|
||||
// Global minimum value: ~0.397887 at 3 locations: (-pi,12.275), (pi,2.275), (9.42478,2.475)
|
||||
class BraninFunction : public math_MultipleVarFunctionWithHessian
|
||||
{
|
||||
public:
|
||||
BraninFunction()
|
||||
{
|
||||
a = 1.0;
|
||||
b = 5.1 / (4.0 * M_PI * M_PI);
|
||||
c = 5.0 / M_PI;
|
||||
r = 6.0;
|
||||
s = 10.0;
|
||||
t = 1.0 / (8.0 * M_PI);
|
||||
}
|
||||
|
||||
int NbVariables() const override { return 2; }
|
||||
|
||||
bool Value(const math_Vector& theX, double& theF) override
|
||||
{
|
||||
const double u = theX(1);
|
||||
const double v = theX(2);
|
||||
const double aSqPt = (v - b * u * u + c * u - r);
|
||||
const double aLnPt = s * (1 - t) * cos(u);
|
||||
theF = a * aSqPt * aSqPt + aLnPt + s;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Gradient(const math_Vector& theX, math_Vector& theG) override
|
||||
{
|
||||
const double u = theX(1);
|
||||
const double v = theX(2);
|
||||
const double aSqPt = (v - b * u * u + c * u - r);
|
||||
theG(1) = 2 * a * aSqPt * (c - 2 * b * u) - s * (1 - t) * sin(u);
|
||||
theG(2) = 2 * a * aSqPt;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Values(const math_Vector& theX, double& theF, math_Vector& theG) override
|
||||
{
|
||||
Value(theX, theF);
|
||||
Gradient(theX, theG);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Values(const math_Vector& theX, double& theF, math_Vector& theG, math_Matrix& theH) override
|
||||
{
|
||||
Value(theX, theF);
|
||||
Gradient(theX, theG);
|
||||
const double u = theX(1);
|
||||
const double v = theX(2);
|
||||
const double aSqPt = (v - b * u * u + c * u - r);
|
||||
const double aTmpPt = c - 2 * b * u;
|
||||
theH(1, 1) = 2 * a * aTmpPt * aTmpPt - 4 * a * b * aSqPt - s * (1 - t) * cos(u);
|
||||
theH(1, 2) = 2 * a * aTmpPt;
|
||||
theH(2, 1) = theH(1, 2);
|
||||
theH(2, 2) = 2 * a;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
double a, b, c, r, s, t;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
TEST(MathGlobOptMinTest, QuadraticFunctionOptimization)
|
||||
@@ -513,4 +580,67 @@ TEST(MathGlobOptMinTest, SmallSearchSpace)
|
||||
aSolver.Points(1, aSol);
|
||||
EXPECT_NEAR(aSol(1), 1.0, 0.02) << "Should find solution close to global minimum";
|
||||
EXPECT_NEAR(aSol(2), 2.0, 0.02) << "Should find solution close to global minimum";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathGlobOptMinTest, OCC25004_BraninFunctionGlobalOptimum)
|
||||
{
|
||||
// OCC25004: Extrema_ExtCC incorrect result. Tests math_GlobOptMin on Branin benchmark.
|
||||
// The Branin function has exactly 3 global minima at ~(-pi,12.275), (pi,2.275), (9.42478,2.475).
|
||||
// Expected minimum value: ~0.39788735772.
|
||||
BraninFunction aFunc;
|
||||
|
||||
math_Vector aLower(1, 2), aUpper(1, 2);
|
||||
aLower(1) = -5;
|
||||
aLower(2) = 0;
|
||||
aUpper(1) = 10;
|
||||
aUpper(2) = 15;
|
||||
|
||||
// Estimate Lipschitz constant on a regular 16x16 grid.
|
||||
const int aGridOrder = 16;
|
||||
math_Vector aFuncValues(1, aGridOrder * aGridOrder);
|
||||
double aLipConst = 0;
|
||||
math_Vector aCurrPnt1(1, 2), aCurrPnt2(1, 2);
|
||||
|
||||
int idx = 1;
|
||||
for (int i = 1; i <= aGridOrder; i++)
|
||||
{
|
||||
for (int j = 1; j <= aGridOrder; j++)
|
||||
{
|
||||
aCurrPnt1(1) = aLower(1) + (aUpper(1) - aLower(1)) * (i - 1) / (aGridOrder - 1.0);
|
||||
aCurrPnt1(2) = aLower(2) + (aUpper(2) - aLower(2)) * (j - 1) / (aGridOrder - 1.0);
|
||||
aFunc.Value(aCurrPnt1, aFuncValues(idx));
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i <= aGridOrder; i++)
|
||||
for (int j = 1; j <= aGridOrder; j++)
|
||||
for (int k = 1; k <= aGridOrder; k++)
|
||||
for (int l = 1; l <= aGridOrder; l++)
|
||||
{
|
||||
if (i == k && j == l)
|
||||
continue;
|
||||
aCurrPnt1(1) = aLower(1) + (aUpper(1) - aLower(1)) * (i - 1) / (aGridOrder - 1.0);
|
||||
aCurrPnt1(2) = aLower(2) + (aUpper(2) - aLower(2)) * (j - 1) / (aGridOrder - 1.0);
|
||||
aCurrPnt2(1) = aLower(1) + (aUpper(1) - aLower(1)) * (k - 1) / (aGridOrder - 1.0);
|
||||
aCurrPnt2(2) = aLower(2) + (aUpper(2) - aLower(2)) * (l - 1) / (aGridOrder - 1.0);
|
||||
const int idx1 = (i - 1) * aGridOrder + j;
|
||||
const int idx2 = (k - 1) * aGridOrder + l;
|
||||
// Use subtracted vector norm for Lipschitz estimation
|
||||
aCurrPnt1.Add(-aCurrPnt2);
|
||||
const double aDist = aCurrPnt1.Norm();
|
||||
if (aDist > 0.0)
|
||||
{
|
||||
const double aC = std::abs(aFuncValues(idx1) - aFuncValues(idx2)) / aDist;
|
||||
if (aC > aLipConst)
|
||||
aLipConst = aC;
|
||||
}
|
||||
}
|
||||
|
||||
math_GlobOptMin aFinder(&aFunc, aLower, aUpper, aLipConst);
|
||||
aFinder.Perform();
|
||||
|
||||
EXPECT_TRUE(aFinder.isDone()) << "Optimizer must converge on Branin function";
|
||||
EXPECT_NEAR(aFinder.GetF(), 0.39788735772, 0.1) << "Minimum value of Branin function";
|
||||
EXPECT_EQ(aFinder.NbExtrema(), 3) << "Branin function has exactly 3 global minima";
|
||||
}
|
||||
|
||||
@@ -861,3 +861,45 @@ TEST(MathVectorTest, Resize_NegativeLowerBound)
|
||||
EXPECT_DOUBLE_EQ(aVec(i), static_cast<double>(i));
|
||||
}
|
||||
}
|
||||
|
||||
// OCC524: math_Vector::Multiply(vector, matrix) and TMultiply(vector, matrix).
|
||||
// Reference values from the original Draw Harness test:
|
||||
// Vector(1..6) filled with 5.0, Matrix(1..6, 1..6) filled with 4.0
|
||||
// Vector1 = Vector * Matrix -> each component = 6 * 5 * 4 = 120
|
||||
// After Matrix(2,1) += 1 (-> 5):
|
||||
// Vector2 = Vector * Matrix^T -> component 2 = 5*5 + 5*4*5 = 25+100 = 125, rest = 120
|
||||
|
||||
TEST(MathVectorTest, Multiply_RowVectorByMatrix_AllComponentsEqual)
|
||||
{
|
||||
const int aLow = 1, aHigh = 6;
|
||||
math_Vector aVec(aLow, aHigh, 5.0);
|
||||
math_Matrix aMat(aLow, aHigh, aLow, aHigh, 4.0);
|
||||
math_Vector aResult(aLow, aHigh);
|
||||
|
||||
aResult.Multiply(aVec, aMat);
|
||||
|
||||
for (int i = aLow; i <= aHigh; ++i)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(aResult(i), 120.0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathVectorTest, TMultiply_RowVectorByTransposedMatrix_ModifiedComponent)
|
||||
{
|
||||
const int aLow = 1, aHigh = 6;
|
||||
math_Vector aVec(aLow, aHigh, 5.0);
|
||||
math_Matrix aMat(aLow, aHigh, aLow, aHigh, 4.0);
|
||||
math_Vector aResult(aLow, aHigh);
|
||||
|
||||
// Modify one element to create an asymmetry in the transposed multiply
|
||||
aMat(aLow + 1, aLow) += 1.0;
|
||||
|
||||
aResult.TMultiply(aVec, aMat);
|
||||
|
||||
EXPECT_DOUBLE_EQ(aResult(1), 120.0);
|
||||
EXPECT_DOUBLE_EQ(aResult(2), 125.0);
|
||||
for (int i = 3; i <= aHigh; ++i)
|
||||
{
|
||||
EXPECT_DOUBLE_EQ(aResult(i), 120.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
set(OCCT_TKernel_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKernel_GTests_FILES
|
||||
FSD_BinaryFile_Test.cxx
|
||||
Handle_Advanced_Test.cxx
|
||||
Handle_Operations_Test.cxx
|
||||
Message_Messenger_Test.cxx
|
||||
@@ -30,8 +31,10 @@ set(OCCT_TKernel_GTests_FILES
|
||||
NCollection_SparseArray_Test.cxx
|
||||
NCollection_UBTree_Test.cxx
|
||||
NCollection_Vec4_Test.cxx
|
||||
OSD_Parallel_Test.cxx
|
||||
OSD_Path_Test.cxx
|
||||
OSD_PerfMeter_Test.cxx
|
||||
Resource_Manager_Test.cxx
|
||||
Quantity_Color_Test.cxx
|
||||
Quantity_ColorRGBA_Test.cxx
|
||||
Quantity_Date_Test.cxx
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2026 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 <FSD_BinaryFile.hxx>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Reference for size_t inversion depending on sizeof(size_t).
|
||||
template <int size>
|
||||
inline const unsigned char* SizeRef();
|
||||
|
||||
template <>
|
||||
[[maybe_unused]] inline const unsigned char* SizeRef<8>()
|
||||
{
|
||||
static const unsigned char aSizeRef[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
return aSizeRef;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[maybe_unused]] inline const unsigned char* SizeRef<4>()
|
||||
{
|
||||
static const unsigned char aSizeRef[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
|
||||
0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07,
|
||||
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00};
|
||||
return aSizeRef;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// OCC24537: GCC compiler warnings in byte order reversion code.
|
||||
// Tests correctness of InverseInt, InverseReal, InverseShortReal, InverseSize
|
||||
// on a little-endian platform.
|
||||
|
||||
TEST(FSD_BinaryFileTest, OCC24537_InverseInt_Sequential)
|
||||
{
|
||||
const unsigned char anIntRef[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05,
|
||||
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00};
|
||||
const int anIntArr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
|
||||
|
||||
int anInv[10];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
anInv[i] = FSD_BinaryFile::InverseInt(anIntArr[i]);
|
||||
|
||||
EXPECT_EQ(0, memcmp(anInv, anIntRef, sizeof(anIntRef)));
|
||||
}
|
||||
|
||||
TEST(FSD_BinaryFileTest, OCC24537_InverseInt_Random)
|
||||
{
|
||||
const unsigned char aRndIntRef[] = {0xFF, 0xC2, 0xF7, 0x00, 0xFF, 0xFF, 0xFB, 0x2E, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0xD2,
|
||||
0x00, 0x00, 0x04, 0xD3, 0xFF, 0xFF, 0xFD, 0x1E, 0xFF, 0xFF,
|
||||
0xFF, 0xFB, 0x00, 0x00, 0x03, 0x8D, 0x00, 0x3D, 0x09, 0x00};
|
||||
const int aRndIntArr[] = {-4000000, -1234, 0, 1, 1234, 1235, -738, -5, 909, 4000000};
|
||||
|
||||
int anInv[10];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
anInv[i] = FSD_BinaryFile::InverseInt(aRndIntArr[i]);
|
||||
|
||||
EXPECT_EQ(0, memcmp(anInv, aRndIntRef, sizeof(aRndIntRef)));
|
||||
}
|
||||
|
||||
TEST(FSD_BinaryFileTest, OCC24537_InverseReal_Sequential)
|
||||
{
|
||||
const unsigned char aRealRef[] = {
|
||||
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const double aRealArr[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 0.0};
|
||||
|
||||
double anInv[10];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
anInv[i] = FSD_BinaryFile::InverseReal(aRealArr[i]);
|
||||
|
||||
EXPECT_EQ(0, memcmp(anInv, aRealRef, sizeof(aRealRef)));
|
||||
}
|
||||
|
||||
TEST(FSD_BinaryFileTest, OCC24537_InverseReal_Random)
|
||||
{
|
||||
const unsigned char aRndRealRef[] = {
|
||||
0xFE, 0x37, 0xE4, 0x3C, 0x88, 0x00, 0x75, 0x9C, 0xBE, 0x11, 0x2E, 0x0B, 0xE8, 0x26, 0xD6, 0x95,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x11, 0x2E, 0x0B, 0xE8, 0x26, 0xD6, 0x95,
|
||||
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x21, 0xDA, 0x45, 0x5B, 0x53, 0xE4,
|
||||
0x54, 0xB2, 0x49, 0xAD, 0x25, 0x94, 0xC3, 0x7D, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xC0, 0x23, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0x40, 0x23, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD};
|
||||
const double aRndRealArr[] = {-1e300, -1.e-9, 0., 1.e-9, 1., 3.1415296, 1.e100, 8.0, -9.9, 9.9};
|
||||
|
||||
double anInv[10];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
anInv[i] = FSD_BinaryFile::InverseReal(aRndRealArr[i]);
|
||||
|
||||
EXPECT_EQ(0, memcmp(anInv, aRndRealRef, sizeof(aRndRealRef)));
|
||||
}
|
||||
|
||||
TEST(FSD_BinaryFileTest, OCC24537_InverseShortReal_Sequential)
|
||||
{
|
||||
const unsigned char aShortRealRef[] = {
|
||||
0x3F, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x80,
|
||||
0x00, 0x00, 0x40, 0xA0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0x40, 0xE0, 0x00, 0x00,
|
||||
0x41, 0x00, 0x00, 0x00, 0x41, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const float aShortRealArr[] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 0.0f};
|
||||
|
||||
float anInv[10];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
anInv[i] = FSD_BinaryFile::InverseShortReal(aShortRealArr[i]);
|
||||
|
||||
EXPECT_EQ(0, memcmp(anInv, aShortRealRef, sizeof(aShortRealRef)));
|
||||
}
|
||||
|
||||
TEST(FSD_BinaryFileTest, OCC24537_InverseShortReal_Random)
|
||||
{
|
||||
const unsigned char aRndShortRealRef[] = {
|
||||
0xB0, 0x89, 0x70, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x30, 0x89, 0x70, 0x5F, 0x3F, 0x80,
|
||||
0x00, 0x00, 0x40, 0x49, 0x0E, 0x56, 0xC0, 0xD6, 0x66, 0x66, 0x40, 0xD6, 0x66, 0x66,
|
||||
0x42, 0xC5, 0xCC, 0xCD, 0xC2, 0xC7, 0xCC, 0xCD, 0x42, 0xC7, 0xCC, 0xCD};
|
||||
const float aRndShortRealArr[] =
|
||||
{-1.e-9f, 0.f, 1.e-9f, 1.f, 3.1415f, -6.7f, 6.7f, 98.9f, -99.9f, 99.9f};
|
||||
|
||||
float anInv[10];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
anInv[i] = FSD_BinaryFile::InverseShortReal(aRndShortRealArr[i]);
|
||||
|
||||
EXPECT_EQ(0, memcmp(anInv, aRndShortRealRef, sizeof(aRndShortRealRef)));
|
||||
}
|
||||
|
||||
TEST(FSD_BinaryFileTest, OCC24537_InverseSize_Sequential)
|
||||
{
|
||||
const size_t aSizeArr[] = {1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 8ul, 9ul, 0ul};
|
||||
const unsigned char* aSizeRef = SizeRef<sizeof(size_t)>();
|
||||
|
||||
size_t anInv[10];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
anInv[i] = FSD_BinaryFile::InverseSize(aSizeArr[i]);
|
||||
|
||||
EXPECT_EQ(0, memcmp(anInv, aSizeRef, sizeof(size_t) * 10));
|
||||
}
|
||||
@@ -910,4 +910,23 @@ TEST(NCollection_DynamicArrayTest, IntAndSizeTOverloadsAgree)
|
||||
{
|
||||
EXPECT_EQ(aVecInt.Value(i), aVecSize.Value(static_cast<size_t>(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OCC7639: NCollection_DynamicArray must handle out-of-order SetValue calls
|
||||
// (sparse / rare data) correctly and preserve all assigned values.
|
||||
// The draw test called: OCC7639 0 1 2 500 1 2
|
||||
// SetValue(0, 1), SetValue(2, 500), SetValue(1, 2)
|
||||
// Expected iterator output (j, value): 0->1, 1->2, 2->500
|
||||
|
||||
TEST(NCollection_DynamicArrayTest, SetValue_OutOfOrderIndices_CorrectValues)
|
||||
{
|
||||
NCollection_DynamicArray<int> aVec;
|
||||
aVec.SetValue(0, 1);
|
||||
aVec.SetValue(2, 500);
|
||||
aVec.SetValue(1, 2);
|
||||
|
||||
ASSERT_EQ(aVec.Size(), 3);
|
||||
EXPECT_EQ(aVec.Value(0), 1);
|
||||
EXPECT_EQ(aVec.Value(1), 2);
|
||||
EXPECT_EQ(aVec.Value(2), 500);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
// Copyright (c) 2026 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 <NCollection_Array1.hxx>
|
||||
#include <NCollection_Array2.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <OSD_ThreadPool.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// SAXPY functor: Y[i] = scalar * X[i] + Y[i]
|
||||
class SaxpyFunctor
|
||||
{
|
||||
public:
|
||||
SaxpyFunctor(const NCollection_Array1<double>& theX,
|
||||
NCollection_Array1<double>& theY,
|
||||
double theScalar)
|
||||
: myX(theX),
|
||||
myY(theY),
|
||||
myScalar(theScalar)
|
||||
{
|
||||
}
|
||||
|
||||
int Begin() const { return 0; }
|
||||
|
||||
int End() const { return myX.Length(); }
|
||||
|
||||
void operator()(int theIndex) const { myY(theIndex) = myScalar * myX(theIndex) + myY(theIndex); }
|
||||
|
||||
void operator()(int /*theThreadIndex*/, int theIndex) const { (*this)(theIndex); }
|
||||
|
||||
private:
|
||||
SaxpyFunctor(const SaxpyFunctor&) = delete;
|
||||
SaxpyFunctor& operator=(SaxpyFunctor&) = delete;
|
||||
|
||||
const NCollection_Array1<double>& myX;
|
||||
NCollection_Array1<double>& myY;
|
||||
double myScalar;
|
||||
};
|
||||
|
||||
// Batched SAXPY functor for large vectors
|
||||
class SaxpyBatchFunctor
|
||||
{
|
||||
public:
|
||||
static const int THE_BATCH_SIZE = 100000;
|
||||
|
||||
SaxpyBatchFunctor(const NCollection_Array1<double>& theX,
|
||||
NCollection_Array1<double>& theY,
|
||||
double theScalar)
|
||||
: myX(theX),
|
||||
myY(theY),
|
||||
myScalar(theScalar),
|
||||
myNbBatches((int)std::ceil((double)theX.Size() / THE_BATCH_SIZE))
|
||||
{
|
||||
}
|
||||
|
||||
int Begin() const { return 0; }
|
||||
|
||||
int End() const { return myNbBatches; }
|
||||
|
||||
void operator()(int theBatchIndex) const
|
||||
{
|
||||
const int aLower = theBatchIndex * THE_BATCH_SIZE;
|
||||
const int anUpper = std::min(aLower + THE_BATCH_SIZE - 1, myX.Upper());
|
||||
for (int i = aLower; i <= anUpper; ++i)
|
||||
myY(i) = myScalar * myX(i) + myY(i);
|
||||
}
|
||||
|
||||
void operator()(int /*theThreadIndex*/, int theBatchIndex) const { (*this)(theBatchIndex); }
|
||||
|
||||
private:
|
||||
SaxpyBatchFunctor(const SaxpyBatchFunctor&) = delete;
|
||||
SaxpyBatchFunctor& operator=(SaxpyBatchFunctor&) = delete;
|
||||
|
||||
const NCollection_Array1<double>& myX;
|
||||
NCollection_Array1<double>& myY;
|
||||
double myScalar;
|
||||
int myNbBatches;
|
||||
};
|
||||
|
||||
// Matrix multiplication functor: result(i,j) = sum_k mat1(i,k)*mat2(k,j)
|
||||
class MatMultFunctor
|
||||
{
|
||||
public:
|
||||
MatMultFunctor(const NCollection_Array2<double>& theMat1,
|
||||
const NCollection_Array2<double>& theMat2,
|
||||
NCollection_Array2<double>& theResult,
|
||||
int theSize)
|
||||
: myMat1(theMat1),
|
||||
myMat2(theMat2),
|
||||
myResult(theResult),
|
||||
mySize(theSize)
|
||||
{
|
||||
}
|
||||
|
||||
int Begin() const { return 0; }
|
||||
|
||||
int End() const { return mySize; }
|
||||
|
||||
void operator()(int theIndex) const
|
||||
{
|
||||
for (int j = 0; j < mySize; ++j)
|
||||
{
|
||||
double aTmp = 0.0;
|
||||
for (int k = 0; k < mySize; ++k)
|
||||
aTmp += myMat1(theIndex, k) * myMat2(k, j);
|
||||
myResult(theIndex, j) = aTmp;
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(int /*theThreadIndex*/, int theIndex) const { (*this)(theIndex); }
|
||||
|
||||
private:
|
||||
MatMultFunctor(const MatMultFunctor&) = delete;
|
||||
MatMultFunctor& operator=(MatMultFunctor&) = delete;
|
||||
|
||||
const NCollection_Array2<double>& myMat1;
|
||||
const NCollection_Array2<double>& myMat2;
|
||||
NCollection_Array2<double>& myResult;
|
||||
int mySize;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Tests that OSD_Parallel::For and OSD_ThreadPool::Launcher produce the same
|
||||
// result as sequential SAXPY Y[i] = scalar * X[i] + Y[i] (OCC24826).
|
||||
TEST(OSD_ParallelTest, OCC24826_SaxpyParallelMatchesSequential)
|
||||
{
|
||||
const int aLength = 500000;
|
||||
|
||||
NCollection_Array1<double> aX(0, aLength - 1);
|
||||
NCollection_Array1<double> anYRef(0, aLength - 1);
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
aX(i) = anYRef(i) = static_cast<double>(i);
|
||||
|
||||
// Sequential reference
|
||||
{
|
||||
const SaxpyFunctor aFunctor(aX, anYRef, 1e-6);
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
aFunctor(i);
|
||||
}
|
||||
|
||||
// OSD_Parallel::For
|
||||
{
|
||||
NCollection_Array1<double> anY = aX;
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
anY(i) = static_cast<double>(i);
|
||||
SaxpyFunctor aFunctor(aX, anY, 1e-6);
|
||||
OSD_Parallel::For(aFunctor.Begin(), aFunctor.End(), aFunctor);
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
EXPECT_DOUBLE_EQ(anY(i), anYRef(i)) << "Mismatch at index " << i;
|
||||
}
|
||||
|
||||
// OSD_ThreadPool::Launcher
|
||||
{
|
||||
NCollection_Array1<double> anY = aX;
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
anY(i) = static_cast<double>(i);
|
||||
SaxpyFunctor aFunctor(aX, anY, 1e-6);
|
||||
OSD_ThreadPool::Launcher aLauncher(*OSD_ThreadPool::DefaultPool());
|
||||
aLauncher.Perform(aFunctor.Begin(), aFunctor.End(), aFunctor);
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
EXPECT_DOUBLE_EQ(anY(i), anYRef(i)) << "Mismatch at index " << i;
|
||||
}
|
||||
|
||||
// OSD_Parallel::For with batched functor
|
||||
{
|
||||
NCollection_Array1<double> anY = aX;
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
anY(i) = static_cast<double>(i);
|
||||
SaxpyBatchFunctor aFunctor(aX, anY, 1e-6);
|
||||
OSD_Parallel::For(aFunctor.Begin(), aFunctor.End(), aFunctor);
|
||||
for (int i = 0; i < aLength; ++i)
|
||||
EXPECT_DOUBLE_EQ(anY(i), anYRef(i)) << "Mismatch at index " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that OSD_Parallel::For and OSD_ThreadPool::Launcher produce the same
|
||||
// result as sequential matrix multiplication (OCC29935).
|
||||
TEST(OSD_ParallelTest, OCC29935_MatrixMultiplyParallelMatchesSequential)
|
||||
{
|
||||
const int aSize = 50;
|
||||
|
||||
std::mt19937 aGen(42);
|
||||
NCollection_Array2<double> aMat1(0, aSize - 1, 0, aSize - 1);
|
||||
NCollection_Array2<double> aMat2(0, aSize - 1, 0, aSize - 1);
|
||||
NCollection_Array2<double> aMatRef(0, aSize - 1, 0, aSize - 1);
|
||||
NCollection_Array2<double> aMatRes(0, aSize - 1, 0, aSize - 1);
|
||||
|
||||
for (int i = 0; i < aSize; ++i)
|
||||
for (int j = 0; j < aSize; ++j)
|
||||
{
|
||||
aMat1(i, j) = static_cast<double>(aGen() % 1000);
|
||||
aMat2(i, j) = static_cast<double>(aGen() % 1000);
|
||||
}
|
||||
|
||||
// Sequential reference
|
||||
{
|
||||
MatMultFunctor aFunctor(aMat1, aMat2, aMatRef, aSize);
|
||||
for (int i = aFunctor.Begin(); i < aFunctor.End(); ++i)
|
||||
aFunctor(i);
|
||||
}
|
||||
|
||||
// OSD_Parallel::For
|
||||
{
|
||||
aMatRes.Init(0.0);
|
||||
MatMultFunctor aFunctor(aMat1, aMat2, aMatRes, aSize);
|
||||
OSD_Parallel::For(aFunctor.Begin(), aFunctor.End(), aFunctor);
|
||||
for (int i = 0; i < aSize; ++i)
|
||||
for (int j = 0; j < aSize; ++j)
|
||||
EXPECT_DOUBLE_EQ(aMatRes(i, j), aMatRef(i, j));
|
||||
}
|
||||
|
||||
// OSD_ThreadPool::Launcher
|
||||
{
|
||||
aMatRes.Init(0.0);
|
||||
MatMultFunctor aFunctor(aMat1, aMat2, aMatRes, aSize);
|
||||
OSD_ThreadPool::Launcher aLauncher(*OSD_ThreadPool::DefaultPool());
|
||||
aLauncher.Perform(aFunctor.Begin(), aFunctor.End(), aFunctor);
|
||||
for (int i = 0; i < aSize; ++i)
|
||||
for (int j = 0; j < aSize; ++j)
|
||||
EXPECT_DOUBLE_EQ(aMatRes(i, j), aMatRef(i, j));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <OSD_Environment.hxx>
|
||||
#include <Resource_Manager.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Returns a platform-independent temp base directory for tests.
|
||||
std::filesystem::path getTempBase()
|
||||
{
|
||||
return std::filesystem::temp_directory_path() / "occt_resource_manager_test";
|
||||
}
|
||||
|
||||
//! Writes a minimal resource file containing one entry: key : value
|
||||
void writeResourceFile(const std::filesystem::path& theDir,
|
||||
const std::string& theFileName,
|
||||
const std::string& theKey,
|
||||
const std::string& theValue)
|
||||
{
|
||||
std::filesystem::create_directories(theDir);
|
||||
std::ofstream aFile(theDir / theFileName);
|
||||
aFile << theKey << " : " << theValue << "\n";
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class Resource_ManagerTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override { std::filesystem::remove_all(getTempBase()); }
|
||||
|
||||
void TearDown() override { std::filesystem::remove_all(getTempBase()); }
|
||||
};
|
||||
|
||||
//! Sets CSF_<theFileName>UserDefaults environment variable to theDir.
|
||||
static void setUserDefaultsEnv(const std::string& theFileName, const std::filesystem::path& theDir)
|
||||
{
|
||||
const std::string anEnvName = "CSF_" + theFileName + "UserDefaults";
|
||||
OSD_Environment anEnv(anEnvName.c_str());
|
||||
anEnv.SetValue(TCollection_AsciiString(theDir.string().c_str()));
|
||||
anEnv.Build();
|
||||
}
|
||||
|
||||
// Test OCC27849: Resource_Manager correctly reads resource files located in
|
||||
// directories whose names contain dots, spaces, or multiple path segments.
|
||||
TEST_F(Resource_ManagerTest, OCC27849_PathsWithSpecialChars)
|
||||
{
|
||||
const std::string aResourceName = "TestResource";
|
||||
const std::string aKey = "test.resource";
|
||||
const std::string aExpected = "ok";
|
||||
|
||||
const std::vector<std::string> aPaths = {
|
||||
"path",
|
||||
"path.with.dots",
|
||||
"path with spaces",
|
||||
"nested/dirs/path with spaces",
|
||||
};
|
||||
|
||||
for (const std::string& aRelPath : aPaths)
|
||||
{
|
||||
std::filesystem::path aDir = getTempBase() / aRelPath;
|
||||
writeResourceFile(aDir, aResourceName, aKey, aExpected);
|
||||
|
||||
// Point the env variable to the directory containing the resource file
|
||||
OSD_Environment anEnv("CSF_TestResourceDefaults");
|
||||
anEnv.SetValue(TCollection_AsciiString(aDir.string().c_str()));
|
||||
anEnv.Build();
|
||||
|
||||
Resource_Manager aManager(aResourceName.c_str());
|
||||
|
||||
EXPECT_TRUE(aManager.Find(aKey.c_str())) << "Resource key not found in path: " << aDir.string();
|
||||
|
||||
if (aManager.Find(aKey.c_str()))
|
||||
{
|
||||
EXPECT_STREQ(aManager.Value(aKey.c_str()), aExpected.c_str())
|
||||
<< "Wrong resource value for path: " << aDir.string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test OCC181 (case 1): Resource_Manager::Save() succeeds when the target user-defaults
|
||||
// directory already exists (flat path).
|
||||
TEST_F(Resource_ManagerTest, OCC181_SaveToExistingDirectory)
|
||||
{
|
||||
const std::string aFileName = "OCC181";
|
||||
|
||||
const std::filesystem::path aSourceDir = getTempBase() / "source";
|
||||
const std::filesystem::path aSaveDir = getTempBase() / "save_flat";
|
||||
|
||||
writeResourceFile(aSourceDir, aFileName, "test.key", "test_value");
|
||||
std::filesystem::create_directories(aSaveDir);
|
||||
|
||||
setUserDefaultsEnv(aFileName, aSourceDir);
|
||||
Resource_Manager aManager(aFileName.c_str());
|
||||
|
||||
// Redirect Save() to a different directory
|
||||
setUserDefaultsEnv(aFileName, aSaveDir);
|
||||
EXPECT_TRUE(aManager.Save());
|
||||
EXPECT_TRUE(std::filesystem::exists(aSaveDir / aFileName))
|
||||
<< "Saved resource file not found in " << aSaveDir.string();
|
||||
}
|
||||
|
||||
// Test OCC181 (case 2): Resource_Manager::Save() succeeds and creates intermediate
|
||||
// directories when the target user-defaults path does not yet exist (nested path).
|
||||
TEST_F(Resource_ManagerTest, OCC181_SaveToNestedNonExistentDirectory)
|
||||
{
|
||||
const std::string aFileName = "OCC181";
|
||||
|
||||
const std::filesystem::path aSourceDir = getTempBase() / "source2";
|
||||
const std::filesystem::path aSaveDir = getTempBase() / "nested" / "deep" / "dir";
|
||||
|
||||
writeResourceFile(aSourceDir, aFileName, "test.key", "test_value");
|
||||
|
||||
setUserDefaultsEnv(aFileName, aSourceDir);
|
||||
Resource_Manager aManager(aFileName.c_str());
|
||||
|
||||
// Redirect Save() to a nested path that does not yet exist
|
||||
setUserDefaultsEnv(aFileName, aSaveDir);
|
||||
EXPECT_TRUE(aManager.Save());
|
||||
EXPECT_TRUE(std::filesystem::exists(aSaveDir / aFileName))
|
||||
<< "Saved resource file not found in nested path " << aSaveDir.string();
|
||||
}
|
||||
@@ -1086,3 +1086,39 @@ TEST(TCollection_ExtendedStringTest, EndsWith_ZeroLength)
|
||||
// Any string ends with empty string
|
||||
EXPECT_TRUE(aString.EndsWith(nullptr, 0));
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Tests for StartsWith/EndsWith bug fix (0030536)
|
||||
// ========================================
|
||||
|
||||
TEST(TCollection_ExtendedStringTest, StartsWith_NoMatchLongerPrefix)
|
||||
{
|
||||
// "hello" does NOT start with "help"
|
||||
const TCollection_ExtendedString aStr("hello");
|
||||
const TCollection_ExtendedString aPrefix("help");
|
||||
EXPECT_FALSE(aStr.StartsWith(aPrefix));
|
||||
}
|
||||
|
||||
TEST(TCollection_ExtendedStringTest, StartsWith_Match)
|
||||
{
|
||||
// "hello" DOES start with "he"
|
||||
const TCollection_ExtendedString aStr("hello");
|
||||
const TCollection_ExtendedString aPrefix("he");
|
||||
EXPECT_TRUE(aStr.StartsWith(aPrefix));
|
||||
}
|
||||
|
||||
TEST(TCollection_ExtendedStringTest, EndsWith_NoMatchMiddlePart)
|
||||
{
|
||||
// "hello" does NOT end with "ll"
|
||||
const TCollection_ExtendedString aStr("hello");
|
||||
const TCollection_ExtendedString aSuffix("ll");
|
||||
EXPECT_FALSE(aStr.EndsWith(aSuffix));
|
||||
}
|
||||
|
||||
TEST(TCollection_ExtendedStringTest, EndsWith_Match)
|
||||
{
|
||||
// "hello" DOES end with "lo"
|
||||
const TCollection_ExtendedString aStr("hello");
|
||||
const TCollection_ExtendedString aSuffix("lo");
|
||||
EXPECT_TRUE(aStr.EndsWith(aSuffix));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRepAlgoAPI_Common.hxx>
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Solid.hxx>
|
||||
|
||||
//! Runs OCC817 test: creates hollow box (30x30x30 outer minus 10x10x10 inner),
|
||||
//! grids the bounding box into cells of theMeshDelta size, computes
|
||||
//! BRepAlgoAPI_Common of the solid with each cell, and returns
|
||||
//! the ratio of accumulated meshed volume to original volume.
|
||||
//! Returns -1.0 on failure.
|
||||
static double runHollowBoxMeshTest(double theMeshDelta)
|
||||
{
|
||||
constexpr double aDelt = 5.0 * Precision::Confusion();
|
||||
|
||||
// Create outer box solid
|
||||
const TopoDS_Solid aFullSolid = BRepPrimAPI_MakeBox(gp_Pnt(0, 0, 0), 30.0, 30.0, 30.0).Solid();
|
||||
|
||||
// Create inner box solid
|
||||
const TopoDS_Solid anInnerSolid =
|
||||
BRepPrimAPI_MakeBox(gp_Pnt(10, 10, 10), 10.0, 10.0, 10.0).Solid();
|
||||
|
||||
// Cut inner from outer
|
||||
BRepAlgoAPI_Cut aCut(aFullSolid, anInnerSolid);
|
||||
if (!aCut.IsDone())
|
||||
return -1.0;
|
||||
|
||||
// Extract the single solid from the cut result
|
||||
TopoDS_Solid aCutSolid;
|
||||
int aNbSolids = 0;
|
||||
TopExp_Explorer anExp;
|
||||
for (anExp.Init(aCut.Shape(), TopAbs_SOLID); anExp.More(); anExp.Next())
|
||||
{
|
||||
const TopoDS_Solid& aSol = TopoDS::Solid(anExp.Current());
|
||||
if (!aSol.IsNull())
|
||||
{
|
||||
aCutSolid = aSol;
|
||||
aNbSolids++;
|
||||
}
|
||||
}
|
||||
if (aNbSolids != 1)
|
||||
return -1.0;
|
||||
|
||||
// Calculate original volume
|
||||
GProp_GProps aVProps;
|
||||
BRepGProp::VolumeProperties(aCutSolid, aVProps);
|
||||
const double anOriginalVolume = aVProps.Mass();
|
||||
if (anOriginalVolume <= 0.0)
|
||||
return -1.0;
|
||||
|
||||
// Build bounding box and extend by small delta
|
||||
Bnd_Box aBndBox;
|
||||
BRepBndLib::Add(aCutSolid, aBndBox);
|
||||
double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
|
||||
aBndBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
|
||||
aXmin -= aDelt;
|
||||
aYmin -= aDelt;
|
||||
aZmin -= aDelt;
|
||||
aXmax += aDelt;
|
||||
aYmax += aDelt;
|
||||
aZmax += aDelt;
|
||||
|
||||
// Grid the bounding box
|
||||
int aNx = (int)((aXmax - aXmin) / theMeshDelta);
|
||||
if (aNx <= 0)
|
||||
aNx = 1;
|
||||
int aNy = (int)((aYmax - aYmin) / theMeshDelta);
|
||||
if (aNy <= 0)
|
||||
aNy = 1;
|
||||
int aNz = (int)((aZmax - aZmin) / theMeshDelta);
|
||||
if (aNz <= 0)
|
||||
aNz = 1;
|
||||
|
||||
const double aStepX = (aXmax - aXmin) / aNx;
|
||||
const double aStepY = (aYmax - aYmin) / aNy;
|
||||
const double aStepZ = (aZmax - aZmin) / aNz;
|
||||
const int aNbSubvols = aNx * aNy * aNz;
|
||||
|
||||
NCollection_Array1<TopoDS_Shape> aSubvols(0, aNbSubvols - 1);
|
||||
NCollection_Array1<double> aSubvolVols(0, aNbSubvols - 1);
|
||||
|
||||
// Build grid cells
|
||||
int l = 0;
|
||||
for (int i = 0; i < aNx; i++)
|
||||
{
|
||||
for (int j = 0; j < aNy; j++)
|
||||
{
|
||||
for (int k = 0; k < aNz; k++)
|
||||
{
|
||||
const gp_Pnt aPnt(aXmin + i * aStepX, aYmin + j * aStepY, aZmin + k * aStepZ);
|
||||
aSubvols.SetValue(l, BRepPrimAPI_MakeBox(aPnt, aStepX, aStepY, aStepZ).Solid());
|
||||
BRepGProp::VolumeProperties(aSubvols(l), aVProps);
|
||||
aSubvolVols.SetValue(l, aVProps.Mass());
|
||||
l++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute common of solid with each grid cell, accumulate volumes
|
||||
double anAccumulated = 0.0;
|
||||
for (l = 0; l < aNbSubvols; l++)
|
||||
{
|
||||
const TopoDS_Shape aCopySolid = BRepBuilderAPI_Copy(aCutSolid).Shape();
|
||||
BRepAlgoAPI_Common aCommon(aCopySolid, aSubvols(l));
|
||||
if (!aCommon.IsDone())
|
||||
continue;
|
||||
|
||||
int aNbCommon = 0;
|
||||
TopoDS_Shape aFoundSolid;
|
||||
for (anExp.Init(aCommon.Shape(), TopAbs_SOLID); anExp.More(); anExp.Next())
|
||||
{
|
||||
const TopoDS_Solid& aSol = TopoDS::Solid(anExp.Current());
|
||||
if (!aSol.IsNull())
|
||||
{
|
||||
aFoundSolid = aSol;
|
||||
aNbCommon++;
|
||||
}
|
||||
}
|
||||
if (aNbCommon == 1)
|
||||
{
|
||||
BRepGProp::VolumeProperties(aFoundSolid, aVProps);
|
||||
const double aVol = aVProps.Mass();
|
||||
if (aVol > 0.0 && aVol <= aSubvolVols(l))
|
||||
anAccumulated += aVol;
|
||||
}
|
||||
}
|
||||
|
||||
return anAccumulated / anOriginalVolume;
|
||||
}
|
||||
|
||||
// OCC817: BRepAlgoAPI_Common result accuracy with hollow box using mesh_delta=10.
|
||||
TEST(BRepAlgoAPI_CutTest, HollowBox_VolumeAccuracy_Delta10)
|
||||
{
|
||||
const double aRatio = runHollowBoxMeshTest(10.0);
|
||||
ASSERT_GE(aRatio, 0.0) << "Cut or Common operation failed";
|
||||
EXPECT_NEAR(aRatio, 1.0, 0.001) << "Accumulated meshed volume differs from original by > 0.1%";
|
||||
}
|
||||
|
||||
// OCC817: BRepAlgoAPI_Common result accuracy with hollow box using mesh_delta=15.
|
||||
TEST(BRepAlgoAPI_CutTest, HollowBox_VolumeAccuracy_Delta15)
|
||||
{
|
||||
const double aRatio = runHollowBoxMeshTest(15.0);
|
||||
ASSERT_GE(aRatio, 0.0) << "Cut or Common operation failed";
|
||||
EXPECT_NEAR(aRatio, 1.0, 0.001) << "Accumulated meshed volume differs from original by > 0.1%";
|
||||
}
|
||||
|
||||
// OCC817: BRepAlgoAPI_Common result accuracy with hollow box using mesh_delta=30.
|
||||
TEST(BRepAlgoAPI_CutTest, HollowBox_VolumeAccuracy_Delta30)
|
||||
{
|
||||
const double aRatio = runHollowBoxMeshTest(30.0);
|
||||
ASSERT_GE(aRatio, 0.0) << "Cut or Common operation failed";
|
||||
EXPECT_NEAR(aRatio, 1.0, 0.001) << "Accumulated meshed volume differs from original by > 0.1%";
|
||||
}
|
||||
|
||||
// OCC817: hollow box has correct surface area and valid shape.
|
||||
// Outer 30x30x30 has area 6*900=5400; inner 10x10x10 hole adds 6*100=600; total=6000.
|
||||
TEST(BRepAlgoAPI_CutTest, HollowBox_SurfaceAreaAndValidity)
|
||||
{
|
||||
const TopoDS_Solid aFullSolid = BRepPrimAPI_MakeBox(gp_Pnt(0, 0, 0), 30.0, 30.0, 30.0).Solid();
|
||||
const TopoDS_Solid anInnerSolid =
|
||||
BRepPrimAPI_MakeBox(gp_Pnt(10, 10, 10), 10.0, 10.0, 10.0).Solid();
|
||||
|
||||
BRepAlgoAPI_Cut aCut(aFullSolid, anInnerSolid);
|
||||
ASSERT_TRUE(aCut.IsDone());
|
||||
|
||||
// Extract solid
|
||||
TopoDS_Solid aCutSolid;
|
||||
TopExp_Explorer anExp;
|
||||
for (anExp.Init(aCut.Shape(), TopAbs_SOLID); anExp.More(); anExp.Next())
|
||||
aCutSolid = TopoDS::Solid(anExp.Current());
|
||||
ASSERT_FALSE(aCutSolid.IsNull());
|
||||
|
||||
// Surface area: outer box 6*900=5400, inner box adds 6*100=600 => total=6000
|
||||
GProp_GProps aSProps;
|
||||
BRepGProp::SurfaceProperties(aCutSolid, aSProps);
|
||||
EXPECT_NEAR(aSProps.Mass(), 6000.0, 6.0); // 0.1% tolerance
|
||||
|
||||
BRepCheck_Analyzer aChecker(aCutSolid);
|
||||
EXPECT_TRUE(aChecker.IsValid());
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
#include <BRepAlgoAPI_Fuse.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_MakePolygon.hxx>
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeCone.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <BRepPrimAPI_MakeTorus.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
// OCC822_1: BRepMesh_IncrementalMesh correctness test - boolean operations with cylinders and
|
||||
// cones. Creates two pairs (inner/outer) of cylinders and cones, fuses each pair, then cuts inner
|
||||
// from outer.
|
||||
TEST(BRepAlgoAPI_FuseTest, CylinderAndCone_FuseThenCut)
|
||||
{
|
||||
const gp_Ax2 anAxis1(gp_Pnt(0, 0, 0), gp_Dir(gp_Dir::D::Z));
|
||||
const TopoDS_Shape aCylIn = BRepPrimAPI_MakeCylinder(anAxis1, 40, 110).Shape();
|
||||
const TopoDS_Shape aCylOut = BRepPrimAPI_MakeCylinder(anAxis1, 50, 100).Shape();
|
||||
|
||||
const gp_Ax2 anAxis2(gp_Pnt(0, 0, 0), gp_Dir(gp_Dir::D::NZ));
|
||||
const TopoDS_Shape aConIn = BRepPrimAPI_MakeCone(anAxis2, 40, 60, 110).Shape();
|
||||
const TopoDS_Shape aConOut = BRepPrimAPI_MakeCone(anAxis2, 50, 70, 100).Shape();
|
||||
|
||||
BRepAlgoAPI_Fuse aFuseIn(aCylIn, aConIn);
|
||||
ASSERT_TRUE(aFuseIn.IsDone());
|
||||
|
||||
BRepAlgoAPI_Fuse aFuseOut(aCylOut, aConOut);
|
||||
ASSERT_TRUE(aFuseOut.IsDone());
|
||||
|
||||
BRepAlgoAPI_Cut aCut(aFuseOut.Shape(), aFuseIn.Shape());
|
||||
ASSERT_TRUE(aCut.IsDone());
|
||||
|
||||
const TopoDS_Shape aResult = aCut.Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
GProp_GProps aSProps;
|
||||
BRepGProp::SurfaceProperties(aResult, aSProps);
|
||||
EXPECT_NEAR(aSProps.Mass(), 133931.0, 133.931); // 0.1% tolerance
|
||||
|
||||
BRepCheck_Analyzer aChecker(aResult);
|
||||
EXPECT_TRUE(aChecker.IsValid());
|
||||
}
|
||||
|
||||
// OCC822_2: BRepMesh_IncrementalMesh correctness test - fuse of box and sphere.
|
||||
TEST(BRepAlgoAPI_FuseTest, BoxAndSphere)
|
||||
{
|
||||
const TopoDS_Shape aBox = BRepPrimAPI_MakeBox(gp_Pnt(0, 0, 0), gp_Pnt(100, 100, 100)).Shape();
|
||||
const TopoDS_Shape aSphere = BRepPrimAPI_MakeSphere(gp_Pnt(100, 50, 50), 25.0).Shape();
|
||||
|
||||
BRepAlgoAPI_Fuse aFuse(aBox, aSphere);
|
||||
ASSERT_TRUE(aFuse.IsDone());
|
||||
|
||||
const TopoDS_Shape aResult = aFuse.Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
GProp_GProps aSProps;
|
||||
BRepGProp::SurfaceProperties(aResult, aSProps);
|
||||
EXPECT_NEAR(aSProps.Mass(), 61963.5, 61.9635); // 0.1% tolerance
|
||||
|
||||
BRepCheck_Analyzer aChecker(aResult);
|
||||
EXPECT_TRUE(aChecker.IsValid());
|
||||
}
|
||||
|
||||
// OCC823: BRepAlgoAPI_Fuse correctness test - fuse of two nearly-parallel cylinders.
|
||||
TEST(BRepAlgoAPI_FuseTest, TwoCylinders)
|
||||
{
|
||||
const gp_Ax2 anAxis1(gp_Pnt(40, 50, 0), gp_Dir(100, 0, 0));
|
||||
const TopoDS_Shape aCyl1 = BRepPrimAPI_MakeCylinder(anAxis1, 20, 100).Shape();
|
||||
|
||||
constexpr double aSize = 0.001;
|
||||
const gp_Ax2 anAxis2(gp_Pnt(100, 50, aSize), gp_Dir(0, aSize, 80));
|
||||
const TopoDS_Shape aCyl2 = BRepPrimAPI_MakeCylinder(anAxis2, 20, 80).Shape();
|
||||
|
||||
BRepAlgoAPI_Fuse aFuse(aCyl2, aCyl1);
|
||||
ASSERT_TRUE(aFuse.IsDone());
|
||||
|
||||
const TopoDS_Shape aResult = aFuse.Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
GProp_GProps aSProps;
|
||||
BRepGProp::SurfaceProperties(aResult, aSProps);
|
||||
EXPECT_NEAR(aSProps.Mass(), 23189.5, 23.1895); // 0.1% tolerance
|
||||
|
||||
BRepCheck_Analyzer aChecker(aResult);
|
||||
EXPECT_TRUE(aChecker.IsValid());
|
||||
}
|
||||
|
||||
// OCC824: BRepAlgoAPI_Fuse correctness test - fuse of cylinder and sphere.
|
||||
TEST(BRepAlgoAPI_FuseTest, CylinderAndSphere)
|
||||
{
|
||||
const gp_Pnt aCenter(100, 0, 0);
|
||||
const gp_Ax2 anAxis(aCenter, gp_Dir(gp_Dir::D::NX));
|
||||
const TopoDS_Shape aCyl = BRepPrimAPI_MakeCylinder(anAxis, 20, 100).Shape();
|
||||
const TopoDS_Shape aSphere = BRepPrimAPI_MakeSphere(aCenter, 20.0).Shape();
|
||||
|
||||
BRepAlgoAPI_Fuse aFuse(aCyl, aSphere);
|
||||
ASSERT_TRUE(aFuse.IsDone());
|
||||
|
||||
const TopoDS_Shape aResult = aFuse.Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
GProp_GProps aSProps;
|
||||
BRepGProp::SurfaceProperties(aResult, aSProps);
|
||||
EXPECT_NEAR(aSProps.Mass(), 16336.3, 16.3363); // 0.1% tolerance
|
||||
|
||||
BRepCheck_Analyzer aChecker(aResult);
|
||||
EXPECT_TRUE(aChecker.IsValid());
|
||||
}
|
||||
|
||||
// OCC826: BRepAlgoAPI_Fuse correctness test - fuse of revolved face and sphere.
|
||||
// Intersection line passes near the pole of the sphere.
|
||||
TEST(BRepAlgoAPI_FuseTest, RevolvedFaceAndSphere)
|
||||
{
|
||||
BRepBuilderAPI_MakePolygon aWire;
|
||||
const double aX1 = 181.82808, aX2 = 202.39390;
|
||||
const double aY1 = 31.011970, aY2 = 123.06856;
|
||||
aWire.Add(gp_Pnt(aX1, aY1, 0));
|
||||
aWire.Add(gp_Pnt(aX2, aY1, 0));
|
||||
aWire.Add(gp_Pnt(aX2, aY2, 0));
|
||||
aWire.Add(gp_Pnt(aX1, aY2, 0));
|
||||
aWire.Add(gp_Pnt(aX1, aY1, 0));
|
||||
|
||||
const TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aWire.Wire(), false);
|
||||
const gp_Ax1 anAxis(gp_Pnt(0, 0, 0), gp_Dir(0, 30, 0));
|
||||
const TopoDS_Shape aRevol = BRepPrimAPI_MakeRevol(aFace, anAxis, 2.0 * M_PI).Shape();
|
||||
const TopoDS_Shape aSphere =
|
||||
BRepPrimAPI_MakeSphere(gp_Pnt(166.373, 77.0402, 96.0555), 23.218586).Shape();
|
||||
|
||||
BRepAlgoAPI_Fuse aFuse(aRevol, aSphere);
|
||||
ASSERT_TRUE(aFuse.IsDone());
|
||||
|
||||
const TopoDS_Shape aResult = aFuse.Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
GProp_GProps aSProps;
|
||||
BRepGProp::SurfaceProperties(aResult, aSProps);
|
||||
EXPECT_NEAR(aSProps.Mass(), 272935.0, 272.935); // 0.1% tolerance
|
||||
|
||||
BRepCheck_Analyzer aChecker(aResult);
|
||||
EXPECT_TRUE(aChecker.IsValid());
|
||||
}
|
||||
|
||||
// OCC827: BRepAlgoAPI_Fuse correctness test - fuse of revolved solid with two tori.
|
||||
TEST(BRepAlgoAPI_FuseTest, RevolvedSolidAndTwoTori)
|
||||
{
|
||||
BRepBuilderAPI_MakePolygon aWire;
|
||||
aWire.Add(gp_Pnt(10, 0, 0));
|
||||
aWire.Add(gp_Pnt(20, 0, 0));
|
||||
aWire.Add(gp_Pnt(20, 0, 50));
|
||||
aWire.Add(gp_Pnt(10, 0, 50));
|
||||
aWire.Add(gp_Pnt(10, 0, 0));
|
||||
|
||||
const TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aWire.Wire(), false);
|
||||
const gp_Ax1 anAxis(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 30));
|
||||
const TopoDS_Shape aRevol = BRepPrimAPI_MakeRevol(aFace, anAxis, 2.0 * M_PI).Shape();
|
||||
|
||||
constexpr double aMajRad = 15.0;
|
||||
constexpr double aMinRad = 5.0;
|
||||
|
||||
const TopoDS_Shape aTor1 =
|
||||
BRepPrimAPI_MakeTorus(gp_Ax2(gp_Pnt(0, 0, 50), gp_Dir(0, 0, 30)), aMajRad, aMinRad).Shape();
|
||||
const TopoDS_Shape aTor2 =
|
||||
BRepPrimAPI_MakeTorus(gp_Ax2(gp_Pnt(0, 0, 10), gp_Dir(0, 0, 30)), aMajRad, aMinRad).Shape();
|
||||
|
||||
BRepAlgoAPI_Fuse aFuse1(aTor1, aRevol);
|
||||
ASSERT_TRUE(aFuse1.IsDone());
|
||||
|
||||
BRepAlgoAPI_Fuse aFuse2(aTor2, aFuse1.Shape());
|
||||
ASSERT_TRUE(aFuse2.IsDone());
|
||||
|
||||
const TopoDS_Shape aResult = aFuse2.Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
GProp_GProps aSProps;
|
||||
BRepGProp::SurfaceProperties(aResult, aSProps);
|
||||
EXPECT_NEAR(aSProps.Mass(), 11847.7, 11.8477); // 0.1% tolerance
|
||||
|
||||
BRepCheck_Analyzer aChecker(aResult);
|
||||
EXPECT_TRUE(aChecker.IsValid());
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <BRepAlgoAPI_Section.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
// Test OCCN2: BRepAlgoAPI_Section of a cylinder intersecting a sphere.
|
||||
// Migrated from QABugs_17.cxx OCCN2
|
||||
TEST(BRepAlgoAPI_SectionTest, OCCN2_CylinderSphereSectionIsDone)
|
||||
{
|
||||
BRepPrimAPI_MakeCylinder aCylMaker(50., 200.);
|
||||
const TopoDS_Shape& aCylinder = aCylMaker.Shape();
|
||||
|
||||
BRepPrimAPI_MakeSphere aSphereMaker(gp_Pnt(60., 0., 100.), 50.);
|
||||
const TopoDS_Shape& aSphere = aSphereMaker.Shape();
|
||||
|
||||
BRepAlgoAPI_Section aSection(aCylinder, aSphere);
|
||||
EXPECT_TRUE(aSection.IsDone());
|
||||
EXPECT_FALSE(aSection.Shape().IsNull());
|
||||
}
|
||||
@@ -2,5 +2,9 @@
|
||||
set(OCCT_TKBool_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKBool_GTests_FILES
|
||||
BRepAlgoAPI_Cut_Test.cxx
|
||||
BRepAlgoAPI_Fuse_Test.cxx
|
||||
BRepAlgoAPI_Section_Test.cxx
|
||||
BRepFill_PipeShell_Test.cxx
|
||||
IntTools_FaceFace_Test.cxx
|
||||
)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <IntTools_Curve.hxx>
|
||||
#include <IntTools_FaceFace.hxx>
|
||||
#include <IntTools_PntOn2Faces.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
|
||||
// Test OCC24005: IntTools_FaceFace should complete quickly and correctly when
|
||||
// intersecting a slightly off-angle plane with a cylinder. Previously took 7+ seconds.
|
||||
TEST(IntTools_FaceFaceTest, OCC24005_PlaneCylinderIntersection)
|
||||
{
|
||||
// Hardcoded geometry from the original regression test
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(
|
||||
gp_Ax3(gp_Pnt(-72.948737453424499, 754.30437716359393, 259.52151854671678),
|
||||
gp_Dir(6.2471473085930200e-007, -0.99999999999980493, 0.00000000000000000),
|
||||
gp_Dir(0.99999999999980493, 6.2471473085930200e-007, 0.00000000000000000)));
|
||||
|
||||
Handle(Geom_CylindricalSurface) aCylinder = new Geom_CylindricalSurface(
|
||||
gp_Ax3(gp_Pnt(-6.4812490053250649, 753.39408794522092, 279.16400974257465),
|
||||
gp_Dir(1.0000000000000000, 0.0, 0.00000000000000000),
|
||||
gp_Dir(0.0, 1.0000000000000000, 0.00000000000000000)),
|
||||
19.712534607908712);
|
||||
|
||||
BRep_Builder aBuilder;
|
||||
TopoDS_Face aFace1, aFace2;
|
||||
aBuilder.MakeFace(aFace1, aPlane, Precision::Confusion());
|
||||
aBuilder.MakeFace(aFace2, aCylinder, Precision::Confusion());
|
||||
|
||||
IntTools_FaceFace anInters;
|
||||
anInters.SetParameters(false, true, true, Precision::Confusion());
|
||||
anInters.Perform(aFace1, aFace2);
|
||||
|
||||
ASSERT_TRUE(anInters.IsDone()) << "IntTools_FaceFace::Perform did not complete";
|
||||
|
||||
// The original test verified that intersection completes without hanging.
|
||||
// Check that we get at least one intersection curve.
|
||||
const NCollection_Sequence<IntTools_Curve>& aCurves = anInters.Lines();
|
||||
EXPECT_GE(aCurves.Length() + anInters.Points().Length(), 1)
|
||||
<< "Expected at least one intersection result (curve or point)";
|
||||
}
|
||||
@@ -52,3 +52,40 @@ TEST(Expr_GeneralExpression_Test, OCC902_ExpressionDerivative)
|
||||
EXPECT_TRUE(isCorrect) << "Derivative result was: " << aDerivativeStr.ToCString()
|
||||
<< ", expected either 'Exp(5*x)*5' or '5*Exp(5*x)'";
|
||||
}
|
||||
|
||||
// Test OCC31697: Expr_GeneralExpression::Derivative for Exp(2*Sin(x^2))
|
||||
// Expected derivative: Exp(2*Sin(x^2))*Cos(x^2)*x*4
|
||||
TEST(Expr_GeneralExpression_Test, OCC31697_DerivativeOfComplexExpression)
|
||||
{
|
||||
occ::handle<ExprIntrp_GenExp> anExprIntrp = ExprIntrp_GenExp::Create();
|
||||
anExprIntrp->Process(TCollection_AsciiString("Exp(2*Sin(x^2))"));
|
||||
|
||||
ASSERT_TRUE(anExprIntrp->IsDone()) << "Expression parsing should succeed";
|
||||
|
||||
occ::handle<Expr_GeneralExpression> anExpr = anExprIntrp->Expression();
|
||||
ASSERT_FALSE(anExpr.IsNull()) << "Expression should not be null";
|
||||
|
||||
occ::handle<Expr_NamedUnknown> aVar = new Expr_NamedUnknown("x");
|
||||
ASSERT_TRUE(anExpr->Contains(aVar)) << "Expression should contain variable x";
|
||||
|
||||
occ::handle<Expr_GeneralExpression> aDer = anExpr->Derivative(aVar);
|
||||
ASSERT_FALSE(aDer.IsNull()) << "Derivative should not be null";
|
||||
|
||||
const TCollection_AsciiString aDerStr = aDer->String();
|
||||
EXPECT_EQ(aDerStr, TCollection_AsciiString("Exp(2*Sin(x^2))*Cos(x^2)*x*4"))
|
||||
<< "Derivative result was: " << aDerStr.ToCString();
|
||||
}
|
||||
|
||||
// Test OCC22611: ExprIntrp_GenExp must not leak and must parse numeric literal correctly.
|
||||
// Migrated from QABugs_19.cxx OCC22611
|
||||
TEST(Expr_GeneralExpression_Test, OCC22611_ParseNumericLiteral)
|
||||
{
|
||||
occ::handle<ExprIntrp_GenExp> aGen = ExprIntrp_GenExp::Create();
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
aGen->Process(TCollection_AsciiString("0.1214343"));
|
||||
ASSERT_TRUE(aGen->IsDone()) << "Parsing should succeed on iteration " << i;
|
||||
occ::handle<Expr_GeneralExpression> aExpr = aGen->Expression();
|
||||
EXPECT_FALSE(aExpr.IsNull()) << "Expression should not be null on iteration " << i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,16 @@
|
||||
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <TopAbs_ShapeEnum.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -99,3 +103,54 @@ TEST(BRepFilletAPI_MakeFilletTest, FilletVariableRadius)
|
||||
BRepCheck_Analyzer anAnalyzer(aResult);
|
||||
EXPECT_TRUE(anAnalyzer.IsValid());
|
||||
}
|
||||
|
||||
// Test OCC570: BRepFilletAPI_MakeFillet with mixed constant and variable radius.
|
||||
// Migrated from QABugs_17.cxx OCC570
|
||||
TEST(BRepFilletAPI_MakeFilletTest, OCC570_MixedVariableConstantRadius)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(100., 100., 100.);
|
||||
const TopoDS_Shape& aBox = aBoxMaker.Shape();
|
||||
|
||||
// Take the first wire of the box and its 4 edges
|
||||
TopExp_Explorer aWireExp(aBox, TopAbs_WIRE);
|
||||
ASSERT_TRUE(aWireExp.More());
|
||||
|
||||
TopExp_Explorer anEdgeExp(aWireExp.Current(), TopAbs_EDGE);
|
||||
ASSERT_TRUE(anEdgeExp.More());
|
||||
TopoDS_Edge anE1 = TopoDS::Edge(anEdgeExp.Current());
|
||||
anEdgeExp.Next();
|
||||
ASSERT_TRUE(anEdgeExp.More());
|
||||
TopoDS_Edge anE2 = TopoDS::Edge(anEdgeExp.Current());
|
||||
anEdgeExp.Next();
|
||||
ASSERT_TRUE(anEdgeExp.More());
|
||||
TopoDS_Edge anE3 = TopoDS::Edge(anEdgeExp.Current());
|
||||
anEdgeExp.Next();
|
||||
ASSERT_TRUE(anEdgeExp.More());
|
||||
TopoDS_Edge anE4 = TopoDS::Edge(anEdgeExp.Current());
|
||||
|
||||
// Variable radius law: 4 (parameter, radius) control points
|
||||
NCollection_Array1<gp_Pnt2d> aVarRadius(1, 4);
|
||||
aVarRadius.SetValue(1, gp_Pnt2d(0.0, 5.0));
|
||||
aVarRadius.SetValue(2, gp_Pnt2d(0.3, 15.0));
|
||||
aVarRadius.SetValue(3, gp_Pnt2d(0.7, 15.0));
|
||||
aVarRadius.SetValue(4, gp_Pnt2d(1.0, 5.0));
|
||||
|
||||
BRepFilletAPI_MakeFillet aFillet(aBox);
|
||||
aFillet.SetContinuity(GeomAbs_C1, 0.001);
|
||||
aFillet.Add(aVarRadius, anE1);
|
||||
aFillet.Add(5.0, anE2);
|
||||
aFillet.Add(aVarRadius, anE3);
|
||||
aFillet.Add(5.0, anE4);
|
||||
|
||||
ASSERT_NO_THROW(aFillet.Build()) << "BRepFilletAPI_MakeFillet::Build should not throw";
|
||||
ASSERT_TRUE(aFillet.IsDone()) << "Fillet operation should succeed";
|
||||
|
||||
const TopoDS_Shape& aResult = aFillet.Shape();
|
||||
|
||||
BRepCheck_Analyzer anAnalyzer(aResult);
|
||||
EXPECT_TRUE(anAnalyzer.IsValid()) << "Result shape should be valid";
|
||||
|
||||
GProp_GProps aProps;
|
||||
BRepGProp::SurfaceProperties(aResult, aProps);
|
||||
EXPECT_NEAR(aProps.Mass(), 58500., 58500. * 0.01) << "Surface area should be approximately 58500";
|
||||
}
|
||||
|
||||
@@ -3,12 +3,17 @@ set(OCCT_TKGeomAlgo_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKGeomAlgo_GTests_FILES
|
||||
Geom2dAPI_InterCurveCurve_Test.cxx
|
||||
Geom2dAPI_Interpolate_Test.cxx
|
||||
Geom2dAPI_PointsToBSpline_Test.cxx
|
||||
GeomFill_BSplineCurves_Test.cxx
|
||||
GeomFill_NSections_Test.cxx
|
||||
Geom2dHatch_Elements_Test.cxx
|
||||
Geom2dHatch_Intersector_Test.cxx
|
||||
GeomAPI_PointsToBSplineSurface_Test.cxx
|
||||
GeomAPI_PointsToBSpline_Test.cxx
|
||||
Geom2dGcc_Circ2d2TanRad_Test.cxx
|
||||
Geom2dGcc_Circ2d3Tan_Test.cxx
|
||||
Geom2dGcc_Lin2d2Tan_Test.cxx
|
||||
GeomFill_CorrectedFrenet_Test.cxx
|
||||
GeomFill_Gordon_Test.cxx
|
||||
GeomFill_GuideTrihedronAC_Test.cxx
|
||||
@@ -25,5 +30,6 @@ set(OCCT_TKGeomAlgo_GTests_FILES
|
||||
IntPolyh_Point_Test.cxx
|
||||
IntSurf_LineOn2S_Test.cxx
|
||||
IntSurf_Quadric_Test.cxx
|
||||
GeomAPI_IntSS_Test.cxx
|
||||
TopTrans_SurfaceTransition_Test.cxx
|
||||
)
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2026 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 <Geom2dAPI_Interpolate.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <NCollection_HArray1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// OCC28594: Geom2dAPI_Interpolate with and without tangent scale produces different curves.
|
||||
// Tests that interpolation with tangent vectors (with scale and without scale) both produce
|
||||
// valid B-Spline curves passing through the given points.
|
||||
|
||||
TEST(Geom2dAPI_InterpolateTest, OCC28594_InterpolateWithAndWithoutTangentScale)
|
||||
{
|
||||
occ::handle<NCollection_HArray1<gp_Pnt2d>> aPoints = new NCollection_HArray1<gp_Pnt2d>(1, 6);
|
||||
NCollection_Array1<gp_Pnt2d>& aPointsArray = aPoints->ChangeArray1();
|
||||
aPointsArray(1) = gp_Pnt2d(-30.4, 8);
|
||||
aPointsArray(2) = gp_Pnt2d(-16.689912, 17.498217);
|
||||
aPointsArray(3) = gp_Pnt2d(-23.803064, 24.748543);
|
||||
aPointsArray(4) = gp_Pnt2d(-16.907466, 32.919615);
|
||||
aPointsArray(5) = gp_Pnt2d(-8.543829, 26.549421);
|
||||
aPointsArray(6) = gp_Pnt2d(0, 39.200000);
|
||||
|
||||
NCollection_Array1<gp_Vec2d> aTangents(1, 6);
|
||||
aTangents(1) = gp_Vec2d(0.3, 0.4);
|
||||
aTangents(2) = gp_Vec2d(0, 0);
|
||||
aTangents(3) = gp_Vec2d(0, 0);
|
||||
aTangents(4) = gp_Vec2d(0, 0);
|
||||
aTangents(5) = gp_Vec2d(0, 0);
|
||||
aTangents(6) = gp_Vec2d(1, 0);
|
||||
|
||||
occ::handle<NCollection_HArray1<bool>> aTangentFlags = new NCollection_HArray1<bool>(1, 6);
|
||||
NCollection_Array1<bool>& aTangentFlagsArray = aTangentFlags->ChangeArray1();
|
||||
aTangentFlagsArray(1) = true;
|
||||
aTangentFlagsArray(2) = false;
|
||||
aTangentFlagsArray(3) = false;
|
||||
aTangentFlagsArray(4) = false;
|
||||
aTangentFlagsArray(5) = false;
|
||||
aTangentFlagsArray(6) = true;
|
||||
|
||||
// Interpolation with tangent scale
|
||||
Geom2dAPI_Interpolate anInterpWithScale(aPoints, false, Precision::Confusion());
|
||||
anInterpWithScale.Load(aTangents, aTangentFlags);
|
||||
anInterpWithScale.Perform();
|
||||
EXPECT_TRUE(anInterpWithScale.IsDone());
|
||||
const occ::handle<Geom2d_BSplineCurve> aCurveWithScale = anInterpWithScale.Curve();
|
||||
EXPECT_FALSE(aCurveWithScale.IsNull());
|
||||
|
||||
// Interpolation without tangent scale
|
||||
Geom2dAPI_Interpolate anInterpWithoutScale(aPoints, false, Precision::Confusion());
|
||||
anInterpWithoutScale.Load(aTangents, aTangentFlags, false);
|
||||
anInterpWithoutScale.Perform();
|
||||
EXPECT_TRUE(anInterpWithoutScale.IsDone());
|
||||
const occ::handle<Geom2d_BSplineCurve> aCurveWithoutScale = anInterpWithoutScale.Curve();
|
||||
EXPECT_FALSE(aCurveWithoutScale.IsNull());
|
||||
|
||||
// Both curves must pass through all given points
|
||||
const double aTol = Precision::Confusion() * 10;
|
||||
for (int anIndex = 1; anIndex <= aPoints->Length(); ++anIndex)
|
||||
{
|
||||
const gp_Pnt2d aPtOnCurveWithScale = aCurveWithScale->EvalD0(aCurveWithScale->Knot(anIndex));
|
||||
const gp_Pnt2d& aPt = aPointsArray(anIndex);
|
||||
EXPECT_NEAR(aPt.X(), aPtOnCurveWithScale.X(), aTol) << " at point index " << anIndex;
|
||||
EXPECT_NEAR(aPt.Y(), aPtOnCurveWithScale.Y(), aTol) << " at point index " << anIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <GccEnt.hxx>
|
||||
#include <Geom2dAdaptor_Curve.hxx>
|
||||
#include <Geom2dGcc_Circ2d2TanRad.hxx>
|
||||
#include <Geom2dGcc_QualifiedCurve.hxx>
|
||||
#include <Geom2d_BezierCurve.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <gp_Circ2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
// Test BUC60897: Geom2dGcc_Circ2d2TanRad finds circles tangent to a line and
|
||||
// a Bezier curve. Verifies that each tangency point lies at the circle radius
|
||||
// from the circle center (within 1% relative tolerance).
|
||||
TEST(Geom2dGcc_Circ2d2TanRadTest, BUC60897_TangentToLineAndBezier)
|
||||
{
|
||||
// Create a Geom2d_Line from point (100, 0) going in the -X direction
|
||||
occ::handle<Geom2d_Line> aLine = new Geom2d_Line(gp_Pnt2d(100, 0), gp_Dir2d(gp_Dir2d::D::NX));
|
||||
|
||||
// Create a Geom2d_BezierCurve from three control points
|
||||
NCollection_Array1<gp_Pnt2d> aPoints(1, 3);
|
||||
aPoints.SetValue(1, gp_Pnt2d(0, 0));
|
||||
aPoints.SetValue(2, gp_Pnt2d(50, 50));
|
||||
aPoints.SetValue(3, gp_Pnt2d(0, 100));
|
||||
occ::handle<Geom2d_BezierCurve> aCurve = new Geom2d_BezierCurve(aPoints);
|
||||
|
||||
// Build qualified curves (outside tangency)
|
||||
Geom2dAdaptor_Curve aCLine(aLine);
|
||||
Geom2dAdaptor_Curve aCCurve(aCurve);
|
||||
Geom2dGcc_QualifiedCurve aQualifCurve1(aCLine, GccEnt_outside);
|
||||
Geom2dGcc_QualifiedCurve aQualifCurve2(aCCurve, GccEnt_outside);
|
||||
|
||||
// Find circles with radius 10 tangent to both curves
|
||||
const double aRadius = 10.0;
|
||||
const double aTolerance = 1e-7;
|
||||
Geom2dGcc_Circ2d2TanRad aGccCirc2d(aQualifCurve1, aQualifCurve2, aRadius, aTolerance);
|
||||
|
||||
ASSERT_TRUE(aGccCirc2d.IsDone()) << "Geom2dGcc_Circ2d2TanRad failed to compute";
|
||||
ASSERT_GT(aGccCirc2d.NbSolutions(), 0) << "No tangent circles found";
|
||||
|
||||
// For each solution, verify tangency points are at the circle radius from its center
|
||||
const double aMaxDeltaPercent = 1.0; // 1% tolerance as used in the original Draw test
|
||||
for (int i = 1; i <= aGccCirc2d.NbSolutions(); i++)
|
||||
{
|
||||
const gp_Circ2d aCirc2d = aGccCirc2d.ThisSolution(i);
|
||||
const gp_Pnt2d aCenter = aCirc2d.Location();
|
||||
const double aR = aCirc2d.Radius();
|
||||
|
||||
double aParSol1, aParArg1, aParSol2, aParArg2;
|
||||
gp_Pnt2d aPntSol1, aPntSol2;
|
||||
aGccCirc2d.Tangency1(i, aParSol1, aParArg1, aPntSol1);
|
||||
aGccCirc2d.Tangency2(i, aParSol2, aParArg2, aPntSol2);
|
||||
|
||||
// Distance from tangency point 1 to circle center must equal radius within 1%
|
||||
const double aD1 = aPntSol1.Distance(aCenter);
|
||||
const double aDelta1 = std::abs(aD1 - aR) / aR * 100.0;
|
||||
EXPECT_LE(aDelta1, aMaxDeltaPercent)
|
||||
<< "Solution " << i << ": tangency1 distance error " << aDelta1 << "% exceeds 1%";
|
||||
|
||||
// Distance from tangency point 2 to circle center must equal radius within 1%
|
||||
const double aD2 = aPntSol2.Distance(aCenter);
|
||||
const double aDelta2 = std::abs(aD2 - aR) / aR * 100.0;
|
||||
EXPECT_LE(aDelta2, aMaxDeltaPercent)
|
||||
<< "Solution " << i << ": tangency2 distance error " << aDelta2 << "% exceeds 1%";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <GccEnt.hxx>
|
||||
#include <Geom2dAdaptor_Curve.hxx>
|
||||
#include <Geom2dGcc_Lin2d2Tan.hxx>
|
||||
#include <Geom2dGcc_QualifiedCurve.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Ellipse.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <GeomAPI.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
// Test OCC813: Geom2dGcc_Lin2d2Tan - tangent line between a 2D ellipse and a point.
|
||||
// Migrated from QABugs_17.cxx OCC813
|
||||
TEST(Geom2dGcc_Lin2d2TanTest, OCC813_EllipseAndPoint)
|
||||
{
|
||||
// Construct 3D ellipse and projection plane
|
||||
const gp_Ax2 anAx2(gp_Pnt(1262.224429, 425.040878, 363.609716),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560));
|
||||
|
||||
Handle(Geom_Ellipse) anEll = new Geom_Ellipse(anAx2, 150, 100);
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(gp_Ax3(anAx2));
|
||||
const gp_Pln aPln = aPlane->Pln();
|
||||
|
||||
// Project ellipse onto the plane and build 2D qualified curve
|
||||
Handle(Geom2d_Curve) aCurve2d = GeomAPI::To2d(anEll, aPln);
|
||||
Geom2dAdaptor_Curve anAdapt(aCurve2d);
|
||||
Geom2dGcc_QualifiedCurve aQCurve(anAdapt, GccEnt_outside);
|
||||
|
||||
// Query tangent line from 2D point to the projected ellipse
|
||||
const gp_Pnt2d aPnt2d(200.0, 200.0);
|
||||
Geom2dGcc_Lin2d2Tan aLinTan(aQCurve, aPnt2d, 0.1);
|
||||
|
||||
EXPECT_GT(aLinTan.NbSolutions(), 0) << "Expected at least one tangent line solution";
|
||||
}
|
||||
|
||||
// Test OCC814: Geom2dGcc_Lin2d2Tan - tangent line between a 2D circle and a 2D ellipse.
|
||||
// Migrated from QABugs_17.cxx OCC814
|
||||
TEST(Geom2dGcc_Lin2d2TanTest, OCC814_CircleAndEllipse)
|
||||
{
|
||||
const gp_Ax2 anAx2(gp_Pnt(1262.224429, 425.040878, 363.609716),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560));
|
||||
|
||||
Handle(Geom_Circle) aCir = new Geom_Circle(gp_Ax2(gp_Pnt(823.687192, 502.366825, 478.960440),
|
||||
gp_Dir(0.173648, 0.984808, 0.000000),
|
||||
gp_Dir(-0.932169, 0.164367, -0.322560)),
|
||||
50);
|
||||
Handle(Geom_Ellipse) anEll = new Geom_Ellipse(anAx2, 150, 100);
|
||||
Handle(Geom_Plane) aPlane = new Geom_Plane(gp_Ax3(anAx2));
|
||||
const gp_Pln aPln = aPlane->Pln();
|
||||
|
||||
// Project both curves onto the plane and build qualified curves
|
||||
Handle(Geom2d_Curve) aCurve2d = GeomAPI::To2d(anEll, aPln);
|
||||
Handle(Geom2d_Curve) aFromCurve2d = GeomAPI::To2d(aCir, aPln);
|
||||
Geom2dAdaptor_Curve anAdaptEll(aCurve2d);
|
||||
Geom2dAdaptor_Curve anAdaptCir(aFromCurve2d);
|
||||
Geom2dGcc_QualifiedCurve aQEll(anAdaptEll, GccEnt_outside);
|
||||
Geom2dGcc_QualifiedCurve aQCir(anAdaptCir, GccEnt_outside);
|
||||
|
||||
Geom2dGcc_Lin2d2Tan aLinTan(aQEll, aQCir, 0.1);
|
||||
|
||||
EXPECT_GT(aLinTan.NbSolutions(), 0) << "Expected at least one tangent line solution";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,173 @@
|
||||
// Copyright (c) 2026 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 <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepOffset_MakeOffset.hxx>
|
||||
#include <BRepOffsetAPI_MakeOffsetShape.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <Geom2dAPI_Interpolate.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <GeomAPI.hxx>
|
||||
#include <GeomConvert.hxx>
|
||||
#include <GeomFill_BSplineCurves.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <NCollection_HArray1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <ShapeFix_Shape.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// OCC28131: BRepOffset_MakeOffset can't create offset with a face made by filling 3 BSpline curves.
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//! Builds the filled face from 3 boundary BSpline/Bezier curves (common setup for all OCC28131
|
||||
//! tests).
|
||||
TopoDS_Shape createOCC28131Face()
|
||||
{
|
||||
const double aHeight = 8.5;
|
||||
const gp_Pnt aV0(-17.6, 0.0, 0.0);
|
||||
const gp_Pnt aV1(0, 32.8, 0.0);
|
||||
|
||||
// Outline Bezier curve
|
||||
NCollection_Array1<gp_Pnt> aBezierPoles(1, 4);
|
||||
aBezierPoles(1) = aV0;
|
||||
aBezierPoles(4) = aV1;
|
||||
aBezierPoles(2) = gp_Pnt(aV0.X(), (5.4 / 13.2) * aV1.Y(), 0);
|
||||
aBezierPoles(3) = gp_Pnt((6.0 / 6.8) * aV0.X(), aV1.Y(), 0);
|
||||
|
||||
occ::handle<Geom_BezierCurve> aBezier = new Geom_BezierCurve(aBezierPoles);
|
||||
occ::handle<Geom_BSplineCurve> anOutlineCurve = GeomConvert::CurveToBSplineCurve(aBezier);
|
||||
|
||||
// First side curve from 2D interpolation projected on YZ plane
|
||||
occ::handle<Geom_BSplineCurve> aCurve1;
|
||||
{
|
||||
occ::handle<NCollection_HArray1<gp_Pnt2d>> aHArray = new NCollection_HArray1<gp_Pnt2d>(1, 2);
|
||||
aHArray->SetValue(1, gp_Pnt2d(-aV1.Y(), 0));
|
||||
aHArray->SetValue(2, gp_Pnt2d(0, aHeight + aHeight / 2));
|
||||
Geom2dAPI_Interpolate anInterp(aHArray, false, 1e-6);
|
||||
anInterp.Load(gp_Vec2d(0, 1), gp_Vec2d(1, 0));
|
||||
anInterp.Perform();
|
||||
const gp_Pln aPln{gp_Ax3(gp_Pnt(), gp_Dir(gp_Dir::D::X), gp_Dir(gp_Dir::D::NY))};
|
||||
aCurve1 = occ::down_cast<Geom_BSplineCurve>(GeomAPI::To3d(anInterp.Curve(), aPln));
|
||||
}
|
||||
|
||||
// Second side curve from 2D interpolation projected on XZ plane
|
||||
occ::handle<Geom_BSplineCurve> aCurve2;
|
||||
{
|
||||
occ::handle<NCollection_HArray1<gp_Pnt2d>> aHArray = new NCollection_HArray1<gp_Pnt2d>(1, 3);
|
||||
aHArray->SetValue(1, gp_Pnt2d(-aV0.X(), 0));
|
||||
aHArray->SetValue(2, gp_Pnt2d(-aV0.X() - 2.6, aHeight));
|
||||
aHArray->SetValue(3, gp_Pnt2d(0, aHeight + aHeight / 2));
|
||||
Geom2dAPI_Interpolate anInterp(aHArray, false, 1e-6);
|
||||
anInterp.Perform();
|
||||
const gp_Pln aPln{gp_Ax3(gp_Pnt(), gp_Dir(gp_Dir::D::NY), gp_Dir(gp_Dir::D::NX))};
|
||||
aCurve2 = occ::down_cast<Geom_BSplineCurve>(GeomAPI::To3d(anInterp.Curve(), aPln));
|
||||
}
|
||||
|
||||
GeomFill_BSplineCurves aFill;
|
||||
aFill.Init(anOutlineCurve, aCurve1, aCurve2, GeomFill_CoonsStyle);
|
||||
|
||||
BRepBuilderAPI_MakeFace aFaceBuilder(aFill.Surface(), 0);
|
||||
return aFaceBuilder.IsDone() ? aFaceBuilder.Shape() : TopoDS_Shape();
|
||||
}
|
||||
|
||||
//! Returns the maximum BRep tolerance across all vertices, edges, and faces of theShape.
|
||||
double maxTolerance(const TopoDS_Shape& theShape)
|
||||
{
|
||||
double aMaxTol = 0.0;
|
||||
for (TopExp_Explorer anExp(theShape, TopAbs_VERTEX); anExp.More(); anExp.Next())
|
||||
aMaxTol = std::max(aMaxTol, BRep_Tool::Tolerance(TopoDS::Vertex(anExp.Current())));
|
||||
for (TopExp_Explorer anExp(theShape, TopAbs_EDGE); anExp.More(); anExp.Next())
|
||||
aMaxTol = std::max(aMaxTol, BRep_Tool::Tolerance(TopoDS::Edge(anExp.Current())));
|
||||
for (TopExp_Explorer anExp(theShape, TopAbs_FACE); anExp.More(); anExp.Next())
|
||||
aMaxTol = std::max(aMaxTol, BRep_Tool::Tolerance(TopoDS::Face(anExp.Current())));
|
||||
return aMaxTol;
|
||||
}
|
||||
|
||||
//! Returns the surface area of theShape.
|
||||
double surfaceArea(const TopoDS_Shape& theShape)
|
||||
{
|
||||
GProp_GProps aProps;
|
||||
BRepGProp::SurfaceProperties(theShape, aProps);
|
||||
return aProps.Mass();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(GeomFill_BSplineCurvesTest, OCC28131_FillSurfaceFromBezierAndInterpolatedCurves)
|
||||
{
|
||||
const TopoDS_Shape aFace = createOCC28131Face();
|
||||
ASSERT_FALSE(aFace.IsNull());
|
||||
EXPECT_TRUE(BRepCheck_Analyzer(aFace).IsValid());
|
||||
}
|
||||
|
||||
TEST(GeomFill_BSplineCurvesTest, OCC28131_SimpleOffsetOfFilledFace)
|
||||
{
|
||||
const TopoDS_Shape aFace = createOCC28131Face();
|
||||
ASSERT_FALSE(aFace.IsNull());
|
||||
|
||||
BRepOffsetAPI_MakeOffsetShape aMaker;
|
||||
aMaker.PerformBySimple(aFace, 10.0);
|
||||
ASSERT_TRUE(aMaker.IsDone());
|
||||
|
||||
const TopoDS_Shape aResult = aMaker.Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
EXPECT_TRUE(BRepCheck_Analyzer(aResult).IsValid());
|
||||
// checkmaxtol -ref 0.205 (1% relative tolerance)
|
||||
EXPECT_NEAR(maxTolerance(aResult), 0.205, 0.205 * 0.01);
|
||||
// checkprops -s 1693.7 (1% relative tolerance)
|
||||
EXPECT_NEAR(surfaceArea(aResult), 1693.7, 1693.7 * 0.01);
|
||||
}
|
||||
|
||||
TEST(GeomFill_BSplineCurvesTest, OCC28131_StandardOffsetOfFilledFace)
|
||||
{
|
||||
const TopoDS_Shape aFace = createOCC28131Face();
|
||||
ASSERT_FALSE(aFace.IsNull());
|
||||
|
||||
BRepOffset_MakeOffset aMaker;
|
||||
aMaker
|
||||
.Initialize(aFace, 10.0, Precision::Confusion(), BRepOffset_Skin, false, false, GeomAbs_Arc);
|
||||
aMaker.MakeOffsetShape();
|
||||
ASSERT_FALSE(aMaker.Shape().IsNull());
|
||||
|
||||
// The Draw test runs fixshape before checking - apply ShapeFix_Shape likewise
|
||||
occ::handle<ShapeFix_Shape> aFixer = new ShapeFix_Shape(aMaker.Shape());
|
||||
aFixer->Perform();
|
||||
const TopoDS_Shape aResult = aFixer->Shape();
|
||||
ASSERT_FALSE(aResult.IsNull());
|
||||
|
||||
EXPECT_TRUE(BRepCheck_Analyzer(aResult).IsValid());
|
||||
// checkmaxtol -ref 0.408
|
||||
EXPECT_NEAR(maxTolerance(aResult), 0.408, 0.408 * 0.01);
|
||||
// checkprops -s 1693.76
|
||||
EXPECT_NEAR(surfaceArea(aResult), 1693.76, 1693.76 * 0.01);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2026 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 <GeomFill_NSections.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//! Builds a simple degree-1 BSpline line segment from (0,0,0) to (1,0,0).
|
||||
static Handle(Geom_BSplineCurve) makeSimpleLinearCurve()
|
||||
{
|
||||
NCollection_Array1<gp_Pnt> aPoles(1, 2);
|
||||
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(1.0, 0.0, 0.0);
|
||||
|
||||
NCollection_Array1<double> aKnots(1, 2);
|
||||
aKnots(1) = 0.0;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
NCollection_Array1<int> aMults(1, 2);
|
||||
aMults(1) = 2;
|
||||
aMults(2) = 2;
|
||||
|
||||
return new Geom_BSplineCurve(aPoles, aKnots, aMults, 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Tests that GeomFill_NSections with a single-curve sequence does not throw.
|
||||
// The resulting BSplineSurface may be null for a degenerate single-section case,
|
||||
// but no exception should be raised (OCC27875).
|
||||
TEST(GeomFill_NSectionsTest, OCC27875_SingleCurveDoesNotThrow)
|
||||
{
|
||||
Handle(Geom_BSplineCurve) aCurve = makeSimpleLinearCurve();
|
||||
ASSERT_FALSE(aCurve.IsNull());
|
||||
|
||||
NCollection_Sequence<Handle(Geom_Curve)> aNC(new NCollection_IncAllocator());
|
||||
aNC.Append(Handle(Geom_Curve)(aCurve));
|
||||
|
||||
// Must not throw even though result may be degenerate
|
||||
EXPECT_NO_THROW({ GeomFill_NSections aNS(aNC); });
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <BRepMesh_CircleTool.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <gp_XY.hxx>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Returns true if thePoint lies on the circle defined by theCenter and theRadius.
|
||||
bool isOnCircle(const gp_XY& thePoint, const gp_XY& theCenter, const double theRadius)
|
||||
{
|
||||
static const double aSqPrec = Precision::PConfusion() * Precision::PConfusion();
|
||||
const gp_XY aDiff = thePoint - theCenter;
|
||||
return aDiff.SquareModulus() - theRadius * theRadius < aSqPrec;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// OCC24923: BRepMesh_CircleTool produces bad circles
|
||||
// For a large set of random non-degenerate triangles, every circumscribed circle
|
||||
// computed by BRepMesh_CircleTool::MakeCircle must pass through all three input points.
|
||||
TEST(BRepMesh_CircleTool_Test, OCC24923_CircumCirclePassesThroughAllVertices)
|
||||
{
|
||||
srand(42);
|
||||
|
||||
static const double aSqPrec = Precision::PConfusion() * Precision::PConfusion();
|
||||
const double aMinArea = 5.0 * M_PI / 180.0; // same threshold as the original command
|
||||
const int aNbTests = 100000;
|
||||
|
||||
int aNbFailed = 0;
|
||||
int i = 0;
|
||||
while (i < aNbTests)
|
||||
{
|
||||
gp_XY p[3];
|
||||
for (int j = 0; j < 3; ++j)
|
||||
p[j].SetCoord(static_cast<double>(rand()) / RAND_MAX, static_cast<double>(rand()) / RAND_MAX);
|
||||
|
||||
// Skip degenerate (nearly collinear) triangles - retry like the original.
|
||||
const gp_XY aV1 = p[1] - p[0];
|
||||
const gp_XY aV2 = p[2] - p[0];
|
||||
if (aV1.SquareModulus() <= aSqPrec || aV2.SquareModulus() <= aSqPrec || (aV1 ^ aV2) <= aMinArea)
|
||||
continue;
|
||||
|
||||
++i;
|
||||
|
||||
gp_XY aCenter;
|
||||
double aRadius = 0.0;
|
||||
if (!BRepMesh_CircleTool::MakeCircle(p[0], p[1], p[2], aCenter, aRadius))
|
||||
continue;
|
||||
|
||||
if (!isOnCircle(p[0], aCenter, aRadius) || !isOnCircle(p[1], aCenter, aRadius)
|
||||
|| !isOnCircle(p[2], aCenter, aRadius))
|
||||
{
|
||||
++aNbFailed;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow at most 1% failure rate (same threshold as the original Draw test).
|
||||
const double aFailRate = static_cast<double>(aNbFailed) / static_cast<double>(aNbTests);
|
||||
EXPECT_LE(aFailRate, 0.01) << "Too many bad circumscribed circles: " << aNbFailed << " / "
|
||||
<< aNbTests;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2026 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 <BRep_Builder.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Test OCC26407: BRepMesh_Delaun must not fail on a planar polygon with frontier edges.
|
||||
// The key check is that GetStatusFlags() == 0 (success) after meshing.
|
||||
// Migrated from QABugs_19.cxx OCC26407
|
||||
TEST(BRepMesh_IncrementalMeshTest, OCC26407_PlanarPolygonMeshStatus)
|
||||
{
|
||||
// Hardcoded octagon-like polygon lying in the Z=88.5 plane
|
||||
std::vector<gp_Pnt> aPnts = {
|
||||
gp_Pnt(587.90000000000009094947, 40.6758179230516248026106, 88.5),
|
||||
gp_Pnt(807.824182076948432040808, 260.599999999999965893949, 88.5),
|
||||
gp_Pnt(644.174182076948454778176, 424.249999999999943156581, 88.5000000000000142108547),
|
||||
gp_Pnt(629.978025792618950617907, 424.25, 88.5),
|
||||
gp_Pnt(793.628025792618700506864, 260.599999999999852207111, 88.5),
|
||||
gp_Pnt(587.900000000000204636308, 54.8719742073813492311274, 88.5),
|
||||
gp_Pnt(218.521974207381418864315, 424.250000000000056843419, 88.5),
|
||||
gp_Pnt(204.325817923051886282337, 424.249999999999943156581, 88.5)};
|
||||
|
||||
std::vector<TopoDS_Vertex> aVertices;
|
||||
aVertices.reserve(aPnts.size());
|
||||
for (const gp_Pnt& aPnt : aPnts)
|
||||
{
|
||||
aVertices.push_back(BRepBuilderAPI_MakeVertex(aPnt));
|
||||
}
|
||||
|
||||
BRepBuilderAPI_MakeWire aWireBuilder;
|
||||
for (size_t i = 0; i < aVertices.size(); ++i)
|
||||
{
|
||||
const TopoDS_Vertex& aV = aVertices[i];
|
||||
const TopoDS_Vertex& aW = aVertices[(i + 1) % aVertices.size()];
|
||||
aWireBuilder.Add(BRepBuilderAPI_MakeEdge(aV, aW));
|
||||
}
|
||||
ASSERT_TRUE(aWireBuilder.IsDone()) << "Wire construction failed";
|
||||
|
||||
const gp_Pnt& aV0 = aPnts[0];
|
||||
const gp_Pnt& aV1 = aPnts[1];
|
||||
const gp_Pnt& aV2 = aPnts[aPnts.size() - 1];
|
||||
const gp_Vec aFaceNormal = gp_Vec(aV0, aV1).Crossed(gp_Vec(aV0, aV2));
|
||||
|
||||
const TopoDS_Face aFace = BRepBuilderAPI_MakeFace(gp_Pln(aV0, aFaceNormal), aWireBuilder.Wire());
|
||||
|
||||
BRepMesh_IncrementalMesh aMesher(aFace, 1.e-7);
|
||||
EXPECT_EQ(aMesher.GetStatusFlags(), 0)
|
||||
<< "Meshing of the planar polygon face should succeed (status 0)";
|
||||
}
|
||||
@@ -3,7 +3,9 @@ set(OCCT_TKMesh_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKMesh_GTests_FILES
|
||||
BRepMesh_BaseMeshAlgo_Test.cxx
|
||||
BRepMesh_CircleTool_Test.cxx
|
||||
BRepMesh_Delaun_Test.cxx
|
||||
BRepMesh_DiscretAlgoFactory_Test.cxx
|
||||
BRepMesh_GeomTool_Test.cxx
|
||||
BRepMesh_IncrementalMesh_Test.cxx
|
||||
)
|
||||
|
||||
@@ -11,13 +11,21 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <GCPnts_AbscissaPoint.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <GeomAdaptor_Curve.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <GProp_PrincipalProps.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
@@ -115,3 +123,75 @@ TEST(BRepGPropTest, LinearProperties_SkipShared)
|
||||
EXPECT_NEAR(aPropsNotSkipped.Mass(), 240.0, Precision::Confusion())
|
||||
<< "Total edge length with SkipShared=false should be double";
|
||||
}
|
||||
|
||||
// Test OCC49: GProp_PrincipalProps::HasSymmetryAxis - cylinder has symmetry, cut does not.
|
||||
// Migrated from QABugs_16.cxx OCC49
|
||||
TEST(BRepGPropTest, OCC49_CylinderHasSymmetryAxis)
|
||||
{
|
||||
const TopoDS_Shape aCylinder = BRepPrimAPI_MakeCylinder(10., 20.).Shape();
|
||||
|
||||
GProp_GProps aProps;
|
||||
BRepGProp::VolumeProperties(aCylinder, aProps);
|
||||
const GProp_PrincipalProps aPrincipal = aProps.PrincipalProperties();
|
||||
EXPECT_TRUE(aPrincipal.HasSymmetryAxis());
|
||||
}
|
||||
|
||||
TEST(BRepGPropTest, OCC49_CutShapeHasNoSymmetryAxis)
|
||||
{
|
||||
const TopoDS_Shape aCylinder = BRepPrimAPI_MakeCylinder(10., 20.).Shape();
|
||||
const TopoDS_Shape aBox = BRepPrimAPI_MakeBox(10., 10., 10.).Shape();
|
||||
|
||||
BRepAlgoAPI_Cut aCut(aCylinder, aBox);
|
||||
ASSERT_TRUE(aCut.IsDone());
|
||||
|
||||
GProp_GProps aProps;
|
||||
BRepGProp::VolumeProperties(aCut.Shape(), aProps);
|
||||
const GProp_PrincipalProps aPrincipal = aProps.PrincipalProperties();
|
||||
EXPECT_FALSE(aPrincipal.HasSymmetryAxis());
|
||||
}
|
||||
|
||||
// OCC8797: Verify that GCPnts_AbscissaPoint::Length and BRepGProp::LinearProperties
|
||||
// produce consistent arc-length values for a degree-3 BSpline curve with 7 poles.
|
||||
// Both methods must agree within a tight relative tolerance.
|
||||
|
||||
TEST(BRepGPropTest, OCC8797_BSplineLengthConsistencyAbscissaVsLinearProperties)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt> aPoles(0, 6);
|
||||
aPoles(0) = gp_Pnt(0.0, 0.0, 0.0);
|
||||
aPoles(1) = gp_Pnt(1.0, 1.0, 0.0);
|
||||
aPoles(2) = gp_Pnt(2.0, 1.0, 0.0);
|
||||
aPoles(3) = gp_Pnt(3.0, 0.0, 0.0);
|
||||
aPoles(4) = gp_Pnt(4.0, 1.0, 0.0);
|
||||
aPoles(5) = gp_Pnt(5.0, 1.0, 0.0);
|
||||
aPoles(6) = gp_Pnt(6.0, 0.0, 0.0);
|
||||
|
||||
NCollection_Array1<double> aKnots(0, 2);
|
||||
aKnots(0) = 0.0;
|
||||
aKnots(1) = 0.5;
|
||||
aKnots(2) = 1.0;
|
||||
|
||||
NCollection_Array1<int> aMults(0, 2);
|
||||
aMults(0) = 4;
|
||||
aMults(1) = 3;
|
||||
aMults(2) = 4;
|
||||
|
||||
occ::handle<Geom_BSplineCurve> aSpline = new Geom_BSplineCurve(aPoles, aKnots, aMults, 3);
|
||||
ASSERT_FALSE(aSpline.IsNull());
|
||||
EXPECT_EQ(aSpline->NbPoles(), 7);
|
||||
EXPECT_EQ(aSpline->NbKnots(), 3);
|
||||
|
||||
// Method 1: GCPnts_AbscissaPoint::Length
|
||||
GeomAdaptor_Curve anAdaptor(aSpline);
|
||||
const double aLengthAbscissa = GCPnts_AbscissaPoint::Length(anAdaptor);
|
||||
EXPECT_GT(aLengthAbscissa, 0.0);
|
||||
|
||||
// Method 2: BRepGProp::LinearProperties on the equivalent edge
|
||||
const TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(aSpline);
|
||||
GProp_GProps aEdgeProps;
|
||||
BRepGProp::LinearProperties(aEdge, aEdgeProps);
|
||||
const double aLengthGProp = aEdgeProps.Mass();
|
||||
EXPECT_GT(aLengthGProp, 0.0);
|
||||
|
||||
// Both methods must agree within 0.1 %
|
||||
EXPECT_NEAR(aLengthAbscissa, aLengthGProp, aLengthGProp * 1e-3);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,18 @@
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakePolygon.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepOffsetAPI_ThruSections.hxx>
|
||||
#include <BSplCLib.hxx>
|
||||
#include <GC_MakeArcOfCircle.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <gce_MakeCirc.hxx>
|
||||
#include <gp.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
@@ -324,3 +333,61 @@ TEST(BRepOffsetAPI_ThruSections_Test, BSplineProfilesWithDifferentPoleCount)
|
||||
EXPECT_FALSE(aThruSections.Shape().IsNull()) << "ThruSections should produce a valid shape";
|
||||
}
|
||||
}
|
||||
|
||||
// Test OCC895: BRepOffsetAPI_ThruSections with two circular arc wires.
|
||||
// Regression test for incorrect computation of mutual orientations of wire segments
|
||||
// that caused a twisted surface to be created.
|
||||
TEST(BRepOffsetAPI_ThruSections_Test, OCC895_TwoCircularArcWires_NoTwist)
|
||||
{
|
||||
// Build the two wires using circular arcs at different positions,
|
||||
// reproducing exactly the OCC895 DRAW command with angle=5, reverse=0, order=0.
|
||||
const double aRad = 1.0;
|
||||
const double aAngle = 5.0 * M_PI / 180.0;
|
||||
|
||||
// Wire 1: arc from a circle whose axis is rotated 5 degrees around Z
|
||||
gp_Pnt aCenter1(0, 10, 0);
|
||||
gp_Ax2 aAxis1(aCenter1, -gp::DY(), gp::DX());
|
||||
aAxis1.Rotate(gp_Ax1(aCenter1, gp::DZ()), aAngle);
|
||||
|
||||
gce_MakeCirc aMakeCirc1(aAxis1, aRad);
|
||||
ASSERT_TRUE(aMakeCirc1.IsDone());
|
||||
GC_MakeArcOfCircle aMakeArc1(aMakeCirc1.Value(), 0, M_PI / 2, true);
|
||||
ASSERT_TRUE(aMakeArc1.IsDone());
|
||||
const occ::handle<Geom_TrimmedCurve>& aArc1 = aMakeArc1.Value();
|
||||
|
||||
BRepBuilderAPI_MakeEdge aMakeEdge1(aArc1, aArc1->StartPoint(), aArc1->EndPoint());
|
||||
ASSERT_TRUE(aMakeEdge1.IsDone());
|
||||
BRepBuilderAPI_MakeWire aMakeWire1(aMakeEdge1.Edge());
|
||||
ASSERT_TRUE(aMakeWire1.IsDone());
|
||||
const TopoDS_Wire& aWire1 = aMakeWire1.Wire();
|
||||
|
||||
// Wire 2: arc from a circle at a different center with fixed axis
|
||||
gp_Pnt aCenter2(10, 0, 0);
|
||||
gp_Ax2 aAxis2(aCenter2, -gp::DX(), gp::DZ());
|
||||
|
||||
gce_MakeCirc aMakeCirc2(aAxis2, aRad);
|
||||
ASSERT_TRUE(aMakeCirc2.IsDone());
|
||||
GC_MakeArcOfCircle aMakeArc2(aMakeCirc2.Value(), 0, M_PI / 2, true);
|
||||
ASSERT_TRUE(aMakeArc2.IsDone());
|
||||
const occ::handle<Geom_TrimmedCurve>& aArc2 = aMakeArc2.Value();
|
||||
|
||||
BRepBuilderAPI_MakeEdge aMakeEdge2(aArc2, aArc2->StartPoint(), aArc2->EndPoint());
|
||||
ASSERT_TRUE(aMakeEdge2.IsDone());
|
||||
BRepBuilderAPI_MakeWire aMakeWire2(aMakeEdge2.Edge());
|
||||
ASSERT_TRUE(aMakeWire2.IsDone());
|
||||
const TopoDS_Wire& aWire2 = aMakeWire2.Wire();
|
||||
|
||||
// Build ThruSections shell with order=0: wire2 first, then wire1
|
||||
BRepOffsetAPI_ThruSections aThruSect(false, true);
|
||||
aThruSect.AddWire(aWire2);
|
||||
aThruSect.AddWire(aWire1);
|
||||
aThruSect.Build();
|
||||
|
||||
ASSERT_TRUE(aThruSect.IsDone()) << "ThruSections must succeed";
|
||||
ASSERT_FALSE(aThruSect.Shape().IsNull()) << "ThruSections must produce a non-null shape";
|
||||
|
||||
// Verify surface area is approximately 18.1614 (reference value from DRAW test)
|
||||
GProp_GProps aProps;
|
||||
BRepGProp::SurfaceProperties(aThruSect.Shape(), aProps);
|
||||
EXPECT_NEAR(aProps.Mass(), 18.1614, 0.01) << "Surface area should be approximately 18.1614";
|
||||
}
|
||||
|
||||
@@ -13,12 +13,24 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepAdaptor_CompCurve.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <GC_MakeArcOfCircle.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
#include <TopAbs_Orientation.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
|
||||
// Test OCC5696: BRepAdaptor_CompCurve::Edge() method
|
||||
// Migrated from QABugs_5.cxx
|
||||
@@ -57,3 +69,111 @@ TEST(BRepAdaptor_CompCurve_Test, OCC5696_EdgeMethod)
|
||||
// The parameter should be approximately half of the edge length
|
||||
EXPECT_NEAR(1.0, aParEdge, 0.01) << "Edge parameter should be approximately 1.0";
|
||||
}
|
||||
|
||||
// Test OCC29430: BRepAdaptor_CompCurve::Value() at boundary parameters matches wire vertices.
|
||||
// The bug was that evaluating a composite curve at its First/LastParameter
|
||||
// did not return the correct endpoint.
|
||||
TEST(BRepAdaptor_CompCurve_Test, OCC29430_ArcBoundaryPoints)
|
||||
{
|
||||
const double r45 = M_PI / 4.0, r225 = 3.0 * M_PI / 4.0;
|
||||
|
||||
GC_MakeArcOfCircle arcMaker(
|
||||
gp_Circ(gp_Ax2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(gp_Dir::D::Z), gp_Dir(gp_Dir::D::X)), 1.0),
|
||||
r45,
|
||||
r225,
|
||||
true);
|
||||
BRepBuilderAPI_MakeEdge edgeMaker(arcMaker.Value());
|
||||
BRepBuilderAPI_MakeWire wireMaker(edgeMaker.Edge());
|
||||
const TopoDS_Wire aWire = wireMaker.Wire();
|
||||
|
||||
BRepAdaptor_CompCurve aCurve(aWire);
|
||||
const gp_Pnt aStartPt = aCurve.Value(aCurve.FirstParameter());
|
||||
const gp_Pnt anEndPt = aCurve.Value(aCurve.LastParameter());
|
||||
|
||||
// Collect wire vertices
|
||||
NCollection_List<gp_Pnt> aVertices;
|
||||
for (TopExp_Explorer anExp(aWire, TopAbs_VERTEX); anExp.More(); anExp.Next())
|
||||
{
|
||||
aVertices.Append(BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current())));
|
||||
}
|
||||
ASSERT_GE(aVertices.Size(), 1);
|
||||
|
||||
// Start point should match one of the wire vertices (within 1e-7 tolerance)
|
||||
bool aStartMatchesAnyVertex = false;
|
||||
bool anEndMatchesAnyVertex = false;
|
||||
for (const gp_Pnt& aV : aVertices)
|
||||
{
|
||||
if (aStartPt.Distance(aV) < 1.0e-7)
|
||||
aStartMatchesAnyVertex = true;
|
||||
if (anEndPt.Distance(aV) < 1.0e-7)
|
||||
anEndMatchesAnyVertex = true;
|
||||
}
|
||||
EXPECT_TRUE(aStartMatchesAnyVertex) << "Start point does not match any wire vertex";
|
||||
EXPECT_TRUE(anEndMatchesAnyVertex) << "End point does not match any wire vertex";
|
||||
EXPECT_GT(aStartPt.Distance(anEndPt), 1.0e-7) << "Start and end points should be different";
|
||||
}
|
||||
|
||||
// Test OCC30869: BRepAdaptor_CompCurve D1 at boundary parameters of a wire with reversed edge.
|
||||
// The bug was that a wire with a single reversed-orientation trimmed-circle edge returned
|
||||
// incorrect boundary point coordinates and tangent directions.
|
||||
// Migrated from QABugs_20.cxx OCC30869
|
||||
TEST(BRepAdaptor_CompCurve_Test, OCC30869_ReversedEdgeBoundaryPoints)
|
||||
{
|
||||
// Build a circle: center(1,0,0), Z-axis(0,-1,0), X-axis(0,0,-1), radius=1
|
||||
const gp_Ax2 anAx2(gp_Pnt(1., 0., 0.), gp_Dir(0., -1., 0.), gp_Dir(0., 0., -1.));
|
||||
Handle(Geom_Circle) aCircle = new Geom_Circle(anAx2, 1.0);
|
||||
|
||||
const double t1 = M_PI / 2.0; // 1.5707963267949
|
||||
const double t2 = 3.0 * M_PI / 2.0; // 4.71238898038469
|
||||
|
||||
Handle(Geom_TrimmedCurve) aTrimmed = new Geom_TrimmedCurve(aCircle, t1, t2);
|
||||
TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aTrimmed).Edge();
|
||||
|
||||
// Reverse the edge, then wrap it in a wire
|
||||
anEdge.Orientation(TopAbs_REVERSED);
|
||||
TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge).Wire();
|
||||
|
||||
BRepAdaptor_CompCurve aBACC(aWire);
|
||||
const double aFirst = aBACC.FirstParameter();
|
||||
const double aLast = aBACC.LastParameter();
|
||||
|
||||
gp_Pnt aPFirst, aPLast;
|
||||
gp_Vec aVFirst, aVLast;
|
||||
aBACC.D1(aFirst, aPFirst, aVFirst);
|
||||
aBACC.D1(aLast, aPLast, aVLast);
|
||||
|
||||
if (aVFirst.SquareMagnitude() > gp::Resolution())
|
||||
aVFirst.Normalize();
|
||||
if (aVLast.SquareMagnitude() > gp::Resolution())
|
||||
aVLast.Normalize();
|
||||
|
||||
// Reference: inverse circle (normal = (0,1,0)), evaluated at the same parameters
|
||||
const gp_Ax2 anAx2Ref(gp_Pnt(1., 0., 0.), gp_Dir(0., 1., 0.), gp_Dir(0., 0., -1.));
|
||||
Handle(Geom_Circle) aCircleRef = new Geom_Circle(anAx2Ref, 1.0);
|
||||
|
||||
gp_Pnt aRefP1, aRefP2;
|
||||
gp_Vec aRefV1, aRefV2;
|
||||
aCircleRef->D1(t1, aRefP1, aRefV1);
|
||||
aCircleRef->D1(t2, aRefP2, aRefV2);
|
||||
if (aRefV1.SquareMagnitude() > gp::Resolution())
|
||||
aRefV1.Normalize();
|
||||
if (aRefV2.SquareMagnitude() > gp::Resolution())
|
||||
aRefV2.Normalize();
|
||||
|
||||
const double aTol = 1.e-7;
|
||||
EXPECT_NEAR(aPFirst.X(), aRefP1.X(), aTol) << "First point X";
|
||||
EXPECT_NEAR(aPFirst.Y(), aRefP1.Y(), aTol) << "First point Y";
|
||||
EXPECT_NEAR(aPFirst.Z(), aRefP1.Z(), aTol) << "First point Z";
|
||||
|
||||
EXPECT_NEAR(aVFirst.X(), aRefV1.X(), aTol) << "First tangent X";
|
||||
EXPECT_NEAR(aVFirst.Y(), aRefV1.Y(), aTol) << "First tangent Y";
|
||||
EXPECT_NEAR(aVFirst.Z(), aRefV1.Z(), aTol) << "First tangent Z";
|
||||
|
||||
EXPECT_NEAR(aPLast.X(), aRefP2.X(), aTol) << "Last point X";
|
||||
EXPECT_NEAR(aPLast.Y(), aRefP2.Y(), aTol) << "Last point Y";
|
||||
EXPECT_NEAR(aPLast.Z(), aRefP2.Z(), aTol) << "Last point Z";
|
||||
|
||||
EXPECT_NEAR(aVLast.X(), aRefV2.X(), aTol) << "Last tangent X";
|
||||
EXPECT_NEAR(aVLast.Y(), aRefV2.Y(), aTol) << "Last tangent Y";
|
||||
EXPECT_NEAR(aVLast.Z(), aRefV2.Z(), aTol) << "Last tangent Z";
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BSplineSurface.hxx>
|
||||
#include <GeomAdaptor_Surface.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
@@ -932,3 +933,95 @@ TEST_F(Geom_BSplineSurface_Test, WeightsArray_Rational_ReturnsOwning)
|
||||
EXPECT_DOUBLE_EQ(aWeights(1, 1), 1.0);
|
||||
EXPECT_EQ(&aWeights, &aRational->WeightsArray());
|
||||
}
|
||||
|
||||
// OCC30990: Foundation Classes - unexpected change in numerical results on bsplines after 0029769
|
||||
// Verify that evaluating a B-Spline surface at a knot gives consistent results regardless of
|
||||
// which span was evaluated beforehand (i.e., the cache is updated correctly).
|
||||
TEST_F(Geom_BSplineSurface_Test, OCC30990_CacheConsistencyAtKnots)
|
||||
{
|
||||
// Build a degree-3 B-Spline surface with 3 interior knots in U (4 spans) and 2 in V (3 spans).
|
||||
// Poles: 7 x 5
|
||||
const int aNbU = 7;
|
||||
const int aNbV = 5;
|
||||
NCollection_Array2<gp_Pnt> aPoles(1, aNbU, 1, aNbV);
|
||||
for (int i = 1; i <= aNbU; ++i)
|
||||
for (int j = 1; j <= aNbV; ++j)
|
||||
aPoles(i, j) =
|
||||
gp_Pnt(static_cast<double>(i - 1),
|
||||
static_cast<double>(j - 1),
|
||||
std::sin(static_cast<double>(i) * 0.5) * std::cos(static_cast<double>(j) * 0.7));
|
||||
|
||||
// Knot vector in U: [0, 0.25, 0.5, 0.75, 1] with multiplicities [4, 1, 1, 1, 4]
|
||||
NCollection_Array1<double> aUKnots(1, 5);
|
||||
aUKnots(1) = 0.0;
|
||||
aUKnots(2) = 0.25;
|
||||
aUKnots(3) = 0.5;
|
||||
aUKnots(4) = 0.75;
|
||||
aUKnots(5) = 1.0;
|
||||
NCollection_Array1<int> aUMults(1, 5);
|
||||
aUMults(1) = 4;
|
||||
aUMults(2) = 1;
|
||||
aUMults(3) = 1;
|
||||
aUMults(4) = 1;
|
||||
aUMults(5) = 4;
|
||||
|
||||
// Knot vector in V: [0, 0.5, 1] with multiplicities [4, 1, 4]
|
||||
NCollection_Array1<double> aVKnots(1, 3);
|
||||
aVKnots(1) = 0.0;
|
||||
aVKnots(2) = 0.5;
|
||||
aVKnots(3) = 1.0;
|
||||
NCollection_Array1<int> aVMults(1, 3);
|
||||
aVMults(1) = 4;
|
||||
aVMults(2) = 1;
|
||||
aVMults(3) = 4;
|
||||
|
||||
const occ::handle<Geom_BSplineSurface> aSurf =
|
||||
new Geom_BSplineSurface(aPoles, aUKnots, aVKnots, aUMults, aVMults, 3, 3);
|
||||
ASSERT_FALSE(aSurf.IsNull());
|
||||
|
||||
GeomAdaptor_Surface aAdaptor(aSurf);
|
||||
|
||||
// For each interior U knot, verify that evaluation at the knot is consistent
|
||||
// regardless of whether the previous evaluation was in the span before or after.
|
||||
int aNbErr = 0;
|
||||
for (int i = 2; i < aSurf->NbUKnots(); ++i)
|
||||
{
|
||||
const double aUknot = aSurf->UKnot(i);
|
||||
const double aUprev = 0.5 * (aUknot + aSurf->UKnot(i - 1));
|
||||
const double aUnext = 0.5 * (aUknot + aSurf->UKnot(i + 1));
|
||||
|
||||
for (int j = 1; j < aSurf->NbVKnots(); ++j)
|
||||
{
|
||||
const double aV = 0.5 * (aSurf->VKnot(j) + aSurf->VKnot(j + 1));
|
||||
aAdaptor.Value(aUprev, aV); // populate cache from span before
|
||||
const gp_Pnt aP1 = aAdaptor.Value(aUknot, aV);
|
||||
aAdaptor.Value(aUnext, aV); // populate cache from span after
|
||||
const gp_Pnt aP2 = aAdaptor.Value(aUknot, aV);
|
||||
|
||||
if (aP1.X() != aP2.X() || aP1.Y() != aP2.Y() || aP1.Z() != aP2.Z())
|
||||
++aNbErr;
|
||||
}
|
||||
}
|
||||
|
||||
// Same check for interior V knots
|
||||
for (int j = 2; j < aSurf->NbVKnots(); ++j)
|
||||
{
|
||||
const double aVknot = aSurf->VKnot(j);
|
||||
const double aVprev = 0.5 * (aVknot + aSurf->VKnot(j - 1));
|
||||
const double aVnext = 0.5 * (aVknot + aSurf->VKnot(j + 1));
|
||||
|
||||
for (int i = 1; i < aSurf->NbUKnots(); ++i)
|
||||
{
|
||||
const double aU = 0.5 * (aSurf->UKnot(i) + aSurf->UKnot(i + 1));
|
||||
aAdaptor.Value(aU, aVprev);
|
||||
const gp_Pnt aP1 = aAdaptor.Value(aU, aVknot);
|
||||
aAdaptor.Value(aU, aVnext);
|
||||
const gp_Pnt aP2 = aAdaptor.Value(aU, aVknot);
|
||||
|
||||
if (aP1.X() != aP2.X() || aP1.Y() != aP2.Y() || aP1.Z() != aP2.Z())
|
||||
++aNbErr;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, aNbErr) << "BSpline surface cache is inconsistent at span knots";
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
|
||||
class Geom_BezierCurve_Test : public ::testing::Test
|
||||
{
|
||||
@@ -524,3 +525,29 @@ TEST_F(Geom_BezierCurve_Test, WeightsArray_Rational_ReturnsOwning)
|
||||
EXPECT_DOUBLE_EQ(aWeights(3), 1.0);
|
||||
EXPECT_EQ(&aWeights, &aRational->WeightsArray());
|
||||
}
|
||||
|
||||
// Test OCC2569: Geom_BezierCurve degree equals NbPoles - 1.
|
||||
// Migrated from QABugs_17.cxx OCC2569
|
||||
TEST(Geom_BezierCurveTest, OCC2569_DegreeEqualsNbPolesMinusOne)
|
||||
{
|
||||
const int aNbPoles = 26;
|
||||
NCollection_Array1<gp_Pnt> aPoles(1, aNbPoles);
|
||||
for (int i = 1; i <= aNbPoles; ++i)
|
||||
aPoles.SetValue(i, gp_Pnt(i + 10, i * 2 + 20, i * 3 + 45));
|
||||
|
||||
Handle(Geom_BezierCurve) aCurve = new Geom_BezierCurve(aPoles);
|
||||
ASSERT_FALSE(aCurve.IsNull());
|
||||
EXPECT_EQ(aCurve->Degree(), aNbPoles - 1);
|
||||
}
|
||||
|
||||
// Test OCC2569: Geom_BezierCurve throws when NbPoles exceeds maximum allowed.
|
||||
// Migrated from QABugs_17.cxx OCC2569 (bug2569_2)
|
||||
TEST(Geom_BezierCurveTest, OCC2569_ThrowsForTooManyPoles)
|
||||
{
|
||||
const int aNbPoles = 29;
|
||||
NCollection_Array1<gp_Pnt> aPoles(1, aNbPoles);
|
||||
for (int i = 1; i <= aNbPoles; ++i)
|
||||
aPoles.SetValue(i, gp_Pnt(i + 10, i * 2 + 20, i * 3 + 45));
|
||||
|
||||
EXPECT_THROW(new Geom_BezierCurve(aPoles), Standard_Failure);
|
||||
}
|
||||
|
||||
@@ -35,9 +35,11 @@ set(OCCT_TKGeomBase_GTests_FILES
|
||||
GC_MakeCircle2d_Test.cxx
|
||||
GC_MakeConicalSurface_Test.cxx
|
||||
GC_MakePlane_Test.cxx
|
||||
GC_MakeParabola2d_Test.cxx
|
||||
GC_MakeSegment2d_Test.cxx
|
||||
GCPnts_AbscissaPoint_Test.cxx
|
||||
GeomConvert_CompCurveToBSplineCurve_Test.cxx
|
||||
Geom2dConvert_CompCurveToBSplineCurve_Test.cxx
|
||||
GeomConvert_Test.cxx
|
||||
Hermit_Test.cxx
|
||||
IntAna_IntQuadQuad_Test.cxx
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2026 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 <gtest/gtest.h>
|
||||
|
||||
#include <GC_MakeParabola2d.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Parab2d.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Helper: verify a parabola built from directrix+focus against expected values.
|
||||
void CheckParabola2d(const gp_Ax2d& theAxes,
|
||||
const gp_Pnt2d& theFocus,
|
||||
bool theSense,
|
||||
double theExpectedFocal,
|
||||
double theExpectedVertX,
|
||||
double theExpectedVertY,
|
||||
double theExpectedParam,
|
||||
const double theExpectedCoeffs[6])
|
||||
{
|
||||
const double aCompareTol = 1.0e-12;
|
||||
|
||||
GC_MakeParabola2d aPrb(theAxes, theFocus, theSense);
|
||||
ASSERT_FALSE(aPrb.Value().IsNull()) << "GC_MakeParabola2d should produce a non-null result";
|
||||
|
||||
const gp_Parab2d& aParab = aPrb.Value()->Parab2d();
|
||||
const gp_Pnt2d aVert(aParab.Location());
|
||||
|
||||
EXPECT_NEAR(aParab.Focal(), theExpectedFocal, aCompareTol) << "Wrong focal length";
|
||||
EXPECT_NEAR(aVert.X(), theExpectedVertX, aCompareTol) << "Wrong vertex X";
|
||||
EXPECT_NEAR(aVert.Y(), theExpectedVertY, aCompareTol) << "Wrong vertex Y";
|
||||
EXPECT_NEAR(aParab.Parameter(), theExpectedParam, aCompareTol) << "Wrong parameter";
|
||||
|
||||
double aF[6];
|
||||
aParab.Coefficients(aF[0], aF[1], aF[2], aF[3], aF[4], aF[5]);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
EXPECT_NEAR(aF[i], theExpectedCoeffs[i], aCompareTol)
|
||||
<< "Wrong coefficient [" << i << "]: got " << aF[i] << ", expected " << theExpectedCoeffs[i];
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Test OCC26747 (case 1): parabola with vertex at (0.5, 3.0) opening in +X direction.
|
||||
// Directrix Y-axis at x=0, y=3; focus at (1.0, 3.0); sense=true.
|
||||
// Equation: (y-3)^2 = 2*(x-0.5), i.e. 1*Y^2 + 2*(-1)*X + 2*(-3)*Y + 10 = 0.
|
||||
TEST(GC_MakeParabola2d_Test, OCC26747_1_ParabolaOpeningRight)
|
||||
{
|
||||
const gp_Ax2d anAxes(gp_Pnt2d(0.0, 3.0), gp_Dir2d(gp_Dir2d::D::Y));
|
||||
const gp_Pnt2d aFocus(1.0, 3.0);
|
||||
const double aCoeffs[6] = {0.0, 1.0, 0.0, -1.0, -3.0, 10.0};
|
||||
CheckParabola2d(anAxes, aFocus, true, 0.5, 0.5, 3.0, 1.0, aCoeffs);
|
||||
}
|
||||
|
||||
// Test OCC26747 (case 2): parabola with vertex at (-0.5, 3.0) opening in -X direction.
|
||||
// Directrix Y-axis at origin; focus at (-1.0, 3.0); sense=false.
|
||||
// Equation (WCS): (y-3)^2 = 2*(-x-0.5), i.e. 1*Y^2 + 2*1*X + 2*(-3)*Y + 10 = 0.
|
||||
TEST(GC_MakeParabola2d_Test, OCC26747_2_ParabolaOpeningLeft)
|
||||
{
|
||||
const gp_Ax2d anAxes(gp_Pnt2d(0.0, 0.0), gp_Dir2d(gp_Dir2d::D::Y));
|
||||
const gp_Pnt2d aFocus(-1.0, 3.0);
|
||||
const double aCoeffs[6] = {0.0, 1.0, 0.0, 1.0, -3.0, 10.0};
|
||||
CheckParabola2d(anAxes, aFocus, false, 0.5, -0.5, 3.0, 1.0, aCoeffs);
|
||||
}
|
||||
|
||||
// Test OCC26747 (case 3): degenerate parabola where focus coincides with vertex.
|
||||
// Directrix Y-axis at origin; focus at (0.0, 3.0); sense=false.
|
||||
// Focal length = 0, parameter = 0. Equation: Y^2 + 2*(-3)*Y + 9 = 0 (line y=3).
|
||||
TEST(GC_MakeParabola2d_Test, OCC26747_3_DegenerateParabola)
|
||||
{
|
||||
const gp_Ax2d anAxes(gp_Pnt2d(0.0, 0.0), gp_Dir2d(gp_Dir2d::D::Y));
|
||||
const gp_Pnt2d aFocus(0.0, 3.0);
|
||||
const double aCoeffs[6] = {0.0, 1.0, 0.0, 0.0, -3.0, 9.0};
|
||||
CheckParabola2d(anAxes, aFocus, false, 0.0, 0.0, 3.0, 0.0, aCoeffs);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2026 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 <GC_MakeCircle2d.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(Geom2dConvert_CompCurveToBSplineCurveTest, OCC30747_ClosedContourFromCircleArcs)
|
||||
{
|
||||
// OCC30747: 2d Curves concatenator must properly handle closed contours.
|
||||
// Split a full circle into 10 arcs and assemble them into a closed BSpline.
|
||||
const occ::handle<Geom2d_Circle> aCirc = GC_MakeCircle2d(gp_Pnt2d(0, 0), 50);
|
||||
ASSERT_FALSE(aCirc.IsNull());
|
||||
|
||||
const double aF = aCirc->FirstParameter();
|
||||
const double aL = aCirc->LastParameter();
|
||||
const int aNb = 10;
|
||||
const double aDelta = (aF + aL) / aNb;
|
||||
|
||||
occ::handle<Geom2d_TrimmedCurve> aFTrim = new Geom2d_TrimmedCurve(aCirc, aF, aDelta);
|
||||
Geom2dConvert_CompCurveToBSplineCurve aRes(aFTrim);
|
||||
|
||||
for (int anId = 1; anId < aNb; anId++)
|
||||
{
|
||||
occ::handle<Geom2d_TrimmedCurve> aLTrim;
|
||||
if (anId == (aNb - 1))
|
||||
{
|
||||
aLTrim = new Geom2d_TrimmedCurve(aCirc, anId * aDelta, aF);
|
||||
}
|
||||
else
|
||||
{
|
||||
aLTrim = new Geom2d_TrimmedCurve(aCirc, anId * aDelta, (anId + 1) * aDelta);
|
||||
}
|
||||
aRes.Add(aLTrim, Precision::PConfusion());
|
||||
}
|
||||
|
||||
const occ::handle<Geom2d_BSplineCurve> aBSpline = aRes.BSplineCurve();
|
||||
ASSERT_FALSE(aBSpline.IsNull());
|
||||
EXPECT_TRUE(aBSpline->IsClosed())
|
||||
<< "Assembled BSpline curve from closed circle arcs must be closed";
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
puts "============"
|
||||
puts "0031320: TObj - method TObj_Object::GetFatherObject() is not protected against deleted object"
|
||||
puts "============"
|
||||
puts ""
|
||||
|
||||
pload TOBJ QAcommands
|
||||
|
||||
# create document with object and sub-object
|
||||
TObjNew TD1
|
||||
TObjAddObj TD1 obj
|
||||
TObjAddChild TD1 obj subobj1
|
||||
|
||||
OCC31320 TD1 obj
|
||||
@@ -1,25 +0,0 @@
|
||||
puts "==========="
|
||||
puts "OCC15489"
|
||||
puts "==========="
|
||||
|
||||
set BugNumber OCC15489
|
||||
|
||||
######################################################
|
||||
# Constructor gp_Lin2d(A, B, C) creates line with origin point in infinity
|
||||
######################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set A 1e-20
|
||||
set B -1.
|
||||
set C 2.
|
||||
|
||||
set OriginList [OCC15489 $A $B $C]
|
||||
regexp {X_0 += +([-0-9.+eE]+)} $OriginList full X_0
|
||||
regexp {Y_0 += +([-0-9.+eE]+)} $OriginList full Y_0
|
||||
|
||||
set good_X_0 -1.9999999999999999e-20
|
||||
set good_Y_0 2
|
||||
|
||||
checkreal "X_0" ${X_0} ${good_X_0} 0 0.001
|
||||
checkreal "Y_0" ${Y_0} ${good_Y_0} 0 0.001
|
||||
@@ -1,34 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC181"
|
||||
puts "OCC701"
|
||||
puts "========"
|
||||
######################################################
|
||||
# Resource_Manager class doesn't return status of saving resources in a file.
|
||||
######################################################
|
||||
# Add method BuildPath to OSD_Directory
|
||||
######################################################
|
||||
|
||||
# Clear tmp-data
|
||||
######################################################################
|
||||
set tmp ${imagedir}
|
||||
######################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set log [OCC181 OCC181 ${imagedir} ${tmp}/1 0]
|
||||
|
||||
set list [split ${log}]
|
||||
set ll [llength ${list}]
|
||||
set status [lindex ${list} [expr ${ll} - 2] ]
|
||||
|
||||
if { ${status} == "TRUE"} then {
|
||||
puts "OCC181: OK"
|
||||
} else {
|
||||
puts "OCC181: Error"
|
||||
}
|
||||
|
||||
if { ! [file exists ${tmp}/1/OCC181] } {
|
||||
puts "Error: user resource file is not found!"
|
||||
}
|
||||
|
||||
file delete -force ${tmp}/1
|
||||
@@ -1,34 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC181"
|
||||
puts "OCC701"
|
||||
puts "========"
|
||||
######################################################
|
||||
# Resource_Manager class doesn't return status of saving resources in a file.
|
||||
######################################################
|
||||
# Add method BuildPath to OSD_Directory
|
||||
######################################################
|
||||
|
||||
# Clear tmp-data
|
||||
######################################################################
|
||||
set tmp ${imagedir}
|
||||
######################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set log [OCC181 OCC181 ${imagedir} ${tmp}/2/2/3 0]
|
||||
|
||||
set list [split ${log}]
|
||||
set ll [llength ${list}]
|
||||
set status [lindex ${list} [expr ${ll} - 2] ]
|
||||
|
||||
if { ${status} == "TRUE"} then {
|
||||
puts "OCC181: OK"
|
||||
} else {
|
||||
puts "OCC181: Error"
|
||||
}
|
||||
|
||||
if { ! [file exists ${tmp}/2/2/3/OCC181] } {
|
||||
puts "Error: user resource file is not found!"
|
||||
}
|
||||
|
||||
file delete -force ${tmp}/2
|
||||
@@ -1,19 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC22611"
|
||||
puts "========"
|
||||
puts ""
|
||||
#######################################################################
|
||||
# Memory leak in expression interpreter
|
||||
#######################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set BugNumber OCC22611
|
||||
set listmem {}
|
||||
|
||||
for {set i 1} {$i < 10} {incr i} {
|
||||
OCC22611 "0.1214343" 10
|
||||
|
||||
lappend listmem [meminfo h]
|
||||
checktrend $listmem 0 1 "Memory leak detected"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
puts "================"
|
||||
puts "OCC24537"
|
||||
puts "================"
|
||||
puts ""
|
||||
#######################################################################
|
||||
# GCC compiler warnings in byte order reversion code.
|
||||
# The matter of this test is to ensure correctness of work of the methods
|
||||
# (in the file FSD_FileHeader.hxx) of inversion of numbers between little/big endian.
|
||||
# Attention! The test is created for working on a little endian platform.
|
||||
#######################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
# The following command gives an error output if conversion is wrong
|
||||
OCC24537
|
||||
@@ -1,11 +0,0 @@
|
||||
puts "============"
|
||||
puts "OCC25329"
|
||||
puts "============"
|
||||
puts ""
|
||||
#######################################################################
|
||||
# ExprIntrp_GenExp can not parse unary plus
|
||||
#######################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC22611 "+1" 1
|
||||
@@ -1,9 +0,0 @@
|
||||
puts "=========="
|
||||
puts "0025574: gp_YawPitchRoll Euler Angle computation gives wrong results"
|
||||
puts "=========="
|
||||
|
||||
pload QAcommands
|
||||
|
||||
puts "Checking conversions of Euler angles in gp_Quaternion"
|
||||
OCC25574
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
puts "Test loading of resources from different paths"
|
||||
puts "0027849: ResourceManager path computations fail for the folders containing dots"
|
||||
|
||||
pload QAcommands
|
||||
|
||||
|
||||
set paths {
|
||||
"path"
|
||||
"path.with.dots"
|
||||
"path with spaces"
|
||||
"nested/dirs/path with spaces"
|
||||
}
|
||||
|
||||
# key word to be saved in resource file and then checked
|
||||
set keyw ok
|
||||
|
||||
foreach p $paths {
|
||||
set path [file join $imagedir $p]
|
||||
|
||||
file mkdir $path
|
||||
|
||||
set fd [open $path/TestResource w]
|
||||
puts $fd "test.resource : $keyw"
|
||||
close $fd
|
||||
|
||||
|
||||
dsetenv CSF_TestResourceDefaults $path
|
||||
|
||||
if { [OCC27849 TestResource test.resource] != "$keyw" } {
|
||||
puts "Error: cannot read resource file in $path"
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
puts "========"
|
||||
puts " 0029064: Copying of empty NCollection map takes excessive memory"
|
||||
puts "========"
|
||||
puts ""
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC29064 map
|
||||
OCC29064 doublemap
|
||||
OCC29064 datamap
|
||||
OCC29064 indexedmap
|
||||
OCC29064 indexeddatamap
|
||||
@@ -1,25 +0,0 @@
|
||||
puts "============"
|
||||
puts "0030536: Foundation Classes - TCollection_ExtendedString::StartsWith() and EndsWith() have a mistake"
|
||||
puts "============"
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set ret1 [QAStartsWith hello help]
|
||||
if { ${ret1} == "Yes" } {
|
||||
puts "Error"
|
||||
}
|
||||
|
||||
set ret2 [QAStartsWith hello he]
|
||||
if { ${ret2} == "No" } {
|
||||
puts "Error"
|
||||
}
|
||||
|
||||
set ret3 [QAEndsWith hello ll]
|
||||
if { ${ret3} == "Yes" } {
|
||||
puts "Error"
|
||||
}
|
||||
|
||||
set ret4 [QAEndsWith hello lo]
|
||||
if { ${ret4} == "No" } {
|
||||
puts "Error"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
puts "# ======================================================================"
|
||||
puts "# 0030990: Foundation Classes - unexpected change in numerical results on bsplines after 0029769"
|
||||
puts "# ======================================================================"
|
||||
puts ""
|
||||
|
||||
pload QAcommands
|
||||
|
||||
restore [locate_data_file bug30990.brep] face
|
||||
mksurface surf face
|
||||
|
||||
puts "Check consistency of evaluation of BSpline surface at knots"
|
||||
OCC30990 surf
|
||||
@@ -1,25 +0,0 @@
|
||||
puts "======="
|
||||
puts "OCC31697 - Expr_GeneralExpression::Derivative does not seem to work"
|
||||
puts "======="
|
||||
puts ""
|
||||
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set exp Exp(2*Sin(x^2))
|
||||
set var x
|
||||
set list [OCC31697 $exp $var]
|
||||
|
||||
set we_have [lindex $list 10]
|
||||
puts "we_have = $we_have"
|
||||
|
||||
set must_be "Exp(2*Sin(x^2))*Cos(x^2)*x*4"
|
||||
puts "must_be = $must_be"
|
||||
|
||||
|
||||
if {[string compare $we_have $must_be] == 0} {
|
||||
puts "OCC31697 OK"
|
||||
} else {
|
||||
puts "OCC31697 Faulty"
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
puts "============"
|
||||
puts "OCC7639"
|
||||
puts "============"
|
||||
puts ""
|
||||
#######################################################################
|
||||
# NCollection_Vector works incorrectly with rare data
|
||||
#######################################################################
|
||||
|
||||
pload QAcommands
|
||||
set BugNumber OCC7639
|
||||
|
||||
set List [OCC7639 0 1 2 500 1 2]
|
||||
|
||||
set Length [llength $List]
|
||||
if { ${Length} != 6} {
|
||||
puts "Faulty (1) ${BugNumber}"
|
||||
} else {
|
||||
if { [regexp "1" $List] != 1 } {
|
||||
puts "Faulty (2) ${BugNumber}"
|
||||
}
|
||||
if { [regexp "2" $List] != 1 } {
|
||||
puts "Faulty (3) ${BugNumber}"
|
||||
}
|
||||
if { [regexp "500" $List] != 1 } {
|
||||
puts "Faulty (4) ${BugNumber}"
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC24923"
|
||||
puts "========"
|
||||
puts ""
|
||||
############################################
|
||||
# BRepMesh_CircleTool produces bad circles
|
||||
############################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set bug_info [OCC24923]
|
||||
set num_failed [string range [lindex $bug_info 12] 0 [expr {[string first "%" [lindex $bug_info 12]] - 1}]]
|
||||
set max_failed [string range [lindex $bug_info 14] 0 [expr {[string first "%" [lindex $bug_info 14]] - 1}]]
|
||||
if {$num_failed > $max_failed} {
|
||||
puts "ERROR: OCC24923 is reproduced. Number of incorrect tests is too large ($num_failed > $max_failed)."
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC26407"
|
||||
puts "========"
|
||||
puts ""
|
||||
##########################################################################################
|
||||
# BRepMesh_Delaun should not take into account frontier edges on first pass of algorithm
|
||||
##########################################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC26407 result
|
||||
@@ -1,12 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "========"
|
||||
puts "OCC570"
|
||||
puts "========"
|
||||
puts ""
|
||||
|
||||
OCC570 result
|
||||
|
||||
checkprops result -s 58500
|
||||
checkshape result
|
||||
checkview -display result -3d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,30 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "============"
|
||||
puts "OCC817"
|
||||
puts "============"
|
||||
puts ""
|
||||
#############################
|
||||
## Bad results of BRepAlgoAPI_Common
|
||||
#############################
|
||||
|
||||
set InfoList [OCC817 result 10]
|
||||
|
||||
set OriginalVolume 0
|
||||
regexp {Info: Original volume = ([-0-9.+eE]+)} $InfoList full OriginalVolume
|
||||
|
||||
set AccumulatedMeshedVolume 0
|
||||
regexp {Info: Accumulated meshed volume = ([-0-9.+eE]+)} $InfoList full AccumulatedMeshedVolume
|
||||
|
||||
set percent_max 0.1
|
||||
set percent [expr abs(${AccumulatedMeshedVolume} - ${OriginalVolume}) / (${OriginalVolume}) * 100.]
|
||||
|
||||
if {${percent} > ${percent_max}} {
|
||||
puts "OCC817: Error"
|
||||
} else {
|
||||
puts "OCC817: OK"
|
||||
}
|
||||
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
checkprops result -s 6000
|
||||
checkshape result
|
||||
@@ -1,29 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "============"
|
||||
puts "OCC817"
|
||||
puts "============"
|
||||
puts ""
|
||||
#############################
|
||||
## Bad results of BRepAlgoAPI_Common
|
||||
#############################
|
||||
|
||||
set InfoList [OCC817 result 15]
|
||||
|
||||
set OriginalVolume 0
|
||||
regexp {Info: Original volume = ([-0-9.+eE]+)} $InfoList full OriginalVolume
|
||||
|
||||
set AccumulatedMeshedVolume 0
|
||||
regexp {Info: Accumulated meshed volume = ([-0-9.+eE]+)} $InfoList full AccumulatedMeshedVolume
|
||||
|
||||
set percent_max 0.1
|
||||
set percent [expr abs(${AccumulatedMeshedVolume} - ${OriginalVolume}) / (${OriginalVolume}) * 100.]
|
||||
|
||||
if {${percent} > ${percent_max}} {
|
||||
puts "OCC817: Error"
|
||||
} else {
|
||||
puts "OCC817: OK"
|
||||
}
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
checkprops result -s 6000
|
||||
checkshape result
|
||||
@@ -1,30 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "============"
|
||||
puts "OCC817"
|
||||
puts "============"
|
||||
puts ""
|
||||
#############################
|
||||
## Bad results of BRepAlgoAPI_Common
|
||||
#############################
|
||||
|
||||
set InfoList [OCC817 result 30]
|
||||
|
||||
|
||||
set OriginalVolume 0
|
||||
regexp {Info: Original volume = ([-0-9.+eE]+)} $InfoList full OriginalVolume
|
||||
|
||||
set AccumulatedMeshedVolume 0
|
||||
regexp {Info: Accumulated meshed volume = ([-0-9.+eE]+)} $InfoList full AccumulatedMeshedVolume
|
||||
|
||||
set percent_max 0.1
|
||||
set percent [expr abs(${AccumulatedMeshedVolume} - ${OriginalVolume}) / (${OriginalVolume}) * 100.]
|
||||
|
||||
if {${percent} > ${percent_max}} {
|
||||
puts "OCC817: Error"
|
||||
} else {
|
||||
puts "OCC817: OK"
|
||||
}
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
checkprops result -s 6000
|
||||
checkshape result
|
||||
@@ -1,26 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "========"
|
||||
puts "OCC822"
|
||||
puts "========"
|
||||
puts ""
|
||||
#####################################
|
||||
## BRepMesh_IncrementalMesh fails on some faces
|
||||
#####################################
|
||||
|
||||
if {[ catch { set info_result [OCC822_1 a1 a2 result] } ] } {
|
||||
puts "Faulty OCC822"
|
||||
} else {
|
||||
if { [regexp {FAILED} $info_result] } {
|
||||
puts "Faulty OCC822"
|
||||
}
|
||||
|
||||
set ExplodeList [explode result]
|
||||
if {[llength ${ExplodeList}] < 1} {
|
||||
puts "Faulty OCC822"
|
||||
}
|
||||
}
|
||||
|
||||
checkprops result -s 133931
|
||||
checkshape result
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,27 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "======="
|
||||
puts "OCC822"
|
||||
puts "======="
|
||||
puts ""
|
||||
#####################################
|
||||
## BRepMesh_IncrementalMesh fails on some faces
|
||||
#####################################
|
||||
## (old topology)
|
||||
#####################################
|
||||
|
||||
if { [ catch { set info_result [OCC822_2 a1 a2 result] } ] } {
|
||||
puts "Faulty OCC822"
|
||||
} else {
|
||||
if { [regexp {FAILED} $info_result] } {
|
||||
puts "Faulty OCC822"
|
||||
}
|
||||
|
||||
set ExplodeList [explode result]
|
||||
if {[llength ${ExplodeList}] < 1} {
|
||||
puts "Faulty OCC822"
|
||||
}
|
||||
}
|
||||
checkprops result -s 61963.5
|
||||
checkshape result
|
||||
checkview -display result -3d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,25 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "======="
|
||||
puts "OCC823"
|
||||
puts "======="
|
||||
puts ""
|
||||
###############################
|
||||
## BRepAlgoAPI_Fuse fails on two cylinders
|
||||
###############################
|
||||
|
||||
if { [ catch { set info_result [OCC823 a1 a2 result] } ] } {
|
||||
puts "Faulty OCC823"
|
||||
} else {
|
||||
if { [regexp {FAILED} $info_result] } {
|
||||
puts "Faulty OCC823"
|
||||
}
|
||||
|
||||
set ExplodeList [explode result]
|
||||
if {[llength ${ExplodeList}] < 1} {
|
||||
puts "Faulty OCC823 : Resulting shape is empty COMPOUND"
|
||||
}
|
||||
}
|
||||
checkprops result -s 23189.5
|
||||
checkshape result
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,26 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "============"
|
||||
puts "OCC824"
|
||||
puts "============"
|
||||
puts ""
|
||||
####################################
|
||||
## BRepAlgoAPI_Fuse fails on cylinder and sphere
|
||||
####################################
|
||||
|
||||
if { [ catch { set info_result [OCC824 a1 a2 result] } ] } {
|
||||
puts "Faulty OCC824"
|
||||
} else {
|
||||
if { [regexp {FAILED} $info_result] } {
|
||||
puts "Faulty OCC824"
|
||||
}
|
||||
|
||||
set ExplodeList [explode result]
|
||||
if {[llength ${ExplodeList}] < 1} {
|
||||
puts "Faulty OCC824"
|
||||
}
|
||||
}
|
||||
|
||||
checkprops result -s 16336.3
|
||||
checkshape result
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,37 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "============"
|
||||
puts "OCC826"
|
||||
puts "============"
|
||||
puts ""
|
||||
###################################
|
||||
## BRepAlgoAPI_Fuse fails on revolved and sphere
|
||||
###################################
|
||||
## Now this test uses BOPAlgo.
|
||||
## Intersection of cylinder and sphere. At that,
|
||||
## the intersection line goes near to the pole
|
||||
## of the sphere (near, but not through).
|
||||
## Walking-line has a point in the seam of
|
||||
## the sphere and neighbour point. Both sections of the
|
||||
## sphere (through every of these points and parallel to
|
||||
## equatorial plane) are circles with small radii. As result,
|
||||
## in 2D-space U-coordinates of these points are too different
|
||||
## (may be even ~60 degrees) in spite of its neighbourhood.
|
||||
#####################################
|
||||
|
||||
if { [ catch { set info_result [OCC826 a1 a2 result] } ] } {
|
||||
puts "Faulty OCC826"
|
||||
} else {
|
||||
if { [regexp {FAILED} $info_result] } {
|
||||
puts "Faulty OCC826"
|
||||
}
|
||||
|
||||
set ExplodeList [explode result]
|
||||
if {[llength ${ExplodeList}] < 1} {
|
||||
puts "Faulty OCC826"
|
||||
}
|
||||
}
|
||||
|
||||
checkprops result -s 272935
|
||||
checkshape result
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,46 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "========"
|
||||
puts "OCC827"
|
||||
puts "========"
|
||||
puts ""
|
||||
###################################
|
||||
## BRepAlgoAPI_Fuse fails on cylinder and torus
|
||||
###################################
|
||||
|
||||
#
|
||||
# a1 - Cylinder
|
||||
# a2 - Torus1
|
||||
# a3 - Torus1
|
||||
# res1 - Fuse(Torus1 & Cylinder)
|
||||
# res2 - Fuse(Torus2 & res1)
|
||||
#
|
||||
|
||||
if { [ catch { set info_result [OCC827 a1 a2 a3 result1 result2] } ] } {
|
||||
puts "Faulty : an exception was caught"
|
||||
} else {
|
||||
if { [lsearch ${info_result} FAILED] > -1} {
|
||||
puts "Faulty OCC827 (case 1)"
|
||||
}
|
||||
checkshape a1
|
||||
checkshape a2
|
||||
checkshape a3
|
||||
checkshape result1
|
||||
checkshape result2
|
||||
|
||||
set ExplodeList [explode result1]
|
||||
if {[llength ${ExplodeList}] < 1} {
|
||||
puts "Faulty : Resulting shape is empty COMPOUND"
|
||||
}
|
||||
|
||||
set ExplodeList [explode result2]
|
||||
if {[llength ${ExplodeList}] < 1} {
|
||||
puts "Faulty : Resulting shape is empty COMPOUND"
|
||||
}
|
||||
|
||||
renamevar result2 result
|
||||
}
|
||||
|
||||
checkprops result -s 11847.7
|
||||
checkshape result
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,52 +0,0 @@
|
||||
puts "============"
|
||||
puts "OCC895"
|
||||
puts "============"
|
||||
puts ""
|
||||
#########################################################
|
||||
## In one case, twisted surface is created.
|
||||
## The problem is in incorrect computation of mutual orientations of wire segments.
|
||||
#########################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set scale 73.609
|
||||
set proj_X 0.523995
|
||||
set proj_Y 0.359655
|
||||
set proj_Z 0.77206
|
||||
set up_X -0.739036
|
||||
set up_Y -0.258607
|
||||
set up_Z 0.622051
|
||||
set at_X 5.51184366274157
|
||||
set at_Y 5.10968389884332
|
||||
set at_Z 0.581665443993578
|
||||
|
||||
set x_coord 210
|
||||
set y_coord 210
|
||||
|
||||
set status 0
|
||||
|
||||
set angle 5
|
||||
set reverse 0
|
||||
set order 0
|
||||
|
||||
if { [ catch { OCC895 result ${angle} ${reverse} ${order} } ] } {
|
||||
puts "Faulty : an exception was caught"
|
||||
}
|
||||
|
||||
if { ${status} == 0} {
|
||||
vinit
|
||||
vsetdispmode 1
|
||||
vdisplay result
|
||||
|
||||
vviewparams -scale ${scale} -proj ${proj_X} ${proj_Y} ${proj_Z} -up ${up_X} ${up_Y} ${up_Z} -at ${at_X} ${at_Y} ${at_Z}
|
||||
|
||||
checkcolor $x_coord $y_coord 0.98 0.72 0.13
|
||||
|
||||
if { ${stat} != 1 } {
|
||||
puts "Faulty OCC895 (case 2)"
|
||||
}
|
||||
}
|
||||
|
||||
checkprops result -s 18.1614
|
||||
checkshape result
|
||||
checkview -display result -3d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,22 +0,0 @@
|
||||
puts "============"
|
||||
puts "OCC25004"
|
||||
puts "============"
|
||||
puts ""
|
||||
##########################################################################################################
|
||||
# Extrema_ExtCC::Extrema curve/curve incorrect result
|
||||
##########################################################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set info [OCC25004]
|
||||
regexp {F += +([-0-9.+eE]+)} $info full aF
|
||||
regexp {NbExtrema += +([-0-9.+eE]+)} $info full aNb
|
||||
|
||||
set expected_F 0.39788735772
|
||||
set expected_aNb 3
|
||||
set tol_abs_dist 1.0e-12
|
||||
set tol_rel_dist 0.1
|
||||
|
||||
checkreal "value F" ${aF} ${expected_F} ${tol_abs_dist} ${tol_rel_dist}
|
||||
checkreal "Nbextrema" ${aNb} ${expected_aNb} ${tol_abs_dist} ${tol_rel_dist}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC26746"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# 0026746: Method gp_Torus::Coefficients(...) returns incorrect value.
|
||||
#################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set Tol 3.0e-7
|
||||
|
||||
torus tr 55.52514413 2.070076585 73.83409062 0.37231784651136368 0.58886674834874120 0.71736697293527607 0.80682335496555135, 0.17666016102759910, -0.56376170618524390 87.08479625 23.14682176
|
||||
|
||||
OCC26746 tr $Tol 5
|
||||
@@ -1,17 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC25605"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# 0026747: Some constructors of gp_Parab2d classes have not understandable interface and create wrong parabola
|
||||
#################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC26747_1 result
|
||||
|
||||
v2d
|
||||
don result
|
||||
2dfit
|
||||
|
||||
checkview -screenshot -2d -l -path ${imagedir}/${test_image}.png
|
||||
@@ -1,17 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC26747"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# 0026747: Some constructors of gp_Parab2d classes have not understandable interface and create wrong parabola
|
||||
#################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC26747_2 result
|
||||
|
||||
v2d
|
||||
don result
|
||||
2dfit
|
||||
|
||||
checkview -screenshot -2d -l -path ${imagedir}/${test_image}.png
|
||||
@@ -1,17 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC26747"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# 0026747: Some constructors of gp_Parab2d classes have not understandable interface and create wrong parabola
|
||||
#################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC26747_3 result
|
||||
|
||||
v2d
|
||||
don result
|
||||
2dfit
|
||||
|
||||
checkview -screenshot -2d -l -path ${imagedir}/${test_image}.png
|
||||
@@ -1,11 +0,0 @@
|
||||
puts "============"
|
||||
puts "OCC26750"
|
||||
puts "============"
|
||||
puts ""
|
||||
#############################################################################################
|
||||
## Method IsNormal(...) for gp_Vec2d returns FALSE if the angle between two vectors is equal to -90 degree (-M_PI/2 radian)
|
||||
#############################################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC26750
|
||||
@@ -1,19 +0,0 @@
|
||||
puts "================"
|
||||
puts "OCC27875"
|
||||
puts "================"
|
||||
puts ""
|
||||
###############################
|
||||
## GeomFill_NSections constructor crash on sequence of curve containing only one curve
|
||||
###############################
|
||||
|
||||
# GeomFill_NSections does not work if the sequence of curves contains only single curve.
|
||||
# Therefore, we should not expect any correct result from this operation. However, the
|
||||
# exception must not be thrown.
|
||||
|
||||
pload QAcommands
|
||||
|
||||
restore [locate_data_file OCC606_2.brep] w2
|
||||
explode w2 e
|
||||
mkcurve cc w2_1
|
||||
trim cc cc
|
||||
OCC27875 cc
|
||||
@@ -1,25 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC28594"
|
||||
puts "========"
|
||||
puts ""
|
||||
####################################################################
|
||||
# Geom2dAPI_Interpolate generated curve is not the same as proe
|
||||
####################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
set anImageWithScale ${imagedir}/${test_image}_c1.png
|
||||
set anImageWithoutScale ${imagedir}/${test_image}_c2.png
|
||||
|
||||
OCC28594 c1 c2
|
||||
smallview -2D-
|
||||
donly c1
|
||||
2dfit
|
||||
checkview -screenshot -2d -path ${anImageWithScale}
|
||||
donly c2
|
||||
checkview -screenshot -2d -path ${anImageWithoutScale}
|
||||
|
||||
set aDiffImageResult [diffimage $anImageWithScale $anImageWithoutScale 0.1 0 0]
|
||||
if {$aDiffImageResult == 0} {
|
||||
puts "Error: curves are equal"
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
puts "# ==============================================================="
|
||||
puts "# 0028131: BRepOffset_MakeOffset can't create offset with a face which created by filling 3 bsplinecurve"
|
||||
puts "# ==============================================================="
|
||||
puts ""
|
||||
|
||||
puts "# Create face to be offset, by dedicated command"
|
||||
pload QAcommands
|
||||
OCC28131 f
|
||||
|
||||
puts "# Try simple offset"
|
||||
offsetshapesimple result_simple f 10.
|
||||
checkshape result_simple
|
||||
checkmaxtol result_simple -ref 0.205
|
||||
checkprops result_simple -s 1693.7
|
||||
|
||||
puts "# Try standard offset"
|
||||
offsetshape result_std f 10.
|
||||
fixshape result_std result_std ;# need to fix it....
|
||||
checkshape result_std
|
||||
checkmaxtol result_std -ref 0.408
|
||||
checkprops result_std -s 1693.76
|
||||
|
||||
puts "# Make snapshots (overall and zoom to degenerated point)"
|
||||
|
||||
smallview -Y+Z
|
||||
fit
|
||||
checkview -2d -screenshot -path ${imagedir}/${test_image}.png
|
||||
|
||||
smallview -Y+Z
|
||||
zoom 400
|
||||
pu; pu; pu
|
||||
pr; pr; pr
|
||||
|
||||
donly result_simple
|
||||
checkview -2d -screenshot -path ${imagedir}/${test_image}_zoom_simple.png
|
||||
|
||||
donly result_std
|
||||
checkview -2d -screenshot -path ${imagedir}/${test_image}_zoom_standard.png
|
||||
@@ -1,46 +0,0 @@
|
||||
puts "========"
|
||||
puts "OCC29430"
|
||||
puts "========"
|
||||
puts ""
|
||||
#################################################
|
||||
# [Regression] Curve evaluation at boundary point.
|
||||
#################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
# After launching the command below we will obtain
|
||||
# some wire (stored in "result" variable) containing
|
||||
# a single edge based on arc of circle and its first and last
|
||||
# 3D-points (p1 and p2 correspondingly) taken from
|
||||
# composite curve (BRepAdaptor_CompCurve) built on this wire.
|
||||
|
||||
OCC29430 result p1 p2
|
||||
|
||||
vertex v1 p1
|
||||
vertex v2 p2
|
||||
|
||||
explode result v
|
||||
|
||||
# Now, let's check
|
||||
# 1. whether p1 and p2 match the vertices of the wire;
|
||||
# 2. whether p1 and p2 are different points.
|
||||
|
||||
distmini d11 result_1 v1
|
||||
distmini d12 result_1 v2
|
||||
distmini d21 result_2 v1
|
||||
distmini d22 result_2 v2
|
||||
distmini dv12 v1 v2
|
||||
|
||||
|
||||
if { ([dval d11_val] > 1.0e-7) && ([dval d21_val] > 1.0e-7) } {
|
||||
puts "Error: Start point of the wire does not match any its vertex."
|
||||
}
|
||||
if { ([dval d12_val] > 1.0e-7) && ([dval d22_val] > 1.0e-7) } {
|
||||
puts "Error: End point of the wire does not match any its vertex."
|
||||
}
|
||||
|
||||
if { [dval dv12_val] < 1.0e-7 } {
|
||||
puts "Error: Start and End points of the wire are the same."
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
puts "================================================================="
|
||||
puts "OCC30747: Modeling Algorithms - 2d Curves concatenator doesn't properly process closed contours."
|
||||
puts "================================================================="
|
||||
puts ""
|
||||
|
||||
pload QAcommands
|
||||
|
||||
OCC30747 res
|
||||
@@ -1,55 +0,0 @@
|
||||
puts "========"
|
||||
puts "0030869: Modeling Data - BRepAdaptor_CompCurve incorrectly evaluates the boundary points"
|
||||
puts "========"
|
||||
puts ""
|
||||
|
||||
pload QAcommands
|
||||
|
||||
# create wire consisting of a single edge based on a trimmed circle
|
||||
circle c 1 0 0 0 -1 0 0 0 -1 1
|
||||
trim c c 1.5707963267949 4.71238898038469
|
||||
mkedge e c
|
||||
orientation e R
|
||||
wire w e
|
||||
|
||||
# compute boundary points using BRepAdaptor_CompCurve
|
||||
set log [OCC30869 w]
|
||||
|
||||
set lines [split $log "\n"]
|
||||
|
||||
if {![regexp {([-0-9.+eE]*): point ([-0-9.+eE]*) ([-0-9.+eE]*) ([-0-9.+eE]*), tangent ([-0-9.+eE]*) ([-0-9.+eE]*) ([-0-9.+eE]*)} [lindex $lines 0] full t1 x1 y1 z1 dx1 dy1 dz1]} {
|
||||
puts "Error: first point is not computed"
|
||||
}
|
||||
|
||||
if {![regexp {([-0-9.+eE]*): point ([-0-9.+eE]*) ([-0-9.+eE]*) ([-0-9.+eE]*), tangent ([-0-9.+eE]*) ([-0-9.+eE]*) ([-0-9.+eE]*)} [lindex $lines 1] full t2 x2 y2 z2 dx2 dy2 dz2]} {
|
||||
puts "Error: last point is not computed"
|
||||
}
|
||||
|
||||
# compute reference values
|
||||
|
||||
# inverse the curve as the edge in the wire is reversed
|
||||
circle ci 1 0 0 0 1 0 0 0 -1 1
|
||||
trim ci ci 1.5707963267949 4.71238898038469
|
||||
|
||||
cvalue ci 1.5707963267949 x1_ref y1_ref z1_ref dx1_ref dy1_ref dz1_ref
|
||||
cvalue ci 4.71238898038469 x2_ref y2_ref z2_ref dx2_ref dy2_ref dz2_ref
|
||||
|
||||
# compare the values
|
||||
set tol_abs 1.e-7
|
||||
set tol_rel 1.e-7
|
||||
|
||||
checkreal first_pnt_x $x1 [dval x1_ref] $tol_abs $tol_rel
|
||||
checkreal first_pnt_y $y1 [dval y1_ref] $tol_abs $tol_rel
|
||||
checkreal first_pnt_z $z1 [dval z1_ref] $tol_abs $tol_rel
|
||||
|
||||
checkreal first_tgt_x $dx1 [dval dx1_ref] $tol_abs $tol_rel
|
||||
checkreal first_tgt_y $dy1 [dval dy1_ref] $tol_abs $tol_rel
|
||||
checkreal first_tgt_z $dz1 [dval dz1_ref] $tol_abs $tol_rel
|
||||
|
||||
checkreal last_pnt_x $x2 [dval x2_ref] $tol_abs $tol_rel
|
||||
checkreal last_pnt_y $y2 [dval y2_ref] $tol_abs $tol_rel
|
||||
checkreal last_pnt_z $z2 [dval z2_ref] $tol_abs $tol_rel
|
||||
|
||||
checkreal last_tgt_x $dx2 [dval dx2_ref] $tol_abs $tol_rel
|
||||
checkreal last_tgt_y $dy2 [dval dy2_ref] $tol_abs $tol_rel
|
||||
checkreal last_tgt_z $dz2 [dval dz2_ref] $tol_abs $tol_rel
|
||||
@@ -1,68 +0,0 @@
|
||||
puts "========"
|
||||
puts "BUC60897"
|
||||
puts "========"
|
||||
|
||||
pload QAcommands
|
||||
|
||||
if [catch { set result [BUC60897] } ] {
|
||||
puts "BUC60897: Error; (case 1)"
|
||||
} else {
|
||||
set len [llength ${result}]
|
||||
if {${len} < 21} {
|
||||
puts "length = ${len}"
|
||||
puts "BUC60897: Error; (case 2)"
|
||||
} else {
|
||||
set circle_X [lindex ${result} 3]
|
||||
set circle_Y [lindex ${result} 5]
|
||||
set circle_R [lindex ${result} 7]
|
||||
set tangency1_X [lindex ${result} 11]
|
||||
set tangency1_Y [lindex ${result} 13]
|
||||
set tangency2_X [lindex ${result} 17]
|
||||
set tangency2_Y [lindex ${result} 19]
|
||||
|
||||
set x1 [expr abs(${tangency1_X} - ${circle_X})]
|
||||
set y1 [expr abs(${tangency1_Y} - ${circle_Y})]
|
||||
set R1 [expr sqrt(${x1} * ${x1} + ${y1} * ${y1})]
|
||||
|
||||
set x2 [expr abs(${tangency2_X} - ${circle_X})]
|
||||
set y2 [expr abs(${tangency2_Y} - ${circle_Y})]
|
||||
set R2 [expr sqrt(${x2} * ${x2} + ${y2} * ${y2})]
|
||||
|
||||
set maxdelta 1.0
|
||||
set delta_R1 [expr abs(${R1} - ${circle_R}) / ${circle_R} * 100.]
|
||||
set delta_R2 [expr abs(${R2} - ${circle_R}) / ${circle_R} * 100.]
|
||||
|
||||
if {${delta_R1} > ${maxdelta}} {
|
||||
puts "circle_X = ${circle_X}"
|
||||
puts "circle_Y = ${circle_Y}"
|
||||
puts "circle_R = ${circle_R}"
|
||||
puts "tangency1_X = ${tangency1_X}"
|
||||
puts "tangency1_Y = ${tangency1_Y}"
|
||||
puts "x1 = ${x1}"
|
||||
puts "y1 = ${y1}"
|
||||
puts "R1 = ${R1}"
|
||||
puts "delta_R1 = ${delta_R1}"
|
||||
puts "maxdelta = ${maxdelta}"
|
||||
puts "BUC60897: Error; (case 3)"
|
||||
} else {
|
||||
puts "BUC60897: OK; (case 1)"
|
||||
}
|
||||
|
||||
if {${delta_R2} > ${maxdelta}} {
|
||||
puts "circle_X = ${circle_X}"
|
||||
puts "circle_Y = ${circle_Y}"
|
||||
puts "circle_R = ${circle_R}"
|
||||
puts "tangency2_X = ${tangency2_X}"
|
||||
puts "tangency2_Y = ${tangency2_Y}"
|
||||
puts "x2 = ${x2}"
|
||||
puts "y2 = ${y2}"
|
||||
puts "R2 = ${R2}"
|
||||
puts "delta_R2 = ${delta_R2}"
|
||||
puts "maxdelta = ${maxdelta}"
|
||||
puts "BUC60897: Error; (case 4)"
|
||||
} else {
|
||||
puts "BUC60897: OK; (case 2)"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
pload QAcommands
|
||||
|
||||
puts "============"
|
||||
puts "OCC2569"
|
||||
puts "============"
|
||||
puts ""
|
||||
######################################################
|
||||
# If it is not possible to create the bezier curve,
|
||||
# it should throw an exception.
|
||||
######################################################
|
||||
cpulimit 60
|
||||
vinit
|
||||
set out [OCC2569 26 result]
|
||||
if {[string compare $out "\n Degree = 25\n"] == 0} {
|
||||
puts "OCC2569: OK"
|
||||
} else {
|
||||
puts "OCC2569: Faulty"
|
||||
}
|
||||
vfit
|
||||
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,20 +0,0 @@
|
||||
# Incompleted behavior of test case is OK.
|
||||
# Exception should be thrown.
|
||||
|
||||
puts "TODO OCC11111 ALL: An exception was caught"
|
||||
|
||||
pload QAcommands
|
||||
|
||||
puts "============"
|
||||
puts "0002569: If it is not possible to create the bezier curve, it should throw an e x c e p t i o n."
|
||||
puts "============"
|
||||
puts ""
|
||||
|
||||
cpulimit 60
|
||||
vinit
|
||||
|
||||
if { [catch {OCC2569 29 result} anException] } {
|
||||
puts "OCC2569 : OK"
|
||||
} else {
|
||||
puts "Error : OCC2569"
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
puts "========"
|
||||
puts "OCC49"
|
||||
puts "========"
|
||||
|
||||
pload QAcommands
|
||||
|
||||
pcylinder c 10 20
|
||||
|
||||
set result [OCC49 c]
|
||||
|
||||
if {$result == 1} {
|
||||
puts "OCC49: OK"
|
||||
} else {
|
||||
puts "Error : OCC49"
|
||||
}
|
||||
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
puts "========"
|
||||
puts "OCC49"
|
||||
puts "========"
|
||||
|
||||
pload QAcommands
|
||||
|
||||
pcylinder c 10 20
|
||||
box b 10 10 10
|
||||
bcut b_c_cut b c
|
||||
checkshape b_c_cut
|
||||
|
||||
set result [OCC49 b_c_cut]
|
||||
|
||||
if {$result == 1} {
|
||||
puts "Error : OCC49"
|
||||
} else {
|
||||
puts "OCC49: OK"
|
||||
}
|
||||
|
||||
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user