Skip to content

Commit

Permalink
Toponaming/Part: Add tests, dependencies, and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
bgbsww committed Feb 9, 2024
1 parent 10d95b9 commit 7ef0b6e
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 52 deletions.
1 change: 1 addition & 0 deletions src/Mod/Part/App/OpenCascadeAll.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@

#include <BRepAlgo.hxx>
#include <BRepAlgo_NormalProjection.hxx>
#include <BRepAlgoAPI_BooleanOperation.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Cut.hxx>
# include <BRepAlgoAPI_Defeaturing.hxx>
Expand Down
50 changes: 15 additions & 35 deletions src/Mod/Part/App/TopoShapeExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,33 @@
#include <BRepAlgoAPI_Section.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>
#include <ShapeUpgrade_ShellSewing.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <Precision.hxx>
#include <ShapeBuild_ReShape.hxx>
#include <ShapeAnalysis_FreeBounds.hxx>
#include <BRepTools.hxx>

#include <ShapeFix_Shape.hxx>
#include <ShapeFix_ShapeTolerance.hxx>
#include <gp_Pln.hxx>

#include <utility>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <ShapeAnalysis_FreeBounds.hxx>

#endif

#if OCC_VERSION_HEX >= 0x070500
# include <OSD_Parallel.hxx>
#endif

#include "TopoShape.h"
#include "TopoShapeOpCode.h"
#include "TopoShapeCache.h"
#include "TopoShapeMapper.h"
#include "FaceMaker.h"

#include "TopoShapeOpCode.h"
#include <App/ElementNamingUtils.h>
#include <BRepLib.hxx>
#include <OSD_Parallel.hxx>

FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT

Expand Down Expand Up @@ -2400,17 +2396,12 @@ TopoShape::makeElementBoolean(const char* maker, const TopoShape& shape, const c
}


// TODO: Refactor this so that each OpCode type is a separate method to reduce size
TopoShape& TopoShape::makeElementBoolean(const char* maker,
const std::vector<TopoShape>& shapes,
const char* op,
double tolerance)
{
#if OCC_VERSION_HEX <= 0x060800
if (tolerance > 0.0) {
Standard_Failure::Raise("Fuzzy Booleans are not supported in this version of OCCT");
}
#endif

if (!maker) {
FC_THROWM(Base::CADKernelError, "no maker");
}
Expand Down Expand Up @@ -2454,10 +2445,10 @@ TopoShape& TopoShape::makeElementBoolean(const char* maker,

if (strcmp(maker, Part::OpCodes::Pipe) == 0) {
if (shapes.size() != 2) {
FC_THROWM(Base::CADKernelError, "Not enough input shapes");
FC_THROWM(Base::CADKernelError, "Sweep needs a spine and a shape");
}
if (shapes[0].isNull() || shapes[1].isNull()) {
FC_THROWM(Base::CADKernelError, "Cannot sweep along empty spine");
FC_THROWM(Base::CADKernelError, "Cannot sweep with empty spine or empty shape");
}
if (shapes[0].getShape().ShapeType() != TopAbs_WIRE) {
FC_THROWM(Base::CADKernelError, "Spine shape is not a wire");
Expand All @@ -2479,7 +2470,7 @@ TopoShape& TopoShape::makeElementBoolean(const char* maker,
if (!check.IsValid()) {
ShapeUpgrade_ShellSewing sewShell;
setShape(sewShell.ApplySewing(shell), false);
// TODO confirm the above won't change OCCT topological naming
// TODO: confirm the above won't change OCCT topological naming
}
return *this;
}
Expand Down Expand Up @@ -2580,26 +2571,15 @@ TopoShape& TopoShape::makeElementBoolean(const char* maker,
}

#if OCC_VERSION_HEX >= 0x070500
// Can't find this threshold value anywhere. Go ahead assuming it is true.
// if (PartParams::getParallelRunThreshold() > 0) {
// -1/22/2024 Removing the parameter.
// if (PartParams::getParallelRunThreshold() > 0) {
mk->SetRunParallel(Standard_True);
OSD_Parallel::SetUseOcctThreads(Standard_True);
// }
// }
#else
// Only run parallel
if (shapeArguments.Size() + shapeTools.Size() > 2) {
mk->SetRunParallel(true);
}
else if (PartParams::getParallelRunThreshold() > 0) {
int total = 0;
for (const auto& shape : inputs) {
total += shape.countSubShapes(TopAbs_FACE);
if (total > PartParams::getParallelRunThreshold()) {
mk->SetRunParallel(true);
break;
}
}
}
// 01/22/2024 This will be an extremely rare case, since we don't
// build against OCCT versions this old. Removing the parameter.
mk->SetRunParallel(true);
#endif

mk->SetArguments(shapeArguments);
Expand Down
109 changes: 92 additions & 17 deletions tests/src/Mod/Part/App/TopoShapeExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundOneShapeReturnsShape)
// Act
topoShape.makeElementCompound(shapes,
"C",
TopoShape::SingleShapeCompoundCreationPolicy::
returnShape /*Don't force the creation*/);
TopoShape::SingleShapeCompoundCreationPolicy::returnShape);

// Assert
EXPECT_EQ(edge.ShapeType(), topoShape.getShape().ShapeType()); // NOT a Compound
Expand All @@ -75,10 +74,9 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundOneShapeForceReturnsCompound)
std::vector<TopoShape> shapes {topoShape};

// Act
topoShape.makeElementCompound(
shapes,
"C",
TopoShape::SingleShapeCompoundCreationPolicy::forceCompound /*Force the creation*/);
topoShape.makeElementCompound(shapes,
"C",
TopoShape::SingleShapeCompoundCreationPolicy::forceCompound);

// Assert
EXPECT_NE(edge.ShapeType(), topoShape.getShape().ShapeType()); // No longer the same thing
Expand Down Expand Up @@ -278,9 +276,7 @@ TEST_F(TopoShapeExpansionTest, MapperMakerGenerated)
TEST_F(TopoShapeExpansionTest, makeElementFaceNull)
{
// Arrange
const float Len = 3;
const float Wid = 2;
const float Rad = 1;
const double Len = 3, Wid = 2, Rad = 1;
auto [face1, wire1, wire2] = CreateFaceWithRoundHole(Len, Wid, Rad);
TopoShape topoShape {face1};
double area = getArea(face1);
Expand Down Expand Up @@ -333,8 +329,7 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceParams)
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
TopoShape newFace =
topoShape.makeElementFace(wire1, "Cut", "Part::FaceMakerBullseye", nullptr);
TopoShape newFace = topoShape.makeElementFace(wire1, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
// Assert
Expand All @@ -358,8 +353,7 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceFromFace)
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
TopoShape newFace =
topoShape.makeElementFace(face1, "Cut", "Part::FaceMakerBullseye", nullptr);
TopoShape newFace = topoShape.makeElementFace(face1, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
// Assert
Expand Down Expand Up @@ -409,8 +403,7 @@ TEST_F(TopoShapeExpansionTest, makeElementFaceClosedWire)
double area = getArea(face1);
double area1 = getArea(topoShape.getShape());
// Act
TopoShape newFace =
topoShape.makeElementFace(wire2, "Cut", "Part::FaceMakerBullseye", nullptr);
TopoShape newFace = topoShape.makeElementFace(wire2, "Cut", "Part::FaceMakerBullseye", nullptr);
double area2 = getArea(newFace.getShape());
double area3 = getArea(topoShape.getShape());
// Assert
Expand Down Expand Up @@ -516,8 +509,7 @@ TEST_F(TopoShapeExpansionTest, splitWires)
std::vector<TopoShape> inner;
// Act
EXPECT_EQ(topoShape.getShape().Orientation(), TopAbs_FORWARD);
TopoShape wire =
topoShape.splitWires(&inner, TopoShape::SplitWireReorient::ReorientReversed);
TopoShape wire = topoShape.splitWires(&inner, TopoShape::SplitWireReorient::ReorientReversed);
// Assert
EXPECT_EQ(inner.size(), 1);
EXPECT_FLOAT_EQ(getLength(wire.getShape()), 2 + 2 + 3 + 3);
Expand Down Expand Up @@ -791,5 +783,88 @@ TEST_F(TopoShapeExpansionTest, makeElementShellIntersecting)
// {
// // Arrange
// }
TEST_F(TopoShapeExpansionTest, makeElementBooleanImpossibleCommon)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
TopoShape topoShape1 {cube1, 1L};
TopoShape topoShape2 {cube2, 2L};
// Act
TopoShape& result =
topoShape1.makeElementBoolean(Part::OpCodes::Common, {topoShape1, topoShape2});
auto elements = elementMap(result);
// Assert
EXPECT_EQ(elements.size(), 0);
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0);
}

