Merge branch 'master' into addImportExportRecentFilesPrefs

This commit is contained in:
Chris Hennes
2021-01-27 10:36:47 -06:00
committed by GitHub
218 changed files with 15081 additions and 1234 deletions
+6 -1
View File
@@ -50,6 +50,12 @@ if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER)
find_package(ZLIB REQUIRED)
find_package(PyCXX REQUIRED)
SetupOpenCasCade()
if(BUILD_GUI)
# Do this before the check for SMESH because it depends on vtk
# that may have its own OpenGL check but possibly fails and leaves
# OPENGL_gl_LIBRARY empty that results into linker errors
SetupOpenGL()
endif(BUILD_GUI)
SetupSalomeSMESH()
if (BUILD_FEM_NETGEN)
find_package(NETGEN)
@@ -64,7 +70,6 @@ if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER)
SetupFreetype()
if(BUILD_GUI)
SetupOpenGL()
SetupCoin3D()
SetupSpaceball()
SetupShibokenAndPyside()
@@ -163,6 +163,7 @@ macro(PrintFinalReport)
message(STATUS "Freetype: disabled")
endif(FREECAD_USE_FREETYPE)
message(STATUS "OpenGL: ${OPENGL_gl_LIBRARY}")
message(STATUS "OpenGLU: ${OPENGL_glu_LIBRARY} [${OPENGL_glu_LIBRARY}][${OPENGL_INCLUDE_DIR}]")
message(STATUS "Coin3D: [${COIN3D_LIBRARIES}] [${COIN3D_INCLUDE_DIRS}]")
+1
View File
@@ -2745,6 +2745,7 @@ void Document::restore (const char *filename,
}
catch (const Base::Exception& e) {
Base::Console().Error("Invalid Document.xml: %s\n", e.what());
setStatus(Document::RestoreError, true);
}
d->partialLoadObjects.clear();
+1
View File
@@ -74,6 +74,7 @@ public:
PartialDoc = 7,
AllowPartialRecompute = 8, // allow recomputing editing object if SkipRecompute is set
TempDoc = 9, // Mark as temporary document without prompt for save
RestoreError = 10
};
/** @name Properties */
+10 -3
View File
@@ -27,12 +27,15 @@
#endif
#include <Base/Exception.h>
#include <Base/Console.h>
#include <Base/Tools.h>
#include <App/Document.h>
#include "Origin.h"
#include "GeoFeature.h"
FC_LOG_LEVEL_INIT("App", true, true)
using namespace App;
EXTENSION_PROPERTY_SOURCE(App::OriginGroupExtension, App::GeoFeatureGroupExtension)
@@ -160,8 +163,12 @@ void OriginGroupExtension::extensionOnChanged(const Property* p) {
&& owner->getDocument()->testStatus(Document::Importing)) {
for (auto o : origin->getInList()) {
if(o != owner && o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) {
Origin.setValue(nullptr);
throw Base::RuntimeError("Origin can only be in a single OriginGroup");
// Temporarily reset 'Restoring' status to allow document to auto label new objects
Base::ObjectStatusLocker<Document::Status, Document> guard(
Document::Restoring, owner->getDocument(), false);
Origin.setValue(owner->getDocument()->addObject("App::Origin", "Origin"));
FC_WARN("Reset origin in " << owner->getFullName());
return;
}
}
}
+25 -6
View File
@@ -67,19 +67,38 @@ Part::~Part(void)
{
}
App::Part *Part::getPartOfObject (const DocumentObject* obj) {
static App::Part *_getPartOfObject(const DocumentObject *obj,
std::set<const DocumentObject*> *objset)
{
// as a Part is a geofeaturegroup it must directly link to all
// objects it contains, even if they are in additional groups etc.
auto list = obj->getInList();
for (auto obj : list) {
if(obj->isDerivedFrom(App::Part::getClassTypeId()))
return static_cast<App::Part*>(obj);
// But we still must call 'hasObject()' to exclude link brought in by
// expressions.
for (auto inObj : obj->getInList()) {
if (objset && !objset->insert(inObj).second)
continue;
auto group = inObj->getExtensionByType<GeoFeatureGroupExtension>(true);
if(group && group->hasObject(obj)) {
if(inObj->isDerivedFrom(App::Part::getClassTypeId()))
return static_cast<App::Part*>(inObj);
else if (objset)
return _getPartOfObject(inObj, objset);
// Only one parent geofeature group per object, so break
break;
}
}
return nullptr;
}
App::Part *Part::getPartOfObject (const DocumentObject* obj, bool recursive) {
if (!recursive)
return _getPartOfObject(obj, nullptr);
std::set<const DocumentObject *> objset;
objset.insert(obj);
return _getPartOfObject(obj, &objset);
}
PyObject *Part::getPyObject()
{
+2 -1
View File
@@ -88,8 +88,9 @@ public:
* Returns the part which contains this object.
* In case this object does not belong to any Part, 0 is returned.
* @param obj the object to search for
* @param recursive: whether to recursively find any grand parent Part container
*/
static App::Part* getPartOfObject (const DocumentObject* obj);
static App::Part* getPartOfObject (const DocumentObject* obj, bool recursive=true);
virtual PyObject *getPyObject(void) override;
};
+5
View File
@@ -97,6 +97,11 @@ text names of the status.
<UserDocu>Return the documentation string of the property of this class.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getEnumerationsOfProperty">
<Documentation>
<UserDocu>Return all enumeration strings of the property of this class or None if not a PropertyEnumeration.</UserDocu>
</Documentation>
</Methode>
<Methode Name="dumpPropertyContent" Keyword="true" Const="true">
<Documentation>
<UserDocu>Dumps the content of the property, both the XML representation as well as the additional datafiles
+28 -1
View File
@@ -357,7 +357,34 @@ PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args)
else
return Py::new_reference_to(Py::String(""));
}
PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args)
{
char *pstr;
if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C
return NULL; // NULL triggers exception
Property* prop = getPropertyContainerPtr()->getPropertyByName(pstr);
if (!prop) {
PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", pstr);
return 0;
}
PropertyEnumeration *enumProp = dynamic_cast<PropertyEnumeration*>(prop);
if (!enumProp) {
Py_INCREF(Py_None);
return Py_None;
}
std::vector<std::string> enumerations = enumProp->getEnumVector();
Py::List ret;
for (std::vector<std::string>::const_iterator it = enumerations.begin(); it != enumerations.end(); ++it) {
ret.append(Py::String(*it));
}
return Py::new_reference_to(ret);
}
Py::List PropertyContainerPy::getPropertiesList(void) const
{
Py::List ret;
+10 -1
View File
@@ -792,7 +792,12 @@ bool Gui::GuiNativeEvent::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawI
if (sRidDeviceInfo.hid.dwVendorId == LOGITECH_VENDOR_ID || sRidDeviceInfo.hid.dwVendorId == CONNEXION_VENDOR_ID) {
switch (sRidDeviceInfo.hid.dwProductId) {
case eSpaceMousePlusXT:
return TranslateSpaceMouseOldGeneric(nInputCode, pRawInput, sRidDeviceInfo.hid.dwProductId);
if (pRawInput->data.hid.bRawData[0] != 0x00) {
return TranslateSpaceMouseNewGeneric(nInputCode, pRawInput, sRidDeviceInfo.hid.dwProductId);
}
else {
return TranslateSpaceMouseOldGeneric(nInputCode, pRawInput, sRidDeviceInfo.hid.dwProductId);
}
case eSpaceMouseEnterprise:
return TranslateSpaceMouseEnterprise(nInputCode, pRawInput, sRidDeviceInfo.hid.dwProductId);
case eSpacePilot:
@@ -1056,6 +1061,10 @@ bool Gui::GuiNativeEvent::TranslateSpaceMouseOldGeneric(UINT nInputCode, PRAWINP
pValueCaps = NULL;
hHeap = GetProcessHeap();
#ifdef _TRACE_RI_RAWDATA
qDebug("pRawInput->data.hid.bRawData[0] = 0x%x", pRawInput->data.hid.bRawData[0]);
#endif
//
// Get the preparsed data block
//
+39 -14
View File
@@ -531,6 +531,7 @@ void WorkbenchComboBox::onWorkbenchActivated(const QString& name)
WorkbenchGroup::WorkbenchGroup ( Command* pcCmd, QObject * parent )
: ActionGroup( pcCmd, parent )
{
// Start a list with 50 elements but extend it when requested
for (int i=0; i<50; i++) {
QAction* action = _group->addAction(QLatin1String(""));
action->setVisible(false);
@@ -590,7 +591,7 @@ void WorkbenchGroup::refreshWorkbenchList()
QStringList items = Application::Instance->workbenches();
QStringList enabled_wbs_list = DlgWorkbenchesImp::load_enabled_workbenches();
QStringList disabled_wbs_list = DlgWorkbenchesImp::load_disabled_workbenches();
int i=0;
QStringList enable_wbs;
// Go through the list of enabled workbenches and verify that they really exist because
// it might be possible that a workbench has been removed after setting up the list of
@@ -598,7 +599,7 @@ void WorkbenchGroup::refreshWorkbenchList()
for (QStringList::Iterator it = enabled_wbs_list.begin(); it != enabled_wbs_list.end(); ++it) {
int index = items.indexOf(*it);
if (index >= 0) {
setWorkbenchData(i++, *it);
enable_wbs << *it;
items.removeAt(index);
}
}
@@ -613,8 +614,22 @@ void WorkbenchGroup::refreshWorkbenchList()
// Now add the remaining workbenches of 'items'. They have been added to the application
// after setting up the list of enabled workbenches.
for (QStringList::Iterator it = items.begin(); it != items.end(); ++it) {
setWorkbenchData(i++, *it);
enable_wbs.append(items);
QList<QAction*> workbenches = _group->actions();
int numActions = workbenches.size();
int extend = enable_wbs.size() - numActions;
if (extend > 0) {
for (int i=0; i<extend; i++) {
QAction* action = _group->addAction(QLatin1String(""));
action->setCheckable(true);
action->setData(QVariant(numActions++)); // set the index
}
}
// Show all enabled wb
int index = 0;
for (QStringList::Iterator it = enable_wbs.begin(); it != enable_wbs.end(); ++it) {
setWorkbenchData(index++, *it);
}
}
@@ -633,21 +648,31 @@ void WorkbenchGroup::slotActivateWorkbench(const char* /*name*/)
void WorkbenchGroup::slotAddWorkbench(const char* name)
{
QList<QAction*> workbenches = _group->actions();
QAction* action = nullptr;
for (QList<QAction*>::Iterator it = workbenches.begin(); it != workbenches.end(); ++it) {
if (!(*it)->isVisible()) {
QString wb = QString::fromLatin1(name);
QPixmap px = Application::Instance->workbenchIcon(wb);
QString text = Application::Instance->workbenchMenuText(wb);
QString tip = Application::Instance->workbenchToolTip(wb);
(*it)->setIcon(px);
(*it)->setObjectName(wb);
(*it)->setText(text);
(*it)->setToolTip(tip);
(*it)->setStatusTip(tr("Select the '%1' workbench").arg(wb));
(*it)->setVisible(true); // do this at last
action = *it;
break;
}
}
if (!action) {
int index = workbenches.size();
action = _group->addAction(QLatin1String(""));
action->setCheckable(true);
action->setData(QVariant(index)); // set the index
}
QString wb = QString::fromLatin1(name);
QPixmap px = Application::Instance->workbenchIcon(wb);
QString text = Application::Instance->workbenchMenuText(wb);
QString tip = Application::Instance->workbenchToolTip(wb);
action->setIcon(px);
action->setObjectName(wb);
action->setText(text);
action->setToolTip(tip);
action->setStatusTip(tr("Select the '%1' workbench").arg(wb));
action->setVisible(true); // do this at last
}
void WorkbenchGroup::slotRemoveWorkbench(const char* name)
+8
View File
@@ -160,6 +160,14 @@ void StdCmdOpen::activated(int iMsg)
else {
for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
getGuiApplication()->open(it.key().toUtf8(), it.value().toLatin1());
App::Document *doc = App::GetApplication().getActiveDocument();
if(doc && doc->testStatus(App::Document::PartialRestore))
QMessageBox::critical(getMainWindow(), QObject::tr("Error"), QObject::tr("There were errors while loading the file. Some data might have been modified or not recovered at all. Look in the report view for more specific information about the objects involved."));
if(doc && doc->testStatus(App::Document::RestoreError))
QMessageBox::critical(getMainWindow(), QObject::tr("Error"), QObject::tr("There were serious errors while loading the file. Some data might have been modified or not recovered at all. Saving the project will most likely result in loss of data."));
}
}
}
+1 -1
View File
@@ -257,7 +257,7 @@ StdCmdWindows::StdCmdWindows()
sToolTipText = QT_TR_NOOP("Windows list");
sWhatsThis = "Std_Windows";
sStatusTip = QT_TR_NOOP("Windows list");
//sPixmap = "";
sPixmap = "Std_Windows";
eType = 0;
}
+292
View File
@@ -0,0 +1,292 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64px"
height="64px"
id="svg2985"
version="1.1">
<title
id="title889">Std_Windows</title>
<defs
id="defs2987">
<linearGradient
id="linearGradient3319">
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="0"
id="stop3315" />
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="1"
id="stop3317" />
</linearGradient>
<linearGradient
id="linearGradient4387">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4389" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4391" />
</linearGradient>
<linearGradient
id="linearGradient6321">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop6323" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop6325" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-0.23443224,0.23443198)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3377-3">
<stop
id="stop3379-8"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381-3"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient3377-3"
id="radialGradient6412"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.67067175,0,0,0.64145918,-63.380792,0.83845403)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<linearGradient
y2="56.000233"
x2="20.93985"
y1="50.468616"
x1="14.824193"
gradientTransform="rotate(33.834399,20.280412,56.143946)"
gradientUnits="userSpaceOnUse"
id="linearGradient3049"
xlink:href="#linearGradient3036" />
<linearGradient
id="linearGradient3036">
<stop
id="stop3038"
offset="0"
style="stop-color:#ef2929;stop-opacity:1" />
<stop
id="stop3040"
offset="1"
style="stop-color:#a40000;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3895-6">
<stop
id="stop3897-7"
offset="0"
style="stop-color:#729fcf;stop-opacity:1;" />
<stop
id="stop3899-5"
offset="1"
style="stop-color:#204a87;stop-opacity:1;" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3319"
id="linearGradient3307"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(33.834399,-6.8783909,90.878388)"
x1="14.824193"
y1="50.468616"
x2="20.93985"
y2="56.000233" />
<linearGradient
gradientTransform="matrix(1.6433254,0,0,0.97077226,-45.241374,0.95414569)"
xlink:href="#linearGradient3842"
id="linearGradient3848"
x1="49"
y1="16"
x2="48"
y2="4"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3842">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3844" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3846" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3830"
id="linearGradient3836"
x1="49"
y1="54"
x2="43"
y2="14"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.8458495,0,0,0.65353286,-54.81737,8.8166943)" />
<linearGradient
id="linearGradient3830">
<stop
style="stop-color:#d3d7cf;stop-opacity:1;"
offset="0"
id="stop3832" />
<stop
style="stop-color:#ffffff;stop-opacity:1"
offset="1"
id="stop3834" />
</linearGradient>
<linearGradient
gradientUnits="userSpaceOnUse"
y2="4"
x2="48"
y1="16"
x1="49"
id="linearGradient3848-5"
xlink:href="#linearGradient3842"
gradientTransform="matrix(1.6433254,0,0,0.97077226,-45.25917,44.291622)" />
</defs>
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Std_Windows</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>Part_Shape_from_Mesh</dc:title>
<dc:date>2021/01/04</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier />
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:contributor>
<dc:subject>
<rdf:Bag>
<rdf:li>window</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description>Window with list of elements</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<rect
y="5.8080096"
x="12.275028"
height="52.421707"
width="39.439812"
id="rect3020"
style="fill:none;stroke:#204a87;stroke-width:7.5783;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6;stroke-opacity:1" />
<rect
y="5.8080096"
x="12.275028"
height="52.421707"
width="39.439812"
id="rect3020-6"
style="fill:none;stroke:#729fcf;stroke-width:2.5261;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6;stroke-opacity:1" />
<rect
y="5.8080068"
x="12.275028"
height="7.7661781"
width="39.439812"
id="rect3826"
style="fill:url(#linearGradient3848);fill-opacity:1;stroke:#729fcf;stroke-width:2.5261;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6;stroke-opacity:1" />
<rect
y="17.31262"
x="17.170778"
height="27.448381"
width="29.533592"
id="rect3828"
style="fill:url(#linearGradient3836);fill-opacity:1;stroke:#ffffff;stroke-width:2.30937;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6;stroke-opacity:1" />
<path
id="path3838"
d="M 13.532966,15.515748 H 50.426045"
style="fill:none;stroke:#204a87;stroke-width:2.55182;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3840"
d="M 13.671701,9.691097 H 26.818305"
style="fill:none;stroke:#ffffff;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1619-0"
d="M 20.590449,27.862348 H 43.628164"
style="fill:none;stroke:#555753;stroke-width:2.33762;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;stroke:#555753;stroke-width:2.33762;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 20.565033,33.623598 h 23.12479"
id="path1619-0-3" />
<rect
style="fill:url(#linearGradient3848-5);fill-opacity:1;stroke:#729fcf;stroke-width:2.5261;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6;stroke-opacity:1"
id="rect3826-5"
width="39.439812"
height="7.7661781"
x="12.257233"
y="49.145481" />
<path
style="fill:none;stroke:#204a87;stroke-width:2.55182;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 13.520488,46.620649 H 50.413567"
id="path3838-2" />
<path
style="fill:none;stroke:#ffffff;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 37.190176,53.059357 H 50.33678"
id="path3840-4" />
<path
style="fill:none;stroke:#ffffff;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 21.521082,52.972283 H 34.667686"
id="path3840-5" />
<path
style="fill:none;stroke:#555753;stroke-width:2.33762;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 20.62131,22.102998 H 43.659025"
id="path1619-0-9" />
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

