PartDesign workflow without part/body

PartDesign: make datum features work outside of body/part
PartDesign old workflow: remove a few messageboxes about no part
PartDesign: old workflow: multitransform without body

Still has visibility issues, but generally works.
This commit is contained in:
DeepSOIC 2015-07-20 17:43:48 +03:00 committed by Stefan Tröger
parent c3da141020
commit 16e4ce20f0
8 changed files with 112 additions and 70 deletions

View File

@ -110,29 +110,6 @@ App::DocumentObjectExecReturn *Pad::execute(void)
base = TopoDS_Shape();
}
/*
// Find Body feature which owns this Pad and get the shape of the feature preceding this one for fusing
// This method was rejected in favour of the BaseFeature property because that makes the feature atomic (independent of the
// Body object). See
// https://sourceforge.net/apps/phpbb/free-cad/viewtopic.php?f=19&t=3831
// https://sourceforge.net/apps/phpbb/free-cad/viewtopic.php?f=19&t=3855
PartDesign::Body* body = getBody();
if (body == NULL) {
return new App::DocumentObjectExecReturn(
"In order to use PartDesign you need an active Body object in the document. "
"Please make one active or create one. If you have a legacy document "
"with PartDesign objects without Body, use the transfer function in "
"PartDesign to put them into a Body."
);
}
const Part::TopoShape& prevShape = body->getPreviousSolid(this);
TopoDS_Shape support;
if (prevShape.isNull())
// ignore, because support isn't mandatory
support = TopoDS_Shape();
else
support = prevShape._Shape;
*/
// get the Sketch plane
Base::Placement SketchPos = sketch->Placement.getValue();

View File

