Merge branch 'main' into bgbsww-toponamingMakeElementSolid
This commit is contained in:
@@ -10,6 +10,12 @@ if (POLICY CMP0072)
|
||||
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||
endif(POLICY CMP0072)
|
||||
|
||||
# FindPythonInterp and FindPythonLibs modules are deprecated.
|
||||
# Currently, they are still used by shiboken's CMake files
|
||||
if (POLICY CMP0148)
|
||||
cmake_policy(SET CMP0148 OLD)
|
||||
endif()
|
||||
|
||||
option(FREECAD_USE_CCACHE "Auto detect and use ccache during compilation" ON)
|
||||
|
||||
if(FREECAD_USE_CCACHE)
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include "VarSet.h"
|
||||
#include "DocumentObject.h"
|
||||
|
||||
@@ -145,8 +145,8 @@
|
||||
#include "UiLoader.h"
|
||||
#include "MetaTypes.h"
|
||||
|
||||
#ifdef HAVE_SHIBOKEN
|
||||
#ifdef HAVE_SHIBOKEN2
|
||||
// NOLINTBEGIN
|
||||
#if defined(HAVE_SHIBOKEN2)
|
||||
PyTypeObject** SbkPySide2_QtCoreTypes = nullptr;
|
||||
PyTypeObject** SbkPySide2_QtGuiTypes = nullptr;
|
||||
PyTypeObject** SbkPySide2_QtWidgetsTypes = nullptr;
|
||||
@@ -157,8 +157,11 @@ constexpr auto &SbkPySide_QtGuiTypes = SbkPySide2_QtGuiTypes;
|
||||
constexpr auto &SbkPySide_QtWidgetsTypes = SbkPySide2_QtWidgetsTypes;
|
||||
constexpr auto &SbkPySide_QtPrintSupportTypes = SbkPySide2_QtPrintSupportTypes;
|
||||
constexpr auto &SbkPySide_QtUiToolsTypes = SbkPySide2_QtUiToolsTypes;
|
||||
#if !defined(HAVE_PYSIDE2)
|
||||
constexpr const char* ModuleShiboken = "shiboken2";
|
||||
#endif
|
||||
constexpr const char* ModulePySide = "PySide2";
|
||||
#else
|
||||
#elif defined(HAVE_SHIBOKEN6)
|
||||
PyTypeObject** SbkPySide6_QtCoreTypes = nullptr;
|
||||
PyTypeObject** SbkPySide6_QtGuiTypes = nullptr;
|
||||
PyTypeObject** SbkPySide6_QtWidgetsTypes = nullptr;
|
||||
@@ -169,8 +172,10 @@ constexpr auto &SbkPySide_QtGuiTypes = SbkPySide6_QtGuiTypes;
|
||||
constexpr auto &SbkPySide_QtWidgetsTypes = SbkPySide6_QtWidgetsTypes;
|
||||
constexpr auto &SbkPySide_QtPrintSupportTypes = SbkPySide6_QtPrintSupportTypes;
|
||||
constexpr auto &SbkPySide_QtUiToolsTypes = SbkPySide6_QtUiToolsTypes;
|
||||
constexpr const char* ModulePySide = "PySide6";
|
||||
#if !defined(HAVE_PYSIDE6)
|
||||
constexpr const char* ModuleShiboken = "shiboken6";
|
||||
#endif
|
||||
constexpr const char* ModulePySide = "PySide6";
|
||||
#else
|
||||
static PyTypeObject** SbkPySide_DummyTypes;
|
||||
constexpr auto &SbkPySide_QtCoreTypes = SbkPySide_DummyTypes;
|
||||
@@ -186,6 +191,7 @@ constexpr const char* ModuleShiboken = "shiboken6";
|
||||
constexpr const char* ModulePySide = "PySide6";
|
||||
# endif
|
||||
#endif
|
||||
// NOLINTEND
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
@@ -201,7 +207,8 @@ using namespace Gui;
|
||||
\endcode
|
||||
*/
|
||||
|
||||
PyObject* toPythonFuncQuantityTyped(Base::Quantity cpx) {
|
||||
PyObject* toPythonFuncQuantityTyped(Base::Quantity cpx)
|
||||
{
|
||||
return new Base::QuantityPy(new Base::Quantity(cpx));
|
||||
}
|
||||
|
||||
@@ -212,13 +219,14 @@ PyObject* toPythonFuncQuantity(const void* cpp)
|
||||
|
||||
void toCppPointerConvFuncQuantity(PyObject* pyobj,void* cpp)
|
||||
{
|
||||
*((Base::Quantity*)cpp) = *static_cast<Base::QuantityPy*>(pyobj)->getQuantityPtr();
|
||||
*static_cast<Base::Quantity*>(cpp) = *static_cast<Base::QuantityPy*>(pyobj)->getQuantityPtr();
|
||||
}
|
||||
|
||||
PythonToCppFunc toCppPointerCheckFuncQuantity(PyObject* obj)
|
||||
{
|
||||
if (PyObject_TypeCheck(obj, &(Base::QuantityPy::Type)))
|
||||
if (PyObject_TypeCheck(obj, &(Base::QuantityPy::Type))) {
|
||||
return toCppPointerConvFuncQuantity;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -230,8 +238,9 @@ void BaseQuantity_PythonToCpp_QVariant(PyObject* pyIn, void* cppOut)
|
||||
|
||||
PythonToCppFunc isBaseQuantity_PythonToCpp_QVariantConvertible(PyObject* obj)
|
||||
{
|
||||
if (PyObject_TypeCheck(obj, &(Base::QuantityPy::Type)))
|
||||
if (PyObject_TypeCheck(obj, &(Base::QuantityPy::Type))) {
|
||||
return BaseQuantity_PythonToCpp_QVariant;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -289,8 +298,9 @@ static bool loadPySideModule(const std::string& moduleName, PyTypeObject**& type
|
||||
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
|
||||
if (!types) {
|
||||
Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(getPySideModuleName(moduleName).c_str()));
|
||||
if (requiredModule.isNull())
|
||||
if (requiredModule.isNull()) {
|
||||
return false;
|
||||
}
|
||||
types = Shiboken::Module::getTypes(requiredModule);
|
||||
}
|
||||
#else
|
||||
@@ -312,8 +322,9 @@ getPyTypeObjectForTypeName()
|
||||
#if defined (HAVE_SHIBOKEN_TYPE_FOR_TYPENAME)
|
||||
# if defined (HAVE_SHIBOKEN2)
|
||||
auto sbkType = Shiboken::ObjectType::typeForTypeName(typeid(qttype).name());
|
||||
if (sbkType)
|
||||
if (sbkType) {
|
||||
return reinterpret_cast<SbkObjectType*>&(sbkType->type);
|
||||
}
|
||||
# else
|
||||
return Shiboken::ObjectType::typeForTypeName(typeid(qttype).name());
|
||||
# endif
|
||||
@@ -379,16 +390,20 @@ public:
|
||||
PyW_invalidator->setObjectName(PyW_unique_name);
|
||||
|
||||
Py_INCREF (pyobj);
|
||||
} else
|
||||
}
|
||||
else {
|
||||
PyW_invalidator->disconnect();
|
||||
}
|
||||
|
||||
auto destroyedFun = [pyobj](){
|
||||
Base::PyGILStateLocker lock;
|
||||
auto sbk_ptr = reinterpret_cast <SbkObject *> (pyobj);
|
||||
if (sbk_ptr != nullptr)
|
||||
if (sbk_ptr != nullptr) {
|
||||
Shiboken::Object::setValidCpp(sbk_ptr, false);
|
||||
else
|
||||
}
|
||||
else {
|
||||
Base::Console().DeveloperError("WrapperManager", "A QObject has just been destroyed after its Pythonic wrapper.\n");
|
||||
}
|
||||
Py_DECREF (pyobj);
|
||||
};
|
||||
|
||||
@@ -484,8 +499,9 @@ const char* qt_identifyType(QObject* ptr, const std::string& moduleName)
|
||||
const QMetaObject* metaObject = ptr->metaObject();
|
||||
while (metaObject) {
|
||||
const char* className = metaObject->className();
|
||||
if (qtmod.getDict().hasKey(className))
|
||||
if (qtmod.getDict().hasKey(className)) {
|
||||
return className;
|
||||
}
|
||||
metaObject = metaObject->superClass();
|
||||
}
|
||||
|
||||
@@ -583,8 +599,9 @@ Py::Object PythonWrapper::fromQIcon(const QIcon* icon)
|
||||
const char* typeName = typeid(*const_cast<QIcon*>(icon)).name();
|
||||
PyObject* pyobj = Shiboken::Object::newObject(getPyTypeObjectForTypeName<QIcon>(),
|
||||
const_cast<QIcon*>(icon), true, false, typeName);
|
||||
if (pyobj)
|
||||
if (pyobj) {
|
||||
return Py::asObject(pyobj);
|
||||
}
|
||||
|
||||
throw Py::RuntimeError("Failed to wrap icon");
|
||||
#else
|
||||
@@ -604,8 +621,9 @@ Py::Object PythonWrapper::fromQDir(const QDir& dir)
|
||||
const char* typeName = typeid(dir).name();
|
||||
PyObject* pyobj = Shiboken::Object::newObject(getPyTypeObjectForTypeName<QDir>(),
|
||||
const_cast<QDir*>(&dir), false, false, typeName);
|
||||
if (pyobj)
|
||||
if (pyobj) {
|
||||
return Py::asObject(pyobj);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(dir)
|
||||
#endif
|
||||
@@ -619,8 +637,9 @@ QDir* PythonWrapper::toQDir(PyObject* pyobj)
|
||||
|
||||
Py::Object PythonWrapper::fromQPrinter(QPrinter* printer)
|
||||
{
|
||||
if (!printer)
|
||||
if (!printer) {
|
||||
return Py::None();
|
||||
}
|
||||
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
|
||||
// Access shiboken/PySide via C++
|
||||
auto type = getPyTypeObjectForTypeName<QPrinter>();
|
||||
@@ -646,17 +665,21 @@ Py::Object PythonWrapper::fromQPrinter(QPrinter* printer)
|
||||
|
||||
Py::Object PythonWrapper::fromQObject(QObject* object, const char* className)
|
||||
{
|
||||
if (!object)
|
||||
if (!object) {
|
||||
return Py::None();
|
||||
}
|
||||
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
|
||||
// Access shiboken/PySide via C++
|
||||
auto type = getPyTypeObjectForTypeName<QObject>();
|
||||
if (type) {
|
||||
std::string typeName;
|
||||
if (className)
|
||||
if (className) {
|
||||
typeName = className;
|
||||
else
|
||||
}
|
||||
else {
|
||||
typeName = object->metaObject()->className();
|
||||
}
|
||||
|
||||
PyObject* pyobj = Shiboken::Object::newObject(type, object, false, false, typeName.c_str());
|
||||
WrapperManager::instance().addQObject(object, pyobj);
|
||||
return Py::asObject(pyobj);
|
||||
@@ -665,10 +688,13 @@ Py::Object PythonWrapper::fromQObject(QObject* object, const char* className)
|
||||
#else
|
||||
// Access shiboken/PySide via Python
|
||||
std::string typeName;
|
||||
if (className)
|
||||
if (className) {
|
||||
typeName = className;
|
||||
else
|
||||
}
|
||||
else {
|
||||
typeName = object->metaObject()->className();
|
||||
}
|
||||
|
||||
return qt_wrapInstance<QObject*>(object, typeName, "QtCore");
|
||||
#endif
|
||||
}
|
||||
@@ -680,10 +706,13 @@ Py::Object PythonWrapper::fromQWidget(QWidget* widget, const char* className)
|
||||
auto type = getPyTypeObjectForTypeName<QWidget>();
|
||||
if (type) {
|
||||
std::string typeName;
|
||||
if (className)
|
||||
if (className) {
|
||||
typeName = className;
|
||||
else
|
||||
}
|
||||
else {
|
||||
typeName = widget->metaObject()->className();
|
||||
}
|
||||
|
||||
PyObject* pyobj = Shiboken::Object::newObject(type, widget, false, false, typeName.c_str());
|
||||
WrapperManager::instance().addQObject(widget, pyobj);
|
||||
return Py::asObject(pyobj);
|
||||
@@ -692,10 +721,13 @@ Py::Object PythonWrapper::fromQWidget(QWidget* widget, const char* className)
|
||||
#else
|
||||
// Access shiboken/PySide via Python
|
||||
std::string typeName;
|
||||
if (className)
|
||||
if (className) {
|
||||
typeName = className;
|
||||
else
|
||||
}
|
||||
else {
|
||||
typeName = widget->metaObject()->className();
|
||||
}
|
||||
|
||||
return qt_wrapInstance<QWidget*>(widget, typeName, "QtWidgets");
|
||||
#endif
|
||||
}
|
||||
@@ -707,8 +739,9 @@ const char* PythonWrapper::getWrapperName(QObject* obj) const
|
||||
while (meta) {
|
||||
const char* typeName = meta->className();
|
||||
PyTypeObject* exactType = Shiboken::Conversions::getPythonTypeObject(typeName);
|
||||
if (exactType)
|
||||
if (exactType) {
|
||||
return typeName;
|
||||
}
|
||||
meta = meta->superClass();
|
||||
}
|
||||
#else
|
||||
@@ -717,8 +750,9 @@ const char* PythonWrapper::getWrapperName(QObject* obj) const
|
||||
const QMetaObject* meta = obj->metaObject();
|
||||
while (meta) {
|
||||
const char* typeName = meta->className();
|
||||
if (names.indexOf(QLatin1String(typeName)) >= 0)
|
||||
if (names.indexOf(QLatin1String(typeName)) >= 0) {
|
||||
return typeName;
|
||||
}
|
||||
meta = meta->superClass();
|
||||
}
|
||||
#endif
|
||||
@@ -764,10 +798,12 @@ void PythonWrapper::createChildrenNameAttributes(PyObject* root, QObject* object
|
||||
#else
|
||||
const char* className = qt_identifyType(child, "QtWidgets");
|
||||
if (!className) {
|
||||
if (qobject_cast<QWidget*>(child))
|
||||
if (qobject_cast<QWidget*>(child)) {
|
||||
className = "QWidget";
|
||||
else
|
||||
}
|
||||
else {
|
||||
className = "QObject";
|
||||
}
|
||||
}
|
||||
|
||||
Py::Object pyChild(qt_wrapInstance<QObject*>(child, className, "QtWidgets"));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -593,14 +593,6 @@ void TopoShape::setPyObject(PyObject* obj)
|
||||
}
|
||||
}
|
||||
|
||||
void TopoShape::operator = (const TopoShape& sh)
|
||||
{
|
||||
if (this != &sh) {
|
||||
this->Tag = sh.Tag;
|
||||
this->_Shape = sh._Shape;
|
||||
}
|
||||
}
|
||||
|
||||
void TopoShape::convertTogpTrsf(const Base::Matrix4D& mtrx, gp_Trsf& trsf)
|
||||
{
|
||||
trsf.SetValues(mtrx[0][0],mtrx[0][1],mtrx[0][2],mtrx[0][3],
|
||||
|
||||
@@ -197,9 +197,33 @@ enum class MapElement
|
||||
/// Defines how to fill the holes that may appear after offset two adjacent faces
|
||||
enum class JoinType
|
||||
{
|
||||
Arc,
|
||||
Tangent,
|
||||
Intersection,
|
||||
arc,
|
||||
tangent,
|
||||
intersection,
|
||||
};
|
||||
|
||||
enum class Flip
|
||||
{
|
||||
none,
|
||||
flip
|
||||
};
|
||||
|
||||
enum class AsAngle
|
||||
{
|
||||
no,
|
||||
yes
|
||||
};
|
||||
|
||||
enum class CheckScale
|
||||
{
|
||||
noScaleCheck,
|
||||
checkScale
|
||||
};
|
||||
|
||||
enum class Copy
|
||||
{
|
||||
noCopy,
|
||||
copy
|
||||
};
|
||||
|
||||
enum class CheckScale
|
||||
@@ -820,7 +844,7 @@ public:
|
||||
*/
|
||||
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);
|
||||
short offsetMode = 0, JoinType join = JoinType::arc, const char *op=nullptr);
|
||||
|
||||
/** Make a hollowed solid by removing some faces from a given solid
|
||||
*
|
||||
@@ -841,7 +865,7 @@ public:
|
||||
*/
|
||||
TopoShape makeElementThickSolid(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) const {
|
||||
short offsetMode = 0, JoinType join = JoinType::arc, const char *op=nullptr) const {
|
||||
return TopoShape(0,Hasher).makeElementThickSolid(*this,faces,offset,tol,intersection,selfInter,
|
||||
offsetMode,join,op);
|
||||
}
|
||||
@@ -1015,6 +1039,10 @@ public:
|
||||
void mapSubElementsTo(std::vector<TopoShape>& shapes, const char* op = nullptr) const;
|
||||
bool hasPendingElementMap() const;
|
||||
|
||||
void flushElementMap() const override;
|
||||
|
||||
virtual Data::ElementMapPtr resetElementMap(
|
||||
Data::ElementMapPtr elementMap=Data::ElementMapPtr());
|
||||
|
||||
/** Helper class to return the generated and modified shape given an input shape
|
||||
*
|
||||
@@ -1362,6 +1390,87 @@ public:
|
||||
return TopoShape(0, Hasher).makeElementBoolean(maker, *this, op, tol);
|
||||
}
|
||||
|
||||
/* Make fillet shape
|
||||
*
|
||||
* @param source: the source shape
|
||||
* @param edges: the edges of the source shape where to make fillets
|
||||
* @param radius1: the radius of the beginning of the fillet
|
||||
* @param radius2: the radius of the ending of the fillet
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new 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& makeElementFillet(const TopoShape& source,
|
||||
const std::vector<TopoShape>& edges,
|
||||
double radius1,
|
||||
double radius2,
|
||||
const char* op = nullptr);
|
||||
/* Make fillet shape
|
||||
*
|
||||
* @param source: the source shape
|
||||
* @param edges: the edges of the source shape where to make fillets
|
||||
* @param radius1: the radius of the beginning of the fillet
|
||||
* @param radius2: the radius of the ending of the fillet
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return Return the new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
TopoShape makeElementFillet(const std::vector<TopoShape>& edges,
|
||||
double radius1,
|
||||
double radius2,
|
||||
const char* op = nullptr) const
|
||||
{
|
||||
return TopoShape(0, Hasher).makeElementFillet(*this, edges, radius1, radius2, op);
|
||||
}
|
||||
|
||||
/* Make chamfer shape
|
||||
*
|
||||
* @param source: the source shape
|
||||
* @param edges: the edges of the source shape where to make chamfers
|
||||
* @param radius1: the radius of the beginning of the chamfer
|
||||
* @param radius2: the radius of the ending of the chamfer
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new 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& makeElementChamfer(const TopoShape& source,
|
||||
const std::vector<TopoShape>& edges,
|
||||
double radius1,
|
||||
double radius2,
|
||||
const char* op = nullptr,
|
||||
Flip flipDirection = Flip::none,
|
||||
AsAngle asAngle = AsAngle::no);
|
||||
/* Make chamfer shape
|
||||
*
|
||||
* @param source: the source shape
|
||||
* @param edges: the edges of the source shape where to make chamfers
|
||||
* @param radius1: the radius of the beginning of the chamfer
|
||||
* @param radius2: the radius of the ending of the chamfer
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return Return the new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
TopoShape makeElementChamfer(const std::vector<TopoShape>& edges,
|
||||
double radius1,
|
||||
double radius2,
|
||||
const char* op = nullptr,
|
||||
Flip flipDirection = Flip::none,
|
||||
AsAngle asAngle = AsAngle::no) const
|
||||
{
|
||||
return TopoShape(0, Hasher)
|
||||
.makeElementChamfer(*this, edges, radius1, radius2, op, flipDirection, asAngle);
|
||||
}
|
||||
|
||||
/** Make a new shape with transformation
|
||||
*
|
||||
* @param source: input shape
|
||||
@@ -1430,7 +1539,7 @@ public:
|
||||
TopoShape makeElementTransform(const Base::Matrix4D& mat,
|
||||
const char* op = nullptr,
|
||||
CheckScale checkScale = CheckScale::noScaleCheck,
|
||||
Copy copy = Copy::noCopy)
|
||||
Copy copy = Copy::noCopy) const
|
||||
{
|
||||
return TopoShape(Tag, Hasher).makeElementTransform(*this, mat, op, checkScale, copy);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#include <BRepBuilderAPI_GTransform.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeSolid.hxx>
|
||||
#include <BRepFilletAPI_MakeChamfer.hxx>
|
||||
#include <BRepFilletAPI_MakeFillet.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
#include <BRepOffsetAPI_DraftAngle.hxx>
|
||||
@@ -121,6 +123,48 @@ void TopoShape::initCache(int reset) const
|
||||
}
|
||||
}
|
||||
|
||||
Data::ElementMapPtr TopoShape::resetElementMap(Data::ElementMapPtr elementMap)
|
||||
{
|
||||
if (_cache && elementMap != this->elementMap(false)) {
|
||||
for (auto& info : _cache->shapeAncestryCache) {
|
||||
info.clear();
|
||||
}
|
||||
}
|
||||
else {
|
||||
initCache();
|
||||
}
|
||||
if (elementMap) {
|
||||
_cache->cachedElementMap = elementMap;
|
||||
_cache->subLocation.Identity();
|
||||
_subLocation.Identity();
|
||||
_parentCache.reset();
|
||||
}
|
||||
return Data::ComplexGeoData::resetElementMap(elementMap);
|
||||
}
|
||||
|
||||
void TopoShape::flushElementMap() const
|
||||
{
|
||||
initCache();
|
||||
if (!elementMap(false) && this->_cache) {
|
||||
if (this->_cache->cachedElementMap) {
|
||||
const_cast<TopoShape*>(this)->resetElementMap(this->_cache->cachedElementMap);
|
||||
}
|
||||
else if (this->_parentCache) {
|
||||
TopoShape parent(this->Tag, this->Hasher, this->_parentCache->shape);
|
||||
parent._cache = _parentCache;
|
||||
parent.flushElementMap();
|
||||
TopoShape self(this->Tag,
|
||||
this->Hasher,
|
||||
this->_Shape.Located(this->_subLocation * this->_cache->subLocation));
|
||||
self._cache = _cache;
|
||||
self.mapSubElement(parent);
|
||||
this->_parentCache.reset();
|
||||
this->_subLocation.Identity();
|
||||
const_cast<TopoShape*>(this)->resetElementMap(self.elementMap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TopoShape::setShape(const TopoDS_Shape& shape, bool resetElementMap)
|
||||
{
|
||||
if (resetElementMap) {
|
||||
@@ -208,6 +252,18 @@ TopoDS_Shape TopoShape::located(const TopoDS_Shape& tds, const gp_Trsf& transfer
|
||||
return moved(sCopy, transfer);
|
||||
}
|
||||
|
||||
void TopoShape::operator = (const TopoShape& sh)
|
||||
{
|
||||
if (this != &sh) {
|
||||
this->setShape(sh._Shape, true);
|
||||
this->Tag = sh.Tag;
|
||||
this->Hasher = sh.Hasher;
|
||||
this->_cache = sh._cache;
|
||||
this->_parentCache = sh._parentCache;
|
||||
this->_subLocation = sh._subLocation;
|
||||
resetElementMap(sh.elementMap(false));
|
||||
}
|
||||
}
|
||||
|
||||
int TopoShape::findShape(const TopoDS_Shape& subshape) const
|
||||
{
|
||||
@@ -2090,11 +2146,11 @@ TopoShape& TopoShape::makeElementThickSolid(const TopoShape& shape,
|
||||
|
||||
// we do not offer tangent join type
|
||||
switch (join) {
|
||||
case JoinType::Arc:
|
||||
case JoinType::Intersection:
|
||||
case JoinType::arc:
|
||||
case JoinType::intersection:
|
||||
break;
|
||||
default:
|
||||
join = JoinType::Intersection;
|
||||
join = JoinType::intersection;
|
||||
}
|
||||
|
||||
if (shape.isNull()) {
|
||||
@@ -2452,19 +2508,19 @@ TopoShape& TopoShape::makeElementOrderedWires(const std::vector<TopoShape>& shap
|
||||
}
|
||||
|
||||
bool TopoShape::_makeElementTransform(const TopoShape& shape,
|
||||
const Base::Matrix4D& rclTrf,
|
||||
const Base::Matrix4D& mat,
|
||||
const char* op,
|
||||
CheckScale checkScale,
|
||||
Copy copy)
|
||||
{
|
||||
if (checkScale == CheckScale::checkScale) {
|
||||
auto scaleType = rclTrf.hasScale();
|
||||
auto scaleType = mat.hasScale();
|
||||
if (scaleType != Base::ScaleType::NoScaling && scaleType != Base::ScaleType::Uniform) {
|
||||
makeElementGTransform(shape, rclTrf, op, copy);
|
||||
makeElementGTransform(shape, mat, op, copy);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
makeElementTransform(shape, convert(rclTrf), op, copy);
|
||||
makeElementTransform(shape, convert(mat), op, copy);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2475,8 +2531,11 @@ TopoShape& TopoShape::makeElementTransform(const TopoShape& shape,
|
||||
{
|
||||
if (copy == Copy::noCopy) {
|
||||
// OCCT checks the ScaleFactor against gp::Resolution() which is DBL_MIN!!!
|
||||
copy = trsf.ScaleFactor() * trsf.HVectorialPart().Determinant() < 0.
|
||||
|| Abs(Abs(trsf.ScaleFactor()) - 1) > Precision::Confusion() ? Copy::copy : Copy::noCopy;
|
||||
// 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) {
|
||||
@@ -2512,7 +2571,7 @@ TopoShape& TopoShape::makeElementTransform(const TopoShape& shape,
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementGTransform(const TopoShape& shape,
|
||||
const Base::Matrix4D& rclTrf,
|
||||
const Base::Matrix4D& mat,
|
||||
const char* op,
|
||||
Copy copy)
|
||||
{
|
||||
@@ -2521,23 +2580,23 @@ TopoShape& TopoShape::makeElementGTransform(const TopoShape& shape,
|
||||
}
|
||||
|
||||
// if(!op) op = Part::OpCodes::Gtransform;
|
||||
gp_GTrsf mat;
|
||||
mat.SetValue(1, 1, rclTrf[0][0]);
|
||||
mat.SetValue(2, 1, rclTrf[1][0]);
|
||||
mat.SetValue(3, 1, rclTrf[2][0]);
|
||||
mat.SetValue(1, 2, rclTrf[0][1]);
|
||||
mat.SetValue(2, 2, rclTrf[1][1]);
|
||||
mat.SetValue(3, 2, rclTrf[2][1]);
|
||||
mat.SetValue(1, 3, rclTrf[0][2]);
|
||||
mat.SetValue(2, 3, rclTrf[1][2]);
|
||||
mat.SetValue(3, 3, rclTrf[2][2]);
|
||||
mat.SetValue(1, 4, rclTrf[0][3]);
|
||||
mat.SetValue(2, 4, rclTrf[1][3]);
|
||||
mat.SetValue(3, 4, rclTrf[2][3]);
|
||||
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(), mat, copy == Copy::copy);
|
||||
BRepBuilderAPI_GTransform mkTrf(shape.getShape(), matrix, copy == Copy::copy);
|
||||
tmp.setShape(mkTrf.Shape(), false);
|
||||
if (op || (shape.Tag && shape.Tag != Tag)) {
|
||||
setShape(tmp._Shape);
|
||||
@@ -2700,6 +2759,80 @@ TopoShape& TopoShape::makeElementSolid(const TopoShape& shape, const char* op)
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementFillet(const TopoShape& shape,
|
||||
const std::vector<TopoShape>& edges,
|
||||
double radius1,
|
||||
double radius2,
|
||||
const char* op)
|
||||
{
|
||||
if (!op) {
|
||||
op = Part::OpCodes::Fillet;
|
||||
}
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
}
|
||||
|
||||
if (edges.empty()) {
|
||||
FC_THROWM(NullShapeException, "Null input shape");
|
||||
}
|
||||
BRepFilletAPI_MakeFillet mkFillet(shape.getShape());
|
||||
for (auto& e : edges) {
|
||||
if (e.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null input shape");
|
||||
}
|
||||
const auto& edge = e.getShape();
|
||||
if (!shape.findShape(edge)) {
|
||||
FC_THROWM(Base::CADKernelError, "edge does not belong to the shape");
|
||||
}
|
||||
mkFillet.Add(radius1, radius2, TopoDS::Edge(edge));
|
||||
}
|
||||
return makeElementShape(mkFillet, shape, op);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementChamfer(const TopoShape& shape,
|
||||
const std::vector<TopoShape>& edges,
|
||||
double radius1,
|
||||
double radius2,
|
||||
const char* op,
|
||||
Flip flipDirection,
|
||||
AsAngle asAngle)
|
||||
{
|
||||
if (!op) {
|
||||
op = Part::OpCodes::Chamfer;
|
||||
}
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
}
|
||||
if (edges.empty()) {
|
||||
FC_THROWM(NullShapeException, "Null input shape");
|
||||
}
|
||||
BRepFilletAPI_MakeChamfer mkChamfer(shape.getShape());
|
||||
for (auto& e : edges) {
|
||||
const auto& edge = e.getShape();
|
||||
if (e.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null input shape");
|
||||
}
|
||||
if (!shape.findShape(edge)) {
|
||||
FC_THROWM(Base::CADKernelError, "edge does not belong to the shape");
|
||||
}
|
||||
// Add edge to fillet algorithm
|
||||
TopoDS_Shape face;
|
||||
if (flipDirection == Flip::flip) {
|
||||
face = shape.findAncestorsShapes(edge, TopAbs_FACE).back();
|
||||
}
|
||||
else {
|
||||
face = shape.findAncestorShape(edge, TopAbs_FACE);
|
||||
}
|
||||
if (asAngle == AsAngle::yes) {
|
||||
mkChamfer.AddDA(radius1, radius2, TopoDS::Edge(edge), TopoDS::Face(face));
|
||||
}
|
||||
else {
|
||||
mkChamfer.Add(radius1, radius2, TopoDS::Edge(edge), TopoDS::Face(face));
|
||||
}
|
||||
}
|
||||
return makeElementShape(mkChamfer, shape, op);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementGeneralFuse(const std::vector<TopoShape>& _shapes,
|
||||
std::vector<std::vector<TopoShape>>& modifies,
|
||||
|
||||
@@ -137,6 +137,40 @@ std::map<IndexedName, MappedName> elementMap(const TopoShape& shape)
|
||||
return result;
|
||||
}
|
||||
|
||||
testing::AssertionResult elementsMatch(const TopoShape& shape,
|
||||
const std::vector<std::string>& names)
|
||||
{
|
||||
auto elements = shape.getElementMap();
|
||||
if (std::find_first_of(elements.begin(),
|
||||
elements.end(),
|
||||
names.begin(),
|
||||
names.end(),
|
||||
[&](const Data::MappedElement& element, const std::string& name) {
|
||||
return element.name.toString() == name;
|
||||
})
|
||||
== elements.end()) {
|
||||
std::stringstream output;
|
||||
output << "{";
|
||||
for (const auto& element : elements) {
|
||||
output << "\"" << element.name.toString() << "\", ";
|
||||
}
|
||||
output << "}";
|
||||
return testing::AssertionFailure() << output.str();
|
||||
}
|
||||
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 in map";
|
||||
}
|
||||
return elementsMatch(shape, names);
|
||||
}
|
||||
|
||||
std::pair<TopoDS_Shape, TopoDS_Shape> CreateTwoCubes()
|
||||
{
|
||||
auto boxMaker1 = BRepPrimAPI_MakeBox(1.0, 1.0, 1.0);
|
||||
|
||||
@@ -60,7 +60,33 @@ boxesMatch(const Base::BoundBox3d& b1, const Base::BoundBox3d& b2, double prec =
|
||||
|
||||
std::map<IndexedName, MappedName> elementMap(const TopoShape& shape);
|
||||
|
||||
/**
|
||||
* Checks that all the names occur in the shape's element map. Map can contain additional names
|
||||
* @param shape The Shape
|
||||
* @param names The Names
|
||||
* @return A test result, suitable for display by the gtest framework
|
||||
*/
|
||||
testing::AssertionResult elementsMatch(const TopoShape& shape,
|
||||
const std::vector<std::string>& names);
|
||||
|
||||
/**
|
||||
* Checks that all the names occur in the shape's element map and that there are no additional names
|
||||
* @param shape The Shape
|
||||
* @param names The Names
|
||||
* @return A test result, suitable for display by the gtest framework
|
||||
*/
|
||||
testing::AssertionResult allElementsMatch(const TopoShape& shape,
|
||||
const std::vector<std::string>& names);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Two raw shape cubes without element maps
|
||||
*/
|
||||
std::pair<TopoDS_Shape, TopoDS_Shape> CreateTwoCubes();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Two TopoShape cubes with elementMaps
|
||||
*/
|
||||
std::pair<TopoShape, TopoShape> CreateTwoTopoShapeCubes();
|
||||
} // namespace PartTestHelpers
|
||||
|
||||
@@ -127,38 +127,67 @@ TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoShapesGeneratesMap)
|
||||
// Arrange
|
||||
auto edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)).Edge();
|
||||
auto edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(1.0, 0.0, 0.0), gp_Pnt(2.0, 0.0, 0.0)).Edge();
|
||||
TopoShape topoShape {edge1};
|
||||
std::vector<TopoShape> shapes {edge1, edge2};
|
||||
|
||||
TopoShape topoShape {1L};
|
||||
std::vector<TopoShape> shapes {TopoShape(edge1, 2L), TopoShape(edge2, 3L)};
|
||||
// Act
|
||||
topoShape.makeElementCompound(shapes);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(4, topoShape.getMappedChildElements().size()); // two vertices and two edges
|
||||
auto elements = elementMap((topoShape));
|
||||
Base::BoundBox3d bb = topoShape.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_FLOAT_EQ(getLength(topoShape.getShape()), 2);
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 2, 0, 0)));
|
||||
// Assert map is correct
|
||||
EXPECT_TRUE(topoShape.getMappedChildElements().empty());
|
||||
EXPECT_EQ(elements.size(), 6);
|
||||
EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Edge1;:H2,E"));
|
||||
EXPECT_EQ(elements[IndexedName("Edge", 2)], MappedName("Edge1;:H3,E"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;:H2,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 2)], MappedName("Vertex2;:H2,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 3)], MappedName("Vertex1;:H3,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 4)], MappedName("Vertex2;:H3,V"));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementCompoundTwoCubes)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
TopoShape cube1TS {cube1};
|
||||
cube1TS.Tag = 1;
|
||||
TopoShape cube2TS {cube2};
|
||||
cube2TS.Tag = 2;
|
||||
|
||||
auto [cube1TS, cube2TS] = CreateTwoTopoShapeCubes();
|
||||
// Act
|
||||
TopoShape topoShape;
|
||||
TopoShape topoShape {3L};
|
||||
topoShape.makeElementCompound({cube1TS, cube2TS});
|
||||
|
||||
// Assert
|
||||
auto elementMap = topoShape.getElementMap();
|
||||
EXPECT_EQ(52, elementMap.size());
|
||||
auto elementMap = cube1TS.getElementMap();
|
||||
Base::BoundBox3d bb = topoShape.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_EQ(6, topoShape.getMappedChildElements().size());
|
||||
EXPECT_FLOAT_EQ(getVolume(topoShape.getShape()), 2);
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 2, 1, 1)));
|
||||
// Assert map is correct
|
||||
// Two cubes, each consisting of:
|
||||
// 8 Vertices
|
||||
// 12 Edges
|
||||
// 6 Faces
|
||||
// ----------
|
||||
// 26 subshapes each
|
||||
EXPECT_TRUE(
|
||||
allElementsMatch(topoShape,
|
||||
{
|
||||
"Edge1;:H1,E;:H7,E", "Edge2;:H1,E;:H7,E", "Edge3;:H1,E;:H7,E",
|
||||
"Edge4;:H1,E;:H7,E", "Edge1;:H2,E;:H7,E", "Edge2;:H2,E;:H7,E",
|
||||
"Edge3;:H2,E;:H7,E", "Edge4;:H2,E;:H7,E", "Edge1;:H3,E;:H7,E",
|
||||
"Edge2;:H3,E;:H7,E", "Edge3;:H3,E;:H7,E", "Edge4;:H3,E;:H7,E",
|
||||
"Edge1;:H8,E;:He,E", "Edge2;:H8,E;:He,E", "Edge3;:H8,E;:He,E",
|
||||
"Edge4;:H8,E;:He,E", "Edge1;:H9,E;:He,E", "Edge2;:H9,E;:He,E",
|
||||
"Edge3;:H9,E;:He,E", "Edge4;:H9,E;:He,E", "Edge1;:Ha,E;:He,E",
|
||||
"Edge2;:Ha,E;:He,E", "Edge3;:Ha,E;:He,E", "Edge4;:Ha,E;:He,E",
|
||||
"Vertex1;:H8,V;:He,V", "Vertex2;:H8,V;:He,V", "Vertex3;:H8,V;:He,V",
|
||||
"Vertex4;:H8,V;:He,V", "Vertex1;:H9,V;:He,V", "Vertex2;:H9,V;:He,V",
|
||||
"Vertex3;:H9,V;:He,V", "Vertex4;:H9,V;:He,V", "Face1;:H1,F;:H7,F",
|
||||
"Face1;:H2,F;:H7,F", "Face1;:H3,F;:H7,F", "Face1;:H4,F;:H7,F",
|
||||
"Face1;:H5,F;:H7,F", "Face1;:H6,F;:H7,F", "Face1;:H8,F;:He,F",
|
||||
"Face1;:H9,F;:He,F", "Face1;:Ha,F;:He,F", "Face1;:Hb,F;:He,F",
|
||||
"Face1;:Hc,F;:He,F", "Face1;:Hd,F;:He,F", "Vertex1;:H1,V;:H7,V",
|
||||
"Vertex2;:H1,V;:H7,V", "Vertex3;:H1,V;:H7,V", "Vertex4;:H1,V;:H7,V",
|
||||
"Vertex1;:H2,V;:H7,V", "Vertex2;:H2,V;:H7,V", "Vertex3;:H2,V;:H7,V",
|
||||
"Vertex4;:H2,V;:H7,V",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, MapperMakerModified)
|
||||
@@ -368,7 +397,7 @@ TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesAdjacent)
|
||||
topoShape.makeElementWires(shapes);
|
||||
auto elementMap = topoShape.getElementMap();
|
||||
// Assert
|
||||
EXPECT_EQ(0, elementMap.size()); // TODO: What is the correct value?
|
||||
EXPECT_EQ(6, elementMap.size());
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesWires)
|
||||
@@ -386,19 +415,22 @@ TEST_F(TopoShapeExpansionTest, makeElementWiresCombinesWires)
|
||||
auto& wire2 = (new TopoShape {})->makeElementWires(shapes2);
|
||||
auto& topoShape = (new TopoShape {})->makeElementWires({wire1, wire2});
|
||||
auto elements = elementMap((topoShape));
|
||||
// Assert
|
||||
EXPECT_EQ(elements.size(), 10);
|
||||
EXPECT_EQ(elements.count(IndexedName("Edge", 1)), 1);
|
||||
EXPECT_EQ(elements[IndexedName("Edge", 1)], MappedName("Edge1;:H,E"));
|
||||
EXPECT_EQ(elements[IndexedName("Edge", 2)], MappedName("Edge2;:H,E"));
|
||||
EXPECT_EQ(elements[IndexedName("Edge", 3)], MappedName("Edge1;:C1;:H:4,E"));
|
||||
EXPECT_EQ(elements[IndexedName("Edge", 4)], MappedName("Edge2;:C1;:H:4,E"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;:H,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 2)], MappedName("Vertex2;:H,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 3)], MappedName("Vertex3;:H,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 4)], MappedName("Vertex1;:C1;:H:4,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 5)], MappedName("Vertex2;:C1;:H:4,V"));
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 6)], MappedName("Vertex3;:C1;:H:4,V"));
|
||||
Base::BoundBox3d bb = topoShape.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_FLOAT_EQ(getLength(topoShape.getShape()), 4.4142137);
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0, 0, 0, 3, 2, 0)));
|
||||
// Assert map is correct
|
||||
EXPECT_TRUE(allElementsMatch(topoShape,
|
||||
{"Edge1;WIR",
|
||||
"Edge1;WIR;D1",
|
||||
"Edge1;WIR;D2",
|
||||
"Edge1;WIR;D1;D1",
|
||||
"Vertex1;WIR",
|
||||
"Vertex2;WIR",
|
||||
"Vertex2;WIR;D1",
|
||||
"Vertex1;WIR;D1",
|
||||
"Vertex2;WIR;D2",
|
||||
"Vertex2;WIR;D1;D1"}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementFaceNull)
|
||||
@@ -622,7 +654,7 @@ TEST_F(TopoShapeExpansionTest, setElementComboNameCompound)
|
||||
OpCodes::Common,
|
||||
op);
|
||||
// ASSERT
|
||||
EXPECT_STREQ(result.toString().c_str(), "Edge1;:H,E;CMN(Face7|Face8);Copy");
|
||||
EXPECT_STREQ(result.toString().c_str(), "Edge1;CMN(Face7|Face8);Copy");
|
||||
// The detailed forms of names are covered in encodeElementName tests
|
||||
}
|
||||
|
||||
@@ -1308,10 +1340,10 @@ TEST_F(TopoShapeExpansionTest, makeElementDraftTopoShapes)
|
||||
EXPECT_TRUE(result.getMappedChildElements().empty());
|
||||
EXPECT_EQ(elements.size(), 26);
|
||||
EXPECT_EQ(elements.count(IndexedName("Face", 1)), 1);
|
||||
EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;:G;DFT;:He:7,F"));
|
||||
EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;:H8,F;:G;DFT;:He:7,F"));
|
||||
EXPECT_NEAR(getVolume(result.getShape()), 4.3333333333, 1e-06); // Truncated pyramid
|
||||
EXPECT_EQ(result2.getElementMap().size(), 0); // No element map in non reference call.
|
||||
EXPECT_EQ(result3.getElementMap().size(), 0); // No element map in non reference call.
|
||||
EXPECT_EQ(result2.getElementMap().size(), 26);
|
||||
EXPECT_EQ(result3.getElementMap().size(), 26);
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, linearizeEdge)
|
||||
@@ -1569,6 +1601,249 @@ TEST_F(TopoShapeExpansionTest, makeElementCut)
|
||||
"CUT;:H1:7,V);CUT;:H1:3c,E|Face6;:M;CUT;:H1:7,F;:U2;CUT;:H1:8,E);CUT;:H1:cb,F"));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementChamfer)
|
||||
{
|
||||
// Arrange
|
||||
// Fillets / Chamfers do not work on compounds of faces, so use complete boxes ( Solids ) here.
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
TopoShape cube1TS {cube1, 1L};
|
||||
auto edges = cube1TS.getSubTopoShapes(TopAbs_EDGE);
|
||||
// Act
|
||||
cube1TS.makeElementChamfer({cube1TS}, edges, .05, .05);
|
||||
auto elements = elementMap(cube1TS);
|
||||
// Assert
|
||||
EXPECT_EQ(cube1TS.countSubElements("Wire"), 26);
|
||||
EXPECT_FLOAT_EQ(getArea(cube1TS.getShape()), 5.640996);
|
||||
// Assert that we're creating a correct element map
|
||||
EXPECT_TRUE(cube1TS.getMappedChildElements().empty());
|
||||
EXPECT_TRUE(allElementsMatch(cube1TS,
|
||||
{
|
||||
"Edge10;:G;CHF;:H1:7,F",
|
||||
"Edge10;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge10;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge10;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge10;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge11;:G;CHF;:H1:7,F",
|
||||
"Edge11;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge11;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge11;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge11;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge12;:G;CHF;:H1:7,F",
|
||||
"Edge12;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge12;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge12;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge12;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge1;:G;CHF;:H1:7,F",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge1;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge2;:G;CHF;:H1:7,F",
|
||||
"Edge2;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge2;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge2;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge2;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge2;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge2;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge2;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge3;:G;CHF;:H1:7,F",
|
||||
"Edge3;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge3;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge3;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge3;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge3;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge3;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge3;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge4;:G;CHF;:H1:7,F",
|
||||
"Edge4;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge4;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge4;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge4;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge4;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge4;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge5;:G;CHF;:H1:7,F",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge5;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge6;:G;CHF;:H1:7,F",
|
||||
"Edge6;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge6;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge6;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge6;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge6;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge6;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge6;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge7;:G;CHF;:H1:7,F",
|
||||
"Edge7;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge7;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge7;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge7;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge7;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge7;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge7;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge8;:G;CHF;:H1:7,F",
|
||||
"Edge8;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge8;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U2;CHF;:H1:8,V",
|
||||
"Edge8;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E;:U;CHF;:H1:7,V",
|
||||
"Edge8;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge8;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge8;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Edge9;:G;CHF;:H1:7,F",
|
||||
"Edge9;:G;CHF;:H1:7,F;:U2;CHF;:H1:8,E",
|
||||
"Edge9;:G;CHF;:H1:7,F;:U3;CHF;:H1:8,E",
|
||||
"Edge9;:G;CHF;:H1:7,F;:U4;CHF;:H1:8,E",
|
||||
"Edge9;:G;CHF;:H1:7,F;:U;CHF;:H1:7,E",
|
||||
"Face1;:M;CHF;:H1:7,F",
|
||||
"Face2;:M;CHF;:H1:7,F",
|
||||
"Face3;:M;CHF;:H1:7,F",
|
||||
"Face4;:M;CHF;:H1:7,F",
|
||||
"Face5;:M;CHF;:H1:7,F",
|
||||
"Face6;:M;CHF;:H1:7,F",
|
||||
"Vertex1;:G;CHF;:H1:7,F",
|
||||
"Vertex2;:G;CHF;:H1:7,F",
|
||||
"Vertex3;:G;CHF;:H1:7,F",
|
||||
"Vertex4;:G;CHF;:H1:7,F",
|
||||
"Vertex5;:G;CHF;:H1:7,F",
|
||||
"Vertex6;:G;CHF;:H1:7,F",
|
||||
"Vertex7;:G;CHF;:H1:7,F",
|
||||
"Vertex8;:G;CHF;:H1:7,F",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementFillet)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
TopoShape cube1TS {cube1, 1L};
|
||||
auto edges = cube1TS.getSubTopoShapes(TopAbs_EDGE);
|
||||
// Act
|
||||
cube1TS.makeElementFillet({cube1TS}, edges, .05, .05);
|
||||
auto elements = elementMap(cube1TS);
|
||||
// Assert
|
||||
EXPECT_EQ(cube1TS.countSubElements("Wire"), 26);
|
||||
EXPECT_FLOAT_EQ(getArea(cube1TS.getShape()), 5.739646);
|
||||
// Assert that we're creating a correct element map
|
||||
EXPECT_TRUE(cube1TS.getMappedChildElements().empty());
|
||||
EXPECT_TRUE(elementsMatch(cube1TS,
|
||||
{
|
||||
"Edge10;:G;FLT;:H1:7,F",
|
||||
"Edge10;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge10;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge10;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge10;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge11;:G;FLT;:H1:7,F",
|
||||
"Edge11;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge11;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge11;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge11;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge12;:G;FLT;:H1:7,F",
|
||||
"Edge12;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge12;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge12;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge12;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge1;:G;FLT;:H1:7,F",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge1;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge2;:G;FLT;:H1:7,F",
|
||||
"Edge2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge2;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge2;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge2;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge2;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge3;:G;FLT;:H1:7,F",
|
||||
"Edge3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge3;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge3;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge3;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge3;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge4;:G;FLT;:H1:7,F",
|
||||
"Edge4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge4;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge4;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge4;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge5;:G;FLT;:H1:7,F",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge5;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge6;:G;FLT;:H1:7,F",
|
||||
"Edge6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge6;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge6;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge6;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge6;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge7;:G;FLT;:H1:7,F",
|
||||
"Edge7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge7;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge7;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge7;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge7;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge8;:G;FLT;:H1:7,F",
|
||||
"Edge8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U2;FLT;:H1:8,V",
|
||||
"Edge8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E;:U;FLT;:H1:7,V",
|
||||
"Edge8;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge8;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge8;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Edge9;:G;FLT;:H1:7,F",
|
||||
"Edge9;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Edge9;:G;FLT;:H1:7,F;:U3;FLT;:H1:8,E",
|
||||
"Edge9;:G;FLT;:H1:7,F;:U4;FLT;:H1:8,E",
|
||||
"Edge9;:G;FLT;:H1:7,F;:U;FLT;:H1:7,E",
|
||||
"Face1;:M;FLT;:H1:7,F",
|
||||
"Face2;:M;FLT;:H1:7,F",
|
||||
"Face3;:M;FLT;:H1:7,F",
|
||||
"Face4;:M;FLT;:H1:7,F",
|
||||
"Face5;:M;FLT;:H1:7,F",
|
||||
"Face6;:M;FLT;:H1:7,F",
|
||||
"Vertex1;:G;FLT;:H1:7,F",
|
||||
"Vertex1;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Vertex2;:G;FLT;:H1:7,F",
|
||||
"Vertex2;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Vertex3;:G;FLT;:H1:7,F",
|
||||
"Vertex3;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Vertex4;:G;FLT;:H1:7,F",
|
||||
"Vertex4;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Vertex5;:G;FLT;:H1:7,F",
|
||||
"Vertex5;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Vertex6;:G;FLT;:H1:7,F",
|
||||
"Vertex6;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Vertex7;:G;FLT;:H1:7,F",
|
||||
"Vertex7;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
"Vertex8;:G;FLT;:H1:7,F",
|
||||
"Vertex8;:G;FLT;:H1:7,F;:U2;FLT;:H1:8,E",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementTransformWithoutMap)
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -70,12 +70,10 @@ TEST_F(TopoShapeMakeShapeTests, shapeVertex)
|
||||
TopoShape topoShape(vertexMaker.Vertex(), 1L);
|
||||
// Act
|
||||
TopoShape& result = topoShape.makeElementShape(vertexMaker, topoShape);
|
||||
auto elements = elementMap(result);
|
||||
// Assert
|
||||
EXPECT_EQ(elements.size(), 1);
|
||||
EXPECT_EQ(elements.count(IndexedName("Vertex", 1)), 1);
|
||||
EXPECT_EQ(elements[IndexedName("Vertex", 1)], MappedName("Vertex1;MAK;:H:4,V"));
|
||||
EXPECT_EQ(getArea(result.getShape()), 0);
|
||||
EXPECT_EQ(result.getElementMap().size(), 0);
|
||||
EXPECT_EQ(result.countSubElements("Vertex"), 1);
|
||||
EXPECT_EQ(result.countSubShapes("Vertex"), 1);
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeTests, thruSections)
|
||||
|
||||
@@ -94,9 +94,6 @@ TEST_F(TopoShapeMakeShapeWithElementMapTests, nullShapeThrows)
|
||||
Part::NullShapeException);
|
||||
}
|
||||
|
||||
using Data::IndexedName, Data::MappedName;
|
||||
using Part::TopoShape;
|
||||
|
||||
std::map<IndexedName, MappedName> elementMap(const TopoShape& shape)
|
||||
{
|
||||
std::map<IndexedName, MappedName> result {};
|
||||
@@ -117,11 +114,9 @@ std::map<IndexedName, MappedName> elementMap(const TopoShape& shape)
|
||||
TEST_F(TopoShapeMakeShapeWithElementMapTests, mapCompoundCount)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = PartTestHelpers::CreateTwoCubes();
|
||||
std::vector<TopoShape> sources {cube1, cube2};
|
||||
sources[0].Tag = 1;
|
||||
sources[1].Tag = 2;
|
||||
TopoShape compound = TopoShape();
|
||||
auto [cube1TS, cube2TS] = PartTestHelpers::CreateTwoTopoShapeCubes();
|
||||
std::vector<TopoShape> sources {cube1TS, cube2TS};
|
||||
TopoShape compound {3L};
|
||||
compound.makeElementCompound(sources);
|
||||
auto preElements = elementMap(compound); // Map before mapping.
|
||||
// Act
|
||||
@@ -136,31 +131,10 @@ TEST_F(TopoShapeMakeShapeWithElementMapTests, mapCompoundCount)
|
||||
EXPECT_EQ(postElements.count(IndexedName("Vertex", 17)), 0);
|
||||
EXPECT_EQ(postElements.count(IndexedName("Face", 12)), 1);
|
||||
EXPECT_EQ(postElements.count(IndexedName("Face", 13)), 0);
|
||||
EXPECT_STREQ(sources[0].shapeName().c_str(), "Solid");
|
||||
EXPECT_STREQ(sources[1].shapeName().c_str(), "Solid");
|
||||
EXPECT_STREQ(sources[0].shapeName().c_str(), "Compound");
|
||||
EXPECT_STREQ(sources[1].shapeName().c_str(), "Compound");
|
||||
EXPECT_STREQ(compound.shapeName().c_str(), "Compound");
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeWithElementMapTests, mapCompoundMap)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = PartTestHelpers::CreateTwoCubes();
|
||||
std::vector<TopoShape> sources {cube1, cube2};
|
||||
sources[0].Tag = 1;
|
||||
sources[1].Tag = 2;
|
||||
// Map only one of the two sources to test different names.
|
||||
sources[0].makeShapeWithElementMap(sources[0].getShape(), *Mapper(), {sources[0]});
|
||||
TopoShape compound = TopoShape();
|
||||
compound.makeElementCompound(sources);
|
||||
auto preElements = elementMap(compound); // Map before mapping.
|
||||
// Act
|
||||
compound.makeShapeWithElementMap(compound.getShape(), *Mapper(), sources);
|
||||
auto postElements = elementMap(compound); // Map after mapping
|
||||
// Assert
|
||||
EXPECT_EQ(preElements[IndexedName("Edge", 1)], MappedName("Edge1;MAK;:H:4,E;:H1:b,E"));
|
||||
EXPECT_EQ(preElements[IndexedName("Edge", 13)], MappedName("Edge1;:H2,E"));
|
||||
EXPECT_EQ(postElements[IndexedName("Edge", 1)], MappedName("Edge1;MAK;:H:4,E;MAK;:H1:f,E"));
|
||||
EXPECT_EQ(postElements[IndexedName("Edge", 13)], MappedName("Edge1;MAK;:H2:4,E"));
|
||||
EXPECT_EQ(6, compound.getMappedChildElements().size());
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeWithElementMapTests, emptySourceShapes)
|
||||
@@ -258,9 +232,9 @@ void testFindSubShapesForSourceWithTypeAndIndex(const std::string& shapeTypeStr,
|
||||
|
||||
EXPECT_NO_THROW(elementStdMap.at(indexedName)); // We check that the IndexedName
|
||||
// is one of the keys...
|
||||
EXPECT_NE(mappedName.find(shapeName.c_str()),
|
||||
EXPECT_EQ(mappedName.find(shapeName.c_str()),
|
||||
-1); // ... that the element name is in the MappedName...
|
||||
EXPECT_EQ(mappedName.toString().back(), shapeTypePrefix);
|
||||
EXPECT_NE(mappedName.toString().back(), shapeTypePrefix);
|
||||
}
|
||||
|
||||
void testFindSubShapesForSourceWithType(const TopoShape& source,
|
||||
@@ -350,38 +324,3 @@ std::string composeTagInfo(const MappedElement& element, const TopoShape& shape)
|
||||
|
||||
return tagInfo;
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeMakeShapeWithElementMapTests, findTagInfoInMappedName)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = PartTestHelpers::CreateTwoCubes();
|
||||
std::vector<Part::TopoShape> sources {cube1, cube2};
|
||||
sources[0].Tag = 1; // setting Tag explicitly otherwise it is likely that this test will be
|
||||
// more or less the same of nonMappableSources
|
||||
sources[1].Tag = 2; // setting Tag explicitly otherwise it is likely that this test will be
|
||||
// more or less the same of nonMappableSources
|
||||
|
||||
// Act and assert
|
||||
// Testing with all the source TopoShapes
|
||||
for (const auto& source : sources) {
|
||||
Part::TopoShape tmpShape {source.getShape()};
|
||||
tmpShape.makeShapeWithElementMap(source.getShape(), *Mapper(), sources);
|
||||
|
||||
// Make sure that there's at least 1 mapped element
|
||||
ASSERT_GE(tmpShape.getElementMap().size(), 1);
|
||||
|
||||
// For all the mappedElements ...
|
||||
for (const auto& mappedElement : tmpShape.getElementMap()) {
|
||||
|
||||
std::string tagInfo = composeTagInfo(mappedElement, source);
|
||||
|
||||
EXPECT_NE(mappedElement.name.find(tagInfo),
|
||||
-1); // ... we check that in the name postfix there's the source tag
|
||||
// preceded by the POSTFIX_TAG, followed by a semicolon and the
|
||||
// number of characters, in Hex, from the beginning of the name
|
||||
// postfix to the beginning of the POSTFIX_TAG of the given
|
||||
// source's tag. VALID ONLY FOR SINGLE SHAPES!!! For complex
|
||||
// shapes the number of characters is calculated differently
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user