diff --git a/src/App/Property.cpp b/src/App/Property.cpp
index 35590a20a66e..a53e4c95c0c2 100644
--- a/src/App/Property.cpp
+++ b/src/App/Property.cpp
@@ -32,6 +32,7 @@
#include "ObjectIdentifier.h"
#include "PropertyContainer.h"
#include
+#include "Application.h"
using namespace App;
@@ -110,6 +111,14 @@ void Property::touch()
StatusBits.set(0);
}
+void Property::setReadOnly(bool readOnly)
+{
+ unsigned long status = this->getStatus();
+ this->setStatus(App::Property::ReadOnly, readOnly);
+ if (status != this->getStatus())
+ App::GetApplication().signalChangePropertyEditor(*this);
+}
+
void Property::hasSetValue(void)
{
if (father)
diff --git a/src/App/Property.h b/src/App/Property.h
index 79a1e21f7da0..43a1bbe912b6 100644
--- a/src/App/Property.h
+++ b/src/App/Property.h
@@ -27,11 +27,11 @@
// Std. configurations
#include
-#ifndef BOOST_105400
-#include
-#else
-#include
-#endif
+#ifndef BOOST_105400
+#include
+#else
+#include
+#endif
#include
#include
@@ -138,6 +138,11 @@ class AppExport Property : public Base::Persistence
inline void setStatus(Status pos, bool on) {
StatusBits.set(static_cast(pos), on);
}
+ ///Sets property editable/grayed out in property editor
+ void setReadOnly(bool readOnly);
+ inline bool isReadOnly() const {
+ return testStatus(App::Property::ReadOnly);
+ }
//@}
/// Returns a new copy of the property (mainly for Undo/Redo and transactions)
@@ -248,4 +253,4 @@ template class AtomicPropertyChangeInterface {
} // namespace App
-#endif // APP_PROPERTY_H
+#endif // APP_PROPERTY_H
diff --git a/src/Mod/Part/App/AttachableObject.cpp b/src/Mod/Part/App/AttachableObject.cpp
index 860a19f9406f..972915507a45 100644
--- a/src/Mod/Part/App/AttachableObject.cpp
+++ b/src/Mod/Part/App/AttachableObject.cpp
@@ -140,16 +140,6 @@ App::DocumentObjectExecReturn *AttachableObject::execute()
return Part::Feature::execute();
}
-namespace Attacher {
- void setReadonlyness(App::Property &prop, bool on)
- {
- unsigned long status = prop.getStatus();
- prop.setStatus(App::Property::ReadOnly, on);
- if (status != prop.getStatus())
- App::GetApplication().signalChangePropertyEditor(prop);
- }
-}
-
void AttachableObject::onChanged(const App::Property* prop)
{
if(! this->isRestoring()){
@@ -172,8 +162,8 @@ void AttachableObject::onChanged(const App::Property* prop)
}
eMapMode mmode = eMapMode(this->MapMode.getValue());
- setReadonlyness(this->superPlacement, !bAttached);
- setReadonlyness(this->Placement, bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached.
+ this->superPlacement.setReadOnly(!bAttached);
+ this->Placement.setReadOnly(bAttached && mmode != mmTranslate); //for mmTranslate, orientation should remain editable even when attached.
}
}
diff --git a/src/Mod/Part/App/FeatureRevolution.cpp b/src/Mod/Part/App/FeatureRevolution.cpp
index cd2250d17da6..66408b10dc8e 100644
--- a/src/Mod/Part/App/FeatureRevolution.cpp
+++ b/src/Mod/Part/App/FeatureRevolution.cpp
@@ -24,11 +24,17 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include
+# include
+# include
+# include
+# include
#endif
#include "FeatureRevolution.h"
#include
+#include
+#include
using namespace Part;
@@ -38,13 +44,14 @@ PROPERTY_SOURCE(Part::Revolution, Part::Feature)
Revolution::Revolution()
{
- //*** why not ADD_PROPERTY_TYPE??
- ADD_PROPERTY(Source,(0));
- ADD_PROPERTY(Base,(Base::Vector3d(0.0,0.0,0.0)));
- ADD_PROPERTY(Axis,(Base::Vector3d(0.0,0.0,1.0)));
- ADD_PROPERTY(Angle,(360.0));
- ADD_PROPERTY_TYPE(Solid,(false),"Base",App::Prop_None,"Make revolution a solid if possible");
+ ADD_PROPERTY_TYPE(Source,(0), "Revolve", App::Prop_None, "Shape to revolve");
+ ADD_PROPERTY_TYPE(Base,(Base::Vector3d(0.0,0.0,0.0)), "Revolve", App::Prop_None, "Base point of revolution axis");
+ ADD_PROPERTY_TYPE(Axis,(Base::Vector3d(0.0,0.0,1.0)), "Revolve", App::Prop_None, "Direction of revolution axis");
+ ADD_PROPERTY_TYPE(AxisLink,(0),"Revolve",App::Prop_None,"Link to edge to use as revolution axis.");
+ ADD_PROPERTY_TYPE(Angle,(360.0), "Revolve", App::Prop_None, "Angle span of revolution. If angle is zero, and an arc is used for axis link, angle span of arc will be used.");
Angle.setConstraints(&angleRangeU);
+ ADD_PROPERTY_TYPE(Symmetric,(false),"Revolve",App::Prop_None,"Extend revolution symmetrically from the profile.");
+ ADD_PROPERTY_TYPE(Solid,(false),"Revolve",App::Prop_None,"Make revolution a solid if possible");
}
short Revolution::mustExecute() const
@@ -53,11 +60,67 @@ short Revolution::mustExecute() const
Axis.isTouched() ||
Angle.isTouched() ||
Source.isTouched() ||
- Solid.isTouched())
+ Solid.isTouched() ||
+ AxisLink.isTouched() ||
+ Symmetric.isTouched())
return 1;
return 0;
}
+void Revolution::onChanged(const App::Property* prop)
+{
+ if(! this->isRestoring()){
+ if(prop == &AxisLink){
+ Base.setReadOnly(AxisLink.getValue() != nullptr);
+ Axis.setReadOnly(AxisLink.getValue() != nullptr);
+ }
+ }
+ Part::Feature::onChanged(prop);
+}
+
+bool Revolution::fetchAxisLink(const App::PropertyLinkSub &axisLink,
+ Base::Vector3d& center,
+ Base::Vector3d& dir,
+ double& angle)
+{
+ if (!axisLink.getValue())
+ return false;
+
+ if (!axisLink.getValue()->isDerivedFrom(Part::Feature::getClassTypeId()))
+ throw Base::TypeError("AxisLink has no OCC shape");
+
+ Part::Feature* linked = static_cast(axisLink.getValue());
+
+ TopoDS_Shape axEdge;
+ if (axisLink.getSubValues().size() > 0 && axisLink.getSubValues()[0].length() > 0){
+ axEdge = linked->Shape.getShape().getSubShape(axisLink.getSubValues()[0].c_str());
+ } else {
+ axEdge = linked->Shape.getValue();
+ }
+
+ if (axEdge.IsNull())
+ throw Base::ValueError("AxisLink shape is null");
+ if (axEdge.ShapeType() != TopAbs_EDGE)
+ throw Base::TypeError("AxisLink shape is not an edge");
+
+ BRepAdaptor_Curve crv(TopoDS::Edge(axEdge));
+ gp_Pnt base;
+ gp_Dir occdir;
+ if (crv.GetType() == GeomAbs_Line){
+ base = crv.Value(crv.FirstParameter());
+ occdir = crv.Line().Direction();
+ } else if (crv.GetType() == GeomAbs_Circle) {
+ base = crv.Circle().Axis().Location();
+ occdir = crv.Circle().Axis().Direction();
+ angle = crv.LastParameter() - crv.FirstParameter();
+ } else {
+ throw Base::TypeError("AxisLink edge is neither line nor arc of circle.");
+ }
+ center.Set(base.X(), base.Y(),base.Z());
+ dir.Set(occdir.X(), occdir.Y(), occdir.Z());
+ return true;
+}
+
App::DocumentObjectExecReturn *Revolution::execute(void)
{
App::DocumentObject* link = Source.getValue();
@@ -67,18 +130,40 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
return new App::DocumentObjectExecReturn("Linked object is not a Part object");
Part::Feature *base = static_cast(Source.getValue());
- Base::Vector3d b = Base.getValue();
- Base::Vector3d v = Axis.getValue();
- gp_Pnt pnt(b.x,b.y,b.z);
- gp_Dir dir(v.x,v.y,v.z);
- Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False;
-
try {
- // Now, let's get the TopoDS_Shape
- //TopoDS_Shape revolve = base->Shape.getShape().revolve(gp_Ax1(pnt, dir),
- // Angle.getValue()/180.0f*M_PI);
- TopoDS_Shape revolve = base->Shape.getShape().revolve(gp_Ax1(pnt, dir),
- Angle.getValue()/180.0f*M_PI,isSolid);
+ //read out axis link
+ double angle_edge = 0;
+ Base::Vector3d b = Base.getValue();
+ Base::Vector3d v = Axis.getValue();
+ bool linkFetched = this->fetchAxisLink(this->AxisLink, b, v, angle_edge);
+ if (linkFetched){
+ this->Base.setValue(b);
+ this->Axis.setValue(v);
+ }
+
+ gp_Pnt pnt(b.x,b.y,b.z);
+ gp_Dir dir(v.x,v.y,v.z);
+ gp_Ax1 revAx(pnt, dir);
+
+ //read out revolution angle
+ double angle = Angle.getValue()/180.0f*M_PI;
+ if (fabs(angle) < Precision::Angular())
+ angle = angle_edge;
+
+ //apply "midplane" symmetry
+ TopoShape sourceShape = base->Shape.getShape();
+ if (Symmetric.getValue()) {
+ //rotate source shape backwards by half angle, to make resulting revolution symmetric to the profile
+ gp_Trsf mov;
+ mov.SetRotation(revAx, angle * (-0.5));
+ TopLoc_Location loc(mov);
+ sourceShape.setShape(sourceShape.getShape().Moved(loc));
+ }
+
+ //do it!
+ Standard_Boolean makeSolid = Solid.getValue() ? Standard_True : Standard_False;
+ TopoDS_Shape revolve = sourceShape.revolve(revAx, angle, makeSolid);
+
if (revolve.IsNull())
return new App::DocumentObjectExecReturn("Resulting shape is null");
this->Shape.setValue(revolve);
diff --git a/src/Mod/Part/App/FeatureRevolution.h b/src/Mod/Part/App/FeatureRevolution.h
index 545420c984e5..4fa6d60558dd 100644
--- a/src/Mod/Part/App/FeatureRevolution.h
+++ b/src/Mod/Part/App/FeatureRevolution.h
@@ -26,11 +26,12 @@
#include
#include "PartFeature.h"
+#include
namespace Part
{
-class Revolution : public Part::Feature
+class PartExport Revolution : public Part::Feature
{
PROPERTY_HEADER(Part::Revolution);
@@ -40,7 +41,9 @@ class Revolution : public Part::Feature
App::PropertyLink Source;
App::PropertyVector Base;
App::PropertyVector Axis;
+ App::PropertyLinkSub AxisLink;
App::PropertyFloatConstraint Angle;
+ App::PropertyBool Symmetric; //like "Midplane" in PartDesign
App::PropertyBool Solid;
/** @name methods override feature */
@@ -48,12 +51,32 @@ class Revolution : public Part::Feature
/// recalculate the feature
App::DocumentObjectExecReturn *execute(void);
short mustExecute() const;
+
+ void onChanged(const App::Property* prop) override;
+
/// returns the type name of the view provider
const char* getViewProviderName(void) const {
return "PartGui::ViewProviderRevolution";
}
//@}
+ /**
+ * @brief fetchAxisLink: read AxisLink to obtain the axis parameters and
+ * angle span. Note: this routine is re-used in Revolve dialog, hence it
+ * is static.
+ * @param axisLink (input): the link
+ * @param center (output): base point of axis
+ * @param dir (output): direction of axis
+ * @param angle (output): if edge is an arc of circle, this argument is
+ * used to return the angle span of the arc.
+ * @return true if link was fetched. false if link was empty. Throws if the
+ * link is wrong.
+ */
+ static bool fetchAxisLink(const App::PropertyLinkSub& axisLink,
+ Base::Vector3d ¢er,
+ Base::Vector3d &dir,
+ double &angle);
+
private:
static App::PropertyFloatConstraint::Constraints angleRangeU;
};
diff --git a/src/Mod/Part/Gui/DlgRevolution.cpp b/src/Mod/Part/Gui/DlgRevolution.cpp
index 05f7957439b4..4171f39e5148 100644
--- a/src/Mod/Part/Gui/DlgRevolution.cpp
+++ b/src/Mod/Part/Gui/DlgRevolution.cpp
@@ -32,6 +32,7 @@
# include
# include
# include
+# include
#endif
#include "ui_DlgRevolution.h"
@@ -48,6 +49,7 @@
#include
#include
#include
+#include
#include
#include
@@ -58,8 +60,6 @@ using namespace PartGui;
class DlgRevolution::EdgeSelection : public Gui::SelectionFilterGate
{
public:
- gp_Pnt loc;
- gp_Dir dir;
bool canSelect;
EdgeSelection()
@@ -82,10 +82,7 @@ class DlgRevolution::EdgeSelection : public Gui::SelectionFilterGate
if (!sub.IsNull() && sub.ShapeType() == TopAbs_EDGE) {
const TopoDS_Edge& edge = TopoDS::Edge(sub);
BRepAdaptor_Curve adapt(edge);
- if (adapt.GetType() == GeomAbs_Line) {
- gp_Lin line = adapt.Line();
- this->loc = line.Location();
- this->dir = line.Direction();
+ if (adapt.GetType() == GeomAbs_Line || adapt.GetType() == GeomAbs_Circle) {
this->canSelect = true;
return true;
}
@@ -99,20 +96,36 @@ class DlgRevolution::EdgeSelection : public Gui::SelectionFilterGate
};
DlgRevolution::DlgRevolution(QWidget* parent, Qt::WindowFlags fl)
- : Gui::LocationDialog(parent, fl), filter(0)
+ : QDialog(parent, fl), filter(0)
{
- ui = new Ui_RevolutionComp(this);
+ ui = new Ui_DlgRevolution();
+
+ ui->setupUi(this);
+
ui->xPos->setRange(-DBL_MAX,DBL_MAX);
ui->yPos->setRange(-DBL_MAX,DBL_MAX);
ui->zPos->setRange(-DBL_MAX,DBL_MAX);
ui->xPos->setUnit(Base::Unit::Length);
ui->yPos->setUnit(Base::Unit::Length);
ui->zPos->setUnit(Base::Unit::Length);
+
+ ui->xDir->setRange(-DBL_MAX,DBL_MAX);
+ ui->yDir->setRange(-DBL_MAX,DBL_MAX);
+ ui->zDir->setRange(-DBL_MAX,DBL_MAX);
+ ui->xDir->setUnit(Base::Unit());
+ ui->yDir->setUnit(Base::Unit());
+ ui->zDir->setUnit(Base::Unit());
+ ui->zDir->setValue(1.0);
+
ui->angle->setUnit(Base::Unit::Angle);
+ ui->angle->setValue(360.0);
findShapes();
Gui::ItemViewSelection sel(ui->treeWidget);
sel.applyFrom(Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()));
+
+ connect(ui->txtAxisLink, SIGNAL(textChanged(QString)), this, SLOT(on_txtAxisLink_textChanged(QString)));
+
}
/*
@@ -125,20 +138,154 @@ DlgRevolution::~DlgRevolution()
delete ui;
}
-void DlgRevolution::directionActivated(int index)
+Base::Vector3d DlgRevolution::getDirection() const
{
- ui->directionActivated(this, index);
+ return Base::Vector3d(
+ ui->xDir->value().getValue(),
+ ui->yDir->value().getValue(),
+ ui->zDir->value().getValue());
}
-Base::Vector3d DlgRevolution::getDirection() const
+Base::Vector3d DlgRevolution::getPosition() const
{
- return ui->getDirection();
+ return Base::Vector3d(
+ ui->xPos->value().getValueAs(Base::Quantity::MilliMetre),
+ ui->yPos->value().getValueAs(Base::Quantity::MilliMetre),
+ ui->zPos->value().getValueAs(Base::Quantity::MilliMetre));
+}
+
+void DlgRevolution::getAxisLink(App::PropertyLinkSub &lnk) const
+{
+ QString text = ui->txtAxisLink->text();
+
+ if (text.length() == 0) {
+ lnk.setValue(nullptr);
+ } else {
+ QStringList parts = text.split(QChar::fromLatin1(':'));
+ App::DocumentObject* obj = App::GetApplication().getActiveDocument()->getObject(parts[0].toLatin1());
+ if(!obj){
+ throw Base::ValueError(tr("Object not found: %1").arg(parts[0]).toUtf8().constData());
+ }
+ lnk.setValue(obj);
+ if (parts.size() == 1) {
+ return;
+ } else if (parts.size() == 2) {
+ std::vector subs;
+ subs.push_back(std::string(parts[1].toLatin1().constData()));
+ lnk.setValue(obj,subs);
+ }
+ }
+
+}
+
+double DlgRevolution::getAngle() const
+{
+ return ui->angle->value().getValueAs(Base::Quantity::Degree);
+}
+
+void DlgRevolution::setDirection(Base::Vector3d dir)
+{
+ ui->xDir->setValue(dir.x);
+ ui->yDir->setValue(dir.y);
+ ui->zDir->setValue(dir.z);
+}
+
+void DlgRevolution::setPosition(Base::Vector3d pos)
+{
+ ui->xPos->setValue(pos.x);
+ ui->yPos->setValue(pos.y);
+ ui->zPos->setValue(pos.z);
+}
+
+void DlgRevolution::setAxisLink(const App::PropertyLinkSub& lnk)
+{
+ if (!lnk.getValue()){
+ ui->txtAxisLink->clear();
+ return;
+ }
+ if (lnk.getSubValues().size() == 1){
+ this->setAxisLink(lnk.getValue()->getNameInDocument(), lnk.getSubValues()[0].c_str());
+ } else {
+ this->setAxisLink(lnk.getValue()->getNameInDocument(), "");
+ }
+}
+
+void DlgRevolution::setAxisLink(const char* objname, const char* subname)
+{
+ if(objname && strlen(objname) > 0){
+ QString txt = QString::fromLatin1(objname);
+ if (subname && strlen(subname) > 0){
+ txt = txt + QString::fromLatin1(":") + QString::fromLatin1(subname);
+ }
+ ui->txtAxisLink->setText(txt);
+ } else {
+ ui->txtAxisLink->clear();
+ }
+}
+
+bool DlgRevolution::validate()
+{
+ //check source shapes
+ if (ui->treeWidget->selectedItems().isEmpty()) {
+ QMessageBox::critical(this, windowTitle(),
+ tr("Select a shape for revolution, first."));
+ return false;
+ }
+
+ //check axis link
+ bool axisLinkIsValid = false;
+ bool axisLinkHasAngle = false;
+ try{
+ App::PropertyLinkSub lnk;
+ this->getAxisLink(lnk);
+ double angle_edge = 1e100;
+ Base::Vector3d axis, center;
+ axisLinkIsValid = Part::Revolution::fetchAxisLink(lnk, center, axis, angle_edge);
+ axisLinkHasAngle = angle_edge != 1e100;
+ } catch(Base::Exception &err) {
+ QMessageBox::critical(this, windowTitle(),
+ tr("Revolution axis link is invalid.\n\n%1").arg(QString::fromUtf8(err.what())));
+ ui->txtAxisLink->setFocus();
+ return false;
+ } catch(Standard_Failure &err) {
+ QMessageBox::critical(this, windowTitle(),
+ tr("Revolution axis link is invalid.\n\n%1").arg(QString::fromLocal8Bit(err.GetMessageString())));
+ ui->txtAxisLink->setFocus();
+ return false;
+ } catch(...) {
+ QMessageBox::critical(this, windowTitle(),
+ tr("Revolution axis link is invalid.\n\n%1").arg(QString::fromUtf8("Unknown error")));
+ ui->txtAxisLink->setFocus();
+ return false;
+ }
+
+ //check axis dir
+ if (!axisLinkIsValid){
+ if(this->getDirection().Length() < Precision::Confusion()){
+ QMessageBox::critical(this, windowTitle(),
+ tr("Revolution axis direction is zero-length. It must be non-zero."));
+ ui->xDir->setFocus();
+ return false;
+ }
+ }
+
+ //check angle
+ if (!axisLinkHasAngle){
+ if (fabs(this->getAngle() / 180.0 * M_PI) < Precision::Angular()){
+ QMessageBox::critical(this, windowTitle(),
+ tr("Revolution angle span is zero. It must be non-zero."));
+ ui->angle->setFocus();
+ return false;
+ }
+ }
+
+ return true;
}
void DlgRevolution::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
- ui->retranslate(this);
+ ui->retranslateUi(this);
}
else {
QDialog::changeEvent(e);
@@ -173,56 +320,89 @@ void DlgRevolution::findShapes()
void DlgRevolution::accept()
{
- if (ui->treeWidget->selectedItems().isEmpty()) {
- QMessageBox::critical(this, windowTitle(),
- tr("Select a shape for revolution, first."));
+ if (!this->validate())
return;
- }
-
Gui::WaitCursor wc;
App::Document* activeDoc = App::GetApplication().getActiveDocument();
activeDoc->openTransaction("Revolve");
- QString shape, type, name, solid;
- QList items = ui->treeWidget->selectedItems();
- if (ui->checkSolid->isChecked()) {
- solid = QString::fromLatin1("True");}
- else {
- solid = QString::fromLatin1("False");}
- for (QList::iterator it = items.begin(); it != items.end(); ++it) {
- shape = (*it)->data(0, Qt::UserRole).toString();
- type = QString::fromLatin1("Part::Revolution");
- name = QString::fromLatin1(activeDoc->getUniqueObjectName("Revolve").c_str());
- Base::Vector3d axis = this->getDirection();
-
- QString code = QString::fromLatin1(
- "FreeCAD.ActiveDocument.addObject(\"%1\",\"%2\")\n"
- "FreeCAD.ActiveDocument.%2.Source = FreeCAD.ActiveDocument.%3\n"
- "FreeCAD.ActiveDocument.%2.Axis = (%4,%5,%6)\n"
- "FreeCAD.ActiveDocument.%2.Base = (%7,%8,%9)\n"
- "FreeCAD.ActiveDocument.%2.Angle = %10\n"
- "FreeCAD.ActiveDocument.%2.Solid = %11\n"
- "FreeCADGui.ActiveDocument.%3.Visibility = False\n")
- .arg(type).arg(name).arg(shape)
- .arg(axis.x,0,'f',Base::UnitsApi::getDecimals())
- .arg(axis.y,0,'f',Base::UnitsApi::getDecimals())
- .arg(axis.z,0,'f',Base::UnitsApi::getDecimals())
- .arg(ui->xPos->value().getValue(), 0,'f',Base::UnitsApi::getDecimals())
- .arg(ui->yPos->value().getValue(), 0,'f',Base::UnitsApi::getDecimals())
- .arg(ui->zPos->value().getValue(), 0,'f',Base::UnitsApi::getDecimals())
- .arg(ui->angle->value().getValue(),0,'f',Base::UnitsApi::getDecimals())
- .arg(solid)
- ;
- Gui::Application::Instance->runPythonCode((const char*)code.toLatin1());
- QByteArray to = name.toLatin1();
- QByteArray from = shape.toLatin1();
- Gui::Command::copyVisual(to, "ShapeColor", from);
- Gui::Command::copyVisual(to, "LineColor", from);
- Gui::Command::copyVisual(to, "PointColor", from);
+ try{
+ QString shape, type, name, solid;
+ QList items = ui->treeWidget->selectedItems();
+ if (ui->checkSolid->isChecked()) {
+ solid = QString::fromLatin1("True");}
+ else {
+ solid = QString::fromLatin1("False");}
+
+ App::PropertyLinkSub axisLink;
+ this->getAxisLink(axisLink);
+ QString strAxisLink;
+ if (axisLink.getValue()){
+ strAxisLink = QString::fromLatin1("(App.ActiveDocument.%1, %2)")
+ .arg(QString::fromLatin1(axisLink.getValue()->getNameInDocument()))
+ .arg(axisLink.getSubValues().size() == 1 ?
+ QString::fromLatin1("\"%1\"").arg(QString::fromLatin1(axisLink.getSubValues()[0].c_str()))
+ : QString() );
+ } else {
+ strAxisLink = QString::fromLatin1("None");
+ }
+
+ QString symmetric;
+ if (ui->checkSymmetric->isChecked()) {
+ symmetric = QString::fromLatin1("True");}
+ else {
+ symmetric = QString::fromLatin1("False");}
+
+ for (QList::iterator it = items.begin(); it != items.end(); ++it) {
+ shape = (*it)->data(0, Qt::UserRole).toString();
+ type = QString::fromLatin1("Part::Revolution");
+ name = QString::fromLatin1(activeDoc->getUniqueObjectName("Revolve").c_str());
+ Base::Vector3d axis = this->getDirection();
+ Base::Vector3d pos = this->getPosition();
+
+
+ QString code = QString::fromLatin1(
+ "FreeCAD.ActiveDocument.addObject(\"%1\",\"%2\")\n"
+ "FreeCAD.ActiveDocument.%2.Source = FreeCAD.ActiveDocument.%3\n"
+ "FreeCAD.ActiveDocument.%2.Axis = (%4,%5,%6)\n"
+ "FreeCAD.ActiveDocument.%2.Base = (%7,%8,%9)\n"
+ "FreeCAD.ActiveDocument.%2.Angle = %10\n"
+ "FreeCAD.ActiveDocument.%2.Solid = %11\n"
+ "FreeCAD.ActiveDocument.%2.AxisLink = %12\n"
+ "FreeCAD.ActiveDocument.%2.Symmetric = %13\n"
+ "FreeCADGui.ActiveDocument.%3.Visibility = False\n")
+ .arg(type).arg(name).arg(shape) //%1, 2, 3
+ .arg(axis.x,0,'f',15) //%4
+ .arg(axis.y,0,'f',15) //%5
+ .arg(axis.z,0,'f',15) //%6
+ .arg(pos.x, 0,'f',15) //%7
+ .arg(pos.y, 0,'f',15) //%8
+ .arg(pos.z, 0,'f',15) //%9
+ .arg(getAngle(),0,'f',15) //%10
+ .arg(solid) //%11
+ .arg(strAxisLink) //%12
+ .arg(symmetric) //13
+ ;
+ Gui::Application::Instance->runPythonCode((const char*)code.toLatin1());
+ QByteArray to = name.toLatin1();
+ QByteArray from = shape.toLatin1();
+ Gui::Command::copyVisual(to, "ShapeColor", from);
+ Gui::Command::copyVisual(to, "LineColor", from);
+ Gui::Command::copyVisual(to, "PointColor", from);
+ }
+
+ activeDoc->commitTransaction();
+ activeDoc->recompute();
+ } catch (Base::Exception &err) {
+ QMessageBox::critical(this, windowTitle(),
+ tr("Creating Revolve failed.\n\n%1").arg(QString::fromUtf8(err.what())));
+ return;
+ } catch (...){
+ QMessageBox::critical(this, windowTitle(),
+ tr("Creating Revolve failed.\n\n%1").arg(QString::fromUtf8("Unknown error")));
+ return;
}
- activeDoc->commitTransaction();
- activeDoc->recompute();
QDialog::accept();
}
@@ -231,15 +411,71 @@ void DlgRevolution::on_selectLine_clicked()
if (!filter) {
filter = new EdgeSelection();
Gui::Selection().addSelectionGate(filter);
+ ui->selectLine->setText(tr("Selecting... (line or arc)"));
+ } else {
+ Gui::Selection().rmvSelectionGate();
+ filter = nullptr;
+ ui->selectLine->setText(tr("Select reference"));
+ }
+}
+
+void DlgRevolution::on_btnX_clicked()
+{
+ setDirection(Base::Vector3d(1,0,0));
+ if (!ui->xDir->isEnabled())
+ ui->txtAxisLink->clear();
+}
+
+void DlgRevolution::on_btnY_clicked()
+{
+ setDirection(Base::Vector3d(0,1,0));
+ if (!ui->xDir->isEnabled())
+ ui->txtAxisLink->clear();
+}
+
+void DlgRevolution::on_btnZ_clicked()
+{
+ setDirection(Base::Vector3d(0,0,1));
+ if (!ui->xDir->isEnabled())
+ ui->txtAxisLink->clear();
+}
+
+void DlgRevolution::on_txtAxisLink_textChanged(QString)
+{
+ bool en = true;
+ try{
+ Base::Vector3d pos, dir;
+ double angle_edge = 1e100;
+ App::PropertyLinkSub lnk; this->getAxisLink(lnk);
+ bool fetched = Part::Revolution::fetchAxisLink(lnk, pos, dir, angle_edge);
+ if (fetched){
+ this->setDirection(dir);
+ this->setPosition(pos);
+ if (angle_edge != 1e100){
+ ui->angle->setValue(0.0);
+ } else if (fabs(ui->angle->value().getValue()) < 1e-12) {
+ ui->angle->setValue(360.0);
+ }
+ en = false;
+ }
+ } catch (Base::Exception &err){
+
+ } catch (...){
+
}
+ ui->xDir->setEnabled(en);
+ ui->yDir->setEnabled(en);
+ ui->zDir->setEnabled(en);
+ ui->xPos->setEnabled(en);
+ ui->yPos->setEnabled(en);
+ ui->zPos->setEnabled(en);
}
void DlgRevolution::onSelectionChanged(const Gui::SelectionChanges& msg)
{
if (msg.Type == Gui::SelectionChanges::AddSelection) {
if (filter && filter->canSelect) {
- ui->setPosition (Base::convertTo(filter->loc));
- ui->setDirection(Base::convertTo(filter->dir));
+ this->setAxisLink(msg.pObjectName, msg.pSubName);
}
}
}
diff --git a/src/Mod/Part/Gui/DlgRevolution.h b/src/Mod/Part/Gui/DlgRevolution.h
index f88b35210cca..4ae1958f88fa 100644
--- a/src/Mod/Part/Gui/DlgRevolution.h
+++ b/src/Mod/Part/Gui/DlgRevolution.h
@@ -31,7 +31,7 @@
namespace PartGui {
class Ui_DlgRevolution;
-class DlgRevolution : public Gui::LocationDialog, public Gui::SelectionObserver
+class DlgRevolution : public QDialog, public Gui::SelectionObserver
{
Q_OBJECT
@@ -41,21 +41,34 @@ class DlgRevolution : public Gui::LocationDialog, public Gui::SelectionObserver
void accept();
Base::Vector3d getDirection() const;
+ Base::Vector3d getPosition() const;
+ void getAxisLink(App::PropertyLinkSub &lnk) const;
+ double getAngle() const;
+
+ void setDirection(Base::Vector3d dir);
+ void setPosition(Base::Vector3d dir);
+ void setAxisLink(const App::PropertyLinkSub &lnk);
+ void setAxisLink(const char* objname, const char* subname);
+
+ bool validate();
protected:
void changeEvent(QEvent *e);
private Q_SLOTS:
void on_selectLine_clicked();
+ void on_btnX_clicked();
+ void on_btnY_clicked();
+ void on_btnZ_clicked();
+ void on_txtAxisLink_textChanged(QString);
private:
void findShapes();
- void directionActivated(int);
void onSelectionChanged(const Gui::SelectionChanges& msg);
private:
- typedef Gui::LocationInterfaceComp Ui_RevolutionComp;
- Ui_RevolutionComp* ui;
+ //typedef Gui::LocationInterfaceComp Ui_RevolutionComp;
+ Ui_DlgRevolution* ui;
class EdgeSelection;
EdgeSelection* filter;
};
diff --git a/src/Mod/Part/Gui/DlgRevolution.ui b/src/Mod/Part/Gui/DlgRevolution.ui
index e859df4ce29f..8f056f8ef25a 100644
--- a/src/Mod/Part/Gui/DlgRevolution.ui
+++ b/src/Mod/Part/Gui/DlgRevolution.ui
@@ -6,55 +6,83 @@
0
0
- 307
- 266
+ 320
+ 599
+
+
+ 0
+ 0
+
+
Revolve
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
9
6
+ -
+
+
+ If checked, revolving wires will produce solids. If not, revolving a wire yeilds a shell.
+
+
+ Create Solid
+
+
+
-
-
-
- 0
+
+
+ QAbstractItemView::ExtendedSelection
+
+
+ 20
+
+
+ false
-
+
+
+ Shape
+
+
+
+
+ -
+
+
6
-
-
-
-
- Y:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- X:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- mm
-
-
-
+
+ 6
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -65,90 +93,220 @@
- -
-
-
- mm
-
-
-
- -
-
-
- -
-
-
- Z:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- Axis:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
- mm
-
-
-
-
-
+
deg
-
+
-360.000000000000000
-
+
360.000000000000000
-
+
360.000000000000000
- -
-
-
- QAbstractItemView::ExtendedSelection
+
-
+
+
+
+ 0
+ 0
+
-
- 20
+
+ Revolution axis
-
- false
-
-
-
- Shape
-
-
+
+
-
+
+
-
+
+
+ Center X:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ mm
+
+
+
+ -
+
+
+ Center Y:
+
+
+
+ -
+
+
+ mm
+
+
+
+ -
+
+
+ Center Z:
+
+
+
+ -
+
+
+ mm
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Click to set this as axis
+
+
+ Dir. X:
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Click to set this as axis
+
+
+ Dir. Y:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Dir. Z:
+
+
+
+
+
+ -
+
+
+ Select reference
+
+
+
+ -
+
+
+
- -
-
-
- Select line in 3D view
+
-
+
+
+ If checked, revolution will extend forwards and backwards by half the angle.
-
-
- -
-
- Create Solid
+ Symmetric angle
@@ -163,11 +321,12 @@
treeWidget
- angle
- xPos
- yPos
- zPos
- direction
+ btnX
+ btnY
+ btnZ
+ selectLine
+ txtAxisLink
+ checkSolid