diff --git a/src/App/PropertyGeo.h b/src/App/PropertyGeo.h index 280deedea..f8f839b47 100644 --- a/src/App/PropertyGeo.h +++ b/src/App/PropertyGeo.h @@ -185,6 +185,9 @@ public: /** This method returns a string representation of the property */ const Base::Matrix4D &getValue(void) const; + const char* getEditorName(void) const { + return "Gui::PropertyEditor::PropertyMatrixItem"; + } virtual PyObject *getPyObject(void); virtual void setPyObject(PyObject *); diff --git a/src/Base/Matrix.cpp b/src/Base/Matrix.cpp index 4ea986415..ba936e13f 100644 --- a/src/Base/Matrix.cpp +++ b/src/Base/Matrix.cpp @@ -691,3 +691,98 @@ void Matrix4D::fromString(const std::string &str) input >> dMtrx4D[i][j]; } } + +// Analyse the a transformation Matrix and describe the transformation +std::string Matrix4D::analyse(void) const +{ + const double eps=1.0e-06; + bool hastranslation = (dMtrx4D[0][3] != 0.0 || + dMtrx4D[1][3] != 0.0 || dMtrx4D[2][3] != 0.0); + const Base::Matrix4D unityMatrix = Base::Matrix4D(); + std::string text; + if (*this == unityMatrix) + { + text = "Unity Matrix"; + } + else + { + if (dMtrx4D[3][0] != 0.0 || dMtrx4D[3][1] != 0.0 || + dMtrx4D[3][2] != 0.0 || dMtrx4D[3][3] != 1.0) + { + text = "Projection"; + } + else //translation and affine + { + if (dMtrx4D[0][1] == 0.0 && dMtrx4D[0][2] == 0.0 && + dMtrx4D[1][0] == 0.0 && dMtrx4D[1][2] == 0.0 && + dMtrx4D[2][0] == 0.0 && dMtrx4D[2][1] == 0.0) //scaling + { + std::ostringstream stringStream; + stringStream << "Scale [" << dMtrx4D[0][0] << ", " << + dMtrx4D[1][1] << ", " << dMtrx4D[2][2] << "]"; + text = stringStream.str(); + } + else + { + Base::Matrix4D sub; + sub[0][0] = dMtrx4D[0][0]; sub[0][1] = dMtrx4D[0][1]; + sub[0][2] = dMtrx4D[0][2]; sub[1][0] = dMtrx4D[1][0]; + sub[1][1] = dMtrx4D[1][1]; sub[1][2] = dMtrx4D[1][2]; + sub[2][0] = dMtrx4D[2][0]; sub[2][1] = dMtrx4D[2][1]; + sub[2][2] = dMtrx4D[2][2]; + + Base::Matrix4D trp = sub; + trp.transpose(); + trp = trp * sub; + bool ortho = true; + for (int i=0; i<4 && ortho; i++) { + for (int j=0; j<4 && ortho; j++) { + if (i != j) { + if (fabs(trp[i][j]) > eps) { + ortho = false; + break; + } + } + } + } + + double determinant = sub.determinant(); + if (ortho) + { + if (fabs(determinant-1.0) + + + +analyze() -> string +Analyzes the type of transformation. + + + The matrix elements diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index a5408bb18..b7d594f54 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -474,6 +474,18 @@ PyObject* MatrixPy::transpose(PyObject * args) PY_CATCH; } +PyObject* MatrixPy::analyze(PyObject * args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + PY_TRY { + std::string type = getMatrixPtr()->analyse(); + return PyString_FromString(type.c_str()); + } + PY_CATCH; +} + Py::Float MatrixPy::getA11(void) const { double val = (*this->getMatrixPtr())[0][0]; diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index a83d5ea5e..c7ea796cb 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -25,6 +25,10 @@ #ifndef _PreComp_ # include # include +# include +# include +# include +# include # include # include # include @@ -319,6 +323,28 @@ bool StdCmdMergeProjects::isActive(void) // Std_ExportGraphviz //=========================================================================== +namespace Gui { +class ImageView : public MDIView +{ +public: + ImageView(const QPixmap& p, QWidget* parent=0) : MDIView(0, parent) + { + scene = new QGraphicsScene(); + scene->addPixmap(p); + view = new QGraphicsView(scene, this); + view->show(); + setCentralWidget(view); + } + ~ImageView() + { + delete scene; + delete view; + } + QGraphicsScene* scene; + QGraphicsView* view; +}; +} + DEF_STD_CMD_A(StdCmdExportGraphviz); StdCmdExportGraphviz::StdCmdExportGraphviz() @@ -336,48 +362,57 @@ StdCmdExportGraphviz::StdCmdExportGraphviz() void StdCmdExportGraphviz::activated(int iMsg) { App::Document* doc = App::GetApplication().getActiveDocument(); - Base::FileInfo fi(Base::FileInfo::getTempFileName()); - Base::ofstream str(fi); + std::stringstream str; doc->exportGraphviz(str); - str.close(); - Base::FileInfo out(Base::FileInfo::getTempFileName()); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Paths"); QProcess proc; - QEventLoop loop; - QObject::connect(&proc, SIGNAL(finished(int, QProcess::ExitStatus)), - &loop, SLOT(quit())); QStringList args; - args << QLatin1String("-Tpng") << QString::fromUtf8(fi.filePath().c_str()) - << QLatin1String("-o") << QString::fromUtf8(out.filePath().c_str()); - QString exe = QLatin1String("dot"); - QStringList env = QProcess::systemEnvironment(); - proc.setEnvironment(env); - proc.start(exe, args); - if (proc.state() == QProcess::Running) { - loop.exec(); - fi.deleteFile(); - } - else { - QMessageBox::warning(getMainWindow(), - qApp->translate("Std_ExportGraphviz","Graphviz not found"), - qApp->translate("Std_ExportGraphviz","Graphviz couldn't be found on your system")); - fi.deleteFile(); - return; + args << QLatin1String("-Tpng"); + QString path = QString::fromUtf8(hGrp->GetASCII("Graphviz").c_str()); + bool pathChanged = false; + QString exe = QString::fromAscii("\"%1/dot\"").arg(path); + proc.setEnvironment(QProcess::systemEnvironment()); + do { + proc.start(exe, args); + if (!proc.waitForStarted()) { + int ret = QMessageBox::warning(getMainWindow(), + qApp->translate("Std_ExportGraphviz","Graphviz not found"), + qApp->translate("Std_ExportGraphviz","Graphviz couldn't be found on your system.\n" + "Do you want to specify its installation path if it's already installed?"), + QMessageBox::Yes, QMessageBox::No); + if (ret == QMessageBox::No) + return; + path = QFileDialog::getExistingDirectory(Gui::getMainWindow(), + qApp->translate("Std_ExportGraphviz","Graphviz installation path")); + if (path.isEmpty()) + return; + pathChanged = true; + exe = QString::fromAscii("\"%1/dot\"").arg(path); + } + else { + if (pathChanged) + hGrp->SetASCII("Graphviz", (const char*)path.toUtf8()); + break; + } } + while(true); - if (out.exists()) { - QPixmap px(QString::fromUtf8(out.filePath().c_str()), "PNG"); - out.deleteFile(); - QLabel* label = new QLabel(0); - label->setAttribute(Qt::WA_DeleteOnClose); - label->setPixmap(px); - label->resize(px.size()); - label->show(); + proc.write(str.str().c_str(), str.str().size()); + proc.closeWriteChannel(); + if (!proc.waitForFinished()) + return; + + QPixmap px; + if (px.loadFromData(proc.readAll(), "PNG")) { + Gui::ImageView* view = new Gui::ImageView(px); + view->setWindowTitle(qApp->translate("Std_ExportGraphviz","Dependency graph")); + getMainWindow()->addWindow(view); } else { QMessageBox::warning(getMainWindow(), - qApp->translate("Std_ExportGraphviz","Graphviz failed"), - qApp->translate("Std_ExportGraphviz","Graphviz failed to create an image file")); + qApp->translate("Std_ExportGraphviz","Graphviz failed"), + qApp->translate("Std_ExportGraphviz","Graphviz failed to create an image file")); } } diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index ddf074ca1..5769248c4 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -111,6 +111,7 @@ void Gui::SoFCDB::init() PropertyBoolItem ::init(); PropertyVectorItem ::init(); PropertyDoubleVectorItem ::init(); + PropertyMatrixItem ::init(); PropertyPlacementItem ::init(); PropertyEnumItem ::init(); PropertyStringListItem ::init(); diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 8d354c937..e1f035a4a 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -32,6 +32,8 @@ # include # include # include +# include +# include # include # include # include @@ -299,6 +301,29 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M else if (strcmp(Reason,"UseAntialiasing") == 0) { _viewer->getGLRenderAction()->setSmoothing(rGrp.GetBool("UseAntialiasing",false)); } + else if (strcmp(Reason,"SampleBuffers") == 0) { +#if SOQT_MAJOR_VERSION > 1 || (SOQT_MAJOR_VERSION == 1 && SOQT_MINOR_VERSION >= 5) + _viewer->setSampleBuffers(rGrp.GetInt("SampleBuffers",4)); +#else + // http://stackoverflow.com/questions/4207506/where-is-gl-multisample-defined + //int sb = rGrp.GetInt("SampleBuffers",4); + //QGLWidget* gl = static_cast(_viewer->getGLWidget()); + //QGLFormat fmt = gl->format(); + //if (sb > 0) { + // fmt.setSampleBuffers(true); + // fmt.setSamples(sb); + // gl->setFormat(fmt); + // gl->makeCurrent(); + // //glEnable(GL_MULTISAMPLE); + //} + //else { + // fmt.setSampleBuffers(false); + // gl->setFormat(fmt); + // gl->makeCurrent(); + // //glDisable(GL_MULTISAMPLE); + //} +#endif + } else if (strcmp(Reason,"ShowFPS") == 0) { _viewer->setEnabledFPSCounter(rGrp.GetBool("ShowFPS",false)); } diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 52b5733ec..ef772af2b 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -1050,6 +1050,358 @@ void PropertyDoubleVectorItem::setZ(double z) setData(QVariant::fromValue(Base::Vector3d(x(), y(), z))); } +// --------------------------------------------------------------- + +TYPESYSTEM_SOURCE(Gui::PropertyEditor::PropertyMatrixItem, Gui::PropertyEditor::PropertyItem); + +PropertyMatrixItem::PropertyMatrixItem() +{ + const int decimals=16; + m_a11 = static_cast(PropertyFloatItem::create()); + m_a11->setParent(this); + m_a11->setPropertyName(QLatin1String("A11")); + m_a11->setDecimals(decimals); + this->appendChild(m_a11); + m_a12 = static_cast(PropertyFloatItem::create()); + m_a12->setParent(this); + m_a12->setPropertyName(QLatin1String("A12")); + m_a12->setDecimals(decimals); + this->appendChild(m_a12); + m_a13 = static_cast(PropertyFloatItem::create()); + m_a13->setParent(this); + m_a13->setPropertyName(QLatin1String("A13")); + m_a13->setDecimals(decimals); + this->appendChild(m_a13); + m_a14 = static_cast(PropertyFloatItem::create()); + m_a14->setParent(this); + m_a14->setPropertyName(QLatin1String("A14")); + m_a14->setDecimals(decimals); + this->appendChild(m_a14); + m_a21 = static_cast(PropertyFloatItem::create()); + m_a21->setParent(this); + m_a21->setPropertyName(QLatin1String("A21")); + m_a21->setDecimals(decimals); + this->appendChild(m_a21); + m_a22 = static_cast(PropertyFloatItem::create()); + m_a22->setParent(this); + m_a22->setPropertyName(QLatin1String("A22")); + m_a22->setDecimals(decimals); + this->appendChild(m_a22); + m_a23 = static_cast(PropertyFloatItem::create()); + m_a23->setParent(this); + m_a23->setPropertyName(QLatin1String("A23")); + m_a23->setDecimals(decimals); + this->appendChild(m_a23); + m_a24 = static_cast(PropertyFloatItem::create()); + m_a24->setParent(this); + m_a24->setPropertyName(QLatin1String("A24")); + m_a24->setDecimals(decimals); + this->appendChild(m_a24); + m_a31 = static_cast(PropertyFloatItem::create()); + m_a31->setParent(this); + m_a31->setPropertyName(QLatin1String("A31")); + m_a31->setDecimals(decimals); + this->appendChild(m_a31); + m_a32 = static_cast(PropertyFloatItem::create()); + m_a32->setParent(this); + m_a32->setPropertyName(QLatin1String("A32")); + m_a32->setDecimals(decimals); + this->appendChild(m_a32); + m_a33 = static_cast(PropertyFloatItem::create()); + m_a33->setParent(this); + m_a33->setPropertyName(QLatin1String("A33")); + m_a33->setDecimals(decimals); + this->appendChild(m_a33); + m_a34 = static_cast(PropertyFloatItem::create()); + m_a34->setParent(this); + m_a34->setPropertyName(QLatin1String("A34")); + m_a34->setDecimals(decimals); + this->appendChild(m_a34); + m_a41 = static_cast(PropertyFloatItem::create()); + m_a41->setParent(this); + m_a41->setPropertyName(QLatin1String("A41")); + m_a41->setDecimals(decimals); + this->appendChild(m_a41); + m_a42 = static_cast(PropertyFloatItem::create()); + m_a42->setParent(this); + m_a42->setPropertyName(QLatin1String("A42")); + m_a42->setDecimals(decimals); + this->appendChild(m_a42); + m_a43 = static_cast(PropertyFloatItem::create()); + m_a43->setParent(this); + m_a43->setPropertyName(QLatin1String("A43")); + m_a43->setDecimals(decimals); + this->appendChild(m_a43); + m_a44 = static_cast(PropertyFloatItem::create()); + m_a44->setParent(this); + m_a44->setPropertyName(QLatin1String("A44")); + m_a44->setDecimals(decimals); + this->appendChild(m_a44); +} + +QVariant PropertyMatrixItem::toString(const QVariant& prop) const +{ + const Base::Matrix4D& value = prop.value(); + QString text = QString::fromAscii("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") + .arg(QLocale::system().toString(value[0][0], 'f', 2)) //(unsigned short usNdx) + .arg(QLocale::system().toString(value[0][1], 'f', 2)) + .arg(QLocale::system().toString(value[0][2], 'f', 2)) + .arg(QLocale::system().toString(value[0][3], 'f', 2)) + .arg(QLocale::system().toString(value[1][0], 'f', 2)) + .arg(QLocale::system().toString(value[1][1], 'f', 2)) + .arg(QLocale::system().toString(value[1][2], 'f', 2)) + .arg(QLocale::system().toString(value[1][3], 'f', 2)) + .arg(QLocale::system().toString(value[2][0], 'f', 2)) + .arg(QLocale::system().toString(value[2][1], 'f', 2)) + .arg(QLocale::system().toString(value[2][2], 'f', 2)) + .arg(QLocale::system().toString(value[2][3], 'f', 2)) + .arg(QLocale::system().toString(value[3][0], 'f', 2)) + .arg(QLocale::system().toString(value[3][1], 'f', 2)) + .arg(QLocale::system().toString(value[3][2], 'f', 2)) + .arg(QLocale::system().toString(value[3][3], 'f', 2)); + return QVariant(text); +} + +QVariant PropertyMatrixItem::value(const App::Property* prop) const +{ + assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMatrix::getClassTypeId())); + + const Base::Matrix4D& value = static_cast(prop)->getValue(); + return QVariant::fromValue(value); +} + +QVariant PropertyMatrixItem::toolTip(const App::Property* prop) const +{ + assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMatrix::getClassTypeId())); + + const Base::Matrix4D& value = static_cast(prop)->getValue(); + return QVariant(QString::fromStdString(value.analyse())); +} + +void PropertyMatrixItem::setValue(const QVariant& value) +{ + if (!value.canConvert()) + return; + const Base::Matrix4D& val = value.value(); + const int decimals=16; + QString data = QString::fromAscii("FreeCAD.Matrix(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)") + .arg(val[0][0],0, 'f', decimals) + .arg(val[0][1],0, 'f', decimals) + .arg(val[0][2],0, 'f', decimals) + .arg(val[0][3],0, 'f', decimals) + .arg(val[1][0],0, 'f', decimals) + .arg(val[1][1],0, 'f', decimals) + .arg(val[1][2],0, 'f', decimals) + .arg(val[1][3],0, 'f', decimals) + .arg(val[2][0],0, 'f', decimals) + .arg(val[2][1],0, 'f', decimals) + .arg(val[2][2],0, 'f', decimals) + .arg(val[2][3],0, 'f', decimals) + .arg(val[3][0],0, 'f', decimals) + .arg(val[3][1],0, 'f', decimals) + .arg(val[3][2],0, 'f', decimals) + .arg(val[3][3],0, 'f', decimals); + setPropertyValue(data); +} + +QWidget* PropertyMatrixItem::createEditor(QWidget* parent, const QObject* /*receiver*/, const char* /*method*/) const +{ + QLineEdit *le = new QLineEdit(parent); + le->setFrame(false); + le->setReadOnly(true); + return le; +} + +void PropertyMatrixItem::setEditorData(QWidget *editor, const QVariant& data) const +{ + QLineEdit* le = qobject_cast(editor); + const Base::Matrix4D& value = data.value(); + QString text = QString::fromAscii("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") + .arg(QLocale::system().toString(value[0][0], 'f', 2)) //(unsigned short usNdx) + .arg(QLocale::system().toString(value[0][1], 'f', 2)) + .arg(QLocale::system().toString(value[0][2], 'f', 2)) + .arg(QLocale::system().toString(value[0][3], 'f', 2)) + .arg(QLocale::system().toString(value[1][0], 'f', 2)) + .arg(QLocale::system().toString(value[1][1], 'f', 2)) + .arg(QLocale::system().toString(value[1][2], 'f', 2)) + .arg(QLocale::system().toString(value[1][3], 'f', 2)) + .arg(QLocale::system().toString(value[2][0], 'f', 2)) + .arg(QLocale::system().toString(value[2][1], 'f', 2)) + .arg(QLocale::system().toString(value[2][2], 'f', 2)) + .arg(QLocale::system().toString(value[2][3], 'f', 2)) + .arg(QLocale::system().toString(value[3][0], 'f', 2)) + .arg(QLocale::system().toString(value[3][1], 'f', 2)) + .arg(QLocale::system().toString(value[3][2], 'f', 2)) + .arg(QLocale::system().toString(value[3][3], 'f', 2)); + le->setText(text); +} + +QVariant PropertyMatrixItem::editorData(QWidget *editor) const +{ + QLineEdit *le = qobject_cast(editor); + return QVariant(le->text()); +} + +double PropertyMatrixItem::getA11() const +{ + return data(1,Qt::EditRole).value()[0][0]; +} + +void PropertyMatrixItem::setA11(double A11) +{ + setData(QVariant::fromValue(Base::Matrix4D(A11,getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA12() const +{ + return data(1,Qt::EditRole).value()[0][1]; +} + +void PropertyMatrixItem::setA12(double A12) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),A12,getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA13() const +{ + return data(1,Qt::EditRole).value()[0][2]; +} + +void PropertyMatrixItem::setA13(double A13) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),A13,getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA14() const +{ + return data(1,Qt::EditRole).value()[0][3]; +} + +void PropertyMatrixItem::setA14(double A14) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),A14,getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA21() const +{ + return data(1,Qt::EditRole).value()[1][0]; +} + +void PropertyMatrixItem::setA21(double A21) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),A21,getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA22() const +{ + return data(1,Qt::EditRole).value()[1][1]; +} + +void PropertyMatrixItem::setA22(double A22) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),A22,getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA23() const +{ + return data(1,Qt::EditRole).value()[1][2]; +} + +void PropertyMatrixItem::setA23(double A23) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),A23,getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA24() const +{ + return data(1,Qt::EditRole).value()[1][3]; +} + +void PropertyMatrixItem::setA24(double A24) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),A24,getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA31() const +{ + return data(1,Qt::EditRole).value()[2][0]; +} + +void PropertyMatrixItem::setA31(double A31) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),A31,getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA32() const +{ + return data(1,Qt::EditRole).value()[2][1]; +} + +void PropertyMatrixItem::setA32(double A32) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),A32,getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA33() const +{ + return data(1,Qt::EditRole).value()[2][2]; +} + +void PropertyMatrixItem::setA33(double A33) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),A33,getA34(),getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA34() const +{ + return data(1,Qt::EditRole).value()[2][3]; +} + +void PropertyMatrixItem::setA34(double A34) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),A34,getA41(),getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA41() const +{ + return data(1,Qt::EditRole).value()[3][0]; +} + +void PropertyMatrixItem::setA41(double A41) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),A41,getA42(),getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA42() const +{ + return data(1,Qt::EditRole).value()[3][1]; +} + +void PropertyMatrixItem::setA42(double A42) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),A42,getA43(),getA44() ))); +} + +double PropertyMatrixItem::getA43() const +{ + return data(1,Qt::EditRole).value()[3][2]; +} + +void PropertyMatrixItem::setA43(double A43) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),A43,getA44() ))); +} + +double PropertyMatrixItem::getA44() const +{ + return data(1,Qt::EditRole).value()[3][3]; +} + +void PropertyMatrixItem::setA44(double A44) +{ + setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),A44 ))); +} + // -------------------------------------------------------------------- PlacementEditor::PlacementEditor(const QString& name, QWidget * parent) diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index bc247966f..e9990136d 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,7 @@ Q_DECLARE_METATYPE(Base::Vector3f) Q_DECLARE_METATYPE(Base::Vector3d) +Q_DECLARE_METATYPE(Base::Matrix4D) Q_DECLARE_METATYPE(Base::Placement) namespace Gui { @@ -366,6 +368,92 @@ private: PropertyFloatItem* m_z; }; +class GuiExport PropertyMatrixItem: public PropertyItem +{ + Q_OBJECT + Q_PROPERTY(double A11 READ getA11 WRITE setA11 DESIGNABLE true USER true) + Q_PROPERTY(double A12 READ getA12 WRITE setA12 DESIGNABLE true USER true) + Q_PROPERTY(double A13 READ getA13 WRITE setA13 DESIGNABLE true USER true) + Q_PROPERTY(double A14 READ getA14 WRITE setA14 DESIGNABLE true USER true) + Q_PROPERTY(double A21 READ getA21 WRITE setA21 DESIGNABLE true USER true) + Q_PROPERTY(double A22 READ getA22 WRITE setA22 DESIGNABLE true USER true) + Q_PROPERTY(double A23 READ getA23 WRITE setA23 DESIGNABLE true USER true) + Q_PROPERTY(double A24 READ getA24 WRITE setA24 DESIGNABLE true USER true) + Q_PROPERTY(double A31 READ getA31 WRITE setA31 DESIGNABLE true USER true) + Q_PROPERTY(double A32 READ getA32 WRITE setA32 DESIGNABLE true USER true) + Q_PROPERTY(double A33 READ getA33 WRITE setA33 DESIGNABLE true USER true) + Q_PROPERTY(double A34 READ getA34 WRITE setA34 DESIGNABLE true USER true) + Q_PROPERTY(double A41 READ getA41 WRITE setA41 DESIGNABLE true USER true) + Q_PROPERTY(double A42 READ getA42 WRITE setA42 DESIGNABLE true USER true) + Q_PROPERTY(double A43 READ getA43 WRITE setA43 DESIGNABLE true USER true) + Q_PROPERTY(double A44 READ getA44 WRITE setA44 DESIGNABLE true USER true) + TYPESYSTEM_HEADER(); + + virtual QWidget* createEditor(QWidget* parent, const QObject* receiver, const char* method) const; + virtual void setEditorData(QWidget *editor, const QVariant& data) const; + virtual QVariant editorData(QWidget *editor) const; + + double getA11() const; + void setA11(double A11); + double getA12() const; + void setA12(double A12); + double getA13() const; + void setA13(double A13); + double getA14() const; + void setA14(double A14); + double getA21() const; + void setA21(double A21); + double getA22() const; + void setA22(double A22); + double getA23() const; + void setA23(double A23); + double getA24() const; + void setA24(double A24); + double getA31() const; + void setA31(double A31); + double getA32() const; + void setA32(double A32); + double getA33() const; + void setA33(double A33); + double getA34() const; + void setA34(double A34); + double getA41() const; + void setA41(double A41); + double getA42() const; + void setA42(double A42); + double getA43() const; + void setA43(double A43); + double getA44() const; + void setA44(double A44); + +protected: + virtual QVariant toString(const QVariant&) const; + virtual QVariant value(const App::Property*) const; + virtual void setValue(const QVariant&); + +protected: + PropertyMatrixItem(); + virtual QVariant toolTip(const App::Property*) const; + +private: + PropertyFloatItem* m_a11; + PropertyFloatItem* m_a12; + PropertyFloatItem* m_a13; + PropertyFloatItem* m_a14; + PropertyFloatItem* m_a21; + PropertyFloatItem* m_a22; + PropertyFloatItem* m_a23; + PropertyFloatItem* m_a24; + PropertyFloatItem* m_a31; + PropertyFloatItem* m_a32; + PropertyFloatItem* m_a33; + PropertyFloatItem* m_a34; + PropertyFloatItem* m_a41; + PropertyFloatItem* m_a42; + PropertyFloatItem* m_a43; + PropertyFloatItem* m_a44; +}; + class PlacementEditor : public Gui::LabelButton { Q_OBJECT diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index e85581e60..2ac0c7604 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -70,20 +70,15 @@ class _CommandRoof: FreeCADGui.doCommand("Arch.makeRoof(FreeCAD.ActiveDocument."+obj.Name+","+str(idx)+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() - elif obj.isDerivedFrom("Part::Feature"): - if len(obj.Shape.Faces) == 1: - FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Roof"))) - FreeCADGui.doCommand("import Arch") - FreeCADGui.doCommand("Arch.makeRoof(FreeCAD.ActiveDocument."+obj.Name+",1)") - FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() - elif obj.isDerivedFrom("Part::Feature"): - if len(obj.Shape.Faces) == 1: + return + if obj.isDerivedFrom("Part::Feature"): + if obj.Shape.Wires: FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Roof"))) FreeCADGui.doCommand("import Arch") - FreeCADGui.doCommand("Arch.makeRoof(FreeCAD.ActiveDocument."+obj.Name+",1)") + FreeCADGui.doCommand("Arch.makeRoof(FreeCAD.ActiveDocument."+obj.Name+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() + return else: FreeCAD.Console.PrintMessage(str(translate("Arch","Unable to create a roof"))) else: @@ -110,37 +105,42 @@ class _Roof(ArchComponent.Component): import Part, math, DraftGeomUtils pl = obj.Placement - if obj.Base and obj.Face and obj.Angle: - if len(obj.Base.Shape.Faces) >= obj.Face: - f = obj.Base.Shape.Faces[obj.Face-1] - if len(f.Wires) == 1: - if f.Wires[0].isClosed(): - c = round(math.tan(math.radians(obj.Angle)),Draft.precision()) - norm = f.normalAt(0,0) - d = f.BoundBox.DiagonalLength - edges = DraftGeomUtils.sortEdges(f.Edges) - l = len(edges) - edges.append(edges[0]) - shps = [] - for i in range(l): - v = DraftGeomUtils.vec(DraftGeomUtils.angleBisection(edges[i],edges[i+1])) - v.normalize() - bis = v.getAngle(DraftGeomUtils.vec(edges[i])) - delta = 1/math.cos(bis) - v.multiply(delta) - n = (FreeCAD.Vector(norm)).multiply(c) - dv = v.add(n) - dv.normalize() - dv.scale(d,d,d) - shps.append(f.extrude(dv)) - c = shps.pop() - for s in shps: - c = c.common(s) - c = c.removeSplitter() - if not c.isNull(): - obj.Shape = c - if not DraftGeomUtils.isNull(pl): - obj.Placement = pl + if obj.Base and obj.Angle: + w = None + if obj.Base.isDerivedFrom("Part::Feature"): + if (obj.Base.Shape.Faces and obj.Face): + w = obj.Base.Shape.Faces[obj.Face-1].Wires[0] + elif obj.Base.Shape.Wires: + w = obj.Base.Shape.Wires[0] + if w: + if w.isClosed(): + f = Part.Face(w) + norm = f.normalAt(0,0) + c = round(math.tan(math.radians(obj.Angle)),Draft.precision()) + d = f.BoundBox.DiagonalLength + edges = DraftGeomUtils.sortEdges(f.Edges) + l = len(edges) + edges.append(edges[0]) + shps = [] + for i in range(l): + v = DraftGeomUtils.vec(DraftGeomUtils.angleBisection(edges[i],edges[i+1])) + v.normalize() + bis = v.getAngle(DraftGeomUtils.vec(edges[i])) + delta = 1/math.cos(bis) + v.multiply(delta) + n = (FreeCAD.Vector(norm)).multiply(c) + dv = v.add(n) + dv.normalize() + dv.scale(d,d,d) + shps.append(f.extrude(dv)) + c = shps.pop() + for s in shps: + c = c.common(s) + c = c.removeSplitter() + if not c.isNull(): + obj.Shape = c + if not DraftGeomUtils.isNull(pl): + obj.Placement = pl class _ViewProviderRoof(ArchComponent.ViewProviderComponent): "A View Provider for the Roof object" diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 1a9f51c07..e30c14106 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -30,7 +30,7 @@ __title__="FreeCAD Structure" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeStructure(baseobj=None,length=None,width=None,height=None,name=str(translate("Arch","Structure"))): +def makeStructure(baseobj=None,length=1,width=1,height=1,name=str(translate("Arch","Structure"))): '''makeStructure([obj],[length],[width],[heigth],[swap]): creates a structure element based on the given profile object and the given extrusion height. If no base object is given, you can also specify @@ -38,16 +38,12 @@ def makeStructure(baseobj=None,length=None,width=None,height=None,name=str(trans obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) _Structure(obj) _ViewProviderStructure(obj.ViewObject) - if baseobj: obj.Base = baseobj - if length: obj.Length = length - if width: obj.Width = width - if height: obj.Height = height - if obj.Base: + if baseobj: + obj.Base = baseobj obj.Base.ViewObject.hide() - else: - if (not obj.Width) and (not obj.Length): - obj.Width = 1 - obj.Height = 1 + obj.Width = width + obj.Height = height + obj.Length = length p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") c = p.GetUnsigned("StructureColor") r = float((c>>24)&0xFF)/255.0 @@ -116,43 +112,45 @@ class _Structure(ArchComponent.Component): def createGeometry(self,obj): import Part, DraftGeomUtils + # getting default values - height = normal = None - if obj.Length: - length = obj.Length - else: - length = 1 - width = 1 + height = width = length = 1 + if hasattr(obj,"Length"): + if obj.Length: + length = obj.Length if hasattr(obj,"Width"): if obj.Width: width = obj.Width - if obj.Height: - height = obj.Height - else: - for p in obj.InList: - if Draft.getType(p) == "Floor": - height = p.Height - if not height: height = 1 - if obj.Normal == Vector(0,0,0): - normal = Vector(0,0,1) - else: - normal = Vector(obj.Normal) + if hasattr(obj,"Height"): + if obj.Height: + height = obj.Height - # creating shape + # creating base shape pl = obj.Placement - norm = normal.multiply(height) base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): + if obj.Normal == Vector(0,0,0): + p = FreeCAD.Placement(obj.Base.Placement) + normal = p.Rotation.multVec(Vector(0,0,1)) + else: + normal = Vector(obj.Normal) + normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: base = base.extrude(normal) - elif (len(base.Wires) == 1) and base.Wires[0].isClosed(): - base = Part.Face(base.Wires[0]) - base = base.extrude(normal) + elif (len(base.Wires) == 1): + if base.Wires[0].isClosed(): + base = Part.Face(base.Wires[0]) + base = base.extrude(normal) else: + if obj.Normal == Vector(0,0,0): + normal = Vector(0,0,1) + else: + normal = Vector(obj.Normal) + normal = normal.multiply(height) l2 = length/2 or 0.5 w2 = width/2 or 0.5 v1 = Vector(-l2,-w2,0) @@ -162,17 +160,20 @@ class _Structure(ArchComponent.Component): base = Part.makePolygon([v1,v2,v3,v4,v1]) base = Part.Face(base) base = base.extrude(normal) - for app in obj.Additions: - if hasattr(app,"Shape"): - if not app.Shape.isNull(): - base = base.fuse(app.Shape) - app.ViewObject.hide() # to be removed - for hole in obj.Subtractions: - if hasattr(hole,"Shape"): - if not hole.Shape.isNull(): - base = base.cut(hole.Shape) - hole.ViewObject.hide() # to be removed + if base: + # applying adds and subs + if not base.isNull(): + for app in obj.Additions: + if hasattr(app,"Shape"): + if not app.Shape.isNull(): + base = base.fuse(app.Shape) + app.ViewObject.hide() # to be removed + for hole in obj.Subtractions: + if hasattr(hole,"Shape"): + if not hole.Shape.isNull(): + base = base.cut(hole.Shape) + hole.ViewObject.hide() # to be removed pts = self.getAxisPoints(obj) if pts: fsh = [] @@ -182,10 +183,12 @@ class _Structure(ArchComponent.Component): fsh.append(sh) obj.Shape = Part.makeCompound(fsh) else: - if not base.isNull(): - base = base.removeSplitter() - obj.Shape = base - if not DraftGeomUtils.isNull(pl): obj.Placement = pl + if base: + if not base.isNull(): + base = base.removeSplitter() + obj.Shape = base + if not DraftGeomUtils.isNull(pl): + obj.Placement = pl class _ViewProviderStructure(ArchComponent.ViewProviderComponent): "A View Provider for the Structure object" diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index e8236af3f..4983d77e7 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -271,7 +271,7 @@ class _Wall(ArchComponent.Component): if prop in ["Base","Height","Width","Align","Additions","Subtractions"]: self.createGeometry(obj) - def getSubVolume(self,base,width,delta=None): + def getSubVolume(self,base,width,plac=None): "returns a subvolume from a base object" import Part max_length = 0 @@ -288,8 +288,8 @@ class _Wall(ArchComponent.Component): v2 = DraftVecUtils.neg(v1) v2 = DraftVecUtils.scale(v1,-2) f = f.extrude(v2) - if delta: - f.translate(delta) + if plac: + f.Placement = plac return f return None @@ -384,12 +384,22 @@ class _Wall(ArchComponent.Component): if base: for app in obj.Additions: - if hasattr(app,"Shape"): + if Draft.getType(app) == "Window": + # window + if app.Base and obj.Width: + f = self.getSubVolume(app.Base,width) + if f: + base = base.cut(f) + elif Draft.isClone(app,"Window"): + if app.Objects[0].Base and width: + f = self.getSubVolume(app.Objects[0].Base,width,app.Placement) + if f: + base = base.cut(f) + elif app.isDerivedFrom("Part::Feature"): if app.Shape: if not app.Shape.isNull(): base = base.fuse(app.Shape) app.ViewObject.hide() #to be removed - for hole in obj.Subtractions: if Draft.getType(hole) == "Window": # window @@ -399,10 +409,10 @@ class _Wall(ArchComponent.Component): base = base.cut(f) elif Draft.isClone(hole,"Window"): if hole.Objects[0].Base and width: - f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement.Base) + f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement) if f: base = base.cut(f) - elif hasattr(hole,"Shape"): + elif hole.isDerivedFrom("Part::Feature"): if hole.Shape: if not hole.Shape.isNull(): base = base.cut(hole.Shape) diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index ad9d49369..9c540e7be 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -107,9 +107,9 @@ class _CommandWindow: s = obj.Support w = FreeCAD.ActiveDocument.Objects[-1] # last created object FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+w.Name+",host=FreeCAD.ActiveDocument."+s.Name+")") - elif Draft.isClone(w,"Window"): - if w.Objects[0].Inlist: - FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+w.Name+",host=FreeCAD.ActiveDocument."+w.Objects[0].Inlist[0].Name+")") + elif Draft.isClone(obj,"Window"): + if obj.Objects[0].Inlist: + FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+obj.Name+",host=FreeCAD.ActiveDocument."+obj.Objects[0].Inlist[0].Name+")") FreeCAD.ActiveDocument.commitTransaction() class _Window(ArchComponent.Component):