Merge branch 'master' into DraftModifiersAppPart
This commit is contained in:
@@ -130,13 +130,13 @@
|
||||
using namespace App;
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace boost::program_options;
|
||||
|
||||
|
||||
// scriptings (scripts are built-in but can be overridden by command line option)
|
||||
#include <App/InitScript.h>
|
||||
#include <App/TestScript.h>
|
||||
#include <App/CMakeScript.h>
|
||||
using namespace boost::program_options;
|
||||
|
||||
|
||||
// scriptings (scripts are built-in but can be overridden by command line option)
|
||||
#include <App/InitScript.h>
|
||||
#include <App/TestScript.h>
|
||||
#include <App/CMakeScript.h>
|
||||
|
||||
#ifdef _MSC_VER // New handler for Microsoft Visual C++ compiler
|
||||
# pragma warning( disable : 4535 )
|
||||
@@ -1082,6 +1082,16 @@ void Application::addImportType(const char* Type, const char* ModuleName)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::changeImportModule(const char* Type, const char* OldModuleName, const char* NewModuleName)
|
||||
{
|
||||
for (auto& it : _mImportTypes) {
|
||||
if (it.filter == Type && it.module == OldModuleName) {
|
||||
it.module = NewModuleName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> Application::getImportModules(const char* Type) const
|
||||
{
|
||||
std::vector<std::string> modules;
|
||||
@@ -1195,6 +1205,16 @@ void Application::addExportType(const char* Type, const char* ModuleName)
|
||||
}
|
||||
}
|
||||
|
||||
void Application::changeExportModule(const char* Type, const char* OldModuleName, const char* NewModuleName)
|
||||
{
|
||||
for (auto& it : _mExportTypes) {
|
||||
if (it.filter == Type && it.module == OldModuleName) {
|
||||
it.module = NewModuleName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> Application::getExportModules(const char* Type) const
|
||||
{
|
||||
std::vector<std::string> modules;
|
||||
@@ -2256,7 +2276,7 @@ void Application::LoadParameters(void)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// fix weird error while linking boost (all versions of VC)
|
||||
// VS2010: https://forum.freecadweb.org/viewtopic.php?f=4&t=1886&p=12553&hilit=boost%3A%3Afilesystem%3A%3Aget#p12553
|
||||
// VS2010: https://forum.freecadweb.org/viewtopic.php?f=4&t=1886&p=12553&hilit=boost%3A%3Afilesystem%3A%3Aget#p12553
|
||||
namespace boost { namespace program_options { std::string arg="arg"; } }
|
||||
#if (defined (BOOST_VERSION) && (BOOST_VERSION >= 104100))
|
||||
namespace boost { namespace program_options {
|
||||
@@ -2946,7 +2966,7 @@ std::string Application::FindHomePath(const char* sCall)
|
||||
binPath += L"bin";
|
||||
SetDllDirectoryW(binPath.c_str());
|
||||
|
||||
// https://stackoverflow.com/questions/5625884/conversion-of-stdwstring-to-qstring-throws-linker-error
|
||||
// https://stackoverflow.com/questions/5625884/conversion-of-stdwstring-to-qstring-throws-linker-error
|
||||
#ifdef _MSC_VER
|
||||
QString str = QString::fromUtf16(reinterpret_cast<const ushort *>(homePath.c_str()));
|
||||
#else
|
||||
|
||||
@@ -300,6 +300,8 @@ public:
|
||||
//@{
|
||||
/// Register an import filetype and a module name
|
||||
void addImportType(const char* Type, const char* ModuleName);
|
||||
/// Change the module name of a registered filetype
|
||||
void changeImportModule(const char* Type, const char* OldModuleName, const char* NewModuleName);
|
||||
/// Return a list of modules that support the given filetype.
|
||||
std::vector<std::string> getImportModules(const char* Type) const;
|
||||
/// Return a list of all modules.
|
||||
@@ -316,6 +318,8 @@ public:
|
||||
//@{
|
||||
/// Register an export filetype and a module name
|
||||
void addExportType(const char* Type, const char* ModuleName);
|
||||
/// Change the module name of a registered filetype
|
||||
void changeExportModule(const char* Type, const char* OldModuleName, const char* NewModuleName);
|
||||
/// Return a list of modules that support the given filetype.
|
||||
std::vector<std::string> getExportModules(const char* Type) const;
|
||||
/// Return a list of all modules.
|
||||
@@ -458,8 +462,10 @@ private:
|
||||
static PyObject* sSetConfig (PyObject *self,PyObject *args);
|
||||
static PyObject* sDumpConfig (PyObject *self,PyObject *args);
|
||||
static PyObject* sAddImportType (PyObject *self,PyObject *args);
|
||||
static PyObject* sChangeImportModule(PyObject *self,PyObject *args);
|
||||
static PyObject* sGetImportType (PyObject *self,PyObject *args);
|
||||
static PyObject* sAddExportType (PyObject *self,PyObject *args);
|
||||
static PyObject* sChangeExportModule(PyObject *self,PyObject *args);
|
||||
static PyObject* sGetExportType (PyObject *self,PyObject *args);
|
||||
static PyObject* sGetResourceDir (PyObject *self,PyObject *args);
|
||||
static PyObject* sGetUserAppDataDir (PyObject *self,PyObject *args);
|
||||
|
||||
@@ -72,6 +72,8 @@ PyMethodDef Application::Methods[] = {
|
||||
"Dump the configuration to the output."},
|
||||
{"addImportType", (PyCFunction) Application::sAddImportType, METH_VARARGS,
|
||||
"Register filetype for import"},
|
||||
{"changeImportModule", (PyCFunction) Application::sChangeImportModule, METH_VARARGS,
|
||||
"Change the import module name of a registered filetype"},
|
||||
{"getImportType", (PyCFunction) Application::sGetImportType, METH_VARARGS,
|
||||
"Get the name of the module that can import the filetype"},
|
||||
{"EndingAdd", (PyCFunction) Application::sAddImportType, METH_VARARGS, // deprecated
|
||||
@@ -80,6 +82,8 @@ PyMethodDef Application::Methods[] = {
|
||||
"deprecated -- use getImportType"},
|
||||
{"addExportType", (PyCFunction) Application::sAddExportType, METH_VARARGS,
|
||||
"Register filetype for export"},
|
||||
{"changeExportModule", (PyCFunction) Application::sChangeExportModule, METH_VARARGS,
|
||||
"Change the export module name of a registered filetype"},
|
||||
{"getExportType", (PyCFunction) Application::sGetExportType, METH_VARARGS,
|
||||
"Get the name of the module that can export the filetype"},
|
||||
{"getResourceDir", (PyCFunction) Application::sGetResourceDir, METH_VARARGS,
|
||||
@@ -526,6 +530,18 @@ PyObject* Application::sAddImportType(PyObject * /*self*/, PyObject *args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* Application::sChangeImportModule(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
char *key,*oldMod,*newMod;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod))
|
||||
return nullptr;
|
||||
|
||||
GetApplication().changeImportModule(key,oldMod,newMod);
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* Application::sGetImportType(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
char* psKey=0;
|
||||
@@ -578,6 +594,18 @@ PyObject* Application::sAddExportType(PyObject * /*self*/, PyObject *args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* Application::sChangeExportModule(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
char *key,*oldMod,*newMod;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "sss", &key,&oldMod,&newMod))
|
||||
return nullptr;
|
||||
|
||||
GetApplication().changeExportModule(key,oldMod,newMod);
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* Application::sGetExportType(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
char* psKey=0;
|
||||
|
||||
@@ -247,6 +247,12 @@ except ImportError:
|
||||
FreeCAD.Console.PrintError("\n\nSeems the python standard libs are not installed, bailing out!\n\n")
|
||||
raise
|
||||
|
||||
# Backward compatibility to Py2
|
||||
import sys
|
||||
if sys.version_info.major < 3:
|
||||
import time
|
||||
time.process_time = time.clock
|
||||
|
||||
class FCADLogger(object):
|
||||
'''Convenient class for tagged logging.
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@ void DlgGeneralImp::loadSettings()
|
||||
|
||||
int index = 1;
|
||||
TStringMap list = Translator::instance()->supportedLocales();
|
||||
ui->Languages->clear();
|
||||
ui->Languages->addItem(QString::fromLatin1("English"), QByteArray("English"));
|
||||
for (TStringMap::iterator it = list.begin(); it != list.end(); ++it, index++) {
|
||||
QByteArray lang = it->first.c_str();
|
||||
|
||||
@@ -324,16 +324,16 @@ public:
|
||||
bool press = (kbev->getState() == SoKeyboardEvent::DOWN);
|
||||
switch (kbev->getKey()) {
|
||||
case SoKeyboardEvent::H:
|
||||
if (press)
|
||||
if (!press)
|
||||
ns.onSetRotationCenter(kbev->getPosition());
|
||||
break;
|
||||
case SoKeyboardEvent::PAGE_UP:
|
||||
if(press){
|
||||
if(!press){
|
||||
ns.doZoom(ns.viewer->getSoRenderManager()->getCamera(), true, posn);
|
||||
}
|
||||
break;
|
||||
case SoKeyboardEvent::PAGE_DOWN:
|
||||
if(press){
|
||||
if(!press){
|
||||
ns.doZoom(ns.viewer->getSoRenderManager()->getCamera(), false, posn);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -244,6 +244,21 @@ int AlignmentGroup::count() const
|
||||
return this->_views.size();
|
||||
}
|
||||
|
||||
Base::BoundBox3d AlignmentGroup::getBoundingBox() const
|
||||
{
|
||||
Base::BoundBox3d box;
|
||||
std::vector<Gui::ViewProviderDocumentObject*>::const_iterator it;
|
||||
for (it = this->_views.begin(); it != this->_views.end(); ++it) {
|
||||
if ((*it)->isDerivedFrom(Gui::ViewProviderGeometryObject::getClassTypeId())) {
|
||||
App::GeoFeature* geo = static_cast<App::GeoFeature*>((*it)->getObject());
|
||||
const App::PropertyComplexGeoData* prop = geo->getPropertyOfGeometry();
|
||||
if (prop)
|
||||
box.Add(prop->getBoundingBox());
|
||||
}
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
MovableGroup::MovableGroup()
|
||||
@@ -334,6 +349,16 @@ const MovableGroup& MovableGroupModel::getGroup(int i) const
|
||||
return this->_groups[i];
|
||||
}
|
||||
|
||||
Base::BoundBox3d MovableGroupModel::getBoundingBox() const
|
||||
{
|
||||
Base::BoundBox3d box;
|
||||
std::vector<MovableGroup>::const_iterator it;
|
||||
for (it = this->_groups.begin(); it != this->_groups.end(); ++it) {
|
||||
box.Add(it->getBoundingBox());
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
namespace Gui {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define GUI_MANUALALIGNMENT_H
|
||||
|
||||
#include <QPointer>
|
||||
#include <Base/BoundBox.h>
|
||||
#include <Base/Placement.h>
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Gui/Application.h>
|
||||
@@ -123,6 +124,10 @@ public:
|
||||
* Return the number of added views.
|
||||
*/
|
||||
int count() const;
|
||||
/**
|
||||
* Get the overall bounding box of all views.
|
||||
*/
|
||||
Base::BoundBox3d getBoundingBox() const;
|
||||
|
||||
protected:
|
||||
std::vector<PickedPoint> _pickedPoints;
|
||||
@@ -170,6 +175,7 @@ public:
|
||||
bool isEmpty() const;
|
||||
int count() const;
|
||||
const MovableGroup& getGroup(int i) const;
|
||||
Base::BoundBox3d getBoundingBox() const;
|
||||
|
||||
protected:
|
||||
void removeActiveGroup();
|
||||
|
||||
@@ -37,6 +37,7 @@ SET(FemExamples_SRCS
|
||||
femexamples/__init__.py
|
||||
femexamples/boxanalysis.py
|
||||
femexamples/ccx_cantilever_std.py
|
||||
femexamples/contact_shell_shell.py
|
||||
femexamples/manager.py
|
||||
femexamples/material_multiple_twoboxes.py
|
||||
femexamples/material_nl_platewithhole.py
|
||||
@@ -50,6 +51,7 @@ SET(FemExampleMeshes_SRCS
|
||||
femexamples/meshes/mesh_boxanalysis_tetra10.py
|
||||
femexamples/meshes/mesh_boxes_2_vertikal_tetra10.py
|
||||
femexamples/meshes/mesh_canticcx_tetra10.py
|
||||
femexamples/meshes/mesh_contact_tube_tube_tria3.py
|
||||
femexamples/meshes/mesh_rc_wall_2d_tria6.py
|
||||
femexamples/meshes/mesh_platewithhole_tetra10.py
|
||||
femexamples/meshes/mesh_thermomech_flow1d_seg3.py
|
||||
@@ -161,6 +163,8 @@ SET(FemTestsFiles_SRCS
|
||||
|
||||
SET(FemTestsCcx_SRCS
|
||||
femtest/data/ccx/__init__.py
|
||||
femtest/data/ccx/contact_shell_shell.FCStd
|
||||
femtest/data/ccx/contact_shell_shell.inp
|
||||
femtest/data/ccx/cube_frequency.inp
|
||||
femtest/data/ccx/cube_frequency.dat
|
||||
femtest/data/ccx/cube_frequency.frd
|
||||
@@ -172,7 +176,8 @@ SET(FemTestsCcx_SRCS
|
||||
femtest/data/ccx/cube_static_expected_values
|
||||
femtest/data/ccx/cube_static.FCStd
|
||||
femtest/data/ccx/cube.FCStd
|
||||
femtest/data/ccx/multimat.inp
|
||||
femtest/data/ccx/mat_multiple.inp
|
||||
femtest/data/ccx/mat_nonlinear.inp
|
||||
femtest/data/ccx/spine_thermomech.inp
|
||||
femtest/data/ccx/spine_thermomech.dat
|
||||
femtest/data/ccx/spine_thermomech.frd
|
||||
|
||||
@@ -37,24 +37,33 @@ using namespace FemGui;
|
||||
#if 0 // needed for Qt's lupdate utility
|
||||
qApp->translate("Workbench", "FEM");
|
||||
qApp->translate("Workbench", "&FEM");
|
||||
//
|
||||
qApp->translate("Workbench", "Model");
|
||||
qApp->translate("Workbench", "M&odel");
|
||||
qApp->translate("Workbench", "Materials");
|
||||
qApp->translate("Workbench", "&Materials");
|
||||
qApp->translate("Workbench", "Element Geometry");
|
||||
qApp->translate("Workbench", "&Element Geometry");
|
||||
qApp->translate("Workbench", "Electrostatic Constraints");
|
||||
qApp->translate("Workbench", "&Electrostatic Constraints");
|
||||
qApp->translate("Workbench", "Fluid Constraints");
|
||||
qApp->translate("Workbench", "&Fluid Constraints");
|
||||
qApp->translate("Workbench", "Mechanical Constraints");
|
||||
qApp->translate("Workbench", "&Mechanical Constraints");
|
||||
qApp->translate("Workbench", "Thermal Constraints");
|
||||
qApp->translate("Workbench", "&Thermal Constraints");
|
||||
//
|
||||
qApp->translate("Workbench", "Mesh");
|
||||
qApp->translate("Workbench", "M&esh");
|
||||
qApp->translate("Workbench", "Fluid Constraints");
|
||||
qApp->translate("Workbench", "&Fluid Constraints");
|
||||
qApp->translate("Workbench", "Electrostatic Constraints");
|
||||
qApp->translate("Workbench", "&Electrostatic Constraints");
|
||||
//
|
||||
qApp->translate("Workbench", "Solve");
|
||||
qApp->translate("Workbench", "&Solve");
|
||||
//
|
||||
qApp->translate("Workbench", "Results");
|
||||
qApp->translate("Workbench", "&Results");
|
||||
qApp->translate("Workbench", "Materials");
|
||||
qApp->translate("Workbench", "&Element Geometry");
|
||||
qApp->translate("Workbench", "Filter functions");
|
||||
qApp->translate("Workbench", "&Filter functions");
|
||||
//
|
||||
qApp->translate("Workbench", "Utilities");
|
||||
#endif
|
||||
|
||||
|
||||
@@ -123,11 +123,13 @@ from femtest.utilstest import get_fem_test_defs as gf
|
||||
gf()
|
||||
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_femimport.TestObjectExistance.test_objects_existance"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_1_static_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_2_static_multiple_material"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_3_freq_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_4_thermomech_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_5_Flow1D_thermomech_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_freq_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_static_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_static_contact_shell_shell"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_static_material_multiple"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_static_material_nonlinar"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_thermomech_flow1D_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_ccxtools.TestCcxTools.test_thermomech_spine_analysis"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_common.TestFemCommon.test_adding_refshaps"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_common.TestFemCommon.test_pyimport_all_FEM_modules"
|
||||
./bin/FreeCADCmd --run-test "femtest.app.test_material.TestMaterialUnits.test_known_quantity_units"
|
||||
@@ -163,19 +165,25 @@ from femtest.utilstest import get_fem_test_defs as gf
|
||||
gf("in")
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_1_static_analysis"))
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_freq_analysis"))
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_2_static_multiple_material"))
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_static_analysis"))
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_3_freq_analysis"))
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_static_contact_shell_shell"))
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_4_thermomech_analysis"))
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_static_material_multiple"))
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_5_Flow1D_thermomech_analysis"))
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_static_material_nonlinar"))
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_thermomech_flow1D_analysis"))
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_ccxtools.TestCcxTools.test_thermomech_spine_analysis"))
|
||||
|
||||
import unittest
|
||||
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.app.test_common.TestFemCommon.test_adding_refshaps"))
|
||||
|
||||
194
src/Mod/Fem/femexamples/contact_shell_shell.py
Normal file
194
src/Mod/Fem/femexamples/contact_shell_shell.py
Normal file
@@ -0,0 +1,194 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2020 Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * FreeCAD is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with FreeCAD; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
# contact example shell to shell elements
|
||||
# https://forum.freecadweb.org/viewtopic.php?f=18&t=42228
|
||||
# based on https://forum.freecadweb.org/viewtopic.php?f=18&t=42228#p359488
|
||||
|
||||
import FreeCAD
|
||||
import ObjectsFem
|
||||
import Fem
|
||||
import Part
|
||||
import BOPTools.SplitFeatures
|
||||
|
||||
mesh_name = "Mesh" # needs to be Mesh to work with unit tests
|
||||
|
||||
|
||||
def init_doc(doc=None):
|
||||
if doc is None:
|
||||
doc = FreeCAD.newDocument()
|
||||
return doc
|
||||
|
||||
|
||||
def setup(doc=None, solvertype="ccxtools"):
|
||||
# setup model
|
||||
|
||||
if doc is None:
|
||||
doc = init_doc()
|
||||
|
||||
# parts
|
||||
# TODO turn circle of upper tube to have the line on the other side
|
||||
# make a boolean fragment of them to be sure there is a mesh point on remesh
|
||||
# but as long as we do not remesh it works without the boolean fragment too
|
||||
# tubes
|
||||
tube_radius = 25
|
||||
tube_length = 500
|
||||
sh_lower_circle = Part.Wire(Part.makeCircle(tube_radius))
|
||||
sh_lower_tube = sh_lower_circle.extrude(FreeCAD.Vector(0, 0, tube_length))
|
||||
sh_lower_tube.reverse()
|
||||
lower_tube = doc.addObject("Part::Feature", "Lower_tube")
|
||||
lower_tube.Shape = sh_lower_tube
|
||||
|
||||
sh_upper_circle = Part.Wire(Part.makeCircle(tube_radius))
|
||||
sh_upper_tube = sh_upper_circle.extrude(FreeCAD.Vector(0, 0, tube_length))
|
||||
sh_upper_tube.reverse()
|
||||
upper_tube = doc.addObject("Part::Feature", "Upper_tube")
|
||||
upper_tube.Shape = sh_upper_tube
|
||||
upper_tube.Placement = FreeCAD.Placement(
|
||||
FreeCAD.Vector(-25, 51, 475),
|
||||
FreeCAD.Rotation(90, 0, 90),
|
||||
FreeCAD.Vector(0, 0, 0),
|
||||
)
|
||||
|
||||
# point for load
|
||||
v_force_pt = FreeCAD.Vector(0, 76, 475)
|
||||
sh_force_point = Part.Vertex(v_force_pt)
|
||||
force_point = doc.addObject("Part::Feature", "Load_place_point")
|
||||
force_point.Shape = sh_force_point
|
||||
if FreeCAD.GuiUp:
|
||||
force_point.ViewObject.PointSize = 10.0
|
||||
force_point.ViewObject.PointColor = (1.0, 0.0, 0.0)
|
||||
|
||||
BooleanFrag = BOPTools.SplitFeatures.makeBooleanFragments(name='BooleanFragments')
|
||||
BooleanFrag.Objects = [upper_tube, force_point]
|
||||
|
||||
compound = doc.addObject("Part::Compound", "Compound")
|
||||
compound.Links = [BooleanFrag, lower_tube]
|
||||
|
||||
# line for load direction
|
||||
sh_load_line = Part.makeLine(v_force_pt, FreeCAD.Vector(0, 150, 475))
|
||||
load_line = doc.addObject("Part::Feature", "Load_direction_line")
|
||||
load_line.Shape = sh_load_line
|
||||
if FreeCAD.GuiUp:
|
||||
load_line.ViewObject.LineWidth = 5.0
|
||||
load_line.ViewObject.LineColor = (1.0, 0.0, 0.0)
|
||||
|
||||
doc.recompute()
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
FreeCADGui.ActiveDocument.activeView().viewAxonometric()
|
||||
FreeCADGui.SendMsgToActiveView("ViewFit")
|
||||
|
||||
# analysis
|
||||
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
|
||||
|
||||
# solver
|
||||
if solvertype == "calculix":
|
||||
solver_object = analysis.addObject(
|
||||
ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX")
|
||||
)[0]
|
||||
elif solvertype == "ccxtools":
|
||||
solver_object = analysis.addObject(
|
||||
ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools")
|
||||
)[0]
|
||||
solver_object.WorkingDir = u""
|
||||
if solvertype == "calculix" or solvertype == "ccxtools":
|
||||
solver_object.AnalysisType = "static"
|
||||
solver_object.BeamShellResultOutput3D = True
|
||||
solver_object.GeometricalNonlinearity = "linear" # really?
|
||||
# TODO iterations parameter !!!
|
||||
solver_object.ThermoMechSteadyState = False
|
||||
solver_object.MatrixSolverType = "default"
|
||||
solver_object.IterationsControlParameterTimeUse = False
|
||||
solver_object.SplitInputWriter = False
|
||||
|
||||
# shell thickness
|
||||
analysis.addObject(ObjectsFem.makeElementGeometry2D(doc, 0.5, 'ShellThickness'))
|
||||
|
||||
# material
|
||||
material_obj = analysis.addObject(
|
||||
ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial")
|
||||
)[0]
|
||||
mat = material_obj.Material
|
||||
mat["Name"] = "AlCuMgPb"
|
||||
mat["YoungsModulus"] = "72000 MPa"
|
||||
mat["PoissonRatio"] = "0.30"
|
||||
material_obj.Material = mat
|
||||
analysis.addObject(material_obj)
|
||||
|
||||
# fixed_constraint
|
||||
fixed_constraint = analysis.addObject(
|
||||
ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed")
|
||||
)[0]
|
||||
fixed_constraint.References = [
|
||||
(lower_tube, "Edge2"),
|
||||
(upper_tube, "Edge3"),
|
||||
]
|
||||
|
||||
# force_constraint
|
||||
force_constraint = doc.Analysis.addObject(
|
||||
ObjectsFem.makeConstraintForce(doc, name="ConstraintForce")
|
||||
)[0]
|
||||
# TODO use point of tube boolean fragment
|
||||
force_constraint.References = [(force_point, "Vertex1")]
|
||||
force_constraint.Force = 5000.0
|
||||
force_constraint.Direction = (load_line, ["Edge1"])
|
||||
force_constraint.Reversed = True
|
||||
|
||||
# contact constraint
|
||||
contact_constraint = doc.Analysis.addObject(
|
||||
ObjectsFem.makeConstraintContact(doc, name="ConstraintContact")
|
||||
)[0]
|
||||
contact_constraint.References = [
|
||||
(lower_tube, "Face1"),
|
||||
(upper_tube, "Face1"),
|
||||
]
|
||||
contact_constraint.Friction = 0.0
|
||||
# contact_constrsh_aint.Slope = "1000000.0 kg/(mm*s^2)" # contact stiffness
|
||||
contact_constraint.Slope = 1000000.0 # should be 1000000.0 kg/(mm*s^2)
|
||||
|
||||
# mesh
|
||||
from .meshes.mesh_contact_tube_tube_tria3 import create_nodes, create_elements
|
||||
fem_mesh = Fem.FemMesh()
|
||||
control = create_nodes(fem_mesh)
|
||||
if not control:
|
||||
FreeCAD.Console.PrintError("Error on creating nodes.\n")
|
||||
control = create_elements(fem_mesh)
|
||||
if not control:
|
||||
FreeCAD.Console.PrintError("Error on creating elements.\n")
|
||||
femmesh_obj = analysis.addObject(
|
||||
doc.addObject("Fem::FemMeshObject", mesh_name)
|
||||
)[0]
|
||||
femmesh_obj.FemMesh = fem_mesh
|
||||
|
||||
doc.recompute()
|
||||
return doc
|
||||
|
||||
|
||||
"""
|
||||
from femexamples.contact_shell_shell import setup
|
||||
setup()
|
||||
|
||||
"""
|
||||
@@ -148,6 +148,21 @@ def run_ccx_cantileverprescribeddisplacement(solver=None, base_name=None):
|
||||
return doc
|
||||
|
||||
|
||||
def run_contact_shell_shell(solver=None, base_name=None):
|
||||
|
||||
from .contact_shell_shell import setup
|
||||
doc = setup()
|
||||
|
||||
if base_name is None:
|
||||
base_name = "Contact_Shell_Shell"
|
||||
if solver is not None:
|
||||
base_name += "_" + solver
|
||||
run_analysis(doc, base_name)
|
||||
doc.recompute()
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def run_material_multiple_twoboxes(solver=None, base_name=None):
|
||||
|
||||
from .material_multiple_twoboxes import setup
|
||||
@@ -180,7 +195,7 @@ def run_material_nl_platewithhole(solver=None, base_name=None):
|
||||
|
||||
def run_rcwall2d(solver=None, base_name=None):
|
||||
|
||||
from .rc_wall_2d import setup as setup
|
||||
from .rc_wall_2d import setup
|
||||
doc = setup()
|
||||
|
||||
if base_name is None:
|
||||
@@ -246,6 +261,7 @@ doc = run_boxanalysisfrequency()
|
||||
doc = run_ccx_cantileverfaceload()
|
||||
doc = run_ccx_cantilevernodeload()
|
||||
doc = run_ccx_cantileverprescribeddisplacement()
|
||||
doc = run_contact_shell_shell()
|
||||
doc = run_material_nl_platewithhole()
|
||||
doc = run_material_multiple_twoboxes()
|
||||
doc = run_rcwall2d()
|
||||
|
||||
@@ -157,7 +157,7 @@ def setup(doc=None, solvertype="ccxtools"):
|
||||
|
||||
|
||||
"""
|
||||
from femexamples import material_multiple_twoboxes as twoboxes
|
||||
twoboxes.setup()
|
||||
from femexamples.material_multiple_twoboxes import setup
|
||||
setup()
|
||||
|
||||
"""
|
||||
|
||||
@@ -157,7 +157,7 @@ def setup(doc=None, solvertype="ccxtools"):
|
||||
|
||||
|
||||
"""
|
||||
from femexamples import material_nl_platewithhole as nlmat
|
||||
nlmat.setup()
|
||||
from femexamples.material_nl_platewithhole import setup
|
||||
setup()
|
||||
|
||||
"""
|
||||
|
||||
22986
src/Mod/Fem/femexamples/meshes/mesh_contact_tube_tube_tria3.py
Normal file
22986
src/Mod/Fem/femexamples/meshes/mesh_contact_tube_tube_tria3.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -159,7 +159,7 @@ def setup(doc=None, solvertype="ccxtools"):
|
||||
|
||||
|
||||
"""
|
||||
from femexamples import rc_wall_2d as rc
|
||||
rc.setup()
|
||||
from femexamples.rc_wall_2d import setup
|
||||
setup()
|
||||
|
||||
"""
|
||||
|
||||
@@ -250,7 +250,7 @@ def setup(doc=None, solvertype="ccxtools"):
|
||||
|
||||
|
||||
"""
|
||||
from femexamples import thermomech_flow1d as flow
|
||||
flow.setup()
|
||||
from femexamples.thermomech_flow1d import setup
|
||||
setup()
|
||||
|
||||
"""
|
||||
|
||||
@@ -143,7 +143,7 @@ def setup(doc=None, solvertype="ccxtools"):
|
||||
|
||||
|
||||
"""
|
||||
from femexamples import thermomech_spine as spine
|
||||
spine.setup()
|
||||
from femexamples.thermomech_spine import setup
|
||||
setup()
|
||||
|
||||
"""
|
||||
|
||||
@@ -92,7 +92,7 @@ def femmesh_2_mesh(myFemMesh, myResults=None):
|
||||
# This code generates a dict and a faceCode for each face of all elements
|
||||
# All faceCodes are than sorted.
|
||||
|
||||
start_time = time.clock()
|
||||
start_time = time.process_time()
|
||||
faceCodeList = []
|
||||
faceCodeDict = {}
|
||||
|
||||
@@ -196,7 +196,7 @@ def femmesh_2_mesh(myFemMesh, myResults=None):
|
||||
output_mesh.extend(triangle)
|
||||
# print("my 2. triangle: ", triangle)
|
||||
|
||||
end_time = time.clock()
|
||||
end_time = time.process_time()
|
||||
FreeCAD.Console.PrintMessage(
|
||||
"Mesh by surface search method: {}\n".format(end_time - start_time)
|
||||
)
|
||||
|
||||
@@ -97,7 +97,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
)
|
||||
|
||||
def write_calculix_input_file(self):
|
||||
timestart = time.clock()
|
||||
timestart = time.process_time()
|
||||
FreeCAD.Console.PrintMessage("Start writing CalculiX input file\n")
|
||||
FreeCAD.Console.PrintMessage("Write ccx input file to: {}\n".format(self.file_name))
|
||||
FreeCAD.Console.PrintLog(
|
||||
@@ -115,7 +115,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
self.write_calculix_one_input_file()
|
||||
writing_time_string = (
|
||||
"Writing time CalculiX input file: {} seconds"
|
||||
.format(round((time.clock() - timestart), 2))
|
||||
.format(round((time.process_time() - timestart), 2))
|
||||
)
|
||||
if self.femelement_count_test is True:
|
||||
FreeCAD.Console.PrintMessage(writing_time_string + " \n\n")
|
||||
@@ -608,9 +608,32 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
|
||||
else:
|
||||
name = "IND" + str(obj)
|
||||
f.write("*SURFACE, NAME =" + name + "\n")
|
||||
|
||||
v = self.mesh_object.FemMesh.getccxVolumesByFace(ref_shape)
|
||||
for i in v:
|
||||
f.write("{},S{}\n".format(i[0], i[1]))
|
||||
if len(v) > 0:
|
||||
# volume elements found
|
||||
FreeCAD.Console.PrintLog(
|
||||
"{}, surface {}, {} touching volume elements found\n"
|
||||
.format(contact_obj.Label, name, len(v))
|
||||
)
|
||||
for i in v:
|
||||
f.write("{},S{}\n".format(i[0], i[1]))
|
||||
else:
|
||||
# try shell elements
|
||||
v = self.mesh_object.FemMesh.getFacesByFace(ref_shape)
|
||||
if len(v) > 0:
|
||||
FreeCAD.Console.PrintLog(
|
||||
"{}, surface {}, {} touching shell elements found\n"
|
||||
.format(contact_obj.Label, name, len(v))
|
||||
)
|
||||
for i in v:
|
||||
f.write("{},S2\n".format(i))
|
||||
else:
|
||||
FreeCAD.Console.PrintError(
|
||||
"{}, surface {}, Error: "
|
||||
"Neither volume nor shell elements found!\n"
|
||||
.format(contact_obj.Label, name)
|
||||
)
|
||||
|
||||
def write_node_sets_constraints_transform(self, f):
|
||||
# get nodes
|
||||
|
||||
@@ -92,7 +92,7 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter):
|
||||
)
|
||||
|
||||
def write_z88_input(self):
|
||||
timestart = time.clock()
|
||||
timestart = time.process_time()
|
||||
if not self.femnodes_mesh:
|
||||
self.femnodes_mesh = self.femmesh.Nodes
|
||||
if not self.femelement_table:
|
||||
@@ -109,7 +109,7 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter):
|
||||
self.write_z88_solver_parameter()
|
||||
writing_time_string = (
|
||||
"Writing time input file: {} seconds"
|
||||
.format(round((time.clock() - timestart), 2))
|
||||
.format(round((time.process_time() - timestart), 2))
|
||||
)
|
||||
FreeCAD.Console.PrintMessage(writing_time_string + " \n\n")
|
||||
return self.dir_name
|
||||
|
||||
@@ -68,412 +68,234 @@ class TestCcxTools(unittest.TestCase):
|
||||
))
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_1_static_analysis(
|
||||
def test_freq_analysis(
|
||||
self
|
||||
):
|
||||
fcc_print("\n--------------- Start of FEM ccxtools static analysis test ---------------")
|
||||
|
||||
# set up the static analysis example
|
||||
from femexamples import boxanalysis as box
|
||||
box.setup_static(self.active_doc, "ccxtools")
|
||||
|
||||
analysis = self.active_doc.Analysis
|
||||
solver_object = self.active_doc.CalculiXccxTools
|
||||
fcc_print("Analysis {}".format(type(analysis)))
|
||||
fcc_print("Analysis {}".format(analysis.TypeId))
|
||||
|
||||
static_analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_static"
|
||||
)
|
||||
fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True)
|
||||
fea.update_objects()
|
||||
fcc_print("fea Analysis {}".format(type(fea.analysis)))
|
||||
fcc_print("fea Analysis {}".format(fea.analysis.TypeId))
|
||||
|
||||
fcc_print("Setting up working directory {}".format(static_analysis_dir))
|
||||
fea.setup_working_dir(static_analysis_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == static_analysis_dir else False,
|
||||
"Setting working directory {} failed".format(static_analysis_dir)
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM inp file prerequisites for static analysis...")
|
||||
error = fea.check_prerequisites()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"ccxtools check_prerequisites returned error message: {}".format(error)
|
||||
)
|
||||
|
||||
static_base_name = "cube_static"
|
||||
inpfile_given = join(self.test_file_dir, (static_base_name + ".inp"))
|
||||
inpfile_totest = join(static_analysis_dir, (self.mesh_name + ".inp"))
|
||||
fcc_print("Checking FEM inp file write...")
|
||||
fcc_print("Writing {} for static analysis".format(inpfile_totest))
|
||||
error = fea.write_inp_file()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"Writing failed"
|
||||
)
|
||||
|
||||
fcc_print("Comparing {} to {}".format(inpfile_given, inpfile_totest))
|
||||
ret = testtools.compare_inp_files(inpfile_given, inpfile_totest)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"ccxtools write_inp_file test failed.\n{}".format(ret)
|
||||
)
|
||||
|
||||
fcc_print(
|
||||
"Setting up working directory to {} in order to read simulated calculations"
|
||||
.format(self.test_file_dir)
|
||||
)
|
||||
fea.setup_working_dir(self.test_file_dir)
|
||||
fcc_print(fea.working_dir)
|
||||
fcc_print(self.test_file_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == self.test_file_dir else False,
|
||||
"Setting working directory {} failed".format(self.test_file_dir)
|
||||
)
|
||||
|
||||
fcc_print("Setting base name to read test {}.frd file...".format("cube_static"))
|
||||
fea.set_base_name(static_base_name)
|
||||
self.assertTrue(
|
||||
True if fea.base_name == static_base_name else False,
|
||||
"Setting base name to {} failed".format(static_base_name)
|
||||
)
|
||||
|
||||
fcc_print("Setting inp file name to read test {}.frd file...".format("cube_static"))
|
||||
fea.set_inp_file_name()
|
||||
self.assertTrue(
|
||||
True if fea.inp_file_name == inpfile_given else False,
|
||||
"Setting inp file name to {} failed".format(inpfile_given)
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM frd file read from static analysis...")
|
||||
fea.load_results()
|
||||
self.assertTrue(
|
||||
fea.results_present,
|
||||
"Cannot read results from {}.frd frd file".format(fea.base_name)
|
||||
)
|
||||
|
||||
fcc_print("Reading stats from result object for static analysis...")
|
||||
static_expected_values = join(self.test_file_dir, "cube_static_expected_values")
|
||||
ret = testtools.compare_stats(
|
||||
fea,
|
||||
static_expected_values,
|
||||
"CCX_Results"
|
||||
)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"Invalid results read from .frd file"
|
||||
)
|
||||
|
||||
static_save_fc_file = static_analysis_dir + static_base_name + ".FCStd"
|
||||
fcc_print("Save FreeCAD file for static analysis to {}...".format(static_save_fc_file))
|
||||
self.active_doc.saveAs(static_save_fc_file)
|
||||
|
||||
fcc_print("--------------- End of FEM ccxtools static analysis test -------------------")
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_2_static_multiple_material(
|
||||
self
|
||||
):
|
||||
fcc_print("\n--------------- Start of FEM ccxtools multiple material test -------------")
|
||||
|
||||
# set up the simple multimat example
|
||||
from femexamples import material_multiple_twoboxes
|
||||
material_multiple_twoboxes.setup(self.active_doc, "ccxtools")
|
||||
|
||||
analysis = self.active_doc.Analysis
|
||||
solver_object = self.active_doc.CalculiXccxTools
|
||||
|
||||
static_multiplemat_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_multimat/"
|
||||
)
|
||||
fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True)
|
||||
fea.update_objects()
|
||||
fea.setup_working_dir(static_multiplemat_dir)
|
||||
|
||||
fcc_print("Checking FEM inp file prerequisites for ccxtools multimat analysis...")
|
||||
error = fea.check_prerequisites()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"ccxtools check_prerequisites returned error message: {}".format(error)
|
||||
)
|
||||
|
||||
static_base_name = "multimat"
|
||||
inpfile_given = join(self.test_file_dir, (static_base_name + ".inp"))
|
||||
inpfile_totest = join(static_multiplemat_dir, (self.mesh_name + ".inp"))
|
||||
fcc_print("Checking FEM inp file write...")
|
||||
fcc_print("Writing {} for static multiple material".format(inpfile_totest))
|
||||
error = fea.write_inp_file()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"Writing failed"
|
||||
)
|
||||
|
||||
fcc_print("Comparing {} to {}".format(inpfile_given, inpfile_totest))
|
||||
ret = testtools.compare_inp_files(inpfile_given, inpfile_totest)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"ccxtools write_inp_file test failed.\n{}".format(ret)
|
||||
)
|
||||
|
||||
static_save_fc_file = static_multiplemat_dir + static_base_name + ".FCStd"
|
||||
fcc_print("Save FreeCAD file for static analysis to {}...".format(static_save_fc_file))
|
||||
self.active_doc.saveAs(static_save_fc_file)
|
||||
|
||||
fcc_print("--------------- End of FEM ccxtools multiple material test -----------------")
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_3_freq_analysis(
|
||||
self
|
||||
):
|
||||
fcc_print("\n--------------- Start of FEM ccxtools frequency analysis test ------------")
|
||||
|
||||
# set up the static analysis example
|
||||
from femexamples import boxanalysis as box
|
||||
box.setup_frequency(self.active_doc, "ccxtools")
|
||||
|
||||
analysis = self.active_doc.Analysis
|
||||
solver_object = self.active_doc.CalculiXccxTools
|
||||
|
||||
frequency_analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
# set up
|
||||
from femexamples.boxanalysis import setup_frequency as setup
|
||||
setup(self.active_doc, "ccxtools")
|
||||
test_name = "frequency"
|
||||
base_name = "cube_frequency"
|
||||
res_obj_name = "CCX_Mode1_Results"
|
||||
analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_frequency"
|
||||
)
|
||||
fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True)
|
||||
fea.update_objects()
|
||||
|
||||
fcc_print("Setting up working directory {}".format(frequency_analysis_dir))
|
||||
fea.setup_working_dir(frequency_analysis_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == frequency_analysis_dir else False,
|
||||
"Setting working directory {} failed".format(frequency_analysis_dir)
|
||||
# test input file writing
|
||||
fea = self.input_file_writing_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
test_end=True,
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM inp file prerequisites for frequency analysis...")
|
||||
error = fea.check_prerequisites()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"ccxtools check_prerequisites returned error message: {}".format(error)
|
||||
# test result reading
|
||||
self.result_reading_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
fea=fea,
|
||||
res_obj_name=res_obj_name,
|
||||
)
|
||||
|
||||
frequency_base_name = "cube_frequency"
|
||||
inpfile_given = join(self.test_file_dir, (frequency_base_name + ".inp"))
|
||||
inpfile_totest = join(frequency_analysis_dir, (self.mesh_name + ".inp"))
|
||||
fcc_print("Checking FEM inp file write...")
|
||||
fcc_print("Writing {} for frequency analysis".format(inpfile_totest))
|
||||
error = fea.write_inp_file()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"Writing failed"
|
||||
)
|
||||
|
||||
fcc_print("Comparing {} to {}".format(inpfile_given, inpfile_totest))
|
||||
ret = testtools.compare_inp_files(inpfile_given, inpfile_totest)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"ccxtools write_inp_file test failed.\n{}".format(ret)
|
||||
)
|
||||
|
||||
fcc_print(
|
||||
"Setting up working directory to {} in order to read simulated calculations".
|
||||
format(self.test_file_dir)
|
||||
)
|
||||
fea.setup_working_dir(self.test_file_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == self.test_file_dir else False,
|
||||
"Setting working directory {} failed".format(self.test_file_dir)
|
||||
)
|
||||
|
||||
fcc_print("Setting base name to read test {}.frd file...".format(frequency_base_name))
|
||||
fea.set_base_name(frequency_base_name)
|
||||
self.assertTrue(
|
||||
True if fea.base_name == frequency_base_name else False,
|
||||
"Setting base name to {} failed".format(frequency_base_name)
|
||||
)
|
||||
|
||||
fcc_print("Setting inp file name to read test {}.frd file...".format("cube_frequency"))
|
||||
fea.set_inp_file_name()
|
||||
self.assertTrue(
|
||||
True if fea.inp_file_name == inpfile_given else False,
|
||||
"Setting inp file name to {} failed".format(inpfile_given)
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM frd file read from frequency analysis...")
|
||||
fea.load_results()
|
||||
self.assertTrue(
|
||||
fea.results_present,
|
||||
"Cannot read results from {}.frd frd file".format(fea.base_name)
|
||||
)
|
||||
|
||||
fcc_print("Reading stats from result object for frequency analysis...")
|
||||
frequency_expected_values = join(self.test_file_dir, "cube_frequency_expected_values")
|
||||
ret = testtools.compare_stats(
|
||||
fea,
|
||||
frequency_expected_values,
|
||||
"CCX_Mode1_Results"
|
||||
)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"Invalid results read from .frd file"
|
||||
)
|
||||
|
||||
frequency_save_fc_file = frequency_analysis_dir + frequency_base_name + ".FCStd"
|
||||
fcc_print(
|
||||
"Save FreeCAD file for frequency analysis to {}..."
|
||||
.format(frequency_save_fc_file)
|
||||
)
|
||||
self.active_doc.saveAs(frequency_save_fc_file)
|
||||
|
||||
fcc_print("--------------- End of FEM ccxtools frequency analysis test ----------------")
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_4_thermomech_analysis(
|
||||
def test_static_analysis(
|
||||
self
|
||||
):
|
||||
|
||||
fcc_print("\n--------------- Start of FEM ccxtools thermomechanical analysis test -----")
|
||||
|
||||
# set up the thermomech example
|
||||
from femexamples.thermomech_spine import setup as thermomech
|
||||
thermomech(self.active_doc, "ccxtools")
|
||||
|
||||
analysis = self.active_doc.Analysis
|
||||
|
||||
thermomech_analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
# set up
|
||||
from femexamples.boxanalysis import setup_static as setup
|
||||
setup(self.active_doc, "ccxtools")
|
||||
test_name = "ccxtools static"
|
||||
base_name = "cube_static"
|
||||
res_obj_name = "CCX_Results"
|
||||
analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_thermomech"
|
||||
)
|
||||
fea = ccxtools.FemToolsCcx(analysis, test_mode=True)
|
||||
fea.update_objects()
|
||||
|
||||
fcc_print("Setting up working directory {}".format(thermomech_analysis_dir))
|
||||
fea.setup_working_dir(thermomech_analysis_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == thermomech_analysis_dir else False,
|
||||
"Setting working directory {} failed".format(thermomech_analysis_dir)
|
||||
"FEM_ccx_static"
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM inp file prerequisites for thermo-mechanical analysis...")
|
||||
error = fea.check_prerequisites()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"ccxtools check_prerequisites returned error message: {}".format(error)
|
||||
# test input file writing
|
||||
fea = self.input_file_writing_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
test_end=True,
|
||||
)
|
||||
|
||||
thermomech_base_name = "spine_thermomech"
|
||||
inpfile_given = join(self.test_file_dir, (thermomech_base_name + ".inp"))
|
||||
inpfile_totest = join(thermomech_analysis_dir, (self.mesh_name + ".inp"))
|
||||
fcc_print("Checking FEM inp file write...")
|
||||
fcc_print("Writing {} for thermomech analysis".format(inpfile_totest))
|
||||
error = fea.write_inp_file()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"Writing failed"
|
||||
# test result reading
|
||||
self.result_reading_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
fea=fea,
|
||||
res_obj_name=res_obj_name,
|
||||
)
|
||||
|
||||
fcc_print("Comparing {} to {}".format(inpfile_given, inpfile_totest))
|
||||
ret = testtools.compare_inp_files(inpfile_given, inpfile_totest)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"ccxtools write_inp_file test failed.\n{}".format(ret)
|
||||
)
|
||||
|
||||
fcc_print(
|
||||
"Setting up working directory to {} in order to read simulated calculations"
|
||||
.format(self.test_file_dir)
|
||||
)
|
||||
fea.setup_working_dir(self.test_file_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == self.test_file_dir else False,
|
||||
"Setting working directory {} failed".format(self.test_file_dir)
|
||||
)
|
||||
|
||||
fcc_print("Setting base name to read test {}.frd file...".format("spine_thermomech"))
|
||||
fea.set_base_name(thermomech_base_name)
|
||||
self.assertTrue(
|
||||
True if fea.base_name == thermomech_base_name else False,
|
||||
"Setting base name to {} failed".format(thermomech_base_name)
|
||||
)
|
||||
|
||||
fcc_print("Setting inp file name to read test {}.frd file...".format("spine_thermomech"))
|
||||
fea.set_inp_file_name()
|
||||
self.assertTrue(
|
||||
True if fea.inp_file_name == inpfile_given else False,
|
||||
"Setting inp file name to {} failed".format(inpfile_given)
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM frd file read from thermomech analysis...")
|
||||
fea.load_results()
|
||||
self.assertTrue(
|
||||
fea.results_present,
|
||||
"Cannot read results from {}.frd frd file".format(fea.base_name)
|
||||
)
|
||||
|
||||
fcc_print("Reading stats from result object for thermomech analysis...")
|
||||
thermomech_expected_values = join(
|
||||
self.test_file_dir,
|
||||
"spine_thermomech_expected_values"
|
||||
)
|
||||
ret = testtools.compare_stats(
|
||||
fea,
|
||||
thermomech_expected_values,
|
||||
"CCX_Results"
|
||||
)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"Invalid results read from .frd file"
|
||||
)
|
||||
|
||||
thermomech_save_fc_file = thermomech_analysis_dir + thermomech_base_name + ".FCStd"
|
||||
fcc_print(
|
||||
"Save FreeCAD file for thermomech analysis to {}..."
|
||||
.format(thermomech_save_fc_file)
|
||||
)
|
||||
self.active_doc.saveAs(thermomech_save_fc_file)
|
||||
|
||||
fcc_print("--------------- End of FEM ccxtools thermomechanical analysis test ---------")
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_5_Flow1D_thermomech_analysis(
|
||||
def test_static_contact_shell_shell(
|
||||
self
|
||||
):
|
||||
fcc_print("\n--------------- Start of FEM ccxtools Flow1D analysis test ---------------")
|
||||
# set up
|
||||
from femexamples.contact_shell_shell import setup
|
||||
setup(self.active_doc, "ccxtools")
|
||||
test_name = "contact shell shell"
|
||||
base_name = "contact_shell_shell"
|
||||
analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_contact_shell_shell",
|
||||
)
|
||||
|
||||
# set up the thermomech flow1d example
|
||||
from femexamples.thermomech_flow1d import setup as flow1d
|
||||
flow1d(self.active_doc, "ccxtools")
|
||||
analysis = self.active_doc.Analysis
|
||||
# test input file writing
|
||||
self.input_file_writing_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
)
|
||||
|
||||
Flow1D_thermomech_analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
# ********************************************************************************************
|
||||
def test_static_material_multiple(
|
||||
self
|
||||
):
|
||||
# set up
|
||||
from femexamples.material_multiple_twoboxes import setup
|
||||
setup(self.active_doc, "ccxtools")
|
||||
test_name = "multiple material"
|
||||
base_name = "mat_multiple"
|
||||
analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_multimat"
|
||||
)
|
||||
|
||||
# test input file writing
|
||||
self.input_file_writing_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
)
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_static_material_nonlinar(
|
||||
self
|
||||
):
|
||||
# set up
|
||||
from femexamples.material_nl_platewithhole import setup
|
||||
setup(self.active_doc, "ccxtools")
|
||||
test_name = "nonlinear material"
|
||||
base_name = "mat_nonlinear"
|
||||
analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_matnonlinear"
|
||||
)
|
||||
|
||||
# test input file writing
|
||||
self.input_file_writing_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
)
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_thermomech_flow1D_analysis(
|
||||
self
|
||||
):
|
||||
# set up
|
||||
from femexamples.thermomech_flow1d import setup
|
||||
setup(self.active_doc, "ccxtools")
|
||||
test_name = "Flow1D"
|
||||
base_name = "Flow1D_thermomech"
|
||||
res_obj_name = "CCX_Time1_0_Results"
|
||||
analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_Flow1D_thermomech"
|
||||
)
|
||||
fea = ccxtools.FemToolsCcx(analysis, test_mode=True)
|
||||
fea.update_objects()
|
||||
|
||||
fcc_print("Setting up working directory {}".format(Flow1D_thermomech_analysis_dir))
|
||||
fea.setup_working_dir(Flow1D_thermomech_analysis_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == Flow1D_thermomech_analysis_dir else False,
|
||||
"Setting working directory {} failed".format(Flow1D_thermomech_analysis_dir)
|
||||
# test input file writing
|
||||
fea = self.input_file_writing_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
test_end=True,
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM inp file prerequisites for thermo-mechanical analysis...")
|
||||
# test result reading
|
||||
self.result_reading_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
fea=fea,
|
||||
res_obj_name=res_obj_name,
|
||||
)
|
||||
|
||||
# ********************************************************************************************
|
||||
def test_thermomech_spine_analysis(
|
||||
self
|
||||
):
|
||||
# set up
|
||||
from femexamples.thermomech_spine import setup
|
||||
setup(self.active_doc, "ccxtools")
|
||||
test_name = "thermomechanical"
|
||||
base_name = "spine_thermomech"
|
||||
res_obj_name = "CCX_Results"
|
||||
analysis_dir = testtools.get_unit_test_tmp_dir(
|
||||
self.temp_dir,
|
||||
"FEM_ccx_thermomech"
|
||||
)
|
||||
|
||||
# test input file writing
|
||||
fea = self.input_file_writing_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
test_end=True,
|
||||
)
|
||||
|
||||
# test result reading
|
||||
self.result_reading_test(
|
||||
test_name=test_name,
|
||||
base_name=base_name,
|
||||
analysis_dir=analysis_dir,
|
||||
fea=fea,
|
||||
res_obj_name=res_obj_name,
|
||||
)
|
||||
|
||||
# ********************************************************************************************
|
||||
def input_file_writing_test(
|
||||
self,
|
||||
test_name,
|
||||
base_name,
|
||||
analysis_dir,
|
||||
test_end=False,
|
||||
):
|
||||
fcc_print(
|
||||
"\n--------------- "
|
||||
"Start of FEM ccxtools {} test"
|
||||
"---------------"
|
||||
.format(test_name)
|
||||
)
|
||||
|
||||
analysis = self.active_doc.Analysis
|
||||
solver_object = self.active_doc.CalculiXccxTools
|
||||
fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True)
|
||||
fea.update_objects()
|
||||
|
||||
fcc_print("Setting up working directory {}".format(analysis_dir))
|
||||
fea.setup_working_dir(analysis_dir)
|
||||
self.assertTrue(
|
||||
True if fea.working_dir == analysis_dir else False,
|
||||
"Setting working directory {} failed".format(analysis_dir)
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM inp file prerequisites for {} ...".format(test_name))
|
||||
error = fea.check_prerequisites()
|
||||
self.assertFalse(
|
||||
error,
|
||||
"ccxtools check_prerequisites returned error message: {}".format(error)
|
||||
)
|
||||
|
||||
Flow1D_thermomech_base_name = "Flow1D_thermomech"
|
||||
inpfile_given = join(self.test_file_dir, (Flow1D_thermomech_base_name + ".inp"))
|
||||
inpfile_totest = join(Flow1D_thermomech_analysis_dir, (self.mesh_name + ".inp"))
|
||||
inpfile_given = join(self.test_file_dir, (base_name + ".inp"))
|
||||
inpfile_totest = join(analysis_dir, (self.mesh_name + ".inp"))
|
||||
fcc_print("Checking FEM inp file write...")
|
||||
fcc_print("Writing {} for thermomech analysis".format(inpfile_totest))
|
||||
fcc_print("Writing {} for {}".format(inpfile_totest, test_name))
|
||||
error = fea.write_inp_file()
|
||||
self.assertFalse(
|
||||
error,
|
||||
@@ -487,6 +309,35 @@ class TestCcxTools(unittest.TestCase):
|
||||
"ccxtools write_inp_file test failed.\n{}".format(ret)
|
||||
)
|
||||
|
||||
if test_end is True:
|
||||
# do not save and print End of tests
|
||||
return fea
|
||||
|
||||
save_fc_file = analysis_dir + base_name + ".FCStd"
|
||||
fcc_print(
|
||||
"Save FreeCAD file for {} to {}..."
|
||||
.format(test_name, save_fc_file)
|
||||
)
|
||||
self.active_doc.saveAs(save_fc_file)
|
||||
|
||||
fcc_print(
|
||||
"\n--------------- "
|
||||
"End of FEM ccxtools {}"
|
||||
"---------------"
|
||||
.format(test_name)
|
||||
)
|
||||
|
||||
# ********************************************************************************************
|
||||
def result_reading_test(
|
||||
self,
|
||||
test_name,
|
||||
base_name,
|
||||
analysis_dir,
|
||||
fea,
|
||||
res_obj_name,
|
||||
):
|
||||
inpfile_given = join(self.test_file_dir, (base_name + ".inp"))
|
||||
|
||||
fcc_print(
|
||||
"Setting up working directory to {} in order to read simulated calculations"
|
||||
.format(self.test_file_dir)
|
||||
@@ -497,53 +348,59 @@ class TestCcxTools(unittest.TestCase):
|
||||
"Setting working directory {} failed".format(self.test_file_dir)
|
||||
)
|
||||
|
||||
fcc_print("Setting base name to read test {}.frd file...".format("Flow1D_thermomech"))
|
||||
fea.set_base_name(Flow1D_thermomech_base_name)
|
||||
fcc_print(
|
||||
"Setting base name to read test {}.frd file..."
|
||||
.format(base_name)
|
||||
)
|
||||
fea.set_base_name(base_name)
|
||||
self.assertTrue(
|
||||
True if fea.base_name == Flow1D_thermomech_base_name else False,
|
||||
"Setting base name to {} failed".format(Flow1D_thermomech_base_name)
|
||||
True if fea.base_name == base_name else False,
|
||||
"Setting base name to {} failed".format(base_name)
|
||||
)
|
||||
|
||||
fcc_print("Setting inp file name to read test {}.frd file...".format("Flow1D_thermomech"))
|
||||
fcc_print(
|
||||
"Setting inp file name to read test {}.frd file..."
|
||||
.format(base_name)
|
||||
)
|
||||
fea.set_inp_file_name()
|
||||
self.assertTrue(
|
||||
True if fea.inp_file_name == inpfile_given else False,
|
||||
"Setting inp file name to {} failed".format(inpfile_given)
|
||||
)
|
||||
|
||||
fcc_print("Checking FEM frd file read from Flow1D thermomech analysis...")
|
||||
fcc_print("Checking FEM frd file read from {}...".format(test_name))
|
||||
fea.load_results()
|
||||
self.assertTrue(
|
||||
fea.results_present,
|
||||
"Cannot read results from {}.frd frd file".format(fea.base_name)
|
||||
)
|
||||
|
||||
fcc_print("Reading stats from result object for Flow1D thermomech analysis...")
|
||||
Flow1D_thermomech_expected_values = join(
|
||||
fcc_print("Reading stats from result object for {}...".format(test_name))
|
||||
expected_values = join(
|
||||
self.test_file_dir,
|
||||
"Flow1D_thermomech_expected_values"
|
||||
base_name + "_expected_values"
|
||||
)
|
||||
ret = testtools.compare_stats(
|
||||
fea,
|
||||
Flow1D_thermomech_expected_values,
|
||||
"CCX_Time1_0_Results"
|
||||
expected_values,
|
||||
res_obj_name
|
||||
)
|
||||
self.assertFalse(
|
||||
ret,
|
||||
"Invalid results read from .frd file"
|
||||
)
|
||||
|
||||
Flow1D_thermomech_save_fc_file = join(
|
||||
Flow1D_thermomech_analysis_dir,
|
||||
(Flow1D_thermomech_base_name + ".FCStd")
|
||||
save_fc_file = join(
|
||||
analysis_dir,
|
||||
(base_name + ".FCStd")
|
||||
)
|
||||
fcc_print(
|
||||
"Save FreeCAD file for thermomech analysis to {}..."
|
||||
.format(Flow1D_thermomech_save_fc_file)
|
||||
"Save FreeCAD file for {} to {}..."
|
||||
.format(test_name, save_fc_file)
|
||||
)
|
||||
self.active_doc.saveAs(Flow1D_thermomech_save_fc_file)
|
||||
self.active_doc.saveAs(save_fc_file)
|
||||
|
||||
fcc_print("--------------- End of FEM ccxtools Flow1D analysis test -------------------")
|
||||
fcc_print("--------------- End of {} -------------------".format(test_name))
|
||||
|
||||
# ********************************************************************************************
|
||||
def tearDown(
|
||||
|
||||
BIN
src/Mod/Fem/femtest/data/ccx/contact_shell_shell.FCStd
Normal file
BIN
src/Mod/Fem/femtest/data/ccx/contact_shell_shell.FCStd
Normal file
Binary file not shown.
38442
src/Mod/Fem/femtest/data/ccx/contact_shell_shell.inp
Normal file
38442
src/Mod/Fem/femtest/data/ccx/contact_shell_shell.inp
Normal file
File diff suppressed because it is too large
Load Diff
20145
src/Mod/Fem/femtest/data/ccx/mat_nonlinear.inp
Normal file
20145
src/Mod/Fem/femtest/data/ccx/mat_nonlinear.inp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -163,7 +163,6 @@ private:
|
||||
Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
|
||||
Handle(TDocStd_Document) hDoc;
|
||||
hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
|
||||
ImportOCAFExt ocaf(hDoc, pcDoc, file.fileNamePure());
|
||||
|
||||
if (file.hasExtension("stp") || file.hasExtension("step")) {
|
||||
try {
|
||||
@@ -230,15 +229,19 @@ private:
|
||||
}
|
||||
|
||||
#if 1
|
||||
if(merge!=Py_None)
|
||||
ImportOCAFExt ocaf(hDoc, pcDoc, file.fileNamePure());
|
||||
if (merge != Py_None)
|
||||
ocaf.setMerge(PyObject_IsTrue(merge));
|
||||
if(importHidden!=Py_None)
|
||||
if (importHidden != Py_None)
|
||||
ocaf.setImportHiddenObject(PyObject_IsTrue(importHidden));
|
||||
if(useLinkGroup!=Py_None)
|
||||
if (useLinkGroup != Py_None)
|
||||
ocaf.setUseLinkGroup(PyObject_IsTrue(useLinkGroup));
|
||||
if(mode>=0)
|
||||
if (mode >= 0)
|
||||
ocaf.setMode(mode);
|
||||
ocaf.loadShapes();
|
||||
#elif 1
|
||||
Import::ImportOCAFCmd ocaf(hDoc, pcDoc, file.fileNamePure());
|
||||
ocaf.loadShapes();
|
||||
#else
|
||||
Import::ImportXCAF xcaf(hDoc, pcDoc, file.fileNamePure());
|
||||
xcaf.loadShapes();
|
||||
@@ -246,7 +249,7 @@ private:
|
||||
#endif
|
||||
hApp->Close(hDoc);
|
||||
|
||||
if (!ocaf.partColors.size()) {
|
||||
if (!ocaf.partColors.empty()) {
|
||||
Py::List list;
|
||||
for (auto &it : ocaf.partColors) {
|
||||
Py::Tuple tuple(2);
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
#***************************************************************************/
|
||||
|
||||
|
||||
# Registered in Part's Init.py file
|
||||
FreeCAD.changeImportModule("STEP with colors (*.step *.stp)","Import","ImportGui")
|
||||
FreeCAD.changeExportModule("STEP with colors (*.step *.stp)","Import","ImportGui")
|
||||
|
||||
"""
|
||||
class ImportWorkbench ( Workbench ):
|
||||
"Import workbench object"
|
||||
|
||||
@@ -32,7 +32,7 @@ FreeCAD.addImportType("BREP format (*.brep *.brp)","Part")
|
||||
FreeCAD.addExportType("BREP format (*.brep *.brp)","Part")
|
||||
FreeCAD.addImportType("IGES format (*.iges *.igs)","Part")
|
||||
FreeCAD.addExportType("IGES format (*.iges *.igs)","Part")
|
||||
FreeCAD.addImportType("STEP with colors (*.step *.stp)","ImportGui")
|
||||
FreeCAD.addExportType("STEP with colors (*.step *.stp)","ImportGui")
|
||||
FreeCAD.addImportType("STEP with colors (*.step *.stp)","Import")
|
||||
FreeCAD.addExportType("STEP with colors (*.step *.stp)","Import")
|
||||
|
||||
FreeCAD.__unit_test__ += [ "TestPartApp" ]
|
||||
|
||||
@@ -60,7 +60,7 @@ Command::~Command()
|
||||
|
||||
// New methods
|
||||
|
||||
Placement Command::getPlacement (void) const
|
||||
Placement Command::getPlacement (const Base::Vector3d pos) const
|
||||
{
|
||||
static const std::string x = "X";
|
||||
static const std::string y = "Y";
|
||||
@@ -68,7 +68,7 @@ Placement Command::getPlacement (void) const
|
||||
static const std::string a = "A";
|
||||
static const std::string b = "B";
|
||||
static const std::string c = "C";
|
||||
Vector3d vec(getParam(x),getParam(y),getParam(z));
|
||||
Vector3d vec(getParam(x, pos.x),getParam(y, pos.y),getParam(z, pos.z));
|
||||
Rotation rot;
|
||||
rot.setYawPitchRoll(getParam(a),getParam(b),getParam(c));
|
||||
Placement plac(vec,rot);
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Path
|
||||
virtual void Restore(Base::XMLReader &/*reader*/);
|
||||
|
||||
// specific methods
|
||||
Base::Placement getPlacement (void) const; // returns a placement from the x,y,z,a,b,c parameters
|
||||
Base::Placement getPlacement (const Base::Vector3d pos = Base::Vector3d()) const; // returns a placement from the x,y,z,a,b,c parameters
|
||||
Base::Vector3d getCenter (void) const; // returns a 3d vector from the i,j,k parameters
|
||||
void setCenter(const Base::Vector3d&, bool clockwise=true); // sets the center coordinates and the command name
|
||||
std::string toGCode (int precision=6, bool padzero=true) const; // returns a GCode string representation of the command
|
||||
@@ -61,9 +61,9 @@ namespace Path
|
||||
void scaleBy(double factor); // scales the receiver - use for imperial/metric conversions
|
||||
|
||||
// this assumes the name is upper case
|
||||
inline double getParam(const std::string &name) const {
|
||||
inline double getParam(const std::string &name, double fallback = 0.0) const {
|
||||
auto it = Parameters.find(name);
|
||||
return it==Parameters.end()?0.0:it->second;
|
||||
return it==Parameters.end() ? fallback : it->second;
|
||||
}
|
||||
|
||||
// attributes
|
||||
|
||||
@@ -129,7 +129,7 @@ double Toolpath::getLength()
|
||||
Vector3d next;
|
||||
for(std::vector<Command*>::const_iterator it = vpcCommands.begin();it!=vpcCommands.end();++it) {
|
||||
std::string name = (*it)->Name;
|
||||
next = (*it)->getPlacement().getPosition();
|
||||
next = (*it)->getPlacement(last).getPosition();
|
||||
if ( (name == "G0") || (name == "G00") || (name == "G1") || (name == "G01") ) {
|
||||
// straight line
|
||||
l += (next - last).Length();
|
||||
|
||||
@@ -52,11 +52,11 @@ class ObjectDressup:
|
||||
obj.addProperty("App::PropertyAngle", "Angle", "Path", QtCore.QT_TRANSLATE_NOOP("Path_DressupRampEntry", "Angle of ramp."))
|
||||
obj.addProperty("App::PropertyEnumeration", "Method", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Ramping Method"))
|
||||
obj.addProperty("App::PropertyEnumeration", "RampFeedRate", "FeedRate", QtCore.QT_TRANSLATE_NOOP("App::Property", "Which feed rate to use for ramping"))
|
||||
obj.addProperty("App::PropertySpeed", "CustomFeedRate", "FeedRate", QtCore.QT_TRANSLATE_NOOP("App::Property", "Custom feedrate"))
|
||||
obj.addProperty("App::PropertySpeed", "CustomFeedRate", "FeedRate", QtCore.QT_TRANSLATE_NOOP("App::Property", "Custom feed rate"))
|
||||
obj.addProperty("App::PropertyBool", "UseStartDepth", "StartDepth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Should the dressup ignore motion commands above DressupStartDepth"))
|
||||
obj.addProperty("App::PropertyDistance", "DressupStartDepth", "StartDepth", QtCore.QT_TRANSLATE_NOOP("App::Property", "The depth where the ramp dressup is enabled. Above this ramps are not generated, but motion commands are passed through as is."))
|
||||
obj.Method = ['RampMethod1', 'RampMethod2', 'RampMethod3', 'Helix']
|
||||
obj.RampFeedRate = ['Horizontal Feed Rate', 'Vertical Feed Rate', 'Custom']
|
||||
obj.RampFeedRate = ['Horizontal Feed Rate', 'Vertical Feed Rate', 'Ramp Feed Rate', 'Custom']
|
||||
obj.Proxy = self
|
||||
self.setEditorProperties(obj)
|
||||
|
||||
@@ -582,12 +582,16 @@ class ObjectDressup:
|
||||
|
||||
horizFeed = tc.HorizFeed.Value
|
||||
vertFeed = tc.VertFeed.Value
|
||||
|
||||
if obj.RampFeedRate == "Horizontal Feed Rate":
|
||||
rampFeed = tc.HorizFeed.Value
|
||||
elif obj.RampFeedRate == "Vertical Feed Rate":
|
||||
rampFeed = tc.VertFeed.Value
|
||||
elif obj.RampFeedRate == 'Ramp Feed Rate':
|
||||
rampFeed = math.sqrt(pow(tc.VertFeed.Value, 2) + pow(tc.HorizFeed.Value, 2))
|
||||
else:
|
||||
rampFeed = obj.CustomFeedRate.Value
|
||||
|
||||
horizRapid = tc.HorizRapid.Value
|
||||
vertRapid = tc.VertRapid.Value
|
||||
|
||||
|
||||
@@ -1,39 +1,52 @@
|
||||
#***************************************************************************
|
||||
#* (c) sliptonic (shopinthewoods@gmail.com) 2014 *
|
||||
#* *
|
||||
#* This file is part of the FreeCAD CAx development system. *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* FreeCAD is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Lesser General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with FreeCAD; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#* This file has been modified from Sliptonis original Linux CNC post *
|
||||
#* for use with a Dynapath 20 controller all changes and Modifications *
|
||||
#* (c) Linden (Linden@aktfast.net) 2016 *
|
||||
#* *
|
||||
#***************************************************************************/
|
||||
from __future__ import print_function
|
||||
# ***************************************************************************
|
||||
# * (c) sliptonic (shopinthewoods@gmail.com) 2014 *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * FreeCAD is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Lesser General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with FreeCAD; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# * This file has been modified from Sliptonic original Linux CNC post *
|
||||
# * for use with a Dynapath 20 controller all changes and Modifications *
|
||||
# * (c) Linden (Linden@aktfast.net) 2016 *
|
||||
# * *
|
||||
# * Additional changes 2020 adding arguments to control units, precision *
|
||||
# * editor, header, etc. Now uses FreeCAD unit system to correctly *
|
||||
# * set Feed rate - sliptonic *
|
||||
# * *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
TOOLTIP='''
|
||||
from __future__ import print_function
|
||||
import FreeCAD
|
||||
from FreeCAD import Units
|
||||
import argparse
|
||||
import datetime
|
||||
import shlex
|
||||
from PathScripts import PostUtils
|
||||
|
||||
TOOLTIP = '''
|
||||
This is a postprocessor file for the Path workbench. It is used to
|
||||
take a pseudo-gcode fragment outputted by a Path object, and output
|
||||
real GCode suitable for a Tree Journyman 325 3 axis mill with Dynapath 20 controller in MM.
|
||||
This is a work in progress and very few of the functions available on the Dynapath have been
|
||||
implemented at this time.
|
||||
This postprocessor, once placed in the appropriate PathScripts folder, can be used directly
|
||||
from inside FreeCAD, via the GUI importer or via python scripts with:
|
||||
real GCode suitable for a Tree Journyman 325 3 axis mill with Dynapath 20
|
||||
controller in MM. This is a work in progress and very few of the functions
|
||||
available on the Dynapath have been implemented at this time.
|
||||
This postprocessor, once placed in the appropriate PathScripts folder,
|
||||
can be used directly from inside FreeCAD, via the GUI importer or via python
|
||||
scripts with:
|
||||
|
||||
Done
|
||||
Coordinate Decimal limited to 3 places
|
||||
@@ -48,35 +61,60 @@ To Do
|
||||
Change G20 and G21 to G70 and G71 for metric or imperial units
|
||||
Convert arcs to absolute
|
||||
Strip comments and white spaces
|
||||
Add file name in brackets limited to 8 alpha numeric no spaces all caps as first line in file
|
||||
Add file name in brackets limited to 8 alpha numeric no spaces all caps as
|
||||
first line in file
|
||||
Change Q to K For depth of peck on G83
|
||||
Fix tool change
|
||||
Limit comments length and characters to Uppercase, alpha numeric and spaces add / prior to comments
|
||||
Limit comments length and characters to Uppercase, alpha numeric and
|
||||
spaces add / prior to comments
|
||||
|
||||
import linuxcnc_post
|
||||
linuxcnc_post.export(object,"/path/to/file.ncc","")
|
||||
import dynapath_post
|
||||
dynapath_post.export(object,"/path/to/file.ncc","")
|
||||
'''
|
||||
|
||||
import datetime
|
||||
now = datetime.datetime.now()
|
||||
from PathScripts import PostUtils
|
||||
parser = argparse.ArgumentParser(prog='dynapath_post',
|
||||
add_help=False)
|
||||
parser.add_argument('--no-header', action='store_true',
|
||||
help='suppress header output')
|
||||
parser.add_argument('--no-comments', action='store_true',
|
||||
help='suppress comment output')
|
||||
parser.add_argument('--line-numbers', action='store_true',
|
||||
help='prefix with line numbers')
|
||||
parser.add_argument('--no-show-editor', action='store_true',
|
||||
help='don\'t pop up editor before writing output')
|
||||
parser.add_argument('--precision', default='3',
|
||||
help='number of digits of precision, default=3')
|
||||
parser.add_argument('--preamble',
|
||||
help='set commands to be issued before the first command, default="G17\nG90\nG80\nG40"')
|
||||
parser.add_argument('--postamble',
|
||||
help='set commands to be issued after the last command, default="M09\nM05\nG80\nG40\nG17\nG90\nM30"')
|
||||
parser.add_argument('--inches', action='store_true',
|
||||
help='Convert output for US imperial mode (G20)')
|
||||
|
||||
#These globals set common customization preferences
|
||||
|
||||
TOOLTIP_ARGS = parser.format_help()
|
||||
|
||||
now = datetime.datetime.now()
|
||||
|
||||
# These globals set common customization preferences
|
||||
OUTPUT_COMMENTS = True
|
||||
OUTPUT_HEADER = False
|
||||
OUTPUT_HEADER = True
|
||||
OUTPUT_LINE_NUMBERS = False
|
||||
SHOW_EDITOR = True
|
||||
MODAL = False #if true commands are suppressed if the same as previous line.
|
||||
MODAL = False # if true commands are suppressed if the same as previous line.
|
||||
COMMAND_SPACE = " "
|
||||
LINENR = 1 #line number starting value
|
||||
LINENR = 1 # line number starting value
|
||||
|
||||
#These globals will be reflected in the Machine configuration of the project
|
||||
UNITS = "G21" #G21 for metric, G20 for us standard
|
||||
UNIT_SPEED_FORMAT = 'mm/min'
|
||||
UNIT_FORMAT = 'mm'
|
||||
|
||||
# These globals will be reflected in the Machine configuration of the project
|
||||
UNITS = "G21" # G21 for metric, G20 for us standard
|
||||
MACHINE_NAME = "Tree MM"
|
||||
CORNER_MIN = {'x':-340, 'y':0, 'z':0 }
|
||||
CORNER_MAX = {'x':340, 'y':-355, 'z':-150 }
|
||||
CORNER_MIN = {'x': -340, 'y': 0, 'z': 0}
|
||||
CORNER_MAX = {'x': 340, 'y': -355, 'z': -150}
|
||||
|
||||
#Preamble text will appear at the beginning of the GCODE output file.
|
||||
# Preamble text will appear at the beginning of the GCODE output file.
|
||||
PREAMBLE = '''G17
|
||||
G90
|
||||
;G90.1 ;needed for simulation only
|
||||
@@ -84,7 +122,7 @@ G80
|
||||
G40
|
||||
'''
|
||||
|
||||
#Postamble text will appear following the last operation.
|
||||
# Postamble text will appear following the last operation.
|
||||
POSTAMBLE = '''M09
|
||||
M05
|
||||
G80
|
||||
@@ -95,37 +133,86 @@ M30
|
||||
'''
|
||||
|
||||
|
||||
#Pre operation text will be inserted before every operation
|
||||
# Pre operation text will be inserted before every operation
|
||||
PRE_OPERATION = ''''''
|
||||
|
||||
#Post operation text will be inserted after every operation
|
||||
# Post operation text will be inserted after every operation
|
||||
POST_OPERATION = ''''''
|
||||
|
||||
#Tool Change commands will be inserted before a tool change
|
||||
# Tool Change commands will be inserted before a tool change
|
||||
TOOL_CHANGE = ''''''
|
||||
|
||||
|
||||
# to distinguish python built-in open function from the one declared below
|
||||
if open.__module__ in ['__builtin__','io']:
|
||||
if open.__module__ in ['__builtin__', 'io']:
|
||||
pythonopen = open
|
||||
|
||||
|
||||
def export(objectslist,filename,argstring):
|
||||
def processArguments(argstring):
|
||||
# pylint: disable=global-statement
|
||||
global OUTPUT_HEADER
|
||||
global OUTPUT_COMMENTS
|
||||
global OUTPUT_LINE_NUMBERS
|
||||
global SHOW_EDITOR
|
||||
global PRECISION
|
||||
global PREAMBLE
|
||||
global POSTAMBLE
|
||||
global UNITS
|
||||
global UNIT_SPEED_FORMAT
|
||||
global UNIT_FORMAT
|
||||
global MODAL
|
||||
global USE_TLO
|
||||
global OUTPUT_DOUBLES
|
||||
|
||||
try:
|
||||
args = parser.parse_args(shlex.split(argstring))
|
||||
if args.no_header:
|
||||
OUTPUT_HEADER = False
|
||||
if args.no_comments:
|
||||
OUTPUT_COMMENTS = False
|
||||
if args.line_numbers:
|
||||
OUTPUT_LINE_NUMBERS = True
|
||||
if args.no_show_editor:
|
||||
SHOW_EDITOR = False
|
||||
print("Show editor = %d" % SHOW_EDITOR)
|
||||
PRECISION = args.precision
|
||||
if args.preamble is not None:
|
||||
PREAMBLE = args.preamble
|
||||
if args.postamble is not None:
|
||||
POSTAMBLE = args.postamble
|
||||
if args.inches:
|
||||
UNITS = 'G20'
|
||||
UNIT_SPEED_FORMAT = 'in/min'
|
||||
UNIT_FORMAT = 'in'
|
||||
PRECISION = 4
|
||||
|
||||
except Exception: # pylint: disable=broad-except
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def export(objectslist, filename, argstring):
|
||||
# pylint: disable=unused-argument
|
||||
global UNITS # pylint: disable=global-statement
|
||||
if not processArguments(argstring):
|
||||
return None
|
||||
global UNITS
|
||||
global UNIT_FORMAT
|
||||
global UNIT_SPEED_FORMAT
|
||||
|
||||
for obj in objectslist:
|
||||
if not hasattr(obj,"Path"):
|
||||
if not hasattr(obj, "Path"):
|
||||
print("the object " + obj.Name + " is not a path. Please select only path and Compounds.")
|
||||
return
|
||||
|
||||
print("postprocessing...")
|
||||
gcode = ""
|
||||
|
||||
#Find the machine.
|
||||
#The user my have overridden post processor defaults in the GUI. Make sure we're using the current values in the Machine Def.
|
||||
# Find the machine.
|
||||
# The user my have overridden post processor defaults in the GUI. Make sure we're using the current values in the Machine Def.
|
||||
myMachine = None
|
||||
for pathobj in objectslist:
|
||||
if hasattr(pathobj,"MachineName"):
|
||||
if hasattr(pathobj, "MachineName"):
|
||||
myMachine = pathobj.MachineName
|
||||
if hasattr(pathobj, "MachineUnits"):
|
||||
if pathobj.MachineUnits == "Metric":
|
||||
@@ -138,36 +225,41 @@ def export(objectslist,filename,argstring):
|
||||
# write header
|
||||
if OUTPUT_HEADER:
|
||||
gcode += linenumber() + "(Exported by FreeCAD)\n"
|
||||
gcode += linenumber() + "(Post Processor: " + __name__ +")\n"
|
||||
gcode += linenumber() + "(Post Processor: " + __name__ + ")\n"
|
||||
gcode += linenumber() + "(Output Time:"+str(now)+")\n"
|
||||
|
||||
#Write the preamble
|
||||
if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n"
|
||||
# Write the preamble
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin preamble)\n"
|
||||
for line in PREAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
gcode += linenumber() + UNITS + "\n"
|
||||
|
||||
for obj in objectslist:
|
||||
|
||||
#do the pre_op
|
||||
if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n"
|
||||
# do the pre_op
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(begin operation: " + obj.Label + ")\n"
|
||||
for line in PRE_OPERATION.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
|
||||
gcode += parse(obj)
|
||||
|
||||
#do the post_op
|
||||
if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n"
|
||||
# do the post_op
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += linenumber() + "(finish operation: " + obj.Label + ")\n"
|
||||
for line in POST_OPERATION.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
|
||||
#do the post_amble
|
||||
# do the post_amble
|
||||
|
||||
if OUTPUT_COMMENTS: gcode += "(begin postamble)\n"
|
||||
if OUTPUT_COMMENTS:
|
||||
gcode += "(begin postamble)\n"
|
||||
for line in POSTAMBLE.splitlines(True):
|
||||
gcode += linenumber() + line
|
||||
|
||||
if SHOW_EDITOR:
|
||||
print(f'show editor: {SHOW_EDITOR}')
|
||||
if FreeCAD.GuiUp and SHOW_EDITOR:
|
||||
dia = PostUtils.GCodeEditorDialog()
|
||||
dia.editor.setText(gcode)
|
||||
result = dia.exec_()
|
||||
@@ -180,85 +272,99 @@ def export(objectslist,filename,argstring):
|
||||
|
||||
print("done postprocessing.")
|
||||
|
||||
gfile = pythonopen(filename,"w")
|
||||
gfile = pythonopen(filename, "w")
|
||||
gfile.write(final)
|
||||
gfile.close()
|
||||
|
||||
|
||||
def linenumber():
|
||||
global LINENR # pylint: disable=global-statement
|
||||
if OUTPUT_LINE_NUMBERS == True:
|
||||
global LINENR # pylint: disable=global-statement
|
||||
if OUTPUT_LINE_NUMBERS is True:
|
||||
LINENR += 1
|
||||
return "N" + str(LINENR) + " "
|
||||
return ""
|
||||
|
||||
|
||||
def parse(pathobj):
|
||||
# pylint: disable=global-statement
|
||||
global PRECISION
|
||||
global UNIT_FORMAT
|
||||
global UNIT_SPEED_FORMAT
|
||||
|
||||
out = ""
|
||||
lastcommand = None
|
||||
|
||||
#params = ['X','Y','Z','A','B','I','J','K','F','S'] #This list control the order of parameters
|
||||
params = ['X','Y','Z','A','B','I','J','F','S','T','Q','R','L'] #linuxcnc doesn't want K properties on XY plane Arcs need work.
|
||||
precision_string = '.' + str(PRECISION) + 'f'
|
||||
|
||||
if hasattr(pathobj,"Group"): #We have a compound or project.
|
||||
if OUTPUT_COMMENTS: out += linenumber() + "(compound: " + pathobj.Label + ")\n"
|
||||
# params = ['X','Y','Z','A','B','I','J','K','F','S'] #This list control the order of parameters
|
||||
params = ['X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L']
|
||||
|
||||
if hasattr(pathobj, "Group"): # We have a compound or project.
|
||||
if OUTPUT_COMMENTS:
|
||||
out += linenumber() + "(compound: " + pathobj.Label + ")\n"
|
||||
for p in pathobj.Group:
|
||||
out += parse(p)
|
||||
return out
|
||||
else: #parsing simple path
|
||||
else: # parsing simple path
|
||||
|
||||
if not hasattr(pathobj,"Path"): #groups might contain non-path things like stock.
|
||||
if not hasattr(pathobj, "Path"): # groups might contain non-path things like stock.
|
||||
return out
|
||||
|
||||
if OUTPUT_COMMENTS: out += linenumber() + "(Path: " + pathobj.Label + ")\n"
|
||||
if OUTPUT_COMMENTS:
|
||||
out += linenumber() + "(Path: " + pathobj.Label + ")\n"
|
||||
|
||||
for c in pathobj.Path.Commands:
|
||||
outstring = []
|
||||
command = c.Name
|
||||
outstring.append(command)
|
||||
# if modal: only print the command if it is not the same as the last one
|
||||
if MODAL == True:
|
||||
if MODAL is True:
|
||||
if command == lastcommand:
|
||||
outstring.pop(0)
|
||||
|
||||
|
||||
# Now add the remaining parameters in order
|
||||
for param in params:
|
||||
if param in c.Parameters:
|
||||
if param == 'F':
|
||||
outstring.append(param + format(c.Parameters['F'], '.0f'))
|
||||
speed = Units.Quantity(c.Parameters['F'], FreeCAD.Units.Velocity)
|
||||
if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0:
|
||||
outstring.append(param + format(float(speed.getValueAs(UNIT_SPEED_FORMAT)), precision_string))
|
||||
elif param == 'S':
|
||||
outstring.append(param + format(c.Parameters[param], '.0f'))
|
||||
outstring.append(param + format(c.Parameters[param], precision_string))
|
||||
elif param == 'T':
|
||||
outstring.append(param + format(c.Parameters['T'], '.0f'))
|
||||
outstring.append(param + format(c.Parameters['T'], precision_string))
|
||||
else:
|
||||
outstring.append(param + format(c.Parameters[param], '.3f'))
|
||||
pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length)
|
||||
outstring.append(
|
||||
param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string))
|
||||
|
||||
# store the latest command
|
||||
lastcommand = command
|
||||
|
||||
# Check for Tool Change:
|
||||
if command == 'M6':
|
||||
if OUTPUT_COMMENTS: out += linenumber() + "(begin toolchange)\n"
|
||||
if OUTPUT_COMMENTS:
|
||||
out += linenumber() + "(begin toolchange)\n"
|
||||
for line in TOOL_CHANGE.splitlines(True):
|
||||
out += linenumber() + line
|
||||
|
||||
if command == "message":
|
||||
if OUTPUT_COMMENTS == False:
|
||||
if OUTPUT_COMMENTS is False:
|
||||
out = []
|
||||
else:
|
||||
outstring.pop(0) #remove the command
|
||||
outstring.pop(0) # remove the command
|
||||
|
||||
#prepend a line number and append a newline
|
||||
# prepend a line number and append a newline
|
||||
if len(outstring) >= 1:
|
||||
if OUTPUT_LINE_NUMBERS:
|
||||
outstring.insert(0,(linenumber()))
|
||||
outstring.insert(0, (linenumber()))
|
||||
|
||||
#append the line to the final output
|
||||
# append the line to the final output
|
||||
for w in outstring:
|
||||
out += w + COMMAND_SPACE
|
||||
out = out.strip() + "\n"
|
||||
|
||||
return out
|
||||
|
||||
print(__name__ + " gcode postprocessor loaded.")
|
||||
|
||||
print(__name__ + " gcode postprocessor loaded.")
|
||||
|
||||
@@ -155,3 +155,12 @@ G0 Z0.500000
|
||||
|
||||
self.assertEqual(len(table.Tools), 2)
|
||||
self.assertEqual(str(table.Tools), '{1: Tool 12.7mm Drill Bit, 2: Tool my other tool}' )
|
||||
|
||||
def test50(self):
|
||||
"""Test Path.Length calculation"""
|
||||
commands = []
|
||||
commands.append(Path.Command("G1",{"X":1}))
|
||||
commands.append(Path.Command("G1",{"Y":1}))
|
||||
path = Path.Path(commands)
|
||||
|
||||
self.assertEqual(path.Length, 2)
|
||||
|
||||
@@ -87,14 +87,14 @@ void DrawWeldSymbol::onSettingDocument()
|
||||
return;
|
||||
}
|
||||
|
||||
std::string tileName1 = doc->getUniqueObjectName("DrawTileWeld");
|
||||
std::string tileName1 = doc->getUniqueObjectName("TileWeld");
|
||||
auto tile1Obj( doc->addObject( "TechDraw::DrawTileWeld", tileName1.c_str() ) );
|
||||
DrawTileWeld* tile1 = dynamic_cast<DrawTileWeld*>(tile1Obj);
|
||||
if (tile1 != nullptr) {
|
||||
tile1->TileParent.setValue(this);
|
||||
}
|
||||
|
||||
std::string tileName2 = doc->getUniqueObjectName("DrawTileWeld");
|
||||
std::string tileName2 = doc->getUniqueObjectName("TileWeld");
|
||||
auto tile2Obj( doc->addObject( "TechDraw::DrawTileWeld", tileName2.c_str() ) );
|
||||
DrawTileWeld* tile2 = dynamic_cast<DrawTileWeld*>(tile2Obj);
|
||||
if (tile2 != nullptr) {
|
||||
|
||||
@@ -151,7 +151,7 @@ private:
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw Py::TypeError("Export of this object type is not supported by TechDraw module");
|
||||
throw Py::TypeError("No Technical Drawing Page found in selection.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,9 +400,6 @@ void MDIViewPage::onDeleteObject(const App::DocumentObject& obj)
|
||||
//if this page has a QView for this obj, delete it.
|
||||
if (obj.isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
|
||||
(void) m_view->removeQViewByName(obj.getNameInDocument());
|
||||
} else if (m_objectName == obj.getNameInDocument()) {
|
||||
// if obj is me, hide myself and my tab
|
||||
m_vpPage->hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>icons/TechDraw_Tree_Annotation.svg</file>
|
||||
<file>icons/TechDraw_Tree_Hatch.svg</file>
|
||||
<file>icons/TechDraw_Tree_Page.svg</file>
|
||||
<file>icons/TechDraw_Tree_Page_Unsync.svg</file>
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 23 KiB |
@@ -116,7 +116,7 @@ TechDraw::DrawViewSymbol* TaskActiveView::createActiveView(void)
|
||||
{
|
||||
// Base::Console().Message("TAV::createActiveView()\n");
|
||||
|
||||
std::string symbolName = m_pageFeat->getDocument()->getUniqueObjectName("DrawActiveView");
|
||||
std::string symbolName = m_pageFeat->getDocument()->getUniqueObjectName("ActiveView");
|
||||
std::string symbolType = "TechDraw::DrawViewSymbol";
|
||||
|
||||
std::string pageName = m_pageFeat->getNameInDocument();
|
||||
|
||||
@@ -261,7 +261,7 @@ void TaskLeaderLine::setUiEdit()
|
||||
void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> converted)
|
||||
{
|
||||
// Base::Console().Message("TTL::createLeaderFeature()\n");
|
||||
m_leaderName = m_basePage->getDocument()->getUniqueObjectName("DrawLeaderLine");
|
||||
m_leaderName = m_basePage->getDocument()->getUniqueObjectName("LeaderLine");
|
||||
m_leaderType = "TechDraw::DrawLeaderLine";
|
||||
|
||||
std::string PageName = m_basePage->getNameInDocument();
|
||||
|
||||
@@ -281,7 +281,7 @@ void TaskRichAnno::onEditorExit(void)
|
||||
void TaskRichAnno::createAnnoFeature()
|
||||
{
|
||||
// Base::Console().Message("TRA::createAnnoFeature()");
|
||||
std::string annoName = m_basePage->getDocument()->getUniqueObjectName("DrawRichAnno");
|
||||
std::string annoName = m_basePage->getDocument()->getUniqueObjectName("RichTextAnnotation");
|
||||
std::string annoType = "TechDraw::DrawRichAnno";
|
||||
|
||||
std::string PageName = m_basePage->getNameInDocument();
|
||||
|
||||
@@ -351,7 +351,7 @@ TechDraw::DrawViewSection* TaskSectionView::createSectionView(void)
|
||||
Gui::Command::openCommand("Create SectionView");
|
||||
TechDraw::DrawViewSection* newSection = nullptr;
|
||||
if (m_section == nullptr) {
|
||||
sectionName = m_base->getDocument()->getUniqueObjectName("DrawViewSection");
|
||||
sectionName = m_base->getDocument()->getUniqueObjectName("SectionView");
|
||||
std::string sectionType = "TechDraw::DrawViewSection";
|
||||
|
||||
TechDraw::DrawPage* page = m_base->findParentPage();
|
||||
|
||||
@@ -434,7 +434,7 @@ TechDraw::DrawWeldSymbol* TaskWeldingSymbol::createWeldingSymbol(void)
|
||||
{
|
||||
// Base::Console().Message("TWS::createWeldingSymbol()\n");
|
||||
|
||||
std::string symbolName = m_leadFeat->getDocument()->getUniqueObjectName("DrawWeldSymbol");
|
||||
std::string symbolName = m_leadFeat->getDocument()->getUniqueObjectName("WeldSymbol");
|
||||
std::string symbolType = "TechDraw::DrawWeldSymbol";
|
||||
|
||||
TechDraw::DrawPage* page = m_leadFeat->findParentPage();
|
||||
|
||||
@@ -49,7 +49,7 @@ PROPERTY_SOURCE(TechDrawGui::ViewProviderAnnotation, TechDrawGui::ViewProviderDr
|
||||
|
||||
ViewProviderAnnotation::ViewProviderAnnotation()
|
||||
{
|
||||
sPixmap = "TechDraw_Tree_Annotation";
|
||||
sPixmap = "actions/techdraw-annotation";
|
||||
}
|
||||
|
||||
ViewProviderAnnotation::~ViewProviderAnnotation()
|
||||
|
||||
Reference in New Issue
Block a user