Merge branch 'master' into feature/misc-improvements
@@ -379,7 +379,7 @@ protected:
|
||||
|
||||
enum eWinGestureTuneState{
|
||||
ewgtsDisabled, //suppress tuning/re-tuning after errors
|
||||
ewgtsNeedTuning, //gestures are to be retuned upon next event
|
||||
ewgtsNeedTuning, //gestures are to be re-tuned upon next event
|
||||
ewgtsTuned
|
||||
};
|
||||
eWinGestureTuneState winGestureTuneState;//See ViewerEventFilter::eventFilter function for explanation
|
||||
@@ -458,4 +458,3 @@ private:
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_VIEW3DINVENTORVIEWER_H
|
||||
|
||||
|
||||
@@ -182,6 +182,7 @@ void View3DInventorPy::init_type()
|
||||
add_varargs_method("getActiveObject", &View3DInventorPy::getActiveObject, "getActiveObject(name)\nreturns the active object for the given type");
|
||||
add_varargs_method("getViewProvidersOfType", &View3DInventorPy::getViewProvidersOfType, "getViewProvidersOfType(name)\nreturns a list of view providers for the given type");
|
||||
add_varargs_method("redraw", &View3DInventorPy::redraw, "redraw(): renders the scene on screen (useful for animations)");
|
||||
add_varargs_method("setName",&View3DInventorPy::setName,"setName(str): sets a name to this viewer\nThe name sets the widget's windowTitle and appears on the viewer tab");
|
||||
|
||||
}
|
||||
|
||||
@@ -2451,3 +2452,24 @@ Py::Object View3DInventorPy::redraw(const Py::Tuple& args)
|
||||
_view->getViewer()->redraw();
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object View3DInventorPy::setName(const Py::Tuple& args)
|
||||
{
|
||||
char* buffer;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "s", &buffer))
|
||||
throw Py::Exception();
|
||||
|
||||
try {
|
||||
_view->setWindowTitle(QString::fromUtf8(buffer));
|
||||
return Py::None();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
throw Py::RuntimeError(e.what());
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw Py::RuntimeError(e.what());
|
||||
}
|
||||
catch(...) {
|
||||
throw Py::RuntimeError("Unknown C++ exception");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ public:
|
||||
Py::Object getActiveObject(const Py::Tuple&);
|
||||
Py::Object getViewProvidersOfType(const Py::Tuple&);
|
||||
Py::Object redraw(const Py::Tuple&);
|
||||
Py::Object setName(const Py::Tuple&);
|
||||
|
||||
private:
|
||||
static void eventCallback(void * ud, SoEventCallback * n);
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
<qresource>
|
||||
<file>icons/3D_Printing_Tools_workbench_icon.svg</file>
|
||||
<file>icons/A2plus_workbench_icon.svg</file>
|
||||
<file>icons/AirPlaneDesign_workbench-icon.svg</file>
|
||||
<file>icons/AirPlaneDesign_workbench_icon.svg</file>
|
||||
<file>icons/ArchTextures_workbench_icon.svg</file>
|
||||
<file>icons/BIMBots_workbench_icon.svg</file>
|
||||
<file>icons/BIM_workbench_icon.svg</file>
|
||||
<file>icons/BOLTSFC_workbench_icon.svg</file>
|
||||
<file>icons/CADExchanger_workbench_icon.svg</file>
|
||||
<file>icons/cadquery_module_workbench_icon.svg</file>
|
||||
<file>icons/CfdOF_workbench_icon.svg</file>
|
||||
<file>icons/CurvedShapes_workbench_icon.svg</file>
|
||||
@@ -24,19 +25,21 @@
|
||||
<file>icons/InventorLoader_workbench_icon.svg</file>
|
||||
<file>icons/kicadStepUpMod_workbench_icon.svg</file>
|
||||
<file>icons/lattice2_workbench_icon.svg</file>
|
||||
<file>icons/LCInterlocking_workbench_icon.svg</file>
|
||||
<file>icons/LCInterlocking_workbench_icon.svg</file>
|
||||
<file>icons/Lithophane_workbench_icon.svg</file>
|
||||
<file>icons/Manipulator_workbench_icon.svg</file>
|
||||
<file>icons/MOOC_workbench_icon.svg</file>
|
||||
<file>icons/Part-o-magic_workbench_icon.svg</file>
|
||||
<file>icons/Plot_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>
|
||||
<file>icons/Render_workbench_icon.svg</file>
|
||||
<file>icons/sheetmetal_workbench_icon.svg</file>
|
||||
<file>icons/slic3r-tools_workbench_icon.svg</file>
|
||||
<file>icons/Ship_workbench_icon.svg</file>
|
||||
<file>icons/timber_workbench_icon.svg</file>
|
||||
<file>icons/ThreadProfile_workbench_icon.svg</file>
|
||||
<file>icons/yaml-workspace_workbench_icon.svg</file>
|
||||
<file>translations/AddonManager_af.qm</file>
|
||||
<file>translations/AddonManager_ar.qm</file>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,169 @@
|
||||
<?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: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="svg2985" version="1.1" inkscape:version="0.48.5 r10040" sodipodi:docname="Arch_Rebar.svg">
|
||||
<defs id="defs2987">
|
||||
<linearGradient id="linearGradient4025">
|
||||
<stop id="stop4027" offset="0" style="stop-color:#c4a000;stop-opacity:1"/>
|
||||
<stop id="stop4029" offset="1" style="stop-color:#fce94f;stop-opacity:1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient4017">
|
||||
<stop id="stop4019" offset="0" style="stop-color:#c4a000;stop-opacity:1"/>
|
||||
<stop id="stop4021" offset="1" style="stop-color:#fce94f;stop-opacity:1"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" id="linearGradient4007">
|
||||
<stop style="stop-color:#c4a000;stop-opacity:1" offset="0" id="stop4009"/>
|
||||
<stop style="stop-color:#fce94f;stop-opacity:1" offset="1" id="stop4011"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" id="linearGradient3999">
|
||||
<stop style="stop-color:#c4a000;stop-opacity:1" offset="0" id="stop4001"/>
|
||||
<stop style="stop-color:#fce94f;stop-opacity:1" offset="1" id="stop4003"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" id="linearGradient3991">
|
||||
<stop style="stop-color:#c4a000;stop-opacity:1" offset="0" id="stop3993"/>
|
||||
<stop style="stop-color:#fce94f;stop-opacity:1" offset="1" id="stop3995"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient3217">
|
||||
<stop id="stop3219" offset="0" style="stop-color:#c4a000;stop-opacity:1"/>
|
||||
<stop id="stop3221" offset="1" style="stop-color:#fce94f;stop-opacity:1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient3883">
|
||||
<stop style="stop-color:#ffb400;stop-opacity:1;" offset="0" id="stop3885"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient3793">
|
||||
<stop style="stop-color:#000f8a;stop-opacity:1;" offset="0" id="stop3795"/>
|
||||
<stop style="stop-color:#0066ff;stop-opacity:1;" offset="1" id="stop3797"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3793-2" id="linearGradient3799-8" x1="12.037806" y1="54.001419" x2="52.882648" y2="9.274148" gradientUnits="userSpaceOnUse"/>
|
||||
<linearGradient id="linearGradient3793-2">
|
||||
<stop style="stop-color:#000f8a;stop-opacity:1;" offset="0" id="stop3795-6"/>
|
||||
<stop style="stop-color:#0066ff;stop-opacity:1;" offset="1" id="stop3797-0"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883" id="linearGradient3889" x1="3" y1="31.671875" x2="59.25" y2="31.671875" gradientUnits="userSpaceOnUse" gradientTransform="translate(84.181818,-14.181818)"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-6" id="linearGradient3889-4" x1="3" y1="31.671875" x2="59.25" y2="31.671875" gradientUnits="userSpaceOnUse" gradientTransform="translate(-1.2727273,-0.18181818)"/>
|
||||
<linearGradient id="linearGradient3883-6">
|
||||
<stop style="stop-color:#ffb400;stop-opacity:1;" offset="0" id="stop3885-4"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient3883-63">
|
||||
<stop style="stop-color:#ffb400;stop-opacity:1;" offset="0" id="stop3885-6"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-51"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="31.671875" x2="59.25" y1="31.671875" x1="3" gradientTransform="translate(-3,-1.9375)" gradientUnits="userSpaceOnUse" id="linearGradient3099" xlink:href="#linearGradient3883-63" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1" id="linearGradient3889-9" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.78523034,-0.61920378,0.61920378,0.78523034,40.449388,-50.080588)"/>
|
||||
<linearGradient id="linearGradient3883-1">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="31.671875" x2="59.25" y1="31.671875" x1="3" gradientTransform="translate(-3,-1.9375)" gradientUnits="userSpaceOnUse" id="linearGradient3950" xlink:href="#linearGradient3883-1" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-0" id="linearGradient3889-9-4" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875" gradientUnits="userSpaceOnUse" gradientTransform="translate(62.772175,-14.278383)"/>
|
||||
<linearGradient id="linearGradient3883-1-0">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-6"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-5"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="37.671875" x2="-45.659092" y1="52.217331" x1="-45.909092" gradientTransform="translate(72.070588,5.7891214)" gradientUnits="userSpaceOnUse" id="linearGradient3983" xlink:href="#linearGradient3883-1-0" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-5" id="linearGradient3889-9-5" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875" gradientUnits="userSpaceOnUse" gradientTransform="translate(62.772175,-14.278383)"/>
|
||||
<linearGradient id="linearGradient3883-1-5">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-3"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-2"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="37.671875" x2="-45.659092" y1="52.217331" x1="-45.909092" gradientTransform="matrix(0.78523034,-0.61920378,0.61920378,0.78523034,80.903931,-30.262405)" gradientUnits="userSpaceOnUse" id="linearGradient3983-2" xlink:href="#linearGradient3883-1-5" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-0" id="linearGradient4060" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.78523034,-0.61920378,0.61920378,0.78523034,60.176658,-40.080587)" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-6" id="linearGradient3889-9-2" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.78523034,-0.61920378,0.61920378,0.78523034,40.449388,-50.080588)"/>
|
||||
<linearGradient id="linearGradient3883-1-6">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-4"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-7"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="37.671875" x2="-45.659092" y1="52.217331" x1="-45.909092" gradientTransform="matrix(0.78523034,-0.61920378,0.61920378,0.78523034,40.449388,-50.080588)" gradientUnits="userSpaceOnUse" id="linearGradient4058" xlink:href="#linearGradient3883-1-6" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3217" id="linearGradient4081" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.76307355,-0.59933979,0.60173176,0.76004024,38.095031,-48.22656)" x1="-47.090748" y1="48.182411" x2="-47.046482" y2="41.506298"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4017" id="linearGradient4083" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.75961823,-0.62787354,0.59900702,0.7962247,56.938596,-42.236467)" x1="-46.284084" y1="48.523933" x2="-45.804276" y2="40.519474"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4025" id="linearGradient4085" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.73381378,-0.61846048,0.57865858,0.78428772,76.44662,-31.907951)" x1="-63.788338" y1="48.997299" x2="-62.86702" y2="40.553333"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-1" id="linearGradient4081-3" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.7532208,-0.59396224,0.59396224,0.7532208,94.343245,-4.8301808)" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875"/>
|
||||
<linearGradient id="linearGradient3883-1-1">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-8"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-0"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-0-2" id="linearGradient4083-9" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.7532208,-0.59396224,0.59396224,0.7532208,113.26634,4.7621752)" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875"/>
|
||||
<linearGradient id="linearGradient3883-1-0-2">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-6-2"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-5-1"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-5-6" id="linearGradient4085-4" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.7532208,-0.59396224,0.59396224,0.7532208,77.313909,-25.823666)" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875"/>
|
||||
<linearGradient id="linearGradient3883-1-5-6">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-3-2"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-2-8"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="37.671875" x2="-45.659092" y1="52.217331" x1="-45.909092" gradientTransform="matrix(0.7532208,-0.59396224,0.59396224,0.7532208,133.14868,14.180124)" gradientUnits="userSpaceOnUse" id="linearGradient4115" xlink:href="#linearGradient3883-1-5-6" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-12" id="linearGradient4081-9" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.77104208,-0.59933979,0.60801545,0.76004024,38.440632,-48.22656)" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875"/>
|
||||
<linearGradient id="linearGradient3883-1-12">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-7"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-09"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="37.671875" x2="-45.659092" y1="52.217331" x1="-45.909092" gradientTransform="matrix(0.65709111,-0.49036892,0.5181579,0.62185111,35.498499,-36.91264)" gradientUnits="userSpaceOnUse" id="linearGradient3147" xlink:href="#linearGradient3883-1-12" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-06" id="linearGradient4081-6" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.77104208,-0.59933979,0.60801545,0.76004024,38.440632,-48.22656)" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875"/>
|
||||
<linearGradient id="linearGradient3883-1-06">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-2"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-6"/>
|
||||
</linearGradient>
|
||||
<linearGradient y2="37.671875" x2="-45.659092" y1="52.217331" x1="-45.909092" gradientTransform="matrix(0.77104208,-0.59933979,0.60801545,0.76004024,18.064696,-48.22656)" gradientUnits="userSpaceOnUse" id="linearGradient3147-1" xlink:href="#linearGradient3883-1-06" inkscape:collect="always"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3883-1-9" id="linearGradient4081-7" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.76307355,-0.59933979,0.60173176,0.76004024,38.095031,-48.22656)" x1="-45.909092" y1="52.217331" x2="-45.659092" y2="37.671875"/>
|
||||
<linearGradient id="linearGradient3883-1-9">
|
||||
<stop style="stop-color:#a27200;stop-opacity:1;" offset="0" id="stop3885-63-20"/>
|
||||
<stop style="stop-color:#ffe900;stop-opacity:1;" offset="1" id="stop3887-3-23"/>
|
||||
</linearGradient>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3991" id="linearGradient3997" x1="13.3365" y1="27.160084" x2="16.853151" y2="18.167061" gradientUnits="userSpaceOnUse"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3999" id="linearGradient4005" x1="13.809239" y1="27.325958" x2="16.208029" y2="18.637737" gradientUnits="userSpaceOnUse"/>
|
||||
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4007" id="linearGradient4013" x1="13.305584" y1="27.051975" x2="15.567404" y2="18.380537" gradientUnits="userSpaceOnUse"/>
|
||||
</defs>
|
||||
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="10.193662" inkscape:cx="51.352241" inkscape:cy="21.397156" inkscape:current-layer="layer1" showgrid="true" inkscape:document-units="px" inkscape:grid-bbox="true" inkscape:window-width="1600" inkscape:window-height="837" inkscape:window-x="0" inkscape:window-y="27" inkscape:window-maximized="1" inkscape:snap-bbox="true" inkscape:snap-nodes="true" inkscape:snap-global="false">
|
||||
<inkscape:grid type="xygrid" id="grid3045" empspacing="2" visible="true" enabled="true" snapvisiblegridlinesonly="true"/>
|
||||
</sodipodi:namedview>
|
||||
<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/>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[Yorik van Havre]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>Arch_Rebar</dc:title>
|
||||
<dc:date>2013-10-07</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>FreeCAD/src/Mod/Arch/Resources/icons/Arch_Rebar.svg</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>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer">
|
||||
<path style="color:#000000;fill:url(#linearGradient4085);fill-opacity:1;fill-rule:evenodd;stroke:#302b00;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" d="M 60.999997,29 43,44 l 8,12 9.999997,-8.522207 z" id="rect3927-7" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/>
|
||||
<path style="color:#000000;fill:url(#linearGradient4083);fill-opacity:1;fill-rule:evenodd;stroke:#302b00;stroke-width:1.99999988000000006;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" d="M 61,2.9999998 23,34 31,46 61,21.790714 z" id="rect3927-9" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/>
|
||||
<path style="color:#000000;fill:url(#linearGradient4081);fill-opacity:1;fill-rule:evenodd;stroke:#302b00;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" d="M 39.353422,14.334536 C 44.482951,10.010831 36.930113,0.05679041 30.855842,4.0421362 20.14891,12.460802 5,24 5,24 l 8,12 c 0,0 19.508425,-16.226689 26.353422,-21.665464 z" id="rect3927" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/>
|
||||
<path style="fill:none;stroke:#fce94f;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" d="m 25.249695,34.588267 c 0.485572,0 33.781873,-27.4694484 33.781873,-27.4694484 l -10e-7,13.6653574 -28.579325,23.099308 z" id="path4015" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/>
|
||||
<path style="color:#000000;fill:none;stroke:#fce94f;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" d="M 37.913291,12.965316 C 41.46823,10.375694 35.930633,2.1213928 31.173418,6.2601274 20.466486,14.678793 7,25 7,25 l 6.232988,8.24525 c 0,0 17.835306,-14.841159 24.680303,-20.279934 z" id="rect3927-75" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/>
|
||||
<path sodipodi:type="arc" style="color:#000000;fill:url(#linearGradient3997);fill-opacity:1;fill-rule:evenodd;stroke:#302b00;stroke-width:2.52394294999999991;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path3082" sodipodi:cx="15.545455" sodipodi:cy="23" sodipodi:rx="8.090909" sodipodi:ry="8.090909" d="M 23.636364,23 A 8.090909,8.090909 0 1 1 7.454546,23 8.090909,8.090909 0 1 1 23.636364,23 z" transform="matrix(0.56525353,-0.41335011,0.47999651,0.75985114,-10.827043,18.949139)"/>
|
||||
<path sodipodi:type="arc" style="color:#000000;fill:none;stroke:#fce94f;stroke-width:3.69287395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path3082-7" sodipodi:cx="15.545455" sodipodi:cy="23" sodipodi:rx="8.090909" sodipodi:ry="8.090909" d="M 23.636364,23 A 8.090909,8.090909 0 1 1 7.454546,23 8.090909,8.090909 0 1 1 23.636364,23 z" transform="matrix(0.30023259,-0.36676447,0.39686301,0.49214378,-4.813901,24.421156)"/>
|
||||
<path sodipodi:type="arc" style="color:#000000;fill:url(#linearGradient4005);fill-opacity:1;fill-rule:evenodd;stroke:#302b00;stroke-width:2.52394294999999991;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path3082-5" sodipodi:cx="15.545455" sodipodi:cy="23" sodipodi:rx="8.090909" sodipodi:ry="8.090909" d="M 23.636364,23 A 8.090909,8.090909 0 1 1 7.454546,23 8.090909,8.090909 0 1 1 23.636364,23 z" transform="matrix(0.56525353,-0.41335011,0.47999651,0.75985114,7.2182949,28.876511)"/>
|
||||
<path sodipodi:type="arc" style="color:#000000;fill:none;stroke:#fce94f;stroke-width:3.69287395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path3082-7-3" sodipodi:cx="15.545455" sodipodi:cy="23" sodipodi:rx="8.090909" sodipodi:ry="8.090909" d="M 23.636364,23 A 8.090909,8.090909 0 1 1 7.454546,23 8.090909,8.090909 0 1 1 23.636364,23 z" transform="matrix(0.30023259,-0.36676447,0.39686301,0.49214378,13.231436,34.348528)"/>
|
||||
<path style="fill:none;stroke:#fce94f;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" d="M 44.395069,45.478932 59.031568,33.270288 58.9622,46.519442 50.360655,54.01111 z" id="path4023" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/>
|
||||
<path sodipodi:type="arc" style="color:#000000;fill:url(#linearGradient4013);fill-opacity:1;fill-rule:evenodd;stroke:#302b00;stroke-width:2.52394294999999991;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path3082-56" sodipodi:cx="15.545455" sodipodi:cy="23" sodipodi:rx="8.090909" sodipodi:ry="8.090909" d="M 23.636364,23 A 8.090909,8.090909 0 1 1 7.454546,23 8.090909,8.090909 0 1 1 23.636364,23 z" transform="matrix(0.56525353,-0.41335011,0.47999651,0.75985114,27.165219,38.943882)"/>
|
||||
<path sodipodi:type="arc" style="color:#000000;fill:none;stroke:#fce94f;stroke-width:3.69287395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path3082-7-2" sodipodi:cx="15.545455" sodipodi:cy="23" sodipodi:rx="8.090909" sodipodi:ry="8.090909" d="M 23.636364,23 A 8.090909,8.090909 0 1 1 7.454546,23 8.090909,8.090909 0 1 1 23.636364,23 z" transform="matrix(0.30023259,-0.36676447,0.39686301,0.49214378,33.178361,44.415899)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,83 @@
|
||||
<?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: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="64"
|
||||
height="64"
|
||||
viewBox="0 0 16.933333 16.933334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="ThreadProfileSVGLogo.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="-166.53392"
|
||||
inkscape:cy="68.194187"
|
||||
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"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-280.06665)">
|
||||
<image
|
||||
y="280.21786"
|
||||
x="0.60476506"
|
||||
id="image4537"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAA3NCSVQICAjb4U/gAAAEmUlEQVRo ge1az2vjRhiVvT0VSi67IOjKgeaQxRPQMZHZQntZJ9eS0R4CNbS3diFkDblapodCim32D0hLiy8Z 5bQ9+VSoidWEUFiQHJI2FNkpCBwIXkKPcQ+yFc9oRh4pcWyB32kszzfznma+HzN2otfrCXFGctIE 7oqZgEnjg2hmmqa5jbm5uTsy6Ha7xJihEPsVmAmYNBLR8kClUnEbqVTqjgxarZbbSCYpb/Pm5sZr ZzIZt7G8vOw9jP0KzARMGhHzwDiwuLgY3GFhYcH/MPYrMBMwaWA+cHh46DYajYb3kBqex4HV1dUI VrFfgZmASQPzAS/QXl1dBZudnJyMi1FIxH4FsGr08vLSbRwfHwebra2t0b9Q8vt5JRQDrxp99Kjz 548//fzOoXSCqIcg1TzKCrx4v5uTxQiGwXgl/kVnHwjMB7zie+QhIcJMY8J0+UCEhY0ioPbRV+PY Qm/+zdx1C/FDzm2XBUEQhFTij60t1I42ig/lsjuqsPXifWpJ4xkWE3B+fu42zs7OvIeJRIKwGdN1 ajKZHD4B81qNg8pDIvYCpuhIubm5efvBKnL6FSZAUfpJdGVlxXvo3/HJZNK7FxIE4b48OBpiv4Wm SoAVwSaKACLYSRGGoAMwP7CB+cDBwYHbODo68h4+2Jk4GqaaHA9mAiYNzAe828nr62u3Yder1d/r rZZt24NO8/PzQurZs0/kbPSKtG0g1DAuLtptL4mI4u6uASFcL0BO96UIGIJdr1ar1bpN+ca2Bdu2 67WaIIryxsaIG1k/c4QMSu5zHMvRLUvXNAEAWCjwqqCdiU/ffrHxNY07BwLOxG2jVC7RuHOAfSb2 rcDpD8+f75xGmiUIbXSPx4ZhYAIeP/5NfUKyBwAW9goQ9NfUsvT9YlHTQ2VNo+RjL0mK+lpVJMm9 lXCcdx/+cxxyWEEgopCuqjpOHiLTNJHHXnD1ILO8nZND0C8ZOHklX6lU8op0m8RFUS4gs2cyNgob QwJI+kAzTcQKCaKcK/NpIOlLaqWSVxj1B2BvdgZuBeg6QX9vVCSQcxwSjAZB/7U6oniCKIwETwDB ny+QydlRbAj+ijrKwJ1c484FAwEkf8j3EkSFtRlckPwzfNeOYJ07m9FLCQDSnPaS9JSzZ6jOIM1L gC4gneZewqcS/3kgRN804GRAF9BscsfjizZ/egrRt2lxMhgIwBVbVpNzonb7Iuhr/J2P6DxMoMlL YCCA2HSETzPhGMHFDbHrCZ9mwtrnTsneFiLiji8p0+DUfhlV3xBxx5eUabCKLzXuLXzrA2Tw1dUl lfkeut3u32+/36n5LpP/u2zh+PjTLHZsMEqvvvv1aKhDd4AB+6UlfvpEOU0zBlArFNaHqiHLsprF z7/VO53AgUU592X/Et6p7fikinI2m5VlURz86a/TgZ91Xhb1Ec4LINrD65seDmbxw4CczTLPZXKu PEDY3xOgxs7FEA0TJsMoRKbJm8efpOE3nEWpnNveZivFASAy0TpfX8G3An3gJTR1Fs10ezLkAojM hxiWIaA/n4k0CAE2JwBQo1ALg3sdNuK/FqcHsb8X+h/s/sbLpcJe1gAAAABJRU5ErkJggg== "
|
||||
style="image-rendering:optimizeQuality"
|
||||
preserveAspectRatio="none"
|
||||
height="16.933332"
|
||||
width="16.933332" />
|
||||
<image
|
||||
y="280.21786"
|
||||
x="0.60476506"
|
||||
id="image835"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAA3NCSVQICAjb4U/gAAAA+ElEQVRo
|
||||
ge2ZQQ6EIBAExfgtXu/D9MDG7ALiqISCTdfFCyRdIUAb3LZt08jMdIC3SIBGAjQSoJEAjQRoJEAj
|
||||
ARoJ0EiARgI0EqCRAI0EaCRAIwGaJXyOVwLnHBfmCcOvgARonN7IYCRAIwEaCdBIgGZ5PLNKb33f
|
||||
A66rBFKw7WKnApbc67reCJXgvbcMK8vEAtncL4M+IHIrOPwIROnb5075NslquPRnsofcEYdG6vA5
|
||||
RntOPxVTzcZx3TL8RfYvAmFzGA/m9oRg2VMoXoEOHcqRSvdAANnZaejTxmC5ibNUEbMs+L0qkRkx
|
||||
aJm7mFbJqkWd7pzh74EdgqxnCcySe50AAAAASUVORK5CYII=
|
||||
"
|
||||
style="image-rendering:optimizeQuality"
|
||||
preserveAspectRatio="none"
|
||||
height="16.933332"
|
||||
width="16.933332" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -91,10 +91,11 @@ class UpdateWorker(QtCore.QThread):
|
||||
if url:
|
||||
addondir = moddir + os.sep + name
|
||||
#print ("found:",name," at ",url)
|
||||
if not os.path.exists(addondir):
|
||||
state = 0
|
||||
else:
|
||||
if os.path.exists(addondir) and os.listdir(addondir):
|
||||
# make sure the folder exists and it contains files!
|
||||
state = 1
|
||||
else:
|
||||
state = 0
|
||||
repos.append([name,url,state])
|
||||
# querying custom addons
|
||||
customaddons = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons").GetString("CustomRepositories","").split("\n")
|
||||
|
||||
@@ -43,6 +43,7 @@ if FreeCAD.GuiUp:
|
||||
from ArchWall import *
|
||||
from ArchFloor import *
|
||||
from ArchFence import *
|
||||
from ArchProject import *
|
||||
from ArchSite import *
|
||||
from ArchBuilding import *
|
||||
from ArchStructure import *
|
||||
|
||||
@@ -313,7 +313,7 @@ class CommandBuildingPart:
|
||||
|
||||
|
||||
|
||||
class BuildingPart:
|
||||
class BuildingPart(ArchIFC.IfcProduct):
|
||||
|
||||
|
||||
"The BuildingPart object"
|
||||
@@ -326,7 +326,7 @@ class BuildingPart:
|
||||
self.setProperties(obj)
|
||||
|
||||
def setProperties(self,obj):
|
||||
ArchIFC.setProperties(obj)
|
||||
ArchIFC.IfcProduct.setProperties(self, obj)
|
||||
|
||||
pl = obj.PropertiesList
|
||||
if not "Height" in pl:
|
||||
@@ -366,7 +366,7 @@ class BuildingPart:
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
|
||||
ArchIFC.onChanged(obj, prop)
|
||||
ArchIFC.IfcProduct.onChanged(self, obj, prop)
|
||||
|
||||
if prop == "Height":
|
||||
for child in obj.Group:
|
||||
@@ -483,13 +483,10 @@ class ViewProviderBuildingPart:
|
||||
vobj.ShowLevel = True
|
||||
if not "ShowUnit" in pl:
|
||||
vobj.addProperty("App::PropertyBool","ShowUnit","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If true, show the unit on the level tag"))
|
||||
if not "SetWorkingPlane" in pl:
|
||||
vobj.addProperty("App::PropertyBool","SetWorkingPlane","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If true, when activated, the working plane will automatically adapt to this level"))
|
||||
vobj.SetWorkingPlane = True
|
||||
if not "OriginOffset" in pl:
|
||||
vobj.addProperty("App::PropertyBool","OriginOffset","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If true, when activated, Display offset will affect the origin mark too"))
|
||||
vobj.addProperty("App::PropertyBool","OriginOffset","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If true, display offset will affect the origin mark too"))
|
||||
if not "ShowLabel" in pl:
|
||||
vobj.addProperty("App::PropertyBool","ShowLabel","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If true, when activated, the object's label is displayed"))
|
||||
vobj.addProperty("App::PropertyBool","ShowLabel","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If true, the object's label is displayed"))
|
||||
vobj.ShowLabel = True
|
||||
if not "FontName" in pl:
|
||||
vobj.addProperty("App::PropertyFont","FontName","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The font to be used for texts"))
|
||||
@@ -497,14 +494,31 @@ class ViewProviderBuildingPart:
|
||||
if not "FontSize" in pl:
|
||||
vobj.addProperty("App::PropertyLength","FontSize","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The font size of texts"))
|
||||
vobj.FontSize = Draft.getParam("textheight",2.0)
|
||||
if not "ViewData" in pl:
|
||||
vobj.addProperty("App::PropertyFloatList","ViewData","BuildingPart",QT_TRANSLATE_NOOP("App::Property","Camera position data associated with this object"))
|
||||
if not "RestoreView" in pl:
|
||||
vobj.addProperty("App::PropertyBool","RestoreView","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If set, the view stored in this object will be restored on double-click"))
|
||||
if not "DiffuseColor" in pl:
|
||||
vobj.addProperty("App::PropertyColorList","DiffuseColor","BuildingPart",QT_TRANSLATE_NOOP("App::Property","The individual face colors"))
|
||||
|
||||
# Interaction properties
|
||||
if not "SetWorkingPlane" in pl:
|
||||
vobj.addProperty("App::PropertyBool","SetWorkingPlane","Interaction",QT_TRANSLATE_NOOP("App::Property","If true, when activated, the working plane will automatically adapt to this level"))
|
||||
vobj.SetWorkingPlane = True
|
||||
if not "AutoWorkingPlane" in pl:
|
||||
vobj.addProperty("App::PropertyBool","AutoWorkingPlane","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If set to True, the working plane will be kept on Auto mode"))
|
||||
vobj.addProperty("App::PropertyBool","AutoWorkingPlane","Interaction",QT_TRANSLATE_NOOP("App::Property","If set to True, the working plane will be kept on Auto mode"))
|
||||
if not "ViewData" in pl:
|
||||
vobj.addProperty("App::PropertyFloatList","ViewData","Interaction",QT_TRANSLATE_NOOP("App::Property","Camera position data associated with this object"))
|
||||
vobj.setEditorMode("ViewData",2)
|
||||
if not "RestoreView" in pl:
|
||||
vobj.addProperty("App::PropertyBool","RestoreView","Interaction",QT_TRANSLATE_NOOP("App::Property","If set, the view stored in this object will be restored on double-click"))
|
||||
if not "DoubleClickActivates" in pl:
|
||||
vobj.addProperty("App::PropertyBool","DoubleClickActivates","Interaction",QT_TRANSLATE_NOOP("App::Property","If True, double-clicking this object in the tree turns it active"))
|
||||
|
||||
# inventor saving
|
||||
if not "SaveInventor" in pl:
|
||||
vobj.addProperty("App::PropertyBool","SaveInventor","Interaction",QT_TRANSLATE_NOOP("App::Property","If this is enabled, the inventor representation of this object will be saved in the FreeCAD file, allowing to reference it in other file sin lightweight mode."))
|
||||
if not "SavedInventor" in pl:
|
||||
vobj.addProperty("App::PropertyFileIncluded","SavedInventor","Interaction",QT_TRANSLATE_NOOP("App::Property","A slot to save the inventor representation of this object, if enabled"))
|
||||
vobj.setEditorMode("SavedInventor",2)
|
||||
|
||||
# children properties
|
||||
if not "ChildrenOverride" in pl:
|
||||
vobj.addProperty("App::PropertyBool","ChildrenOverride","Children",QT_TRANSLATE_NOOP("App::Property","If true, show the objects contained in this Building Part will adopt these line, color and transparency settings"))
|
||||
if not "ChildrenLineWidth" in pl:
|
||||
@@ -520,6 +534,8 @@ class ViewProviderBuildingPart:
|
||||
vobj.ChildrenLineColor = (float((c>>24)&0xFF)/255.0,float((c>>16)&0xFF)/255.0,float((c>>8)&0xFF)/255.0,0.0)
|
||||
if not "ChildrenTransparency" in pl:
|
||||
vobj.addProperty("App::PropertyPercent","ChildrenTransparency","Children",QT_TRANSLATE_NOOP("App::Property","The transparency of child objects"))
|
||||
|
||||
# clip properties
|
||||
if not "CutView" in pl:
|
||||
vobj.addProperty("App::PropertyBool","CutView","Clip",QT_TRANSLATE_NOOP("App::Property","Cut the view above this level"))
|
||||
if not "CutMargin" in pl:
|
||||
@@ -527,8 +543,6 @@ class ViewProviderBuildingPart:
|
||||
vobj.CutMargin = 1600
|
||||
if not "AutoCutView" in pl:
|
||||
vobj.addProperty("App::PropertyBool","AutoCutView","Clip",QT_TRANSLATE_NOOP("App::Property","Turn cutting on when activating this level"))
|
||||
if not "SaveInventor" in pl:
|
||||
vobj.addProperty("App::PropertyBool","SaveInventor","BuildingPart",QT_TRANSLATE_NOOP("App::Property","If this is enabled, the inventor representation of this object will be saved in the FreeCAD file, allowing to reference it in other file sin lightweight mode."))
|
||||
|
||||
def onDocumentRestored(self,vobj):
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ def addComponents(objectsList,host):
|
||||
if not isinstance(objectsList,list):
|
||||
objectsList = [objectsList]
|
||||
hostType = Draft.getType(host)
|
||||
if hostType in ["Floor","Building","Site","BuildingPart"]:
|
||||
if hostType in ["Floor","Building","Site","Project","BuildingPart"]:
|
||||
for o in objectsList:
|
||||
host.addObject(o)
|
||||
elif hostType in ["Wall","Structure","Window","Roof","Stairs","StructuralSystem","Panel","Component"]:
|
||||
@@ -744,7 +744,7 @@ def pruneIncluded(objectslist,strict=False):
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
if not (Draft.getType(obj) in ["Window","Clone","Pipe","Rebar"]):
|
||||
for parent in obj.InList:
|
||||
if parent.isDerivedFrom("Part::Feature") and not (Draft.getType(parent) in ["Space","Facebinder","Window","Roof","Clone","Site"]):
|
||||
if parent.isDerivedFrom("Part::Feature") and not (Draft.getType(parent) in ["Space","Facebinder","Window","Roof","Clone","Site","Project"]):
|
||||
if not parent.isDerivedFrom("Part::Part2DObject"):
|
||||
# don't consider 2D objects based on arch elements
|
||||
if hasattr(parent,"Host") and (parent.Host == obj):
|
||||
|
||||
@@ -133,22 +133,20 @@ def removeFromComponent(compobject,subobject):
|
||||
|
||||
|
||||
|
||||
class Component:
|
||||
|
||||
class Component(ArchIFC.IfcProduct):
|
||||
|
||||
"The default Arch Component object"
|
||||
|
||||
def __init__(self,obj):
|
||||
|
||||
def __init__(self, obj):
|
||||
obj.Proxy = self
|
||||
Component.setProperties(self,obj)
|
||||
Component.setProperties(self, obj)
|
||||
self.Type = "Component"
|
||||
|
||||
def setProperties(self,obj):
|
||||
def setProperties(self, obj):
|
||||
|
||||
"Sets the needed properties of this object"
|
||||
|
||||
ArchIFC.setProperties(obj)
|
||||
ArchIFC.IfcProduct.setProperties(self, obj)
|
||||
|
||||
pl = obj.PropertiesList
|
||||
if not "Base" in pl:
|
||||
@@ -195,9 +193,8 @@ class Component:
|
||||
#self.MoveWithHost = False
|
||||
self.Type = "Component"
|
||||
|
||||
def onDocumentRestored(self,obj):
|
||||
|
||||
Component.setProperties(self,obj)
|
||||
def onDocumentRestored(self, obj):
|
||||
Component.setProperties(self, obj)
|
||||
|
||||
def execute(self,obj):
|
||||
|
||||
@@ -210,24 +207,20 @@ class Component:
|
||||
obj.Shape = shape
|
||||
|
||||
def __getstate__(self):
|
||||
|
||||
# for compatibility with 0.17
|
||||
if hasattr(self,"Type"):
|
||||
return self.Type
|
||||
return "Component"
|
||||
|
||||
def __setstate__(self,state):
|
||||
|
||||
return None
|
||||
|
||||
def onBeforeChange(self,obj,prop):
|
||||
|
||||
if prop == "Placement":
|
||||
self.oldPlacement = FreeCAD.Placement(obj.Placement)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
|
||||
ArchIFC.onChanged(obj, prop)
|
||||
def onChanged(self, obj, prop):
|
||||
ArchIFC.IfcProduct.onChanged(self, obj, prop)
|
||||
|
||||
if prop == "Placement":
|
||||
if hasattr(self,"oldPlacement"):
|
||||
@@ -741,12 +734,19 @@ class ViewProviderComponent:
|
||||
|
||||
vobj.Proxy = self
|
||||
self.Object = vobj.Object
|
||||
self.setProperties(vobj)
|
||||
|
||||
def setProperties(self,vobj):
|
||||
|
||||
if not "UseMaterialColor" in vobj.PropertiesList:
|
||||
vobj.addProperty("App::PropertyBool","UseMaterialColor","Component",QT_TRANSLATE_NOOP("App::Property","Use the material color as this object's shape color, if available"))
|
||||
vobj.UseMaterialColor = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("UseMaterialColor",True)
|
||||
|
||||
def updateData(self,obj,prop):
|
||||
|
||||
#print(obj.Name," : updating ",prop)
|
||||
if prop == "Material":
|
||||
if obj.Material:
|
||||
if obj.Material and ( (not hasattr(obj.ViewObject,"UseMaterialColor")) or obj.ViewObject.UseMaterialColor):
|
||||
if hasattr(obj.Material,"Material"):
|
||||
if 'DiffuseColor' in obj.Material.Material:
|
||||
if "(" in obj.Material.Material['DiffuseColor']:
|
||||
|
||||
@@ -231,6 +231,9 @@ class _ViewProviderFence(ArchComponent.ViewProviderComponent):
|
||||
|
||||
def __init__(self, vobj):
|
||||
ArchComponent.ViewProviderComponent.__init__(self, vobj)
|
||||
# setProperties of ArchComponent will be overwritten
|
||||
# thus setProperties from ArchComponent will be explicit called to get the properties
|
||||
ArchComponent.ViewProviderComponent.setProperties(self, vobj)
|
||||
self.setProperties(vobj)
|
||||
|
||||
def setProperties(self, vobj):
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import FreeCAD,Draft,ArchCommands, DraftVecUtils
|
||||
import FreeCAD,Draft,ArchCommands, DraftVecUtils, ArchIFC
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
@@ -121,7 +121,7 @@ Floor creation aborted.") + "\n"
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
class _Floor:
|
||||
class _Floor(ArchIFC.IfcProduct):
|
||||
|
||||
"The Floor object"
|
||||
|
||||
@@ -134,6 +134,7 @@ class _Floor:
|
||||
|
||||
def setProperties(self,obj):
|
||||
|
||||
ArchIFC.IfcProduct.setProperties(self, obj)
|
||||
pl = obj.PropertiesList
|
||||
if not "Height" in pl:
|
||||
obj.addProperty("App::PropertyLength","Height","Floor",QT_TRANSLATE_NOOP("App::Property","The height of this object"))
|
||||
@@ -142,10 +143,6 @@ class _Floor:
|
||||
if not hasattr(obj,"Placement"):
|
||||
# obj can be a Part Feature and already has a placement
|
||||
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
|
||||
if not "IfcType" in pl:
|
||||
obj.addProperty("App::PropertyEnumeration","IfcType","IFC",QT_TRANSLATE_NOOP("App::Property","The type of this object"))
|
||||
import ArchIFC
|
||||
obj.IfcType = ArchIFC.IfcTypes
|
||||
self.Type = "Floor"
|
||||
|
||||
def onDocumentRestored(self,obj):
|
||||
@@ -161,6 +158,7 @@ class _Floor:
|
||||
return None
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
ArchIFC.IfcProduct.onChanged(self, obj, prop)
|
||||
|
||||
if not hasattr(self,"Object"):
|
||||
# on restore, self.Object is not there anymore
|
||||
|
||||
@@ -9,181 +9,185 @@ else:
|
||||
return txt
|
||||
|
||||
import ArchIFCSchema
|
||||
IfcTypes = ['Undefined']+[''.join(map(lambda x: x if x.islower() else " "+x, t[3:]))[1:] for t in ArchIFCSchema.IfcProducts.keys()]
|
||||
|
||||
def setProperties(obj):
|
||||
IfcTypes = [''.join(map(lambda x: x if x.islower() else " "+x, t[3:]))[1:] for t in ArchIFCSchema.IfcProducts.keys()]
|
||||
|
||||
"Checks and sets all the needed IFC-related properties"
|
||||
class IfcRoot:
|
||||
def setProperties(self, obj):
|
||||
if not "IfcData" in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyMap","IfcData","IFC",QT_TRANSLATE_NOOP("App::Property","IFC data"))
|
||||
|
||||
if not "IfcType" in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyEnumeration","IfcType","IFC",QT_TRANSLATE_NOOP("App::Property","The type of this object"))
|
||||
obj.IfcType = IfcTypes
|
||||
if not "IfcType" in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyEnumeration","IfcType","IFC",QT_TRANSLATE_NOOP("App::Property","The type of this object"))
|
||||
obj.IfcType = self.getCanonicalisedIfcTypes()
|
||||
|
||||
if not "IfcData" in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyMap","IfcData","IFC",QT_TRANSLATE_NOOP("App::Property","IFC data"))
|
||||
if not "IfcProperties" in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyMap","IfcProperties","IFC",QT_TRANSLATE_NOOP("App::Property","IFC properties of this object"))
|
||||
|
||||
if not "IfcProperties" in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyMap","IfcProperties","IFC",QT_TRANSLATE_NOOP("App::Property","IFC properties of this object"))
|
||||
self.migrateDeprecatedAttributes(obj)
|
||||
|
||||
migrateDeprecatedAttributes(obj)
|
||||
def onChanged(self, obj, prop):
|
||||
if prop == "IfcType":
|
||||
self.setupIfcAttributes(obj)
|
||||
self.setupIfcComplexAttributes(obj)
|
||||
if obj.getGroupOfProperty(prop) == "IFC Attributes":
|
||||
self.setObjIfcAttributeValue(obj, prop, obj.getPropertyByName(prop))
|
||||
|
||||
def onChanged(obj, prop):
|
||||
def setupIfcAttributes(self, obj):
|
||||
ifcTypeSchema = self.getIfcTypeSchema(obj.IfcType)
|
||||
if ifcTypeSchema is None:
|
||||
return
|
||||
self.purgeUnusedIfcAttributesFromPropertiesList(ifcTypeSchema, obj)
|
||||
self.addIfcAttributes(ifcTypeSchema, obj)
|
||||
|
||||
"Called by Arch object's OnChanged method"
|
||||
def setupIfcComplexAttributes(self, obj):
|
||||
ifcTypeSchema = self.getIfcTypeSchema(obj.IfcType)
|
||||
if ifcTypeSchema is None:
|
||||
return
|
||||
IfcData = obj.IfcData
|
||||
if "complex_attributes" not in IfcData:
|
||||
IfcData["complex_attributes"] = "{}"
|
||||
ifcComplexAttributes = json.loads(IfcData["complex_attributes"])
|
||||
for attribute in ifcTypeSchema["complex_attributes"]:
|
||||
if attribute["name"] not in ifcComplexAttributes.keys():
|
||||
ifcComplexAttributes[attribute["name"]] = {}
|
||||
IfcData["complex_attributes"] = json.dumps(ifcComplexAttributes)
|
||||
obj.IfcData = IfcData
|
||||
|
||||
if prop == "IfcType":
|
||||
setupIfcAttributes(obj)
|
||||
if obj.getGroupOfProperty(prop) == "IFC Attributes":
|
||||
setObjIfcAttributeValue(obj, prop, obj.getPropertyByName(prop))
|
||||
def getIfcTypeSchema(self, IfcType):
|
||||
name = "Ifc" + IfcType.replace(" ", "")
|
||||
if IfcType == "Undefined":
|
||||
name = "IfcBuildingElementProxy"
|
||||
if name in self.getIfcSchema():
|
||||
return self.getIfcSchema()[name]
|
||||
return None
|
||||
|
||||
def getIfcProduct(IfcType):
|
||||
|
||||
"Returns an IFC product name from an obj.IfcType"
|
||||
|
||||
name = "Ifc" + IfcType.replace(" ", "")
|
||||
if IfcType == "Undefined":
|
||||
name = "IfcBuildingElementProxy"
|
||||
if name in ArchIFCSchema.IfcProducts:
|
||||
return ArchIFCSchema.IfcProducts[name]
|
||||
return None
|
||||
def getIfcSchema(self):
|
||||
return {}
|
||||
|
||||
def getIfcProductAttribute(ifcProduct, name):
|
||||
|
||||
"Returns the attributes of a given product"
|
||||
def getCanonicalisedIfcTypes(self):
|
||||
schema = self.getIfcSchema()
|
||||
return [''.join(map(lambda x: x if x.islower() else " "+x, t[3:]))[1:] for t in schema.keys()]
|
||||
|
||||
for attribute in ifcProduct["attributes"]:
|
||||
if attribute["name"].replace(' ', '') == name:
|
||||
return attribute
|
||||
return None
|
||||
def getIfcAttributeSchema(self, ifcTypeSchema, name):
|
||||
for attribute in ifcTypeSchema["attributes"]:
|
||||
if attribute["name"].replace(' ', '') == name:
|
||||
return attribute
|
||||
return None
|
||||
|
||||
def setupIfcAttributes(obj):
|
||||
def addIfcAttributes(self, ifcTypeSchema, obj):
|
||||
for attribute in ifcTypeSchema["attributes"]:
|
||||
if attribute["name"] in obj.PropertiesList \
|
||||
or attribute["name"] == "RefLatitude" \
|
||||
or attribute["name"] == "RefLongitude" \
|
||||
or attribute["name"] == "Name":
|
||||
continue
|
||||
self.addIfcAttribute(obj, attribute)
|
||||
self.addIfcAttributeValueExpressions(obj, attribute)
|
||||
|
||||
"Sets the necessary IFC attribute properties for an object"
|
||||
|
||||
ifcProduct = getIfcProduct(obj.IfcType)
|
||||
if ifcProduct is None:
|
||||
return
|
||||
purgeUnusedIfcAttributesFromPropertiesList(ifcProduct, obj)
|
||||
addIfcProductAttributesToObj(ifcProduct, obj)
|
||||
|
||||
def addIfcProductAttributesToObj(ifcProduct, obj):
|
||||
|
||||
"Adds the necessary attribute properties to an object"
|
||||
|
||||
for attribute in ifcProduct["attributes"]:
|
||||
if attribute["name"] in obj.PropertiesList \
|
||||
or attribute["name"] == "RefLatitude" \
|
||||
or attribute["name"] == "RefLongitude":
|
||||
continue
|
||||
addIfcProductAttribute(obj, attribute)
|
||||
addIfcAttributeValueExpressions(obj, attribute)
|
||||
|
||||
def addIfcProductAttribute(obj, attribute):
|
||||
|
||||
"Adds a given attribute property"
|
||||
|
||||
if not hasattr(obj,"IfcData"):
|
||||
return
|
||||
IfcData = obj.IfcData
|
||||
if "attributes" not in IfcData:
|
||||
IfcData["attributes"] = "{}"
|
||||
IfcAttributes = json.loads(IfcData["attributes"])
|
||||
IfcAttributes[attribute["name"]] = attribute
|
||||
IfcData["attributes"] = json.dumps(IfcAttributes)
|
||||
obj.IfcData = IfcData
|
||||
if attribute["is_enum"]:
|
||||
obj.addProperty("App::PropertyEnumeration", attribute["name"], "IFC Attributes", QT_TRANSLATE_NOOP("App::Property", "Description of IFC attributes are not yet implemented"))
|
||||
setattr(obj, attribute["name"], attribute["enum_values"])
|
||||
else:
|
||||
import ArchIFCSchema
|
||||
propertyType = "App::" + ArchIFCSchema.IfcTypes[attribute["type"]]["property"]
|
||||
obj.addProperty(propertyType, attribute["name"], "IFC Attributes", QT_TRANSLATE_NOOP("App::Property", "Description of IFC attributes are not yet implemented"))
|
||||
|
||||
def addIfcAttributeValueExpressions(obj, attribute):
|
||||
|
||||
"Binds the given attribute properties with expressions"
|
||||
|
||||
if not attribute["name"] in obj.PropertiesList:
|
||||
return
|
||||
if obj.getGroupOfProperty(attribute["name"]) != "IFC Attributes":
|
||||
return
|
||||
if attribute["name"] == "OverallWidth":
|
||||
if "Length" in obj.PropertiesList:
|
||||
obj.setExpression("OverallWidth", "Length.Value")
|
||||
elif "Width" in obj.PropertiesList:
|
||||
obj.setExpression("OverallWidth", "Width.Value")
|
||||
elif obj.Shape and (obj.Shape.BoundBox.XLength > obj.Shape.BoundBox.YLength):
|
||||
obj.setExpression("OverallWidth", "Shape.BoundBox.XLength")
|
||||
elif obj.Shape:
|
||||
obj.setExpression("OverallWidth", "Shape.BoundBox.YLength")
|
||||
elif attribute["name"] == "OverallHeight":
|
||||
if "Height" in obj.PropertiesList:
|
||||
obj.setExpression("OverallHeight", "Height.Value")
|
||||
def addIfcAttribute(self, obj, attribute):
|
||||
if not hasattr(obj, "IfcData"):
|
||||
return
|
||||
IfcData = obj.IfcData
|
||||
if "attributes" not in IfcData:
|
||||
IfcData["attributes"] = "{}"
|
||||
IfcAttributes = json.loads(IfcData["attributes"])
|
||||
IfcAttributes[attribute["name"]] = attribute
|
||||
IfcData["attributes"] = json.dumps(IfcAttributes)
|
||||
obj.IfcData = IfcData
|
||||
if attribute["is_enum"]:
|
||||
obj.addProperty("App::PropertyEnumeration", attribute["name"], "IFC Attributes", QT_TRANSLATE_NOOP("App::Property", "Description of IFC attributes are not yet implemented"))
|
||||
setattr(obj, attribute["name"], attribute["enum_values"])
|
||||
else:
|
||||
obj.setExpression("OverallHeight", "Shape.BoundBox.ZLength")
|
||||
elif attribute["name"] == "ElevationWithFlooring":
|
||||
if "Shape" in obj.PropertiesList:
|
||||
import ArchIFCSchema
|
||||
propertyType = "App::" + ArchIFCSchema.IfcTypes[attribute["type"]]["property"]
|
||||
obj.addProperty(propertyType, attribute["name"], "IFC Attributes", QT_TRANSLATE_NOOP("App::Property", "Description of IFC attributes are not yet implemented"))
|
||||
|
||||
def addIfcAttributeValueExpressions(self, obj, attribute):
|
||||
if obj.getGroupOfProperty(attribute["name"]) != "IFC Attributes" \
|
||||
or attribute["name"] not in obj.PropertiesList:
|
||||
return
|
||||
if attribute["name"] == "OverallWidth":
|
||||
if "Length" in obj.PropertiesList:
|
||||
obj.setExpression("OverallWidth", "Length.Value")
|
||||
elif "Width" in obj.PropertiesList:
|
||||
obj.setExpression("OverallWidth", "Width.Value")
|
||||
elif obj.Shape and (obj.Shape.BoundBox.XLength > obj.Shape.BoundBox.YLength):
|
||||
obj.setExpression("OverallWidth", "Shape.BoundBox.XLength")
|
||||
elif obj.Shape:
|
||||
obj.setExpression("OverallWidth", "Shape.BoundBox.YLength")
|
||||
elif attribute["name"] == "OverallHeight":
|
||||
if "Height" in obj.PropertiesList:
|
||||
obj.setExpression("OverallHeight", "Height.Value")
|
||||
else:
|
||||
obj.setExpression("OverallHeight", "Shape.BoundBox.ZLength")
|
||||
elif attribute["name"] == "ElevationWithFlooring" and "Shape" in obj.PropertiesList:
|
||||
obj.setExpression("ElevationWithFlooring", "Shape.BoundBox.ZMin")
|
||||
elif attribute["name"] == "Elevation":
|
||||
if "Placement" in obj.PropertiesList:
|
||||
elif attribute["name"] == "Elevation" and "Placement" in obj.PropertiesList:
|
||||
obj.setExpression("Elevation", "Placement.Base.z")
|
||||
elif attribute["name"] == "NominalDiameter":
|
||||
if "Diameter" in obj.PropertiesList:
|
||||
elif attribute["name"] == "NominalDiameter" and "Diameter" in obj.PropertiesList:
|
||||
obj.setExpression("NominalDiameter", "Diameter.Value")
|
||||
elif attribute["name"] == "BarLength":
|
||||
if "Length" in obj.PropertiesList:
|
||||
elif attribute["name"] == "BarLength" and "Length" in obj.PropertiesList:
|
||||
obj.setExpression("BarLength", "Length.Value")
|
||||
elif attribute["name"] == "RefElevation":
|
||||
if "Elevation" in obj.PropertiesList:
|
||||
elif attribute["name"] == "RefElevation" and "Elevation" in obj.PropertiesList:
|
||||
obj.setExpression("RefElevation", "Elevation.Value")
|
||||
elif attribute["name"] == "LongName":
|
||||
obj.LongName = obj.Label
|
||||
elif attribute["name"] == "LongName":
|
||||
obj.LongName = obj.Label
|
||||
|
||||
def setObjIfcAttributeValue(obj, attributeName, value):
|
||||
|
||||
"Sets the value of a given attribute property"
|
||||
|
||||
IfcData = obj.IfcData
|
||||
if "attributes" not in IfcData:
|
||||
IfcData["attributes"] = "{}"
|
||||
IfcAttributes = json.loads(IfcData["attributes"])
|
||||
if isinstance(value, FreeCAD.Units.Quantity):
|
||||
value = float(value)
|
||||
if not attributeName in IfcAttributes:
|
||||
IfcAttributes[attributeName] = {}
|
||||
IfcAttributes[attributeName]["value"] = value
|
||||
IfcData["attributes"] = json.dumps(IfcAttributes)
|
||||
obj.IfcData = IfcData
|
||||
def setObjIfcAttributeValue(self, obj, attributeName, value):
|
||||
IfcData = obj.IfcData
|
||||
if "attributes" not in IfcData:
|
||||
IfcData["attributes"] = "{}"
|
||||
IfcAttributes = json.loads(IfcData["attributes"])
|
||||
if isinstance(value, FreeCAD.Units.Quantity):
|
||||
value = float(value)
|
||||
if not attributeName in IfcAttributes:
|
||||
IfcAttributes[attributeName] = {}
|
||||
IfcAttributes[attributeName]["value"] = value
|
||||
IfcData["attributes"] = json.dumps(IfcAttributes)
|
||||
obj.IfcData = IfcData
|
||||
|
||||
def purgeUnusedIfcAttributesFromPropertiesList(ifcProduct, obj):
|
||||
|
||||
"Removes unused attribute properties"
|
||||
|
||||
for property in obj.PropertiesList:
|
||||
if obj.getGroupOfProperty(property) != "IFC Attributes":
|
||||
continue
|
||||
ifcProductAttribute = getIfcProductAttribute(ifcProduct, property)
|
||||
if ifcProductAttribute is None or ifcProductAttribute["is_enum"] is True:
|
||||
obj.removeProperty(property)
|
||||
def setObjIfcComplexAttributeValue(self, obj, attributeName, value):
|
||||
IfcData = obj.IfcData
|
||||
IfcAttributes = json.loads(IfcData["complex_attributes"])
|
||||
IfcAttributes[attributeName] = value
|
||||
IfcData["complex_attributes"] = json.dumps(IfcAttributes)
|
||||
obj.IfcData = IfcData
|
||||
|
||||
def migrateDeprecatedAttributes(obj):
|
||||
|
||||
"Fixes obsolete properties"
|
||||
def getObjIfcComplexAttribute(self, obj, attributeName):
|
||||
return json.loads(obj.IfcData["complex_attributes"])[attributeName]
|
||||
|
||||
if "Role" in obj.PropertiesList:
|
||||
r = obj.Role
|
||||
obj.removeProperty("Role")
|
||||
if r in IfcTypes:
|
||||
obj.IfcType = r
|
||||
FreeCAD.Console.PrintMessage("Upgrading "+obj.Label+" Role property to IfcType\n")
|
||||
def purgeUnusedIfcAttributesFromPropertiesList(self, ifcTypeSchema, obj):
|
||||
for property in obj.PropertiesList:
|
||||
if obj.getGroupOfProperty(property) != "IFC Attributes":
|
||||
continue
|
||||
ifcAttribute = self.getIfcAttributeSchema(ifcTypeSchema, property)
|
||||
if ifcAttribute is None or ifcAttribute["is_enum"] is True:
|
||||
obj.removeProperty(property)
|
||||
|
||||
if "IfcRole" in obj.PropertiesList:
|
||||
r = obj.IfcRole
|
||||
obj.removeProperty("IfcRole")
|
||||
if r in IfcTypes:
|
||||
obj.IfcType = r
|
||||
FreeCAD.Console.PrintMessage("Upgrading "+obj.Label+" IfcRole property to IfcType\n")
|
||||
|
||||
if "IfcAttributes"in obj.PropertiesList:
|
||||
obj.IfcData = obj.IfcAttributes
|
||||
obj.removeProperty("IfcAttributes")
|
||||
def migrateDeprecatedAttributes(self, obj):
|
||||
if "Role" in obj.PropertiesList:
|
||||
r = obj.Role
|
||||
obj.removeProperty("Role")
|
||||
if r in IfcTypes:
|
||||
obj.IfcType = r
|
||||
FreeCAD.Console.PrintMessage("Upgrading "+obj.Label+" Role property to IfcType\n")
|
||||
|
||||
if "IfcRole" in obj.PropertiesList:
|
||||
r = obj.IfcRole
|
||||
obj.removeProperty("IfcRole")
|
||||
if r in IfcTypes:
|
||||
obj.IfcType = r
|
||||
FreeCAD.Console.PrintMessage("Upgrading "+obj.Label+" IfcRole property to IfcType\n")
|
||||
|
||||
if "IfcAttributes"in obj.PropertiesList:
|
||||
obj.IfcData = obj.IfcAttributes
|
||||
obj.removeProperty("IfcAttributes")
|
||||
|
||||
class IfcProduct(IfcRoot):
|
||||
def getIfcSchema(self):
|
||||
return ArchIFCSchema.IfcProducts
|
||||
|
||||
class IfcContext(IfcRoot):
|
||||
def getIfcSchema(self):
|
||||
return ArchIFCSchema.IfcContexts
|
||||
|
||||
@@ -3,6 +3,10 @@ import FreeCAD, os, json
|
||||
ifcVersions = ["IFC4", "IFC2X3"]
|
||||
IfcVersion = ifcVersions[FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetInt("IfcVersion",0)]
|
||||
|
||||
with open(os.path.join(FreeCAD.getResourceDir(), "Mod", "Arch", "Presets",
|
||||
"ifc_contexts_" + IfcVersion + ".json")) as f:
|
||||
IfcContexts = json.load(f)
|
||||
|
||||
with open(os.path.join(FreeCAD.getResourceDir(), "Mod", "Arch", "Presets",
|
||||
"ifc_products_" + IfcVersion + ".json")) as f:
|
||||
IfcProducts = json.load(f)
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import FreeCAD, ArchIFC
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
|
||||
class IfcContextView:
|
||||
def setEdit(self, viewObject, mode):
|
||||
# What does mode do?
|
||||
FreeCADGui.Control.showDialog(IfcContextUI(viewObject.Object))
|
||||
return True
|
||||
|
||||
class IfcContextUI:
|
||||
def __init__(self, object):
|
||||
self.object = object
|
||||
self.lineEditObjects = []
|
||||
self.createBaseLayout()
|
||||
self.createMapConversionFormLayout()
|
||||
self.prefillMapConversionForm()
|
||||
self.form = self.baseWidget
|
||||
|
||||
def accept(self):
|
||||
data = {}
|
||||
for lineEdit in self.lineEditObjects:
|
||||
data[lineEdit.objectName()] = lineEdit.text()
|
||||
ArchIFC.IfcRoot.setObjIfcComplexAttributeValue(self, self.object, "RepresentationContexts", data)
|
||||
return True
|
||||
|
||||
def createBaseLayout(self):
|
||||
self.baseWidget = QtGui.QWidget()
|
||||
self.baseLayout = QtGui.QVBoxLayout(self.baseWidget)
|
||||
|
||||
def createMapConversionFormLayout(self):
|
||||
self.baseLayout.addWidget(self.createLabel("Target Coordinate Reference System"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("name", "Name"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("description", "Description"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("geodetic_datum", "Geodetic datum"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("vertical_datum", "Vertical datum"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("map_projection", "Map projection"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("map_zone", "Map zone"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("map_unit", "Map unit"))
|
||||
|
||||
self.baseLayout.addWidget(self.createLabel("Map Conversion"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("eastings", "Eastings"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("northings", "Northings"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("orthogonal_height", "Orthogonal height"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("true_north", "True north (anti-clockwise from +Y)"))
|
||||
self.baseLayout.addLayout(self.createFormEntry("scale", "Scale"))
|
||||
|
||||
def prefillMapConversionForm(self):
|
||||
data = ArchIFC.IfcRoot.getObjIfcComplexAttribute(self, self.object, "RepresentationContexts")
|
||||
for lineEdit in self.lineEditObjects:
|
||||
if lineEdit.objectName() in data.keys():
|
||||
lineEdit.setText(data[lineEdit.objectName()])
|
||||
|
||||
def createFormEntry(self, name, label):
|
||||
layout = QtGui.QHBoxLayout(self.baseWidget)
|
||||
layout.addWidget(self.createLabel(label))
|
||||
layout.addWidget(self.createLineEdit(name))
|
||||
return layout
|
||||
|
||||
def createLabel(self, value):
|
||||
label = QtGui.QLabel(self.baseWidget)
|
||||
label.setText(QtGui.QApplication.translate("Arch", value, None))
|
||||
return label
|
||||
|
||||
def createLineEdit(self, name):
|
||||
lineEdit = QtGui.QLineEdit(self.baseWidget)
|
||||
lineEdit.setObjectName(name)
|
||||
self.lineEditObjects.append(lineEdit)
|
||||
return lineEdit
|
||||
@@ -825,6 +825,11 @@ class PanelView:
|
||||
def __init__(self, obj):
|
||||
|
||||
obj.Proxy = self
|
||||
|
||||
# setProperties of ArchComponent will be overwritten
|
||||
# thus setProperties from ArchComponent will be explicit called to get the properties
|
||||
ArchComponent.ViewProviderComponent.setProperties(self, vobj)
|
||||
|
||||
self.setProperties(obj)
|
||||
obj.X = 10
|
||||
obj.Y = 10
|
||||
@@ -924,6 +929,11 @@ class PanelCut(Draft._DraftObject):
|
||||
def __init__(self, obj):
|
||||
Draft._DraftObject.__init__(self,obj)
|
||||
obj.Proxy = self
|
||||
|
||||
# setProperties of ArchComponent will be overwritten
|
||||
# thus setProperties from ArchComponent will be explicit called to get the properties
|
||||
ArchComponent.ViewProviderComponent.setProperties(self, vobj)
|
||||
|
||||
self.setProperties(obj)
|
||||
|
||||
def setProperties(self,obj):
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
# -*- coding: utf8 -*-
|
||||
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011 *
|
||||
#* Yorik van Havre <[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,Draft,ArchComponent,ArchCommands,math,re,datetime,ArchIFC,ArchIFCView
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
from DraftTools import translate
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
else:
|
||||
def translate(ctxt,txt):
|
||||
return txt
|
||||
def QT_TRANSLATE_NOOP(ctxt,txt):
|
||||
return txt
|
||||
|
||||
## @package ArchProject
|
||||
# \ingroup ARCH
|
||||
# \brief The Project object and tools
|
||||
#
|
||||
# This module provides tools to build Project objects.
|
||||
|
||||
__title__="FreeCAD Project"
|
||||
__author__ = "Yorik van Havre"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
def makeProject(sites=None, name="Project"):
|
||||
|
||||
'''makeProject(sites): creates a project aggregating the list of sites.'''
|
||||
|
||||
if not FreeCAD.ActiveDocument:
|
||||
return FreeCAD.Console.PrintError("No active document. Aborting\n")
|
||||
|
||||
import Part
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Project")
|
||||
obj.Label = translate("Arch", name)
|
||||
_Project(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
_ViewProviderProject(obj.ViewObject)
|
||||
if sites:
|
||||
obj.Group = sites
|
||||
return obj
|
||||
|
||||
class _CommandProject:
|
||||
|
||||
"the Arch Project command definition"
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Arch_Project',
|
||||
'MenuText': QT_TRANSLATE_NOOP("Arch_Project", "Project"),
|
||||
'Accel': "P, O",
|
||||
'ToolTip': QT_TRANSLATE_NOOP("Arch_Project", "Creates a project entity aggregating the selected sites.")}
|
||||
|
||||
def IsActive(self):
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
|
||||
def Activated(self):
|
||||
selection = FreeCADGui.Selection.getSelection()
|
||||
siteobj = []
|
||||
|
||||
for obj in selection:
|
||||
if hasattr(obj, "IfcType") and obj.IfcType == "Site":
|
||||
siteobj.append(obj)
|
||||
|
||||
ss = "[ "
|
||||
for o in siteobj:
|
||||
ss += "FreeCAD.ActiveDocument." + o.Name + ", "
|
||||
ss += "]"
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Project"))
|
||||
FreeCADGui.addModule("Arch")
|
||||
FreeCADGui.doCommand("obj = Arch.makeProject("+ss+")")
|
||||
FreeCADGui.addModule("Draft")
|
||||
FreeCADGui.doCommand("Draft.autogroup(obj)")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
class _Project(ArchIFC.IfcContext):
|
||||
|
||||
def __init__(self, obj):
|
||||
obj.Proxy = self
|
||||
self.setProperties(obj)
|
||||
obj.IfcType = "Project"
|
||||
|
||||
def setProperties(self, obj):
|
||||
ArchIFC.IfcContext.setProperties(self, obj)
|
||||
pl = obj.PropertiesList
|
||||
if not hasattr(obj,"Group"):
|
||||
obj.addExtension("App::GroupExtensionPython", self)
|
||||
self.Type = "Project"
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
self.setProperties(obj)
|
||||
|
||||
class _ViewProviderProject(ArchIFCView.IfcContextView):
|
||||
|
||||
def __init__(self,vobj):
|
||||
vobj.Proxy = self
|
||||
vobj.addExtension("Gui::ViewProviderGroupExtensionPython", self)
|
||||
|
||||
def getIcon(self):
|
||||
import Arch_rc
|
||||
return ":/icons/Arch_Project_Tree.svg"
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Arch_Project', _CommandProject())
|
||||
@@ -298,7 +298,7 @@ def getSVG(section, renderMode="Wireframe", allOn=False, showHidden=False, scale
|
||||
svgcache += render.getHiddenSVG(linewidth="SVGLINEWIDTH")
|
||||
svgcache += '</g>\n'
|
||||
# print(render.info())
|
||||
section.Proxy.svgcache = [svgcache,renderMode,showHidden,showFill]
|
||||
section.Proxy.svgcache = [svgcache,renderMode,showHidden,showFill,fillSpaces]
|
||||
else:
|
||||
|
||||
if not svgcache:
|
||||
|
||||
@@ -521,7 +521,7 @@ Site creation aborted.") + "\n"
|
||||
|
||||
|
||||
|
||||
class _Site:
|
||||
class _Site(ArchIFC.IfcProduct):
|
||||
|
||||
"The Site object"
|
||||
|
||||
@@ -533,8 +533,7 @@ class _Site:
|
||||
|
||||
def setProperties(self,obj):
|
||||
|
||||
import ArchIFC
|
||||
ArchIFC.setProperties(obj)
|
||||
ArchIFC.IfcProduct.setProperties(self, obj)
|
||||
|
||||
pl = obj.PropertiesList
|
||||
if not "Terrain" in pl:
|
||||
@@ -638,7 +637,7 @@ class _Site:
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
|
||||
ArchIFC.onChanged(obj, prop)
|
||||
ArchIFC.IfcProduct.onChanged(self, obj, prop)
|
||||
if prop == "Terrain":
|
||||
if obj.Terrain:
|
||||
if FreeCAD.GuiUp:
|
||||
|
||||
@@ -896,6 +896,11 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
|
||||
def __init__(self,vobj):
|
||||
|
||||
ArchComponent.ViewProviderComponent.__init__(self,vobj)
|
||||
|
||||
# setProperties of ArchComponent will be overwritten
|
||||
# thus setProperties from ArchComponent will be explicit called to get the properties
|
||||
ArchComponent.ViewProviderComponent.setProperties(self, vobj)
|
||||
|
||||
self.setProperties(vobj)
|
||||
vobj.ShapeColor = ArchCommands.getDefaultColor("Structure")
|
||||
|
||||
|
||||
@@ -521,13 +521,13 @@ class _Wall(ArchComponent.Component):
|
||||
|
||||
"The Wall object"
|
||||
|
||||
def __init__(self,obj):
|
||||
def __init__(self, obj):
|
||||
|
||||
ArchComponent.Component.__init__(self,obj)
|
||||
ArchComponent.Component.__init__(self, obj)
|
||||
self.setProperties(obj)
|
||||
obj.IfcType = "Wall"
|
||||
|
||||
def setProperties(self,obj):
|
||||
def setProperties(self, obj):
|
||||
|
||||
lp = obj.PropertiesList
|
||||
if not "Length" in lp:
|
||||
@@ -750,12 +750,10 @@ class _Wall(ArchComponent.Component):
|
||||
obj.Area = obj.Length.Value * obj.Height.Value
|
||||
|
||||
def onBeforeChange(self,obj,prop):
|
||||
|
||||
if prop == "Length":
|
||||
self.oldLength = obj.Length.Value
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
if prop == "Length":
|
||||
if obj.Base and obj.Length.Value and hasattr(self,"oldLength") and (self.oldLength != None) and (self.oldLength != obj.Length.Value):
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
@@ -804,6 +802,8 @@ class _Wall(ArchComponent.Component):
|
||||
|
||||
# TODO currently layers were not supported when len(basewires) > 0
|
||||
width = 0
|
||||
widths = obj.OverrideWidth
|
||||
|
||||
if obj.OverrideWidth:
|
||||
if obj.OverrideWidth[0]:
|
||||
width = obj.OverrideWidth[0]
|
||||
@@ -811,7 +811,7 @@ class _Wall(ArchComponent.Component):
|
||||
if obj.Width:
|
||||
width = obj.Width.Value
|
||||
else:
|
||||
print("Width or Widths Of Wall [0] should not be 0")
|
||||
print("Width or OverrideWidth[0] should not be 0")
|
||||
return
|
||||
|
||||
height = obj.Height.Value
|
||||
@@ -888,9 +888,12 @@ class _Wall(ArchComponent.Component):
|
||||
|
||||
if (len(self.basewires) == 1) and layers:
|
||||
self.basewires = [self.basewires[0] for l in layers]
|
||||
|
||||
layeroffset = 0
|
||||
baseface = None
|
||||
for i,wire in enumerate(self.basewires):
|
||||
|
||||
edgeNum = len(wire.Edges)
|
||||
e = wire.Edges[0]
|
||||
if isinstance(e.Curve,Part.Circle):
|
||||
dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
|
||||
@@ -911,7 +914,7 @@ class _Wall(ArchComponent.Component):
|
||||
dvec2 = DraftVecUtils.scaleTo(dvec,off)
|
||||
wire = DraftGeomUtils.offsetWire(wire,dvec2)
|
||||
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, obj.OverrideWidth)
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, widths)
|
||||
|
||||
w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
@@ -928,7 +931,7 @@ class _Wall(ArchComponent.Component):
|
||||
dvec2 = DraftVecUtils.scaleTo(dvec,off)
|
||||
wire = DraftGeomUtils.offsetWire(wire,dvec2)
|
||||
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, obj.OverrideWidth)
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, widths)
|
||||
|
||||
w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
@@ -944,12 +947,16 @@ class _Wall(ArchComponent.Component):
|
||||
else:
|
||||
dvec.multiply(width/2) ## TODO width Value should be of no use (width/2), width Direction remains 'in use'
|
||||
|
||||
overrideWidthHalfen = [i/2 for i in obj.OverrideWidth]
|
||||
overrideWidthHalfen = [i/2 for i in widths]
|
||||
|
||||
w1 = DraftGeomUtils.offsetWire(wire,dvec,False, False, overrideWidthHalfen)
|
||||
dvec = dvec.negative()
|
||||
w2 = DraftGeomUtils.offsetWire(wire,dvec,False, False, overrideWidthHalfen)
|
||||
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
|
||||
del widths[0:edgeNum]
|
||||
|
||||
if sh:
|
||||
sh.fix(0.1,0,1) # fixes self-intersecting wires
|
||||
f = Part.Face(sh)
|
||||
|
||||
@@ -7,10 +7,14 @@ SET(Arch_SRCS
|
||||
InitGui.py
|
||||
ArchComponent.py
|
||||
ArchIFC.py
|
||||
ArchIFCView.py
|
||||
ArchIFCSchema.py
|
||||
ArchProject.py
|
||||
ArchWall.py
|
||||
importIFC.py
|
||||
importIFClegacy.py
|
||||
importIFCHelper.py
|
||||
exportIFCHelper.py
|
||||
Arch.py
|
||||
ArchBuilding.py
|
||||
ArchFloor.py
|
||||
@@ -62,6 +66,7 @@ SET(Arch_presets
|
||||
Presets/ifc_products_IFC4.json
|
||||
Presets/ifc_types_IFC2X3.json
|
||||
Presets/ifc_types_IFC4.json
|
||||
Presets/ifc_contexts_IFC4.json
|
||||
)
|
||||
|
||||
SOURCE_GROUP("" FILES ${Arch_SRCS})
|
||||
|
||||
@@ -34,7 +34,7 @@ class ArchWorkbench(Workbench):
|
||||
|
||||
# arch tools
|
||||
self.archtools = ["Arch_Wall","Arch_Structure","Arch_Rebar","Arch_BuildingPart",
|
||||
"Arch_Floor","Arch_Building","Arch_Site","Arch_Reference",
|
||||
"Arch_Project", "Arch_Site", "Arch_Building", "Arch_Floor", "Arch_Reference",
|
||||
"Arch_Window","Arch_Roof","Arch_AxisTools",
|
||||
"Arch_SectionPlane","Arch_Space","Arch_Stairs",
|
||||
"Arch_PanelTools","Arch_Equipment",
|
||||
@@ -64,9 +64,6 @@ class ArchWorkbench(Workbench):
|
||||
FreeCADGui.addCommand('Arch_RebarTools', RebarGroupCommand())
|
||||
self.archtools[2] = "Arch_RebarTools"
|
||||
|
||||
# setup Draft_Edit command
|
||||
import DraftEdit
|
||||
FreeCADGui.addCommand('Draft_Edit',DraftEdit.Edit())
|
||||
|
||||
# draft tools
|
||||
self.drafttools = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse",
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"IfcProject": {
|
||||
"is_abstract": false,
|
||||
"parent": "IfcContext",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "GlobalId",
|
||||
"type": "IfcGloballyUniqueId",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "Name",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "Description",
|
||||
"type": "IfcText",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "ObjectType",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "LongName",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "Phase",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
}
|
||||
],
|
||||
"complex_attributes": [
|
||||
{
|
||||
"name": "OwnerHistory",
|
||||
"type": "IfcOwnerHistory"
|
||||
},
|
||||
{
|
||||
"name": "IsNestedBy",
|
||||
"type": "IfcRelNests"
|
||||
},
|
||||
{
|
||||
"name": "IsDecomposedBy",
|
||||
"type": "IfcRelAggregates"
|
||||
},
|
||||
{
|
||||
"name": "RepresentationContexts",
|
||||
"type": "IfcRepresentationContext"
|
||||
},
|
||||
{
|
||||
"name": "UnitsInContext",
|
||||
"type": "IfcUnitAssignment"
|
||||
},
|
||||
{
|
||||
"name": "IsDefinedBy",
|
||||
"type": "IfcRelDefinesByProperties"
|
||||
},
|
||||
{
|
||||
"name": "Declares",
|
||||
"type": "IfcRelDeclares"
|
||||
}
|
||||
]
|
||||
},
|
||||
"IfcProjectLibrary": {
|
||||
"is_abstract": false,
|
||||
"parent": "IfcContext",
|
||||
"attributes": [
|
||||
{
|
||||
"name": "GlobalId",
|
||||
"type": "IfcGloballyUniqueId",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "Name",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "Description",
|
||||
"type": "IfcText",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "ObjectType",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "LongName",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
},
|
||||
{
|
||||
"name": "Phase",
|
||||
"type": "IfcLabel",
|
||||
"is_enum": false,
|
||||
"enum_values": []
|
||||
}
|
||||
],
|
||||
"complex_attributes": [
|
||||
{
|
||||
"name": "OwnerHistory",
|
||||
"type": "IfcOwnerHistory"
|
||||
},
|
||||
{
|
||||
"name": "IsNestedBy",
|
||||
"type": "IfcRelNests"
|
||||
},
|
||||
{
|
||||
"name": "IsDecomposedBy",
|
||||
"type": "IfcRelAggregates"
|
||||
},
|
||||
{
|
||||
"name": "RepresentationContexts",
|
||||
"type": "IfcRepresentationContext"
|
||||
},
|
||||
{
|
||||
"name": "UnitsInContext",
|
||||
"type": "IfcUnitAssignment"
|
||||
},
|
||||
{
|
||||
"name": "IsDefinedBy",
|
||||
"type": "IfcRelDefinesByProperties"
|
||||
},
|
||||
{
|
||||
"name": "Declares",
|
||||
"type": "IfcRelDeclares"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<file>icons/Arch_Cell.svg</file>
|
||||
<file>icons/Arch_Wall.svg</file>
|
||||
<file>icons/Arch_Site.svg</file>
|
||||
<file>icons/Arch_Project.svg</file>
|
||||
<file>icons/Arch_Structure.svg</file>
|
||||
<file>icons/Arch_Add.svg</file>
|
||||
<file>icons/Arch_Remove.svg</file>
|
||||
@@ -21,6 +22,7 @@
|
||||
<file>icons/Arch_Floor_Tree.svg</file>
|
||||
<file>icons/Arch_SectionPlane_Tree.svg</file>
|
||||
<file>icons/Arch_Site_Tree.svg</file>
|
||||
<file>icons/Arch_Project_Tree.svg</file>
|
||||
<file>icons/Arch_Structure_Tree.svg</file>
|
||||
<file>icons/Arch_Structure_Clone.svg</file>
|
||||
<file>icons/Arch_Window_Tree.svg</file>
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
<?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: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="svg2980"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="ifc_project_icon.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<title
|
||||
id="title4553">ifc_project_icon</title>
|
||||
<defs
|
||||
id="defs2982">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1491">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1487" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1489" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1460">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1456" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1458" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1452">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1448" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1450" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1371">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1367" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1369" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1212">
|
||||
<stop
|
||||
style="stop-color:#9f8201;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1208" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1210" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient966">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop962" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop964" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient958">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop954" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop956" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1584">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1580" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1582" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3794">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3796" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3798" />
|
||||
</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>
|
||||
<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="perspective2988" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3794"
|
||||
id="radialGradient3800"
|
||||
cx="1"
|
||||
cy="45"
|
||||
fx="1"
|
||||
fy="45"
|
||||
r="41"
|
||||
gradientTransform="matrix(0.93348213,-2.2905276e-8,0,0.28687573,0.06651751,32.090592)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1584"
|
||||
id="linearGradient1586"
|
||||
x1="19.742287"
|
||||
y1="29.617214"
|
||||
x2="16.630623"
|
||||
y2="5.6647563"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient958"
|
||||
id="linearGradient960"
|
||||
x1="42.720432"
|
||||
y1="35.358803"
|
||||
x2="38.797985"
|
||||
y2="12.301081"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="rotate(29.953188,22.410187,2.0303151)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient966"
|
||||
id="linearGradient968"
|
||||
x1="38.753258"
|
||||
y1="11.986131"
|
||||
x2="36.959591"
|
||||
y2="4.3561206"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.86036595,0.4957957,-0.65446032,1.1357004,4.8924107,-11.874215)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient958"
|
||||
id="linearGradient1017"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="rotate(29.953188,22.410187,2.0303151)"
|
||||
x1="42.720432"
|
||||
y1="35.358803"
|
||||
x2="38.797985"
|
||||
y2="12.301081" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1212"
|
||||
id="linearGradient1214"
|
||||
x1="35.502228"
|
||||
y1="43.943478"
|
||||
x2="25.338087"
|
||||
y2="20.853832"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1371"
|
||||
id="linearGradient1373"
|
||||
x1="103.49044"
|
||||
y1="57.973423"
|
||||
x2="91.800392"
|
||||
y2="9.8313513"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1371"
|
||||
id="linearGradient1403"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="106.64566"
|
||||
y1="32.015091"
|
||||
x2="83.025734"
|
||||
y2="16.70879"
|
||||
gradientTransform="matrix(0.71299585,0,0,0.71299585,-38.159919,7.6652554)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1452"
|
||||
id="linearGradient1454"
|
||||
x1="25.694189"
|
||||
y1="41.841251"
|
||||
x2="17.957205"
|
||||
y2="35.542679"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1460"
|
||||
id="linearGradient1462"
|
||||
x1="29.591785"
|
||||
y1="38.03183"
|
||||
x2="28.189938"
|
||||
y2="32.499073"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1491"
|
||||
id="linearGradient1493"
|
||||
x1="35.284328"
|
||||
y1="12.935562"
|
||||
x2="29.851774"
|
||||
y2="10.693736"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.9632948"
|
||||
inkscape:cx="13.992731"
|
||||
inkscape:cy="39.787963"
|
||||
inkscape:current-layer="g1015"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1051"
|
||||
inkscape:window-x="1791"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2991"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2985">
|
||||
<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>ifc_project_icon</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[bitacovir] Rafael Moya</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>Part_Box</dc:title>
|
||||
<dc:date>2019-06-16</dc:date>
|
||||
<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
|
||||
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/">https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g1015"
|
||||
transform="matrix(1.4025327,0,0,1.4025327,-12.5084,-9.9751934)">
|
||||
<path
|
||||
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.16908914;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="M 33.762019,29.98086 C 25.043358,23.889681 17.89608,18.865025 17.879176,18.814958 c -0.01691,-0.05007 0.197559,-0.313039 0.476582,-0.584381 0.878355,-0.854175 1.765285,-1.182233 3.196257,-1.182233 1.536913,0 2.775433,0.302228 5.677307,1.385393 2.559942,0.955533 3.863647,1.258501 6.105455,1.418843 l 1.314957,0.09405 0.676355,0.42569 c 0.371999,0.23413 1.950871,1.249591 3.508603,2.256581 1.557732,1.006989 3.139841,2.027163 3.515804,2.267053 0.407256,0.259862 0.727776,0.530464 0.792951,0.669459 0.06018,0.128313 0.373111,0.88006 0.695442,1.670552 0.928392,2.276847 1.391575,2.997958 3.059536,4.763285 2.162232,2.288437 3.252103,3.90544 3.639217,5.399359 0.200416,0.773427 0.172894,1.821207 -0.06289,2.394268 -0.197991,0.481212 -0.696176,1.267387 -0.801293,1.264491 -0.03265,-9.27e-4 -7.192795,-4.985328 -15.91145,-11.076508 z"
|
||||
id="path1108"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#linearGradient1403);fill-opacity:1;stroke:#302b00;stroke-width:1.42599171;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.079201,14.206157 c -7.3491,5.068907 -9.808395,11.28394 -10.687974,17.868066 v 11.101568 l 31.24788,-0.190782 0.05433,-10.910786 c 0.06718,-7.621033 -5.002286,-12.874 -10.632294,-17.868066 z m 20.509768,28.922286 -31.112796,0.126725 -4.733346,3.761331 0.04177,3.636001 h 40.497334 v -3.889448 z"
|
||||
id="path1265-5" />
|
||||
<path
|
||||
style="fill:url(#linearGradient1493);stroke:#302b00;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 27.239239,13.981979 c 1.23915,-5.8754621 8.21462,-5.4405771 9.55166,0 z"
|
||||
id="path1220-87"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<rect
|
||||
style="opacity:1;fill:url(#linearGradient1454);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.62589371;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect1431"
|
||||
width="9.002841"
|
||||
height="10.222729"
|
||||
x="17.366549"
|
||||
y="32.418114" />
|
||||
<path
|
||||
style="fill:none;stroke:#fce94f;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.725189,15.641754 8.81324,0.003 c 6.940872,5.302711 9.686672,11.546987 9.674182,15.867818 l 0.01925,12.395919 4.609275,3.539053 0.0095,1.787896 -37.693861,-0.0023 0.0049,-1.597929 4.64051,-3.599752 0.113104,-12.478863 c 0.96778,-6.426734 3.59727,-11.70258 9.567,-15.618951 z"
|
||||
id="path1216-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccc" />
|
||||
<rect
|
||||
style="opacity:1;fill:url(#linearGradient1462);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75087309;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect1431-2"
|
||||
width="10.440099"
|
||||
height="10.222729"
|
||||
x="26.796108"
|
||||
y="32.629475" />
|
||||
<path
|
||||
style="fill:none;stroke:#302b00;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 16.575149,32.276223 h 31.07164"
|
||||
id="path1196-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
style="opacity:1;fill:#302b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.07927084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path1242-1"
|
||||
cx="21.528547"
|
||||
cy="37.260105"
|
||||
r="2.6079915" />
|
||||
<circle
|
||||
style="opacity:1;fill:#302b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.07927084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path1242-8-2"
|
||||
cx="32.098705"
|
||||
cy="37.294384"
|
||||
r="2.6079915" />
|
||||
<circle
|
||||
style="opacity:1;fill:#302b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.07927084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path1242-3-4"
|
||||
cx="42.29948"
|
||||
cy="37.32428"
|
||||
r="2.6079915" />
|
||||
<path
|
||||
style="fill:none;stroke:#302b00;stroke-width:1.84060574;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 16.30258,43.183831 H 47.823829"
|
||||
id="path1196-4-2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#fce94f;stroke-width:1.3768388;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 17.506414,30.800931 H 46.472936"
|
||||
id="path1196-4-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#302b00;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 31.382129,14.083052 c -3.13613,4.970362 -4.81717,10.954296 -4.98681,17.991026 v 10.781139"
|
||||
id="path1192-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#302b00;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 33.300129,14.150434 c 2.58579,5.068087 4.38829,10.79545 4.52649,17.923644 l -0.15344,10.781139"
|
||||
id="path1194-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,435 @@
|
||||
<?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: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="svg2980"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="ifc_Project_Tree.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<title
|
||||
id="title4553">ifc_project_tree</title>
|
||||
<defs
|
||||
id="defs2982">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient904">
|
||||
<stop
|
||||
style="stop-color:#babdb6;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop900" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop902" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient896"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop892"
|
||||
offset="0"
|
||||
style="stop-color:#888a85;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop894"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1460">
|
||||
<stop
|
||||
style="stop-color:#888a85;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1456" />
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1458" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1452">
|
||||
<stop
|
||||
style="stop-color:#888a85;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1448" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1450" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1371">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1367" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1369" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1212">
|
||||
<stop
|
||||
style="stop-color:#9f8201;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1208" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1210" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient966">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop962" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop964" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient958">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop954" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop956" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1584">
|
||||
<stop
|
||||
style="stop-color:#c4a000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1580" />
|
||||
<stop
|
||||
style="stop-color:#fce94f;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1582" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3794">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3796" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3798" />
|
||||
</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>
|
||||
<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="perspective2988" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3794"
|
||||
id="radialGradient3800"
|
||||
cx="1"
|
||||
cy="45"
|
||||
fx="1"
|
||||
fy="45"
|
||||
r="41"
|
||||
gradientTransform="matrix(0.93348213,-2.2905276e-8,0,0.28687573,0.06651751,32.090592)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1584"
|
||||
id="linearGradient1586"
|
||||
x1="19.742287"
|
||||
y1="29.617214"
|
||||
x2="16.630623"
|
||||
y2="5.6647563"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient958"
|
||||
id="linearGradient960"
|
||||
x1="42.720432"
|
||||
y1="35.358803"
|
||||
x2="38.797985"
|
||||
y2="12.301081"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="rotate(29.953188,22.410187,2.0303151)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient966"
|
||||
id="linearGradient968"
|
||||
x1="38.753258"
|
||||
y1="11.986131"
|
||||
x2="36.959591"
|
||||
y2="4.3561206"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.86036595,0.4957957,-0.65446032,1.1357004,4.8924107,-11.874215)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient958"
|
||||
id="linearGradient1017"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="rotate(29.953188,22.410187,2.0303151)"
|
||||
x1="42.720432"
|
||||
y1="35.358803"
|
||||
x2="38.797985"
|
||||
y2="12.301081" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1212"
|
||||
id="linearGradient1214"
|
||||
x1="35.502228"
|
||||
y1="43.943478"
|
||||
x2="25.338087"
|
||||
y2="20.853832"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1371"
|
||||
id="linearGradient1373"
|
||||
x1="103.49044"
|
||||
y1="57.973423"
|
||||
x2="91.800392"
|
||||
y2="9.8313513"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient896"
|
||||
id="linearGradient1403"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="106.64566"
|
||||
y1="32.015091"
|
||||
x2="80.061317"
|
||||
y2="27.380676"
|
||||
gradientTransform="matrix(0.71299585,0,0,0.71299585,-38.159919,7.6652554)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1452"
|
||||
id="linearGradient1454"
|
||||
x1="25.947823"
|
||||
y1="40.234905"
|
||||
x2="17.87266"
|
||||
y2="37.06448"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1460"
|
||||
id="linearGradient1462"
|
||||
x1="33.903557"
|
||||
y1="37.440018"
|
||||
x2="28.189938"
|
||||
y2="32.499073"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient904"
|
||||
id="linearGradient906"
|
||||
x1="34.81163"
|
||||
y1="13.296743"
|
||||
x2="30.571222"
|
||||
y2="11.436762"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="8.4333724"
|
||||
inkscape:cx="5.7127805"
|
||||
inkscape:cy="30.61729"
|
||||
inkscape:current-layer="g1015"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1051"
|
||||
inkscape:window-x="1791"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2991"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2985">
|
||||
<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>ifc_project_tree</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[bitacovir] Rafael Moya</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>Part_Box</dc:title>
|
||||
<dc:date>2019-06-16</dc:date>
|
||||
<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
|
||||
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/">https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title></dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g1015"
|
||||
transform="matrix(1.4025327,0,0,1.4025327,-12.5084,-9.9751934)">
|
||||
<path
|
||||
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.16908914;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="M 33.762019,29.98086 C 25.043358,23.889681 17.89608,18.865025 17.879176,18.814958 c -0.01691,-0.05007 0.197559,-0.313039 0.476582,-0.584381 0.878355,-0.854175 1.765285,-1.182233 3.196257,-1.182233 1.536913,0 2.775433,0.302228 5.677307,1.385393 2.559942,0.955533 3.863647,1.258501 6.105455,1.418843 l 1.314957,0.09405 0.676355,0.42569 c 0.371999,0.23413 1.950871,1.249591 3.508603,2.256581 1.557732,1.006989 3.139841,2.027163 3.515804,2.267053 0.407256,0.259862 0.727776,0.530464 0.792951,0.669459 0.06018,0.128313 0.373111,0.88006 0.695442,1.670552 0.928392,2.276847 1.391575,2.997958 3.059536,4.763285 2.162232,2.288437 3.252103,3.90544 3.639217,5.399359 0.200416,0.773427 0.172894,1.821207 -0.06289,2.394268 -0.197991,0.481212 -0.696176,1.267387 -0.801293,1.264491 -0.03265,-9.27e-4 -7.192795,-4.985328 -15.91145,-11.076508 z"
|
||||
id="path1108"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#linearGradient1403);fill-opacity:1;stroke:#2e3436;stroke-width:1.42599171;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.079201,14.206157 c -7.3491,5.068907 -9.808395,11.28394 -10.687974,17.868066 v 11.101568 l 31.24788,-0.190782 0.05433,-10.910786 c 0.06718,-7.621033 -5.002286,-12.874 -10.632294,-17.868066 z m 20.509768,28.922286 -31.112796,0.126725 -4.733346,3.761331 0.04177,3.636001 h 40.497334 v -3.889448 z"
|
||||
id="path1265-5" />
|
||||
<path
|
||||
style="fill:url(#linearGradient906);stroke:#2e3436;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 27.239239,13.981979 c 1.23915,-5.8754621 8.21462,-5.4405771 9.55166,0 z"
|
||||
id="path1220-87"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<rect
|
||||
style="opacity:1;fill:url(#linearGradient1454);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.62589371;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect1431"
|
||||
width="9.002841"
|
||||
height="10.222729"
|
||||
x="17.366549"
|
||||
y="32.418114" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.725189,15.641754 8.81324,0.003 c 6.940872,5.302711 9.686672,11.546987 9.674182,15.867818 l 0.01925,12.395919 4.609275,3.539053 0.0095,1.787896 -37.693861,-0.0023 0.0049,-1.597929 4.64051,-3.599752 0.113104,-12.478863 c 0.96778,-6.426734 3.59727,-11.70258 9.567,-15.618951 z"
|
||||
id="path1216-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccc" />
|
||||
<rect
|
||||
style="opacity:1;fill:url(#linearGradient1462);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75087309;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect1431-2"
|
||||
width="10.440099"
|
||||
height="10.222729"
|
||||
x="26.796108"
|
||||
y="32.629475" />
|
||||
<circle
|
||||
style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.07927084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path1242-1"
|
||||
cx="21.528547"
|
||||
cy="37.260105"
|
||||
r="2.6079915" />
|
||||
<circle
|
||||
style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.07927084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path1242-8-2"
|
||||
cx="32.098705"
|
||||
cy="37.294384"
|
||||
r="2.6079915" />
|
||||
<circle
|
||||
style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.07927084;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path1242-3-4"
|
||||
cx="42.29948"
|
||||
cy="37.32428"
|
||||
r="2.6079915" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.3768388;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 17.506414,30.800931 H 46.472936"
|
||||
id="path1196-4-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#2e3436;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 31.382129,14.083052 c -3.13613,4.970362 -4.81717,10.954296 -4.98681,17.991026 v 10.781139"
|
||||
id="path1192-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#2e3436;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 33.300129,14.150434 c 2.58579,5.068087 4.38829,10.79545 4.52649,17.923644 l -0.15344,10.781139"
|
||||
id="path1194-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#2e3436;stroke-width:1.42599165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 16.575149,32.276223 h 31.07164"
|
||||
id="path1196-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#2e3436;stroke-width:1.85104859;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 16.30258,43.183831 H 48.182521"
|
||||
id="path1196-4-2"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>446</width>
|
||||
<height>792</height>
|
||||
<height>811</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -217,6 +217,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_6">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, when an Arch object has a material, the object will take the color of the material. This can be overridden for each object.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use material color as shape color</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
|
||||
@@ -43,6 +43,7 @@ from DraftGeomUtils import vec
|
||||
from importIFC import recycler
|
||||
from importIFC import dd2dms
|
||||
from importIFC import decode
|
||||
import exportIFCHelper
|
||||
|
||||
|
||||
## @package exportIFC
|
||||
@@ -94,7 +95,6 @@ DATA;
|
||||
#8=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
|
||||
#10=IFCDIRECTION((0.,1.,0.));
|
||||
#11=IFCGEOMETRICREPRESENTATIONCONTEXT('Plan','Model',3,1.E-05,#9,#10);
|
||||
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
|
||||
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
|
||||
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
|
||||
@@ -103,7 +103,6 @@ DATA;
|
||||
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
|
||||
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
|
||||
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
|
||||
#20=IFCPROJECT('$projectid',#5,'$project',$,$,$,$,(#11),#19);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
"""
|
||||
@@ -111,7 +110,7 @@ END-ISO-10303-21;
|
||||
|
||||
# ************************************************************************************************
|
||||
# ********** duplicate methods ****************
|
||||
# TODO red rid of this duplicate
|
||||
# TODO get rid of this duplicate
|
||||
|
||||
def getPreferences():
|
||||
|
||||
@@ -196,8 +195,6 @@ def export(exportList,filename,colors=None):
|
||||
template = template.replace("$company",FreeCAD.ActiveDocument.Company)
|
||||
template = template.replace("$email",email)
|
||||
template = template.replace("$now",str(int(time.time())))
|
||||
template = template.replace("$projectid",FreeCAD.ActiveDocument.Uid[:22].replace("-","_"))
|
||||
template = template.replace("$project",FreeCAD.ActiveDocument.Name)
|
||||
template = template.replace("$filename",os.path.basename(filename))
|
||||
template = template.replace("$timestamp",str(time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())))
|
||||
if hasattr(ifcopenshell,"version"):
|
||||
@@ -212,12 +209,7 @@ def export(exportList,filename,colors=None):
|
||||
global ifcfile, surfstyles, clones, sharedobjects, profiledefs, shapedefs
|
||||
ifcfile = ifcopenshell.open(templatefile)
|
||||
history = ifcfile.by_type("IfcOwnerHistory")[0]
|
||||
context = ifcfile.by_type("IfcGeometricRepresentationContext")[0]
|
||||
project = ifcfile.by_type("IfcProject")[0]
|
||||
objectslist = Draft.getGroupContents(exportList,walls=True,addgroups=True)
|
||||
if(Draft.getObjectsOfType(objectslist, "Site")): # we assume one site and one representation context only
|
||||
trueNorthX = math.tan(-Draft.getObjectsOfType(objectslist, "Site")[0].Declination.getValueAs(FreeCAD.Units.Radian))
|
||||
context.TrueNorth.DirectionRatios = (trueNorthX, 1., 1.)
|
||||
annotations = []
|
||||
for obj in objectslist:
|
||||
if obj.isDerivedFrom("Part::Part2DObject"):
|
||||
@@ -234,6 +226,16 @@ def export(exportList,filename,colors=None):
|
||||
objectslist = [obj for obj in objectslist if Draft.getType(obj) not in ["Dimension","Material","MaterialContainer","WorkingPlaneProxy"]]
|
||||
if FULL_PARAMETRIC:
|
||||
objectslist = Arch.getAllChildren(objectslist)
|
||||
|
||||
contextCreator = exportIFCHelper.ContextCreator(ifcfile, objectslist)
|
||||
context = contextCreator.model_view_subcontext
|
||||
project = contextCreator.project
|
||||
objectslist = [obj for obj in objectslist if obj != contextCreator.project_object]
|
||||
|
||||
if Draft.getObjectsOfType(objectslist, "Site"): # we assume one site and one representation context only
|
||||
trueNorthX = math.tan(-Draft.getObjectsOfType(objectslist, "Site")[0].Declination.getValueAs(FreeCAD.Units.Radian))
|
||||
contextCreator.model_context.TrueNorth.DirectionRatios = (trueNorthX, 1., 1.)
|
||||
|
||||
products = {} # { Name: IfcEntity, ... }
|
||||
subproducts = {} # { Name: IfcEntity, ... } for storing additions/subtractions and other types of subcomponents of a product
|
||||
surfstyles = {} # { (r,g,b): IfcEntity, ... }
|
||||
@@ -262,6 +264,7 @@ def export(exportList,filename,colors=None):
|
||||
#print(objectslist)
|
||||
|
||||
# testing if more than one site selected (forbidden in IFC)
|
||||
# TODO: Moult: This is not forbidden in IFC.
|
||||
|
||||
if len(Draft.getObjectsOfType(objectslist,"Site")) > 1:
|
||||
FreeCAD.Console.PrintError("More than one site is selected, which is forbidden by IFC standards. Please export only one site by IFC file.\n")
|
||||
@@ -593,7 +596,7 @@ def export(exportList,filename,colors=None):
|
||||
#if DEBUG : print(" adding ifc attributes")
|
||||
props = []
|
||||
for key in obj.IfcData:
|
||||
if not (key in ["attributes","IfcUID","FlagForceBrep"]):
|
||||
if not (key in ["attributes", "complex_attributes", "IfcUID", "FlagForceBrep"]):
|
||||
|
||||
# (deprecated) properties in IfcData dict are stored as "key":"type(value)"
|
||||
|
||||
@@ -872,7 +875,7 @@ def export(exportList,filename,colors=None):
|
||||
|
||||
# sites
|
||||
|
||||
for site in Draft.getObjectsOfType(objectslist,"Site"):
|
||||
for site in exportIFCHelper.getObjectsOfIfcType(objectslist, "Site"):
|
||||
objs = Draft.getGroupContents(site,walls=True,addgroups=True)
|
||||
objs = Arch.pruneIncluded(objs)
|
||||
children = []
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import FreeCAD, Draft, json, ifcopenshell, math
|
||||
|
||||
def getObjectsOfIfcType(objects, ifcType):
|
||||
results = []
|
||||
for object in objects:
|
||||
if hasattr(object,"IfcType"):
|
||||
if object.IfcType == ifcType:
|
||||
results.append(object)
|
||||
return results
|
||||
|
||||
class SIUnitCreator:
|
||||
def __init__(self, file, text, type):
|
||||
self.prefixes = ["EXA", "PETA", "TERA", "GIGA", "MEGA", "KILO", "HECTO",
|
||||
"DECA", "DECI", "CENTI", "MILLI", "MICRO", "NANO", "PICO", "FEMTO",
|
||||
"ATTO"]
|
||||
self.unitNames = ["AMPERE", "BECQUEREL", "CANDELA", "COULOMB",
|
||||
"CUBIC_METRE", "DEGREE CELSIUS", "FARAD", "GRAM", "GRAY", "HENRY",
|
||||
"HERTZ", "JOULE", "KELVIN", "LUMEN", "LUX", "MOLE", "NEWTON", "OHM",
|
||||
"PASCAL", "RADIAN", "SECOND", "SIEMENS", "SIEVERT", "SQUARE METRE",
|
||||
"METRE", "STERADIAN", "TESLA", "VOLT", "WATT", "WEBER"]
|
||||
self.text = text
|
||||
self.SIUnit = file.createIfcSIUnit(None, type, self.getSIPrefix(), self.getSIUnitName())
|
||||
|
||||
def getSIPrefix(self):
|
||||
for prefix in self.prefixes:
|
||||
if prefix in self.text.upper():
|
||||
return prefix
|
||||
return None
|
||||
|
||||
def getSIUnitName(self):
|
||||
for unitName in self.unitNames:
|
||||
if unitName in self.text.upper():
|
||||
return unitName
|
||||
return None
|
||||
|
||||
class ContextCreator:
|
||||
def __init__(self, file, objects):
|
||||
self.file = file
|
||||
self.objects = objects
|
||||
self.project_object = self.getProjectObject()
|
||||
self.project_data = self.getProjectObjectData()
|
||||
self.model_context = self.createGeometricRepresentationContext()
|
||||
self.model_view_subcontext = self.createGeometricRepresentationSubContext()
|
||||
self.target_crs = self.createTargetCRS()
|
||||
self.map_conversion = self.createMapConversion()
|
||||
self.project = self.createProject()
|
||||
|
||||
def createGeometricRepresentationContext(self):
|
||||
return self.file.createIfcGeometricRepresentationContext(
|
||||
None, "Model",
|
||||
3, 1.0E-05,
|
||||
self.file.by_type("IfcAxis2Placement3D")[0],
|
||||
self.createTrueNorth())
|
||||
|
||||
def createGeometricRepresentationSubContext(self):
|
||||
return self.file.createIfcGeometricRepresentationSubContext(
|
||||
"Body", "Model",
|
||||
None, None, None, None,
|
||||
self.model_context, None, "MODEL_VIEW", None)
|
||||
|
||||
def createTargetCRS(self):
|
||||
try:
|
||||
SIUnit = SIUnitCreator(self.file, self.project_data["map_unit"], "LENGTHUNIT")
|
||||
return self.file.createIfcProjectedCRS(
|
||||
self.project_data["name"],
|
||||
self.project_data["description"],
|
||||
self.project_data["geodetic_datum"],
|
||||
self.project_data["vertical_datum"],
|
||||
self.project_data["map_projection"],
|
||||
self.project_data["map_zone"],
|
||||
SIUnit.SIUnit
|
||||
)
|
||||
except:
|
||||
return None
|
||||
|
||||
def createMapConversion(self):
|
||||
try:
|
||||
return self.file.createIfcMapConversion(
|
||||
self.model_context, self.target_crs,
|
||||
float(self.project_data["eastings"]),
|
||||
float(self.project_data["northings"]),
|
||||
float(self.project_data["orthogonal_height"]),
|
||||
self.calculateXAxisAbscissa(),
|
||||
self.calculateXAxisOrdinate(),
|
||||
float(self.project_data["scale"])
|
||||
)
|
||||
except:
|
||||
return None
|
||||
|
||||
def createTrueNorth(self):
|
||||
return self.file.createIfcDirection(
|
||||
(self.calculateXAxisAbscissa(), self.calculateXAxisOrdinate(), 0.))
|
||||
|
||||
def calculateXAxisAbscissa(self):
|
||||
if "true_north" in self.project_data:
|
||||
return math.cos(math.radians(float(self.project_data["true_north"]) + 90))
|
||||
return 0.
|
||||
|
||||
def calculateXAxisOrdinate(self):
|
||||
if "true_north" in self.project_data:
|
||||
return math.sin(math.radians(float(self.project_data["true_north"]) + 90))
|
||||
return 1.
|
||||
|
||||
def createProject(self):
|
||||
if not self.project_object:
|
||||
return self.createAutomaticProject()
|
||||
return self.createCustomProject()
|
||||
|
||||
def createAutomaticProject(self):
|
||||
return self.file.createIfcProject(
|
||||
self.getProjectGUID(),
|
||||
self.file.by_type("IfcOwnerHistory")[0],
|
||||
FreeCAD.ActiveDocument.Name, None,
|
||||
None, None, None, [self.model_context],
|
||||
self.file.by_type("IfcUnitAssignment")[0])
|
||||
|
||||
def createCustomProject(self):
|
||||
return self.file.createIfcProject(
|
||||
self.getProjectGUID(),
|
||||
self.file.by_type("IfcOwnerHistory")[0],
|
||||
self.project_object.Label, self.project_object.Description,
|
||||
self.project_object.ObjectType, self.project_object.LongName,
|
||||
self.project_object.Phase,
|
||||
[self.model_context],
|
||||
self.file.by_type("IfcUnitAssignment")[0])
|
||||
|
||||
def getProjectGUID(self):
|
||||
# TODO: Do not generate a new one each time, but at least this one
|
||||
# conforms to the community consensus on how a GUID is generated.
|
||||
return ifcopenshell.guid.new()
|
||||
|
||||
def getProjectObject(self):
|
||||
try:
|
||||
return getObjectsOfIfcType(self.objects, "Project")[0]
|
||||
except:
|
||||
return None
|
||||
|
||||
def getProjectObjectData(self):
|
||||
if not self.project_object:
|
||||
return {}
|
||||
return json.loads(self.project_object.IfcData['complex_attributes'])["RepresentationContexts"]
|
||||
@@ -38,6 +38,7 @@ import Draft
|
||||
import Arch
|
||||
import DraftVecUtils
|
||||
import ArchIFCSchema
|
||||
import importIFCHelper
|
||||
|
||||
## @package importIFC
|
||||
# \ingroup ARCH
|
||||
@@ -173,7 +174,7 @@ def dms2dd(degrees, minutes, seconds, milliseconds=0):
|
||||
|
||||
# ************************************************************************************************
|
||||
# ********** duplicate methods ****************
|
||||
# TODO red rid of this duplicate
|
||||
# TODO get rid of this duplicate
|
||||
def getPreferences():
|
||||
|
||||
"""retrieves IFC preferences"""
|
||||
@@ -403,6 +404,9 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
import FreeCADGui
|
||||
FreeCADGui.ActiveDocument.activeView().viewAxonometric()
|
||||
|
||||
projectImporter = importIFCHelper.ProjectImporter(ifcfile, objects)
|
||||
projectImporter.execute()
|
||||
|
||||
# handle IFC products
|
||||
|
||||
for product in products:
|
||||
@@ -623,53 +627,55 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
# full Arch objects
|
||||
|
||||
for freecadtype,ifctypes in typesmap.items():
|
||||
if ptype in ifctypes:
|
||||
if clone:
|
||||
obj = getattr(Arch,"make"+freecadtype)(name=name)
|
||||
obj.CloneOf = clone
|
||||
if shape:
|
||||
if shape.Solids:
|
||||
s1 = shape.Solids[0]
|
||||
else:
|
||||
s1 = shape
|
||||
if clone.Shape.Solids:
|
||||
s2 = clone.Shape.Solids[0]
|
||||
else:
|
||||
s1 = clone.Shape
|
||||
if hasattr(s1,"CenterOfMass") and hasattr(s2,"CenterOfMass"):
|
||||
v = s1.CenterOfMass.sub(s2.CenterOfMass)
|
||||
if product.Representation:
|
||||
r = getRotation(product.Representation.Representations[0].Items[0].MappingTarget)
|
||||
if not r.isNull():
|
||||
v = v.add(s2.CenterOfMass)
|
||||
v = v.add(r.multVec(s2.CenterOfMass.negative()))
|
||||
obj.Placement.Rotation = r
|
||||
obj.Placement.move(v)
|
||||
else:
|
||||
print("failed to compute placement ",)
|
||||
else:
|
||||
obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
|
||||
if freecadtype in ["Wall","Structure"] and baseobj and baseobj.isDerivedFrom("Part::Extrusion"):
|
||||
# remove intermediary extrusion for types that can extrude themselves
|
||||
obj.Base = baseobj.Base
|
||||
obj.Placement = obj.Placement.multiply(baseobj.Placement)
|
||||
obj.Height = baseobj.Dir.Length
|
||||
obj.Normal = FreeCAD.Vector(baseobj.Dir).normalize()
|
||||
bn = baseobj.Name
|
||||
FreeCAD.ActiveDocument.removeObject(bn)
|
||||
if (freecadtype in ["Structure","Wall"]) and not baseobj:
|
||||
# remove sizes to prevent auto shape creation for types that don't require a base object
|
||||
obj.Height = 0
|
||||
obj.Width = 0
|
||||
obj.Length = 0
|
||||
if store:
|
||||
sharedobjects[store] = obj
|
||||
|
||||
if ptype == "IfcBuildingStorey":
|
||||
if product.Elevation:
|
||||
obj.Placement.Base.z = product.Elevation * getScaling(ifcfile)
|
||||
if ptype not in ifctypes:
|
||||
continue
|
||||
if clone:
|
||||
obj = getattr(Arch,"make"+freecadtype)(name=name)
|
||||
obj.CloneOf = clone
|
||||
if shape:
|
||||
if shape.Solids:
|
||||
s1 = shape.Solids[0]
|
||||
else:
|
||||
s1 = shape
|
||||
if clone.Shape.Solids:
|
||||
s2 = clone.Shape.Solids[0]
|
||||
else:
|
||||
s1 = clone.Shape
|
||||
if hasattr(s1,"CenterOfMass") and hasattr(s2,"CenterOfMass"):
|
||||
v = s1.CenterOfMass.sub(s2.CenterOfMass)
|
||||
if product.Representation:
|
||||
r = getRotation(product.Representation.Representations[0].Items[0].MappingTarget)
|
||||
if not r.isNull():
|
||||
v = v.add(s2.CenterOfMass)
|
||||
v = v.add(r.multVec(s2.CenterOfMass.negative()))
|
||||
obj.Placement.Rotation = r
|
||||
obj.Placement.move(v)
|
||||
else:
|
||||
print("failed to compute placement ",)
|
||||
else:
|
||||
obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
|
||||
if freecadtype in ["Wall","Structure"] and baseobj and baseobj.isDerivedFrom("Part::Extrusion"):
|
||||
# remove intermediary extrusion for types that can extrude themselves
|
||||
obj.Base = baseobj.Base
|
||||
obj.Placement = obj.Placement.multiply(baseobj.Placement)
|
||||
obj.Height = baseobj.Dir.Length
|
||||
obj.Normal = FreeCAD.Vector(baseobj.Dir).normalize()
|
||||
bn = baseobj.Name
|
||||
FreeCAD.ActiveDocument.removeObject(bn)
|
||||
if (freecadtype in ["Structure","Wall"]) and not baseobj:
|
||||
# remove sizes to prevent auto shape creation for types that don't require a base object
|
||||
obj.Height = 0
|
||||
obj.Width = 0
|
||||
obj.Length = 0
|
||||
if store:
|
||||
sharedobjects[store] = obj
|
||||
|
||||
break
|
||||
if ptype == "IfcBuildingStorey":
|
||||
if product.Elevation:
|
||||
obj.Placement.Base.z = product.Elevation * getScaling(ifcfile)
|
||||
|
||||
break
|
||||
|
||||
if not obj:
|
||||
obj = Arch.makeComponent(baseobj,name=name)
|
||||
@@ -704,6 +710,8 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
# setting IFC attributes
|
||||
|
||||
for attribute in ArchIFCSchema.IfcProducts[product.is_a()]["attributes"]:
|
||||
if attribute["name"] == "Name":
|
||||
continue
|
||||
#print("attribute:",attribute["name"])
|
||||
if hasattr(product, attribute["name"]) and getattr(product, attribute["name"]) and hasattr(obj,attribute["name"]):
|
||||
#print("Setting attribute",attribute["name"],"to",getattr(product, attribute["name"]))
|
||||
@@ -1025,23 +1033,25 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
# additions
|
||||
|
||||
for host,children in additions.items():
|
||||
if host in objects.keys():
|
||||
cobs = []
|
||||
for child in children:
|
||||
if child in objects.keys():
|
||||
if child not in swallowed: # don't add objects already in groups
|
||||
cobs.append(objects[child])
|
||||
if cobs:
|
||||
if DEBUG and first:
|
||||
print("")
|
||||
first = False
|
||||
if DEBUG and (len(cobs) > 10) and (not(Draft.getType(objects[host]) in ["Site","Building","Floor","BuildingPart"])):
|
||||
# avoid huge fusions
|
||||
print("more than 10 shapes to add: skipping.")
|
||||
else:
|
||||
if DEBUG: print(" adding",len(cobs), "object(s) to", objects[host].Label)
|
||||
Arch.addComponents(cobs,objects[host])
|
||||
if DEBUG: FreeCAD.ActiveDocument.recompute()
|
||||
if host not in objects.keys():
|
||||
continue
|
||||
cobs = []
|
||||
for child in children:
|
||||
if child in objects.keys() \
|
||||
and child not in swallowed: # don't add objects already in groups
|
||||
cobs.append(objects[child])
|
||||
if not cobs:
|
||||
continue
|
||||
if DEBUG and first:
|
||||
print("")
|
||||
first = False
|
||||
if DEBUG and (len(cobs) > 10) and (not(Draft.getType(objects[host]) in ["Site","Building","Floor","BuildingPart","Project"])):
|
||||
# avoid huge fusions
|
||||
print("more than 10 shapes to add: skipping.")
|
||||
else:
|
||||
if DEBUG: print(" adding",len(cobs), "object(s) to", objects[host].Label)
|
||||
Arch.addComponents(cobs,objects[host])
|
||||
if DEBUG: FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
if DEBUG and first: print("done.")
|
||||
|
||||
@@ -1051,7 +1061,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
|
||||
for obj in objects.values():
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
if obj.Shape.isNull() and not(Draft.getType(obj) in ["Site"]):
|
||||
if obj.Shape.isNull() and not(Draft.getType(obj) in ["Site","Project"]):
|
||||
Arch.rebuildArchShape(obj)
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
@@ -1195,9 +1205,9 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
||||
if hasattr(objects[o],"Material"):
|
||||
# the reason behind ...
|
||||
# there are files around in which the material color is different from the shape color
|
||||
# all viewers use the shape color wheras in FreeCAD the shape color will be
|
||||
# overwritten by the material coloer (if there is a material with a color)
|
||||
# in such a case FreeCAD shows different color than all common ifc viewers
|
||||
# all viewers use the shape color whereas in FreeCAD the shape color will be
|
||||
# overwritten by the material color (if there is a material with a color).
|
||||
# In such a case FreeCAD shows a different color than all common ifc viewers
|
||||
# https://forum.freecadweb.org/viewtopic.php?f=39&t=38440
|
||||
col = objects[o].ViewObject.ShapeColor[:3]
|
||||
dig = 5
|
||||
@@ -1673,7 +1683,7 @@ class recycler:
|
||||
else:
|
||||
if isinstance(pvalue,float) and pvalue < 0.000000001: # remove the exp notation that some bim apps hate
|
||||
pvalue = 0
|
||||
c = self.ifcfile.createIfcPropertySingleValue(name,None,ifcfile.create_entity(ptype,pvalue),None)
|
||||
c = self.ifcfile.createIfcPropertySingleValue(name,None,self.ifcfile.create_entity(ptype,pvalue),None)
|
||||
if self.compress:
|
||||
self.propertysinglevalues[key] = c
|
||||
return c
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import Arch, ArchIFC, math
|
||||
|
||||
class ProjectImporter:
|
||||
def __init__(self, file, objects):
|
||||
self.file = file
|
||||
self.objects = objects
|
||||
|
||||
def execute(self):
|
||||
self.project = self.file.by_type("IfcProject")[0]
|
||||
self.object = Arch.makeProject()
|
||||
self.objects[self.project.id()] = self.object
|
||||
self.setAttributes()
|
||||
self.setComplexAttributes()
|
||||
|
||||
def setAttributes(self):
|
||||
for property in self.object.PropertiesList:
|
||||
if hasattr(self.project, property) and getattr(self.project, property):
|
||||
setattr(self.object, property, getattr(self.project, property))
|
||||
|
||||
def setComplexAttributes(self):
|
||||
try:
|
||||
mapConversion = self.project.RepresentationContexts[0].HasCoordinateOperation[0]
|
||||
|
||||
data = self.extractTargetCRSData(mapConversion.TargetCRS)
|
||||
data.update(self.extractMapConversionData(mapConversion))
|
||||
ArchIFC.IfcRoot.setObjIfcComplexAttributeValue(self, self.object, "RepresentationContexts", data)
|
||||
except:
|
||||
# This scenario occurs validly in IFC2X3, as the mapConversion does
|
||||
# not exist
|
||||
return
|
||||
|
||||
def extractTargetCRSData(self, targetCRS):
|
||||
mappings = {
|
||||
"name": "Name",
|
||||
"description": "Description",
|
||||
"geodetic_datum": "GeodeticDatum",
|
||||
"vertical_datum": "VerticalDatum",
|
||||
"map_projection": "MapProjection",
|
||||
"map_zone": "MapZone"
|
||||
}
|
||||
data = {}
|
||||
for attributeName, ifcName in mappings.items():
|
||||
data[attributeName] = str(getattr(targetCRS, ifcName))
|
||||
|
||||
if targetCRS.MapUnit.Prefix:
|
||||
data["map_unit"] = targetCRS.MapUnit.Prefix.title() + targetCRS.MapUnit.Name.lower()
|
||||
else:
|
||||
data["map_unit"] = targetCRS.MapUnit.Name.title()
|
||||
|
||||
return data
|
||||
|
||||
def extractMapConversionData(self, mapConversion):
|
||||
mappings = {
|
||||
"eastings": "Eastings",
|
||||
"northings": "Northings",
|
||||
"orthogonal_height": "OrthogonalHeight",
|
||||
"x_axis_abscissa": "XAxisAbscissa",
|
||||
"x_axis_ordinate": "XAxisOrdinate",
|
||||
"scale": "Scale"
|
||||
}
|
||||
data = {}
|
||||
for attributeName, ifcName in mappings.items():
|
||||
data[attributeName] = str(getattr(mapConversion, ifcName))
|
||||
|
||||
data["true_north"] = str(self.calculateTrueNorthAngle(
|
||||
mapConversion.XAxisAbscissa, mapConversion.XAxisOrdinate))
|
||||
return data
|
||||
|
||||
def calculateTrueNorthAngle(self, x, y):
|
||||
return round(math.degrees(math.atan2(y, x)) - 90, 6)
|
||||
@@ -27,16 +27,24 @@ __title__="FreeCAD Draft Edit Tool"
|
||||
__author__ = "Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, Dmitry Chigrin"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD, FreeCADGui, Draft, DraftTools, math
|
||||
import FreeCAD
|
||||
import Draft
|
||||
import math
|
||||
|
||||
from FreeCAD import Vector
|
||||
from DraftTrackers import *
|
||||
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
from DraftTools import translate
|
||||
# Do not import GUI-related modules if GUI is not there
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import DraftTools
|
||||
from DraftTrackers import *
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
from DraftTools import translate
|
||||
|
||||
|
||||
class Edit():
|
||||
|
||||
"The Draft_Edit FreeCAD command definition"
|
||||
|
||||
def __init__(self):
|
||||
@@ -1125,3 +1133,9 @@ class Edit():
|
||||
self.obj.TagPosition = self.invpl.multVec(v)
|
||||
else:
|
||||
self.obj.Group[self.editing-1].Placement.Base = self.invpl.multVec(v)
|
||||
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# setup command
|
||||
FreeCADGui.addCommand('Draft_Edit', Edit())
|
||||
|
||||
@@ -34,10 +34,9 @@ __url__ = ["http://www.freecadweb.org"]
|
||||
# toolbars and task panels, and Qt-dependent utilities such as
|
||||
# a delayed (todo) commit system
|
||||
|
||||
'''
|
||||
This is the GUI part of the Draft module.
|
||||
"""This is the GUI part of the Draft module.
|
||||
Report to Draft.py for info
|
||||
'''
|
||||
"""
|
||||
|
||||
import six
|
||||
|
||||
@@ -128,12 +127,13 @@ inCommandShortcuts = {
|
||||
|
||||
|
||||
class todo:
|
||||
''' static todo class, delays execution of functions. Use todo.delay
|
||||
"""static todo class, delays execution of functions. Use todo.delay
|
||||
to schedule geometry manipulation that would crash coin if done in the
|
||||
event callback'''
|
||||
event callback
|
||||
|
||||
'''List of (function, argument) pairs to be executed by
|
||||
QtCore.QTimer.singleShot(0,doTodo).'''
|
||||
List of (function, argument) pairs to be executed by
|
||||
QtCore.QTimer.singleShot(0,doTodo).
|
||||
"""
|
||||
itinerary = []
|
||||
commitlist = []
|
||||
afteritinerary = []
|
||||
@@ -283,7 +283,7 @@ class DraftBaseWidget(QtGui.QWidget):
|
||||
return QtGui.QWidget.eventFilter(self, widget, event)
|
||||
|
||||
class DraftDockWidget(DraftBaseWidget):
|
||||
"custom Widget that emits a resized() signal when resized"
|
||||
"""custom Widget that emits a resized() signal when resized"""
|
||||
def __init__(self,parent = None):
|
||||
QtGui.QWidget.__init__(self,parent)
|
||||
def resizeEvent(self,event):
|
||||
@@ -295,7 +295,7 @@ class DraftDockWidget(DraftBaseWidget):
|
||||
QtGui.QWidget.changeEvent(self,event)
|
||||
|
||||
class DraftLineEdit(QtGui.QLineEdit):
|
||||
"custom QLineEdit widget that has the power to catch Escape keypress"
|
||||
"""custom QLineEdit widget that has the power to catch Escape keypress"""
|
||||
def __init__(self, parent=None):
|
||||
QtGui.QLineEdit.__init__(self, parent)
|
||||
def keyPressEvent(self, event):
|
||||
@@ -336,7 +336,7 @@ class DraftTaskPanel:
|
||||
return False
|
||||
|
||||
class DraftToolBar:
|
||||
"main draft Toolbar"
|
||||
"""main draft Toolbar"""
|
||||
def __init__(self):
|
||||
self.tray = None
|
||||
self.sourceCmd = None
|
||||
@@ -508,7 +508,7 @@ class DraftToolBar:
|
||||
layout.addWidget(cb)
|
||||
|
||||
def setupToolBar(self,task=False):
|
||||
"sets the draft toolbar up"
|
||||
"""sets the draft toolbar up"""
|
||||
|
||||
# command
|
||||
|
||||
@@ -753,7 +753,7 @@ class DraftToolBar:
|
||||
#QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("returnPressed()"),self.checkSTrack)
|
||||
|
||||
def setupTray(self):
|
||||
"sets draft tray buttons up"
|
||||
"""sets draft tray buttons up"""
|
||||
|
||||
self.wplabel = self._pushbutton("wplabel", self.toptray, icon='Draft_SelectPlane',hide=False,width=120)
|
||||
defaultWP = Draft.getParam("defaultWP",0)
|
||||
@@ -947,7 +947,7 @@ class DraftToolBar:
|
||||
else:
|
||||
# create a dummy task to block the UI during the works
|
||||
class dummy:
|
||||
"an empty dialog"
|
||||
"""an empty dialog"""
|
||||
def __init__(self,extra=None):
|
||||
if extra:
|
||||
if isinstance(extra,list):
|
||||
@@ -972,7 +972,7 @@ class DraftToolBar:
|
||||
self.setTitle(title,icon)
|
||||
|
||||
def redraw(self):
|
||||
"utility function that is performed after each clicked point"
|
||||
"""utility function that is performed after each clicked point"""
|
||||
self.checkLocal()
|
||||
|
||||
def setFocus(self,f=None):
|
||||
@@ -1356,7 +1356,7 @@ class DraftToolBar:
|
||||
self.delButton.setChecked(not(addmode))
|
||||
|
||||
def checkLocal(self):
|
||||
"checks if x,y,z coords must be displayed as local or global"
|
||||
"""checks if x,y,z coords must be displayed as local or global"""
|
||||
self.labelx.setText(translate("draft", "Global X"))
|
||||
self.labely.setText(translate("draft", "Global Y"))
|
||||
self.labelz.setText(translate("draft", "Global Z"))
|
||||
@@ -1408,14 +1408,14 @@ class DraftToolBar:
|
||||
p.SetBool("OffsetCopyMode",bool(val))
|
||||
|
||||
def relocate(self):
|
||||
"relocates the right-aligned buttons depending on the toolbar size"
|
||||
"""relocates the right-aligned buttons depending on the toolbar size"""
|
||||
if self.baseWidget.geometry().width() < 400:
|
||||
self.layout.setDirection(QtGui.QBoxLayout.TopToBottom)
|
||||
else:
|
||||
self.layout.setDirection(QtGui.QBoxLayout.LeftToRight)
|
||||
|
||||
def makeDumbTask(self,extra=None,callback=None):
|
||||
"create a dumb taskdialog to prevent deleting the temp object"
|
||||
"""create a dumb taskdialog to prevent deleting the temp object"""
|
||||
class TaskPanel:
|
||||
def __init__(self,extra=None,callback=None):
|
||||
if extra:
|
||||
@@ -1431,7 +1431,7 @@ class DraftToolBar:
|
||||
FreeCADGui.Control.showDialog(panel)
|
||||
|
||||
def setGridSize(self,text):
|
||||
"sets the Draft grid to the given grid size"
|
||||
"""sets the Draft grid to the given grid size"""
|
||||
try:
|
||||
q = FreeCAD.Units.Quantity(text)
|
||||
except:
|
||||
@@ -1442,7 +1442,7 @@ class DraftToolBar:
|
||||
FreeCADGui.Snapper.setGrid()
|
||||
|
||||
def setMainline(self,val):
|
||||
"sets the grid main lines"
|
||||
"""sets the grid main lines"""
|
||||
if val > 1:
|
||||
Draft.setParam("gridEvery",val)
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
@@ -1456,7 +1456,7 @@ class DraftToolBar:
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def getcol(self):
|
||||
"opens a color picker dialog"
|
||||
"""opens a color picker dialog"""
|
||||
oldColor = self.color
|
||||
self.color=QtGui.QColorDialog.getColor()
|
||||
if not QtGui.QColor.isValid(self.color): #user canceled
|
||||
@@ -1480,7 +1480,7 @@ class DraftToolBar:
|
||||
i.ViewObject.PointColor = col
|
||||
|
||||
def getfacecol(self):
|
||||
"opens a color picker dialog"
|
||||
"""opens a color picker dialog"""
|
||||
oldColor = self.facecolor
|
||||
self.facecolor=QtGui.QColorDialog.getColor()
|
||||
if not QtGui.QColor.isValid(self.facecolor): #user canceled
|
||||
@@ -1546,7 +1546,7 @@ class DraftToolBar:
|
||||
self.updateSnapper()
|
||||
|
||||
def validatePoint(self):
|
||||
"function for checking and sending numbers entered manually"
|
||||
"""function for checking and sending numbers entered manually"""
|
||||
if self.sourceCmd or self.pointcallback:
|
||||
if (self.labelRadius.isVisible()):
|
||||
try:
|
||||
@@ -1673,7 +1673,7 @@ class DraftToolBar:
|
||||
|
||||
|
||||
def finish(self):
|
||||
"finish button action"
|
||||
"""finish button action"""
|
||||
if self.sourceCmd:
|
||||
self.sourceCmd.finish(False)
|
||||
if self.cancel:
|
||||
@@ -1683,27 +1683,27 @@ class DraftToolBar:
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def escape(self):
|
||||
"escapes the current command"
|
||||
"""escapes the current command"""
|
||||
self.continueMode = False
|
||||
if not self.taskmode:
|
||||
self.continueCmd.setChecked(False)
|
||||
self.finish()
|
||||
|
||||
def closeLine(self):
|
||||
"close button action"
|
||||
"""close button action"""
|
||||
self.sourceCmd.finish(True)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def wipeLine(self):
|
||||
"wipes existing segments of a line"
|
||||
"""wipes existing segments of a line"""
|
||||
self.sourceCmd.wipe()
|
||||
|
||||
def orientWP(self):
|
||||
"reorients the current working plane"
|
||||
"""reorients the current working plane"""
|
||||
self.sourceCmd.orientWP()
|
||||
|
||||
def selectEdge(self):
|
||||
"allows the dimension command to select an edge"
|
||||
"""allows the dimension command to select an edge"""
|
||||
if hasattr(self.sourceCmd,"selectEdge"):
|
||||
self.sourceCmd.selectEdge()
|
||||
|
||||
@@ -1726,15 +1726,14 @@ class DraftToolBar:
|
||||
self.sourceCmd.selectHandler("alignToWP")
|
||||
|
||||
def undoSegment(self):
|
||||
"undo last line segment"
|
||||
"""undo last line segment"""
|
||||
if hasattr(self.sourceCmd,"undolast"):
|
||||
self.sourceCmd.undolast()
|
||||
|
||||
def checkSpecialChars(self,txt):
|
||||
'''
|
||||
checks for special characters in the entered coords that must be
|
||||
"""checks for special characters in the entered coords that must be
|
||||
treated as shortcuts
|
||||
'''
|
||||
"""
|
||||
|
||||
# in-command shortcut definitions
|
||||
#Relative
|
||||
@@ -1840,7 +1839,7 @@ class DraftToolBar:
|
||||
self.updateSnapper()
|
||||
|
||||
def updateSnapper(self):
|
||||
"updates the snapper track line if applicable"
|
||||
"""updates the snapper track line if applicable"""
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
if FreeCADGui.Snapper.trackLine:
|
||||
if FreeCADGui.Snapper.trackLine.Visible:
|
||||
@@ -1863,10 +1862,9 @@ class DraftToolBar:
|
||||
self.textValue.setText(tstr)
|
||||
|
||||
def sendText(self):
|
||||
'''
|
||||
this function sends the entered text to the active draft command
|
||||
"""this function sends the entered text to the active draft command
|
||||
if enter has been pressed twice. Otherwise it blanks the line.
|
||||
'''
|
||||
"""
|
||||
if self.textline == len(self.textbuffer):
|
||||
if self.textline:
|
||||
if not self.currEditText:
|
||||
@@ -1884,7 +1882,7 @@ class DraftToolBar:
|
||||
self.setCurrentText('')
|
||||
|
||||
def lineUp(self):
|
||||
"displays previous line in text editor"
|
||||
"""displays previous line in text editor"""
|
||||
if self.textline:
|
||||
if self.textline == len(self.textbuffer):
|
||||
self.textbuffer.append(self.textValue.text())
|
||||
@@ -1897,7 +1895,7 @@ class DraftToolBar:
|
||||
self.textValue.setText(self.textbuffer[self.textline])
|
||||
|
||||
def displayPoint(self, point=None, last=None, plane=None, mask=None):
|
||||
"this function displays the passed coords in the x, y, and z widgets"
|
||||
"""this function displays the passed coords in the x, y, and z widgets"""
|
||||
|
||||
if self.taskmode and (not self.isTaskOn):
|
||||
return
|
||||
@@ -1966,7 +1964,7 @@ class DraftToolBar:
|
||||
|
||||
|
||||
def getDefaultColor(self,type,rgb=False):
|
||||
"gets color from the preferences or toolbar"
|
||||
"""gets color from the preferences or toolbar"""
|
||||
r = 0
|
||||
g = 0
|
||||
b = 0
|
||||
@@ -1997,7 +1995,7 @@ class DraftToolBar:
|
||||
return (r,g,b)
|
||||
|
||||
def cross(self,on=True):
|
||||
"deprecated"
|
||||
"""deprecated"""
|
||||
pass
|
||||
|
||||
def toggleConstrMode(self,checked):
|
||||
@@ -2045,7 +2043,7 @@ class DraftToolBar:
|
||||
FreeCADGui.runCommand("Draft_SelectPlane")
|
||||
|
||||
def popupMenu(self,llist,ilist=None,pos=None):
|
||||
"pops up a menu filled with the given list"
|
||||
"""pops up a menu filled with the given list"""
|
||||
self.groupmenu = QtGui.QMenu()
|
||||
for i,l in enumerate(llist):
|
||||
if ilist:
|
||||
@@ -2363,7 +2361,7 @@ class FacebinderTaskPanel:
|
||||
return int(QtGui.QDialogButtonBox.Ok)
|
||||
|
||||
def update(self):
|
||||
'fills the treewidget'
|
||||
"""fills the treewidget"""
|
||||
self.tree.clear()
|
||||
if self.obj:
|
||||
for f in self.obj.Faces:
|
||||
@@ -2439,8 +2437,7 @@ class FacebinderTaskPanel:
|
||||
|
||||
|
||||
class ScaleTaskPanel:
|
||||
|
||||
'''A Task Panel for the Scale tool'''
|
||||
"""A Task Panel for the Scale tool"""
|
||||
|
||||
def __init__(self):
|
||||
self.sourceCmd = None
|
||||
@@ -2628,7 +2625,7 @@ class ShapeStringTaskPanel:
|
||||
self.setPoint(origin)
|
||||
|
||||
def action(self,arg):
|
||||
"scene event handler"
|
||||
"""scene event handler"""
|
||||
import DraftTools
|
||||
if arg["Type"] == "SoKeyboardEvent":
|
||||
if arg["Key"] == "ESCAPE":
|
||||
@@ -2648,7 +2645,7 @@ class ShapeStringTaskPanel:
|
||||
self.task.sbZ.setProperty('rawValue',point.z)
|
||||
|
||||
def createObject(self):
|
||||
"creates object in the current doc"
|
||||
"""creates object in the current doc"""
|
||||
dquote = '"'
|
||||
if sys.version_info.major < 3: # Python3: no more unicode
|
||||
String = 'u' + dquote + str(self.task.leString.text().encode('unicode_escape')) + dquote
|
||||
|
||||
@@ -31,14 +31,13 @@ def translate(ctx,txt):
|
||||
def QT_TRANSLATE_NOOP(ctx,txt):
|
||||
return txt
|
||||
|
||||
"This module contains everything related to Draft Layers"
|
||||
"""This module contains everything related to Draft Layers"""
|
||||
|
||||
|
||||
def makeLayer(name=None,linecolor=None,drawstyle=None,shapecolor=None,transparency=None):
|
||||
|
||||
'''makeLayer([name,linecolor,drawstyle,shapecolor,transparency]):
|
||||
creates a Layer object in the active document'''
|
||||
|
||||
"""makeLayer([name,linecolor,drawstyle,shapecolor,transparency]):
|
||||
creates a Layer object in the active document
|
||||
"""
|
||||
if not FreeCAD.ActiveDocument:
|
||||
FreeCAD.Console.PrintError(translate("draft","No active document. Aborting")+"\n")
|
||||
return
|
||||
@@ -63,9 +62,7 @@ def makeLayer(name=None,linecolor=None,drawstyle=None,shapecolor=None,transparen
|
||||
|
||||
|
||||
def getLayerContainer():
|
||||
|
||||
'''getLayerContainer(): returns a group object to put layers in'''
|
||||
|
||||
"""getLayerContainer(): returns a group object to put layers in"""
|
||||
for obj in FreeCAD.ActiveDocument.Objects:
|
||||
if obj.Name == "LayerContainer":
|
||||
return obj
|
||||
@@ -78,17 +75,14 @@ def getLayerContainer():
|
||||
|
||||
|
||||
class CommandLayer():
|
||||
|
||||
"The Draft_Layer FreeCAD command"
|
||||
"""The Draft_Layer FreeCAD command"""
|
||||
|
||||
def GetResources(self):
|
||||
|
||||
return {'Pixmap' : 'Draft_VisGroup',
|
||||
'MenuText': QT_TRANSLATE_NOOP("Draft_Layer", "Layer"),
|
||||
'ToolTip' : QT_TRANSLATE_NOOP("Draft_Layer", "Adds a layer")}
|
||||
|
||||
def Activated(self):
|
||||
|
||||
import FreeCADGui
|
||||
FreeCAD.ActiveDocument.openTransaction("Create Layer")
|
||||
FreeCADGui.addModule("Draft")
|
||||
@@ -99,31 +93,25 @@ class CommandLayer():
|
||||
|
||||
|
||||
class Layer:
|
||||
|
||||
"The Draft Layer object"
|
||||
"""The Draft Layer object"""
|
||||
|
||||
def __init__(self,obj):
|
||||
|
||||
self.Type = "Layer"
|
||||
obj.Proxy = self
|
||||
self.Object = obj
|
||||
self.setProperties(obj)
|
||||
|
||||
def onDocumentRestored(self,obj):
|
||||
|
||||
self.setProperties(obj)
|
||||
|
||||
def setProperties(self,obj):
|
||||
|
||||
if not "Group" in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyLinkList","Group","Layer",QT_TRANSLATE_NOOP("App::Property","The objects that are part of this layer"))
|
||||
|
||||
def __getstate__(self):
|
||||
|
||||
return self.Type
|
||||
|
||||
def __setstate__(self,state):
|
||||
|
||||
if state:
|
||||
self.Type = state
|
||||
|
||||
@@ -131,7 +119,6 @@ class Layer:
|
||||
pass
|
||||
|
||||
def addObject(self,obj,child):
|
||||
|
||||
g = obj.Group
|
||||
if not child in g:
|
||||
g.append(child)
|
||||
@@ -139,11 +126,9 @@ class Layer:
|
||||
|
||||
|
||||
class ViewProviderLayer:
|
||||
|
||||
"A View Provider for the Layer object"
|
||||
"""A View Provider for the Layer object"""
|
||||
|
||||
def __init__(self,vobj):
|
||||
|
||||
vobj.addProperty("App::PropertyBool","OverrideChildren","Layer",QT_TRANSLATE_NOOP("App::Property","If on, the child objects of this layer will match its visual aspects"))
|
||||
vobj.addProperty("App::PropertyColor","LineColor","Layer",QT_TRANSLATE_NOOP("App::Property","The line color of the children of this layer"))
|
||||
vobj.addProperty("App::PropertyColor","ShapeColor","Layer",QT_TRANSLATE_NOOP("App::Property","The shape color of the children of this layer"))
|
||||
@@ -164,14 +149,12 @@ class ViewProviderLayer:
|
||||
vobj.Proxy = self
|
||||
|
||||
def getIcon(self):
|
||||
|
||||
if hasattr(self,"icondata"):
|
||||
return self.icondata
|
||||
import Draft_rc
|
||||
return ":/icons/Draft_VisGroup.svg"
|
||||
|
||||
def attach(self,vobj):
|
||||
|
||||
self.Object = vobj.Object
|
||||
from pivy import coin
|
||||
sep = coin.SoGroup()
|
||||
@@ -179,37 +162,29 @@ class ViewProviderLayer:
|
||||
return
|
||||
|
||||
def claimChildren(self):
|
||||
|
||||
if hasattr(self,"Object") and hasattr(self.Object,"Group"):
|
||||
return self.Object.Group
|
||||
|
||||
def getDisplayModes(self, vobj):
|
||||
|
||||
return ["Default"]
|
||||
|
||||
def getDefaultDisplayMode(self):
|
||||
|
||||
return "Default"
|
||||
|
||||
def setDisplayMode(self, mode):
|
||||
|
||||
return mode
|
||||
|
||||
def __getstate__(self):
|
||||
|
||||
return None
|
||||
|
||||
def __setstate__(self,state):
|
||||
|
||||
return None
|
||||
|
||||
def updateData(self,obj,prop):
|
||||
|
||||
if prop == "Group":
|
||||
self.onChanged(obj.ViewObject,"LineColor")
|
||||
|
||||
def onChanged(self,vobj,prop):
|
||||
|
||||
if hasattr(vobj,"OverrideChildren") and vobj.OverrideChildren:
|
||||
if hasattr(vobj,"Object")and hasattr(vobj.Object,"Group"):
|
||||
for o in vobj.Object.Group:
|
||||
@@ -249,15 +224,12 @@ class ViewProviderLayer:
|
||||
self.icondata = ba.data().decode("latin1")
|
||||
|
||||
def canDragObject(self,obj):
|
||||
|
||||
return True
|
||||
|
||||
def canDragObjects(self):
|
||||
|
||||
return True
|
||||
|
||||
def dragObject(self,vobj,otherobj):
|
||||
|
||||
if hasattr(vobj.Object,"Group"):
|
||||
if otherobj in vobj.Object.Group:
|
||||
g = vobj.Object.Group
|
||||
@@ -309,8 +281,7 @@ class ViewProviderLayer:
|
||||
|
||||
|
||||
class LayerContainer:
|
||||
|
||||
"The Layer Container"
|
||||
"""The Layer Container"""
|
||||
|
||||
def __init__(self,obj):
|
||||
|
||||
@@ -335,8 +306,7 @@ class LayerContainer:
|
||||
|
||||
|
||||
class ViewProviderLayerContainer:
|
||||
|
||||
"A View Provider for the Layer Container"
|
||||
"""A View Provider for the Layer Container"""
|
||||
|
||||
def __init__(self,vobj):
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ from pivy import coin
|
||||
|
||||
|
||||
class Tracker:
|
||||
"A generic Draft Tracker, to be used by other specific trackers"
|
||||
"""A generic Draft Tracker, to be used by other specific trackers"""
|
||||
def __init__(self,dotted=False,scolor=None,swidth=None,children=[],ontop=False,name=None):
|
||||
global Part, DraftGeomUtils
|
||||
import Part, DraftGeomUtils
|
||||
@@ -111,7 +111,7 @@ class Tracker:
|
||||
sg.insertChild(self.switch,0)
|
||||
|
||||
class snapTracker(Tracker):
|
||||
"A Snap Mark tracker, used by tools that support snapping"
|
||||
"""A Snap Mark tracker, used by tools that support snapping"""
|
||||
def __init__(self):
|
||||
color = coin.SoBaseColor()
|
||||
color.rgb = FreeCADGui.draftToolBar.getDefaultColor("snap")
|
||||
@@ -141,7 +141,7 @@ class snapTracker(Tracker):
|
||||
|
||||
|
||||
class lineTracker(Tracker):
|
||||
"A Line tracker, used by the tools that need to draw temporary lines"
|
||||
"""A Line tracker, used by the tools that need to draw temporary lines"""
|
||||
def __init__(self,dotted=False,scolor=None,swidth=None,ontop=False):
|
||||
line = coin.SoLineSet()
|
||||
line.numVertices.setValue(2)
|
||||
@@ -150,7 +150,7 @@ class lineTracker(Tracker):
|
||||
Tracker.__init__(self,dotted,scolor,swidth,[self.coords,line],ontop,name="lineTracker")
|
||||
|
||||
def p1(self,point=None):
|
||||
"sets or gets the first point of the line"
|
||||
"""sets or gets the first point of the line"""
|
||||
if point:
|
||||
if self.coords.point.getValues()[0].getValue() != tuple(point):
|
||||
self.coords.point.set1Value(0,point.x,point.y,point.z)
|
||||
@@ -158,7 +158,7 @@ class lineTracker(Tracker):
|
||||
return Vector(self.coords.point.getValues()[0].getValue())
|
||||
|
||||
def p2(self,point=None):
|
||||
"sets or gets the second point of the line"
|
||||
"""sets or gets the second point of the line"""
|
||||
if point:
|
||||
if self.coords.point.getValues()[-1].getValue() != tuple(point):
|
||||
self.coords.point.set1Value(1,point.x,point.y,point.z)
|
||||
@@ -166,13 +166,13 @@ class lineTracker(Tracker):
|
||||
return Vector(self.coords.point.getValues()[-1].getValue())
|
||||
|
||||
def getLength(self):
|
||||
"returns the length of the line"
|
||||
"""returns the length of the line"""
|
||||
p1 = Vector(self.coords.point.getValues()[0].getValue())
|
||||
p2 = Vector(self.coords.point.getValues()[-1].getValue())
|
||||
return (p2.sub(p1)).Length
|
||||
|
||||
class rectangleTracker(Tracker):
|
||||
"A Rectangle tracker, used by the rectangle tool"
|
||||
"""A Rectangle tracker, used by the rectangle tool"""
|
||||
def __init__(self,dotted=False,scolor=None,swidth=None,face=False):
|
||||
self.origin = Vector(0,0,0)
|
||||
line = coin.SoLineSet()
|
||||
@@ -192,13 +192,13 @@ class rectangleTracker(Tracker):
|
||||
self.v = FreeCAD.DraftWorkingPlane.v
|
||||
|
||||
def setorigin(self,point):
|
||||
"sets the base point of the rectangle"
|
||||
"""sets the base point of the rectangle"""
|
||||
self.coords.point.set1Value(0,point.x,point.y,point.z)
|
||||
self.coords.point.set1Value(4,point.x,point.y,point.z)
|
||||
self.origin = point
|
||||
|
||||
def update(self,point):
|
||||
"sets the opposite (diagonal) point of the rectangle"
|
||||
"""sets the opposite (diagonal) point of the rectangle"""
|
||||
diagonal = point.sub(self.origin)
|
||||
inpoint1 = self.origin.add(DraftVecUtils.project(diagonal,self.v))
|
||||
inpoint2 = self.origin.add(DraftVecUtils.project(diagonal,self.u))
|
||||
@@ -217,40 +217,40 @@ class rectangleTracker(Tracker):
|
||||
self.v = self.u.cross(norm)
|
||||
|
||||
def p1(self,point=None):
|
||||
"sets or gets the base point of the rectangle"
|
||||
"""sets or gets the base point of the rectangle"""
|
||||
if point:
|
||||
self.setorigin(point)
|
||||
else:
|
||||
return Vector(self.coords.point.getValues()[0].getValue())
|
||||
|
||||
def p2(self):
|
||||
"gets the second point (on u axis) of the rectangle"
|
||||
"""gets the second point (on u axis) of the rectangle"""
|
||||
return Vector(self.coords.point.getValues()[3].getValue())
|
||||
|
||||
def p3(self,point=None):
|
||||
"sets or gets the opposite (diagonal) point of the rectangle"
|
||||
"""sets or gets the opposite (diagonal) point of the rectangle"""
|
||||
if point:
|
||||
self.update(point)
|
||||
else:
|
||||
return Vector(self.coords.point.getValues()[2].getValue())
|
||||
|
||||
def p4(self):
|
||||
"gets the fourth point (on v axis) of the rectangle"
|
||||
"""gets the fourth point (on v axis) of the rectangle"""
|
||||
return Vector(self.coords.point.getValues()[1].getValue())
|
||||
|
||||
def getSize(self):
|
||||
"returns (length,width) of the rectangle"
|
||||
"""returns (length,width) of the rectangle"""
|
||||
p1 = Vector(self.coords.point.getValues()[0].getValue())
|
||||
p2 = Vector(self.coords.point.getValues()[2].getValue())
|
||||
diag = p2.sub(p1)
|
||||
return ((DraftVecUtils.project(diag,self.u)).Length,(DraftVecUtils.project(diag,self.v)).Length)
|
||||
|
||||
def getNormal(self):
|
||||
"returns the normal of the rectangle"
|
||||
"""returns the normal of the rectangle"""
|
||||
return (self.u.cross(self.v)).normalize()
|
||||
|
||||
def isInside(self,point):
|
||||
"returns True if the given point is inside the rectangle"
|
||||
"""returns True if the given point is inside the rectangle"""
|
||||
vp = point.sub(self.p1())
|
||||
uv = self.p2().sub(self.p1())
|
||||
vv = self.p4().sub(self.p1())
|
||||
@@ -264,7 +264,7 @@ class rectangleTracker(Tracker):
|
||||
return False
|
||||
|
||||
class dimTracker(Tracker):
|
||||
"A Dimension tracker, used by the dimension tool"
|
||||
"""A Dimension tracker, used by the dimension tool"""
|
||||
def __init__(self,dotted=False,scolor=None,swidth=None):
|
||||
line = coin.SoLineSet()
|
||||
line.numVertices.setValue(4)
|
||||
@@ -308,7 +308,7 @@ class dimTracker(Tracker):
|
||||
self.coords.point.setValues(0,4,points)
|
||||
|
||||
class bsplineTracker(Tracker):
|
||||
"A bspline tracker"
|
||||
"""A bspline tracker"""
|
||||
def __init__(self,dotted=False,scolor=None,swidth=None,points = []):
|
||||
self.bspline = None
|
||||
self.points = points
|
||||
@@ -375,7 +375,7 @@ class bsplineTracker(Tracker):
|
||||
FreeCAD.Console.PrintWarning("bsplineTracker.recompute() failed to read-in Inventor string\n")
|
||||
#######################################
|
||||
class bezcurveTracker(Tracker):
|
||||
"A bezcurve tracker"
|
||||
"""A bezcurve tracker"""
|
||||
def __init__(self,dotted=False,scolor=None,swidth=None,points = []):
|
||||
self.bezcurve = None
|
||||
self.points = points
|
||||
@@ -459,7 +459,7 @@ class bezcurveTracker(Tracker):
|
||||
|
||||
#######################################
|
||||
class arcTracker(Tracker):
|
||||
"An arc tracker"
|
||||
"""An arc tracker"""
|
||||
def __init__(self,dotted=False,scolor=None,swidth=None,start=0,end=math.pi*2,normal=None):
|
||||
self.circle = None
|
||||
self.startangle = math.degrees(start)
|
||||
@@ -477,35 +477,35 @@ class arcTracker(Tracker):
|
||||
Tracker.__init__(self,dotted,scolor,swidth,[self.trans, self.sep],name="arcTracker")
|
||||
|
||||
def getDeviation(self):
|
||||
"returns a deviation vector that represents the base of the circle"
|
||||
"""returns a deviation vector that represents the base of the circle"""
|
||||
import Part
|
||||
c = Part.makeCircle(1,Vector(0,0,0),self.normal)
|
||||
return c.Vertexes[0].Point
|
||||
|
||||
def setCenter(self,cen):
|
||||
"sets the center point"
|
||||
"""sets the center point"""
|
||||
self.trans.translation.setValue([cen.x,cen.y,cen.z])
|
||||
|
||||
def setRadius(self,rad):
|
||||
"sets the radius"
|
||||
"""sets the radius"""
|
||||
self.trans.scaleFactor.setValue([rad,rad,rad])
|
||||
|
||||
def getRadius(self):
|
||||
"returns the current radius"
|
||||
"""returns the current radius"""
|
||||
return self.trans.scaleFactor.getValue()[0]
|
||||
|
||||
def setStartAngle(self,ang):
|
||||
"sets the start angle"
|
||||
"""sets the start angle"""
|
||||
self.startangle = math.degrees(ang)
|
||||
self.recompute()
|
||||
|
||||
def setEndAngle(self,ang):
|
||||
"sets the end angle"
|
||||
"""sets the end angle"""
|
||||
self.endangle = math.degrees(ang)
|
||||
self.recompute()
|
||||
|
||||
def getAngle(self,pt):
|
||||
"returns the angle of a given vector in radians"
|
||||
"""returns the angle of a given vector in radians"""
|
||||
c = self.trans.translation.getValue()
|
||||
center = Vector(c[0],c[1],c[2])
|
||||
rad = pt.sub(center)
|
||||
@@ -514,25 +514,25 @@ class arcTracker(Tracker):
|
||||
return(a)
|
||||
|
||||
def getAngles(self):
|
||||
"returns the start and end angles in degrees"
|
||||
"""returns the start and end angles in degrees"""
|
||||
return(self.startangle,self.endangle)
|
||||
|
||||
def setStartPoint(self,pt):
|
||||
"sets the start angle from a point"
|
||||
"""sets the start angle from a point"""
|
||||
self.setStartAngle(-self.getAngle(pt))
|
||||
|
||||
def setEndPoint(self,pt):
|
||||
"sets the end angle from a point"
|
||||
"""sets the end angle from a point"""
|
||||
self.setEndAngle(-self.getAngle(pt))
|
||||
|
||||
def setApertureAngle(self,ang):
|
||||
"sets the end angle by giving the aperture angle"
|
||||
"""sets the end angle by giving the aperture angle"""
|
||||
ap = math.degrees(ang)
|
||||
self.endangle = self.startangle + ap
|
||||
self.recompute()
|
||||
|
||||
def setBy3Points(self,p1,p2,p3):
|
||||
"sets the arc by three points"
|
||||
"""sets the arc by three points"""
|
||||
import Part
|
||||
try:
|
||||
arc=Part.ArcOfCircle(p1,p2,p3)
|
||||
@@ -619,7 +619,7 @@ class ghostTracker(Tracker):
|
||||
Tracker.__init__(self,dotted,scolor,swidth,children=self.children,name="ghostTracker")
|
||||
|
||||
def update(self,obj):
|
||||
"recreates the ghost from a new object"
|
||||
"""recreates the ghost from a new object"""
|
||||
obj.ViewObject.show()
|
||||
self.finalize()
|
||||
sep = self.getNode(obj)
|
||||
@@ -628,23 +628,23 @@ class ghostTracker(Tracker):
|
||||
obj.ViewObject.hide()
|
||||
|
||||
def move(self,delta):
|
||||
"moves the ghost to a given position, relative from its start position"
|
||||
"""moves the ghost to a given position, relative from its start position"""
|
||||
self.trans.translation.setValue([delta.x,delta.y,delta.z])
|
||||
|
||||
def rotate(self,axis,angle):
|
||||
"rotates the ghost of a given angle"
|
||||
"""rotates the ghost of a given angle"""
|
||||
self.trans.rotation.setValue(coin.SbVec3f(DraftVecUtils.tup(axis)),angle)
|
||||
|
||||
def center(self,point):
|
||||
"sets the rotation/scale center of the ghost"
|
||||
"""sets the rotation/scale center of the ghost"""
|
||||
self.trans.center.setValue(point.x,point.y,point.z)
|
||||
|
||||
def scale(self,delta):
|
||||
"scales the ghost by the given factor"
|
||||
"""scales the ghost by the given factor"""
|
||||
self.trans.scaleFactor.setValue([delta.x,delta.y,delta.z])
|
||||
|
||||
def getNode(self,obj):
|
||||
"returns a coin node representing the given object"
|
||||
"""returns a coin node representing the given object"""
|
||||
import Part
|
||||
if isinstance(obj,Part.Shape):
|
||||
return self.getNodeLight(obj)
|
||||
@@ -654,7 +654,7 @@ class ghostTracker(Tracker):
|
||||
return self.getNodeFull(obj)
|
||||
|
||||
def getNodeFull(self,obj):
|
||||
"gets a coin node which is a full copy of the current representation"
|
||||
"""gets a coin node which is a full copy of the current representation"""
|
||||
sep = coin.SoSeparator()
|
||||
try:
|
||||
sep.addChild(obj.ViewObject.RootNode.copy())
|
||||
@@ -671,7 +671,7 @@ class ghostTracker(Tracker):
|
||||
return sep
|
||||
|
||||
def getNodeLight(self,shape):
|
||||
"extract a lighter version directly from a shape"
|
||||
"""extract a lighter version directly from a shape"""
|
||||
# error-prone
|
||||
sep = coin.SoSeparator()
|
||||
try:
|
||||
@@ -706,7 +706,7 @@ class ghostTracker(Tracker):
|
||||
self.trans.setMatrix(m)
|
||||
|
||||
class editTracker(Tracker):
|
||||
"A node edit tracker"
|
||||
"""A node edit tracker"""
|
||||
def __init__(self,pos=Vector(0,0,0),name=None,idx=0,objcol=None,\
|
||||
marker=FreeCADGui.getMarkerIndex("quad", 9),inactive=False):
|
||||
color = coin.SoBaseColor()
|
||||
@@ -746,7 +746,7 @@ class editTracker(Tracker):
|
||||
self.set(self.get().add(delta))
|
||||
|
||||
class PlaneTracker(Tracker):
|
||||
"A working plane tracker"
|
||||
"""A working plane tracker"""
|
||||
def __init__(self):
|
||||
# getting screen distance
|
||||
p1 = Draft.get3DView().getPoint((100,100))
|
||||
@@ -794,7 +794,7 @@ class PlaneTracker(Tracker):
|
||||
self.on()
|
||||
|
||||
class wireTracker(Tracker):
|
||||
"A wire tracker"
|
||||
"""A wire tracker"""
|
||||
def __init__(self,wire):
|
||||
self.line = coin.SoLineSet()
|
||||
self.closed = DraftGeomUtils.isReallyClosed(wire)
|
||||
@@ -827,7 +827,7 @@ class wireTracker(Tracker):
|
||||
self.coords.point.set1Value(i,[p.x,p.y,p.z])
|
||||
|
||||
class gridTracker(Tracker):
|
||||
"A grid tracker"
|
||||
"""A grid tracker"""
|
||||
def __init__(self):
|
||||
col = self.getGridColor()
|
||||
pick = coin.SoPickStyle()
|
||||
@@ -873,7 +873,7 @@ class gridTracker(Tracker):
|
||||
return [r, g, b]
|
||||
|
||||
def update(self):
|
||||
"redraws the grid"
|
||||
"""redraws the grid"""
|
||||
# resize the grid to make sure it fits an exact pair number of main lines
|
||||
numlines = self.numlines//self.mainlines//2*2*self.mainlines
|
||||
bound = (numlines//2)*self.space
|
||||
@@ -927,14 +927,14 @@ class gridTracker(Tracker):
|
||||
self.update()
|
||||
|
||||
def reset(self):
|
||||
"resets the grid according to preferences settings"
|
||||
"""resets the grid according to preferences settings"""
|
||||
self.space = Draft.getParam("gridSpacing",1)
|
||||
self.mainlines = Draft.getParam("gridEvery",10)
|
||||
self.numlines = Draft.getParam("gridSize",100)
|
||||
self.update()
|
||||
|
||||
def set(self):
|
||||
"moves and rotates the grid according to the current WP"
|
||||
"""moves and rotates the grid according to the current WP"""
|
||||
self.reset()
|
||||
Q = FreeCAD.DraftWorkingPlane.getRotation().Rotation.Q
|
||||
P = FreeCAD.DraftWorkingPlane.position
|
||||
@@ -943,7 +943,7 @@ class gridTracker(Tracker):
|
||||
self.on()
|
||||
|
||||
def getClosestNode(self,point):
|
||||
"returns the closest node from the given point"
|
||||
"""returns the closest node from the given point"""
|
||||
# get the 2D coords.
|
||||
# point = FreeCAD.DraftWorkingPlane.projectPoint(point)
|
||||
pt = FreeCAD.DraftWorkingPlane.getLocalCoords(point)
|
||||
@@ -953,7 +953,7 @@ class gridTracker(Tracker):
|
||||
return pt
|
||||
|
||||
class boxTracker(Tracker):
|
||||
"A box tracker, can be based on a line object"
|
||||
"""A box tracker, can be based on a line object"""
|
||||
def __init__(self,line=None,width=0.1,height=1,shaded=False):
|
||||
self.trans = coin.SoTransform()
|
||||
m = coin.SoMaterial()
|
||||
@@ -1024,7 +1024,7 @@ class boxTracker(Tracker):
|
||||
return self.cube.depth.getValue()
|
||||
|
||||
class radiusTracker(Tracker):
|
||||
"A tracker that displays a transparent sphere to inicate a radius"
|
||||
"""A tracker that displays a transparent sphere to inicate a radius"""
|
||||
def __init__(self,position=FreeCAD.Vector(0,0,0),radius=1):
|
||||
self.trans = coin.SoTransform()
|
||||
self.trans.translation.setValue([position.x,position.y,position.z])
|
||||
@@ -1048,7 +1048,7 @@ class radiusTracker(Tracker):
|
||||
self.sphere.radius.setValue(arg2)
|
||||
|
||||
class archDimTracker(Tracker):
|
||||
"A wrapper around a Sketcher dim"
|
||||
"""A wrapper around a Sketcher dim"""
|
||||
def __init__(self,p1=FreeCAD.Vector(0,0,0),p2=FreeCAD.Vector(1,0,0),mode=1):
|
||||
import SketcherGui
|
||||
self.dimnode = coin.SoType.fromName("SoDatumLabel").createInstance()
|
||||
@@ -1063,7 +1063,7 @@ class archDimTracker(Tracker):
|
||||
Tracker.__init__(self,children=[self.dimnode],name="archDimTracker")
|
||||
|
||||
def setString(self,text=None):
|
||||
"sets the dim string to the given value or auto value"
|
||||
"""sets the dim string to the given value or auto value"""
|
||||
self.dimnode.param1.setValue(.5)
|
||||
p1 = Vector(self.dimnode.pnts.getValues()[0].getValue())
|
||||
p2 = Vector(self.dimnode.pnts.getValues()[-1].getValue())
|
||||
@@ -1083,7 +1083,7 @@ class archDimTracker(Tracker):
|
||||
self.dimnode.datumtype.setValue(mode)
|
||||
|
||||
def p1(self,point=None):
|
||||
"sets or gets the first point of the dim"
|
||||
"""sets or gets the first point of the dim"""
|
||||
if point:
|
||||
self.dimnode.pnts.set1Value(0,point.x,point.y,point.z)
|
||||
self.setString()
|
||||
@@ -1091,7 +1091,7 @@ class archDimTracker(Tracker):
|
||||
return Vector(self.dimnode.pnts.getValues()[0].getValue())
|
||||
|
||||
def p2(self,point=None):
|
||||
"sets or gets the second point of the dim"
|
||||
"""sets or gets the second point of the dim"""
|
||||
if point:
|
||||
self.dimnode.pnts.set1Value(1,point.x,point.y,point.z)
|
||||
self.setString()
|
||||
|
||||
@@ -347,7 +347,7 @@ def angle(u, v=Vector(1, 0, 0), normal=Vector(0, 0, 1)):
|
||||
dp = u.dot(v)/ll
|
||||
|
||||
# Due to rounding errors, the dot product could be outside
|
||||
# the range [-1, 1], so let's force it to be withing this range.
|
||||
# the range [-1, 1], so let's force it to be within this range.
|
||||
if dp < -1:
|
||||
dp = -1
|
||||
elif dp > 1:
|
||||
@@ -785,7 +785,7 @@ def removeDoubles(vlist):
|
||||
Finding duplicated vectors tests for `equality` which depends
|
||||
on the `precision` parameter in the parameter database.
|
||||
|
||||
Paramaters
|
||||
Parameters
|
||||
----------
|
||||
vlist : list of Base::Vector3
|
||||
List with vectors.
|
||||
|
||||
@@ -65,7 +65,6 @@ class DraftWorkbench(Workbench):
|
||||
# Import Draft tools, icons
|
||||
try:
|
||||
import os, Draft_rc, DraftTools, DraftGui
|
||||
import DraftEdit
|
||||
from DraftTools import translate
|
||||
FreeCADGui.addLanguagePath(":/translations")
|
||||
FreeCADGui.addIconPath(":/icons")
|
||||
@@ -73,9 +72,6 @@ class DraftWorkbench(Workbench):
|
||||
print(inst)
|
||||
FreeCAD.Console.PrintError("Error: Initializing one or more of the Draft modules failed, Draft will not work as expected.\n")
|
||||
|
||||
# setup commands
|
||||
FreeCADGui.addCommand('Draft_Edit', DraftEdit.Edit())
|
||||
|
||||
# setup menus
|
||||
self.cmdList = ["Draft_Line", "Draft_Wire", "Draft_Circle",
|
||||
"Draft_ArcTools", "Draft_Ellipse",
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
#
|
||||
# This module provides the plane class which provides a virtual working plane
|
||||
# in FreeCAD and a couple of utility functions.
|
||||
"""
|
||||
"""@package WorkingPlane
|
||||
\ingroup DRAFT
|
||||
\brief This module handles the working plane and grid of the Draft Workbench.
|
||||
|
||||
This module provides the plane class which provides a virtual working plane
|
||||
in FreeCAD and a couple of utility functions.
|
||||
The Working Plane is mostly intended to be used in the Draft Workbench
|
||||
to draw 2D objects.
|
||||
The working plane is mostly intended to be used in the Draft Workbench
|
||||
to draw 2D objects in various orientations, not only in the standard XY,
|
||||
YZ, and XZ planes.
|
||||
"""
|
||||
|
||||
# ***************************************************************************
|
||||
@@ -37,6 +41,7 @@ to draw 2D objects.
|
||||
|
||||
import FreeCAD, math, DraftVecUtils
|
||||
from FreeCAD import Vector
|
||||
from FreeCAD import Console as FCC
|
||||
|
||||
__title__ = "FreeCAD Working Plane utility"
|
||||
__author__ = "Ken Cline"
|
||||
@@ -61,13 +66,15 @@ class plane:
|
||||
A vector that is supposed to be perpendicular to `u` and `v`;
|
||||
it is helpful although redundant.
|
||||
position : Base::Vector3
|
||||
A point throught which the plane goes through,
|
||||
A point, which the plane goes through,
|
||||
that helps define the working plane.
|
||||
stored : bool
|
||||
A placeholder for a stored state.
|
||||
"""
|
||||
|
||||
def __init__(self, u=Vector(1, 0, 0), v=Vector(0, 1, 0), w=Vector(0, 0, 1), pos=Vector(0, 0, 0)):
|
||||
def __init__(self,
|
||||
u=Vector(1, 0, 0), v=Vector(0, 1, 0), w=Vector(0, 0, 1),
|
||||
pos=Vector(0, 0, 0)):
|
||||
"""Initialize the working plane.
|
||||
|
||||
Parameters
|
||||
@@ -98,7 +105,11 @@ class plane:
|
||||
|
||||
def __repr__(self):
|
||||
"""Show the string representation of the object."""
|
||||
return "Workplane x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis))
|
||||
text = "Workplane"
|
||||
text += " x=" + str(DraftVecUtils.rounded(self.u))
|
||||
text += " y=" + str(DraftVecUtils.rounded(self.v))
|
||||
text += " z=" + str(DraftVecUtils.rounded(self.axis))
|
||||
return text
|
||||
|
||||
def copy(self):
|
||||
"""Return a new plane that is a copy of the present object."""
|
||||
@@ -148,7 +159,7 @@ class plane:
|
||||
|
||||
The points are as follows
|
||||
|
||||
* `p` is an arbitraty point outside the plane.
|
||||
* `p` is an arbitrary point outside the plane.
|
||||
* `c` is a known point on the plane,
|
||||
for example, `plane.position`.
|
||||
* `x` is the intercept on the plane from `p` in
|
||||
@@ -198,7 +209,8 @@ class plane:
|
||||
**Note:** for 2D these trigonometric operations
|
||||
produce the full `|xp|` distance.
|
||||
"""
|
||||
if direction == None: direction = self.axis
|
||||
if direction is None:
|
||||
direction = self.axis
|
||||
return direction.dot(self.position.sub(p))
|
||||
|
||||
def projectPoint(self, p, direction=None):
|
||||
@@ -257,7 +269,7 @@ class plane:
|
||||
if not direction:
|
||||
direction = self.axis
|
||||
t = Vector(direction)
|
||||
#t.normalize()
|
||||
# t.normalize()
|
||||
a = round(t.getAngle(self.axis), DraftVecUtils.precision())
|
||||
pp = round((math.pi)/2, DraftVecUtils.precision())
|
||||
if a == pp:
|
||||
@@ -314,8 +326,8 @@ class plane:
|
||||
offsetVector.multiply(offset)
|
||||
self.position = point.add(offsetVector)
|
||||
self.weak = False
|
||||
# FreeCAD.Console.PrintMessage("(position = " + str(self.position) + ")\n")
|
||||
# FreeCAD.Console.PrintMessage("Current workplane: x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis))+"\n")
|
||||
# FCC.PrintMessage("(position = " + str(self.position) + ")\n")
|
||||
# FCC.PrintMessage(self.__repr__() + "\n")
|
||||
|
||||
def alignToPointAndAxis_SVG(self, point, axis, offset=0):
|
||||
"""Align the working plane to a point and an axis (vector).
|
||||
@@ -387,50 +399,51 @@ class plane:
|
||||
self.u = axis.negative().cross(ref_vec)
|
||||
self.u.normalize()
|
||||
self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
|
||||
#projcase = "Case new"
|
||||
# projcase = "Case new"
|
||||
|
||||
elif ((abs(axis.y) > abs(axis.z)) and (abs(axis.z) >= abs(axis.x))):
|
||||
ref_vec = Vector(1.0, 0.0, 0.0)
|
||||
self.u = axis.negative().cross(ref_vec)
|
||||
self.u.normalize()
|
||||
self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
|
||||
#projcase = "Y>Z, View Y"
|
||||
# projcase = "Y>Z, View Y"
|
||||
|
||||
elif ((abs(axis.y) >= abs(axis.x)) and (abs(axis.x) > abs(axis.z))):
|
||||
ref_vec = Vector(0.0, 0., 1.0)
|
||||
self.u = axis.cross(ref_vec)
|
||||
self.u.normalize()
|
||||
self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
|
||||
#projcase = "ehem. XY, Case XY"
|
||||
# projcase = "ehem. XY, Case XY"
|
||||
|
||||
elif ((abs(axis.x) > abs(axis.z)) and (abs(axis.z) >= abs(axis.y))):
|
||||
self.u = axis.cross(ref_vec)
|
||||
self.u.normalize()
|
||||
self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
|
||||
#projcase = "X>Z, View X"
|
||||
# projcase = "X>Z, View X"
|
||||
|
||||
elif ((abs(axis.z) >= abs(axis.y)) and (abs(axis.y) > abs(axis.x))):
|
||||
ref_vec = Vector(1.0, 0., 0.0)
|
||||
self.u = axis.cross(ref_vec)
|
||||
self.u.normalize()
|
||||
self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
|
||||
#projcase = "Y>X, Case YZ"
|
||||
# projcase = "Y>X, Case YZ"
|
||||
|
||||
else:
|
||||
self.u = axis.negative().cross(ref_vec)
|
||||
self.u.normalize()
|
||||
self.v = DraftVecUtils.rotate(self.u, math.pi/2, self.axis)
|
||||
#projcase = "else"
|
||||
# projcase = "else"
|
||||
|
||||
#spat_vec = self.u.cross(self.v)
|
||||
#spat_res = spat_vec.dot(axis)
|
||||
#FreeCAD.Console.PrintMessage(projcase + " spat Prod = " + str(spat_res) + "\n")
|
||||
# spat_vec = self.u.cross(self.v)
|
||||
# spat_res = spat_vec.dot(axis)
|
||||
# FCC.PrintMessage(projcase + " spat Prod = " + str(spat_res) + "\n")
|
||||
|
||||
offsetVector = Vector(axis); offsetVector.multiply(offset)
|
||||
offsetVector = Vector(axis)
|
||||
offsetVector.multiply(offset)
|
||||
self.position = point.add(offsetVector)
|
||||
self.weak = False
|
||||
# FreeCAD.Console.PrintMessage("(position = " + str(self.position) + ")\n")
|
||||
# FreeCAD.Console.PrintMessage("Current workplane: x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis))+"\n")
|
||||
# FCC.PrintMessage("(position = " + str(self.position) + ")\n")
|
||||
# FCC.PrintMessage(self.__repr__() + "\n")
|
||||
|
||||
def alignToCurve(self, shape, offset=0):
|
||||
"""Align plane to curve. NOT YET IMPLEMENTED.
|
||||
@@ -453,10 +466,10 @@ class plane:
|
||||
if shape.isNull():
|
||||
return False
|
||||
elif shape.ShapeType == 'Edge':
|
||||
#??? TODO: process curve here. look at shape.edges[0].Curve
|
||||
# ??? TODO: process curve here. look at shape.edges[0].Curve
|
||||
return False
|
||||
elif shape.ShapeType == 'Wire':
|
||||
#??? TODO: determine if edges define a plane
|
||||
# ??? TODO: determine if edges define a plane
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
@@ -490,7 +503,7 @@ class plane:
|
||||
v1.normalize()
|
||||
v2.normalize()
|
||||
v3.normalize()
|
||||
#print v1,v2,v3
|
||||
# print(v1,v2,v3)
|
||||
self.u = v1
|
||||
self.v = v2
|
||||
self.axis = v3
|
||||
@@ -519,7 +532,7 @@ class plane:
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
`True` if the operation was succesful, and `False` if the shape
|
||||
`True` if the operation was successful, and `False` if the shape
|
||||
is not a `'Face'`.
|
||||
|
||||
See Also
|
||||
@@ -528,7 +541,9 @@ class plane:
|
||||
"""
|
||||
# Set face to the unique selected face, if found
|
||||
if shape.ShapeType == 'Face':
|
||||
self.alignToPointAndAxis(shape.Faces[0].CenterOfMass, shape.Faces[0].normalAt(0, 0), offset)
|
||||
self.alignToPointAndAxis(shape.Faces[0].CenterOfMass,
|
||||
shape.Faces[0].normalAt(0, 0),
|
||||
offset)
|
||||
import DraftGeomUtils
|
||||
q = DraftGeomUtils.getQuad(shape)
|
||||
if q:
|
||||
@@ -570,7 +585,7 @@ class plane:
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
`True` if the operation was succesful, and `False` otherwise.
|
||||
`True` if the operation was successful, and `False` otherwise.
|
||||
"""
|
||||
import Part
|
||||
w = Part.makePolygon([p1, p2, p3, p1])
|
||||
@@ -597,7 +612,7 @@ class plane:
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
`True` if the operation was succesful, and `False` otherwise.
|
||||
`True` if the operation was successful, and `False` otherwise.
|
||||
It returns `False` if the selection has no elements,
|
||||
or if it has more than one element,
|
||||
or if the object is not derived from `'Part::Feature'`
|
||||
@@ -625,12 +640,13 @@ class plane:
|
||||
if len(sex) == 0:
|
||||
return False
|
||||
elif len(sex) == 1:
|
||||
if not sex[0].Object.isDerivedFrom("Part::Feature") \
|
||||
or not sex[0].Object.Shape:
|
||||
if (not sex[0].Object.isDerivedFrom("Part::Feature")
|
||||
or not sex[0].Object.Shape):
|
||||
return False
|
||||
return self.alignToCurve(sex[0].Object.Shape, offset) \
|
||||
or self.alignToFace(sex[0].Object.Shape, offset) \
|
||||
or (len(sex[0].SubObjects) == 1 and self.alignToFace(sex[0].SubObjects[0], offset))
|
||||
return (self.alignToFace(sex[0].Object.Shape, offset)
|
||||
or (len(sex[0].SubObjects) == 1
|
||||
and self.alignToFace(sex[0].SubObjects[0], offset))
|
||||
or self.alignToCurve(sex[0].Object.Shape, offset))
|
||||
else:
|
||||
# len(sex) > 2, look for point and line, three points, etc.
|
||||
return False
|
||||
@@ -673,12 +689,19 @@ class plane:
|
||||
try:
|
||||
import FreeCADGui
|
||||
from pivy import coin
|
||||
rot = FreeCADGui.ActiveDocument.ActiveView.getCameraNode().getField("orientation").getValue()
|
||||
upvec = Vector(rot.multVec(coin.SbVec3f(0, 1, 0)).getValue())
|
||||
vdir = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
|
||||
if (vdir.getAngle(self.axis) > 0.001) and (vdir.getAngle(self.axis) < 3.14159):
|
||||
# don't change the WP if it is already perpendicular to the current view
|
||||
self.alignToPointAndAxis(Vector(0, 0, 0), vdir.negative(), 0, upvec)
|
||||
view = FreeCADGui.ActiveDocument.ActiveView
|
||||
camera = view.getCameraNode()
|
||||
rot = camera.getField("orientation").getValue()
|
||||
coin_up = coin.SbVec3f(0, 1, 0)
|
||||
upvec = Vector(rot.multVec(coin_up).getValue())
|
||||
vdir = view.getViewDirection()
|
||||
# The angle is between 0 and 180 degrees.
|
||||
angle = vdir.getAngle(self.axis)
|
||||
if (angle > 0.001) and (angle < 3.14159):
|
||||
# don't change the plane if it is already
|
||||
# perpendicular to the current view
|
||||
self.alignToPointAndAxis(Vector(0, 0, 0),
|
||||
vdir.negative(), 0, upvec)
|
||||
except:
|
||||
pass
|
||||
self.weak = True
|
||||
@@ -709,8 +732,9 @@ class plane:
|
||||
# Arch active container
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
if FreeCADGui.ActiveDocument.ActiveView:
|
||||
a = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch")
|
||||
view = FreeCADGui.ActiveDocument.ActiveView
|
||||
if view:
|
||||
a = view.getActiveObject("Arch")
|
||||
if a:
|
||||
p = a.Placement.inverse().multiply(p)
|
||||
return p
|
||||
@@ -744,9 +768,10 @@ class plane:
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
p = FreeCAD.Placement(m)
|
||||
# Arch active container if based on App Part
|
||||
#if FreeCAD.GuiUp:
|
||||
# if FreeCAD.GuiUp:
|
||||
# import FreeCADGui
|
||||
# a = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch")
|
||||
# view = FreeCADGui.ActiveDocument.ActiveView
|
||||
# a = view.getActiveObject("Arch")
|
||||
# if a:
|
||||
# p = a.Placement.inverse().multiply(p)
|
||||
return p
|
||||
@@ -761,9 +786,10 @@ class plane:
|
||||
"""
|
||||
n = self.axis
|
||||
# Arch active container if based on App Part
|
||||
#if FreeCAD.GuiUp:
|
||||
# if FreeCAD.GuiUp:
|
||||
# import FreeCADGui
|
||||
# a = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch")
|
||||
# view = FreeCADGui.ActiveDocument.ActiveView
|
||||
# a = view.getActiveObject("Arch")
|
||||
# if a:
|
||||
# n = a.Placement.inverse().Rotation.multVec(n)
|
||||
return n
|
||||
@@ -818,7 +844,6 @@ class plane:
|
||||
Restores the attributes `u`, `v`, `axis`, `position` and `weak`
|
||||
from `stored`, and set `stored` to `None`.
|
||||
"""
|
||||
"restores a previously saved plane state, if exists"
|
||||
if self.stored:
|
||||
self.u = self.stored[0]
|
||||
self.v = self.stored[1]
|
||||
@@ -1071,22 +1096,30 @@ class plane:
|
||||
def isOrtho(self):
|
||||
"""Return True if the plane axes are orthogonal with the global axes.
|
||||
|
||||
Orthogonal means that the angle between `u` and the global axis `+X`
|
||||
Orthogonal means that the angle between `u` and the global axis `+Y`
|
||||
is a multiple of 90 degrees, meaning 0, -90, 90, -180, 180,
|
||||
-270, 270, or 360 degrees.
|
||||
And similarly for `v` and `axis` with `+Y` and `+Z`, respectively.
|
||||
And similarly for `v` and `axis`.
|
||||
All three axes should be orthogonal to the `+Y` axis.
|
||||
|
||||
Due to rounding errors, the angle difference is rounded
|
||||
to 6 decimal digits to do the test.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Returns `True` if all three `u`, `v`, and `axis`
|
||||
are orthogonal with their respective global axes `+X`, `+Y`,
|
||||
and `+Z`.
|
||||
are orthogonal with the global axis `+Y`.
|
||||
Otherwise it returns `False`.
|
||||
"""
|
||||
if round(self.u.getAngle(Vector(0, 1, 0)), 6) in [0, -1.570796, 1.570796, -3.141593, 3.141593, -4.712389, 4.712389, 6.283185]:
|
||||
if round(self.v.getAngle(Vector(0, 1, 0)), 6) in [0, -1.570796, 1.570796, -3.141593, 3.141593, -4.712389, 4.712389, 6.283185]:
|
||||
if round(self.axis.getAngle(Vector(0, 1, 0)), 6) in [0, -1.570796, 1.570796, -3.141593, 3.141593, -4.712389, 4.712389, 6.283185]:
|
||||
ortho = [0, -1.570796, 1.570796,
|
||||
-3.141593, 3.141593,
|
||||
-4.712389, 4.712389, 6.283185]
|
||||
# Shouldn't the angle difference be calculated with
|
||||
# the other global axes `+X` and `+Z` as well?
|
||||
if round(self.u.getAngle(Vector(0, 1, 0)), 6) in ortho:
|
||||
if round(self.v.getAngle(Vector(0, 1, 0)), 6) in ortho:
|
||||
if round(self.axis.getAngle(Vector(0, 1, 0)), 6) in ortho:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -1,45 +1,80 @@
|
||||
# -*- coding: utf8 -*-
|
||||
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2009 Yorik van Havre <[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 *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
"FreeCAD Draft Workbench - DWG importer/exporter"
|
||||
|
||||
## @package importDWG
|
||||
# \ingroup DRAFT
|
||||
# \brief DWG file importer & exporter
|
||||
#
|
||||
# This module provides support for importing and exporting Autodesk DWG files.
|
||||
# This module is only a thin layer that uses the ODA (formerly Teigha) File
|
||||
# Converter application to convert to/from DXF. Then the real work is done by
|
||||
# importDXF
|
||||
'''
|
||||
@package importDWG
|
||||
ingroup DRAFT
|
||||
\brief DWG file importer & exporter
|
||||
|
||||
This module provides support for importing and exporting Autodesk DWG files.
|
||||
This module is only a thin layer that uses the ODA (formerly Teigha) File
|
||||
Converter application to convert to/from DXF. Then the real work is done by
|
||||
importDXF
|
||||
|
||||
The converter may be called
|
||||
/usr/bin/TeighaFileConverter
|
||||
/usr/bin/ODAFileConverter
|
||||
|
||||
Test files
|
||||
https://knowledge.autodesk.com/support/autocad/downloads/
|
||||
caas/downloads/content/autocad-sample-files.html
|
||||
'''
|
||||
# Check code quality with
|
||||
# flake8 --ignore=E226,E266,E401,W503
|
||||
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2009 Yorik van Havre <[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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
# TODO: use subprocess.popen() instead of subprocess.call()
|
||||
|
||||
import six
|
||||
import FreeCAD
|
||||
from FreeCAD import Console as FCC
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
from DraftTools import translate
|
||||
else:
|
||||
def translate(context, txt):
|
||||
return txt
|
||||
|
||||
# Save the native open function to avoid collisions
|
||||
if open.__module__ == '__builtin__':
|
||||
pythonopen = open # to distinguish python built-in open function from the one declared here
|
||||
pythonopen = open
|
||||
|
||||
|
||||
def open(filename):
|
||||
"called when freecad opens a file."
|
||||
"""Open filename and parse using importDXF.open().
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
The path to the filename to be opened.
|
||||
|
||||
Returns
|
||||
-------
|
||||
App::Document
|
||||
The new FreeCAD document object created, with the parsed information.
|
||||
"""
|
||||
dxf = convertToDxf(filename)
|
||||
if dxf:
|
||||
import importDXF
|
||||
@@ -47,27 +82,79 @@ def open(filename):
|
||||
return doc
|
||||
return
|
||||
|
||||
def insert(filename,docname):
|
||||
"called when freecad imports a file"
|
||||
|
||||
def insert(filename, docname):
|
||||
"""Imports a file using importDXF.insert().
|
||||
|
||||
If no document exist, it is created.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
The path to the filename to be opened.
|
||||
docname : str
|
||||
The name of the active App::Document if one exists, or
|
||||
of the new one created.
|
||||
|
||||
Returns
|
||||
-------
|
||||
App::Document
|
||||
The active FreeCAD document, or the document created if none exists,
|
||||
with the parsed information.
|
||||
"""
|
||||
dxf = convertToDxf(filename)
|
||||
if dxf:
|
||||
import importDXF
|
||||
doc = importDXF.insert(dxf,docname)
|
||||
# Warning: function doesn't return?
|
||||
doc = importDXF.insert(dxf, docname)
|
||||
return doc
|
||||
return
|
||||
|
||||
def export(objectslist,filename):
|
||||
"called when freecad exports a file"
|
||||
import importDXF,os,tempfile
|
||||
|
||||
def export(objectslist, filename):
|
||||
"""Export the DWG file with a given list of objects.
|
||||
|
||||
The objects are exported with importDXF.export().
|
||||
Then the result is converted to DWG.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
exportList : list
|
||||
List of document objects to export.
|
||||
filename : str
|
||||
Path to the new file.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The same `filename` input.
|
||||
"""
|
||||
import importDXF, os, tempfile
|
||||
outdir = tempfile.mkdtemp()
|
||||
dxf = outdir + os.sep + os.path.splitext(os.path.basename(filename))[0] + ".dxf"
|
||||
importDXF.export(objectslist,dxf)
|
||||
convertToDwg(dxf,filename)
|
||||
_basename = os.path.splitext(os.path.basename(filename))[0]
|
||||
dxf = outdir + os.sep + _basename + ".dxf"
|
||||
importDXF.export(objectslist, dxf)
|
||||
convertToDwg(dxf, filename)
|
||||
return filename
|
||||
|
||||
|
||||
def getTeighaConverter():
|
||||
import FreeCAD,os,platform
|
||||
"finds the Teigha Converter executable"
|
||||
"""Find the ODA (formerly Teigha) executable.
|
||||
|
||||
It searches the FreeCAD parameters database, then searches for common
|
||||
paths in Linux and Windows systems.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
None
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The full path of the converter executable
|
||||
'/usr/bin/TeighaFileConverter'
|
||||
"""
|
||||
import FreeCAD, os, platform
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
|
||||
p = p.GetString("TeighaFileConverter")
|
||||
if p:
|
||||
@@ -78,55 +165,99 @@ def getTeighaConverter():
|
||||
teigha = None
|
||||
if platform.system() == "Linux":
|
||||
teigha = "/usr/bin/TeighaFileConverter"
|
||||
if not os.path.exists(teigha):
|
||||
teigha = "/usr/bin/ODAFileConverter"
|
||||
elif platform.system() == "Windows":
|
||||
odadir = os.path.expandvars("%ProgramFiles%\ODA")
|
||||
if os.path.exists(odadir):
|
||||
subdirs = os.walk(odadir).next()[1]
|
||||
for sub in subdirs:
|
||||
t = odadir + os.sep + sub + os.sep + "TeighaFileConverter.exe"
|
||||
t = (odadir + os.sep + sub + os.sep
|
||||
+ "TeighaFileConverter.exe")
|
||||
t = os.path.join(odadir, sub, "TeighaFileConverter.exe")
|
||||
if os.path.exists(t):
|
||||
teigha = t
|
||||
if teigha:
|
||||
if os.path.exists(teigha):
|
||||
return teigha
|
||||
from DraftTools import translate
|
||||
FreeCAD.Console.PrintMessage(translate("draft","ODA (formerly Teigha) File Converter not found, DWG support is disabled")+"\n")
|
||||
_msg = ("ODA (formerly Teigha) File Converter not found, "
|
||||
"DWG support is disabled")
|
||||
FCC.PrintMessage(translate("draft", _msg) + "\n")
|
||||
return None
|
||||
|
||||
|
||||
def convertToDxf(dwgfilename):
|
||||
"converts a DWG file to DXF"
|
||||
import os,tempfile,subprocess,sys #import os,tempfile
|
||||
"""Convert a DWG file to a DXF file.
|
||||
|
||||
If the converter is found it is used, otherwise the convesion fails.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dwgfilename : str
|
||||
The input filename.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The new file produced.
|
||||
"""
|
||||
import os, tempfile, subprocess, sys
|
||||
teigha = getTeighaConverter()
|
||||
if teigha:
|
||||
indir = os.path.dirname(dwgfilename)
|
||||
outdir = tempfile.mkdtemp()
|
||||
basename = os.path.basename(dwgfilename)
|
||||
cmdline = '"%s" "%s" "%s" "ACAD2000" "DXF" "0" "1" "%s"' % (teigha, indir, outdir, basename)
|
||||
print("Converting: " + cmdline)
|
||||
cmdline = ('"%s" "%s" "%s" "ACAD2000" "DXF" "0" "1" "%s"'
|
||||
% (teigha, indir, outdir, basename))
|
||||
FCC.PrintMessage(translate("ImportDWG", "Converting: ")
|
||||
+ cmdline + "\n")
|
||||
if six.PY2:
|
||||
if isinstance(cmdline,six.text_type):
|
||||
if isinstance(cmdline, six.text_type):
|
||||
encoding = sys.getfilesystemencoding()
|
||||
cmdline = cmdline.encode(encoding)
|
||||
subprocess.call(cmdline, shell=True) #os.system(cmdline)
|
||||
subprocess.call(cmdline, shell=True) # os.system(cmdline)
|
||||
result = outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
|
||||
if os.path.exists(result):
|
||||
print("Conversion successful")
|
||||
FCC.PrintMessage(translate("ImportDWG",
|
||||
"Conversion successful") + "\n")
|
||||
return result
|
||||
else:
|
||||
print("Error during DWG to DXF conversion. Try moving the DWG file to a directory path")
|
||||
print("without spaces and non-english characters, or try saving to a lower DWG version")
|
||||
_msg = ("Error during DWG to DXF conversion. "
|
||||
"Try moving the DWG file to a directory path\n"
|
||||
"without spaces and non-english characters, "
|
||||
"or try saving to a lower DWG version.")
|
||||
FCC.PrintMessage(translate("ImportDWG", _msg) + "\n")
|
||||
return None
|
||||
|
||||
def convertToDwg(dxffilename,dwgfilename):
|
||||
"converts a DXF file to DWG"
|
||||
import os,subprocess #import os
|
||||
|
||||
def convertToDwg(dxffilename, dwgfilename):
|
||||
"""Convert a DXF file to a DWG file.
|
||||
|
||||
If the converter is found it is used, otherwise the convesion fails.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dxffilename : str
|
||||
The input DXF file
|
||||
dwgfilename : str
|
||||
The output DWG file
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The same `dwgfilename` file path.
|
||||
"""
|
||||
import os, subprocess
|
||||
teigha = getTeighaConverter()
|
||||
if teigha:
|
||||
indir = os.path.dirname(dxffilename)
|
||||
outdir = os.path.dirname(dwgfilename)
|
||||
basename = os.path.basename(dxffilename)
|
||||
cmdline = '"%s" "%s" "%s" "ACAD2000" "DWG" "0" "1" "%s"' % (teigha, indir, outdir, basename)
|
||||
print("converting " + cmdline)
|
||||
subprocess.call(cmdline, shell=True) #os.system(cmdline)
|
||||
cmdline = ('"%s" "%s" "%s" "ACAD2000" "DWG" "0" "1" "%s"'
|
||||
% (teigha, indir, outdir, basename))
|
||||
FCC.PrintMessage(translate("ImportDWG", "Converting: ")
|
||||
+ cmdline + "\n")
|
||||
subprocess.call(cmdline, shell=True) # os.system(cmdline)
|
||||
return dwgfilename
|
||||
return None
|
||||
|
||||
@@ -743,7 +743,6 @@ class svgHandler(xml.sax.ContentHandler):
|
||||
ret = msgBox.exec_()
|
||||
if ret == QtGui.QMessageBox.Yes:
|
||||
self.svgdpi = 96.0
|
||||
<<<<<<< HEAD
|
||||
else:
|
||||
self.svgdpi = 90.0
|
||||
if ret:
|
||||
@@ -751,88 +750,6 @@ class svgHandler(xml.sax.ContentHandler):
|
||||
FCC.PrintMessage(translate("ImportSVG", _qst) + "\n")
|
||||
FCC.PrintMessage("*** User specified "
|
||||
+ str(self.svgdpi) + " dpi ***\n")
|
||||
=======
|
||||
if 'style' in data:
|
||||
if not data['style']:
|
||||
pass#empty style attribute stops inheriting from parent
|
||||
else:
|
||||
content = data['style'].replace(' ','')
|
||||
content = content.split(';')
|
||||
for i in content:
|
||||
pair = i.split(':')
|
||||
if len(pair)>1: data[pair[0]]=pair[1]
|
||||
|
||||
for k in ['x','y','x1','y1','x2','y2','r','rx','ry','cx','cy','width','height']:
|
||||
if k in data:
|
||||
data[k] = getsize(data[k][0],'css'+str(self.svgdpi))
|
||||
|
||||
for k in ['fill','stroke','stroke-width','font-size']:
|
||||
if k in data:
|
||||
if isinstance(data[k],list):
|
||||
if data[k][0].lower().startswith("rgb("):
|
||||
data[k] = ",".join(data[k])
|
||||
else:
|
||||
data[k]=data[k][0]
|
||||
|
||||
# extracting style info
|
||||
|
||||
self.fill = None
|
||||
self.color = None
|
||||
self.width = None
|
||||
self.text = None
|
||||
|
||||
if name == 'svg':
|
||||
m=FreeCAD.Matrix()
|
||||
if not self.disableUnitScaling:
|
||||
if 'width' in data and 'height' in data and \
|
||||
'viewBox' in data:
|
||||
vbw=float(data['viewBox'][2])
|
||||
vbh=float(data['viewBox'][3])
|
||||
w=attrs.getValue('width')
|
||||
h=attrs.getValue('height')
|
||||
self.viewbox=(vbw,vbh)
|
||||
if len(self.grouptransform)==0:
|
||||
unitmode='mm'+str(self.svgdpi)
|
||||
else: #nested svg element
|
||||
unitmode='css'+str(self.svgdpi)
|
||||
abw = getsize(w,unitmode)
|
||||
abh = getsize(h,unitmode)
|
||||
sx=abw/vbw
|
||||
sy=abh/vbh
|
||||
preservearstr=' '.join(data.get('preserveAspectRatio',[])).lower()
|
||||
uniformscaling = round(sx/sy,5) == 1
|
||||
if uniformscaling:
|
||||
m.scale(Vector(sx,sy,1))
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning('Scaling Factors do not match!!!\n')
|
||||
if preservearstr.startswith('none'):
|
||||
m.scale(Vector(sx,sy,1))
|
||||
else: #preserve the aspect ratio
|
||||
if preservearstr.endswith('slice'):
|
||||
sxy=max(sx,sy)
|
||||
else:
|
||||
sxy=min(sx,sy)
|
||||
m.scale(Vector(sxy,sxy,1))
|
||||
elif len(self.grouptransform)==0:
|
||||
#fallback to current dpi
|
||||
m.scale(Vector(25.4/self.svgdpi,25.4/self.svgdpi,1))
|
||||
self.grouptransform.append(m)
|
||||
if 'fill' in data:
|
||||
if data['fill'][0] != 'none':
|
||||
self.fill = getcolor(data['fill'])
|
||||
if 'stroke' in data:
|
||||
if data['stroke'][0] != 'none':
|
||||
self.color = getcolor(data['stroke'])
|
||||
if 'stroke-width' in data:
|
||||
if data['stroke-width'] != 'none':
|
||||
self.width = getsize(data['stroke-width'],'css'+str(self.svgdpi))
|
||||
if 'transform' in data:
|
||||
m = self.getMatrix(attrs.getValue('transform'))
|
||||
if name == "g":
|
||||
self.grouptransform.append(m)
|
||||
else:
|
||||
self.transform = m
|
||||
>>>>>>> 6d64c2b2c6bc64ce21e7c2f4ed7e1ab2c8991f8e
|
||||
else:
|
||||
self.svgdpi = 96.0
|
||||
FCC.PrintMessage(_msg + "\n")
|
||||
@@ -1569,7 +1486,7 @@ class svgHandler(xml.sax.ContentHandler):
|
||||
obj.ViewObject.TextColor = (0.0, 0.0, 0.0, 0.0)
|
||||
|
||||
def endElement(self, name):
|
||||
"""Finish procesing the element indicated by the name.
|
||||
"""Finish processing the element indicated by the name.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
@@ -51,7 +51,7 @@ FreeCAD.addExportType("FEM mesh Z88 (*i1.txt)", "feminout.importZ88Mesh")
|
||||
|
||||
FreeCAD.addImportType("FEM result Z88 displacements (*o2.txt)", "feminout.importZ88O2Results")
|
||||
|
||||
if("BUILD_FEM_VTK" in FreeCAD.__cmake__):
|
||||
if "BUILD_FEM_VTK" in FreeCAD.__cmake__:
|
||||
FreeCAD.addImportType("FEM result VTK (*.vtk *.vtu)", "feminout.importVTKResults")
|
||||
FreeCAD.addExportType("FEM result VTK (*.vtk *.vtu)", "feminout.importVTKResults")
|
||||
|
||||
|
||||
@@ -33,8 +33,9 @@ import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
|
||||
class FemWorkbench (Workbench):
|
||||
class FemWorkbench(Workbench):
|
||||
"Fem workbench object"
|
||||
|
||||
def __init__(self):
|
||||
self.__class__.Icon = FreeCAD.getResourceDir() + "Mod/Fem/Resources/icons/FemWorkbench.svg"
|
||||
self.__class__.MenuText = "FEM"
|
||||
|
||||
@@ -35,8 +35,8 @@ def makeAnalysis(
|
||||
doc,
|
||||
name="Analysis"
|
||||
):
|
||||
'''makeAnalysis(document, [name]):
|
||||
makes a Fem Analysis object'''
|
||||
"""makeAnalysis(document, [name]):
|
||||
makes a Fem Analysis object"""
|
||||
obj = doc.addObject("Fem::FemAnalysis", name)
|
||||
return obj
|
||||
|
||||
@@ -46,8 +46,8 @@ def makeConstraintBearing(
|
||||
doc,
|
||||
name="ConstraintBearing"
|
||||
):
|
||||
'''makeConstraintBearing(document, [name]):
|
||||
makes a Fem ConstraintBearing object'''
|
||||
"""makeConstraintBearing(document, [name]):
|
||||
makes a Fem ConstraintBearing object"""
|
||||
obj = doc.addObject("Fem::ConstraintBearing", name)
|
||||
return obj
|
||||
|
||||
@@ -56,8 +56,8 @@ def makeConstraintBodyHeatSource(
|
||||
doc,
|
||||
name="ConstraintBodyHeatSource"
|
||||
):
|
||||
'''makeConstraintBodyHeatSource(document, [name]):
|
||||
makes a Fem ConstraintBodyHeatSource object'''
|
||||
"""makeConstraintBodyHeatSource(document, [name]):
|
||||
makes a Fem ConstraintBodyHeatSource object"""
|
||||
obj = doc.addObject("Fem::ConstraintPython", name)
|
||||
from femobjects import _FemConstraintBodyHeatSource
|
||||
_FemConstraintBodyHeatSource.Proxy(obj)
|
||||
@@ -71,8 +71,8 @@ def makeConstraintContact(
|
||||
doc,
|
||||
name="ConstraintContact"
|
||||
):
|
||||
'''makeConstraintContact(document, [name]):
|
||||
makes a Fem ConstraintContact object'''
|
||||
"""makeConstraintContact(document, [name]):
|
||||
makes a Fem ConstraintContact object"""
|
||||
obj = doc.addObject("Fem::ConstraintContact", name)
|
||||
return obj
|
||||
|
||||
@@ -81,8 +81,8 @@ def makeConstraintDisplacement(
|
||||
doc,
|
||||
name="ConstraintDisplacement"
|
||||
):
|
||||
'''makeConstraintDisplacement(document, [name]):
|
||||
makes a Fem ConstraintDisplacement object'''
|
||||
"""makeConstraintDisplacement(document, [name]):
|
||||
makes a Fem ConstraintDisplacement object"""
|
||||
obj = doc.addObject("Fem::ConstraintDisplacement", name)
|
||||
return obj
|
||||
|
||||
@@ -91,8 +91,8 @@ def makeConstraintElectrostaticPotential(
|
||||
doc,
|
||||
name="ConstraintElectrostaticPotential"
|
||||
):
|
||||
'''makeConstraintElectrostaticPotential(document, [name]):
|
||||
makes a Fem ElectrostaticPotential object'''
|
||||
"""makeConstraintElectrostaticPotential(document, [name]):
|
||||
makes a Fem ElectrostaticPotential object"""
|
||||
obj = doc.addObject("Fem::ConstraintPython", name)
|
||||
from femobjects import _FemConstraintElectrostaticPotential
|
||||
_FemConstraintElectrostaticPotential.Proxy(obj)
|
||||
@@ -106,8 +106,8 @@ def makeConstraintFixed(
|
||||
doc,
|
||||
name="ConstraintFixed"
|
||||
):
|
||||
'''makeConstraintFixed(document, [name]):
|
||||
makes a Fem ConstraintFixed object'''
|
||||
"""makeConstraintFixed(document, [name]):
|
||||
makes a Fem ConstraintFixed object"""
|
||||
obj = doc.addObject("Fem::ConstraintFixed", name)
|
||||
return obj
|
||||
|
||||
@@ -116,8 +116,8 @@ def makeConstraintFlowVelocity(
|
||||
doc,
|
||||
name="ConstraintFlowVelocity"
|
||||
):
|
||||
'''makeConstraintFlowVelocity(document, [name]):
|
||||
makes a Fem ConstraintFlowVelocity object'''
|
||||
"""makeConstraintFlowVelocity(document, [name]):
|
||||
makes a Fem ConstraintFlowVelocity object"""
|
||||
obj = doc.addObject("Fem::ConstraintPython", name)
|
||||
from femobjects import _FemConstraintFlowVelocity
|
||||
_FemConstraintFlowVelocity.Proxy(obj)
|
||||
@@ -131,8 +131,8 @@ def makeConstraintFluidBoundary(
|
||||
doc,
|
||||
name="ConstraintFluidBoundary"
|
||||
):
|
||||
'''makeConstraintFluidBoundary(document, name):
|
||||
makes a Fem ConstraintFluidBoundary object'''
|
||||
"""makeConstraintFluidBoundary(document, name):
|
||||
makes a Fem ConstraintFluidBoundary object"""
|
||||
obj = doc.addObject("Fem::ConstraintFluidBoundary", name)
|
||||
return obj
|
||||
|
||||
@@ -141,8 +141,8 @@ def makeConstraintForce(
|
||||
doc,
|
||||
name="ConstraintForce"
|
||||
):
|
||||
'''makeConstraintForce(document, [name]):
|
||||
makes a Fem ConstraintForce object'''
|
||||
"""makeConstraintForce(document, [name]):
|
||||
makes a Fem ConstraintForce object"""
|
||||
obj = doc.addObject("Fem::ConstraintForce", name)
|
||||
return obj
|
||||
|
||||
@@ -151,8 +151,8 @@ def makeConstraintGear(
|
||||
doc,
|
||||
name="ConstraintGear"
|
||||
):
|
||||
'''makeConstraintGear(document, [name]):
|
||||
makes a Fem ConstraintGear object'''
|
||||
"""makeConstraintGear(document, [name]):
|
||||
makes a Fem ConstraintGear object"""
|
||||
obj = doc.addObject("Fem::ConstraintGear", name)
|
||||
return obj
|
||||
|
||||
@@ -161,8 +161,8 @@ def makeConstraintHeatflux(
|
||||
doc,
|
||||
name="ConstraintHeatflux"
|
||||
):
|
||||
'''makeConstraintHeatflux(document, [name]):
|
||||
makes a Fem ConstraintHeatflux object'''
|
||||
"""makeConstraintHeatflux(document, [name]):
|
||||
makes a Fem ConstraintHeatflux object"""
|
||||
obj = doc.addObject("Fem::ConstraintHeatflux", name)
|
||||
return obj
|
||||
|
||||
@@ -171,8 +171,8 @@ def makeConstraintInitialFlowVelocity(
|
||||
doc,
|
||||
name="ConstraintInitialFlowVelocity"
|
||||
):
|
||||
'''makeConstraintInitialFlowVelocity(document, [name]):
|
||||
makes a Fem ConstraintInitialFlowVelocity object'''
|
||||
"""makeConstraintInitialFlowVelocity(document, [name]):
|
||||
makes a Fem ConstraintInitialFlowVelocity object"""
|
||||
obj = doc.addObject("Fem::ConstraintPython", name)
|
||||
from femobjects import _FemConstraintInitialFlowVelocity
|
||||
_FemConstraintInitialFlowVelocity.Proxy(obj)
|
||||
@@ -186,8 +186,8 @@ def makeConstraintInitialTemperature(
|
||||
doc,
|
||||
name="ConstraintInitialTemperature"
|
||||
):
|
||||
'''makeConstraintInitialTemperature(document, name):
|
||||
makes a Fem ConstraintInitialTemperature object'''
|
||||
"""makeConstraintInitialTemperature(document, name):
|
||||
makes a Fem ConstraintInitialTemperature object"""
|
||||
obj = doc.addObject("Fem::ConstraintInitialTemperature", name)
|
||||
return obj
|
||||
|
||||
@@ -196,8 +196,8 @@ def makeConstraintPlaneRotation(
|
||||
doc,
|
||||
name="ConstraintPlaneRotation"
|
||||
):
|
||||
'''makeConstraintPlaneRotation(document, [name]):
|
||||
makes a Fem ConstraintPlaneRotation object'''
|
||||
"""makeConstraintPlaneRotation(document, [name]):
|
||||
makes a Fem ConstraintPlaneRotation object"""
|
||||
obj = doc.addObject("Fem::ConstraintPlaneRotation", name)
|
||||
return obj
|
||||
|
||||
@@ -206,8 +206,8 @@ def makeConstraintPressure(
|
||||
doc,
|
||||
name="ConstraintPressure"
|
||||
):
|
||||
'''makeConstraintPressure(document, [name]):
|
||||
makes a Fem ConstraintPressure object'''
|
||||
"""makeConstraintPressure(document, [name]):
|
||||
makes a Fem ConstraintPressure object"""
|
||||
obj = doc.addObject("Fem::ConstraintPressure", name)
|
||||
return obj
|
||||
|
||||
@@ -216,8 +216,8 @@ def makeConstraintPulley(
|
||||
doc,
|
||||
name="ConstraintPulley"
|
||||
):
|
||||
'''makeConstraintPulley(document, [name]):
|
||||
makes a Fem ConstraintPulley object'''
|
||||
"""makeConstraintPulley(document, [name]):
|
||||
makes a Fem ConstraintPulley object"""
|
||||
obj = doc.addObject("Fem::ConstraintPulley", name)
|
||||
return obj
|
||||
|
||||
@@ -226,8 +226,8 @@ def makeConstraintSelfWeight(
|
||||
doc,
|
||||
name="ConstraintSelfWeight"
|
||||
):
|
||||
'''makeConstraintSelfWeight(document, [name]):
|
||||
creates an self weight object to define a gravity load'''
|
||||
"""makeConstraintSelfWeight(document, [name]):
|
||||
creates an self weight object to define a gravity load"""
|
||||
obj = doc.addObject("Fem::ConstraintPython", name)
|
||||
from femobjects import _FemConstraintSelfWeight
|
||||
_FemConstraintSelfWeight._FemConstraintSelfWeight(obj)
|
||||
@@ -243,8 +243,8 @@ def makeConstraintTemperature(
|
||||
doc,
|
||||
name="ConstraintTemperature"
|
||||
):
|
||||
'''makeConstraintTemperature(document, [name]):
|
||||
makes a Fem ConstraintTemperature object'''
|
||||
"""makeConstraintTemperature(document, [name]):
|
||||
makes a Fem ConstraintTemperature object"""
|
||||
obj = doc.addObject("Fem::ConstraintTemperature", name)
|
||||
return obj
|
||||
|
||||
@@ -253,8 +253,8 @@ def makeConstraintTransform(
|
||||
doc,
|
||||
name="ConstraintTransform"
|
||||
):
|
||||
'''makeConstraintTransform(document, [name]):
|
||||
makes a Fem ConstraintTransform object'''
|
||||
"""makeConstraintTransform(document, [name]):
|
||||
makes a Fem ConstraintTransform object"""
|
||||
obj = doc.addObject("Fem::ConstraintTransform", name)
|
||||
return obj
|
||||
|
||||
@@ -264,8 +264,8 @@ def makeElementFluid1D(
|
||||
doc,
|
||||
name="ElementFluid1D"
|
||||
):
|
||||
'''makeElementFluid1D(document, [name]):
|
||||
creates an 1D fluid element object to define 1D flow'''
|
||||
"""makeElementFluid1D(document, [name]):
|
||||
creates an 1D fluid element object to define 1D flow"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemElementFluid1D
|
||||
_FemElementFluid1D._FemElementFluid1D(obj)
|
||||
@@ -277,13 +277,13 @@ def makeElementFluid1D(
|
||||
|
||||
def makeElementGeometry1D(
|
||||
doc,
|
||||
sectiontype='Rectangular',
|
||||
sectiontype="Rectangular",
|
||||
width=10.0,
|
||||
height=25.0,
|
||||
name="ElementGeometry1D"
|
||||
):
|
||||
'''makeElementGeometry1D(document, [width], [height], [name]):
|
||||
creates an 1D geometry element object to define a cross section'''
|
||||
"""makeElementGeometry1D(document, [width], [height], [name]):
|
||||
creates an 1D geometry element object to define a cross section"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemElementGeometry1D
|
||||
_FemElementGeometry1D._FemElementGeometry1D(obj)
|
||||
@@ -309,8 +309,8 @@ def makeElementGeometry2D(
|
||||
thickness=20.0,
|
||||
name="ElementGeometry2D"
|
||||
):
|
||||
'''makeElementGeometry2D(document, [thickness], [name]):
|
||||
creates an 2D geometry element object to define a plate thickness'''
|
||||
"""makeElementGeometry2D(document, [thickness], [name]):
|
||||
creates an 2D geometry element object to define a plate thickness"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemElementGeometry2D
|
||||
_FemElementGeometry2D._FemElementGeometry2D(obj)
|
||||
@@ -325,8 +325,8 @@ def makeElementRotation1D(
|
||||
doc,
|
||||
name="ElementRotation1D"
|
||||
):
|
||||
'''makeElementRotation1D(document, [name]):
|
||||
creates an 1D geometry rotation element object to rotate a 1D cross section'''
|
||||
"""makeElementRotation1D(document, [name]):
|
||||
creates an 1D geometry rotation element object to rotate a 1D cross section"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemElementRotation1D
|
||||
_FemElementRotation1D._FemElementRotation1D(obj)
|
||||
@@ -341,12 +341,12 @@ def makeMaterialFluid(
|
||||
doc,
|
||||
name="FluidMaterial"
|
||||
):
|
||||
'''makeMaterialFluid(document, [name]):
|
||||
makes a FEM Material for fluid'''
|
||||
"""makeMaterialFluid(document, [name]):
|
||||
makes a FEM Material for fluid"""
|
||||
obj = doc.addObject("App::MaterialObjectPython", name)
|
||||
from femobjects import _FemMaterial
|
||||
_FemMaterial._FemMaterial(obj)
|
||||
obj.Category = 'Fluid'
|
||||
obj.Category = "Fluid"
|
||||
if FreeCAD.GuiUp:
|
||||
from femguiobjects import _ViewProviderFemMaterial
|
||||
_ViewProviderFemMaterial._ViewProviderFemMaterial(obj.ViewObject)
|
||||
@@ -358,8 +358,8 @@ def makeMaterialMechanicalNonlinear(
|
||||
base_material,
|
||||
name="MechanicalMaterialNonlinear"
|
||||
):
|
||||
'''makeMaterialMechanicalNonlinear(document, base_material, [name]):
|
||||
creates a nonlinear material object'''
|
||||
"""makeMaterialMechanicalNonlinear(document, base_material, [name]):
|
||||
creates a nonlinear material object"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemMaterialMechanicalNonlinear
|
||||
_FemMaterialMechanicalNonlinear._FemMaterialMechanicalNonlinear(obj)
|
||||
@@ -376,8 +376,8 @@ def makeMaterialReinforced(
|
||||
doc,
|
||||
name="MaterialReinforced"
|
||||
):
|
||||
'''makeMaterialReinforced(document, [matrix_material], [reinforcement_material], [name]):
|
||||
creates a reinforced material object'''
|
||||
"""makeMaterialReinforced(document, [matrix_material], [reinforcement_material], [name]):
|
||||
creates a reinforced material object"""
|
||||
obj = doc.addObject("App::MaterialObjectPython", name)
|
||||
from femobjects import _FemMaterialReinforced
|
||||
_FemMaterialReinforced._FemMaterialReinforced(obj)
|
||||
@@ -391,12 +391,12 @@ def makeMaterialSolid(
|
||||
doc,
|
||||
name="MechanicalSolidMaterial"
|
||||
):
|
||||
'''makeMaterialSolid(document, [name]):
|
||||
makes a FEM Material for solid'''
|
||||
"""makeMaterialSolid(document, [name]):
|
||||
makes a FEM Material for solid"""
|
||||
obj = doc.addObject("App::MaterialObjectPython", name)
|
||||
from femobjects import _FemMaterial
|
||||
_FemMaterial._FemMaterial(obj)
|
||||
obj.Category = 'Solid'
|
||||
obj.Category = "Solid"
|
||||
if FreeCAD.GuiUp:
|
||||
from femguiobjects import _ViewProviderFemMaterial
|
||||
_ViewProviderFemMaterial._ViewProviderFemMaterial(obj.ViewObject)
|
||||
@@ -409,8 +409,8 @@ def makeMeshBoundaryLayer(
|
||||
base_mesh,
|
||||
name="MeshBoundaryLayer"
|
||||
):
|
||||
'''makeMeshBoundaryLayer(document, base_mesh, [name]):
|
||||
creates a FEM mesh BoundaryLayer object to define boundary layer properties'''
|
||||
"""makeMeshBoundaryLayer(document, base_mesh, [name]):
|
||||
creates a FEM mesh BoundaryLayer object to define boundary layer properties"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemMeshBoundaryLayer
|
||||
_FemMeshBoundaryLayer._FemMeshBoundaryLayer(obj)
|
||||
@@ -430,8 +430,8 @@ def makeMeshGmsh(
|
||||
doc,
|
||||
name="MeshGmsh"
|
||||
):
|
||||
'''makeMeshGmsh(document, [name]):
|
||||
makes a Gmsh FEM mesh object'''
|
||||
"""makeMeshGmsh(document, [name]):
|
||||
makes a Gmsh FEM mesh object"""
|
||||
obj = doc.addObject("Fem::FemMeshObjectPython", name)
|
||||
from femobjects import _FemMeshGmsh
|
||||
_FemMeshGmsh._FemMeshGmsh(obj)
|
||||
@@ -447,8 +447,8 @@ def makeMeshGroup(
|
||||
use_label=False,
|
||||
name="MeshGroup"
|
||||
):
|
||||
'''makeMeshGroup(document, base_mesh, [use_label], [name]):
|
||||
creates a FEM mesh region object to define properties for a region of a FEM mesh'''
|
||||
"""makeMeshGroup(document, base_mesh, [use_label], [name]):
|
||||
creates a FEM mesh region object to define properties for a region of a FEM mesh"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemMeshGroup
|
||||
_FemMeshGroup._FemMeshGroup(obj)
|
||||
@@ -469,8 +469,8 @@ def makeMeshNetgen(
|
||||
doc,
|
||||
name="MeshNetgen"
|
||||
):
|
||||
'''makeMeshNetgen(document, [name]):
|
||||
makes a Fem MeshShapeNetgenObject object'''
|
||||
"""makeMeshNetgen(document, [name]):
|
||||
makes a Fem MeshShapeNetgenObject object"""
|
||||
obj = doc.addObject("Fem::FemMeshShapeNetgenObject", name)
|
||||
return obj
|
||||
|
||||
@@ -481,8 +481,8 @@ def makeMeshRegion(
|
||||
element_length=0.0,
|
||||
name="MeshRegion"
|
||||
):
|
||||
'''makeMeshRegion(document, base_mesh, [element_length], [name]):
|
||||
creates a FEM mesh region object to define properties for a region of a FEM mesh'''
|
||||
"""makeMeshRegion(document, base_mesh, [element_length], [name]):
|
||||
creates a FEM mesh region object to define properties for a region of a FEM mesh"""
|
||||
obj = doc.addObject("Fem::FeaturePython", name)
|
||||
from femobjects import _FemMeshRegion
|
||||
_FemMeshRegion._FemMeshRegion(obj)
|
||||
@@ -503,7 +503,7 @@ def makeMeshResult(
|
||||
doc,
|
||||
name="MeshResult"
|
||||
):
|
||||
'''makeMeshResult(document, name): makes a Fem MeshResult object'''
|
||||
"""makeMeshResult(document, name): makes a Fem MeshResult object"""
|
||||
obj = doc.addObject("Fem::FemMeshObjectPython", name)
|
||||
from femobjects import _FemMeshResult
|
||||
_FemMeshResult._FemMeshResult(obj)
|
||||
@@ -518,9 +518,9 @@ def makeResultMechanical(
|
||||
doc,
|
||||
name="MechanicalResult"
|
||||
):
|
||||
'''makeResultMechanical(document, [name]):
|
||||
creates an mechanical result object to hold FEM results'''
|
||||
obj = doc.addObject('Fem::FemResultObjectPython', name)
|
||||
"""makeResultMechanical(document, [name]):
|
||||
creates an mechanical result object to hold FEM results"""
|
||||
obj = doc.addObject("Fem::FemResultObjectPython", name)
|
||||
from femobjects import _FemResultMechanical
|
||||
_FemResultMechanical._FemResultMechanical(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
@@ -534,8 +534,8 @@ def makePostVtkFilterClipRegion(
|
||||
base_vtk_result,
|
||||
name="VtkFilterClipRegion"
|
||||
):
|
||||
'''makePostVtkFilterClipRegion(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing region clip filter object (vtk based)'''
|
||||
"""makePostVtkFilterClipRegion(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing region clip filter object (vtk based)"""
|
||||
obj = doc.addObject("Fem::FemPostClipFilter", name)
|
||||
tmp_filter_list = base_vtk_result.Filter
|
||||
tmp_filter_list.append(obj)
|
||||
@@ -549,8 +549,8 @@ def makePostVtkFilterClipScalar(
|
||||
base_vtk_result,
|
||||
name="VtkFilterClipScalar"
|
||||
):
|
||||
'''makePostVtkFilterClipScalar(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing scalar clip filter object (vtk based)'''
|
||||
"""makePostVtkFilterClipScalar(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing scalar clip filter object (vtk based)"""
|
||||
obj = doc.addObject("Fem::FemPostScalarClipFilter", name)
|
||||
tmp_filter_list = base_vtk_result.Filter
|
||||
tmp_filter_list.append(obj)
|
||||
@@ -564,8 +564,8 @@ def makePostVtkFilterCutFunction(
|
||||
base_vtk_result,
|
||||
name="VtkFilterCutFunction"
|
||||
):
|
||||
'''makePostVtkFilterCutFunction(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing cut function filter object (vtk based)'''
|
||||
"""makePostVtkFilterCutFunction(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing cut function filter object (vtk based)"""
|
||||
obj = doc.addObject("Fem::FemPostClipFilter", name)
|
||||
tmp_filter_list = base_vtk_result.Filter
|
||||
tmp_filter_list.append(obj)
|
||||
@@ -579,8 +579,8 @@ def makePostVtkFilterWarp(
|
||||
base_vtk_result,
|
||||
name="VtkFilterWarp"
|
||||
):
|
||||
'''makePostVtkFilterWarp(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing warp filter object (vtk based)'''
|
||||
"""makePostVtkFilterWarp(document, base_vtk_result, [name]):
|
||||
creates an FEM post processing warp filter object (vtk based)"""
|
||||
obj = doc.addObject("Fem::FemPostWarpVectorFilter", name)
|
||||
tmp_filter_list = base_vtk_result.Filter
|
||||
tmp_filter_list.append(obj)
|
||||
@@ -593,8 +593,8 @@ def makePostVtkResult(
|
||||
doc, base_result,
|
||||
name="VtkResult"
|
||||
):
|
||||
'''makePostVtkResult(document, base_result [name]):
|
||||
creates an FEM post processing result object (vtk based) to hold FEM results'''
|
||||
"""makePostVtkResult(document, base_result [name]):
|
||||
creates an FEM post processing result object (vtk based) to hold FEM results"""
|
||||
obj = doc.addObject("Fem::FemPostPipeline", name)
|
||||
obj.load(base_result)
|
||||
return obj
|
||||
@@ -605,10 +605,10 @@ def makeEquationElasticity(
|
||||
doc,
|
||||
base_solver
|
||||
):
|
||||
'''makeEquationElasticity(document, base_solver):
|
||||
creates a FEM elasticity equation for a solver'''
|
||||
"""makeEquationElasticity(document, base_solver):
|
||||
creates a FEM elasticity equation for a solver"""
|
||||
obj = doc.SolverElmer.addObject(
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, 'Elasticity')
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, "Elasticity")
|
||||
)[0]
|
||||
return obj
|
||||
|
||||
@@ -617,10 +617,10 @@ def makeEquationElectrostatic(
|
||||
doc,
|
||||
base_solver
|
||||
):
|
||||
'''makeEquationElectrostatic(document, base_solver):
|
||||
creates a FEM electrostatic equation for a solver'''
|
||||
"""makeEquationElectrostatic(document, base_solver):
|
||||
creates a FEM electrostatic equation for a solver"""
|
||||
obj = doc.SolverElmer.addObject(
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, 'Electrostatic')
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, "Electrostatic")
|
||||
)[0]
|
||||
return obj
|
||||
|
||||
@@ -629,10 +629,10 @@ def makeEquationFlow(
|
||||
doc,
|
||||
base_solver
|
||||
):
|
||||
'''makeEquationFlow(document, base_solver):
|
||||
creates a FEM flow equation for a solver'''
|
||||
"""makeEquationFlow(document, base_solver):
|
||||
creates a FEM flow equation for a solver"""
|
||||
obj = doc.SolverElmer.addObject(
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, 'Flow')
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, "Flow")
|
||||
)[0]
|
||||
return obj
|
||||
|
||||
@@ -641,10 +641,10 @@ def makeEquationFluxsolver(
|
||||
doc,
|
||||
base_solver
|
||||
):
|
||||
'''makeEquationFluxsolver(document, base_solver):
|
||||
creates a FEM fluxsolver equation for a solver'''
|
||||
"""makeEquationFluxsolver(document, base_solver):
|
||||
creates a FEM fluxsolver equation for a solver"""
|
||||
obj = doc.SolverElmer.addObject(
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, 'Fluxsolver')
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, "Fluxsolver")
|
||||
)[0]
|
||||
return obj
|
||||
|
||||
@@ -653,10 +653,10 @@ def makeEquationHeat(
|
||||
doc,
|
||||
base_solver
|
||||
):
|
||||
'''makeEquationHeat(document, base_solver):
|
||||
creates a FEM heat equation for a solver'''
|
||||
"""makeEquationHeat(document, base_solver):
|
||||
creates a FEM heat equation for a solver"""
|
||||
obj = doc.SolverElmer.addObject(
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, 'Heat')
|
||||
doc.SolverElmer.Proxy.createEquation(doc.SolverElmer.Document, "Heat")
|
||||
)[0]
|
||||
return obj
|
||||
|
||||
@@ -665,8 +665,8 @@ def makeSolverCalculixCcxTools(
|
||||
doc,
|
||||
name="CalculiXccxTools"
|
||||
):
|
||||
'''makeSolverCalculixCcxTools(document, [name]):
|
||||
makes a Calculix solver object for the ccx tools module'''
|
||||
"""makeSolverCalculixCcxTools(document, [name]):
|
||||
makes a Calculix solver object for the ccx tools module"""
|
||||
obj = doc.addObject("Fem::FemSolverObjectPython", name)
|
||||
from femobjects import _FemSolverCalculix
|
||||
_FemSolverCalculix._FemSolverCalculix(obj)
|
||||
@@ -680,8 +680,8 @@ def makeSolverCalculix(
|
||||
doc,
|
||||
name="SolverCalculiX"
|
||||
):
|
||||
'''makeSolverCalculix(document, [name]):
|
||||
makes a Calculix solver object'''
|
||||
"""makeSolverCalculix(document, [name]):
|
||||
makes a Calculix solver object"""
|
||||
import femsolver.calculix.solver
|
||||
obj = femsolver.calculix.solver.create(doc, name)
|
||||
return obj
|
||||
@@ -691,8 +691,8 @@ def makeSolverElmer(
|
||||
doc,
|
||||
name="SolverElmer"
|
||||
):
|
||||
'''makeSolverElmer(document, [name]):
|
||||
makes a Elmer solver object'''
|
||||
"""makeSolverElmer(document, [name]):
|
||||
makes a Elmer solver object"""
|
||||
import femsolver.elmer.solver
|
||||
obj = femsolver.elmer.solver.create(doc, name)
|
||||
return obj
|
||||
@@ -702,21 +702,21 @@ def makeSolverZ88(
|
||||
doc,
|
||||
name="SolverZ88"
|
||||
):
|
||||
'''makeSolverZ88(document, [name]):
|
||||
makes a Z88 solver object'''
|
||||
"""makeSolverZ88(document, [name]):
|
||||
makes a Z88 solver object"""
|
||||
import femsolver.z88.solver
|
||||
obj = femsolver.z88.solver.create(doc, name)
|
||||
return obj
|
||||
|
||||
|
||||
'''
|
||||
"""
|
||||
# get the supportedTypes
|
||||
App.newDocument()
|
||||
module = 'Fem'
|
||||
FreeCADGui.doCommand('import ' + module)
|
||||
module = "Fem"
|
||||
FreeCADGui.doCommand("import " + module)
|
||||
for s in sorted(App.ActiveDocument.supportedTypes()):
|
||||
if s.startswith(module):
|
||||
print(s)
|
||||
'''
|
||||
"""
|
||||
|
||||
## @}
|
||||
|
||||
@@ -58,7 +58,7 @@ False if TestSolverFrameWork.__name__ else True
|
||||
# in tearDown method to not close the document
|
||||
|
||||
|
||||
'''
|
||||
"""
|
||||
# examples from within FreeCAD:
|
||||
# all FEM tests
|
||||
import Test, TestFem
|
||||
@@ -277,4 +277,4 @@ doc = FreeCAD.open(app_home + 'data/examples/FemCalculixCantilever3D_newSolver.F
|
||||
doc = FreeCAD.open(app_home + 'data/examples/Fem.FCStd')
|
||||
doc = FreeCAD.open(app_home + 'data/examples/Fem2.FCStd')
|
||||
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -30,6 +30,7 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import femtools.femutils as femutils
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
@@ -37,304 +38,338 @@ if FreeCAD.GuiUp:
|
||||
|
||||
|
||||
class CommandManager(object):
|
||||
def __init__(self):
|
||||
self.resources = {
|
||||
'Pixmap': 'FemWorkbench',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_Command", "Default Fem Command MenuText"),
|
||||
'Accel': "",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_Command", "Default Fem Command ToolTip")
|
||||
}
|
||||
# FIXME add option description
|
||||
self.is_active = None
|
||||
self.selobj = None
|
||||
self.selobj2 = None
|
||||
self.active_analysis = None
|
||||
|
||||
def GetResources(self):
|
||||
return self.resources
|
||||
def __init__(self):
|
||||
self.resources = {
|
||||
"Pixmap": "FemWorkbench",
|
||||
"MenuText": QtCore.QT_TRANSLATE_NOOP("Fem_Command", "Default Fem Command MenuText"),
|
||||
"Accel": "",
|
||||
"ToolTip": QtCore.QT_TRANSLATE_NOOP("Fem_Command", "Default Fem Command ToolTip")
|
||||
}
|
||||
# FIXME add option description
|
||||
self.is_active = None
|
||||
self.selobj = None
|
||||
self.selobj2 = None
|
||||
self.active_analysis = None
|
||||
|
||||
def IsActive(self):
|
||||
if not self.is_active:
|
||||
active = False
|
||||
elif self.is_active == 'allways':
|
||||
active = True
|
||||
elif self.is_active == 'with_document':
|
||||
active = FreeCADGui.ActiveDocument is not None
|
||||
elif self.is_active == 'with_analysis':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc()
|
||||
elif self.is_active == 'with_results':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc() \
|
||||
and (self.results_present() or self.result_mesh_present())
|
||||
elif self.is_active == 'with_selresult':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc() \
|
||||
and self.result_selected()
|
||||
elif self.is_active == 'with_part_feature':
|
||||
active = FreeCADGui.ActiveDocument is not None \
|
||||
and self.part_feature_selected()
|
||||
elif self.is_active == 'with_femmesh':
|
||||
active = FreeCADGui.ActiveDocument is not None \
|
||||
and self.femmesh_selected()
|
||||
elif self.is_active == 'with_gmsh_femmesh':
|
||||
active = FreeCADGui.ActiveDocument is not None \
|
||||
and self.gmsh_femmesh_selected()
|
||||
elif self.is_active == 'with_femmesh_andor_res':
|
||||
active = FreeCADGui.ActiveDocument is not None \
|
||||
and self.with_femmesh_andor_res_selected()
|
||||
elif self.is_active == 'with_material':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc() \
|
||||
and self.material_selected()
|
||||
elif self.is_active == 'with_material_solid_which_has_no_nonlinear_material':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc() \
|
||||
and self.material_solid_selected() \
|
||||
and self.has_no_nonlinear_material()
|
||||
elif self.is_active == 'with_solver':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc() \
|
||||
and self.solver_selected()
|
||||
elif self.is_active == 'with_solver_elmer':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc() \
|
||||
and self.solver_elmer_selected()
|
||||
elif self.is_active == 'with_analysis_without_solver':
|
||||
active = FemGui.getActiveAnalysis() is not None \
|
||||
and self.active_analysis_in_active_doc() \
|
||||
and not self.analysis_has_solver()
|
||||
return active
|
||||
def GetResources(self):
|
||||
return self.resources
|
||||
|
||||
def results_present(self):
|
||||
results = False
|
||||
analysis_members = FemGui.getActiveAnalysis().Group
|
||||
for o in analysis_members:
|
||||
if o.isDerivedFrom('Fem::FemResultObject'):
|
||||
results = True
|
||||
return results
|
||||
def IsActive(self):
|
||||
if not self.is_active:
|
||||
active = False
|
||||
elif self.is_active == "allways":
|
||||
active = True
|
||||
elif self.is_active == "with_document":
|
||||
active = FreeCADGui.ActiveDocument is not None
|
||||
elif self.is_active == "with_analysis":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
)
|
||||
elif self.is_active == "with_results":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
and (self.results_present() or self.result_mesh_present())
|
||||
)
|
||||
elif self.is_active == "with_selresult":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
and self.result_selected()
|
||||
)
|
||||
elif self.is_active == "with_part_feature":
|
||||
active = (
|
||||
FreeCADGui.ActiveDocument is not None
|
||||
and self.part_feature_selected()
|
||||
)
|
||||
elif self.is_active == "with_femmesh":
|
||||
active = (
|
||||
FreeCADGui.ActiveDocument is not None
|
||||
and self.femmesh_selected()
|
||||
)
|
||||
elif self.is_active == "with_gmsh_femmesh":
|
||||
active = (
|
||||
FreeCADGui.ActiveDocument is not None
|
||||
and self.gmsh_femmesh_selected()
|
||||
)
|
||||
elif self.is_active == "with_femmesh_andor_res":
|
||||
active = (
|
||||
FreeCADGui.ActiveDocument is not None
|
||||
and self.with_femmesh_andor_res_selected()
|
||||
)
|
||||
elif self.is_active == "with_material":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
and self.material_selected()
|
||||
)
|
||||
elif self.is_active == "with_material_solid_which_has_no_nonlinear_material":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
and self.material_solid_selected()
|
||||
and self.has_no_nonlinear_material()
|
||||
)
|
||||
elif self.is_active == "with_solver":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
and self.solver_selected()
|
||||
)
|
||||
elif self.is_active == "with_solver_elmer":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
and self.solver_elmer_selected()
|
||||
)
|
||||
elif self.is_active == "with_analysis_without_solver":
|
||||
active = (
|
||||
FemGui.getActiveAnalysis() is not None
|
||||
and self.active_analysis_in_active_doc()
|
||||
and not self.analysis_has_solver()
|
||||
)
|
||||
return active
|
||||
|
||||
def result_mesh_present(self):
|
||||
result_mesh = False
|
||||
analysis_members = FemGui.getActiveAnalysis().Group
|
||||
for o in analysis_members:
|
||||
if femutils.is_of_type(o, 'Fem::FemMeshResult'):
|
||||
result_mesh = True
|
||||
return result_mesh
|
||||
def results_present(self):
|
||||
results = False
|
||||
analysis_members = FemGui.getActiveAnalysis().Group
|
||||
for o in analysis_members:
|
||||
if o.isDerivedFrom("Fem::FemResultObject"):
|
||||
results = True
|
||||
return results
|
||||
|
||||
def result_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemResultObject"):
|
||||
for o in FemGui.getActiveAnalysis().Group:
|
||||
if o == sel[0]:
|
||||
self.selobj = o
|
||||
return True
|
||||
def result_mesh_present(self):
|
||||
result_mesh = False
|
||||
analysis_members = FemGui.getActiveAnalysis().Group
|
||||
for o in analysis_members:
|
||||
if femutils.is_of_type(o, "Fem::FemMeshResult"):
|
||||
result_mesh = True
|
||||
return result_mesh
|
||||
|
||||
def result_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemResultObject"):
|
||||
for o in FemGui.getActiveAnalysis().Group:
|
||||
if o == sel[0]:
|
||||
self.selobj = o
|
||||
return True
|
||||
return False
|
||||
|
||||
def part_feature_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Part::Feature"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def part_feature_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Part::Feature"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def femmesh_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemMeshObject"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def gmsh_femmesh_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 \
|
||||
and hasattr(sel[0], "Proxy") \
|
||||
and sel[0].Proxy.Type == "Fem::FemMeshGmsh":
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def material_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("App::MaterialObjectPython"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def material_solid_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 \
|
||||
and sel[0].isDerivedFrom("App::MaterialObjectPython") \
|
||||
and hasattr(sel[0], "Category") \
|
||||
and sel[0].Category == "Solid":
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def has_no_nonlinear_material(self):
|
||||
"check if an nonlinear material exists which is already based on the selected material"
|
||||
for o in FreeCAD.ActiveDocument.Objects:
|
||||
if hasattr(o, "Proxy") \
|
||||
and o.Proxy is not None \
|
||||
and o.Proxy.Type == "Fem::MaterialMechanicalNonlinear" \
|
||||
and o.LinearBaseMaterial == self.selobj:
|
||||
FreeCAD.Console.PrintError(
|
||||
'{} is based on the selected material: {}. '
|
||||
'Only one nonlinear object for each material allowed.\n'
|
||||
.format(o.Name, self.selobj)
|
||||
)
|
||||
return False
|
||||
def femmesh_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemMeshObject"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def with_femmesh_andor_res_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemMeshObject"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
elif len(sel) == 2:
|
||||
if(sel[0].isDerivedFrom("Fem::FemMeshObject")):
|
||||
if(sel[1].isDerivedFrom("Fem::FemResultObject")):
|
||||
self.selobj = sel[0] # mesh
|
||||
self.selobj2 = sel[1] # res
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
elif(sel[1].isDerivedFrom("Fem::FemMeshObject")):
|
||||
if(sel[0].isDerivedFrom("Fem::FemResultObject")):
|
||||
self.selobj = sel[1] # mesh
|
||||
self.selobj2 = sel[0] # res
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def gmsh_femmesh_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if (
|
||||
len(sel) == 1
|
||||
and hasattr(sel[0], "Proxy")
|
||||
and sel[0].Proxy.Type == "Fem::FemMeshGmsh"
|
||||
):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def material_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("App::MaterialObjectPython"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def material_solid_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if (
|
||||
len(sel) == 1
|
||||
and sel[0].isDerivedFrom("App::MaterialObjectPython")
|
||||
and hasattr(sel[0], "Category")
|
||||
and sel[0].Category == "Solid"
|
||||
):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def has_no_nonlinear_material(self):
|
||||
"check if an nonlinear material exists which is already based on the selected material"
|
||||
for o in FreeCAD.ActiveDocument.Objects:
|
||||
if (
|
||||
hasattr(o, "Proxy")
|
||||
and o.Proxy is not None
|
||||
and o.Proxy.Type == "Fem::MaterialMechanicalNonlinear"
|
||||
and o.LinearBaseMaterial == self.selobj
|
||||
):
|
||||
FreeCAD.Console.PrintError(
|
||||
"{} is based on the selected material: {}. "
|
||||
"Only one nonlinear object for each material allowed.\n"
|
||||
.format(o.Name, self.selobj)
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
def with_femmesh_andor_res_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemMeshObject"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
elif len(sel) == 2:
|
||||
if sel[0].isDerivedFrom("Fem::FemMeshObject"):
|
||||
if sel[1].isDerivedFrom("Fem::FemResultObject"):
|
||||
self.selobj = sel[0] # mesh
|
||||
self.selobj2 = sel[1] # res
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
elif sel[1].isDerivedFrom("Fem::FemMeshObject"):
|
||||
if sel[0].isDerivedFrom("Fem::FemResultObject"):
|
||||
self.selobj = sel[1] # mesh
|
||||
self.selobj2 = sel[0] # res
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
def active_analysis_in_active_doc(self):
|
||||
analysis = FemGui.getActiveAnalysis()
|
||||
if analysis.Document is FreeCAD.ActiveDocument:
|
||||
self.active_analysis = analysis
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def active_analysis_in_active_doc(self):
|
||||
analysis = FemGui.getActiveAnalysis()
|
||||
if analysis.Document is FreeCAD.ActiveDocument:
|
||||
self.active_analysis = analysis
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def solver_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemSolverObjectPython"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def solver_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemSolverObjectPython"):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def solver_elmer_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) == 1 \
|
||||
and hasattr(sel[0], "Proxy") \
|
||||
and sel[0].Proxy.Type == "Fem::FemSolverObjectElmer":
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def solver_elmer_selected(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if (
|
||||
len(sel) == 1
|
||||
and hasattr(sel[0], "Proxy")
|
||||
and sel[0].Proxy.Type == "Fem::FemSolverObjectElmer"
|
||||
):
|
||||
self.selobj = sel[0]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def analysis_has_solver(self):
|
||||
solver = False
|
||||
analysis_members = FemGui.getActiveAnalysis().Group
|
||||
for o in analysis_members:
|
||||
if o.isDerivedFrom("Fem::FemSolverObjectPython"):
|
||||
solver = True
|
||||
if solver is True:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def analysis_has_solver(self):
|
||||
solver = False
|
||||
analysis_members = FemGui.getActiveAnalysis().Group
|
||||
for o in analysis_members:
|
||||
if o.isDerivedFrom("Fem::FemSolverObjectPython"):
|
||||
solver = True
|
||||
if solver is True:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def hide_meshes_show_parts_constraints(self):
|
||||
if FreeCAD.GuiUp:
|
||||
for acnstrmesh in FemGui.getActiveAnalysis().Group:
|
||||
if "Constraint" in acnstrmesh.TypeId:
|
||||
acnstrmesh.ViewObject.Visibility = True
|
||||
if "Mesh" in acnstrmesh.TypeId:
|
||||
# OvG: Hide meshes and show constraints and meshed part
|
||||
# e.g. on purging results
|
||||
acnstrmesh.ViewObject.Visibility = False
|
||||
def hide_meshes_show_parts_constraints(self):
|
||||
if FreeCAD.GuiUp:
|
||||
for acnstrmesh in FemGui.getActiveAnalysis().Group:
|
||||
if "Constraint" in acnstrmesh.TypeId:
|
||||
acnstrmesh.ViewObject.Visibility = True
|
||||
if "Mesh" in acnstrmesh.TypeId:
|
||||
# OvG: Hide meshes and show constraints and meshed part
|
||||
# e.g. on purging results
|
||||
acnstrmesh.ViewObject.Visibility = False
|
||||
|
||||
# ****************************************************************************************
|
||||
# methods to add the objects to the document in FreeCADGui mode
|
||||
# ****************************************************************************************
|
||||
# methods to add the objects to the document in FreeCADGui mode
|
||||
|
||||
def add_obj_on_gui_set_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
|
||||
"make{}(FreeCAD.ActiveDocument))"
|
||||
.format(objtype)
|
||||
)
|
||||
# no other obj should be selected if we go in task panel
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.doCommand(
|
||||
"FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)"
|
||||
)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
def add_obj_on_gui_set_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
|
||||
"make{}(FreeCAD.ActiveDocument))"
|
||||
.format(objtype)
|
||||
)
|
||||
# no other obj should be selected if we go in task panel
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.doCommand(
|
||||
"FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)"
|
||||
)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def add_obj_on_gui_noset_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
|
||||
"make{}(FreeCAD.ActiveDocument))"
|
||||
.format(objtype)
|
||||
)
|
||||
# FreeCAD.ActiveDocument.commitTransaction() # solver command class had this line
|
||||
# no clear selection is done
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
def add_obj_on_gui_noset_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
|
||||
"make{}(FreeCAD.ActiveDocument))"
|
||||
.format(objtype)
|
||||
)
|
||||
# FreeCAD.ActiveDocument.commitTransaction() # solver command class had this line
|
||||
# no clear selection is done
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def add_obj_on_gui_selobj_set_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"ObjectsFem.make{}("
|
||||
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})"
|
||||
.format(objtype, self.selobj.Name)
|
||||
)
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.doCommand(
|
||||
"FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)"
|
||||
)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
def add_obj_on_gui_selobj_set_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"ObjectsFem.make{}("
|
||||
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})"
|
||||
.format(objtype, self.selobj.Name)
|
||||
)
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.doCommand(
|
||||
"FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)"
|
||||
)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def add_obj_on_gui_selobj_noset_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"ObjectsFem.make{}("
|
||||
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})"
|
||||
.format(objtype, self.selobj.Name)
|
||||
)
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def add_obj_on_gui_selobj_noset_edit(self, objtype):
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
"Create Fem{}"
|
||||
.format(objtype)
|
||||
)
|
||||
FreeCADGui.addModule(
|
||||
"ObjectsFem"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
"ObjectsFem.make{}("
|
||||
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})"
|
||||
.format(objtype, self.selobj.Name)
|
||||
)
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
## @}
|
||||
|
||||
@@ -803,9 +803,13 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
|
||||
ccx_stdout = None
|
||||
ccx_stderr = None
|
||||
try:
|
||||
p = subprocess.Popen([self.ccx_binary], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=False,
|
||||
startupinfo=startup_info)
|
||||
p = subprocess.Popen(
|
||||
[self.ccx_binary],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
shell=False,
|
||||
startupinfo=startup_info
|
||||
)
|
||||
ccx_stdout, ccx_stderr = p.communicate()
|
||||
if ccx_binary_sig in str(ccx_stdout):
|
||||
self.ccx_binary_present = True
|
||||
@@ -861,9 +865,13 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
|
||||
cwd = QtCore.QDir.currentPath()
|
||||
f = QtCore.QFileInfo(self.inp_file_name)
|
||||
QtCore.QDir.setCurrent(f.path())
|
||||
p = subprocess.Popen([self.ccx_binary, "-i ", f.baseName()],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
shell=False, env=_env)
|
||||
p = subprocess.Popen(
|
||||
[self.ccx_binary, "-i ", f.baseName()],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
shell=False,
|
||||
env=_env
|
||||
)
|
||||
self.ccx_stdout, self.ccx_stderr = p.communicate()
|
||||
if sys.version_info.major >= 3:
|
||||
self.ccx_stdout = self.ccx_stdout.decode()
|
||||
@@ -884,9 +892,13 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject):
|
||||
ccx_stdout = None
|
||||
ccx_stderr = None
|
||||
# Now extract the version number
|
||||
p = subprocess.Popen([self.ccx_binary, '-v'], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=False,
|
||||
startupinfo=startup_info)
|
||||
p = subprocess.Popen(
|
||||
[self.ccx_binary, '-v'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
shell=False,
|
||||
startupinfo=startup_info
|
||||
)
|
||||
ccx_stdout, ccx_stderr = p.communicate()
|
||||
if sys.version_info.major >= 3:
|
||||
ccx_stdout = ccx_stdout.decode()
|
||||
|
||||
@@ -141,8 +141,17 @@ class ObjectOp(PathOp.ObjectOp):
|
||||
|
||||
if shape.ShapeType == 'Edge' and type(shape.Curve) == Part.Circle:
|
||||
return shape.Curve.Radius * 2
|
||||
|
||||
# for all other shapes the diameter is just the dimension in X
|
||||
|
||||
if shape.ShapeType == 'Face':
|
||||
for i in range(len(shape.Edges)):
|
||||
if (type(shape.Edges[i].Curve) == Part.Circle and
|
||||
shape.Edges[i].Curve.Radius * 2 < shape.BoundBox.XLength*1.1 and
|
||||
shape.Edges[i].Curve.Radius * 2 > shape.BoundBox.XLength*0.9):
|
||||
return shape.Edges[i].Curve.Radius * 2
|
||||
|
||||
|
||||
# for all other shapes the diameter is just the dimension in X. This may be inaccurate as the BoundBox is calculated on the tesselated geometry
|
||||
PathLog.warning(translate("Path", "Hole diameter may be inaccurate due to tessellation on face. Consider selecting hole edge."))
|
||||
return shape.BoundBox.XLength
|
||||
except Part.OCCError as e:
|
||||
PathLog.error(e)
|
||||
|
||||
@@ -45,10 +45,10 @@ QGIArrow::QGIArrow() :
|
||||
m_fill(Qt::SolidPattern),
|
||||
m_size(5.0),
|
||||
m_style(0),
|
||||
m_flipped(false),
|
||||
m_dirMode(false),
|
||||
m_dir(Base::Vector3d(1.0,0.0,0.0))
|
||||
{
|
||||
isFlipped = false;
|
||||
m_brush.setStyle(m_fill);
|
||||
|
||||
setCacheMode(QGraphicsItem::NoCache);
|
||||
@@ -57,43 +57,38 @@ QGIArrow::QGIArrow() :
|
||||
setFlag(QGraphicsItem::ItemIsMovable, false);
|
||||
}
|
||||
|
||||
|
||||
void QGIArrow::flip(bool state) {
|
||||
isFlipped = state;
|
||||
}
|
||||
|
||||
void QGIArrow::draw() {
|
||||
QPainterPath path;
|
||||
if (m_style == 0) {
|
||||
if (m_dirMode) {
|
||||
path = makeFilledTriangle(getDirection(), m_size,m_size/6.0);
|
||||
} else {
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //"arrow l/w sb 3/1" ??
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped()); //"arrow l/w sb 3/1" ??
|
||||
}
|
||||
} else if (m_style == 1) {
|
||||
if (m_dirMode) {
|
||||
path = makeOpenArrow(getDirection(), m_size,m_size/3.0); //broad arrow?
|
||||
} else {
|
||||
path = makeOpenArrow(m_size,m_size/3.0,isFlipped);
|
||||
path = makeOpenArrow(m_size,m_size/3.0,isFlipped());
|
||||
}
|
||||
} else if (m_style == 2) {
|
||||
if (m_dirMode) {
|
||||
path = makeHashMark(getDirection(), m_size/2.0,m_size/2.0); //big enough?
|
||||
} else {
|
||||
path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped); //big enough?
|
||||
path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped()); //big enough?
|
||||
}
|
||||
} else if (m_style == 3) {
|
||||
path = makeDot(m_size/2.0,m_size/2.0,isFlipped);
|
||||
path = makeDot(m_size/2.0,m_size/2.0,isFlipped());
|
||||
} else if (m_style == 4) {
|
||||
path = makeOpenDot(m_size/2.0,m_size/2.0,isFlipped);
|
||||
path = makeOpenDot(m_size/2.0,m_size/2.0,isFlipped());
|
||||
} else if (m_style == 5) {
|
||||
if (m_dirMode) {
|
||||
path = makeForkArrow(getDirection(), m_size/2.0,m_size/2.0); //big enough?
|
||||
} else {
|
||||
path = makeForkArrow(m_size/2.0,m_size/2.0,isFlipped); //big enough?
|
||||
path = makeForkArrow(m_size/2.0,m_size/2.0,isFlipped()); //big enough?
|
||||
}
|
||||
} else {
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //sb a question mark or ???
|
||||
path = makeFilledTriangle(m_size,m_size/6.0,isFlipped()); //sb a question mark or ???
|
||||
}
|
||||
setPath(path);
|
||||
}
|
||||
|
||||
@@ -46,15 +46,18 @@ public:
|
||||
|
||||
public:
|
||||
void draw();
|
||||
void flip(bool state);
|
||||
bool isFlipped() { return m_flipped; }
|
||||
void setFlipped(bool flipped) { m_flipped = flipped; }
|
||||
void flip() { m_flipped = !m_flipped; }
|
||||
double getSize() { return m_size; }
|
||||
void setSize(double s);
|
||||
int getStyle() { return m_style; }
|
||||
void setStyle(int s) { m_style = s; }
|
||||
bool getDirMode() { return m_dirMode; }
|
||||
void setDirMode(bool b) { m_dirMode = b; }
|
||||
Base::Vector3d getDirection(void) { return m_dir; }
|
||||
Base::Vector3d getDirection(void) { return m_flipped ? -m_dir : m_dir; }
|
||||
void setDirection(Base::Vector3d v) { m_dir = v; }
|
||||
void setDirection(double angle) { m_dir = Base::Vector3d(cos(angle), sin(angle), 0.0); }
|
||||
static int getPrefArrowStyle();
|
||||
static double getPrefArrowSize();
|
||||
static double getOverlapAdjust(int style, double size);
|
||||
@@ -78,7 +81,7 @@ private:
|
||||
Qt::BrushStyle m_fill;
|
||||
double m_size;
|
||||
int m_style;
|
||||
bool isFlipped;
|
||||
bool m_flipped;
|
||||
bool m_dirMode;
|
||||
Base::Vector3d m_dir;
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
# include <QPaintDevice>
|
||||
# include <QSvgGenerator>
|
||||
|
||||
# include <math.h>
|
||||
# include <cmath>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
@@ -69,6 +69,11 @@
|
||||
#include "ViewProviderDimension.h"
|
||||
#include "DrawGuiUtil.h"
|
||||
|
||||
#ifndef M_2PI
|
||||
// #define M_2PI 6.283185307179586476925287
|
||||
#define M_2PI (M_PI * 2.0)
|
||||
#endif
|
||||
|
||||
//TODO: hide the Qt coord system (+y down).
|
||||
|
||||
using namespace TechDraw;
|
||||
@@ -182,8 +187,7 @@ void QGIDatumLabel::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
|
||||
QStyleOptionGraphicsItem myOption(*option);
|
||||
myOption.state &= ~QStyle::State_Selected;
|
||||
|
||||
// painter->drawRect(boundingRect()); //good for debugging
|
||||
|
||||
//painter->drawRect(boundingRect()); //good for debugging
|
||||
}
|
||||
|
||||
void QGIDatumLabel::setPosFromCenter(const double &xCenter, const double &yCenter)
|
||||
@@ -1171,127 +1175,13 @@ void QGIViewDimension::draw()
|
||||
// dim->getViewPart()->addVertex(curveCenter,true);
|
||||
// }
|
||||
} else if(strcmp(dimType, "Radius") == 0) {
|
||||
// preferred terminology: Dimension Text, Dimension Line(s), Extension Lines, Arrowheads
|
||||
// radius gets 1 dimension line from the dimension text to a point on the curve
|
||||
Base::Vector3d pointOnCurve,curveCenter;
|
||||
double radius;
|
||||
arcPoints pts = dim->getArcPoints();
|
||||
bool isArc = pts.isArc;
|
||||
radius = Rez::guiX(pts.radius);
|
||||
curveCenter = Rez::guiX(pts.center);
|
||||
pointOnCurve = Rez::guiX(pts.onCurve.first);
|
||||
QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect());
|
||||
lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0);
|
||||
|
||||
// Note Bounding Box size is not the same width or height as text (only used for finding center)
|
||||
float bbX = datumLabel->boundingRect().width();
|
||||
float bbY = datumLabel->boundingRect().height();
|
||||
datumLabel->setTransformOriginPoint(bbX / 2, bbY /2);
|
||||
datumLabel->setRotation(0.0); //label is always right side up & horizontal
|
||||
|
||||
//if inside the arc (len(DimLine < radius)) arrow goes from center to edge away from label
|
||||
//if outside the arc arrow kinks, then goes to edge nearest label
|
||||
bool outerPlacement = false;
|
||||
if ((lblCenter - curveCenter).Length() > radius) { //label is outside circle
|
||||
outerPlacement = true;
|
||||
if (prefRadiusAligned() == 0) { //ISO
|
||||
drawRadiusAligned(dim, vp);
|
||||
} else if (prefRadiusAligned() == 1) { //ASME
|
||||
drawRadiusUniform(dim, vp);
|
||||
} else {
|
||||
Base::Console().Error("QGIVD::draw - bad radiusAligned pref: %d\n", prefRadiusAligned());
|
||||
}
|
||||
|
||||
Base::Vector3d dirDimLine = (lblCenter - curveCenter).Normalize();
|
||||
if (fabs(dirDimLine.Length()) < (Precision::Confusion())) {
|
||||
dirDimLine = Base::Vector3d(-1.0,0.0,0.0);
|
||||
}
|
||||
// Base::Vector3d adjustDir = dirDimLine; //adjust line lengths for arrowheads
|
||||
double dimLineAdjust = Rez::guiX(QGIArrow::getOverlapAdjust(QGIArrow::getPrefArrowStyle(),
|
||||
QGIArrow::getPrefArrowSize()));
|
||||
|
||||
|
||||
Base::Vector3d dLineStart;
|
||||
Base::Vector3d dLineEnd; //?? radius draws line from text to curve?? (diam is curve to text!)
|
||||
Base::Vector3d kinkPoint;
|
||||
margin = Rez::guiX(5.f); //space around label
|
||||
double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)???
|
||||
if (outerPlacement) {
|
||||
double offset = getDefaultTextHorizontalOffset(lblCenter.x > curveCenter.x);
|
||||
dLineStart.y = lblCenter.y;
|
||||
dLineStart.x = lblCenter.x + offset; //start at right or left of label
|
||||
kinkLength = (lblCenter.x < curveCenter.x) ? kinkLength : -kinkLength;
|
||||
kinkPoint.y = dLineStart.y;
|
||||
kinkPoint.x = dLineStart.x + kinkLength;
|
||||
pointOnCurve = curveCenter + (kinkPoint - curveCenter).Normalize() * radius;
|
||||
dLineEnd = pointOnCurve + (kinkPoint - curveCenter).Normalize() * dimLineAdjust;
|
||||
if ((kinkPoint - curveCenter).Length() < radius) {
|
||||
dirDimLine = (curveCenter - kinkPoint).Normalize();
|
||||
} else {
|
||||
dirDimLine = (kinkPoint - curveCenter).Normalize();
|
||||
}
|
||||
} else {
|
||||
dLineStart = curveCenter - dirDimLine * margin; //just beyond centerpoint
|
||||
pointOnCurve = curveCenter - dirDimLine * radius;
|
||||
dLineEnd = pointOnCurve + dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart; //no kink
|
||||
}
|
||||
|
||||
//handle partial arc weird cases
|
||||
if (isArc) {
|
||||
Base::Vector3d midPt = Rez::guiX(pts.midArc);
|
||||
Base::Vector3d startPt = Rez::guiX(pts.arcEnds.first);
|
||||
Base::Vector3d endPt = Rez::guiX(pts.arcEnds.second);
|
||||
if (outerPlacement &&
|
||||
!dim->leaderIntersectsArc(Rez::appX(curveCenter),Rez::appX(kinkPoint))) { //keep pathological case within arc
|
||||
pointOnCurve = midPt;
|
||||
} else if (!outerPlacement) {
|
||||
if ((midPt - lblCenter).Length() > (midPt - curveCenter).Length()) { //label is farther than center
|
||||
dirDimLine = dirDimLine * -1;
|
||||
}
|
||||
dLineStart = curveCenter + dirDimLine * margin;
|
||||
pointOnCurve = curveCenter + dirDimLine * radius;
|
||||
dLineEnd = pointOnCurve - dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart;
|
||||
if (!dim->leaderIntersectsArc(Rez::appX(dLineStart),Rez::appX(pointOnCurve))) { //keep pathological case within arc
|
||||
if ((pointOnCurve - endPt).Length() < (pointOnCurve - startPt).Length()) {
|
||||
if (!pts.arcCW ) {
|
||||
pointOnCurve = endPt;
|
||||
} else {
|
||||
pointOnCurve = startPt;
|
||||
}
|
||||
} else {
|
||||
if (!pts.arcCW ) {
|
||||
pointOnCurve = startPt;
|
||||
} else {
|
||||
pointOnCurve = endPt;
|
||||
}
|
||||
}
|
||||
dLineStart = curveCenter + (pointOnCurve - curveCenter).Normalize() * margin;
|
||||
dLineEnd = pointOnCurve - dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPainterPath dLinePath; //radius dimension line path
|
||||
dLinePath.moveTo(dLineStart.x, dLineStart.y);
|
||||
dLinePath.lineTo(kinkPoint.x, kinkPoint.y);
|
||||
dLinePath.lineTo(dLineEnd.x, dLineEnd.y);
|
||||
|
||||
dimLines->setPath(dLinePath);
|
||||
//NOTE: in this case aHead1->dirMode is false and Qt rotation is used to point arrowhead
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead1->draw();
|
||||
|
||||
Base::Vector3d ar1Pos = pointOnCurve;
|
||||
Base::Vector3d dirArrowLine = (pointOnCurve - kinkPoint).Normalize();
|
||||
float arAngle = atan2(dirArrowLine.y, dirArrowLine.x) * 180 / M_PI;
|
||||
|
||||
aHead1->setPos(ar1Pos.x, ar1Pos.y);
|
||||
aHead1->setRotation(arAngle);
|
||||
aHead1->show();
|
||||
aHead2->hide();
|
||||
// if (dim->CentreLines.getValue()) {
|
||||
// curveCenterMark->setPos(curveCenter.x,curveCenter.y);
|
||||
// centerMark->show();
|
||||
// dim->getViewPart()->addVertex(curveCenter,true);
|
||||
// }
|
||||
} else if( (strcmp(dimType, "Angle") == 0) ||
|
||||
(strcmp(dimType, "Angle3Pt") == 0)) {
|
||||
anglePoints pts = dim->getAnglePoints();
|
||||
@@ -1408,7 +1298,7 @@ void QGIViewDimension::draw()
|
||||
dimLines->setPath(path);
|
||||
|
||||
//NOTE: arrowheads are dirMode(false)
|
||||
aHead1->flip(true);
|
||||
aHead1->setFlipped(true);
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead1->draw();
|
||||
@@ -1489,6 +1379,420 @@ void QGIViewDimension::draw()
|
||||
}
|
||||
}
|
||||
|
||||
int QGIViewDimension::classifyPointToArcPosition(double pointDistance, double pointAngle,
|
||||
double radius, double startAngle, double endAngle, bool clockwise) const
|
||||
{
|
||||
if (angleWithinSector(pointAngle, startAngle, endAngle, clockwise)) {
|
||||
return pointDistance > radius ? OUTER_SECTOR : INNER_SECTOR;
|
||||
}
|
||||
|
||||
if (angleWithinSector(addAngles(pointAngle, M_PI), startAngle, endAngle, clockwise)) {
|
||||
return OPPOSITE_SECTOR;
|
||||
}
|
||||
|
||||
return COMPLEMENT_SECTOR;
|
||||
}
|
||||
|
||||
double QGIViewDimension::computeLineAndLabelAngles(Base::Vector3d lineTarget, Base::Vector3d labelCenter,
|
||||
double lineLabelDistance, double &lineAngle, double &labelAngle) const
|
||||
{
|
||||
// By default horizontal line and no label rotation
|
||||
lineAngle = 0.0;
|
||||
labelAngle = 0.0;
|
||||
|
||||
Base::Vector3d rawDirection(labelCenter - lineTarget);
|
||||
double rawDistance = rawDirection.Length();
|
||||
if (rawDistance < Precision::Confusion()) { // Almost single point, can't tell
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double rawAngle = atan2(rawDirection.y, rawDirection.x);
|
||||
lineAngle = rawAngle;
|
||||
|
||||
// If we are too close to the line origin, no further adjustments
|
||||
if (lineLabelDistance >= rawDistance) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Rotate the line by angle between the label rectangle center and label bottom side center
|
||||
double devAngle = getStandardLinePlacement(rawAngle)*asin(lineLabelDistance/rawDistance);
|
||||
lineAngle = addAngles(lineAngle, devAngle);
|
||||
|
||||
labelAngle = devAngle > 0.0 ? lineAngle : addAngles(lineAngle, M_PI);
|
||||
|
||||
return devAngle;
|
||||
}
|
||||
|
||||
Base::Vector3d QGIViewDimension::computeLineOriginPoint(Base::Vector3d lineTarget, double projectedLabelDistance,
|
||||
double lineAngle, double labelWidth, double direction) const
|
||||
{
|
||||
return lineTarget + (projectedLabelDistance + direction*(0.5*labelWidth + getDefaultReferenceLineOverhang()))
|
||||
*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
}
|
||||
|
||||
//draw a Radius dimension using "aligned" convention (ISO)
|
||||
void QGIViewDimension::drawRadiusAligned(TechDraw::DrawViewDimension *dimension,
|
||||
ViewProviderDimension *viewProvider) const
|
||||
{
|
||||
// Preferred terminology according to ISO 129-1 for Radius:
|
||||
// Dimensional Value, Leader Line, Reference Line, Terminator
|
||||
|
||||
QPainterPath radiusPath;
|
||||
aHead1->setFlipped(false);
|
||||
|
||||
datumLabel->setRotation(0.0);
|
||||
QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect());
|
||||
Base::Vector3d labelCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0);
|
||||
|
||||
arcPoints curvePoints = dimension->getArcPoints();
|
||||
|
||||
Base::Vector3d curveCenter = Rez::guiX(curvePoints.center);
|
||||
double mappedRadius = Rez::guiX(curvePoints.radius);
|
||||
double centerDistance = (labelCenter - curveCenter).Length();
|
||||
|
||||
double arcStartAngle;
|
||||
double arcEndAngle;
|
||||
bool arcClockwise;
|
||||
if (curvePoints.isArc) {
|
||||
arcStartAngle = atan2(curvePoints.arcEnds.first.y - curvePoints.center.y,
|
||||
curvePoints.arcEnds.first.x - curvePoints.center.x);
|
||||
arcEndAngle = atan2(curvePoints.arcEnds.second.y - curvePoints.center.y,
|
||||
curvePoints.arcEnds.second.x - curvePoints.center.x);
|
||||
arcClockwise = !curvePoints.arcCW;
|
||||
}
|
||||
else { // A circle arc covers the whole plane
|
||||
arcStartAngle = -M_PI;
|
||||
arcEndAngle = +M_PI;
|
||||
arcClockwise = false;
|
||||
}
|
||||
|
||||
double labelAngle = 0.0;
|
||||
Base::Vector3d arcPoint;
|
||||
double lineAngle;
|
||||
|
||||
//TODO: does this violate "Aligned" convention?
|
||||
if (viewProvider->TiltText.getValue()) { // We may rotate the label so no reference line is needed
|
||||
double devAngle = computeLineAndLabelAngles(curveCenter, labelCenter,
|
||||
getDefaultTextVerticalOffset(), lineAngle, labelAngle);
|
||||
// Correct the label center distance projected on the leader line
|
||||
centerDistance *= cos(devAngle);
|
||||
|
||||
Base::Vector3d originPoint;
|
||||
Base::Vector3d targetPoint;
|
||||
switch (classifyPointToArcPosition(centerDistance, lineAngle, mappedRadius,
|
||||
arcStartAngle, arcEndAngle, arcClockwise)) {
|
||||
case INNER_SECTOR: {
|
||||
// The label is placed within the arc sector angle, there's always point
|
||||
// on the arc where the leader line can cross it perpendicularly
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
|
||||
if (viewProvider->ExtendToCenter.getValue()) { // Start in the very center
|
||||
originPoint = curveCenter;
|
||||
}
|
||||
else { // Start on the label side closer to the center
|
||||
originPoint = computeLineOriginPoint(curveCenter, centerDistance, lineAngle,
|
||||
mappedRect.width(), -1.0);
|
||||
}
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
}
|
||||
case OUTER_SECTOR: {
|
||||
// Same situation as when on the inner side of sector
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
aHead1->flip();
|
||||
|
||||
originPoint = computeLineOriginPoint(curveCenter, centerDistance, lineAngle,
|
||||
mappedRect.width(), +1.0);
|
||||
// If leader line shall not be extended to the center, start on the arc projection
|
||||
targetPoint = viewProvider->ExtendToCenter.getValue() ? curveCenter : arcPoint;
|
||||
break;
|
||||
}
|
||||
case OPPOSITE_SECTOR: {
|
||||
// If the label is placed within the vertically opposite angle of the arc sector,
|
||||
// the leader line passing through the arc center can mark a point on the arc
|
||||
arcPoint = curveCenter - mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
aHead1->flip();
|
||||
|
||||
originPoint = computeLineOriginPoint(curveCenter, centerDistance, lineAngle,
|
||||
mappedRect.width(), +1.0);
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Label outside both arc wedges
|
||||
arcPoint = Rez::guiX(curvePoints.midArc);
|
||||
aHead1->flip();
|
||||
devAngle = computeLineAndLabelAngles(arcPoint, labelCenter,
|
||||
getDefaultTextVerticalOffset(), lineAngle, labelAngle);
|
||||
centerDistance = (labelCenter - arcPoint).Length()*cos(devAngle);
|
||||
|
||||
originPoint = computeLineOriginPoint(arcPoint, centerDistance, lineAngle,
|
||||
mappedRect.width(), +1.0);
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw only the leader line from start point to end point
|
||||
radiusPath.moveTo(originPoint.x, originPoint.y);
|
||||
radiusPath.lineTo(targetPoint.x, targetPoint.y);
|
||||
}
|
||||
else { // The dimensional value text must stay horizontal
|
||||
Base::Vector3d leftJoint(mappedRect.left() - getDefaultReferenceLineOverhang(),
|
||||
labelCenter.y + getDefaultTextVerticalOffset(), 0.0);
|
||||
Base::Vector3d rightJoint(mappedRect.right() + getDefaultReferenceLineOverhang(),
|
||||
labelCenter.y + getDefaultTextVerticalOffset(), 0.0);
|
||||
|
||||
double leftAngle = atan2(leftJoint.y - curveCenter.y, leftJoint.x - curveCenter.x);
|
||||
double rightAngle = atan2(rightJoint.y - curveCenter.y, rightJoint.x - curveCenter.x);
|
||||
|
||||
int leftPosition = classifyPointToArcPosition((leftJoint - curveCenter).Length(),
|
||||
leftAngle, mappedRadius, arcStartAngle, arcEndAngle, arcClockwise);
|
||||
int rightPosition = classifyPointToArcPosition((rightJoint - curveCenter).Length(),
|
||||
rightAngle, mappedRadius, arcStartAngle, arcEndAngle, arcClockwise);
|
||||
|
||||
Base::Vector3d originPoint;
|
||||
Base::Vector3d jointPoint;
|
||||
Base::Vector3d targetPoint;
|
||||
if (leftPosition >= OPPOSITE_SECTOR || rightPosition >= OPPOSITE_SECTOR) {
|
||||
// At least from one of the reference line sides can run the leader line
|
||||
// perpendicularly to the arc, i.e. in direction to the center
|
||||
if (leftPosition >= OPPOSITE_SECTOR && rightPosition >= OPPOSITE_SECTOR) {
|
||||
// Both are acceptable, so choose the more convenient one
|
||||
double leftBend = leftPosition == INNER_SECTOR ? M_PI - fabs(leftAngle) : fabs(leftAngle);
|
||||
double rightBend = rightPosition == INNER_SECTOR ? fabs(rightAngle) : M_PI - fabs(rightAngle);
|
||||
|
||||
// If right leader line bends less or does not cross the dimensional value,
|
||||
// use it by marking left point as outlayer
|
||||
if (leftBend <= M_PI_2 || rightBend <= M_PI_2) { // At least one line is not crossing the text
|
||||
if (rightBend < leftBend) {
|
||||
leftPosition = COMPLEMENT_SECTOR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool leftDown = leftPosition == INNER_SECTOR ? leftAngle > 0.0 : leftAngle < 0.0;
|
||||
bool rightDown = rightPosition == INNER_SECTOR ? rightAngle > 0.0 : rightAngle < 0.0;
|
||||
|
||||
if (leftDown == rightDown) { // Both lines go downwards or upwards
|
||||
if (rightBend < leftBend) {
|
||||
leftPosition = COMPLEMENT_SECTOR;
|
||||
}
|
||||
}
|
||||
else if (rightDown) {
|
||||
leftPosition = COMPLEMENT_SECTOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int resultPosition;
|
||||
if (leftPosition >= OPPOSITE_SECTOR) {
|
||||
originPoint = rightJoint;
|
||||
jointPoint = leftJoint;
|
||||
lineAngle = leftAngle;
|
||||
resultPosition = leftPosition;
|
||||
}
|
||||
else {
|
||||
originPoint = leftJoint;
|
||||
jointPoint = rightJoint;
|
||||
lineAngle = rightAngle;
|
||||
resultPosition = rightPosition;
|
||||
}
|
||||
|
||||
switch (resultPosition) {
|
||||
case INNER_SECTOR:
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
targetPoint = arcPoint;
|
||||
break;
|
||||
case OUTER_SECTOR:
|
||||
arcPoint = curveCenter + mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
// If desired, extend the target point to the center
|
||||
targetPoint = viewProvider->ExtendToCenter.getValue() ? curveCenter : arcPoint;
|
||||
aHead1->flip();
|
||||
break;
|
||||
case OPPOSITE_SECTOR:
|
||||
arcPoint = curveCenter - mappedRadius*Base::Vector3d(cos(lineAngle), sin(lineAngle), 0.0);
|
||||
targetPoint = arcPoint;
|
||||
aHead1->flip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { // Both joint points lay outside the vertical angles
|
||||
arcPoint = Rez::guiX(curvePoints.midArc);
|
||||
|
||||
if (labelCenter.x >= arcPoint.x) { // Place the dimensional value right
|
||||
originPoint = rightJoint;
|
||||
jointPoint = leftJoint;
|
||||
}
|
||||
else { // Place the dimensional value left
|
||||
originPoint = leftJoint;
|
||||
jointPoint = rightJoint;
|
||||
}
|
||||
|
||||
targetPoint = arcPoint;
|
||||
lineAngle = atan2(targetPoint.y - jointPoint.y, targetPoint.x - jointPoint.x);
|
||||
}
|
||||
|
||||
radiusPath.moveTo(originPoint.x, originPoint.y);
|
||||
radiusPath.lineTo(jointPoint.x, jointPoint.y);
|
||||
radiusPath.lineTo(targetPoint.x, targetPoint.y);
|
||||
}
|
||||
|
||||
datumLabel->setTransformOriginPoint(datumLabel->boundingRect().width()*0.5,
|
||||
datumLabel->boundingRect().height()*0.5);
|
||||
datumLabel->setRotation(labelAngle*180.0/M_PI);
|
||||
|
||||
dimLines->setPath(radiusPath);
|
||||
|
||||
aHead1->setPos(arcPoint.x, arcPoint.y);
|
||||
aHead1->setRotation(0.0);
|
||||
aHead1->setDirMode(true);
|
||||
aHead1->setDirection(lineAngle);
|
||||
if (viewProvider->FlipArrowheads.getValue()) {
|
||||
aHead1->flip();
|
||||
}
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead1->draw();
|
||||
aHead1->show();
|
||||
|
||||
aHead2->hide();
|
||||
}
|
||||
|
||||
//Draw a Radius dimension using "uniform" alignment convention (Ansi/Asme)
|
||||
void QGIViewDimension::drawRadiusUniform(TechDraw::DrawViewDimension* dim,
|
||||
TechDrawGui::ViewProviderDimension* viewProvider) const
|
||||
{
|
||||
// preferred terminology: Dimension Text, Dimension Line(s), Extension Lines, Arrowheads
|
||||
// radius gets 1 dimension line from the dimension text to a point on the curve
|
||||
aHead1->setFlipped(false);
|
||||
|
||||
Base::Vector3d pointOnCurve,curveCenter;
|
||||
double radius;
|
||||
arcPoints pts = dim->getArcPoints();
|
||||
bool isArc = pts.isArc;
|
||||
radius = Rez::guiX(pts.radius);
|
||||
curveCenter = Rez::guiX(pts.center);
|
||||
pointOnCurve = Rez::guiX(pts.onCurve.first);
|
||||
QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect());
|
||||
Base::Vector3d lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0);
|
||||
|
||||
// Note Bounding Box size is not the same width or height as text (only used for finding center)
|
||||
float bbX = datumLabel->boundingRect().width();
|
||||
float bbY = datumLabel->boundingRect().height();
|
||||
datumLabel->setTransformOriginPoint(bbX / 2, bbY /2);
|
||||
datumLabel->setRotation(0.0); //label is always right side up & horizontal
|
||||
|
||||
//if inside the arc (len(DimLine < radius)) arrow goes from center to edge away from label
|
||||
//if outside the arc arrow kinks, then goes to edge nearest label
|
||||
bool outerPlacement = false;
|
||||
if ((lblCenter - curveCenter).Length() > radius) { //label is outside circle
|
||||
outerPlacement = true;
|
||||
}
|
||||
|
||||
Base::Vector3d dirDimLine = (lblCenter - curveCenter).Normalize();
|
||||
if (fabs(dirDimLine.Length()) < (Precision::Confusion())) {
|
||||
dirDimLine = Base::Vector3d(-1.0,0.0,0.0);
|
||||
}
|
||||
// Base::Vector3d adjustDir = dirDimLine; //adjust line lengths for arrowheads
|
||||
double dimLineAdjust = Rez::guiX(QGIArrow::getOverlapAdjust(QGIArrow::getPrefArrowStyle(),
|
||||
QGIArrow::getPrefArrowSize()));
|
||||
|
||||
Base::Vector3d dLineStart;
|
||||
Base::Vector3d dLineEnd; //?? radius draws line from text to curve?? (diam is curve to text!)
|
||||
Base::Vector3d kinkPoint;
|
||||
double margin = Rez::guiX(5.f); //space around label
|
||||
double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)???
|
||||
if (outerPlacement) {
|
||||
double offset = getDefaultTextHorizontalOffset(lblCenter.x > curveCenter.x);
|
||||
dLineStart.y = lblCenter.y;
|
||||
dLineStart.x = lblCenter.x + offset; //start at right or left of label
|
||||
kinkLength = (lblCenter.x < curveCenter.x) ? kinkLength : -kinkLength;
|
||||
kinkPoint.y = dLineStart.y;
|
||||
kinkPoint.x = dLineStart.x + kinkLength;
|
||||
pointOnCurve = curveCenter + (kinkPoint - curveCenter).Normalize() * radius;
|
||||
dLineEnd = pointOnCurve + (kinkPoint - curveCenter).Normalize() * dimLineAdjust;
|
||||
if ((kinkPoint - curveCenter).Length() < radius) {
|
||||
dirDimLine = (curveCenter - kinkPoint).Normalize();
|
||||
} else {
|
||||
dirDimLine = (kinkPoint - curveCenter).Normalize();
|
||||
}
|
||||
} else {
|
||||
dLineStart = curveCenter - dirDimLine * margin; //just beyond centerpoint
|
||||
pointOnCurve = curveCenter - dirDimLine * radius;
|
||||
dLineEnd = pointOnCurve + dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart; //no kink
|
||||
}
|
||||
|
||||
//handle partial arc weird cases
|
||||
if (isArc) {
|
||||
Base::Vector3d midPt = Rez::guiX(pts.midArc);
|
||||
Base::Vector3d startPt = Rez::guiX(pts.arcEnds.first);
|
||||
Base::Vector3d endPt = Rez::guiX(pts.arcEnds.second);
|
||||
if (outerPlacement &&
|
||||
!dim->leaderIntersectsArc(Rez::appX(curveCenter),Rez::appX(kinkPoint))) { //keep pathological case within arc
|
||||
pointOnCurve = midPt;
|
||||
} else if (!outerPlacement) {
|
||||
if ((midPt - lblCenter).Length() > (midPt - curveCenter).Length()) { //label is farther than center
|
||||
dirDimLine = dirDimLine * -1;
|
||||
}
|
||||
dLineStart = curveCenter + dirDimLine * margin;
|
||||
pointOnCurve = curveCenter + dirDimLine * radius;
|
||||
dLineEnd = pointOnCurve - dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart;
|
||||
if (!dim->leaderIntersectsArc(Rez::appX(dLineStart),Rez::appX(pointOnCurve))) { //keep pathological case within arc
|
||||
if ((pointOnCurve - endPt).Length() < (pointOnCurve - startPt).Length()) {
|
||||
if (!pts.arcCW ) {
|
||||
pointOnCurve = endPt;
|
||||
} else {
|
||||
pointOnCurve = startPt;
|
||||
}
|
||||
} else {
|
||||
if (!pts.arcCW ) {
|
||||
pointOnCurve = startPt;
|
||||
} else {
|
||||
pointOnCurve = endPt;
|
||||
}
|
||||
}
|
||||
dLineStart = curveCenter + (pointOnCurve - curveCenter).Normalize() * margin;
|
||||
dLineEnd = pointOnCurve - dirDimLine * dimLineAdjust;
|
||||
kinkPoint = dLineStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPainterPath dLinePath; //radius dimension line path
|
||||
dLinePath.moveTo(dLineStart.x, dLineStart.y);
|
||||
dLinePath.lineTo(kinkPoint.x, kinkPoint.y);
|
||||
dLinePath.lineTo(dLineEnd.x, dLineEnd.y);
|
||||
|
||||
dimLines->setPath(dLinePath);
|
||||
|
||||
Base::Vector3d ar1Pos = pointOnCurve;
|
||||
Base::Vector3d dirArrowLine = (pointOnCurve - kinkPoint).Normalize();
|
||||
float arAngle = atan2(dirArrowLine.y, dirArrowLine.x) * 180 / M_PI;
|
||||
|
||||
//NOTE: in this case aHead1->dirMode is false and Qt rotation is used to point arrowhead
|
||||
aHead1->setPos(ar1Pos.x, ar1Pos.y);
|
||||
aHead1->setDirMode(false);
|
||||
aHead1->setRotation(arAngle);
|
||||
if (viewProvider->FlipArrowheads.getValue()) {
|
||||
aHead1->flip();
|
||||
}
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead1->draw();
|
||||
aHead1->show();
|
||||
|
||||
aHead2->hide();
|
||||
|
||||
// code for showCenterMark as attribute of Dimension instead of View
|
||||
// if (dim->CentreLines.getValue()) {
|
||||
// curveCenterMark->setPos(curveCenter.x,curveCenter.y);
|
||||
// centerMark->show();
|
||||
// dim->getViewPart()->addVertex(curveCenter,true);
|
||||
// }
|
||||
}
|
||||
|
||||
QColor QGIViewDimension::getNormalColor()
|
||||
{
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
@@ -1613,6 +1917,50 @@ double QGIViewDimension::getDefaultTextVerticalOffset() const
|
||||
return textMult*Rez::guiX(vp->Fontsize.getValue()) + TextOffsetFudge;
|
||||
}
|
||||
|
||||
double QGIViewDimension::getDefaultReferenceLineOverhang() const
|
||||
{
|
||||
return 2.0*TextOffsetFudge;
|
||||
}
|
||||
|
||||
double QGIViewDimension::getStandardLinePlacement(double labelAngle)
|
||||
{
|
||||
// According to ISO 129-1 Standard Figure 23, the bordering angle is 2/3 PI, resp. -1/3 PI
|
||||
// As Qt Y axis points downwards, all signs are flipped
|
||||
return labelAngle > +M_PI/3.0 || labelAngle < -2.0*M_PI/3.0
|
||||
? -1.0 : +1.0;
|
||||
}
|
||||
|
||||
bool QGIViewDimension::angleWithinSector(double testAngle, double startAngle, double endAngle, bool clockwise)
|
||||
{
|
||||
if (clockwise) {
|
||||
std::swap(startAngle, endAngle);
|
||||
}
|
||||
|
||||
if (endAngle < startAngle) {
|
||||
endAngle += M_2PI;
|
||||
}
|
||||
|
||||
if (testAngle < startAngle) {
|
||||
testAngle += M_2PI;
|
||||
}
|
||||
|
||||
return testAngle <= endAngle;
|
||||
}
|
||||
|
||||
double QGIViewDimension::addAngles(double angle1, double angle2)
|
||||
{
|
||||
angle1 += angle2;
|
||||
|
||||
if (angle2 >= 0.0) {
|
||||
if (angle1 > +M_PI) angle1 -= M_2PI;
|
||||
return angle1;
|
||||
}
|
||||
else {
|
||||
if (angle1 < -M_PI) angle1 += M_2PI;
|
||||
return angle1;
|
||||
}
|
||||
}
|
||||
|
||||
//frame, border, caption are never shown in QGIVD, so shouldn't be in bRect
|
||||
QRectF QGIViewDimension::boundingRect() const
|
||||
{
|
||||
@@ -1662,5 +2010,13 @@ void QGIViewDimension::setPens(void)
|
||||
aHead2->setWidth(m_lineWidth);
|
||||
}
|
||||
|
||||
int QGIViewDimension::prefRadiusAligned(void)
|
||||
{
|
||||
int result = 0;
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Standards");
|
||||
result = hGrp->GetInt("RadiusAligned", 0); //default to ISO
|
||||
return result;
|
||||
}
|
||||
|
||||
#include <Mod/TechDraw/Gui/moc_QGIViewDimension.cpp>
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace TechDrawGui
|
||||
class QGIArrow;
|
||||
class QGIDimLines;
|
||||
class QGIViewDimension;
|
||||
class ViewProviderDimension;
|
||||
|
||||
class QGIDatumLabel : public QGraphicsObject
|
||||
{
|
||||
@@ -154,7 +155,25 @@ public Q_SLOTS:
|
||||
void updateDim(bool obtuse = false);
|
||||
|
||||
protected:
|
||||
|
||||
static const int INNER_SECTOR = 3;
|
||||
static const int OUTER_SECTOR = 2;
|
||||
static const int OPPOSITE_SECTOR = 1;
|
||||
static const int COMPLEMENT_SECTOR = 0;
|
||||
|
||||
int classifyPointToArcPosition(double pointDistance, double pointAngle,
|
||||
double radius, double startAngle, double endAngle, bool clockwise) const;
|
||||
double computeLineAndLabelAngles(Base::Vector3d lineTarget, Base::Vector3d labelCenter,
|
||||
double lineLabelDistance, double &lineAngle, double &labelAngle) const;
|
||||
Base::Vector3d computeLineOriginPoint(Base::Vector3d lineTarget, double projectedLabelDistance,
|
||||
double lineAngle, double labelWidth, double direction) const;
|
||||
|
||||
void draw() override;
|
||||
void drawRadiusAligned(TechDraw::DrawViewDimension *dimension,
|
||||
ViewProviderDimension *viewProvider) const;
|
||||
void drawRadiusUniform(TechDraw::DrawViewDimension *dimension,
|
||||
ViewProviderDimension *viewProvider) const;
|
||||
|
||||
virtual QVariant itemChange( GraphicsItemChange change,
|
||||
const QVariant &value ) override;
|
||||
virtual void setSvgPens(void);
|
||||
@@ -162,6 +181,8 @@ protected:
|
||||
Base::Vector3d findIsoDir(Base::Vector3d ortho);
|
||||
Base::Vector3d findIsoExt(Base::Vector3d isoDir);
|
||||
QString getPrecision(void);
|
||||
|
||||
int prefRadiusAligned(void);
|
||||
|
||||
protected:
|
||||
bool hasHover;
|
||||
@@ -178,6 +199,11 @@ private:
|
||||
|
||||
double getDefaultTextHorizontalOffset(bool toLeft) const;
|
||||
double getDefaultTextVerticalOffset() const;
|
||||
double getDefaultReferenceLineOverhang() const;
|
||||
|
||||
static double getStandardLinePlacement(double labelAngle);
|
||||
static bool angleWithinSector(double testAngle, double startAngle, double endAngle, bool clockwise);
|
||||
static double addAngles(double angle1, double angle2);
|
||||
};
|
||||
|
||||
} // namespace MDIViewPageGui
|
||||
|
||||
@@ -79,8 +79,9 @@ ViewProviderDimension::ViewProviderDimension()
|
||||
fcColor.setPackedValue(hGrp->GetUnsigned("Color", 0x00000000));
|
||||
ADD_PROPERTY_TYPE(Color,(fcColor),group,App::Prop_None,"The color of the Dimension");
|
||||
|
||||
ADD_PROPERTY_TYPE(FlipArrowheads ,(false),group,App::Prop_None,"Reverse the normal direction of arrowheads on dimline");
|
||||
|
||||
ADD_PROPERTY_TYPE(FlipArrowheads, (false), group, App::Prop_None,"Reverse the normal direction of arrowheads on dimline");
|
||||
ADD_PROPERTY_TYPE(TiltText, (true), group, App::Prop_None,"Rotate the text label so it is parallel with dimline");
|
||||
ADD_PROPERTY_TYPE(ExtendToCenter, (true), group, App::Prop_None,"Prolong the leader line right upto the center point");
|
||||
}
|
||||
|
||||
ViewProviderDimension::~ViewProviderDimension()
|
||||
@@ -131,7 +132,9 @@ void ViewProviderDimension::onChanged(const App::Property* p)
|
||||
if ((p == &Font) ||
|
||||
(p == &Fontsize) ||
|
||||
(p == &LineWidth) ||
|
||||
(p == &FlipArrowheads)) {
|
||||
(p == &FlipArrowheads) ||
|
||||
(p == &TiltText) ||
|
||||
(p == &ExtendToCenter)) {
|
||||
QGIView* qgiv = getQView();
|
||||
if (qgiv) {
|
||||
qgiv->updateView(true);
|
||||
|
||||
@@ -49,7 +49,8 @@ public:
|
||||
App::PropertyFloat LineWidth;
|
||||
App::PropertyColor Color;
|
||||
App::PropertyBool FlipArrowheads;
|
||||
|
||||
App::PropertyBool TiltText;
|
||||
App::PropertyBool ExtendToCenter;
|
||||
|
||||
virtual void attach(App::DocumentObject *);
|
||||
virtual void setDisplayMode(const char* ModeName);
|
||||
|
||||