Merge branch 'master' of git://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad
This commit is contained in:
commit
7aeed0695a
|
@ -345,6 +345,14 @@ void Document::abortTransaction()
|
|||
}
|
||||
}
|
||||
|
||||
bool Document::hasPendingTransaction() const
|
||||
{
|
||||
if (d->activeUndoTransaction)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Document::clearUndos()
|
||||
{
|
||||
if (d->activeUndoTransaction)
|
||||
|
@ -738,11 +746,13 @@ Document::readObjects(Base::XMLReader& reader)
|
|||
// otherwise we may cause a dependency to itself
|
||||
// Example: Object 'Cut001' references object 'Cut' and removing the
|
||||
// digits we make an object 'Cut' referencing itself.
|
||||
App::DocumentObject* o = addObject(type.c_str(),name.c_str());
|
||||
objs.push_back(o);
|
||||
// use this name for the later access because an object with
|
||||
// the given name may already exist
|
||||
reader.addName(name.c_str(), o->getNameInDocument());
|
||||
App::DocumentObject* obj = addObject(type.c_str(),name.c_str());
|
||||
if (obj) {
|
||||
objs.push_back(obj);
|
||||
// use this name for the later access because an object with
|
||||
// the given name may already exist
|
||||
reader.addName(name.c_str(), obj->getNameInDocument());
|
||||
}
|
||||
}
|
||||
catch (Base::Exception&) {
|
||||
Base::Console().Message("Cannot create object '%s'\n", name.c_str());
|
||||
|
|
|
@ -208,6 +208,8 @@ public:
|
|||
void commitTransaction();
|
||||
/// Abort the actually running transaction.
|
||||
void abortTransaction();
|
||||
/// Check if a transaction is open
|
||||
bool hasPendingTransaction() const;
|
||||
/// Set the Undo limit in Byte!
|
||||
void setUndoLimit(unsigned int UndoMemSize=0);
|
||||
/// Returns the actual memory consumption of the Undo redo stuff.
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <sstream>
|
||||
# include <QDir>
|
||||
# include <QKeySequence>
|
||||
# include <QMessageBox>
|
||||
|
@ -389,6 +390,11 @@ void Command::abortCommand(void)
|
|||
Gui::Application::Instance->activeDocument()->abortCommand();
|
||||
}
|
||||
|
||||
bool Command::hasPendingCommand(void)
|
||||
{
|
||||
return Gui::Application::Instance->activeDocument()->hasPendingCommand();
|
||||
}
|
||||
|
||||
bool Command::_blockCmd = false;
|
||||
|
||||
void Command::blockCommand(bool block)
|
||||
|
@ -447,6 +453,20 @@ void Command::copyVisual(const char* to, const char* attr_to, const char* from,
|
|||
doCommand(Gui,"Gui.ActiveDocument.%s.%s=Gui.ActiveDocument.%s.%s", to, attr_to, from, attr_from);
|
||||
}
|
||||
|
||||
std::string Command::getPythonTuple(const std::string& name, const std::vector<std::string>& subnames)
|
||||
{
|
||||
std::stringstream str;
|
||||
std::vector<std::string>::const_iterator last = --subnames.end();
|
||||
str << "(App.ActiveDocument." << name << ",[";
|
||||
for (std::vector<std::string>::const_iterator it = subnames.begin();it!=subnames.end();++it){
|
||||
str << "\"" << *it << "\"";
|
||||
if (it != last)
|
||||
str << ",";
|
||||
}
|
||||
str << "])";
|
||||
return str.str();
|
||||
}
|
||||
|
||||
const std::string Command::strToPython(const char* Str)
|
||||
{
|
||||
return Base::InterpreterSingleton::strToPython(Str);
|
||||
|
|
|
@ -209,6 +209,8 @@ public:
|
|||
static void commitCommand(void);
|
||||
/// Abort the Undo transaction on the active document
|
||||
static void abortCommand(void);
|
||||
/// Check if an Undo transaction is open on the active document
|
||||
static bool hasPendingCommand(void);
|
||||
/// Updates the (active) document (propagate changes)
|
||||
static void updateActive(void);
|
||||
/// Updates the (all or listed) documents (propagate changes)
|
||||
|
@ -237,6 +239,8 @@ public:
|
|||
static void runCommand(DoCmd_Type eType,const char* sCmd);
|
||||
static void copyVisual(const char* to, const char* attr, const char* from);
|
||||
static void copyVisual(const char* to, const char* attr_to, const char* from, const char* attr_from);
|
||||
/// Get Python tuple from object and sub-elements
|
||||
static std::string getPythonTuple(const std::string& name, const std::vector<std::string>& subnames);
|
||||
/// import an external module only once
|
||||
//static void addModule(const char* sModuleName);
|
||||
/// translate a string to a python string literal (needed e.g. in file names for windows...)
|
||||
|
|
|
@ -1067,6 +1067,7 @@ StdCmdRefresh::StdCmdRefresh()
|
|||
sStatusTip = QT_TR_NOOP("Recomputes the current active document");
|
||||
sPixmap = "view-refresh";
|
||||
sAccel = keySequenceToAccel(QKeySequence::Refresh);
|
||||
eType = AlterDoc | Alter3DView | AlterSelection | ForEdit;
|
||||
}
|
||||
|
||||
void StdCmdRefresh::activated(int iMsg)
|
||||
|
|
|
@ -64,20 +64,22 @@ public:
|
|||
/// This method start an Task dialog in the TaskView
|
||||
void showDialog(Gui::TaskView::TaskDialog *dlg);
|
||||
Gui::TaskView::TaskDialog* activeDialog() const;
|
||||
void closeDialog();
|
||||
//@}
|
||||
|
||||
/** @name task view handling
|
||||
*/
|
||||
//@{
|
||||
Gui::TaskView::TaskView* taskPanel() const;
|
||||
void showTaskView();
|
||||
//@}
|
||||
|
||||
bool isAllowedAlterDocument(void) const;
|
||||
bool isAllowedAlterView(void) const;
|
||||
bool isAllowedAlterSelection(void) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void closeDialog();
|
||||
void showTaskView();
|
||||
|
||||
private Q_SLOTS:
|
||||
/// This get called by the TaskView when the Dialog is finished
|
||||
void closedDialog();
|
||||
|
|
|
@ -1090,7 +1090,12 @@ void Document::commitCommand(void)
|
|||
|
||||
void Document::abortCommand(void)
|
||||
{
|
||||
getDocument()->abortTransaction();
|
||||
getDocument()->abortTransaction();
|
||||
}
|
||||
|
||||
bool Document::hasPendingCommand(void) const
|
||||
{
|
||||
return getDocument()->hasPendingTransaction();
|
||||
}
|
||||
|
||||
/// Get a string vector with the 'Undo' actions
|
||||
|
|
|
@ -181,6 +181,8 @@ public:
|
|||
void commitCommand(void);
|
||||
/// Abort the Undo transaction on the document
|
||||
void abortCommand(void);
|
||||
/// Check if an Undo transaction is open
|
||||
bool hasPendingCommand(void) const;
|
||||
/// Get an Undo string vector with the Undo names
|
||||
std::vector<std::string> getUndoVector(void) const;
|
||||
/// Get an Redo string vector with the Redo names
|
||||
|
|
|
@ -724,7 +724,10 @@ void NavigationStyle::zoomByCursor(const SbVec2f & thispos, const SbVec2f & prev
|
|||
{
|
||||
// There is no "geometrically correct" value, 20 just seems to give
|
||||
// about the right "feel".
|
||||
zoom(viewer->getCamera(), (thispos[1] - prevpos[1]) * 10.0f/*20.0f*/);
|
||||
float value = (thispos[1] - prevpos[1]) * 10.0f/*20.0f*/;
|
||||
if (this->invertZoom)
|
||||
value = -value;
|
||||
zoom(viewer->getCamera(), value);
|
||||
}
|
||||
|
||||
void NavigationStyle::zoomIn()
|
||||
|
|
|
@ -255,7 +255,12 @@ void TreeWidget::onStartEditing()
|
|||
Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
|
||||
MDIView *view = doc->getActiveView();
|
||||
if (view) getMainWindow()->setActiveWindow(view);
|
||||
doc->setEdit(objitem->object(), edit);
|
||||
// open a transaction before starting edit mode
|
||||
std::string cmd("Edit ");
|
||||
cmd += obj->Label.getValue();
|
||||
doc->openCommand(cmd.c_str());
|
||||
bool ok = doc->setEdit(objitem->object(), edit);
|
||||
if (!ok) doc->abortCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,6 +273,7 @@ void TreeWidget::onFinishEditing()
|
|||
App::DocumentObject* obj = objitem->object()->getObject();
|
||||
if (!obj) return;
|
||||
Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
|
||||
doc->commitCommand();
|
||||
doc->resetEdit();
|
||||
doc->getDocument()->recompute();
|
||||
}
|
||||
|
|
|
@ -233,6 +233,53 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
<< "Mesh_Segmentation"
|
||||
<< "Mesh_VertexCurvature";
|
||||
|
||||
// Sketch **************************************************************************************************
|
||||
|
||||
Gui::MenuItem* sketch = new Gui::MenuItem(menuBar);
|
||||
sketch->setCommand("S&ketch");
|
||||
|
||||
Gui::MenuItem* geom = new Gui::MenuItem();
|
||||
geom->setCommand("Sketcher geometries");
|
||||
*geom << "Sketcher_CreatePoint"
|
||||
<< "Sketcher_CreateArc"
|
||||
<< "Sketcher_CreateCircle"
|
||||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
<< "Sketcher_ToggleConstruction";
|
||||
|
||||
Gui::MenuItem* cons = new Gui::MenuItem();
|
||||
cons->setCommand("Sketcher constraints");
|
||||
*cons << "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainAngle";
|
||||
|
||||
*sketch
|
||||
<< "Sketcher_NewSketch"
|
||||
<< "Sketcher_LeaveSketch"
|
||||
<< "Sketcher_ViewSketch"
|
||||
<< "Sketcher_MapSketch"
|
||||
<< geom
|
||||
<< cons
|
||||
;
|
||||
|
||||
// Part ****************************************************************************************************
|
||||
|
||||
Gui::MenuItem* part = new Gui::MenuItem(menuBar);
|
||||
|
@ -251,44 +298,16 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
Gui::MenuItem* PartDesign = new Gui::MenuItem();
|
||||
PartDesign->setCommand("Part design");
|
||||
|
||||
*PartDesign << "Sketcher_NewSketch"
|
||||
<< "Sketcher_LeaveSketch"
|
||||
<< "Sketcher_ViewSketch"
|
||||
<< "Sketcher_MapSketch"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreatePoint"
|
||||
<< "Sketcher_CreateArc"
|
||||
<< "Sketcher_CreateCircle"
|
||||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
<< "Sketcher_ToggleConstruction"
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainAngle"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
<< "Separator"
|
||||
<< "PartDesign_Pad"
|
||||
*PartDesign << "PartDesign_Pad"
|
||||
<< "PartDesign_Pocket"
|
||||
<< "PartDesign_Revolution"
|
||||
<< "PartDesign_Groove"
|
||||
<< "PartDesign_Fillet"
|
||||
<< "PartDesign_Chamfer";
|
||||
|
||||
<< "PartDesign_Chamfer"
|
||||
<< "PartDesign_Mirrored"
|
||||
<< "PartDesign_LinearPattern"
|
||||
<< "PartDesign_PolarPattern"
|
||||
<< "PartDesign_MultiTransform";
|
||||
|
||||
*part << para
|
||||
<< PartDesign
|
||||
|
@ -478,46 +497,58 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
<< "Part_Chamfer"
|
||||
;
|
||||
|
||||
// Sketch based
|
||||
Gui::ToolBarItem* sketch_based = new Gui::ToolBarItem( root );
|
||||
sketch_based->setCommand("Sketch based");
|
||||
*sketch_based
|
||||
<< "Sketcher_NewSketch"
|
||||
<< "Sketcher_LeaveSketch"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreatePoint"
|
||||
<< "Sketcher_CreateArc"
|
||||
<< "Sketcher_CreateCircle"
|
||||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
<< "Sketcher_ToggleConstruction"
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainAngle"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
<< "Separator"
|
||||
Gui::ToolBarItem* geom = new Gui::ToolBarItem(root);
|
||||
geom->setCommand("Sketcher geometries");
|
||||
*geom << "Sketcher_NewSketch"
|
||||
<< "Sketcher_LeaveSketch"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreatePoint"
|
||||
<< "Sketcher_CreateArc"
|
||||
<< "Sketcher_CreateCircle"
|
||||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
<< "Sketcher_ToggleConstruction"
|
||||
/*<< "Sketcher_CreateText"*/
|
||||
/*<< "Sketcher_CreateDraftLine"*/;
|
||||
|
||||
Gui::ToolBarItem* cons = new Gui::ToolBarItem(root);
|
||||
cons->setCommand("Sketcher constraints");
|
||||
*cons << "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainAngle";
|
||||
|
||||
// Part Design
|
||||
Gui::ToolBarItem* partdesign = new Gui::ToolBarItem(root);
|
||||
partdesign->setCommand("Part Design");
|
||||
*partdesign
|
||||
<< "PartDesign_Pad"
|
||||
<< "PartDesign_Pocket"
|
||||
<< "PartDesign_Revolution"
|
||||
<< "PartDesign_Groove"
|
||||
<< "PartDesign_Fillet"
|
||||
<< "PartDesign_Chamfer";
|
||||
|
||||
<< "PartDesign_Chamfer"
|
||||
<< "PartDesign_Mirrored"
|
||||
<< "PartDesign_LinearPattern"
|
||||
<< "PartDesign_PolarPattern"
|
||||
<< "PartDesign_MultiTransform";
|
||||
|
||||
// Drawing
|
||||
Gui::ToolBarItem* drawing = new Gui::ToolBarItem( root );
|
||||
|
|
|
@ -199,9 +199,9 @@ App::DocumentObjectExecReturn *FeatureViewPart::execute(void)
|
|||
<< " transform=\"rotate("<< Rotation.getValue() << ","<< X.getValue()<<","<<Y.getValue()<<") translate("<< X.getValue()<<","<<Y.getValue()<<") scale("<< Scale.getValue()<<","<<Scale.getValue()<<")\"" << endl
|
||||
<< " >" << endl;
|
||||
|
||||
ProjectionAlgos::SvgExtractionType type = ProjectionAlgos::Plain;
|
||||
if (hidden) type = (ProjectionAlgos::SvgExtractionType)(type|ProjectionAlgos::WithHidden);
|
||||
if (smooth) type = (ProjectionAlgos::SvgExtractionType)(type|ProjectionAlgos::WithSmooth);
|
||||
ProjectionAlgos::ExtractionType type = ProjectionAlgos::Plain;
|
||||
if (hidden) type = (ProjectionAlgos::ExtractionType)(type|ProjectionAlgos::WithHidden);
|
||||
if (smooth) type = (ProjectionAlgos::ExtractionType)(type|ProjectionAlgos::WithSmooth);
|
||||
result << Alg.getSVG(type, this->LineWidth.getValue() / this->Scale.getValue(), this->Tolerance.getValue());
|
||||
|
||||
result << "</g>" << endl;
|
||||
|
|
|
@ -149,7 +149,7 @@ void ProjectionAlgos::execute(void)
|
|||
|
||||
}
|
||||
|
||||
std::string ProjectionAlgos::getSVG(SvgExtractionType type, float scale, float tolerance)
|
||||
std::string ProjectionAlgos::getSVG(ExtractionType type, float scale, float tolerance)
|
||||
{
|
||||
std::stringstream result;
|
||||
SVGOutput output;
|
||||
|
@ -251,7 +251,7 @@ std::string ProjectionAlgos::getSVG(SvgExtractionType type, float scale, float t
|
|||
|
||||
/* dxf output section - Dan Falck 2011/09/25 */
|
||||
|
||||
std::string ProjectionAlgos::getDXF(SvgExtractionType type, float scale, float tolerance)
|
||||
std::string ProjectionAlgos::getDXF(ExtractionType type, float scale, float tolerance)
|
||||
{
|
||||
std::stringstream result;
|
||||
DXFOutput output;
|
||||
|
|
|
@ -45,14 +45,14 @@ public:
|
|||
void execute(void);
|
||||
static TopoDS_Shape invertY(const TopoDS_Shape&);
|
||||
|
||||
enum SvgExtractionType {
|
||||
enum ExtractionType {
|
||||
Plain = 0,
|
||||
WithHidden = 1,
|
||||
WithSmooth = 2
|
||||
};
|
||||
|
||||
std::string getSVG(SvgExtractionType type, float scale, float tolerance);
|
||||
std::string getDXF(SvgExtractionType type, float scale, float tolerance);//added by Dan Falck 2011/09/25
|
||||
std::string getSVG(ExtractionType type, float scale, float tolerance);
|
||||
std::string getDXF(ExtractionType type, float scale, float tolerance);//added by Dan Falck 2011/09/25
|
||||
|
||||
|
||||
const TopoDS_Shape &Input;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
|
||||
#include "DrawingView.h"
|
||||
#include <Mod/Drawing/App/FeaturePage.h>
|
||||
#include <Mod/Drawing/App/FeatureViewPart.h>
|
||||
#include <Mod/Drawing/App/ProjectionAlgos.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
|
@ -115,16 +118,6 @@ exporter(PyObject *self, PyObject *args)
|
|||
if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
|
||||
if (obj->getTypeId().isDerivedFrom(Drawing::FeaturePage::getClassTypeId())) {
|
||||
std::string fn = static_cast<Drawing::FeaturePage*>(obj)->PageResult.getValue();
|
||||
Base::FileInfo fi_in(fn);
|
||||
Base::ifstream str_in(fi_in, std::ios::in | std::ios::binary);
|
||||
if (!str_in) {
|
||||
std::stringstream str;
|
||||
str << "Cannot open file '" << fn << "' for reading";
|
||||
PyErr_SetString(PyExc_IOError, str.str().c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Base::FileInfo fi_out(filename);
|
||||
Base::ofstream str_out(fi_out, std::ios::out | std::ios::binary);
|
||||
if (!str_out) {
|
||||
|
@ -133,14 +126,64 @@ exporter(PyObject *self, PyObject *args)
|
|||
PyErr_SetString(PyExc_IOError, str.str().c_str());
|
||||
return NULL;
|
||||
}
|
||||
if (fi_out.hasExtension("svg")) {
|
||||
std::string fn = static_cast<Drawing::FeaturePage*>(obj)->PageResult.getValue();
|
||||
Base::FileInfo fi_in(fn);
|
||||
Base::ifstream str_in(fi_in, std::ios::in | std::ios::binary);
|
||||
if (!str_in) {
|
||||
std::stringstream str;
|
||||
str << "Cannot open file '" << fn << "' for reading";
|
||||
PyErr_SetString(PyExc_IOError, str.str().c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str_in >> str_out.rdbuf();
|
||||
str_in.close();
|
||||
str_out.close();
|
||||
break;
|
||||
str_in >> str_out.rdbuf();
|
||||
str_in.close();
|
||||
str_out.close();
|
||||
break;
|
||||
}
|
||||
else if (fi_out.hasExtension("dxf")) {
|
||||
const std::vector<App::DocumentObject*>& views = static_cast<Drawing::FeaturePage*>(obj)->Group.getValues();
|
||||
for (std::vector<App::DocumentObject*>::const_iterator it = views.begin(); it != views.end(); ++it) {
|
||||
if ((*it)->getTypeId().isDerivedFrom(Drawing::FeatureViewPart::getClassTypeId())) {
|
||||
Drawing::FeatureViewPart* view = static_cast<Drawing::FeatureViewPart*>(*it);
|
||||
std::string viewName = view->Label.getValue();
|
||||
App::DocumentObject* link = view->Source.getValue();
|
||||
if (!link) {
|
||||
PyErr_SetString(PyExc_Exception, "No object linked");
|
||||
return 0;
|
||||
}
|
||||
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
PyErr_SetString(PyExc_TypeError, "Linked object is not a Part object");
|
||||
return 0;
|
||||
}
|
||||
TopoDS_Shape shape = static_cast<Part::Feature*>(link)->Shape.getShape()._Shape;
|
||||
if (!shape.IsNull()) {
|
||||
Base::Vector3f dir = view->Direction.getValue();
|
||||
bool hidden = view->ShowHiddenLines.getValue();
|
||||
bool smooth = view->ShowSmoothLines.getValue();
|
||||
Drawing::ProjectionAlgos::ExtractionType type = Drawing::ProjectionAlgos::Plain;
|
||||
if (hidden) type = (Drawing::ProjectionAlgos::ExtractionType)(type|Drawing::ProjectionAlgos::WithHidden);
|
||||
if (smooth) type = (Drawing::ProjectionAlgos::ExtractionType)(type|Drawing::ProjectionAlgos::WithSmooth);
|
||||
float scale = view->Scale.getValue();
|
||||
float tol = view->Tolerance.getValue();
|
||||
|
||||
Drawing::ProjectionAlgos project(shape, dir);
|
||||
str_out << project.getDXF(type, scale, tol);
|
||||
break; // TODO: How to add several shapes?
|
||||
}
|
||||
}
|
||||
}
|
||||
str_out.close();
|
||||
break;
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "Export of page object as this file format is not supported by Drawing module");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "Export as SVG of this object type is not supported by Drawing module");
|
||||
PyErr_SetString(PyExc_TypeError, "Export of this object type is not supported by Drawing module");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,4 +116,4 @@ Gui.addWorkbench(DrawingWorkbench())
|
|||
|
||||
# Append the open handler
|
||||
FreeCAD.addImportType("Drawing (*.svg *.svgz)","DrawingGui")
|
||||
FreeCAD.addExportType("Drawing (*.svg *.svgz)","DrawingGui")
|
||||
FreeCAD.addExportType("Drawing (*.svg *.svgz *.dxf)","DrawingGui")
|
||||
|
|
|
@ -199,6 +199,7 @@ void PartExport initPart()
|
|||
Part::Loft ::init();
|
||||
Part::Sweep ::init();
|
||||
Part::Offset ::init();
|
||||
Part::Thickness ::init();
|
||||
|
||||
// Geometry types
|
||||
Part::Geometry ::init();
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
# include <BRepBuilderAPI_MakeWire.hxx>
|
||||
# include <BRepOffsetAPI_MakePipeShell.hxx>
|
||||
# include <TopTools_ListIteratorOfListOfShape.hxx>
|
||||
# include <TopExp_Explorer.hxx>
|
||||
# include <Precision.hxx>
|
||||
#endif
|
||||
|
||||
|
@ -375,11 +376,6 @@ short Offset::mustExecute() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Offset::onChanged(const App::Property* prop)
|
||||
{
|
||||
Part::Feature::onChanged(prop);
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn *Offset::execute(void)
|
||||
{
|
||||
App::DocumentObject* source = Source.getValue();
|
||||
|
@ -399,3 +395,78 @@ App::DocumentObjectExecReturn *Offset::execute(void)
|
|||
this->Shape.setValue(shape);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const char* Part::Thickness::ModeEnums[]= {"Skin","Pipe", "RectoVerso",NULL};
|
||||
const char* Part::Thickness::JoinEnums[]= {"Arc","Tangent", "Intersection",NULL};
|
||||
|
||||
PROPERTY_SOURCE(Part::Thickness, Part::Feature)
|
||||
|
||||
Thickness::Thickness()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(Faces,(0),"Thickness",App::Prop_None,"Source shape");
|
||||
ADD_PROPERTY_TYPE(Value,(1.0),"Thickness",App::Prop_None,"Thickness value");
|
||||
ADD_PROPERTY_TYPE(Mode,(long(0)),"Thickness",App::Prop_None,"Mode");
|
||||
Mode.setEnums(ModeEnums);
|
||||
ADD_PROPERTY_TYPE(Join,(long(0)),"Thickness",App::Prop_None,"Join type");
|
||||
Join.setEnums(JoinEnums);
|
||||
ADD_PROPERTY_TYPE(Intersection,(false),"Thickness",App::Prop_None,"Intersection");
|
||||
ADD_PROPERTY_TYPE(SelfIntersection,(false),"Thickness",App::Prop_None,"Self Intersection");
|
||||
}
|
||||
|
||||
short Thickness::mustExecute() const
|
||||
{
|
||||
if (Faces.isTouched())
|
||||
return 1;
|
||||
if (Value.isTouched())
|
||||
return 1;
|
||||
if (Mode.isTouched())
|
||||
return 1;
|
||||
if (Join.isTouched())
|
||||
return 1;
|
||||
if (Intersection.isTouched())
|
||||
return 1;
|
||||
if (SelfIntersection.isTouched())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn *Thickness::execute(void)
|
||||
{
|
||||
App::DocumentObject* source = Faces.getValue();
|
||||
if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
|
||||
return new App::DocumentObjectExecReturn("No source shape linked.");
|
||||
const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
|
||||
if (shape.isNull())
|
||||
return new App::DocumentObjectExecReturn("Source shape is empty.");
|
||||
|
||||
int countSolids = 0;
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(shape._Shape,TopAbs_SOLID);
|
||||
for (;xp.More(); xp.Next()) {
|
||||
countSolids++;
|
||||
}
|
||||
if (countSolids != 1)
|
||||
return new App::DocumentObjectExecReturn("Source shape is not a solid.");
|
||||
|
||||
TopTools_ListOfShape closingFaces;
|
||||
const std::vector<std::string>& subStrings = Faces.getSubValues();
|
||||
for (std::vector<std::string>::const_iterator it = subStrings.begin(); it != subStrings.end(); ++it) {
|
||||
TopoDS_Face face = TopoDS::Face(shape.getSubShape(it->c_str()));
|
||||
closingFaces.Append(face);
|
||||
}
|
||||
|
||||
double thickness = Value.getValue();
|
||||
double tol = Precision::Confusion();
|
||||
bool inter = Intersection.getValue();
|
||||
bool self = SelfIntersection.getValue();
|
||||
short mode = (short)Mode.getValue();
|
||||
short join = (short)Join.getValue();
|
||||
|
||||
if (fabs(thickness) > 2*tol)
|
||||
this->Shape.setValue(shape.makeThickSolid(closingFaces, thickness, tol, inter, self, mode, join));
|
||||
else
|
||||
this->Shape.setValue(shape);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
|
|
@ -132,8 +132,34 @@ public:
|
|||
}
|
||||
//@}
|
||||
|
||||
protected:
|
||||
void onChanged (const App::Property* prop);
|
||||
private:
|
||||
static const char* ModeEnums[];
|
||||
static const char* JoinEnums[];
|
||||
};
|
||||
|
||||
class Thickness : public Part::Feature
|
||||
{
|
||||
PROPERTY_HEADER(Part::Thickness);
|
||||
|
||||
public:
|
||||
Thickness();
|
||||
|
||||
App::PropertyLinkSub Faces;
|
||||
App::PropertyFloat Value;
|
||||
App::PropertyEnumeration Mode;
|
||||
App::PropertyEnumeration Join;
|
||||
App::PropertyBool Intersection;
|
||||
App::PropertyBool SelfIntersection;
|
||||
|
||||
/** @name methods override feature */
|
||||
//@{
|
||||
/// recalculate the feature
|
||||
App::DocumentObjectExecReturn *execute(void);
|
||||
short mustExecute() const;
|
||||
const char* getViewProviderName(void) const {
|
||||
return "PartGui::ViewProviderThickness";
|
||||
}
|
||||
//@}
|
||||
|
||||
private:
|
||||
static const char* ModeEnums[];
|
||||
|
|
|
@ -84,10 +84,17 @@
|
|||
</Attribute>
|
||||
<Attribute Name="Wire" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The Wire of this face</UserDocu>
|
||||
<UserDocu>The outer wire of this face
|
||||
deprecated -- please use OuterWire</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Wire" Type="Object"/>
|
||||
</Attribute>
|
||||
<Attribute Name="OuterWire" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The outer wire of this face</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="OuterWire" Type="Object"/>
|
||||
</Attribute>
|
||||
<Attribute Name="CenterOfMass" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
|
|
|
@ -548,7 +548,22 @@ Py::Tuple TopoShapeFacePy::getParameterRange(void) const
|
|||
return t;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
Py::Object TopoShapeFacePy::getWire(void) const
|
||||
{
|
||||
try {
|
||||
Py::Object sys_out(PySys_GetObject(const_cast<char*>("stdout")));
|
||||
Py::Callable write(sys_out.getAttr("write"));
|
||||
Py::Tuple arg(1);
|
||||
arg.setItem(0, Py::String("Warning: Wire is deprecated, please use OuterWire\n"));
|
||||
write.apply(arg);
|
||||
}
|
||||
catch (const Py::Exception&) {
|
||||
}
|
||||
return getOuterWire();
|
||||
}
|
||||
|
||||
Py::Object TopoShapeFacePy::getOuterWire(void) const
|
||||
{
|
||||
const TopoDS_Shape& clSh = getTopoShapePtr()->_Shape;
|
||||
if (clSh.IsNull())
|
||||
|
|
|
@ -106,6 +106,7 @@ void PartGuiExport initPartGui()
|
|||
PartGui::ViewProviderLoft ::init();
|
||||
PartGui::ViewProviderSweep ::init();
|
||||
PartGui::ViewProviderOffset ::init();
|
||||
PartGui::ViewProviderThickness ::init();
|
||||
PartGui::ViewProviderCustom ::init();
|
||||
PartGui::ViewProviderCustomPython ::init();
|
||||
PartGui::ViewProviderBoolean ::init();
|
||||
|
|
|
@ -43,6 +43,7 @@ set(PartGui_MOC_HDRS
|
|||
TaskLoft.h
|
||||
TaskOffset.h
|
||||
TaskSweep.h
|
||||
TaskThickness.h
|
||||
TaskCheckGeometry.h
|
||||
)
|
||||
fc_wrap_cpp(PartGui_MOC_SRCS ${PartGui_MOC_HDRS})
|
||||
|
@ -166,6 +167,8 @@ SET(PartGui_SRCS
|
|||
TaskSweep.cpp
|
||||
TaskSweep.h
|
||||
TaskSweep.ui
|
||||
TaskThickness.cpp
|
||||
TaskThickness.h
|
||||
TaskCheckGeometry.cpp
|
||||
TaskCheckGeometry.h
|
||||
)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
# include <QPointer>
|
||||
# include <Standard_math.hxx>
|
||||
# include <TopoDS_Shape.hxx>
|
||||
# include <TopExp_Explorer.hxx>
|
||||
# include <Inventor/events/SoMouseButtonEvent.h>
|
||||
#endif
|
||||
|
||||
|
@ -1035,6 +1036,78 @@ bool CmdPartOffset::isActive(void)
|
|||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
DEF_STD_CMD_A(CmdPartThickness);
|
||||
|
||||
CmdPartThickness::CmdPartThickness()
|
||||
: Command("Part_Thickness")
|
||||
{
|
||||
sAppModule = "Part";
|
||||
sGroup = QT_TR_NOOP("Part");
|
||||
sMenuText = QT_TR_NOOP("Thickness...");
|
||||
sToolTipText = QT_TR_NOOP("Utility to apply a thickness");
|
||||
sWhatsThis = sToolTipText;
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Part_Thickness";
|
||||
}
|
||||
|
||||
void CmdPartThickness::activated(int iMsg)
|
||||
{
|
||||
Gui::SelectionFilter faceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1..");
|
||||
if (!faceFilter.match()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(),
|
||||
QApplication::translate("CmdPartThickness", "Wrong selection"),
|
||||
QApplication::translate("CmdPartThickness", "Selected one or more faces of a shape"));
|
||||
return;
|
||||
}
|
||||
|
||||
// get the selected object
|
||||
const std::vector<Gui::SelectionObject>& result = faceFilter.Result[0];
|
||||
std::string selection = result.front().getAsPropertyLinkSubString();
|
||||
|
||||
const Part::Feature* shape = static_cast<const Part::Feature*>(result.front().getObject());
|
||||
if (shape->Shape.getValue().IsNull())
|
||||
return;
|
||||
int countSolids = 0;
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(shape->Shape.getValue(),TopAbs_SOLID);
|
||||
for (;xp.More(); xp.Next()) {
|
||||
countSolids++;
|
||||
}
|
||||
if (countSolids != 1) {
|
||||
QMessageBox::warning(Gui::getMainWindow(),
|
||||
QApplication::translate("CmdPartThickness", "Wrong selection"),
|
||||
QApplication::translate("CmdPartThickness", "Selected shape is not a solid"));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string thick = getUniqueObjectName("Thickness");
|
||||
|
||||
openCommand("Make Thickness");
|
||||
doCommand(Doc,"App.ActiveDocument.addObject(\"Part::Thickness\",\"%s\")",thick.c_str());
|
||||
doCommand(Doc,"App.ActiveDocument.%s.Faces = %s" ,thick.c_str(), selection.c_str());
|
||||
doCommand(Doc,"App.ActiveDocument.%s.Value = 1.0",thick.c_str());
|
||||
updateActive();
|
||||
if (isActiveObjectValid())
|
||||
doCommand(Gui,"Gui.ActiveDocument.hide(\"%s\")",shape->getNameInDocument());
|
||||
doCommand(Gui,"Gui.ActiveDocument.setEdit('%s')",thick.c_str());
|
||||
|
||||
//commitCommand();
|
||||
adjustCameraPosition();
|
||||
|
||||
copyVisual(thick.c_str(), "ShapeColor", shape->getNameInDocument());
|
||||
copyVisual(thick.c_str(), "LineColor" , shape->getNameInDocument());
|
||||
copyVisual(thick.c_str(), "PointColor", shape->getNameInDocument());
|
||||
}
|
||||
|
||||
bool CmdPartThickness::isActive(void)
|
||||
{
|
||||
Base::Type partid = Base::Type::fromName("Part::Feature");
|
||||
bool objectsSelected = Gui::Selection().countObjectsOfType(partid) > 0;
|
||||
return (objectsSelected && !Gui::Control().activeDialog());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
DEF_STD_CMD_A(CmdShapeInfo);
|
||||
|
||||
CmdShapeInfo::CmdShapeInfo()
|
||||
|
@ -1306,5 +1379,6 @@ void CreatePartCommands(void)
|
|||
rcCmdMgr.addCommand(new CmdPartLoft());
|
||||
rcCmdMgr.addCommand(new CmdPartSweep());
|
||||
rcCmdMgr.addCommand(new CmdPartOffset());
|
||||
rcCmdMgr.addCommand(new CmdPartThickness());
|
||||
rcCmdMgr.addCommand(new CmdCheckGeometry());
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<file>icons/Part_ShapeInfo.svg</file>
|
||||
<file>icons/Part_Sphere.svg</file>
|
||||
<file>icons/Part_Sweep.svg</file>
|
||||
<file>icons/Part_Thickness.svg</file>
|
||||
<file>icons/Part_Torus.svg</file>
|
||||
<file>icons/preferences-part_design.svg</file>
|
||||
<file>icons/Tree_Part.svg</file>
|
||||
|
|
156
src/Mod/Part/Gui/Resources/icons/Part_Thickness.svg
Normal file
156
src/Mod/Part/Gui/Resources/icons/Part_Thickness.svg
Normal file
|
@ -0,0 +1,156 @@
|
|||
<?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="svg2682"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="Part_Extrude.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2684">
|
||||
<linearGradient
|
||||
id="linearGradient3593">
|
||||
<stop
|
||||
style="stop-color:#c8e0f9;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3595" />
|
||||
<stop
|
||||
style="stop-color:#637dca;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3597" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3593"
|
||||
id="radialGradient3354"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="330.63791"
|
||||
cy="39.962704"
|
||||
fx="330.63791"
|
||||
fy="39.962704"
|
||||
r="19.571428"
|
||||
gradientTransform="matrix(0.9327663,0,0,0.9327663,-298.15651,8.1913381)" />
|
||||
<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="perspective2690" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3864"
|
||||
id="radialGradient2401"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.959337,5.1799939e-2,0,0.7352325,-29.610908,-1.2314128)"
|
||||
cx="51.105499"
|
||||
cy="23.807407"
|
||||
fx="51.105499"
|
||||
fy="23.807407"
|
||||
r="19.571428" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3864"
|
||||
id="radialGradient2404"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.2993671,-1.5757258e-2,8.4161044e-3,0.9850979,-94.354208,-10.998387)"
|
||||
cx="48.288067"
|
||||
cy="46.74614"
|
||||
fx="48.288067"
|
||||
fy="46.74614"
|
||||
r="19.571428" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3593"
|
||||
id="radialGradient3377"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.9327663,0,0,0.9327663,-267.16323,12.515981)"
|
||||
cx="317.68173"
|
||||
cy="35.227276"
|
||||
fx="317.68173"
|
||||
fy="35.227276"
|
||||
r="19.571428" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.75"
|
||||
inkscape:cx="61.342448"
|
||||
inkscape:cy="37.42735"
|
||||
inkscape:current-layer="g3381"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="758"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="19"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2687">
|
||||
<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="g3381">
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
id="path3379"
|
||||
d="M 36.363637,60.272727 L 59.454546,53.545455 L 62.363637,51.363636 L 62.363637,43.181818 L 54.909091,42.090909 L 36.363637,60.272727 z"
|
||||
style="opacity:0.63944205;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3354);fill-opacity:1;fill-rule:evenodd;stroke:#4b4dba;stroke-width:2.2;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 4.9501369,37.23429 L 36.070613,40.053788 L 35.816223,59.36629 L 5.1197308,56.292401 L 4.9501369,37.23429 z"
|
||||
id="rect2568"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3377);fill-opacity:1;fill-rule:evenodd;stroke:#4b4dba;stroke-width:2.20000000000000018;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 35.773823,40.117385 L 55.107525,31.319703 L 54.768337,49.869032 L 35.604229,59.429887 L 35.773823,40.117385 z"
|
||||
id="path3375"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="rect3633"
|
||||
d="M 23.530174,28.496274 L 55.6968,30.8755 L 36.406189,40.084227 L 4.2395647,37.705001 L 23.530174,28.496274 z"
|
||||
style="fill:url(#radialGradient2404);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2.2;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
|
@ -72,9 +72,10 @@ OffsetWidget::OffsetWidget(Part::Offset* offset, QWidget* parent)
|
|||
|
||||
d->offset = offset;
|
||||
d->ui.setupUi(this);
|
||||
d->ui.spinOffset->setValue(d->offset->Value.getValue());
|
||||
d->ui.spinOffset->setRange(-INT_MAX, INT_MAX);
|
||||
d->ui.spinOffset->setSingleStep(0.1);
|
||||
d->ui.spinOffset->setValue(d->offset->Value.getValue());
|
||||
d->ui.facesButton->hide();
|
||||
}
|
||||
|
||||
OffsetWidget::~OffsetWidget()
|
||||
|
@ -177,6 +178,7 @@ bool OffsetWidget::reject()
|
|||
// roll back the done things
|
||||
Gui::Command::abortCommand();
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
|
||||
Gui::Command::updateActive();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>256</width>
|
||||
<height>260</height>
|
||||
<width>264</width>
|
||||
<height>244</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -21,7 +21,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="2">
|
||||
<widget class="QDoubleSpinBox" name="spinOffset"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
|
@ -31,7 +31,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="modeType">
|
||||
<item>
|
||||
<property name="text">
|
||||
|
@ -57,7 +57,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="joinType">
|
||||
<item>
|
||||
<property name="text">
|
||||
|
@ -83,30 +83,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="selfIntersection">
|
||||
<property name="text">
|
||||
<string>Self-intersection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QCheckBox" name="updateView">
|
||||
<property name="text">
|
||||
<string>Update view</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="fillOffset">
|
||||
<property name="text">
|
||||
|
@ -114,6 +97,50 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="QLabel" name="labelFaces">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QPushButton" name="facesButton">
|
||||
<property name="text">
|
||||
<string>Faces</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>152</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QCheckBox" name="updateView">
|
||||
<property name="text">
|
||||
<string>Update view</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
|
|
311
src/Mod/Part/Gui/TaskThickness.cpp
Normal file
311
src/Mod/Part/Gui/TaskThickness.cpp
Normal file
|
@ -0,0 +1,311 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2012 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <QEventLoop>
|
||||
# include <QMessageBox>
|
||||
# include <QTextStream>
|
||||
#endif
|
||||
|
||||
#include "ui_TaskOffset.h"
|
||||
#include "TaskThickness.h"
|
||||
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/SelectionFilter.h>
|
||||
#include <Gui/ViewProvider.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <Mod/Part/App/PartFeatures.h>
|
||||
|
||||
|
||||
using namespace PartGui;
|
||||
|
||||
class ThicknessWidget::Private
|
||||
{
|
||||
public:
|
||||
Ui_TaskOffset ui;
|
||||
QEventLoop loop;
|
||||
QString text;
|
||||
std::string selection;
|
||||
Part::Thickness* thickness;
|
||||
Private()
|
||||
{
|
||||
}
|
||||
~Private()
|
||||
{
|
||||
}
|
||||
|
||||
class FaceSelection : public Gui::SelectionFilterGate
|
||||
{
|
||||
const App::DocumentObject* object;
|
||||
public:
|
||||
FaceSelection(const App::DocumentObject* obj)
|
||||
: Gui::SelectionFilterGate((Gui::SelectionFilter*)0), object(obj)
|
||||
{
|
||||
}
|
||||
bool allow(App::Document*pDoc, App::DocumentObject*pObj, const char*sSubName)
|
||||
{
|
||||
if (pObj != this->object)
|
||||
return false;
|
||||
if (!sSubName || sSubName[0] == '\0')
|
||||
return false;
|
||||
std::string element(sSubName);
|
||||
return element.substr(0,4) == "Face";
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/* TRANSLATOR PartGui::ThicknessWidget */
|
||||
|
||||
ThicknessWidget::ThicknessWidget(Part::Thickness* thickness, QWidget* parent)
|
||||
: d(new Private())
|
||||
{
|
||||
Gui::Application::Instance->runPythonCode("from FreeCAD import Base");
|
||||
Gui::Application::Instance->runPythonCode("import Part");
|
||||
|
||||
d->thickness = thickness;
|
||||
d->ui.setupUi(this);
|
||||
d->ui.spinOffset->setRange(-INT_MAX, INT_MAX);
|
||||
d->ui.spinOffset->setSingleStep(0.1);
|
||||
d->ui.spinOffset->setValue(d->thickness->Value.getValue());
|
||||
d->ui.labelOffset->setText(tr("Thickness"));
|
||||
d->ui.fillOffset->hide();
|
||||
}
|
||||
|
||||
ThicknessWidget::~ThicknessWidget()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
Part::Thickness* ThicknessWidget::getObject() const
|
||||
{
|
||||
return d->thickness;
|
||||
}
|
||||
|
||||
void ThicknessWidget::on_spinOffset_valueChanged(double val)
|
||||
{
|
||||
d->thickness->Value.setValue((float)val);
|
||||
if (d->ui.updateView->isChecked())
|
||||
d->thickness->getDocument()->recomputeFeature(d->thickness);
|
||||
}
|
||||
|
||||
void ThicknessWidget::on_modeType_activated(int val)
|
||||
{
|
||||
d->thickness->Mode.setValue(val);
|
||||
if (d->ui.updateView->isChecked())
|
||||
d->thickness->getDocument()->recomputeFeature(d->thickness);
|
||||
}
|
||||
|
||||
void ThicknessWidget::on_joinType_activated(int val)
|
||||
{
|
||||
d->thickness->Join.setValue((float)val);
|
||||
if (d->ui.updateView->isChecked())
|
||||
d->thickness->getDocument()->recomputeFeature(d->thickness);
|
||||
}
|
||||
|
||||
void ThicknessWidget::on_intersection_toggled(bool on)
|
||||
{
|
||||
d->thickness->Intersection.setValue(on);
|
||||
if (d->ui.updateView->isChecked())
|
||||
d->thickness->getDocument()->recomputeFeature(d->thickness);
|
||||
}
|
||||
|
||||
void ThicknessWidget::on_selfIntersection_toggled(bool on)
|
||||
{
|
||||
d->thickness->SelfIntersection.setValue(on);
|
||||
if (d->ui.updateView->isChecked())
|
||||
d->thickness->getDocument()->recomputeFeature(d->thickness);
|
||||
}
|
||||
|
||||
void ThicknessWidget::on_facesButton_clicked()
|
||||
{
|
||||
if (!d->loop.isRunning()) {
|
||||
QList<QWidget*> c = this->findChildren<QWidget*>();
|
||||
for (QList<QWidget*>::iterator it = c.begin(); it != c.end(); ++it)
|
||||
(*it)->setEnabled(false);
|
||||
d->ui.facesButton->setEnabled(true);
|
||||
d->ui.labelFaces->setText(tr("Select faces of the source object and press 'Done'"));
|
||||
d->ui.labelFaces->setEnabled(true);
|
||||
d->text = d->ui.facesButton->text();
|
||||
d->ui.facesButton->setText(tr("Done"));
|
||||
|
||||
Gui::Application::Instance->showViewProvider(d->thickness->Faces.getValue());
|
||||
Gui::Application::Instance->hideViewProvider(d->thickness);
|
||||
Gui::Selection().clearSelection();
|
||||
Gui::Selection().addSelectionGate(new Private::FaceSelection(d->thickness->Faces.getValue()));
|
||||
d->loop.exec();
|
||||
}
|
||||
else {
|
||||
QList<QWidget*> c = this->findChildren<QWidget*>();
|
||||
for (QList<QWidget*>::iterator it = c.begin(); it != c.end(); ++it)
|
||||
(*it)->setEnabled(true);
|
||||
d->ui.facesButton->setText(d->text);
|
||||
d->ui.labelFaces->clear();
|
||||
d->loop.quit();
|
||||
|
||||
d->selection = Gui::Command::getPythonTuple
|
||||
(d->thickness->Faces.getValue()->getNameInDocument(), d->thickness->Faces.getSubValues());
|
||||
std::vector<Gui::SelectionObject> sel = Gui::Selection().getSelectionEx();
|
||||
for (std::vector<Gui::SelectionObject>::iterator it = sel.begin(); it != sel.end(); ++it) {
|
||||
if (it->getObject() == d->thickness->Faces.getValue()) {
|
||||
d->thickness->Faces.setValue(it->getObject(), it->getSubNames());
|
||||
d->selection = it->getAsPropertyLinkSubString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
Gui::Application::Instance->showViewProvider(d->thickness);
|
||||
Gui::Application::Instance->hideViewProvider(d->thickness->Faces.getValue());
|
||||
if (d->ui.updateView->isChecked())
|
||||
d->thickness->getDocument()->recomputeFeature(d->thickness);
|
||||
}
|
||||
}
|
||||
|
||||
void ThicknessWidget::on_updateView_toggled(bool on)
|
||||
{
|
||||
if (on) {
|
||||
d->thickness->getDocument()->recomputeFeature(d->thickness);
|
||||
}
|
||||
}
|
||||
|
||||
bool ThicknessWidget::accept()
|
||||
{
|
||||
if (d->loop.isRunning())
|
||||
return false;
|
||||
|
||||
std::string name = d->thickness->getNameInDocument();
|
||||
try {
|
||||
if (!d->selection.empty()) {
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Faces = %s",
|
||||
name.c_str(),d->selection.c_str());
|
||||
}
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Value = %f",
|
||||
name.c_str(),d->ui.spinOffset->value());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Mode = %i",
|
||||
name.c_str(),d->ui.modeType->currentIndex());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Join = %i",
|
||||
name.c_str(),d->ui.joinType->currentIndex());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Intersection = %s",
|
||||
name.c_str(),d->ui.intersection->isChecked() ? "True" : "False");
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.SelfIntersection = %s",
|
||||
name.c_str(),d->ui.selfIntersection->isChecked() ? "True" : "False");
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
|
||||
if (!d->thickness->isValid())
|
||||
throw Base::Exception(d->thickness->getStatusString());
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
QMessageBox::warning(this, tr("Input error"), QString::fromAscii(e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThicknessWidget::reject()
|
||||
{
|
||||
if (d->loop.isRunning())
|
||||
return false;
|
||||
|
||||
// save this and check if the object is still there after the
|
||||
// transaction is aborted
|
||||
std::string objname = d->thickness->getNameInDocument();
|
||||
App::DocumentObject* source = d->thickness->Faces.getValue();
|
||||
|
||||
// roll back the done things
|
||||
Gui::Command::abortCommand();
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
|
||||
Gui::Command::updateActive();
|
||||
|
||||
// Thickness object was deleted
|
||||
if (source && !source->getDocument()->getObject(objname.c_str())) {
|
||||
Gui::Application::Instance->getViewProvider(source)->show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ThicknessWidget::changeEvent(QEvent *e)
|
||||
{
|
||||
QWidget::changeEvent(e);
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
d->ui.retranslateUi(this);
|
||||
d->ui.labelOffset->setText(tr("Thickness"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* TRANSLATOR PartGui::TaskThickness */
|
||||
|
||||
TaskThickness::TaskThickness(Part::Thickness* offset)
|
||||
{
|
||||
widget = new ThicknessWidget(offset);
|
||||
widget->setWindowTitle(ThicknessWidget::tr("Thickness"));
|
||||
taskbox = new Gui::TaskView::TaskBox(
|
||||
Gui::BitmapFactory().pixmap("Part_Thickness"),
|
||||
widget->windowTitle(), true, 0);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
TaskThickness::~TaskThickness()
|
||||
{
|
||||
}
|
||||
|
||||
Part::Thickness* TaskThickness::getObject() const
|
||||
{
|
||||
return widget->getObject();
|
||||
}
|
||||
|
||||
void TaskThickness::open()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskThickness::clicked(int)
|
||||
{
|
||||
}
|
||||
|
||||
bool TaskThickness::accept()
|
||||
{
|
||||
return widget->accept();
|
||||
}
|
||||
|
||||
bool TaskThickness::reject()
|
||||
{
|
||||
return widget->reject();
|
||||
}
|
||||
|
||||
#include "moc_TaskThickness.cpp"
|
87
src/Mod/Part/Gui/TaskThickness.h
Normal file
87
src/Mod/Part/Gui/TaskThickness.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2012 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef PARTGUI_TASKTHICKNESS_H
|
||||
#define PARTGUI_TASKTHICKNESS_H
|
||||
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
|
||||
namespace Part { class Thickness; }
|
||||
namespace PartGui {
|
||||
|
||||
class ThicknessWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ThicknessWidget(Part::Thickness*, QWidget* parent = 0);
|
||||
~ThicknessWidget();
|
||||
|
||||
bool accept();
|
||||
bool reject();
|
||||
Part::Thickness* getObject() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_spinOffset_valueChanged(double);
|
||||
void on_modeType_activated(int);
|
||||
void on_joinType_activated(int);
|
||||
void on_intersection_toggled(bool);
|
||||
void on_selfIntersection_toggled(bool);
|
||||
void on_facesButton_clicked();
|
||||
void on_updateView_toggled(bool);
|
||||
|
||||
private:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private* d;
|
||||
};
|
||||
|
||||
class TaskThickness : public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskThickness(Part::Thickness*);
|
||||
~TaskThickness();
|
||||
|
||||
public:
|
||||
void open();
|
||||
bool accept();
|
||||
bool reject();
|
||||
void clicked(int);
|
||||
Part::Thickness* getObject() const;
|
||||
|
||||
QDialogButtonBox::StandardButtons getStandardButtons() const
|
||||
{ return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; }
|
||||
|
||||
private:
|
||||
ThicknessWidget* widget;
|
||||
Gui::TaskView::TaskBox* taskbox;
|
||||
};
|
||||
|
||||
} //namespace PartGui
|
||||
|
||||
#endif // PARTGUI_TASKTHICKNESS_H
|
|
@ -81,6 +81,7 @@
|
|||
#include <Base/Exception.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/SoFCSelection.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
|
@ -107,6 +108,17 @@ ViewProviderPart::ViewProviderPart()
|
|||
ViewProviderPart::~ViewProviderPart()
|
||||
{
|
||||
}
|
||||
|
||||
bool ViewProviderPart::doubleClicked(void)
|
||||
{
|
||||
std::string Msg("Edit ");
|
||||
Msg += this->pcObject->Label.getValue();
|
||||
Gui::Command::openCommand(Msg.c_str());
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.setEdit('%s',0)",
|
||||
this->pcObject->getNameInDocument());
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
PROPERTY_SOURCE(PartGui::ViewProviderPart, PartGui::ViewProviderPartBase)
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ public:
|
|||
ViewProviderPart();
|
||||
/// destructor
|
||||
virtual ~ViewProviderPart();
|
||||
virtual bool doubleClicked(void);
|
||||
};
|
||||
#else
|
||||
class PartGuiExport ViewProviderPart : public ViewProviderPartBase
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#ifndef _PreComp_
|
||||
# include <QAction>
|
||||
# include <QMenu>
|
||||
# include <QTimer>
|
||||
# include <Standard_math.hxx>
|
||||
# include <Inventor/actions/SoSearchAction.h>
|
||||
# include <Inventor/draggers/SoDragger.h>
|
||||
|
@ -47,6 +48,7 @@
|
|||
#include "ViewProviderMirror.h"
|
||||
#include "DlgFilletEdges.h"
|
||||
#include "TaskOffset.h"
|
||||
#include "TaskThickness.h"
|
||||
|
||||
using namespace PartGui;
|
||||
|
||||
|
@ -477,3 +479,84 @@ bool ViewProviderOffset::onDelete(const std::vector<std::string> &)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
|
||||
PROPERTY_SOURCE(PartGui::ViewProviderThickness, PartGui::ViewProviderPart)
|
||||
|
||||
ViewProviderThickness::ViewProviderThickness()
|
||||
{
|
||||
sPixmap = "Part_Thickness";
|
||||
}
|
||||
|
||||
ViewProviderThickness::~ViewProviderThickness()
|
||||
{
|
||||
}
|
||||
|
||||
void ViewProviderThickness::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
|
||||
{
|
||||
QAction* act;
|
||||
act = menu->addAction(QObject::tr("Edit thickness"), receiver, member);
|
||||
act->setData(QVariant((int)ViewProvider::Default));
|
||||
PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member);
|
||||
}
|
||||
|
||||
bool ViewProviderThickness::setEdit(int ModNum)
|
||||
{
|
||||
if (ModNum == ViewProvider::Default ) {
|
||||
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
|
||||
TaskThickness* thicknessDlg = qobject_cast<TaskThickness*>(dlg);
|
||||
if (thicknessDlg && thicknessDlg->getObject() != this->getObject())
|
||||
thicknessDlg = 0; // another pad left open its task panel
|
||||
if (dlg && !thicknessDlg) {
|
||||
if (dlg->canClose())
|
||||
Gui::Control().closeDialog();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// clear the selection (convenience)
|
||||
Gui::Selection().clearSelection();
|
||||
|
||||
// start the edit dialog
|
||||
if (thicknessDlg)
|
||||
Gui::Control().showDialog(thicknessDlg);
|
||||
else
|
||||
Gui::Control().showDialog(new TaskThickness(static_cast<Part::Thickness*>(getObject())));
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return ViewProviderPart::setEdit(ModNum);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderThickness::unsetEdit(int ModNum)
|
||||
{
|
||||
if (ModNum == ViewProvider::Default) {
|
||||
// when pressing ESC make sure to close the dialog
|
||||
QTimer::singleShot(0, &Gui::Control(), SLOT(closeDialog()));
|
||||
}
|
||||
else {
|
||||
PartGui::ViewProviderPart::unsetEdit(ModNum);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> ViewProviderThickness::claimChildren() const
|
||||
{
|
||||
std::vector<App::DocumentObject*> child;
|
||||
child.push_back(static_cast<Part::Thickness*>(getObject())->Faces.getValue());
|
||||
return child;
|
||||
}
|
||||
|
||||
bool ViewProviderThickness::onDelete(const std::vector<std::string> &)
|
||||
{
|
||||
// get the support and Sketch
|
||||
Part::Thickness* thickness = static_cast<Part::Thickness*>(getObject());
|
||||
App::DocumentObject* source = thickness->Faces.getValue();
|
||||
if (source){
|
||||
Gui::Application::Instance->getViewProvider(source)->show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -158,6 +158,26 @@ protected:
|
|||
virtual void unsetEdit(int ModNum);
|
||||
};
|
||||
|
||||
class ViewProviderThickness : public ViewProviderPart
|
||||
{
|
||||
PROPERTY_HEADER(PartGui::ViewProviderThickness);
|
||||
|
||||
public:
|
||||
/// constructor
|
||||
ViewProviderThickness();
|
||||
/// destructor
|
||||
virtual ~ViewProviderThickness();
|
||||
|
||||
/// grouping handling
|
||||
std::vector<App::DocumentObject*> claimChildren(void)const;
|
||||
void setupContextMenu(QMenu*, QObject*, const char*);
|
||||
bool onDelete(const std::vector<std::string> &);
|
||||
|
||||
protected:
|
||||
virtual bool setEdit(int ModNum);
|
||||
virtual void unsetEdit(int ModNum);
|
||||
};
|
||||
|
||||
} // namespace PartGui
|
||||
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
<< "Part_SimpleCopy" << "Part_RefineShape" << "Part_CheckGeometry" << "Separator"
|
||||
<< "Part_Boolean" << "Part_CrossSections" << "Part_Extrude"
|
||||
<< "Part_Revolve" << "Part_Mirror" << "Part_Fillet" << "Part_Chamfer"
|
||||
<< "Part_RuledSurface" << "Part_Loft" << "Part_Sweep" << "Part_Offset";
|
||||
<< "Part_RuledSurface" << "Part_Loft" << "Part_Sweep"
|
||||
<< "Part_Offset" << "Part_Thickness";
|
||||
|
||||
return root;
|
||||
}
|
||||
|
@ -90,7 +91,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
tool->setCommand("Part tools");
|
||||
*tool << "Part_Extrude" << "Part_Revolve" << "Part_Mirror" << "Part_Fillet"
|
||||
<< "Part_Chamfer" << "Part_RuledSurface" << "Part_Loft" << "Part_Sweep"
|
||||
<< "Part_Offset";
|
||||
<< "Part_Offset" << "Part_Thickness";
|
||||
|
||||
Gui::ToolBarItem* boolop = new Gui::ToolBarItem(root);
|
||||
boolop->setCommand("Boolean");
|
||||
|
|
|
@ -231,6 +231,8 @@ bool SketchBased::isInside(const TopoDS_Wire& wire1, const TopoDS_Wire& wire2) c
|
|||
double prec = Precision::Confusion();
|
||||
|
||||
BRepBuilderAPI_MakeFace mkFace(wire1);
|
||||
if (!mkFace.IsDone())
|
||||
Standard_Failure::Raise("Failed to create a face from wire in sketch");
|
||||
TopoDS_Face face = validateFace(mkFace.Face());
|
||||
BRepAdaptor_Surface adapt(face);
|
||||
IntTools_FClass2d class2d(face, prec);
|
||||
|
|
|
@ -29,3 +29,29 @@ INSTALL(
|
|||
Mod/PartDesign/Scripts
|
||||
)
|
||||
|
||||
SET(WizardShaft_SRCS
|
||||
WizardShaft/__init__.py
|
||||
WizardShaft/WizardShaft.svg
|
||||
WizardShaft/WizardShaft.py
|
||||
WizardShaft/WizardShaftTable.py
|
||||
WizardShaft/Shaft.py
|
||||
WizardShaft/ShaftFeature.py
|
||||
WizardShaft/ShaftDiagram.py
|
||||
WizardShaft/SegmentFunction.py
|
||||
)
|
||||
SOURCE_GROUP("wizardshaft" FILES ${WizardShaft_SRCS})
|
||||
|
||||
SET(all_files ${WizardShaft_SRCS})
|
||||
|
||||
ADD_CUSTOM_TARGET(WizardShaft ALL
|
||||
SOURCES ${all_files}
|
||||
)
|
||||
|
||||
fc_copy_sources(Mod/PartDesign "${CMAKE_BINARY_DIR}/Mod/PartDesign" ${all_files})
|
||||
|
||||
INSTALL(
|
||||
FILES
|
||||
${WizardShaft_SRCS}
|
||||
DESTINATION
|
||||
Mod/PartDesign/WizardShaft
|
||||
)
|
||||
|
|
|
@ -45,8 +45,8 @@ ViewProvider::~ViewProvider()
|
|||
|
||||
bool ViewProvider::doubleClicked(void)
|
||||
{
|
||||
std::string Msg("Change ");
|
||||
Msg += this->pcObject->getNameInDocument();
|
||||
std::string Msg("Edit ");
|
||||
Msg += this->pcObject->Label.getValue();
|
||||
Gui::Command::openCommand(Msg.c_str());
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().setEdit('%s',0)",this->pcObject->getNameInDocument());
|
||||
return true;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#endif
|
||||
|
||||
#include "Workbench.h"
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/MenuManager.h>
|
||||
#include <Gui/ToolBarManager.h>
|
||||
#include <Gui/Control.h>
|
||||
|
@ -167,6 +169,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
|
@ -176,22 +179,22 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
|
||||
Gui::MenuItem* cons = new Gui::MenuItem();
|
||||
cons->setCommand("Sketcher constraints");
|
||||
*cons << "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainCoincident"
|
||||
*cons << "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainAngle"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
;
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainAngle";
|
||||
|
||||
Gui::MenuItem* part = new Gui::MenuItem;
|
||||
root->insertItem(item, part);
|
||||
|
@ -214,6 +217,12 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
<< "PartDesign_PolarPattern"
|
||||
// << "PartDesign_Scaled"
|
||||
<< "PartDesign_MultiTransform";
|
||||
// For 0.13 a couple of python packages like numpy, matplotlib and others
|
||||
// are not deployed with the installer on Windows. Thus, the WizardShaft is
|
||||
// not deployed either hence the check for the existence of the command.
|
||||
if (Gui::Application::Instance->commandManager().getCommandByName("PartDesign_WizardShaft")) {
|
||||
*part << "Separator" << "PartDesign_WizardShaft";
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
@ -238,14 +247,15 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
// << "PartDesign_Scaled"
|
||||
<< "PartDesign_MultiTransform";
|
||||
|
||||
part = new Gui::ToolBarItem(root);
|
||||
part->setCommand("Sketcher geometries");
|
||||
*part << "Sketcher_CreatePoint"
|
||||
Gui::ToolBarItem* geom = new Gui::ToolBarItem(root);
|
||||
geom->setCommand("Sketcher geometries");
|
||||
*geom << "Sketcher_CreatePoint"
|
||||
<< "Sketcher_CreateArc"
|
||||
<< "Sketcher_CreateCircle"
|
||||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
|
@ -253,24 +263,24 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
/*<< "Sketcher_CreateText"*/
|
||||
/*<< "Sketcher_CreateDraftLine"*/;
|
||||
|
||||
part = new Gui::ToolBarItem(root);
|
||||
part->setCommand("Sketcher constraints");
|
||||
*part << "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainCoincident"
|
||||
Gui::ToolBarItem* cons = new Gui::ToolBarItem(root);
|
||||
cons->setCommand("Sketcher constraints");
|
||||
*cons << "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainAngle"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
;
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainAngle";
|
||||
|
||||
return root;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# PartDesign gui init module
|
||||
# PartDesign gui init module
|
||||
# (c) 2003 Juergen Riegel
|
||||
#
|
||||
# Gathering all the information to start FreeCAD
|
||||
|
@ -29,11 +29,9 @@
|
|||
#* Juergen Riegel 2002 *
|
||||
#***************************************************************************/
|
||||
|
||||
|
||||
|
||||
class PartDesignWorkbench ( Workbench ):
|
||||
"PartDesign workbench object"
|
||||
Icon = """
|
||||
"PartDesign workbench object"
|
||||
Icon = """
|
||||
/* XPM */
|
||||
static char * partdesign_xpm[] = {
|
||||
"16 16 9 1",
|
||||
|
@ -62,15 +60,19 @@ class PartDesignWorkbench ( Workbench ):
|
|||
".+@@@####@.@.. ",
|
||||
" ......+++.. ",
|
||||
" ... "};
|
||||
"""
|
||||
"""
|
||||
MenuText = "Part Design"
|
||||
ToolTip = "Part Design workbench"
|
||||
|
||||
def Initialize(self):
|
||||
# load the module
|
||||
import PartDesignGui
|
||||
import PartDesign
|
||||
def GetClassName(self):
|
||||
return "PartDesignGui::Workbench"
|
||||
def Initialize(self):
|
||||
# load the module
|
||||
try:
|
||||
from WizardShaft import WizardShaft
|
||||
except:
|
||||
print "Wizard shaft not installed"
|
||||
import PartDesignGui
|
||||
import PartDesign
|
||||
def GetClassName(self):
|
||||
return "PartDesignGui::Workbench"
|
||||
|
||||
Gui.addWorkbench(PartDesignWorkbench())
|
||||
|
|
76
src/Mod/PartDesign/WizardShaft/InitGui.py
Normal file
76
src/Mod/PartDesign/WizardShaft/InitGui.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
# PartDesign gui init module
|
||||
# (c) 2003 Juergen Riegel
|
||||
#
|
||||
# Gathering all the information to start FreeCAD
|
||||
# This is the second one of three init scripts, the third one
|
||||
# runs when the gui is up
|
||||
|
||||
#***************************************************************************
|
||||
#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 *
|
||||
#* *
|
||||
#* This file is part of the FreeCAD CAx development system. *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU General Public License (GPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* FreeCAD is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with FreeCAD; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#* Juergen Riegel 2002 *
|
||||
#***************************************************************************/
|
||||
|
||||
class PartDesignWorkbench ( Workbench ):
|
||||
"PartDesign workbench object"
|
||||
from WizardShaft import WizardShaft
|
||||
Icon = """
|
||||
/* XPM */
|
||||
static char * partdesign_xpm[] = {
|
||||
"16 16 9 1",
|
||||
" c None",
|
||||
". c #040006",
|
||||
"+ c #070F38",
|
||||
"@ c #002196",
|
||||
"# c #0030F3",
|
||||
"$ c #5A4D20",
|
||||
"% c #858EB2",
|
||||
"& c #DEB715",
|
||||
"* c #BFB99D",
|
||||
" & ........ ",
|
||||
"&&&$..@@@@@@+...",
|
||||
"&&&&$@#####@..@.",
|
||||
"&&&&&$......@#@.",
|
||||
"&&&&&&@@@+.###@.",
|
||||
"$&&&&&&@#@.###@.",
|
||||
".$&&&&&%#@.###@.",
|
||||
".@*&&&*%#@.###@.",
|
||||
".@#*&**%#@.###@.",
|
||||
".@#@%%%.@@.###@.",
|
||||
".@@@@@@@#@.###@.",
|
||||
".@#######@.###@.",
|
||||
".@#######@.##+. ",
|
||||
".+@@@####@.@.. ",
|
||||
" ......+++.. ",
|
||||
" ... "};
|
||||
"""
|
||||
MenuText = "Part Design"
|
||||
ToolTip = "Part Design workbench"
|
||||
|
||||
def Initialize(self):
|
||||
# load the module
|
||||
import PartDesignGui
|
||||
import PartDesign
|
||||
def GetClassName(self):
|
||||
return "PartDesignGui::Workbench"
|
||||
|
||||
Gui.addWorkbench(PartDesignWorkbench())
|
||||
|
158
src/Mod/PartDesign/WizardShaft/SegmentFunction.py
Normal file
158
src/Mod/PartDesign/WizardShaft/SegmentFunction.py
Normal file
|
@ -0,0 +1,158 @@
|
|||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library 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 library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
import FreeCAD # just for debug printing to console...
|
||||
|
||||
class SegmentFunctionSegment:
|
||||
"One segment of a segment function"
|
||||
start = 0
|
||||
variable = "x"
|
||||
coefficient = 0
|
||||
exponent = 0
|
||||
|
||||
def __init__(self, st, var, coeff, exp):
|
||||
self.start = st
|
||||
self.variable = var
|
||||
self.coefficient = coeff
|
||||
self.exponent = exp
|
||||
|
||||
def hasStart(self, xval):
|
||||
"Return true if the start of this segment is xval"
|
||||
#FIXME: 1E-9 is arbitrary here. But since units are in meters, 1E-9 is a nanometer...
|
||||
return abs(self.start - xval) < 1E-9
|
||||
|
||||
def value(self, xval):
|
||||
if xval < self.start:
|
||||
return 0
|
||||
else:
|
||||
return self.coefficient * pow(xval - self.start, self.exponent)
|
||||
|
||||
def clone(self):
|
||||
return SegmentFunctionSegment(self.start, self.variable, self.coefficient, self.exponent)
|
||||
|
||||
def negate(self):
|
||||
self.coefficient *= -1
|
||||
|
||||
def integrate(self):
|
||||
self.exponent = self.exponent + 1
|
||||
self.coefficient = self.coefficient * 1 / self.exponent
|
||||
|
||||
def asString(self):
|
||||
return "%f * {%s - %f}^%i" % (self.coefficient, self.variable, self.start, self.exponent)
|
||||
|
||||
class SegmentFunction:
|
||||
"Function that is defined segment-wise"
|
||||
variable = "x"
|
||||
segments = []
|
||||
name = "f(x)"
|
||||
|
||||
def __init__(self, name = "f(x)"):
|
||||
self.variable = "x"
|
||||
self.segments = []
|
||||
self.name = name
|
||||
|
||||
def negate(self):
|
||||
for s in self.segments:
|
||||
s.negate()
|
||||
return self
|
||||
|
||||
def index(self, xval):
|
||||
"Find insert position for start value xval"
|
||||
lastStart = 0.0
|
||||
for i in range(len(self.segments)):
|
||||
newStart = self.segments[i].start
|
||||
if (xval >= lastStart) and (xval < newStart):
|
||||
return i
|
||||
lastStart = newStart
|
||||
return len(self.segments)
|
||||
|
||||
def buildFromDict(self, var, dict):
|
||||
self.variable = var
|
||||
for key in sorted(dict.iterkeys()):
|
||||
#if abs(dict[key]) > 1E-9:
|
||||
self.segments.append(SegmentFunctionSegment(key, var, dict[key], 0))
|
||||
|
||||
def addSegments(self, dict):
|
||||
for key in sorted(dict.iterkeys()):
|
||||
if abs(dict[key]) > 1E-9:
|
||||
self.segments.insert(self.index(key), SegmentFunctionSegment(key, self.variable, dict[key], 0))
|
||||
|
||||
def setMaxX(self, mx):
|
||||
self.maxX = mx
|
||||
|
||||
def value(self, xval):
|
||||
"Return the value of the function at the specified x value"
|
||||
result = 0
|
||||
for s in self.segments:
|
||||
result = result + s.value(xval)
|
||||
return result
|
||||
|
||||
def lowervalue(self, xval):
|
||||
"Return the value of the previous segment at the specified x value"
|
||||
result = 0
|
||||
for s in self.segments:
|
||||
result = result + s.value(xval - 1E-8)
|
||||
return result
|
||||
|
||||
def clone(self):
|
||||
result = SegmentFunction()
|
||||
result.variable = self.variable
|
||||
for s in self.segments:
|
||||
result.segments.append(s.clone())
|
||||
return result
|
||||
|
||||
def integrate(self):
|
||||
"Integrate all segments with respect to the variable"
|
||||
for s in self.segments:
|
||||
s.integrate()
|
||||
|
||||
def integrated(self):
|
||||
"Return a copy of self integrated with respect to the variable"
|
||||
result = self.clone()
|
||||
result.integrate()
|
||||
return result
|
||||
|
||||
def evaluate(self, maxX, pointsX):
|
||||
# Note: This usually creates a few more points than specified in pointsX
|
||||
offset = (maxX - self.segments[0].start) / (pointsX - 1)
|
||||
xvals = set([self.segments[0].start + s * offset for s in range(pointsX)])
|
||||
starts = set([self.segments[i].start for i in range(len(self.segments))])
|
||||
xvals = xvals.union(starts) # Make sure we have a point on each segment start
|
||||
xresult = []
|
||||
yresult = []
|
||||
for xval in sorted(xvals):
|
||||
if xval in starts:
|
||||
# create double point at segment border
|
||||
xresult.append(xval)
|
||||
yresult.append(self.lowervalue(xval))
|
||||
xresult.append(xval)
|
||||
yresult.append(self.value(xval))
|
||||
return (xresult, yresult)
|
||||
|
||||
def output(self):
|
||||
FreeCAD.Console.PrintMessage(self.name + " = ")
|
||||
for i in range(len(self.segments)):
|
||||
FreeCAD.Console.PrintMessage(self.segments[i].asString())
|
||||
if i < len(self.segments) - 1:
|
||||
FreeCAD.Console.PrintMessage(" + ")
|
||||
FreeCAD.Console.PrintMessage("\n")
|
||||
|
245
src/Mod/PartDesign/WizardShaft/Shaft.py
Normal file
245
src/Mod/PartDesign/WizardShaft/Shaft.py
Normal file
|
@ -0,0 +1,245 @@
|
|||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library 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 library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
import FreeCAD, FreeCADGui # FreeCAD just required for debug printing to the console...
|
||||
from SegmentFunction import SegmentFunction
|
||||
from ShaftFeature import ShaftFeature
|
||||
from ShaftDiagram import Diagram
|
||||
|
||||
class ShaftSegment:
|
||||
length = 0.0
|
||||
diameter = 0.0
|
||||
loadType = "None"
|
||||
loadSize = 0.0
|
||||
loadLocation = 0.0
|
||||
|
||||
def __init__(self, l, d):
|
||||
self.length = l
|
||||
self.diameter = d
|
||||
|
||||
class Shaft:
|
||||
"The axis of the shaft is always assumed to correspond to the X-axis"
|
||||
# List of shaft segments (each segment has a different diameter)
|
||||
segments = []
|
||||
# The sketch
|
||||
sketch = 0
|
||||
#featureWindow = None
|
||||
# The diagrams
|
||||
diagrams = {} # map of function name against Diagram object
|
||||
# Calculation of shaft
|
||||
Qy = 0 # force in direction of y axis
|
||||
Qz = 0 # force in direction of z axis
|
||||
Mbz = 0 # bending moment around z axis
|
||||
Mby = 0 # bending moment around y axis
|
||||
Mtz = 0 # torsion moment around z axis
|
||||
|
||||
def __init__(self, doc):
|
||||
self.sketch = ShaftFeature(doc)
|
||||
|
||||
def getLengthTo(self, index):
|
||||
"Get the total length of all segments up to the given one"
|
||||
result = 0.0
|
||||
for i in range(index):
|
||||
result += self.segments[i].length
|
||||
return result
|
||||
|
||||
def addSegment(self, l, d):
|
||||
#print "Adding segment: ", l, " : ", d
|
||||
self.segments.append(ShaftSegment(l,d))
|
||||
self.sketch.addSegment(l, d)
|
||||
# We don't call equilibrium() here because the new segment has no loads defined yet
|
||||
|
||||
def updateSegment(self, index, length = None, diameter = None):
|
||||
oldLength = self.segments[index].length
|
||||
#print "Old length of ", index, ": ", oldLength, ", new Length: ", length, " diameter: ", diameter
|
||||
if length is not None:
|
||||
self.segments[index].length = length
|
||||
if diameter is not None:
|
||||
self.segments[index].diameter = diameter
|
||||
self.sketch.updateSegment(index, oldLength, self.segments[index].length, self.segments[index].diameter)
|
||||
self.equilibrium()
|
||||
self.updateDiagrams()
|
||||
|
||||
def updateLoad(self, index, loadType = None, loadSize = None, loadLocation = None):
|
||||
if (loadType is not None):
|
||||
self.segments[index].loadType = loadType
|
||||
if (loadSize is not None):
|
||||
self.segments[index].loadSize = loadSize
|
||||
if (loadLocation is not None):
|
||||
if (loadLocation >= 0) and (loadLocation <= self.segments[index].length):
|
||||
self.segments[index].loadLocation = loadLocation
|
||||
else:
|
||||
# TODO: Show warning
|
||||
FreeCAD.Console.PrintMessage("Load location must be inside segment\n")
|
||||
|
||||
#self.feature.updateForces() graphical representation of the forces
|
||||
self.equilibrium()
|
||||
self.updateDiagrams()
|
||||
|
||||
def updateEdge(self, column, start):
|
||||
App.Console.PrintMessage("Not implemented yet - waiting for robust references...")
|
||||
return
|
||||
if self.sketchClosed is not True:
|
||||
return
|
||||
# Create a chamfer or fillet at the start or end edge of the segment
|
||||
if start is True:
|
||||
row = rowStartEdgeType
|
||||
idx = 0
|
||||
else:
|
||||
row = rowEndEdgeType
|
||||
idx = 1
|
||||
|
||||
edgeType = self.tableWidget.item(row, column).text().toAscii()[0].upper()
|
||||
if not ((edgeType == "C") or (edgeType == "F")):
|
||||
return # neither chamfer nor fillet defined
|
||||
|
||||
if edgeType == "C":
|
||||
objName = self.doc.addObject("PartDesign::Chamfer","ChamferShaft%u" % (column * 2 + idx))
|
||||
else:
|
||||
objName = self.doc.addObject("PartDesign::Fillet","FilletShaft%u" % (column * 2 + idx))
|
||||
if objName == "":
|
||||
return
|
||||
|
||||
edgeName = "Edge%u" % self.getEdgeIndex(column, idx, edgeType)
|
||||
self.doc.getObject(objName).Base = (self.doc.getObject("RevolutionShaft"),"[%s]" % edgeName)
|
||||
# etc. etc.
|
||||
|
||||
def getEdgeIndex(self, column, startIdx):
|
||||
# FIXME: This is impossible without robust references anchored in the sketch!!!
|
||||
return
|
||||
|
||||
def updateDiagrams(self):
|
||||
if (self.Qy == 0) or (self.Mbz == 0):
|
||||
return
|
||||
if self.Qy.name in self.diagrams:
|
||||
# Update diagram
|
||||
self.diagrams[self.Qy.name].update(self.Qy, self.getLengthTo(len(self.segments)) / 1000.0)
|
||||
else:
|
||||
# Create diagram
|
||||
self.diagrams[self.Qy.name] = Diagram()
|
||||
self.diagrams[self.Qy.name].create("Shear force", self.Qy, self.getLengthTo(len(self.segments)) / 1000.0, "x", "mm", 1000.0, "Q_y", "N", 1.0, 10)
|
||||
if self.Mbz.name in self.diagrams:
|
||||
# Update diagram
|
||||
self.diagrams[self.Mbz.name].update(self.Mbz, self.getLengthTo(len(self.segments)) / 1000.0)
|
||||
else:
|
||||
# Create diagram
|
||||
self.diagrams[self.Mbz.name] = Diagram()
|
||||
self.diagrams[self.Mbz.name].create("Bending moment", self.Mbz, self.getLengthTo(len(self.segments)) / 1000.0, "x", "mm", 1000.0, "M_{b,z}", "Nm", 1.0, 10)
|
||||
|
||||
def equilibrium(self):
|
||||
# Build equilibrium equations
|
||||
forces = {0.0:0.0} # dictionary of (location : outer force)
|
||||
moments = {0.0:0.0} # dictionary of (location : outer moment)
|
||||
variableNames = [""] # names of all variables
|
||||
locations = {} # dictionary of (variableName : location)
|
||||
coefficientsFy = [0] # force equilibrium equation
|
||||
coefficientsMbz = [0] # moment equilibrium equation
|
||||
|
||||
for i in range(len(self.segments)):
|
||||
lType = self.segments[i].loadType
|
||||
load = -1 # -1 means unknown (just for debug printing)
|
||||
location = -1
|
||||
|
||||
if lType == "Fixed":
|
||||
# Fixed segment
|
||||
if i == 0:
|
||||
location = 0
|
||||
variableNames.append("Fy%u" % i)
|
||||
coefficientsFy.append(1)
|
||||
coefficientsMbz.append(0)
|
||||
variableNames.append("Mz%u" % i)
|
||||
coefficientsFy.append(0)
|
||||
coefficientsMbz.append(1) # Force does not contribute because location is zero
|
||||
elif i == len(self.segments) - 1:
|
||||
location = self.getLengthTo(len(self.segments)) / 1000
|
||||
variableNames.append("Fy%u" % i)
|
||||
coefficientsFy.append(1)
|
||||
coefficientsMbz.append(location)
|
||||
variableNames.append("Mz%u" % i)
|
||||
coefficientsFy.append(0)
|
||||
coefficientsMbz.append(1)
|
||||
else:
|
||||
# TODO: Better error message
|
||||
FreeCAD.Console.PrintMessage("Fixed constraint must be at beginning or end of shaft\n")
|
||||
return
|
||||
|
||||
locations["Fy%u" % i] = location
|
||||
locations["Mz%u" % i] = location
|
||||
elif lType == "Static":
|
||||
# Static load (currently force only)
|
||||
load = self.segments[i].loadSize
|
||||
location = (self.getLengthTo(i) + self.segments[i].loadLocation) / 1000 # convert to meters
|
||||
coefficientsFy[0] = coefficientsFy[0] - load
|
||||
forces[location] = load
|
||||
coefficientsMbz[0] = coefficientsMbz[0] - load * location
|
||||
moments[location] = 0
|
||||
#elif lType == "None":
|
||||
# # No loads on segment
|
||||
|
||||
FreeCAD.Console.PrintMessage("Segment: %u, type: %s, load: %f, location: %f\n" % (i, lType, load, location))
|
||||
|
||||
self.printEquilibrium(variableNames, coefficientsFy)
|
||||
self.printEquilibrium(variableNames, coefficientsMbz)
|
||||
|
||||
# Build matrix and vector for linear algebra solving algorithm
|
||||
try:
|
||||
import numpy as np
|
||||
except ImportError:
|
||||
FreeCAD.Console.PrintMessage("numpy is not installed on your system\n")
|
||||
raise ImportError("numpy not installed")
|
||||
if (len(coefficientsFy) < 3) or (len(coefficientsMbz) < 3):
|
||||
return
|
||||
A = np.array([coefficientsFy[1:], coefficientsMbz[1:]])
|
||||
b = np.array([coefficientsFy[0], coefficientsMbz[0]])
|
||||
solution = np.linalg.solve(A, b)
|
||||
|
||||
# Complete dictionary of forces and moments
|
||||
if variableNames[1][0] == "F":
|
||||
forces[locations[variableNames[1]]] = solution[0]
|
||||
else:
|
||||
moments[locations[variableNames[1]]] = solution[0]
|
||||
|
||||
if variableNames[2][0] == "F":
|
||||
forces[locations[variableNames[2]]] = solution[1]
|
||||
else:
|
||||
moments[locations[variableNames[2]]] = solution[1]
|
||||
|
||||
FreeCAD.Console.PrintMessage(forces)
|
||||
FreeCAD.Console.PrintMessage(moments)
|
||||
self.Qy = SegmentFunction("Qy")
|
||||
self.Qy.buildFromDict("x", forces)
|
||||
self.Qy.output()
|
||||
self.Mbz = self.Qy.integrated().negate()
|
||||
self.Mbz.addSegments(moments) # takes care of boundary conditions
|
||||
self.Mbz.name = "Mbz"
|
||||
self.Mbz.output()
|
||||
|
||||
def printEquilibrium(self, var, coeff):
|
||||
# Auxiliary method for debugging purposes
|
||||
for i in range(len(var)):
|
||||
if i == 0:
|
||||
FreeCAD.Console.PrintMessage("%f = " % coeff[i])
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage("%f * %s" % (coeff[i], var[i]))
|
||||
if (i < len(var) - 1) and (i != 0):
|
||||
FreeCAD.Console.PrintMessage(" + ")
|
||||
FreeCAD.Console.PrintMessage("\n")
|
91
src/Mod/PartDesign/WizardShaft/ShaftDiagram.py
Normal file
91
src/Mod/PartDesign/WizardShaft/ShaftDiagram.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library 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 library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
import FreeCAD, FreeCADGui
|
||||
|
||||
class Diagram:
|
||||
function = 0 # This is assumed to be always a SegmentFunction
|
||||
fname = "y(x)"
|
||||
xlength = 0.0
|
||||
xname = "x"
|
||||
xunit = ""
|
||||
xscale = 1.0
|
||||
yname = "y"
|
||||
yunit = ""
|
||||
yscale = 1.0
|
||||
numxpoints = 10
|
||||
xpoints = []
|
||||
ypoints = []
|
||||
# Plot object
|
||||
thePlot = None
|
||||
|
||||
def create(self, title, function, xlength, xname, xunit, xscale, yname, yunit, yscale, numxpoints):
|
||||
# Initialize
|
||||
import Plot
|
||||
self.title = title
|
||||
self.function = function
|
||||
self.xlength = xlength
|
||||
self.xname = xname
|
||||
self.xunit = xunit
|
||||
self.xscale = xscale
|
||||
self.yname = yname
|
||||
self.yunit = yunit
|
||||
self.yscale = yscale
|
||||
self.numxpoints = numxpoints
|
||||
|
||||
# Create a plot window
|
||||
win = Plot.figure(title)
|
||||
# Get the plot object from the window
|
||||
self.thePlot = Plot.getPlot()
|
||||
# Format the plot object
|
||||
Plot.xlabel("$%s$ [%s]" % (xname, xunit))
|
||||
Plot.ylabel("$%s$ [%s]" % (yname, yunit))
|
||||
Plot.grid(True)
|
||||
|
||||
# Calculate points
|
||||
(self.xpoints, self.ypoints) = self.function.evaluate(self.xlength, self.numxpoints)
|
||||
# Create plot
|
||||
self.plot()
|
||||
|
||||
def update(self, function = None, xlength = None):
|
||||
if function is not None:
|
||||
self.function = function
|
||||
if xlength is not None:
|
||||
self.xlength = xlength
|
||||
# Calculate points
|
||||
(self.xpoints, self.ypoints) = self.function.evaluate(self.xlength, self.numxpoints)
|
||||
# Create plot
|
||||
self.plot()
|
||||
|
||||
def plot(self):
|
||||
plots = self.thePlot.series
|
||||
|
||||
if plots:
|
||||
# Remove line from plot
|
||||
axes = plots[0].axes
|
||||
axes.lines.pop(plots[0].lid)
|
||||
# Remove serie from list
|
||||
del self.thePlot.series[0]
|
||||
|
||||
self.thePlot.update()
|
||||
self.thePlot.plot(self.xpoints, self.ypoints)
|
133
src/Mod/PartDesign/WizardShaft/ShaftFeature.py
Normal file
133
src/Mod/PartDesign/WizardShaft/ShaftFeature.py
Normal file
|
@ -0,0 +1,133 @@
|
|||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library 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 library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
import FreeCAD, FreeCADGui
|
||||
import Part, Sketcher
|
||||
|
||||
class ShaftFeature:
|
||||
"Creates and updates the feature of the shaft"
|
||||
Doc = 0
|
||||
App = FreeCAD
|
||||
Gui = FreeCADGui
|
||||
sketch = 0
|
||||
feature = 0
|
||||
segments = 0 # number of segments
|
||||
totalLength = 0 # total length of all segments
|
||||
lastRadius = 0 # radius of last segment (required for adding segments)
|
||||
|
||||
def __init__(self, doc):
|
||||
"Create new feature"
|
||||
self.Doc = doc
|
||||
|
||||
# TODO: Discover existing sketch and get data from it
|
||||
self.sketch = self.Doc.addObject("Sketcher::SketchObject","SketchShaft")
|
||||
self.sketch.Placement = self.App.Placement(self.App.Vector(0,0,0),self.App.Rotation(0,0,0,1))
|
||||
|
||||
def addSegment(self, length, diameter):
|
||||
"Add a segment at the end of the shaft"
|
||||
# Find constraint indices of vertical line constraint, horizontal line constraint
|
||||
# FIXME: Should have a unique id instead of indices that might change with user editing
|
||||
# 0-3 belong to the centerline
|
||||
# 4-6 to the first vertical section
|
||||
# 7-9 to the first horizontal section
|
||||
# 10-12 to the second vertical section
|
||||
# etc. etc.
|
||||
constrRadius = 4 + self.segments * 6
|
||||
constrLength = 7 + self.segments * 6
|
||||
# Find line index of vertical segment, horizontal segment, last shaft segment
|
||||
# FIXME: Should have a unique id instead of indices that might change with user editing
|
||||
segRadius = 1 + self.segments * 2
|
||||
segLength = 2 + self.segments * 2
|
||||
prevSegLength = 0 + self.segments * 2
|
||||
prevSegEnd = 3 + (self.segments - 1) * 2
|
||||
segEnd = prevSegEnd + 2
|
||||
|
||||
radius = diameter / 2
|
||||
oldLength = self.totalLength
|
||||
self.totalLength += length
|
||||
self.segments += 1
|
||||
|
||||
if oldLength == 0:
|
||||
# First segment of shaft
|
||||
# Create centerline
|
||||
self.sketch.addGeometry(Part.Line(self.App.Vector(0,0,0), self.App.Vector(self.totalLength,0,0)))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('DistanceX',0, self.totalLength)) # Constraint1
|
||||
self.sketch.addConstraint(Sketcher.Constraint('PointOnObject',0,1,-1)) # Constraint2
|
||||
self.sketch.addConstraint(Sketcher.Constraint('PointOnObject',0,1,-2)) # Constraint3
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Horizontal', 0)) # Constraint4
|
||||
# Create first segment
|
||||
self.sketch.addGeometry(Part.Line(self.App.Vector(0,0,0), self.App.Vector(0,radius,0)))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('DistanceY',1,radius)) # Constraint5
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Coincident',0,1,1,1)) # Constraint6
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Vertical',1)) # Constraint7
|
||||
self.sketch.addGeometry(Part.Line(self.App.Vector(0,radius,0), self.App.Vector(length,radius,0)))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('DistanceX',2,length)) # Constraint8
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Coincident',2,1,1,2)) # Constraint9
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Horizontal',2)) # Constraint10
|
||||
else:
|
||||
# remove line that closes the shaft
|
||||
self.sketch.delGeometry(prevSegEnd)
|
||||
# TODO: Delete the two constraints? Or will they disappear automatically?
|
||||
# Adjust length of centerline
|
||||
self.sketch.setDatum(0,self.totalLength)
|
||||
# Add segment at the end
|
||||
self.sketch.addGeometry(Part.Line(self.App.Vector(oldLength,self.lastRadius,0), self.App.Vector(oldLength,radius,0)))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('DistanceY', 0, 1, segRadius, 2, radius))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Coincident',segRadius,1,prevSegLength,2))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Vertical',segRadius))
|
||||
self.sketch.addGeometry(Part.Line(self.App.Vector(oldLength,radius,0), self.App.Vector(oldLength+length,radius,0)))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('DistanceX',segLength,length))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Coincident',segLength,1,segRadius,2))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Horizontal',segLength))
|
||||
|
||||
# close the sketch
|
||||
self.sketch.addGeometry(Part.Line(self.App.Vector(oldLength+length,radius,0), self.App.Vector(oldLength+length,0,0)))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Coincident',0,2,segEnd,2))
|
||||
self.sketch.addConstraint(Sketcher.Constraint('Coincident',segEnd,1,segLength,2))
|
||||
lastRadius = radius
|
||||
|
||||
if oldLength == 0:
|
||||
# create feature
|
||||
self.feature = self.Doc.addObject("PartDesign::Revolution","RevolutionShaft")
|
||||
self.feature.Sketch = self.sketch
|
||||
self.feature.ReferenceAxis = (self.sketch,['H_Axis'])
|
||||
self.feature.Angle = 360.0
|
||||
self.Doc.recompute()
|
||||
self.Gui.hide("SketchShaft")
|
||||
else:
|
||||
self.Doc.recompute()
|
||||
# FIXME: Will give a warning in the console if the active window is not the feature
|
||||
self.Gui.SendMsgToActiveView("ViewFit")
|
||||
|
||||
def updateSegment(self, segment, oldLength, length, diameter):
|
||||
constrRadius = 4 + segment * 6
|
||||
constrLength = 7 + segment * 6
|
||||
# update total length
|
||||
self.totalLength = self.totalLength - oldLength + length
|
||||
# Adjust length of centerline
|
||||
self.sketch.setDatum(0,self.totalLength)
|
||||
# Adjust segment length
|
||||
self.sketch.setDatum(constrLength, length)
|
||||
self.sketch.setDatum(constrRadius, diameter/2)
|
||||
# Update feature
|
||||
self.Doc.recompute()
|
||||
self.Gui.SendMsgToActiveView("ViewFit")
|
94
src/Mod/PartDesign/WizardShaft/WizardShaft.py
Normal file
94
src/Mod/PartDesign/WizardShaft/WizardShaft.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library 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 library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
import FreeCAD, FreeCADGui
|
||||
#import os
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from WizardShaftTable import WizardShaftTable
|
||||
from Shaft import Shaft
|
||||
|
||||
class TaskWizardShaft:
|
||||
"Shaft Wizard"
|
||||
# GUI
|
||||
App = FreeCAD
|
||||
Gui = FreeCADGui
|
||||
doc = Gui.ActiveDocument
|
||||
# Table and widget
|
||||
table = 0
|
||||
form = 0
|
||||
# Shaft
|
||||
shaft = 0
|
||||
# Feature
|
||||
featureWindow = 0
|
||||
|
||||
def __init__(self):
|
||||
mw = QtGui.qApp.activeWindow()
|
||||
cw = mw.centralWidget() # This is a qmdiarea widget
|
||||
|
||||
# Get active document or create a new one
|
||||
# Important because when setting the default data in WizardShaftTable() the
|
||||
# updateSketch() slot will be activated and it relies on finding a valid document
|
||||
if self.doc == None:
|
||||
self.Gui.activateWorkbench("PartDesignWorkbench")
|
||||
self.doc = self.App.ActiveDocument
|
||||
# Grab the newly created feature window
|
||||
featureWindow = cw.subWindowList()[-1]
|
||||
else:
|
||||
featureWindow = cw.activeSubWindow()
|
||||
|
||||
# Create Shaft object
|
||||
self.shaft = Shaft(self.doc)
|
||||
|
||||
# Assign a table widget to the dock window
|
||||
self.table = WizardShaftTable(self, self.shaft)
|
||||
self.form = self.table.widget
|
||||
self.form.setWindowTitle("Shaft wizard")
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Ok)
|
||||
|
||||
def accept(self):
|
||||
if self.table:
|
||||
del self.table
|
||||
if self.shaft:
|
||||
del self.shaft
|
||||
if self.form:
|
||||
del self.form
|
||||
return True
|
||||
|
||||
class WizardShaftGui:
|
||||
def Activated(self):
|
||||
FreeCADGui.Control.showDialog(TaskWizardShaft())
|
||||
|
||||
def GetResources(self):
|
||||
IconPath = FreeCAD.ConfigGet("AppHomePath") + "Mod/PartDesign/WizardShaft/WizardShaft.svg"
|
||||
MenuText = 'Shaft design wizard...'
|
||||
ToolTip = 'Start the shaft design wizard'
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
def IsActive(self):
|
||||
return FreeCAD.ActiveDocument != None
|
||||
|
||||
FreeCADGui.addCommand('PartDesign_WizardShaft', WizardShaftGui())
|
||||
|
||||
#Note: Start wizard in Python Console with
|
||||
# Gui.runCommand('PartDesign_WizardShaft')
|
419
src/Mod/PartDesign/WizardShaft/WizardShaft.svg
Normal file
419
src/Mod/PartDesign/WizardShaft/WizardShaft.svg
Normal file
|
@ -0,0 +1,419 @@
|
|||
<?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="svg2901"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="PartDesign_Groove.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1"
|
||||
inkscape:export-filename="/home/yorik/PartDesign_Groove.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs2903">
|
||||
<linearGradient
|
||||
id="linearGradient4237">
|
||||
<stop
|
||||
id="stop4239"
|
||||
offset="0"
|
||||
style="stop-color:#f82b39;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4241"
|
||||
offset="1"
|
||||
style="stop-color:#520001;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4052">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4054" />
|
||||
<stop
|
||||
id="stop4060"
|
||||
offset="0.5"
|
||||
style="stop-color:#f0f1f1;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#0046ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4056" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4044">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4046" />
|
||||
<stop
|
||||
style="stop-color:#061aff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4048" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3273">
|
||||
<stop
|
||||
id="stop3275"
|
||||
offset="0"
|
||||
style="stop-color:#c8e0f9;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3277"
|
||||
offset="1"
|
||||
style="stop-color:#f7f9fa;stop-opacity:0.09649123;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3377">
|
||||
<stop
|
||||
id="stop3379"
|
||||
offset="0"
|
||||
style="stop-color:#c8e0f9;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3381"
|
||||
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="perspective2909" />
|
||||
<inkscape:perspective
|
||||
id="perspective3674"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4044"
|
||||
id="linearGradient4050"
|
||||
x1="44.858215"
|
||||
y1="14.016123"
|
||||
x2="33.928684"
|
||||
y2="33.216251"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,1.4694319,0.12765765)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4052"
|
||||
id="linearGradient4058"
|
||||
x1="42.373707"
|
||||
y1="5.7974987"
|
||||
x2="52.323219"
|
||||
y2="22.675821"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,1.4694319,0.12765765)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4052-1"
|
||||
id="linearGradient4058-6"
|
||||
x1="42.373707"
|
||||
y1="5.7974987"
|
||||
x2="52.323219"
|
||||
y2="22.675821"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,1.4694319,0.12765765)" />
|
||||
<linearGradient
|
||||
id="linearGradient4052-1">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4054-5" />
|
||||
<stop
|
||||
id="stop4060-8"
|
||||
offset="0.5"
|
||||
style="stop-color:#f0f1f1;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#0046ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4056-4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="translate(-30.295225,-2.9287147)"
|
||||
y2="22.675821"
|
||||
x2="52.323219"
|
||||
y1="5.7974987"
|
||||
x1="42.373707"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4078"
|
||||
xlink:href="#linearGradient4052-1"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4044"
|
||||
id="linearGradient3885"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,107.10579,-22.235978)"
|
||||
x1="44.858215"
|
||||
y1="14.016123"
|
||||
x2="33.928684"
|
||||
y2="33.216251" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4052-1"
|
||||
id="linearGradient3890"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,107.10579,-22.235978)"
|
||||
x1="42.373707"
|
||||
y1="5.7974987"
|
||||
x2="52.323219"
|
||||
y2="22.675821" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4052"
|
||||
id="linearGradient3893"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,107.10579,-22.235978)"
|
||||
x1="42.373707"
|
||||
y1="5.7974987"
|
||||
x2="52.323219"
|
||||
y2="22.675821" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4052-1-0"
|
||||
id="linearGradient3890-3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.55370638,0,0,0.55364331,74.680363,-24.12284)"
|
||||
x1="42.373707"
|
||||
y1="5.7974987"
|
||||
x2="52.323219"
|
||||
y2="22.675821" />
|
||||
<linearGradient
|
||||
id="linearGradient4052-1-0">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4054-5-5" />
|
||||
<stop
|
||||
id="stop4060-8-6"
|
||||
offset="0.5"
|
||||
style="stop-color:#f0f1f1;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#0046ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4056-4-6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="22.675821"
|
||||
x2="52.323219"
|
||||
y1="5.7974987"
|
||||
x1="42.373707"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,-3.3630199,-18.322982)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3912"
|
||||
xlink:href="#linearGradient4052-1-0"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4052-1-0-0">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4054-5-5-9" />
|
||||
<stop
|
||||
id="stop4060-8-6-8"
|
||||
offset="0.5"
|
||||
style="stop-color:#f0f1f1;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#0046ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4056-4-6-4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="22.675821"
|
||||
x2="52.323219"
|
||||
y1="5.7974987"
|
||||
x1="42.373707"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,126.73769,-70.092683)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3985"
|
||||
xlink:href="#linearGradient4052-1-0-0"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4044"
|
||||
id="linearGradient3885-6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.55370638,0,0,0.55364331,60.929239,37.280914)"
|
||||
x1="44.858215"
|
||||
y1="14.016123"
|
||||
x2="33.928684"
|
||||
y2="33.216251" />
|
||||
<linearGradient
|
||||
id="linearGradient4044-8">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4046-2" />
|
||||
<stop
|
||||
style="stop-color:#061aff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4048-1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="33.216251"
|
||||
x2="33.928684"
|
||||
y1="14.016123"
|
||||
x1="44.858215"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,-26.24677,-8.4607595)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4072"
|
||||
xlink:href="#linearGradient4044-8"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4044-8-4"
|
||||
id="linearGradient3885-6-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,58.307367,54.671469)"
|
||||
x1="44.858215"
|
||||
y1="14.016123"
|
||||
x2="33.928684"
|
||||
y2="33.216251" />
|
||||
<linearGradient
|
||||
id="linearGradient4044-8-4">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4046-2-0" />
|
||||
<stop
|
||||
style="stop-color:#061aff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4048-1-9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="33.216251"
|
||||
x2="33.928684"
|
||||
y1="14.016123"
|
||||
x1="44.858215"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,145.41299,94.782221)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4163"
|
||||
xlink:href="#linearGradient4044-8-4"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4052-1-0-9"
|
||||
id="linearGradient3890-3-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.55370638,0,0,0.55364331,74.680363,-24.12284)"
|
||||
x1="42.373707"
|
||||
y1="5.7974987"
|
||||
x2="52.323219"
|
||||
y2="22.675821" />
|
||||
<linearGradient
|
||||
id="linearGradient4052-1-0-9">
|
||||
<stop
|
||||
style="stop-color:#0090ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4054-5-5-2" />
|
||||
<stop
|
||||
id="stop4060-8-6-5"
|
||||
offset="0.5"
|
||||
style="stop-color:#f0f1f1;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#0046ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4056-4-6-5" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="22.675821"
|
||||
x2="52.323219"
|
||||
y1="5.7974987"
|
||||
x1="42.373707"
|
||||
gradientTransform="matrix(0.97680237,0,0,0.96003508,126.73769,-70.092687)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4217"
|
||||
xlink:href="#linearGradient4052-1-0-9"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.8890873"
|
||||
inkscape:cx="38.625766"
|
||||
inkscape:cy="12.657788"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1018"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-intersection-paths="true" />
|
||||
<metadata
|
||||
id="metadata2906">
|
||||
<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">
|
||||
<path
|
||||
style="color:#000000;fill:none;stroke:#ff0d00;stroke-width:5;stroke-linecap:round;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.033553,11.624146 2.9356835,49.895439"
|
||||
id="path4129"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="color:#000000;fill:url(#linearGradient3885-6);fill-opacity:1.0;fill-rule:evenodd;stroke:#000137;stroke-width:2;stroke-linecap:round;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 33.589321,8.1499488 c 0.310719,0.4348594 0.568952,0.924885 0.761713,1.4417267 1.54209,4.1347065 -1.513953,9.1431885 -6.819987,11.1914025 -1.079148,0.416568 -2.160312,0.657262 -3.223995,0.774928 7.099799,4.804046 13.087612,12.269737 15.251972,21.806117 0.674062,-1.709016 1.803272,-3.374523 3.365708,-4.775719 2.394689,-2.147563 5.276855,-3.22083 7.847415,-3.153778 1.999324,0.05215 3.808695,0.783303 5.066276,2.234677 0.431584,0.49809 0.762456,1.065523 1.027427,1.657986 C 57.308292,21.656223 46.249275,12.722898 33.589321,8.1499488 z"
|
||||
id="path3832-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cssccssscc" />
|
||||
<path
|
||||
style="color:#000000;fill:none;stroke:#000137;stroke-width:2;stroke-linecap:round;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 33.595667,8.1588471 c 0.31072,0.4348652 0.568952,0.9248908 0.761713,1.4417268 1.542089,4.1347081 -1.513952,9.1431901 -6.819987,11.1914041 -1.079148,0.416568 -2.160311,0.657262 -3.223994,0.774928 m 15.251974,21.806118 c 0.67406,-1.709017 1.803271,-3.374523 3.365708,-4.77572 2.394689,-2.147563 5.276852,-3.22083 7.847414,-3.153778 1.999324,0.05215 3.808695,0.783303 5.066277,2.234677 0.431581,0.49809 0.762455,1.065523 1.027426,1.657986"
|
||||
id="path3832-2-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cssccsssc" />
|
||||
<path
|
||||
id="path3846-3"
|
||||
style="color:#000000;fill:url(#linearGradient3890-3);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2;stroke-linecap:round;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 3.536174,22.642207 c 18.022131,7.741361 26.381756,27.136035 26.236001,37.96079 L 40.42899,51.501192 C 40.591405,33.650608 27.82732,21.231698 15.136181,17.008914 z"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
id="path3842-6"
|
||||
style="color:#000000;fill:url(#linearGradient3890-3-5);fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2;stroke-linecap:round;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 56.874841,39.325295 C 57.306666,21.656073 46.253772,12.727686 33.592842,8.1578264 L 39.537797,5.2929423 C 56.829323,9.1025668 61.692642,25.014757 61.692642,35.542943 z"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
id="path3852-7"
|
||||
style="color:#000000;fill:#8bd2f7;fill-opacity:1;fill-rule:evenodd;stroke:#000137;stroke-width:2;stroke-linecap:round;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 29.772175,60.602996 C 29.91793,49.77824 21.558305,30.383568 3.5361734,22.642207 L 3.97344,30.797845 c 7.619318,3.028308 17.782178,14.976717 18.219445,24.911767 z"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
334
src/Mod/PartDesign/WizardShaft/WizardShaftTable.py
Normal file
334
src/Mod/PartDesign/WizardShaft/WizardShaftTable.py
Normal file
|
@ -0,0 +1,334 @@
|
|||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library 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 library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
import FreeCAD # Just for debug printing...
|
||||
|
||||
class WizardShaftTable:
|
||||
"The table widget that contains all the data of the shaft"
|
||||
# Dictionary to access different parameters without using a numeric row index that might change
|
||||
# as the code evolves
|
||||
rowDict = {
|
||||
"Length" : 0,
|
||||
"Diameter" : 1,
|
||||
"LoadType" : 2,
|
||||
"LoadSize" : 3,
|
||||
"LoadLocation" : 4,
|
||||
"StartEdgeType" : 5,
|
||||
"StartEdgeSize" : 6,
|
||||
"EndEdgeType" : 7,
|
||||
"EndEdgeSize" : 8
|
||||
}
|
||||
rowDictReverse = {}
|
||||
headers = ["Length [mm]",
|
||||
"Diameter [mm]",
|
||||
"Load type",
|
||||
"Load [N]",
|
||||
"Location [mm]",
|
||||
"Start edge type",
|
||||
"Start edge size",
|
||||
"End edge type",
|
||||
"End edge size"
|
||||
]
|
||||
widget = 0
|
||||
wizard = 0
|
||||
shaft = 0
|
||||
|
||||
def __init__(self, w, s):
|
||||
for key in self.rowDict.iterkeys():
|
||||
self.rowDictReverse[self.rowDict[key]] = key
|
||||
# Set parent wizard (for connecting slots)
|
||||
self.wizard = w
|
||||
self.shaft = s
|
||||
# Create table widget
|
||||
self.widget = QtGui.QTableWidget(len(self.rowDict), 0)
|
||||
self.widget.resize(QtCore.QSize(300,100))
|
||||
#self.widget.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||
|
||||
# Label rows and columns
|
||||
self.widget.setVerticalHeaderLabels(self.headers)
|
||||
self.widget.setHorizontalHeaderLabels(["Section 1", "Section 2"])
|
||||
#self.widget.columnMoved.connect(column, oldIndex, newIndex)
|
||||
|
||||
# Create context menu
|
||||
action = QtGui.QAction("Add column", self.widget)
|
||||
action.triggered.connect(self.slotInsertColumn)
|
||||
self.widget.addAction(action)
|
||||
self.widget.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
|
||||
|
||||
# Set some default data
|
||||
# Section 1
|
||||
self.addColumn()
|
||||
self.setLength(0, 40.0)
|
||||
self.setDiameter(0, 50.0)
|
||||
self.setLoadType(0, "Static")
|
||||
self.setLoadSize(0, 1000.0)
|
||||
self.setLoadLocation(0, 25.0)
|
||||
# Section 2
|
||||
self.addColumn()
|
||||
self.setLength(1, 80.0)
|
||||
self.setDiameter(1, 60.0)
|
||||
self.setLoadType(1, "Fixed")
|
||||
|
||||
def slotInsertColumn(self, point):
|
||||
# FIXME: Allow inserting columns, not just adding at the end
|
||||
# Note: need to re-name all the following column headers then
|
||||
# if (column == self.tableWidget.columnCount()):
|
||||
self.addColumn()
|
||||
# else:
|
||||
# self.insertColumn(index)
|
||||
|
||||
def addColumn(self):
|
||||
"Add a new column, fill it with widgets, and connect the signals"
|
||||
index = self.widget.columnCount()
|
||||
# Make an intelligent guess at the length/dia of the next segment
|
||||
if index > 0:
|
||||
length = self.shaft.segments[index-1].length
|
||||
diameter = self.shaft.segments[index-1].diameter
|
||||
if index > 2:
|
||||
diameter -= 5.0
|
||||
else:
|
||||
diameter += 5.0
|
||||
else:
|
||||
length = 20.0
|
||||
diameter = 10.0
|
||||
self.shaft.addSegment(length, diameter)
|
||||
|
||||
self.widget.insertColumn(index)
|
||||
self.widget.setHorizontalHeaderItem(index + 1, QtGui.QTableWidgetItem("Section %s" % (index + 1)))
|
||||
|
||||
# Length
|
||||
widget = QtGui.QDoubleSpinBox(self.widget)
|
||||
widget.setMinimum(0)
|
||||
widget.setMaximum(1E9)
|
||||
self.widget.setCellWidget(self.rowDict["Length"], index, widget)
|
||||
widget.setValue(length)
|
||||
widget.valueChanged.connect(self.slotValueChanged)
|
||||
widget.editingFinished.connect(self.slotEditingFinished)
|
||||
# Diameter
|
||||
widget = QtGui.QDoubleSpinBox(self.widget)
|
||||
widget.setMinimum(0)
|
||||
widget.setMaximum(1E9)
|
||||
self.widget.setCellWidget(self.rowDict["Diameter"], index, widget)
|
||||
widget.setValue(diameter)
|
||||
widget.valueChanged.connect(self.slotValueChanged)
|
||||
widget.editingFinished.connect(self.slotEditingFinished)
|
||||
# Load type
|
||||
widget = QtGui.QComboBox(self.widget)
|
||||
widget.insertItem(0, "None")
|
||||
widget.insertItem(1, "Fixed")
|
||||
widget.insertItem(2, "Static")
|
||||
widget.insertItem(3, "Bearing")
|
||||
widget.insertItem(4, "Pulley")
|
||||
self.widget.setCellWidget(self.rowDict["LoadType"], index, widget)
|
||||
widget.setCurrentIndex(0)
|
||||
self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
|
||||
# Load size
|
||||
widget = QtGui.QDoubleSpinBox(self.widget)
|
||||
widget.setMinimum(-1E9)
|
||||
widget.setMaximum(1E9)
|
||||
self.widget.setCellWidget(self.rowDict["LoadSize"], index, widget)
|
||||
widget.setValue(0)
|
||||
widget.valueChanged.connect(self.slotValueChanged)
|
||||
widget.editingFinished.connect(self.slotEditingFinished)
|
||||
# Load location
|
||||
widget = QtGui.QDoubleSpinBox(self.widget)
|
||||
widget.setMinimum(0)
|
||||
widget.setMaximum(1E9)
|
||||
self.widget.setCellWidget(self.rowDict["LoadLocation"], index, widget)
|
||||
widget.setValue(0)
|
||||
widget.valueChanged.connect(self.slotValueChanged)
|
||||
widget.editingFinished.connect(self.slotEditingFinished)
|
||||
# Start edge type
|
||||
widget = QtGui.QComboBox(self.widget)
|
||||
widget.insertItem(0, "None",)
|
||||
widget.insertItem(1, "Chamfer")
|
||||
widget.insertItem(2, "Fillet")
|
||||
self.widget.setCellWidget(self.rowDict["StartEdgeType"],index, widget)
|
||||
widget.setCurrentIndex(0)
|
||||
self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
|
||||
# Start edge size
|
||||
widget = QtGui.QDoubleSpinBox(self.widget)
|
||||
widget.setMinimum(0)
|
||||
widget.setMaximum(1E9)
|
||||
self.widget.setCellWidget(self.rowDict["StartEdgeSize"],index, widget)
|
||||
widget.setValue(1)
|
||||
widget.valueChanged.connect(self.slotValueChanged)
|
||||
widget.editingFinished.connect(self.slotEditingFinished)
|
||||
# End edge type
|
||||
widget = QtGui.QComboBox(self.widget)
|
||||
widget.insertItem(0, "None",)
|
||||
widget.insertItem(1, "Chamfer")
|
||||
widget.insertItem(2, "Fillet")
|
||||
self.widget.setCellWidget(self.rowDict["EndEdgeType"],index, widget)
|
||||
widget.setCurrentIndex(0)
|
||||
self.widget.connect(widget, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.slotLoadType)
|
||||
# End edge size
|
||||
widget = QtGui.QDoubleSpinBox(self.widget)
|
||||
widget.setMinimum(0)
|
||||
widget.setMaximum(1E9)
|
||||
self.widget.setCellWidget(self.rowDict["EndEdgeSize"],index, widget)
|
||||
widget.setValue(1)
|
||||
widget.valueChanged.connect(self.slotValueChanged)
|
||||
widget.editingFinished.connect(self.slotEditingFinished)
|
||||
|
||||
def slotValueChanged(self, value):
|
||||
(self.editedRow, self.editedColumn) = self.getFocusedCell()
|
||||
self.editedValue = value
|
||||
|
||||
def slotEditingFinished(self):
|
||||
rowName = self.rowDictReverse[self.editedRow]
|
||||
if rowName is None:
|
||||
return
|
||||
if rowName == "Length":
|
||||
self.shaft.updateSegment(self.editedColumn, length = self.getDoubleValue(rowName, self.editedColumn))
|
||||
elif rowName == "Diameter":
|
||||
self.shaft.updateSegment(self.editedColumn, diameter = self.getDoubleValue(rowName, self.editedColumn))
|
||||
elif rowName == "LoadType":
|
||||
self.shaft.updateLoad(self.editedColumn, loadType = self.getListValue(rowName, self.editedColumn))
|
||||
elif rowName == "LoadSize":
|
||||
self.shaft.updateLoad(self.editedColumn, loadSize = self.getDoubleValue(rowName, self.editedColumn))
|
||||
elif rowName == "LoadLocation":
|
||||
self.shaft.updateLoad(self.editedColumn, loadLocation = self.getDoubleValue(rowName, self.editedColumn))
|
||||
elif rowName == "StartEdgeType":
|
||||
pass
|
||||
elif rowName == "StartEdgeSize":
|
||||
pass
|
||||
elif rowName == "EndEdgeType":
|
||||
pass
|
||||
elif rowName == "EndEdgeSize":
|
||||
pass
|
||||
|
||||
def setLength(self, column, l):
|
||||
self.setDoubleValue("Length", column, l)
|
||||
self.shaft.updateSegment(column, length = l)
|
||||
|
||||
def getLength(self, column):
|
||||
return self.getDoubleValue("Length", column)
|
||||
|
||||
def setDiameter(self, column, d):
|
||||
self.setDoubleValue("Diameter", column, d)
|
||||
self.shaft.updateSegment(column, diameter = d)
|
||||
|
||||
def getDiameter(self, column):
|
||||
return self.getDoubleValue("Diameter", column)
|
||||
|
||||
@QtCore.pyqtSlot('QString')
|
||||
def slotLoadType(self, text):
|
||||
if text != "Fixed":
|
||||
if (self.getLoadSize is None) or (self.getLoadLocation is None):
|
||||
return
|
||||
self.shaft.updateLoad(self.getFocusedColumn(), loadType = text)
|
||||
|
||||
def setLoadType(self, column, t):
|
||||
self.setListValue("LoadType", column, t)
|
||||
self.shaft.updateLoad(column, loadType = t)
|
||||
|
||||
def getLoadType(self, column):
|
||||
return self.getListValue("LoadType", column)
|
||||
|
||||
def setLoadSize(self, column, s):
|
||||
self.setDoubleValue("LoadSize", column, s)
|
||||
self.shaft.updateLoad(column, loadSize = s)
|
||||
|
||||
def getLoadSize(self, column):
|
||||
return self.getDoubleValue("LoadSize", column)
|
||||
|
||||
def setLoadLocation(self, column, l):
|
||||
self.setDoubleValue("LoadLocation", column, l)
|
||||
self.shaft.updateLoad(column, loadLocation = l)
|
||||
|
||||
def getLoadLocation(self, column):
|
||||
return self.getDoubleValue("LoadLocation", column)
|
||||
|
||||
def slotStartEdgeType(self, old, new):
|
||||
pass
|
||||
|
||||
def setStartEdgeType(self, column, t):
|
||||
self.setListValue("StartEdgeType", column, t)
|
||||
|
||||
def getStartEdgeType(self, column):
|
||||
return self.getListValue("StartEdgeType", column)
|
||||
|
||||
def setStartEdgeSize(self, column, s):
|
||||
self.setDoubleValue("StartEdgeSize", column, s)
|
||||
|
||||
def getStartEdgeSize(self, column):
|
||||
return self.getDoubleValue("StartEdgeSize", column)
|
||||
|
||||
def slotEndEdgeType(self, old, new):
|
||||
pass
|
||||
|
||||
def setEndEdgeType(self, column, t):
|
||||
self.setListValue("EndEdgeType", column, t)
|
||||
|
||||
def getEndEdgeType(self, column):
|
||||
return self.getListValue("EndEdgeType", column)
|
||||
|
||||
def setEndEdgeSize(self, column, s):
|
||||
self.setDoubleValue("EndEdgeSize", column, s)
|
||||
|
||||
def getEndEdgeSize(self, column):
|
||||
return self.getDoubleValue("EndEdgeSize", column)
|
||||
|
||||
def setDoubleValue(self, row, column, v):
|
||||
widget = self.widget.cellWidget(self.rowDict[row], column)
|
||||
# Avoid triggering a signal, because the slot will work on the focused cell, not the current one
|
||||
widget.blockSignals(True)
|
||||
widget.setValue(v)
|
||||
widget.blockSignals(False)
|
||||
|
||||
def getDoubleValue(self, row, column):
|
||||
widget = self.widget.cellWidget(self.rowDict[row], column)
|
||||
if widget is not None:
|
||||
return widget.value()
|
||||
else:
|
||||
return None
|
||||
|
||||
def setListValue(self, row, column, v):
|
||||
widget = self.widget.cellWidget(self.rowDict[row], column)
|
||||
widget.blockSignals(True)
|
||||
widget.setCurrentIndex(widget.findText(v, QtCore.Qt.MatchExactly))
|
||||
widget.blockSignals(False)
|
||||
|
||||
def getListValue(self, row, column):
|
||||
widget = self.widget.cellWidget(self.rowDict[row], column)
|
||||
if widget is not None:
|
||||
return widget.currentText().toAscii()[0].upper()
|
||||
else:
|
||||
return None
|
||||
|
||||
def getFocusedColumn(self):
|
||||
# Make the focused cell also the current one in the table
|
||||
widget = QtGui.QApplication.focusWidget()
|
||||
if widget is not None:
|
||||
index = self.widget.indexAt(widget.pos())
|
||||
self.widget.setCurrentCell(index.row(), index.column())
|
||||
return self.widget.currentColumn()
|
||||
|
||||
def getFocusedCell(self):
|
||||
# Make the focused cell also the current one in the table
|
||||
widget = QtGui.QApplication.focusWidget()
|
||||
if widget is not None:
|
||||
index = self.widget.indexAt(widget.pos())
|
||||
self.widget.setCurrentCell(index.row(), index.column())
|
||||
return (self.widget.currentRow(), self.widget.currentColumn())
|
27
src/Mod/PartDesign/WizardShaft/__init__.py
Normal file
27
src/Mod/PartDesign/WizardShaft/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
Shaft Wizard
|
||||
"""
|
||||
|
||||
#/******************************************************************************
|
||||
# * Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
# * This library is free software; you can redistribute it and/or *
|
||||
# * modify it under the terms of the GNU Library General Public *
|
||||
# * License as published by the Free Software Foundation; either *
|
||||
# * version 2 of the License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * This library 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 library; see the file COPYING.LIB. If not, *
|
||||
# * write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
# * Suite 330, Boston, MA 02111-1307, USA *
|
||||
# * *
|
||||
# ******************************************************************************/
|
||||
|
||||
# Empty file to treat the folder as a package
|
|
@ -51,7 +51,7 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|||
int SecondIndex= Constraint::GeoUndef;
|
||||
int SecondPos = none;
|
||||
int ThirdIndex = Constraint::GeoUndef;
|
||||
//int ThirdPos = none;
|
||||
int ThirdPos = none;
|
||||
double Value = 0;
|
||||
// Note: In Python 2.x PyArg_ParseTuple prints a warning if a float is given but an integer is expected.
|
||||
// This means we must use a PyObject and check afterwards if it's a float or integer.
|
||||
|
@ -292,6 +292,21 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|||
}
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
|
||||
if (PyArg_ParseTuple(args, "siiiiii", &ConstraintType, &FirstIndex, &FirstPos, &SecondIndex, &SecondPos, &ThirdIndex, &ThirdPos)) {
|
||||
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2, GeoIndex3, PosIndex3
|
||||
if (strcmp("Symmetric",ConstraintType) == 0 ) {
|
||||
this->getConstraintPtr()->Type = Symmetric;
|
||||
this->getConstraintPtr()->First = FirstIndex;
|
||||
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
|
||||
this->getConstraintPtr()->Second = SecondIndex;
|
||||
this->getConstraintPtr()->SecondPos = (Sketcher::PointPos) SecondPos;
|
||||
this->getConstraintPtr()->Third = ThirdIndex;
|
||||
this->getConstraintPtr()->ThirdPos = (Sketcher::PointPos) ThirdPos;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Constraint constructor accepts:\n"
|
||||
"-- empty parameter list\n"
|
||||
|
|
|
@ -537,8 +537,13 @@ int Sketch::addConstraint(const Constraint *constraint)
|
|||
rtn = addEqualConstraint(constraint->First,constraint->Second);
|
||||
break;
|
||||
case Symmetric:
|
||||
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,constraint->SecondPos,constraint->Third);
|
||||
if (constraint->ThirdPos != none)
|
||||
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,constraint->SecondPos,
|
||||
constraint->Third,constraint->ThirdPos);
|
||||
else
|
||||
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,constraint->SecondPos,constraint->Third);
|
||||
break;
|
||||
case None:
|
||||
break;
|
||||
|
@ -1522,6 +1527,30 @@ int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointP
|
|||
return -1;
|
||||
}
|
||||
|
||||
int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2,
|
||||
int geoId3, PointPos pos3)
|
||||
{
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
geoId3 = checkGeoId(geoId3);
|
||||
|
||||
int pointId1 = getPointId(geoId1, pos1);
|
||||
int pointId2 = getPointId(geoId2, pos2);
|
||||
int pointId3 = getPointId(geoId3, pos3);
|
||||
|
||||
if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
|
||||
pointId2 >= 0 && pointId2 < int(Points.size()) &&
|
||||
pointId3 >= 0 && pointId3 < int(Points.size())) {
|
||||
GCS::Point &p1 = Points[pointId1];
|
||||
GCS::Point &p2 = Points[pointId2];
|
||||
GCS::Point &p = Points[pointId3];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PSymmetric(p1, p2, p, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Sketch::updateGeometry()
|
||||
{
|
||||
int i=0;
|
||||
|
|
|
@ -172,6 +172,8 @@ public:
|
|||
int addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2);
|
||||
/// add a symmetric constraint between two points with respect to a line
|
||||
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3);
|
||||
/// add a symmetric constraint between three points, the last point is in the middle of the first two
|
||||
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3, PointPos pos3);
|
||||
//@}
|
||||
|
||||
enum GeoType {
|
||||
|
|
|
@ -1519,7 +1519,7 @@ void SketchObject::onFinishDuplicating()
|
|||
onDocumentRestored();
|
||||
}
|
||||
|
||||
void SketchObject::getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId)
|
||||
void SketchObject::getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId) const
|
||||
{
|
||||
if (VertexId < 0 || VertexId >= int(VertexId2GeoId.size())) {
|
||||
GeoId = Constraint::GeoUndef;
|
||||
|
|
|
@ -124,7 +124,7 @@ public:
|
|||
int trim(int geoId, const Base::Vector3d& point);
|
||||
|
||||
/// retrieves for a Vertex number the corresponding GeoId and PosId
|
||||
void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId);
|
||||
void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId) const;
|
||||
int getHighestVertexIndex(void) const { return VertexId2GeoId.size() - 1; }
|
||||
int getHighestCurveIndex(void) const { return Geometry.getSize() - 1; }
|
||||
void rebuildVertexIndex(void);
|
||||
|
|
|
@ -413,6 +413,18 @@ ConstraintPointOnLine::ConstraintPointOnLine(Point &p, Line &l)
|
|||
rescale();
|
||||
}
|
||||
|
||||
ConstraintPointOnLine::ConstraintPointOnLine(Point &p, Point &lp1, Point &lp2)
|
||||
{
|
||||
pvec.push_back(p.x);
|
||||
pvec.push_back(p.y);
|
||||
pvec.push_back(lp1.x);
|
||||
pvec.push_back(lp1.y);
|
||||
pvec.push_back(lp2.x);
|
||||
pvec.push_back(lp2.y);
|
||||
origpvec = pvec;
|
||||
rescale();
|
||||
}
|
||||
|
||||
ConstraintType ConstraintPointOnLine::getTypeId()
|
||||
{
|
||||
return PointOnLine;
|
||||
|
@ -460,6 +472,74 @@ double ConstraintPointOnLine::grad(double *param)
|
|||
return scale * deriv;
|
||||
}
|
||||
|
||||
// PointOnPerpBisector
|
||||
ConstraintPointOnPerpBisector::ConstraintPointOnPerpBisector(Point &p, Line &l)
|
||||
{
|
||||
pvec.push_back(p.x);
|
||||
pvec.push_back(p.y);
|
||||
pvec.push_back(l.p1.x);
|
||||
pvec.push_back(l.p1.y);
|
||||
pvec.push_back(l.p2.x);
|
||||
pvec.push_back(l.p2.y);
|
||||
origpvec = pvec;
|
||||
rescale();
|
||||
}
|
||||
|
||||
ConstraintPointOnPerpBisector::ConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2)
|
||||
{
|
||||
pvec.push_back(p.x);
|
||||
pvec.push_back(p.y);
|
||||
pvec.push_back(lp1.x);
|
||||
pvec.push_back(lp1.y);
|
||||
pvec.push_back(lp2.x);
|
||||
pvec.push_back(lp2.y);
|
||||
origpvec = pvec;
|
||||
rescale();
|
||||
}
|
||||
|
||||
ConstraintType ConstraintPointOnPerpBisector::getTypeId()
|
||||
{
|
||||
return PointOnPerpBisector;
|
||||
}
|
||||
|
||||
void ConstraintPointOnPerpBisector::rescale(double coef)
|
||||
{
|
||||
scale = coef;
|
||||
}
|
||||
|
||||
double ConstraintPointOnPerpBisector::error()
|
||||
{
|
||||
double dx1 = *p1x() - *p0x();
|
||||
double dy1 = *p1y() - *p0y();
|
||||
double dx2 = *p2x() - *p0x();
|
||||
double dy2 = *p2y() - *p0y();
|
||||
return scale * (sqrt(dx1*dx1+dy1*dy1) - sqrt(dx2*dx2+dy2*dy2));
|
||||
}
|
||||
|
||||
double ConstraintPointOnPerpBisector::grad(double *param)
|
||||
{
|
||||
double deriv=0.;
|
||||
if (param == p0x() || param == p0y() ||
|
||||
param == p1x() || param == p1y()) {
|
||||
double dx1 = *p1x() - *p0x();
|
||||
double dy1 = *p1y() - *p0y();
|
||||
if (param == p0x()) deriv -= dx1/sqrt(dx1*dx1+dy1*dy1);
|
||||
if (param == p0y()) deriv -= dy1/sqrt(dx1*dx1+dy1*dy1);
|
||||
if (param == p1x()) deriv += dx1/sqrt(dx1*dx1+dy1*dy1);
|
||||
if (param == p1y()) deriv += dy1/sqrt(dx1*dx1+dy1*dy1);
|
||||
}
|
||||
if (param == p0x() || param == p0y() ||
|
||||
param == p2x() || param == p2y()) {
|
||||
double dx2 = *p2x() - *p0x();
|
||||
double dy2 = *p2y() - *p0y();
|
||||
if (param == p0x()) deriv += dx2/sqrt(dx2*dx2+dy2*dy2);
|
||||
if (param == p0y()) deriv += dy2/sqrt(dx2*dx2+dy2*dy2);
|
||||
if (param == p2x()) deriv -= dx2/sqrt(dx2*dx2+dy2*dy2);
|
||||
if (param == p2y()) deriv -= dy2/sqrt(dx2*dx2+dy2*dy2);
|
||||
}
|
||||
return scale * deriv;
|
||||
}
|
||||
|
||||
// Parallel
|
||||
ConstraintParallel::ConstraintParallel(Line &l1, Line &l2)
|
||||
{
|
||||
|
|
|
@ -41,11 +41,12 @@ namespace GCS
|
|||
P2PAngle = 4,
|
||||
P2LDistance = 5,
|
||||
PointOnLine = 6,
|
||||
Parallel = 7,
|
||||
Perpendicular = 8,
|
||||
L2LAngle = 9,
|
||||
MidpointOnLine = 10,
|
||||
TangentCircumf = 11
|
||||
PointOnPerpBisector = 7,
|
||||
Parallel = 8,
|
||||
Perpendicular = 9,
|
||||
L2LAngle = 10,
|
||||
MidpointOnLine = 11,
|
||||
TangentCircumf = 12
|
||||
};
|
||||
|
||||
class Constraint
|
||||
|
@ -171,6 +172,26 @@ namespace GCS
|
|||
inline double* p2y() { return pvec[5]; }
|
||||
public:
|
||||
ConstraintPointOnLine(Point &p, Line &l);
|
||||
ConstraintPointOnLine(Point &p, Point &lp1, Point &lp2);
|
||||
virtual ConstraintType getTypeId();
|
||||
virtual void rescale(double coef=1.);
|
||||
virtual double error();
|
||||
virtual double grad(double *);
|
||||
};
|
||||
|
||||
// PointOnPerpBisector
|
||||
class ConstraintPointOnPerpBisector : public Constraint
|
||||
{
|
||||
private:
|
||||
inline double* p0x() { return pvec[0]; }
|
||||
inline double* p0y() { return pvec[1]; }
|
||||
inline double* p1x() { return pvec[2]; }
|
||||
inline double* p1y() { return pvec[3]; }
|
||||
inline double* p2x() { return pvec[4]; }
|
||||
inline double* p2y() { return pvec[5]; }
|
||||
public:
|
||||
ConstraintPointOnPerpBisector(Point &p, Line &l);
|
||||
ConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2);
|
||||
virtual ConstraintType getTypeId();
|
||||
virtual void rescale(double coef=1.);
|
||||
virtual double error();
|
||||
|
|
|
@ -250,6 +250,27 @@ int System::addConstraintPointOnLine(Point &p, Line &l, int tagId)
|
|||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintPointOnLine(Point &p, Point &lp1, Point &lp2, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintPointOnLine(p, lp1, lp2);
|
||||
constr->setTag(tagId);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintPointOnPerpBisector(Point &p, Line &l, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintPointOnPerpBisector(p, l);
|
||||
constr->setTag(tagId);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintPointOnPerpBisector(p, lp1, lp2);
|
||||
constr->setTag(tagId);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintParallel(Line &l1, Line &l2, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintParallel(l1, l2);
|
||||
|
@ -552,6 +573,12 @@ int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId)
|
|||
return addConstraintMidpointOnLine(p1, p2, l.p1, l.p2, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId)
|
||||
{
|
||||
addConstraintPointOnPerpBisector(p, p1, p2, tagId);
|
||||
return addConstraintPointOnLine(p, p1, p2, tagId);
|
||||
}
|
||||
|
||||
void System::rescaleConstraint(int id, double coeff)
|
||||
{
|
||||
if (id >= clist.size() || id < 0)
|
||||
|
|
|
@ -99,6 +99,9 @@ namespace GCS
|
|||
int addConstraintP2PAngle(Point &p1, Point &p2, double *angle, int tagId=0);
|
||||
int addConstraintP2LDistance(Point &p, Line &l, double *distance, int tagId=0);
|
||||
int addConstraintPointOnLine(Point &p, Line &l, int tagId=0);
|
||||
int addConstraintPointOnLine(Point &p, Point &lp1, Point &lp2, int tagId=0);
|
||||
int addConstraintPointOnPerpBisector(Point &p, Line &l, int tagId=0);
|
||||
int addConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2, int tagId=0);
|
||||
int addConstraintParallel(Line &l1, Line &l2, int tagId=0);
|
||||
int addConstraintPerpendicular(Line &l1, Line &l2, int tagId=0);
|
||||
int addConstraintPerpendicular(Point &l1p1, Point &l1p2,
|
||||
|
@ -151,6 +154,7 @@ namespace GCS
|
|||
int addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId=0);
|
||||
int addConstraintEqualRadius(Arc &a1, Arc &a2, int tagId=0);
|
||||
int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0);
|
||||
int addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId=0);
|
||||
void rescaleConstraint(int id, double coeff);
|
||||
|
||||
void declareUnknowns(VEC_pD ¶ms);
|
||||
|
|
|
@ -79,22 +79,55 @@ bool checkBothExternal(int GeoId1, int GeoId2)
|
|||
return false;
|
||||
}
|
||||
|
||||
void getIdsFromName(const std::string &name, int &GeoId, int &VtId)
|
||||
void getIdsFromName(const std::string &name, const Sketcher::SketchObject* Obj,
|
||||
int &GeoId, PointPos &PosId)
|
||||
{
|
||||
GeoId = Constraint::GeoUndef;
|
||||
VtId = -1;
|
||||
if (name.size() > 4 && name.substr(0,4) == "Edge")
|
||||
PosId = Sketcher::none;
|
||||
|
||||
if (name.size() > 4 && name.substr(0,4) == "Edge") {
|
||||
GeoId = std::atoi(name.substr(4,4000).c_str());
|
||||
}
|
||||
else if (name.size() == 9 && name.substr(0,9) == "RootPoint") {
|
||||
GeoId = -1;
|
||||
PosId = Sketcher::start;
|
||||
}
|
||||
else if (name.size() == 6 && name.substr(0,6) == "H_Axis")
|
||||
GeoId = -1;
|
||||
else if (name.size() == 6 && name.substr(0,6) == "V_Axis")
|
||||
GeoId = -2;
|
||||
else if (name.size() > 12 && name.substr(0,12) == "ExternalEdge")
|
||||
GeoId = -3 - std::atoi(name.substr(12,4000).c_str());
|
||||
else if (name.size() > 6 && name.substr(0,6) == "Vertex")
|
||||
VtId = std::atoi(name.substr(6,4000).c_str());
|
||||
else if (name.size() > 6 && name.substr(0,6) == "Vertex") {
|
||||
int VtId = std::atoi(name.substr(6,4000).c_str());
|
||||
Obj->getGeoVertexIndex(VtId,GeoId,PosId);
|
||||
}
|
||||
}
|
||||
|
||||
bool inline isVertex(int GeoId, PointPos PosId)
|
||||
{
|
||||
return (GeoId != Constraint::GeoUndef && PosId != Sketcher::none);
|
||||
}
|
||||
|
||||
bool inline isEdge(int GeoId, PointPos PosId)
|
||||
{
|
||||
return (GeoId != Constraint::GeoUndef && PosId == Sketcher::none);
|
||||
}
|
||||
|
||||
bool isSimpleVertex(const Sketcher::SketchObject* Obj, int GeoId, PointPos PosId)
|
||||
{
|
||||
if (PosId == Sketcher::start && (GeoId == -1 || GeoId == -2))
|
||||
return true;
|
||||
const Part::Geometry *geo = Obj->getGeometry(GeoId);
|
||||
if (geo->getTypeId() == Part::GeomPoint::getClassTypeId())
|
||||
return true;
|
||||
else if (PosId == Sketcher::mid &&
|
||||
(geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
|
||||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace SketcherGui {
|
||||
|
||||
|
@ -405,16 +438,12 @@ void CmdSketcherConstrainLock::activated(int iMsg)
|
|||
}
|
||||
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId=Sketcher::none;
|
||||
if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex") {
|
||||
int VtId = std::atoi(SubNames[0].substr(6,4000).c_str());
|
||||
Obj->getGeoVertexIndex(VtId,GeoId,PosId);
|
||||
}
|
||||
else if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
|
||||
GeoId = std::atoi(SubNames[0].substr(4,4000).c_str());
|
||||
else {
|
||||
Sketcher::PointPos PosId;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId, PosId);
|
||||
|
||||
if (isEdge(GeoId,PosId) || GeoId < 0) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly one entity from the sketch."));
|
||||
QObject::tr("Select one vertex from the sketch."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -481,34 +510,22 @@ void CmdSketcherConstrainCoincident::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int index1,index2;
|
||||
// get first vertex index
|
||||
if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
|
||||
index1 = std::atoi(SubNames[0].substr(6,4000).c_str());
|
||||
else {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly two vertexes from the sketch."));
|
||||
return;
|
||||
}
|
||||
int GeoId1, GeoId2;
|
||||
Sketcher::PointPos PosId1, PosId2;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
// get second vertex index
|
||||
if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
|
||||
index2 = std::atoi(SubNames[1].substr(6,4000).c_str());
|
||||
else {
|
||||
if (isEdge(GeoId1,PosId1) || isEdge(GeoId2,PosId2)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly two vertexes from the sketch."));
|
||||
return;
|
||||
}
|
||||
int GeoId1,GeoId2;
|
||||
Sketcher::PointPos Pt1,Pt2;
|
||||
Obj->getGeoVertexIndex(index1,GeoId1,Pt1);
|
||||
Obj->getGeoVertexIndex(index2,GeoId2,Pt2);
|
||||
|
||||
// undo command open
|
||||
openCommand("add coincident constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,Pt1,GeoId2,Pt2);
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2);
|
||||
|
||||
// finish the transaction and update
|
||||
commitCommand();
|
||||
|
@ -562,44 +579,41 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
|
||||
if (SubNames.size() >= 1) {
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
if (SubNames.size() == 2)
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
}
|
||||
int GeoId1, GeoId2=Constraint::GeoUndef;
|
||||
Sketcher::PointPos PosId1, PosId2=Sketcher::none;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
if (SubNames.size() == 2)
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
else if ((GeoId2 == -2 || GeoId2 == -1) && GeoId1 == Constraint::GeoUndef) {
|
||||
else if (isVertex(GeoId1,PosId1) && (GeoId2 == -2 || GeoId2 == -1)) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(VtId1,VtId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
|
||||
if ((GeoId1 == -2 || GeoId1 == -1 || VtId1 >= 0) && VtId2 >= 0) { // point to point distance
|
||||
Sketcher::PointPos PosId1,PosId2;
|
||||
if (GeoId1 == -2 || GeoId1 == -1)
|
||||
PosId1 = Sketcher::start;
|
||||
else
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
if ((isVertex(GeoId1,PosId1) || GeoId1 == -2 || GeoId1 == -1) &&
|
||||
isVertex(GeoId2,PosId2)) { // point to point distance
|
||||
|
||||
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
|
||||
Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
|
||||
Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
|
||||
|
||||
if (GeoId1 == -1) {
|
||||
if (GeoId1 == -1 && PosId1 == Sketcher::none) {
|
||||
PosId1 = Sketcher::start;
|
||||
openCommand("add distance from horizontal axis constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%d,%d,%f)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,pnt2.y);
|
||||
}
|
||||
else if (GeoId1 == -2) {
|
||||
else if (GeoId1 == -2 && PosId1 == Sketcher::none) {
|
||||
PosId1 = Sketcher::start;
|
||||
openCommand("add distance from vertical axis constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%d,%d,%d,%f)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,pnt2.x);
|
||||
}
|
||||
else {
|
||||
Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
|
||||
|
||||
openCommand("add point to point distance constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%d,%f)) ",
|
||||
|
@ -617,14 +631,12 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if ((VtId1 >= 0 && GeoId2 != Constraint::GeoUndef) ||
|
||||
(VtId2 >= 0 && GeoId1 != Constraint::GeoUndef)) { // point to line distance
|
||||
if (VtId2 >= 0 && GeoId1 != Constraint::GeoUndef) {
|
||||
std::swap(VtId1,VtId2);
|
||||
else if ((isVertex(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) ||
|
||||
(isEdge(GeoId1,PosId1) && isVertex(GeoId2,PosId2))) { // point to line distance
|
||||
if (isVertex(GeoId2,PosId2)) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
Sketcher::PointPos PosId1;
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
Base::Vector3d pnt = Obj->getPoint(GeoId1,PosId1);
|
||||
const Part::Geometry *geom = Obj->getGeometry(GeoId2);
|
||||
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
|
@ -652,10 +664,11 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (GeoId1 != Constraint::GeoUndef) { // line length
|
||||
else if (isEdge(GeoId1,PosId1)) { // line length
|
||||
if (GeoId1 < 0) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a length constraint on an external geometry!"));
|
||||
GeoId1 < 2 ? QObject::tr("Cannot add a length constraint on an external geometry!")
|
||||
: QObject::tr("Cannot add a length constraint on an axis!"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -732,29 +745,22 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
|
||||
if (SubNames.size() >= 1) {
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
if (SubNames.size() == 2)
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
}
|
||||
int GeoId1, GeoId2=Constraint::GeoUndef;
|
||||
Sketcher::PointPos PosId1, PosId2=Sketcher::none;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
if (SubNames.size() == 2)
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
|
||||
if ((VtId1 >= 0 && GeoId2 != Constraint::GeoUndef) ||
|
||||
(VtId2 >= 0 && GeoId1 != Constraint::GeoUndef)) {
|
||||
if (VtId2 >= 0 && GeoId1 != Constraint::GeoUndef) {
|
||||
std::swap(VtId1,VtId2);
|
||||
if ((isVertex(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) ||
|
||||
(isEdge(GeoId1,PosId1) && isVertex(GeoId2,PosId2))) {
|
||||
if (isVertex(GeoId2,PosId2)) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
|
||||
Sketcher::PointPos PosId1;
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
|
||||
const Part::Geometry *geom = Obj->getGeometry(GeoId2);
|
||||
|
||||
// Currently only accepts line segments and circles
|
||||
|
@ -821,32 +827,28 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
|
||||
if (SubNames.size() >= 1) {
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
if (GeoId1 == -1) // reject horizontal axis from selection
|
||||
GeoId1 = Constraint::GeoUndef;
|
||||
if (SubNames.size() == 2) {
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
if (GeoId2 == -1) // reject horizontal axis from selection
|
||||
GeoId2 = Constraint::GeoUndef;
|
||||
}
|
||||
}
|
||||
int GeoId1, GeoId2=Constraint::GeoUndef;
|
||||
Sketcher::PointPos PosId1, PosId2=Sketcher::none;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
if (SubNames.size() == 2)
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
else if (GeoId2 == -2 && GeoId1 == Constraint::GeoUndef) {
|
||||
else if (GeoId2 == -1 || GeoId2 == -2) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(VtId1,VtId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
|
||||
if ((GeoId1 == -2 || VtId1 >= 0) && VtId2 >= 0) { // point to point horizontal distance
|
||||
Sketcher::PointPos PosId1,PosId2;
|
||||
if (GeoId1 == -2)
|
||||
PosId1 = Sketcher::start;
|
||||
else
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
|
||||
if (GeoId1 == -1 && PosId1 == Sketcher::none) // reject horizontal axis from selection
|
||||
GeoId1 = Constraint::GeoUndef;
|
||||
else if (GeoId1 == -2 && PosId1 == Sketcher::none) {
|
||||
GeoId1 = -1;
|
||||
PosId1 = Sketcher::start;
|
||||
}
|
||||
|
||||
if (isVertex(GeoId1,PosId1) && isVertex(GeoId2,PosId2)) { // point to point horizontal distance
|
||||
|
||||
Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
|
||||
Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
|
||||
double ActLength = pnt2.x-pnt1.x;
|
||||
|
@ -867,12 +869,12 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if (GeoId1 != Constraint::GeoUndef &&
|
||||
GeoId2 == Constraint::GeoUndef && VtId2 < 0) { // horizontal length of a line
|
||||
else if (isEdge(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // horizontal length of a line
|
||||
|
||||
if (GeoId1 < 0) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a horizontal length constraint on an external geometry!"));
|
||||
GeoId1 < -2 ? QObject::tr("Cannot add a horizontal length constraint on an external geometry!")
|
||||
: QObject::tr("Cannot add a horizontal length constraint on an axis!"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -899,9 +901,15 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (VtId1 >= 0) { // point on fixed x-coordinate
|
||||
Sketcher::PointPos PosId1;
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
else if (isVertex(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // point on fixed x-coordinate
|
||||
|
||||
if (GeoId1 < 0) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
GeoId1 < -2 ? QObject::tr("Cannot add a fixed x-cootdinate constraint on an external geometry!")
|
||||
: QObject::tr("Cannot add a fixed x-cootdinate constraint on the root point!"));
|
||||
return;
|
||||
}
|
||||
|
||||
Base::Vector3d pnt = Obj->getPoint(GeoId1,PosId1);
|
||||
double ActX = pnt.x;
|
||||
|
||||
|
@ -971,32 +979,26 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1=Constraint::GeoUndef, VtId1=-1, GeoId2=Constraint::GeoUndef, VtId2=-1;
|
||||
if (SubNames.size() >= 1) {
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
if (GeoId1 == -2) // reject vertical axis from selection
|
||||
GeoId1 = Constraint::GeoUndef;
|
||||
if (SubNames.size() == 2) {
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
if (GeoId2 == -2) // reject vertical axis from selection
|
||||
GeoId2 = Constraint::GeoUndef;
|
||||
}
|
||||
}
|
||||
int GeoId1, GeoId2=Constraint::GeoUndef;
|
||||
Sketcher::PointPos PosId1, PosId2=Sketcher::none;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
if (SubNames.size() == 2)
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
else if (GeoId2 == -1 && GeoId1 == Constraint::GeoUndef) {
|
||||
else if (GeoId2 == -1 || GeoId2 == -2) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(VtId1,VtId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
|
||||
if ((GeoId1 == -1 || VtId1 >= 0) && VtId2 >= 0) { // point to point horizontal distance
|
||||
Sketcher::PointPos PosId1,PosId2;
|
||||
if (GeoId1 == -1)
|
||||
PosId1 = Sketcher::start;
|
||||
else
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
|
||||
if (GeoId1 == -2 && PosId1 == Sketcher::none) // reject vertical axis from selection
|
||||
GeoId1 = Constraint::GeoUndef;
|
||||
else if (GeoId1 == -1 && PosId1 == Sketcher::none)
|
||||
PosId1 = Sketcher::start;
|
||||
|
||||
if (isVertex(GeoId1,PosId1) && isVertex(GeoId2,PosId2)) { // point to point vertical distance
|
||||
|
||||
Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
|
||||
Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
|
||||
double ActLength = pnt2.y-pnt1.y;
|
||||
|
@ -1017,12 +1019,12 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if (GeoId1 != Constraint::GeoUndef &&
|
||||
GeoId2 == Constraint::GeoUndef && VtId2 < 0) { // vertical length of a line
|
||||
else if (isEdge(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // vertical length of a line
|
||||
|
||||
if (GeoId1 < 0) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a vertical length constraint on an external geometry!"));
|
||||
GeoId1 < -2 ? QObject::tr("Cannot add a vertical length constraint on an external geometry!")
|
||||
: QObject::tr("Cannot add a vertical length constraint on an axis!"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1049,9 +1051,15 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (VtId1 >= 0) { // point on fixed y-coordinate
|
||||
Sketcher::PointPos PosId1;
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
else if (isVertex(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // point on fixed y-coordinate
|
||||
|
||||
if (GeoId1 < 0) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
GeoId1 < -2 ? QObject::tr("Cannot add a fixed y-cootdinate constraint on an external geometry!")
|
||||
: QObject::tr("Cannot add a fixed y-cootdinate constraint on the root point!"));
|
||||
return;
|
||||
}
|
||||
|
||||
Base::Vector3d pnt = Obj->getPoint(GeoId1,PosId1);
|
||||
double ActY = pnt.y;
|
||||
|
||||
|
@ -1126,10 +1134,12 @@ void CmdSketcherConstrainParallel::activated(int iMsg)
|
|||
std::vector<int> ids;
|
||||
bool hasAlreadyExternal=false;
|
||||
for (std::vector<std::string>::const_iterator it=SubNames.begin();it!=SubNames.end();++it) {
|
||||
int GeoId, VtId;
|
||||
getIdsFromName(*it, GeoId, VtId);
|
||||
|
||||
if (GeoId == Constraint::GeoUndef) {
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
getIdsFromName(*it, Obj, GeoId, PosId);
|
||||
|
||||
if (!isEdge(GeoId,PosId)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select a valid line"));
|
||||
return;
|
||||
|
@ -1212,17 +1222,22 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1, VtId1, GeoId2, VtId2;
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
int GeoId1, GeoId2;
|
||||
Sketcher::PointPos PosId1, PosId2;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
Sketcher::PointPos PosId1,PosId2;
|
||||
if (VtId1 >= 0 && VtId2 >= 0) { // perpendicularity at common point
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
if (isVertex(GeoId1,PosId1) && isVertex(GeoId2,PosId2)) { // perpendicularity at common point
|
||||
|
||||
if (isSimpleVertex(Obj, GeoId1, PosId1) ||
|
||||
isSimpleVertex(Obj, GeoId2, PosId2)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a perpendicularity constraint at an unconnected point!"));
|
||||
return;
|
||||
}
|
||||
|
||||
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
|
||||
|
@ -1247,18 +1262,18 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if ((VtId1 >= 0 && GeoId2 != Constraint::GeoUndef) ||
|
||||
(VtId2 >= 0 && GeoId1 != Constraint::GeoUndef)) { // VtId1 is a connecting point
|
||||
if (VtId2 >= 0 && GeoId1 != Constraint::GeoUndef) {
|
||||
VtId1 = VtId2;
|
||||
VtId2 = -1;
|
||||
GeoId2 = GeoId1;
|
||||
GeoId1 = -1;
|
||||
else if ((isVertex(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) ||
|
||||
(isEdge(GeoId1,PosId1) && isVertex(GeoId2,PosId2))) { // connecting point
|
||||
if (isVertex(GeoId2,PosId2)) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
if (isSimpleVertex(Obj, GeoId1, PosId1)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a perpendicularity constraint at an unconnected point!"));
|
||||
return;
|
||||
}
|
||||
|
||||
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
|
||||
|
@ -1286,10 +1301,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if (GeoId1 != Constraint::GeoUndef && GeoId2 != Constraint::GeoUndef) { // simple perpendicularity between GeoId1 and GeoId2
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
else if (isEdge(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) { // simple perpendicularity between GeoId1 and GeoId2
|
||||
|
||||
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
|
||||
|
@ -1358,17 +1370,22 @@ void CmdSketcherConstrainTangent::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1, VtId1, GeoId2, VtId2;
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
int GeoId1, GeoId2;
|
||||
Sketcher::PointPos PosId1, PosId2;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
Sketcher::PointPos PosId1,PosId2;
|
||||
if (VtId1 >= 0 && VtId2 >= 0) { // tangency at common point
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
if (isVertex(GeoId1,PosId1) && isVertex(GeoId2,PosId2)) { // tangency at common point
|
||||
|
||||
if (isSimpleVertex(Obj, GeoId1, PosId1) ||
|
||||
isSimpleVertex(Obj, GeoId2, PosId2)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a tangency constraint at an unconnected point!"));
|
||||
return;
|
||||
}
|
||||
|
||||
openCommand("add tangent constraint");
|
||||
Gui::Command::doCommand(
|
||||
|
@ -1379,18 +1396,18 @@ void CmdSketcherConstrainTangent::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if ((VtId1 >= 0 && GeoId2 != Constraint::GeoUndef) ||
|
||||
(VtId2 >= 0 && GeoId1 != Constraint::GeoUndef)) { // VtId1 is a tangency point
|
||||
if (VtId2 >= 0 && GeoId1 != Constraint::GeoUndef) {
|
||||
VtId1 = VtId2;
|
||||
VtId2 = -1;
|
||||
GeoId2 = GeoId1;
|
||||
GeoId1 = -1;
|
||||
else if ((isVertex(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) ||
|
||||
(isEdge(GeoId1,PosId1) && isVertex(GeoId2,PosId2))) { // tangency point
|
||||
if (isVertex(GeoId2,PosId2)) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
if (isSimpleVertex(Obj, GeoId1, PosId1)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a tangency constraint at an unconnected point!"));
|
||||
return;
|
||||
}
|
||||
|
||||
openCommand("add tangent constraint");
|
||||
Gui::Command::doCommand(
|
||||
|
@ -1401,10 +1418,7 @@ void CmdSketcherConstrainTangent::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
else if (GeoId1 != Constraint::GeoUndef && GeoId2 != Constraint::GeoUndef) { // simple tangency between GeoId1 and GeoId2
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
else if (isEdge(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) { // simple tangency between GeoId1 and GeoId2
|
||||
|
||||
openCommand("add tangent constraint");
|
||||
Gui::Command::doCommand(
|
||||
|
@ -1545,19 +1559,21 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1, VtId1, GeoId2=Constraint::GeoUndef, VtId2=-1;
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
|
||||
int GeoId1, GeoId2=Constraint::GeoUndef;
|
||||
Sketcher::PointPos PosId1, PosId2=Sketcher::none;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
if (SubNames.size() == 2)
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
|
||||
if (checkBothExternal(GeoId1, GeoId2))
|
||||
return;
|
||||
else if (GeoId1 == Constraint::GeoUndef && GeoId2 != Constraint::GeoUndef) {
|
||||
else if (isVertex(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) {
|
||||
std::swap(GeoId1,GeoId2);
|
||||
std::swap(VtId1,VtId2);
|
||||
std::swap(PosId1,PosId2);
|
||||
}
|
||||
|
||||
if (GeoId2 != Constraint::GeoUndef) { // line to line angle
|
||||
if (isEdge(GeoId2,PosId2)) { // line to line angle
|
||||
|
||||
const Part::Geometry *geom1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geom2 = Obj->getGeometry(GeoId2);
|
||||
|
@ -1612,10 +1628,11 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
|
|||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
} else if (GeoId1 != Constraint::GeoUndef) { // line angle
|
||||
} else if (isEdge(GeoId1,PosId1)) { // line angle
|
||||
if (GeoId1 < 0) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add an angle constraint on an external geometry!"));
|
||||
GeoId1 < -2 ? QObject::tr("Cannot add an angle constraint on an external geometry!")
|
||||
: QObject::tr("Cannot add an angle constraint on an axis!"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1700,10 +1717,11 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
|
|||
|
||||
for (std::vector<std::string>::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
|
||||
|
||||
int GeoId, VtId;
|
||||
getIdsFromName(*it, GeoId, VtId);
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
getIdsFromName(*it, Obj, GeoId, PosId);
|
||||
|
||||
if (GeoId == Constraint::GeoUndef) {
|
||||
if (isVertex(GeoId,PosId)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select two or more compatible edges"));
|
||||
return;
|
||||
|
@ -1802,38 +1820,60 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg)
|
|||
return;
|
||||
}
|
||||
|
||||
int GeoId1, VtId1, GeoId2, VtId2, GeoId3, VtId3;
|
||||
getIdsFromName(SubNames[0], GeoId1, VtId1);
|
||||
getIdsFromName(SubNames[1], GeoId2, VtId2);
|
||||
getIdsFromName(SubNames[2], GeoId3, VtId3);
|
||||
int GeoId1, GeoId2, GeoId3;
|
||||
Sketcher::PointPos PosId1, PosId2, PosId3;
|
||||
getIdsFromName(SubNames[0], Obj, GeoId1, PosId1);
|
||||
getIdsFromName(SubNames[1], Obj, GeoId2, PosId2);
|
||||
getIdsFromName(SubNames[2], Obj, GeoId3, PosId3);
|
||||
|
||||
if (GeoId1 != Constraint::GeoUndef && GeoId3 == Constraint::GeoUndef) {
|
||||
if (isEdge(GeoId1,PosId1) && isVertex(GeoId3,PosId3)) {
|
||||
std::swap(GeoId1,GeoId3);
|
||||
std::swap(VtId1,VtId3);
|
||||
std::swap(PosId1,PosId3);
|
||||
}
|
||||
else if (GeoId2 != Constraint::GeoUndef && GeoId3 == Constraint::GeoUndef) {
|
||||
else if (isEdge(GeoId2,PosId2) && isVertex(GeoId3,PosId3)) {
|
||||
std::swap(GeoId2,GeoId3);
|
||||
std::swap(VtId2,VtId3);
|
||||
std::swap(PosId2,PosId3);
|
||||
}
|
||||
|
||||
if (VtId1 >= 0 && VtId2 >= 0 && GeoId3 != Constraint::GeoUndef) {
|
||||
Sketcher::PointPos PosId1,PosId2;
|
||||
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
|
||||
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
|
||||
if ((GeoId1 < 0 && GeoId2 < 0 && GeoId3 < 0)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a constraint between external geometries!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((GeoId1 < 0 && GeoId2 < 0) || (GeoId1 < 0 && GeoId3 < 0) || (GeoId2 < 0 && GeoId3 < 0)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a constraint between external geometries!"));
|
||||
return;
|
||||
if (isVertex(GeoId1,PosId1) &&
|
||||
isVertex(GeoId2,PosId2)) {
|
||||
|
||||
if (isEdge(GeoId3,PosId3)) {
|
||||
const Part::Geometry *geom = Obj->getGeometry(GeoId3);
|
||||
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (GeoId1 == GeoId2 && GeoId2 == GeoId3) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a symmetry constraint between a line and its end points!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// undo command open
|
||||
openCommand("add symmetric constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Symmetric',%d,%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3);
|
||||
|
||||
// finish the transaction and update
|
||||
commitCommand();
|
||||
updateActive();
|
||||
|
||||
// clear the selection (convenience)
|
||||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const Part::Geometry *geom = Obj->getGeometry(GeoId3);
|
||||
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
else if (isVertex(GeoId3,PosId3)) {
|
||||
// undo command open
|
||||
openCommand("add symmetric constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Symmetric',%d,%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3);
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Symmetric',%d,%d,%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3,PosId3);
|
||||
|
||||
// finish the transaction and update
|
||||
commitCommand();
|
||||
|
|
|
@ -1444,6 +1444,7 @@ public:
|
|||
setPositionText(onSketchPos);
|
||||
if (seekAutoConstraint(sugConstr, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr);
|
||||
return;
|
||||
}
|
||||
applyCursor();
|
||||
}
|
||||
|
|
|
@ -141,31 +141,42 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
|
|||
// Get Preselection
|
||||
int preSelPnt = sketchgui->getPreselectPoint();
|
||||
int preSelCrv = sketchgui->getPreselectCurve();
|
||||
int preSelCrs = sketchgui->getPreselectCross();
|
||||
int GeoId = Constraint::GeoUndef;
|
||||
Sketcher::PointPos PosId = Sketcher::none;
|
||||
if (preSelPnt != -1)
|
||||
sketchgui->getSketchObject()->getGeoVertexIndex(preSelPnt, GeoId, PosId);
|
||||
else if (preSelCrv != -1)
|
||||
GeoId = preSelCrv;
|
||||
else if (preSelCrs == 0) { // root point
|
||||
GeoId = -1;
|
||||
PosId = Sketcher::start;
|
||||
}
|
||||
else if (preSelCrs == 1) // x axis
|
||||
GeoId = -1;
|
||||
else if (preSelCrs == 2) // y axis
|
||||
GeoId = -2;
|
||||
|
||||
// Currently only considers objects in current Sketcher
|
||||
AutoConstraint constr;
|
||||
constr.Type = Sketcher::None;
|
||||
constr.GeoId = GeoId;
|
||||
constr.PosId = PosId;
|
||||
if (type == AutoConstraint::VERTEX && preSelPnt != -1)
|
||||
constr.Type = Sketcher::Coincident;
|
||||
else if (type == AutoConstraint::CURVE && preSelPnt != -1)
|
||||
constr.Type = Sketcher::PointOnObject;
|
||||
else if (type == AutoConstraint::VERTEX && preSelCrv != -1)
|
||||
constr.Type = Sketcher::PointOnObject;
|
||||
else if (type == AutoConstraint::CURVE && preSelCrv != -1)
|
||||
constr.Type = Sketcher::Tangent;
|
||||
if (GeoId != Constraint::GeoUndef) {
|
||||
// Currently only considers objects in current Sketcher
|
||||
AutoConstraint constr;
|
||||
constr.Type = Sketcher::None;
|
||||
constr.GeoId = GeoId;
|
||||
constr.PosId = PosId;
|
||||
if (type == AutoConstraint::VERTEX && PosId != Sketcher::none)
|
||||
constr.Type = Sketcher::Coincident;
|
||||
else if (type == AutoConstraint::CURVE && PosId != Sketcher::none)
|
||||
constr.Type = Sketcher::PointOnObject;
|
||||
else if (type == AutoConstraint::VERTEX && PosId == Sketcher::none)
|
||||
constr.Type = Sketcher::PointOnObject;
|
||||
else if (type == AutoConstraint::CURVE && PosId == Sketcher::none)
|
||||
constr.Type = Sketcher::Tangent;
|
||||
|
||||
if (constr.Type != Sketcher::None)
|
||||
suggestedConstraints.push_back(constr);
|
||||
if (constr.Type != Sketcher::None)
|
||||
suggestedConstraints.push_back(constr);
|
||||
}
|
||||
|
||||
if (Dir.Length() < 1)
|
||||
if (Dir.Length() < 1e-8)
|
||||
// Direction not set so return;
|
||||
return suggestedConstraints.size();
|
||||
|
||||
|
@ -175,6 +186,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
|
|||
const double angleDev = 2;
|
||||
const double angleDevRad = angleDev * M_PI / 180.;
|
||||
|
||||
AutoConstraint constr;
|
||||
constr.Type = Sketcher::None;
|
||||
constr.GeoId = Constraint::GeoUndef;
|
||||
constr.PosId = Sketcher::none;
|
||||
|
|
|
@ -107,8 +107,8 @@ SbColor ViewProviderSketch::VertexColor (1.0f,0.149f,0.0f); // #FF26
|
|||
SbColor ViewProviderSketch::CurveColor (1.0f,1.0f,1.0f); // #FFFFFF -> (255,255,255)
|
||||
SbColor ViewProviderSketch::CurveDraftColor (0.0f,0.0f,0.86f); // #0000DC -> ( 0, 0,220)
|
||||
SbColor ViewProviderSketch::CurveExternalColor (0.8f,0.2f,0.6f); // #CC3399 -> (204, 51,153)
|
||||
SbColor ViewProviderSketch::CrossColorV (0.8f,0.4f,0.4f); // #CC6666 -> (204,102,102)
|
||||
SbColor ViewProviderSketch::CrossColorH (0.4f,0.8f,0.4f); // #66CC66 -> (102,204,102)
|
||||
SbColor ViewProviderSketch::CrossColorH (0.8f,0.4f,0.4f); // #CC6666 -> (204,102,102)
|
||||
SbColor ViewProviderSketch::CrossColorV (0.4f,0.8f,0.4f); // #66CC66 -> (102,204,102)
|
||||
SbColor ViewProviderSketch::FullyConstrainedColor (0.0f,1.0f,0.0f); // #00FF00 -> ( 0,255, 0)
|
||||
SbColor ViewProviderSketch::ConstrDimColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0)
|
||||
SbColor ViewProviderSketch::ConstrIcoColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0)
|
||||
|
@ -1294,6 +1294,9 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI
|
|||
if (point_detail && point_detail->getTypeId() == SoPointDetail::getClassTypeId()) {
|
||||
// get the index
|
||||
PtIndex = static_cast<const SoPointDetail *>(point_detail)->getCoordinateIndex();
|
||||
PtIndex -= 1; // shift corresponding to RootPoint
|
||||
if (PtIndex == -1)
|
||||
CrossIndex = 0; // RootPoint was hit
|
||||
}
|
||||
} else {
|
||||
// checking for a hit in the curves
|
||||
|
@ -1382,7 +1385,10 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI
|
|||
,Point->getPoint()[2]);
|
||||
edit->blockedPreselection = !accepted;
|
||||
if (accepted) {
|
||||
resetPreselectPoint();
|
||||
if (CrossIndex == 0)
|
||||
setPreselectPoint(-1);
|
||||
else
|
||||
resetPreselectPoint();
|
||||
edit->PreselectCurve = -1;
|
||||
edit->PreselectCross = CrossIndex;
|
||||
edit->PreselectConstraint = -1;
|
||||
|
@ -1661,16 +1667,21 @@ void ViewProviderSketch::updateColor(void)
|
|||
SbColor *crosscolor = edit->RootCrossMaterials->diffuseColor.startEditing();
|
||||
|
||||
// colors of the point set
|
||||
for (int i=0; i < PtNum; i++) {
|
||||
if (edit->SelPointSet.find(i) != edit->SelPointSet.end())
|
||||
pcolor[i] = SelectColor;
|
||||
else if (edit->PreselectPoint == i)
|
||||
pcolor[i] = PreselectColor;
|
||||
else if (edit->FullyConstrained)
|
||||
if (edit->FullyConstrained)
|
||||
for (int i=0; i < PtNum; i++)
|
||||
pcolor[i] = FullyConstrainedColor;
|
||||
else
|
||||
else
|
||||
for (int i=0; i < PtNum; i++)
|
||||
pcolor[i] = VertexColor;
|
||||
}
|
||||
|
||||
if (edit->PreselectCross == 0)
|
||||
pcolor[0] = PreselectColor;
|
||||
else if (edit->PreselectPoint != -1)
|
||||
pcolor[edit->PreselectPoint + 1] = PreselectColor;
|
||||
|
||||
for (std::set<int>::iterator it=edit->SelPointSet.begin();
|
||||
it != edit->SelPointSet.end(); it++)
|
||||
pcolor[*it] = SelectColor;
|
||||
|
||||
// colors of the curves
|
||||
int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1;
|
||||
|
@ -1933,6 +1944,10 @@ void ViewProviderSketch::draw(bool temp)
|
|||
|
||||
edit->CurvIdToGeoId.clear();
|
||||
int GeoId = 0;
|
||||
|
||||
// RootPoint
|
||||
Points.push_back(Base::Vector3d(0.,0.,0.));
|
||||
|
||||
for (std::vector<Part::Geometry *>::const_iterator it = geomlist->begin(); it != geomlist->end()-2; ++it, GeoId++) {
|
||||
if (GeoId >= intGeoCount)
|
||||
GeoId = -extGeoCount;
|
||||
|
@ -3182,17 +3197,23 @@ void ViewProviderSketch::resetPositionText(void)
|
|||
void ViewProviderSketch::setPreselectPoint(int PreselectPoint)
|
||||
{
|
||||
if (edit) {
|
||||
int oldPtId = -1;
|
||||
if (edit->PreselectPoint != -1)
|
||||
oldPtId = edit->PreselectPoint + 1;
|
||||
else if (edit->PreselectCross == 0)
|
||||
oldPtId = 0;
|
||||
int newPtId = PreselectPoint + 1;
|
||||
SbVec3f *pverts = edit->PointsCoordinate->point.startEditing();
|
||||
float x,y,z;
|
||||
if (edit->PreselectPoint != -1 &&
|
||||
edit->SelPointSet.find(edit->PreselectPoint) == edit->SelPointSet.end()) {
|
||||
if (oldPtId != -1 &&
|
||||
edit->SelPointSet.find(oldPtId) == edit->SelPointSet.end()) {
|
||||
// send to background
|
||||
pverts[edit->PreselectPoint].getValue(x,y,z);
|
||||
pverts[edit->PreselectPoint].setValue(x,y,zPoints);
|
||||
pverts[oldPtId].getValue(x,y,z);
|
||||
pverts[oldPtId].setValue(x,y,zPoints);
|
||||
}
|
||||
// bring to foreground
|
||||
pverts[PreselectPoint].getValue(x,y,z);
|
||||
pverts[PreselectPoint].setValue(x,y,zHighlight);
|
||||
pverts[newPtId].getValue(x,y,z);
|
||||
pverts[newPtId].setValue(x,y,zHighlight);
|
||||
edit->PreselectPoint = PreselectPoint;
|
||||
edit->PointsCoordinate->point.finishEditing();
|
||||
}
|
||||
|
@ -3201,13 +3222,18 @@ void ViewProviderSketch::setPreselectPoint(int PreselectPoint)
|
|||
void ViewProviderSketch::resetPreselectPoint(void)
|
||||
{
|
||||
if (edit) {
|
||||
if (edit->PreselectPoint != -1 &&
|
||||
edit->SelPointSet.find(edit->PreselectPoint) == edit->SelPointSet.end()) {
|
||||
int oldPtId = -1;
|
||||
if (edit->PreselectPoint != -1)
|
||||
oldPtId = edit->PreselectPoint + 1;
|
||||
else if (edit->PreselectCross == 0)
|
||||
oldPtId = 0;
|
||||
if (oldPtId != -1 &&
|
||||
edit->SelPointSet.find(oldPtId) == edit->SelPointSet.end()) {
|
||||
// send to background
|
||||
SbVec3f *pverts = edit->PointsCoordinate->point.startEditing();
|
||||
float x,y,z;
|
||||
pverts[edit->PreselectPoint].getValue(x,y,z);
|
||||
pverts[edit->PreselectPoint].setValue(x,y,zPoints);
|
||||
pverts[oldPtId].getValue(x,y,z);
|
||||
pverts[oldPtId].setValue(x,y,zPoints);
|
||||
edit->PointsCoordinate->point.finishEditing();
|
||||
}
|
||||
edit->PreselectPoint = -1;
|
||||
|
@ -3217,12 +3243,13 @@ void ViewProviderSketch::resetPreselectPoint(void)
|
|||
void ViewProviderSketch::addSelectPoint(int SelectPoint)
|
||||
{
|
||||
if (edit) {
|
||||
int PtId = SelectPoint + 1;
|
||||
SbVec3f *pverts = edit->PointsCoordinate->point.startEditing();
|
||||
// bring to foreground
|
||||
float x,y,z;
|
||||
pverts[SelectPoint].getValue(x,y,z);
|
||||
pverts[SelectPoint].setValue(x,y,zHighlight);
|
||||
edit->SelPointSet.insert(SelectPoint);
|
||||
pverts[PtId].getValue(x,y,z);
|
||||
pverts[PtId].setValue(x,y,zHighlight);
|
||||
edit->SelPointSet.insert(PtId);
|
||||
edit->PointsCoordinate->point.finishEditing();
|
||||
}
|
||||
}
|
||||
|
@ -3230,12 +3257,13 @@ void ViewProviderSketch::addSelectPoint(int SelectPoint)
|
|||
void ViewProviderSketch::removeSelectPoint(int SelectPoint)
|
||||
{
|
||||
if (edit) {
|
||||
int PtId = SelectPoint + 1;
|
||||
SbVec3f *pverts = edit->PointsCoordinate->point.startEditing();
|
||||
// send to background
|
||||
float x,y,z;
|
||||
pverts[SelectPoint].getValue(x,y,z);
|
||||
pverts[SelectPoint].setValue(x,y,zPoints);
|
||||
edit->SelPointSet.erase(SelectPoint);
|
||||
pverts[PtId].getValue(x,y,z);
|
||||
pverts[PtId].setValue(x,y,zPoints);
|
||||
edit->SelPointSet.erase(PtId);
|
||||
edit->PointsCoordinate->point.finishEditing();
|
||||
}
|
||||
}
|
||||
|
@ -3270,6 +3298,13 @@ int ViewProviderSketch::getPreselectCurve(void) const
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ViewProviderSketch::getPreselectCross(void) const
|
||||
{
|
||||
if (edit)
|
||||
return edit->PreselectCross;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ViewProviderSketch::getPreselectConstraint(void) const
|
||||
{
|
||||
if (edit)
|
||||
|
|
|
@ -164,6 +164,7 @@ public:
|
|||
float getScaleFactor();
|
||||
int getPreselectPoint(void) const;
|
||||
int getPreselectCurve(void) const;
|
||||
int getPreselectCross(void) const;
|
||||
int getPreselectConstraint(void) const;
|
||||
//@}
|
||||
|
||||
|
|
|
@ -66,29 +66,33 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
<< "Sketcher_ToggleConstruction"
|
||||
/*<< "Sketcher_CreateText"*/
|
||||
/*<< "Sketcher_CreateDraftLine"*/;
|
||||
|
||||
Gui::MenuItem* cons = new Gui::MenuItem();
|
||||
cons->setCommand("Sketcher constraints");
|
||||
*cons << "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainCoincident"
|
||||
*cons << "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainAngle"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric";
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainAngle";
|
||||
|
||||
*sketch
|
||||
<< "Sketcher_NewSketch"
|
||||
<< "Sketcher_LeaveSketch"
|
||||
|
@ -96,7 +100,6 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
|||
<< "Sketcher_MapSketch"
|
||||
<< geom
|
||||
<< cons
|
||||
<< "Separator"
|
||||
;
|
||||
|
||||
return root;
|
||||
|
@ -110,14 +113,15 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
part->setCommand("Sketcher");
|
||||
*part << "Sketcher_NewSketch"<< "Sketcher_LeaveSketch";
|
||||
|
||||
part = new Gui::ToolBarItem(root);
|
||||
part->setCommand("Sketcher geometries");
|
||||
*part << "Sketcher_CreatePoint"
|
||||
Gui::ToolBarItem* geom = new Gui::ToolBarItem(root);
|
||||
geom->setCommand("Sketcher geometries");
|
||||
*geom << "Sketcher_CreatePoint"
|
||||
<< "Sketcher_CreateArc"
|
||||
<< "Sketcher_CreateCircle"
|
||||
<< "Sketcher_CreateLine"
|
||||
<< "Sketcher_CreatePolyline"
|
||||
<< "Sketcher_CreateRectangle"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_External"
|
||||
|
@ -125,23 +129,24 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
/*<< "Sketcher_CreateText"*/
|
||||
/*<< "Sketcher_CreateDraftLine"*/;
|
||||
|
||||
part = new Gui::ToolBarItem(root);
|
||||
part->setCommand("Sketcher constraints");
|
||||
*part << "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainCoincident"
|
||||
Gui::ToolBarItem* cons = new Gui::ToolBarItem(root);
|
||||
cons->setCommand("Sketcher constraints");
|
||||
*cons << "Sketcher_ConstrainCoincident"
|
||||
<< "Sketcher_ConstrainPointOnObject"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainVertical"
|
||||
<< "Sketcher_ConstrainHorizontal"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainParallel"
|
||||
<< "Sketcher_ConstrainPerpendicular"
|
||||
<< "Sketcher_ConstrainAngle"
|
||||
<< "Sketcher_ConstrainTangent"
|
||||
<< "Sketcher_ConstrainEqual"
|
||||
<< "Sketcher_ConstrainSymmetric";
|
||||
<< "Sketcher_ConstrainSymmetric"
|
||||
<< "Separator"
|
||||
<< "Sketcher_ConstrainLock"
|
||||
<< "Sketcher_ConstrainDistanceX"
|
||||
<< "Sketcher_ConstrainDistanceY"
|
||||
<< "Sketcher_ConstrainDistance"
|
||||
<< "Sketcher_ConstrainRadius"
|
||||
<< "Sketcher_ConstrainAngle";
|
||||
return root;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user