TEST_F(TopoShapeExpansionTest, makeElementBooleanCommon)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
auto tr {gp_Trsf()};
tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0)));
cube2.Move(TopLoc_Location(tr));
TopoShape topoShape1 {cube1, 1L};
TopoShape topoShape2 {cube2, 2L};
// Act
TopoShape& result =
topoShape1.makeElementBoolean(Part::OpCodes::Common, {topoShape1, topoShape2});
auto elements = elementMap(result);
// Assert
EXPECT_EQ(elements.size(), 26);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face3;:M;CMN;:H1:7,F"));
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.25);
}

TEST_F(TopoShapeExpansionTest, makeElementBooleanCut)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
auto tr {gp_Trsf()};
tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0)));
cube2.Move(TopLoc_Location(tr));
TopoShape topoShape1 {cube1, 1L};
TopoShape topoShape2 {cube2, 2L};
// Act
TopoShape& result = topoShape1.makeElementBoolean(Part::OpCodes::Cut, {topoShape1, topoShape2});
auto elements = elementMap(result);
// Assert
EXPECT_EQ(elements.size(), 38);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;CUT;:H1:7,F;:U;CUT;:H1:7,E;:L(Face5;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E|Face5;:M;"
"CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;CUT;:H1:7,V;:L(Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E;:U;"
"CUT;:H1:7,V);CUT;:H1:3c,E|Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E);CUT;:H1:cb,F"));
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.75);
}

TEST_F(TopoShapeExpansionTest, makeElementBooleanFuse)
{
// Arrange
auto [cube1, cube2] = CreateTwoCubes();
auto tr {gp_Trsf()};
tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0)));
cube2.Move(TopLoc_Location(tr));
TopoShape topoShape1 {cube1, 1L};
TopoShape topoShape2 {cube2, 2L};
// Act
TopoShape& result =
topoShape1.makeElementBoolean(Part::OpCodes::Fuse, {topoShape1, topoShape2});
auto elements = elementMap(result);
// Assert
EXPECT_EQ(elements.size(), 66);
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
EXPECT_EQ(
elements[IndexedName("Face", 1)],
MappedName(
"Face3;:M;FUS;:H1:7,F;:U;FUS;:H1:7,E;:L(Face5;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E|Face5;:M;"
"FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;FUS;:H1:7,V;:L(Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E;:U;"
"FUS;:H1:7,V);FUS;:H1:3c,E|Face6;:M;FUS;:H1:7,F;:U2;FUS;:H1:8,E);FUS;:H1:cb,F"));
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75);
}

// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)

0 comments on commit 7ef0b6e

Please sign in to comment.