Part: new tools - JoinFeatures (Connect, Embed and Cutout)

Attributions:
Mark (quick61) - icons
Yorik - help with internationalization
Everyone who appeared in forum thread "A new Part tool is being born...
JoinFeatures!" - for endorsement!
http://forum.freecadweb.org/viewtopic.php?f=22&t=11112
This commit is contained in:
DeepSOIC 2015-06-04 01:46:16 +03:00 committed by wmayer
parent 5ced7e5cbe
commit 37fbcb64a6
11 changed files with 1166 additions and 14 deletions

View File

@ -265,6 +265,7 @@ SET(Part_Scripts
Init.py
TestPartApp.py
MakeBottle.py
JoinFeatures.py
)
add_library(Part SHARED ${Part_SRCS})

View File

@ -11,6 +11,7 @@ INSTALL(
MakeBottle.py
TestPartApp.py
TestPartGui.py
JoinFeatures.py
DESTINATION
Mod/Part
)

View File

@ -39,6 +39,7 @@
#include <Base/Exception.h>
#include <App/Document.h>
#include <App/DocumentObjectGroup.h>
#include <Gui/Action.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
@ -490,6 +491,101 @@ bool CmdPartFuse::isActive(void)
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=2;
}
//===========================================================================
// Part_CompJoinFeatures (dropdown toolbar button for Connect, Embed and Cutout)
//===========================================================================
DEF_STD_CMD_ACL(CmdPartCompJoinFeatures);
CmdPartCompJoinFeatures::CmdPartCompJoinFeatures()
: Command("Part_CompJoinFeatures")
{
sAppModule = "Part";
sGroup = QT_TR_NOOP("Part");
sMenuText = QT_TR_NOOP("Join objects...");
sToolTipText = QT_TR_NOOP("Join walled objects");
sWhatsThis = "Part_CompJoinFeatures";
sStatusTip = sToolTipText;
}
void CmdPartCompJoinFeatures::activated(int iMsg)
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
if (iMsg==0)
rcCmdMgr.runCommandByName("Part_JoinConnect");
else if (iMsg==1)
rcCmdMgr.runCommandByName("Part_JoinEmbed");
else if (iMsg==2)
rcCmdMgr.runCommandByName("Part_JoinCutout");
else
return;
// Since the default icon is reset when enabing/disabling the command we have
// to explicitly set the icon of the used command.
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
assert(iMsg < a.size());
pcAction->setIcon(a[iMsg]->icon());
}
Gui::Action * CmdPartCompJoinFeatures::createAction(void)
{
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
pcAction->setDropDownMenu(true);
applyCommandData(this->className(), pcAction);
QAction* cmd0 = pcAction->addAction(QString());
cmd0->setIcon(Gui::BitmapFactory().pixmap("Part_JoinConnect"));
QAction* cmd1 = pcAction->addAction(QString());
cmd1->setIcon(Gui::BitmapFactory().pixmap("Part_JoinEmbed"));
QAction* cmd2 = pcAction->addAction(QString());
cmd2->setIcon(Gui::BitmapFactory().pixmap("Part_JoinCutout"));
_pcAction = pcAction;
languageChange();
pcAction->setIcon(cmd0->icon());
int defaultId = 0;
pcAction->setProperty("defaultAction", QVariant(defaultId));
return pcAction;
}
void CmdPartCompJoinFeatures::languageChange()
{
Command::languageChange();
if (!_pcAction)
return;
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
QAction* cmd0 = a[0];
cmd0->setText(QApplication::translate("PartCompJoinFeatures", rcCmdMgr.getCommandByName("Part_JoinConnect")->getMenuText()));
cmd0->setToolTip(QApplication::translate("Part_JoinConnect", rcCmdMgr.getCommandByName("Part_JoinConnect")->getToolTipText()));
cmd0->setStatusTip(QApplication::translate("Part_JoinConnect", rcCmdMgr.getCommandByName("Part_JoinConnect")->getStatusTip()));
QAction* cmd1 = a[1];
cmd1->setText(QApplication::translate("PartCompJoinFeatures", rcCmdMgr.getCommandByName("Part_JoinEmbed")->getMenuText()));
cmd1->setToolTip(QApplication::translate("Part_JoinEmbed", rcCmdMgr.getCommandByName("Part_JoinEmbed")->getToolTipText()));
cmd1->setStatusTip(QApplication::translate("Part_JoinEmbed", rcCmdMgr.getCommandByName("Part_JoinEmbed")->getStatusTip()));
QAction* cmd2 = a[2];
cmd2->setText(QApplication::translate("PartCompJoinFeatures", rcCmdMgr.getCommandByName("Part_JoinCutout")->getMenuText()));
cmd2->setToolTip(QApplication::translate("Part_JoinCutout", rcCmdMgr.getCommandByName("Part_JoinCutout")->getToolTipText()));
cmd2->setStatusTip(QApplication::translate("Part_JoinCutout", rcCmdMgr.getCommandByName("Part_JoinCutout")->getStatusTip()));
}
bool CmdPartCompJoinFeatures::isActive(void)
{
if (getActiveGuiDocument())
return true;
else
return false;
}
//===========================================================================
// Part_Compound
//===========================================================================
@ -1747,6 +1843,7 @@ void CreatePartCommands(void)
rcCmdMgr.addCommand(new CmdPartCommon());
rcCmdMgr.addCommand(new CmdPartCut());
rcCmdMgr.addCommand(new CmdPartFuse());
rcCmdMgr.addCommand(new CmdPartCompJoinFeatures());
rcCmdMgr.addCommand(new CmdPartCompound());
rcCmdMgr.addCommand(new CmdPartSection());
//rcCmdMgr.addCommand(new CmdPartBox2());

