| | |
| |
|
| | #include <regex> |
| | #include "PartTestHelpers.h" |
| |
|
| | |
| |
|
| | namespace PartTestHelpers |
| | { |
| |
|
| | double getVolume(const TopoDS_Shape& shape) |
| | { |
| | GProp_GProps prop; |
| | BRepGProp::VolumeProperties(shape, prop); |
| | return abs(prop.Mass()); |
| | } |
| |
|
| | double getArea(const TopoDS_Shape& shape) |
| | { |
| | GProp_GProps prop; |
| | BRepGProp::SurfaceProperties(shape, prop); |
| | return abs(prop.Mass()); |
| | } |
| |
|
| | double getLength(const TopoDS_Shape& shape) |
| | { |
| | GProp_GProps prop; |
| | BRepGProp::LinearProperties(shape, prop); |
| | return abs(prop.Mass()); |
| | } |
| |
|
| |
|
| | void PartTestHelperClass::createTestDoc() |
| | { |
| | _docName = App::GetApplication().getUniqueDocumentName("test"); |
| | _doc = App::GetApplication().newDocument(_docName.c_str(), "testUser"); |
| | std::array<Base::Vector3d, 6> box_origins = { |
| | Base::Vector3d(), |
| | Base::Vector3d(0, 1, 0), |
| | Base::Vector3d(0, 3, 0), |
| | Base::Vector3d(0, 2, 0), |
| | Base::Vector3d(0, 2 + Base::Precision::Confusion(), 0), |
| | |
| | Base::Vector3d(0, 2 - minimalDistance, 0) |
| | }; |
| |
|
| | for (unsigned i = 0; i < _boxes.size(); i++) { |
| | auto box = _boxes[i] = _doc->addObject<Part::Box>(); |
| | box->Length.setValue(1); |
| | box->Width.setValue(2); |
| | box->Height.setValue(3); |
| | box->Placement.setValue( |
| | Base::Placement(box_origins[i], Base::Rotation(), Base::Vector3d()) |
| | ); |
| | } |
| | } |
| |
|
| | std::vector<Part::FilletElement> _getFilletEdges( |
| | const std::vector<int>& edges, |
| | double startRadius, |
| | double endRadius |
| | ) |
| | { |
| | std::vector<Part::FilletElement> filletElements; |
| | for (auto edge : edges) { |
| | Part::FilletElement fe = {edge, startRadius, endRadius}; |
| | filletElements.push_back(fe); |
| | } |
| | return filletElements; |
| | } |
| |
|
| |
|
| | void ExecutePython(const std::vector<std::string>& python) |
| | { |
| | Base::InterpreterSingleton is = Base::InterpreterSingleton(); |
| |
|
| | for (auto const& line : python) { |
| | is.runInteractiveString(line.c_str()); |
| | } |
| | } |
| |
|
| |
|
| | void rectangle(double height, double width, const char* name) |
| | { |
| | std::vector<std::string> rectstring { |
| | "import FreeCAD, Part", |
| | "V1 = FreeCAD.Vector(0, 0, 0)", |
| | boost::str(boost::format("V2 = FreeCAD.Vector(%d, 0, 0)") % height), |
| | boost::str(boost::format("V3 = FreeCAD.Vector(%d, %d, 0)") % height % width), |
| | boost::str(boost::format("V4 = FreeCAD.Vector(0, %d, 0)") % width), |
| | "P1 = Part.makePolygon([V1, V2, V3, V4],True)", |
| | "F1 = Part.Face(P1)", |
| | boost::str(boost::format("Part.show(F1,'%s')") % name), |
| | }; |
| | ExecutePython(rectstring); |
| | } |
| |
|
| | std::tuple<TopoDS_Face, TopoDS_Wire, TopoDS_Edge, TopoDS_Edge, TopoDS_Edge, TopoDS_Edge> CreateRectFace( |
| | float len, |
| | float wid |
| | ) |
| | { |
| | auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(len, 0.0, 0.0)).Edge(); |
| | auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(len, 0.0, 0.0), gp_Pnt(len, wid, 0.0)).Edge(); |
| | auto edge3 = BRepBuilderAPI_MakeEdge(gp_Pnt(len, wid, 0.0), gp_Pnt(0.0, wid, 0.0)).Edge(); |
| | auto edge4 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, wid, 0.0), gp_Pnt(0.0, 0.0, 0.0)).Edge(); |
| | auto wire1 = BRepBuilderAPI_MakeWire({edge1, edge2, edge3, edge4}).Wire(); |
| | auto face1 = BRepBuilderAPI_MakeFace(wire1).Face(); |
| | return {face1, wire1, edge1, edge2, edge3, edge4}; |
| | } |
| |
|
| | std::tuple<TopoDS_Face, TopoDS_Wire, TopoDS_Wire> CreateFaceWithRoundHole(float len, float wid, float radius) |
| | { |
| | auto [face1, wire1, edge1, edge2, edge3, edge4] = CreateRectFace(len, wid); |
| | auto circ1 = GC_MakeCircle(gp_Pnt(len / 2.0, wid / 2.0, 0), gp_Dir(0.0, 0.0, 1.0), radius).Value(); |
| | auto edge5 = BRepBuilderAPI_MakeEdge(circ1).Edge(); |
| | auto wire2 = BRepBuilderAPI_MakeWire(edge5).Wire(); |
| | auto face2 = BRepBuilderAPI_MakeFace(face1, wire2).Face(); |
| | |
| | |
| | return {face2, wire1, wire2}; |
| | } |
| |
|
| | testing::AssertionResult boxesMatch(const Base::BoundBox3d& b1, const Base::BoundBox3d& b2, double prec) |
| | { |
| | if (abs(b1.MinX - b2.MinX) < prec && abs(b1.MinY - b2.MinY) < prec |
| | && abs(b1.MinZ - b2.MinZ) < prec && abs(b1.MaxX - b2.MaxX) < prec |
| | && abs(b1.MaxY - b2.MaxY) < prec && abs(b1.MaxZ - b2.MaxZ) < prec) { |
| | return testing::AssertionSuccess(); |
| | } |
| | return testing::AssertionFailure() |
| | << "(" << b1.MinX << "," << b1.MinY << "," << b1.MinZ << " ; " |
| | << "(" << b1.MaxX << "," << b1.MaxY << "," << b1.MaxZ << ") != (" << b2.MinX << "," |
| | << b2.MinY << "," << b2.MinZ << " ; " << b2.MaxX << "," << b2.MaxY << "," << b2.MaxZ << ")"; |
| | } |
| |
|
| | std::map<IndexedName, MappedName> elementMap(const TopoShape& shape) |
| | { |
| | std::map<IndexedName, MappedName> result {}; |
| | auto elements = shape.getElementMap(); |
| | for (auto const& entry : elements) { |
| | result[entry.index] = entry.name; |
| | } |
| | return result; |
| | } |
| |
|
| | std::string mappedElementVectorToString(std::vector<MappedElement>& elements) |
| | { |
| | std::stringstream output; |
| | output << "{"; |
| | for (const auto& element : elements) { |
| | output << "\"" << element.name.toString() << "\", "; |
| | } |
| | output << "}"; |
| | return output.str(); |
| | } |
| |
|
| | bool matchStringsWithoutClause(std::string first, std::string second, const std::string& regex) |
| | { |
| | first = std::regex_replace(first, std::regex(regex), ""); |
| | second = std::regex_replace(second, std::regex(regex), ""); |
| | return first == second; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | testing::AssertionResult elementsMatch(const TopoShape& shape, const std::vector<std::string>& names) |
| | { |
| | auto elements = shape.getElementMap(); |
| | if (!elements.empty() || !names.empty()) { |
| | for (const auto& name : names) { |
| | if (std::find_if( |
| | elements.begin(), |
| | elements.end(), |
| | [&, name](const Data::MappedElement& element) { |
| | return matchStringsWithoutClause( |
| | element.name.toString(), |
| | name, |
| | "(;D|;:H|;K)-?[a-fA-F0-9]+(:[0-9]+)?|(\\(.*?\\))?" |
| | ); |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| | ) |
| | == elements.end()) { |
| | return testing::AssertionFailure() << mappedElementVectorToString(elements); |
| | } |
| | } |
| | } |
| | return testing::AssertionSuccess(); |
| | } |
| |
|
| | testing::AssertionResult allElementsMatch(const TopoShape& shape, const std::vector<std::string>& names) |
| | { |
| | auto elements = shape.getElementMap(); |
| | if (elements.size() != names.size()) { |
| | return testing::AssertionFailure() << elements.size() << " != " << names.size() |
| | << " elements: " << mappedElementVectorToString(elements); |
| | } |
| | return elementsMatch(shape, names); |
| | } |
| |
|
| | std::pair<TopoDS_Shape, TopoDS_Shape> CreateTwoCubes() |
| | { |
| | auto boxMaker1 = BRepPrimAPI_MakeBox(1.0, 1.0, 1.0); |
| | boxMaker1.Build(); |
| | auto box1 = boxMaker1.Shape(); |
| |
|
| | auto boxMaker2 = BRepPrimAPI_MakeBox(1.0, 1.0, 1.0); |
| | boxMaker2.Build(); |
| | auto box2 = boxMaker2.Shape(); |
| | auto transform = gp_Trsf(); |
| | transform.SetTranslation(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)); |
| | box2.Location(TopLoc_Location(transform)); |
| |
|
| | return {box1, box2}; |
| | } |
| |
|
| | std::pair<TopoShape, TopoShape> CreateTwoTopoShapeCubes() |
| | { |
| | auto [box1, box2] = CreateTwoCubes(); |
| | std::vector<TopoShape> vec; |
| | long tag = 1L; |
| | for (TopExp_Explorer exp(box1, TopAbs_FACE); exp.More(); exp.Next()) { |
| | vec.emplace_back(TopoShape(exp.Current(), tag++)); |
| | } |
| | TopoShape box1ts; |
| | box1ts.makeElementCompound(vec); |
| | box1ts.Tag = tag++; |
| | vec.clear(); |
| | for (TopExp_Explorer exp(box2, TopAbs_FACE); exp.More(); exp.Next()) { |
| | vec.emplace_back(TopoShape(exp.Current(), tag++)); |
| | } |
| | TopoShape box2ts; |
| | box2ts.Tag = tag++; |
| | box2ts.makeElementCompound(vec); |
| |
|
| | return {box1ts, box2ts}; |
| | } |
| |
|
| | } |
| |
|
| | |
| |
|