@ -522,9 +522,7 @@ void UnifiedDatumCommand(Gui::Command &cmd, Base::Type type, std::string name)
cmd.openCommand(tmp.c_str());
cmd.doCommand(Gui::Command::Gui,"Gui.activeDocument().setEdit('%s')",support.getValue()->getNameInDocument());
} else {
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true);
if (pcActiveBody == 0)
return;
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false);
std::string FeatName = cmd.getUniqueObjectName(name.c_str());
@ -547,8 +545,10 @@ void UnifiedDatumCommand(Gui::Command &cmd, Base::Type type, std::string name)
QMessageBox::information(Gui::getMainWindow(),QObject::tr("Invalid selection"), QObject::tr("There are no attachment modes that fit seleted objects. Select something else."));
}
}
cmd.doCommand(Gui::Command::Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), FeatName.c_str());
if (pcActiveBody) {
cmd.doCommand(Gui::Command::Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), FeatName.c_str());
}
cmd.doCommand(Gui::Command::Doc,"App.activeDocument().recompute()"); // recompute the feature based on its references
cmd.doCommand(Gui::Command::Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
}
@ -667,7 +667,11 @@ void CmdPartDesignNewSketch::activated(int iMsg)
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true);
// No PartDesign feature without Body past FreeCAD 0.13
if(!pcActiveBody) return;
if(!pcActiveBody) {
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.runCommandByName("Sketcher_NewSketch");
return;
}
Gui::SelectionFilter SketchFilter("SELECT Sketcher::SketchObject COUNT 1");
Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1");
@ -893,10 +897,9 @@ bool CmdPartDesignNewSketch::isActive(void)
void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const bool hidePrevSolid = true)
{
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false);
if (pcActiveBody == 0)
throw Base::Exception("No active body!");
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
if (pcActiveBody)
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), FeatName.c_str());
if (pcActiveBody != NULL) {
@ -939,8 +942,8 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const b
for (std::vector<App::DocumentObject*>::iterator s = sketches.begin(); s != sketches.end(); s++) {
// Check whether this plane belongs to the active body
if (!pcActiveBody->hasFeature(*s)) {
if(pcActivePart->hasObject(*s, true))
if (pcActiveBody && !pcActiveBody->hasFeature(*s)) {
if(pcActivePart && pcActivePart->hasObject(*s, true))
status.push_back(PartDesignGui::TaskFeaturePick::otherBody);
else
status.push_back(PartDesignGui::TaskFeaturePick::otherPart);
@ -968,7 +971,7 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const b
continue;
}
if (pcActiveBody->isAfterTip(*s)){
if (pcActiveBody && pcActiveBody->isAfterTip(*s)){
status.push_back(PartDesignGui::TaskFeaturePick::afterTip);
continue;
}
@ -1005,9 +1008,6 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const b
void prepareSketchBased(Gui::Command* cmd, const std::string& which,
boost::function<void (Part::Part2DObject*, std::string)> func)
{
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true);
if (!pcActiveBody) return;
bool bNoSketchWasSelected = false;
// Get a valid sketch from the user
// First check selections
@ -1050,8 +1050,6 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which,
which.c_str(), FeatName.c_str());
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",
FeatName.c_str(), sketch->getNameInDocument());
//Gui::Command::doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
// pcActiveBody->getNameInDocument(), FeatName.c_str());
func(sketch, FeatName);
};
@ -2061,8 +2059,8 @@ CmdPartDesignMultiTransform::CmdPartDesignMultiTransform()
void CmdPartDesignMultiTransform::activated(int iMsg)
{
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true);
if (!pcActiveBody) return;
PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false);
//if (!pcActiveBody) return;
std::vector<App::DocumentObject*> features;
@ -2082,8 +2080,12 @@ void CmdPartDesignMultiTransform::activated(int iMsg)
PartDesign::Transformed* trFeat = static_cast<PartDesign::Transformed*>(features.front());
// Move the insert point back one feature
App::DocumentObject* oldTip = pcActiveBody->Tip.getValue();
App::DocumentObject* prevFeature = pcActiveBody->getPrevFeature(trFeat);
App::DocumentObject* oldTip = 0;
App::DocumentObject* prevFeature = 0;
if (pcActiveBody){
oldTip = pcActiveBody->Tip.getValue();
prevFeature = pcActiveBody->getPrevFeature(trFeat);
}
Gui::Selection().clearSelection();
if (prevFeature != NULL)
Gui::Selection().addSelection(prevFeature->getDocument()->getName(), prevFeature->getNameInDocument());
@ -2091,8 +2093,9 @@ void CmdPartDesignMultiTransform::activated(int iMsg)
doCommand(Gui, "FreeCADGui.runCommand('PartDesign_MoveTip')");
// Remove the Transformed feature from the Body
doCommand(Doc, "App.activeDocument().%s.removeFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), trFeat->getNameInDocument());
if(pcActiveBody)
doCommand(Doc, "App.activeDocument().%s.removeFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), trFeat->getNameInDocument());
// Create a MultiTransform feature and move the Transformed feature inside it
std::string FeatName = getUniqueObjectName("MultiTransform");
@ -2105,7 +2108,7 @@ void CmdPartDesignMultiTransform::activated(int iMsg)
finishFeature(this, FeatName);
// Restore the insert point
if (oldTip != trFeat) {
if (pcActiveBody && oldTip != trFeat) {
Gui::Selection().clearSelection();
Gui::Selection().addSelection(oldTip->getDocument()->getName(), oldTip->getNameInDocument());
Gui::Command::doCommand(Gui::Command::Gui,"FreeCADGui.runCommand('PartDesign_MoveTip')");
@ -2120,7 +2123,9 @@ void CmdPartDesignMultiTransform::activated(int iMsg)
return;
// Make sure the user isn't presented with an empty screen because no transformations are defined yet...
App::DocumentObject* prevSolid = pcActiveBody->getPrevSolidFeature(NULL, true);
App::DocumentObject* prevSolid = 0;
if (pcActiveBody)
pcActiveBody->getPrevSolidFeature(NULL, true);
if (prevSolid != NULL) {
Part::Feature* feat = static_cast<Part::Feature*>(prevSolid);
doCommand(Doc,"App.activeDocument().%s.Shape = App.activeDocument().%s.Shape",

View File

@ -94,15 +94,28 @@ const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChan
void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool edge, const bool face, const bool planar) {
// Note: Even if there is no solid, App::Plane and Part::Datum can still be selected
PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY);
App::DocumentObject* prevSolid = activeBody->getPrevSolidFeature(vp->getObject(), false);
App::DocumentObject* curSolid = activeBody->getPrevSolidFeature();
PartDesign::SketchBased* pcSketchBased = static_cast<PartDesign::SketchBased*>(vp->getObject());
PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY);
App::DocumentObject* curSolid = 0;//the last solid of the body, the one that is likely visible, but can't be used for up-to-face
if (activeBody)
curSolid = activeBody->getPrevSolidFeature();
else
curSolid = pcSketchBased;
App::DocumentObject* prevSolid = 0;//the solid this feature will be fused to
try {
prevSolid = pcSketchBased->getBaseObject();
} catch (Base::Exception) {
//this feature is a starting feature
}
if (pressed) {
Gui::Document* doc = Gui::Application::Instance->activeDocument();
if (doc) {
if (curSolid)
doc->setHide(curSolid->getNameInDocument());
doc->setHide(curSolid->getNameInDocument());
if (prevSolid)
doc->setShow(prevSolid->getNameInDocument());
}
@ -114,7 +127,7 @@ void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool
Gui::Document* doc = Gui::Application::Instance->activeDocument();
if (doc) {
if (curSolid)
doc->setShow(curSolid->getNameInDocument());
doc->setShow(curSolid->getNameInDocument());
if (prevSolid)
doc->setHide(prevSolid->getNameInDocument());
}
@ -200,7 +213,7 @@ App::DocumentObject* TaskSketchBasedParameters::getPartPlanes(const char* str) c
//TODO: Adjust to GRAPH handling when available
App::DocumentObject* obj = vp->getObject();
App::Part* part = getPartFor(obj, true);
App::Part* part = getPartFor(obj, false);
if(!part)
return nullptr;
@ -224,11 +237,15 @@ App::DocumentObject* TaskSketchBasedParameters::getPartLines(const char* str) co
//TODO: Adjust to GRAPH handling when available
App::DocumentObject* obj = vp->getObject();
App::Part* part = getPartFor(obj, true);
if(!part)
return nullptr;
App::Part* part = getPartFor(obj, false);
std::vector<App::DocumentObject*> origs = part->getObjectsOfType(App::Origin::getClassTypeId());
std::vector<App::DocumentObject*> origs;
if(part)
origs = part->getObjectsOfType(App::Origin::getClassTypeId());
else
origs = vp->getObject()->getDocument()->getObjectsOfType(App::Origin::getClassTypeId());
if(origs.size()<1)
return nullptr;

View File

@ -182,7 +182,7 @@ App::DocumentObject* TaskTransformedParameters::getPartPlanes(const char* str) c
//TODO: Adjust to GRAPH handling when available
App::DocumentObject* obj = getObject();
App::Part* part = getPartFor(obj, true);
App::Part* part = getPartFor(obj, false);
if (part) {
std::vector<App::DocumentObject*> origs = part->getObjectsOfType(App::Origin::getClassTypeId());

View File

@ -54,6 +54,7 @@
#include "ViewProviderDatum.h"
#include "TaskDatumParameters.h"
#include "Workbench.h"
#include <App/Part.h>
#include <Mod/PartDesign/App/DatumPoint.h>
#include <Mod/PartDesign/App/DatumLine.h>
#include <Mod/PartDesign/App/DatumPlane.h>
@ -314,3 +315,39 @@ void ViewProviderDatum::unsetEdit(int ModNum)
}
}
Base::BoundBox3d ViewProviderDatum::getRelevantExtents()
{
Base::BoundBox3d bbox;
PartDesign::Body* body = static_cast<PartDesign::Body*>(Part::BodyBase::findBodyOf(this->getObject()));
if (body != NULL)
bbox = body->getBoundBox();
else {
App::Part* part = getPartFor(this->getObject(),false);
std::vector<App::DocumentObject*> objs;
if(part)
objs = part->getObjectsOfType(Part::Feature::getClassTypeId());
else
objs = this->getObject()->getDocument()->getObjectsOfType(Part::Feature::getClassTypeId());
for(App::DocumentObject* obj: objs){
Part::Feature* feat = static_cast<Part::Feature*>(obj);
Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(feat);
if (vp->isVisible()){
Base::BoundBox3d bbf = feat->Shape.getBoundingBox();
if (bbf.CalcDiagonalLength() < Precision::Infinite())
bbox.Add(bbf);
}
}
if (bbox.CalcDiagonalLength() < Precision::Confusion()){
bbox.Add(Base::Vector3d(-10.0,-10.0,-10.0));
bbox.Add(Base::Vector3d(10.0,10.0,10.0));
}
}
bbox.Enlarge(0.1 * bbox.CalcDiagonalLength());
return bbox;
}

View File

@ -25,6 +25,7 @@
#define PARTGUI_ViewProviderDatum_H
#include "Gui/ViewProviderGeometryObject.h"
#include <Base/BoundBox.h>
namespace PartDesignGui {
@ -64,6 +65,19 @@ protected:
virtual bool setEdit(int ModNum);
virtual void unsetEdit(int ModNum);
//
/**
* @brief getRelevantExtents computes the bounding box of the objects
* relevant to the datum feature, which is intended to be used for
* determinimg the size of the rendered piece of the datum.
* @return Bounding box of body, if the datum is in a body. Bounding box of
* all visible shapes of a part, if in a part but not in a body. Bounding
* box of all visible Part::Feature-derived objects if just in a document.
* This behavior is subject to change.
*/
virtual Base::BoundBox3d getRelevantExtents();
protected:
SoSeparator* pShapeSep;
std::string oldWb;

View File

@ -47,7 +47,6 @@
#include <Gui/Control.h>
#include <Gui/Command.h>
#include <Gui/Application.h>
#include <Mod/PartDesign/App/Body.h>
using namespace PartDesignGui;
@ -80,12 +79,9 @@ void ViewProviderDatumLine::updateData(const App::Property* prop)
Base::Vector3d dir(0,0,1);
// Get limits of the line from bounding box of the body
PartDesign::Body* body = static_cast<PartDesign::Body*>(Part::BodyBase::findBodyOf(this->getObject()));
if (body == NULL)
return;
Base::BoundBox3d bbox = body->getBoundBox();
Base::BoundBox3d bbox = this->getRelevantExtents();
bbox = bbox.Transformed(plm.toMatrix());
bbox.Enlarge(0.1 * bbox.CalcDiagonalLength());
Base::Vector3d p1, p2;
if (bbox.IsInBox(base)) {
bbox.IntersectionPoint(base, dir, p1, Precision::Confusion());

View File

@ -48,7 +48,6 @@
#include <Gui/Control.h>
#include <Gui/Command.h>
#include <Gui/Application.h>
#include <Mod/PartDesign/App/Body.h>
using namespace PartDesignGui;
@ -81,10 +80,7 @@ void ViewProviderDatumPlane::updateData(const App::Property* prop)
Base::Vector3d normal(0,0,1);
// Get limits of the plane from bounding box of the body
PartDesign::Body* body = static_cast<PartDesign::Body*>(Part::BodyBase::findBodyOf(this->getObject()));
if (body == NULL)
return;
Base::BoundBox3d bbox = body->getBoundBox();
Base::BoundBox3d bbox = this->getRelevantExtents();
bbox = bbox.Transformed(plm.toMatrix());
double dlength = bbox.CalcDiagonalLength();
if (dlength < Precision::Confusion())