View File

@ -59,6 +59,10 @@
<file>icons/Tree_Part_Prism.svg</file>
<file>icons/Tree_Part_Wedge.svg</file>
<file>icons/Part_Shape_from_Mesh.svg</file>
<file>icons/Part_JoinBypass.svg</file>
<file>icons/Part_JoinConnect.svg</file>
<file>icons/Part_JoinCutout.svg</file>
<file>icons/Part_JoinEmbed.svg</file>
<file>translations/Part_af.qm</file>
<file>translations/Part_de.qm</file>
<file>translations/Part_fi.qm</file>

View File

@ -0,0 +1,203 @@
<?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="svg2644"
sodipodi:version="0.32"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Part-Cutout.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="C:\_vt\dev\PC\Qt\FreeCAD\macros\JoinFeatures\resources\icons\try2\Part-Cutout64.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs2646">
<linearGradient
id="linearGradient3787">
<stop
style="stop-color:#f17878;stop-opacity:1;"
offset="0"
id="stop3789" />
<stop
style="stop-color:#870e0e;stop-opacity:1;"
offset="1"
id="stop3791" />
</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="perspective2652" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3864"
id="radialGradient3761"
cx="172.60796"
cy="10.167614"
fx="172.60796"
fy="10.167614"
r="22.06875"
gradientTransform="matrix(1,0,0,0.99858397,0,0.01439764)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3787"
id="radialGradient3796"
cx="15.844314"
cy="22.236769"
fx="15.844314"
fy="22.236769"
r="24.5"
gradientTransform="matrix(-1.7959187,-8.5004252e-7,7.4195815e-7,-1.6326528,246.83616,55.161607)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3864"
id="radialGradient3775"
cx="221.79019"
cy="36.43409"
fx="221.79019"
fy="36.43409"
r="30.999998"
gradientTransform="matrix(-1.4193551,-5.0298722e-7,4.5726095e-7,-1.2903224,533.18009,65.868506)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3864"
id="radialGradient3785"
cx="24.500006"
cy="35.850002"
fx="24.500006"
fy="35.850002"
r="11"
gradientTransform="matrix(-3.9999998,-1.5358005e-6,1.3961822e-6,-3.6363634,119.99997,148.36367)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3864"
id="radialGradient3801"
cx="21.999996"
cy="17.999996"
fx="21.999996"
fy="17.999996"
r="10.5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-4.1904764,-1.5632622e-6,1.4211471e-6,-3.8095236,114.19044,86.57144)" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.7781746"
inkscape:cx="-13.073002"
inkscape:cy="33.785734"
inkscape:current-layer="g3706"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="990"
inkscape:window-x="-11"
inkscape:window-y="-11"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-grids="true"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid3777"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
spacingx="4px"
spacingy="4px"
originy="2px"
originx="2px" />
</sodipodi:namedview>
<metadata
id="metadata2649">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3706"
transform="translate(-196.38107,-0.85667132)"
style="fill:#908c8c;fill-opacity:1">
<rect
style="fill:url(#radialGradient3785);stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
id="rect3763"
width="20"
height="60"
x="14"
y="2"
transform="translate(196.38107,0.85667132)" />
<rect
style="fill:url(#radialGradient3775);stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
id="rect3765"
width="59.999996"
height="20"
x="198.38107"
y="26.85667"
ry="0" />
<path
style="fill:url(#radialGradient3796);fill-opacity:1.0;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 210.38107,26.856671 0,20 20,0 0,-20 z"
id="path3784"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:none;stroke:url(#radialGradient3801);stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 22,26 -8,8 0,8 16,-16 4,0 0,4 -16,16 8,0 8,-8"
id="path3793"
inkscape:connector-curvature="0"
transform="translate(196.38107,0.85667132)" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3803"
width="20"
height="20"
x="14"
y="26"
transform="translate(196.38107,0.85667132)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -0,0 +1,194 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
viewBox="0 0 18.062222 18.062221"
version="1.1"
id="svg6662"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Connect.svg">
<metadata
id="metadata6694">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6692">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4391"
id="radialGradient3552"
gradientUnits="userSpaceOnUse"
cx="48.645836"
cy="25.149042"
fx="48.645836"
fy="25.149042"
r="19.571428" />
<linearGradient
id="linearGradient4391">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4393" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4395" />
</linearGradient>
<radialGradient
r="19.571428"
fy="25.149042"
fx="48.645836"
cy="25.149042"
cx="48.645836"
gradientUnits="userSpaceOnUse"
id="radialGradient6546"
xlink:href="#linearGradient4391"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4391"
id="radialGradient7250"
cx="4.8811665"
cy="14.492186"
fx="4.8811665"
fy="14.492186"
r="3.7374249"
gradientTransform="matrix(-0.81470605,-0.00967045,0.03403256,-2.8671429,8.3666287,41.405173)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4391"
id="radialGradient7271"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.81470605,-0.00967045,0.03403256,-2.8671429,8.3666287,41.405173)"
cx="4.8811665"
cy="14.492186"
fx="4.8811665"
fy="14.492186"
r="3.7374249" />
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="824"
id="namedview6690"
showgrid="false"
inkscape:zoom="8.1523184"
inkscape:cx="37.110431"
inkscape:cy="27.597859"
inkscape:window-x="-2"
inkscape:window-y="53"
inkscape:window-maximized="1"
inkscape:current-layer="svg6662" />
<g
id="g7252"
transform="matrix(0.9962767,0,0,1.0097864,-0.00324012,-0.17735289)">
<path
id="Cut001_f0000"
d="m 1.2212469,17.887225 0,0 0,-17.53601187 0,0 0,17.53601187 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0002"
d="m 1.2212469,0.35121313 0,17.53601187 -1.04624903,0 0,-17.53601187 1.04624903,0 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0004"
d="m 8.5449899,0.35121313 -7.323743,0 0,17.53601187 7.323743,0 0,-5.480004 0,-5.480004 0,-6.57600387 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0005"
d="m 0.17499787,0.35121313 0,17.53601187 0,0 0,-17.53601187 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0007"
d="m 8.5449899,0.35121313 0,17.53601187 -7.323743,0 0,-17.53601187 7.323743,0 z"
style="fill:url(#radialGradient7271);fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0008"
d="m 8.5449899,0.35121313 a 1.046249,1.0960006 0 0 0 1.046249,0 l 0,6.57600387 0,5.480004 0,5.480004 a 1.046249,1.0960006 0 0 0 -1.046249,0 l 0,-17.53601187 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0009"
d="m 9.5912389,13.503222 0,4.384003 0,0 0,-5.480004 a 1.046249,1.0960006 0 0 0 0,1.096001 l 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0010"
d="m 8.5449899,12.407221 0,5.480004 1.046249,0 0,-4.384003 8.3699921,0 0,-1.096001 -9.4162411,0 z"
style="fill:#c00000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0011"
d="m 8.5449899,17.887225 0,0 0,-5.480004 0,0 0,-5.480004 0,0 0,-6.57600387 0,0 0,6.57600387 0,5.480004 0,5.480004 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0012"
d="m 9.5912389,0.35121313 0,0 0,5.48000317 0,0 a 1.046249,1.0960006 0 0 0 0,1.0960007 l 0,-6.57600387 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0013"
d="m 8.5449899,0.35121313 0,6.57600387 9.4162411,0 0,-1.0960007 -8.3699921,0 0,-5.48000317 -1.046249,0 z"
style="fill:#c00000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0014"
d="m 17.961231,12.407221 0,-5.480004 -8.3699921,0 0,5.480004 8.3699921,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0015"
d="m 9.5912389,13.503222 8.3699921,0 0,0 -8.3699921,0 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0017"
d="m 8.5449899,12.407221 1.046249,0 8.3699921,0 0,0 -9.4162411,0 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0019"
d="m 8.5449899,6.927217 1.046249,0 8.3699921,0 0,5.480004 -8.3699921,0 -1.046249,0 0,-5.480004 z"
style="fill:#002795;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0020"
d="m 8.5449899,6.927217 0,0 1.046249,0 8.3699921,0 0,0 -9.4162411,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut001_f0022"
d="m 9.5912389,5.8312163 8.3699921,0 0,0 -8.3699921,0 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15110685;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
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 18.062221 18.062221"
version="1.1"
id="svg5940"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Cutout.svg">
<metadata
id="metadata5968">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs5966">
<linearGradient
id="linearGradient6569">
<stop
id="stop6571"
offset="0"
style="stop-color:#73b2f6;stop-opacity:1;" />
<stop
id="stop6573"
offset="1"
style="stop-color:#002795;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient6517"
osb:paint="solid">
<stop
style="stop-color:#0000ff;stop-opacity:0.63855422;"
offset="0"
id="stop6519" />
</linearGradient>
<linearGradient
id="linearGradient6497">
<stop
style="stop-color:#ff0000;stop-opacity:1;"
offset="0"
id="stop6499" />
<stop
id="stop6509"
offset="0.5"
style="stop-color:#df0000;stop-opacity:0.49803922;" />
<stop
style="stop-color:#0000ff;stop-opacity:0;"
offset="1"
id="stop6501" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4391"
id="radialGradient3552"
gradientUnits="userSpaceOnUse"
cx="48.645836"
cy="25.149042"
fx="48.645836"
fy="25.149042"
r="19.571428" />
<linearGradient
id="linearGradient4391">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4393" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4395" />
</linearGradient>
<radialGradient
r="19.571428"
fy="25.149042"
fx="48.645836"
cy="25.149042"
cx="48.645836"
gradientUnits="userSpaceOnUse"
id="radialGradient6546"
xlink:href="#linearGradient4391"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient6569"
id="radialGradient6567"
cx="8.9553537"
cy="44.946674"
fx="8.9553537"
fy="44.946674"
r="3.5705557"
gradientTransform="matrix(-0.94733236,-0.00407076,0.01580094,-3.3143438,17.05981,147.31969)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient6569"
id="radialGradient6621"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.94733236,-0.00407076,0.01580094,-3.3143438,17.05981,147.31969)"
cx="8.9553537"
cy="44.946674"
fx="8.9553537"
fy="44.946674"
r="3.5705557" />
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="824"
id="namedview5964"
showgrid="false"
showborder="true"
inkscape:zoom="8.2329346"
inkscape:cx="9.4830598"
inkscape:cy="31.197307"
inkscape:window-x="-2"
inkscape:window-y="53"
inkscape:window-maximized="1"
inkscape:current-layer="svg5940" />
<g
id="g6611"
transform="matrix(1.0057818,0,0,1.0057818,-0.30889471,0.58721331)">
<path
id="Cut002_f0000"
d="m 5.2334517,17.209018 0,0 0,-17.58963669 0,0 0,17.58963669 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut002_f0002"
d="m 5.2334517,-0.38061869 0,17.58963669 -1.1579605,0 0,-17.58963669 1.1579605,0 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut002_f0007"
d="m 13.339176,-0.38061869 0,17.58963669 -8.1057243,0 0,-17.58963669 8.1057243,0 z"
style="fill:url(#radialGradient6621);fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut002_f0008"
d="m 13.339176,-0.41830416 a 1.1579605,1.0993523 0 0 0 1.15796,0 l 0,6.59611396 0,5.4967612 0,5.496762 a 1.1579605,1.0993523 0 0 0 -1.15796,0 l 0,-17.58963716 z"
style="fill:#5a96e4;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut002_f0010"
d="m 13.339176,12.811609 0,4.397409 1.15796,0 0,-4.397409 -1.15796,0 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut002_f0014"
d="m 13.339176,-0.38061869 0,5.49676159 1.15796,0 0,-5.49676159 -1.15796,0 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut002_f0017"
d="m 14.497136,12.811609 0,0 -1.15796,0 0,0 1.15796,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut002_f0018"
d="m 13.339176,5.1161429 1.15796,0 0,0 -1.15796,0 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15921226;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
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 18.062222 18.062221"
version="1.1"
id="svg3042"
inkscape:version="0.48.4 r9939"
sodipodi:docname="Embed.svg">
<metadata
id="metadata3080">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3078">
<linearGradient
id="linearGradient5841"
osb:paint="solid">
<stop
style="stop-color:#bf80ff;stop-opacity:1;"
offset="0"
id="stop5843" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4391"
id="radialGradient3552"
gradientUnits="userSpaceOnUse"
cx="48.645836"
cy="25.149042"
fx="48.645836"
fy="25.149042"
r="19.571428" />
<linearGradient
id="linearGradient4391">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4393" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4395" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4391"
id="radialGradient5919"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,2.2603081,0,-10.296717)"
cx="4.6700001"
cy="8.1700001"
fx="4.6700001"
fy="8.1700001"
r="3.5705557" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4391"
id="radialGradient6607"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.90118131,-4.2608786e-4,0.00142851,-3.0212961,9.1622386,40.335088)"
cx="4.8302736"
cy="13.504073"
fx="4.8302736"
fy="13.504073"
r="3.5705557" />
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="824"
id="namedview3076"
showgrid="false"
inkscape:zoom="8.1523184"
inkscape:cx="4.1676008"
inkscape:cy="33.30994"
inkscape:window-x="-2"
inkscape:window-y="53"
inkscape:window-maximized="1"
inkscape:current-layer="svg3042" />
<g
id="g6623">
<path
id="Cut_f0000"
d="m 1.243156,17.847824 0,0 0,-17.6334271 0,0 0,17.6334271 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0002"
d="m 1.243156,0.2143969 0,17.6334271 -1.038394,0 0,-17.6334271 1.038394,0 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0004"
d="m 8.511914,0.2143969 -7.268758,0 0,17.6334271 7.268758,0 0,-5.510446 -3.115182,0 0,-5.5104459 3.115182,0 0,-6.6125352 z"
style="fill:url(#radialGradient6607);fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095608999999999;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0005"
d="m 0.204762,0.2143969 0,17.6334271 0,0 0,-17.6334271 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0007"
d="m 8.511914,0.2143969 0,17.6334271 -7.268758,0 0,-17.6334271 7.268758,0 z"
style="fill:none;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0008"
d="m 8.511914,0.2143969 a 1.038394,1.1020892 0 0 0 1.038394,0 l 0,6.6125352 0,5.5104459 0,5.510446 a 1.038394,1.1020892 0 0 0 -1.038394,0 l 0,-17.6334271 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0009"
d="m 9.550308,13.439467 0,4.408357 0,0 0,-5.510446 a 1.038394,1.1020892 0 0 0 0,1.102089 l 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0010"
d="m 8.511914,13.439467 0,4.408357 1.038394,0 0,-4.408357 8.307152,0 0,-1.102089 -12.460728,0 0,1.102089 3.115182,0 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0012"
d="m 8.511914,0.2143969 0,5.510446 0,0 a 1.038394,1.1020892 0 0 0 0,1.1020892 l 0,-6.6125352 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0013"
d="m 9.550308,0.2143969 0,0 0,5.510446 0,0 a 1.038394,1.1020892 0 0 0 0,1.1020892 l 0,-6.6125352 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0014"
d="m 8.511914,0.2143969 0,5.510446 -3.115182,0 0,1.1020892 12.460728,0 0,-1.1020892 -8.307152,0 0,-5.510446 -1.038394,0 z"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0018"
d="m 9.550308,12.337378 0,-5.5104459 8.307152,0 0,5.5104459 -8.307152,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0019"
d="m 9.550308,13.439467 8.307152,0 0,0 -8.307152,0 0,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0022"
d="m 17.85746,12.337378 0,0 -12.460728,0 0,0 12.460728,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0024"
d="m 5.396732,5.7248429 0,0 3.115182,0 0,0 -3.115182,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0026"
d="m 9.550308,5.7248429 0,0 8.307152,0 0,0 -8.307152,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0027"
d="m 17.85746,6.8269321 0,0 -12.460728,0 0,0 12.460728,0 z"
style="fill:#c080ff;fill-rule:evenodd;stroke:#191919;stroke-width:0.15095609;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
id="Cut_f0028"
d="m 5.396732,6.8269321 0,5.5104459 12.460728,0 0,-5.5104459 -12.460728,0 z"
style="fill:#002795;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.15095609;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -66,7 +66,10 @@ Gui::MenuItem* Workbench::setupMenuBar() const
Gui::MenuItem* bop = new Gui::MenuItem;
bop->setCommand("Boolean");
*bop << "Part_Boolean" << "Part_Cut" << "Part_Fuse" << "Part_Common";
Gui::MenuItem* join = new Gui::MenuItem;
join->setCommand("Join");
*join << "Part_JoinConnect" << "Part_JoinEmbed" << "Part_JoinCutout";
Gui::MenuItem* part = new Gui::MenuItem;
root->insertItem(item, part);
@ -75,7 +78,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
*part << prim << "Part_Primitives" << "Part_Builder" << "Separator"
<< "Part_ShapeFromMesh" << "Part_MakeSolid" << "Part_ReverseShape"
<< "Part_SimpleCopy" << "Part_RefineShape" << "Part_CheckGeometry"
<< "Separator" << bop << "Separator"
<< "Separator" << bop << join << "Separator"
<< "Part_CrossSections" << "Part_Compound" << "Part_Extrude"
<< "Part_Revolve" << "Part_Mirror" << "Part_Fillet" << "Part_Chamfer"
<< "Part_RuledSurface" << "Part_Loft" << "Part_Sweep"
@ -120,7 +123,8 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
Gui::ToolBarItem* boolop = new Gui::ToolBarItem(root);
boolop->setCommand("Boolean");
*boolop << "Part_Boolean" << "Part_Cut" << "Part_Fuse" << "Part_Common"
<< "Part_CheckGeometry" << "Part_Section" << "Part_CrossSections";
<< "Part_CompJoinFeatures" << "Part_CheckGeometry" << "Part_Section"
<< "Part_CrossSections";
Gui::ToolBarItem* measure = new Gui::ToolBarItem(root);
measure->setCommand("Measure");

