Merge branch 'master' of ssh://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad
This commit is contained in:
commit
413437fd6b
|
@ -152,6 +152,7 @@ SET(FreeCADBase_XML_SRCS
|
|||
SOURCE_GROUP("XML" FILES ${FreeCADBase_XML_SRCS})
|
||||
|
||||
set(FreeCADBase_MOC_HDRS
|
||||
Debugger.h
|
||||
FutureWatcherProgress.h
|
||||
)
|
||||
fc_wrap_cpp(FreeCADBase_MOC_SRCS ${FreeCADBase_MOC_HDRS})
|
||||
|
@ -182,6 +183,7 @@ SET(FreeCADBase_CPP_SRCS
|
|||
BoundBoxPyImp.cpp
|
||||
Builder3D.cpp
|
||||
Console.cpp
|
||||
Debugger.cpp
|
||||
Exception.cpp
|
||||
Factory.cpp
|
||||
FileInfo.cpp
|
||||
|
@ -234,6 +236,7 @@ SET(FreeCADBase_HPP_SRCS
|
|||
BoundBox.h
|
||||
Builder3D.h
|
||||
Console.h
|
||||
Debugger.h
|
||||
Exception.h
|
||||
Factory.h
|
||||
FileInfo.h
|
||||
|
|
80
src/Base/Debugger.cpp
Normal file
80
src/Base/Debugger.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
/***************************************************************************
|
||||
* 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., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QCoreApplication>
|
||||
# include <QEvent>
|
||||
#endif
|
||||
|
||||
#include "Debugger.h"
|
||||
#include "Console.h"
|
||||
|
||||
using namespace Base;
|
||||
|
||||
Debugger::Debugger(QObject* parent)
|
||||
: QObject(parent), isAttached(false)
|
||||
{
|
||||
}
|
||||
|
||||
Debugger::~Debugger()
|
||||
{
|
||||
}
|
||||
|
||||
void Debugger::attach()
|
||||
{
|
||||
QCoreApplication::instance()->installEventFilter(this);
|
||||
isAttached = true;
|
||||
}
|
||||
|
||||
void Debugger::detach()
|
||||
{
|
||||
QCoreApplication::instance()->removeEventFilter(this);
|
||||
isAttached = false;
|
||||
}
|
||||
|
||||
bool Debugger::eventFilter(QObject*, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
if (loop.isRunning()) {
|
||||
loop.quit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int Debugger::exec()
|
||||
{
|
||||
if (isAttached)
|
||||
Base::Console().Message("TO CONTINUE PRESS ANY KEY...\n");
|
||||
return loop.exec();
|
||||
}
|
||||
|
||||
void Debugger::quit()
|
||||
{
|
||||
loop.quit();
|
||||
}
|
||||
|
||||
#include "moc_Debugger.cpp"
|
76
src/Base/Debugger.h
Normal file
76
src/Base/Debugger.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/***************************************************************************
|
||||
* 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., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BASE_DEBUGGER_H
|
||||
#define BASE_DEBUGGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QEventLoop>
|
||||
|
||||
namespace Base {
|
||||
/**
|
||||
This is a utility class to break the application at a point to inspect e.g. the result of
|
||||
an algorithm.
|
||||
You usually use it like this
|
||||
\code
|
||||
...
|
||||
Base::Debugger dbg;
|
||||
dbg.attach();
|
||||
dbg.exec();
|
||||
...
|
||||
\endcode
|
||||
Or you can connect it with a button and let the user click it in order to continue.
|
||||
\code
|
||||
QPushButton* btn = new QPushButton();
|
||||
btn->setText("Continue");
|
||||
btn->show();
|
||||
Base::Debugger dbg;
|
||||
connect(btn, SIGNAL(clicked()), &dbg, SLOT(quit()));
|
||||
dbg.exec();
|
||||
\endcode
|
||||
\author Werner Mayer
|
||||
*/
|
||||
class BaseExport Debugger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Debugger(QObject* parent=0);
|
||||
~Debugger();
|
||||
|
||||
void attach();
|
||||
void detach();
|
||||
bool eventFilter(QObject*, QEvent*);
|
||||
int exec();
|
||||
|
||||
public Q_SLOTS:
|
||||
void quit();
|
||||
|
||||
private:
|
||||
bool isAttached;
|
||||
QEventLoop loop;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BASE_DEBUGGER_H
|
|
@ -105,6 +105,8 @@
|
|||
// QtCore
|
||||
#include <QBuffer>
|
||||
#include <QByteArray>
|
||||
#include <QCoreApplication>
|
||||
#include <QEvent>
|
||||
#include <QIODevice>
|
||||
#include <QDataStream>
|
||||
#include <QWriteLocker>
|
||||
|
|
|
@ -1457,9 +1457,10 @@ namespace Gui {
|
|||
*/
|
||||
class GUIApplication : public GUIApplicationNativeEventAware
|
||||
{
|
||||
int systemExit;
|
||||
public:
|
||||
GUIApplication(int & argc, char ** argv)
|
||||
: GUIApplicationNativeEventAware(argc, argv)
|
||||
GUIApplication(int & argc, char ** argv, int exitcode)
|
||||
: GUIApplicationNativeEventAware(argc, argv), systemExit(exitcode)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1480,6 +1481,10 @@ public:
|
|||
else
|
||||
return QApplication::notify(receiver, event);
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
qApp->exit(systemExit);
|
||||
return true;
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("Unhandled Base::Exception caught in GUIApplication::notify.\n"
|
||||
"The error message is: %s\n", e.what());
|
||||
|
@ -1543,7 +1548,8 @@ void Application::runApplication(void)
|
|||
Base::Console().Log("Init: Creating Gui::Application and QApplication\n");
|
||||
// if application not yet created by the splasher
|
||||
int argc = App::Application::GetARGC();
|
||||
GUIApplication mainApp(argc, App::Application::GetARGV());
|
||||
int systemExit = 1000;
|
||||
GUIApplication mainApp(argc, App::Application::GetARGV(), systemExit);
|
||||
// set application icon and window title
|
||||
const std::map<std::string,std::string>& cfg = App::Application::Config();
|
||||
std::map<std::string,std::string>::const_iterator it;
|
||||
|
@ -1716,9 +1722,15 @@ void Application::runApplication(void)
|
|||
Base::Console().Log("Init: Entering event loop\n");
|
||||
|
||||
try {
|
||||
mainApp.exec();
|
||||
int ret = mainApp.exec();
|
||||
if (ret == systemExit)
|
||||
throw Base::SystemExitException();
|
||||
}
|
||||
catch(...) {
|
||||
catch (const Base::SystemExitException&) {
|
||||
Base::Console().Message("System exit\n");
|
||||
throw;
|
||||
}
|
||||
catch (...) {
|
||||
// catching nasty stuff coming out of the event loop
|
||||
App::Application::destructObserver();
|
||||
Base::Console().Error("Event loop left through unhandled exception\n");
|
||||
|
|
|
@ -281,6 +281,9 @@ void Command::invoke(int i)
|
|||
if (isActive())
|
||||
activated( i );
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
throw;
|
||||
}
|
||||
catch (Base::PyException &e) {
|
||||
e.ReportException();
|
||||
Base::Console().Error("Stack Trace: %s\n",e.getStackTrace().c_str());
|
||||
|
|
|
@ -66,10 +66,14 @@ void DlgSettingsViewColor::saveSettings()
|
|||
checkBoxSelection->onSave();
|
||||
HighlightColor->onSave();
|
||||
SelectionColor->onSave();
|
||||
CursorTextColor->onSave();
|
||||
EditedEdgeColor->onSave();
|
||||
EditedVertexColor->onSave();
|
||||
ConstructionColor->onSave();
|
||||
FullyConstrainedColor->onSave();
|
||||
DefaultShapeColor->onSave();
|
||||
DefaultShapeLineColor->onSave();
|
||||
DefaultShapeLineWidth->onSave();
|
||||
}
|
||||
|
||||
void DlgSettingsViewColor::loadSettings()
|
||||
|
@ -85,10 +89,14 @@ void DlgSettingsViewColor::loadSettings()
|
|||
checkBoxSelection->onRestore();
|
||||
HighlightColor->onRestore();
|
||||
SelectionColor->onRestore();
|
||||
CursorTextColor->onRestore();
|
||||
EditedEdgeColor->onRestore();
|
||||
EditedVertexColor->onRestore();
|
||||
ConstructionColor->onRestore();
|
||||
FullyConstrainedColor->onRestore();
|
||||
DefaultShapeColor->onRestore();
|
||||
DefaultShapeLineColor->onRestore();
|
||||
DefaultShapeLineWidth->onRestore();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>601</width>
|
||||
<height>407</height>
|
||||
<height>445</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -361,7 +361,20 @@
|
|||
<string>Default colors</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="colgridLayout">
|
||||
<item row="0" column="0">
|
||||
<item row="2" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QGridLayout" name="_2">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
|
@ -369,7 +382,7 @@
|
|||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
@ -382,28 +395,28 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Edited vertex color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Construction geometry</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Fully constrained geometry</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="ConstructionColor">
|
||||
<property name="toolTip">
|
||||
<string>The color of construction geometry in edit mode</string>
|
||||
|
@ -423,7 +436,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="FullyConstrainedColor">
|
||||
<property name="toolTip">
|
||||
<string>The color of fully constrained geometry in edit mode</string>
|
||||
|
@ -443,7 +456,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="EditedVertexColor">
|
||||
<property name="toolTip">
|
||||
<string>The color of vertices being edited</string>
|
||||
|
@ -463,7 +476,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="EditedEdgeColor">
|
||||
<property name="toolTip">
|
||||
<string>The color of edges being edited</string>
|
||||
|
@ -483,20 +496,124 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Cursor text color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="CursorTextColor">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CursorTextColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="_1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>240</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Default shape color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::PrefColorButton" name="DefaultShapeColor">
|
||||
<property name="toolTip">
|
||||
<string>The default color for new shapes</string>
|
||||
</property>
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>204</red>
|
||||
<green>204</green>
|
||||
<blue>204</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>DefaultShapeColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>182</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Default line width and color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="Gui::PrefColorButton" name="DefaultShapeLineColor">
|
||||
<property name="toolTip">
|
||||
<string>The default line color for new shapes</string>
|
||||
</property>
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>25</red>
|
||||
<green>25</green>
|
||||
<blue>25</blue>
|
||||
</color>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>DefaultShapeLineColor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::PrefSpinBox" name="DefaultShapeLineWidth">
|
||||
<property name="toolTip">
|
||||
<string>The default line thickness for new shapes</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>px</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>DefaultShapeLineWidth</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>View</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -509,6 +626,11 @@
|
|||
<extends>QPushButton</extends>
|
||||
<header>Gui/Widgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefColorButton</class>
|
||||
<extends>Gui::ColorButton</extends>
|
||||
|
@ -530,6 +652,11 @@
|
|||
<tabstop>checkBoxSelection</tabstop>
|
||||
<tabstop>HighlightColor</tabstop>
|
||||
<tabstop>SelectionColor</tabstop>
|
||||
<tabstop>CursorTextColor</tabstop>
|
||||
<tabstop>EditedEdgeColor</tabstop>
|
||||
<tabstop>EditedVertexColor</tabstop>
|
||||
<tabstop>ConstructionColor</tabstop>
|
||||
<tabstop>FullyConstrainedColor</tabstop>
|
||||
<tabstop>radioButtonSimple</tabstop>
|
||||
<tabstop>radioButtonGradient</tabstop>
|
||||
<tabstop>checkMidColor</tabstop>
|
||||
|
|
|
@ -187,6 +187,9 @@ bool Document::setEdit(Gui::ViewProvider* p, int ModNum)
|
|||
View3DInventor *activeView = dynamic_cast<View3DInventor *>(getActiveView());
|
||||
if (activeView && activeView->getViewer()->setEditingViewProvider(p,ModNum)) {
|
||||
d->_pcInEdit = p;
|
||||
Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
|
||||
if (dlg)
|
||||
dlg->setDocumentName(this->getDocument()->getName());
|
||||
if (d->_pcInEdit->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
|
||||
signalInEdit(*(static_cast<ViewProviderDocumentObject*>(d->_pcInEdit)));
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ void MacroManager::run(MacroType eType,const char *sName)
|
|||
Base::Interpreter().runFile(sName, this->localEnv);
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
qApp->quit();
|
||||
throw;
|
||||
}
|
||||
catch (const Base::PyException& e) {
|
||||
Base::Console().Error("%s%s: %s\n",
|
||||
|
|
|
@ -1157,8 +1157,7 @@ void MainWindow::delayedStartup()
|
|||
App::Application::processCmdLineFiles();
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
QApplication::quit();
|
||||
return;
|
||||
throw;
|
||||
}
|
||||
|
||||
const std::map<std::string,std::string>& cfg = App::Application::Config();
|
||||
|
|
|
@ -709,7 +709,7 @@ void PythonConsole::runSource(const QString& line)
|
|||
}
|
||||
if (ret == QMessageBox::Yes) {
|
||||
PyErr_Clear();
|
||||
qApp->quit();
|
||||
throw;
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
|
||||
const std::string& getDocumentName() const
|
||||
{ return documentName; }
|
||||
void setDocumentName(const std::string& doc)
|
||||
{ documentName = doc; }
|
||||
virtual bool isAllowedAlterDocument(void) const
|
||||
{ return false; }
|
||||
virtual bool isAllowedAlterView(void) const
|
||||
|
@ -94,6 +96,8 @@ protected:
|
|||
/// List of TaskBoxes of that dialog
|
||||
std::vector<QWidget*> Content;
|
||||
ButtonPosition pos;
|
||||
|
||||
private:
|
||||
std::string documentName;
|
||||
};
|
||||
|
||||
|
|
|
@ -63,14 +63,17 @@
|
|||
|
||||
using namespace Gui;
|
||||
|
||||
|
||||
PROPERTY_SOURCE(Gui::ViewProviderGeometryObject, Gui::ViewProviderDocumentObject)
|
||||
|
||||
const App::PropertyIntegerConstraint::Constraints intPercent = {0,100,1};
|
||||
|
||||
ViewProviderGeometryObject::ViewProviderGeometryObject() : pcBoundSwitch(0)
|
||||
{
|
||||
ADD_PROPERTY(ShapeColor,(0.8f,0.8f,0.8f));
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
unsigned long shcol = hGrp->GetUnsigned("DefaultShapeColor",3435973887UL); // light gray (204,204,204)
|
||||
float r,g,b;
|
||||
r = ((shcol >> 24) & 0xff) / 255.0; g = ((shcol >> 16) & 0xff) / 255.0; b = ((shcol >> 8) & 0xff) / 255.0;
|
||||
ADD_PROPERTY(ShapeColor,(r, g, b));
|
||||
ADD_PROPERTY(Transparency,(0));
|
||||
Transparency.setConstraints(&intPercent);
|
||||
App::Material mat(App::Material::DEFAULT);
|
||||
|
@ -86,7 +89,8 @@ ViewProviderGeometryObject::ViewProviderGeometryObject() : pcBoundSwitch(0)
|
|||
|
||||
pcShapeMaterial = new SoMaterial;
|
||||
pcShapeMaterial->ref();
|
||||
ShapeMaterial.touch();
|
||||
//ShapeMaterial.touch(); materials are rarely used, so better to initialize with default shape color
|
||||
ShapeColor.touch();
|
||||
|
||||
pcBoundingBox = new Gui::SoFCBoundingBox;
|
||||
pcBoundingBox->ref();
|
||||
|
|
|
@ -498,6 +498,8 @@ const char* ViewProviderPythonFeatureImp::getDefaultDisplayMode() const
|
|||
Py::Callable method(vp.getAttr(std::string("getDefaultDisplayMode")));
|
||||
Py::Tuple args(0);
|
||||
Py::String str(method.apply(args));
|
||||
if (str.isUnicode())
|
||||
str = str.encode("ascii"); // json converts strings into unicode
|
||||
mode = str.as_std_string();
|
||||
return mode.c_str();
|
||||
}
|
||||
|
|
|
@ -300,6 +300,9 @@ int main( int argc, char ** argv )
|
|||
else
|
||||
App::Application::runApplication();
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
exit(0);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
|
|
|
@ -43,6 +43,22 @@ def getStringList(objects):
|
|||
result += "]"
|
||||
return result
|
||||
|
||||
def getDefaultColor(objectType):
|
||||
'''getDefaultColor(string): returns a color value for the given object
|
||||
type (Wall, Structure, Window)'''
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
if objectType == "Wall":
|
||||
c = p.GetUnsigned("WallColor")
|
||||
elif objectType == "Structure":
|
||||
c = p.GetUnsigned("StructureColor")
|
||||
else:
|
||||
c = p.GetUnsigned("WindowsColor")
|
||||
r = float((c>>24)&0xFF)/255.0
|
||||
g = float((c>>16)&0xFF)/255.0
|
||||
b = float((c>>8)&0xFF)/255.0
|
||||
result = (r,g,b,1.0)
|
||||
return result
|
||||
|
||||
def addComponents(objectsList,host):
|
||||
'''addComponents(objectsList,hostObject): adds the given object or the objects
|
||||
from the given list as components to the given host Object. Use this for
|
||||
|
@ -278,7 +294,7 @@ def getCutVolume(cutplane,shapes):
|
|||
v = placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
|
||||
if not bb.isCutPlane(placement.Base,ax):
|
||||
print "No objects are cut by the plane"
|
||||
return None,None
|
||||
return None,None,None
|
||||
else:
|
||||
corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin),
|
||||
FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMin),
|
||||
|
@ -305,7 +321,44 @@ def getCutVolume(cutplane,shapes):
|
|||
cutface.Placement = placement
|
||||
cutnormal = DraftVecUtils.scaleTo(ax,wm)
|
||||
cutvolume = cutface.extrude(cutnormal)
|
||||
return cutface,cutvolume
|
||||
cutnormal = DraftVecUtils.neg(cutnormal)
|
||||
invcutvolume = cutface.extrude(cutnormal)
|
||||
return cutface,cutvolume,invcutvolume
|
||||
|
||||
def getShapeFromMesh(mesh):
|
||||
import Part, MeshPart
|
||||
if mesh.isSolid() and (mesh.countComponents() == 1):
|
||||
# use the best method
|
||||
faces = []
|
||||
for f in mesh.Facets:
|
||||
p=f.Points+[f.Points[0]]
|
||||
pts = []
|
||||
for pp in p:
|
||||
pts.append(FreeCAD.Vector(pp[0],pp[1],pp[2]))
|
||||
faces.append(Part.Face(Part.makePolygon(pts)))
|
||||
shell = Part.makeShell(faces)
|
||||
solid = Part.Solid(shell)
|
||||
solid = solid.removeSplitter()
|
||||
return solid
|
||||
|
||||
faces = []
|
||||
segments = mesh.getPlanarSegments(0.001) # use rather strict tolerance here
|
||||
for i in segments:
|
||||
if len(i) > 0:
|
||||
wires = MeshPart.wireFromSegment(mesh, i)
|
||||
if wires:
|
||||
faces.append(makeFace(wires))
|
||||
try:
|
||||
se = Part.makeShell(faces)
|
||||
except:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
solid = Part.Solid(se)
|
||||
except:
|
||||
return se
|
||||
else:
|
||||
return solid
|
||||
|
||||
|
||||
def meshToShape(obj,mark=True):
|
||||
|
@ -313,36 +366,18 @@ def meshToShape(obj,mark=True):
|
|||
mark is True (default), non-solid objects will be marked in red'''
|
||||
|
||||
name = obj.Name
|
||||
import Part, MeshPart, DraftGeomUtils
|
||||
if "Mesh" in obj.PropertiesList:
|
||||
faces = []
|
||||
mesh = obj.Mesh
|
||||
plac = obj.Placement
|
||||
segments = mesh.getPlanarSegments(0.001) # use rather strict tolerance here
|
||||
print len(segments)," segments ",segments
|
||||
for i in segments:
|
||||
print "treating",segments.index(i),i
|
||||
if len(i) > 0:
|
||||
wires = MeshPart.wireFromSegment(mesh, i)
|
||||
print "wire done"
|
||||
print wires
|
||||
if wires:
|
||||
faces.append(makeFace(wires))
|
||||
print "done facing"
|
||||
print "faces",faces
|
||||
|
||||
try:
|
||||
se = Part.makeShell(faces)
|
||||
solid = Part.Solid(se)
|
||||
except:
|
||||
raise
|
||||
else:
|
||||
if solid.isClosed():
|
||||
solid = getShapeFromMesh(mesh)
|
||||
if solid:
|
||||
if solid.isClosed() and solid.isValid():
|
||||
FreeCAD.ActiveDocument.removeObject(name)
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
|
||||
newobj.Shape = solid
|
||||
newobj.Placement = plac
|
||||
if not solid.isClosed():
|
||||
if (not solid.isClosed()) or (not solid.isValid()):
|
||||
if mark:
|
||||
newobj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0)
|
||||
return newobj
|
||||
|
@ -428,8 +463,8 @@ def download(url):
|
|||
else:
|
||||
return filepath
|
||||
|
||||
def check(objectslist,includehidden=True):
|
||||
"""check(objectslist,includehidden=True): checks if the given objects contain only solids"""
|
||||
def check(objectslist,includehidden=False):
|
||||
"""check(objectslist,includehidden=False): checks if the given objects contain only solids"""
|
||||
objs = Draft.getGroupContents(objectslist)
|
||||
if not includehidden:
|
||||
objs = Draft.removeHidden(objs)
|
||||
|
@ -439,11 +474,11 @@ def check(objectslist,includehidden=True):
|
|||
bad.append([o,"is not a Part-based object"])
|
||||
else:
|
||||
s = o.Shape
|
||||
if not s.isClosed():
|
||||
if (not s.isClosed()) and (not (Draft.getType(o) == "Axis")):
|
||||
bad.append([o,"is not closed"])
|
||||
elif not s.isValid():
|
||||
bad.append([o,"is not valid"])
|
||||
elif not s.Solids:
|
||||
elif (not s.Solids) and (not (Draft.getType(o) == "Axis")):
|
||||
bad.append([o,"doesn't contain any solid"])
|
||||
else:
|
||||
f = 0
|
||||
|
|
|
@ -184,12 +184,14 @@ class _ArchDrawingView:
|
|||
def __init__(self, obj):
|
||||
obj.addProperty("App::PropertyLink","Source","Base","The linked object")
|
||||
obj.addProperty("App::PropertyEnumeration","RenderingMode","Drawing View","The rendering mode to use")
|
||||
obj.addProperty("App::PropertyBool","ShowCut","Drawing View","If cut geometry is shown or not")
|
||||
obj.addProperty("App::PropertyFloat","LineWidth","Drawing View","The line width of the rendered objects")
|
||||
obj.RenderingMode = ["Solid","Wireframe"]
|
||||
obj.RenderingMode = "Wireframe"
|
||||
obj.LineWidth = 0.35
|
||||
obj.ShowCut = False
|
||||
obj.Proxy = self
|
||||
self.Type = "DrawingView"
|
||||
self.Type = "ArchSectionView"
|
||||
|
||||
def execute(self, obj):
|
||||
if obj.Source:
|
||||
|
@ -199,6 +201,40 @@ class _ArchDrawingView:
|
|||
if prop in ["Source","RenderingMode"]:
|
||||
obj.ViewResult = self.updateSVG(obj)
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self,state):
|
||||
return None
|
||||
|
||||
def getDisplayModes(self,vobj):
|
||||
modes=["Default"]
|
||||
return modes
|
||||
|
||||
def setDisplayMode(self,mode):
|
||||
return mode
|
||||
|
||||
def getFlatShape(self):
|
||||
"returns a flat shape representation of the view"
|
||||
if hasattr(self,"baseshape"):
|
||||
import Drawing
|
||||
[V0,V1,H0,H1] = Drawing.project(self.baseshape,self.direction)
|
||||
return V0.Edges+V1.Edges
|
||||
else:
|
||||
print "No shape has been computed yet"
|
||||
return None
|
||||
|
||||
def getDXF(self):
|
||||
"returns a flat shape representation of the view"
|
||||
if hasattr(self,"baseshape"):
|
||||
import Drawing
|
||||
[V0,V1,H0,H1] = Drawing.project(self.baseshape,self.direction)
|
||||
DxfOutput = Drawing.projectToDXF(self.baseshape,self.direction)
|
||||
return DxfOutput
|
||||
else:
|
||||
print "No shape has been computed yet"
|
||||
return None
|
||||
|
||||
def updateSVG(self, obj,join=False):
|
||||
"encapsulates a svg fragment into a transformation node"
|
||||
import Part, DraftGeomUtils
|
||||
|
@ -209,6 +245,9 @@ class _ArchDrawingView:
|
|||
objs = Draft.removeHidden(objs)
|
||||
svg = ''
|
||||
|
||||
st = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("CutLineThickness")
|
||||
if not st: st = 2
|
||||
|
||||
# generating SVG
|
||||
linewidth = obj.LineWidth/obj.Scale
|
||||
if obj.RenderingMode == "Solid":
|
||||
|
@ -217,42 +256,74 @@ class _ArchDrawingView:
|
|||
render = ArchVRM.Renderer()
|
||||
render.setWorkingPlane(obj.Source.Placement)
|
||||
render.addObjects(Draft.getGroupContents(objs,walls=True))
|
||||
render.cut(obj.Source.Shape)
|
||||
render.cut(obj.Source.Shape,obj.ShowCut)
|
||||
svg += render.getViewSVG(linewidth=linewidth)
|
||||
svg += render.getSectionSVG(linewidth=linewidth*2)
|
||||
svg += render.getSectionSVG(linewidth=linewidth*st)
|
||||
if obj.ShowCut:
|
||||
svg += render.getHiddenSVG(linewidth=linewidth)
|
||||
# print render.info()
|
||||
|
||||
else:
|
||||
# render using the Drawing module
|
||||
import Drawing, Part
|
||||
shapes = []
|
||||
hshapes = []
|
||||
sshapes = []
|
||||
p = FreeCAD.Placement(obj.Source.Placement)
|
||||
direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
|
||||
self.direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
|
||||
for o in objs:
|
||||
if o.isDerivedFrom("Part::Feature"):
|
||||
shapes.extend(o.Shape.Solids)
|
||||
cutface,cutvolume = ArchCommands.getCutVolume(obj.Source.Shape.copy(),shapes)
|
||||
if o.Shape.isValid():
|
||||
shapes.extend(o.Shape.Solids)
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning("Skipping invalid object: "+o.Name)
|
||||
cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(obj.Source.Shape.copy(),shapes)
|
||||
if cutvolume:
|
||||
nsh = []
|
||||
for sh in shapes:
|
||||
for sol in sh.Solids:
|
||||
c = sol.cut(cutvolume)
|
||||
nsh.append(c)
|
||||
s = sol.section(cutface)
|
||||
nsh.extend(c.Solids)
|
||||
sshapes.append(s)
|
||||
if obj.ShowCut:
|
||||
c = sol.cut(invcutvolume)
|
||||
hshapes.append(c)
|
||||
shapes = nsh
|
||||
base = Part.makeCompound(shapes)
|
||||
#if shapes:
|
||||
# base = shapes.pop().copy()
|
||||
#for sh in shapes:
|
||||
# try:
|
||||
# base = base.fuse(sh)
|
||||
# except:
|
||||
# print "unable to fuse, passing..."
|
||||
svgf = Drawing.projectToSVG(base,direction)
|
||||
if shapes:
|
||||
self.shapes = shapes
|
||||
self.baseshape = Part.makeCompound(shapes)
|
||||
svgf = Drawing.projectToSVG(self.baseshape,self.direction)
|
||||
if svgf:
|
||||
svgf = svgf.replace('stroke-width="0.35"','stroke-width="' + str(linewidth) + 'px"')
|
||||
svgf = svgf.replace('stroke-width="1"','stroke-width="' + str(linewidth) + 'px"')
|
||||
svgf = svgf.replace('stroke-width:0.01','stroke-width:' + str(linewidth) + 'px')
|
||||
svg += svgf
|
||||
svg += svgf
|
||||
if hshapes:
|
||||
hshapes = Part.makeCompound(hshapes)
|
||||
svgh = Drawing.projectToSVG(hshapes,self.direction)
|
||||
if svgh:
|
||||
svgh = svgh.replace('stroke-width="0.35"','stroke-width="' + str(linewidth) + 'px"')
|
||||
svgh = svgh.replace('stroke-width="1"','stroke-width="' + str(linewidth) + 'px"')
|
||||
svgh = svgh.replace('stroke-width:0.01','stroke-width:' + str(linewidth) + 'px')
|
||||
svgh = svgh.replace('fill="none"','fill="none"\nstroke-dasharray="0.09,0.05"')
|
||||
svg += svgh
|
||||
if sshapes:
|
||||
edges = []
|
||||
for s in sshapes:
|
||||
edges.extend(s.Edges)
|
||||
wires = DraftGeomUtils.findWires(edges)
|
||||
faces = []
|
||||
for w in wires:
|
||||
if (w.ShapeType == "Wire") and w.isClosed():
|
||||
faces.append(Part.Face(w))
|
||||
sshapes = Part.makeCompound(faces)
|
||||
svgs = Drawing.projectToSVG(sshapes,self.direction)
|
||||
if svgs:
|
||||
svgs = svgs.replace('stroke-width="0.35"','stroke-width="' + str(linewidth*st) + 'px"')
|
||||
svgs = svgs.replace('stroke-width="1"','stroke-width="' + str(linewidth*st) + 'px"')
|
||||
svgs = svgs.replace('stroke-width:0.01','stroke-width:' + str(linewidth*st) + 'px')
|
||||
svg += svgs
|
||||
|
||||
result = ''
|
||||
result += '<g id="' + obj.Name + '"'
|
||||
|
|
|
@ -44,12 +44,7 @@ def makeStructure(baseobj=None,length=1,width=1,height=1,name=str(translate("Arc
|
|||
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
|
||||
g = float((c>>16)&0xFF)/255.0
|
||||
b = float((c>>8)&0xFF)/255.0
|
||||
obj.ViewObject.ShapeColor = (r,g,b,1.0)
|
||||
obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Structure")
|
||||
return obj
|
||||
|
||||
def makeStructuralSystem(objects,axes):
|
||||
|
@ -171,7 +166,13 @@ class _Structure(ArchComponent.Component):
|
|||
elif (len(base.Wires) == 1):
|
||||
if base.Wires[0].isClosed():
|
||||
base = Part.Face(base.Wires[0])
|
||||
base = base.extrude(normal)
|
||||
base = base.extrude(normal)
|
||||
elif obj.Base.isDerivedFrom("Mesh::Feature"):
|
||||
if obj.Base.Mesh.isSolid():
|
||||
if obj.Base.Mesh.countComponents() == 1:
|
||||
sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
|
||||
if sh.isClosed() and sh.isValid() and sh.Solids:
|
||||
base = sh
|
||||
else:
|
||||
if obj.Normal == Vector(0,0,0):
|
||||
normal = Vector(0,0,1)
|
||||
|
@ -221,7 +222,12 @@ class _Structure(ArchComponent.Component):
|
|||
# finalizing
|
||||
else:
|
||||
if base:
|
||||
if not base.isNull():
|
||||
if base.isValid() and (not base.isNull()) and base.Solids:
|
||||
if base.Volume < 0:
|
||||
base.reverse()
|
||||
if base.Volume < 0:
|
||||
FreeCAD.Console.PrintError(str(translate("Arch","Couldn't compute the wall shape")))
|
||||
return
|
||||
base = base.removeSplitter()
|
||||
obj.Shape = base
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
|
|
|
@ -25,12 +25,13 @@
|
|||
|
||||
import FreeCAD,math,Part,ArchCommands,DraftVecUtils,DraftGeomUtils
|
||||
|
||||
DEBUG = True # if we want debug messages
|
||||
MAXLOOP = 10 # the max number of loop before abort
|
||||
|
||||
# WARNING: in this module, faces are lists whose first item is the actual OCC face, the
|
||||
# other items being additional information such as color, etc.
|
||||
|
||||
DEBUG = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ShowVRMDebug")
|
||||
|
||||
class Renderer:
|
||||
"A renderer object"
|
||||
def __init__(self,wp=None):
|
||||
|
@ -73,6 +74,7 @@ class Renderer:
|
|||
self.iscut = False
|
||||
self.joined = False
|
||||
self.sections = []
|
||||
self.hiddenEdges = []
|
||||
|
||||
def setWorkingPlane(self,wp):
|
||||
"sets a Draft WorkingPlane or Placement for this renderer"
|
||||
|
@ -151,6 +153,8 @@ class Renderer:
|
|||
self.faces = [self.projectFace(f) for f in self.faces]
|
||||
if self.sections:
|
||||
self.sections = [self.projectFace(f) for f in self.sections]
|
||||
if self.hiddenEdges:
|
||||
self.hiddenEdges = [self.projectEdge(e) for e in self.hiddenEdges]
|
||||
self.oriented = True
|
||||
#print "VRM: end reorient"
|
||||
|
||||
|
@ -200,6 +204,14 @@ class Renderer:
|
|||
#print "VRM: projectFace end: ",len(sh.Vertexes)," verts"
|
||||
return [sh]+face[1:]
|
||||
|
||||
def projectEdge(self,edge):
|
||||
"projects a single edge on the WP"
|
||||
if len(edge.Vertexes) > 1:
|
||||
v1 = self.wp.getLocalCoords(edge.Vertexes[0].Point)
|
||||
v2 = self.wp.getLocalCoords(edge.Vertexes[-1].Point)
|
||||
return Part.Line(v1,v2).toShape()
|
||||
return edge
|
||||
|
||||
def flattenFace(self,face):
|
||||
"Returns a face where all vertices have Z = 0"
|
||||
wires = []
|
||||
|
@ -219,7 +231,7 @@ class Renderer:
|
|||
else:
|
||||
return [sh]+face[1:]
|
||||
|
||||
def cut(self,cutplane):
|
||||
def cut(self,cutplane,hidden=False):
|
||||
"Cuts through the shapes with a given cut plane and builds section faces"
|
||||
if DEBUG: print "\n\n======> Starting cut\n\n"
|
||||
if self.iscut:
|
||||
|
@ -231,7 +243,7 @@ class Renderer:
|
|||
shps = []
|
||||
for sh in self.shapes:
|
||||
shps.append(sh[0])
|
||||
cutface,cutvolume = ArchCommands.getCutVolume(cutplane,shps)
|
||||
cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(cutplane,shps)
|
||||
if cutface and cutvolume:
|
||||
shapes = []
|
||||
faces = []
|
||||
|
@ -246,6 +258,9 @@ class Renderer:
|
|||
if DraftGeomUtils.isCoplanar([f,cutface]):
|
||||
print "COPLANAR"
|
||||
sections.append([f,fill])
|
||||
if hidden:
|
||||
c = sol.cut(invcutvolume)
|
||||
self.hiddenEdges.extend(c.Edges)
|
||||
self.shapes = shapes
|
||||
self.faces = faces
|
||||
self.sections = sections
|
||||
|
@ -555,7 +570,8 @@ class Renderer:
|
|||
v = e.Vertexes[-1].Point
|
||||
svg += 'A '+ tostr(r) + ' '+ tostr(r) +' 0 0 1 '+ tostr(v.x) +' '
|
||||
svg += tostr(v.y) + ' '
|
||||
svg += 'Z '
|
||||
if len(edges) > 1:
|
||||
svg += 'Z '
|
||||
return svg
|
||||
|
||||
def getViewSVG(self,linewidth=0.01):
|
||||
|
@ -608,4 +624,25 @@ class Renderer:
|
|||
svg += 'fill-rule: evenodd'
|
||||
svg += '"/>\n'
|
||||
return svg
|
||||
|
||||
def getHiddenSVG(self,linewidth=0.02):
|
||||
"Returns a SVG fragment from cut geometry"
|
||||
if DEBUG: print "Printing ", len(self.sections), " hidden faces"
|
||||
if not self.oriented:
|
||||
self.reorient()
|
||||
svg = ''
|
||||
for e in self.hiddenEdges:
|
||||
svg +='<path '
|
||||
svg += 'd="'
|
||||
svg += self.getPathData(e)
|
||||
svg += '" '
|
||||
svg += 'stroke="#000000" '
|
||||
svg += 'stroke-width="' + str(linewidth) + '" '
|
||||
svg += 'style="stroke-width:' + str(linewidth) + ';'
|
||||
svg += 'stroke-miterlimit:1;'
|
||||
svg += 'stroke-linejoin:round;'
|
||||
svg += 'stroke-dasharray:0.09,0.05;'
|
||||
svg += 'fill:none;'
|
||||
svg += '"/>\n'
|
||||
return svg
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils
|
||||
import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils,ArchCommands
|
||||
from FreeCAD import Vector
|
||||
from PyQt4 import QtCore
|
||||
from DraftTools import translate
|
||||
|
@ -37,17 +37,16 @@ def makeWall(baseobj=None,width=None,height=None,align="Center",name=str(transla
|
|||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
|
||||
_Wall(obj)
|
||||
_ViewProviderWall(obj.ViewObject)
|
||||
if baseobj: obj.Base = baseobj
|
||||
if width: obj.Width = width
|
||||
if height: obj.Height = height
|
||||
if baseobj:
|
||||
obj.Base = baseobj
|
||||
if width:
|
||||
obj.Width = width
|
||||
if height:
|
||||
obj.Height = height
|
||||
obj.Align = align
|
||||
if obj.Base: obj.Base.ViewObject.hide()
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
c = p.GetUnsigned("WallColor")
|
||||
r = float((c>>24)&0xFF)/255.0
|
||||
g = float((c>>16)&0xFF)/255.0
|
||||
b = float((c>>8)&0xFF)/255.0
|
||||
obj.ViewObject.ShapeColor = (r,g,b,1.0)
|
||||
if obj.Base:
|
||||
obj.Base.ViewObject.hide()
|
||||
obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Wall")
|
||||
return obj
|
||||
|
||||
def joinWalls(walls):
|
||||
|
@ -357,7 +356,7 @@ class _Wall(ArchComponent.Component):
|
|||
# computing shape
|
||||
base = None
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
if not obj.Base.Shape.isNull():
|
||||
if obj.Base.Shape.isValid() and (not obj.Base.Shape.isNull()):
|
||||
base = obj.Base.Shape.copy()
|
||||
if base.Solids:
|
||||
pass
|
||||
|
@ -380,9 +379,21 @@ class _Wall(ArchComponent.Component):
|
|||
if sh:
|
||||
base = sh
|
||||
else:
|
||||
base = None
|
||||
FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object")))
|
||||
|
||||
elif obj.Base.isDerivedFrom("Mesh::Feature"):
|
||||
if obj.Base.Mesh.isSolid():
|
||||
if obj.Base.Mesh.countComponents() == 1:
|
||||
sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
|
||||
if sh.isClosed() and sh.isValid() and sh.Solids and (not sh.isNull()):
|
||||
base = sh
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning("This mesh is an invalid solid")
|
||||
obj.Base.ViewObject.show()
|
||||
|
||||
if base:
|
||||
|
||||
for app in obj.Additions:
|
||||
if Draft.getType(app) == "Window":
|
||||
# window
|
||||
|
@ -418,7 +429,12 @@ class _Wall(ArchComponent.Component):
|
|||
base = base.cut(hole.Shape)
|
||||
hole.ViewObject.hide() # to be removed
|
||||
|
||||
if not base.isNull():
|
||||
if base.isValid() and (not base.isNull()) and base.Solids:
|
||||
if base.Volume < 0:
|
||||
base.reverse()
|
||||
if base.Volume < 0:
|
||||
FreeCAD.Console.PrintError(str(translate("Arch","Couldn't compute the wall shape")))
|
||||
return
|
||||
try:
|
||||
base = base.removeSplitter()
|
||||
except:
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils
|
||||
import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils,ArchCommands
|
||||
from FreeCAD import Vector
|
||||
from PyQt4 import QtCore,QtGui
|
||||
from DraftTools import translate
|
||||
|
@ -49,12 +49,7 @@ def makeWindow(baseobj=None,width=None,name=str(translate("Arch","Window"))):
|
|||
if obj.Base:
|
||||
obj.Base.ViewObject.DisplayMode = "Wireframe"
|
||||
obj.Base.ViewObject.hide()
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
c = p.GetUnsigned("WindowColor")
|
||||
r = float((c>>24)&0xFF)/255.0
|
||||
g = float((c>>16)&0xFF)/255.0
|
||||
b = float((c>>8)&0xFF)/255.0
|
||||
obj.ViewObject.ShapeColor = (r,g,b,1.0)
|
||||
obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Window")
|
||||
return obj
|
||||
|
||||
def makeDefaultWindowPart(obj):
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
# Resource object code
|
||||
#
|
||||
# Created: Sun Jul 22 16:38:54 2012
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.1)
|
||||
# Created: Sun Aug 5 16:52:51 2012
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.2)
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
|
@ -6042,85 +6042,100 @@ qt_resource_data = "\
|
|||
\x00\x00\x00\x12\x00\x57\x00\x65\x00\x72\x00\x6b\x00\x7a\x00\x65\
|
||||
\x00\x75\x00\x67\x00\x65\x08\x00\x00\x00\x00\x06\x00\x00\x00\x05\
|
||||
\x54\x6f\x6f\x6c\x73\x07\x00\x00\x00\x04\x61\x72\x63\x68\x01\
|
||||
\x00\x00\x04\xd0\
|
||||
\x00\x00\x05\xb5\
|
||||
\x00\
|
||||
\x00\x1e\xaa\x78\x9c\xed\x59\x6d\x6f\xdb\x36\x10\xfe\x9e\x5f\x41\
|
||||
\xe8\xd3\x06\x6c\x95\xed\xd8\x6e\x13\xc8\x2a\xd6\x74\x79\x01\x5a\
|
||||
\x2c\x81\xd3\xe6\xe3\x20\x4b\x67\x8b\xab\x24\x7a\x24\x95\xd8\xfd\
|
||||
\xf5\x3d\x92\x92\x65\xbd\x58\x89\x63\x27\x01\x82\x00\x31\x22\xf2\
|
||||
\x4e\xc7\xe3\xc3\xe3\xa3\x3b\xd2\xf9\xb8\x88\x23\x72\x0b\x5c\x50\
|
||||
\x96\x8c\xac\xee\xbb\x8e\x45\x20\xf1\x59\x40\x93\xd9\xc8\xfa\x76\
|
||||
\x7d\xfa\xe7\x07\xeb\xa3\x7b\xe0\xa4\xb4\x50\xea\xa3\x92\x7b\x40\
|
||||
\x1c\x3f\xf2\x84\x70\xcf\x52\x7a\x7c\xfc\x99\x7a\x11\x9b\xe1\xff\
|
||||
\x68\x36\x06\x29\xf1\x65\xf1\x17\xf7\x43\xc7\x36\x3a\xa8\x7c\x47\
|
||||
\x83\x19\x48\xa2\xdb\x23\xeb\xea\x46\x37\x2d\x92\x78\x31\x8c\xac\
|
||||
\x36\x1b\x6a\x28\xe2\xcc\x39\x9b\x03\x97\xcb\xec\x85\x19\xb0\x18\
|
||||
\x24\x5f\x6a\x21\x71\x38\xf8\x52\x3f\x11\x67\xe1\x76\x1c\x7b\x91\
|
||||
\x35\x96\xaa\xb1\xcc\x1a\xe8\x81\x0c\xdd\xc1\xfb\x81\x63\x9b\x47\
|
||||
\xd3\x1d\x02\x9d\x85\xd2\x1d\xf6\x8e\x1c\x3b\x7b\xd6\x36\xed\xdc\
|
||||
\xa8\x63\xe7\x83\x37\x79\x72\x47\x93\x80\xdd\x5d\x53\x19\x41\xe6\
|
||||
\x8c\x90\x1c\x7d\x77\xcf\x20\x01\xee\x45\x44\x64\x73\x71\xec\x4c\
|
||||
\x50\x37\x19\x79\x4b\x96\x16\xd8\x7c\xff\xc4\x16\x5f\x74\x57\x66\
|
||||
\xb1\x32\xa4\x98\x7b\x3e\x1a\xb2\xb2\x09\x24\x69\x3c\x01\xee\x0e\
|
||||
\x1d\x3b\x7b\x32\xee\xaf\x8f\x50\x33\x11\x7b\x7c\x46\x93\x8a\x85\
|
||||
\xa3\x56\x0b\x54\x42\x5c\x20\xb9\xbe\x96\x67\x9c\xa5\x73\xf4\x39\
|
||||
\x5f\xcd\x59\xde\x36\xea\xb5\xc1\x65\x01\x56\x03\x5e\x6a\xcd\xc9\
|
||||
\xb8\x01\xb4\xba\x4f\xad\xd0\x65\x83\x61\xd4\x4a\xea\x7b\x91\xe9\
|
||||
\xfd\xb7\x57\x8c\x5b\x4c\xa8\xc1\xd0\x79\xcd\x50\xc8\x38\xfd\xc9\
|
||||
\x12\xd9\x60\xaa\x6a\xac\x0e\xd1\x17\x6f\x02\x51\x6e\x29\x52\x8d\
|
||||
\xd2\xeb\x0d\x18\xc1\x42\x96\x14\x56\x38\x7d\x86\xa9\x97\x46\x68\
|
||||
\x9a\x45\x8c\x93\x29\xfe\xee\xbc\x28\xaa\x22\xd5\x0c\x97\xe9\x34\
|
||||
\xbe\xad\x39\x6f\x97\xbd\xaf\x4d\x46\x05\x1c\xf0\x1a\x0e\x63\xdd\
|
||||
\xdd\x3a\x0d\xd4\x05\x54\x95\xc8\x1b\x95\xd9\x00\x86\x9a\x7b\x25\
|
||||
\x8f\x8f\xcf\x57\xf6\x1c\x5b\x77\xde\x37\x81\xfa\x7e\xa0\x3f\xe1\
|
||||
\x9c\x26\xb8\x52\x42\x06\xb8\xdd\x46\x56\xa7\x0a\x1d\x6a\x94\x7a\
|
||||
\x72\x36\xe8\x77\x4a\x64\xb0\x92\x66\x44\xd0\xeb\x94\x38\xa1\x70\
|
||||
\xab\x6a\x70\x03\xd2\x06\xb8\x2d\x90\x2e\x87\x8d\xa6\xc5\x4b\x0e\
|
||||
\xd3\x13\xb5\xd6\x9f\x52\x29\x11\xc6\x7c\x93\x29\xd9\x1c\x65\x3a\
|
||||
\x0e\x26\x46\xd6\x1a\x51\x8c\x45\xd7\x74\xde\x1c\x54\xd7\x21\x15\
|
||||
\x04\xff\x64\x08\x24\xa8\x05\x58\x02\x77\xe4\x06\x83\x8c\xb0\xc9\
|
||||
\x7f\x48\x8a\x0f\x8f\xb5\x9a\x13\xda\x66\xc5\x05\xdd\x57\xc1\x9f\
|
||||
\x43\xe0\xf6\x06\x03\x45\xc2\x41\x45\x34\xe3\x00\x89\xdb\x3d\xc2\
|
||||
\xa5\x31\x8f\x65\xf1\x24\x4a\xc1\xed\xbe\x47\xa9\x7e\x2a\x2f\x5b\
|
||||
\x6d\xa8\x87\x79\xad\x60\xfe\x3b\x51\x9f\x9b\x8d\x11\xe6\x67\x88\
|
||||
\x28\x98\xf4\x6a\xe1\x60\x8f\x05\x49\x0d\x77\xe9\xc9\xf0\xfe\xd1\
|
||||
\xbe\xb2\xc0\xce\xbe\xb3\xfb\xda\xfd\x8e\x6d\x98\x70\x45\x93\x25\
|
||||
\xf1\xae\xa4\xb9\x13\x65\xee\x8d\x30\x51\x90\xfa\x32\xe5\xf0\x72\
|
||||
\xac\x79\x0f\xfd\xbf\xf1\xe6\x73\xf2\xe6\x7d\xdf\xe2\xdd\x98\x73\
|
||||
\x9c\x47\xdb\xf3\xd2\x67\x77\xd0\x69\xa1\xcf\xe1\x51\x1b\x7d\x7e\
|
||||
\x18\xbe\x10\x7d\xae\xb0\x7a\xe3\xd0\xcd\x89\xe7\x70\xb7\xc4\x73\
|
||||
\xb0\xbf\xc4\x53\xd7\x3e\x2f\x48\xa2\xfd\x37\x12\xdd\x8c\xf5\x73\
|
||||
\x93\xe8\x61\xeb\x62\x6c\x43\x5d\x83\xa3\x16\xe6\x3a\xec\xb5\x31\
|
||||
\x57\xff\xa5\x98\xeb\x46\xef\x85\xd7\x4b\x5b\x65\x61\xc9\xd6\x9a\
|
||||
\xde\x23\x4e\x09\x8a\x8f\xef\xc3\xce\x09\x2e\x4e\x4f\x08\x8d\xe7\
|
||||
\x8c\xcb\x7d\x1f\x0e\xec\xef\x68\x60\xf0\x70\x86\x2e\xb6\x59\x08\
|
||||
\xfe\x8f\x75\x7c\x56\x7b\x4c\x09\x26\xc5\x71\x4a\x33\x56\x6d\x39\
|
||||
\xca\xc5\x14\xd3\x13\x93\xa6\x68\x63\x10\xfc\xa1\xf3\x15\x84\xf2\
|
||||
\x9f\x39\x24\xe3\x10\xb0\xb6\x33\x98\x82\x62\x75\x6c\x4d\x80\xa4\
|
||||
\x42\xe9\x61\x3d\xc3\x90\xe7\x67\x44\xb2\x4c\x85\xc4\x8c\xeb\x77\
|
||||
\x89\x5c\xce\xb7\x48\xa1\xb7\xf8\xd4\x7c\x13\x55\xe7\xa6\xc4\xbb\
|
||||
\xf5\x28\x7e\xc0\x22\x78\xfc\x80\x5b\x6c\x67\x9c\xfc\xc5\xd4\x5f\
|
||||
\x39\xf0\x2a\xb7\xf4\xee\x71\x7e\xf8\x14\x71\xbe\x4b\x36\x7e\xc2\
|
||||
\xc1\x93\x20\x88\x26\x17\xa1\x93\x14\xf0\xfc\xd0\x1c\x2a\x9a\xf4\
|
||||
\x5b\x47\xed\x53\x04\xad\x26\x38\xcc\x8e\x70\x93\x24\x98\x77\x08\
|
||||
\x32\x59\xee\xba\x43\xb6\x08\x58\x5f\xcf\x1c\x63\x56\xbb\x21\xde\
|
||||
\x02\xb6\x31\x60\xfb\x4f\x12\xb0\xed\x99\xcf\xe6\x88\xb9\x30\x7c\
|
||||
\x3a\x4d\x79\x42\x75\x81\xf8\x9b\xef\x25\x24\xf6\x7e\x80\xa6\xe7\
|
||||
\x98\x05\x10\x91\x10\xbc\xdb\xe5\xef\xcf\x12\x43\x86\xdf\x31\x86\
|
||||
\x4e\x73\x8f\x5e\x65\x18\x6d\x9f\xca\x94\xaa\x90\x3c\x69\x28\x1f\
|
||||
\x7f\x3f\xa4\xf8\x28\xea\x8e\xef\x99\x8d\x52\xd5\x51\x4f\x60\xb6\
|
||||
\xa8\x35\xca\x65\x46\x56\x61\xf4\x6a\x15\x46\x5e\x5c\xf4\x6b\xc5\
|
||||
\x45\xa9\xae\xa8\xba\x52\xaa\x26\x0a\x90\xd6\x90\x5c\x83\x31\xdb\
|
||||
\x97\xf9\x69\x48\x76\x5d\x35\xb2\x86\x16\x31\xf7\x4e\x23\xab\xdb\
|
||||
\xb5\x6c\xa5\x39\xa7\x8b\xd8\x9b\x4f\xd3\xc4\x57\x40\xb9\xff\x5f\
|
||||
\xea\xf6\x29\x67\xf1\x57\x1a\xc3\x98\xa5\xdc\xc7\x18\xac\x68\xa9\
|
||||
\xab\xc7\x54\x48\x16\x9b\x11\x85\xf6\x64\xbd\xc7\x78\xb9\x76\x3d\
|
||||
\xb9\x56\xc2\x14\x57\x92\x6a\x3d\x16\x12\x92\x40\xb8\x57\x97\xa9\
|
||||
\x08\x73\x79\xde\x79\x60\xe0\xf2\x02\x9c\x36\x5a\xb1\xcd\x95\xa5\
|
||||
\x78\x17\x2a\xe4\x74\xaf\x46\xa0\x3a\x70\xbb\x27\x95\x82\xaa\xd1\
|
||||
\x9b\xba\xcb\x9b\x5c\x52\xd6\xf6\xe7\x56\xc6\x73\xcd\x08\x15\xd2\
|
||||
\xdd\x9d\x29\x77\xe8\xeb\x61\x0e\x42\x2f\xb6\xd0\x61\xe1\xb3\x24\
|
||||
\x01\xbd\xd8\xaa\xed\xd8\x29\x75\x0f\x7e\x01\x09\x6b\xe1\xfc\
|
||||
\x00\x27\xfd\x78\x9c\xed\x5a\x6d\x4f\xe3\x38\x10\xfe\xce\xaf\xb0\
|
||||
\xf2\xe9\x4e\xba\x23\xa5\x50\x58\x50\x9a\xd5\x2d\x1c\x0b\xd2\xae\
|
||||
\x8e\xbd\xb2\xbb\x1f\x4f\x69\x32\x6d\x7c\x9b\xd8\x39\xc7\xa1\xed\
|
||||
\xfe\xfa\x1b\xdb\x49\xd3\xbc\x34\x50\x5a\x40\x42\x20\x10\xb1\xc7\
|
||||
\x9d\x19\x3f\x9e\x79\x3c\x76\xe3\xbc\x9f\xc7\x11\xb9\x03\x91\x52\
|
||||
\xce\x86\xd6\xc1\x7e\xcf\x22\xc0\x7c\x1e\x50\x36\x1d\x5a\x5f\x6f\
|
||||
\x2f\x7f\x7f\x67\xbd\x77\xf7\x9c\x8c\x96\x83\x8e\x70\x90\xbb\x47\
|
||||
\x1c\x3f\xf2\xd2\xd4\xfd\x98\xd1\xb3\xb3\x0b\xea\x45\x7c\x8a\xff\
|
||||
\xa3\xe9\x08\xa4\xc4\x0f\xa7\x7f\x08\x3f\x74\x6c\x33\x06\x07\xcf\
|
||||
\x68\x30\x05\x49\x74\x7b\x68\x7d\xf9\xae\x9b\x16\x61\x5e\x0c\x43\
|
||||
\xab\x4b\x87\x32\x45\x9c\x44\xf0\x04\x84\x5c\xe4\x1f\x98\x02\x8f\
|
||||
\x41\x8a\x85\x16\x12\x47\x80\x2f\xf5\x13\x71\xe6\x6e\xcf\xb1\xe7\
|
||||
\x79\x63\xa1\x1a\x8b\xbc\x81\x1e\xc8\xd0\x1d\x9c\x0c\x1c\xdb\x3c\
|
||||
\x9a\xee\x10\xe8\x34\x94\xee\x71\xff\xd4\xb1\xf3\x67\xad\xd3\x2e\
|
||||
\x94\x3a\x76\x61\xbc\xcd\x93\x19\x65\x01\x9f\xdd\x52\x19\x41\xee\
|
||||
\x4c\x2a\x05\xfa\xee\x7e\x04\x06\xc2\x8b\x48\x9a\xcf\xc5\xb1\x73\
|
||||
\x41\x53\x65\xe4\x2d\x78\x56\x62\xf3\xed\x03\x9f\x7f\xd2\x5d\xb9\
|
||||
\xc6\x9a\xc9\x34\xf1\x7c\x54\x64\xe5\x13\x60\x59\x3c\x06\xe1\x1e\
|
||||
\x3b\x76\xfe\x64\xdc\x5f\xb5\xd0\x50\x11\x7b\x62\x4a\x59\x4d\xc3\
|
||||
\x69\xa7\x06\x2a\x21\x2e\x91\x5c\x5d\xcb\x8f\x82\x67\x09\xfa\x5c\
|
||||
\xac\xe6\xb4\x68\x9b\xe1\x0d\xe3\xb2\x04\xab\x05\x2f\xb5\xe6\x64\
|
||||
\xd4\x02\x5a\xd3\xa7\x4e\xe8\x72\x63\x18\xb5\x92\xfa\x5e\x64\x7a\
|
||||
\xff\xe9\x97\x76\xcb\x09\xb5\x28\xba\x6a\x28\x0a\xb9\xa0\x3f\x39\
|
||||
\x93\x2d\xaa\xea\xca\x9a\x10\x7d\xf2\xc6\x10\x15\x9a\x22\xd5\xa8\
|
||||
\x7c\xbc\x05\x23\x98\xcb\xca\x80\x25\x4e\x17\x30\xf1\xb2\x08\x55\
|
||||
\xf3\x88\x0b\x32\xc1\xbf\x99\x17\x45\x75\xa4\xda\xe1\x32\x9d\xc6\
|
||||
\xb7\x15\xe7\xed\xaa\xf7\x8d\xc9\xa8\x80\x03\xd1\xc0\x61\xa4\xbb\
|
||||
\x3b\xa7\x81\x63\x01\x87\x4a\xe4\x8d\xda\x6c\x00\x43\xcd\xfd\x22\
|
||||
\xcf\xce\xae\x96\xfa\x1c\x5b\x77\xde\x37\x81\x66\x3e\xd0\x9f\x70\
|
||||
\x45\x19\xae\x54\x2a\x03\x4c\xb7\xa1\xd5\xab\x43\x87\x23\x2a\x3d\
|
||||
\x05\x1b\x1c\xf5\x2a\x64\xb0\x94\xe6\x44\xd0\xef\x55\x38\xa1\x74\
|
||||
\xab\xae\x70\x0d\xd2\x06\xb8\x0d\x90\xae\x86\x8d\xa6\xc5\x1b\x01\
|
||||
\x93\x73\xb5\xd6\x1f\x32\x29\x11\xc6\x22\xc9\x94\x2c\x41\x99\x8e\
|
||||
\x83\xb1\x91\x75\x46\x14\xe7\xd1\x2d\x4d\xda\x83\xea\x36\xa4\x29\
|
||||
\xc1\x5f\x19\x02\x09\x1a\x01\xc6\x60\x46\xbe\x63\x90\x11\x3e\xfe\
|
||||
\x17\x49\xf1\xe1\xb1\xd6\x70\x42\xeb\xac\xb9\xa0\xfb\x6a\xf8\x0b\
|
||||
\x08\xdc\xfe\x60\xa0\x48\x38\xa8\x89\xa6\x02\x80\xb9\x07\xa7\xb8\
|
||||
\x34\xe6\xb1\x2a\x1e\x47\x19\xb8\x07\x27\x28\xd5\x4f\xd5\x65\x6b\
|
||||
\x98\x7a\x98\xd7\x0a\xe6\x3f\x99\xda\x6e\xd6\x46\x98\x9f\x23\xa2\
|
||||
\x60\xd2\xab\x85\xc6\x1e\x0b\x92\x32\x77\xe3\xc9\xf0\x7e\x6b\x9f\
|
||||
\x79\x60\xe7\xfb\xec\xae\xb2\xdf\xb1\x0d\x13\x2e\x69\xb2\x22\xde\
|
||||
\x96\x34\xb7\xa2\xcc\x9d\x11\x26\x0a\x32\x5f\x66\x02\x5e\x8e\x35\
|
||||
\xef\xa1\xff\x37\xde\x7c\x4e\xde\xbc\x6f\x2f\xde\x8e\x39\x47\x45\
|
||||
\xb4\x3d\x2f\x7d\x1e\x0c\x7a\x1d\xf4\x79\x7c\xda\x45\x9f\xef\x8e\
|
||||
\x5f\x88\x3e\x97\x58\xbd\x71\xe8\xfa\xc2\xf3\x78\xbb\xc2\x73\xb0\
|
||||
\xbb\xc2\x53\x9f\x7d\x5e\x90\x44\x8f\xde\x48\x74\x3d\xd6\xcf\x4d\
|
||||
\xa2\x87\x9d\x8b\xb1\x09\x75\x0d\x4e\x3b\x98\xeb\xb0\xdf\xc5\x5c\
|
||||
\x47\x2f\xc5\x5c\xdf\x75\x2e\xbc\x5e\xda\xaa\x0a\x2b\xba\x56\xc6\
|
||||
\x3d\xe2\x96\xa0\xdc\x7c\x1f\x76\x4f\x70\x7d\x79\x4e\x68\x9c\x70\
|
||||
\x21\x77\x7d\x39\xb0\xbb\xab\x81\xc1\xc3\x19\xba\x4c\xb3\x10\xfc\
|
||||
\x1f\xab\xf8\x2c\x73\x4c\x09\xc6\xe5\x75\x4a\x3b\x56\x5d\x35\xca\
|
||||
\xf5\x04\xcb\x13\x53\xa6\x68\x65\x10\xfc\xa6\xeb\x15\x84\xf2\xaf\
|
||||
\x04\xd8\x28\x04\x3c\xdb\x19\x4c\x41\xb1\x3a\xb6\xc6\x40\xb2\x54\
|
||||
\x8d\xc3\xf3\x0c\x47\x9e\x9f\x12\xc9\xf3\x21\x24\xe6\x42\x7f\x96\
|
||||
\xc8\x45\xb2\x41\x09\xbd\xc1\x56\xf3\x35\xad\x3b\x37\x21\xde\x9d\
|
||||
\x47\x71\x03\x8b\xe0\xf1\x06\x37\x48\x67\x9c\xfc\xf5\xc4\x5f\x3a\
|
||||
\xf0\x2a\x53\x7a\xfb\x38\x3f\x7c\x8a\x38\xdf\xa6\x1a\x3f\x17\xe0\
|
||||
\x49\x48\x89\x26\x97\x54\x17\x29\xe0\xf9\xa1\xb9\x54\x34\xe5\xb7\
|
||||
\x8e\xda\xa7\x08\x5a\x4d\x70\x58\x1d\x61\x92\x30\xac\x3b\x52\x32\
|
||||
\x5e\x6c\x9b\x21\x1b\x04\xac\xaf\x67\x8e\x31\xab\xdd\x48\xdf\x02\
|
||||
\xb6\x35\x60\x8f\x9e\x24\x60\xbb\x2b\x9f\xf5\x11\x73\x6d\xf8\x74\
|
||||
\x92\x09\x46\xf5\x01\xf1\x17\xdf\x63\x24\xf6\x7e\x80\xa6\xe7\x98\
|
||||
\x07\x10\x91\x10\xbc\xbb\xc5\xaf\xcf\x12\x43\x86\xdf\x31\x86\x2e\
|
||||
\x0b\x8f\x5e\x65\x18\x3d\x5d\x29\x73\xb8\x59\x29\xd3\xbf\x20\x02\
|
||||
\x58\x00\xaa\xb1\xf3\x6f\x3a\x0e\x77\x57\xce\x9c\x3c\x49\xd6\x74\
|
||||
\x1f\xde\x3a\x69\x7e\x14\xf2\x19\x09\x60\x9c\x4d\x09\x65\x48\xf2\
|
||||
\xb1\x3e\xe4\x91\x20\x53\x52\xd2\x01\xeb\x06\xf1\xbb\x3e\x6d\xb5\
|
||||
\x75\x63\x01\xcb\x25\xe3\x46\x0c\x69\xea\x4d\x9f\x89\xeb\x95\x03\
|
||||
\xdf\xfe\xfe\x7c\xa1\x2c\xbf\xca\x0c\xdd\x3e\x64\xdf\x6d\x77\x47\
|
||||
\xf2\x58\x46\x3f\x47\x2f\x3d\xdc\x89\x53\x12\x51\xa6\x58\x9c\xfa\
|
||||
\x3f\x18\x86\x06\x11\x2a\x42\x5f\xee\xa2\xa4\x7b\x3e\x6f\x17\x25\
|
||||
\x3b\xb9\x28\xb9\xe0\x19\x1e\x4f\x46\x09\x65\x6d\xbc\x17\x68\x69\
|
||||
\x8a\xd2\xad\xce\x72\xa3\x04\x7c\x3a\xa1\x58\xe3\x2a\x16\x8a\x3d\
|
||||
\x86\x45\x26\x45\xf6\xd1\x15\xc3\x1d\x85\x19\x04\xf5\xd8\x8b\xb3\
|
||||
\x54\xaa\x03\x9d\x97\x24\x11\x45\x31\x9e\xe4\x7c\x8c\x53\x35\x6a\
|
||||
\x0b\xbe\xba\xf3\xa2\x0c\x6a\x3e\x9a\x39\xba\xfd\xfd\x5e\xf5\xc7\
|
||||
\xb1\x73\xc9\x53\xb2\x22\xe6\xde\x27\x9c\xd2\x6d\x31\xef\x57\xc9\
|
||||
\x8c\x9b\xd7\x2e\x15\x62\x28\x6a\x84\xea\x57\xf7\x0f\xe1\x83\x92\
|
||||
\x0a\xbe\xe5\x3a\x2a\x44\xd0\xac\x57\x36\x48\xff\x6a\xe6\xe7\x49\
|
||||
\xdf\x6f\x24\x7d\x91\xef\x47\x8d\x7c\xaf\xa4\x7a\xdd\x95\x4a\x82\
|
||||
\x97\x20\xad\x20\xb9\x02\x63\xbe\xd5\x14\xdf\xe4\xe4\xaf\xda\x0c\
|
||||
\xad\x63\x8b\x98\x77\x66\x86\xd6\xc1\x81\x65\xab\x91\x09\x9d\xc7\
|
||||
\x5e\x32\xc9\x98\xaf\x80\x72\xff\xbb\xd1\xed\x4b\xc1\xe3\xcf\x98\
|
||||
\x90\x23\x9e\x09\x1f\xeb\xe7\xda\x28\xf5\xda\x14\xa6\x23\x8f\x8d\
|
||||
\xc5\x54\x7b\xb2\xda\x63\xbc\x5c\x79\xb5\x6a\xe5\xfa\xb5\x7c\x9d\
|
||||
\x4a\xad\xc7\x5c\x62\x09\x92\xba\x5f\x6e\xb2\x34\x2c\xe4\x45\xe7\
|
||||
\x9e\x81\xcb\xc3\x12\x45\x69\xb1\xcd\xeb\x56\xe9\x7e\xa8\x90\xd3\
|
||||
\xbd\x1a\x81\xba\xe1\x6e\x4f\x6a\x97\xc1\xad\xde\x34\x5d\x5e\xe7\
|
||||
\x92\xd2\xb6\x3b\xb7\xf2\x6a\xb3\x1d\xa1\x52\xfa\x2c\xce\x54\xf6\
|
||||
\x81\x76\x8f\x6a\x43\xb6\x77\xab\xda\xa1\xdf\xb8\x13\x90\xea\x18\
|
||||
\x4c\x75\xb4\xfa\x9c\x31\xd0\x31\xa8\xda\x8e\x9d\x51\x77\xef\x7f\
|
||||
\xd6\x19\x97\xf4\
|
||||
\x00\x00\x07\x4c\
|
||||
\x00\
|
||||
\x00\x29\xd1\x78\x9c\xed\x59\x5b\x8f\xe2\x46\x16\x7e\xef\x5f\xe1\
|
||||
|
@ -11371,35 +11386,35 @@ qt_resource_struct = "\
|
|||
\x00\x00\x01\x8a\x00\x00\x00\x00\x00\x01\x00\x01\x1d\x6e\
|
||||
\x00\x00\x00\xba\x00\x00\x00\x00\x00\x01\x00\x00\x6c\x7e\
|
||||
\x00\x00\x00\x38\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x05\x6e\x00\x01\x00\x00\x00\x01\x00\x02\x52\xde\
|
||||
\x00\x00\x04\x7a\x00\x00\x00\x00\x00\x01\x00\x02\x15\x0f\
|
||||
\x00\x00\x03\x16\x00\x00\x00\x00\x00\x01\x00\x01\xb7\x13\
|
||||
\x00\x00\x06\x9e\x00\x01\x00\x00\x00\x01\x00\x02\xa9\x48\
|
||||
\x00\x00\x05\x40\x00\x01\x00\x00\x00\x01\x00\x02\x4c\x0c\
|
||||
\x00\x00\x03\x50\x00\x01\x00\x00\x00\x01\x00\x01\xc5\x82\
|
||||
\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x01\xd9\x09\
|
||||
\x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x01\x9c\x71\
|
||||
\x00\x00\x06\x38\x00\x00\x00\x00\x00\x01\x00\x02\x86\x04\
|
||||
\x00\x00\x04\xba\x00\x00\x00\x00\x00\x01\x00\x02\x2e\xe9\
|
||||
\x00\x00\x04\x5a\x00\x01\x00\x00\x00\x01\x00\x02\x0d\x47\
|
||||
\x00\x00\x02\x98\x00\x01\x00\x00\x00\x01\x00\x01\x93\x78\
|
||||
\x00\x00\x06\x0e\x00\x01\x00\x00\x00\x01\x00\x02\x7e\x6f\
|
||||
\x00\x00\x03\x7e\x00\x01\x00\x00\x00\x01\x00\x01\xce\xda\
|
||||
\x00\x00\x02\x4e\x00\x01\x00\x00\x00\x01\x00\x01\x82\xd0\
|
||||
\x00\x00\x02\x78\x00\x01\x00\x00\x00\x01\x00\x01\x8c\x78\
|
||||
\x00\x00\x04\xea\x00\x01\x00\x00\x00\x01\x00\x02\x3e\x57\
|
||||
\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x01\xf5\x04\
|
||||
\x00\x00\x05\x18\x00\x01\x00\x00\x00\x01\x00\x02\x43\xa7\
|
||||
\x00\x00\x04\x38\x00\x01\x00\x00\x00\x01\x00\x02\x05\x85\
|
||||
\x00\x00\x05\x98\x00\x00\x00\x00\x00\x01\x00\x02\x59\xb8\
|
||||
\x00\x00\x03\xc6\x00\x01\x00\x00\x00\x01\x00\x01\xde\x20\
|
||||
\x00\x00\x05\xe2\x00\x01\x00\x00\x00\x01\x00\x02\x75\xf5\
|
||||
\x00\x00\x05\xc2\x00\x01\x00\x00\x00\x01\x00\x02\x6b\xbb\
|
||||
\x00\x00\x04\x9a\x00\x01\x00\x00\x00\x01\x00\x02\x28\xd1\
|
||||
\x00\x00\x06\x64\x00\x00\x00\x00\x00\x01\x00\x02\x97\xd3\
|
||||
\x00\x00\x02\xec\x00\x00\x00\x00\x00\x01\x00\x01\xa4\xb3\
|
||||
\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x01\x00\x01\xe6\x08\
|
||||
\x00\x00\x02\x1a\x00\x01\x00\x00\x00\x01\x00\x01\x7b\x80\
|
||||
\x00\x00\x05\x6e\x00\x01\x00\x00\x00\x01\x00\x02\x53\xc3\
|
||||
\x00\x00\x04\x7a\x00\x00\x00\x00\x00\x01\x00\x02\x15\xf4\
|
||||
\x00\x00\x03\x16\x00\x00\x00\x00\x00\x01\x00\x01\xb7\xf8\
|
||||
\x00\x00\x06\x9e\x00\x01\x00\x00\x00\x01\x00\x02\xaa\x2d\
|
||||
\x00\x00\x05\x40\x00\x01\x00\x00\x00\x01\x00\x02\x4c\xf1\
|
||||
\x00\x00\x03\x50\x00\x01\x00\x00\x00\x01\x00\x01\xc6\x67\
|
||||
\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x01\xd9\xee\
|
||||
\x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x01\x9d\x56\
|
||||
\x00\x00\x06\x38\x00\x00\x00\x00\x00\x01\x00\x02\x86\xe9\
|
||||
\x00\x00\x04\xba\x00\x00\x00\x00\x00\x01\x00\x02\x2f\xce\
|
||||
\x00\x00\x04\x5a\x00\x01\x00\x00\x00\x01\x00\x02\x0e\x2c\
|
||||
\x00\x00\x02\x98\x00\x01\x00\x00\x00\x01\x00\x01\x94\x5d\
|
||||
\x00\x00\x06\x0e\x00\x01\x00\x00\x00\x01\x00\x02\x7f\x54\
|
||||
\x00\x00\x03\x7e\x00\x01\x00\x00\x00\x01\x00\x01\xcf\xbf\
|
||||
\x00\x00\x02\x4e\x00\x01\x00\x00\x00\x01\x00\x01\x83\xb5\
|
||||
\x00\x00\x02\x78\x00\x01\x00\x00\x00\x01\x00\x01\x8d\x5d\
|
||||
\x00\x00\x04\xea\x00\x01\x00\x00\x00\x01\x00\x02\x3f\x3c\
|
||||
\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x01\xf5\xe9\
|
||||
\x00\x00\x05\x18\x00\x01\x00\x00\x00\x01\x00\x02\x44\x8c\
|
||||
\x00\x00\x04\x38\x00\x01\x00\x00\x00\x01\x00\x02\x06\x6a\
|
||||
\x00\x00\x05\x98\x00\x00\x00\x00\x00\x01\x00\x02\x5a\x9d\
|
||||
\x00\x00\x03\xc6\x00\x01\x00\x00\x00\x01\x00\x01\xdf\x05\
|
||||
\x00\x00\x05\xe2\x00\x01\x00\x00\x00\x01\x00\x02\x76\xda\
|
||||
\x00\x00\x05\xc2\x00\x01\x00\x00\x00\x01\x00\x02\x6c\xa0\
|
||||
\x00\x00\x04\x9a\x00\x01\x00\x00\x00\x01\x00\x02\x29\xb6\
|
||||
\x00\x00\x06\x64\x00\x00\x00\x00\x00\x01\x00\x02\x98\xb8\
|
||||
\x00\x00\x02\xec\x00\x00\x00\x00\x00\x01\x00\x01\xa5\x98\
|
||||
\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x01\x00\x01\xe6\xed\
|
||||
\x00\x00\x02\x1a\x00\x01\x00\x00\x00\x01\x00\x01\x7c\x65\
|
||||
\x00\x00\x01\xf2\x00\x01\x00\x00\x00\x01\x00\x01\x76\xac\
|
||||
"
|
||||
|
||||
|
|
|
@ -224,6 +224,75 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>2D rendering</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_4">
|
||||
<property name="toolTip">
|
||||
<string>Show debug information during 2D rendering</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show renderer debug messages</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ShowVRMDebug</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Cut areas line thickness ratio</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefDoubleSpinBox" name="gui::prefdoublespinbox">
|
||||
<property name="toolTip">
|
||||
<string>Specifies how many times the viewed line thickness must be applied to cut lines</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>2.000000000000000</double>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CutLineThickness</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -257,6 +326,11 @@
|
|||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
@ -1562,10 +1562,8 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"):
|
|||
if tp == "BSpline":
|
||||
print "makeSketch: BSplines not supported"
|
||||
elif tp == "Circle":
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
nobj.addGeometry(obj.Shape.Edges[0].Curve)
|
||||
else:
|
||||
nobj.addGeometry(Part.ArcOfCircle(obj.Shape.Edges[0].Curve,math.radians(obj.FirstAngle),math.radians(obj.LastAngle)))
|
||||
g = (DraftGeomUtils.geom(obj.Shape.Edges[0],nobj.Placement))
|
||||
nobj.addGeometry(g)
|
||||
# TODO add Radius constraits
|
||||
ok = True
|
||||
elif tp == "Rectangle":
|
||||
|
@ -1586,25 +1584,26 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"):
|
|||
nobj.addConstraint(Constraint("Vertical",last))
|
||||
ok = True
|
||||
elif tp in ["Wire","Polygon"]:
|
||||
closed = False
|
||||
if tp == "Polygon":
|
||||
closed = True
|
||||
elif hasattr(obj,"Closed"):
|
||||
closed = obj.Closed
|
||||
for edge in obj.Shape.Edges:
|
||||
nobj.addGeometry(edge.Curve)
|
||||
if autoconstraints:
|
||||
last = nobj.GeometryCount
|
||||
segs = range(last-len(obj.Shape.Edges),last-1)
|
||||
for seg in segs:
|
||||
nobj.addConstraint(Constraint("Coincident",seg,EndPoint,seg+1,StartPoint))
|
||||
if DraftGeomUtils.isAligned(nobj.Geometry[seg],"x"):
|
||||
nobj.addConstraint(Constraint("Vertical",seg))
|
||||
elif DraftGeomUtils.isAligned(nobj.Geometry[seg],"y"):
|
||||
nobj.addConstraint(Constraint("Horizontal",seg))
|
||||
if closed:
|
||||
nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,segs[0],StartPoint))
|
||||
ok = True
|
||||
if obj.FilletRadius == 0:
|
||||
closed = False
|
||||
if tp == "Polygon":
|
||||
closed = True
|
||||
elif hasattr(obj,"Closed"):
|
||||
closed = obj.Closed
|
||||
for edge in obj.Shape.Edges:
|
||||
nobj.addGeometry(edge.Curve)
|
||||
if autoconstraints:
|
||||
last = nobj.GeometryCount
|
||||
segs = range(last-len(obj.Shape.Edges),last-1)
|
||||
for seg in segs:
|
||||
nobj.addConstraint(Constraint("Coincident",seg,EndPoint,seg+1,StartPoint))
|
||||
if DraftGeomUtils.isAligned(nobj.Geometry[seg],"x"):
|
||||
nobj.addConstraint(Constraint("Vertical",seg))
|
||||
elif DraftGeomUtils.isAligned(nobj.Geometry[seg],"y"):
|
||||
nobj.addConstraint(Constraint("Horizontal",seg))
|
||||
if closed:
|
||||
nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,segs[0],StartPoint))
|
||||
ok = True
|
||||
if (not ok) and obj.isDerivedFrom("Part::Feature"):
|
||||
if not DraftGeomUtils.isPlanar(obj.Shape):
|
||||
print "Error: The given object is not planar and cannot be converted into a sketch."
|
||||
|
|
|
@ -39,14 +39,14 @@ precision = params.GetInt("precision")
|
|||
|
||||
|
||||
def vec(edge):
|
||||
"vec(edge) or vec(line) -- returns a vector from an edge or a Part.line"
|
||||
# if edge is not straight, you'll get strange results!
|
||||
if isinstance(edge,Part.Shape):
|
||||
return edge.Vertexes[-1].Point.sub(edge.Vertexes[0].Point)
|
||||
elif isinstance(edge,Part.Line):
|
||||
return edge.EndPoint.sub(edge.StartPoint)
|
||||
else:
|
||||
return None
|
||||
"vec(edge) or vec(line) -- returns a vector from an edge or a Part.line"
|
||||
# if edge is not straight, you'll get strange results!
|
||||
if isinstance(edge,Part.Shape):
|
||||
return edge.Vertexes[-1].Point.sub(edge.Vertexes[0].Point)
|
||||
elif isinstance(edge,Part.Line):
|
||||
return edge.EndPoint.sub(edge.StartPoint)
|
||||
else:
|
||||
return None
|
||||
|
||||
def edg(p1,p2):
|
||||
"edg(Vector,Vector) -- returns an edge from 2 vectors"
|
||||
|
@ -370,17 +370,18 @@ def geom(edge,plac=FreeCAD.Placement()):
|
|||
c = edge.Curve.Center
|
||||
cu = Part.Circle(edge.Curve.Center,normal,edge.Curve.Radius)
|
||||
ref = plac.Rotation.multVec(Vector(1,0,0))
|
||||
a1 = math.pi + DraftVecUtils.angle(v1.sub(c),ref,normal)
|
||||
a2 = DraftVecUtils.angle(v2.sub(c),ref,normal)
|
||||
a1 = DraftVecUtils.angle(v1.sub(c),ref,DraftVecUtils.neg(normal))
|
||||
a2 = DraftVecUtils.angle(v2.sub(c),ref,DraftVecUtils.neg(normal))
|
||||
|
||||
# direction check
|
||||
if a1 > a2:
|
||||
if edge.Curve.Axis.getAngle(normal) > 1:
|
||||
a1,a2 = a2,a1
|
||||
|
||||
#print "creating sketch arc from ",cu, ", p1=",v1, " (",math.degrees(a1), "d) p2=",v2," (", math.degrees(a2),"d)"
|
||||
|
||||
p= Part.ArcOfCircle(cu,a1,a2)
|
||||
return p
|
||||
else:
|
||||
print edge.Curve
|
||||
return edge.Curve
|
||||
|
||||
def mirror (point, edge):
|
||||
|
@ -539,57 +540,62 @@ def sortEdges(lEdges, aVertex=None):
|
|||
|
||||
|
||||
def findWires(edgeslist):
|
||||
'''finds connected wires in the given list of edges'''
|
||||
'''finds connected wires in the given list of edges'''
|
||||
|
||||
def touches(e1,e2):
|
||||
if len(e1.Vertexes) < 2:
|
||||
return False
|
||||
if len(e2.Vertexes) < 2:
|
||||
return False
|
||||
if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[0].Point):
|
||||
return True
|
||||
if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[-1].Point):
|
||||
return True
|
||||
if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[0].Point):
|
||||
return True
|
||||
if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[-1].Point):
|
||||
return True
|
||||
return False
|
||||
|
||||
edges = edgeslist[:]
|
||||
wires = []
|
||||
lost = []
|
||||
while edges:
|
||||
e = edges[0]
|
||||
if not wires:
|
||||
# create first group
|
||||
edges.remove(e)
|
||||
wires.append([e])
|
||||
def touches(e1,e2):
|
||||
if len(e1.Vertexes) < 2:
|
||||
return False
|
||||
if len(e2.Vertexes) < 2:
|
||||
return False
|
||||
if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[0].Point):
|
||||
return True
|
||||
if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[-1].Point):
|
||||
return True
|
||||
if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[0].Point):
|
||||
return True
|
||||
if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[-1].Point):
|
||||
return True
|
||||
return False
|
||||
|
||||
edges = edgeslist[:]
|
||||
wires = []
|
||||
lost = []
|
||||
while edges:
|
||||
e = edges[0]
|
||||
if not wires:
|
||||
# create first group
|
||||
edges.remove(e)
|
||||
wires.append([e])
|
||||
else:
|
||||
found = False
|
||||
for w in wires:
|
||||
if not found:
|
||||
for we in w:
|
||||
if touches(e,we):
|
||||
edges.remove(e)
|
||||
w.append(e)
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
if e in lost:
|
||||
# we already tried this edge, and still nothing
|
||||
edges.remove(e)
|
||||
wires.append([e])
|
||||
lost = []
|
||||
else:
|
||||
found = False
|
||||
for w in wires:
|
||||
if not found:
|
||||
for we in w:
|
||||
if touches(e,we):
|
||||
edges.remove(e)
|
||||
w.append(e)
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
if e in lost:
|
||||
# we already tried this edge, and still nothing
|
||||
edges.remove(e)
|
||||
wires.append([e])
|
||||
lost = []
|
||||
else:
|
||||
# put to the end of the list
|
||||
edges.remove(e)
|
||||
edges.append(e)
|
||||
lost.append(e)
|
||||
nwires = []
|
||||
for w in wires:
|
||||
nwires.append(Part.Wire(w))
|
||||
return nwires
|
||||
# put to the end of the list
|
||||
edges.remove(e)
|
||||
edges.append(e)
|
||||
lost.append(e)
|
||||
nwires = []
|
||||
for w in wires:
|
||||
try:
|
||||
wi = Part.Wire(w)
|
||||
except:
|
||||
print "couldn't join some edges"
|
||||
else:
|
||||
nwires.append(wi)
|
||||
return nwires
|
||||
|
||||
def superWire(edgeslist,closed=False):
|
||||
'''superWire(edges,[closed]): forces a wire between edges that don't necessarily
|
||||
|
@ -767,8 +773,8 @@ def getNormal(shape):
|
|||
if (shape.ShapeType == "Face") and hasattr(shape,"normalAt"):
|
||||
n = shape.normalAt(0.5,0.5)
|
||||
elif shape.ShapeType == "Edge":
|
||||
if isinstance(shape.Curve,Part.Circle):
|
||||
n = shape.Curve.Axis
|
||||
if isinstance(shape.Edges[0].Curve,Part.Circle):
|
||||
n = shape.Edges[0].Curve.Axis
|
||||
else:
|
||||
for e in shape.Edges:
|
||||
if isinstance(e.Curve,Part.Circle):
|
||||
|
|
|
@ -990,7 +990,7 @@ class DraftToolBar:
|
|||
def setCurrentText(self,tstr):
|
||||
if (not self.taskmode) or (self.taskmode and self.isTaskOn):
|
||||
self.textValue.setText(tstr)
|
||||
|
||||
|
||||
def sendText(self):
|
||||
'''
|
||||
this function sends the entered text to the active draft command
|
||||
|
|
|
@ -317,16 +317,16 @@ class Snapper:
|
|||
"returns a 3D point, projected on the current working plane"
|
||||
view = Draft.get3DView()
|
||||
pt = view.getPoint(x,y)
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
if view.getCameraType() == "Perspective":
|
||||
camera = view.getCameraNode()
|
||||
p = camera.getField("position").getValue()
|
||||
dv = pt.sub(Vector(p[0],p[1],p[2]))
|
||||
else:
|
||||
dv = view.getViewDirection()
|
||||
return FreeCAD.DraftWorkingPlane.projectPoint(pt,dv)
|
||||
else:
|
||||
return pt
|
||||
if self.mask != "z":
|
||||
if hasattr(FreeCAD,"DraftWorkingPlane"):
|
||||
if view.getCameraType() == "Perspective":
|
||||
camera = view.getCameraNode()
|
||||
p = camera.getField("position").getValue()
|
||||
dv = pt.sub(Vector(p[0],p[1],p[2]))
|
||||
else:
|
||||
dv = view.getViewDirection()
|
||||
return FreeCAD.DraftWorkingPlane.projectPoint(pt,dv)
|
||||
return pt
|
||||
|
||||
def snapToExtensions(self,point,last,constrain,eline):
|
||||
"returns a point snapped to extension or parallel line to last object, if any"
|
||||
|
|
|
@ -3711,7 +3711,7 @@ class Draft2Sketch():
|
|||
elif obj.isDerivedFrom("Part::Part2DObjectPython"):
|
||||
Draft.makeSketch(obj,autoconstraints=True)
|
||||
elif obj.isDerivedFrom("Part::Feature"):
|
||||
if len(obj.Shape.Wires) == 1:
|
||||
if (len(obj.Shape.Wires) == 1) or (len(obj.Shape.Edges) == 1):
|
||||
Draft.makeSketch(obj,autoconstraints=False)
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
||||
|
|
|
@ -1356,65 +1356,76 @@ def export(objectslist,filename,nospline=False):
|
|||
"called when freecad exports a file. If nospline=True, bsplines are exported as straight segs"
|
||||
global exportList
|
||||
exportList = objectslist
|
||||
dxf = dxfLibrary.Drawing()
|
||||
if (len(exportList) == 1) and (exportList[0].isDerivedFrom("Drawing::FeaturePage")):
|
||||
|
||||
if (len(exportList) == 1) and (Draft.getType(exportList[0]) == "ArchSectionView"):
|
||||
# arch view: export it "as is"
|
||||
dxf = exportList[0].Proxy.getDXF()
|
||||
if dxf:
|
||||
f = open(filename,"w")
|
||||
f.write(dxf)
|
||||
f.close()
|
||||
|
||||
elif (len(exportList) == 1) and (exportList[0].isDerivedFrom("Drawing::FeaturePage")):
|
||||
# page: special hack-export! (see below)
|
||||
exportPage(exportList[0],filename)
|
||||
return
|
||||
for ob in exportList:
|
||||
print "processing ",ob.Name
|
||||
if ob.isDerivedFrom("Part::Feature"):
|
||||
if not ob.Shape.isNull():
|
||||
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"):
|
||||
writeMesh(ob,dxf)
|
||||
else:
|
||||
if ob.Shape.ShapeType == 'Compound':
|
||||
if (len(ob.Shape.Wires) == 1):
|
||||
# only one wire in this compound, no lone edge -> polyline
|
||||
if (len(ob.Shape.Wires[0].Edges) == len(ob.Shape.Edges)):
|
||||
writeShape(ob,dxf,nospline)
|
||||
|
||||
else:
|
||||
# other cases, treat edges
|
||||
dxf = dxfLibrary.Drawing()
|
||||
for ob in exportList:
|
||||
print "processing ",ob.Name
|
||||
if ob.isDerivedFrom("Part::Feature"):
|
||||
if not ob.Shape.isNull():
|
||||
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"):
|
||||
writeMesh(ob,dxf)
|
||||
else:
|
||||
if ob.Shape.ShapeType == 'Compound':
|
||||
if (len(ob.Shape.Wires) == 1):
|
||||
# only one wire in this compound, no lone edge -> polyline
|
||||
if (len(ob.Shape.Wires[0].Edges) == len(ob.Shape.Edges)):
|
||||
writeShape(ob,dxf,nospline)
|
||||
else:
|
||||
# 1 wire + lone edges -> block
|
||||
block = getBlock(ob)
|
||||
dxf.blocks.append(block)
|
||||
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
|
||||
else:
|
||||
# 1 wire + lone edges -> block
|
||||
# all other cases: block
|
||||
block = getBlock(ob)
|
||||
dxf.blocks.append(block)
|
||||
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
|
||||
else:
|
||||
# all other cases: block
|
||||
block = getBlock(ob)
|
||||
dxf.blocks.append(block)
|
||||
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
|
||||
else:
|
||||
writeShape(ob,dxf,nospline)
|
||||
|
||||
elif (ob.Type == "App::Annotation"):
|
||||
|
||||
# texts
|
||||
|
||||
# temporary - as dxfLibrary doesn't support mtexts well, we use several single-line texts
|
||||
# well, anyway, at the moment, Draft only writes single-line texts, so...
|
||||
for text in ob.LabelText:
|
||||
point = DraftVecUtils.tup(FreeCAD.Vector(ob.Position.x,
|
||||
ob.Position.y-ob.LabelText.index(text),
|
||||
ob.Position.z))
|
||||
if gui: height = float(ob.ViewObject.FontSize)
|
||||
else: height = 1
|
||||
dxf.append(dxfLibrary.Text(text,point,height=height,
|
||||
color=getACI(ob,text=True),
|
||||
style='STANDARD',
|
||||
layer=getGroup(ob,exportList)))
|
||||
|
||||
elif 'Dimline' in ob.PropertiesList:
|
||||
p1 = DraftVecUtils.tup(ob.Start)
|
||||
p2 = DraftVecUtils.tup(ob.End)
|
||||
base = Part.Line(ob.Start,ob.End).toShape()
|
||||
proj = DraftGeomUtils.findDistance(ob.Dimline,base)
|
||||
if not proj:
|
||||
pbase = DraftVecUtils.tup(ob.End)
|
||||
else:
|
||||
pbase = DraftVecUtils.tup(ob.End.add(DraftVecUtils.neg(proj)))
|
||||
dxf.append(dxfLibrary.Dimension(pbase,p1,p2,color=getACI(ob),
|
||||
layer=getGroup(ob,exportList)))
|
||||
|
||||
dxf.saveas(filename)
|
||||
writeShape(ob,dxf,nospline)
|
||||
|
||||
elif Draft.getType(ob) == "Annotation":
|
||||
# texts
|
||||
|
||||
# temporary - as dxfLibrary doesn't support mtexts well, we use several single-line texts
|
||||
# well, anyway, at the moment, Draft only writes single-line texts, so...
|
||||
for text in ob.LabelText:
|
||||
point = DraftVecUtils.tup(FreeCAD.Vector(ob.Position.x,
|
||||
ob.Position.y-ob.LabelText.index(text),
|
||||
ob.Position.z))
|
||||
if gui: height = float(ob.ViewObject.FontSize)
|
||||
else: height = 1
|
||||
dxf.append(dxfLibrary.Text(text,point,height=height,
|
||||
color=getACI(ob,text=True),
|
||||
style='STANDARD',
|
||||
layer=getGroup(ob,exportList)))
|
||||
|
||||
elif Draft.getType(ob) == "Dimension":
|
||||
p1 = DraftVecUtils.tup(ob.Start)
|
||||
p2 = DraftVecUtils.tup(ob.End)
|
||||
base = Part.Line(ob.Start,ob.End).toShape()
|
||||
proj = DraftGeomUtils.findDistance(ob.Dimline,base)
|
||||
if not proj:
|
||||
pbase = DraftVecUtils.tup(ob.End)
|
||||
else:
|
||||
pbase = DraftVecUtils.tup(ob.End.add(DraftVecUtils.neg(proj)))
|
||||
dxf.append(dxfLibrary.Dimension(pbase,p1,p2,color=getACI(ob),
|
||||
layer=getGroup(ob,exportList)))
|
||||
|
||||
dxf.saveas(filename)
|
||||
FreeCAD.Console.PrintMessage("successfully exported "+filename+"\r\n")
|
||||
|
||||
def exportPage(page,filename):
|
||||
|
|
|
@ -255,6 +255,17 @@ float MeshAlgorithm::GetAverageEdgeLength() const
|
|||
return fLen;
|
||||
}
|
||||
|
||||
Base::Vector3f MeshAlgorithm::GetGravityPoint() const
|
||||
{
|
||||
Base::Vector3f center;
|
||||
MeshPointIterator cP(_rclMesh);
|
||||
for (cP.Init(); cP.More(); cP.Next()) {
|
||||
center += *cP;
|
||||
}
|
||||
|
||||
return center / (float)_rclMesh.CountPoints();
|
||||
}
|
||||
|
||||
void MeshAlgorithm::GetMeshBorders (std::list<std::vector<Base::Vector3f> > &rclBorders) const
|
||||
{
|
||||
std::vector<unsigned long> aulAllFacets(_rclMesh.CountFacets());
|
||||
|
|
|
@ -115,6 +115,10 @@ public:
|
|||
* Calculates the average length of edges.
|
||||
*/
|
||||
float GetAverageEdgeLength() const;
|
||||
/**
|
||||
* Calculates the gravity point of the mesh.
|
||||
*/
|
||||
Base::Vector3f GetGravityPoint() const;
|
||||
/**
|
||||
* Returns all boundaries of the mesh.
|
||||
*/
|
||||
|
|
|
@ -30,11 +30,15 @@
|
|||
# include <QSet>
|
||||
#endif
|
||||
|
||||
#include <boost/signals.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "ui_TaskFaceColors.h"
|
||||
#include "TaskFaceColors.h"
|
||||
#include "ViewProviderExt.h"
|
||||
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/Selection.h>
|
||||
|
||||
|
@ -69,15 +73,20 @@ namespace PartGui {
|
|||
class FaceColors::Private
|
||||
{
|
||||
public:
|
||||
typedef boost::signals::connection Connection;
|
||||
Ui_TaskFaceColors* ui;
|
||||
ViewProviderPartExt* vp;
|
||||
App::DocumentObject* obj;
|
||||
Gui::Document* doc;
|
||||
std::vector<App::Color> current,perface;
|
||||
QSet<int> index;
|
||||
Connection connectDelDoc;
|
||||
Connection connectDelObj;
|
||||
|
||||
Private(ViewProviderPartExt* vp) : ui(new Ui_TaskFaceColors()), vp(vp)
|
||||
{
|
||||
obj = vp->getObject();
|
||||
doc = Gui::Application::Instance->getDocument(obj->getDocument());
|
||||
|
||||
// build up map edge->face
|
||||
TopTools_IndexedMapOfShape mapOfShape;
|
||||
|
@ -110,14 +119,33 @@ FaceColors::FaceColors(ViewProviderPartExt* vp, QWidget* parent)
|
|||
|
||||
FaceSelection* gate = new FaceSelection(d->vp->getObject());
|
||||
Gui::Selection().addSelectionGate(gate);
|
||||
|
||||
d->connectDelDoc = Gui::Application::Instance->signalDeleteDocument.connect(boost::bind
|
||||
(&FaceColors::slotDeleteDocument, this, _1));
|
||||
d->connectDelObj = Gui::Application::Instance->signalDeletedObject.connect(boost::bind
|
||||
(&FaceColors::slotDeleteObject, this, _1));
|
||||
}
|
||||
|
||||
FaceColors::~FaceColors()
|
||||
{
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
d->connectDelDoc.disconnect();
|
||||
d->connectDelObj.disconnect();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void FaceColors::slotDeleteDocument(const Gui::Document& Doc)
|
||||
{
|
||||
if (d->doc == &Doc)
|
||||
Gui::Control().closeDialog();
|
||||
}
|
||||
|
||||
void FaceColors::slotDeleteObject(const Gui::ViewProvider& obj)
|
||||
{
|
||||
if (d->vp == &obj)
|
||||
Gui::Control().closeDialog();
|
||||
}
|
||||
|
||||
void FaceColors::on_defaultButton_clicked()
|
||||
{
|
||||
std::fill(d->perface.begin(), d->perface.end(), d->vp->ShapeColor.getValue());
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
|
||||
namespace Gui {
|
||||
class Document;
|
||||
class ViewProvider;
|
||||
}
|
||||
|
||||
namespace PartGui {
|
||||
|
||||
class ViewProviderPartExt;
|
||||
|
@ -49,6 +54,8 @@ private Q_SLOTS:
|
|||
protected:
|
||||
void onSelectionChanged(const Gui::SelectionChanges& msg);
|
||||
void changeEvent(QEvent *e);
|
||||
void slotDeleteDocument(const Gui::Document&);
|
||||
void slotDeleteObject(const Gui::ViewProvider&);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
|
|
|
@ -125,9 +125,14 @@ ViewProviderPartExt::ViewProviderPartExt()
|
|||
{
|
||||
VisualTouched = true;
|
||||
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
unsigned long lcol = hGrp->GetUnsigned("DefaultShapeLineColor",421075455UL); // dark grey (25,25,25)
|
||||
float r,g,b;
|
||||
r = ((lcol >> 24) & 0xff) / 255.0; g = ((lcol >> 16) & 0xff) / 255.0; b = ((lcol >> 8) & 0xff) / 255.0;
|
||||
int lwidth = hGrp->GetInt("DefaultShapeLineWidth",2);
|
||||
App::Material mat;
|
||||
mat.ambientColor.set(0.2f,0.2f,0.2f);
|
||||
mat.diffuseColor.set(0.1f,0.1f,0.1f);
|
||||
mat.diffuseColor.set(r,g,b);
|
||||
mat.specularColor.set(0.0f,0.0f,0.0f);
|
||||
mat.emissiveColor.set(0.0f,0.0f,0.0f);
|
||||
mat.shininess = 1.0f;
|
||||
|
@ -137,10 +142,10 @@ ViewProviderPartExt::ViewProviderPartExt()
|
|||
ADD_PROPERTY(LineColor,(mat.diffuseColor));
|
||||
ADD_PROPERTY(PointColor,(mat.diffuseColor));
|
||||
ADD_PROPERTY(DiffuseColor,(ShapeColor.getValue()));
|
||||
ADD_PROPERTY(LineWidth,(2.0f));
|
||||
ADD_PROPERTY(LineWidth,(lwidth));
|
||||
LineWidth.setConstraints(&sizeRange);
|
||||
PointSize.setConstraints(&sizeRange);
|
||||
ADD_PROPERTY(PointSize,(2.0f));
|
||||
ADD_PROPERTY(PointSize,(lwidth));
|
||||
ADD_PROPERTY(Deviation,(0.5f));
|
||||
Deviation.setConstraints(&tessRange);
|
||||
ADD_PROPERTY(ControlPoints,(false));
|
||||
|
|
|
@ -45,6 +45,8 @@ SET(ShipIcons_SRCS
|
|||
Icons/SimRunIco.xpm
|
||||
Icons/SimStopIco.png
|
||||
Icons/SimStopIco.xpm
|
||||
Icons/SimPostIco.png
|
||||
Icons/SimPostIco.xpm
|
||||
Icons/Tank.png
|
||||
Icons/Tank.xcf
|
||||
Icons/Tank.xpm
|
||||
|
@ -150,10 +152,20 @@ SET(SimRun_SRCS
|
|||
simRun/clSim/Utils.py
|
||||
simRun/Sim/__init__.py
|
||||
simRun/Sim/initialization.py
|
||||
simRun/Sim/matrixGen.py
|
||||
simRun/Sim/computeSources.py
|
||||
simRun/Sim/fsEvolution.py
|
||||
)
|
||||
SOURCE_GROUP("simrun" FILES ${SimRun_SRCS})
|
||||
|
||||
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS} ${SimCreate_SRCS} ${SimRun_SRCS})
|
||||
SET(SimPost_SRCS
|
||||
simPost/__init__.py
|
||||
simPost/TaskPanel.py
|
||||
simPost/TaskPanel.ui
|
||||
)
|
||||
SOURCE_GROUP("simpost" FILES ${SimPost_SRCS})
|
||||
|
||||
SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipWeights_SRCS} ${ShipCreateTank_SRCS} ${ShipGZ_SRCS} ${SimCreate_SRCS} ${SimRun_SRCS} ${SimPost_SRCS})
|
||||
|
||||
ADD_CUSTOM_TARGET(Ship ALL
|
||||
SOURCES ${all_files}
|
||||
|
@ -239,6 +251,12 @@ INSTALL(
|
|||
DESTINATION
|
||||
Mod/Ship/simRun
|
||||
)
|
||||
INSTALL(
|
||||
FILES
|
||||
${SimPost_SRCS}
|
||||
DESTINATION
|
||||
Mod/Ship/simPost
|
||||
)
|
||||
INSTALL(
|
||||
FILES
|
||||
${ShipMain_SRCS}
|
||||
|
|
Binary file not shown.
BIN
src/Mod/Ship/Icons/SimPostIco.png
Normal file
BIN
src/Mod/Ship/Icons/SimPostIco.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
2077
src/Mod/Ship/Icons/SimPostIco.xpm
Normal file
2077
src/Mod/Ship/Icons/SimPostIco.xpm
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -1,68 +1,68 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
class ShipWorkbench ( Workbench ):
|
||||
""" @brief Workbench of Ship design module. Here toolbars & icons are append. """
|
||||
from shipUtils import Paths, Translator
|
||||
import ShipGui
|
||||
|
||||
Icon = Paths.iconsPath() + "/Ico.png"
|
||||
MenuText = str(Translator.translate("Ship design"))
|
||||
ToolTip = str(Translator.translate("Ship design"))
|
||||
|
||||
def Initialize(self):
|
||||
from shipUtils import Translator
|
||||
# ToolBar
|
||||
list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"]
|
||||
self.appendToolbar("Ship design",list)
|
||||
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
|
||||
self.appendToolbar("Weights",list)
|
||||
# Simulation stuff only if pyOpenCL & numpy are present
|
||||
hasOpenCL = True
|
||||
hasNumpy = True
|
||||
try:
|
||||
import pyopencl
|
||||
except ImportError:
|
||||
hasOpenCL = False
|
||||
msg = Translator.translate("pyOpenCL not installed, ship simulations disabled\n")
|
||||
App.Console.PrintWarning(msg)
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
hasNumpy = False
|
||||
msg = Translator.translate("numpy not installed, ship simulations disabled\n")
|
||||
App.Console.PrintWarning(msg)
|
||||
if hasOpenCL and hasNumpy:
|
||||
list = ["Ship_CreateSim", "Ship_RunSim", "Ship_StopSim"]
|
||||
self.appendToolbar("Simulation",list)
|
||||
|
||||
# Menu
|
||||
list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"]
|
||||
self.appendMenu("Ship design",list)
|
||||
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
|
||||
self.appendMenu("Weights",list)
|
||||
if hasOpenCL and hasNumpy:
|
||||
list = ["Ship_CreateSim", "Ship_RunSim", "Ship_StopSim"]
|
||||
self.appendMenu("Simulation",list)
|
||||
|
||||
Gui.addWorkbench(ShipWorkbench())
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
class ShipWorkbench ( Workbench ):
|
||||
""" @brief Workbench of Ship design module. Here toolbars & icons are append. """
|
||||
from shipUtils import Paths, Translator
|
||||
import ShipGui
|
||||
|
||||
Icon = Paths.iconsPath() + "/Ico.png"
|
||||
MenuText = str(Translator.translate("Ship design"))
|
||||
ToolTip = str(Translator.translate("Ship design"))
|
||||
|
||||
def Initialize(self):
|
||||
from shipUtils import Translator
|
||||
# ToolBar
|
||||
list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"]
|
||||
self.appendToolbar("Ship design",list)
|
||||
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
|
||||
self.appendToolbar("Weights",list)
|
||||
# Simulation stuff only if pyOpenCL & numpy are present
|
||||
hasOpenCL = True
|
||||
hasNumpy = True
|
||||
try:
|
||||
import pyopencl
|
||||
except ImportError:
|
||||
hasOpenCL = False
|
||||
msg = Translator.translate("pyOpenCL not installed, ship simulations disabled\n")
|
||||
App.Console.PrintWarning(msg)
|
||||
try:
|
||||
import numpy
|
||||
except ImportError:
|
||||
hasNumpy = False
|
||||
msg = Translator.translate("numpy not installed, ship simulations disabled\n")
|
||||
App.Console.PrintWarning(msg)
|
||||
if hasOpenCL and hasNumpy:
|
||||
list = ["Ship_CreateSim", "Ship_RunSim", "Ship_StopSim", "Ship_TrackSim"]
|
||||
self.appendToolbar("Simulation",list)
|
||||
|
||||
# Menu
|
||||
list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"]
|
||||
self.appendMenu("Ship design",list)
|
||||
list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"]
|
||||
self.appendMenu("Weights",list)
|
||||
if hasOpenCL and hasNumpy:
|
||||
list = ["Ship_CreateSim", "Ship_RunSim", "Ship_StopSim", "Ship_TrackSim"]
|
||||
self.appendMenu("Simulation",list)
|
||||
|
||||
Gui.addWorkbench(ShipWorkbench())
|
||||
|
|
|
@ -46,6 +46,8 @@ nobase_data_DATA = \
|
|||
Icons/SimRunIco.xpm \
|
||||
Icons/SimStopIco.png \
|
||||
Icons/SimStopIco.xpm \
|
||||
Icons/SimPostIco.png \
|
||||
Icons/SimPostIco.xpm \
|
||||
Icons/Tank.png \
|
||||
Icons/Tank.xcf \
|
||||
Icons/Tank.xpm \
|
||||
|
@ -102,7 +104,13 @@ nobase_data_DATA = \
|
|||
simRun/clSim/initialization.py \
|
||||
simRun/clSim/Utils.py \
|
||||
simRun/Sim/__init__.py \
|
||||
simRun/Sim/initialization.py
|
||||
simRun/Sim/initialization.py \
|
||||
simRun/Sim/matrixGen.py \
|
||||
simRun/Sim/computeSources.py \
|
||||
simRun/Sim/fsEvolution.py \
|
||||
simPost/__init__.py \
|
||||
simPost/TaskPanel.py \
|
||||
simPost/TaskPanel.ui
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
|
|
|
@ -1,169 +1,183 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
import FreeCAD, FreeCADGui, os
|
||||
|
||||
class LoadExample:
|
||||
def Activated(self):
|
||||
import shipLoadExample
|
||||
shipLoadExample.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/LoadIco.png"
|
||||
MenuText = str(Translator.translate('Load an example ship geometry'))
|
||||
ToolTip = str(Translator.translate('Load an example ship geometry able to be converted into a ship.'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class CreateShip:
|
||||
def Activated(self):
|
||||
import shipCreateShip
|
||||
shipCreateShip.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/Ico.png"
|
||||
MenuText = str(Translator.translate('Create a new ship'))
|
||||
ToolTip = str(Translator.translate('Create a new ship in order to work with them'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class OutlineDraw:
|
||||
def Activated(self):
|
||||
import shipOutlineDraw
|
||||
shipOutlineDraw.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/OutlineDrawIco.png"
|
||||
MenuText = str(Translator.translate('Outline draw'))
|
||||
ToolTip = str(Translator.translate('Plot ship outline draw'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class AreasCurve:
|
||||
def Activated(self):
|
||||
import shipAreasCurve
|
||||
shipAreasCurve.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/AreaCurveIco.png"
|
||||
MenuText = str(Translator.translate('Areas curve'))
|
||||
ToolTip = str(Translator.translate('Plot transversal areas curve'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class Hydrostatics:
|
||||
def Activated(self):
|
||||
import shipHydrostatics
|
||||
shipHydrostatics.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/HydrostaticsIco.png"
|
||||
MenuText = str(Translator.translate('Hydrostatics'))
|
||||
ToolTip = str(Translator.translate('Plot ship hydrostatics'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class SetWeights:
|
||||
def Activated(self):
|
||||
import tankWeights
|
||||
tankWeights.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/Weight.png"
|
||||
MenuText = str(Translator.translate('Set ship weights'))
|
||||
ToolTip = str(Translator.translate('Set ship weights, tanks must be added later'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class CreateTank:
|
||||
def Activated(self):
|
||||
import tankCreateTank
|
||||
tankCreateTank.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/Tank.png"
|
||||
MenuText = str(Translator.translate('Create a new tank'))
|
||||
ToolTip = str(Translator.translate('Create a new ship tank'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class GZ:
|
||||
def Activated(self):
|
||||
import tankGZ
|
||||
tankGZ.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/HydrostaticsIco.png"
|
||||
MenuText = str(Translator.translate('GZ curve'))
|
||||
ToolTip = str(Translator.translate('Transversal stability GZ curve computation'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class CreateSim:
|
||||
def Activated(self):
|
||||
import simCreate
|
||||
simCreate.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/SimCreateIco.png"
|
||||
MenuText = str(Translator.translate('Create a new simulation'))
|
||||
ToolTip = str(Translator.translate('Create a new simulation in order to process later'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class RunSim:
|
||||
def Activated(self):
|
||||
import simRun
|
||||
simRun.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/SimRunIco.png"
|
||||
MenuText = str(Translator.translate('Run a simulation'))
|
||||
ToolTip = str(Translator.translate('Run a simulation'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class StopSim:
|
||||
def Activated(self):
|
||||
import simRun
|
||||
simRun.stop()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/SimStopIco.png"
|
||||
MenuText = str(Translator.translate('Stop active simulation'))
|
||||
ToolTip = str(Translator.translate('Stop active simulation'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
FreeCADGui.addCommand('Ship_LoadExample', LoadExample())
|
||||
FreeCADGui.addCommand('Ship_CreateShip', CreateShip())
|
||||
FreeCADGui.addCommand('Ship_OutlineDraw', OutlineDraw())
|
||||
FreeCADGui.addCommand('Ship_AreasCurve', AreasCurve())
|
||||
FreeCADGui.addCommand('Ship_Hydrostatics', Hydrostatics())
|
||||
FreeCADGui.addCommand('Ship_Weights', SetWeights())
|
||||
FreeCADGui.addCommand('Ship_CreateTank', CreateTank())
|
||||
FreeCADGui.addCommand('Ship_GZ', GZ())
|
||||
FreeCADGui.addCommand('Ship_CreateSim', CreateSim())
|
||||
FreeCADGui.addCommand('Ship_RunSim', RunSim())
|
||||
FreeCADGui.addCommand('Ship_StopSim', StopSim())
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
import FreeCAD, FreeCADGui, os
|
||||
|
||||
class LoadExample:
|
||||
def Activated(self):
|
||||
import shipLoadExample
|
||||
shipLoadExample.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/LoadIco.png"
|
||||
MenuText = str(Translator.translate('Load an example ship geometry'))
|
||||
ToolTip = str(Translator.translate('Load an example ship geometry able to be converted into a ship.'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class CreateShip:
|
||||
def Activated(self):
|
||||
import shipCreateShip
|
||||
shipCreateShip.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/Ico.png"
|
||||
MenuText = str(Translator.translate('Create a new ship'))
|
||||
ToolTip = str(Translator.translate('Create a new ship in order to work with them'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class OutlineDraw:
|
||||
def Activated(self):
|
||||
import shipOutlineDraw
|
||||
shipOutlineDraw.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/OutlineDrawIco.png"
|
||||
MenuText = str(Translator.translate('Outline draw'))
|
||||
ToolTip = str(Translator.translate('Plot ship outline draw'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class AreasCurve:
|
||||
def Activated(self):
|
||||
import shipAreasCurve
|
||||
shipAreasCurve.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/AreaCurveIco.png"
|
||||
MenuText = str(Translator.translate('Areas curve'))
|
||||
ToolTip = str(Translator.translate('Plot transversal areas curve'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class Hydrostatics:
|
||||
def Activated(self):
|
||||
import shipHydrostatics
|
||||
shipHydrostatics.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/HydrostaticsIco.png"
|
||||
MenuText = str(Translator.translate('Hydrostatics'))
|
||||
ToolTip = str(Translator.translate('Plot ship hydrostatics'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class SetWeights:
|
||||
def Activated(self):
|
||||
import tankWeights
|
||||
tankWeights.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/Weight.png"
|
||||
MenuText = str(Translator.translate('Set ship weights'))
|
||||
ToolTip = str(Translator.translate('Set ship weights, tanks must be added later'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class CreateTank:
|
||||
def Activated(self):
|
||||
import tankCreateTank
|
||||
tankCreateTank.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/Tank.png"
|
||||
MenuText = str(Translator.translate('Create a new tank'))
|
||||
ToolTip = str(Translator.translate('Create a new ship tank'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class GZ:
|
||||
def Activated(self):
|
||||
import tankGZ
|
||||
tankGZ.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/HydrostaticsIco.png"
|
||||
MenuText = str(Translator.translate('GZ curve'))
|
||||
ToolTip = str(Translator.translate('Transversal stability GZ curve computation'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class CreateSim:
|
||||
def Activated(self):
|
||||
import simCreate
|
||||
simCreate.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/SimCreateIco.png"
|
||||
MenuText = str(Translator.translate('Create a new simulation'))
|
||||
ToolTip = str(Translator.translate('Create a new simulation in order to process later'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class RunSim:
|
||||
def Activated(self):
|
||||
import simRun
|
||||
simRun.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/SimRunIco.png"
|
||||
MenuText = str(Translator.translate('Run a simulation'))
|
||||
ToolTip = str(Translator.translate('Run a simulation'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class StopSim:
|
||||
def Activated(self):
|
||||
import simRun
|
||||
simRun.stop()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/SimStopIco.png"
|
||||
MenuText = str(Translator.translate('Stop active simulation'))
|
||||
ToolTip = str(Translator.translate('Stop active simulation'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
class TrackSim:
|
||||
def Activated(self):
|
||||
import simPost
|
||||
simPost.load()
|
||||
|
||||
def GetResources(self):
|
||||
from shipUtils import Paths, Translator
|
||||
IconPath = Paths.iconsPath() + "/SimPostIco.png"
|
||||
MenuText = str(Translator.translate('Track simulation'))
|
||||
ToolTip = str(Translator.translate('Track simulation'))
|
||||
return {'Pixmap' : IconPath, 'MenuText': MenuText, 'ToolTip': ToolTip}
|
||||
|
||||
|
||||
FreeCADGui.addCommand('Ship_LoadExample', LoadExample())
|
||||
FreeCADGui.addCommand('Ship_CreateShip', CreateShip())
|
||||
FreeCADGui.addCommand('Ship_OutlineDraw', OutlineDraw())
|
||||
FreeCADGui.addCommand('Ship_AreasCurve', AreasCurve())
|
||||
FreeCADGui.addCommand('Ship_Hydrostatics', Hydrostatics())
|
||||
FreeCADGui.addCommand('Ship_Weights', SetWeights())
|
||||
FreeCADGui.addCommand('Ship_CreateTank', CreateTank())
|
||||
FreeCADGui.addCommand('Ship_GZ', GZ())
|
||||
FreeCADGui.addCommand('Ship_CreateSim', CreateSim())
|
||||
FreeCADGui.addCommand('Ship_RunSim', RunSim())
|
||||
FreeCADGui.addCommand('Ship_StopSim', StopSim())
|
||||
FreeCADGui.addCommand('Ship_TrackSim', TrackSim())
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,7 +31,6 @@ from PyQt4 import QtGui,QtCore
|
|||
import Preview, Plot
|
||||
import Instance
|
||||
from shipUtils import Paths, Translator
|
||||
from surfUtils import Geometry
|
||||
from shipHydrostatics import Tools as Hydrostatics
|
||||
|
||||
class TaskPanel:
|
||||
|
@ -114,7 +113,7 @@ class TaskPanel:
|
|||
""" Set initial values for fields
|
||||
"""
|
||||
# Get objects
|
||||
selObjs = Geometry.getSelectedObjs()
|
||||
selObjs = Gui.Selection.getSelection()
|
||||
if not selObjs:
|
||||
msg = Translator.translate("Ship instance must be selected (no object selected)\n")
|
||||
App.Console.PrintError(msg)
|
||||
|
|
|
@ -28,7 +28,6 @@ import FreeCADGui as Gui
|
|||
from PyQt4 import QtGui,QtCore
|
||||
# Module
|
||||
from shipUtils import Paths, Translator
|
||||
from surfUtils import Geometry
|
||||
|
||||
class TaskPanel:
|
||||
def __init__(self):
|
||||
|
|
|
@ -27,7 +27,6 @@ from FreeCAD import Base, Vector
|
|||
import Part
|
||||
# FreeCADShip modules
|
||||
from shipUtils import Paths, Translator
|
||||
from surfUtils import Geometry
|
||||
|
||||
def Plot(scale, sections, shape):
|
||||
""" Creates the outline draw.
|
||||
|
@ -52,7 +51,7 @@ def Plot(scale, sections, shape):
|
|||
x0 = xMid - 0.5*xTot
|
||||
y0 = 297.0 - yMid - 0.5*yTot # 297 = A3_width
|
||||
# Get border
|
||||
edges = Geometry.getEdges([shape])
|
||||
edges = self.getEdges([shape])
|
||||
border = edges[0]
|
||||
for i in range(0,len(edges)):
|
||||
border = border.oldFuse(edges[i]) # Only group objects, don't try to build more complex entities
|
||||
|
@ -95,3 +94,31 @@ def Plot(scale, sections, shape):
|
|||
FreeCAD.ActiveDocument.OutlineDrawPlot.addObject(FreeCAD.ActiveDocument.OutlineDrawUpView)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return obj
|
||||
|
||||
def getEdges(self, objs=None):
|
||||
""" Returns object edges (list of them)
|
||||
@param objs Object to get the faces, none if selected
|
||||
object may used.
|
||||
@return Selected edges. None if errors happens
|
||||
"""
|
||||
edges = []
|
||||
if not objs:
|
||||
objs = FreeCADGui.Selection.getSelection()
|
||||
if not objs:
|
||||
return None
|
||||
for i in range(0, len(objs)):
|
||||
obj = objs[i]
|
||||
if obj.isDerivedFrom('Part::Feature'):
|
||||
# get shape
|
||||
shape = obj.Shape
|
||||
if not shape:
|
||||
return None
|
||||
obj = shape
|
||||
if not obj.isDerivedFrom('Part::TopoShape'):
|
||||
return None
|
||||
objEdges = obj.Edges
|
||||
if not objEdges:
|
||||
continue
|
||||
for j in range(0, len(objEdges)):
|
||||
edges.append(objEdges[j])
|
||||
return edges
|
||||
|
|
|
@ -30,7 +30,6 @@ from PyQt4 import QtGui,QtCore
|
|||
import Preview, Plot
|
||||
import Instance
|
||||
from shipUtils import Paths, Translator
|
||||
from surfUtils import Geometry
|
||||
|
||||
class TaskPanel:
|
||||
def __init__(self):
|
||||
|
@ -116,7 +115,7 @@ class TaskPanel:
|
|||
""" Set initial values for fields
|
||||
"""
|
||||
# Get selected objects
|
||||
selObjs = Geometry.getSelectedObjs()
|
||||
selObjs = Gui.Selection.getSelection()
|
||||
if not selObjs:
|
||||
msg = Translator.translate("Ship instance must be selected (no object selected)\n")
|
||||
App.Console.PrintError(msg)
|
||||
|
|
|
@ -1,174 +1,177 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# FreeCAD modules
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
# Qt library
|
||||
from PyQt4 import QtGui,QtCore
|
||||
# Module
|
||||
import SimInstance
|
||||
from shipUtils import Paths, Translator
|
||||
|
||||
class TaskPanel:
|
||||
def __init__(self):
|
||||
self.ui = Paths.modulePath() + "/simCreate/TaskPanel.ui"
|
||||
|
||||
def accept(self):
|
||||
form = self.form
|
||||
# Read waves data
|
||||
w = []
|
||||
for i in range(0,form.waves.rowCount() - 1):
|
||||
item = form.waves.item(i,0)
|
||||
A = item.text().toFloat()[0]
|
||||
item = form.waves.item(i,1)
|
||||
T = item.text().toFloat()[0]
|
||||
item = form.waves.item(i,2)
|
||||
phi = item.text().toFloat()[0]
|
||||
item = form.waves.item(i,3)
|
||||
head = item.text().toFloat()[0]
|
||||
w.append([A,T,phi,head])
|
||||
obj = App.ActiveDocument.addObject("Part::FeaturePython","ShipSimulation")
|
||||
sim = SimInstance.ShipSimulation(obj,
|
||||
[form.length.value(), form.beam.value(), form.n.value()],
|
||||
w)
|
||||
SimInstance.ViewProviderShipSimulation(obj.ViewObject)
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
return True
|
||||
|
||||
def clicked(self, index):
|
||||
pass
|
||||
|
||||
def open(self):
|
||||
pass
|
||||
|
||||
def needsFullSpace(self):
|
||||
return True
|
||||
|
||||
def isAllowedAlterSelection(self):
|
||||
return False
|
||||
|
||||
def isAllowedAlterView(self):
|
||||
return True
|
||||
|
||||
def isAllowedAlterDocument(self):
|
||||
return False
|
||||
|
||||
def helpRequested(self):
|
||||
pass
|
||||
|
||||
def setupUi(self):
|
||||
mw = self.getMainWindow()
|
||||
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
||||
form.length = form.findChild(QtGui.QDoubleSpinBox, "Length")
|
||||
form.beam = form.findChild(QtGui.QDoubleSpinBox, "Beam")
|
||||
form.n = form.findChild(QtGui.QSpinBox, "N")
|
||||
form.waves = form.findChild(QtGui.QTableWidget, "Waves")
|
||||
self.form = form
|
||||
# Initial values
|
||||
if self.initValues():
|
||||
return True
|
||||
self.retranslateUi()
|
||||
# Connect Signals and Slots
|
||||
QtCore.QObject.connect(form.length, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
|
||||
QtCore.QObject.connect(form.beam, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
|
||||
QtCore.QObject.connect(form.n, QtCore.SIGNAL("valueChanged(int)"), self.onFS)
|
||||
QtCore.QObject.connect(form.waves,QtCore.SIGNAL("cellChanged(int,int)"),self.onWaves);
|
||||
|
||||
def getMainWindow(self):
|
||||
"returns the main window"
|
||||
# using QtGui.qApp.activeWindow() isn't very reliable because if another
|
||||
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
|
||||
# returned
|
||||
toplevel = QtGui.qApp.topLevelWidgets()
|
||||
for i in toplevel:
|
||||
if i.metaObject().className() == "Gui::MainWindow":
|
||||
return i
|
||||
raise Exception("No main window found")
|
||||
|
||||
def initValues(self):
|
||||
""" Set initial values for fields
|
||||
"""
|
||||
msg = Translator.translate("Ready to work\n")
|
||||
App.Console.PrintMessage(msg)
|
||||
return False
|
||||
|
||||
def retranslateUi(self):
|
||||
""" Set user interface locale strings.
|
||||
"""
|
||||
self.form.setWindowTitle(Translator.translate("Create a new ship simulation"))
|
||||
self.form.findChild(QtGui.QGroupBox, "FSDataBox").setTitle(Translator.translate("Free surface"))
|
||||
self.form.findChild(QtGui.QLabel, "LengthLabel").setText(Translator.translate("Length"))
|
||||
self.form.findChild(QtGui.QLabel, "BeamLabel").setText(Translator.translate("Beam"))
|
||||
self.form.findChild(QtGui.QLabel, "NLabel").setText(Translator.translate("Number of points"))
|
||||
self.form.findChild(QtGui.QGroupBox, "WavesDataBox").setTitle(Translator.translate("Waves"))
|
||||
labels = []
|
||||
labels.append(Translator.translate("Amplitude") + " [m]")
|
||||
labels.append(Translator.translate("Period") + " [s]")
|
||||
labels.append(Translator.translate("Phase") + " [rad]")
|
||||
labels.append(Translator.translate("Heading") + " [deg]")
|
||||
self.form.waves.setHorizontalHeaderLabels(labels)
|
||||
|
||||
def onFS(self, value):
|
||||
""" Method called when free surface data is changed.
|
||||
@param value Changed value.
|
||||
"""
|
||||
pass
|
||||
|
||||
def onWaves(self, row, column):
|
||||
""" Method called when waves data is changed.
|
||||
@param row Affected row.
|
||||
@param col Affected column.
|
||||
"""
|
||||
item = self.form.waves.item(row,column)
|
||||
# Row deletion
|
||||
if column == 0:
|
||||
if not item.text():
|
||||
self.form.waves.removeRow(row)
|
||||
# Ensure that exist one empty item at the end
|
||||
nRow = self.form.waves.rowCount()
|
||||
last = self.form.waves.item(nRow-1,0)
|
||||
if last:
|
||||
if(last.text() != ''):
|
||||
self.form.waves.setRowCount(nRow+1)
|
||||
# Fields must be numbers
|
||||
for i in range(0,self.form.waves.rowCount()-1): # Avoid last row
|
||||
for j in range(0,self.form.waves.columnCount()): # Avoid name column
|
||||
item = self.form.waves.item(i,j)
|
||||
if not item:
|
||||
item = QtGui.QTableWidgetItem('0.0')
|
||||
self.form.waves.setItem(i,j,item)
|
||||
continue
|
||||
(number,flag) = item.text().toFloat()
|
||||
if not flag:
|
||||
item.setText('0.0')
|
||||
|
||||
def createTask():
|
||||
panel = TaskPanel()
|
||||
Gui.Control.showDialog(panel)
|
||||
if panel.setupUi():
|
||||
Gui.Control.closeDialog(panel)
|
||||
return None
|
||||
return panel
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# FreeCAD modules
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
# Qt library
|
||||
from PyQt4 import QtGui,QtCore
|
||||
# Module
|
||||
import SimInstance
|
||||
from shipUtils import Paths, Translator
|
||||
|
||||
class TaskPanel:
|
||||
def __init__(self):
|
||||
self.ui = Paths.modulePath() + "/simCreate/TaskPanel.ui"
|
||||
|
||||
def accept(self):
|
||||
form = self.form
|
||||
# Read waves data
|
||||
w = []
|
||||
for i in range(0,form.waves.rowCount() - 1):
|
||||
item = form.waves.item(i,0)
|
||||
A = item.text().toFloat()[0]
|
||||
item = form.waves.item(i,1)
|
||||
T = item.text().toFloat()[0]
|
||||
item = form.waves.item(i,2)
|
||||
phi = item.text().toFloat()[0]
|
||||
item = form.waves.item(i,3)
|
||||
head = item.text().toFloat()[0]
|
||||
w.append([A,T,phi,head])
|
||||
obj = App.ActiveDocument.addObject("Part::FeaturePython","ShipSimulation")
|
||||
sim = SimInstance.ShipSimulation(obj,
|
||||
[form.length.value(), form.beam.value(), form.n.value()],
|
||||
w)
|
||||
SimInstance.ViewProviderShipSimulation(obj.ViewObject)
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
return True
|
||||
|
||||
def clicked(self, index):
|
||||
pass
|
||||
|
||||
def open(self):
|
||||
pass
|
||||
|
||||
def needsFullSpace(self):
|
||||
return True
|
||||
|
||||
def isAllowedAlterSelection(self):
|
||||
return False
|
||||
|
||||
def isAllowedAlterView(self):
|
||||
return True
|
||||
|
||||
def isAllowedAlterDocument(self):
|
||||
return False
|
||||
|
||||
def helpRequested(self):
|
||||
pass
|
||||
|
||||
def setupUi(self):
|
||||
mw = self.getMainWindow()
|
||||
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
||||
form.length = form.findChild(QtGui.QDoubleSpinBox, "Length")
|
||||
form.beam = form.findChild(QtGui.QDoubleSpinBox, "Beam")
|
||||
form.n = form.findChild(QtGui.QSpinBox, "N")
|
||||
form.waves = form.findChild(QtGui.QTableWidget, "Waves")
|
||||
self.form = form
|
||||
# Initial values
|
||||
if self.initValues():
|
||||
return True
|
||||
self.retranslateUi()
|
||||
# Connect Signals and Slots
|
||||
QtCore.QObject.connect(form.length, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
|
||||
QtCore.QObject.connect(form.beam, QtCore.SIGNAL("valueChanged(double)"), self.onFS)
|
||||
QtCore.QObject.connect(form.n, QtCore.SIGNAL("valueChanged(int)"), self.onFS)
|
||||
QtCore.QObject.connect(form.waves,QtCore.SIGNAL("cellChanged(int,int)"),self.onWaves);
|
||||
|
||||
def getMainWindow(self):
|
||||
"returns the main window"
|
||||
# using QtGui.qApp.activeWindow() isn't very reliable because if another
|
||||
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
|
||||
# returned
|
||||
toplevel = QtGui.qApp.topLevelWidgets()
|
||||
for i in toplevel:
|
||||
if i.metaObject().className() == "Gui::MainWindow":
|
||||
return i
|
||||
raise Exception("No main window found")
|
||||
|
||||
def initValues(self):
|
||||
""" Set initial values for fields
|
||||
"""
|
||||
msg = Translator.translate("Ready to work\n")
|
||||
App.Console.PrintMessage(msg)
|
||||
return False
|
||||
|
||||
def retranslateUi(self):
|
||||
""" Set user interface locale strings.
|
||||
"""
|
||||
self.form.setWindowTitle(Translator.translate("Create a new ship simulation"))
|
||||
self.form.findChild(QtGui.QGroupBox, "FSDataBox").setTitle(Translator.translate("Free surface"))
|
||||
self.form.findChild(QtGui.QLabel, "LengthLabel").setText(Translator.translate("Length"))
|
||||
self.form.findChild(QtGui.QLabel, "BeamLabel").setText(Translator.translate("Beam"))
|
||||
self.form.findChild(QtGui.QLabel, "NLabel").setText(Translator.translate("Number of points"))
|
||||
self.form.findChild(QtGui.QGroupBox, "WavesDataBox").setTitle(Translator.translate("Waves"))
|
||||
labels = []
|
||||
labels.append(Translator.translate("Amplitude") + " [m]")
|
||||
labels.append(Translator.translate("Period") + " [s]")
|
||||
labels.append(Translator.translate("Phase") + " [rad]")
|
||||
labels.append(Translator.translate("Heading") + " [deg]")
|
||||
self.form.waves.setHorizontalHeaderLabels(labels)
|
||||
|
||||
def onFS(self, value):
|
||||
""" Method called when free surface data is changed.
|
||||
@param value Changed value.
|
||||
"""
|
||||
pass
|
||||
|
||||
def onWaves(self, row, column):
|
||||
""" Method called when waves data is changed.
|
||||
@param row Affected row.
|
||||
@param col Affected column.
|
||||
"""
|
||||
item = self.form.waves.item(row,column)
|
||||
# Row deletion
|
||||
if column == 0:
|
||||
if not item.text():
|
||||
self.form.waves.removeRow(row)
|
||||
# Ensure that exist one empty item at the end
|
||||
nRow = self.form.waves.rowCount()
|
||||
if not nRow:
|
||||
self.form.waves.setRowCount(1)
|
||||
else:
|
||||
last = self.form.waves.item(nRow-1,0)
|
||||
if last:
|
||||
if(last.text() != ''):
|
||||
self.form.waves.setRowCount(nRow+1)
|
||||
# Fields must be numbers
|
||||
for i in range(0,self.form.waves.rowCount()-1): # Avoid last row
|
||||
for j in range(0,self.form.waves.columnCount()): # Avoid name column
|
||||
item = self.form.waves.item(i,j)
|
||||
if not item:
|
||||
item = QtGui.QTableWidgetItem('0.0')
|
||||
self.form.waves.setItem(i,j,item)
|
||||
continue
|
||||
(number,flag) = item.text().toFloat()
|
||||
if not flag:
|
||||
item.setText('0.0')
|
||||
|
||||
def createTask():
|
||||
panel = TaskPanel()
|
||||
Gui.Control.showDialog(panel)
|
||||
if panel.setupUi():
|
||||
Gui.Control.closeDialog(panel)
|
||||
return None
|
||||
return panel
|
||||
|
|
156
src/Mod/Ship/simPost/TaskPanel.py
Normal file
156
src/Mod/Ship/simPost/TaskPanel.py
Normal file
|
@ -0,0 +1,156 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# FreeCAD modules
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
# Qt library
|
||||
from PyQt4 import QtGui,QtCore
|
||||
# pyOpenCL
|
||||
import pyopencl as cl
|
||||
# Module
|
||||
import SimInstance
|
||||
from shipUtils import Paths, Translator
|
||||
from simRun import Simulation
|
||||
Sim = Simulation.FreeCADShipSimulation
|
||||
# from Simulation import FreeCADShipSimulation as Sim
|
||||
|
||||
class TaskPanel:
|
||||
def __init__(self):
|
||||
self.ui = Paths.modulePath() + "/simPost/TaskPanel.ui"
|
||||
|
||||
def accept(self):
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
return True
|
||||
|
||||
def clicked(self, index):
|
||||
pass
|
||||
|
||||
def open(self):
|
||||
pass
|
||||
|
||||
def needsFullSpace(self):
|
||||
return True
|
||||
|
||||
def isAllowedAlterSelection(self):
|
||||
return False
|
||||
|
||||
def isAllowedAlterView(self):
|
||||
return True
|
||||
|
||||
def isAllowedAlterDocument(self):
|
||||
return False
|
||||
|
||||
def helpRequested(self):
|
||||
pass
|
||||
|
||||
def setupUi(self):
|
||||
mw = self.getMainWindow()
|
||||
form = mw.findChild(QtGui.QWidget, "TaskPanel")
|
||||
form.time = form.findChild(QtGui.QLabel, "TimeLabel")
|
||||
form.first = form.findChild(QtGui.QPushButton, "First")
|
||||
form.prev = form.findChild(QtGui.QPushButton, "Prev")
|
||||
form.now = form.findChild(QtGui.QPushButton, "Now")
|
||||
form.next = form.findChild(QtGui.QPushButton, "Next")
|
||||
form.last = form.findChild(QtGui.QPushButton, "Last")
|
||||
self.form = form
|
||||
# Initial values
|
||||
if self.initValues():
|
||||
return True
|
||||
self.retranslateUi()
|
||||
# Connect Signals and Slots
|
||||
QtCore.QObject.connect(form.first, QtCore.SIGNAL("pressed()"), self.onFirst)
|
||||
QtCore.QObject.connect(form.prev, QtCore.SIGNAL("pressed()"), self.onPrev)
|
||||
QtCore.QObject.connect(form.now, QtCore.SIGNAL("pressed()"), self.onNow)
|
||||
QtCore.QObject.connect(form.next, QtCore.SIGNAL("pressed()"), self.onNext)
|
||||
QtCore.QObject.connect(form.last, QtCore.SIGNAL("pressed()"), self.onLast)
|
||||
|
||||
def getMainWindow(self):
|
||||
"returns the main window"
|
||||
# using QtGui.qApp.activeWindow() isn't very reliable because if another
|
||||
# widget than the mainwindow is active (e.g. a dialog) the wrong widget is
|
||||
# returned
|
||||
toplevel = QtGui.qApp.topLevelWidgets()
|
||||
for i in toplevel:
|
||||
if i.metaObject().className() == "Gui::MainWindow":
|
||||
return i
|
||||
raise Exception("No main window found")
|
||||
|
||||
def initValues(self):
|
||||
""" Set initial values for fields
|
||||
"""
|
||||
msg = Translator.translate("Ready to work\n")
|
||||
App.Console.PrintMessage(msg)
|
||||
return False
|
||||
|
||||
def retranslateUi(self):
|
||||
""" Set user interface locale strings.
|
||||
"""
|
||||
self.form.setWindowTitle(Translator.translate("Track simulation"))
|
||||
self.form.findChild(QtGui.QPushButton, "Now").setText(Translator.translate("Now"))
|
||||
|
||||
def onFirst(self):
|
||||
""" Called when first frame button is pressed.
|
||||
"""
|
||||
|
||||
def onPrev(self):
|
||||
""" Called when previous frame button is pressed.
|
||||
"""
|
||||
|
||||
def onNow(self):
|
||||
""" Called when actual frame button is pressed.
|
||||
"""
|
||||
sim = Sim()
|
||||
pos = sim.sim.FS_Position[:]
|
||||
nx = sim.FS['Nx']
|
||||
ny = sim.FS['Ny']
|
||||
for i in range(0, nx):
|
||||
for j in range(0, ny):
|
||||
pos[i*ny+j].z = float(sim.FS['pos'][i,j][2])
|
||||
sim.sim.FS_Position = pos[:]
|
||||
App.ActiveDocument.recompute()
|
||||
self.form.time.setText("t = %g s" % (sim.t))
|
||||
|
||||
def onNext(self):
|
||||
""" Called when next frame button is pressed.
|
||||
"""
|
||||
|
||||
def onLast(self):
|
||||
""" Called when last frame button is pressed.
|
||||
"""
|
||||
|
||||
def createTask():
|
||||
try:
|
||||
simulator = Sim()
|
||||
except:
|
||||
msg = Translator.translate("Can't find any active simulation!\n")
|
||||
App.Console.PrintError(msg)
|
||||
return
|
||||
panel = TaskPanel()
|
||||
Gui.Control.showDialog(panel)
|
||||
if panel.setupUi():
|
||||
Gui.Control.closeDialog(panel)
|
||||
return None
|
||||
return panel
|
81
src/Mod/Ship/simPost/TaskPanel.ui
Normal file
81
src/Mod/Ship/simPost/TaskPanel.ui
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TaskPanel</class>
|
||||
<widget class="QWidget" name="TaskPanel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<height>102</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Track simulation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="First">
|
||||
<property name="text">
|
||||
<string>|<</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="Prev">
|
||||
<property name="text">
|
||||
<string><</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="Next">
|
||||
<property name="text">
|
||||
<string>></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QPushButton" name="Last">
|
||||
<property name="text">
|
||||
<string>>|</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="Now">
|
||||
<property name="text">
|
||||
<string>Now</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="5">
|
||||
<widget class="QLabel" name="TimeLabel">
|
||||
<property name="text">
|
||||
<string>t = 0 s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
40
src/Mod/Ship/simPost/__init__.py
Normal file
40
src/Mod/Ship/simPost/__init__.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# FreeCAD modules
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
# Qt libraries
|
||||
from PyQt4 import QtGui,QtCore
|
||||
|
||||
# Main object
|
||||
import TaskPanel
|
||||
|
||||
def load():
|
||||
""" Loads the tool """
|
||||
TaskPanel.createTask()
|
||||
|
||||
def stop():
|
||||
""" Stops the simulation """
|
||||
TaskPanel.stopSimulation()
|
|
@ -21,4 +21,7 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import initialization
|
||||
from initialization import *
|
||||
from matrixGen import *
|
||||
from computeSources import *
|
||||
from fsEvolution import *
|
||||
|
|
69
src/Mod/Ship/simRun/Sim/computeSources.py
Normal file
69
src/Mod/Ship/simRun/Sim/computeSources.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# numpy
|
||||
import numpy as np
|
||||
|
||||
grav=9.81
|
||||
|
||||
class simComputeSources:
|
||||
def __init__(self, context=None, queue=None):
|
||||
""" Constructor.
|
||||
@param context OpenCL context where apply. Only for compatibility,
|
||||
must be None.
|
||||
@param queue OpenCL command queue. Only for compatibility,
|
||||
must be None.
|
||||
"""
|
||||
self.context = context
|
||||
self.queue = queue
|
||||
|
||||
def execute(self, fs, A):
|
||||
""" Compute potential sources (for velocity potential and
|
||||
acceleration potential).
|
||||
@param fs Free surface instance.
|
||||
@param A Linear system matrix.
|
||||
"""
|
||||
self.fs = fs
|
||||
# Allocate memory
|
||||
nx = self.fs['Nx']
|
||||
ny = self.fs['Ny']
|
||||
nF = nx*ny
|
||||
nB = 0 # No body for the moment
|
||||
N = nx*ny + nB
|
||||
b = np.ndarray(N, dtype=np.float32)
|
||||
bb = np.ndarray(N, dtype=np.float32)
|
||||
s = np.ndarray(N, dtype=np.float32)
|
||||
ss = np.ndarray(N, dtype=np.float32)
|
||||
# Create independent terms
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
b[i*ny+j] = self.fs['velPot'][i,j]
|
||||
bb[i*ny+j] = self.fs['accPot'][i,j]
|
||||
# Solve systems
|
||||
s = np.linalg.solve(A, b)
|
||||
ss = np.linalg.solve(A, bb)
|
||||
# Store sources
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
self.fs['velSrc'][i,j] = s[i*ny+j]
|
||||
self.fs['accSrc'][i,j] = ss[i*ny+j]
|
177
src/Mod/Ship/simRun/Sim/fsEvolution.py
Normal file
177
src/Mod/Ship/simRun/Sim/fsEvolution.py
Normal file
|
@ -0,0 +1,177 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# numpy
|
||||
import numpy as np
|
||||
|
||||
grav=9.81
|
||||
|
||||
class simFSEvolution:
|
||||
def __init__(self, context=None, queue=None):
|
||||
""" Constructor.
|
||||
@param context OpenCL context where apply. Only for compatibility,
|
||||
must be None.
|
||||
@param queue OpenCL command queue. Only for compatibility,
|
||||
must be None.
|
||||
"""
|
||||
self.context = context
|
||||
self.queue = queue
|
||||
|
||||
def execute(self, fs, waves, dt, t):
|
||||
""" Compute free surface for next time step.
|
||||
@param fs Free surface instance.
|
||||
@param waves Waves instance.
|
||||
@param dt Time step.
|
||||
@param t Actual time (without adding dt).
|
||||
"""
|
||||
self.fs = fs
|
||||
nx = self.fs['Nx']
|
||||
ny = self.fs['Ny']
|
||||
nF = nx*ny
|
||||
grad = self.evaluateGradient()
|
||||
# In order to improve results in really long simulations free surface
|
||||
# will performed considering external waves and second order effects
|
||||
# in two different ways. First external waves at time t will be
|
||||
# substracted, then second order waves will be computed, and finally
|
||||
# external waves at t+dt will be added.
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
pos = np.copy(self.fs['pos'][i,j])
|
||||
# Substract external waves at time t.
|
||||
for w in waves['data']:
|
||||
A = w[0]
|
||||
T = w[1]
|
||||
phase = w[2]
|
||||
heading = np.pi*w[3]/180.0
|
||||
wl = 0.5 * grav / np.pi * T*T
|
||||
k = 2.0*np.pi/wl
|
||||
frec = 2.0*np.pi/T
|
||||
l = pos[0]*np.cos(heading) + pos[1]*np.sin(heading)
|
||||
amp = A*np.sin(k*l - frec*t + phase)
|
||||
pos[2] = pos[2] - amp
|
||||
amp = - grav/frec*A*np.sin(k*l - frec*t + phase)
|
||||
self.fs['velPot'][i,j] = self.fs['velPot'][i,j] - amp
|
||||
amp = grav*A*np.cos(k*l - frec*t + phase)
|
||||
self.fs['accPot'][i,j] = self.fs['accPot'][i,j] - amp
|
||||
# Now compute second order waves using position copy,
|
||||
# where external waves are excluded, in order impose
|
||||
# free surface boundary condition relative to second
|
||||
# order phenomena.
|
||||
self.fs['velPot'][i,j] = self.fs['velPot'][i,j] + \
|
||||
dt*self.fs['accPot'][i,j]
|
||||
# self.fs['accPot'][i,j] = self.fs['accPot'][i,j] + \
|
||||
# grav*pos[2]
|
||||
# Restore external waves to velocity and acceleration
|
||||
# potentials.
|
||||
for w in waves['data']:
|
||||
A = w[0]
|
||||
T = w[1]
|
||||
phase = w[2]
|
||||
heading = np.pi*w[3]/180.0
|
||||
wl = 0.5 * grav / np.pi * T*T
|
||||
k = 2.0*np.pi/wl
|
||||
frec = 2.0*np.pi/T
|
||||
l = pos[0]*np.cos(heading) + pos[1]*np.sin(heading)
|
||||
amp = - grav/frec*A*np.sin(k*l - frec*(t+dt) + phase)
|
||||
self.fs['velPot'][i,j] = self.fs['velPot'][i,j] + amp
|
||||
amp = grav*A*np.cos(k*l - frec*(t+dt) + phase)
|
||||
self.fs['accPot'][i,j] = self.fs['accPot'][i,j] + amp
|
||||
# Update free surface point position
|
||||
gradVal = np.dot(np.abs(grad[i*ny+j]),grad[i*ny+j])
|
||||
gradVal = np.copysign(np.sqrt(np.abs(gradVal)), gradVal)
|
||||
self.fs['pos'][i,j][2] = self.fs['pos'][i,j][2] + dt*gradVal
|
||||
# Impose values at beach (far free surface)
|
||||
for i in range(0,nx):
|
||||
for j in [0,ny-1]:
|
||||
self.beach(i,j, waves, dt, t)
|
||||
for j in range(0,ny):
|
||||
for i in [0,nx-1]:
|
||||
self.beach(i,j, waves, dt, t)
|
||||
|
||||
def evaluateGradient(self):
|
||||
""" Evaluate potential gradients over free surface.
|
||||
@return Potential gradients.
|
||||
"""
|
||||
nx = self.fs['Nx']
|
||||
ny = self.fs['Ny']
|
||||
nF = nx*ny
|
||||
grad = np.ndarray((nF,3), dtype=np.float32)
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
pos = self.fs['pos'][i,j]
|
||||
grad[i*ny+j] = self.gradientphi(pos)
|
||||
gradVal = np.dot(np.abs(grad[i*ny+j]),grad[i*ny+j])
|
||||
gradVal = np.copysign(np.sqrt(np.abs(gradVal)), gradVal)
|
||||
return grad
|
||||
|
||||
def gradientphi(self, pos):
|
||||
""" Compute gradient over desired position.
|
||||
@param pos Point to evaluate.
|
||||
@return Potential gradient.
|
||||
"""
|
||||
nx = self.fs['Nx']
|
||||
ny = self.fs['Ny']
|
||||
grad = np.zeros(3, dtype=np.float32)
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
# Get source position (desingularized)
|
||||
srcPos = np.copy(self.fs['pos'][i,j])
|
||||
area = self.fs['area'][i,j]
|
||||
srcPos[2] = srcPos[2] + np.sqrt(area)
|
||||
src = self.fs['velSrc'][i,j]
|
||||
# Get distance between points
|
||||
d = pos-srcPos
|
||||
grad = grad + d/np.dot(d,d)*src*area
|
||||
# Discard Z induced effect by desingularization
|
||||
grad[2] = 0.
|
||||
return grad
|
||||
|
||||
def beach(self, i,j, waves, dt, t):
|
||||
""" Compute far free surface where only
|
||||
incident waves can be taken into account.
|
||||
@param i First free surface cell index.
|
||||
@param j Second free surface cell index.
|
||||
@param waves Waves instance.
|
||||
@param dt Time step.
|
||||
@param t Actual time (without adding dt).
|
||||
"""
|
||||
pos = self.fs['pos'][i,j]
|
||||
pos[2] = 0.
|
||||
self.fs['velPot'][i,j] = 0.
|
||||
self.fs['accPot'][i,j] = 0.
|
||||
for w in waves['data']:
|
||||
A = w[0]
|
||||
T = w[1]
|
||||
phase = w[2]
|
||||
heading = np.pi*w[3]/180.0
|
||||
wl = 0.5 * grav / np.pi * T*T
|
||||
k = 2.0*np.pi/wl
|
||||
frec = 2.0*np.pi/T
|
||||
l = pos[0]*np.cos(heading) + pos[1]*np.sin(heading)
|
||||
amp = A*np.sin(k*l - frec*(t+dt) + phase)
|
||||
self.fs['pos'][i,j][2] = self.fs['pos'][i,j][2] + amp
|
||||
amp = - grav/frec*A*np.sin(k*l - frec*(t+dt) + phase)
|
||||
self.fs['velPot'][i,j] = self.fs['velPot'][i,j] + amp
|
||||
amp = grav*A*np.cos(k*l - frec*(t+dt) + phase)
|
||||
self.fs['accPot'][i,j] = self.fs['accPot'][i,j] + amp
|
||||
|
|
@ -26,9 +26,9 @@ import numpy as np
|
|||
|
||||
grav=9.81
|
||||
|
||||
class perform:
|
||||
class simInitialization:
|
||||
def __init__(self, FSmesh, waves, context=None, queue=None):
|
||||
""" Constructor, includes program loading.
|
||||
""" Constructor.
|
||||
@param FSmesh Initial free surface mesh.
|
||||
@param waves Considered simulation waves (A,T,phi,heading).
|
||||
@param context OpenCL context where apply. Only for compatibility,
|
||||
|
@ -40,6 +40,11 @@ class perform:
|
|||
self.queue = queue
|
||||
self.loadData(FSmesh, waves)
|
||||
self.execute()
|
||||
# Compute time step
|
||||
self.dt = 0.1
|
||||
for w in self.waves['data']:
|
||||
if(self.dt > w[1]/200.0):
|
||||
self.dt = w[1]/200.0
|
||||
|
||||
def loadData(self, FSmesh, waves):
|
||||
""" Convert data to numpy format.
|
||||
|
@ -51,12 +56,12 @@ class perform:
|
|||
nW = len(waves)
|
||||
# Mesh data
|
||||
p = np.ndarray((nx,ny, 3), dtype=np.float32)
|
||||
v = np.ndarray((nx,ny, 3), dtype=np.float32)
|
||||
f = np.ndarray((nx,ny, 3), dtype=np.float32)
|
||||
n = np.ndarray((nx,ny, 3), dtype=np.float32)
|
||||
a = np.ndarray((nx,ny, 1), dtype=np.float32)
|
||||
phi = np.ndarray((nx,ny, 1), dtype=np.float32)
|
||||
Phi = np.ndarray((nx,ny, 1), dtype=np.float32)
|
||||
a = np.ndarray((nx,ny), dtype=np.float32)
|
||||
phi = np.ndarray((nx,ny), dtype=np.float32)
|
||||
Phi = np.ndarray((nx,ny), dtype=np.float32)
|
||||
s = np.ndarray((nx,ny), dtype=np.float32)
|
||||
ss = np.ndarray((nx,ny), dtype=np.float32)
|
||||
for i in range(0, nx):
|
||||
for j in range(0, ny):
|
||||
pos = FSmesh[i][j].pos
|
||||
|
@ -65,18 +70,16 @@ class perform:
|
|||
p[i,j,0] = pos.x
|
||||
p[i,j,1] = pos.y
|
||||
p[i,j,2] = pos.z
|
||||
v[i,j,0] = 0.
|
||||
v[i,j,1] = 0.
|
||||
v[i,j,2] = 0.
|
||||
f[i,j,0] = 0.
|
||||
f[i,j,1] = 0.
|
||||
f[i,j,2] = 0.
|
||||
n[i,j,0] = normal.x
|
||||
n[i,j,1] = normal.y
|
||||
n[i,j,2] = normal.z
|
||||
a[i,j] = area
|
||||
self.fs = {'Nx':nx, 'Ny':ny, 'pos':p, 'vel':v, 'acc':f, \
|
||||
'normal':n, 'area':a, 'velPot':phi, 'accPot':Phi}
|
||||
phi[i,j] = 0.
|
||||
Phi[i,j] = 0.
|
||||
s[i,j] = 0.
|
||||
ss[i,j] = 0.
|
||||
self.fs = {'Nx':nx, 'Ny':ny, 'pos':p, 'normal':n, 'area':a, \
|
||||
'velPot':phi, 'accPot':Phi, 'velSrc':s, 'accSrc':ss}
|
||||
# Waves data
|
||||
w = np.ndarray((nW, 4), dtype=np.float32)
|
||||
for i in range(0,nW):
|
||||
|
@ -85,6 +88,11 @@ class perform:
|
|||
w[i,2] = waves[i][2]
|
||||
w[i,3] = waves[i][3]
|
||||
self.waves = {'N':nW, 'data':w}
|
||||
# Linear system matrix
|
||||
nF = nx*ny
|
||||
nB = 0 # No body for the moment
|
||||
N = nx*ny + nB
|
||||
self.A = np.ndarray((N, N), dtype=np.float32)
|
||||
|
||||
def execute(self):
|
||||
""" Compute initial conditions. """
|
||||
|
@ -92,6 +100,7 @@ class perform:
|
|||
ny = self.fs['Ny']
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
self.fs['pos'][i,j][2] = 0.
|
||||
for w in self.waves['data']:
|
||||
A = w[0]
|
||||
T = w[1]
|
||||
|
@ -104,11 +113,7 @@ class perform:
|
|||
l = pos[0]*np.cos(heading) + pos[1]*np.sin(heading)
|
||||
amp = A*np.sin(k*l + phase)
|
||||
self.fs['pos'][i,j][2] = self.fs['pos'][i,j][2] + amp
|
||||
amp = frec*A*np.cos(k*l + phase)
|
||||
self.fs['vel'][i,j][2] = self.fs['vel'][i,j][2] - amp
|
||||
amp = frec*frec*A*np.sin(k*l + phase)
|
||||
self.fs['acc'][i,j][2] = self.fs['acc'][i,j][2] - amp
|
||||
amp = grav/frec*A*np.sin(k*l + phase)
|
||||
amp = - grav/frec*A*np.sin(k*l + phase)
|
||||
self.fs['velPot'][i,j] = self.fs['velPot'][i,j] + amp
|
||||
amp = grav*A*np.cos(k*l + phase)
|
||||
self.fs['accPot'][i,j] = self.fs['accPot'][i,j] + amp
|
||||
|
|
79
src/Mod/Ship/simRun/Sim/matrixGen.py
Normal file
79
src/Mod/Ship/simRun/Sim/matrixGen.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2011, 2012 *
|
||||
#* Jose Luis Cercos Pita <jlcercos@gmail.com> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* This program is distributed in the hope that it will be useful, *
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
#* GNU Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library General Public *
|
||||
#* License along with this program; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# numpy
|
||||
import numpy as np
|
||||
|
||||
grav=9.81
|
||||
|
||||
class simMatrixGen:
|
||||
def __init__(self, context=None, queue=None):
|
||||
""" Constructor.
|
||||
@param context OpenCL context where apply. Only for compatibility,
|
||||
must be None.
|
||||
@param queue OpenCL command queue. Only for compatibility,
|
||||
must be None.
|
||||
"""
|
||||
self.context = context
|
||||
self.queue = queue
|
||||
|
||||
def execute(self, fs, A):
|
||||
""" Compute system matrix.
|
||||
@param fs Free surface instance.
|
||||
@param A Linear system matrix.
|
||||
"""
|
||||
self.fs = fs
|
||||
nx = self.fs['Nx']
|
||||
ny = self.fs['Ny']
|
||||
nF = nx*ny
|
||||
nB = 0 # No body for the moment
|
||||
N = nx*ny + nB
|
||||
# Fluid sources rows
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
# Append fluid effect
|
||||
pos = self.fs['pos'][i,j]
|
||||
A[i*ny+j,0:nF] = self.fluidEffect(pos)
|
||||
# Append body effect
|
||||
# ...
|
||||
|
||||
def fluidEffect(self, pos):
|
||||
""" Compute fluid effect terms over desired position. Desingularized
|
||||
sources must taken into account.
|
||||
@param pos Point to evaluate.
|
||||
@return Fluid effect row.
|
||||
"""
|
||||
nx = self.fs['Nx']
|
||||
ny = self.fs['Ny']
|
||||
nF = nx*ny
|
||||
row = np.ndarray(nF, dtype=np.float32)
|
||||
for i in range(0,nx):
|
||||
for j in range(0,ny):
|
||||
# Get source position (desingularized)
|
||||
source = np.copy(self.fs['pos'][i,j])
|
||||
area = self.fs['area'][i,j]
|
||||
source[2] = source[2] + np.sqrt(area)
|
||||
# Get distance between points
|
||||
d = np.linalg.norm(pos-source)
|
||||
row[i*ny+j] = np.log(d)*area
|
||||
return row
|
|
@ -21,7 +21,6 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import time
|
||||
from math import *
|
||||
import threading
|
||||
|
||||
|
@ -49,11 +48,12 @@ class Singleton(type):
|
|||
|
||||
class FreeCADShipSimulation(threading.Thread):
|
||||
__metaclass__ = Singleton
|
||||
def __init__ (self, device, endTime, output, FSmesh, waves):
|
||||
def __init__ (self, device, endTime, output, simInstance, FSmesh, waves):
|
||||
""" Thread constructor.
|
||||
@param device Device to use.
|
||||
@param endTime Maximum simulation time.
|
||||
@param output [Rate,Type] Output rate, Type=0 if FPS, 1 if IPF.
|
||||
@param simInstance Simulaation instance.
|
||||
@param FSmesh Free surface mesh faces.
|
||||
@param waves Waves parameters (A,T,phi,heading)
|
||||
"""
|
||||
|
@ -71,6 +71,7 @@ class FreeCADShipSimulation(threading.Thread):
|
|||
# Storage data
|
||||
self.endTime = endTime
|
||||
self.output = output
|
||||
self.sim = simInstance
|
||||
self.FSmesh = FSmesh
|
||||
self.waves = waves
|
||||
|
||||
|
@ -80,19 +81,37 @@ class FreeCADShipSimulation(threading.Thread):
|
|||
self.active = True
|
||||
# Simulation stuff
|
||||
if self.device == None:
|
||||
from Sim import initialization
|
||||
from Sim import *
|
||||
else:
|
||||
from clSim import initialization
|
||||
msg = Translator.translate("\t[Sim]: Initializating OpenCL...\n")
|
||||
from clSim import *
|
||||
msg = Translator.translate("\t[Sim]: Initializating...\n")
|
||||
FreeCAD.Console.PrintMessage(msg)
|
||||
init = initialization.perform(self.FSmesh,self.waves,self.context,self.queue)
|
||||
msg = Translator.translate("\t[Sim]: Iterating (outputs will be noticed)...\n")
|
||||
init = simInitialization(self.FSmesh,self.waves,self.context,self.queue)
|
||||
matGen = simMatrixGen(self.context,self.queue)
|
||||
solver = simComputeSources(self.context,self.queue)
|
||||
fsEvol = simFSEvolution(self.context,self.queue)
|
||||
A = init.A
|
||||
FS = init.fs
|
||||
waves = init.waves
|
||||
dt = init.dt
|
||||
self.t = 0.0
|
||||
self.FS = FS
|
||||
nx = FS['Nx']
|
||||
ny = FS['Ny']
|
||||
msg = Translator.translate("\t[Sim]: Iterating...\n")
|
||||
FreeCAD.Console.PrintMessage(msg)
|
||||
while self.active:
|
||||
print("Im thread, Im running...")
|
||||
time.sleep(1)
|
||||
# ...
|
||||
print("Im thread, step done!")
|
||||
while self.active and self.t < self.endTime:
|
||||
msg = Translator.translate("\t\t[Sim]: Generating linear system matrix...\n")
|
||||
FreeCAD.Console.PrintMessage(msg)
|
||||
matGen.execute(FS, A)
|
||||
msg = Translator.translate("\t\t[Sim]: Solving linear systems...\n")
|
||||
FreeCAD.Console.PrintMessage(msg)
|
||||
solver.execute(FS, A)
|
||||
msg = Translator.translate("\t\t[Sim]: Time integrating...\n")
|
||||
FreeCAD.Console.PrintMessage(msg)
|
||||
fsEvol.execute(FS, waves, dt, self.t)
|
||||
self.t = self.t + dt
|
||||
FreeCAD.Console.PrintMessage('t = %g s\n' % (self.t))
|
||||
# Set thread as stopped (and prepare it to restarting)
|
||||
self.active = False
|
||||
threading.Event().set()
|
||||
|
|
|
@ -69,7 +69,7 @@ class TaskPanel:
|
|||
msg = Translator.translate("Launching simulation...\n")
|
||||
App.Console.PrintMessage(msg)
|
||||
# Build simulation thread
|
||||
simulator = Sim(device, endTime, output, FSMesh, waves)
|
||||
simulator = Sim(device, endTime, output, self.sim, FSMesh, waves)
|
||||
simulator.start()
|
||||
msg = Translator.translate("Done!\n")
|
||||
App.Console.PrintMessage(msg)
|
||||
|
|
|
@ -1350,6 +1350,8 @@ void SketchObject::rebuildExternalGeometry(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rebuildVertexIndex();
|
||||
}
|
||||
|
||||
std::vector<Part::Geometry*> SketchObject::getCompleteGeometry(void) const
|
||||
|
@ -1491,8 +1493,6 @@ void SketchObject::Restore(XMLReader &reader)
|
|||
{
|
||||
// read the father classes
|
||||
Part::Part2DObject::Restore(reader);
|
||||
Constraints.acceptGeometry(getCompleteGeometry());
|
||||
rebuildVertexIndex();
|
||||
}
|
||||
|
||||
void SketchObject::onChanged(const App::Property* prop)
|
||||
|
|
|
@ -1636,15 +1636,7 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
|
|||
const std::vector<Sketcher::Constraint *> &ConStr = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject())->Constraints.getValues();
|
||||
Sketcher::Constraint *constr = ConStr[ConStr.size() -1];
|
||||
|
||||
float sf = 1.f;
|
||||
Gui::Document *doc = getActiveGuiDocument();
|
||||
if (doc && doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) {
|
||||
SketcherGui::ViewProviderSketch *vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
|
||||
sf = vp->getScaleFactor();
|
||||
|
||||
constr->LabelDistance = 2. * sf;
|
||||
vp->draw(); // Redraw
|
||||
}
|
||||
updateDatumDistance(getActiveGuiDocument(), constr);
|
||||
|
||||
//updateActive();
|
||||
getSelection().clearSelection();
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include <Gui/Application.h>
|
||||
|
@ -142,15 +143,20 @@ public:
|
|||
|
||||
virtual void mouseMove(Base::Vector2D onSketchPos)
|
||||
{
|
||||
setPositionText(onSketchPos);
|
||||
|
||||
if (Mode==STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Mode==STATUS_SEEK_Second){
|
||||
float length = (onSketchPos - EditCurve[0]).Length();
|
||||
float angle = (onSketchPos - EditCurve[0]).GetAngle(Base::Vector2D(1.f,0.f));
|
||||
SbString text;
|
||||
text.sprintf(" (%.1f,%.1fdeg)", length, angle * 180 / M_PI);
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
EditCurve[1] = onSketchPos;
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) {
|
||||
|
@ -301,15 +307,21 @@ public:
|
|||
|
||||
virtual void mouseMove(Base::Vector2D onSketchPos)
|
||||
{
|
||||
setPositionText(onSketchPos);
|
||||
|
||||
if (Mode==STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Mode==STATUS_SEEK_Second) {
|
||||
float dx = onSketchPos.fX - EditCurve[0].fX;
|
||||
float dy = onSketchPos.fY - EditCurve[0].fY;
|
||||
SbString text;
|
||||
text.sprintf(" (%.1f x %.1f)", dx, dy);
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
EditCurve[2] = onSketchPos;
|
||||
EditCurve[1] = Base::Vector2D(onSketchPos.fX ,EditCurve[0].fY);
|
||||
EditCurve[3] = Base::Vector2D(EditCurve[0].fX,onSketchPos.fY);
|
||||
|
@ -488,50 +500,106 @@ class DrawSketchHandlerLineSet: public DrawSketchHandler
|
|||
{
|
||||
public:
|
||||
DrawSketchHandlerLineSet()
|
||||
: Mode(STATUS_SEEK_First),LineMode(LINE_MODE_Line),EditCurve(2),
|
||||
firstVertex(-1),firstCurve(-1),previousCurve(-1),previousPosId(-1),
|
||||
isTangent(false) {}
|
||||
: Mode(STATUS_SEEK_First),SegmentMode(SEGMENT_MODE_Line),
|
||||
TransitionMode(TRANSITION_MODE_Free),suppressTransition(false),EditCurve(2),
|
||||
firstVertex(-1),firstCurve(-1),previousCurve(-1),previousPosId(Sketcher::none) {}
|
||||
virtual ~DrawSketchHandlerLineSet() {}
|
||||
/// mode table
|
||||
enum SelectMode {
|
||||
enum SELECT_MODE {
|
||||
STATUS_SEEK_First, /**< enum value ----. */
|
||||
STATUS_SEEK_Second, /**< enum value ----. */
|
||||
STATUS_Do,
|
||||
STATUS_Close
|
||||
};
|
||||
|
||||
enum SelectLineMode
|
||||
enum SEGMENT_MODE
|
||||
{
|
||||
LINE_MODE_Arc,
|
||||
LINE_MODE_Line
|
||||
SEGMENT_MODE_Arc,
|
||||
SEGMENT_MODE_Line
|
||||
};
|
||||
|
||||
enum TRANSITION_MODE
|
||||
{
|
||||
TRANSITION_MODE_Free,
|
||||
TRANSITION_MODE_Tangent,
|
||||
TRANSITION_MODE_Perpendicular_L,
|
||||
TRANSITION_MODE_Perpendicular_R
|
||||
};
|
||||
|
||||
virtual void registerPressedKey(bool pressed, int key)
|
||||
{
|
||||
if (key == SoKeyboardEvent::A && pressed && previousCurve != -1) {
|
||||
if (LineMode != LINE_MODE_Arc) {
|
||||
Base::Vector2D onSketchPos = EditCurve[isTangent ? 2 : 1];
|
||||
LineMode = LINE_MODE_Arc;
|
||||
if (previousCurve != -1)
|
||||
isTangent = true;
|
||||
else
|
||||
isTangent = false;
|
||||
EditCurve.resize(32);
|
||||
mouseMove(onSketchPos); // trigger an update of EditCurve
|
||||
if (Mode != STATUS_SEEK_Second)
|
||||
return; // SegmentMode can be changed only in STATUS_SEEK_Second mode
|
||||
|
||||
if (key == SoKeyboardEvent::M && pressed && previousCurve != -1) {
|
||||
// loop through the following modes:
|
||||
// SEGMENT_MODE_Line, TRANSITION_MODE_Free / TRANSITION_MODE_Tangent
|
||||
// SEGMENT_MODE_Line, TRANSITION_MODE_Perpendicular_L
|
||||
// SEGMENT_MODE_Line, TRANSITION_MODE_Tangent / TRANSITION_MODE_Free
|
||||
// SEGMENT_MODE_Arc, TRANSITION_MODE_Tangent
|
||||
// SEGMENT_MODE_Arc, TRANSITION_MODE_Perpendicular_L
|
||||
// SEGMENT_MODE_Arc, TRANSITION_MODE_Perpendicular_R
|
||||
|
||||
Base::Vector2D onSketchPos;
|
||||
if (SegmentMode == SEGMENT_MODE_Line)
|
||||
onSketchPos = EditCurve[EditCurve.size()-1];
|
||||
else
|
||||
onSketchPos = EditCurve[29];
|
||||
|
||||
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(previousCurve);
|
||||
|
||||
if (SegmentMode == SEGMENT_MODE_Line) {
|
||||
switch (TransitionMode) {
|
||||
case TRANSITION_MODE_Free:
|
||||
if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { // 3rd mode
|
||||
SegmentMode = SEGMENT_MODE_Arc;
|
||||
TransitionMode = TRANSITION_MODE_Tangent;
|
||||
}
|
||||
else // 1st mode
|
||||
TransitionMode = TRANSITION_MODE_Perpendicular_L;
|
||||
break;
|
||||
case TRANSITION_MODE_Perpendicular_L: // 2nd mode
|
||||
if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
|
||||
TransitionMode = TRANSITION_MODE_Free;
|
||||
else
|
||||
TransitionMode = TRANSITION_MODE_Tangent;
|
||||
break;
|
||||
case TRANSITION_MODE_Tangent:
|
||||
if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) // 1st mode
|
||||
TransitionMode = TRANSITION_MODE_Perpendicular_L;
|
||||
else { // 3rd mode
|
||||
SegmentMode = SEGMENT_MODE_Arc;
|
||||
TransitionMode = TRANSITION_MODE_Tangent;
|
||||
}
|
||||
break;
|
||||
default: // unexpected mode
|
||||
TransitionMode = TRANSITION_MODE_Free;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Vector2D onSketchPos = EditCurve[29];
|
||||
LineMode = LINE_MODE_Line;
|
||||
if (previousCurve != -1) {
|
||||
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(previousCurve);
|
||||
if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
|
||||
isTangent = true;
|
||||
else
|
||||
isTangent = false;
|
||||
switch (TransitionMode) {
|
||||
case TRANSITION_MODE_Tangent: // 4th mode
|
||||
TransitionMode = TRANSITION_MODE_Perpendicular_L;
|
||||
break;
|
||||
case TRANSITION_MODE_Perpendicular_L: // 5th mode
|
||||
TransitionMode = TRANSITION_MODE_Perpendicular_R;
|
||||
break;
|
||||
default: // 6th mode (Perpendicular_R) + unexpexted mode
|
||||
SegmentMode = SEGMENT_MODE_Line;
|
||||
if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
|
||||
TransitionMode = TRANSITION_MODE_Tangent;
|
||||
else
|
||||
TransitionMode = TRANSITION_MODE_Free;
|
||||
break;
|
||||
}
|
||||
EditCurve.resize(isTangent ? 3 : 2);
|
||||
mouseMove(onSketchPos); // trigger an update of EditCurve
|
||||
}
|
||||
|
||||
if (SegmentMode == SEGMENT_MODE_Line)
|
||||
EditCurve.resize(TransitionMode == TRANSITION_MODE_Free ? 2 : 3);
|
||||
else
|
||||
EditCurve.resize(32);
|
||||
mouseMove(onSketchPos); // trigger an update of EditCurve
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -542,31 +610,59 @@ public:
|
|||
|
||||
virtual void mouseMove(Base::Vector2D onSketchPos)
|
||||
{
|
||||
setPositionText(onSketchPos);
|
||||
suppressTransition = false;
|
||||
if (Mode==STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Mode==STATUS_SEEK_Second){
|
||||
if (LineMode == LINE_MODE_Line) {
|
||||
EditCurve[isTangent ? 2 : 1] = onSketchPos;
|
||||
if (isTangent) {
|
||||
if (SegmentMode == SEGMENT_MODE_Line) {
|
||||
EditCurve[EditCurve.size()-1] = onSketchPos;
|
||||
if (TransitionMode == TRANSITION_MODE_Tangent) {
|
||||
Base::Vector2D Tangent(dirVec.x,dirVec.y);
|
||||
EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Tangent);
|
||||
if (EditCurve[1] * Tangent < 0) {
|
||||
EditCurve[1] = EditCurve[2];
|
||||
suppressTransition = true;
|
||||
}
|
||||
else
|
||||
EditCurve[1] = EditCurve[0] + EditCurve[1];
|
||||
}
|
||||
else if (TransitionMode == TRANSITION_MODE_Perpendicular_L ||
|
||||
TransitionMode == TRANSITION_MODE_Perpendicular_R) {
|
||||
Base::Vector2D Perpendicular(-dirVec.y,dirVec.x);
|
||||
EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Perpendicular);
|
||||
EditCurve[1] = EditCurve[0] + EditCurve[1];
|
||||
}
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
if (!isTangent) {
|
||||
|
||||
float length = (EditCurve[1] - EditCurve[0]).Length();
|
||||
float angle = (EditCurve[1] - EditCurve[0]).GetAngle(Base::Vector2D(1.f,0.f));
|
||||
|
||||
SbString text;
|
||||
text.sprintf(" (%.1f,%.1fdeg)", length, angle * 180 / M_PI);
|
||||
setPositionText(EditCurve[1], text);
|
||||
|
||||
if (TransitionMode == TRANSITION_MODE_Free) {
|
||||
if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) {
|
||||
renderSuggestConstraintsCursor(sugConstr2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (LineMode == LINE_MODE_Arc) {
|
||||
Base::Vector2D Tangent(dirVec.x,dirVec.y);
|
||||
else if (SegmentMode == SEGMENT_MODE_Arc) {
|
||||
Base::Vector2D Tangent;
|
||||
if (TransitionMode == TRANSITION_MODE_Tangent)
|
||||
Tangent = Base::Vector2D(dirVec.x,dirVec.y);
|
||||
else if (TransitionMode == TRANSITION_MODE_Perpendicular_L)
|
||||
Tangent = Base::Vector2D(-dirVec.y,dirVec.x);
|
||||
else if (TransitionMode == TRANSITION_MODE_Perpendicular_R)
|
||||
Tangent = Base::Vector2D(dirVec.y,-dirVec.x);
|
||||
|
||||
float theta = Tangent.GetAngle(onSketchPos - EditCurve[0]);
|
||||
arcRadius = (onSketchPos - EditCurve[0]).Length()/(2.0*sin(theta));
|
||||
// At this point we need a unit normal vector pointing torwards
|
||||
|
@ -580,11 +676,10 @@ public:
|
|||
float y3 = onSketchPos.fY;
|
||||
if ((x2*y3-x3*y2)-(x1*y3-x3*y1)+(x1*y2-x2*y1) > 0)
|
||||
arcRadius *= -1;
|
||||
if (boost::math::isnan(arcRadius) || boost::math::isinf(arcRadius))
|
||||
arcRadius = 0.f;
|
||||
|
||||
Base::Vector3d centerVec = dirVec % Base::Vector3d(0.f,0.f,1.0);
|
||||
centerVec.Normalize(); // this step should actually be redundant
|
||||
|
||||
CenterPoint = EditCurve[0] + Base::Vector2D(arcRadius * centerVec.x, arcRadius * centerVec.y);
|
||||
CenterPoint = EditCurve[0] + Base::Vector2D(arcRadius * Tangent.fY, -arcRadius * Tangent.fX);
|
||||
|
||||
float rx = EditCurve[0].fX - CenterPoint.fX;
|
||||
float ry = EditCurve[0].fY - CenterPoint.fY;
|
||||
|
@ -594,6 +689,8 @@ public:
|
|||
float rxe = onSketchPos.fX - CenterPoint.fX;
|
||||
float rye = onSketchPos.fY - CenterPoint.fY;
|
||||
float arcAngle = atan2(-rxe*ry + rye*rx, rxe*rx + rye*ry);
|
||||
if (boost::math::isnan(arcAngle) || boost::math::isinf(arcAngle))
|
||||
arcAngle = 0.f;
|
||||
if (arcRadius >= 0 && arcAngle > 0)
|
||||
arcAngle -= 2*M_PI;
|
||||
if (arcRadius < 0 && arcAngle < 0)
|
||||
|
@ -611,6 +708,11 @@ public:
|
|||
EditCurve[31] = EditCurve[0];
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
|
||||
SbString text;
|
||||
text.sprintf(" (%.1fR,%.1fdeg)", std::abs(arcRadius), arcAngle * 180 / M_PI);
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr2);
|
||||
return;
|
||||
|
@ -622,35 +724,45 @@ public:
|
|||
|
||||
virtual bool pressButton(Base::Vector2D onSketchPos)
|
||||
{
|
||||
if (Mode==STATUS_SEEK_First) {
|
||||
// remember our first point
|
||||
firstVertex = getHighestVertexIndex() + 1;
|
||||
firstCurve = getHighestCurveIndex() + 1;
|
||||
// TODO: here we should check if there is a preselected point
|
||||
// and set up a transition from the neighbouring segment.
|
||||
// (peviousCurve, previousPosId, dirVec, isTangent)
|
||||
// in that case we should set firstCurve and firstVertex to -1
|
||||
// in order to disable closing the wire
|
||||
if (LineMode == LINE_MODE_Line)
|
||||
EditCurve.resize(isTangent ? 3 : 2);
|
||||
else if (LineMode == LINE_MODE_Arc)
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
|
||||
EditCurve[0] = onSketchPos; // this may be overwritten if previousCurve is found
|
||||
|
||||
// here we check if there is a preselected point and
|
||||
// we set up a transition from the neighbouring segment.
|
||||
// (peviousCurve, previousPosId, dirVec, TransitionMode)
|
||||
for (int i=0; i < sugConstr1.size(); i++)
|
||||
if (sugConstr1[i].Type == Sketcher::Coincident) {
|
||||
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(sugConstr1[i].GeoId);
|
||||
if ((geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
|
||||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) &&
|
||||
(sugConstr1[i].PosId == Sketcher::start ||
|
||||
sugConstr1[i].PosId == Sketcher::end)) {
|
||||
previousCurve = sugConstr1[i].GeoId;
|
||||
previousPosId = sugConstr1[i].PosId;
|
||||
updateTransitionData(previousCurve,previousPosId); // -> dirVec, EditMode[0]
|
||||
if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
|
||||
TransitionMode = TRANSITION_MODE_Tangent;
|
||||
sugConstr1.erase(sugConstr1.begin()+i); // actually we should clear the vector completely
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// in case a transition is set up, firstCurve and firstVertex should
|
||||
// remain set to -1 in order to disable closing the wire
|
||||
if (previousCurve == -1) {
|
||||
// remember our first point
|
||||
firstVertex = getHighestVertexIndex() + 1;
|
||||
firstCurve = getHighestCurveIndex() + 1;
|
||||
}
|
||||
|
||||
if (SegmentMode == SEGMENT_MODE_Line)
|
||||
EditCurve.resize(TransitionMode == TRANSITION_MODE_Free ? 2 : 3);
|
||||
else if (SegmentMode == SEGMENT_MODE_Arc)
|
||||
EditCurve.resize(32);
|
||||
EditCurve[0] = onSketchPos;
|
||||
Mode = STATUS_SEEK_Second;
|
||||
}
|
||||
else if (Mode==STATUS_SEEK_Second) {
|
||||
if (LineMode == LINE_MODE_Line) {
|
||||
EditCurve[isTangent ? 2 : 1] = onSketchPos;
|
||||
if (isTangent) {
|
||||
Base::Vector2D Tangent(dirVec.x,dirVec.y);
|
||||
EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Tangent);
|
||||
EditCurve[1] = EditCurve[0] + EditCurve[1];
|
||||
}
|
||||
}
|
||||
else if (LineMode == LINE_MODE_Arc)
|
||||
EditCurve[29] = onSketchPos; // not so important
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
applyCursor();
|
||||
else if (Mode == STATUS_SEEK_Second) {
|
||||
// exit on clicking exactly at the same position (e.g. double click)
|
||||
if (onSketchPos == EditCurve[0]) {
|
||||
unsetCursor();
|
||||
|
@ -659,7 +771,7 @@ public:
|
|||
sketchgui->drawEdit(EditCurve);
|
||||
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
|
||||
}
|
||||
if (sketchgui->getPreselectPoint() == firstVertex)
|
||||
if (sketchgui->getPreselectPoint() == firstVertex && firstVertex != -1)
|
||||
Mode = STATUS_Close;
|
||||
else
|
||||
Mode = STATUS_Do;
|
||||
|
@ -671,7 +783,7 @@ public:
|
|||
{
|
||||
if (Mode == STATUS_Do || Mode == STATUS_Close) {
|
||||
|
||||
if (LineMode == LINE_MODE_Line) {
|
||||
if (SegmentMode == SEGMENT_MODE_Line) {
|
||||
// open the transaction
|
||||
Gui::Command::openCommand("Add line to sketch wire");
|
||||
// issue the geometry
|
||||
|
@ -680,7 +792,11 @@ public:
|
|||
sketchgui->getObject()->getNameInDocument(),
|
||||
EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY);
|
||||
}
|
||||
else if (LineMode == LINE_MODE_Arc) { // We're dealing with an Arc
|
||||
else if (SegmentMode == SEGMENT_MODE_Arc) { // We're dealing with an Arc
|
||||
if (!boost::math::isnormal(arcRadius)) {
|
||||
Mode = STATUS_SEEK_Second;
|
||||
return true;
|
||||
}
|
||||
Gui::Command::openCommand("Add arc to sketch wire");
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.addGeometry(Part.ArcOfCircle"
|
||||
|
@ -691,15 +807,24 @@ public:
|
|||
}
|
||||
// issue the constraint
|
||||
if (previousCurve != -1) {
|
||||
int lastCurve = previousCurve+1;
|
||||
int lastStartPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 2 : 1;
|
||||
int lastEndPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2;
|
||||
// in case of a tangency constraint, the coincident constraint is redundant
|
||||
int lastCurve = getHighestCurveIndex();
|
||||
Sketcher::PointPos lastStartPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ?
|
||||
Sketcher::end : Sketcher::start;
|
||||
Sketcher::PointPos lastEndPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ?
|
||||
Sketcher::start : Sketcher::end;
|
||||
// in case of a tangency constraint, the coincident constraint is redundant
|
||||
std::string constrType = "Coincident";
|
||||
if (!suppressTransition) {
|
||||
if (TransitionMode == TRANSITION_MODE_Tangent)
|
||||
constrType = "Tangent";
|
||||
else if (TransitionMode == TRANSITION_MODE_Perpendicular_L ||
|
||||
TransitionMode == TRANSITION_MODE_Perpendicular_R)
|
||||
constrType = "Perpendicular";
|
||||
}
|
||||
Gui::Command::doCommand(Gui::Command::Doc,
|
||||
"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('%s',%i,%i,%i,%i)) ",
|
||||
sketchgui->getObject()->getNameInDocument(),
|
||||
isTangent ? "Tangent" : "Coincident",
|
||||
previousCurve, previousPosId /* == 2 */, lastCurve, lastStartPosId);
|
||||
sketchgui->getObject()->getNameInDocument(), constrType.c_str(),
|
||||
previousCurve, previousPosId, lastCurve, lastStartPosId);
|
||||
if (Mode == STATUS_Close) {
|
||||
int firstGeoId;
|
||||
Sketcher::PointPos firstPosId;
|
||||
|
@ -750,61 +875,74 @@ public:
|
|||
|
||||
// remember the vertex for the next rounds constraint..
|
||||
previousCurve = getHighestCurveIndex();
|
||||
previousPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2;
|
||||
previousPosId = (SegmentMode == SEGMENT_MODE_Arc && startAngle > endAngle) ?
|
||||
Sketcher::start : Sketcher::end; // cw arcs are rendered in reverse
|
||||
|
||||
// setup for the next line segment
|
||||
// Use updated endPoint as autoconstraints can modify the position
|
||||
// Need to determine if the previous element was a line or an arc or ???
|
||||
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(getHighestCurveIndex());
|
||||
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geom);
|
||||
EditCurve[0] = Base::Vector2D(lineSeg->getEndPoint().x, lineSeg->getEndPoint().y);
|
||||
dirVec.Set(lineSeg->getEndPoint().x - lineSeg->getStartPoint().x,
|
||||
lineSeg->getEndPoint().y - lineSeg->getStartPoint().y,
|
||||
0.f);
|
||||
}
|
||||
else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
||||
assert(LineMode == LINE_MODE_Arc);
|
||||
const Part::GeomArcOfCircle *arcSeg = dynamic_cast<const Part::GeomArcOfCircle *>(geom);
|
||||
if (startAngle > endAngle) {
|
||||
EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint().x,arcSeg->getStartPoint().y);
|
||||
dirVec = Base::Vector3d(0.f,0.f,-1.0) % (arcSeg->getStartPoint()-arcSeg->getCenter());
|
||||
}
|
||||
else { // cw arcs are rendered in reverse
|
||||
EditCurve[0] = Base::Vector2D(arcSeg->getEndPoint().x,arcSeg->getEndPoint().y);
|
||||
dirVec = Base::Vector3d(0.f,0.f,1.0) % (arcSeg->getEndPoint()-arcSeg->getCenter());
|
||||
}
|
||||
}
|
||||
dirVec.Normalize();
|
||||
// calculate dirVec and EditCurve[0]
|
||||
updateTransitionData(previousCurve,previousPosId);
|
||||
|
||||
applyCursor();
|
||||
Mode = STATUS_SEEK_Second;
|
||||
isTangent = (LineMode == LINE_MODE_Arc);
|
||||
LineMode = LINE_MODE_Line;
|
||||
EditCurve.resize(isTangent ? 3 : 2);
|
||||
EditCurve[1] = EditCurve[0];
|
||||
if (isTangent)
|
||||
if (SegmentMode == SEGMENT_MODE_Arc) {
|
||||
TransitionMode = TRANSITION_MODE_Tangent;
|
||||
EditCurve.resize(3);
|
||||
EditCurve[2] = EditCurve[0];
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
}
|
||||
else {
|
||||
TransitionMode = TRANSITION_MODE_Free;
|
||||
EditCurve.resize(2);
|
||||
}
|
||||
SegmentMode = SEGMENT_MODE_Line;
|
||||
EditCurve[1] = EditCurve[0];
|
||||
mouseMove(onSketchPos); // trigger an update of EditCurve
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
SelectMode Mode;
|
||||
SelectLineMode LineMode;
|
||||
SELECT_MODE Mode;
|
||||
SEGMENT_MODE SegmentMode;
|
||||
TRANSITION_MODE TransitionMode;
|
||||
bool suppressTransition;
|
||||
|
||||
std::vector<Base::Vector2D> EditCurve;
|
||||
int firstVertex;
|
||||
int firstCurve;
|
||||
int previousPosId;
|
||||
int previousCurve;
|
||||
Sketcher::PointPos previousPosId;
|
||||
std::vector<AutoConstraint> sugConstr1, sugConstr2;
|
||||
|
||||
Base::Vector2D CenterPoint;
|
||||
Base::Vector3d dirVec;
|
||||
bool isTangent;
|
||||
float startAngle, endAngle, arcRadius;
|
||||
|
||||
void updateTransitionData(int GeoId, Sketcher::PointPos PosId) {
|
||||
|
||||
// Use updated startPoint/endPoint as autoconstraints can modify the position
|
||||
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId);
|
||||
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geom);
|
||||
EditCurve[0] = Base::Vector2D(lineSeg->getEndPoint().x, lineSeg->getEndPoint().y);
|
||||
dirVec.Set(lineSeg->getEndPoint().x - lineSeg->getStartPoint().x,
|
||||
lineSeg->getEndPoint().y - lineSeg->getStartPoint().y,
|
||||
0.f);
|
||||
if (PosId == Sketcher::start)
|
||||
dirVec *= -1;
|
||||
}
|
||||
else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
||||
const Part::GeomArcOfCircle *arcSeg = dynamic_cast<const Part::GeomArcOfCircle *>(geom);
|
||||
if (PosId == Sketcher::start) {
|
||||
EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint().x,arcSeg->getStartPoint().y);
|
||||
dirVec = Base::Vector3d(0.f,0.f,-1.0) % (arcSeg->getStartPoint()-arcSeg->getCenter());
|
||||
}
|
||||
else {
|
||||
EditCurve[0] = Base::Vector2D(arcSeg->getEndPoint().x,arcSeg->getEndPoint().y);
|
||||
dirVec = Base::Vector3d(0.f,0.f,1.0) % (arcSeg->getEndPoint()-arcSeg->getCenter());
|
||||
}
|
||||
}
|
||||
dirVec.Normalize();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -916,11 +1054,10 @@ public:
|
|||
|
||||
// Display radius and start angle
|
||||
float radius = (onSketchPos - EditCurve[0]).Length();
|
||||
float angle = atan2f(dy_ , dx_) * 180 / M_PI;
|
||||
float angle = atan2f(dy_ , dx_);
|
||||
|
||||
char buf[40];
|
||||
sprintf( buf, " (R%.1f,%.1f)", radius, angle);
|
||||
std::string text = buf;
|
||||
SbString text;
|
||||
text.sprintf(" (%.1fR,%.1fdeg)", radius, angle * 180 / M_PI);
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
|
@ -941,12 +1078,11 @@ public:
|
|||
EditCurve[i] = Base::Vector2D(CenterPoint.fX + dx, CenterPoint.fY + dy);
|
||||
}
|
||||
|
||||
// Display radius and end angle
|
||||
// Display radius and arc angle
|
||||
float radius = (onSketchPos - EditCurve[0]).Length();
|
||||
|
||||
char buf[40];
|
||||
sprintf( buf, " (R%.1f,%.1f)", radius, arcAngle * 180 / M_PI);
|
||||
std::string text = buf;
|
||||
SbString text;
|
||||
text.sprintf(" (%.1fR,%.1fdeg)", radius, arcAngle * 180 / M_PI);
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
|
@ -1154,9 +1290,8 @@ public:
|
|||
// Display radius for user
|
||||
float radius = (onSketchPos - EditCurve[0]).Length();
|
||||
|
||||
char buf[40];
|
||||
sprintf( buf, "R%.1f", radius);
|
||||
std::string text = buf;
|
||||
SbString text;
|
||||
text.sprintf(" (%.1fR)", radius);
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
|
|
|
@ -381,7 +381,7 @@ void DrawSketchHandler::renderSuggestConstraintsCursor(std::vector<AutoConstrain
|
|||
applyCursor(newCursor);
|
||||
}
|
||||
|
||||
void DrawSketchHandler::setPositionText(const Base::Vector2D &Pos, const std::string &text)
|
||||
void DrawSketchHandler::setPositionText(const Base::Vector2D &Pos, const SbString &text)
|
||||
{
|
||||
sketchgui->setPositionText(Pos, text);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
void createAutoConstraints(const std::vector<AutoConstraint> &autoConstrs,
|
||||
int geoId, Sketcher::PointPos pointPos=Sketcher::none);
|
||||
|
||||
void setPositionText(const Base::Vector2D &Pos, const std::string &text);
|
||||
void setPositionText(const Base::Vector2D &Pos, const SbString &text);
|
||||
void setPositionText(const Base::Vector2D &Pos);
|
||||
void resetPositionText(void);
|
||||
void renderSuggestConstraintsCursor(std::vector<AutoConstraint> &suggestedConstraints);
|
||||
|
|
|
@ -42,7 +42,6 @@ TaskDlgEditSketch::TaskDlgEditSketch(ViewProviderSketch *sketchView)
|
|||
: TaskDialog(),sketchView(sketchView)
|
||||
{
|
||||
assert(sketchView);
|
||||
documentName = sketchView->getObject()->getDocument()->getName();
|
||||
Constraints = new TaskSketcherConstrains(sketchView);
|
||||
General = new TaskSketcherGeneral(sketchView);
|
||||
Messages = new TaskSketcherMessages(sketchView);
|
||||
|
@ -77,7 +76,7 @@ bool TaskDlgEditSketch::accept()
|
|||
|
||||
bool TaskDlgEditSketch::reject()
|
||||
{
|
||||
std::string document = documentName; // needed because resetEdit() deletes this instance
|
||||
std::string document = getDocumentName(); // needed because resetEdit() deletes this instance
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.getDocument('%s').resetEdit()", document.c_str());
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.getDocument('%s').recompute()", document.c_str());
|
||||
|
||||
|
|
|
@ -1005,55 +1005,55 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
|
|||
draw(true);
|
||||
}
|
||||
|
||||
bool ViewProviderSketch::isConstraintAtPosition(const Base::Vector3d &constrPos, const SoNode *constraint)
|
||||
Base::Vector3d ViewProviderSketch::seekConstraintPosition(const Base::Vector3d &origPos,
|
||||
const Base::Vector3d &norm,
|
||||
const Base::Vector3d &dir, float step,
|
||||
const SoNode *constraint)
|
||||
{
|
||||
assert(edit);
|
||||
Gui::MDIView *mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
Gui::View3DInventorViewer *viewer = static_cast<Gui::View3DInventor *>(mdi)->getViewer();
|
||||
|
||||
SoRayPickAction rp(viewer->getViewportRegion());
|
||||
rp.setRadius(0.1f);
|
||||
rp.setPickAll(true);
|
||||
rp.setRay(SbVec3f(constrPos.x, constrPos.y, -1.f), SbVec3f(0, 0, 1) );
|
||||
//problem
|
||||
rp.apply(edit->constrGroup); // We could narrow it down to just the SoGroup containing the constraints
|
||||
|
||||
// returns a copy of the point
|
||||
SoPickedPoint *pp = rp.getPickedPoint();
|
||||
const SoPickedPointList ppl = rp.getPickedPointList();
|
||||
float scaled_step = step * getScaleFactor();
|
||||
|
||||
if(ppl.getLength() > 1)
|
||||
return true;
|
||||
if (pp) {
|
||||
SoPath *path = pp->getPath();
|
||||
int length = path->getLength();
|
||||
SoNode *tailFather1 = path->getNode(length-2);
|
||||
SoNode *tailFather2 = path->getNode(length-3);
|
||||
|
||||
// checking if a constraint is the same as the one selected
|
||||
if (tailFather1 == constraint || tailFather2 == constraint) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Base::Vector3d ViewProviderSketch::seekConstraintPosition(const Base::Vector3d &suggestedPos,
|
||||
const Base::Vector3d &dir, float step,
|
||||
const SoNode *constraint)
|
||||
{
|
||||
int multiplier = 0;
|
||||
Base::Vector3d freePos;
|
||||
do {
|
||||
Base::Vector3d relPos, freePos;
|
||||
bool isConstraintAtPosition = true;
|
||||
while (isConstraintAtPosition && multiplier < 10) {
|
||||
// Calculate new position of constraint
|
||||
freePos = suggestedPos + (dir * (multiplier * step));
|
||||
multiplier++; // Increment the multiplier
|
||||
relPos = norm * 0.5f + dir * multiplier;
|
||||
freePos = origPos + relPos * scaled_step;
|
||||
|
||||
rp.setRadius(0.1f);
|
||||
rp.setPickAll(true);
|
||||
rp.setRay(SbVec3f(freePos.x, freePos.y, -1.f), SbVec3f(0, 0, 1) );
|
||||
//problem
|
||||
rp.apply(edit->constrGroup); // We could narrow it down to just the SoGroup containing the constraints
|
||||
|
||||
// returns a copy of the point
|
||||
SoPickedPoint *pp = rp.getPickedPoint();
|
||||
const SoPickedPointList ppl = rp.getPickedPointList();
|
||||
|
||||
if (ppl.getLength() <= 1 && pp) {
|
||||
SoPath *path = pp->getPath();
|
||||
int length = path->getLength();
|
||||
SoNode *tailFather1 = path->getNode(length-2);
|
||||
SoNode *tailFather2 = path->getNode(length-3);
|
||||
|
||||
// checking if a constraint is the same as the one selected
|
||||
if (tailFather1 == constraint || tailFather2 == constraint)
|
||||
isConstraintAtPosition = false;
|
||||
} else
|
||||
isConstraintAtPosition = false;
|
||||
|
||||
multiplier *= -1; // search in both sides
|
||||
if (multiplier >= 0)
|
||||
multiplier++; // Increment the multiplier
|
||||
}
|
||||
while (isConstraintAtPosition(freePos, constraint));
|
||||
return freePos;
|
||||
if (multiplier == 10)
|
||||
relPos = norm * 0.5f; // no free position found
|
||||
return relPos * step;
|
||||
}
|
||||
|
||||
bool ViewProviderSketch::isSelectable(void) const
|
||||
|
@ -1716,7 +1716,7 @@ void ViewProviderSketch::draw(bool temp)
|
|||
Points.push_back(start);
|
||||
Points.push_back(end);
|
||||
}
|
||||
else if ((*it)->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { // add a circle
|
||||
else if ((*it)->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { // add a bspline
|
||||
const Part::GeomBSplineCurve *spline = dynamic_cast<const Part::GeomBSplineCurve *>(*it);
|
||||
Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast(spline->handle());
|
||||
|
||||
|
@ -1842,19 +1842,12 @@ Restart:
|
|||
Base::Vector3d dir = (lineSeg->getEndPoint()-lineSeg->getStartPoint()).Normalize();
|
||||
Base::Vector3d norm(-dir.y,dir.x,0);
|
||||
|
||||
float scale = dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->getScaleFactor();
|
||||
Base::Vector3d constrPos = midpos + (norm * 2.5 * scale);
|
||||
|
||||
constrPos = seekConstraintPosition(constrPos, dir, 2.5 * scale, edit->constrGroup->getChild(i));
|
||||
|
||||
// Translate the Icon based on calculated position
|
||||
Base::Vector3d relPos = constrPos - midpos; // Relative Position of Icons to Midpoint
|
||||
relPos = relPos / scale; // Must Divide by Scale Factor
|
||||
Base::Vector3d relpos = seekConstraintPosition(midpos, norm, dir, 2.5, edit->constrGroup->getChild(i));
|
||||
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->abPos = SbVec3f(midpos.x, midpos.y, zConstr); //Absolute Reference
|
||||
|
||||
//Reference Position that is scaled according to zoom
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relPos.x, relPos.y, 0);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relpos.x, relpos.y, 0);
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -1921,25 +1914,16 @@ Restart:
|
|||
dir1 = Base::Vector3d(1,0,0);
|
||||
}
|
||||
|
||||
// Get Current Scale Factor
|
||||
float scale = dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->getScaleFactor();
|
||||
|
||||
Base::Vector3d constrPos1 = midpos1 + (norm1 * 2.5 * scale);
|
||||
constrPos1 = seekConstraintPosition(constrPos1, dir1, scale * 2.5, edit->constrGroup->getChild(i));
|
||||
|
||||
// Translate the Icon based on calculated position
|
||||
Base::Vector3d relPos1 = (constrPos1 - midpos1) / scale ; // Relative Position of Icons to Midpoint1
|
||||
Base::Vector3d relpos1 = seekConstraintPosition(midpos1, norm1, dir1, 2.5, edit->constrGroup->getChild(i));
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->abPos = SbVec3f(midpos1.x, midpos1.y, zConstr);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relPos1.x, relPos1.y, 0);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relpos1.x, relpos1.y, 0);
|
||||
|
||||
if (Constr->FirstPos == Sketcher::none) {
|
||||
Base::Vector3d constrPos2 = midpos2 + (norm2 * 2.5 * scale);
|
||||
constrPos2 = seekConstraintPosition(constrPos2, dir2, 2.5 * scale, edit->constrGroup->getChild(i));
|
||||
Base::Vector3d relpos2 = seekConstraintPosition(midpos2, norm2, dir2, 2.5, edit->constrGroup->getChild(i));
|
||||
|
||||
Base::Vector3d relPos2 = (constrPos2 - midpos2) / scale ; // Relative Position of Icons to Midpoint2
|
||||
Base::Vector3d secondPos = midpos2 - midpos1;
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->abPos = SbVec3f(secondPos.x, secondPos.y, zConstr);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->translation = SbVec3f(relPos2.x -relPos1.x, relPos2.y -relPos1.y, 0);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->translation = SbVec3f(relpos2.x -relpos1.x, relpos2.y -relpos1.y, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2012,32 +1996,19 @@ Restart:
|
|||
norm2 = Base::Vector3d(-dir2.y,dir2.x,0.);
|
||||
}
|
||||
|
||||
// Get Current Scale Factor
|
||||
float scale = dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->getScaleFactor();
|
||||
|
||||
Base::Vector3d constrPos1 = midpos1 + (norm1 * 2.5 * scale);
|
||||
constrPos1 = seekConstraintPosition(constrPos1, dir1, scale * 2.5, edit->constrGroup->getChild(i));
|
||||
|
||||
Base::Vector3d constrPos2 = midpos2 + (norm2 * 2.5 * scale);
|
||||
constrPos2 = seekConstraintPosition(constrPos2, dir2, 2.5 * scale, edit->constrGroup->getChild(i));
|
||||
|
||||
// Translate the Icon based on calculated position
|
||||
Base::Vector3d relPos1 = constrPos1 - midpos1 ; // Relative Position of Icons to Midpoint1
|
||||
Base::Vector3d relPos2 = constrPos2 - midpos2 ; // Relative Position of Icons to Midpoint2
|
||||
|
||||
relPos1 = relPos1 / scale;
|
||||
relPos2 = relPos2 / scale;
|
||||
Base::Vector3d relpos1 = seekConstraintPosition(midpos1, norm1, dir1, 2.5, edit->constrGroup->getChild(i));
|
||||
Base::Vector3d relpos2 = seekConstraintPosition(midpos2, norm2, dir2, 2.5, edit->constrGroup->getChild(i));
|
||||
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->abPos = SbVec3f(midpos1.x, midpos1.y, zConstr); //Absolute Reference
|
||||
|
||||
//Reference Position that is scaled according to zoom
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relPos1.x, relPos1.y, 0);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relpos1.x, relpos1.y, 0);
|
||||
|
||||
Base::Vector3d secondPos = midpos2 - midpos1;
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->abPos = SbVec3f(secondPos.x, secondPos.y, zConstr); //Absolute Reference
|
||||
|
||||
//Reference Position that is scaled according to zoom
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->translation = SbVec3f(relPos2.x -relPos1.x, relPos2.y -relPos1.y, 0);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->translation = SbVec3f(relpos2.x - relpos1.x, relpos2.y -relpos1.y, 0);
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -2148,32 +2119,19 @@ Restart:
|
|||
Base::Vector3d norm1 = Base::Vector3d(-dir1.y,dir1.x,0.f);
|
||||
Base::Vector3d norm2 = Base::Vector3d(-dir2.y,dir2.x,0.f);
|
||||
|
||||
// Get Current Scale Factor
|
||||
float scale = dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->getScaleFactor();
|
||||
|
||||
Base::Vector3d constrPos1 = midpos1 + (norm1 * 2.5 * scale);
|
||||
constrPos1 = seekConstraintPosition(constrPos1, dir1, 2.5 * scale, edit->constrGroup->getChild(i));
|
||||
|
||||
Base::Vector3d constrPos2 = midpos2 + (norm2 * 2.5 * scale);
|
||||
constrPos2 = seekConstraintPosition(constrPos2, dir2, 2.5 * scale, edit->constrGroup->getChild(i));
|
||||
|
||||
// Translate the Icon based on calculated position
|
||||
Base::Vector3d relPos1 = constrPos1 - midpos1 ; // Relative Position of Icons to Midpoint1
|
||||
Base::Vector3d relPos2 = constrPos2 - midpos2 ; // Relative Position of Icons to Midpoint2
|
||||
|
||||
relPos1 = relPos1 / scale;
|
||||
relPos2 = relPos2 / scale;
|
||||
Base::Vector3d relpos1 = seekConstraintPosition(midpos1, norm1, dir1, 2.5, edit->constrGroup->getChild(i));
|
||||
Base::Vector3d relpos2 = seekConstraintPosition(midpos2, norm2, dir2, 2.5, edit->constrGroup->getChild(i));
|
||||
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->abPos = SbVec3f(midpos1.x, midpos1.y, zConstr); //Absolute Reference
|
||||
|
||||
//Reference Position that is scaled according to zoom
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relPos1.x, relPos1.y, 0);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relpos1.x, relpos1.y, 0);
|
||||
|
||||
Base::Vector3d secondPos = midpos2 - midpos1;
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->abPos = SbVec3f(secondPos.x, secondPos.y, zConstr); //Absolute Reference
|
||||
|
||||
//Reference Position that is scaled according to zoom
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->translation = SbVec3f(relPos2.x -relPos1.x, relPos2.y -relPos1.y, 0);
|
||||
dynamic_cast<SoZoomTranslation *>(sep->getChild(3))->translation = SbVec3f(relpos2.x -relpos1.x, relpos2.y -relpos1.y, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2777,9 +2735,14 @@ void ViewProviderSketch::createEditInventorNodes(void)
|
|||
edit->EditCurveSet = new SoLineSet;
|
||||
edit->EditRoot->addChild(edit->EditCurveSet);
|
||||
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
float transparency;
|
||||
SbColor cursorTextColor(0,0,1);
|
||||
cursorTextColor.setPackedValue((uint32_t)hGrp->GetUnsigned("CursorTextColor", cursorTextColor.getPackedValue()), transparency);
|
||||
|
||||
// stuff for the edit coordinates ++++++++++++++++++++++++++++++++++++++
|
||||
SoMaterial *EditMaterials = new SoMaterial;
|
||||
EditMaterials->diffuseColor = SbColor(0,0,1);
|
||||
EditMaterials->diffuseColor = cursorTextColor;
|
||||
edit->EditRoot->addChild(EditMaterials);
|
||||
|
||||
SoSeparator *Coordsep = new SoSeparator();
|
||||
|
@ -2867,17 +2830,17 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer)
|
|||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(TRUE);
|
||||
}
|
||||
|
||||
void ViewProviderSketch::setPositionText(const Base::Vector2D &Pos, const std::string &text)
|
||||
void ViewProviderSketch::setPositionText(const Base::Vector2D &Pos, const SbString &text)
|
||||
{
|
||||
edit->textX->string = text.c_str();
|
||||
edit->textX->string = text;
|
||||
edit->textPos->translation = SbVec3f(Pos.fX,Pos.fY,zText);
|
||||
}
|
||||
|
||||
void ViewProviderSketch::setPositionText(const Base::Vector2D &Pos)
|
||||
{
|
||||
char buf[40];
|
||||
sprintf( buf, " (%.1f,%.1f)", Pos.fX,Pos.fY );
|
||||
edit->textX->string = buf;
|
||||
SbString text;
|
||||
text.sprintf(" (%.1f,%.1f)", Pos.fX, Pos.fY);
|
||||
edit->textX->string = text;
|
||||
edit->textPos->translation = SbVec3f(Pos.fX,Pos.fY,zText);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ class SoMarkerSet;
|
|||
|
||||
class SoText2;
|
||||
class SoTranslation;
|
||||
class SbString;
|
||||
class SbTime;
|
||||
|
||||
struct EditData;
|
||||
|
@ -137,10 +138,9 @@ public:
|
|||
|
||||
/// moves a selected constraint
|
||||
void moveConstraint(int constNum, const Base::Vector2D &toPos);
|
||||
/// checks if there is a constraint object at position vector
|
||||
bool isConstraintAtPosition(const Base::Vector3d &constrPos, const SoNode *constraint);
|
||||
/// finds a free position for placing a constraint icon
|
||||
Base::Vector3d seekConstraintPosition(const Base::Vector3d &suggestedPos,
|
||||
Base::Vector3d seekConstraintPosition(const Base::Vector3d &origPos,
|
||||
const Base::Vector3d &norm,
|
||||
const Base::Vector3d &dir, float step,
|
||||
const SoNode *constraint);
|
||||
|
||||
|
@ -200,7 +200,7 @@ protected:
|
|||
/// build up the visual of the constraints
|
||||
void rebuildConstraintsVisual(void);
|
||||
|
||||
void setPositionText(const Base::Vector2D &Pos, const std::string &txt);
|
||||
void setPositionText(const Base::Vector2D &Pos, const SbString &txt);
|
||||
void setPositionText(const Base::Vector2D &Pos);
|
||||
void resetPositionText(void);
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ BrowserView::BrowserView(QWidget* parent)
|
|||
connect(view, SIGNAL(loadProgress(int)),
|
||||
this, SLOT(onLoadProgress(int)));
|
||||
connect(view, SIGNAL(loadFinished(bool)),
|
||||
this, SLOT(onLoadFinished()));
|
||||
this, SLOT(onLoadFinished(bool)));
|
||||
connect(view, SIGNAL(linkClicked(const QUrl &)),
|
||||
this, SLOT(onLinkClicked(const QUrl &)));
|
||||
connect(view->page(), SIGNAL(downloadRequested(const QNetworkRequest &)),
|
||||
|
@ -242,12 +242,14 @@ void BrowserView::onLoadProgress(int step)
|
|||
bar->setValue(step);
|
||||
}
|
||||
|
||||
void BrowserView::onLoadFinished()
|
||||
void BrowserView::onLoadFinished(bool ok)
|
||||
{
|
||||
QProgressBar* bar = Sequencer::instance()->getProgressBar();
|
||||
bar->setValue(100);
|
||||
bar->hide();
|
||||
getMainWindow()->statusBar()->showMessage(QString());
|
||||
if (ok) {
|
||||
QProgressBar* bar = Sequencer::instance()->getProgressBar();
|
||||
bar->setValue(100);
|
||||
bar->hide();
|
||||
getMainWindow()->statusBar()->showMessage(QString());
|
||||
}
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,10 +92,10 @@ public:
|
|||
protected Q_SLOTS:
|
||||
void onLoadStarted();
|
||||
void onLoadProgress(int);
|
||||
void onLoadFinished();
|
||||
void onLinkClicked ( const QUrl & url ) ;
|
||||
void onLoadFinished(bool);
|
||||
void onLinkClicked (const QUrl& url);
|
||||
bool chckHostAllowed(const QString& host);
|
||||
void onDownloadRequested(const QNetworkRequest & request);
|
||||
void onDownloadRequested(const QNetworkRequest& request);
|
||||
|
||||
private:
|
||||
WebView* view;
|
||||
|
|
Loading…
Reference in New Issue
Block a user