+1
View File
@@ -196,6 +196,7 @@
<file>Std_ViewIvStereoQuadBuff.svg</file>
<file>Std_ViewIvStereoRedGreen.svg</file>
<file>Std_ViewTrimetric.svg</file>
<file>Std_Windows.svg</file>
<file>Std_WindowCascade.svg</file>
<file>Std_WindowNext.svg</file>
<file>Std_WindowPrev.svg</file>
+10 -5
View File
@@ -116,18 +116,23 @@ Py::Object SelectionObjectPy::getObject(void) const
Py::Tuple SelectionObjectPy::getSubObjects(void) const
{
std::vector<PyObject *> objs;
App::DocumentObject *obj = getSelectionObjectPtr()->getObject();
if (!obj)
throw Py::RuntimeError("Cannot get sub-objects of deleted object");
std::vector<PyObject *> subObjs;
for(const auto &subname : getSelectionObjectPtr()->getSubNames()) {
PyObject *pyObj=0;
Base::Matrix4D mat;
getSelectionObjectPtr()->getObject()->getSubObject(subname.c_str(),&pyObj,&mat);
if(pyObj) objs.push_back(pyObj);
obj->getSubObject(subname.c_str(),&pyObj,&mat);
if(pyObj)
subObjs.push_back(pyObj);
}
Py::Tuple temp(objs.size());
Py::Tuple temp(subObjs.size());
Py::sequence_index_type index = 0;
for(std::vector<PyObject *>::const_iterator it= objs.begin();it!=objs.end();++it)
for(std::vector<PyObject *>::const_iterator it= subObjs.begin();it!=subObjs.end();++it)
temp.setItem(index++, Py::asObject(*it));
return temp;
+35 -10
View File
@@ -77,6 +77,7 @@
# include <Inventor/VRMLnodes/SoVRMLGroup.h>
# include <Inventor/nodes/SoPickStyle.h>
# include <Inventor/nodes/SoTransparencyType.h>
# include <QApplication>
# include <QEventLoop>
# include <QKeyEvent>
# include <QWheelEvent>
@@ -599,17 +600,12 @@ void View3DInventorViewer::init()
}
//create the cursors
QBitmap cursor = QBitmap::fromData(QSize(ROTATE_WIDTH, ROTATE_HEIGHT), rotate_bitmap);
QBitmap mask = QBitmap::fromData(QSize(ROTATE_WIDTH, ROTATE_HEIGHT), rotate_mask_bitmap);
spinCursor = QCursor(cursor, mask, ROTATE_HOT_X, ROTATE_HOT_Y);
createStandardCursors(devicePixelRatio());
#if (QT_VERSION >= 0x050000)
connect(this, &View3DInventorViewer::devicePixelRatioChanged,
this, &View3DInventorViewer::createStandardCursors);
#endif
cursor = QBitmap::fromData(QSize(ZOOM_WIDTH, ZOOM_HEIGHT), zoom_bitmap);
mask = QBitmap::fromData(QSize(ZOOM_WIDTH, ZOOM_HEIGHT), zoom_mask_bitmap);
zoomCursor = QCursor(cursor, mask, ZOOM_HOT_X, ZOOM_HOT_Y);
cursor = QBitmap::fromData(QSize(PAN_WIDTH, PAN_HEIGHT), pan_bitmap);
mask = QBitmap::fromData(QSize(PAN_WIDTH, PAN_HEIGHT), pan_mask_bitmap);
panCursor = QCursor(cursor, mask, PAN_HOT_X, PAN_HOT_Y);
naviCube = new NaviCube(this);
naviCubeEnabled = true;
}
@@ -683,6 +679,35 @@ View3DInventorViewer::~View3DInventorViewer()
delete glAction;
}
void View3DInventorViewer::createStandardCursors(double dpr)
{
QBitmap cursor = QBitmap::fromData(QSize(ROTATE_WIDTH, ROTATE_HEIGHT), rotate_bitmap);
QBitmap mask = QBitmap::fromData(QSize(ROTATE_WIDTH, ROTATE_HEIGHT), rotate_mask_bitmap);
#if defined(Q_OS_WIN32)
cursor.setDevicePixelRatio(dpr);
mask.setDevicePixelRatio(dpr);
#else
Q_UNUSED(dpr)
#endif
spinCursor = QCursor(cursor, mask, ROTATE_HOT_X, ROTATE_HOT_Y);
cursor = QBitmap::fromData(QSize(ZOOM_WIDTH, ZOOM_HEIGHT), zoom_bitmap);
mask = QBitmap::fromData(QSize(ZOOM_WIDTH, ZOOM_HEIGHT), zoom_mask_bitmap);
#if defined(Q_OS_WIN32)
cursor.setDevicePixelRatio(dpr);
mask.setDevicePixelRatio(dpr);
#endif
zoomCursor = QCursor(cursor, mask, ZOOM_HOT_X, ZOOM_HOT_Y);
cursor = QBitmap::fromData(QSize(PAN_WIDTH, PAN_HEIGHT), pan_bitmap);
mask = QBitmap::fromData(QSize(PAN_WIDTH, PAN_HEIGHT), pan_mask_bitmap);
#if defined(Q_OS_WIN32)
cursor.setDevicePixelRatio(dpr);
mask.setDevicePixelRatio(dpr);
#endif
panCursor = QCursor(cursor, mask, PAN_HOT_X, PAN_HOT_Y);
}
void View3DInventorViewer::aboutToDestroyGLContext()
{
if (naviCube) {
+1
View File
@@ -426,6 +426,7 @@ private:
static void drawArrow(void);
void setCursorRepresentation(int mode);
void aboutToDestroyGLContext();
void createStandardCursors(double);
private:
NaviCube* naviCube;
@@ -41,6 +41,7 @@
<file>icons/Part-o-magic_workbench_icon.svg</file>
<file>icons/Plot_workbench_icon.svg</file>
<file>icons/POV-Ray-Rendering_workbench_icon.svg</file>
<file>icons/Pyramids-and-Polyhedrons_workbench_icon.svg</file>
<file>icons/pyrate_workbench_icon.svg</file>
<file>icons/Reinforcement_workbench_icon.svg</file>
<file>icons/Reporting_workbench_icon.svg</file>
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16.933334mm"
height="16.933334mm"
viewBox="0 0 16.933334 16.933334"
version="1.1"
id="svg830"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="Pyramids-and-Polyhedrons_workbench_icon.svg">
<defs
id="defs824" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.7613637"
inkscape:cx="47.718164"
inkscape:cy="-15.87115"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1025"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata827">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Laag 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-108.80373,-155.64809)">
<g
id="g829"
transform="matrix(0.38917917,0,0,0.38917917,66.50284,95.165496)">
<path
inkscape:connector-curvature="0"
id="path1472"
d="m 131.1424,176.86022 12.78082,1.83377 -0.11113,10.94706 -12.33628,5.3346 -8.33532,-7.89076 z"
style="fill:#000099;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1474"
d="m 126.36348,164.9685 9.6134,-5.50131 10.89149,8.39089 -2.94515,10.83591 -12.78082,-1.83377 z"
style="fill:#6666ff;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1476"
d="m 115.47199,167.80251 10.89149,-2.83401 4.77892,11.89172 -8.00191,10.22467 -9.55784,-5.72359 z"
style="fill:#6666ff;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1478"
d="m 118.58385,163.80155 12.33627,-4.94562 5.05676,0.61126 -9.6134,5.50131 -10.89149,2.83401 z"
style="fill:#000099;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1480"
d="m 115.52756,186.14021 -1.94491,-4.77891 9.55784,5.72359 8.33532,7.89076 -5.3346,-0.50011 z"
style="fill:#000050;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1482"
d="m 146.92394,185.75123 -3.11185,3.88982 0.11113,-10.94706 2.94515,-10.83591 2.05605,4.77891 z"
style="fill:#000050;fill-opacity:1;stroke:#000000;stroke-width:0.26499999;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="155.41066"
x="108.6926"
height="43.51038"
width="43.51038"
id="rect1488"
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:0.26499999;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+9 -7
View File
@@ -757,8 +757,8 @@ class Component(ArchIFC.IfcProduct):
subs = obj.Subtractions
for link in obj.InListRecursive:
if hasattr(link,"Hosts"):
for host in link.Hosts:
if host == obj:
if link.Hosts:
if obj in link.Hosts:
subs.append(link)
elif hasattr(link,"Host") and Draft.getType(link) != "Rebar":
if link.Host == obj:
@@ -770,9 +770,10 @@ class Component(ArchIFC.IfcProduct):
if base:
subvolume = None
if (Draft.getType(o) == "Window") or (Draft.isClone(o,"Window",True)):
# windows can be additions or subtractions, treated the same way
subvolume = o.Proxy.getSubVolume(o)
if (Draft.getType(o.getLinkedObject()) == "Window") or (Draft.isClone(o,"Window",True)):
# windows can be additions or subtractions, treated the same way
subvolume = o.getLinkedObject().Proxy.getSubVolume(o)
elif (Draft.getType(o) == "Roof") or (Draft.isClone(o,"Roof")):
# roofs define their own special subtraction volume
subvolume = o.Proxy.getSubVolume(o)
@@ -1119,14 +1120,15 @@ class Component(ArchIFC.IfcProduct):
"""
hosts = []
for link in obj.InListRecursive:
if hasattr(link,"Host"):
if link.Host:
if link.Host == obj:
hosts.append(link)
elif hasattr(link,"Hosts"):
for host in link.Hosts:
if host == obj:
if link.Hosts:
if obj in link.Hosts:
hosts.append(link)
return hosts
+1 -1
View File
@@ -951,7 +951,7 @@ class PanelCut(Draft._DraftObject):
obj.addProperty("App::PropertyAngle","TagRotation","PanelCut",QT_TRANSLATE_NOOP("App::Property","The rotation of the tag text"))
if not "FontFile" in pl:
obj.addProperty("App::PropertyFile","FontFile","PanelCut",QT_TRANSLATE_NOOP("App::Property","The font of the tag text"))
obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile",QT_TRANSLATE_NOOP("App::Property","The font file"))
obj.FontFile = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetString("FontFile","")
if not "MakeFace" in pl:
obj.addProperty("App::PropertyBool","MakeFace","PanelCut",QT_TRANSLATE_NOOP("App::Property","If True, the object is rendered as a face, if possible."))
if not "AllowedAngles" in pl:
+3 -2
View File
@@ -438,8 +438,9 @@ class _Roof(ArchComponent.Component):
rel = profilCurr["idrel"]
if i != rel and 0 <= rel < numEdges:
profilRel = self.profilsDico[rel]
# do not use data from the relative profile if it in turn references a relative profile:
if 0 <= profilRel["idrel"] < numEdges:
# do not use data from the relative profile if it in turn references a relative profile
# other than itself:
if 0 <= profilRel["idrel"] < numEdges and rel != profilRel["idrel"]:
hgt = self.calcHeight(i)
profilCurr["height"] = hgt
elif ang == 0.0 and run == 0.0:
+1 -1
View File
@@ -220,7 +220,7 @@ class _ArchSchedule:
prop = args[0].upper()
fval = args[1].upper()
if prop == "TYPE":
prop == "IFCTYPE"
prop = "IFCTYPE"
if inv:
if prop in props:
csprop = o.PropertiesList[props.index(prop)]
+5 -1
View File
@@ -122,9 +122,13 @@ class Line(gui_base_original.Creator):
if not self.isWire and len(self.node) == 2:
self.finish(False, cont=True)
if len(self.node) > 2:
# The wire is closed
if (self.point - self.node[0]).Length < utils.tolerance():
self.undolast()
self.finish(True, cont=True)
if len(self.node) > 2:
self.finish(True, cont=True)
else:
self.finish(False, cont=True)
def finish(self, closed=False, cont=False):
"""Terminate the operation and close the polyline if asked.
+20 -11
View File
@@ -57,6 +57,7 @@ __title__ = "FreeCAD Draft Snap tools"
__author__ = "Yorik van Havre"
__url__ = "https://www.freecadweb.org"
UNSNAPPABLES = ('Image::ImagePlane',)
class Snapper:
"""Classes to manage snapping in Draft and Arch.
@@ -125,7 +126,7 @@ class Snapper:
# snap keys, it's important that they are in this order for
# saving in preferences and for properly restoring the toolbar
self.snaps = ['Lock', # 0
self.snaps = ['Lock', # 0
'Near', # 1 former "passive" snap
'Extension', # 2
'Parallel', # 3
@@ -311,6 +312,8 @@ class Snapper:
point, eline = self.snapToExtensions(point, lastpoint,
constrain, eline)
# Check if we have an object under the cursor and try to
# snap to it
_view = Draft.get3DView()
objectsUnderCursor = _view.getObjectsInfo((screenpos[0], screenpos[1]))
if objectsUnderCursor:
@@ -319,8 +322,10 @@ class Snapper:
self.snapInfo = objectsUnderCursor[self.snapObjectIndex]
if self.snapInfo and "Component" in self.snapInfo:
return self.snapToObject(lastpoint, active, constrain,
osnap = self.snapToObject(lastpoint, active, constrain,
eline, point, oldActive)
if osnap:
return osnap
# Nothing has been snapped.
# Check for grid snap and ext crossings
@@ -352,6 +357,7 @@ class Snapper:
def snapToObject(self, lastpoint, active, constrain,
eline, point, oldActive):
"""Snap to an object."""
parent = self.snapInfo.get('ParentObject', None)
if parent:
subname = self.snapInfo['SubName']
@@ -368,6 +374,9 @@ class Snapper:
snaps = []
self.lastSnappedObject = obj
if obj and (Draft.getType(obj) in UNSNAPPABLES):
return []
if hasattr(obj.ViewObject, "Selectable"):
if not obj.ViewObject.Selectable:
self.spoint = self.cstr(lastpoint, constrain, point)
@@ -609,9 +618,9 @@ class Snapper:
self.setCursor(tsnap[1])
return tsnap[2], eline
for o in (self.lastObj[1], self.lastObj[0]):
if o and (self.isEnabled('Extension')
or self.isEnabled('Parallel')):
for o in (self.lastObj[1], self.lastObj[0]):
if o and (self.isEnabled('Extension')
or self.isEnabled('Parallel')):
ob = App.ActiveDocument.getObject(o)
if not ob:
continue
@@ -1480,8 +1489,8 @@ class Snapper:
Parameters:
commands Snap command list,
use: get_draft_snap_commands():
context The toolbar or action group the buttons have
to be added to
context The toolbar or action group the buttons have
to be added to
button_suffix The suffix that have to be applied to the command name
to define the button name
"""
@@ -1492,7 +1501,7 @@ class Snapper:
gb = self.init_grid_button(self.toolbar)
context.addAction(gb)
QtCore.QObject.connect(gb, QtCore.SIGNAL("triggered()"),
lambda f=Gui.doCommand,
lambda f=Gui.doCommand,
arg='Gui.runCommand("Draft_ToggleGrid")':f(arg))
continue
# setup toolbar buttons
@@ -1508,7 +1517,7 @@ class Snapper:
context.addAction(b)
QtCore.QObject.connect(b,
QtCore.SIGNAL("triggered()"),
lambda f=Gui.doCommand,
lambda f=Gui.doCommand,
arg=command:f(arg))
for b in context.actions():
@@ -1520,7 +1529,7 @@ class Snapper:
"""Add grid button to the given toolbar"""
b = QtGui.QAction(context)
b.setIcon(QtGui.QIcon.fromTheme("Draft", QtGui.QIcon(":/icons/"
"Draft_Grid.svg")))
"Draft_Grid.svg")))
b.setText(QtCore.QCoreApplication.translate("Draft_Snap", "Toggles Grid On/Off"))
b.setToolTip(QtCore.QCoreApplication.translate("Draft_Snap", "Toggle Draft Grid"))
b.setObjectName("Grid_Button")
@@ -1703,7 +1712,7 @@ class Snapper:
self.trackers[8].append(self.extLine2)
self.trackers[9].append(self.holdTracker)
self.activeview = v
if self.grid and (not self.forceGridOff):
self.grid.set()
+115 -3
View File
@@ -50,7 +50,7 @@
# include <SMESHDS_GroupBase.hxx>
# include <SMESHDS_Group.hxx>
# include <SMESHDS_Mesh.hxx>
# include <SMDS_PolyhedralVolumeOfNodes.hxx>
//# include <SMDS_PolyhedralVolumeOfNodes.hxx>
# include <SMDS_VolumeTool.hxx>
# include <StdMeshers_MaxLength.hxx>
# include <StdMeshers_LocalLength.hxx>
@@ -93,7 +93,9 @@ using namespace Fem;
using namespace Base;
using namespace boost;
#if SMESH_VERSION_MAJOR < 9
static int StatCount = 0;
#endif
SMESH_Gen* FemMesh::_mesh_gen = 0;
@@ -103,12 +105,20 @@ FemMesh::FemMesh()
{
//Base::Console().Log("FemMesh::FemMesh():%p (id=%i)\n",this,StatCount);
// create a mesh always with new StudyId to avoid overlapping destruction
#if SMESH_VERSION_MAJOR >= 9
myMesh = getGenerator()->CreateMesh(false);
#else
myMesh = getGenerator()->CreateMesh(StatCount++,false);
#endif
}
FemMesh::FemMesh(const FemMesh& mesh)
{
#if SMESH_VERSION_MAJOR >= 9
myMesh = getGenerator()->CreateMesh(false);
#else
myMesh = getGenerator()->CreateMesh(StatCount++,false);
#endif
copyMeshData(mesh);
}
@@ -130,7 +140,11 @@ FemMesh::~FemMesh()
FemMesh &FemMesh::operator=(const FemMesh& mesh)
{
if (this != &mesh) {
#if SMESH_VERSION_MAJOR >= 9
myMesh = getGenerator()->CreateMesh(true);
#else
myMesh = getGenerator()->CreateMesh(0,true);
#endif
copyMeshData(mesh);
}
return *this;
@@ -176,10 +190,17 @@ void FemMesh::copyMeshData(const FemMesh& mesh)
int ID = elem->GetID();
switch (elem->GetEntityType()) {
case SMDSEntity_Polyhedra:
#if SMESH_VERSION_MAJOR >= 9
editor.GetMeshDS()->
AddPolyhedralVolumeWithID(nodes,
static_cast<const SMDS_MeshVolume*>(elem)->GetQuantities(),
ID);
#else
editor.GetMeshDS()->
AddPolyhedralVolumeWithID(nodes,
static_cast<const SMDS_VtkVolume*>(elem)->GetQuantities(),
ID);
#endif
break;
case SMDSEntity_Ball:
{
@@ -239,7 +260,7 @@ void FemMesh::copyMeshData(const FemMesh& mesh)
// Make a new group
if (!groupElems.empty()) {
int aId;
int aId = -1;
SMESH_Group* newGroupObj = this->myMesh->AddGroup(groupType, group->GetName(), aId);
SMESHDS_Group* newGroupDS = dynamic_cast<SMESHDS_Group*>(newGroupObj->GetGroupDS());
if (newGroupDS) {
@@ -512,6 +533,41 @@ void FemMesh::setStandardHypotheses()
{
if (!hypoth.empty())
return;
#if SMESH_VERSION_MAJOR >= 9
int hyp=0;
SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, getGenerator()));
static_cast<StdMeshers_MaxLength*>(len.get())->SetLength(1.0);
hypoth.push_back(len);
SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, getGenerator()));
static_cast<StdMeshers_LocalLength*>(loc.get())->SetLength(1.0);
hypoth.push_back(loc);
SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, getGenerator()));
static_cast<StdMeshers_MaxElementArea*>(area.get())->SetMaxArea(1.0);
hypoth.push_back(area);
SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, getGenerator()));
static_cast<StdMeshers_NumberOfSegments*>(segm.get())->SetNumberOfSegments(1);
hypoth.push_back(segm);
SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, getGenerator()));
static_cast<StdMeshers_Deflection1D*>(defl.get())->SetDeflection(0.01);
hypoth.push_back(defl);
SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, getGenerator()));
hypoth.push_back(reg);
//SMESH_HypothesisPtr sel(new StdMeshers_StartEndLength(hyp++, getGenerator()));
//static_cast<StdMeshers_StartEndLength*>(sel.get())->SetLength(1.0, true);
//hypoth.push_back(sel);
SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,getGenerator()));
hypoth.push_back(qdp);
SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,getGenerator()));
hypoth.push_back(q2d);
#else
int hyp=0;
SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, getGenerator()));
static_cast<StdMeshers_MaxLength*>(len.get())->SetLength(1.0);
@@ -545,6 +601,7 @@ void FemMesh::setStandardHypotheses()
SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,getGenerator()));
hypoth.push_back(q2d);
#endif
// Apply hypothesis
for (int i=0; i<hyp;i++)
@@ -572,10 +629,60 @@ std::set<long> FemMesh::getSurfaceNodes(long /*ElemId*/, short /*FaceId*/, float
*/
std::list<std::pair<int, int> > FemMesh::getVolumesByFace(const TopoDS_Face &face) const
{
//TODO: This function is broken with SMESH7 as it is impossible to iterate volume faces
std::list<std::pair<int, int> > result;
std::set<int> nodes_on_face = getNodesByFace(face);
#if SMESH_VERSION_MAJOR >= 7
// SMDS_MeshVolume::facesIterator() is broken with SMESH7 as it is impossible to iterate volume faces
// In SMESH9 this function has been removed
//
std::map< int, std::set<int> > face_nodes;
// get faces that contribute to 'nodes_on_face' with all of its nodes
SMDS_FaceIteratorPtr face_iter = myMesh->GetMeshDS()->facesIterator();
while (face_iter && face_iter->more()) {
const SMDS_MeshFace* face = face_iter->next();
SMDS_NodeIteratorPtr node_iter = face->nodeIterator();
// all nodes of the current face must be part of 'nodes_on_face'
std::set<int> node_ids;
while (node_iter && node_iter->more()) {
const SMDS_MeshNode* node = node_iter->next();
node_ids.insert(node->GetID());
}
std::vector<int> element_face_nodes;
std::set_intersection(nodes_on_face.begin(), nodes_on_face.end(), node_ids.begin(), node_ids.end(),
std::back_insert_iterator<std::vector<int> >(element_face_nodes));
if (element_face_nodes.size() == node_ids.size()) {
face_nodes[face->GetID()] = node_ids;
}
}
// get all nodes of a volume and check which faces contribute to it with all of its nodes
SMDS_VolumeIteratorPtr vol_iter = myMesh->GetMeshDS()->volumesIterator();
while (vol_iter->more()) {
const SMDS_MeshVolume* vol = vol_iter->next();
SMDS_NodeIteratorPtr node_iter = vol->nodeIterator();
std::set<int> node_ids;
while (node_iter && node_iter->more()) {
const SMDS_MeshNode* node = node_iter->next();
node_ids.insert(node->GetID());
}
for (const auto& it : face_nodes) {
std::vector<int> element_face_nodes;
std::set_intersection(node_ids.begin(), node_ids.end(), it.second.begin(), it.second.end(),
std::back_insert_iterator<std::vector<int> >(element_face_nodes));
// For curved faces it is possible that a volume contributes more than one face
if (element_face_nodes.size() == it.second.size()) {
result.emplace_back(vol->GetID(), it.first);
}
}
}
#else
SMDS_VolumeIteratorPtr vol_iter = myMesh->GetMeshDS()->volumesIterator();
while (vol_iter->more()) {
const SMDS_MeshVolume* vol = vol_iter->next();
@@ -600,6 +707,7 @@ std::list<std::pair<int, int> > FemMesh::getVolumesByFace(const TopoDS_Face &fac
}
}
}
#endif
result.sort();
return result;
@@ -2085,7 +2193,11 @@ int FemMesh::addGroup(const std::string TypeString, const std::string Name, cons
SMESH_Group* group = this->getSMesh()->AddGroup(mapping[TypeString], Name.c_str(), aId);
if (!group)
throw std::runtime_error("AddGroup: Failed to create new group.");
#if SMESH_VERSION_MAJOR >= 9
return group->GetID();
#else
return aId;
#endif
}
void FemMesh::addGroupElements(int GroupId, const std::set<int>& ElementIds)
+5 -1
View File
@@ -22,13 +22,13 @@
#include "PreCompiled.h"
#include <SMESH_Version.h>
#ifndef _PreComp_
# include <Python.h>
# include <SMESH_Gen.hxx>
# include <SMESHDS_Mesh.hxx>
# include <SMESH_Mesh.hxx>
# include <SMDS_PolyhedralVolumeOfNodes.hxx>
# include <SMDS_VolumeTool.hxx>
# include <BRepBuilderAPI_Copy.hxx>
@@ -83,7 +83,11 @@ App::DocumentObjectExecReturn *FemMeshShapeNetgenObject::execute(void)
TopoDS_Shape shape = feat->Shape.getValue();
NETGENPlugin_Mesher myNetGenMesher(newMesh.getSMesh(),shape,true);
#if SMESH_VERSION_MAJOR >= 9
NETGENPlugin_Hypothesis* tet= new NETGENPlugin_Hypothesis(0,newMesh.getGenerator());
#else
NETGENPlugin_Hypothesis* tet= new NETGENPlugin_Hypothesis(0,1,newMesh.getGenerator());
#endif
tet->SetMaxSize(MaxSize.getValue());
tet->SetSecondOrder(SecondOrder.getValue());
tet->SetOptimize(Optimize.getValue());
+32 -1
View File
@@ -22,12 +22,12 @@
#include "PreCompiled.h"
#include <SMESH_Version.h>
#ifndef _PreComp_
# include <Python.h>
# include <SMESH_Gen.hxx>
# include <SMESH_Mesh.hxx>
# include <SMDS_PolyhedralVolumeOfNodes.hxx>
# include <SMDS_VolumeTool.hxx>
# include <StdMeshers_Arithmetic1D.hxx>
# include <StdMeshers_AutomaticLength.hxx>
@@ -147,6 +147,36 @@ App::DocumentObjectExecReturn *FemMeshShapeObject::execute(void)
newMesh.compute();
#endif
#if 1 // Surface quad mesh
#if SMESH_VERSION_MAJOR >= 9
SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, myGen));
static_cast<StdMeshers_MaxLength*>(len.get())->SetLength(1.0);
newMesh.addHypothesis(shape, len);
SMESH_HypothesisPtr loc(new StdMeshers_LocalLength(hyp++, myGen));
static_cast<StdMeshers_LocalLength*>(loc.get())->SetLength(1.0);
newMesh.addHypothesis(shape, loc);
SMESH_HypothesisPtr area(new StdMeshers_MaxElementArea(hyp++, myGen));
static_cast<StdMeshers_MaxElementArea*>(area.get())->SetMaxArea(1.0);
newMesh.addHypothesis(shape, area);
SMESH_HypothesisPtr segm(new StdMeshers_NumberOfSegments(hyp++, myGen));
static_cast<StdMeshers_NumberOfSegments*>(segm.get())->SetNumberOfSegments(1);
newMesh.addHypothesis(shape, segm);
SMESH_HypothesisPtr defl(new StdMeshers_Deflection1D(hyp++, myGen));
static_cast<StdMeshers_Deflection1D*>(defl.get())->SetDeflection(0.01);
newMesh.addHypothesis(shape, defl);
SMESH_HypothesisPtr reg(new StdMeshers_Regular_1D(hyp++, myGen));
newMesh.addHypothesis(shape, reg);
SMESH_HypothesisPtr qdp(new StdMeshers_QuadranglePreference(hyp++,myGen));
newMesh.addHypothesis(shape, qdp);
SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,myGen));
newMesh.addHypothesis(shape, q2d);
#else
SMESH_HypothesisPtr len(new StdMeshers_MaxLength(hyp++, 1, myGen));
static_cast<StdMeshers_MaxLength*>(len.get())->SetLength(1.0);
newMesh.addHypothesis(shape, len);
@@ -179,6 +209,7 @@ App::DocumentObjectExecReturn *FemMeshShapeObject::execute(void)
SMESH_HypothesisPtr q2d(new StdMeshers_Quadrangle_2D(hyp++,1,myGen));
newMesh.addHypothesis(shape, q2d);
#endif
// create mesh
newMesh.compute();
-1
View File
@@ -44,7 +44,6 @@
# include <SMESH_Gen.hxx>
# include <SMESH_Mesh.hxx>
# include <SMDS_PolyhedralVolumeOfNodes.hxx>
# include <SMDS_VolumeTool.hxx>
# include <SMESHDS_Mesh.hxx>
+228
View File
@@ -223,7 +223,11 @@ PyObject *SMESH_HypothesisPy<T>::PyMake(struct _typeobject * /*type*/, PyObject
if (!PyArg_ParseTuple(args, "iO!",&hypId,&(FemMeshPy::Type),&obj))
return 0;
FemMesh* mesh = static_cast<FemMeshPy*>(obj)->getFemMeshPtr();
#if SMESH_VERSION_MAJOR >= 9
return new T(hypId, mesh->getGenerator());
#else
return new T(hypId, 1, mesh->getGenerator());
#endif
}
// ---------------------------------------------------------------------------
@@ -238,10 +242,17 @@ void StdMeshers_Arithmetic1DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Arithmetic1DPy::StdMeshers_Arithmetic1DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Arithmetic1D(hypId, gen))
{
}
#else
StdMeshers_Arithmetic1DPy::StdMeshers_Arithmetic1DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Arithmetic1D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Arithmetic1DPy::~StdMeshers_Arithmetic1DPy()
{
@@ -276,10 +287,17 @@ void StdMeshers_AutomaticLengthPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_AutomaticLengthPy::StdMeshers_AutomaticLengthPy(int /*hypId*/, SMESH_Gen* /*gen*/)
: SMESH_HypothesisPyBase(0)
{
}
#else
StdMeshers_AutomaticLengthPy::StdMeshers_AutomaticLengthPy(int /*hypId*/, int /*studyId*/, SMESH_Gen* /*gen*/)
: SMESH_HypothesisPyBase(0)
{
}
#endif
StdMeshers_AutomaticLengthPy::~StdMeshers_AutomaticLengthPy()
{
@@ -338,10 +356,17 @@ void StdMeshers_NotConformAllowedPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_NotConformAllowedPy::StdMeshers_NotConformAllowedPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_NotConformAllowed(hypId, gen))
{
}
#else
StdMeshers_NotConformAllowedPy::StdMeshers_NotConformAllowedPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_NotConformAllowed(hypId, studyId, gen))
{
}
#endif
StdMeshers_NotConformAllowedPy::~StdMeshers_NotConformAllowedPy()
{
@@ -364,10 +389,17 @@ void StdMeshers_MaxLengthPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_MaxLengthPy::StdMeshers_MaxLengthPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MaxLength(hypId, gen))
{
}
#else
StdMeshers_MaxLengthPy::StdMeshers_MaxLengthPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MaxLength(hypId, studyId, gen))
{
}
#endif
StdMeshers_MaxLengthPy::~StdMeshers_MaxLengthPy()
{
@@ -433,10 +465,17 @@ void StdMeshers_LocalLengthPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_LocalLengthPy::StdMeshers_LocalLengthPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_LocalLength(hypId, gen))
{
}
#else
StdMeshers_LocalLengthPy::StdMeshers_LocalLengthPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_LocalLength(hypId, studyId, gen))
{
}
#endif
StdMeshers_LocalLengthPy::~StdMeshers_LocalLengthPy()
{
@@ -480,10 +519,17 @@ void StdMeshers_MaxElementAreaPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_MaxElementAreaPy::StdMeshers_MaxElementAreaPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MaxElementArea(hypId, gen))
{
}
#else
StdMeshers_MaxElementAreaPy::StdMeshers_MaxElementAreaPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MaxElementArea(hypId, studyId, gen))
{
}
#endif
StdMeshers_MaxElementAreaPy::~StdMeshers_MaxElementAreaPy()
{
@@ -511,10 +557,17 @@ void StdMeshers_QuadranglePreferencePy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_QuadranglePreferencePy::StdMeshers_QuadranglePreferencePy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_QuadranglePreference(hypId, gen))
{
}
#else
StdMeshers_QuadranglePreferencePy::StdMeshers_QuadranglePreferencePy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_QuadranglePreference(hypId, studyId, gen))
{
}
#endif
StdMeshers_QuadranglePreferencePy::~StdMeshers_QuadranglePreferencePy()
{
@@ -529,10 +582,17 @@ void StdMeshers_Quadrangle_2DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Quadrangle_2DPy::StdMeshers_Quadrangle_2DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Quadrangle_2D(hypId, gen))
{
}
#else
StdMeshers_Quadrangle_2DPy::StdMeshers_Quadrangle_2DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Quadrangle_2D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Quadrangle_2DPy::~StdMeshers_Quadrangle_2DPy()
{
@@ -547,10 +607,17 @@ void StdMeshers_Regular_1DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Regular_1DPy::StdMeshers_Regular_1DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Regular_1D(hypId, gen))
{
}
#else
StdMeshers_Regular_1DPy::StdMeshers_Regular_1DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Regular_1D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Regular_1DPy::~StdMeshers_Regular_1DPy()
{
@@ -565,10 +632,17 @@ void StdMeshers_UseExisting_1DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_UseExisting_1DPy::StdMeshers_UseExisting_1DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_UseExisting_1D(hypId, gen))
{
}
#else
StdMeshers_UseExisting_1DPy::StdMeshers_UseExisting_1DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_UseExisting_1D(hypId, studyId, gen))
{
}
#endif
StdMeshers_UseExisting_1DPy::~StdMeshers_UseExisting_1DPy()
{
@@ -583,10 +657,17 @@ void StdMeshers_UseExisting_2DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_UseExisting_2DPy::StdMeshers_UseExisting_2DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_UseExisting_2D(hypId, gen))
{
}
#else
StdMeshers_UseExisting_2DPy::StdMeshers_UseExisting_2DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_UseExisting_2D(hypId, studyId, gen))
{
}
#endif
StdMeshers_UseExisting_2DPy::~StdMeshers_UseExisting_2DPy()
{
@@ -601,10 +682,17 @@ void StdMeshers_CompositeSegment_1DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_CompositeSegment_1DPy::StdMeshers_CompositeSegment_1DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_CompositeSegment_1D(hypId, gen))
{
}
#else
StdMeshers_CompositeSegment_1DPy::StdMeshers_CompositeSegment_1DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_CompositeSegment_1D(hypId, studyId, gen))
{
}
#endif
StdMeshers_CompositeSegment_1DPy::~StdMeshers_CompositeSegment_1DPy()
{
@@ -621,10 +709,17 @@ void StdMeshers_Deflection1DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Deflection1DPy::StdMeshers_Deflection1DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Deflection1D(hypId, gen))
{
}
#else
StdMeshers_Deflection1DPy::StdMeshers_Deflection1DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Deflection1D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Deflection1DPy::~StdMeshers_Deflection1DPy()
{
@@ -646,10 +741,17 @@ void StdMeshers_Hexa_3DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Hexa_3DPy::StdMeshers_Hexa_3DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Hexa_3D(hypId, gen))
{
}
#else
StdMeshers_Hexa_3DPy::StdMeshers_Hexa_3DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Hexa_3D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Hexa_3DPy::~StdMeshers_Hexa_3DPy()
{
@@ -686,10 +788,17 @@ void StdMeshers_StartEndLengthPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_StartEndLengthPy::StdMeshers_StartEndLengthPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_StartEndLength(hypId, gen))
{
}
#else
StdMeshers_StartEndLengthPy::StdMeshers_StartEndLengthPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_StartEndLength(hypId, studyId, gen))
{
}
#endif
StdMeshers_StartEndLengthPy::~StdMeshers_StartEndLengthPy()
{
@@ -717,10 +826,17 @@ void StdMeshers_SegmentLengthAroundVertexPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_SegmentLengthAroundVertexPy::StdMeshers_SegmentLengthAroundVertexPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_SegmentLengthAroundVertex(hypId, gen))
{
}
#else
StdMeshers_SegmentLengthAroundVertexPy::StdMeshers_SegmentLengthAroundVertexPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_SegmentLengthAroundVertex(hypId, studyId, gen))
{
}
#endif
StdMeshers_SegmentLengthAroundVertexPy::~StdMeshers_SegmentLengthAroundVertexPy()
{
@@ -748,10 +864,17 @@ void StdMeshers_SegmentAroundVertex_0DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_SegmentAroundVertex_0DPy::StdMeshers_SegmentAroundVertex_0DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_SegmentAroundVertex_0D(hypId, gen))
{
}
#else
StdMeshers_SegmentAroundVertex_0DPy::StdMeshers_SegmentAroundVertex_0DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_SegmentAroundVertex_0D(hypId, studyId, gen))
{
}
#endif
StdMeshers_SegmentAroundVertex_0DPy::~StdMeshers_SegmentAroundVertex_0DPy()
{
@@ -766,10 +889,17 @@ void StdMeshers_RadialPrism_3DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_RadialPrism_3DPy::StdMeshers_RadialPrism_3DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_RadialPrism_3D(hypId, gen))
{
}
#else
StdMeshers_RadialPrism_3DPy::StdMeshers_RadialPrism_3DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_RadialPrism_3D(hypId, studyId, gen))
{
}
#endif
StdMeshers_RadialPrism_3DPy::~StdMeshers_RadialPrism_3DPy()
{
@@ -784,10 +914,17 @@ void StdMeshers_QuadraticMeshPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_QuadraticMeshPy::StdMeshers_QuadraticMeshPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_QuadraticMesh(hypId, gen))
{
}
#else
StdMeshers_QuadraticMeshPy::StdMeshers_QuadraticMeshPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_QuadraticMesh(hypId, studyId, gen))
{
}
#endif
StdMeshers_QuadraticMeshPy::~StdMeshers_QuadraticMeshPy()
{
@@ -802,10 +939,17 @@ void StdMeshers_ProjectionSource3DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_ProjectionSource3DPy::StdMeshers_ProjectionSource3DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource3D(hypId, gen))
{
}
#else
StdMeshers_ProjectionSource3DPy::StdMeshers_ProjectionSource3DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource3D(hypId, studyId, gen))
{
}
#endif
StdMeshers_ProjectionSource3DPy::~StdMeshers_ProjectionSource3DPy()
{
@@ -820,10 +964,17 @@ void StdMeshers_ProjectionSource2DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_ProjectionSource2DPy::StdMeshers_ProjectionSource2DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource2D(hypId, gen))
{
}
#else
StdMeshers_ProjectionSource2DPy::StdMeshers_ProjectionSource2DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource2D(hypId, studyId, gen))
{
}
#endif
StdMeshers_ProjectionSource2DPy::~StdMeshers_ProjectionSource2DPy()
{
@@ -838,10 +989,17 @@ void StdMeshers_ProjectionSource1DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_ProjectionSource1DPy::StdMeshers_ProjectionSource1DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource1D(hypId, gen))
{
}
#else
StdMeshers_ProjectionSource1DPy::StdMeshers_ProjectionSource1DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource1D(hypId, studyId, gen))
{
}
#endif
StdMeshers_ProjectionSource1DPy::~StdMeshers_ProjectionSource1DPy()
{
@@ -856,10 +1014,17 @@ void StdMeshers_Projection_3DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Projection_3DPy::StdMeshers_Projection_3DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Projection_3D(hypId, gen))
{
}
#else
StdMeshers_Projection_3DPy::StdMeshers_Projection_3DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Projection_3D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Projection_3DPy::~StdMeshers_Projection_3DPy()
{
@@ -874,10 +1039,17 @@ void StdMeshers_Projection_2DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Projection_2DPy::StdMeshers_Projection_2DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Projection_2D(hypId, gen))
{
}
#else
StdMeshers_Projection_2DPy::StdMeshers_Projection_2DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Projection_2D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Projection_2DPy::~StdMeshers_Projection_2DPy()
{
@@ -892,10 +1064,17 @@ void StdMeshers_Projection_1DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Projection_1DPy::StdMeshers_Projection_1DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Projection_1D(hypId, gen))
{
}
#else
StdMeshers_Projection_1DPy::StdMeshers_Projection_1DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Projection_1D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Projection_1DPy::~StdMeshers_Projection_1DPy()
{
@@ -910,10 +1089,17 @@ void StdMeshers_Prism_3DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Prism_3DPy::StdMeshers_Prism_3DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Prism_3D(hypId, gen))
{
}
#else
StdMeshers_Prism_3DPy::StdMeshers_Prism_3DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_Prism_3D(hypId, studyId, gen))
{
}
#endif
StdMeshers_Prism_3DPy::~StdMeshers_Prism_3DPy()
{
@@ -930,10 +1116,17 @@ void StdMeshers_NumberOfSegmentsPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_NumberOfSegmentsPy::StdMeshers_NumberOfSegmentsPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_NumberOfSegments(hypId, gen))
{
}
#else
StdMeshers_NumberOfSegmentsPy::StdMeshers_NumberOfSegmentsPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_NumberOfSegments(hypId, studyId, gen))
{
}
#endif
StdMeshers_NumberOfSegmentsPy::~StdMeshers_NumberOfSegmentsPy()
{
@@ -967,10 +1160,17 @@ void StdMeshers_NumberOfLayersPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_NumberOfLayersPy::StdMeshers_NumberOfLayersPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_NumberOfLayers(hypId, gen))
{
}
#else
StdMeshers_NumberOfLayersPy::StdMeshers_NumberOfLayersPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_NumberOfLayers(hypId, studyId, gen))
{
}
#endif
StdMeshers_NumberOfLayersPy::~StdMeshers_NumberOfLayersPy()
{
@@ -1002,10 +1202,17 @@ void StdMeshers_MEFISTO_2DPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_MEFISTO_2DPy::StdMeshers_MEFISTO_2DPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MEFISTO_2D(hypId, gen))
{
}
#else
StdMeshers_MEFISTO_2DPy::StdMeshers_MEFISTO_2DPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MEFISTO_2D(hypId, studyId, gen))
{
}
#endif
StdMeshers_MEFISTO_2DPy::~StdMeshers_MEFISTO_2DPy()
{
@@ -1022,10 +1229,17 @@ void StdMeshers_MaxElementVolumePy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_MaxElementVolumePy::StdMeshers_MaxElementVolumePy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MaxElementVolume(hypId, gen))
{
}
#else
StdMeshers_MaxElementVolumePy::StdMeshers_MaxElementVolumePy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_MaxElementVolume(hypId, studyId, gen))
{
}
#endif
StdMeshers_MaxElementVolumePy::~StdMeshers_MaxElementVolumePy()
{
@@ -1055,10 +1269,17 @@ void StdMeshers_LengthFromEdgesPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_LengthFromEdgesPy::StdMeshers_LengthFromEdgesPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_LengthFromEdges(hypId, gen))
{
}
#else
StdMeshers_LengthFromEdgesPy::StdMeshers_LengthFromEdgesPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_LengthFromEdges(hypId, studyId, gen))
{
}
#endif
StdMeshers_LengthFromEdgesPy::~StdMeshers_LengthFromEdgesPy()
{
@@ -1096,10 +1317,17 @@ void StdMeshers_LayerDistributionPy::init_type(PyObject* module)
SMESH_HypothesisPyBase::init_type(module);
}
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_LayerDistributionPy::StdMeshers_LayerDistributionPy(int hypId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_LayerDistribution(hypId, gen))
{
}
#else
StdMeshers_LayerDistributionPy::StdMeshers_LayerDistributionPy(int hypId, int studyId, SMESH_Gen* gen)
: SMESH_HypothesisPyBase(new StdMeshers_LayerDistribution(hypId, studyId, gen))
{
}
#endif
StdMeshers_LayerDistributionPy::~StdMeshers_LayerDistributionPy()
{
+297
View File
@@ -86,6 +86,302 @@ private:
boost::shared_ptr<SMESH_Hypothesis> hyp;
};
#if SMESH_VERSION_MAJOR >= 9
class StdMeshers_Arithmetic1DPy : public SMESH_HypothesisPy<StdMeshers_Arithmetic1DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Arithmetic1DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Arithmetic1DPy();
Py::Object setLength(const Py::Tuple& args);
Py::Object getLength(const Py::Tuple& args);
};
class StdMeshers_AutomaticLengthPy : public SMESH_HypothesisPy<StdMeshers_AutomaticLengthPy>
{
public:
static void init_type(PyObject*);
StdMeshers_AutomaticLengthPy(int hypId, SMESH_Gen* gen);
~StdMeshers_AutomaticLengthPy();
Py::Object setFineness(const Py::Tuple& args);
Py::Object getFineness(const Py::Tuple& args);
Py::Object getLength(const Py::Tuple& args);
};
class StdMeshers_NotConformAllowedPy : public SMESH_HypothesisPy<StdMeshers_NotConformAllowedPy>
{
public:
static void init_type(PyObject*);
StdMeshers_NotConformAllowedPy(int hypId, SMESH_Gen* gen);
~StdMeshers_NotConformAllowedPy();
};
class StdMeshers_MaxLengthPy : public SMESH_HypothesisPy<StdMeshers_MaxLengthPy>
{
public:
static void init_type(PyObject*);
StdMeshers_MaxLengthPy(int hypId, SMESH_Gen* gen);
~StdMeshers_MaxLengthPy();
Py::Object setLength(const Py::Tuple& args);
Py::Object getLength(const Py::Tuple& args);
Py::Object havePreestimatedLength(const Py::Tuple& args);
Py::Object getPreestimatedLength(const Py::Tuple& args);
Py::Object setPreestimatedLength(const Py::Tuple& args);
Py::Object setUsePreestimatedLength(const Py::Tuple& args);
Py::Object getUsePreestimatedLength(const Py::Tuple& args);
};
class StdMeshers_LocalLengthPy : public SMESH_HypothesisPy<StdMeshers_LocalLengthPy>
{
public:
static void init_type(PyObject*);
StdMeshers_LocalLengthPy(int hypId, SMESH_Gen* gen);
~StdMeshers_LocalLengthPy();
Py::Object setLength(const Py::Tuple& args);
Py::Object getLength(const Py::Tuple& args);
Py::Object setPrecision(const Py::Tuple& args);
Py::Object getPrecision(const Py::Tuple& args);
};
class StdMeshers_MaxElementAreaPy : public SMESH_HypothesisPy<StdMeshers_MaxElementAreaPy>
{
public:
static void init_type(PyObject*);
StdMeshers_MaxElementAreaPy(int hypId, SMESH_Gen* gen);
~StdMeshers_MaxElementAreaPy();
Py::Object setMaxArea(const Py::Tuple& args);
Py::Object getMaxArea(const Py::Tuple& args);
};
class StdMeshers_QuadranglePreferencePy : public SMESH_HypothesisPy<StdMeshers_QuadranglePreferencePy>
{
public:
static void init_type(PyObject*);
StdMeshers_QuadranglePreferencePy(int hypId, SMESH_Gen* gen);
~StdMeshers_QuadranglePreferencePy();
};
class StdMeshers_Quadrangle_2DPy : public SMESH_HypothesisPy<StdMeshers_Quadrangle_2DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Quadrangle_2DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Quadrangle_2DPy();
};
class StdMeshers_Regular_1DPy : public SMESH_HypothesisPy<StdMeshers_Regular_1DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Regular_1DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Regular_1DPy();
};
class StdMeshers_UseExisting_1DPy : public SMESH_HypothesisPy<StdMeshers_UseExisting_1DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_UseExisting_1DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_UseExisting_1DPy();
};
class StdMeshers_UseExisting_2DPy : public SMESH_HypothesisPy<StdMeshers_UseExisting_2DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_UseExisting_2DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_UseExisting_2DPy();
};
class StdMeshers_CompositeSegment_1DPy : public SMESH_HypothesisPy<StdMeshers_CompositeSegment_1DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_CompositeSegment_1DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_CompositeSegment_1DPy();
};
class StdMeshers_Deflection1DPy : public SMESH_HypothesisPy<StdMeshers_Deflection1DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Deflection1DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Deflection1DPy();
Py::Object setDeflection(const Py::Tuple& args);
};
class StdMeshers_Hexa_3DPy : public SMESH_HypothesisPy<StdMeshers_Hexa_3DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Hexa_3DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Hexa_3DPy();
};
class StdMeshers_StartEndLengthPy : public SMESH_HypothesisPy<StdMeshers_StartEndLengthPy>
{
public:
static void init_type(PyObject*);
StdMeshers_StartEndLengthPy(int hypId, SMESH_Gen* gen);
~StdMeshers_StartEndLengthPy();
Py::Object setLength(const Py::Tuple& args);
Py::Object getLength(const Py::Tuple& args);
};
class StdMeshers_SegmentLengthAroundVertexPy : public SMESH_HypothesisPy<StdMeshers_SegmentLengthAroundVertexPy>
{
public:
static void init_type(PyObject*);
StdMeshers_SegmentLengthAroundVertexPy(int hypId, SMESH_Gen* gen);
~StdMeshers_SegmentLengthAroundVertexPy();
Py::Object setLength(const Py::Tuple& args);
Py::Object getLength(const Py::Tuple& args);
};
class StdMeshers_SegmentAroundVertex_0DPy : public SMESH_HypothesisPy<StdMeshers_SegmentAroundVertex_0DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_SegmentAroundVertex_0DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_SegmentAroundVertex_0DPy();
};
class StdMeshers_RadialPrism_3DPy : public SMESH_HypothesisPy<StdMeshers_RadialPrism_3DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_RadialPrism_3DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_RadialPrism_3DPy();
};
class StdMeshers_QuadraticMeshPy : public SMESH_HypothesisPy<StdMeshers_QuadraticMeshPy>
{
public:
static void init_type(PyObject*);
StdMeshers_QuadraticMeshPy(int hypId, SMESH_Gen* gen);
~StdMeshers_QuadraticMeshPy();
};
class StdMeshers_ProjectionSource3DPy : public SMESH_HypothesisPy<StdMeshers_ProjectionSource3DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_ProjectionSource3DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_ProjectionSource3DPy();
};
class StdMeshers_ProjectionSource2DPy : public SMESH_HypothesisPy<StdMeshers_ProjectionSource2DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_ProjectionSource2DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_ProjectionSource2DPy();
};
class StdMeshers_ProjectionSource1DPy : public SMESH_HypothesisPy<StdMeshers_ProjectionSource1DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_ProjectionSource1DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_ProjectionSource1DPy();
};
class StdMeshers_Projection_3DPy : public SMESH_HypothesisPy<StdMeshers_Projection_3DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Projection_3DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Projection_3DPy();
};
class StdMeshers_Projection_2DPy : public SMESH_HypothesisPy<StdMeshers_Projection_2DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Projection_2DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Projection_2DPy();
};
class StdMeshers_Projection_1DPy : public SMESH_HypothesisPy<StdMeshers_Projection_1DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Projection_1DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Projection_1DPy();
};
class StdMeshers_Prism_3DPy : public SMESH_HypothesisPy<StdMeshers_Prism_3DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_Prism_3DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_Prism_3DPy();
};
class StdMeshers_NumberOfSegmentsPy : public SMESH_HypothesisPy<StdMeshers_NumberOfSegmentsPy>
{
public:
static void init_type(PyObject*);
StdMeshers_NumberOfSegmentsPy(int hypId, SMESH_Gen* gen);
~StdMeshers_NumberOfSegmentsPy();
Py::Object setNumSegm(const Py::Tuple& args);
Py::Object getNumSegm(const Py::Tuple& args);
};
class StdMeshers_NumberOfLayersPy : public SMESH_HypothesisPy<StdMeshers_NumberOfLayersPy>
{
public:
static void init_type(PyObject*);
StdMeshers_NumberOfLayersPy(int hypId, SMESH_Gen* gen);
~StdMeshers_NumberOfLayersPy();
Py::Object setNumLayers(const Py::Tuple& args);
Py::Object getNumLayers(const Py::Tuple& args);
};
class StdMeshers_MEFISTO_2DPy : public SMESH_HypothesisPy<StdMeshers_MEFISTO_2DPy>
{
public:
static void init_type(PyObject*);
StdMeshers_MEFISTO_2DPy(int hypId, SMESH_Gen* gen);
~StdMeshers_MEFISTO_2DPy();
};
class StdMeshers_MaxElementVolumePy : public SMESH_HypothesisPy<StdMeshers_MaxElementVolumePy>
{
public:
static void init_type(PyObject*);
StdMeshers_MaxElementVolumePy(int hypId, SMESH_Gen* gen);
~StdMeshers_MaxElementVolumePy();
Py::Object setMaxVolume(const Py::Tuple& args);
Py::Object getMaxVolume(const Py::Tuple& args);
};
class StdMeshers_LengthFromEdgesPy : public SMESH_HypothesisPy<StdMeshers_LengthFromEdgesPy>
{
public:
static void init_type(PyObject*);
StdMeshers_LengthFromEdgesPy(int hypId, SMESH_Gen* gen);
~StdMeshers_LengthFromEdgesPy();
Py::Object setMode(const Py::Tuple& args);
Py::Object getMode(const Py::Tuple& args);
};
class StdMeshers_LayerDistributionPy : public SMESH_HypothesisPy<StdMeshers_LayerDistributionPy>
{
public:
static void init_type(PyObject*);
StdMeshers_LayerDistributionPy(int hypId, SMESH_Gen* gen);
~StdMeshers_LayerDistributionPy();
Py::Object setLayerDistribution(const Py::Tuple& args);
Py::Object getLayerDistribution(const Py::Tuple& args);
};
#else
class StdMeshers_Arithmetic1DPy : public SMESH_HypothesisPy<StdMeshers_Arithmetic1DPy>
{
public:
@@ -421,6 +717,7 @@ public:
Py::Object setLayerDistribution(const Py::Tuple& args);
Py::Object getLayerDistribution(const Py::Tuple& args);
};
#endif
} // namespace Fem
@@ -57,6 +57,11 @@
using namespace FemGui;
#ifdef VTK_CELL_ARRAY_V2
typedef const vtkIdType* vtkIdTypePtr;
#else
typedef vtkIdType* vtkIdTypePtr;
#endif
PROPERTY_SOURCE(FemGui::ViewProviderFemPostObject, Gui::ViewProviderDocumentObject)
@@ -317,7 +322,7 @@ void ViewProviderFemPostObject::update3D() {
vtkDataArray *tcoords = NULL;
vtkCellArray *cells;
vtkIdType npts = 0;
vtkIdType *indx = 0;
vtkIdTypePtr indx = 0;
points = pd->GetPoints();
pntData = pd->GetPointData();
+3
View File
@@ -1621,6 +1621,9 @@ def get_pressure_obj_faces(
# 0 if femmeshface normal == reference face normal direction
# -1 if femmeshface normal opposite reference face normal direction
# easy on plane faces, but on a half sphere ... ?!?
# might be useful to add ...
# How to find the orientation of a FEM mesh face?
# https://forum.freecadweb.org/viewtopic.php?f=18&t=51898
else:
FreeCAD.Console.PrintError(
"Pressure on shell mesh at the moment only "
+15 -5
View File
@@ -269,16 +269,26 @@ def getBoundBoxOfAllDocumentShapes(doc):
no objects at all return ``None``.
"""
overalboundbox = None
# netgen mesh obj has an attribute Shape which is an Document obj, which has no BB
# a FemMesh without a Shape could be clipped too
# https://forum.freecadweb.org/viewtopic.php?f=18&t=52920
for o in doc.Objects:
# netgen mesh obj has an attribute Shape which is an Document obj, which has no BB
bb = None
if hasattr(o, "Shape") and hasattr(o.Shape, "BoundBox"):
try:
bb = o.Shape.BoundBox
except Exception:
bb = None
if bb.isValid():
if not overalboundbox:
overalboundbox = bb
pass
elif hasattr(o, "FemMesh") and hasattr(o.FemMesh, "BoundBox"):
try:
bb = o.FemMesh.BoundBox
except Exception:
pass
if bb.isValid():
if not overalboundbox:
overalboundbox = bb
else:
overalboundbox.add(bb)
return overalboundbox
+15 -4
View File
@@ -209,10 +209,21 @@ void MeshSelection::prepareFreehandSelection(bool add,SoEventCallbackCB *cb)
freehand->setLineWidth(3.0f);
viewer->navigationStyle()->startSelection(freehand);
QBitmap cursor = QBitmap::fromData(QSize(CROSS_WIDTH, CROSS_HEIGHT), cross_bitmap);
QBitmap mask = QBitmap::fromData(QSize(CROSS_WIDTH, CROSS_HEIGHT), cross_mask_bitmap);
QCursor custom(cursor, mask, CROSS_HOT_X, CROSS_HOT_Y);
viewer->setComponentCursor(custom);
auto setComponentCursor = [=]() {
QBitmap cursor = QBitmap::fromData(QSize(CROSS_WIDTH, CROSS_HEIGHT), cross_bitmap);
QBitmap mask = QBitmap::fromData(QSize(CROSS_WIDTH, CROSS_HEIGHT), cross_mask_bitmap);
#if defined(Q_OS_WIN32)
double dpr = viewer->devicePixelRatio();
cursor.setDevicePixelRatio(dpr);
mask.setDevicePixelRatio(dpr);
#endif
QCursor custom(cursor, mask, CROSS_HOT_X, CROSS_HOT_Y);
viewer->setComponentCursor(custom);
};
#if (QT_VERSION >= 0x050000)
QObject::connect(viewer, &Gui::View3DInventorViewer::devicePixelRatioChanged, setComponentCursor);
#endif
setComponentCursor();
this->addToSelection = add;
}
}
+48
View File
@@ -334,7 +334,11 @@ Mesh::MeshObject* Mesher::createMesh() const
Mesher::_mesh_gen = new SMESH_Gen();
SMESH_Gen* meshgen = Mesher::_mesh_gen;
#if SMESH_VERSION_MAJOR >= 9
SMESH_Mesh* mesh = meshgen->CreateMesh(true);
#else
SMESH_Mesh* mesh = meshgen->CreateMesh(0, true);
#endif
int hyp=0;
@@ -342,7 +346,11 @@ Mesh::MeshObject* Mesher::createMesh() const
switch (method) {
#if defined (HAVE_NETGEN)
case Netgen: {
#if SMESH_VERSION_MAJOR >= 9
NETGENPlugin_Hypothesis_2D* hyp2d = new NETGENPlugin_Hypothesis_2D(hyp++,meshgen);
#else
NETGENPlugin_Hypothesis_2D* hyp2d = new NETGENPlugin_Hypothesis_2D(hyp++,0,meshgen);
#endif
if (fineness >=0 && fineness < 5) {
hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::Fineness(fineness));
@@ -367,58 +375,98 @@ Mesh::MeshObject* Mesher::createMesh() const
hyp2d->SetSecondOrder(secondOrder); // apply bisecting to create four triangles out of one
hypoth.push_back(hyp2d);
#if SMESH_VERSION_MAJOR >= 9
NETGENPlugin_NETGEN_2D* alg2d = new NETGENPlugin_NETGEN_2D(hyp++,meshgen);
#else
NETGENPlugin_NETGEN_2D* alg2d = new NETGENPlugin_NETGEN_2D(hyp++,0,meshgen);
#endif
hypoth.push_back(alg2d);
} break;
#endif
#if defined (HAVE_MEFISTO)
case Mefisto: {
if (maxLength > 0) {
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_MaxLength* hyp1d = new StdMeshers_MaxLength(hyp++, meshgen);
#else
StdMeshers_MaxLength* hyp1d = new StdMeshers_MaxLength(hyp++, 0, meshgen);
#endif
hyp1d->SetLength(maxLength);
hypoth.push_back(hyp1d);
}
else if (localLength > 0) {
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_LocalLength* hyp1d = new StdMeshers_LocalLength(hyp++,meshgen);
#else
StdMeshers_LocalLength* hyp1d = new StdMeshers_LocalLength(hyp++,0,meshgen);
#endif
hyp1d->SetLength(localLength);
hypoth.push_back(hyp1d);
}
else if (maxArea > 0) {
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_MaxElementArea* hyp2d = new StdMeshers_MaxElementArea(hyp++,meshgen);
#else
StdMeshers_MaxElementArea* hyp2d = new StdMeshers_MaxElementArea(hyp++,0,meshgen);
#endif
hyp2d->SetMaxArea(maxArea);
hypoth.push_back(hyp2d);
}
else if (deflection > 0) {
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Deflection1D* hyp1d = new StdMeshers_Deflection1D(hyp++,meshgen);
#else
StdMeshers_Deflection1D* hyp1d = new StdMeshers_Deflection1D(hyp++,0,meshgen);
#endif
hyp1d->SetDeflection(deflection);
hypoth.push_back(hyp1d);
}
else if (minLen > 0 && maxLen > 0) {
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Arithmetic1D* hyp1d = new StdMeshers_Arithmetic1D(hyp++,meshgen);
#else
StdMeshers_Arithmetic1D* hyp1d = new StdMeshers_Arithmetic1D(hyp++,0,meshgen);
#endif
hyp1d->SetLength(minLen, false);
hyp1d->SetLength(maxLen, true);
hypoth.push_back(hyp1d);
}
else {
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_AutomaticLength* hyp1d = new StdMeshers_AutomaticLength(hyp++,meshgen);
#else
StdMeshers_AutomaticLength* hyp1d = new StdMeshers_AutomaticLength(hyp++,0,meshgen);
#endif
hypoth.push_back(hyp1d);
}
{
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_NumberOfSegments* hyp1d = new StdMeshers_NumberOfSegments(hyp++,meshgen);
#else
StdMeshers_NumberOfSegments* hyp1d = new StdMeshers_NumberOfSegments(hyp++,0,meshgen);
#endif
hyp1d->SetNumberOfSegments(1);
hypoth.push_back(hyp1d);
}
if (regular) {
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_Regular_1D* hyp1d = new StdMeshers_Regular_1D(hyp++,meshgen);
#else
StdMeshers_Regular_1D* hyp1d = new StdMeshers_Regular_1D(hyp++,0,meshgen);
#endif
hypoth.push_back(hyp1d);
}
#if SMESH_VERSION_MAJOR < 7
StdMeshers_TrianglePreference* hyp2d_1 = new StdMeshers_TrianglePreference(hyp++,0,meshgen);
hypoth.push_back(hyp2d_1);
#endif
#if SMESH_VERSION_MAJOR >= 9
StdMeshers_MEFISTO_2D* alg2d = new StdMeshers_MEFISTO_2D(hyp++,meshgen);
#else
StdMeshers_MEFISTO_2D* alg2d = new StdMeshers_MEFISTO_2D(hyp++,0,meshgen);
#endif
hypoth.push_back(alg2d);
} break;
#endif
@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
@@ -8,82 +6,428 @@
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="68.26667"
height="68.26667"
viewBox="0 0 68.26667 68.26667"
sodipodi:docname="OpenSCAD_MirrorMeshFeature.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
width="64px"
height="64px"
id="svg3364"
version="1.1">
<title
id="title915">OpenSCAD_MirrorMeshFeature</title>
<defs
id="defs3366">
<linearGradient
id="linearGradient916">
<stop
id="stop912"
offset="0"
style="stop-color:#8ae234;stop-opacity:1" />
<stop
id="stop914"
offset="1"
style="stop-color:#4e9a06;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3885">
<stop
id="stop3887"
offset="0"
style="stop-color:#8ae234;stop-opacity:1" />
<stop
id="stop3889"
offset="1"
style="stop-color:#4e9a06;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3833">
<stop
style="stop-color:#729fcf;stop-opacity:1;"
offset="0"
id="stop3835" />
<stop
style="stop-color:#3465a4;stop-opacity:1"
offset="1"
id="stop3837" />
</linearGradient>
<linearGradient
id="linearGradient3864">
<stop
id="stop3866"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient3864"
id="radialGradient2571"
gradientUnits="userSpaceOnUse"
cx="342.58258"
cy="27.256668"
fx="342.58258"
fy="27.256668"
r="19.571428"
gradientTransform="matrix(1.6258409,0.5434973,-8.8819886e-2,0.2656996,-215.02413,-170.90186)" />
<radialGradient
xlink:href="#linearGradient3593"
id="radialGradient3352"
gradientUnits="userSpaceOnUse"
cx="345.28433"
cy="15.560534"
fx="345.28433"
fy="15.560534"
r="19.571428"
gradientTransform="translate(-0.1767767,-2.6516504)" />
<linearGradient
id="linearGradient3593">
<stop
style="stop-color:#c8e0f9;stop-opacity:1;"
offset="0"
id="stop3595" />
<stop
style="stop-color:#637dca;stop-opacity:1;"
offset="1"
id="stop3597" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient3593"
id="radialGradient3354"
gradientUnits="userSpaceOnUse"
cx="330.63791"
cy="39.962704"
fx="330.63791"
fy="39.962704"
r="19.571428"
gradientTransform="translate(-0.1767767,-2.6516504)" />
<radialGradient
xlink:href="#linearGradient3864"
id="radialGradient3369"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.6258409,0.5434973,-8.8819886e-2,0.2656996,-461.81066,-173.06271)"
cx="342.58258"
cy="27.256668"
fx="342.58258"
fy="27.256668"
r="19.571428" />
<linearGradient
id="linearGradient3864-4">
<stop
id="stop3866-5"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868-2"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.571428"
fy="113.23357"
fx="320.44025"
cy="113.23357"
cx="320.44025"
gradientTransform="matrix(0.9829174,1.3240854,-1.2330051,0.8105158,-138.75617,-494.52855)"
gradientUnits="userSpaceOnUse"
id="radialGradient3036"
xlink:href="#linearGradient3864-4" />
<radialGradient
xlink:href="#linearGradient3864-6"
id="radialGradient3007-9"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9829174,1.3240854,-1.2330051,0.8105158,-189.40979,-484.51702)"
cx="320.44025"
cy="113.23357"
fx="320.44025"
fy="113.23357"
r="19.571428" />
<linearGradient
id="linearGradient3864-6">
<stop
id="stop3866-0"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868-9"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient3864-1"
id="radialGradient3960"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.2993671,-0.01575726,0.0084161,0.9850979,-94.354208,-10.998387)"
cx="48.288067"
cy="46.74614"
fx="48.288067"
fy="46.74614"
r="19.571428" />
<linearGradient
id="linearGradient3864-1">
<stop
id="stop3866-9"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868-0"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.571428"
fy="32.799232"
fx="41.803806"
cy="32.799232"
cx="41.803806"
gradientTransform="matrix(-0.70352355,2.1948421,-1.0402627,-0.30894741,102.4266,-56.052881)"
gradientUnits="userSpaceOnUse"
id="radialGradient3986-4"
xlink:href="#linearGradient3864-1-9" />
<linearGradient
id="linearGradient3864-1-9">
<stop
id="stop3866-9-6"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868-0-6"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.571428"
fy="46.74614"
fx="48.288067"
cy="46.74614"
cx="48.288067"
gradientTransform="matrix(0.01575726,2.2993671,-0.9850979,0.0084161,52.182614,-97.493771)"
gradientUnits="userSpaceOnUse"
id="radialGradient4024"
xlink:href="#linearGradient3864-1-9" />
<radialGradient
xlink:href="#linearGradient3593-5"
id="radialGradient3966"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9327663,0,0,0.9327663,-298.15651,8.1913381)"
cx="330.63791"
cy="39.962704"
fx="330.63791"
fy="39.962704"
r="19.571428" />
<linearGradient
id="linearGradient3593-5">
<stop
style="stop-color:#c8e0f9;stop-opacity:1;"
offset="0"
id="stop3595-2" />
<stop
style="stop-color:#637dca;stop-opacity:1;"
offset="1"
id="stop3597-5" />
</linearGradient>
<radialGradient
r="19.571428"
fy="6.0560789"
fx="374.42535"
cy="6.0560789"
cx="374.42535"
gradientTransform="matrix(0.52013132,0.80077671,-0.81763607,0.49523365,-185.59014,-277.02153)"
gradientUnits="userSpaceOnUse"
id="radialGradient4061-4"
xlink:href="#linearGradient3593-5-4" />
<linearGradient
id="linearGradient3593-5-4">
<stop
style="stop-color:#c8e0f9;stop-opacity:1;"
offset="0"
id="stop3595-2-8" />
<stop
style="stop-color:#637dca;stop-opacity:1;"
offset="1"
id="stop3597-5-4" />
</linearGradient>
<radialGradient
r="19.571428"
fy="39.962704"
fx="330.63791"
cy="39.962704"
cx="330.63791"
gradientTransform="matrix(0.9327663,0,0,0.9327663,-302.00666,-27.942952)"
gradientUnits="userSpaceOnUse"
id="radialGradient4099"
xlink:href="#linearGradient3593-5-4" />
<linearGradient
id="linearGradient3864-1-9-2">
<stop
id="stop3866-9-6-6"
offset="0"
style="stop-color:#71b2f8;stop-opacity:1;" />
<stop
id="stop3868-0-6-8"
offset="1"
style="stop-color:#002795;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.571428"
fy="6.0560789"
fx="374.42535"
cy="6.0560789"
cx="374.42535"
gradientTransform="matrix(0.52013132,0.80077671,-0.81763607,0.49523365,-185.59014,-276.99255)"
gradientUnits="userSpaceOnUse"
id="radialGradient4061-4-8"
xlink:href="#linearGradient3593-5-4-9" />
<linearGradient
id="linearGradient3593-5-4-9">
<stop
style="stop-color:#c8e0f9;stop-opacity:1;"
offset="0"
id="stop3595-2-8-8" />
<stop
style="stop-color:#637dca;stop-opacity:1;"
offset="1"
id="stop3597-5-4-8" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3833"
id="linearGradient3839"
x1="90"
y1="17"
x2="93"
y2="47"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-40,60)" />
<linearGradient
xlink:href="#linearGradient3833-7"
id="linearGradient3839-6"
x1="90"
y1="17"
x2="93"
y2="47"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-40,60)" />
<linearGradient
id="linearGradient3833-7">
<stop
style="stop-color:#729fcf;stop-opacity:1;"
offset="0"
id="stop3835-5" />
<stop
style="stop-color:#3465a4;stop-opacity:1"
offset="1"
id="stop3837-3" />
</linearGradient>
<linearGradient
y2="42"
x2="86"
y1="17"
x1="90"
gradientTransform="matrix(-1,0,0,1,104,0)"
gradientUnits="userSpaceOnUse"
id="linearGradient3862"
xlink:href="#linearGradient3885" />
<linearGradient
xlink:href="#linearGradient916"
id="linearGradient3893"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-40)"
x1="90"
y1="17"
x2="93"
y2="47" />
</defs>
<metadata
id="metadata8">
id="metadata3369">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title>OpenSCAD_MirrorMeshFeature</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>Part_Mirror</dc:title>
<dc:date>2021/01/05</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier></dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title>Work based on a design made by [agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="790"
inkscape:window-height="480"
id="namedview4"
showgrid="false"
inkscape:zoom="3.4570311"
inkscape:cx="34.133335"
inkscape:cy="34.133335"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<image
width="68.26667"
height="68.26667"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI
WXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH5AcTFBQx1dILlgAABYNJREFUeNrtm21sU1UYx3+3L8B6
eWvXDl8m8y5S2lWNsBmnAR2GGUz0ywgmJIgviX5SRL5hhKCo7JOJ4ZPGSDAYEGFIBEKEiGaIxDA1
xrKxwS6DoEnbvTFueQnj+KG3deu6rmtv27ndJzkfes7u7vn/z/95zjnP04JpphXcfOD1wX4fXNXb
fh94izEXqRjggdOAM2moF6htg/ZCzsdSBNK3Ac56u53P7Ha2A4ti/U59bNLLv98HIuz1iojXK86A
+B6EL9b6Cz0fWxE4mA1gs1oTHa6kscnuAhPK8kGAVS5T1soepdXhUZpz/WcOj9Ise5RzcpmyFrBO
ZAISwBHsBHwSLDFgm1oCeBHslD1Kq9FEWPIAfIF7fsBwWVX4qgEWGE1ELgRYZnqUVbJHCcaBl5ZX
obWodB04NObDQm+Z2tmv9qG1qNz/YO1QIjocbuV1qLMVkoA48LMC9gILS8v9aC0qlw4ezuT5qwBX
QiF6QyEAepLG0llw5260FpUK/6MAiiTxqezpas+WCIsxwI+M553HAT7q7qazu5teYEfSWEaK2LXX
ECKkDIGvFLAVWAhQWl415mrL1QoAWliVcjkKyx5FAGgtatr3BV5azcW/Tsc/qkLQGI1UfAE/3s5W
ASlWvGo8Uk9pOsBaoAkY0FtTrveAuGvoMSJjRUhGrXimChivZaqAbBUhGQ18ohCQKREJF5jpUU7G
pe6eH2Dw+EBOUp8olnCNwGNDXeOHEZchAY/HmdZQmWwW/HLPUGUuNS9DJgEmASYBRSNgImWFLcUA
rx+FG4BZemsATheDhCmfFS4GAcsBNisKVYqCE3glaayQZmaFzV3AJMAkwCTAJGAKm61YLxZTmICr
wOwroRAOvWM8dYHJ4AKG1AX+zwrYCCz7HZxvDu/v1cdyspL+eSn7eub/aSwBtogrZf9td0/a59qg
3RerC2wD6vXuY8DGTOoCQwGmAjuj/64RUSYnAkYDao+4hgcyEesbWPrrmOTpQFdmQ7zz0sNpCRBA
Sd+8jAOuLR1wuw4+FdDkF9jDLnobjubdf6ZPsyOFXZT0zdPBlo2Yi+o4kXsMsIVdI1Y/DjTZCgE8
burCI3rZBpxNK8ARzM8uUNL6QIyEIS0Z/PWq8yPAP/LWO8g1lQBIscxPjucFcQpArqnkma0fGk58
1ttgb8NRbvjOD+srrVtMx8ndIERUkqT3rs2x1uU6wWi4tA7EeoQY+Pnbz/E8tZg1O/YOm8fcQPa7
eaJul1yDczatGBV4sikvrCR04bf4x0ODNt648Y/aZaT0He777pGwNSLxIkCFv4azu74ZHiBHmfPQ
eSfXLDOmLpXcqzdsQq6pjIPvAPGsFlafNxo8QDRy+W8toq6VxJ2nESLY1XoGuaaS+i3vDwM5Xrew
5CL3tp92JeSuzbE+pIUv5j0aXot0ndAipYvibnHqux0p3aL22qu5u0C+5K6nv7M6CGXrFqO5wKgE
JNvi9Rs51/x1/FTQAWJdNiuej2+Lz3RXLBNI25GkAJLEE8+9zLEtm1P+bVYxwPXkIs417wEMkbvh
dYFM3GLcLjCjz8Pdry0h1PmHodFd/0b47GavFwm42N5OD7BOvw63wZx87hYZKaB6wyasy2fFwRsd
3RN1AateGzCyLpDJbpFWAdMdc7kZ7QPQQPpAC5d8DMFbRkVxnx5EfvH7AbjQ2grAmv8uSgb+iiUw
TfZc3wDiXUCWZ7nQBnrSK+BmtA8B++4MWvxauLPRSPCFt+AtLdzZeGfQ4hewLw4+5WVIwElJCCcW
6e1oSD02mRKf13suXAZWyWVKPYJPBHSPICAaVpcyyU2LLWxVsVNiYyYpJntO0MwKw8TJCk/5H05a
C01ABLrdcAC4FygHbgGHgdWFBm+aafAv2lXBU0fJZqIAAAAASUVORK5CYII=
"
id="image10"
x="0"
y="0" />
<g
id="layer1">
<g
id="g3922">
<path
style="fill:#8ae234;stroke:#172a04;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="M 41,9 61,19 V 55 L 41,43 Z"
id="path3045" />
<path
style="fill:url(#linearGradient3893);fill-opacity:1;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 43,12.2 16,8 V 51.5 L 43,41.9 Z"
id="path3045-3" />
<path
style="fill:#8ae234;stroke:#172a04;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="M 23,9 3,19 V 55 L 23,43 Z"
id="path3045-6" />
<path
style="fill:url(#linearGradient3862);fill-opacity:1;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 21,12.2 -16,8 v 31.3 l 16,-9.6 z"
id="path3045-3-2" />
<path
style="fill:none;stroke:#280000;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:8, 16;stroke-dashoffset:2;stroke-opacity:1"
d="M 32,5.9999998 V 58"
id="path3891" />
<path
style="fill:none;stroke:#cc0000;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:8, 16;stroke-dashoffset:2;stroke-opacity:1"
d="M 32,6 V 58"
id="path3891-9" />
<path
style="fill:none;stroke:#ef2929;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:8, 16;stroke-dashoffset:2;stroke-opacity:1"
d="m 31,5.7 v 52"
id="path3891-9-1" />
<path
style="fill:none;stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 23,10 4,54"
id="path918" />
<path
style="fill:none;stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 41,10 61,55"
id="path920" />
<path
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 8,50 21,20"
id="path922" />
<path
id="path922-9"
d="M 5.0935052,46.374021 19,14"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 43.012401,19.729601 56.570656,50.165549"
id="path939" />
<path
id="path939-4"
d="M 44.695494,13.067355 59.001791,45.560417"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 14 KiB

@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
@@ -8,99 +6,282 @@
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="13.546667mm"
height="13.546667mm"
viewBox="0 0 13.546667 13.546667"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="OpenSCAD_ScaleMesh.svg">
id="svg2766"
height="64px"
width="64px">
<title
id="title870">OpenSCAD_ScaleMeshFeature</title>
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="9.9518731"
inkscape:cy="-16.322498"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="1791"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
id="defs2768">
<linearGradient
id="linearGradient3856">
<stop
id="stop3858"
offset="0"
style="stop-color:#4e9a06;stop-opacity:1" />
<stop
id="stop3860"
offset="1"
style="stop-color:#8ae234;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3824">
<stop
id="stop3826"
offset="0"
style="stop-color:#8ae234;stop-opacity:1" />
<stop
id="stop3828"
offset="1"
style="stop-color:#4e9a06;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient3787">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3789" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3791" />
</linearGradient>
<linearGradient
id="linearGradient3864">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3036"
gradientUnits="userSpaceOnUse"
x1="56.172409"
y1="29.279999"
x2="21.689653"
y2="36.079998"
gradientTransform="matrix(0,-1.4500001,1.4705882,0,-15.05882,91.45)" />
<linearGradient
id="linearGradient3895">
<stop
id="stop3897"
offset="0"
style="stop-color:#729fcf;stop-opacity:1;" />
<stop
id="stop3899"
offset="1"
style="stop-color:#204a87;stop-opacity:1;" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3012"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.38366341,-0.38366341,0.41875298,0.41875298,12.196434,25.003375)"
x1="44.058071"
y1="18.865765"
x2="32.329041"
y2="43.940212" />
<linearGradient
gradientTransform="translate(-0.9420628,1.000004)"
gradientUnits="userSpaceOnUse"
y2="128.1946"
x2="599.1272"
y1="103.1946"
x1="591.59064"
id="linearGradient3830"
xlink:href="#linearGradient3824" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="68.194603"
x2="595.35895"
y1="135.1946"
x1="613.25824"
id="linearGradient3862"
xlink:href="#linearGradient3856"
gradientTransform="matrix(1.0614931,0,0,1,-612.96941,-69.194602)" />
<linearGradient
y2="43.940212"
x2="32.329041"
y1="18.865765"
x1="44.058071"
gradientTransform="matrix(0.38366341,-0.38366341,0.41875298,0.41875298,47.516141,23.120403)"
gradientUnits="userSpaceOnUse"
id="linearGradient3012-2"
xlink:href="#linearGradient3895" />
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3012-2-5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.38366341,-0.38366341,0.41875298,0.41875298,47.516141,23.120403)"
x1="44.058071"
y1="18.865765"
x2="32.329041"
y2="43.940212" />
<linearGradient
xlink:href="#linearGradient3895"
id="linearGradient3012-2-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.38366341,-0.38366341,0.41875298,0.41875298,47.516141,23.120403)"
x1="44.058071"
y1="18.865765"
x2="32.329041"
y2="43.940212" />
</defs>
<path
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3862);fill-opacity:1;fill-rule:nonzero;stroke:#172a04;stroke-width:2.00001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 2.9999733,3 3.19e-5,14 H 8.9999994 V 9 H 11.000001 V 3 Z M 15.000004,3 V 9 H 23 V 3 Z m 11.999999,0 v 6 h 7.999996 V 3 Z m 11.999999,0 v 6 h 7.999996 V 3 Z m 11.999999,0 v 6 h 4.000004 v 4 h 5.999994 V 3 Z m 4.000004,14 v 8 h 5.999994 V 17 Z M 3.0000052,21 v 8 h 5.9999942 v -8 z m 51.9999998,8 v 7.999998 h 5.999994 V 29 Z m 0,11.999998 v 8 h 5.999994 v -8 z m 0,12 v 2 h -4.000004 v 6 h 9.999998 v -8 z m -20.000006,2 v 6 h 11.999999 v -6 z"
id="rect3446" />
<path
id="path3018"
d="m 3.8583179,33.746218 v 26.48566 H 30.230137 v -26.48566 z"
style="fill:none;stroke:#172a04;stroke-width:3.60392;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path3832"
d="m 36.000003,57 h 10"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3834"
d="m 52.000003,57 h 5 v -2 h 3"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
id="path3836"
d="M 57.000003,48 V 42"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3838"
d="M 57.000003,36 V 30"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3840"
d="M 57.000003,24 V 18"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3842"
d="M 53.000003,8 V 5 h 7"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3844"
d="m 46.000003,5 h -6"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3846"
d="m 34.000003,5 h -6"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3848"
d="m 22.000003,5 h -6"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3850"
d="M 10.000003,5 H 5.0000028 v 11"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3852"
d="m 5.0000028,22 v 6"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3854"
d="M 57.000003,12 V 9"
style="fill:none;stroke:#8ae234;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<metadata
id="metadata5">
id="metadata5370">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title>OpenSCAD_ScaleMeshFeature</dc:title>
<cc:license
rdf:resource="" />
<dc:date>12-01-2021</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier />
<dc:relation />
<dc:contributor>
<cc:Agent>
<dc:title>Based on a wmayer's design</dc:title>
</cc:Agent>
</dc:contributor>
<dc:subject>
<rdf:Bag>
<rdf:li>green square</rdf:li>
<rdf:li>arrow</rdf:li>
<rdf:li>dotted line</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description></dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<rect
style="fill:none;fill-rule:evenodd;stroke:#8ae234;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;paint-order:markers stroke fill"
id="rect908"
width="23.379589"
height="23.553743"
x="5.2244897"
y="35.39592" />
<rect
y="37.359825"
x="7.2423844"
height="19.635378"
width="19.33061"
id="rect908-4"
style="fill:none;fill-rule:evenodd;stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;paint-order:markers stroke fill" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-42.363567,-31.690952)">
<image
y="31.690952"
x="42.363567"
id="image823"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABgmlDQ1BJQ0MgcHJvZmlsZQAAKM+V
kU0oRFEcxX8zQyORZBYS9RZYUUKy1JBJURqjDBbee2PG1Lxnem9kY6lslYWPja+FjTVbC1ullI+S
laUVsZGe/32jZlKj3LrdX+fec7r3XAge5EzLreoByy448VhUm0nOauFnaqiikR7adNPNT0yNJqg4
Pm4JqPWmW2Xxv1GfWnRNCGjCQ2beKQgvCA+sFvKKd4Qj5pKeEj4V7nLkgsL3SjeK/KI443NQZUac
RHxYOCKsZcrYKGNzybGE+4XbU5Yt+cGZIqcUrym2civmzz3VC+sW7ekppctsJcYYE0yiYbBClhwF
umW1RXGJy360gr/F90+KyxBXFlMcIyxjoft+1B/87tZN9/UWk+qiUP3keW8dEN6Cr03P+zz0vK8j
CD3ChV3yLx/A4LvomyWtfR8a1uHssqQZ23C+Ac0Ped3RfSkkM5hOw+uJfFMSmq6hdq7Y288+x3eQ
kK7Gr2B3Dzozkj1f4d015b39ecbvj+g3ku5ytCDpbfYAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAG
YktHRAD/AP8A/6C9p5MAAAAHdElNRQfkCAQRMSOHzZAlAAAGiElEQVR4Xu2b+1MVZRjHv+C5ASp4
SbSDdptK8VZ44SCaVF5yvJQ6oY2NZaNp01ha/tD0W39A6eRMQ8lUx0pNG00p0zQzHfMKKhaiQiqi
iZKKmHDgoJ3nPe973F12z54F9lygD7Oz776X3X2e9/s++767h7i7PtCBief7DgtTAGlg6cWVKCj6
mWerMzVjApY7F7N0LNYXiHZxcdwBngYv0rdN58XBKXluE9vHan0BtbPbLLDw4wC7J33OU3JyfnqN
p+TESn2Bsl2HjwHNFCD4sGodTwUn1HoCs+sLQm33/1NAGQTFGFJ6UETYWAqCFO2VSO2gIKirAGog
GtEJbVYL29ROriTS9em+302dzTYtdBWg9FgsYMSeDh8D2r0D6LlPm3QoS2mXDtCLISJ2EFETA8ZP
zcX+g0f4kTGyModjR8F6fmSMqFGAx+PhKeO01HFEyIshsxXw9+UqjJ+Si3MVFzC/aGnQR5eUAWku
+BZ1qK0q92f40Fvd0hAQq0GmACNjxiz69E5FwXdfoXdqL+RnLA95KkvWxpElEhoavZrGE1RGdQim
AJaKEv4oKcXE52ejpuamTAlKh4j8Ac5MxMfH4+blMnZMxPQ8YFB6f0yeOI6l3a5P2J4IOptTKMAI
zAGkgSWVK/HIlqmqG5WFQyckxmXvf4A16zfCZrOj+OweXtJcAVJaYb/fAUbGjFk0NTXhzaXvIS/f
DZsjCcc1jFdTQqsVIIXGDG0U+IIFxrakoaERry58G6vXbEBil244Xr6Ll6gbH2w4GCXiMeB2XR1m
zX0dm7ZsRefuvVBYuo2X6Pe8oE0VEE5qa29h+ux52LHrN3Tt4cThEwW8RNv4zKEzm8WDODYTUCdq
1wLXrl/H5JlzsG//IaT07oeDxRt5ibbxwwdOwc3qSt15QkysBcZOfAGFR4vRs29/7D3g5rnaxo8Y
PA23rlVhTLYLRwqPoa6+ns0TyBkOux3VF07ymsaIeAzoZLHxlByZ7IfMYMZPmvAMNn/rxvqvVyHB
4WDGE62JARFbC1yt/geTZ8xBSelppD48GLv35vMSOa4nc1Fz5TyezRnDDLfb/A77dc8+5L68gCmB
nHG1ooTlEzRnifq1wH09e+DHjd8gvf9jqPrrBHJGz+cl93ANm8WMJ9mvdecFjCeefio7oAQ6l5SY
WgvIlPDgEOzet4rljxoxB9cvlcE1chiTfVJSIstXcvZ8BawWK9KcfXhOjK0FZEo4V4yxoxdgdOZc
ZvzwjKHYtPYLTeOJhx7oJzPeKDIFVFRexEcf57FHU319y19QBMPhsCM7ayTeeWsR+qU5ea5cCcSQ
QenY6nNMSkoyOzaCEQUEHPDnyVNsGXrjRg2rYDZk2PbN6zBwwOM8x++EGS/NY+nvfbLv0b0bSxul
RQ4YN+VFHDhchPmFS1gFs8kftgKuERnY+cMGntN2GI4B9PLhwKFCWK3qz2QziIuPZ9eka0cSvwNq
a9mBxZ7A9uHAYrWzvbi2WRheC9AMTDoLi0UMrwUo+qdnjEFClxQUlW5nBWLMrM7+DA11/7J0S7E6
EvHK7wv5kR931qdo9NxGSdFe2dMg3OjPA/hTsm/a/eyZa2SjNn6az9Xv+v6iAbkCOvsUcEquAPco
X0/Vt6ynxHkdSck4eto//sR5v8zKg9dTZ4oCqM8MrQUE5vVKeHvbyFpAfwjEODQPoI16XS0wht0B
gcdRdISAUIIg37cGlXNEif36DmgvcUELuQNMuqdo6W01FAq4d6uBsdomRK8Lwh4EA4TJJ63/LhDN
+tXAyFogPApQcaKZfqUZ3oq0xSifVqC6UZl4k64bBNviRtXPYaYLQkfmgGi+USPQWiDU3zsohoBZ
xqqc10S/Gv4uIFZt9sQuOHZmJyugyElUv1GOpsZ6trS1dDL2ccTb5MWFykuwJXTG8bJfWJ4479VF
Zbjj9bDVYF+n09D//AjEqo7Qak91pC94xPUNfxcgQ+gjhJGN2jB0BKDXY1qIntRqrzReDbkCEnwK
KJMrgBBvVtsCcd4rPgXc5QpI7ZXa7C2uHtKeJPTaB30rLDBxWDLETfgx+2r3kF9XDlMAvZp2PvoE
rFY7is/5f5wkVYAZVC046fPBHVw8cwyOhMRADwabwEiR9iQRantVBSQnd2UfIRu9DazQbG4su8WM
p2vStSMJUwAlIvlpLJTfJ2ihVECoCAUEHEBQMIzEx1G9l5hahPIYVEO0o+mwzAEdkZDnAe0T4D8U
7FGz5guiMQAAAABJRU5ErkJggg==
"
style="image-rendering:optimizeQuality"
preserveAspectRatio="none"
height="13.546667"
width="13.546667" />
id="g954"
transform="matrix(0.53865293,-0.53865293,0.53865293,0.53865293,-32.932436,50.082417)">
<path
style="fill:url(#linearGradient3012-2);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 70.319706,13.117028 4.062816,4.37832 -8.062816,7.62168 6,6 7.719671,-7.964826 4.24264,4.242641 0.03769,-14.277815 z"
id="path3343-1" />
<path
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 74.869729,15.117028 2.325151,2.37832 -7.987668,7.653821 3.080353,3.112494 7.751812,-7.937888 2.221642,2.240472 0.05869,-7.447219 z"
id="path3343-2-8" />
</g>
<g
transform="matrix(0.53865293,0.53865293,-0.53865293,0.53865293,13.524918,-8.0540131)"
id="g954-4">
<path
id="path3343-1-3"
d="m 70.319706,13.117028 4.062816,4.37832 -8.062816,7.62168 6,6 7.719671,-7.964826 4.24264,4.242641 0.03769,-14.277815 z"
style="fill:url(#linearGradient3012-2-5);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path3343-2-8-6"
d="m 74.869729,15.117028 2.325151,2.37832 -7.987668,7.653821 3.080353,3.112494 7.751812,-7.937888 2.221642,2.240472 0.05869,-7.447219 z"
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
transform="matrix(0.76177028,0,0,0.76177028,-15.114559,5.5800087)"
id="g954-6">
<path
id="path3343-1-0"
d="m 70.319706,13.117028 4.062816,4.37832 -8.062816,7.62168 6,6 7.719671,-7.964826 4.24264,4.242641 0.03769,-14.277815 z"
style="fill:url(#linearGradient3012-2-4);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path3343-2-8-0"
d="m 74.869729,15.117028 2.325151,2.37832 -7.987668,7.653821 3.080353,3.112494 7.751812,-7.937888 2.221642,2.240472 0.05869,-7.447219 z"
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+7 -2
View File
@@ -2972,8 +2972,13 @@ void TopoShapePy::setOrientation(Py::String arg)
Py::List TopoShapePy::getSubShapes(void) const
{
Py::List ret;
for(TopoDS_Iterator it(getTopoShapePtr()->getShape());it.More();it.Next())
ret.append(shape2pyshape(it.Value()));
const TopoDS_Shape& shape = getTopoShapePtr()->getShape();
if (!shape.IsNull()) {
for(TopoDS_Iterator it(shape);it.More();it.Next())
ret.append(shape2pyshape(it.Value()));
}
return ret;
}
+2
View File
@@ -1150,6 +1150,7 @@ CmdPartMakeSolid::CmdPartMakeSolid()
sToolTipText = QT_TR_NOOP("Create solid from a shell or compound");
sWhatsThis = "Part_MakeSolid";
sStatusTip = sToolTipText;
sPixmap = "Part_MakeSolid";
}
void CmdPartMakeSolid::activated(int iMsg)
@@ -1350,6 +1351,7 @@ CmdPartMakeFace::CmdPartMakeFace()
sToolTipText = QT_TR_NOOP("Make face from set of wires (e.g. from a sketch)");
sWhatsThis = "Part_MakeFace";
sStatusTip = sToolTipText;
sPixmap = "Part_MakeFace";
}
void CmdPartMakeFace::activated(int iMsg)
+2
View File
@@ -67,6 +67,8 @@
<file>icons/tools/Part_Extrude.svg</file>
<file>icons/tools/Part_Fillet.svg</file>
<file>icons/tools/Part_Loft.svg</file>
<file>icons/tools/Part_MakeFace.svg</file>
<file>icons/tools/Part_MakeSolid.svg</file>
<file>icons/tools/Part_Mirror.svg</file>
<file>icons/tools/Part_Offset.svg</file>
<file>icons/tools/Part_Offset2D.svg</file>
@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64px"
height="64px"
id="svg2825"
version="1.1">
<title
id="title848">Part_MakeFace</title>
<defs
id="defs2827">
<linearGradient
id="linearGradient889">
<stop
style="stop-color:#204a87;stop-opacity:1;"
offset="0"
id="stop885" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop887" />
</linearGradient>
<linearGradient
id="linearGradient3836-0">
<stop
style="stop-color:#c4a000;stop-opacity:1;"
offset="0"
id="stop3838-2" />
<stop
style="stop-color:#fce94f;stop-opacity:1;"
offset="1"
id="stop3840-5" />
</linearGradient>
<linearGradient
id="linearGradient3836-0-6">
<stop
style="stop-color:#c4a000;stop-opacity:1;"
offset="0"
id="stop3838-2-7" />
<stop
style="stop-color:#fce94f;stop-opacity:1;"
offset="1"
id="stop3840-5-5" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient889"
id="linearGradient891"
x1="38"
y1="51"
x2="17"
y2="19"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.82608697,0,0,0.82608697,10.434783,10.434782)" />
</defs>
<g
id="layer1">
<g
id="g3527"
transform="matrix(0.12582859,0,0,0.13656891,-119.21901,-53.81056)">
<path
id="rect2233"
d="M 971.31349,415.98457 V 752.81086 H 1336.8902 V 415.98457 Z m 43.86921,44.36492 274.0236,-0.43105 v 248.95857 l -274.0236,0.0646 z"
style="fill:#d3d7cf;fill-opacity:1;stroke:#2e3436;stroke-width:15.2568;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 55.913045,10.935149 H 9.1739164 v 43.063378"
id="path3040"
transform="matrix(7.3115342,0,0,7.3115342,920.13275,350.67648)" />
<path
style="fill:none;stroke:#ffffff;stroke-width:2.08668;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 13,51 39.685575,0.03219 -0.06987,-36.128755"
id="path3042"
transform="matrix(7.3115342,0,0,7.3115342,920.13275,350.67648)" />
</g>
<rect
style="fill:url(#linearGradient891);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill"
id="rect881"
width="38"
height="36.347828"
x="22"
y="23.652174" />
<rect
style="fill:none;fill-rule:evenodd;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill"
id="rect883"
width="36.347828"
height="34.695652"
x="22.826086"
y="24.47826"
ry="0" />
</g>
<metadata
id="metadata5305">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Part_MakeFace</dc:title>
<cc:license
rdf:resource="" />
<dc:date>12-01-2021</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier></dc:identifier>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:contributor>
<cc:Agent>
<dc:title></dc:title>
</cc:Agent>
</dc:contributor>
<dc:description></dc:description>
<dc:subject>
<rdf:Bag />
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,747 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg3052"
sodipodi:version="0.32"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="Part_MakeSolid.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<title
id="title930">Part_MakeSolid</title>
<defs
id="defs3054">
<linearGradient
inkscape:collect="always"
id="linearGradient3873">
<stop
style="stop-color:#729fcf;stop-opacity:1;"
offset="0"
id="stop3875" />
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="1"
id="stop3877" />
</linearGradient>
<linearGradient
id="linearGradient4032">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4034" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4036" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective3060" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.6244669,-0.05136783,0.04345521,0.9993132,-102.99033,7.7040438)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#4bff54;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#00b800;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3206"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.87904684,0.2250379,-0.41709097,2.0016728,56.73751,-127.99883)" />
<linearGradient
id="linearGradient3199">
<stop
id="stop3201"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3203"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3206">
<stop
id="stop3208"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3210"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032"
id="radialGradient4030"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.260164,-0.05136783,0.03370995,0.9993132,-43.139781,7.2044077)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
<linearGradient
id="linearGradient3836-0-6-92-4-6">
<stop
style="stop-color:#a40000;stop-opacity:1"
offset="0"
id="stop3838-2-7-06-8-7" />
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="1"
id="stop3840-5-5-8-7-5" />
</linearGradient>
<linearGradient
id="linearGradient3836-0-6-92-4-6-5">
<stop
style="stop-color:#a40000;stop-opacity:1"
offset="0"
id="stop3838-2-7-06-8-7-3" />
<stop
style="stop-color:#ef2929;stop-opacity:1"
offset="1"
id="stop3840-5-5-8-7-5-5" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2671"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2673"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2677"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2679"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2689"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2691"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2695"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2697"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient2703"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
y2="57.854782"
x2="33.467113"
y1="46.315926"
x1="27.71979"
gradientUnits="userSpaceOnUse"
id="linearGradient2695-1"
xlink:href="#linearGradient3873"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient3215"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient3217"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient3219"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
y2="57.854782"
x2="33.467113"
y1="46.315926"
x1="27.71979"
gradientUnits="userSpaceOnUse"
id="linearGradient3217-6"
xlink:href="#linearGradient3873"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient3291"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3873"
id="linearGradient3293"
gradientUnits="userSpaceOnUse"
x1="27.71979"
y1="46.315926"
x2="33.467113"
y2="57.854782" />
<linearGradient
y2="57.854782"
x2="33.467113"
y1="46.315926"
x1="27.71979"
gradientUnits="userSpaceOnUse"
id="linearGradient3291-8"
xlink:href="#linearGradient3873"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8.7173008"
inkscape:cx="27.712712"
inkscape:cy="30.023552"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="2391"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-bbox="false"
inkscape:snap-nodes="true"
inkscape:document-rotation="0"
inkscape:snap-grids="false">
<sodipodi:guide
orientation="0,1"
position="31.959442,64.811153"
id="guide3868" />
<inkscape:grid
type="xygrid"
id="grid3091"
empspacing="2"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
<sodipodi:guide
position="141,-5"
orientation="0,-1"
id="guide1253" />
<sodipodi:guide
position="72,-29"
orientation="1,0"
id="guide1687" />
<sodipodi:guide
position="1,33"
orientation="-0.8660254,0.5"
id="guide1689"
inkscape:label=""
inkscape:locked="false"
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="60.139028,44.70647"
orientation="1,0"
id="guide3325" />
</sodipodi:namedview>
<metadata
id="metadata3057">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Part_MakeSolid</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>PartDesign_MoveTip</dc:title>
<dc:date>12-01-2021</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier></dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title></dc:title>
</cc:Agent>
</dc:contributor>
<dc:subject>
<rdf:Bag />
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
transform="translate(-2.062694,-20.131811)"
id="g3863-0-8-9-03-8-8-3">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-1-2-6-7-4-5-4"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient3291-8);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-5-3-8-0-6-6-2"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
transform="translate(-31.203497,-37.448504)"
id="g3863-7-6-4-8-7">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-39-1-2-7-2"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient3217-6);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-54-9-7-3-6"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
transform="translate(-16.663827,-37.396392)"
id="g3863-0-8-9-03-94">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-1-2-6-7-6"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient3293);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-5-3-8-0-7"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
id="g3863-0-8-9-03-8-8"
transform="translate(-2.068201,-37.300132)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-1-2-6-7-4-5"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-5-3-8-0-6-6"
style="fill:url(#linearGradient3291);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
id="g3863-7-6-1-6"
transform="translate(-31.398665,-17.323749)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-39-1-8-9"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-54-9-74-6"
style="fill:url(#linearGradient2703);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
transform="translate(-35.821495,-9.6203256)"
id="g3863-7-6-4-2-0">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-39-1-2-4-9"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient2697);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-54-9-7-8-0"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
transform="translate(-21.281825,-9.5682136)"
id="g3863-0-8-9-6-9">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-1-2-6-3-1"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient2695);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-5-3-8-1-4"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
transform="translate(-40.244255,-1.9748289)"
id="g3863-7-6-7-0-4">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-39-1-4-6-1"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient2691);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-54-9-4-2-5"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
transform="translate(-25.704585,-1.9227169)"
id="g3863-0-8-4-5-0">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-1-2-4-5-9"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient2689);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-5-3-5-39-0"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
id="g3863-7-6-4-8"
transform="translate(-35.846655,-29.385578)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-39-1-2-7"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-54-9-7-3"
style="fill:url(#linearGradient2679);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
id="g3863-0-8-9-03"
transform="translate(-21.306985,-29.333466)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-1-2-6-7"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-5-3-8-0"
style="fill:url(#linearGradient2677);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
id="g3863-7-6-7-72"
transform="translate(-40.269415,-21.740081)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-39-1-4-4"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-54-9-4-6"
style="fill:url(#linearGradient2673);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
id="g3863-0-8-4-2"
transform="translate(-25.729745,-21.687969)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-1-2-4-0"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-5-3-5-8"
style="fill:url(#linearGradient2671);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
id="g3863-0-8-9-6-9-1"
transform="translate(-6.6861992,-9.4719544)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-1-2-6-3-1-80"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-5-3-8-1-4-0"
style="fill:url(#linearGradient2695-1);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
id="g3863-0-8-4-5-0-9"
transform="translate(-11.108959,-1.8264575)">
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-1-2-4-5-9-7"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
<ellipse
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)"
id="path3024-3-5-3-5-39-0-8"
style="fill:url(#linearGradient3219);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
cx="30.018719"
cy="52.085354"
rx="8.0462542"
ry="8.0772018" />
</g>
<g
transform="translate(-6.7113592,-29.237206)"
id="g3863-0-8-9-03-8">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-1-2-6-7-4"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient3217);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-5-3-8-0-6"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
<g
transform="translate(-11.134119,-21.591709)"
id="g3863-0-8-4-2-8">
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:none;stroke:#0b1521;stroke-width:6.91004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-1-2-4-0-6"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
<ellipse
ry="8.0772018"
rx="8.0462542"
cy="52.085354"
cx="30.018719"
style="fill:url(#linearGradient3215);fill-opacity:1;stroke:#729fcf;stroke-width:2.30335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dasharray:none;stroke-dashoffset:20.4;stroke-opacity:1"
id="path3024-3-5-3-5-8-5"
transform="matrix(0.86997005,0,0,0.86663677,26.084867,6.7443139)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 27 KiB

+3
View File
@@ -303,6 +303,9 @@ App::DocumentObjectExecReturn *Pipe::execute(void)
AddSubShape.setValue(result);
if(base.IsNull()) {
if (getAddSubType() == FeatureAddSub::Subtractive)
return new App::DocumentObjectExecReturn("Pipe: There is nothing to subtract from\n");
result = refineShapeIfActive(result);
Shape.setValue(getSolid(result));
return App::DocumentObject::StdReturn;
+6 -6
View File
@@ -33,12 +33,12 @@ namespace PartDesign
class PartDesignExport Pipe : public ProfileBased
{
PROPERTY_HEADER(PartDesign::Pad);
PROPERTY_HEADER(PartDesign::Pipe);
public:
Pipe();
App::PropertyLinkSub Spine;
App::PropertyBool SpineTangent;
App::PropertyLinkSub AuxillerySpine;
@@ -57,7 +57,7 @@ public:
return "PartDesignGui::ViewProviderPipe";
}
//@}
protected:
///get the given edges and all their tangent ones
void getContiniusEdges(Part::TopoShape TopShape, std::vector< std::string >& SubNames);
@@ -72,14 +72,14 @@ private:
};
class PartDesignExport AdditivePipe : public Pipe {
PROPERTY_HEADER(PartDesign::AdditivePipe);
public:
AdditivePipe();
};
class PartDesignExport SubtractivePipe : public Pipe {
PROPERTY_HEADER(PartDesign::SubtractivePipe);
public:
SubtractivePipe();
@@ -88,4 +88,4 @@ public:
} //namespace PartDesign
#endif // PART_Pad_H
#endif // PARTDESIGN_Pipe_H
+3 -2
View File
@@ -316,6 +316,7 @@ CmdPartDesignMigrate::CmdPartDesignMigrate()
sToolTipText = QT_TR_NOOP("Migrate document to the modern PartDesign workflow");
sWhatsThis = "PartDesign_Migrate";
sStatusTip = sToolTipText;
sPixmap = "PartDesign_Migrate";
}
void CmdPartDesignMigrate::activated(int iMsg)
@@ -665,7 +666,7 @@ CmdPartDesignMoveFeature::CmdPartDesignMoveFeature()
sToolTipText = QT_TR_NOOP("Moves the selected object to another body");
sWhatsThis = "PartDesign_MoveFeature";
sStatusTip = sToolTipText;
sPixmap = "";
sPixmap = "PartDesign_MoveFeature";
}
void CmdPartDesignMoveFeature::activated(int iMsg)
@@ -827,7 +828,7 @@ CmdPartDesignMoveFeatureInTree::CmdPartDesignMoveFeatureInTree()
sToolTipText = QT_TR_NOOP("Moves the selected object and insert it after another object");
sWhatsThis = "PartDesign_MoveFeatureInTree";
sStatusTip = sToolTipText;
sPixmap = "";
sPixmap = "PartDesign_MoveFeatureInTree";
}
void CmdPartDesignMoveFeatureInTree::activated(int iMsg)
@@ -28,7 +28,10 @@
<file>icons/PartDesign_InvoluteGear.svg</file>
<file>icons/PartDesign_Line.svg</file>
<file>icons/PartDesign_LinearPattern.svg</file>
<file>icons/PartDesign_Migrate.svg</file>
<file>icons/PartDesign_Mirrored.svg</file>
<file>icons/PartDesign_MoveFeature.svg</file>
<file>icons/PartDesign_MoveFeatureInTree.svg</file>
<file>icons/PartDesign_MoveTip.svg</file>
<file>icons/PartDesign_MultiTransform.svg</file>
<file>icons/PartDesign_Pad.svg</file>
@@ -0,0 +1,758 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
id="svg4198"
version="1.1">
<title
id="title954">PartDesign_Migrate</title>
<defs
id="defs4200">
<linearGradient
id="linearGradient978">
<stop
id="stop970"
offset="0.0000000"
style="stop-color:#73d216;stop-opacity:1" />
<stop
style="stop-color:#e8e8e8;stop-opacity:1;"
offset="0.59928656"
id="stop972" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0.82758623"
id="stop974" />
<stop
id="stop976"
offset="1.0000000"
style="stop-color:#4e9a06;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient15218">
<stop
style="stop-color:#f0f0ef;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop15220" />
<stop
id="stop2269"
offset="0.59928656"
style="stop-color:#e8e8e8;stop-opacity:1;" />
<stop
id="stop2267"
offset="0.82758623"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#d8d8d3;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop15222" />
</linearGradient>
<linearGradient
id="linearGradient2259">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2261" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2263" />
</linearGradient>
<linearGradient
id="linearGradient2224">
<stop
style="stop-color:#4e9a06;stop-opacity:1"
offset="0"
id="stop2226" />
<stop
style="stop-color:#8ae234;stop-opacity:1"
offset="1"
id="stop2228" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient2224"
id="linearGradient2230"
x1="35.996582"
y1="40.458221"
x2="33.664921"
y2="37.770721"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3533009,0,0,1.3316921,7.7280954,-11.61264)" />
<linearGradient
id="linearGradient2251">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2253" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2255" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient2251"
id="linearGradient2257"
x1="33.396004"
y1="36.921333"
x2="34.170048"
y2="38.070381"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3533009,0,0,1.3316921,7.8581449,-11.881779)" />
<linearGradient
xlink:href="#linearGradient15218"
id="linearGradient4258"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.084283,0,0,0.987595,-8.7244004,-4.891713)"
x1="22.308331"
y1="18.99214"
x2="35.785294"
y2="39.498238" />
<linearGradient
xlink:href="#linearGradient2259"
id="linearGradient4260"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9820092,0,0,0.9700232,-6.2978926,-4.1789139)"
x1="26.076092"
y1="26.696676"
x2="30.811172"
y2="42.007351" />
<linearGradient
xlink:href="#linearGradient2259"
id="linearGradient13651"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3097058,0,0,1.2925679,8.5353421,-10.651073)"
x1="26.076092"
y1="26.696676"
x2="30.811172"
y2="42.007351" />
<linearGradient
xlink:href="#linearGradient978"
id="linearGradient13653"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.4442914,0,0,1.317411,5.3325471,-11.610222)"
x1="22.308331"
y1="18.99214"
x2="35.785294"
y2="39.498238" />
<radialGradient
r="19.571428"
fy="33.899986"
fx="270.58316"
cy="33.899986"
cx="270.58316"
gradientTransform="matrix(1.1149219,0.2722306,-0.7507171,3.0745639,-471.08629,-148.32863)"
gradientUnits="userSpaceOnUse"
id="radialGradient3817"
xlink:href="#linearGradient3682" />
<linearGradient
id="linearGradient3682">
<stop
id="stop3684"
offset="0"
style="stop-color:#ff6d0f;stop-opacity:1;" />
<stop
id="stop3686"
offset="1"
style="stop-color:#ff1000;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.571428"
fy="29.149046"
fx="282.64584"
cy="29.149046"
cx="282.64584"
gradientTransform="matrix(0.6186598,0.9666542,-1.0332462,0.6612786,-327.27568,-255.84136)"
gradientUnits="userSpaceOnUse"
id="radialGradient3661"
xlink:href="#linearGradient3864" />
<linearGradient
id="linearGradient3864">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop3866" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop3868" />
</linearGradient>
<linearGradient
gradientUnits="userSpaceOnUse"
y2="24.842253"
x2="37.124462"
y1="30.748846"
x1="32.647972"
id="linearGradient2696"
xlink:href="#linearGradient2690" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="24.842253"
x2="37.124462"
y1="31.455952"
x1="36.713837"
id="linearGradient2688"
xlink:href="#linearGradient2682" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="26.649363"
x2="53.588623"
y1="23.667896"
x1="18.935766"
id="linearGradient2408"
xlink:href="#linearGradient2402" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="20.60858"
x2="15.984863"
y1="36.061237"
x1="62.513836"
id="linearGradient2386"
xlink:href="#linearGradient2380" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1,0,0,0.536723,0,16.87306)"
gradientUnits="userSpaceOnUse"
id="radialGradient1503"
xlink:href="#linearGradient8662" />
<linearGradient
y2="50.939667"
x2="45.380436"
y1="45.264122"
x1="46.834816"
gradientUnits="userSpaceOnUse"
id="linearGradient1501"
xlink:href="#linearGradient2871" />
<linearGradient
y2="26.048164"
x2="52.854095"
y1="26.048164"
x1="5.9649177"
gradientUnits="userSpaceOnUse"
id="linearGradient1493"
xlink:href="#linearGradient2797" />
<linearGradient
y2="26.048164"
x2="52.854095"
y1="26.048164"
x1="5.9649177"
gradientUnits="userSpaceOnUse"
id="linearGradient1491"
xlink:href="#linearGradient2797" />
<linearGradient
y2="26.194071"
x2="37.065414"
y1="29.729605"
x1="37.128052"
gradientTransform="matrix(-1,0,0,-1,47.52791,45.84741)"
gradientUnits="userSpaceOnUse"
id="linearGradient1488"
xlink:href="#linearGradient2847" />
<linearGradient
y2="19.115122"
x2="15.419417"
y1="10.612206"
x1="13.478554"
gradientTransform="translate(0.465413,-0.277593)"
gradientUnits="userSpaceOnUse"
id="linearGradient1486"
xlink:href="#linearGradient2831" />
<linearGradient
id="linearGradient8662">
<stop
id="stop8664"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop8666"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2797">
<stop
id="stop2799"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop2801"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2831">
<stop
id="stop2833"
offset="0"
style="stop-color:#3465a4;stop-opacity:1;" />
<stop
style="stop-color:#5b86be;stop-opacity:1;"
offset="0.33333334"
id="stop2855" />
<stop
id="stop2835"
offset="1"
style="stop-color:#83a8d8;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2847">
<stop
id="stop2849"
offset="0"
style="stop-color:#3465a4;stop-opacity:1;" />
<stop
id="stop2851"
offset="1"
style="stop-color:#3465a4;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2871">
<stop
id="stop2873"
offset="0"
style="stop-color:#3465a4;stop-opacity:1;" />
<stop
id="stop2875"
offset="1"
style="stop-color:#3465a4;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient2380">
<stop
id="stop2382"
offset="0"
style="stop-color:#b9cfe7;stop-opacity:1" />
<stop
id="stop2384"
offset="1"
style="stop-color:#729fcf;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient2402">
<stop
id="stop2404"
offset="0"
style="stop-color:#729fcf;stop-opacity:1;" />
<stop
id="stop2406"
offset="1"
style="stop-color:#528ac5;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2682">
<stop
id="stop2684"
offset="0"
style="stop-color:#3977c3;stop-opacity:1;" />
<stop
id="stop2686"
offset="1"
style="stop-color:#89aedc;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2690">
<stop
id="stop2692"
offset="0"
style="stop-color:#c4d7eb;stop-opacity:1;" />
<stop
id="stop2694"
offset="1"
style="stop-color:#c4d7eb;stop-opacity:0;" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient2380"
id="linearGradient3681"
gradientUnits="userSpaceOnUse"
x1="62.513836"
y1="36.061237"
x2="15.984863"
y2="20.60858" />
<linearGradient
xlink:href="#linearGradient2871"
id="linearGradient3683"
gradientUnits="userSpaceOnUse"
x1="46.834816"
y1="45.264122"
x2="45.380436"
y2="50.939667" />
<linearGradient
xlink:href="#linearGradient2402"
id="linearGradient3685"
gradientUnits="userSpaceOnUse"
x1="18.935766"
y1="23.667896"
x2="53.588623"
y2="26.649363" />
<linearGradient
xlink:href="#linearGradient2871"
id="linearGradient3687"
gradientUnits="userSpaceOnUse"
x1="46.834816"
y1="45.264122"
x2="45.380436"
y2="50.939667" />
<linearGradient
xlink:href="#linearGradient2690"
id="linearGradient3698"
gradientUnits="userSpaceOnUse"
x1="32.647972"
y1="30.748846"
x2="37.124462"
y2="24.842253"
gradientTransform="translate(-64.247811,5.5825138)" />
<linearGradient
xlink:href="#linearGradient2682"
id="linearGradient3700"
gradientUnits="userSpaceOnUse"
x1="36.713837"
y1="31.455952"
x2="37.124462"
y2="24.842253"
gradientTransform="translate(-64.247811,5.5825138)" />
<linearGradient
xlink:href="#linearGradient2831"
id="linearGradient3705"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-63.782398,5.3049208)"
x1="13.478554"
y1="10.612206"
x2="15.419417"
y2="19.115122" />
<linearGradient
xlink:href="#linearGradient2847"
id="linearGradient3707"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,-1,-16.719901,51.429924)"
x1="37.128052"
y1="29.729605"
x2="37.065414"
y2="26.194071" />
<linearGradient
xlink:href="#linearGradient2831"
id="linearGradient3745"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-63.782398,5.3049208)"
x1="13.478554"
y1="10.612206"
x2="15.419417"
y2="19.115122" />
<linearGradient
xlink:href="#linearGradient2847"
id="linearGradient3747"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,-1,-16.719901,51.429924)"
x1="37.128052"
y1="29.729605"
x2="37.065414"
y2="26.194071" />
<linearGradient
xlink:href="#linearGradient2380"
id="linearGradient3749"
gradientUnits="userSpaceOnUse"
x1="62.513836"
y1="36.061237"
x2="15.984863"
y2="20.60858" />
<linearGradient
xlink:href="#linearGradient2871"
id="linearGradient3751"
gradientUnits="userSpaceOnUse"
x1="46.834816"
y1="45.264122"
x2="45.380436"
y2="50.939667" />
<linearGradient
xlink:href="#linearGradient2380"
id="linearGradient3753"
gradientUnits="userSpaceOnUse"
x1="62.513836"
y1="36.061237"
x2="15.984863"
y2="20.60858" />
<linearGradient
xlink:href="#linearGradient2797"
id="linearGradient3755"
gradientUnits="userSpaceOnUse"
x1="5.9649177"
y1="26.048164"
x2="52.854095"
y2="26.048164" />
<linearGradient
gradientTransform="matrix(0.8506406,0,0,0.8506406,98.197782,5.1873131)"
xlink:href="#linearGradient3682-0"
id="linearGradient3806"
x1="-206.69949"
y1="68.841812"
x2="-211.40184"
y2="7.7114096"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3682-0">
<stop
id="stop3684-0"
offset="0"
style="stop-color:#a40000;stop-opacity:1" />
<stop
id="stop3686-0"
offset="1"
style="stop-color:#ef2929;stop-opacity:1" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3864-9"
id="linearGradient3808"
x1="-146.74467"
y1="58.261547"
x2="-157.32494"
y2="26.520763"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0094494,0,0,1.0094493,-20.307973,3.7260081)" />
<linearGradient
id="linearGradient3864-9">
<stop
style="stop-color:#204a87;stop-opacity:1"
offset="0"
id="stop3866-1" />
<stop
style="stop-color:#729fcf;stop-opacity:1"
offset="1"
id="stop3868-1" />
</linearGradient>
<linearGradient
y2="26.520763"
x2="-157.32494"
y1="58.261547"
x1="-146.74467"
gradientTransform="matrix(0.85867864,0,0,0.85867856,80.922992,8.356807)"
gradientUnits="userSpaceOnUse"
id="linearGradient3168"
xlink:href="#linearGradient3864-9" />
<linearGradient
xlink:href="#linearGradient3864-9"
id="linearGradient3212"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.85867864,0,0,0.85867856,80.922992,8.356807)"
x1="-146.74467"
y1="58.261547"
x2="-157.32494"
y2="26.520763" />
<linearGradient
xlink:href="#linearGradient3682-0"
id="linearGradient3214"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8506406,0,0,0.8506406,98.197782,5.1873131)"
x1="-206.69949"
y1="68.841812"
x2="-211.40184"
y2="7.7114096" />
</defs>
<metadata
id="metadata4203">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>PartDesign_Migrate</dc:title>
<dc:date>12-01-2021</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag />
</dc:subject>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
<dc:contributor>
<cc:Agent>
<dc:title></dc:title>
</cc:Agent>
</dc:contributor>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(0,16)">
<g
id="g4268"
style="opacity:0.5"
transform="matrix(1.3337003,0,0,1.3325124,0.93484405,-15.082624)">
<rect
y="34.033413"
x="20.161837"
height="2"
width="13"
id="rect2279"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.170454;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" />
<rect
ry="0.56615961"
rx="0.57551974"
y="1.5629303"
x="1.5484408"
height="35.976688"
width="31.491333"
id="rect4238"
style="fill:url(#linearGradient4258);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.50026;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
ry="0"
rx="0"
y="3.0638545"
x="3.048028"
height="33.020332"
width="28.492159"
id="rect4240"
style="fill:none;stroke:url(#linearGradient4260);stroke-width:1.50026;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="10.033414"
x="7.016119"
height="2"
width="21"
id="rect4248"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.170454;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" />
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.170454;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none"
id="rect4250"
width="20"
height="2"
x="7.016119"
y="14.033414" />
<rect
y="18.033415"
x="7.016119"
height="2"
width="18"
id="rect4252"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.170454;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" />
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.170454;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none"
id="rect4254"
width="21"
height="2"
x="7.016119"
y="22.033415" />
<rect
y="26.033413"
x="7.016119"
height="2"
width="13"
id="rect4256"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.170454;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" />
</g>
<path
id="rect12413"
d="m 19.787508,-3.0000004 h 40.404673 c 0.427291,0 0.771281,0.3370414 0.771281,0.7556975 V 33.934258 c 0,3.297872 -9.310453,11.057156 -12.542301,11.057156 H 19.787508 c -0.427291,0 -0.771281,-0.337041 -0.771281,-0.7557 V -2.2443029 c 0,-0.4186561 0.34399,-0.7556975 0.771281,-0.7556975 z"
style="fill:url(#linearGradient13653);fill-opacity:1;fill-rule:evenodd;stroke:#4e9a06;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:none;stroke:url(#linearGradient13651);stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect15244"
width="38"
height="43.999996"
x="21"
y="-0.99999958"
rx="0"
ry="0" />
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient2230);fill-opacity:1;fill-rule:evenodd;stroke:#4e9a06;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
d="m 48.407078,44.989007 c 2.747766,0.439323 12.976522,-6.03247 12.564601,-11.316511 -2.115564,3.226819 -6.439712,1.713539 -12.000098,1.925291 0,0 0.535054,8.725374 -0.564503,9.39122 z"
id="path2210" />
<path
id="path2247"
d="m 50.500005,42.300846 c 1.853723,-0.91065 5.992753,-2.858431 7.751207,-5.363349 -2.159996,0.905624 -3.989274,0.278984 -7.716974,0.253561 0,0 0.21967,4.077766 -0.03424,5.109788 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.369318;fill:none;stroke:url(#linearGradient2257);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" />
<g
id="g3205"
transform="matrix(0.48144021,0,0,0.48144028,68.706783,0.7888651)">
<path
id="path3659-5"
d="m -37.178967,28.803284 -6.180993,3.546247 -2.729476,-0.947201 -2.604143,-6.655379 -4.096464,0.21527 -1.868508,6.882078 -2.615074,1.252306 -6.522448,-2.85323 -2.75491,3.061349 3.546261,6.180989 -0.969093,2.721475 -6.655386,2.60415 0.23715,4.104451 6.882091,1.868503 1.252304,2.615071 -2.875105,6.514464 3.061345,2.754904 6.180984,-3.546249 2.743367,0.977075 2.582264,6.647391 4.12633,-0.229167 1.846622,-6.890065 2.615081,-1.252307 6.536331,2.883105 2.75491,-3.06135 -3.546252,-6.180988 0.955184,-2.75135 6.647399,-2.58227 -0.207267,-4.11834 -6.890078,-1.846619 -1.252313,-2.615072 2.861223,-6.544338 z m -9.257241,10.136064 1.268824,0.736194 1.099299,0.996698 0.88009,1.189461 0.633098,1.322475 0.372232,1.425614 0.06167,1.46101 -0.211018,1.46063 -0.481582,1.38662 -0.76607,1.282723 -0.966821,1.085402 -1.189468,0.880088 -1.322473,0.633095 -1.425615,0.372223 -1.468996,0.08356 -1.460644,-0.211006 -1.386612,-0.481592 -1.282715,-0.766069 -1.07743,-0.988709 -0.88806,-1.167575 -0.633115,-1.322473 -0.364227,-1.447498 -0.08353,-1.469 0.21101,-1.460634 0.481598,-1.386617 0.758074,-1.260841 0.974826,-1.107284 1.189451,-0.880088 1.322474,-0.633098 1.447492,-0.36423 1.461009,-0.06167 1.460635,0.211004 1.386621,0.481593 z"
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3212);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:4.1542;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
id="path3659-5-6"
d="m -37.400474,31.220497 -5.769096,3.304934 -4.349793,-1.564099 -2.53291,-6.134027 -1.224199,0.0662 -1.762085,6.451631 -4.246279,1.936568 -6.013757,-2.613635 -0.805123,0.921673 3.32102,5.833384 -1.664261,4.262195 -6.069746,2.420417 0.06992,1.30296 6.403427,1.754832 1.984791,4.24628 -2.649498,6.006532 0.889514,0.772979 5.704822,-3.256725 4.587343,1.607198 2.255975,6.094659 1.226335,-0.01449 1.783249,-6.410646 4.165927,-2.081205 6.283444,2.688876 0.756917,-0.809178 -3.321012,-5.688747 1.426695,-4.466002 6.239296,-2.480975 -0.04287,-1.283384 -6.330305,-1.622539 -2.097289,-4.294491 2.653012,-6.146057 z"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#729fcf;stroke-width:4.1542;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<circle
transform="matrix(1.1037731,0,0,1.1037731,-95.071194,1.4359331)"
id="path3898"
style="fill:none;stroke:#729fcf;stroke-width:3.76364;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6;stroke-opacity:1"
cx="41.15683"
cy="40.103004"
r="8.6941996" />
<path
id="rect3663-8"
d="m -86.629206,8.7469513 8e-6,58.0000007 11.999996,-10e-7 v -24 h 11.999995 v -12 h -11.999995 v -9.999999 h 19.999998 V 8.7469513 Z"
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3214);fill-opacity:1;fill-rule:evenodd;stroke:#280000;stroke-width:4.1542;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
id="rect3663-8-3"
d="m -84.629206,10.746951 v 54 h 8.000003 v -24 h 11.999995 v -8 H -76.629203 V 18.746952 h 19.999998 v -8.000001 z"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ef2929;stroke-width:4.1542;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
</g>
<g
id="g3728"
transform="matrix(0.83232643,0,0,0.83232643,60.679451,-19.928729)"
style="stroke-width:1.21277;stroke-miterlimit:4;stroke-dasharray:none">
<path
id="path2865"
d="m -44.094898,15.992418 c 0,0 -8.9375,-0.625 -6.1875,9.875 h -7.6875 c 0,0 0.5,-11.875 13.875,-9.875 z"
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient3745);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3747);stroke-width:0.9107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" />
<g
style="fill:url(#linearGradient3753);fill-opacity:1;stroke:#3465a4;stroke-width:1.20137;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(-0.579051,-0.489228,-0.489228,0.579051,-7.331961,18.953884)"
id="g1878">
<path
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient3749);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3751);stroke-width:1.20137;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
d="M 44.306783,50.229694 C 62.821497,35.818859 49.664587,13.411704 22.462411,12.49765 L 22.113843,3.1515478 7.6245439,20.496754 22.714328,33.219189 c 0,0 -0.251917,-9.88122 -0.251917,-9.88122 18.82976,0.998977 32.981627,14.071729 21.844372,26.891725 z"
id="path1880" />
</g>
<g
id="g2805"
transform="matrix(-0.508536,-0.429651,-0.429651,0.508536,-11.198811,18.947994)"
style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1.36795;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
id="path2807"
d="M 51.389927,46.505946 C 60.510127,31.286196 47.050763,12.432359 19.628482,12.069755 L 19.342824,4.0507204 6.3413093,19.379475 19.809059,30.764589 c 0,0 -0.181765,-9.453243 -0.181765,-9.453243 18.244937,0.381972 34.783881,10.925246 31.762633,25.1946 z"
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient3755);stroke-width:1.36795;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" />
</g>
<path
id="path2811"
d="m -57.435311,22.082514 c 3.593435,-10.441273 16.443782,-6.144607 20.1875,-4.5 4.175307,0.211475 5.674736,-2.835004 9,-3 -14.049736,-9.7899965 -28.8125,-6.5000002 -29.1875,7.5 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.272222;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.21277;marker:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 29 KiB

@@ -0,0 +1,551 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64"
height="64"
id="svg2"
version="1.1">
<title
id="title882">PartDesign_MoveFeature</title>
<defs
id="defs4">
<linearGradient
id="linearGradient3829">
<stop
style="stop-color:#75507b;stop-opacity:1"
offset="0"
id="stop3831" />
<stop
style="stop-color:#ad7fa8;stop-opacity:1"
offset="1"
id="stop3833" />
</linearGradient>
<linearGradient
id="linearGradient3795">
<stop
style="stop-color:#f57900;stop-opacity:1"
offset="0"
id="stop3797" />
<stop
style="stop-color:#fcaf3e;stop-opacity:1"
offset="1"
id="stop3799" />
</linearGradient>
<linearGradient
id="linearGradient3934">
<stop
id="stop3936"
offset="0"
style="stop-color:#c9830a;stop-opacity:1;" />
<stop
id="stop3938"
offset="1"
style="stop-color:#c9830a;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3848">
<stop
style="stop-color:#bf3995;stop-opacity:1;"
offset="0"
id="stop3850" />
<stop
style="stop-color:#bf3995;stop-opacity:0;"
offset="1"
id="stop3852" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3848"
id="linearGradient3854"
x1="48.093758"
y1="1008.9432"
x2="38.347614"
y2="995.77875"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.77529578,-0.06923186,0.06310961,0.72219207,30.120639,289.13727)" />
<linearGradient
xlink:href="#linearGradient3775"
id="linearGradient3781"
x1="52.716118"
y1="26.490843"
x2="36.133701"
y2="13.440783"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.84821031,0,0,0.80134799,9.4347167,988.8022)" />
<linearGradient
id="linearGradient3775">
<stop
style="stop-color:#0061e6;stop-opacity:1;"
offset="0"
id="stop3777" />
<stop
style="stop-color:#0061e6;stop-opacity:0;"
offset="1"
id="stop3779" />
</linearGradient>
<linearGradient
y2="5.601934"
x2="34.596375"
y1="25.452681"
x1="47.099728"
gradientTransform="matrix(0.72500566,-0.07035626,0.06715982,0.68170903,97.583428,1026.7212)"
gradientUnits="userSpaceOnUse"
id="linearGradient3004"
xlink:href="#linearGradient3775" />
<linearGradient
xlink:href="#linearGradient3848-3"
id="linearGradient3854-9"
x1="48.093758"
y1="1008.9432"
x2="38.032986"
y2="999.64392"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.77529578,-0.06923186,0.06310961,0.72219207,-48.394623,284.99564)" />
<linearGradient
id="linearGradient3848-3">
<stop
style="stop-color:#bf3995;stop-opacity:1;"
offset="0"
id="stop3850-0" />
<stop
style="stop-color:#bf3995;stop-opacity:0;"
offset="1"
id="stop3852-2" />
</linearGradient>
<linearGradient
y2="996.14545"
x2="36.858414"
y1="1008.9432"
x1="48.093758"
gradientTransform="matrix(1.0220271,-0.0694911,0.02166527,1.2488507,31.644662,-245.52192)"
gradientUnits="userSpaceOnUse"
id="linearGradient3915"
xlink:href="#linearGradient3934" />
<linearGradient
xlink:href="#linearGradient3795"
id="linearGradient3801"
x1="12"
y1="1044.3622"
x2="13"
y2="1033.3622"
gradientUnits="userSpaceOnUse" />
<linearGradient
xlink:href="#linearGradient3829"
id="linearGradient3835"
x1="45"
y1="1040.3622"
x2="62"
y2="1037.3622"
gradientUnits="userSpaceOnUse" />
<linearGradient
xlink:href="#linearGradient3829-5"
id="linearGradient3841-7"
gradientUnits="userSpaceOnUse"
x1="45"
y1="1040.3622"
x2="62"
y2="1037.3622" />
<linearGradient
id="linearGradient3829-5">
<stop
style="stop-color:#75507b;stop-opacity:1"
offset="0"
id="stop3831-3" />
<stop
style="stop-color:#ad7fa8;stop-opacity:1"
offset="1"
id="stop3833-5" />
</linearGradient>
<linearGradient
y2="1037.3622"
x2="62"
y1="1040.3622"
x1="45"
gradientUnits="userSpaceOnUse"
id="linearGradient3860"
xlink:href="#linearGradient3829-5" />
<linearGradient
xlink:href="#linearGradient3829-2"
id="linearGradient3841-1"
gradientUnits="userSpaceOnUse"
x1="45"
y1="1040.3622"
x2="62"
y2="1037.3622" />
<linearGradient
id="linearGradient3829-2">
<stop
style="stop-color:#75507b;stop-opacity:1"
offset="0"
id="stop3831-7" />
<stop
style="stop-color:#ad7fa8;stop-opacity:1"
offset="1"
id="stop3833-0" />
</linearGradient>
<linearGradient
y2="27.588112"
x2="17.243532"
y1="54.588112"
x1="27.243532"
gradientTransform="translate(65.756467,954.77401)"
gradientUnits="userSpaceOnUse"
id="linearGradient69056"
xlink:href="#linearGradient4383" />
<linearGradient
id="linearGradient4383">
<stop
id="stop4385"
offset="0"
style="stop-color:#3465a4;stop-opacity:1" />
<stop
id="stop4387"
offset="1"
style="stop-color:#729fcf;stop-opacity:1" />
</linearGradient>
<linearGradient
gradientTransform="translate(68.285649,958.77634)"
gradientUnits="userSpaceOnUse"
y2="34.585785"
x2="44.714352"
y1="45.585785"
x1="48.714352"
id="linearGradient4399"
xlink:href="#linearGradient4393" />
<linearGradient
id="linearGradient4393">
<stop
id="stop4395"
offset="0"
style="stop-color:#204a87;stop-opacity:1" />
<stop
id="stop4397"
offset="1"
style="stop-color:#3465a4;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="34.585785"
x2="44.714352"
y1="45.585785"
x1="48.714352"
gradientTransform="translate(54.285649,939.77634)"
gradientUnits="userSpaceOnUse"
id="linearGradient69042"
xlink:href="#linearGradient4393" />
<linearGradient
xlink:href="#linearGradient4383"
id="linearGradient1001"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(65.756467,954.77401)"
x1="27.243532"
y1="54.588112"
x2="17.243532"
y2="27.588112" />
<linearGradient
xlink:href="#linearGradient4393"
id="linearGradient1003"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(68.285649,958.77634)"
x1="48.714352"
y1="45.585785"
x2="44.714352"
y2="34.585785" />
<linearGradient
xlink:href="#linearGradient4393"
id="linearGradient1005"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(54.285649,939.77634)"
x1="48.714352"
y1="45.585785"
x2="44.714352"
y2="34.585785" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1.6173222,0,0,0.58341935,-131.2612,-1035.2381)"
gradientUnits="userSpaceOnUse"
id="radialGradient3757"
xlink:href="#linearGradient8662" />
<linearGradient
id="linearGradient8662">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop8664" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop8666" />
</linearGradient>
<linearGradient
y2="24.842253"
x2="37.124462"
y1="30.748846"
x1="32.647972"
gradientTransform="matrix(1.0856435,0,0,1.0856435,64.810432,971.84991)"
gradientUnits="userSpaceOnUse"
id="linearGradient3759"
xlink:href="#linearGradient2690" />
<linearGradient
id="linearGradient2690">
<stop
style="stop-color:#c4d7eb;stop-opacity:1;"
offset="0"
id="stop2692" />
<stop
style="stop-color:#c4d7eb;stop-opacity:0;"
offset="1"
id="stop2694" />
</linearGradient>
<linearGradient
y2="24.842253"
x2="37.124462"
y1="31.455952"
x1="36.713837"
gradientTransform="matrix(1.0856435,0,0,1.0856435,64.810432,971.84991)"
gradientUnits="userSpaceOnUse"
id="linearGradient3761"
xlink:href="#linearGradient2682" />
<linearGradient
id="linearGradient2682">
<stop
style="stop-color:#3977c3;stop-opacity:1;"
offset="0"
id="stop2684" />
<stop
style="stop-color:#89aedc;stop-opacity:0;"
offset="1"
id="stop2686" />
</linearGradient>
<linearGradient
y2="26.649363"
x2="53.588623"
y1="23.667896"
x1="18.935766"
gradientUnits="userSpaceOnUse"
id="linearGradient3767"
xlink:href="#linearGradient2402" />
<linearGradient
id="linearGradient2402">
<stop
style="stop-color:#729fcf;stop-opacity:1;"
offset="0"
id="stop2404" />
<stop
style="stop-color:#528ac5;stop-opacity:1;"
offset="1"
id="stop2406" />
</linearGradient>
<linearGradient
y2="50.939667"
x2="45.380436"
y1="45.264122"
x1="46.834816"
gradientUnits="userSpaceOnUse"
id="linearGradient3769"
xlink:href="#linearGradient2871" />
<linearGradient
id="linearGradient2871">
<stop
style="stop-color:#3465a4;stop-opacity:1;"
offset="0"
id="stop2873" />
<stop
style="stop-color:#3465a4;stop-opacity:1"
offset="1"
id="stop2875" />
</linearGradient>
<linearGradient
y2="26.048164"
x2="52.854095"
y1="26.048164"
x1="5.9649177"
gradientUnits="userSpaceOnUse"
id="linearGradient3771"
xlink:href="#linearGradient2797" />
<linearGradient
id="linearGradient2797">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2799" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2801" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient2402"
id="linearGradient1083"
gradientUnits="userSpaceOnUse"
x1="18.935766"
y1="23.667896"
x2="53.588623"
y2="26.649363" />
<linearGradient
xlink:href="#linearGradient2871"
id="linearGradient1085"
gradientUnits="userSpaceOnUse"
x1="46.834816"
y1="45.264122"
x2="45.380436"
y2="50.939667" />
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>PartDesign_MoveFeature</dc:title>
<dc:date>12-01-2021</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:subject>
<rdf:Bag />
</dc:subject>
<dc:contributor>
<cc:Agent>
<dc:title></dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(0,-988.36218)">
<path
style="fill:none;stroke:#2e3436;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 10,1008.3622 H 42 32 v 26 h 14"
id="path3929" />
<path
style="fill:none;stroke:#d3d7cf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 8,1008.3622 H 42 32 v 26 h 14"
id="path3929-0" />
<g
id="g933"
transform="matrix(0.45454461,0,0,0.45454461,5.8182532,555.2893)">
<path
style="fill:url(#linearGradient69056);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="m 76,1006.3622 v -28.00002 l 14,5 v 14 l 14,5.00002 v 14 z"
id="path4381" />
<path
style="fill:url(#linearGradient4399);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="m 104,1016.3622 v -14 l 18,-17.00002 v 13 z"
id="path4391" />
<path
style="fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="m 76,978.36218 20,-16.00005 13,4.99995 -19,16.0001 z"
id="path4403" />
<path
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
d="M 78.008035,1004.9684 78,981.36218 l 10,4 v 13 l 14,5.00002 0.008,10.1848 z"
id="path4381-7" />
<path
style="fill:none;stroke:#3465a4;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
d="m 106.00504,1011.5304 -0.005,-8.1682 14,-13.00002 0.002,7.1768 z"
id="path4391-0" />
<path
id="path69038"
d="m 90,997.36218 19,-17 13,5 -18,17.00002 z"
style="fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<path
id="path69040"
d="m 90,997.36218 v -14 l 19,-16.0001 v 13.0001 z"
style="fill:url(#linearGradient69042);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<path
id="path69044"
d="m 92,993.36218 v -9 l 15,-13.0001 v 8.0001 z"
style="fill:none;stroke:#3465a4;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<g
transform="matrix(0.45454461,0,0,0.45454461,5.7273606,583.74384)"
id="g933-4">
<path
id="path4381-6"
d="m 76,1006.3622 v -28.00002 l 14,5 v 14 l 14,5.00002 v 14 z"
style="fill:url(#linearGradient1001);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<path
id="path4391-5"
d="m 104,1016.3622 v -14 l 18,-17.00002 v 13 z"
style="fill:url(#linearGradient1003);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<path
id="path4403-9"
d="m 76,978.36218 20,-16.00005 13,4.99995 -19,16.0001 z"
style="fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
<path
id="path4381-7-8"
d="M 78.008035,1004.9684 78,981.36218 l 10,4 v 13 l 14,5.00002 0.008,10.1848 z"
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" />
<path
id="path4391-0-0"
d="m 106.00504,1011.5304 -0.005,-8.1682 14,-13.00002 0.002,7.1768 z"
style="fill:none;stroke:#3465a4;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none" />
<path
style="fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="m 90,997.36218 19,-17 13,5 -18,17.00002 z"
id="path69038-1" />
<path
style="fill:url(#linearGradient1005);fill-opacity:1;fill-rule:nonzero;stroke:#0b1521;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="m 90,997.36218 v -14 l 19,-16.0001 v 13.0001 z"
id="path69040-3" />
<path
style="fill:none;stroke:#3465a4;stroke-width:2;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
d="m 92,993.36218 v -9 l 15,-13.0001 v 8.0001 z"
id="path69044-7" />
</g>
<g
id="g1100"
transform="matrix(0,-1,-1,0,1019.3622,1107.3622)">
<path
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient3759);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3761);stroke-width:1.08351;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
d="m 95.615566,1008.1511 c 0,0 9.702934,0.6785 6.717424,-10.72071 h 8.44184 c 0,1.63129 -0.63878,12.89201 -15.159264,10.72071 z"
id="path2839" />
<g
id="g2779"
transform="matrix(0.62864295,0.5311272,0.5311272,-0.62864295,56.211024,1005.0011)"
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient3767);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3769);stroke-width:1.31657;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none">
<path
id="path2781"
d="M 44.306783,50.229694 C 62.821497,35.818859 49.664587,13.411704 22.462411,12.49765 L 22.399432,3.0690297 7.793943,20.424005 22.462411,33.006349 c 0,0 0,-9.66838 0,-9.66838 18.82976,0.998977 32.981627,14.071729 21.844372,26.891725 z"
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:url(#linearGradient1083);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1085);stroke-width:1.31657;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" />
</g>
<path
id="path2791"
d="m 72.477789,1013.3079 0.06785,-16.14893 14.045512,-0.40711 -4.764751,5.62234 4.198428,2.5765 c -3.256931,2.4427 -4.939188,2.6295 -6.024831,5.4115 l -3.058104,-2.291 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.272222;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.4429;stroke-miterlimit:4;stroke-dasharray:none;marker:none" />
<g
style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1.49913;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(0.5520888,0.46644782,0.46644782,-0.5520888,60.496966,1005.0068)"
id="g2793">
<path
style="color:#000000;display:block;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient3771);stroke-width:1.49913;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
d="M 51.090265,45.943705 C 60.210465,30.723955 46.631614,12.20113 19.485058,11.948579 L 19.513464,3.7032834 6.5341979,19.296639 19.367661,30.26876 c 0,0 0.05562,-9.006878 0.05562,-9.006878 17.527815,-0.223909 35.195185,10.103372 31.666984,24.681823 z"
id="path2795" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

@@ -0,0 +1,524 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="64px"
height="64px"
id="svg3612"
version="1.1">
<title
id="title964">PartDesign_MoveFeatureInTree</title>
<defs
id="defs3614">
<marker
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;">
<path
id="path3835"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible">
<path
id="path3832"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible">
<path
id="path3826"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<linearGradient
id="linearGradient3144-6">
<stop
id="stop3146-9"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop3148-2"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3701">
<stop
id="stop3703"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop3705"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient3144-6"
id="radialGradient3688"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
cx="225.26402"
cy="672.79736"
fx="225.26402"
fy="672.79736"
r="34.345188" />
<linearGradient
id="linearGradient3708">
<stop
id="stop3710"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop3712"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3864-0-0">
<stop
id="stop3866-5-7"
offset="0"
style="stop-color:#0619c0;stop-opacity:1;" />
<stop
id="stop3868-7-6"
offset="1"
style="stop-color:#379cfb;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#ffaa00;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#faff2b;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3864-0">
<stop
id="stop3866-5"
offset="0"
style="stop-color:#0619c0;stop-opacity:1;" />
<stop
id="stop3868-7"
offset="1"
style="stop-color:#379cfb;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient5048">
<stop
style="stop-color:black;stop-opacity:0;"
offset="0"
id="stop5050" />
<stop
id="stop5056"
offset="0.5"
style="stop-color:black;stop-opacity:1;" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop5052" />
</linearGradient>
<linearGradient
id="linearGradient3841-0-3">
<stop
id="stop3843-1-3"
offset="0"
style="stop-color:#0619c0;stop-opacity:1;" />
<stop
id="stop3845-0-8"
offset="1"
style="stop-color:#379cfb;stop-opacity:1;" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
fy="114.5684"
fx="20.892099"
r="5.256"
cy="114.5684"
cx="20.892099"
id="aigrd2">
<stop
id="stop15566"
style="stop-color:#F0F0F0"
offset="0" />
<stop
id="stop15568"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
offset="1.0000000" />
</radialGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
fy="64.567902"
fx="20.892099"
r="5.257"
cy="64.567902"
cx="20.892099"
id="aigrd3">
<stop
id="stop15573"
style="stop-color:#F0F0F0"
offset="0" />
<stop
id="stop15575"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
offset="1.0000000" />
</radialGradient>
<linearGradient
id="linearGradient15662">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop15664" />
<stop
style="stop-color:#f8f8f8;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop15666" />
</linearGradient>
<radialGradient
r="86.70845"
fy="35.736916"
fx="33.966679"
cy="35.736916"
cx="33.966679"
gradientTransform="matrix(0.96049297,0,0,1.041132,-52.144249,-702.33158)"
gradientUnits="userSpaceOnUse"
id="radialGradient4452"
xlink:href="#linearGradient259" />
<linearGradient
id="linearGradient259">
<stop
style="stop-color:#fafafa;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop260" />
<stop
style="stop-color:#bbbbbb;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop261" />
</linearGradient>
<radialGradient
r="37.751713"
fy="3.7561285"
fx="8.824419"
cy="3.7561285"
cx="8.824419"
gradientTransform="matrix(0.96827297,0,0,1.032767,-48.790699,-701.68513)"
gradientUnits="userSpaceOnUse"
id="radialGradient4454"
xlink:href="#linearGradient269" />
<linearGradient
id="linearGradient269">
<stop
style="stop-color:#a3a3a3;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop270" />
<stop
style="stop-color:#4c4c4c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop271" />
</linearGradient>
<linearGradient
id="linearGradient4095">
<stop
style="stop-color:#005bff;stop-opacity:1;"
offset="0"
id="stop4097" />
<stop
style="stop-color:#c1e3f7;stop-opacity:1;"
offset="1"
id="stop4099" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient4247"
id="linearGradient4253"
x1="394.15784"
y1="185.1304"
x2="434.73947"
y2="140.22731"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.94231826,0,0,0.94231826,23.727549,8.8262536)" />
<linearGradient
id="linearGradient4247">
<stop
style="stop-color:#2e8207;stop-opacity:1;"
offset="0"
id="stop4249" />
<stop
style="stop-color:#52ff00;stop-opacity:1;"
offset="1"
id="stop4251" />
</linearGradient>
<linearGradient
y2="140.22731"
x2="434.73947"
y1="185.1304"
x1="394.15784"
gradientTransform="matrix(0.94231826,0,0,0.94231826,23.727549,8.8262536)"
gradientUnits="userSpaceOnUse"
id="linearGradient5087"
xlink:href="#linearGradient4247" />
<marker
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart-9"
style="overflow:visible">
<path
id="path3832-1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(0.4,0,0,0.4,4,0)" />
</marker>
<marker
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend-2"
style="overflow:visible">
<path
id="path3835-7"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
</marker>
<linearGradient
id="linearGradient3895-5">
<stop
style="stop-color:#729fcf;stop-opacity:1;"
offset="0"
id="stop3897-6" />
<stop
style="stop-color:#204a87;stop-opacity:1;"
offset="1"
id="stop3899-2" />
</linearGradient>
<linearGradient
id="linearGradient3094-7-8">
<stop
id="stop3096-6-7"
offset="0"
style="stop-color:#4e9a06;stop-opacity:1" />
<stop
id="stop3098-0-4"
offset="1"
style="stop-color:#8ae234;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="42"
x2="46"
y1="54"
x1="48"
gradientUnits="userSpaceOnUse"
id="linearGradient3834-3-0"
xlink:href="#linearGradient3895-5" />
<linearGradient
xlink:href="#linearGradient3895-5"
id="linearGradient3834-3-0-5"
gradientUnits="userSpaceOnUse"
x1="48"
y1="54"
x2="46"
y2="42" />
</defs>
<metadata
id="metadata3617">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>PartDesign_MoveFeatureInTree</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>[bitacovir]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>OpenSCAD_RemoveSubtree</dc:title>
<dc:date>12-01-2021</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier></dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title></dc:title>
</cc:Agent>
</dc:contributor>
<dc:subject>
<rdf:Bag />
</dc:subject>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<g
id="g4294-3"
transform="translate(2.7790302,-33.031848)">
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="rect4258-1-7-4-3-6"
width="26.38888"
height="9.9999943"
x="21"
y="51"
rx="0"
ry="0" />
<rect
y="53"
x="23"
height="6"
width="22"
id="rect3852-5-5-7"
style="fill:#d3d7cf;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g4294-3-5"
transform="translate(0.73689359,-1.1438838)">
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="rect4258-1-7-4-3-6-3"
width="26.38888"
height="9.9999943"
x="21"
y="51"
rx="0"
ry="0" />
<rect
y="53"
x="23"
height="6"
width="22"
id="rect3852-5-5-7-5"
style="fill:#d3d7cf;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<path
id="path5098-3"
d="M 8.999987,12.999998 V 55 h 12"
style="fill:none;stroke:#2e3436;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path5100-6"
d="m 23,23 -14.000013,-2e-6"
style="fill:none;stroke:#2e3436;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path5098-36"
d="M 8.999987,12.999998 V 55 h 12"
style="fill:none;stroke:#d3d7cf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path5100-7"
d="m 24,23 -15.000013,-2e-6"
style="fill:none;stroke:#d3d7cf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
ry="0"
rx="0"
y="3"
x="3.0000002"
height="10"
width="37.999989"
id="rect4258-1-7-4-5"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<rect
style="fill:#d3d7cf;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3852-5-3"
width="34"
height="6"
x="5"
y="5" />
<g
id="g4294"
transform="translate(8.5333989,-17.066798)">
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#eeeeec;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="rect4258-1-7-4-3"
width="26.38888"
height="9.9999943"
x="21"
y="51"
rx="0"
ry="0" />
<rect
y="53"
x="23"
height="6"
width="22"
id="rect3852-5-5"
style="fill:#d3d7cf;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<path
id="path5098-3-2"
d="M 17,24 V 39 H 29"
style="fill:none;stroke:#2e3436;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path5098-36-6"
d="M 17,23 V 39 H 29"
style="fill:none;stroke:#d3d7cf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g985"
transform="translate(-32.24262,11.414205)">
<g
id="g3830-3-2"
transform="rotate(-135,58.322322,11.665485)">
<path
transform="translate(0,-16)"
id="path3050-5-8"
d="M 57,57 V 39 l -6,6 -8,-8 -6,6 8,8 -6,6 z"
style="fill:url(#linearGradient3834-3-0);fill-opacity:1;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
<path
transform="translate(0,-16)"
id="path3820-6-9"
d="M 43.84375,55 H 55 V 43.84375 l -4,3.984375 -8,-8 L 39.828125,43 47.84375,51 Z"
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
<g
transform="matrix(1,0,0,-1,-32.242834,51.899718)"
id="g985-6">
<g
transform="rotate(-135,58.322322,11.665485)"
id="g3830-3-2-7">
<path
style="fill:url(#linearGradient3834-3-0-5);fill-opacity:1;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="M 57,57 V 39 l -6,6 -8,-8 -6,6 8,8 -6,6 z"
id="path3050-5-8-3"
transform="translate(0,-16)" />
<path
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 43.84375,55 H 55 V 43.84375 l -4,3.984375 -8,-8 L 39.828125,43 47.84375,51 Z"
id="path3820-6-9-2"
transform="translate(0,-16)" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

+4 -1
View File
@@ -43,7 +43,7 @@ pairs, or a placement, or a vector</UserDocu>
</Methode>
<Methode Name="setFromGCode">
<Documentation>
<UserDocu>toGCode(): returns a GCode representation of the command</UserDocu>
<UserDocu>setFromGCode(): sets the path from the contents of the given GCode string</UserDocu>
</Documentation>
</Methode>
<Methode Name="transform">
@@ -51,5 +51,8 @@ pairs, or a placement, or a vector</UserDocu>
<UserDocu>transform(Placement): returns a copy of this command transformed by the given placement</UserDocu>
</Documentation>
</Methode>
<ClassDeclarations>
mutable Py::Dict parameters_copy_dict;
</ClassDeclarations>
</PythonExport>
</GenerateModel>
+17 -4
View File
@@ -56,6 +56,11 @@ std::string CommandPy::representation(void) const
return str.str();
}
//
// Py::Dict parameters_copy_dict is now a class member to avoid delete/create/copy on every read access from python code
// Now the pre-filled Py::Dict is returned which is more consistent with normal python behaviour.
// It should be cleared whenever the c++ Parameters object is changed eg setParameters() or other objects invalidate its content, eg setPlacement()
// https://forum.freecadweb.org/viewtopic.php?f=15&t=50583
PyObject *CommandPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
{
@@ -117,6 +122,7 @@ int CommandPy::PyInit(PyObject* args, PyObject* kwd)
}
getCommandPtr()->Parameters[ckey]=cvalue;
}
parameters_copy_dict.clear();
return 0;
}
PyErr_Clear(); // set by PyArg_ParseTuple()
@@ -157,11 +163,13 @@ void CommandPy::setName(Py::String arg)
Py::Dict CommandPy::getParameters(void) const
{
Py::Dict dict;
for(std::map<std::string,double>::iterator i = getCommandPtr()->Parameters.begin(); i != getCommandPtr()->Parameters.end(); ++i) {
dict.setItem(i->first, Py::Float(i->second));
// dict now a class member , https://forum.freecadweb.org/viewtopic.php?f=15&t=50583
if (parameters_copy_dict.length()==0) {
for(std::map<std::string,double>::iterator i = getCommandPtr()->Parameters.begin(); i != getCommandPtr()->Parameters.end(); ++i) {
parameters_copy_dict.setItem(i->first, Py::Float(i->second));
}
}
return dict;
return parameters_copy_dict;
}
void CommandPy::setParameters(Py::Dict arg)
@@ -200,6 +208,7 @@ void CommandPy::setParameters(Py::Dict arg)
throw Py::TypeError("The dictionary can only contain number values");
}
getCommandPtr()->Parameters[ckey]=cvalue;
parameters_copy_dict.clear();
}
}
@@ -224,6 +233,7 @@ PyObject* CommandPy::setFromGCode(PyObject *args)
std::string gcode(pstr);
try {
getCommandPtr()->setFromGCode(gcode);
parameters_copy_dict.clear();
}
catch (const Base::Exception& e) {
PyErr_SetString(PyExc_ValueError, e.what());
@@ -249,6 +259,7 @@ void CommandPy::setPlacement(Py::Object arg)
Py::Type PlacementType(pyType.o);
if(arg.isType(PlacementType)) {
getCommandPtr()->setFromPlacement( *static_cast<Base::PlacementPy*>((*arg))->getPlacementPtr() );
parameters_copy_dict.clear();
} else
throw Py::TypeError("Argument must be a placement");
}
@@ -259,6 +270,7 @@ PyObject* CommandPy::transform(PyObject *args)
if ( PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &placement) ) {
Base::PlacementPy *p = static_cast<Base::PlacementPy*>(placement);
Path::Command trCmd = getCommandPtr()->transform( *p->getPlacementPtr() );
parameters_copy_dict.clear();
return new CommandPy(new Path::Command(trCmd));
} else
throw Py::TypeError("Argument must be a placement");
@@ -302,6 +314,7 @@ int CommandPy::setCustomAttributes(const char* attr, PyObject* obj)
return 0;
}
getCommandPtr()->Parameters[satt]=cvalue;
parameters_copy_dict.clear();
return 1;
}
}
+18 -1
View File
@@ -96,6 +96,10 @@ SET(PathScripts_SRCS
PathScripts/PathProfileFaces.py
PathScripts/PathProfileFacesGui.py
PathScripts/PathProfileGui.py
PathScripts/PathProperty.py
PathScripts/PathPropertyBag.py
PathScripts/PathPropertyBagGui.py
PathScripts/PathPropertyEditor.py
PathScripts/PathSanity.py
PathScripts/PathSelection.py
PathScripts/PathSetupSheet.py
@@ -158,13 +162,14 @@ SET(PathScripts_post_SRCS
SET(Tools_Bit_SRCS
Tools/Bit/45degree_chamfer.fctb
Tools/Bit/5mm-thread-cutter.fctb
Tools/Bit/5mm_Drill.fctb
Tools/Bit/5mm_Endmill.fctb
Tools/Bit/60degree_Vbit.fctb
Tools/Bit/6mm_Ball_End.fctb
Tools/Bit/6mm_Bullnose.fctb
Tools/Bit/slittingsaw.fctb
Tools/Bit/probe.fctb
Tools/Bit/slittingsaw.fctb
)
SET(Tools_Library_SRCS
@@ -197,6 +202,7 @@ SET(PathTests_SRCS
PathTests/TestPathOpTools.py
PathTests/TestPathPost.py
PathTests/TestPathPreferences.py
PathTests/TestPathPropertyBag.py
PathTests/TestPathSetupSheet.py
PathTests/TestPathStock.py
PathTests/TestPathThreadMilling.py
@@ -207,6 +213,9 @@ SET(PathTests_SRCS
PathTests/TestPathUtil.py
PathTests/TestPathVcarve.py
PathTests/TestPathVoronoi.py
PathTests/Tools/Bit/test-path-tool-bit-bit-00.fctb
PathTests/Tools/Library/test-path-tool-bit-library-00.fctl
PathTests/Tools/Shape/test-path-tool-bit-shape-00.fcstd
PathTests/boxtest.fcstd
PathTests/test_centroid_00.ngc
PathTests/test_geomop.fcstd
@@ -278,6 +287,14 @@ INSTALL(
Mod/Path/PathTests
)
INSTALL(
DIRECTORY
PathTests/Tools
DESTINATION
Mod/Path/PathTests
)
INSTALL(
FILES
${PathScripts_post_SRCS}
+3
View File
@@ -97,6 +97,7 @@
<file>panels/DogboneEdit.ui</file>
<file>panels/DressupPathBoundary.ui</file>
<file>panels/DragKnifeEdit.ui</file>
<file>panels/DressUpLeadInOutEdit.ui</file>
<file>panels/HoldingTagsEdit.ui</file>
<file>panels/PageBaseGeometryEdit.ui</file>
<file>panels/PageBaseHoleGeometryEdit.ui</file>
@@ -120,6 +121,8 @@
<file>panels/PageOpVcarveEdit.ui</file>
<file>panels/PathEdit.ui</file>
<file>panels/PointEdit.ui</file>
<file>panels/PropertyBag.ui</file>
<file>panels/PropertyCreate.ui</file>
<file>panels/SetupGlobal.ui</file>
<file>panels/SetupOp.ui</file>
<file>panels/ToolBitEditor.ui</file>
@@ -0,0 +1,381 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskPanel</class>
<widget class="QWidget" name="TaskPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>452</height>
</rect>
</property>
<property name="windowTitle">
<string>LeadInOut</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QToolBox" name="toolBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>400</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="tabSpacing">
<number>6</number>
</property>
<widget class="QWidget" name="Dressup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>363</width>
<height>403</height>
</rect>
</property>
<attribute name="label">
<string>Dressup</string>
</attribute>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>361</width>
<height>401</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>180</width>
<height>190</height>
</size>
</property>
<property name="title">
<string>LeadIn</string>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>161</width>
<height>151</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="chkLeadIn">
<property name="text">
<string>Enable LeadIn</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Extend In:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="dsbExtendIn">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Style In:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cboStyleIn">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>Arc</string>
</property>
</item>
<item>
<property name="text">
<string>Tangent</string>
</property>
</item>
<item>
<property name="text">
<string>Perpendicular</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="maximumSize">
<size>
<width>180</width>
<height>190</height>
</size>
</property>
<property name="title">
<string>LeadOut</string>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>161</width>
<height>151</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="chkLeadOut">
<property name="text">
<string>Enable LeadOut</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Extend Out:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="dsbExtendOut">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Style Out:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cboStyleOut">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>Arc</string>
</property>
</item>
<item>
<property name="text">
<string>Tangent</string>
</property>
</item>
<item>
<property name="text">
<string>Perpendicular</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Length / Radius:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="dsbLen">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Radius / Center:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cboRadius">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>Radius</string>
</property>
</item>
<item>
<property name="text">
<string>Center</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QCheckBox" name="chkKeepToolDown">
<property name="text">
<string>Keep Tool Down</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkRapidPlunge">
<property name="text">
<string>Rapid Plunge</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QCheckBox" name="chkLayers">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Apply Lead In/Out on all layers&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Include Layers</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkUseCRC">
<property name="text">
<string>Use Machine CRC</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>250</height>
<width>476</width>
<height>342</height>
</rect>
</property>
<property name="sizePolicy">
@@ -23,94 +23,28 @@
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path_BaseGeometry.svg</normaloff>:/icons/Path_BaseGeometry.svg</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<widget class="QPushButton" name="geometryImportButton">
<property name="text">
<string>Import</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="deleteBase">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove the selected list items from the list of base geometries. The operation will not be applied to them.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QComboBox" name="geometryImportList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;List of operations with Base Geometry in current Job.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QListWidget" name="baseList">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select one or more features in the 3d view and press 'Add' to add them as the base items for this operation.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Selected features can be deleted entirely.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="clearBase">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clears list of base geometries.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="addBase">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add selected features to the list of base geometries for this operation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>All objects will be processed using the same operation properties</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QPushButton" name="addBase">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add selected features to the list of base geometries for this operation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<item row="3" column="1">
<widget class="QPushButton" name="deleteBase">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove the selected list items from the list of base geometries. The operation will not be applied to them.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="7" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -123,14 +57,70 @@
</property>
</spacer>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="clearBase">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clears list of base geometries.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>All objects will be processed using the same operation properties</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QListWidget" name="baseList">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select one or more features in the 3d view and press 'Add' to add them as the base items for this operation.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Selected features can be deleted entirely.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="geometryImportButton">
<property name="text">
<string>Import</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QComboBox" name="geometryImportList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;List of operations with Base Geometry in current Job.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>baseList</tabstop>
<tabstop>addBase</tabstop>
<tabstop>deleteBase</tabstop>
<tabstop>clearBase</tabstop>
</tabstops>
<resources>
<include location="../Path.qrc"/>
</resources>
+17 -17
View File
@@ -31,8 +31,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>549</width>
<height>628</height>
<width>146</width>
<height>378</height>
</rect>
</property>
<attribute name="label">
@@ -112,8 +112,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>98</width>
<height>28</height>
<width>96</width>
<height>26</height>
</rect>
</property>
<attribute name="label">
@@ -281,7 +281,7 @@
<string>G54</string>
</property>
<property name="checkState">
<enum>Checked</enum>
<enum>Unchecked</enum>
</property>
</item>
<item>
@@ -431,8 +431,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>536</width>
<height>1291</height>
<width>545</width>
<height>896</height>
</rect>
</property>
<attribute name="label">
@@ -1002,8 +1002,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>419</width>
<height>548</height>
<width>213</width>
<height>321</height>
</rect>
</property>
<attribute name="label">
@@ -1096,7 +1096,7 @@
</widget>
</item>
<item row="1" column="3">
<widget class="Gui::QuantitySpinBox" name="setupClearanceHeightOffs" native="true">
<widget class="Gui::QuantitySpinBox" name="setupClearanceHeightOffs">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ClearanceHeightOffset - can be used by expressions to set the default ClearanceHeight for new operations.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Default: &amp;quot;3 mm&amp;quot;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@@ -1123,7 +1123,7 @@
</widget>
</item>
<item row="3" column="3">
<widget class="Gui::QuantitySpinBox" name="setupSafeHeightOffs" native="true">
<widget class="Gui::QuantitySpinBox" name="setupSafeHeightOffs">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;SafeHeightOffset can be for expressions to set the SafeHeight for new operations.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Default: &amp;quot;5 mm&amp;quot;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@@ -1185,8 +1185,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>549</width>
<height>628</height>
<width>317</width>
<height>173</height>
</rect>
</property>
<attribute name="label">
@@ -1285,8 +1285,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>208</width>
<height>160</height>
<width>138</width>
<height>112</height>
</rect>
</property>
<attribute name="label">
@@ -1310,7 +1310,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::QuantitySpinBox" name="setupRapidHorizontal" native="true">
<widget class="Gui::QuantitySpinBox" name="setupRapidHorizontal">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -1330,7 +1330,7 @@
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::QuantitySpinBox" name="setupRapidVertical" native="true">
<widget class="Gui::QuantitySpinBox" name="setupRapidVertical">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>552</width>
<height>651</height>
</rect>
</property>
<property name="windowTitle">
<string>Property Bag</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableView" name="table">
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::AllEditTriggers</set>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="remove">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="modify">
<property name="text">
<string>Modify...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="add">
<property name="text">
<string>Add...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>table</tabstop>
<tabstop>add</tabstop>
<tabstop>remove</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>452</height>
</rect>
</property>
<property name="windowTitle">
<string>Create Property</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="propertyName">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Name of property.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="propertyGroup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The category group the property belongs to.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelGroup">
<property name="text">
<string>Group</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="propertyType">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The type of the property value.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelType">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="propertyEnum">
<property name="placeholderText">
<string>val1,val2,val3,...</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QTextEdit" name="propertyInfo">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ToolTip to be displayed when user hovers mouse over property.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelEnum">
<property name="text">
<string>Enums</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelInfo">
<property name="text">
<string>ToolTip</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QWidget" name="widget_2" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="createAnother">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check if you want to create several properties in a batch.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Create another</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>propertyName</tabstop>
<tabstop>propertyGroup</tabstop>
<tabstop>propertyType</tabstop>
<tabstop>propertyEnum</tabstop>
<tabstop>propertyInfo</tabstop>
<tabstop>createAnother</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>401</width>
<width>489</width>
<height>715</height>
</rect>
</property>
@@ -17,7 +17,7 @@
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -32,6 +32,12 @@
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Tool Bit</string>
</property>
@@ -65,6 +71,12 @@
</item>
<item row="1" column="1">
<widget class="QWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
@@ -83,6 +95,9 @@
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The file which defines the type and shape of the Tool Bit.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="placeholderText">
<string>path</string>
</property>
</widget>
</item>
<item>
@@ -104,7 +119,7 @@
<item>
<widget class="QGroupBox" name="bitParams">
<property name="title">
<string>Bit Parameter</string>
<string>Parameter</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
@@ -184,7 +199,7 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTableView" name="attrTable">
<widget class="QTreeView" name="attrTree">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
@@ -200,9 +215,6 @@
<property name="editTriggers">
<set>QAbstractItemView::AllEditTriggers</set>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item>
</layout>
@@ -173,6 +173,12 @@
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item>
+4
View File
@@ -154,6 +154,10 @@ class PathWorkbench (Workbench):
if extracmdlist:
self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path")], extracmdlist)
self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path")], ["Separator"])
self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path"), QtCore.QT_TRANSLATE_NOOP("Path", "Utils")],
["Path_PropertyBag"])
self.dressupcmds = dressupcmdlist
curveAccuracy = PathPreferences.defaultLibAreaCurveAccuracy()
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathLog as PathLog
import PathScripts.PathOpGui as PathOpGui
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathCustom as PathCustom
import PathScripts.PathOpGui as PathOpGui
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathDeburr as PathDeburr
import PathScripts.PathGui as PathGui
import PathScripts.PathLog as PathLog
@@ -1108,6 +1108,7 @@ class CommandDressupDogbone:
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtGui
@@ -24,6 +24,7 @@
from __future__ import print_function
import FreeCAD
import FreeCADGui
import Path
import PathScripts.PathDressup as PathDressup
import PathScripts.PathGeom as PathGeom
@@ -32,7 +33,7 @@ import PathScripts.PathUtils as PathUtils
import math
import copy
from PySide import QtCore
from PySide import QtCore, QtGui
__doc__ = """LeadInOut Dressup MASHIN-CRC USE ROLL-ON ROLL-OFF to profile"""
@@ -463,13 +464,124 @@ class ObjectDressup:
commands = newpath
return Path.Path(commands)
class ViewProviderDressup:
class TaskPanel:
def __init__(self, obj, view):
self.obj = obj
self.viewProvider = view
self.form = FreeCADGui.PySideUic.loadUi(":/panels/DressUpLeadInOutEdit.ui")
self.setupUi()
FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupLeadInOut", "Edit LeadInOut Dress-up"))
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel)
def modifyStandardButtons(self, buttonBox):
self.buttonBox = buttonBox
def setDirty(self):
self.isDirty = True
self.buttonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(True)
def setClean(self):
self.isDirty = False
self.buttonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(False)
def clicked(self, button):
# callback for standard buttons
if button == QtGui.QDialogButtonBox.Apply:
self.updateModel()
FreeCAD.ActiveDocument.recompute()
if button == QtGui.QDialogButtonBox.Cancel:
self.abort()
def abort(self):
FreeCAD.ActiveDocument.abortTransaction()
self.cleanup(True)
def reject(self):
FreeCAD.ActiveDocument.abortTransaction()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def accept(self):
self.getFields()
FreeCAD.ActiveDocument.commitTransaction()
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def cleanup(self, gui):
self.viewProvider.clearTaskPanel()
if gui:
#FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def getFields(self):
self.obj.LeadIn = self.form.chkLeadIn.isChecked()
self.obj.LeadOut = self.form.chkLeadOut.isChecked()
self.obj.Length = self.form.dsbLen.value()
self.obj.ExtendLeadIn = self.form.dsbExtendIn.value()
self.obj.ExtendLeadOut = self.form.dsbExtendOut.value()
self.obj.StyleOn = str(self.form.cboStyleIn.currentText())
self.obj.StyleOff = str(self.form.cboStyleOut.currentText())
self.obj.RadiusCenter = str(self.form.cboRadius.currentText())
self.obj.RapidPlunge = self.form.chkRapidPlunge.isChecked()
self.obj.IncludeLayers = self.form.chkLayers.isChecked()
self.obj.KeepToolDown = self.form.chkKeepToolDown.isChecked()
self.obj.UseMachineCRC = self.form.chkUseCRC.isChecked()
self.updateUI()
self.obj.Proxy.execute(self.obj)
def updateUI(self):
self.form.chkLeadIn.setChecked(self.obj.LeadIn)
self.form.chkLeadOut.setChecked(self.obj.LeadOut)
self.form.chkRapidPlunge.setChecked(self.obj.RapidPlunge)
self.form.chkLayers.setChecked(self.obj.IncludeLayers)
self.form.chkKeepToolDown.setChecked(self.obj.KeepToolDown)
self.form.chkUseCRC.setChecked(self.obj.UseMachineCRC)
self.form.dsbLen.setValue(self.obj.Length)
self.form.dsbExtendIn.setValue(self.obj.ExtendLeadIn)
#self.form.dsbExtendIn.setEnabled(self.obj.LeadIn)
self.form.dsbExtendOut.setValue(self.obj.ExtendLeadOut)
#self.form.dsbExtendOut.setEnabled(self.obj.LeadOut)
self.form.cboStyleIn.setCurrentIndex(self.form.cboStyleIn.findText(self.obj.StyleOn))
#self.form.cboStyleIn.setEnabled(self.obj.LeadIn)
self.form.cboStyleOut.setCurrentIndex(self.form.cboStyleIn.findText(self.obj.StyleOff))
#self.form.cboStyleOut.setEnabled(self.obj.LeadOut)
self.form.cboRadius.setCurrentIndex(self.form.cboRadius.findText(self.obj.RadiusCenter))
def updateModel(self):
self.getFields()
FreeCAD.ActiveDocument.recompute()
def setFields(self):
self.updateUI()
def open(self):
pass
def setupUi(self):
self.setFields()
class ViewProviderDressup:
def __init__(self, vobj):
self.obj = vobj.Object
self.setEdit(vobj)
def attach(self, vobj):
self.obj = vobj.Object
self.panel = None
def claimChildren(self):
if hasattr(self.obj.Base, "InList"):
@@ -484,6 +596,18 @@ class ViewProviderDressup:
# FreeCADGui.ActiveDocument.getObject(obj.Base.Name).Visibility = False
return [self.obj.Base]
def setEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
FreeCADGui.Control.closeDialog()
panel = TaskPanel(vobj.Object, self)
FreeCADGui.Control.showDialog(panel)
panel.setupUi()
return True
def unsetEdit(self, vobj, mode=0):
if self.panel:
self.panel.abort()
def onDelete(self, arg1=None, arg2=None):
'''this makes sure that the base operation is added back to the project and visible'''
# pylint: disable=unused-argument
@@ -502,6 +626,9 @@ class ViewProviderDressup:
def __setstate__(self, state):
# pylint: disable=unused-argument
return None
def clearTaskPanel(self):
self.panel = None
class CommandPathDressupLeadInOut:
@@ -519,7 +646,6 @@ class CommandPathDressupLeadInOut:
return False
def Activated(self):
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
@@ -543,9 +669,9 @@ class CommandPathDressupLeadInOut:
FreeCADGui.doCommand('job = PathScripts.PathUtils.findParentJob(base)')
FreeCADGui.doCommand('obj.Base = base')
FreeCADGui.doCommand('job.Proxy.addOperation(obj, base)')
FreeCADGui.doCommand('dbo.setup(obj)')
FreeCADGui.doCommand('obj.ViewObject.Proxy = PathScripts.PathDressupLeadInOut.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('Gui.ActiveDocument.getObject(base.Name).Visibility = False')
FreeCADGui.doCommand('dbo.setup(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathDressupPathBoundary as PathDressupPathBoundary
import PathScripts.PathLog as PathLog
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathGeom as PathGeom
import PathScripts.PathGetPoint as PathGetPoint
import PathScripts.PathDressupHoldingTags as PathDressupTag
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui
import PathScripts.PathDrilling as PathDrilling
import PathScripts.PathGui as PathGui
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathEngrave as PathEngrave
import PathScripts.PathLog as PathLog
import PathScripts.PathOpGui as PathOpGui
+7
View File
@@ -48,6 +48,7 @@ def updateInputField(obj, prop, widget, onBeforeChange=None):
If onBeforeChange is specified it is called before a new value is assigned to the property.
Returns True if a new value was assigned, False otherwise (new value is the same as the current).
'''
PathLog.track()
value = widget.property('rawValue')
attr = PathUtil.getProperty(obj, prop)
attrValue = attr.Value if hasattr(attr, 'Value') else attr
@@ -98,10 +99,12 @@ class QuantitySpinBox:
PathLog.track(widget)
self.widget = widget
self.onBeforeChange = onBeforeChange
self.prop = None
self.attachTo(obj, prop)
def attachTo(self, obj, prop = None):
'''attachTo(obj, prop=None) ... use an existing editor for the given object and property'''
PathLog.track(self.prop, prop)
self.obj = obj
self.prop = prop
if obj and prop:
@@ -119,12 +122,14 @@ class QuantitySpinBox:
def expression(self):
'''expression() ... returns the expression if one is bound to the property'''
PathLog.track(self.prop, self.valid)
if self.valid:
return self.widget.property('expression')
return ''
def setMinimum(self, quantity):
'''setMinimum(quantity) ... set the minimum'''
PathLog.track(self.prop, self.valid)
if self.valid:
value = quantity.Value if hasattr(quantity, 'Value') else quantity
self.widget.setProperty('setMinimum', value)
@@ -133,6 +138,7 @@ class QuantitySpinBox:
'''updateSpinBox(quantity=None) ... update the display value of the spin box.
If no value is provided the value of the bound property is used.
quantity can be of type Quantity or Float.'''
PathLog.track(self.prop, self.valid)
if self.valid:
if quantity is None:
quantity = PathUtil.getProperty(self.obj, self.prop)
@@ -141,6 +147,7 @@ class QuantitySpinBox:
def updateProperty(self):
'''updateProperty() ... update the bound property with the value from the spin box'''
PathLog.track(self.prop, self.valid)
if self.valid:
return updateInputField(self.obj, self.prop, self.widget, self.onBeforeChange)
return None
+1
View File
@@ -66,6 +66,7 @@ def Startup():
# from PathScripts import PathProfileEdgesGui
# from PathScripts import PathProfileFacesGui
from PathScripts import PathProfileGui
from PathScripts import PathPropertyBagGui
from PathScripts import PathSanity
from PathScripts import PathSetupSheetGui
from PathScripts import PathSimpleCopy
+1
View File
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui
import PathScripts.PathHelix as PathHelix
import PathScripts.PathLog as PathLog
+15 -1
View File
@@ -56,6 +56,9 @@ class JobTemplate:
PostProcessor = 'Post'
PostProcessorArgs = 'PostArgs'
PostProcessorOutputFile = 'Output'
Fixtures = 'Fixtures'
OrderOutputBy = 'OrderOutputBy'
SplitOutput = 'SplitOutput'
SetupSheet = 'SetupSheet'
Stock = 'Stock'
# TCs are grouped under Tools in a job, the template refers to them directly though
@@ -121,7 +124,6 @@ class ObjectJob:
obj.addProperty("App::PropertyLink", "Stock", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Solid object to be used as stock."))
obj.addProperty("App::PropertyLink", "Operations", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Compound path of all operations in the order they are processed."))
#obj.addProperty("App::PropertyLinkList", "ToolController", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of tool controllers available for this job."))
obj.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Split output into multiple gcode files"))
obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way"))
@@ -350,6 +352,15 @@ class ObjectJob:
if attrs.get(JobTemplate.Stock):
obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock))
if attrs.get(JobTemplate.Fixtures):
obj.Fixtures = [x for y in attrs.get(JobTemplate.Fixtures) for x in y]
if attrs.get(JobTemplate.OrderOutputBy):
obj.OrderOutputBy = attrs.get(JobTemplate.OrderOutputBy)
if attrs.get(JobTemplate.SplitOutput):
obj.SplitOutput = attrs.get(JobTemplate.SplitOutput)
PathLog.debug("setting tool controllers (%d)" % len(tcs))
obj.Tools.Group = tcs
else:
@@ -364,6 +375,9 @@ class ObjectJob:
if obj.PostProcessor:
attrs[JobTemplate.PostProcessor] = obj.PostProcessor
attrs[JobTemplate.PostProcessorArgs] = obj.PostProcessorArgs
attrs[JobTemplate.Fixtures] = [{f: True} for f in obj.Fixtures]
attrs[JobTemplate.OrderOutputBy] = obj.OrderOutputBy
attrs[JobTemplate.SplitOutput] = obj.SplitOutput
if obj.PostProcessorOutputFile:
attrs[JobTemplate.PostProcessorOutputFile] = obj.PostProcessorOutputFile
attrs[JobTemplate.GeometryTolerance] = str(obj.GeometryTolerance.Value)
+1
View File
@@ -31,6 +31,7 @@ from PySide import QtCore, QtGui
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathJob as PathJob
import PathScripts.PathJobCmd as PathJobCmd
import PathScripts.PathJobDlg as PathJobDlg
+4 -1
View File
@@ -422,7 +422,10 @@ class ObjectOp(object):
zmax = max(zmax, bb.ZMax)
for sub in sublist:
try:
fbb = base.Shape.getElement(sub).BoundBox
if sub:
fbb = base.Shape.getElement(sub).BoundBox
else:
fbb = base.Shape.BoundBox
zmin = max(zmin, faceZmin(bb, fbb))
zmax = max(zmax, fbb.ZMax)
except Part.OCCError as e:
+18 -13
View File
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathGeom as PathGeom
import PathScripts.PathGetPoint as PathGetPoint
import PathScripts.PathGui as PathGui
@@ -42,13 +43,8 @@ __author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Base classes and framework for Path operation's UI"
LOGLEVEL = False
if LOGLEVEL:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
def translate(context, text, disambig=None):
@@ -566,6 +562,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
return False
def addBase(self):
PathLog.track()
if self.addBaseGeometry(FreeCADGui.Selection.getSelectionEx()):
# self.obj.Proxy.execute(self.obj)
self.setFields(self.obj)
@@ -606,12 +603,13 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
def importBaseGeometry(self):
opLabel = str(self.form.geometryImportList.currentText())
ops = FreeCAD.ActiveDocument.getObjectsByLabel(opLabel)
if ops.__len__() > 1:
if len(ops) > 1:
msg = translate('PathOpGui', 'Mulitiple operations are labeled as')
msg += " {}\n".format(opLabel)
FreeCAD.Console.PrintWarning(msg)
for (base, subList) in ops[0].Base:
FreeCADGui.Selection.addSelection(base, subList)
(base, subList) = ops[0].Base[0]
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(base, subList)
self.addBase()
def registerSignalHandlers(self, obj):
@@ -635,11 +633,18 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
# Set base geometry list window to resize based on contents
# Code reference:
# https://stackoverflow.com/questions/6337589/qlistwidget-adjust-size-to-content
# ml: disabling this logic because I can't get it to work on HPD monitor.
# On my systems the values returned by the list object are also incorrect on
# creation, leading to a list object of size 15. count() always returns 0 until
# the list is actually displayed. The same is true for sizeHintForRow(0), which
# returns -1 until the widget is rendered. The widget claims to have a size of
# (100, 30), once it becomes visible the size is (535, 192).
# Leaving the framework here in case somebody figures out how to set this up
# properly.
qList = self.form.baseList
# qList.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
col = qList.width() # 300
row = (qList.count() + qList.frameWidth()) * 15
qList.setFixedSize(col, row)
#qList.setMinimumHeight(row)
PathLog.debug("baseList({}, {}) {} * {}".format(qList.size(), row, qList.count(), qList.sizeHintForRow(0)))
class TaskPanelBaseLocationPage(TaskPanelPage):
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathGui as PathGui
import PathScripts.PathOpGui as PathOpGui
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathGeom as PathGeom
import PathScripts.PathGui as PathGui
import PathScripts.PathLog as PathLog
+8 -20
View File
@@ -151,26 +151,9 @@ def searchPathsPost():
return paths
def searchPathsTool(sub='Bit'):
def searchPathsTool(sub):
paths = []
if 'Bit' == sub:
paths.append("{}/Bit".format(os.path.dirname(lastPathToolLibrary())))
paths.append(lastPathToolBit())
if 'Library' == sub:
paths.append(lastPathToolLibrary())
if 'Shape' == sub:
paths.append(lastPathToolShape())
def appendPath(p, sub):
if p:
paths.append(os.path.join(p, 'Tools', sub))
paths.append(os.path.join(p, sub))
paths.append(p)
appendPath(defaultFilePath(), sub)
appendPath(macroFilePath(), sub)
appendPath(os.path.join(FreeCAD.getHomePath(), "Mod/Path/"), sub)
paths.append(os.path.join(FreeCAD.getHomePath(), 'Mod', 'Path', 'Tools', sub))
return paths
@@ -263,15 +246,19 @@ def setDefaultTaskPanelLayout(style):
def experimentalFeaturesEnabled():
return preferences().GetBool(EnableExperimentalFeatures, False)
def suppressAllSpeedsWarning():
return preferences().GetBool(WarningSuppressAllSpeeds, True)
def suppressRapidSpeedsWarning():
return suppressAllSpeedsWarning() or preferences().GetBool(WarningSuppressRapidSpeeds, True)
def suppressSelectionModeWarning():
return preferences().GetBool(WarningSuppressSelectionMode, True)
def suppressOpenCamLibWarning():
return preferences().GetBool(WarningSuppressOpenCamLib, True)
@@ -316,7 +303,8 @@ def lastPathToolLibrary():
def setLastPathToolLibrary(path):
PathLog.track(path)
curLib = lastFileToolLibrary()
if os.path.split(curLib)[0] != path:
PathLog.debug('curLib: {}'.format(curLib))
if curLib and os.path.split(curLib)[0] != path:
setLastFileToolLibrary('') # a path is known but not specific file
return preferences().SetString(LastPathToolLibrary, path)
+1
View File
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathProbe as PathProbe
import PathScripts.PathOpGui as PathOpGui
import PathScripts.PathGui as PathGui
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathGui as PathGui
import PathScripts.PathOpGui as PathOpGui
import PathScripts.PathProfile as PathProfile
+201
View File
@@ -0,0 +1,201 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <[email protected]> *
# * *
# * 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. *
# * *
# * This program 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 this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import PathScripts.PathLog as PathLog
__title__ = "Property type abstraction for editing purposes"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Prototype objects to allow extraction of setup sheet values and editing."
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
#PathLog.trackModule(PathLog.thisModule())
class Property(object):
'''Base class for all prototype properties'''
def __init__(self, name, propType, category, info):
self.name = name
self.propType = propType
self.category = category
self.info = info
self.editorMode = 0
self.value = None
def setValue(self, value):
self.value = value
def getValue(self):
return self.value
def setEditorMode(self, mode):
self.editorMode = mode
def displayString(self):
if self.value is None:
t = self.typeString()
p = 'an' if t[0] in ['A', 'E', 'I', 'O', 'U'] else 'a'
return "%s %s" % (p, t)
return self.value
def typeString(self):
return "Property"
def setupProperty(self, obj, name, category, value):
created = False
if not hasattr(obj, name):
obj.addProperty(self.propType, name, category, self.info)
self.initProperty(obj, name)
created = True
setattr(obj, name, value)
return created
def initProperty(self, obj, name):
pass
def setValueFromString(self, string):
self.setValue(self.valueFromString(string))
def valueFromString(self, string):
return string
class PropertyEnumeration(Property):
def typeString(self):
return "Enumeration"
def setValue(self, value):
if list == type(value):
self.enums = value # pylint: disable=attribute-defined-outside-init
else:
super(PropertyEnumeration, self).setValue(value)
def getEnumValues(self):
return self.enums
def initProperty(self, obj, name):
setattr(obj, name, self.enums)
class PropertyQuantity(Property):
def displayString(self):
if self.value is None:
return Property.displayString(self)
return self.value.getUserPreferred()[0]
class PropertyAngle(PropertyQuantity):
def typeString(self):
return "Angle"
class PropertyDistance(PropertyQuantity):
def typeString(self):
return "Distance"
class PropertyLength(PropertyQuantity):
def typeString(self):
return "Length"
class PropertyPercent(Property):
def typeString(self):
return "Percent"
class PropertyFloat(Property):
def typeString(self):
return "Float"
def valueFromString(self, string):
return float(string)
class PropertyInteger(Property):
def typeString(self):
return "Integer"
def valueFromString(self, string):
return int(string)
class PropertyBool(Property):
def typeString(self):
return "Bool"
def valueFromString(self, string):
return bool(string)
class PropertyString(Property):
def typeString(self):
return "String"
class PropertyMap(Property):
def typeString(self):
return "Map"
def displayString(self, value):
return str(value)
class OpPrototype(object):
PropertyType = {
'App::PropertyAngle': PropertyAngle,
'App::PropertyBool': PropertyBool,
'App::PropertyDistance': PropertyDistance,
'App::PropertyEnumeration': PropertyEnumeration,
'App::PropertyFile': PropertyString,
'App::PropertyFloat': PropertyFloat,
'App::PropertyFloatConstraint': Property,
'App::PropertyFloatList': Property,
'App::PropertyInteger': PropertyInteger,
'App::PropertyIntegerList': PropertyInteger,
'App::PropertyLength': PropertyLength,
'App::PropertyLink': Property,
'App::PropertyLinkList': Property,
'App::PropertyLinkSubListGlobal': Property,
'App::PropertyMap': PropertyMap,
'App::PropertyPercent': PropertyPercent,
'App::PropertyString': PropertyString,
'App::PropertyStringList': Property,
'App::PropertyVectorDistance': Property,
'App::PropertyVectorList': Property,
'Part::PropertyPartShape': Property,
}
def __init__(self, name):
self.Label = name
self.properties = {}
self.DoNotSetDefaultValues = True
self.Proxy = None
def __setattr__(self, name, val):
if name in ['Label', 'DoNotSetDefaultValues', 'properties', 'Proxy']:
if name == 'Proxy':
val = None # make sure the proxy is never set
return super(OpPrototype, self).__setattr__(name, val)
self.properties[name].setValue(val)
def addProperty(self, typeString, name, category, info = None):
prop = self.PropertyType[typeString](name, typeString, category, info)
self.properties[name] = prop
return self
def setEditorMode(self, name, mode):
self.properties[name].setEditorMode(mode)
def getProperty(self, name):
return self.properties[name]
def setupProperties(self, setup):
return [p for p in self.properties if p.name in setup]
+113
View File
@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <[email protected]> *
# * *
# * 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. *
# * *
# * This program 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 this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import PySide
__title__ = 'Generic property container to store some values.'
__author__ = 'sliptonic (Brad Collette)'
__url__ = 'https://www.freecadweb.org'
__doc__ = 'A generic container for typed properties in arbitrary categories.'
def translate(context, text, disambig=None):
return PySide.QtCore.QCoreApplication.translate(context, text, disambig)
SupportedPropertyType = {
'Angle' : 'App::PropertyAngle',
'Bool' : 'App::PropertyBool',
'Distance' : 'App::PropertyDistance',
'Enumeration' : 'App::PropertyEnumeration',
'File' : 'App::PropertyFile',
'Float' : 'App::PropertyFloat',
'Integer' : 'App::PropertyInteger',
'Length' : 'App::PropertyLength',
'Percent' : 'App::PropertyPercent',
'String' : 'App::PropertyString',
}
def getPropertyTypeName(o):
for typ in SupportedPropertyType:
if SupportedPropertyType[typ] == o:
return typ
raise IndexError()
class PropertyBag(object):
'''Property container object.'''
CustomPropertyGroups = 'CustomPropertyGroups'
CustomPropertyGroupDefault = 'User'
def __init__(self, obj):
obj.addProperty('App::PropertyStringList', self.CustomPropertyGroups, 'Base', PySide.QtCore.QT_TRANSLATE_NOOP('PathPropertyBag', 'List of custom property groups'))
self.onDocumentRestored(obj)
def __getstate__(self):
return None
def __setstate__(self, state):
return None
def onDocumentRestored(self, obj):
self.obj = obj
obj.setEditorMode(self.CustomPropertyGroups, 2) # hide
def getCustomProperties(self):
'''getCustomProperties() ... Return a list of all custom properties created in this container.'''
return [p for p in self.obj.PropertiesList if self.obj.getGroupOfProperty(p) in self.obj.CustomPropertyGroups]
def addCustomProperty(self, propertyType, name, group=None, desc=None):
'''addCustomProperty(propertyType, name, group=None, desc=None) ... adds a custom property and tracks its group.'''
if desc is None:
desc = ''
if group is None:
group = self.CustomPropertyGroupDefault
groups = self.obj.CustomPropertyGroups
if not group in groups:
groups.append(group)
self.obj.CustomPropertyGroups = groups
self.obj.addProperty(propertyType, name, group, desc)
def refreshCustomPropertyGroups(self):
'''refreshCustomPropertyGroups() ... removes empty property groups, should be called after deleting properties.'''
customGroups = []
for p in self.obj.PropertiesList:
group = self.obj.getGroupOfProperty(p)
if group in self.obj.CustomPropertyGroups and not group in customGroups:
customGroups.append(group)
self.obj.CustomPropertyGroups = customGroups
def Create(name = 'PropertyBag'):
obj = FreeCAD.ActiveDocument.addObject('App::FeaturePython', name)
obj.Proxy = PropertyBag(obj)
return obj
def IsPropertyBag(obj):
'''Returns True if the supplied object is a property container (or its Proxy).'''
if type(obj) == PropertyBag:
return True
if hasattr(obj, 'Proxy'):
return IsPropertyBag(obj.Proxy)
return False
@@ -0,0 +1,425 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <[email protected]> *
# * *
# * 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. *
# * *
# * This program 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 this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathIconViewProvider as PathIconViewProvider
import PathScripts.PathLog as PathLog
import PathScripts.PathPropertyBag as PathPropertyBag
import PathScripts.PathPropertyEditor as PathPropertyEditor
import PathScripts.PathUtil as PathUtil
from PySide import QtCore, QtGui
__title__ = "Property Bag Editor"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Task panel editor for a PropertyBag"
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
#PathLog.trackModule(PathLog.thisModule())
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class ViewProvider(object):
'''ViewProvider for a PropertyBag.
It's sole job is to provide an icon and invoke the TaskPanel on edit.'''
def __init__(self, vobj, name):
PathLog.track(name)
vobj.Proxy = self
self.icon = name
# mode = 2
self.obj = None
self.vobj = None
def attach(self, vobj):
PathLog.track()
self.vobj = vobj
self.obj = vobj.Object
def getIcon(self):
return ":/icons/Path-SetupSheet.svg"
def __getstate__(self):
return None
def __setstate__(self, state):
# pylint: disable=unused-argument
return None
def getDisplayMode(self, mode):
# pylint: disable=unused-argument
return 'Default'
def setEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
PathLog.track()
taskPanel = TaskPanel(vobj)
FreeCADGui.Control.closeDialog()
FreeCADGui.Control.showDialog(taskPanel)
taskPanel.setupUi()
return True
def unsetEdit(self, vobj, mode):
# pylint: disable=unused-argument
FreeCADGui.Control.closeDialog()
return
def claimChildren(self):
return []
def doubleClicked(self, vobj):
self.setEdit(vobj)
class Delegate(QtGui.QStyledItemDelegate):
RoleObject = QtCore.Qt.UserRole + 1
RoleProperty = QtCore.Qt.UserRole + 2
RoleEditor = QtCore.Qt.UserRole + 3
#def paint(self, painter, option, index):
# #PathLog.track(index.column(), type(option))
def createEditor(self, parent, option, index):
# pylint: disable=unused-argument
editor = PathPropertyEditor.Editor(index.data(self.RoleObject), index.data(self.RoleProperty))
index.model().setData(index, editor, self.RoleEditor)
return editor.widget(parent)
def setEditorData(self, widget, index):
PathLog.track(index.row(), index.column())
index.data(self.RoleEditor).setEditorData(widget)
def setModelData(self, widget, model, index):
# pylint: disable=unused-argument
PathLog.track(index.row(), index.column())
editor = index.data(self.RoleEditor)
editor.setModelData(widget)
index.model().setData(index, editor.displayString(), QtCore.Qt.DisplayRole)
def updateEditorGeometry(self, widget, option, index):
# pylint: disable=unused-argument
widget.setGeometry(option.rect)
class PropertyCreate(object):
def __init__(self, obj, grp, typ, another):
self.obj = obj
self.form = FreeCADGui.PySideUic.loadUi(":panels/PropertyCreate.ui")
obj.Proxy.refreshCustomPropertyGroups()
for g in sorted(obj.CustomPropertyGroups):
self.form.propertyGroup.addItem(g)
if grp:
self.form.propertyGroup.setCurrentText(grp)
for t in sorted(PathPropertyBag.SupportedPropertyType):
self.form.propertyType.addItem(t)
if PathPropertyBag.SupportedPropertyType[t] == typ:
typ = t
if typ:
self.form.propertyType.setCurrentText(typ)
else:
self.form.propertyType.setCurrentText('String')
self.form.createAnother.setChecked(another)
self.form.propertyGroup.currentTextChanged.connect(self.updateUI)
self.form.propertyGroup.currentIndexChanged.connect(self.updateUI)
self.form.propertyName.textChanged.connect(self.updateUI)
self.form.propertyType.currentIndexChanged.connect(self.updateUI)
self.form.propertyEnum.textChanged.connect(self.updateUI)
def updateUI(self):
typeSet = True
if self.propertyIsEnumeration():
self.form.labelEnum.setEnabled(True)
self.form.propertyEnum.setEnabled(True)
typeSet = self.form.propertyEnum.text().strip() != ''
else:
self.form.labelEnum.setEnabled(False)
self.form.propertyEnum.setEnabled(False)
if self.form.propertyEnum.text().strip():
self.form.propertyEnum.setText('')
ok = self.form.buttonBox.button(QtGui.QDialogButtonBox.Ok)
if typeSet and self.propertyName() and self.propertyGroup():
ok.setEnabled(True)
else:
ok.setEnabled(False)
def propertyName(self):
return self.form.propertyName.text().strip()
def propertyGroup(self):
return self.form.propertyGroup.currentText().strip()
def propertyType(self):
return PathPropertyBag.SupportedPropertyType[self.form.propertyType.currentText()].strip()
def propertyInfo(self):
return self.form.propertyInfo.toPlainText().strip()
def createAnother(self):
return self.form.createAnother.isChecked()
def propertyEnumerations(self):
return [s.strip() for s in self.form.propertyEnum.text().strip().split(',')]
def propertyIsEnumeration(self):
return self.propertyType() == 'App::PropertyEnumeration'
def exec_(self, name):
if name:
# property exists - this is an edit operation
self.form.propertyName.setText(name)
if self.propertyIsEnumeration():
self.form.propertyEnum.setText(','.join(self.obj.getEnumerationsOfProperty(name)))
self.form.propertyInfo.setText(self.obj.getDocumentationOfProperty(name))
self.form.labelName.setEnabled(False)
self.form.propertyName.setEnabled(False)
self.form.labelType.setEnabled(False)
self.form.propertyType.setEnabled(False)
self.form.createAnother.setEnabled(False)
else:
self.form.propertyName.setText('')
self.form.propertyInfo.setText('')
self.form.propertyEnum.setText('')
#self.form.propertyName.setFocus()
self.updateUI()
return self.form.exec_()
Panel = []
class TaskPanel(object):
ColumnName = 0
#ColumnType = 1
ColumnVal = 1
#TableHeaders = ['Property', 'Type', 'Value']
TableHeaders = ['Property', 'Value']
def __init__(self, vobj):
self.obj = vobj.Object
self.props = sorted(self.obj.Proxy.getCustomProperties())
self.form = FreeCADGui.PySideUic.loadUi(":panels/PropertyBag.ui")
# initialized later
self.model = None
self.delegate = None
FreeCAD.ActiveDocument.openTransaction(translate("PathPropertyBag", "Edit PropertyBag"))
Panel.append(self)
def updateData(self, topLeft, bottomRight):
pass
def _setupProperty(self, i, name):
typ = PathPropertyBag.getPropertyTypeName(self.obj.getTypeIdOfProperty(name))
val = PathUtil.getPropertyValueString(self.obj, name)
info = self.obj.getDocumentationOfProperty(name)
self.model.setData(self.model.index(i, self.ColumnName), name, QtCore.Qt.EditRole)
#self.model.setData(self.model.index(i, self.ColumnType), typ, QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, self.ColumnVal), self.obj, Delegate.RoleObject)
self.model.setData(self.model.index(i, self.ColumnVal), name, Delegate.RoleProperty)
self.model.setData(self.model.index(i, self.ColumnVal), val, QtCore.Qt.DisplayRole)
self.model.setData(self.model.index(i, self.ColumnName), typ, QtCore.Qt.ToolTipRole)
#self.model.setData(self.model.index(i, self.ColumnType), info, QtCore.Qt.ToolTipRole)
self.model.setData(self.model.index(i, self.ColumnVal), info, QtCore.Qt.ToolTipRole)
self.model.item(i, self.ColumnName).setEditable(False)
#self.model.item(i, self.ColumnType).setEditable(False)
def setupUi(self):
PathLog.track()
self.delegate = Delegate(self.form)
self.model = QtGui.QStandardItemModel(len(self.props), len(self.TableHeaders), self.form)
self.model.setHorizontalHeaderLabels(self.TableHeaders)
for i,name in enumerate(self.props):
self._setupProperty(i, name)
self.form.table.setModel(self.model)
self.form.table.setItemDelegateForColumn(self.ColumnVal, self.delegate)
self.form.table.resizeColumnsToContents()
self.model.dataChanged.connect(self.updateData)
self.form.table.selectionModel().selectionChanged.connect(self.propertySelected)
self.form.add.clicked.connect(self.propertyAdd)
self.form.remove.clicked.connect(self.propertyRemove)
self.form.modify.clicked.connect(self.propertyModify)
self.form.table.doubleClicked.connect(self.propertyModifyIndex)
self.propertySelected([])
def accept(self):
FreeCAD.ActiveDocument.commitTransaction()
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def reject(self):
FreeCAD.ActiveDocument.abortTransaction()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def propertySelected(self, selection):
PathLog.track()
if selection:
self.form.modify.setEnabled(True)
self.form.remove.setEnabled(True)
else:
self.form.modify.setEnabled(False)
self.form.remove.setEnabled(False)
def addCustomProperty(self, obj, dialog):
name = dialog.propertyName()
typ = dialog.propertyType()
grp = dialog.propertyGroup()
info = dialog.propertyInfo()
self.obj.Proxy.addCustomProperty(typ, name, grp, info)
if dialog.propertyIsEnumeration():
setattr(self.obj, name, dialog.propertyEnumerations())
return (name, info)
def propertyAdd(self):
PathLog.track()
more = False
grp = None
typ = None
while True:
dialog = PropertyCreate(self.obj, grp, typ, more)
if dialog.exec_(None):
# if we block signals the view doesn't get updated, surprise, surprise
#self.model.blockSignals(True)
name, info = self.addCustomProperty(self.obj, dialog)
index = 0
for i in range(self.model.rowCount()):
index = i
if self.model.item(i, self.ColumnName).data(QtCore.Qt.EditRole) > dialog.propertyName():
break
self.model.insertRows(index, 1)
self._setupProperty(index, name)
self.form.table.selectionModel().setCurrentIndex(self.model.index(index, 0), QtCore.QItemSelectionModel.Rows)
#self.model.blockSignals(False)
more = dialog.createAnother()
else:
more = False
if not more:
break
def propertyModifyIndex(self, index):
PathLog.track(index.row(), index.column())
row = index.row()
obj = self.model.item(row, self.ColumnVal).data(Delegate.RoleObject)
nam = self.model.item(row, self.ColumnVal).data(Delegate.RoleProperty)
grp = obj.getGroupOfProperty(nam)
typ = obj.getTypeIdOfProperty(nam)
dialog = PropertyCreate(self.obj, grp, typ, False)
if dialog.exec_(nam):
val = getattr(obj, nam)
obj.removeProperty(nam)
name, info = self.addCustomProperty(self.obj, dialog)
try:
setattr(obj, nam, val)
except:
# this can happen if the old enumeration value doesn't exist anymore
pass
newVal = PathUtil.getPropertyValueString(obj, nam)
self.model.setData(self.model.index(row, self.ColumnVal), newVal, QtCore.Qt.DisplayRole)
#self.model.setData(self.model.index(row, self.ColumnType), info, QtCore.Qt.ToolTipRole)
self.model.setData(self.model.index(row, self.ColumnVal), info, QtCore.Qt.ToolTipRole)
def propertyModify(self):
PathLog.track()
rows = []
for index in self.form.table.selectionModel().selectedIndexes():
row = index.row()
if row in rows:
continue
rows.append(row)
self.propertyModifyIndex(index)
def propertyRemove(self):
PathLog.track()
# first find all rows which need to be removed
rows = []
for index in self.form.table.selectionModel().selectedIndexes():
if not index.row() in rows:
rows.append(index.row())
# then remove them in reverse order so the indexes of the remaining rows
# to delete are still valid
for row in reversed(sorted(rows)):
self.obj.removeProperty(self.model.item(row).data(QtCore.Qt.EditRole))
self.model.removeRow(row)
def Create(name = 'PropertyBag'):
'''Create(name = 'PropertyBag') ... creates a new setup sheet'''
FreeCAD.ActiveDocument.openTransaction(translate("PathPropertyBag", "Create PropertyBag"))
pcont = PathPropertyBag.Create(name)
PathIconViewProvider.Attach(pcont.ViewObject, name)
return pcont
PathIconViewProvider.RegisterViewProvider('PropertyBag', ViewProvider)
class PropertyBagCreateCommand(object):
'''Command to create a property container object'''
def __init__(self):
pass
def GetResources(self):
return {'MenuText': translate('PathPropertyBag', 'Property Bag'),
'ToolTip': translate('PathPropertyBag', 'Creates an object which can be used to store reference properties.')}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
sel = FreeCADGui.Selection.getSelectionEx()
obj = Create()
body = None
if sel:
if 'PartDesign::Body' == sel[0].Object.TypeId:
body = sel[0].Object
elif hasattr(sel[0].Object, 'getParentGeoFeatureGroup'):
body = sel[0].Object.getParentGeoFeatureGroup()
if body:
obj.Label = 'Attributes'
group = body.Group
group.append(obj)
body.Group = group
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Path_PropertyBag', PropertyBagCreateCommand())
FreeCAD.Console.PrintLog("Loading PathPropertyBagGui ... done\n")
@@ -0,0 +1,228 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <[email protected]> *
# * *
# * 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. *
# * *
# * This program 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 this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import PathScripts.PathLog as PathLog
import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype
from PySide import QtCore, QtGui
__title__ = "Path Property Editor"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Task panel editor for Properties"
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
#PathLog.trackModule(PathLog.thisModule())
class _PropertyEditor(object):
'''Base class of all property editors - just outlines the TableView delegate interface.'''
def __init__(self, obj, prop):
self.obj = obj
self.prop = prop
def widget(self, parent):
'''widget(parent) ... called by the delegate to get a new editor widget.
Must be implemented by subclasses and return the widget.'''
pass # pylint: disable=unnecessary-pass
def setEditorData(self, widget):
'''setEditorData(widget) ... called by the delegate to initialize the editor.
The widget is the object returned by widget().
Must be implemented by subclasses.'''
pass # pylint: disable=unnecessary-pass
def setModelData(self, widget):
'''setModelData(widget) ... called by the delegate to store new values.
Must be implemented by subclasses.'''
pass # pylint: disable=unnecessary-pass
def propertyValue(self):
return self.obj.getPropertyByName(self.prop)
def setProperty(self, value):
setattr(self.obj, self.prop, value)
def displayString(self):
return self.propertyValue()
class _PropertyEditorBool(_PropertyEditor):
'''Editor for boolean values - uses a combo box.'''
def widget(self, parent):
return QtGui.QComboBox(parent)
def setEditorData(self, widget):
widget.clear()
widget.addItems([str(False), str(True)])
index = 1 if self.propertyValue() else 0
widget.setCurrentIndex(index)
def setModelData(self, widget):
self.setProperty(widget.currentText() == str(True))
class _PropertyEditorString(_PropertyEditor):
'''Editor for string values - uses a line edit.'''
def widget(self, parent):
return QtGui.QLineEdit(parent)
def setEditorData(self, widget):
text = '' if self.propertyValue() is None else self.propertyValue()
widget.setText(text)
def setModelData(self, widget):
self.setProperty(widget.text())
class _PropertyEditorQuantity(_PropertyEditor):
def widget(self, parent):
return QtGui.QLineEdit(parent)
def setEditorData(self, widget):
quantity = self.propertyValue()
if quantity is None:
quantity = self.defaultQuantity()
widget.setText(quantity.getUserPreferred()[0])
def defaultQuantity(self):
pass
def setModelData(self, widget):
self.setProperty(FreeCAD.Units.Quantity(widget.text()))
def displayString(self):
if self.propertyValue() is None:
return ''
return self.propertyValue().getUserPreferred()[0]
class _PropertyEditorAngle(_PropertyEditorQuantity):
'''Editor for angle values - uses a line edit'''
def defaultQuantity(self):
return FreeCAD.Units.Quantity(0, FreeCAD.Units.Angle)
class _PropertyEditorLength(_PropertyEditorQuantity):
'''Editor for length values - uses a line edit.'''
def defaultQuantity(self):
return FreeCAD.Units.Quantity(0, FreeCAD.Units.Length)
class _PropertyEditorPercent(_PropertyEditor):
'''Editor for percent values - uses a spin box.'''
def widget(self, parent):
return QtGui.QSpinBox(parent)
def setEditorData(self, widget):
widget.setRange(0, 100)
value = self.propertyValue()
if value is None:
value = 0
widget.setValue(value)
def setModelData(self, widget):
self.setProperty(widget.value())
class _PropertyEditorInteger(_PropertyEditor):
'''Editor for integer values - uses a spin box.'''
def widget(self, parent):
return QtGui.QSpinBox(parent)
def setEditorData(self, widget):
value = self.propertyValue()
if value is None:
value = 0
widget.setValue(value)
def setModelData(self, widget):
self.setProperty(widget.value())
class _PropertyEditorFloat(_PropertyEditor):
'''Editor for float values - uses a double spin box.'''
def widget(self, parent):
return QtGui.QDoubleSpinBox(parent)
def setEditorData(self, widget):
value = self.propertyValue()
if value is None:
value = 0.0
widget.setValue(value)
def setModelData(self, widget):
self.setProperty(widget.value())
class _PropertyEditorFile(_PropertyEditor):
def widget(self, parent):
return QtGui.QLineEdit(parent)
def setEditorData(self, widget):
text = '' if self.propertyValue() is None else self.propertyValue()
widget.setText(text)
def setModelData(self, widget):
self.setProperty(widget.text())
class _PropertyEditorEnumeration(_PropertyEditor):
def widget(self, parent):
return QtGui.QComboBox(parent)
def setEditorData(self, widget):
widget.clear()
widget.addItems(self.obj.getEnumerationsOfProperty(self.prop))
widget.setCurrentText(self.propertyValue())
def setModelData(self, widget):
self.setProperty(widget.currentText())
_EditorFactory = {
'App::PropertyAngle' : _PropertyEditorAngle,
'App::PropertyBool' : _PropertyEditorBool,
'App::PropertyDistance' : _PropertyEditorLength,
'App::PropertyEnumeration' : _PropertyEditorEnumeration,
#'App::PropertyFile' : _PropertyEditorFile,
'App::PropertyFloat' : _PropertyEditorFloat,
'App::PropertyInteger' : _PropertyEditorInteger,
'App::PropertyLength' : _PropertyEditorLength,
'App::PropertyPercent' : _PropertyEditorPercent,
'App::PropertyString' : _PropertyEditorString,
}
def Types():
'''Return the types of properties supported.'''
return [t for t in _EditorFactory]
def Editor(obj, prop):
'''Returns an editor class to be used for the given property.'''
factory = _EditorFactory[obj.getTypeIdOfProperty(prop)]
if factory:
return factory(obj, prop)
return None
+5 -1
View File
@@ -34,7 +34,7 @@ __doc__ = "A container for all default values and job specific configuration val
_RegisteredOps = {}
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
@@ -55,11 +55,15 @@ class Template:
StartDepthExpression = 'StartDepthExpression'
FinalDepthExpression = 'FinalDepthExpression'
StepDownExpression = 'StepDownExpression'
Fixtures = 'Fixtures'
OrderOutputBy = 'OrderOutputBy'
SplitOutput = 'SplitOutput'
All = [HorizRapid, VertRapid, CoolantMode, SafeHeightOffset, SafeHeightExpression, ClearanceHeightOffset, ClearanceHeightExpression, StartDepthExpression, FinalDepthExpression, StepDownExpression]
def _traverseTemplateAttributes(attrs, codec):
PathLog.debug(attrs)
coded = {}
for key, value in PathUtil.keyValueIter(attrs):
if type(value) == dict:
+31 -33
View File
@@ -22,11 +22,11 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathGui as PathGui
import PathScripts.PathIconViewProvider as PathIconViewProvider
import PathScripts.PathLog as PathLog
import PathScripts.PathSetupSheet as PathSetupSheet
# import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype
import PathScripts.PathSetupSheetOpPrototypeGui as PathSetupSheetOpPrototypeGui
import PathScripts.PathUtil as PathUtil
@@ -37,18 +37,22 @@ __author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Task panel editor for a SetupSheet"
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
LOGLEVEL = False
if LOGLEVEL:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
class ViewProvider:
'''ViewProvider for a SetupSheet.
It's sole job is to provide an icon and invoke the TaskPanel on edit.'''
@@ -100,14 +104,11 @@ class ViewProvider:
def doubleClicked(self, vobj):
self.setEdit(vobj)
class Delegate(QtGui.QStyledItemDelegate):
PropertyRole = QtCore.Qt.UserRole + 1
EditorRole = QtCore.Qt.UserRole + 2
#def paint(self, painter, option, index):
# #PathLog.track(index.column(), type(option))
def createEditor(self, parent, option, index):
# pylint: disable=unused-argument
if index.data(self.EditorRole) is None:
@@ -130,6 +131,7 @@ class Delegate(QtGui.QStyledItemDelegate):
# pylint: disable=unused-argument
widget.setGeometry(option.rect)
class OpTaskPanel:
'''Editor for an operation's property default values.
The implementation is a simplified generic property editor with basically 3 fields
@@ -168,16 +170,16 @@ class OpTaskPanel:
self.model = QtGui.QStandardItemModel(len(self.props), 3, self.form)
self.model.setHorizontalHeaderLabels(['Set', 'Property', 'Value'])
for i,name in enumerate(self.props):
for i, name in enumerate(self.props):
prop = self.prototype.getProperty(name)
isset = hasattr(self.obj, self.propertyName(name))
if isset:
prop.setValue(getattr(self.obj, self.propertyName(name)))
self.model.setData(self.model.index(i, 0), isset, QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 2), prop, Delegate.PropertyRole)
self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole)
self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 2), prop, Delegate.PropertyRole)
self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole)
self.model.item(i, 0).setCheckable(True)
self.model.item(i, 0).setText('')
@@ -206,7 +208,7 @@ class OpTaskPanel:
def accept(self):
propertiesCreatedRemoved = False
for i,name in enumerate(self.props):
for i, name in enumerate(self.props):
prop = self.prototype.getProperty(name)
propName = self.propertyName(name)
enabled = self.model.item(i, 0).checkState() == QtCore.Qt.Checked
@@ -229,7 +231,7 @@ class OpsDefaultEditor:
def __init__(self, obj, form):
self.form = form
self.obj = obj
self.ops = sorted([OpTaskPanel(self.obj, name, op) for name, op in PathUtil.keyValueIter(PathSetupSheet._RegisteredOps)], key = lambda op: op.name) # pylint: disable=protected-access
self.ops = sorted([OpTaskPanel(self.obj, name, op) for name, op in PathUtil.keyValueIter(PathSetupSheet._RegisteredOps)], key=lambda op: op.name)
if form:
parent = form.tabOpDefaults
for op in self.ops:
@@ -245,10 +247,6 @@ class OpsDefaultEditor:
def accept(self):
if any([op.accept() for op in self.ops]):
PathLog.track()
#sel = FreeCADGui.Selection.getSelection()
#FreeCADGui.Selection.clearSelection()
#for o in sel:
# FreeCADGui.Selection.addSelection(o)
def getFields(self):
pass
@@ -264,7 +262,7 @@ class OpsDefaultEditor:
self.currentOp = self.form.opDefaultOp.itemData(current)
self.currentOp.form.show()
def updateModel(self, recomp = True):
def updateModel(self, recomp=True):
PathLog.track()
self.getFields()
self.updateUI()
@@ -281,6 +279,7 @@ class OpsDefaultEditor:
if self.form:
self.form.opDefaultOp.currentIndexChanged.connect(self.updateUI)
class GlobalEditor(object):
'''Editor for the global properties which affect almost every operation.'''
@@ -293,7 +292,6 @@ class GlobalEditor(object):
self.safeHeightOffs = None
self.rapidHorizontal = None
self.rapidVertical = None
#self.coolantMode = None
def reject(self):
pass
@@ -308,16 +306,15 @@ class GlobalEditor(object):
if val != value:
PathUtil.setProperty(self.obj, name, value)
updateExpression('StartDepthExpression', self.form.setupStartDepthExpr)
updateExpression('FinalDepthExpression', self.form.setupFinalDepthExpr)
updateExpression('StepDownExpression', self.form.setupStepDownExpr)
updateExpression('ClearanceHeightExpression', self.form.setupClearanceHeightExpr)
updateExpression('SafeHeightExpression', self.form.setupSafeHeightExpr)
updateExpression('StartDepthExpression', self.form.setupStartDepthExpr)
updateExpression('FinalDepthExpression', self.form.setupFinalDepthExpr)
updateExpression('StepDownExpression', self.form.setupStepDownExpr)
updateExpression('ClearanceHeightExpression', self.form.setupClearanceHeightExpr)
updateExpression('SafeHeightExpression', self.form.setupSafeHeightExpr)
self.clearanceHeightOffs.updateProperty()
self.safeHeightOffs.updateProperty()
self.rapidVertical.updateProperty()
self.rapidHorizontal.updateProperty()
#self.coolantMode.updateProperty()
self.obj.CoolantMode = self.form.setupCoolantMode.currentText()
def selectInComboBox(self, name, combo):
@@ -330,18 +327,18 @@ class GlobalEditor(object):
def updateUI(self):
PathLog.track()
self.form.setupStartDepthExpr.setText( self.obj.StartDepthExpression)
self.form.setupFinalDepthExpr.setText( self.obj.FinalDepthExpression)
self.form.setupStepDownExpr.setText( self.obj.StepDownExpression)
self.form.setupClearanceHeightExpr.setText( self.obj.ClearanceHeightExpression)
self.form.setupSafeHeightExpr.setText( self.obj.SafeHeightExpression)
self.form.setupStartDepthExpr.setText(self.obj.StartDepthExpression)
self.form.setupFinalDepthExpr.setText(self.obj.FinalDepthExpression)
self.form.setupStepDownExpr.setText(self.obj.StepDownExpression)
self.form.setupClearanceHeightExpr.setText(self.obj.ClearanceHeightExpression)
self.form.setupSafeHeightExpr.setText(self.obj.SafeHeightExpression)
self.clearanceHeightOffs.updateSpinBox()
self.safeHeightOffs.updateSpinBox()
self.rapidVertical.updateSpinBox()
self.rapidHorizontal.updateSpinBox()
self.selectInComboBox(self.obj.CoolantMode, self.form.setupCoolantMode)
def updateModel(self, recomp = True):
def updateModel(self, recomp=True):
PathLog.track()
self.getFields()
self.updateUI()
@@ -359,6 +356,7 @@ class GlobalEditor(object):
self.form.setupCoolantMode.addItems(self.obj.CoolantModes)
self.setFields()
class TaskPanel:
'''TaskPanel for the SetupSheet - if it is being edited directly.'''
@@ -387,8 +385,6 @@ class TaskPanel:
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
#FreeCADGui.Selection.removeObserver(self.s)
#FreeCAD.ActiveDocument.recompute()
def getFields(self):
self.globalEditor.getFields()
@@ -411,11 +407,13 @@ class TaskPanel:
self.globalEditor.setupUi()
self.opsEditor.setupUi()
def Create(name = 'SetupSheet'):
'''Create(name = 'SetupSheet') ... creates a new setup sheet'''
def Create(name='SetupSheet'):
'''Create(name='SetupSheet') ... creates a new setup sheet'''
FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Create Job"))
ssheet = PathSetupSheet.Create(name)
PathIconViewProvider.Attach(ssheet, name)
return ssheet
PathIconViewProvider.RegisterViewProvider('SetupSheet', ViewProvider)
@@ -22,6 +22,7 @@
import FreeCAD
import Path
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathDressup as PathDressup
import PathScripts.PathGeom as PathGeom
import PathScripts.PathLog as PathLog
+1
View File
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathSlot as PathSlot
import PathScripts.PathGui as PathGui
import PathScripts.PathOpGui as PathOpGui
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathSurface as PathSurface
import PathScripts.PathGui as PathGui
import PathScripts.PathOpGui as PathOpGui
@@ -23,6 +23,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui
import PathScripts.PathThreadMilling as PathThreadMilling
import PathScripts.PathGui as PathGui
+165 -185
View File
@@ -24,6 +24,7 @@ import FreeCAD
import PathScripts.PathGeom as PathGeom
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferences as PathPreferences
import PathScripts.PathPropertyBag as PathPropertyBag
import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype
import PathScripts.PathUtil as PathUtil
import PySide
@@ -42,74 +43,73 @@ __author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Class to deal with and represent a tool bit."
# PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
# PathLog.trackModule()
PropertyGroupShape = 'Shape'
_DebugFindTool = False
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
#PathLog.trackModule()
def translate(context, text, disambig=None):
return PySide.QtCore.QCoreApplication.translate(context, text, disambig)
def _findToolFile(name, containerFile, typ):
PathLog.track(name)
if os.path.exists(name): # absolute reference
return name
ParameterTypeConstraint = {
'Angle': 'App::PropertyAngle',
'Distance': 'App::PropertyLength',
'DistanceX': 'App::PropertyLength',
'DistanceY': 'App::PropertyLength',
'Radius': 'App::PropertyLength'}
if containerFile:
rootPath = os.path.dirname(os.path.dirname(containerFile))
paths = [os.path.join(rootPath, typ)]
else:
paths = []
paths.extend(PathPreferences.searchPathsTool(typ))
def _findFile(path, name):
PathLog.track(path, name)
fullPath = os.path.join(path, name)
if os.path.exists(fullPath):
return (True, fullPath)
for root, ds, fs in os.walk(path):
for d in ds:
found, fullPath = _findFile(d, name)
if found:
return (True, fullPath)
return (False, None)
def _findTool(path, typ, dbg=False):
if os.path.exists(path): # absolute reference
if dbg:
PathLog.debug("Found {} at {}".format(typ, path))
return path
def searchFor(pname, fname):
# PathLog.debug("pname: {} fname: {}".format(pname, fname))
if dbg:
PathLog.debug("Looking for {}".format(pname))
if fname:
for p in PathPreferences.searchPathsTool(typ):
PathLog.track(p)
f = os.path.join(p, fname)
if dbg:
PathLog.debug(" Checking {}".format(f))
if os.path.exists(f):
if dbg:
PathLog.debug(" Found {} at {}".format(typ, f))
return f
if pname and os.path.sep != pname:
PathLog.track(pname)
ppname, pfname = os.path.split(pname)
ffname = os.path.join(pfname, fname) if fname else pfname
return searchFor(ppname, ffname)
return None
return searchFor(path, '')
for p in paths:
found, path = _findFile(p, name)
if found:
return path
return None
def findShape(path):
'''
findShape(path) ... search for path, full and partially
in all known shape directories.
'''
return _findTool(path, 'Shape')
def findToolShape(name, path=None):
'''findToolShape(name, path) ... search for name, if relative path look in path'''
PathLog.track(name, path)
return _findToolFile(name, path, 'Shape')
def findBit(path):
PathLog.track(path)
if path.endswith('.fctb'):
return _findTool(path, 'Bit')
return _findTool("{}.fctb".format(path), 'Bit')
def findToolBit(name, path=None):
'''findToolBit(name, path) ... search for name, if relative path look in path'''
PathLog.track(name, path)
if name.endswith('.fctb'):
return _findToolFile(name, path, 'Bit')
return _findToolFile("{}.fctb".format(name), path, 'Bit')
def findLibrary(path, dbg=False):
if path.endswith('.fctl'):
return _findTool(path, 'Library', dbg)
return _findTool("{}.fctl".format(path), 'Library', dbg)
def findToolLibrary(name, path=None):
'''findToolLibrary(name, path) ... search for name, if relative path look in path'''
PathLog.track(name, path)
if name.endswith('.fctl'):
return _findToolFile(name, path, 'Library')
return _findToolFile("{}.fctl".format(name), path, 'Library')
def _findRelativePath(path, typ):
PathLog.track(path, typ)
relative = path
for p in PathPreferences.searchPathsTool(typ):
if path.startswith(p):
@@ -132,48 +132,19 @@ def findRelativePathTool(path):
def findRelativePathLibrary(path):
return _findRelativePath(path, 'Library')
def updateConstraint(sketch, name, value):
for i, constraint in enumerate(sketch.Constraints):
if constraint.Name.split(';')[0] == name:
constr = None
if constraint.Type in ['DistanceX', 'DistanceY', 'Distance', 'Radius', 'Angle']:
constr = Sketcher.Constraint(constraint.Type, constraint.First, constraint.FirstPos, constraint.Second, constraint.SecondPos, value)
else:
print(constraint.Name, constraint.Type)
if constr is not None:
if not PathGeom.isRoughly(constraint.Value, value.Value):
PathLog.track(name, constraint.Type,
'update', i, "(%.2f -> %.2f)"
% (constraint.Value, value.Value))
sketch.delConstraint(i)
sketch.recompute()
n = sketch.addConstraint(constr)
sketch.renameConstraint(n, constraint.Name)
else:
PathLog.track(name, constraint.Type, 'unchanged')
break
PropertyGroupBit = 'Bit'
PropertyGroupAttribute = 'Attribute'
class ToolBit(object):
def __init__(self, obj, shapeFile):
PathLog.track(obj.Label, shapeFile)
def __init__(self, obj, shapeFile, path=None):
PathLog.track(obj.Label, shapeFile, path)
self.obj = obj
obj.addProperty('App::PropertyFile', 'BitShape', 'Base',
translate('PathToolBit', 'Shape for bit shape'))
obj.addProperty('App::PropertyLink', 'BitBody', 'Base',
translate('PathToolBit',
'The parametrized body representing the tool bit'))
obj.addProperty('App::PropertyFile', 'File', 'Base',
translate('PathToolBit', 'The file of the tool'))
obj.addProperty('App::PropertyString', 'ShapeName', 'Base',
translate('PathToolBit', 'The name of the shape file'))
obj.addProperty('App::PropertyFile', 'BitShape', 'Base', translate('PathToolBit', 'Shape for bit shape'))
obj.addProperty('App::PropertyLink', 'BitBody', 'Base', translate('PathToolBit', 'The parametrized body representing the tool bit'))
obj.addProperty('App::PropertyFile', 'File', 'Base', translate('PathToolBit', 'The file of the tool'))
obj.addProperty('App::PropertyString', 'ShapeName', 'Base', translate('PathToolBit', 'The name of the shape file'))
obj.addProperty('App::PropertyStringList', 'BitPropertyNames', 'Base', translate('PathToolBit', 'List of all properties inherited from the bit'))
if path:
obj.File = path
if shapeFile is None:
obj.BitShape = 'endmill.fcstd'
self._setupBitShape(obj)
@@ -193,12 +164,6 @@ class ToolBit(object):
break
return None
def propertyNamesBit(self, obj):
return [prop for prop in obj.PropertiesList if obj.getGroupOfProperty(prop) == PropertyGroupBit]
def propertyNamesAttribute(self, obj):
return [prop for prop in obj.PropertiesList if obj.getGroupOfProperty(prop) == PropertyGroupAttribute]
def onDocumentRestored(self, obj):
# when files are shared it is essential to be able to change/set the shape file,
# otherwise the file is hard to use
@@ -206,19 +171,39 @@ class ToolBit(object):
obj.setEditorMode('BitBody', 2)
obj.setEditorMode('File', 1)
obj.setEditorMode('Shape', 2)
if not hasattr(obj, 'BitPropertyNames'):
obj.addProperty('App::PropertyStringList', 'BitPropertyNames', 'Base', translate('PathToolBit', 'List of all properties inherited from the bit'))
propNames = []
for prop in obj.PropertiesList:
if obj.getGroupOfProperty(prop) == 'Bit':
val = obj.getPropertyByName(prop)
typ = obj.getTypeIdOfProperty(prop)
dsc = obj.getDocumentationOfProperty(prop)
for prop in self.propertyNamesBit(obj):
obj.setEditorMode(prop, 1)
# I currently don't see why these need to be read-only
# for prop in self.propertyNamesAttribute(obj):
# obj.setEditorMode(prop, 1)
obj.removeProperty(prop)
obj.addProperty(typ, prop, PropertyGroupShape, dsc)
PathUtil.setProperty(obj, prop, val)
propNames.append(prop)
elif obj.getGroupOfProperty(prop) == 'Attribute':
propNames.append(prop)
obj.BitPropertyNames = propNames
obj.setEditorMode('BitPropertyNames', 2)
for prop in obj.BitPropertyNames:
if obj.getGroupOfProperty(prop) == PropertyGroupShape:
# properties in the Shape group can only be modified while the actual
# shape is loaded, so we have to disable direct property editing
obj.setEditorMode(prop, 1)
else:
# all other custom properties can and should be edited directly in the
# property editor widget, not much value in re-implementing that
obj.setEditorMode(prop, 0)
def onChanged(self, obj, prop):
PathLog.track(obj.Label, prop)
if prop == 'BitShape' and 'Restore' not in obj.State:
self._setupBitShape(obj)
# elif obj.getGroupOfProperty(prop) == PropertyGroupBit:
# self._updateBitShape(obj, [prop])
def onDelete(self, obj, arg2=None):
PathLog.track(obj.Label)
@@ -227,12 +212,19 @@ class ToolBit(object):
def _updateBitShape(self, obj, properties=None):
if obj.BitBody is not None:
if not properties:
properties = self.propertyNamesBit(obj)
for prop in properties:
for sketch in [o for o in obj.BitBody.Group if o.TypeId == 'Sketcher::SketchObject']:
PathLog.track(obj.Label, sketch.Label, prop)
updateConstraint(sketch, prop, obj.getPropertyByName(prop))
for attributes in [o for o in obj.BitBody.Group if hasattr(o, 'Proxy') and hasattr(o.Proxy, 'getCustomProperties')]:
for prop in attributes.Proxy.getCustomProperties():
# the property might not exist in our local object (new attribute in shape)
# for such attributes we just keep the default
if hasattr(obj, prop):
setattr(attributes, prop, obj.getPropertyByName(prop))
else:
# if the template shape has a new attribute defined we should add that
# to the local object
self._setupProperty(obj, prop, attributes)
propNames = obj.BitPropertyNames
propNames.append(prop)
obj.BitPropertyNames = propNames
self._copyBitShape(obj)
def _copyBitShape(self, obj):
@@ -243,6 +235,7 @@ class ToolBit(object):
obj.Shape = Part.Shape()
def _loadBitBody(self, obj, path=None):
PathLog.track(obj.Label, path)
p = path if path else obj.BitShape
docOpened = False
doc = None
@@ -251,12 +244,15 @@ class ToolBit(object):
doc = FreeCAD.getDocument(d)
break
if doc is None:
p = findShape(p)
p = findToolShape(p, path if path else obj.File)
if not path and p != obj.BitShape:
obj.BitShape = p
PathLog.debug("ToolBit {} using shape file: {}".format(obj.Label, p))
doc = FreeCAD.openDocument(p, True)
obj.ShapeName = doc.Name
docOpened = True
else:
PathLog.debug("ToolBit {} already open: {}".format(obj.Label, doc))
return (doc, docOpened)
def _removeBitBody(self, obj):
@@ -269,7 +265,7 @@ class ToolBit(object):
PathLog.track(obj.Label)
self._removeBitBody(obj)
self._copyBitShape(obj)
for prop in self.propertyNamesBit(obj):
for prop in obj.BitPropertyNames:
obj.removeProperty(prop)
def loadBitBody(self, obj, force=False):
@@ -287,6 +283,20 @@ class ToolBit(object):
def unloadBitBody(self, obj):
self._removeBitBody(obj)
def _setupProperty(self, obj, prop, orig):
# extract property parameters and values so it can be copied
val = orig.getPropertyByName(prop)
typ = orig.getTypeIdOfProperty(prop)
grp = orig.getGroupOfProperty(prop)
dsc = orig.getDocumentationOfProperty(prop)
obj.addProperty(typ, prop, grp, dsc)
if 'App::PropertyEnumeration' == typ:
setattr(obj, prop, orig.getEnumerationsOfProperty(prop))
obj.setEditorMode(prop, 1)
PathUtil.setProperty(obj, prop, val)
def _setupBitShape(self, obj, path=None):
PathLog.track(obj.Label)
@@ -296,6 +306,8 @@ class ToolBit(object):
obj.Label = doc.RootObjects[0].Label
self._deleteBitSetup(obj)
bitBody = obj.Document.copyObject(doc.RootObjects[0], True)
docName = doc.Name
if docOpened:
FreeCAD.setActiveDocument(activeDoc.Name)
FreeCAD.closeDocument(doc.Name)
@@ -303,29 +315,44 @@ class ToolBit(object):
if bitBody.ViewObject:
bitBody.ViewObject.Visibility = False
for sketch in [o for o in bitBody.Group if o.TypeId == 'Sketcher::SketchObject']:
for constraint in [c for c in sketch.Constraints if c.Name != '']:
typ = ParameterTypeConstraint.get(constraint.Type)
PathLog.track(constraint, typ)
if typ is not None:
parts = [p.strip() for p in constraint.Name.split(';')]
prop = parts[0]
desc = ''
if len(parts) > 1:
desc = parts[1]
obj.addProperty(typ, prop, PropertyGroupBit, desc)
obj.setEditorMode(prop, 1)
value = constraint.Value
if constraint.Type == 'Angle':
value = value * 180 / math.pi
PathUtil.setProperty(obj, prop, value)
PathLog.debug("bitBody.{} ({}): {}".format(bitBody.Label, bitBody.Name, type(bitBody)))
propNames = []
for attributes in [o for o in bitBody.Group if PathPropertyBag.IsPropertyBag(o)]:
PathLog.debug("Process properties from {}".format(attributes.Label))
for prop in attributes.Proxy.getCustomProperties():
self._setupProperty(obj, prop, attributes)
propNames.append(prop)
if not propNames:
PathLog.error(translate('PathToolBit', 'Did not find a PropertyBag in {} - not a ToolBit shape?').format(docName))
# has to happen last because it could trigger op.execute evaluations
obj.BitPropertyNames = propNames
obj.BitBody = bitBody
self._copyBitShape(obj)
def toolShapeProperties(self, obj):
'''toolShapeProperties(obj) ... return all properties defining it's shape'''
return sorted([prop for prop in obj.BitPropertyNames if obj.getGroupOfProperty(prop) == PropertyGroupShape])
def toolAdditionalProperties(self, obj):
'''toolShapeProperties(obj) ... return all properties unrelated to it's shape'''
return sorted([prop for prop in obj.BitPropertyNames if obj.getGroupOfProperty(prop) != PropertyGroupShape])
def toolGroupsAndProperties(self, obj, includeShape=True):
'''toolGroupsAndProperties(obj) ... returns a dictionary of group names with a list of property names.'''
category = {}
for prop in obj.BitPropertyNames:
group = obj.getGroupOfProperty(prop)
if includeShape or group != PropertyGroupShape:
properties = category.get(group, [])
properties.append(prop)
category[group] = properties
return category
def getBitThumbnail(self, obj):
if obj.BitShape:
path = findShape(obj.BitShape)
path = findToolShape(obj.BitShape)
if path:
with open(path, 'rb') as fd:
try:
@@ -347,8 +374,7 @@ class ToolBit(object):
obj.File = path
return True
except (OSError, IOError) as e:
PathLog.error("Could not save tool {} to {} ({})".format(
obj.Label, path, e))
PathLog.error("Could not save tool {} to {} ({})".format(obj.Label, path, e))
raise
def templateAttrs(self, obj):
@@ -360,16 +386,10 @@ class ToolBit(object):
else:
attrs['shape'] = findRelativePathShape(obj.BitShape)
params = {}
for name in self.propertyNamesBit(obj):
for name in obj.BitPropertyNames:
params[name] = PathUtil.getPropertyValueString(obj, name)
attrs['parameter'] = params
params = {}
for name in self.propertyNamesAttribute(obj):
if name == "UserAttributes":
for key, value in obj.UserAttributes.items():
params[key] = value
else:
params[name] = PathUtil.getPropertyValueString(obj, name)
attrs['attribute'] = params
return attrs
@@ -380,73 +400,33 @@ def Declaration(path):
return json.load(fp)
class AttributePrototype(PathSetupSheetOpPrototype.OpPrototype):
def __init__(self):
PathSetupSheetOpPrototype.OpPrototype.__init__(self, 'ToolBitAttribute')
self.addProperty('App::PropertyEnumeration', 'Material',
PropertyGroupAttribute,
translate('PathToolBit', 'Tool bit material'))
self.Material = ['Carbide', 'CastAlloy', 'Ceramics', 'Diamond',
'HighCarbonToolSteel', 'HighSpeedSteel', 'Sialon']
self.addProperty('App::PropertyDistance', 'LengthOffset',
PropertyGroupAttribute, translate('PathToolBit',
'Length offset in Z direction'))
self.addProperty('App::PropertyInteger', 'Flutes',
PropertyGroupAttribute, translate('PathToolBit',
'The number of flutes'))
self.addProperty('App::PropertyDistance', 'ChipLoad',
PropertyGroupAttribute, translate('PathToolBit',
'Chipload as per manufacturer'))
self.addProperty('App::PropertyMap', 'UserAttributes',
PropertyGroupAttribute, translate('PathToolBit',
'User Defined Values'))
self.addProperty('App::PropertyBool', 'SpindlePower',
PropertyGroupAttribute, translate('PathToolBit',
'Whether Spindle Power should be allowed'))
class ToolBitFactory(object):
def CreateFromAttrs(self, attrs, name='ToolBit'):
PathLog.debug(attrs)
obj = Factory.Create(name, attrs['shape'])
def CreateFromAttrs(self, attrs, name='ToolBit', path=None):
PathLog.track(attrs, path)
obj = Factory.Create(name, attrs['shape'], path)
obj.Label = attrs['name']
params = attrs['parameter']
for prop in params:
PathUtil.setProperty(obj, prop, params[prop])
obj.Proxy._updateBitShape(obj)
obj.Proxy.unloadBitBody(obj)
params = attrs['attribute']
proto = AttributePrototype()
uservals = {}
for pname in params:
try:
prop = proto.getProperty(pname)
prop.setupProperty(obj, pname, PropertyGroupAttribute, prop.valueFromString(params[pname]))
except Exception:
prop = proto.getProperty("UserAttributes")
uservals.update({pname: params[pname]})
if len(uservals.items()) > 0:
prop.setupProperty(obj, "UserAttributes",
PropertyGroupAttribute, uservals)
return obj
def CreateFrom(self, path, name='ToolBit'):
PathLog.track(name, path)
try:
data = Declaration(path)
bit = Factory.CreateFromAttrs(data, name)
bit.File = path
bit = Factory.CreateFromAttrs(data, name, path)
return bit
except (OSError, IOError) as e:
PathLog.error("%s not a valid tool file (%s)" % (path, e))
raise
def Create(self, name='ToolBit', shapeFile=None):
def Create(self, name='ToolBit', shapeFile=None, path=None):
PathLog.track(name, shapeFile, path)
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', name)
obj.Proxy = ToolBit(obj, shapeFile)
obj.Proxy = ToolBit(obj, shapeFile, path)
return obj
+108 -113
View File
@@ -20,12 +20,14 @@
# * *
# ***************************************************************************
import FreeCAD
import FreeCADGui
import PathScripts.PathGui as PathGui
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferences as PathPreferences
import PathScripts.PathSetupSheetGui as PathSetupSheetGui
import PathScripts.PathPropertyEditor as PathPropertyEditor
import PathScripts.PathToolBit as PathToolBit
import PathScripts.PathUtil as PathUtil
import os
import re
@@ -39,6 +41,31 @@ PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class _Delegate(QtGui.QStyledItemDelegate):
'''Handles the creation of an appropriate editing widget for a given property.'''
ObjectRole = QtCore.Qt.UserRole + 1
PropertyRole = QtCore.Qt.UserRole + 2
EditorRole = QtCore.Qt.UserRole + 3
def createEditor(self, parent, option, index):
editor = index.data(self.EditorRole)
if editor is None:
obj = index.data(self.ObjectRole)
prp = index.data(self.PropertyRole)
editor = PathPropertyEditor.Editor(obj, prp)
index.model().setData(index, editor, self.EditorRole)
return editor.widget(parent)
def setEditorData(self, widget, index):
# called to update the widget with the current data
index.data(self.EditorRole).setEditorData(widget)
def setModelData(self, widget, model, index):
# called to update the model with the data from the widget
editor = index.data(self.EditorRole)
editor.setModelData(widget)
index.model().setData(index, PathUtil.getPropertyValueString(editor.obj, editor.prop), QtCore.Qt.DisplayRole)
class ToolBitEditor(object):
'''UI and controller for editing a ToolBit.
@@ -84,32 +111,35 @@ class ToolBitEditor(object):
layout = self.form.bitParams.layout()
ui = FreeCADGui.UiLoader()
nr = 0
# for all properties either assign them to existing labels and editors
# or create additional ones for them if not enough have already been
# created.
for name in tool.PropertiesList:
if tool.getGroupOfProperty(name) == PathToolBit.PropertyGroupBit:
if nr < len(self.widgets):
PathLog.debug("re-use row: {} [{}]".format(nr, name))
label, qsb, editor = self.widgets[nr]
label.setText(labelText(name))
editor.attachTo(tool, name)
label.show()
qsb.show()
else:
qsb = ui.createWidget('Gui::QuantitySpinBox')
editor = PathGui.QuantitySpinBox(qsb, tool, name)
label = QtGui.QLabel(labelText(name))
self.widgets.append((label, qsb, editor))
PathLog.debug("create row: {} [{}]".format(nr, name))
if nr >= layout.rowCount():
layout.addRow(label, qsb)
nr = nr + 1
usedRows = 0
for nr, name in enumerate(tool.Proxy.toolShapeProperties(tool)):
if nr < len(self.widgets):
PathLog.debug("re-use row: {} [{}]".format(nr, name))
label, qsb, editor = self.widgets[nr]
label.setText(labelText(name))
editor.attachTo(tool, name)
label.show()
qsb.show()
else:
qsb = ui.createWidget('Gui::QuantitySpinBox')
editor = PathGui.QuantitySpinBox(qsb, tool, name)
label = QtGui.QLabel(labelText(name))
self.widgets.append((label, qsb, editor))
PathLog.debug("create row: {} [{}] {}".format(nr, name, type(qsb)))
if hasattr(qsb, 'editingFinished'):
qsb.editingFinished.connect(self.updateTool)
if nr >= layout.rowCount():
layout.addRow(label, qsb)
usedRows = usedRows + 1
# hide all rows which aren't being used
for i in range(nr, len(self.widgets)):
PathLog.track(usedRows, len(self.widgets))
for i in range(usedRows, len(self.widgets)):
label, qsb, editor = self.widgets[i]
label.hide()
qsb.hide()
@@ -124,98 +154,48 @@ class ToolBitEditor(object):
def setupAttributes(self, tool):
PathLog.track()
self.proto = PathToolBit.AttributePrototype()
self.props = sorted(self.proto.properties)
self.delegate = PathSetupSheetGui.Delegate(self.form)
self.model = QtGui.QStandardItemModel(len(self.props)-1, 3, self.form)
self.model.setHorizontalHeaderLabels(['Set', 'Property', 'Value'])
for i, name in enumerate(self.props):
PathLog.debug("propname: %s " % name)
setup = True
if not hasattr(self, 'delegate'):
self.delegate = _Delegate(self.form.attrTree)
self.model = QtGui.QStandardItemModel(self.form.attrTree)
self.model.setHorizontalHeaderLabels(['Property', 'Value'])
else:
self.model.removeRows(0, self.model.rowCount())
setup = False
prop = self.proto.getProperty(name)
isset = hasattr(tool, name)
attributes = tool.Proxy.toolGroupsAndProperties(tool, False)
for name in attributes:
group = QtGui.QStandardItem()
group.setData(name, QtCore.Qt.EditRole)
group.setEditable(False)
for prop in attributes[name]:
label = QtGui.QStandardItem()
label.setData(prop, QtCore.Qt.EditRole)
label.setEditable(False)
if isset:
prop.setValue(getattr(tool, name))
value = QtGui.QStandardItem()
value.setData(PathUtil.getPropertyValueString(tool, prop), QtCore.Qt.DisplayRole)
value.setData(tool, _Delegate.ObjectRole)
value.setData(prop, _Delegate.PropertyRole)
if name == "UserAttributes":
continue
group.appendRow([label, value])
self.model.appendRow(group)
else:
self.model.setData(self.model.index(i, 0), isset,
QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 1), name,
QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 2), prop,
PathSetupSheetGui.Delegate.PropertyRole)
self.model.setData(self.model.index(i, 2),
prop.displayString(),
QtCore.Qt.DisplayRole)
self.model.item(i, 0).setCheckable(True)
self.model.item(i, 0).setText('')
self.model.item(i, 1).setEditable(False)
self.model.item(i, 1).setToolTip(prop.info)
self.model.item(i, 2).setToolTip(prop.info)
if isset:
self.model.item(i, 0).setCheckState(QtCore.Qt.Checked)
else:
self.model.item(i, 0).setCheckState(QtCore.Qt.Unchecked)
self.model.item(i, 1).setEnabled(False)
self.model.item(i, 2).setEnabled(False)
if hasattr(tool, "UserAttributes"):
for key, value in tool.UserAttributes.items():
PathLog.debug(key, value)
c1 = QtGui.QStandardItem()
c1.setCheckable(False)
c1.setEditable(False)
c1.setCheckState(QtCore.Qt.CheckState.Checked)
c1.setText('')
c2 = QtGui.QStandardItem(key)
c2.setEditable(False)
c3 = QtGui.QStandardItem(value)
c3.setEditable(False)
self.model.appendRow([c1, c2, c3])
self.form.attrTable.setModel(self.model)
self.form.attrTable.setItemDelegateForColumn(2, self.delegate)
self.form.attrTable.resizeColumnsToContents()
self.form.attrTable.verticalHeader().hide()
self.model.dataChanged.connect(self.updateData)
def updateData(self, topLeft, bottomRight):
PathLog.track()
if 0 == topLeft.column():
isset = self.model.item(topLeft.row(),
0).checkState() == QtCore.Qt.Checked
self.model.item(topLeft.row(), 1).setEnabled(isset)
self.model.item(topLeft.row(), 2).setEnabled(isset)
if setup:
self.form.attrTree.setModel(self.model)
self.form.attrTree.setItemDelegateForColumn(1, self.delegate)
self.form.attrTree.expandAll()
self.form.attrTree.resizeColumnToContents(0)
self.form.attrTree.resizeColumnToContents(1)
#self.form.attrTree.collapseAll()
def accept(self):
PathLog.track()
self.refresh()
self.tool.Proxy.unloadBitBody(self.tool)
# get the attributes
for i, name in enumerate(self.props):
PathLog.debug('in accept: {}'.format(name))
prop = self.proto.getProperty(name)
if self.model.item(i, 0) is not None:
enabled = self.model.item(i, 0).checkState() == QtCore.Qt.Checked
if enabled and not prop.getValue() is None:
prop.setupProperty(self.tool, name,
PathToolBit.PropertyGroupAttribute,
prop.getValue())
elif hasattr(self.tool, name):
self.tool.removeProperty(name)
def reject(self):
PathLog.track()
self.tool.Proxy.unloadBitBody(self.tool)
@@ -228,27 +208,45 @@ class ToolBitEditor(object):
for lbl, qsb, editor in self.widgets:
editor.updateSpinBox()
def _updateBitShape(self, shapePath):
# Only need to go through this exercise if the shape actually changed.
if self.tool.BitShape != shapePath:
# Before setting a new bitshape we need to make sure that none of
# editors fires an event and tries to access its old property, which
# might not exist anymore.
for lbl, qsb, editor in self.widgets:
editor.attachTo(self.tool, 'File')
self.tool.BitShape = shapePath
self.setupTool(self.tool)
self.form.toolName.setText(self.tool.Label)
if self.tool.BitBody and self.tool.BitBody.ViewObject:
if not self.tool.BitBody.ViewObject.Visibility:
self.tool.BitBody.ViewObject.Visibility = True
self.setupAttributes(self.tool)
return True
return False
def updateShape(self):
PathLog.track()
shapePath = str(self.form.shapePath.text())
# Only need to go through this exercise if the shape actually changed.
if self.tool.BitShape != shapePath:
self.tool.BitShape = shapePath
self.setupTool(self.tool)
self.form.toolName.setText(self.tool.Label)
if self._updateBitShape(shapePath):
for lbl, qsb, editor in self.widgets:
editor.updateSpinBox()
def updateTool(self):
PathLog.track()
self.tool.Label = str(self.form.toolName.text())
self.tool.BitShape = str(self.form.shapePath.text())
label = str(self.form.toolName.text())
shape = str(self.form.shapePath.text())
if self.tool.Label != label:
self.tool.Label = label
self._updateBitShape(shape)
for lbl, qsb, editor in self.widgets:
editor.updateProperty()
# self.tool.Proxy._updateBitShape(self.tool)
self.tool.Proxy._updateBitShape(self.tool)
def refresh(self):
PathLog.track()
@@ -262,10 +260,7 @@ class ToolBitEditor(object):
path = self.tool.BitShape
if not path:
path = PathPreferences.lastPathToolShape()
foo = QtGui.QFileDialog.getOpenFileName(self.form,
"Path - Tool Shape",
path,
"*.fcstd")
foo = QtGui.QFileDialog.getOpenFileName(self.form, "Path - Tool Shape", path, "*.fcstd")
if foo and foo[0]:
PathPreferences.setLastPathToolShape(os.path.dirname(foo[0]))
self.form.shapePath.setText(foo[0])
+6 -5
View File
@@ -170,13 +170,13 @@ class TaskPanel:
class ToolBitGuiFactory(PathToolBit.ToolBitFactory):
def Create(self, name='ToolBit', shapeFile=None):
def Create(self, name='ToolBit', shapeFile=None, path=None):
'''Create(name = 'ToolBit') ... creates a new tool bit.
It is assumed the tool will be edited immediately so the internal bit body is still attached.'''
FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit',
'Create ToolBit'))
tool = PathToolBit.ToolBitFactory.Create(self, name, shapeFile)
PathLog.track(name, shapeFile, path)
FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit', 'Create ToolBit'))
tool = PathToolBit.ToolBitFactory.Create(self, name, shapeFile, path)
PathIconViewProvider.Attach(tool.ViewObject, name)
FreeCAD.ActiveDocument.commitTransaction()
return tool
@@ -247,7 +247,8 @@ def GetToolShapeFile(parent=None):
location, '*.fcstd')
if fname and fname[0]:
if fname != location:
PathPreferences.setLastPathToolShape(location)
newloc = os.path.dirname(fname[0])
PathPreferences.setLastPathToolShape(newloc)
return fname[0]
else:
return None
@@ -24,23 +24,25 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferences as PathPreferences
import PathScripts.PathToolBit as PathToolBit
import PathScripts.PathToolBitGui as PathToolBitGui
import PathScripts.PathToolBitEdit as PathToolBitEdit
import PathScripts.PathToolBitGui as PathToolBitGui
import PathScripts.PathToolControllerGui as PathToolControllerGui
import PathScripts.PathUtilsGui as PathUtilsGui
from PySide import QtCore, QtGui
import PySide
import glob
import json
import os
import glob
import uuid as UUID
from functools import partial
import shutil
import uuid as UUID
# PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
from functools import partial
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
_UuidRole = PySide.QtCore.Qt.UserRole + 1
@@ -50,6 +52,75 @@ _PathRole = PySide.QtCore.Qt.UserRole + 2
def translate(context, text, disambig=None):
return PySide.QtCore.QCoreApplication.translate(context, text, disambig)
def checkWorkingDir():
# users shouldn't use the example toolbits and libraries.
# working directory should be writable
PathLog.track()
workingdir = os.path.dirname(PathPreferences.lastPathToolLibrary())
defaultdir = os.path.dirname(PathPreferences.pathDefaultToolsPath())
PathLog.debug('workingdir: {} defaultdir: {}'.format(workingdir, defaultdir))
dirOK = lambda : workingdir != defaultdir and (os.access(workingdir, os.W_OK))
if dirOK():
return True
qm = PySide.QtGui.QMessageBox
ret = qm.question(None,'', "Toolbit working directory not set up. Do that now?", qm.Yes | qm.No)
if ret == qm.No:
return False
msg = translate("Path", "Choose a writable location for your toolbits", None)
while not dirOK():
workingdir = PySide.QtGui.QFileDialog.getExistingDirectory(None, msg,
PathPreferences.filePath())
if workingdir[-8:] == os.path.sep + 'Library':
workingdir = workingdir[:-8] # trim off trailing /Library if user chose it
PathPreferences.setLastPathToolLibrary("{}{}Library".format(workingdir, os.path.sep))
PathPreferences.setLastPathToolBit("{}{}Bit".format(workingdir, os.path.sep))
PathLog.debug('setting workingdir to: {}'.format(workingdir))
subdirlist = ['Bit', 'Library', 'Shape']
mode = 0o777
for dir in subdirlist.copy():
subdir = "{}{}{}".format(workingdir, os.path.sep, dir)
if os.path.exists(subdir):
subdirlist.remove(dir)
if len(subdirlist) >= 1:
needed = ', '.join([str(d) for d in subdirlist])
qm = PySide.QtGui.QMessageBox
ret = qm.question(None,'', "Toolbit Working directory {} needs these sudirectories:\n {} \n Create them?".format(workingdir, needed), qm.Yes | qm.No)
if ret == qm.No:
return False
else:
for dir in subdirlist:
subdir = "{}{}{}".format(workingdir, os.path.sep, dir)
os.mkdir(subdir, mode)
if dir != 'Shape':
qm = PySide.QtGui.QMessageBox
ret = qm.question(None,'', "Copy example files to new {} directory?".format(dir), qm.Yes | qm.No)
if ret == qm.Yes:
src="{}{}{}".format(defaultdir, os.path.sep, dir)
src_files = os.listdir(src)
for file_name in src_files:
full_file_name = os.path.join(src, file_name)
if os.path.isfile(full_file_name):
shutil.copy(full_file_name, subdir)
# if no library is set, choose the first one in the Library directory
if PathPreferences.lastFileToolLibrary() is None:
libFiles = [f for f in glob.glob(PathPreferences.lastPathToolLibrary() + os.path.sep + '*.fctl')]
PathPreferences.setLastFileToolLibrary(libFiles[0])
return True
class _TableView(PySide.QtGui.QTableView):
'''Subclass of QTableView to support rearrange and copying of ToolBits'''
@@ -141,7 +212,7 @@ class ModelFactory(object):
for toolBit in library['tools']:
try:
nr = toolBit['nr']
bit = PathToolBit.findBit(toolBit['path'])
bit = PathToolBit.findToolBit(toolBit['path'], path)
if bit:
PathLog.track(bit)
tool = PathToolBit.Declaration(bit)
@@ -203,15 +274,15 @@ class ModelFactory(object):
path = PathPreferences.lastPathToolLibrary()
if os.path.isdir(path): # opening all tables in a directory
libFiles = [f for f in glob.glob(path + '/*.fctl')]
libFiles = [f for f in glob.glob(path + os.path.sep + '*.fctl')]
libFiles.sort()
for libFile in libFiles:
loc, fnlong = os.path.split(libFile)
fn, ext = os.path.splitext(fnlong)
libItem = QtGui.QStandardItem(fn)
libItem = PySide.QtGui.QStandardItem(fn)
libItem.setToolTip(loc)
libItem.setData(libFile, _PathRole)
libItem.setIcon(QtGui.QPixmap(':/icons/Path_ToolTable.svg'))
libItem.setIcon(PySide.QtGui.QPixmap(':/icons/Path_ToolTable.svg'))
model.appendRow(libItem)
PathLog.debug('model rows: {}'.format(model.rowCount()))
@@ -241,6 +312,7 @@ class ToolBitSelector(object):
'''Controller for displaying a library and creating ToolControllers'''
def __init__(self):
checkWorkingDir()
self.form = FreeCADGui.PySideUic.loadUi(':/panels/ToolBitSelector.ui')
self.factory = ModelFactory()
self.toolModel = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()))
@@ -250,20 +322,20 @@ class ToolBitSelector(object):
def columnNames(self):
return ['#', 'Tool']
def curLib(self):
def currentLibrary(self, shortNameOnly):
libfile = PathPreferences.lastFileToolLibrary()
if libfile is None or libfile == "":
return ""
else:
libfile = os.path.split(PathPreferences.lastFileToolLibrary())[1]
libfile = os.path.splitext(libfile)[0]
elif shortNameOnly:
return os.path.splitext(os.path.basename(libfile))[0]
return libfile
def loadData(self):
PathLog.track()
self.toolModel.clear()
self.toolModel.setHorizontalHeaderLabels(self.columnNames())
self.form.lblLibrary.setText(self.curLib())
self.form.lblLibrary.setText(self.currentLibrary(True))
self.form.lblLibrary.setToolTip(self.currentLibrary(False))
self.factory.libraryOpen(self.toolModel)
self.toolModel.takeColumn(3)
self.toolModel.takeColumn(2)
@@ -271,7 +343,6 @@ class ToolBitSelector(object):
def setupUI(self):
PathLog.track()
self.loadData()
self.form.tools.setModel(self.toolModel)
self.form.tools.selectionModel().selectionChanged.connect(self.enableButtons)
self.form.tools.doubleClicked.connect(partial(self.selectedOrAllToolControllers))
@@ -340,7 +411,7 @@ class ToolBitSelector(object):
def open(self, path=None):
''' load library stored in path and bring up ui'''
docs = FreeCADGui.getMainWindow().findChildren(QtGui.QDockWidget)
docs = FreeCADGui.getMainWindow().findChildren(PySide.QtGui.QDockWidget)
for doc in docs:
if doc.objectName() == "ToolSelector":
if doc.isVisible():
@@ -351,7 +422,7 @@ class ToolBitSelector(object):
return
mw = FreeCADGui.getMainWindow()
mw.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.form,
mw.addDockWidget(PySide.QtCore.Qt.RightDockWidgetArea, self.form,
PySide.QtCore.Qt.Orientation.Vertical)
@@ -361,9 +432,7 @@ class ToolBitLibrary(object):
def __init__(self):
PathLog.track()
if not self.checkWorkingDir():
return
checkWorkingDir()
self.factory = ModelFactory()
self.temptool = None
self.toolModel = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()))
@@ -375,55 +444,6 @@ class ToolBitLibrary(object):
self.setupUI()
self.title = self.form.windowTitle()
def checkWorkingDir(self):
# users shouldn't use the example toolbits and libraries.
# working directory should be writable
PathLog.track()
workingdir = os.path.dirname(PathPreferences.lastPathToolLibrary())
defaultdir = os.path.dirname(PathPreferences.pathDefaultToolsPath())
dirOK = lambda : workingdir != defaultdir and (os.access(workingdir, os.W_OK))
if dirOK():
return True
qm = PySide.QtGui.QMessageBox
ret = qm.question(None,'', "Toolbit working directory not set up. Do that now?", qm.Yes | qm.No)
if ret == qm.No:
return False
msg = translate("Path", "Choose a writable location for your toolbits", None)
while not dirOK():
workingdir = PySide.QtGui.QFileDialog.getExistingDirectory(None, msg,
PathPreferences.filePath())
PathPreferences.setLastPathToolLibrary("{}/Library".format(workingdir))
subdirlist = ['Bit', 'Library', 'Shape']
mode = 0o777
for dir in subdirlist:
subdir = "{}/{}".format(workingdir, dir)
if not os.path.exists(subdir):
qm = PySide.QtGui.QMessageBox
ret = qm.question(None,'', "Toolbit Working directory {} should contain a '{}' subdirectory. Create it?".format(workingdir, dir), qm.Yes | qm.No)
if ret == qm.Yes:
os.mkdir(subdir, mode)
qm = PySide.QtGui.QMessageBox
ret = qm.question(None,'', "Copy example files to new {} directory?".format(dir), qm.Yes | qm.No)
if ret == qm.Yes:
src="{}/{}".format(defaultdir, dir)
src_files = os.listdir(src)
for file_name in src_files:
full_file_name = os.path.join(src, file_name)
if os.path.isfile(full_file_name):
shutil.copy(full_file_name, subdir)
return True
def toolBitNew(self):
PathLog.track()
@@ -439,7 +459,7 @@ class ToolBitLibrary(object):
# Parse out the name of the file and write the structure
loc, fil = os.path.split(filename)
fname = os.path.splitext(fil)[0]
fullpath = "{}/{}.fctb".format(loc, fname)
fullpath = "{}{}{}.fctb".format(loc, os.path.sep, fname)
PathLog.debug(fullpath)
self.temptool = PathToolBit.ToolBitFactory().Create(name=fname)
@@ -464,7 +484,7 @@ class ToolBitLibrary(object):
loc, fil = os.path.split(f)
fname = os.path.splitext(fil)[0]
fullpath = "{}/{}.fctb".format(loc, fname)
fullpath = "{}{}{}.fctb".format(loc, os.path.sep, fname)
self.factory.newTool(self.toolModel, fullpath)
@@ -557,8 +577,8 @@ class ToolBitLibrary(object):
self.temptool = PathToolBit.ToolBitFactory().CreateFrom(tbpath, 'temptool')
self.editor = PathToolBitEdit.ToolBitEditor(self.temptool, self.form.toolTableGroup, loadBitBody=False)
QBtn = QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel
buttonBox = QtGui.QDialogButtonBox(QBtn)
QBtn = PySide.QtGui.QDialogButtonBox.Ok | PySide.QtGui.QDialogButtonBox.Cancel
buttonBox = PySide.QtGui.QDialogButtonBox(QBtn)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
@@ -604,8 +624,9 @@ class ToolBitLibrary(object):
else:
tools.append({'nr': toolNr, 'path': PathToolBit.findRelativePathTool(toolPath)})
with open(self.path, 'w') as fp:
json.dump(library, fp, sort_keys=True, indent=2)
if self.path is not None:
with open(self.path, 'w') as fp:
json.dump(library, fp, sort_keys=True, indent=2)
def libraryOk(self):
self.librarySave()
@@ -652,7 +673,7 @@ class ToolBitLibrary(object):
if curIndex:
sm = self.form.TableList.selectionModel()
sm.select(curIndex, QtCore.QItemSelectionModel.Select)
sm.select(curIndex, PySide.QtCore.QItemSelectionModel.Select)
self.toolTableView.setUpdatesEnabled(True)
self.form.TableList.setUpdatesEnabled(True)
@@ -250,7 +250,8 @@ def Create(name='TC: Default Tool', tool=None, toolNumber=1, assignViewProvider=
if tool.ViewObject:
tool.ViewObject.Visibility = False
obj.Tool = tool
if tool:
obj.Tool = tool
obj.ToolNumber = toolNumber
return obj
@@ -260,7 +261,7 @@ def FromTemplate(template, assignViewProvider=True):
PathLog.track()
name = template.get(ToolControllerTemplate.Name, ToolControllerTemplate.Label)
obj = Create(name, assignViewProvider=True)
obj = Create(name, tool=False, assignViewProvider=True)
obj.Proxy.setFromTemplate(obj, template)
return obj
@@ -22,6 +22,7 @@
import FreeCAD
import FreeCADGui
import PathGui as PGui # ensure Path/Gui/Resources are loaded
import PathScripts
import PathScripts.PathGui as PathGui
import PathScripts.PathLog as PathLog

Some files were not shown because too many files have changed in this diff Show More