View File

@ -32,8 +32,8 @@
class PartWorkbench ( Workbench ):
"Part workbench object"
Icon = """
"Part workbench object"
Icon = """
/* XPM */
static char * part_xpm[] = {
"16 16 9 1",
@ -62,15 +62,20 @@ class PartWorkbench ( Workbench ):
".@$%&****%.%.. ",
" ......@##.. ",
" ... "};
"""
MenuText = "Part"
ToolTip = "Part workbench"
"""
MenuText = "Part"
ToolTip = "Part workbench"
def Initialize(self):
# load the module
import PartGui
import Part
def GetClassName(self):
return "PartGui::Workbench"
def Initialize(self):
# load the module
import PartGui
import Part
try:
import JoinFeatures
except ImportError:
print "JoinFeatures module cannot be loaded"
def GetClassName(self):
return "PartGui::Workbench"
Gui.addWorkbench(PartWorkbench())

View File

@ -0,0 +1,260 @@
#***************************************************************************
#* *
#* Copyright (c) 2015 - Victor Titov (DeepSOIC) *
#* <vv.titov@gmail.com> *
#* *
#* 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, Part
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
__title__="JoinFeatures module"
__author__ = "DeepSOIC"
__url__ = "http://www.freecadweb.org"
#-------------------------- translation-related code ----------------------------------------
#Thanks, yorik! (see forum thread "A new Part tool is being born... JoinFeatures!"
#http://forum.freecadweb.org/viewtopic.php?f=22&t=11112&start=30#p90239 )
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
#--------------------------/translation-related code ----------------------------------------
# -------------------------- common stuff --------------------------------------------------
def getParamRefine():
return FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Part/Boolean").GetBool("RefineModel")
def shapeOfMaxVol(compound):
if compound.ShapeType == 'Compound':
maxVol = 0
cntEq = 0
shMax = None
for sh in compound.childShapes():
v = sh.Volume
if v > maxVol + 1e-8 :
maxVol = v
shMax = sh
cntEq = 1
elif abs(v - maxVol) <= 1e-8 :
cntEq = cntEq + 1
if cntEq > 1 :
raise ValueError("Equal volumes, can't figure out what to cut off!")
return shMax
else:
return compound
def makePartJoinFeature(name, mode = 'bypass'):
'''makePartJoinFeature(name, mode = 'bypass'): makes an PartJoinFeature object.'''
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
_PartJoinFeature(obj)
obj.Mode = mode
obj.Refine = getParamRefine()
_ViewProviderPartJoinFeature(obj.ViewObject)
return obj
class _PartJoinFeature:
"The PartJoinFeature object"
def __init__(self,obj):
self.Type = "PartJoinFeature"
obj.addProperty("App::PropertyEnumeration","Mode","Join","The mode of operation. bypass = make compound (fast)")
obj.Mode = ['bypass','Connect','Embed','Cutout']
obj.addProperty("App::PropertyLink","Base","Join","First object")
obj.addProperty("App::PropertyLink","Tool","Join","Second object")
obj.addProperty("App::PropertyBool","Refine","Join","True = refine resulting shape. False = output as is.")
obj.Proxy = self
def execute(self,obj):
rst = None
if obj.Mode == 'bypass':
rst = Part.makeCompound([obj.Base.Shape, obj.Tool.Shape])
else:
cut1 = obj.Base.Shape.cut(obj.Tool.Shape)
cut1 = shapeOfMaxVol(cut1)
if obj.Mode == 'Connect':
cut2 = obj.Tool.Shape.cut(obj.Base.Shape)
cut2 = shapeOfMaxVol(cut2)
rst = cut1.multiFuse([cut2, obj.Tool.Shape.common(obj.Base.Shape)])
elif obj.Mode == 'Embed':
rst = cut1.fuse(obj.Tool.Shape)
elif obj.Mode == 'Cutout':
rst = cut1
if obj.Refine:
rst = rst.removeSplitter()
obj.Shape = rst
return
class _ViewProviderPartJoinFeature:
"A View Provider for the PartJoinFeature object"
def __init__(self,vobj):
vobj.Proxy = self
def getIcon(self):
if self.Object == None:
return getIconPath("Part_JoinConnect.svg")
else:
return getIconPath( {
'bypass':"Part_JoinBypass.svg",
'Connect':"Part_JoinConnect.svg",
'Embed':"Part_JoinEmbed.svg",
'Cutout':"Part_JoinCutout.svg",
}[self.Object.Mode] )
def attach(self, vobj):
self.ViewObject = vobj
self.Object = vobj.Object
def setEdit(self,vobj,mode):
return False
def unsetEdit(self,vobj,mode):
return
def __getstate__(self):
return None
def __setstate__(self,state):
return None
def CreateJoinFeature(name, mode):
FreeCAD.ActiveDocument.openTransaction("Create "+mode+"ObjectsFeature")
FreeCADGui.addModule("JoinFeatures")
FreeCADGui.doCommand("j = JoinFeatures.makePartJoinFeature(name = '"+name+"', mode = '"+mode+"' )")
FreeCADGui.doCommand("j.Base = FreeCADGui.Selection.getSelection()[0]")
FreeCADGui.doCommand("j.Tool = FreeCADGui.Selection.getSelection()[1]")
FreeCADGui.doCommand("j.Proxy.execute(j)")
FreeCADGui.doCommand("j.purgeTouched()")
FreeCADGui.doCommand("j.Base.ViewObject.hide()")
FreeCADGui.doCommand("j.Tool.ViewObject.hide()")
FreeCAD.ActiveDocument.commitTransaction()
def getIconPath(icon_dot_svg):
return ":/icons/" + icon_dot_svg
# -------------------------- /common stuff --------------------------------------------------
# -------------------------- ConnectObjectsFeature --------------------------------------------------
class _CommandConnectFeature:
"Command to create PartJoinFeature in Connect mode"
def GetResources(self):
return {'Pixmap' : getIconPath("Part_JoinConnect.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Part_ConnectFeature","Connect objects"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_ConnectFeature","Fuses objects, taking care to preserve voids.")}
def Activated(self):
if len(FreeCADGui.Selection.getSelection()) == 2 :
CreateJoinFeature(name = "Connect", mode = "Connect")
else:
mb = QtGui.QMessageBox()
mb.setIcon(mb.Icon.Warning)
mb.setText(_translate("Part_JoinFeatures", "Two solids need to be selected, first!", None))
mb.setWindowTitle(_translate("Part_JoinFeatures","Bad selection", None))
mb.exec_()
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
FreeCADGui.addCommand('Part_JoinConnect',_CommandConnectFeature())
# -------------------------- /ConnectObjectsFeature --------------------------------------------------
# -------------------------- EmbedFeature --------------------------------------------------
class _CommandEmbedFeature:
"Command to create PartJoinFeature in Embed mode"
def GetResources(self):
return {'Pixmap' : getIconPath("Part_JoinEmbed.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Part_EmbedFeature","Embed object"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_EmbedFeature","Fuses one object into another, taking care to preserve voids.")}
def Activated(self):
if len(FreeCADGui.Selection.getSelection()) == 2 :
CreateJoinFeature(name = "Embed", mode = "Embed")
else:
mb = QtGui.QMessageBox()
mb.setIcon(mb.Icon.Warning)
mb.setText(_translate("Part_JoinFeatures","Select base object, then the object to embed, and invoke this tool.", None))
mb.setWindowTitle(_translate("Part_JoinFeatures","Bad selection", None))
mb.exec_()
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
FreeCADGui.addCommand('Part_JoinEmbed',_CommandEmbedFeature())
# -------------------------- /EmbedFeature --------------------------------------------------
# -------------------------- CutoutFeature --------------------------------------------------
class _CommandCutoutFeature:
"Command to create PartJoinFeature in Cutout mode"
def GetResources(self):
return {'Pixmap' : getIconPath("Part_JoinCutout.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Part_CutoutFeature","Cutout for object"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_CutoutFeature","Makes a cutout in one object to fit another object.")}
def Activated(self):
if len(FreeCADGui.Selection.getSelection()) == 2 :
CreateJoinFeature(name = "Cutout", mode = "Cutout")
else:
mb = QtGui.QMessageBox()
mb.setIcon(mb.Icon.Warning)
mb.setText(_translate("Part_JoinFeatures","Select the object to make a cutout in, then the object that should fit into the cutout, and invoke this tool.", None))
mb.setWindowTitle(_translate("Part_JoinFeatures","Bad selection", None))
mb.exec_()
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
FreeCADGui.addCommand('Part_JoinCutout',_CommandCutoutFeature())
# -------------------------- /CutoutFeature --------------------------------------------------