Merge branch 'main' into bgbsww-toponamingMakeElementSliceMirror
This commit is contained in:
@@ -20,7 +20,11 @@
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include "VarSet.h"
|
||||
#include "DocumentObject.h"
|
||||
|
||||
@@ -112,7 +112,7 @@ installed addons will be checked for available updates
|
||||
<string>Hide Addons with non-FSF Free/Libre license</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>HideNonFSFFreeLibre</cstring>
|
||||
|
||||
@@ -502,7 +502,6 @@ if HAVE_QTNETWORK:
|
||||
current_index = index
|
||||
break
|
||||
|
||||
sender.abort()
|
||||
if current_index != -1:
|
||||
self.__launch_request(current_index, self.__create_get_request(url, timeout_ms))
|
||||
|
||||
@@ -579,7 +578,7 @@ if HAVE_QTNETWORK:
|
||||
return
|
||||
|
||||
response_code = reply.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
|
||||
if response_code == 301: # Permanently moved -- this is a redirect, bail out
|
||||
if response_code == 301 or response_code == 302: # This is a redirect, bail out
|
||||
return
|
||||
if reply.error() != QtNetwork.QNetworkReply.NetworkError.OperationCanceledError:
|
||||
# It this was not a timeout, make sure we mark the queue task done
|
||||
|
||||
@@ -93,9 +93,9 @@ class PackageList(QtWidgets.QWidget):
|
||||
self.set_view_style(style)
|
||||
self.ui.view_bar.view_selector.set_current_view(style)
|
||||
|
||||
self.item_filter.setHidePy2(pref.GetBool("HidePy2", True))
|
||||
self.item_filter.setHideObsolete(pref.GetBool("HideObsolete", True))
|
||||
self.item_filter.setHideNonOSIApproved(pref.GetBool("HideNonOSIApproved", True))
|
||||
self.item_filter.setHidePy2(pref.GetBool("HidePy2", False))
|
||||
self.item_filter.setHideObsolete(pref.GetBool("HideObsolete", False))
|
||||
self.item_filter.setHideNonOSIApproved(pref.GetBool("HideNonOSIApproved", False))
|
||||
self.item_filter.setHideNonFSFLibre(pref.GetBool("HideNonFSFFreeLibre", False))
|
||||
self.item_filter.setHideNewerFreeCADRequired(
|
||||
pref.GetBool("HideNewerFreeCADRequired", False)
|
||||
|
||||
@@ -2508,4 +2508,21 @@ def compact_mesh(
|
||||
# may be return another value if the mesh was compacted, just check last map entries
|
||||
return (new_mesh, node_map, elem_map)
|
||||
|
||||
# ************************************************************************************************
|
||||
def beam_reduced_integration(
|
||||
fileName
|
||||
):
|
||||
# replace B3x elements with B3xR elements
|
||||
f = open(fileName, "r+")
|
||||
lines = f.readlines()
|
||||
f.seek(0)
|
||||
for line in lines:
|
||||
if line.find("B32") != -1:
|
||||
line = line.replace("B32", "B32R")
|
||||
if line.find("B31") != -1:
|
||||
line = line.replace("B31", "B31R")
|
||||
f.write(line)
|
||||
|
||||
f.truncate()
|
||||
f.close()
|
||||
## @}
|
||||
|
||||
@@ -372,6 +372,15 @@ def add_attributes(obj, ccx_prefs):
|
||||
obj.BeamShellResultOutput3D = dimout
|
||||
|
||||
|
||||
if not hasattr(obj, "BeamReducedIntegration"):
|
||||
obj.addProperty(
|
||||
"App::PropertyBool",
|
||||
"BeamReducedIntegration",
|
||||
"Fem",
|
||||
"Set to True to use beam elements with reduced integration"
|
||||
)
|
||||
obj.BeamReducedIntegration = True
|
||||
|
||||
"""
|
||||
Should there be some equation object for Calculix too?
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ def write_femelement_geometry(f, ccxwriter):
|
||||
thickness = beamsec_obj.PipeThickness.getValueAs("mm").Value
|
||||
section_type = ", SECTION=PIPE"
|
||||
section_geo = "{:.13G},{:.13G}\n".format(radius, thickness)
|
||||
section_def = "*BEAM GENERAL SECTION, {}{}{}\n".format(
|
||||
section_def = "*BEAM SECTION, {}{}{}\n".format(
|
||||
elsetdef,
|
||||
material,
|
||||
section_type
|
||||
|
||||
@@ -51,6 +51,10 @@ def write_mesh(ccxwriter):
|
||||
if ccxwriter.member.geos_fluidsection:
|
||||
meshtools.write_D_network_element_to_inputfile(ccxwriter.femmesh_file)
|
||||
|
||||
# Use reduced integration beam elements if this option is enabled in ccx solver settings
|
||||
if ccxwriter.solver_obj.BeamReducedIntegration:
|
||||
meshtools.beam_reduced_integration(ccxwriter.femmesh_file)
|
||||
|
||||
inpfile = codecs.open(ccxwriter.file_name, "w", encoding="utf-8")
|
||||
inpfile.write("{}\n".format(59 * "*"))
|
||||
inpfile.write("** {}\n".format(write_name))
|
||||
@@ -69,6 +73,10 @@ def write_mesh(ccxwriter):
|
||||
# inpfile is closed
|
||||
meshtools.write_D_network_element_to_inputfile(ccxwriter.femmesh_file)
|
||||
|
||||
# Use reduced integration beam elements if this option is enabled in ccx solver settings
|
||||
if ccxwriter.solver_obj.BeamReducedIntegration:
|
||||
meshtools.beam_reduced_integration(ccxwriter.femmesh_file)
|
||||
|
||||
# reopen file with "append" to add all the rest
|
||||
inpfile = codecs.open(ccxwriter.femmesh_file, "a", encoding="utf-8")
|
||||
inpfile.write("\n\n")
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
** Edge elements
|
||||
*Element, TYPE=B32, ELSET=Eedges
|
||||
*Element, TYPE=B32R, ELSET=Eedges
|
||||
1, 1, 7, 3
|
||||
2, 3, 8, 4
|
||||
3, 4, 9, 5
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
** Edge elements
|
||||
*Element, TYPE=B32, ELSET=Eedges
|
||||
*Element, TYPE=B32R, ELSET=Eedges
|
||||
1, 1, 7, 3
|
||||
2, 3, 8, 4
|
||||
3, 4, 9, 5
|
||||
@@ -56,7 +56,7 @@ Eedges
|
||||
|
||||
***********************************************************
|
||||
** Sections
|
||||
*BEAM GENERAL SECTION, ELSET=M0B0RstdD0, MATERIAL=MechanicalMaterial, SECTION=PIPE
|
||||
*BEAM SECTION, ELSET=M0B0RstdD0, MATERIAL=MechanicalMaterial, SECTION=PIPE
|
||||
500,100
|
||||
-0, 1, 0
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
** Edge elements
|
||||
*Element, TYPE=B32, ELSET=Eedges
|
||||
*Element, TYPE=B32R, ELSET=Eedges
|
||||
1, 1, 7, 3
|
||||
2, 3, 8, 4
|
||||
3, 4, 9, 5
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
|
||||
** Edge elements
|
||||
*Element, TYPE=B31, ELSET=Eedges
|
||||
*Element, TYPE=B31R, ELSET=Eedges
|
||||
1, 1, 3
|
||||
2, 3, 4
|
||||
3, 4, 5
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
** Edge elements
|
||||
*Element, TYPE=B32, ELSET=Eedges
|
||||
*Element, TYPE=B32R, ELSET=Eedges
|
||||
1, 1, 7, 3
|
||||
2, 3, 8, 4
|
||||
3, 4, 9, 5
|
||||
|
||||
@@ -214,6 +214,18 @@ enum class AsAngle
|
||||
yes
|
||||
};
|
||||
|
||||
enum class CheckScale
|
||||
{
|
||||
noScaleCheck,
|
||||
checkScale
|
||||
};
|
||||
|
||||
enum class Copy
|
||||
{
|
||||
noCopy,
|
||||
copy
|
||||
};
|
||||
|
||||
/** The representation for a CAD Shape
|
||||
*/
|
||||
// NOLINTNEXTLINE cppcoreguidelines-special-member-functions
|
||||
@@ -802,7 +814,7 @@ public:
|
||||
|
||||
/** Make a hollowed solid by removing some faces from a given solid
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param shape: input shape
|
||||
* @param faces: list of faces to remove, must be sub shape of the input shape
|
||||
* @param offset: thickness of the walls
|
||||
* @param tol: tolerance criterion for coincidence in generated shapes
|
||||
@@ -818,13 +830,12 @@ public:
|
||||
* a self reference so that multiple operations can be carried out
|
||||
* for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape &makeElementThickSolid(const TopoShape &source, const std::vector<TopoShape> &faces,
|
||||
TopoShape &makeElementThickSolid(const TopoShape &shape, const std::vector<TopoShape> &faces,
|
||||
double offset, double tol, bool intersection = false, bool selfInter = false,
|
||||
short offsetMode = 0, JoinType join = JoinType::arc, const char *op=nullptr);
|
||||
|
||||
/** Make a hollowed solid by removing some faces from a given solid
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param faces: list of faces to remove, must be sub shape of the input shape
|
||||
* @param offset: thickness of the walls
|
||||
* @param tol: tolerance criterion for coincidence in generated shapes
|
||||
@@ -1240,6 +1251,43 @@ public:
|
||||
return TopoShape(0, Hasher).makeElementWires(*this, op, tol, policy, output);
|
||||
}
|
||||
|
||||
/** Make a new shape with transformation that may contain non-uniform scaling
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param mat: transformation matrix
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param copy: whether to perform deep copy of the shape. If false, the
|
||||
* shape will still be copied if there is scaling.
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new transformed shape. The function returns the
|
||||
* TopoShape itself as a self reference so that multiple operations
|
||||
* can be carried out for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape& makeElementGTransform(const TopoShape& source,
|
||||
const Base::Matrix4D& mat,
|
||||
const char* op = nullptr,
|
||||
Copy copy = Copy::noCopy);
|
||||
|
||||
/** Make a new shape with transformation that may contain non-uniform scaling
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param mat: transformation matrix
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param copy: whether to perform deep copy of the shape. If false, the
|
||||
* shape will still be copied if there is scaling.
|
||||
*
|
||||
* @return Return a new shape with transformation. The shape itself is not
|
||||
* modified
|
||||
*/
|
||||
TopoShape makeElementGTransform(const Base::Matrix4D& mat,
|
||||
const char* op = nullptr,
|
||||
Copy copy = Copy::noCopy) const
|
||||
{
|
||||
return TopoShape(Tag, Hasher).makeElementGTransform(*this, mat, op, copy);
|
||||
}
|
||||
|
||||
/** Make a deep copy of the shape
|
||||
*
|
||||
@@ -1505,6 +1553,114 @@ public:
|
||||
.makeElementChamfer(*this, edges, radius1, radius2, op, flipDirection, asAngle);
|
||||
}
|
||||
|
||||
/** Make a new shape with transformation
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param mat: transformation matrix
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param checkScale: whether to check if the transformation matrix
|
||||
* contains scaling factor.
|
||||
* @param copy: whether to perform deep copy of the shape. If noCopy, and
|
||||
* checkScale, then the shape will be copied if there
|
||||
* is scaling.
|
||||
*
|
||||
* @return Returns true if scaling is performed.
|
||||
*
|
||||
* The original content of this TopoShape is discarded and replaced with
|
||||
* the new transformed shape.
|
||||
*/
|
||||
bool _makeElementTransform(const TopoShape& source,
|
||||
const Base::Matrix4D& mat,
|
||||
const char* op = nullptr,
|
||||
CheckScale checkScale = CheckScale::noScaleCheck,
|
||||
Copy copy = Copy::noCopy);
|
||||
|
||||
/** Make a new shape with transformation
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param mat: transformation matrix
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param checkScale: whether to check if the transformation matrix
|
||||
* contains scaling factor.
|
||||
* @param copy: whether to perform deep copy of the shape. If noCopy, and
|
||||
* checkScale, then the shape will be copied if there
|
||||
* is scaling.
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new transformed shape. The function returns the
|
||||
* TopoShape itself as a self reference so that multiple operations
|
||||
* can be carried out for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape& makeElementTransform(const TopoShape& source,
|
||||
const Base::Matrix4D& mat,
|
||||
const char* op = nullptr,
|
||||
CheckScale checkScale = CheckScale::noScaleCheck,
|
||||
Copy copy = Copy::noCopy)
|
||||
{
|
||||
_makeElementTransform(source, mat, op, checkScale, copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Make a new shape with transformation
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param mat: transformation matrix
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param checkScale: whether to check if the transformation matrix
|
||||
* contains scaling factor.
|
||||
* @param copy: whether to perform deep copy of the shape. If noCopy, and
|
||||
* checkScale, then the shape will be copied if there
|
||||
* is scaling.
|
||||
*
|
||||
* @return Return a new shape with transformation. The shape itself is not
|
||||
* modified
|
||||
*/
|
||||
TopoShape makeElementTransform(const Base::Matrix4D& mat,
|
||||
const char* op = nullptr,
|
||||
CheckScale checkScale = CheckScale::noScaleCheck,
|
||||
Copy copy = Copy::noCopy) const
|
||||
{
|
||||
return TopoShape(Tag, Hasher).makeElementTransform(*this, mat, op, checkScale, copy);
|
||||
}
|
||||
|
||||
/** Make a new shape with transformation
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param trsf: OCCT transformation matrix
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param copy: whether to perform deep copy of the shape.
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new transformed shape. The function returns the
|
||||
* TopoShape itself as a self reference so that multiple operations
|
||||
* can be carried out for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape& makeElementTransform(const TopoShape& shape,
|
||||
const gp_Trsf& trsf,
|
||||
const char* op = nullptr,
|
||||
Copy copy = Copy::noCopy);
|
||||
|
||||
/** Make a new shape with transformation
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param trsf: OCCT transformation matrix
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param copy: whether to perform deep copy of the shape.
|
||||
*
|
||||
* @return Return a new shape with transformation. The shape itself is not
|
||||
* modified
|
||||
*/
|
||||
TopoShape
|
||||
makeElementTransform(const gp_Trsf& trsf, const char* op = nullptr, Copy copy = Copy::noCopy)
|
||||
{
|
||||
return TopoShape(Tag, Hasher).makeElementTransform(*this, trsf, op, copy);
|
||||
}
|
||||
|
||||
/* Make draft shape
|
||||
*
|
||||
* @param source: the source shape
|
||||
@@ -1743,7 +1899,7 @@ public:
|
||||
* makeShapeWithElementMap directly. For example:
|
||||
* makeElementShape(sewer, sources)
|
||||
* makeShapeWithElementMap(sewer.SewedShape(), MapperSewing(sewer), sources, OpCodes::Sewing);
|
||||
* Note that if op exists in the method, it should be checked for null and overriden with
|
||||
* Note that if op exists in the method, it should be checked for null and overridden with
|
||||
* the appropriate operation if so.
|
||||
*/
|
||||
|
||||
|
||||
@@ -48,10 +48,12 @@
|
||||
#include <BRepAlgoAPI_Fuse.hxx>
|
||||
#include <BRepAlgoAPI_Section.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepBuilderAPI_GTransform.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepFilletAPI_MakeChamfer.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
#include <BRepOffsetAPI_DraftAngle.hxx>
|
||||
#include <BRepOffsetAPI_MakePipe.hxx>
|
||||
@@ -85,8 +87,6 @@
|
||||
#include "Geometry.h"
|
||||
|
||||
#include <App/ElementNamingUtils.h>
|
||||
#include <BRepLib.hxx>
|
||||
#include "Geometry.h"
|
||||
|
||||
FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT
|
||||
|
||||
@@ -2508,6 +2508,110 @@ TopoShape& TopoShape::makeElementOrderedWires(const std::vector<TopoShape>& shap
|
||||
return makeElementCompound(wires, nullptr, SingleShapeCompoundCreationPolicy::returnShape);
|
||||
}
|
||||
|
||||
bool TopoShape::_makeElementTransform(const TopoShape& shape,
|
||||
const Base::Matrix4D& mat,
|
||||
const char* op,
|
||||
CheckScale checkScale,
|
||||
Copy copy)
|
||||
{
|
||||
if (checkScale == CheckScale::checkScale) {
|
||||
auto scaleType = mat.hasScale();
|
||||
if (scaleType != Base::ScaleType::NoScaling && scaleType != Base::ScaleType::Uniform) {
|
||||
makeElementGTransform(shape, mat, op, copy);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
makeElementTransform(shape, convert(mat), op, copy);
|
||||
return false;
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementTransform(const TopoShape& shape,
|
||||
const gp_Trsf& trsf,
|
||||
const char* op,
|
||||
Copy copy)
|
||||
{
|
||||
if (copy == Copy::noCopy) {
|
||||
// OCCT checks the ScaleFactor against gp::Resolution() which is DBL_MIN!!!
|
||||
// No scaling is 1 as in 1:1
|
||||
const bool scaling = Abs(Abs(trsf.ScaleFactor()) - 1) > Precision::Confusion();
|
||||
const bool negative_scaling =
|
||||
trsf.ScaleFactor() * trsf.HVectorialPart().Determinant() < 0.0;
|
||||
copy = negative_scaling || scaling ? Copy::copy : Copy::noCopy;
|
||||
}
|
||||
TopoShape tmp(shape);
|
||||
if (copy == Copy::copy) {
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null input shape");
|
||||
}
|
||||
|
||||
BRepBuilderAPI_Transform mkTrf(shape.getShape(), trsf, Standard_True);
|
||||
// TODO: calling Moved() is to make sure the shape has some Location,
|
||||
// which is necessary for STEP export to work. However, if we reach
|
||||
// here, it probably means BRepBuilderAPI_Transform has modified
|
||||
// underlying shapes (because of scaling), it will break compound child
|
||||
// parent relationship anyway. In short, STEP import/export will most
|
||||
// likely break badly if there is any scaling involved
|
||||
tmp.setShape(mkTrf.Shape().Moved(gp_Trsf()), false);
|
||||
}
|
||||
else {
|
||||
tmp.move(trsf);
|
||||
}
|
||||
|
||||
if (op || (shape.Tag && shape.Tag != Tag)) {
|
||||
setShape(tmp._Shape);
|
||||
initCache();
|
||||
if (!Hasher) {
|
||||
Hasher = tmp.Hasher;
|
||||
}
|
||||
copyElementMap(tmp, op);
|
||||
}
|
||||
else {
|
||||
*this = tmp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementGTransform(const TopoShape& shape,
|
||||
const Base::Matrix4D& mat,
|
||||
const char* op,
|
||||
Copy copy)
|
||||
{
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null input shape");
|
||||
}
|
||||
|
||||
// if(!op) op = Part::OpCodes::Gtransform;
|
||||
gp_GTrsf matrix;
|
||||
matrix.SetValue(1, 1, mat[0][0]);
|
||||
matrix.SetValue(2, 1, mat[1][0]);
|
||||
matrix.SetValue(3, 1, mat[2][0]);
|
||||
matrix.SetValue(1, 2, mat[0][1]);
|
||||
matrix.SetValue(2, 2, mat[1][1]);
|
||||
matrix.SetValue(3, 2, mat[2][1]);
|
||||
matrix.SetValue(1, 3, mat[0][2]);
|
||||
matrix.SetValue(2, 3, mat[1][2]);
|
||||
matrix.SetValue(3, 3, mat[2][2]);
|
||||
matrix.SetValue(1, 4, mat[0][3]);
|
||||
matrix.SetValue(2, 4, mat[1][3]);
|
||||
matrix.SetValue(3, 4, mat[2][3]);
|
||||
|
||||
// geometric transformation
|
||||
TopoShape tmp(shape);
|
||||
BRepBuilderAPI_GTransform mkTrf(shape.getShape(), matrix, copy == Copy::copy);
|
||||
tmp.setShape(mkTrf.Shape(), false);
|
||||
if (op || (shape.Tag && shape.Tag != Tag)) {
|
||||
setShape(tmp._Shape);
|
||||
initCache();
|
||||
if (!Hasher) {
|
||||
Hasher = tmp.Hasher;
|
||||
}
|
||||
copyElementMap(tmp, op);
|
||||
}
|
||||
else {
|
||||
*this = tmp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TopoShape&
|
||||
TopoShape::makeElementCopy(const TopoShape& shape, const char* op, bool copyGeom, bool copyMesh)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include <regex>
|
||||
#include "PartTestHelpers.h"
|
||||
|
||||
// NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
|
||||
@@ -137,6 +138,32 @@ std::map<IndexedName, MappedName> elementMap(const TopoShape& shape)
|
||||
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, std::string regex)
|
||||
{
|
||||
first = std::regex_replace(first, std::regex(regex), "");
|
||||
second = std::regex_replace(second, std::regex(regex), "");
|
||||
return first == second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the elementMap in a shape contains all the names in a list
|
||||
* The "Duplicate" clause in a name - ";Dnnn" can contain a random number, so we need to
|
||||
* exclude those.
|
||||
* @param shape The Shape
|
||||
* @param names The vector of names
|
||||
* @return An assertion usable by the gtest framework
|
||||
*/
|
||||
testing::AssertionResult elementsMatch(const TopoShape& shape,
|
||||
const std::vector<std::string>& names)
|
||||
{
|
||||
@@ -147,16 +174,12 @@ testing::AssertionResult elementsMatch(const TopoShape& shape,
|
||||
names.begin(),
|
||||
names.end(),
|
||||
[&](const Data::MappedElement& element, const std::string& name) {
|
||||
return element.name.toString() == name;
|
||||
return matchStringsWithoutClause(element.name.toString(),
|
||||
name,
|
||||
";D[a-fA-F0-9]+");
|
||||
})
|
||||
== elements.end()) {
|
||||
std::stringstream output;
|
||||
output << "{";
|
||||
for (const auto& element : elements) {
|
||||
output << "\"" << element.name.toString() << "\", ";
|
||||
}
|
||||
output << "}";
|
||||
return testing::AssertionFailure() << output.str();
|
||||
return testing::AssertionFailure() << mappedElementVectorToString(elements);
|
||||
}
|
||||
}
|
||||
return testing::AssertionSuccess();
|
||||
@@ -168,7 +191,8 @@ testing::AssertionResult allElementsMatch(const TopoShape& shape,
|
||||
auto elements = shape.getElementMap();
|
||||
if (elements.size() != names.size()) {
|
||||
return testing::AssertionFailure()
|
||||
<< elements.size() << " != " << names.size() << " elements in map";
|
||||
<< elements.size() << " != " << names.size()
|
||||
<< " elements: " << mappedElementVectorToString(elements);
|
||||
}
|
||||
return elementsMatch(shape, names);
|
||||
}
|
||||
|
||||
@@ -1523,7 +1523,6 @@ TEST_F(TopoShapeExpansionTest, makeElementThickSolid)
|
||||
EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Edge11;THK;:H1:4,E"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementGeneralFuse)
|
||||
{
|
||||
// Arrange
|
||||
@@ -1860,19 +1859,19 @@ TEST_F(TopoShapeExpansionTest, makeElementSlice)
|
||||
EXPECT_EQ(TopAbs_ShapeEnum::TopAbs_WIRE, result.getShape().ShapeType());
|
||||
// Assert that we're creating a correct element map
|
||||
EXPECT_TRUE(result.getMappedChildElements().empty());
|
||||
EXPECT_TRUE(allElementsMatch(result,
|
||||
{
|
||||
"Edge1;SLC;D1;MAK",
|
||||
"Edge1;SLC;D2;MAK",
|
||||
"Edge1;SLC;D3;MAK",
|
||||
"Edge1;SLC;MAK",
|
||||
"Vertex1;SLC;D1;MAK",
|
||||
"Vertex1;SLC;D2;MAK",
|
||||
"Vertex1;SLC;MAK",
|
||||
"Vertex2;SLC;D1;MAK",
|
||||
"Vertex2;SLC;D2;MAK",
|
||||
"Vertex2;SLC;MAK",
|
||||
}));
|
||||
EXPECT_TRUE(elementsMatch(result,
|
||||
{
|
||||
"Edge1;SLC;D1;MAK",
|
||||
"Edge1;SLC;D2;MAK",
|
||||
"Edge1;SLC;D3;MAK",
|
||||
"Edge1;SLC;MAK",
|
||||
"Vertex1;SLC;D1;MAK",
|
||||
"Vertex1;SLC;D2;MAK",
|
||||
"Vertex1;SLC;MAK",
|
||||
"Vertex2;SLC;D1;MAK",
|
||||
"Vertex2;SLC;D2;MAK",
|
||||
"Vertex2;SLC;MAK",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementSlices)
|
||||
@@ -1954,4 +1953,99 @@ TEST_F(TopoShapeExpansionTest, makeElementMirror)
|
||||
"Vertex7;:M;MIR;:H1:7,V", "Vertex8;:M;MIR;:H1:7,V"}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementTransformWithoutMap)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
auto tr {gp_Trsf()};
|
||||
tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0)));
|
||||
TopoShape topoShape1 {cube1, 1L};
|
||||
// Act
|
||||
TopoShape& result = topoShape1.makeElementTransform(topoShape1, tr);
|
||||
auto elements = elementMap(result);
|
||||
Base::BoundBox3d bb = result.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -0.5, 0.0, 0.5, 0.5, 1.0)));
|
||||
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1);
|
||||
// Assert elementMap is correct
|
||||
EXPECT_EQ(elements.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementTransformWithMap)
|
||||
{
|
||||
// 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.makeElementFuse({topoShape1, topoShape2}); // op, tolerance
|
||||
topoShape1.makeElementTransform(result, tr);
|
||||
auto elements = elementMap(result);
|
||||
Base::BoundBox3d bb = result.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -1.0, 0.0, 1.0, 0.5, 1.0)));
|
||||
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75);
|
||||
// Assert elementMap is correct
|
||||
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"));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementGTransformWithoutMap)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
auto tr {gp_Trsf()};
|
||||
tr.SetTranslation(gp_Vec(gp_XYZ(-0.5, -0.5, 0)));
|
||||
TopoShape topoShape1 {cube1, 1L};
|
||||
// Act
|
||||
TopoShape& result = topoShape1.makeElementGTransform(topoShape1, TopoShape::convert(tr));
|
||||
auto elements = elementMap(result);
|
||||
Base::BoundBox3d bb = result.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -0.5, 0.0, 0.5, 0.5, 1.0)));
|
||||
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1);
|
||||
// Assert elementMap is correct
|
||||
EXPECT_EQ(elements.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementGTransformWithMap)
|
||||
{
|
||||
// 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.makeElementFuse({topoShape1, topoShape2}); // op, tolerance
|
||||
topoShape1.makeElementGTransform(result, TopoShape::convert(tr));
|
||||
auto elements = elementMap(result);
|
||||
Base::BoundBox3d bb = result.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(-0.5, -1.0, 0.0, 1.0, 0.5, 1.0)));
|
||||
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 1.75);
|
||||
// Assert elementMap is correct
|
||||
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"));
|
||||
}
|
||||
|
||||
// Not testing _makeElementTransform as it is a thin wrapper that calls the same places as the four
|
||||
// preceding tests.
|
||||
|
||||
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
|
||||
|
||||
@@ -48,6 +48,6 @@ TEST_F(FeaturePartMakeElementRefineTest, makeElementRefineBoxes)
|
||||
EXPECT_EQ(refined.countSubElements("Face"), 6); // After refining it is one box
|
||||
EXPECT_EQ(refined.countSubElements("Edge"), 12); // 12 edges in a box
|
||||
// TODO: Make sure we have an elementMap for the refine.
|
||||
// Refine doesn't work on compounds, so we're going to need a binary operation or the
|
||||
// TODO: Refine doesn't work on compounds, so we're going to need a binary operation or the
|
||||
// like, and those don't exist yet. Once they do, this test can be expanded
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user