From 0808d532a82c295955ace3122c25f510fc202436 Mon Sep 17 00:00:00 2001 From: tanderson Date: Tue, 28 Feb 2012 10:42:17 -0500 Subject: [PATCH 001/351] new algorithm for spaceball movements *consolidate motion3 event handeling. *rotation about focal point. *translation based on world to screen scale. *cleanup axes map and constants. --- src/Gui/BlenderNavigationStyle.cpp | 25 +++++++---------------- src/Gui/CADNavigationStyle.cpp | 17 +++------------- src/Gui/InventorNavigationStyle.cpp | 14 ++++--------- src/Gui/NavigationStyle.cpp | 31 +++++++++++++++++++++++++++++ src/Gui/NavigationStyle.h | 10 ++++++---- src/Gui/TouchpadNavigationStyle.cpp | 25 +++++++---------------- src/Gui/View3DInventorViewer.cpp | 8 +++----- 7 files changed, 61 insertions(+), 69 deletions(-) diff --git a/src/Gui/BlenderNavigationStyle.cpp b/src/Gui/BlenderNavigationStyle.cpp index d40ab1acc7..1541800722 100644 --- a/src/Gui/BlenderNavigationStyle.cpp +++ b/src/Gui/BlenderNavigationStyle.cpp @@ -79,10 +79,10 @@ const char* BlenderNavigationStyle::mouseButtons(ViewerMode mode) SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) { - // Events when in "ready-to-seek" mode are ignored, except those - // which influence the seek mode itself -- these are handled further - // up the inheritance hierarchy. - if (this->isSeekMode()) { return inherited::processSoEvent(ev); } + // Events when in "ready-to-seek" mode are ignored, except those + // which influence the seek mode itself -- these are handled further + // up the inheritance hierarchy. + if (this->isSeekMode()) { return inherited::processSoEvent(ev); } const SoType type(ev->getTypeId()); @@ -291,20 +291,9 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev) // Spaceball & Joystick handling if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) { - SoMotion3Event * const event = (SoMotion3Event *) ev; - SoCamera * const camera = viewer->getCamera(); - - SbVec3f dir = event->getTranslation(); - if (camera->getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId())){ - static float zoomConstant(-.03f); - dir[2] = 0.0;//don't move the cam for z translation. - - SoOrthographicCamera *oCam = static_cast(camera); - oCam->scaleHeight(1.0-event->getTranslation()[2] * zoomConstant); - } - camera->orientation.getValue().multVec(dir,dir); - camera->position = camera->position.getValue() + dir; - camera->orientation = event->getRotation() * camera->orientation.getValue(); + const SoMotion3Event * const event = static_cast(ev); + if (event) + this->processMotionEvent(event); processed = TRUE; } diff --git a/src/Gui/CADNavigationStyle.cpp b/src/Gui/CADNavigationStyle.cpp index 99f0d5919a..a85124a022 100644 --- a/src/Gui/CADNavigationStyle.cpp +++ b/src/Gui/CADNavigationStyle.cpp @@ -320,20 +320,9 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev) // Spaceball & Joystick handling if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) { - SoMotion3Event * const event = (SoMotion3Event *) ev; - SoCamera * const camera = viewer->getCamera(); - - SbVec3f dir = event->getTranslation(); - if (camera->getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId())){ - static float zoomConstant(-.03f); - dir[2] = 0.0;//don't move the cam for z translation. - - SoOrthographicCamera *oCam = static_cast(camera); - oCam->scaleHeight(1.0-event->getTranslation()[2] * zoomConstant); - } - camera->orientation.getValue().multVec(dir,dir); - camera->position = camera->position.getValue() + dir; - camera->orientation = event->getRotation() * camera->orientation.getValue(); + const SoMotion3Event * const event = static_cast(ev); + if (event) + this->processMotionEvent(event); processed = TRUE; } diff --git a/src/Gui/InventorNavigationStyle.cpp b/src/Gui/InventorNavigationStyle.cpp index 5fb72f9893..e1e6f47557 100644 --- a/src/Gui/InventorNavigationStyle.cpp +++ b/src/Gui/InventorNavigationStyle.cpp @@ -285,16 +285,10 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev) // Spaceball & Joystick handling if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) { - SoMotion3Event * const event = (SoMotion3Event *) ev; - SoCamera * const camera = viewer->getCamera(); - if (camera) { - SbVec3f dir = event->getTranslation(); - camera->orientation.getValue().multVec(dir,dir); - camera->position = camera->position.getValue() + dir; - camera->orientation = - event->getRotation() * camera->orientation.getValue(); - processed = TRUE; - } + const SoMotion3Event * const event = static_cast(ev); + if (event) + this->processMotionEvent(event); + processed = TRUE; } enum { diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index 8a44dd6677..192cb7ae5a 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -1140,6 +1140,37 @@ SbBool NavigationStyle::processSoEvent(const SoEvent * const ev) return viewer->processSoEventBase(ev); } +SbBool NavigationStyle::processMotionEvent(const SoMotion3Event * const ev) +{ + SoCamera * const camera = viewer->getCamera(); + if (!camera) + return FALSE; + + SbViewVolume volume(camera->getViewVolume()); + SbVec3f center(volume.getSightPoint(camera->focalDistance.getValue())); + float scale(volume.getWorldToScreenScale(center, 1.0)); + float translationFactor = scale * .0001; + + SbVec3f dir = ev->getTranslation(); + + if (camera->getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId())){ + SoOrthographicCamera *oCam = static_cast(camera); + oCam->scaleHeight(1.0 + (dir[2] * 0.0001)); + dir[2] = 0.0;//don't move the cam for z translation. + } + + SbRotation newRotation(ev->getRotation() * camera->orientation.getValue()); + SbVec3f newPosition, newDirection; + newRotation.multVec(SbVec3f(0.0, 0.0, -1.0), newDirection); + newPosition = center - (newDirection * camera->focalDistance.getValue()); + + camera->orientation.setValue(newRotation); + camera->orientation.getValue().multVec(dir,dir); + camera->position = newPosition + (dir * translationFactor); + + return TRUE; +} + void NavigationStyle::setPopupMenuEnabled(const SbBool on) { this->menuenabled = on; diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 846e65f869..7644a73403 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -38,6 +38,7 @@ // forward declarations class SoEvent; +class SoMotion3Event; class SoQtViewer; class SoCamera; class SoSensor; @@ -90,10 +91,10 @@ public: Clip = 3, /**< Clip objects using a lasso. */ }; - enum OrbitStyle { - Turntable, - Trackball - }; + enum OrbitStyle { + Turntable, + Trackball + }; public: NavigationStyle(); @@ -126,6 +127,7 @@ public: void setViewingMode(const ViewerMode newmode); int getViewingMode() const; virtual SbBool processEvent(const SoEvent * const ev); + virtual SbBool processMotionEvent(const SoMotion3Event * const ev); void setPopupMenuEnabled(const SbBool on); SbBool isPopupMenuEnabled(void) const; diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp index 530b0650d4..e33323c33b 100644 --- a/src/Gui/TouchpadNavigationStyle.cpp +++ b/src/Gui/TouchpadNavigationStyle.cpp @@ -79,10 +79,10 @@ const char* TouchpadNavigationStyle::mouseButtons(ViewerMode mode) SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) { - // Events when in "ready-to-seek" mode are ignored, except those - // which influence the seek mode itself -- these are handled further - // up the inheritance hierarchy. - if (this->isSeekMode()) { return inherited::processSoEvent(ev); } + // Events when in "ready-to-seek" mode are ignored, except those + // which influence the seek mode itself -- these are handled further + // up the inheritance hierarchy. + if (this->isSeekMode()) { return inherited::processSoEvent(ev); } const SoType type(ev->getTypeId()); @@ -265,20 +265,9 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev) // Spaceball & Joystick handling if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) { - SoMotion3Event * const event = (SoMotion3Event *) ev; - SoCamera * const camera = viewer->getCamera(); - - SbVec3f dir = event->getTranslation(); - if (camera->getTypeId().isDerivedFrom(SoOrthographicCamera::getClassTypeId())){ - static float zoomConstant(-.03f); - dir[2] = 0.0;//don't move the cam for z translation. - - SoOrthographicCamera *oCam = static_cast(camera); - oCam->scaleHeight(1.0-event->getTranslation()[2] * zoomConstant); - } - camera->orientation.getValue().multVec(dir,dir); - camera->position = camera->position.getValue() + dir; - camera->orientation = event->getRotation() * camera->orientation.getValue(); + const SoMotion3Event * const event = static_cast(ev); + if (event) + this->processMotionEvent(event); processed = TRUE; } diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 1b5ab3af07..cb161f3618 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1070,18 +1070,16 @@ void View3DInventorViewer::processEvent(QEvent * event) motionEvent->setHandled(true); - static float translationConstant(-.001f); float xTrans, yTrans, zTrans; xTrans = static_cast(motionEvent->translationX()); yTrans = static_cast(motionEvent->translationY()); zTrans = static_cast(motionEvent->translationZ()); - SbVec3f translationVector(xTrans, yTrans, zTrans * -1.0); - translationVector *= translationConstant; + SbVec3f translationVector(xTrans, yTrans, zTrans); static float rotationConstant(.0001f); SbRotation xRot, yRot, zRot; - xRot.setValue(SbVec3f(-1.0, 0.0, 0.0), static_cast(motionEvent->rotationX()) * rotationConstant); - yRot.setValue(SbVec3f(0.0, -1.0, 0.0), static_cast(motionEvent->rotationY()) * rotationConstant); + xRot.setValue(SbVec3f(1.0, 0.0, 0.0), static_cast(motionEvent->rotationX()) * rotationConstant); + yRot.setValue(SbVec3f(0.0, 1.0, 0.0), static_cast(motionEvent->rotationY()) * rotationConstant); zRot.setValue(SbVec3f(0.0, 0.0, 1.0), static_cast(motionEvent->rotationZ()) * rotationConstant); SoMotion3Event motion3Event; From 09922ab7a51cc55b21a12a83aba4d8bae7dab3ab Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 11 Mar 2012 18:37:28 +0100 Subject: [PATCH 002/351] Fix a couple of minor issues and a possible crash when closing a document with several MDI views --- src/Gui/Application.cpp | 10 ++++++++++ src/Gui/Document.cpp | 20 ++++++++++---------- src/Gui/SplitView3DInventor.cpp | 6 ++++-- src/Gui/SplitView3DInventor.h | 2 ++ src/Gui/View3DInventor.cpp | 2 +- src/Gui/View3DInventorViewer.cpp | 10 ++++++++++ src/Gui/View3DInventorViewer.h | 3 +++ src/Mod/Mesh/App/Core/MeshIO.cpp | 2 +- 8 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 8c3ff25c67..7b59be2d7f 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -80,6 +80,7 @@ #include "DlgOnlineHelpImp.h" #include "SpaceballEvent.h" +#include "SplitView3DInventor.h" #include "View3DInventor.h" #include "ViewProvider.h" #include "ViewProviderExtern.h" @@ -708,6 +709,14 @@ void Application::setActiveDocument(Gui::Document* pcDocument) { if (d->activeDocument == pcDocument) return; // nothing needs to be done + if (pcDocument) { + // This happens if a document with more than one view is about being + // closed and a second view is activated. The document is still not + // removed from the map. + App::Document* doc = pcDocument->getDocument(); + if (d->documents.find(doc) == d->documents.end()) + return; + } d->activeDocument = pcDocument; std::string name; @@ -1391,6 +1400,7 @@ void Application::initTypes(void) Gui::BaseView ::init(); Gui::MDIView ::init(); Gui::View3DInventor ::init(); + Gui::SplitView3DInventor ::init(); // View Provider Gui::ViewProvider ::init(); Gui::ViewProviderExtern ::init(); diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index 18447b2e10..aaeab815e8 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -55,7 +55,6 @@ #include "BitmapFactory.h" #include "ViewProviderDocumentObject.h" #include "Selection.h" -#include "SoFCSelection.h" #include "WaitCursor.h" #include "Thumbnail.h" @@ -406,17 +405,18 @@ void Document::slotDeletedObject(const App::DocumentObject& Obj) // cycling to all views of the document ViewProvider* viewProvider = getViewProvider(&Obj); - for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) { - View3DInventor *activeView = dynamic_cast(*vIt); - if (activeView && viewProvider) { - if (d->_pcInEdit == viewProvider) - resetEdit(); - activeView->getViewer()->removeViewProvider(viewProvider); + if (viewProvider && viewProvider->getTypeId().isDerivedFrom + (ViewProviderDocumentObject::getClassTypeId())) { + // go through the views + for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) { + View3DInventor *activeView = dynamic_cast(*vIt); + if (activeView) { + if (d->_pcInEdit == viewProvider) + resetEdit(); + activeView->getViewer()->removeViewProvider(viewProvider); + } } - } - if (viewProvider && viewProvider->getTypeId().isDerivedFrom( - ViewProviderDocumentObject::getClassTypeId())) { // removing from tree signalDeletedObject(*(static_cast(viewProvider))); diff --git a/src/Gui/SplitView3DInventor.cpp b/src/Gui/SplitView3DInventor.cpp index be874b05c8..f80532af86 100644 --- a/src/Gui/SplitView3DInventor.cpp +++ b/src/Gui/SplitView3DInventor.cpp @@ -41,8 +41,10 @@ using namespace Gui; -SplitView3DInventor::SplitView3DInventor( int views, Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags ) - : MDIView( pcDocument,parent, wflags) +TYPESYSTEM_SOURCE_ABSTRACT(Gui::SplitView3DInventor,Gui::MDIView); + +SplitView3DInventor::SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags) + : MDIView(pcDocument,parent, wflags) { // important for highlighting setMouseTracking(true); diff --git a/src/Gui/SplitView3DInventor.h b/src/Gui/SplitView3DInventor.h index c10da630db..c4596e9a95 100644 --- a/src/Gui/SplitView3DInventor.h +++ b/src/Gui/SplitView3DInventor.h @@ -38,6 +38,8 @@ class View3DInventorViewer; */ class GuiExport SplitView3DInventor : public MDIView,public ParameterGrp::ObserverType { + TYPESYSTEM_HEADER(); + public: SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags=0); ~SplitView3DInventor(); diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp index 262916d1e6..2645b61961 100644 --- a/src/Gui/View3DInventor.cpp +++ b/src/Gui/View3DInventor.cpp @@ -93,7 +93,7 @@ void GLOverlayWidget::paintEvent(QPaintEvent* ev) /* TRANSLATOR Gui::View3DInventor */ -TYPESYSTEM_SOURCE_ABSTRACT(Gui::View3DInventor,Gui::BaseView); +TYPESYSTEM_SOURCE_ABSTRACT(Gui::View3DInventor,Gui::MDIView); View3DInventor::View3DInventor(Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags) : MDIView(pcDocument, parent, wflags), _viewerPy(0) diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 1b5ab3af07..ab3dd8e109 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1636,6 +1636,16 @@ void View3DInventorViewer::stopAnimating(void) navigation->stopAnimating(); } +void View3DInventorViewer::setPopupMenuEnabled(const SbBool on) +{ + navigation->setPopupMenuEnabled(on); +} + +SbBool View3DInventorViewer::isPopupMenuEnabled(void) const +{ + return navigation->isPopupMenuEnabled(); +} + /*! Set the flag deciding whether or not to show the axis cross. */ diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 96c6fdce7d..71e5a2bf39 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -106,6 +106,9 @@ public: void setAnimationEnabled(const SbBool enable); SbBool isAnimationEnabled(void) const; + void setPopupMenuEnabled(const SbBool on); + SbBool isPopupMenuEnabled(void) const; + void startAnimating(const SbVec3f& axis, float velocity); void stopAnimating(void); SbBool isAnimating(void) const; diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 6017172a27..687cf9fc3a 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -786,7 +786,7 @@ bool MeshInput::LoadAsciiSTL (std::istream &rstrIn) if (line.find("ENDFACET") != std::string::npos) ulFacetCt++; // prevent from reading EOF (as I don't know how to reread the file then) - else if (rstrIn.tellg() > ulSize) + if (rstrIn.tellg() > ulSize) break; else if (line.find("ENDSOLID") != std::string::npos) break; From 66d54bc90ebb1150d0b8e5929838b9a331bec16a Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 11 Mar 2012 19:27:02 +0100 Subject: [PATCH 003/351] Import OFF mesh format --- src/Mod/Mesh/App/Core/MeshIO.cpp | 122 +++++++++++++++++++++++++++++++ src/Mod/Mesh/App/Core/MeshIO.h | 2 + src/Mod/Mesh/Gui/Command.cpp | 3 +- 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 687cf9fc3a..6c78277346 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -42,6 +42,7 @@ #include #include #include +#include using namespace MeshCore; @@ -330,6 +331,9 @@ bool MeshInput::LoadAny(const char* FileName) else if (fi.hasExtension("obj")) { ok = LoadOBJ( str ); } + else if (fi.hasExtension("off")) { + ok = LoadOFF( str ); + } else if (fi.hasExtension("ply")) { ok = LoadPLY( str ); } @@ -512,6 +516,124 @@ bool MeshInput::LoadOBJ (std::istream &rstrIn) return true; } +/** Loads an OFF file. */ +bool MeshInput::LoadOFF (std::istream &rstrIn) +{ + boost::regex rx_n("^\\s*([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*$"); + boost::regex rx_p("^\\s*([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" + "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" + "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$"); + boost::regex rx_f3("^\\s*([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*$"); + boost::regex rx_f4("^\\s*([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*$"); + + boost::cmatch what; + + MeshPointArray meshPoints; + MeshFacetArray meshFacets; + + std::string line; + float fX, fY, fZ; + unsigned int i1=1,i2=1,i3=1,i4=1; + MeshGeomFacet clFacet; + MeshFacet item; + + if (!rstrIn || rstrIn.bad() == true) + return false; + + std::streambuf* buf = rstrIn.rdbuf(); + if (!buf) + return false; + + bool readvertices=false; + std::getline(rstrIn, line); + boost::algorithm::to_lower(line); + if (line.find("off") == std::string::npos) + return false; // not an OFF file + + // get number of vertices and faces + int numPoints=0, numFaces=0; + std::getline(rstrIn, line); + boost::algorithm::to_lower(line); + if (boost::regex_match(line.c_str(), what, rx_n)) { + numPoints = std::atoi(what[1].first); + numFaces = std::atoi(what[2].first); + } + else { + // Cannot read number of elements + return false; + } + + meshPoints.reserve(numPoints); + meshFacets.reserve(numFaces); + + for (int i=0; i_rclMesh.Clear(); // remove all data before + // Don't use Assign() because Merge() checks which points are really needed. + // This method sets already the correct neighbourhood + unsigned long ct = meshPoints.size(); + std::list removeFaces; + for (MeshFacetArray::_TConstIterator it = meshFacets.begin(); it != meshFacets.end(); ++it) { + bool ok = true; + for (int i=0;i<3;i++) { + if (it->_aulPoints[i] >= ct) { + Base::Console().Warning("Face index %ld out of range\n", it->_aulPoints[i]); + ok = false; + } + } + + if (!ok) + removeFaces.push_front(it-meshFacets.begin()); + } + + for (std::list::iterator it = removeFaces.begin(); it != removeFaces.end(); ++it) + meshFacets.erase(meshFacets.begin() + *it); + + MeshKernel tmp; + tmp.Adopt(meshPoints,meshFacets); + this->_rclMesh.Merge(tmp); + + return true; +} + bool MeshInput::LoadPLY (std::istream &inp) { // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/ diff --git a/src/Mod/Mesh/App/Core/MeshIO.h b/src/Mod/Mesh/App/Core/MeshIO.h index a056b17a4d..e45d9f64e4 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.h +++ b/src/Mod/Mesh/App/Core/MeshIO.h @@ -89,6 +89,8 @@ public: bool LoadBinarySTL (std::istream &rstrIn); /** Loads an OBJ Mesh file. */ bool LoadOBJ (std::istream &rstrIn); + /** Loads an OFF Mesh file. */ + bool LoadOFF (std::istream &rstrIn); /** Loads a PLY Mesh file. */ bool LoadPLY (std::istream &rstrIn); /** Loads the mesh object from an XML file. */ diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index 35228e7780..03d9714749 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -289,11 +289,12 @@ void CmdMeshImport::activated(int iMsg) { // use current path as default QStringList filter; - filter << QObject::tr("All Mesh Files (*.stl *.ast *.bms *.obj *.ply)"); + filter << QObject::tr("All Mesh Files (*.stl *.ast *.bms *.obj *.off *.ply)"); filter << QObject::tr("Binary STL (*.stl)"); filter << QObject::tr("ASCII STL (*.ast)"); filter << QObject::tr("Binary Mesh (*.bms)"); filter << QObject::tr("Alias Mesh (*.obj)"); + filter << QObject::tr("Object File Format (*.off)"); filter << QObject::tr("Inventor V2.1 ascii (*.iv)"); filter << QObject::tr("Stanford Polygon (*.ply)"); //filter << "Nastran (*.nas *.bdf)"; From ef852e8f980eed460de8c26d887f1fae2a3bae0e Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 12 Mar 2012 08:54:56 +0100 Subject: [PATCH 004/351] 0000632: Cone mesh fails with radius=0 on one end --- src/Mod/Mesh/BuildRegularGeoms.py | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Mod/Mesh/BuildRegularGeoms.py b/src/Mod/Mesh/BuildRegularGeoms.py index 8b4003935f..b67985eab4 100644 --- a/src/Mod/Mesh/BuildRegularGeoms.py +++ b/src/Mod/Mesh/BuildRegularGeoms.py @@ -39,12 +39,16 @@ def Cylinder (radius, len, closed, edgelen, count): def Cone (radius1, radius2, len, closed, edgelen, count): polyline = [] - if (closed): - step = radius2 / math.ceil(radius2 / edgelen) - i = 0.0 - while (i < radius2 - step / 2.0): - polyline.append([len, i]) - i = i + step + if (closed): + try: + step = radius2 / math.ceil(radius2 / edgelen) + except ZeroDivisionError: + pass + else: + i = 0.0 + while (i < radius2 - step / 2.0): + polyline.append([len, i]) + i = i + step ct = math.ceil(len / edgelen) step = len / ct @@ -58,12 +62,16 @@ def Cone (radius1, radius2, len, closed, edgelen, count): polyline.append([0.0, radius1]) if (closed): - step = radius1 / math.ceil(radius1 / edgelen) - i = radius1 - step - while (i > 0.0 + step / 2.0): - polyline.append([0.0, i]) - i = i - step - polyline.append([0.0, 0.0]) + try: + step = radius1 / math.ceil(radius1 / edgelen) + except ZeroDivisionError: + pass + else: + i = radius1 - step + while (i > 0.0 + step / 2.0): + polyline.append([0.0, i]) + i = i - step + polyline.append([0.0, 0.0]) return RotationBody(polyline, count) From 02a962207bca0c9719a5e28d10881ecb16a9ca9e Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 12 Mar 2012 10:11:27 +0100 Subject: [PATCH 005/351] Fix possible crash when cleaning up MDI views --- src/Gui/MDIView.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Gui/MDIView.cpp b/src/Gui/MDIView.cpp index 6aef8cd64e..3b7c07b602 100644 --- a/src/Gui/MDIView.cpp +++ b/src/Gui/MDIView.cpp @@ -56,15 +56,17 @@ MDIView::~MDIView() //the application crashes when accessing this deleted view. //This effect only occurs if this widget is not in Child mode, because otherwise //the focus stuff is done correctly. - QWidget* foc = getMainWindow()->focusWidget(); - if (foc) { - QWidget* par = foc; - while (par) { - if (par == this) { - getMainWindow()->setFocus(); - break; + if (getMainWindow()) { + QWidget* foc = getMainWindow()->focusWidget(); + if (foc) { + QWidget* par = foc; + while (par) { + if (par == this) { + getMainWindow()->setFocus(); + break; + } + par = par->parentWidget(); } - par = par->parentWidget(); } } } From 8a57a948d36a1f0714d9640c7798688832e625f5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 12 Mar 2012 11:13:58 +0100 Subject: [PATCH 006/351] 0000623: Matrix and Vector API extension --- src/Base/MatrixPy.xml | 3 ++- src/Base/MatrixPyImp.cpp | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Base/MatrixPy.xml b/src/Base/MatrixPy.xml index c91da2aa2d..23b5b15e4c 100644 --- a/src/Base/MatrixPy.xml +++ b/src/Base/MatrixPy.xml @@ -110,9 +110,10 @@ Compute the determinant of the matrix -isOrthogonal() -> Float +isOrthogonal([Float]) -> Float Checks if the matrix is orthogonal, i.e. M * M^T = k*I and returns the multiple of the identity matrix. If it's not orthogonal 0 is returned. +As argument you can set a tolerance which by default is 1.0e-6. diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index 9186f15167..b4f37b89ae 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #include +#include #include "Base/Matrix.h" // inclusion of the generated files (generated out of MatrixPy.xml) @@ -415,32 +416,34 @@ PyObject* MatrixPy::submatrix(PyObject * args) PyObject* MatrixPy::isOrthogonal(PyObject * args) { - if (!PyArg_ParseTuple(args, "")) + double eps=1.0e-06; + if (!PyArg_ParseTuple(args, "|d",&eps)) return 0; const Base::Matrix4D& mat = *getMatrixPtr(); Base::Matrix4D trp = mat; trp.transpose(); trp = trp * mat; + bool ok = true; double mult = trp[0][0]; - for (int i=0; (i<4) && (mult!=0.0); i++) { - for (int j=0; (j<4) && (mult!=0.0); j++) { + for (int i=0; i<4 && ok; i++) { + for (int j=0; j<4 && ok; j++) { if (i != j) { - if (trp[i][j] != 0.0) { - mult = 0.0; + if (fabs(trp[i][j]) > eps) { + ok = false; break; } } - else { // the diagonal - if (trp[i][j] != mult) { - mult = 0.0; + else { // the main diagonal + if (fabs(trp[i][j]-mult) > eps) { + ok = false; break; } } } } - return Py::new_reference_to(Py::Float(mult)); + return Py::new_reference_to(Py::Float(ok ? mult : 0.0)); } PyObject* MatrixPy::transposed(PyObject * args) From 1b4147144b2fdace1c00970bf585c5a4386a095c Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 12 Mar 2012 10:27:32 -0300 Subject: [PATCH 007/351] Fixing again bug #569 in Draft Offset --- src/Mod/Draft/draftlibs/fcgeo.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/draftlibs/fcgeo.py index 06bc691f29..44690d49d1 100755 --- a/src/Mod/Draft/draftlibs/fcgeo.py +++ b/src/Mod/Draft/draftlibs/fcgeo.py @@ -719,7 +719,9 @@ def offsetWire(wire,dvec,bind=False,occ=False): if occ: l=abs(dvec.Length) if not l: return None - if not wire.Wires: + if wire.Wires: + wire = wire.Wires[0] + else: wire = Part.Wire(edges) try: off = wire.makeOffset(l) @@ -1857,7 +1859,7 @@ def innerSoddyCircle(circle1, circle2, circle3): else: print "debug: innerSoddyCircle bad parameters!\n" # FreeCAD.Console.PrintMessage("debug: innerSoddyCircle bad parameters!\n") - return None + return None def circleFrom3CircleTangents(circle1, circle2, circle3): ''' From 17290798dc52628d077ec6c5490d568c9016aa6d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 12 Mar 2012 17:20:03 -0300 Subject: [PATCH 008/351] New Draft Snap toolbar A new toolbar will now appear when using the Draft Snap system (can be disabled in preferences) allowing to turn snaps on/off globally or invidually --- src/Mod/Arch/InitGui.py | 2 +- src/Mod/Draft/Draft.py | 2 +- src/Mod/Draft/DraftGui.py | 2 +- src/Mod/Draft/DraftSnap.py | 343 +- src/Mod/Draft/DraftTools.py | 17 +- src/Mod/Draft/Draft_rc.py | 2824 +++++++++++++++-- src/Mod/Draft/InitGui.py | 3 +- src/Mod/Draft/Resources/Draft.qrc | 11 + src/Mod/Draft/Resources/icons/Snap_Angle.svg | 459 +++ src/Mod/Draft/Resources/icons/Snap_Center.svg | 164 + .../Draft/Resources/icons/Snap_Endpoint.svg | 176 + .../Draft/Resources/icons/Snap_Extension.svg | 314 ++ src/Mod/Draft/Resources/icons/Snap_Grid.svg | 153 + .../Resources/icons/Snap_Intersection.svg | 175 + src/Mod/Draft/Resources/icons/Snap_Lock.svg | 204 ++ .../Draft/Resources/icons/Snap_Midpoint.svg | 178 ++ src/Mod/Draft/Resources/icons/Snap_Ortho.svg | 292 ++ .../Draft/Resources/icons/Snap_Parallel.svg | 164 + .../Resources/icons/Snap_Perpendicular.svg | 140 + src/Mod/Draft/Resources/ui/userprefs-base.ui | 23 + 20 files changed, 5234 insertions(+), 412 deletions(-) create mode 100644 src/Mod/Draft/Resources/icons/Snap_Angle.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Center.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Endpoint.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Extension.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Grid.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Intersection.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Lock.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Midpoint.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Ortho.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Parallel.svg create mode 100644 src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 75f85e3e25..554764e2e2 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -70,7 +70,7 @@ class ArchWorkbench(Workbench): "Draft_Downgrade","Draft_Trimex"] self.draftcontexttools = ["Draft_ApplyStyle","Draft_ToggleDisplayMode", "Draft_AddToGroup","Draft_SelectGroup", - "Draft_SelectPlane"] + "Draft_SelectPlane","Draft_ToggleSnap"] self.meshtools = ["Arch_SplitMesh","Arch_MeshToShape", "Arch_SelectNonSolidMeshes","Arch_RemoveShape"] self.appendToolbar(str(DraftTools.translate("arch","Arch tools")),self.archtools) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 0a8e045f20..5bd391bb87 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -101,7 +101,7 @@ def getParamType(param): elif param in ["textheight","tolerance","gridSpacing"]: return "float" elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit","maxSnap", - "SvgLinesBlack","dxfStdSize"]: + "SvgLinesBlack","dxfStdSize","showSnapBar"]: return "bool" elif param in ["color","constructioncolor","snapcolor"]: return "unsigned" diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 6b33e6b8ba..1d54e1c75b 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -1103,7 +1103,7 @@ class DraftToolBar: def togglesnap(self): if hasattr(FreeCADGui,"Snapper"): - FreeCADGui.Snapper.active = not FreeCADGui.Snapper.active + FreeCADGui.Snapper.toggle() #--------------------------------------------------------------------------- diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index e496ea8f68..c14841f911 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -27,7 +27,7 @@ __url__ = "http://free-cad.sourceforge.net" import FreeCAD, FreeCADGui, math, Draft, DraftGui, DraftTrackers -from DraftGui import todo +from DraftGui import todo,getMainWindow from draftlibs import fcvec from FreeCAD import Vector from pivy import coin @@ -84,16 +84,16 @@ class Snapper: 'ortho':'dot', 'intersection':'dot'} self.cursors = {'passive':None, - 'extension':':/icons/Constraint_Parallel.svg', - 'parallel':':/icons/Constraint_Parallel.svg', - 'grid':':/icons/Constraint_PointOnPoint.svg', - 'endpoint':':/icons/Constraint_PointOnEnd.svg', - 'midpoint':':/icons/Constraint_PointOnObject.svg', - 'perpendicular':':/icons/Constraint_PointToObject.svg', - 'angle':':/icons/Constraint_ExternalAngle.svg', - 'center':':/icons/Constraint_Concentric.svg', - 'ortho':':/icons/Constraint_Perpendicular.svg', - 'intersection':':/icons/Constraint_Tangent.svg'} + 'extension':':/icons/Snap_Extension.svg', + 'parallel':':/icons/Snap_Parallel.svg', + 'grid':':/icons/Snap_Grid.svg', + 'endpoint':':/icons/Snap_Endpoint.svg', + 'midpoint':':/icons/Snap_Midpoint.svg', + 'perpendicular':':/icons/Snap_Perpendicular.svg', + 'angle':':/icons/Snap_Angle.svg', + 'center':':/icons/Snap_Center.svg', + 'ortho':':/icons/Snap_Ortho.svg', + 'intersection':':/icons/Snap_Intersection.svg'} def snap(self,screenpos,lastpoint=None,active=True,constrain=False): """snap(screenpos,lastpoint=None,active=True,constrain=False): returns a snapped @@ -104,9 +104,19 @@ class Snapper: Screenpos can be a list, a tuple or a coin.SbVec2s object.""" global Part,fcgeo - import Part, SketcherGui + import Part from draftlibs import fcgeo + if not hasattr(self,"toolbar"): + self.makeSnapToolBar() + mw = getMainWindow() + bt = mw.findChild(QtGui.QToolBar,"Draft Snap") + if not bt: + mw.addToolBar(self.toolbar) + else: + if Draft.getParam("showSnapBar"): + bt.show() + def cstr(point): "constrains if needed" if constrain: @@ -342,181 +352,195 @@ class Snapper: def snapToPolar(self,point,last): "snaps to polar lines from the given point" - polarAngles = [90,45] - if last: - vecs = [] - ax = [FreeCAD.DraftWorkingPlane.u, - FreeCAD.DraftWorkingPlane.v, - FreeCAD.DraftWorkingPlane.axis] - for a in polarAngles: - if a == 90: - vecs.extend([ax[0],fcvec.neg(ax[0])]) - vecs.extend([ax[1],fcvec.neg(ax[1])]) - else: - v = fcvec.rotate(ax[0],math.radians(a),ax[2]) - vecs.extend([v,fcvec.neg(v)]) - v = fcvec.rotate(ax[1],math.radians(a),ax[2]) - vecs.extend([v,fcvec.neg(v)]) - for v in vecs: - de = Part.Line(last,last.add(v)).toShape() - np = self.getPerpendicular(de,point) - if (np.sub(point)).Length < self.radius: - if self.tracker: - self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['parallel']) - self.tracker.on() - self.setCursor('ortho') - return np,de + if self.isEnabled('ortho'): + polarAngles = [90,45] + if last: + vecs = [] + ax = [FreeCAD.DraftWorkingPlane.u, + FreeCAD.DraftWorkingPlane.v, + FreeCAD.DraftWorkingPlane.axis] + for a in polarAngles: + if a == 90: + vecs.extend([ax[0],fcvec.neg(ax[0])]) + vecs.extend([ax[1],fcvec.neg(ax[1])]) + else: + v = fcvec.rotate(ax[0],math.radians(a),ax[2]) + vecs.extend([v,fcvec.neg(v)]) + v = fcvec.rotate(ax[1],math.radians(a),ax[2]) + vecs.extend([v,fcvec.neg(v)]) + for v in vecs: + de = Part.Line(last,last.add(v)).toShape() + np = self.getPerpendicular(de,point) + if (np.sub(point)).Length < self.radius: + if self.tracker: + self.tracker.setCoords(np) + self.tracker.setMarker(self.mk['parallel']) + self.tracker.on() + self.setCursor('ortho') + return np,de return point,None def snapToGrid(self,point): "returns a grid snap point if available" if self.grid: - np = self.grid.getClosestNode(point) - if np: - if self.radius != 0: - dv = point.sub(np) - if dv.Length <= self.radius: - if self.tracker: - self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['grid']) - self.tracker.on() - self.setCursor('grid') - return np + if self.isEnabled("grid"): + np = self.grid.getClosestNode(point) + if np: + if self.radius != 0: + dv = point.sub(np) + if dv.Length <= self.radius: + if self.tracker: + self.tracker.setCoords(np) + self.tracker.setMarker(self.mk['grid']) + self.tracker.on() + self.setCursor('grid') + return np return point def snapToEndpoints(self,shape): "returns a list of enpoints snap locations" snaps = [] - if hasattr(shape,"Vertexes"): - for v in shape.Vertexes: - snaps.append([v.Point,'endpoint',v.Point]) - elif hasattr(shape,"Point"): - snaps.append([shape.Point,'endpoint',shape.Point]) - elif hasattr(shape,"Points"): - for v in shape.Points: - snaps.append([v.Vector,'endpoint',v.Vector]) + if self.isEnabled("endpoint"): + if hasattr(shape,"Vertexes"): + for v in shape.Vertexes: + snaps.append([v.Point,'endpoint',v.Point]) + elif hasattr(shape,"Point"): + snaps.append([shape.Point,'endpoint',shape.Point]) + elif hasattr(shape,"Points"): + for v in shape.Points: + snaps.append([v.Vector,'endpoint',v.Vector]) return snaps def snapToMidpoint(self,shape): "returns a list of midpoints snap locations" snaps = [] - if isinstance(shape,Part.Edge): - mp = fcgeo.findMidpoint(shape) - if mp: - snaps.append([mp,'midpoint',mp]) + if self.isEnabled("midpoint"): + if isinstance(shape,Part.Edge): + mp = fcgeo.findMidpoint(shape) + if mp: + snaps.append([mp,'midpoint',mp]) return snaps def snapToPerpendicular(self,shape,last): "returns a list of perpendicular snap locations" snaps = [] - if last: - if isinstance(shape,Part.Edge): - if isinstance(shape.Curve,Part.Line): - np = self.getPerpendicular(shape,last) - elif isinstance(shape.Curve,Part.Circle): - dv = last.sub(shape.Curve.Center) - dv = fcvec.scaleTo(dv,shape.Curve.Radius) - np = (shape.Curve.Center).add(dv) - elif isinstance(shape.Curve,Part.BSplineCurve): - pr = shape.Curve.parameter(last) - np = shape.Curve.value(pr) - else: - return snaps - snaps.append([np,'perpendicular',np]) + if self.isEnabled("perpendicular"): + if last: + if isinstance(shape,Part.Edge): + if isinstance(shape.Curve,Part.Line): + np = self.getPerpendicular(shape,last) + elif isinstance(shape.Curve,Part.Circle): + dv = last.sub(shape.Curve.Center) + dv = fcvec.scaleTo(dv,shape.Curve.Radius) + np = (shape.Curve.Center).add(dv) + elif isinstance(shape.Curve,Part.BSplineCurve): + pr = shape.Curve.parameter(last) + np = shape.Curve.value(pr) + else: + return snaps + snaps.append([np,'perpendicular',np]) return snaps def snapToOrtho(self,shape,last,constrain): "returns a list of ortho snap locations" snaps = [] - if constrain: - if isinstance(shape,Part.Edge): - if last: - if isinstance(shape.Curve,Part.Line): - if self.constraintAxis: - tmpEdge = Part.Line(last,last.add(self.constraintAxis)).toShape() - # get the intersection points - pt = fcgeo.findIntersection(tmpEdge,shape,True,True) - if pt: - for p in pt: - snaps.append([p,'ortho',p]) + if self.isEnabled("ortho"): + if constrain: + if isinstance(shape,Part.Edge): + if last: + if isinstance(shape.Curve,Part.Line): + if self.constraintAxis: + tmpEdge = Part.Line(last,last.add(self.constraintAxis)).toShape() + # get the intersection points + pt = fcgeo.findIntersection(tmpEdge,shape,True,True) + if pt: + for p in pt: + snaps.append([p,'ortho',p]) return snaps def snapToExtOrtho(self,last,constrain,eline): "returns an ortho X extension snap location" - if constrain and last and self.constraintAxis and self.extLine: - tmpEdge1 = Part.Line(last,last.add(self.constraintAxis)).toShape() - tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() - # get the intersection points - pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True) - if pt: - return [pt[0],'ortho',pt[0]] - if eline: - try: + if self.isEnabled("extension") and self.isEnabled("ortho"): + if constrain and last and self.constraintAxis and self.extLine: + tmpEdge1 = Part.Line(last,last.add(self.constraintAxis)).toShape() tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() # get the intersection points - pt = fcgeo.findIntersection(eline,tmpEdge2,True,True) + pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True) if pt: return [pt[0],'ortho',pt[0]] - except: - return None + if eline: + try: + tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() + # get the intersection points + pt = fcgeo.findIntersection(eline,tmpEdge2,True,True) + if pt: + return [pt[0],'ortho',pt[0]] + except: + return None return None def snapToElines(self,e1,e2): "returns a snap location at the infinite intersection of the given edges" snaps = [] - if e1 and e2: - # get the intersection points - pts = fcgeo.findIntersection(e1,e2,True,True) - if pts: - for p in pts: - snaps.append([p,'intersection',p]) + if self.isEnabled("intersection") and self.isEnabled("extension"): + if e1 and e2: + # get the intersection points + pts = fcgeo.findIntersection(e1,e2,True,True) + if pts: + for p in pts: + snaps.append([p,'intersection',p]) return snaps def snapToAngles(self,shape): "returns a list of angle snap locations" snaps = [] - rad = shape.Curve.Radius - pos = shape.Curve.Center - for i in [0,30,45,60,90,120,135,150,180,210,225,240,270,300,315,330]: - ang = math.radians(i) - cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) - snaps.append([cur,'angle',cur]) + if self.isEnabled("angle"): + rad = shape.Curve.Radius + pos = shape.Curve.Center + for i in [0,30,45,60,90,120,135,150,180,210,225,240,270,300,315,330]: + ang = math.radians(i) + cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) + snaps.append([cur,'angle',cur]) return snaps def snapToCenter(self,shape): "returns a list of center snap locations" snaps = [] - rad = shape.Curve.Radius - pos = shape.Curve.Center - for i in [15,37.5,52.5,75,105,127.5,142.5,165,195,217.5,232.5,255,285,307.5,322.5,345]: - ang = math.radians(i) - cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) - snaps.append([cur,'center',pos]) + if self.isEnabled("center"): + rad = shape.Curve.Radius + pos = shape.Curve.Center + for i in [15,37.5,52.5,75,105,127.5,142.5,165,195,217.5,232.5,255,285,307.5,322.5,345]: + ang = math.radians(i) + cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z) + snaps.append([cur,'center',pos]) return snaps def snapToIntersection(self,shape): "returns a list of intersection snap locations" snaps = [] - # get the stored objects to calculate intersections - if self.lastObj[0]: - obj = FreeCAD.ActiveDocument.getObject(self.lastObj[0]) - if obj: - if obj.isDerivedFrom("Part::Feature"): - if (not self.maxEdges) or (len(obj.Shape.Edges) <= self.maxEdges): - for e in obj.Shape.Edges: - # get the intersection points - pt = fcgeo.findIntersection(e,shape) - if pt: - for p in pt: - snaps.append([p,'intersection',p]) + if self.isEnabled("intersection"): + # get the stored objects to calculate intersections + if self.lastObj[0]: + obj = FreeCAD.ActiveDocument.getObject(self.lastObj[0]) + if obj: + if obj.isDerivedFrom("Part::Feature"): + if (not self.maxEdges) or (len(obj.Shape.Edges) <= self.maxEdges): + for e in obj.Shape.Edges: + # get the intersection points + pt = fcgeo.findIntersection(e,shape) + if pt: + for p in pt: + snaps.append([p,'intersection',p]) return snaps def snapToVertex(self,info,active=False): p = Vector(info['x'],info['y'],info['z']) if active: - return [p,'endpoint',p] + if self.isEnabled("endpoint"): + return [p,'endpoint',p] + else: + return [] else: return [p,'passive',p] @@ -722,8 +746,69 @@ class Snapper: # adding callback functions self.ui.pointUi(cancel=cancel,getcoords=getcoords,extra=extradlg,rel=bool(last)) self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click) - self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move) + self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move) + def makeSnapToolBar(self): + "builds the Snap toolbar" + self.toolbar = QtGui.QToolBar(None) + self.toolbar.setObjectName("Draft Snap") + self.toolbar.setWindowTitle("Draft Snap") + self.toolbarButtons = [] + self.masterbutton = QtGui.QPushButton(None) + self.masterbutton.setIcon(QtGui.QIcon(":/icons/Snap_Lock.svg")) + self.masterbutton.setIconSize(QtCore.QSize(16, 16)) + self.masterbutton.setMaximumSize(QtCore.QSize(26,26)) + self.masterbutton.setToolTip("Snap On/Off") + self.masterbutton.setObjectName("SnapButtonMain") + self.masterbutton.setCheckable(True) + self.masterbutton.setChecked(True) + QtCore.QObject.connect(self.masterbutton,QtCore.SIGNAL("toggled(bool)"),self.toggle) + self.toolbar.addWidget(self.masterbutton) + for c,i in self.cursors.iteritems(): + if i: + b = QtGui.QPushButton(None) + b.setIcon(QtGui.QIcon(i)) + b.setIconSize(QtCore.QSize(16, 16)) + b.setMaximumSize(QtCore.QSize(26,26)) + b.setToolTip(c) + b.setObjectName("SnapButton"+c) + b.setCheckable(True) + b.setChecked(True) + self.toolbar.addWidget(b) + self.toolbarButtons.append(b) + if not Draft.getParam("showSnapBar"): + self.toolbar.hide() + + def toggle(self,checked=None): + print "checked",checked + if hasattr(self,"toolbarButtons"): + if checked == None: + self.masterbutton.toggle() + elif checked: + if hasattr(self,"savedButtonStates"): + for i in range(len(self.toolbarButtons)): + self.toolbarButtons[i].setEnabled(True) + self.toolbarButtons[i].setChecked(self.savedButtonStates[i]) + else: + self.savedButtonStates = [] + for i in range(len(self.toolbarButtons)): + self.savedButtonStates.append(self.toolbarButtons[i].isChecked()) + self.toolbarButtons[i].setEnabled(False) + + def isEnabled(self,but): + "returns true if the given button is turned on" + for b in self.toolbarButtons: + if str(b.objectName()) == "SnapButton" + but: + return (b.isEnabled() and b.isChecked()) + return False + + def show(self): + "shows the toolbar" + if hasattr(self,"toolbar"): + self.toolbar.show() + else: + self.makeSnapToolBar() + self.toolbar.show() if not hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper = Snapper() diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 3196c96fdc..e8eb87c56b 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -3642,13 +3642,25 @@ class ToggleSnap(): "The ToggleSnap FreeCAD command definition" def GetResources(self): - return {'Pixmap' : 'Draft_Snap', + return {'Pixmap' : 'Snap_Lock', + 'Accel' : "Shift+S", 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggle snap"), 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggles Draft snap on or off")} def Activated(self): if hasattr(FreeCADGui,"Snapper"): - FreeCADGui.Snapper.active = not FreeCADGui.Snapper.active + FreeCADGui.Snapper.toggle() + +class ShowSnapBar(): + "The ShowSnapBar FreeCAD command definition" + + def GetResources(self): + return {'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ShowSnapBar", "Show Snap Bar"), + 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ShowSnapBar", "Shows Draft snap toolbar")} + + def Activated(self): + if hasattr(FreeCADGui,"Snapper"): + FreeCADGui.Snapper.show() #--------------------------------------------------------------------------- # Adds the icons & commands to the FreeCAD command manager, and sets defaults @@ -3695,6 +3707,7 @@ FreeCADGui.addCommand('Draft_AddToGroup',AddToGroup()) FreeCADGui.addCommand('Draft_SelectGroup',SelectGroup()) FreeCADGui.addCommand('Draft_Shape2DView',Shape2DView()) FreeCADGui.addCommand('Draft_ToggleSnap',ToggleSnap()) +FreeCADGui.addCommand('Draft_ShowSnapBar',ShowSnapBar()) # a global place to look for active draft Command FreeCAD.activeDraftCommand = None diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 43477b4e37..3714290401 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Sun Feb 26 13:28:36 2012 +# Created: Mon Mar 12 17:12:41 2012 # by: The Resource Compiler for PyQt (Qt v4.7.4) # # WARNING! All changes made in this file will be lost! @@ -23949,241 +23949,245 @@ qt_resource_data = "\ \xe3\xab\x65\xc9\x7a\xb7\x23\x8c\x3b\xb9\x4f\x11\x66\xdc\xbb\xbe\ \x30\xc5\x06\xf3\x83\x24\x92\x29\x63\x03\xca\x58\x8b\x27\xe2\x98\ \x19\x1b\xc0\xe7\x66\x3d\xe1\xad\x83\xff\x03\xad\x19\x30\x45\ -\x00\x00\x0e\x86\ +\x00\x00\x0e\xc2\ \x00\ -\x00\x94\xbb\x78\x9c\xed\x1d\xfd\x73\xda\xb8\xf2\xf7\xfc\x15\x9a\ -\xfc\xd0\xe9\x9b\xc9\x85\x90\xe6\xa3\x69\x09\x37\xfd\x6e\x67\x7a\ -\x77\xbd\x92\xf6\xde\xbd\x5f\x6e\x84\x2d\x40\xaf\xc6\xa2\x92\x08\ -\xe1\xe6\xfd\xf1\x6f\x57\x92\xc1\x36\xc6\x04\x04\x98\x5c\xe9\x74\ -\x26\x58\xb2\x57\xab\xd5\x7e\x69\x77\x2d\x37\x7e\xbe\xeb\x47\xe4\ -\x96\x49\xc5\x45\x7c\x7d\x58\x3f\x3e\x39\x24\x2c\x0e\x44\xc8\xe3\ -\xee\xf5\xe1\x97\x9b\xb7\x3f\x3d\x3d\xfc\xb9\x79\xd0\x18\xf2\xe9\ -\x4d\x67\x70\x53\xf3\x80\x34\x82\x88\x2a\xd5\x7c\x37\xe4\xcf\x9e\ -\xbd\xe6\x34\x12\x5d\xf8\x1b\x75\x5b\x4c\x6b\x78\x58\xbd\x96\xb4\ -\xa3\x1b\x35\x7b\x13\xdc\x3d\xe2\x61\x97\x69\x62\xae\xaf\x0f\x7f\ -\xff\xc3\x5c\x1e\x92\x98\xf6\xd9\xf5\x61\x29\x10\x1c\x8c\x34\x06\ -\x52\x0c\x98\xd4\x63\xf7\x44\x97\x89\x3e\xd3\x72\x6c\x3a\x49\x43\ -\xb2\x40\x9b\x5f\xa4\x71\xd7\x3c\x69\xd4\xee\xdc\xc5\x18\x2f\xc6\ -\xee\x02\x50\xd0\xbd\xe6\xf9\x15\x34\xd9\x9f\xb6\xb9\xc7\x78\xb7\ -\xa7\x9b\x17\xa7\x57\x8d\x9a\xfb\x6d\x60\xd6\x12\xa0\x8d\x5a\x32\ -\x78\x11\x26\x23\x1e\x87\x62\x74\xc3\x75\xc4\x1c\x32\x4a\x4b\x40\ -\xbe\xf9\x8e\xc5\x4c\xd2\x88\x28\x37\x99\x46\xcd\x75\xcc\x82\x8c\ -\xe8\x58\x0c\xa7\xc4\xf9\xfa\x52\xdc\x7d\x34\x4d\x0e\x62\x6e\x48\ -\x35\xa0\x01\x00\x3a\x74\x13\x88\x87\xfd\x36\x93\xcd\x8b\x46\xcd\ -\xfd\xb2\xe8\xa7\x47\x98\x01\xd1\xa7\xb2\xcb\xe3\x1c\x84\xab\x52\ -\x08\x5c\xb3\xfe\x94\x92\xe9\xc5\x7c\x27\xc5\x70\x00\x38\x27\xcb\ -\xd9\x4d\xae\xed\xed\x33\x83\xeb\x29\xb1\x0a\xe8\x65\x16\x9d\xb4\ -\x0a\xa8\x36\x8b\x54\x29\xed\xdc\x68\xc0\xb8\x9a\x07\x34\xb2\xad\ -\x7f\x9d\x4e\x07\x9e\xce\xa8\x00\xd0\xfb\x19\x40\x3d\x21\xf9\xdf\ -\x22\xd6\x13\x50\xf5\xab\x09\xac\x3c\xb4\x59\x22\x7d\xa4\x6d\x16\ -\x25\xa0\x22\xbc\xc8\x3e\x5f\x40\x26\x76\xa7\x33\x37\x4c\x48\x65\ -\x49\xc4\x63\xcd\x64\x87\x06\x8c\xf4\x45\xc8\x72\x84\x2a\xa6\x96\ -\x6d\xb4\x98\xa5\x50\xaf\x65\x71\x5f\x30\x15\x23\xad\x9f\x24\xeb\ -\xbc\x12\xfd\xb6\x48\xaf\x3b\x76\x0c\xa0\x23\xc0\x8e\xb6\xb8\xfb\ -\xeb\xac\x7c\x82\x42\x44\x37\x7c\x50\x3c\xc7\x9b\x1e\x57\x04\xfe\ -\xeb\x1e\x23\x5f\x3e\x98\x29\xc2\x8c\xc9\xa8\xc7\x83\x9e\x69\xb4\ -\x44\x80\xf6\x61\xc4\xc8\x88\x47\x11\x19\x09\xf9\xed\x19\xb9\x01\ -\xa8\x6d\x2a\xed\x13\xa6\x7d\x10\x21\x91\x68\x94\xf0\x56\x22\x91\ -\x08\x8f\xc2\xd5\x80\x4a\xaa\x19\xd1\xf6\xc1\x23\x1c\x03\x40\x6a\ -\xaa\xbe\x65\xe1\x0c\x15\x33\x23\xbf\x95\x8c\xbd\x7a\xf1\x9a\xdc\ -\xc0\x1d\xb7\x9c\x8d\x88\x1a\x2b\xa0\x18\xe9\x08\x69\x46\xe1\x5a\ -\xe1\xbd\xd2\xae\x10\x0d\x34\xe8\xcd\x7b\x2f\xcf\x0c\x95\x90\xa0\ -\x6f\x62\xd4\x75\x44\xe9\x10\x70\xbf\x3e\x3c\xc9\x91\x2c\x70\xb0\ -\xbf\xf0\x5f\x0c\x27\x04\x3e\x63\x7d\xa2\xba\xb7\x78\x28\x18\xa8\ -\x96\xe8\xf8\x7b\x8f\x96\xe3\xab\xfb\xb0\xfc\x94\x1f\xec\xea\x14\ -\xd1\x71\xde\x70\xb5\xfc\x78\x7e\x08\xb8\xd5\xf6\xc1\x60\xa1\xec\ -\x35\x6a\x56\x0d\x4d\x74\x54\xa6\xdb\x5b\x63\x9d\xfa\x29\xac\xd3\ -\x55\xf5\x15\xeb\xd0\x61\x04\xa0\x45\x24\x0a\x57\x70\xe3\x8a\x0a\ -\xc6\x7d\x39\xd4\x5a\xc4\x05\xba\x0a\xfa\xda\xb6\x6f\x65\x65\x85\ -\x5a\x21\x4c\x4f\xd2\xe8\x82\x18\x54\x83\x68\xff\x17\xdc\x88\xbc\ -\x19\x2b\xe3\x99\xdc\xb8\x06\x5c\x5e\x08\xb1\x2d\xc7\xa5\x92\x85\ -\xe8\xec\xe0\x9f\x6c\x47\x17\xb4\x55\x8c\x5d\xf6\x47\xb6\xb3\x1d\ -\x0d\x19\xf6\x99\xbf\x59\x86\x9e\x19\x64\xed\xea\xca\xb1\xc3\x6e\ -\x6a\x2b\x6f\xee\x2b\x12\xa0\x05\xf6\x70\xae\x00\xb5\x62\x3a\xd8\ -\x75\xe9\x59\xa4\x1d\x96\x97\x1f\x85\xb3\x56\x63\xf0\x25\xa2\xbd\ -\x00\x65\xd0\x77\xb4\x40\x02\xfd\x78\x42\xb4\xaa\xd7\xfc\x4a\xc4\ -\xf0\x6b\x68\xdc\xb1\x9d\x17\xa6\x27\xeb\xf1\x9c\x67\x85\xca\x19\ -\x24\xd2\x66\x70\x2f\x09\x25\x1d\xc5\xce\xe1\xe5\x48\x95\x14\x89\ -\xd0\xf1\x3d\xde\x8e\xdc\x9d\x9d\xcd\x17\xbc\xfa\xe9\x79\x89\xe8\ -\x9d\x9e\x9f\x57\x66\xbd\xa6\xb4\xfa\xf1\x84\x70\x01\x7f\x2e\x74\ -\x05\x23\x0e\xde\x11\x46\x61\x2a\x90\xc1\xd6\x80\xc7\x45\xdb\x56\ -\x05\xed\xed\x69\xd8\xa2\x78\x66\xf7\x35\x63\x93\x09\xae\xcf\x15\ -\xbc\xa5\xc0\xe7\xb9\x91\x5d\xc0\xe6\x34\x13\xba\x59\x0a\xea\x12\ -\x2c\x9f\x5a\xb4\x07\xca\xea\x1b\xde\x5f\x3d\xf1\xdc\x5f\x9d\x78\ -\x99\x36\xca\x8d\xd2\xde\xc9\x48\xd0\xb9\x8f\x3d\x63\x64\x32\x41\ -\x34\x5a\x30\x47\xde\xe1\x4c\x92\x6f\x6c\xbc\x95\xb8\x0a\x0c\x18\ -\x24\x08\xec\x2a\xeb\xfb\x05\x37\x54\x8f\xe3\x60\x55\xc5\x56\x02\ -\x2d\xa3\xea\x46\xa7\x91\xd7\xd4\x57\x10\x23\x8c\xe0\x03\xff\xe6\ -\xb5\x48\xcb\x34\x2f\x90\x15\xb8\x9b\xc1\xcd\xe8\x76\xe4\xb8\x87\ -\x81\x09\x68\xfe\xae\x9f\x3d\x7b\x3f\x81\xd8\xa8\x99\xc6\xa5\x59\ -\x55\xf1\xbf\xd9\x7b\x1e\xeb\xf9\xac\x8a\x77\xe4\xc8\x69\xb3\x2a\ -\x67\xd9\xfc\xca\xa4\xd7\xe5\x56\x4e\x4f\x32\x69\x96\x29\x5a\x79\ -\x80\x73\x54\x96\x25\xdd\x5a\x7d\x99\xd3\xba\xcf\xb6\x7c\x57\x35\ -\xee\x85\x9f\xc6\x55\x6e\x6e\x6b\xd0\xb4\xc1\x50\x4a\x60\xd9\x0f\ -\x71\xc8\xee\x8a\xdd\x97\xfa\x56\xdc\x17\x98\x0d\xce\x6a\xaf\xc1\ -\x6d\xeb\x5e\x83\x4f\x1b\xd6\xac\xc1\xcb\x65\x6f\xaf\xc1\xd7\xae\ -\xc1\x57\xcd\x4c\xbc\x88\xf4\xce\x2a\xf0\x4b\x3f\x05\x4e\xed\xd4\ -\xb6\xa2\xbf\xb7\xb3\xfd\x84\xd9\x18\x41\xdf\xab\xef\xbd\xfa\xde\ -\xa5\xac\x6a\x3d\xcd\x45\xab\xd4\x81\xf8\x6d\xfb\x5d\xb8\xd6\x54\ -\xdd\x98\x47\x2a\xd0\x66\x1f\x79\xcc\xde\x84\x5c\xcf\x68\x33\x0c\ -\x19\x31\xe8\xf0\xc9\x0e\x15\x05\xb4\xa7\xb3\x35\xf1\xb5\x4c\xe0\ -\x3a\x29\x0e\x5b\x5d\xe3\xdd\x8f\xe4\x5b\x89\x3d\xa4\x67\x66\x26\ -\x6d\x57\x78\x37\x75\x60\xd5\x92\x78\x76\x7f\x41\x9c\x1a\xe2\x1e\ -\x0b\xbe\x15\x1a\x62\xec\xf0\x8a\x07\x1b\x08\xc0\xb6\xc8\xbe\x1d\ -\x02\x18\x92\x11\x8d\x35\xd1\x62\x52\x4a\x64\x12\x07\xb5\x54\xac\ -\x58\x8a\xbe\xe9\x70\xc5\x48\x84\xaa\x84\xe5\x37\xc1\xcd\x2d\x7a\ -\x0b\x38\x58\xf3\xee\x72\x44\x34\x0e\x53\xb1\x6b\x1a\x48\xa1\x14\ -\x51\x4c\x61\xf1\xa7\x47\xec\x7a\x99\xac\x26\x20\x25\x62\x76\xc7\ -\x77\xd6\xd4\x57\xcd\xe6\x97\x9b\x60\x73\x9f\x10\xed\x87\x8e\xe3\ -\x72\x45\x0c\x38\x16\x1e\x01\x3b\x0d\xc6\xa9\xe2\xb9\x36\x03\x27\ -\x74\xa0\x13\x8e\x02\x2f\xb7\x0f\xac\x76\x44\x04\x70\xbb\x1c\x71\ -\xc5\x92\x26\x65\xef\xa7\xd1\x88\x8e\x81\xf3\x34\x95\x58\xea\x48\ -\x62\xf1\xd3\x04\xe2\x26\x44\xe1\x5d\x24\xda\x34\x22\x6b\x18\xc3\ -\x51\x20\x37\x4c\x1b\xe8\xd7\x04\x45\x0e\x80\xcd\xcf\xcd\xda\x8c\ -\xc1\xb8\xbf\xc3\x95\x80\x55\xcb\x4f\xfd\xe9\x46\x04\xc8\x23\x67\ -\xff\xab\x90\x7d\x1a\x45\xe3\x23\x02\x84\x64\xd2\xb0\x21\xa6\x3a\ -\x5c\xce\xf0\xc8\x19\x8b\x01\x67\x8a\x20\x72\x8a\x45\xd0\xce\xc2\ -\x63\x92\x88\x9e\x18\x18\xdf\x27\x2d\x81\xf8\x4c\x9b\x82\x64\x25\ -\x39\xff\x44\x10\x93\xa7\x41\xae\x94\x66\x34\xf4\xc8\xf2\x97\xd8\ -\x16\x33\x48\x16\x81\xcc\xe4\xb6\x63\x4c\x0c\x16\x2f\x01\x89\xdf\ -\x92\xf4\xeb\x5e\x26\x8a\x64\xe2\x7c\x23\x22\xf1\x74\xbd\x36\xc5\ -\xb8\x50\x69\xeb\x80\x41\x6a\x70\xa7\xc0\x59\x50\x3a\x25\x2f\xae\ -\xa2\x05\xab\x5b\xa0\xd5\x08\x49\x2c\x74\xea\xf9\xb6\x0d\x70\x0f\ -\xcc\x33\x71\x34\x86\x07\x58\x4c\x00\x75\xf0\x73\xa0\xe9\xd5\xcd\ -\xe7\x8f\x1b\x11\x8a\x17\x59\xbc\x13\x74\x1f\x87\x5c\xd1\x76\x34\ -\x8d\xba\x63\xc0\xe6\x5f\x0f\xd9\x04\xd9\x05\x6a\xed\x70\xb8\x7d\ -\xed\x41\xdf\xf2\x1d\xee\x3e\xe8\xbb\xee\xa0\x6f\xdd\x33\x40\x2a\ -\x69\xc8\x87\x6a\x52\x69\x6a\x74\x01\xc8\xa4\x1a\xb0\x80\x83\x27\ -\x38\x10\x40\x48\x75\x8c\x6f\x22\x61\xf3\x89\xad\xe3\x11\x04\x44\ -\x55\xd3\x38\x60\xe4\x31\x8f\x3b\x3c\x06\xbc\x3d\x04\x75\x41\x6e\ -\x51\xd2\xb8\x5b\x45\x38\x67\x41\x85\xd4\x02\x56\x57\xc3\x4e\x87\ -\xe7\x23\xc5\x6e\x0e\x83\xbb\xed\x98\x7d\xa0\xde\x67\x4b\xbc\x07\ -\xaa\x7d\x36\xfd\x26\xc8\x12\x31\xcb\x25\xec\xbd\xc7\x0b\x5f\x45\ -\xf6\x7e\x22\x97\xc6\x68\x83\x09\x27\x22\x08\x86\x92\xd0\x2e\x45\ -\xd7\x35\xe5\xd8\xea\x1e\x98\x4d\x89\x41\x15\x1a\x1b\xc7\x97\xc7\ -\x21\x0f\x28\x3a\xb9\x36\x33\x41\x44\x87\x30\x98\x95\x47\x0c\x63\ -\x51\x21\x00\xbd\xe3\xfd\x61\xff\x21\x5b\x6d\x98\xc2\x8f\x64\xb2\ -\xf7\x06\x7b\x3e\xa5\x37\x91\xa5\xf5\xd8\x20\xff\x62\x85\x2b\x2f\ -\xcc\x68\x99\xdb\xcc\x84\xff\x79\xc8\x24\x48\x7b\xda\x9c\x6f\x42\ -\xd4\xe7\x20\xb2\x83\x46\xba\xbc\x08\xc1\x69\xab\xe2\x7c\xee\xd5\ -\xd5\xd5\xea\x19\xdd\xb2\x32\xe5\xb3\xed\x24\x8a\xad\x1a\x7b\x63\ -\x17\xe6\x81\xea\xb2\x0d\x3b\x00\x9b\x09\x81\x79\x14\x9d\x15\xd9\ -\xff\x4c\xe0\x0a\x64\x9a\xd9\x8c\x48\x07\x2e\x41\xd4\xa7\xb9\x91\ -\x63\xf2\x5b\x12\x46\x36\x61\xaf\x71\xfe\x89\x11\x07\x2c\xe5\x32\ -\xb9\xd1\x25\x54\xc2\x5b\x1c\x6b\xf2\x5e\xcd\xd8\x3f\x61\xb3\x04\ -\xab\x23\x29\xf6\xa1\xde\xf9\x6c\xee\x7b\x44\x83\xef\x2b\xcf\x78\ -\x26\x01\x3a\xb0\x83\x88\xc6\xbb\x79\x46\x43\xf9\x0c\x97\x60\x45\ -\xc7\xf6\x7f\x7c\xda\x55\x5e\xf4\x2b\x52\xf9\x55\x14\x2f\xe0\x76\ -\x4a\x64\xfe\xfd\x27\x79\x7c\x23\x06\x85\xa1\x86\x2d\x61\xf0\x1f\ -\xf2\xf8\xad\x04\xd9\xaa\x10\x87\x3f\x01\x87\x16\x38\x7a\x5e\x28\ -\x54\xad\x92\xea\x9b\x49\xdf\x7a\x14\xd8\x80\xe9\x9d\x98\x5c\x4a\ -\xba\x92\x87\x19\xfb\x69\x62\xe3\x2e\x96\xbe\x09\xfb\xf9\x45\x31\ -\x33\xe8\x43\xde\x39\x5b\xfc\x77\x53\xef\xad\x3d\xd2\x5d\x1e\x78\ -\xdd\x6f\x9c\xd7\x1e\xe9\x5e\x50\x9a\x31\xbf\xa8\x01\x45\xd9\x1d\ -\x17\x56\x81\xf3\xf1\x5a\x0c\xdb\x11\x9b\xb7\x4f\x0d\x4d\x6f\xb2\ -\x5b\xf5\x7a\xe1\x9d\x25\x93\x24\x6d\xa6\x47\x0c\xd4\x15\xa3\x41\ -\xcf\x6a\x32\x2c\x66\x5a\xef\x3b\xb7\x16\xf1\x66\xfd\xf8\x24\xfb\ -\xaf\x51\x73\x3d\x9b\x56\x34\xad\x64\x45\xff\x31\xfa\xe6\x1e\x32\ -\xb0\x60\x6b\x59\x12\xb0\xe1\xb1\x61\x02\x45\xd8\x2d\x5b\xa2\x2a\ -\x74\x7b\x91\x1a\x8f\xa8\x39\xce\xce\x4e\x2e\xc9\x6b\xdb\x23\x1d\ -\x60\x2b\x0d\x16\x51\x1e\x93\x16\xa6\xb3\x3a\x63\x02\xdb\x63\x46\ -\x7a\x62\x44\xfa\x34\x1e\x13\xf5\x7d\x48\x25\x53\x13\x71\xe9\x27\ -\x60\x3c\xb2\xde\x25\x71\x9f\xfa\xc9\x56\xe2\x3e\x28\x1b\x6f\xec\ -\x1a\x3f\x50\xc9\xd8\xb4\xeb\xe9\xf9\x82\xfa\x82\x72\x8e\xb9\x32\ -\xf8\x01\x0f\xc2\x8b\x31\xa9\x2a\x81\x1b\xb1\x94\x94\x44\x20\x8c\ -\x85\xaf\x1c\x54\x2c\x8b\xe5\x76\xc8\x45\x4d\x5b\xe0\x0a\xdc\xd7\ -\xdd\xb8\x28\x77\x37\xea\x17\x97\x97\x97\xa7\xf5\x73\x1f\xa7\x63\ -\x79\x73\x39\x8d\x5e\x87\xb0\x20\x7d\x1a\x99\xc3\x10\x79\xb2\x4c\ -\x81\x10\x32\xe4\x31\xd5\x0c\x0b\xcb\x98\x34\xce\x9c\x22\x8f\x31\ -\xb8\xce\xee\x8e\xc9\x13\x72\x4d\x4e\xc0\xfc\xd5\x3d\x52\xdf\x25\ -\xea\xe2\x62\x2b\xda\x62\xc2\x8b\x0f\x56\x5b\x2c\xeb\xb7\x97\xdb\ -\x99\xbd\xdf\xbe\x76\xbf\x7d\x55\x7d\xf9\x9a\xf7\x59\x6c\x2a\xee\ -\x1f\x80\xc6\x2c\xdf\x9c\x94\xe6\x99\x9e\x6e\x26\xcb\xb4\x15\xf5\ -\x11\xf2\xfe\xa7\x07\xaf\x41\x36\xed\x6f\x2c\x51\x55\x5a\x24\x40\ -\x0b\x2a\xbc\xe6\xca\xcf\x8d\x88\xc0\x68\xc5\xc1\x46\x23\xee\xe5\ -\xba\xb6\x5c\xf4\xf7\xba\xd6\x47\xd7\xae\x12\x60\xf8\x01\xdc\xba\ -\xe9\x5b\x92\x46\x39\xe2\x4b\x66\x21\xe6\x23\x3b\xc3\x38\xb0\x0e\ -\x9c\xee\x51\x6d\xde\x3d\xa3\x44\x27\x22\x72\x7c\xf0\x15\xef\x76\ -\x45\x54\x21\xef\x74\x60\xa7\x08\xed\xb8\x39\x8c\x60\xbf\x68\x92\ -\xb2\x16\x60\xb2\xc5\xd4\x92\x99\xca\x2a\xaa\x88\x02\xc4\x3c\xf6\ -\x8c\x25\xa5\x82\xb5\x55\x18\x3e\xee\x02\x3b\x68\x96\x27\x91\x8b\ -\xcb\x80\xcb\x5a\x5f\x53\xc4\xa6\x24\x2e\x04\xa3\x9c\x6f\x3f\x2e\ -\xa4\xa7\x2a\x6f\x6f\x8b\x8a\x6c\xd1\x85\x9f\x29\x5a\x35\xfc\x94\ -\x24\x82\xf1\x0e\x62\x75\x41\x75\x46\xa9\xfc\xe8\xd4\xbd\x51\xda\ -\xb6\x51\x5a\x90\xb4\xfb\x27\x98\xa5\x84\xff\xed\x78\xa6\x3c\x0f\ -\x45\x41\x99\x17\x8d\xc3\xc9\x3e\x67\x23\x11\xfa\x93\xe3\xd3\x0a\ -\x22\xf4\x38\xbd\x44\xd0\xf7\xaa\xb8\x70\x5b\xe0\xf9\x1d\x82\x55\ -\xd3\x61\x19\x5d\xdc\x01\x8c\xaa\xd3\xc4\xe5\x61\xc6\xbd\x26\x5e\ -\x8b\x26\x5e\x78\x2a\x89\x4f\xce\x71\xf6\x4c\x12\xe4\x28\xf3\xec\ -\xe4\x4b\x30\xf6\x7b\x33\x45\xfa\xee\xf8\xe0\x03\xe0\x4b\x63\x74\ -\xa7\x69\xea\x49\x35\x0c\x7a\xe8\x57\x3f\xfa\x3e\x14\xfa\xf9\x0b\ -\xc9\x69\x64\x7f\x62\x65\x46\x32\x90\xd2\xe3\x28\x7f\xab\xa2\xb1\ -\x4a\xee\x74\x2d\x4c\xf2\x8e\xfd\x79\x00\xf8\xd8\x5f\x7d\x11\x8b\ -\xe4\x36\x44\x92\x74\x68\x9f\x47\xe3\xa2\x71\x8f\xde\xb3\xe8\x96\ -\xe1\xb7\x93\x8e\xa6\xc0\xed\x43\x06\x55\xb3\x5f\xa0\x16\x99\x83\ -\x82\xe7\x9f\xbd\x14\x51\x68\xaf\x37\xf2\x2a\x25\x8e\xb1\x3a\x60\ -\x1a\xf1\x6e\x0c\xab\x31\x03\x1d\x84\x1c\xe5\xeb\x05\xf6\x7f\x46\ -\x1e\xfe\xdf\xe4\xf2\x46\x52\x0e\xac\xd3\x9d\xb6\x7c\x7d\xc5\x30\ -\x66\x0e\x68\x30\xbd\x3c\x0e\x4b\x1a\x15\xab\xb1\xf6\x26\xa5\xd0\ -\xa4\xd4\xfd\x4c\x4a\x7d\xd5\x33\x40\xa7\x36\xa5\x3f\x88\xf0\x33\ -\x52\xaa\xc7\x58\x85\x86\x65\xc1\x44\xf6\x96\x65\x2d\x96\xe5\x2d\ -\x8f\xd8\xab\x9e\x10\xa0\x63\x67\x8c\x4b\x07\xfa\x02\xdb\xb7\xc8\ -\xbf\xe7\xf1\xb2\xfe\xfd\x93\x93\x72\x02\x79\xd1\x67\xf9\x3c\x62\ -\x98\xe7\x7e\x77\xb6\x91\x29\x19\x0c\x30\x4c\x84\x45\x39\xd4\x9c\ -\x7f\xef\x2a\x08\x97\x14\x10\x3f\xa5\x69\xb1\xda\x2b\xcd\x39\x4a\ -\x73\x89\xf3\xb2\x0a\x94\xa6\x7f\x72\xeb\x11\xed\x0f\x9e\x93\x8f\ -\x8c\x86\xa0\xd0\xa8\x94\x62\x64\xdd\x89\x5d\x2c\x94\x5f\x5b\x99\ -\x3c\xef\xdb\x6f\x1a\xed\x2a\x57\xfa\x95\x68\xbf\x16\x9a\x9c\x57\ -\x57\x21\x8e\xc3\x5f\x56\x3b\xfc\x55\x75\xc3\xbf\xe2\x32\x80\x9d\ -\x41\x85\xf4\x77\x18\x54\xb8\x04\x0e\x83\x0a\x57\xa1\x05\xaa\xa5\ -\x57\xe5\x22\x58\x04\x2a\x5c\x03\x8b\x40\x85\x4b\xf0\x92\x06\xdf\ -\x54\xd5\xcb\x30\x45\xa2\xc2\xa5\x98\x22\xe1\xb5\x1c\x95\xbb\x2a\ -\x9e\xe9\x9b\xfa\x82\x1a\xdb\xb9\xde\xca\x57\x66\x3f\x1f\x9d\x8a\ -\xdd\xd8\xf8\x61\x6a\x27\xb5\x8b\xee\xca\xba\xbe\x20\x97\x9a\x26\ -\x96\x0b\x9a\x78\x57\x42\x09\x17\xd9\x32\xce\xbe\xee\xc1\x86\x27\ -\x4d\x24\x2a\x19\x49\xbe\xbd\x7d\x4c\x92\x6d\x32\x40\x8d\x58\x47\ -\x1f\xb9\x0f\x39\xbb\x41\x3e\xb4\x7e\xc3\x93\x1e\xe3\x90\x4a\x9f\ -\xc3\xe8\x96\xf3\xc2\x32\x0b\xf8\x4f\x74\xc5\x3e\x02\xa1\xc9\xe3\ -\x34\x6d\x2b\x7c\x75\xef\xf3\xbc\xcc\xe7\x03\xd1\x40\x9e\xea\x67\ -\xd5\xef\xe5\xbd\x88\x4c\x49\x2e\xec\xac\x5b\x5f\xdf\x11\x60\x34\ -\xbc\x04\x19\x12\xc1\xc6\x35\xcf\x82\x38\x53\xf9\xa1\xe5\xfb\x38\ -\xd3\x56\xe3\x4c\x0b\xaa\xd6\x1f\x74\x9c\xe9\x3d\xbe\xb9\x82\x27\ -\x37\x62\xba\x44\xb9\xd7\x59\x28\x98\x1a\xc9\x02\x2d\xe4\x18\x4f\ -\x7f\xd1\xee\xd3\x70\x28\x24\x48\x17\x95\x6e\x7c\x14\xe9\xe7\x03\ -\x2b\x39\x8f\xba\xfa\x39\x06\xad\xf0\xdc\xb6\x69\x45\x54\x92\x87\ -\x09\x43\x16\x62\x04\x0b\x4d\x52\xa2\x32\x5d\x0e\x07\x6e\x03\x73\ -\xe5\xa0\x6c\xe7\x1c\x6c\x37\x18\xb2\xc0\xae\xda\x27\x3f\x9d\x9c\ -\xed\xcc\xc0\x9a\xde\x97\xba\x29\x75\x87\xd3\xdf\x93\x84\x98\x7d\ -\x21\xee\xfa\xf0\xe2\x90\xf4\xa9\xec\xf2\xf8\xfa\xb0\x5e\x3f\xc4\ -\x12\xb2\xc6\x80\xdf\xf5\xe9\x20\xa9\x81\x6b\x7e\xff\x64\xae\xdf\ -\x4a\xd1\xff\x05\x9c\x95\x96\x18\x4a\xac\x99\xca\xdd\x05\xcf\x05\ -\x43\xa5\x45\xdf\x8e\xa8\x0c\x26\xe9\x16\x8b\xa5\x11\xd7\xa6\x91\ -\xd6\x94\xa4\x02\xfd\x4c\xbb\xb9\x05\x34\x3b\x8b\x43\xd5\xfc\xfd\ -\x0f\xf3\x1c\xa8\x3a\xd7\x70\x60\xa5\x09\x43\x5f\x08\xa1\x86\x00\ -\x5e\x73\x1a\x89\xee\x71\x0f\x85\xcb\x74\x18\x02\xe4\xc7\x2d\x47\ -\x24\xf5\x85\xe1\x62\x44\x3e\x0d\x55\x2f\xe9\x9f\x87\x8c\x45\x56\ -\xf9\x61\x92\x53\x60\x85\xd8\xcc\xd2\x6e\x1e\x4a\x08\x6d\x6d\x68\ -\xb9\xea\x9c\x62\x02\x4d\x3a\xb7\x82\xca\xa2\xf5\x9a\x5d\xd4\xed\ -\xa0\xe5\x0e\x1c\x28\x26\xd1\xb4\x77\x4b\x34\xb2\xbb\x9d\x39\xc8\ -\x4c\x7a\xb7\x82\x4c\x52\x55\x50\x8c\xcc\xb4\x77\x2b\xc8\x64\x8a\ -\xcd\x8a\x31\xca\xdd\xe2\x8f\x56\xb6\x01\x21\x35\x24\x53\x46\x91\ -\x2a\xa3\x72\xc1\xf6\xc6\xcc\x96\x1c\xdb\x59\x4c\xae\xed\xa8\x0a\ -\x10\x00\xd8\x05\x67\x58\x60\x22\x3d\x76\xe3\xa2\x77\xd2\x8d\x69\ -\xd4\x0c\x22\x7c\x97\x35\x7c\x8c\x87\x38\xe0\x0e\xc6\xb6\x9a\x3b\ -\xc0\x05\x60\xfc\x36\x0d\x2b\xf7\x56\x39\x7e\x57\xdc\xdd\x62\x41\ -\x46\x42\x37\xc1\x0c\xbe\x89\xf1\xbc\xe5\x29\x4c\x6c\xb6\x14\xc1\ -\x53\x5f\x9d\x45\xc2\xdf\x44\x8f\x07\xe8\x6a\x9a\xe9\x65\xd2\x1e\ -\x8d\xbb\x66\xfd\x04\x06\xb8\x4b\xae\xc7\xcd\x27\x97\x70\x3d\x4e\ -\xec\x19\x3e\x3e\x0b\x29\x64\x78\x54\xb5\xf1\x8c\xf3\xe0\x9e\x9c\ -\x5d\xe6\xc0\x9d\x15\x81\xb3\x3f\x95\x5b\x9b\x0c\x6d\xb7\x4a\xea\ -\xc9\xeb\xcb\x9b\x25\xf2\xe5\xd5\x3a\x69\x7c\x7e\x59\xdf\x1a\x8d\ -\xcf\xd6\x47\xe3\x8b\xcd\xd2\xf8\x2c\x4b\xe3\xd3\xcb\x73\x2f\x1a\ -\x9f\x9f\xe4\xc0\x5d\xee\x20\x8d\x93\x43\x29\x37\x4c\xd9\xb3\x75\ -\x52\xf6\xec\xe4\x3c\x0b\xee\x69\xa1\x30\x54\xac\x21\x92\x53\x4b\ -\x36\x4b\xd9\xf3\xa7\x59\x41\xbe\xf0\xa2\x6c\xfd\x22\xa7\xca\x2f\ -\xae\x76\x97\xb2\x1b\xd6\x06\x4f\xf2\xa4\x28\x14\xdf\x7b\x5b\xb5\ -\xab\x3c\xb8\xa7\xcb\x51\x36\x7d\x09\xfd\x8d\xda\x90\x37\x0f\xfe\ -\x0f\x44\xe6\x40\x56\ +\x00\x97\xdb\x78\x9c\xed\x1d\x6b\x73\xdb\x36\xf2\xbb\x7f\x05\xc6\ +\x1f\x32\xb9\x19\xd7\xb2\x1c\x3f\xe2\x44\x56\x27\xef\x64\x26\x6d\ +\xd3\xc8\x49\xaf\xf7\xa5\x03\x91\x90\x84\x0b\x45\xa8\x00\x14\x5b\ +\x9d\xfb\xf1\xb7\x0b\x80\x12\x49\x51\x94\x25\x88\xa2\xdc\x2a\x93\ +\x19\x8b\x00\xb9\x58\x2c\xf6\x85\xdd\x25\xd8\xfa\xf1\x6e\x18\x91\ +\xef\x4c\x2a\x2e\xe2\xeb\xc3\xe6\xf1\xc9\x21\x61\x71\x20\x42\x1e\ +\xf7\xaf\x0f\xbf\xdc\xbc\xfd\xe1\xe9\xe1\x8f\xed\x83\xd6\x98\xcf\ +\x6e\x3a\x83\x9b\xda\x07\xa4\x15\x44\x54\xa9\xf6\xbb\x31\x7f\xf6\ +\xec\x35\xa7\x91\xe8\xc3\xdf\xa8\xdf\x61\x5a\xc3\xc3\xea\xb5\xa4\ +\x3d\xdd\x6a\xd8\x9b\xe0\xee\x5b\x1e\xf6\x99\x26\xe6\xfa\xfa\xf0\ +\xd7\xdf\xcc\xe5\x21\x89\xe9\x90\x5d\x1f\x96\x02\xc1\xc1\x48\x6b\ +\x24\xc5\x88\x49\x3d\x71\x4f\xf4\x99\x18\x32\x2d\x27\xa6\x93\xb4\ +\x24\x0b\xb4\xf9\x45\x5a\x77\xed\x93\x56\xe3\xce\x5d\x4c\xf0\x62\ +\xe2\x2e\x00\x05\x3d\x68\x9f\x5f\x41\x93\xfd\x69\x9b\x07\x8c\xf7\ +\x07\xba\x7d\x71\x7a\xd5\x6a\xb8\xdf\x06\x66\x23\x01\xda\x6a\x24\ +\x83\x17\x61\x72\xcb\xe3\x50\xdc\xde\x70\x1d\x31\x87\x8c\xd2\x12\ +\x90\x6f\xbf\x63\x31\x93\x34\x22\xca\x4d\xa6\xd5\x70\x1d\xf3\x20\ +\x23\x3a\x11\xe3\x19\x71\xbe\xbe\x14\x77\x1f\x4d\x93\x83\x98\x1b\ +\x52\x8d\x68\x00\x80\x0e\xdd\x04\xe2\xf1\xb0\xcb\x64\xfb\xa2\xd5\ +\x70\xbf\x2c\xfa\xe9\x11\xe6\x40\x0c\xa9\xec\xf3\x38\x07\xe1\xaa\ +\x14\x02\xd7\x6c\x38\xa3\x64\x7a\x31\xdf\x49\x31\x1e\x01\xce\xc9\ +\x72\xf6\x93\x6b\x7b\xfb\xdc\xe0\x7a\x46\xac\x02\x7a\x99\x45\x27\ +\x9d\x02\xaa\xcd\x23\x55\x4a\x3b\x37\x1a\x30\xae\xe6\x01\x8d\x6c\ +\xeb\x1f\xa7\xb3\x81\x67\x33\x2a\x00\xf4\x7e\x0e\xd0\x40\x48\xfe\ +\x97\x88\xf5\x14\x54\xf3\x6a\x0a\x2b\x0f\x6d\x9e\x48\x1f\x69\x97\ +\x45\x09\xa8\x08\x2f\xb2\xcf\x17\x90\x89\xdd\xe9\xcc\x0d\x53\x52\ +\x59\x12\xf1\x58\x33\xd9\xa3\x01\x23\x43\x11\xb2\x1c\xa1\x8a\xa9\ +\x65\x1b\x2d\x66\x29\xd4\x1b\x59\xdc\x97\x4c\xc5\x48\xeb\x27\xc9\ +\x7a\xaf\xc4\xb0\x2b\xd2\xeb\x8e\x1d\x23\xe8\x08\xb0\xa3\x2b\xee\ +\xfe\x38\x2b\x9f\xa0\x10\xd1\x0d\x1f\x15\xcf\xf1\x66\xc0\x15\x81\ +\xff\x7a\xc0\xc8\x97\x0f\x66\x8a\x30\x63\x72\x3b\xe0\xc1\xc0\x34\ +\x5a\x22\x40\xfb\x38\x62\xe4\x96\x47\x11\xb9\x15\xf2\xdb\x33\x72\ +\x03\x50\xbb\x54\xda\x27\x4c\xfb\x28\x42\x22\xd1\x28\xe1\xad\x44\ +\x22\x11\x1e\x85\xab\x11\x95\x54\x33\xa2\xed\x83\x47\x38\x06\x80\ +\xd4\x54\x7d\xcb\xc2\x19\x2b\x66\x46\x7e\x2b\x19\x7b\xf5\xe2\x35\ +\xb9\x81\x3b\xbe\x73\x76\x4b\xd4\x44\x01\xc5\x48\x4f\x48\x33\x0a\ +\xd7\x0a\xef\x95\x76\x85\x68\xa0\x41\x6f\xde\x7b\x79\xe6\xa8\x84\ +\x04\x7d\x13\xa3\xae\x23\x4a\x87\x80\xfb\xf5\xe1\x49\x8e\x64\x81\ +\x83\xfd\x85\xff\x64\x38\x21\xf0\x19\xeb\x13\xd5\x83\xe5\x43\xc1\ +\x40\x8d\x44\xc7\xdf\x7b\xb4\x1c\x5f\xdd\x87\xe5\x67\xfc\x60\x57\ +\xa7\x88\x8e\x8b\x86\x6b\xe4\xc7\xf3\x43\xc0\xad\xb6\x0f\x06\x4b\ +\x65\xaf\xd5\xb0\x6a\x68\xaa\xa3\x32\xdd\xde\x1a\xeb\xd4\x4f\x61\ +\x9d\xae\xab\xaf\x58\x8f\x8e\x23\x00\x2d\x22\x51\xb8\x82\x95\x2b\ +\x2a\x18\xf7\xe5\x58\x6b\x11\x17\xe8\x2a\xe8\xeb\xda\xbe\xb5\x95\ +\x15\x6a\x85\x30\x3d\x49\xa3\x0b\x62\x50\x0d\xa2\xfb\x5f\x70\x23\ +\xf2\x66\xac\x8c\x67\x72\xe3\x1a\x70\x79\x21\xc4\xb6\x1c\x97\x4a\ +\x16\xa2\xb3\x83\x7f\xb2\x1d\x7d\xd0\x56\x31\x76\xd9\x1f\xd9\xce\ +\x6e\x34\x66\xd8\x67\xfe\x66\x19\x7a\x6e\x90\x8d\xab\x2b\xc7\x0e\ +\xbb\xa9\xad\xbc\xb9\xaf\x48\x80\x96\xd8\xc3\x85\x02\xd4\x89\xe9\ +\x68\xd7\xa5\x67\x99\x76\x58\x5d\x7e\x14\xce\x5a\x4d\xc0\x97\x88\ +\xf6\x02\x94\x41\xdf\xd1\x02\x09\xf4\xcf\x13\xa2\x75\xbd\xe6\x57\ +\x22\x86\x5f\x63\xe3\x8e\xed\xbc\x30\x3d\xd9\x8c\xe7\x3c\x2f\x54\ +\xce\x20\x91\x2e\x83\x7b\x49\x28\xe9\x6d\xec\x1c\x5e\x8e\x54\x49\ +\x91\x08\x1d\xdf\xe3\xed\xc8\xdd\xd9\xd9\x62\xc1\x6b\x9e\x9e\x97\ +\x88\xde\xe9\xf9\x79\x6d\xd6\x6b\x46\xab\x7f\x9e\x10\x2e\xe1\xcf\ +\xa5\xae\x60\xc4\xc1\x3b\xc2\x28\x4c\x0d\x32\xd8\x19\xf1\xb8\x68\ +\xdb\xaa\xa0\xbd\x3b\x0b\x5b\x14\xcf\xec\xbe\x66\x6c\x3a\xc1\xcd\ +\xb9\x82\xdf\x29\xf0\x79\x6e\x64\x17\xb0\x39\xcd\x84\x6e\x56\x82\ +\xba\x02\xcb\xa7\x16\xed\x81\xb2\x7a\xc5\xfb\xab\x27\x9e\xfb\xab\ +\x13\x2f\xd3\x46\xb9\x51\xda\x3b\x19\x09\x3a\xf7\xb1\x67\x8c\x4c\ +\x27\x88\x46\x0b\xe6\xc8\x7b\x9c\x49\xf2\x8d\x4d\xb6\x12\x57\x81\ +\x01\x83\x04\x81\x5d\x65\x7d\xbf\xe0\x86\x1a\x70\x1c\xac\xae\xd8\ +\x4a\xa0\x65\x54\xdf\xe8\x34\xf2\x9a\xfa\x1a\x62\x84\x11\x7c\xe0\ +\xdf\xbc\x16\xe9\x98\xe6\x25\xb2\x02\x77\x33\xb8\x19\xdd\x8e\x1c\ +\xf7\x30\x30\x01\xed\x5f\xf5\xb3\x67\xef\xa7\x10\x5b\x0d\xd3\xb8\ +\x32\xab\x2a\xfe\x17\x7b\xcf\x63\xbd\x98\x55\xf1\x8e\x1c\x39\x6d\ +\x56\xe5\x2c\x9b\x5f\x99\xf6\xba\xdc\xca\xe9\x49\x26\xcd\x32\x43\ +\x2b\x0f\x70\x81\xca\xb2\xa4\xdb\xa8\x2f\x73\xda\xf4\xd9\x96\xef\ +\xaa\xc6\xbd\xf0\xd3\xb8\xca\xcd\x6d\x03\x9a\x36\x18\x4b\x09\x2c\ +\xfb\x21\x0e\xd9\x5d\xb1\xfb\xd2\xdc\x8a\xfb\x02\xb3\xc1\x59\xed\ +\x35\xb8\x6d\xdd\x6b\xf0\x59\xc3\x86\x35\x78\xb9\xec\xed\x35\xf8\ +\xc6\x35\xf8\xba\x99\x89\x17\x91\xde\x59\x05\x7e\xe9\xa7\xc0\xa9\ +\x9d\xda\x56\xf4\xf7\x76\xb6\x9f\x30\x1b\x23\xe8\x7b\xf5\xbd\x57\ +\xdf\xbb\x94\x55\x6d\xa6\xb9\x68\x9d\x3a\x10\xbf\x6d\xbf\x0b\xd7\ +\x9a\xaa\x1b\xf3\x48\x0d\xda\xec\x23\x8f\xd9\x9b\x90\xeb\x39\x6d\ +\x86\x21\x23\x06\x1d\x3e\xd9\xa1\xa2\x80\xf6\x6c\xb6\x26\xbe\x96\ +\x09\x5c\x27\xc5\x61\xeb\x6b\xbc\xfb\x91\x7c\x2b\xb1\x87\xf4\xcc\ +\xcc\xa4\xed\x0a\xef\xa6\x0e\xac\x5b\x12\xcf\xee\x2f\x88\x33\x43\ +\x3c\x60\xc1\xb7\x42\x43\x8c\x1d\x5e\xf1\x60\x03\x01\xd8\x16\xd9\ +\xb7\x47\x00\x43\x72\x4b\x63\x4d\xb4\x98\x96\x12\x99\xc4\x41\x23\ +\x15\x2b\x96\x62\x68\x3a\x5c\x31\x12\xa1\x2a\x61\xf9\x2a\xb8\xb9\ +\x43\xbf\x03\x0e\xd6\xbc\xbb\x1c\x11\x8d\xc3\x54\xec\x9a\x06\x52\ +\x28\x45\x14\x53\x58\xfc\xe9\x11\xbb\x5e\x25\xab\x09\x48\x89\x98\ +\xdd\xf1\x9d\x35\xf5\x75\xb3\xf9\x65\x15\x6c\xee\x13\xa2\xfd\xd0\ +\x73\x5c\xae\x88\x01\xc7\xc2\x23\x60\xa7\xd1\x24\x55\x3c\xd7\x65\ +\xe0\x84\x8e\x74\xc2\x51\xe0\xe5\x0e\x81\xd5\x8e\x88\x00\x6e\x97\ +\xb7\x5c\xb1\xa4\x49\xd9\xfb\x69\x74\x4b\x27\xc0\x79\x9a\x4a\x2c\ +\x75\x24\xb1\xf8\x61\x0a\xb1\x0a\x51\x78\x17\x89\x2e\x8d\xc8\x06\ +\xc6\x70\x14\xc8\x0d\xd3\x05\xfa\xb5\x41\x91\x03\x60\xf3\xb3\x5a\ +\x9b\x31\x9a\x0c\x77\xb8\x12\xb0\x6e\xf9\x69\x3e\xad\x44\x80\x3c\ +\x72\xf6\x3f\x0b\x39\xa4\x51\x34\x39\x22\x40\x48\x26\x0d\x1b\x62\ +\xaa\xc3\xe5\x0c\x8f\x9c\xb1\x18\x71\xa6\x08\x22\xa7\x58\x04\xed\ +\x2c\x3c\x26\x89\xe8\x89\x91\xf1\x7d\xd2\x12\x88\xcf\x74\x29\x48\ +\x56\x92\xf3\x4f\x04\x31\x79\x1a\xe4\x4a\x69\x46\x43\x8f\x2c\x7f\ +\x89\x6d\x31\x83\x64\x11\xc8\x4c\x6e\x3b\xc6\xc4\x60\xf1\x12\x90\ +\xf8\x25\x49\xbf\xee\x65\xa2\x48\x26\xce\x2b\x11\x89\xa7\x9b\xb5\ +\x29\xc6\x85\x4a\x5b\x07\x0c\x52\x83\x3b\x05\xce\x82\xd2\x29\x79\ +\x71\x15\x2d\x58\xdd\x02\xad\x46\x48\x62\xa1\x53\xcf\x77\x6d\x80\ +\x7b\x64\x9e\x89\xa3\x09\x3c\xc0\x62\x02\xa8\x83\x9f\x03\x4d\xaf\ +\x6e\x3e\x7f\xac\x44\x28\x5e\x64\xf1\x4e\xd0\x7d\x1c\x72\x45\xbb\ +\xd1\x2c\xea\x8e\x01\x9b\x7f\x3d\x64\x13\x64\x17\xa8\xb3\xc3\xe1\ +\xf6\x8d\x07\x7d\xcb\x77\xb8\xfb\xa0\xef\xa6\x83\xbe\x4d\xcf\x00\ +\xa9\xa4\x21\x1f\xab\x69\xa5\xa9\xd1\x05\x20\x93\x6a\xc4\x02\x0e\ +\x9e\xe0\x48\x00\x21\xd5\x31\xbe\x89\x84\xcd\x27\xb6\x8e\x47\x10\ +\x10\x55\x4d\xe3\x80\x91\xc7\x3c\xee\xf1\x18\xf0\xf6\x10\xd4\x25\ +\xb9\x45\x49\xe3\x7e\x1d\xe1\x9c\x25\x15\x52\x4b\x58\x5d\x8d\x7b\ +\x3d\x9e\x8f\x14\xbb\x39\x8c\xee\xb6\x63\xf6\x81\x7a\x9f\x2d\xf1\ +\x1e\xa8\xf6\xa9\xfa\x4d\x90\x15\x62\x96\x2b\xd8\x7b\x8f\x17\xbe\ +\x8a\xec\xfd\x54\x2e\x8d\xd1\x06\x13\x4e\x44\x10\x8c\x25\xa1\x7d\ +\x8a\xae\x6b\xca\xb1\xd5\x03\x30\x9b\x12\x83\x2a\x34\x36\x8e\x2f\ +\x8f\x43\x1e\x50\x74\x72\x6d\x66\x82\x88\x1e\x61\x30\x2b\x8f\x18\ +\xc6\xb2\x42\x00\x7a\xc7\x87\xe3\xe1\x43\xb6\xda\x30\x85\x7f\x92\ +\xc9\xde\x1b\xec\xc5\x94\xae\x22\x4b\xeb\xb1\x41\xfe\xc9\x0a\x57\ +\x5e\x98\xd1\x32\x77\x99\x09\xff\xf3\x90\x49\x90\xf6\xb4\x39\xaf\ +\x42\xd4\x17\x20\xb2\x83\x46\xba\xbc\x08\xc1\x69\xab\xe2\x7c\xee\ +\xd5\xd5\xd5\xfa\x19\xdd\xb2\x32\xe5\xb3\xed\x24\x8a\xad\x1a\x7b\ +\x63\x17\xe6\x81\xea\xb2\xaa\x1d\x80\x66\x25\x0e\x80\x87\x4f\x0e\ +\x0e\x40\x26\x74\xd5\xb1\x9b\x64\x9b\x07\x99\xee\xda\x07\xc2\xbc\ +\xb0\xc2\x62\xf6\x1d\xc4\x0f\x37\xf4\x98\x4b\xa9\x52\xe2\x3b\x30\ +\x64\x72\x2a\x41\x0a\xa5\x87\x6c\xe7\x91\x8a\x38\x97\x97\xf4\xe1\ +\xbe\xb5\x52\xb1\x7c\x54\x13\x22\xf6\x28\xca\x2c\xf2\x8f\x33\x81\ +\x5d\x90\x00\x66\x33\x86\x3d\xb8\x04\x53\x38\xcb\x1d\x1e\x93\x5f\ +\x92\x34\x8b\x91\xad\x49\xfe\x89\x5b\x0e\x58\xca\x55\x6a\x07\x56\ +\x10\xa0\xb7\x38\xd6\xf4\xbd\xb3\x89\x7f\x42\x73\x05\x4e\x47\x52\ +\xec\x53\x21\x8b\xd9\xdc\xf7\x08\x13\xdf\x23\x01\xf0\xcc\x0e\xdc\ +\xe0\x8d\x22\x1a\xef\xe6\x19\x26\xe5\x33\x5c\x81\x15\x1d\xdb\xff\ +\xf6\x69\x57\x79\xd1\xaf\x88\xeb\x67\x51\xbc\x80\xdb\x29\x21\xfb\ +\xf7\xef\xe4\xf1\x8d\x18\x15\x86\xe2\xb6\x84\xc1\x7f\xc8\xe3\xb7\ +\x12\x64\xab\x46\x1c\x7e\x07\x1c\x3a\xb0\x11\xf2\x42\xa1\x6e\x95\ +\xd4\xac\xa6\xbc\xc1\xa3\x00\x2d\xed\x99\x52\xd2\x97\x3c\xcc\xd8\ +\x4f\x93\x3b\x72\xb9\xa6\x2a\xec\xe7\x17\x70\x70\x71\xd0\x87\xec\ +\x71\x5a\xfc\x77\x53\xef\x6d\x3c\x13\x54\xbe\x09\xda\x07\x96\x36\ +\x9e\x09\x5a\x52\xba\xb4\xb8\xe8\x07\x45\xd9\x1d\xa7\x57\x83\xf3\ +\xf1\x5a\x8c\xbb\x11\x5b\x14\xc7\x09\x4d\x6f\x12\xcd\xf1\x3a\x10\ +\x82\x25\x93\x84\x2d\xb4\xbe\x65\xa0\xae\x18\x0d\x06\x56\x93\x61\ +\xb1\xdf\x66\xdf\x49\xb7\x88\xb7\x9b\xc7\x27\xd9\x7f\xad\x86\xeb\ +\xa9\x5a\xd1\x74\x92\x15\xfd\xdb\xe8\x9b\x7b\xc8\xc0\x92\xad\x65\ +\x49\x40\x93\xc7\x86\x09\x14\xc1\x90\xca\xfd\xab\xa6\xb7\x17\xc9\ +\xf4\xc8\x2a\xe1\xec\xec\xe4\x92\x08\x92\x3d\xf2\x04\xb6\xd2\x60\ +\x11\xe5\x31\xe9\x60\xba\xb7\x37\x21\xb0\x3d\x66\x04\x23\x3d\x43\ +\x1a\x4f\x88\xfa\x73\x4c\x25\x53\x53\x71\x19\x26\x60\x3c\xaa\x42\ +\x4a\xe2\xa2\xcd\x93\xad\xc4\x45\x51\x36\xde\xd8\x35\x7e\xa0\x92\ +\x51\xb5\xeb\xe9\x79\x80\xc3\x92\x72\xa7\x85\x32\xf8\x01\x0f\x8a\ +\x8c\xb1\xe8\x40\x02\x37\x62\xa9\x35\x89\x40\x18\x0b\x5f\xc9\xa9\ +\x59\x16\xcb\xed\x90\xcb\x2a\x74\xc0\x15\xb8\xaf\xbb\x71\x51\xee\ +\x6e\x34\x2f\x2e\x2f\x2f\x4f\x9b\xe7\x3e\x4e\xc7\xea\xe6\x72\x96\ +\xdd\x09\x61\x41\x86\x34\x32\x87\x85\xf2\x64\x99\x02\x21\x64\xc8\ +\x63\xaa\x19\x16\x5e\x32\x69\x9c\x39\x45\x1e\x63\xf2\x89\xdd\x1d\ +\x93\x27\xe4\x9a\x9c\x80\xf9\x6b\x7a\x94\x86\x94\xa8\x8b\x8b\xad\ +\x68\x8b\x29\x2f\x3e\x58\x6d\xb1\xaa\xdf\x5e\x6e\x67\xf6\x7e\xfb\ +\xc6\xfd\xf6\x75\xf5\xe5\x6b\x3e\x64\xb1\x79\x23\xe5\x01\x68\xcc\ +\xf2\xcd\x49\x69\x1e\xf6\x69\x35\x59\xd8\xad\xa8\x8f\x90\x0f\x3f\ +\x3d\x78\x0d\x52\xb5\xbf\xb1\x42\xd5\x75\x91\x00\x2d\xc9\xb6\x2e\ +\x94\x9f\x1b\x11\x81\xd1\x8a\x83\x4a\x23\xee\xe5\xba\xb6\x5c\xf4\ +\xf7\xba\xd6\x47\xd7\xae\x13\x60\xf8\x07\xb8\x75\xb3\xb7\x88\x8d\ +\x72\xc4\xc2\x81\x10\xf3\x91\xbd\x71\x1c\x58\x07\x4e\x0f\xa8\x36\ +\xf5\x04\x94\xe8\x44\x44\x8e\x0f\xbe\xe2\xdd\xae\xc8\x30\xe4\xbd\ +\x1e\xec\x14\xa1\x1d\x37\x87\x11\xec\x17\x4d\x52\xd6\x02\x4c\xb6\ +\x98\x5a\x32\x53\x79\x48\x15\x51\x80\x98\xc7\x9e\xb1\xa4\x94\xb6\ +\xb1\x0e\xc3\xc7\x7d\x60\x07\xcd\xf2\x24\x72\x71\x19\x70\x59\x9b\ +\x1b\x8a\xd8\x94\xc4\x85\x60\x94\xf3\xed\xc7\x85\xf4\x4c\xe5\xed\ +\x6d\x51\x91\x2d\xba\xf0\x33\x45\xeb\x86\x9f\x92\x44\x30\xde\x41\ +\xac\x2e\xa8\xcf\x28\x95\x1f\x2d\xbc\x37\x4a\xdb\x36\x4a\x4b\x92\ +\x76\x7f\x07\xb3\x94\xf0\xbf\x1d\xcf\x94\xaf\xa2\x28\x28\xf3\x22\ +\x7e\x38\xdd\xe7\x54\x12\xa1\x3f\x39\x3e\xad\x21\x42\x8f\xd3\x4b\ +\x04\x7d\xaf\x8a\x0b\xb7\x05\x9e\xdf\xe9\x58\x37\x1d\x96\xd1\xc5\ +\x3d\xc0\xa8\x3e\x4d\x5c\x1e\x66\xdc\x6b\xe2\x8d\x68\xe2\xa5\xa7\ +\xf6\xf8\xe4\x1c\xe7\xcf\xec\x41\x8e\x32\xcf\x4e\xbf\x94\x64\xab\ +\x6a\x8b\xf4\xdd\xf1\xc1\x07\xc0\x97\xc6\xe8\x4e\xd3\xd4\x93\x6a\ +\x1c\x0c\xd0\xaf\x7e\xf4\xe7\x58\xe8\xe7\x2f\x24\xa7\x91\xfd\x89\ +\x95\x19\xc9\x40\x4a\x4f\xa2\xfc\xad\x8a\xc6\x2a\xb9\xd3\xb5\x30\ +\xc9\x7b\xf6\xe7\x01\xe0\x63\x7f\x0d\x45\x2c\x92\xdb\x10\x49\xd2\ +\xa3\x43\x1e\x4d\x8a\xc6\x3d\x7a\xcf\xa2\xef\x0c\xbf\x2d\x76\x34\ +\x03\x6e\x1f\x32\xa8\x9a\xfd\x02\xb5\xc8\x1c\x14\x3c\xff\xec\xa5\ +\x88\x42\x7b\x5d\xc9\xab\xc6\x38\xc6\xfa\x80\x69\xc4\xfb\x31\xac\ +\xc6\x1c\x74\x10\x72\x94\xaf\x17\xd8\xff\x19\x79\xf8\x7f\xd3\xcb\ +\x1b\x49\x39\xb0\x4e\x7f\xd6\xf2\xf5\x15\xc3\x98\x39\xa0\xc1\xf4\ +\xea\x38\xac\x68\x54\xac\xc6\xda\x9b\x94\x42\x93\xb2\x42\xb9\x7f\ +\x61\xa8\x76\xdd\x33\x72\x67\x36\x65\x38\x8a\xf0\x33\x6b\x6a\xc0\ +\x58\x8d\x86\x65\xc9\x44\xf6\x96\x65\x23\x96\xe5\x2d\x8f\xd8\xab\ +\x81\x10\xa0\x63\xe7\x8c\x4b\x0f\xfa\x02\xdb\xb7\xcc\xbf\xe7\xf1\ +\xaa\xfe\xfd\x93\x93\x72\x02\x79\xd1\x67\xf5\x3c\x62\x98\xe7\x7e\ +\x77\xf6\x97\x29\x19\x0c\x30\x4c\x84\x45\x39\xd4\x7c\x1f\xc2\x55\ +\x10\xae\x28\x20\x7e\x4a\xd3\x62\xb5\x57\x9a\x0b\x94\xe6\x0a\xe7\ +\xc9\x15\x28\x4d\xff\xe4\xd6\x23\x3a\x1c\x3d\x27\x1f\x19\x0d\x41\ +\xa1\x51\x29\xc5\xad\x75\x27\x76\xb1\x50\x7e\x63\x65\xf2\x7c\x68\ +\xbf\xf9\xb5\xab\x5c\xe9\x57\xa2\xfd\x5a\x68\x72\x5e\x5f\x85\x38\ +\x0e\x7f\x59\xef\xf0\x57\xf5\x0d\xff\x8a\xcb\x00\x76\x06\x35\xd2\ +\xdf\x61\x50\xe3\x12\x38\x0c\x6a\x5c\x85\x0e\xa8\x96\x41\x9d\x8b\ +\x60\x11\xa8\x71\x0d\x2c\x02\x35\x2e\xc1\x4b\x1a\x7c\x53\x75\x2f\ +\xc3\x0c\x89\x1a\x97\x62\x86\x84\xd7\x72\xd4\xee\xaa\x78\xa6\x6f\ +\x9a\x4b\x6a\x6c\x17\x7a\x2b\x5f\x99\xfd\xbc\x7a\x2a\x76\x63\xe3\ +\x87\xa9\x9d\xd4\x2e\xba\x2b\x9b\xfa\xc2\x62\x6a\x9a\x58\x2e\x68\ +\xe2\x5d\x09\x25\x5c\x64\xcb\x38\xfb\x7a\x00\x1b\x9e\x34\x91\xa8\ +\x64\x24\xf9\x36\xfd\x31\x49\xb6\xc9\x00\x35\x62\x3d\x7d\xe4\x3e\ +\x74\xee\x06\xf9\xd0\xf9\x05\x4f\x42\x8d\x43\x2a\x7d\x0e\x6b\x5c\ +\xcd\x0b\xcb\x2c\xe0\xdf\xd1\x15\xfb\x08\x84\x26\x8f\xd3\xb4\xad\ +\xf1\xd5\xbd\xcf\x8b\x32\x9f\x0f\x44\x03\x79\xaa\x9f\x75\xbf\x27\ +\xf9\x22\x32\x25\xb9\xb0\xb3\xee\x7c\x7d\x47\x80\xd1\xf0\x12\x64\ +\x48\x04\x95\x6b\x9e\x25\x71\xa6\xf2\x43\xfd\xf7\x71\xa6\xad\xc6\ +\x99\x96\x54\xad\x3f\xe8\x38\xd3\x7b\x7c\x73\x05\x0f\x42\xc1\x74\ +\x89\x72\xaf\xb3\x50\x30\x35\x92\x05\x5a\xc8\x09\x9e\x8e\xa4\xdd\ +\xa7\x13\x51\x48\x90\x2e\x2a\xdd\xf8\x28\xd2\xcf\x47\x56\x72\x1e\ +\xf5\xf5\x73\x0c\x5a\xe1\xb9\x86\xb3\x8a\xa8\x24\x0f\x13\x86\x2c\ +\xc4\x08\x16\x9a\xa4\x44\x65\xba\x1c\x0e\xdc\x06\xe6\xca\x41\xd9\ +\xce\x39\xf1\x6e\x30\x64\x81\x5d\xb5\x4f\x7e\x3a\x39\xdb\x99\x81\ +\x35\xbb\x2f\x75\x53\xea\x0e\xa7\xbf\xa7\x09\x31\xfb\x42\xdc\xf5\ +\xe1\xc5\x21\x19\x52\xd9\xe7\xf1\xf5\x61\xb3\x79\x88\x25\x64\xad\ +\x11\xbf\x1b\xd2\x51\x52\x03\xd7\xfe\xf3\x93\xb9\x7e\x2b\xc5\xf0\ +\x27\x70\x56\x3a\x62\x2c\xb1\x66\x2a\x77\x17\x3c\x17\x8c\x95\x16\ +\x43\x3b\xa2\x32\x98\xa4\x5b\x2c\x96\x46\x5c\xdb\x46\x5a\x53\x92\ +\x0a\xf4\x33\xed\xe6\x16\xd0\xec\x2c\x0e\x55\xfb\xd7\xdf\xcc\x73\ +\xa0\xea\x5c\xc3\x81\x95\x26\x0c\x7d\x21\x84\x06\x02\x78\xcd\x69\ +\x24\xfa\xc7\x03\x14\x2e\xd3\x61\x08\x90\x1f\xb7\x1c\x91\xd4\x17\ +\xb8\x8b\x11\xf9\x34\x56\x83\xa4\x7f\x11\x32\x16\x59\xe5\x87\x49\ +\x4e\x81\x15\x62\x33\x4f\xbb\x45\x28\x21\xb4\x8d\xa1\xe5\xaa\x73\ +\x8a\x09\x34\xed\xdc\x0a\x2a\xcb\xd6\x6b\x7e\x51\xb7\x83\x96\x3b\ +\x70\xa0\x98\x44\xb3\xde\x2d\xd1\xc8\xee\x76\x16\x20\x33\xed\xdd\ +\x0a\x32\x49\x55\x41\x31\x32\xb3\xde\xad\x20\x93\x29\x36\x2b\xc6\ +\x28\x77\x8b\x3f\x5a\xd9\x06\x84\xd4\x92\x4c\x19\x45\xaa\x8c\xca\ +\x05\xdb\x1b\x33\x5b\x72\x6c\x67\x31\xbd\xb6\xa3\x2a\x40\x00\x60\ +\x17\x9c\x61\x81\x89\xf4\xd8\x8d\x8b\xde\x49\x3f\xa6\x51\x3b\x88\ +\xf0\x5d\xd6\xf0\x31\x1e\xe2\x80\x3b\x18\xdb\x6a\xee\x00\x17\x80\ +\xf1\xef\x69\x58\xb9\xb7\xca\x5b\x8d\xe9\x2d\x16\x64\x24\x74\x1b\ +\xcc\xe0\x9b\x18\xcf\x23\x9f\xc1\xc4\x66\x4b\x11\x3c\x15\xd9\x59\ +\x24\xfc\x4d\xf4\x64\x84\xae\xa6\x99\x5e\x26\xed\xd1\xba\x6b\x37\ +\x4f\x60\x80\xbb\xe4\x7a\xd2\x7e\x72\x09\xd7\x93\xc4\x9e\xe1\xe3\ +\xf3\x90\x42\x86\x47\xb9\x1b\xcf\x38\x0f\xee\xc9\xd9\x65\x0e\xdc\ +\x59\x11\x38\xfb\x53\xb9\xb5\xc9\xd0\x76\xab\xa4\x9e\xbe\xbe\x5c\ +\x2d\x91\x2f\xaf\x36\x49\xe3\xf3\xcb\xe6\xd6\x68\x7c\xb6\x39\x1a\ +\x5f\x54\x4b\xe3\xb3\x2c\x8d\x4f\x2f\xcf\xbd\x68\x7c\x7e\x92\x03\ +\x77\xb9\x83\x34\x4e\x0e\x6d\xad\x98\xb2\x67\x9b\xa4\xec\xd9\xc9\ +\x79\x16\xdc\xd3\x42\x61\xa8\x59\x43\x24\xa7\x96\x54\x4b\xd9\xf3\ +\xa7\x59\x41\xbe\xf0\xa2\x6c\xf3\x22\xa7\xca\x2f\xae\x76\x97\xb2\ +\x15\x6b\x83\x27\x79\x52\x14\x8a\xef\xbd\xad\xda\x55\x1e\xdc\xd3\ +\xd5\x28\x9b\xbe\x84\xfe\x56\x63\xcc\xdb\x07\xff\x07\x43\xae\x28\ +\x5c\ \x00\x00\x07\xb5\ \x00\ \x00\x1a\x6e\x78\x9c\xed\x58\x5d\x6f\xe3\xb8\x15\x7d\xcf\xaf\x50\ @@ -24441,6 +24445,150 @@ qt_resource_data = "\ \x4b\xa7\xa0\xf2\x0f\xed\x14\xf4\x17\x26\x82\x6f\x9d\xc2\x5c\xbf\ \x47\xa7\x68\x1f\xea\xdb\xa3\xf9\x69\xef\xe9\xc3\x7f\x00\xa5\x17\ \x49\xdb\ +\x00\x00\x08\xd6\ +\x00\ +\x00\x1d\x78\x78\x9c\xdd\x58\xdd\x8f\xdb\xb8\x11\x7f\xdf\xbf\x42\ +\xf5\xbe\x64\x51\x7d\xf0\x5b\xa4\xb3\xbb\xf7\xd0\xe0\x8a\x03\x0e\ +\xe8\xe1\x92\xa0\x8f\x81\x6c\xd1\x5e\x75\x65\xc9\x90\xe4\xb5\xbd\ +\x7f\x7d\x87\x94\x44\x49\xb6\x36\x4d\x9b\xeb\x3d\xc4\x41\xd6\xd2\ +\xcc\x6f\x38\xe4\x70\x38\xf3\xa3\xef\x7f\x3a\xed\x72\xef\x45\x57\ +\x75\x56\x16\x0f\x0b\x1c\xa2\x85\xa7\x8b\x75\x99\x66\xc5\xf6\x61\ +\xf1\xf9\xd3\xcf\x81\x5c\x78\x75\x93\x14\x69\x92\x97\x85\x7e\x58\ +\x14\xe5\xe2\xa7\xc7\x9b\xfb\xbf\x04\x81\xf7\xb7\x4a\x27\x8d\x4e\ +\xbd\x63\xd6\x3c\x79\xbf\x14\xcf\xf5\x3a\xd9\x6b\xef\xdd\x53\xd3\ +\xec\x97\x51\x74\x3c\x1e\xc3\xac\x13\x86\x65\xb5\x8d\xee\xbc\x20\ +\x78\xbc\xb9\xb9\xaf\x5f\xb6\x37\x9e\xe7\x81\xdf\xa2\x5e\xa6\xeb\ +\x87\x45\x67\xb0\x3f\x54\xb9\x05\xa6\xeb\x48\xe7\x7a\xa7\x8b\xa6\ +\x8e\x70\x88\xa3\xc5\x00\x5f\x0f\xf0\xb5\xf1\x9e\xbd\xe8\x75\xb9\ +\xdb\x95\x45\x6d\x2d\x8b\xfa\x76\x04\xae\xd2\x8d\x43\x9b\xd9\x1c\ +\xa9\x05\x61\xa5\x54\x84\x48\x44\x48\x00\x88\xa0\x3e\x17\x4d\x72\ +\x0a\xa6\xa6\x30\xc7\x39\x53\x82\x10\x8a\x40\x37\x20\xbf\x0d\xb5\ +\x3c\xe5\x10\x8a\x37\x27\x63\xb5\x63\xef\x10\xfe\x3d\xfc\x77\x06\ +\xbd\x20\xac\xcb\x43\xb5\xd6\x1b\xb0\xd4\x61\xa1\x9b\xe8\xc3\xa7\ +\x0f\x4e\x19\xa0\x30\x6d\xd2\xd1\x30\x7d\xf4\x27\x7e\x27\x5b\x52\ +\x24\x3b\x5d\xef\x93\xb5\xae\xa3\x5e\x6e\xed\x8f\x59\xda\x3c\x3d\ +\x2c\x04\xdb\x9f\xec\xfb\x93\xce\xb6\x4f\xcd\x48\x90\xa5\x0f\x0b\ +\x58\x21\x89\x89\xb0\xef\xfd\x1c\x96\x2e\x93\x50\x48\x49\x0b\xed\ +\x06\x1e\xab\x98\x0c\xb1\x57\xa9\x58\xa0\xa9\x75\x5a\xae\xcd\x94\ +\x1e\x16\x1f\x8b\x64\xff\xe5\xb7\xa4\x4a\xf2\x5c\xe7\x61\x1f\x4b\ +\x37\x54\x79\x68\xf6\x87\xe6\x8b\x3e\x35\xba\x68\xc7\x84\xd5\x8c\ +\x96\x66\xd5\xc6\x2c\x9c\x2c\x6b\x94\xe6\x78\xf1\x08\x92\xfb\x54\ +\x6f\x6a\xa3\x69\x57\x64\xde\x60\x49\xd2\xea\x40\x0b\xdb\xa2\x93\ +\xea\xef\x55\x92\x66\x90\x8c\x2d\x6e\x34\x8b\x75\x09\xb3\x5b\x43\ +\x58\x92\xfc\x98\x9c\xeb\x85\x03\xc0\x50\x53\x53\x8a\x19\xeb\x06\ +\x85\x61\xeb\xa6\xdc\xf7\x58\x58\x7c\x73\xce\x61\xc5\x46\x18\xc0\ +\x88\x65\xb5\xbc\xdd\xd8\xcf\x7b\x2b\x2a\x61\x7b\xb2\xe6\xbc\xc4\ +\xef\x17\x83\x4d\xb9\xd9\xd4\x1a\x1c\xa3\x91\xcc\x6e\x09\x58\x80\ +\x2f\xb1\xf0\xa2\xef\xf3\x86\xe6\xbc\xe1\x79\x6f\xd2\x79\xbb\x8f\ +\xa6\xcb\xee\xa4\x2e\x60\x7b\x88\xff\x1e\x22\x06\xa7\xb6\x1f\xc9\ +\x6d\x7d\x73\x36\x89\x3a\x85\xd2\x74\x71\x15\xf4\x97\xfd\x97\x13\ +\x2c\xdc\x5b\x7a\x94\xc0\x1f\x3c\x8b\x38\xb7\x08\x0c\x07\x11\xbe\ +\xd0\x2c\xe6\xd5\xa4\xf3\x57\x86\xe9\x66\x10\x94\x55\xb6\xcd\x20\ +\x67\x2c\x8e\xe0\x90\xda\xcf\xd4\x06\x82\x31\x5a\x1b\x89\x29\x1b\ +\x62\x62\x62\x91\xe4\xff\x75\x12\xd9\x9a\xb0\x7c\xaa\x34\xd4\xb0\ +\xdb\x99\x6c\x1a\xfb\x9e\xba\xa0\x92\x0f\x2b\xde\x76\xc2\xcf\x45\ +\xd6\x40\xb1\x3a\xd4\xba\xfa\x68\x0e\xfc\x3f\x8a\xcf\xb5\xbe\x42\ +\x7d\xaa\x92\xa2\x86\xea\xb2\x7b\x58\xec\x92\xa6\xca\x4e\xef\xb0\ +\x8f\xcc\xbf\x50\x28\xc9\x89\x62\xf0\x4c\x10\x09\x25\x91\x82\xde\ +\x39\xf3\x35\xec\x08\x21\x3c\x24\x82\x21\x32\x48\x61\x17\x44\x4c\ +\xc2\x58\xc5\x54\x38\xe9\x66\x16\xbb\x99\xc5\x56\x10\x75\x16\x52\ +\xc6\xb1\x94\xff\xef\x80\x06\xf1\x7f\x08\x69\x40\x7e\xe4\xa0\xfe\ +\xa1\xa5\x0e\x62\xf9\x27\x16\xbb\x80\xfd\xb9\xe5\x6e\xe4\xef\x8d\ +\x82\x37\x9f\xa1\x93\xc0\x7f\x7d\x8f\xe6\xf7\x73\x7e\xef\xe7\xf3\ +\xe4\x3b\x93\xef\xdb\x32\xfc\xfa\xa0\x30\x46\xe3\xff\xe5\xc4\xbd\ +\x95\x67\x6d\xa0\xef\x23\xd3\x99\xed\x93\xeb\x17\x86\x27\xa4\x2f\ +\x99\x3e\x0e\xed\x7b\x95\xb8\xb9\xed\x93\xad\xb6\xfb\x0d\x9e\xdb\ +\x0d\xef\x14\xab\xb2\x4a\x75\xd5\xab\x84\xfd\x4c\x54\x5d\x4a\xb4\ +\x54\xf8\x66\x3a\x3b\x33\xaa\xd3\xa3\x79\x7d\xfd\x94\xa4\xe5\x11\ +\xb6\xe4\x52\xf9\x5a\x96\xb0\x09\x34\x94\x52\x21\x19\xd3\x4b\xb5\ +\xdd\x46\xa0\x45\x38\xc6\x44\x5c\x29\xc1\x1f\xa7\xa1\x10\x3c\x8e\ +\xaf\x95\x87\xaa\x82\x90\x06\x79\x72\xd6\xb0\xa8\x2d\x23\x52\x75\ +\x98\xfa\xa9\x3c\x6e\x2b\x13\x9b\xa6\x3a\xe8\x4b\x43\x60\x5b\x07\ +\xc3\xb2\x83\x43\xbb\xcb\x1d\xb7\x1b\x21\x8c\x6d\xb0\x5a\x95\xa7\ +\xf9\x01\x8e\x59\x01\x6b\x0d\x3a\xb6\x88\x89\xbc\x8a\x48\x87\xe8\ +\xf9\x63\xcc\xf9\x1b\x88\xd3\x70\xbe\x2f\x55\x67\x93\xdf\x6f\xe8\ +\x76\xc9\x29\xdb\x65\xaf\x3a\x35\xc7\xb5\x4b\x96\x9d\x6e\x92\x34\ +\x69\x92\x21\x31\x7a\x09\x34\x66\xdc\x73\x3b\xa0\xfe\xcb\xdf\x3f\ +\xfc\xec\xea\xc6\x7a\xbd\xfc\x67\x59\x3d\x0f\x47\xde\x00\x92\x15\ +\x50\xc9\x87\x85\xab\x66\x86\x31\xae\x97\xe6\x38\x25\xcd\x63\xb6\ +\x83\xed\x36\x3c\xff\xaf\x40\xb7\x21\x45\x9d\x62\x02\x36\xbc\x66\ +\x18\xb4\x1d\xb6\xd2\x2d\x8f\x9f\xbd\xfa\xa4\xeb\x5d\x66\x8c\xa2\ +\x8f\x4d\x96\xe7\xbf\x18\x27\xa3\xfa\xd6\x0d\x9a\x35\xb9\x7e\xb4\ +\x3e\xdb\xc7\x7e\x15\x51\xb7\x8c\xbe\x3c\x8d\x56\x79\x1f\xf5\x61\ +\xb0\x6f\xdb\x21\x3c\x36\x71\xf0\x65\x84\xf3\x64\xa5\xf3\x87\xc5\ +\xaf\x46\xe9\x5d\x69\xb7\x55\x79\xd8\xef\xca\x54\x77\xe6\x7d\x58\ +\xb7\xe3\xda\x30\x4e\x45\xcf\x6b\xae\x4a\x11\x0a\xb1\x20\x90\x36\ +\xa4\x2b\x49\xfd\x9b\x08\xa9\x40\x5c\x49\xe1\x07\x42\x84\x18\x49\ +\x89\xc4\xdd\xd0\x52\xf6\x49\xf3\x74\x55\xe2\x5d\x29\x0f\x39\xe1\ +\xef\x37\x10\xba\xe5\x2d\xb2\x1f\xfb\x32\x6a\x2d\xf6\xb5\x3a\xe4\ +\x7a\x59\x94\xc5\x2b\x9c\x78\xe8\x05\x55\xf9\xac\x1d\xbe\x7d\x6d\ +\xd3\x7a\xc9\xa1\xdc\x9a\x4f\x8c\x7b\xb9\xa9\x64\x10\x83\xe5\xea\ +\xd0\x34\x63\xd9\xbf\xca\xac\x58\xc2\xde\xe9\xaa\x97\xda\x97\x1c\ +\x12\xb4\x59\xb2\x5e\x36\xcc\xa3\x13\xa4\x09\x94\x8c\xaa\x4a\xce\ +\x66\x3a\x7a\x2c\x6d\x1b\x11\x34\xa7\x5d\x52\x3d\xeb\xaa\xd5\xbf\ +\x64\x75\xb6\xca\x72\x33\x84\x7d\xcc\xf5\xfb\x34\xab\xf7\xb0\x09\ +\x70\xdf\x33\xd3\x78\x5f\xc2\x35\x67\x93\x97\x47\xa7\xd7\x45\x02\ +\x5f\xc1\x2a\x59\x3f\x9b\x6d\x2b\xd2\x65\xb2\x86\x93\x7f\xc8\xe1\ +\xf6\x3e\xea\x71\xe6\xa0\x78\x58\xc8\x90\x51\xae\x84\xcf\x38\x0f\ +\x85\x54\x92\x7a\x6b\x2f\x50\x38\x14\x14\x53\x26\x7d\xe4\x05\x58\ +\x40\x50\x04\x95\x31\x74\x8f\x98\x85\xd0\xcf\x10\x99\x4a\xb1\xd9\ +\x36\xa6\xa8\xf4\x90\xdf\x99\x72\x0f\xa0\x98\x12\x0e\xa5\xdf\xef\ +\xb1\xd2\x9b\x5a\xf5\xd2\xde\x06\xbc\x19\xa1\xe2\x42\x50\x3f\xe8\ +\x07\x18\xcb\x06\x1b\xe4\xf7\xb3\x14\x9e\x81\x02\x92\x48\x03\xe8\ +\xa7\x12\x4c\xcc\x7a\xe9\xab\xb7\x03\x53\x2a\xc3\x98\x11\x26\x61\ +\xad\x31\x32\xad\x94\x9a\x95\x62\x12\x87\x0c\x41\x10\x7c\x1e\x03\ +\x9c\x70\x3c\x12\x75\x4f\x0a\xac\x3b\x13\xe5\x05\x3d\xce\x6a\x11\ +\xc1\x46\x36\x35\xe9\x84\xbd\x49\x6c\x03\x0a\x72\x82\x19\x04\x26\ +\xe0\x22\x8c\x79\x3c\x11\x0d\x56\xb0\x44\xe7\x0a\x80\x8a\xa9\x98\ +\x51\x3f\x70\x33\xb9\x30\xb2\x32\xb3\x3e\xb8\xee\x72\xc1\x94\x1f\ +\x83\x4c\x32\x65\x56\x19\xd0\x90\x98\x7b\x8a\x1f\x40\x1f\xc3\x0a\ +\x3c\x8a\x90\x33\x8c\x20\xe4\x21\xc5\x18\x42\xa8\x42\x49\x11\x86\ +\x30\x84\x4a\xd0\x98\x7b\x01\x81\x63\x89\x29\x62\x3e\x70\x0d\xe8\ +\x52\x00\x61\x34\xa4\x12\xfc\xf9\x14\x41\xf8\x10\x87\x18\x43\x20\ +\xb1\x80\x48\x9a\x88\x21\x4e\x05\xf6\x3a\xb4\xdf\x9b\x7b\x3d\xd8\ +\xef\xcd\xbd\x1e\xeb\xf7\xd6\x9e\xf3\x15\xf4\xce\x9c\xaf\xc0\x39\ +\x73\xbe\x02\xe7\x2c\x80\x74\x14\x1c\x11\x3f\x20\x14\x82\x46\x15\ +\x88\x08\x83\xac\x20\x08\x02\x05\x06\x4a\xc2\x59\x06\x18\x04\x8a\ +\x50\x13\x3c\xaa\x42\x88\x15\xc8\x5e\x2f\xe8\x9e\xa9\x32\x14\x2a\ +\x52\xc0\xc7\x8a\x81\xa8\x14\x50\x05\x9a\xb2\x0a\xa0\xfd\xbe\x24\ +\xcd\xa1\xd2\xa6\x83\x8d\x88\xe8\x76\xc6\x4a\x9f\xf6\x65\xd5\x04\ +\xe7\x74\x9f\x41\x33\x0c\x51\x4c\xb0\xe2\x78\x6e\xfc\x0e\x79\xfa\ +\x66\x24\x54\x35\xdd\xfe\x76\x12\x3d\x95\x3b\x1d\x9d\xe1\xde\xfa\ +\x1c\x7d\xe8\x5a\x7c\x1d\xfd\x9a\xac\xa2\x0f\x55\xb2\x69\xa2\x0c\ +\xe6\x5e\x5b\xe2\x1a\xee\x8b\xed\x68\xc8\xeb\x02\x0d\xc9\xa1\x24\ +\x52\x88\xdb\xbc\xc0\x8a\x31\x19\x63\x9b\x33\xe3\x67\x07\x61\xb1\ +\x34\x27\x14\xc2\x8f\x21\xde\x21\x63\x48\xdd\x5d\x44\x75\x0b\x21\ +\x45\xe3\x7e\x3a\x2d\xe6\x57\x3f\x08\x24\xd5\x7a\x31\x51\xb7\xd5\ +\xbe\xaf\xef\x2b\xa0\xad\xdf\x5b\xdf\xa5\x95\x62\xf5\xa3\xd7\xf7\ +\x69\x5a\x2f\x66\x83\x6e\x58\x28\x54\x03\x53\xc4\x24\x7f\x03\x62\ +\x6e\x21\xdc\x1c\x4b\x45\xe7\x11\x15\x0c\xc2\x64\xc8\x21\x3d\xde\ +\x42\x9c\xdf\x40\xd8\x1e\x44\x18\xd4\x74\x33\x03\xbf\xf7\x03\x05\ +\x0b\x99\x02\x22\xa1\xa6\x43\xdd\x21\x18\x2a\x80\xc0\xb1\xdf\x8f\ +\x01\x07\xba\x7b\x1a\x89\x7a\xbc\xa9\xb0\x4e\xed\x6c\xc7\x32\x67\ +\x03\x05\xd6\x79\x71\x4e\x06\xf5\x8c\xc5\xc8\x89\xd3\x3a\x17\xd7\ +\x93\x7a\x9d\x52\xb9\xef\x48\x7e\x60\x8c\xef\x6e\xaf\x7f\xa5\xb8\ +\xbb\x3c\x0d\x5d\xee\x9b\xdc\x7a\x2b\x17\xd8\xdb\xb9\x70\x7d\xb1\ +\xbc\xce\x85\xab\x1b\xe9\x55\x32\x5c\x5f\x7b\xaf\xb2\x01\xca\xb5\ +\x52\x18\x93\xb9\x74\xe0\x2a\x14\x48\x11\xec\x3b\x57\x36\x1f\x30\ +\xb4\x30\xa6\x20\x39\x02\xcc\x43\x1a\x0b\xa0\x8b\xdd\x28\x20\xea\ +\x5c\xaa\x91\x08\x43\xf5\x17\x92\x12\x93\x0f\x4e\x1d\x60\xd3\x4d\ +\x30\x19\x8b\x9c\x09\xa4\x83\x73\xd2\xf9\x88\x9d\x9a\x78\x57\x16\ +\xc4\xeb\x7c\x50\xf0\xe1\xb4\xad\x07\xac\xbc\xcb\x39\x91\x49\xcf\ +\x99\x27\xc8\x92\x43\x1b\x24\xd4\x94\x59\x4e\x98\x88\x39\x5c\xd8\ +\x47\x4f\x4e\x4d\xa1\xb7\x09\x25\x14\x81\xec\x03\x9a\xa4\x28\x91\ +\x77\xe3\x6e\x14\x6d\xbf\x4e\x9f\xbb\x1f\x47\x46\x8c\xd9\xfd\x52\ +\xf2\x47\x94\x57\x28\x38\x3f\x7a\x79\x6d\xe9\x33\xd0\x32\x0e\xa4\ +\xd9\x90\x1b\xd8\x6d\x24\xf9\x88\x3d\x9b\x1d\x6b\x59\x28\x64\x88\ +\x14\xc2\xb2\x67\x0a\xcf\x7c\x2a\x35\xe4\x14\x61\x16\x0f\xe4\x59\ +\x18\xf2\x0c\x7d\x95\x63\xd2\xd2\x64\x03\x8d\xbd\xa9\x51\x2f\x9d\ +\x90\xe7\x76\x24\xcb\x9d\xad\xfd\x48\x34\x58\x0c\xd4\x99\xb7\xd4\ +\xd9\xcc\xa9\x25\xc9\x76\x1e\xc1\xd8\xa8\x93\x0d\xbc\x19\xc1\x55\ +\x6d\xe0\xcd\xaa\xe3\xcd\x40\xf3\x31\xb6\x2c\x10\x58\x2a\x19\x89\ +\xdc\x93\x23\xce\xcc\xf2\x66\x8b\xb3\x5a\x4c\x29\xe9\x28\xf0\x60\ +\xd2\x09\x3b\x8b\x9e\x35\x5b\xa9\x65\xcd\x52\x48\x19\x4f\x84\x83\ +\xd5\x05\x6f\xb6\x50\x7f\x18\xdf\xbb\x30\x6a\x85\x73\x7c\x90\xd1\ +\x49\xb1\xfc\x56\x36\xd8\x9d\x3e\xfb\x75\x6f\x7e\x31\x78\xbc\xf9\ +\x37\x48\xea\xec\x50\ \x00\x00\x08\x8b\ \x00\ \x00\x1c\x9e\x78\x9c\xed\x58\xdf\x8f\x9b\x48\x12\x7e\xcf\x5f\xe1\ @@ -26893,6 +27041,140 @@ qt_resource_data = "\ \x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\ \x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\ \x73\x76\x67\x3e\x0a\ +\x00\x00\x08\x37\ +\x00\ +\x00\x1c\x3d\x78\x9c\xed\x58\x5b\x6f\xdb\xc8\x15\x7e\xf7\xaf\x60\ +\xe9\x97\x18\x15\x87\x73\xe3\x70\xa8\x58\xde\x87\xa6\x5b\x2c\xb0\ +\x40\x81\x4d\x82\x7d\x0c\x28\x72\x24\xb3\xa6\x48\x81\xa4\x2c\xc9\ +\xbf\xbe\xdf\xf0\x26\xca\x92\xd3\xa0\xdd\xa6\x40\x50\x05\xb1\xc8\ +\x73\x99\x73\x99\x6f\xce\x39\xa3\xfb\x9f\x0e\x9b\xdc\x79\x36\x55\ +\x9d\x95\xc5\xc2\x65\x84\xba\x8e\x29\x92\x32\xcd\x8a\xf5\xc2\xfd\ +\xfc\xe9\x67\x4f\xbb\x4e\xdd\xc4\x45\x1a\xe7\x65\x61\x16\x6e\x51\ +\xba\x3f\x3d\xdc\xdc\xff\xc9\xf3\x9c\xbf\x54\x26\x6e\x4c\xea\xec\ +\xb3\xe6\xd1\xf9\xa5\x78\xaa\x93\x78\x6b\x9c\x77\x8f\x4d\xb3\x9d\ +\xfb\xfe\x7e\xbf\x27\x59\x4f\x24\x65\xb5\xf6\xef\x1c\xcf\x7b\xb8\ +\xb9\xb9\xaf\x9f\xd7\x37\x8e\xe3\xc0\x6e\x51\xcf\xd3\x64\xe1\xf6\ +\x0a\xdb\x5d\x95\xb7\x82\x69\xe2\x9b\xdc\x6c\x4c\xd1\xd4\x3e\x23\ +\xcc\x77\x4f\xe2\xc9\x49\x3c\xb1\xd6\xb3\x67\x93\x94\x9b\x4d\x59\ +\xd4\xad\x66\x51\xdf\x4e\x84\xab\x74\x35\x4a\x5b\x6f\xf6\xa2\x15\ +\x62\x51\x14\xf9\x94\xfb\x9c\x7b\x90\xf0\xea\x63\xd1\xc4\x07\xef\ +\x5c\x15\x3e\x5e\x53\xe5\x94\x52\x1f\xbc\x93\xe4\xb7\x49\xcd\x0f\ +\x39\x52\xf1\xa6\x33\x2d\x77\x6a\x1d\xe9\xdf\xe2\xff\xa8\x30\x10\ +\x48\x5d\xee\xaa\xc4\xac\xa0\x69\x48\x61\x1a\xff\xc3\xa7\x0f\x23\ +\xd3\xa3\x24\x6d\xd2\xc9\x32\x43\xf6\xcf\xec\x9e\x6d\x49\x11\x6f\ +\x4c\xbd\x8d\x13\x53\xfb\x03\xbd\xd5\xdf\x67\x69\xf3\xb8\x70\x95\ +\xdc\x1e\xda\xf7\x47\x93\xad\x1f\x9b\x09\x21\x4b\x17\x2e\x22\xe4\ +\x21\x57\xed\xfb\xe0\xc3\x7c\x44\x12\x25\x82\x77\xa2\xfd\xc2\x53\ +\x96\xd4\x84\x39\x55\x14\x2a\x7a\xae\x9d\x96\x89\x75\x69\xe1\x7e\ +\x2c\xe2\xed\x97\xbf\x16\xe9\xb6\xcc\x8a\x86\x0c\xb9\x1c\x97\x2a\ +\x77\xcd\x76\xd7\x7c\x31\x87\xc6\x14\xdd\x9a\x88\x66\x12\x5a\xcb\ +\xb6\x6a\xe4\x2c\xac\x09\xcc\x99\xfb\x00\xca\x7d\x6a\x56\xb5\xe5\ +\x74\x11\xd9\x37\x84\xa4\x5b\x1e\xb8\x55\x9c\x66\x71\xfe\x37\xfb\ +\x05\x30\x76\x72\x13\x2f\x92\x32\xcf\x4d\x82\xb4\xc4\xf9\x3e\x3e\ +\xd6\xee\x20\xd0\x6e\xe7\xfc\xb1\x32\x80\xdf\x2d\x9e\x4d\x5c\x0d\ +\x6b\x08\x26\xe5\x28\x67\x4d\x9e\x9b\x90\x3c\x3c\xb1\xd7\x3d\xf1\ +\x73\x91\x35\xc0\xd9\xae\x36\xd5\x47\xbb\x57\x7f\x2f\x3e\xd7\xe6\ +\x42\xea\x53\x15\x17\x35\x80\xb1\x59\xb8\x9b\xb8\xa9\xb2\xc3\x3b\ +\x36\xa3\xf6\x1f\x51\x91\x0e\x78\x24\xf1\xcc\x29\x27\x9a\x6b\x25\ +\xee\x46\xf5\xe4\xb0\x70\x39\x0f\x08\x57\x92\xf2\x13\xf5\x88\xbd\ +\x0e\x39\x09\xa3\x50\xa8\x91\xba\xba\x2a\xbb\xba\x2a\x5b\x2d\x5c\ +\x21\x89\x90\x01\xd3\x28\x20\x7e\x9f\xd0\xf3\x64\x7c\x73\x42\x6d\ +\xa2\xae\xe4\xf1\xa1\xe7\xdf\xd7\x4d\xb9\x1d\x64\x81\xa6\xe6\x98\ +\x03\x42\x96\xe8\x61\xc5\xb2\x9a\xdf\xae\xda\xcf\xfb\x96\x54\x22\ +\x87\x59\x73\x9c\xb3\xf7\xee\x49\xa7\x5c\xad\x6a\x03\xc3\x74\x42\ +\x6b\x31\x0e\x0d\xd8\x52\x63\x08\xff\xae\x35\x7a\xcd\x1a\xbb\x6e\ +\x6d\x92\x30\xff\x3c\xec\xff\x21\x2e\xf9\x8f\x8c\xcb\x31\x75\x5b\ +\x54\x88\x2d\x72\x87\xbe\x32\x68\x8c\xc5\xa9\x39\xda\x52\x7a\x2e\ +\x2a\x52\xf7\x22\xfd\xcf\xdb\x2f\x70\x88\x3a\x73\x47\x70\xfc\x61\ +\x57\x25\x8e\x9d\x04\x43\xab\xc0\x17\xbd\x2a\xf3\x62\x0b\xee\x57\ +\x96\xe9\x3d\xf0\xca\x2a\x5b\x67\xa8\x6a\xad\x1c\x67\x44\xb4\x9f\ +\x73\x1d\x6c\xe9\x24\x36\x1e\x0a\x79\x8a\xfe\xbb\xc3\x49\xe8\x80\ +\xfe\xc8\x70\xfa\xef\x24\xd4\x0b\xff\x45\x4a\xbd\xe8\x47\x4e\xea\ +\x1f\xda\x3b\x90\xcb\xef\xd8\x3d\x3c\xfa\x7d\xfb\x87\x27\xbe\xda\ +\x41\xee\x7d\x3b\xe8\xb4\x4f\x63\x71\xb3\x63\x57\xfa\x9c\x99\xfd\ +\x69\x1a\x5a\xc6\x23\x54\xb6\xf1\xda\xb4\xce\x01\x98\x9d\x77\x3d\ +\x63\x59\x56\xa9\xa9\x06\x96\x6a\x3f\x67\xac\xde\xff\xee\x66\x71\ +\x73\xbe\x65\x76\xd5\x91\x4f\xaf\xf3\xeb\xc7\x38\x2d\xf7\xc0\xce\ +\x6b\xe6\x4b\x59\x02\xae\x82\x68\x1d\x51\x1d\x8a\xd7\x6c\x8b\x4d\ +\xcf\xe2\x8d\x29\xca\xe5\x05\x17\x06\xc1\xd4\x54\xe9\xf0\x92\xb9\ +\xab\x2a\x64\xca\xcb\xe3\xa3\x41\x54\x6b\xc9\xf5\x70\xb0\xea\xc7\ +\x72\xbf\xae\x6c\x72\x9a\x6a\x67\x5e\x2b\x62\x7a\xdd\xd9\x5b\x8b\ +\xb7\xeb\x4e\x5d\x3f\x2b\x4f\x24\xac\xae\xb7\x5c\x96\x87\xeb\x0b\ +\xec\xb3\x02\xc1\x7a\xfd\xf4\xcd\xb8\xbe\x48\x49\x2f\x31\xcc\xe3\ +\x61\x10\xbc\x21\x71\x38\xa1\xf1\x35\xcb\xc6\x7e\x91\xce\x9e\xb7\ +\x89\x0f\xd9\x26\x7b\x31\xa9\x05\x57\x87\xa1\xfb\x8d\x69\xe2\x34\ +\x6e\xe2\x13\x32\x06\x0a\xda\x08\x1b\x67\xe5\x74\x35\xff\xed\xc3\ +\xcf\x23\xca\x93\x64\xfe\x7b\x59\x3d\x9d\x00\x6a\x05\xe2\x25\x46\ +\xf3\x85\x3b\x9e\x3d\x3b\x81\x27\x73\x5b\x79\xe2\xe6\x21\xdb\x60\ +\xbf\xed\xbd\xe9\xcf\xb8\xbe\x00\xa3\x23\xe3\x4c\xd8\x76\xe1\xd3\ +\xa2\xdd\xb2\x95\xe9\xee\x45\x57\xaf\x92\x69\xb2\xc9\xac\x92\xff\ +\xb1\xc9\xf2\xfc\x17\x6b\x64\x72\x1a\xfb\x45\xb3\x26\x37\x0f\xad\ +\xcd\xee\x71\x88\xc2\xef\xc3\x18\x0e\xd3\x24\xca\x7b\x7f\x48\x43\ +\xfb\xb6\x3e\xa5\xa7\x05\x0e\x7b\x9d\xe1\x3c\x5e\x9a\x7c\xe1\xfe\ +\x6a\x99\xce\x05\x77\x5d\x95\xbb\xed\xa6\x4c\x4d\xaf\x3e\xa4\x75\ +\x3d\xad\x63\x53\x28\x3a\x4e\x73\x51\xb5\x29\x61\x8a\x03\x36\xbc\ +\xaf\xde\xc3\x9b\x22\x42\xd1\x20\xd2\x6a\xe6\x29\x45\x18\xd5\x00\ +\xfe\xdd\xa9\x00\x6e\xe3\xe6\xf1\xa2\x20\x8d\x85\x87\x04\xba\x1b\ +\x28\xde\xaf\x90\xbf\xf9\x2d\x6d\x3f\xed\xcb\xa4\x1a\xb6\xaf\xd5\ +\x2e\x37\xf3\xa2\x2c\x5e\x70\xee\x51\xbe\xaa\xf2\xc9\x8c\xf2\xdd\ +\x6b\x87\xed\xb9\x3d\x7a\xf8\xc0\xbf\x81\x6e\xab\x14\x12\x31\x5f\ +\xee\x9a\x66\x4a\xfb\x07\x2e\x80\x73\x6c\xa0\xa9\x06\x6a\xfb\x92\ +\x03\xa5\xcd\x5c\x0e\xb4\x93\x1f\x3d\x21\x8d\x51\x38\xaa\x2a\x3e\ +\x5a\x77\xcc\x94\xda\xd5\x4e\xd4\xd3\x4d\x5c\x3d\x99\xaa\xe3\x3f\ +\x67\x75\xb6\xcc\x72\xbb\x44\xfb\x98\x9b\xf7\x69\x56\x6f\xb1\x13\ +\xb8\x44\x5b\x37\xde\x97\xb8\x3b\xae\xf2\x72\x3f\xf2\x4d\x11\xe3\ +\xcb\x5b\xc6\xc9\x93\xdd\xbb\x22\x9d\xc7\x09\x8e\xff\x2e\x8f\x1b\ +\x33\x29\xcb\xf6\xb4\x38\xb8\xd5\x91\x30\x0c\x18\x9b\x05\x3c\xc4\ +\xae\x08\xce\x1d\x4f\x73\x22\xa8\x08\x67\xe0\x51\x16\x04\x4e\xe2\ +\x78\x8a\xc8\x48\x4a\x39\xf3\x04\x91\x4a\x85\x91\xe3\x31\x41\x42\ +\x1e\x70\x36\xf3\x02\xa2\xa8\xd0\xd0\xc3\x80\x17\xe8\x50\x07\x96\ +\x14\x6a\x2e\x15\x48\x8a\x68\xa6\x05\x14\xd1\xb1\x69\x24\x1c\x4f\ +\x46\x84\xb1\x48\x87\x68\xdb\x68\xae\xd8\xfb\x96\x14\xf2\x88\x85\ +\x33\x19\x42\x48\x5b\x29\x20\x24\x90\x92\x01\x1f\x61\xa4\xa4\x70\ +\x18\x81\xa7\x42\xcc\x60\x95\xa1\xf9\x4a\x47\x10\xa5\x38\x07\x21\ +\x22\x54\x03\x4b\x4e\xee\x78\x51\x40\x24\xa3\x8a\xca\x99\x86\x03\ +\xa8\x00\xa1\x03\x23\x54\x06\x5a\x05\x33\x8e\xa0\x02\xad\x03\x27\ +\x92\x44\x89\x08\xce\xcc\x3c\x88\x51\xca\x99\x46\x84\x08\x5e\x52\ +\x11\xcc\x24\x91\x01\xb6\xdf\x61\x58\x2b\xd0\x8c\xcf\x42\xeb\x6e\ +\xc0\x1c\x0e\x0e\xfc\xd5\x20\x08\x2e\x11\xdb\x18\x5a\x1b\x19\x8f\ +\x9c\x31\x32\x0f\x56\x83\x08\x89\x70\xc6\xc8\x3c\x84\x26\x99\x62\ +\x91\x83\xc8\x34\x8b\x04\x8c\xc3\x76\xa8\x18\x32\x69\x65\x42\xb8\ +\x03\x9b\x88\x89\x83\x04\xbf\x18\x93\x76\xa5\xce\x6b\x89\xf0\x34\ +\xb2\x2b\x38\x68\xa1\x20\x70\x00\x2e\x79\x43\x74\xa3\x5c\xe0\xbc\ +\xbc\x6a\xbc\x15\x26\x0f\xce\x55\x34\x19\xd1\xce\x46\x93\x02\xe0\ +\x6e\xca\xca\x43\x6b\x79\x8e\x9b\x5d\x65\x6c\x75\x9e\x8c\x04\x56\ +\xff\xa4\x78\xed\x60\x2b\xa5\x83\x88\x46\x21\xf2\x80\x2d\x52\x40\ +\x8e\xb2\xbb\x3d\x3e\x4f\x25\x66\xf4\x6e\xe2\x86\xed\xbd\x4c\x23\ +\x8b\x54\x4d\xa8\xe8\x0f\x88\x93\x44\xd8\xdd\x09\x75\xe8\x2b\x42\ +\x20\x66\x6c\x10\x9f\xf0\xfa\xae\xd4\x71\x28\xd5\x6f\xa4\xc0\xbd\ +\xa8\x24\x5d\xd9\xe8\x87\x9a\xff\x97\x8d\xaf\x94\x8d\x09\x22\xd6\ +\x57\x70\x64\x0e\xdb\xb2\x6a\xbc\x63\xba\xcd\xd0\xfa\x09\x0d\xb9\ +\x3d\x33\xd7\x10\xd7\x4b\x1e\xbe\x59\x12\xfb\x60\xba\x5f\xde\xfc\ +\xc7\x72\x63\xfc\x23\xee\x94\x4f\xfe\x87\x7e\xa0\xa9\xfd\x5f\xe3\ +\xa5\xff\xa1\x8a\x57\x8d\x9f\x01\xcd\x75\x3b\x54\x92\x6d\xb1\x76\ +\xbf\x86\x5a\xe0\x33\x8a\xa2\x50\x72\x8b\x54\xca\x79\xc8\x44\x80\ +\x8b\xc5\xe9\xf1\x24\x80\x61\x1f\x87\x31\x54\x28\x35\x28\x77\x70\ +\x38\x0a\xef\x5e\x01\x6c\x2d\x30\xca\x4d\x27\x87\xf3\xb6\x75\x71\ +\x51\x8f\xab\xc4\x3d\x63\x4f\xd1\x48\xe9\x12\x77\x99\x3f\x04\x8d\ +\x94\x45\x3f\x26\x1a\xa7\xc9\x6b\x7f\x3f\x40\xbe\xb1\x07\xdc\xbd\ +\x9a\x74\x3b\x70\xb3\xc8\x16\x78\xae\x83\x37\x44\xec\x6d\x2f\xb0\ +\x33\x79\x24\xae\x4b\x54\x58\x44\x6a\x12\x84\x4c\xbe\x25\x71\x7c\ +\x43\xa2\x6b\xb4\x80\x51\x68\x3d\x98\x0d\x76\xd0\x74\x70\x77\x45\ +\x13\x01\xac\x54\xdb\x3c\x43\xa9\x6c\x13\xec\xd7\x40\x5f\xec\x9f\ +\x26\xa4\x41\x7e\x46\x27\xec\x51\x77\x4a\x1b\x75\xe8\x6c\xd4\x72\ +\x46\x23\x27\xf6\x15\x8d\x89\x91\x91\x3b\x9a\xb8\x74\xea\xe5\x7c\ +\x68\xfd\x0f\xc0\x8f\xd9\xf8\xdd\xed\xe5\xaf\x07\x77\xaf\x4f\x43\ +\x8f\x7d\x8b\xad\xb7\xb0\x20\xdf\xc6\xc2\xe5\x65\xff\x12\x0b\x17\ +\x37\xff\x0b\x30\x9c\x7e\x07\x78\x13\x0d\x5c\xa0\x88\x30\xc6\xaf\ +\xc1\x21\x88\xda\xa9\x01\x13\xce\x60\xaa\xc5\x03\xb3\xbd\x3d\xb2\ +\x13\x10\x86\x01\x11\x2a\xf4\xf6\x7e\x15\x90\x7a\x93\xd1\x84\x84\ +\xf6\x19\x29\x2d\xb8\xc5\xc3\xc8\xf6\x98\x6d\xbf\x98\x89\x26\xa4\ +\x51\x05\x70\x18\x8d\xf4\x36\xc2\x91\xcd\x9d\x0b\x0d\xee\xf4\x36\ +\x04\x6c\x8c\xdc\xce\x02\xc6\x99\xd7\x3e\xf1\xb3\x09\xe4\xfa\xc4\ +\xa0\x03\x26\x28\x66\x37\x14\xd9\x00\x53\x62\x18\xd8\x19\xea\xf4\ +\x34\xb2\x85\xd0\x44\x45\x2a\xe2\x40\x9f\x24\x38\x32\x5c\xdf\x4d\ +\x3b\x91\xbf\x1e\x2e\x3f\xeb\xee\xda\x83\xaf\x7b\x7b\x4d\x7b\xb8\ +\xf9\x27\xa5\x63\xc0\x92\ \x00\x00\x0d\x5b\ \x00\ \x00\x43\x5b\x78\x9c\xed\x5b\x59\x6f\xe3\x46\x12\x7e\x9f\x5f\xc1\ @@ -28257,6 +28539,399 @@ qt_resource_data = "\ \x1d\xf9\xce\x6b\x06\xfa\x4c\x06\x12\xcf\xe8\xb8\xe7\x33\x90\xb0\ \xbf\xf3\x0c\xd4\x7f\x6c\x3f\x84\x5f\x17\xf4\x27\xb6\xef\xbe\xf9\ \x6f\x78\x95\xb1\x1d\ +\x00\x00\x18\x63\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x50\x65\x72\x70\x65\ +\x6e\x64\x69\x63\x75\x6c\x61\x72\x2e\x73\x76\x67\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\ +\x5f\x65\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\ +\x73\x76\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\ +\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\ +\x20\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x64\x65\x66\x73\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\ +\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\ +\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x36\x22\x20\x2f\x3e\x0a\x20\ +\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\ +\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\ +\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\ +\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x73\x74\x6f\x70\x33\x31\x34\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\ +\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\ +\x65\x3d\x22\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\ +\x70\x33\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\x20\x33\ +\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\ +\x20\x31\x30\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x7a\x3d\ +\x22\x36\x34\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\ +\x72\x73\x70\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\x33\x32\ +\x20\x3a\x20\x32\x31\x2e\x33\x33\x33\x33\x33\x33\x20\x3a\x20\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x65\x72\ +\x73\x70\x65\x63\x74\x69\x76\x65\x32\x37\x33\x34\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\ +\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\ +\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\ +\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\ +\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\ +\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\ +\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\ +\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\ +\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\ +\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\ +\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\ +\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\ +\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\ +\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\ +\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\ +\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\ +\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\ +\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\ +\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ +\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\ +\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\ +\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x33\ +\x2e\x38\x38\x39\x30\x38\x37\x33\x22\x0a\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x32\x31\x2e\x38\ +\x35\x32\x31\x37\x38\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x31\x36\x2e\x32\x37\x33\x32\ +\x31\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\ +\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x73\x68\x6f\ +\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\x6d\ +\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x69\ +\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\ +\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\ +\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\x35\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\ +\x77\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\ +\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\x20\ +\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\ +\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x37\x33\x31\ +\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\ +\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\ +\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\ +\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\ +\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\ +\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\ +\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\ +\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\x63\x3a\ +\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\ +\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\ +\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\ +\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\ +\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\x3d\x22\ +\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\ +\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\x3c\x67\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x34\x32\x38\ +\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\ +\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x31\x36\ +\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x36\x32\x31\ +\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\x39\x38\x36\x2c\x2d\x36\ +\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\x3e\x0a\x20\x20\x20\x20\ +\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\ +\x30\x2e\x35\x33\x33\x33\x33\x32\x39\x37\x3b\x63\x6f\x6c\x6f\x72\ +\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x30\ +\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\ +\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\ +\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\ +\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\ +\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\x30\x31\x36\x32\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\ +\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ +\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\ +\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\ +\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\ +\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\ +\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\ +\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\ +\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\ +\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\ +\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\ +\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\ +\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\ +\x6d\x20\x31\x36\x31\x2e\x36\x36\x36\x32\x31\x2c\x34\x37\x36\x2e\ +\x37\x37\x38\x31\x34\x20\x30\x2c\x32\x30\x35\x2e\x30\x38\x34\x36\ +\x32\x20\x63\x20\x2d\x31\x33\x2e\x38\x33\x33\x36\x2c\x35\x2e\x30\ +\x38\x36\x36\x34\x20\x2d\x32\x34\x2e\x38\x31\x36\x30\x34\x2c\x31\ +\x36\x2e\x33\x36\x39\x39\x31\x20\x2d\x32\x39\x2e\x34\x39\x30\x35\ +\x35\x2c\x33\x30\x2e\x34\x35\x34\x32\x39\x20\x6c\x20\x2d\x31\x31\ +\x34\x2e\x36\x38\x35\x34\x37\x38\x2c\x30\x20\x30\x2c\x33\x34\x2e\ +\x38\x38\x37\x35\x32\x20\x31\x31\x36\x2e\x34\x32\x30\x32\x31\x38\ +\x2c\x30\x20\x63\x20\x37\x2e\x33\x38\x37\x35\x33\x2c\x31\x36\x2e\ +\x36\x36\x33\x39\x38\x20\x32\x33\x2e\x37\x34\x35\x30\x34\x2c\x32\ +\x38\x2e\x34\x37\x30\x38\x35\x20\x34\x33\x2e\x31\x37\x35\x37\x2c\ +\x32\x38\x2e\x39\x31\x32\x33\x20\x32\x30\x2e\x31\x37\x36\x39\x36\ +\x2c\x30\x2e\x34\x35\x38\x34\x31\x20\x33\x37\x2e\x37\x35\x38\x33\ +\x33\x2c\x2d\x31\x31\x2e\x35\x36\x32\x39\x20\x34\x35\x2e\x34\x38\ +\x38\x37\x2c\x2d\x32\x38\x2e\x39\x31\x32\x33\x20\x6c\x20\x31\x31\ +\x30\x2e\x34\x34\x35\x2c\x30\x20\x30\x2c\x2d\x33\x34\x2e\x38\x38\ +\x37\x35\x32\x20\x2d\x31\x30\x38\x2e\x37\x31\x30\x32\x36\x2c\x30\ +\x20\x63\x20\x2d\x34\x2e\x34\x35\x38\x31\x34\x2c\x2d\x31\x33\x2e\ +\x34\x36\x39\x30\x32\x20\x2d\x31\x34\x2e\x36\x38\x31\x36\x38\x2c\ +\x2d\x32\x34\x2e\x33\x31\x37\x35\x39\x20\x2d\x32\x37\x2e\x37\x35\ +\x35\x38\x32\x2c\x2d\x32\x39\x2e\x36\x38\x33\x33\x20\x6c\x20\x30\ +\x2c\x2d\x32\x30\x35\x2e\x38\x35\x35\x36\x31\x20\x2d\x33\x34\x2e\ +\x38\x38\x37\x35\x31\x2c\x30\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\ +\x2d\x34\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\ +\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\ +\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\ +\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\ +\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\ +\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\ +\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\ +\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\x30\x31\x36\x32\ +\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\ +\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\ +\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\ +\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\ +\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\ +\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\ +\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\ +\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\ +\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\ +\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x31\ +\x35\x2e\x36\x30\x37\x31\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x34\x2e\x38\x39\x31\ +\x32\x35\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x78\x3d\ +\x22\x2d\x38\x2e\x37\x34\x36\x37\x35\x37\x35\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x36\x39\x31\x2e\x34\x38\x38\ +\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x63\ +\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\ +\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\ +\x66\x69\x6c\x6c\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x66\x69\x6c\ +\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\ +\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\ +\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\ +\x30\x31\x36\x32\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\ +\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\ +\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\ +\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\ +\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\ +\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\ +\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\ +\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\ +\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\ +\x2d\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\ +\x74\x68\x3d\x22\x32\x34\x37\x2e\x34\x31\x30\x36\x33\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\ +\x33\x34\x2e\x38\x39\x31\x32\x35\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x78\x3d\x22\x2d\x37\x30\x33\x2e\x33\x38\x32\x38\ +\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\ +\x33\x35\x2e\x35\x37\x36\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\ +\x72\x69\x78\x28\x30\x2c\x2d\x31\x2c\x31\x2c\x30\x2c\x30\x2c\x30\ +\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x67\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x65\x78\x70\x6f\x72\x74\x2d\x79\x64\x70\x69\x3d\x22\x37\x2e\ +\x30\x37\x32\x31\x39\x35\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\ +\x74\x2d\x78\x64\x70\x69\x3d\x22\x37\x2e\x30\x37\x32\x31\x39\x35\ +\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\x74\x2d\x66\x69\x6c\x65\ +\x6e\x61\x6d\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x79\x6f\x72\x69\ +\x6b\x2f\x44\x6f\x63\x75\x6d\x65\x6e\x74\x73\x2f\x4c\x61\x62\x2f\ +\x44\x72\x61\x66\x74\x2f\x69\x63\x6f\x6e\x73\x2f\x6c\x69\x6e\x65\ +\x2e\x70\x6e\x67\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\ +\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\ +\x28\x2d\x30\x2e\x39\x39\x39\x37\x34\x32\x2c\x2d\x30\x2e\x30\x32\ +\x32\x37\x31\x33\x35\x31\x2c\x30\x2e\x30\x32\x32\x37\x31\x33\x35\ +\x31\x2c\x2d\x30\x2e\x39\x39\x39\x37\x34\x32\x2c\x33\x33\x34\x2e\ +\x32\x36\x37\x36\x38\x2c\x31\x33\x36\x36\x2e\x32\x36\x39\x32\x29\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\ +\x33\x31\x36\x30\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\ +\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\ +\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ +\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x23\x30\x30\x62\x32\ +\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ +\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\ +\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\ +\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\ +\x35\x2e\x38\x30\x30\x30\x30\x30\x31\x39\x3b\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\ +\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\ +\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\ +\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\ +\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\ +\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\ +\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\ +\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\ +\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x70\x61\x74\x68\x33\x31\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\ +\x3d\x22\x31\x39\x37\x2e\x31\x34\x32\x38\x35\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\ +\x3a\x63\x79\x3d\x22\x36\x35\x35\x2e\x32\x31\x39\x33\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ +\x64\x69\x3a\x72\x78\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\x33\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\ +\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\ +\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\ +\x22\x6d\x20\x32\x34\x35\x2e\x37\x31\x34\x32\x38\x2c\x36\x35\x35\ +\x2e\x32\x31\x39\x33\x20\x63\x20\x30\x2c\x32\x36\x2e\x38\x32\x35\ +\x32\x36\x20\x2d\x32\x31\x2e\x37\x34\x36\x31\x37\x2c\x34\x38\x2e\ +\x35\x37\x31\x34\x33\x20\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\ +\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x2d\x32\x36\x2e\x38\x32\x35\ +\x32\x36\x2c\x30\x20\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\ +\x32\x31\x2e\x37\x34\x36\x31\x37\x20\x2d\x34\x38\x2e\x35\x37\x31\ +\x34\x33\x2c\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x30\x2c\x2d\ +\x32\x36\x2e\x38\x32\x35\x32\x36\x20\x32\x31\x2e\x37\x34\x36\x31\ +\x37\x2c\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x34\x38\x2e\x35\ +\x37\x31\x34\x33\x2c\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x32\ +\x36\x2e\x38\x32\x35\x32\x36\x2c\x30\x20\x34\x38\x2e\x35\x37\x31\ +\x34\x33\x2c\x32\x31\x2e\x37\x34\x36\x31\x37\x20\x34\x38\x2e\x35\ +\x37\x31\x34\x33\x2c\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x7a\x22\ +\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\ +\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\ +\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\ +\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x75\x72\x6c\x28\x23\x72\x61\x64\ +\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x29\ +\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\ +\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\ +\x33\x31\x36\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\x3d\x22\x32\x32\ +\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\ +\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\ +\x72\x78\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ +\x64\x69\x3a\x72\x79\x3d\x22\x32\x33\x2e\x39\x39\x31\x31\x32\x33\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\ +\x6d\x20\x32\x35\x39\x2e\x36\x30\x39\x32\x31\x2c\x36\x37\x32\x2e\ +\x37\x39\x37\x33\x36\x20\x63\x20\x30\x2c\x31\x33\x2e\x32\x34\x39\ +\x39\x33\x20\x2d\x31\x35\x2e\x33\x37\x36\x38\x36\x2c\x32\x33\x2e\ +\x39\x39\x31\x31\x33\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\ +\x32\x33\x2e\x39\x39\x31\x31\x33\x20\x2d\x31\x38\x2e\x39\x36\x38\ +\x33\x32\x2c\x30\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\ +\x31\x30\x2e\x37\x34\x31\x32\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\ +\x39\x2c\x2d\x32\x33\x2e\x39\x39\x31\x31\x33\x20\x30\x2c\x2d\x31\ +\x33\x2e\x32\x34\x39\x39\x33\x20\x31\x35\x2e\x33\x37\x36\x38\x37\ +\x2c\x2d\x32\x33\x2e\x39\x39\x31\x31\x32\x20\x33\x34\x2e\x33\x34\ +\x35\x31\x39\x2c\x2d\x32\x33\x2e\x39\x39\x31\x31\x32\x20\x31\x38\ +\x2e\x39\x36\x38\x33\x33\x2c\x30\x20\x33\x34\x2e\x33\x34\x35\x31\ +\x39\x2c\x31\x30\x2e\x37\x34\x31\x31\x39\x20\x33\x34\x2e\x33\x34\ +\x35\x31\x39\x2c\x32\x33\x2e\x39\x39\x31\x31\x32\x20\x7a\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\ +\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x38\ +\x35\x31\x33\x30\x32\x33\x2c\x2d\x30\x2e\x35\x32\x34\x36\x37\x35\ +\x34\x2c\x30\x2e\x35\x32\x34\x36\x37\x35\x34\x2c\x30\x2e\x38\x35\ +\x31\x33\x30\x32\x33\x2c\x2d\x33\x33\x38\x2e\x36\x39\x36\x39\x32\ +\x2c\x32\x31\x34\x2e\x31\x39\x33\x32\x38\x29\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\ +\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\ +\x3e\x0a\ \x00\x00\x09\xad\ \x00\ \x00\x21\x35\x78\x9c\xed\x58\xdb\x6e\xe3\xc8\x11\x7d\xf7\x57\x30\ @@ -28700,6 +29375,463 @@ qt_resource_data = "\ \x75\x6d\x75\x6c\x61\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\ \x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\ \x67\x3e\x0a\ +\x00\x00\x1c\x6d\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x50\x65\x72\x70\x65\ +\x6e\x64\x69\x63\x75\x6c\x61\x72\x2e\x73\x76\x67\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\ +\x5f\x65\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\ +\x73\x76\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\ +\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\ +\x20\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x64\x65\x66\x73\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\ +\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\ +\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x36\x22\x20\x2f\x3e\x0a\x20\ +\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\ +\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\ +\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\ +\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x73\x74\x6f\x70\x33\x31\x34\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\ +\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\ +\x65\x3d\x22\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\ +\x70\x33\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\x20\x33\ +\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\ +\x20\x31\x30\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x7a\x3d\ +\x22\x36\x34\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\ +\x72\x73\x70\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\x33\x32\ +\x20\x3a\x20\x32\x31\x2e\x33\x33\x33\x33\x33\x33\x20\x3a\x20\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x65\x72\ +\x73\x70\x65\x63\x74\x69\x76\x65\x32\x37\x33\x34\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\ +\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\ +\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\ +\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\ +\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\ +\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\ +\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\ +\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\ +\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\ +\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\ +\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\ +\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\ +\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\ +\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\ +\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\ +\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x31\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\ +\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x2d\x34\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\ +\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\ +\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\ +\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\ +\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\ +\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\ +\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\ +\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\ +\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\ +\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x66\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\ +\x38\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\ +\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\ +\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x31\x22\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\ +\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\ +\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\ +\x74\x6f\x70\x33\x31\x34\x36\x2d\x39\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\ +\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\ +\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\ +\x74\x6f\x70\x33\x31\x34\x38\x2d\x38\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\ +\x3c\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\ +\x69\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\ +\x72\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\ +\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\ +\x36\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\ +\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\ +\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\ +\x67\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\ +\x22\x33\x2e\x38\x38\x39\x30\x38\x37\x33\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x32\x31\ +\x2e\x38\x35\x32\x31\x37\x38\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x31\x36\x2e\x32\x37\ +\x33\x32\x31\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\ +\x72\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x73\ +\x68\x6f\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\ +\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\ +\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\ +\x72\x69\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\ +\x6e\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\ +\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\ +\x64\x6f\x77\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\ +\x6d\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\ +\x0a\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x37\ +\x33\x31\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\ +\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\ +\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\ +\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\ +\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\ +\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\ +\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\ +\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\ +\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\ +\x63\x3a\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\ +\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\ +\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\ +\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\ +\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\ +\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\ +\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\ +\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x34\ +\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\ +\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\ +\x31\x36\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x36\ +\x32\x31\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\x39\x38\x36\x2c\ +\x2d\x36\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x30\x2e\x35\x32\x39\x31\x36\x36\x37\x39\x3b\x63\x6f\x6c\ +\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\ +\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\ +\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\ +\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\ +\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\x30\x31\x36\x32\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\ +\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\ +\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ +\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\ +\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\ +\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\ +\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\ +\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\ +\x3d\x22\x6d\x20\x35\x39\x2e\x38\x38\x39\x33\x37\x37\x2c\x34\x36\ +\x39\x2e\x33\x39\x36\x37\x35\x20\x30\x2c\x35\x35\x2e\x33\x31\x38\ +\x38\x37\x20\x2d\x34\x39\x2e\x31\x35\x30\x39\x31\x38\x2c\x30\x20\ +\x30\x2c\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x34\x39\x2e\x31\x35\ +\x30\x39\x31\x38\x2c\x30\x20\x30\x2c\x31\x35\x30\x2e\x31\x35\x31\ +\x32\x33\x20\x2d\x34\x39\x2e\x31\x35\x30\x39\x31\x38\x2c\x30\x20\ +\x30\x2c\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x34\x39\x2e\x31\x35\ +\x30\x39\x31\x38\x2c\x30\x20\x30\x2c\x34\x32\x2e\x30\x31\x39\x32\ +\x32\x20\x33\x34\x2e\x38\x38\x37\x35\x31\x35\x2c\x30\x20\x30\x2c\ +\x2d\x34\x32\x2e\x30\x31\x39\x32\x32\x20\x31\x33\x37\x2e\x38\x31\ +\x35\x33\x31\x38\x2c\x30\x20\x30\x2c\x34\x32\x2e\x30\x31\x39\x32\ +\x32\x20\x33\x34\x2e\x38\x38\x37\x35\x32\x2c\x30\x20\x30\x2c\x2d\ +\x34\x32\x2e\x30\x31\x39\x32\x32\x20\x35\x38\x2e\x39\x38\x31\x31\ +\x2c\x30\x20\x30\x2c\x2d\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x2d\ +\x35\x38\x2e\x39\x38\x31\x31\x2c\x30\x20\x30\x2c\x2d\x31\x31\x37\ +\x2e\x33\x38\x33\x39\x35\x20\x63\x20\x31\x34\x2e\x30\x33\x38\x39\ +\x37\x2c\x2d\x35\x2e\x37\x31\x33\x32\x36\x20\x32\x34\x2e\x38\x34\ +\x30\x39\x39\x2c\x2d\x31\x37\x2e\x38\x30\x38\x36\x37\x20\x32\x38\ +\x2e\x37\x31\x39\x35\x35\x2c\x2d\x33\x32\x2e\x37\x36\x37\x32\x38\ +\x20\x6c\x20\x33\x30\x2e\x32\x36\x31\x35\x35\x2c\x30\x20\x30\x2c\ +\x2d\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x2d\x33\x34\x2e\x35\x30\ +\x32\x30\x32\x2c\x30\x20\x63\x20\x2d\x35\x2e\x33\x33\x33\x33\x33\ +\x2c\x2d\x31\x30\x2e\x30\x31\x35\x31\x38\x20\x2d\x31\x33\x2e\x38\ +\x33\x38\x30\x37\x2c\x2d\x31\x38\x2e\x30\x36\x32\x37\x33\x20\x2d\ +\x32\x34\x2e\x34\x37\x39\x30\x38\x2c\x2d\x32\x32\x2e\x33\x35\x38\ +\x38\x35\x20\x6c\x20\x30\x2c\x2d\x33\x32\x2e\x39\x36\x30\x30\x32\ +\x20\x2d\x33\x34\x2e\x38\x38\x37\x35\x32\x2c\x30\x20\x30\x2c\x33\ +\x32\x2e\x33\x38\x31\x37\x38\x20\x63\x20\x2d\x31\x31\x2e\x33\x33\ +\x33\x31\x34\x2c\x34\x2e\x31\x32\x36\x36\x34\x20\x2d\x32\x30\x2e\ +\x38\x30\x30\x31\x32\x2c\x31\x32\x2e\x33\x35\x38\x32\x38\x20\x2d\ +\x32\x36\x2e\x34\x30\x36\x35\x37\x2c\x32\x32\x2e\x39\x33\x37\x30\ +\x39\x20\x6c\x20\x2d\x31\x31\x31\x2e\x34\x30\x38\x37\x34\x38\x2c\ +\x30\x20\x30\x2c\x2d\x35\x35\x2e\x33\x31\x38\x38\x37\x20\x2d\x33\ +\x34\x2e\x38\x38\x37\x35\x31\x35\x2c\x30\x20\x7a\x20\x6d\x20\x33\ +\x34\x2e\x38\x38\x37\x35\x31\x35\x2c\x39\x30\x2e\x32\x30\x36\x33\ +\x39\x20\x31\x30\x37\x2e\x35\x35\x33\x37\x37\x38\x2c\x30\x20\x63\ +\x20\x34\x2e\x30\x31\x37\x31\x36\x2c\x31\x35\x2e\x34\x34\x32\x36\ +\x38\x20\x31\x35\x2e\x33\x35\x34\x35\x36\x2c\x32\x38\x2e\x31\x30\ +\x33\x37\x39\x20\x33\x30\x2e\x32\x36\x31\x35\x34\x2c\x33\x33\x2e\ +\x35\x33\x38\x32\x37\x20\x6c\x20\x30\x2c\x31\x31\x36\x2e\x36\x31\ +\x32\x39\x36\x20\x2d\x31\x33\x37\x2e\x38\x31\x35\x33\x31\x38\x2c\ +\x30\x20\x30\x2c\x2d\x31\x35\x30\x2e\x31\x35\x31\x32\x33\x20\x7a\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\ +\x65\x63\x74\x33\x39\x34\x32\x2d\x30\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\ +\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\ +\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\ +\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\ +\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\ +\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x66\ +\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\ +\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\ +\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x30\x2e\x39\x34\ +\x30\x33\x34\x33\x38\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\ +\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\ +\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ +\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\ +\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\ +\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\ +\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\ +\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\ +\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\ +\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\ +\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x31\x32\x2e\x39\x30\x36\ +\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\x20\x4c\x20\x31\x32\x2e\ +\x39\x30\x36\x32\x35\x20\x31\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\ +\x35\x20\x31\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\x35\x20\x32\x31\ +\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\x39\x30\x36\x32\ +\x35\x20\x32\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\ +\x39\x30\x36\x32\x35\x20\x34\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\ +\x35\x20\x34\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\x35\x20\x35\x31\ +\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\x39\x30\x36\x32\ +\x35\x20\x35\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\ +\x39\x30\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\x35\x20\x4c\ +\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\ +\x35\x20\x4c\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x35\x31\x2e\x36\ +\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\x30\x36\x32\x35\x20\ +\x35\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\x30\ +\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\x35\x20\x4c\x20\x34\ +\x36\x2e\x35\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\x35\x20\ +\x4c\x20\x34\x36\x2e\x35\x36\x32\x35\x20\x35\x31\x2e\x36\x35\x36\ +\x32\x35\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x35\x31\x2e\x36\ +\x35\x36\x32\x35\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x34\x36\ +\x20\x4c\x20\x34\x36\x2e\x35\x36\x32\x35\x20\x34\x36\x20\x4c\x20\ +\x34\x36\x2e\x35\x36\x32\x35\x20\x32\x31\x2e\x36\x35\x36\x32\x35\ +\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x32\x31\x2e\x36\x35\x36\ +\x32\x35\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x31\x36\x20\x4c\ +\x20\x34\x36\x2e\x35\x36\x32\x35\x20\x31\x36\x20\x4c\x20\x34\x36\ +\x2e\x35\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\x20\x4c\x20\ +\x34\x30\x2e\x39\x30\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\ +\x20\x4c\x20\x34\x30\x2e\x39\x30\x36\x32\x35\x20\x31\x36\x20\x4c\ +\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x31\x36\x20\x4c\x20\x31\x38\ +\x2e\x35\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\x20\x4c\x20\ +\x31\x32\x2e\x39\x30\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\ +\x20\x7a\x20\x4d\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x32\x31\x2e\ +\x36\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\x30\x36\x32\x35\ +\x20\x32\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\ +\x30\x36\x32\x35\x20\x34\x36\x20\x4c\x20\x31\x38\x2e\x35\x36\x32\ +\x35\x20\x34\x36\x20\x4c\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x32\ +\x31\x2e\x36\x35\x36\x32\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\ +\x6d\x61\x74\x72\x69\x78\x28\x36\x2e\x31\x36\x37\x39\x35\x38\x34\ +\x2c\x30\x2c\x30\x2c\x36\x2e\x31\x36\x37\x39\x35\x38\x34\x2c\x2d\ +\x33\x39\x2e\x32\x33\x31\x39\x30\x38\x2c\x34\x30\x37\x2e\x37\x35\ +\x36\x33\x37\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\ +\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\ +\x74\x2d\x79\x64\x70\x69\x3d\x22\x37\x2e\x30\x37\x32\x31\x39\x35\ +\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\x74\x2d\x78\x64\x70\x69\ +\x3d\x22\x37\x2e\x30\x37\x32\x31\x39\x35\x31\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x65\ +\x78\x70\x6f\x72\x74\x2d\x66\x69\x6c\x65\x6e\x61\x6d\x65\x3d\x22\ +\x2f\x68\x6f\x6d\x65\x2f\x79\x6f\x72\x69\x6b\x2f\x44\x6f\x63\x75\ +\x6d\x65\x6e\x74\x73\x2f\x4c\x61\x62\x2f\x44\x72\x61\x66\x74\x2f\ +\x69\x63\x6f\x6e\x73\x2f\x6c\x69\x6e\x65\x2e\x70\x6e\x67\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\ +\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x2d\x30\x2e\x39\x39\ +\x39\x37\x34\x32\x2c\x2d\x30\x2e\x30\x32\x32\x37\x31\x33\x35\x31\ +\x2c\x30\x2e\x30\x32\x32\x37\x31\x33\x35\x31\x2c\x2d\x30\x2e\x39\ +\x39\x39\x37\x34\x32\x2c\x34\x31\x31\x2e\x39\x37\x39\x39\x39\x2c\ +\x31\x31\x38\x38\x2e\x36\x34\x31\x31\x29\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x33\x31\x36\x30\x22\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ +\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\ +\x66\x69\x6c\x6c\x3a\x23\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\ +\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\ +\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\ +\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\ +\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\ +\x30\x30\x31\x39\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ +\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\ +\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\ +\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\ +\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\ +\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\ +\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\ +\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\ +\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\ +\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\ +\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ +\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\x3d\x22\x31\x39\x37\x2e\ +\x31\x34\x32\x38\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\x36\ +\x35\x35\x2e\x32\x31\x39\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\ +\x22\x34\x38\x2e\x35\x37\x31\x34\x33\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\ +\x79\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\x33\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x32\x34\x35\ +\x2e\x37\x31\x34\x32\x38\x2c\x36\x35\x35\x2e\x32\x31\x39\x33\x20\ +\x63\x20\x30\x2c\x32\x36\x2e\x38\x32\x35\x32\x36\x20\x2d\x32\x31\ +\x2e\x37\x34\x36\x31\x37\x2c\x34\x38\x2e\x35\x37\x31\x34\x33\x20\ +\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x34\x38\x2e\x35\x37\x31\ +\x34\x33\x20\x2d\x32\x36\x2e\x38\x32\x35\x32\x36\x2c\x30\x20\x2d\ +\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\x32\x31\x2e\x37\x34\x36\ +\x31\x37\x20\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\x34\x38\ +\x2e\x35\x37\x31\x34\x33\x20\x30\x2c\x2d\x32\x36\x2e\x38\x32\x35\ +\x32\x36\x20\x32\x31\x2e\x37\x34\x36\x31\x37\x2c\x2d\x34\x38\x2e\ +\x35\x37\x31\x34\x33\x20\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\ +\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x32\x36\x2e\x38\x32\x35\x32\ +\x36\x2c\x30\x20\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x32\x31\x2e\ +\x37\x34\x36\x31\x37\x20\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x34\ +\x38\x2e\x35\x37\x31\x34\x33\x20\x7a\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\ +\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\ +\x6c\x3a\x75\x72\x6c\x28\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x29\x3b\x66\x69\x6c\x6c\x2d\ +\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\ +\x3a\x6e\x6f\x6e\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x36\x34\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\ +\x6f\x64\x69\x3a\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\ +\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\ +\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\ +\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\x33\x34\ +\x2e\x33\x34\x35\x31\x38\x38\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\ +\x22\x32\x33\x2e\x39\x39\x31\x31\x32\x33\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x32\x35\x39\x2e\ +\x36\x30\x39\x32\x31\x2c\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x20\ +\x63\x20\x30\x2c\x31\x33\x2e\x32\x34\x39\x39\x33\x20\x2d\x31\x35\ +\x2e\x33\x37\x36\x38\x36\x2c\x32\x33\x2e\x39\x39\x31\x31\x33\x20\ +\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x32\x33\x2e\x39\x39\x31\ +\x31\x33\x20\x2d\x31\x38\x2e\x39\x36\x38\x33\x32\x2c\x30\x20\x2d\ +\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\x31\x30\x2e\x37\x34\x31\ +\x32\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\x32\x33\x2e\ +\x39\x39\x31\x31\x33\x20\x30\x2c\x2d\x31\x33\x2e\x32\x34\x39\x39\ +\x33\x20\x31\x35\x2e\x33\x37\x36\x38\x37\x2c\x2d\x32\x33\x2e\x39\ +\x39\x31\x31\x32\x20\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\x32\ +\x33\x2e\x39\x39\x31\x31\x32\x20\x31\x38\x2e\x39\x36\x38\x33\x33\ +\x2c\x30\x20\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x31\x30\x2e\x37\ +\x34\x31\x31\x39\x20\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x32\x33\ +\x2e\x39\x39\x31\x31\x32\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\ +\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x38\x35\x31\x33\x30\x32\x33\ +\x2c\x2d\x30\x2e\x35\x32\x34\x36\x37\x35\x34\x2c\x30\x2e\x35\x32\ +\x34\x36\x37\x35\x34\x2c\x30\x2e\x38\x35\x31\x33\x30\x32\x33\x2c\ +\x2d\x33\x33\x38\x2e\x36\x39\x36\x39\x32\x2c\x32\x31\x34\x2e\x31\ +\x39\x33\x32\x38\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\ +\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ \x00\x00\x05\xc0\ \x00\ \x00\x13\xbe\x78\x9c\xd5\x57\x59\x73\xdb\x36\x10\x7e\xf7\xaf\x60\ @@ -28794,6 +29926,144 @@ qt_resource_data = "\ \xe6\x77\x5b\x82\xcc\x0b\xcd\x22\xfc\x47\x30\x78\xae\xeb\xfd\xb4\ \x5a\x79\x11\x19\xe2\x7f\x1d\x32\xff\xd5\xf2\x39\xc2\x32\xee\xa7\ \xb5\xf5\xed\xd5\x5c\x4d\x4b\xb7\x57\x7f\x02\xb2\xe9\xd6\x37\ +\x00\x00\x08\x75\ +\x00\ +\x00\x29\x56\x78\x9c\xed\x5a\x59\x6f\xe3\x38\x12\x7e\xcf\xaf\xd0\ +\xaa\x5f\x3a\x58\x8b\xe2\x2d\xd1\x39\xe6\x61\xb3\x33\x18\x60\x80\ +\x05\xb6\xbb\xb1\x8f\x0d\x59\xa2\x1d\x6d\x64\xc9\xa0\xe4\xd8\xce\ +\xaf\xdf\xa2\x2e\xcb\xb6\xd2\x49\x6f\xcf\x38\x40\x23\x0e\x12\x8b\ +\x75\xb0\x58\xc5\x8f\xc5\xa2\x98\xeb\x5f\xb6\xcb\xcc\x79\xd4\xa6\ +\x4c\x8b\xfc\xc6\x25\x08\xbb\x8e\xce\xe3\x22\x49\xf3\xc5\x8d\xfb\ +\xe5\xf3\xaf\x5e\xe8\x3a\x65\x15\xe5\x49\x94\x15\xb9\xbe\x71\xf3\ +\xc2\xfd\xe5\xf6\xe2\xfa\x6f\x9e\xe7\xfc\xc3\xe8\xa8\xd2\x89\xb3\ +\x49\xab\x7b\xe7\xf7\xfc\xa1\x8c\xa3\x95\x76\x3e\xde\x57\xd5\x6a\ +\xea\xfb\x9b\xcd\x06\xa5\x2d\x11\x15\x66\xe1\x5f\x3a\x9e\x77\x7b\ +\x71\x71\x5d\x3e\x2e\x2e\x1c\xc7\x01\xbb\x79\x39\x4d\xe2\x1b\xb7\ +\x55\x58\xad\x4d\x56\x0b\x26\xb1\xaf\x33\xbd\xd4\x79\x55\xfa\x04\ +\x11\xdf\xdd\x8b\xc7\x7b\xf1\xd8\x5a\x4f\x1f\x75\x5c\x2c\x97\x45\ +\x5e\xd6\x9a\x79\xf9\x61\x20\x6c\x92\x79\x2f\x6d\x47\xb3\x61\xb5\ +\x10\x51\x4a\xf9\x98\xfa\x94\x7a\x20\xe1\x95\xbb\xbc\x8a\xb6\xde\ +\xa1\x2a\x8c\x71\x4c\x95\x62\x8c\x7d\xe0\xed\x25\x5f\x27\x35\xdd\ +\x66\x10\x8a\x67\x07\x53\x73\x87\xd6\x21\xfc\x2b\xf8\xed\x15\x3a\ +\x02\x2a\x8b\xb5\x89\xf5\x1c\x34\x35\xca\x75\xe5\xdf\x7d\xbe\xeb\ +\x99\x1e\x46\x49\x95\x0c\xba\xe9\xa2\x7f\x60\xf7\x60\x4a\xf2\x68\ +\xa9\xcb\x55\x14\xeb\xd2\xef\xe8\xb5\xfe\x26\x4d\xaa\xfb\x1b\x57\ +\xf2\xd5\xb6\x6e\xdf\xeb\x74\x71\x5f\x0d\x08\x69\x72\xe3\x82\x87\ +\x34\xa0\xb2\x6e\x77\x63\x98\xf6\x48\xc2\x88\xd1\x46\xb4\xed\x78\ +\xc8\xe2\x21\x22\x8e\x51\x81\xc4\x87\xda\x49\x11\xdb\x21\xdd\xb8\ +\x9f\xf2\x68\xf5\xf5\x9f\xdb\x4a\xe7\x56\x05\x75\xc1\xec\xfb\x2a\ +\xd6\xd5\x6a\x5d\x7d\xd5\x9d\xc4\x8d\x0b\xee\x0c\x7c\xab\xd9\x56\ +\x0d\x1d\xf8\x35\xc0\x39\x71\x6f\x81\x72\x9d\xe8\x79\x69\x39\x8d\ +\x4b\xb6\x05\x3e\x85\x35\x0f\xb8\x30\x2f\x3a\x32\xbf\x99\x28\x49\ +\x01\x8d\x8d\xdc\x60\x14\x71\x91\x65\x3a\x86\xb8\x44\xd9\x26\xda\ +\x95\x6e\x2f\x00\x5d\x1d\xaa\x32\xc2\x79\xdb\x29\x74\x5b\x56\xc5\ +\xaa\x93\x05\xef\xab\x5d\x06\x2e\x5b\xa2\x07\x3d\x16\x66\xfa\x61\ +\x5e\x7f\xae\x6a\x52\x01\xf3\x93\x56\xbb\x29\xb9\x72\xf7\x3a\xc5\ +\x7c\x5e\x6a\x30\x8c\x07\xb4\x7a\x4e\x40\x03\x6c\x49\xd7\xf1\x7f\ +\xcc\x1a\x1e\xb3\x46\xc6\xad\x85\xbd\xb5\x6b\xff\xd0\xed\x96\xda\ +\x07\x6c\x05\xf1\x5f\x41\xc4\x60\xd9\x76\x3d\xf5\x73\x5f\xed\x2c\ +\x52\x0f\x45\x59\xe2\x9e\x04\xfd\x71\xf5\x75\x0b\x8e\x3b\x53\x87\ +\x51\xf8\x43\x46\x25\x76\x8d\x04\x81\x95\x08\x5f\x78\x54\xe6\xc9\ +\xe2\xf9\x1b\xdd\xb4\x23\xf0\x0a\x93\x2e\x52\xc0\x4c\x2d\x47\x09\ +\x62\xf5\xe7\x50\x07\x82\x31\xf0\x8d\x06\x8c\xef\x63\x62\x63\x11\ +\x65\xdf\x0d\xa2\x3a\x29\x4c\xef\x8d\x86\x24\xf6\x61\x04\x4d\x43\ +\xdb\x87\x26\x58\x28\xf6\x1e\x2f\x5a\xe2\x97\x3c\xad\x20\x5b\xad\ +\x4b\x6d\x3e\xd9\x15\xff\xaf\xfc\x4b\xa9\x4f\xa4\x3e\x9b\x28\x2f\ +\x21\xbd\x2c\x6f\xdc\x65\x54\x99\x74\xfb\x91\x4c\xb0\xfd\x41\x52\ +\x85\x82\x2a\x0e\xcf\x14\x53\x14\xd2\x50\xb2\xcb\x5e\x3d\x86\x19\ +\xa1\x54\x20\x2a\x39\xa6\x7b\x2a\xcc\x82\x0c\x28\x0a\x54\xc0\x64\ +\x4f\x9d\x8f\xca\xce\x47\x65\x0d\x44\x9d\x23\xc6\x05\x09\xc3\xbf\ +\x3a\xa0\x5e\xf0\x42\x48\x3d\xfa\x33\x07\xf5\x4f\x4d\x75\x10\xcb\ +\x33\x26\x3b\x8f\x9f\x37\xdd\x0d\xec\x3d\x93\xf0\xfe\x22\x84\x8a\ +\x97\x10\x1a\xbc\x23\xf4\xb5\x08\x15\x67\x45\xe8\x99\x37\x64\xf0\ +\xee\x6d\x10\xca\x5e\x44\xe8\x4f\xbd\x33\xfd\xb9\x10\x65\x67\x85\ +\x28\x3d\x33\x44\xd9\x1b\x41\x94\xbc\x04\x51\xf1\x8e\xd0\xd7\x22\ +\x94\x9c\x15\xa1\xe2\xcc\x08\x25\x6f\x84\x50\xf5\x12\x42\xd9\x3b\ +\x42\x5f\x8b\x50\x75\x56\x84\xaa\x73\x23\x94\xbe\x11\x44\xe9\x4b\ +\x10\x95\xef\x10\x7d\x2d\x44\xe9\x59\x21\x8a\xcf\x0c\xd1\xb7\x42\ +\xe8\x4b\x2f\x48\x3c\xf9\x9e\x45\x5f\x0d\xd1\xb3\xbe\xbb\x84\x53\ +\xec\x99\xb3\xe8\xb7\x4b\xd1\x6b\xdf\xbe\x16\xae\x9f\xfa\x97\x95\ +\xf6\x2d\x75\xf2\x98\xea\xcd\x45\xdf\xdd\x2c\xea\xb1\xb2\x8a\x16\ +\xba\x1e\x1d\x40\xb3\x19\x5e\xcb\x98\x15\x26\xd1\xa6\x63\xc9\xfa\ +\x73\xc0\x6a\x1d\x68\x2e\x62\x2e\x0e\xe7\xcc\xf6\xda\xf3\xf1\x38\ +\xbf\xbc\x8f\x92\x62\x03\xe0\x39\x66\x3e\x15\x05\xe0\x15\xb0\x23\ +\x8e\x39\x16\x97\x5c\xa1\x20\x10\xb4\x7f\xab\xb8\x67\x82\x29\x2a\ +\x11\xa0\x9a\x11\x79\xc2\x5c\x1b\x03\x31\xf2\xb2\x68\xa7\xc1\x9f\ +\x05\xa7\x61\x57\xba\x94\xf7\xc5\x66\x61\x6c\x58\x2a\xb3\xd6\xc7\ +\x8a\x49\x11\xaf\xed\xf5\x8e\xb7\x6e\x16\x5c\x7b\xa9\x30\x90\xb0\ +\xba\xde\x6c\x56\x6c\xc7\x3b\xd8\xa4\x39\xb8\xe9\xb5\xd7\x14\x84\ +\x86\x27\xc1\x68\x25\xba\x8b\x8b\x40\x9c\xf8\xdd\x4a\x6c\xf7\x40\ +\x3c\x66\x59\xdf\x4f\x02\xd9\xf2\x96\xd1\x36\x5d\xa6\x4f\x3a\xb1\ +\xb8\x6a\xd0\x73\xbd\xd4\x55\x94\x44\x55\xb4\xc7\x44\x47\xa1\x01\ +\xeb\x4a\xe5\x6b\x93\xcc\xa7\xff\xbe\xfb\xb5\x07\x78\x1c\x4f\xff\ +\x53\x98\x87\x3d\x36\xad\x40\x34\x2b\xd6\x30\xec\x7e\xd9\xd9\x9b\ +\x8a\x78\x6a\x93\x4e\x54\xdd\xa6\x4b\x98\x69\x7b\xc1\xf4\xf7\xed\ +\x32\x03\x74\xf6\x8c\x03\x61\xfb\x3e\x7d\xdf\x69\xd3\xad\xd1\xcd\ +\x05\xd2\xe8\x9d\x5b\x12\x2f\x53\xab\xe4\x7f\xaa\xd2\x2c\xfb\xdd\ +\x1a\x19\x2c\xc4\xb6\xd3\xb4\xca\xf4\x6d\x6d\xb3\x79\xec\xbc\xf0\ +\x5b\x37\xba\x65\x34\xf0\xf2\xda\xef\xc2\x50\xb7\x16\xfb\xf0\xd4\ +\xc0\x21\xc7\x11\xce\xa2\x99\xce\x6e\xdc\x3f\x2c\xd3\x39\xe1\x2e\ +\x4c\xb1\x5e\x2d\x8b\x44\xb7\xea\x5d\x58\x17\xc3\x14\x36\x84\xa2\ +\xe3\x54\x27\x09\x1b\x23\x22\x29\xc0\x86\xb6\x89\xbb\x6b\x49\xc4\ +\x24\x16\x2a\x94\x13\x4f\x4a\x44\x70\x18\x62\x79\xb9\xcf\x7d\xab\ +\xa8\xba\x3f\xc9\x45\x7d\xce\x41\x82\x05\xe2\xaa\xcd\x4a\xb8\xfe\ +\x5c\xcd\x21\x92\x07\x8d\x41\x4a\xac\x9b\x66\x9d\xe9\x69\x5e\xe4\ +\x4f\xb0\xf6\x21\x87\x99\xe2\x41\xf7\xf2\x4d\xb3\x41\xf9\x34\x40\ +\x1c\x13\x21\x30\x55\x1d\xdd\x66\x2a\x08\xc9\x74\xb6\xae\xaa\x21\ +\xed\xbf\x45\x9a\x4f\x61\x2a\xb5\xe9\xa8\x75\x23\x03\xbc\x56\x53\ +\xde\xd1\xf6\xe3\x68\x09\x49\x04\xc9\xc3\x98\x68\x67\x87\xa3\x87\ +\xd4\x26\x81\x42\x52\x5d\x46\xe6\x41\x9b\x86\xff\x98\x96\xe9\x2c\ +\xcd\x6c\x17\xf5\x63\xa6\xaf\x92\xb4\x5c\xc1\x9c\x4c\xd3\xdc\x0e\ +\xe3\xaa\x78\xd4\x66\x9e\x15\x9b\x9e\xaf\xf3\x08\xbe\xbc\x59\x14\ +\x3f\xd8\x59\xcc\x93\x69\x14\x43\x22\x58\x67\x51\xa5\x07\xb9\xd9\ +\xae\x1b\xc7\x23\x02\x29\xce\x99\xe4\x13\x2e\x24\xc2\x3c\x94\xa1\ +\x83\x27\x8c\x60\x14\x10\xac\x88\x83\x91\x92\x2c\xe0\x6c\x82\x1d\ +\x1e\x22\x16\x28\x45\x61\xe3\x75\x28\x08\x48\x20\xd3\x00\x1a\xb1\ +\xa3\x10\xcc\x26\xe1\x13\xc2\x90\xc2\x98\x10\x07\x92\x99\x54\x94\ +\xa9\x09\x25\x48\x32\x86\xa9\xc3\x39\x22\x4c\x71\x31\x21\x21\x22\ +\x24\x64\x81\x43\x19\x12\x21\x91\x62\xe2\x71\xc8\x97\x98\x33\x87\ +\x85\x48\x85\x3c\x54\x13\x8f\x86\x08\x87\x8c\x38\x76\xcb\xc5\x0a\ +\xac\x78\x82\xc2\xe8\x28\xe1\x0e\x48\xcb\x40\x48\x0a\x42\x60\x4d\ +\x28\x0c\x24\x1a\x20\x19\x2a\x41\x26\x1e\x53\x88\x73\x41\x1d\x4f\ +\x10\x44\x03\x42\x00\x62\xd0\x87\x54\x3c\x08\xc0\x59\x0a\xa6\x03\ +\x09\xa3\x02\x21\x82\x25\x28\x12\xa4\x82\x80\x04\x13\x85\xa4\xe4\ +\xe0\xbb\xb5\x4c\x38\x61\x64\x42\xa0\x27\x19\x48\xea\x64\x40\xc4\ +\xca\xc6\x43\x04\xd6\x5d\x0c\x96\x25\x41\x42\x28\xa5\x60\x34\x0a\ +\x8a\x02\x26\xa5\xe5\x3c\x1d\x6d\x7d\x06\xf6\x7e\x30\x4c\x06\x47\ +\xcd\x83\xe2\x20\x07\x64\x55\x85\xf1\x20\xc3\x3f\x46\xd5\xda\x68\ +\x9b\x24\x07\x9b\xf2\xe8\x42\x18\x43\x7e\xbb\x39\xbf\x23\xff\x3b\ +\x90\x0f\x89\x87\x2b\x4a\xe9\x84\x53\x98\x7c\x01\x30\x1f\x05\xbe\ +\x18\x20\xbf\x6e\x50\x49\x11\x20\x5a\x05\xa2\xc1\x02\x00\x80\x08\ +\xc0\x28\xa0\xe4\x88\xf3\x9d\x28\xf9\xff\x30\xb2\x18\xd1\xd2\xdb\ +\x55\x61\x2a\x6f\x97\xac\x52\xd8\x93\x11\x0e\x28\x81\xc5\x31\xd6\ +\x7f\x2b\xb9\x7d\xb5\x24\x60\x4a\x37\xff\x3b\xe0\xdf\x17\x4b\xed\ +\xef\x0a\x93\x3e\xf8\x77\x6d\xa5\x51\xfa\x7f\x44\x33\xff\xce\x44\ +\xf3\xca\x4f\x61\xec\x65\x5d\xe7\xa1\x55\xbe\x18\x74\x79\xba\x4f\ +\x78\x18\x85\x81\x82\x05\x4f\xa5\xdd\x25\x82\xc0\xee\x08\x90\x05\ +\xec\x33\xcc\x4e\x28\x89\x7d\x0e\xa1\x38\x12\xb0\x12\x27\xb0\x0c\ +\x21\x97\x70\xbb\x46\xa9\x14\x00\x5b\x21\x2e\x8f\x62\xba\x80\x3a\ +\x6a\x58\xf8\xf6\x05\xed\x00\xf0\xb0\xd0\x15\x13\x3c\xa0\xe2\x5b\ +\x30\x3e\x44\xed\xb0\x52\x38\x5c\x9d\x27\x57\xec\x91\x89\xdd\x03\ +\x76\x33\x84\x6e\xab\x9a\xc1\xb1\xe5\xc7\x16\xec\xe9\xf8\x7f\xd6\ +\x05\xdb\xde\xfc\x43\xbc\x61\x5a\xa9\x3b\x1a\x74\x5b\x5f\x13\x05\ +\xc0\x80\x9a\x44\x3c\x23\x62\x0f\x76\x02\x8e\x7b\x10\xb7\x71\x09\ +\x63\x8b\xf4\x10\x89\x80\xf0\xe7\x24\x76\xcf\x48\xd4\x49\x85\x72\ +\x01\xe9\x03\x46\x30\xe9\xec\xc0\xe6\x08\xc7\x54\x09\xa7\x54\x41\ +\x9b\xfd\x26\xe0\x12\xf6\x9b\xae\x0f\x48\x0d\xed\xd3\x80\xd4\xc9\ +\x43\xb2\xd8\xb3\x7b\xdd\x21\xad\xd7\xa9\xd3\x4d\x6b\xa5\x37\xb2\ +\x67\x8f\x68\x0c\x8c\xf4\xdc\xde\xc4\xe9\xa0\x9e\x0e\x8b\xd4\x1f\ +\x00\x3f\xd4\xc2\x1f\x3f\x9c\xbe\x29\xb8\x3c\x5e\x0d\x2d\xf6\xeb\ +\x65\xf7\x0c\x16\xf8\xf3\x58\x38\x3d\xd7\x9f\x62\xe1\xe4\x90\x7f\ +\x02\x86\xfd\x91\xff\x59\x34\xd8\x2a\x44\x11\x42\xc7\xe0\x20\x60\ +\x67\x81\xad\x81\x4c\x7a\x53\x35\x1e\xa0\x4c\xa2\x5c\x01\x38\x6c\ +\xf9\xc5\x02\x09\x85\x70\xdb\x0b\x90\x5a\x93\x6a\x40\x82\x92\x49\ +\x49\xc8\x8e\x16\x0f\x3d\xdb\xb3\x5b\x15\x27\x74\x48\xea\x55\x00\ +\x0e\xbd\x91\xd6\x46\xd0\xb3\xa9\x73\xa2\x41\x9d\xd6\x86\x2d\xf4\ +\x7a\x6e\x63\x81\x28\xe7\x78\x4c\xf4\x60\x13\x1b\x2f\xfd\x43\x41\ +\xa0\xee\x63\x36\x73\xc3\x91\x17\x4a\x36\xa8\x1b\x07\x4f\x3d\x9b\ +\x41\xd5\x27\x15\x54\x8b\x80\x3e\x6e\x53\x1a\x0d\x2f\x87\x1b\x9c\ +\xbf\xe8\x0e\x3b\x8b\xe6\x98\x03\x5f\xd7\xf6\x58\x76\x7b\xf1\x3f\ +\xca\x4d\x58\x0d\ \x00\x00\x0b\x6e\ \x00\ \x00\x2d\x39\x78\x9c\xed\x5a\x6d\x6f\xdb\xc8\x11\xfe\x9e\x5f\xc1\ @@ -28979,6 +30249,212 @@ qt_resource_data = "\ \x4b\x1e\x8f\xd8\x68\x55\x45\xac\x6f\x07\xcf\x23\x0b\x77\x08\x41\ \x2b\x25\x81\x15\x65\xa4\x15\xe6\xcb\xe5\xdb\xc5\x74\x15\xef\xe2\ \xf1\x75\x41\xbf\x1d\xbc\x7e\xf1\x1f\x62\x9b\x4c\x39\ +\x00\x00\x0c\xb1\ +\x00\ +\x00\x4d\x5e\x78\x9c\xed\x5b\x5b\x6f\xdb\x56\x12\x7e\xcf\xaf\xe0\ +\x2a\x2f\x0d\x96\xa4\xce\xfd\xa2\xd8\xe9\x43\x83\x2e\x0a\x14\x58\ +\x60\xdb\x62\x1f\x0b\x5a\xa2\x65\x6e\x24\x51\xa0\x28\x5f\xf2\xeb\ +\xf7\x1b\xde\x44\x59\x54\xe2\x38\xa9\xda\xa4\x52\x10\x9b\x9c\x33\ +\xe7\xcc\x9c\x99\x6f\x2e\x87\xa2\x2f\xbe\xbf\x5f\x2e\x82\xdb\xb4\ +\xd8\x64\xf9\xea\x72\xc4\x63\x36\x0a\xd2\xd5\x34\x9f\x65\xab\xf9\ +\xe5\xe8\xb7\x5f\x7f\x8c\xdc\x28\xd8\x94\xc9\x6a\x96\x2c\xf2\x55\ +\x7a\x39\x5a\xe5\xa3\xef\xdf\xbc\xb8\xf8\x47\x14\x05\x3f\x14\x69\ +\x52\xa6\xb3\xe0\x2e\x2b\x6f\x82\x9f\x56\xef\x36\xd3\x64\x9d\x06\ +\xdf\xdd\x94\xe5\x7a\x32\x1e\xdf\xdd\xdd\xc5\x59\x43\x8c\xf3\x62\ +\x3e\x7e\x15\x44\xd1\x9b\x17\x2f\x2e\x36\xb7\xf3\x17\x41\x10\x40\ +\xee\x6a\x33\x99\x4d\x2f\x47\xcd\x84\xf5\xb6\x58\x54\x8c\xb3\xe9\ +\x38\x5d\xa4\xcb\x74\x55\x6e\xc6\x3c\xe6\xe3\xd1\x8e\x7d\xba\x63\ +\x9f\x92\xf4\xec\x36\x9d\xe6\xcb\x65\xbe\xda\x54\x33\x57\x9b\x97\ +\x3d\xe6\x62\x76\xdd\x71\x93\x36\x77\xb2\x62\xe2\xde\xfb\x31\x13\ +\x63\x21\x22\x70\x44\x9b\x87\x55\x99\xdc\x47\xfb\x53\xa1\xe3\xd0\ +\x54\xc1\x18\x1b\x63\x6c\xc7\xf9\x34\xae\xc9\xfd\x02\xa6\x38\xaa\ +\x4c\x35\xda\x97\x0e\xf3\xaf\xf1\xbf\x9b\xd0\x12\xe2\x4d\xbe\x2d\ +\xa6\xe9\x35\x66\xa6\xf1\x2a\x2d\xc7\x6f\x7f\x7d\xdb\x0d\x46\x2c\ +\x9e\x95\xb3\xde\x32\xad\xf5\xf7\xe4\xee\xb9\x64\x95\x2c\xd3\xcd\ +\x3a\x99\xa6\x9b\x71\x4b\xaf\xe6\xdf\x65\xb3\xf2\xe6\x72\x64\xd4\ +\xfa\xbe\xba\xbf\x49\xb3\xf9\x4d\xd9\x23\x64\xb3\xcb\x11\x76\x28\ +\xac\x30\xd5\x7d\xab\xc3\xa4\x43\x12\x8b\xa5\xa8\x59\x9b\x85\xfb\ +\x43\xca\xc5\x3c\x28\xbc\x35\x6c\x7f\xf6\x2c\x9f\x92\x4a\x97\xa3\ +\x5f\x56\xc9\xfa\xf7\x1f\x80\x80\xb4\x88\x5b\x4b\x76\x0b\xe5\xdb\ +\x72\xbd\x2d\x7f\x4f\xef\xcb\x74\x55\xaf\x88\xbd\xf4\x36\x56\x0d\ +\xd3\xb4\x78\x6f\x53\x3d\x90\xf3\xd1\x1b\x50\x2e\x66\xe9\xf5\x86\ +\x46\xea\xfd\xd0\x1d\x36\xe4\xaa\x31\x8c\xc2\x29\x69\x52\xfc\xab\ +\x48\x66\x19\x14\xa9\xf9\x7a\x5a\x4c\xf3\xc5\x22\x9d\xc2\x28\xc9\ +\xe2\x2e\x79\xd8\x8c\x3a\x06\x2c\xb5\x3f\x55\x72\xa5\x9a\x45\xb1\ +\xec\xa6\xcc\xd7\x2d\x2f\xb6\x5e\x3e\x2c\xb0\x5f\x22\x46\x58\x31\ +\x2f\x26\x2f\xaf\xab\xcf\xeb\x8a\x94\xc3\x39\x59\xf9\x30\xe1\xaf\ +\x47\xbb\x39\xf9\xf5\xf5\x26\x85\x60\xd6\xa3\x55\x0e\xc1\x0c\xc8\ +\x32\xa3\x60\xfc\x79\xd2\xd8\x90\x34\x3e\x2c\xcd\x75\xd2\x2e\xc6\ +\xfb\xdb\x6e\xa8\x9d\xc1\xd6\xb0\xff\x1a\x16\x43\xcc\xb6\x2b\x75\ +\x8e\x2f\x1f\x08\xa6\xfb\xac\x72\x36\x3a\x30\xfa\xed\xfa\xf7\x7b\ +\x6c\x3c\x98\x04\x52\xe0\x07\x1f\xe4\x78\xa8\x39\x38\xc2\x10\xbf\ +\xd8\x20\xcf\x7b\x02\xf3\x07\x96\x69\x34\x88\xf2\x22\x9b\x67\xc0\ +\x4c\xc5\x27\x78\x2c\xab\xcf\xfe\x1c\x18\xa3\xb7\x37\x61\xa5\xda\ +\xd9\x84\x6c\x91\x2c\x3e\x19\x44\x55\x46\x98\xdc\x14\x29\x32\xd8\ +\xcb\x01\x34\xf5\x65\xef\x8b\x90\x4e\xef\x76\x3c\x6f\x88\xbf\xad\ +\xb2\x12\xa9\x6a\xbb\x49\x8b\x5f\x28\xdc\xff\xbd\xfa\x6d\x93\x1e\ +\x70\xfd\x5a\x24\xab\x0d\x72\xcb\xf2\x72\xb4\x4c\xca\x22\xbb\xff\ +\x8e\x87\x8c\xfe\xc5\xc6\x3b\x2d\xbc\xc2\xb5\x60\x22\x76\xc2\x19\ +\xf9\xaa\x9b\x3e\x85\x47\x84\xd0\xb1\x30\x8a\x89\x1d\x15\x5e\x30\ +\x56\xc4\xd6\x5b\x69\x3a\xea\xf5\x20\xef\xf5\x20\x6f\x01\xab\xab\ +\x58\x2a\xcd\x9d\xfb\xa3\x0d\x1a\xd9\x8f\x98\x34\x12\xdf\xb2\x51\ +\xbf\x68\xaa\x83\x2d\x4f\x98\xec\x22\x75\xda\x74\xd7\x93\x77\x24\ +\xe1\xfd\x41\x08\xd5\x1f\x43\xa8\x3d\x23\xf4\xa9\x08\xd5\x27\x45\ +\xe8\x89\x0b\x32\x76\xf7\x2c\x84\xee\x19\xfe\xc3\x3e\x1a\xf6\xe7\ +\xb0\xef\x87\x71\xf2\x99\xe0\x7b\x1a\xc2\x0f\x03\x45\x69\xc6\x9f\ +\x13\x71\xc7\x70\xf6\x47\x97\x25\xf9\xd1\xa0\xff\xa6\x8b\xfd\x97\ +\x8d\x7a\x79\xd2\xa8\x17\x27\x8e\x7a\x79\x8e\xfa\x9d\x55\x0e\xa3\ +\x3e\x72\xcf\x09\xba\x3f\x2b\xee\xf9\xc7\xe2\x5e\x9f\xc3\xfe\xa9\ +\x61\xcf\x4f\x1a\xf6\xfa\xc4\x61\xcf\xcf\x61\xbf\xb3\xca\x40\xd8\ +\x3f\xbd\xdc\x0f\x3c\x05\x38\x75\xd8\xfb\x8f\x85\xbd\x3c\x87\xfd\ +\x53\xc3\xde\x9f\x34\xec\xfd\xa9\xc3\x5e\x9c\xe3\x7e\x67\x96\xc7\ +\x71\xef\xe4\x73\x42\xee\x99\x51\xff\xf7\x30\x29\xa5\xd2\xc8\x3c\ +\x3d\x99\x7e\x52\x17\xf5\x85\x0b\xfe\x89\x3b\x7d\x7d\xf2\x67\x50\ +\x3c\x3a\x87\xff\x87\xb1\xea\x22\xf6\x64\xac\xca\x4f\x3a\xe9\x7f\ +\xe1\x33\xe9\x89\x9f\x45\x89\x93\x57\x2a\xf9\xdc\x27\xa6\x7f\x1b\ +\xac\xaa\x27\x23\x55\x7f\x52\xb9\xfa\xc2\xcf\x4c\x4f\xdc\x51\x99\ +\xde\xd1\xe6\x44\xcf\x4d\x7b\xb1\x71\xda\x67\xfb\xf2\x63\xdf\xe8\ +\xf5\xfc\x7e\x6e\xfc\x3f\x96\x52\x4f\xfa\x65\xfb\xc9\x51\xfa\xe1\ +\xca\x7f\x31\xa6\xd7\x18\xaa\xab\xee\xcb\x75\x7a\xa5\x62\x76\x9b\ +\xa5\x77\x2f\xba\xd5\xae\x92\x0e\x2b\xeb\x64\x9e\x56\xca\x01\x9a\ +\xb5\x76\xcd\xc0\x55\x5e\xcc\xd2\xa2\x1d\x32\xd5\x67\x6f\xa8\xd1\ +\xbf\x7e\x6b\xe8\xc5\xbe\xcf\x68\xd5\x6e\x9c\x0d\x8f\x6f\x6e\x92\ +\x59\x7e\x07\xf0\x3c\x1e\x7c\x9f\xe7\xc0\xab\x8c\x9d\xf3\xcc\x59\ +\xf9\x78\xb8\x02\xa7\x8b\x39\xb7\x5c\x98\x83\x41\xc8\xd3\x32\x36\ +\x46\x5b\x7b\x38\xb8\x2d\x0a\x18\x2a\x5a\x24\x0f\x29\x36\x35\x57\ +\xc2\xb5\x81\xb5\xb9\xc9\xef\xe6\x05\xd9\xa6\x2c\xb6\xe9\xe3\x89\ +\xb3\x7c\xba\xa5\x17\x92\xa2\x6d\x1d\x75\xcd\x6b\x30\x3d\x0e\x9a\ +\x1b\x5d\x5d\xe5\xf7\xc3\x0b\xdc\x65\x2b\xec\x35\x6a\x5e\xac\xe1\ +\xc2\x1d\x58\xa4\xe1\x68\x5f\xb5\xb1\x5a\x1f\xe1\xb8\xdf\x81\xf1\ +\xf1\xd0\x03\x45\xe2\x91\xb1\x65\x72\x9f\x2d\xb3\xf7\xe9\x8c\xb0\ +\x55\x43\xe8\x62\x99\x96\xc9\x2c\x29\x93\x1d\x30\x5a\x8a\xb0\xb2\ +\x7d\x6e\x76\x51\xcc\xae\x27\xff\x79\xfb\x63\x07\xf2\xe9\x74\xf2\ +\xdf\xbc\x78\xb7\xc3\x27\x31\x24\x57\xf9\x16\x6a\x77\xa1\x47\xaf\ +\xd7\x4c\x27\x94\x79\x92\xf2\x4d\xb6\x84\xbb\xe9\x95\xa8\x7f\xde\ +\x2f\x17\x80\x68\x37\xb0\xc7\x4c\x2f\x81\xec\x16\xad\x97\x2d\xd2\ +\xfa\x95\xa7\xc1\xb7\xc4\x66\xd3\x65\x46\x93\xc6\xbf\x94\xd9\x62\ +\xf1\x13\x09\xe9\x05\x63\xb3\x68\x56\x2e\xd2\x37\x95\xcc\xfa\xb2\ +\xdd\xc5\xb8\xd9\x46\x1b\x4b\xbd\x5d\x5e\x8c\x5b\x33\x54\x77\xf3\ +\x9d\x79\x2a\xe0\xf0\xc7\x16\x5e\x24\x57\xe9\xe2\x72\xf4\x33\x0d\ +\x06\x07\xa3\xf3\x22\xdf\xae\x97\xf9\x2c\x6d\xa6\xb7\x66\x9d\xf7\ +\xf3\x58\x1f\x8a\x41\x50\x1e\x64\x6d\x16\x73\x23\x00\x1b\xd1\x64\ +\xef\xf6\xce\xc4\xd2\x30\xed\x9d\x09\x23\x63\x62\xce\x9c\x63\xe6\ +\xd5\x2e\xff\xad\x93\xf2\xe6\x20\x1f\x75\x79\x27\xd6\x5c\xe8\xd7\ +\x4d\x66\x62\xd5\xe7\xf5\x35\x2c\xb9\x77\xd3\x4b\x8b\xd5\x6d\xb1\ +\x5d\xa4\x93\x55\xbe\x7a\x8f\x04\x80\x3c\x56\xe4\xef\xd2\x8e\xbf\ +\xbe\xad\x51\x3e\xd1\xb1\xb6\x42\x09\xa9\x4c\x4b\xa7\x74\x05\x93\ +\x4c\xae\xb6\x65\xd9\xa7\xfd\x2f\xcf\x56\x13\xb8\x32\x2d\x5a\x6a\ +\x75\xb3\x00\x5e\xcb\x89\x6a\x69\x3b\x3d\x1a\xc2\x2c\x41\x06\x29\ +\x8a\xe4\x81\xd4\x49\xfb\xd4\x3a\x89\x22\xb1\x2e\x93\xe2\x5d\x5a\ +\xd4\xe3\xb7\xd9\x26\xbb\xca\x16\xb4\x44\x75\xb9\x48\x5f\xcf\xb2\ +\xcd\x1a\x3e\x99\x64\x2b\x52\xe3\x75\x7e\x9b\x16\xd7\x8b\xfc\xae\ +\x1b\x4f\x57\x09\x7e\x45\x57\xc9\xf4\x1d\x79\x71\x35\x9b\x24\x53\ +\x24\x82\xed\x22\x29\xd3\x5e\x7e\xa6\xb8\x09\xb8\xb6\xb1\xf6\x4c\ +\x89\x50\x29\x16\x3b\xa9\x85\x0b\xa6\x41\x84\xd2\xea\x61\x83\x30\ +\x42\x12\xe4\xd6\x07\x91\x8e\x9d\x65\x5e\x90\x0f\xc1\xa2\x82\xc8\ +\xc5\x8e\xa3\xf8\x82\x60\x15\xd2\x56\x10\x71\x1b\x0b\xeb\x98\x0b\ +\x65\xac\xe0\xce\x20\x92\x34\x97\x69\x1d\x62\x84\x19\xc6\x1d\x48\ +\xc8\x8e\x4c\x59\x19\xe2\x42\x71\xa1\x64\x10\x29\x1b\x73\xf4\x0a\ +\xd2\x84\x5c\xc6\xde\x08\x03\x61\x4e\xc5\x4a\x7a\xe7\x5c\xa8\x91\ +\xa4\x1d\x07\x9b\xf7\xf0\x8b\x65\xcc\x87\xde\xc5\xd2\x32\xcb\xa1\ +\x24\x8b\xa5\x14\x46\x1b\x1d\x42\x82\xf4\x0a\x5a\x48\x11\x7b\x2d\ +\xac\x16\x21\x72\xad\xe0\x56\x43\x55\x5c\x19\xc0\x4d\x62\x39\x06\ +\x1a\xf7\x3e\xc0\xfe\xd0\x3b\x08\x1e\x72\x15\x5b\x2b\xa4\x0c\x38\ +\x8a\x3e\x14\xb2\xd8\x5c\x28\x4c\xac\x99\x75\x3a\x40\x7f\x20\xb5\ +\xd4\x1a\x0a\x0b\xc0\x54\x3b\x4e\x7c\xd2\x2a\x67\xb0\x98\x88\x85\ +\x30\x46\x05\x50\x52\x39\x6d\x3c\x0f\xbd\x8c\x2d\x93\x0e\xab\x31\ +\x1e\x5b\xc7\x8d\x56\x21\x67\x9e\xec\xa0\x78\xa0\x63\xe3\x0c\xf7\ +\xa1\x10\x30\xb9\x10\x22\x10\x36\x46\x9b\xa1\x60\x32\xb2\x90\x57\ +\x36\x80\x82\x1a\xda\x78\x92\xa7\xac\xc7\xce\xb9\x81\x81\xb5\x10\ +\x61\x24\x21\x58\x0a\x1b\x08\x0f\xb9\x52\xb8\x30\xc2\x98\xd0\xc2\ +\xd8\x80\xcc\x09\xd5\x3d\x98\x78\xec\xb9\xe7\x3a\x50\x3e\x36\x9a\ +\x3c\x88\x1d\x6a\xae\xb1\x67\xe7\xa0\x9c\x22\x26\x0d\x12\xba\x1c\ +\x6c\x06\x3d\x14\x4c\xe8\x24\xd8\x18\x7a\x21\x6b\x39\xd6\x47\x97\ +\xe5\xa4\xe4\x88\x4d\x34\x58\x52\x39\x5a\x5e\x2b\x8d\xb8\x25\x53\ +\x4a\x6b\x84\xae\x94\x40\x29\xc3\x5a\xd0\x18\xee\x13\x30\x3d\x7a\ +\x29\x2b\x2b\xad\xac\x12\x64\x78\xae\xe1\x65\xed\xc1\x05\x76\xc9\ +\xac\x10\x15\x2a\x94\xb7\x56\x87\x04\x06\xd8\xd8\xda\xa0\x56\x11\ +\x99\x21\x24\x34\x38\xe1\x3d\x01\x8e\x13\xe2\x48\xa6\x83\xdd\xac\ +\x61\x35\x08\x98\xd0\x8e\x36\xc5\xe0\x49\x98\x03\x28\x00\x56\xbc\ +\xe1\xa0\x11\x1c\xac\x74\x90\x01\x03\xc3\xac\x0c\x34\xb4\x6d\x8a\ +\x39\x0f\x34\x2a\x78\x4b\xc3\xec\x15\x0d\xfa\xc2\x1f\xef\x83\x25\ +\xf4\x31\xb4\x23\xac\x69\xb0\x23\x8d\x56\x05\xf0\x07\xd6\xa4\xb5\ +\x96\xc0\x01\x8c\x6b\xc0\x85\x2c\x01\x5a\x28\xa0\x95\xd2\xd2\x07\ +\x0a\x0b\x03\x53\x2e\xe4\x80\x99\xa7\x88\xe0\x40\x81\x76\x1e\x6e\ +\x81\x74\xe6\xa4\x21\x43\x7a\x02\x01\xb6\x00\xa7\x30\xb2\x1a\xc0\ +\xee\x19\x56\xa6\x68\x81\x9f\x34\x0f\x24\x75\xb1\xcc\x02\xfe\x1c\ +\x6e\x15\x46\x06\x1a\xbb\x34\x5a\xd7\xa8\x00\xfc\x6c\x60\xb1\x10\ +\x37\x4a\x93\x8e\xde\x3b\x2e\x2a\x93\x01\xef\x48\xa0\x1e\x9e\x77\ +\x80\x6a\x24\x80\x01\x63\xb0\x36\x84\x68\xc9\x34\xd9\xd5\x43\x5b\ +\xa0\x21\x54\x94\x64\x35\xc2\x0d\xc8\x53\xd8\x3b\xc5\x1a\x93\x02\ +\x21\xc9\x19\xcd\x47\x68\x60\x3a\x9c\xaf\x6a\xad\x15\xfc\x17\xc2\ +\x67\xd8\xbc\xa3\x75\xa0\x9a\xf3\xb0\x31\x4c\x67\x80\x45\x8a\x64\ +\x6c\xdb\x72\xc3\x43\x23\x62\xc4\x38\x9c\x8d\xae\x59\x3a\x23\x64\ +\x68\x09\x2d\xc0\x72\x04\x9f\x23\x9e\x5d\x05\x41\x40\x52\x93\x67\ +\x4c\xec\x99\x70\x84\x08\xc0\x45\x59\x85\x89\x4a\x23\x3e\x38\x21\ +\x02\xfa\x02\xa8\x34\x15\x51\x86\x84\x81\x48\x8c\x95\xe0\x94\x4c\ +\x60\x78\x8f\x06\x1c\xdb\xc5\x06\xaa\xed\xa2\x95\x62\x1e\x2e\xe1\ +\x14\x0e\x00\x40\x95\x5d\x3c\x42\xd8\x90\x79\x39\xb5\x61\x64\x03\ +\x03\x34\x63\x75\x04\x59\x24\x11\x12\xdc\x1a\xac\x66\xe1\x2b\x60\ +\x4a\x02\x0d\x16\x8e\xb4\xb0\x83\xc5\xd1\xc2\x38\x4e\xbe\x42\x51\ +\x43\x00\x51\xfe\xa0\x30\x73\x35\xea\x11\xa6\x81\x50\x04\x11\x48\ +\x03\x50\x11\x4c\x9c\x6c\x03\x8b\x6a\xaa\x17\x90\x09\x9b\x5a\x2f\ +\x80\x5d\x18\x15\x49\x49\xd1\x6a\x82\x8c\xc1\xaa\x2c\xc4\x63\x2e\ +\x2c\x32\x5c\x15\x0d\x06\x9c\x94\x4b\xe0\x29\x21\x75\x15\xb7\x8a\ +\xc2\x9d\xec\xca\x94\x87\x43\x22\x6d\x60\x03\xa0\x8e\xdc\xcf\xa1\ +\x91\x75\x55\xb5\x34\x80\xb8\x08\xde\x3f\x6a\xb4\xa9\x64\x62\xeb\ +\xfd\xd7\x3f\xf6\xce\x22\x2b\xd4\xb0\x32\x2f\x22\xf4\x92\xb7\x49\ +\xb9\x2d\x52\x6a\xc7\x7a\x47\x80\xc1\x92\x3b\x54\x63\x9b\xa3\xc0\ +\xb9\xc6\x7e\x4a\x8d\xa5\x42\x25\xb5\x45\x8d\x95\x14\xb6\x9c\x4a\ +\xac\x43\x45\xe1\x1e\xa5\x33\x64\x14\xce\xa8\x51\xd5\x9d\x0f\x0d\ +\xaa\x02\xc2\x4d\xec\x53\x39\x12\x22\xda\x27\x54\x20\x16\x3a\x4a\ +\xf7\xd2\xf3\xc0\x50\xa1\xa2\x0f\x8d\xb3\x2a\x37\xd8\x60\x7f\x56\ +\x4b\x6d\xc5\x41\x1a\x31\x20\x2f\x59\x20\x11\xb2\xb4\x51\xc2\xf4\ +\x69\xbb\x39\x0c\xd1\x50\x89\x72\x00\x35\x41\xcf\x08\x66\x88\xa1\ +\x55\x25\xda\x9b\xd6\x52\x29\xaf\xb2\x50\xa2\x9e\x50\x66\xc1\x5e\ +\x91\x23\xbc\x65\x88\x4b\xc8\x46\x2e\x60\x1e\x59\x89\x4a\x3b\x4c\ +\xe1\x5d\x8f\xc4\x51\x30\x10\xc1\xc8\x53\x2c\x34\x92\x92\x27\xe5\ +\x02\x5d\x05\x8e\x55\xd5\xb0\x45\x39\x71\x94\x91\xfa\x73\x1a\x62\ +\x23\x06\xd5\x8c\x2c\x4a\xed\x84\x34\x12\x9d\x0d\xad\x00\x25\xa9\ +\x58\xf4\xa9\xbb\x99\xd8\x67\x23\x4e\x53\x05\xf6\xd4\x52\xf8\x9a\ +\xa1\x56\xe7\xf1\xb4\x9a\x7a\x2c\x06\x9f\x17\x81\xf3\x81\x59\xe9\ +\xfd\x3a\x2f\xca\xe8\x61\xb6\xce\x70\xb6\x42\x7a\x11\x54\x33\x86\ +\xd6\x6f\x38\xef\x9f\xcc\x89\x88\x4d\xeb\xbf\x5a\x18\xdf\xe4\xcb\ +\x74\xfc\x90\x17\xd9\xbb\xf1\xdb\xe6\xc4\xb8\x19\xff\x9c\x5c\x8d\ +\xdf\x16\xc9\x75\x39\xce\xa0\xfb\xa6\x3a\xb4\xc7\xeb\xd5\xbc\xb7\ +\xe4\x61\xbf\x8f\x76\xd1\x59\x9c\x7e\xd1\x95\x51\xa7\x88\x86\x0d\ +\x9d\xbd\xa7\x2e\x12\x19\x58\xa0\xdf\xe7\x74\xed\xbc\x44\x13\x09\ +\x3a\x32\x39\xb2\x1e\x55\x1f\xf4\x4b\x28\xe8\x9e\x4e\x01\xfb\x36\ +\x9d\x4b\x6e\x58\xff\x78\xb6\x9f\xa8\x0e\x5e\xc6\x4f\x8a\xe9\x68\ +\x6f\xb8\xce\x64\xed\xf9\xe0\x4a\x38\xf3\xb9\xb9\xcb\x55\x54\xee\ +\xbf\xf5\xdc\xb5\x03\x35\x7c\x20\x46\x83\x46\xa7\x87\x1a\xdc\xa3\ +\xab\x41\xcd\xd4\x47\x58\xe8\x91\x9a\x46\x32\xe0\x5e\x0e\x73\x14\ +\x58\x04\x79\x44\x5b\xae\x8e\x71\x3c\x1c\xe1\xa8\xf2\xab\x40\x07\ +\x61\x49\x83\xb0\x95\x83\x9c\xc3\xc2\xba\x69\x13\x75\xf3\x80\xce\ +\x06\xdd\x6a\xbb\x46\x10\xb5\x57\x3d\x52\xcb\x4f\xd9\xa3\x1b\xee\ +\xe6\xf6\x69\xdd\x1c\x24\x8e\x4e\x4a\x27\x64\x37\x3c\x30\xa3\x27\ +\xa4\x1b\xed\x44\x1c\x2a\xf5\x7e\xff\xc9\xc0\x67\x80\x7f\x5b\x2c\ +\xbe\x7b\x79\xf8\x88\xf6\xd5\xe3\x68\x68\xb0\x4f\xd8\x3a\x86\x05\ +\x75\x1c\x0b\x87\x4f\x54\x0f\xb1\x70\xf0\x78\xf5\x00\x0c\x87\x5f\ +\xa0\x1c\xa0\x01\x7d\x95\xf7\x9c\x8b\x21\x38\xa0\x81\x36\x38\xab\ +\xa2\x37\x6d\x45\x55\x78\xe0\xd4\x71\x7a\x80\x83\xce\x25\xd4\xf3\ +\x9b\xb0\x59\x05\xa4\x46\xa4\xef\x91\xd0\xd9\xa3\x23\x44\x8f\xc8\ +\x7a\xc3\xd4\xdb\x59\x45\x1d\xf8\x8e\xd4\x4d\x61\x55\x13\x58\x0b\ +\x69\x64\xd8\x6e\x58\x04\x07\x33\xd0\x01\xd6\x32\xa8\x62\x75\xa3\ +\xb5\x04\xee\x83\xc7\x3a\xed\x77\x7d\xc3\xcf\x5b\x9c\xe6\xd4\x51\ +\x52\x9a\x45\x5b\x6a\x70\xfe\x0d\xfb\x57\xdd\x30\x6a\x3a\x35\xbc\ +\x38\x0f\x09\x3a\xe5\x78\x34\xba\xaf\xfa\xd5\x68\x3c\xff\x3b\x17\ +\x26\x09\x1f\xe0\x2c\xcb\x70\xba\xe0\x8a\xfe\x26\xd0\xb8\xc1\xc2\ +\xd4\xfb\xa3\x91\x73\x69\xfa\xd3\x4a\x53\x74\x24\x95\x9c\x8b\xd3\ +\x57\x5c\x9c\xe8\x3b\xe6\x67\x15\xa7\xde\x97\x8e\x07\x68\x38\x97\ +\xa7\x73\x79\x1a\xe4\xfc\xba\xca\x93\x92\x48\x6a\x96\x7b\x9c\x9b\ +\x84\x85\x8b\xb4\x3b\x52\x9e\xce\x27\xa7\xbf\x42\x79\x3a\x56\x7b\ +\xce\xe5\xe9\xeb\x2e\x4f\x91\x7b\x5e\x81\xfa\xc0\x59\xfa\x5c\xa0\ +\xce\x05\x6a\x90\xf3\xeb\x2a\x50\xda\x58\xfa\xba\xc6\xd3\xe3\x59\ +\x05\x8f\x72\x3d\x5c\x9f\xf4\xb9\x3e\xfd\x05\xea\xd3\x91\x34\x71\ +\xae\x4f\x5f\x7b\x7d\x7a\xee\x01\xea\x88\xa7\xce\x05\xea\x1b\x2c\ +\x50\xcd\x45\xf5\xeb\x82\x5e\x76\x7b\xf3\xe2\xff\xf6\xfc\x3b\x6e\ +\ \x00\x00\x0f\xd2\ \x00\ \x00\x52\x9a\x78\x9c\xe5\x5c\x5b\x6f\xe3\xb8\x15\x7e\x9f\x5f\xa1\ @@ -30164,6 +31640,147 @@ qt_resource_data = "\ \x74\x68\x69\x63\x20\x42\x6f\x6c\x64\x2c\x20\x42\x6f\x6c\x64\x27\ \x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\ \x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ +\x00\x00\x08\xa3\ +\x00\ +\x00\x2b\x7a\x78\x9c\xed\x5a\x5b\x6f\xdb\x38\x16\x7e\xcf\xaf\xd0\ +\xba\x2f\x0d\xd6\xa2\xc4\x3b\xe9\x26\x19\x2c\xb6\x98\xc5\x00\x03\ +\x2c\xb0\x6d\xb1\x8f\x85\x2c\xd1\x8e\x36\xb2\x64\x48\x72\x6c\xe7\ +\xd7\xef\xa1\x6e\x96\x22\xa5\xc9\xa6\x53\x0f\xd0\x8d\x8b\xd6\xd2\ +\xb9\x92\x87\xdf\x39\x87\x34\x7b\xf5\xcb\x61\x93\x38\xf7\x26\x2f\ +\xe2\x2c\xbd\x9e\x61\xe4\xcf\x1c\x93\x86\x59\x14\xa7\xeb\xeb\xd9\ +\x97\xcf\xbf\xba\x6a\xe6\x14\x65\x90\x46\x41\x92\xa5\xe6\x7a\x96\ +\x66\xb3\x5f\x6e\x2e\xae\xfe\xe2\xba\xce\xdf\x73\x13\x94\x26\x72\ +\xf6\x71\x79\xeb\xfc\x96\xde\x15\x61\xb0\x35\xce\xfb\xdb\xb2\xdc\ +\x2e\x3c\x6f\xbf\xdf\xa3\xb8\x21\xa2\x2c\x5f\x7b\x97\x8e\xeb\xde\ +\x5c\x5c\x5c\x15\xf7\xeb\x0b\xc7\x71\xc0\x6f\x5a\x2c\xa2\xf0\x7a\ +\xd6\x28\x6c\x77\x79\x52\x09\x46\xa1\x67\x12\xb3\x31\x69\x59\x78\ +\x18\x61\x6f\x76\x12\x0f\x4f\xe2\xa1\xf5\x1e\xdf\x9b\x30\xdb\x6c\ +\xb2\xb4\xa8\x34\xd3\xe2\x5d\x4f\x38\x8f\x56\x9d\xb4\x1d\xcd\x9e\ +\x56\x42\x58\x6b\xed\xf9\xc4\x23\xc4\x05\x09\xb7\x38\xa6\x65\x70\ +\x70\x87\xaa\x30\xc6\x29\x55\xe2\xfb\xbe\x07\xbc\x93\xe4\xcb\xa4\ +\x16\x87\x04\x42\xf1\xe4\x60\x2a\x6e\xdf\x3b\x84\x7f\x0b\x7f\x3b\ +\x85\x96\x80\x8a\x6c\x97\x87\x66\x05\x9a\x06\xa5\xa6\xf4\x3e\x7e\ +\xfe\xd8\x31\x5d\x1f\x45\x65\xd4\x33\xd3\x46\x7f\xe0\x77\xb0\x24\ +\x69\xb0\x31\xc5\x36\x08\x4d\xe1\xb5\xf4\x4a\x7f\x1f\x47\xe5\xed\ +\xf5\x4c\xb0\xed\xa1\x7a\xbf\x35\xf1\xfa\xb6\xec\x11\xe2\xe8\x7a\ +\x06\x33\x24\x92\x88\xea\xbd\x1d\xc3\xa2\x43\x92\x8f\x28\xa9\x45\ +\x1b\xc3\x7d\x16\x53\x08\x3b\xb9\x96\xc2\x1f\x6a\x47\x59\x68\x87\ +\x74\x3d\xfb\x94\x06\xdb\xaf\x7f\x4b\xd7\x89\x41\x6d\x20\x3b\x3b\ +\xd9\xae\xdc\xee\xca\xaf\xe6\x50\x9a\xb4\x36\x08\x53\xe9\xcd\xab\ +\x62\x5b\x35\x34\x98\x53\x0f\xe3\x78\x76\x03\x94\xab\xc8\xac\x0a\ +\xcb\xa9\xa7\x63\xdf\x60\x3e\xaa\xe2\x01\x17\xd6\xc4\x04\xf9\x3f\ +\xf2\x20\x8a\x01\x89\xb5\x5c\x6f\x14\x61\x96\x24\x26\x84\x98\x04\ +\xc9\x3e\x38\x16\xb3\x4e\x00\x4c\x0d\x55\x29\x66\xac\x31\x0a\x66\ +\x8b\x32\xdb\xb6\xb2\x30\xf3\xf2\x98\xc0\x74\x2d\xd1\x05\x8b\x59\ +\xbe\x78\xb7\xaa\x3e\x1f\x2a\x52\x06\x6b\x13\x97\xc7\x05\xfe\x30\ +\x3b\xe9\x64\xab\x55\x61\xc0\xb1\xdf\xa3\x55\xeb\x01\x1a\xe0\x4b\ +\xcc\x1c\xef\xfb\xbc\xf9\x53\xde\xf0\xb4\x37\xd5\x79\xbb\xf2\x86\ +\xd3\x6e\xa8\x5d\xc0\xb6\x10\xff\x2d\x44\x0c\x52\xb6\xb5\xd4\xad\ +\x7b\x79\xb4\x28\x1d\x8a\xd2\x68\x36\x0a\xfa\xfd\xf6\xeb\x01\x26\ +\xee\x2c\x1c\x4a\xe0\x1f\x3c\x29\x71\xac\x25\x30\x64\x21\x7c\xf9\ +\x93\x32\x0f\x16\xcb\xdf\x30\xd3\x8c\xc0\xcd\xf2\x78\x1d\x03\x66\ +\x2a\x39\x82\x11\xad\x3e\x43\x1d\x08\x46\x6f\x6e\x44\x52\x76\x8a\ +\x89\x8d\x45\x90\xfc\xcf\x20\xaa\x0a\xc2\xe2\x36\x37\x50\xc0\xde\ +\x4d\xa0\xa9\xef\x7b\xe8\x82\x2a\x7e\x9a\xf1\xba\x21\x7e\x49\xe3\ +\x12\x2a\xd5\xae\x30\xf9\x27\x9b\xed\xff\x4c\xbf\x14\x66\x24\xf5\ +\x39\x0f\xd2\x02\x4a\xcb\xe6\x7a\xb6\x09\xca\x3c\x3e\xbc\xc7\x73\ +\xdf\xfe\x41\x42\x2b\x4e\x34\x83\x67\xe2\x13\xa4\x88\x12\xf4\xb2\ +\x53\x0f\x61\x45\x08\xe1\x88\x08\xe6\x93\x13\x15\x56\x41\x48\x82\ +\xa4\x96\x54\x74\xd4\xd5\xa4\xec\x6a\x52\x36\x87\xa8\x33\x44\x19\ +\xc7\x4a\xfd\xe8\x80\xba\xf2\x99\x90\xba\xe4\x67\x0e\xea\x1f\x5a\ +\xea\x20\x96\x67\x2c\x76\x2e\x3b\x6f\xb9\xeb\xf9\x7b\xa2\xe0\xfd\ +\x20\x84\xf2\xe7\x10\x2a\xdf\x10\xfa\x52\x84\xf2\xb3\x22\xf4\xcc\ +\x0d\x19\x66\xf7\x2a\x84\x0e\x02\xff\xed\x35\x9a\x5e\xcf\xe9\xb5\ +\x9f\xc6\xc9\x77\x82\xef\x65\x08\x1f\x27\x0a\xe3\x3e\x7e\x4d\xc6\ +\x3d\x85\xb3\x1f\xdd\x96\xe8\xb3\x49\xff\x53\x37\xfb\x3f\x36\xeb\ +\xe9\x59\xb3\x9e\x9c\x39\xeb\xe9\x5b\xd6\x9f\xa2\x32\xce\x7a\x57\ +\xbd\x26\xe9\xfe\xac\xbc\xc7\xcf\xe5\x3d\x7f\x4b\xfb\x97\xa6\x3d\ +\x3e\x6b\xda\xf3\x33\xa7\x3d\x7e\x4b\xfb\x53\x54\x26\xd2\xfe\xe5\ +\xed\x7e\xe2\x57\x80\x73\xa7\xbd\x7e\x2e\xed\xe9\x5b\xda\xbf\x34\ +\xed\xf5\x59\xd3\x5e\x9f\x3b\xed\xc9\x9f\x74\x0c\x25\xcf\x41\x54\ +\xbc\x41\xf4\xa5\x10\x25\x67\x85\xa8\x7f\x66\x88\xbe\x12\xa1\xff\ +\x17\x9d\x49\x61\xfe\x9a\x8c\xfb\x76\x5f\xba\xf2\xec\x15\x46\xf5\ +\xd4\xfd\xb0\x6e\x6f\x53\xa2\xfb\xd8\xec\x2f\xba\xa1\x2c\x83\x6e\ +\x6c\xdb\x60\x6d\xaa\xf5\x06\xcf\xf5\x82\x37\x8c\x65\x96\x47\x26\ +\x6f\x59\xa2\xfa\x0c\x58\x0d\x24\xea\x0b\xc3\x8b\xe1\xe8\xac\xd5\ +\x8e\xef\x4f\xf3\x8b\xdb\x20\xca\xf6\xb0\x24\x8f\x99\x0f\x59\x06\ +\x8b\x40\x91\x52\xda\x57\x92\x3e\x66\x57\xcb\xa8\x10\xc6\x12\x13\ +\x31\x62\x82\x3f\x4e\x91\x10\x5c\xca\x31\x73\x97\xe7\x10\x52\x37\ +\x09\x8e\x06\x26\xb5\x66\x44\xb5\xed\xb6\xb8\xcd\xf6\xeb\xdc\xc6\ +\xa6\xcc\x77\xe6\xb1\x62\x94\x85\x3b\x7b\x17\xe9\xee\xea\x55\x6e\ +\x6e\xc0\x7a\x12\x56\xd7\x5d\x2e\xb3\xc3\xb4\x81\x7d\x9c\xc2\x5c\ +\xdd\xe6\x4e\x0d\x13\x35\x8a\x48\x23\xd1\xde\xb2\x49\xce\x9f\x90\ +\x38\x9c\xf2\xfb\x31\xeb\x68\xf1\xfd\x04\x6f\x13\x1c\xe2\x4d\xfc\ +\x60\x22\x9b\xae\x0d\x58\x36\xa6\x0c\xa2\xa0\x0c\x4e\xc0\x68\x29\ +\x44\xd2\x76\xcf\x7c\x95\x47\xab\xc5\xbf\x3e\xfe\xda\xd5\x8d\x30\ +\x5c\xfc\x3b\xcb\xef\x4e\x29\x6f\x05\x82\x65\xb6\x83\x61\x77\xd5\ +\xcc\x5e\xad\x85\x0b\x9b\x4e\x41\x79\x13\x6f\x60\xb9\xed\x6d\xe8\ +\x5f\x0f\x9b\x04\x20\xda\x31\x06\xc2\xf6\x02\xe8\x64\xb4\x36\x9b\ +\x9b\xfa\xb6\x73\xf2\x82\x38\x0a\x37\xb1\x55\xf2\x3e\x95\x71\x92\ +\xfc\x66\x9d\xf4\xea\x5b\x63\x34\x2e\x13\x73\x53\xf9\xac\x1f\xdb\ +\x59\x78\xcd\x34\xda\xf2\xd4\x9b\xe5\x95\xd7\x86\xa1\x7a\x5b\x9f\ +\xc2\x53\x01\x07\x3f\x8e\x70\x12\x2c\x4d\x72\x3d\xfb\xdd\x32\x9d\ +\x11\x77\x9d\x67\xbb\xed\x26\x8b\x4c\xa3\xde\x86\x75\xdd\xaf\x0d\ +\x7d\x28\x3a\x4e\x39\x2a\x45\x3e\xc2\x82\x00\x6c\x48\x53\x92\xda\ +\x37\x81\xa8\xf0\xb9\x56\x62\xee\x0a\x81\xb0\xaf\x94\x2f\x2e\x4f\ +\x2d\x65\x1b\x94\xb7\xa3\x12\xdf\x95\x72\xc4\xb9\xaa\xee\xb2\x3e\ +\xac\x20\x7e\x8b\x77\x7e\xf5\xa9\x5e\x7a\xfd\xa5\x7a\xcd\x77\x89\ +\x59\xa4\x59\xfa\x00\x69\x0f\x0d\x21\xcf\xee\x4c\x27\x5f\xbf\xd6\ +\xd8\x5e\x40\x75\xa5\x9a\x0a\x18\x54\x4b\xb7\xe5\x0c\x02\xb1\x58\ +\xee\xca\xb2\x4f\xfb\x4f\x16\xa7\x0b\x58\x40\x93\xb7\xd4\xea\x25\ +\x01\x94\x96\x0b\xd6\xd2\x4e\xe3\x68\x08\x51\x00\x75\x23\xcf\x83\ +\xa3\x1d\x8e\xe9\x53\xeb\x6e\x04\x1d\x6a\x13\xe4\x77\x26\xaf\xf9\ +\xf7\x71\x11\x2f\xe3\xc4\x9a\xa8\x1e\x13\xf3\x21\x8a\x8b\x2d\xac\ +\xc4\x22\x4e\xed\x30\x3e\x64\xf7\x26\x5f\x25\xd9\xbe\xe3\x9b\x34\ +\x80\x2f\x77\x19\x84\x77\x76\xed\xd2\x68\x11\x84\x90\xfe\xbb\x24\ +\x28\x4d\xaf\xd1\xd9\x6c\x71\x88\x56\x48\x60\x81\xe5\x9c\x6b\x86\ +\x60\xef\x23\x84\x13\x3a\x2e\x74\x09\x4d\x28\x9d\xbb\x50\xfa\xb0\ +\xd4\x8e\xcb\x91\xc6\x4a\x42\x0b\x81\xf5\xd2\x9a\x3b\xae\x42\x4a\ +\x08\x66\x09\x5a\x50\x09\x04\x42\x11\x57\x58\xb0\x39\x43\x92\xfb\ +\x8c\x3a\x2e\x55\xd0\xbf\x08\xa6\x73\x22\xc1\x9c\x4f\x05\x90\x18\ +\x94\x3d\xc1\xc9\x9c\x63\xa4\x98\x66\x0e\x43\x42\x72\x31\x07\x65\ +\xcd\xb5\xcf\x1c\x10\x65\x5a\x48\x39\xa7\x1a\x81\x5d\xf0\x04\x92\ +\xbe\x54\x6c\x0e\xaa\x4a\x49\x8e\x9d\xce\x91\xdb\x7a\x02\x47\x5a\ +\x31\xa5\xe6\x2e\x94\x55\x5f\x51\x8c\x1d\xdb\x7e\x7d\x4d\xe4\xdc\ +\xe5\x04\xf9\x8c\x60\x18\x21\x43\xbe\xc6\x98\x83\x94\x1d\x34\xb3\ +\x24\x42\x10\x06\x0c\x81\x26\xe5\x88\x53\xa2\xac\x18\x41\xcc\x67\ +\x12\x57\x34\xc1\x15\xb8\x7c\x70\x36\x30\x76\x10\x26\x92\x2b\x30\ +\x6a\x7b\x30\xf7\x7d\xe5\xf8\x73\xa6\xc1\x02\x78\x72\xb0\x22\x60\ +\x81\x42\xb8\xe6\x3e\xd0\xdd\x8e\xe1\x0e\x38\x0f\x8f\xb6\x1a\x16\ +\xe1\x14\xb2\xa1\x77\x6e\x1a\x34\xc9\x14\xc0\x57\x66\xb9\x0b\xa5\ +\xff\x3e\x28\x77\xb9\xb1\xd5\xb3\xb7\x09\x5a\x4f\x68\x99\xc3\x36\ +\xcb\x4b\xf7\x18\x6d\x63\x28\xc4\x10\x3e\x82\x35\xc7\x53\xf6\x1b\ +\xc9\xc3\x8b\x25\x21\x99\x4c\xfd\xbf\x1b\xbc\xdb\x6c\x63\xbc\x63\ +\x96\xc7\x77\xde\xc7\xa6\xbd\x14\xde\xef\xc1\xd2\xfb\x98\x07\xab\ +\xd2\x8b\x61\xec\x45\xb5\x69\x42\xdb\x74\xdd\x33\x39\x2e\x0e\x80\ +\x32\x25\xa1\x55\x52\x22\x6c\x69\x90\xd2\x96\x01\x6d\xc1\x87\x25\ +\x03\x84\x0a\x6c\x9f\x95\xa6\x98\x13\xa0\x73\x05\xa1\x15\x1c\xe3\ +\x39\xac\xa6\x44\x52\x71\x76\xf9\x28\xaa\x6b\x08\xa9\xdf\xaf\xe5\ +\xc3\x42\x32\xba\xb5\x0f\xf2\x70\x36\x60\xd7\x95\xa6\x2d\x2b\x4b\ +\xd8\x32\x7d\x6f\x59\x51\x15\x15\xeb\x9f\xbd\xac\x0c\x61\x3d\x9b\ +\x0c\xba\xdd\x01\x61\x2d\x11\x86\xae\xc1\x9f\x10\xb1\x3b\x60\x0e\ +\x79\x86\x35\x9d\x96\xc8\xc1\x08\x53\x88\x4b\xcc\x9e\x92\x38\x3e\ +\x21\x51\x97\x3e\xc6\x91\xb4\x23\x98\xb7\x7e\xa0\xf2\xc1\x16\x59\ +\xc0\x0e\x99\x13\x28\x56\x04\x23\xc9\x6c\x69\x6c\x6d\x40\x6d\x68\ +\x9e\x7a\xa4\x56\x1e\x72\xfb\xc4\xee\x74\xfb\xb4\x4e\x07\xaa\x43\ +\xe7\xa5\x73\x72\x62\x4f\x68\xf4\x9c\x74\xdc\xce\xc5\x78\x50\x0f\ +\xc3\x6d\xc4\x77\x80\x1f\x76\x2b\xef\xdf\x8d\x4f\xc8\x97\x8f\xb3\ +\xa1\xc1\xbe\xc5\xd6\x53\x58\x60\x4f\x63\x61\x7c\xa8\x19\x63\x61\ +\x74\x1a\x1a\x81\x61\x7c\xe4\x1a\xa1\xc1\xf6\x19\xe8\x01\x64\x0a\ +\x0e\x1c\x3a\x0e\xd4\x6b\x3c\xef\x5c\x55\x78\xc0\x14\x11\xa6\x01\ +\x1c\x2e\xe6\x88\x4a\xa1\xea\x6e\x05\x56\x68\xd5\xcf\xac\x4b\xdd\ +\x23\x61\x68\x46\x02\x4a\x99\xc5\x43\xc7\x76\xb1\x0f\x8b\x85\x49\ +\x9f\xd4\xa9\x00\x1c\x3a\x27\x8d\x0f\xd9\xb1\x89\x33\xd2\xb0\xbd\ +\xa6\xf2\x41\xc1\x47\xc7\xad\x3d\x60\xed\x3c\x1e\x13\x19\xf4\x9c\ +\xe9\xcd\x19\x34\x39\xea\x93\xaa\xdf\x73\xc2\xa0\x25\xdb\xc6\x7e\ +\x7a\xea\xd8\x14\x5a\xad\xd0\x42\x13\x40\x1f\xb4\x72\x0d\x1d\xf3\ +\xb2\xdf\x8d\xbc\x75\xf7\x98\x43\xdf\x1a\x6d\xdd\x9a\x83\x79\x6f\ +\xa3\xd6\x9d\xd2\xbf\xb3\xbc\x72\x49\x18\xa1\x4c\xfc\xec\xe5\xb5\ +\x3a\x88\x43\x68\x99\x94\xfd\x3e\xdd\x1e\xcc\x60\xab\x41\x15\x6c\ +\x5e\x7b\xac\xf6\x44\x66\x37\x24\x82\x69\x2c\x7b\x3c\xc8\x1a\xbb\ +\x1b\x22\xbe\x4f\x71\x5f\xc7\x1e\x42\x95\x82\x7d\x90\x4f\x75\xef\ +\x27\x90\x75\x7d\xba\x80\xaf\x2b\x7b\x1a\xba\xb9\xf8\x2f\x2d\x23\ +\xd5\xbb\ \x00\x00\x09\xcf\ \x00\ \x00\x35\xea\x78\x9c\xed\x5a\x5b\x6f\xdb\xca\x11\x7e\xf7\xaf\x60\ @@ -30992,6 +32609,140 @@ qt_resource_data = "\ \x33\x31\x30\x30\x32\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ \x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\ \x3e\x0a\ +\x00\x00\x08\x39\ +\x00\ +\x00\x1c\x01\x78\x9c\xed\x58\x4b\x6f\xdb\x48\x12\xbe\xfb\x57\x70\ +\x99\x4b\x8c\x65\x37\xfb\xdd\x4d\xd9\xf2\x1c\xd6\x98\x41\x80\x2c\ +\x16\xd8\x24\xd8\x63\x40\x91\x2d\x99\x6b\x8a\x14\x48\xca\x92\xfc\ +\xeb\xb7\x9a\x2f\x51\x0f\xcf\x64\x31\x99\x1c\x06\xc3\x20\x16\x59\ +\xcf\xae\xea\xaf\xab\x8a\xbc\xff\x69\xbf\xce\xbd\x17\x5b\xd5\x59\ +\x59\xcc\x7d\x8a\x89\xef\xd9\x22\x29\xd3\xac\x58\xcd\xfd\x2f\x9f\ +\x7f\x46\xc6\xf7\xea\x26\x2e\xd2\x38\x2f\x0b\x3b\xf7\x8b\xd2\xff\ +\xe9\xe1\xe6\xfe\x6f\x08\x79\xff\xa8\x6c\xdc\xd8\xd4\xdb\x65\xcd\ +\x93\xf7\xa1\x78\xae\x93\x78\x63\xbd\xf7\x4f\x4d\xb3\x99\x85\xe1\ +\x6e\xb7\xc3\x59\x4f\xc4\x65\xb5\x0a\x6f\x3d\x84\x1e\x6e\x6e\xee\ +\xeb\x97\xd5\x8d\xe7\x79\xe0\xb7\xa8\x67\x69\x32\xf7\x7b\x85\xcd\ +\xb6\xca\x5b\xc1\x34\x09\x6d\x6e\xd7\xb6\x68\xea\x90\x62\x1a\xfa\ +\x47\xf1\xe4\x28\x9e\x38\xef\xd9\x8b\x4d\xca\xf5\xba\x2c\xea\x56\ +\xb3\xa8\xdf\x4d\x84\xab\x74\x39\x4a\xbb\xd5\xec\x78\x2b\x44\xa3\ +\x28\x0a\x09\x0b\x19\x43\x20\x81\xea\x43\xd1\xc4\x7b\x74\xaa\x0a\ +\x6b\xbc\xa6\xca\x08\x21\x21\xf0\x8e\x92\xdf\x26\x35\xdb\xe7\x90\ +\x8a\x37\x17\xd3\x72\xa7\xde\x21\xfd\x1b\xf8\x3f\x2a\x0c\x04\x5c\ +\x97\xdb\x2a\xb1\x4b\xd0\xb4\xb8\xb0\x4d\xf8\xf8\xf9\x71\x64\x22\ +\x82\xd3\x26\x9d\x98\x19\xb2\x7f\xe2\xf7\x64\x4b\x8a\x78\x6d\xeb\ +\x4d\x9c\xd8\x3a\x1c\xe8\xad\xfe\x2e\x4b\x9b\xa7\xb9\xaf\xc4\x66\ +\xdf\x3e\x3f\xd9\x6c\xf5\xd4\x4c\x08\x59\x3a\xf7\x21\x42\xa6\x99\ +\x6a\x9f\x87\x35\xcc\x46\x24\x11\xcc\x59\x27\xda\x1b\x9e\xb2\x84\ +\xc1\xd4\xab\x22\xad\xc8\xa9\x76\x5a\x26\x6e\x49\x73\xff\x53\x11\ +\x6f\xbe\x7e\x28\x1a\x50\xb1\x49\x03\x5a\x78\xc8\xe7\x68\xae\xdc\ +\x36\x9b\x6d\xf3\xd5\xee\x1b\x5b\x74\x76\x21\xa2\x49\x78\x2d\xdb\ +\xa9\xe1\x93\xd0\x26\x50\xa7\xfe\x03\x50\xee\x53\xbb\xac\x1d\xa7\ +\x8b\xca\x3d\x41\x58\xa6\xe5\x01\x17\xb6\xc6\xc6\xd5\x2f\x55\x9c\ +\x66\x00\xc8\x4e\x6e\xb2\x8a\xa4\xcc\x73\x58\xe1\xdc\x8f\xf3\x5d\ +\x7c\xa8\xfd\x51\x00\x4c\x9d\xaa\x72\x2a\x44\x6f\x14\xcc\xd6\x4d\ +\xb9\x19\x64\x21\x01\xcd\x21\x87\xa8\x1d\x11\x81\xc5\xb2\x9a\xbd\ +\x5b\xb6\xd7\x5d\x4b\x2a\x61\x8b\xb2\xe6\x30\xa3\x77\xfe\x51\xa7\ +\x5c\x2e\x6b\x0b\x8e\xc9\x84\xd6\x6e\x0b\x68\x80\x2f\xe5\x7b\xe1\ +\xef\xf3\x46\xae\x79\xa3\xd7\xbd\x99\xd1\xdb\x7d\x78\x1a\x76\x4f\ +\x1d\x13\xb6\x81\xfc\x6f\xdc\x9e\xbe\xd8\xc1\xd2\xb8\xfd\xcd\xc1\ +\x81\xf5\x54\x94\xa7\xfe\x45\xd2\x5f\x36\x5f\xf7\x10\xb8\x37\xf3\ +\x38\x83\x3f\xf4\xaa\xc4\xa1\x93\xa0\x70\x18\xe1\x87\x5c\x95\x79\ +\x75\x90\xfe\x15\x33\xfd\x0a\x50\x59\x65\xab\x0c\x30\xd3\xca\x31\ +\x8a\x79\x7b\x9d\xea\x40\x32\x26\xb1\x31\xcd\xc5\x31\x27\x2e\x17\ +\x71\xfe\x7f\x83\xa8\xad\x0b\xb3\xa7\xca\x42\x1d\x7b\x77\x05\x4d\ +\x53\xdf\xa7\x2e\xb8\x91\xc7\x88\x57\x3d\xf1\x4b\x91\x35\x50\xb0\ +\xb6\xb5\xad\x3e\xb9\x43\xff\xaf\xe2\x4b\x6d\x2f\xa4\x3e\x57\x71\ +\x51\x43\x85\x59\xcf\xfd\x75\xdc\x54\xd9\xfe\x3d\x0d\x88\xfb\x87\ +\x55\x64\x24\x8b\x04\xdc\x33\xc2\xb0\x61\x46\xf1\xdb\x51\x3d\x81\ +\x1d\x61\x4c\x62\xa6\x04\x61\x47\x2a\xec\x82\xd2\x0c\xeb\x48\x73\ +\x35\x52\x97\x57\x65\x97\x57\x65\x2b\xc8\xba\xc0\x5c\x48\x6a\xcc\ +\x1f\x9d\x50\xf4\x5b\x29\x45\xd1\x9f\x39\xa9\xdf\xb5\xd4\xa1\x1f\ +\x5a\xec\x10\xfb\xb1\xe5\x0e\x91\x5f\x2d\x78\xf7\xa1\x6b\x23\xed\ +\xdd\x58\xdc\x5c\x63\x4b\x5f\x32\xbb\x3b\xf6\x9a\x45\x3c\x42\x65\ +\x13\xaf\x6c\xbb\x38\x00\x66\xb7\xba\x9e\xb1\x28\xab\xd4\x56\x03\ +\x4b\xb5\xd7\x09\xab\x5f\x7f\x37\xbb\xdd\x9c\x6e\x99\xb3\x3a\xf2\ +\xc9\x75\x7e\xfd\x14\xa7\xe5\x0e\xb0\x73\xce\x7c\x2d\x4b\x80\x2b\ +\xc7\xc6\x44\xc4\x68\x7e\xce\x6e\xb1\x09\x7d\x9c\x6a\xca\xd4\x05\ +\x13\xfc\x49\x8e\x95\x92\x5a\x5f\x32\xb7\x55\x05\x89\x42\x79\x7c\ +\xb0\x10\xd4\x4a\x30\x33\x9c\xab\xfa\xa9\xdc\xad\x2a\x97\x9b\xa6\ +\xda\xda\x73\x45\x18\x0f\xb6\x6e\x2c\x44\xdb\xee\xd0\xf5\xc3\xc8\ +\x44\xc2\xe9\xa2\xc5\xa2\xdc\x5f\x37\xb0\xcb\x0a\x88\x15\xf5\xe3\ +\x0d\x65\xe6\x22\x23\xbd\xc4\x30\xf0\x68\x29\xdf\x90\xd8\x1f\xc1\ +\x78\xce\x3a\xb8\x83\xf8\x06\x6f\x1d\xef\xb3\x75\xf6\x6a\x53\x87\ +\xad\x0e\x42\xf7\x6b\xdb\xc4\x69\xdc\xc4\x47\x60\x0c\x14\xe8\x22\ +\x74\x18\x44\x60\x56\x9d\xfd\xfb\xf1\xe7\x11\xe4\x49\x32\xfb\x4f\ +\x59\x3d\x1f\xf1\xe9\x04\xe2\x05\xcc\x3d\x73\x7f\x3c\x7a\x6e\xbc\ +\x49\x66\xae\xf0\xc4\xcd\x43\xb6\x86\xed\x76\x83\xe9\xdf\x61\x3e\ +\x04\x88\x8e\x8c\x13\x61\xd7\x84\x8f\x46\x3b\xb3\x95\xed\x06\xcf\ +\xab\xb3\x7a\x9a\xac\x33\xa7\x14\x7e\x6a\xb2\x3c\xff\xe0\x9c\x4c\ +\x0e\x63\x6f\x34\x6b\x72\xfb\xd0\xfa\xec\x6e\x87\x28\xc2\x3e\x8c\ +\xe1\x2c\x4d\xa2\xbc\x0f\x87\x34\xb4\x4f\xab\x63\x7a\x5a\xe0\xd0\ +\xf3\x0c\xe7\xf1\xc2\xe6\x73\xff\xa3\x63\x7a\x17\xdc\x55\x55\x6e\ +\x37\xeb\x32\xb5\xbd\xfa\x90\xd6\xd5\xb4\x8c\x4d\xa1\xe8\x79\xcd\ +\x45\xd1\x26\x98\x2a\x06\xb0\x61\x7d\xf1\x1e\x9e\x14\xe6\x8a\xc8\ +\xc8\xa8\x00\x29\x85\x29\x31\x86\xa8\xdb\x63\xfd\xdb\xc4\xcd\xd3\ +\x45\x3d\x1a\xeb\x0e\x96\xc4\xb4\xf3\xc4\x5d\x5f\x9d\x48\x7b\xdd\ +\x2d\x21\x9b\x27\x0f\x93\xd2\xd8\x3e\x56\xdb\xdc\xce\x8a\xb2\x78\ +\x85\x22\x00\xb5\xac\x2a\x9f\xed\x28\xdf\x3d\x76\x48\x9f\x49\x6c\ +\x1c\x11\x56\x3b\xd0\x5d\xc9\x82\xb4\xcc\x16\xdb\xa6\x99\xd2\xfe\ +\x5b\x66\xc5\x0c\xb6\xd3\x56\x03\xb5\x7d\xc8\x01\xb3\xcd\x4c\x0c\ +\xb4\xe3\x3a\x7a\x42\x1a\x43\x15\xa9\xaa\xf8\xe0\x96\x63\xa7\xd4\ +\xae\x90\x42\x71\x5d\xc7\xd5\xb3\xad\x3a\xfe\x4b\x56\x67\x8b\x2c\ +\x77\x26\xda\xdb\xdc\xde\xa5\x59\xbd\x81\x7d\x81\x77\x16\xb7\x8c\ +\xbb\x12\xc6\xf4\x65\x5e\xee\x46\xbe\x2d\x62\xf8\x41\x8b\x38\x79\ +\x76\x3b\x59\xa4\xb3\x38\x81\x62\xb0\xcd\xe1\x0d\x74\x52\xa3\xdd\ +\xd9\xf1\xb4\xc6\x5c\x33\xad\x58\x20\x14\xc7\x11\x95\x5a\x78\x89\ +\x87\x18\xec\x12\xe5\x84\xd3\x00\x9a\x24\x54\x2d\xed\x21\xc1\xe1\ +\x55\xc4\x28\xca\x03\x4e\xb0\x96\x5c\x70\x0f\x71\x83\x99\x86\x06\ +\xa6\x02\xa9\x31\x51\x4a\x48\xaf\x93\x57\x26\xe8\x4d\x08\xaf\x17\ +\x67\x3c\xe8\x4d\x30\x6f\x90\xd6\x41\x6f\x41\x7a\x06\x13\x4d\xb4\ +\xd0\x01\xa2\x58\x11\xc2\xa8\x47\x25\x06\x75\x6d\x80\x24\x31\x34\ +\x5f\x1d\xb9\x71\x12\x5a\x36\x6d\xa5\xa0\x44\x4b\xca\x23\xef\xa3\ +\xc7\x69\x04\xae\x22\xa2\x02\x05\xe1\x68\x6e\x3c\x0e\x66\x09\x94\ +\x53\x1d\x28\x78\x7d\xe2\x70\xeb\x51\x68\xe2\x3a\x22\x91\x09\xa0\ +\x91\x63\x03\x91\x1a\x08\x94\x60\x03\xe1\x73\xe7\x41\x08\x67\x0d\ +\xd6\x6a\x08\x8c\x18\xce\x7e\x04\x42\xd2\x83\x57\x45\x2e\xa9\x06\ +\xb8\x52\x85\x35\x11\x20\x84\xfa\xa4\x04\x68\x0c\x12\x0d\x49\x09\ +\xd0\x18\x25\x1a\xc2\x34\x01\x1a\xe3\x7c\xf5\xfe\xe9\xc1\x4a\x28\ +\xcc\x32\x3a\x0a\xa4\x11\xd0\x33\x64\x04\x06\xa8\xc0\x10\xb5\x76\ +\x51\xc0\x2d\xa7\x86\x09\x8f\x41\x5f\x90\x46\x41\x7e\x35\x08\x4a\ +\x2e\x09\xe4\x00\x26\x14\xce\x24\x05\x9a\x84\xbc\x10\xa6\xcd\x55\ +\x83\xaf\x67\xed\xb8\x82\x79\x84\x47\x82\x21\x81\x22\xc4\xa6\xcc\ +\xe3\xd0\x52\x00\xd2\x9b\xb2\x42\xd0\x75\x5e\xe2\x66\x5b\x59\x57\ +\xb8\x27\xc3\x82\xb3\x71\x71\x38\xaf\x9d\xc4\x7e\x68\xf8\xeb\x24\ +\x7e\xd3\x49\x3c\xdf\x9e\x09\xab\x6f\xbf\x9c\x6a\x4c\x23\x00\xc5\ +\x84\x35\xf4\x5d\x00\x36\xc0\x99\x49\x31\xe1\x41\xc7\x45\x0a\x74\ +\xdc\x79\x9d\x9a\x83\x76\x8b\xb8\x16\x58\xc1\x84\x2e\x27\xf4\xcb\ +\xf2\x0d\xb0\x37\x82\x4b\x80\x3b\x1c\x06\xa8\xbb\x1c\x90\x09\x7b\ +\x11\x4c\x6e\xa7\x22\x50\xe1\x6f\xa7\x48\x59\x5d\xc1\x97\xdd\x6f\ +\xca\xaa\x41\x87\x74\x93\xc1\xb4\x00\xe7\x9d\xd1\x48\xd2\x6b\x48\ +\xec\x25\xf7\xdf\x2c\x09\xc8\xb2\xdd\xd7\x90\xf0\xa9\x5c\xdb\xf0\ +\x00\x6f\xa1\xcf\xe1\x63\x3f\x03\xd5\xe1\xc7\x78\x11\x3e\x56\xf1\ +\xb2\x09\x33\x40\x79\xdd\x8e\xa1\x78\x53\xac\x7e\x2b\x05\x11\x14\ +\x03\x22\x89\x74\xfd\x2b\x12\xc2\xc0\x11\x76\x61\x4f\xef\x47\x11\ +\x41\xa0\xd4\x88\x48\xf2\x00\x9a\x9a\x82\x45\x47\xf2\xf6\x6c\x93\ +\x57\x9c\x2a\x32\x1d\x38\x4e\xbb\xdd\xc5\xeb\x7d\x5c\x25\xfe\x09\ +\xbb\x3b\x71\x43\xb7\x5b\xc0\x1b\xd0\x77\x39\x63\x84\x46\x7f\xf6\ +\x33\xd6\x7f\x75\x80\x7c\xc3\x1e\x30\xff\x6a\xd2\xdd\x98\x4e\x23\ +\x38\x69\x30\xda\xc8\x37\x44\xdc\x3b\xa2\x74\xf5\x3f\xe2\xd7\x25\ +\x2a\x30\x02\x4d\x47\x02\x3c\xde\x92\x38\xbc\x21\xd1\x76\x64\x26\ +\x24\x54\x73\x58\x41\x30\xf8\x71\x7d\xca\xb5\x53\xc3\x24\x53\xd0\ +\x9b\x29\xd6\x02\x0e\x77\x30\xd8\x80\xde\xdc\xdf\x4d\x48\x83\x7c\ +\x40\x26\xec\x51\x77\x4a\x1b\x75\x48\x30\x6a\x79\xa3\x93\x23\xfb\ +\x8a\xc6\xc4\xc9\xc8\x1d\x5d\x5c\x2e\xea\xf5\x74\xd6\xfd\x1d\xe0\ +\x87\x91\xfa\xfd\xbb\xcb\x6f\x0e\xb7\xe7\xa7\xa1\xc7\xbe\xc3\xd6\ +\x5b\x58\x10\x6f\x63\xe1\xf2\x13\xc1\x25\x16\x2e\xbe\x17\x5c\x80\ +\xe1\xf8\xf5\xe0\x4d\x34\x30\xee\x86\x0d\xca\xae\xc1\x41\x46\x30\ +\x0f\x45\x8c\x06\xa3\xab\x16\x0f\x94\x63\x26\x22\x00\x07\x72\x73\ +\x92\x56\x30\x4f\xf7\x56\xdc\x5c\xd6\xb9\x8c\x26\x24\x18\x7a\x22\ +\x65\x38\x73\x78\x18\xd9\x6e\xca\xd1\x82\xb2\x29\x69\x54\x01\x38\ +\x8c\x4e\x7a\x1f\x7a\x64\x33\xef\x42\x83\x79\xbd\x0f\x0e\x3e\x46\ +\x6e\xe7\x81\x46\xde\xf9\x9a\xd8\xc9\x84\x72\xfd\x0d\xc2\xc0\x84\ +\x47\xdc\x78\x06\x5d\x87\x09\xa5\xa5\x08\xa6\x77\x23\xdb\xcd\x7b\ +\x2a\x52\x11\x03\xf4\x09\xd7\x28\x99\x39\xe9\x46\xe1\xea\xaf\x11\ +\xe6\xc7\x8e\x30\x48\x7e\xaf\x21\x26\x82\x6d\x96\xf2\x7c\x88\x91\ +\x04\xba\x30\xe7\x8a\xfe\x61\x43\x4c\x0f\x9a\xf6\xe7\xde\x7d\x09\ +\x78\xb8\xf9\x1f\x14\xb2\xc8\x77\ \x00\x00\x0a\x5e\ \x00\ \x00\x29\x34\x78\x9c\xed\x5a\xdb\x8e\xdb\x46\x12\x7d\xf7\x57\x68\ @@ -31797,6 +33548,320 @@ qt_resource_data = "\ \xcb\xdd\x3a\x51\x7b\x74\x02\xf9\xeb\xe7\x4f\xdb\xeb\xf5\xcb\x1d\ \x4a\xda\x12\xe7\xf5\x68\xd6\xe4\xb0\xb3\x2a\x7b\x9d\xad\xf3\x56\ \xf8\xb9\xb6\x79\xf6\xed\xc5\xff\x01\xea\x49\x79\xab\ +\x00\x00\x0a\x96\ +\x00\ +\x00\x29\x84\x78\x9c\xed\x5a\x59\x6f\xdb\x48\x12\x7e\xcf\xaf\xd0\ +\x2a\x2f\x09\x56\x6c\xf6\x7d\x28\x96\xe7\x21\xc1\x0c\x06\xf0\x62\ +\x81\x9d\x04\xfb\x18\xd0\x24\x2d\x73\x4d\x91\x02\x49\xd9\x92\x7f\ +\xfd\x56\x37\x6f\x91\xf6\xe4\x9a\x64\x1e\xa2\x20\xb1\xf8\x75\xf5\ +\x51\xc7\x57\x5d\x45\xe7\xe2\x97\xe3\x2e\x5d\xdc\xc7\x45\x99\xe4\ +\xd9\x66\x49\x10\x5e\x2e\xe2\x2c\xcc\xa3\x24\xdb\x6e\x96\x1f\xde\ +\xff\xea\xe9\xe5\xa2\xac\x82\x2c\x0a\xd2\x3c\x8b\x37\xcb\x2c\x5f\ +\xfe\x72\xf9\xe2\xe2\x1f\x9e\xb7\x78\x5b\xc4\x41\x15\x47\x8b\x87\ +\xa4\xba\x5d\xfc\x9e\xdd\x95\x61\xb0\x8f\x17\xaf\x6e\xab\x6a\xbf\ +\xf6\xfd\x87\x87\x07\x94\x34\x20\xca\x8b\xad\xff\x7a\xe1\x79\x97\ +\x2f\x5e\x5c\x94\xf7\xdb\x17\x8b\xc5\x02\xf6\xcd\xca\x75\x14\x6e\ +\x96\xcd\x84\xfd\xa1\x48\x9d\x60\x14\xfa\x71\x1a\xef\xe2\xac\x2a\ +\x7d\x82\x88\xbf\xec\xc5\xc3\x5e\x3c\xb4\xbb\x27\xf7\x71\x98\xef\ +\x76\x79\x56\xba\x99\x59\xf9\x72\x20\x5c\x44\x37\x9d\xb4\x3d\xcd\ +\x03\x73\x42\xc4\x18\xe3\x63\xea\x53\xea\x81\x84\x57\x9e\xb2\x2a\ +\x38\x7a\xe3\xa9\x70\xc6\xb9\xa9\x14\x63\xec\xc3\x58\x2f\xf9\x69\ +\x52\xeb\x63\x0a\xa6\x78\xf2\x30\x6e\x74\xb8\x3b\x98\x7f\x0f\x7f\ +\xbb\x09\x2d\x80\xca\xfc\x50\x84\xf1\x0d\xcc\x8c\x51\x16\x57\xfe\ +\xbb\xf7\xef\xba\x41\x0f\xa3\xa8\x8a\x06\xcb\xb4\xd6\x1f\xed\x3b\ +\x72\x49\x16\xec\xe2\x72\x1f\x84\x71\xe9\xb7\xb8\x9b\xff\x90\x44\ +\xd5\xed\x66\x29\xf9\xfe\xe8\x9e\x6f\xe3\x64\x7b\x5b\x0d\x80\x24\ +\xda\x2c\x41\x43\x46\x19\x76\xcf\xed\x19\xd6\x5d\x24\x61\xc4\x68\ +\x2d\xda\x2c\x3c\x1c\xe2\x1a\x91\x45\x61\x94\x3c\x9b\x1d\xe5\xa1\ +\x3d\xd2\x66\xf9\xae\x08\x6e\xaa\x8f\x57\x79\x78\x87\x5a\x43\x76\ +\xeb\xe4\x87\x6a\x7f\xa8\x3e\xc6\xc7\x2a\xce\xea\x05\x41\x95\x81\ +\x5e\x6e\xd8\x4e\x43\x23\x9d\x06\x31\x4e\x96\x97\x80\x5c\x44\xf1\ +\x4d\x69\x47\x6a\x75\xec\x13\xe8\x43\xdd\x18\x8c\x82\x4f\xe2\xa0\ +\xf8\xad\x08\xa2\x04\x22\xb1\x96\x1b\x9c\x22\xcc\xd3\x34\x0e\xc1\ +\x26\x41\xfa\x10\x9c\xca\x65\x27\x00\x4b\x8d\xa7\x32\xaa\x58\xb3\ +\x28\x2c\x5b\x56\xf9\xbe\x95\x05\xcd\xab\x53\x0a\xea\x5a\xd0\x83\ +\x15\xf3\x62\xfd\xf2\xc6\x7d\xde\x38\x28\x07\xdf\x24\xd5\x69\x4d\ +\xde\x2c\xfb\x39\xf9\xcd\x4d\x19\xc3\xc6\x78\x80\x39\x7f\xc0\x0c\ +\xd8\x4b\x2c\x17\xfe\xd7\xed\x86\xe7\x76\x23\xf3\xbb\xa9\x6e\xb7\ +\x0b\x7f\xac\x76\x83\xda\xa7\x20\xfd\x6c\x33\x3a\x4a\xac\x6f\x8b\ +\x18\x28\xfc\x72\xc6\x9e\x43\x73\x8f\xb7\xa0\x9c\xf4\x67\xdd\x36\ +\xe0\x87\x2c\xa9\x80\xab\x87\x32\x2e\xfe\xb0\xf1\xfe\xef\xec\x43\ +\x19\x4f\xa4\xde\x17\x41\x56\x02\xb9\x76\x9b\xe5\x2e\xa8\x8a\xe4\ +\xf8\x8a\xac\x30\xfc\x81\xac\xa8\xb1\xe2\xc6\xc0\x77\x8f\x73\x24\ +\xb9\xe4\x58\xbd\xee\xe6\x87\xc7\xcd\x92\x2a\xad\x90\x30\xa6\xdf\ +\x3b\x3c\x6d\x96\x42\x50\xa4\x8d\x62\xb2\x43\x6f\x66\x65\x6f\x66\ +\x65\x8b\xcd\x92\x69\xa4\xa9\x61\xd2\xf4\x76\xfe\xc2\xc0\x7c\xd6\ +\xa2\x86\x3d\x13\xc0\x94\x63\xf3\xcd\x2c\xea\xd5\x26\x85\x1f\x42\ +\x0a\x89\x34\x63\x7a\x45\x38\xd6\x88\x52\x22\x7b\x93\x1e\x89\x35\ +\x93\x00\x5b\x6b\xa1\x3b\xf4\x04\xa8\x54\x40\x60\x82\x75\x6f\xbc\ +\x23\x05\x59\x83\x31\x22\x7c\x20\x4a\x87\xa2\x3f\xd4\x78\xea\xaf\ +\x35\x1e\x53\xf2\xc7\x1a\x6f\x26\xe3\x99\xcf\xc9\x78\x18\xd3\x80\ +\x46\x5f\x9c\xf1\xcc\xe7\x65\x3c\x0c\x5c\x16\xe6\x8b\x33\x9e\xf9\ +\xd3\x8c\xf7\x23\x42\x4c\xfc\xc5\x21\x06\x49\xef\x6f\xcd\xcf\xb9\ +\x18\x14\xe2\xfb\xdd\xba\x42\x7d\xcf\x5b\x57\x98\x1f\x11\x83\x42\ +\x3c\x1f\x83\xec\x9b\xc5\x20\x46\x4a\x63\x4a\x19\xaf\x6f\xdf\x15\ +\x5c\x95\x48\x0b\x22\xe4\x0a\x9f\x47\x20\xa3\x88\x09\x45\x46\x11\ +\xa8\x88\x0d\x2b\x4a\xcc\x38\x02\x35\x33\x08\x2b\xc2\x46\x21\xd8\ +\xcb\x76\x16\xed\xac\xb4\x87\x8a\x71\x0f\x66\x82\x26\xa3\x9d\xd2\ +\x55\xaa\xd5\xc9\xd6\xd5\x63\x51\x16\x2d\x27\x96\xbe\xdf\x7f\x84\ +\x0b\x1f\x2f\xd6\x0b\x46\xe1\x1f\x32\x2b\x71\xaa\x25\x08\xf4\x0d\ +\xf0\x03\xcf\xca\x3c\xda\xea\xfb\x99\x65\x9a\x13\x78\x79\x91\x6c\ +\x13\xa8\x72\x9d\x1c\x25\x88\xb9\xcf\x78\x0e\x78\x6f\xa0\x1b\x14\ +\xbd\xba\xd1\xfe\xc2\xb7\x55\xb0\xfb\xd6\x69\x6a\x0b\xf2\xe8\x3e\ +\x89\x1f\xfa\x52\xf9\x3a\xe8\xdc\xb8\x0f\xb6\xb1\x0b\x6a\x08\x98\ +\x3a\xaa\x9b\x81\xeb\xbc\x88\xe2\xa2\x1d\x92\xee\x33\x1a\x6a\xe2\ +\xbe\xee\x39\x5f\x9c\x29\x03\xab\x76\xe3\x78\x7e\xbc\xbc\x0d\xa2\ +\xfc\x01\xfc\x7a\x3e\xf8\x98\xe7\x10\x4a\x02\x89\xf3\x01\x57\xa6\ +\x19\x04\xd5\x0c\xa5\x7a\x32\x78\xb2\xe1\x04\x4d\x0b\xa6\x52\x4d\ +\x06\x0f\x45\x01\x91\xea\xa5\xc1\x29\x06\x75\xb6\x94\x75\x09\xb9\ +\xbc\xcd\x1f\xb6\x85\xb5\x4a\x55\x1c\xe2\xf3\x89\xd0\xd0\x1c\x6c\ +\x23\xeb\x1d\x6a\x2a\x34\xed\xd3\x40\xc2\xce\xf5\xae\xaf\xf3\xe3\ +\xfc\x02\x0f\x49\x06\x5a\x7a\x4d\x43\x46\xa8\x9e\xd8\xa2\x91\x68\ +\x5b\x34\x25\x26\x7a\x37\x12\xc7\x3e\x79\x9d\x0f\x59\xdd\x27\x76\ +\x6c\xc6\x76\xc1\x31\xd9\x25\x8f\x71\x64\xb3\x51\x13\x26\xbb\xb8\ +\x0a\xa2\xa0\x0a\xfa\x90\x68\x11\x08\xa6\x36\xed\x5e\x40\x77\xbd\ +\xfe\xcf\xbb\x5f\xbb\xb4\x18\x86\xeb\xff\xe6\xc5\x5d\x9f\xd1\xac\ +\x40\x70\x0d\x0d\xdb\x66\xd9\xa5\x6a\xdb\x97\x85\x6b\x9b\x0e\x82\ +\xea\x32\xd9\x81\xa3\x6d\x2b\xfd\x4f\xe8\x68\x21\x38\xbb\x81\x91\ +\xb0\xe5\x62\xbf\x68\xbd\x6c\x11\xd7\xad\xf2\xec\xdb\x85\x28\xdc\ +\x25\x76\x92\xff\x47\x95\xa4\xe9\xef\x76\x93\x41\xfa\x6e\x16\x4d\ +\xaa\x34\xbe\x74\x7b\xd6\x5f\x5b\x2d\xfc\x46\x8d\x36\xff\x0e\xb4\ +\xbc\xf0\x5b\x33\xb8\xa7\x6d\x6f\x1e\x17\x38\xe4\xdc\xc2\x69\x70\ +\x1d\xa7\x9b\xe5\x95\x1d\x5c\x4c\x46\xb7\x45\x7e\xd8\xef\xf2\x28\ +\x6e\xa6\xb7\x66\xdd\x0e\x79\x0c\xa1\xa8\xfb\x8c\x56\xcd\xa4\x52\ +\x62\x18\xb4\x1b\xc2\xa5\xd2\xfe\xc9\x83\x74\x8a\x30\x91\x82\xac\ +\x3c\xc3\x90\x52\x4a\x92\x41\x47\xd3\x1d\x22\x3e\xee\xf3\xa2\xf2\ +\x6e\x92\x34\xae\x3b\x73\xff\x36\xdf\xc5\xfe\x09\xd2\xcc\x9d\xff\ +\xae\x89\xee\xd2\xbf\x0a\xae\x7d\xd7\xb3\xfb\x49\x98\x67\xa5\x1f\ +\xa6\x79\x19\xa3\x7d\xb6\x7d\x72\xc5\x63\xb4\x4f\x36\x4b\x8e\xb8\ +\x91\x84\x4b\xfa\xa4\xdc\xe9\x4c\xae\xf3\xc3\xb6\x77\xf9\xfc\x1c\ +\x89\x04\x26\x46\xaa\xfe\x1a\x78\xea\x14\x9f\x22\xf9\xf5\x16\x18\ +\xb9\xc7\x7d\x4d\x83\x2a\x7e\xe5\xc9\x95\xa7\x5f\x0f\x77\x6e\xdc\ +\x2a\x86\x9c\xd8\x07\xd5\xed\x30\xc6\x9b\xa2\xa2\x2f\x55\xe0\x7c\ +\xa9\x2d\x6e\x8d\x50\xcc\x3d\x78\xe3\x31\xaf\x38\xa4\xa0\xcc\x7d\ +\x9c\xe5\x91\xad\xb5\x8b\xfc\x2e\x1e\x94\xde\xf6\xb1\xce\x32\x6b\ +\x85\x14\xc7\x9c\xc1\xd5\x6a\xdc\x47\x6b\xd3\x0a\xd8\x3b\x1f\x8c\ +\xb2\xbe\x3e\x54\xd5\x10\xfb\x5f\x9e\x64\x6b\xe0\x54\x5c\xbc\xd9\ +\x05\xc5\x5d\x5c\xac\xb3\x3c\x8b\x9b\xef\x5e\x59\x05\x45\x35\x42\ +\x76\x49\x34\x7a\x8e\xb3\xe6\xb9\x59\xd3\x2d\x95\x42\xda\xa9\xd6\ +\xbc\xc5\xa2\x00\x32\x7e\x51\x04\xa7\x91\xa4\x45\xeb\x62\x09\x0a\ +\xa8\x06\xeb\x15\xbf\x4f\xca\xe4\x3a\x49\xed\x83\xfb\x9a\xc6\x6f\ +\xa2\xa4\xdc\x03\x9d\xd6\x49\x66\x0f\xfe\x26\xbf\x8f\x8b\x9b\x34\ +\x7f\xe8\xc6\xc1\xc9\xf0\xc3\xbb\x0e\xc2\x3b\x4b\x40\x38\x58\x10\ +\x82\x8f\x0f\xd6\x57\xcb\xa1\x07\xc0\x4b\xff\x5a\x40\x51\x81\x91\ +\x86\xcf\x4a\x10\x89\xb8\x16\x74\xf1\x76\x01\xed\xbd\x46\x44\xb2\ +\x0e\x24\x06\x30\xc1\x10\xd3\x86\xaf\x84\x20\xc8\x76\xd4\xda\x62\ +\x14\x09\xf0\x17\x14\x38\x1c\xc1\x95\xa2\xe9\xe2\xaa\x41\xa1\xdc\ +\x7a\x12\x15\xc8\x68\xc1\xc8\x08\x95\x92\x21\x22\x08\x13\x0e\xd5\ +\x14\x2a\x1d\x2e\x9f\x40\xc7\xeb\x5a\x94\x72\x33\x40\x9d\x06\x0c\ +\x41\x63\x05\xa7\x95\x0a\x09\xcb\x3c\x50\x15\x0b\xbb\x18\x68\xc5\ +\x25\x22\x4a\x82\xae\xa0\x3e\x41\x06\x6b\x36\xc0\x60\xb6\x16\x50\ +\x69\x11\x26\x3b\x94\x00\xa6\xe1\x9e\x17\x56\x52\x6a\x84\xb5\xd4\ +\xa6\xc6\x94\x21\xca\xe9\xc4\x65\xad\x92\xb6\x07\x22\x42\xcc\x83\ +\x52\x52\xa4\xe1\x28\xca\xa2\x06\x1b\xc4\x88\x79\x0a\x15\x90\xd8\ +\xb4\x22\x92\xb4\x28\x80\x74\x80\xbe\xb5\x28\x1c\x46\x59\x0f\x08\ +\x0c\x8a\x30\x0d\x5e\xd1\x8a\x21\x6e\x8b\xcf\xd6\xa5\x64\xce\xcd\ +\x8f\xa3\x60\x70\x25\x15\x50\x14\x68\xab\xc6\x57\x49\x01\x45\xd6\ +\xa7\x11\x97\x28\xfe\x6d\x89\x6b\x94\xfe\x49\xdc\x29\x71\xdd\x2b\ +\x43\xf0\x0a\xf8\xca\x8c\x06\xda\x22\xcb\xc0\x35\x29\xb8\xe1\xa3\ +\xc1\xb6\xbe\x22\x5c\x20\xa9\x38\x13\xa3\x51\xf7\x52\x8f\xb9\x7b\ +\x64\x3c\x70\xb2\x65\xbb\x84\x2a\x1c\xda\xe7\x61\x8b\xe8\x6f\xbb\ +\xaf\xe3\xd4\xde\xd7\xdd\x70\xf3\xdb\x22\x05\xaa\xc6\xb0\x2c\x43\ +\xf8\x9c\xdd\x11\x75\xbc\x99\x61\x8b\xd8\xe4\x24\xc2\x11\xf4\x44\ +\x6c\x25\x39\x86\x2f\x92\x6b\x47\xca\x29\x4a\x15\x34\x56\x98\x2b\ +\xbe\x92\x42\x23\xa1\x0d\x74\x18\x80\x29\x5b\x18\x00\xa6\x2c\x37\ +\x9a\xd9\x0a\xb2\x03\xd7\x98\xaf\x14\xa6\x50\x41\x2b\xda\x24\x04\ +\x6c\x14\x05\x0c\xb8\xc5\x81\xc9\x16\xb3\x35\x34\xcc\x56\x4c\x0c\ +\xf6\x06\x01\x21\xa0\x7f\x53\x40\x54\x8c\x05\x16\x16\x83\xc2\x5e\ +\x13\xb1\x52\x90\x05\x64\x3b\x7b\x82\xd9\x14\x65\x9b\x3c\x69\xd8\ +\x14\xc5\x06\x4b\xa7\x8f\x61\x4c\x32\x97\x28\xa6\x5a\x0e\x99\xda\ +\xb0\xcf\x71\x0e\x0a\xc2\x57\x2f\xa7\x5d\xec\xeb\x4f\x26\xe1\x30\ +\x9c\x6b\x06\x92\xfd\xf1\x33\x18\x77\x1e\xf5\xc3\xf8\xd8\xfe\x49\ +\xd5\x80\x57\x73\x35\xc3\xe0\xb5\xdb\x27\xd7\x0c\xf3\x66\x10\xcf\ +\x98\x01\xf4\x7e\x84\xfe\xed\x69\x33\x08\xc8\xea\x2e\xff\x90\x9f\ +\xf9\xe7\xa9\xc2\x41\xc1\xc5\x4a\x6c\x25\x2e\x25\x41\xc2\x51\x0c\ +\xb8\x21\xa4\x31\x0d\x02\x77\xbb\x46\x52\xd8\x47\x08\x69\x42\x98\ +\x2b\x22\x14\x72\x97\xbd\x46\xca\x4e\x76\xd3\x00\x03\x12\xd6\xa8\ +\x80\x4b\x93\x36\x53\x8d\x26\x0e\xe3\xd2\x4a\x02\x66\xec\x57\x3d\ +\xc0\xdc\xc5\xca\x90\x19\xa3\x96\xaf\xda\xd8\x57\x30\xa6\x43\x21\ +\x2f\x68\x9b\x01\x98\x3d\x30\xdc\x8f\x14\x12\x9a\x1c\x61\x90\x01\ +\x84\xa4\xf5\x9a\x1d\xaa\xdd\x25\x3b\x78\xa6\x88\x12\xc8\x9d\x35\ +\x46\xa1\x15\x01\xcc\xd6\x45\x54\xda\x62\xc2\xdd\xcc\x56\x8c\x0f\ +\x8e\x62\x40\x15\x28\x3b\x9c\x20\xac\x42\xa4\xbd\xb5\xa9\xdb\xad\ +\xde\x56\x69\x31\x82\x38\xc2\x8c\xd4\x27\x19\xa0\x14\xb5\x06\x6b\ +\x40\x48\x11\x52\x22\x48\x55\xae\x3a\x81\xa4\x07\x5b\x72\x67\x7b\ +\x6e\x63\xd7\x62\x90\x6d\xdc\x64\xe7\x8f\xab\x89\xcf\x9e\x2a\x01\ +\x46\x2f\xa4\xbf\x92\x87\xea\x27\x0f\xbf\x17\x0f\x21\xfa\xce\x78\ +\xe8\x90\x9e\x87\x46\x9e\xf1\x50\xc1\x75\x35\xe5\xa1\x45\xcf\x79\ +\x68\xb1\x73\x1e\xf6\xd8\x90\x87\x3d\x3a\xe4\x61\x8b\x0e\x79\xa8\ +\xe0\xfa\x3d\xe7\xa1\x7b\x9d\x39\xe1\x21\xdc\x87\x23\x1e\x2a\xb8\ +\x24\xcf\x79\xa8\x88\x38\xe7\xa1\xb2\xb5\xee\x84\x87\x56\xf0\x9c\ +\x87\x6e\xdb\x31\x0f\x15\x96\x33\x3c\x54\x98\xcf\xf0\x10\x96\x9e\ +\xf0\x10\xce\x30\xe1\xa1\xf3\xc7\xd5\xc4\x67\x4f\xf2\x50\x7d\x3b\ +\x1e\x9a\x9f\x3c\xfc\x4e\x3c\x04\x0a\x9d\xf1\xb0\x46\x3a\x1e\x2a\ +\xaa\xcf\x79\x08\xa5\xe0\x0c\x0f\x19\x9d\xf2\x10\xb0\x09\x0f\x3b\ +\x6c\xc4\xc3\x0e\x1d\xf1\xb0\x41\x47\x3c\x64\x6a\xca\x43\xce\xe6\ +\x78\xc8\xc5\x98\x87\xd0\x19\x4c\x78\xc8\xd5\x84\x87\x5c\xcf\xf1\ +\x10\x04\x27\x3c\xb4\xdb\x9e\xf1\x90\xe9\x39\x1e\x42\xaf\x32\xe1\ +\xa1\x82\x26\xf7\x9c\x87\xd6\xf6\xe7\x3c\xac\xfd\x71\x35\xf1\xd9\ +\x93\x3c\x34\x5f\xd7\xf9\x3c\x3e\x3e\xce\x37\x3f\x1c\xcf\x34\x3f\ +\x14\x92\x16\xd5\xd0\xfd\x93\xb6\x2d\x78\x3b\x8b\x42\xb3\x41\xc0\ +\xa9\xd0\x94\x58\xac\x6d\x88\xb4\xfd\xdf\x1d\x14\xfa\x7c\x6a\x43\ +\xca\x30\x5e\x47\xa2\x72\x46\x58\x09\xc6\x91\x96\xb4\x89\x28\xe3\ +\x16\x84\x7e\xb0\x59\xd0\xbe\xe2\x01\x77\xd2\x15\x18\x73\xd0\x39\ +\xf1\x76\xb2\x06\xf3\xba\x25\xa9\xf5\x68\x3d\xdb\xd4\xc7\xa1\xb3\ +\x98\x33\x31\x69\x0e\x6e\x9a\xad\xdf\xce\x81\x54\x29\x02\xb1\xe2\ +\x5e\xe3\x08\xa4\x39\x77\xbb\x40\xa1\xe6\x7a\x21\x01\x5a\xd5\xfd\ +\x99\x9d\xac\xe0\xda\x90\x04\x4e\x09\x35\x11\x37\x70\xab\x59\x4c\ +\x22\x89\x95\xfb\x9d\xaf\x3b\xa3\xd5\x46\x4b\x6b\x1e\xb5\x12\xa0\ +\x96\x32\xa0\x4f\xdd\x07\x4a\xe0\x87\xd5\x91\xdb\xa6\x8c\xda\x57\ +\x5b\x1a\xec\xc7\x39\x04\x90\xb0\x4c\x50\xd4\x75\x72\xc4\x20\x53\ +\x9b\x4c\x0c\xdd\x00\x7d\x20\xc1\xda\x19\x52\x62\xcc\x6c\x94\x03\ +\x9d\x6b\xab\xd1\xce\x92\x33\xd8\xd5\xac\x13\x9f\xed\xed\xa6\xff\ +\x2f\xe8\x6f\xd0\xdb\x35\xf1\xef\x7e\x5c\xd8\x5f\x6d\x5c\xbe\xf8\ +\x3f\x45\x39\x68\xb0\ +\x00\x00\x08\xb6\ +\x00\ +\x00\x1e\x19\x78\x9c\xed\x58\xdb\x6e\xdb\x48\x12\x7d\xf7\x57\x70\ +\x95\x97\x18\xcb\x4b\xdf\xd8\x17\xf9\x32\x0f\x6b\xcc\x60\x80\x01\ +\x16\xd8\x24\xd8\xc7\x80\x12\x5b\x32\xd7\x14\x29\x90\x94\x25\xf9\ +\xeb\xe7\x34\x45\x52\x94\x25\x27\x59\xcc\x6c\x16\x08\x86\x41\xac\ +\x66\x55\x75\x55\x75\x55\x75\xf5\x69\xde\xfe\xb4\x5b\xe5\xde\xb3\ +\xad\xea\xac\x2c\xee\x26\x34\x24\x13\xcf\x16\xf3\x32\xcd\x8a\xe5\ +\xdd\xe4\xd3\xc7\x9f\x03\x3d\xf1\xea\x26\x29\xd2\x24\x2f\x0b\x7b\ +\x37\x29\xca\xc9\x4f\xf7\x57\xb7\x7f\x0b\x02\xef\x1f\x95\x4d\x1a\ +\x9b\x7a\xdb\xac\x79\xf4\x7e\x2d\x9e\xea\x79\xb2\xb6\xde\xfb\xc7\ +\xa6\x59\x4f\xa3\x68\xbb\xdd\x86\x59\x47\x0c\xcb\x6a\x19\x5d\x7b\ +\x41\x70\x7f\x75\x75\x5b\x3f\x2f\xaf\x3c\xcf\x83\xdd\xa2\x9e\xa6\ +\xf3\xbb\x49\x37\x61\xbd\xa9\xf2\x56\x30\x9d\x47\x36\xb7\x2b\x5b\ +\x34\x75\x44\x43\x1a\x4d\x8e\xe2\xf3\xa3\xf8\xdc\x59\xcf\x9e\xed\ +\xbc\x5c\xad\xca\xa2\x6e\x67\x16\xf5\xbb\x91\x70\x95\x2e\x06\x69\ +\xe7\xcd\x96\xb7\x42\xd4\x18\x13\x11\x16\x31\x16\x40\x22\xa8\xf7\ +\x45\x93\xec\x82\xd3\xa9\xf0\xf1\xd2\x54\x46\x08\x89\xc0\x3b\x4a\ +\x7e\x9b\xd4\x74\x97\x23\x14\x6f\x3a\xd3\x72\xc7\xd6\x11\xfe\x35\ +\xfe\x0f\x13\x7a\x42\x58\x97\x9b\x6a\x6e\x17\x98\x69\xc3\xc2\x36\ +\xd1\xc3\xc7\x87\x81\x19\x90\x30\x6d\xd2\x91\x9a\x3e\xfa\x27\x76\ +\x4f\x52\x52\x24\x2b\x5b\xaf\x93\xb9\xad\xa3\x9e\xde\xce\xdf\x66\ +\x69\xf3\x78\x37\x91\x62\xbd\x6b\xdf\x1f\x6d\xb6\x7c\x6c\x46\x84\ +\x2c\xbd\x9b\x60\x85\x4c\x31\xd9\xbe\xf7\x3e\x4c\x87\x4a\x22\x21\ +\x67\x07\xd1\x4e\xf1\x98\x25\x74\x48\xbd\xca\x28\x49\x4e\x67\xa7\ +\xe5\xdc\xb9\x74\x37\xf9\x50\x24\xeb\xcf\xbf\x54\x59\x1a\xf6\x71\ +\x1c\xd4\x94\x9b\x66\xbd\x69\x3e\xdb\x5d\x63\x8b\x83\x3e\xac\x64\ +\xb4\xac\x96\xed\xa6\x85\x27\x4b\x1a\x95\x38\x9d\xdc\x83\x72\x9b\ +\xda\x45\xed\x38\x87\xd5\xb8\x37\x2c\x47\xb7\x3c\x70\x91\x12\x9b\ +\x54\xbf\x54\x49\x9a\xa1\x10\x0f\x72\x23\x2f\xe6\x65\x9e\xdb\x39\ +\x42\x92\xe4\xdb\x64\x5f\x4f\x06\x01\xa8\x3a\x9d\xca\xa9\x10\x9d\ +\x52\xa8\xad\x9b\x72\xdd\xcb\x62\xe1\xcd\x3e\xc7\x6a\x1d\x31\x80\ +\xc6\xb2\x9a\xbe\x5b\xb4\xcf\x4d\x4b\x2a\x91\x9a\xac\xd9\x4f\xe9\ +\xcd\xe4\x38\xa7\x5c\x2c\x6a\x0b\xc3\x64\x44\x6b\xd3\x81\x19\xb0\ +\x25\x27\x5e\xf4\xc7\xac\x91\x4b\xd6\xe8\x65\x6b\x7a\xb0\x76\x1b\ +\x9d\x2e\xbb\xa3\x0e\x01\x5b\x23\xfe\x6b\x44\x0c\x3b\xb6\xd7\x34\ +\xa4\xbd\xd9\xbb\x22\x3d\x15\xe5\xe9\xe4\x2c\xe8\xcf\xeb\xcf\x3b\ +\x2c\xdc\x9b\x7a\x9c\xe1\x0f\xbd\x28\xb1\x3f\x48\x50\x6c\x42\xfc\ +\x90\x8b\x32\x2f\xae\x94\xbf\xa0\xa6\xf3\x20\x28\xab\x6c\x99\xa1\ +\x66\x5a\x39\x46\x43\xde\x3e\xa7\x73\x10\x8c\xd1\xda\x98\xe2\xe2\ +\x18\x13\x17\x8b\x24\xff\xaf\x8b\xa8\xed\x07\xd3\xc7\xca\xa2\x7f\ +\xbd\xbb\x50\x4d\x63\xdb\xa7\x26\xb8\x8e\x8f\x2b\x5e\x76\xc4\x4f\ +\x45\xd6\xa0\x51\x6d\x6a\x5b\x7d\x70\x9b\xfd\x9f\xc5\xa7\xda\x9e\ +\x49\x7d\xac\x92\xa2\x46\x67\x59\xdd\x4d\x56\x49\x53\x65\xbb\xf7\ +\xd4\x27\xee\x5f\x28\x8d\x8e\x99\x11\x18\x33\xc2\x42\xcd\xb4\xe4\ +\xd7\xc3\xf4\x39\x32\xc2\x58\x1c\x32\x29\x08\x3b\x52\x91\x05\xa9\ +\x58\xa8\x8c\xe2\x72\xa0\x2e\x2e\xca\x2e\x2e\xca\x56\x88\xba\x08\ +\xb9\x88\xa9\xd6\xff\xeb\x80\x06\xf4\x2b\x21\x0d\xc4\x8f\x1c\xd4\ +\x3f\xb5\xd5\x05\xf4\x7b\x36\xbb\x80\x7d\xdf\x76\x37\xb2\xf7\x46\ +\xc3\xfb\x3f\x54\xa8\x60\x42\xfd\xb0\xf5\x79\x1b\xb9\x93\xb9\x1d\ +\x0d\xe7\x85\xc3\x08\xe9\x73\x66\xb7\xc7\xe3\x7b\x96\x0c\xab\x5b\ +\x27\x4b\xdb\xe6\x1b\x91\x3c\x24\xbc\x63\xcc\xca\x2a\xb5\x55\xcf\ +\x92\xed\x73\xc2\xea\x4a\xe2\x00\x83\xaf\x4e\x13\xe7\xb4\x0e\x7c\ +\x72\x99\x5f\x3f\x26\x69\xb9\xc5\x72\x5f\x33\x5f\xca\x12\x11\xe6\ +\xa1\xd6\x86\x68\xc5\x5f\xb3\x5d\x38\x69\x1c\xc6\x54\x29\x69\xce\ +\x98\xce\x1f\x15\x0a\x4a\x84\x3e\x9f\xb9\xa9\x2a\xa4\x31\xc8\x93\ +\xbd\xc5\xa2\x96\x82\xe9\x5e\x41\xfd\x58\x6e\x97\x95\x8b\x4d\x53\ +\x6d\xec\xeb\x89\x40\x5a\x1b\x87\xb0\x83\xcd\xa1\x4e\x3a\x5c\x37\ +\x92\x70\x73\x83\xd9\xac\xdc\x5d\x56\xb0\xcd\x0a\xac\x35\xe8\x90\ +\x22\x65\xfa\x2c\x22\x9d\x44\x8f\x1d\x55\x1c\xbf\x21\xb1\x3b\xee\ +\xef\xd7\xac\xbd\xab\x9d\x37\x78\xab\x64\x97\xad\xb2\x17\x9b\xba\ +\xed\xda\x15\xcb\xca\x36\x49\x9a\x34\xc9\xb1\x30\x7a\x0a\x0e\xe6\ +\xbe\x33\xdd\x02\xf6\x4f\xff\xf5\xf0\xf3\xd0\x37\xe6\xf3\xe9\xbf\ +\xcb\xea\xe9\xb8\xe5\x9d\x40\x32\x03\x94\xbc\x9b\x0c\xdd\xcc\x21\ +\xc6\xf9\xd4\xed\x95\xa4\xb9\xcf\x56\x48\xb7\xc3\xf8\x7f\x07\xd4\ +\x46\x89\x0e\x8c\x13\x61\x87\x6b\x8e\x4a\x0f\x6a\x2b\x7b\xc0\xf0\ +\x17\xaf\x3d\xe9\x7c\x95\xb9\x49\xd1\x87\x26\xcb\xf3\x5f\x9d\x91\ +\x51\x7f\xeb\x94\x66\x4d\x6e\xef\x5b\x9b\x87\x61\xbf\x8a\xa8\x5b\ +\x46\xdf\x9e\x46\xab\xbc\x8d\xfa\x30\xb4\x6f\xcb\x63\x78\xda\xc2\ +\xa1\xaf\x23\x9c\x27\x33\x9b\xdf\x4d\x7e\x73\x4c\xef\x8c\xbb\xac\ +\xca\xcd\x7a\x55\xa6\xb6\x9b\xde\x87\x75\x39\x6e\x51\xe3\x52\xf4\ +\xbc\xe6\xac\xcf\x90\x90\x4a\x86\xb2\x61\x5d\xbf\xe9\xdf\x64\xc8\ +\x25\x89\x8d\x96\x7e\x20\x65\x48\x89\xd6\x44\x5e\x1f\x8f\x94\x75\ +\xd2\x3c\x9e\xb5\xf8\xa1\x95\x87\x31\xf6\x08\x1e\x76\xd3\x35\x7c\ +\xd2\x3e\x37\x0b\x44\xf3\xe4\x65\x74\xda\xb4\xaf\xd5\x26\xb7\xd3\ +\xa2\x2c\x5e\xd0\x04\x70\x3c\x54\xe5\x93\x1d\xe4\x0f\xaf\x87\x4a\ +\x9f\xc6\xa1\x76\x44\x78\xdb\xd3\x5d\xb3\x46\x58\xa6\xb3\x4d\xd3\ +\x8c\x69\xff\x29\xb3\x62\x8a\x74\xda\xaa\xa7\xb6\x2f\x39\x6a\xb6\ +\x99\x8a\x9e\x76\xf4\xa3\x23\xa4\x09\xba\x48\x55\x25\x7b\xe7\x8e\ +\x1d\x53\x0f\x67\x13\xce\xab\x55\x52\x3d\xd9\xea\xc0\x7f\xce\xea\ +\x6c\x96\xe5\x4e\x45\x3b\xcc\xed\x4d\x9a\xd5\x6b\xe4\x05\xd7\x3f\ +\xe7\xc6\x4d\x89\x9b\xcf\x22\x2f\xb7\x03\xdf\x16\x09\x7e\x82\x59\ +\x32\x7f\x72\x99\x2c\xd2\x69\x32\x47\x33\xd8\xe4\xb8\xcc\x8f\x8e\ +\x3d\xb7\x77\x3c\x26\x78\xa8\x98\x91\x7e\x4c\x64\x28\xb5\xa0\xd2\ +\x0b\x94\x09\x19\x35\x8a\xf9\xdd\x80\x7a\xb8\x79\x52\xc3\x54\xec\ +\x13\x6f\xee\x05\x22\xc4\xc1\xc1\xb9\x1f\x50\x0c\xa0\xc0\x0b\x4c\ +\x28\x98\x52\xd4\x0f\x58\xc8\x0d\x15\xc6\x0b\xa8\x08\x45\x2c\x69\ +\xec\x48\x31\x89\x15\x84\x74\xc8\xa0\xc3\xf8\x4e\x99\x86\x25\x08\ +\x49\xe8\x87\x56\x8a\xc3\x48\x08\xe5\x05\x8c\x87\x94\x19\x2d\x7c\ +\x9c\x26\x44\x30\xea\xe5\x98\x46\xe1\x60\x2c\x62\xe6\xf7\x43\x01\ +\x41\x11\x4a\x45\x35\x17\x7e\x3f\xf2\x34\xc7\x09\xa4\x04\x97\x7e\ +\x37\x12\xce\x57\x1a\x1a\x8a\x3b\x2c\x14\x12\xae\x9c\x4d\x8e\xd3\ +\x87\x10\xe9\x53\x5c\x52\x8d\x50\xc2\x51\x04\xcc\x2b\x1f\xde\x50\ +\x74\x6f\xd3\xae\x96\xb3\x18\x16\x51\x0c\x5c\x78\x24\x34\x9c\x50\ +\x9f\xe2\x7a\x10\x53\x19\x7b\xcc\x9d\x9d\x42\xbb\x09\xb1\x92\xdc\ +\xb4\x5e\x62\xe5\x84\x4b\xa3\xfc\x7e\xe4\xf5\x9e\xf1\xa3\x8f\x08\ +\xa8\x31\x44\x51\xe1\x07\xfd\x10\x4e\x22\xf0\xb1\x84\x8f\x1c\x7a\ +\x09\xd4\xb9\xd8\x01\xfa\x28\x98\x57\x20\xc0\x20\x62\x08\xcb\x78\ +\x37\x2a\x46\x54\xa4\x7b\x35\xb1\xdb\x54\x42\x6b\xe9\x51\x1c\xb3\ +\x42\x49\xea\x42\xab\x25\x65\xca\xa3\x1a\x51\xe7\x5a\xf9\x58\x1d\ +\xd1\xdc\x68\xf8\xa8\x90\x80\x38\x86\x87\xdd\x40\xf7\x1e\xc2\x9b\ +\x7e\x84\xe4\xab\x90\x18\x83\xd5\x0d\x23\x78\x88\xb4\x60\xa1\xc8\ +\x00\x12\x26\x91\x60\xcf\x85\x93\x1b\x57\x02\x88\x27\x6a\x84\x79\ +\x5d\xc6\xa0\x0a\x3e\x50\x09\xaf\x08\x28\x1c\x04\x8d\xf0\x19\x97\ +\x34\xe4\x82\x89\x18\x25\x81\xd3\x8e\x6b\x46\xb5\x17\x74\x2b\x1a\ +\x1c\xe0\xce\xcf\x73\x0f\x06\xf6\x48\xf0\xe5\x15\x82\xab\x80\xba\ +\x60\x87\x05\x6a\xcc\x38\xc2\xb2\x02\xbb\xb8\x29\xab\x00\x27\xea\ +\x73\xd2\x6c\x2a\xeb\x0e\xa5\x11\xb6\x74\xf3\xcf\x1a\xcf\xa5\x2e\ +\xd3\x61\xcc\xbf\xba\xcc\x37\x75\x99\x71\x6a\x46\xe4\x0e\x56\x70\ +\xa0\x22\x89\x5d\x10\x8f\x58\x3d\x9e\x00\x50\xd4\x86\xb2\x78\x0c\ +\xd5\x81\x24\x02\x81\xad\x43\x19\x21\x66\x44\x07\x8c\x70\x0d\x8c\ +\x72\x3e\x22\x5e\x3a\x93\x14\x8c\x11\xa9\xb4\xdb\x2a\xc3\xf8\x8d\ +\xa1\x4f\xae\xff\x2a\x90\xef\x5a\x20\x81\x08\xcc\xa5\x22\x51\xe8\ +\xcc\x9c\xea\x2f\x14\x89\x78\x55\x24\x12\x6d\x18\xad\x90\xe8\xd3\ +\x22\x09\xd0\xb5\x42\x4a\x95\x89\xbf\x58\x27\xc1\xd7\x0b\x25\xf8\ +\x42\xa5\x2c\x2f\x34\x20\xbb\x5b\x97\x55\x13\xec\xd3\x75\x06\xa8\ +\x1c\x12\x85\xae\x79\x52\xda\xaf\x25\x77\xdf\x2c\x89\xca\xb2\x87\ +\xaf\xaa\xd1\x63\xb9\xb2\xd1\xbe\xac\xb2\xa7\xe8\xa1\xbb\x00\xd4\ +\xd1\x6f\xc9\x2c\x7a\xa8\x92\x45\x13\x65\x68\x83\x75\x7b\xad\x0d\ +\xd7\xc5\xf2\x6b\x21\x30\xc6\x28\xc1\xdc\x4a\x09\x63\x8a\xe2\xf0\ +\xf3\x47\xc3\xa3\x00\x67\x06\xa7\x8d\x41\x20\x90\x08\x0d\x28\xc0\ +\xe3\xeb\x57\x09\x5e\x72\x2a\xc9\x18\x69\x9f\xc2\xbc\xb3\x4f\x85\ +\x49\x35\x9f\x9c\xb0\x0f\xbb\xad\x87\x79\x33\xdc\x56\xff\x94\xfd\ +\x45\xa8\xf9\xd1\xf7\x57\xf7\x05\x13\xf1\x46\x0e\xd8\xe4\x62\xd0\ +\xdb\xfb\xa9\xc1\x2e\x03\xa6\x8f\xdf\x10\x71\xf7\xf9\x38\x76\x80\ +\x90\x5f\x96\xa8\xa0\x44\x00\x77\x00\xde\xbc\x25\xb1\x7f\x43\xa2\ +\x83\xa2\xc0\x3b\xce\x03\xbf\xb7\x03\xe4\x41\x7c\x26\x43\xcd\x62\ +\x06\x5c\xca\x00\xff\x84\xa4\xca\xef\x75\x00\x8a\x76\xa3\x11\xa9\ +\x97\x07\x56\x3d\xb2\x87\xb9\x63\xda\x30\x87\xf8\xc3\x2c\x6f\x30\ +\x72\x64\x5f\x98\x31\x32\x32\x70\x07\x13\xe7\x4e\xbd\x9c\x5e\xf2\ +\xfe\x40\xf1\xe3\x2e\xf9\xfe\xdd\xf9\xf7\xcb\xeb\xd7\xbb\xa1\xab\ +\x7d\x57\x5b\x6f\xd5\x82\x78\xbb\x16\xce\x3f\xe7\x9c\xd7\xc2\xd9\ +\xb7\x9d\xb3\x62\x38\x7e\xe9\x79\xb3\x1a\x00\xf8\x8d\xa1\x94\x5d\ +\x2a\x87\xd8\x00\x1a\x18\x80\xc3\xc1\x54\x5b\x0f\x40\x9c\x4c\x18\ +\x14\x47\x00\xec\xc0\x15\x90\xa6\xdf\x69\x01\xa9\x33\x69\x46\x24\ +\x40\x61\x23\x35\xc0\x2b\x19\xb1\x03\xc0\x7f\x5c\x07\xd8\x98\x34\ +\x4c\x21\x2d\xac\x3d\x18\xe9\x6c\xa8\x81\xcd\xbc\xb3\x19\xcc\xeb\ +\x6c\x70\xd8\x18\xb8\x07\x0b\xd4\x78\xaf\x7d\x62\x27\xd0\xf5\x32\ +\x4c\xd1\x31\xe5\x84\x71\xd7\x64\x63\x86\xab\x40\x2c\xfc\xf1\x68\ +\x60\x73\xae\x71\x69\x90\x86\xa1\xfa\x84\x3b\x24\x99\x3e\x39\x89\ +\xa2\x65\xff\xb1\x60\x79\xf8\x4c\x80\x9f\x5b\xf7\x59\xe3\xfe\xea\ +\x77\x92\xf5\x44\x82\ \x00\x00\x0b\xd5\ \x00\ \x00\x37\xfe\x78\x9c\xed\x5a\xdb\x72\xdb\xd6\x15\x7d\xd7\x57\xa0\ @@ -31989,6 +34054,150 @@ qt_resource_data = "\ \xe2\x26\xcb\xa0\x11\x91\x47\x58\x2c\x11\x28\x7f\x4c\x7d\x1c\x4c\ \x7b\xb4\xde\xf8\x64\x7c\xf1\xee\xe8\x84\xde\x7e\xbc\x3b\xfa\x2f\ \xca\x86\x31\xf6\ +\x00\x00\x08\xd8\ +\x00\ +\x00\x1f\xc6\x78\x9c\xed\x58\x5b\x6f\xdb\x38\x16\x7e\xcf\xaf\xd0\ +\xba\x2f\x0d\xd6\x92\x78\x17\xe9\xc6\x19\x2c\xa6\x98\xc1\x00\x5d\ +\x2c\xb0\xd3\x62\x1f\x0b\xc5\xa2\x1d\x6d\x6c\xc9\x90\xe4\xd8\xe9\ +\xaf\xdf\x8f\xb2\xae\xb1\x92\xcd\xcc\xc3\x5e\xab\xa0\x35\x75\x2e\ +\x24\xcf\x85\xdf\x39\xd4\xcd\x0f\xa7\xdd\xd6\x7b\xb4\x45\x99\xe6\ +\xd9\x72\x46\x03\x32\xf3\x6c\xb6\xca\x93\x34\xdb\x2c\x67\x5f\x3e\ +\xff\xe4\xeb\x99\x57\x56\x71\x96\xc4\xdb\x3c\xb3\xcb\x59\x96\xcf\ +\x7e\xb8\xbd\xba\xf9\x83\xef\x7b\x3f\x16\x36\xae\x6c\xe2\x1d\xd3\ +\xea\xde\xfb\x25\x7b\x28\x57\xf1\xde\x7a\xef\xef\xab\x6a\xbf\x08\ +\xc3\xe3\xf1\x18\xa4\x0d\x31\xc8\x8b\x4d\x78\xed\xf9\xfe\xed\xd5\ +\xd5\x4d\xf9\xb8\xb9\xf2\x3c\x0f\xeb\x66\xe5\x22\x59\x2d\x67\x8d\ +\xc2\xfe\x50\x6c\x6b\xc1\x64\x15\xda\xad\xdd\xd9\xac\x2a\x43\x1a\ +\xd0\x70\xd6\x8b\xaf\x7a\xf1\x95\x5b\x3d\x7d\xb4\xab\x7c\xb7\xcb\ +\xb3\xb2\xd6\xcc\xca\x77\x03\xe1\x22\x59\x77\xd2\x6e\x37\x47\x5e\ +\x0b\x51\x63\x4c\x48\x58\xc8\x98\x0f\x09\xbf\x7c\xca\xaa\xf8\xe4\ +\x8f\x55\xb1\xc7\x29\x55\x46\x08\x09\xc1\xeb\x25\xdf\x26\xb5\x38\ +\x6d\xe1\x8a\x17\x37\x53\x73\x87\xab\xc3\xfd\x7b\xfc\xeb\x14\x5a\ +\x42\x50\xe6\x87\x62\x65\xd7\xd0\xb4\x41\x66\xab\xf0\xe3\xe7\x8f\ +\x1d\xd3\x27\x41\x52\x25\x83\x69\x5a\xef\x8f\xd6\x1d\x85\x24\x8b\ +\x77\xb6\xdc\xc7\x2b\x5b\x86\x2d\xbd\xd6\x3f\xa6\x49\x75\xbf\x9c\ +\x29\xb1\x3f\xd5\xef\xf7\x36\xdd\xdc\x57\x03\x42\x9a\x2c\x67\xb0\ +\x90\x45\x4c\xd5\xef\xed\x1e\x16\x5d\x26\x91\x80\xb3\xb3\x68\x33\ +\xf1\x90\x25\x74\x40\xbd\xc2\x44\x8a\x8c\xb5\x93\x7c\xe5\xb6\xb4\ +\x9c\x7d\x2c\xe2\x75\xf5\xf5\x53\x9a\xd9\xa0\x75\x64\x37\x4f\x7e\ +\xa8\xf6\x87\xea\xab\x3d\x55\x36\x3b\x4f\x08\x53\x06\x76\xd5\x6c\ +\xa7\x16\x8c\x6c\x1a\xe4\x38\x9d\xdd\x82\x72\x93\xd8\x75\xe9\x38\ +\x67\x73\xdc\x1b\xec\xd1\x35\x0f\xdc\x22\x4e\xd2\x78\xfb\xb3\xfb\ +\x41\x26\x9e\xe5\x06\xbb\x58\xe5\xdb\xad\x5d\xc1\x27\xf1\xf6\x18\ +\x3f\x95\xb3\x56\xa0\x8e\xe5\xe2\xbe\xb0\xc8\xbd\x77\x18\xdb\xb8\ +\x68\xe7\xe0\x54\x88\x4e\xce\x2d\x39\x5e\x42\xb0\xa8\x67\x6f\x1a\ +\xe2\x97\x2c\xad\x90\x64\x87\xd2\x16\xbf\xba\x40\xfd\x25\xfb\x52\ +\xda\x0b\xa9\xcf\x45\x9c\x95\xc8\x8a\xdd\x72\xb6\x8b\xab\x22\x3d\ +\xbd\xa7\x73\xe2\xfe\x02\x65\xb4\x64\x46\x60\xcc\x08\x0b\x34\xd3\ +\x8a\x5f\x77\xea\xab\xd3\x72\xc6\x98\x0c\x98\x12\x84\xf5\xd4\x27\ +\x04\x3a\x62\x41\x64\x22\xae\x3a\xea\x7a\x52\x76\x3d\x29\x5b\x2c\ +\x67\x5c\x04\x5c\x48\xaa\x81\x1e\x61\xe3\xd0\xb1\x33\xde\xec\x50\ +\xe7\xa8\x09\x3f\xde\x36\xfc\x9b\xb2\xca\xf7\xad\x2c\x52\xa9\x7a\ +\xda\x22\x7f\x1c\xd1\xc7\x8c\x79\xb1\x78\xb7\xae\x9f\x0f\x35\x29\ +\x87\x0f\xd3\xea\x69\x41\x3f\xcc\x7a\x9d\x7c\xbd\x2e\x2d\x16\x26\ +\x03\x5a\x9d\xe0\xd0\xc0\x5a\xaa\x33\xe1\xf7\xae\x46\xa6\x56\xa3\ +\xd3\xab\x0d\x1c\x16\x8e\xcd\xfe\x37\xe6\x25\xfb\x5f\xce\xcb\xce\ +\x75\x7b\x20\xc4\x1e\xbe\x43\x51\x69\x35\x3a\x64\xaa\x9e\x1c\x8e\ +\x8e\x45\x79\x32\xbb\x70\xff\xe3\xfe\x2b\x36\x44\xbc\x85\xc7\x19\ +\xfe\xa3\x93\x12\x4f\x67\x09\x8a\x3a\x81\x1f\x32\x29\xf3\xcd\xa1\ +\xed\x2b\xd3\x34\x3b\xf0\xf3\x22\xdd\xa4\x40\xb5\x5a\x8e\xd1\x80\ +\xd7\xcf\x58\x07\x21\x1d\xd8\xc6\x22\x2e\x1a\xeb\x6f\x42\x87\x7a\ +\xf5\xa8\xb3\xd4\x01\x70\xf2\x98\xda\x63\x0f\x8d\x77\x71\x17\xdb\ +\x7d\xbc\xb1\x75\xa6\x23\x8b\xce\xa9\xde\x30\xee\xf2\x22\xb1\x45\ +\xcb\x52\xf5\x33\x62\x35\x87\xe1\xdc\x63\x5c\x3d\x33\x06\xb3\x76\ +\x7c\x32\xcd\x2f\xef\xe3\x24\x3f\x22\xd8\xcf\x99\xdf\xf2\x1c\xf9\ +\xc5\x03\xad\x0d\xd1\x11\x7f\xce\x76\xc9\xe4\xbb\x04\xa1\x8a\x30\ +\x71\xc1\xc5\x82\x60\x6a\xa2\x74\x74\xc9\x3c\x14\x05\xb2\xd8\xdf\ +\xc6\x4f\x16\x56\x6d\x38\x95\xad\x4c\x79\x9f\x1f\x37\x85\x73\x4e\ +\x55\x1c\xec\x73\x45\xd4\xb1\x83\xeb\x5f\xfc\xc3\xf9\x98\x34\x55\ +\x73\x20\xe1\x74\xfd\xbb\xbb\xfc\x34\x3d\xc1\x31\xcd\x60\xac\xdf\ +\xd4\x61\xca\xf4\x85\x4b\x1a\x89\xb6\x32\x47\x52\xbe\x20\x71\xea\ +\x81\xed\x39\xcb\xd9\x7e\xe1\xce\x86\xb7\x8b\x4f\xe9\x2e\xfd\x66\ +\x13\x87\x54\x4d\xb6\xec\x6c\x15\x27\x71\x15\xf7\x99\xd1\x52\x90\ +\x53\xb4\x2b\x9c\xc9\x7a\xf1\xd7\x8f\x3f\x75\x90\xb9\x5a\x2d\xfe\ +\x96\x17\x0f\x3d\xda\x39\x81\xf8\x0e\x75\x7a\x39\xeb\x60\xdc\x95\ +\xe3\xd5\xc2\x41\x45\x5c\xdd\xa6\x3b\xc4\xdb\x75\x50\x7f\x44\x23\ +\x83\x1c\xed\x18\x23\x61\x77\x24\xfb\x49\xcf\xd3\x16\xf6\xdc\x21\ +\x4d\x36\x95\xc9\x6a\x97\x3a\xa5\xf0\xd7\x2a\xdd\x6e\x7f\x71\x8b\ +\x0c\xa0\xbd\x99\x34\xad\xb6\xf6\xb6\x5e\xf3\x3c\x6c\xad\x08\x1b\ +\x33\x5a\x6c\x1e\x58\x79\x13\xb6\x6e\xa8\xdf\x36\xbd\x7b\xea\xc4\ +\xa1\xcf\x3d\xbc\x8d\xef\xec\x76\x39\xfb\xe4\x98\xde\x05\x77\x53\ +\xe4\x87\xfd\x2e\x4f\x6c\xa3\xde\xba\x75\x33\x3c\xce\x1b\xc1\xb4\ +\xe9\x0e\x78\x75\x01\xb3\x24\xa0\x8a\x21\x6d\x58\x03\xb7\xed\x9b\ +\x0a\xb8\x22\xd2\x68\x35\xf7\x95\x0a\x28\xd1\x48\xfc\xeb\xbe\x96\ +\x6e\x7a\x7f\x0e\xe6\xac\x87\x5b\xb4\xfa\xef\x05\x0f\x22\x2a\x38\ +\x13\x73\xa5\xdd\x88\x89\xa8\x47\xed\x66\x67\x9c\x21\x15\x07\x4e\ +\xdd\xc7\xd5\xfd\x30\x4c\x75\x81\x01\x12\x41\x2e\x9a\x0d\x19\xa0\ +\xff\xd9\x63\x42\x05\x86\x12\x21\xe6\x02\x4d\xa2\x91\xca\x70\xef\ +\x47\xcf\x01\xbc\x89\x22\x0d\xa2\x09\xa4\xb3\xdd\x63\x04\x6c\x6a\ +\xa4\x99\x0b\x58\x22\x14\x20\xbd\xa6\x09\x0e\xe3\x84\x8e\x02\x85\ +\x05\x8c\xd3\x05\x91\x33\x1d\xd1\xb9\x30\x0c\x82\x46\x38\x41\x13\ +\x50\x4a\x25\x24\x4d\x84\x11\xaa\x04\xb0\x13\x55\x89\xc0\xa4\xb9\ +\x24\x34\x10\x82\x2a\xed\x7d\xf2\x24\x0b\x18\x89\x98\xe1\x73\x05\ +\xe3\x51\xa5\x0c\xc5\x9c\x42\x06\x44\x52\x94\xb0\xb9\xe2\x51\xa0\ +\x85\x16\xdc\xe3\x32\x88\x64\x44\x19\x9c\x7c\x2e\x32\x0a\x9b\x94\ +\x81\xd2\x42\xc9\xa8\xa6\x29\x2a\xb9\x86\x36\xe6\xe1\x9c\x11\x65\ +\x40\x05\x2e\x11\x58\xeb\xf9\x94\x07\x82\x71\x28\x4b\x0c\x08\xe5\ +\x11\x48\x28\x8c\x5c\x53\x8e\xb5\x23\xc8\x49\xa6\x25\xb4\x1d\x99\ +\x49\x4e\x94\x9a\x2b\xb7\x79\x6c\xd9\x78\x70\x8f\x88\xb4\x66\x72\ +\x8e\xa8\xb8\x18\x47\xd4\x63\x11\xca\x9f\xe1\x5c\x80\x86\xb8\x45\ +\x12\xf5\x04\x5b\x37\x81\x92\x24\x42\x2e\x38\x2a\x35\x44\x46\x1e\ +\x1c\x68\xa0\x81\xfd\x18\x11\x18\x6d\x20\x08\x12\x67\xc8\x19\x44\ +\x3a\x82\x18\xb6\x11\x41\x19\x54\x84\x1c\x56\x47\x68\xef\x25\x25\ +\x50\x05\x76\x46\x94\xa0\x92\x2b\x05\x9f\x0b\x58\xe4\x68\xd8\x2c\ +\x11\xb0\x1a\x43\xc2\x61\x37\x3c\xe9\x62\x28\x60\xb4\x9e\x4b\x94\ +\x29\xc2\xdd\xb6\x11\x1d\x4e\x03\x89\x24\x84\xd7\xc1\x07\x91\x63\ +\xe3\xdc\xc0\xbd\x50\x97\x30\xc1\x19\x00\x47\x0a\x58\xca\x4d\xe4\ +\xc4\x70\x77\xa0\xd8\xac\x53\x46\x16\x3a\x0b\x75\x4d\x55\x94\x3b\ +\x97\x23\xf4\x94\x45\x9a\xcf\x25\xa5\x01\x33\x92\xaa\x9a\xa6\x98\ +\x80\x27\x84\x36\x2e\xb4\xb2\x4e\x2a\x8d\x99\x90\x1d\xa0\x62\xeb\ +\x52\x47\x2e\xab\x60\x98\x26\x0c\x2e\x77\x99\x26\x24\x47\x60\x99\ +\x4b\x44\xa1\x95\x1e\xa7\x24\xc6\x0c\x91\x55\x67\xaa\xc0\x61\xa8\ +\x77\x29\xb5\x6c\x25\xb9\x26\x7c\x32\xa1\xbf\x8d\xf2\xbe\x69\x22\ +\xfb\xd6\x74\x0d\x74\x5a\xbc\x23\xf5\x53\xbf\xf4\x8d\x24\xa6\x47\ +\x06\x1b\x21\xce\xf4\xe2\xb0\xb5\x8b\x2c\xcf\xbe\xa1\xbc\xa2\xe5\ +\x2c\xf2\x87\xfa\xd5\x36\xe3\x73\xfd\x58\xb8\xf2\x86\x87\x52\xd1\ +\xd2\x5d\xff\x07\xb0\x59\xdc\x1d\xaa\x6a\x48\xfb\x7b\x9e\x66\x0b\ +\x80\xa4\x2d\x3e\xec\xe2\xe2\xc1\x16\xe7\xd9\xce\x63\xbf\xac\xe2\ +\xa2\x1a\x51\x76\x69\x32\x7a\xb7\x59\x32\x5a\xbf\x9e\x6a\x8b\x3a\ +\x52\x2d\xba\xb5\x93\x18\x95\xbc\x28\xe2\xa7\x91\xa4\xa3\x9e\x3b\ +\x63\x74\xcb\x0d\xad\xf7\xc8\x63\x5a\xa6\x77\xe9\xd6\xbd\xd4\xc3\ +\xad\xfd\x90\xa4\xe5\x1e\xf8\x88\x4b\xae\xdb\xf8\x87\x1c\xd7\xbb\ +\xf5\x36\x3f\x76\x7c\x9b\xc5\xf8\xf1\xef\xe2\xd5\x83\x43\x54\x6c\ +\x2c\x5e\xa1\x28\x1f\x1c\x8e\x0d\x1b\xfa\x70\x33\x85\x7e\x0d\x92\ +\x09\x36\x44\x32\x87\x5a\x6f\x08\x5c\x73\x03\x18\x05\x8e\xbe\x1c\ +\xaf\x36\xd0\xdf\x43\xf6\x6a\xc8\xa6\x4a\x08\x63\xca\x8c\x18\x4d\ +\xbf\xc4\xd1\x42\xba\x47\x8d\x98\x6d\xab\xc4\x1b\xf6\x58\x15\x6d\ +\x12\x4e\x3b\xe0\x14\xb8\x3f\x62\xb8\x8e\x95\x1a\xa0\x1c\x31\xe3\ +\xf9\xa6\xaa\xae\x52\x5a\x1a\xdc\x71\x82\x48\x70\xc5\x89\x98\xfb\ +\xfd\xb0\xe7\xce\xc9\xf5\xb8\xf1\xd8\x3c\xb7\x6e\xd8\x6a\xbe\xb4\ +\x1a\xa6\x36\x06\x58\x4d\xa3\x39\x0b\x54\xa4\x24\x60\xcd\xfa\x6c\ +\xee\x8f\xdf\x06\x52\x5c\x03\x77\x1d\x34\x52\x2e\x4d\x10\x69\x21\ +\xaf\xc7\x7e\x6d\x7b\x10\x7b\xda\xe7\x45\xe5\x23\x67\xed\xf9\x7b\ +\x4c\x78\x9f\xef\x6c\xf8\x84\xcb\xc6\x43\xf8\xb1\x69\x6e\xcb\xf0\ +\x53\x7c\x17\xd6\x5f\x6a\xc2\x74\x95\x67\x65\x7d\x5f\x0d\xf6\xd9\ +\xe6\xd5\x49\x4f\xc9\x3e\x45\xbf\x1a\xa0\xaa\xa2\x7c\xd3\x57\x65\ +\x9f\x9e\xc9\xde\x0e\x84\x2f\x1a\x8b\xae\x83\x90\x75\x6b\xa2\x51\ +\x4a\x5d\xd7\x0f\xbc\xfd\x93\x07\xe8\x95\xae\x73\x99\xb7\x03\x8f\ +\x78\xd4\xfd\x35\xef\xec\x2d\xc2\x13\x33\x8f\x91\x7c\x70\x5f\x2c\ +\x90\x36\xad\xfa\x8b\x32\xa7\x7f\x2e\x53\x5f\x7a\x9b\xd5\x5e\x94\ +\xc1\x3c\xd4\xb5\x02\xd8\x9a\x7c\x26\x54\xdf\xfd\xe0\x28\xdc\x7e\ +\xd8\x73\xfd\x33\x7c\xb5\xd5\xe6\x0e\x77\xf0\xe7\xa0\xf5\x06\x88\ +\x22\x68\x21\xce\x8f\x10\xbf\x1d\x43\xba\xa5\x5e\xb2\xed\x7c\xef\ +\x8e\x8b\xd5\xe8\xc0\x4c\x46\x7f\xea\x3c\x6a\x49\x39\xca\xb9\x3b\ +\x05\x12\x95\x38\x92\xee\x18\xf6\xa3\x8e\x8d\x1e\x22\x50\x46\x19\ +\x36\x67\xe8\x9f\xe0\x6b\xa6\xaf\x67\x53\xc9\x85\x73\xa3\x88\x61\ +\x74\xde\x7d\x5d\x40\xc2\x74\x1f\x15\x70\xc4\x70\xda\x28\x65\x5d\ +\x7e\x19\x1c\x3f\x30\xf8\x1b\xe5\xa7\xe6\x7f\x35\xc7\xba\x09\x5e\ +\x4b\xb2\xfe\xa3\xc7\x6b\x59\x76\xf1\xb9\x64\x22\xcd\x2e\xbf\xb4\ +\x8c\xd3\x8c\x53\x2e\x5e\x49\x33\x5c\xc6\xde\xbf\xbb\xfc\xba\x74\ +\xfd\x42\xde\x5d\xb6\x32\xe4\x5f\x96\x62\x83\xc6\xe0\x05\x80\x56\ +\xe4\x4d\x00\x1d\x89\x1a\x92\x19\xda\x6d\x49\x85\x83\xe4\xd1\x4b\ +\x2f\x84\xc6\x3a\x40\x57\xaf\xe7\x94\xba\x4b\x85\x21\xec\x3b\x3a\ +\xff\x9f\xa0\x33\x7f\x11\x9d\x2f\x6f\x05\x53\x38\xfd\xbb\x9a\xcb\ +\x29\xe4\xfe\xde\x65\x4e\xc6\xf0\x7b\x15\xfa\x2f\xab\x42\xea\xb7\ +\x57\x21\xf1\x1f\x5e\x85\xba\x61\x33\xa8\x7f\x6e\xdc\x57\xd2\xdb\ +\xab\x7f\x00\xf7\x4d\x9e\xb9\ " qt_resource_name = "\ @@ -32112,6 +34321,10 @@ qt_resource_name = "\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x52\x00\x65\x00\x63\x00\x74\x00\x61\x00\x6e\x00\x67\x00\x6c\x00\x65\x00\x2e\x00\x73\ \x00\x76\x00\x67\ +\x00\x0f\ +\x0a\x03\x3b\x47\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x43\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x15\ \x0b\x6a\xb0\xa7\ \x00\x70\ @@ -32175,6 +34388,11 @@ qt_resource_name = "\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x44\x00\x6f\x00\x77\x00\x6e\x00\x67\x00\x72\x00\x61\x00\x64\x00\x65\x00\x2e\x00\x73\ \x00\x76\x00\x67\ +\x00\x11\ +\x09\x41\x15\xe7\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x4d\x00\x69\x00\x64\x00\x70\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\ \x00\x0e\ \x0b\xfc\x0f\x47\ \x00\x44\ @@ -32201,6 +34419,11 @@ qt_resource_name = "\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x44\x00\x69\x00\x6d\x00\x65\x00\x6e\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x2e\x00\x73\ \x00\x76\x00\x67\ +\x00\x16\ +\x03\x26\xaf\xe7\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x50\x00\x65\x00\x72\x00\x70\x00\x65\x00\x6e\x00\x64\x00\x69\x00\x63\x00\x75\x00\x6c\x00\x61\ +\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x11\ \x0c\x01\x82\x47\ \x00\x44\ @@ -32210,15 +34433,27 @@ qt_resource_name = "\ \x08\x90\xca\xa7\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x54\x00\x72\x00\x69\x00\x6d\x00\x65\x00\x78\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0d\ +\x0c\x67\x9c\x67\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x47\x00\x72\x00\x69\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x10\ \x02\x9d\x02\x87\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x4f\x00\x66\x00\x66\x00\x73\x00\x65\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0e\ +\x03\xfe\xc1\x67\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x4f\x00\x72\x00\x74\x00\x68\x00\x6f\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x11\ \x0d\x09\x0b\xe7\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x42\x00\x53\x00\x70\x00\x6c\x00\x69\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ \ +\x00\x0e\ +\x07\x2c\x24\xc7\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x41\x00\x6e\x00\x67\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x11\ \x0d\x13\x54\x07\ \x00\x44\ @@ -32241,6 +34476,11 @@ qt_resource_name = "\ \x0c\x0c\x01\x67\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x54\x00\x65\x00\x78\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x12\ +\x03\x46\xc9\x27\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x45\x00\x78\x00\x74\x00\x65\x00\x6e\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\ +\x00\x67\ \x00\x15\ \x0c\xdd\x3c\xc7\ \x00\x44\ @@ -32254,6 +34494,11 @@ qt_resource_name = "\ \x08\x62\x03\xc7\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x44\x00\x72\x00\x61\x00\x66\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x11\ +\x0b\x07\x6b\x27\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x50\x00\x61\x00\x72\x00\x61\x00\x6c\x00\x6c\x00\x65\x00\x6c\x00\x2e\x00\x73\x00\x76\x00\x67\ +\ \x00\x0e\ \x05\x69\x00\x47\ \x00\x44\ @@ -32275,17 +34520,31 @@ qt_resource_name = "\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x44\x00\x65\x00\x6c\x00\x50\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\x2e\x00\x73\x00\x76\ \x00\x67\ +\x00\x0d\ +\x01\x0e\x93\xc7\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x4c\x00\x6f\x00\x63\x00\x6b\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x15\ +\x09\x1f\xeb\x67\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x49\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x73\x00\x65\x00\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\ +\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x15\ \x03\x74\x49\x07\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x32\x00\x44\x00\x53\x00\x68\x00\x61\x00\x70\x00\x65\x00\x56\x00\x69\x00\x65\x00\x77\ \x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x11\ +\x0a\x37\x15\xe7\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x45\x00\x6e\x00\x64\x00\x70\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\ " qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\ -\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x42\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x28\x00\x00\x00\x1a\ +\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x4d\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x33\x00\x00\x00\x1a\ \x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x15\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x10\x00\x00\x00\x05\ \x00\x00\x02\x72\x00\x01\x00\x00\x00\x01\x00\x05\x98\x94\ @@ -32309,46 +34568,57 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x05\x9a\x00\x01\x00\x00\x00\x01\x00\x06\x98\x18\ -\x00\x00\x03\x70\x00\x00\x00\x00\x00\x01\x00\x05\xfc\x04\ -\x00\x00\x07\x1a\x00\x01\x00\x00\x00\x01\x00\x07\x1b\xa6\ -\x00\x00\x04\x7a\x00\x01\x00\x00\x00\x01\x00\x06\x46\xeb\ -\x00\x00\x05\xe2\x00\x00\x00\x00\x00\x01\x00\x06\xb5\x62\ -\x00\x00\x06\xa4\x00\x01\x00\x00\x00\x01\x00\x06\xfa\x9a\ -\x00\x00\x08\xea\x00\x01\x00\x00\x00\x01\x00\x07\xba\x42\ -\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x15\x26\ -\x00\x00\x05\xbc\x00\x00\x00\x00\x00\x01\x00\x06\xa2\xcc\ -\x00\x00\x03\xda\x00\x00\x00\x00\x00\x01\x00\x06\x1a\xa5\ -\x00\x00\x06\x2a\x00\x01\x00\x00\x00\x01\x00\x06\xce\x27\ -\x00\x00\x03\x92\x00\x01\x00\x00\x00\x01\x00\x06\x0a\xba\ -\x00\x00\x08\x74\x00\x00\x00\x00\x00\x01\x00\x07\x9c\x88\ -\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\x6e\ -\x00\x00\x04\xca\x00\x01\x00\x00\x00\x01\x00\x06\x62\x0a\ -\x00\x00\x08\x2c\x00\x01\x00\x00\x00\x01\x00\x07\x88\x92\ -\x00\x00\x08\x4e\x00\x01\x00\x00\x00\x01\x00\x07\x92\xf4\ -\x00\x00\x04\xa8\x00\x00\x00\x00\x00\x01\x00\x06\x4f\xf1\ -\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe3\xb5\ -\x00\x00\x07\xe4\x00\x00\x00\x00\x00\x01\x00\x07\x5f\x08\ -\x00\x00\x05\x1e\x00\x01\x00\x00\x00\x01\x00\x06\x73\x7a\ -\x00\x00\x08\x08\x00\x00\x00\x00\x00\x01\x00\x07\x75\xbb\ -\x00\x00\x06\x7e\x00\x00\x00\x00\x00\x01\x00\x06\xe8\xe2\ -\x00\x00\x04\x2c\x00\x01\x00\x00\x00\x01\x00\x06\x36\x0d\ -\x00\x00\x03\x40\x00\x01\x00\x00\x00\x01\x00\x05\xf3\x75\ -\x00\x00\x07\x3c\x00\x01\x00\x00\x00\x01\x00\x07\x24\x4f\ -\x00\x00\x08\x9a\x00\x00\x00\x00\x00\x01\x00\x07\xa5\x15\ -\x00\x00\x05\x78\x00\x01\x00\x00\x00\x01\x00\x06\x8a\xb9\ -\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xdf\x31\ -\x00\x00\x07\x92\x00\x00\x00\x00\x00\x01\x00\x07\x40\xa4\ -\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x3c\xaa\ -\x00\x00\x04\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x6d\xfb\ -\x00\x00\x07\xb4\x00\x01\x00\x00\x00\x01\x00\x07\x55\x35\ -\x00\x00\x06\xca\x00\x01\x00\x00\x00\x01\x00\x07\x00\x5e\ -\x00\x00\x06\xf2\x00\x01\x00\x00\x00\x01\x00\x07\x0b\xd0\ -\x00\x00\x08\xc0\x00\x01\x00\x00\x00\x01\x00\x07\xaf\xc0\ -\x00\x00\x03\xfc\x00\x01\x00\x00\x00\x01\x00\x06\x2d\xc4\ -\x00\x00\x05\x4c\x00\x00\x00\x00\x00\x01\x00\x06\x7b\x5f\ -\x00\x00\x06\x0a\x00\x01\x00\x00\x00\x01\x00\x06\xc4\xb3\ -\x00\x00\x07\x60\x00\x00\x00\x00\x00\x01\x00\x07\x2b\xa0\ +\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xa9\x69\ +\x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x05\x1a\ +\x00\x00\x07\xfc\x00\x01\x00\x00\x00\x01\x00\x07\x76\xfd\ +\x00\x00\x0a\x1e\x00\x01\x00\x00\x00\x01\x00\x08\x26\x7d\ +\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x50\x01\ +\x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xc6\xb3\ +\x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x40\xc3\ +\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x06\xf0\x82\ +\x00\x00\x08\x96\x00\x01\x00\x00\x00\x01\x00\x07\xb0\x8c\ +\x00\x00\x0a\x6e\x00\x01\x00\x00\x00\x01\x00\x08\x39\xd1\ +\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x1e\x3c\ +\x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x46\x87\ +\x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xb4\x1d\ +\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x23\xbb\ +\x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xdf\x78\ +\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x13\xd0\ +\x00\x00\x09\xa8\x00\x00\x00\x00\x00\x01\x00\x08\x08\xc3\ +\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\xaa\ +\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x6b\x20\ +\x00\x00\x09\x60\x00\x01\x00\x00\x00\x01\x00\x07\xf4\xcd\ +\x00\x00\x09\x82\x00\x01\x00\x00\x00\x01\x00\x07\xff\x2f\ +\x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x59\x07\ +\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe3\xf1\ +\x00\x00\x07\xb2\x00\x01\x00\x00\x00\x01\x00\x07\x5a\x72\ +\x00\x00\x08\xf0\x00\x00\x00\x00\x00\x01\x00\x07\xc3\x06\ +\x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x7c\x90\ +\x00\x00\x09\x14\x00\x00\x00\x00\x00\x01\x00\x07\xd9\xb9\ +\x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x12\x9a\ +\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x3f\x23\ +\x00\x00\x0a\x3e\x00\x01\x00\x00\x00\x01\x00\x08\x31\x17\ +\x00\x00\x05\x9c\x00\x01\x00\x00\x00\x01\x00\x06\x93\xcf\ +\x00\x00\x03\x40\x00\x01\x00\x00\x00\x01\x00\x05\xf3\xb1\ +\x00\x00\x0a\x9e\x00\x01\x00\x00\x00\x01\x00\x08\x45\xaa\ +\x00\x00\x09\x38\x00\x01\x00\x00\x00\x01\x00\x07\xec\x90\ +\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x05\xfc\x8b\ +\x00\x00\x08\x1e\x00\x01\x00\x00\x00\x01\x00\x07\x7f\xa6\ +\x00\x00\x09\xce\x00\x00\x00\x00\x00\x01\x00\x08\x11\x50\ +\x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\x9c\x0a\ +\x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x08\xe9\ +\x00\x00\x08\x74\x00\x00\x00\x00\x00\x01\x00\x07\x9b\xfb\ +\x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x45\xc0\ +\x00\x00\x07\x22\x00\x00\x00\x00\x00\x01\x00\x07\x24\x52\ +\x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x77\x11\ +\x00\x00\x08\xc0\x00\x01\x00\x00\x00\x01\x00\x07\xb9\x33\ +\x00\x00\x07\x8a\x00\x01\x00\x00\x00\x01\x00\x07\x4f\x00\ +\x00\x00\x07\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x67\x27\ +\x00\x00\x09\xf4\x00\x01\x00\x00\x00\x01\x00\x08\x1b\xfb\ +\x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x36\xda\ +\x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x84\x75\ +\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xd6\x04\ +\x00\x00\x08\x42\x00\x00\x00\x00\x00\x01\x00\x07\x86\xf7\ \x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x05\xcc\x17\ \x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x05\xd5\x2b\ " diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 957d9ed072..70b0ab50c6 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -192,7 +192,8 @@ class DraftWorkbench (Workbench): "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", "Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array"] self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup", - "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap"] + "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap", + "Draft_ShowSnapBar"] self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] self.appendToolbar(str(DraftTools.translate("draft","Draft creation tools")),self.cmdList) self.appendToolbar(str(DraftTools.translate("draft","Draft modification tools")),self.modList) diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc index 6823b6747a..ca70f95168 100644 --- a/src/Mod/Draft/Resources/Draft.qrc +++ b/src/Mod/Draft/Resources/Draft.qrc @@ -40,6 +40,17 @@ icons/Draft_Dot.svg icons/Draft_Point.svg icons/Draft_Snap.svg + icons/Snap_Lock.svg + icons/Snap_Endpoint.svg + icons/Snap_Midpoint.svg + icons/Snap_Perpendicular.svg + icons/Snap_Grid.svg + icons/Snap_Intersection.svg + icons/Snap_Parallel.svg + icons/Snap_Angle.svg + icons/Snap_Center.svg + icons/Snap_Extension.svg + icons/Snap_Ortho.svg patterns/concrete.svg patterns/cross.svg patterns/line.svg diff --git a/src/Mod/Draft/Resources/icons/Snap_Angle.svg b/src/Mod/Draft/Resources/icons/Snap_Angle.svg new file mode 100644 index 0000000000..279c585690 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Angle.svg @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Center.svg b/src/Mod/Draft/Resources/icons/Snap_Center.svg new file mode 100644 index 0000000000..d3fbeb24cb --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Center.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Endpoint.svg b/src/Mod/Draft/Resources/icons/Snap_Endpoint.svg new file mode 100644 index 0000000000..853c845646 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Endpoint.svg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Extension.svg b/src/Mod/Draft/Resources/icons/Snap_Extension.svg new file mode 100644 index 0000000000..5202b9938d --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Extension.svg @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Grid.svg b/src/Mod/Draft/Resources/icons/Snap_Grid.svg new file mode 100644 index 0000000000..4408922fe7 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Grid.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Intersection.svg b/src/Mod/Draft/Resources/icons/Snap_Intersection.svg new file mode 100644 index 0000000000..f2086928a6 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Intersection.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Lock.svg b/src/Mod/Draft/Resources/icons/Snap_Lock.svg new file mode 100644 index 0000000000..a5fbc85b31 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Lock.svg @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Midpoint.svg b/src/Mod/Draft/Resources/icons/Snap_Midpoint.svg new file mode 100644 index 0000000000..31ce4eb424 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Midpoint.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Ortho.svg b/src/Mod/Draft/Resources/icons/Snap_Ortho.svg new file mode 100644 index 0000000000..6b2a6e75c1 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Ortho.svg @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Parallel.svg b/src/Mod/Draft/Resources/icons/Snap_Parallel.svg new file mode 100644 index 0000000000..0cb69485c2 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Parallel.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg b/src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg new file mode 100644 index 0000000000..2401df9590 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/Resources/ui/userprefs-base.ui b/src/Mod/Draft/Resources/ui/userprefs-base.ui index 320d916725..eb55cb4e56 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-base.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-base.ui @@ -520,6 +520,29 @@ + + + + + + If checked, the Snap toolbar will be shown whenever you use snapping + + + Show Draft Snap toolbar + + + true + + + showSnapBar + + + Mod/Draft + + + + + From f38e6da3c763dd61388c0b666d044deaa24759bb Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 12 Mar 2012 18:45:47 -0300 Subject: [PATCH 009/351] Fixed bug 625 in Draft importers --- src/Mod/Draft/importAirfoilDAT.py | 12 +++++++----- src/Mod/Draft/importDXF.py | 3 ++- src/Mod/Draft/importOCA.py | 4 +++- src/Mod/Draft/importSVG.py | 3 ++- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Mod/Draft/importAirfoilDAT.py b/src/Mod/Draft/importAirfoilDAT.py index 8815ee9a32..4b0d681622 100644 --- a/src/Mod/Draft/importAirfoilDAT.py +++ b/src/Mod/Draft/importAirfoilDAT.py @@ -28,7 +28,9 @@ import re, FreeCAD, FreeCADGui, Part, cProfile, os, string from FreeCAD import Vector, Base from Draft import * -pythonopen = open +if open.__module__ == '__builtin__': + pythonopen = open + useDraftWire = True def decodeName(name): @@ -53,10 +55,10 @@ def open(filename): def insert(filename,docname): "called when freecad imports a file" groupname = os.path.splitext(os.path.basename(filename))[0] - try: - doc=FreeCAD.getDocument(docname) - except: - doc=FreeCAD.newDocument(docname) + try: + doc=FreeCAD.getDocument(docname) + except: + doc=FreeCAD.newDocument(docname) importgroup = doc.addObject("App::DocumentObjectGroup",groupname) importgroup.Label = decodeName(groupname) process(doc,filename) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 234da7d887..58f9bbee5b 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -52,7 +52,8 @@ else: gui = True try: draftui = FreeCADGui.draftToolBar except: draftui = None -pythonopen = open # to distinguish python built-in open function from the one declared here +if open.__module__ == '__builtin__': + pythonopen = open # to distinguish python built-in open function from the one declared here def prec(): "returns the current Draft precision level" diff --git a/src/Mod/Draft/importOCA.py b/src/Mod/Draft/importOCA.py index 18220fa53b..6324ce7100 100644 --- a/src/Mod/Draft/importOCA.py +++ b/src/Mod/Draft/importOCA.py @@ -37,7 +37,9 @@ try: import FreeCADGui except ValueError: gui = False else: gui = True -pythonopen = open +if open.__module__ == '__builtin__': + pythonopen = open + params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") def getpoint(data): diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index b2f7377103..14ff99076b 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -48,7 +48,8 @@ else: gui = True try: draftui = FreeCADGui.draftToolBar except: draftui = None -pythonopen = open +if open.__module__ == '__builtin__': + pythonopen = open svgcolors = { 'Pink': (255, 192, 203), From f22fc553638dfc186d99df2e05eff807b98586df Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 13 Mar 2012 08:49:01 +0100 Subject: [PATCH 010/351] Return a NotImplemented exception when comparing Matrix or Vector with other types --- src/Base/MatrixPyImp.cpp | 5 +++-- src/Base/VectorPyImp.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index b4f37b89ae..a5408bb181 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -159,8 +159,9 @@ PyObject* MatrixPy::richCompare(PyObject *v, PyObject *w, int op) } } else { - PyErr_SetString(PyExc_TypeError, "Cannot compare Matrix with other type"); - return 0; + // This always returns False + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } } diff --git a/src/Base/VectorPyImp.cpp b/src/Base/VectorPyImp.cpp index 3476ac06a5..da2bb58311 100644 --- a/src/Base/VectorPyImp.cpp +++ b/src/Base/VectorPyImp.cpp @@ -237,8 +237,9 @@ PyObject* VectorPy::richCompare(PyObject *v, PyObject *w, int op) } } else { - PyErr_SetString(PyExc_TypeError, "Cannot compare Matrix with other type"); - return 0; + // This always returns False + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } } From 8fdc39df93cf0fcfd863e57768145df2c3cbeae5 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 13 Mar 2012 10:05:04 -0300 Subject: [PATCH 011/351] Fixed bug 625 in Arch module too --- src/Mod/Arch/importIFC.py | 4 +++- src/Mod/Arch/importOBJ.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index e676114293..39d32045af 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -31,7 +31,9 @@ __url__ = "http://free-cad.sourceforge.net" DEBUG = True SCHEMA = "http://www.steptools.com/support/stdev_docs/express/ifc2x3/ifc2x3_tc1.exp" SKIP = ["IfcOpeningElement"] -pyopen = open # because we'll redefine open below + +if open.__module__ == '__builtin__': + pyopen = open # because we'll redefine open below def open(filename): "called when freecad opens a file" diff --git a/src/Mod/Arch/importOBJ.py b/src/Mod/Arch/importOBJ.py index 4c452eb72a..e5ddca4348 100644 --- a/src/Mod/Arch/importOBJ.py +++ b/src/Mod/Arch/importOBJ.py @@ -24,7 +24,8 @@ import FreeCAD from draftlibs import fcgeo -pythonopen = open +if open.__module__ == '__builtin__': + pythonopen = open def findVert(aVertex,aList): "finds aVertex in aList, returns index" From 2a23bd13ce8928d46b66e85d22fab3e32e428b98 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 13 Mar 2012 11:41:04 -0300 Subject: [PATCH 012/351] Finished implementing RFE 510 - Arch Axes Arch axes are now printable on a Drawing sheet with the Draft tool --- src/Mod/Arch/ArchAxis.py | 6 ++---- src/Mod/Draft/Draft.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index dc9cca6504..aac12dc0a4 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -102,16 +102,14 @@ class _ViewProviderAxis: def __init__(self,vobj): vobj.addProperty("App::PropertyLength","BubbleSize","Base", "The size of the axis bubbles") vobj.addProperty("App::PropertyEnumeration","NumerationStyle","Base", "The numeration style") - vobj.addProperty("App::PropertyEnumeration","DrawStyle","Base", "The representation style") vobj.NumerationStyle = ["1,2,3","01,02,03","001,002,003","A,B,C","a,b,c","I,II,III","L0,L1,L2"] - vobj.DrawStyle = ["solid","dotted","dashed","dashdot"] vobj.Proxy = self self.Object = vobj.Object self.ViewObject = vobj vobj.BubbleSize = .1 vobj.LineWidth = 1 vobj.LineColor = (0.13,0.15,0.37) - vobj.DrawStyle = "dashdot" + vobj.DrawStyle = "Dashdot" def getIcon(self): return ":/icons/Arch_Axis_Tree.svg" @@ -203,7 +201,7 @@ class _ViewProviderAxis: self.bubbles.addChild(li) st = coin.SoSeparator() tr = coin.SoTransform() - tr.translation.setValue((center.x,center.y,center.z)) + tr.translation.setValue((center.x,center.y-rad/4,center.z)) fo = coin.SoFont() fo.name = "Arial,Sans" fo.size = rad*100 diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 5bd391bb87..f82ba9922f 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1227,6 +1227,46 @@ def getSVG(obj,modifier=100,textmodifier=100,linestyle="continuous",fillstyle="s svg += ''+l+'\n' svg += '\n' + elif getType(obj) == "Axis": + "returns the SVG representation of an Arch Axis system" + color = getrgb(obj.ViewObject.LineColor) + # setting linetype + if linestyle == "dashed": + lorig = "0.09,0.05" + elif linestyle == "dashdotted": + lorig = "0.09,0.05,0.02,0.05" + elif linestyle == "dotted": + lorig = "0.02,0.02" + else: + lorig = "none" + name = obj.Name + stroke = getrgb(obj.ViewObject.LineColor) + width = obj.ViewObject.LineWidth/modifier + fill = 'none' + invpl = obj.Placement.inverse() + n = 0 + for e in obj.Shape.Edges: + lstyle = lorig + svg += getPath([e]) + p1 = invpl.multVec(e.Vertexes[0].Point) + p2 = invpl.multVec(e.Vertexes[1].Point) + dv = p2.sub(p1) + dv.normalize() + rad = obj.ViewObject.BubbleSize + center = p2.add(dv.scale(rad,rad,rad)) + lstyle = "none" + svg += getCircle(Part.makeCircle(rad,center)) + svg += '\n' + svg += '\n' + n += 1 + elif obj.isDerivedFrom('Part::Feature'): if obj.Shape.isNull(): return '' color = getrgb(obj.ViewObject.LineColor) From 07d752677774a03246416e3826cecd212b5fb831 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 13 Mar 2012 11:55:21 -0300 Subject: [PATCH 013/351] Removed redundant LineStyle prop from Draft DrawingView objects The printed linestyle now uses the linestyle of the source object --- src/Mod/Arch/ArchAxis.py | 13 ------------ src/Mod/Draft/Draft.py | 43 ++++++++++++++++++---------------------- 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index aac12dc0a4..367ec47880 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -160,17 +160,6 @@ class _ViewProviderAxis: return "L"+str(num) return "" - def setStyle(self): - ds = self.ViewObject.RootNode.getChild(2).getChild(0).getChild(0).getChild(1) - if self.ViewObject.DrawStyle == "solid": - ds.linePattern = 0xffff - elif self.ViewObject.DrawStyle == "dotted": - ds.linePattern = 0x0f0f - elif self.ViewObject.DrawStyle == "dashed": - ds.linePattern = 0xf00f - elif self.ViewObject.DrawStyle == "dashdot": - ds.linePattern = 0xff88 - def makeBubbles(self): import Part rn = self.ViewObject.RootNode.getChild(2).getChild(0).getChild(0) @@ -223,8 +212,6 @@ class _ViewProviderAxis: def onChanged(self, vobj, prop): if prop in ["NumerationStyle","BubbleSize"]: self.makeBubbles() - elif prop == "DrawStyle": - self.setStyle() elif prop == "LineWidth": if self.bubbles: self.bubblestyle.lineWidth = vobj.LineWidth diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index f82ba9922f..7be81b5d57 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1040,8 +1040,8 @@ def draftify(objectslist,makeblock=False): return newobjlist[0] return newobjlist -def getSVG(obj,modifier=100,textmodifier=100,linestyle="continuous",fillstyle="shape color",direction=None): - '''getSVG(object,[modifier],[textmodifier],[linestyle],[fillstyle],[direction]): +def getSVG(obj,modifier=100,textmodifier=100,fillstyle="shape color",direction=None): + '''getSVG(object,[modifier],[textmodifier],[fillstyle],[direction]): returns a string containing a SVG representation of the given object. the modifier attribute specifies a scale factor for linewidths in %, and textmodifier specifies a scale factor for texts, in % (both default = 100). You can also supply @@ -1061,6 +1061,19 @@ def getSVG(obj,modifier=100,textmodifier=100,linestyle="continuous",fillstyle="s plane = WorkingPlane.plane() plane.alignToPointAndAxis(Vector(0,0,0),fcvec.neg(direction),0) + def getLineStyle(obj): + "returns a linestyle pattern for a given object" + if obj.ViewObject: + if hasattr(obj.ViewObject,"DrawStyle"): + ds = obj.ViewObject.DrawStyle + if ds == "Dashed": + return "0.09,0.05" + elif ds == "Dashdot": + return "0.09,0.05,0.02,0.05" + elif ds == "Dotted": + return "0.02,0.02" + return "none" + def getrgb(color): "getRGB(color): returns a rgb value #000000 from a freecad color" r = str(hex(int(color[0]*255)))[2:].zfill(2) @@ -1230,15 +1243,7 @@ def getSVG(obj,modifier=100,textmodifier=100,linestyle="continuous",fillstyle="s elif getType(obj) == "Axis": "returns the SVG representation of an Arch Axis system" color = getrgb(obj.ViewObject.LineColor) - # setting linetype - if linestyle == "dashed": - lorig = "0.09,0.05" - elif linestyle == "dashdotted": - lorig = "0.09,0.05,0.02,0.05" - elif linestyle == "dotted": - lorig = "0.02,0.02" - else: - lorig = "none" + lorig = getLineStyle(obj) name = obj.Name stroke = getrgb(obj.ViewObject.LineColor) width = obj.ViewObject.LineWidth/modifier @@ -1279,15 +1284,7 @@ def getSVG(obj,modifier=100,textmodifier=100,linestyle="continuous",fillstyle="s svg += getPattern(fillstyle) else: fill = 'none' - # setting linetype - if linestyle == "dashed": - lstyle = "0.09,0.05" - elif linestyle == "dashdotted": - lstyle = "0.09,0.05,0.02,0.05" - elif linestyle == "dotted": - lstyle = "0.02,0.02" - else: - lstyle = "none" + lstyle = getLineStyle(obj) name = obj.Name if obj.ViewObject.DisplayMode == "Shaded": stroke = "none" @@ -2380,9 +2377,7 @@ class _DrawingView: obj.addProperty("App::PropertyFloat","LinewidthModifier","Drawing view","Modifies the linewidth of the lines inside this object") obj.addProperty("App::PropertyFloat","TextModifier","Drawing view","Modifies the size of the texts inside this object") obj.addProperty("App::PropertyLink","Source","Base","The linked object") - obj.addProperty("App::PropertyEnumeration","LineStyle","Drawing view","Line Style") obj.addProperty("App::PropertyEnumeration","FillStyle","Drawing view","Shape Fill Style") - obj.LineStyle = ['continuous','dashed','dashdotted','dotted'] fills = ['shape color'] for f in FreeCAD.svgpatterns.keys(): fills.append(f) @@ -2398,12 +2393,12 @@ class _DrawingView: obj.ViewResult = self.updateSVG(obj) def onChanged(self, obj, prop): - if prop in ["X","Y","Scale","LinewidthModifier","TextModifier","LineStyle","FillStyle","Direction"]: + if prop in ["X","Y","Scale","LinewidthModifier","TextModifier","FillStyle","Direction"]: obj.ViewResult = self.updateSVG(obj) def updateSVG(self, obj): "encapsulates a svg fragment into a transformation node" - svg = getSVG(obj.Source,obj.LinewidthModifier,obj.TextModifier,obj.LineStyle,obj.FillStyle,obj.Direction) + svg = getSVG(obj.Source,obj.LinewidthModifier,obj.TextModifier,obj.FillStyle,obj.Direction) result = '' result += ' Date: Tue, 13 Mar 2012 14:18:52 -0300 Subject: [PATCH 014/351] Added RFE 583 - remove coin3d image loading from Draft --- src/Mod/Draft/Draft.py | 86 +++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 7be81b5d57..c6fd4713ca 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -278,6 +278,47 @@ def select(objs=None): for obj in objs: FreeCADGui.Selection.addSelection(obj) +def loadTexture(filename): + "loadTexture(filename): returns a SoSFImage from a file" + from pivy import coin + from PyQt4 import QtGui + try: + p = QtGui.QImage(filename) + size = coin.SbVec2s(p.width(), p.height()) + buffersize = p.numBytes() + numcomponents = int (buffersize / ( size[0] * size[1] )) + + img = coin.SoSFImage() + width = size[0] + height = size[1] + bytes = "" + + for y in range(height): + #line = width*numcomponents*(height-(y)); + for x in range(width): + rgb = p.pixel(x,y) + if numcomponents == 1: + bytes = bytes + chr(QtGui.qGray( rgb )) + elif numcomponents == 2: + bytes = bytes + chr(QtGui.qGray( rgb )) + bytes = bytes + chr(QtGui.qAlpha( rgb )) + elif numcomponents == 3: + bytes = bytes + chr(QtGui.qRed( rgb )) + bytes = bytes + chr(QtGui.qGreen( rgb )) + bytes = bytes + chr(QtGui.qBlue( rgb )) + elif numcomponents == 4: + bytes = bytes + chr(QtGui.qRed( rgb )) + bytes = bytes + chr(QtGui.qGreen( rgb )) + bytes = bytes + chr(QtGui.qBlue( rgb )) + bytes = bytes + chr(QtGui.qAlpha( rgb )) + #line += numcomponents + + img.setValue(size, numcomponents, bytes) + except: + return None + else: + return img + def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None, support=None): '''makeCircle(radius,[placement,face,startangle,endangle]) or makeCircle(edge,[face]): @@ -1375,21 +1416,22 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"): # TODO add Radius constraits ok = True elif tp == "Rectangle": - for edge in obj.Shape.Edges: - nobj.addGeometry(edge.Curve) - if autoconstraints: - last = nobj.GeometryCount - 1 - segs = [last-3,last-2,last-1,last] - if obj.Placement.Rotation.Q == (0,0,0,1): - nobj.addConstraint(Constraint("Coincident",last-3,EndPoint,last-2,StartPoint)) - nobj.addConstraint(Constraint("Coincident",last-2,EndPoint,last-1,StartPoint)) - nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,last,StartPoint)) - nobj.addConstraint(Constraint("Coincident",last,EndPoint,last-3,StartPoint)) - nobj.addConstraint(Constraint("Horizontal",last-3)) - nobj.addConstraint(Constraint("Vertical",last-2)) - nobj.addConstraint(Constraint("Horizontal",last-1)) - nobj.addConstraint(Constraint("Vertical",last)) - ok = True + if obj.FilletRadius == 0: + for edge in obj.Shape.Edges: + nobj.addGeometry(edge.Curve) + if autoconstraints: + last = nobj.GeometryCount - 1 + segs = [last-3,last-2,last-1,last] + if obj.Placement.Rotation.Q == (0,0,0,1): + nobj.addConstraint(Constraint("Coincident",last-3,EndPoint,last-2,StartPoint)) + nobj.addConstraint(Constraint("Coincident",last-2,EndPoint,last-1,StartPoint)) + nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,last,StartPoint)) + nobj.addConstraint(Constraint("Coincident",last,EndPoint,last-3,StartPoint)) + nobj.addConstraint(Constraint("Horizontal",last-3)) + nobj.addConstraint(Constraint("Vertical",last-2)) + nobj.addConstraint(Constraint("Horizontal",last-1)) + nobj.addConstraint(Constraint("Vertical",last)) + ok = True elif tp in ["Wire","Polygon"]: closed = False if tp == "Polygon": @@ -1410,13 +1452,13 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"): if closed: nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,segs[0],StartPoint)) ok = True - elif obj.isDerivedFrom("Part::Feature"): + if (not ok) and obj.isDerivedFrom("Part::Feature"): if fcgeo.hasOnlyWires(obj.Shape): for w in obj.Shape.Wires: for edge in fcgeo.sortEdges(w.Edges): g = fcgeo.geom(edge) if g: - nobj.addGeometry(g) + nobj.addGeometry(g) if autoconstraints: last = nobj.GeometryCount segs = range(last-len(w.Edges),last-1) @@ -1543,8 +1585,6 @@ class _ViewProviderDraft: def __init__(self, obj): obj.Proxy = self - obj.addProperty("App::PropertyEnumeration","DrawStyle","Base", - "The line style of this object") self.Object = obj.Object def attach(self, obj): @@ -2148,9 +2188,11 @@ class _ViewProviderRectangle(_ViewProviderDraft): if prop == "TextureImage": r = vp.RootNode if os.path.exists(vp.TextureImage): - self.texture = coin.SoTexture2() - self.texture.filename = str(vp.TextureImage) - r.insertChild(self.texture,1) + im = loadTexture(vp.TextureImage) + if im: + self.texture = coin.SoTexture2() + self.texture.image = im + r.insertChild(self.texture,1) else: if self.texture: r.removeChild(self.texture) From 06d708c86ea7bcf1078dca5799949260ed72d619 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 13 Mar 2012 18:21:01 -0300 Subject: [PATCH 015/351] Better icons for Draft Snap --- src/Mod/Draft/Draft_rc.py | 3874 +++++++++-------- src/Mod/Draft/Resources/icons/Snap_Angle.svg | 168 +- src/Mod/Draft/Resources/icons/Snap_Center.svg | 51 +- .../Draft/Resources/icons/Snap_Endpoint.svg | 97 +- .../Draft/Resources/icons/Snap_Extension.svg | 76 +- src/Mod/Draft/Resources/icons/Snap_Grid.svg | 52 +- .../Resources/icons/Snap_Intersection.svg | 54 +- .../Draft/Resources/icons/Snap_Midpoint.svg | 55 +- src/Mod/Draft/Resources/icons/Snap_Ortho.svg | 69 +- .../Draft/Resources/icons/Snap_Parallel.svg | 84 +- .../Resources/icons/Snap_Perpendicular.svg | 49 +- 11 files changed, 2122 insertions(+), 2507 deletions(-) diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 3714290401..560fa03cc5 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Mon Mar 12 17:12:41 2012 +# Created: Tue Mar 13 18:19:12 2012 # by: The Resource Compiler for PyQt (Qt v4.7.4) # # WARNING! All changes made in this file will be lost! @@ -24445,150 +24445,346 @@ qt_resource_data = "\ \x4b\xa7\xa0\xf2\x0f\xed\x14\xf4\x17\x26\x82\x6f\x9d\xc2\x5c\xbf\ \x47\xa7\x68\x1f\xea\xdb\xa3\xf9\x69\xef\xe9\xc3\x7f\x00\xa5\x17\ \x49\xdb\ -\x00\x00\x08\xd6\ -\x00\ -\x00\x1d\x78\x78\x9c\xdd\x58\xdd\x8f\xdb\xb8\x11\x7f\xdf\xbf\x42\ -\xf5\xbe\x64\x51\x7d\xf0\x5b\xa4\xb3\xbb\xf7\xd0\xe0\x8a\x03\x0e\ -\xe8\xe1\x92\xa0\x8f\x81\x6c\xd1\x5e\x75\x65\xc9\x90\xe4\xb5\xbd\ -\x7f\x7d\x87\x94\x44\x49\xb6\x36\x4d\x9b\xeb\x3d\xc4\x41\xd6\xd2\ -\xcc\x6f\x38\xe4\x70\x38\xf3\xa3\xef\x7f\x3a\xed\x72\xef\x45\x57\ -\x75\x56\x16\x0f\x0b\x1c\xa2\x85\xa7\x8b\x75\x99\x66\xc5\xf6\x61\ -\xf1\xf9\xd3\xcf\x81\x5c\x78\x75\x93\x14\x69\x92\x97\x85\x7e\x58\ -\x14\xe5\xe2\xa7\xc7\x9b\xfb\xbf\x04\x81\xf7\xb7\x4a\x27\x8d\x4e\ -\xbd\x63\xd6\x3c\x79\xbf\x14\xcf\xf5\x3a\xd9\x6b\xef\xdd\x53\xd3\ -\xec\x97\x51\x74\x3c\x1e\xc3\xac\x13\x86\x65\xb5\x8d\xee\xbc\x20\ -\x78\xbc\xb9\xb9\xaf\x5f\xb6\x37\x9e\xe7\x81\xdf\xa2\x5e\xa6\xeb\ -\x87\x45\x67\xb0\x3f\x54\xb9\x05\xa6\xeb\x48\xe7\x7a\xa7\x8b\xa6\ -\x8e\x70\x88\xa3\xc5\x00\x5f\x0f\xf0\xb5\xf1\x9e\xbd\xe8\x75\xb9\ -\xdb\x95\x45\x6d\x2d\x8b\xfa\x76\x04\xae\xd2\x8d\x43\x9b\xd9\x1c\ -\xa9\x05\x61\xa5\x54\x84\x48\x44\x48\x00\x88\xa0\x3e\x17\x4d\x72\ -\x0a\xa6\xa6\x30\xc7\x39\x53\x82\x10\x8a\x40\x37\x20\xbf\x0d\xb5\ -\x3c\xe5\x10\x8a\x37\x27\x63\xb5\x63\xef\x10\xfe\x3d\xfc\x77\x06\ -\xbd\x20\xac\xcb\x43\xb5\xd6\x1b\xb0\xd4\x61\xa1\x9b\xe8\xc3\xa7\ -\x0f\x4e\x19\xa0\x30\x6d\xd2\xd1\x30\x7d\xf4\x27\x7e\x27\x5b\x52\ -\x24\x3b\x5d\xef\x93\xb5\xae\xa3\x5e\x6e\xed\x8f\x59\xda\x3c\x3d\ -\x2c\x04\xdb\x9f\xec\xfb\x93\xce\xb6\x4f\xcd\x48\x90\xa5\x0f\x0b\ -\x58\x21\x89\x89\xb0\xef\xfd\x1c\x96\x2e\x93\x50\x48\x49\x0b\xed\ -\x06\x1e\xab\x98\x0c\xb1\x57\xa9\x58\xa0\xa9\x75\x5a\xae\xcd\x94\ -\x1e\x16\x1f\x8b\x64\xff\xe5\xb7\xa4\x4a\xf2\x5c\xe7\x61\x1f\x4b\ -\x37\x54\x79\x68\xf6\x87\xe6\x8b\x3e\x35\xba\x68\xc7\x84\xd5\x8c\ -\x96\x66\xd5\xc6\x2c\x9c\x2c\x6b\x94\xe6\x78\xf1\x08\x92\xfb\x54\ -\x6f\x6a\xa3\x69\x57\x64\xde\x60\x49\xd2\xea\x40\x0b\xdb\xa2\x93\ -\xea\xef\x55\x92\x66\x90\x8c\x2d\x6e\x34\x8b\x75\x09\xb3\x5b\x43\ -\x58\x92\xfc\x98\x9c\xeb\x85\x03\xc0\x50\x53\x53\x8a\x19\xeb\x06\ -\x85\x61\xeb\xa6\xdc\xf7\x58\x58\x7c\x73\xce\x61\xc5\x46\x18\xc0\ -\x88\x65\xb5\xbc\xdd\xd8\xcf\x7b\x2b\x2a\x61\x7b\xb2\xe6\xbc\xc4\ -\xef\x17\x83\x4d\xb9\xd9\xd4\x1a\x1c\xa3\x91\xcc\x6e\x09\x58\x80\ -\x2f\xb1\xf0\xa2\xef\xf3\x86\xe6\xbc\xe1\x79\x6f\xd2\x79\xbb\x8f\ -\xa6\xcb\xee\xa4\x2e\x60\x7b\x88\xff\x1e\x22\x06\xa7\xb6\x1f\xc9\ -\x6d\x7d\x73\x36\x89\x3a\x85\xd2\x74\x71\x15\xf4\x97\xfd\x97\x13\ -\x2c\xdc\x5b\x7a\x94\xc0\x1f\x3c\x8b\x38\xb7\x08\x0c\x07\x11\xbe\ -\xd0\x2c\xe6\xd5\xa4\xf3\x57\x86\xe9\x66\x10\x94\x55\xb6\xcd\x20\ -\x67\x2c\x8e\xe0\x90\xda\xcf\xd4\x06\x82\x31\x5a\x1b\x89\x29\x1b\ -\x62\x62\x62\x91\xe4\xff\x75\x12\xd9\x9a\xb0\x7c\xaa\x34\xd4\xb0\ -\xdb\x99\x6c\x1a\xfb\x9e\xba\xa0\x92\x0f\x2b\xde\x76\xc2\xcf\x45\ -\xd6\x40\xb1\x3a\xd4\xba\xfa\x68\x0e\xfc\x3f\x8a\xcf\xb5\xbe\x42\ -\x7d\xaa\x92\xa2\x86\xea\xb2\x7b\x58\xec\x92\xa6\xca\x4e\xef\xb0\ -\x8f\xcc\xbf\x50\x28\xc9\x89\x62\xf0\x4c\x10\x09\x25\x91\x82\xde\ -\x39\xf3\x35\xec\x08\x21\x3c\x24\x82\x21\x32\x48\x61\x17\x44\x4c\ -\xc2\x58\xc5\x54\x38\xe9\x66\x16\xbb\x99\xc5\x56\x10\x75\x16\x52\ -\xc6\xb1\x94\xff\xef\x80\x06\xf1\x7f\x08\x69\x40\x7e\xe4\xa0\xfe\ -\xa1\xa5\x0e\x62\xf9\x27\x16\xbb\x80\xfd\xb9\xe5\x6e\xe4\xef\x8d\ -\x82\x37\x9f\xa1\x93\xc0\x7f\x7d\x8f\xe6\xf7\x73\x7e\xef\xe7\xf3\ -\xe4\x3b\x93\xef\xdb\x32\xfc\xfa\xa0\x30\x46\xe3\xff\xe5\xc4\xbd\ -\x95\x67\x6d\xa0\xef\x23\xd3\x99\xed\x93\xeb\x17\x86\x27\xa4\x2f\ -\x99\x3e\x0e\xed\x7b\x95\xb8\xb9\xed\x93\xad\xb6\xfb\x0d\x9e\xdb\ -\x0d\xef\x14\xab\xb2\x4a\x75\xd5\xab\x84\xfd\x4c\x54\x5d\x4a\xb4\ -\x54\xf8\x66\x3a\x3b\x33\xaa\xd3\xa3\x79\x7d\xfd\x94\xa4\xe5\x11\ -\xb6\xe4\x52\xf9\x5a\x96\xb0\x09\x34\x94\x52\x21\x19\xd3\x4b\xb5\ -\xdd\x46\xa0\x45\x38\xc6\x44\x5c\x29\xc1\x1f\xa7\xa1\x10\x3c\x8e\ -\xaf\x95\x87\xaa\x82\x90\x06\x79\x72\xd6\xb0\xa8\x2d\x23\x52\x75\ -\x98\xfa\xa9\x3c\x6e\x2b\x13\x9b\xa6\x3a\xe8\x4b\x43\x60\x5b\x07\ -\xc3\xb2\x83\x43\xbb\xcb\x1d\xb7\x1b\x21\x8c\x6d\xb0\x5a\x95\xa7\ -\xf9\x01\x8e\x59\x01\x6b\x0d\x3a\xb6\x88\x89\xbc\x8a\x48\x87\xe8\ -\xf9\x63\xcc\xf9\x1b\x88\xd3\x70\xbe\x2f\x55\x67\x93\xdf\x6f\xe8\ -\x76\xc9\x29\xdb\x65\xaf\x3a\x35\xc7\xb5\x4b\x96\x9d\x6e\x92\x34\ -\x69\x92\x21\x31\x7a\x09\x34\x66\xdc\x73\x3b\xa0\xfe\xcb\xdf\x3f\ -\xfc\xec\xea\xc6\x7a\xbd\xfc\x67\x59\x3d\x0f\x47\xde\x00\x92\x15\ -\x50\xc9\x87\x85\xab\x66\x86\x31\xae\x97\xe6\x38\x25\xcd\x63\xb6\ -\x83\xed\x36\x3c\xff\xaf\x40\xb7\x21\x45\x9d\x62\x02\x36\xbc\x66\ -\x18\xb4\x1d\xb6\xd2\x2d\x8f\x9f\xbd\xfa\xa4\xeb\x5d\x66\x8c\xa2\ -\x8f\x4d\x96\xe7\xbf\x18\x27\xa3\xfa\xd6\x0d\x9a\x35\xb9\x7e\xb4\ -\x3e\xdb\xc7\x7e\x15\x51\xb7\x8c\xbe\x3c\x8d\x56\x79\x1f\xf5\x61\ -\xb0\x6f\xdb\x21\x3c\x36\x71\xf0\x65\x84\xf3\x64\xa5\xf3\x87\xc5\ -\xaf\x46\xe9\x5d\x69\xb7\x55\x79\xd8\xef\xca\x54\x77\xe6\x7d\x58\ -\xb7\xe3\xda\x30\x4e\x45\xcf\x6b\xae\x4a\x11\x0a\xb1\x20\x90\x36\ -\xa4\x2b\x49\xfd\x9b\x08\xa9\x40\x5c\x49\xe1\x07\x42\x84\x18\x49\ -\x89\xc4\xdd\xd0\x52\xf6\x49\xf3\x74\x55\xe2\x5d\x29\x0f\x39\xe1\ -\xef\x37\x10\xba\xe5\x2d\xb2\x1f\xfb\x32\x6a\x2d\xf6\xb5\x3a\xe4\ -\x7a\x59\x94\xc5\x2b\x9c\x78\xe8\x05\x55\xf9\xac\x1d\xbe\x7d\x6d\ -\xd3\x7a\xc9\xa1\xdc\x9a\x4f\x8c\x7b\xb9\xa9\x64\x10\x83\xe5\xea\ -\xd0\x34\x63\xd9\xbf\xca\xac\x58\xc2\xde\xe9\xaa\x97\xda\x97\x1c\ -\x12\xb4\x59\xb2\x5e\x36\xcc\xa3\x13\xa4\x09\x94\x8c\xaa\x4a\xce\ -\x66\x3a\x7a\x2c\x6d\x1b\x11\x34\xa7\x5d\x52\x3d\xeb\xaa\xd5\xbf\ -\x64\x75\xb6\xca\x72\x33\x84\x7d\xcc\xf5\xfb\x34\xab\xf7\xb0\x09\ -\x70\xdf\x33\xd3\x78\x5f\xc2\x35\x67\x93\x97\x47\xa7\xd7\x45\x02\ -\x5f\xc1\x2a\x59\x3f\x9b\x6d\x2b\xd2\x65\xb2\x86\x93\x7f\xc8\xe1\ -\xf6\x3e\xea\x71\xe6\xa0\x78\x58\xc8\x90\x51\xae\x84\xcf\x38\x0f\ -\x85\x54\x92\x7a\x6b\x2f\x50\x38\x14\x14\x53\x26\x7d\xe4\x05\x58\ -\x40\x50\x04\x95\x31\x74\x8f\x98\x85\xd0\xcf\x10\x99\x4a\xb1\xd9\ -\x36\xa6\xa8\xf4\x90\xdf\x99\x72\x0f\xa0\x98\x12\x0e\xa5\xdf\xef\ -\xb1\xd2\x9b\x5a\xf5\xd2\xde\x06\xbc\x19\xa1\xe2\x42\x50\x3f\xe8\ -\x07\x18\xcb\x06\x1b\xe4\xf7\xb3\x14\x9e\x81\x02\x92\x48\x03\xe8\ -\xa7\x12\x4c\xcc\x7a\xe9\xab\xb7\x03\x53\x2a\xc3\x98\x11\x26\x61\ -\xad\x31\x32\xad\x94\x9a\x95\x62\x12\x87\x0c\x41\x10\x7c\x1e\x03\ -\x9c\x70\x3c\x12\x75\x4f\x0a\xac\x3b\x13\xe5\x05\x3d\xce\x6a\x11\ -\xc1\x46\x36\x35\xe9\x84\xbd\x49\x6c\x03\x0a\x72\x82\x19\x04\x26\ -\xe0\x22\x8c\x79\x3c\x11\x0d\x56\xb0\x44\xe7\x0a\x80\x8a\xa9\x98\ -\x51\x3f\x70\x33\xb9\x30\xb2\x32\xb3\x3e\xb8\xee\x72\xc1\x94\x1f\ -\x83\x4c\x32\x65\x56\x19\xd0\x90\x98\x7b\x8a\x1f\x40\x1f\xc3\x0a\ -\x3c\x8a\x90\x33\x8c\x20\xe4\x21\xc5\x18\x42\xa8\x42\x49\x11\x86\ -\x30\x84\x4a\xd0\x98\x7b\x01\x81\x63\x89\x29\x62\x3e\x70\x0d\xe8\ -\x52\x00\x61\x34\xa4\x12\xfc\xf9\x14\x41\xf8\x10\x87\x18\x43\x20\ -\xb1\x80\x48\x9a\x88\x21\x4e\x05\xf6\x3a\xb4\xdf\x9b\x7b\x3d\xd8\ -\xef\xcd\xbd\x1e\xeb\xf7\xd6\x9e\xf3\x15\xf4\xce\x9c\xaf\xc0\x39\ -\x73\xbe\x02\xe7\x2c\x80\x74\x14\x1c\x11\x3f\x20\x14\x82\x46\x15\ -\x88\x08\x83\xac\x20\x08\x02\x05\x06\x4a\xc2\x59\x06\x18\x04\x8a\ -\x50\x13\x3c\xaa\x42\x88\x15\xc8\x5e\x2f\xe8\x9e\xa9\x32\x14\x2a\ -\x52\xc0\xc7\x8a\x81\xa8\x14\x50\x05\x9a\xb2\x0a\xa0\xfd\xbe\x24\ -\xcd\xa1\xd2\xa6\x83\x8d\x88\xe8\x76\xc6\x4a\x9f\xf6\x65\xd5\x04\ -\xe7\x74\x9f\x41\x33\x0c\x51\x4c\xb0\xe2\x78\x6e\xfc\x0e\x79\xfa\ -\x66\x24\x54\x35\xdd\xfe\x76\x12\x3d\x95\x3b\x1d\x9d\xe1\xde\xfa\ -\x1c\x7d\xe8\x5a\x7c\x1d\xfd\x9a\xac\xa2\x0f\x55\xb2\x69\xa2\x0c\ -\xe6\x5e\x5b\xe2\x1a\xee\x8b\xed\x68\xc8\xeb\x02\x0d\xc9\xa1\x24\ -\x52\x88\xdb\xbc\xc0\x8a\x31\x19\x63\x9b\x33\xe3\x67\x07\x61\xb1\ -\x34\x27\x14\xc2\x8f\x21\xde\x21\x63\x48\xdd\x5d\x44\x75\x0b\x21\ -\x45\xe3\x7e\x3a\x2d\xe6\x57\x3f\x08\x24\xd5\x7a\x31\x51\xb7\xd5\ -\xbe\xaf\xef\x2b\xa0\xad\xdf\x5b\xdf\xa5\x95\x62\xf5\xa3\xd7\xf7\ -\x69\x5a\x2f\x66\x83\x6e\x58\x28\x54\x03\x53\xc4\x24\x7f\x03\x62\ -\x6e\x21\xdc\x1c\x4b\x45\xe7\x11\x15\x0c\xc2\x64\xc8\x21\x3d\xde\ -\x42\x9c\xdf\x40\xd8\x1e\x44\x18\xd4\x74\x33\x03\xbf\xf7\x03\x05\ -\x0b\x99\x02\x22\xa1\xa6\x43\xdd\x21\x18\x2a\x80\xc0\xb1\xdf\x8f\ -\x01\x07\xba\x7b\x1a\x89\x7a\xbc\xa9\xb0\x4e\xed\x6c\xc7\x32\x67\ -\x03\x05\xd6\x79\x71\x4e\x06\xf5\x8c\xc5\xc8\x89\xd3\x3a\x17\xd7\ -\x93\x7a\x9d\x52\xb9\xef\x48\x7e\x60\x8c\xef\x6e\xaf\x7f\xa5\xb8\ -\xbb\x3c\x0d\x5d\xee\x9b\xdc\x7a\x2b\x17\xd8\xdb\xb9\x70\x7d\xb1\ -\xbc\xce\x85\xab\x1b\xe9\x55\x32\x5c\x5f\x7b\xaf\xb2\x01\xca\xb5\ -\x52\x18\x93\xb9\x74\xe0\x2a\x14\x48\x11\xec\x3b\x57\x36\x1f\x30\ -\xb4\x30\xa6\x20\x39\x02\xcc\x43\x1a\x0b\xa0\x8b\xdd\x28\x20\xea\ -\x5c\xaa\x91\x08\x43\xf5\x17\x92\x12\x93\x0f\x4e\x1d\x60\xd3\x4d\ -\x30\x19\x8b\x9c\x09\xa4\x83\x73\xd2\xf9\x88\x9d\x9a\x78\x57\x16\ -\xc4\xeb\x7c\x50\xf0\xe1\xb4\xad\x07\xac\xbc\xcb\x39\x91\x49\xcf\ -\x99\x27\xc8\x92\x43\x1b\x24\xd4\x94\x59\x4e\x98\x88\x39\x5c\xd8\ -\x47\x4f\x4e\x4d\xa1\xb7\x09\x25\x14\x81\xec\x03\x9a\xa4\x28\x91\ -\x77\xe3\x6e\x14\x6d\xbf\x4e\x9f\xbb\x1f\x47\x46\x8c\xd9\xfd\x52\ -\xf2\x47\x94\x57\x28\x38\x3f\x7a\x79\x6d\xe9\x33\xd0\x32\x0e\xa4\ -\xd9\x90\x1b\xd8\x6d\x24\xf9\x88\x3d\x9b\x1d\x6b\x59\x28\x64\x88\ -\x14\xc2\xb2\x67\x0a\xcf\x7c\x2a\x35\xe4\x14\x61\x16\x0f\xe4\x59\ -\x18\xf2\x0c\x7d\x95\x63\xd2\xd2\x64\x03\x8d\xbd\xa9\x51\x2f\x9d\ -\x90\xe7\x76\x24\xcb\x9d\xad\xfd\x48\x34\x58\x0c\xd4\x99\xb7\xd4\ -\xd9\xcc\xa9\x25\xc9\x76\x1e\xc1\xd8\xa8\x93\x0d\xbc\x19\xc1\x55\ -\x6d\xe0\xcd\xaa\xe3\xcd\x40\xf3\x31\xb6\x2c\x10\x58\x2a\x19\x89\ -\xdc\x93\x23\xce\xcc\xf2\x66\x8b\xb3\x5a\x4c\x29\xe9\x28\xf0\x60\ -\xd2\x09\x3b\x8b\x9e\x35\x5b\xa9\x65\xcd\x52\x48\x19\x4f\x84\x83\ -\xd5\x05\x6f\xb6\x50\x7f\x18\xdf\xbb\x30\x6a\x85\x73\x7c\x90\xd1\ -\x49\xb1\xfc\x56\x36\xd8\x9d\x3e\xfb\x75\x6f\x7e\x31\x78\xbc\xf9\ -\x37\x48\xea\xec\x50\ +\x00\x00\x15\x1c\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x43\x65\x6e\x74\x65\ +\x72\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\x78\x74\x65\x6e\x73\ +\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\x67\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\ +\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\x73\x32\x37\ +\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\ +\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\ +\x65\x6e\x74\x33\x31\x34\x34\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ +\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\ +\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\ +\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\ +\x31\x34\x36\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\ +\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\ +\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\ +\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\ +\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\ +\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\ +\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\ +\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x65\ +\x63\x74\x69\x76\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\ +\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x33\x64\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\ +\x5f\x78\x3d\x22\x30\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\x20\x31\x30\x30\x30\x20\x3a\ +\x20\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x76\x70\x5f\x7a\x3d\x22\x36\x34\x20\x3a\x20\x33\ +\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x33\x64\x2d\x6f\ +\x72\x69\x67\x69\x6e\x3d\x22\x33\x32\x20\x3a\x20\x32\x31\x2e\x33\ +\x33\x33\x33\x33\x33\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\ +\x65\x32\x37\x33\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\ +\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\ +\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\ +\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x33\x31\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\ +\x33\x38\x35\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\ +\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\ +\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\ +\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\ +\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\ +\x30\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\ +\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\ +\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x66\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\ +\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\ +\x33\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ +\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\ +\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\ +\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x33\x31\x34\x34\x2d\x37\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\ +\x65\x6e\x74\x33\x38\x35\x30\x2d\x32\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\ +\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\ +\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\ +\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\ +\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\ +\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\ +\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\x37\x32\ +\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\ +\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\ +\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\ +\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\ +\x34\x34\x2d\x37\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\ +\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\ +\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\ +\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\ +\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x36\ +\x2d\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\ +\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\ +\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\ +\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\ +\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x38\ +\x2d\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\ +\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\ +\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\ +\x35\x31\x38\x38\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\ +\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\ +\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\ +\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\ +\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\ +\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\ +\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\ +\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\ +\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x34\x33\x37\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\ +\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x37\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\ +\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x20\x2f\x3e\x0a\ +\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\x64\ +\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0a\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\x20\ +\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\ +\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\ +\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\ +\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\ +\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\ +\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\ +\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x33\x2e\x38\ +\x38\x39\x30\x38\x37\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x32\x38\x2e\x31\x31\x37\ +\x31\x32\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x63\x79\x3d\x22\x35\x33\x2e\x36\x36\x35\x37\x37\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\x67\ +\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x73\x68\x6f\x77\x67\ +\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\ +\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x69\x64\x2d\ +\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\ +\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\ +\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\x35\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\ +\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\ +\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\x78\x69\ +\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\ +\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x37\x33\x31\x22\x3e\ +\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\ +\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\ +\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\ +\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\ +\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\ +\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\ +\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\ +\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\x74\x70\ +\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\ +\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\ +\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\ +\x64\x63\x3a\x74\x69\x74\x6c\x65\x20\x2f\x3e\x0a\x20\x20\x20\x20\ +\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\ +\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\ +\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\ +\x62\x65\x6c\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\ +\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\ +\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x74\ +\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\ +\x28\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\x30\ +\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\x39\ +\x38\x36\x2c\x2d\x36\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\ +\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\ +\x23\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\ +\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\ +\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\ +\x23\x30\x30\x32\x65\x32\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3a\x35\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\ +\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\ +\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\ +\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\ +\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\ +\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\ +\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\ +\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\ +\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\ +\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\ +\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ +\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x33\x31\x2e\x37\x35\ +\x20\x34\x2e\x33\x31\x32\x35\x20\x43\x20\x31\x36\x2e\x38\x39\x33\ +\x39\x37\x34\x20\x34\x2e\x33\x31\x32\x35\x20\x34\x2e\x38\x37\x35\ +\x20\x31\x36\x2e\x33\x36\x32\x37\x32\x34\x20\x34\x2e\x38\x37\x35\ +\x20\x33\x31\x2e\x32\x31\x38\x37\x35\x20\x43\x20\x34\x2e\x38\x37\ +\x35\x20\x34\x36\x2e\x30\x37\x34\x37\x37\x37\x20\x31\x36\x2e\x38\ +\x39\x33\x39\x37\x34\x20\x35\x38\x2e\x30\x39\x33\x37\x35\x20\x33\ +\x31\x2e\x37\x35\x20\x35\x38\x2e\x30\x39\x33\x37\x35\x20\x43\x20\ +\x34\x36\x2e\x36\x30\x36\x30\x32\x36\x20\x35\x38\x2e\x30\x39\x33\ +\x37\x35\x20\x35\x38\x2e\x36\x35\x36\x32\x35\x20\x34\x36\x2e\x30\ +\x37\x34\x37\x37\x37\x20\x35\x38\x2e\x36\x35\x36\x32\x35\x20\x33\ +\x31\x2e\x32\x31\x38\x37\x35\x20\x43\x20\x35\x38\x2e\x36\x35\x36\ +\x32\x35\x20\x31\x36\x2e\x33\x36\x32\x37\x32\x34\x20\x34\x36\x2e\ +\x36\x30\x36\x30\x32\x36\x20\x34\x2e\x33\x31\x32\x35\x20\x33\x31\ +\x2e\x37\x35\x20\x34\x2e\x33\x31\x32\x35\x20\x7a\x20\x4d\x20\x33\ +\x31\x2e\x37\x35\x20\x31\x33\x2e\x34\x36\x38\x37\x35\x20\x43\x20\ +\x34\x31\x2e\x35\x33\x38\x39\x35\x31\x20\x31\x33\x2e\x34\x36\x38\ +\x37\x35\x20\x34\x39\x2e\x35\x20\x32\x31\x2e\x34\x32\x39\x38\x30\ +\x31\x20\x34\x39\x2e\x35\x20\x33\x31\x2e\x32\x31\x38\x37\x35\x20\ +\x43\x20\x34\x39\x2e\x35\x20\x34\x31\x2e\x30\x30\x37\x37\x30\x32\ +\x20\x34\x31\x2e\x35\x33\x38\x39\x35\x31\x20\x34\x38\x2e\x39\x33\ +\x37\x35\x20\x33\x31\x2e\x37\x35\x20\x34\x38\x2e\x39\x33\x37\x35\ +\x20\x43\x20\x32\x31\x2e\x39\x36\x31\x30\x34\x39\x20\x34\x38\x2e\ +\x39\x33\x37\x35\x20\x31\x34\x2e\x30\x33\x31\x32\x35\x20\x34\x31\ +\x2e\x30\x30\x37\x37\x30\x32\x20\x31\x34\x2e\x30\x33\x31\x32\x35\ +\x20\x33\x31\x2e\x32\x31\x38\x37\x35\x20\x43\x20\x31\x34\x2e\x30\ +\x33\x31\x32\x35\x20\x32\x31\x2e\x34\x32\x39\x38\x30\x31\x20\x32\ +\x31\x2e\x39\x36\x31\x30\x34\x39\x20\x31\x33\x2e\x34\x36\x38\x37\ +\x35\x20\x33\x31\x2e\x37\x35\x20\x31\x33\x2e\x34\x36\x38\x37\x35\ +\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\ +\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\ +\x36\x2e\x31\x36\x37\x39\x35\x38\x34\x2c\x30\x2c\x30\x2c\x36\x2e\ +\x31\x36\x37\x39\x35\x38\x34\x2c\x2d\x33\x39\x2e\x32\x33\x31\x39\ +\x30\x38\x2c\x34\x30\x37\x2e\x37\x35\x36\x33\x37\x29\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\ +\x34\x33\x36\x34\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\ +\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\ +\x22\x6d\x20\x32\x34\x35\x2e\x37\x31\x34\x32\x38\x2c\x36\x35\x35\ +\x2e\x32\x31\x39\x33\x20\x61\x20\x34\x38\x2e\x35\x37\x31\x34\x33\ +\x2c\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x30\x20\x31\x20\x31\x20\ +\x2d\x39\x37\x2e\x31\x34\x32\x38\x36\x2c\x30\x20\x34\x38\x2e\x35\ +\x37\x31\x34\x33\x2c\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x30\x20\ +\x31\x20\x31\x20\x39\x37\x2e\x31\x34\x32\x38\x36\x2c\x30\x20\x7a\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\ +\x6f\x64\x69\x3a\x72\x79\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\x33\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\ +\x6f\x64\x69\x3a\x72\x78\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\x33\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\ +\x6f\x64\x69\x3a\x63\x79\x3d\x22\x36\x35\x35\x2e\x32\x31\x39\x33\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\ +\x6f\x64\x69\x3a\x63\x78\x3d\x22\x31\x39\x37\x2e\x31\x34\x32\x38\ +\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x70\x61\x74\x68\x33\x31\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x23\ +\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\ +\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\ +\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\ +\x30\x30\x32\x65\x32\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\ +\x64\x74\x68\x3a\x33\x30\x2e\x38\x33\x39\x37\x39\x32\x37\x36\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\ +\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\ +\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ +\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\ +\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\ +\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\ +\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\ +\x6c\x61\x74\x65\x3b\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\ +\x30\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\ +\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\ +\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x2d\x30\x2e\x39\ +\x38\x30\x39\x30\x35\x30\x35\x2c\x30\x2e\x31\x39\x34\x34\x38\x37\ +\x31\x34\x2c\x2d\x30\x2e\x31\x39\x34\x34\x38\x37\x31\x34\x2c\x2d\ +\x30\x2e\x39\x38\x30\x39\x30\x35\x30\x35\x2c\x34\x37\x38\x2e\x31\ +\x33\x32\x30\x32\x2c\x31\x32\x30\x33\x2e\x34\x34\x30\x39\x29\x22\ +\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\ +\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ \x00\x00\x08\x8b\ \x00\ \x00\x1c\x9e\x78\x9c\xed\x58\xdf\x8f\x9b\x48\x12\x7e\xcf\x5f\xe1\ @@ -27041,140 +27237,300 @@ qt_resource_data = "\ \x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\ \x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\ \x73\x76\x67\x3e\x0a\ -\x00\x00\x08\x37\ -\x00\ -\x00\x1c\x3d\x78\x9c\xed\x58\x5b\x6f\xdb\xc8\x15\x7e\xf7\xaf\x60\ -\xe9\x97\x18\x15\x87\x73\xe3\x70\xa8\x58\xde\x87\xa6\x5b\x2c\xb0\ -\x40\x81\x4d\x82\x7d\x0c\x28\x72\x24\xb3\xa6\x48\x81\xa4\x2c\xc9\ -\xbf\xbe\xdf\xf0\x26\xca\x92\xd3\xa0\xdd\xa6\x40\x50\x05\xb1\xc8\ -\x73\x99\x73\x99\x6f\xce\x39\xa3\xfb\x9f\x0e\x9b\xdc\x79\x36\x55\ -\x9d\x95\xc5\xc2\x65\x84\xba\x8e\x29\x92\x32\xcd\x8a\xf5\xc2\xfd\ -\xfc\xe9\x67\x4f\xbb\x4e\xdd\xc4\x45\x1a\xe7\x65\x61\x16\x6e\x51\ -\xba\x3f\x3d\xdc\xdc\xff\xc9\xf3\x9c\xbf\x54\x26\x6e\x4c\xea\xec\ -\xb3\xe6\xd1\xf9\xa5\x78\xaa\x93\x78\x6b\x9c\x77\x8f\x4d\xb3\x9d\ -\xfb\xfe\x7e\xbf\x27\x59\x4f\x24\x65\xb5\xf6\xef\x1c\xcf\x7b\xb8\ -\xb9\xb9\xaf\x9f\xd7\x37\x8e\xe3\xc0\x6e\x51\xcf\xd3\x64\xe1\xf6\ -\x0a\xdb\x5d\x95\xb7\x82\x69\xe2\x9b\xdc\x6c\x4c\xd1\xd4\x3e\x23\ -\xcc\x77\x4f\xe2\xc9\x49\x3c\xb1\xd6\xb3\x67\x93\x94\x9b\x4d\x59\ -\xd4\xad\x66\x51\xdf\x4e\x84\xab\x74\x35\x4a\x5b\x6f\xf6\xa2\x15\ -\x62\x51\x14\xf9\x94\xfb\x9c\x7b\x90\xf0\xea\x63\xd1\xc4\x07\xef\ -\x5c\x15\x3e\x5e\x53\xe5\x94\x52\x1f\xbc\x93\xe4\xb7\x49\xcd\x0f\ -\x39\x52\xf1\xa6\x33\x2d\x77\x6a\x1d\xe9\xdf\xe2\xff\xa8\x30\x10\ -\x48\x5d\xee\xaa\xc4\xac\xa0\x69\x48\x61\x1a\xff\xc3\xa7\x0f\x23\ -\xd3\xa3\x24\x6d\xd2\xc9\x32\x43\xf6\xcf\xec\x9e\x6d\x49\x11\x6f\ -\x4c\xbd\x8d\x13\x53\xfb\x03\xbd\xd5\xdf\x67\x69\xf3\xb8\x70\x95\ -\xdc\x1e\xda\xf7\x47\x93\xad\x1f\x9b\x09\x21\x4b\x17\x2e\x22\xe4\ -\x21\x57\xed\xfb\xe0\xc3\x7c\x44\x12\x25\x82\x77\xa2\xfd\xc2\x53\ -\x96\xd4\x84\x39\x55\x14\x2a\x7a\xae\x9d\x96\x89\x75\x69\xe1\x7e\ -\x2c\xe2\xed\x97\xbf\x16\xe9\xb6\xcc\x8a\x86\x0c\xb9\x1c\x97\x2a\ -\x77\xcd\x76\xd7\x7c\x31\x87\xc6\x14\xdd\x9a\x88\x66\x12\x5a\xcb\ -\xb6\x6a\xe4\x2c\xac\x09\xcc\x99\xfb\x00\xca\x7d\x6a\x56\xb5\xe5\ -\x74\x11\xd9\x37\x84\xa4\x5b\x1e\xb8\x55\x9c\x66\x71\xfe\x37\xfb\ -\x05\x30\x76\x72\x13\x2f\x92\x32\xcf\x4d\x82\xb4\xc4\xf9\x3e\x3e\ -\xd6\xee\x20\xd0\x6e\xe7\xfc\xb1\x32\x80\xdf\x2d\x9e\x4d\x5c\x0d\ -\x6b\x08\x26\xe5\x28\x67\x4d\x9e\x9b\x90\x3c\x3c\xb1\xd7\x3d\xf1\ -\x73\x91\x35\xc0\xd9\xae\x36\xd5\x47\xbb\x57\x7f\x2f\x3e\xd7\xe6\ -\x42\xea\x53\x15\x17\x35\x80\xb1\x59\xb8\x9b\xb8\xa9\xb2\xc3\x3b\ -\x36\xa3\xf6\x1f\x51\x91\x0e\x78\x24\xf1\xcc\x29\x27\x9a\x6b\x25\ -\xee\x46\xf5\xe4\xb0\x70\x39\x0f\x08\x57\x92\xf2\x13\xf5\x88\xbd\ -\x0e\x39\x09\xa3\x50\xa8\x91\xba\xba\x2a\xbb\xba\x2a\x5b\x2d\x5c\ -\x21\x89\x90\x01\xd3\x28\x20\x7e\x9f\xd0\xf3\x64\x7c\x73\x42\x6d\ -\xa2\xae\xe4\xf1\xa1\xe7\xdf\xd7\x4d\xb9\x1d\x64\x81\xa6\xe6\x98\ -\x03\x42\x96\xe8\x61\xc5\xb2\x9a\xdf\xae\xda\xcf\xfb\x96\x54\x22\ -\x87\x59\x73\x9c\xb3\xf7\xee\x49\xa7\x5c\xad\x6a\x03\xc3\x74\x42\ -\x6b\x31\x0e\x0d\xd8\x52\x63\x08\xff\xae\x35\x7a\xcd\x1a\xbb\x6e\ -\x6d\x92\x30\xff\x3c\xec\xff\x21\x2e\xf9\x8f\x8c\xcb\x31\x75\x5b\ -\x54\x88\x2d\x72\x87\xbe\x32\x68\x8c\xc5\xa9\x39\xda\x52\x7a\x2e\ -\x2a\x52\xf7\x22\xfd\xcf\xdb\x2f\x70\x88\x3a\x73\x47\x70\xfc\x61\ -\x57\x25\x8e\x9d\x04\x43\xab\xc0\x17\xbd\x2a\xf3\x62\x0b\xee\x57\ -\x96\xe9\x3d\xf0\xca\x2a\x5b\x67\xa8\x6a\xad\x1c\x67\x44\xb4\x9f\ -\x73\x1d\x6c\xe9\x24\x36\x1e\x0a\x79\x8a\xfe\xbb\xc3\x49\xe8\x80\ -\xfe\xc8\x70\xfa\xef\x24\xd4\x0b\xff\x45\x4a\xbd\xe8\x47\x4e\xea\ -\x1f\xda\x3b\x90\xcb\xef\xd8\x3d\x3c\xfa\x7d\xfb\x87\x27\xbe\xda\ -\x41\xee\x7d\x3b\xe8\xb4\x4f\x63\x71\xb3\x63\x57\xfa\x9c\x99\xfd\ -\x69\x1a\x5a\xc6\x23\x54\xb6\xf1\xda\xb4\xce\x01\x98\x9d\x77\x3d\ -\x63\x59\x56\xa9\xa9\x06\x96\x6a\x3f\x67\xac\xde\xff\xee\x66\x71\ -\x73\xbe\x65\x76\xd5\x91\x4f\xaf\xf3\xeb\xc7\x38\x2d\xf7\xc0\xce\ -\x6b\xe6\x4b\x59\x02\xae\x82\x68\x1d\x51\x1d\x8a\xd7\x6c\x8b\x4d\ -\xcf\xe2\x8d\x29\xca\xe5\x05\x17\x06\xc1\xd4\x54\xe9\xf0\x92\xb9\ -\xab\x2a\x64\xca\xcb\xe3\xa3\x41\x54\x6b\xc9\xf5\x70\xb0\xea\xc7\ -\x72\xbf\xae\x6c\x72\x9a\x6a\x67\x5e\x2b\x62\x7a\xdd\xd9\x5b\x8b\ -\xb7\xeb\x4e\x5d\x3f\x2b\x4f\x24\xac\xae\xb7\x5c\x96\x87\xeb\x0b\ -\xec\xb3\x02\xc1\x7a\xfd\xf4\xcd\xb8\xbe\x48\x49\x2f\x31\xcc\xe3\ -\x61\x10\xbc\x21\x71\x38\xa1\xf1\x35\xcb\xc6\x7e\x91\xce\x9e\xb7\ -\x89\x0f\xd9\x26\x7b\x31\xa9\x05\x57\x87\xa1\xfb\x8d\x69\xe2\x34\ -\x6e\xe2\x13\x32\x06\x0a\xda\x08\x1b\x67\xe5\x74\x35\xff\xed\xc3\ -\xcf\x23\xca\x93\x64\xfe\x7b\x59\x3d\x9d\x00\x6a\x05\xe2\x25\x46\ -\xf3\x85\x3b\x9e\x3d\x3b\x81\x27\x73\x5b\x79\xe2\xe6\x21\xdb\x60\ -\xbf\xed\xbd\xe9\xcf\xb8\xbe\x00\xa3\x23\xe3\x4c\xd8\x76\xe1\xd3\ -\xa2\xdd\xb2\x95\xe9\xee\x45\x57\xaf\x92\x69\xb2\xc9\xac\x92\xff\ -\xb1\xc9\xf2\xfc\x17\x6b\x64\x72\x1a\xfb\x45\xb3\x26\x37\x0f\xad\ -\xcd\xee\x71\x88\xc2\xef\xc3\x18\x0e\xd3\x24\xca\x7b\x7f\x48\x43\ -\xfb\xb6\x3e\xa5\xa7\x05\x0e\x7b\x9d\xe1\x3c\x5e\x9a\x7c\xe1\xfe\ -\x6a\x99\xce\x05\x77\x5d\x95\xbb\xed\xa6\x4c\x4d\xaf\x3e\xa4\x75\ -\x3d\xad\x63\x53\x28\x3a\x4e\x73\x51\xb5\x29\x61\x8a\x03\x36\xbc\ -\xaf\xde\xc3\x9b\x22\x42\xd1\x20\xd2\x6a\xe6\x29\x45\x18\xd5\x00\ -\xfe\xdd\xa9\x00\x6e\xe3\xe6\xf1\xa2\x20\x8d\x85\x87\x04\xba\x1b\ -\x28\xde\xaf\x90\xbf\xf9\x2d\x6d\x3f\xed\xcb\xa4\x1a\xb6\xaf\xd5\ -\x2e\x37\xf3\xa2\x2c\x5e\x70\xee\x51\xbe\xaa\xf2\xc9\x8c\xf2\xdd\ -\x6b\x87\xed\xb9\x3d\x7a\xf8\xc0\xbf\x81\x6e\xab\x14\x12\x31\x5f\ -\xee\x9a\x66\x4a\xfb\x07\x2e\x80\x73\x6c\xa0\xa9\x06\x6a\xfb\x92\ -\x03\xa5\xcd\x5c\x0e\xb4\x93\x1f\x3d\x21\x8d\x51\x38\xaa\x2a\x3e\ -\x5a\x77\xcc\x94\xda\xd5\x4e\xd4\xd3\x4d\x5c\x3d\x99\xaa\xe3\x3f\ -\x67\x75\xb6\xcc\x72\xbb\x44\xfb\x98\x9b\xf7\x69\x56\x6f\xb1\x13\ -\xb8\x44\x5b\x37\xde\x97\xb8\x3b\xae\xf2\x72\x3f\xf2\x4d\x11\xe3\ -\xcb\x5b\xc6\xc9\x93\xdd\xbb\x22\x9d\xc7\x09\x8e\xff\x2e\x8f\x1b\ -\x33\x29\xcb\xf6\xb4\x38\xb8\xd5\x91\x30\x0c\x18\x9b\x05\x3c\xc4\ -\xae\x08\xce\x1d\x4f\x73\x22\xa8\x08\x67\xe0\x51\x16\x04\x4e\xe2\ -\x78\x8a\xc8\x48\x4a\x39\xf3\x04\x91\x4a\x85\x91\xe3\x31\x41\x42\ -\x1e\x70\x36\xf3\x02\xa2\xa8\xd0\xd0\xc3\x80\x17\xe8\x50\x07\x96\ -\x14\x6a\x2e\x15\x48\x8a\x68\xa6\x05\x14\xd1\xb1\x69\x24\x1c\x4f\ -\x46\x84\xb1\x48\x87\x68\xdb\x68\xae\xd8\xfb\x96\x14\xf2\x88\x85\ -\x33\x19\x42\x48\x5b\x29\x20\x24\x90\x92\x01\x1f\x61\xa4\xa4\x70\ -\x18\x81\xa7\x42\xcc\x60\x95\xa1\xf9\x4a\x47\x10\xa5\x38\x07\x21\ -\x22\x54\x03\x4b\x4e\xee\x78\x51\x40\x24\xa3\x8a\xca\x99\x86\x03\ -\xa8\x00\xa1\x03\x23\x54\x06\x5a\x05\x33\x8e\xa0\x02\xad\x03\x27\ -\x92\x44\x89\x08\xce\xcc\x3c\x88\x51\xca\x99\x46\x84\x08\x5e\x52\ -\x11\xcc\x24\x91\x01\xb6\xdf\x61\x58\x2b\xd0\x8c\xcf\x42\xeb\x6e\ -\xc0\x1c\x0e\x0e\xfc\xd5\x20\x08\x2e\x11\xdb\x18\x5a\x1b\x19\x8f\ -\x9c\x31\x32\x0f\x56\x83\x08\x89\x70\xc6\xc8\x3c\x84\x26\x99\x62\ -\x91\x83\xc8\x34\x8b\x04\x8c\xc3\x76\xa8\x18\x32\x69\x65\x42\xb8\ -\x03\x9b\x88\x89\x83\x04\xbf\x18\x93\x76\xa5\xce\x6b\x89\xf0\x34\ -\xb2\x2b\x38\x68\xa1\x20\x70\x00\x2e\x79\x43\x74\xa3\x5c\xe0\xbc\ -\xbc\x6a\xbc\x15\x26\x0f\xce\x55\x34\x19\xd1\xce\x46\x93\x02\xe0\ -\x6e\xca\xca\x43\x6b\x79\x8e\x9b\x5d\x65\x6c\x75\x9e\x8c\x04\x56\ -\xff\xa4\x78\xed\x60\x2b\xa5\x83\x88\x46\x21\xf2\x80\x2d\x52\x40\ -\x8e\xb2\xbb\x3d\x3e\x4f\x25\x66\xf4\x6e\xe2\x86\xed\xbd\x4c\x23\ -\x8b\x54\x4d\xa8\xe8\x0f\x88\x93\x44\xd8\xdd\x09\x75\xe8\x2b\x42\ -\x20\x66\x6c\x10\x9f\xf0\xfa\xae\xd4\x71\x28\xd5\x6f\xa4\xc0\xbd\ -\xa8\x24\x5d\xd9\xe8\x87\x9a\xff\x97\x8d\xaf\x94\x8d\x09\x22\xd6\ -\x57\x70\x64\x0e\xdb\xb2\x6a\xbc\x63\xba\xcd\xd0\xfa\x09\x0d\xb9\ -\x3d\x33\xd7\x10\xd7\x4b\x1e\xbe\x59\x12\xfb\x60\xba\x5f\xde\xfc\ -\xc7\x72\x63\xfc\x23\xee\x94\x4f\xfe\x87\x7e\xa0\xa9\xfd\x5f\xe3\ -\xa5\xff\xa1\x8a\x57\x8d\x9f\x01\xcd\x75\x3b\x54\x92\x6d\xb1\x76\ -\xbf\x86\x5a\xe0\x33\x8a\xa2\x50\x72\x8b\x54\xca\x79\xc8\x44\x80\ -\x8b\xc5\xe9\xf1\x24\x80\x61\x1f\x87\x31\x54\x28\x35\x28\x77\x70\ -\x38\x0a\xef\x5e\x01\x6c\x2d\x30\xca\x4d\x27\x87\xf3\xb6\x75\x71\ -\x51\x8f\xab\xc4\x3d\x63\x4f\xd1\x48\xe9\x12\x77\x99\x3f\x04\x8d\ -\x94\x45\x3f\x26\x1a\xa7\xc9\x6b\x7f\x3f\x40\xbe\xb1\x07\xdc\xbd\ -\x9a\x74\x3b\x70\xb3\xc8\x16\x78\xae\x83\x37\x44\xec\x6d\x2f\xb0\ -\x33\x79\x24\xae\x4b\x54\x58\x44\x6a\x12\x84\x4c\xbe\x25\x71\x7c\ -\x43\xa2\x6b\xb4\x80\x51\x68\x3d\x98\x0d\x76\xd0\x74\x70\x77\x45\ -\x13\x01\xac\x54\xdb\x3c\x43\xa9\x6c\x13\xec\xd7\x40\x5f\xec\x9f\ -\x26\xa4\x41\x7e\x46\x27\xec\x51\x77\x4a\x1b\x75\xe8\x6c\xd4\x72\ -\x46\x23\x27\xf6\x15\x8d\x89\x91\x91\x3b\x9a\xb8\x74\xea\xe5\x7c\ -\x68\xfd\x0f\xc0\x8f\xd9\xf8\xdd\xed\xe5\xaf\x07\x77\xaf\x4f\x43\ -\x8f\x7d\x8b\xad\xb7\xb0\x20\xdf\xc6\xc2\xe5\x65\xff\x12\x0b\x17\ -\x37\xff\x0b\x30\x9c\x7e\x07\x78\x13\x0d\x5c\xa0\x88\x30\xc6\xaf\ -\xc1\x21\x88\xda\xa9\x01\x13\xce\x60\xaa\xc5\x03\xb3\xbd\x3d\xb2\ -\x13\x10\x86\x01\x11\x2a\xf4\xf6\x7e\x15\x90\x7a\x93\xd1\x84\x84\ -\xf6\x19\x29\x2d\xb8\xc5\xc3\xc8\xf6\x98\x6d\xbf\x98\x89\x26\xa4\ -\x51\x05\x70\x18\x8d\xf4\x36\xc2\x91\xcd\x9d\x0b\x0d\xee\xf4\x36\ -\x04\x6c\x8c\xdc\xce\x02\xc6\x99\xd7\x3e\xf1\xb3\x09\xe4\xfa\xc4\ -\xa0\x03\x26\x28\x66\x37\x14\xd9\x00\x53\x62\x18\xd8\x19\xea\xf4\ -\x34\xb2\x85\xd0\x44\x45\x2a\xe2\x40\x9f\x24\x38\x32\x5c\xdf\x4d\ -\x3b\x91\xbf\x1e\x2e\x3f\xeb\xee\xda\x83\xaf\x7b\x7b\x4d\x7b\xb8\ -\xf9\x27\xa5\x63\xc0\x92\ +\x00\x00\x12\x3b\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x4d\x69\x64\x70\x6f\ +\x69\x6e\x74\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\x78\x74\x65\ +\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\x67\x2e\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\x65\x72\x73\ +\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\x20\x20\x3c\x64\x65\ +\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\x73\ +\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\ +\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\ +\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\ +\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\ +\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\ +\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x32\x37\ +\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\ +\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\ +\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\ +\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\ +\x30\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\ +\x38\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\ +\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\ +\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\ +\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x66\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\ +\x31\x38\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\ +\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\ +\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\ +\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\ +\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\ +\x6f\x70\x33\x31\x34\x36\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\ +\x33\x31\x34\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\ +\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\ +\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\ +\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\ +\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x34\x32\x37\x32\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\ +\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\ +\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\ +\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\ +\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\ +\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\ +\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\x37\x32\ +\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\ +\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\ +\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x33\x64\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\x20\x33\x32\x20\x3a\ +\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\x20\x31\x30\ +\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x7a\x3d\x22\x36\x34\ +\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\ +\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\x33\x32\x20\x3a\x20\ +\x32\x31\x2e\x33\x33\x33\x33\x33\x33\x20\x3a\x20\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x65\x72\x73\x70\x65\ +\x63\x74\x69\x76\x65\x32\x37\x33\x34\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\ +\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\ +\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x37\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x2d\x39\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\ +\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\ +\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\ +\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\ +\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\ +\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\ +\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\ +\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\ +\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\ +\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\ +\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\ +\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\ +\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x33\x31\x34\x34\x2d\x37\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ +\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\ +\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\ +\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\ +\x31\x34\x36\x2d\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ +\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\ +\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\x70\ +\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\ +\x31\x34\x38\x2d\x33\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\ +\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\ +\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\x64\ +\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0a\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\x20\ +\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\ +\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\ +\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\ +\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\ +\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\ +\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\ +\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x33\x2e\x38\ +\x38\x39\x30\x38\x37\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x2d\x32\x35\x2e\x32\x31\ +\x36\x30\x32\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x63\x79\x3d\x22\x32\x35\x2e\x38\x30\x36\x38\x37\ +\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\ +\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x73\x68\x6f\x77\ +\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\ +\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x69\x64\ +\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\ +\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\ +\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\x35\x22\ +\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\ +\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\ +\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\x78\ +\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\x20\x20\ +\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\ +\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x37\x33\x31\x22\ +\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\ +\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\ +\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\ +\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\ +\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\ +\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\ +\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\ +\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\ +\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x20\x2f\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\ +\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\ +\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\ +\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\ +\x61\x62\x65\x6c\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\ +\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\ +\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\ +\x78\x28\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\ +\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\ +\x39\x38\x36\x2c\x2d\x36\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\ +\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\ +\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\ +\x3a\x23\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\ +\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\ +\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\ +\x3a\x23\x30\x30\x32\x65\x32\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3a\x32\x39\x2e\x34\x39\x34\x33\x34\x36\x36\ +\x32\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ +\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\ +\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\ +\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\ +\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\ +\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\ +\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\ +\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\ +\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\ +\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\ +\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\ +\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x64\x3d\x22\x6d\x20\x32\x38\x32\x2e\x31\x31\x33\x38\x37\x2c\ +\x34\x34\x39\x2e\x36\x37\x34\x35\x35\x20\x2d\x39\x34\x2e\x37\x30\ +\x34\x38\x39\x2c\x38\x36\x2e\x39\x36\x35\x39\x38\x20\x63\x20\x2d\ +\x39\x2e\x32\x32\x34\x38\x32\x2c\x2d\x33\x2e\x39\x31\x32\x33\x35\ +\x20\x2d\x31\x39\x2e\x33\x33\x37\x38\x34\x2c\x2d\x36\x2e\x32\x37\ +\x32\x33\x20\x2d\x32\x39\x2e\x39\x32\x36\x30\x32\x2c\x2d\x36\x2e\ +\x35\x31\x37\x37\x39\x20\x2d\x34\x35\x2e\x37\x32\x38\x36\x38\x2c\ +\x2d\x31\x2e\x30\x36\x30\x32\x37\x20\x2d\x38\x33\x2e\x36\x32\x39\ +\x38\x31\x33\x2c\x33\x36\x2e\x30\x31\x35\x31\x39\x20\x2d\x38\x34\ +\x2e\x36\x36\x38\x37\x33\x39\x2c\x38\x32\x2e\x36\x38\x32\x38\x35\ +\x20\x2d\x30\x2e\x32\x30\x31\x32\x36\x2c\x39\x2e\x30\x34\x30\x35\ +\x34\x20\x31\x2e\x30\x37\x33\x30\x33\x33\x2c\x31\x37\x2e\x36\x35\ +\x38\x36\x38\x20\x33\x2e\x34\x36\x37\x30\x33\x38\x2c\x32\x35\x2e\ +\x38\x38\x34\x39\x35\x20\x6c\x20\x2d\x39\x32\x2e\x38\x38\x30\x31\ +\x34\x32\x2c\x38\x35\x2e\x32\x38\x39\x39\x37\x20\x34\x33\x2e\x34\ +\x32\x39\x32\x32\x31\x2c\x34\x39\x2e\x33\x34\x39\x20\x39\x31\x2e\ +\x30\x35\x35\x33\x38\x32\x2c\x2d\x38\x33\x2e\x36\x31\x33\x39\x37\ +\x20\x63\x20\x31\x30\x2e\x37\x39\x33\x36\x35\x2c\x35\x2e\x36\x36\ +\x30\x31\x34\x20\x32\x32\x2e\x38\x31\x38\x33\x31\x2c\x39\x2e\x31\ +\x39\x37\x31\x37\x20\x33\x35\x2e\x37\x36\x35\x32\x35\x2c\x39\x2e\ +\x34\x39\x37\x33\x36\x20\x34\x35\x2e\x37\x32\x38\x36\x38\x2c\x31\ +\x2e\x30\x36\x30\x32\x36\x20\x38\x33\x2e\x38\x31\x32\x32\x38\x2c\ +\x2d\x33\x36\x2e\x30\x31\x35\x31\x39\x20\x38\x34\x2e\x38\x35\x31\ +\x32\x2c\x2d\x38\x32\x2e\x36\x38\x32\x38\x36\x20\x30\x2e\x32\x35\ +\x33\x37\x31\x2c\x2d\x31\x31\x2e\x33\x39\x36\x30\x37\x20\x2d\x31\ +\x2e\x38\x37\x30\x31\x36\x2c\x2d\x32\x32\x2e\x32\x30\x33\x35\x37\ +\x20\x2d\x35\x2e\x36\x35\x36\x37\x34\x2c\x2d\x33\x32\x2e\x32\x31\ +\x36\x35\x31\x20\x6c\x20\x39\x32\x2e\x38\x38\x30\x31\x34\x2c\x2d\ +\x38\x35\x2e\x32\x38\x39\x39\x37\x20\x2d\x34\x33\x2e\x36\x31\x31\ +\x37\x2c\x2d\x34\x39\x2e\x33\x34\x39\x30\x31\x20\x7a\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\ +\x32\x32\x36\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\ +\x72\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\ +\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\ +\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ \x00\x00\x0d\x5b\ \x00\ \x00\x43\x5b\x78\x9c\xed\x5b\x59\x6f\xe3\x46\x12\x7e\x9f\x5f\xc1\ @@ -28539,7 +28895,7 @@ qt_resource_data = "\ \x1d\xf9\xce\x6b\x06\xfa\x4c\x06\x12\xcf\xe8\xb8\xe7\x33\x90\xb0\ \xbf\xf3\x0c\xd4\x7f\x6c\x3f\x84\x5f\x17\xf4\x27\xb6\xef\xbe\xf9\ \x6f\x78\x95\xb1\x1d\ -\x00\x00\x18\x63\ +\x00\x00\x0c\xed\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ \x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ @@ -28697,241 +29053,57 @@ qt_resource_data = "\ \x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\ \x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\ \x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\x63\x3a\ -\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\ -\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\ -\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\ -\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\ -\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\ -\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\x3d\x22\ -\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ -\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\ -\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\x3c\x67\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x34\x32\x38\ -\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\ -\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x31\x36\ -\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x36\x32\x31\ -\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\x39\x38\x36\x2c\x2d\x36\ -\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\x3e\x0a\x20\x20\x20\x20\ -\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x30\x2e\x35\x33\x33\x33\x33\x32\x39\x37\x3b\x63\x6f\x6c\x6f\x72\ -\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x30\ -\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\ -\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\ -\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\ -\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\ -\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\x30\x31\x36\x32\x3b\x73\x74\ -\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\ -\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\ -\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\ -\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\ -\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\ -\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\ -\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\ -\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\ -\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\ -\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\ -\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\ -\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\ -\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\ -\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\ -\x6d\x20\x31\x36\x31\x2e\x36\x36\x36\x32\x31\x2c\x34\x37\x36\x2e\ -\x37\x37\x38\x31\x34\x20\x30\x2c\x32\x30\x35\x2e\x30\x38\x34\x36\ -\x32\x20\x63\x20\x2d\x31\x33\x2e\x38\x33\x33\x36\x2c\x35\x2e\x30\ -\x38\x36\x36\x34\x20\x2d\x32\x34\x2e\x38\x31\x36\x30\x34\x2c\x31\ -\x36\x2e\x33\x36\x39\x39\x31\x20\x2d\x32\x39\x2e\x34\x39\x30\x35\ -\x35\x2c\x33\x30\x2e\x34\x35\x34\x32\x39\x20\x6c\x20\x2d\x31\x31\ -\x34\x2e\x36\x38\x35\x34\x37\x38\x2c\x30\x20\x30\x2c\x33\x34\x2e\ -\x38\x38\x37\x35\x32\x20\x31\x31\x36\x2e\x34\x32\x30\x32\x31\x38\ -\x2c\x30\x20\x63\x20\x37\x2e\x33\x38\x37\x35\x33\x2c\x31\x36\x2e\ -\x36\x36\x33\x39\x38\x20\x32\x33\x2e\x37\x34\x35\x30\x34\x2c\x32\ -\x38\x2e\x34\x37\x30\x38\x35\x20\x34\x33\x2e\x31\x37\x35\x37\x2c\ -\x32\x38\x2e\x39\x31\x32\x33\x20\x32\x30\x2e\x31\x37\x36\x39\x36\ -\x2c\x30\x2e\x34\x35\x38\x34\x31\x20\x33\x37\x2e\x37\x35\x38\x33\ -\x33\x2c\x2d\x31\x31\x2e\x35\x36\x32\x39\x20\x34\x35\x2e\x34\x38\ -\x38\x37\x2c\x2d\x32\x38\x2e\x39\x31\x32\x33\x20\x6c\x20\x31\x31\ -\x30\x2e\x34\x34\x35\x2c\x30\x20\x30\x2c\x2d\x33\x34\x2e\x38\x38\ -\x37\x35\x32\x20\x2d\x31\x30\x38\x2e\x37\x31\x30\x32\x36\x2c\x30\ -\x20\x63\x20\x2d\x34\x2e\x34\x35\x38\x31\x34\x2c\x2d\x31\x33\x2e\ -\x34\x36\x39\x30\x32\x20\x2d\x31\x34\x2e\x36\x38\x31\x36\x38\x2c\ -\x2d\x32\x34\x2e\x33\x31\x37\x35\x39\x20\x2d\x32\x37\x2e\x37\x35\ -\x35\x38\x32\x2c\x2d\x32\x39\x2e\x36\x38\x33\x33\x20\x6c\x20\x30\ -\x2c\x2d\x32\x30\x35\x2e\x38\x35\x35\x36\x31\x20\x2d\x33\x34\x2e\ -\x38\x38\x37\x35\x31\x2c\x30\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\ -\x2d\x34\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ -\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\ -\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\ -\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\ -\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\ -\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\ -\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\ -\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\ -\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ -\x77\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\x30\x31\x36\x32\ -\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\ -\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ -\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\ -\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\ -\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\ -\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\ -\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\ -\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\ -\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\ -\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\ -\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\ -\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\ -\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x33\x31\ -\x35\x2e\x36\x30\x37\x31\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x34\x2e\x38\x39\x31\ -\x32\x35\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x78\x3d\ -\x22\x2d\x38\x2e\x37\x34\x36\x37\x35\x37\x35\x22\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x36\x39\x31\x2e\x34\x38\x38\ -\x31\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x63\ -\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\ -\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\ -\x66\x69\x6c\x6c\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x66\x69\x6c\ -\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\ -\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\ -\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\ -\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\ -\x30\x31\x36\x32\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ -\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\ -\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\ -\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\ -\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\ -\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\ -\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\ -\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\ -\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\ -\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\ -\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\ -\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\ -\x2d\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\ -\x74\x68\x3d\x22\x32\x34\x37\x2e\x34\x31\x30\x36\x33\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\ -\x33\x34\x2e\x38\x39\x31\x32\x35\x31\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x78\x3d\x22\x2d\x37\x30\x33\x2e\x33\x38\x32\x38\ -\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x31\ -\x33\x35\x2e\x35\x37\x36\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\ -\x72\x69\x78\x28\x30\x2c\x2d\x31\x2c\x31\x2c\x30\x2c\x30\x2c\x30\ -\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x67\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ -\x3a\x65\x78\x70\x6f\x72\x74\x2d\x79\x64\x70\x69\x3d\x22\x37\x2e\ -\x30\x37\x32\x31\x39\x35\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\ -\x74\x2d\x78\x64\x70\x69\x3d\x22\x37\x2e\x30\x37\x32\x31\x39\x35\ -\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\x74\x2d\x66\x69\x6c\x65\ -\x6e\x61\x6d\x65\x3d\x22\x2f\x68\x6f\x6d\x65\x2f\x79\x6f\x72\x69\ -\x6b\x2f\x44\x6f\x63\x75\x6d\x65\x6e\x74\x73\x2f\x4c\x61\x62\x2f\ -\x44\x72\x61\x66\x74\x2f\x69\x63\x6f\x6e\x73\x2f\x6c\x69\x6e\x65\ -\x2e\x70\x6e\x67\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\ -\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\ -\x28\x2d\x30\x2e\x39\x39\x39\x37\x34\x32\x2c\x2d\x30\x2e\x30\x32\ -\x32\x37\x31\x33\x35\x31\x2c\x30\x2e\x30\x32\x32\x37\x31\x33\x35\ -\x31\x2c\x2d\x30\x2e\x39\x39\x39\x37\x34\x32\x2c\x33\x33\x34\x2e\ -\x32\x36\x37\x36\x38\x2c\x31\x33\x36\x36\x2e\x32\x36\x39\x32\x29\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\ -\x33\x31\x36\x30\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\ -\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\ -\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ -\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x23\x30\x30\x62\x32\ -\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\ -\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\ -\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\ -\x35\x2e\x38\x30\x30\x30\x30\x30\x31\x39\x3b\x73\x74\x72\x6f\x6b\ -\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\ -\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\ -\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\ -\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\ -\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\ -\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\ -\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\ -\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\ -\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\ -\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\ -\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ -\x70\x61\x74\x68\x33\x31\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\ -\x3d\x22\x31\x39\x37\x2e\x31\x34\x32\x38\x35\x22\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\ -\x3a\x63\x79\x3d\x22\x36\x35\x35\x2e\x32\x31\x39\x33\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ -\x64\x69\x3a\x72\x78\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\x33\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\ -\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\ -\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\ -\x22\x6d\x20\x32\x34\x35\x2e\x37\x31\x34\x32\x38\x2c\x36\x35\x35\ -\x2e\x32\x31\x39\x33\x20\x63\x20\x30\x2c\x32\x36\x2e\x38\x32\x35\ -\x32\x36\x20\x2d\x32\x31\x2e\x37\x34\x36\x31\x37\x2c\x34\x38\x2e\ -\x35\x37\x31\x34\x33\x20\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\ -\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x2d\x32\x36\x2e\x38\x32\x35\ -\x32\x36\x2c\x30\x20\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\ -\x32\x31\x2e\x37\x34\x36\x31\x37\x20\x2d\x34\x38\x2e\x35\x37\x31\ -\x34\x33\x2c\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x30\x2c\x2d\ -\x32\x36\x2e\x38\x32\x35\x32\x36\x20\x32\x31\x2e\x37\x34\x36\x31\ -\x37\x2c\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x34\x38\x2e\x35\ -\x37\x31\x34\x33\x2c\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x32\ -\x36\x2e\x38\x32\x35\x32\x36\x2c\x30\x20\x34\x38\x2e\x35\x37\x31\ -\x34\x33\x2c\x32\x31\x2e\x37\x34\x36\x31\x37\x20\x34\x38\x2e\x35\ -\x37\x31\x34\x33\x2c\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x7a\x22\ -\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\ -\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\ -\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\ -\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x75\x72\x6c\x28\x23\x72\x61\x64\ -\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x29\ -\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\ -\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x22\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\ -\x33\x31\x36\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\x3d\x22\x32\x32\ -\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\ -\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\ -\x72\x78\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ -\x64\x69\x3a\x72\x79\x3d\x22\x32\x33\x2e\x39\x39\x31\x31\x32\x33\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\ -\x6d\x20\x32\x35\x39\x2e\x36\x30\x39\x32\x31\x2c\x36\x37\x32\x2e\ -\x37\x39\x37\x33\x36\x20\x63\x20\x30\x2c\x31\x33\x2e\x32\x34\x39\ -\x39\x33\x20\x2d\x31\x35\x2e\x33\x37\x36\x38\x36\x2c\x32\x33\x2e\ -\x39\x39\x31\x31\x33\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\ -\x32\x33\x2e\x39\x39\x31\x31\x33\x20\x2d\x31\x38\x2e\x39\x36\x38\ -\x33\x32\x2c\x30\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\ -\x31\x30\x2e\x37\x34\x31\x32\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\ -\x39\x2c\x2d\x32\x33\x2e\x39\x39\x31\x31\x33\x20\x30\x2c\x2d\x31\ -\x33\x2e\x32\x34\x39\x39\x33\x20\x31\x35\x2e\x33\x37\x36\x38\x37\ -\x2c\x2d\x32\x33\x2e\x39\x39\x31\x31\x32\x20\x33\x34\x2e\x33\x34\ -\x35\x31\x39\x2c\x2d\x32\x33\x2e\x39\x39\x31\x31\x32\x20\x31\x38\ -\x2e\x39\x36\x38\x33\x33\x2c\x30\x20\x33\x34\x2e\x33\x34\x35\x31\ -\x39\x2c\x31\x30\x2e\x37\x34\x31\x31\x39\x20\x33\x34\x2e\x33\x34\ -\x35\x31\x39\x2c\x32\x33\x2e\x39\x39\x31\x31\x32\x20\x7a\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\ -\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x38\ -\x35\x31\x33\x30\x32\x33\x2c\x2d\x30\x2e\x35\x32\x34\x36\x37\x35\ -\x34\x2c\x30\x2e\x35\x32\x34\x36\x37\x35\x34\x2c\x30\x2e\x38\x35\ -\x31\x33\x30\x32\x33\x2c\x2d\x33\x33\x38\x2e\x36\x39\x36\x39\x32\ -\x2c\x32\x31\x34\x2e\x31\x39\x33\x32\x38\x29\x22\x20\x2f\x3e\x0a\ -\x20\x20\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\ -\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\ -\x3e\x0a\ +\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\ +\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\ +\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\ +\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x6c\x61\x62\x65\x6c\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\ +\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\ +\x0a\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\x69\ +\x64\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\ +\x69\x78\x28\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\ +\x2c\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\ +\x35\x39\x38\x36\x2c\x2d\x36\x36\x2e\x31\x30\x38\x38\x30\x36\x29\ +\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\ +\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\ +\x6c\x3a\x23\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\ +\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\ +\x65\x3a\x23\x30\x30\x32\x65\x32\x65\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x77\x69\x64\x74\x68\x3a\x32\x39\x2e\x38\x37\x37\x35\x37\x33\ +\x30\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ +\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\ +\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ +\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\ +\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\ +\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\ +\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\ +\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\ +\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\ +\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\ +\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\ +\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x64\x3d\x22\x6d\x20\x31\x32\x36\x2e\x33\x31\x34\x39\x36\ +\x2c\x34\x33\x39\x2e\x35\x35\x32\x32\x34\x20\x30\x2c\x32\x35\x34\ +\x2e\x37\x31\x39\x38\x33\x20\x2d\x31\x33\x37\x2e\x30\x38\x38\x35\ +\x34\x31\x2c\x30\x20\x30\x2c\x36\x39\x2e\x31\x35\x37\x32\x38\x20\ +\x33\x34\x30\x2e\x32\x35\x30\x34\x36\x31\x2c\x30\x20\x30\x2c\x2d\ +\x36\x39\x2e\x31\x35\x37\x32\x38\x20\x2d\x31\x33\x32\x2e\x35\x31\ +\x32\x38\x32\x2c\x30\x20\x30\x2c\x2d\x32\x35\x34\x2e\x37\x31\x39\ +\x38\x33\x20\x2d\x37\x30\x2e\x36\x34\x39\x31\x2c\x30\x20\x7a\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\ +\x63\x74\x33\x39\x34\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\ +\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\ +\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\ +\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ \x00\x00\x09\xad\ \x00\ \x00\x21\x35\x78\x9c\xed\x58\xdb\x6e\xe3\xc8\x11\x7d\xf7\x57\x30\ @@ -29375,463 +29547,112 @@ qt_resource_data = "\ \x75\x6d\x75\x6c\x61\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\ \x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\ \x67\x3e\x0a\ -\x00\x00\x1c\x6d\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ -\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ -\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ -\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ -\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ -\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ -\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ -\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ -\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ -\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ -\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ -\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ -\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ -\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ -\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ -\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ -\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ -\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ -\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ -\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ -\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ -\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ -\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ -\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ -\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ -\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ -\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ -\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ -\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ -\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ -\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ -\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ -\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ -\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ -\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ -\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x50\x65\x72\x70\x65\ -\x6e\x64\x69\x63\x75\x6c\x61\x72\x2e\x73\x76\x67\x22\x0a\x20\x20\ -\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\ -\x5f\x65\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\ -\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\ -\x73\x76\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\ -\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\ -\x20\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\ -\x22\x64\x65\x66\x73\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\ -\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\ -\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x3e\ -\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ -\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\ -\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ -\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ -\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x36\x22\x20\x2f\x3e\x0a\x20\ -\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\ -\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\ -\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\ -\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ -\x73\x74\x6f\x70\x33\x31\x34\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\ -\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ -\x74\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\ -\x3a\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\ -\x65\x3d\x22\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\ -\x70\x33\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\x20\x33\ -\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ -\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\ -\x20\x31\x30\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x7a\x3d\ -\x22\x36\x34\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\ -\x72\x73\x70\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\x33\x32\ -\x20\x3a\x20\x32\x31\x2e\x33\x33\x33\x33\x33\x33\x20\x3a\x20\x31\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x65\x72\ -\x73\x70\x65\x63\x74\x69\x76\x65\x32\x37\x33\x34\x22\x20\x2f\x3e\ -\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\ -\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\ -\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\ -\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\ -\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\ -\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x22\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\ -\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\ -\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\ -\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\ -\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\ -\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\ -\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\ -\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\ -\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\ -\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\ -\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\ -\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\ -\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\ -\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\ -\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\ -\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x31\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\ -\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x2d\x34\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\ -\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\ -\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\ -\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\ -\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\ -\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\ -\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\ -\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\ -\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\ -\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x66\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\ -\x38\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\ -\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\ -\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ -\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x31\x22\x3e\x0a\x20\x20\ -\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\ -\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\ -\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\ -\x74\x6f\x70\x33\x31\x34\x36\x2d\x39\x22\x20\x2f\x3e\x0a\x20\x20\ -\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\ -\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\ -\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\ -\x74\x6f\x70\x33\x31\x34\x38\x2d\x38\x22\x20\x2f\x3e\x0a\x20\x20\ -\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\ -\x6e\x74\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\ -\x3c\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\ -\x69\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\ -\x65\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\ -\x72\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\ -\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\ -\x36\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\ -\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\ -\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\ -\x67\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\ -\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\ -\x22\x33\x2e\x38\x38\x39\x30\x38\x37\x33\x22\x0a\x20\x20\x20\x20\ -\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x32\x31\ -\x2e\x38\x35\x32\x31\x37\x38\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ -\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x31\x36\x2e\x32\x37\ -\x33\x32\x31\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ -\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\ -\x72\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x73\ -\x68\x6f\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\ -\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\ -\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\ -\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\ -\x72\x69\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\ -\x6e\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\ -\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\ -\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ -\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\ -\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\ -\x64\x6f\x77\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\ -\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\ -\x6d\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\ -\x0a\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\ -\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x37\ -\x33\x31\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\ -\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\ -\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\ -\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\ -\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\ -\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\ -\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\ -\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\ -\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\ -\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\ -\x63\x3a\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\ -\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\ -\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\ -\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\ -\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\ -\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\ -\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\ -\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\ -\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\ -\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x34\ -\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\ -\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\ -\x31\x36\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x36\ -\x32\x31\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\x39\x38\x36\x2c\ -\x2d\x36\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\x3e\x0a\x20\x20\ -\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x6f\x70\x61\x63\x69\x74\ -\x79\x3a\x30\x2e\x35\x32\x39\x31\x36\x36\x37\x39\x3b\x63\x6f\x6c\ -\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\ -\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\ -\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\ -\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\ -\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\ -\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\x30\x31\x36\x32\x3b\ -\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\ -\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ -\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\x74\x72\x6f\x6b\x65\ -\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\ -\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\ -\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ -\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\ -\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\ -\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\ -\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\ -\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\ -\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\ -\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\ -\x3d\x22\x6d\x20\x35\x39\x2e\x38\x38\x39\x33\x37\x37\x2c\x34\x36\ -\x39\x2e\x33\x39\x36\x37\x35\x20\x30\x2c\x35\x35\x2e\x33\x31\x38\ -\x38\x37\x20\x2d\x34\x39\x2e\x31\x35\x30\x39\x31\x38\x2c\x30\x20\ -\x30\x2c\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x34\x39\x2e\x31\x35\ -\x30\x39\x31\x38\x2c\x30\x20\x30\x2c\x31\x35\x30\x2e\x31\x35\x31\ -\x32\x33\x20\x2d\x34\x39\x2e\x31\x35\x30\x39\x31\x38\x2c\x30\x20\ -\x30\x2c\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x34\x39\x2e\x31\x35\ -\x30\x39\x31\x38\x2c\x30\x20\x30\x2c\x34\x32\x2e\x30\x31\x39\x32\ -\x32\x20\x33\x34\x2e\x38\x38\x37\x35\x31\x35\x2c\x30\x20\x30\x2c\ -\x2d\x34\x32\x2e\x30\x31\x39\x32\x32\x20\x31\x33\x37\x2e\x38\x31\ -\x35\x33\x31\x38\x2c\x30\x20\x30\x2c\x34\x32\x2e\x30\x31\x39\x32\ -\x32\x20\x33\x34\x2e\x38\x38\x37\x35\x32\x2c\x30\x20\x30\x2c\x2d\ -\x34\x32\x2e\x30\x31\x39\x32\x32\x20\x35\x38\x2e\x39\x38\x31\x31\ -\x2c\x30\x20\x30\x2c\x2d\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x2d\ -\x35\x38\x2e\x39\x38\x31\x31\x2c\x30\x20\x30\x2c\x2d\x31\x31\x37\ -\x2e\x33\x38\x33\x39\x35\x20\x63\x20\x31\x34\x2e\x30\x33\x38\x39\ -\x37\x2c\x2d\x35\x2e\x37\x31\x33\x32\x36\x20\x32\x34\x2e\x38\x34\ -\x30\x39\x39\x2c\x2d\x31\x37\x2e\x38\x30\x38\x36\x37\x20\x32\x38\ -\x2e\x37\x31\x39\x35\x35\x2c\x2d\x33\x32\x2e\x37\x36\x37\x32\x38\ -\x20\x6c\x20\x33\x30\x2e\x32\x36\x31\x35\x35\x2c\x30\x20\x30\x2c\ -\x2d\x33\x34\x2e\x38\x38\x37\x35\x32\x20\x2d\x33\x34\x2e\x35\x30\ -\x32\x30\x32\x2c\x30\x20\x63\x20\x2d\x35\x2e\x33\x33\x33\x33\x33\ -\x2c\x2d\x31\x30\x2e\x30\x31\x35\x31\x38\x20\x2d\x31\x33\x2e\x38\ -\x33\x38\x30\x37\x2c\x2d\x31\x38\x2e\x30\x36\x32\x37\x33\x20\x2d\ -\x32\x34\x2e\x34\x37\x39\x30\x38\x2c\x2d\x32\x32\x2e\x33\x35\x38\ -\x38\x35\x20\x6c\x20\x30\x2c\x2d\x33\x32\x2e\x39\x36\x30\x30\x32\ -\x20\x2d\x33\x34\x2e\x38\x38\x37\x35\x32\x2c\x30\x20\x30\x2c\x33\ -\x32\x2e\x33\x38\x31\x37\x38\x20\x63\x20\x2d\x31\x31\x2e\x33\x33\ -\x33\x31\x34\x2c\x34\x2e\x31\x32\x36\x36\x34\x20\x2d\x32\x30\x2e\ -\x38\x30\x30\x31\x32\x2c\x31\x32\x2e\x33\x35\x38\x32\x38\x20\x2d\ -\x32\x36\x2e\x34\x30\x36\x35\x37\x2c\x32\x32\x2e\x39\x33\x37\x30\ -\x39\x20\x6c\x20\x2d\x31\x31\x31\x2e\x34\x30\x38\x37\x34\x38\x2c\ -\x30\x20\x30\x2c\x2d\x35\x35\x2e\x33\x31\x38\x38\x37\x20\x2d\x33\ -\x34\x2e\x38\x38\x37\x35\x31\x35\x2c\x30\x20\x7a\x20\x6d\x20\x33\ -\x34\x2e\x38\x38\x37\x35\x31\x35\x2c\x39\x30\x2e\x32\x30\x36\x33\ -\x39\x20\x31\x30\x37\x2e\x35\x35\x33\x37\x37\x38\x2c\x30\x20\x63\ -\x20\x34\x2e\x30\x31\x37\x31\x36\x2c\x31\x35\x2e\x34\x34\x32\x36\ -\x38\x20\x31\x35\x2e\x33\x35\x34\x35\x36\x2c\x32\x38\x2e\x31\x30\ -\x33\x37\x39\x20\x33\x30\x2e\x32\x36\x31\x35\x34\x2c\x33\x33\x2e\ -\x35\x33\x38\x32\x37\x20\x6c\x20\x30\x2c\x31\x31\x36\x2e\x36\x31\ -\x32\x39\x36\x20\x2d\x31\x33\x37\x2e\x38\x31\x35\x33\x31\x38\x2c\ -\x30\x20\x30\x2c\x2d\x31\x35\x30\x2e\x31\x35\x31\x32\x33\x20\x7a\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\ -\x65\x63\x74\x33\x39\x34\x32\x2d\x30\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\ -\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\ -\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\ -\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\ -\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\ -\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x66\ -\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\ -\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\ -\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x30\x2e\x39\x34\ -\x30\x33\x34\x33\x38\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ -\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\ -\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\ -\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\ -\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\ -\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ -\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\ -\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\ -\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\ -\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\ -\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\ -\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\ -\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\ -\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x31\x32\x2e\x39\x30\x36\ -\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\x20\x4c\x20\x31\x32\x2e\ -\x39\x30\x36\x32\x35\x20\x31\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\ -\x35\x20\x31\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\x35\x20\x32\x31\ -\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\x39\x30\x36\x32\ -\x35\x20\x32\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\ -\x39\x30\x36\x32\x35\x20\x34\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\ -\x35\x20\x34\x36\x20\x4c\x20\x34\x2e\x39\x33\x37\x35\x20\x35\x31\ -\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\x39\x30\x36\x32\ -\x35\x20\x35\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x31\x32\x2e\ -\x39\x30\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\x35\x20\x4c\ -\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\ -\x35\x20\x4c\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x35\x31\x2e\x36\ -\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\x30\x36\x32\x35\x20\ -\x35\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\x30\ -\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\x35\x20\x4c\x20\x34\ -\x36\x2e\x35\x36\x32\x35\x20\x35\x38\x2e\x34\x36\x38\x37\x35\x20\ -\x4c\x20\x34\x36\x2e\x35\x36\x32\x35\x20\x35\x31\x2e\x36\x35\x36\ -\x32\x35\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x35\x31\x2e\x36\ -\x35\x36\x32\x35\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x34\x36\ -\x20\x4c\x20\x34\x36\x2e\x35\x36\x32\x35\x20\x34\x36\x20\x4c\x20\ -\x34\x36\x2e\x35\x36\x32\x35\x20\x32\x31\x2e\x36\x35\x36\x32\x35\ -\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x32\x31\x2e\x36\x35\x36\ -\x32\x35\x20\x4c\x20\x35\x36\x2e\x31\x32\x35\x20\x31\x36\x20\x4c\ -\x20\x34\x36\x2e\x35\x36\x32\x35\x20\x31\x36\x20\x4c\x20\x34\x36\ -\x2e\x35\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\x20\x4c\x20\ -\x34\x30\x2e\x39\x30\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\ -\x20\x4c\x20\x34\x30\x2e\x39\x30\x36\x32\x35\x20\x31\x36\x20\x4c\ -\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x31\x36\x20\x4c\x20\x31\x38\ -\x2e\x35\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\x20\x4c\x20\ -\x31\x32\x2e\x39\x30\x36\x32\x35\x20\x37\x2e\x30\x33\x31\x32\x35\ -\x20\x7a\x20\x4d\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x32\x31\x2e\ -\x36\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\x30\x36\x32\x35\ -\x20\x32\x31\x2e\x36\x35\x36\x32\x35\x20\x4c\x20\x34\x30\x2e\x39\ -\x30\x36\x32\x35\x20\x34\x36\x20\x4c\x20\x31\x38\x2e\x35\x36\x32\ -\x35\x20\x34\x36\x20\x4c\x20\x31\x38\x2e\x35\x36\x32\x35\x20\x32\ -\x31\x2e\x36\x35\x36\x32\x35\x20\x7a\x20\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\ -\x6d\x61\x74\x72\x69\x78\x28\x36\x2e\x31\x36\x37\x39\x35\x38\x34\ -\x2c\x30\x2c\x30\x2c\x36\x2e\x31\x36\x37\x39\x35\x38\x34\x2c\x2d\ -\x33\x39\x2e\x32\x33\x31\x39\x30\x38\x2c\x34\x30\x37\x2e\x37\x35\ -\x36\x33\x37\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\ -\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\x22\x20\x2f\x3e\x0a\ -\x20\x20\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\ -\x74\x2d\x79\x64\x70\x69\x3d\x22\x37\x2e\x30\x37\x32\x31\x39\x35\ -\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x65\x78\x70\x6f\x72\x74\x2d\x78\x64\x70\x69\ -\x3d\x22\x37\x2e\x30\x37\x32\x31\x39\x35\x31\x22\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x65\ -\x78\x70\x6f\x72\x74\x2d\x66\x69\x6c\x65\x6e\x61\x6d\x65\x3d\x22\ -\x2f\x68\x6f\x6d\x65\x2f\x79\x6f\x72\x69\x6b\x2f\x44\x6f\x63\x75\ -\x6d\x65\x6e\x74\x73\x2f\x4c\x61\x62\x2f\x44\x72\x61\x66\x74\x2f\ -\x69\x63\x6f\x6e\x73\x2f\x6c\x69\x6e\x65\x2e\x70\x6e\x67\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x2d\x30\x2e\x39\x39\ -\x39\x37\x34\x32\x2c\x2d\x30\x2e\x30\x32\x32\x37\x31\x33\x35\x31\ -\x2c\x30\x2e\x30\x32\x32\x37\x31\x33\x35\x31\x2c\x2d\x30\x2e\x39\ -\x39\x39\x37\x34\x32\x2c\x34\x31\x31\x2e\x39\x37\x39\x39\x39\x2c\ -\x31\x31\x38\x38\x2e\x36\x34\x31\x31\x29\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x33\x31\x36\x30\x22\x3e\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ -\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\ -\x66\x69\x6c\x6c\x3a\x23\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\ -\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\ -\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\ -\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\ -\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x2e\x38\x30\x30\x30\ -\x30\x30\x31\x39\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ -\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x6d\x69\x74\x65\x72\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\ -\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\ -\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\ -\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\ -\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\ -\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\ -\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\ -\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\ -\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\ -\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\ -\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\ -\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ -\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\x3d\x22\x31\x39\x37\x2e\ -\x31\x34\x32\x38\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\x36\ -\x35\x35\x2e\x32\x31\x39\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\ -\x22\x34\x38\x2e\x35\x37\x31\x34\x33\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\ -\x79\x3d\x22\x34\x38\x2e\x35\x37\x31\x34\x33\x22\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x32\x34\x35\ -\x2e\x37\x31\x34\x32\x38\x2c\x36\x35\x35\x2e\x32\x31\x39\x33\x20\ -\x63\x20\x30\x2c\x32\x36\x2e\x38\x32\x35\x32\x36\x20\x2d\x32\x31\ -\x2e\x37\x34\x36\x31\x37\x2c\x34\x38\x2e\x35\x37\x31\x34\x33\x20\ -\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x34\x38\x2e\x35\x37\x31\ -\x34\x33\x20\x2d\x32\x36\x2e\x38\x32\x35\x32\x36\x2c\x30\x20\x2d\ -\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\x32\x31\x2e\x37\x34\x36\ -\x31\x37\x20\x2d\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\x34\x38\ -\x2e\x35\x37\x31\x34\x33\x20\x30\x2c\x2d\x32\x36\x2e\x38\x32\x35\ -\x32\x36\x20\x32\x31\x2e\x37\x34\x36\x31\x37\x2c\x2d\x34\x38\x2e\ -\x35\x37\x31\x34\x33\x20\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x2d\ -\x34\x38\x2e\x35\x37\x31\x34\x33\x20\x32\x36\x2e\x38\x32\x35\x32\ -\x36\x2c\x30\x20\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x32\x31\x2e\ -\x37\x34\x36\x31\x37\x20\x34\x38\x2e\x35\x37\x31\x34\x33\x2c\x34\ -\x38\x2e\x35\x37\x31\x34\x33\x20\x7a\x22\x20\x2f\x3e\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\ -\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\x6c\ -\x6c\x3a\x75\x72\x6c\x28\x23\x72\x61\x64\x69\x61\x6c\x47\x72\x61\ -\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x29\x3b\x66\x69\x6c\x6c\x2d\ -\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\ -\x3a\x6e\x6f\x6e\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x31\x36\x34\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\ -\x6f\x64\x69\x3a\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\ -\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\ -\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\ -\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\x33\x34\ -\x2e\x33\x34\x35\x31\x38\x38\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\ -\x22\x32\x33\x2e\x39\x39\x31\x31\x32\x33\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x32\x35\x39\x2e\ -\x36\x30\x39\x32\x31\x2c\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x20\ -\x63\x20\x30\x2c\x31\x33\x2e\x32\x34\x39\x39\x33\x20\x2d\x31\x35\ -\x2e\x33\x37\x36\x38\x36\x2c\x32\x33\x2e\x39\x39\x31\x31\x33\x20\ -\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x32\x33\x2e\x39\x39\x31\ -\x31\x33\x20\x2d\x31\x38\x2e\x39\x36\x38\x33\x32\x2c\x30\x20\x2d\ -\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\x31\x30\x2e\x37\x34\x31\ -\x32\x20\x2d\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\x32\x33\x2e\ -\x39\x39\x31\x31\x33\x20\x30\x2c\x2d\x31\x33\x2e\x32\x34\x39\x39\ -\x33\x20\x31\x35\x2e\x33\x37\x36\x38\x37\x2c\x2d\x32\x33\x2e\x39\ -\x39\x31\x31\x32\x20\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x2d\x32\ -\x33\x2e\x39\x39\x31\x31\x32\x20\x31\x38\x2e\x39\x36\x38\x33\x33\ -\x2c\x30\x20\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x31\x30\x2e\x37\ -\x34\x31\x31\x39\x20\x33\x34\x2e\x33\x34\x35\x31\x39\x2c\x32\x33\ -\x2e\x39\x39\x31\x31\x32\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\ -\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x38\x35\x31\x33\x30\x32\x33\ -\x2c\x2d\x30\x2e\x35\x32\x34\x36\x37\x35\x34\x2c\x30\x2e\x35\x32\ -\x34\x36\x37\x35\x34\x2c\x30\x2e\x38\x35\x31\x33\x30\x32\x33\x2c\ -\x2d\x33\x33\x38\x2e\x36\x39\x36\x39\x32\x2c\x32\x31\x34\x2e\x31\ -\x39\x33\x32\x38\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ -\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\ -\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ +\x00\x00\x06\x71\ +\x00\ +\x00\x16\x14\x78\x9c\xdd\x57\x5b\x6f\xdb\x36\x14\x7e\xcf\xaf\xd0\ +\xd4\x97\x16\xb3\x28\x92\xba\x2b\x76\x8a\x61\x45\x8b\x02\x2d\x06\ +\xac\x2d\xf6\x58\xd0\x12\x6d\x6b\x91\x25\x81\xa2\x63\x3b\xbf\x7e\ +\x87\xd4\x3d\x56\xb2\x74\x97\x0e\x98\x8d\x44\xe2\xb9\xf3\xf0\x3b\ +\x87\xc7\xcb\xd7\xa7\x7d\x6e\xdc\x71\x51\x67\x65\xb1\x32\x09\xc2\ +\xa6\xc1\x8b\xa4\x4c\xb3\x62\xbb\x32\xbf\x7c\x7e\x6b\x85\xa6\x51\ +\x4b\x56\xa4\x2c\x2f\x0b\xbe\x32\x8b\xd2\x7c\x7d\x73\xb5\xfc\xc1\ +\xb2\x8c\x9f\x05\x67\x92\xa7\xc6\x31\x93\x3b\xe3\x7d\x71\x5b\x27\ +\xac\xe2\xc6\xcb\x9d\x94\x55\x6c\xdb\xc7\xe3\x11\x65\x2d\x11\x95\ +\x62\x6b\xbf\x32\x2c\xeb\xe6\xea\x6a\x59\xdf\x6d\xaf\x0c\xc3\x00\ +\xbf\x45\x1d\xa7\xc9\xca\x6c\x15\xaa\x83\xc8\xb5\x60\x9a\xd8\x3c\ +\xe7\x7b\x5e\xc8\xda\x26\x88\xd8\xe6\x20\x9e\x0c\xe2\x89\xf2\x9e\ +\xdd\xf1\xa4\xdc\xef\xcb\xa2\xd6\x9a\x45\xfd\x62\x24\x2c\xd2\x4d\ +\x2f\xad\xa2\x39\x3a\x5a\x88\x44\x51\x64\x63\x6a\x53\x6a\x81\x84\ +\x55\x9f\x0b\xc9\x4e\xd6\x54\x15\x62\x9c\x53\xa5\x18\x63\x1b\x78\ +\x83\xe4\xf3\xa4\xe2\x53\x0e\xa9\x78\x34\x18\xcd\x1d\x7b\x87\xf4\ +\x57\xf0\xd7\x2b\x74\x04\x54\x97\x07\x91\xf0\x0d\x68\x72\x54\x70\ +\x69\xbf\xf9\xfc\xa6\x67\x5a\x18\xa5\x32\x1d\x99\xe9\xb2\x3f\xf1\ +\x3b\x39\x92\x82\xed\x79\x5d\xb1\x84\xd7\x76\x47\xd7\xfa\xc7\x2c\ +\x95\xbb\x95\xe9\xbb\xd5\x49\xaf\x77\x3c\xdb\xee\xe4\x88\x90\xa5\ +\x2b\x13\x76\x48\x03\xea\xeb\x75\x17\x43\xdc\x23\x09\x23\x87\x36\ +\xa2\xad\xe1\x31\xcb\x0d\x11\x31\x44\x14\xf8\x78\xaa\x9d\x96\x89\ +\x0a\x69\x65\x7e\x2a\x58\xf5\xf5\x9d\xc8\x52\xd4\xe5\xb1\x37\x53\ +\x1e\x64\x75\x90\x5f\xf9\x49\xf2\xa2\xb1\x07\x3b\x19\x6d\x4b\xb3\ +\x95\x1a\x9a\x6c\x69\x04\x71\x62\xde\x00\x65\x99\xf2\x4d\xad\x38\ +\xcd\x6e\xd4\x0a\xb6\x13\x6a\x1e\x70\xe1\x48\x38\x13\xef\x04\x4b\ +\x33\x00\x62\x23\x37\x8a\x22\x29\xf3\x9c\x27\x90\x12\x96\x1f\xd9\ +\xb9\x36\x7b\x01\x30\x35\x55\x75\x88\xeb\xb6\x46\xc1\x6c\x2d\xcb\ +\xaa\x93\x85\x8d\xcb\x73\x0e\xbb\x55\x44\x0b\x2c\x96\x22\x7e\xb1\ +\xd1\x9f\x6b\x4d\x2a\xe1\x68\x32\x79\x8e\xc9\xb5\x39\xe8\x94\x9b\ +\x4d\xcd\xc1\x31\x1e\xd1\xf4\x71\x80\x06\xf8\xf2\x4d\xc3\xfe\x7b\ +\xde\xf0\x9c\x37\x32\xef\x2d\xec\xbd\x2d\xed\xe9\xb6\x5b\x6a\x9f\ +\xb0\x0a\xf2\x5f\x41\xc6\xa0\x62\x3b\x4b\xfd\xb1\xcb\xb3\x02\xe9\ +\x54\xd4\x49\xcd\x8b\xa4\xdf\x55\x5f\x4f\xb0\x71\x23\x36\x1c\x0a\ +\xff\xc8\xac\xc4\xb9\x91\x20\x50\x84\xf0\xc0\xb3\x32\xf7\x0a\xca\ +\x4f\x98\x69\x23\xb0\x4a\x91\x6d\x33\xc0\x8c\x96\xa3\x04\x39\xfa\ +\x33\xd5\x81\x64\x8c\xf6\x46\x03\xc7\x1d\x72\xa2\x72\xc1\xf2\x6f\ +\x06\x91\xee\x07\xf1\x4e\x70\xe8\x5f\x2f\x66\xd0\x34\xf6\x3d\x75\ +\xe1\x84\xde\xb0\xe3\x6d\x4b\xfc\x52\x64\x12\x1a\xd5\xa1\xe6\xe2\ +\x93\x2a\xf6\x5f\x8a\x2f\x35\xbf\x90\xfa\x2c\x58\x51\x43\x67\xd9\ +\xaf\xcc\x3d\x93\x22\x3b\xbd\x24\x0b\xac\xbe\xc8\x8f\x42\x8f\x46\ +\x2e\xbc\x53\x4c\x51\x48\x43\xdf\x79\xd5\xab\x27\x70\x22\x94\x7a\ +\x88\xfa\x2e\xa6\x03\x15\x4e\xc1\x0f\x28\x0a\xa2\xc0\xf1\x7b\xea\ +\x66\x56\x76\x33\x2b\x2b\x20\xeb\x2e\x72\x5c\x8f\x84\xe1\xbf\x9d\ +\x50\x8b\xfc\x49\x4a\x2d\xf7\xff\x9c\xd4\x7f\xb4\xd5\x59\xe4\x7b\ +\x36\x3b\x2b\xfa\xbe\xed\xce\x7a\xba\xe1\x2d\x6d\x75\x8d\xe8\xb7\ +\xbe\xb9\xa9\x0b\x2d\xbd\xcb\xf8\x71\xb8\x6b\xd6\xac\x87\x4a\xc5\ +\xb6\x5c\x07\x07\xc0\x6c\xa2\x6b\x19\xeb\x52\xa4\x5c\x74\x2c\x5f\ +\x7f\x26\xac\x36\xfe\x66\x66\xbb\x9a\x1e\x99\xb2\xda\xf3\xf1\x3c\ +\xbf\xde\xb1\xb4\x3c\x02\x76\x1e\x32\xef\xcb\x12\xe0\x1a\xa0\x20\ +\x08\x49\xe0\xfa\x0f\xd9\x0a\x9b\x8e\x8f\xdc\x88\x86\x0e\xb9\x60\ +\x82\x3f\x07\xa3\x30\xf2\x7d\xcf\xbb\x60\x1e\x84\x80\x44\x59\x39\ +\x3b\x73\xd8\xd4\xd6\xa5\x61\xd4\xca\xd4\xbb\xf2\xb8\x15\x2a\x37\ +\x52\x1c\xf8\x43\x45\x18\x0b\x0e\x6a\x1c\xb4\x0e\x4d\xd1\xb5\x43\ +\xc8\x48\x42\xe9\x5a\xeb\x75\x79\x9a\x37\x70\xcc\x0a\xd8\xab\xd5\ +\x8e\x35\x84\x86\x17\x19\x69\x25\xba\x41\x27\xb8\x8c\xbe\x95\x38\ +\x0d\x60\x7c\xc8\x3a\xab\x42\x7c\x84\xb7\x67\xa7\x6c\x9f\xdd\xf3\ +\x54\x61\xab\x81\xd0\x72\xcf\x25\x4b\x99\x64\x03\x30\x3a\x0a\xdc\ +\x22\x5d\x19\x2d\x61\x46\x8d\x7f\x7d\xf3\xb6\x07\x79\x92\xc4\xbf\ +\x95\xe2\x76\xc0\xa7\x12\x60\x6b\x98\x7b\x56\x66\x5f\x7a\x6a\xbc\ +\x49\x62\xd5\x78\x98\xbc\xc9\xf6\x70\xdc\x6a\x20\xfd\x11\xe6\x42\ +\x80\x68\xcf\x98\x08\xab\x4b\x78\x30\xda\x98\x15\xbc\x19\x38\x67\ +\x67\xf4\x34\xd9\x67\x4a\xc9\xfe\x24\xb3\x3c\x7f\xaf\x9c\x8c\x8a\ +\xb1\x35\x9a\xc9\x9c\x8f\x2a\xd4\x6e\xa3\xef\x4a\x68\xb4\xb9\xa5\ +\xdd\xed\x5e\xaf\xb6\x43\x56\x34\x5e\x2e\xa0\x96\xb3\x35\xcf\x57\ +\xe6\x07\xc5\x34\x2e\xb8\x5b\x51\x1e\xaa\x7d\x99\xf2\x56\xbd\xcb\ +\xe6\x76\xdc\xbd\xc6\x08\x34\x0c\x79\xd1\xab\x31\x22\x3e\x05\xb4\ +\xd0\xb6\x67\x77\x2b\x1f\x39\x3e\xf6\xa2\xd0\x5f\x58\xbe\x8f\x08\ +\x0e\x43\xec\xbf\x1a\xda\x5e\xc5\xe4\x6e\xd4\x86\x1e\x99\x72\x9a\ +\x56\x33\xee\x33\x1d\x47\x35\x94\x03\xc0\x5c\x5f\x0b\x2e\x0d\xc8\ +\x9c\x50\x33\x9a\x30\xc8\xc0\x47\x83\x50\x14\x61\x9f\x7a\x46\x80\ +\xb0\x43\xe0\xf9\x61\x20\x11\x1f\x56\x2e\x8a\x9c\x60\xfa\x0e\xd3\ +\x8c\xef\xf9\x53\xd9\x39\x9a\x3b\xd2\x19\xbf\x7b\x33\xb2\xb3\xb4\ +\x10\xb9\x7e\x18\x68\x5a\x88\xbc\xc7\x48\x83\xa6\x8b\x2f\xad\x0d\ +\xb4\x41\xd5\xf5\x2f\xac\xf5\xa4\x41\xd3\x83\xf3\x99\xa5\x34\x7b\ +\x69\x15\x26\x0b\x7a\x21\x7b\x49\x21\x63\x85\xc9\x62\x38\x82\x3e\ +\xe8\x19\x92\x56\xe9\x36\x3f\x59\xcc\x1c\x61\x47\xba\x37\x3e\xf6\ +\x62\x74\x26\x39\x73\x34\x77\x6c\x7b\xb2\xe8\xa5\xef\x8d\x11\xbe\ +\xda\x4b\xb3\xbd\x2f\xb1\xfe\x5c\x6f\xa0\xbe\xd5\x62\x0d\x53\x8a\ +\x5e\x8c\x2e\x6b\xbd\x14\x87\x9c\xc7\x45\x59\xdc\xc3\xb5\x04\xb7\ +\xab\x28\x6f\xb9\x92\xa7\x9c\xf2\x76\xd9\xf4\xde\xd8\x45\x8d\x49\ +\xec\x74\x74\x75\x89\x02\xa0\xe3\xf5\x41\xca\x31\xed\xf7\x32\x2b\ +\x62\x68\x30\x5c\x74\x54\xbd\xc8\xa1\x8b\xca\xd8\xed\x68\x43\x1c\ +\x2d\x21\x65\x70\xaf\x09\xc1\xce\x2a\x1c\x3e\xa6\x36\xf5\x06\xd7\ +\xfd\x9e\x89\x5b\x2e\x1a\xfe\x5d\x56\x67\xeb\x2c\x57\x26\xf4\x6b\ +\xce\xaf\xd3\xac\xae\xa0\x65\xc0\xaf\x67\x15\xc6\x75\x09\x3f\x1c\ +\x37\x79\x79\xec\xf9\xbc\x60\xf0\xb0\xd6\x2c\xb9\x55\x4d\xa6\x48\ +\x63\x96\xc0\xf5\x74\xc8\x99\xe4\x0f\xa6\x06\xd5\x08\x9c\x20\xf0\ +\x46\xe4\x74\x5c\xaf\x0b\x17\x11\x85\xdc\x9f\x0c\x5d\xea\x01\x8e\ +\xa2\x45\xff\x66\x60\xfd\x25\x70\x7d\x2b\xd1\x0e\x04\xb9\x81\x17\ +\x0d\x06\x2d\x4f\x3d\x16\xf8\x49\x75\x8a\xb0\x2a\xd7\x05\x60\x4c\ +\x69\x7a\xed\x99\x3f\xa5\xd2\x14\xf8\x82\xba\x48\x79\xeb\x9c\xe0\ +\x05\x00\xa7\x51\xfe\x26\xc7\xee\x37\x3b\xf6\x1e\x3a\x76\x50\xa4\ +\x0b\x9c\x3d\xe9\x2e\x74\x75\xd4\xcd\x53\xeb\x6b\x8f\x60\xe1\x39\ +\x7a\xd6\xa0\x88\x17\x56\xe7\x91\xf8\xbd\x91\xff\x32\x0c\x1f\x05\ +\x0a\x27\x7f\xc9\xc6\x73\x12\xdf\x34\xb5\x85\xeb\x20\xa2\x65\x73\ +\xc3\x1a\x5c\x82\x8d\xfe\xe4\xbf\x53\x20\xe4\xb1\x40\x1a\xe0\x3f\ +\x89\xa1\xa6\x0d\x77\x95\x95\x1b\xd6\x70\x00\x4f\xe9\x39\xe1\xa3\ +\x65\x36\x01\xc1\x33\x42\x68\x1b\xec\x6c\x08\xf7\xc6\xde\x00\x36\ +\xfc\xe6\x43\x4e\x73\x8f\x8c\x6c\x0f\x05\x36\x75\xd9\xd3\xef\x47\ +\x8d\xe4\x72\x5a\x81\xc8\xfc\x20\xf2\x42\x57\x4f\x2b\xc3\xca\xa2\ +\x21\x22\x0e\x26\x2e\x84\x84\x61\xac\xf7\x7c\x27\x78\x35\xfa\x19\ +\xb3\x6d\xa6\x2f\x78\x2c\xd5\x90\x78\x73\xf5\x07\xc6\xbb\xc6\xcf\ +\ \x00\x00\x05\xc0\ \x00\ \x00\x13\xbe\x78\x9c\xd5\x57\x59\x73\xdb\x36\x10\x7e\xf7\xaf\x60\ @@ -29926,144 +29747,99 @@ qt_resource_data = "\ \xe6\x77\x5b\x82\xcc\x0b\xcd\x22\xfc\x47\x30\x78\xae\xeb\xfd\xb4\ \x5a\x79\x11\x19\xe2\x7f\x1d\x32\xff\xd5\xf2\x39\xc2\x32\xee\xa7\ \xb5\xf5\xed\xd5\x5c\x4d\x4b\xb7\x57\x7f\x02\xb2\xe9\xd6\x37\ -\x00\x00\x08\x75\ +\x00\x00\x05\xac\ \x00\ -\x00\x29\x56\x78\x9c\xed\x5a\x59\x6f\xe3\x38\x12\x7e\xcf\xaf\xd0\ -\xaa\x5f\x3a\x58\x8b\xe2\x2d\xd1\x39\xe6\x61\xb3\x33\x18\x60\x80\ -\x05\xb6\xbb\xb1\x8f\x0d\x59\xa2\x1d\x6d\x64\xc9\xa0\xe4\xd8\xce\ -\xaf\xdf\xa2\x2e\xcb\xb6\xd2\x49\x6f\xcf\x38\x40\x23\x0e\x12\x8b\ -\x75\xb0\x58\xc5\x8f\xc5\xa2\x98\xeb\x5f\xb6\xcb\xcc\x79\xd4\xa6\ -\x4c\x8b\xfc\xc6\x25\x08\xbb\x8e\xce\xe3\x22\x49\xf3\xc5\x8d\xfb\ -\xe5\xf3\xaf\x5e\xe8\x3a\x65\x15\xe5\x49\x94\x15\xb9\xbe\x71\xf3\ -\xc2\xfd\xe5\xf6\xe2\xfa\x6f\x9e\xe7\xfc\xc3\xe8\xa8\xd2\x89\xb3\ -\x49\xab\x7b\xe7\xf7\xfc\xa1\x8c\xa3\x95\x76\x3e\xde\x57\xd5\x6a\ -\xea\xfb\x9b\xcd\x06\xa5\x2d\x11\x15\x66\xe1\x5f\x3a\x9e\x77\x7b\ -\x71\x71\x5d\x3e\x2e\x2e\x1c\xc7\x01\xbb\x79\x39\x4d\xe2\x1b\xb7\ -\x55\x58\xad\x4d\x56\x0b\x26\xb1\xaf\x33\xbd\xd4\x79\x55\xfa\x04\ -\x11\xdf\xdd\x8b\xc7\x7b\xf1\xd8\x5a\x4f\x1f\x75\x5c\x2c\x97\x45\ -\x5e\xd6\x9a\x79\xf9\x61\x20\x6c\x92\x79\x2f\x6d\x47\xb3\x61\xb5\ -\x10\x51\x4a\xf9\x98\xfa\x94\x7a\x20\xe1\x95\xbb\xbc\x8a\xb6\xde\ -\xa1\x2a\x8c\x71\x4c\x95\x62\x8c\x7d\xe0\xed\x25\x5f\x27\x35\xdd\ -\x66\x10\x8a\x67\x07\x53\x73\x87\xd6\x21\xfc\x2b\xf8\xed\x15\x3a\ -\x02\x2a\x8b\xb5\x89\xf5\x1c\x34\x35\xca\x75\xe5\xdf\x7d\xbe\xeb\ -\x99\x1e\x46\x49\x95\x0c\xba\xe9\xa2\x7f\x60\xf7\x60\x4a\xf2\x68\ -\xa9\xcb\x55\x14\xeb\xd2\xef\xe8\xb5\xfe\x26\x4d\xaa\xfb\x1b\x57\ -\xf2\xd5\xb6\x6e\xdf\xeb\x74\x71\x5f\x0d\x08\x69\x72\xe3\x82\x87\ -\x34\xa0\xb2\x6e\x77\x63\x98\xf6\x48\xc2\x88\xd1\x46\xb4\xed\x78\ -\xc8\xe2\x21\x22\x8e\x51\x81\xc4\x87\xda\x49\x11\xdb\x21\xdd\xb8\ -\x9f\xf2\x68\xf5\xf5\x9f\xdb\x4a\xe7\x56\x05\x75\xc1\xec\xfb\x2a\ -\xd6\xd5\x6a\x5d\x7d\xd5\x9d\xc4\x8d\x0b\xee\x0c\x7c\xab\xd9\x56\ -\x0d\x1d\xf8\x35\xc0\x39\x71\x6f\x81\x72\x9d\xe8\x79\x69\x39\x8d\ -\x4b\xb6\x05\x3e\x85\x35\x0f\xb8\x30\x2f\x3a\x32\xbf\x99\x28\x49\ -\x01\x8d\x8d\xdc\x60\x14\x71\x91\x65\x3a\x86\xb8\x44\xd9\x26\xda\ -\x95\x6e\x2f\x00\x5d\x1d\xaa\x32\xc2\x79\xdb\x29\x74\x5b\x56\xc5\ -\xaa\x93\x05\xef\xab\x5d\x06\x2e\x5b\xa2\x07\x3d\x16\x66\xfa\x61\ -\x5e\x7f\xae\x6a\x52\x01\xf3\x93\x56\xbb\x29\xb9\x72\xf7\x3a\xc5\ -\x7c\x5e\x6a\x30\x8c\x07\xb4\x7a\x4e\x40\x03\x6c\x49\xd7\xf1\x7f\ -\xcc\x1a\x1e\xb3\x46\xc6\xad\x85\xbd\xb5\x6b\xff\xd0\xed\x96\xda\ -\x07\x6c\x05\xf1\x5f\x41\xc4\x60\xd9\x76\x3d\xf5\x73\x5f\xed\x2c\ -\x52\x0f\x45\x59\xe2\x9e\x04\xfd\x71\xf5\x75\x0b\x8e\x3b\x53\x87\ -\x51\xf8\x43\x46\x25\x76\x8d\x04\x81\x95\x08\x5f\x78\x54\xe6\xc9\ -\xe2\xf9\x1b\xdd\xb4\x23\xf0\x0a\x93\x2e\x52\xc0\x4c\x2d\x47\x09\ -\x62\xf5\xe7\x50\x07\x82\x31\xf0\x8d\x06\x8c\xef\x63\x62\x63\x11\ -\x65\xdf\x0d\xa2\x3a\x29\x4c\xef\x8d\x86\x24\xf6\x61\x04\x4d\x43\ -\xdb\x87\x26\x58\x28\xf6\x1e\x2f\x5a\xe2\x97\x3c\xad\x20\x5b\xad\ -\x4b\x6d\x3e\xd9\x15\xff\xaf\xfc\x4b\xa9\x4f\xa4\x3e\x9b\x28\x2f\ -\x21\xbd\x2c\x6f\xdc\x65\x54\x99\x74\xfb\x91\x4c\xb0\xfd\x41\x52\ -\x85\x82\x2a\x0e\xcf\x14\x53\x14\xd2\x50\xb2\xcb\x5e\x3d\x86\x19\ -\xa1\x54\x20\x2a\x39\xa6\x7b\x2a\xcc\x82\x0c\x28\x0a\x54\xc0\x64\ -\x4f\x9d\x8f\xca\xce\x47\x65\x0d\x44\x9d\x23\xc6\x05\x09\xc3\xbf\ -\x3a\xa0\x5e\xf0\x42\x48\x3d\xfa\x33\x07\xf5\x4f\x4d\x75\x10\xcb\ -\x33\x26\x3b\x8f\x9f\x37\xdd\x0d\xec\x3d\x93\xf0\xfe\x22\x84\x8a\ -\x97\x10\x1a\xbc\x23\xf4\xb5\x08\x15\x67\x45\xe8\x99\x37\x64\xf0\ -\xee\x6d\x10\xca\x5e\x44\xe8\x4f\xbd\x33\xfd\xb9\x10\x65\x67\x85\ -\x28\x3d\x33\x44\xd9\x1b\x41\x94\xbc\x04\x51\xf1\x8e\xd0\xd7\x22\ -\x94\x9c\x15\xa1\xe2\xcc\x08\x25\x6f\x84\x50\xf5\x12\x42\xd9\x3b\ -\x42\x5f\x8b\x50\x75\x56\x84\xaa\x73\x23\x94\xbe\x11\x44\xe9\x4b\ -\x10\x95\xef\x10\x7d\x2d\x44\xe9\x59\x21\x8a\xcf\x0c\xd1\xb7\x42\ -\xe8\x4b\x2f\x48\x3c\xf9\x9e\x45\x5f\x0d\xd1\xb3\xbe\xbb\x84\x53\ -\xec\x99\xb3\xe8\xb7\x4b\xd1\x6b\xdf\xbe\x16\xae\x9f\xfa\x97\x95\ -\xf6\x2d\x75\xf2\x98\xea\xcd\x45\xdf\xdd\x2c\xea\xb1\xb2\x8a\x16\ -\xba\x1e\x1d\x40\xb3\x19\x5e\xcb\x98\x15\x26\xd1\xa6\x63\xc9\xfa\ -\x73\xc0\x6a\x1d\x68\x2e\x62\x2e\x0e\xe7\xcc\xf6\xda\xf3\xf1\x38\ -\xbf\xbc\x8f\x92\x62\x03\xe0\x39\x66\x3e\x15\x05\xe0\x15\xb0\x23\ -\x8e\x39\x16\x97\x5c\xa1\x20\x10\xb4\x7f\xab\xb8\x67\x82\x29\x2a\ -\x11\xa0\x9a\x11\x79\xc2\x5c\x1b\x03\x31\xf2\xb2\x68\xa7\xc1\x9f\ -\x05\xa7\x61\x57\xba\x94\xf7\xc5\x66\x61\x6c\x58\x2a\xb3\xd6\xc7\ -\x8a\x49\x11\xaf\xed\xf5\x8e\xb7\x6e\x16\x5c\x7b\xa9\x30\x90\xb0\ -\xba\xde\x6c\x56\x6c\xc7\x3b\xd8\xa4\x39\xb8\xe9\xb5\xd7\x14\x84\ -\x86\x27\xc1\x68\x25\xba\x8b\x8b\x40\x9c\xf8\xdd\x4a\x6c\xf7\x40\ -\x3c\x66\x59\xdf\x4f\x02\xd9\xf2\x96\xd1\x36\x5d\xa6\x4f\x3a\xb1\ -\xb8\x6a\xd0\x73\xbd\xd4\x55\x94\x44\x55\xb4\xc7\x44\x47\xa1\x01\ -\xeb\x4a\xe5\x6b\x93\xcc\xa7\xff\xbe\xfb\xb5\x07\x78\x1c\x4f\xff\ -\x53\x98\x87\x3d\x36\xad\x40\x34\x2b\xd6\x30\xec\x7e\xd9\xd9\x9b\ -\x8a\x78\x6a\x93\x4e\x54\xdd\xa6\x4b\x98\x69\x7b\xc1\xf4\xf7\xed\ -\x32\x03\x74\xf6\x8c\x03\x61\xfb\x3e\x7d\xdf\x69\xd3\xad\xd1\xcd\ -\x05\xd2\xe8\x9d\x5b\x12\x2f\x53\xab\xe4\x7f\xaa\xd2\x2c\xfb\xdd\ -\x1a\x19\x2c\xc4\xb6\xd3\xb4\xca\xf4\x6d\x6d\xb3\x79\xec\xbc\xf0\ -\x5b\x37\xba\x65\x34\xf0\xf2\xda\xef\xc2\x50\xb7\x16\xfb\xf0\xd4\ -\xc0\x21\xc7\x11\xce\xa2\x99\xce\x6e\xdc\x3f\x2c\xd3\x39\xe1\x2e\ -\x4c\xb1\x5e\x2d\x8b\x44\xb7\xea\x5d\x58\x17\xc3\x14\x36\x84\xa2\ -\xe3\x54\x27\x09\x1b\x23\x22\x29\xc0\x86\xb6\x89\xbb\x6b\x49\xc4\ -\x24\x16\x2a\x94\x13\x4f\x4a\x44\x70\x18\x62\x79\xb9\xcf\x7d\xab\ -\xa8\xba\x3f\xc9\x45\x7d\xce\x41\x82\x05\xe2\xaa\xcd\x4a\xb8\xfe\ -\x5c\xcd\x21\x92\x07\x8d\x41\x4a\xac\x9b\x66\x9d\xe9\x69\x5e\xe4\ -\x4f\xb0\xf6\x21\x87\x99\xe2\x41\xf7\xf2\x4d\xb3\x41\xf9\x34\x40\ -\x1c\x13\x21\x30\x55\x1d\xdd\x66\x2a\x08\xc9\x74\xb6\xae\xaa\x21\ -\xed\xbf\x45\x9a\x4f\x61\x2a\xb5\xe9\xa8\x75\x23\x03\xbc\x56\x53\ -\xde\xd1\xf6\xe3\x68\x09\x49\x04\xc9\xc3\x98\x68\x67\x87\xa3\x87\ -\xd4\x26\x81\x42\x52\x5d\x46\xe6\x41\x9b\x86\xff\x98\x96\xe9\x2c\ -\xcd\x6c\x17\xf5\x63\xa6\xaf\x92\xb4\x5c\xc1\x9c\x4c\xd3\xdc\x0e\ -\xe3\xaa\x78\xd4\x66\x9e\x15\x9b\x9e\xaf\xf3\x08\xbe\xbc\x59\x14\ -\x3f\xd8\x59\xcc\x93\x69\x14\x43\x22\x58\x67\x51\xa5\x07\xb9\xd9\ -\xae\x1b\xc7\x23\x02\x29\xce\x99\xe4\x13\x2e\x24\xc2\x3c\x94\xa1\ -\x83\x27\x8c\x60\x14\x10\xac\x88\x83\x91\x92\x2c\xe0\x6c\x82\x1d\ -\x1e\x22\x16\x28\x45\x61\xe3\x75\x28\x08\x48\x20\xd3\x00\x1a\xb1\ -\xa3\x10\xcc\x26\xe1\x13\xc2\x90\xc2\x98\x10\x07\x92\x99\x54\x94\ -\xa9\x09\x25\x48\x32\x86\xa9\xc3\x39\x22\x4c\x71\x31\x21\x21\x22\ -\x24\x64\x81\x43\x19\x12\x21\x91\x62\xe2\x71\xc8\x97\x98\x33\x87\ -\x85\x48\x85\x3c\x54\x13\x8f\x86\x08\x87\x8c\x38\x76\xcb\xc5\x0a\ -\xac\x78\x82\xc2\xe8\x28\xe1\x0e\x48\xcb\x40\x48\x0a\x42\x60\x4d\ -\x28\x0c\x24\x1a\x20\x19\x2a\x41\x26\x1e\x53\x88\x73\x41\x1d\x4f\ -\x10\x44\x03\x42\x00\x62\xd0\x87\x54\x3c\x08\xc0\x59\x0a\xa6\x03\ -\x09\xa3\x02\x21\x82\x25\x28\x12\xa4\x82\x80\x04\x13\x85\xa4\xe4\ -\xe0\xbb\xb5\x4c\x38\x61\x64\x42\xa0\x27\x19\x48\xea\x64\x40\xc4\ -\xca\xc6\x43\x04\xd6\x5d\x0c\x96\x25\x41\x42\x28\xa5\x60\x34\x0a\ -\x8a\x02\x26\xa5\xe5\x3c\x1d\x6d\x7d\x06\xf6\x7e\x30\x4c\x06\x47\ -\xcd\x83\xe2\x20\x07\x64\x55\x85\xf1\x20\xc3\x3f\x46\xd5\xda\x68\ -\x9b\x24\x07\x9b\xf2\xe8\x42\x18\x43\x7e\xbb\x39\xbf\x23\xff\x3b\ -\x90\x0f\x89\x87\x2b\x4a\xe9\x84\x53\x98\x7c\x01\x30\x1f\x05\xbe\ -\x18\x20\xbf\x6e\x50\x49\x11\x20\x5a\x05\xa2\xc1\x02\x00\x80\x08\ -\xc0\x28\xa0\xe4\x88\xf3\x9d\x28\xf9\xff\x30\xb2\x18\xd1\xd2\xdb\ -\x55\x61\x2a\x6f\x97\xac\x52\xd8\x93\x11\x0e\x28\x81\xc5\x31\xd6\ -\x7f\x2b\xb9\x7d\xb5\x24\x60\x4a\x37\xff\x3b\xe0\xdf\x17\x4b\xed\ -\xef\x0a\x93\x3e\xf8\x77\x6d\xa5\x51\xfa\x7f\x44\x33\xff\xce\x44\ -\xf3\xca\x4f\x61\xec\x65\x5d\xe7\xa1\x55\xbe\x18\x74\x79\xba\x4f\ -\x78\x18\x85\x81\x82\x05\x4f\xa5\xdd\x25\x82\xc0\xee\x08\x90\x05\ -\xec\x33\xcc\x4e\x28\x89\x7d\x0e\xa1\x38\x12\xb0\x12\x27\xb0\x0c\ -\x21\x97\x70\xbb\x46\xa9\x14\x00\x5b\x21\x2e\x8f\x62\xba\x80\x3a\ -\x6a\x58\xf8\xf6\x05\xed\x00\xf0\xb0\xd0\x15\x13\x3c\xa0\xe2\x5b\ -\x30\x3e\x44\xed\xb0\x52\x38\x5c\x9d\x27\x57\xec\x91\x89\xdd\x03\ -\x76\x33\x84\x6e\xab\x9a\xc1\xb1\xe5\xc7\x16\xec\xe9\xf8\x7f\xd6\ -\x05\xdb\xde\xfc\x43\xbc\x61\x5a\xa9\x3b\x1a\x74\x5b\x5f\x13\x05\ -\xc0\x80\x9a\x44\x3c\x23\x62\x0f\x76\x02\x8e\x7b\x10\xb7\x71\x09\ -\x63\x8b\xf4\x10\x89\x80\xf0\xe7\x24\x76\xcf\x48\xd4\x49\x85\x72\ -\x01\xe9\x03\x46\x30\xe9\xec\xc0\xe6\x08\xc7\x54\x09\xa7\x54\x41\ -\x9b\xfd\x26\xe0\x12\xf6\x9b\xae\x0f\x48\x0d\xed\xd3\x80\xd4\xc9\ -\x43\xb2\xd8\xb3\x7b\xdd\x21\xad\xd7\xa9\xd3\x4d\x6b\xa5\x37\xb2\ -\x67\x8f\x68\x0c\x8c\xf4\xdc\xde\xc4\xe9\xa0\x9e\x0e\x8b\xd4\x1f\ -\x00\x3f\xd4\xc2\x1f\x3f\x9c\xbe\x29\xb8\x3c\x5e\x0d\x2d\xf6\xeb\ -\x65\xf7\x0c\x16\xf8\xf3\x58\x38\x3d\xd7\x9f\x62\xe1\xe4\x90\x7f\ -\x02\x86\xfd\x91\xff\x59\x34\xd8\x2a\x44\x11\x42\xc7\xe0\x20\x60\ -\x67\x81\xad\x81\x4c\x7a\x53\x35\x1e\xa0\x4c\xa2\x5c\x01\x38\x6c\ -\xf9\xc5\x02\x09\x85\x70\xdb\x0b\x90\x5a\x93\x6a\x40\x82\x92\x49\ -\x49\xc8\x8e\x16\x0f\x3d\xdb\xb3\x5b\x15\x27\x74\x48\xea\x55\x00\ -\x0e\xbd\x91\xd6\x46\xd0\xb3\xa9\x73\xa2\x41\x9d\xd6\x86\x2d\xf4\ -\x7a\x6e\x63\x81\x28\xe7\x78\x4c\xf4\x60\x13\x1b\x2f\xfd\x43\x41\ -\xa0\xee\x63\x36\x73\xc3\x91\x17\x4a\x36\xa8\x1b\x07\x4f\x3d\x9b\ -\x41\xd5\x27\x15\x54\x8b\x80\x3e\x6e\x53\x1a\x0d\x2f\x87\x1b\x9c\ -\xbf\xe8\x0e\x3b\x8b\xe6\x98\x03\x5f\xd7\xf6\x58\x76\x7b\xf1\x3f\ -\xca\x4d\x58\x0d\ +\x00\x1c\xdf\x78\x9c\xed\x59\x5b\x6f\x9b\x48\x14\x7e\xf7\xaf\x60\ +\xe9\x4b\xab\x0d\x30\x0c\x18\x03\xb1\xd3\x87\xad\xba\xaa\xb4\x52\ +\xa5\x4d\xab\x7d\xac\xc6\x30\xc6\xb3\x01\x06\x0d\x83\x2f\xf9\xf5\ +\x7b\x86\x3b\xb6\xb7\xb1\x56\x5a\xe7\x25\x44\x09\xcc\xb9\x9f\x33\ +\xdf\x39\xa0\xc9\xf2\xe3\x21\x4b\xb5\x1d\x15\x25\xe3\xf9\x4a\xb7\ +\x4d\xa4\x6b\x34\x8f\x78\xcc\xf2\x64\xa5\x7f\xff\xf6\xd9\xf0\x75\ +\xad\x94\x24\x8f\x49\xca\x73\xba\xd2\x73\xae\x7f\x7c\x98\x2d\x7f\ +\x31\x0c\xed\x37\x41\x89\xa4\xb1\xb6\x67\x72\xab\x7d\xc9\x9f\xca\ +\x88\x14\x54\x7b\xbf\x95\xb2\x08\x2d\x6b\xbf\xdf\x9b\xac\x25\x9a\ +\x5c\x24\xd6\x07\xcd\x30\x1e\x66\xb3\x65\xb9\x4b\x66\x9a\xa6\x81\ +\xdf\xbc\x0c\xe3\x68\xa5\xb7\x0a\x45\x25\xd2\x5a\x30\x8e\x2c\x9a\ +\xd2\x8c\xe6\xb2\xb4\x6c\xd3\xb6\xf4\x41\x3c\x1a\xc4\x23\xe5\x9d\ +\xed\x68\xc4\xb3\x8c\xe7\x65\xad\x99\x97\xef\x46\xc2\x22\xde\xf4\ +\xd2\x2a\x9a\xbd\x53\x0b\xd9\x41\x10\x58\x08\x5b\x18\x1b\x20\x61\ +\x94\xc7\x5c\x92\x83\x31\x55\x85\x18\x2f\xa9\x62\x84\x90\x05\xbc\ +\x41\xf2\x3a\xa9\xf0\x90\x42\x29\xfe\x35\x98\x9a\x3b\xf6\x0e\xe5\ +\x2f\xe0\xb7\x57\xe8\x08\x66\xc9\x2b\x11\xd1\x0d\x68\x52\x33\xa7\ +\xd2\xfa\xf4\xed\x53\xcf\x34\x90\x19\xcb\x78\x64\xa6\xab\xfe\xc4\ +\xef\x64\x4b\x72\x92\xd1\xb2\x20\x11\x2d\xad\x8e\x5e\xeb\xef\x59\ +\x2c\xb7\x2b\xdd\x73\x8b\x43\xbd\xde\x52\x96\x6c\xe5\x88\xc0\xe2\ +\x95\x0e\x19\xe2\x05\xf6\xea\x75\x17\x43\xd8\x23\x09\x99\x0e\x6e\ +\x44\x5b\xc3\x63\x96\xeb\x9b\xb6\x26\x82\x85\x87\xa6\xda\x31\x8f\ +\x54\x48\x2b\xfd\x31\x27\xc5\x8f\xaf\x42\x6e\xb9\xd9\x15\xb2\xb7\ +\xc3\x2b\x59\x54\xf2\x07\x3d\x48\x9a\x37\x06\x21\x95\x51\x5e\x35\ +\x5b\xa9\x99\x93\x9c\x46\x18\xb7\xf5\x07\xa0\x2c\x63\xba\x29\x15\ +\xa7\x49\x47\xad\x20\x1f\xbf\xe6\x01\xb7\xf7\x57\x80\x62\x41\x23\ +\x85\xb5\x46\x7a\x14\xb0\x3c\xaa\xf2\x4e\x45\x9d\x66\x0f\xb4\x49\ +\xee\xc5\x8f\x03\x24\xae\x85\x9a\x83\xe1\x8f\x7d\x51\xe2\xd8\x48\ +\xd8\x00\x1f\xb8\xa1\x8b\x32\xcf\x6a\x13\x7e\x62\xa6\x8d\xc0\xe0\ +\x82\x25\x0c\x92\xad\xe5\xb0\x6d\x3a\xf5\x35\xd5\x81\xa4\x47\xb9\ +\xe1\x85\xe3\xea\x9a\xd5\x66\x2f\x48\xcc\x48\xfa\xbb\xba\x41\x1f\ +\x9e\xb9\x89\x78\x9a\x82\xda\x4a\x27\xe9\x9e\x1c\xcb\xde\x66\x8d\ +\xe4\x70\x2b\x28\x74\xde\x3b\x78\xa6\x44\x74\x36\x1c\xdb\x75\x8d\ +\xc5\xc4\xfb\xd4\x89\xe3\xcf\x91\x81\x7b\x81\xa4\x25\x7f\xcf\x99\ +\x84\x36\xab\x4a\x2a\x1e\x15\x54\xbf\xe6\xdf\x4b\x7a\x26\xf5\x4d\ +\x90\xbc\x84\xbe\xc8\x56\x7a\x46\xa4\x60\x87\xf7\xf6\x1d\x52\x3f\ +\xa6\x17\xf8\x73\x1c\xb8\xf0\x8c\x11\x36\x7d\xec\x7b\xce\x87\x5e\ +\x3d\x82\x5d\xc1\x78\x6e\x62\xcf\x45\x83\xeb\x08\x76\xc2\x5b\x60\ +\x73\x11\x2c\x1c\xaf\xa7\x6e\x2e\xca\x6e\x2e\xca\x0a\xa8\xbc\x6b\ +\x3a\xee\xdc\xf6\xfd\xa1\xa8\xd3\x82\x5c\x5d\x54\x55\xaa\x8b\xb5\ +\x7c\x68\x25\x96\xa5\xe4\x45\x27\x0d\xe8\x94\xc7\x14\x50\xa9\x88\ +\x06\xd8\xe4\x22\x7c\xb7\xa9\xaf\xfb\x9a\xc4\xa1\x8a\x4c\x1e\x43\ +\xfb\x5e\x1f\x74\xf8\x66\x53\x52\x70\x8d\x46\xb4\xba\xc9\x41\x03\ +\xbc\x79\xc6\x80\x8d\xff\xea\x0f\x5d\xf2\x67\x5f\xf6\xe7\x8f\xfc\ +\x2d\xad\x69\xf2\xff\x2f\x42\xe7\x2f\x21\x74\xf1\x86\xd0\x6b\x11\ +\x3a\xbf\x29\x42\xbd\x1b\x23\x74\xfe\x4a\x08\x75\x5e\x44\x28\x7a\ +\x83\xe8\xb5\x10\x75\x6e\x0a\x51\x7c\x63\x88\x3a\xaf\x04\x51\xfb\ +\x25\x88\xce\xdf\x10\x7a\x2d\x42\xed\x9b\x22\x74\x7e\x63\x84\xda\ +\xaf\x84\xd0\xe0\x25\x84\x3a\x6f\x08\xbd\x16\xa1\xc1\x4d\x11\x1a\ +\xdc\x1a\xa1\xf8\x95\x20\x8a\x5f\x82\xa8\xf7\x06\xd1\x6b\x21\x8a\ +\x6f\x0a\x51\x74\x63\x88\xbe\x16\x42\xdd\x17\x11\xfa\x36\x45\xaf\ +\x86\xa8\x7b\x53\x88\x2e\x6e\x3d\x45\x7f\xfe\x29\xba\xb4\xd4\xf1\ +\x5b\xfd\xd4\x9f\xad\xa9\x93\xc0\x78\xc7\xe8\x7e\xd6\x9b\x5b\x93\ +\x1e\x2b\x05\x49\x68\x1d\x1d\x40\xb3\x09\xaf\x65\xac\xb9\x88\xa9\ +\xe8\x58\x5e\x7d\x4d\x58\x6d\x02\xcd\x61\xf7\x6c\xba\x67\xca\x6a\ +\xcf\x47\x97\xf9\xe5\x96\xc4\x7c\x0f\xe0\x39\x65\x3e\x73\x0e\x78\ +\x05\xec\xcc\x4f\x39\x0a\x97\x36\x36\x6d\xc7\x07\xfc\x9c\xf2\xc0\ +\x13\x56\xe0\x5a\xb8\xc1\x39\xb3\x12\x02\x4a\x64\xa4\xe4\x48\x21\ +\x9d\xc4\xc5\x7e\xf7\xe5\x52\x6e\xf9\x3e\x11\xaa\x2a\x52\x54\xf4\ +\x54\x31\xe6\x51\xa5\x4e\xd0\x8d\xaa\xe9\xb7\xf6\xdc\x76\x24\xa1\ +\x74\x8d\xf5\x9a\x1f\x2e\x1b\xd8\xb3\x1c\xb2\x34\xda\x93\x60\x1b\ +\xfb\x67\xb5\x68\x25\xba\xb3\xe1\xc5\xfc\x2c\xed\x56\xe2\x30\xe0\ +\xf0\x94\xa5\x72\x3f\xab\x63\xcb\xcb\xc8\x81\x65\xec\x99\xc6\x0a\ +\x56\x0d\x78\x96\x19\x95\x24\x26\x92\x0c\x90\xe8\x28\x78\xe1\x74\ +\x5f\xca\x4b\x11\x6f\xc2\x3f\x3f\x7d\xee\xf1\x1d\x45\xe1\x5f\x5c\ +\x3c\x0d\xd0\x54\x02\x64\xcd\x2b\x08\xbb\xef\x3a\x75\x20\x1c\x85\ +\x6a\xe6\x10\xf9\xc0\x32\xd8\x68\x75\x86\xff\xeb\x21\x4b\x01\x9c\ +\x3d\x63\x22\xac\x4e\x7f\x07\xa3\x8d\x59\x41\x9b\x33\xfa\x8b\xff\ +\xd6\x88\xa3\x8c\x29\x25\xeb\x51\xb2\x34\xfd\xa2\x9c\x8c\xfa\xb0\ +\x35\xca\x64\x4a\x47\xcd\x69\xb5\xd1\x77\xcd\x33\x4a\x6e\x69\x75\ +\xd9\xd7\xab\x64\xa8\x4a\x8d\x17\xfb\xb4\xb0\x29\x59\xd3\x74\xa5\ +\xff\xa1\x98\xda\x19\x37\x11\xbc\x2a\x32\x1e\xd3\x56\xbd\xab\x66\ +\x32\x1e\x5c\x63\x04\x6a\x9a\x3c\x1b\xd3\xc8\xb4\x3d\x0c\x68\xc1\ +\xed\xb8\xee\x56\x9e\xe9\x78\x68\x1e\xf8\xde\x9d\xe1\x79\xa6\x8d\ +\x7c\x1f\x79\x1f\x86\x89\x57\x10\xb9\x3d\x9b\x40\xed\xf0\x41\xf5\ +\x75\xbf\x81\x8a\xa9\xc5\x1a\x46\x7e\xbd\x18\x4d\xbe\x7a\x29\xaa\ +\x94\x86\x39\xcf\x9f\xa1\xc5\x61\x54\x09\xfe\x44\x95\x3c\xa6\x98\ +\xb6\xcb\x06\xcd\x21\x74\x9b\xed\x41\x2c\x01\xb2\x3b\x86\x9a\x48\ +\x50\x84\x70\x5d\x49\x39\xa6\xfd\xcd\x59\x1e\x42\x5d\xf2\xb8\xa3\ +\xc2\x06\x52\x91\x02\x30\x65\xe8\x76\xb4\x21\x90\x96\x10\x13\x18\ +\x12\x42\x90\xa3\x8a\x87\x8e\xa9\xcd\xa0\x84\xe1\x99\x11\xf1\x44\ +\x45\xc3\xdf\xb1\x92\xad\x59\xaa\x4c\xd4\x8f\x29\xbd\x8f\x59\x59\ +\xc0\x2e\x84\x2c\x57\x61\xdc\xf3\x1d\x15\x9b\x94\xef\x7b\x3e\xcd\ +\x09\xdc\x8c\x35\x89\x9e\x92\x3a\xbe\x90\x44\xd0\xf1\x55\x4a\x24\ +\x1d\xcd\x60\xd5\x20\x1a\x8c\x1d\x13\x05\x0e\x76\xee\xdc\x85\x67\ +\xe2\xc0\x77\x34\x74\x17\x04\xa6\xef\xb9\x76\xa0\x19\xdd\xd3\x1d\ +\x02\xb2\x1b\x98\xb0\x37\xb6\xaf\x4d\xa8\xed\xc2\xd7\x3a\x76\x4d\ +\x35\x7a\xf2\x44\xd8\xe8\x6d\x4c\x4d\x1b\x83\xcb\x91\x99\xe7\x93\ +\x37\x86\x80\x57\xa6\x87\x7c\x67\x4c\x1e\xde\xa8\x39\x6c\x93\xe4\ +\xc2\x80\xb9\xb8\x23\xb2\x12\x54\x8d\x96\xe1\xc5\x92\x34\x5d\x01\ +\xb7\xa5\x6a\xde\x87\xd9\x3f\xeb\x1f\x07\xd5\ \x00\x00\x0b\x6e\ \x00\ \x00\x2d\x39\x78\x9c\xed\x5a\x6d\x6f\xdb\xc8\x11\xfe\x9e\x5f\xc1\ @@ -30249,212 +30025,125 @@ qt_resource_data = "\ \x4b\x1e\x8f\xd8\x68\x55\x45\xac\x6f\x07\xcf\x23\x0b\x77\x08\x41\ \x2b\x25\x81\x15\x65\xa4\x15\xe6\xcb\xe5\xdb\xc5\x74\x15\xef\xe2\ \xf1\x75\x41\xbf\x1d\xbc\x7e\xf1\x1f\x62\x9b\x4c\x39\ -\x00\x00\x0c\xb1\ +\x00\x00\x07\x50\ \x00\ -\x00\x4d\x5e\x78\x9c\xed\x5b\x5b\x6f\xdb\x56\x12\x7e\xcf\xaf\xe0\ -\x2a\x2f\x0d\x96\xa4\xce\xfd\xa2\xd8\xe9\x43\x83\x2e\x0a\x14\x58\ -\x60\xdb\x62\x1f\x0b\x5a\xa2\x65\x6e\x24\x51\xa0\x28\x5f\xf2\xeb\ -\xf7\x1b\xde\x44\x59\x54\xe2\x38\xa9\xda\xa4\x52\x10\x9b\x9c\x33\ -\xe7\xcc\x9c\x99\x6f\x2e\x87\xa2\x2f\xbe\xbf\x5f\x2e\x82\xdb\xb4\ -\xd8\x64\xf9\xea\x72\xc4\x63\x36\x0a\xd2\xd5\x34\x9f\x65\xab\xf9\ -\xe5\xe8\xb7\x5f\x7f\x8c\xdc\x28\xd8\x94\xc9\x6a\x96\x2c\xf2\x55\ -\x7a\x39\x5a\xe5\xa3\xef\xdf\xbc\xb8\xf8\x47\x14\x05\x3f\x14\x69\ -\x52\xa6\xb3\xe0\x2e\x2b\x6f\x82\x9f\x56\xef\x36\xd3\x64\x9d\x06\ -\xdf\xdd\x94\xe5\x7a\x32\x1e\xdf\xdd\xdd\xc5\x59\x43\x8c\xf3\x62\ -\x3e\x7e\x15\x44\xd1\x9b\x17\x2f\x2e\x36\xb7\xf3\x17\x41\x10\x40\ -\xee\x6a\x33\x99\x4d\x2f\x47\xcd\x84\xf5\xb6\x58\x54\x8c\xb3\xe9\ -\x38\x5d\xa4\xcb\x74\x55\x6e\xc6\x3c\xe6\xe3\xd1\x8e\x7d\xba\x63\ -\x9f\x92\xf4\xec\x36\x9d\xe6\xcb\x65\xbe\xda\x54\x33\x57\x9b\x97\ -\x3d\xe6\x62\x76\xdd\x71\x93\x36\x77\xb2\x62\xe2\xde\xfb\x31\x13\ -\x63\x21\x22\x70\x44\x9b\x87\x55\x99\xdc\x47\xfb\x53\xa1\xe3\xd0\ -\x54\xc1\x18\x1b\x63\x6c\xc7\xf9\x34\xae\xc9\xfd\x02\xa6\x38\xaa\ -\x4c\x35\xda\x97\x0e\xf3\xaf\xf1\xbf\x9b\xd0\x12\xe2\x4d\xbe\x2d\ -\xa6\xe9\x35\x66\xa6\xf1\x2a\x2d\xc7\x6f\x7f\x7d\xdb\x0d\x46\x2c\ -\x9e\x95\xb3\xde\x32\xad\xf5\xf7\xe4\xee\xb9\x64\x95\x2c\xd3\xcd\ -\x3a\x99\xa6\x9b\x71\x4b\xaf\xe6\xdf\x65\xb3\xf2\xe6\x72\x64\xd4\ -\xfa\xbe\xba\xbf\x49\xb3\xf9\x4d\xd9\x23\x64\xb3\xcb\x11\x76\x28\ -\xac\x30\xd5\x7d\xab\xc3\xa4\x43\x12\x8b\xa5\xa8\x59\x9b\x85\xfb\ -\x43\xca\xc5\x3c\x28\xbc\x35\x6c\x7f\xf6\x2c\x9f\x92\x4a\x97\xa3\ -\x5f\x56\xc9\xfa\xf7\x1f\x80\x80\xb4\x88\x5b\x4b\x76\x0b\xe5\xdb\ -\x72\xbd\x2d\x7f\x4f\xef\xcb\x74\x55\xaf\x88\xbd\xf4\x36\x56\x0d\ -\xd3\xb4\x78\x6f\x53\x3d\x90\xf3\xd1\x1b\x50\x2e\x66\xe9\xf5\x86\ -\x46\xea\xfd\xd0\x1d\x36\xe4\xaa\x31\x8c\xc2\x29\x69\x52\xfc\xab\ -\x48\x66\x19\x14\xa9\xf9\x7a\x5a\x4c\xf3\xc5\x22\x9d\xc2\x28\xc9\ -\xe2\x2e\x79\xd8\x8c\x3a\x06\x2c\xb5\x3f\x55\x72\xa5\x9a\x45\xb1\ -\xec\xa6\xcc\xd7\x2d\x2f\xb6\x5e\x3e\x2c\xb0\x5f\x22\x46\x58\x31\ -\x2f\x26\x2f\xaf\xab\xcf\xeb\x8a\x94\xc3\x39\x59\xf9\x30\xe1\xaf\ -\x47\xbb\x39\xf9\xf5\xf5\x26\x85\x60\xd6\xa3\x55\x0e\xc1\x0c\xc8\ -\x32\xa3\x60\xfc\x79\xd2\xd8\x90\x34\x3e\x2c\xcd\x75\xd2\x2e\xc6\ -\xfb\xdb\x6e\xa8\x9d\xc1\xd6\xb0\xff\x1a\x16\x43\xcc\xb6\x2b\x75\ -\x8e\x2f\x1f\x08\xa6\xfb\xac\x72\x36\x3a\x30\xfa\xed\xfa\xf7\x7b\ -\x6c\x3c\x98\x04\x52\xe0\x07\x1f\xe4\x78\xa8\x39\x38\xc2\x10\xbf\ -\xd8\x20\xcf\x7b\x02\xf3\x07\x96\x69\x34\x88\xf2\x22\x9b\x67\xc0\ -\x4c\xc5\x27\x78\x2c\xab\xcf\xfe\x1c\x18\xa3\xb7\x37\x61\xa5\xda\ -\xd9\x84\x6c\x91\x2c\x3e\x19\x44\x55\x46\x98\xdc\x14\x29\x32\xd8\ -\xcb\x01\x34\xf5\x65\xef\x8b\x90\x4e\xef\x76\x3c\x6f\x88\xbf\xad\ -\xb2\x12\xa9\x6a\xbb\x49\x8b\x5f\x28\xdc\xff\xbd\xfa\x6d\x93\x1e\ -\x70\xfd\x5a\x24\xab\x0d\x72\xcb\xf2\x72\xb4\x4c\xca\x22\xbb\xff\ -\x8e\x87\x8c\xfe\xc5\xc6\x3b\x2d\xbc\xc2\xb5\x60\x22\x76\xc2\x19\ -\xf9\xaa\x9b\x3e\x85\x47\x84\xd0\xb1\x30\x8a\x89\x1d\x15\x5e\x30\ -\x56\xc4\xd6\x5b\x69\x3a\xea\xf5\x20\xef\xf5\x20\x6f\x01\xab\xab\ -\x58\x2a\xcd\x9d\xfb\xa3\x0d\x1a\xd9\x8f\x98\x34\x12\xdf\xb2\x51\ -\xbf\x68\xaa\x83\x2d\x4f\x98\xec\x22\x75\xda\x74\xd7\x93\x77\x24\ -\xe1\xfd\x41\x08\xd5\x1f\x43\xa8\x3d\x23\xf4\xa9\x08\xd5\x27\x45\ -\xe8\x89\x0b\x32\x76\xf7\x2c\x84\xee\x19\xfe\xc3\x3e\x1a\xf6\xe7\ -\xb0\xef\x87\x71\xf2\x99\xe0\x7b\x1a\xc2\x0f\x03\x45\x69\xc6\x9f\ -\x13\x71\xc7\x70\xf6\x47\x97\x25\xf9\xd1\xa0\xff\xa6\x8b\xfd\x97\ -\x8d\x7a\x79\xd2\xa8\x17\x27\x8e\x7a\x79\x8e\xfa\x9d\x55\x0e\xa3\ -\x3e\x72\xcf\x09\xba\x3f\x2b\xee\xf9\xc7\xe2\x5e\x9f\xc3\xfe\xa9\ -\x61\xcf\x4f\x1a\xf6\xfa\xc4\x61\xcf\xcf\x61\xbf\xb3\xca\x40\xd8\ -\x3f\xbd\xdc\x0f\x3c\x05\x38\x75\xd8\xfb\x8f\x85\xbd\x3c\x87\xfd\ -\x53\xc3\xde\x9f\x34\xec\xfd\xa9\xc3\x5e\x9c\xe3\x7e\x67\x96\xc7\ -\x71\xef\xe4\x73\x42\xee\x99\x51\xff\xf7\x30\x29\xa5\xd2\xc8\x3c\ -\x3d\x99\x7e\x52\x17\xf5\x85\x0b\xfe\x89\x3b\x7d\x7d\xf2\x67\x50\ -\x3c\x3a\x87\xff\x87\xb1\xea\x22\xf6\x64\xac\xca\x4f\x3a\xe9\x7f\ -\xe1\x33\xe9\x89\x9f\x45\x89\x93\x57\x2a\xf9\xdc\x27\xa6\x7f\x1b\ -\xac\xaa\x27\x23\x55\x7f\x52\xb9\xfa\xc2\xcf\x4c\x4f\xdc\x51\x99\ -\xde\xd1\xe6\x44\xcf\x4d\x7b\xb1\x71\xda\x67\xfb\xf2\x63\xdf\xe8\ -\xf5\xfc\x7e\x6e\xfc\x3f\x96\x52\x4f\xfa\x65\xfb\xc9\x51\xfa\xe1\ -\xca\x7f\x31\xa6\xd7\x18\xaa\xab\xee\xcb\x75\x7a\xa5\x62\x76\x9b\ -\xa5\x77\x2f\xba\xd5\xae\x92\x0e\x2b\xeb\x64\x9e\x56\xca\x01\x9a\ -\xb5\x76\xcd\xc0\x55\x5e\xcc\xd2\xa2\x1d\x32\xd5\x67\x6f\xa8\xd1\ -\xbf\x7e\x6b\xe8\xc5\xbe\xcf\x68\xd5\x6e\x9c\x0d\x8f\x6f\x6e\x92\ -\x59\x7e\x07\xf0\x3c\x1e\x7c\x9f\xe7\xc0\xab\x8c\x9d\xf3\xcc\x59\ -\xf9\x78\xb8\x02\xa7\x8b\x39\xb7\x5c\x98\x83\x41\xc8\xd3\x32\x36\ -\x46\x5b\x7b\x38\xb8\x2d\x0a\x18\x2a\x5a\x24\x0f\x29\x36\x35\x57\ -\xc2\xb5\x81\xb5\xb9\xc9\xef\xe6\x05\xd9\xa6\x2c\xb6\xe9\xe3\x89\ -\xb3\x7c\xba\xa5\x17\x92\xa2\x6d\x1d\x75\xcd\x6b\x30\x3d\x0e\x9a\ -\x1b\x5d\x5d\xe5\xf7\xc3\x0b\xdc\x65\x2b\xec\x35\x6a\x5e\xac\xe1\ -\xc2\x1d\x58\xa4\xe1\x68\x5f\xb5\xb1\x5a\x1f\xe1\xb8\xdf\x81\xf1\ -\xf1\xd0\x03\x45\xe2\x91\xb1\x65\x72\x9f\x2d\xb3\xf7\xe9\x8c\xb0\ -\x55\x43\xe8\x62\x99\x96\xc9\x2c\x29\x93\x1d\x30\x5a\x8a\xb0\xb2\ -\x7d\x6e\x76\x51\xcc\xae\x27\xff\x79\xfb\x63\x07\xf2\xe9\x74\xf2\ -\xdf\xbc\x78\xb7\xc3\x27\x31\x24\x57\xf9\x16\x6a\x77\xa1\x47\xaf\ -\xd7\x4c\x27\x94\x79\x92\xf2\x4d\xb6\x84\xbb\xe9\x95\xa8\x7f\xde\ -\x2f\x17\x80\x68\x37\xb0\xc7\x4c\x2f\x81\xec\x16\xad\x97\x2d\xd2\ -\xfa\x95\xa7\xc1\xb7\xc4\x66\xd3\x65\x46\x93\xc6\xbf\x94\xd9\x62\ -\xf1\x13\x09\xe9\x05\x63\xb3\x68\x56\x2e\xd2\x37\x95\xcc\xfa\xb2\ -\xdd\xc5\xb8\xd9\x46\x1b\x4b\xbd\x5d\x5e\x8c\x5b\x33\x54\x77\xf3\ -\x9d\x79\x2a\xe0\xf0\xc7\x16\x5e\x24\x57\xe9\xe2\x72\xf4\x33\x0d\ -\x06\x07\xa3\xf3\x22\xdf\xae\x97\xf9\x2c\x6d\xa6\xb7\x66\x9d\xf7\ -\xf3\x58\x1f\x8a\x41\x50\x1e\x64\x6d\x16\x73\x23\x00\x1b\xd1\x64\ -\xef\xf6\xce\xc4\xd2\x30\xed\x9d\x09\x23\x63\x62\xce\x9c\x63\xe6\ -\xd5\x2e\xff\xad\x93\xf2\xe6\x20\x1f\x75\x79\x27\xd6\x5c\xe8\xd7\ -\x4d\x66\x62\xd5\xe7\xf5\x35\x2c\xb9\x77\xd3\x4b\x8b\xd5\x6d\xb1\ -\x5d\xa4\x93\x55\xbe\x7a\x8f\x04\x80\x3c\x56\xe4\xef\xd2\x8e\xbf\ -\xbe\xad\x51\x3e\xd1\xb1\xb6\x42\x09\xa9\x4c\x4b\xa7\x74\x05\x93\ -\x4c\xae\xb6\x65\xd9\xa7\xfd\x2f\xcf\x56\x13\xb8\x32\x2d\x5a\x6a\ -\x75\xb3\x00\x5e\xcb\x89\x6a\x69\x3b\x3d\x1a\xc2\x2c\x41\x06\x29\ -\x8a\xe4\x81\xd4\x49\xfb\xd4\x3a\x89\x22\xb1\x2e\x93\xe2\x5d\x5a\ -\xd4\xe3\xb7\xd9\x26\xbb\xca\x16\xb4\x44\x75\xb9\x48\x5f\xcf\xb2\ -\xcd\x1a\x3e\x99\x64\x2b\x52\xe3\x75\x7e\x9b\x16\xd7\x8b\xfc\xae\ -\x1b\x4f\x57\x09\x7e\x45\x57\xc9\xf4\x1d\x79\x71\x35\x9b\x24\x53\ -\x24\x82\xed\x22\x29\xd3\x5e\x7e\xa6\xb8\x09\xb8\xb6\xb1\xf6\x4c\ -\x89\x50\x29\x16\x3b\xa9\x85\x0b\xa6\x41\x84\xd2\xea\x61\x83\x30\ -\x42\x12\xe4\xd6\x07\x91\x8e\x9d\x65\x5e\x90\x0f\xc1\xa2\x82\xc8\ -\xc5\x8e\xa3\xf8\x82\x60\x15\xd2\x56\x10\x71\x1b\x0b\xeb\x98\x0b\ -\x65\xac\xe0\xce\x20\x92\x34\x97\x69\x1d\x62\x84\x19\xc6\x1d\x48\ -\xc8\x8e\x4c\x59\x19\xe2\x42\x71\xa1\x64\x10\x29\x1b\x73\xf4\x0a\ -\xd2\x84\x5c\xc6\xde\x08\x03\x61\x4e\xc5\x4a\x7a\xe7\x5c\xa8\x91\ -\xa4\x1d\x07\x9b\xf7\xf0\x8b\x65\xcc\x87\xde\xc5\xd2\x32\xcb\xa1\ -\x24\x8b\xa5\x14\x46\x1b\x1d\x42\x82\xf4\x0a\x5a\x48\x11\x7b\x2d\ -\xac\x16\x21\x72\xad\xe0\x56\x43\x55\x5c\x19\xc0\x4d\x62\x39\x06\ -\x1a\xf7\x3e\xc0\xfe\xd0\x3b\x08\x1e\x72\x15\x5b\x2b\xa4\x0c\x38\ -\x8a\x3e\x14\xb2\xd8\x5c\x28\x4c\xac\x99\x75\x3a\x40\x7f\x20\xb5\ -\xd4\x1a\x0a\x0b\xc0\x54\x3b\x4e\x7c\xd2\x2a\x67\xb0\x98\x88\x85\ -\x30\x46\x05\x50\x52\x39\x6d\x3c\x0f\xbd\x8c\x2d\x93\x0e\xab\x31\ -\x1e\x5b\xc7\x8d\x56\x21\x67\x9e\xec\xa0\x78\xa0\x63\xe3\x0c\xf7\ -\xa1\x10\x30\xb9\x10\x22\x10\x36\x46\x9b\xa1\x60\x32\xb2\x90\x57\ -\x36\x80\x82\x1a\xda\x78\x92\xa7\xac\xc7\xce\xb9\x81\x81\xb5\x10\ -\x61\x24\x21\x58\x0a\x1b\x08\x0f\xb9\x52\xb8\x30\xc2\x98\xd0\xc2\ -\xd8\x80\xcc\x09\xd5\x3d\x98\x78\xec\xb9\xe7\x3a\x50\x3e\x36\x9a\ -\x3c\x88\x1d\x6a\xae\xb1\x67\xe7\xa0\x9c\x22\x26\x0d\x12\xba\x1c\ -\x6c\x06\x3d\x14\x4c\xe8\x24\xd8\x18\x7a\x21\x6b\x39\xd6\x47\x97\ -\xe5\xa4\xe4\x88\x4d\x34\x58\x52\x39\x5a\x5e\x2b\x8d\xb8\x25\x53\ -\x4a\x6b\x84\xae\x94\x40\x29\xc3\x5a\xd0\x18\xee\x13\x30\x3d\x7a\ -\x29\x2b\x2b\xad\xac\x12\x64\x78\xae\xe1\x65\xed\xc1\x05\x76\xc9\ -\xac\x10\x15\x2a\x94\xb7\x56\x87\x04\x06\xd8\xd8\xda\xa0\x56\x11\ -\x99\x21\x24\x34\x38\xe1\x3d\x01\x8e\x13\xe2\x48\xa6\x83\xdd\xac\ -\x61\x35\x08\x98\xd0\x8e\x36\xc5\xe0\x49\x98\x03\x28\x00\x56\xbc\ -\xe1\xa0\x11\x1c\xac\x74\x90\x01\x03\xc3\xac\x0c\x34\xb4\x6d\x8a\ -\x39\x0f\x34\x2a\x78\x4b\xc3\xec\x15\x0d\xfa\xc2\x1f\xef\x83\x25\ -\xf4\x31\xb4\x23\xac\x69\xb0\x23\x8d\x56\x05\xf0\x07\xd6\xa4\xb5\ -\x96\xc0\x01\x8c\x6b\xc0\x85\x2c\x01\x5a\x28\xa0\x95\xd2\xd2\x07\ -\x0a\x0b\x03\x53\x2e\xe4\x80\x99\xa7\x88\xe0\x40\x81\x76\x1e\x6e\ -\x81\x74\xe6\xa4\x21\x43\x7a\x02\x01\xb6\x00\xa7\x30\xb2\x1a\xc0\ -\xee\x19\x56\xa6\x68\x81\x9f\x34\x0f\x24\x75\xb1\xcc\x02\xfe\x1c\ -\x6e\x15\x46\x06\x1a\xbb\x34\x5a\xd7\xa8\x00\xfc\x6c\x60\xb1\x10\ -\x37\x4a\x93\x8e\xde\x3b\x2e\x2a\x93\x01\xef\x48\xa0\x1e\x9e\x77\ -\x80\x6a\x24\x80\x01\x63\xb0\x36\x84\x68\xc9\x34\xd9\xd5\x43\x5b\ -\xa0\x21\x54\x94\x64\x35\xc2\x0d\xc8\x53\xd8\x3b\xc5\x1a\x93\x02\ -\x21\xc9\x19\xcd\x47\x68\x60\x3a\x9c\xaf\x6a\xad\x15\xfc\x17\xc2\ -\x67\xd8\xbc\xa3\x75\xa0\x9a\xf3\xb0\x31\x4c\x67\x80\x45\x8a\x64\ -\x6c\xdb\x72\xc3\x43\x23\x62\xc4\x38\x9c\x8d\xae\x59\x3a\x23\x64\ -\x68\x09\x2d\xc0\x72\x04\x9f\x23\x9e\x5d\x05\x41\x40\x52\x93\x67\ -\x4c\xec\x99\x70\x84\x08\xc0\x45\x59\x85\x89\x4a\x23\x3e\x38\x21\ -\x02\xfa\x02\xa8\x34\x15\x51\x86\x84\x81\x48\x8c\x95\xe0\x94\x4c\ -\x60\x78\x8f\x06\x1c\xdb\xc5\x06\xaa\xed\xa2\x95\x62\x1e\x2e\xe1\ -\x14\x0e\x00\x40\x95\x5d\x3c\x42\xd8\x90\x79\x39\xb5\x61\x64\x03\ -\x03\x34\x63\x75\x04\x59\x24\x11\x12\xdc\x1a\xac\x66\xe1\x2b\x60\ -\x4a\x02\x0d\x16\x8e\xb4\xb0\x83\xc5\xd1\xc2\x38\x4e\xbe\x42\x51\ -\x43\x00\x51\xfe\xa0\x30\x73\x35\xea\x11\xa6\x81\x50\x04\x11\x48\ -\x03\x50\x11\x4c\x9c\x6c\x03\x8b\x6a\xaa\x17\x90\x09\x9b\x5a\x2f\ -\x80\x5d\x18\x15\x49\x49\xd1\x6a\x82\x8c\xc1\xaa\x2c\xc4\x63\x2e\ -\x2c\x32\x5c\x15\x0d\x06\x9c\x94\x4b\xe0\x29\x21\x75\x15\xb7\x8a\ -\xc2\x9d\xec\xca\x94\x87\x43\x22\x6d\x60\x03\xa0\x8e\xdc\xcf\xa1\ -\x91\x75\x55\xb5\x34\x80\xb8\x08\xde\x3f\x6a\xb4\xa9\x64\x62\xeb\ -\xfd\xd7\x3f\xf6\xce\x22\x2b\xd4\xb0\x32\x2f\x22\xf4\x92\xb7\x49\ -\xb9\x2d\x52\x6a\xc7\x7a\x47\x80\xc1\x92\x3b\x54\x63\x9b\xa3\xc0\ -\xb9\xc6\x7e\x4a\x8d\xa5\x42\x25\xb5\x45\x8d\x95\x14\xb6\x9c\x4a\ -\xac\x43\x45\xe1\x1e\xa5\x33\x64\x14\xce\xa8\x51\xd5\x9d\x0f\x0d\ -\xaa\x02\xc2\x4d\xec\x53\x39\x12\x22\xda\x27\x54\x20\x16\x3a\x4a\ -\xf7\xd2\xf3\xc0\x50\xa1\xa2\x0f\x8d\xb3\x2a\x37\xd8\x60\x7f\x56\ -\x4b\x6d\xc5\x41\x1a\x31\x20\x2f\x59\x20\x11\xb2\xb4\x51\xc2\xf4\ -\x69\xbb\x39\x0c\xd1\x50\x89\x72\x00\x35\x41\xcf\x08\x66\x88\xa1\ -\x55\x25\xda\x9b\xd6\x52\x29\xaf\xb2\x50\xa2\x9e\x50\x66\xc1\x5e\ -\x91\x23\xbc\x65\x88\x4b\xc8\x46\x2e\x60\x1e\x59\x89\x4a\x3b\x4c\ -\xe1\x5d\x8f\xc4\x51\x30\x10\xc1\xc8\x53\x2c\x34\x92\x92\x27\xe5\ -\x02\x5d\x05\x8e\x55\xd5\xb0\x45\x39\x71\x94\x91\xfa\x73\x1a\x62\ -\x23\x06\xd5\x8c\x2c\x4a\xed\x84\x34\x12\x9d\x0d\xad\x00\x25\xa9\ -\x58\xf4\xa9\xbb\x99\xd8\x67\x23\x4e\x53\x05\xf6\xd4\x52\xf8\x9a\ -\xa1\x56\xe7\xf1\xb4\x9a\x7a\x2c\x06\x9f\x17\x81\xf3\x81\x59\xe9\ -\xfd\x3a\x2f\xca\xe8\x61\xb6\xce\x70\xb6\x42\x7a\x11\x54\x33\x86\ -\xd6\x6f\x38\xef\x9f\xcc\x89\x88\x4d\xeb\xbf\x5a\x18\xdf\xe4\xcb\ -\x74\xfc\x90\x17\xd9\xbb\xf1\xdb\xe6\xc4\xb8\x19\xff\x9c\x5c\x8d\ -\xdf\x16\xc9\x75\x39\xce\xa0\xfb\xa6\x3a\xb4\xc7\xeb\xd5\xbc\xb7\ -\xe4\x61\xbf\x8f\x76\xd1\x59\x9c\x7e\xd1\x95\x51\xa7\x88\x86\x0d\ -\x9d\xbd\xa7\x2e\x12\x19\x58\xa0\xdf\xe7\x74\xed\xbc\x44\x13\x09\ -\x3a\x32\x39\xb2\x1e\x55\x1f\xf4\x4b\x28\xe8\x9e\x4e\x01\xfb\x36\ -\x9d\x4b\x6e\x58\xff\x78\xb6\x9f\xa8\x0e\x5e\xc6\x4f\x8a\xe9\x68\ -\x6f\xb8\xce\x64\xed\xf9\xe0\x4a\x38\xf3\xb9\xb9\xcb\x55\x54\xee\ -\xbf\xf5\xdc\xb5\x03\x35\x7c\x20\x46\x83\x46\xa7\x87\x1a\xdc\xa3\ -\xab\x41\xcd\xd4\x47\x58\xe8\x91\x9a\x46\x32\xe0\x5e\x0e\x73\x14\ -\x58\x04\x79\x44\x5b\xae\x8e\x71\x3c\x1c\xe1\xa8\xf2\xab\x40\x07\ -\x61\x49\x83\xb0\x95\x83\x9c\xc3\xc2\xba\x69\x13\x75\xf3\x80\xce\ -\x06\xdd\x6a\xbb\x46\x10\xb5\x57\x3d\x52\xcb\x4f\xd9\xa3\x1b\xee\ -\xe6\xf6\x69\xdd\x1c\x24\x8e\x4e\x4a\x27\x64\x37\x3c\x30\xa3\x27\ -\xa4\x1b\xed\x44\x1c\x2a\xf5\x7e\xff\xc9\xc0\x67\x80\x7f\x5b\x2c\ -\xbe\x7b\x79\xf8\x88\xf6\xd5\xe3\x68\x68\xb0\x4f\xd8\x3a\x86\x05\ -\x75\x1c\x0b\x87\x4f\x54\x0f\xb1\x70\xf0\x78\xf5\x00\x0c\x87\x5f\ -\xa0\x1c\xa0\x01\x7d\x95\xf7\x9c\x8b\x21\x38\xa0\x81\x36\x38\xab\ -\xa2\x37\x6d\x45\x55\x78\xe0\xd4\x71\x7a\x80\x83\xce\x25\xd4\xf3\ -\x9b\xb0\x59\x05\xa4\x46\xa4\xef\x91\xd0\xd9\xa3\x23\x44\x8f\xc8\ -\x7a\xc3\xd4\xdb\x59\x45\x1d\xf8\x8e\xd4\x4d\x61\x55\x13\x58\x0b\ -\x69\x64\xd8\x6e\x58\x04\x07\x33\xd0\x01\xd6\x32\xa8\x62\x75\xa3\ -\xb5\x04\xee\x83\xc7\x3a\xed\x77\x7d\xc3\xcf\x5b\x9c\xe6\xd4\x51\ -\x52\x9a\x45\x5b\x6a\x70\xfe\x0d\xfb\x57\xdd\x30\x6a\x3a\x35\xbc\ -\x38\x0f\x09\x3a\xe5\x78\x34\xba\xaf\xfa\xd5\x68\x3c\xff\x3b\x17\ -\x26\x09\x1f\xe0\x2c\xcb\x70\xba\xe0\x8a\xfe\x26\xd0\xb8\xc1\xc2\ -\xd4\xfb\xa3\x91\x73\x69\xfa\xd3\x4a\x53\x74\x24\x95\x9c\x8b\xd3\ -\x57\x5c\x9c\xe8\x3b\xe6\x67\x15\xa7\xde\x97\x8e\x07\x68\x38\x97\ -\xa7\x73\x79\x1a\xe4\xfc\xba\xca\x93\x92\x48\x6a\x96\x7b\x9c\x9b\ -\x84\x85\x8b\xb4\x3b\x52\x9e\xce\x27\xa7\xbf\x42\x79\x3a\x56\x7b\ -\xce\xe5\xe9\xeb\x2e\x4f\x91\x7b\x5e\x81\xfa\xc0\x59\xfa\x5c\xa0\ -\xce\x05\x6a\x90\xf3\xeb\x2a\x50\xda\x58\xfa\xba\xc6\xd3\xe3\x59\ -\x05\x8f\x72\x3d\x5c\x9f\xf4\xb9\x3e\xfd\x05\xea\xd3\x91\x34\x71\ -\xae\x4f\x5f\x7b\x7d\x7a\xee\x01\xea\x88\xa7\xce\x05\xea\x1b\x2c\ -\x50\xcd\x45\xf5\xeb\x82\x5e\x76\x7b\xf3\xe2\xff\xf6\xfc\x3b\x6e\ -\ +\x00\x36\x1d\x78\x9c\xed\x5a\x5b\x6f\xe3\x36\x16\x7e\xcf\xaf\xd0\ +\x6a\x5e\x1a\xac\x45\xf3\xa2\x7b\xec\x14\xc5\x0e\x5a\x14\x28\xb0\ +\x40\x67\x06\x7d\x1c\xd0\x12\x6d\xab\x91\x25\x83\x92\x63\x3b\xbf\ +\xbe\x87\xb2\x2e\x74\x2c\x27\x99\x4c\x46\xdd\x9d\xda\xc1\x8c\xc5\ +\x73\x21\x79\x0e\xbf\xef\x48\xa2\x39\xf9\x71\xb7\x4a\x8d\x7b\x21\ +\x8b\x24\xcf\xa6\x26\x41\xd8\x34\x44\x16\xe5\x71\x92\x2d\xa6\xe6\ +\xa7\x8f\x3f\x5b\xbe\x69\x14\x25\xcf\x62\x9e\xe6\x99\x98\x9a\x59\ +\x6e\xfe\x78\x7b\x35\xf9\x97\x65\x19\xff\x91\x82\x97\x22\x36\xb6\ +\x49\xb9\x34\x7e\xcd\xee\x8a\x88\xaf\x85\xf1\xc3\xb2\x2c\xd7\xe1\ +\x78\xbc\xdd\x6e\x51\x52\x0b\x51\x2e\x17\xe3\x6b\xc3\xb2\x6e\xaf\ +\xae\x26\xc5\xfd\xe2\xca\x30\x0c\x18\x37\x2b\xc2\x38\x9a\x9a\xb5\ +\xc3\x7a\x23\xd3\xca\x30\x8e\xc6\x22\x15\x2b\x91\x95\xc5\x98\x20\ +\x32\x36\x3b\xf3\xa8\x33\x8f\xd4\xe8\xc9\xbd\x88\xf2\xd5\x2a\xcf\ +\x8a\xca\x33\x2b\xde\x69\xc6\x32\x9e\xb7\xd6\x6a\x36\x5b\x56\x19\ +\x91\x20\x08\xc6\x98\x8e\x29\xb5\xc0\xc2\x2a\xf6\x59\xc9\x77\xd6\ +\xb1\x2b\xcc\xb1\xcf\x95\x62\x8c\xc7\xa0\xeb\x2c\x5f\x66\x15\xee\ +\x52\x48\xc5\xd9\xc9\x54\x5a\x7d\x74\x48\xff\x1a\xfe\xb5\x0e\x8d\ +\x00\x15\xf9\x46\x46\x62\x0e\x9e\x02\x65\xa2\x1c\xbf\xff\xf8\xbe\ +\x55\x5a\x18\xc5\x65\xac\x75\xd3\x64\xff\x68\xdc\xa3\x25\xc9\xf8\ +\x4a\x14\x6b\x1e\x89\x62\xdc\xc8\x2b\xff\x6d\x12\x97\xcb\xa9\xe9\ +\xda\xeb\x5d\xd5\x5e\x8a\x64\xb1\x2c\x35\x41\x12\x4f\x4d\x88\x90\ +\x7a\xd4\xad\xda\xcd\x1c\xc2\x16\x49\x18\x31\x7a\x30\xad\x3b\xd6\ +\x55\xb6\x8f\x88\x21\x03\xcf\xc5\xc7\xde\x71\x1e\xa9\x29\x4d\xcd\ +\x0f\x19\x5f\x7f\xfe\x29\x5b\xa4\x02\x35\x89\x6c\xfb\xc9\x37\xe5\ +\x7a\x53\x7e\x16\xbb\x52\x64\x87\x0e\x21\x14\x2d\xae\x4a\xad\xdc\ +\xd0\x51\x4c\x1a\xc6\x89\x79\x0b\x92\x49\x2c\xe6\x85\xd2\x1c\xc2\ +\x51\x2d\x88\xc7\xaf\x74\xa0\x85\x35\x11\x5c\xfe\x22\x79\x9c\x00\ +\x12\x0f\x76\xda\x2c\xa2\x3c\x4d\x45\x04\x39\xe1\xe9\x96\xef\x0b\ +\xb3\x35\x80\xae\x8e\x5d\x19\xb1\xed\xba\x53\xe8\xb6\x28\xf3\x75\ +\x63\x0b\x91\x97\xfb\x14\xc2\x55\x42\x0b\x7a\xcc\x65\xf8\x6e\x5e\ +\x7d\x6e\x2a\x51\x0e\x6b\x93\x94\xfb\x90\xdc\x98\x9d\x4f\x3e\x9f\ +\x17\x02\x06\xc6\x9a\xac\x5a\x0f\xf0\x80\xb1\x5c\xd3\x18\x7f\xdd\ +\x68\xb8\x6f\x34\xd2\x3f\x9a\xdf\x8e\x36\x19\x1f\x87\x5d\x4b\xdb\ +\x84\xad\x21\xff\x6b\xc8\x18\x50\xb6\xe9\xa9\x5d\xf7\x72\xaf\x50\ +\x7a\x6c\xca\x62\xf3\x24\xe9\xf7\xeb\xcf\x3b\x08\xdc\x08\x0d\x46\ +\xe1\x3f\xd2\x6b\xb1\x3f\x58\x10\x60\x21\x7c\xe1\x5e\x9b\x07\x85\ +\xe5\x27\xba\xa9\x67\x60\xe5\x32\x59\x24\x80\x99\xca\x8e\x12\xc4\ +\xaa\xcf\xb1\x0f\x24\x43\x8b\x8d\x7a\xcc\xee\x72\xa2\x72\xc1\xd3\ +\x2f\x06\x51\x55\x10\xc2\xa5\x14\x50\xc0\xde\xf5\xa0\x49\x1f\xfb\ +\x78\x08\xe6\x3b\x5d\xc4\x8b\x5a\xf8\x29\x4b\x4a\xa8\x54\x9b\x42\ +\xc8\x0f\x8a\xed\xff\xcd\x3e\x15\xe2\xc4\xea\xa3\xe4\x59\x01\xa5\ +\x65\x35\x35\x57\xbc\x94\xc9\xee\x07\x32\xc2\xea\x0f\xb9\x81\xef\ +\xd0\xc0\x86\x6b\x8a\x29\xf2\xa9\xef\xb2\xeb\xd6\x3d\x82\x15\xa1\ +\xd4\x41\xd4\xb5\x31\xed\xa4\xb0\x0a\xae\x47\x91\x17\x78\xcc\x6d\ +\xa5\xf3\x5e\xdb\x79\xaf\xad\x84\xac\xdb\x88\xd9\x0e\xf1\xfd\x6f\ +\x9d\x50\xcb\x7b\x26\xa5\x16\xfd\x9e\x93\xfa\xa6\xa5\x0e\x72\x39\ +\x60\xb1\xb3\xec\x61\xcb\x9d\x36\xde\x99\x82\xf7\x8d\x10\xea\x3c\ +\x87\x50\xef\x82\xd0\x97\x22\xd4\x19\x14\xa1\x03\xdf\x90\x21\xba\ +\x57\x21\xf4\x28\xf1\x4f\xaf\x51\xff\x7a\xf6\xaf\x7d\x3f\x4e\xbe\ +\x12\x7c\x2f\x43\xf8\x29\x51\x6c\x07\x93\xd7\x30\xee\x1c\xce\xbe\ +\xf5\x6d\x89\x3d\x4b\xfa\xef\xfa\x66\xff\xb6\xac\x67\x83\xb2\x9e\ +\x0e\xcc\x7a\x76\x61\x7d\x97\x95\x53\xd6\x5b\xfe\x6b\x48\xf7\x77\ +\xf1\x9e\x3c\xc7\x7b\xe7\x42\xfb\x97\xd2\x9e\x0c\x4a\x7b\x67\x60\ +\xda\x93\x0b\xed\xbb\xac\xf4\xd0\xfe\xe5\xb7\xfb\x9e\x5d\x80\xa1\ +\x69\x1f\x3c\x47\x7b\x76\xa1\xfd\x4b\x69\x1f\x0c\x4a\xfb\x60\x68\ +\xda\xd3\x0b\xef\xbb\xb4\x3c\xe6\xbd\xcf\x5e\x43\xb9\x57\xb2\xfe\ +\x9f\x91\x52\x55\x4a\x2d\xf7\xe5\xc5\xf4\x8b\x9e\xa2\xde\xf8\x86\ +\x3f\xf0\x93\xbe\x33\xf8\x1e\x14\xb1\x2e\xf4\x7f\x1a\xab\xbe\x85\ +\x5f\x8c\x55\xf6\x45\x6f\xfa\x6f\xfc\x4e\x3a\xf0\x5e\x14\x1d\xfc\ +\x4e\xc5\x5e\xbb\x63\xfa\x8f\xc1\xaa\xfd\x62\xa4\x3a\x5f\x74\xbb\ +\x7a\xe3\x3d\xd3\x81\x9f\xa8\x5c\xed\xd5\x66\xa0\x7d\x53\x8d\x1b\ +\xc3\xee\xed\xb3\xe7\x7e\xd1\xd3\xd6\xfd\xf2\xe0\xff\x5c\x49\x1d\ +\xf4\xc7\xf6\xc1\x51\xfa\xf4\x9d\x7f\x32\x56\xc7\x18\xaa\xab\xf6\ +\xc7\x75\x75\xa2\x22\xbe\x4f\xc4\xf6\xaa\xed\x6d\xc6\x5b\xac\xac\ +\xf9\x42\x54\x93\x03\x68\x1e\x66\x57\x2b\x66\xb9\x8c\x85\x6c\x54\ +\x6e\xf5\x39\x52\xd5\xf3\x3f\x1c\x1a\xba\x3a\x5e\x33\xd5\x6b\xab\ +\xc7\xfd\xfa\x62\xc9\xe3\x7c\x0b\xe0\x79\xac\x7c\xc8\x73\xc0\x2b\ +\x43\xbe\x1f\x60\xdf\x63\x8f\xd5\x15\x38\x5d\xe4\x61\x1a\x90\x13\ +\x5f\x85\x51\x86\x01\x8c\x6e\xe0\x9d\xe8\x36\x52\x42\x9e\xac\x94\ +\xef\x05\xc4\xb4\xb0\xa9\xdf\xf0\xaa\x58\xe6\xdb\x85\x54\xa9\x29\ +\xe5\x46\x3c\x76\x8c\xf3\x68\xa3\x8e\x23\x59\x9b\x03\xe9\xea\x43\ +\x30\x9a\x85\xf2\xb5\x66\xb3\x7c\xd7\xdf\xc1\x36\xc9\x20\x54\xab\ +\x3e\x56\x43\xa8\x7f\x92\x90\xda\xa2\x39\x68\xe3\x39\xce\x19\x8b\ +\x5d\x87\xc5\xc7\xaa\xbd\x22\xe2\x19\xdd\x8a\xef\x92\x55\xf2\x20\ +\x62\x05\xad\x03\x82\x26\x2b\x51\xf2\x98\x97\xbc\xc3\x45\x23\xa1\ +\x1e\x6b\xb6\xcd\x26\x32\x9e\x87\xbf\xbf\xff\xb9\xc5\x78\x14\x85\ +\x7f\xe4\xf2\xae\x83\xa7\x32\xe0\xb3\x7c\x03\xd3\x6e\x99\xa7\x4e\ +\xd7\x44\xa1\x2a\x3c\xbc\xbc\x4d\x56\xb0\xda\xea\x40\xd4\xbf\x77\ +\xab\x14\x10\xda\x2a\x8e\x8c\xd5\x19\x90\xae\xd3\x43\xb7\x52\x1c\ +\x0e\x3c\xf5\x9e\x11\x8b\xa3\x55\xa2\x9c\xc6\x1f\xca\x24\x4d\x7f\ +\x55\x83\x68\x5c\xac\x3b\x4d\xca\x54\x68\x04\x1d\xd7\xb3\x6f\x18\ +\xa4\x05\x37\x19\x37\xd1\x57\xad\x45\x97\x95\x0a\x2f\xe4\x71\x62\ +\x53\x3e\x13\xe9\xd4\xfc\x4d\x29\x8d\x13\xed\x42\xe6\x9b\xf5\x2a\ +\x8f\x45\xed\xde\x64\x73\xa1\x57\x2f\x1d\x81\x86\x51\x9e\xd4\x6a\ +\x8c\x88\x4b\x01\x2d\xb4\xae\xd9\x4d\xcb\x45\xcc\xc5\x4e\xe0\xbb\ +\x23\xcb\x75\x11\xc1\xbe\x8f\xdd\xeb\xae\xea\xad\x79\xb9\xd4\xaa\ +\xd0\xf1\x21\x1b\x2e\x23\xad\xb4\xd4\x25\xaa\x2b\x7d\x75\x9d\xc2\ +\xd5\xe7\x66\x0e\x89\x0d\xb3\x3c\x13\xd5\x95\x56\x21\xab\xa6\xdc\ +\xa4\x42\x69\x1f\xa0\x16\x40\x49\x93\xf9\x9d\x50\x9e\x54\x50\x51\ +\x37\x0f\x88\x0f\x9d\xa6\xa9\x0a\x16\xa4\x27\x9c\x6d\xca\x52\x97\ +\xfd\x99\x27\x59\x08\x19\xcb\xe2\x46\x0a\x4b\x2b\x64\x0a\x90\x2d\ +\x43\xbb\x91\x75\xc3\xd7\x82\x98\x43\x0d\x91\x92\xef\x0f\x73\xd4\ +\xa4\x87\x32\x0a\xa5\x75\xc5\xe5\x9d\x90\x07\xfd\x7d\x52\x24\xb3\ +\x24\x55\x5d\x54\x97\xa9\xb8\x89\x93\x62\x0d\xeb\x13\x26\x99\x9a\ +\xc6\x4d\x7e\x2f\xe4\x3c\xcd\xb7\xad\x5e\x64\x1c\xbe\xac\x19\x8f\ +\xee\x16\xd5\xfc\x42\x1e\x41\x2d\xd8\xa4\xbc\x14\x8f\x2a\xb4\xca\ +\xba\xcd\x08\x33\x7b\x52\xaf\x4a\x16\x23\x50\xd0\x6c\x28\x68\xbd\ +\x06\xfb\x83\x81\xe3\x7b\x3e\xed\x33\x90\xd0\x03\x09\x10\xa6\x9e\ +\x8b\x49\xaf\xc1\xbe\xdf\x40\xb1\xda\x70\x30\x0a\x08\x71\x7d\x7f\ +\xd4\x0e\x62\x70\xa3\x35\x1f\xb5\x57\x06\x36\x08\xfc\x59\xcc\x47\ +\xd8\x71\x28\x66\x23\xfc\x84\x99\x6e\xf5\xa0\x8d\x79\x8a\x64\x40\ +\xa9\xeb\x05\x8e\x6f\x57\x48\xee\x5a\x16\x0b\x10\x65\x04\xea\xfc\ +\xc8\xc6\x1e\xf2\x1c\x97\x79\xd7\xfa\x1d\xf5\x18\xcb\x55\x30\xd4\ +\x76\x90\x47\x80\x3a\x23\xd7\x81\xc7\x0e\x12\x30\x88\xc5\xf6\x91\ +\x03\x42\x36\x6a\x2e\x9a\x48\x02\x0f\x29\x5b\x17\xa6\x78\xce\x46\ +\x33\x79\x38\x97\xda\xc6\xe5\xdc\xda\x3c\xa5\xaf\x9e\x9b\xea\xa9\ +\x9e\x43\x07\xa9\x27\xe1\xf4\xa0\x8a\x01\xef\xb5\xbd\x97\x96\xb5\ +\x3d\x5c\x85\xc6\x0c\x22\xf9\x3a\xba\x52\x06\xeb\x03\x48\x66\x2e\ +\xfd\xde\x89\xfb\x64\x71\x3c\x85\xb1\x05\x8f\x3a\xc4\xa1\x3e\x01\ +\xac\x20\x8a\x6d\x87\xda\x9e\x33\xb2\xd4\x35\x61\x98\xe1\x60\xa4\ +\x2c\x18\x71\x18\xa6\x23\xe6\xda\x28\x70\x1c\x07\x78\x43\x81\x29\ +\x2e\x75\xec\x0b\xb4\x7b\xa1\x6d\xd1\x0b\xb8\xff\xe7\xc1\x4d\x74\ +\x6c\xbb\x84\x20\xd7\x63\x01\xbd\x60\xfb\x39\x6c\x7b\x17\x6c\xff\ +\xfd\xd8\xd6\x00\xdd\xa1\x5c\xc3\x73\x07\x72\x2f\x80\x27\x24\x12\ +\xd8\xee\x88\x05\x36\x62\x1e\x73\xd8\x05\xd9\xfd\xc8\xa6\x16\xbb\ +\x60\xfb\xff\x13\xdb\xc4\xf6\x10\x20\x00\x07\xd7\xda\x76\xd2\xe2\ +\xf0\x1a\x0c\x5f\x13\xf5\xb6\x7e\x7b\xf5\x17\x93\x56\xec\x3d\ \x00\x00\x0f\xd2\ \x00\ \x00\x52\x9a\x78\x9c\xe5\x5c\x5b\x6f\xe3\xb8\x15\x7e\x9f\x5f\xa1\ @@ -31640,147 +31329,112 @@ qt_resource_data = "\ \x74\x68\x69\x63\x20\x42\x6f\x6c\x64\x2c\x20\x42\x6f\x6c\x64\x27\ \x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\ \x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ -\x00\x00\x08\xa3\ +\x00\x00\x06\x71\ \x00\ -\x00\x2b\x7a\x78\x9c\xed\x5a\x5b\x6f\xdb\x38\x16\x7e\xcf\xaf\xd0\ -\xba\x2f\x0d\xd6\xa2\xc4\x3b\xe9\x26\x19\x2c\xb6\x98\xc5\x00\x03\ -\x2c\xb0\x6d\xb1\x8f\x85\x2c\xd1\x8e\x36\xb2\x64\x48\x72\x6c\xe7\ -\xd7\xef\xa1\x6e\x96\x22\xa5\xc9\xa6\x53\x0f\xd0\x8d\x8b\xd6\xd2\ -\xb9\x92\x87\xdf\x39\x87\x34\x7b\xf5\xcb\x61\x93\x38\xf7\x26\x2f\ -\xe2\x2c\xbd\x9e\x61\xe4\xcf\x1c\x93\x86\x59\x14\xa7\xeb\xeb\xd9\ -\x97\xcf\xbf\xba\x6a\xe6\x14\x65\x90\x46\x41\x92\xa5\xe6\x7a\x96\ -\x66\xb3\x5f\x6e\x2e\xae\xfe\xe2\xba\xce\xdf\x73\x13\x94\x26\x72\ -\xf6\x71\x79\xeb\xfc\x96\xde\x15\x61\xb0\x35\xce\xfb\xdb\xb2\xdc\ -\x2e\x3c\x6f\xbf\xdf\xa3\xb8\x21\xa2\x2c\x5f\x7b\x97\x8e\xeb\xde\ -\x5c\x5c\x5c\x15\xf7\xeb\x0b\xc7\x71\xc0\x6f\x5a\x2c\xa2\xf0\x7a\ -\xd6\x28\x6c\x77\x79\x52\x09\x46\xa1\x67\x12\xb3\x31\x69\x59\x78\ -\x18\x61\x6f\x76\x12\x0f\x4f\xe2\xa1\xf5\x1e\xdf\x9b\x30\xdb\x6c\ -\xb2\xb4\xa8\x34\xd3\xe2\x5d\x4f\x38\x8f\x56\x9d\xb4\x1d\xcd\x9e\ -\x56\x42\x58\x6b\xed\xf9\xc4\x23\xc4\x05\x09\xb7\x38\xa6\x65\x70\ -\x70\x87\xaa\x30\xc6\x29\x55\xe2\xfb\xbe\x07\xbc\x93\xe4\xcb\xa4\ -\x16\x87\x04\x42\xf1\xe4\x60\x2a\x6e\xdf\x3b\x84\x7f\x0b\x7f\x3b\ -\x85\x96\x80\x8a\x6c\x97\x87\x66\x05\x9a\x06\xa5\xa6\xf4\x3e\x7e\ -\xfe\xd8\x31\x5d\x1f\x45\x65\xd4\x33\xd3\x46\x7f\xe0\x77\xb0\x24\ -\x69\xb0\x31\xc5\x36\x08\x4d\xe1\xb5\xf4\x4a\x7f\x1f\x47\xe5\xed\ -\xf5\x4c\xb0\xed\xa1\x7a\xbf\x35\xf1\xfa\xb6\xec\x11\xe2\xe8\x7a\ -\x06\x33\x24\x92\x88\xea\xbd\x1d\xc3\xa2\x43\x92\x8f\x28\xa9\x45\ -\x1b\xc3\x7d\x16\x53\x08\x3b\xb9\x96\xc2\x1f\x6a\x47\x59\x68\x87\ -\x74\x3d\xfb\x94\x06\xdb\xaf\x7f\x4b\xd7\x89\x41\x6d\x20\x3b\x3b\ -\xd9\xae\xdc\xee\xca\xaf\xe6\x50\x9a\xb4\x36\x08\x53\xe9\xcd\xab\ -\x62\x5b\x35\x34\x98\x53\x0f\xe3\x78\x76\x03\x94\xab\xc8\xac\x0a\ -\xcb\xa9\xa7\x63\xdf\x60\x3e\xaa\xe2\x01\x17\xd6\xc4\x04\xf9\x3f\ -\xf2\x20\x8a\x01\x89\xb5\x5c\x6f\x14\x61\x96\x24\x26\x84\x98\x04\ -\xc9\x3e\x38\x16\xb3\x4e\x00\x4c\x0d\x55\x29\x66\xac\x31\x0a\x66\ -\x8b\x32\xdb\xb6\xb2\x30\xf3\xf2\x98\xc0\x74\x2d\xd1\x05\x8b\x59\ -\xbe\x78\xb7\xaa\x3e\x1f\x2a\x52\x06\x6b\x13\x97\xc7\x05\xfe\x30\ -\x3b\xe9\x64\xab\x55\x61\xc0\xb1\xdf\xa3\x55\xeb\x01\x1a\xe0\x4b\ -\xcc\x1c\xef\xfb\xbc\xf9\x53\xde\xf0\xb4\x37\xd5\x79\xbb\xf2\x86\ -\xd3\x6e\xa8\x5d\xc0\xb6\x10\xff\x2d\x44\x0c\x52\xb6\xb5\xd4\xad\ -\x7b\x79\xb4\x28\x1d\x8a\xd2\x68\x36\x0a\xfa\xfd\xf6\xeb\x01\x26\ -\xee\x2c\x1c\x4a\xe0\x1f\x3c\x29\x71\xac\x25\x30\x64\x21\x7c\xf9\ -\x93\x32\x0f\x16\xcb\xdf\x30\xd3\x8c\xc0\xcd\xf2\x78\x1d\x03\x66\ -\x2a\x39\x82\x11\xad\x3e\x43\x1d\x08\x46\x6f\x6e\x44\x52\x76\x8a\ -\x89\x8d\x45\x90\xfc\xcf\x20\xaa\x0a\xc2\xe2\x36\x37\x50\xc0\xde\ -\x4d\xa0\xa9\xef\x7b\xe8\x82\x2a\x7e\x9a\xf1\xba\x21\x7e\x49\xe3\ -\x12\x2a\xd5\xae\x30\xf9\x27\x9b\xed\xff\x4c\xbf\x14\x66\x24\xf5\ -\x39\x0f\xd2\x02\x4a\xcb\xe6\x7a\xb6\x09\xca\x3c\x3e\xbc\xc7\x73\ -\xdf\xfe\x41\x42\x2b\x4e\x34\x83\x67\xe2\x13\xa4\x88\x12\xf4\xb2\ -\x53\x0f\x61\x45\x08\xe1\x88\x08\xe6\x93\x13\x15\x56\x41\x48\x82\ -\xa4\x96\x54\x74\xd4\xd5\xa4\xec\x6a\x52\x36\x87\xa8\x33\x44\x19\ -\xc7\x4a\xfd\xe8\x80\xba\xf2\x99\x90\xba\xe4\x67\x0e\xea\x1f\x5a\ -\xea\x20\x96\x67\x2c\x76\x2e\x3b\x6f\xb9\xeb\xf9\x7b\xa2\xe0\xfd\ -\x20\x84\xf2\xe7\x10\x2a\xdf\x10\xfa\x52\x84\xf2\xb3\x22\xf4\xcc\ -\x0d\x19\x66\xf7\x2a\x84\x0e\x02\xff\xed\x35\x9a\x5e\xcf\xe9\xb5\ -\x9f\xc6\xc9\x77\x82\xef\x65\x08\x1f\x27\x0a\xe3\x3e\x7e\x4d\xc6\ -\x3d\x85\xb3\x1f\xdd\x96\xe8\xb3\x49\xff\x53\x37\xfb\x3f\x36\xeb\ -\xe9\x59\xb3\x9e\x9c\x39\xeb\xe9\x5b\xd6\x9f\xa2\x32\xce\x7a\x57\ -\xbd\x26\xe9\xfe\xac\xbc\xc7\xcf\xe5\x3d\x7f\x4b\xfb\x97\xa6\x3d\ -\x3e\x6b\xda\xf3\x33\xa7\x3d\x7e\x4b\xfb\x53\x54\x26\xd2\xfe\xe5\ -\xed\x7e\xe2\x57\x80\x73\xa7\xbd\x7e\x2e\xed\xe9\x5b\xda\xbf\x34\ -\xed\xf5\x59\xd3\x5e\x9f\x3b\xed\xc9\x9f\x74\x0c\x25\xcf\x41\x54\ -\xbc\x41\xf4\xa5\x10\x25\x67\x85\xa8\x7f\x66\x88\xbe\x12\xa1\xff\ -\x17\x9d\x49\x61\xfe\x9a\x8c\xfb\x76\x5f\xba\xf2\xec\x15\x46\xf5\ -\xd4\xfd\xb0\x6e\x6f\x53\xa2\xfb\xd8\xec\x2f\xba\xa1\x2c\x83\x6e\ -\x6c\xdb\x60\x6d\xaa\xf5\x06\xcf\xf5\x82\x37\x8c\x65\x96\x47\x26\ -\x6f\x59\xa2\xfa\x0c\x58\x0d\x24\xea\x0b\xc3\x8b\xe1\xe8\xac\xd5\ -\x8e\xef\x4f\xf3\x8b\xdb\x20\xca\xf6\xb0\x24\x8f\x99\x0f\x59\x06\ -\x8b\x40\x91\x52\xda\x57\x92\x3e\x66\x57\xcb\xa8\x10\xc6\x12\x13\ -\x31\x62\x82\x3f\x4e\x91\x10\x5c\xca\x31\x73\x97\xe7\x10\x52\x37\ -\x09\x8e\x06\x26\xb5\x66\x44\xb5\xed\xb6\xb8\xcd\xf6\xeb\xdc\xc6\ -\xa6\xcc\x77\xe6\xb1\x62\x94\x85\x3b\x7b\x17\xe9\xee\xea\x55\x6e\ -\x6e\xc0\x7a\x12\x56\xd7\x5d\x2e\xb3\xc3\xb4\x81\x7d\x9c\xc2\x5c\ -\xdd\xe6\x4e\x0d\x13\x35\x8a\x48\x23\xd1\xde\xb2\x49\xce\x9f\x90\ -\x38\x9c\xf2\xfb\x31\xeb\x68\xf1\xfd\x04\x6f\x13\x1c\xe2\x4d\xfc\ -\x60\x22\x9b\xae\x0d\x58\x36\xa6\x0c\xa2\xa0\x0c\x4e\xc0\x68\x29\ -\x44\xd2\x76\xcf\x7c\x95\x47\xab\xc5\xbf\x3e\xfe\xda\xd5\x8d\x30\ -\x5c\xfc\x3b\xcb\xef\x4e\x29\x6f\x05\x82\x65\xb6\x83\x61\x77\xd5\ -\xcc\x5e\xad\x85\x0b\x9b\x4e\x41\x79\x13\x6f\x60\xb9\xed\x6d\xe8\ -\x5f\x0f\x9b\x04\x20\xda\x31\x06\xc2\xf6\x02\xe8\x64\xb4\x36\x9b\ -\x9b\xfa\xb6\x73\xf2\x82\x38\x0a\x37\xb1\x55\xf2\x3e\x95\x71\x92\ -\xfc\x66\x9d\xf4\xea\x5b\x63\x34\x2e\x13\x73\x53\xf9\xac\x1f\xdb\ -\x59\x78\xcd\x34\xda\xf2\xd4\x9b\xe5\x95\xd7\x86\xa1\x7a\x5b\x9f\ -\xc2\x53\x01\x07\x3f\x8e\x70\x12\x2c\x4d\x72\x3d\xfb\xdd\x32\x9d\ -\x11\x77\x9d\x67\xbb\xed\x26\x8b\x4c\xa3\xde\x86\x75\xdd\xaf\x0d\ -\x7d\x28\x3a\x4e\x39\x2a\x45\x3e\xc2\x82\x00\x6c\x48\x53\x92\xda\ -\x37\x81\xa8\xf0\xb9\x56\x62\xee\x0a\x81\xb0\xaf\x94\x2f\x2e\x4f\ -\x2d\x65\x1b\x94\xb7\xa3\x12\xdf\x95\x72\xc4\xb9\xaa\xee\xb2\x3e\ -\xac\x20\x7e\x8b\x77\x7e\xf5\xa9\x5e\x7a\xfd\xa5\x7a\xcd\x77\x89\ -\x59\xa4\x59\xfa\x00\x69\x0f\x0d\x21\xcf\xee\x4c\x27\x5f\xbf\xd6\ -\xd8\x5e\x40\x75\xa5\x9a\x0a\x18\x54\x4b\xb7\xe5\x0c\x02\xb1\x58\ -\xee\xca\xb2\x4f\xfb\x4f\x16\xa7\x0b\x58\x40\x93\xb7\xd4\xea\x25\ -\x01\x94\x96\x0b\xd6\xd2\x4e\xe3\x68\x08\x51\x00\x75\x23\xcf\x83\ -\xa3\x1d\x8e\xe9\x53\xeb\x6e\x04\x1d\x6a\x13\xe4\x77\x26\xaf\xf9\ -\xf7\x71\x11\x2f\xe3\xc4\x9a\xa8\x1e\x13\xf3\x21\x8a\x8b\x2d\xac\ -\xc4\x22\x4e\xed\x30\x3e\x64\xf7\x26\x5f\x25\xd9\xbe\xe3\x9b\x34\ -\x80\x2f\x77\x19\x84\x77\x76\xed\xd2\x68\x11\x84\x90\xfe\xbb\x24\ -\x28\x4d\xaf\xd1\xd9\x6c\x71\x88\x56\x48\x60\x81\xe5\x9c\x6b\x86\ -\x60\xef\x23\x84\x13\x3a\x2e\x74\x09\x4d\x28\x9d\xbb\x50\xfa\xb0\ -\xd4\x8e\xcb\x91\xc6\x4a\x42\x0b\x81\xf5\xd2\x9a\x3b\xae\x42\x4a\ -\x08\x66\x09\x5a\x50\x09\x04\x42\x11\x57\x58\xb0\x39\x43\x92\xfb\ -\x8c\x3a\x2e\x55\xd0\xbf\x08\xa6\x73\x22\xc1\x9c\x4f\x05\x90\x18\ -\x94\x3d\xc1\xc9\x9c\x63\xa4\x98\x66\x0e\x43\x42\x72\x31\x07\x65\ -\xcd\xb5\xcf\x1c\x10\x65\x5a\x48\x39\xa7\x1a\x81\x5d\xf0\x04\x92\ -\xbe\x54\x6c\x0e\xaa\x4a\x49\x8e\x9d\xce\x91\xdb\x7a\x02\x47\x5a\ -\x31\xa5\xe6\x2e\x94\x55\x5f\x51\x8c\x1d\xdb\x7e\x7d\x4d\xe4\xdc\ -\xe5\x04\xf9\x8c\x60\x18\x21\x43\xbe\xc6\x98\x83\x94\x1d\x34\xb3\ -\x24\x42\x10\x06\x0c\x81\x26\xe5\x88\x53\xa2\xac\x18\x41\xcc\x67\ -\x12\x57\x34\xc1\x15\xb8\x7c\x70\x36\x30\x76\x10\x26\x92\x2b\x30\ -\x6a\x7b\x30\xf7\x7d\xe5\xf8\x73\xa6\xc1\x02\x78\x72\xb0\x22\x60\ -\x81\x42\xb8\xe6\x3e\xd0\xdd\x8e\xe1\x0e\x38\x0f\x8f\xb6\x1a\x16\ -\xe1\x14\xb2\xa1\x77\x6e\x1a\x34\xc9\x14\xc0\x57\x66\xb9\x0b\xa5\ -\xff\x3e\x28\x77\xb9\xb1\xd5\xb3\xb7\x09\x5a\x4f\x68\x99\xc3\x36\ -\xcb\x4b\xf7\x18\x6d\x63\x28\xc4\x10\x3e\x82\x35\xc7\x53\xf6\x1b\ -\xc9\xc3\x8b\x25\x21\x99\x4c\xfd\xbf\x1b\xbc\xdb\x6c\x63\xbc\x63\ -\x96\xc7\x77\xde\xc7\xa6\xbd\x14\xde\xef\xc1\xd2\xfb\x98\x07\xab\ -\xd2\x8b\x61\xec\x45\xb5\x69\x42\xdb\x74\xdd\x33\x39\x2e\x0e\x80\ -\x32\x25\xa1\x55\x52\x22\x6c\x69\x90\xd2\x96\x01\x6d\xc1\x87\x25\ -\x03\x84\x0a\x6c\x9f\x95\xa6\x98\x13\xa0\x73\x05\xa1\x15\x1c\xe3\ -\x39\xac\xa6\x44\x52\x71\x76\xf9\x28\xaa\x6b\x08\xa9\xdf\xaf\xe5\ -\xc3\x42\x32\xba\xb5\x0f\xf2\x70\x36\x60\xd7\x95\xa6\x2d\x2b\x4b\ -\xd8\x32\x7d\x6f\x59\x51\x15\x15\xeb\x9f\xbd\xac\x0c\x61\x3d\x9b\ -\x0c\xba\xdd\x01\x61\x2d\x11\x86\xae\xc1\x9f\x10\xb1\x3b\x60\x0e\ -\x79\x86\x35\x9d\x96\xc8\xc1\x08\x53\x88\x4b\xcc\x9e\x92\x38\x3e\ -\x21\x51\x97\x3e\xc6\x91\xb4\x23\x98\xb7\x7e\xa0\xf2\xc1\x16\x59\ -\xc0\x0e\x99\x13\x28\x56\x04\x23\xc9\x6c\x69\x6c\x6d\x40\x6d\x68\ -\x9e\x7a\xa4\x56\x1e\x72\xfb\xc4\xee\x74\xfb\xb4\x4e\x07\xaa\x43\ -\xe7\xa5\x73\x72\x62\x4f\x68\xf4\x9c\x74\xdc\xce\xc5\x78\x50\x0f\ -\xc3\x6d\xc4\x77\x80\x1f\x76\x2b\xef\xdf\x8d\x4f\xc8\x97\x8f\xb3\ -\xa1\xc1\xbe\xc5\xd6\x53\x58\x60\x4f\x63\x61\x7c\xa8\x19\x63\x61\ -\x74\x1a\x1a\x81\x61\x7c\xe4\x1a\xa1\xc1\xf6\x19\xe8\x01\x64\x0a\ -\x0e\x1c\x3a\x0e\xd4\x6b\x3c\xef\x5c\x55\x78\xc0\x14\x11\xa6\x01\ -\x1c\x2e\xe6\x88\x4a\xa1\xea\x6e\x05\x56\x68\xd5\xcf\xac\x4b\xdd\ -\x23\x61\x68\x46\x02\x4a\x99\xc5\x43\xc7\x76\xb1\x0f\x8b\x85\x49\ -\x9f\xd4\xa9\x00\x1c\x3a\x27\x8d\x0f\xd9\xb1\x89\x33\xd2\xb0\xbd\ -\xa6\xf2\x41\xc1\x47\xc7\xad\x3d\x60\xed\x3c\x1e\x13\x19\xf4\x9c\ -\xe9\xcd\x19\x34\x39\xea\x93\xaa\xdf\x73\xc2\xa0\x25\xdb\xc6\x7e\ -\x7a\xea\xd8\x14\x5a\xad\xd0\x42\x13\x40\x1f\xb4\x72\x0d\x1d\xf3\ -\xb2\xdf\x8d\xbc\x75\xf7\x98\x43\xdf\x1a\x6d\xdd\x9a\x83\x79\x6f\ -\xa3\xd6\x9d\xd2\xbf\xb3\xbc\x72\x49\x18\xa1\x4c\xfc\xec\xe5\xb5\ -\x3a\x88\x43\x68\x99\x94\xfd\x3e\xdd\x1e\xcc\x60\xab\x41\x15\x6c\ -\x5e\x7b\xac\xf6\x44\x66\x37\x24\x82\x69\x2c\x7b\x3c\xc8\x1a\xbb\ -\x1b\x22\xbe\x4f\x71\x5f\xc7\x1e\x42\x95\x82\x7d\x90\x4f\x75\xef\ -\x27\x90\x75\x7d\xba\x80\xaf\x2b\x7b\x1a\xba\xb9\xf8\x2f\x2d\x23\ -\xd5\xbb\ +\x00\x28\x71\x78\x9c\xed\x59\x5b\x6f\xdb\x36\x14\x7e\xcf\xaf\xd0\ +\xd4\x97\x06\xb3\x28\x91\xba\x2b\x76\xf6\xb0\xae\x43\x81\x01\x03\ +\xd6\x16\x7b\x2c\x68\x89\xb6\xb5\xc8\xa2\x40\xd1\xb1\x9d\x5f\xbf\ +\x43\xdd\x1d\x2b\x97\xa5\xad\xbb\x75\x76\x90\x58\x3c\x17\xf2\x5c\ +\xbe\x73\x8e\x63\x4e\x7f\xda\xad\x33\xed\x96\x89\x32\xe5\xf9\x4c\ +\xc7\xc8\xd2\x35\x96\xc7\x3c\x49\xf3\xe5\x4c\xff\xf8\xe1\xad\x11\ +\xe8\x5a\x29\x69\x9e\xd0\x8c\xe7\x6c\xa6\xe7\x5c\xff\xe9\xfa\x62\ +\xfa\x83\x61\x68\x3f\x0b\x46\x25\x4b\xb4\x6d\x2a\x57\xda\xbb\xfc\ +\xa6\x8c\x69\xc1\xb4\xd7\x2b\x29\x8b\xc8\x34\xb7\xdb\x2d\x4a\x1b\ +\x22\xe2\x62\x69\x5e\x6a\x86\x71\x7d\x71\x31\x2d\x6f\x97\x17\x9a\ +\xa6\xc1\xb9\x79\x19\x25\xf1\x4c\x6f\x14\x8a\x8d\xc8\x2a\xc1\x24\ +\x36\x59\xc6\xd6\x2c\x97\xa5\x89\x11\x36\xf5\x5e\x3c\xee\xc5\x63\ +\x75\x7a\x7a\xcb\x62\xbe\x5e\xf3\xbc\xac\x34\xf3\xf2\xd5\x40\x58\ +\x24\x8b\x4e\x5a\x59\xb3\xb5\x2b\x21\x1c\x86\xa1\x69\x11\x93\x10\ +\x03\x24\x8c\x72\x9f\x4b\xba\x33\x0e\x55\xc1\xc6\x31\x55\x62\x59\ +\x96\x09\xbc\x5e\xf2\x79\x52\xd1\x2e\x83\x50\x3c\x68\x4c\xc5\x1d\ +\x9e\x0e\xe1\x2f\xe0\xb7\x53\x68\x09\xa8\xe4\x1b\x11\xb3\x05\x68\ +\x32\x94\x33\x69\xbe\xf9\xf0\xa6\x63\x1a\x16\x4a\x64\x32\xd8\xa6\ +\x8d\xfe\xc1\xb9\x07\x29\xc9\xe9\x9a\x95\x05\x8d\x59\x69\xb6\xf4\ +\x4a\x7f\x9b\x26\x72\x35\xd3\x3d\xa7\xd8\x55\xeb\x15\x4b\x97\x2b\ +\x39\x20\xa4\xc9\x4c\x07\x0f\x89\x4f\xbc\x6a\xdd\xda\x10\x75\x48\ +\xb2\x90\x4d\x6a\xd1\x66\xe3\x21\xcb\x09\x10\xd6\x44\xe8\x7b\xd6\ +\xa1\x76\xc2\x63\x65\xd2\x4c\x7f\x9f\xd3\xe2\xd3\x2f\x3b\xc9\x72\ +\xa5\x82\xda\x60\x76\x7b\xf1\x8d\x2c\x36\xf2\x13\x6b\x25\x66\x3a\ +\xb8\x33\xf0\xad\x62\x2b\x35\x74\xe0\xd7\x00\xe7\x58\xbf\x06\xca\ +\x34\x61\x8b\x52\x71\x6a\x97\xd4\x0a\x7c\x0a\x2a\x1e\x70\x21\x2f\ +\x8c\x8a\x5f\x05\x4d\x52\x40\x63\x2d\x37\xb0\x22\xe6\x59\xc6\x62\ +\x88\x0b\xcd\xb6\x74\x5f\xea\x9d\x00\x6c\x75\xa8\x6a\x63\xc7\x69\ +\x36\x85\x6d\x4b\xc9\x8b\x56\x16\xbc\x97\xfb\x0c\x5c\x56\x44\x03\ +\x76\xe4\x22\x7a\xb5\xa8\x5e\x57\x15\x89\x43\x7e\x52\xb9\x8f\xf0\ +\x95\xde\xeb\xf0\xc5\xa2\x64\x70\xb0\x35\xa0\x55\x39\x01\x0d\x38\ +\xcb\xd3\x35\xf3\xf3\x4e\xb3\xc6\x4e\xc3\xe3\xa7\x05\xdd\x69\x53\ +\xf3\xd0\xed\x86\xda\x05\xac\x80\xf8\x17\x10\x31\x28\xdb\x76\xa7\ +\x2e\xf7\x72\xaf\x90\x7a\x28\x6a\x27\xfa\x51\xd0\x6f\x8b\x4f\x3b\ +\x70\x5c\x8b\x34\x9b\xc0\x1f\x3c\x2a\xb1\xaf\x25\x30\x54\x22\xbc\ +\x59\xa3\x32\x77\x0a\xcf\x8f\x6c\xd3\x58\x60\x70\x91\x2e\x53\xc0\ +\x4c\x25\x47\x30\xb2\xab\xd7\xa1\x0e\x04\x63\xe0\x1b\xf1\x6d\xa7\ +\x8f\x89\x8a\x05\xcd\xfe\x31\x88\xaa\xa6\x10\xad\x04\x83\x26\xf6\ +\x6a\x04\x4d\xc3\xb3\x0f\x8f\xb0\x03\xb7\xf7\x78\xd9\x10\x3f\xe6\ +\xa9\x84\x6e\xb5\x29\x99\x78\xaf\x2a\xfe\xf7\xfc\x63\xc9\x8e\xa4\ +\x3e\x08\x9a\x97\xd0\x5e\xd6\x33\x7d\x4d\xa5\x48\x77\xaf\xf1\xc4\ +\x52\x3f\xc8\x0b\x03\x97\x84\x0e\x3c\x13\x8b\xa0\x80\x04\x9e\x7d\ +\xd9\xa9\xc7\x90\x11\x42\x5c\x44\x3c\xc7\x22\x3d\x15\xb2\xe0\xf9\ +\x04\xf9\xa1\x6f\x7b\x1d\x75\x31\x2a\xbb\x18\x95\x15\x10\x75\x07\ +\xd9\x8e\x8b\x83\xe0\x6b\x07\xd4\xf0\x9f\x08\xa9\x41\xbe\xe7\xa0\ +\x7e\xd1\x56\x07\xb1\x3c\x61\xb3\x33\x9c\xd3\xb6\xbb\xc1\x79\x0f\ +\x34\xbc\xaf\x84\x50\xf7\x29\x84\xfa\x67\x84\x3e\x17\xa1\xee\x49\ +\x11\x7a\xe2\x81\x0c\xde\xbd\x08\xa1\x07\x81\x7f\x3c\x47\xe3\xf9\ +\x1c\xcf\xfd\x38\x4e\x3e\x13\x7c\xcf\x43\xf8\x71\xa1\x38\xae\x85\ +\x5f\x52\x71\x0f\xe1\xec\x6b\x8f\x25\xfb\xc9\xa2\xff\xae\x87\xfd\ +\x97\xad\x7a\xfb\xa4\x55\x4f\x4e\x5c\xf5\xf6\xb9\xea\xfb\xa8\x1c\ +\x57\xbd\x11\xbc\xa4\xe8\xbe\x55\xdd\xe3\xa7\xea\xde\x3d\x97\xfd\ +\x73\xcb\x1e\x9f\xb4\xec\xdd\x13\x97\x3d\x3e\x97\x7d\x1f\x95\x91\ +\xb2\x7f\xfe\xb8\x1f\xf9\x16\xe0\xd4\x65\x1f\x3e\x55\xf6\xf6\xb9\ +\xec\x9f\x5b\xf6\xe1\x49\xcb\x3e\x3c\x75\xd9\x93\x6f\xf4\x6f\x28\ +\x79\x0a\xa2\xde\x19\xa2\xcf\x85\x28\x39\x29\x44\xad\x13\x43\xf4\ +\x85\x08\xfd\x5f\x4c\xa6\x00\xbb\x2f\xa9\xb8\xc7\xe7\xd2\xd4\x54\ +\x57\x18\xd5\x53\xf7\xc5\xba\xba\x51\x49\x6e\x53\xb6\xbd\xe8\x4c\ +\x99\xd3\xce\xb6\x82\x2e\x59\x95\x6f\x38\xb9\x4e\x78\xc3\x98\x73\ +\x91\x30\xd1\xb2\xbc\xea\x75\xc0\x6a\x20\x51\x5f\x1a\x5e\x1c\x5a\ +\xa7\x76\xed\xf8\xd6\x38\xbf\x5c\xd1\x84\x6f\x21\x25\xf7\x99\x77\ +\x9c\x43\x12\x5c\xe4\xde\x67\x54\x09\x0c\x90\x6b\x11\xdb\x0d\x8f\ +\x98\x70\x12\xf1\x91\x4d\x1c\x72\xb4\x63\xbc\x11\x02\x62\x69\x64\ +\x74\xcf\xc0\x9b\xa5\x43\x82\x56\xbf\x5c\xf1\xed\x52\xa8\xa0\x48\ +\xb1\x61\xf7\x15\x13\x1e\x6f\xd4\x45\xa4\xb1\xa9\xd3\xdb\x5c\x7f\ +\x0d\x24\x94\xae\x31\x9f\xf3\xdd\xf8\x06\xdb\x34\x07\x27\x8d\xe6\ +\x42\x0d\x93\xe0\x28\x14\x8d\x44\x7b\xc5\xe6\xbb\x47\x6e\x37\x12\ +\xbb\xbe\xb0\xef\xb3\x94\xeb\x47\x4e\x37\xbc\x35\xdd\xa5\xeb\xf4\ +\x8e\x25\xaa\x4e\x1b\x94\xac\x99\xa4\x09\x95\xb4\x47\x44\x4b\x21\ +\xbe\xdd\x7e\x58\x9e\x8a\x64\x11\xfd\xf1\xe6\x6d\xd7\x30\xe2\x38\ +\xfa\x93\x8b\x9b\xbe\xd6\x95\x00\x9d\xf3\x0d\x98\xdd\xb5\x31\x75\ +\xa7\x16\x47\xaa\x8e\xa8\xbc\x4e\xd7\x90\x67\x75\x15\xfa\xe3\x6e\ +\x9d\x01\x36\x3b\xc6\x81\xb0\xba\xf9\xe9\x37\xad\xb7\x15\xac\xbe\ +\xea\x1c\xbd\x1d\x4e\xe2\x75\xaa\x94\xcc\xf7\x32\xcd\xb2\x77\xea\ +\x90\x41\x63\x6b\x36\x4d\x65\xc6\x06\xdd\xce\x6c\xac\x6f\xdb\xd1\ +\xc0\xb9\xa9\xd9\x7a\x5f\xad\x96\x7d\x54\x2a\xbc\xe0\xfb\x81\xcd\ +\xe8\x9c\x65\x33\xfd\x37\xc5\xd4\x8e\xb8\x4b\xc1\x37\xc5\x9a\x27\ +\xac\x51\x6f\xa3\xb9\x1c\xf6\x82\x21\x02\x35\x4d\x1e\xb5\x1e\x0b\ +\x61\x8f\x00\x5a\x48\xd3\x82\xda\x95\x87\x6c\xcf\x72\xc3\xc0\x9b\ +\x18\x9e\x87\xb0\x15\x04\x96\x77\xd9\x8f\x90\x82\xca\x55\x1f\x49\ +\x95\x56\x8d\x38\x2e\xf2\x31\x1c\x37\xf1\x5c\x68\x7d\x38\xb4\x35\ +\xaa\x39\x50\x44\x40\xb4\x27\xed\x83\x66\x69\x18\x7e\x8c\xd0\x47\ +\x4a\xd6\x9b\x58\x0f\xca\x0c\x44\xee\x06\x7d\xbf\x6b\x37\x02\xc0\ +\xd8\xaa\x8c\xf2\x77\x8f\xf3\xab\xde\xdd\x98\x3a\xca\x07\x7d\xdc\ +\x18\xe1\x0e\x04\xaa\x3b\x38\xf0\xdf\x86\x58\x0d\xf5\xea\xb9\xd6\ +\x8c\x34\xab\x7a\x5d\x2d\x00\x36\x6a\x31\x07\x3f\xaa\xc5\x60\x9e\ +\x56\x4b\xb1\xc9\x58\x94\xf3\xfc\x0e\xda\x1c\x0c\x40\xc1\x6f\x98\ +\x92\x27\x8c\xb0\x66\x59\x97\x74\x44\x6c\x04\x43\x2a\x24\x9e\xdf\ +\xd2\x55\xfb\x06\x20\x44\xf3\x8d\x94\x43\xda\x5f\x3c\xcd\x23\xc0\ +\x46\x9e\xb4\x54\x00\x31\x13\x19\x14\xa7\x8c\x9c\x96\xd6\xdb\xd1\ +\x10\x12\x0a\x7d\x52\x08\xba\x57\xe6\xb0\x21\xb5\x9e\xbe\x30\x91\ +\xd7\x54\xdc\x30\x51\xf3\x6f\xd3\x32\x9d\xa7\x99\xda\xa2\x7a\xcc\ +\xd8\x55\x92\x96\x05\x20\x31\x4a\x73\x65\xc6\x15\xbf\x65\x62\x91\ +\xf1\x6d\xc7\x67\x39\x85\x37\x63\x4e\xe3\x9b\x65\x65\x5f\x44\x63\ +\xe8\x7a\x9b\x8c\x4a\x36\x96\x80\xfa\xa2\x96\x8a\x78\xc0\x3c\x46\ +\xb0\x61\x21\x1f\xe2\x42\x7c\xec\x4f\xe0\xd9\xf1\x89\xe5\xc0\x30\ +\x9e\xa8\xcb\x7f\x3b\xf0\x42\xe2\x2a\x32\x0c\xe8\xd0\x0f\x5c\x3c\ +\xc1\x36\x86\x81\x1f\xd8\x13\x4c\x88\x9a\xdb\xa1\x7f\x39\xfc\xac\ +\x72\x06\x76\x0d\x6c\xc3\x3e\x43\xfb\x5f\x04\x6d\x77\x00\x6d\xb7\ +\x87\xb6\x3f\x80\xf6\xc4\x20\xc8\xc3\x24\xc4\x5e\xa8\xb0\x6d\xa3\ +\x90\x60\x7c\xc6\xf6\x28\xb6\x07\x5f\xd0\x9e\xd1\xfd\x1f\x41\x37\ +\xb6\x6d\x44\x2c\x58\x29\x74\xfb\x08\xd2\xeb\x5c\x0e\xfe\xeb\x5b\ +\xd6\x1f\xb0\xe0\x6d\xaa\x3e\x07\x5e\x5f\xfc\x0d\x09\xf6\x2a\xdc\ +\ \x00\x00\x09\xcf\ \x00\ \x00\x35\xea\x78\x9c\xed\x5a\x5b\x6f\xdb\xca\x11\x7e\xf7\xaf\x60\ @@ -32609,140 +32263,251 @@ qt_resource_data = "\ \x33\x31\x30\x30\x32\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ \x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\ \x3e\x0a\ -\x00\x00\x08\x39\ -\x00\ -\x00\x1c\x01\x78\x9c\xed\x58\x4b\x6f\xdb\x48\x12\xbe\xfb\x57\x70\ -\x99\x4b\x8c\x65\x37\xfb\xdd\x4d\xd9\xf2\x1c\xd6\x98\x41\x80\x2c\ -\x16\xd8\x24\xd8\x63\x40\x91\x2d\x99\x6b\x8a\x14\x48\xca\x92\xfc\ -\xeb\xb7\x9a\x2f\x51\x0f\xcf\x64\x31\x99\x1c\x06\xc3\x20\x16\x59\ -\xcf\xae\xea\xaf\xab\x8a\xbc\xff\x69\xbf\xce\xbd\x17\x5b\xd5\x59\ -\x59\xcc\x7d\x8a\x89\xef\xd9\x22\x29\xd3\xac\x58\xcd\xfd\x2f\x9f\ -\x7f\x46\xc6\xf7\xea\x26\x2e\xd2\x38\x2f\x0b\x3b\xf7\x8b\xd2\xff\ -\xe9\xe1\xe6\xfe\x6f\x08\x79\xff\xa8\x6c\xdc\xd8\xd4\xdb\x65\xcd\ -\x93\xf7\xa1\x78\xae\x93\x78\x63\xbd\xf7\x4f\x4d\xb3\x99\x85\xe1\ -\x6e\xb7\xc3\x59\x4f\xc4\x65\xb5\x0a\x6f\x3d\x84\x1e\x6e\x6e\xee\ -\xeb\x97\xd5\x8d\xe7\x79\xe0\xb7\xa8\x67\x69\x32\xf7\x7b\x85\xcd\ -\xb6\xca\x5b\xc1\x34\x09\x6d\x6e\xd7\xb6\x68\xea\x90\x62\x1a\xfa\ -\x47\xf1\xe4\x28\x9e\x38\xef\xd9\x8b\x4d\xca\xf5\xba\x2c\xea\x56\ -\xb3\xa8\xdf\x4d\x84\xab\x74\x39\x4a\xbb\xd5\xec\x78\x2b\x44\xa3\ -\x28\x0a\x09\x0b\x19\x43\x20\x81\xea\x43\xd1\xc4\x7b\x74\xaa\x0a\ -\x6b\xbc\xa6\xca\x08\x21\x21\xf0\x8e\x92\xdf\x26\x35\xdb\xe7\x90\ -\x8a\x37\x17\xd3\x72\xa7\xde\x21\xfd\x1b\xf8\x3f\x2a\x0c\x04\x5c\ -\x97\xdb\x2a\xb1\x4b\xd0\xb4\xb8\xb0\x4d\xf8\xf8\xf9\x71\x64\x22\ -\x82\xd3\x26\x9d\x98\x19\xb2\x7f\xe2\xf7\x64\x4b\x8a\x78\x6d\xeb\ -\x4d\x9c\xd8\x3a\x1c\xe8\xad\xfe\x2e\x4b\x9b\xa7\xb9\xaf\xc4\x66\ -\xdf\x3e\x3f\xd9\x6c\xf5\xd4\x4c\x08\x59\x3a\xf7\x21\x42\xa6\x99\ -\x6a\x9f\x87\x35\xcc\x46\x24\x11\xcc\x59\x27\xda\x1b\x9e\xb2\x84\ -\xc1\xd4\xab\x22\xad\xc8\xa9\x76\x5a\x26\x6e\x49\x73\xff\x53\x11\ -\x6f\xbe\x7e\x28\x1a\x50\xb1\x49\x03\x5a\x78\xc8\xe7\x68\xae\xdc\ -\x36\x9b\x6d\xf3\xd5\xee\x1b\x5b\x74\x76\x21\xa2\x49\x78\x2d\xdb\ -\xa9\xe1\x93\xd0\x26\x50\xa7\xfe\x03\x50\xee\x53\xbb\xac\x1d\xa7\ -\x8b\xca\x3d\x41\x58\xa6\xe5\x01\x17\xb6\xc6\xc6\xd5\x2f\x55\x9c\ -\x66\x00\xc8\x4e\x6e\xb2\x8a\xa4\xcc\x73\x58\xe1\xdc\x8f\xf3\x5d\ -\x7c\xa8\xfd\x51\x00\x4c\x9d\xaa\x72\x2a\x44\x6f\x14\xcc\xd6\x4d\ -\xb9\x19\x64\x21\x01\xcd\x21\x87\xa8\x1d\x11\x81\xc5\xb2\x9a\xbd\ -\x5b\xb6\xd7\x5d\x4b\x2a\x61\x8b\xb2\xe6\x30\xa3\x77\xfe\x51\xa7\ -\x5c\x2e\x6b\x0b\x8e\xc9\x84\xd6\x6e\x0b\x68\x80\x2f\xe5\x7b\xe1\ -\xef\xf3\x46\xae\x79\xa3\xd7\xbd\x99\xd1\xdb\x7d\x78\x1a\x76\x4f\ -\x1d\x13\xb6\x81\xfc\x6f\xdc\x9e\xbe\xd8\xc1\xd2\xb8\xfd\xcd\xc1\ -\x81\xf5\x54\x94\xa7\xfe\x45\xd2\x5f\x36\x5f\xf7\x10\xb8\x37\xf3\ -\x38\x83\x3f\xf4\xaa\xc4\xa1\x93\xa0\x70\x18\xe1\x87\x5c\x95\x79\ -\x75\x90\xfe\x15\x33\xfd\x0a\x50\x59\x65\xab\x0c\x30\xd3\xca\x31\ -\x8a\x79\x7b\x9d\xea\x40\x32\x26\xb1\x31\xcd\xc5\x31\x27\x2e\x17\ -\x71\xfe\x7f\x83\xa8\xad\x0b\xb3\xa7\xca\x42\x1d\x7b\x77\x05\x4d\ -\x53\xdf\xa7\x2e\xb8\x91\xc7\x88\x57\x3d\xf1\x4b\x91\x35\x50\xb0\ -\xb6\xb5\xad\x3e\xb9\x43\xff\xaf\xe2\x4b\x6d\x2f\xa4\x3e\x57\x71\ -\x51\x43\x85\x59\xcf\xfd\x75\xdc\x54\xd9\xfe\x3d\x0d\x88\xfb\x87\ -\x55\x64\x24\x8b\x04\xdc\x33\xc2\xb0\x61\x46\xf1\xdb\x51\x3d\x81\ -\x1d\x61\x4c\x62\xa6\x04\x61\x47\x2a\xec\x82\xd2\x0c\xeb\x48\x73\ -\x35\x52\x97\x57\x65\x97\x57\x65\x2b\xc8\xba\xc0\x5c\x48\x6a\xcc\ -\x1f\x9d\x50\xf4\x5b\x29\x45\xd1\x9f\x39\xa9\xdf\xb5\xd4\xa1\x1f\ -\x5a\xec\x10\xfb\xb1\xe5\x0e\x91\x5f\x2d\x78\xf7\xa1\x6b\x23\xed\ -\xdd\x58\xdc\x5c\x63\x4b\x5f\x32\xbb\x3b\xf6\x9a\x45\x3c\x42\x65\ -\x13\xaf\x6c\xbb\x38\x00\x66\xb7\xba\x9e\xb1\x28\xab\xd4\x56\x03\ -\x4b\xb5\xd7\x09\xab\x5f\x7f\x37\xbb\xdd\x9c\x6e\x99\xb3\x3a\xf2\ -\xc9\x75\x7e\xfd\x14\xa7\xe5\x0e\xb0\x73\xce\x7c\x2d\x4b\x80\x2b\ -\xc7\xc6\x44\xc4\x68\x7e\xce\x6e\xb1\x09\x7d\x9c\x6a\xca\xd4\x05\ -\x13\xfc\x49\x8e\x95\x92\x5a\x5f\x32\xb7\x55\x05\x89\x42\x79\x7c\ -\xb0\x10\xd4\x4a\x30\x33\x9c\xab\xfa\xa9\xdc\xad\x2a\x97\x9b\xa6\ -\xda\xda\x73\x45\x18\x0f\xb6\x6e\x2c\x44\xdb\xee\xd0\xf5\xc3\xc8\ -\x44\xc2\xe9\xa2\xc5\xa2\xdc\x5f\x37\xb0\xcb\x0a\x88\x15\xf5\xe3\ -\x0d\x65\xe6\x22\x23\xbd\xc4\x30\xf0\x68\x29\xdf\x90\xd8\x1f\xc1\ -\x78\xce\x3a\xb8\x83\xf8\x06\x6f\x1d\xef\xb3\x75\xf6\x6a\x53\x87\ -\xad\x0e\x42\xf7\x6b\xdb\xc4\x69\xdc\xc4\x47\x60\x0c\x14\xe8\x22\ -\x74\x18\x44\x60\x56\x9d\xfd\xfb\xf1\xe7\x11\xe4\x49\x32\xfb\x4f\ -\x59\x3d\x1f\xf1\xe9\x04\xe2\x05\xcc\x3d\x73\x7f\x3c\x7a\x6e\xbc\ -\x49\x66\xae\xf0\xc4\xcd\x43\xb6\x86\xed\x76\x83\xe9\xdf\x61\x3e\ -\x04\x88\x8e\x8c\x13\x61\xd7\x84\x8f\x46\x3b\xb3\x95\xed\x06\xcf\ -\xab\xb3\x7a\x9a\xac\x33\xa7\x14\x7e\x6a\xb2\x3c\xff\xe0\x9c\x4c\ -\x0e\x63\x6f\x34\x6b\x72\xfb\xd0\xfa\xec\x6e\x87\x28\xc2\x3e\x8c\ -\xe1\x2c\x4d\xa2\xbc\x0f\x87\x34\xb4\x4f\xab\x63\x7a\x5a\xe0\xd0\ -\xf3\x0c\xe7\xf1\xc2\xe6\x73\xff\xa3\x63\x7a\x17\xdc\x55\x55\x6e\ -\x37\xeb\x32\xb5\xbd\xfa\x90\xd6\xd5\xb4\x8c\x4d\xa1\xe8\x79\xcd\ -\x45\xd1\x26\x98\x2a\x06\xb0\x61\x7d\xf1\x1e\x9e\x14\xe6\x8a\xc8\ -\xc8\xa8\x00\x29\x85\x29\x31\x86\xa8\xdb\x63\xfd\xdb\xc4\xcd\xd3\ -\x45\x3d\x1a\xeb\x0e\x96\xc4\xb4\xf3\xc4\x5d\x5f\x9d\x48\x7b\xdd\ -\x2d\x21\x9b\x27\x0f\x93\xd2\xd8\x3e\x56\xdb\xdc\xce\x8a\xb2\x78\ -\x85\x22\x00\xb5\xac\x2a\x9f\xed\x28\xdf\x3d\x76\x48\x9f\x49\x6c\ -\x1c\x11\x56\x3b\xd0\x5d\xc9\x82\xb4\xcc\x16\xdb\xa6\x99\xd2\xfe\ -\x5b\x66\xc5\x0c\xb6\xd3\x56\x03\xb5\x7d\xc8\x01\xb3\xcd\x4c\x0c\ -\xb4\xe3\x3a\x7a\x42\x1a\x43\x15\xa9\xaa\xf8\xe0\x96\x63\xa7\xd4\ -\xae\x90\x42\x71\x5d\xc7\xd5\xb3\xad\x3a\xfe\x4b\x56\x67\x8b\x2c\ -\x77\x26\xda\xdb\xdc\xde\xa5\x59\xbd\x81\x7d\x81\x77\x16\xb7\x8c\ -\xbb\x12\xc6\xf4\x65\x5e\xee\x46\xbe\x2d\x62\xf8\x41\x8b\x38\x79\ -\x76\x3b\x59\xa4\xb3\x38\x81\x62\xb0\xcd\xe1\x0d\x74\x52\xa3\xdd\ -\xd9\xf1\xb4\xc6\x5c\x33\xad\x58\x20\x14\xc7\x11\x95\x5a\x78\x89\ -\x87\x18\xec\x12\xe5\x84\xd3\x00\x9a\x24\x54\x2d\xed\x21\xc1\xe1\ -\x55\xc4\x28\xca\x03\x4e\xb0\x96\x5c\x70\x0f\x71\x83\x99\x86\x06\ -\xa6\x02\xa9\x31\x51\x4a\x48\xaf\x93\x57\x26\xe8\x4d\x08\xaf\x17\ -\x67\x3c\xe8\x4d\x30\x6f\x90\xd6\x41\x6f\x41\x7a\x06\x13\x4d\xb4\ -\xd0\x01\xa2\x58\x11\xc2\xa8\x47\x25\x06\x75\x6d\x80\x24\x31\x34\ -\x5f\x1d\xb9\x71\x12\x5a\x36\x6d\xa5\xa0\x44\x4b\xca\x23\xef\xa3\ -\xc7\x69\x04\xae\x22\xa2\x02\x05\xe1\x68\x6e\x3c\x0e\x66\x09\x94\ -\x53\x1d\x28\x78\x7d\xe2\x70\xeb\x51\x68\xe2\x3a\x22\x91\x09\xa0\ -\x91\x63\x03\x91\x1a\x08\x94\x60\x03\xe1\x73\xe7\x41\x08\x67\x0d\ -\xd6\x6a\x08\x8c\x18\xce\x7e\x04\x42\xd2\x83\x57\x45\x2e\xa9\x06\ -\xb8\x52\x85\x35\x11\x20\x84\xfa\xa4\x04\x68\x0c\x12\x0d\x49\x09\ -\xd0\x18\x25\x1a\xc2\x34\x01\x1a\xe3\x7c\xf5\xfe\xe9\xc1\x4a\x28\ -\xcc\x32\x3a\x0a\xa4\x11\xd0\x33\x64\x04\x06\xa8\xc0\x10\xb5\x76\ -\x51\xc0\x2d\xa7\x86\x09\x8f\x41\x5f\x90\x46\x41\x7e\x35\x08\x4a\ -\x2e\x09\xe4\x00\x26\x14\xce\x24\x05\x9a\x84\xbc\x10\xa6\xcd\x55\ -\x83\xaf\x67\xed\xb8\x82\x79\x84\x47\x82\x21\x81\x22\xc4\xa6\xcc\ -\xe3\xd0\x52\x00\xd2\x9b\xb2\x42\xd0\x75\x5e\xe2\x66\x5b\x59\x57\ -\xb8\x27\xc3\x82\xb3\x71\x71\x38\xaf\x9d\xc4\x7e\x68\xf8\xeb\x24\ -\x7e\xd3\x49\x3c\xdf\x9e\x09\xab\x6f\xbf\x9c\x6a\x4c\x23\x00\xc5\ -\x84\x35\xf4\x5d\x00\x36\xc0\x99\x49\x31\xe1\x41\xc7\x45\x0a\x74\ -\xdc\x79\x9d\x9a\x83\x76\x8b\xb8\x16\x58\xc1\x84\x2e\x27\xf4\xcb\ -\xf2\x0d\xb0\x37\x82\x4b\x80\x3b\x1c\x06\xa8\xbb\x1c\x90\x09\x7b\ -\x11\x4c\x6e\xa7\x22\x50\xe1\x6f\xa7\x48\x59\x5d\xc1\x97\xdd\x6f\ -\xca\xaa\x41\x87\x74\x93\xc1\xb4\x00\xe7\x9d\xd1\x48\xd2\x6b\x48\ -\xec\x25\xf7\xdf\x2c\x09\xc8\xb2\xdd\xd7\x90\xf0\xa9\x5c\xdb\xf0\ -\x00\x6f\xa1\xcf\xe1\x63\x3f\x03\xd5\xe1\xc7\x78\x11\x3e\x56\xf1\ -\xb2\x09\x33\x40\x79\xdd\x8e\xa1\x78\x53\xac\x7e\x2b\x05\x11\x14\ -\x03\x22\x89\x74\xfd\x2b\x12\xc2\xc0\x11\x76\x61\x4f\xef\x47\x11\ -\x41\xa0\xd4\x88\x48\xf2\x00\x9a\x9a\x82\x45\x47\xf2\xf6\x6c\x93\ -\x57\x9c\x2a\x32\x1d\x38\x4e\xbb\xdd\xc5\xeb\x7d\x5c\x25\xfe\x09\ -\xbb\x3b\x71\x43\xb7\x5b\xc0\x1b\xd0\x77\x39\x63\x84\x46\x7f\xf6\ -\x33\xd6\x7f\x75\x80\x7c\xc3\x1e\x30\xff\x6a\xd2\xdd\x98\x4e\x23\ -\x38\x69\x30\xda\xc8\x37\x44\xdc\x3b\xa2\x74\xf5\x3f\xe2\xd7\x25\ -\x2a\x30\x02\x4d\x47\x02\x3c\xde\x92\x38\xbc\x21\xd1\x76\x64\x26\ -\x24\x54\x73\x58\x41\x30\xf8\x71\x7d\xca\xb5\x53\xc3\x24\x53\xd0\ -\x9b\x29\xd6\x02\x0e\x77\x30\xd8\x80\xde\xdc\xdf\x4d\x48\x83\x7c\ -\x40\x26\xec\x51\x77\x4a\x1b\x75\x48\x30\x6a\x79\xa3\x93\x23\xfb\ -\x8a\xc6\xc4\xc9\xc8\x1d\x5d\x5c\x2e\xea\xf5\x74\xd6\xfd\x1d\xe0\ -\x87\x91\xfa\xfd\xbb\xcb\x6f\x0e\xb7\xe7\xa7\xa1\xc7\xbe\xc3\xd6\ -\x5b\x58\x10\x6f\x63\xe1\xf2\x13\xc1\x25\x16\x2e\xbe\x17\x5c\x80\ -\xe1\xf8\xf5\xe0\x4d\x34\x30\xee\x86\x0d\xca\xae\xc1\x41\x46\x30\ -\x0f\x45\x8c\x06\xa3\xab\x16\x0f\x94\x63\x26\x22\x00\x07\x72\x73\ -\x92\x56\x30\x4f\xf7\x56\xdc\x5c\xd6\xb9\x8c\x26\x24\x18\x7a\x22\ -\x65\x38\x73\x78\x18\xd9\x6e\xca\xd1\x82\xb2\x29\x69\x54\x01\x38\ -\x8c\x4e\x7a\x1f\x7a\x64\x33\xef\x42\x83\x79\xbd\x0f\x0e\x3e\x46\ -\x6e\xe7\x81\x46\xde\xf9\x9a\xd8\xc9\x84\x72\xfd\x0d\xc2\xc0\x84\ -\x47\xdc\x78\x06\x5d\x87\x09\xa5\xa5\x08\xa6\x77\x23\xdb\xcd\x7b\ -\x2a\x52\x11\x03\xf4\x09\xd7\x28\x99\x39\xe9\x46\xe1\xea\xaf\x11\ -\xe6\xc7\x8e\x30\x48\x7e\xaf\x21\x26\x82\x6d\x96\xf2\x7c\x88\x91\ -\x04\xba\x30\xe7\x8a\xfe\x61\x43\x4c\x0f\x9a\xf6\xe7\xde\x7d\x09\ -\x78\xb8\xf9\x1f\x14\xb2\xc8\x77\ +\x00\x00\x0f\x23\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x50\x61\x72\x61\x6c\ +\x6c\x65\x6c\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\x78\x74\x65\ +\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\x67\x2e\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\x65\x72\x73\ +\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\x20\x20\x3c\x64\x65\ +\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\x73\ +\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\ +\x3a\x74\x79\x70\x65\x3d\x22\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x70\x65\x72\x73\x70\x33\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\ +\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\ +\x22\x30\x20\x3a\x20\x31\x30\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\ +\x70\x5f\x7a\x3d\x22\x36\x34\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x70\x65\x72\x73\x70\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\ +\x3d\x22\x33\x32\x20\x3a\x20\x32\x31\x2e\x33\x33\x33\x33\x33\x33\ +\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x32\x37\x33\x34\ +\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\ +\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\ +\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\ +\x2d\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\ +\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\ +\x30\x2d\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\ +\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\ +\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\ +\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\ +\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\ +\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\ +\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\ +\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x66\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\ +\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\ +\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\ +\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x34\x22\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x36\x2d\x32\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x38\x2d\x30\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\ +\x0a\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\ +\x65\x64\x76\x69\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x62\x61\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\ +\x6f\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\ +\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\ +\x22\x23\x36\x36\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\ +\x6f\x72\x64\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\ +\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x70\x61\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\ +\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x70\x61\x67\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\ +\x6f\x6d\x3d\x22\x33\x2e\x38\x38\x39\x30\x38\x37\x33\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\ +\x22\x32\x38\x2e\x31\x31\x37\x31\x32\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x35\x33\ +\x2e\x36\x36\x35\x37\x37\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\ +\x61\x79\x65\x72\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\ +\x20\x20\x73\x68\x6f\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\ +\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x67\x72\x69\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\ +\x32\x38\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\ +\x3d\x22\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x77\x69\x6e\x64\x6f\x77\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\ +\x6f\x77\x2d\x6d\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\ +\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\ +\x61\x32\x37\x33\x31\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\ +\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\ +\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\ +\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\ +\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\ +\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\ +\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\ +\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x20\ +\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\ +\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\ +\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\ +\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\ +\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x4c\x61\x79\x65\ +\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\ +\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x31\x36\x32\x31\x32\x38\ +\x32\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\ +\x36\x2e\x33\x36\x30\x35\x39\x38\x36\x2c\x2d\x36\x36\x2e\x31\x30\ +\x38\x38\x30\x36\x29\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\ +\x65\x63\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\ +\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\ +\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x62\x32\x38\x36\x3b\x66\ +\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\ +\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\ +\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x32\x65\x32\x65\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x32\x37\x2e\x38\ +\x34\x35\x32\x33\x30\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ +\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\ +\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\ +\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\ +\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\ +\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\ +\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\ +\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\ +\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\ +\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\ +\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\ +\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\ +\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ +\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\ +\x34\x32\x2d\x34\x2d\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x77\x69\x64\x74\x68\x3d\x22\x32\x39\x33\x2e\x35\x32\x34\x39\ +\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\ +\x68\x74\x3d\x22\x36\x32\x2e\x33\x37\x32\x36\x35\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x2d\x36\x30\x34\x2e\x30\ +\x31\x37\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x3d\ +\x22\x2d\x33\x38\x34\x2e\x34\x35\x36\x31\x35\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x6d\x61\x74\x72\x69\x78\x28\x2d\x30\x2e\x38\x34\x31\x33\x32\ +\x37\x36\x32\x2c\x2d\x30\x2e\x35\x34\x30\x35\x32\x35\x35\x31\x2c\ +\x30\x2e\x35\x33\x33\x35\x39\x39\x30\x34\x2c\x2d\x30\x2e\x38\x34\ +\x35\x37\x33\x37\x35\x39\x2c\x30\x2c\x30\x29\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\ +\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\ +\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\ +\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\ +\x30\x30\x32\x65\x32\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\ +\x64\x74\x68\x3a\x32\x37\x2e\x38\x34\x35\x32\x33\x30\x31\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\ +\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\ +\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\ +\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\ +\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\ +\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\ +\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\ +\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\ +\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\ +\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\x2d\x34\x2d\x39\x2d\x39\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\ +\x3d\x22\x32\x39\x33\x2e\x35\x32\x34\x39\x36\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x32\ +\x2e\x33\x37\x32\x36\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x78\x3d\x22\x2d\x36\x30\x33\x2e\x32\x36\x38\x38\x36\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x2d\x35\x32\x30\ +\x2e\x39\x39\x37\x33\x38\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\ +\x69\x78\x28\x2d\x30\x2e\x38\x34\x31\x33\x32\x37\x36\x31\x2c\x2d\ +\x30\x2e\x35\x34\x30\x35\x32\x35\x35\x33\x2c\x30\x2e\x35\x33\x33\ +\x35\x39\x39\x30\x36\x2c\x2d\x30\x2e\x38\x34\x35\x37\x33\x37\x35\ +\x38\x2c\x30\x2c\x30\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ +\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\ +\x3e\x0a\ \x00\x00\x0a\x5e\ \x00\ \x00\x29\x34\x78\x9c\xed\x5a\xdb\x8e\xdb\x46\x12\x7d\xf7\x57\x68\ @@ -33720,148 +33485,288 @@ qt_resource_data = "\ \x9d\x6b\xab\xd1\xce\x92\x33\xd8\xd5\xac\x13\x9f\xed\xed\xa6\xff\ \x2f\xe8\x6f\xd0\xdb\x35\xf1\xef\x7e\x5c\xd8\x5f\x6d\x5c\xbe\xf8\ \x3f\x45\x39\x68\xb0\ -\x00\x00\x08\xb6\ -\x00\ -\x00\x1e\x19\x78\x9c\xed\x58\xdb\x6e\xdb\x48\x12\x7d\xf7\x57\x70\ -\x95\x97\x18\xcb\x4b\xdf\xd8\x17\xf9\x32\x0f\x6b\xcc\x60\x80\x01\ -\x16\xd8\x24\xd8\xc7\x80\x12\x5b\x32\xd7\x14\x29\x90\x94\x25\xf9\ -\xeb\xe7\x34\x45\x52\x94\x25\x27\x59\xcc\x6c\x16\x08\x86\x41\xac\ -\x66\x55\x75\x55\x75\x55\x75\xf5\x69\xde\xfe\xb4\x5b\xe5\xde\xb3\ -\xad\xea\xac\x2c\xee\x26\x34\x24\x13\xcf\x16\xf3\x32\xcd\x8a\xe5\ -\xdd\xe4\xd3\xc7\x9f\x03\x3d\xf1\xea\x26\x29\xd2\x24\x2f\x0b\x7b\ -\x37\x29\xca\xc9\x4f\xf7\x57\xb7\x7f\x0b\x02\xef\x1f\x95\x4d\x1a\ -\x9b\x7a\xdb\xac\x79\xf4\x7e\x2d\x9e\xea\x79\xb2\xb6\xde\xfb\xc7\ -\xa6\x59\x4f\xa3\x68\xbb\xdd\x86\x59\x47\x0c\xcb\x6a\x19\x5d\x7b\ -\x41\x70\x7f\x75\x75\x5b\x3f\x2f\xaf\x3c\xcf\x83\xdd\xa2\x9e\xa6\ -\xf3\xbb\x49\x37\x61\xbd\xa9\xf2\x56\x30\x9d\x47\x36\xb7\x2b\x5b\ -\x34\x75\x44\x43\x1a\x4d\x8e\xe2\xf3\xa3\xf8\xdc\x59\xcf\x9e\xed\ -\xbc\x5c\xad\xca\xa2\x6e\x67\x16\xf5\xbb\x91\x70\x95\x2e\x06\x69\ -\xe7\xcd\x96\xb7\x42\xd4\x18\x13\x11\x16\x31\x16\x40\x22\xa8\xf7\ -\x45\x93\xec\x82\xd3\xa9\xf0\xf1\xd2\x54\x46\x08\x89\xc0\x3b\x4a\ -\x7e\x9b\xd4\x74\x97\x23\x14\x6f\x3a\xd3\x72\xc7\xd6\x11\xfe\x35\ -\xfe\x0f\x13\x7a\x42\x58\x97\x9b\x6a\x6e\x17\x98\x69\xc3\xc2\x36\ -\xd1\xc3\xc7\x87\x81\x19\x90\x30\x6d\xd2\x91\x9a\x3e\xfa\x27\x76\ -\x4f\x52\x52\x24\x2b\x5b\xaf\x93\xb9\xad\xa3\x9e\xde\xce\xdf\x66\ -\x69\xf3\x78\x37\x91\x62\xbd\x6b\xdf\x1f\x6d\xb6\x7c\x6c\x46\x84\ -\x2c\xbd\x9b\x60\x85\x4c\x31\xd9\xbe\xf7\x3e\x4c\x87\x4a\x22\x21\ -\x67\x07\xd1\x4e\xf1\x98\x25\x74\x48\xbd\xca\x28\x49\x4e\x67\xa7\ -\xe5\xdc\xb9\x74\x37\xf9\x50\x24\xeb\xcf\xbf\x54\x59\x1a\xf6\x71\ -\x1c\xd4\x94\x9b\x66\xbd\x69\x3e\xdb\x5d\x63\x8b\x83\x3e\xac\x64\ -\xb4\xac\x96\xed\xa6\x85\x27\x4b\x1a\x95\x38\x9d\xdc\x83\x72\x9b\ -\xda\x45\xed\x38\x87\xd5\xb8\x37\x2c\x47\xb7\x3c\x70\x91\x12\x9b\ -\x54\xbf\x54\x49\x9a\xa1\x10\x0f\x72\x23\x2f\xe6\x65\x9e\xdb\x39\ -\x42\x92\xe4\xdb\x64\x5f\x4f\x06\x01\xa8\x3a\x9d\xca\xa9\x10\x9d\ -\x52\xa8\xad\x9b\x72\xdd\xcb\x62\xe1\xcd\x3e\xc7\x6a\x1d\x31\x80\ -\xc6\xb2\x9a\xbe\x5b\xb4\xcf\x4d\x4b\x2a\x91\x9a\xac\xd9\x4f\xe9\ -\xcd\xe4\x38\xa7\x5c\x2c\x6a\x0b\xc3\x64\x44\x6b\xd3\x81\x19\xb0\ -\x25\x27\x5e\xf4\xc7\xac\x91\x4b\xd6\xe8\x65\x6b\x7a\xb0\x76\x1b\ -\x9d\x2e\xbb\xa3\x0e\x01\x5b\x23\xfe\x6b\x44\x0c\x3b\xb6\xd7\x34\ -\xa4\xbd\xd9\xbb\x22\x3d\x15\xe5\xe9\xe4\x2c\xe8\xcf\xeb\xcf\x3b\ -\x2c\xdc\x9b\x7a\x9c\xe1\x0f\xbd\x28\xb1\x3f\x48\x50\x6c\x42\xfc\ -\x90\x8b\x32\x2f\xae\x94\xbf\xa0\xa6\xf3\x20\x28\xab\x6c\x99\xa1\ -\x66\x5a\x39\x46\x43\xde\x3e\xa7\x73\x10\x8c\xd1\xda\x98\xe2\xe2\ -\x18\x13\x17\x8b\x24\xff\xaf\x8b\xa8\xed\x07\xd3\xc7\xca\xa2\x7f\ -\xbd\xbb\x50\x4d\x63\xdb\xa7\x26\xb8\x8e\x8f\x2b\x5e\x76\xc4\x4f\ -\x45\xd6\xa0\x51\x6d\x6a\x5b\x7d\x70\x9b\xfd\x9f\xc5\xa7\xda\x9e\ -\x49\x7d\xac\x92\xa2\x46\x67\x59\xdd\x4d\x56\x49\x53\x65\xbb\xf7\ -\xd4\x27\xee\x5f\x28\x8d\x8e\x99\x11\x18\x33\xc2\x42\xcd\xb4\xe4\ -\xd7\xc3\xf4\x39\x32\xc2\x58\x1c\x32\x29\x08\x3b\x52\x91\x05\xa9\ -\x58\xa8\x8c\xe2\x72\xa0\x2e\x2e\xca\x2e\x2e\xca\x56\x88\xba\x08\ -\xb9\x88\xa9\xd6\xff\xeb\x80\x06\xf4\x2b\x21\x0d\xc4\x8f\x1c\xd4\ -\x3f\xb5\xd5\x05\xf4\x7b\x36\xbb\x80\x7d\xdf\x76\x37\xb2\xf7\x46\ -\xc3\xfb\x3f\x54\xa8\x60\x42\xfd\xb0\xf5\x79\x1b\xb9\x93\xb9\x1d\ -\x0d\xe7\x85\xc3\x08\xe9\x73\x66\xb7\xc7\xe3\x7b\x96\x0c\xab\x5b\ -\x27\x4b\xdb\xe6\x1b\x91\x3c\x24\xbc\x63\xcc\xca\x2a\xb5\x55\xcf\ -\x92\xed\x73\xc2\xea\x4a\xe2\x00\x83\xaf\x4e\x13\xe7\xb4\x0e\x7c\ -\x72\x99\x5f\x3f\x26\x69\xb9\xc5\x72\x5f\x33\x5f\xca\x12\x11\xe6\ -\xa1\xd6\x86\x68\xc5\x5f\xb3\x5d\x38\x69\x1c\xc6\x54\x29\x69\xce\ -\x98\xce\x1f\x15\x0a\x4a\x84\x3e\x9f\xb9\xa9\x2a\xa4\x31\xc8\x93\ -\xbd\xc5\xa2\x96\x82\xe9\x5e\x41\xfd\x58\x6e\x97\x95\x8b\x4d\x53\ -\x6d\xec\xeb\x89\x40\x5a\x1b\x87\xb0\x83\xcd\xa1\x4e\x3a\x5c\x37\ -\x92\x70\x73\x83\xd9\xac\xdc\x5d\x56\xb0\xcd\x0a\xac\x35\xe8\x90\ -\x22\x65\xfa\x2c\x22\x9d\x44\x8f\x1d\x55\x1c\xbf\x21\xb1\x3b\xee\ -\xef\xd7\xac\xbd\xab\x9d\x37\x78\xab\x64\x97\xad\xb2\x17\x9b\xba\ -\xed\xda\x15\xcb\xca\x36\x49\x9a\x34\xc9\xb1\x30\x7a\x0a\x0e\xe6\ -\xbe\x33\xdd\x02\xf6\x4f\xff\xf5\xf0\xf3\xd0\x37\xe6\xf3\xe9\xbf\ -\xcb\xea\xe9\xb8\xe5\x9d\x40\x32\x03\x94\xbc\x9b\x0c\xdd\xcc\x21\ -\xc6\xf9\xd4\xed\x95\xa4\xb9\xcf\x56\x48\xb7\xc3\xf8\x7f\x07\xd4\ -\x46\x89\x0e\x8c\x13\x61\x87\x6b\x8e\x4a\x0f\x6a\x2b\x7b\xc0\xf0\ -\x17\xaf\x3d\xe9\x7c\x95\xb9\x49\xd1\x87\x26\xcb\xf3\x5f\x9d\x91\ -\x51\x7f\xeb\x94\x66\x4d\x6e\xef\x5b\x9b\x87\x61\xbf\x8a\xa8\x5b\ -\x46\xdf\x9e\x46\xab\xbc\x8d\xfa\x30\xb4\x6f\xcb\x63\x78\xda\xc2\ -\xa1\xaf\x23\x9c\x27\x33\x9b\xdf\x4d\x7e\x73\x4c\xef\x8c\xbb\xac\ -\xca\xcd\x7a\x55\xa6\xb6\x9b\xde\x87\x75\x39\x6e\x51\xe3\x52\xf4\ -\xbc\xe6\xac\xcf\x90\x90\x4a\x86\xb2\x61\x5d\xbf\xe9\xdf\x64\xc8\ -\x25\x89\x8d\x96\x7e\x20\x65\x48\x89\xd6\x44\x5e\x1f\x8f\x94\x75\ -\xd2\x3c\x9e\xb5\xf8\xa1\x95\x87\x31\xf6\x08\x1e\x76\xd3\x35\x7c\ -\xd2\x3e\x37\x0b\x44\xf3\xe4\x65\x74\xda\xb4\xaf\xd5\x26\xb7\xd3\ -\xa2\x2c\x5e\xd0\x04\x70\x3c\x54\xe5\x93\x1d\xe4\x0f\xaf\x87\x4a\ -\x9f\xc6\xa1\x76\x44\x78\xdb\xd3\x5d\xb3\x46\x58\xa6\xb3\x4d\xd3\ -\x8c\x69\xff\x29\xb3\x62\x8a\x74\xda\xaa\xa7\xb6\x2f\x39\x6a\xb6\ -\x99\x8a\x9e\x76\xf4\xa3\x23\xa4\x09\xba\x48\x55\x25\x7b\xe7\x8e\ -\x1d\x53\x0f\x67\x13\xce\xab\x55\x52\x3d\xd9\xea\xc0\x7f\xce\xea\ -\x6c\x96\xe5\x4e\x45\x3b\xcc\xed\x4d\x9a\xd5\x6b\xe4\x05\xd7\x3f\ -\xe7\xc6\x4d\x89\x9b\xcf\x22\x2f\xb7\x03\xdf\x16\x09\x7e\x82\x59\ -\x32\x7f\x72\x99\x2c\xd2\x69\x32\x47\x33\xd8\xe4\xb8\xcc\x8f\x8e\ -\x3d\xb7\x77\x3c\x26\x78\xa8\x98\x91\x7e\x4c\x64\x28\xb5\xa0\xd2\ -\x0b\x94\x09\x19\x35\x8a\xf9\xdd\x80\x7a\xb8\x79\x52\xc3\x54\xec\ -\x13\x6f\xee\x05\x22\xc4\xc1\xc1\xb9\x1f\x50\x0c\xa0\xc0\x0b\x4c\ -\x28\x98\x52\xd4\x0f\x58\xc8\x0d\x15\xc6\x0b\xa8\x08\x45\x2c\x69\ -\xec\x48\x31\x89\x15\x84\x74\xc8\xa0\xc3\xf8\x4e\x99\x86\x25\x08\ -\x49\xe8\x87\x56\x8a\xc3\x48\x08\xe5\x05\x8c\x87\x94\x19\x2d\x7c\ -\x9c\x26\x44\x30\xea\xe5\x98\x46\xe1\x60\x2c\x62\xe6\xf7\x43\x01\ -\x41\x11\x4a\x45\x35\x17\x7e\x3f\xf2\x34\xc7\x09\xa4\x04\x97\x7e\ -\x37\x12\xce\x57\x1a\x1a\x8a\x3b\x2c\x14\x12\xae\x9c\x4d\x8e\xd3\ -\x87\x10\xe9\x53\x5c\x52\x8d\x50\xc2\x51\x04\xcc\x2b\x1f\xde\x50\ -\x74\x6f\xd3\xae\x96\xb3\x18\x16\x51\x0c\x5c\x78\x24\x34\x9c\x50\ -\x9f\xe2\x7a\x10\x53\x19\x7b\xcc\x9d\x9d\x42\xbb\x09\xb1\x92\xdc\ -\xb4\x5e\x62\xe5\x84\x4b\xa3\xfc\x7e\xe4\xf5\x9e\xf1\xa3\x8f\x08\ -\xa8\x31\x44\x51\xe1\x07\xfd\x10\x4e\x22\xf0\xb1\x84\x8f\x1c\x7a\ -\x09\xd4\xb9\xd8\x01\xfa\x28\x98\x57\x20\xc0\x20\x62\x08\xcb\x78\ -\x37\x2a\x46\x54\xa4\x7b\x35\xb1\xdb\x54\x42\x6b\xe9\x51\x1c\xb3\ -\x42\x49\xea\x42\xab\x25\x65\xca\xa3\x1a\x51\xe7\x5a\xf9\x58\x1d\ -\xd1\xdc\x68\xf8\xa8\x90\x80\x38\x86\x87\xdd\x40\xf7\x1e\xc2\x9b\ -\x7e\x84\xe4\xab\x90\x18\x83\xd5\x0d\x23\x78\x88\xb4\x60\xa1\xc8\ -\x00\x12\x26\x91\x60\xcf\x85\x93\x1b\x57\x02\x88\x27\x6a\x84\x79\ -\x5d\xc6\xa0\x0a\x3e\x50\x09\xaf\x08\x28\x1c\x04\x8d\xf0\x19\x97\ -\x34\xe4\x82\x89\x18\x25\x81\xd3\x8e\x6b\x46\xb5\x17\x74\x2b\x1a\ -\x1c\xe0\xce\xcf\x73\x0f\x06\xf6\x48\xf0\xe5\x15\x82\xab\x80\xba\ -\x60\x87\x05\x6a\xcc\x38\xc2\xb2\x02\xbb\xb8\x29\xab\x00\x27\xea\ -\x73\xd2\x6c\x2a\xeb\x0e\xa5\x11\xb6\x74\xf3\xcf\x1a\xcf\xa5\x2e\ -\xd3\x61\xcc\xbf\xba\xcc\x37\x75\x99\x71\x6a\x46\xe4\x0e\x56\x70\ -\xa0\x22\x89\x5d\x10\x8f\x58\x3d\x9e\x00\x50\xd4\x86\xb2\x78\x0c\ -\xd5\x81\x24\x02\x81\xad\x43\x19\x21\x66\x44\x07\x8c\x70\x0d\x8c\ -\x72\x3e\x22\x5e\x3a\x93\x14\x8c\x11\xa9\xb4\xdb\x2a\xc3\xf8\x8d\ -\xa1\x4f\xae\xff\x2a\x90\xef\x5a\x20\x81\x08\xcc\xa5\x22\x51\xe8\ -\xcc\x9c\xea\x2f\x14\x89\x78\x55\x24\x12\x6d\x18\xad\x90\xe8\xd3\ -\x22\x09\xd0\xb5\x42\x4a\x95\x89\xbf\x58\x27\xc1\xd7\x0b\x25\xf8\ -\x42\xa5\x2c\x2f\x34\x20\xbb\x5b\x97\x55\x13\xec\xd3\x75\x06\xa8\ -\x1c\x12\x85\xae\x79\x52\xda\xaf\x25\x77\xdf\x2c\x89\xca\xb2\x87\ -\xaf\xaa\xd1\x63\xb9\xb2\xd1\xbe\xac\xb2\xa7\xe8\xa1\xbb\x00\xd4\ -\xd1\x6f\xc9\x2c\x7a\xa8\x92\x45\x13\x65\x68\x83\x75\x7b\xad\x0d\ -\xd7\xc5\xf2\x6b\x21\x30\xc6\x28\xc1\xdc\x4a\x09\x63\x8a\xe2\xf0\ -\xf3\x47\xc3\xa3\x00\x67\x06\xa7\x8d\x41\x20\x90\x08\x0d\x28\xc0\ -\xe3\xeb\x57\x09\x5e\x72\x2a\xc9\x18\x69\x9f\xc2\xbc\xb3\x4f\x85\ -\x49\x35\x9f\x9c\xb0\x0f\xbb\xad\x87\x79\x33\xdc\x56\xff\x94\xfd\ -\x45\xa8\xf9\xd1\xf7\x57\xf7\x05\x13\xf1\x46\x0e\xd8\xe4\x62\xd0\ -\xdb\xfb\xa9\xc1\x2e\x03\xa6\x8f\xdf\x10\x71\xf7\xf9\x38\x76\x80\ -\x90\x5f\x96\xa8\xa0\x44\x00\x77\x00\xde\xbc\x25\xb1\x7f\x43\xa2\ -\x83\xa2\xc0\x3b\xce\x03\xbf\xb7\x03\xe4\x41\x7c\x26\x43\xcd\x62\ -\x06\x5c\xca\x00\xff\x84\xa4\xca\xef\x75\x00\x8a\x76\xa3\x11\xa9\ -\x97\x07\x56\x3d\xb2\x87\xb9\x63\xda\x30\x87\xf8\xc3\x2c\x6f\x30\ -\x72\x64\x5f\x98\x31\x32\x32\x70\x07\x13\xe7\x4e\xbd\x9c\x5e\xf2\ -\xfe\x40\xf1\xe3\x2e\xf9\xfe\xdd\xf9\xf7\xcb\xeb\xd7\xbb\xa1\xab\ -\x7d\x57\x5b\x6f\xd5\x82\x78\xbb\x16\xce\x3f\xe7\x9c\xd7\xc2\xd9\ -\xb7\x9d\xb3\x62\x38\x7e\xe9\x79\xb3\x1a\x00\xf8\x8d\xa1\x94\x5d\ -\x2a\x87\xd8\x00\x1a\x18\x80\xc3\xc1\x54\x5b\x0f\x40\x9c\x4c\x18\ -\x14\x47\x00\xec\xc0\x15\x90\xa6\xdf\x69\x01\xa9\x33\x69\x46\x24\ -\x40\x61\x23\x35\xc0\x2b\x19\xb1\x03\xc0\x7f\x5c\x07\xd8\x98\x34\ -\x4c\x21\x2d\xac\x3d\x18\xe9\x6c\xa8\x81\xcd\xbc\xb3\x19\xcc\xeb\ -\x6c\x70\xd8\x18\xb8\x07\x0b\xd4\x78\xaf\x7d\x62\x27\xd0\xf5\x32\ -\x4c\xd1\x31\xe5\x84\x71\xd7\x64\x63\x86\xab\x40\x2c\xfc\xf1\x68\ -\x60\x73\xae\x71\x69\x90\x86\xa1\xfa\x84\x3b\x24\x99\x3e\x39\x89\ -\xa2\x65\xff\xb1\x60\x79\xf8\x4c\x80\x9f\x5b\xf7\x59\xe3\xfe\xea\ -\x77\x92\xf5\x44\x82\ +\x00\x00\x11\x72\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x49\x6e\x74\x65\x72\ +\x73\x65\x63\x74\x69\x6f\x6e\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\ +\x65\x78\x74\x65\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\ +\x76\x67\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\ +\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\x20\ +\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x64\x65\x66\x73\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\x3c\ +\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\ +\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\ +\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\ +\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\ +\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\ +\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x73\x74\x6f\x70\x33\x31\x34\x36\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\ +\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\ +\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\ +\x74\x6f\x70\x33\x31\x34\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\ +\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\ +\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\ +\x3d\x22\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\ +\x33\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\x20\x33\x32\ +\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\x20\ +\x31\x30\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x7a\x3d\x22\ +\x36\x34\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\ +\x73\x70\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\x33\x32\x20\ +\x3a\x20\x32\x31\x2e\x33\x33\x33\x33\x33\x33\x20\x3a\x20\x31\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x65\x72\x73\ +\x70\x65\x63\x74\x69\x76\x65\x32\x37\x33\x34\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\ +\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\ +\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\ +\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\ +\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\ +\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\ +\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\ +\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\ +\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\ +\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\ +\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\ +\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\x37\ +\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\ +\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\ +\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x31\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\ +\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\x30\x2d\x34\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\ +\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\ +\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\ +\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\ +\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\ +\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\ +\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\ +\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\ +\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\ +\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\ +\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\ +\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x31\x22\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\ +\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\ +\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\ +\x6f\x70\x33\x31\x34\x36\x2d\x32\x22\x20\x2f\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\ +\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\ +\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\ +\x6f\x70\x33\x31\x34\x38\x2d\x32\x22\x20\x2f\x3e\x0a\x20\x20\x20\ +\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\ +\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\ +\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\ +\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\ +\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x32\x34\x37\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\ +\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\ +\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\ +\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\ +\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\ +\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\ +\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\ +\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\ +\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\ +\x38\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\ +\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\ +\x64\x76\x69\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\ +\x61\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\ +\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\ +\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\ +\x23\x36\x36\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\ +\x72\x64\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x70\x61\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x70\x61\x67\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\ +\x6d\x3d\x22\x33\x2e\x38\x38\x39\x30\x38\x37\x33\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\ +\x31\x35\x2e\x35\x31\x37\x37\x36\x39\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x31\x37\x2e\ +\x34\x31\x30\x34\x38\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\ +\x79\x65\x72\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\ +\x20\x73\x68\x6f\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\ +\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\ +\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\ +\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x67\x72\x69\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x77\x69\x6e\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\ +\x38\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\ +\x22\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\ +\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\ +\x69\x6e\x64\x6f\x77\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\ +\x77\x2d\x6d\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\ +\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\ +\x32\x37\x33\x31\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\ +\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\ +\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\ +\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\ +\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\ +\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\ +\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\ +\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x20\x2f\ +\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\ +\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\ +\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\ +\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\ +\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\x3d\x22\x4c\x61\x79\x65\x72\ +\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\ +\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\ +\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x31\x36\x32\x31\x32\x38\x32\ +\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x36\ +\x2e\x33\x36\x30\x35\x39\x38\x36\x2c\x2d\x36\x36\x2e\x31\x30\x38\ +\x38\x30\x36\x29\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x70\x61\ +\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\ +\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\ +\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x62\x32\x38\x36\x3b\x66\x69\ +\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\ +\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\ +\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x32\x65\x32\x65\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x35\x2e\x30\x30\x30\ +\x30\x30\x30\x30\x33\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\ +\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\ +\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ +\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\ +\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\ +\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\ +\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\ +\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\ +\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\ +\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\ +\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x31\x34\x2e\x34\x33\x37\ +\x35\x20\x34\x2e\x37\x38\x31\x32\x35\x20\x4c\x20\x34\x2e\x36\x35\ +\x36\x32\x35\x20\x31\x34\x2e\x35\x36\x32\x35\x20\x4c\x20\x32\x32\ +\x20\x33\x31\x2e\x39\x30\x36\x32\x35\x20\x4c\x20\x34\x2e\x36\x35\ +\x36\x32\x35\x20\x34\x39\x2e\x32\x35\x20\x4c\x20\x31\x34\x2e\x34\ +\x33\x37\x35\x20\x35\x39\x2e\x30\x33\x31\x32\x35\x20\x4c\x20\x33\ +\x31\x2e\x37\x38\x31\x32\x35\x20\x34\x31\x2e\x36\x38\x37\x35\x20\ +\x4c\x20\x34\x39\x2e\x31\x32\x35\x20\x35\x39\x2e\x30\x33\x31\x32\ +\x35\x20\x4c\x20\x35\x38\x2e\x39\x30\x36\x32\x35\x20\x34\x39\x2e\ +\x32\x35\x20\x4c\x20\x34\x31\x2e\x35\x36\x32\x35\x20\x33\x31\x2e\ +\x39\x30\x36\x32\x35\x20\x4c\x20\x35\x38\x2e\x39\x30\x36\x32\x35\ +\x20\x31\x34\x2e\x35\x36\x32\x35\x20\x4c\x20\x34\x39\x2e\x31\x32\ +\x35\x20\x34\x2e\x37\x38\x31\x32\x35\x20\x4c\x20\x33\x31\x2e\x37\ +\x38\x31\x32\x35\x20\x32\x32\x2e\x31\x32\x35\x20\x4c\x20\x31\x34\ +\x2e\x34\x33\x37\x35\x20\x34\x2e\x37\x38\x31\x32\x35\x20\x7a\x20\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\x61\x6e\x73\ +\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x36\x2e\x31\ +\x36\x37\x39\x35\x38\x34\x2c\x30\x2c\x30\x2c\x36\x2e\x31\x36\x37\ +\x39\x35\x38\x34\x2c\x2d\x33\x39\x2e\x32\x33\x31\x39\x30\x38\x2c\ +\x34\x30\x37\x2e\x37\x35\x36\x33\x37\x29\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\ +\x32\x2d\x34\x2d\x39\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\ +\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\ +\x0a\ \x00\x00\x0b\xd5\ \x00\ \x00\x37\xfe\x78\x9c\xed\x5a\xdb\x72\xdb\xd6\x15\x7d\xd7\x57\xa0\ @@ -34054,150 +33959,273 @@ qt_resource_data = "\ \xe2\x26\xcb\xa0\x11\x91\x47\x58\x2c\x11\x28\x7f\x4c\x7d\x1c\x4c\ \x7b\xb4\xde\xf8\x64\x7c\xf1\xee\xe8\x84\xde\x7e\xbc\x3b\xfa\x2f\ \xca\x86\x31\xf6\ -\x00\x00\x08\xd8\ -\x00\ -\x00\x1f\xc6\x78\x9c\xed\x58\x5b\x6f\xdb\x38\x16\x7e\xcf\xaf\xd0\ -\xba\x2f\x0d\xd6\x92\x78\x17\xe9\xc6\x19\x2c\xa6\x98\xc1\x00\x5d\ -\x2c\xb0\xd3\x62\x1f\x0b\xc5\xa2\x1d\x6d\x6c\xc9\x90\xe4\xd8\xe9\ -\xaf\xdf\x8f\xb2\xae\xb1\x92\xcd\xcc\xc3\x5e\xab\xa0\x35\x75\x2e\ -\x24\xcf\x85\xdf\x39\xd4\xcd\x0f\xa7\xdd\xd6\x7b\xb4\x45\x99\xe6\ -\xd9\x72\x46\x03\x32\xf3\x6c\xb6\xca\x93\x34\xdb\x2c\x67\x5f\x3e\ -\xff\xe4\xeb\x99\x57\x56\x71\x96\xc4\xdb\x3c\xb3\xcb\x59\x96\xcf\ -\x7e\xb8\xbd\xba\xf9\x83\xef\x7b\x3f\x16\x36\xae\x6c\xe2\x1d\xd3\ -\xea\xde\xfb\x25\x7b\x28\x57\xf1\xde\x7a\xef\xef\xab\x6a\xbf\x08\ -\xc3\xe3\xf1\x18\xa4\x0d\x31\xc8\x8b\x4d\x78\xed\xf9\xfe\xed\xd5\ -\xd5\x4d\xf9\xb8\xb9\xf2\x3c\x0f\xeb\x66\xe5\x22\x59\x2d\x67\x8d\ -\xc2\xfe\x50\x6c\x6b\xc1\x64\x15\xda\xad\xdd\xd9\xac\x2a\x43\x1a\ -\xd0\x70\xd6\x8b\xaf\x7a\xf1\x95\x5b\x3d\x7d\xb4\xab\x7c\xb7\xcb\ -\xb3\xb2\xd6\xcc\xca\x77\x03\xe1\x22\x59\x77\xd2\x6e\x37\x47\x5e\ -\x0b\x51\x63\x4c\x48\x58\xc8\x98\x0f\x09\xbf\x7c\xca\xaa\xf8\xe4\ -\x8f\x55\xb1\xc7\x29\x55\x46\x08\x09\xc1\xeb\x25\xdf\x26\xb5\x38\ -\x6d\xe1\x8a\x17\x37\x53\x73\x87\xab\xc3\xfd\x7b\xfc\xeb\x14\x5a\ -\x42\x50\xe6\x87\x62\x65\xd7\xd0\xb4\x41\x66\xab\xf0\xe3\xe7\x8f\ -\x1d\xd3\x27\x41\x52\x25\x83\x69\x5a\xef\x8f\xd6\x1d\x85\x24\x8b\ -\x77\xb6\xdc\xc7\x2b\x5b\x86\x2d\xbd\xd6\x3f\xa6\x49\x75\xbf\x9c\ -\x29\xb1\x3f\xd5\xef\xf7\x36\xdd\xdc\x57\x03\x42\x9a\x2c\x67\xb0\ -\x90\x45\x4c\xd5\xef\xed\x1e\x16\x5d\x26\x91\x80\xb3\xb3\x68\x33\ -\xf1\x90\x25\x74\x40\xbd\xc2\x44\x8a\x8c\xb5\x93\x7c\xe5\xb6\xb4\ -\x9c\x7d\x2c\xe2\x75\xf5\xf5\x53\x9a\xd9\xa0\x75\x64\x37\x4f\x7e\ -\xa8\xf6\x87\xea\xab\x3d\x55\x36\x3b\x4f\x08\x53\x06\x76\xd5\x6c\ -\xa7\x16\x8c\x6c\x1a\xe4\x38\x9d\xdd\x82\x72\x93\xd8\x75\xe9\x38\ -\x67\x73\xdc\x1b\xec\xd1\x35\x0f\xdc\x22\x4e\xd2\x78\xfb\xb3\xfb\ -\x41\x26\x9e\xe5\x06\xbb\x58\xe5\xdb\xad\x5d\xc1\x27\xf1\xf6\x18\ -\x3f\x95\xb3\x56\xa0\x8e\xe5\xe2\xbe\xb0\xc8\xbd\x77\x18\xdb\xb8\ -\x68\xe7\xe0\x54\x88\x4e\xce\x2d\x39\x5e\x42\xb0\xa8\x67\x6f\x1a\ -\xe2\x97\x2c\xad\x90\x64\x87\xd2\x16\xbf\xba\x40\xfd\x25\xfb\x52\ -\xda\x0b\xa9\xcf\x45\x9c\x95\xc8\x8a\xdd\x72\xb6\x8b\xab\x22\x3d\ -\xbd\xa7\x73\xe2\xfe\x02\x65\xb4\x64\x46\x60\xcc\x08\x0b\x34\xd3\ -\x8a\x5f\x77\xea\xab\xd3\x72\xc6\x98\x0c\x98\x12\x84\xf5\xd4\x27\ -\x04\x3a\x62\x41\x64\x22\xae\x3a\xea\x7a\x52\x76\x3d\x29\x5b\x2c\ -\x67\x5c\x04\x5c\x48\xaa\x81\x1e\x61\xe3\xd0\xb1\x33\xde\xec\x50\ -\xe7\xa8\x09\x3f\xde\x36\xfc\x9b\xb2\xca\xf7\xad\x2c\x52\xa9\x7a\ -\xda\x22\x7f\x1c\xd1\xc7\x8c\x79\xb1\x78\xb7\xae\x9f\x0f\x35\x29\ -\x87\x0f\xd3\xea\x69\x41\x3f\xcc\x7a\x9d\x7c\xbd\x2e\x2d\x16\x26\ -\x03\x5a\x9d\xe0\xd0\xc0\x5a\xaa\x33\xe1\xf7\xae\x46\xa6\x56\xa3\ -\xd3\xab\x0d\x1c\x16\x8e\xcd\xfe\x37\xe6\x25\xfb\x5f\xce\xcb\xce\ -\x75\x7b\x20\xc4\x1e\xbe\x43\x51\x69\x35\x3a\x64\xaa\x9e\x1c\x8e\ -\x8e\x45\x79\x32\xbb\x70\xff\xe3\xfe\x2b\x36\x44\xbc\x85\xc7\x19\ -\xfe\xa3\x93\x12\x4f\x67\x09\x8a\x3a\x81\x1f\x32\x29\xf3\xcd\xa1\ -\xed\x2b\xd3\x34\x3b\xf0\xf3\x22\xdd\xa4\x40\xb5\x5a\x8e\xd1\x80\ -\xd7\xcf\x58\x07\x21\x1d\xd8\xc6\x22\x2e\x1a\xeb\x6f\x42\x87\x7a\ -\xf5\xa8\xb3\xd4\x01\x70\xf2\x98\xda\x63\x0f\x8d\x77\x71\x17\xdb\ -\x7d\xbc\xb1\x75\xa6\x23\x8b\xce\xa9\xde\x30\xee\xf2\x22\xb1\x45\ -\xcb\x52\xf5\x33\x62\x35\x87\xe1\xdc\x63\x5c\x3d\x33\x06\xb3\x76\ -\x7c\x32\xcd\x2f\xef\xe3\x24\x3f\x22\xd8\xcf\x99\xdf\xf2\x1c\xf9\ -\xc5\x03\xad\x0d\xd1\x11\x7f\xce\x76\xc9\xe4\xbb\x04\xa1\x8a\x30\ -\x71\xc1\xc5\x82\x60\x6a\xa2\x74\x74\xc9\x3c\x14\x05\xb2\xd8\xdf\ -\xc6\x4f\x16\x56\x6d\x38\x95\xad\x4c\x79\x9f\x1f\x37\x85\x73\x4e\ -\x55\x1c\xec\x73\x45\xd4\xb1\x83\xeb\x5f\xfc\xc3\xf9\x98\x34\x55\ -\x73\x20\xe1\x74\xfd\xbb\xbb\xfc\x34\x3d\xc1\x31\xcd\x60\xac\xdf\ -\xd4\x61\xca\xf4\x85\x4b\x1a\x89\xb6\x32\x47\x52\xbe\x20\x71\xea\ -\x81\xed\x39\xcb\xd9\x7e\xe1\xce\x86\xb7\x8b\x4f\xe9\x2e\xfd\x66\ -\x13\x87\x54\x4d\xb6\xec\x6c\x15\x27\x71\x15\xf7\x99\xd1\x52\x90\ -\x53\xb4\x2b\x9c\xc9\x7a\xf1\xd7\x8f\x3f\x75\x90\xb9\x5a\x2d\xfe\ -\x96\x17\x0f\x3d\xda\x39\x81\xf8\x0e\x75\x7a\x39\xeb\x60\xdc\x95\ -\xe3\xd5\xc2\x41\x45\x5c\xdd\xa6\x3b\xc4\xdb\x75\x50\x7f\x44\x23\ -\x83\x1c\xed\x18\x23\x61\x77\x24\xfb\x49\xcf\xd3\x16\xf6\xdc\x21\ -\x4d\x36\x95\xc9\x6a\x97\x3a\xa5\xf0\xd7\x2a\xdd\x6e\x7f\x71\x8b\ -\x0c\xa0\xbd\x99\x34\xad\xb6\xf6\xb6\x5e\xf3\x3c\x6c\xad\x08\x1b\ -\x33\x5a\x6c\x1e\x58\x79\x13\xb6\x6e\xa8\xdf\x36\xbd\x7b\xea\xc4\ -\xa1\xcf\x3d\xbc\x8d\xef\xec\x76\x39\xfb\xe4\x98\xde\x05\x77\x53\ -\xe4\x87\xfd\x2e\x4f\x6c\xa3\xde\xba\x75\x33\x3c\xce\x1b\xc1\xb4\ -\xe9\x0e\x78\x75\x01\xb3\x24\xa0\x8a\x21\x6d\x58\x03\xb7\xed\x9b\ -\x0a\xb8\x22\xd2\x68\x35\xf7\x95\x0a\x28\xd1\x48\xfc\xeb\xbe\x96\ -\x6e\x7a\x7f\x0e\xe6\xac\x87\x5b\xb4\xfa\xef\x05\x0f\x22\x2a\x38\ -\x13\x73\xa5\xdd\x88\x89\xa8\x47\xed\x66\x67\x9c\x21\x15\x07\x4e\ -\xdd\xc7\xd5\xfd\x30\x4c\x75\x81\x01\x12\x41\x2e\x9a\x0d\x19\xa0\ -\xff\xd9\x63\x42\x05\x86\x12\x21\xe6\x02\x4d\xa2\x91\xca\x70\xef\ -\x47\xcf\x01\xbc\x89\x22\x0d\xa2\x09\xa4\xb3\xdd\x63\x04\x6c\x6a\ -\xa4\x99\x0b\x58\x22\x14\x20\xbd\xa6\x09\x0e\xe3\x84\x8e\x02\x85\ -\x05\x8c\xd3\x05\x91\x33\x1d\xd1\xb9\x30\x0c\x82\x46\x38\x41\x13\ -\x50\x4a\x25\x24\x4d\x84\x11\xaa\x04\xb0\x13\x55\x89\xc0\xa4\xb9\ -\x24\x34\x10\x82\x2a\xed\x7d\xf2\x24\x0b\x18\x89\x98\xe1\x73\x05\ -\xe3\x51\xa5\x0c\xc5\x9c\x42\x06\x44\x52\x94\xb0\xb9\xe2\x51\xa0\ -\x85\x16\xdc\xe3\x32\x88\x64\x44\x19\x9c\x7c\x2e\x32\x0a\x9b\x94\ -\x81\xd2\x42\xc9\xa8\xa6\x29\x2a\xb9\x86\x36\xe6\xe1\x9c\x11\x65\ -\x40\x05\x2e\x11\x58\xeb\xf9\x94\x07\x82\x71\x28\x4b\x0c\x08\xe5\ -\x11\x48\x28\x8c\x5c\x53\x8e\xb5\x23\xc8\x49\xa6\x25\xb4\x1d\x99\ -\x49\x4e\x94\x9a\x2b\xb7\x79\x6c\xd9\x78\x70\x8f\x88\xb4\x66\x72\ -\x8e\xa8\xb8\x18\x47\xd4\x63\x11\xca\x9f\xe1\x5c\x80\x86\xb8\x45\ -\x12\xf5\x04\x5b\x37\x81\x92\x24\x42\x2e\x38\x2a\x35\x44\x46\x1e\ -\x1c\x68\xa0\x81\xfd\x18\x11\x18\x6d\x20\x08\x12\x67\xc8\x19\x44\ -\x3a\x82\x18\xb6\x11\x41\x19\x54\x84\x1c\x56\x47\x68\xef\x25\x25\ -\x50\x05\x76\x46\x94\xa0\x92\x2b\x05\x9f\x0b\x58\xe4\x68\xd8\x2c\ -\x11\xb0\x1a\x43\xc2\x61\x37\x3c\xe9\x62\x28\x60\xb4\x9e\x4b\x94\ -\x29\xc2\xdd\xb6\x11\x1d\x4e\x03\x89\x24\x84\xd7\xc1\x07\x91\x63\ -\xe3\xdc\xc0\xbd\x50\x97\x30\xc1\x19\x00\x47\x0a\x58\xca\x4d\xe4\ -\xc4\x70\x77\xa0\xd8\xac\x53\x46\x16\x3a\x0b\x75\x4d\x55\x94\x3b\ -\x97\x23\xf4\x94\x45\x9a\xcf\x25\xa5\x01\x33\x92\xaa\x9a\xa6\x98\ -\x80\x27\x84\x36\x2e\xb4\xb2\x4e\x2a\x8d\x99\x90\x1d\xa0\x62\xeb\ -\x52\x47\x2e\xab\x60\x98\x26\x0c\x2e\x77\x99\x26\x24\x47\x60\x99\ -\x4b\x44\xa1\x95\x1e\xa7\x24\xc6\x0c\x91\x55\x67\xaa\xc0\x61\xa8\ -\x77\x29\xb5\x6c\x25\xb9\x26\x7c\x32\xa1\xbf\x8d\xf2\xbe\x69\x22\ -\xfb\xd6\x74\x0d\x74\x5a\xbc\x23\xf5\x53\xbf\xf4\x8d\x24\xa6\x47\ -\x06\x1b\x21\xce\xf4\xe2\xb0\xb5\x8b\x2c\xcf\xbe\xa1\xbc\xa2\xe5\ -\x2c\xf2\x87\xfa\xd5\x36\xe3\x73\xfd\x58\xb8\xf2\x86\x87\x52\xd1\ -\xd2\x5d\xff\x07\xb0\x59\xdc\x1d\xaa\x6a\x48\xfb\x7b\x9e\x66\x0b\ -\x80\xa4\x2d\x3e\xec\xe2\xe2\xc1\x16\xe7\xd9\xce\x63\xbf\xac\xe2\ -\xa2\x1a\x51\x76\x69\x32\x7a\xb7\x59\x32\x5a\xbf\x9e\x6a\x8b\x3a\ -\x52\x2d\xba\xb5\x93\x18\x95\xbc\x28\xe2\xa7\x91\xa4\xa3\x9e\x3b\ -\x63\x74\xcb\x0d\xad\xf7\xc8\x63\x5a\xa6\x77\xe9\xd6\xbd\xd4\xc3\ -\xad\xfd\x90\xa4\xe5\x1e\xf8\x88\x4b\xae\xdb\xf8\x87\x1c\xd7\xbb\ -\xf5\x36\x3f\x76\x7c\x9b\xc5\xf8\xf1\xef\xe2\xd5\x83\x43\x54\x6c\ -\x2c\x5e\xa1\x28\x1f\x1c\x8e\x0d\x1b\xfa\x70\x33\x85\x7e\x0d\x92\ -\x09\x36\x44\x32\x87\x5a\x6f\x08\x5c\x73\x03\x18\x05\x8e\xbe\x1c\ -\xaf\x36\xd0\xdf\x43\xf6\x6a\xc8\xa6\x4a\x08\x63\xca\x8c\x18\x4d\ -\xbf\xc4\xd1\x42\xba\x47\x8d\x98\x6d\xab\xc4\x1b\xf6\x58\x15\x6d\ -\x12\x4e\x3b\xe0\x14\xb8\x3f\x62\xb8\x8e\x95\x1a\xa0\x1c\x31\xe3\ -\xf9\xa6\xaa\xae\x52\x5a\x1a\xdc\x71\x82\x48\x70\xc5\x89\x98\xfb\ -\xfd\xb0\xe7\xce\xc9\xf5\xb8\xf1\xd8\x3c\xb7\x6e\xd8\x6a\xbe\xb4\ -\x1a\xa6\x36\x06\x58\x4d\xa3\x39\x0b\x54\xa4\x24\x60\xcd\xfa\x6c\ -\xee\x8f\xdf\x06\x52\x5c\x03\x77\x1d\x34\x52\x2e\x4d\x10\x69\x21\ -\xaf\xc7\x7e\x6d\x7b\x10\x7b\xda\xe7\x45\xe5\x23\x67\xed\xf9\x7b\ -\x4c\x78\x9f\xef\x6c\xf8\x84\xcb\xc6\x43\xf8\xb1\x69\x6e\xcb\xf0\ -\x53\x7c\x17\xd6\x5f\x6a\xc2\x74\x95\x67\x65\x7d\x5f\x0d\xf6\xd9\ -\xe6\xd5\x49\x4f\xc9\x3e\x45\xbf\x1a\xa0\xaa\xa2\x7c\xd3\x57\x65\ -\x9f\x9e\xc9\xde\x0e\x84\x2f\x1a\x8b\xae\x83\x90\x75\x6b\xa2\x51\ -\x4a\x5d\xd7\x0f\xbc\xfd\x93\x07\xe8\x95\xae\x73\x99\xb7\x03\x8f\ -\x78\xd4\xfd\x35\xef\xec\x2d\xc2\x13\x33\x8f\x91\x7c\x70\x5f\x2c\ -\x90\x36\xad\xfa\x8b\x32\xa7\x7f\x2e\x53\x5f\x7a\x9b\xd5\x5e\x94\ -\xc1\x3c\xd4\xb5\x02\xd8\x9a\x7c\x26\x54\xdf\xfd\xe0\x28\xdc\x7e\ -\xd8\x73\xfd\x33\x7c\xb5\xd5\xe6\x0e\x77\xf0\xe7\xa0\xf5\x06\x88\ -\x22\x68\x21\xce\x8f\x10\xbf\x1d\x43\xba\xa5\x5e\xb2\xed\x7c\xef\ -\x8e\x8b\xd5\xe8\xc0\x4c\x46\x7f\xea\x3c\x6a\x49\x39\xca\xb9\x3b\ -\x05\x12\x95\x38\x92\xee\x18\xf6\xa3\x8e\x8d\x1e\x22\x50\x46\x19\ -\x36\x67\xe8\x9f\xe0\x6b\xa6\xaf\x67\x53\xc9\x85\x73\xa3\x88\x61\ -\x74\xde\x7d\x5d\x40\xc2\x74\x1f\x15\x70\xc4\x70\xda\x28\x65\x5d\ -\x7e\x19\x1c\x3f\x30\xf8\x1b\xe5\xa7\xe6\x7f\x35\xc7\xba\x09\x5e\ -\x4b\xb2\xfe\xa3\xc7\x6b\x59\x76\xf1\xb9\x64\x22\xcd\x2e\xbf\xb4\ -\x8c\xd3\x8c\x53\x2e\x5e\x49\x33\x5c\xc6\xde\xbf\xbb\xfc\xba\x74\ -\xfd\x42\xde\x5d\xb6\x32\xe4\x5f\x96\x62\x83\xc6\xe0\x05\x80\x56\ -\xe4\x4d\x00\x1d\x89\x1a\x92\x19\xda\x6d\x49\x85\x83\xe4\xd1\x4b\ -\x2f\x84\xc6\x3a\x40\x57\xaf\xe7\x94\xba\x4b\x85\x21\xec\x3b\x3a\ -\xff\x9f\xa0\x33\x7f\x11\x9d\x2f\x6f\x05\x53\x38\xfd\xbb\x9a\xcb\ -\x29\xe4\xfe\xde\x65\x4e\xc6\xf0\x7b\x15\xfa\x2f\xab\x42\xea\xb7\ -\x57\x21\xf1\x1f\x5e\x85\xba\x61\x33\xa8\x7f\x6e\xdc\x57\xd2\xdb\ -\xab\x7f\x00\xf7\x4d\x9e\xb9\ +\x00\x00\x10\x89\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x45\x6e\x64\x70\x6f\ +\x69\x6e\x74\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\x78\x74\x65\ +\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\x67\x2e\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\x65\x72\x73\ +\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\x20\x20\x3c\x64\x65\ +\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\x73\ +\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\ +\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\ +\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\ +\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\ +\x34\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\ +\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x32\x37\ +\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\ +\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\ +\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\ +\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\x30\x2c\ +\x30\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\x32\x2e\ +\x38\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\ +\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\ +\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\x22\x32\ +\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x66\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\x34\x35\ +\x31\x38\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\ +\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\ +\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\ +\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\ +\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\ +\x6f\x70\x33\x31\x34\x36\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x73\x74\x6f\x70\x2d\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\ +\x33\x31\x34\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\ +\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\ +\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\ +\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\ +\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\ +\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x34\x32\x37\x32\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\ +\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\ +\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\ +\x78\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\ +\x34\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\ +\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\ +\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\x37\x32\ +\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\ +\x3d\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\ +\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x33\x64\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\x20\x33\x32\x20\x3a\ +\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\x20\x31\x30\ +\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x7a\x3d\x22\x36\x34\ +\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\ +\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\x33\x32\x20\x3a\x20\ +\x32\x31\x2e\x33\x33\x33\x33\x33\x33\x20\x3a\x20\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x65\x72\x73\x70\x65\ +\x63\x74\x69\x76\x65\x32\x37\x33\x34\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\ +\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\ +\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x33\x30\x31\x31\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\ +\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\ +\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\ +\x28\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\x34\ +\x2c\x30\x2c\x32\x30\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\ +\x34\x30\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\x22\ +\x36\x37\x32\x2e\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x66\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x79\x3d\x22\x36\x37\x32\x2e\ +\x37\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\x3d\ +\x22\x33\x34\x2e\x33\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\x0a\x20\ +\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\x64\x69\ +\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0a\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\x20\x20\ +\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x66\ +\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\ +\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\x61\ +\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\x61\ +\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\x61\ +\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x33\x2e\x38\x38\ +\x39\x30\x38\x37\x33\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x31\x35\x2e\x37\x39\x36\x31\ +\x36\x39\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x63\x79\x3d\x22\x32\x35\x2e\x32\x39\x32\x36\x31\x35\x22\ +\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\ +\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\x67\x34\ +\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x73\x68\x6f\x77\x67\x72\ +\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\ +\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x69\x64\x2d\x62\ +\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\ +\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\x35\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\ +\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\ +\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\x78\x69\x6d\ +\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\ +\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x37\x33\x31\x22\x3e\x0a\ +\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\ +\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\ +\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\ +\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\ +\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\ +\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\ +\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\ +\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\ +\x63\x3a\x74\x69\x74\x6c\x65\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\ +\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\ +\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\ +\x65\x6c\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\ +\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\ +\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x74\x72\ +\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\ +\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\x30\x2e\ +\x31\x36\x32\x31\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\x39\x38\ +\x36\x2c\x2d\x36\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\ +\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\ +\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\ +\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\ +\x30\x30\x32\x65\x32\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\ +\x64\x74\x68\x3a\x33\x30\x2e\x38\x33\x39\x37\x39\x32\x32\x31\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\ +\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\ +\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ +\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\ +\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\ +\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\ +\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\ +\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x64\ +\x3d\x22\x4d\x20\x32\x37\x37\x2e\x30\x35\x36\x34\x2c\x34\x35\x35\ +\x2e\x32\x38\x31\x38\x33\x20\x39\x32\x2e\x34\x34\x31\x30\x32\x37\ +\x2c\x36\x32\x31\x2e\x33\x31\x38\x33\x32\x20\x63\x20\x2d\x38\x2e\ +\x38\x32\x34\x32\x37\x37\x2c\x2d\x33\x2e\x35\x31\x38\x35\x37\x20\ +\x2d\x31\x38\x2e\x34\x35\x33\x38\x33\x35\x2c\x2d\x35\x2e\x33\x35\ +\x35\x31\x33\x20\x2d\x32\x38\x2e\x35\x35\x32\x38\x30\x32\x2c\x2d\ +\x35\x2e\x30\x38\x34\x37\x34\x20\x2d\x33\x39\x2e\x37\x38\x32\x37\ +\x37\x32\x2c\x31\x2e\x30\x36\x35\x31\x37\x20\x2d\x37\x31\x2e\x30\ +\x37\x38\x32\x30\x38\x36\x2c\x33\x34\x2e\x31\x34\x31\x36\x31\x20\ +\x2d\x37\x30\x2e\x30\x31\x33\x30\x33\x34\x38\x2c\x37\x33\x2e\x39\ +\x32\x34\x33\x38\x20\x31\x2e\x30\x36\x35\x31\x37\x33\x37\x2c\x33\ +\x39\x2e\x37\x38\x32\x37\x37\x20\x33\x34\x2e\x31\x34\x31\x36\x30\ +\x34\x38\x2c\x37\x31\x2e\x32\x37\x33\x37\x37\x20\x37\x33\x2e\x39\ +\x32\x34\x33\x37\x37\x38\x2c\x37\x30\x2e\x32\x30\x38\x36\x20\x33\ +\x39\x2e\x37\x38\x32\x37\x37\x32\x2c\x2d\x31\x2e\x30\x36\x35\x31\ +\x37\x20\x37\x31\x2e\x32\x37\x33\x37\x38\x32\x2c\x2d\x33\x34\x2e\ +\x33\x33\x37\x31\x38\x20\x37\x30\x2e\x32\x30\x38\x36\x30\x32\x2c\ +\x2d\x37\x34\x2e\x31\x31\x39\x39\x35\x20\x2d\x30\x2e\x31\x30\x34\ +\x33\x37\x2c\x2d\x33\x2e\x38\x39\x37\x39\x36\x20\x2d\x30\x2e\x36\ +\x37\x33\x31\x32\x2c\x2d\x37\x2e\x36\x32\x38\x37\x36\x20\x2d\x31\ +\x2e\x33\x36\x38\x39\x37\x2c\x2d\x31\x31\x2e\x33\x34\x32\x38\x39\ +\x20\x4c\x20\x33\x32\x33\x2e\x34\x30\x35\x38\x31\x2c\x35\x30\x36\ +\x2e\x39\x31\x31\x35\x35\x20\x32\x37\x37\x2e\x30\x35\x36\x34\x2c\ +\x34\x35\x35\x2e\x32\x38\x31\x38\x33\x20\x7a\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x32\x32\ +\x36\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\ +\x63\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\ +\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ " qt_resource_name = "\ @@ -34568,57 +34596,57 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xa9\x69\ -\x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x05\x1a\ -\x00\x00\x07\xfc\x00\x01\x00\x00\x00\x01\x00\x07\x76\xfd\ -\x00\x00\x0a\x1e\x00\x01\x00\x00\x00\x01\x00\x08\x26\x7d\ -\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x50\x01\ -\x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xc6\xb3\ -\x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x40\xc3\ -\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x06\xf0\x82\ -\x00\x00\x08\x96\x00\x01\x00\x00\x00\x01\x00\x07\xb0\x8c\ -\x00\x00\x0a\x6e\x00\x01\x00\x00\x00\x01\x00\x08\x39\xd1\ -\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x1e\x3c\ -\x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x46\x87\ -\x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xb4\x1d\ -\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x23\xbb\ -\x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xdf\x78\ -\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x13\xd0\ -\x00\x00\x09\xa8\x00\x00\x00\x00\x00\x01\x00\x08\x08\xc3\ +\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xbf\xb3\ +\x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x11\x60\ +\x00\x00\x07\xfc\x00\x01\x00\x00\x00\x01\x00\x07\x63\xab\ +\x00\x00\x0a\x1e\x00\x01\x00\x00\x00\x01\x00\x08\x17\xe3\ +\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x5c\x47\ +\x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xdc\xfd\ +\x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x35\x9b\ +\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x07\x06\xcc\ +\x00\x00\x08\x96\x00\x01\x00\x00\x00\x01\x00\x07\x9d\x3a\ +\x00\x00\x0a\x6e\x00\x01\x00\x00\x00\x01\x00\x08\x33\xf3\ +\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x2a\x82\ +\x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x3b\x5f\ +\x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xca\x67\ +\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x30\x01\ +\x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xf5\xc2\ +\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x20\x16\ +\x00\x00\x09\xa8\x00\x00\x00\x00\x00\x01\x00\x07\xfa\x29\ \x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\xaa\ -\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x6b\x20\ -\x00\x00\x09\x60\x00\x01\x00\x00\x00\x01\x00\x07\xf4\xcd\ -\x00\x00\x09\x82\x00\x01\x00\x00\x00\x01\x00\x07\xff\x2f\ -\x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x59\x07\ +\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x77\x66\ +\x00\x00\x09\x60\x00\x01\x00\x00\x00\x01\x00\x07\xe6\x33\ +\x00\x00\x09\x82\x00\x01\x00\x00\x00\x01\x00\x07\xf0\x95\ +\x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x65\x4d\ \x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe3\xf1\ -\x00\x00\x07\xb2\x00\x01\x00\x00\x00\x01\x00\x07\x5a\x72\ -\x00\x00\x08\xf0\x00\x00\x00\x00\x00\x01\x00\x07\xc3\x06\ -\x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x7c\x90\ -\x00\x00\x09\x14\x00\x00\x00\x00\x00\x01\x00\x07\xd9\xb9\ -\x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x12\x9a\ -\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x3f\x23\ -\x00\x00\x0a\x3e\x00\x01\x00\x00\x00\x01\x00\x08\x31\x17\ -\x00\x00\x05\x9c\x00\x01\x00\x00\x00\x01\x00\x06\x93\xcf\ -\x00\x00\x03\x40\x00\x01\x00\x00\x00\x01\x00\x05\xf3\xb1\ -\x00\x00\x0a\x9e\x00\x01\x00\x00\x00\x01\x00\x08\x45\xaa\ -\x00\x00\x09\x38\x00\x01\x00\x00\x00\x01\x00\x07\xec\x90\ -\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x05\xfc\x8b\ -\x00\x00\x08\x1e\x00\x01\x00\x00\x00\x01\x00\x07\x7f\xa6\ -\x00\x00\x09\xce\x00\x00\x00\x00\x00\x01\x00\x08\x11\x50\ -\x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\x9c\x0a\ -\x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x08\xe9\ -\x00\x00\x08\x74\x00\x00\x00\x00\x00\x01\x00\x07\x9b\xfb\ -\x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x45\xc0\ -\x00\x00\x07\x22\x00\x00\x00\x00\x00\x01\x00\x07\x24\x52\ -\x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x77\x11\ -\x00\x00\x08\xc0\x00\x01\x00\x00\x00\x01\x00\x07\xb9\x33\ -\x00\x00\x07\x8a\x00\x01\x00\x00\x00\x01\x00\x07\x4f\x00\ -\x00\x00\x07\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x67\x27\ -\x00\x00\x09\xf4\x00\x01\x00\x00\x00\x01\x00\x08\x1b\xfb\ -\x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x36\xda\ -\x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x84\x75\ -\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xd6\x04\ -\x00\x00\x08\x42\x00\x00\x00\x00\x00\x01\x00\x07\x86\xf7\ +\x00\x00\x07\xb2\x00\x01\x00\x00\x00\x01\x00\x07\x4c\x81\ +\x00\x00\x08\xf0\x00\x00\x00\x00\x00\x01\x00\x07\xad\x82\ +\x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x88\xd6\ +\x00\x00\x09\x14\x00\x00\x00\x00\x00\x01\x00\x07\xc4\x35\ +\x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x1d\x6e\ +\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x4b\x69\ +\x00\x00\x0a\x3e\x00\x00\x00\x00\x00\x01\x00\x08\x22\x7d\ +\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x15\ +\x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x05\xf3\xb1\ +\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\x3f\xcc\ +\x00\x00\x09\x38\x00\x00\x00\x00\x00\x01\x00\x07\xd7\x0c\ +\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x06\x08\xd1\ +\x00\x00\x08\x1e\x00\x01\x00\x00\x00\x01\x00\x07\x6c\x54\ +\x00\x00\x09\xce\x00\x00\x00\x00\x00\x01\x00\x08\x02\xb6\ +\x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\xb2\x54\ +\x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x13\xbd\ +\x00\x00\x08\x74\x00\x00\x00\x00\x00\x01\x00\x07\x88\xa9\ +\x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x52\x06\ +\x00\x00\x07\x22\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x26\ +\x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x83\x57\ +\x00\x00\x08\xc0\x00\x01\x00\x00\x00\x01\x00\x07\xa3\xaf\ +\x00\x00\x07\x8a\x00\x01\x00\x00\x00\x01\x00\x07\x41\x0f\ +\x00\x00\x07\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x53\xd5\ +\x00\x00\x09\xf4\x00\x01\x00\x00\x00\x01\x00\x08\x0d\x61\ +\x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x43\x20\ +\x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x90\xbb\ +\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xec\x4e\ +\x00\x00\x08\x42\x00\x00\x00\x00\x00\x01\x00\x07\x73\xa5\ \x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x05\xcc\x17\ \x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x05\xd5\x2b\ " diff --git a/src/Mod/Draft/Resources/icons/Snap_Angle.svg b/src/Mod/Draft/Resources/icons/Snap_Angle.svg index 279c585690..ed16f54e8a 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Angle.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Angle.svg @@ -15,7 +15,7 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Center.svg" + sodipodi:docname="Snap_Angle.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> image/svg+xml - + @@ -341,119 +341,55 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> + sodipodi:type="arc" + style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="path4313" + sodipodi:cx="31.884087" + sodipodi:cy="31.858782" + sodipodi:rx="19.027601" + sodipodi:ry="19.027601" + d="m 50.911688,31.858782 a 19.027601,19.027601 0 1 1 -38.055203,0 19.027601,19.027601 0 1 1 38.055203,0 z" + transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" /> - - - - - - - - - - - - - - - - + d="m 245.71428,655.2193 a 48.57143,48.57143 0 1 1 -97.14286,0 48.57143,48.57143 0 1 1 97.14286,0 z" + sodipodi:ry="48.57143" + sodipodi:rx="48.57143" + sodipodi:cy="655.2193" + sodipodi:cx="197.14285" + id="path3162-6" + style="color:#000000;fill:#00b286;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:23.16313362;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + sodipodi:type="arc" + transform="matrix(-1.0152816,0.20452475,-0.20130309,-1.0315302,364.95551,1238.6254)" /> + + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Center.svg b/src/Mod/Draft/Resources/icons/Snap_Center.svg index d3fbeb24cb..2471899893 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Center.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Center.svg @@ -15,7 +15,7 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Parallel.svg" + sodipodi:docname="Snap_Center.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> image/svg+xml - + @@ -124,41 +124,20 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> - - - - + style="color:#000000;fill:#00b286;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + d="M 31.75 4.3125 C 16.893974 4.3125 4.875 16.362724 4.875 31.21875 C 4.875 46.074777 16.893974 58.09375 31.75 58.09375 C 46.606026 58.09375 58.65625 46.074777 58.65625 31.21875 C 58.65625 16.362724 46.606026 4.3125 31.75 4.3125 z M 31.75 13.46875 C 41.538951 13.46875 49.5 21.429801 49.5 31.21875 C 49.5 41.007702 41.538951 48.9375 31.75 48.9375 C 21.961049 48.9375 14.03125 41.007702 14.03125 31.21875 C 14.03125 21.429801 21.961049 13.46875 31.75 13.46875 z " + transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" + id="path4364" /> + d="m 245.71428,655.2193 a 48.57143,48.57143 0 1 1 -97.14286,0 48.57143,48.57143 0 1 1 97.14286,0 z" + sodipodi:ry="48.57143" + sodipodi:rx="48.57143" + sodipodi:cy="655.2193" + sodipodi:cx="197.14285" + id="path3162" + style="fill:#00b286;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:30.83979276;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;color:#000000" + sodipodi:type="arc" + transform="matrix(-0.98090505,0.19448714,-0.19448714,-0.98090505,478.13202,1203.4409)" /> diff --git a/src/Mod/Draft/Resources/icons/Snap_Endpoint.svg b/src/Mod/Draft/Resources/icons/Snap_Endpoint.svg index 853c845646..c2646f3bbb 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Endpoint.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Endpoint.svg @@ -15,7 +15,7 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Draft_Line.svg" + sodipodi:docname="Snap_Endpoint.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> + image/svg+xml - + @@ -100,77 +111,11 @@ - - - - - - - - - - - - - - + diff --git a/src/Mod/Draft/Resources/icons/Snap_Extension.svg b/src/Mod/Draft/Resources/icons/Snap_Extension.svg index 5202b9938d..3614773f8f 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Extension.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Extension.svg @@ -15,7 +15,7 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Angle.svg" + sodipodi:docname="Snap_Extension.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> image/svg+xml - + @@ -272,43 +272,35 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> - - - - - + d="m 245.71428,655.2193 a 48.57143,48.57143 0 1 1 -97.14286,0 48.57143,48.57143 0 1 1 97.14286,0 z" + sodipodi:ry="48.57143" + sodipodi:rx="48.57143" + sodipodi:cy="655.2193" + sodipodi:cx="197.14285" + id="path3162" + style="color:#000000;fill:#00b286;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:23.1889267;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + sodipodi:type="arc" + transform="matrix(-0.78922717,-0.47204736,0.48386925,-0.79797851,131.3483,1222.7997)" /> + + diff --git a/src/Mod/Draft/Resources/icons/Snap_Grid.svg b/src/Mod/Draft/Resources/icons/Snap_Grid.svg index 4408922fe7..ad29fdc4f4 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Grid.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Grid.svg @@ -15,7 +15,7 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Perpendicular.svg" + sodipodi:docname="Snap_Grid.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> image/svg+xml - + @@ -113,41 +113,13 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> - - - - - + sodipodi:type="inkscape:offset" + inkscape:radius="2.8284271" + inkscape:original="M 12.90625 7.03125 L 12.90625 16 L 4.9375 16 L 4.9375 21.65625 L 12.90625 21.65625 L 12.90625 46 L 4.9375 46 L 4.9375 51.65625 L 12.90625 51.65625 L 12.90625 58.46875 L 18.5625 58.46875 L 18.5625 51.65625 L 40.90625 51.65625 L 40.90625 58.46875 L 46.5625 58.46875 L 46.5625 51.65625 L 56.125 51.65625 L 56.125 46 L 46.5625 46 L 46.5625 21.65625 L 56.125 21.65625 L 56.125 16 L 46.5625 16 L 46.5625 7.03125 L 40.90625 7.03125 L 40.90625 16 L 18.5625 16 L 18.5625 7.03125 L 12.90625 7.03125 z M 18.5625 21.65625 L 40.90625 21.65625 L 40.90625 46 L 18.5625 46 L 18.5625 21.65625 z " + style="color:#000000;fill:#00b286;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:4.00000003;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="path3775" + d="M 12.90625,4.1875 A 2.8287099,2.8287099 0 0 0 10.0625,7.03125 l 0,6.125 -5.125,0 A 2.8287099,2.8287099 0 0 0 2.09375,16 l 0,5.65625 A 2.8287099,2.8287099 0 0 0 4.9375,24.5 l 5.125,0 0,18.65625 -5.125,0 A 2.8287099,2.8287099 0 0 0 2.09375,46 l 0,5.65625 A 2.8287099,2.8287099 0 0 0 4.9375,54.5 l 5.125,0 0,3.96875 a 2.8287099,2.8287099 0 0 0 2.84375,2.84375 l 5.65625,0 a 2.8287099,2.8287099 0 0 0 2.84375,-2.84375 l 0,-3.96875 16.65625,0 0,3.96875 a 2.8287099,2.8287099 0 0 0 2.84375,2.84375 l 5.65625,0 a 2.8287099,2.8287099 0 0 0 2.84375,-2.84375 l 0,-3.96875 6.71875,0 a 2.8287099,2.8287099 0 0 0 2.84375,-2.84375 l 0,-5.65625 A 2.8287099,2.8287099 0 0 0 56.125,43.15625 l -6.71875,0 0,-18.65625 6.71875,0 a 2.8287099,2.8287099 0 0 0 2.84375,-2.84375 l 0,-5.65625 A 2.8287099,2.8287099 0 0 0 56.125,13.15625 l -6.71875,0 0,-6.125 A 2.8287099,2.8287099 0 0 0 46.5625,4.1875 l -5.65625,0 A 2.8287099,2.8287099 0 0 0 38.0625,7.03125 l 0,6.125 -16.65625,0 0,-6.125 A 2.8287099,2.8287099 0 0 0 18.5625,4.1875 l -5.65625,0 z m 8.5,20.3125 16.65625,0 0,18.65625 -16.65625,0 0,-18.65625 z" + transform="matrix(6.1679584,0,0,6.1679584,-28.130145,407.75637)" /> diff --git a/src/Mod/Draft/Resources/icons/Snap_Intersection.svg b/src/Mod/Draft/Resources/icons/Snap_Intersection.svg index f2086928a6..2f14be47dc 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Intersection.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Intersection.svg @@ -15,7 +15,7 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Grid.svg" + sodipodi:docname="Snap_Intersection.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> image/svg+xml - + @@ -124,52 +124,10 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> - - - - - - + style="color:#000000;fill:#00b286;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:5.00000003;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + d="M 14.4375 4.78125 L 4.65625 14.5625 L 22 31.90625 L 4.65625 49.25 L 14.4375 59.03125 L 31.78125 41.6875 L 49.125 59.03125 L 58.90625 49.25 L 41.5625 31.90625 L 58.90625 14.5625 L 49.125 4.78125 L 31.78125 22.125 L 14.4375 4.78125 z " + transform="matrix(6.1679584,0,0,6.1679584,-39.231908,407.75637)" + id="rect3942-4-9" /> diff --git a/src/Mod/Draft/Resources/icons/Snap_Midpoint.svg b/src/Mod/Draft/Resources/icons/Snap_Midpoint.svg index 31ce4eb424..ce2b5e7440 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Midpoint.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Midpoint.svg @@ -15,7 +15,7 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Endpoint.svg" + sodipodi:docname="Snap_Midpoint.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> - image/svg+xml - + @@ -135,44 +124,10 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> - - - - - + inkscape:connector-curvature="0" /> diff --git a/src/Mod/Draft/Resources/icons/Snap_Ortho.svg b/src/Mod/Draft/Resources/icons/Snap_Ortho.svg index 6b2a6e75c1..14ca56c127 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Ortho.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Ortho.svg @@ -15,23 +15,11 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Extension.svg" + sodipodi:docname="Snap_Ortho.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> - - - - - image/svg+xml - + @@ -251,42 +228,10 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> - - - - - diff --git a/src/Mod/Draft/Resources/icons/Snap_Parallel.svg b/src/Mod/Draft/Resources/icons/Snap_Parallel.svg index 0cb69485c2..ab186c586b 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Parallel.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Parallel.svg @@ -15,23 +15,11 @@ id="svg2726" sodipodi:version="0.32" inkscape:version="0.48.1 r9760" - sodipodi:docname="Snap_Intersection.svg" + sodipodi:docname="Snap_Parallel.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1"> - - - - - image/svg+xml - + @@ -112,53 +89,22 @@ - - - - - + width="293.52496" + height="62.37265" + x="-604.0174" + y="-384.45615" + transform="matrix(-0.84132762,-0.54052551,0.53359904,-0.84573759,0,0)" /> + style="color:#000000;fill:#00b286;fill-opacity:1;fill-rule:nonzero;stroke:#002e2e;stroke-width:27.8452301;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect3942-4-9-9" + width="293.52496" + height="62.37265" + x="-603.26886" + y="-520.99738" + transform="matrix(-0.84132761,-0.54052553,0.53359906,-0.84573758,0,0)" /> diff --git a/src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg b/src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg index 2401df9590..8dc363effe 100644 --- a/src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg +++ b/src/Mod/Draft/Resources/icons/Snap_Perpendicular.svg @@ -78,7 +78,7 @@ image/svg+xml - + @@ -90,51 +90,10 @@ id="g4289" transform="matrix(0.1621282,0,0,0.1621282,6.3605986,-66.108806)"> - - - - - - + inkscape:connector-curvature="0" /> From 1f690c0c817500159c078f2d91ee15a7ebda3cc9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 14 Mar 2012 08:52:42 +0100 Subject: [PATCH 016/351] Fix bug with identifying SWIG version --- src/Base/Interpreter.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index 6e31a38103..0a8c4b9e8b 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -598,21 +598,21 @@ bool InterpreterSingleton::convertSWIGPointerObj(const char* Module, const char* int result = 0; PyGILStateLocker locker; int version = getSWIGVersionFromModule(Module); - switch (version&0xff) + switch (version) { - case 25: + case 66329: result = Swig_1_3_25::convertSWIGPointerObj_T(TypeName, obj, ptr, flags); break; - case 33: + case 66337: result = Swig_1_3_33::convertSWIGPointerObj_T(TypeName, obj, ptr, flags); break; - case 36: + case 66340: result = Swig_1_3_36::convertSWIGPointerObj_T(TypeName, obj, ptr, flags); break; - case 38: + case 66342: result = Swig_1_3_38::convertSWIGPointerObj_T(TypeName, obj, ptr, flags); break; - case 40: + case 66344: result = Swig_1_3_40::convertSWIGPointerObj_T(TypeName, obj, ptr, flags); break; default: From 13e5e28625e5d47d03e5a77eacecd89d88d71005 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 14 Mar 2012 13:27:07 -0300 Subject: [PATCH 017/351] Small improvements to sphinx API docs generator --- src/Doc/sphinx/Arch.rst | 23 +++++++++++++---------- src/Doc/sphinx/Draft.rst | 22 ++++++++++++---------- src/Doc/sphinx/FreeCAD.rst | 4 +++- src/Mod/Draft/DraftSnap.py | 11 +++++++++-- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/Doc/sphinx/Arch.rst b/src/Doc/sphinx/Arch.rst index c126eb3271..e89fca847b 100644 --- a/src/Doc/sphinx/Arch.rst +++ b/src/Doc/sphinx/Arch.rst @@ -1,7 +1,7 @@ The Arch module =============== -The Arch module is a metamodule that imports useful methods from several of the Arch submodules. +The Arch module is a metamodule that imports useful methods from several of the Arch submodules. You can invoke the following methods either from their specific submodule (ArchWall.areSameWallTypes()) or from the Arch module itself (Arch.areSameWallTypes()). .. toctree:: :maxdepth: 4 @@ -9,29 +9,32 @@ The Arch module is a metamodule that imports useful methods from several of the .. automodule:: Arch :members: -.. automodule:: Wall +.. automodule:: ArchWall :members: -.. automodule:: Cell +.. automodule:: ArchCell :members: -.. automodule:: Floor +.. automodule:: ArchFloor :members: -.. automodule:: Site +.. automodule:: ArchSite :members: -.. automodule:: Structure +.. automodule:: ArchStructure :members: -.. automodule:: Window +.. automodule:: ArchWindow :members: -.. automodule:: SectionPlane +.. automodule:: ArchSectionPlane :members: -.. automodule:: Building +.. automodule:: ArchBuilding :members: -.. automodule:: Commands +.. automodule:: ArchCommands + :members: + +.. automodule:: ArchAxis :members: diff --git a/src/Doc/sphinx/Draft.rst b/src/Doc/sphinx/Draft.rst index 542acff0bc..2b41017809 100644 --- a/src/Doc/sphinx/Draft.rst +++ b/src/Doc/sphinx/Draft.rst @@ -1,19 +1,21 @@ The Draft module ================ -The Draft module offer several convenient functions to work with simple 2D and 3D objects. -These functions can be used in scripts and macros or from the python interpreter, once the Draft module has been imported. - -Example:: - - import FreeCAD - from Draft import * - myrect = makeRectangle(4,3) - mydistance = FreeCAD.Vector(2,2,0) - move(myrect,mydistance) +The Draft module offer several convenient functions to work with simple objects. .. toctree:: :maxdepth: 4 .. automodule:: Draft :members: + +.. automodule:: DraftSnap + :members: + +The draftlibs contain two submodules, widely used throughout the Draft module: fcvec, which contains useful methods for dealing with vectors, and fcgeo, which offers many tools for working with Part shape objects. + +.. automodule:: draftlibs.fcvec + :members: + +.. automodule:: draftlibs.fcgeo + :members: \ No newline at end of file diff --git a/src/Doc/sphinx/FreeCAD.rst b/src/Doc/sphinx/FreeCAD.rst index cb37b3c4d2..eff8e09cfe 100644 --- a/src/Doc/sphinx/FreeCAD.rst +++ b/src/Doc/sphinx/FreeCAD.rst @@ -6,7 +6,6 @@ The FreeCAD module .. automodule:: FreeCAD :members: - :show-inheritance: .. autoclass:: Vector :members: @@ -16,3 +15,6 @@ The FreeCAD module .. autoclass:: Placement :members: + + .. autoclass:: Console + :members: diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index c14841f911..d3e8488f47 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -47,6 +47,9 @@ class Snapper: the form [real_point,marker_type,visual_point], and are not meant to be used directly, they are all called when necessary by the general snap() function. + + The Snapper lives inside FreeCADGui once the Draft module has been + loaded. """ @@ -661,7 +664,8 @@ class Snapper: def getPoint(self,last=None,callback=None,movecallback=None,extradlg=None): - """getPoint([last],[callback],[movecallback],[extradlg]) : gets a 3D point + """ + getPoint([last],[callback],[movecallback],[extradlg]) : gets a 3D point from the screen. You can provide an existing point, in that case additional snap options and a tracker are available. You can also pass a function as callback, which will get called @@ -675,10 +679,13 @@ class Snapper: def cb(point): if point: print "got a 3D point: ",point + FreeCADGui.Snapper.getPoint(callback=cb) If the callback function accepts more than one argument, it will also receive - the last snapped object. Finally, a pyqt dialog can be passed as extra taskbox.""" + the last snapped object. Finally, a pyqt dialog can be passed as extra taskbox. + + """ import inspect From 3beef4aa3c1ddf4fb24eb1483afb6d9344503357 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 15 Mar 2012 18:28:26 +0100 Subject: [PATCH 018/351] Allow to import from HomePath/icons before loading builtin icons --- src/Gui/BitmapFactory.cpp | 47 ++++++++++++++++++++++++++------------- src/Gui/BitmapFactory.h | 1 + 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/Gui/BitmapFactory.cpp b/src/Gui/BitmapFactory.cpp index 0b2699bf26..9b781a4d07 100644 --- a/src/Gui/BitmapFactory.cpp +++ b/src/Gui/BitmapFactory.cpp @@ -87,10 +87,10 @@ BitmapFactoryInst& BitmapFactoryInst::instance(void) } _pcSingleton->addPath(path); } + _pcSingleton->addPath(QString::fromAscii("%1/icons").arg(QString::fromUtf8(App::GetApplication().GetHomePath()))); + _pcSingleton->addPath(QString::fromAscii("%1/icons").arg(QString::fromUtf8(App::GetApplication().Config()["UserAppData"].c_str()))); _pcSingleton->addPath(QLatin1String(":/icons/")); _pcSingleton->addPath(QLatin1String(":/Icons/")); - _pcSingleton->addPath(QString::fromUtf8(App::GetApplication().GetHomePath())); - _pcSingleton->addPath(QString::fromUtf8(App::GetApplication().Config()["UserAppData"].c_str())); RegisterIcons(); } @@ -189,6 +189,27 @@ bool BitmapFactoryInst::findPixmapInCache(const char* name, QPixmap& px) const return false; } +bool BitmapFactoryInst::loadPixmap(const QString& filename, QPixmap& icon) const +{ + QFileInfo fi(filename); + if (fi.exists()) { + // first check if it's an SVG because Qt's qsvg4 module shouldn't be used therefore + if (fi.suffix().toLower() == QLatin1String("svg")) { + QFile svgFile(filename); + if (svgFile.open(QFile::ReadOnly | QFile::Text)) { + QByteArray content = svgFile.readAll(); + icon = pixmapFromSvg(content, QSize(64,64)); + } + } + else { + // try with Qt plugins + icon.load(filename); + } + } + + return !icon.isNull(); +} + QPixmap BitmapFactoryInst::pixmap(const char* name) const { if (!name || *name == '\0') @@ -205,33 +226,29 @@ QPixmap BitmapFactoryInst::pixmap(const char* name) const if (It != d->xpmMap.end()) icon = QPixmap(It.value()); - // If an absolute path is given + // Try whether an absolute path is given QString fn = QString::fromUtf8(name); - if (icon.isNull() && QFile(fn).exists()) - icon.load(fn); - - // first check if it's an SVG because Qt's qsvg4 module shouldn't be used therefore - if (icon.isNull()) { - icon = pixmapFromSvg(name, QSize(64,64)); - } + if (icon.isNull()) + loadPixmap(fn, icon); // try to find it in the given directories if (icon.isNull()) { bool found = false; QList formats = QImageReader::supportedImageFormats(); + formats.prepend("SVG"); // check first for SVG to use special import mechanism for (QStringList::ConstIterator pt = d->paths.begin(); pt != d->paths.end() && !found; ++pt) { QDir d(*pt); QString fileName = d.filePath(fn); - if (QFile(fileName).exists()) { - icon.load(fileName); + if (loadPixmap(fileName, icon)) { found = true; break; - } else { + } + else { + // Go through supported file formats for (QList::iterator fm = formats.begin(); fm != formats.end(); ++fm) { QString path = QString::fromAscii("%1.%2").arg(fileName). arg(QString::fromAscii((*fm).toLower().constData())); - if (QFile(path).exists()) { - icon.load(path); + if (loadPixmap(path, icon)) { found = true; break; } diff --git a/src/Gui/BitmapFactory.h b/src/Gui/BitmapFactory.h index 822156ab7b..4579c7b741 100644 --- a/src/Gui/BitmapFactory.h +++ b/src/Gui/BitmapFactory.h @@ -124,6 +124,7 @@ public: void convert(const SoSFImage& img, QImage& out) const; private: + bool loadPixmap(const QString& path, QPixmap&) const; void restoreCustomPaths(); static BitmapFactoryInst* _pcSingleton; From 8bb7636bd745d28c9aad720d6408a5d742f5bb57 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 16 Mar 2012 18:29:56 -0300 Subject: [PATCH 019/351] Improvements in Draft Snap + fixed bug in parallel/extension button + added button for passive snap + fixed snap toolbar appearing outside the FreeCAD window --- src/Mod/Draft/DraftSnap.py | 89 +++--- src/Mod/Draft/Draft_rc.py | 308 ++++++++++++++++++-- src/Mod/Draft/Resources/Draft.qrc | 1 + src/Mod/Draft/Resources/icons/Snap_Near.svg | 112 +++++++ 4 files changed, 445 insertions(+), 65 deletions(-) create mode 100644 src/Mod/Draft/Resources/icons/Snap_Near.svg diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index d3e8488f47..e142699015 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -73,6 +73,8 @@ class Snapper: self.trackLine = None self.lastSnappedObject = None self.active = True + + self.polarAngles = [90,45] # the snapmarker has "dot","circle" and "square" available styles self.mk = {'passive':'circle', @@ -86,7 +88,7 @@ class Snapper: 'center':'dot', 'ortho':'dot', 'intersection':'dot'} - self.cursors = {'passive':None, + self.cursors = {'passive':':/icons/Snap_Near.svg', 'extension':':/icons/Snap_Extension.svg', 'parallel':':/icons/Snap_Parallel.svg', 'grid':':/icons/Snap_Grid.svg', @@ -282,7 +284,7 @@ class Snapper: if self.radius: dv = point.sub(winner[2]) if (dv.Length > self.radius): - if not oldActive: + if (not oldActive) and self.isEnabled("passive"): winner = self.snapToVertex(info) # setting the cursors @@ -304,18 +306,19 @@ class Snapper: def snapToExtensions(self,point,last,constrain,eline): "returns a point snapped to extension or parallel line to last object, if any" - tsnap = self.snapToExtOrtho(last,constrain,eline) - if tsnap: - if (tsnap[0].sub(point)).Length < self.radius: - if self.tracker: - self.tracker.setCoords(tsnap[2]) - self.tracker.setMarker(self.mk[tsnap[1]]) - self.tracker.on() - if self.extLine: - self.extLine.p2(tsnap[2]) - self.extLine.on() - self.setCursor(tsnap[1]) - return tsnap[2],eline + if self.isEnabled("extension"): + tsnap = self.snapToExtOrtho(last,constrain,eline) + if tsnap: + if (tsnap[0].sub(point)).Length < self.radius: + if self.tracker: + self.tracker.setCoords(tsnap[2]) + self.tracker.setMarker(self.mk[tsnap[1]]) + self.tracker.on() + if self.extLine: + self.extLine.p2(tsnap[2]) + self.extLine.on() + self.setCursor(tsnap[1]) + return tsnap[2],eline for o in [self.lastObj[1],self.lastObj[0]]: if o: @@ -329,40 +332,41 @@ class Snapper: np = self.getPerpendicular(e,point) if not fcgeo.isPtOnEdge(np,e): if (np.sub(point)).Length < self.radius: - if np != e.Vertexes[0].Point: - if self.tracker: - self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['extension']) - self.tracker.on() - if self.extLine: - self.extLine.p1(e.Vertexes[0].Point) - self.extLine.p2(np) - self.extLine.on() - self.setCursor('extension') - return np,Part.Line(e.Vertexes[0].Point,np).toShape() - else: - if last: - de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() - np = self.getPerpendicular(de,point) - if (np.sub(point)).Length < self.radius: + if self.isEnabled('extension'): + if np != e.Vertexes[0].Point: if self.tracker: self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['parallel']) + self.tracker.setMarker(self.mk['extension']) self.tracker.on() + if self.extLine: + self.extLine.p1(e.Vertexes[0].Point) + self.extLine.p2(np) + self.extLine.on() self.setCursor('extension') - return np,de + return np,Part.Line(e.Vertexes[0].Point,np).toShape() + else: + if self.isEnabled('parallel'): + if last: + de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() + np = self.getPerpendicular(de,point) + if (np.sub(point)).Length < self.radius: + if self.tracker: + self.tracker.setCoords(np) + self.tracker.setMarker(self.mk['parallel']) + self.tracker.on() + self.setCursor('parallel') + return np,de return point,eline def snapToPolar(self,point,last): "snaps to polar lines from the given point" - if self.isEnabled('ortho'): - polarAngles = [90,45] + if self.isEnabled('ortho'): if last: vecs = [] ax = [FreeCAD.DraftWorkingPlane.u, FreeCAD.DraftWorkingPlane.v, FreeCAD.DraftWorkingPlane.axis] - for a in polarAngles: + for a in self.polarAngles: if a == 90: vecs.extend([ax[0],fcvec.neg(ax[0])]) vecs.extend([ax[1],fcvec.neg(ax[1])]) @@ -544,8 +548,10 @@ class Snapper: return [p,'endpoint',p] else: return [] - else: + elif self.isEnabled("passive"): return [p,'passive',p] + else: + return [] def getScreenDist(self,dist,cursor): "returns a distance in 3D space from a screen pixels distance" @@ -787,7 +793,6 @@ class Snapper: self.toolbar.hide() def toggle(self,checked=None): - print "checked",checked if hasattr(self,"toolbarButtons"): if checked == None: self.masterbutton.toggle() @@ -811,11 +816,13 @@ class Snapper: def show(self): "shows the toolbar" - if hasattr(self,"toolbar"): - self.toolbar.show() - else: + if not hasattr(self,"toolbar"): self.makeSnapToolBar() - self.toolbar.show() + mw = getMainWindow() + bt = mw.findChild(QtGui.QToolBar,"Draft Snap") + if not bt: + mw.addToolBar(self.toolbar) + self.toolbar.show() if not hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper = Snapper() diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 560fa03cc5..66a43f5767 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Tue Mar 13 18:19:12 2012 +# Created: Fri Mar 16 17:36:21 2012 # by: The Resource Compiler for PyQt (Qt v4.7.4) # # WARNING! All changes made in this file will be lost! @@ -29840,6 +29840,261 @@ qt_resource_data = "\ \x37\x86\x80\x57\xa6\x87\x7c\x67\x4c\x1e\xde\xa8\x39\x6c\x93\xe4\ \xc2\x80\xb9\xb8\x23\xb2\x12\x54\x8d\x96\xe1\xc5\x92\x34\x5d\x01\ \xb7\xa5\x6a\xde\x87\xd9\x3f\xeb\x1f\x07\xd5\ +\x00\x00\x0f\xce\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\ +\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\ +\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\ +\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\ +\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\ +\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\ +\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ +\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ +\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ +\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ +\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ +\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\ +\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\ +\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x70\x78\ +\x22\x0a\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ +\x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x37\x32\ +\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x33\x32\x22\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\ +\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\x30\x22\ +\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\x63\ +\x6e\x61\x6d\x65\x3d\x22\x53\x6e\x61\x70\x5f\x50\x61\x72\x61\x6c\ +\x6c\x65\x6c\x2e\x73\x76\x67\x22\x0a\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x6f\x75\x74\x70\x75\x74\x5f\x65\x78\x74\x65\ +\x6e\x73\x69\x6f\x6e\x3d\x22\x6f\x72\x67\x2e\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x2e\x6f\x75\x74\x70\x75\x74\x2e\x73\x76\x67\x2e\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x22\x0a\x20\x20\x20\x76\x65\x72\x73\ +\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x3e\x0a\x20\x20\x3c\x64\x65\ +\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\x73\ +\x32\x37\x32\x38\x22\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\ +\x3a\x74\x79\x70\x65\x3d\x22\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x70\x65\x72\x73\x70\x33\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\ +\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\ +\x22\x30\x20\x3a\x20\x31\x30\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\ +\x70\x5f\x7a\x3d\x22\x36\x34\x20\x3a\x20\x33\x32\x20\x3a\x20\x31\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x70\x65\x72\x73\x70\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\ +\x3d\x22\x33\x32\x20\x3a\x20\x32\x31\x2e\x33\x33\x33\x33\x33\x33\ +\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x32\x37\x33\x34\ +\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x72\x61\x64\x69\x61\x6c\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\ +\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\ +\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\ +\x2d\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x72\ +\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x35\ +\x30\x2d\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\ +\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\ +\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\ +\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2c\x30\x2c\ +\x30\x2c\x30\x2e\x36\x39\x38\x35\x32\x39\x34\x2c\x30\x2c\x32\x30\ +\x32\x2e\x38\x32\x38\x36\x33\x29\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x63\x78\x3d\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x63\x79\x3d\x22\x36\x37\x32\x2e\x37\ +\x39\x37\x33\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x66\x78\x3d\ +\x22\x32\x32\x35\x2e\x32\x36\x34\x30\x32\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x66\x79\x3d\x22\x36\x37\x32\x2e\x37\x39\x37\x33\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x72\x3d\x22\x33\x34\x2e\x33\ +\x34\x35\x31\x38\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\ +\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\ +\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\ +\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x31\x34\x34\x2d\x34\x22\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x36\x2d\x32\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x31\x34\x38\x2d\x30\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ +\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\ +\x0a\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\ +\x65\x64\x76\x69\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x62\x61\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\ +\x6f\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\ +\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\ +\x22\x23\x36\x36\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\ +\x6f\x72\x64\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\ +\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x70\x61\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\ +\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x70\x61\x67\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\ +\x6f\x6d\x3d\x22\x33\x2e\x38\x38\x39\x30\x38\x37\x33\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\ +\x22\x32\x38\x2e\x31\x31\x37\x31\x32\x36\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x35\x33\ +\x2e\x36\x36\x35\x37\x37\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\ +\x61\x79\x65\x72\x3d\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\ +\x20\x20\x73\x68\x6f\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\ +\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x67\x72\x69\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\ +\x32\x38\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\ +\x3d\x22\x37\x35\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\ +\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x77\x69\x6e\x64\x6f\x77\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\ +\x6f\x77\x2d\x6d\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\ +\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\ +\x61\x32\x37\x33\x31\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\ +\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\ +\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\ +\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\ +\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\ +\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\ +\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\ +\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\ +\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\ +\x3c\x2f\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\ +\x20\x20\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\ +\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\ +\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\ +\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\ +\x62\x65\x6c\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\ +\x70\x6d\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\ +\x20\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\ +\x22\x67\x34\x32\x38\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x74\ +\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\ +\x28\x30\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x30\x2c\x30\x2c\x30\ +\x2e\x31\x36\x32\x31\x32\x38\x32\x2c\x36\x2e\x33\x36\x30\x35\x39\ +\x38\x36\x2c\x2d\x36\x36\x2e\x31\x30\x38\x38\x30\x36\x29\x22\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\ +\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\ +\x23\x30\x30\x62\x32\x38\x36\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\ +\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\ +\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\ +\x23\x30\x30\x32\x65\x32\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\ +\x69\x64\x74\x68\x3a\x32\x37\x2e\x38\x34\x35\x32\x33\x30\x31\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\ +\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ +\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\ +\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ +\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\ +\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\ +\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\ +\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\ +\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\ +\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\ +\x64\x3d\x22\x72\x65\x63\x74\x33\x39\x34\x32\x2d\x34\x2d\x39\x2d\ +\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\ +\x68\x3d\x22\x32\x39\x33\x2e\x35\x32\x34\x39\x36\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\ +\x32\x2e\x33\x37\x32\x36\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x20\x20\x78\x3d\x22\x2d\x36\x31\x33\x2e\x39\x39\x39\x36\x39\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x2d\x35\x31\ +\x34\x2e\x31\x33\x39\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\ +\x69\x78\x28\x2d\x30\x2e\x38\x34\x31\x33\x32\x37\x36\x31\x2c\x2d\ +\x30\x2e\x35\x34\x30\x35\x32\x35\x35\x33\x2c\x30\x2e\x35\x33\x33\ +\x35\x39\x39\x30\x36\x2c\x2d\x30\x2e\x38\x34\x35\x37\x33\x37\x35\ +\x38\x2c\x30\x2c\x30\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\ +\x72\x63\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\ +\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\ +\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x62\x32\x38\x36\x3b\x66\ +\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\ +\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\ +\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x32\x65\x32\x65\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x2e\x39\x31\ +\x37\x39\x38\x38\x33\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ +\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\ +\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\ +\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\ +\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\ +\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\ +\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\ +\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\ +\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\ +\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\ +\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\ +\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\ +\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x32\x39\x39\ +\x38\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\ +\x70\x6f\x64\x69\x3a\x63\x78\x3d\x22\x33\x32\x2e\x30\x31\x32\x36\ +\x35\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\ +\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\x32\x36\x2e\x35\x38\x37\ +\x36\x32\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x6f\ +\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\x38\x2e\x38\x37\x30\ +\x39\x37\x36\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ +\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x38\x2e\x38\x37\ +\x30\x39\x37\x36\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x64\x3d\x22\x6d\x20\x34\x30\x2e\x38\x38\x33\x36\x33\x2c\x32\x36\ +\x2e\x35\x38\x37\x36\x32\x34\x20\x61\x20\x38\x2e\x38\x37\x30\x39\ +\x37\x36\x34\x2c\x38\x2e\x38\x37\x30\x39\x37\x36\x34\x20\x30\x20\ +\x31\x20\x31\x20\x2d\x31\x37\x2e\x37\x34\x31\x39\x35\x33\x2c\x30\ +\x20\x38\x2e\x38\x37\x30\x39\x37\x36\x34\x2c\x38\x2e\x38\x37\x30\ +\x39\x37\x36\x34\x20\x30\x20\x31\x20\x31\x20\x31\x37\x2e\x37\x34\ +\x31\x39\x35\x33\x2c\x30\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\ +\x74\x72\x69\x78\x28\x36\x2e\x31\x36\x37\x39\x35\x38\x34\x2c\x30\ +\x2c\x30\x2c\x36\x2e\x31\x36\x37\x39\x35\x38\x34\x2c\x33\x33\x2e\ +\x37\x32\x32\x35\x30\x36\x2c\x33\x34\x35\x2e\x39\x30\x33\x37\x31\ +\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\ +\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ \x00\x00\x0b\x6e\ \x00\ \x00\x2d\x39\x78\x9c\xed\x5a\x6d\x6f\xdb\xc8\x11\xfe\x9e\x5f\xc1\ @@ -34473,6 +34728,10 @@ qt_resource_name = "\ \x03\xfe\xc1\x67\ \x00\x53\ \x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x4f\x00\x72\x00\x74\x00\x68\x00\x6f\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0d\ +\x0f\x15\x93\x27\ +\x00\x53\ +\x00\x6e\x00\x61\x00\x70\x00\x5f\x00\x4e\x00\x65\x00\x61\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x11\ \x0d\x09\x0b\xe7\ \x00\x44\ @@ -34571,8 +34830,8 @@ qt_resource_name = "\ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\ -\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x4d\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x33\x00\x00\x00\x1a\ +\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x4e\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x34\x00\x00\x00\x1a\ \x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x15\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x10\x00\x00\x00\x05\ \x00\x00\x02\x72\x00\x01\x00\x00\x00\x01\x00\x05\x98\x94\ @@ -34598,55 +34857,56 @@ qt_resource_struct = "\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ \x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xbf\xb3\ \x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x11\x60\ -\x00\x00\x07\xfc\x00\x01\x00\x00\x00\x01\x00\x07\x63\xab\ -\x00\x00\x0a\x1e\x00\x01\x00\x00\x00\x01\x00\x08\x17\xe3\ +\x00\x00\x08\x1c\x00\x01\x00\x00\x00\x01\x00\x07\x73\x7d\ +\x00\x00\x0a\x3e\x00\x01\x00\x00\x00\x01\x00\x08\x27\xb5\ \x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x5c\x47\ \x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xdc\xfd\ \x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x35\x9b\ \x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x07\x06\xcc\ -\x00\x00\x08\x96\x00\x01\x00\x00\x00\x01\x00\x07\x9d\x3a\ -\x00\x00\x0a\x6e\x00\x01\x00\x00\x00\x01\x00\x08\x33\xf3\ +\x00\x00\x08\xb6\x00\x01\x00\x00\x00\x01\x00\x07\xad\x0c\ +\x00\x00\x0a\x8e\x00\x01\x00\x00\x00\x01\x00\x08\x43\xc5\ \x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x2a\x82\ \x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x3b\x5f\ \x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xca\x67\ \x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x30\x01\ \x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xf5\xc2\ \x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x20\x16\ -\x00\x00\x09\xa8\x00\x00\x00\x00\x00\x01\x00\x07\xfa\x29\ +\x00\x00\x09\xc8\x00\x00\x00\x00\x00\x01\x00\x08\x09\xfb\ \x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\xaa\ \x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x77\x66\ -\x00\x00\x09\x60\x00\x01\x00\x00\x00\x01\x00\x07\xe6\x33\ -\x00\x00\x09\x82\x00\x01\x00\x00\x00\x01\x00\x07\xf0\x95\ +\x00\x00\x09\x80\x00\x01\x00\x00\x00\x01\x00\x07\xf6\x05\ +\x00\x00\x09\xa2\x00\x01\x00\x00\x00\x01\x00\x08\x00\x67\ \x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x65\x4d\ \x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe3\xf1\ -\x00\x00\x07\xb2\x00\x01\x00\x00\x00\x01\x00\x07\x4c\x81\ -\x00\x00\x08\xf0\x00\x00\x00\x00\x00\x01\x00\x07\xad\x82\ +\x00\x00\x07\xd2\x00\x01\x00\x00\x00\x01\x00\x07\x5c\x53\ +\x00\x00\x09\x10\x00\x00\x00\x00\x00\x01\x00\x07\xbd\x54\ \x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x88\xd6\ -\x00\x00\x09\x14\x00\x00\x00\x00\x00\x01\x00\x07\xc4\x35\ +\x00\x00\x09\x34\x00\x00\x00\x00\x00\x01\x00\x07\xd4\x07\ \x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x1d\x6e\ \x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x4b\x69\ -\x00\x00\x0a\x3e\x00\x00\x00\x00\x00\x01\x00\x08\x22\x7d\ +\x00\x00\x0a\x5e\x00\x00\x00\x00\x00\x01\x00\x08\x32\x4f\ \x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x15\ \x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x05\xf3\xb1\ -\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\x3f\xcc\ -\x00\x00\x09\x38\x00\x00\x00\x00\x00\x01\x00\x07\xd7\x0c\ +\x00\x00\x0a\xbe\x00\x00\x00\x00\x00\x01\x00\x08\x4f\x9e\ +\x00\x00\x09\x58\x00\x00\x00\x00\x00\x01\x00\x07\xe6\xde\ \x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x06\x08\xd1\ -\x00\x00\x08\x1e\x00\x01\x00\x00\x00\x01\x00\x07\x6c\x54\ -\x00\x00\x09\xce\x00\x00\x00\x00\x00\x01\x00\x08\x02\xb6\ +\x00\x00\x08\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x7c\x26\ +\x00\x00\x09\xee\x00\x00\x00\x00\x00\x01\x00\x08\x12\x88\ \x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\xb2\x54\ \x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x13\xbd\ -\x00\x00\x08\x74\x00\x00\x00\x00\x00\x01\x00\x07\x88\xa9\ +\x00\x00\x08\x94\x00\x00\x00\x00\x00\x01\x00\x07\x98\x7b\ \x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x52\x06\ \x00\x00\x07\x22\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x26\ \x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x83\x57\ -\x00\x00\x08\xc0\x00\x01\x00\x00\x00\x01\x00\x07\xa3\xaf\ -\x00\x00\x07\x8a\x00\x01\x00\x00\x00\x01\x00\x07\x41\x0f\ -\x00\x00\x07\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x53\xd5\ -\x00\x00\x09\xf4\x00\x01\x00\x00\x00\x01\x00\x08\x0d\x61\ +\x00\x00\x08\xe0\x00\x01\x00\x00\x00\x01\x00\x07\xb3\x81\ +\x00\x00\x07\xaa\x00\x01\x00\x00\x00\x01\x00\x07\x50\xe1\ +\x00\x00\x07\xf4\x00\x01\x00\x00\x00\x01\x00\x07\x63\xa7\ +\x00\x00\x0a\x14\x00\x01\x00\x00\x00\x01\x00\x08\x1d\x33\ \x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x43\x20\ +\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x07\x41\x0f\ \x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x90\xbb\ \x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xec\x4e\ -\x00\x00\x08\x42\x00\x00\x00\x00\x00\x01\x00\x07\x73\xa5\ +\x00\x00\x08\x62\x00\x00\x00\x00\x00\x01\x00\x07\x83\x77\ \x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x05\xcc\x17\ \x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x05\xd5\x2b\ " diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc index ca70f95168..1d9788ccee 100644 --- a/src/Mod/Draft/Resources/Draft.qrc +++ b/src/Mod/Draft/Resources/Draft.qrc @@ -51,6 +51,7 @@ icons/Snap_Center.svg icons/Snap_Extension.svg icons/Snap_Ortho.svg + icons/Snap_Near.svg patterns/concrete.svg patterns/cross.svg patterns/line.svg diff --git a/src/Mod/Draft/Resources/icons/Snap_Near.svg b/src/Mod/Draft/Resources/icons/Snap_Near.svg new file mode 100644 index 0000000000..a2389050ed --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Snap_Near.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + From 3a0d1ad42f7220e0d36e96967a806584a4618ed0 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 16 Mar 2012 20:08:09 -0300 Subject: [PATCH 020/351] Bugfix in Draft upgrade --- src/Mod/Draft/DraftTools.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index e8eb87c56b..b9588c342b 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -2368,21 +2368,26 @@ class Upgrade(Modifier): Draft.formatObject(newob,lastob) elif (len(openwires) == 1) and (not faces) and (not wires): - # special case, we have only one open wire. We close it!" + # special case, we have only one open wire. We close it, unless it has only 1 edge!" p0 = openwires[0].Vertexes[0].Point p1 = openwires[0].Vertexes[-1].Point edges = openwires[0].Edges - edges.append(Part.Line(p1,p0).toShape()) + if len(edges) > 1: + edges.append(Part.Line(p1,p0).toShape()) w = Part.Wire(fcgeo.sortEdges(edges)) - msg(translate("draft", "Found 1 open wire: closing it\n")) - if not curves: - newob = Draft.makeWire(w,closed=True) + if len(edges) == 1: + msg(translate("draft", "Found 1 open edge: making a line\n")) + newob = Draft.makeWire(w,closed=False) else: - # if not possible, we do a non-parametric union - newob = self.doc.addObject("Part::Feature","Wire") - newob.Shape = w - Draft.formatObject(newob,lastob) - + msg(translate("draft", "Found 1 open wire: closing it\n")) + if not curves: + newob = Draft.makeWire(w,closed=True) + else: + # if not possible, we do a non-parametric union + newob = self.doc.addObject("Part::Feature","Wire") + newob.Shape = w + Draft.formatObject(newob,lastob) + elif openwires and (not wires) and (not faces): # only open wires and edges: we try to join their edges for ob in self.sel: From 1fb805556b8bece39cc87224f18bcb294c383436 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 17 Mar 2012 12:11:29 +0100 Subject: [PATCH 021/351] Improve Python doc for makeThickness() --- src/Mod/Part/App/TopoShapePy.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShapePy.xml b/src/Mod/Part/App/TopoShapePy.xml index eb612ab736..34522f5f95 100644 --- a/src/Mod/Part/App/TopoShapePy.xml +++ b/src/Mod/Part/App/TopoShapePy.xml @@ -179,7 +179,8 @@ the underlying geometry. - A hollowed solid is built from an initial solid and a set of faces on this solid, + makeThickness(List of shapes, Ofset (Float), Tolerance (Float)) -> Shape +A hollowed solid is built from an initial solid and a set of faces on this solid, which are to be removed. The remaining faces of the solid become the walls of the hollowed solid, their thickness defined at the time of construction. From 8637696bf509d2d73d1aa4bb3755470d01634633 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 17 Mar 2012 12:25:52 +0100 Subject: [PATCH 022/351] 0000643: Mesh doesn't register off file import properly --- src/Mod/Mesh/Init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Mesh/Init.py b/src/Mod/Mesh/Init.py index 427c366aff..bc76d6a79b 100644 --- a/src/Mod/Mesh/Init.py +++ b/src/Mod/Mesh/Init.py @@ -31,7 +31,7 @@ ParGrp = FreeCAD.ParamGet("System parameter:Modules").GetGroup("Mesh") # Append the open handler -FreeCAD.addImportType("Mesh formats (*.stl *.ast *.bms *.obj *.ply)","Mesh") +FreeCAD.addImportType("Mesh formats (*.stl *.ast *.bms *.obj *.off *.ply)","Mesh") FreeCAD.addExportType("Mesh formats (*.stl *.ast *.bms *.obj *.off *.ply)","Mesh") From c0a864c1faf2d4205c64553ce196da72138f8520 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 17 Mar 2012 14:40:28 +0100 Subject: [PATCH 023/351] Fix typo --- src/Gui/CommandStd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/CommandStd.cpp b/src/Gui/CommandStd.cpp index f0c3210a6c..3861e1e647 100644 --- a/src/Gui/CommandStd.cpp +++ b/src/Gui/CommandStd.cpp @@ -521,7 +521,7 @@ StdCmdMeasurementSimple::StdCmdMeasurementSimple() :Command("Std_MeasurementSimple") { sGroup = QT_TR_NOOP("Tools"); - sMenuText = QT_TR_NOOP("Mesure distance"); + sMenuText = QT_TR_NOOP("Measure distance"); sToolTipText = QT_TR_NOOP("Measures distance between two selected objects"); sWhatsThis = QT_TR_NOOP("Measures distance between two selected objects"); sStatusTip = QT_TR_NOOP("Measures distance between two selected objects"); From 405e640c282edb97eb764122fc4ee87e9f5f0910 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 17 Mar 2012 17:12:22 -0300 Subject: [PATCH 024/351] Bugfixes in Draft + fixed bug in Draft Edit + fixed bug in Draft Wire --- src/Mod/Draft/Draft.py | 7 ++++++- src/Mod/Draft/DraftTools.py | 39 +++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index c6fd4713ca..0947750031 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -448,13 +448,18 @@ def makeWire(pointslist,closed=False,placement=None,face=True,support=None): true (and wire is closed), the wire will appear filled. Instead of a pointslist, you can also pass a Part Wire.''' from draftlibs import fcgeo + import Part if not isinstance(pointslist,list): + e = pointslist.Wires[0].Edges + pointslist = Part.Wire(fcgeo.sortEdges(e)) nlist = [] for v in pointslist.Vertexes: nlist.append(v.Point) if fcgeo.isReallyClosed(pointslist): - nlist.append(pointslist.Vertexes[0].Point) + closed = True pointslist = nlist + print pointslist + print closed if placement: typecheck([(placement,FreeCAD.Placement)], "makeWire") if len(pointslist) == 2: fname = "Line" else: fname = "Wire" diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index b9588c342b..649f8db2b6 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -2359,10 +2359,11 @@ class Upgrade(Modifier): faces.append(f) for f in faces: if not curves: + msg(translate("draft", "Found a closed wire: making a Draft wire\n")) newob = Draft.makeWire(f.Wire,closed=True) else: # if there are curved segments, we do a non-parametric face - msg(translate("draft", "Found closed wires: making faces\n")) + msg(translate("draft", "Found a closed wire with curves: making a face\n")) newob = self.doc.addObject("Part::Feature","Face") newob.Shape = f Draft.formatObject(newob,lastob) @@ -3096,10 +3097,10 @@ class Edit(Modifier): if hasattr(self.obj.ViewObject,"Selectable"): self.selectstate = self.obj.ViewObject.Selectable self.obj.ViewObject.Selectable = False - if not Draft.getType(self.obj) in ["Wire","BSpline"]: - self.ui.setEditButtons(False) - else: + if Draft.getType(self.obj) in ["Wire","BSpline"]: self.ui.setEditButtons(True) + else: + self.ui.setEditButtons(False) self.editing = None self.editpoints = [] self.pl = None @@ -3137,13 +3138,13 @@ class Edit(Modifier): for ep in range(len(self.editpoints)): self.trackers.append(editTracker(self.editpoints[ep],self.obj.Name, ep,self.obj.ViewObject.LineColor)) - self.constraintrack = lineTracker(dotted=True) - self.call = self.view.addEventCallback("SoEvent",self.action) - self.running = True - plane.save() - if "Shape" in self.obj.PropertiesList: - plane.alignToFace(self.obj.Shape) - self.planetrack.set(self.editpoints[0]) + self.constraintrack = lineTracker(dotted=True) + self.call = self.view.addEventCallback("SoEvent",self.action) + self.running = True + plane.save() + if "Shape" in self.obj.PropertiesList: + plane.alignToFace(self.obj.Shape) + self.planetrack.set(self.editpoints[0]) else: msg(translate("draft", "This object type is not editable\n"),'warning') self.finish() @@ -3188,27 +3189,27 @@ class Edit(Modifier): elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): if self.editing == None: - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - if snapped['Object'] == self.obj.Name: + sel = FreeCADGui.Selection.getSelectionEx() + if sel: + sel = sel[0] + if sel.ObjectName == self.obj.Name: if self.ui.addButton.isChecked(): point,ctrlPoint = getPoint(self,arg) self.pos = arg["Position"] self.addPoint(point) elif self.ui.delButton.isChecked(): - if 'EditNode' in snapped['Component']: - self.delPoint(int(snapped['Component'][8:])) - elif 'EditNode' in snapped['Component']: + if 'EditNode' in sel.SubElementNames[0]: + self.delPoint(int(sel.SubElementNames[0][8:])) + elif 'EditNode' in sel.SubElementNames[0]: self.ui.pointUi() self.ui.isRelative.show() - self.editing = int(snapped['Component'][8:]) + self.editing = int(sel.SubElementNames[0][8:]) self.trackers[self.editing].off() if hasattr(self.obj.ViewObject,"Selectable"): self.obj.ViewObject.Selectable = False if "Points" in self.obj.PropertiesList: self.node.append(self.obj.Points[self.editing]) else: - print "finishing edit" self.trackers[self.editing].on() if hasattr(self.obj.ViewObject,"Selectable"): self.obj.ViewObject.Selectable = True From c0d21e69233145b617e2e6ab5c15b5edc30d0645 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 18 Mar 2012 00:10:08 -0300 Subject: [PATCH 025/351] Small fix in Arch mesh2shape --- src/Mod/Arch/ArchCommands.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index e94d21b3ef..cdb992b4af 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -192,12 +192,12 @@ def meshToShape(obj,mark=True): else: if solid.isClosed(): FreeCAD.ActiveDocument.removeObject(name) - else: - if mark: - newobj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0) newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name) newobj.Shape = solid newobj.Placement = plac + if not solid.isClosed(): + if mark: + newobj.ViewObject.ShapeColor = (1.0,0.0,0.0,1.0) return newobj return None From 5ca9ca11117873212cab6f17a0e97c9048f84f7c Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 18 Mar 2012 01:53:04 -0300 Subject: [PATCH 026/351] Allow to change macro editor line highlight color in preferences --- src/Gui/DlgEditorImp.cpp | 4 ++++ src/Gui/PythonEditor.cpp | 2 +- src/Gui/TextEdit.cpp | 9 ++++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Gui/DlgEditorImp.cpp b/src/Gui/DlgEditorImp.cpp index 7b23a1e219..c4d1d283df 100644 --- a/src/Gui/DlgEditorImp.cpp +++ b/src/Gui/DlgEditorImp.cpp @@ -115,6 +115,10 @@ DlgSettingsEditorImp::DlgSettingsEditorImp( QWidget* parent ) unsigned long lPyError = (col.red() << 24) | (col.green() << 16) | (col.blue() << 8); d->colormap.push_back(QPair (QString::fromAscii(QT_TR_NOOP("Python error")), lPyError)); + col.setRgb(224, 224, 224); + unsigned long lCLine = (col.red() << 24) | (col.green() << 16) | (col.blue() << 8); + d->colormap.push_back(QPair + (QString::fromAscii(QT_TR_NOOP("Current line highlight")), lCLine)); QStringList labels; labels << tr("Items"); this->displayItems->setHeaderLabels(labels); diff --git a/src/Gui/PythonEditor.cpp b/src/Gui/PythonEditor.cpp index c79a518144..5b448633a6 100644 --- a/src/Gui/PythonEditor.cpp +++ b/src/Gui/PythonEditor.cpp @@ -61,7 +61,7 @@ struct PythonEditorP colormap[QLatin1String("Operator")] = QColor(160, 160, 164); colormap[QLatin1String("Python output")] = QColor(170, 170, 127); colormap[QLatin1String("Python error")] = Qt::red; - colormap[QLatin1String("Line")] = QColor(224,224,224); + colormap[QLatin1String("Current line highlight")] = QColor(224,224,224); } }; } // namespace Gui diff --git a/src/Gui/TextEdit.cpp b/src/Gui/TextEdit.cpp index 75fb88c1d4..bbb06d8b68 100644 --- a/src/Gui/TextEdit.cpp +++ b/src/Gui/TextEdit.cpp @@ -192,7 +192,7 @@ struct TextEditorP colormap[QLatin1String("Operator")] = QColor(160, 160, 164); colormap[QLatin1String("Python output")] = QColor(170, 170, 127); colormap[QLatin1String("Python error")] = Qt::red; - colormap[QLatin1String("Line")] = QColor(224,224,224); + colormap[QLatin1String("Current line highlight")] = QColor(224,224,224); } }; } // namespace Gui @@ -272,8 +272,11 @@ void TextEditor::highlightCurrentLine() if (!isReadOnly()) { QTextEdit::ExtraSelection selection; - QColor lineColor = d->colormap[QLatin1String("Line")]; - + QColor lineColor = d->colormap[QLatin1String("Current line highlight")]; + unsigned long col = (lineColor.red() << 24) | (lineColor.green() << 16) | (lineColor.blue() << 8); + ParameterGrp::handle hPrefGrp = getWindowParameter(); + col = hPrefGrp->GetUnsigned( "Current line highlight", col); + lineColor.setRgb((col>>24)&0xff, (col>>16)&0xff, (col>>8)&0xff); selection.format.setBackground(lineColor); selection.format.setProperty(QTextFormat::FullWidthSelection, true); selection.cursor = textCursor(); From 09f8453b5cee2a1786028576d25e01b06f0d3ed8 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 19 Mar 2012 15:14:27 -0300 Subject: [PATCH 027/351] Small fix to DraftSnap to work with walls containing walls --- src/Mod/Draft/DraftSnap.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index e142699015..3141d091c5 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -215,13 +215,17 @@ class Snapper: comp = info['Component'] if (Draft.getType(obj) == "Wall") and not oldActive: - if obj.Base: - for edge in obj.Base.Shape.Edges: - snaps.extend(self.snapToEndpoints(edge)) - snaps.extend(self.snapToMidpoint(edge)) - snaps.extend(self.snapToPerpendicular(edge,lastpoint)) - snaps.extend(self.snapToIntersection(edge)) - snaps.extend(self.snapToElines(edge,eline)) + edges = [] + for o in [obj]+obj.Additions: + if Draft.getType(o) == "Wall": + if o.Base: + edges.extend(o.Base.Shape.Edges) + for edge in edges: + snaps.extend(self.snapToEndpoints(edge)) + snaps.extend(self.snapToMidpoint(edge)) + snaps.extend(self.snapToPerpendicular(edge,lastpoint)) + snaps.extend(self.snapToIntersection(edge)) + snaps.extend(self.snapToElines(edge,eline)) elif obj.isDerivedFrom("Part::Feature"): if (not self.maxEdges) or (len(obj.Edges) <= self.maxEdges): From 1c4d89013b086ae99bc3fa058223e19ff42b4119 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 19 Mar 2012 15:27:15 -0300 Subject: [PATCH 028/351] Fixed shortcuts in Arch and Draft menus --- src/Mod/Arch/InitGui.py | 6 +++--- src/Mod/Draft/InitGui.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 554764e2e2..066ee12b82 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -75,9 +75,9 @@ class ArchWorkbench(Workbench): "Arch_SelectNonSolidMeshes","Arch_RemoveShape"] self.appendToolbar(str(DraftTools.translate("arch","Arch tools")),self.archtools) self.appendToolbar(str(DraftTools.translate("arch","Draft tools")),self.drafttools) - self.appendMenu([str(DraftTools.translate("arch","Architecture")),str(DraftTools.translate("arch","Tools"))],self.meshtools) - self.appendMenu(str(DraftTools.translate("arch","Architecture")),self.archtools) - self.appendMenu(str(DraftTools.translate("arch","Draft")),self.drafttools+self.draftcontexttools) + self.appendMenu([str(DraftTools.translate("arch","&Architecture")),str(DraftTools.translate("arch","Tools"))],self.meshtools) + self.appendMenu(str(DraftTools.translate("arch","&Architecture")),self.archtools) + self.appendMenu(str(DraftTools.translate("arch","&Draft")),self.drafttools+self.draftcontexttools) FreeCADGui.addIconPath(":/icons") FreeCADGui.addLanguagePath(":/translations") FreeCADGui.addPreferencePage(":/ui/archprefs-base.ui","Arch") diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 70b0ab50c6..7ec5028ed1 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -197,9 +197,9 @@ class DraftWorkbench (Workbench): self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] self.appendToolbar(str(DraftTools.translate("draft","Draft creation tools")),self.cmdList) self.appendToolbar(str(DraftTools.translate("draft","Draft modification tools")),self.modList) - self.appendMenu(str(DraftTools.translate("draft","Draft")),self.cmdList+self.modList) - self.appendMenu([str(DraftTools.translate("draft","Draft")),str(DraftTools.translate("draft","Display options"))],self.treecmdList) - self.appendMenu([str(DraftTools.translate("draft","Draft")),str(DraftTools.translate("draft","Wire tools"))],self.lineList) + self.appendMenu(str(DraftTools.translate("draft","&Draft")),self.cmdList+self.modList) + self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Display options"))],self.treecmdList) + self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Wire tools"))],self.lineList) def Activated(self): FreeCADGui.draftToolBar.Activated() From 23ddc2d30fd7ea2425e2bc09f148e85e9befd749 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 19 Mar 2012 15:45:49 -0300 Subject: [PATCH 029/351] Added a Draft prefs option to hide the Snap bar after use --- src/Mod/Draft/Draft.py | 2 +- src/Mod/Draft/DraftSnap.py | 2 + src/Mod/Draft/Draft_rc.py | 585 ++++++++++--------- src/Mod/Draft/Resources/ui/userprefs-base.ui | 63 +- 4 files changed, 343 insertions(+), 309 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 0947750031..6dba687095 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -101,7 +101,7 @@ def getParamType(param): elif param in ["textheight","tolerance","gridSpacing"]: return "float" elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit","maxSnap", - "SvgLinesBlack","dxfStdSize","showSnapBar"]: + "SvgLinesBlack","dxfStdSize","showSnapBar","hideSnapBar"]: return "bool" elif param in ["color","constructioncolor","snapcolor"]: return "unsigned" diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 3141d091c5..e56d12e8d3 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -609,6 +609,8 @@ class Snapper: self.unconstrain() self.radius = 0 self.setCursor() + if Draft.getParam("hideSnapBar"): + self.toolbar.hide() def constrain(self,point,basepoint=None,axis=None): '''constrain(point,basepoint=None,axis=None: Returns a diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 66a43f5767..c97248fb51 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Fri Mar 16 17:36:21 2012 +# Created: Mon Mar 19 15:43:18 2012 # by: The Resource Compiler for PyQt (Qt v4.7.4) # # WARNING! All changes made in this file will be lost! @@ -23949,245 +23949,248 @@ qt_resource_data = "\ \xe3\xab\x65\xc9\x7a\xb7\x23\x8c\x3b\xb9\x4f\x11\x66\xdc\xbb\xbe\ \x30\xc5\x06\xf3\x83\x24\x92\x29\x63\x03\xca\x58\x8b\x27\xe2\x98\ \x19\x1b\xc0\xe7\x66\x3d\xe1\xad\x83\xff\x03\xad\x19\x30\x45\ -\x00\x00\x0e\xc2\ +\x00\x00\x0e\xf8\ \x00\ -\x00\x97\xdb\x78\x9c\xed\x1d\x6b\x73\xdb\x36\xf2\xbb\x7f\x05\xc6\ -\x1f\x32\xb9\x19\xd7\xb2\x1c\x3f\xe2\x44\x56\x27\xef\x64\x26\x6d\ -\xd3\xc8\x49\xaf\xf7\xa5\x03\x91\x90\x84\x0b\x45\xa8\x00\x14\x5b\ -\x9d\xfb\xf1\xb7\x0b\x80\x12\x49\x51\x94\x25\x88\xa2\xdc\x2a\x93\ -\x19\x8b\x00\xb9\x58\x2c\xf6\x85\xdd\x25\xd8\xfa\xf1\x6e\x18\x91\ -\xef\x4c\x2a\x2e\xe2\xeb\xc3\xe6\xf1\xc9\x21\x61\x71\x20\x42\x1e\ -\xf7\xaf\x0f\xbf\xdc\xbc\xfd\xe1\xe9\xe1\x8f\xed\x83\xd6\x98\xcf\ -\x6e\x3a\x83\x9b\xda\x07\xa4\x15\x44\x54\xa9\xf6\xbb\x31\x7f\xf6\ -\xec\x35\xa7\x91\xe8\xc3\xdf\xa8\xdf\x61\x5a\xc3\xc3\xea\xb5\xa4\ -\x3d\xdd\x6a\xd8\x9b\xe0\xee\x5b\x1e\xf6\x99\x26\xe6\xfa\xfa\xf0\ -\xd7\xdf\xcc\xe5\x21\x89\xe9\x90\x5d\x1f\x96\x02\xc1\xc1\x48\x6b\ -\x24\xc5\x88\x49\x3d\x71\x4f\xf4\x99\x18\x32\x2d\x27\xa6\x93\xb4\ -\x24\x0b\xb4\xf9\x45\x5a\x77\xed\x93\x56\xe3\xce\x5d\x4c\xf0\x62\ -\xe2\x2e\x00\x05\x3d\x68\x9f\x5f\x41\x93\xfd\x69\x9b\x07\x8c\xf7\ -\x07\xba\x7d\x71\x7a\xd5\x6a\xb8\xdf\x06\x66\x23\x01\xda\x6a\x24\ -\x83\x17\x61\x72\xcb\xe3\x50\xdc\xde\x70\x1d\x31\x87\x8c\xd2\x12\ -\x90\x6f\xbf\x63\x31\x93\x34\x22\xca\x4d\xa6\xd5\x70\x1d\xf3\x20\ -\x23\x3a\x11\xe3\x19\x71\xbe\xbe\x14\x77\x1f\x4d\x93\x83\x98\x1b\ -\x52\x8d\x68\x00\x80\x0e\xdd\x04\xe2\xf1\xb0\xcb\x64\xfb\xa2\xd5\ -\x70\xbf\x2c\xfa\xe9\x11\xe6\x40\x0c\xa9\xec\xf3\x38\x07\xe1\xaa\ -\x14\x02\xd7\x6c\x38\xa3\x64\x7a\x31\xdf\x49\x31\x1e\x01\xce\xc9\ -\x72\xf6\x93\x6b\x7b\xfb\xdc\xe0\x7a\x46\xac\x02\x7a\x99\x45\x27\ -\x9d\x02\xaa\xcd\x23\x55\x4a\x3b\x37\x1a\x30\xae\xe6\x01\x8d\x6c\ -\xeb\x1f\xa7\xb3\x81\x67\x33\x2a\x00\xf4\x7e\x0e\xd0\x40\x48\xfe\ -\x97\x88\xf5\x14\x54\xf3\x6a\x0a\x2b\x0f\x6d\x9e\x48\x1f\x69\x97\ -\x45\x09\xa8\x08\x2f\xb2\xcf\x17\x90\x89\xdd\xe9\xcc\x0d\x53\x52\ -\x59\x12\xf1\x58\x33\xd9\xa3\x01\x23\x43\x11\xb2\x1c\xa1\x8a\xa9\ -\x65\x1b\x2d\x66\x29\xd4\x1b\x59\xdc\x97\x4c\xc5\x48\xeb\x27\xc9\ -\x7a\xaf\xc4\xb0\x2b\xd2\xeb\x8e\x1d\x23\xe8\x08\xb0\xa3\x2b\xee\ -\xfe\x38\x2b\x9f\xa0\x10\xd1\x0d\x1f\x15\xcf\xf1\x66\xc0\x15\x81\ -\xff\x7a\xc0\xc8\x97\x0f\x66\x8a\x30\x63\x72\x3b\xe0\xc1\xc0\x34\ -\x5a\x22\x40\xfb\x38\x62\xe4\x96\x47\x11\xb9\x15\xf2\xdb\x33\x72\ -\x03\x50\xbb\x54\xda\x27\x4c\xfb\x28\x42\x22\xd1\x28\xe1\xad\x44\ -\x22\x11\x1e\x85\xab\x11\x95\x54\x33\xa2\xed\x83\x47\x38\x06\x80\ -\xd4\x54\x7d\xcb\xc2\x19\x2b\x66\x46\x7e\x2b\x19\x7b\xf5\xe2\x35\ -\xb9\x81\x3b\xbe\x73\x76\x4b\xd4\x44\x01\xc5\x48\x4f\x48\x33\x0a\ -\xd7\x0a\xef\x95\x76\x85\x68\xa0\x41\x6f\xde\x7b\x79\xe6\xa8\x84\ -\x04\x7d\x13\xa3\xae\x23\x4a\x87\x80\xfb\xf5\xe1\x49\x8e\x64\x81\ -\x83\xfd\x85\xff\x64\x38\x21\xf0\x19\xeb\x13\xd5\x83\xe5\x43\xc1\ -\x40\x8d\x44\xc7\xdf\x7b\xb4\x1c\x5f\xdd\x87\xe5\x67\xfc\x60\x57\ -\xa7\x88\x8e\x8b\x86\x6b\xe4\xc7\xf3\x43\xc0\xad\xb6\x0f\x06\x4b\ -\x65\xaf\xd5\xb0\x6a\x68\xaa\xa3\x32\xdd\xde\x1a\xeb\xd4\x4f\x61\ -\x9d\xae\xab\xaf\x58\x8f\x8e\x23\x00\x2d\x22\x51\xb8\x82\x95\x2b\ -\x2a\x18\xf7\xe5\x58\x6b\x11\x17\xe8\x2a\xe8\xeb\xda\xbe\xb5\x95\ -\x15\x6a\x85\x30\x3d\x49\xa3\x0b\x62\x50\x0d\xa2\xfb\x5f\x70\x23\ -\xf2\x66\xac\x8c\x67\x72\xe3\x1a\x70\x79\x21\xc4\xb6\x1c\x97\x4a\ -\x16\xa2\xb3\x83\x7f\xb2\x1d\x7d\xd0\x56\x31\x76\xd9\x1f\xd9\xce\ -\x6e\x34\x66\xd8\x67\xfe\x66\x19\x7a\x6e\x90\x8d\xab\x2b\xc7\x0e\ -\xbb\xa9\xad\xbc\xb9\xaf\x48\x80\x96\xd8\xc3\x85\x02\xd4\x89\xe9\ -\x68\xd7\xa5\x67\x99\x76\x58\x5d\x7e\x14\xce\x5a\x4d\xc0\x97\x88\ -\xf6\x02\x94\x41\xdf\xd1\x02\x09\xf4\xcf\x13\xa2\x75\xbd\xe6\x57\ -\x22\x86\x5f\x63\xe3\x8e\xed\xbc\x30\x3d\xd9\x8c\xe7\x3c\x2f\x54\ -\xce\x20\x91\x2e\x83\x7b\x49\x28\xe9\x6d\xec\x1c\x5e\x8e\x54\x49\ -\x91\x08\x1d\xdf\xe3\xed\xc8\xdd\xd9\xd9\x62\xc1\x6b\x9e\x9e\x97\ -\x88\xde\xe9\xf9\x79\x6d\xd6\x6b\x46\xab\x7f\x9e\x10\x2e\xe1\xcf\ -\xa5\xae\x60\xc4\xc1\x3b\xc2\x28\x4c\x0d\x32\xd8\x19\xf1\xb8\x68\ -\xdb\xaa\xa0\xbd\x3b\x0b\x5b\x14\xcf\xec\xbe\x66\x6c\x3a\xc1\xcd\ -\xb9\x82\xdf\x29\xf0\x79\x6e\x64\x17\xb0\x39\xcd\x84\x6e\x56\x82\ -\xba\x02\xcb\xa7\x16\xed\x81\xb2\x7a\xc5\xfb\xab\x27\x9e\xfb\xab\ -\x13\x2f\xd3\x46\xb9\x51\xda\x3b\x19\x09\x3a\xf7\xb1\x67\x8c\x4c\ -\x27\x88\x46\x0b\xe6\xc8\x7b\x9c\x49\xf2\x8d\x4d\xb6\x12\x57\x81\ -\x01\x83\x04\x81\x5d\x65\x7d\xbf\xe0\x86\x1a\x70\x1c\xac\xae\xd8\ -\x4a\xa0\x65\x54\xdf\xe8\x34\xf2\x9a\xfa\x1a\x62\x84\x11\x7c\xe0\ -\xdf\xbc\x16\xe9\x98\xe6\x25\xb2\x02\x77\x33\xb8\x19\xdd\x8e\x1c\ -\xf7\x30\x30\x01\xed\x5f\xf5\xb3\x67\xef\xa7\x10\x5b\x0d\xd3\xb8\ -\x32\xab\x2a\xfe\x17\x7b\xcf\x63\xbd\x98\x55\xf1\x8e\x1c\x39\x6d\ -\x56\xe5\x2c\x9b\x5f\x99\xf6\xba\xdc\xca\xe9\x49\x26\xcd\x32\x43\ -\x2b\x0f\x70\x81\xca\xb2\xa4\xdb\xa8\x2f\x73\xda\xf4\xd9\x96\xef\ -\xaa\xc6\xbd\xf0\xd3\xb8\xca\xcd\x6d\x03\x9a\x36\x18\x4b\x09\x2c\ -\xfb\x21\x0e\xd9\x5d\xb1\xfb\xd2\xdc\x8a\xfb\x02\xb3\xc1\x59\xed\ -\x35\xb8\x6d\xdd\x6b\xf0\x59\xc3\x86\x35\x78\xb9\xec\xed\x35\xf8\ -\xc6\x35\xf8\xba\x99\x89\x17\x91\xde\x59\x05\x7e\xe9\xa7\xc0\xa9\ -\x9d\xda\x56\xf4\xf7\x76\xb6\x9f\x30\x1b\x23\xe8\x7b\xf5\xbd\x57\ -\xdf\xbb\x94\x55\x6d\xa6\xb9\x68\x9d\x3a\x10\xbf\x6d\xbf\x0b\xd7\ -\x9a\xaa\x1b\xf3\x48\x0d\xda\xec\x23\x8f\xd9\x9b\x90\xeb\x39\x6d\ -\x86\x21\x23\x06\x1d\x3e\xd9\xa1\xa2\x80\xf6\x6c\xb6\x26\xbe\x96\ -\x09\x5c\x27\xc5\x61\xeb\x6b\xbc\xfb\x91\x7c\x2b\xb1\x87\xf4\xcc\ -\xcc\xa4\xed\x0a\xef\xa6\x0e\xac\x5b\x12\xcf\xee\x2f\x88\x33\x43\ -\x3c\x60\xc1\xb7\x42\x43\x8c\x1d\x5e\xf1\x60\x03\x01\xd8\x16\xd9\ -\xb7\x47\x00\x43\x72\x4b\x63\x4d\xb4\x98\x96\x12\x99\xc4\x41\x23\ -\x15\x2b\x96\x62\x68\x3a\x5c\x31\x12\xa1\x2a\x61\xf9\x2a\xb8\xb9\ -\x43\xbf\x03\x0e\xd6\xbc\xbb\x1c\x11\x8d\xc3\x54\xec\x9a\x06\x52\ -\x28\x45\x14\x53\x58\xfc\xe9\x11\xbb\x5e\x25\xab\x09\x48\x89\x98\ -\xdd\xf1\x9d\x35\xf5\x75\xb3\xf9\x65\x15\x6c\xee\x13\xa2\xfd\xd0\ -\x73\x5c\xae\x88\x01\xc7\xc2\x23\x60\xa7\xd1\x24\x55\x3c\xd7\x65\ -\xe0\x84\x8e\x74\xc2\x51\xe0\xe5\x0e\x81\xd5\x8e\x88\x00\x6e\x97\ -\xb7\x5c\xb1\xa4\x49\xd9\xfb\x69\x74\x4b\x27\xc0\x79\x9a\x4a\x2c\ -\x75\x24\xb1\xf8\x61\x0a\xb1\x0a\x51\x78\x17\x89\x2e\x8d\xc8\x06\ -\xc6\x70\x14\xc8\x0d\xd3\x05\xfa\xb5\x41\x91\x03\x60\xf3\xb3\x5a\ -\x9b\x31\x9a\x0c\x77\xb8\x12\xb0\x6e\xf9\x69\x3e\xad\x44\x80\x3c\ -\x72\xf6\x3f\x0b\x39\xa4\x51\x34\x39\x22\x40\x48\x26\x0d\x1b\x62\ -\xaa\xc3\xe5\x0c\x8f\x9c\xb1\x18\x71\xa6\x08\x22\xa7\x58\x04\xed\ -\x2c\x3c\x26\x89\xe8\x89\x91\xf1\x7d\xd2\x12\x88\xcf\x74\x29\x48\ -\x56\x92\xf3\x4f\x04\x31\x79\x1a\xe4\x4a\x69\x46\x43\x8f\x2c\x7f\ -\x89\x6d\x31\x83\x64\x11\xc8\x4c\x6e\x3b\xc6\xc4\x60\xf1\x12\x90\ -\xf8\x25\x49\xbf\xee\x65\xa2\x48\x26\xce\x2b\x11\x89\xa7\x9b\xb5\ -\x29\xc6\x85\x4a\x5b\x07\x0c\x52\x83\x3b\x05\xce\x82\xd2\x29\x79\ -\x71\x15\x2d\x58\xdd\x02\xad\x46\x48\x62\xa1\x53\xcf\x77\x6d\x80\ -\x7b\x64\x9e\x89\xa3\x09\x3c\xc0\x62\x02\xa8\x83\x9f\x03\x4d\xaf\ -\x6e\x3e\x7f\xac\x44\x28\x5e\x64\xf1\x4e\xd0\x7d\x1c\x72\x45\xbb\ -\xd1\x2c\xea\x8e\x01\x9b\x7f\x3d\x64\x13\x64\x17\xa8\xb3\xc3\xe1\ -\xf6\x8d\x07\x7d\xcb\x77\xb8\xfb\xa0\xef\xa6\x83\xbe\x4d\xcf\x00\ -\xa9\xa4\x21\x1f\xab\x69\xa5\xa9\xd1\x05\x20\x93\x6a\xc4\x02\x0e\ -\x9e\xe0\x48\x00\x21\xd5\x31\xbe\x89\x84\xcd\x27\xb6\x8e\x47\x10\ -\x10\x55\x4d\xe3\x80\x91\xc7\x3c\xee\xf1\x18\xf0\xf6\x10\xd4\x25\ -\xb9\x45\x49\xe3\x7e\x1d\xe1\x9c\x25\x15\x52\x4b\x58\x5d\x8d\x7b\ -\x3d\x9e\x8f\x14\xbb\x39\x8c\xee\xb6\x63\xf6\x81\x7a\x9f\x2d\xf1\ -\x1e\xa8\xf6\xa9\xfa\x4d\x90\x15\x62\x96\x2b\xd8\x7b\x8f\x17\xbe\ -\x8a\xec\xfd\x54\x2e\x8d\xd1\x06\x13\x4e\x44\x10\x8c\x25\xa1\x7d\ -\x8a\xae\x6b\xca\xb1\xd5\x03\x30\x9b\x12\x83\x2a\x34\x36\x8e\x2f\ -\x8f\x43\x1e\x50\x74\x72\x6d\x66\x82\x88\x1e\x61\x30\x2b\x8f\x18\ -\xc6\xb2\x42\x00\x7a\xc7\x87\xe3\xe1\x43\xb6\xda\x30\x85\x7f\x92\ -\xc9\xde\x1b\xec\xc5\x94\xae\x22\x4b\xeb\xb1\x41\xfe\xc9\x0a\x57\ -\x5e\x98\xd1\x32\x77\x99\x09\xff\xf3\x90\x49\x90\xf6\xb4\x39\xaf\ -\x42\xd4\x17\x20\xb2\x83\x46\xba\xbc\x08\xc1\x69\xab\xe2\x7c\xee\ -\xd5\xd5\xd5\xfa\x19\xdd\xb2\x32\xe5\xb3\xed\x24\x8a\xad\x1a\x7b\ -\x63\x17\xe6\x81\xea\xb2\xaa\x1d\x80\x66\x25\x0e\x80\x87\x4f\x0e\ -\x0e\x40\x26\x74\xd5\xb1\x9b\x64\x9b\x07\x99\xee\xda\x07\xc2\xbc\ -\xb0\xc2\x62\xf6\x1d\xc4\x0f\x37\xf4\x98\x4b\xa9\x52\xe2\x3b\x30\ -\x64\x72\x2a\x41\x0a\xa5\x87\x6c\xe7\x91\x8a\x38\x97\x97\xf4\xe1\ -\xbe\xb5\x52\xb1\x7c\x54\x13\x22\xf6\x28\xca\x2c\xf2\x8f\x33\x81\ -\x5d\x90\x00\x66\x33\x86\x3d\xb8\x04\x53\x38\xcb\x1d\x1e\x93\x5f\ -\x92\x34\x8b\x91\xad\x49\xfe\x89\x5b\x0e\x58\xca\x55\x6a\x07\x56\ -\x10\xa0\xb7\x38\xd6\xf4\xbd\xb3\x89\x7f\x42\x73\x05\x4e\x47\x52\ -\xec\x53\x21\x8b\xd9\xdc\xf7\x08\x13\xdf\x23\x01\xf0\xcc\x0e\xdc\ -\xe0\x8d\x22\x1a\xef\xe6\x19\x26\xe5\x33\x5c\x81\x15\x1d\xdb\xff\ -\xf6\x69\x57\x79\xd1\xaf\x88\xeb\x67\x51\xbc\x80\xdb\x29\x21\xfb\ -\xf7\xef\xe4\xf1\x8d\x18\x15\x86\xe2\xb6\x84\xc1\x7f\xc8\xe3\xb7\ -\x12\x64\xab\x46\x1c\x7e\x07\x1c\x3a\xb0\x11\xf2\x42\xa1\x6e\x95\ -\xd4\xac\xa6\xbc\xc1\xa3\x00\x2d\xed\x99\x52\xd2\x97\x3c\xcc\xd8\ -\x4f\x93\x3b\x72\xb9\xa6\x2a\xec\xe7\x17\x70\x70\x71\xd0\x87\xec\ -\x71\x5a\xfc\x77\x53\xef\x6d\x3c\x13\x54\xbe\x09\xda\x07\x96\x36\ -\x9e\x09\x5a\x52\xba\xb4\xb8\xe8\x07\x45\xd9\x1d\xa7\x57\x83\xf3\ -\xf1\x5a\x8c\xbb\x11\x5b\x14\xc7\x09\x4d\x6f\x12\xcd\xf1\x3a\x10\ -\x82\x25\x93\x84\x2d\xb4\xbe\x65\xa0\xae\x18\x0d\x06\x56\x93\x61\ -\xb1\xdf\x66\xdf\x49\xb7\x88\xb7\x9b\xc7\x27\xd9\x7f\xad\x86\xeb\ -\xa9\x5a\xd1\x74\x92\x15\xfd\xdb\xe8\x9b\x7b\xc8\xc0\x92\xad\x65\ -\x49\x40\x93\xc7\x86\x09\x14\xc1\x90\xca\xfd\xab\xa6\xb7\x17\xc9\ -\xf4\xc8\x2a\xe1\xec\xec\xe4\x92\x08\x92\x3d\xf2\x04\xb6\xd2\x60\ -\x11\xe5\x31\xe9\x60\xba\xb7\x37\x21\xb0\x3d\x66\x04\x23\x3d\x43\ -\x1a\x4f\x88\xfa\x73\x4c\x25\x53\x53\x71\x19\x26\x60\x3c\xaa\x42\ -\x4a\xe2\xa2\xcd\x93\xad\xc4\x45\x51\x36\xde\xd8\x35\x7e\xa0\x92\ -\x51\xb5\xeb\xe9\x79\x80\xc3\x92\x72\xa7\x85\x32\xf8\x01\x0f\x8a\ -\x8c\xb1\xe8\x40\x02\x37\x62\xa9\x35\x89\x40\x18\x0b\x5f\xc9\xa9\ -\x59\x16\xcb\xed\x90\xcb\x2a\x74\xc0\x15\xb8\xaf\xbb\x71\x51\xee\ -\x6e\x34\x2f\x2e\x2f\x2f\x4f\x9b\xe7\x3e\x4e\xc7\xea\xe6\x72\x96\ -\xdd\x09\x61\x41\x86\x34\x32\x87\x85\xf2\x64\x99\x02\x21\x64\xc8\ -\x63\xaa\x19\x16\x5e\x32\x69\x9c\x39\x45\x1e\x63\xf2\x89\xdd\x1d\ -\x93\x27\xe4\x9a\x9c\x80\xf9\x6b\x7a\x94\x86\x94\xa8\x8b\x8b\xad\ -\x68\x8b\x29\x2f\x3e\x58\x6d\xb1\xaa\xdf\x5e\x6e\x67\xf6\x7e\xfb\ -\xc6\xfd\xf6\x75\xf5\xe5\x6b\x3e\x64\xb1\x79\x23\xe5\x01\x68\xcc\ -\xf2\xcd\x49\x69\x1e\xf6\x69\x35\x59\xd8\xad\xa8\x8f\x90\x0f\x3f\ -\x3d\x78\x0d\x52\xb5\xbf\xb1\x42\xd5\x75\x91\x00\x2d\xc9\xb6\x2e\ -\x94\x9f\x1b\x11\x81\xd1\x8a\x83\x4a\x23\xee\xe5\xba\xb6\x5c\xf4\ -\xf7\xba\xd6\x47\xd7\xae\x13\x60\xf8\x07\xb8\x75\xb3\xb7\x88\x8d\ -\x72\xc4\xc2\x81\x10\xf3\x91\xbd\x71\x1c\x58\x07\x4e\x0f\xa8\x36\ -\xf5\x04\x94\xe8\x44\x44\x8e\x0f\xbe\xe2\xdd\xae\xc8\x30\xe4\xbd\ -\x1e\xec\x14\xa1\x1d\x37\x87\x11\xec\x17\x4d\x52\xd6\x02\x4c\xb6\ -\x98\x5a\x32\x53\x79\x48\x15\x51\x80\x98\xc7\x9e\xb1\xa4\x94\xb6\ -\xb1\x0e\xc3\xc7\x7d\x60\x07\xcd\xf2\x24\x72\x71\x19\x70\x59\x9b\ -\x1b\x8a\xd8\x94\xc4\x85\x60\x94\xf3\xed\xc7\x85\xf4\x4c\xe5\xed\ -\x6d\x51\x91\x2d\xba\xf0\x33\x45\xeb\x86\x9f\x92\x44\x30\xde\x41\ -\xac\x2e\xa8\xcf\x28\x95\x1f\x2d\xbc\x37\x4a\xdb\x36\x4a\x4b\x92\ -\x76\x7f\x07\xb3\x94\xf0\xbf\x1d\xcf\x94\xaf\xa2\x28\x28\xf3\x22\ -\x7e\x38\xdd\xe7\x54\x12\xa1\x3f\x39\x3e\xad\x21\x42\x8f\xd3\x4b\ -\x04\x7d\xaf\x8a\x0b\xb7\x05\x9e\xdf\xe9\x58\x37\x1d\x96\xd1\xc5\ -\x3d\xc0\xa8\x3e\x4d\x5c\x1e\x66\xdc\x6b\xe2\x8d\x68\xe2\xa5\xa7\ -\xf6\xf8\xe4\x1c\xe7\xcf\xec\x41\x8e\x32\xcf\x4e\xbf\x94\x64\xab\ -\x6a\x8b\xf4\xdd\xf1\xc1\x07\xc0\x97\xc6\xe8\x4e\xd3\xd4\x93\x6a\ -\x1c\x0c\xd0\xaf\x7e\xf4\xe7\x58\xe8\xe7\x2f\x24\xa7\x91\xfd\x89\ -\x95\x19\xc9\x40\x4a\x4f\xa2\xfc\xad\x8a\xc6\x2a\xb9\xd3\xb5\x30\ -\xc9\x7b\xf6\xe7\x01\xe0\x63\x7f\x0d\x45\x2c\x92\xdb\x10\x49\xd2\ -\xa3\x43\x1e\x4d\x8a\xc6\x3d\x7a\xcf\xa2\xef\x0c\xbf\x2d\x76\x34\ -\x03\x6e\x1f\x32\xa8\x9a\xfd\x02\xb5\xc8\x1c\x14\x3c\xff\xec\xa5\ -\x88\x42\x7b\x5d\xc9\xab\xc6\x38\xc6\xfa\x80\x69\xc4\xfb\x31\xac\ -\xc6\x1c\x74\x10\x72\x94\xaf\x17\xd8\xff\x19\x79\xf8\x7f\xd3\xcb\ -\x1b\x49\x39\xb0\x4e\x7f\xd6\xf2\xf5\x15\xc3\x98\x39\xa0\xc1\xf4\ -\xea\x38\xac\x68\x54\xac\xc6\xda\x9b\x94\x42\x93\xb2\x42\xb9\x7f\ -\x61\xa8\x76\xdd\x33\x72\x67\x36\x65\x38\x8a\xf0\x33\x6b\x6a\xc0\ -\x58\x8d\x86\x65\xc9\x44\xf6\x96\x65\x23\x96\xe5\x2d\x8f\xd8\xab\ -\x81\x10\xa0\x63\xe7\x8c\x4b\x0f\xfa\x02\xdb\xb7\xcc\xbf\xe7\xf1\ -\xaa\xfe\xfd\x93\x93\x72\x02\x79\xd1\x67\xf5\x3c\x62\x98\xe7\x7e\ -\x77\xf6\x97\x29\x19\x0c\x30\x4c\x84\x45\x39\xd4\x7c\x1f\xc2\x55\ -\x10\xae\x28\x20\x7e\x4a\xd3\x62\xb5\x57\x9a\x0b\x94\xe6\x0a\xe7\ -\xc9\x15\x28\x4d\xff\xe4\xd6\x23\x3a\x1c\x3d\x27\x1f\x19\x0d\x41\ -\xa1\x51\x29\xc5\xad\x75\x27\x76\xb1\x50\x7e\x63\x65\xf2\x7c\x68\ -\xbf\xf9\xb5\xab\x5c\xe9\x57\xa2\xfd\x5a\x68\x72\x5e\x5f\x85\x38\ -\x0e\x7f\x59\xef\xf0\x57\xf5\x0d\xff\x8a\xcb\x00\x76\x06\x35\xd2\ -\xdf\x61\x50\xe3\x12\x38\x0c\x6a\x5c\x85\x0e\xa8\x96\x41\x9d\x8b\ -\x60\x11\xa8\x71\x0d\x2c\x02\x35\x2e\xc1\x4b\x1a\x7c\x53\x75\x2f\ -\xc3\x0c\x89\x1a\x97\x62\x86\x84\xd7\x72\xd4\xee\xaa\x78\xa6\x6f\ -\x9a\x4b\x6a\x6c\x17\x7a\x2b\x5f\x99\xfd\xbc\x7a\x2a\x76\x63\xe3\ -\x87\xa9\x9d\xd4\x2e\xba\x2b\x9b\xfa\xc2\x62\x6a\x9a\x58\x2e\x68\ -\xe2\x5d\x09\x25\x5c\x64\xcb\x38\xfb\x7a\x00\x1b\x9e\x34\x91\xa8\ -\x64\x24\xf9\x36\xfd\x31\x49\xb6\xc9\x00\x35\x62\x3d\x7d\xe4\x3e\ -\x74\xee\x06\xf9\xd0\xf9\x05\x4f\x42\x8d\x43\x2a\x7d\x0e\x6b\x5c\ -\xcd\x0b\xcb\x2c\xe0\xdf\xd1\x15\xfb\x08\x84\x26\x8f\xd3\xb4\xad\ -\xf1\xd5\xbd\xcf\x8b\x32\x9f\x0f\x44\x03\x79\xaa\x9f\x75\xbf\x27\ -\xf9\x22\x32\x25\xb9\xb0\xb3\xee\x7c\x7d\x47\x80\xd1\xf0\x12\x64\ -\x48\x04\x95\x6b\x9e\x25\x71\xa6\xf2\x43\xfd\xf7\x71\xa6\xad\xc6\ -\x99\x96\x54\xad\x3f\xe8\x38\xd3\x7b\x7c\x73\x05\x0f\x42\xc1\x74\ -\x89\x72\xaf\xb3\x50\x30\x35\x92\x05\x5a\xc8\x09\x9e\x8e\xa4\xdd\ -\xa7\x13\x51\x48\x90\x2e\x2a\xdd\xf8\x28\xd2\xcf\x47\x56\x72\x1e\ -\xf5\xf5\x73\x0c\x5a\xe1\xb9\x86\xb3\x8a\xa8\x24\x0f\x13\x86\x2c\ -\xc4\x08\x16\x9a\xa4\x44\x65\xba\x1c\x0e\xdc\x06\xe6\xca\x41\xd9\ -\xce\x39\xf1\x6e\x30\x64\x81\x5d\xb5\x4f\x7e\x3a\x39\xdb\x99\x81\ -\x35\xbb\x2f\x75\x53\xea\x0e\xa7\xbf\xa7\x09\x31\xfb\x42\xdc\xf5\ -\xe1\xc5\x21\x19\x52\xd9\xe7\xf1\xf5\x61\xb3\x79\x88\x25\x64\xad\ -\x11\xbf\x1b\xd2\x51\x52\x03\xd7\xfe\xf3\x93\xb9\x7e\x2b\xc5\xf0\ -\x27\x70\x56\x3a\x62\x2c\xb1\x66\x2a\x77\x17\x3c\x17\x8c\x95\x16\ -\x43\x3b\xa2\x32\x98\xa4\x5b\x2c\x96\x46\x5c\xdb\x46\x5a\x53\x92\ -\x0a\xf4\x33\xed\xe6\x16\xd0\xec\x2c\x0e\x55\xfb\xd7\xdf\xcc\x73\ -\xa0\xea\x5c\xc3\x81\x95\x26\x0c\x7d\x21\x84\x06\x02\x78\xcd\x69\ -\x24\xfa\xc7\x03\x14\x2e\xd3\x61\x08\x90\x1f\xb7\x1c\x91\xd4\x17\ -\xb8\x8b\x11\xf9\x34\x56\x83\xa4\x7f\x11\x32\x16\x59\xe5\x87\x49\ -\x4e\x81\x15\x62\x33\x4f\xbb\x45\x28\x21\xb4\x8d\xa1\xe5\xaa\x73\ -\x8a\x09\x34\xed\xdc\x0a\x2a\xcb\xd6\x6b\x7e\x51\xb7\x83\x96\x3b\ -\x70\xa0\x98\x44\xb3\xde\x2d\xd1\xc8\xee\x76\x16\x20\x33\xed\xdd\ -\x0a\x32\x49\x55\x41\x31\x32\xb3\xde\xad\x20\x93\x29\x36\x2b\xc6\ -\x28\x77\x8b\x3f\x5a\xd9\x06\x84\xd4\x92\x4c\x19\x45\xaa\x8c\xca\ -\x05\xdb\x1b\x33\x5b\x72\x6c\x67\x31\xbd\xb6\xa3\x2a\x40\x00\x60\ -\x17\x9c\x61\x81\x89\xf4\xd8\x8d\x8b\xde\x49\x3f\xa6\x51\x3b\x88\ -\xf0\x5d\xd6\xf0\x31\x1e\xe2\x80\x3b\x18\xdb\x6a\xee\x00\x17\x80\ -\xf1\xef\x69\x58\xb9\xb7\xca\x5b\x8d\xe9\x2d\x16\x64\x24\x74\x1b\ -\xcc\xe0\x9b\x18\xcf\x23\x9f\xc1\xc4\x66\x4b\x11\x3c\x15\xd9\x59\ -\x24\xfc\x4d\xf4\x64\x84\xae\xa6\x99\x5e\x26\xed\xd1\xba\x6b\x37\ -\x4f\x60\x80\xbb\xe4\x7a\xd2\x7e\x72\x09\xd7\x93\xc4\x9e\xe1\xe3\ -\xf3\x90\x42\x86\x47\xb9\x1b\xcf\x38\x0f\xee\xc9\xd9\x65\x0e\xdc\ -\x59\x11\x38\xfb\x53\xb9\xb5\xc9\xd0\x76\xab\xa4\x9e\xbe\xbe\x5c\ -\x2d\x91\x2f\xaf\x36\x49\xe3\xf3\xcb\xe6\xd6\x68\x7c\xb6\x39\x1a\ -\x5f\x54\x4b\xe3\xb3\x2c\x8d\x4f\x2f\xcf\xbd\x68\x7c\x7e\x92\x03\ -\x77\xb9\x83\x34\x4e\x0e\x6d\xad\x98\xb2\x67\x9b\xa4\xec\xd9\xc9\ -\x79\x16\xdc\xd3\x42\x61\xa8\x59\x43\x24\xa7\x96\x54\x4b\xd9\xf3\ -\xa7\x59\x41\xbe\xf0\xa2\x6c\xf3\x22\xa7\xca\x2f\xae\x76\x97\xb2\ -\x15\x6b\x83\x27\x79\x52\x14\x8a\xef\xbd\xad\xda\x55\x1e\xdc\xd3\ -\xd5\x28\x9b\xbe\x84\xfe\x56\x63\xcc\xdb\x07\xff\x07\x43\xae\x28\ -\x5c\ +\x00\x9b\x0d\x78\x9c\xed\x1d\xfd\x73\xda\xb8\xf2\xf7\xfc\x15\x9a\ +\xfc\xd0\xc9\x9b\xc9\x85\x40\xbe\x9a\x96\x70\xd3\xef\x76\xa6\x77\ +\xd7\x2b\x69\xef\xdd\xfb\xe5\x46\xd8\x02\xf4\x6a\x2c\x4e\x12\x49\ +\xb8\x79\x7f\xfc\xdb\x95\x6c\xb0\x8d\x31\x01\x61\x0c\x2d\x9d\xce\ +\xc4\x96\xec\xd5\x6a\xb5\x5f\xda\x5d\x8b\xe6\xcf\x0f\x83\x80\xdc\ +\x31\xa9\xb8\x08\x6f\x0e\xeb\x27\xa7\x87\x84\x85\x9e\xf0\x79\xd8\ +\xbb\x39\xfc\x72\xfb\xf6\xa7\xa7\x87\x3f\xb7\x0e\x9a\x23\x3e\x7d\ +\xe8\x1c\x1e\x6a\x1d\x90\xa6\x17\x50\xa5\x5a\xef\x46\xfc\xd9\xb3\ +\xd7\x9c\x06\xa2\x07\x7f\x83\x5e\x9b\x69\x0d\x2f\xab\xd7\x92\x76\ +\x75\xb3\x66\x1f\x82\xa7\xef\xb9\xdf\x63\x9a\x98\xfb\x9b\xc3\xdf\ +\xff\x30\xb7\x87\x24\xa4\x03\x76\x73\x58\x08\x04\x07\x23\xcd\xa1\ +\x14\x43\x26\xf5\x38\x7a\xa3\xc7\xc4\x80\x69\x39\x36\x9d\xa4\x29\ +\x99\xa7\xcd\x15\x69\x3e\xb4\x4e\x9b\xb5\x87\xe8\x66\x8c\x37\xe3\ +\xe8\x06\x50\xd0\xfd\xd6\xc5\x35\x34\xd9\x4b\xdb\xdc\x67\xbc\xd7\ +\xd7\xad\xcb\xb3\x46\xb3\x16\x5d\x1b\x98\xb5\x18\x68\xb3\x16\x0f\ +\x9e\x87\xc9\x3d\x0f\x7d\x71\x7f\xcb\x75\xc0\x22\x64\x94\x96\x80\ +\x7c\xeb\x1d\x0b\x99\xa4\x01\x51\xd1\x64\x9a\xb5\xa8\x63\x16\x64\ +\x40\xc7\x62\x34\x25\xce\xd7\x97\xe2\xe1\xa3\x69\x8a\x20\x66\x86\ +\x54\x43\xea\x01\xa0\xc3\x68\x02\xe1\x68\xd0\x61\xb2\x75\xd9\xac\ +\x45\x57\x16\xfd\xe4\x08\x33\x20\x06\x54\xf6\x78\x98\x81\x70\x5d\ +\x08\x81\x6b\x36\x98\x52\x32\xb9\x98\xef\xa4\x18\x0d\x01\xe7\x78\ +\x39\x7b\xf1\xbd\x7d\x7c\x66\x70\x3d\x25\x56\x0e\xbd\xcc\xa2\x93\ +\x76\x0e\xd5\x66\x91\x2a\xa4\x5d\x34\x1a\x30\xae\xe6\x1e\x0d\x6c\ +\xeb\x5f\x8d\xe9\xc0\xd3\x19\xe5\x00\x7a\x3f\x03\xa8\x2f\x24\xff\ +\x47\x84\x7a\x02\xaa\x7e\x3d\x81\x95\x85\x36\x4b\xa4\x8f\xb4\xc3\ +\x82\x18\x54\x80\x37\xe9\xf7\x73\xc8\xc4\x1e\x74\xea\x81\x09\xa9\ +\x2c\x89\x78\xa8\x99\xec\x52\x8f\x91\x81\xf0\x59\x86\x50\xf9\xd4\ +\xb2\x8d\x16\xb3\x04\xea\xb5\x34\xee\x0b\xa6\x62\xa4\xf5\x93\x64\ +\xdd\x57\x62\xd0\x11\xc9\x75\xc7\x8e\x21\x74\x78\xd8\xd1\x11\x0f\ +\x7f\x9d\x17\x4f\x50\x88\xe0\x96\x0f\xf3\xe7\x78\xdb\xe7\x8a\xc0\ +\x7f\xdd\x67\xe4\xcb\x07\x33\x45\x98\x31\xb9\xef\x73\xaf\x6f\x1a\ +\x2d\x11\xa0\x7d\x14\x30\x72\xcf\x83\x80\xdc\x0b\xf9\xed\x19\xb9\ +\x05\xa8\x1d\x2a\xed\x1b\xa6\x7d\x18\x20\x91\x68\x10\xf3\x56\x2c\ +\x91\x08\x8f\xc2\xdd\x90\x4a\xaa\x19\xd1\xf6\xc5\x63\x1c\x03\x40\ +\x6a\xaa\xbe\xa5\xe1\x8c\x14\x33\x23\xbf\x95\x8c\xbd\x7a\xf1\x9a\ +\xdc\xc2\x13\x77\x9c\xdd\x13\x35\x56\x40\x31\xd2\x15\xd2\x8c\xc2\ +\xb5\xc2\x67\xa5\x5d\x21\xea\x69\xd0\x9b\x8f\x5e\x9e\x19\x2a\x21\ +\x41\xdf\x84\xa8\xeb\x88\xd2\x3e\xe0\x7e\x73\x78\x9a\x21\x99\x17\ +\xc1\xfe\xc2\x7f\x31\x9c\xe0\xb9\x8c\xf5\x89\xea\xfe\xe2\xa1\x60\ +\xa0\x5a\xac\xe3\x1f\x3d\x5a\x86\xaf\x1e\xc3\xf2\x53\x7e\xb0\xab\ +\x93\x47\xc7\x79\xc3\xd5\xb2\xe3\xb9\x21\x10\xad\xb6\x0b\x06\x0b\ +\x65\xaf\x59\xb3\x6a\x68\xa2\xa3\x52\xdd\xce\x1a\xab\xe1\xa6\xb0\ +\x1a\xab\xea\x2b\xd6\xa5\xa3\x00\x40\x8b\x40\xe4\xae\x60\xe9\x8a\ +\x0a\xc6\x7d\x39\xd2\x5a\x84\x39\xba\x0a\xfa\x3a\xb6\x6f\x65\x65\ +\x85\x5a\xc1\x4f\x4e\xd2\xe8\x82\x10\x54\x83\xe8\xfc\x17\xdc\x88\ +\xac\x19\x2b\xe2\x99\xcc\xb8\x06\x5c\x56\x08\xb1\x2d\xc3\xa5\x92\ +\xf9\xe8\xec\xe0\x9f\x74\x47\x0f\xb4\x55\x88\x5d\xf6\x22\xdd\xd9\ +\x09\x46\x0c\xfb\xcc\xdf\x34\x43\xcf\x0c\xb2\x76\x75\x15\xb1\xc3\ +\x76\x6a\x2b\x67\xee\xcb\x13\xa0\x05\xf6\x70\xae\x00\xb5\x43\x3a\ +\xdc\x76\xe9\x59\xa4\x1d\x96\x97\x1f\x85\xb3\x56\x63\xf0\x25\x82\ +\xbd\x00\xa5\xd0\x8f\x68\x81\x04\xfa\xf1\x84\x68\x55\xaf\xf9\x95\ +\x08\xe1\x6a\x64\xdc\xb1\xad\x17\xa6\xb3\xf5\x78\xce\xb3\x42\x15\ +\x19\x24\xd2\x61\xf0\x2c\xf1\x25\xbd\x0f\x23\x87\x97\x23\x55\x12\ +\x24\x42\xc7\xf7\x64\x33\x72\x77\x7e\x3e\x5f\xf0\xea\x8d\x8b\x02\ +\xd1\x6b\x5c\x5c\x54\x66\xbd\xa6\xb4\xfa\xf1\x84\x70\x01\x7f\x2e\ +\x74\x05\x03\x0e\xde\x11\x46\x61\x2a\x90\xc1\xf6\x90\x87\x79\xdb\ +\x56\x05\xed\x9d\x69\xd8\x22\x7f\x66\x8f\x35\x63\x93\x09\xae\xcf\ +\x15\xbc\xa3\xc0\xe7\x99\x91\xa3\x80\x4d\x23\x15\xba\x59\x0a\xea\ +\x12\x2c\x9f\x58\xb4\x1d\x65\xf5\x92\xf7\x57\x67\x8e\xfb\xab\x53\ +\x27\xd3\x46\xb9\x51\xda\x5b\x19\x09\xba\x70\xb1\x67\x8c\x4c\x26\ +\x88\x46\x0b\xe6\xc8\xbb\x9c\x49\xf2\x8d\x8d\x37\x12\x57\x81\x01\ +\xbd\x18\x81\x6d\x65\x7d\xb7\xe0\x86\xea\x73\x1c\xac\xaa\xd8\x8a\ +\xa7\x65\x50\xdd\xe8\x34\x70\x9a\xfa\x0a\x62\x84\x11\x7c\xe0\xdf\ +\xac\x16\x69\x9b\xe6\x05\xb2\x02\x4f\x33\x78\x18\xdd\x8e\x0c\xf7\ +\x30\x30\x01\xad\xdf\xf5\xb3\x67\xef\x27\x10\x9b\x35\xd3\xb8\x34\ +\xab\x2a\xfe\x0f\x7b\xcf\x43\x3d\x9f\x55\xf1\x89\x0c\x39\x6d\x56\ +\xe5\x3c\x9d\x5f\x99\xf4\x46\xb9\x95\xc6\x69\x2a\xcd\x32\x45\x2b\ +\x0b\x70\x8e\xca\xb2\xa4\x5b\xab\x2f\xd3\xa8\xbb\x6c\xcb\xb7\x55\ +\xe3\x5e\xba\x69\x5c\x15\xcd\x6d\x0d\x9a\xd6\x1b\x49\x09\x2c\xfb\ +\x21\xf4\xd9\x43\xbe\xfb\x52\xdf\x88\xfb\x02\xb3\xc1\x59\xed\x35\ +\xb8\x6d\xdd\x6b\xf0\x69\xc3\x9a\x35\x78\xb1\xec\xed\x35\xf8\xda\ +\x35\xf8\xaa\x99\x89\x17\x81\xde\x5a\x05\x7e\xe5\xa6\xc0\xa9\x9d\ +\xda\x46\xf4\xf7\x66\xb6\x9f\x30\x1b\x23\xe8\x7b\xf5\xbd\x57\xdf\ +\xdb\x94\x55\xad\x27\xb9\x68\x95\x3a\x10\xb7\x6d\x7f\x14\xae\x35\ +\x55\x37\xe6\x95\x0a\xb4\xd9\x47\x1e\xb2\x37\x3e\xd7\x33\xda\x0c\ +\x43\x46\x0c\x3a\x5c\xb2\x43\x79\x01\xed\xe9\x6c\x4d\x7c\x2d\x15\ +\xb8\x8e\x8b\xc3\x56\xd7\x78\x8f\x23\xf9\x46\x62\x0f\xc9\x99\x99\ +\x49\xdb\x15\xde\x4e\x1d\x58\xb5\x24\x9e\x3f\x5e\x10\xa7\x86\xb8\ +\xcf\xbc\x6f\xb9\x86\x18\x3b\x9c\xe2\xc1\x06\x02\xb0\x2d\xb2\x6f\ +\x97\x00\x86\xe4\x9e\x86\x9a\x68\x31\x29\x25\x32\x89\x83\x5a\x22\ +\x56\x2c\xc5\xc0\x74\x44\xc5\x48\x84\xaa\x98\xe5\xcb\xe0\xe6\x36\ +\xbd\x03\x1c\xac\x79\x8f\x72\x44\x34\xf4\x13\xb1\x6b\xea\x49\xa1\ +\x14\x51\x4c\x61\xf1\xa7\x43\xec\x7a\x99\xac\x26\x20\x25\x42\xf6\ +\xc0\xb7\xd6\xd4\x57\xcd\xe6\x57\x65\xb0\xb9\x4b\x88\xf6\x43\x37\ +\xe2\x72\x45\x0c\x38\xe6\x1f\x03\x3b\x0d\xc7\x89\xe2\xb9\x0e\x03\ +\x27\x74\xa8\x63\x8e\x02\x2f\x77\x00\xac\x76\x4c\x04\x70\xbb\xbc\ +\xe7\x8a\xc5\x4d\xca\x3e\x4f\x83\x7b\x3a\x06\xce\xd3\x54\x62\xa9\ +\x23\x09\xc5\x4f\x13\x88\x65\x88\xc2\xbb\x40\x74\x68\x40\xd6\x30\ +\x46\x44\x81\xcc\x30\x1d\xa0\x5f\x0b\x14\x39\x00\x36\x97\xe5\xda\ +\x8c\xe1\x78\xb0\xc5\x95\x80\x55\xcb\x4f\xfd\x69\x29\x02\xe4\x90\ +\xb3\xff\x55\xc8\x01\x0d\x82\xf1\x31\x01\x42\x32\x69\xd8\x10\x53\ +\x1d\x51\xce\xf0\x38\x32\x16\x43\xce\x14\x41\xe4\x14\x0b\xa0\x9d\ +\xf9\x27\x24\x16\x3d\x31\x34\xbe\x4f\x52\x02\xf1\x9d\x0e\x05\xc9\ +\x8a\x73\xfe\xb1\x20\xc6\x6f\x83\x5c\x29\xcd\xa8\xef\x90\xe5\x2f\ +\xb0\x2d\x66\x90\x34\x02\xa9\xc9\x6d\xc6\x98\x18\x2c\x5e\x02\x12\ +\xbf\xc5\xe9\xd7\xbd\x4c\xe4\xc9\xc4\x45\x29\x22\xf1\x74\xbd\x36\ +\xc5\xb8\x50\x49\xeb\x80\x41\x6a\x70\xa7\xc0\x59\x50\x3a\x21\x2f\ +\x51\x45\x0b\x56\xb7\x40\xab\x11\x92\x50\xe8\xc4\xfb\x1d\x1b\xe0\ +\x1e\x9a\x77\xc2\x60\x0c\x2f\xb0\x90\x00\xea\xe0\xe7\x40\xd3\xab\ +\xdb\xcf\x1f\x4b\x11\x8a\x17\x69\xbc\x63\x74\x8f\x7c\xae\x68\x27\ +\x98\x46\xdd\x31\x60\xf3\xaf\x5d\x36\x41\x76\x81\xda\x5b\x1c\x6e\ +\x5f\x7b\xd0\xb7\x78\x87\xbb\x0f\xfa\xae\x3b\xe8\x5b\x77\x0c\x90\ +\x4a\xea\xf3\x91\x9a\x54\x9a\x1a\x5d\x00\x32\xa9\x86\xcc\xe3\xe0\ +\x09\x0e\x05\x10\x52\x9d\xe0\x97\x48\xd8\x7c\x6a\xeb\x78\x04\x01\ +\x51\xd5\x34\xf4\x18\x39\xe2\x61\x97\x87\x80\xb7\x83\xa0\x2e\xc8\ +\x2d\x4a\x1a\xf6\xaa\x08\xe7\x2c\xa8\x90\x5a\xc0\xea\x6a\xd4\xed\ +\xf2\x6c\xa4\x38\x9a\xc3\xf0\x61\x33\x66\x1f\xa8\xf7\xd9\x12\x6f\ +\x47\xb5\x4f\xd9\x5f\x82\x2c\x11\xb3\x5c\xc2\xde\x3b\x7c\xf0\x95\ +\x67\xef\x27\x72\x69\x8c\x36\x98\x70\x22\x3c\x6f\x24\x09\xed\x51\ +\x74\x5d\x13\x8e\xad\xee\x83\xd9\x94\x18\x54\xa1\xa1\x71\x7c\x79\ +\xe8\x73\x8f\xa2\x93\x6b\x33\x13\x44\x74\x09\x83\x59\x39\xc4\x30\ +\x16\x15\x02\xd0\x07\x3e\x18\x0d\x76\xd9\x6a\xc3\x14\x7e\x24\x93\ +\xbd\x37\xd8\xf3\x29\x5d\x46\x96\xd6\x61\x83\xfc\x8b\x15\xae\xac\ +\x30\xa3\x65\xee\x30\x13\xfe\xe7\x3e\x93\x20\xed\x49\x73\x5e\x86\ +\xa8\xcf\x41\x64\x0b\x8d\x74\x71\x11\x42\xa4\xad\xf2\xf3\xb9\xd7\ +\xd7\xd7\xab\x67\x74\x8b\xca\x94\xcf\x37\x93\x28\xb6\x6a\xec\x8d\ +\x5d\x98\x1d\xd5\x65\x65\x3b\x00\xf5\x52\x1c\x00\x07\x9f\x1c\x1c\ +\x80\x54\xe8\xaa\x6d\x37\xc9\x36\x0f\x32\xd9\xb5\xf7\x85\xf9\x60\ +\x85\x85\xec\x0e\xc4\x0f\x37\xf4\x98\x4b\x29\x53\xe2\xdb\x30\x64\ +\x7c\x2a\x41\x02\xa5\x5d\xb6\xf3\x48\x45\x9c\xcb\x4b\xfa\xfd\x7e\ +\xb5\xb2\x04\xd3\xae\xfa\x45\xd9\x7b\xb0\x39\xf1\x99\x02\x49\x66\ +\xb5\x61\x4e\xe0\xcb\x8d\xec\x75\xfa\x80\xc5\xae\x2f\x66\xc9\xca\ +\xae\x9c\x78\xbf\x43\x85\x6d\xde\x66\x27\x15\xa5\x07\x75\xc6\x6c\ +\xfa\xb7\x0b\xb7\xe0\xd7\x4c\x13\xc1\x27\xe4\xb7\x38\x67\x66\x14\ +\xe5\x38\xfb\xc6\x3d\x07\x2c\xe5\x32\x85\x20\x4b\xf0\xfc\x5b\x1c\ +\x6b\xf2\x11\xe1\xd8\x3d\x3b\xbd\x04\xa7\x23\x29\xf6\x79\xad\xf9\ +\x6c\xee\x7a\x1e\x8d\xeb\xf9\x0e\x78\x00\x0b\xee\xd6\x87\x01\x0d\ +\xb7\xf3\x40\x9a\xe2\x19\x2e\xc1\x8a\x11\xdb\xff\xf1\x69\x5b\x79\ +\xd1\xad\x22\xef\x57\x91\xbf\x80\x9b\xa9\x07\xfc\xf7\x9f\xe4\xe8\ +\x56\x0c\x73\xe3\xaa\x1b\xc2\xe0\x3f\xe4\xe8\xad\x04\xd9\xaa\x10\ +\x87\x3f\x01\x87\x36\xd8\x76\x27\x14\xaa\x56\x49\xf5\x72\x6a\x55\ +\x1c\xaa\x09\x93\xdb\x0c\x4a\x7a\x92\xfb\x29\xfb\x69\x12\x81\x51\ +\xe2\xb0\x0c\xfb\xf9\x05\x76\x2b\x38\xe8\x2e\x6f\x1f\x2c\xfe\xdb\ +\xa9\xf7\xd6\x9e\xd6\x2b\xde\xd1\xee\xa3\x84\x6b\x4f\xeb\x2d\xa8\ +\x43\x9b\x5f\xc1\x85\xa2\x1c\x9d\x8d\x58\x81\xf3\xf1\x5a\x8c\x3a\ +\x01\x9b\x17\x94\xf3\x4d\x6f\x1c\x9a\x73\x3a\xdd\x83\xc5\x93\x24\ +\x1d\xa6\xef\x19\xa8\x2b\x46\xbd\xbe\xd5\x64\x58\xb9\xb9\xde\x03\ +\x06\x2c\xe2\xad\xfa\xc9\x69\xfa\x5f\xb3\x16\xf5\x94\xad\x68\xda\ +\xf1\x8a\x7e\x37\xfa\xe6\x11\x32\xb0\x60\x6b\x59\x10\x9d\xe6\xa1\ +\x61\x02\x45\x30\x3e\xf6\xf8\x12\xf8\xcd\x85\xa5\x1d\x52\x84\x38\ +\x3b\x3b\xb9\x38\x1c\x68\xcf\xaf\x81\xad\x34\x58\x44\x79\x42\xda\ +\x98\xbb\xef\x8e\x09\x6c\x8f\x19\xc1\xb0\xdd\x80\x86\x63\xa2\xfe\ +\x1e\x51\xc9\xd4\x44\x5c\x06\x31\x18\x87\x12\x9f\x82\x20\x77\xfd\ +\x74\x23\x41\x6e\x94\x8d\x37\x76\x8d\x77\x54\x32\xca\x76\x3d\x1d\ +\x4f\xe3\x58\x50\xbb\x36\x57\x06\x3f\xe0\xa9\x9f\x21\x56\x90\x48\ +\xe0\x46\xac\x9b\x27\x01\x08\x63\xee\xf7\x55\x15\xcb\x62\xb1\x1d\ +\x8a\x52\x44\x6d\x70\x05\x1e\xeb\x6e\x5c\x16\xbb\x1b\xf5\xcb\xab\ +\xab\xab\x46\xfd\xc2\xc5\xe9\x58\xde\x5c\x4e\x53\x75\x3e\x2c\xc8\ +\x80\x06\xe6\xe4\x57\x1e\x2f\x93\x27\x84\xf4\x79\x48\x35\xc3\x2a\ +\x5a\x26\x8d\x33\xa7\xc8\x11\x66\x12\xd9\xc3\x09\x39\x23\x37\xe4\ +\x14\xcc\x5f\xdd\xa1\xce\xa7\x40\x5d\x5c\x6e\x44\x5b\x4c\x78\x71\ +\x67\xb5\xc5\xb2\x7e\x7b\xb1\x9d\xd9\xfb\xed\x6b\xf7\xdb\x57\xd5\ +\x97\xaf\xf9\x80\x85\xe6\xf3\xa2\x1d\xd0\x98\xc5\x9b\x93\xc2\xa4\ +\xfa\xd3\x72\x52\xea\x1b\x51\x1f\x3e\x1f\x7c\xda\x79\x0d\x52\xb6\ +\xbf\xb1\x44\x09\x7d\x9e\x00\x2d\x48\x9d\xcf\x95\x9f\x5b\x11\x80\ +\xd1\x0a\xbd\x52\x23\xee\xc5\xba\xb6\x58\xf4\xf7\xba\xd6\x45\xd7\ +\xae\x12\x60\xf8\x01\xdc\xba\xe9\x27\xe1\x46\x39\x62\xb6\xdd\xc7\ +\x7c\x64\x77\x14\x7a\xd6\x81\xd3\x7d\xaa\x4d\x71\x08\x25\x3a\x16\ +\x91\x93\x83\xaf\xf8\x74\x54\x31\xea\xf3\x6e\x17\x76\x8a\xd0\x8e\ +\x9b\xc3\x00\xf6\x8b\x26\x29\x6b\x01\xc6\x5b\x4c\x2d\x99\x29\x23\ +\xa5\x8a\x28\x40\xcc\x61\xcf\x58\x50\x17\x5d\x5b\x85\xe1\xc3\x1e\ +\xb0\x83\x66\x59\x12\x45\x71\x19\x70\x59\xeb\x6b\x8a\xd8\x14\xc4\ +\x85\x60\x94\x8b\xcd\xc7\x85\xf4\x54\xe5\xed\x6d\x51\x9e\x2d\xba\ +\x74\x33\x45\xab\x86\x9f\xe2\x44\x30\x3e\x41\xac\x2e\xa8\xce\x28\ +\x15\x57\xf5\xec\x8d\xd2\xa6\x8d\xd2\x82\xa4\xdd\xf7\x60\x96\x62\ +\xfe\xb7\xe3\x99\x5a\x64\x14\x05\x65\x4e\x55\xf0\x27\xfb\x9c\x52\ +\x22\xf4\xa7\x27\x8d\x0a\x22\xf4\x38\xbd\x58\xd0\xf7\xaa\x38\x77\ +\x5b\xe0\xf8\xa3\x2b\xab\xa6\xc3\x52\xba\xb8\x0b\x18\x55\xa7\x89\ +\x8b\xc3\x8c\x7b\x4d\xbc\x16\x4d\xbc\xf0\x08\x26\x97\x9c\xe3\xec\ +\x01\x4c\xc8\x51\xe6\xdd\xc9\xcf\x5e\xd9\x42\xd8\x3c\x7d\x77\x72\ +\xf0\x01\xf0\xa5\x21\xba\xd3\x34\xf1\xa6\x1a\x79\x7d\xf4\xab\x9f\ +\xfc\x3d\x12\xfa\xf9\x0b\xc9\x69\x60\x2f\xb1\x32\x23\x1e\x48\xe9\ +\x71\x90\x7d\x54\xd1\x50\xc5\x4f\x46\x2d\x4c\xf2\xae\xbd\x3c\x00\ +\x7c\xec\xd5\x40\x84\x22\x7e\x0c\x91\x24\x5d\x3a\xe0\xc1\x38\x6f\ +\xdc\xe3\xf7\x2c\xb8\x63\xf8\x43\x71\xc7\x53\xe0\xf6\x25\x83\xaa\ +\xd9\x2f\x50\x8b\xcc\x41\xce\xfb\xcf\x5e\x8a\xc0\xb7\xf7\xa5\x7c\ +\x37\x8e\x63\xac\x0e\x98\x06\xbc\x17\xc2\x6a\xcc\x40\x07\x21\x47\ +\xf9\x7a\x81\xfd\x9f\x91\x87\xff\x37\xb9\xbd\x95\x94\x03\xeb\xf4\ +\xa6\x2d\x5f\x5f\x31\x8c\x99\x03\x1a\x4c\x2f\x8f\xc3\x92\x46\xc5\ +\x6a\xac\xbd\x49\xc9\x35\x29\x4b\x7c\xbb\x91\x1b\xaa\x5d\xf5\xc0\ +\xe3\xa9\x4d\x19\x0c\x03\xfc\xcd\x3c\xd5\x67\xac\x42\xc3\xb2\x60\ +\x22\x7b\xcb\xb2\x16\xcb\xf2\x96\x07\xec\x55\x5f\x08\xd0\xb1\x33\ +\xc6\xa5\x0b\x7d\x9e\xed\x5b\xe4\xdf\xf3\x70\x59\xff\xfe\xec\xb4\ +\x98\x40\x4e\xf4\x59\x3e\x8f\xe8\x67\xb9\x3f\x3a\xc8\xcd\x94\x0c\ +\x7a\x18\x26\xc2\xa2\x1c\x6a\x7e\xec\x23\xaa\x20\x5c\x52\x40\xdc\ +\x94\xa6\xc5\x6a\xaf\x34\xe7\x28\xcd\x25\x0e\x07\xcc\x51\x9a\xee\ +\xc9\xad\x27\x74\x30\x7c\x4e\x3e\x32\xea\x83\x42\xa3\x52\x8a\x7b\ +\xeb\x4e\x6c\x63\xa1\xfc\xda\xca\xe4\xf9\xc0\xfe\x80\xdb\xb6\x72\ +\xa5\x5b\x89\xf6\x6b\xa1\xc9\x45\x75\x15\xe2\x38\xfc\x55\xb5\xc3\ +\x5f\x57\x37\xfc\x2b\x2e\x3d\xd8\x19\x54\x48\xff\x08\x83\x0a\x97\ +\x20\xc2\xa0\xc2\x55\x68\x83\x6a\xe9\x57\xb9\x08\x16\x81\x0a\xd7\ +\xc0\x22\x50\xe1\x12\xbc\xa4\xde\x37\x55\xf5\x32\x4c\x91\xa8\x70\ +\x29\xa6\x48\x38\x2d\x47\xe5\xae\x8a\x63\xfa\xa6\xbe\xa0\xc6\x76\ +\xae\xb7\xf2\x15\x9e\xe2\x1e\x0d\x12\xb1\x1b\x1b\x3f\x4c\xec\xa4\ +\xb6\xd1\x5d\x59\xd7\xcf\x65\x26\xa6\x89\xe5\x82\x26\xde\x15\x53\ +\x22\x8a\x6c\x19\x67\x5f\xf7\x61\xc3\x93\x24\x12\x95\x8c\xdc\x45\ +\xc4\x3b\x21\xf1\x36\x19\xa0\x06\xac\xab\x8f\xa3\x5f\xad\x8f\x06\ +\xf9\xd0\xfe\x0d\x8f\xb5\x0d\x7d\x2a\x5d\x4e\xde\x5c\xce\x0b\x4b\ +\x2d\xe0\xf7\xe8\x8a\x7d\x04\x42\x93\xa3\x24\x6d\x2b\xfc\x74\xef\ +\xf3\xbc\xcc\xe7\x8e\x68\x20\x47\xf5\xb3\xea\x8f\x83\xbe\x08\x4c\ +\x49\x2e\xec\xac\xdb\x5f\xdf\x11\x60\x34\xbc\x05\x19\x12\x5e\xe9\ +\x9a\x67\x41\x9c\xa9\xf8\x17\x1a\xf6\x71\xa6\x8d\xc6\x99\x16\x54\ +\xad\xef\x74\x9c\xe9\x3d\x7e\xb9\x82\xa7\xda\x60\xba\x44\x45\x9f\ +\xb3\x50\x30\x35\x92\x79\x5a\xc8\x31\x1e\x75\xa5\xa3\xdf\xc1\x44\ +\x21\x41\xba\xa8\x64\xe3\x93\x40\x3f\x1f\x5a\xc9\x79\xd2\xd3\xcf\ +\x31\x68\x85\x87\x54\x4e\x2b\xa2\xe2\x3c\x8c\xef\x33\x1f\x23\x58\ +\x68\x92\x62\x95\x19\xe5\x70\xe0\x31\x30\x57\x11\x94\xcd\x1c\xfa\ +\x1f\x0d\x86\x2c\xb0\xad\xf6\xc9\x4d\x27\xa7\x3b\x53\xb0\xa6\xcf\ +\x25\x1e\x4a\x3c\x11\xe9\xef\x49\x42\xcc\x7e\x10\x77\x73\x78\x79\ +\x48\x06\x54\xf6\x78\x78\x73\x58\xaf\x1f\x62\x09\x59\x73\xc8\x1f\ +\x06\x74\x18\xd7\xc0\xb5\xfe\xfe\x64\xee\xdf\x4a\x31\xf8\x05\x9c\ +\x95\xb6\x18\x49\xac\x99\xca\x3c\x05\xef\x79\x23\xa5\xc5\xc0\x8e\ +\xa8\x0c\x26\xc9\x16\x8b\xa5\x11\xd7\x96\x91\xd6\x84\xa4\x02\xfd\ +\x4c\xbb\x79\x04\x34\x3b\x0b\x7d\xd5\xfa\xfd\x0f\xf3\x1e\xa8\xba\ +\xa8\xe1\xc0\x4a\x13\x86\xbe\x10\x42\x0d\x01\xbc\xe6\x34\x10\xbd\ +\x93\x3e\x0a\x97\xe9\x30\x04\xc8\x8e\x5b\x8c\x48\xe2\xe7\xd4\xf3\ +\x11\xf9\x34\x52\xfd\xb8\x7f\x1e\x32\x16\x59\xe5\x86\x49\x46\x81\ +\xe5\x62\x33\x4b\xbb\x79\x28\x21\xb4\xb5\xa1\x15\x55\xe7\xe4\x13\ +\x68\xd2\xb9\x11\x54\x16\xad\xd7\xec\xa2\x6e\x06\xad\xe8\xc0\x81\ +\x7c\x12\x4d\x7b\x37\x44\x23\xbb\xdb\x99\x83\xcc\xa4\x77\x23\xc8\ +\xc4\x55\x05\xf9\xc8\x4c\x7b\x37\x82\x4c\xaa\xd8\x2c\x1f\xa3\xcc\ +\x23\xee\x68\xa5\x1b\x10\x52\x53\x32\x65\x14\xa9\x32\x2a\x17\x6c\ +\x6f\xc8\x6c\xc9\xb1\x9d\xc5\xe4\xde\x8e\xaa\x00\x01\x80\x9d\x73\ +\x86\x05\x26\xd2\xc3\x68\x5c\xf4\x4e\x7a\x21\x0d\x5a\x5e\x80\xdf\ +\xb2\xfa\x47\x78\x88\x03\xee\x60\x6c\xab\x79\x02\x5c\x00\xc6\xef\ +\x92\xb0\x32\x5f\x95\x37\x6b\x93\x47\x2c\xc8\x40\xe8\x16\x98\xc1\ +\x37\x21\x1e\x2e\x3f\x85\x89\xcd\x96\x22\x78\xc4\x75\x64\x91\xf0\ +\x9a\xe8\xf1\x10\x5d\x4d\x33\xbd\x54\xda\xa3\xf9\xd0\xba\x06\x84\ +\x1f\xe2\xdb\x71\xeb\xec\xea\xba\x59\x1b\xc7\xe6\x0c\xdf\x9e\x05\ +\xe4\x33\x3c\x96\xdf\x38\xc6\x59\x68\xe7\xf5\xab\x34\xb8\xa7\xf5\ +\x3c\x70\xf6\x52\x45\x4b\x93\x22\xed\x46\x29\x3d\xf9\x7a\xb9\x5c\ +\x1a\x23\x4d\x53\x34\x3e\x73\xa1\xf1\xc5\x55\x3d\x03\xee\xbc\x34\ +\x1a\x9f\xaf\x8f\xc6\x97\xe5\xd2\xf8\x32\xcd\x78\x8d\xab\xd3\x75\ +\xd2\xb8\x71\xd5\xd8\x42\x1a\xc7\x07\xf0\x96\x4c\xd9\xc6\x5a\x29\ +\x5b\xbf\xdc\x18\x65\x57\xd7\x10\xf1\xa1\x25\xe5\x52\xf6\xe2\x69\ +\x5a\x90\x2f\x2f\x5c\x28\x7b\x76\x71\xbe\x03\xba\x37\x3e\x0a\xa3\ +\x5c\xca\x9e\x9d\x65\x28\x7b\xb5\x4e\x9e\x2d\x93\xb2\x57\xee\x1a\ +\x77\x7a\x02\x6a\xb9\x44\xae\x67\xf8\xb7\x71\xed\xa4\x19\xce\x31\ +\x5e\x93\x02\x97\x6b\x26\xe7\x53\x39\x79\x0b\xfd\xcd\xda\x88\xb7\ +\x0e\xfe\x0f\x26\xd1\x19\x22\ \x00\x00\x07\xb5\ \x00\ \x00\x1a\x6e\x78\x9c\xed\x58\x5d\x6f\xe3\xb8\x15\x7d\xcf\xaf\x50\ @@ -34855,58 +34858,58 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xbf\xb3\ -\x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x11\x60\ -\x00\x00\x08\x1c\x00\x01\x00\x00\x00\x01\x00\x07\x73\x7d\ -\x00\x00\x0a\x3e\x00\x01\x00\x00\x00\x01\x00\x08\x27\xb5\ -\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x5c\x47\ -\x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xdc\xfd\ -\x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x35\x9b\ -\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x07\x06\xcc\ -\x00\x00\x08\xb6\x00\x01\x00\x00\x00\x01\x00\x07\xad\x0c\ -\x00\x00\x0a\x8e\x00\x01\x00\x00\x00\x01\x00\x08\x43\xc5\ -\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x2a\x82\ -\x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x3b\x5f\ -\x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xca\x67\ -\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x30\x01\ -\x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xf5\xc2\ -\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x20\x16\ -\x00\x00\x09\xc8\x00\x00\x00\x00\x00\x01\x00\x08\x09\xfb\ -\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\xaa\ -\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x77\x66\ -\x00\x00\x09\x80\x00\x01\x00\x00\x00\x01\x00\x07\xf6\x05\ -\x00\x00\x09\xa2\x00\x01\x00\x00\x00\x01\x00\x08\x00\x67\ -\x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x65\x4d\ -\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe3\xf1\ -\x00\x00\x07\xd2\x00\x01\x00\x00\x00\x01\x00\x07\x5c\x53\ -\x00\x00\x09\x10\x00\x00\x00\x00\x00\x01\x00\x07\xbd\x54\ -\x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x88\xd6\ -\x00\x00\x09\x34\x00\x00\x00\x00\x00\x01\x00\x07\xd4\x07\ -\x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x1d\x6e\ -\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x4b\x69\ -\x00\x00\x0a\x5e\x00\x00\x00\x00\x00\x01\x00\x08\x32\x4f\ -\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x15\ -\x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x05\xf3\xb1\ -\x00\x00\x0a\xbe\x00\x00\x00\x00\x00\x01\x00\x08\x4f\x9e\ -\x00\x00\x09\x58\x00\x00\x00\x00\x00\x01\x00\x07\xe6\xde\ -\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x06\x08\xd1\ -\x00\x00\x08\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x7c\x26\ -\x00\x00\x09\xee\x00\x00\x00\x00\x00\x01\x00\x08\x12\x88\ -\x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\xb2\x54\ -\x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x13\xbd\ -\x00\x00\x08\x94\x00\x00\x00\x00\x00\x01\x00\x07\x98\x7b\ -\x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x52\x06\ -\x00\x00\x07\x22\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x26\ -\x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x83\x57\ -\x00\x00\x08\xe0\x00\x01\x00\x00\x00\x01\x00\x07\xb3\x81\ -\x00\x00\x07\xaa\x00\x01\x00\x00\x00\x01\x00\x07\x50\xe1\ -\x00\x00\x07\xf4\x00\x01\x00\x00\x00\x01\x00\x07\x63\xa7\ -\x00\x00\x0a\x14\x00\x01\x00\x00\x00\x01\x00\x08\x1d\x33\ -\x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x43\x20\ -\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x07\x41\x0f\ -\x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x90\xbb\ -\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xec\x4e\ -\x00\x00\x08\x62\x00\x00\x00\x00\x00\x01\x00\x07\x83\x77\ +\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xbf\xe9\ +\x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x11\x96\ +\x00\x00\x08\x1c\x00\x01\x00\x00\x00\x01\x00\x07\x73\xb3\ +\x00\x00\x0a\x3e\x00\x01\x00\x00\x00\x01\x00\x08\x27\xeb\ +\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x5c\x7d\ +\x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xdd\x33\ +\x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x35\xd1\ +\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x07\x07\x02\ +\x00\x00\x08\xb6\x00\x01\x00\x00\x00\x01\x00\x07\xad\x42\ +\x00\x00\x0a\x8e\x00\x01\x00\x00\x00\x01\x00\x08\x43\xfb\ +\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x2a\xb8\ +\x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x3b\x95\ +\x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xca\x9d\ +\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x30\x37\ +\x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xf5\xf8\ +\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x20\x4c\ +\x00\x00\x09\xc8\x00\x00\x00\x00\x00\x01\x00\x08\x0a\x31\ +\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\xe0\ +\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x77\x9c\ +\x00\x00\x09\x80\x00\x01\x00\x00\x00\x01\x00\x07\xf6\x3b\ +\x00\x00\x09\xa2\x00\x01\x00\x00\x00\x01\x00\x08\x00\x9d\ +\x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x65\x83\ +\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe4\x27\ +\x00\x00\x07\xd2\x00\x01\x00\x00\x00\x01\x00\x07\x5c\x89\ +\x00\x00\x09\x10\x00\x00\x00\x00\x00\x01\x00\x07\xbd\x8a\ +\x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x89\x0c\ +\x00\x00\x09\x34\x00\x00\x00\x00\x00\x01\x00\x07\xd4\x3d\ +\x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x1d\xa4\ +\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x4b\x9f\ +\x00\x00\x0a\x5e\x00\x00\x00\x00\x00\x01\x00\x08\x32\x85\ +\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x4b\ +\x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x05\xf3\xe7\ +\x00\x00\x0a\xbe\x00\x00\x00\x00\x00\x01\x00\x08\x4f\xd4\ +\x00\x00\x09\x58\x00\x00\x00\x00\x00\x01\x00\x07\xe7\x14\ +\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x06\x09\x07\ +\x00\x00\x08\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x7c\x5c\ +\x00\x00\x09\xee\x00\x00\x00\x00\x00\x01\x00\x08\x12\xbe\ +\x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\xb2\x8a\ +\x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x13\xf3\ +\x00\x00\x08\x94\x00\x00\x00\x00\x00\x01\x00\x07\x98\xb1\ +\x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x52\x3c\ +\x00\x00\x07\x22\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x5c\ +\x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x83\x8d\ +\x00\x00\x08\xe0\x00\x01\x00\x00\x00\x01\x00\x07\xb3\xb7\ +\x00\x00\x07\xaa\x00\x01\x00\x00\x00\x01\x00\x07\x51\x17\ +\x00\x00\x07\xf4\x00\x01\x00\x00\x00\x01\x00\x07\x63\xdd\ +\x00\x00\x0a\x14\x00\x01\x00\x00\x00\x01\x00\x08\x1d\x69\ +\x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x43\x56\ +\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x07\x41\x45\ +\x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x90\xf1\ +\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xec\x84\ +\x00\x00\x08\x62\x00\x00\x00\x00\x00\x01\x00\x07\x83\xad\ \x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x05\xcc\x17\ \x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x05\xd5\x2b\ " diff --git a/src/Mod/Draft/Resources/ui/userprefs-base.ui b/src/Mod/Draft/Resources/ui/userprefs-base.ui index eb55cb4e56..b98eb637b3 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-base.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-base.ui @@ -7,7 +7,7 @@ 0 0 590 - 629 + 632 @@ -541,6 +541,19 @@ + + + + Hide Draft snap toolbar after use + + + hideSnapBar + + + Mod/Draft + + + @@ -1164,12 +1177,12 @@ such as "Arial:Bold" setEnabled(bool) - 103 - 373 + 92 + 379 - 347 - 374 + 417 + 381 @@ -1196,12 +1209,12 @@ such as "Arial:Bold" setEnabled(bool) - 49 - 275 + 67 + 270 - 550 - 277 + 571 + 272 @@ -1212,12 +1225,12 @@ such as "Arial:Bold" setEnabled(bool) - 44 - 275 + 62 + 270 - 405 - 283 + 516 + 272 @@ -1232,8 +1245,8 @@ such as "Arial:Bold" 365 - 163 - 369 + 354 + 381 @@ -1248,8 +1261,24 @@ such as "Arial:Bold" 367 - 393 - 368 + 516 + 381 + + + + + gui::prefcheckbox_7 + clicked(bool) + gui::prefcheckbox_9 + setEnabled(bool) + + + 158 + 290 + + + 400 + 293 From 13153b6260edd1a6553c9a557cc7c20f5ad64a18 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 19 Mar 2012 16:10:10 -0300 Subject: [PATCH 030/351] Fixed bug #584 in Draft Downgrade --- src/Mod/Draft/Draft.py | 16 +++++++++++++++- src/Mod/Draft/DraftTools.py | 7 +++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 6dba687095..8d306c25db 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -204,7 +204,21 @@ def shapify(obj): if not (obj.isDerivedFrom("Part::Feature")): return None if not "Shape" in obj.PropertiesList: return None shape = obj.Shape - name = getRealName(obj.Name) + if len(shape.Faces) == 1: + name = "Face" + elif len(shape.Solids) > 0: + name = "Solid" + elif len(shape.Faces) > 1: + name = "Shell" + elif len(shape.Wires) == 1: + name = "Wire" + elif len(shape.Edges) == 1: + if isinstance(shape.Edges[0].Curve,Part.Line): + name = "Line" + else: + name = "Circle" + else: + name = getRealName(obj.Name) FreeCAD.ActiveDocument.removeObject(obj.Name) newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name) newobj.Shape = shape diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 649f8db2b6..06f0222fdc 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -2297,7 +2297,7 @@ class Upgrade(Modifier): newob = Draft.fuse(self.sel[0],self.sel[1]) self.nodelete = True - elif (len(self.sel) > 2) and (len(faces) > 10): + elif (len(self.sel) > 2) and (len(faces) > 6): # we have many separate faces: we try to make a shell sh = Part.makeShell(faces) newob = self.doc.addObject("Part::Feature","Shell") @@ -2316,6 +2316,7 @@ class Upgrade(Modifier): f = True u = fcgeo.concatenate(u) if not curves: + # several coplanar and non-curved faces: they can becoem a Draft wire msg(translate("draft", "Found several objects or faces: making a parametric face\n")) newob = Draft.makeWire(u.Wires[0],closed=True,face=f) Draft.formatObject(newob,lastob) @@ -2340,6 +2341,8 @@ class Upgrade(Modifier): if (not curves) and (Draft.getType(self.sel[0]) == "Part"): msg(translate("draft", "Found 1 non-parametric objects: draftifying it\n")) Draft.draftify(self.sel[0]) + else: + msg(translate("draft", "Couldn't upgrade these objects\n")) elif wires and (not faces) and (not openwires): # we have only wires, no faces @@ -2473,7 +2476,7 @@ class Downgrade(Modifier): self.doc.openTransaction("Downgrade") if (len(self.sel) == 1) and (Draft.getType(self.sel[0]) == "Block"): - # a block, we explode it + # we have a block, we explode it pl = self.sel[0].Placement newob = [] for ob in self.sel[0].Components: From 062dc9d6dfd8277bf7fb5c5a879840531846df8a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 19 Mar 2012 16:36:28 -0300 Subject: [PATCH 031/351] Added RFE 513 - Arch walls auto-grouping --- src/Mod/Arch/ArchWall.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index c3e5ec85c5..b1389556a7 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -143,6 +143,7 @@ class _CommandWall: FreeCADGui.Snapper.getPoint(last=self.points[0],callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox()) elif len(self.points) == 2: import Part + add = False l = Part.Line(self.points[0],self.points[1]) self.tracker.finalize() FreeCAD.ActiveDocument.openTransaction("Wall") @@ -154,16 +155,21 @@ class _CommandWall: if areSameWallTypes([w,self]): w.Base.addGeometry(l) else: - self.addDefault(l) + nw = self.addDefault(l) + add = True else: self.addDefault(l) FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() + if add: + import ArchCommands + ArchCommands.addComponents(nw,w) def addDefault(self,l): s = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace") s.addGeometry(l) - makeWall(s,width=self.Width,height=self.Height,align=self.Align) + w = makeWall(s,width=self.Width,height=self.Height,align=self.Align) + return w def update(self,point): "this function is called by the Snapper when the mouse is moved" From 343bc96bfe1ab2fb2860a825065ab883c00f084a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 19 Mar 2012 18:49:00 -0300 Subject: [PATCH 032/351] Fixed 0000647: Draft module startup defaults --- src/Mod/Draft/Draft.py | 12 +- src/Mod/Draft/DraftTools.py | 9 + src/Mod/Draft/Draft_rc.py | 590 ++++++++++--------- src/Mod/Draft/Resources/ui/userprefs-base.ui | 22 +- 4 files changed, 332 insertions(+), 301 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 8d306c25db..c015ccead5 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -128,7 +128,7 @@ def setParam(param,value): elif t == "float": p.SetFloat(param,value) elif t == "bool": p.SetBool(param,value) elif t == "unsigned": p.SetUnsigned(param,value) - + def precision(): "precision(): returns the precision value from Draft user settings" return getParam("precision") @@ -250,10 +250,12 @@ def formatObject(target,origin=None): if ui.isConstructionMode(): col = fcol = ui.getDefaultColor("constr") gname = getParam("constructiongroupname") - if gname: - grp = doc.getObject(gname) - if not grp: grp = doc.addObject("App::DocumentObjectGroup",gname) - grp.addObject(target) + if not gname: + gname = "Construction" + grp = doc.getObject(gname) + if not grp: + grp = doc.addObject("App::DocumentObjectGroup",gname) + grp.addObject(target) obrep.Transparency = 80 else: col = ui.getDefaultColor("ui") diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 06f0222fdc..6153ee32f1 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -72,6 +72,15 @@ MODCONSTRAIN = MODS[Draft.getParam("modconstrain")] MODSNAP = MODS[Draft.getParam("modsnap")] MODALT = MODS[Draft.getParam("modalt")] +# sets defaults on first load + +if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/").HasGroup("Draft"): + p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") + p.SetBool("copymode",1) + p.SetBool("alwaysSnap",1) + p.SetBool("showSnapBar",1) + p.SetUnsigned("constructioncolor",746455039) + #--------------------------------------------------------------------------- # General functions #--------------------------------------------------------------------------- diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index c97248fb51..f77fd18a83 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Mon Mar 19 15:43:18 2012 +# Created: Mon Mar 19 18:32:07 2012 # by: The Resource Compiler for PyQt (Qt v4.7.4) # # WARNING! All changes made in this file will be lost! @@ -23949,248 +23949,250 @@ qt_resource_data = "\ \xe3\xab\x65\xc9\x7a\xb7\x23\x8c\x3b\xb9\x4f\x11\x66\xdc\xbb\xbe\ \x30\xc5\x06\xf3\x83\x24\x92\x29\x63\x03\xca\x58\x8b\x27\xe2\x98\ \x19\x1b\xc0\xe7\x66\x3d\xe1\xad\x83\xff\x03\xad\x19\x30\x45\ -\x00\x00\x0e\xf8\ +\x00\x00\x0f\x1f\ \x00\ -\x00\x9b\x0d\x78\x9c\xed\x1d\xfd\x73\xda\xb8\xf2\xf7\xfc\x15\x9a\ -\xfc\xd0\xc9\x9b\xc9\x85\x40\xbe\x9a\x96\x70\xd3\xef\x76\xa6\x77\ -\xd7\x2b\x69\xef\xdd\xfb\xe5\x46\xd8\x02\xf4\x6a\x2c\x4e\x12\x49\ -\xb8\x79\x7f\xfc\xdb\x95\x6c\xb0\x8d\x31\x01\x61\x0c\x2d\x9d\xce\ -\xc4\x96\xec\xd5\x6a\xb5\x5f\xda\x5d\x8b\xe6\xcf\x0f\x83\x80\xdc\ -\x31\xa9\xb8\x08\x6f\x0e\xeb\x27\xa7\x87\x84\x85\x9e\xf0\x79\xd8\ -\xbb\x39\xfc\x72\xfb\xf6\xa7\xa7\x87\x3f\xb7\x0e\x9a\x23\x3e\x7d\ -\xe8\x1c\x1e\x6a\x1d\x90\xa6\x17\x50\xa5\x5a\xef\x46\xfc\xd9\xb3\ -\xd7\x9c\x06\xa2\x07\x7f\x83\x5e\x9b\x69\x0d\x2f\xab\xd7\x92\x76\ -\x75\xb3\x66\x1f\x82\xa7\xef\xb9\xdf\x63\x9a\x98\xfb\x9b\xc3\xdf\ -\xff\x30\xb7\x87\x24\xa4\x03\x76\x73\x58\x08\x04\x07\x23\xcd\xa1\ -\x14\x43\x26\xf5\x38\x7a\xa3\xc7\xc4\x80\x69\x39\x36\x9d\xa4\x29\ -\x99\xa7\xcd\x15\x69\x3e\xb4\x4e\x9b\xb5\x87\xe8\x66\x8c\x37\xe3\ -\xe8\x06\x50\xd0\xfd\xd6\xc5\x35\x34\xd9\x4b\xdb\xdc\x67\xbc\xd7\ -\xd7\xad\xcb\xb3\x46\xb3\x16\x5d\x1b\x98\xb5\x18\x68\xb3\x16\x0f\ -\x9e\x87\xc9\x3d\x0f\x7d\x71\x7f\xcb\x75\xc0\x22\x64\x94\x96\x80\ -\x7c\xeb\x1d\x0b\x99\xa4\x01\x51\xd1\x64\x9a\xb5\xa8\x63\x16\x64\ -\x40\xc7\x62\x34\x25\xce\xd7\x97\xe2\xe1\xa3\x69\x8a\x20\x66\x86\ -\x54\x43\xea\x01\xa0\xc3\x68\x02\xe1\x68\xd0\x61\xb2\x75\xd9\xac\ -\x45\x57\x16\xfd\xe4\x08\x33\x20\x06\x54\xf6\x78\x98\x81\x70\x5d\ -\x08\x81\x6b\x36\x98\x52\x32\xb9\x98\xef\xa4\x18\x0d\x01\xe7\x78\ -\x39\x7b\xf1\xbd\x7d\x7c\x66\x70\x3d\x25\x56\x0e\xbd\xcc\xa2\x93\ -\x76\x0e\xd5\x66\x91\x2a\xa4\x5d\x34\x1a\x30\xae\xe6\x1e\x0d\x6c\ -\xeb\x5f\x8d\xe9\xc0\xd3\x19\xe5\x00\x7a\x3f\x03\xa8\x2f\x24\xff\ -\x47\x84\x7a\x02\xaa\x7e\x3d\x81\x95\x85\x36\x4b\xa4\x8f\xb4\xc3\ -\x82\x18\x54\x80\x37\xe9\xf7\x73\xc8\xc4\x1e\x74\xea\x81\x09\xa9\ -\x2c\x89\x78\xa8\x99\xec\x52\x8f\x91\x81\xf0\x59\x86\x50\xf9\xd4\ -\xb2\x8d\x16\xb3\x04\xea\xb5\x34\xee\x0b\xa6\x62\xa4\xf5\x93\x64\ -\xdd\x57\x62\xd0\x11\xc9\x75\xc7\x8e\x21\x74\x78\xd8\xd1\x11\x0f\ -\x7f\x9d\x17\x4f\x50\x88\xe0\x96\x0f\xf3\xe7\x78\xdb\xe7\x8a\xc0\ -\x7f\xdd\x67\xe4\xcb\x07\x33\x45\x98\x31\xb9\xef\x73\xaf\x6f\x1a\ -\x2d\x11\xa0\x7d\x14\x30\x72\xcf\x83\x80\xdc\x0b\xf9\xed\x19\xb9\ -\x05\xa8\x1d\x2a\xed\x1b\xa6\x7d\x18\x20\x91\x68\x10\xf3\x56\x2c\ -\x91\x08\x8f\xc2\xdd\x90\x4a\xaa\x19\xd1\xf6\xc5\x63\x1c\x03\x40\ -\x6a\xaa\xbe\xa5\xe1\x8c\x14\x33\x23\xbf\x95\x8c\xbd\x7a\xf1\x9a\ -\xdc\xc2\x13\x77\x9c\xdd\x13\x35\x56\x40\x31\xd2\x15\xd2\x8c\xc2\ -\xb5\xc2\x67\xa5\x5d\x21\xea\x69\xd0\x9b\x8f\x5e\x9e\x19\x2a\x21\ -\x41\xdf\x84\xa8\xeb\x88\xd2\x3e\xe0\x7e\x73\x78\x9a\x21\x99\x17\ -\xc1\xfe\xc2\x7f\x31\x9c\xe0\xb9\x8c\xf5\x89\xea\xfe\xe2\xa1\x60\ -\xa0\x5a\xac\xe3\x1f\x3d\x5a\x86\xaf\x1e\xc3\xf2\x53\x7e\xb0\xab\ -\x93\x47\xc7\x79\xc3\xd5\xb2\xe3\xb9\x21\x10\xad\xb6\x0b\x06\x0b\ -\x65\xaf\x59\xb3\x6a\x68\xa2\xa3\x52\xdd\xce\x1a\xab\xe1\xa6\xb0\ -\x1a\xab\xea\x2b\xd6\xa5\xa3\x00\x40\x8b\x40\xe4\xae\x60\xe9\x8a\ -\x0a\xc6\x7d\x39\xd2\x5a\x84\x39\xba\x0a\xfa\x3a\xb6\x6f\x65\x65\ -\x85\x5a\xc1\x4f\x4e\xd2\xe8\x82\x10\x54\x83\xe8\xfc\x17\xdc\x88\ -\xac\x19\x2b\xe2\x99\xcc\xb8\x06\x5c\x56\x08\xb1\x2d\xc3\xa5\x92\ -\xf9\xe8\xec\xe0\x9f\x74\x47\x0f\xb4\x55\x88\x5d\xf6\x22\xdd\xd9\ -\x09\x46\x0c\xfb\xcc\xdf\x34\x43\xcf\x0c\xb2\x76\x75\x15\xb1\xc3\ -\x76\x6a\x2b\x67\xee\xcb\x13\xa0\x05\xf6\x70\xae\x00\xb5\x43\x3a\ -\xdc\x76\xe9\x59\xa4\x1d\x96\x97\x1f\x85\xb3\x56\x63\xf0\x25\x82\ -\xbd\x00\xa5\xd0\x8f\x68\x81\x04\xfa\xf1\x84\x68\x55\xaf\xf9\x95\ -\x08\xe1\x6a\x64\xdc\xb1\xad\x17\xa6\xb3\xf5\x78\xce\xb3\x42\x15\ -\x19\x24\xd2\x61\xf0\x2c\xf1\x25\xbd\x0f\x23\x87\x97\x23\x55\x12\ -\x24\x42\xc7\xf7\x64\x33\x72\x77\x7e\x3e\x5f\xf0\xea\x8d\x8b\x02\ -\xd1\x6b\x5c\x5c\x54\x66\xbd\xa6\xb4\xfa\xf1\x84\x70\x01\x7f\x2e\ -\x74\x05\x03\x0e\xde\x11\x46\x61\x2a\x90\xc1\xf6\x90\x87\x79\xdb\ -\x56\x05\xed\x9d\x69\xd8\x22\x7f\x66\x8f\x35\x63\x93\x09\xae\xcf\ -\x15\xbc\xa3\xc0\xe7\x99\x91\xa3\x80\x4d\x23\x15\xba\x59\x0a\xea\ -\x12\x2c\x9f\x58\xb4\x1d\x65\xf5\x92\xf7\x57\x67\x8e\xfb\xab\x53\ -\x27\xd3\x46\xb9\x51\xda\x5b\x19\x09\xba\x70\xb1\x67\x8c\x4c\x26\ -\x88\x46\x0b\xe6\xc8\xbb\x9c\x49\xf2\x8d\x8d\x37\x12\x57\x81\x01\ -\xbd\x18\x81\x6d\x65\x7d\xb7\xe0\x86\xea\x73\x1c\xac\xaa\xd8\x8a\ -\xa7\x65\x50\xdd\xe8\x34\x70\x9a\xfa\x0a\x62\x84\x11\x7c\xe0\xdf\ -\xac\x16\x69\x9b\xe6\x05\xb2\x02\x4f\x33\x78\x18\xdd\x8e\x0c\xf7\ -\x30\x30\x01\xad\xdf\xf5\xb3\x67\xef\x27\x10\x9b\x35\xd3\xb8\x34\ -\xab\x2a\xfe\x0f\x7b\xcf\x43\x3d\x9f\x55\xf1\x89\x0c\x39\x6d\x56\ -\xe5\x3c\x9d\x5f\x99\xf4\x46\xb9\x95\xc6\x69\x2a\xcd\x32\x45\x2b\ -\x0b\x70\x8e\xca\xb2\xa4\x5b\xab\x2f\xd3\xa8\xbb\x6c\xcb\xb7\x55\ -\xe3\x5e\xba\x69\x5c\x15\xcd\x6d\x0d\x9a\xd6\x1b\x49\x09\x2c\xfb\ -\x21\xf4\xd9\x43\xbe\xfb\x52\xdf\x88\xfb\x02\xb3\xc1\x59\xed\x35\ -\xb8\x6d\xdd\x6b\xf0\x69\xc3\x9a\x35\x78\xb1\xec\xed\x35\xf8\xda\ -\x35\xf8\xaa\x99\x89\x17\x81\xde\x5a\x05\x7e\xe5\xa6\xc0\xa9\x9d\ -\xda\x46\xf4\xf7\x66\xb6\x9f\x30\x1b\x23\xe8\x7b\xf5\xbd\x57\xdf\ -\xdb\x94\x55\xad\x27\xb9\x68\x95\x3a\x10\xb7\x6d\x7f\x14\xae\x35\ -\x55\x37\xe6\x95\x0a\xb4\xd9\x47\x1e\xb2\x37\x3e\xd7\x33\xda\x0c\ -\x43\x46\x0c\x3a\x5c\xb2\x43\x79\x01\xed\xe9\x6c\x4d\x7c\x2d\x15\ -\xb8\x8e\x8b\xc3\x56\xd7\x78\x8f\x23\xf9\x46\x62\x0f\xc9\x99\x99\ -\x49\xdb\x15\xde\x4e\x1d\x58\xb5\x24\x9e\x3f\x5e\x10\xa7\x86\xb8\ -\xcf\xbc\x6f\xb9\x86\x18\x3b\x9c\xe2\xc1\x06\x02\xb0\x2d\xb2\x6f\ -\x97\x00\x86\xe4\x9e\x86\x9a\x68\x31\x29\x25\x32\x89\x83\x5a\x22\ -\x56\x2c\xc5\xc0\x74\x44\xc5\x48\x84\xaa\x98\xe5\xcb\xe0\xe6\x36\ -\xbd\x03\x1c\xac\x79\x8f\x72\x44\x34\xf4\x13\xb1\x6b\xea\x49\xa1\ -\x14\x51\x4c\x61\xf1\xa7\x43\xec\x7a\x99\xac\x26\x20\x25\x42\xf6\ -\xc0\xb7\xd6\xd4\x57\xcd\xe6\x57\x65\xb0\xb9\x4b\x88\xf6\x43\x37\ -\xe2\x72\x45\x0c\x38\xe6\x1f\x03\x3b\x0d\xc7\x89\xe2\xb9\x0e\x03\ -\x27\x74\xa8\x63\x8e\x02\x2f\x77\x00\xac\x76\x4c\x04\x70\xbb\xbc\ -\xe7\x8a\xc5\x4d\xca\x3e\x4f\x83\x7b\x3a\x06\xce\xd3\x54\x62\xa9\ -\x23\x09\xc5\x4f\x13\x88\x65\x88\xc2\xbb\x40\x74\x68\x40\xd6\x30\ -\x46\x44\x81\xcc\x30\x1d\xa0\x5f\x0b\x14\x39\x00\x36\x97\xe5\xda\ -\x8c\xe1\x78\xb0\xc5\x95\x80\x55\xcb\x4f\xfd\x69\x29\x02\xe4\x90\ -\xb3\xff\x55\xc8\x01\x0d\x82\xf1\x31\x01\x42\x32\x69\xd8\x10\x53\ -\x1d\x51\xce\xf0\x38\x32\x16\x43\xce\x14\x41\xe4\x14\x0b\xa0\x9d\ -\xf9\x27\x24\x16\x3d\x31\x34\xbe\x4f\x52\x02\xf1\x9d\x0e\x05\xc9\ -\x8a\x73\xfe\xb1\x20\xc6\x6f\x83\x5c\x29\xcd\xa8\xef\x90\xe5\x2f\ -\xb0\x2d\x66\x90\x34\x02\xa9\xc9\x6d\xc6\x98\x18\x2c\x5e\x02\x12\ -\xbf\xc5\xe9\xd7\xbd\x4c\xe4\xc9\xc4\x45\x29\x22\xf1\x74\xbd\x36\ -\xc5\xb8\x50\x49\xeb\x80\x41\x6a\x70\xa7\xc0\x59\x50\x3a\x21\x2f\ -\x51\x45\x0b\x56\xb7\x40\xab\x11\x92\x50\xe8\xc4\xfb\x1d\x1b\xe0\ -\x1e\x9a\x77\xc2\x60\x0c\x2f\xb0\x90\x00\xea\xe0\xe7\x40\xd3\xab\ -\xdb\xcf\x1f\x4b\x11\x8a\x17\x69\xbc\x63\x74\x8f\x7c\xae\x68\x27\ -\x98\x46\xdd\x31\x60\xf3\xaf\x5d\x36\x41\x76\x81\xda\x5b\x1c\x6e\ -\x5f\x7b\xd0\xb7\x78\x87\xbb\x0f\xfa\xae\x3b\xe8\x5b\x77\x0c\x90\ -\x4a\xea\xf3\x91\x9a\x54\x9a\x1a\x5d\x00\x32\xa9\x86\xcc\xe3\xe0\ -\x09\x0e\x05\x10\x52\x9d\xe0\x97\x48\xd8\x7c\x6a\xeb\x78\x04\x01\ -\x51\xd5\x34\xf4\x18\x39\xe2\x61\x97\x87\x80\xb7\x83\xa0\x2e\xc8\ -\x2d\x4a\x1a\xf6\xaa\x08\xe7\x2c\xa8\x90\x5a\xc0\xea\x6a\xd4\xed\ -\xf2\x6c\xa4\x38\x9a\xc3\xf0\x61\x33\x66\x1f\xa8\xf7\xd9\x12\x6f\ -\x47\xb5\x4f\xd9\x5f\x82\x2c\x11\xb3\x5c\xc2\xde\x3b\x7c\xf0\x95\ -\x67\xef\x27\x72\x69\x8c\x36\x98\x70\x22\x3c\x6f\x24\x09\xed\x51\ -\x74\x5d\x13\x8e\xad\xee\x83\xd9\x94\x18\x54\xa1\xa1\x71\x7c\x79\ -\xe8\x73\x8f\xa2\x93\x6b\x33\x13\x44\x74\x09\x83\x59\x39\xc4\x30\ -\x16\x15\x02\xd0\x07\x3e\x18\x0d\x76\xd9\x6a\xc3\x14\x7e\x24\x93\ -\xbd\x37\xd8\xf3\x29\x5d\x46\x96\xd6\x61\x83\xfc\x8b\x15\xae\xac\ -\x30\xa3\x65\xee\x30\x13\xfe\xe7\x3e\x93\x20\xed\x49\x73\x5e\x86\ -\xa8\xcf\x41\x64\x0b\x8d\x74\x71\x11\x42\xa4\xad\xf2\xf3\xb9\xd7\ -\xd7\xd7\xab\x67\x74\x8b\xca\x94\xcf\x37\x93\x28\xb6\x6a\xec\x8d\ -\x5d\x98\x1d\xd5\x65\x65\x3b\x00\xf5\x52\x1c\x00\x07\x9f\x1c\x1c\ -\x80\x54\xe8\xaa\x6d\x37\xc9\x36\x0f\x32\xd9\xb5\xf7\x85\xf9\x60\ -\x85\x85\xec\x0e\xc4\x0f\x37\xf4\x98\x4b\x29\x53\xe2\xdb\x30\x64\ -\x7c\x2a\x41\x02\xa5\x5d\xb6\xf3\x48\x45\x9c\xcb\x4b\xfa\xfd\x7e\ -\xb5\xb2\x04\xd3\xae\xfa\x45\xd9\x7b\xb0\x39\xf1\x99\x02\x49\x66\ -\xb5\x61\x4e\xe0\xcb\x8d\xec\x75\xfa\x80\xc5\xae\x2f\x66\xc9\xca\ -\xae\x9c\x78\xbf\x43\x85\x6d\xde\x66\x27\x15\xa5\x07\x75\xc6\x6c\ -\xfa\xb7\x0b\xb7\xe0\xd7\x4c\x13\xc1\x27\xe4\xb7\x38\x67\x66\x14\ -\xe5\x38\xfb\xc6\x3d\x07\x2c\xe5\x32\x85\x20\x4b\xf0\xfc\x5b\x1c\ -\x6b\xf2\x11\xe1\xd8\x3d\x3b\xbd\x04\xa7\x23\x29\xf6\x79\xad\xf9\ -\x6c\xee\x7a\x1e\x8d\xeb\xf9\x0e\x78\x00\x0b\xee\xd6\x87\x01\x0d\ -\xb7\xf3\x40\x9a\xe2\x19\x2e\xc1\x8a\x11\xdb\xff\xf1\x69\x5b\x79\ -\xd1\xad\x22\xef\x57\x91\xbf\x80\x9b\xa9\x07\xfc\xf7\x9f\xe4\xe8\ -\x56\x0c\x73\xe3\xaa\x1b\xc2\xe0\x3f\xe4\xe8\xad\x04\xd9\xaa\x10\ -\x87\x3f\x01\x87\x36\xd8\x76\x27\x14\xaa\x56\x49\xf5\x72\x6a\x55\ -\x1c\xaa\x09\x93\xdb\x0c\x4a\x7a\x92\xfb\x29\xfb\x69\x12\x81\x51\ -\xe2\xb0\x0c\xfb\xf9\x05\x76\x2b\x38\xe8\x2e\x6f\x1f\x2c\xfe\xdb\ -\xa9\xf7\xd6\x9e\xd6\x2b\xde\xd1\xee\xa3\x84\x6b\x4f\xeb\x2d\xa8\ -\x43\x9b\x5f\xc1\x85\xa2\x1c\x9d\x8d\x58\x81\xf3\xf1\x5a\x8c\x3a\ -\x01\x9b\x17\x94\xf3\x4d\x6f\x1c\x9a\x73\x3a\xdd\x83\xc5\x93\x24\ -\x1d\xa6\xef\x19\xa8\x2b\x46\xbd\xbe\xd5\x64\x58\xb9\xb9\xde\x03\ -\x06\x2c\xe2\xad\xfa\xc9\x69\xfa\x5f\xb3\x16\xf5\x94\xad\x68\xda\ -\xf1\x8a\x7e\x37\xfa\xe6\x11\x32\xb0\x60\x6b\x59\x10\x9d\xe6\xa1\ -\x61\x02\x45\x30\x3e\xf6\xf8\x12\xf8\xcd\x85\xa5\x1d\x52\x84\x38\ -\x3b\x3b\xb9\x38\x1c\x68\xcf\xaf\x81\xad\x34\x58\x44\x79\x42\xda\ -\x98\xbb\xef\x8e\x09\x6c\x8f\x19\xc1\xb0\xdd\x80\x86\x63\xa2\xfe\ -\x1e\x51\xc9\xd4\x44\x5c\x06\x31\x18\x87\x12\x9f\x82\x20\x77\xfd\ -\x74\x23\x41\x6e\x94\x8d\x37\x76\x8d\x77\x54\x32\xca\x76\x3d\x1d\ -\x4f\xe3\x58\x50\xbb\x36\x57\x06\x3f\xe0\xa9\x9f\x21\x56\x90\x48\ -\xe0\x46\xac\x9b\x27\x01\x08\x63\xee\xf7\x55\x15\xcb\x62\xb1\x1d\ -\x8a\x52\x44\x6d\x70\x05\x1e\xeb\x6e\x5c\x16\xbb\x1b\xf5\xcb\xab\ -\xab\xab\x46\xfd\xc2\xc5\xe9\x58\xde\x5c\x4e\x53\x75\x3e\x2c\xc8\ -\x80\x06\xe6\xe4\x57\x1e\x2f\x93\x27\x84\xf4\x79\x48\x35\xc3\x2a\ -\x5a\x26\x8d\x33\xa7\xc8\x11\x66\x12\xd9\xc3\x09\x39\x23\x37\xe4\ -\x14\xcc\x5f\xdd\xa1\xce\xa7\x40\x5d\x5c\x6e\x44\x5b\x4c\x78\x71\ -\x67\xb5\xc5\xb2\x7e\x7b\xb1\x9d\xd9\xfb\xed\x6b\xf7\xdb\x57\xd5\ -\x97\xaf\xf9\x80\x85\xe6\xf3\xa2\x1d\xd0\x98\xc5\x9b\x93\xc2\xa4\ -\xfa\xd3\x72\x52\xea\x1b\x51\x1f\x3e\x1f\x7c\xda\x79\x0d\x52\xb6\ -\xbf\xb1\x44\x09\x7d\x9e\x00\x2d\x48\x9d\xcf\x95\x9f\x5b\x11\x80\ -\xd1\x0a\xbd\x52\x23\xee\xc5\xba\xb6\x58\xf4\xf7\xba\xd6\x45\xd7\ -\xae\x12\x60\xf8\x01\xdc\xba\xe9\x27\xe1\x46\x39\x62\xb6\xdd\xc7\ -\x7c\x64\x77\x14\x7a\xd6\x81\xd3\x7d\xaa\x4d\x71\x08\x25\x3a\x16\ -\x91\x93\x83\xaf\xf8\x74\x54\x31\xea\xf3\x6e\x17\x76\x8a\xd0\x8e\ -\x9b\xc3\x00\xf6\x8b\x26\x29\x6b\x01\xc6\x5b\x4c\x2d\x99\x29\x23\ -\xa5\x8a\x28\x40\xcc\x61\xcf\x58\x50\x17\x5d\x5b\x85\xe1\xc3\x1e\ -\xb0\x83\x66\x59\x12\x45\x71\x19\x70\x59\xeb\x6b\x8a\xd8\x14\xc4\ -\x85\x60\x94\x8b\xcd\xc7\x85\xf4\x54\xe5\xed\x6d\x51\x9e\x2d\xba\ -\x74\x33\x45\xab\x86\x9f\xe2\x44\x30\x3e\x41\xac\x2e\xa8\xce\x28\ -\x15\x57\xf5\xec\x8d\xd2\xa6\x8d\xd2\x82\xa4\xdd\xf7\x60\x96\x62\ -\xfe\xb7\xe3\x99\x5a\x64\x14\x05\x65\x4e\x55\xf0\x27\xfb\x9c\x52\ -\x22\xf4\xa7\x27\x8d\x0a\x22\xf4\x38\xbd\x58\xd0\xf7\xaa\x38\x77\ -\x5b\xe0\xf8\xa3\x2b\xab\xa6\xc3\x52\xba\xb8\x0b\x18\x55\xa7\x89\ -\x8b\xc3\x8c\x7b\x4d\xbc\x16\x4d\xbc\xf0\x08\x26\x97\x9c\xe3\xec\ -\x01\x4c\xc8\x51\xe6\xdd\xc9\xcf\x5e\xd9\x42\xd8\x3c\x7d\x77\x72\ -\xf0\x01\xf0\xa5\x21\xba\xd3\x34\xf1\xa6\x1a\x79\x7d\xf4\xab\x9f\ -\xfc\x3d\x12\xfa\xf9\x0b\xc9\x69\x60\x2f\xb1\x32\x23\x1e\x48\xe9\ -\x71\x90\x7d\x54\xd1\x50\xc5\x4f\x46\x2d\x4c\xf2\xae\xbd\x3c\x00\ -\x7c\xec\xd5\x40\x84\x22\x7e\x0c\x91\x24\x5d\x3a\xe0\xc1\x38\x6f\ -\xdc\xe3\xf7\x2c\xb8\x63\xf8\x43\x71\xc7\x53\xe0\xf6\x25\x83\xaa\ -\xd9\x2f\x50\x8b\xcc\x41\xce\xfb\xcf\x5e\x8a\xc0\xb7\xf7\xa5\x7c\ -\x37\x8e\x63\xac\x0e\x98\x06\xbc\x17\xc2\x6a\xcc\x40\x07\x21\x47\ -\xf9\x7a\x81\xfd\x9f\x91\x87\xff\x37\xb9\xbd\x95\x94\x03\xeb\xf4\ -\xa6\x2d\x5f\x5f\x31\x8c\x99\x03\x1a\x4c\x2f\x8f\xc3\x92\x46\xc5\ -\x6a\xac\xbd\x49\xc9\x35\x29\x4b\x7c\xbb\x91\x1b\xaa\x5d\xf5\xc0\ -\xe3\xa9\x4d\x19\x0c\x03\xfc\xcd\x3c\xd5\x67\xac\x42\xc3\xb2\x60\ -\x22\x7b\xcb\xb2\x16\xcb\xf2\x96\x07\xec\x55\x5f\x08\xd0\xb1\x33\ -\xc6\xa5\x0b\x7d\x9e\xed\x5b\xe4\xdf\xf3\x70\x59\xff\xfe\xec\xb4\ -\x98\x40\x4e\xf4\x59\x3e\x8f\xe8\x67\xb9\x3f\x3a\xc8\xcd\x94\x0c\ -\x7a\x18\x26\xc2\xa2\x1c\x6a\x7e\xec\x23\xaa\x20\x5c\x52\x40\xdc\ -\x94\xa6\xc5\x6a\xaf\x34\xe7\x28\xcd\x25\x0e\x07\xcc\x51\x9a\xee\ -\xc9\xad\x27\x74\x30\x7c\x4e\x3e\x32\xea\x83\x42\xa3\x52\x8a\x7b\ -\xeb\x4e\x6c\x63\xa1\xfc\xda\xca\xe4\xf9\xc0\xfe\x80\xdb\xb6\x72\ -\xa5\x5b\x89\xf6\x6b\xa1\xc9\x45\x75\x15\xe2\x38\xfc\x55\xb5\xc3\ -\x5f\x57\x37\xfc\x2b\x2e\x3d\xd8\x19\x54\x48\xff\x08\x83\x0a\x97\ -\x20\xc2\xa0\xc2\x55\x68\x83\x6a\xe9\x57\xb9\x08\x16\x81\x0a\xd7\ -\xc0\x22\x50\xe1\x12\xbc\xa4\xde\x37\x55\xf5\x32\x4c\x91\xa8\x70\ -\x29\xa6\x48\x38\x2d\x47\xe5\xae\x8a\x63\xfa\xa6\xbe\xa0\xc6\x76\ -\xae\xb7\xf2\x15\x9e\xe2\x1e\x0d\x12\xb1\x1b\x1b\x3f\x4c\xec\xa4\ -\xb6\xd1\x5d\x59\xd7\xcf\x65\x26\xa6\x89\xe5\x82\x26\xde\x15\x53\ -\x22\x8a\x6c\x19\x67\x5f\xf7\x61\xc3\x93\x24\x12\x95\x8c\xdc\x45\ -\xc4\x3b\x21\xf1\x36\x19\xa0\x06\xac\xab\x8f\xa3\x5f\xad\x8f\x06\ -\xf9\xd0\xfe\x0d\x8f\xb5\x0d\x7d\x2a\x5d\x4e\xde\x5c\xce\x0b\x4b\ -\x2d\xe0\xf7\xe8\x8a\x7d\x04\x42\x93\xa3\x24\x6d\x2b\xfc\x74\xef\ -\xf3\xbc\xcc\xe7\x8e\x68\x20\x47\xf5\xb3\xea\x8f\x83\xbe\x08\x4c\ -\x49\x2e\xec\xac\xdb\x5f\xdf\x11\x60\x34\xbc\x05\x19\x12\x5e\xe9\ -\x9a\x67\x41\x9c\xa9\xf8\x17\x1a\xf6\x71\xa6\x8d\xc6\x99\x16\x54\ -\xad\xef\x74\x9c\xe9\x3d\x7e\xb9\x82\xa7\xda\x60\xba\x44\x45\x9f\ -\xb3\x50\x30\x35\x92\x79\x5a\xc8\x31\x1e\x75\xa5\xa3\xdf\xc1\x44\ -\x21\x41\xba\xa8\x64\xe3\x93\x40\x3f\x1f\x5a\xc9\x79\xd2\xd3\xcf\ -\x31\x68\x85\x87\x54\x4e\x2b\xa2\xe2\x3c\x8c\xef\x33\x1f\x23\x58\ -\x68\x92\x62\x95\x19\xe5\x70\xe0\x31\x30\x57\x11\x94\xcd\x1c\xfa\ -\x1f\x0d\x86\x2c\xb0\xad\xf6\xc9\x4d\x27\xa7\x3b\x53\xb0\xa6\xcf\ -\x25\x1e\x4a\x3c\x11\xe9\xef\x49\x42\xcc\x7e\x10\x77\x73\x78\x79\ -\x48\x06\x54\xf6\x78\x78\x73\x58\xaf\x1f\x62\x09\x59\x73\xc8\x1f\ -\x06\x74\x18\xd7\xc0\xb5\xfe\xfe\x64\xee\xdf\x4a\x31\xf8\x05\x9c\ -\x95\xb6\x18\x49\xac\x99\xca\x3c\x05\xef\x79\x23\xa5\xc5\xc0\x8e\ -\xa8\x0c\x26\xc9\x16\x8b\xa5\x11\xd7\x96\x91\xd6\x84\xa4\x02\xfd\ -\x4c\xbb\x79\x04\x34\x3b\x0b\x7d\xd5\xfa\xfd\x0f\xf3\x1e\xa8\xba\ -\xa8\xe1\xc0\x4a\x13\x86\xbe\x10\x42\x0d\x01\xbc\xe6\x34\x10\xbd\ -\x93\x3e\x0a\x97\xe9\x30\x04\xc8\x8e\x5b\x8c\x48\xe2\xe7\xd4\xf3\ -\x11\xf9\x34\x52\xfd\xb8\x7f\x1e\x32\x16\x59\xe5\x86\x49\x46\x81\ -\xe5\x62\x33\x4b\xbb\x79\x28\x21\xb4\xb5\xa1\x15\x55\xe7\xe4\x13\ -\x68\xd2\xb9\x11\x54\x16\xad\xd7\xec\xa2\x6e\x06\xad\xe8\xc0\x81\ -\x7c\x12\x4d\x7b\x37\x44\x23\xbb\xdb\x99\x83\xcc\xa4\x77\x23\xc8\ -\xc4\x55\x05\xf9\xc8\x4c\x7b\x37\x82\x4c\xaa\xd8\x2c\x1f\xa3\xcc\ -\x23\xee\x68\xa5\x1b\x10\x52\x53\x32\x65\x14\xa9\x32\x2a\x17\x6c\ -\x6f\xc8\x6c\xc9\xb1\x9d\xc5\xe4\xde\x8e\xaa\x00\x01\x80\x9d\x73\ -\x86\x05\x26\xd2\xc3\x68\x5c\xf4\x4e\x7a\x21\x0d\x5a\x5e\x80\xdf\ -\xb2\xfa\x47\x78\x88\x03\xee\x60\x6c\xab\x79\x02\x5c\x00\xc6\xef\ -\x92\xb0\x32\x5f\x95\x37\x6b\x93\x47\x2c\xc8\x40\xe8\x16\x98\xc1\ -\x37\x21\x1e\x2e\x3f\x85\x89\xcd\x96\x22\x78\xc4\x75\x64\x91\xf0\ -\x9a\xe8\xf1\x10\x5d\x4d\x33\xbd\x54\xda\xa3\xf9\xd0\xba\x06\x84\ -\x1f\xe2\xdb\x71\xeb\xec\xea\xba\x59\x1b\xc7\xe6\x0c\xdf\x9e\x05\ -\xe4\x33\x3c\x96\xdf\x38\xc6\x59\x68\xe7\xf5\xab\x34\xb8\xa7\xf5\ -\x3c\x70\xf6\x52\x45\x4b\x93\x22\xed\x46\x29\x3d\xf9\x7a\xb9\x5c\ -\x1a\x23\x4d\x53\x34\x3e\x73\xa1\xf1\xc5\x55\x3d\x03\xee\xbc\x34\ -\x1a\x9f\xaf\x8f\xc6\x97\xe5\xd2\xf8\x32\xcd\x78\x8d\xab\xd3\x75\ -\xd2\xb8\x71\xd5\xd8\x42\x1a\xc7\x07\xf0\x96\x4c\xd9\xc6\x5a\x29\ -\x5b\xbf\xdc\x18\x65\x57\xd7\x10\xf1\xa1\x25\xe5\x52\xf6\xe2\x69\ -\x5a\x90\x2f\x2f\x5c\x28\x7b\x76\x71\xbe\x03\xba\x37\x3e\x0a\xa3\ -\x5c\xca\x9e\x9d\x65\x28\x7b\xb5\x4e\x9e\x2d\x93\xb2\x57\xee\x1a\ -\x77\x7a\x02\x6a\xb9\x44\xae\x67\xf8\xb7\x71\xed\xa4\x19\xce\x31\ -\x5e\x93\x02\x97\x6b\x26\xe7\x53\x39\x79\x0b\xfd\xcd\xda\x88\xb7\ -\x0e\xfe\x0f\x26\xd1\x19\x22\ +\x00\x9d\x1f\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ +\x0f\x45\x0e\xc8\xc6\xb1\xf3\x6a\x5a\xc7\x8b\x26\x7d\x02\xdd\xdd\ +\x6e\x9d\x76\x6f\xef\xcb\x82\x96\x68\x9b\x57\x99\xf4\x92\x74\x12\ +\x2f\xee\xc7\xdf\x0c\x29\xd9\x92\x2c\xcb\xb1\x65\x59\x4e\xeb\xa2\ +\x40\x2c\x92\x22\x87\xc3\x79\x71\x66\x48\x35\x7f\x7e\x18\x04\xe4\ +\x8e\x29\xcd\xa5\xb8\xda\xaf\x1f\x1d\xef\x13\x26\x3c\xe9\x73\xd1\ +\xbb\xda\xff\x72\xfb\xf6\xa7\xe7\xfb\x3f\xb7\xf6\x9a\x23\x3e\x6d\ +\x74\x0a\x8d\x5a\x7b\xa4\xe9\x05\x54\xeb\xd6\xbb\x11\x7f\xf1\xe2\ +\x35\xa7\x81\xec\xc1\xdf\xa0\xd7\x66\xc6\xc0\xcb\xfa\xb5\xa2\x5d\ +\xd3\xac\xb9\x46\xd0\xfa\x9e\xfb\x3d\x66\x88\x7d\xbe\xda\xff\xfd\ +\x0f\xfb\xb8\x4f\x04\x1d\xb0\xab\xfd\xdc\x4e\x70\x30\xd2\x1c\x2a\ +\x39\x64\xca\x8c\xc3\x37\x7a\x4c\x0e\x98\x51\x63\x5b\x49\x9a\x8a\ +\x79\xc6\xfe\x22\xcd\x87\xd6\x71\xb3\xf6\x10\x3e\x8c\xf1\x61\x1c\ +\x3e\x00\x08\xa6\xdf\x3a\xbb\x84\x22\xf7\xd3\x15\xf7\x19\xef\xf5\ +\x4d\xeb\xfc\xa4\xd1\xac\x85\xbf\x6d\x9f\xb5\xa8\xd3\x66\x2d\x1a\ +\x3c\x0b\x92\x7b\x2e\x7c\x79\x7f\xcb\x4d\xc0\x42\x60\xb4\x51\x00\ +\x7c\xeb\x1d\x13\x4c\xd1\x80\xe8\x70\x32\xcd\x5a\x58\x31\xdb\x65\ +\x40\xc7\x72\x34\x45\xce\xd7\x6b\xf9\xf0\xd1\x16\x85\x3d\xa6\x86\ +\xd4\x43\xea\x41\x47\xfb\xe1\x04\xc4\x68\xd0\x61\xaa\x75\xde\xac\ +\x85\xbf\x1c\xf8\xf1\x11\x66\xba\x18\x50\xd5\xe3\x22\xd5\xc3\x65\ +\x6e\x0f\xdc\xb0\xc1\x14\x93\xf1\xc5\x7c\xa7\xe4\x68\x08\x30\x47\ +\xcb\xd9\x8b\x9e\x5d\xf3\x99\xc1\xcd\x14\x59\x19\xf8\xb2\x8b\x4e\ +\xda\x19\x58\x9b\x05\x2a\x17\x77\xe1\x68\x40\xb8\x86\x7b\x34\x70\ +\xa5\x7f\x35\xa6\x03\x4f\x67\x94\xd1\xd1\xfb\x99\x8e\xfa\x52\xf1\ +\x7f\xa4\x30\x93\xae\xea\x97\x93\xbe\xd2\xbd\xcd\x22\xe9\x23\xed\ +\xb0\x20\xea\x2a\xc0\x87\xe4\xfb\x19\x68\x62\x0f\x26\xd1\x60\x82\ +\x2a\x87\x22\x2e\x0c\x53\x5d\xea\x31\x32\x90\x3e\x4b\x21\x2a\x1b\ +\x5b\xae\xd0\x41\x16\x03\xbd\x96\x84\x7d\xc1\x54\x2c\xb7\x7e\x52\ +\xac\x7b\x23\x07\x1d\x19\x5f\x77\xac\x18\x42\x85\x87\x15\x1d\xf9\ +\xf0\xd7\x69\xfe\x04\xa5\x0c\x6e\xf9\x30\x7b\x8e\xb7\x7d\xae\x09\ +\xfc\x37\x7d\x46\xbe\x7c\xb0\x53\x84\x19\x93\xfb\x3e\xf7\xfa\xb6\ +\xd0\x21\x01\xca\x47\x01\x23\xf7\x3c\x08\xc8\xbd\x54\xdf\x5e\x90\ +\x5b\xe8\xb5\x43\x95\x7b\xc3\x96\x0f\x03\x44\x12\x0d\x22\xda\x8a\ +\x38\x12\xfb\xa3\xf0\x34\xa4\x8a\x1a\x46\x8c\x7b\xf1\x10\xc7\x80\ +\x2e\x0d\xd5\xdf\x92\xfd\x8c\x34\xb3\x23\xbf\x55\x8c\xdd\xbc\x7a\ +\x4d\x6e\xa1\xc5\x1d\x67\xf7\x44\x8f\x35\x60\x8c\x74\xa5\xb2\xa3\ +\x70\xa3\xb1\xad\x72\x2b\x44\x3d\x03\x72\xf3\xd1\xcb\x33\x83\x25\ +\x44\xe8\x1b\x81\xb2\x8e\x68\xe3\x03\xec\x57\xfb\xc7\x29\x94\x79\ +\x61\xdf\x5f\xf8\x2f\x96\x12\xbc\x22\x63\x7d\xa2\xa6\xbf\x78\x28\ +\x18\xa8\x16\xc9\xf8\x47\x8f\x96\xa2\xab\xc7\x90\xfc\x94\x1e\xdc\ +\xea\x64\xe1\x71\xde\x70\xb5\xf4\x78\xc5\x00\x08\x57\xbb\x08\x04\ +\x0b\x79\xaf\x59\x73\x62\x68\x22\xa3\x12\xd5\x85\x25\x56\xa3\x98\ +\xc0\x6a\xac\x2a\xaf\x58\x97\x8e\x02\xe8\x5a\x06\x32\x73\x05\x4b\ +\x17\x54\x30\xee\xf5\xc8\x18\x29\x32\x64\x15\xd4\x75\x5c\xdd\xca\ +\xc2\x0a\xa5\x82\x1f\x9f\xa4\x95\x05\x02\x44\x83\xec\xfc\x17\xcc\ +\x88\xb4\x1a\xcb\xa3\x99\xd4\xb8\xb6\xbb\x34\x13\x62\x59\x8a\x4a\ +\x15\xf3\xd1\xd8\xc1\x3f\xc9\x8a\x1e\x48\x2b\x81\x55\xee\x47\xb2\ +\xb2\x13\x8c\x18\xd6\xd9\xbf\x49\x82\x9e\x19\x64\xed\xe2\x2a\x24\ +\x87\xed\x94\x56\x85\xa9\x2f\x8b\x81\x16\xe8\xc3\xb9\x0c\xd4\x16\ +\x74\xb8\xed\xdc\xb3\x48\x3a\x2c\xcf\x3f\x1a\x67\xad\xc7\x60\x4b\ +\x04\x3b\x06\x4a\x80\x1f\xe2\x02\x11\xf4\xe3\x31\xd1\xaa\x56\xf3\ +\x8d\x14\xf0\x6b\x64\xcd\xb1\xad\x67\xa6\x93\xf5\x58\xce\xb3\x4c\ +\x15\x2a\x24\xd2\x61\xd0\x96\xf8\x8a\xde\x8b\xd0\xe0\xe5\x88\x95\ +\x18\x8a\xd0\xf0\x3d\xda\x0c\xdf\x9d\x9e\xce\x67\xbc\x7a\xe3\x2c\ +\x87\xf5\x1a\x67\x67\x95\x69\xaf\x29\xae\x7e\x3c\x26\x5c\x40\x9f\ +\x0b\x4d\xc1\x80\x83\x75\x84\x5e\x98\x0a\x78\xb0\x3d\xe4\x22\x6b\ +\xdb\xaa\xa1\xbc\x33\x75\x5b\x64\xcf\xec\xb1\x6a\x6c\x32\xc1\xf5\ +\x99\x82\x77\x14\xe8\x3c\x35\x72\xe8\xb0\x69\x24\x5c\x37\x4b\xf5\ +\xba\x04\xc9\xc7\x16\xed\x89\x92\x7a\xc9\xfb\xab\x93\x82\xfb\xab\ +\xe3\x42\xaa\x8d\x72\x2b\xb4\xb7\xd2\x13\x74\x56\x44\x9f\x31\x32\ +\x99\x20\x2a\x2d\x98\x23\xef\x72\xa6\xc8\x37\x36\xde\x88\x5f\x05\ +\x06\xf4\x22\x00\xb6\x95\xf4\x8b\x39\x37\x74\x9f\xe3\x60\x55\xf9\ +\x56\x3c\xa3\x82\xea\x46\xa7\x41\xa1\xa9\xaf\xc0\x46\xe8\xc1\x07\ +\xfa\x4d\x4b\x91\xb6\x2d\x5e\xc0\x2b\xd0\x9a\x41\x63\x34\x3b\x52\ +\xd4\xc3\x40\x05\xb4\x7e\x37\x2f\x5e\xbc\x9f\xf4\xd8\xac\xd9\xc2\ +\xa5\x49\x55\xf3\x7f\xd8\x7b\x2e\xcc\x7c\x52\xc5\x16\x29\x74\xba\ +\xa8\xca\x69\x32\xbe\x32\xa9\x0d\x63\x2b\x8d\xe3\x44\x98\x65\x0a\ +\x56\xba\xc3\x39\x22\xcb\xa1\x6e\xad\xb6\x4c\xa3\x5e\x64\x5b\xbe\ +\xad\x12\xf7\xbc\x98\xc4\xd5\xe1\xdc\xd6\x20\x69\xbd\x91\x52\x40\ +\xb2\x1f\x84\xcf\x1e\xb2\xcd\x97\xfa\x46\xcc\x17\x98\x0d\xce\x6a\ +\x27\xc1\x5d\xe9\x4e\x82\x4f\x0b\xd6\x2c\xc1\xf3\x79\x6f\x27\xc1\ +\xd7\x2e\xc1\x57\x8d\x4c\xbc\x0a\xcc\xd6\x0a\xf0\x8b\x62\x02\x9c\ +\xba\xa9\x6d\x44\x7e\x6f\x66\xfb\x09\xb3\xb1\x8c\xbe\x13\xdf\x3b\ +\xf1\xbd\x4d\x51\xd5\x7a\x9c\x8a\x56\xc9\x03\x29\xb6\xed\x0f\xdd\ +\xb5\x36\xeb\xc6\xbe\x52\x81\x34\xfb\xc8\x05\x7b\xe3\x73\x33\x23\ +\xcd\xd0\x65\xc4\xa0\xa2\x48\x74\x28\xcb\xa1\x3d\x9d\xad\xf5\xaf\ +\x25\x1c\xd7\x51\x72\xd8\xea\x12\xef\x71\x28\xdf\x88\xef\x21\x3e\ +\x33\x3b\x69\xb7\xc2\xdb\x29\x03\xab\xe6\xc4\xd3\xc7\x33\xe2\x54\ +\x11\xf7\x99\xf7\x2d\x53\x11\x63\x45\x21\x7f\xb0\xed\x01\xc8\x16\ +\xc9\xb7\x4b\x00\x42\x72\x4f\x85\x21\x46\x4e\x52\x89\x6c\xe0\xa0\ +\x16\xf3\x15\x2b\x39\xb0\x15\x61\x32\x12\xa1\x3a\x22\xf9\x32\xa8\ +\xb9\x4d\xef\x00\x06\xa7\xde\xc3\x18\x11\x15\x7e\xcc\x77\x4d\x3d\ +\x25\xb5\x26\x9a\x69\x4c\xfe\x2c\xe0\xbb\x5e\x26\xaa\x09\x40\x49\ +\xc1\x1e\xf8\xd6\xaa\xfa\xaa\xc9\xfc\xa2\x0c\x32\x2f\xe2\xa2\xfd\ +\xd0\x0d\xa9\x5c\x13\xdb\x1d\xf3\x0f\x81\x9c\x86\xe3\x58\xf2\x5c\ +\x87\x81\x11\x3a\x34\x11\x45\x81\x95\x3b\x00\x52\x3b\x24\x12\xa8\ +\x5d\xdd\x73\xcd\xa2\x22\xed\xda\xd3\xe0\x9e\x8e\x81\xf2\x0c\x55\ +\x98\xea\x48\x84\xfc\x69\xd2\x63\x19\xac\xf0\x2e\x90\x1d\x1a\x90\ +\x35\x8c\x11\x62\x20\x35\x4c\x07\xf0\xd7\x02\x41\x0e\x1d\xdb\x9f\ +\xe5\xea\x8c\xe1\x78\xb0\xc5\x99\x80\x55\xf3\x4f\xfd\x79\x29\x0c\ +\x54\x20\x66\xff\xab\x54\x03\x1a\x04\xe3\x43\x02\x88\x64\xca\x92\ +\x21\x86\x3a\xc2\x98\xe1\x61\xa8\x2c\x86\x9c\x69\x82\xc0\x69\x16\ +\x40\x39\xf3\x8f\x48\xc4\x7a\x72\x68\x6d\x9f\x38\x07\xe2\x3b\x1d\ +\x0a\x9c\x15\xc5\xfc\x23\x46\x8c\xde\x06\xbe\xd2\x86\x51\xbf\x40\ +\x94\x3f\x47\xb7\xd8\x41\x92\x00\x24\x26\xb7\x19\x65\x62\xa1\xb8\ +\x06\x20\x7e\x8b\xc2\xaf\x3b\x9e\xc8\xe2\x89\xb3\x52\x58\xe2\xf9\ +\x7a\x75\x8a\x35\xa1\xe2\xda\x01\x9d\xd4\x60\x4e\x81\xb1\xa0\x4d\ +\x8c\x5f\xc2\x8c\x16\xcc\x6e\x81\x52\xcb\x24\x42\x9a\xd8\xfb\x1d\ +\xe7\xe0\x1e\xda\x77\x44\x30\x86\x17\x98\x20\x00\x3a\xd8\x39\x50\ +\x74\x73\xfb\xf9\x63\x29\x4c\xf1\x2a\x09\x77\x04\xee\x81\xcf\x35\ +\xed\x04\x53\xaf\x3b\x3a\x6c\xfe\xf5\x94\x55\x90\x5b\xa0\xf6\x16\ +\xbb\xdb\xd7\xee\xf4\xcd\xdf\xe1\xee\x9c\xbe\xeb\x76\xfa\xd6\x0b\ +\x3a\x48\x15\xf5\xf9\x48\x4f\x32\x4d\xad\x2c\x00\x9e\xd4\x43\xe6\ +\x71\xb0\x04\x87\x12\x10\xa9\x8f\xf0\x24\x12\x16\x1f\xbb\x3c\x1e\ +\x49\x80\x55\x0d\x15\x1e\x23\x07\x5c\x74\xb9\x00\xb8\x0b\x30\xea\ +\x82\xd8\xa2\xa2\xa2\x57\x85\x3b\x67\x41\x86\xd4\x02\x52\xd7\xa3\ +\x6e\x97\xa7\x3d\xc5\xe1\x1c\x86\x0f\x9b\x51\xfb\x80\xbd\xcf\x0e\ +\x79\x4f\x54\xfa\x94\x7d\x12\x64\x09\x9f\xe5\x12\xfa\xbe\xc0\x81\ +\xaf\x2c\x7d\x3f\xe1\x4b\xab\xb4\x41\x85\x13\xe9\x79\x23\x45\x68\ +\x8f\xa2\xe9\x1a\x33\x6c\x4d\x1f\xd4\xa6\x42\xa7\x0a\x15\xd6\xf0\ +\xe5\xc2\xe7\x1e\x45\x23\xd7\x45\x26\x88\xec\x12\x06\xb3\x2a\xe0\ +\xc3\x58\x94\x08\x40\x1f\xf8\x60\x34\x28\x45\x6b\x77\x69\xa0\x37\ +\xa1\xb6\x61\x0e\x3f\x92\xce\xde\x69\xec\xf9\x98\x2e\x23\x4c\x9b\ +\xbf\x43\x66\x02\x6d\xe0\xf5\xd3\x7f\xae\xd8\xf9\xc5\x71\x6d\x5a\ +\x4a\xa0\xca\xef\x30\x1b\x57\xe0\x3e\x53\x20\x46\xe2\x76\x42\x19\ +\x32\x64\x0e\x20\x5b\xa8\xfd\xf3\xb3\x1b\xca\x5a\xc5\x50\xbc\x66\ +\x07\xa0\x2f\x2f\x2f\x57\x0f\x41\xe7\xe5\x55\x9f\x6e\x26\xb2\xed\ +\xc4\xee\x1b\xb7\xe0\x4f\x54\xf6\x96\x6d\xb1\xd4\x4b\xb1\x58\x0a\ +\x6c\x22\xc0\x62\x49\xf8\xda\xda\x6e\x57\xef\x02\x37\x13\x37\x43\ +\x5f\xda\x13\x36\x4c\xb0\x3b\x60\x6b\xf4\x40\x60\xf0\xa7\x4c\x49\ +\xd2\x86\x21\xa3\x6b\x14\x62\x20\x3d\x65\x77\x02\x62\x11\xe7\x72\ +\x4d\xbf\xdf\x63\x36\x4b\x10\xed\xaa\x47\xe0\xde\x83\x2e\x8b\x2e\ +\x41\x88\x13\xab\xf3\xcb\x8e\x74\x81\xa8\xc7\x12\x8b\xd9\x07\x28\ +\x9e\xfa\x62\x96\x2c\xec\xca\x09\x50\x14\x48\x09\xce\xda\x9d\x25\ +\xc2\x0a\x20\xce\x98\x8b\x57\x77\xe1\x11\xec\xa5\x69\xe4\xfa\x88\ +\xfc\x16\x05\xf9\xac\xa0\x1c\xa7\xdf\xb8\xe7\x00\xa5\x5a\x26\x73\ +\x65\x09\x9a\x7f\x8b\x63\x4d\x4e\x3d\x8e\x8b\x87\xd3\x97\xa0\x74\ +\x44\xc5\x2e\x10\x37\x9f\xcc\x8b\x5e\xa0\x53\xf4\x42\x0a\xbc\x31\ +\x06\xdd\x0b\xc3\x80\x8a\xed\xbc\x41\x27\x7f\x86\x4b\x90\x62\x48\ +\xf6\x7f\x7c\xda\x56\x5a\x2c\x96\x42\xf8\xab\xcc\x5e\xc0\xcd\x24\ +\x30\xfe\xfb\x4f\x72\x70\x2b\x87\x99\x8e\xe0\x0d\x41\xf0\x1f\x72\ +\xf0\x56\x01\x6f\x55\x08\xc3\x9f\x00\x43\x1b\x74\x7b\x21\x10\xaa\ +\x16\x49\xf5\x72\x92\x6b\x0a\xa4\x3f\xc6\xb7\x19\x94\xf4\x14\xf7\ +\x13\xfa\xd3\x46\x2e\xc3\x48\x67\x19\xfa\xf3\x0b\xec\x56\x70\xd0\ +\x27\xed\xd7\x74\x13\xd8\x4e\xc1\xb7\xf6\x40\x64\xfe\x96\x76\xe7\ +\xd6\x5c\x7b\x20\x32\x3f\x73\xae\x34\xb7\xe6\xfc\x5c\x36\x94\x11\ +\xe1\x2d\x91\x15\x58\x35\xaf\xe5\x08\x26\x3c\xcf\x8b\xe8\xdb\xda\ +\xc8\x97\xb8\x85\x1e\x61\x7b\xfa\xd1\x21\x8f\x74\x98\xb9\x67\x20\ +\x5f\x19\xf5\xfa\x4e\xf4\x62\x6e\xec\x7a\xaf\x70\x70\x08\x69\xd5\ +\x8f\x8e\x93\xff\x9a\xb5\xb0\xa6\x6c\xc1\xd8\x8e\x28\xe5\xbb\x91\ +\x8f\x8f\xe0\xd9\x6a\x9c\xd8\x79\xee\x7f\x2e\x2c\x71\x69\x82\x8e\ +\xc2\xc7\x1f\x5e\xd8\x9c\xdf\x3f\x3f\xb8\x5b\x51\xf4\x86\x0b\x87\ +\xb4\xc8\xdf\xea\x6e\x34\x32\x7d\x0e\x26\x87\x3a\x22\x6d\xcc\xe6\ +\xe8\x8e\x49\x9f\x29\x46\xd0\x2f\x3a\xa0\x62\x4c\xf4\xdf\x23\xaa\ +\x98\x9e\xb0\xf7\x20\xea\xa6\x40\xd2\x57\x4e\x14\xa1\x7e\xbc\x91\ +\x28\x02\xf2\xf2\x1b\x47\x3b\x4f\x94\x93\xcb\xb6\xed\x0b\xde\xcf\ +\xb2\x20\x9b\x71\x2e\x6f\x7f\xc0\x7b\x60\x05\xe6\x14\x29\xa0\x46\ +\x3c\x49\x41\x02\x60\xf2\xcc\x13\x77\x15\xf3\x78\xbe\x3e\x0e\x63\ +\x70\x6d\x30\xb5\x1e\x6b\xce\x9d\xe7\x9b\x73\xf5\xf3\x8b\x8b\x8b\ +\x46\xfd\xac\x88\x51\xb7\xbc\x7a\x9f\xc6\x58\x7d\x58\x90\x01\x88\ +\x27\x3c\x62\xc0\xa3\x65\xf2\xa4\x54\x3e\x17\xd4\x30\xcc\xab\x66\ +\xca\x1a\xcb\x9a\x1c\x60\x08\x98\x3d\x1c\x91\x13\x72\x45\x8e\x41\ +\x5d\xd7\x0b\x64\x7e\xe5\x88\x8b\xf3\x8d\x48\x8b\x09\x2d\x3e\x59\ +\x69\xb1\xec\xbe\x28\x5f\x7f\xed\xf6\x45\x6b\xdf\x17\xad\x2a\x2f\ +\x5f\xf3\x01\x13\xf6\xc0\xd9\x13\x90\x98\xf9\x9b\xbf\xdc\xac\x85\ +\xe7\xe5\xe4\x2c\x6c\x44\x7c\xf8\x7c\xf0\xe9\xc9\x4b\x90\xb2\xed\ +\x8d\x25\x0e\x55\x64\x31\xd0\x82\xdc\x84\xb9\xfc\x73\x2b\x03\x50\ +\x5a\xc2\x2b\x35\xa4\x91\x2f\x6b\xf3\x59\x7f\x27\x6b\x8b\xc8\xda\ +\x55\x1c\x2d\x3f\x80\x59\x37\xbd\x24\xc0\x0a\x47\x4c\x67\xf0\x31\ +\xe0\xdb\x1d\x09\xcf\x19\x70\xa6\x4f\x8d\xcd\xbe\xa1\xc4\x44\x2c\ +\x72\xb4\xf7\x15\x5b\x87\x39\xc4\x3e\xef\x76\x61\xa7\x08\xe5\xb8\ +\x39\x0c\x60\xbf\x68\xa3\xde\xae\xc3\x68\x8b\x69\x14\xb3\x89\xc5\ +\x54\x13\x0d\x80\x15\xd8\x33\xe6\x64\xca\xd7\x56\x21\x78\xd1\x03\ +\x72\x30\x2c\x8d\xa2\xd0\x8f\x04\x26\x6b\x7d\x4d\x1e\xa6\x1c\x3f\ +\x16\x8c\x72\xb6\x79\x3f\x96\x99\x8a\xbc\x9d\x2e\xca\xd2\x45\xe7\ +\xc5\x54\xd1\x82\xd4\x91\x85\x91\x76\x6c\x41\x9c\x2c\xa8\x4e\x29\ +\xe5\xa7\x4d\xed\x94\xd2\xa6\x95\xd2\x82\xa8\xe8\xf7\xa0\x96\x22\ +\xfa\x77\xe3\xd9\x24\x72\x64\x05\x6d\xef\xd9\xf0\x27\xfb\x9c\x52\ +\x22\x0a\xc7\x47\x8d\x0a\x22\x0a\x38\xbd\x88\xd1\x77\xa2\x38\x73\ +\x5b\x50\xf0\x33\x3c\x0b\x2e\xea\x78\x9c\x2c\xee\x02\x44\xd5\x49\ +\xe2\x7c\x37\xe3\x4e\x12\xaf\x45\x12\x2f\xbc\x94\x6b\xf5\x9c\x94\ +\xac\x2b\xb9\x90\xa2\xec\xbb\x93\x0f\xa1\xb9\x4c\xe3\x2c\x79\x77\ +\xb4\xf7\x01\xe0\xa5\x02\xcd\x69\x1a\x7b\x53\x8f\xbc\x3e\xda\xd5\ +\xcf\xfe\x1e\x49\xf3\xf2\x95\xe2\x34\x70\x3f\x31\xf5\x25\x1a\x48\ +\x9b\x71\x90\x6e\xaa\xa9\xd0\x51\xcb\xb0\x84\x29\xde\x75\x3f\xf7\ +\x00\x1e\xf7\x6b\x20\x85\x8c\x9a\x21\x90\xa4\x4b\x07\x3c\x18\x67\ +\x8d\x7b\xf8\x9e\x05\x77\x0c\x3f\x1d\x78\x38\xed\xdc\xbd\x64\x41\ +\xb5\xfb\x05\xea\x80\xd9\xcb\x78\xff\xc5\xb5\x0c\x7c\xf7\x5c\xca\ +\x4d\x02\x38\xc6\xea\x1d\xd3\x80\xf7\x04\xac\xc6\x4c\xef\xc0\xe4\ +\xc8\x5f\xaf\xb0\xfe\x33\xd2\xf0\xff\x26\x8f\xb7\x8a\x72\x20\x9d\ +\xde\xb4\xe4\xeb\x0d\x43\x9f\x39\x80\xc1\xcc\xf2\x30\x2c\xa9\x54\ +\x9c\xc4\xda\xa9\x94\x4c\x95\xb2\xc4\xe1\x98\x4c\x57\xed\xaa\x57\ +\x60\x4f\x75\xca\x60\x18\xe0\x57\x14\x75\x9f\xb1\x0a\x15\xcb\x82\ +\x89\xec\x34\xcb\x5a\x34\xcb\x5b\x1e\xb0\x9b\xbe\x94\x20\x63\x67\ +\x94\x4b\x17\xea\x3c\x57\xb7\xc8\xbe\xe7\x62\x59\xfb\xfe\xe4\x38\ +\x1f\x41\x85\xf0\xb3\x7c\x1c\xd1\x4f\x53\x7f\x78\xb5\x9f\xcd\xc9\ +\xf4\xd0\x4d\x84\x49\x44\xd4\x7e\xfe\x25\x4c\xd1\x5c\x92\x41\x8a\ +\x09\x4d\x07\xd5\x4e\x68\xce\x11\x9a\x4b\x5c\x17\x99\x21\x34\x8b\ +\x07\xb7\x9e\xd1\xc1\xf0\x25\xf9\xc8\xa8\x0f\x02\x8d\x2a\x25\xef\ +\x9d\x39\xb1\x8d\x27\x11\xd6\x76\x0e\x81\x0f\xdc\x27\xfd\xb6\x95\ +\x2a\x8b\xe5\xc0\xbf\x96\x86\x9c\x55\x97\x82\x8f\xc3\x5f\x54\x3b\ +\xfc\x65\x75\xc3\xdf\x70\xe5\xc1\xce\xa0\x42\xfc\x87\x10\x54\xb8\ +\x04\x21\x04\x15\xae\x42\x1b\x44\x4b\xbf\xca\x45\x70\x00\x54\xb8\ +\x06\x0e\x80\x0a\x97\xe0\x9a\x7a\xdf\x74\xd5\xcb\x30\x05\xa2\xc2\ +\xa5\x98\x02\x51\x68\x39\x2a\x37\x55\x0a\x86\x6f\xea\xf9\xb9\x4f\ +\xf3\xad\x95\xaf\xd0\x8a\x7b\x34\x88\xf9\x6e\x9c\xff\x30\xb6\x93\ +\xda\x46\x73\x65\x5d\x1f\x50\x8d\x4d\x13\xd3\x05\xad\xbf\x2b\xc2\ +\x44\xe8\xd9\xb2\xc6\xbe\xe9\xc3\x86\x27\x8e\x24\xaa\x18\xb9\x0b\ +\x91\x77\x44\xa2\x6d\x32\xf4\x1a\xb0\xae\x39\xc4\x0b\x2a\xbd\x7e\ +\x34\xc8\x87\xf6\x6f\x78\xd1\xb1\xf0\xa9\x2a\x72\x17\xeb\x72\x56\ +\x58\x62\x01\xbf\x47\x53\xec\x23\x20\x9a\x1c\xc4\x71\x5b\xe1\xd9\ +\xc8\xcf\xf3\x22\x9f\x4f\x44\x02\x15\x14\x3f\xab\x7e\x2e\xf6\x55\ +\x60\x53\x72\x61\x67\xdd\xfe\xfa\x8e\x00\xa1\xe1\x23\xf0\x90\xf4\ +\x4a\x97\x3c\x0b\xfc\x4c\xf9\xdf\xec\xd8\xf9\x99\x36\xea\x67\x5a\ +\x90\xb5\xfe\xa4\xfd\x4c\xef\xf1\xe4\x0a\x5e\x1b\x84\xe1\x12\x1d\ +\x1e\x67\xa1\xa0\x6a\x14\xf3\x8c\x54\x63\xbc\xa3\xcc\x84\x5f\x46\ +\x45\x26\x41\xbc\xe8\x78\xe1\xb3\xc0\xbc\x1c\x3a\xce\x79\xd6\x33\ +\x2f\xd1\x69\x85\xd7\x96\x4e\x33\xa2\xa2\x38\x8c\xef\x33\x1f\x3d\ +\x58\xa8\x92\x22\x91\x19\xc6\x70\xa0\x19\xa8\xab\xb0\x97\xcd\x7c\ +\x06\x22\x1c\x0c\x49\x60\x5b\xf5\x53\x31\x99\x9c\xac\x4c\xf4\x35\ +\x6d\x17\x6b\x14\x6b\x11\xca\xef\x49\x40\xcc\x1d\xe0\xbb\xda\x3f\ +\xdf\x27\x03\xaa\x7a\x5c\x5c\xed\xd7\xeb\xfb\x98\x42\xd6\x1c\xf2\ +\x87\x01\x1d\x46\x39\x70\xad\xbf\x3f\xd9\xe7\xb7\x4a\x0e\x7e\x01\ +\x63\xa5\x2d\x47\x0a\x73\xa6\x52\xad\xe0\x3d\x6f\xa4\x8d\x1c\xb8\ +\x11\xb5\x85\x24\x5e\xe2\xa0\xb4\xec\xda\xb2\xdc\x1a\xe3\x54\xc0\ +\x9f\x2d\xb7\x4d\x40\xb2\x33\xe1\xeb\xd6\xef\x7f\xd8\xf7\x40\xd4\ +\x85\x05\x7b\x8e\x9b\xd0\xf5\x85\x3d\xd4\xb0\x83\xd7\x9c\x06\xb2\ +\x77\xd4\x47\xe6\xb2\x15\x16\x01\xe9\x71\xf3\x01\xb9\xc1\xaf\x98\ +\x5c\x8f\x8c\xb1\x66\x4d\x06\x20\x9f\x46\xba\x1f\xd5\xcf\x03\xc6\ +\x01\xab\x8b\x41\x92\x12\x60\x99\xd0\xcc\xe2\x6e\x1e\x48\xd8\xdb\ +\xda\xc0\x0a\xb3\x73\xb2\x11\x34\xa9\xdc\x08\x28\x8b\xd6\x6b\x76\ +\x51\x37\x03\x56\x78\xa3\x43\x36\x8a\xa6\xb5\x1b\xc2\x91\xdb\xed\ +\xcc\x01\x66\x52\xbb\x11\x60\xa2\xac\x82\x6c\x60\xa6\xb5\x1b\x01\ +\x26\x91\x6c\x96\x0d\x51\xaa\x49\x71\xb0\x92\x05\xd8\x53\x53\x31\ +\x6d\x05\xa9\xb6\x22\x17\x74\xaf\x60\x2e\xe5\xd8\xcd\x62\xf2\xec\ +\x46\xd5\x00\x00\xf4\x9d\x71\x49\x08\x06\xd2\x45\x38\x2e\x5a\x27\ +\x3d\x41\x83\x96\x17\xe0\x59\x56\xff\x00\x8f\xcf\xe2\x0e\xc6\x95\ +\xda\x16\x60\x02\x30\x7e\x17\xef\x2b\x75\xba\xbe\x59\x9b\x34\x71\ +\x5d\x06\xd2\xb4\x40\x0d\xbe\x71\x87\x75\x27\x7d\x62\xb1\xc3\x08\ +\x5e\x7a\x1e\x6a\x24\xfc\x4d\xcc\x78\x88\xa6\xa6\x9d\x5e\x22\xec\ +\xd1\x7c\x68\x5d\x02\xc0\x0f\xd1\xe3\xb8\x75\x72\x71\xd9\xac\x8d\ +\x23\x75\x86\x6f\xcf\x76\xe4\x33\xfc\x50\x83\x35\x8c\xd3\xbd\x9d\ +\xd6\x2f\x92\xdd\x3d\xaf\x67\x75\xe7\x7e\xea\x70\x69\x12\xa8\xdd\ +\x28\xa6\x27\xa7\xa2\xcb\xc5\x31\xe2\x34\x81\xe3\x93\x22\x38\x3e\ +\xbb\xa8\xa7\xba\x3b\x2d\x0d\xc7\xa7\xeb\xc3\xf1\x79\xb9\x38\x3e\ +\x4f\x12\x5e\xe3\xe2\x78\x9d\x38\x6e\x5c\x34\xb6\x10\xc7\xd1\x8d\ +\xcc\x25\x63\xb6\xb1\x56\xcc\xd6\xcf\x37\x86\xd9\xd5\x25\x44\x74\ +\x29\x4c\xb9\x98\x3d\x7b\x9e\x64\xe4\xf3\xb3\x22\x98\x3d\x39\x3b\ +\x7d\x02\xb2\x37\xba\xba\xa3\x5c\xcc\x9e\x9c\xa4\x30\x7b\xb1\x4e\ +\x9a\x2d\x13\xb3\x17\xc5\x25\xee\xf4\x8a\xd9\x72\x91\x5c\x4f\xd1\ +\x6f\xe3\xb2\x90\x64\x38\x45\x7f\x4d\xa2\xbb\x4c\x35\x39\x1f\xcb\ +\xf1\x47\xa8\x6f\xd6\x46\xbc\xb5\xf7\x7f\x52\xff\xa8\x2c\ \x00\x00\x07\xb5\ \x00\ \x00\x1a\x6e\x78\x9c\xed\x58\x5d\x6f\xe3\xb8\x15\x7d\xcf\xaf\x50\ @@ -34858,58 +34860,58 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xbf\xe9\ -\x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x11\x96\ -\x00\x00\x08\x1c\x00\x01\x00\x00\x00\x01\x00\x07\x73\xb3\ -\x00\x00\x0a\x3e\x00\x01\x00\x00\x00\x01\x00\x08\x27\xeb\ -\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x5c\x7d\ -\x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xdd\x33\ -\x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x35\xd1\ -\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x07\x07\x02\ -\x00\x00\x08\xb6\x00\x01\x00\x00\x00\x01\x00\x07\xad\x42\ -\x00\x00\x0a\x8e\x00\x01\x00\x00\x00\x01\x00\x08\x43\xfb\ -\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x2a\xb8\ -\x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x3b\x95\ -\x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xca\x9d\ -\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x30\x37\ -\x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xf5\xf8\ -\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x20\x4c\ -\x00\x00\x09\xc8\x00\x00\x00\x00\x00\x01\x00\x08\x0a\x31\ -\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\xe0\ -\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x77\x9c\ -\x00\x00\x09\x80\x00\x01\x00\x00\x00\x01\x00\x07\xf6\x3b\ -\x00\x00\x09\xa2\x00\x01\x00\x00\x00\x01\x00\x08\x00\x9d\ -\x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x65\x83\ -\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe4\x27\ -\x00\x00\x07\xd2\x00\x01\x00\x00\x00\x01\x00\x07\x5c\x89\ -\x00\x00\x09\x10\x00\x00\x00\x00\x00\x01\x00\x07\xbd\x8a\ -\x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x89\x0c\ -\x00\x00\x09\x34\x00\x00\x00\x00\x00\x01\x00\x07\xd4\x3d\ -\x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x1d\xa4\ -\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x4b\x9f\ -\x00\x00\x0a\x5e\x00\x00\x00\x00\x00\x01\x00\x08\x32\x85\ -\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x4b\ -\x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x05\xf3\xe7\ -\x00\x00\x0a\xbe\x00\x00\x00\x00\x00\x01\x00\x08\x4f\xd4\ -\x00\x00\x09\x58\x00\x00\x00\x00\x00\x01\x00\x07\xe7\x14\ -\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x06\x09\x07\ -\x00\x00\x08\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x7c\x5c\ -\x00\x00\x09\xee\x00\x00\x00\x00\x00\x01\x00\x08\x12\xbe\ -\x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\xb2\x8a\ -\x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x13\xf3\ -\x00\x00\x08\x94\x00\x00\x00\x00\x00\x01\x00\x07\x98\xb1\ -\x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x52\x3c\ -\x00\x00\x07\x22\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x5c\ -\x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x83\x8d\ -\x00\x00\x08\xe0\x00\x01\x00\x00\x00\x01\x00\x07\xb3\xb7\ -\x00\x00\x07\xaa\x00\x01\x00\x00\x00\x01\x00\x07\x51\x17\ -\x00\x00\x07\xf4\x00\x01\x00\x00\x00\x01\x00\x07\x63\xdd\ -\x00\x00\x0a\x14\x00\x01\x00\x00\x00\x01\x00\x08\x1d\x69\ -\x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x43\x56\ -\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x07\x41\x45\ -\x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x90\xf1\ -\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xec\x84\ -\x00\x00\x08\x62\x00\x00\x00\x00\x00\x01\x00\x07\x83\xad\ +\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x06\xc0\x10\ +\x00\x00\x03\x94\x00\x00\x00\x00\x00\x01\x00\x06\x11\xbd\ +\x00\x00\x08\x1c\x00\x01\x00\x00\x00\x01\x00\x07\x73\xda\ +\x00\x00\x0a\x3e\x00\x01\x00\x00\x00\x01\x00\x08\x28\x12\ +\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x06\x5c\xa4\ +\x00\x00\x06\x2e\x00\x00\x00\x00\x00\x01\x00\x06\xdd\x5a\ +\x00\x00\x07\x42\x00\x01\x00\x00\x00\x01\x00\x07\x35\xf8\ +\x00\x00\x06\xa2\x00\x00\x00\x00\x00\x01\x00\x07\x07\x29\ +\x00\x00\x08\xb6\x00\x01\x00\x00\x00\x01\x00\x07\xad\x69\ +\x00\x00\x0a\x8e\x00\x01\x00\x00\x00\x01\x00\x08\x44\x22\ +\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x2a\xdf\ +\x00\x00\x07\x68\x00\x01\x00\x00\x00\x01\x00\x07\x3b\xbc\ +\x00\x00\x06\x08\x00\x00\x00\x00\x00\x01\x00\x06\xca\xc4\ +\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x01\x00\x06\x30\x5e\ +\x00\x00\x06\x76\x00\x01\x00\x00\x00\x01\x00\x06\xf6\x1f\ +\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x20\x73\ +\x00\x00\x09\xc8\x00\x00\x00\x00\x00\x01\x00\x08\x0a\x58\ +\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xec\x07\ +\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x06\x77\xc3\ +\x00\x00\x09\x80\x00\x01\x00\x00\x00\x01\x00\x07\xf6\x62\ +\x00\x00\x09\xa2\x00\x01\x00\x00\x00\x01\x00\x08\x00\xc4\ +\x00\x00\x04\xcc\x00\x00\x00\x00\x00\x01\x00\x06\x65\xaa\ +\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe4\x4e\ +\x00\x00\x07\xd2\x00\x01\x00\x00\x00\x01\x00\x07\x5c\xb0\ +\x00\x00\x09\x10\x00\x00\x00\x00\x00\x01\x00\x07\xbd\xb1\ +\x00\x00\x05\x42\x00\x01\x00\x00\x00\x01\x00\x06\x89\x33\ +\x00\x00\x09\x34\x00\x00\x00\x00\x00\x01\x00\x07\xd4\x64\ +\x00\x00\x06\xfc\x00\x00\x00\x00\x00\x01\x00\x07\x1d\xcb\ +\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x4b\xc6\ +\x00\x00\x0a\x5e\x00\x00\x00\x00\x00\x01\x00\x08\x32\xac\ +\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x72\ +\x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x05\xf4\x0e\ +\x00\x00\x0a\xbe\x00\x00\x00\x00\x00\x01\x00\x08\x4f\xfb\ +\x00\x00\x09\x58\x00\x00\x00\x00\x00\x01\x00\x07\xe7\x3b\ +\x00\x00\x03\x64\x00\x01\x00\x00\x00\x01\x00\x06\x09\x2e\ +\x00\x00\x08\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x7c\x83\ +\x00\x00\x09\xee\x00\x00\x00\x00\x00\x01\x00\x08\x12\xe5\ +\x00\x00\x05\xc4\x00\x01\x00\x00\x00\x01\x00\x06\xb2\xb1\ +\x00\x00\x06\xd4\x00\x01\x00\x00\x00\x01\x00\x07\x14\x1a\ +\x00\x00\x08\x94\x00\x00\x00\x00\x00\x01\x00\x07\x98\xd8\ +\x00\x00\x04\x74\x00\x01\x00\x00\x00\x01\x00\x06\x52\x63\ +\x00\x00\x07\x22\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x83\ +\x00\x00\x05\x22\x00\x01\x00\x00\x00\x01\x00\x06\x83\xb4\ +\x00\x00\x08\xe0\x00\x01\x00\x00\x00\x01\x00\x07\xb3\xde\ +\x00\x00\x07\xaa\x00\x01\x00\x00\x00\x01\x00\x07\x51\x3e\ +\x00\x00\x07\xf4\x00\x01\x00\x00\x00\x01\x00\x07\x64\x04\ +\x00\x00\x0a\x14\x00\x01\x00\x00\x00\x01\x00\x08\x1d\x90\ +\x00\x00\x04\x20\x00\x01\x00\x00\x00\x01\x00\x06\x43\x7d\ +\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x07\x41\x6c\ +\x00\x00\x05\x70\x00\x00\x00\x00\x00\x01\x00\x06\x91\x18\ +\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xec\xab\ +\x00\x00\x08\x62\x00\x00\x00\x00\x00\x01\x00\x07\x83\xd4\ \x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x05\xcc\x17\ \x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x05\xd5\x2b\ " diff --git a/src/Mod/Draft/Resources/ui/userprefs-base.ui b/src/Mod/Draft/Resources/ui/userprefs-base.ui index b98eb637b3..64bb05c9ad 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-base.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-base.ui @@ -469,7 +469,7 @@ Snap maximum - true + false maxSnap @@ -494,6 +494,9 @@ + + false + Maximum number of edges to be considered for snapping @@ -504,6 +507,9 @@ + + false + 999 @@ -628,7 +634,7 @@ Use grid - true + false grid @@ -653,6 +659,9 @@ + + false + Grid spacing @@ -660,6 +669,9 @@ + + false + The spacing between each grid line @@ -676,6 +688,9 @@ + + false + Main lines every @@ -683,6 +698,9 @@ + + false + Mainlines will be drawn thicker. Specify here how many squares between mainlines. From f0a6d25621a289d1335953c537b33cc2f4b4c7dc Mon Sep 17 00:00:00 2001 From: logari81 Date: Thu, 22 Mar 2012 14:14:07 +0100 Subject: [PATCH 033/351] Fix 0000461: Sketcher: tangent constraint between two arcs/circles --- src/Mod/Sketcher/App/Sketch.cpp | 87 +++++++++++++++----- src/Mod/Sketcher/App/freegcs/Constraints.cpp | 60 ++++++++++++++ src/Mod/Sketcher/App/freegcs/Constraints.h | 23 +++++- src/Mod/Sketcher/App/freegcs/GCS.cpp | 72 ++++++++++++++++ src/Mod/Sketcher/App/freegcs/GCS.h | 9 ++ src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 23 ++++-- 6 files changed, 245 insertions(+), 29 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 35f6bdb64c..974ea38bcc 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -836,8 +836,33 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2) GCSsys.addConstraintTangent(l, c, tag); return ConstraintsCounter; } - } else - Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n"); + } else if (Geoms[geoId1].type == Circle) { + GCS::Circle &c = Circles[Geoms[geoId1].index]; + if (Geoms[geoId2].type == Circle) { + GCS::Circle &c2 = Circles[Geoms[geoId2].index]; + int tag = ++ConstraintsCounter; + GCSsys.addConstraintTangent(c, c2, tag); + return ConstraintsCounter; + } else if (Geoms[geoId2].type == Arc) { + GCS::Arc &a = Arcs[Geoms[geoId2].index]; + int tag = ++ConstraintsCounter; + GCSsys.addConstraintTangent(c, a, tag); + return ConstraintsCounter; + } + } else if (Geoms[geoId1].type == Arc) { + GCS::Arc &a = Arcs[Geoms[geoId1].index]; + if (Geoms[geoId2].type == Circle) { + GCS::Circle &c = Circles[Geoms[geoId2].index]; + int tag = ++ConstraintsCounter; + GCSsys.addConstraintTangent(c, a, tag); + return ConstraintsCounter; + } else if (Geoms[geoId2].type == Arc) { + GCS::Arc &a2 = Arcs[Geoms[geoId2].index]; + int tag = ++ConstraintsCounter; + GCSsys.addConstraintTangent(a, a2, tag); + return ConstraintsCounter; + } + } return -1; } @@ -850,8 +875,8 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2) // 2) Line1, start/end/mid, Circle2 // 3) Line1, start/end/mid, Arc2 // 4) Arc1, start/end, Line2 - // 5) Arc1, start/end, Circle2 (not implemented yet) - // 6) Arc1, start/end, Arc2 (not implemented yet) + // 5) Arc1, start/end, Circle2 + // 6) Arc1, start/end, Arc2 geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -895,16 +920,24 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2) return ConstraintsCounter; } else if (Geoms[geoId2].type == Arc) { - //GCS::Arcs &a2 = Arcs[Geoms[geoId2].index]; - //GCSsys.addConstraintPointOnArc(p1, a2); - //GCSsys.addConstraintTangent(a1, a2); - Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n"); + GCS::Arc &a2 = Arcs[Geoms[geoId2].index]; + int tag = ++ConstraintsCounter; + GCSsys.addConstraintPointOnArc(p1, a2, tag); + GCSsys.addConstraintTangent(a1, a2, tag); + return ConstraintsCounter; } else if (Geoms[geoId2].type == Circle) { - //GCS::Circle &c2 = Circles[Geoms[geoId2].index]; - //GCSsys.addConstraintPointOnCircle(p1, c2); - //GCSsys.addConstraintTangent(a1, c2); - Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n"); + GCS::Circle &c2 = Circles[Geoms[geoId2].index]; + if (pos1 == start) { + int tag = ++ConstraintsCounter; + GCSsys.addConstraintTangentCircle2Arc(c2, a1, tag); + return ConstraintsCounter; + } + else if (pos1 == end) { + int tag = ++ConstraintsCounter; + GCSsys.addConstraintTangentArc2Circle(a1, c2, tag); + return ConstraintsCounter; + } } } return -1; @@ -917,7 +950,7 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos // 1) Line1, start/end/mid, Line2, start/end/mid // 2) Line1, start/end/mid, Arc2, start/end // 3) Arc1, start/end, Line2, start/end/mid (converted to case #2) - // 4) Arc1, start/end, Arc2, start/end (not implemented yet) + // 4) Arc1, start/end, Arc2, start/end geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -970,7 +1003,7 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos GCSsys.addConstraintTangentLine2Arc(l1.p1, l1.p2, a2, tag); return ConstraintsCounter; } - else if (pos1 == mid) { + else if (pos1 == mid) { // FIXME: coincidence with midpoint of line?? int tag = ++ConstraintsCounter; GCSsys.addConstraintP2PCoincident(p1, p2, tag); GCSsys.addConstraintTangent(l1, a2, tag); @@ -988,7 +1021,7 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos GCSsys.addConstraintTangentArc2Line(a2, l1.p2, l1.p1, tag); return ConstraintsCounter; } - else if (pos1 == mid) { + else if (pos1 == mid) { // FIXME: coincidence with midpoint of line?? int tag = ++ConstraintsCounter; GCSsys.addConstraintP2PCoincident(p1, p2, tag); GCSsys.addConstraintTangent(l1, a2, tag); @@ -1000,12 +1033,26 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos } } else if (Geoms[geoId1].type == Arc) { - //GCS::Arc &a1 = Arcs[Geoms[geoId1].index]; + GCS::Arc &a1 = Arcs[Geoms[geoId1].index]; if (Geoms[geoId2].type == Arc) { - //GCS::Arcs &a2 = Arcs[Geoms[geoId2].index]; - //GCSsys.addConstraintPointOnArc(p1, a2); - //GCSsys.addConstraintTangent(a1, a2); - Base::Console().Warning("Tangency constraints between arcs are not implemented yet.\n"); + GCS::Arc &a2 = Arcs[Geoms[geoId2].index]; + if (pos1 == start && (pos2 == start || pos2 == end)) { + int tag = ++ConstraintsCounter; + if (pos2 == start) + GCSsys.addConstraintTangentArc2Arc(a1, true, a2, false, tag); + else // if (pos2 == end) + GCSsys.addConstraintTangentArc2Arc(a1, true, a2, true, tag); + // GCSsys.addConstraintTangentArc2Arc(a2, false, a1, false, tag); + return ConstraintsCounter; + } + else if (pos1 == end && (pos2 == start || pos2 == end)) { + int tag = ++ConstraintsCounter; + if (pos2 == start) + GCSsys.addConstraintTangentArc2Arc(a1, false, a2, false, tag); + else // if (pos2 == end) + GCSsys.addConstraintTangentArc2Arc(a1, false, a2, true, tag); + return ConstraintsCounter; + } } } return -1; diff --git a/src/Mod/Sketcher/App/freegcs/Constraints.cpp b/src/Mod/Sketcher/App/freegcs/Constraints.cpp index b893bb70ee..76b42f8d73 100644 --- a/src/Mod/Sketcher/App/freegcs/Constraints.cpp +++ b/src/Mod/Sketcher/App/freegcs/Constraints.cpp @@ -771,4 +771,64 @@ double ConstraintMidpointOnLine::grad(double *param) return scale * deriv; } +// TangentCircumf +ConstraintTangentCircumf::ConstraintTangentCircumf(Point &p1, Point &p2, + double *rad1, double *rad2, bool internal_) +{ + internal = internal_; + pvec.push_back(p1.x); + pvec.push_back(p1.y); + pvec.push_back(p2.x); + pvec.push_back(p2.y); + pvec.push_back(rad1); + pvec.push_back(rad2); + origpvec = pvec; + rescale(); +} + +ConstraintType ConstraintTangentCircumf::getTypeId() +{ + return TangentCircumf; +} + +void ConstraintTangentCircumf::rescale(double coef) +{ + scale = coef * 1; +} + +double ConstraintTangentCircumf::error() +{ + double dx = (*c1x() - *c2x()); + double dy = (*c1y() - *c2y()); + if (internal) + return scale * (sqrt(dx*dx + dy*dy) - std::abs(*r1() - *r2())); + else + return scale * (sqrt(dx*dx + dy*dy) - (*r1() + *r2())); +} + +double ConstraintTangentCircumf::grad(double *param) +{ + double deriv=0.; + if (param == c1x() || param == c1y() || + param == c2x() || param == c2y()|| + param == r1() || param == r2()) { + double dx = (*c1x() - *c2x()); + double dy = (*c1y() - *c2y()); + double d = sqrt(dx*dx + dy*dy); + if (param == c1x()) deriv += dx/d; + if (param == c1y()) deriv += dy/d; + if (param == c2x()) deriv += -dx/d; + if (param == c2y()) deriv += -dy/d; + if (internal) { + if (param == r1()) deriv += (*r1() > *r2()) ? -1 : 1; + if (param == r2()) deriv += (*r1() > *r2()) ? 1 : -1; + } + else { + if (param == r1()) deriv += -1; + if (param == r2()) deriv += -1; + } + } + return scale * deriv; +} + } //namespace GCS diff --git a/src/Mod/Sketcher/App/freegcs/Constraints.h b/src/Mod/Sketcher/App/freegcs/Constraints.h index 40018a9e8b..6a9369ab2a 100644 --- a/src/Mod/Sketcher/App/freegcs/Constraints.h +++ b/src/Mod/Sketcher/App/freegcs/Constraints.h @@ -44,7 +44,8 @@ namespace GCS Parallel = 7, Perpendicular = 8, L2LAngle = 9, - MidpointOnLine = 10 + MidpointOnLine = 10, + TangentCircumf = 11 }; class Constraint @@ -262,6 +263,26 @@ namespace GCS virtual double grad(double *); }; + // TangentCircumf + class ConstraintTangentCircumf : public Constraint + { + private: + inline double* c1x() { return pvec[0]; } + inline double* c1y() { return pvec[1]; } + inline double* c2x() { return pvec[2]; } + inline double* c2y() { return pvec[3]; } + inline double* r1() { return pvec[4]; } + inline double* r2() { return pvec[5]; } + bool internal; + public: + ConstraintTangentCircumf(Point &p1, Point &p2, + double *rad1, double *rad2, bool internal_=false); + virtual ConstraintType getTypeId(); + virtual void rescale(double coef=1.); + virtual double error(); + virtual double grad(double *); + }; + } //namespace GCS #endif // FREEGCS_CONSTRAINTS_H diff --git a/src/Mod/Sketcher/App/freegcs/GCS.cpp b/src/Mod/Sketcher/App/freegcs/GCS.cpp index 069e181626..2d7c0eba30 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/freegcs/GCS.cpp @@ -286,6 +286,14 @@ int System::addConstraintMidpointOnLine(Point &l1p1, Point &l1p2, return addConstraint(constr); } +int System::addConstraintTangentCircumf(Point &p1, Point &p2, double *rad1, double *rad2, + bool internal, int tagId) +{ + Constraint *constr = new ConstraintTangentCircumf(p1, p2, rad1, rad2, internal); + constr->setTag(tagId); + return addConstraint(constr); +} + // derived constraints int System::addConstraintP2PCoincident(Point &p1, Point &p2, int tagId) @@ -352,6 +360,33 @@ int System::addConstraintTangent(Line &l, Arc &a, int tagId) return addConstraintP2LDistance(a.center, l, a.rad, tagId); } +int System::addConstraintTangent(Circle &c1, Circle &c2, int tagId) +{ + double dx = *(c2.center.x) - *(c1.center.x); + double dy = *(c2.center.y) - *(c1.center.y); + double d = sqrt(dx*dx + dy*dy); + return addConstraintTangentCircumf(c1.center, c2.center, c1.rad, c2.rad, + (d < *c1.rad || d < *c2.rad), tagId); +} + +int System::addConstraintTangent(Arc &a1, Arc &a2, int tagId) +{ + double dx = *(a2.center.x) - *(a1.center.x); + double dy = *(a2.center.y) - *(a1.center.y); + double d = sqrt(dx*dx + dy*dy); + return addConstraintTangentCircumf(a1.center, a2.center, a1.rad, a2.rad, + (d < *a1.rad || d < *a2.rad), tagId); +} + +int System::addConstraintTangent(Circle &c, Arc &a, int tagId) +{ + double dx = *(a.center.x) - *(c.center.x); + double dy = *(a.center.y) - *(c.center.y); + double d = sqrt(dx*dx + dy*dy); + return addConstraintTangentCircumf(c.center, a.center, c.rad, a.rad, + (d < *c.rad || d < *a.rad), tagId); +} + int System::addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId) { addConstraintP2PCoincident(p2, a.start, tagId); @@ -366,6 +401,43 @@ int System::addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId return addConstraintP2PAngle(p1, p2, a.endAngle, incr_angle, tagId); } +int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId) +{ + addConstraintPointOnCircle(a.start, c, tagId); + double dx = *(a.start.x) - *(c.center.x); + double dy = *(a.start.y) - *(c.center.y); + if (dx * cos(*(a.startAngle)) + dy * sin(*(a.startAngle)) > 0) + addConstraintP2PAngle(c.center, a.start, a.startAngle, 0, tagId); + else + addConstraintP2PAngle(c.center, a.start, a.startAngle, M_PI, tagId); +} + +int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId) +{ + addConstraintPointOnCircle(a.end, c, tagId); + double dx = *(a.end.x) - *(c.center.x); + double dy = *(a.end.y) - *(c.center.y); + if (dx * cos(*(a.endAngle)) + dy * sin(*(a.endAngle)) > 0) + addConstraintP2PAngle(c.center, a.end, a.endAngle, 0, tagId); + else + addConstraintP2PAngle(c.center, a.end, a.endAngle, M_PI, tagId); +} + +int System::addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2, + int tagId) +{ + Point &p1 = reverse1 ? a1.start : a1.end; + Point &p2 = reverse2 ? a2.end : a2.start; + addConstraintP2PCoincident(p1, p2, tagId); + + double *angle1 = reverse1 ? a1.startAngle : a1.endAngle; + double *angle2 = reverse2 ? a2.endAngle : a2.startAngle; + if (cos(*angle1) * cos(*angle2) + sin(*angle1) * sin(*angle2) > 0) + addConstraintEqual(angle1, angle2, tagId); + else + addConstraintP2PAngle(p2, a2.center, angle1, 0, tagId); +} + int System::addConstraintCircleRadius(Circle &c, double *radius, int tagId) { return addConstraintEqual(c.rad, radius, tagId); diff --git a/src/Mod/Sketcher/App/freegcs/GCS.h b/src/Mod/Sketcher/App/freegcs/GCS.h index 9e809c6c23..3c85383486 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.h +++ b/src/Mod/Sketcher/App/freegcs/GCS.h @@ -101,6 +101,8 @@ namespace GCS int addConstraintMidpointOnLine(Line &l1, Line &l2, int tagId=0); int addConstraintMidpointOnLine(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2, int tagId=0); + int addConstraintTangentCircumf(Point &p1, Point &p2, double *rad1, double *rad2, + bool internal=false, int tagId=0); // derived constraints int addConstraintP2PCoincident(Point &p1, Point &p2, int tagId=0); @@ -115,8 +117,15 @@ namespace GCS int addConstraintPointOnArc(Point &p, Arc &a, int tagId=0); int addConstraintTangent(Line &l, Circle &c, int tagId=0); int addConstraintTangent(Line &l, Arc &a, int tagId=0); + int addConstraintTangent(Circle &c1, Circle &c2, int tagId=0); + int addConstraintTangent(Arc &a1, Arc &a2, int tagId=0); + int addConstraintTangent(Circle &c, Arc &a, int tagId=0); int addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId=0); int addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId=0); + int addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId=0); + int addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId=0); + int addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2, + int tagId=0); int addConstraintCircleRadius(Circle &c, double *radius, int tagId=0); int addConstraintArcRadius(Arc &a, double *radius, int tagId=0); int addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId=0); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 8699b4a1d3..7dc3273ab5 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -2153,24 +2153,31 @@ Restart: const Part::GeomCircle *circle1 = dynamic_cast(geo1); const Part::GeomCircle *circle2 = dynamic_cast(geo2); // tangency between two cicles + Base::Vector3d dir = (circle2->getCenter() - circle1->getCenter()).Normalize(); + pos = circle1->getCenter() + dir * circle1->getRadius(); + relPos = dir * 1; } else if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) { std::swap(geo1,geo2); } - if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId()) { + if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() && + geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomCircle *circle = dynamic_cast(geo1); - if (geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle *arc = dynamic_cast(geo2); - // tangency between a circle and an arc - } + const Part::GeomArcOfCircle *arc = dynamic_cast(geo2); + // tangency between a circle and an arc + Base::Vector3d dir = (arc->getCenter() - circle->getCenter()).Normalize(); + pos = circle->getCenter() + dir * circle->getRadius(); + relPos = dir * 1; } - - if (geo1->getTypeId()== Part::GeomArcOfCircle::getClassTypeId() && - geo1->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) { + else if (geo1->getTypeId()== Part::GeomArcOfCircle::getClassTypeId() && + geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomArcOfCircle *arc1 = dynamic_cast(geo1); const Part::GeomArcOfCircle *arc2 = dynamic_cast(geo2); // tangency between two arcs + Base::Vector3d dir = (arc2->getCenter() - arc1->getCenter()).Normalize(); + pos = arc1->getCenter() + dir * arc1->getRadius(); + relPos = dir * 1; } dynamic_cast(sep->getChild(1))->abPos = SbVec3f(pos.x, pos.y, zConstr); //Absolute Reference dynamic_cast(sep->getChild(1))->translation = SbVec3f(relPos.x, relPos.y, 0); From ac75725737856df7eac9013d773fdb4846cd1556 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 22 Mar 2012 11:27:09 -0300 Subject: [PATCH 034/351] The draft module can now work without GUI --- src/Mod/Draft/Draft.py | 322 +++++++++++++++++-------------- src/Mod/Draft/draftlibs/fcgeo.py | 14 +- 2 files changed, 191 insertions(+), 145 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index c015ccead5..e8f25025ab 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -72,12 +72,18 @@ How it works / how to extend: ''' # import FreeCAD modules - -import FreeCAD, FreeCADGui, math, sys, os, WorkingPlane +import FreeCAD, math, sys, os from FreeCAD import Vector from draftlibs import fcvec from pivy import coin +if FreeCAD.GuiUp: + import FreeCADGui, WorkingPlane + gui = True +else: + print "FreeCAD Gui not present. Draft module will have some features disabled." + gui = False + #--------------------------------------------------------------------------- # General functions #--------------------------------------------------------------------------- @@ -245,95 +251,104 @@ def formatObject(target,origin=None): It also places the object in construction group if needed. ''' obrep = target.ViewObject - ui = FreeCADGui.draftToolBar - doc = FreeCAD.ActiveDocument - if ui.isConstructionMode(): - col = fcol = ui.getDefaultColor("constr") - gname = getParam("constructiongroupname") - if not gname: - gname = "Construction" - grp = doc.getObject(gname) - if not grp: - grp = doc.addObject("App::DocumentObjectGroup",gname) - grp.addObject(target) - obrep.Transparency = 80 - else: - col = ui.getDefaultColor("ui") - fcol = ui.getDefaultColor("face") - col = (float(col[0]),float(col[1]),float(col[2]),0.0) - fcol = (float(fcol[0]),float(fcol[1]),float(fcol[2]),0.0) - lw = ui.linewidth - fs = ui.fontsize - if not origin: - if "FontSize" in obrep.PropertiesList: obrep.FontSize = fs - if "TextColor" in obrep.PropertiesList: obrep.TextColor = col - if "LineWidth" in obrep.PropertiesList: obrep.LineWidth = lw - if "PointColor" in obrep.PropertiesList: obrep.PointColor = col - if "LineColor" in obrep.PropertiesList: obrep.LineColor = col - if "ShapeColor" in obrep.PropertiesList: obrep.ShapeColor = fcol - else: - matchrep = origin.ViewObject - for p in matchrep.PropertiesList: - if not p in ["DisplayMode","BoundingBox","Proxy","RootNode"]: - if p in obrep.PropertiesList: - val = getattr(matchrep,p) - setattr(obrep,p,val) - if matchrep.DisplayMode in obrep.listDisplayModes(): - obrep.DisplayMode = matchrep.DisplayMode + ui = None + if gui: + if hasattr(FreeCADGui,"draftToolBar"): + ui = FreeCADGui.draftToolBar + if ui: + doc = FreeCAD.ActiveDocument + if ui.isConstructionMode(): + col = fcol = ui.getDefaultColor("constr") + gname = getParam("constructiongroupname") + if not gname: + gname = "Construction" + grp = doc.getObject(gname) + if not grp: + grp = doc.addObject("App::DocumentObjectGroup",gname) + grp.addObject(target) + obrep.Transparency = 80 + else: + col = ui.getDefaultColor("ui") + fcol = ui.getDefaultColor("face") + col = (float(col[0]),float(col[1]),float(col[2]),0.0) + fcol = (float(fcol[0]),float(fcol[1]),float(fcol[2]),0.0) + lw = ui.linewidth + fs = ui.fontsize + if not origin: + if "FontSize" in obrep.PropertiesList: obrep.FontSize = fs + if "TextColor" in obrep.PropertiesList: obrep.TextColor = col + if "LineWidth" in obrep.PropertiesList: obrep.LineWidth = lw + if "PointColor" in obrep.PropertiesList: obrep.PointColor = col + if "LineColor" in obrep.PropertiesList: obrep.LineColor = col + if "ShapeColor" in obrep.PropertiesList: obrep.ShapeColor = fcol + else: + matchrep = origin.ViewObject + for p in matchrep.PropertiesList: + if not p in ["DisplayMode","BoundingBox","Proxy","RootNode"]: + if p in obrep.PropertiesList: + val = getattr(matchrep,p) + setattr(obrep,p,val) + if matchrep.DisplayMode in obrep.listDisplayModes(): + obrep.DisplayMode = matchrep.DisplayMode def getSelection(): "getSelection(): returns the current FreeCAD selection" - return FreeCADGui.Selection.getSelection() + if gui: + return FreeCADGui.Selection.getSelection() + return None def select(objs=None): "select(object): deselects everything and selects only the passed object or list" - FreeCADGui.Selection.clearSelection() - if objs: - if not isinstance(objs,list): - objs = [objs] - for obj in objs: - FreeCADGui.Selection.addSelection(obj) + if gui: + FreeCADGui.Selection.clearSelection() + if objs: + if not isinstance(objs,list): + objs = [objs] + for obj in objs: + FreeCADGui.Selection.addSelection(obj) def loadTexture(filename): "loadTexture(filename): returns a SoSFImage from a file" - from pivy import coin - from PyQt4 import QtGui - try: - p = QtGui.QImage(filename) - size = coin.SbVec2s(p.width(), p.height()) - buffersize = p.numBytes() - numcomponents = int (buffersize / ( size[0] * size[1] )) + if gui: + from pivy import coin + from PyQt4 import QtGui + try: + p = QtGui.QImage(filename) + size = coin.SbVec2s(p.width(), p.height()) + buffersize = p.numBytes() + numcomponents = int (buffersize / ( size[0] * size[1] )) - img = coin.SoSFImage() - width = size[0] - height = size[1] - bytes = "" - - for y in range(height): - #line = width*numcomponents*(height-(y)); - for x in range(width): - rgb = p.pixel(x,y) - if numcomponents == 1: - bytes = bytes + chr(QtGui.qGray( rgb )) - elif numcomponents == 2: - bytes = bytes + chr(QtGui.qGray( rgb )) - bytes = bytes + chr(QtGui.qAlpha( rgb )) - elif numcomponents == 3: - bytes = bytes + chr(QtGui.qRed( rgb )) - bytes = bytes + chr(QtGui.qGreen( rgb )) - bytes = bytes + chr(QtGui.qBlue( rgb )) - elif numcomponents == 4: - bytes = bytes + chr(QtGui.qRed( rgb )) - bytes = bytes + chr(QtGui.qGreen( rgb )) - bytes = bytes + chr(QtGui.qBlue( rgb )) - bytes = bytes + chr(QtGui.qAlpha( rgb )) - #line += numcomponents + img = coin.SoSFImage() + width = size[0] + height = size[1] + bytes = "" + + for y in range(height): + #line = width*numcomponents*(height-(y)); + for x in range(width): + rgb = p.pixel(x,y) + if numcomponents == 1: + bytes = bytes + chr(QtGui.qGray( rgb )) + elif numcomponents == 2: + bytes = bytes + chr(QtGui.qGray( rgb )) + bytes = bytes + chr(QtGui.qAlpha( rgb )) + elif numcomponents == 3: + bytes = bytes + chr(QtGui.qRed( rgb )) + bytes = bytes + chr(QtGui.qGreen( rgb )) + bytes = bytes + chr(QtGui.qBlue( rgb )) + elif numcomponents == 4: + bytes = bytes + chr(QtGui.qRed( rgb )) + bytes = bytes + chr(QtGui.qGreen( rgb )) + bytes = bytes + chr(QtGui.qBlue( rgb )) + bytes = bytes + chr(QtGui.qAlpha( rgb )) + #line += numcomponents - img.setValue(size, numcomponents, bytes) - except: - return None - else: - return img + img.setValue(size, numcomponents, bytes) + except: + return None + else: + return img + return None def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None, support=None): '''makeCircle(radius,[placement,face,startangle,endangle]) @@ -347,7 +362,6 @@ def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None if placement: typecheck([(placement,FreeCAD.Placement)], "makeCircle") obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Circle") _Circle(obj) - _ViewProviderDraft(obj.ViewObject) if isinstance(radius,Part.Edge): edge = radius if isinstance(edge.Curve,Part.Circle): @@ -369,11 +383,13 @@ def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None if startangle == -0: startangle = 0 obj.FirstAngle = startangle obj.LastAngle = endangle - if not face: obj.ViewObject.DisplayMode = "Wireframe" obj.Support = support if placement: obj.Placement = placement - formatObject(obj) - select(obj) + if gui: + _ViewProviderDraft(obj.ViewObject) + if not face: obj.ViewObject.DisplayMode = "Wireframe" + formatObject(obj) + select(obj) FreeCAD.ActiveDocument.recompute() return obj @@ -385,14 +401,16 @@ def makeRectangle(length, height, placement=None, face=True, support=None): if placement: typecheck([(placement,FreeCAD.Placement)], "makeRectangle") obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Rectangle") _Rectangle(obj) - _ViewProviderRectangle(obj.ViewObject) + obj.Length = length obj.Height = height obj.Support = support - if not face: obj.ViewObject.DisplayMode = "Wireframe" if placement: obj.Placement = placement - formatObject(obj) - select(obj) + if gui: + _ViewProviderRectangle(obj.ViewObject) + if not face: obj.ViewObject.DisplayMode = "Wireframe" + formatObject(obj) + select(obj) FreeCAD.ActiveDocument.recompute() return obj @@ -411,7 +429,6 @@ def makeDimension(p1,p2,p3=None,p4=None): ''' obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Dimension") _Dimension(obj) - _ViewProviderDimension(obj.ViewObject) if isinstance(p1,Vector) and isinstance(p2,Vector): obj.Start = p1 obj.End = p2 @@ -433,8 +450,10 @@ def makeDimension(p1,p2,p3=None,p4=None): p3.multiply(0.5) p3 = p1.add(p3) obj.Dimline = p3 - formatObject(obj) - select(obj) + if gui: + _ViewProviderDimension(obj.ViewObject) + formatObject(obj) + select(obj) FreeCAD.ActiveDocument.recompute() return obj @@ -444,7 +463,6 @@ def makeAngularDimension(center,angles,p3): ''' obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Dimension") _AngularDimension(obj) - _ViewProviderAngularDimension(obj.ViewObject) obj.Center = center for a in range(len(angles)): if angles[a] > 2*math.pi: @@ -452,8 +470,10 @@ def makeAngularDimension(center,angles,p3): obj.FirstAngle = math.degrees(angles[1]) obj.LastAngle = math.degrees(angles[0]) obj.Dimline = p3 - formatObject(obj) - select(obj) + if gui: + _ViewProviderAngularDimension(obj.ViewObject) + formatObject(obj) + select(obj) FreeCAD.ActiveDocument.recompute() return obj @@ -481,14 +501,15 @@ def makeWire(pointslist,closed=False,placement=None,face=True,support=None): else: fname = "Wire" obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) _Wire(obj) - _ViewProviderWire(obj.ViewObject) obj.Points = pointslist obj.Closed = closed obj.Support = support - if not face: obj.ViewObject.DisplayMode = "Wireframe" if placement: obj.Placement = placement - formatObject(obj) - select(obj) + if gui: + _ViewProviderWire(obj.ViewObject) + if not face: obj.ViewObject.DisplayMode = "Wireframe" + formatObject(obj) + select(obj) FreeCAD.ActiveDocument.recompute() return obj @@ -502,18 +523,19 @@ def makePolygon(nfaces,radius=1,inscribed=True,placement=None,face=True,support= if nfaces < 3: return None obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Polygon") _Polygon(obj) - _ViewProviderDraft(obj.ViewObject) obj.FacesNumber = nfaces obj.Radius = radius if inscribed: obj.DrawMode = "inscribed" else: obj.DrawMode = "circumscribed" - if not face: obj.ViewObject.DisplayMode = "Wireframe" obj.Support = support if placement: obj.Placement = placement - formatObject(obj) - select(obj) + if gui: + _ViewProviderDraft(obj.ViewObject) + if not face: obj.ViewObject.DisplayMode = "Wireframe" + formatObject(obj) + select(obj) FreeCAD.ActiveDocument.recompute() return obj @@ -538,14 +560,15 @@ def makeBSpline(pointslist,closed=False,placement=None,face=True,support=None): else: fname = "BSpline" obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) _BSpline(obj) - _ViewProviderBSpline(obj.ViewObject) obj.Points = pointslist obj.Closed = closed obj.Support = support - if not face: obj.ViewObject.DisplayMode = "Wireframe" if placement: obj.Placement = placement - formatObject(obj) - select(obj) + if gui: + _ViewProviderBSpline(obj.ViewObject) + if not face: obj.ViewObject.DisplayMode = "Wireframe" + formatObject(obj) + select(obj) FreeCAD.ActiveDocument.recompute() return obj @@ -577,51 +600,62 @@ def makeCopy(obj,force=None,reparent=False): if (getType(obj) == "Rectangle") or (force == "Rectangle"): newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) _Rectangle(newobj) - _ViewProviderRectangle(newobj.ViewObject) + if gui: + _ViewProviderRectangle(newobj.ViewObject) elif (getType(obj) == "Dimension") or (force == "Dimension"): newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) _Dimension(newobj) - _ViewProviderDimension(newobj.ViewObject) + if gui: + _ViewProviderDimension(newobj.ViewObject) elif (getType(obj) == "Wire") or (force == "Wire"): newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) _Wire(newobj) - _ViewProviderWire(newobj.ViewObject) + if gui: + _ViewProviderWire(newobj.ViewObject) elif (getType(obj) == "Circle") or (force == "Circle"): newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) _Circle(newobj) - _ViewProviderDraft(newobj.ViewObject) + if gui: + _ViewProviderDraft(newobj.ViewObject) elif (getType(obj) == "Polygon") or (force == "Polygon"): newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) _Polygon(newobj) - _ViewProviderPolygon(newobj.ViewObject) + if gui: + _ViewProviderPolygon(newobj.ViewObject) elif (getType(obj) == "BSpline") or (force == "BSpline"): newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) _BSpline(newobj) - _ViewProviderBSpline(newobj.ViewObject) + if gui: + _ViewProviderBSpline(newobj.ViewObject) elif (getType(obj) == "Block") or (force == "BSpline"): newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) _Block(newobj) - _ViewProviderDraftPart(newobj.ViewObject) + if gui: + _ViewProviderDraftPart(newobj.ViewObject) elif (getType(obj) == "Structure") or (force == "Structure"): import ArchStructure newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) ArchStructure._Structure(newobj) - ArchStructure._ViewProviderStructure(newobj.ViewObject) + if gui: + ArchStructure._ViewProviderStructure(newobj.ViewObject) elif (getType(obj) == "Wall") or (force == "Wall"): import ArchWall newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) ArchWall._Wall(newobj) - ArchWall._ViewProviderWall(newobj.ViewObject) + if gui: + ArchWall._ViewProviderWall(newobj.ViewObject) elif (getType(obj) == "Window") or (force == "Window"): import ArchWindow newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) ArchWindow._Window(newobj) - Archwindow._ViewProviderWindow(newobj.ViewObject) + if gui: + Archwindow._ViewProviderWindow(newobj.ViewObject) elif (getType(obj) == "Cell") or (force == "Cell"): import ArchCell newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name)) ArchCell._Cell(newobj) - ArchCell._ViewProviderCell(newobj.ViewObject) + if gui: + ArchCell._ViewProviderCell(newobj.ViewObject) elif obj.isDerivedFrom("Part::Feature"): newobj = FreeCAD.ActiveDocument.addObject("Part::Feature",getRealName(obj.Name)) newobj.Shape = obj.Shape @@ -649,11 +683,12 @@ def makeBlock(objectslist): '''makeBlock(objectslist): Creates a Draft Block from the given objects''' obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Block") _Block(obj) - _ViewProviderDraftPart(obj.ViewObject) obj.Components = objectslist - for o in objectslist: - o.ViewObject.Visibility = False - select(obj) + if gui: + _ViewProviderDraftPart(obj.ViewObject) + for o in objectslist: + o.ViewObject.Visibility = False + select(obj) return obj def makeArray(baseobject,arg1,arg2,arg3,arg4=None): @@ -667,7 +702,6 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None): The result is a parametric Draft Array.''' obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Array") _Array(obj) - _ViewProviderDraftPart(obj.ViewObject) obj.Base = baseobject if arg4: obj.ArrayType = "ortho" @@ -679,9 +713,11 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None): obj.ArrayType = "polar" obj.Center = arg1 obj.Angle = arg2 - obj.NumberPolar = arg3 - baseobject.ViewObject.hide() - select(obj) + obj.NumberPolar = arg3 + if gui: + _ViewProviderDraftPart(obj.ViewObject) + baseobject.ViewObject.hide() + select(obj) return obj def extrude(obj,vector): @@ -705,14 +741,16 @@ def fuse(object1,object2): if fcgeo.isCoplanar(object1.Shape.fuse(object2.Shape).Faces): obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Fusion") _Wire(obj) - _ViewProviderWire(obj.ViewObject) + if gui: + _ViewProviderWire(obj.ViewObject) else: obj = FreeCAD.ActiveDocument.addObject("Part::Fuse","Fusion") obj.Base = object1 obj.Tool = object2 - object1.ViewObject.Visibility = False - object2.ViewObject.Visibility = False - formatObject(obj,object1) + if gui: + object1.ViewObject.Visibility = False + object2.ViewObject.Visibility = False + formatObject(obj,object1) FreeCAD.ActiveDocument.recompute() return obj @@ -756,7 +794,8 @@ def move(objectslist,vector,copy=False): if copy: newobj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",getRealName(obj.Name)) _Dimension(newobj) - _ViewProviderDimension(newobj.ViewObject) + if gui: + _ViewProviderDimension(newobj.ViewObject) else: newobj = obj newobj.Start = obj.Start.add(vector) @@ -922,7 +961,6 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy else: obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Scale") _Clone(obj) - _ViewProviderDraftPart(obj.ViewObject) obj.Objects = objectslist obj.Scale = delta corr = Vector(center.x,center.y,center.z) @@ -934,8 +972,10 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy if not copy: for o in objectslist: o.ViewObject.hide() - formatObject(obj,objectslist[-1]) - select(obj) + if gui: + _ViewProviderDraftPart(obj.ViewObject) + formatObject(obj,objectslist[-1]) + select(obj) return obj def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): @@ -1396,7 +1436,8 @@ def makeShape2DView(baseobj,projectionVector=None): ''' obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Shape2DView") _Shape2DView(obj) - _ViewProviderDraft(obj.ViewObject) + if gui: + _ViewProviderDraft(obj.ViewObject) obj.Base = baseobj if projectionVector: obj.Projection = projectionVector @@ -1517,17 +1558,18 @@ def makePoint(X=0, Y=0, Z=0,color=None,name = "Point", point_size= 5): p1.X = 1 #move it in x p1.ViewObject.PointColor =(0.0,0.0,1.0) #change the color-make sure values are floats ''' - if not color: - color = FreeCADGui.draftToolBar.getDefaultColor('ui') obj=FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) _Point(obj,X,Y,Z) - _ViewProviderPoint(obj.ViewObject) obj.X = X obj.Y = Y obj.Z = Z - obj.ViewObject.PointColor = (float(color[0]), float(color[1]), float(color[2])) - obj.ViewObject.PointSize = point_size - obj.ViewObject.Visibility = True + if gui: + _ViewProviderPoint(obj.ViewObject) + if not color: + color = FreeCADGui.draftToolBar.getDefaultColor('ui') + obj.ViewObject.PointColor = (float(color[0]), float(color[1]), float(color[2])) + obj.ViewObject.PointSize = point_size + obj.ViewObject.Visibility = True FreeCAD.ActiveDocument.recompute() return obj diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/draftlibs/fcgeo.py index 44690d49d1..9863a2b1a3 100755 --- a/src/Mod/Draft/draftlibs/fcgeo.py +++ b/src/Mod/Draft/draftlibs/fcgeo.py @@ -27,7 +27,7 @@ __url__ = ["http://free-cad.sourceforge.net"] "this file contains generic geometry functions for manipulating Part shapes" -import FreeCAD, Part, fcvec, math, cmath, FreeCADGui +import FreeCAD, Part, fcvec, math, cmath from FreeCAD import Vector NORM = Vector(0,0,1) # provisory normal direction for all geometry ops. @@ -364,12 +364,14 @@ def geom(edge): return Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius) else: ref = edge.Placement.multVec(Vector(1,0,0)) + ref = ref.sub(edge.Placement.Base) # we only want the orientation v1 = edge.Vertexes[0].Point v2 = edge.Vertexes[-1].Point c = edge.Curve.Center cu = Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius) - a1 = -fcvec.angle(v1.sub(c),ref) - a2 = -fcvec.angle(v2.sub(c),ref) + a1 = -fcvec.angle(v1.sub(c),ref,edge.Curve.Axis) + a2 = -fcvec.angle(v2.sub(c),ref,edge.Curve.Axis) + 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: @@ -701,8 +703,10 @@ def getNormal(shape): if 0.1 < abs(e1.getAngle(e2)) < 1.56: n = e1.cross(e2).normalize() break - vdir = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() - if n.getAngle(vdir) < 0.78: n = fcvec.neg(n) + if FreeCAD.GuiUp: + import FreeCADGui + vdir = FreeCADGui.ActiveDocument.ActiveView.getViewDirection() + if n.getAngle(vdir) < 0.78: n = fcvec.neg(n) return n def offsetWire(wire,dvec,bind=False,occ=False): From 70ca4b65d58444bd2912d9e1d42eeed336b6cf50 Mon Sep 17 00:00:00 2001 From: tanderson Date: Thu, 22 Mar 2012 14:35:02 -0400 Subject: [PATCH 035/351] refine shape, face union fix * fix for circular boundary of a planar face. --- src/Mod/Part/App/modelRefine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Part/App/modelRefine.cpp b/src/Mod/Part/App/modelRefine.cpp index 3fd6082a0c..1a68b8ffea 100644 --- a/src/Mod/Part/App/modelRefine.cpp +++ b/src/Mod/Part/App/modelRefine.cpp @@ -364,7 +364,7 @@ TopoDS_Face FaceTypedPlane::buildFace(const FaceVectorType &faces) const std::sort(wires.begin(), wires.end(), ModelRefine::WireSort()); - TopoDS_Face current = BRepLib_MakeFace(wires.at(0)); + TopoDS_Face current = BRepLib_MakeFace(wires.at(0), Standard_True); if (wires.size() > 1) { ShapeFix_Face faceFix(current); From 723d6cde00a866f220cd2e9b8c761720193a762c Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 22 Mar 2012 19:59:50 +0100 Subject: [PATCH 036/351] Fix build errors with Sketcher, Support of workbenches with delayed retrieval of class name --- src/Gui/Application.cpp | 7 +++++++ src/Mod/Sketcher/App/freegcs/Constraints.h | 2 +- src/Mod/Sketcher/App/freegcs/GCS.cpp | 12 ++++++------ src/Mod/Sketcher/App/freegcs/GCS.h | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 7b59be2d7f..deffe1024f 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -947,6 +947,13 @@ bool Application::activateWorkbench(const char* name) // import the matching module first Py::Callable activate(handler.getAttr(std::string("Initialize"))); activate.apply(args); + + // Dependent on the implementation of a workbench handler the type + // can be defined after the call of Initialize() + if (type.empty()) { + Py::String result(method.apply(args)); + type = result.as_std_string(); + } } // does the Python workbench handler have changed the workbench? diff --git a/src/Mod/Sketcher/App/freegcs/Constraints.h b/src/Mod/Sketcher/App/freegcs/Constraints.h index 6a9369ab2a..17abd3106e 100644 --- a/src/Mod/Sketcher/App/freegcs/Constraints.h +++ b/src/Mod/Sketcher/App/freegcs/Constraints.h @@ -276,7 +276,7 @@ namespace GCS bool internal; public: ConstraintTangentCircumf(Point &p1, Point &p2, - double *rad1, double *rad2, bool internal_=false); + double *rd1, double *rd2, bool internal_=false); virtual ConstraintType getTypeId(); virtual void rescale(double coef=1.); virtual double error(); diff --git a/src/Mod/Sketcher/App/freegcs/GCS.cpp b/src/Mod/Sketcher/App/freegcs/GCS.cpp index 2d7c0eba30..29705fde2f 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/freegcs/GCS.cpp @@ -407,9 +407,9 @@ int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId) double dx = *(a.start.x) - *(c.center.x); double dy = *(a.start.y) - *(c.center.y); if (dx * cos(*(a.startAngle)) + dy * sin(*(a.startAngle)) > 0) - addConstraintP2PAngle(c.center, a.start, a.startAngle, 0, tagId); + return addConstraintP2PAngle(c.center, a.start, a.startAngle, 0, tagId); else - addConstraintP2PAngle(c.center, a.start, a.startAngle, M_PI, tagId); + return addConstraintP2PAngle(c.center, a.start, a.startAngle, M_PI, tagId); } int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId) @@ -418,9 +418,9 @@ int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId) double dx = *(a.end.x) - *(c.center.x); double dy = *(a.end.y) - *(c.center.y); if (dx * cos(*(a.endAngle)) + dy * sin(*(a.endAngle)) > 0) - addConstraintP2PAngle(c.center, a.end, a.endAngle, 0, tagId); + return addConstraintP2PAngle(c.center, a.end, a.endAngle, 0, tagId); else - addConstraintP2PAngle(c.center, a.end, a.endAngle, M_PI, tagId); + return addConstraintP2PAngle(c.center, a.end, a.endAngle, M_PI, tagId); } int System::addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2, @@ -433,9 +433,9 @@ int System::addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool re double *angle1 = reverse1 ? a1.startAngle : a1.endAngle; double *angle2 = reverse2 ? a2.endAngle : a2.startAngle; if (cos(*angle1) * cos(*angle2) + sin(*angle1) * sin(*angle2) > 0) - addConstraintEqual(angle1, angle2, tagId); + return addConstraintEqual(angle1, angle2, tagId); else - addConstraintP2PAngle(p2, a2.center, angle1, 0, tagId); + return addConstraintP2PAngle(p2, a2.center, angle1, 0, tagId); } int System::addConstraintCircleRadius(Circle &c, double *radius, int tagId) diff --git a/src/Mod/Sketcher/App/freegcs/GCS.h b/src/Mod/Sketcher/App/freegcs/GCS.h index 3c85383486..9df5a01230 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.h +++ b/src/Mod/Sketcher/App/freegcs/GCS.h @@ -101,7 +101,7 @@ namespace GCS int addConstraintMidpointOnLine(Line &l1, Line &l2, int tagId=0); int addConstraintMidpointOnLine(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2, int tagId=0); - int addConstraintTangentCircumf(Point &p1, Point &p2, double *rad1, double *rad2, + int addConstraintTangentCircumf(Point &p1, Point &p2, double *rd1, double *rd2, bool internal=false, int tagId=0); // derived constraints From 9b6492f9d76910556d2e6171a9bb1ac7b250359f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 24 Mar 2012 00:49:12 -0300 Subject: [PATCH 037/351] Fixed bugs in Arch Window + now builds its shape more correctly + can be inserted in walls --- src/Mod/Arch/ArchWall.py | 31 ++++++++++++++++++++----------- src/Mod/Arch/ArchWindow.py | 9 +++++---- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index b1389556a7..5b12b796cd 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -339,17 +339,26 @@ class _Wall(ArchComponent.Component): base = base.oldFuse(app.Shape) app.ViewObject.hide() #to be removed for hole in obj.Subtractions: - cut = False - if hasattr(hole,"Proxy"): - if hasattr(hole.Proxy,"Subvolume"): - if hole.Proxy.Subvolume: - print "cutting subvolume",hole.Proxy.Subvolume - base = base.cut(hole.Proxy.Subvolume) - cut = True - if not cut: - if hasattr(obj,"Shape"): - base = base.cut(hole.Shape) - hole.ViewObject.hide() # to be removed + if Draft.getType(hole) == "Window": + # window + if hole.Base and obj.Width: + max_length = 0 + for w in hole.Base.Shape.Wires: + if w.BoundBox.DiagonalLength > max_length: + max_length = w.BoundBox.DiagonalLength + ext = w + f = Part.Face(ext) + l = obj.Width + n = f.normalAt(0,0) + v1 = fcvec.scaleTo(n,l) + f.translate(v1) + v2 = fcvec.neg(v1) + v2 = fcvec.scale(v1,-2) + f = f.extrude(v2) + base = base.cut(f) + elif hasattr(obj,"Shape"): + base = base.cut(hole.Shape) + hole.ViewObject.hide() # to be removed obj.Shape = base if not fcgeo.isNull(pl): obj.Placement = pl diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index f6f1303cb6..0e9202f847 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -121,15 +121,16 @@ class _Window(ArchComponent.Component): max_length = w.BoundBox.DiagonalLength ext = w wires.remove(ext) - for w in wires: - w.reverse() - wires.insert(0, ext) - shape = Part.Face(wires) + shape = Part.Face(ext) norm = shape.normalAt(0,0) thk = float(obj.WindowParts[(i*5)+3]) if thk: exv = fcvec.scaleTo(norm,thk) shape = shape.extrude(exv) + for w in wires: + f = Part.Face(w) + f = f.extrude(exv) + shape = shape.cut(f) if obj.WindowParts[(i*5)+4]: zof = float(obj.WindowParts[(i*5)+4]) if zof: From e102ab5eca794560bab9b080b8cf8ec3e163e55f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 24 Mar 2012 11:41:45 -0300 Subject: [PATCH 038/351] Using the Arch window tool when a window is selected now produces a clone --- src/Mod/Arch/ArchWindow.py | 4 ++++ src/Mod/Draft/Draft.py | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 0e9202f847..ce884801df 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -33,6 +33,10 @@ __url__ = "http://free-cad.sourceforge.net" def makeWindow(baseobj=None,name="Window"): '''makeWindow(obj,[name]): creates a window based on the given object''' + if baseobj: + if Draft.getType(baseobj) == "Window": + obj = Draft.clone(baseobj) + return obj obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) _Window(obj) _ViewProviderWindow(obj.ViewObject) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index e8f25025ab..37a7f31485 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1581,8 +1581,11 @@ def clone(obj,delta=None): if not isinstance(obj,list): obj = [obj] cl = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Clone") + cl.Label = "Clone of " + obj[0].Label _Clone(cl) - _ViewProviderDraftPart(cl.ViewObject) + if gui: + _ViewProviderDraftPart(cl.ViewObject) + formatObject(cl,obj[0]) cl.Objects = obj if delta: cl.Placement.move(delta) @@ -2813,3 +2816,6 @@ class _ViewProviderDraftPart(_ViewProviderDraft): def getIcon(self): return ":/icons/Tree_Part.svg" + def claimChildren(self): + return [] + From 0f6eca5ef8e7a3b428aae5f65eeb4bcc7f1cb31a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 24 Mar 2012 18:26:01 -0300 Subject: [PATCH 039/351] Bugfixes in Arch Windows --- src/Mod/Arch/ArchWall.py | 37 ++++++++++++++++++++++++------------- src/Mod/Draft/Draft.py | 9 +++++++++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 5b12b796cd..4799d4abcc 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -257,6 +257,25 @@ class _Wall(ArchComponent.Component): if prop in ["Base","Height","Width","Align","Additions","Subtractions"]: self.createGeometry(obj) + def getSubVolume(self,base,width,delta=None): + "returns a subvolume from a base object" + import Part + max_length = 0 + for w in base.Shape.Wires: + if w.BoundBox.DiagonalLength > max_length: + max_length = w.BoundBox.DiagonalLength + f = w + f = Part.Face(f) + n = f.normalAt(0,0) + v1 = fcvec.scaleTo(n,width) + f.translate(v1) + v2 = fcvec.neg(v1) + v2 = fcvec.scale(v1,-2) + f = f.extrude(v2) + if delta: + f.translate(delta) + return f + def createGeometry(self,obj): import Part @@ -342,20 +361,12 @@ class _Wall(ArchComponent.Component): if Draft.getType(hole) == "Window": # window if hole.Base and obj.Width: - max_length = 0 - for w in hole.Base.Shape.Wires: - if w.BoundBox.DiagonalLength > max_length: - max_length = w.BoundBox.DiagonalLength - ext = w - f = Part.Face(ext) - l = obj.Width - n = f.normalAt(0,0) - v1 = fcvec.scaleTo(n,l) - f.translate(v1) - v2 = fcvec.neg(v1) - v2 = fcvec.scale(v1,-2) - f = f.extrude(v2) + f = self.getSubVolume(hole.Base,obj.Width) base = base.cut(f) + elif Draft.isClone(hole,"Window"): + if hole.Objects[0].Base and obj.Width: + f = self.getSubVolume(hole.Objects[0].Base,obj.Width,hole.Placement.Base) + base = base.cut(f) elif hasattr(obj,"Shape"): base = base.cut(hole.Shape) hole.ViewObject.hide() # to be removed diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 37a7f31485..59c4e16d11 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -170,6 +170,15 @@ def getType(obj): return "Group" return "Unknown" +def isClone(obj,objtype): + """isClone(obj,objtype): returns True if the given object is + a clone of an object of the given type""" + if getType(obj) == "Clone": + if len(obj.Objects) == 1: + if getType(obj.Objects[0]) == objtype: + return True + return False + def getGroupNames(): "returns a list of existing groups in the document" glist = [] From 11c1efca7e06e3cb66044b21379dc4e901f9c80a Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 25 Mar 2012 11:44:57 +0200 Subject: [PATCH 040/351] Improve I/O of PLY mesh format --- src/Mod/Mesh/App/Core/MeshIO.cpp | 143 ++++++++++++++++++++++++-- src/Mod/Mesh/App/Core/MeshIO.h | 13 ++- src/Mod/Mesh/App/Mesh.cpp | 30 +++++- src/Mod/Mesh/App/Mesh.h | 10 +- src/Mod/Mesh/App/MeshFeaturePyImp.cpp | 40 +++++-- src/Mod/Mesh/App/MeshProperties.cpp | 107 ------------------- src/Mod/Mesh/App/MeshProperties.h | 20 ---- src/Mod/Mesh/App/MeshPyImp.cpp | 1 + src/Mod/Mesh/Gui/Makefile.am | 2 +- src/Mod/Mesh/Gui/ViewProvider.cpp | 97 +++++++++++++++-- src/Mod/Mesh/Gui/ViewProvider.h | 3 + 11 files changed, 308 insertions(+), 158 deletions(-) diff --git a/src/Mod/Mesh/App/Core/MeshIO.cpp b/src/Mod/Mesh/App/Core/MeshIO.cpp index 6c78277346..4003e019c0 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.cpp +++ b/src/Mod/Mesh/App/Core/MeshIO.cpp @@ -661,7 +661,8 @@ bool MeshInput::LoadPLY (std::istream &inp) return false; // wrong header std::string line, element; - bool xyz_float=false,xyz_double=false,rgb_value=false; + bool xyz_float=false,xyz_double=false; + MeshIO::Binding rgb_value = MeshIO::OVERALL; while (std::getline(inp, line)) { std::istringstream str(line); str.unsetf(std::ios_base::skipws); @@ -738,7 +739,11 @@ bool MeshInput::LoadPLY (std::istream &inp) xyz_double = true; } else if (name == "red") { - rgb_value = true; + rgb_value = MeshIO::PER_VERTEX; + if (_material) { + _material->binding = MeshIO::PER_VERTEX; + _material->diffuseColor.reserve(v_count); + } } } else if (element == "face") { @@ -753,9 +758,38 @@ bool MeshInput::LoadPLY (std::istream &inp) boost::regex rx_p("^([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$"); + boost::regex rx_c("^([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" + "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" + "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)" + "\\s+([0-9]{1,3})\\s+([0-9]{1,3})\\s+([0-9]{1,3})\\s*$"); boost::regex rx_f("^\\s*3\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*$"); boost::cmatch what; Base::Vector3f pt; + + if (rgb_value == MeshIO::PER_VERTEX) { + int r,g,b; + for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { + if (boost::regex_match(line.c_str(), what, rx_c)) { + pt.x = (float)std::atof(what[1].first); + pt.y = (float)std::atof(what[4].first); + pt.z = (float)std::atof(what[7].first); + meshPoints.push_back(pt); + if (_material) { + r = std::min(std::atoi(what[10].first),255); + g = std::min(std::atoi(what[11].first),255); + b = std::min(std::atoi(what[12].first),255); + float fr = (float)r/255.0f; + float fg = (float)g/255.0f; + float fb = (float)b/255.0f; + _material->diffuseColor.push_back(App::Color(fr, fg, fb)); + } + } + else { + return false; + } + } + } + else { for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) { if (boost::regex_match(line.c_str(), what, rx_p)) { pt.x = (float)std::atof(what[1].first); @@ -767,6 +801,7 @@ bool MeshInput::LoadPLY (std::istream &inp) return false; } } + } int f1, f2, f3; for (std::size_t i = 0; i < f_count && std::getline(inp, line); i++) { if (boost::regex_match(line.c_str(), what, rx_f)) { @@ -777,6 +812,7 @@ bool MeshInput::LoadPLY (std::istream &inp) } } } + // binary else { Base::InputStream is(inp); if (format == binary_little_endian) @@ -789,16 +825,31 @@ bool MeshInput::LoadPLY (std::istream &inp) for (std::size_t i = 0; i < v_count; i++) { is >> pt.x >> pt.y >> pt.z; meshPoints.push_back(pt); - if (rgb_value) + if (rgb_value == MeshIO::PER_VERTEX) { is >> r >> g >> b; + if (_material) { + float fr = (float)r/255.0f; + float fg = (float)g/255.0f; + float fb = (float)b/255.0f; + _material->diffuseColor.push_back(App::Color(fr, fg, fb)); + } + } } } else if (xyz_double) { Base::Vector3d pt; for (std::size_t i = 0; i < v_count; i++) { is >> pt.x >> pt.y >> pt.z; - is >> r >> g >> b; meshPoints.push_back(Base::Vector3f((float)pt.x,(float)pt.y,(float)pt.z)); + if (rgb_value == MeshIO::PER_VERTEX) { + is >> r >> g >> b; + if (_material) { + float fr = (float)r/255.0f; + float fg = (float)g/255.0f; + float fb = (float)b/255.0f; + _material->diffuseColor.push_back(App::Color(fr, fg, fb)); + } + } } } unsigned char n; @@ -1428,7 +1479,12 @@ bool MeshOutput::SaveAny(const char* FileName, MeshIO::Format format) const } else if (fileformat == MeshIO::PLY) { // write file - if (!SavePLY(str)) + if (!SaveBinaryPLY(str)) + throw Base::FileException("Export of PLY mesh failed",FileName); + } + else if (fileformat == MeshIO::APLY) { + // write file + if (!SaveAsciiPLY(str)) throw Base::FileException("Export of PLY mesh failed",FileName); } else if (fileformat == MeshIO::IV) { @@ -1646,7 +1702,7 @@ bool MeshOutput::SaveOFF (std::ostream &out) const return true; } -bool MeshOutput::SavePLY (std::ostream &out) const +bool MeshOutput::SaveBinaryPLY (std::ostream &out) const { const MeshPointArray& rPoints = _rclMesh.GetPoints(); const MeshFacetArray& rFacets = _rclMesh.GetFacets(); @@ -1706,6 +1762,81 @@ bool MeshOutput::SavePLY (std::ostream &out) const return true; } +bool MeshOutput::SaveAsciiPLY (std::ostream &out) const +{ + const MeshPointArray& rPoints = _rclMesh.GetPoints(); + const MeshFacetArray& rFacets = _rclMesh.GetFacets(); + std::size_t v_count = rPoints.size(); + std::size_t f_count = rFacets.size(); + if (!out || out.bad() == true) + return false; + + bool saveVertexColor = (_material && _material->binding == MeshIO::PER_VERTEX + && _material->diffuseColor.size() == rPoints.size()); + out << "ply" << std::endl + << "format ascii 1.0" << std::endl + << "comment Created by FreeCAD " << std::endl + << "element vertex " << v_count << std::endl + << "property float32 x" << std::endl + << "property float32 y" << std::endl + << "property float32 z" << std::endl; + if (saveVertexColor) { + out << "property uchar red" << std::endl + << "property uchar green" << std::endl + << "property uchar blue" << std::endl; + } + out << "element face " << f_count << std::endl + << "property list uchar int vertex_index" << std::endl + << "end_header" << std::endl; + + Base::Vector3f pt; + + out.precision(6); + out.setf(std::ios::fixed | std::ios::showpoint); + if (saveVertexColor) { + for (std::size_t i = 0; i < v_count; i++) { + const MeshPoint& p = rPoints[i]; + if (this->apply_transform) { + Base::Vector3f pt = this->_transform * p; + out << pt.x << " " << pt.y << " " << pt.z; + } + else { + out << p.x << " " << p.y << " " << p.z; + } + + const App::Color& c = _material->diffuseColor[i]; + int r = (int)(255.0f * c.r); + int g = (int)(255.0f * c.g); + int b = (int)(255.0f * c.b); + out << " " << r << " " << g << " " << b << std::endl; + } + } + else { + for (std::size_t i = 0; i < v_count; i++) { + const MeshPoint& p = rPoints[i]; + if (this->apply_transform) { + Base::Vector3f pt = this->_transform * p; + out << pt.x << " " << pt.y << " " << pt.z << std::endl; + } + else { + out << p.x << " " << p.y << " " << p.z << std::endl; + } + } + } + + unsigned int n = 3; + int f1, f2, f3; + for (std::size_t i = 0; i < f_count; i++) { + const MeshFacet& f = rFacets[i]; + f1 = (int)f._aulPoints[0]; + f2 = (int)f._aulPoints[1]; + f3 = (int)f._aulPoints[2]; + out << n << " " << f1 << " " << f2 << " " << f3 << std::endl; + } + + return true; +} + bool MeshOutput::SaveMeshNode (std::ostream &rstrOut) { const MeshPointArray& rPoints = _rclMesh.GetPoints(); diff --git a/src/Mod/Mesh/App/Core/MeshIO.h b/src/Mod/Mesh/App/Core/MeshIO.h index e45d9f64e4..b439f1bd2a 100644 --- a/src/Mod/Mesh/App/Core/MeshIO.h +++ b/src/Mod/Mesh/App/Core/MeshIO.h @@ -51,6 +51,7 @@ namespace MeshIO { WRZ, NAS, PLY, + APLY, PY }; enum Binding { @@ -74,7 +75,10 @@ struct MeshExport Material class MeshExport MeshInput { public: - MeshInput (MeshKernel &rclM): _rclMesh(rclM){}; + MeshInput (MeshKernel &rclM) + : _rclMesh(rclM), _material(0){} + MeshInput (MeshKernel &rclM, Material* m) + : _rclMesh(rclM), _material(m){} virtual ~MeshInput (void) { } /// Loads the file, decided by extension @@ -106,6 +110,7 @@ public: protected: MeshKernel &_rclMesh; /**< reference to mesh data structure */ + Material* _material; }; /** @@ -138,8 +143,10 @@ public: bool SaveOBJ (std::ostream &rstrOut) const; /** Saves the mesh object into an OFF file. */ bool SaveOFF (std::ostream &rstrOut) const; - /** Saves the mesh object into a PLY file. */ - bool SavePLY (std::ostream &rstrOut) const; + /** Saves the mesh object into a binary PLY file. */ + bool SaveBinaryPLY (std::ostream &rstrOut) const; + /** Saves the mesh object into an ASCII PLY file. */ + bool SaveAsciiPLY (std::ostream &rstrOut) const; /** Saves the mesh object into an XML file. */ void SaveXML (Base::Writer &writer) const; /** Saves a node to an OpenInventor file. */ diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index 47f7a57cf2..f7b133a113 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -311,10 +311,10 @@ void MeshObject::save(std::ostream& out) const _kernel.Write(out); } -bool MeshObject::load(const char* file) +bool MeshObject::load(const char* file, MeshCore::Material* mat) { MeshCore::MeshKernel kernel; - MeshCore::MeshInput aReader(kernel); + MeshCore::MeshInput aReader(kernel, mat); if (!aReader.LoadAny(file)) return false; @@ -631,6 +631,32 @@ void MeshObject::removeComponents(unsigned long count) deletedFacets(removeIndices); } +unsigned long MeshObject::getPointDegree(const std::vector& indices, + std::vector& point_degree) const +{ + const MeshCore::MeshFacetArray& faces = _kernel.GetFacets(); + std::vector pointDeg(_kernel.CountPoints()); + + for (MeshCore::MeshFacetArray::_TConstIterator it = faces.begin(); it != faces.end(); ++it) { + pointDeg[it->_aulPoints[0]]++; + pointDeg[it->_aulPoints[1]]++; + pointDeg[it->_aulPoints[2]]++; + } + + for (std::vector::const_iterator it = indices.begin(); it != indices.end(); ++it) { + const MeshCore::MeshFacet& face = faces[*it]; + pointDeg[face._aulPoints[0]]--; + pointDeg[face._aulPoints[1]]--; + pointDeg[face._aulPoints[2]]--; + } + + unsigned long countInvalids = std::count_if(pointDeg.begin(), pointDeg.end(), + std::bind2nd(std::equal_to(), 0)); + + point_degree = pointDeg; + return countInvalids; +} + void MeshObject::fillupHoles(unsigned long length, int level, MeshCore::AbstractPolygonTriangulator& cTria) { diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index aedc0defc0..de42bd381f 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -144,7 +144,7 @@ public: void save(const char* file,MeshCore::MeshIO::Format f=MeshCore::MeshIO::Undefined, const MeshCore::Material* mat = 0) const; void save(std::ostream&) const; - bool load(const char* file); + bool load(const char* file, MeshCore::Material* mat = 0); void load(std::istream&); //@} @@ -177,6 +177,14 @@ public: std::vector > getComponents() const; unsigned long countComponents() const; void removeComponents(unsigned long); + /** + * Checks for the given facet indices what will be the degree for each point + * when these facets are removed from the mesh kernel. + * The point degree information is stored in \a point_degree. The return value + * gices the number of points which will have a degree of zero. + */ + unsigned long getPointDegree(const std::vector& facets, + std::vector& point_degree) const; void fillupHoles(unsigned long, int, MeshCore::AbstractPolygonTriangulator&); void offset(float fSize); void offsetSpecial2(float fSize); diff --git a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp index fb0d60dacb..b99e5bee1e 100644 --- a/src/Mod/Mesh/App/MeshFeaturePyImp.cpp +++ b/src/Mod/Mesh/App/MeshFeaturePyImp.cpp @@ -77,7 +77,10 @@ PyObject* MeshFeaturePy::smooth(PyObject *args) return NULL; PY_TRY { - getFeaturePtr()->Mesh.smooth(iter, d_max); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->smooth(iter, d_max); + obj->Mesh.finishEditing(); } PY_CATCH; Py_Return; @@ -87,7 +90,10 @@ PyObject* MeshFeaturePy::removeNonManifolds(PyObject *args) { if (!PyArg_ParseTuple(args, "")) return NULL; - getFeaturePtr()->Mesh.removeNonManifolds(); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->removeNonManifolds(); + obj->Mesh.finishEditing(); Py_Return } @@ -97,7 +103,10 @@ PyObject* MeshFeaturePy::fixIndices(PyObject *args) return NULL; PY_TRY { - getFeaturePtr()->Mesh.validateIndices(); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->validateIndices(); + obj->Mesh.finishEditing(); } PY_CATCH; Py_Return; @@ -109,7 +118,10 @@ PyObject* MeshFeaturePy::fixDegenerations(PyObject *args) return NULL; PY_TRY { - getFeaturePtr()->Mesh.validateDegenerations(); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->validateDegenerations(); + obj->Mesh.finishEditing(); } PY_CATCH; Py_Return; @@ -121,7 +133,10 @@ PyObject* MeshFeaturePy::removeDuplicatedFacets(PyObject *args) return NULL; PY_TRY { - getFeaturePtr()->Mesh.removeDuplicatedFacets(); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->removeDuplicatedFacets(); + obj->Mesh.finishEditing(); } PY_CATCH; Py_Return; @@ -133,7 +148,10 @@ PyObject* MeshFeaturePy::removeDuplicatedPoints(PyObject *args) return NULL; PY_TRY { - getFeaturePtr()->Mesh.removeDuplicatedPoints(); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->removeDuplicatedPoints(); + obj->Mesh.finishEditing(); } PY_CATCH; Py_Return; @@ -144,7 +162,10 @@ PyObject* MeshFeaturePy::fixSelfIntersections(PyObject *args) if (!PyArg_ParseTuple(args, "")) return NULL; try { - getFeaturePtr()->Mesh.removeSelfIntersections(); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->removeSelfIntersections(); + obj->Mesh.finishEditing(); } catch (const Base::Exception& e) { PyErr_SetString(PyExc_Exception, e.what()); @@ -158,7 +179,10 @@ PyObject* MeshFeaturePy::removeFoldsOnSurface(PyObject *args) if (!PyArg_ParseTuple(args, "")) return NULL; try { - getFeaturePtr()->Mesh.removeFoldsOnSurface(); + Mesh::Feature* obj = getFeaturePtr(); + MeshObject* kernel = obj->Mesh.startEditing(); + kernel->removeFoldsOnSurface(); + obj->Mesh.finishEditing(); } catch (const Base::Exception& e) { PyErr_SetString(PyExc_Exception, e.what()); diff --git a/src/Mod/Mesh/App/MeshProperties.cpp b/src/Mod/Mesh/App/MeshProperties.cpp index 3c0b41190c..9e68cae10a 100644 --- a/src/Mod/Mesh/App/MeshProperties.cpp +++ b/src/Mod/Mesh/App/MeshProperties.cpp @@ -390,20 +390,6 @@ void PropertyMeshKernel::transformGeometry(const Base::Matrix4D &rclMat) hasSetValue(); } -void PropertyMeshKernel::deletePointIndices( const std::vector& inds ) -{ - aboutToSetValue(); - _meshObject->deletePoints(inds); - hasSetValue(); -} - -void PropertyMeshKernel::deleteFacetIndices( const std::vector& inds ) -{ - aboutToSetValue(); - _meshObject->deleteFacets(inds); - hasSetValue(); -} - void PropertyMeshKernel::setPointIndices(const std::vector >& inds) { aboutToSetValue(); @@ -413,99 +399,6 @@ void PropertyMeshKernel::setPointIndices(const std::vector& rFaces, - const std::vector& rPoints) -{ - aboutToSetValue(); - _meshObject->addFacets(rFaces, rPoints); - hasSetValue(); -} - -void PropertyMeshKernel::createSegment(const std::vector& segm) -{ - aboutToSetValue(); - _meshObject->addSegment(segm); - hasSetValue(); -} - -void PropertyMeshKernel::smooth(int iter, float d_max) -{ - aboutToSetValue(); - _meshObject->smooth(iter, d_max); - hasSetValue(); -} - -void PropertyMeshKernel::clear() -{ - // clear the underlying mesh kernel and free any allocated memory - aboutToSetValue(); - _meshObject->clear(); - hasSetValue(); -} - -void PropertyMeshKernel::harmonizeNormals() -{ - aboutToSetValue(); - _meshObject->harmonizeNormals(); - hasSetValue(); -} - -void PropertyMeshKernel::removeNonManifolds() -{ - aboutToSetValue(); - _meshObject->removeNonManifolds(); - hasSetValue(); -} - -void PropertyMeshKernel::validateIndices() -{ - aboutToSetValue(); - _meshObject->validateIndices(); - hasSetValue(); -} - -void PropertyMeshKernel::validateDegenerations() -{ - aboutToSetValue(); - _meshObject->validateDegenerations(); - hasSetValue(); -} - -void PropertyMeshKernel::validateDeformations(float fMaxAngle) -{ - aboutToSetValue(); - _meshObject->validateDeformations(fMaxAngle); - hasSetValue(); -} - -void PropertyMeshKernel::removeDuplicatedFacets() -{ - aboutToSetValue(); - _meshObject->removeDuplicatedFacets(); - hasSetValue(); -} - -void PropertyMeshKernel::removeDuplicatedPoints() -{ - aboutToSetValue(); - _meshObject->removeDuplicatedPoints(); - hasSetValue(); -} - -void PropertyMeshKernel::removeSelfIntersections() -{ - aboutToSetValue(); - _meshObject->removeSelfIntersections(); - hasSetValue(); -} - -void PropertyMeshKernel::removeFoldsOnSurface() -{ - aboutToSetValue(); - _meshObject->removeFoldsOnSurface(); - hasSetValue(); -} - PyObject *PropertyMeshKernel::getPyObject(void) { if (!meshPyObject) { diff --git a/src/Mod/Mesh/App/MeshProperties.h b/src/Mod/Mesh/App/MeshProperties.h index af1cd0f8b4..04bfb8dee9 100644 --- a/src/Mod/Mesh/App/MeshProperties.h +++ b/src/Mod/Mesh/App/MeshProperties.h @@ -179,27 +179,7 @@ public: void finishEditing(); /// Transform the real mesh data void transformGeometry(const Base::Matrix4D &rclMat); - void deletePointIndices ( const std::vector& ); - void deleteFacetIndices ( const std::vector& ); void setPointIndices( const std::vector >& ); - void append(const std::vector& rFaces, - const std::vector& rPoints); - void createSegment(const std::vector& segm); - void smooth(int iter, float d_max); - void clear(); - //@} - - /** @name Mesh validation */ - //@{ - void harmonizeNormals(); - void validateIndices(); - void validateDeformations(float fMaxAngle); - void validateDegenerations(); - void removeDuplicatedPoints(); - void removeDuplicatedFacets(); - void removeNonManifolds(); - void removeSelfIntersections(); - void removeFoldsOnSurface(); //@} /** @name Python interface */ diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index ace1032894..a25e3e2f6d 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -165,6 +165,7 @@ PyObject* MeshPy::write(PyObject *args) ext["NAS" ] = MeshCore::MeshIO::NAS; ext["BDF" ] = MeshCore::MeshIO::NAS; ext["PLY" ] = MeshCore::MeshIO::PLY; + ext["APLY"] = MeshCore::MeshIO::APLY; ext["PY" ] = MeshCore::MeshIO::PY; if (ext.find(Ext) != ext.end()) format = ext[Ext]; diff --git a/src/Mod/Mesh/Gui/Makefile.am b/src/Mod/Mesh/Gui/Makefile.am index 82cde54eec..7bc944804a 100644 --- a/src/Mod/Mesh/Gui/Makefile.am +++ b/src/Mod/Mesh/Gui/Makefile.am @@ -66,7 +66,7 @@ libMeshGui_la_CPPFLAGS = -DMeshExport= -DMeshGuiExport= libMeshGui_la_LIBADD = \ @BOOST_SIGNALS_LIB@ @BOOST_SYSTEM_LIB@ \ - @GL_LIBS@ \ + @GL_LIBS@ @ZIPIOS_LIB@ \ -lFreeCADBase \ -lFreeCADApp \ -lFreeCADGui \ diff --git a/src/Mod/Mesh/Gui/ViewProvider.cpp b/src/Mod/Mesh/Gui/ViewProvider.cpp index db7e99057c..d927661904 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.cpp +++ b/src/Mod/Mesh/Gui/ViewProvider.cpp @@ -27,6 +27,8 @@ # include # include # include +# include +# include # include # include # include @@ -44,6 +46,7 @@ # include # include # include +# include #endif /// Here the FreeCAD includes sorted by Base,App,Gui...... @@ -63,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +86,7 @@ #include #include #include +#include #include "ViewProvider.h" #include "SoFCIndexedFaceSet.h" @@ -484,6 +489,69 @@ std::vector ViewProviderMesh::getDisplayModes(void) const return StrList; } +bool ViewProviderMesh::exportToVrml(const char* filename, const MeshCore::Material& mat, bool binary) const +{ + SoCoordinate3* coords = new SoCoordinate3(); + SoIndexedFaceSet* faces = new SoIndexedFaceSet(); + ViewProviderMeshBuilder builder; + builder.createMesh(&static_cast(pcObject)->Mesh, coords, faces); + + SoMaterialBinding* binding = new SoMaterialBinding; + SoMaterial* material = new SoMaterial; + + if (mat.diffuseColor.size() == coords->point.getNum()) { + binding->value = SoMaterialBinding::PER_VERTEX_INDEXED; + } + else if (mat.diffuseColor.size() == faces->coordIndex.getNum()/4) { + binding->value = SoMaterialBinding::PER_FACE_INDEXED; + } + + if (mat.diffuseColor.size() > 1) { + material->diffuseColor.setNum(mat.diffuseColor.size()); + SbColor* colors = material->diffuseColor.startEditing(); + for (unsigned int i=0; idiffuseColor.finishEditing(); + } + + SoGroup* group = new SoGroup(); + group->addChild(material); + group->addChild(binding); + group->addChild(new SoTransform()); + group->addChild(coords); + group->addChild(faces); + + SoToVRML2Action tovrml2; + group->ref(); + tovrml2.apply(group); + group->unref(); + SoVRMLGroup *vrmlRoot = tovrml2.getVRML2SceneGraph(); + vrmlRoot->ref(); + std::string buffer = Gui::SoFCDB::writeNodesToString(vrmlRoot); + vrmlRoot->unref(); // release the memory as soon as possible + + Base::FileInfo fi(filename); + if (binary) { + Base::ofstream str(fi, std::ios::out | std::ios::binary); + zipios::GZIPOutputStream gzip(str); + if (gzip) { + gzip << buffer; + gzip.close(); + return true; + } + } + else { + Base::ofstream str(fi, std::ios::out); + if (str) { + str << buffer; + str.close(); + return true; + } + } + + return false; +} + bool ViewProviderMesh::setEdit(int ModNum) { if (ModNum == ViewProvider::Transform) @@ -1045,13 +1113,7 @@ void ViewProviderMesh::cutMesh(const std::vector& picked, // Get the facet indices inside the tool mesh std::vector indices; getFacetsFromPolygon(picked, Viewer, inner, indices); - - // Get the attached mesh property - Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; - - //Remove the facets from the mesh and open a transaction object for the undo/redo stuff - meshProp.deleteFacetIndices(indices); - pcObject->purgeTouched(); + removeFacets(indices); } void ViewProviderMesh::trimMesh(const std::vector& polygon, @@ -1137,7 +1199,7 @@ void ViewProviderMesh::splitMesh(const MeshCore::MeshKernel& toolMesh, const Bas // Remove the facets from the mesh and create a new one Mesh::MeshObject* kernel = meshProp.getValue().meshFromSegment(indices); - meshProp.deleteFacetIndices(indices); + removeFacets(indices); Mesh::Feature* splitMesh = static_cast(App::GetApplication().getActiveDocument() ->addObject("Mesh::Feature",pcObject->getNameInDocument())); // Note: deletes also kernel @@ -1167,7 +1229,9 @@ void ViewProviderMesh::segmentMesh(const MeshCore::MeshKernel& toolMesh, const B indices = complementary; } - meshProp.createSegment(indices); + Mesh::MeshObject* kernel = meshProp.startEditing(); + kernel->addSegment(indices); + meshProp.finishEditing(); static_cast(pcObject)->purgeTouched(); } @@ -1401,10 +1465,23 @@ void ViewProviderMesh::fillHole(unsigned long uFacet) //add the facets to the mesh and open a transaction object for the undo/redo stuff Gui::Application::Instance->activeDocument()->openCommand("Fill hole"); - fea->Mesh.append(newFacets, newPoints); + Mesh::MeshObject* kernel = fea->Mesh.startEditing(); + kernel->addFacets(newFacets, newPoints); + fea->Mesh.finishEditing(); Gui::Application::Instance->activeDocument()->commitCommand(); } +void ViewProviderMesh::removeFacets(const std::vector& facets) +{ + // Get the attached mesh property + Mesh::PropertyMeshKernel& meshProp = static_cast(pcObject)->Mesh; + Mesh::MeshObject* kernel = meshProp.startEditing(); + //Remove the facets from the mesh and open a transaction object for the undo/redo stuff + kernel->deleteFacets(facets); + meshProp.finishEditing(); + pcObject->purgeTouched(); +} + void ViewProviderMesh::selectFacet(unsigned long facet) { std::vector selection; diff --git a/src/Mod/Mesh/Gui/ViewProvider.h b/src/Mod/Mesh/Gui/ViewProvider.h index ce0de6b8c9..3bf180bdd5 100644 --- a/src/Mod/Mesh/Gui/ViewProvider.h +++ b/src/Mod/Mesh/Gui/ViewProvider.h @@ -60,6 +60,7 @@ namespace Gui { namespace MeshCore { class MeshKernel; + struct Material; } @@ -122,6 +123,7 @@ public: virtual void setDisplayMode(const char* ModeName); /// returns a list of all possible modes virtual std::vector getDisplayModes(void) const; + bool exportToVrml(const char* filename, const MeshCore::Material&, bool binary=false) const; /** @name Editing */ //@{ @@ -141,6 +143,7 @@ public: std::vector getFacetsOfRegion(const SbViewportRegion&, const SbViewportRegion&, SoCamera*) const; std::vector getVisibleFacetsAfterZoom(const SbBox2s&, const SbViewportRegion&, SoCamera*) const; std::vector getVisibleFacets(const SbViewportRegion&, SoCamera*) const; + virtual void removeFacets(const std::vector&); //@} protected: From 2e062ab79713607566248a1e480b8921d5a03b58 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 25 Mar 2012 13:38:32 +0200 Subject: [PATCH 041/351] 0000652: Polish language not available even if translation is available in source --- src/Gui/Language/Makefile.am | 2 ++ src/Gui/Language/Translator.cpp | 1 + src/Gui/Language/translation.qrc | 1 + src/Mod/Arch/Resources/Arch.qrc | 1 + src/Mod/Complete/Gui/Resources/Complete.qrc | 1 + src/Mod/Complete/Gui/Resources/Makefile.am | 2 ++ src/Mod/Draft/Makefile.am | 2 ++ src/Mod/Draft/Resources/Draft.qrc | 1 + src/Mod/Drawing/Gui/Resources/Drawing.qrc | 1 + src/Mod/Drawing/Gui/Resources/Makefile.am | 2 ++ src/Mod/Fem/Gui/Resources/Fem.qrc | 1 + src/Mod/Fem/Gui/Resources/Makefile.am | 2 ++ src/Mod/Image/Gui/Makefile.am | 2 ++ src/Mod/Image/Gui/Resources/Image.qrc | 1 + src/Mod/Mesh/Gui/Makefile.am | 2 ++ src/Mod/Mesh/Gui/Resources/Mesh.qrc | 1 + src/Mod/MeshPart/Gui/Resources/Makefile.am | 2 ++ src/Mod/MeshPart/Gui/Resources/MeshPart.qrc | 1 + src/Mod/Part/Gui/Makefile.am | 2 ++ src/Mod/Part/Gui/Resources/Part.qrc | 1 + src/Mod/PartDesign/Gui/Resources/Makefile.am | 2 ++ .../PartDesign/Gui/Resources/PartDesign.qrc | 1 + src/Mod/Points/Gui/Makefile.am | 2 ++ src/Mod/Points/Gui/Resources/Points.qrc | 1 + src/Mod/Raytracing/Gui/Makefile.am | 2 ++ .../Raytracing/Gui/Resources/Raytracing.qrc | 1 + .../Gui/Resources/Makefile.am | 2 ++ .../Gui/Resources/ReverseEngineering.qrc | 1 + src/Mod/Robot/Gui/Resources/Makefile.am | 2 ++ src/Mod/Robot/Gui/Resources/Robot.qrc | 1 + src/Mod/Sketcher/Gui/Resources/Makefile.am | 2 ++ src/Mod/Sketcher/Gui/Resources/Sketcher.qrc | 1 + src/Mod/Start/Gui/Resources/Start.qrc | 1 + src/Mod/Test/Gui/Makefile.am | 32 ++++++++++++++++--- src/Mod/Test/Gui/Resources/Test.qrc | 12 +++++++ 35 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/Gui/Language/Makefile.am b/src/Gui/Language/Makefile.am index aec3aeb8ad..a72ca473f0 100644 --- a/src/Gui/Language/Makefile.am +++ b/src/Gui/Language/Makefile.am @@ -23,6 +23,7 @@ EXTRA_DIST = \ FreeCAD_it.qm \ FreeCAD_nl.qm \ FreeCAD_no.qm \ + FreeCAD_pl.qm \ FreeCAD_pt.qm \ FreeCAD_ru.qm \ FreeCAD_se.qm \ @@ -37,6 +38,7 @@ EXTRA_DIST = \ FreeCAD_it.ts \ FreeCAD_nl.ts \ FreeCAD_no.ts \ + FreeCAD_pl.ts \ FreeCAD_pt.ts \ FreeCAD_ru.ts \ FreeCAD_se.ts \ diff --git a/src/Gui/Language/Translator.cpp b/src/Gui/Language/Translator.cpp index 9f322afd8b..b32401875f 100644 --- a/src/Gui/Language/Translator.cpp +++ b/src/Gui/Language/Translator.cpp @@ -146,6 +146,7 @@ Translator::Translator() d->mapLanguageTopLevelDomain[QT_TR_NOOP("Ukrainian" )] = "uk"; d->mapLanguageTopLevelDomain[QT_TR_NOOP("Finnish" )] = "fi"; d->mapLanguageTopLevelDomain[QT_TR_NOOP("Croatian" )] = "hr"; + d->mapLanguageTopLevelDomain[QT_TR_NOOP("Polish" )] = "pl"; d->activatedLanguage = "English"; d->paths = directories(); diff --git a/src/Gui/Language/translation.qrc b/src/Gui/Language/translation.qrc index 63d2e5d686..e2e81ad1e7 100644 --- a/src/Gui/Language/translation.qrc +++ b/src/Gui/Language/translation.qrc @@ -9,6 +9,7 @@ FreeCAD_it.qm FreeCAD_nl.qm FreeCAD_no.qm + FreeCAD_pl.qm FreeCAD_pt.qm FreeCAD_ru.qm FreeCAD_se.qm diff --git a/src/Mod/Arch/Resources/Arch.qrc b/src/Mod/Arch/Resources/Arch.qrc index ba886872b9..7d305d7104 100644 --- a/src/Mod/Arch/Resources/Arch.qrc +++ b/src/Mod/Arch/Resources/Arch.qrc @@ -36,6 +36,7 @@ translations/Arch_ru.qm translations/Arch_se.qm translations/Arch_uk.qm + translations/Arch_pl.qm translations/Arch_pt.qm translations/Arch_hr.qm translations/Arch_zh.qm diff --git a/src/Mod/Complete/Gui/Resources/Complete.qrc b/src/Mod/Complete/Gui/Resources/Complete.qrc index d7115bce7d..97769440c8 100644 --- a/src/Mod/Complete/Gui/Resources/Complete.qrc +++ b/src/Mod/Complete/Gui/Resources/Complete.qrc @@ -9,6 +9,7 @@ translations/Complete_it.qm translations/Complete_nl.qm translations/Complete_no.qm + translations/Complete_pl.qm translations/Complete_pt.qm translations/Complete_ru.qm translations/Complete_se.qm diff --git a/src/Mod/Complete/Gui/Resources/Makefile.am b/src/Mod/Complete/Gui/Resources/Makefile.am index c895368eed..6cfd345e7a 100644 --- a/src/Mod/Complete/Gui/Resources/Makefile.am +++ b/src/Mod/Complete/Gui/Resources/Makefile.am @@ -16,6 +16,7 @@ EXTRA_DIST = \ translations/Complete_it.qm \ translations/Complete_nl.qm \ translations/Complete_no.qm \ + translations/Complete_pl.qm \ translations/Complete_pt.qm \ translations/Complete_ru.qm \ translations/Complete_se.qm \ @@ -30,6 +31,7 @@ EXTRA_DIST = \ translations/Complete_it.ts \ translations/Complete_nl.ts \ translations/Complete_no.ts \ + translations/Complete_pl.ts \ translations/Complete_pt.ts \ translations/Complete_ru.ts \ translations/Complete_se.ts \ diff --git a/src/Mod/Draft/Makefile.am b/src/Mod/Draft/Makefile.am index 7cf2d42240..fef1303c4d 100644 --- a/src/Mod/Draft/Makefile.am +++ b/src/Mod/Draft/Makefile.am @@ -57,6 +57,8 @@ EXTRA_DIST = \ Resources/translations/Draft_nl.qm \ Resources/translations/Draft_no.ts \ Resources/translations/Draft_no.qm \ + Resources/translations/Draft_pl.ts \ + Resources/translations/Draft_pl.qm \ Resources/translations/Draft_pt.ts \ Resources/translations/Draft_pt.qm \ Resources/translations/Draft_ru.ts \ diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc index 1d9788ccee..5dfc9edfde 100644 --- a/src/Mod/Draft/Resources/Draft.qrc +++ b/src/Mod/Draft/Resources/Draft.qrc @@ -68,6 +68,7 @@ translations/Draft_ru.qm translations/Draft_se.qm translations/Draft_uk.qm + translations/Draft_pl.qm translations/Draft_pt.qm translations/Draft_hr.qm translations/Draft_zh.qm diff --git a/src/Mod/Drawing/Gui/Resources/Drawing.qrc b/src/Mod/Drawing/Gui/Resources/Drawing.qrc index 853d6aa5e5..5d5d80ca37 100644 --- a/src/Mod/Drawing/Gui/Resources/Drawing.qrc +++ b/src/Mod/Drawing/Gui/Resources/Drawing.qrc @@ -25,6 +25,7 @@ translations/Drawing_it.qm translations/Drawing_nl.qm translations/Drawing_no.qm + translations/Drawing_pl.qm translations/Drawing_pt.qm translations/Drawing_ru.qm translations/Drawing_se.qm diff --git a/src/Mod/Drawing/Gui/Resources/Makefile.am b/src/Mod/Drawing/Gui/Resources/Makefile.am index dbca09f2ec..a6063f8eab 100644 --- a/src/Mod/Drawing/Gui/Resources/Makefile.am +++ b/src/Mod/Drawing/Gui/Resources/Makefile.am @@ -32,6 +32,7 @@ EXTRA_DIST = \ translations/Drawing_it.qm \ translations/Drawing_nl.qm \ translations/Drawing_no.qm \ + translations/Drawing_pl.qm \ translations/Drawing_pt.qm \ translations/Drawing_ru.qm \ translations/Drawing_se.qm \ @@ -46,6 +47,7 @@ EXTRA_DIST = \ translations/Drawing_it.ts \ translations/Drawing_nl.ts \ translations/Drawing_no.ts \ + translations/Drawing_pl.ts \ translations/Drawing_pt.ts \ translations/Drawing_ru.ts \ translations/Drawing_se.ts \ diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index 660112d807..db072a5bfd 100644 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -10,6 +10,7 @@ translations/Fem_it.qm translations/Fem_nl.qm translations/Fem_no.qm + translations/Fem_pl.qm translations/Fem_pt.qm translations/Fem_ru.qm translations/Fem_se.qm diff --git a/src/Mod/Fem/Gui/Resources/Makefile.am b/src/Mod/Fem/Gui/Resources/Makefile.am index f915bc77ed..742affb819 100644 --- a/src/Mod/Fem/Gui/Resources/Makefile.am +++ b/src/Mod/Fem/Gui/Resources/Makefile.am @@ -26,6 +26,8 @@ EXTRA_DIST = \ translations/Fem_nl.ts \ translations/Fem_no.qm \ translations/Fem_no.ts \ + translations/Fem_pl.qm \ + translations/Fem_pl.ts \ translations/Fem_pt.qm \ translations/Fem_pt.ts \ translations/Fem_ru.qm \ diff --git a/src/Mod/Image/Gui/Makefile.am b/src/Mod/Image/Gui/Makefile.am index 0d09c514a3..b24c50a5c6 100644 --- a/src/Mod/Image/Gui/Makefile.am +++ b/src/Mod/Image/Gui/Makefile.am @@ -107,6 +107,8 @@ EXTRA_DIST = \ Resources/translations/Image_nl.ts \ Resources/translations/Image_no.qm \ Resources/translations/Image_no.ts \ + Resources/translations/Image_pl.qm \ + Resources/translations/Image_pl.ts \ Resources/translations/Image_pt.qm \ Resources/translations/Image_pt.ts \ Resources/translations/Image_ru.qm \ diff --git a/src/Mod/Image/Gui/Resources/Image.qrc b/src/Mod/Image/Gui/Resources/Image.qrc index fd16dcdfab..41122d6b2a 100644 --- a/src/Mod/Image/Gui/Resources/Image.qrc +++ b/src/Mod/Image/Gui/Resources/Image.qrc @@ -10,6 +10,7 @@ translations/Image_it.qm translations/Image_nl.qm translations/Image_no.qm + translations/Image_pl.qm translations/Image_pt.qm translations/Image_ru.qm translations/Image_se.qm diff --git a/src/Mod/Mesh/Gui/Makefile.am b/src/Mod/Mesh/Gui/Makefile.am index 7bc944804a..6b2066ff0e 100644 --- a/src/Mod/Mesh/Gui/Makefile.am +++ b/src/Mod/Mesh/Gui/Makefile.am @@ -146,6 +146,8 @@ EXTRA_DIST = \ Resources/translations/Mesh_nl.ts \ Resources/translations/Mesh_no.qm \ Resources/translations/Mesh_no.ts \ + Resources/translations/Mesh_pl.qm \ + Resources/translations/Mesh_pl.ts \ Resources/translations/Mesh_pt.qm \ Resources/translations/Mesh_pt.ts \ Resources/translations/Mesh_ru.qm \ diff --git a/src/Mod/Mesh/Gui/Resources/Mesh.qrc b/src/Mod/Mesh/Gui/Resources/Mesh.qrc index 347f3b8aa2..940c6d4401 100644 --- a/src/Mod/Mesh/Gui/Resources/Mesh.qrc +++ b/src/Mod/Mesh/Gui/Resources/Mesh.qrc @@ -12,6 +12,7 @@ translations/Mesh_it.qm translations/Mesh_nl.qm translations/Mesh_no.qm + translations/Mesh_pl.qm translations/Mesh_pt.qm translations/Mesh_ru.qm translations/Mesh_se.qm diff --git a/src/Mod/MeshPart/Gui/Resources/Makefile.am b/src/Mod/MeshPart/Gui/Resources/Makefile.am index cbc6560bb0..15086a83a7 100644 --- a/src/Mod/MeshPart/Gui/Resources/Makefile.am +++ b/src/Mod/MeshPart/Gui/Resources/Makefile.am @@ -26,6 +26,8 @@ EXTRA_DIST = \ translations/MeshPart_nl.ts \ translations/MeshPart_no.qm \ translations/MeshPart_no.ts \ + translations/MeshPart_pl.qm \ + translations/MeshPart_pl.ts \ translations/MeshPart_pt.qm \ translations/MeshPart_pt.ts \ translations/MeshPart_ru.qm \ diff --git a/src/Mod/MeshPart/Gui/Resources/MeshPart.qrc b/src/Mod/MeshPart/Gui/Resources/MeshPart.qrc index 486d2d5bed..2975b17301 100644 --- a/src/Mod/MeshPart/Gui/Resources/MeshPart.qrc +++ b/src/Mod/MeshPart/Gui/Resources/MeshPart.qrc @@ -10,6 +10,7 @@ translations/MeshPart_it.qm translations/MeshPart_nl.qm translations/MeshPart_no.qm + translations/MeshPart_pl.qm translations/MeshPart_pt.qm translations/MeshPart_ru.qm translations/MeshPart_se.qm diff --git a/src/Mod/Part/Gui/Makefile.am b/src/Mod/Part/Gui/Makefile.am index fe7d7a8ddb..ca433d86f5 100644 --- a/src/Mod/Part/Gui/Makefile.am +++ b/src/Mod/Part/Gui/Makefile.am @@ -247,6 +247,8 @@ EXTRA_DIST = \ Resources/translations/Part_nl.ts \ Resources/translations/Part_no.qm \ Resources/translations/Part_no.ts \ + Resources/translations/Part_pl.qm \ + Resources/translations/Part_pl.ts \ Resources/translations/Part_pt.qm \ Resources/translations/Part_pt.ts \ Resources/translations/Part_ru.qm \ diff --git a/src/Mod/Part/Gui/Resources/Part.qrc b/src/Mod/Part/Gui/Resources/Part.qrc index 213e2c47a9..82c60f77a2 100644 --- a/src/Mod/Part/Gui/Resources/Part.qrc +++ b/src/Mod/Part/Gui/Resources/Part.qrc @@ -36,6 +36,7 @@ translations/Part_it.qm translations/Part_nl.qm translations/Part_no.qm + translations/Part_pl.qm translations/Part_pt.qm translations/Part_ru.qm translations/Part_se.qm diff --git a/src/Mod/PartDesign/Gui/Resources/Makefile.am b/src/Mod/PartDesign/Gui/Resources/Makefile.am index ab021d8df3..3320073356 100644 --- a/src/Mod/PartDesign/Gui/Resources/Makefile.am +++ b/src/Mod/PartDesign/Gui/Resources/Makefile.am @@ -25,6 +25,8 @@ EXTRA_DIST = \ translations/PartDesign_nl.ts \ translations/PartDesign_no.qm \ translations/PartDesign_no.ts \ + translations/PartDesign_pl.qm \ + translations/PartDesign_pl.ts \ translations/PartDesign_pt.qm \ translations/PartDesign_pt.ts \ translations/PartDesign_ru.qm \ diff --git a/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc b/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc index 457ff17198..caff25cabd 100644 --- a/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc +++ b/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc @@ -12,6 +12,7 @@ translations/PartDesign_it.qm translations/PartDesign_nl.qm translations/PartDesign_no.qm + translations/PartDesign_pl.qm translations/PartDesign_pt.qm translations/PartDesign_ru.qm translations/PartDesign_se.qm diff --git a/src/Mod/Points/Gui/Makefile.am b/src/Mod/Points/Gui/Makefile.am index bf7db853dc..240f526796 100644 --- a/src/Mod/Points/Gui/Makefile.am +++ b/src/Mod/Points/Gui/Makefile.am @@ -100,6 +100,8 @@ EXTRA_DIST = \ Resources/translations/Points_nl.ts \ Resources/translations/Points_no.qm \ Resources/translations/Points_no.ts \ + Resources/translations/Points_pl.qm \ + Resources/translations/Points_pl.ts \ Resources/translations/Points_pt.qm \ Resources/translations/Points_pt.ts \ Resources/translations/Points_ru.qm \ diff --git a/src/Mod/Points/Gui/Resources/Points.qrc b/src/Mod/Points/Gui/Resources/Points.qrc index f581657337..b69922e70d 100644 --- a/src/Mod/Points/Gui/Resources/Points.qrc +++ b/src/Mod/Points/Gui/Resources/Points.qrc @@ -9,6 +9,7 @@ translations/Points_it.qm translations/Points_nl.qm translations/Points_no.qm + translations/Points_pl.qm translations/Points_pt.qm translations/Points_ru.qm translations/Points_se.qm diff --git a/src/Mod/Raytracing/Gui/Makefile.am b/src/Mod/Raytracing/Gui/Makefile.am index e6de6088f4..b83c798555 100644 --- a/src/Mod/Raytracing/Gui/Makefile.am +++ b/src/Mod/Raytracing/Gui/Makefile.am @@ -118,6 +118,8 @@ EXTRA_DIST = \ Resources/translations/Raytracing_nl.ts \ Resources/translations/Raytracing_no.qm \ Resources/translations/Raytracing_no.ts \ + Resources/translations/Raytracing_pl.qm \ + Resources/translations/Raytracing_pl.ts \ Resources/translations/Raytracing_pt.qm \ Resources/translations/Raytracing_pt.ts \ Resources/translations/Raytracing_ru.qm \ diff --git a/src/Mod/Raytracing/Gui/Resources/Raytracing.qrc b/src/Mod/Raytracing/Gui/Resources/Raytracing.qrc index a7420fd6c0..69d1523663 100644 --- a/src/Mod/Raytracing/Gui/Resources/Raytracing.qrc +++ b/src/Mod/Raytracing/Gui/Resources/Raytracing.qrc @@ -16,6 +16,7 @@ translations/Raytracing_it.qm translations/Raytracing_nl.qm translations/Raytracing_no.qm + translations/Raytracing_pl.qm translations/Raytracing_pt.qm translations/Raytracing_ru.qm translations/Raytracing_se.qm diff --git a/src/Mod/ReverseEngineering/Gui/Resources/Makefile.am b/src/Mod/ReverseEngineering/Gui/Resources/Makefile.am index 24b8a7852a..a22aca9c0a 100644 --- a/src/Mod/ReverseEngineering/Gui/Resources/Makefile.am +++ b/src/Mod/ReverseEngineering/Gui/Resources/Makefile.am @@ -26,6 +26,8 @@ EXTRA_DIST = \ translations/ReverseEngineering_nl.ts \ translations/ReverseEngineering_no.qm \ translations/ReverseEngineering_no.ts \ + translations/ReverseEngineering_pl.qm \ + translations/ReverseEngineering_pl.ts \ translations/ReverseEngineering_pt.qm \ translations/ReverseEngineering_pt.ts \ translations/ReverseEngineering_ru.qm \ diff --git a/src/Mod/ReverseEngineering/Gui/Resources/ReverseEngineering.qrc b/src/Mod/ReverseEngineering/Gui/Resources/ReverseEngineering.qrc index 93af7ddc1d..5063d5c727 100644 --- a/src/Mod/ReverseEngineering/Gui/Resources/ReverseEngineering.qrc +++ b/src/Mod/ReverseEngineering/Gui/Resources/ReverseEngineering.qrc @@ -10,6 +10,7 @@ translations/ReverseEngineering_it.qm translations/ReverseEngineering_nl.qm translations/ReverseEngineering_no.qm + translations/ReverseEngineering_pl.qm translations/ReverseEngineering_pt.qm translations/ReverseEngineering_ru.qm translations/ReverseEngineering_se.qm diff --git a/src/Mod/Robot/Gui/Resources/Makefile.am b/src/Mod/Robot/Gui/Resources/Makefile.am index 14c5cfa1cf..8b536ce973 100644 --- a/src/Mod/Robot/Gui/Resources/Makefile.am +++ b/src/Mod/Robot/Gui/Resources/Makefile.am @@ -38,6 +38,8 @@ EXTRA_DIST = \ translations/Robot_nl.ts \ translations/Robot_no.qm \ translations/Robot_no.ts \ + translations/Robot_pl.qm \ + translations/Robot_pl.ts \ translations/Robot_pt.qm \ translations/Robot_pt.ts \ translations/Robot_ru.qm \ diff --git a/src/Mod/Robot/Gui/Resources/Robot.qrc b/src/Mod/Robot/Gui/Resources/Robot.qrc index 97016da491..e7842fc4fa 100644 --- a/src/Mod/Robot/Gui/Resources/Robot.qrc +++ b/src/Mod/Robot/Gui/Resources/Robot.qrc @@ -22,6 +22,7 @@ translations/Robot_it.qm translations/Robot_nl.qm translations/Robot_no.qm + translations/Robot_pl.qm translations/Robot_pt.qm translations/Robot_ru.qm translations/Robot_se.qm diff --git a/src/Mod/Sketcher/Gui/Resources/Makefile.am b/src/Mod/Sketcher/Gui/Resources/Makefile.am index 9f2fcbe477..1209d54ef4 100644 --- a/src/Mod/Sketcher/Gui/Resources/Makefile.am +++ b/src/Mod/Sketcher/Gui/Resources/Makefile.am @@ -92,6 +92,8 @@ icons/Constraint_PointOnObject.svg \ translations/Sketcher_nl.ts \ translations/Sketcher_no.qm \ translations/Sketcher_no.ts \ + translations/Sketcher_pl.qm \ + translations/Sketcher_pl.ts \ translations/Sketcher_pt.qm \ translations/Sketcher_pt.ts \ translations/Sketcher_ru.qm \ diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index 8a3fe93244..bdc5ad8050 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -74,6 +74,7 @@ translations/Sketcher_it.qm translations/Sketcher_nl.qm translations/Sketcher_no.qm + translations/Sketcher_pl.qm translations/Sketcher_pt.qm translations/Sketcher_ru.qm translations/Sketcher_se.qm diff --git a/src/Mod/Start/Gui/Resources/Start.qrc b/src/Mod/Start/Gui/Resources/Start.qrc index c709e8da31..925ecd7f91 100644 --- a/src/Mod/Start/Gui/Resources/Start.qrc +++ b/src/Mod/Start/Gui/Resources/Start.qrc @@ -11,6 +11,7 @@ translations/StartPage_ru.qm translations/StartPage_se.qm translations/StartPage_uk.qm + translations/StartPage_pl.qm translations/StartPage_pt.qm translations/StartPage_hr.qm translations/StartPage_zh.qm diff --git a/src/Mod/Test/Gui/Makefile.am b/src/Mod/Test/Gui/Makefile.am index 8a3ead943e..35ce4cd52d 100644 --- a/src/Mod/Test/Gui/Makefile.am +++ b/src/Mod/Test/Gui/Makefile.am @@ -77,14 +77,38 @@ EXTRA_DIST = \ CMakeLists.txt \ UnitTest.ui \ Resources/Test.qrc \ + Resources/translations/Test_af.qm \ + Resources/translations/Test_af.ts \ Resources/translations/Test_de.qm \ - Resources/translations/Test_es.qm \ - Resources/translations/Test_fr.qm \ - Resources/translations/Test_it.qm \ - Resources/translations/Test_se.qm \ Resources/translations/Test_de.ts \ + Resources/translations/Test_es.qm \ Resources/translations/Test_es.ts \ + Resources/translations/Test_fi.qm \ + Resources/translations/Test_fi.ts \ + Resources/translations/Test_fr.qm \ Resources/translations/Test_fr.ts \ + Resources/translations/Test_hr.qm \ + Resources/translations/Test_hr.ts \ + Resources/translations/Test_hu.qm \ + Resources/translations/Test_hu.ts \ + Resources/translations/Test_it.qm \ Resources/translations/Test_it.ts \ + Resources/translations/Test_ja.qm \ + Resources/translations/Test_ja.ts \ + Resources/translations/Test_nl.qm \ + Resources/translations/Test_nl.ts \ + Resources/translations/Test_no.qm \ + Resources/translations/Test_no.ts \ + Resources/translations/Test_pl.qm \ + Resources/translations/Test_pl.ts \ + Resources/translations/Test_pt.qm \ + Resources/translations/Test_pt.ts \ + Resources/translations/Test_ru.qm \ + Resources/translations/Test_ru.ts \ + Resources/translations/Test_se.qm \ Resources/translations/Test_se.ts \ + Resources/translations/Test_uk.qm \ + Resources/translations/Test_uk.ts \ + Resources/translations/Test_zh.qm \ + Resources/translations/Test_zh.ts \ qtunittest.py diff --git a/src/Mod/Test/Gui/Resources/Test.qrc b/src/Mod/Test/Gui/Resources/Test.qrc index ef40be4f04..a494fcc5bc 100644 --- a/src/Mod/Test/Gui/Resources/Test.qrc +++ b/src/Mod/Test/Gui/Resources/Test.qrc @@ -1,9 +1,21 @@ + translations/Test_af.qm translations/Test_de.qm translations/Test_es.qm + translations/Test_fi.qm translations/Test_fr.qm + translations/Test_hr.qm + translations/Test_hu.qm translations/Test_it.qm + translations/Test_ja.qm + translations/Test_nl.qm + translations/Test_no.qm + translations/Test_pl.qm + translations/Test_pt.qm + translations/Test_ru.qm translations/Test_se.qm + translations/Test_uk.qm + translations/Test_zh.qm From 0f6d6d4b3735573e4a14df5d40b48c7314ca2f26 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 26 Mar 2012 15:54:13 +0200 Subject: [PATCH 042/351] Implement manual alignment utility --- src/Gui/Application.cpp | 1 + src/Gui/CMakeLists.txt | 7 +- src/Gui/CommandDoc.cpp | 60 ++ src/Gui/ManualAlignment.cpp | 1244 ++++++++++++++++++++++++++++ src/Gui/ManualAlignment.h | 257 ++++++ src/Gui/SoAxisCrossKit.cpp | 146 +++- src/Gui/SoAxisCrossKit.h | 29 + src/Gui/SoFCDB.cpp | 1 + src/Gui/SplitView3DInventor.cpp | 102 ++- src/Gui/SplitView3DInventor.h | 23 +- src/Gui/Workbench.cpp | 3 +- src/Mod/Complete/Gui/Workbench.cpp | 3 +- 12 files changed, 1822 insertions(+), 54 deletions(-) create mode 100644 src/Gui/ManualAlignment.cpp create mode 100644 src/Gui/ManualAlignment.h diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index deffe1024f..2dbc4b2c8c 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -1407,6 +1407,7 @@ void Application::initTypes(void) Gui::BaseView ::init(); Gui::MDIView ::init(); Gui::View3DInventor ::init(); + Gui::AbstractSplitView ::init(); Gui::SplitView3DInventor ::init(); // View Provider Gui::ViewProvider ::init(); diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 133d81a540..b7788cfcd7 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -125,6 +125,7 @@ set(Gui_MOC_HDRS HelpView.h InputVector.h MainWindow.h + ManualAlignment.h MDIView.h NetworkRetriever.h OnlineDocumentation.h @@ -627,7 +628,7 @@ SET(Inventor_CPP_SRCS SoFCInteractiveElement.cpp SoFCOffscreenRenderer.cpp SoFCSelection.cpp - SoFCUnifiedSelection.cpp + SoFCUnifiedSelection.cpp SoFCSelectionAction.cpp SoFCVectorizeSVGAction.cpp SoFCVectorizeU3DAction.cpp @@ -647,7 +648,7 @@ SET(Inventor_SRCS SoFCInteractiveElement.h SoFCOffscreenRenderer.h SoFCSelection.h - SoFCUnifiedSelection.h + SoFCUnifiedSelection.h SoFCSelectionAction.h SoFCVectorizeSVGAction.h SoFCVectorizeU3DAction.h @@ -743,6 +744,7 @@ SET(FreeCADGui_CPP_SRCS Thumbnail.cpp Utilities.cpp WaitCursor.cpp + ManualAlignment.cpp ) SET(FreeCADGui_SRCS Application.h @@ -763,6 +765,7 @@ SET(FreeCADGui_SRCS Thumbnail.h Utilities.h WaitCursor.h + ManualAlignment.h ) SET(FreeCADGui_SRCS diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index a0496abab3..52fa870be9 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -50,11 +50,13 @@ #include "DlgProjectUtility.h" #include "Transform.h" #include "Placement.h" +#include "ManualAlignment.h" #include "WaitCursor.h" #include "ViewProvider.h" #include #include #include "MergeDocuments.h" +#include "NavigationStyle.h" using namespace Gui; @@ -1013,6 +1015,63 @@ bool StdCmdPlacement::isActive(void) return (Gui::Control().activeDialog()==0); } +//=========================================================================== +// Std_Alignment +//=========================================================================== +DEF_STD_CMD_A(StdCmdAlignment); + +StdCmdAlignment::StdCmdAlignment() + : Command("Std_Alignment") +{ + sGroup = QT_TR_NOOP("Edit"); + sMenuText = QT_TR_NOOP("Alignment..."); + sToolTipText = QT_TR_NOOP("Align the selected objects"); + sStatusTip = QT_TR_NOOP("Align the selected objects"); + sWhatsThis = "Std_Alignment"; +} + +void StdCmdAlignment::activated(int iMsg) +{ + std::vector sel = Gui::Selection().getObjectsOfType + (App::GeoFeature::getClassTypeId()); + ManualAlignment* align = ManualAlignment::instance(); + QObject::connect(align, SIGNAL(emitCanceled()), align, SLOT(deleteLater())); + QObject::connect(align, SIGNAL(emitFinished()), align, SLOT(deleteLater())); + + // Get the fixed and moving meshes + FixedGroup fixedGroup; + std::map groupMap; + fixedGroup.addView(sel[0]); + groupMap[0].addView(sel[1]); + + // add the fixed group + align->setFixedGroup(fixedGroup); + + // create the model of movable groups + MovableGroupModel model; + model.addGroups(groupMap); + align->setModel(model); + Base::Type style = Base::Type::fromName("Gui::CADNavigationStyle"); + Gui::Document* doc = Application::Instance->activeDocument(); + if (doc) { + View3DInventor* mdi = qobject_cast(doc->getActiveView()); + if (mdi) { + style = mdi->getViewer()->navigationStyle()->getTypeId(); + } + } + + align->setMinPoints(1); + align->startAlignment(style); + Gui::Selection().clearSelection(); +} + +bool StdCmdAlignment::isActive(void) +{ + if (ManualAlignment::hasInstance()) + return false; + return Gui::Selection().countObjectsOfType(App::GeoFeature::getClassTypeId()) == 2; +} + //=========================================================================== // Std_Edit //=========================================================================== @@ -1085,6 +1144,7 @@ void CreateDocCommands(void) rcCmdMgr.addCommand(new StdCmdRefresh()); rcCmdMgr.addCommand(new StdCmdTransform()); rcCmdMgr.addCommand(new StdCmdPlacement()); + rcCmdMgr.addCommand(new StdCmdAlignment()); rcCmdMgr.addCommand(new StdCmdEdit()); } diff --git a/src/Gui/ManualAlignment.cpp b/src/Gui/ManualAlignment.cpp new file mode 100644 index 0000000000..ae4d8e1788 --- /dev/null +++ b/src/Gui/ManualAlignment.cpp @@ -0,0 +1,1244 @@ +/*************************************************************************** + * Copyright (c) 2012 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ManualAlignment.h" +#include "BitmapFactory.h" +#include "SoAxisCrossKit.h" + + +using namespace Gui; + +AlignmentGroup::AlignmentGroup() +{ +} + +AlignmentGroup::~AlignmentGroup() +{ +} + +void AlignmentGroup::addView(App::DocumentObject* pView) +{ + if (pView) { + App::Document* rDoc = pView->getDocument(); + Gui::Document* pDoc = Gui::Application::Instance->getDocument(rDoc); + Gui::ViewProviderDocumentObject* pProvider = static_cast + (pDoc->getViewProvider(pView)); + this->_views.push_back(pProvider); + } +} + +std::vector AlignmentGroup::getViews() const +{ + std::vector views; + + std::vector::const_iterator it; + for (it = this->_views.begin(); it != this->_views.end(); ++it) { + App::DocumentObject* pView = (*it)->getObject(); + views.push_back(pView); + } + + return views; +} + +bool AlignmentGroup::hasView(Gui::ViewProviderDocumentObject* pView) const +{ + std::vector::const_iterator it; + for (it = this->_views.begin(); it != this->_views.end(); ++it) { + if (*it == pView) + return true; + } + + return false; +} + +void AlignmentGroup::removeView(Gui::ViewProviderDocumentObject* pView) +{ + std::vector::iterator it; + for (it = this->_views.begin(); it != this->_views.end(); ++it) { + if (*it == pView) { + this->_views.erase(it); + break; + } + } +} + +void AlignmentGroup::addToViewer(Gui::View3DInventorViewer* viewer) const +{ + std::vector::const_iterator it; + for (it = this->_views.begin(); it != this->_views.end(); ++it) + viewer->addViewProvider(*it); + + viewer->viewAll(); +} + +void AlignmentGroup::removeFromViewer(Gui::View3DInventorViewer* viewer) const +{ + std::vector::const_iterator it; + for (it = this->_views.begin(); it != this->_views.end(); ++it) + viewer->removeViewProvider(*it); +} + +void AlignmentGroup::setRandomColor() +{ + std::vector::iterator it; + for (it = this->_views.begin(); it != this->_views.end(); ++it) { + float r = /*(float)rand()/(float)RAND_MAX*/0.0f; + float g = (float)rand()/(float)RAND_MAX; + float b = (float)rand()/(float)RAND_MAX; + if ((*it)->isDerivedFrom(Gui::ViewProviderGeometryObject::getClassTypeId())) { + SoSearchAction searchAction; + searchAction.setType(SoMaterial::getClassTypeId()); + searchAction.setInterest(SoSearchAction::FIRST); + searchAction.apply((*it)->getRoot()); + SoPath* selectionPath = searchAction.getPath(); + + if (selectionPath) { + SoMaterial* material = static_cast(selectionPath->getTail()); + material->diffuseColor.setValue(r, g, b); + } + } + } +} + +Gui::Document* AlignmentGroup::getDocument() const +{ + if (this->_views.empty()) + return 0; + App::DocumentObject* pView = this->_views[0]->getObject(); + if (pView) { + App::Document* rDoc = pView->getDocument(); + Gui::Document* pDoc = Gui::Application::Instance->getDocument(rDoc); + return pDoc; + } + + return 0; +} + +void AlignmentGroup::addPoint(const Base::Vector3d& pnt) +{ + this->_pickedPoints.push_back(pnt); +} + +void AlignmentGroup::removeLastPoint() +{ + this->_pickedPoints.pop_back(); +} + +int AlignmentGroup::countPoints() const +{ + return this->_pickedPoints.size(); +} + +const std::vector& AlignmentGroup::getPoints() const +{ + return this->_pickedPoints; +} + +void AlignmentGroup::clearPoints() +{ + this->_pickedPoints.clear(); +} + +void AlignmentGroup::setAlignable(bool align) +{ + //std::vector::iterator it; + //for (it = this->_views.begin(); it != this->_views.end(); ++it) { + // if (!align){ + // App::PropertyColor* pColor = (App::PropertyColor*)(*it)->getPropertyByName("ShapeColor"); + // if (pColor) + // pColor->touch(); // resets to color defined by property + // } + //} +} + +void AlignmentGroup::moveTo(AlignmentGroup& that) +{ + std::vector::iterator it; + for (it = this->_views.begin(); it != this->_views.end(); ++it) + that._views.push_back(*it); + + this->_views.clear(); +} + +void AlignmentGroup::clear() +{ + this->_views.clear(); + this->_pickedPoints.clear(); +} + +bool AlignmentGroup::isEmpty() const +{ + return this->_views.empty(); +} + +int AlignmentGroup::count() const +{ + return this->_views.size(); +} + +// ------------------------------------------------------------------ + +MovableGroup::MovableGroup() +{ +} + +MovableGroup::~MovableGroup() +{ +} + +// ------------------------------------------------------------------ + +FixedGroup::FixedGroup() +{ +} + +FixedGroup::~FixedGroup() +{ +} + +// ------------------------------------------------------------------ + +MovableGroupModel::MovableGroupModel() +{ +} + +MovableGroupModel::~MovableGroupModel() +{ +} + +void MovableGroupModel::addGroup(const MovableGroup& grp) +{ + this->_groups.push_back(grp); +} + +void MovableGroupModel::addGroups(const std::map& grps) +{ + for (std::map::const_iterator it = grps.begin(); it != grps.end(); ++it) + this->_groups.push_back(it->second); +} + +void MovableGroupModel::removeActiveGroup() +{ + this->_groups.erase(this->_groups.begin()); +} + +MovableGroup& MovableGroupModel::activeGroup() +{ + // Make sure that the array is not empty + if (this->_groups.empty()) + throw Base::Exception("Empty group"); + return *(this->_groups.begin()); +} + +const MovableGroup& MovableGroupModel::activeGroup() const +{ + // Make sure that the array is not empty + if (this->_groups.empty()) + throw Base::Exception("Empty group"); + return *(this->_groups.begin()); +} + +void MovableGroupModel::continueAlignment() +{ + if (!isEmpty()) + removeActiveGroup(); +} + +void MovableGroupModel::clear() +{ + this->_groups.clear(); +} + +bool MovableGroupModel::isEmpty() const +{ + return this->_groups.empty(); +} + +int MovableGroupModel::count() const +{ + return this->_groups.size(); +} + +// ------------------------------------------------------------------ + +namespace Gui { +class AlignmentView : public Gui::AbstractSplitView +{ +public: + QLabel* myLabel; + + AlignmentView(Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags=0) + : AbstractSplitView(pcDocument, parent, wflags) + { + QSplitter* mainSplitter=0; + mainSplitter = new QSplitter(Qt::Horizontal, this); + _viewer.push_back(new View3DInventorViewer(mainSplitter)); + _viewer.push_back(new View3DInventorViewer(mainSplitter)); + + QFrame* vbox = new QFrame(this); + QVBoxLayout* layout = new QVBoxLayout(); + layout->setMargin(0); + layout->setSpacing(0); + vbox->setLayout(layout); + + myLabel = new QLabel(this); + myLabel->setAutoFillBackground(true); + QPalette pal = myLabel->palette(); + pal.setColor(QPalette::Window, Qt::darkGray); + pal.setColor(QPalette::WindowText, Qt::white); + myLabel->setPalette(pal); + mainSplitter->setPalette(pal); + myLabel->setAlignment(Qt::AlignCenter); + myLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + QFont font = myLabel->font(); + font.setPointSize(14); + myLabel->setFont(font); + layout->addWidget(myLabel); + layout->addWidget(mainSplitter); + + vbox->show(); + setCentralWidget(vbox); + + // apply the user settings + setupSettings(); + + static_cast(getViewer(0)->getSceneManager()->getSceneGraph())-> + addChild(setupHeadUpDisplay(tr("Movable object"))); + static_cast(getViewer(1)->getSceneManager()->getSceneGraph())-> + addChild(setupHeadUpDisplay(tr("Fixed object"))); + } + ~AlignmentView() + { + } + bool canClose() + { + return false; + } + SoNode* setupHeadUpDisplay(const QString& text) const + { + SoSeparator* hudRoot = new SoSeparator; + hudRoot->ref(); + + SoOrthographicCamera* hudCam = new SoOrthographicCamera(); + hudCam->viewportMapping = SoCamera::LEAVE_ALONE; + + // Set the position in the window. + // [0, 0] is in the center of the screen. + // + SoTranslation* hudTrans = new SoTranslation; + hudTrans->translation.setValue(-0.95f, -0.95f, 0.0f); + + QFont font = this->font(); + font.setPointSize(24); + QFontMetrics fm(font); + + QColor front; + front.setRgbF(0.8f, 0.8f, 0.8f); + + int w = fm.width(text); + int h = fm.height(); + + QImage image(w,h,QImage::Format_ARGB32_Premultiplied); + image.fill(0x00000000); + QPainter painter(&image); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(front); + painter.setFont(font); + painter.drawText(0,0,w,h,Qt::AlignLeft,text); + painter.end(); + SoSFImage sfimage; + Gui::BitmapFactory().convert(image, sfimage); + SoImage* hudImage = new SoImage(); + hudImage->image = sfimage; + + // Assemble the parts... + // + hudRoot->addChild(hudCam); + hudRoot->addChild(hudTrans); + hudRoot->addChild(hudImage); + + return hudRoot; + } +}; +} + +class ManualAlignment::Private { +public: + SoSeparator * picksepLeft; + SoSeparator * picksepRight; + SoNodeSensor* sensorCam1; + SoNodeSensor* sensorCam2; + SbRotation rot_cam1, rot_cam2; + SbVec3f pos_cam1, pos_cam2; + + Private() + : sensorCam1(0), sensorCam2(0) + { + // left view + picksepLeft = new SoSeparator; + picksepLeft->ref(); + // right view + picksepRight = new SoSeparator; + picksepRight->ref(); + } + ~Private() + { + picksepLeft->unref(); + picksepRight->unref(); + delete sensorCam1; + delete sensorCam2; + } + + static + void reorientCamera(SoCamera * cam, const SbRotation & rot) + { + if (cam == NULL) return; + + // Find global coordinates of focal point. + SbVec3f direction; + cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction); + SbVec3f focalpoint = cam->position.getValue() + + cam->focalDistance.getValue() * direction; + + // Set new orientation value by accumulating the new rotation. + cam->orientation = rot * cam->orientation.getValue(); + + // Reposition camera so we are still pointing at the same old focal point. + cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction); + cam->position = focalpoint - cam->focalDistance.getValue() * direction; + } + + static + void copyCameraSettings(SoCamera* cam1, SbRotation& rot_cam1, SbVec3f& pos_cam1, + SoCamera* cam2, SbRotation& rot_cam2, SbVec3f& pos_cam2) + { + // recompute the diff we have applied to the camera's orientation + SbRotation rot = cam1->orientation.getValue(); + SbRotation dif = rot * rot_cam1.inverse(); + rot_cam1 = rot; + + // copy the values + cam2->enableNotify(FALSE); + cam2->nearDistance = cam1->nearDistance; + cam2->farDistance = cam1->farDistance; + cam2->focalDistance = cam1->focalDistance; + reorientCamera(cam2,dif); + rot_cam2 = cam2->orientation.getValue(); + + // reverse engineer the translation part in wc + SbVec3f pos = cam1->position.getValue(); + SbVec3f difpos = pos - pos_cam1; + pos_cam1 = pos; + // the translation in pixel coords + cam1->orientation.getValue().inverse().multVec(difpos,difpos); + // the translation again in wc for the second camera + cam2->orientation.getValue().multVec(difpos,difpos); + cam2->position.setValue(cam2->position.getValue()+difpos); + + if (cam1->getTypeId() == cam2->getTypeId()) { + if (cam1->getTypeId() == SoOrthographicCamera::getClassTypeId()) + static_cast(cam2)->height = + static_cast(cam1)->height; + } + + cam2->enableNotify(TRUE); + } + static + void syncCameraCB(void * data, SoSensor * s) + { + ManualAlignment* self = reinterpret_cast(data); + if (!self->myViewer) + return; // already destroyed + SoCamera* cam1 = self->myViewer->getViewer(0)->getCamera(); + SoCamera* cam2 = self->myViewer->getViewer(1)->getCamera(); + if (!cam1 || !cam2) + return; // missing camera + SoNodeSensor* sensor = static_cast(s); + SoNode* node = sensor->getAttachedNode(); + if (node && node->getTypeId().isDerivedFrom(SoCamera::getClassTypeId())) { + if (node == cam1) { + Private::copyCameraSettings(cam1, self->d->rot_cam1, self->d->pos_cam1, + cam2, self->d->rot_cam2, self->d->pos_cam2); + self->myViewer->getViewer(1)->render(); + } + else if (node == cam2) { + Private::copyCameraSettings(cam2, self->d->rot_cam2, self->d->pos_cam2, + cam1, self->d->rot_cam1, self->d->pos_cam1); + self->myViewer->getViewer(0)->render(); + } + } + } + + static Base::Placement + transformation2x2(const Base::Vector3d& plane1_base, + const Base::Vector3d& plane1_xaxis, + const Base::Vector3d& plane2_base, + const Base::Vector3d& plane2_xaxis) + { + // the transformation is: + // * move from plane1_base to plane2_base + // * rotate from plane1_zaxis to plane2_zaxis around plane2_base as center point + Base::Rotation rot(plane1_xaxis, plane2_xaxis); + + Base::Vector3d pln_base; + rot.multVec(plane1_base,pln_base); + Base::Vector3d dif = plane2_base - pln_base; + return Base::Placement(dif, rot); + } + + static Base::Placement + transformation3x3(const Base::Vector3d& plane1_base, + const Base::Vector3d& plane1_zaxis, + const Base::Vector3d& plane1_xaxis, + const Base::Vector3d& plane2_base, + const Base::Vector3d& plane2_zaxis, + const Base::Vector3d& plane2_xaxis) + { + // the transformation is: + // * move from plane1_base to plane2_base + // * rotate from plane1_zaxis to plane2_zaxis around plane2_base as center point + Base::Rotation rot(plane1_zaxis, plane2_zaxis); + + // first transformation to align the plane normals and base points + Base::Vector3d dif1 = plane1_base; + rot.multVec(dif1,dif1); + dif1 = plane2_base - dif1; + Base::Placement plm1(dif1, rot); + + // second transformation to align the planes' x axes + Base::Vector3d pln_xaxis; + rot.multVec(plane1_xaxis,pln_xaxis); + Base::Rotation rot2(pln_xaxis, plane2_xaxis); + Base::Vector3d dif2 = plane2_base; + rot2.multVec(dif2,dif2); + dif2 = plane2_base - dif2; + Base::Placement plm2(dif2, rot2); + plm2 = plm2 * plm1; + return plm2; + } +}; + +/* TRANSLATOR Gui::ManualAlignment */ + +ManualAlignment* ManualAlignment::_instance = 0; + +/** + * Construction. + */ +ManualAlignment::ManualAlignment() + : myViewer(0), myDocument(0), myPickPoints(3), d(new Private) +{ + // connect with the application's signal for deletion of documents + this->connectApplicationDeletedDocument = Gui::Application::Instance->signalDeleteDocument + .connect(boost::bind(&ManualAlignment::slotDeletedDocument, this, _1)); + + // setup sensor connection + d->sensorCam1 = new SoNodeSensor(Private::syncCameraCB, this); + d->sensorCam2 = new SoNodeSensor(Private::syncCameraCB, this); +} + +/** + * Destruction. + */ +ManualAlignment::~ManualAlignment() +{ + this->connectDocumentDeletedObject.disconnect(); + this->connectApplicationDeletedDocument.disconnect(); + closeViewer(); + delete d; + _instance = 0; +} + +/** + * Creates the one and only instance of this class. + */ +ManualAlignment* ManualAlignment::instance() +{ + // not initialized? + if (!_instance) + _instance = new ManualAlignment(); + return _instance; +} + +/** + * Destructs the one and only instance of this class. + */ +void ManualAlignment::destruct() +{ + if (_instance) { + ManualAlignment* tmp = _instance; + _instance = 0; + delete tmp; + } +} + +/** + * Checks whether the one instance exists. + */ +bool ManualAlignment::hasInstance() +{ + return _instance != 0; +} + +void ManualAlignment::setMinPoints(int minPoints) +{ + if ((minPoints > 0) && (minPoints <= 3)) + myPickPoints = minPoints; +} + +void ManualAlignment::setFixedGroup(const FixedGroup& fixed) +{ + this->myFixedGroup = fixed; + this->myDocument = fixed.getDocument(); +} + +void ManualAlignment::setModel(const MovableGroupModel& model) +{ + this->myAlignModel = model; +} + +void ManualAlignment::clearAll() +{ + myFixedGroup.clear(); + myAlignModel.clear(); + myDocument = 0; +} + +void ManualAlignment::setViewingDirections(const Base::Vector3d& view1, const Base::Vector3d& up1, + const Base::Vector3d& view2, const Base::Vector3d& up2) +{ + if (myViewer.isNull()) + return; + + { + SbRotation rot; + rot.setValue(SbVec3f(0.0f, 0.0f, 1.0f), SbVec3f(-view1.x,-view1.y,-view1.z)); + + SbRotation rot2; + SbVec3f up(0.0f, 1.0f, 0.0f); + rot.multVec(up, up); + rot2.setValue(up, SbVec3f(up1.x, up1.y, up1.z)); + myViewer->getViewer(0)->getCamera()->orientation.setValue(rot * rot2); + myViewer->getViewer(0)->viewAll(); + } + + { + SbRotation rot; + rot.setValue(SbVec3f(0.0f, 0.0f, 1.0f), SbVec3f(-view2.x,-view2.y,-view2.z)); + + SbRotation rot2; + SbVec3f up(0.0f, 1.0f, 0.0f); + rot.multVec(up, up); + rot2.setValue(up, SbVec3f(up2.x, up2.y, up2.z)); + myViewer->getViewer(1)->getCamera()->orientation.setValue(rot * rot2); + myViewer->getViewer(1)->viewAll(); + } +} + +/** + * Performs the alignment for the specified aligned and non-aligned views specified by setModel() and setFixedGroup(). + */ +void ManualAlignment::startAlignment(Base::Type mousemodel) +{ + // allow only one alignment at a time + if (!myViewer.isNull()) { + QMessageBox::warning(qApp->activeWindow(), tr("Manual alignment"), tr("The alignment is already in progress.")); + return; + } + + myTransform = Base::Placement(); + + if (myFixedGroup.isEmpty()) + return; + if (myAlignModel.isEmpty()) + return; + + // create a splitted window for picking the points + myViewer = new AlignmentView(myDocument,Gui::getMainWindow()); + myViewer->setWindowTitle(tr("Alignment[*]")); + myViewer->setWindowIcon(QApplication::windowIcon()); + myViewer->resize(400, 300); + Gui::getMainWindow()->addWindow(myViewer); + myViewer->showMaximized(); + int n = this->myPickPoints; + QString msg = n == 1 + ? tr("Please, select at least one point in the left and the right view") + : tr("Please, select at least %1 points in the left and the right view").arg(n); + myViewer->myLabel->setText(msg); + + connect(myViewer, SIGNAL(destroyed()), this, SLOT(reset())); + + // show all aligned views in the 2nd view + myFixedGroup.addToViewer(myViewer->getViewer(1)); + myFixedGroup.setAlignable(true); + + // set picked points root + SoNode* node1 = myViewer->getViewer(0)->getSceneGraph(); + if (node1->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())){ + ((SoGroup*)node1)->addChild(d->picksepLeft); + } + SoNode* node2 = myViewer->getViewer(1)->getSceneGraph(); + if (node2->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())){ + ((SoGroup*)node2)->addChild(d->picksepRight); + } + + myViewer->getViewer(0)->setEditing(true); + myViewer->getViewer(0)->addEventCallback(SoMouseButtonEvent::getClassTypeId(), + ManualAlignment::probePickedCallback); + myViewer->getViewer(1)->setEditing(true); + myViewer->getViewer(1)->addEventCallback(SoMouseButtonEvent::getClassTypeId(), + ManualAlignment::probePickedCallback); + // apply the mouse model + myViewer->getViewer(0)->setNavigationType(mousemodel); + myViewer->getViewer(1)->setNavigationType(mousemodel); + + // Connect to the document's signal as we want to be notified when something happens + if (this->connectDocumentDeletedObject.connected()) + this->connectDocumentDeletedObject.disconnect(); + this->connectDocumentDeletedObject = myDocument->signalDeletedObject.connect(boost::bind + (&ManualAlignment::slotDeletedObject, this, _1)); + + continueAlignment(); +} + +/** + * If still one view needs to be aligned then it is shown in the first window. If all views are aligned the process will be terminated. + */ +void ManualAlignment::continueAlignment() +{ + myFixedGroup.clearPoints(); + d->picksepLeft->removeAllChildren(); + d->picksepRight->removeAllChildren(); + + if (!myAlignModel.isEmpty()) { + AlignmentGroup& grp = myAlignModel.activeGroup(); + grp.clearPoints(); + grp.addToViewer(myViewer->getViewer(0)); + grp.setAlignable(true); + + Gui::getMainWindow()->statusBar()->showMessage(tr("Please pick points in the left and right view")); + + myViewer->getViewer(0)->setEditingCursor(QCursor(Qt::PointingHandCursor)); + myViewer->getViewer(1)->setEditingCursor(QCursor(Qt::PointingHandCursor)); + } + else { + finish(); + } +} + +void ManualAlignment::closeViewer() +{ + if (!myViewer) + return; + // Close the viewer +#if !defined(NO_USE_QT_MDI_AREA) + if (myViewer->parentWidget()) + myViewer->parentWidget()->deleteLater(); +#else + myViewer->deleteLater(); +#endif + myViewer = 0; +} + +/** + * Make all views unpickable and resets internal data. + */ +void ManualAlignment::reset() +{ + if (!myAlignModel.isEmpty()) { + myAlignModel.activeGroup().setAlignable(false); + myAlignModel.activeGroup().clear(); + myAlignModel.clear(); + } + + myFixedGroup.setAlignable(false); + myFixedGroup.clear(); + + d->picksepLeft->removeAllChildren(); + d->picksepRight->removeAllChildren(); + + if (myDocument) { + this->connectDocumentDeletedObject.disconnect(); + myDocument = 0; + } +} + +/** + * Terminates the process and closes the windows. + */ +void ManualAlignment::finish() +{ + if (myViewer.isNull()) + return; + + if (myDocument) + myDocument->getDocument()->recompute(); + closeViewer(); + reset(); + + Gui::getMainWindow()->statusBar()->showMessage(tr("The alignment has finished")); + + // If an event receiver has been defined send the manual alignment finished event to it + emitFinished(); +} + +/** + * Cancels the process and clöses the windows without performing an alignment. + */ +void ManualAlignment::cancel() +{ + if (myViewer.isNull()) + return; + + closeViewer(); + myTransform = Base::Placement(); + reset(); + + Gui::getMainWindow()->statusBar()->showMessage(tr("The alignment has been canceled")); + + // If an event receiver has been defined send the manual alignment cancelled event to it + emitCanceled(); +} + +void ManualAlignment::align() +{ + // Now we can start the actual alignment + if (myAlignModel.activeGroup().countPoints() < myPickPoints) { + QMessageBox::warning(myViewer, tr("Manual alignment"), + tr("Too few points picked in the left view." + " At least %1 points are needed.").arg(myPickPoints)); + } + else if (myFixedGroup.countPoints() < myPickPoints) { + QMessageBox::warning(myViewer, tr("Manual alignment"), + tr("Too few points picked in the right view." + " At least %1 points are needed.").arg(myPickPoints)); + } + else if (myAlignModel.activeGroup().countPoints() != myFixedGroup.countPoints()) { + QMessageBox::warning(myViewer, tr("Manual alignment"), + tr("Different number of points picked in left and right view.\n" + "On the left view %1 points are picked,\n" + "on the right view %2 points are picked.") + .arg(myAlignModel.activeGroup().countPoints()) + .arg(myFixedGroup.countPoints())); + } + else { + // do not allow to pick further points + myAlignModel.activeGroup().removeFromViewer(myViewer->getViewer(0)); + myAlignModel.activeGroup().setAlignable(false); + std::vector pViews = myAlignModel.activeGroup().getViews(); + Gui::getMainWindow()->statusBar()->showMessage(tr("Try to align group of views")); + + // Compute alignment + bool ok = computeAlignment(myAlignModel.activeGroup().getPoints(), myFixedGroup.getPoints()); + if (ok) { + // Align views + for (std::vector::iterator it = pViews.begin(); it != pViews.end(); ++it) + alignObject(*it); + + // the alignment was successful so show it in the right view now + //myAlignModel.activeGroup().setRandomColor(); + myAlignModel.activeGroup().setAlignable(true); + myAlignModel.activeGroup().addToViewer(myViewer->getViewer(1)); + myAlignModel.activeGroup().moveTo(myFixedGroup); + myAlignModel.continueAlignment(); + } + else { + // Inform user that alignment failed + int ret = QMessageBox::critical(myViewer, tr("Manual alignment"), + tr("The alignment failed.\nHow do you want to proceed?"), + tr("Retry"), tr("Ignore"), tr("Abort")); + if ( ret == 1 ) { + myAlignModel.continueAlignment(); + } + else if ( ret == 2 ) { + finish(); + return; + } + } + + continueAlignment(); + } +} + +void ManualAlignment::showInstructions() +{ + // Now we can start the actual alignment + if (myAlignModel.activeGroup().countPoints() < myPickPoints) { + Gui::getMainWindow()->statusBar()->showMessage( + tr("Too few points picked in the left view." + " At least %1 points are needed.").arg(myPickPoints)); + } + else if (myFixedGroup.countPoints() < myPickPoints) { + Gui::getMainWindow()->statusBar()->showMessage( + tr("Too few points picked in the right view." + " At least %1 points are needed.").arg(myPickPoints)); + } + else if (myAlignModel.activeGroup().countPoints() != myFixedGroup.countPoints()) { + Gui::getMainWindow()->statusBar()->showMessage( + tr("Different number of points picked in left and right view. " + "On the left view %1 points are picked, " + "on the right view %2 points are picked.") + .arg(myAlignModel.activeGroup().countPoints()) + .arg(myFixedGroup.countPoints())); + } +} + +bool ManualAlignment::canAlign() const +{ + if (myAlignModel.activeGroup().countPoints() == myFixedGroup.countPoints()) { + if (myFixedGroup.countPoints() >= myPickPoints) + return true; + } + + return false; +} + +/** + * This method computes the alignment. For the calculation of the alignment the picked points of both views + * are taken. If the alignment fails false is returned, true otherwise. + */ +bool ManualAlignment::computeAlignment(const std::vector& movPts, + const std::vector& fixPts) +{ + assert((int)movPts.size() >= myPickPoints); + assert((int)fixPts.size() >= myPickPoints); + assert((int)movPts.size() == (int)fixPts.size()); + myTransform = Base::Placement(); + + if (movPts.size() == 1) { + // 1 point partial solution: Simple translation only + myTransform.setPosition(fixPts[0] - movPts[0]); + } + else if (movPts.size() == 2) { + const Base::Vector3d& p1 = movPts[0]; + const Base::Vector3d& p2 = movPts[1]; + Base::Vector3d d1 = p2-p1; + d1.Normalize(); + + const Base::Vector3d& q1 = fixPts[0]; + const Base::Vector3d& q2 = fixPts[1]; + Base::Vector3d d2 = q2-q1; + d2.Normalize(); + + myTransform = Private::transformation2x2(p1, d1, q1, d2); + } + else if (movPts.size() >= 3) { + const Base::Vector3d& p1 = movPts[0]; + const Base::Vector3d& p2 = movPts[1]; + const Base::Vector3d& p3 = movPts[2]; + Base::Vector3d d1 = p2-p1; + d1.Normalize(); + Base::Vector3d n1 = (p2-p1) % (p3-p1); + n1.Normalize(); + + const Base::Vector3d& q1 = fixPts[0]; + const Base::Vector3d& q2 = fixPts[1]; + const Base::Vector3d& q3 = fixPts[2]; + Base::Vector3d d2 = q2-q1; + d2.Normalize(); + Base::Vector3d n2 = (q2-q1) % (q3-q1); + n2.Normalize(); + + myTransform = Private::transformation3x3(p1, d1, n1, q1, d2, n2); + } + + return true; +} + +/** + * This method performs the actual alignment of view \a pView. + */ +void ManualAlignment::alignObject(App::DocumentObject *obj) +{ + if (obj->getTypeId().isDerivedFrom(App::GeoFeature::getClassTypeId())) { + App::GeoFeature* geom = static_cast(obj); + Base::Placement plm = geom->Placement.getValue(); + plm = this->myTransform * plm; + geom->Placement.setValue(plm); + } +} + +/** + * Creates a point element as visible feedback for the user. + */ +SoNode* ManualAlignment::pickedPointsSubGraph(const SbVec3f& p, const SbVec3f& n, int id) +{ + static const float color_table [10][3] = { + {1.0f,0.0f,0.0f}, // red + {0.0f,1.0f,0.0f}, // green + {0.0f,0.0f,1.0f}, // blue + {1.0f,1.0f,0.0f}, // yellow + {0.0f,1.0f,1.0f}, // cyan + {0.7f,0.0f,0.0f}, + {0.0f,0.7f,0.0f}, + {0.7f,0.7f,0.0f}, + {0.7f,0.0f,0.5f}, + {1.0f,0.7f,0.0f} + }; + + int index = (id-1) % 10; + + SoRegPoint* probe = new SoRegPoint(); + probe->base.setValue(p); + probe->normal.setValue(n); + probe->color.setValue(color_table[index][0],color_table[index][1],color_table[index][2]); + SbString s; + probe->text.setValue(s.sprintf("RegPoint_%d", id)); + return probe; +} + +/** + * Handle if the current document is about to being closed. + */ +void ManualAlignment::slotDeletedDocument(const Gui::Document& Doc) +{ + if (&Doc == this->myDocument) + reset(); +} + +/** + * Handle if the a view provider is about to being destroyed. + */ +void ManualAlignment::slotDeletedObject(const Gui::ViewProvider& Obj) +{ + // remove the view provider either from the left or the right view + if (Obj.getTypeId().isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId())) { + // remove the view provider immediately from the split window + bool found = false; + Gui::ViewProviderDocumentObject* vp = const_cast + (static_cast(&Obj)); + if (myAlignModel.activeGroup().hasView(vp)) { + myViewer->getViewer(0)->removeViewProvider(vp); + found = true; + } + if (myFixedGroup.hasView(vp)) { + myViewer->getViewer(1)->removeViewProvider(vp); + found = true; + } + + if (found) + cancel(); + } +} + +void ManualAlignment::onAlign() +{ + align(); +} + +void ManualAlignment::onRemoveLastPointMoveable() +{ + int nPoints = myAlignModel.activeGroup().countPoints(); + if (nPoints > 0) { + myAlignModel.activeGroup().removeLastPoint(); + d->picksepLeft->removeChild(nPoints-1); + } +} + +void ManualAlignment::onRemoveLastPointFixed() +{ + int nPoints = myFixedGroup.countPoints(); + if (nPoints > 0) { + myFixedGroup.removeLastPoint(); + d->picksepRight->removeChild(nPoints-1); + } +} + +void ManualAlignment::onClear() +{ + myAlignModel.activeGroup().clear(); + myFixedGroup.clear(); + + d->picksepLeft->removeAllChildren(); + d->picksepRight->removeAllChildren(); +} + +void ManualAlignment::onCancel() +{ + cancel(); +} + +void ManualAlignment::probePickedCallback(void * ud, SoEventCallback * n) +{ + Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); + const SoEvent* ev = n->getEvent(); + if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) { + // set as handled + n->getAction()->setHandled(); + n->setHandled(); + + const SoMouseButtonEvent * mbe = static_cast(ev); + if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { + // if we are in 'align' mode then handle the click event + ManualAlignment* self = ManualAlignment::instance(); + // Get the closest point to the camera of the whole scene. + // This point doesn't need to be part of this view provider. + Gui::WaitCursor wc; + const SoPickedPoint * point = n->getPickedPoint(); + if (point) { + Gui::ViewProvider* vp = static_cast(view->getViewProviderByPath(point->getPath())); + if (vp && vp->getTypeId().isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId())) { + Gui::ViewProviderDocumentObject* that = static_cast(vp); + self->applyPickedProbe(that, point); + + const SbVec3f& vec = point->getPoint(); + Gui::getMainWindow()->statusBar()->showMessage( + tr("Point picked at (%1,%2,%3)") + .arg(vec[0]).arg(vec[1]).arg(vec[2])); + } + } + else { + Gui::getMainWindow()->statusBar()->showMessage( + tr("No point was picked")); + } + } + else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { + ManualAlignment* self = ManualAlignment::instance(); + if (self->myAlignModel.isEmpty() || self->myFixedGroup.isEmpty()) + return; + self->showInstructions(); + int nPoints; + if (view == self->myViewer->getViewer(0)) + nPoints = self->myAlignModel.activeGroup().countPoints(); + else + nPoints = self->myFixedGroup.countPoints(); + QMenu menu; + QAction* fi = menu.addAction(QLatin1String("&Align")); + QAction* rem = menu.addAction(QLatin1String("&Remove last point")); + //QAction* cl = menu.addAction("C&lear"); + QAction* ca = menu.addAction(QLatin1String("&Cancel")); + fi->setEnabled(self->canAlign()); + rem->setEnabled(nPoints > 0); + menu.addSeparator(); + QAction* sync = menu.addAction(QLatin1String("&Synchronize views")); + sync->setCheckable(true); + if (self->d->sensorCam1->getAttachedNode()) + sync->setChecked(true); + QAction* id = menu.exec(QCursor::pos()); + if (id == fi) { + // call align->align(); + QTimer::singleShot(300, self, SLOT(onAlign())); + } + else if ((id == rem) && (view == self->myViewer->getViewer(0))) { + QTimer::singleShot(300, self, SLOT(onRemoveLastPointMoveable())); + } + else if ((id == rem) && (view == self->myViewer->getViewer(1))) { + QTimer::singleShot(300, self, SLOT(onRemoveLastPointFixed())); + } + //else if (id == cl) { + // // call align->clear(); + // QTimer::singleShot(300, self, SLOT(onClear())); + //} + else if (id == ca) { + // call align->cancel(); + QTimer::singleShot(300, self, SLOT(onCancel())); + } + else if (id == sync) { + // setup sensor connection + if (sync->isChecked()) { + SoCamera* cam1 = self->myViewer->getViewer(0)->getCamera(); + SoCamera* cam2 = self->myViewer->getViewer(1)->getCamera(); + if (cam1 && cam2) { + self->d->sensorCam1->attach(cam1); + self->d->rot_cam1 = cam1->orientation.getValue(); + self->d->pos_cam1 = cam1->position.getValue(); + self->d->sensorCam2->attach(cam2); + self->d->rot_cam2 = cam2->orientation.getValue(); + self->d->pos_cam2 = cam2->position.getValue(); + } + } + else { + self->d->sensorCam1->detach(); + self->d->sensorCam2->detach(); + } + } + } + } +} + +/** + * This method stores the picked point \a pnt from the view provider \a prov. If enough points in both windows have been picked + * the alignment gets invoked. + */ +void ManualAlignment::applyPickedProbe(Gui::ViewProviderDocumentObject* prov, const SoPickedPoint* pnt) +{ + const SbVec3f& vec = pnt->getPoint(); + const SbVec3f& nor = pnt->getNormal(); + + // add to the list for the non-aligned view in the left view + if (myAlignModel.activeGroup().hasView(prov)) { + myAlignModel.activeGroup().addPoint(Base::Vector3d(vec[0],vec[1],vec[2])); + // Adds a point marker for the picked point. + d->picksepLeft->addChild(pickedPointsSubGraph(vec, nor, myAlignModel.activeGroup().countPoints())); + } + else if (myFixedGroup.hasView(prov)) { + myFixedGroup.addPoint(Base::Vector3d(vec[0],vec[1],vec[2])); + // Adds a point marker for the picked point. + d->picksepRight->addChild(pickedPointsSubGraph(vec, nor, myFixedGroup.countPoints())); + } +} + +#include "moc_ManualAlignment.cpp" + diff --git a/src/Gui/ManualAlignment.h b/src/Gui/ManualAlignment.h new file mode 100644 index 0000000000..78a93391fe --- /dev/null +++ b/src/Gui/ManualAlignment.h @@ -0,0 +1,257 @@ +/*************************************************************************** + * Copyright (c) 2012 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef GUI_MANUALALIGNMENT_H +#define GUI_MANUALALIGNMENT_H + +#include +#include +#include +#include +#include +#include + +class SbVec3f; +class SoPickedPoint; +class SoEventCallback; + +namespace Gui { +class Document; +class AlignmentView; +class View3DInventorViewer; + +/** + * The AlignemntGroup class is the base for fixed and movable groups. + * @author Werner Mayer + */ +class GuiExport AlignmentGroup +{ +protected: + AlignmentGroup(); + ~AlignmentGroup(); + +public: + /** + * Add a mesh to the group. + */ + void addView(App::DocumentObject*); + std::vector getViews() const; + /** + * Checks for the view provider of one of the added views. + */ + bool hasView(Gui::ViewProviderDocumentObject*) const; + /** + * Remove a previously added view by its view provider. + */ + void removeView(Gui::ViewProviderDocumentObject*); + /** + * Add the group and therefore all its added view providers to the Inventor tree. + */ + void addToViewer(Gui::View3DInventorViewer*) const; + /** + * Remove all the view providers from the Inventor tree. + */ + void removeFromViewer(Gui::View3DInventorViewer*) const; + void setRandomColor(); + /** + * Returns the document of the added views. + */ + Gui::Document* getDocument() const; + /** + * Add a point to an array of picked points. + */ + void addPoint(const Base::Vector3d&); + /** + * Remove last point from array of picked points. + */ + void removeLastPoint(); + /** + * Count the number of picked points. + */ + int countPoints() const; + /** + * Return an array of picked points. + */ + const std::vector& getPoints() const; + /** + * Clear all picked points. + */ + void clearPoints(); + /** + * Set or unset the alignable mode for the added views. If a view is not alignable it also not pickable. + */ + void setAlignable(bool); + void moveTo(AlignmentGroup&); + /** + * Clear the list of added views. + */ + void clear(); + /** + * Checks whether the list of added views is empty or not. + */ + bool isEmpty() const; + /** + * Return the number of added views. + */ + int count() const; + +protected: + std::vector _pickedPoints; + std::vector _views; +}; + +/** + * The FixedGroup class can be used for a fixed group of views. + * @author Werner Mayer + */ +class GuiExport MovableGroup : public AlignmentGroup +{ +public: + MovableGroup(); + ~MovableGroup(); +}; + +/** + * The FixedGroup class can be used for a fixed group of views. + * @author Werner Mayer + */ +class GuiExport FixedGroup : public AlignmentGroup +{ +public: + FixedGroup(); + ~FixedGroup(); +}; + +/** + * The MovableGroupModel class keeps an array of movable groups. + * @author Werner Mayer + */ +class GuiExport MovableGroupModel +{ +public: + MovableGroupModel(); + ~MovableGroupModel(); + + void addGroup(const MovableGroup&); + void addGroups(const std::map&); + MovableGroup& activeGroup(); + const MovableGroup& activeGroup() const; + void continueAlignment(); + void clear(); + bool isEmpty() const; + int count() const; + +protected: + void removeActiveGroup(); + +private: + std::vector _groups; +}; + +/** + * @author Werner Mayer + */ +class GuiExport ManualAlignment : public QObject +{ + Q_OBJECT + +protected: + ManualAlignment(); + ~ManualAlignment(); + +public: + static ManualAlignment* instance(); + static void destruct(); + static bool hasInstance(); + + void setMinPoints(int minPoints); + void setFixedGroup(const FixedGroup&); + void setModel(const MovableGroupModel&); + void clearAll(); + + void setViewingDirections(const Base::Vector3d& view1, const Base::Vector3d& up1, + const Base::Vector3d& view2, const Base::Vector3d& up2); + void startAlignment(Base::Type mousemodel); + void finish(); + void align(); + bool canAlign() const; + void cancel(); + + const Base::Placement & getTransform() const + { return myTransform; } + void alignObject(App::DocumentObject*); + + // Observer stuff + /// Checks if the given object is about to be removed + void slotDeletedDocument(const Gui::Document& Doc); + /// Checks if the given document is about to be closed + void slotDeletedObject(const Gui::ViewProvider& Obj); + +protected: + bool computeAlignment(const std::vector& unnavPts, const std::vector& navigPts); + void continueAlignment(); + void showInstructions(); + /** @name Probe picking */ + //@{ + static void probePickedCallback(void * ud, SoEventCallback * n); + void applyPickedProbe(Gui::ViewProviderDocumentObject*, const SoPickedPoint* pnt); + //@} + +protected Q_SLOTS: + void reset(); + void onAlign(); + void onRemoveLastPointMoveable(); + void onRemoveLastPointFixed(); + void onClear(); + void onCancel(); + +Q_SIGNALS: + void emitCanceled(); + void emitFinished(); + +private: + SoNode* pickedPointsSubGraph(const SbVec3f& p, const SbVec3f& n, int id); + void closeViewer(); + + static ManualAlignment* _instance; + + typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection; + Connection connectApplicationDeletedDocument; + Connection connectDocumentDeletedObject; + + FixedGroup myFixedGroup; + MovableGroupModel myAlignModel; + QPointer myViewer; + Gui::Document* myDocument; + int myPickPoints; + Base::Placement myTransform; + + class Private; + Private* d; +}; + +} // namespace Gui + + +#endif // GUI_MANUALALIGNMENT_H + diff --git a/src/Gui/SoAxisCrossKit.cpp b/src/Gui/SoAxisCrossKit.cpp index 6eed7457de..d05f856702 100644 --- a/src/Gui/SoAxisCrossKit.cpp +++ b/src/Gui/SoAxisCrossKit.cpp @@ -24,20 +24,34 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# ifdef FC_OS_WIN32 +# include +# endif +# ifdef FC_OS_MACOSX +# include +# else +# include +# endif # include # include +# include +# include +# include +# include +# include +# include # include # include # include # include # include # include +# include # include # include +# include +# include # include -# include -# include -# include #endif @@ -217,3 +231,129 @@ SoAxisCrossKit::createAxes() set("zAxis.pickStyle", "style UNPICKABLE"); set("zHead.pickStyle", "style UNPICKABLE"); } + +// -------------------------------------------------------------- + +SO_NODE_SOURCE(SoRegPoint); + +void SoRegPoint::initClass() +{ + SO_NODE_INIT_CLASS(SoRegPoint, SoShape, "Shape"); +} + +SoRegPoint::SoRegPoint() +{ + SO_NODE_CONSTRUCTOR(SoRegPoint); + + SO_NODE_ADD_FIELD(base, (SbVec3f(0,0,0))); + SO_NODE_ADD_FIELD(normal, (SbVec3f(1,1,1))); + SO_NODE_ADD_FIELD(length, (3.0)); + SO_NODE_ADD_FIELD(color, (1.0f, 0.447059f, 0.337255f)); + SO_NODE_ADD_FIELD(text, ("")); + + root = new SoSeparator(); + root->ref(); + + // translation + SoTranslation* move = new SoTranslation(); + move->translation.setValue(base.getValue() + normal.getValue() * length.getValue()); + root->addChild(move); + + // sub-group + SoBaseColor* col = new SoBaseColor(); + col->rgb.setValue(this->color.getValue()); + + SoFontStyle* font = new SoFontStyle; + font->size = 14; + + SoSeparator* sub = new SoSeparator(); + sub->addChild(col); + sub->addChild(font); + sub->addChild(new SoText2()); + root->addChild(sub); +} + +SoRegPoint::~SoRegPoint() +{ + root->unref(); +} + +/** + * Renders the probe with text label and a bullet at the base point. + */ +void SoRegPoint::GLRender(SoGLRenderAction *action) +{ + if (shouldGLRender(action)) + { + SoState* state = action->getState(); + state->push(); + SoMaterialBundle mb(action); + SoTextureCoordinateBundle tb(action, TRUE, FALSE); + SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); + mb.sendFirst(); // make sure we have the correct material + + SbVec3f p1 = base.getValue(); + SbVec3f p2 = p1 + normal.getValue() * length.getValue(); + + glLineWidth(1.0f); + glColor3fv(color.getValue().getValue()); + glBegin(GL_LINE_STRIP); + glVertex3d(p1[0], p1[1], p1[2]); + glVertex3d(p2[0], p2[1], p2[2]); + glEnd(); + glPointSize(5.0f); + glBegin(GL_POINTS); + glVertex3fv(p1.getValue()); + glEnd(); + glPointSize(2.0f); + glBegin(GL_POINTS); + glVertex3fv(p2.getValue()); + glEnd(); + + root->GLRender(action); + state->pop(); + } +} + +void SoRegPoint::generatePrimitives(SoAction* action) +{ +} + +/** + * Sets the bounding box of the probe to \a box and its center to \a center. + */ +void SoRegPoint::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) +{ + root->doAction(action); + if (action->getTypeId().isDerivedFrom(SoGetBoundingBoxAction::getClassTypeId())) + static_cast(action)->resetCenter(); + + SbVec3f p1 = base.getValue(); + SbVec3f p2 = p1 + normal.getValue() * length.getValue(); + + box.extendBy(p1); + box.extendBy(p2); + + center = box.getCenter(); +} + +void SoRegPoint::notify(SoNotList * node) +{ + SoField * f = node->getLastField(); + if (f == &this->base || f == &this->normal || f == &this->length) { + SoTranslation* move = static_cast(root->getChild(0)); + move->translation.setValue(base.getValue() + normal.getValue() * length.getValue()); + } + else if (f == &this->color) { + SoSeparator* sub = static_cast(root->getChild(1)); + SoBaseColor* col = static_cast(sub->getChild(0)); + col->rgb = this->color.getValue(); + } + else if (f == &this->text) { + SoSeparator* sub = static_cast(root->getChild(1)); + SoText2* label = static_cast(sub->getChild(2)); + label->string = this->text.getValue(); + } + + SoShape::notify(node); +} diff --git a/src/Gui/SoAxisCrossKit.h b/src/Gui/SoAxisCrossKit.h index bb1a24934e..488c51ee82 100644 --- a/src/Gui/SoAxisCrossKit.h +++ b/src/Gui/SoAxisCrossKit.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include class SbViewport; class SoState; @@ -84,6 +86,33 @@ private: virtual ~SoAxisCrossKit(); }; +class GuiExport SoRegPoint : public SoShape { + typedef SoShape inherited; + + SO_NODE_HEADER(SoRegPoint); + +public: + static void initClass(); + SoRegPoint(); + + void notify(SoNotList * node); + + SoSFVec3f base; + SoSFVec3f normal; + SoSFFloat length; + SoSFColor color; + SoSFString text; + +protected: + virtual ~SoRegPoint(); + virtual void GLRender(SoGLRenderAction *action); + virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er); + virtual void generatePrimitives(SoAction *action); + +private: + SoSeparator* root; +}; + } // namespace Gui #endif // GUI_SOSHAPESCALE_H diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index 46435be068..ddf074ca11 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -95,6 +95,7 @@ void Gui::SoFCDB::init() TranslateManip ::initClass(); SoShapeScale ::initClass(); SoAxisCrossKit ::initClass(); + SoRegPoint ::initClass(); SoDrawingGrid ::initClass(); PropertyItem ::init(); diff --git a/src/Gui/SplitView3DInventor.cpp b/src/Gui/SplitView3DInventor.cpp index f80532af86..7014aaa77a 100644 --- a/src/Gui/SplitView3DInventor.cpp +++ b/src/Gui/SplitView3DInventor.cpp @@ -41,42 +41,29 @@ using namespace Gui; -TYPESYSTEM_SOURCE_ABSTRACT(Gui::SplitView3DInventor,Gui::MDIView); +TYPESYSTEM_SOURCE_ABSTRACT(Gui::AbstractSplitView,Gui::MDIView); -SplitView3DInventor::SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags) +AbstractSplitView::AbstractSplitView(Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags) : MDIView(pcDocument,parent, wflags) { // important for highlighting setMouseTracking(true); - +} + +AbstractSplitView::~AbstractSplitView() +{ + hGrp->Detach(this); + for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it) { + delete *it; + } +} + +void AbstractSplitView::setupSettings() +{ // attach Parameter Observer hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); hGrp->Attach(this); - QSplitter* mainSplitter=0; - - if (views <= 3) { - mainSplitter = new QSplitter(Qt::Horizontal, this); - _viewer.push_back(new View3DInventorViewer(mainSplitter)); - _viewer.push_back(new View3DInventorViewer(mainSplitter)); - if (views==3) - _viewer.push_back(new View3DInventorViewer(mainSplitter)); - } - else { - mainSplitter = new QSplitter(Qt::Vertical, this); - QSplitter *topSplitter = new QSplitter(Qt::Horizontal, mainSplitter); - QSplitter *botSplitter = new QSplitter(Qt::Horizontal, mainSplitter); - _viewer.push_back(new View3DInventorViewer(topSplitter)); - _viewer.push_back(new View3DInventorViewer(topSplitter)); - for (int i=2;isetOpaqueResize( true ); - botSplitter->setOpaqueResize( true ); - } - - mainSplitter->show(); - setCentralWidget(mainSplitter); - // apply the user settings OnChange(*hGrp,"EyeDistance"); OnChange(*hGrp,"CornerCoordSystem"); @@ -100,21 +87,13 @@ SplitView3DInventor::SplitView3DInventor(int views, Gui::Document* pcDocument, Q OnChange(*hGrp,"NavigationStyle"); } -SplitView3DInventor::~SplitView3DInventor() -{ - hGrp->Detach(this); - for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it) { - delete *it; - } -} - -View3DInventorViewer* SplitView3DInventor::getViewer(unsigned int n) const +View3DInventorViewer* AbstractSplitView::getViewer(unsigned int n) const { return (_viewer.size() > n ? _viewer[n] : 0); } /// Observer message from the ParameterGrp -void SplitView3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason) +void AbstractSplitView::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason) { const ParameterGrp& rGrp = static_cast(rCaller); if (strcmp(Reason,"HeadlightColor") == 0) { @@ -266,17 +245,17 @@ void SplitView3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterG } } -void SplitView3DInventor::onUpdate(void) +void AbstractSplitView::onUpdate(void) { update(); } -const char *SplitView3DInventor::getName(void) const +const char *AbstractSplitView::getName(void) const { return "SplitView3DInventor"; } -bool SplitView3DInventor::onMsg(const char* pMsg, const char** ppReturn) +bool AbstractSplitView::onMsg(const char* pMsg, const char** ppReturn) { if (strcmp("ViewFit",pMsg) == 0 ) { for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it) @@ -346,7 +325,7 @@ bool SplitView3DInventor::onMsg(const char* pMsg, const char** ppReturn) return false; } -bool SplitView3DInventor::onHasMsg(const char* pMsg) const +bool AbstractSplitView::onHasMsg(const char* pMsg) const { if (strcmp("ViewFit",pMsg) == 0) { return true; @@ -375,7 +354,46 @@ bool SplitView3DInventor::onHasMsg(const char* pMsg) const return false; } -void SplitView3DInventor::setCursor(const QCursor& aCursor) +void AbstractSplitView::setCursor(const QCursor& aCursor) { //_viewer->getWidget()->setCursor(aCursor); } + +// ------------------------------------------------------ + +TYPESYSTEM_SOURCE_ABSTRACT(Gui::SplitView3DInventor, Gui::AbstractSplitView); + +SplitView3DInventor::SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags) + : AbstractSplitView(pcDocument,parent, wflags) +{ + QSplitter* mainSplitter=0; + + if (views <= 3) { + mainSplitter = new QSplitter(Qt::Horizontal, this); + _viewer.push_back(new View3DInventorViewer(mainSplitter)); + _viewer.push_back(new View3DInventorViewer(mainSplitter)); + if (views==3) + _viewer.push_back(new View3DInventorViewer(mainSplitter)); + } + else { + mainSplitter = new QSplitter(Qt::Vertical, this); + QSplitter *topSplitter = new QSplitter(Qt::Horizontal, mainSplitter); + QSplitter *botSplitter = new QSplitter(Qt::Horizontal, mainSplitter); + _viewer.push_back(new View3DInventorViewer(topSplitter)); + _viewer.push_back(new View3DInventorViewer(topSplitter)); + for (int i=2;isetOpaqueResize( true ); + botSplitter->setOpaqueResize( true ); + } + + mainSplitter->show(); + setCentralWidget(mainSplitter); + + // apply the user settings + setupSettings(); +} + +SplitView3DInventor::~SplitView3DInventor() +{ +} diff --git a/src/Gui/SplitView3DInventor.h b/src/Gui/SplitView3DInventor.h index c4596e9a95..de7254ec49 100644 --- a/src/Gui/SplitView3DInventor.h +++ b/src/Gui/SplitView3DInventor.h @@ -36,13 +36,13 @@ class View3DInventorViewer; /** The SplitView3DInventor class allows to create a window with two or more Inventor views. * \author Werner Mayer */ -class GuiExport SplitView3DInventor : public MDIView,public ParameterGrp::ObserverType +class GuiExport AbstractSplitView : public MDIView, public ParameterGrp::ObserverType { TYPESYSTEM_HEADER(); public: - SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags=0); - ~SplitView3DInventor(); + AbstractSplitView(Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags=0); + ~AbstractSplitView(); virtual const char *getName(void) const; @@ -56,14 +56,27 @@ public: void setCursor(const QCursor&); +protected: + void setupSettings(); + protected: /// handle to the viewer parameter group ParameterGrp::handle hGrp; - -private: std::vector _viewer; }; +/** The SplitView3DInventor class allows to create a window with two or more Inventor views. + * \author Werner Mayer + */ +class GuiExport SplitView3DInventor : public AbstractSplitView +{ + TYPESYSTEM_HEADER(); + +public: + SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WFlags wflags=0); + ~SplitView3DInventor(); +}; + } // namespace Gui #endif //GUI_SPLITVIEW3DINVENTOR_H diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index d6b82d4abe..dc32d7dc7c 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -441,7 +441,8 @@ MenuItem* StdWorkbench::setupMenuBar() const edit->setCommand("&Edit"); *edit << "Std_Undo" << "Std_Redo" << "Separator" << "Std_Cut" << "Std_Copy" << "Std_Paste" << "Std_DuplicateSelection" << "Separator" - << "Std_Refresh" << "Std_SelectAll" << "Std_Delete" << "Std_Placement" + << "Std_Refresh" << "Std_SelectAll" << "Std_Delete" + << "Std_Placement" << "Std_Alignment" << "Std_Edit" << "Separator" << "Std_DlgPreferences"; // Standard views diff --git a/src/Mod/Complete/Gui/Workbench.cpp b/src/Mod/Complete/Gui/Workbench.cpp index 45a2faa030..80a0336ddf 100644 --- a/src/Mod/Complete/Gui/Workbench.cpp +++ b/src/Mod/Complete/Gui/Workbench.cpp @@ -132,7 +132,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const edit->setCommand("&Edit"); *edit << "Std_Undo" << "Std_Redo" << "Separator" << "Std_Cut" << "Std_Copy" << "Std_Paste" << "Std_DuplicateSelection" << "Separator" - << "Std_Refresh" << "Std_SelectAll" << "Std_Delete" << "Std_Placement" + << "Std_Refresh" << "Std_SelectAll" << "Std_Delete" + << "Std_Placement" << "Std_Alignment" << "Separator" << "Std_DlgPreferences"; // Standard views From 54f8375cde9ccc78d5471ebc01aba0d7fcf4e1d0 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 27 Mar 2012 12:36:11 -0300 Subject: [PATCH 043/351] Fixed #0000654 - Startpage translation --- src/Mod/Start/StartPage/StartPage.py | 647 ++++++++++++++------------- 1 file changed, 338 insertions(+), 309 deletions(-) diff --git a/src/Mod/Start/StartPage/StartPage.py b/src/Mod/Start/StartPage/StartPage.py index 26a573ba3d..4ae0511e11 100644 --- a/src/Mod/Start/StartPage/StartPage.py +++ b/src/Mod/Start/StartPage/StartPage.py @@ -1,4 +1,4 @@ -import os,FreeCAD,FreeCADGui,tempfile,time,zipfile,urllib,re +import os,FreeCAD,FreeCADGui,tempfile,time,zipfile,urllib,re,cStringIO from PyQt4 import QtGui from xml.etree.ElementTree import parse @@ -6,8 +6,19 @@ FreeCADGui.addLanguagePath(":/translations") FreeCADGui.updateLocale() def translate(context,text): - "convenience function for the Qt translator" - return str(QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).toUtf8()) + "convenience function for the Qt translator" + # return str(QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).toUtf8()) + u = QtGui.QApplication.translate(context, text, None, + QtGui.QApplication.UnicodeUTF8).toUtf8() + s = cStringIO.StringIO() + for i in u: + if ord(i) == 39: + s.write("\\'") + else: + s.write(i) + t = s.getvalue() + s.close() + return t # texts to be translated @@ -66,144 +77,164 @@ page = """ FreeCAD - Start page + + + @@ -269,204 +300,202 @@ page = """ """ def getWebExamples(): - return """ - """ + return """ + """ def getExamples(): - return """ - """ + return """ + """ def getLinks(): - return """ - """ + return """ + """ def getWorkbenches(): - return """ - -""" + return """ + """ def getInfo(filename): - "returns available file information" + "returns available file information" - def getLocalTime(timestamp): - "returns a local time from a timestamp" - - return time.strftime("%m/%d/%Y %H:%M:%S",time.localtime(timestamp)) + def getLocalTime(timestamp): + "returns a local time from a timestamp" + return time.strftime("%m/%d/%Y %H:%M:%S",time.localtime(timestamp)) - def getSize(size): - "returns a human-readable size" - - if size > 1024*1024: - hsize = str(size/(1024*1024)) + "Mb" - elif size > 1024: - hsize = str(size/1024) + "Kb" - else: - hsize = str(size) + "b" - return hsize - - html = '

'+os.path.basename(filename)+'

' - - if os.path.exists(filename): - # get normal file info - s = os.stat(filename) - html += "

" + text33 + " " + getSize(s.st_size) + "
" - html += text34 + " " + getLocalTime(s.st_ctime) + "
" - html += text35 + " " + getLocalTime(s.st_mtime) + "
" - html += "" + text36 + " " + filename + "

" - # get additional info from fcstd files - if os.path.splitext(filename)[1] in [".fcstd",".FcStd"]: - zfile=zipfile.ZipFile(filename) - files=zfile.namelist() - # check for meta-file if it's really a FreeCAD document - if files[0] == "Document.xml": - html += "

FreeCAD Standard File

" - image="thumbnails/Thumbnail.png" - if image in files: - image=zfile.read(image) - thumbfile = tempfile.mkstemp(suffix='.png')[1] - thumb = open(thumbfile,"wb") - thumb.write(image) - thumb.close() - html += '
' + def getSize(size): + "returns a human-readable size" + if size > 1024*1024: + hsize = str(size/(1024*1024)) + "Mb" + elif size > 1024: + hsize = str(size/1024) + "Kb" else: - html += "

" + text41 + "

" - - return html + hsize = str(size) + "b" + return hsize + + html = '

'+os.path.basename(filename)+'

' + + if os.path.exists(filename): + # get normal file info + s = os.stat(filename) + html += "

" + text33 + " " + getSize(s.st_size) + "
" + html += text34 + " " + getLocalTime(s.st_ctime) + "
" + html += text35 + " " + getLocalTime(s.st_mtime) + "
" + html += "" + text36 + " " + filename + "

" + # get additional info from fcstd files + if os.path.splitext(filename)[1] in [".fcstd",".FcStd"]: + zfile=zipfile.ZipFile(filename) + files=zfile.namelist() + # check for meta-file if it's really a FreeCAD document + if files[0] == "Document.xml": + html += "

FreeCAD Standard File

" + image="thumbnails/Thumbnail.png" + if image in files: + image=zfile.read(image) + thumbfile = tempfile.mkstemp(suffix='.png')[1] + thumb = open(thumbfile,"wb") + thumb.write(image) + thumb.close() + html += '
' + else: + html += "

" + text41 + "

" + + return html def getRecentFiles(): - "returns a list of 3 latest recent files" - - rf=FreeCAD.ParamGet("User parameter:BaseApp/Preferences/RecentFiles") - ct=rf.GetInt("RecentFiles") - html = '
    ' - for i in range(3): - if i < ct: - mr = rf.GetString("MRU%d" % (i)) - fn = os.path.basename(mr) - html += '
  • ' - html += fn - html += '
  • ' - html += '
' - return html + "returns a list of 3 latest recent files" + rf = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/RecentFiles") + ct = rf.GetInt("RecentFiles") + html = '
    ' + for i in range(3): + if i < ct: + mr = rf.GetString("MRU%d" % (i)) + fn = os.path.basename(mr) + html += '
  • ' + html += fn + html += '
  • ' + html += '
' + return html def getFeed(url,numitems=3): - "returns a html list with links from the given RSS feed url" - xml = parse(urllib.urlopen(url)).getroot() - items = [] - channel = xml.find('channel') - for element in channel.findall('item'): - items.append({ - 'title': element.find('title').text, - 'description': element.find('description').text, - 'link': element.find('link').text, - }) - if len(items) > numitems: - items = items[:numitems] - resp = '
    ' - for item in items: - descr = re.compile("style=\".*?\"").sub('',item['description']) - descr = re.compile("alt=\".*?\"").sub('',descr) - descr = re.compile("\"").sub('',descr) - d1 = re.findall("",descr)[0] - d2 = re.findall(".*?",descr)[0] - descr = "

    " + item['title'] + "

    " - descr += d1 + "
    " - descr += d2 - resp += '
  • ' - resp += item['title'] - resp += '
  • ' - resp += '
' - print resp - return resp + "returns a html list with links from the given RSS feed url" + xml = parse(urllib.urlopen(url)).getroot() + items = [] + channel = xml.find('channel') + for element in channel.findall('item'): + items.append({'title': element.find('title').text, + 'description': element.find('description').text, + 'link': element.find('link').text}) + if len(items) > numitems: + items = items[:numitems] + resp = '
    ' + for item in items: + descr = re.compile("style=\".*?\"").sub('',item['description']) + descr = re.compile("alt=\".*?\"").sub('',descr) + descr = re.compile("\"").sub('',descr) + d1 = re.findall("",descr)[0] + d2 = re.findall(".*?",descr)[0] + descr = "

    " + item['title'] + "

    " + descr += d1 + "
    " + descr += d2 + resp += '
  • ' + resp += item['title'] + resp += '
  • ' + resp += '
' + print resp + return resp def getCustomBlocks(): - "fetches custom html files in FreeCAD user dir" - output = "" - return output + "fetches custom html files in FreeCAD user dir" + output = "" + return output def handle(): - "returns the complete html startpage" - - # add recent files - recentfiles = getRecentFiles() - html = page.replace("recentfiles",recentfiles) + "returns the complete html startpage" + + # add recent files + recentfiles = getRecentFiles() + html = page.replace("recentfiles",recentfiles) - # add default workbenches - html = html.replace("defaultworkbenches",getWorkbenches()) + # add default workbenches + html = html.replace("defaultworkbenches",getWorkbenches()) - # add default web links - html = html.replace("defaultlinks",getLinks()) + # add default web links + html = html.replace("defaultlinks",getLinks()) - # add default examples - html = html.replace("defaultexamples",getExamples()) + # add default examples + html = html.replace("defaultexamples",getExamples()) - # add web examples - #html = html.replace("webexamples",getWebExamples()) + # add web examples + #html = html.replace("webexamples",getWebExamples()) + + # add custom blocks + html = html.replace("customblocks",getCustomBlocks()) + + return html - # add custom blocks - html = html.replace("customblocks",getCustomBlocks()) - - return html - From 334aace3a9acc3d0e6934edf96b004230de72da9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 27 Mar 2012 19:43:39 +0200 Subject: [PATCH 044/351] Fix Makefile.am --- src/Gui/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Gui/Makefile.am b/src/Gui/Makefile.am index 1cf4fcc163..c714f4913b 100644 --- a/src/Gui/Makefile.am +++ b/src/Gui/Makefile.am @@ -48,6 +48,7 @@ BUILT_SOURCES=\ moc_HelpView.cpp \ moc_InputVector.cpp \ moc_MainWindow.cpp \ + moc_ManualAlignment.cpp \ moc_NetworkRetriever.cpp \ moc_OnlineDocumentation.cpp \ moc_Placement.cpp \ @@ -282,6 +283,8 @@ libFreeCADGui_la_SOURCES=\ Placement.h \ Macro.cpp \ MainWindow.cpp \ + ManualAlignment.cpp \ + ManualAlignment.h \ MDIView.cpp \ MenuManager.cpp \ MergeDocuments.cpp \ From c1886bf24d935ac799651af45c9b163293c62bea Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 28 Mar 2012 15:07:28 +0200 Subject: [PATCH 045/351] Fix crash in TopoShapeface.getWire() --- src/Mod/Part/App/TopoShapeFacePyImp.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Mod/Part/App/TopoShapeFacePyImp.cpp b/src/Mod/Part/App/TopoShapeFacePyImp.cpp index 9c65d51f28..ab03bb14c8 100644 --- a/src/Mod/Part/App/TopoShapeFacePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeFacePyImp.cpp @@ -550,14 +550,16 @@ Py::Tuple TopoShapeFacePy::getParameterRange(void) const Py::Object TopoShapeFacePy::getWire(void) const { - TopoDS_Shape clSh = getTopoShapePtr()->_Shape; + const TopoDS_Shape& clSh = getTopoShapePtr()->_Shape; + if (clSh.IsNull()) + throw Py::Exception("Null shape"); if (clSh.ShapeType() == TopAbs_FACE) { TopoDS_Face clFace = (TopoDS_Face&)clSh; TopoDS_Wire clWire = ShapeAnalysis::OuterWire(clFace); return Py::Object(new TopoShapeWirePy(new TopoShape(clWire)),true); } else - throw "Internal error, TopoDS_Shape is not a face!"; + throw Py::Exception("Internal error, TopoDS_Shape is not a face!"); return Py::Object(); } From 9656a989b2f11db03f182aae5065b3506e638c22 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 28 Mar 2012 10:39:10 -0300 Subject: [PATCH 046/351] Added 0000650 - Placement.isNull() function --- src/Base/PlacementPy.xml | 8 ++++++++ src/Base/PlacementPyImp.cpp | 33 +++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/Base/PlacementPy.xml b/src/Base/PlacementPy.xml index 3ccb012a32..9a78c23671 100644 --- a/src/Base/PlacementPy.xml +++ b/src/Base/PlacementPy.xml @@ -75,6 +75,14 @@ Placement(Base, Axis, Angle) -- define position and rotation + + + + isNull() -> Bool + returns True if the placement has no displacement and no rotation + + + Vector to the Base Position of the Placement diff --git a/src/Base/PlacementPyImp.cpp b/src/Base/PlacementPyImp.cpp index 7e1dece97c..6a3f7956e9 100644 --- a/src/Base/PlacementPyImp.cpp +++ b/src/Base/PlacementPyImp.cpp @@ -83,9 +83,9 @@ int PlacementPy::PyInit(PyObject* args, PyObject* /*kwd*/) PyObject* d; double angle; if (PyArg_ParseTuple(args, "O!O!d", &(Base::VectorPy::Type), &o, - &(Base::VectorPy::Type), &d, &angle)) { - // NOTE: The first parameter defines the translation, the second the rotation axis - // and the last parameter defines the rotation angle in degree. + &(Base::VectorPy::Type), &d, &angle)) { + // NOTE: The first parameter defines the translation, the second the rotation axis + // and the last parameter defines the rotation angle in degree. Base::Rotation rot(static_cast(d)->value(), angle/180.0*D_PI); *getPlacementPtr() = Base::Placement(static_cast(o)->value(),rot); return 0; @@ -145,13 +145,13 @@ PyObject* PlacementPy::multVec(PyObject * args) getPlacementPtr()->multVec(pnt, pnt); return new VectorPy(new Vector3d(pnt)); } - -PyObject* PlacementPy::copy(PyObject * args) -{ - if (!PyArg_ParseTuple(args, "")) - return NULL; - return new PlacementPy(new Placement(*getPlacementPtr())); -} + +PyObject* PlacementPy::copy(PyObject * args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + return new PlacementPy(new Placement(*getPlacementPtr())); +} PyObject* PlacementPy::toMatrix(PyObject * args) { @@ -169,6 +169,19 @@ PyObject* PlacementPy::inverse(PyObject * args) return new PlacementPy(new Placement(p)); } +PyObject* PlacementPy::isNull(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + Base::Vector3d pos = getPlacementPtr()->getPosition(); + Base::Rotation rot = getPlacementPtr()->getRotation(); + Base::Vector3d nullvec(0,0,0); + Base::Rotation nullrot(0,0,0,1); + Base::Rotation nullrotinv(0,0,0,-1); + bool null = (pos == nullvec) & ((rot == nullrot) | (rot == nullrotinv)); + return Py_BuildValue("O", (null ? Py_True : Py_False)); +} + Py::Object PlacementPy::getBase(void) const { return Py::Vector(getPlacementPtr()->getPosition()); From ee3201793c8b08f6a5445dbda3cc6de54aab5985 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 28 Mar 2012 10:45:17 -0300 Subject: [PATCH 047/351] Fixed 000655 - Draft dimension default size --- src/Mod/Draft/DraftTools.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 6153ee32f1..f5c056ed78 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -80,6 +80,7 @@ if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/").HasGroup("Dra p.SetBool("alwaysSnap",1) p.SetBool("showSnapBar",1) p.SetUnsigned("constructioncolor",746455039) + p.SetFloat("textheight",0.2) #--------------------------------------------------------------------------- # General functions From 6775e67d9078a0387bae7d2f3bcd0258edcf9de2 Mon Sep 17 00:00:00 2001 From: jriegel Date: Wed, 28 Mar 2012 18:29:27 +0200 Subject: [PATCH 048/351] fix in libPack install for windows --- src/WindowsInstaller/LibPack.wxs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/WindowsInstaller/LibPack.wxs b/src/WindowsInstaller/LibPack.wxs index cbe94cdc66..37b4da8ce6 100644 --- a/src/WindowsInstaller/LibPack.wxs +++ b/src/WindowsInstaller/LibPack.wxs @@ -71,6 +71,10 @@ + + + + + + inkscape:version="0.48.3.1 r9886" + sodipodi:docname="edit-select-all.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.1"> - + id="defs2982"> + id="linearGradient4590"> + id="stop4592" /> + id="stop4594" /> + + + + + + + + - - - - - - - - - - + gradientTransform="matrix(0.6028459,1.0471639,-1.9794021,1.1395295,127.9588,-74.456907)" + cx="51.328892" + cy="31.074146" + fx="51.328892" + fy="31.074146" + r="19.571428" /> + + + xlink:href="#linearGradient3864" + id="radialGradient2890" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.58019421,1.0078171,-1.9050269,1.0967121,-8.5316607,-197.0902)" + cx="51.328892" + cy="31.074146" + fx="51.328892" + fy="31.074146" + r="19.571428" /> + + + inkscape:collect="always" + xlink:href="#linearGradient3811" + id="linearGradient3817" + x1="36.870125" + y1="30.196993" + x2="3.3695574" + y2="39.373768" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.27764843,-1.1190823,1.1190823,0.27764843,-10.424279,50.285999)" /> + + + id="stop3813-8" /> - + id="stop3815-7" /> + gradientTransform="translate(0,8)" /> + + + + + + + + + + + + inkscape:window-height="758" + inkscape:window-x="0" + inkscape:window-y="19" + inkscape:window-maximized="0" /> + id="metadata2985"> image/svg+xml - Select All - - - - Andreas Nilsson - - - - - select - all - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/src/Gui/Icons/edit-select-box.svg b/src/Gui/Icons/edit-select-box.svg new file mode 100755 index 0000000000..abaf58cbe0 --- /dev/null +++ b/src/Gui/Icons/edit-select-box.svg @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/src/Gui/Icons/resource.qrc b/src/Gui/Icons/resource.qrc index 82548cd396..2114905a6d 100644 --- a/src/Gui/Icons/resource.qrc +++ b/src/Gui/Icons/resource.qrc @@ -43,6 +43,7 @@ edit-delete.svg edit-paste.svg edit-select-all.svg + edit-select-box.svg edit-redo.svg edit-undo.svg edit-edit.svg From a6aa5d1bd81329f3a4ab5d89d5d238faa97725ce Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 28 Apr 2012 18:05:07 -0300 Subject: [PATCH 152/351] Fixed bug in Arch Axes --- src/Mod/Arch/ArchAxis.py | 98 +++++++++++++++++++++----------------- src/Mod/Draft/DraftSnap.py | 1 + 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index 367ec47880..a56a50ff26 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -104,8 +104,6 @@ class _ViewProviderAxis: vobj.addProperty("App::PropertyEnumeration","NumerationStyle","Base", "The numeration style") vobj.NumerationStyle = ["1,2,3","01,02,03","001,002,003","A,B,C","a,b,c","I,II,III","L0,L1,L2"] vobj.Proxy = self - self.Object = vobj.Object - self.ViewObject = vobj vobj.BubbleSize = .1 vobj.LineWidth = 1 vobj.LineColor = (0.13,0.15,0.37) @@ -119,6 +117,7 @@ class _ViewProviderAxis: def attach(self, vobj): self.ViewObject = vobj + self.Object = vobj.Object self.bubbles = None def getNumber(self,num): @@ -162,48 +161,59 @@ class _ViewProviderAxis: def makeBubbles(self): import Part - rn = self.ViewObject.RootNode.getChild(2).getChild(0).getChild(0) - if self.bubbles: - rn.removeChild(self.bubbles) - self.bubbles = None - self.bubbles = coin.SoSeparator() - isep = coin.SoSeparator() - self.bubblestyle = coin.SoDrawStyle() - self.bubblestyle.linePattern = 0xffff - self.bubbles.addChild(self.bubblestyle) - for i in range(len(self.ViewObject.Object.Distances)): - invpl = self.ViewObject.Object.Placement.inverse() - verts = self.ViewObject.Object.Shape.Edges[i].Vertexes - p1 = invpl.multVec(verts[0].Point) - p2 = invpl.multVec(verts[1].Point) - dv = p2.sub(p1) - dv.normalize() - rad = self.ViewObject.BubbleSize - center = p2.add(dv.scale(rad,rad,rad)) - ts = Part.makeCircle(rad,center).writeInventor() - cin = coin.SoInput() - cin.setBuffer(ts) - cob = coin.SoDB.readAll(cin) - co = cob.getChild(1).getChild(0).getChild(2) - li = cob.getChild(1).getChild(0).getChild(3) - self.bubbles.addChild(co) - self.bubbles.addChild(li) - st = coin.SoSeparator() - tr = coin.SoTransform() - tr.translation.setValue((center.x,center.y-rad/4,center.z)) - fo = coin.SoFont() - fo.name = "Arial,Sans" - fo.size = rad*100 - tx = coin.SoText2() - tx.justification = coin.SoText2.CENTER - tx.string = self.getNumber(i) - st.addChild(tr) - st.addChild(fo) - st.addChild(tx) - isep.addChild(st) - self.bubbles.addChild(isep) - rn.addChild(self.bubbles) - + + def getNode(): + # make sure we already have the complete node built + r = self.ViewObject.RootNode + if r.getChildren().getLength() > 2: + if r.getChild(2).getChildren().getLength() > 0: + if r.getChild(2).getChild(0).getChildren().getLength() > 0: + return self.ViewObject.RootNode.getChild(2).getChild(0).getChild(0) + return None + + rn = getNode() + if rn: + if self.bubbles: + rn.removeChild(self.bubbles) + self.bubbles = None + self.bubbles = coin.SoSeparator() + isep = coin.SoSeparator() + self.bubblestyle = coin.SoDrawStyle() + self.bubblestyle.linePattern = 0xffff + self.bubbles.addChild(self.bubblestyle) + for i in range(len(self.ViewObject.Object.Distances)): + invpl = self.ViewObject.Object.Placement.inverse() + verts = self.ViewObject.Object.Shape.Edges[i].Vertexes + p1 = invpl.multVec(verts[0].Point) + p2 = invpl.multVec(verts[1].Point) + dv = p2.sub(p1) + dv.normalize() + rad = self.ViewObject.BubbleSize + center = p2.add(dv.scale(rad,rad,rad)) + ts = Part.makeCircle(rad,center).writeInventor() + cin = coin.SoInput() + cin.setBuffer(ts) + cob = coin.SoDB.readAll(cin) + co = cob.getChild(1).getChild(0).getChild(2) + li = cob.getChild(1).getChild(0).getChild(3) + self.bubbles.addChild(co) + self.bubbles.addChild(li) + st = coin.SoSeparator() + tr = coin.SoTransform() + tr.translation.setValue((center.x,center.y-rad/4,center.z)) + fo = coin.SoFont() + fo.name = "Arial,Sans" + fo.size = rad*100 + tx = coin.SoText2() + tx.justification = coin.SoText2.CENTER + tx.string = self.getNumber(i) + st.addChild(tr) + st.addChild(fo) + st.addChild(tx) + isep.addChild(st) + self.bubbles.addChild(isep) + rn.addChild(self.bubbles) + def updateData(self, obj, prop): if prop == "Shape": self.makeBubbles() diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index c4a3e7139d..4ded2583db 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -736,6 +736,7 @@ class Snapper: import inspect self.pt = None + self.lastSnappedObject = None self.ui = FreeCADGui.draftToolBar self.view = Draft.get3DView() From add5f9d154f28a2976ec8a4fd7f58ac7839df9ab Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 30 Apr 2012 11:36:48 +0200 Subject: [PATCH 153/351] 0000687: sandbox module automake patch --- src/Gui/Icons/Makefile.am | 1 + src/Mod/Sandbox/Gui/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Gui/Icons/Makefile.am b/src/Gui/Icons/Makefile.am index 70c30f0f4b..9be01aa6cb 100644 --- a/src/Gui/Icons/Makefile.am +++ b/src/Gui/Icons/Makefile.am @@ -58,6 +58,7 @@ EXTRA_DIST = \ edit-delete.svg \ edit-paste.svg \ edit-select-all.svg \ + edit-select-box.svg \ edit-redo.svg \ edit-undo.svg \ preferences-system.svg \ diff --git a/src/Mod/Sandbox/Gui/Makefile.am b/src/Mod/Sandbox/Gui/Makefile.am index 87a548f3de..c936b9cc30 100644 --- a/src/Mod/Sandbox/Gui/Makefile.am +++ b/src/Mod/Sandbox/Gui/Makefile.am @@ -13,7 +13,7 @@ libSandboxGui_la_LDFLAGS = -L../../../Base -L../../../App -L../../../Gui -L../.. $(sim_ac_coin_ldflags) $(sim_ac_coin_libs) $(sim_ac_soqt_ldflags) $(sim_ac_soqt_libs) \ $(QT_LIBS) $(all_libraries) -version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@ -libSandboxGui_la_CPPFLAGS = -DSandboxAppExport= -DSandboxGuiExport= +libSandboxGui_la_CPPFLAGS = $(sim_ac_coin_cppflags) -DSandboxAppExport= -DSandboxGuiExport= libSandboxGui_la_LIBADD = \ @BOOST_SYSTEM_LIB@ \ From 5586348adef2a9f227a8eb3c9b5467a61f579842 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 30 Apr 2012 17:15:43 +0200 Subject: [PATCH 154/351] locale stuff --- src/Gui/DlgGeneralImp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Gui/DlgGeneralImp.cpp b/src/Gui/DlgGeneralImp.cpp index a908d04b9b..e1e5302b30 100644 --- a/src/Gui/DlgGeneralImp.cpp +++ b/src/Gui/DlgGeneralImp.cpp @@ -180,7 +180,12 @@ void DlgGeneralImp::loadSettings() TStringList list = Translator::instance()->supportedLanguages(); for (TStringList::iterator it = list.begin(); it != list.end(); ++it, index++) { QByteArray lang = it->c_str(); +#if QT_VERSION >= 0x040800 + QLocale locale(QString::fromAscii(lang.constData())); + Languages->addItem(locale.nativeCountryName(), lang); +#else Languages->addItem(Gui::Translator::tr(lang.constData()), lang); +#endif if (language == lang) { Languages->setCurrentIndex(index); } From 95cf62b9901bfe5b9184282a083504b1a70b89c5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 30 Apr 2012 18:02:22 +0200 Subject: [PATCH 155/351] locale stuff --- src/Gui/DlgGeneralImp.cpp | 23 +++++++++++++++-------- src/Gui/Language/Translator.cpp | 16 ++++++++++++++++ src/Gui/Language/Translator.h | 2 ++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/Gui/DlgGeneralImp.cpp b/src/Gui/DlgGeneralImp.cpp index e1e5302b30..1c52b875f4 100644 --- a/src/Gui/DlgGeneralImp.cpp +++ b/src/Gui/DlgGeneralImp.cpp @@ -177,19 +177,26 @@ void DlgGeneralImp::loadSettings() QByteArray language = hGrp->GetASCII("Language", (const char*)lang.toAscii()).c_str(); Languages->addItem(Gui::Translator::tr("English"), QByteArray("English")); int index = 1; - TStringList list = Translator::instance()->supportedLanguages(); - for (TStringList::iterator it = list.begin(); it != list.end(); ++it, index++) { - QByteArray lang = it->c_str(); #if QT_VERSION >= 0x040800 - QLocale locale(QString::fromAscii(lang.constData())); - Languages->addItem(locale.nativeCountryName(), lang); -#else - Languages->addItem(Gui::Translator::tr(lang.constData()), lang); -#endif + TStringList list = Translator::instance()->supportedLocales(); + for (TStringList::iterator it = list.begin(); it != list.end(); ++it, index++) { + QLocale locale(QString::fromAscii(it->c_str())); + QByteArray lang = QLocale::languageToString(locale.language()).toAscii(); + Languages->addItem(locale.nativeLanguageName(), lang); if (language == lang) { Languages->setCurrentIndex(index); } } +#else + TStringList list = Translator::instance()->supportedLanguages(); + for (TStringList::iterator it = list.begin(); it != list.end(); ++it, index++) { + QByteArray lang = it->c_str(); + Languages->addItem(Gui::Translator::tr(lang.constData()), lang); + if (language == lang) { + Languages->setCurrentIndex(index); + } + } +#endif int size = QApplication::style()->pixelMetric(QStyle::PM_ToolBarIconSize); int current = getMainWindow()->iconSize().width(); diff --git a/src/Gui/Language/Translator.cpp b/src/Gui/Language/Translator.cpp index b32401875f..0b7103f6e3 100644 --- a/src/Gui/Language/Translator.cpp +++ b/src/Gui/Language/Translator.cpp @@ -174,6 +174,22 @@ TStringList Translator::supportedLanguages() const return languages; } +TStringList Translator::supportedLocales() const +{ + // List all .qm files + TStringList languages; + QDir dir(QLatin1String(":/translations")); + for (std::map::const_iterator it = d->mapLanguageTopLevelDomain.begin(); + it != d->mapLanguageTopLevelDomain.end(); ++it) { + QString filter = QString::fromAscii("*_%1.qm").arg(QLatin1String(it->second.c_str())); + QStringList fileNames = dir.entryList(QStringList(filter), QDir::Files, QDir::Name); + if (!fileNames.isEmpty()) + languages.push_back(it->second); + } + + return languages; +} + void Translator::activateLanguage (const char* lang) { removeTranslators(); // remove the currently installed translators diff --git a/src/Gui/Language/Translator.h b/src/Gui/Language/Translator.h index 7ce7905bb8..2bccff06e1 100644 --- a/src/Gui/Language/Translator.h +++ b/src/Gui/Language/Translator.h @@ -65,6 +65,8 @@ public: std::string activeLanguage() const; /** Returns a list of supported languages. */ TStringList supportedLanguages() const; + /** Returns a list of supported locales. */ + TStringList supportedLocales() const; /** Adds a path where localization files can be found */ void addPath(const QString& path); From da1a42e2ee858da886fd40e2e600fc9f0d1cc299 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 30 Apr 2012 18:30:29 +0200 Subject: [PATCH 156/351] locale stuff --- src/Gui/DlgGeneralImp.cpp | 34 ++++++++++++++++----------------- src/Gui/Language/Translator.cpp | 6 +++--- src/Gui/Language/Translator.h | 5 +++-- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Gui/DlgGeneralImp.cpp b/src/Gui/DlgGeneralImp.cpp index 1c52b875f4..920baaa0ca 100644 --- a/src/Gui/DlgGeneralImp.cpp +++ b/src/Gui/DlgGeneralImp.cpp @@ -175,28 +175,26 @@ void DlgGeneralImp::loadSettings() ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General"); QString lang = QLocale::languageToString(QLocale::system().language()); QByteArray language = hGrp->GetASCII("Language", (const char*)lang.toAscii()).c_str(); - Languages->addItem(Gui::Translator::tr("English"), QByteArray("English")); int index = 1; + Languages->addItem(QString::fromAscii("English"), QByteArray("English")); + TStringMap list = Translator::instance()->supportedLocales(); + for (TStringMap::iterator it = list.begin(); it != list.end(); ++it, index++) { + QLocale locale(QString::fromAscii(it->second.c_str())); + QByteArray lang = it->first.c_str(); + QString langname = QString::fromAscii(lang.constData()); #if QT_VERSION >= 0x040800 - TStringList list = Translator::instance()->supportedLocales(); - for (TStringList::iterator it = list.begin(); it != list.end(); ++it, index++) { - QLocale locale(QString::fromAscii(it->c_str())); - QByteArray lang = QLocale::languageToString(locale.language()).toAscii(); - Languages->addItem(locale.nativeLanguageName(), lang); - if (language == lang) { - Languages->setCurrentIndex(index); + QString native = locale.nativeLanguageName(); + if (!native.isEmpty()) { + if (native[0].isLetter()) + native[0] = native[0].toUpper(); + langname = native; } - } -#else - TStringList list = Translator::instance()->supportedLanguages(); - for (TStringList::iterator it = list.begin(); it != list.end(); ++it, index++) { - QByteArray lang = it->c_str(); - Languages->addItem(Gui::Translator::tr(lang.constData()), lang); - if (language == lang) { - Languages->setCurrentIndex(index); - } - } #endif + Languages->addItem(langname, lang); + if (language == lang) { + Languages->setCurrentIndex(index); + } + } int size = QApplication::style()->pixelMetric(QStyle::PM_ToolBarIconSize); int current = getMainWindow()->iconSize().width(); diff --git a/src/Gui/Language/Translator.cpp b/src/Gui/Language/Translator.cpp index 0b7103f6e3..d48c1ec3fc 100644 --- a/src/Gui/Language/Translator.cpp +++ b/src/Gui/Language/Translator.cpp @@ -174,17 +174,17 @@ TStringList Translator::supportedLanguages() const return languages; } -TStringList Translator::supportedLocales() const +TStringMap Translator::supportedLocales() const { // List all .qm files - TStringList languages; + TStringMap languages; QDir dir(QLatin1String(":/translations")); for (std::map::const_iterator it = d->mapLanguageTopLevelDomain.begin(); it != d->mapLanguageTopLevelDomain.end(); ++it) { QString filter = QString::fromAscii("*_%1.qm").arg(QLatin1String(it->second.c_str())); QStringList fileNames = dir.entryList(QStringList(filter), QDir::Files, QDir::Name); if (!fileNames.isEmpty()) - languages.push_back(it->second); + languages[it->first] = it->second; } return languages; diff --git a/src/Gui/Language/Translator.h b/src/Gui/Language/Translator.h index 2bccff06e1..30f4543c18 100644 --- a/src/Gui/Language/Translator.h +++ b/src/Gui/Language/Translator.h @@ -34,6 +34,7 @@ class QDir; namespace Gui { typedef std::list TStringList; +typedef std::map TStringMap; /** * The Translator class uses Qt's QTranslator objects to change the language of the application @@ -65,8 +66,8 @@ public: std::string activeLanguage() const; /** Returns a list of supported languages. */ TStringList supportedLanguages() const; - /** Returns a list of supported locales. */ - TStringList supportedLocales() const; + /** Returns a map of supported languages/locales. */ + TStringMap supportedLocales() const; /** Adds a path where localization files can be found */ void addPath(const QString& path); From 3baa98cd906484c7e9225d5845d426d05c2dd183 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 30 Apr 2012 16:24:14 -0300 Subject: [PATCH 157/351] Fixed 0000660: Draft radial dimensions --- src/Mod/Draft/Draft.py | 24 +++++++---- src/Mod/Draft/DraftSnap.py | 22 +++++----- src/Mod/Draft/DraftTools.py | 70 ++++++++++++++++---------------- src/Mod/Draft/draftlibs/fcgeo.py | 2 +- 4 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 381a34a5af..89cbb15fe2 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -451,13 +451,25 @@ def makeDimension(p1,p2,p3=None,p4=None): ''' obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Dimension") _Dimension(obj) + if gui: + _ViewProviderDimension(obj.ViewObject) if isinstance(p1,Vector) and isinstance(p2,Vector): obj.Start = p1 obj.End = p2 + if not p3: + p3 = p2.sub(p1) + p3.multiply(0.5) + p3 = p1.add(p3) elif isinstance(p2,int) and isinstance(p3,int): obj.Base = p1 - obj.LinkedVertices = [p2,p3] + obj.LinkedVertices = idx = [p2,p3] p3 = p4 + if not p3: + v1 = obj.Base.Shape.Vertexes[idx[0]].Point + v2 = obj.Base.Shape.Vertexes[idx[1]].Point + p3 = v2.sub(v1) + p3.multiply(0.5) + p3 = v1.add(p3) elif isinstance(p3,str): obj.Base = p1 if p3 == "radius": @@ -467,13 +479,10 @@ def makeDimension(p1,p2,p3=None,p4=None): obj.LinkedVertices = [p2,2,1] obj.ViewObject.Override = "ddim" p3 = p4 - if not p3: - p3 = p2.sub(p1) - p3.multiply(0.5) - p3 = p1.add(p3) + if not p3: + p3 = obj.Base.Shape.Edges[0].Curve.Center.add(Vector(1,0,0)) obj.Dimline = p3 if gui: - _ViewProviderDimension(obj.ViewObject) formatObject(obj) select(obj) FreeCAD.ActiveDocument.recompute() @@ -1806,7 +1815,8 @@ class _ViewProviderDimension: proj = ed.cross(Vector(0,0,1)) if not proj: norm = Vector(0,0,1) else: norm = fcvec.neg(p3.sub(p2).cross(proj)) - norm.normalize() + if not fcvec.isNull(norm): + norm.normalize() va = get3DView().getViewDirection() if va.getAngle(norm) < math.pi/2: norm = fcvec.neg(norm) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 4ded2583db..50a0b19ba6 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -71,6 +71,7 @@ class Snapper: self.grid = None self.constrainLine = None self.trackLine = None + self.snapInfo = None self.lastSnappedObject = None self.active = True self.trackers = [[],[],[],[]] # view, grid, snap, extline @@ -132,6 +133,7 @@ class Snapper: return point snaps = [] + self.snapInfo = None # type conversion if needed if isinstance(screenpos,list): @@ -186,7 +188,7 @@ class Snapper: point = self.getApparentPoint(screenpos[0],screenpos[1]) # check if we snapped to something - info = Draft.get3DView().getObjectInfo((screenpos[0],screenpos[1])) + self.snapInfo = Draft.get3DView().getObjectInfo((screenpos[0],screenpos[1])) # checking if parallel to one of the edges of the last objects or to a polar direction @@ -195,7 +197,7 @@ class Snapper: point,eline = self.snapToPolar(point,lastpoint) point,eline = self.snapToExtensions(point,lastpoint,constrain,eline) - if not info: + if not self.snapInfo: # nothing has been snapped, check fro grid snap if active: @@ -206,7 +208,7 @@ class Snapper: # we have an object to snap to - obj = FreeCAD.ActiveDocument.getObject(info['Object']) + obj = FreeCAD.ActiveDocument.getObject(self.snapInfo['Object']) if not obj: return cstr(point) @@ -219,12 +221,12 @@ class Snapper: if not active: # passive snapping - snaps = [self.snapToVertex(info)] + snaps = [self.snapToVertex(self.snapInfo)] else: # active snapping - comp = info['Component'] + comp = self.snapInfo['Component'] if (Draft.getType(obj) == "Wall") and not oldActive: edges = [] @@ -258,13 +260,13 @@ class Snapper: elif "Vertex" in comp: # directly snapped to a vertex - snaps.append(self.snapToVertex(info,active=True)) + snaps.append(self.snapToVertex(self.snapInfo,active=True)) elif comp == '': # workaround for the new view provider - snaps.append(self.snapToVertex(info,active=True)) + snaps.append(self.snapToVertex(self.snapInfo,active=True)) else: # all other cases (face, etc...) default to passive snap - snapArray = [self.snapToVertex(info)] + snapArray = [self.snapToVertex(self.snapInfo)] elif Draft.getType(obj) == "Dimension": # for dimensions we snap to their 3 points @@ -290,7 +292,7 @@ class Snapper: # calculating the nearest snap point shortest = 1000000000000000000 - origin = Vector(info['x'],info['y'],info['z']) + origin = Vector(self.snapInfo['x'],self.snapInfo['y'],self.snapInfo['z']) winner = [Vector(0,0,0),None,Vector(0,0,0)] for snap in snaps: # if snap[0] == None: print "debug: Snapper: 'i[0]' is 'None'" @@ -304,7 +306,7 @@ class Snapper: dv = point.sub(winner[2]) if (dv.Length > self.radius): if (not oldActive) and self.isEnabled("passive"): - winner = self.snapToVertex(info) + winner = self.snapToVertex(self.snapInfo) # setting the cursors if self.tracker: diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 1502a67752..e0e767564f 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -143,7 +143,7 @@ def getPoint(target,args,mobile=False,sym=False,workingplane=True): amod = hasMod(args,MODSNAP) cmod = hasMod(args,MODCONSTRAIN) point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod) - + info = FreeCADGui.Snapper.snapInfo # project onto working plane if needed if (not plane.weak) and workingplane: # working plane was explicitely selected - project onto it @@ -168,7 +168,7 @@ def getPoint(target,args,mobile=False,sym=False,workingplane=True): else: ui.displayPoint(point, target.node[-1], plane=plane, mask=mask) else: ui.displayPoint(point, plane=plane, mask=mask) - return point,ctrlPoint + return point,ctrlPoint,info def getSupport(args): "returns the supporting object and sets the working plane" @@ -436,7 +436,7 @@ class Line(Creator): self.finish() elif arg["Type"] == "SoLocation2Event": # mouse movement detection - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.ui.cross(True) self.linetrack.p2(point) elif arg["Type"] == "SoMouseButtonEvent": @@ -446,7 +446,7 @@ class Line(Creator): self.finish(False,cont=True) else: if not self.node: self.support = getSupport(arg) - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.pos = arg["Position"] self.node.append(point) self.linetrack.p1(point) @@ -551,7 +551,7 @@ class BSpline(Line): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.ui.cross(True) self.bsplinetrack.update(self.node + [point]) # Draw constraint tracker line. @@ -566,7 +566,7 @@ class BSpline(Line): self.finish(False,cont=True) else: if not self.node: self.support = getSupport(arg) - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.pos = arg["Position"] self.node.append(point) self.drawUpdate(point) @@ -739,7 +739,7 @@ class Rectangle(Creator): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - point,ctrlPoint = getPoint(self,arg,mobile=True) + point,ctrlPoint,info = getPoint(self,arg,mobile=True) self.rect.update(point) self.ui.cross(True) elif arg["Type"] == "SoMouseButtonEvent": @@ -748,7 +748,7 @@ class Rectangle(Creator): self.finish() else: if not self.node: self.support = getSupport(arg) - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.appendPoint(point) def numericInput(self,numx,numy,numz): @@ -840,7 +840,7 @@ class Arc(Creator): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen self.ui.cross(True) if self.center and fcvec.dist(point,self.center) > 0: @@ -871,10 +871,9 @@ class Arc(Creator): if not self.altdown: self.ui.cross(False) self.altdown = True - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - if snapped: - ob = self.doc.getObject(snapped['Object']) - num = int(snapped['Component'].lstrip('Edge'))-1 + if info: + ob = self.doc.getObject(info['Object']) + num = int(info['Component'].lstrip('Edge'))-1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) @@ -937,7 +936,7 @@ class Arc(Creator): elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen if self.center and fcvec.dist(point,self.center) > 0: viewdelta = fcvec.project(point.sub(self.center), plane.axis) @@ -1132,7 +1131,7 @@ class Polygon(Creator): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen self.ui.cross(True) if self.center and fcvec.dist(point,self.center) > 0: @@ -1197,7 +1196,7 @@ class Polygon(Creator): elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen if self.center and fcvec.dist(point,self.center) > 0: viewdelta = fcvec.project(point.sub(self.center), plane.axis) @@ -1317,10 +1316,10 @@ class Text(Creator): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,dtrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.node.append(point) self.ui.textUi() self.ui.textValue.setFocus() @@ -1452,7 +1451,7 @@ class Dimension(Creator): shift = hasMod(arg,MODCONSTRAIN) if self.arcmode or self.point2: setMod(arg,MODCONSTRAIN,False) - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.ui.cross(True) if hasMod(arg,MODALT) and (len(self.node)<3): self.ui.cross(False) @@ -1536,15 +1535,14 @@ class Dimension(Creator): self.dimtrack.update(self.node+[point]+[self.cont]) elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) if not self.node: self.support = getSupport(arg) if hasMod(arg,MODALT) and (len(self.node)<3): - snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) - print "snapped: ",snapped - if snapped: - ob = self.doc.getObject(snapped['Object']) - if 'Edge' in snapped['Component']: - num = int(snapped['Component'].lstrip('Edge'))-1 + print "snapped: ",info + if info: + ob = self.doc.getObject(info['Object']) + if 'Edge' in info['Component']: + num = int(info['Component'].lstrip('Edge'))-1 ed = ob.Shape.Edges[num] v1 = ed.Vertexes[0].Point v2 = ed.Vertexes[-1].Point @@ -1761,7 +1759,7 @@ class Move(Modifier): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.linetrack.p2(point) self.ui.cross(True) # Draw constraint tracker line. @@ -1778,7 +1776,7 @@ class Move(Modifier): if not hasMod(arg,MODALT): self.finish() elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) if (self.node == []): self.node.append(point) self.ui.isRelative.show() @@ -1922,7 +1920,7 @@ class Rotate(Modifier): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.ui.cross(True) # this is to make sure radius is what you see on screen if self.center and fcvec.dist(point,self.center): @@ -1977,7 +1975,7 @@ class Rotate(Modifier): elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) if self.center and fcvec.dist(point,self.center): viewdelta = fcvec.project(point.sub(self.center), plane.axis) if not fcvec.isNull(viewdelta): point = point.add(fcvec.neg(viewdelta)) @@ -2119,7 +2117,7 @@ class Offset(Modifier): self.finish() elif arg["Type"] == "SoLocation2Event": self.ui.cross(True) - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) if hasMod(arg,MODCONSTRAIN) and self.constrainSeg: dist = fcgeo.findPerpendicular(point,self.shape,self.constrainSeg[1]) e = self.shape.Edges[self.constrainSeg[1]] @@ -2663,7 +2661,7 @@ class Trimex(Modifier): self.shift = hasMod(arg,MODCONSTRAIN) self.alt = hasMod(arg,MODALT) wp = not(self.extrudeMode and self.shift) - self.point = getPoint(self,arg,workingplane=wp)[0] + self.point,info = getPoint(self,arg,workingplane=wp)[0] if hasMod(arg,MODSNAP): self.snapped = None else: self.snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) if self.extrudeMode: @@ -2929,7 +2927,7 @@ class Scale(Modifier): if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection - point,ctrlPoint = getPoint(self,arg,sym=True) + point,ctrlPoint,info = getPoint(self,arg,sym=True) self.linetrack.p2(point) self.ui.cross(True) # Draw constraint tracker line. @@ -2950,7 +2948,7 @@ class Scale(Modifier): if not hasMod(arg,MODALT): self.finish() elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): - point,ctrlPoint = getPoint(self,arg,sym=True) + point,ctrlPoint,info = getPoint(self,arg,sym=True) if (self.node == []): self.node.append(point) self.ui.isRelative.show() @@ -3205,7 +3203,7 @@ class Edit(Modifier): self.finish() elif arg["Type"] == "SoLocation2Event": #mouse movement detection if self.editing != None: - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) # Draw constraint tracker line. if hasMod(arg,MODCONSTRAIN): self.constraintrack.p1(point) @@ -3223,7 +3221,7 @@ class Edit(Modifier): sel = sel[0] if sel.ObjectName == self.obj.Name: if self.ui.addButton.isChecked(): - point,ctrlPoint = getPoint(self,arg) + point,ctrlPoint,info = getPoint(self,arg) self.pos = arg["Position"] self.addPoint(point) elif self.ui.delButton.isChecked(): diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/draftlibs/fcgeo.py index f2387afce0..bf9f53e185 100755 --- a/src/Mod/Draft/draftlibs/fcgeo.py +++ b/src/Mod/Draft/draftlibs/fcgeo.py @@ -1686,7 +1686,7 @@ def circlefrom1Line2Points(edge, p1, p2): v1 = p1.sub(s) v2 = p2.sub(s) projectedDist = math.sqrt(abs(v1.dot(v2))) - edgeDir = vec(edge); edgeDir.normailze() + edgeDir = vec(edge); edgeDir.normalize() projectedCen1 = Vector.add(s, fcvec.scale(edgeDir, projectedDist)) projectedCen2 = Vector.add(s, fcvec.scale(edgeDir, -projectedDist)) perpEdgeDir = edgeDir.cross(Vector(0,0,1)) From 7c0aaa5814eefd5672a731234e21e737b5c6dd14 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 1 May 2012 12:20:12 +0200 Subject: [PATCH 158/351] Do not override placement if shape is null --- src/Mod/Part/App/PartFeature.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index 508009317f..c9483f37c1 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -103,9 +103,12 @@ void Feature::onChanged(const App::Property* prop) } else { Base::Placement p; - p.fromMatrix(this->Shape.getShape().getTransform()); - if (p != this->Placement.getValue()) - this->Placement.setValue(p); + // shape must not be null to override the placement + if (!this->Shape.getValue().IsNull()) { + p.fromMatrix(this->Shape.getShape().getTransform()); + if (p != this->Placement.getValue()) + this->Placement.setValue(p); + } } } From 11358e1b86bfa09afdd2c9051d6851b0c1b8c900 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 1 May 2012 13:17:10 +0200 Subject: [PATCH 159/351] left hand helix --- src/Mod/Part/App/PrimitiveFeature.cpp | 11 ++++- src/Mod/Part/App/PrimitiveFeature.h | 4 ++ src/Mod/Part/App/TopoShape.cpp | 65 +++++++++++++++------------ src/Mod/Part/App/TopoShape.h | 2 +- src/Mod/Part/Gui/DlgPrimitives.cpp | 4 +- src/Mod/Part/Gui/DlgPrimitives.ui | 21 +++++++++ 6 files changed, 74 insertions(+), 33 deletions(-) diff --git a/src/Mod/Part/App/PrimitiveFeature.cpp b/src/Mod/Part/App/PrimitiveFeature.cpp index 2aef7aa077..0213ac04d1 100644 --- a/src/Mod/Part/App/PrimitiveFeature.cpp +++ b/src/Mod/Part/App/PrimitiveFeature.cpp @@ -100,7 +100,7 @@ void Primitive::onChanged(const App::Property* prop) // Do not support sphere, ellipsoid and torus because the creation // takes too long and thus is not feasible std::string grp = (prop->getGroup() ? prop->getGroup() : ""); - if (grp == "Plane" || grp == "Cylinder" || grp == "Cone"){ + if (grp == "Plane" || grp == "Cylinder" || grp == "Cone" || grp == "Helix") { try { App::DocumentObjectExecReturn *ret = recompute(); delete ret; @@ -585,6 +585,8 @@ App::DocumentObjectExecReturn *Torus::execute(void) PROPERTY_SOURCE(Part::Helix, Part::Primitive) +const char* Part::Helix::LocalCSEnums[]= {"Right-handed","Left-handed",NULL}; + Helix::Helix(void) { ADD_PROPERTY_TYPE(Pitch, (1.0),"Helix",App::Prop_None,"The pitch of the helix"); @@ -595,6 +597,8 @@ Helix::Helix(void) Radius.setConstraints(&floatRange); ADD_PROPERTY_TYPE(Angle,(0.0),"Helix",App::Prop_None,"If angle is > 0 a conical otherwise a cylindircal surface is used"); Angle.setConstraints(&apexRange); + ADD_PROPERTY_TYPE(LocalCoord,(long(0)),"Coordinate System",App::Prop_None,"Orientation of the local coordinate system of the helix"); + LocalCoord.setEnums(LocalCSEnums); } short Helix::mustExecute() const @@ -607,6 +611,8 @@ short Helix::mustExecute() const return 1; if (Angle.isTouched()) return 1; + if (LocalCoord.isTouched()) + return 1; return Primitive::mustExecute(); } @@ -617,8 +623,9 @@ App::DocumentObjectExecReturn *Helix::execute(void) Standard_Real myHeight = Height.getValue(); Standard_Real myRadius = Radius.getValue(); Standard_Real myAngle = Angle.getValue(); + Standard_Boolean myLocalCS = LocalCoord.getValue() ? Standard_True : Standard_False; TopoShape helix; - this->Shape.setValue(helix.makeHelix(myPitch, myHeight, myRadius, myAngle)); + this->Shape.setValue(helix.makeHelix(myPitch, myHeight, myRadius, myAngle, myLocalCS)); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); diff --git a/src/Mod/Part/App/PrimitiveFeature.h b/src/Mod/Part/App/PrimitiveFeature.h index fe1eb06091..e90a4d6a1f 100644 --- a/src/Mod/Part/App/PrimitiveFeature.h +++ b/src/Mod/Part/App/PrimitiveFeature.h @@ -227,6 +227,7 @@ public: App::PropertyFloatConstraint Height; App::PropertyFloatConstraint Radius; App::PropertyFloatConstraint Angle; + App::PropertyEnumeration LocalCoord; /** @name methods override feature */ //@{ @@ -234,6 +235,9 @@ public: App::DocumentObjectExecReturn *execute(void); short mustExecute() const; //@} + +private: + static const char* LocalCSEnums[]; }; class PartExport Wedge : public Primitive diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 0a434914a2..f78bc50262 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1493,42 +1493,49 @@ TopoDS_Shape TopoShape::makeSweep(const TopoDS_Shape& profile, double tol, int f } TopoDS_Shape TopoShape::makeHelix(Standard_Real pitch, Standard_Real height, - Standard_Real radius, Standard_Real angle) const + Standard_Real radius, Standard_Real angle, + Standard_Boolean leftHanded) const { - if (pitch < Precision::Confusion()) - Standard_Failure::Raise("Pitch of helix too small"); + if (pitch < Precision::Confusion()) + Standard_Failure::Raise("Pitch of helix too small"); - if (height < Precision::Confusion()) - Standard_Failure::Raise("Height of helix too small"); + if (height < Precision::Confusion()) + Standard_Failure::Raise("Height of helix too small"); - if (radius < Precision::Confusion()) - Standard_Failure::Raise("Radius of helix too small"); + if (radius < Precision::Confusion()) + Standard_Failure::Raise("Radius of helix too small"); - gp_Ax2 cylAx2(gp_Pnt(0.0,0.0,0.0) , gp::DZ()); - Handle_Geom_Surface surf; - if (angle < Precision::Confusion()) { - surf = new Geom_CylindricalSurface(cylAx2, radius); - } - else { - angle = Base::toRadians(angle); - if (angle < Precision::Confusion()) - Standard_Failure::Raise("Angle of helix too small"); - surf = new Geom_ConicalSurface(gp_Ax3(cylAx2), angle, radius); - } + gp_Ax2 cylAx2(gp_Pnt(0.0,0.0,0.0) , gp::DZ()); + Handle_Geom_Surface surf; + if (angle < Precision::Confusion()) { + surf = new Geom_CylindricalSurface(cylAx2, radius); + } + else { + angle = Base::toRadians(angle); + if (angle < Precision::Confusion()) + Standard_Failure::Raise("Angle of helix too small"); + surf = new Geom_ConicalSurface(gp_Ax3(cylAx2), angle, radius); + } - gp_Pnt2d aPnt(0, 0); - gp_Dir2d aDir(2. * PI, pitch); - gp_Ax2d aAx2d(aPnt, aDir); + gp_Pnt2d aPnt(0, 0); + gp_Dir2d aDir(2. * PI, pitch); + if (leftHanded) { + //aPnt.SetCoord(0.0, height); + //aDir.SetCoord(2.0 * PI, -pitch); + aPnt.SetCoord(2. * PI, 0.0); + aDir.SetCoord(-2. * PI, pitch); + } + gp_Ax2d aAx2d(aPnt, aDir); - Handle(Geom2d_Line) line = new Geom2d_Line(aAx2d); - gp_Pnt2d beg = line->Value(0); - gp_Pnt2d end = line->Value(sqrt(4.0*PI*PI+pitch*pitch)*(height/pitch)); - Handle(Geom2d_TrimmedCurve) segm = GCE2d_MakeSegment(beg , end); + Handle(Geom2d_Line) line = new Geom2d_Line(aAx2d); + gp_Pnt2d beg = line->Value(0); + gp_Pnt2d end = line->Value(sqrt(4.0*PI*PI+pitch*pitch)*(height/pitch)); + Handle(Geom2d_TrimmedCurve) segm = GCE2d_MakeSegment(beg , end); - TopoDS_Edge edgeOnSurf = BRepBuilderAPI_MakeEdge(segm , surf); - TopoDS_Wire wire = BRepBuilderAPI_MakeWire(edgeOnSurf); - BRepLib::BuildCurves3d(wire); - return wire; + TopoDS_Edge edgeOnSurf = BRepBuilderAPI_MakeEdge(segm , surf); + TopoDS_Wire wire = BRepBuilderAPI_MakeWire(edgeOnSurf); + BRepLib::BuildCurves3d(wire); + return wire; } TopoDS_Shape TopoShape::makeLoft(const TopTools_ListOfShape& profiles, diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 9f3b17562b..0cf1087f93 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -161,7 +161,7 @@ public: TopoDS_Shape makeTube(double radius, double tol) const; TopoDS_Shape makeTube() const; TopoDS_Shape makeHelix(Standard_Real pitch, Standard_Real height, - Standard_Real radius, Standard_Real angle=0) const; + Standard_Real radius, Standard_Real angle=0, Standard_Boolean left=Standard_False) const; TopoDS_Shape makeLoft(const TopTools_ListOfShape& profiles, Standard_Boolean isSolid, Standard_Boolean isRuled) const; TopoDS_Shape makeOffset(double offset, double tol, diff --git a/src/Mod/Part/Gui/DlgPrimitives.cpp b/src/Mod/Part/Gui/DlgPrimitives.cpp index 83b6b53cc5..3665dd196e 100644 --- a/src/Mod/Part/Gui/DlgPrimitives.cpp +++ b/src/Mod/Part/Gui/DlgPrimitives.cpp @@ -481,12 +481,14 @@ void DlgPrimitives::createPrimitive(const QString& placement) "App.ActiveDocument.%1.Height=%3\n" "App.ActiveDocument.%1.Radius=%4\n" "App.ActiveDocument.%1.Angle=%5\n" - "App.ActiveDocument.%1.Placement=%6\n") + "App.ActiveDocument.%1.LocalCoord=%6\n" + "App.ActiveDocument.%1.Placement=%7\n") .arg(name) .arg(ui.helixPitch->value(),0,'f',2) .arg(ui.helixHeight->value(),0,'f',2) .arg(ui.helixRadius->value(),0,'f',2) .arg(ui.helixAngle->value(),0,'f',2) + .arg(ui.helixLocalCS->currentIndex()) .arg(placement); } else if (ui.comboBox1->currentIndex() == 9) { // circle diff --git a/src/Mod/Part/Gui/DlgPrimitives.ui b/src/Mod/Part/Gui/DlgPrimitives.ui index 6138066ea9..4bc21969f7 100644 --- a/src/Mod/Part/Gui/DlgPrimitives.ui +++ b/src/Mod/Part/Gui/DlgPrimitives.ui @@ -1231,6 +1231,27 @@
+ + + + Coordinate system: + + + + + + + + Right-handed + + + + + Left-handed + + + + From 47d53335e0ef538e5088f6976bb338a3343b2a78 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 1 May 2012 18:07:37 -0300 Subject: [PATCH 160/351] Fixed 0000688 Gui issues with Draft rectanges --- src/Mod/Draft/Draft.py | 2 +- src/Mod/Draft/DraftGui.py | 7 +++++-- src/Mod/Draft/DraftTools.py | 38 ++++++++++++++++++++++--------------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 89cbb15fe2..070d87ddae 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -2297,7 +2297,7 @@ class _ViewProviderRectangle(_ViewProviderDraft): "A View Provider for the Rectangle object" def __init__(self, vobj): _ViewProviderDraft.__init__(self,vobj) - obj.addProperty("App::PropertyFile","TextureImage", + vobj.addProperty("App::PropertyFile","TextureImage", "Base","Uses an image as a texture map") def attach(self,vobj): diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index a3402501e4..3fd0339d49 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -496,8 +496,11 @@ class DraftToolBar: self.offsetLabel.show() self.offsetValue.show() - def lineUi(self): - self.pointUi(translate("draft", "Line")) + def lineUi(self,title=None): + if title: + self.pointUi(title) + else: + self.pointUi(translate("draft", "Line")) self.xValue.setEnabled(True) self.yValue.setEnabled(True) self.isRelative.show() diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index e0e767564f..3994fea19f 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -401,7 +401,7 @@ class Line(Creator): Creator.Activated(self,name) if self.doc: self.obj = None - self.ui.lineUi() + self.ui.lineUi(name) self.linetrack = lineTracker() self.constraintrack = lineTracker(dotted=True) self.obj=self.doc.addObject("Part::Feature",self.featureName) @@ -526,6 +526,8 @@ class Wire(Line): 'Accel' : "W, I", 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Wire"), 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Creates a multiple-point wire. CTRL to snap, SHIFT to constrain")} + def Activated(self): + Line.Activated(self,name=str(translate("draft","Wire"))) class BSpline(Line): @@ -541,7 +543,7 @@ class BSpline(Line): 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_BSpline", "Creates a multiple-point b-spline. CTRL to snap, SHIFT to constrain")} def Activated(self): - Line.Activated(self,"BSpline") + Line.Activated(self,name=str(translate("draft","BSpline"))) if self.doc: self.bsplinetrack = bsplineTracker() @@ -693,10 +695,11 @@ class Rectangle(Creator): 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Rectangle", "Creates a 2-point rectangle. CTRL to snap")} def Activated(self): - Creator.Activated(self,"Rectangle") + name = str(translate("draft","Rectangle")) + Creator.Activated(self,name) if self.ui: self.refpoint = None - self.ui.pointUi() + self.ui.pointUi(name) self.ui.extUi() self.call = self.view.addEventCallback("SoEvent",self.action) self.rect = rectangleTracker() @@ -1096,14 +1099,15 @@ class Polygon(Creator): 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Polygon", "Creates a regular polygon. CTRL to snap, SHIFT to constrain")} def Activated(self): - Creator.Activated(self,"Polygon") + name = str(translate("draft","Polygon")) + Creator.Activated(self,name) if self.ui: self.step = 0 self.center = None self.rad = None self.tangents = [] self.tanpoints = [] - self.ui.pointUi() + self.ui.pointUi(name) self.ui.extUi() self.ui.numFaces.show() self.altdown = False @@ -1284,12 +1288,13 @@ class Text(Creator): 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Text", "Creates an annotation. CTRL to snap")} def Activated(self): - Creator.Activated(self,"Text") + name = str(translate("draft","Text")) + Creator.Activated(self,name) if self.ui: self.dialog = None self.text = '' self.ui.sourceCmd = self - self.ui.pointUi() + self.ui.pointUi(name) self.call = self.view.addEventCallback("SoEvent",self.action) self.ui.xValue.setFocus() self.ui.xValue.selectAll() @@ -1350,19 +1355,20 @@ class Dimension(Creator): 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Dimension", "Creates a dimension. CTRL to snap, SHIFT to constrain, ALT to select a segment")} def Activated(self): + name = str(translate("draft","Dimension")) if self.cont: self.finish() elif self.hasMeasures(): - Creator.Activated(self,"Dimension") + Creator.Activated(self,name) self.dimtrack = dimTracker() self.arctrack = arcTracker() self.constraintrack = lineTracker(dotted=True) self.createOnMeasures() self.finish() else: - Creator.Activated(self,"Dimension") + Creator.Activated(self,name) if self.ui: - self.ui.pointUi() + self.ui.pointUi(name) self.ui.continueCmd.show() self.altdown = False self.call = self.view.addEventCallback("SoEvent",self.action) @@ -1707,7 +1713,8 @@ class Move(Modifier): 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Move", "Moves the selected objects between 2 points. CTRL to snap, SHIFT to constrain, ALT to copy")} def Activated(self): - Modifier.Activated(self,"Move") + self.name = str(translate("draft","Move")) + Modifier.Activated(self,self.name) if self.ui: if not Draft.getSelection(): self.ghost = None @@ -1723,7 +1730,7 @@ class Move(Modifier): if self.call: self.view.removeEventCallback("SoEvent",self.call) self.sel = Draft.getSelection() self.sel = Draft.getGroupContents(self.sel) - self.ui.pointUi() + self.ui.pointUi(self.name) self.ui.modUi() self.ui.xValue.setFocus() self.ui.xValue.selectAll() @@ -2874,7 +2881,8 @@ class Scale(Modifier): 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Scale", "Scales the selected objects from a base point. CTRL to snap, SHIFT to constrain, ALT to copy")} def Activated(self): - Modifier.Activated(self,"Scale") + self.name = str(translate("draft","Scale")) + Modifier.Activated(self,self.name) if self.ui: if not Draft.getSelection(): self.ghost = None @@ -2890,7 +2898,7 @@ class Scale(Modifier): if self.call: self.view.removeEventCallback("SoEvent",self.call) self.sel = Draft.getSelection() self.sel = Draft.getGroupContents(self.sel) - self.ui.pointUi() + self.ui.pointUi(self.name) self.ui.modUi() self.ui.xValue.setFocus() self.ui.xValue.selectAll() From e274524b43cdae91b0205f759d43f761dde37ef5 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 2 May 2012 11:37:46 -0300 Subject: [PATCH 161/351] Fixed 0000686: Draft upgrade looses inner holes --- src/Mod/Draft/Draft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 070d87ddae..1c9961679b 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -779,6 +779,7 @@ def fuse(object1,object2): # testing if we have holes: holes = False fshape = object1.Shape.fuse(object2.Shape) + fshape = fshape.removeSplitter() for f in fshape.Faces: if len(f.Wires) > 1: holes = True @@ -791,7 +792,6 @@ def fuse(object1,object2): obj.Tool = object2 elif holes: # temporary hack, since Part::Fuse objects don't remove splitters - fshape = fshape.removeSplitter() obj = FreeCAD.ActiveDocument.addObject("Part::Feature","Fusion") obj.Shape = fshape else: From 2dc62d783e8ba168f2c9c91a682726acd1ba96bc Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 2 May 2012 18:16:41 -0300 Subject: [PATCH 162/351] Added 0000602 : Annotations object for Drawing pages --- src/Mod/Drawing/App/AppDrawing.cpp | 2 + src/Mod/Drawing/App/CMakeLists.txt | 2 + src/Mod/Drawing/App/FeatureViewAnnotation.cpp | 103 +++ src/Mod/Drawing/App/FeatureViewAnnotation.h | 73 ++ src/Mod/Drawing/App/Makefile.am | 2 + src/Mod/Drawing/Gui/Command.cpp | 29 + src/Mod/Drawing/Gui/Resources/Drawing.qrc | 1 + src/Mod/Drawing/Gui/Resources/Makefile.am | 1 + .../icons/actions/drawing-annotation.svg | 722 ++++++++++++++++++ src/Mod/Drawing/Gui/Workbench.cpp | 2 + 10 files changed, 937 insertions(+) create mode 100644 src/Mod/Drawing/App/FeatureViewAnnotation.cpp create mode 100644 src/Mod/Drawing/App/FeatureViewAnnotation.h create mode 100755 src/Mod/Drawing/Gui/Resources/icons/actions/drawing-annotation.svg diff --git a/src/Mod/Drawing/App/AppDrawing.cpp b/src/Mod/Drawing/App/AppDrawing.cpp index 86aafb4203..a581668bad 100644 --- a/src/Mod/Drawing/App/AppDrawing.cpp +++ b/src/Mod/Drawing/App/AppDrawing.cpp @@ -20,6 +20,7 @@ #include "FeaturePage.h" #include "FeatureView.h" #include "FeatureViewPart.h" +#include "FeatureViewAnnotation.h" #include "FeatureProjection.h" #include "PageGroup.h" @@ -57,6 +58,7 @@ void DrawingExport initDrawing() Drawing::FeatureProjection ::init(); Drawing::FeatureViewPartPython ::init(); Drawing::FeatureViewPython ::init(); + Drawing::FeatureViewAnnotation ::init(); } } // extern "C" diff --git a/src/Mod/Drawing/App/CMakeLists.txt b/src/Mod/Drawing/App/CMakeLists.txt index 3258959f80..98767a24a7 100644 --- a/src/Mod/Drawing/App/CMakeLists.txt +++ b/src/Mod/Drawing/App/CMakeLists.txt @@ -27,6 +27,8 @@ SET(Features_SRCS FeatureView.h FeatureViewPart.cpp FeatureViewPart.h + FeatureViewAnnotation.cpp + FeatureViewAnnotation.h PageGroup.cpp PageGroup.h ) diff --git a/src/Mod/Drawing/App/FeatureViewAnnotation.cpp b/src/Mod/Drawing/App/FeatureViewAnnotation.cpp new file mode 100644 index 0000000000..50d78add53 --- /dev/null +++ b/src/Mod/Drawing/App/FeatureViewAnnotation.cpp @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2012 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include + +#include +#include + +#include "FeatureViewAnnotation.h" + +using namespace Drawing; +using namespace std; + + +//=========================================================================== +// FeatureViewAnnotation +//=========================================================================== + +PROPERTY_SOURCE(Drawing::FeatureViewAnnotation, Drawing::FeatureView) + + +FeatureViewAnnotation::FeatureViewAnnotation(void) +{ + static const char *vgroup = "Drawing view"; + + ADD_PROPERTY_TYPE(Text ,(""),vgroup,App::Prop_None,"The text to be displayed"); + ADD_PROPERTY_TYPE(Font ,("Sans"),vgroup,App::Prop_None,"The name of the font to use"); + ADD_PROPERTY_TYPE(TextColor,(0.0f,0.0f,0.0f),vgroup,App::Prop_None,"The color of the text"); +} + +FeatureViewAnnotation::~FeatureViewAnnotation() +{ +} + +App::DocumentObjectExecReturn *FeatureViewAnnotation::execute(void) +{ + std::stringstream result,hr,hg,hb; + const App::Color& c = TextColor.getValue(); + hr << hex << setfill('0') << setw(2) << (int)(255.0*c.r); + hg << hex << setfill('0') << setw(2) << (int)(255.0*c.g); + hb << hex << setfill('0') << setw(2) << (int)(255.0*c.b); + + result << "" << endl; + + int index=0; + for (std::vector::const_iterator it = Text.getValues().begin(); it != Text.getValues().end(); ++it) { + result << "" << it->c_str() << "" << endl; + index++; + } + + result << "" << endl; + + // Apply the resulting fragment + ViewResult.setValue(result.str().c_str()); + + return App::DocumentObject::StdReturn; +} + +// Python Drawing feature --------------------------------------------------------- + +namespace App { +/// @cond DOXERR +PROPERTY_SOURCE_TEMPLATE(Drawing::FeatureViewAnnotationPython, Drawing::FeatureViewAnnotation) +template<> const char* Drawing::FeatureViewAnnotationPython::getViewProviderName(void) const { + return "DrawingGui::ViewProviderDrawingView"; +} +/// @endcond + +// explicit template instantiation +template class DrawingExport FeaturePythonT; +} diff --git a/src/Mod/Drawing/App/FeatureViewAnnotation.h b/src/Mod/Drawing/App/FeatureViewAnnotation.h new file mode 100644 index 0000000000..8bd68cf406 --- /dev/null +++ b/src/Mod/Drawing/App/FeatureViewAnnotation.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net 2012) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + + + +#ifndef _FeatureViewAnnotation_h_ +#define _FeatureViewAnnotation_h_ + + +#include +#include +#include "FeatureView.h" +#include + + +namespace Drawing +{ + + +/** Base class of all View Features in the drawing module + */ +class DrawingExport FeatureViewAnnotation : public FeatureView +{ + PROPERTY_HEADER(Drawing::FeatureView); + +public: + /// Constructor + FeatureViewAnnotation(void); + virtual ~FeatureViewAnnotation(); + + App::PropertyStringList Text; + App::PropertyString Font; + App::PropertyColor TextColor; + + /** @name methods overide Feature */ + //@{ + /// recalculate the Feature + virtual App::DocumentObjectExecReturn *execute(void); + //@} + + /// returns the type name of the ViewProvider + virtual const char* getViewProviderName(void) const { + return "DrawingGui::ViewProviderDrawingView"; + } +}; + +typedef App::FeaturePythonT FeatureViewAnnotationPython; + + +} //namespace Drawing + + +#endif diff --git a/src/Mod/Drawing/App/Makefile.am b/src/Mod/Drawing/App/Makefile.am index 790f1ddccb..462017c0fd 100644 --- a/src/Mod/Drawing/App/Makefile.am +++ b/src/Mod/Drawing/App/Makefile.am @@ -13,6 +13,8 @@ libDrawing_la_SOURCES=\ FeatureView.h \ FeatureViewPart.cpp \ FeatureViewPart.h \ + FeatureViewAnnotation.cpp \ + FeatureViewAnnotation.h \ PageGroup.cpp \ PageGroup.h \ ProjectionAlgos.cpp \ diff --git a/src/Mod/Drawing/Gui/Command.cpp b/src/Mod/Drawing/Gui/Command.cpp index 2dc1a49576..4da43412c8 100644 --- a/src/Mod/Drawing/Gui/Command.cpp +++ b/src/Mod/Drawing/Gui/Command.cpp @@ -354,6 +354,34 @@ bool CmdDrawingOpenBrowserView::isActive(void) return (getActiveGuiDocument() ? true : false); } +//=========================================================================== +// Drawing_Annotation +//=========================================================================== + +DEF_STD_CMD_A(CmdDrawingAnnotation); + +CmdDrawingAnnotation::CmdDrawingAnnotation() + : Command("Drawing_Annotation") +{ + // seting the + sGroup = QT_TR_NOOP("Drawing"); + sMenuText = QT_TR_NOOP("&Annotation"); + sToolTipText = QT_TR_NOOP("Inserts an Annotation view in the active document"); + sWhatsThis = "Drawing_Annotation"; + sStatusTip = QT_TR_NOOP("Inserts an Annotation view in the active document"); + sPixmap = "actions/drawing-annotation"; +} + +void CmdDrawingAnnotation::activated(int iMsg) +{ + doCommand(Doc,"AnnotationView = App.activeDocument().addObject(\"Drawing::FeatureViewAnnotation\",\"ViewAnnotation\")"); + doCommand(Doc,"AnnotationView.Scale = 7.0"); +} + +bool CmdDrawingAnnotation::isActive(void) +{ + return (getActiveGuiDocument() ? true : false); +} //=========================================================================== // Drawing_ExportPage @@ -451,6 +479,7 @@ void CreateDrawingCommands(void) rcCmdMgr.addCommand(new CmdDrawingNewView()); rcCmdMgr.addCommand(new CmdDrawingOrthoViews()); rcCmdMgr.addCommand(new CmdDrawingOpenBrowserView()); + rcCmdMgr.addCommand(new CmdDrawingAnnotation()); rcCmdMgr.addCommand(new CmdDrawingExportPage()); rcCmdMgr.addCommand(new CmdDrawingProjectShape()); } diff --git a/src/Mod/Drawing/Gui/Resources/Drawing.qrc b/src/Mod/Drawing/Gui/Resources/Drawing.qrc index 5d5d80ca37..fad40eb814 100644 --- a/src/Mod/Drawing/Gui/Resources/Drawing.qrc +++ b/src/Mod/Drawing/Gui/Resources/Drawing.qrc @@ -16,6 +16,7 @@ icons/actions/drawing-view.svg icons/actions/drawing-orthoviews.svg icons/actions/drawing-openbrowser.svg + icons/actions/drawing-annotation.svg translations/Drawing_af.qm translations/Drawing_de.qm translations/Drawing_es.qm diff --git a/src/Mod/Drawing/Gui/Resources/Makefile.am b/src/Mod/Drawing/Gui/Resources/Makefile.am index a6063f8eab..e42a14b034 100644 --- a/src/Mod/Drawing/Gui/Resources/Makefile.am +++ b/src/Mod/Drawing/Gui/Resources/Makefile.am @@ -20,6 +20,7 @@ EXTRA_DIST = \ icons/actions/drawing-portrait-A4.svg \ icons/actions/drawing-orthoviews.svg \ icons/actions/drawing-openbrowser.svg \ + icons/actions/drawing-annotation.svg \ icons/Page.svg \ icons/Pages.svg \ icons/View.svg \ diff --git a/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-annotation.svg b/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-annotation.svg new file mode 100755 index 0000000000..b45e42a483 --- /dev/null +++ b/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-annotation.svg @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + Ab + + + diff --git a/src/Mod/Drawing/Gui/Workbench.cpp b/src/Mod/Drawing/Gui/Workbench.cpp index d4816ada24..b7bd8bbce4 100644 --- a/src/Mod/Drawing/Gui/Workbench.cpp +++ b/src/Mod/Drawing/Gui/Workbench.cpp @@ -62,6 +62,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const *part << "Drawing_NewView"; *part << "Drawing_OrthoViews"; *part << "Drawing_OpenBrowserView"; + *part << "Drawing_Annotation"; *part << "Drawing_ExportPage"; return root; @@ -78,6 +79,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const *part << "Drawing_NewView"; *part << "Drawing_OrthoViews"; *part << "Drawing_OpenBrowserView"; + *part << "Drawing_Annotation"; *part << "Drawing_ExportPage"; return root; } From 6e69faa86d4c9d4d65e69da1955b155e83aa79a6 Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Thu, 3 May 2012 11:08:40 +0200 Subject: [PATCH 163/351] importSVG support numbers only seperated through a minus sign in path definition. Like in files created by Adobe Ilustrator. --- src/Mod/Draft/importSVG.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index e30e0cadb5..5de678d519 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -256,7 +256,7 @@ def getsize(length,mode='discard',base=1): elif mode == 'tuple': return float(number),unit elif mode == 'isabsolute': - return unit in ['mm','cm','in','px','pt'] + return unit in ('mm','cm','in','px','pt') elif mode == 'mm': return float(number)*tomm[unit] elif mode == 'css': @@ -525,9 +525,11 @@ class svgHandler(xml.sax.ContentHandler): self.lastdim = obj data['d']=[] pathcommandsre=re.compile('\s*?([mMlLhHvVaAcCqQsStTzZ])\s*?([^mMlLhHvVaAcCqQsStTzZ]*)\s*?',re.DOTALL) + pointsre=re.compile('([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)',re.DOTALL) for d,pointsstr in pathcommandsre.findall(' '.join(data['d'])): relative = d.islower() - pointlist = [float(str1) for str1 in pointsstr.replace(',',' ').split()] + pointlist = [float(number) for number,exponent in pointsre.findall(pointsstr.replace(',',' '))] + if (d == "M" or d == "m"): x = pointlist.pop(0) y = pointlist.pop(0) From 0ea8beed7ace828fb5447269ebee0568bf11be03 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 3 May 2012 17:01:09 +0200 Subject: [PATCH 164/351] update helix immediately --- src/Mod/Part/App/PrimitiveFeature.cpp | 18 +++++++++++++++++- src/Mod/Part/App/PrimitiveFeature.h | 3 +++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/PrimitiveFeature.cpp b/src/Mod/Part/App/PrimitiveFeature.cpp index 0213ac04d1..5673ddd424 100644 --- a/src/Mod/Part/App/PrimitiveFeature.cpp +++ b/src/Mod/Part/App/PrimitiveFeature.cpp @@ -100,7 +100,7 @@ void Primitive::onChanged(const App::Property* prop) // Do not support sphere, ellipsoid and torus because the creation // takes too long and thus is not feasible std::string grp = (prop->getGroup() ? prop->getGroup() : ""); - if (grp == "Plane" || grp == "Cylinder" || grp == "Cone" || grp == "Helix") { + if (grp == "Plane" || grp == "Cylinder" || grp == "Cone") { try { App::DocumentObjectExecReturn *ret = recompute(); delete ret; @@ -601,6 +601,22 @@ Helix::Helix(void) LocalCoord.setEnums(LocalCSEnums); } +void Helix::onChanged(const App::Property* prop) +{ + if (!isRestoring()) { + if (prop == &Pitch || prop == &Height || prop == &Radius || + prop == &Angle || prop == &LocalCoord) { + try { + App::DocumentObjectExecReturn *ret = recompute(); + delete ret; + } + catch (...) { + } + } + } + Part::Feature::onChanged(prop); +} + short Helix::mustExecute() const { if (Pitch.isTouched()) diff --git a/src/Mod/Part/App/PrimitiveFeature.h b/src/Mod/Part/App/PrimitiveFeature.h index e90a4d6a1f..0c0b7b81d6 100644 --- a/src/Mod/Part/App/PrimitiveFeature.h +++ b/src/Mod/Part/App/PrimitiveFeature.h @@ -236,6 +236,9 @@ public: short mustExecute() const; //@} +protected: + void onChanged (const App::Property* prop); + private: static const char* LocalCSEnums[]; }; From e12bc00f9bf4316202a8baf34dad4d65444a7c22 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 3 May 2012 13:00:01 -0300 Subject: [PATCH 165/351] Further fixes of 0000688 in Draft Gui --- src/Mod/Draft/DraftGui.py | 90 +++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 3fd0339d49..17b3dba50e 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -150,6 +150,8 @@ class DraftTaskPanel: FreeCADGui.ActiveDocument.resetEdit() return True def reject(self): + FreeCADGui.draftToolBar.isTaskOn = False + FreeCADGui.draftToolBar.escape() FreeCADGui.ActiveDocument.resetEdit() return True @@ -169,6 +171,7 @@ class DraftToolBar: self.paramconstr = Draft.getParam("constructioncolor")>>8 self.constrMode = False self.continueMode = False + self.relativeMode = True self.state = None self.textbuffer = [] self.crossedViews = [] @@ -307,7 +310,7 @@ class DraftToolBar: self.labelRadius = self._label("labelRadius", self.layout) self.radiusValue = self._lineedit("radiusValue", self.layout, width=60) self.radiusValue.setText("0.00") - self.isRelative = self._checkbox("isRelative",self.layout,checked=True) + self.isRelative = self._checkbox("isRelative",self.layout,checked=self.relativeMode) self.hasFill = self._checkbox("hasFill",self.layout,checked=self.fillmode) self.continueCmd = self._checkbox("continueCmd",self.layout,checked=self.continueMode) self.occOffset = self._checkbox("occOffset",self.layout,checked=False) @@ -358,6 +361,7 @@ class DraftToolBar: QtCore.QObject.connect(self.xzButton,QtCore.SIGNAL("clicked()"),self.selectXZ) QtCore.QObject.connect(self.yzButton,QtCore.SIGNAL("clicked()"),self.selectYZ) QtCore.QObject.connect(self.continueCmd,QtCore.SIGNAL("stateChanged(int)"),self.setContinue) + QtCore.QObject.connect(self.isRelative,QtCore.SIGNAL("stateChanged(int)"),self.setRelative) QtCore.QObject.connect(self.hasFill,QtCore.SIGNAL("stateChanged(int)"),self.setFill) QtCore.QObject.connect(self.currentViewButton,QtCore.SIGNAL("clicked()"),self.selectCurrentView) QtCore.QObject.connect(self.resetPlaneButton,QtCore.SIGNAL("clicked()"),self.selectResetPlane) @@ -712,7 +716,8 @@ class DraftToolBar: self.radiusValue.setFocus() self.radiusValue.selectAll() - def setRelative(self): + def setRelative(self,val=1): + self.relativeMode = bool(val) if (not self.taskmode) or self.isTaskOn: self.isRelative.show() @@ -836,9 +841,9 @@ class DraftToolBar: pass else: if self.pointcallback: - self.pointcallback(FreeCAD.Vector(numx,numy,numz),(self.isRelative.isVisible() and self.isRelative.isChecked())) + self.pointcallback(FreeCAD.Vector(numx,numy,numz),self.relativeMode) else: - if self.isRelative.isVisible() and self.isRelative.isChecked(): + if self.relativeMode: if self.sourceCmd.node: if self.sourceCmd.featureName == "Rectangle": last = self.sourceCmd.node[0] @@ -903,6 +908,7 @@ class DraftToolBar: spec = False if txt.endsWith(" ") or txt.endsWith("r"): self.isRelative.setChecked(not self.isRelative.isChecked()) + self.relativeMode = self.isRelative.isChecked() spec = True elif txt.endsWith("i"): if self.hasFill.isVisible(): @@ -972,44 +978,46 @@ class DraftToolBar: def displayPoint(self, point, last=None, plane=None, mask=None): "this function displays the passed coords in the x, y, and z widgets" - # get coords to display - dp = point - if self.isRelative.isChecked() and (last != None): - if plane: - dp = plane.getLocalCoords(FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z)) + if (not self.taskmode) or self.isTaskOn: + + # get coords to display + dp = point + if self.relativeMode and (last != None): + if plane: + dp = plane.getLocalCoords(FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z)) + else: + dp = FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z) + + # set widgets + self.xValue.setText("%.2f" % dp.x) + self.yValue.setText("%.2f" % dp.y) + self.zValue.setText("%.2f" % dp.z) + + # set masks + if mask == "x": + self.xValue.setEnabled(True) + self.yValue.setEnabled(False) + self.zValue.setEnabled(False) + self.xValue.setFocus() + self.xValue.selectAll() + elif mask == "y": + self.xValue.setEnabled(False) + self.yValue.setEnabled(True) + self.zValue.setEnabled(False) + self.yValue.setFocus() + self.yValue.selectAll() + elif mask == "z": + self.xValue.setEnabled(False) + self.yValue.setEnabled(False) + self.zValue.setEnabled(True) + self.zValue.setFocus() + self.zValue.selectAll() else: - dp = FreeCAD.Vector(point.x-last.x, point.y-last.y, point.z-last.z) - - # set widgets - self.xValue.setText("%.2f" % dp.x) - self.yValue.setText("%.2f" % dp.y) - self.zValue.setText("%.2f" % dp.z) - - # set masks - if mask == "x": - self.xValue.setEnabled(True) - self.yValue.setEnabled(False) - self.zValue.setEnabled(False) - self.xValue.setFocus() - self.xValue.selectAll() - elif mask == "y": - self.xValue.setEnabled(False) - self.yValue.setEnabled(True) - self.zValue.setEnabled(False) - self.yValue.setFocus() - self.yValue.selectAll() - elif mask == "z": - self.xValue.setEnabled(False) - self.yValue.setEnabled(False) - self.zValue.setEnabled(True) - self.zValue.setFocus() - self.zValue.selectAll() - else: - self.xValue.setEnabled(True) - self.yValue.setEnabled(True) - self.zValue.setEnabled(True) - self.xValue.setFocus() - self.xValue.selectAll() + self.xValue.setEnabled(True) + self.yValue.setEnabled(True) + self.zValue.setEnabled(True) + self.xValue.setFocus() + self.xValue.selectAll() def getDefaultColor(self,type,rgb=False): From d4b5a079d930c6ee033b721ae2c9e61f0adbcf37 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 3 May 2012 16:04:48 -0300 Subject: [PATCH 166/351] Refined Drawing::FeatureViewAnnotation + Now goes inside an existing page automatically + Supports Rotation value --- src/Mod/Drawing/App/FeatureViewAnnotation.cpp | 11 +++++------ src/Mod/Drawing/Gui/Command.cpp | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Mod/Drawing/App/FeatureViewAnnotation.cpp b/src/Mod/Drawing/App/FeatureViewAnnotation.cpp index 50d78add53..b8624c28b1 100644 --- a/src/Mod/Drawing/App/FeatureViewAnnotation.cpp +++ b/src/Mod/Drawing/App/FeatureViewAnnotation.cpp @@ -66,21 +66,20 @@ App::DocumentObjectExecReturn *FeatureViewAnnotation::execute(void) hg << hex << setfill('0') << setw(2) << (int)(255.0*c.g); hb << hex << setfill('0') << setw(2) << (int)(255.0*c.b); - result << "" << endl + << "" << endl; int index=0; for (std::vector::const_iterator it = Text.getValues().begin(); it != Text.getValues().end(); ++it) { - result << "" << it->c_str() << "" << endl; + result << "" << it->c_str() << "" << endl; index++; } - result << "" << endl; + result << "" << endl << "" << endl; // Apply the resulting fragment ViewResult.setValue(result.str().c_str()); diff --git a/src/Mod/Drawing/Gui/Command.cpp b/src/Mod/Drawing/Gui/Command.cpp index 4da43412c8..2f9345b974 100644 --- a/src/Mod/Drawing/Gui/Command.cpp +++ b/src/Mod/Drawing/Gui/Command.cpp @@ -374,8 +374,23 @@ CmdDrawingAnnotation::CmdDrawingAnnotation() void CmdDrawingAnnotation::activated(int iMsg) { - doCommand(Doc,"AnnotationView = App.activeDocument().addObject(\"Drawing::FeatureViewAnnotation\",\"ViewAnnotation\")"); - doCommand(Doc,"AnnotationView.Scale = 7.0"); + + std::vector pages = this->getDocument()->getObjectsOfType(Drawing::FeaturePage::getClassTypeId()); + if (pages.empty()){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No page to insert"), + QObject::tr("Create a page to insert.")); + return; + } + std::string PageName = pages.front()->getNameInDocument(); + std::string FeatName = getUniqueObjectName("Annotation"); + openCommand("Create Annotation"); + doCommand(Doc,"App.activeDocument().addObject('Drawing::FeatureViewAnnotation','%s')",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.X = 10.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Y = 10.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Scale = 7.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); + updateActive(); + commitCommand(); } bool CmdDrawingAnnotation::isActive(void) From 4e2a6eb1fb803f2d28134b19ece863f37aaed2ac Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 3 May 2012 18:57:25 -0300 Subject: [PATCH 167/351] Bugfix in Arch Wall --- src/Mod/Arch/ArchWall.py | 60 +++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 5e811856ad..108edabfc9 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -249,14 +249,11 @@ class _Wall(ArchComponent.Component): "The width of this wall. Not used if this wall is based on a face") obj.addProperty("App::PropertyLength","Height","Base", "The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid") - obj.addProperty("App::PropertyLength","Length","Base", - "The length of this wall. Not used if this wall is based on a shape") obj.addProperty("App::PropertyEnumeration","Align","Base", "The alignment of this wall on its base object, if applicable") obj.Align = ['Left','Right','Center'] self.Type = "Wall" obj.Width = 0.1 - obj.Length = 1 obj.Height = 0 def execute(self,obj): @@ -288,6 +285,9 @@ class _Wall(ArchComponent.Component): def createGeometry(self,obj): "builds the wall shape" + if not obj.Base: + return + import Part from draftlibs import fcgeo @@ -346,36 +346,25 @@ class _Wall(ArchComponent.Component): # computing shape base = None - if obj.Base: - if obj.Base.isDerivedFrom("Part::Feature"): - if not obj.Base.Shape.isNull(): - base = obj.Base.Shape.copy() - if base.Solids: - pass - elif base.Faces: - if height: - norm = normal.multiply(height) - base = base.extrude(norm) - elif base.Wires: - temp = None - for wire in obj.Base.Shape.Wires: - sh = getbase(wire) - if temp: - temp = temp.fuse(sh) - else: - temp = sh - base = temp - base = base.removeSplitter() - if not base: - if obj.Length == 0: - return - length = obj.Length - if not length: - length = 1 - v1 = Vector(0,0,0) - v2 = Vector(length,0,0) - w = Part.Wire(Part.Line(v1,v2).toShape()) - base = getbase(w) + if obj.Base.isDerivedFrom("Part::Feature"): + if not obj.Base.Shape.isNull(): + base = obj.Base.Shape.copy() + if base.Solids: + pass + elif base.Faces: + if height: + norm = normal.multiply(height) + base = base.extrude(norm) + elif base.Wires: + temp = None + for wire in obj.Base.Shape.Wires: + sh = getbase(wire) + if temp: + temp = temp.fuse(sh) + else: + temp = sh + base = temp + base = base.removeSplitter() for app in obj.Additions: base = base.oldFuse(app.Shape) @@ -394,8 +383,9 @@ class _Wall(ArchComponent.Component): if not hole.Shape.isNull(): base = base.cut(hole.Shape) hole.ViewObject.hide() # to be removed - - obj.Shape = base + + if base: + obj.Shape = base if not fcgeo.isNull(pl): obj.Placement = pl From 454096a34ecfe10447541d27f97ade418e586556 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 3 May 2012 18:57:59 -0300 Subject: [PATCH 168/351] Bugfix in Draft toolbar mode --- src/Mod/Draft/DraftGui.py | 19 ++++++++++++++++++- src/Mod/Draft/DraftTools.py | 3 ++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 17b3dba50e..02c6c57d4a 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -154,7 +154,7 @@ class DraftTaskPanel: FreeCADGui.draftToolBar.escape() FreeCADGui.ActiveDocument.resetEdit() return True - + class DraftToolBar: "main draft Toolbar" def __init__(self): @@ -488,6 +488,21 @@ class DraftToolBar: self.retranslateUi(self.baseWidget) self.panel = DraftTaskPanel(self.baseWidget,extra) todo.delay(FreeCADGui.Control.showDialog,self.panel) + else: + # create a dummy task to block the UI during the works + class dummy: + "an empty dialog" + def getStandardButtons(self): + return int(QtGui.QDialogButtonBox.Cancel) + def accept(self): + FreeCADGui.ActiveDocument.resetEdit() + return True + def reject(self): + FreeCADGui.draftToolBar.isTaskOn = False + FreeCADGui.draftToolBar.escape() + FreeCADGui.ActiveDocument.resetEdit() + return True + todo.delay(FreeCADGui.Control.showDialog,dummy()) self.setTitle(title) def selectPlaneUi(self): @@ -871,6 +886,8 @@ class DraftToolBar: def escape(self): "escapes the current command" self.continueMode = False + if not self.taskmode: + self.continueCmd.setChecked(False) self.finish() def closeLine(self): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 3994fea19f..32654eb3a3 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -74,7 +74,7 @@ MODALT = MODS[Draft.getParam("modalt")] # sets defaults on first load -if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/").HasGroup("Draft"): +if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod").HasGroup("Draft"): p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") p.SetBool("copymode",1) p.SetBool("alwaysSnap",1) @@ -84,6 +84,7 @@ if not FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/").HasGroup("Dra p.SetInt("precision",4) p.SetInt("gridEvery",10) p.SetFloat("gridSpacing",1.0) + p.SetInt("UiMode",1) #--------------------------------------------------------------------------- # General functions From 9f74316fa6c232ad5aa77735a51c3ece73d181da Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 4 May 2012 15:52:49 +0200 Subject: [PATCH 169/351] fix error in translation --- .../Gui/Resources/translations/Points_de.qm | Bin 3926 -> 3933 bytes .../Gui/Resources/translations/Points_de.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Points/Gui/Resources/translations/Points_de.qm b/src/Mod/Points/Gui/Resources/translations/Points_de.qm index 668c2abcdbf662f760c5d0983842f8b5a5bd8bf3..9407ace9b07e8ed97a99fcac4fb0cf9b95b55339 100644 GIT binary patch delta 21 ccmca6cUNvh4IiWR>UgY3`~rS09G~y@Bjb+ delta 13 UcmcaBcTH|X4IiVz Ascii Points (*.asc);;All Files (*.*) - ASCII-Punkte (.asc); Alle Dateien (*.*) + ASCII-Punkte (.asc);;Alle Dateien (*.*) From c3f4871f15f86034a7b2ba2b1a0ccf42b94d7709 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 4 May 2012 11:44:31 -0300 Subject: [PATCH 170/351] Fixed a bug in Draft DXF import with solids --- src/Mod/Draft/importDXF.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 58f9bbee5b..a03ec28aaf 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -526,7 +526,7 @@ def drawSolid(solid): if p4x != None: p4 = FreeCAD.Vector(p4x,p4y,p4z) if p4 and (p4 != p3) and (p4 != p2) and (p4 != p1): try: - return Part.Face(Part.makePolygon([p1,p2,p3,p4,p1])) + return Part.Face(Part.makePolygon([p1,p2,p4,p3,p1])) except: warn(solid) else: From 18c14eb1b0d03f2291cb0c47d4c09131c7199223 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 4 May 2012 18:07:33 -0300 Subject: [PATCH 171/351] Fixed 0000663 - Naming scheme in Draft up/downgrade --- src/Mod/Draft/DraftTools.py | 38 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 32654eb3a3..7735f044cf 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -2361,8 +2361,14 @@ class Upgrade(Modifier): if (not curves) and (Draft.getType(self.sel[0]) == "Part"): msg(translate("draft", "Found 1 non-parametric objects: draftifying it\n")) Draft.draftify(self.sel[0]) + else: + msg(translate("draft", "No upgrade available for this object\n")) + self.doc.abortTransaction() + return else: msg(translate("draft", "Couldn't upgrade these objects\n")) + self.doc.abortTransaction() + return elif wires and (not faces) and (not openwires): # we have only wires, no faces @@ -2385,15 +2391,12 @@ class Upgrade(Modifier): msg(translate("draft", "One wire is not planar, upgrade not done\n")) self.nodelete = True for f in faces: - if not curves: - msg(translate("draft", "Found a closed wire: making a Draft wire\n")) - newob = Draft.makeWire(f.Wire,closed=True) - else: - # if there are curved segments, we do a non-parametric face - msg(translate("draft", "Found a closed wire with curves: making a face\n")) - newob = self.doc.addObject("Part::Feature","Face") - newob.Shape = f - Draft.formatObject(newob,lastob) + # if there are curved segments, we do a non-parametric face + msg(translate("draft", "Found a closed wire: making a face\n")) + newob = self.doc.addObject("Part::Feature","Face") + newob.Shape = f + Draft.formatObject(newob,lastob) + newob.ViewObject.DisplayMode = "Flat Lines" elif (len(openwires) == 1) and (not faces) and (not wires): # special case, we have only one open wire. We close it, unless it has only 1 edge!" @@ -2435,12 +2438,9 @@ class Upgrade(Modifier): w = Part.Wire(nedges) if len(w.Edges) == len(edges): msg(translate("draft", "Found several edges: wiring them\n")) - if not curves: - newob = Draft.makeWire(w) - else: - newob = self.doc.addObject("Part::Feature","Wire") - newob.Shape = w - Draft.formatObject(newob,lastob) + newob = self.doc.addObject("Part::Feature","Wire") + newob.Shape = w + Draft.formatObject(newob,lastob) if not newob: print "no new object found" msg(translate("draft", "Found several non-connected edges: making compound\n")) @@ -2562,6 +2562,14 @@ class Downgrade(Modifier): else: # no faces: split wire into single edges + onlyedges = True + for ob in self.sel: + if ob.Shape.ShapeType != "Edge": + onlyedges = False + if onlyedges: + msg(translate("draft", "No more downgrade possible\n")) + self.doc.abortTransaction() + return msg(translate("draft", "Found only wires: extracting their edges\n")) for ob in self.sel: for e in edges: From 3e78f7e7a3d92669d062fcb2084cf169ed37b3e0 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 4 May 2012 19:21:54 -0300 Subject: [PATCH 172/351] Added Draft_Clone command --- src/Mod/Draft/Draft.py | 14 +- src/Mod/Draft/DraftTools.py | 24 +++ src/Mod/Draft/Draft_rc.py | 204 ++++++++++++++++-- src/Mod/Draft/InitGui.py | 3 +- src/Mod/Draft/Resources/Draft.qrc | 1 + src/Mod/Draft/Resources/icons/Draft_Clone.svg | 169 +++++++++++++++ 6 files changed, 400 insertions(+), 15 deletions(-) create mode 100755 src/Mod/Draft/Resources/icons/Draft_Clone.svg diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 1c9961679b..6f8250a3da 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1635,7 +1635,7 @@ def clone(obj,delta=None): cl.Label = "Clone of " + obj[0].Label _Clone(cl) if gui: - _ViewProviderDraftPart(cl.ViewObject) + _ViewProviderClone(cl.ViewObject) formatObject(cl,obj[0]) cl.Objects = obj if delta: @@ -2873,5 +2873,17 @@ class _ViewProviderDraftPart(_ViewProviderDraft): def claimChildren(self): return [] +class _ViewProviderClone(_ViewProviderDraft): + "a view provider that displays a Part icon instead of a Draft icon" + + def __init__(self,vobj): + _ViewProviderDraft.__init__(self,vobj) + + def getIcon(self): + return ":/icons/Draft_Clone.svg" + + def claimChildren(self): + return [] + if not hasattr(FreeCADGui,"Snapper"): import DraftSnap diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 7735f044cf..39713964b6 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -3711,6 +3711,29 @@ class ShowSnapBar(): def Activated(self): if hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper.show() + + +class Draft_Clone(): + "The Draft Clone command definition" + + def GetResources(self): + return {'Pixmap' : 'Draft_Clone', + 'Accel' : "C,L", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Clone", "Clone"), + 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_Clone", "Clones the selected object(s)")} + + def Activated(self): + if FreeCADGui.Selection.getSelection(): + FreeCAD.ActiveDocument.openTransaction("Clone") + for obj in FreeCADGui.Selection.getSelection(): + Draft.clone(obj) + FreeCAD.ActiveDocument.commitTransaction() + + def IsActive(self): + if FreeCADGui.Selection.getSelection(): + return True + else: + return False #--------------------------------------------------------------------------- # Adds the icons & commands to the FreeCAD command manager, and sets defaults @@ -3744,6 +3767,7 @@ FreeCADGui.addCommand('Draft_DelPoint',DelPoint()) FreeCADGui.addCommand('Draft_WireToBSpline',WireToBSpline()) FreeCADGui.addCommand('Draft_Draft2Sketch',Draft2Sketch()) FreeCADGui.addCommand('Draft_Array',Array()) +FreeCADGui.addCommand('Draft_Clone',Draft_Clone()) # context commands FreeCADGui.addCommand('Draft_FinishLine',FinishLine()) diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 38f69d0944..7ef42e43f0 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Thu Apr 12 11:34:15 2012 +# Created: Fri May 4 19:15:01 2012 # by: The Resource Compiler for PyQt (Qt v4.7.4) # # WARNING! All changes made in this file will be lost! @@ -35272,6 +35272,179 @@ qt_resource_data = "\ \x33\x31\x30\x30\x32\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ \x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\ \x3e\x0a\ +\x00\x00\x0a\xac\ +\x00\ +\x00\x25\xf5\x78\x9c\xed\x59\x5b\x6f\xdb\xd8\x11\x7e\xf7\xaf\x60\ +\x95\x97\x04\x15\xa9\x73\xbf\xc8\x96\xf7\x61\x83\x2d\x16\x68\x51\ +\xa0\x9b\xa0\x8f\x05\x4d\xd1\x36\x1b\x49\x14\x48\xca\x97\xfc\xfa\ +\x7e\xc3\xbb\x2c\xda\x71\xb6\xdb\xdd\x4d\xb1\x56\x8c\x88\x73\xe6\ +\x9c\x33\x67\xe6\x9b\x6f\xe6\xd0\x17\xdf\x3d\x6c\x37\xc1\x5d\x5a\ +\x94\x59\xbe\x5b\xcd\x78\xc4\x66\x41\xba\x4b\xf2\x75\xb6\xbb\x59\ +\xcd\x3e\x7e\xf8\x21\x74\xb3\xa0\xac\xe2\xdd\x3a\xde\xe4\xbb\x74\ +\x35\xdb\xe5\xb3\xef\x2e\xcf\x2e\xfe\x14\x86\xc1\xf7\x45\x1a\x57\ +\xe9\x3a\xb8\xcf\xaa\xdb\xe0\xc7\xdd\xa7\x32\x89\xf7\x69\xf0\xf6\ +\xb6\xaa\xf6\xcb\xc5\xe2\xfe\xfe\x3e\xca\x5a\x61\x94\x17\x37\x8b\ +\x77\x41\x18\x5e\x9e\x9d\x5d\x94\x77\x37\x67\x41\x10\x60\xdf\x5d\ +\xb9\x5c\x27\xab\x59\x3b\x61\x7f\x28\x36\xb5\xe2\x3a\x59\xa4\x9b\ +\x74\x9b\xee\xaa\x72\xc1\x23\xbe\x98\x0d\xea\xc9\xa0\x9e\xd0\xee\ +\xd9\x5d\x9a\xe4\xdb\x6d\xbe\x2b\xeb\x99\xbb\xf2\xcd\x48\xb9\x58\ +\x5f\xf7\xda\x64\xcd\xbd\xac\x95\xb8\xf7\x7e\xc1\xc4\x42\x88\x10\ +\x1a\x61\xf9\xb8\xab\xe2\x87\xf0\x78\x2a\x6c\x9c\x9a\x2a\x18\x63\ +\x0b\x8c\x0d\x9a\xaf\xd3\x5a\x3e\x6c\xe0\x8a\x67\x8d\xa9\x47\xc7\ +\xbb\xc3\xfd\x7b\xfc\xf6\x13\x3a\x41\x54\xe6\x87\x22\x49\xaf\x31\ +\x33\x8d\x76\x69\xb5\x78\xff\xe1\x7d\x3f\x18\xb2\x68\x5d\xad\x47\ +\xcb\x74\xde\x3f\xda\xf7\x28\x24\xbb\x78\x9b\x96\xfb\x38\x49\xcb\ +\x45\x27\xaf\xe7\xdf\x67\xeb\xea\x76\x35\x33\x6a\xff\x50\x3f\xdf\ +\xa6\xd9\xcd\x6d\x35\x12\x64\xeb\xd5\x0c\x27\x14\xde\xe9\xfa\x79\ +\x04\x20\xde\x28\xb4\xcb\x2d\xfb\x11\x16\x29\x17\xc9\x88\x07\x85\ +\x77\xce\xd4\x4a\x9d\xe5\xcb\x75\x9e\x90\x29\xab\xd9\xfb\x22\xbe\ +\xae\xfe\xf5\x3d\x41\x2d\x22\x0f\x5e\x42\xed\x62\x9d\x5e\x97\xa4\ +\xde\x6c\x4b\x4f\xd8\xd7\xd6\x63\x18\x85\xef\xd2\xb8\xf8\x4b\x11\ +\xaf\x33\x20\xa6\xd1\x6b\x34\x8f\x47\xa4\x33\xac\x9d\x83\x59\x65\ +\x95\xef\x3b\x5d\x18\x52\x3d\x6e\xb0\x3b\x09\xc3\x24\xdf\xe4\xc5\ +\xf2\x0d\x4f\xad\x49\xe5\x79\x2d\xca\xe1\xa2\xac\x7a\x5c\xf2\xf3\ +\xd9\x30\x27\xbf\xbe\x2e\x53\xf8\x84\x8d\x64\xb5\x5b\x30\x03\x7b\ +\x89\x59\xb0\x78\xfd\x6e\xd7\xf5\xcf\x2b\x76\xe3\xd3\xbb\xa9\x7e\ +\xb7\x8b\xc5\xf1\xb1\x5f\xf6\x52\x17\x25\x98\xb1\x49\x13\xac\x1f\ +\x6f\xee\xe3\xc7\xb2\xdf\xa4\x46\xe6\xf2\xb6\x48\x91\x49\x6f\x26\ +\xfc\xf9\xa2\xbb\xcd\xb0\x0c\x5f\xcd\x24\xa0\x21\xb4\xf4\xba\x97\ +\x3e\x42\x6a\x78\xa4\x38\xb3\x46\x0e\xba\x02\xba\x2c\xe2\x5c\x1a\ +\x39\xac\xf0\x08\x29\x17\x11\x37\xd0\x1d\x7c\x70\xd3\x6e\xf6\x71\ +\x97\x55\x48\xc5\x43\x99\x16\x3f\x11\x9c\xff\xbe\xfb\x58\xa6\x27\ +\x5a\x1f\x8a\x78\x57\x22\x77\xb6\xab\xd9\x36\xae\x8a\xec\xe1\x2d\ +\x9f\x33\xfa\x44\xde\x38\xe7\x85\xf5\xf3\x90\x47\x7a\x0e\x12\x54\ +\x5a\x28\xe3\xdf\x0d\x5e\xfd\xdf\xf8\x2f\x34\x5f\xf0\x60\xa8\x7f\ +\x63\x1f\x7e\xc9\x01\x93\x69\x86\x63\xbd\x1e\xfa\x3a\xf6\xd7\xd7\ +\xfa\xbf\x48\xb4\x50\xfd\xba\xa9\x16\xbe\x9c\x6c\x17\x0b\x62\xa8\ +\xfa\x5b\xcf\x6f\x44\x6e\xeb\xbb\x2c\xbd\x1f\x68\xec\x2a\xee\x11\ +\xba\x8f\x6f\xd2\xda\x38\x60\xa4\xb1\xae\x1d\xb8\xca\x8b\x75\x5a\ +\x74\x43\xa6\xfe\x39\x1a\x6a\xed\x6f\xea\xf6\xd9\x31\x24\x69\xd5\ +\x7e\x9c\x4d\x8f\x97\xb7\xf1\x3a\xbf\x5f\xcd\xc4\xd3\xc1\xcf\x79\ +\x8e\x2c\x11\x91\x13\x4e\x09\xcb\x9f\x0e\x27\x0f\x18\xd4\x91\x52\ +\xcc\x9e\x4c\x4d\xb0\x5d\xc8\x7d\xa4\xbd\xe0\xcc\x9d\x8c\x1e\x8a\ +\x02\x8e\x0a\x37\xf1\x63\x8a\x43\xd5\xff\x75\xcb\x97\xb7\xf9\xfd\ +\x4d\x41\xce\xa9\x8a\x43\xfa\x74\x26\x6a\xc4\x81\x7a\x82\xf0\xd0\ +\x00\xb5\xad\x44\x23\x0d\x9a\x1b\x5e\x5d\xe5\x0f\xd3\x0b\xdc\x67\ +\x3b\x1c\x36\x6c\x6b\x1b\x17\xee\xc4\x25\xad\x46\x57\xed\xac\xd6\ +\xcf\x68\x3c\x0c\x68\x7c\x3a\x84\xd3\x8b\x13\x9f\xb4\x63\xdb\xf8\ +\x21\xdb\x66\x9f\xd3\x35\x81\xab\xc1\xd0\xc5\x36\xad\xe2\x75\x5c\ +\xc5\x03\x32\x3a\x89\xf0\xbe\x2b\x58\x17\x68\x54\x96\xff\x78\xff\ +\x43\x8f\xf2\x24\x59\xfe\x33\x2f\x3e\x0d\x00\x25\x85\xf8\x2a\x3f\ +\xc0\xec\x3e\xf7\xa8\x74\x26\x4b\x22\xbc\xb8\xba\xcc\xb6\x88\x37\ +\x75\x25\x7f\x46\x73\x00\x8c\xf6\x03\x47\xca\xd5\xe3\x3e\x1d\x16\ +\x6d\x96\x2d\xd2\xa6\xeb\x98\x6c\xd4\xd6\xc9\x36\xa3\x49\x8b\x9f\ +\xaa\x6c\xb3\xf9\x91\x36\x19\x65\x63\xbb\x68\x56\x6d\xd2\x51\x8a\ +\x2e\x5a\xeb\xbb\x1c\x1a\x1d\xee\x62\xd1\x9d\xbe\x7e\xba\x19\xbc\ +\x72\x84\x94\xde\xb1\x9b\xf8\x2a\xdd\xac\x66\x7f\xa5\xc1\xe0\x64\ +\xf4\xa6\xc8\x0f\xfb\x6d\xbe\x4e\xdb\xe9\x9d\x37\xf7\x71\x75\x3b\ +\x66\x30\x7a\x96\x8c\xa9\x90\x87\x03\x87\xb6\xd4\xd1\x51\x04\x8b\ +\x34\xaf\x13\xd0\x9e\x5f\xe3\xa4\xcb\x37\xac\xfe\xa9\x1f\x46\x3c\ +\x52\x56\x45\xfe\x29\xed\x47\x9b\xc7\x06\x73\x4b\x4e\x75\xc6\x28\ +\xdb\x49\x89\x3b\x60\xe7\x12\x56\xee\xd6\x63\xe1\xbf\xf3\x6c\x77\ +\x2c\x85\x93\xd3\x62\x03\xf0\x54\x4b\xd5\xc9\x9e\x6e\x1a\xae\x63\ +\xe4\x73\x51\xc4\x8f\xcb\x1d\xfa\xa7\xfe\x20\x04\xa9\x00\x95\x43\ +\x4a\xcd\xe4\x5c\xfb\x88\x5b\xcb\xbd\x09\x92\x00\xa5\x2f\x10\x73\ +\xf4\x8d\x1c\x05\xc1\x88\x20\x54\x73\x11\x29\x63\x84\xc5\x77\x83\ +\xef\x46\x09\x25\x75\x10\x72\x16\x49\xee\xb8\x13\x54\x20\xa5\xe0\ +\x82\x1b\x08\x05\x6a\x65\x28\x22\xef\x95\xd5\x3e\xf8\x3e\x80\xc0\ +\x42\x87\xeb\xb9\xb6\x11\x13\x9a\x09\x13\x70\x54\x2c\x8f\x42\x66\ +\xe6\x5a\x46\xc2\x6a\xab\x5d\x2d\xd3\xb4\xca\x5c\x63\x5d\xe3\x99\ +\x0b\x5c\xe4\x2d\x97\x5e\x91\x84\x71\x83\xcc\x0b\x4c\xa4\x84\xf6\ +\xd2\xcf\x95\x8a\x2c\x76\x77\x3a\xb0\x14\x03\xa7\x1c\x9f\x2b\x11\ +\x31\xe7\x95\xc6\x44\x54\x33\x2c\x3b\x97\x1e\x74\x64\x31\x97\xcc\ +\x60\x46\x48\x9c\x55\xba\x48\x70\xe9\xac\x0f\xb8\x8c\x0c\x99\x01\ +\x3d\x18\x2c\x3c\xe3\x3c\xe0\xba\x75\x89\xb0\x38\xa8\xe2\x2a\xe0\ +\xaa\x33\x83\x63\x5d\x8d\x09\x62\xd0\xe2\x36\xc2\x91\xb4\x51\x24\ +\x6a\x17\xc3\x37\xa7\xb8\x30\x3a\xe0\xad\x6d\x7e\x4e\xb4\x68\x8d\ +\xb3\x2a\x90\x30\x5c\x8f\x9e\x13\xd2\x12\x52\x72\x2d\xe6\x9c\xa5\ +\xa1\x0d\x40\x93\x4c\x73\x29\xb1\x21\x3c\xe1\xa5\xb6\xce\x90\x10\ +\xc6\xc0\x90\x39\x1c\xe5\x98\x70\xd6\x9a\x80\x1c\x45\x1f\x34\x27\ +\x8a\xe1\x00\x0e\xc1\xeb\xe6\x60\x4a\x54\x0f\x4a\x32\xc8\x58\x87\ +\x0d\x3b\x11\x3c\x1a\x81\xc3\x9d\x71\x81\x8e\x98\xa7\xcf\xdc\xc0\ +\x54\xc7\x18\xb9\x98\x82\xca\xdd\xdc\x53\x53\xa0\x24\xfc\x54\xeb\ +\xf0\x71\xe8\x23\xa5\xe9\x33\xb7\xf0\x9b\x95\x98\x15\xca\x6e\x37\ +\xb8\xd7\x7a\x23\x03\x20\x88\xd5\x3a\xf0\x2d\x83\x5f\x1c\x4d\xd3\ +\x46\x33\xb8\xcd\xc0\x91\xda\x2b\x53\x4f\x6b\x76\x6b\xa6\x09\x1f\ +\x00\x3c\xad\x01\xb0\xd6\x4a\xad\xb0\x14\x8c\x83\xc9\x46\x02\xa2\ +\xaa\xc5\x58\x0f\x31\x60\x32\x6c\x2d\x53\x04\xd6\x70\x40\xeb\xf8\ +\xe1\xf3\xd0\x54\x0d\xfd\xd9\x0e\xb9\x56\xe5\x45\x88\x02\x74\x17\ +\x57\x87\x22\x1d\x37\x14\x43\xa1\x06\x59\x10\x9d\xa1\xbe\x24\x65\ +\x89\x7f\xdd\x6f\x92\x0c\x45\xff\x79\xfa\x78\x4a\x1e\x35\x53\x80\ +\x2d\xdf\x9e\xf6\x7e\xe6\xdd\xb7\x42\x1d\x48\x0f\xdf\x40\x40\x13\ +\x60\x14\x43\x72\xfe\x92\xdc\x61\x40\x1d\x1e\x49\x66\x2d\xd8\x49\ +\x45\x8c\x72\x5d\x21\xd7\x6b\x64\x70\x49\x94\x20\x9c\x30\xdc\x42\ +\x66\x2d\xd6\x87\x9e\xb2\x91\xb4\xc4\x0e\x40\xb5\xf6\x0d\x66\x15\ +\x91\x8e\x34\x5c\x06\xb2\x81\x23\x2c\x56\x1c\xdc\x81\xdc\x53\x81\ +\x8a\x78\x9b\x41\x60\x0a\x06\xd4\x32\x9a\x2b\x44\xbd\xe0\x5c\x82\ +\x6d\x34\x14\x6b\x42\x69\x20\x29\x69\x94\x61\x76\x30\x9c\x40\xf8\ +\x08\x09\x47\xc9\x94\x0c\x39\x17\x36\x19\x46\x29\xd7\xae\x16\x82\ +\x48\x84\xf1\x5c\xb9\x91\x56\x97\x9a\x7d\x2e\x93\x1e\x25\xb3\x0c\ +\xda\x34\xa0\xeb\x47\x9b\xf1\xc4\x28\x2d\x0d\x8c\x84\x62\x44\x20\ +\x62\x9a\x3f\xe0\xfd\x09\xfe\x10\x5f\xcb\x1f\xe6\x29\x7f\xd8\x13\ +\xfa\xb0\x4f\xe9\x43\xf1\x57\xd0\x87\xfa\x79\xf4\xa1\x4f\xe9\xc3\ +\x9d\xd2\x87\x3a\xa2\x0f\x7d\x44\x1f\xe6\xf7\xc8\x1e\x63\x9a\xf8\ +\x19\x0d\x05\x2e\xae\x4e\x49\x21\xf5\xfe\xe1\x29\x31\x5c\x1d\xaa\ +\xea\x65\x5e\xe8\xb7\x18\x67\xfb\xdf\xa8\x06\x6a\xcb\x0c\xe2\x2c\ +\x90\x46\xb8\x17\x4b\x43\x0c\xa0\xb5\x46\x0d\x17\x82\x06\xb5\x95\ +\x2d\x01\x84\xd4\x15\x51\x99\x86\x93\xad\x02\x04\xea\xf0\x5a\xe1\ +\x24\xd5\x68\x94\x66\xba\x55\x93\x48\x70\x94\x49\x00\x32\x72\x54\ +\xbf\xeb\x38\xa1\xbd\x45\xa8\x21\xb2\x28\x3c\xdc\x4d\x89\xda\x2d\ +\x2c\xd5\x64\xa2\x1a\xa1\x3c\x97\x9c\xd0\xe1\x81\x49\xd0\x00\xc5\ +\x93\x6b\x00\x9c\x64\x1c\xa6\xb9\x3a\x92\x12\x20\xa2\x8a\x03\x38\ +\x0a\xa7\x29\xaf\x60\x01\xb2\x9b\xe9\x49\xd9\x28\xe2\x1d\x9b\x5b\ +\xaf\x5e\x0d\x83\x6f\x25\xb2\x8a\xa2\x88\x38\x8c\x02\x8b\x0e\x05\ +\x61\x95\x14\xbf\x27\x91\x3d\x0d\xec\x69\x5c\x4f\xc3\x7a\x1a\xc2\ +\xe9\xa0\x9e\xc6\x74\x22\xa4\x13\x11\x9d\x08\xde\xab\xe3\x19\xb2\ +\xdf\x6b\x44\x5f\x51\xc4\x27\x43\xba\xa5\x72\x80\x08\x80\x34\xa9\ +\x49\x16\x4a\x61\x8b\x36\x7e\x12\x34\x6f\xbc\xa9\xdf\x68\x21\x44\ +\x20\x65\x10\xb8\xb7\xa8\xa3\x86\x3c\x05\xfa\xc5\xb5\x3e\xa0\xa0\ +\x73\x14\x03\x72\xb1\x50\x02\xd1\x19\xe6\xa1\x17\x86\xb6\x90\x75\ +\xd5\x75\x1c\x9d\xec\x20\x52\xa8\xbe\x5c\x30\x8d\x8d\x50\x1e\x2c\ +\xe7\xa8\xaa\x54\x89\x9c\x36\x28\xa0\x52\x1b\x0b\x09\x2a\xb3\x92\ +\xe8\x89\xb1\x8b\x77\xc4\xe1\xd4\x20\x70\x46\xc5\x1d\x0c\xad\x8d\ +\xd3\x24\x41\x81\xb2\xb8\x27\x9c\x4a\xea\xe4\x47\xd5\xb6\x8e\xf0\ +\xc9\x22\x23\xd0\x05\x80\x26\x70\x64\xa9\xa5\xe6\xa3\x93\x51\x23\ +\xa1\x8d\xf7\xb5\xac\x86\x99\x25\x59\x7d\x36\x4b\x66\x33\x45\xc8\ +\x25\x8a\x41\x43\xe1\xa9\xf2\x4a\xe0\x0d\x22\x43\x5b\xe0\xe4\x06\ +\x69\x81\x56\x46\x28\xa4\x03\x89\x3c\xea\xa7\xb2\x54\xc7\x6c\xad\ +\xe4\xd0\x96\x68\x54\xaf\xf9\x30\x0f\x07\x86\xbd\xb8\x79\xa0\xec\ +\x63\x9a\xc6\x96\x3a\xb2\x4e\x2b\x34\xf7\xbd\x61\x27\x92\x09\x6c\ +\x3a\xfe\x7a\xae\xf9\x42\xc9\x69\xea\xcd\x37\x84\x5f\x44\xdb\x7b\ +\xdc\x9f\xa8\xb3\x32\x48\x76\x5c\xcb\x24\x20\x6d\x90\xcf\x32\x72\ +\xd8\x8e\x2a\x8a\xa0\x96\x85\xda\x0a\x0c\x59\x34\x2f\x62\x54\x7d\ +\x9a\x96\x84\xa0\xc0\xf0\x51\x24\x33\x6d\x2f\x25\xa8\x83\xd4\xde\ +\xd6\xfd\x45\x3d\x9f\xd0\x01\x20\xbb\xa6\xe5\xd0\x5a\x38\x02\x07\ +\x5a\x5a\x63\xfc\x94\x68\x32\x58\xe6\xff\x8f\x46\x14\x3a\x46\x26\ +\x04\xe7\xa3\x30\x84\x27\x71\x78\x2e\x0c\x13\x51\x98\x08\xc2\x69\ +\x0c\x4e\xfd\xfd\xda\x08\x84\xe2\xab\x13\xa6\xd7\xab\xba\x3f\x02\ +\x84\x09\x2e\x62\x69\x41\xef\xf2\xa8\xdd\x6c\xda\xd4\x67\x62\xd6\ +\x65\x1b\x65\xda\x6a\x16\x17\xc9\xd3\x8b\x5e\xfb\x6e\x79\x14\xcf\ +\xe7\x82\x5b\x3f\x16\x87\x4d\xba\x4c\xef\x52\x64\xef\xfa\xc5\x70\ +\x8b\x5f\xe7\xc2\x37\x96\x36\xaf\xbf\x97\xec\x7c\x1b\x17\x9f\xd2\ +\xa2\x19\xbf\xcb\xca\xec\x2a\xdb\xd0\x12\xf5\xd7\x4d\x7a\xbe\xce\ +\xca\xfd\x06\xf3\xb3\x1d\x99\x71\x9e\xdf\xa5\xc5\xf5\x26\xbf\xef\ +\xc7\xd3\x5d\x8c\xff\xc2\xab\x38\xf9\x74\x53\xdb\xb7\x8c\x93\xe4\ +\xb0\x3d\x6c\xe2\x2a\x9d\x88\xea\xe8\xef\x14\xbd\xbb\xeb\xd7\xcc\ +\xac\xbd\xa4\x4d\x0c\x3f\xae\x66\x5a\x37\xa8\x9c\x18\x2e\x68\x76\ +\x77\x13\x9c\x18\x7e\x9c\x1a\x6e\x6e\xbc\xa2\xbb\xc9\xf5\xcb\x07\ +\x71\xd0\x2b\xcf\xfb\x6f\x01\x0b\xd0\xba\x50\xc1\x68\xef\x46\xec\ +\x05\xad\x91\xd2\x00\xeb\xea\xcb\x7f\x93\x62\xfd\xcd\x95\x08\x0f\ +\x89\xca\x15\x93\xef\xfe\x40\xea\x6f\x87\xd4\xd0\xfd\x81\xd5\x69\ +\xac\x8a\xfe\xb5\x01\xb0\xea\xa5\xd1\x8e\x49\xf1\x1c\x56\xc7\x95\ +\x10\x0d\x14\x3e\xdf\xcc\x2b\x31\xd7\xe4\xa4\x3a\x79\x25\x16\xb6\ +\xe1\x70\x47\xdf\xe9\x1b\xc3\x07\x25\xae\xfb\x2e\xe9\xca\x83\xc6\ +\x59\xa2\xaf\x36\x91\x42\xf7\x2a\x35\xdc\x6e\x01\x20\xd6\x88\x70\ +\x71\x12\x9a\xda\x21\xc9\xa4\x32\x73\x7a\x49\x82\x3e\x93\x74\x9c\ +\xf1\xce\xce\xe9\x8d\x96\x47\xf3\x08\x09\xae\x4b\xce\x9b\x79\x3f\ +\x89\xf5\xef\x61\x9a\x57\xdd\x28\x70\xce\x4a\x09\x4b\x70\x95\x42\ +\x47\xeb\x27\x45\x53\xc5\x56\xbf\xbe\xdd\xf9\x62\x6f\xfa\x8a\xc6\ +\x74\x94\xe2\xd3\x51\x47\xff\x2d\xad\xf0\x8a\xf1\xa7\x71\x9f\xbc\ +\x17\xd7\x91\xfe\xc5\xc2\xee\xe8\x4f\x07\x4e\x20\x5d\x18\x5d\x93\ +\x84\xb2\x6d\xd4\x39\x5d\x06\xb8\xa2\x3b\x12\xb5\x37\xc2\xe2\xfa\ +\x2a\xe8\x26\x83\xcb\x99\xac\xdf\x7b\x5a\xea\xaf\x02\x5f\xc7\x97\ +\x13\xa7\x4b\xdc\xae\x81\x1a\x24\x8c\x44\x0b\xec\xe8\x12\xad\xe9\ +\xb5\x9d\x9f\x10\x4d\xc5\xc5\x7d\x65\x1b\x7a\xb1\xb8\xb9\x3c\xbb\ +\xa0\x3f\x00\x5e\x9e\xfd\x07\x1b\x72\x19\xbf\ \x00\x00\x0f\x23\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ @@ -37539,6 +37712,10 @@ qt_resource_name = "\ \x08\x62\x03\xc7\ \x00\x44\ \x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x44\x00\x72\x00\x61\x00\x66\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0f\ +\x0d\xf5\x38\xa7\ +\x00\x44\ +\x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x43\x00\x6c\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ \x00\x11\ \x0b\x07\x6b\x27\ \x00\x53\ @@ -37588,8 +37765,8 @@ qt_resource_name = "\ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\ -\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x4f\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x34\x00\x00\x00\x1b\ +\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x50\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x35\x00\x00\x00\x1b\ \x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x16\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x11\x00\x00\x00\x05\ \x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x06\x43\xc1\ @@ -37617,24 +37794,24 @@ qt_resource_struct = "\ \x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x6b\xbd\ \x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xbd\x6a\ \x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x1f\x87\ -\x00\x00\x0a\x5a\x00\x01\x00\x00\x00\x01\x00\x08\xd3\xbf\ +\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xde\x6f\ \x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x08\x51\ \x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x89\x07\ \x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe1\xa5\ \x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb2\xd6\ \x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x59\x16\ -\x00\x00\x0a\xaa\x00\x01\x00\x00\x00\x01\x00\x08\xef\xcf\ +\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xfa\x7f\ \x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xd6\x8c\ \x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xe7\x69\ \x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x76\x71\ \x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xdc\x0b\ \x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa1\xcc\ \x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xcc\x20\ -\x00\x00\x09\xe4\x00\x00\x00\x00\x00\x01\x00\x08\xb6\x05\ +\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc0\xb5\ \x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x97\xb4\ \x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x23\x70\ -\x00\x00\x09\x9c\x00\x01\x00\x00\x00\x01\x00\x08\xa2\x0f\ -\x00\x00\x09\xbe\x00\x01\x00\x00\x00\x01\x00\x08\xac\x71\ +\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xac\xbf\ +\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xb7\x21\ \x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x11\x57\ \x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x8f\xfb\ \x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x08\x5d\ @@ -37643,14 +37820,14 @@ qt_resource_struct = "\ \x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x80\x11\ \x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xc9\x78\ \x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xf7\x73\ -\x00\x00\x0a\x7a\x00\x00\x00\x00\x00\x01\x00\x08\xde\x59\ +\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xe9\x09\ \x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x4c\x1f\ \x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\x9f\xbb\ -\x00\x00\x0a\xda\x00\x00\x00\x00\x00\x01\x00\x08\xfb\xa8\ -\x00\x00\x09\x74\x00\x00\x00\x00\x00\x01\x00\x08\x92\xe8\ +\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x06\x58\ +\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\x9d\x98\ \x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb4\xdb\ \x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x28\x30\ -\x00\x00\x0a\x0a\x00\x00\x00\x00\x00\x01\x00\x08\xbe\x92\ +\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xc9\x42\ \x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x5e\x5e\ \x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xbf\xc7\ \x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x44\x85\ @@ -37660,7 +37837,8 @@ qt_resource_struct = "\ \x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x5f\x8b\ \x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x07\xfc\xeb\ \x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x0f\xb1\ -\x00\x00\x0a\x30\x00\x01\x00\x00\x00\x01\x00\x08\xc9\x3d\ +\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd3\xed\ +\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x92\xe8\ \x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xef\x2a\ \x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xed\x19\ \x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x3c\xc5\ diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 9ae60310d7..1bcbadbc8c 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -188,7 +188,8 @@ class DraftWorkbench (Workbench): self.modList = ["Draft_Move","Draft_Rotate","Draft_Offset", "Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale", "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint", - "Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array"] + "Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array", + "Draft_Clone"] self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup", "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap", "Draft_ShowSnapBar"] diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc index 5dfc9edfde..c2ac4a36d1 100644 --- a/src/Mod/Draft/Resources/Draft.qrc +++ b/src/Mod/Draft/Resources/Draft.qrc @@ -52,6 +52,7 @@ icons/Snap_Extension.svg icons/Snap_Ortho.svg icons/Snap_Near.svg + icons/Draft_Clone.svg patterns/concrete.svg patterns/cross.svg patterns/line.svg diff --git a/src/Mod/Draft/Resources/icons/Draft_Clone.svg b/src/Mod/Draft/Resources/icons/Draft_Clone.svg new file mode 100755 index 0000000000..2084513660 --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Draft_Clone.svg @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + From 7b2e15bedf5743fda7439581203619aae29cd9e7 Mon Sep 17 00:00:00 2001 From: logari81 Date: Sat, 5 May 2012 08:32:32 +0200 Subject: [PATCH 173/351] FreeGCS: Variables naming and comments improvements --- src/Mod/Sketcher/App/freegcs/GCS.cpp | 128 +++++++++++++++------------ src/Mod/Sketcher/App/freegcs/GCS.h | 11 ++- 2 files changed, 76 insertions(+), 63 deletions(-) diff --git a/src/Mod/Sketcher/App/freegcs/GCS.cpp b/src/Mod/Sketcher/App/freegcs/GCS.cpp index d17e79b5c2..c608c9bd0b 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/freegcs/GCS.cpp @@ -209,9 +209,9 @@ int System::addConstraintP2PDistance(Point &p1, Point &p2, double *distance, int } int System::addConstraintP2PAngle(Point &p1, Point &p2, double *angle, - double incr_angle, int tagId) + double incrAngle, int tagId) { - Constraint *constr = new ConstraintP2PAngle(p1, p2, angle, incr_angle); + Constraint *constr = new ConstraintP2PAngle(p1, p2, angle, incrAngle); constr->setTag(tagId); return addConstraint(constr); } @@ -379,28 +379,28 @@ int System::addConstraintPerpendicularCircle2Arc(Point ¢er, double *radius, Arc &a, int tagId) { addConstraintP2PDistance(a.start, center, radius, tagId); - double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2; - double tang_angle = *a.startAngle + incr_angle; + double incrAngle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2; + double tangAngle = *a.startAngle + incrAngle; double dx = *(a.start.x) - *(center.x); double dy = *(a.start.y) - *(center.y); - if (dx * cos(tang_angle) + dy * sin(tang_angle) > 0) - return addConstraintP2PAngle(center, a.start, a.startAngle, incr_angle, tagId); + if (dx * cos(tangAngle) + dy * sin(tangAngle) > 0) + return addConstraintP2PAngle(center, a.start, a.startAngle, incrAngle, tagId); else - return addConstraintP2PAngle(center, a.start, a.startAngle, -incr_angle, tagId); + return addConstraintP2PAngle(center, a.start, a.startAngle, -incrAngle, tagId); } int System::addConstraintPerpendicularArc2Circle(Arc &a, Point ¢er, double *radius, int tagId) { addConstraintP2PDistance(a.end, center, radius, tagId); - double incr_angle = *(a.startAngle) < *(a.endAngle) ? -M_PI/2 : M_PI/2; - double tang_angle = *a.endAngle + incr_angle; + double incrAngle = *(a.startAngle) < *(a.endAngle) ? -M_PI/2 : M_PI/2; + double tangAngle = *a.endAngle + incrAngle; double dx = *(a.end.x) - *(center.x); double dy = *(a.end.y) - *(center.y); - if (dx * cos(tang_angle) + dy * sin(tang_angle) > 0) - return addConstraintP2PAngle(center, a.end, a.endAngle, incr_angle, tagId); + if (dx * cos(tangAngle) + dy * sin(tangAngle) > 0) + return addConstraintP2PAngle(center, a.end, a.endAngle, incrAngle, tagId); else - return addConstraintP2PAngle(center, a.end, a.endAngle, -incr_angle, tagId); + return addConstraintP2PAngle(center, a.end, a.endAngle, -incrAngle, tagId); } int System::addConstraintPerpendicularArc2Arc(Arc &a1, bool reverse1, @@ -452,15 +452,15 @@ int System::addConstraintTangent(Circle &c, Arc &a, int tagId) int System::addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId) { addConstraintP2PCoincident(p2, a.start, tagId); - double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2; - return addConstraintP2PAngle(p1, p2, a.startAngle, incr_angle, tagId); + double incrAngle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2; + return addConstraintP2PAngle(p1, p2, a.startAngle, incrAngle, tagId); } int System::addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId) { addConstraintP2PCoincident(p1, a.end, tagId); - double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2; - return addConstraintP2PAngle(p1, p2, a.endAngle, incr_angle, tagId); + double incrAngle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2; + return addConstraintP2PAngle(p1, p2, a.endAngle, incrAngle, tagId); } int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId) @@ -548,16 +548,19 @@ void System::rescaleConstraint(int id, double coeff) void System::initSolution(VEC_pD ¶ms) { + // - identifies any decoupled subsystems and partitions the original + // system into corresponding components // - Stores the current parameters in the vector "reference" // - Identifies the equality constraints tagged with ids >= 0 // and prepares a corresponding system reduction // - Organizes the rest of constraints into two subsystems for // tag ids >=0 and < 0 respectively and applies the // system reduction specified in the previous step - MAP_pD_I params_index; + MAP_pD_I pIndex; for (int i=0; i < int(params.size()); ++i) - params_index[params[i]] = i; + pIndex[params[i]] = i; + // partitioning into decoupled components Graph g; for (int i=0; i < int(params.size() + clist.size()); i++) boost::add_vertex(g); @@ -568,14 +571,14 @@ void System::initSolution(VEC_pD ¶ms) VEC_pD &cparams = c2p[*constr]; for (VEC_pD::const_iterator param=cparams.begin(); param != cparams.end(); ++param) { - MAP_pD_I::const_iterator it = params_index.find(*param); - if (it != params_index.end()) + MAP_pD_I::const_iterator it = pIndex.find(*param); + if (it != pIndex.end()) boost::add_edge(cvtid, it->second, g); } } VEC_I components(boost::num_vertices(g)); - int components_size = boost::connected_components(g, &components[0]); + int componentsSize = boost::connected_components(g, &components[0]); clearReference(); for (VEC_pD::const_iterator param=params.begin(); @@ -592,9 +595,9 @@ void System::initSolution(VEC_pD ¶ms) constr != clist.end(); ++constr) { if ((*constr)->getTag() >= 0 && (*constr)->getTypeId() == Equal) { MAP_pD_I::const_iterator it1,it2; - it1 = params_index.find((*constr)->params()[0]); - it2 = params_index.find((*constr)->params()[1]); - if (it1 != params_index.end() && it2 != params_index.end()) { + it1 = pIndex.find((*constr)->params()[0]); + it2 = pIndex.find((*constr)->params()[1]); + if (it1 != pIndex.end() && it2 != pIndex.end()) { eliminated.insert(*constr); double *p_kept = reduced_params[it1->second]; double *p_replaced = reduced_params[it2->second]; @@ -609,9 +612,9 @@ void System::initSolution(VEC_pD ¶ms) reductionmap[params[i]] = reduced_params[i]; } - std::vector< std::vector > clists0(components_size), - clists1(components_size), - clists2(components_size); + std::vector< std::vector > clists0(componentsSize), + clists1(componentsSize), + clists2(componentsSize); int i = int(params.size()); for (std::vector::const_iterator constr=clist.begin(); constr != clist.end(); ++constr, i++) { @@ -626,14 +629,14 @@ void System::initSolution(VEC_pD ¶ms) } } - std::vector< std::vector > plists(components_size); + std::vector< std::vector > plists(componentsSize); for (int i=0; i < int(params.size()); ++i) { int id = components[i]; plists[id].push_back(params[i]); } clearSubSystems(); - for (int cid=0; cid < components_size; cid++) { + for (int cid=0; cid < componentsSize; cid++) { subsyslist.push_back(std::vector(0)); if (clists0[cid].size() > 0) subsyslist[cid].push_back(new SubSystem(clists0[cid], plists[cid], reductionmap)); @@ -729,13 +732,13 @@ int System::solve_BFGS(SubSystem *subsys, bool isFine) double convergence = isFine ? XconvergenceFine : XconvergenceRough; int maxIterNumber = MaxIterations * xsize; - double diverging_lim = 1e6*err + 1e12; + double divergingLim = 1e6*err + 1e12; for (int iter=1; iter < maxIterNumber; iter++) { if (h.norm() <= convergence || err <= smallF) break; - if (err > diverging_lim || err != err) // check for diverging and NaN + if (err > divergingLim || err != err) // check for diverging and NaN break; y = grad; @@ -793,7 +796,7 @@ int System::solve_LM(SubSystem* subsys) e*=-1; int maxIterNumber = MaxIterations * xsize; - double diverging_lim = 1e6*e.squaredNorm() + 1e12; + double divergingLim = 1e6*e.squaredNorm() + 1e12; double eps=1e-10, eps1=1e-80; double tau=1e-3; @@ -807,7 +810,7 @@ int System::solve_LM(SubSystem* subsys) stop = 1; break; } - else if (err > diverging_lim || err != err) { // check for diverging and NaN + else if (err > divergingLim || err != err) { // check for diverging and NaN stop = 6; break; } @@ -937,7 +940,7 @@ int System::solve_DL(SubSystem* subsys) double fx_inf = fx.lpNorm(); int maxIterNumber = MaxIterations * xsize; - double diverging_lim = 1e6*err + 1e12; + double divergingLim = 1e6*err + 1e12; double delta=0.1; double alpha=0.; @@ -954,7 +957,7 @@ int System::solve_DL(SubSystem* subsys) stop = 2; else if (iter >= maxIterNumber) stop = 4; - else if (err > diverging_lim || err != err) { // check for diverging and NaN + else if (err > divergingLim || err != err) { // check for diverging and NaN stop = 6; } else { @@ -1107,7 +1110,7 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) double convergence = isFine ? XconvergenceFine : XconvergenceRough; int maxIterNumber = MaxIterations * xsize; - double diverging_lim = 1e6*subsysA->error() + 1e12; + double divergingLim = 1e6*subsysA->error() + 1e12; double mu = 0; lambda.setZero(); @@ -1202,7 +1205,7 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) double err = subsysA->error(); if (h.norm() <= convergence && err <= smallF) break; - if (err > diverging_lim || err != err) // check for diverging and NaN + if (err > divergingLim || err != err) // check for diverging and NaN break; } @@ -1236,11 +1239,22 @@ void System::undoSolution() resetToReference(); } -int System::diagnose(VEC_pD ¶ms, VEC_I &conflicting) +int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags) { // Analyses the constrainess grad of the system and provides feedback - // The vector "conflicting" will hold a group of conflicting constraints - conflicting.clear(); + // The vector "conflictingTags" will hold a group of conflicting constraints + + // Hint 1: Only constraints with tag >= 0 are taken into account + // Hint 2: Constraints tagged with 0 are treated as high priority + // constraints and they are excluded from the returned + // list of conflicting constraints. Therefore, this function + // will provide no feedback about possible conflicts between + // two high priority constraints. For this reason, tagging + // constraints with 0 should be used carefully. + if (!isInit()) + return -1; + + conflictingTags.clear(); std::vector conflictingIndex; VEC_I tags; Eigen::MatrixXd J(clist.size(), params.size()); @@ -1259,39 +1273,39 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflicting) if (J.rows() > 0) { Eigen::FullPivHouseholderQR qrJT(J.topRows(count).transpose()); Eigen::MatrixXd Q = qrJT.matrixQ (); - int params_num = qrJT.rows(); - int constr_num = qrJT.cols(); + int paramsNum = qrJT.rows(); + int constrNum = qrJT.cols(); int rank = qrJT.rank(); Eigen::MatrixXd R; - if (constr_num >= params_num) + if (constrNum >= paramsNum) R = qrJT.matrixQR().triangularView(); else - R = qrJT.matrixQR().topRows(constr_num) + R = qrJT.matrixQR().topRows(constrNum) .triangularView(); - if (constr_num > rank) { // conflicting constraints + if (constrNum > rank) { // conflicting constraints for (int i=1; i < rank; i++) { // eliminate non zeros above pivot assert(R(i,i) != 0); for (int row=0; row < i; row++) { if (R(row,i) != 0) { double coef=R(row,i)/R(i,i); - R.block(row,i+1,1,constr_num-i-1) -= coef * R.block(i,i+1,1,constr_num-i-1); + R.block(row,i+1,1,constrNum-i-1) -= coef * R.block(i,i+1,1,constrNum-i-1); R(row,i) = 0; } } } - conflictingIndex.resize(constr_num-rank); - for (int j=rank; j < constr_num; j++) { + conflictingIndex.resize(constrNum-rank); + for (int j=rank; j < constrNum; j++) { for (int row=0; row < rank; row++) { if (fabs(R(row,j)) > 1e-10) { - int orig_col = qrJT.colsPermutation().indices()[row]; - conflictingIndex[j-rank].push_back(orig_col); + int origCol = qrJT.colsPermutation().indices()[row]; + conflictingIndex[j-rank].push_back(origCol); } } - int orig_col = qrJT.colsPermutation().indices()[j]; - conflictingIndex[j-rank].push_back(orig_col); + int origCol = qrJT.colsPermutation().indices()[j]; + conflictingIndex[j-rank].push_back(origCol); } SET_I tags_set; @@ -1301,14 +1315,14 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflicting) } } tags_set.erase(0); // exclude constraints tagged with zero - conflicting.resize(tags_set.size()); - std::copy(tags_set.begin(), tags_set.end(), conflicting.begin()); + conflictingTags.resize(tags_set.size()); + std::copy(tags_set.begin(), tags_set.end(), conflictingTags.begin()); - if (params_num == rank) // over-constrained - return params_num - constr_num; + if (paramsNum == rank) // over-constrained + return paramsNum - constrNum; } - return params_num - rank; + return paramsNum - rank; } return params.size(); } diff --git a/src/Mod/Sketcher/App/freegcs/GCS.h b/src/Mod/Sketcher/App/freegcs/GCS.h index f17f585c92..5cd1466eaf 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.h +++ b/src/Mod/Sketcher/App/freegcs/GCS.h @@ -54,11 +54,10 @@ namespace GCS std::map c2p; // constraint to parameter adjacency list std::map > p2c; // parameter to constraint adjacency list - // each row of subsyslist contains 3 subsystems. + // each row of subsyslist contains up to 3 subsystems. // the first one has the highest priority, always used as the primary subsystem - // the second one is normally used as secondary subsystem, it is considered primary - // only if the first one is missing - // the rhird one has the lowest priority, always used as secondary system + // the second one is used as secondary subsystem + // the third one is used as secondary system and serves as a preconditioner std::vector< std::vector > subsyslist; void clearSubSystems(); @@ -90,7 +89,7 @@ namespace GCS double *difference, int tagId=0); int addConstraintP2PDistance(Point &p1, Point &p2, double *distance, int tagId=0); int addConstraintP2PAngle(Point &p1, Point &p2, double *angle, - double incr_angle, int tagId=0); + double incrAngle, int tagId=0); int addConstraintP2PAngle(Point &p1, Point &p2, double *angle, int tagId=0); int addConstraintP2LDistance(Point &p, Line &l, double *distance, int tagId=0); int addConstraintPointOnLine(Point &p, Line &l, int tagId=0); @@ -160,7 +159,7 @@ namespace GCS bool isInit() const { return init; } - int diagnose(VEC_pD ¶ms, VEC_I &conflicting); + int diagnose(VEC_pD ¶ms, VEC_I &conflictingTags); }; /////////////////////////////////////// From c9fa928b8029c550a65345e708244c7ca6f19326 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 5 May 2012 16:11:41 +0200 Subject: [PATCH 174/351] 0000646: Expose BRepOffsetAPI_MakePipeShell to python --- src/Mod/Part/App/AppPart.cpp | 6 + .../App/BRepOffsetAPI_MakePipeShellPy.xml | 107 ++++++++ .../App/BRepOffsetAPI_MakePipeShellPyImp.cpp | 248 ++++++++++++++++++ src/Mod/Part/App/CMakeLists.txt | 3 + src/Mod/Part/App/Makefile.am | 4 + 5 files changed, 368 insertions(+) create mode 100644 src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPy.xml create mode 100644 src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 48eba53431..875f04cd4c 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -74,6 +74,7 @@ #include "SurfaceOfExtrusionPy.h" #include "SurfaceOfRevolutionPy.h" #include "ToroidPy.h" +#include "BRepOffsetAPI_MakePipeShellPy.h" #include "PartFeaturePy.h" #include "PropertyGeometryList.h" @@ -125,6 +126,11 @@ void PartExport initPart() Base::Interpreter().addType(&Part::PartFeaturePy ::Type,partModule,"Feature"); + PyObject* brepModule = Py_InitModule3("BRepOffsetAPI", 0, "BrepOffsetAPI"); + Py_INCREF(brepModule); + PyModule_AddObject(partModule, "BRepOffsetAPI", brepModule); + Base::Interpreter().addType(&Part::BRepOffsetAPI_MakePipeShellPy::Type,brepModule,"MakePipeShell"); + Part::TopoShape ::init(); Part::PropertyPartShape ::init(); Part::PropertyGeometryList ::init(); diff --git a/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPy.xml b/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPy.xml new file mode 100644 index 0000000000..1f375a4371 --- /dev/null +++ b/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPy.xml @@ -0,0 +1,107 @@ + + + + + + Describes a portion of a circle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0: BRepBuilderAPI_Transformed + 1: BRepBuilderAPI_RightCorner + 2: BRepBuilderAPI_RoundCorner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp b/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp new file mode 100644 index 0000000000..8e587c8601 --- /dev/null +++ b/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp @@ -0,0 +1,248 @@ +/*************************************************************************** + * Copyright (c) 2012 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +#endif + +#include "TopoShapePy.h" +#include "BRepOffsetAPI_MakePipeShellPy.h" +#include "BRepOffsetAPI_MakePipeShellPy.cpp" +#include "Tools.h" +#include +#include + +using namespace Part; + +PyObject *BRepOffsetAPI_MakePipeShellPy::PyMake(struct _typeobject *, PyObject *args, PyObject *) // Python wrapper +{ + // create a new instance of BRepOffsetAPI_MakePipeShellPy and the Twin object + PyObject* obj; + if (!PyArg_ParseTuple(args, "O!",&(TopoShapePy::Type),&obj)) + return 0; + const TopoDS_Shape& wire = static_cast(obj)->getTopoShapePtr()->_Shape; + if (!wire.IsNull() && wire.ShapeType() == TopAbs_WIRE) { + return new BRepOffsetAPI_MakePipeShellPy(new BRepOffsetAPI_MakePipeShell(TopoDS::Wire(wire))); + } + + PyErr_SetString(PyExc_Exception, "A valid wire is needed as argument"); + return 0; +} + +// constructor method +int BRepOffsetAPI_MakePipeShellPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +// returns a string which represents the object e.g. when printed in python +std::string BRepOffsetAPI_MakePipeShellPy::representation(void) const +{ + return std::string(""); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::setFrenetMode(PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O!",&PyBool_Type,&obj)) + return 0; + this->getBRepOffsetAPI_MakePipeShellPtr()->SetMode(obj==Py_True); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::setTrihedronMode(PyObject *args) +{ + PyObject *pnt, *dir; + if (!PyArg_ParseTuple(args, "O!O!",&Base::VectorPy::Type,&pnt + ,&Base::VectorPy::Type,&dir)) + return 0; + gp_Pnt p = Base::convertTo(Py::Vector(pnt,false).toVector()); + gp_Dir d = Base::convertTo(Py::Vector(dir,false).toVector()); + this->getBRepOffsetAPI_MakePipeShellPtr()->SetMode(gp_Ax2(p,d)); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::setBiNormalMode(PyObject *args) +{ + PyObject *dir; + if (!PyArg_ParseTuple(args, "O!",&Base::VectorPy::Type,&dir)) + return 0; + gp_Dir d = Base::convertTo(Py::Vector(dir,false).toVector()); + this->getBRepOffsetAPI_MakePipeShellPtr()->SetMode(d); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::setSpineSupport(PyObject *args) +{ + PyObject *shape; + if (!PyArg_ParseTuple(args, "O!",&Part::TopoShapePy::Type,&shape)) + return 0; + const TopoDS_Shape& s = static_cast(shape)->getTopoShapePtr()->_Shape; + Standard_Boolean ok = this->getBRepOffsetAPI_MakePipeShellPtr()->SetMode(s); + return Py::new_reference_to(Py::Boolean(ok ? true : false)); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::setAuxiliarySpine(PyObject *args) +{ + PyObject *spine, *curv, *keep; + if (!PyArg_ParseTuple(args, "O!O!O!",&Part::TopoShapePy::Type,&spine + ,&PyBool_Type,&curv + ,&PyBool_Type,&keep)) + return 0; + const TopoDS_Shape& s = static_cast(spine)->getTopoShapePtr()->_Shape; + if (s.IsNull() || s.ShapeType() != TopAbs_WIRE) { + PyErr_SetString(PyExc_TypeError, "spine is not a wire"); + return 0; + } + this->getBRepOffsetAPI_MakePipeShellPtr()->SetMode(TopoDS::Wire(s), curv==Py_True, keep==Py_True); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::add(PyObject *args) +{ + PyObject *prof, *curv=0, *keep=0; + if (!PyArg_ParseTuple(args, "O!|O!O!",&Part::TopoShapePy::Type,&prof + ,&PyBool_Type,&curv + ,&PyBool_Type,&keep)) + return 0; + const TopoDS_Shape& s = static_cast(prof)->getTopoShapePtr()->_Shape; + this->getBRepOffsetAPI_MakePipeShellPtr()->Add(s, curv==Py_True, keep==Py_True); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::remove(PyObject *args) +{ + PyObject *prof; + if (!PyArg_ParseTuple(args, "O!",&Part::TopoShapePy::Type,&prof)) + return 0; + const TopoDS_Shape& s = static_cast(prof)->getTopoShapePtr()->_Shape; + this->getBRepOffsetAPI_MakePipeShellPtr()->Delete(s); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::isReady(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + Standard_Boolean ok = this->getBRepOffsetAPI_MakePipeShellPtr()->IsReady(); + return Py::new_reference_to(Py::Boolean(ok ? true : false)); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::getStatus(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + Standard_Integer val = this->getBRepOffsetAPI_MakePipeShellPtr()->GetStatus(); + return Py::new_reference_to(Py::Int(val)); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::makeSolid(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + Standard_Boolean ok = this->getBRepOffsetAPI_MakePipeShellPtr()->MakeSolid(); + return Py::new_reference_to(Py::Boolean(ok ? true : false)); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::build(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + this->getBRepOffsetAPI_MakePipeShellPtr()->Build(); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::shape(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + const TopoDS_Shape& shape = this->getBRepOffsetAPI_MakePipeShellPtr()->Shape(); + return new TopoShapePy(new TopoShape(shape)); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::firstShape(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + TopoDS_Shape shape = this->getBRepOffsetAPI_MakePipeShellPtr()->FirstShape(); + return new TopoShapePy(new TopoShape(shape)); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::lastShape(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + TopoDS_Shape shape = this->getBRepOffsetAPI_MakePipeShellPtr()->LastShape(); + return new TopoShapePy(new TopoShape(shape)); +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::generated(PyObject *args) +{ + //PyObject *shape; + //if (!PyArg_ParseTuple(args, "O!",&Part::TopoShapePy::Type,&shape)) + // return 0; + //const TopoDS_Shape& s = static_cast(shape)->getTopoShapePtr()->_Shape; + //const TopTools_ListOfShape& list = this->getBRepOffsetAPI_MakePipeShellPtr()->Generated(s); + + //Py::List shapes; + //for (int i=1; i<=list.Extent(); i++) { + // const TopoDS_Shape& s = list. + //} + //return Py::new_reference_to(shapes); + PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); + return 0; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::setTolerance(PyObject *args) +{ + double tol3d, boundTol, tolAngular; + if (!PyArg_ParseTuple(args, "ddd",&tol3d,&boundTol,&tolAngular)) + return 0; + this->getBRepOffsetAPI_MakePipeShellPtr()->SetTolerance(tol3d, boundTol, tolAngular); + Py_Return; +} + +PyObject* BRepOffsetAPI_MakePipeShellPy::setTransitionMode(PyObject *args) +{ + int mode; + if (!PyArg_ParseTuple(args, "i",&mode)) + return 0; + this->getBRepOffsetAPI_MakePipeShellPtr()->SetTransitionMode(BRepBuilderAPI_TransitionMode(mode)); + Py_Return; +} + +PyObject *BRepOffsetAPI_MakePipeShellPy::getCustomAttributes(const char* attr) const +{ + return 0; +} + +int BRepOffsetAPI_MakePipeShellPy::setCustomAttributes(const char* attr, PyObject *obj) +{ + return 0; +} diff --git a/src/Mod/Part/App/CMakeLists.txt b/src/Mod/Part/App/CMakeLists.txt index bd0cb791a6..20a33407b3 100644 --- a/src/Mod/Part/App/CMakeLists.txt +++ b/src/Mod/Part/App/CMakeLists.txt @@ -61,6 +61,7 @@ generate_from_xml(TopoShapeShellPy) generate_from_xml(TopoShapeSolidPy) generate_from_xml(TopoShapeVertexPy) generate_from_xml(TopoShapeWirePy) +generate_from_xml(BRepOffsetAPI_MakePipeShellPy) SET(Features_SRCS FeaturePartBoolean.cpp @@ -203,6 +204,8 @@ SET(Python_SRCS TopoShapeVertexPyImp.cpp TopoShapeWirePy.xml TopoShapeWirePyImp.cpp + BRepOffsetAPI_MakePipeShellPy.xml + BRepOffsetAPI_MakePipeShellPyImp.cpp ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) diff --git a/src/Mod/Part/App/Makefile.am b/src/Mod/Part/App/Makefile.am index 91c711564e..7784278143 100644 --- a/src/Mod/Part/App/Makefile.am +++ b/src/Mod/Part/App/Makefile.am @@ -4,6 +4,7 @@ lib_LTLIBRARIES=libPart.la Part.la BUILT_SOURCES=\ ArcPy.cpp \ ArcOfCirclePy.cpp \ + BRepOffsetAPI_MakePipeShellPy.cpp \ CirclePy.cpp \ EllipsePy.cpp \ HyperbolaPy.cpp \ @@ -42,6 +43,7 @@ BUILT_SOURCES=\ libPart_la_BUILT=\ ArcPy.h \ ArcOfCirclePy.h \ + BRepOffsetAPI_MakePipeShellPy.h \ CirclePy.h \ EllipsePy.h \ HyperbolaPy.h \ @@ -81,6 +83,7 @@ libPart_la_SOURCES=\ AppPartPy.cpp \ ArcPyImp.cpp \ ArcOfCirclePyImp.cpp \ + BRepOffsetAPI_MakePipeShellPyImp.cpp \ CirclePyImp.cpp \ CrossSection.cpp \ EllipsePyImp.cpp \ @@ -260,6 +263,7 @@ EXTRA_DIST = \ OpenCascadeAll.h \ ArcPy.xml \ ArcOfCirclePy.xml \ + BRepOffsetAPI_MakePipeShellPy.xml \ CirclePy.xml \ EllipsePy.xml \ HyperbolaPy.xml \ From 4b1c918f2d90d6f1ac641874b8dbe0e277a0ad69 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 5 May 2012 16:19:39 +0200 Subject: [PATCH 175/351] 0000646: Expose BRepOffsetAPI_MakePipeShell to python --- .../App/BRepOffsetAPI_MakePipeShellPyImp.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp b/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp index 8e587c8601..2017e86d23 100644 --- a/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp +++ b/src/Mod/Part/App/BRepOffsetAPI_MakePipeShellPyImp.cpp @@ -29,6 +29,7 @@ # include # include # include +# include #endif #include "TopoShapePy.h" @@ -204,19 +205,19 @@ PyObject* BRepOffsetAPI_MakePipeShellPy::lastShape(PyObject *args) PyObject* BRepOffsetAPI_MakePipeShellPy::generated(PyObject *args) { - //PyObject *shape; - //if (!PyArg_ParseTuple(args, "O!",&Part::TopoShapePy::Type,&shape)) - // return 0; - //const TopoDS_Shape& s = static_cast(shape)->getTopoShapePtr()->_Shape; - //const TopTools_ListOfShape& list = this->getBRepOffsetAPI_MakePipeShellPtr()->Generated(s); + PyObject *shape; + if (!PyArg_ParseTuple(args, "O!",&Part::TopoShapePy::Type,&shape)) + return 0; + const TopoDS_Shape& s = static_cast(shape)->getTopoShapePtr()->_Shape; + const TopTools_ListOfShape& list = this->getBRepOffsetAPI_MakePipeShellPtr()->Generated(s); - //Py::List shapes; - //for (int i=1; i<=list.Extent(); i++) { - // const TopoDS_Shape& s = list. - //} - //return Py::new_reference_to(shapes); - PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); - return 0; + Py::List shapes; + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(list); it.More(); it.Next()) { + const TopoDS_Shape& s = it.Value(); + shapes.append(Py::asObject(new TopoShapePy(new TopoShape(s)))); + } + return Py::new_reference_to(shapes); } PyObject* BRepOffsetAPI_MakePipeShellPy::setTolerance(PyObject *args) From 2ded296857abb751619c64a98457619ea8d07535 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 7 May 2012 11:18:10 +0200 Subject: [PATCH 176/351] 0000697: Text boxes to set dimension constraints insert a space between thousands and hundreds digits that makes the data invalid. --- src/Mod/Sketcher/Gui/EditDatumDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp index 8fe503c376..58f1f027a6 100644 --- a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp +++ b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp @@ -103,7 +103,7 @@ void EditDatumDialog::exec(bool atCursor) if (dlg.exec()) { bool ok; - double newDatum = ui_ins_datum.lineEdit->text().toDouble(&ok); + double newDatum = QLocale::system().toDouble(ui_ins_datum.lineEdit->text(), &ok); if (ok) { if (Constr->Type == Sketcher::Angle) newDatum = Base::toRadians(newDatum); From 3b2dc816ce6b4f7d6058e3d1118e05bc07165ccd Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 7 May 2012 11:40:30 +0200 Subject: [PATCH 177/351] 0000689: create Chamfers/Fillets from Face --- src/Mod/PartDesign/Gui/Command.cpp | 347 ++++++++++++++++++++++------- 1 file changed, 271 insertions(+), 76 deletions(-) diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index ddf3240840..c5fa4d2ad1 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -20,24 +20,36 @@ * * ***************************************************************************/ - -#include "PreCompiled.h" -#ifndef _PreComp_ -# include -# include -#endif - -#include -#include -#include -#include -#include -#include - -#include - - -using namespace std; + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +using namespace std; //=========================================================================== // Part_Pad @@ -331,35 +343,126 @@ CmdPartDesignFillet::CmdPartDesignFillet() sStatusTip = sToolTipText; sPixmap = "Part_Fillet"; } - -void CmdPartDesignFillet::activated(int iMsg) -{ - std::vector selection = getSelection().getSelectionEx(); - - if (selection.size() != 1) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("Select an edge, face or body. Only one body is allowed.")); - return; - } - - if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), - QObject::tr("Fillet works only on parts")); - return; - } - std::string SelString = selection[0].getAsPropertyLinkSubString(); - std::string FeatName = getUniqueObjectName("Fillet"); - - openCommand("Make Fillet"); - doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Fillet\",\"%s\")",FeatName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Base = %s",FeatName.c_str(),SelString.c_str()); - doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",selection[0].getFeatName()); - doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); - - copyVisual(FeatName.c_str(), "ShapeColor", selection[0].getFeatName()); - copyVisual(FeatName.c_str(), "LineColor", selection[0].getFeatName()); - copyVisual(FeatName.c_str(), "PointColor", selection[0].getFeatName()); -} + +void CmdPartDesignFillet::activated(int iMsg) +{ + std::vector selection = getSelection().getSelectionEx(); + + if (selection.size() != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge, face or body. Only one body is allowed.")); + return; + } + + if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), + QObject::tr("Fillet works only on parts")); + return; + } + + Part::Feature *base = static_cast(selection[0].getObject()); + + const Part::TopoShape& TopShape = base->Shape.getShape(); + if (TopShape._Shape.IsNull()){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Shape of selected Part is empty")); + return; + } + + TopTools_IndexedMapOfShape mapOfEdges; + TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace; + TopExp::MapShapesAndAncestors(TopShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace); + TopExp::MapShapes(TopShape._Shape, TopAbs_EDGE, mapOfEdges); + + std::vector SubNames = std::vector(selection[0].getSubNames()); + + int i = 0; + + while(i < SubNames.size()) + { + std::string aSubName = static_cast(SubNames.at(i)); + + if (aSubName.size() > 4 && aSubName.substr(0,4) == "Edge") { + TopoDS_Edge edge = TopoDS::Edge(TopShape.getSubShape(aSubName.c_str())); + const TopTools_ListOfShape& los = mapEdgeFace.FindFromKey(edge); + + if(los.Extent() != 2) + { + SubNames.erase(SubNames.begin()+i); + continue; + } + + const TopoDS_Shape& face1 = los.First(); + const TopoDS_Shape& face2 = los.Last(); + GeomAbs_Shape cont = BRep_Tool::Continuity(TopoDS::Edge(edge), + TopoDS::Face(face1), + TopoDS::Face(face2)); + if (cont != GeomAbs_C0) { + SubNames.erase(SubNames.begin()+i); + continue; + } + + i++; + } + else if(aSubName.size() > 4 && aSubName.substr(0,4) == "Face") { + TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(aSubName.c_str())); + + TopTools_IndexedMapOfShape mapOfFaces; + TopExp::MapShapes(face, TopAbs_EDGE, mapOfFaces); + + for(int j = 1; j <= mapOfFaces.Extent(); ++j) { + TopoDS_Edge edge = TopoDS::Edge(mapOfFaces.FindKey(j)); + + int id = mapOfEdges.FindIndex(edge); + + std::stringstream buf; + buf << "Edge"; + buf << id; + + if(std::find(SubNames.begin(),SubNames.end(),buf.str()) == SubNames.end()) + { + SubNames.push_back(buf.str()); + } + + } + + SubNames.erase(SubNames.begin()+i); + } + } + + if(SubNames.size() == 0){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("No Fillet possilbe on seleced faces/edges")); + return; + } + + std::string SelString; + SelString += "(App."; + SelString += "ActiveDocument";//getObject()->getDocument()->getName(); + SelString += "."; + SelString += selection[0].getFeatName(); + SelString += ",["; + for(std::vector::const_iterator it = SubNames.begin();it!=SubNames.end();++it){ + SelString += "\""; + SelString += *it; + SelString += "\""; + if(it != --SubNames.end()) + SelString += ","; + } + SelString += "])"; + + std::string FeatName = getUniqueObjectName("Fillet"); + + openCommand("Make Fillet"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Fillet\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Base = %s",FeatName.c_str(),SelString.c_str()); + doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",selection[0].getFeatName()); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + copyVisual(FeatName.c_str(), "ShapeColor", selection[0].getFeatName()); + copyVisual(FeatName.c_str(), "LineColor", selection[0].getFeatName()); + copyVisual(FeatName.c_str(), "PointColor", selection[0].getFeatName()); +} bool CmdPartDesignFillet::isActive(void) { @@ -382,35 +485,127 @@ CmdPartDesignChamfer::CmdPartDesignChamfer() sStatusTip = sToolTipText; sPixmap = "Part_Chamfer"; } - -void CmdPartDesignChamfer::activated(int iMsg) -{ - std::vector selection = getSelection().getSelectionEx(); - - if (selection.size() != 1) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("Select an edge, face or body. Only one body is allowed.")); - return; - } - - if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), - QObject::tr("Chamfer works only on parts")); - return; - } - std::string SelString = selection[0].getAsPropertyLinkSubString(); - std::string FeatName = getUniqueObjectName("Chamfer"); - - openCommand("Make Chamfer"); - doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Chamfer\",\"%s\")",FeatName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Base = %s",FeatName.c_str(),SelString.c_str()); - doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",selection[0].getFeatName()); - doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); - - copyVisual(FeatName.c_str(), "ShapeColor", selection[0].getFeatName()); - copyVisual(FeatName.c_str(), "LineColor", selection[0].getFeatName()); - copyVisual(FeatName.c_str(), "PointColor", selection[0].getFeatName()); -} + +void CmdPartDesignChamfer::activated(int iMsg) +{ + std::vector selection = getSelection().getSelectionEx(); + + if (selection.size() != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge, face or body. Only one body is allowed.")); + return; + } + + if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), + QObject::tr("Chamfer works only on parts")); + return; + } + + Part::Feature *base = static_cast(selection[0].getObject()); + + const Part::TopoShape& TopShape = base->Shape.getShape(); + + if (TopShape._Shape.IsNull()){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Shape of selected part is empty")); + return; + } + + TopTools_IndexedMapOfShape mapOfEdges; + TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace; + TopExp::MapShapesAndAncestors(TopShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace); + TopExp::MapShapes(TopShape._Shape, TopAbs_EDGE, mapOfEdges); + + std::vector SubNames = std::vector(selection[0].getSubNames()); + + int i = 0; + + while(i < SubNames.size()) + { + std::string aSubName = static_cast(SubNames.at(i)); + + if (aSubName.size() > 4 && aSubName.substr(0,4) == "Edge") { + TopoDS_Edge edge = TopoDS::Edge(TopShape.getSubShape(aSubName.c_str())); + const TopTools_ListOfShape& los = mapEdgeFace.FindFromKey(edge); + + if(los.Extent() != 2) + { + SubNames.erase(SubNames.begin()+i); + continue; + } + + const TopoDS_Shape& face1 = los.First(); + const TopoDS_Shape& face2 = los.Last(); + GeomAbs_Shape cont = BRep_Tool::Continuity(TopoDS::Edge(edge), + TopoDS::Face(face1), + TopoDS::Face(face2)); + if (cont != GeomAbs_C0) { + SubNames.erase(SubNames.begin()+i); + continue; + } + + i++; + } + else if(aSubName.size() > 4 && aSubName.substr(0,4) == "Face") { + TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(aSubName.c_str())); + + TopTools_IndexedMapOfShape mapOfFaces; + TopExp::MapShapes(face, TopAbs_EDGE, mapOfFaces); + + for(int j = 1; j <= mapOfFaces.Extent(); ++j) { + TopoDS_Edge edge = TopoDS::Edge(mapOfFaces.FindKey(j)); + + int id = mapOfEdges.FindIndex(edge); + + std::stringstream buf; + buf << "Edge"; + buf << id; + + if(std::find(SubNames.begin(),SubNames.end(),buf.str()) == SubNames.end()) + { + SubNames.push_back(buf.str()); + } + + } + + SubNames.erase(SubNames.begin()+i); + } + } + + if(SubNames.size() == 0){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("No Fillet possilbe on seleced faces/edges")); + return; + } + + std::string SelString; + SelString += "(App."; + SelString += "ActiveDocument";//getObject()->getDocument()->getName(); + SelString += "."; + SelString += selection[0].getFeatName(); + SelString += ",["; + for(std::vector::const_iterator it = SubNames.begin();it!=SubNames.end();++it){ + SelString += "\""; + SelString += *it; + SelString += "\""; + if(it != --SubNames.end()) + SelString += ","; + } + SelString += "])"; + + std::string FeatName = getUniqueObjectName("Chamfer"); + + openCommand("Make Chamfer"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Chamfer\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Base = %s",FeatName.c_str(),SelString.c_str()); + doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",selection[0].getFeatName()); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + copyVisual(FeatName.c_str(), "ShapeColor", selection[0].getFeatName()); + copyVisual(FeatName.c_str(), "LineColor", selection[0].getFeatName()); + copyVisual(FeatName.c_str(), "PointColor", selection[0].getFeatName()); +} bool CmdPartDesignChamfer::isActive(void) { From 612219ced85ff9f3bd188bcbc760ddf769f2632f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 9 May 2012 12:54:01 -0300 Subject: [PATCH 178/351] Fixed python online documentation (patch by msocorcim) --- src/Gui/OnlineDocumentation.cpp | 14 ++- src/Mod/Draft/Makefile.am | 163 ++++++++++++++++++-------------- 2 files changed, 101 insertions(+), 76 deletions(-) diff --git a/src/Gui/OnlineDocumentation.cpp b/src/Gui/OnlineDocumentation.cpp index 9f8032b893..985b9c0d12 100644 --- a/src/Gui/OnlineDocumentation.cpp +++ b/src/Gui/OnlineDocumentation.cpp @@ -232,9 +232,10 @@ QByteArray PythonOnlineHelp::loadResource(const QString& filename) const " return self.bigsection(dir, '#ffffff', '#ee77aa', contents)\n" "\n" "pydoc.html=FreeCADDoc()\n" + "title='FreeCAD Python Modules Index'\n" "\n" - "heading = pydoc.html.heading(\n" - "'Python: Index of Modules',\n" + "heading = pydoc.html.heading(" + "'Python: Index of Modules'," "'#ffffff', '#7799ee')\n" "def bltinlink(name):\n" " return '%s' % (name, name)\n" @@ -257,13 +258,16 @@ QByteArray PythonOnlineHelp::loadResource(const QString& filename) const " indices.append(ret)\n" "contents = heading + string.join(indices) + '''

\n" "\n" - "pydoc by Ka-Ping Yee <ping@lfw.org>'''\n"; + "pydoc by Ka-Ping Yee <ping@lfw.org>'''\n" + "htmldocument=pydoc.html.page(title,contents)\n"; PyObject* result = PyRun_String(cmd.constData(), Py_file_input, dict, dict); if (result) { Py_DECREF(result); - result = PyDict_GetItemString(dict, "contents"); + result = PyDict_GetItemString(dict, "htmldocument"); const char* contents = PyString_AsString(result); + res.append("HTTP/1.0 200 OK\n"); + res.append("Content-type: text/html\n"); res.append(contents); return res; } @@ -293,6 +297,8 @@ QByteArray PythonOnlineHelp::loadResource(const QString& filename) const Py_DECREF(result); result = PyDict_GetItemString(dict, "page"); const char* page = PyString_AsString(result); + res.append("HTTP/1.0 200 OK\n"); + res.append("Content-type: text/html\n"); res.append(page); } else { diff --git a/src/Mod/Draft/Makefile.am b/src/Mod/Draft/Makefile.am index fef1303c4d..2502ec4d21 100644 --- a/src/Mod/Draft/Makefile.am +++ b/src/Mod/Draft/Makefile.am @@ -39,78 +39,97 @@ EXTRA_DIST = \ CMakeLists.txt \ draft.dox \ Resources/Draft.qrc \ - Resources/translations/Draft_af.ts \ - Resources/translations/Draft_af.qm \ - Resources/translations/Draft_de.ts \ - Resources/translations/Draft_de.qm \ - Resources/translations/Draft_es.ts \ - Resources/translations/Draft_es.qm \ - Resources/translations/Draft_fi.ts \ - Resources/translations/Draft_fi.qm \ - Resources/translations/Draft_fr.ts \ - Resources/translations/Draft_fr.qm \ - Resources/translations/Draft_hr.ts \ - Resources/translations/Draft_hr.qm \ - Resources/translations/Draft_it.ts \ - Resources/translations/Draft_it.qm \ - Resources/translations/Draft_nl.ts \ - Resources/translations/Draft_nl.qm \ - Resources/translations/Draft_no.ts \ - Resources/translations/Draft_no.qm \ - Resources/translations/Draft_pl.ts \ - Resources/translations/Draft_pl.qm \ - Resources/translations/Draft_pt.ts \ - Resources/translations/Draft_pt.qm \ - Resources/translations/Draft_ru.ts \ - Resources/translations/Draft_ru.qm \ - Resources/translations/Draft_se.ts \ - Resources/translations/Draft_se.qm \ - Resources/translations/Draft_uk.ts \ - Resources/translations/Draft_uk.qm \ - Resources/translations/Draft_zh.ts \ - Resources/translations/Draft_zh.qm \ - Resources/icons/preferences-draft.svg \ - Resources/icons/Draft_AddPoint.svg \ - Resources/icons/Draft_AddToGroup.svg \ - Resources/icons/Draft_Apply.svg \ - Resources/icons/Draft_Arc.svg \ - Resources/icons/Draft_BSpline.svg \ - Resources/icons/Draft_Circle.svg \ - Resources/icons/Draft_Cursor.svg \ - Resources/icons/Draft_DelPoint.svg \ - Resources/icons/Draft_Dimension.svg \ - Resources/icons/Draft_Dot.svg \ - Resources/icons/Draft_Downgrade.svg \ - Resources/icons/Draft_Drawing.svg \ - Resources/icons/Draft_Edit.svg \ - Resources/icons/Draft_Finish.svg \ - Resources/icons/Draft_Line.svg \ - Resources/icons/Draft_Lock.svg \ - Resources/icons/Draft_Macro.svg \ - Resources/icons/Draft_Move.svg \ - Resources/icons/Draft_Offset.svg \ - Resources/icons/Draft_Point.svg \ - Resources/icons/Draft_Polygon.svg \ - Resources/icons/Draft_Rectangle.svg \ - Resources/icons/Draft_Rotate.svg \ - Resources/icons/Draft_Scale.svg \ - Resources/icons/Draft_SelectGroup.svg \ - Resources/icons/Draft_SelectPlane.svg \ - Resources/icons/Draft_SwitchMode.svg \ - Resources/icons/Draft_Text.svg \ - Resources/icons/Draft_Trimex.svg \ - Resources/icons/Draft_Upgrade.svg \ - Resources/icons/Draft_Wire.svg \ - Resources/icons/Draft_Wipe.svg \ - Resources/icons/Draft_WireToBSpline.svg \ - Resources/icons/Draft_Construction.svg \ - Resources/icons/Draft_Draft.svg \ Resources/icons/Draft_2DShapeView.svg \ + Resources/icons/Draft_AddPoint.svg \ + Resources/icons/Draft_AddToGroup.svg \ + Resources/icons/Draft_Apply.svg \ + Resources/icons/Draft_Arc.svg \ + Resources/icons/Draft_Array.svg \ + Resources/icons/Draft_BSpline.svg \ + Resources/icons/Draft_Circle.svg \ + Resources/icons/Draft_Clone.svg \ + Resources/icons/Draft_Construction.svg \ Resources/icons/Draft_Cursor.svg \ - Resources/patterns/concrete.svg \ - Resources/patterns/cross.svg \ - Resources/patterns/line.svg \ - Resources/patterns/simple.svg \ - Resources/patterns/square.svg \ + Resources/icons/Draft_DelPoint.svg \ + Resources/icons/Draft_Dimension.svg \ + Resources/icons/Draft_Dot.svg \ + Resources/icons/Draft_Downgrade.svg \ + Resources/icons/Draft_Draft2Sketch.svg \ + Resources/icons/Draft_Draft.svg \ + Resources/icons/Draft_Drawing.svg \ + Resources/icons/Draft_Edit.svg \ + Resources/icons/Draft_Finish.svg \ + Resources/icons/Draft_Line.svg \ + Resources/icons/Draft_Lock.svg \ + Resources/icons/Draft_Macro.svg \ + Resources/icons/Draft_Move.svg \ + Resources/icons/Draft_Offset.svg \ + Resources/icons/Draft_Point.svg \ + Resources/icons/Draft_Polygon.svg \ + Resources/icons/Draft_Rectangle.svg \ + Resources/icons/Draft_Rotate.svg \ + Resources/icons/Draft_Scale.svg \ + Resources/icons/Draft_SelectGroup.svg \ + Resources/icons/Draft_SelectPlane.svg \ + Resources/icons/Draft_SwitchMode.svg \ + Resources/icons/Draft_Text.svg \ + Resources/icons/Draft_Trimex.svg \ + Resources/icons/Draft_Upgrade.svg \ + Resources/icons/Draft_Wipe.svg \ + Resources/icons/Draft_Wire.svg \ + Resources/icons/Draft_WireToBSpline.svg \ + Resources/icons/preferences-draft.svg \ + Resources/icons/Snap_Angle.svg \ + Resources/icons/Snap_Center.svg \ + Resources/icons/Snap_Endpoint.svg \ + Resources/icons/Snap_Extension.svg \ + Resources/icons/Snap_Grid.svg \ + Resources/icons/Snap_Intersection.svg \ + Resources/icons/Snap_Lock.svg \ + Resources/icons/Snap_Midpoint.svg \ + Resources/icons/Snap_Near.svg \ + Resources/icons/Snap_Ortho.svg \ + Resources/icons/Snap_Parallel.svg \ + Resources/icons/Snap_Perpendicular.svg \ + Resources/patterns/concrete.svg \ + Resources/patterns/cross.svg \ + Resources/patterns/line.svg \ + Resources/patterns/simple.svg \ + Resources/patterns/square.svg \ + Resources/translations/Draft_af.qm \ + Resources/translations/Draft_af.ts \ + Resources/translations/Draft_de.qm \ + Resources/translations/Draft_de.ts \ + Resources/translations/Draft_es.qm \ + Resources/translations/Draft_es.ts \ + Resources/translations/Draft_fi.qm \ + Resources/translations/Draft_fi.ts \ + Resources/translations/Draft_fr.qm \ + Resources/translations/Draft_fr.ts \ + Resources/translations/Draft_hr.qm \ + Resources/translations/Draft_hr.ts \ + Resources/translations/Draft_hu.qm \ + Resources/translations/Draft_hu.ts \ + Resources/translations/Draft_it.qm \ + Resources/translations/Draft_it.ts \ + Resources/translations/Draft_ja.qm \ + Resources/translations/Draft_ja.ts \ + Resources/translations/Draft_nl.qm \ + Resources/translations/Draft_nl.ts \ + Resources/translations/Draft_no.qm \ + Resources/translations/Draft_no.ts \ + Resources/translations/Draft_pl.qm \ + Resources/translations/Draft_pl.ts \ + Resources/translations/Draft_pt.qm \ + Resources/translations/Draft_pt.ts \ + Resources/translations/Draft_ru.qm \ + Resources/translations/Draft_ru.ts \ + Resources/translations/Draft_se.qm \ + Resources/translations/Draft_se.ts \ + Resources/translations/Draft_uk.qm \ + Resources/translations/Draft_uk.ts \ + Resources/translations/Draft_zh.qm \ + Resources/translations/Draft_zh.ts \ Resources/ui/userprefs-base.ui \ - Resources/ui/userprefs-import.ui + Resources/ui/userprefs-import.ui + From f88d724b1ee21505a2b25b4941318d63e8f37017 Mon Sep 17 00:00:00 2001 From: msocorcim Date: Wed, 9 May 2012 16:47:56 -0400 Subject: [PATCH 179/351] fix parsing "git branch" response so currently checked out branch is returned --- src/Tools/SubWCRev.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Tools/SubWCRev.py b/src/Tools/SubWCRev.py index 843f0796be..53b8a2eb66 100644 --- a/src/Tools/SubWCRev.py +++ b/src/Tools/SubWCRev.py @@ -153,7 +153,10 @@ class GitControl(VersionControl): self.url = r.groups()[0] break self.hash=os.popen("git log -1 --pretty=format:%H").read() - self.branch=os.popen("git branch").read().split('\n')[0][2:] + for self.branch in os.popen("git branch").read().split('\n'): + if re.match( "\*", self.branch ) != None: + break + self.branch=self.branch[2:] return True def printInfo(self): From cfaa15ebc2aa5c84897109ba082a5a58db179a29 Mon Sep 17 00:00:00 2001 From: msocorcim Date: Wed, 9 May 2012 18:03:59 -0400 Subject: [PATCH 180/351] replace StartPage references to "FreeCAD default workbench" with "FreeCAD Complete workbench" --- .../Gui/Resources/translations/StartPage.ts | 2 +- .../Resources/translations/StartPage_af.qm | Bin 8137 -> 8138 bytes .../Resources/translations/StartPage_af.ts | 4 ++-- .../Resources/translations/StartPage_de.qm | Bin 8167 -> 8168 bytes .../Resources/translations/StartPage_de.ts | 4 ++-- .../Resources/translations/StartPage_es.qm | Bin 8319 -> 8320 bytes .../Resources/translations/StartPage_es.ts | 2 +- .../Resources/translations/StartPage_fi.qm | Bin 8125 -> 8126 bytes .../Resources/translations/StartPage_fi.ts | 4 ++-- .../Resources/translations/StartPage_fr.qm | Bin 8939 -> 8940 bytes .../Resources/translations/StartPage_fr.ts | 2 +- .../Resources/translations/StartPage_hr.qm | Bin 8303 -> 8304 bytes .../Resources/translations/StartPage_hr.ts | 2 +- .../Resources/translations/StartPage_hu.qm | Bin 8389 -> 8390 bytes .../Resources/translations/StartPage_hu.ts | 2 +- .../Resources/translations/StartPage_it.qm | Bin 8517 -> 8518 bytes .../Resources/translations/StartPage_it.ts | 2 +- .../Resources/translations/StartPage_ja.qm | Bin 7415 -> 7416 bytes .../Resources/translations/StartPage_ja.ts | 2 +- .../Resources/translations/StartPage_nl.qm | Bin 8417 -> 8418 bytes .../Resources/translations/StartPage_nl.ts | 2 +- .../Resources/translations/StartPage_no.qm | Bin 8127 -> 8128 bytes .../Resources/translations/StartPage_no.ts | 4 ++-- .../Resources/translations/StartPage_pl.qm | Bin 8403 -> 8404 bytes .../Resources/translations/StartPage_pl.ts | 2 +- .../Resources/translations/StartPage_pt.qm | Bin 8433 -> 8434 bytes .../Resources/translations/StartPage_pt.ts | 2 +- .../Resources/translations/StartPage_ru.qm | Bin 8307 -> 8308 bytes .../Resources/translations/StartPage_ru.ts | 2 +- .../Resources/translations/StartPage_se.qm | Bin 8177 -> 8178 bytes .../Resources/translations/StartPage_se.ts | 2 +- .../Resources/translations/StartPage_uk.qm | Bin 8127 -> 8128 bytes .../Resources/translations/StartPage_uk.ts | 4 ++-- .../Resources/translations/StartPage_zh.qm | Bin 6385 -> 6386 bytes .../Resources/translations/StartPage_zh.ts | 2 +- src/Mod/Start/StartPage/StartPage.py | 2 +- 36 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage.ts b/src/Mod/Start/Gui/Resources/translations/StartPage.ts index 351391a346..f34c864d6e 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage.ts @@ -139,7 +139,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_af.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_af.qm index a62fcc758e8a76890977b1e4b42b17d7d0b47a80..8f915edb5e5a726fa295cafdd8f9aefb3dd6a9fe 100644 GIT binary patch delta 18 ZcmX?Uf69J?6FZ~x - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_de.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_de.qm index 00eb940240dd9945ad098b61427b3b1ff5f57ea7..573d336fe8f2926ef5a928050f98459bc7281651 100644 GIT binary patch delta 18 ZcmaEE|H6KQ8#|-(+fx2CD!7 delta 24 fcmaE1|J;6q8#{YSYFc7xPRZm2BC?ya*=r>Le|QO1 diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts index a394715b70..fb8eee8d9e 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts @@ -140,8 +140,8 @@ - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_es.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_es.qm index 1f1b3340ad379991d8eeaa47239f15b382a90b96..cb1ecc850c52819d89e2b5a280bb8193627ce7bf 100644 GIT binary patch delta 21 ccmezG(BQaX7dwY@er`cdYDwzmgY5ex0A`N~1ONa4 delta 34 qcmZp0{O_<~7rS6eYFc7xPKiQ!eo=N(YF={2 - FreeCAD default workbench + FreeCAD Complete workbench Entorno de trabajo predeterminado de FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_fi.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_fi.qm index 07b72ed6ac2758680b36c01ad672f23406d04d67..6b18866b425902c78eb50e865efd071b52519d24 100644 GIT binary patch delta 18 ZcmdmMzt4Vy13RPh - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_fr.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_fr.qm index b0deb5c621c13054d4267090a20a3a653b9f59a2..1af30245908c730faaa8c1e00cbeca3387f0b429 100644 GIT binary patch delta 18 acmaFu`o?v`6?R7F$@j!mHveG%ECm2oS_qo} delta 20 bcmaFk`r38F6?XQN)U?FXoRZCV*af5kW#$N) diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts index 36e72f5f0b..3598521433 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench Atelier par défaut FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_hr.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_hr.qm index 42ee820c832941a51f4b53c6b15f2a9c5dc41e6a..303541ace4c3f7e3c8554f450209d24955f736c2 100644 GIT binary patch delta 18 acmaFw@WElj1a?N}$!el1o42s - FreeCAD default workbench + FreeCAD Complete workbench Inicijalno FreeCAD radno okruženje diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_hu.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_hu.qm index 84aedcf29e7a7406f8089bf71c8d54cd635672e1..d1c60b3b33dfa77b0d68d402deb5fb9b4ea16696 100644 GIT binary patch delta 18 acmX@=c+7Fb9Ck+M$rYk1n-8$FN&)~#0tSHq delta 24 gcmX@+c+_#j9Cr4U)U?FXoRY~6qOzM0va?D80Dp!FD*ylh diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts index 1e7bbc2f29..6e46c89d20 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCAD alapértelmezett munkafelület diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_it.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_it.qm index e696ad3807e2a77143ef9fd8b3aa88a31d911c54..08408c5306c762133a4a7383d2b1f9f241632ec9 100644 GIT binary patch delta 18 acmX@=bj)eP6?R7F$tOfrHveGvl>`7z>IaJe delta 24 gcmX@+bku3X6?XQN)U?FXoRY~GL}fSsWcQT>0Efy7H2?qr diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts index 04d4fa1893..b9aa0b60ff 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench Ambiente di lavoro predefinito di FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_ja.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_ja.qm index 89fdd9e76e4f95a8daf9045f32a3a70995095444..ca9c3e5a8837f3f062fcc2d35992e1a3c1405845 100644 GIT binary patch delta 18 acmexv`NMKU0UM+9 - FreeCAD default workbench + FreeCAD Complete workbench FreeCADã®ãƒ‡ãƒ•ォルトワークベンムdiff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_nl.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_nl.qm index 43d54648e92288d77eae04992be5158384ffc68a..abf2a7236f2285de8cc070aa0cc08b216ce57938 100644 GIT binary patch delta 18 acmaFp_{ed?6m~}E$!(%4n|H8lN&)~&>IT~Y delta 24 gcmaFl_|S2~6n6HM)U?FXoRZ0XqOzNJvTI5L0ECVSg#Z8m diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts index 1f37830bad..6ab92c4d3f 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCAD standaard werkbank diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_no.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_no.qm index 81164c1ea104a0377860e7dc30ad86a98149b927..e920714c27ca3dd82388c2bec72e1c2d3dda3770 100644 GIT binary patch delta 18 ZcmdmQf53i&6+5HzTpc035V diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts index c526fdc84b..9b24bb94ae 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts @@ -140,8 +140,8 @@ - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pl.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_pl.qm index 9d2baeffa96df8d84e856a4b7cc20db61f00aa50..5e35f5b0abb5e4c0ee7e3329d695115e1b3f2c7e 100644 GIT binary patch delta 18 acmccYc*SwU9(G3O$!Vf0n;)=$mH+@vNe8$9 delta 24 gcmccOc-e8o9(MMW)U?FXoRZ0TqOzMGvVWEU0ERURVgLXD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts index 922ec55976..00d0e9e4ce 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench DomyÅ›lne Å›rodowisko FreeCADa diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pt.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_pt.qm index 7edfbb4cd7944920e5a1df8bd35730103e8efcad..3f1299c58059c1bcae0e6914e60fc7b71731226b 100644 GIT binary patch delta 18 acmez9_{niY1v{hjPi diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts index 767755c562..120f704820 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench Bancada padrão do FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_ru.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_ru.qm index f13fc55c4d89c85688d5bc002066eb84db04cc31..fc8b49b01abd8ced286920799379ba538bdadbbe 100644 GIT binary patch delta 18 acmezD@Wo+62RozlWFAqK&1=|?O8@{$%?Aho delta 20 bcmez3@Y!KQ2RnO8YFc7xPRZs8>`x>BVq*x| diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts index 90d45ed33a..dda7c4891f 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench ИнÑтрументарий FreeCAD по умолчанию diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_se.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_se.qm index 05cb07df745adb00547a65df8521c09b63d84b28..af6a58a2b1c1d15a5c9f8833f4af15f4dded0d16 100644 GIT binary patch delta 18 Zcmexp|H*!X13RPh+nX2J-*_ delta 24 fcmexl|IvPf13P<4YFc7xPRZm8BC?xP*?T1bf?5fk diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts index 7310ccd02a..32a4cc2a89 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCAD standard arbetsbänk diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_uk.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_uk.qm index b49021a9ea2472ad3f7ab857c9cc479ab073987b..5ac3d9b66d29ce756979524b595daba07f2419a8 100644 GIT binary patch delta 18 ZcmdmQf53i&4LhUr diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts index 38a2e414a8..7ae42e6e1a 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts @@ -140,8 +140,8 @@ - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_zh.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_zh.qm index 04c3229e0a71b8af16c91b4d36ae3e84eba67d54..05b637001acf8006ef000418411ce1d00cd4cb28 100644 GIT binary patch delta 18 acmexp_{ng?0aixm$t8R$o1d`q3IhO5*#`6g delta 24 gcmexl_|b5~0ao^u)U?FXoRY~ke6pLLvhoT80Ec-Ao&W#< diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts index ccf91a0f56..b740960fc1 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCADé»˜è®¤å·¥ä½œå° diff --git a/src/Mod/Start/StartPage/StartPage.py b/src/Mod/Start/StartPage/StartPage.py index 4ae0511e11..c3983a86f5 100644 --- a/src/Mod/Start/StartPage/StartPage.py +++ b/src/Mod/Start/StartPage/StartPage.py @@ -52,7 +52,7 @@ text27 = translate("StartPage","The Mesh Workbench is used to work with M text28 = translate("StartPage","FreeCAD offers you several tools to convert between Mesh and Part objects.") text29 = translate("StartPage","Work with Meshes") text30 = translate("StartPage","The complete workbench") -text31 = translate("StartPage","FreeCAD default workbench") +text31 = translate("StartPage","FreeCAD Complete workbench") text32 = translate("StartPage","populated with some of the most commonly used tools.") text33 = translate("StartPage","file size:") text34 = translate("StartPage","creation time:") From e2813c845fd405fd61df3133c3801abf75320040 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 10 May 2012 10:41:10 +0200 Subject: [PATCH 181/351] fix typo --- src/App/PropertyFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 70b0f7edac..e1e4ade913 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -343,7 +343,7 @@ Property *PropertyFileIncluded::Copy(void) const bool done = file.renameFile(NewName.filePath().c_str()); assert(done); // remember the new name for the Undo - Base::Console().Log("Copy this=%p Befor=%s After=%s\n",p,p->_cValue.c_str(),NewName.filePath().c_str()); + Base::Console().Log("Copy this=%p Before=%s After=%s\n",p,p->_cValue.c_str(),NewName.filePath().c_str()); p->_cValue = NewName.filePath().c_str(); } From 435d4f82d7ede8fee38429e71a1696535c820411 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 10 May 2012 12:07:37 +0200 Subject: [PATCH 182/351] fix some issues when writing binary data into an XML file --- src/App/PropertyFile.cpp | 4 ++-- src/Base/Writer.cpp | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index e1e4ade913..13599c88a6 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -296,7 +296,7 @@ void PropertyFileIncluded::Restore(Base::XMLReader &reader) void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const { - std::ifstream from(_cValue.c_str()); + Base::ifstream from(Base::FileInfo(_cValue.c_str())); if (!from) throw Base::Exception("PropertyFileIncluded::SaveDocFile() " "File in document transient dir deleted"); @@ -311,7 +311,7 @@ void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader) { - std::ofstream to(_cValue.c_str()); + Base::ofstream to(Base::FileInfo(_cValue.c_str())); if (!to) throw Base::Exception("PropertyFileIncluded::RestoreDocFile() " "File in document transient dir deleted"); diff --git a/src/Base/Writer.cpp b/src/Base/Writer.cpp index 74742f2a6f..01eecef6b5 100644 --- a/src/Base/Writer.cpp +++ b/src/Base/Writer.cpp @@ -32,6 +32,7 @@ #include "Exception.h" #include "Base64.h" #include "FileInfo.h" +#include "Stream.h" #include "Tools.h" #include @@ -59,19 +60,24 @@ Writer::~Writer() void Writer::insertAsciiFile(const char* FileName) { - std::ifstream from(FileName); - if (!from) throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); + Base::FileInfo fi(FileName); + Base::ifstream from(fi); + if (!from) + throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); Stream() << "" << endl; } void Writer::insertBinFile(const char* FileName) { - std::ifstream from(FileName); - if (!from) throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); + Base::FileInfo fi(FileName); + Base::ifstream from(fi, std::ios::in | std::ios::binary); + if (!from) + throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); Stream() << " Date: Wed, 9 May 2012 16:47:56 -0400 Subject: [PATCH 183/351] fix parsing "git branch" response so currently checked out branch is returned --- src/Tools/SubWCRev.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Tools/SubWCRev.py b/src/Tools/SubWCRev.py index 843f0796be..53b8a2eb66 100644 --- a/src/Tools/SubWCRev.py +++ b/src/Tools/SubWCRev.py @@ -153,7 +153,10 @@ class GitControl(VersionControl): self.url = r.groups()[0] break self.hash=os.popen("git log -1 --pretty=format:%H").read() - self.branch=os.popen("git branch").read().split('\n')[0][2:] + for self.branch in os.popen("git branch").read().split('\n'): + if re.match( "\*", self.branch ) != None: + break + self.branch=self.branch[2:] return True def printInfo(self): From 8905c5e8078f8e1eaa1b163c130d2afdc0d19f28 Mon Sep 17 00:00:00 2001 From: msocorcim Date: Wed, 9 May 2012 18:03:59 -0400 Subject: [PATCH 184/351] replace StartPage references to "FreeCAD default workbench" with "FreeCAD Complete workbench" --- .../Gui/Resources/translations/StartPage.ts | 2 +- .../Resources/translations/StartPage_af.qm | Bin 8137 -> 8138 bytes .../Resources/translations/StartPage_af.ts | 4 ++-- .../Resources/translations/StartPage_de.qm | Bin 8167 -> 8168 bytes .../Resources/translations/StartPage_de.ts | 4 ++-- .../Resources/translations/StartPage_es.qm | Bin 8319 -> 8320 bytes .../Resources/translations/StartPage_es.ts | 2 +- .../Resources/translations/StartPage_fi.qm | Bin 8125 -> 8126 bytes .../Resources/translations/StartPage_fi.ts | 4 ++-- .../Resources/translations/StartPage_fr.qm | Bin 8939 -> 8940 bytes .../Resources/translations/StartPage_fr.ts | 2 +- .../Resources/translations/StartPage_hr.qm | Bin 8303 -> 8304 bytes .../Resources/translations/StartPage_hr.ts | 2 +- .../Resources/translations/StartPage_hu.qm | Bin 8389 -> 8390 bytes .../Resources/translations/StartPage_hu.ts | 2 +- .../Resources/translations/StartPage_it.qm | Bin 8517 -> 8518 bytes .../Resources/translations/StartPage_it.ts | 2 +- .../Resources/translations/StartPage_ja.qm | Bin 7415 -> 7416 bytes .../Resources/translations/StartPage_ja.ts | 2 +- .../Resources/translations/StartPage_nl.qm | Bin 8417 -> 8418 bytes .../Resources/translations/StartPage_nl.ts | 2 +- .../Resources/translations/StartPage_no.qm | Bin 8127 -> 8128 bytes .../Resources/translations/StartPage_no.ts | 4 ++-- .../Resources/translations/StartPage_pl.qm | Bin 8403 -> 8404 bytes .../Resources/translations/StartPage_pl.ts | 2 +- .../Resources/translations/StartPage_pt.qm | Bin 8433 -> 8434 bytes .../Resources/translations/StartPage_pt.ts | 2 +- .../Resources/translations/StartPage_ru.qm | Bin 8307 -> 8308 bytes .../Resources/translations/StartPage_ru.ts | 2 +- .../Resources/translations/StartPage_se.qm | Bin 8177 -> 8178 bytes .../Resources/translations/StartPage_se.ts | 2 +- .../Resources/translations/StartPage_uk.qm | Bin 8127 -> 8128 bytes .../Resources/translations/StartPage_uk.ts | 4 ++-- .../Resources/translations/StartPage_zh.qm | Bin 6385 -> 6386 bytes .../Resources/translations/StartPage_zh.ts | 2 +- src/Mod/Start/StartPage/StartPage.py | 2 +- 36 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage.ts b/src/Mod/Start/Gui/Resources/translations/StartPage.ts index 351391a346..f34c864d6e 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage.ts @@ -139,7 +139,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_af.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_af.qm index a62fcc758e8a76890977b1e4b42b17d7d0b47a80..8f915edb5e5a726fa295cafdd8f9aefb3dd6a9fe 100644 GIT binary patch delta 18 ZcmX?Uf69J?6FZ~x - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_de.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_de.qm index 00eb940240dd9945ad098b61427b3b1ff5f57ea7..573d336fe8f2926ef5a928050f98459bc7281651 100644 GIT binary patch delta 18 ZcmaEE|H6KQ8#|-(+fx2CD!7 delta 24 fcmaE1|J;6q8#{YSYFc7xPRZm2BC?ya*=r>Le|QO1 diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts index a394715b70..fb8eee8d9e 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_de.ts @@ -140,8 +140,8 @@ - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_es.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_es.qm index 1f1b3340ad379991d8eeaa47239f15b382a90b96..cb1ecc850c52819d89e2b5a280bb8193627ce7bf 100644 GIT binary patch delta 21 ccmezG(BQaX7dwY@er`cdYDwzmgY5ex0A`N~1ONa4 delta 34 qcmZp0{O_<~7rS6eYFc7xPKiQ!eo=N(YF={2 - FreeCAD default workbench + FreeCAD Complete workbench Entorno de trabajo predeterminado de FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_fi.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_fi.qm index 07b72ed6ac2758680b36c01ad672f23406d04d67..6b18866b425902c78eb50e865efd071b52519d24 100644 GIT binary patch delta 18 ZcmdmMzt4Vy13RPh - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_fr.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_fr.qm index b0deb5c621c13054d4267090a20a3a653b9f59a2..1af30245908c730faaa8c1e00cbeca3387f0b429 100644 GIT binary patch delta 18 acmaFu`o?v`6?R7F$@j!mHveG%ECm2oS_qo} delta 20 bcmaFk`r38F6?XQN)U?FXoRZCV*af5kW#$N) diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts index 36e72f5f0b..3598521433 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_fr.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench Atelier par défaut FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_hr.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_hr.qm index 42ee820c832941a51f4b53c6b15f2a9c5dc41e6a..303541ace4c3f7e3c8554f450209d24955f736c2 100644 GIT binary patch delta 18 acmaFw@WElj1a?N}$!el1o42s - FreeCAD default workbench + FreeCAD Complete workbench Inicijalno FreeCAD radno okruženje diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_hu.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_hu.qm index 84aedcf29e7a7406f8089bf71c8d54cd635672e1..d1c60b3b33dfa77b0d68d402deb5fb9b4ea16696 100644 GIT binary patch delta 18 acmX@=c+7Fb9Ck+M$rYk1n-8$FN&)~#0tSHq delta 24 gcmX@+c+_#j9Cr4U)U?FXoRY~6qOzM0va?D80Dp!FD*ylh diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts index 1e7bbc2f29..6e46c89d20 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_hu.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCAD alapértelmezett munkafelület diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_it.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_it.qm index e696ad3807e2a77143ef9fd8b3aa88a31d911c54..08408c5306c762133a4a7383d2b1f9f241632ec9 100644 GIT binary patch delta 18 acmX@=bj)eP6?R7F$tOfrHveGvl>`7z>IaJe delta 24 gcmX@+bku3X6?XQN)U?FXoRY~GL}fSsWcQT>0Efy7H2?qr diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts index 04d4fa1893..b9aa0b60ff 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_it.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench Ambiente di lavoro predefinito di FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_ja.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_ja.qm index 89fdd9e76e4f95a8daf9045f32a3a70995095444..ca9c3e5a8837f3f062fcc2d35992e1a3c1405845 100644 GIT binary patch delta 18 acmexv`NMKU0UM+9 - FreeCAD default workbench + FreeCAD Complete workbench FreeCADã®ãƒ‡ãƒ•ォルトワークベンムdiff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_nl.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_nl.qm index 43d54648e92288d77eae04992be5158384ffc68a..abf2a7236f2285de8cc070aa0cc08b216ce57938 100644 GIT binary patch delta 18 acmaFp_{ed?6m~}E$!(%4n|H8lN&)~&>IT~Y delta 24 gcmaFl_|S2~6n6HM)U?FXoRZ0XqOzNJvTI5L0ECVSg#Z8m diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts index 1f37830bad..6ab92c4d3f 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_nl.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCAD standaard werkbank diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_no.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_no.qm index 81164c1ea104a0377860e7dc30ad86a98149b927..e920714c27ca3dd82388c2bec72e1c2d3dda3770 100644 GIT binary patch delta 18 ZcmdmQf53i&6+5HzTpc035V diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts index c526fdc84b..9b24bb94ae 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_no.ts @@ -140,8 +140,8 @@ - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pl.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_pl.qm index 9d2baeffa96df8d84e856a4b7cc20db61f00aa50..5e35f5b0abb5e4c0ee7e3329d695115e1b3f2c7e 100644 GIT binary patch delta 18 acmccYc*SwU9(G3O$!Vf0n;)=$mH+@vNe8$9 delta 24 gcmccOc-e8o9(MMW)U?FXoRZ0TqOzMGvVWEU0ERURVgLXD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts index 922ec55976..00d0e9e4ce 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_pl.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench DomyÅ›lne Å›rodowisko FreeCADa diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pt.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_pt.qm index 7edfbb4cd7944920e5a1df8bd35730103e8efcad..3f1299c58059c1bcae0e6914e60fc7b71731226b 100644 GIT binary patch delta 18 acmez9_{niY1v{hjPi diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts index 767755c562..120f704820 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_pt.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench Bancada padrão do FreeCAD diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_ru.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_ru.qm index f13fc55c4d89c85688d5bc002066eb84db04cc31..fc8b49b01abd8ced286920799379ba538bdadbbe 100644 GIT binary patch delta 18 acmezD@Wo+62RozlWFAqK&1=|?O8@{$%?Aho delta 20 bcmez3@Y!KQ2RnO8YFc7xPRZs8>`x>BVq*x| diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts index 90d45ed33a..dda7c4891f 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_ru.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench ИнÑтрументарий FreeCAD по умолчанию diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_se.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_se.qm index 05cb07df745adb00547a65df8521c09b63d84b28..af6a58a2b1c1d15a5c9f8833f4af15f4dded0d16 100644 GIT binary patch delta 18 Zcmexp|H*!X13RPh+nX2J-*_ delta 24 fcmexl|IvPf13P<4YFc7xPRZm8BC?xP*?T1bf?5fk diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts index 7310ccd02a..32a4cc2a89 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_se.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCAD standard arbetsbänk diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_uk.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_uk.qm index b49021a9ea2472ad3f7ab857c9cc479ab073987b..5ac3d9b66d29ce756979524b595daba07f2419a8 100644 GIT binary patch delta 18 ZcmdmQf53i&4LhUr diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts index 38a2e414a8..7ae42e6e1a 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_uk.ts @@ -140,8 +140,8 @@ - FreeCAD default workbench - FreeCAD default workbench + FreeCAD Complete workbench + FreeCAD Complete workbench diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_zh.qm b/src/Mod/Start/Gui/Resources/translations/StartPage_zh.qm index 04c3229e0a71b8af16c91b4d36ae3e84eba67d54..05b637001acf8006ef000418411ce1d00cd4cb28 100644 GIT binary patch delta 18 acmexp_{ng?0aixm$t8R$o1d`q3IhO5*#`6g delta 24 gcmexl_|b5~0ao^u)U?FXoRY~ke6pLLvhoT80Ec-Ao&W#< diff --git a/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts b/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts index ccf91a0f56..b740960fc1 100644 --- a/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts +++ b/src/Mod/Start/Gui/Resources/translations/StartPage_zh.ts @@ -140,7 +140,7 @@ - FreeCAD default workbench + FreeCAD Complete workbench FreeCADé»˜è®¤å·¥ä½œå° diff --git a/src/Mod/Start/StartPage/StartPage.py b/src/Mod/Start/StartPage/StartPage.py index 4ae0511e11..c3983a86f5 100644 --- a/src/Mod/Start/StartPage/StartPage.py +++ b/src/Mod/Start/StartPage/StartPage.py @@ -52,7 +52,7 @@ text27 = translate("StartPage","The Mesh Workbench is used to work with M text28 = translate("StartPage","FreeCAD offers you several tools to convert between Mesh and Part objects.") text29 = translate("StartPage","Work with Meshes") text30 = translate("StartPage","The complete workbench") -text31 = translate("StartPage","FreeCAD default workbench") +text31 = translate("StartPage","FreeCAD Complete workbench") text32 = translate("StartPage","populated with some of the most commonly used tools.") text33 = translate("StartPage","file size:") text34 = translate("StartPage","creation time:") From ba17ed0ee743cf58ac586669c4900aa2ca3f646e Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 11 May 2012 16:36:21 -0300 Subject: [PATCH 185/351] Added 0000698 : Draft Extrude --- src/Mod/Draft/DraftTools.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 39713964b6..ad61cf65d0 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -2676,8 +2676,10 @@ class Trimex(Modifier): self.ui.cross(True) self.shift = hasMod(arg,MODCONSTRAIN) self.alt = hasMod(arg,MODALT) + if self.extrudeMode: + arg["ShiftDown"] = False wp = not(self.extrudeMode and self.shift) - self.point,info = getPoint(self,arg,workingplane=wp)[0] + self.point,cp,info = getPoint(self,arg,workingplane=wp) if hasMod(arg,MODSNAP): self.snapped = None else: self.snapped = self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) if self.extrudeMode: @@ -2705,7 +2707,7 @@ class Trimex(Modifier): "redraws the ghost in extrude mode" self.newpoint = self.obj.Shape.Faces[0].CenterOfMass dvec = self.point.sub(self.newpoint) - if shift: delta = fcvec.project(dvec,self.normal) + if not shift: delta = fcvec.project(dvec,self.normal) else: delta = dvec if self.force: ratio = self.force/delta.Length From 9185bdcd8f5c4e28f3cb459c44f4d1e8975789d9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 13 May 2012 13:11:07 +0200 Subject: [PATCH 186/351] 0000702: Patch to fix compilation of FreeCAD with gcc 4.7 --- src/Mod/Fem/App/HypothesisPy.cpp | 2112 ++++++++--------- .../Mesh/App/WildMagic4/Wm4Query2Filtered.inl | 210 +- .../Mesh/App/WildMagic4/Wm4Query3Filtered.inl | 258 +- 3 files changed, 1290 insertions(+), 1290 deletions(-) diff --git a/src/Mod/Fem/App/HypothesisPy.cpp b/src/Mod/Fem/App/HypothesisPy.cpp index 755e8a5392..7dbe2f7224 100644 --- a/src/Mod/Fem/App/HypothesisPy.cpp +++ b/src/Mod/Fem/App/HypothesisPy.cpp @@ -1,1056 +1,1056 @@ -/*************************************************************************** - * Copyright (c) 2010 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - -#include "PreCompiled.h" -#include "HypothesisPy.h" -#include "FemMeshPy.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include - -using namespace Fem; - - -HypothesisPy::HypothesisPy(boost::shared_ptr h) - : hyp(h) -{ -} - -HypothesisPy::~HypothesisPy() -{ -} - -// ---------------------------------------------------------------------------- - -template -void SMESH_HypothesisPy::init_type(PyObject* module) -{ - // you must have overwritten the virtual functions - SMESH_HypothesisPy::behaviors().supportRepr(); - SMESH_HypothesisPy::behaviors().supportGetattr(); - SMESH_HypothesisPy::behaviors().supportSetattr(); - SMESH_HypothesisPy::behaviors().type_object()->tp_new = &PyMake; - - add_varargs_method("setLibName", &SMESH_HypothesisPy::setLibName, "setLibName(String)"); - add_varargs_method("getLibName", &SMESH_HypothesisPy::getLibName, "String getLibName()"); - add_varargs_method("setParameters", &SMESH_HypothesisPy::setParameters, "setParameters(String)"); - add_varargs_method("getParameters", &SMESH_HypothesisPy::getParameters, "String getParameters()"); - add_varargs_method("setLastParameters", &SMESH_HypothesisPy::setLastParameters, "setLastParameters(String)"); - add_varargs_method("getLastParameters", &SMESH_HypothesisPy::getLastParameters, "String getLastParameters()"); - add_varargs_method("clearParameters", &SMESH_HypothesisPy::clearParameters, "clearParameters()"); - add_varargs_method("isAuxiliary", &SMESH_HypothesisPy::isAuxiliary, "Bool isAuxiliary()"); - add_varargs_method("setParametersByMesh", &SMESH_HypothesisPy::setParametersByMesh, "setParametersByMesh(Mesh,Shape)"); - Base::Interpreter().addType(SMESH_HypothesisPy::behaviors().type_object(), - module,SMESH_HypothesisPy::behaviors().getName()); -} - -template -SMESH_HypothesisPy::SMESH_HypothesisPy(SMESH_Hypothesis* h) : hyp(h) -{ -} - -template -SMESH_HypothesisPy::~SMESH_HypothesisPy() -{ -} - -template -Py::Object SMESH_HypothesisPy::getattr(const char *name) -{ - if (strcmp(name,"this") == 0) - return Hypothesis(Py::asObject(new HypothesisPy(this->getHypothesis()))); - return Py::PythonExtension::getattr(name); -} - -template -Py::Object SMESH_HypothesisPy::repr() -{ - std::stringstream str; - str << hyp->GetName() << ", " << hyp->GetID(); - return Py::String(str.str()); -} - -template -Py::Object SMESH_HypothesisPy::setLibName(const Py::Tuple& args) -{ - std::string libName = (std::string)Py::String(args[0]); - hypothesis()->SetLibName(libName.c_str()); - return Py::None(); -} - -template -Py::Object SMESH_HypothesisPy::getLibName(const Py::Tuple& args) -{ - return Py::String(hypothesis()->GetLibName()); -} - -template -Py::Object SMESH_HypothesisPy::setParameters(const Py::Tuple& args) -{ - std::string paramName = (std::string)Py::String(args[0]); - hypothesis()->SetParameters(paramName.c_str()); - return Py::None(); -} - -template -Py::Object SMESH_HypothesisPy::getParameters(const Py::Tuple& args) -{ - return Py::String(hypothesis()->GetParameters()); -} - -template -Py::Object SMESH_HypothesisPy::setLastParameters(const Py::Tuple& args) -{ - std::string paramName = (std::string)Py::String(args[0]); - hypothesis()->SetLastParameters(paramName.c_str()); - return Py::None(); -} - -template -Py::Object SMESH_HypothesisPy::getLastParameters(const Py::Tuple& args) -{ - return Py::String(hypothesis()->GetLastParameters()); -} - -template -Py::Object SMESH_HypothesisPy::clearParameters(const Py::Tuple& args) -{ - hypothesis()->ClearParameters(); - return Py::None(); -} - -template -Py::Object SMESH_HypothesisPy::setParametersByMesh(const Py::Tuple& args) -{ - PyObject *mesh, *shape; - if (!PyArg_ParseTuple(args.ptr(), "O!O!", - &(Fem::FemMeshPy::Type), &mesh, - &(Part::TopoShapePy::Type), &shape)) - throw Py::Exception(); - Fem::FemMesh* m = static_cast(mesh)->getFemMeshPtr(); - const TopoDS_Shape& s = static_cast(shape)->getTopoShapePtr()->_Shape; - return Py::Boolean(hypothesis()->SetParametersByMesh(m->getSMesh(), s)); -} - -template -Py::Object SMESH_HypothesisPy::isAuxiliary(const Py::Tuple& args) -{ - return Py::Boolean(hypothesis()->IsAuxiliary()); -} - -template -PyObject *SMESH_HypothesisPy::PyMake(struct _typeobject *type, PyObject * args, PyObject * kwds) -{ - int hypId; - PyObject* obj; - if (!PyArg_ParseTuple(args, "iO!",&hypId,&(FemMeshPy::Type),&obj)) - return 0; - FemMesh* mesh = static_cast(obj)->getFemMeshPtr(); - return new T(hypId, 1, mesh->getGenerator()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Arithmetic1DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Arithmetic1D"); - behaviors().doc("StdMeshers_Arithmetic1D"); - - add_varargs_method("setLength", &StdMeshers_Arithmetic1DPy::setLength, "setLength()"); - add_varargs_method("getLength", &StdMeshers_Arithmetic1DPy::getLength, "getLength()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Arithmetic1DPy::StdMeshers_Arithmetic1DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Arithmetic1D(hypId, studyId, gen)) -{ -} - -StdMeshers_Arithmetic1DPy::~StdMeshers_Arithmetic1DPy() -{ -} - -Py::Object StdMeshers_Arithmetic1DPy::setLength(const Py::Tuple& args) -{ - hypothesis()-> - SetLength((double)Py::Float(args[0]), (bool)Py::Boolean(args[1])); - return Py::None(); -} - -Py::Object StdMeshers_Arithmetic1DPy::getLength(const Py::Tuple& args) -{ - int start; - if (!PyArg_ParseTuple(args.ptr(), "i",&start)) - throw Py::Exception(); - return Py::Float(hypothesis()-> - GetLength(start ? true : false)); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_AutomaticLengthPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_AutomaticLength"); - behaviors().doc("StdMeshers_AutomaticLength"); - - add_varargs_method("setFineness", &StdMeshers_AutomaticLengthPy::setFineness, "setFineness()"); - add_varargs_method("getFineness", &StdMeshers_AutomaticLengthPy::getFineness, "getFineness()"); - add_varargs_method("getLength", &StdMeshers_AutomaticLengthPy::getLength, "getLength()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_AutomaticLengthPy::StdMeshers_AutomaticLengthPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(0) -{ -} - -StdMeshers_AutomaticLengthPy::~StdMeshers_AutomaticLengthPy() -{ -} - -Py::Object StdMeshers_AutomaticLengthPy::setFineness(const Py::Tuple& args) -{ - double fine = (double)Py::Float(args[0]); - hypothesis()->SetFineness(fine); - return Py::None(); -} - -Py::Object StdMeshers_AutomaticLengthPy::getFineness(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetFineness()); -} - -namespace Py { - typedef ExtensionObject FemMesh; - typedef ExtensionObject TopoShape; - template<> bool FemMesh::accepts (PyObject *pyob) const - { - return (pyob && PyObject_TypeCheck(pyob, &(Fem::FemMeshPy::Type))); - } - template<> bool TopoShape::accepts (PyObject *pyob) const - { - return (pyob && PyObject_TypeCheck(pyob, &(Part::TopoShapePy::Type))); - } -} - -Py::Object StdMeshers_AutomaticLengthPy::getLength(const Py::Tuple& args) -{ - Py::FemMesh mesh(args[0]); - Py::Object shape_or_double(args[1]); - - Fem::FemMesh* m = mesh.extensionObject()->getFemMeshPtr(); - if (shape_or_double.type() == Py::Float().type()) { - double len = (double)Py::Float(shape_or_double); - return Py::Float(hypothesis()->GetLength(m->getSMesh(),len)); - } - else { - Py::TopoShape shape(shape_or_double); - const TopoDS_Shape& s = shape.extensionObject()->getTopoShapePtr()->_Shape; - return Py::Float(hypothesis()->GetLength(m->getSMesh(),s)); - } - - throw Py::Exception(); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_NotConformAllowedPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_NotConformAllowed"); - behaviors().doc("StdMeshers_NotConformAllowed"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_NotConformAllowedPy::StdMeshers_NotConformAllowedPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_NotConformAllowed(hypId, studyId, gen)) -{ -} - -StdMeshers_NotConformAllowedPy::~StdMeshers_NotConformAllowedPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_MaxLengthPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_MaxLength"); - behaviors().doc("StdMeshers_MaxLength"); - - add_varargs_method("setLength", &StdMeshers_MaxLengthPy::setLength, "setLength()"); - add_varargs_method("getLength", &StdMeshers_MaxLengthPy::getLength, "getLength()"); - add_varargs_method("havePreestimatedLength", &StdMeshers_MaxLengthPy::havePreestimatedLength, "havePreestimatedLength()"); - add_varargs_method("getPreestimatedLength", &StdMeshers_MaxLengthPy::getPreestimatedLength, "getPreestimatedLength()"); - add_varargs_method("setPreestimatedLength", &StdMeshers_MaxLengthPy::setPreestimatedLength, "setPreestimatedLength()"); - add_varargs_method("setUsePreestimatedLength", &StdMeshers_MaxLengthPy::setUsePreestimatedLength, "setUsePreestimatedLength()"); - add_varargs_method("getUsePreestimatedLength", &StdMeshers_MaxLengthPy::getUsePreestimatedLength, "getUsePreestimatedLength()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_MaxLengthPy::StdMeshers_MaxLengthPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_MaxLength(hypId, studyId, gen)) -{ -} - -StdMeshers_MaxLengthPy::~StdMeshers_MaxLengthPy() -{ -} - -Py::Object StdMeshers_MaxLengthPy::setLength(const Py::Tuple& args) -{ - hypothesis()->SetLength((double)Py::Float(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_MaxLengthPy::getLength(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetLength()); -} - -Py::Object StdMeshers_MaxLengthPy::havePreestimatedLength(const Py::Tuple& args) -{ - return Py::Boolean(hypothesis()->HavePreestimatedLength()); -} - -Py::Object StdMeshers_MaxLengthPy::getPreestimatedLength(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetPreestimatedLength()); -} - -Py::Object StdMeshers_MaxLengthPy::setPreestimatedLength(const Py::Tuple& args) -{ - hypothesis()->SetPreestimatedLength((double)Py::Float(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_MaxLengthPy::setUsePreestimatedLength(const Py::Tuple& args) -{ - hypothesis()->SetUsePreestimatedLength((bool)Py::Boolean(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_MaxLengthPy::getUsePreestimatedLength(const Py::Tuple& args) -{ - return Py::Boolean(hypothesis()->GetUsePreestimatedLength()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_LocalLengthPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_LocalLength"); - behaviors().doc("StdMeshers_LocalLength"); - - add_varargs_method("setLength", &StdMeshers_LocalLengthPy::setLength, "setLength()"); - add_varargs_method("getLength", &StdMeshers_LocalLengthPy::getLength, "getLength()"); - add_varargs_method("setPrecision", &StdMeshers_LocalLengthPy::setPrecision, "setPrecision()"); - add_varargs_method("getPrecision", &StdMeshers_LocalLengthPy::getPrecision, "getPrecision()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_LocalLengthPy::StdMeshers_LocalLengthPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_LocalLength(hypId, studyId, gen)) -{ -} - -StdMeshers_LocalLengthPy::~StdMeshers_LocalLengthPy() -{ -} - -Py::Object StdMeshers_LocalLengthPy::setLength(const Py::Tuple& args) -{ - hypothesis()->SetLength((double)Py::Float(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_LocalLengthPy::getLength(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetLength()); -} - -Py::Object StdMeshers_LocalLengthPy::setPrecision(const Py::Tuple& args) -{ - hypothesis()->SetPrecision((double)Py::Float(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_LocalLengthPy::getPrecision(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetPrecision()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_MaxElementAreaPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_MaxElementArea"); - behaviors().doc("StdMeshers_MaxElementArea"); - - add_varargs_method("setMaxArea", &StdMeshers_MaxElementAreaPy::setMaxArea, "setMaxArea()"); - add_varargs_method("getMaxArea", &StdMeshers_MaxElementAreaPy::getMaxArea, "getMaxArea()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_MaxElementAreaPy::StdMeshers_MaxElementAreaPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_MaxElementArea(hypId, studyId, gen)) -{ -} - -StdMeshers_MaxElementAreaPy::~StdMeshers_MaxElementAreaPy() -{ -} - -Py::Object StdMeshers_MaxElementAreaPy::setMaxArea(const Py::Tuple& args) -{ - hypothesis()->SetMaxArea((double)Py::Float(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_MaxElementAreaPy::getMaxArea(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetMaxArea()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_QuadranglePreferencePy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_QuadranglePreference"); - behaviors().doc("StdMeshers_QuadranglePreference"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_QuadranglePreferencePy::StdMeshers_QuadranglePreferencePy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_QuadranglePreference(hypId, studyId, gen)) -{ -} - -StdMeshers_QuadranglePreferencePy::~StdMeshers_QuadranglePreferencePy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Quadrangle_2DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Quadrangle_2D"); - behaviors().doc("StdMeshers_Quadrangle_2D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Quadrangle_2DPy::StdMeshers_Quadrangle_2DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Quadrangle_2D(hypId, studyId, gen)) -{ -} - -StdMeshers_Quadrangle_2DPy::~StdMeshers_Quadrangle_2DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Regular_1DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Regular_1D"); - behaviors().doc("StdMeshers_Regular_1D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Regular_1DPy::StdMeshers_Regular_1DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Regular_1D(hypId, studyId, gen)) -{ -} - -StdMeshers_Regular_1DPy::~StdMeshers_Regular_1DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_UseExisting_1DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_UseExisting_1D"); - behaviors().doc("StdMeshers_UseExisting_1D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_UseExisting_1DPy::StdMeshers_UseExisting_1DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_UseExisting_1D(hypId, studyId, gen)) -{ -} - -StdMeshers_UseExisting_1DPy::~StdMeshers_UseExisting_1DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_UseExisting_2DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_UseExisting_2D"); - behaviors().doc("StdMeshers_UseExisting_2D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_UseExisting_2DPy::StdMeshers_UseExisting_2DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_UseExisting_2D(hypId, studyId, gen)) -{ -} - -StdMeshers_UseExisting_2DPy::~StdMeshers_UseExisting_2DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_CompositeSegment_1DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_CompositeSegment_1D"); - behaviors().doc("StdMeshers_CompositeSegment_1D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_CompositeSegment_1DPy::StdMeshers_CompositeSegment_1DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_CompositeSegment_1D(hypId, studyId, gen)) -{ -} - -StdMeshers_CompositeSegment_1DPy::~StdMeshers_CompositeSegment_1DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Deflection1DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Deflection1D"); - behaviors().doc("StdMeshers_Deflection1D"); - - add_varargs_method("setDeflection", &StdMeshers_Deflection1DPy::setDeflection, "setDeflection()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Deflection1DPy::StdMeshers_Deflection1DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Deflection1D(hypId, studyId, gen)) -{ -} - -StdMeshers_Deflection1DPy::~StdMeshers_Deflection1DPy() -{ -} - -Py::Object StdMeshers_Deflection1DPy::setDeflection(const Py::Tuple& args) -{ - double fine = (double)Py::Float(args[0]); - hypothesis()->SetDeflection(fine); - return Py::None(); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Hexa_3DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Hexa_3D"); - behaviors().doc("StdMeshers_Hexa_3D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Hexa_3DPy::StdMeshers_Hexa_3DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Hexa_3D(hypId, studyId, gen)) -{ -} - -StdMeshers_Hexa_3DPy::~StdMeshers_Hexa_3DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_TrianglePreferencePy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_TrianglePreference"); - behaviors().doc("StdMeshers_TrianglePreference"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_TrianglePreferencePy::StdMeshers_TrianglePreferencePy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_TrianglePreference(hypId, studyId, gen)) -{ -} - -StdMeshers_TrianglePreferencePy::~StdMeshers_TrianglePreferencePy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_StartEndLengthPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_StartEndLength"); - behaviors().doc("StdMeshers_StartEndLength"); - add_varargs_method("setLength", &StdMeshers_StartEndLengthPy::setLength, "setLength()"); - add_varargs_method("getLength", &StdMeshers_StartEndLengthPy::getLength, "getLength()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_StartEndLengthPy::StdMeshers_StartEndLengthPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_StartEndLength(hypId, studyId, gen)) -{ -} - -StdMeshers_StartEndLengthPy::~StdMeshers_StartEndLengthPy() -{ -} - -Py::Object StdMeshers_StartEndLengthPy::setLength(const Py::Tuple& args) -{ - hypothesis()->SetLength((double)Py::Float(args[0]),(bool)Py::Boolean(args[1])); - return Py::None(); -} - -Py::Object StdMeshers_StartEndLengthPy::getLength(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetLength((bool)Py::Boolean(args[0]))); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_SegmentLengthAroundVertexPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_SegmentLengthAroundVertex"); - behaviors().doc("StdMeshers_SegmentLengthAroundVertex"); - add_varargs_method("setLength", &StdMeshers_SegmentLengthAroundVertexPy::setLength, "setLength()"); - add_varargs_method("getLength", &StdMeshers_SegmentLengthAroundVertexPy::getLength, "getLength()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_SegmentLengthAroundVertexPy::StdMeshers_SegmentLengthAroundVertexPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_SegmentLengthAroundVertex(hypId, studyId, gen)) -{ -} - -StdMeshers_SegmentLengthAroundVertexPy::~StdMeshers_SegmentLengthAroundVertexPy() -{ -} - -Py::Object StdMeshers_SegmentLengthAroundVertexPy::setLength(const Py::Tuple& args) -{ - hypothesis()->SetLength((double)Py::Float(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_SegmentLengthAroundVertexPy::getLength(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetLength()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_SegmentAroundVertex_0DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_SegmentAroundVertex_0D"); - behaviors().doc("StdMeshers_SegmentAroundVertex_0D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_SegmentAroundVertex_0DPy::StdMeshers_SegmentAroundVertex_0DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_SegmentAroundVertex_0D(hypId, studyId, gen)) -{ -} - -StdMeshers_SegmentAroundVertex_0DPy::~StdMeshers_SegmentAroundVertex_0DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_RadialPrism_3DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_RadialPrism_3D"); - behaviors().doc("StdMeshers_RadialPrism_3D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_RadialPrism_3DPy::StdMeshers_RadialPrism_3DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_RadialPrism_3D(hypId, studyId, gen)) -{ -} - -StdMeshers_RadialPrism_3DPy::~StdMeshers_RadialPrism_3DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_QuadraticMeshPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_QuadraticMesh"); - behaviors().doc("StdMeshers_QuadraticMesh"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_QuadraticMeshPy::StdMeshers_QuadraticMeshPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_QuadraticMesh(hypId, studyId, gen)) -{ -} - -StdMeshers_QuadraticMeshPy::~StdMeshers_QuadraticMeshPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_ProjectionSource3DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_ProjectionSource3D"); - behaviors().doc("StdMeshers_ProjectionSource3D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_ProjectionSource3DPy::StdMeshers_ProjectionSource3DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource3D(hypId, studyId, gen)) -{ -} - -StdMeshers_ProjectionSource3DPy::~StdMeshers_ProjectionSource3DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_ProjectionSource2DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_ProjectionSource2D"); - behaviors().doc("StdMeshers_ProjectionSource2D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_ProjectionSource2DPy::StdMeshers_ProjectionSource2DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource2D(hypId, studyId, gen)) -{ -} - -StdMeshers_ProjectionSource2DPy::~StdMeshers_ProjectionSource2DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_ProjectionSource1DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_ProjectionSource1D"); - behaviors().doc("StdMeshers_ProjectionSource1D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_ProjectionSource1DPy::StdMeshers_ProjectionSource1DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource1D(hypId, studyId, gen)) -{ -} - -StdMeshers_ProjectionSource1DPy::~StdMeshers_ProjectionSource1DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Projection_3DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Projection_3D"); - behaviors().doc("StdMeshers_Projection_3D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Projection_3DPy::StdMeshers_Projection_3DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Projection_3D(hypId, studyId, gen)) -{ -} - -StdMeshers_Projection_3DPy::~StdMeshers_Projection_3DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Projection_2DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Projection_2D"); - behaviors().doc("StdMeshers_Projection_2D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Projection_2DPy::StdMeshers_Projection_2DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Projection_2D(hypId, studyId, gen)) -{ -} - -StdMeshers_Projection_2DPy::~StdMeshers_Projection_2DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Projection_1DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Projection_1D"); - behaviors().doc("StdMeshers_Projection_1D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Projection_1DPy::StdMeshers_Projection_1DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Projection_1D(hypId, studyId, gen)) -{ -} - -StdMeshers_Projection_1DPy::~StdMeshers_Projection_1DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_Prism_3DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_Prism_3D"); - behaviors().doc("StdMeshers_Prism_3D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_Prism_3DPy::StdMeshers_Prism_3DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_Prism_3D(hypId, studyId, gen)) -{ -} - -StdMeshers_Prism_3DPy::~StdMeshers_Prism_3DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_NumberOfSegmentsPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_NumberOfSegments"); - behaviors().doc("StdMeshers_NumberOfSegments"); - add_varargs_method("setNumberOfSegments",&StdMeshers_NumberOfSegmentsPy::setNumSegm,"setNumberOfSegments()"); - add_varargs_method("getNumberOfSegments",&StdMeshers_NumberOfSegmentsPy::getNumSegm,"getNumberOfSegments()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_NumberOfSegmentsPy::StdMeshers_NumberOfSegmentsPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_NumberOfSegments(hypId, studyId, gen)) -{ -} - -StdMeshers_NumberOfSegmentsPy::~StdMeshers_NumberOfSegmentsPy() -{ -} - -Py::Object StdMeshers_NumberOfSegmentsPy::setNumSegm(const Py::Tuple& args) -{ - hypothesis()->SetNumberOfSegments((int)Py::Int(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_NumberOfSegmentsPy::getNumSegm(const Py::Tuple& args) -{ - return Py::Int(hypothesis()->GetNumberOfSegments()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_NumberOfLayersPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_NumberOfLayers"); - behaviors().doc("StdMeshers_NumberOfLayers"); - add_varargs_method("setNumberOfLayers",&StdMeshers_NumberOfLayersPy::setNumLayers,"setNumberOfLayers()"); - add_varargs_method("getNumberOfLayers",&StdMeshers_NumberOfLayersPy::getNumLayers,"getNumberOfLayers()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_NumberOfLayersPy::StdMeshers_NumberOfLayersPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_NumberOfLayers(hypId, studyId, gen)) -{ -} - -StdMeshers_NumberOfLayersPy::~StdMeshers_NumberOfLayersPy() -{ -} - -Py::Object StdMeshers_NumberOfLayersPy::setNumLayers(const Py::Tuple& args) -{ - hypothesis()->SetNumberOfLayers((int)Py::Int(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_NumberOfLayersPy::getNumLayers(const Py::Tuple& args) -{ - return Py::Int(hypothesis()->GetNumberOfLayers()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_MEFISTO_2DPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_MEFISTO_2D"); - behaviors().doc("StdMeshers_MEFISTO_2D"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_MEFISTO_2DPy::StdMeshers_MEFISTO_2DPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_MEFISTO_2D(hypId, studyId, gen)) -{ -} - -StdMeshers_MEFISTO_2DPy::~StdMeshers_MEFISTO_2DPy() -{ -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_MaxElementVolumePy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_MaxElementVolume"); - behaviors().doc("StdMeshers_MaxElementVolume"); - add_varargs_method("setMaxVolume",&StdMeshers_MaxElementVolumePy::setMaxVolume,"setMaxVolume()"); - add_varargs_method("getMaxVolume",&StdMeshers_MaxElementVolumePy::getMaxVolume,"getMaxVolume()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_MaxElementVolumePy::StdMeshers_MaxElementVolumePy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_MaxElementVolume(hypId, studyId, gen)) -{ -} - -StdMeshers_MaxElementVolumePy::~StdMeshers_MaxElementVolumePy() -{ -} - -Py::Object StdMeshers_MaxElementVolumePy::setMaxVolume(const Py::Tuple& args) -{ - hypothesis()->SetMaxVolume((double)Py::Float(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_MaxElementVolumePy::getMaxVolume(const Py::Tuple& args) -{ - return Py::Float(hypothesis()->GetMaxVolume()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_LengthFromEdgesPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_LengthFromEdges"); - behaviors().doc("StdMeshers_LengthFromEdges"); - add_varargs_method("setMode",&StdMeshers_LengthFromEdgesPy::setMode,"setMode()"); - add_varargs_method("getMode",&StdMeshers_LengthFromEdgesPy::getMode,"getMode()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_LengthFromEdgesPy::StdMeshers_LengthFromEdgesPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_LengthFromEdges(hypId, studyId, gen)) -{ -} - -StdMeshers_LengthFromEdgesPy::~StdMeshers_LengthFromEdgesPy() -{ -} - -Py::Object StdMeshers_LengthFromEdgesPy::setMode(const Py::Tuple& args) -{ - hypothesis()->SetMode((int)Py::Int(args[0])); - return Py::None(); -} - -Py::Object StdMeshers_LengthFromEdgesPy::getMode(const Py::Tuple& args) -{ - return Py::Int(hypothesis()->GetMode()); -} - -// ---------------------------------------------------------------------------- - -void StdMeshers_LayerDistributionPy::init_type(PyObject* module) -{ - behaviors().name("StdMeshers_LayerDistribution"); - behaviors().doc("StdMeshers_LayerDistribution"); - add_varargs_method("setLayerDistribution", - &StdMeshers_LayerDistributionPy::setLayerDistribution, - "setLayerDistribution()"); - add_varargs_method("getLayerDistribution", - &StdMeshers_LayerDistributionPy::getLayerDistribution, - "getLayerDistribution()"); - SMESH_HypothesisPyBase::init_type(module); -} - -StdMeshers_LayerDistributionPy::StdMeshers_LayerDistributionPy(int hypId, int studyId, SMESH_Gen* gen) - : SMESH_HypothesisPyBase(new StdMeshers_LayerDistribution(hypId, studyId, gen)) -{ -} - -StdMeshers_LayerDistributionPy::~StdMeshers_LayerDistributionPy() -{ -} - -Py::Object StdMeshers_LayerDistributionPy::setLayerDistribution(const Py::Tuple& args) -{ - return Py::None(); -} - -Py::Object StdMeshers_LayerDistributionPy::getLayerDistribution(const Py::Tuple& args) -{ - //return hypothesis()->GetLayerDistribution(); - return Py::None(); -} +/*************************************************************************** + * Copyright (c) 2010 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#include "HypothesisPy.h" +#include "FemMeshPy.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +using namespace Fem; + + +HypothesisPy::HypothesisPy(boost::shared_ptr h) + : hyp(h) +{ +} + +HypothesisPy::~HypothesisPy() +{ +} + +// ---------------------------------------------------------------------------- + +template +void SMESH_HypothesisPy::init_type(PyObject* module) +{ + // you must have overwritten the virtual functions + SMESH_HypothesisPy::behaviors().supportRepr(); + SMESH_HypothesisPy::behaviors().supportGetattr(); + SMESH_HypothesisPy::behaviors().supportSetattr(); + SMESH_HypothesisPy::behaviors().type_object()->tp_new = &PyMake; + + SMESH_HypothesisPy::add_varargs_method("setLibName", &SMESH_HypothesisPy::setLibName, "setLibName(String)"); + SMESH_HypothesisPy::add_varargs_method("getLibName", &SMESH_HypothesisPy::getLibName, "String getLibName()"); + SMESH_HypothesisPy::add_varargs_method("setParameters", &SMESH_HypothesisPy::setParameters, "setParameters(String)"); + SMESH_HypothesisPy::add_varargs_method("getParameters", &SMESH_HypothesisPy::getParameters, "String getParameters()"); + SMESH_HypothesisPy::add_varargs_method("setLastParameters", &SMESH_HypothesisPy::setLastParameters, "setLastParameters(String)"); + SMESH_HypothesisPy::add_varargs_method("getLastParameters", &SMESH_HypothesisPy::getLastParameters, "String getLastParameters()"); + SMESH_HypothesisPy::add_varargs_method("clearParameters", &SMESH_HypothesisPy::clearParameters, "clearParameters()"); + SMESH_HypothesisPy::add_varargs_method("isAuxiliary", &SMESH_HypothesisPy::isAuxiliary, "Bool isAuxiliary()"); + SMESH_HypothesisPy::add_varargs_method("setParametersByMesh", &SMESH_HypothesisPy::setParametersByMesh, "setParametersByMesh(Mesh,Shape)"); + Base::Interpreter().addType(SMESH_HypothesisPy::behaviors().type_object(), + module,SMESH_HypothesisPy::behaviors().getName()); +} + +template +SMESH_HypothesisPy::SMESH_HypothesisPy(SMESH_Hypothesis* h) : hyp(h) +{ +} + +template +SMESH_HypothesisPy::~SMESH_HypothesisPy() +{ +} + +template +Py::Object SMESH_HypothesisPy::getattr(const char *name) +{ + if (strcmp(name,"this") == 0) + return Hypothesis(Py::asObject(new HypothesisPy(this->getHypothesis()))); + return Py::PythonExtension::getattr(name); +} + +template +Py::Object SMESH_HypothesisPy::repr() +{ + std::stringstream str; + str << hyp->GetName() << ", " << hyp->GetID(); + return Py::String(str.str()); +} + +template +Py::Object SMESH_HypothesisPy::setLibName(const Py::Tuple& args) +{ + std::string libName = (std::string)Py::String(args[0]); + hypothesis()->SetLibName(libName.c_str()); + return Py::None(); +} + +template +Py::Object SMESH_HypothesisPy::getLibName(const Py::Tuple& args) +{ + return Py::String(hypothesis()->GetLibName()); +} + +template +Py::Object SMESH_HypothesisPy::setParameters(const Py::Tuple& args) +{ + std::string paramName = (std::string)Py::String(args[0]); + hypothesis()->SetParameters(paramName.c_str()); + return Py::None(); +} + +template +Py::Object SMESH_HypothesisPy::getParameters(const Py::Tuple& args) +{ + return Py::String(hypothesis()->GetParameters()); +} + +template +Py::Object SMESH_HypothesisPy::setLastParameters(const Py::Tuple& args) +{ + std::string paramName = (std::string)Py::String(args[0]); + hypothesis()->SetLastParameters(paramName.c_str()); + return Py::None(); +} + +template +Py::Object SMESH_HypothesisPy::getLastParameters(const Py::Tuple& args) +{ + return Py::String(hypothesis()->GetLastParameters()); +} + +template +Py::Object SMESH_HypothesisPy::clearParameters(const Py::Tuple& args) +{ + hypothesis()->ClearParameters(); + return Py::None(); +} + +template +Py::Object SMESH_HypothesisPy::setParametersByMesh(const Py::Tuple& args) +{ + PyObject *mesh, *shape; + if (!PyArg_ParseTuple(args.ptr(), "O!O!", + &(Fem::FemMeshPy::Type), &mesh, + &(Part::TopoShapePy::Type), &shape)) + throw Py::Exception(); + Fem::FemMesh* m = static_cast(mesh)->getFemMeshPtr(); + const TopoDS_Shape& s = static_cast(shape)->getTopoShapePtr()->_Shape; + return Py::Boolean(hypothesis()->SetParametersByMesh(m->getSMesh(), s)); +} + +template +Py::Object SMESH_HypothesisPy::isAuxiliary(const Py::Tuple& args) +{ + return Py::Boolean(hypothesis()->IsAuxiliary()); +} + +template +PyObject *SMESH_HypothesisPy::PyMake(struct _typeobject *type, PyObject * args, PyObject * kwds) +{ + int hypId; + PyObject* obj; + if (!PyArg_ParseTuple(args, "iO!",&hypId,&(FemMeshPy::Type),&obj)) + return 0; + FemMesh* mesh = static_cast(obj)->getFemMeshPtr(); + return new T(hypId, 1, mesh->getGenerator()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Arithmetic1DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Arithmetic1D"); + behaviors().doc("StdMeshers_Arithmetic1D"); + + add_varargs_method("setLength", &StdMeshers_Arithmetic1DPy::setLength, "setLength()"); + add_varargs_method("getLength", &StdMeshers_Arithmetic1DPy::getLength, "getLength()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Arithmetic1DPy::StdMeshers_Arithmetic1DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Arithmetic1D(hypId, studyId, gen)) +{ +} + +StdMeshers_Arithmetic1DPy::~StdMeshers_Arithmetic1DPy() +{ +} + +Py::Object StdMeshers_Arithmetic1DPy::setLength(const Py::Tuple& args) +{ + hypothesis()-> + SetLength((double)Py::Float(args[0]), (bool)Py::Boolean(args[1])); + return Py::None(); +} + +Py::Object StdMeshers_Arithmetic1DPy::getLength(const Py::Tuple& args) +{ + int start; + if (!PyArg_ParseTuple(args.ptr(), "i",&start)) + throw Py::Exception(); + return Py::Float(hypothesis()-> + GetLength(start ? true : false)); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_AutomaticLengthPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_AutomaticLength"); + behaviors().doc("StdMeshers_AutomaticLength"); + + add_varargs_method("setFineness", &StdMeshers_AutomaticLengthPy::setFineness, "setFineness()"); + add_varargs_method("getFineness", &StdMeshers_AutomaticLengthPy::getFineness, "getFineness()"); + add_varargs_method("getLength", &StdMeshers_AutomaticLengthPy::getLength, "getLength()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_AutomaticLengthPy::StdMeshers_AutomaticLengthPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(0) +{ +} + +StdMeshers_AutomaticLengthPy::~StdMeshers_AutomaticLengthPy() +{ +} + +Py::Object StdMeshers_AutomaticLengthPy::setFineness(const Py::Tuple& args) +{ + double fine = (double)Py::Float(args[0]); + hypothesis()->SetFineness(fine); + return Py::None(); +} + +Py::Object StdMeshers_AutomaticLengthPy::getFineness(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetFineness()); +} + +namespace Py { + typedef ExtensionObject FemMesh; + typedef ExtensionObject TopoShape; + template<> bool FemMesh::accepts (PyObject *pyob) const + { + return (pyob && PyObject_TypeCheck(pyob, &(Fem::FemMeshPy::Type))); + } + template<> bool TopoShape::accepts (PyObject *pyob) const + { + return (pyob && PyObject_TypeCheck(pyob, &(Part::TopoShapePy::Type))); + } +} + +Py::Object StdMeshers_AutomaticLengthPy::getLength(const Py::Tuple& args) +{ + Py::FemMesh mesh(args[0]); + Py::Object shape_or_double(args[1]); + + Fem::FemMesh* m = mesh.extensionObject()->getFemMeshPtr(); + if (shape_or_double.type() == Py::Float().type()) { + double len = (double)Py::Float(shape_or_double); + return Py::Float(hypothesis()->GetLength(m->getSMesh(),len)); + } + else { + Py::TopoShape shape(shape_or_double); + const TopoDS_Shape& s = shape.extensionObject()->getTopoShapePtr()->_Shape; + return Py::Float(hypothesis()->GetLength(m->getSMesh(),s)); + } + + throw Py::Exception(); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_NotConformAllowedPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_NotConformAllowed"); + behaviors().doc("StdMeshers_NotConformAllowed"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_NotConformAllowedPy::StdMeshers_NotConformAllowedPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_NotConformAllowed(hypId, studyId, gen)) +{ +} + +StdMeshers_NotConformAllowedPy::~StdMeshers_NotConformAllowedPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_MaxLengthPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_MaxLength"); + behaviors().doc("StdMeshers_MaxLength"); + + add_varargs_method("setLength", &StdMeshers_MaxLengthPy::setLength, "setLength()"); + add_varargs_method("getLength", &StdMeshers_MaxLengthPy::getLength, "getLength()"); + add_varargs_method("havePreestimatedLength", &StdMeshers_MaxLengthPy::havePreestimatedLength, "havePreestimatedLength()"); + add_varargs_method("getPreestimatedLength", &StdMeshers_MaxLengthPy::getPreestimatedLength, "getPreestimatedLength()"); + add_varargs_method("setPreestimatedLength", &StdMeshers_MaxLengthPy::setPreestimatedLength, "setPreestimatedLength()"); + add_varargs_method("setUsePreestimatedLength", &StdMeshers_MaxLengthPy::setUsePreestimatedLength, "setUsePreestimatedLength()"); + add_varargs_method("getUsePreestimatedLength", &StdMeshers_MaxLengthPy::getUsePreestimatedLength, "getUsePreestimatedLength()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_MaxLengthPy::StdMeshers_MaxLengthPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_MaxLength(hypId, studyId, gen)) +{ +} + +StdMeshers_MaxLengthPy::~StdMeshers_MaxLengthPy() +{ +} + +Py::Object StdMeshers_MaxLengthPy::setLength(const Py::Tuple& args) +{ + hypothesis()->SetLength((double)Py::Float(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_MaxLengthPy::getLength(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetLength()); +} + +Py::Object StdMeshers_MaxLengthPy::havePreestimatedLength(const Py::Tuple& args) +{ + return Py::Boolean(hypothesis()->HavePreestimatedLength()); +} + +Py::Object StdMeshers_MaxLengthPy::getPreestimatedLength(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetPreestimatedLength()); +} + +Py::Object StdMeshers_MaxLengthPy::setPreestimatedLength(const Py::Tuple& args) +{ + hypothesis()->SetPreestimatedLength((double)Py::Float(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_MaxLengthPy::setUsePreestimatedLength(const Py::Tuple& args) +{ + hypothesis()->SetUsePreestimatedLength((bool)Py::Boolean(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_MaxLengthPy::getUsePreestimatedLength(const Py::Tuple& args) +{ + return Py::Boolean(hypothesis()->GetUsePreestimatedLength()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_LocalLengthPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_LocalLength"); + behaviors().doc("StdMeshers_LocalLength"); + + add_varargs_method("setLength", &StdMeshers_LocalLengthPy::setLength, "setLength()"); + add_varargs_method("getLength", &StdMeshers_LocalLengthPy::getLength, "getLength()"); + add_varargs_method("setPrecision", &StdMeshers_LocalLengthPy::setPrecision, "setPrecision()"); + add_varargs_method("getPrecision", &StdMeshers_LocalLengthPy::getPrecision, "getPrecision()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_LocalLengthPy::StdMeshers_LocalLengthPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_LocalLength(hypId, studyId, gen)) +{ +} + +StdMeshers_LocalLengthPy::~StdMeshers_LocalLengthPy() +{ +} + +Py::Object StdMeshers_LocalLengthPy::setLength(const Py::Tuple& args) +{ + hypothesis()->SetLength((double)Py::Float(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_LocalLengthPy::getLength(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetLength()); +} + +Py::Object StdMeshers_LocalLengthPy::setPrecision(const Py::Tuple& args) +{ + hypothesis()->SetPrecision((double)Py::Float(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_LocalLengthPy::getPrecision(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetPrecision()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_MaxElementAreaPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_MaxElementArea"); + behaviors().doc("StdMeshers_MaxElementArea"); + + add_varargs_method("setMaxArea", &StdMeshers_MaxElementAreaPy::setMaxArea, "setMaxArea()"); + add_varargs_method("getMaxArea", &StdMeshers_MaxElementAreaPy::getMaxArea, "getMaxArea()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_MaxElementAreaPy::StdMeshers_MaxElementAreaPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_MaxElementArea(hypId, studyId, gen)) +{ +} + +StdMeshers_MaxElementAreaPy::~StdMeshers_MaxElementAreaPy() +{ +} + +Py::Object StdMeshers_MaxElementAreaPy::setMaxArea(const Py::Tuple& args) +{ + hypothesis()->SetMaxArea((double)Py::Float(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_MaxElementAreaPy::getMaxArea(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetMaxArea()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_QuadranglePreferencePy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_QuadranglePreference"); + behaviors().doc("StdMeshers_QuadranglePreference"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_QuadranglePreferencePy::StdMeshers_QuadranglePreferencePy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_QuadranglePreference(hypId, studyId, gen)) +{ +} + +StdMeshers_QuadranglePreferencePy::~StdMeshers_QuadranglePreferencePy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Quadrangle_2DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Quadrangle_2D"); + behaviors().doc("StdMeshers_Quadrangle_2D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Quadrangle_2DPy::StdMeshers_Quadrangle_2DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Quadrangle_2D(hypId, studyId, gen)) +{ +} + +StdMeshers_Quadrangle_2DPy::~StdMeshers_Quadrangle_2DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Regular_1DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Regular_1D"); + behaviors().doc("StdMeshers_Regular_1D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Regular_1DPy::StdMeshers_Regular_1DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Regular_1D(hypId, studyId, gen)) +{ +} + +StdMeshers_Regular_1DPy::~StdMeshers_Regular_1DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_UseExisting_1DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_UseExisting_1D"); + behaviors().doc("StdMeshers_UseExisting_1D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_UseExisting_1DPy::StdMeshers_UseExisting_1DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_UseExisting_1D(hypId, studyId, gen)) +{ +} + +StdMeshers_UseExisting_1DPy::~StdMeshers_UseExisting_1DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_UseExisting_2DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_UseExisting_2D"); + behaviors().doc("StdMeshers_UseExisting_2D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_UseExisting_2DPy::StdMeshers_UseExisting_2DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_UseExisting_2D(hypId, studyId, gen)) +{ +} + +StdMeshers_UseExisting_2DPy::~StdMeshers_UseExisting_2DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_CompositeSegment_1DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_CompositeSegment_1D"); + behaviors().doc("StdMeshers_CompositeSegment_1D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_CompositeSegment_1DPy::StdMeshers_CompositeSegment_1DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_CompositeSegment_1D(hypId, studyId, gen)) +{ +} + +StdMeshers_CompositeSegment_1DPy::~StdMeshers_CompositeSegment_1DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Deflection1DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Deflection1D"); + behaviors().doc("StdMeshers_Deflection1D"); + + add_varargs_method("setDeflection", &StdMeshers_Deflection1DPy::setDeflection, "setDeflection()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Deflection1DPy::StdMeshers_Deflection1DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Deflection1D(hypId, studyId, gen)) +{ +} + +StdMeshers_Deflection1DPy::~StdMeshers_Deflection1DPy() +{ +} + +Py::Object StdMeshers_Deflection1DPy::setDeflection(const Py::Tuple& args) +{ + double fine = (double)Py::Float(args[0]); + hypothesis()->SetDeflection(fine); + return Py::None(); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Hexa_3DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Hexa_3D"); + behaviors().doc("StdMeshers_Hexa_3D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Hexa_3DPy::StdMeshers_Hexa_3DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Hexa_3D(hypId, studyId, gen)) +{ +} + +StdMeshers_Hexa_3DPy::~StdMeshers_Hexa_3DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_TrianglePreferencePy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_TrianglePreference"); + behaviors().doc("StdMeshers_TrianglePreference"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_TrianglePreferencePy::StdMeshers_TrianglePreferencePy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_TrianglePreference(hypId, studyId, gen)) +{ +} + +StdMeshers_TrianglePreferencePy::~StdMeshers_TrianglePreferencePy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_StartEndLengthPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_StartEndLength"); + behaviors().doc("StdMeshers_StartEndLength"); + add_varargs_method("setLength", &StdMeshers_StartEndLengthPy::setLength, "setLength()"); + add_varargs_method("getLength", &StdMeshers_StartEndLengthPy::getLength, "getLength()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_StartEndLengthPy::StdMeshers_StartEndLengthPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_StartEndLength(hypId, studyId, gen)) +{ +} + +StdMeshers_StartEndLengthPy::~StdMeshers_StartEndLengthPy() +{ +} + +Py::Object StdMeshers_StartEndLengthPy::setLength(const Py::Tuple& args) +{ + hypothesis()->SetLength((double)Py::Float(args[0]),(bool)Py::Boolean(args[1])); + return Py::None(); +} + +Py::Object StdMeshers_StartEndLengthPy::getLength(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetLength((bool)Py::Boolean(args[0]))); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_SegmentLengthAroundVertexPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_SegmentLengthAroundVertex"); + behaviors().doc("StdMeshers_SegmentLengthAroundVertex"); + add_varargs_method("setLength", &StdMeshers_SegmentLengthAroundVertexPy::setLength, "setLength()"); + add_varargs_method("getLength", &StdMeshers_SegmentLengthAroundVertexPy::getLength, "getLength()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_SegmentLengthAroundVertexPy::StdMeshers_SegmentLengthAroundVertexPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_SegmentLengthAroundVertex(hypId, studyId, gen)) +{ +} + +StdMeshers_SegmentLengthAroundVertexPy::~StdMeshers_SegmentLengthAroundVertexPy() +{ +} + +Py::Object StdMeshers_SegmentLengthAroundVertexPy::setLength(const Py::Tuple& args) +{ + hypothesis()->SetLength((double)Py::Float(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_SegmentLengthAroundVertexPy::getLength(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetLength()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_SegmentAroundVertex_0DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_SegmentAroundVertex_0D"); + behaviors().doc("StdMeshers_SegmentAroundVertex_0D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_SegmentAroundVertex_0DPy::StdMeshers_SegmentAroundVertex_0DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_SegmentAroundVertex_0D(hypId, studyId, gen)) +{ +} + +StdMeshers_SegmentAroundVertex_0DPy::~StdMeshers_SegmentAroundVertex_0DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_RadialPrism_3DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_RadialPrism_3D"); + behaviors().doc("StdMeshers_RadialPrism_3D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_RadialPrism_3DPy::StdMeshers_RadialPrism_3DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_RadialPrism_3D(hypId, studyId, gen)) +{ +} + +StdMeshers_RadialPrism_3DPy::~StdMeshers_RadialPrism_3DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_QuadraticMeshPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_QuadraticMesh"); + behaviors().doc("StdMeshers_QuadraticMesh"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_QuadraticMeshPy::StdMeshers_QuadraticMeshPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_QuadraticMesh(hypId, studyId, gen)) +{ +} + +StdMeshers_QuadraticMeshPy::~StdMeshers_QuadraticMeshPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_ProjectionSource3DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_ProjectionSource3D"); + behaviors().doc("StdMeshers_ProjectionSource3D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_ProjectionSource3DPy::StdMeshers_ProjectionSource3DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource3D(hypId, studyId, gen)) +{ +} + +StdMeshers_ProjectionSource3DPy::~StdMeshers_ProjectionSource3DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_ProjectionSource2DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_ProjectionSource2D"); + behaviors().doc("StdMeshers_ProjectionSource2D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_ProjectionSource2DPy::StdMeshers_ProjectionSource2DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource2D(hypId, studyId, gen)) +{ +} + +StdMeshers_ProjectionSource2DPy::~StdMeshers_ProjectionSource2DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_ProjectionSource1DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_ProjectionSource1D"); + behaviors().doc("StdMeshers_ProjectionSource1D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_ProjectionSource1DPy::StdMeshers_ProjectionSource1DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_ProjectionSource1D(hypId, studyId, gen)) +{ +} + +StdMeshers_ProjectionSource1DPy::~StdMeshers_ProjectionSource1DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Projection_3DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Projection_3D"); + behaviors().doc("StdMeshers_Projection_3D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Projection_3DPy::StdMeshers_Projection_3DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Projection_3D(hypId, studyId, gen)) +{ +} + +StdMeshers_Projection_3DPy::~StdMeshers_Projection_3DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Projection_2DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Projection_2D"); + behaviors().doc("StdMeshers_Projection_2D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Projection_2DPy::StdMeshers_Projection_2DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Projection_2D(hypId, studyId, gen)) +{ +} + +StdMeshers_Projection_2DPy::~StdMeshers_Projection_2DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Projection_1DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Projection_1D"); + behaviors().doc("StdMeshers_Projection_1D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Projection_1DPy::StdMeshers_Projection_1DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Projection_1D(hypId, studyId, gen)) +{ +} + +StdMeshers_Projection_1DPy::~StdMeshers_Projection_1DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_Prism_3DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_Prism_3D"); + behaviors().doc("StdMeshers_Prism_3D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_Prism_3DPy::StdMeshers_Prism_3DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_Prism_3D(hypId, studyId, gen)) +{ +} + +StdMeshers_Prism_3DPy::~StdMeshers_Prism_3DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_NumberOfSegmentsPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_NumberOfSegments"); + behaviors().doc("StdMeshers_NumberOfSegments"); + add_varargs_method("setNumberOfSegments",&StdMeshers_NumberOfSegmentsPy::setNumSegm,"setNumberOfSegments()"); + add_varargs_method("getNumberOfSegments",&StdMeshers_NumberOfSegmentsPy::getNumSegm,"getNumberOfSegments()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_NumberOfSegmentsPy::StdMeshers_NumberOfSegmentsPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_NumberOfSegments(hypId, studyId, gen)) +{ +} + +StdMeshers_NumberOfSegmentsPy::~StdMeshers_NumberOfSegmentsPy() +{ +} + +Py::Object StdMeshers_NumberOfSegmentsPy::setNumSegm(const Py::Tuple& args) +{ + hypothesis()->SetNumberOfSegments((int)Py::Int(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_NumberOfSegmentsPy::getNumSegm(const Py::Tuple& args) +{ + return Py::Int(hypothesis()->GetNumberOfSegments()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_NumberOfLayersPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_NumberOfLayers"); + behaviors().doc("StdMeshers_NumberOfLayers"); + add_varargs_method("setNumberOfLayers",&StdMeshers_NumberOfLayersPy::setNumLayers,"setNumberOfLayers()"); + add_varargs_method("getNumberOfLayers",&StdMeshers_NumberOfLayersPy::getNumLayers,"getNumberOfLayers()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_NumberOfLayersPy::StdMeshers_NumberOfLayersPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_NumberOfLayers(hypId, studyId, gen)) +{ +} + +StdMeshers_NumberOfLayersPy::~StdMeshers_NumberOfLayersPy() +{ +} + +Py::Object StdMeshers_NumberOfLayersPy::setNumLayers(const Py::Tuple& args) +{ + hypothesis()->SetNumberOfLayers((int)Py::Int(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_NumberOfLayersPy::getNumLayers(const Py::Tuple& args) +{ + return Py::Int(hypothesis()->GetNumberOfLayers()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_MEFISTO_2DPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_MEFISTO_2D"); + behaviors().doc("StdMeshers_MEFISTO_2D"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_MEFISTO_2DPy::StdMeshers_MEFISTO_2DPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_MEFISTO_2D(hypId, studyId, gen)) +{ +} + +StdMeshers_MEFISTO_2DPy::~StdMeshers_MEFISTO_2DPy() +{ +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_MaxElementVolumePy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_MaxElementVolume"); + behaviors().doc("StdMeshers_MaxElementVolume"); + add_varargs_method("setMaxVolume",&StdMeshers_MaxElementVolumePy::setMaxVolume,"setMaxVolume()"); + add_varargs_method("getMaxVolume",&StdMeshers_MaxElementVolumePy::getMaxVolume,"getMaxVolume()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_MaxElementVolumePy::StdMeshers_MaxElementVolumePy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_MaxElementVolume(hypId, studyId, gen)) +{ +} + +StdMeshers_MaxElementVolumePy::~StdMeshers_MaxElementVolumePy() +{ +} + +Py::Object StdMeshers_MaxElementVolumePy::setMaxVolume(const Py::Tuple& args) +{ + hypothesis()->SetMaxVolume((double)Py::Float(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_MaxElementVolumePy::getMaxVolume(const Py::Tuple& args) +{ + return Py::Float(hypothesis()->GetMaxVolume()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_LengthFromEdgesPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_LengthFromEdges"); + behaviors().doc("StdMeshers_LengthFromEdges"); + add_varargs_method("setMode",&StdMeshers_LengthFromEdgesPy::setMode,"setMode()"); + add_varargs_method("getMode",&StdMeshers_LengthFromEdgesPy::getMode,"getMode()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_LengthFromEdgesPy::StdMeshers_LengthFromEdgesPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_LengthFromEdges(hypId, studyId, gen)) +{ +} + +StdMeshers_LengthFromEdgesPy::~StdMeshers_LengthFromEdgesPy() +{ +} + +Py::Object StdMeshers_LengthFromEdgesPy::setMode(const Py::Tuple& args) +{ + hypothesis()->SetMode((int)Py::Int(args[0])); + return Py::None(); +} + +Py::Object StdMeshers_LengthFromEdgesPy::getMode(const Py::Tuple& args) +{ + return Py::Int(hypothesis()->GetMode()); +} + +// ---------------------------------------------------------------------------- + +void StdMeshers_LayerDistributionPy::init_type(PyObject* module) +{ + behaviors().name("StdMeshers_LayerDistribution"); + behaviors().doc("StdMeshers_LayerDistribution"); + add_varargs_method("setLayerDistribution", + &StdMeshers_LayerDistributionPy::setLayerDistribution, + "setLayerDistribution()"); + add_varargs_method("getLayerDistribution", + &StdMeshers_LayerDistributionPy::getLayerDistribution, + "getLayerDistribution()"); + SMESH_HypothesisPyBase::init_type(module); +} + +StdMeshers_LayerDistributionPy::StdMeshers_LayerDistributionPy(int hypId, int studyId, SMESH_Gen* gen) + : SMESH_HypothesisPyBase(new StdMeshers_LayerDistribution(hypId, studyId, gen)) +{ +} + +StdMeshers_LayerDistributionPy::~StdMeshers_LayerDistributionPy() +{ +} + +Py::Object StdMeshers_LayerDistributionPy::setLayerDistribution(const Py::Tuple& args) +{ + return Py::None(); +} + +Py::Object StdMeshers_LayerDistributionPy::getLayerDistribution(const Py::Tuple& args) +{ + //return hypothesis()->GetLayerDistribution(); + return Py::None(); +} diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4Query2Filtered.inl b/src/Mod/Mesh/App/WildMagic4/Wm4Query2Filtered.inl index 772c4c3257..8306c72c39 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4Query2Filtered.inl +++ b/src/Mod/Mesh/App/WildMagic4/Wm4Query2Filtered.inl @@ -1,105 +1,105 @@ -// Wild Magic Source Code -// David Eberly -// http://www.geometrictools.com -// Copyright (c) 1998-2007 -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation; either version 2.1 of the License, or (at -// your option) any later version. The license is available for reading at -// either of the locations: -// http://www.gnu.org/copyleft/lgpl.html -// http://www.geometrictools.com/License/WildMagicLicense.pdf -// The license applies to versions 0 through 4 of Wild Magic. -// -// Version: 4.0.0 (2006/06/28) - -namespace Wm4 -{ -//---------------------------------------------------------------------------- -template -Query2Filtered::Query2Filtered (int iVQuantity, - const Vector2* akVertex, Real fUncertainty) - : - Query2(iVQuantity,akVertex), - m_kRQuery(iVQuantity,akVertex) -{ - assert((Real)0.0 <= fUncertainty && fUncertainty <= (Real)1.0); - m_fUncertainty = fUncertainty; -} -//---------------------------------------------------------------------------- -template -Query2Filtered::~Query2Filtered () -{ -} -//---------------------------------------------------------------------------- -template -Query::Type Query2Filtered::GetType () const -{ - return Query::QT_FILTERED; -} -//---------------------------------------------------------------------------- -template -int Query2Filtered::ToLine (const Vector2& rkP, int iV0, int iV1) - const -{ - const Vector2& rkV0 = m_akVertex[iV0]; - const Vector2& rkV1 = m_akVertex[iV1]; - - Real fX0 = rkP[0] - rkV0[0]; - Real fY0 = rkP[1] - rkV0[1]; - Real fX1 = rkV1[0] - rkV0[0]; - Real fY1 = rkV1[1] - rkV0[1]; - - Real fLen0 = Math::Sqrt(fX0*fX0 + fY0*fY0); - Real fLen1 = Math::Sqrt(fX1*fX1 + fY1*fY1); - Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1; - - Real fDet2 = Det2(fX0,fY0,fX1,fY1); - if (Math::FAbs(fDet2) >= fScaledUncertainty) - { - return (fDet2 > (Real)0.0 ? +1 : (fDet2 < (Real)0.0 ? -1 : 0)); - } - - return m_kRQuery.ToLine(rkP,iV0,iV1); -} -//---------------------------------------------------------------------------- -template -int Query2Filtered::ToCircumcircle (const Vector2& rkP, int iV0, - int iV1, int iV2) const -{ - const Vector2& rkV0 = m_akVertex[iV0]; - const Vector2& rkV1 = m_akVertex[iV1]; - const Vector2& rkV2 = m_akVertex[iV2]; - - Real fS0x = rkV0[0] + rkP[0]; - Real fD0x = rkV0[0] - rkP[0]; - Real fS0y = rkV0[1] + rkP[1]; - Real fD0y = rkV0[1] - rkP[1]; - Real fS1x = rkV1[0] + rkP[0]; - Real fD1x = rkV1[0] - rkP[0]; - Real fS1y = rkV1[1] + rkP[1]; - Real fD1y = rkV1[1] - rkP[1]; - Real fS2x = rkV2[0] + rkP[0]; - Real fD2x = rkV2[0] - rkP[0]; - Real fS2y = rkV2[1] + rkP[1]; - Real fD2y = rkV2[1] - rkP[1]; - Real fZ0 = fS0x*fD0x + fS0y*fD0y; - Real fZ1 = fS1x*fD1x + fS1y*fD1y; - Real fZ2 = fS2x*fD2x + fS2y*fD2y; - - Real fLen0 = Math::Sqrt(fD0x*fD0x + fD0y*fD0y + fZ0*fZ0); - Real fLen1 = Math::Sqrt(fD1x*fD1x + fD1y*fD1y + fZ1*fZ1); - Real fLen2 = Math::Sqrt(fD2x*fD2x + fD2y*fD2y + fZ2*fZ2); - Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1*fLen2; - - Real fDet3 = Det3(fD0x,fD0y,fZ0,fD1x,fD1y,fZ1,fD2x,fD2y,fZ2); - if (Math::FAbs(fDet3) >= fScaledUncertainty) - { - return (fDet3 < (Real)0.0 ? 1 : (fDet3 > (Real)0.0 ? -1 : 0)); - } - - return m_kRQuery.ToCircumcircle(rkP,iV0,iV1,iV2); -} -//---------------------------------------------------------------------------- -} //namespace Wm4 +// Wild Magic Source Code +// David Eberly +// http://www.geometrictools.com +// Copyright (c) 1998-2007 +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or (at +// your option) any later version. The license is available for reading at +// either of the locations: +// http://www.gnu.org/copyleft/lgpl.html +// http://www.geometrictools.com/License/WildMagicLicense.pdf +// The license applies to versions 0 through 4 of Wild Magic. +// +// Version: 4.0.0 (2006/06/28) + +namespace Wm4 +{ +//---------------------------------------------------------------------------- +template +Query2Filtered::Query2Filtered (int iVQuantity, + const Vector2* akVertex, Real fUncertainty) + : + Query2(iVQuantity,akVertex), + m_kRQuery(iVQuantity,akVertex) +{ + assert((Real)0.0 <= fUncertainty && fUncertainty <= (Real)1.0); + m_fUncertainty = fUncertainty; +} +//---------------------------------------------------------------------------- +template +Query2Filtered::~Query2Filtered () +{ +} +//---------------------------------------------------------------------------- +template +Query::Type Query2Filtered::GetType () const +{ + return Query::QT_FILTERED; +} +//---------------------------------------------------------------------------- +template +int Query2Filtered::ToLine (const Vector2& rkP, int iV0, int iV1) + const +{ + const Vector2& rkV0 = m_akVertex[iV0]; + const Vector2& rkV1 = m_akVertex[iV1]; + + Real fX0 = rkP[0] - rkV0[0]; + Real fY0 = rkP[1] - rkV0[1]; + Real fX1 = rkV1[0] - rkV0[0]; + Real fY1 = rkV1[1] - rkV0[1]; + + Real fLen0 = Math::Sqrt(fX0*fX0 + fY0*fY0); + Real fLen1 = Math::Sqrt(fX1*fX1 + fY1*fY1); + Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1; + + Real fDet2 = this->Det2(fX0,fY0,fX1,fY1); + if (Math::FAbs(fDet2) >= fScaledUncertainty) + { + return (fDet2 > (Real)0.0 ? +1 : (fDet2 < (Real)0.0 ? -1 : 0)); + } + + return m_kRQuery.ToLine(rkP,iV0,iV1); +} +//---------------------------------------------------------------------------- +template +int Query2Filtered::ToCircumcircle (const Vector2& rkP, int iV0, + int iV1, int iV2) const +{ + const Vector2& rkV0 = m_akVertex[iV0]; + const Vector2& rkV1 = m_akVertex[iV1]; + const Vector2& rkV2 = m_akVertex[iV2]; + + Real fS0x = rkV0[0] + rkP[0]; + Real fD0x = rkV0[0] - rkP[0]; + Real fS0y = rkV0[1] + rkP[1]; + Real fD0y = rkV0[1] - rkP[1]; + Real fS1x = rkV1[0] + rkP[0]; + Real fD1x = rkV1[0] - rkP[0]; + Real fS1y = rkV1[1] + rkP[1]; + Real fD1y = rkV1[1] - rkP[1]; + Real fS2x = rkV2[0] + rkP[0]; + Real fD2x = rkV2[0] - rkP[0]; + Real fS2y = rkV2[1] + rkP[1]; + Real fD2y = rkV2[1] - rkP[1]; + Real fZ0 = fS0x*fD0x + fS0y*fD0y; + Real fZ1 = fS1x*fD1x + fS1y*fD1y; + Real fZ2 = fS2x*fD2x + fS2y*fD2y; + + Real fLen0 = Math::Sqrt(fD0x*fD0x + fD0y*fD0y + fZ0*fZ0); + Real fLen1 = Math::Sqrt(fD1x*fD1x + fD1y*fD1y + fZ1*fZ1); + Real fLen2 = Math::Sqrt(fD2x*fD2x + fD2y*fD2y + fZ2*fZ2); + Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1*fLen2; + + Real fDet3 = this->Det3(fD0x,fD0y,fZ0,fD1x,fD1y,fZ1,fD2x,fD2y,fZ2); + if (Math::FAbs(fDet3) >= fScaledUncertainty) + { + return (fDet3 < (Real)0.0 ? 1 : (fDet3 > (Real)0.0 ? -1 : 0)); + } + + return m_kRQuery.ToCircumcircle(rkP,iV0,iV1,iV2); +} +//---------------------------------------------------------------------------- +} //namespace Wm4 diff --git a/src/Mod/Mesh/App/WildMagic4/Wm4Query3Filtered.inl b/src/Mod/Mesh/App/WildMagic4/Wm4Query3Filtered.inl index 45a7239960..75224ee524 100644 --- a/src/Mod/Mesh/App/WildMagic4/Wm4Query3Filtered.inl +++ b/src/Mod/Mesh/App/WildMagic4/Wm4Query3Filtered.inl @@ -1,129 +1,129 @@ -// Wild Magic Source Code -// David Eberly -// http://www.geometrictools.com -// Copyright (c) 1998-2007 -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation; either version 2.1 of the License, or (at -// your option) any later version. The license is available for reading at -// either of the locations: -// http://www.gnu.org/copyleft/lgpl.html -// http://www.geometrictools.com/License/WildMagicLicense.pdf -// The license applies to versions 0 through 4 of Wild Magic. -// -// Version: 4.0.0 (2006/06/28) - -namespace Wm4 -{ -//---------------------------------------------------------------------------- -template -Query3Filtered::Query3Filtered (int iVQuantity, - const Vector3* akVertex, Real fUncertainty) - : - Query3(iVQuantity,akVertex), - m_kRQuery(iVQuantity,akVertex) -{ - assert((Real)0.0 <= fUncertainty && fUncertainty <= (Real)1.0); - m_fUncertainty = fUncertainty; -} -//---------------------------------------------------------------------------- -template -Query3Filtered::~Query3Filtered () -{ -} -//---------------------------------------------------------------------------- -template -Query::Type Query3Filtered::GetType () const -{ - return Query::QT_FILTERED; -} -//---------------------------------------------------------------------------- -template -int Query3Filtered::ToPlane (const Vector3& rkP, int iV0, int iV1, - int iV2) const -{ - const Vector3& rkV0 = m_akVertex[iV0]; - const Vector3& rkV1 = m_akVertex[iV1]; - const Vector3& rkV2 = m_akVertex[iV2]; - - Real fX0 = rkP[0] - rkV0[0]; - Real fY0 = rkP[1] - rkV0[1]; - Real fZ0 = rkP[2] - rkV0[2]; - Real fX1 = rkV1[0] - rkV0[0]; - Real fY1 = rkV1[1] - rkV0[1]; - Real fZ1 = rkV1[2] - rkV0[2]; - Real fX2 = rkV2[0] - rkV0[0]; - Real fY2 = rkV2[1] - rkV0[1]; - Real fZ2 = rkV2[2] - rkV0[2]; - - Real fLen0 = Math::Sqrt(fX0*fX0 + fY0*fY0 + fZ0*fZ0); - Real fLen1 = Math::Sqrt(fX1*fX1 + fY1*fY1 + fZ1*fZ1); - Real fLen2 = Math::Sqrt(fX2*fX2 + fY2*fY2 + fZ2*fZ2); - Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1*fLen2; - - Real fDet3 = Det3(fX0,fY0,fZ0,fX1,fY1,fZ1,fX2,fY2,fZ2); - if (Math::FAbs(fDet3) >= fScaledUncertainty) - { - return (fDet3 > (Real)0.0 ? +1 : (fDet3 < (Real)0.0 ? -1 : 0)); - } - - return m_kRQuery.ToPlane(rkP,iV0,iV1,iV2); -} -//---------------------------------------------------------------------------- -template -int Query3Filtered::ToCircumsphere (const Vector3& rkP, int iV0, - int iV1, int iV2, int iV3) const -{ - const Vector3& rkV0 = m_akVertex[iV0]; - const Vector3& rkV1 = m_akVertex[iV1]; - const Vector3& rkV2 = m_akVertex[iV2]; - const Vector3& rkV3 = m_akVertex[iV3]; - - Real fS0x = rkV0[0] + rkP[0]; - Real fD0x = rkV0[0] - rkP[0]; - Real fS0y = rkV0[1] + rkP[1]; - Real fD0y = rkV0[1] - rkP[1]; - Real fS0z = rkV0[2] + rkP[2]; - Real fD0z = rkV0[2] - rkP[2]; - Real fS1x = rkV1[0] + rkP[0]; - Real fD1x = rkV1[0] - rkP[0]; - Real fS1y = rkV1[1] + rkP[1]; - Real fD1y = rkV1[1] - rkP[1]; - Real fS1z = rkV1[2] + rkP[2]; - Real fD1z = rkV1[2] - rkP[2]; - Real fS2x = rkV2[0] + rkP[0]; - Real fD2x = rkV2[0] - rkP[0]; - Real fS2y = rkV2[1] + rkP[1]; - Real fD2y = rkV2[1] - rkP[1]; - Real fS2z = rkV2[2] + rkP[2]; - Real fD2z = rkV2[2] - rkP[2]; - Real fS3x = rkV3[0] + rkP[0]; - Real fD3x = rkV3[0] - rkP[0]; - Real fS3y = rkV3[1] + rkP[1]; - Real fD3y = rkV3[1] - rkP[1]; - Real fS3z = rkV3[2] + rkP[2]; - Real fD3z = rkV3[2] - rkP[2]; - Real fW0 = fS0x*fD0x + fS0y*fD0y + fS0z*fD0z; - Real fW1 = fS1x*fD1x + fS1y*fD1y + fS1z*fD1z; - Real fW2 = fS2x*fD2x + fS2y*fD2y + fS2z*fD2z; - Real fW3 = fS3x*fD3x + fS3y*fD3y + fS3z*fD3z; - - Real fLen0 = Math::Sqrt(fD0x*fD0x+fD0y*fD0y+fD0z*fD0z+fW0*fW0); - Real fLen1 = Math::Sqrt(fD1x*fD1x+fD1y*fD1y+fD1z*fD1z+fW1*fW1); - Real fLen2 = Math::Sqrt(fD2x*fD2x+fD2y*fD2y+fD2z*fD2z+fW2*fW2); - Real fLen3 = Math::Sqrt(fD3x*fD3x+fD3y*fD3y+fD3z*fD3z+fW3*fW3); - Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1*fLen2*fLen3; - - Real fDet4 = Det4(fD0x,fD0y,fD0z,fW0,fD1x,fD1y,fD1z,fW1,fD2x, - fD2y,fD2z,fW2,fD3x,fD3y,fD3z,fW3); - - if (Math::FAbs(fDet4) >= fScaledUncertainty) - { - return (fDet4 > (Real)0.0 ? 1 : (fDet4 < (Real)0.0 ? -1 : 0)); - } - - return m_kRQuery.ToCircumsphere(rkP,iV0,iV1,iV2,iV3); -} -//---------------------------------------------------------------------------- -} //namespace Wm4 +// Wild Magic Source Code +// David Eberly +// http://www.geometrictools.com +// Copyright (c) 1998-2007 +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation; either version 2.1 of the License, or (at +// your option) any later version. The license is available for reading at +// either of the locations: +// http://www.gnu.org/copyleft/lgpl.html +// http://www.geometrictools.com/License/WildMagicLicense.pdf +// The license applies to versions 0 through 4 of Wild Magic. +// +// Version: 4.0.0 (2006/06/28) + +namespace Wm4 +{ +//---------------------------------------------------------------------------- +template +Query3Filtered::Query3Filtered (int iVQuantity, + const Vector3* akVertex, Real fUncertainty) + : + Query3(iVQuantity,akVertex), + m_kRQuery(iVQuantity,akVertex) +{ + assert((Real)0.0 <= fUncertainty && fUncertainty <= (Real)1.0); + m_fUncertainty = fUncertainty; +} +//---------------------------------------------------------------------------- +template +Query3Filtered::~Query3Filtered () +{ +} +//---------------------------------------------------------------------------- +template +Query::Type Query3Filtered::GetType () const +{ + return Query::QT_FILTERED; +} +//---------------------------------------------------------------------------- +template +int Query3Filtered::ToPlane (const Vector3& rkP, int iV0, int iV1, + int iV2) const +{ + const Vector3& rkV0 = m_akVertex[iV0]; + const Vector3& rkV1 = m_akVertex[iV1]; + const Vector3& rkV2 = m_akVertex[iV2]; + + Real fX0 = rkP[0] - rkV0[0]; + Real fY0 = rkP[1] - rkV0[1]; + Real fZ0 = rkP[2] - rkV0[2]; + Real fX1 = rkV1[0] - rkV0[0]; + Real fY1 = rkV1[1] - rkV0[1]; + Real fZ1 = rkV1[2] - rkV0[2]; + Real fX2 = rkV2[0] - rkV0[0]; + Real fY2 = rkV2[1] - rkV0[1]; + Real fZ2 = rkV2[2] - rkV0[2]; + + Real fLen0 = Math::Sqrt(fX0*fX0 + fY0*fY0 + fZ0*fZ0); + Real fLen1 = Math::Sqrt(fX1*fX1 + fY1*fY1 + fZ1*fZ1); + Real fLen2 = Math::Sqrt(fX2*fX2 + fY2*fY2 + fZ2*fZ2); + Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1*fLen2; + + Real fDet3 = this->Det3(fX0,fY0,fZ0,fX1,fY1,fZ1,fX2,fY2,fZ2); + if (Math::FAbs(fDet3) >= fScaledUncertainty) + { + return (fDet3 > (Real)0.0 ? +1 : (fDet3 < (Real)0.0 ? -1 : 0)); + } + + return m_kRQuery.ToPlane(rkP,iV0,iV1,iV2); +} +//---------------------------------------------------------------------------- +template +int Query3Filtered::ToCircumsphere (const Vector3& rkP, int iV0, + int iV1, int iV2, int iV3) const +{ + const Vector3& rkV0 = m_akVertex[iV0]; + const Vector3& rkV1 = m_akVertex[iV1]; + const Vector3& rkV2 = m_akVertex[iV2]; + const Vector3& rkV3 = m_akVertex[iV3]; + + Real fS0x = rkV0[0] + rkP[0]; + Real fD0x = rkV0[0] - rkP[0]; + Real fS0y = rkV0[1] + rkP[1]; + Real fD0y = rkV0[1] - rkP[1]; + Real fS0z = rkV0[2] + rkP[2]; + Real fD0z = rkV0[2] - rkP[2]; + Real fS1x = rkV1[0] + rkP[0]; + Real fD1x = rkV1[0] - rkP[0]; + Real fS1y = rkV1[1] + rkP[1]; + Real fD1y = rkV1[1] - rkP[1]; + Real fS1z = rkV1[2] + rkP[2]; + Real fD1z = rkV1[2] - rkP[2]; + Real fS2x = rkV2[0] + rkP[0]; + Real fD2x = rkV2[0] - rkP[0]; + Real fS2y = rkV2[1] + rkP[1]; + Real fD2y = rkV2[1] - rkP[1]; + Real fS2z = rkV2[2] + rkP[2]; + Real fD2z = rkV2[2] - rkP[2]; + Real fS3x = rkV3[0] + rkP[0]; + Real fD3x = rkV3[0] - rkP[0]; + Real fS3y = rkV3[1] + rkP[1]; + Real fD3y = rkV3[1] - rkP[1]; + Real fS3z = rkV3[2] + rkP[2]; + Real fD3z = rkV3[2] - rkP[2]; + Real fW0 = fS0x*fD0x + fS0y*fD0y + fS0z*fD0z; + Real fW1 = fS1x*fD1x + fS1y*fD1y + fS1z*fD1z; + Real fW2 = fS2x*fD2x + fS2y*fD2y + fS2z*fD2z; + Real fW3 = fS3x*fD3x + fS3y*fD3y + fS3z*fD3z; + + Real fLen0 = Math::Sqrt(fD0x*fD0x+fD0y*fD0y+fD0z*fD0z+fW0*fW0); + Real fLen1 = Math::Sqrt(fD1x*fD1x+fD1y*fD1y+fD1z*fD1z+fW1*fW1); + Real fLen2 = Math::Sqrt(fD2x*fD2x+fD2y*fD2y+fD2z*fD2z+fW2*fW2); + Real fLen3 = Math::Sqrt(fD3x*fD3x+fD3y*fD3y+fD3z*fD3z+fW3*fW3); + Real fScaledUncertainty = m_fUncertainty*fLen0*fLen1*fLen2*fLen3; + + Real fDet4 = this->Det4(fD0x,fD0y,fD0z,fW0,fD1x,fD1y,fD1z,fW1,fD2x, + fD2y,fD2z,fW2,fD3x,fD3y,fD3z,fW3); + + if (Math::FAbs(fDet4) >= fScaledUncertainty) + { + return (fDet4 > (Real)0.0 ? 1 : (fDet4 < (Real)0.0 ? -1 : 0)); + } + + return m_kRQuery.ToCircumsphere(rkP,iV0,iV1,iV2,iV3); +} +//---------------------------------------------------------------------------- +} //namespace Wm4 From af3eefbb5b44e078c6f58a4e388d4004aea5e347 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 13 May 2012 14:56:24 -0300 Subject: [PATCH 187/351] Small fixes to wiki download scripts --- src/Tools/offlinedoc/buildwikiindex.py | 43 ++++++++++++++++++++++---- src/Tools/offlinedoc/downloadwiki.py | 5 ++- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/Tools/offlinedoc/buildwikiindex.py b/src/Tools/offlinedoc/buildwikiindex.py index 581ef0d3e5..f7cee86c8b 100755 --- a/src/Tools/offlinedoc/buildwikiindex.py +++ b/src/Tools/offlinedoc/buildwikiindex.py @@ -42,6 +42,7 @@ NORETRIEVE = ['Manual','Developer_hub','Power_users_hub','Users_hub','Source_doc GETTRANSLATIONS = False # Set true if you want to get the translations too. MAXFAIL = 3 # max number of retries if download fails VERBOSE = True # to display what's going on. Otherwise, runs totally silent. +WRITETHROUGH = True # if true, fetched files are constantly written to disk, in case of failure. # END CONFIGURATION ############################################## @@ -52,8 +53,24 @@ def crawl(): todolist = [] processed = [] count = 1 - indexpages,imgs = get(INDEX) - todolist.extend(indexpages) + if os.path.exists("wikifiles.txt"): + f = open("wikifiles.txt","r") + if VERBOSE: print "Reading existing list..." + for l in f.readlines(): + if l.strip() != "": + if VERBOSE: print "Adding ",l + processed.append(l.strip()) + f.close() + if os.path.exists("todolist.txt"): + f = open("todolist.txt","r") + if VERBOSE: print "Reading existing todo list..." + for l in f.readlines(): + if l.strip() != "": + todolist.append(l.strip()) + f.close() + else: + indexpages,imgs = get(INDEX) + todolist.extend(indexpages) while todolist: targetpage = todolist.pop() if not targetpage in NORETRIEVE: @@ -66,8 +83,12 @@ def crawl(): for p in pages: if (not (p in todolist)) and (not (p in processed)): todolist.append(p) + if WRITETHROUGH: + writeList(processed) + writeList(todolist,"todolist.txt") if VERBOSE: print "Fetched ", count, " pages" - writeList(processed) + if not WRITETHROUGH: + writeList(processed) return 0 def get(page): @@ -136,12 +157,22 @@ def fetchpage(page): failcount += 1 print 'Error: unable to fetch page ' + page -def writeList(pages): - f = open("wikifiles.txt","wb") +def cleanList(pagelist): + "cleans the list" + npages = [] + for p in pagelist: + if not p in npages: + if not "redlink" in p: + npages.append(p) + return npages + +def writeList(pages,filename="wikifiles.txt"): + pages = cleanList(pages) + f = open(filename,"wb") for p in pages: f.write(p+"\n") f.close() - if VERBOSE: print "written wikifiles.txt" + if VERBOSE: print "written ",filename if __name__ == "__main__": crawl() diff --git a/src/Tools/offlinedoc/downloadwiki.py b/src/Tools/offlinedoc/downloadwiki.py index 7589107664..50f88a2eb4 100755 --- a/src/Tools/offlinedoc/downloadwiki.py +++ b/src/Tools/offlinedoc/downloadwiki.py @@ -236,6 +236,9 @@ def fetchpage(page): def fetchimage(imagelink): "retrieves given image from the wiki and saves it" + if imagelink[0:5] == "File:": + print "Skipping file page link" + return filename = re.findall('.*/(.*)',imagelink)[0] print "saving",filename if not exists(filename,image=True): @@ -263,7 +266,7 @@ def local(page,image=False): def exists(page,image=False): "checks if given page/image already exists" - path = local(page,image) + path = local(page.replace("/","-"),image) if os.path.exists(path): return True return False From 958246985758e44864b461bcd0cb2eeaf13a30ba Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 13 May 2012 20:47:20 -0300 Subject: [PATCH 188/351] Minor tweaks to Arch icons --- src/Mod/Arch/Makefile.am | 4 +- src/Mod/Arch/Resources/Arch.qrc | 2 + src/Mod/Arch/Resources/icons/Arch_Roof.svg | 406 ++++++++++++++++++ .../Arch/Resources/icons/Arch_Roof_Tree.svg | 397 +++++++++++++++++ .../Arch/Resources/icons/Arch_Site_Tree.svg | 18 +- .../Arch/Resources/icons/Arch_Wall_Tree.svg | 28 +- 6 files changed, 831 insertions(+), 24 deletions(-) create mode 100644 src/Mod/Arch/Resources/icons/Arch_Roof.svg create mode 100644 src/Mod/Arch/Resources/icons/Arch_Roof_Tree.svg diff --git a/src/Mod/Arch/Makefile.am b/src/Mod/Arch/Makefile.am index e26e085eb5..61917f8f7f 100644 --- a/src/Mod/Arch/Makefile.am +++ b/src/Mod/Arch/Makefile.am @@ -59,6 +59,8 @@ EXTRA_DIST = \ Resources/icons/Arch_Structure_Tree.svg \ Resources/icons/Arch_Window_Tree.svg \ Resources/icons/Arch_Axis.svg \ - Resources/icons/Arch_Axis_Tree.svg + Resources/icons/Arch_Axis_Tree.svg \ + Resources/icons/Arch_Roof.svg \ + Resources/icons/Arch_Roof_Tree.svg Resources/ui/archprefs-base.ui diff --git a/src/Mod/Arch/Resources/Arch.qrc b/src/Mod/Arch/Resources/Arch.qrc index 7d305d7104..b3667134cf 100644 --- a/src/Mod/Arch/Resources/Arch.qrc +++ b/src/Mod/Arch/Resources/Arch.qrc @@ -24,6 +24,8 @@ icons/Arch_Window_Tree.svg icons/Arch_Axis.svg icons/Arch_Axis_Tree.svg + icons/Arch_Roof.svg + icons/Arch_Roof_Tree.svg ui/archprefs-base.ui translations/Arch_af.qm translations/Arch_de.qm diff --git a/src/Mod/Arch/Resources/icons/Arch_Roof.svg b/src/Mod/Arch/Resources/icons/Arch_Roof.svg new file mode 100644 index 0000000000..0d72e27b02 --- /dev/null +++ b/src/Mod/Arch/Resources/icons/Arch_Roof.svg @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/Mod/Arch/Resources/icons/Arch_Roof_Tree.svg b/src/Mod/Arch/Resources/icons/Arch_Roof_Tree.svg new file mode 100644 index 0000000000..8b105168a9 --- /dev/null +++ b/src/Mod/Arch/Resources/icons/Arch_Roof_Tree.svg @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/Mod/Arch/Resources/icons/Arch_Site_Tree.svg b/src/Mod/Arch/Resources/icons/Arch_Site_Tree.svg index 4e4bd79310..d43aee6133 100644 --- a/src/Mod/Arch/Resources/icons/Arch_Site_Tree.svg +++ b/src/Mod/Arch/Resources/icons/Arch_Site_Tree.svg @@ -14,8 +14,8 @@ height="64px" id="svg2985" version="1.1" - inkscape:version="0.48.1 r9760" - sodipodi:docname="Arch_Site.svg"> + inkscape:version="0.48.3.1 r9886" + sodipodi:docname="Arch_Site_Tree.svg"> @@ -99,7 +99,7 @@ image/svg+xml - + @@ -118,7 +118,7 @@ id="path3869" inkscape:connector-curvature="0" /> diff --git a/src/Mod/Arch/Resources/icons/Arch_Wall_Tree.svg b/src/Mod/Arch/Resources/icons/Arch_Wall_Tree.svg index 94c448db00..9ab2fe9307 100644 --- a/src/Mod/Arch/Resources/icons/Arch_Wall_Tree.svg +++ b/src/Mod/Arch/Resources/icons/Arch_Wall_Tree.svg @@ -13,8 +13,8 @@ height="64px" id="svg2816" version="1.1" - inkscape:version="0.48.1 r9760" - sodipodi:docname="preferences-arch.svg"> + inkscape:version="0.48.3.1 r9886" + sodipodi:docname="Arch_Wall_Tree.svg"> image/svg+xml - + @@ -160,7 +160,7 @@ y="59.61282" transform="matrix(0.7577145,-0.65258619,0,1,0,0)" /> @@ -191,7 +191,7 @@ id="path3849" sodipodi:nodetypes="cccccc" /> From 73d2fa9e61b09a8d636501acd6a41ece64d6f564 Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 14 May 2012 10:44:44 +0200 Subject: [PATCH 189/351] Sketcher: avoid duplicate code and unnecessary arguments --- src/Mod/Sketcher/App/Sketch.cpp | 13 ++---- src/Mod/Sketcher/App/Sketch.h | 16 ++++++- src/Mod/Sketcher/App/SketchObject.cpp | 8 ++-- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 51 ++++----------------- src/Mod/Sketcher/Gui/ViewProviderSketch.h | 2 + 5 files changed, 35 insertions(+), 55 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 608d9da0ec..969c083123 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -96,8 +96,9 @@ void Sketch::clear(void) Conflicting.clear(); } -int Sketch::setUpSketch(const std::vector &GeoList, const std::vector &ConstraintList, - bool withDiagnose, int extGeoCount) +int Sketch::setUpSketch(const std::vector &GeoList, + const std::vector &ConstraintList, + int extGeoCount) { clear(); @@ -121,11 +122,7 @@ int Sketch::setUpSketch(const std::vector &GeoList, const std: GCSsys.clearByTag(-1); GCSsys.clearByTag(-2); GCSsys.initSolution(Parameters); - - if (withDiagnose) - return diagnose(); - else - return 0; + return diagnose(); } const char* nameByType(Sketch::GeoType type) @@ -1606,7 +1603,7 @@ int Sketch::solve(void) break; } - // if successfully solved try write the parameters back + // if successfully solved try to write the parameters back if (ret == GCS::Success) { GCSsys.applySolution(); valid_solution = updateGeometry(); diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index ec108421b5..3f22f7fdd5 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -53,9 +53,21 @@ public: int solve(void); /// delete all geometry and constraints, leave an empty sketch void clear(void); - /// set the sketch up with geoms and constraints + /** set the sketch up with geoms and constraints + * + * returns the degree of freedom of a sketch and calculates a list of + * conflicting constraints + * + * 0 degrees of freedom correspond to a fully constrained sketch + * -1 degrees of freedom correspond to an over-constrained sketch + * positive degrees of freedom correspond to an under-constrained sketch + * + * an over-constrained sketch will always contain conflicting constraints + * a fully constrained or under-constrained sketch may contain conflicting + * constraints or may not + */ int setUpSketch(const std::vector &GeoList, const std::vector &ConstraintList, - bool withDiagnose=true, int extGeoCount=0); + int extGeoCount=0); /// return the actual geometry of the sketch a TopoShape Part::TopoShape toShape(void) const; /// add unspecified geometry diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 95aa455a77..c9e5b38458 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -97,7 +97,7 @@ App::DocumentObjectExecReturn *SketchObject::execute(void) rebuildExternalGeometry(); Sketch sketch; int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(), - true, getExternalGeometryCount()); + getExternalGeometryCount()); if (dofs < 0) { // over-constrained sketch std::string msg="Over-constrained sketch\n"; appendConflictMsg(sketch.getConflicting(), msg); @@ -128,7 +128,7 @@ int SketchObject::hasConflicts(void) const // set up a sketch (including dofs counting and diagnosing of conflicts) Sketch sketch; int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(), - true, getExternalGeometryCount()); + getExternalGeometryCount()); if (dofs < 0) // over-constrained sketch return -2; if (sketch.hasConflicts()) // conflicting constraints @@ -166,7 +166,7 @@ int SketchObject::setDatum(int ConstrId, double Datum) // set up a sketch (including dofs counting and diagnosing of conflicts) Sketch sketch; int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(), - true, getExternalGeometryCount()); + getExternalGeometryCount()); int err=0; if (dofs < 0) // over-constrained sketch err = -3; @@ -192,7 +192,7 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP { Sketch sketch; int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(), - true, getExternalGeometryCount()); + getExternalGeometryCount()); if (dofs < 0) // over-constrained sketch return -1; if (sketch.hasConflicts()) // conflicting constraints diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index ee289f1d7a..1618af878a 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -2694,42 +2694,7 @@ void ViewProviderSketch::updateData(const App::Property *prop) if (edit && (prop == &(getSketchObject()->Geometry) || &(getSketchObject()->Constraints))) { edit->FullyConstrained = false; - int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(), - getSketchObject()->Constraints.getValues(), - true, getSketchObject()->getExternalGeometryCount()); - std::string msg; - if (getSketchObject()->Geometry.getSize() == 0) { - signalSetUp(-1, 0, msg); - signalSolved(-1, 0); - } - else if (dofs < 0) { // over-constrained sketch - SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg); - //Base::Console().Warning("Over-constrained sketch\n%s",msg.c_str()); - signalSetUp(3, 0, msg); - signalSolved(-1,0); - } - else if (edit->ActSketch.hasConflicts()) { // conflicting constraints - SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg); - //Base::Console().Warning("Sketch with conflicting constraints\n%s",msg.c_str()); - signalSetUp(2, dofs, msg); - signalSolved(-1,0); - } - else if (edit->ActSketch.solve() == 0) { // solving the sketch - if (dofs == 0) { - // color the sketch as fully constrained - edit->FullyConstrained = true; - //Base::Console().Message("Fully constrained sketch\n"); - signalSetUp(0, 0, msg); - } - else { - //Base::Console().Message("Under-constrained sketch with %d degrees of freedom\n", dofs); - signalSetUp(1, dofs, msg); - } - signalSolved(0,edit->ActSketch.SolveTime); - } - else { - signalSolved(1,edit->ActSketch.SolveTime); - } + solveSketch(); draw(true); } if (edit && &(getSketchObject()->Constraints)) { @@ -2831,10 +2796,18 @@ bool ViewProviderSketch::setEdit(int ModNum) else Gui::Control().showDialog(new TaskDlgEditSketch(this)); + solveSketch(); + draw(); + + return true; +} + +void ViewProviderSketch::solveSketch(void) +{ // set up the sketch and diagnose possible conflicts int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(), getSketchObject()->Constraints.getValues(), - true, getSketchObject()->getExternalGeometryCount()); + getSketchObject()->getExternalGeometryCount()); std::string msg; if (getSketchObject()->Geometry.getSize() == 0) { signalSetUp(-1, 0, msg); @@ -2868,10 +2841,6 @@ bool ViewProviderSketch::setEdit(int ModNum) else { signalSolved(1, edit->ActSketch.SolveTime); } - - draw(); - - return true; } void ViewProviderSketch::createEditInventorNodes(void) diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index 572547186a..234ede976c 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -183,6 +183,8 @@ protected: virtual void unsetEdit(int ModNum); virtual void setEditViewer(Gui::View3DInventorViewer*, int ModNum); virtual void unsetEditViewer(Gui::View3DInventorViewer*); + /// set up and solve the sketch + void solveSketch(void); /// helper to detect whether the picked point lies on the sketch bool isPointOnSketch(const SoPickedPoint *pp) const; /// get called by the container whenever a property has been changed From 63b2b239b164425ad856e891cb05a5afcd1940f8 Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 14 May 2012 10:55:44 +0200 Subject: [PATCH 190/351] Sketcher: use low precision solving during mouse drag and code simplifications --- src/Mod/Sketcher/App/Sketch.cpp | 9 ++------- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 969c083123..bfdc0aa3a3 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -120,7 +120,6 @@ int Sketch::setUpSketch(const std::vector &GeoList, addConstraints(ConstraintList); GCSsys.clearByTag(-1); - GCSsys.clearByTag(-2); GCSsys.initSolution(Parameters); return diagnose(); } @@ -1566,7 +1565,6 @@ int Sketch::solve(void) Base::TimeInfo start_time; if (!isInitMove) { // make sure we are in single subsystem mode GCSsys.clearByTag(-1); - GCSsys.clearByTag(-2); isFine = true; } @@ -1590,13 +1588,11 @@ int Sketch::solve(void) break; case 3: // last resort: augment the system with a second subsystem and use the SQP solver solvername = "SQP(augmented system)"; - GCSsys.clearByTag(-1); - GCSsys.clearByTag(-2); InitParameters.resize(Parameters.size()); int i=0; for (std::vector::iterator it = Parameters.begin(); it != Parameters.end(); ++it, i++) { InitParameters[i] = **it; - GCSsys.addConstraintEqual(*it, &InitParameters[i], -2); + GCSsys.addConstraintEqual(*it, &InitParameters[i], -1); } GCSsys.initSolution(Parameters); ret = GCSsys.solve(isFine); @@ -1615,7 +1611,7 @@ int Sketch::solve(void) } if (soltype == 3) // cleanup temporary constraints of the augmented system - GCSsys.clearByTag(-2); + GCSsys.clearByTag(-1); if (valid_solution) { if (soltype == 1) @@ -1652,7 +1648,6 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine) geoId = checkGeoId(geoId); GCSsys.clearByTag(-1); - GCSsys.clearByTag(-2); // don't try to move sketches that contain conflicting constraints if (hasConflicts()) { diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 1618af878a..78841d18cb 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -768,7 +768,7 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal, int GeoId; Sketcher::PointPos PosId; getSketchObject()->getGeoVertexIndex(edit->DragPoint, GeoId, PosId); - edit->ActSketch.initMove(GeoId, PosId); + edit->ActSketch.initMove(GeoId, PosId, false); relative = false; xInit = 0; yInit = 0; @@ -785,7 +785,7 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal, edit->PreselectCurve != -1 && edit->DragCurve != edit->PreselectCurve) { Mode = STATUS_SKETCH_DragCurve; edit->DragCurve = edit->PreselectCurve; - edit->ActSketch.initMove(edit->DragCurve, Sketcher::none); + edit->ActSketch.initMove(edit->DragCurve, Sketcher::none, false); const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve); if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { relative = true; From ce5d9a332a75c3e02c79709f38c62311d60a0b2e Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 14 May 2012 11:28:05 +0200 Subject: [PATCH 191/351] Sketcher, Issue #0000691: detect redundant constraints and skip them if necessary --- src/Mod/Sketcher/App/Sketch.cpp | 33 +- src/Mod/Sketcher/App/Sketch.h | 19 +- src/Mod/Sketcher/App/SketchObject.cpp | 19 + src/Mod/Sketcher/App/SketchObject.h | 2 + src/Mod/Sketcher/App/freegcs/GCS.cpp | 438 ++++++++++++------ src/Mod/Sketcher/App/freegcs/GCS.h | 40 +- src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp | 3 + src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 33 +- 8 files changed, 386 insertions(+), 201 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index bfdc0aa3a3..59b6410a7a 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -120,8 +120,11 @@ int Sketch::setUpSketch(const std::vector &GeoList, addConstraints(ConstraintList); GCSsys.clearByTag(-1); - GCSsys.initSolution(Parameters); - return diagnose(); + GCSsys.declareUnknowns(Parameters); + GCSsys.initSolution(); + GCSsys.getConflicting(Conflicting); + GCSsys.getRedundant(Redundant); + return GCSsys.dofsNumber(); } const char* nameByType(Sketch::GeoType type) @@ -1594,7 +1597,7 @@ int Sketch::solve(void) InitParameters[i] = **it; GCSsys.addConstraintEqual(*it, &InitParameters[i], -1); } - GCSsys.initSolution(Parameters); + GCSsys.initSolution(); ret = GCSsys.solve(isFine); break; } @@ -1603,8 +1606,11 @@ int Sketch::solve(void) if (ret == GCS::Success) { GCSsys.applySolution(); valid_solution = updateGeometry(); - if (!valid_solution) + if (!valid_solution) { + GCSsys.undoSolution(); + updateGeometry(); Base::Console().Warning("Invalid solution from %s solver.\n", solvername.c_str()); + } } else { valid_solution = false; //Base::Console().Log("NotSolved "); @@ -1630,11 +1636,6 @@ int Sketch::solve(void) } } // soltype - if (!valid_solution) { // undo any changes - GCSsys.undoSolution(); - updateGeometry(); - } - Base::TimeInfo end_time; //Base::Console().Log("T:%s\n",Base::TimeInfo::diffTime(start_time,end_time).c_str()); SolveTime = Base::TimeInfo::diffTimeF(start_time,end_time); @@ -1752,7 +1753,7 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine) } InitParameters = MoveParameters; - GCSsys.initSolution(Parameters); + GCSsys.initSolution(); isInitMove = true; return 0; } @@ -1830,18 +1831,6 @@ Base::Vector3d Sketch::getPoint(int geoId, PointPos pos) return Base::Vector3d(); } -int Sketch::diagnose(void) -{ - Conflicting.clear(); - if (GCSsys.isInit()) { - int dofs = GCSsys.diagnose(Parameters, Conflicting); - return dofs; - } - else { - return -1; - } -} - TopoShape Sketch::toShape(void) const diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index 3f22f7fdd5..3ea95bc4fd 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -83,20 +83,10 @@ public: /// retrieves a point Base::Vector3d getPoint(int geoId, PointPos pos); - /** returns the degree of freedom of a sketch and calculates a list of - * conflicting constraints - * - * 0 degrees of freedom correspond to a fully constrained sketch - * -1 degrees of freedom correspond to an over-constrained sketch - * positive degrees of freedom correspond to an under-constrained sketch - * - * an over-constrained sketch will always contain conflicting constraints - * a fully constrained or under-constrained sketch may contain conflicting - * constraints or may not - */ - int diagnose(void); - bool hasConflicts(void) const { return (Conflicting.size() > 0); }; - const std::vector &getConflicting(void) const { return Conflicting; }; + bool hasConflicts(void) const { return (Conflicting.size() > 0); } + const std::vector &getConflicting(void) const { return Conflicting; } + bool hasRedundancies(void) const { return (Redundant.size() > 0); } + const std::vector &getRedundant(void) const { return Redundant; } /** set the datum of a distance or angle constraint to a certain value and solve * This can cause the solving to fail! @@ -213,6 +203,7 @@ protected: GCS::System GCSsys; int ConstraintsCounter; std::vector Conflicting; + std::vector Redundant; // solving parameters std::vector Parameters; // with memory allocation diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index c9e5b38458..8d75c5f24c 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -108,6 +108,11 @@ App::DocumentObjectExecReturn *SketchObject::execute(void) appendConflictMsg(sketch.getConflicting(), msg); return new App::DocumentObjectExecReturn(msg.c_str(),this); } + if (sketch.hasRedundancies()) { // redundant constraints + std::string msg="Sketch with redundant constraints\n"; + appendRedundantMsg(sketch.getRedundant(), msg); + return new App::DocumentObjectExecReturn(msg.c_str(),this); + } // solve the sketch if (sketch.solve() != 0) @@ -1396,6 +1401,20 @@ void SketchObject::appendConflictMsg(const std::vector &conflicting, std::s msg = ss.str(); } +void SketchObject::appendRedundantMsg(const std::vector &redundant, std::string &msg) +{ + std::stringstream ss; + if (msg.length() > 0) + ss << msg; + if (redundant.size() > 0) { + ss << "The following constraints were identified as redundant and should be removed:\n" << redundant[0]; + for (unsigned int i=1; i < redundant.size(); i++) + ss << ", " << redundant[i]; + ss << "\n"; + } + msg = ss.str(); +} + PyObject *SketchObject::getPyObject(void) { if (PythonObject.is(Py::_None())) { diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 83802d83a3..cf865d4053 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -136,6 +136,8 @@ public: /// generates a warning message about constraint conflicts and appends it to the given message static void appendConflictMsg(const std::vector &conflicting, std::string &msg); + /// generates a warning message about redundant constraints and appends it to the given message + static void appendRedundantMsg(const std::vector &redundant, std::string &msg); // from base class virtual PyObject *getPyObject(void); diff --git a/src/Mod/Sketcher/App/freegcs/GCS.cpp b/src/Mod/Sketcher/App/freegcs/GCS.cpp index c608c9bd0b..aa850c9a2e 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/freegcs/GCS.cpp @@ -41,19 +41,20 @@ typedef boost::adjacency_list Gra // System System::System() -: clist(0), +: plist(0), clist(0), c2p(), p2c(), - subsyslist(0), - reference(), - init(false) + subSystems(0), subSystemsAux(0), + reference(0), + hasUnknowns(false), hasDiagnosis(false), isInit(false) { } System::System(std::vector clist_) -: c2p(), p2c(), - subsyslist(0), - reference(), - init(false) +: plist(0), + c2p(), p2c(), + subSystems(0), subSystemsAux(0), + reference(0), + hasUnknowns(false), hasDiagnosis(false), isInit(false) { // create own (shallow) copy of constraints for (std::vector::iterator constr=clist_.begin(); @@ -125,7 +126,16 @@ System::~System() void System::clear() { - clearReference(); + plist.clear(); + pIndex.clear(); + hasUnknowns = false; + hasDiagnosis = false; + + redundant.clear(); + conflictingTags.clear(); + redundantTags.clear(); + + reference.clear(); clearSubSystems(); free(clist); c2p.clear(); @@ -148,7 +158,9 @@ void System::clearByTag(int tagId) int System::addConstraint(Constraint *constr) { - clearReference(); + isInit = false; + if (constr->getTag() >= 0) // negatively tagged constraints have no impact + hasDiagnosis = false; // on the diagnosis clist.push_back(constr); VEC_pD constr_params = constr->params(); @@ -163,12 +175,15 @@ int System::addConstraint(Constraint *constr) void System::removeConstraint(Constraint *constr) { - clearReference(); - clearSubSystems(); - std::vector::iterator it; it = std::find(clist.begin(), clist.end(), constr); + if (it == clist.end()) + return; + clist.erase(it); + if (constr->getTag() >= 0) + hasDiagnosis = false; + clearSubSystems(); VEC_pD constr_params = c2p[constr]; for (VEC_pD::const_iterator param=constr_params.begin(); @@ -545,9 +560,18 @@ void System::rescaleConstraint(int id, double coeff) clist[id]->rescale(coeff); } - -void System::initSolution(VEC_pD ¶ms) +void System::declareUnknowns(VEC_pD ¶ms) { + plist = params; + pIndex.clear(); + for (int i=0; i < int(plist.size()); ++i) + pIndex[plist[i]] = i; + hasUnknowns = true; +} + +void System::initSolution() +{ + // - Stores the current parameters values in the vector "reference" // - identifies any decoupled subsystems and partitions the original // system into corresponding components // - Stores the current parameters in the vector "reference" @@ -556,18 +580,38 @@ void System::initSolution(VEC_pD ¶ms) // - Organizes the rest of constraints into two subsystems for // tag ids >=0 and < 0 respectively and applies the // system reduction specified in the previous step - MAP_pD_I pIndex; - for (int i=0; i < int(params.size()); ++i) - pIndex[params[i]] = i; + + isInit = false; + if (!hasUnknowns) + return; + + // storing reference configuration + setReference(); + + // diagnose conflicting or redundant constraints + if (!hasDiagnosis) { + diagnose(); + if (!hasDiagnosis) + return; + } + std::vector clistR; + if (redundant.size()) { + for (std::vector::const_iterator constr=clist.begin(); + constr != clist.end(); ++constr) + if (redundant.count(*constr) == 0) + clistR.push_back(*constr); + } + else + clistR = clist; // partitioning into decoupled components Graph g; - for (int i=0; i < int(params.size() + clist.size()); i++) + for (int i=0; i < int(plist.size() + clistR.size()); i++) boost::add_vertex(g); - int cvtid = int(params.size()); - for (std::vector::const_iterator constr=clist.begin(); - constr != clist.end(); ++constr, cvtid++) { + int cvtid = int(plist.size()); + for (std::vector::const_iterator constr=clistR.begin(); + constr != clistR.end(); ++constr, cvtid++) { VEC_pD &cparams = c2p[*constr]; for (VEC_pD::const_iterator param=cparams.begin(); param != cparams.end(); ++param) { @@ -580,113 +624,131 @@ void System::initSolution(VEC_pD ¶ms) VEC_I components(boost::num_vertices(g)); int componentsSize = boost::connected_components(g, &components[0]); - clearReference(); - for (VEC_pD::const_iterator param=params.begin(); - param != params.end(); ++param) - reference[*param] = **param; - // identification of equality constraints and parameter reduction - std::set eliminated; // constraints that will be eliminated through reduction - reductionmap.clear(); + std::set reducedConstrs; // constraints that will be eliminated through reduction + reductionmaps.clear(); // destroy any maps + reductionmaps.resize(componentsSize); // create empty maps to be filled in { - VEC_pD reduced_params=params; + VEC_pD reducedParams=plist; - for (std::vector::const_iterator constr=clist.begin(); - constr != clist.end(); ++constr) { + for (std::vector::const_iterator constr=clistR.begin(); + constr != clistR.end(); ++constr) { if ((*constr)->getTag() >= 0 && (*constr)->getTypeId() == Equal) { MAP_pD_I::const_iterator it1,it2; it1 = pIndex.find((*constr)->params()[0]); it2 = pIndex.find((*constr)->params()[1]); if (it1 != pIndex.end() && it2 != pIndex.end()) { - eliminated.insert(*constr); - double *p_kept = reduced_params[it1->second]; - double *p_replaced = reduced_params[it2->second]; - for (int i=0; i < int(params.size()); ++i) - if (reduced_params[i] == p_replaced) - reduced_params[i] = p_kept; + reducedConstrs.insert(*constr); + double *p_kept = reducedParams[it1->second]; + double *p_replaced = reducedParams[it2->second]; + for (int i=0; i < int(plist.size()); ++i) + if (reducedParams[i] == p_replaced) + reducedParams[i] = p_kept; } } } - for (int i=0; i < int(params.size()); ++i) - if (params[i] != reduced_params[i]) - reductionmap[params[i]] = reduced_params[i]; + for (int i=0; i < int(plist.size()); ++i) + if (plist[i] != reducedParams[i]) { + int cid = components[i]; + reductionmaps[cid][plist[i]] = reducedParams[i]; + } } - std::vector< std::vector > clists0(componentsSize), - clists1(componentsSize), - clists2(componentsSize); - int i = int(params.size()); - for (std::vector::const_iterator constr=clist.begin(); - constr != clist.end(); ++constr, i++) { - if (eliminated.count(*constr) == 0) { - int id = components[i]; - if ((*constr)->getTag() >= 0) - clists0[id].push_back(*constr); - else if ((*constr)->getTag() == -1) // move constraints - clists1[id].push_back(*constr); - else // distance from reference constraints - clists2[id].push_back(*constr); + clists.clear(); // destroy any lists + clists.resize(componentsSize); // create empty lists to be filled in + int i = int(plist.size()); + for (std::vector::const_iterator constr=clistR.begin(); + constr != clistR.end(); ++constr, i++) { + if (reducedConstrs.count(*constr) == 0) { + int cid = components[i]; + clists[cid].push_back(*constr); } } - std::vector< std::vector > plists(componentsSize); - for (int i=0; i < int(params.size()); ++i) { - int id = components[i]; - plists[id].push_back(params[i]); + plists.clear(); // destroy any lists + plists.resize(componentsSize); // create empty lists to be filled in + for (int i=0; i < int(plist.size()); ++i) { + int cid = components[i]; + plists[cid].push_back(plist[i]); } + // calculates subSystems and subSystemsAux from clists, plists and reductionmaps clearSubSystems(); - for (int cid=0; cid < componentsSize; cid++) { - subsyslist.push_back(std::vector(0)); - if (clists0[cid].size() > 0) - subsyslist[cid].push_back(new SubSystem(clists0[cid], plists[cid], reductionmap)); - if (clists1[cid].size() > 0) - subsyslist[cid].push_back(new SubSystem(clists1[cid], plists[cid], reductionmap)); - if (clists2[cid].size() > 0) - subsyslist[cid].push_back(new SubSystem(clists2[cid], plists[cid], reductionmap)); + for (int cid=0; cid < clists.size(); cid++) { + std::vector clist0, clist1; + for (std::vector::const_iterator constr=clists[cid].begin(); + constr != clists[cid].end(); ++constr) { + if ((*constr)->getTag() >= 0) + clist0.push_back(*constr); + else // move or distance from reference constraints + clist1.push_back(*constr); + } + + subSystems.push_back(NULL); + subSystemsAux.push_back(NULL); + if (clist0.size() > 0) + subSystems[cid] = new SubSystem(clist0, plists[cid], reductionmaps[cid]); + if (clist1.size() > 0) + subSystemsAux[cid] = new SubSystem(clist1, plists[cid], reductionmaps[cid]); } - init = true; + + isInit = true; } -void System::clearReference() +void System::setReference() { - init = false; reference.clear(); + reference.reserve(plist.size()); + for (VEC_pD::const_iterator param=plist.begin(); + param != plist.end(); ++param) + reference.push_back(**param); } void System::resetToReference() { - for (MAP_pD_D::const_iterator it=reference.begin(); - it != reference.end(); ++it) - *(it->first) = it->second; + if (reference.size() == plist.size()) { + VEC_D::const_iterator ref=reference.begin(); + VEC_pD::iterator param=plist.begin(); + for (; ref != reference.end(); ++ref, ++param) + **param = *ref; + } } int System::solve(VEC_pD ¶ms, bool isFine, Algorithm alg) { - initSolution(params); + declareUnknowns(params); + initSolution(); return solve(isFine, alg); } int System::solve(bool isFine, Algorithm alg) { + if (!isInit) + return Failed; + bool isReset = false; // return success by default in order to permit coincidence constraints to be applied // even if no other system has to be solved int res = Success; - for (int cid=0; cid < int(subsyslist.size()); cid++) { - if (subsyslist[cid].size() > 0 && !isReset) { + for (int cid=0; cid < int(subSystems.size()); cid++) { + if ((subSystems[cid] || subSystemsAux[cid]) && !isReset) { resetToReference(); isReset = true; } - if (subsyslist[cid].size() == 1) - res = std::max(res, solve(subsyslist[cid][0], isFine, alg)); - else if (subsyslist[cid].size() == 2) - res = std::max(res, solve(subsyslist[cid][0], subsyslist[cid][1], isFine)); - else if (subsyslist[cid].size() > 2) - // subsystem 1 has higher priority than subsystems 2,3,... - // these subsystems act like a preconditioner - for (int i=subsyslist[cid].size()-1; i > 0; i--) - res = std::max(res, solve(subsyslist[cid][0], subsyslist[cid][i], isFine)); + if (subSystems[cid] && subSystemsAux[cid]) + res = std::max(res, solve(subSystems[cid], subSystemsAux[cid], isFine)); + else if (subSystems[cid]) + res = std::max(res, solve(subSystems[cid], isFine, alg)); + else if (subSystemsAux[cid]) + res = std::max(res, solve(subSystemsAux[cid], isFine, alg)); + } + if (res == Success) { + for (std::set::const_iterator constr=redundant.begin(); + constr != redundant.end(); constr++) + if ((*constr)->error() > XconvergenceFine) { + res = Converged; + return res; + } } return res; } @@ -1068,7 +1130,7 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) int xsizeB = subsysB->pSize(); int csizeA = subsysA->cSize(); - VEC_pD plist(xsizeA+xsizeB); + VEC_pD plistAB(xsizeA+xsizeB); { VEC_pD plistA, plistB; subsysA->getParamList(plistA); @@ -1079,10 +1141,10 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) VEC_pD::const_iterator it; it = std::set_union(plistA.begin(),plistA.end(), - plistB.begin(),plistB.end(),plist.begin()); - plist.resize(it-plist.begin()); + plistB.begin(),plistB.end(),plistAB.begin()); + plistAB.resize(it-plistAB.begin()); } - int xsize = plist.size(); + int xsize = plistAB.size(); Eigen::MatrixXd B = Eigen::MatrixXd::Identity(xsize, xsize); Eigen::MatrixXd JA(csizeA, xsize); @@ -1100,12 +1162,12 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) subsysA->redirectParams(); subsysB->redirectParams(); - subsysB->getParams(plist,x); - subsysA->getParams(plist,x); - subsysB->setParams(plist,x); // just to ensure that A and B are synchronized + subsysB->getParams(plistAB,x); + subsysA->getParams(plistAB,x); + subsysB->setParams(plistAB,x); // just to ensure that A and B are synchronized - subsysB->calcGrad(plist,grad); - subsysA->calcJacobi(plist,JA); + subsysB->calcGrad(plistAB,grad); + subsysA->calcJacobi(plistAB,JA); subsysA->calcResidual(resA); double convergence = isFine ? XconvergenceFine : XconvergenceRough; @@ -1130,7 +1192,7 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) double tau=0.5; double rho=0.5; double alpha=1; - alpha = std::min(alpha, subsysA->maxStep(plist,xdir)); + alpha = std::min(alpha, subsysA->maxStep(plistAB,xdir)); // Eq. 18.32 // double mu = lambda.lpNorm() + 0.01; @@ -1148,8 +1210,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) double deriv = grad.dot(xdir) - mu * resA.lpNorm<1>(); x = x0 + alpha * xdir; - subsysA->setParams(plist,x); - subsysB->setParams(plist,x); + subsysA->setParams(plistAB,x); + subsysB->setParams(plistAB,x); subsysA->calcResidual(resA); double f = subsysB->error() + mu * resA.lpNorm<1>(); @@ -1161,8 +1223,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) // Eigen::ComputeThinV).solve(-resA); xdir1 = -Y*resA; x += xdir1; // = x0 + alpha * xdir + xdir1 - subsysA->setParams(plist,x); - subsysB->setParams(plist,x); + subsysA->setParams(plistAB,x); + subsysB->setParams(plistAB,x); subsysA->calcResidual(resA); f = subsysB->error() + mu * resA.lpNorm<1>(); if (f < f0 + eta * alpha * deriv) @@ -1172,8 +1234,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) if (alpha < 1e-8) // let the linesearch fail alpha = 0.; x = x0 + alpha * xdir; - subsysA->setParams(plist,x); - subsysB->setParams(plist,x); + subsysA->setParams(plistAB,x); + subsysB->setParams(plistAB,x); subsysA->calcResidual(resA); f = subsysB->error() + mu * resA.lpNorm<1>(); if (alpha < 1e-8) // let the linesearch fail @@ -1186,8 +1248,8 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) y = grad - JA.transpose() * lambda; { - subsysB->calcGrad(plist,grad); - subsysA->calcJacobi(plist,JA); + subsysB->calcGrad(plistAB,grad); + subsysA->calcJacobi(plistAB,JA); subsysA->calcResidual(resA); } y = grad - JA.transpose() * lambda - y; // Eq. 18.13 @@ -1225,13 +1287,15 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine) void System::applySolution() { - for (int cid=0; cid < int(subsyslist.size()); cid++) - for (int i=subsyslist[cid].size()-1; i >= 0; i--) - subsyslist[cid][i]->applySolution(); - - for (MAP_pD_pD::const_iterator it=reductionmap.begin(); - it != reductionmap.end(); ++it) - *(it->first) = *(it->second); + for (int cid=0; cid < int(subSystems.size()); cid++) { + if (subSystemsAux[cid]) + subSystemsAux[cid]->applySolution(); + if (subSystems[cid]) + subSystems[cid]->applySolution(); + for (MAP_pD_pD::const_iterator it=reductionmaps[cid].begin(); + it != reductionmaps[cid].end(); ++it) + *(it->first) = *(it->second); + } } void System::undoSolution() @@ -1239,7 +1303,7 @@ void System::undoSolution() resetToReference(); } -int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags) +int System::diagnose() { // Analyses the constrainess grad of the system and provides feedback // The vector "conflictingTags" will hold a group of conflicting constraints @@ -1251,22 +1315,24 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags) // will provide no feedback about possible conflicts between // two high priority constraints. For this reason, tagging // constraints with 0 should be used carefully. - if (!isInit()) - return -1; + hasDiagnosis = false; + if (!hasUnknowns) { + dofs = -1; + return dofs; + } + redundant.clear(); conflictingTags.clear(); - std::vector conflictingIndex; - VEC_I tags; - Eigen::MatrixXd J(clist.size(), params.size()); + redundantTags.clear(); + Eigen::MatrixXd J(clist.size(), plist.size()); int count=0; for (std::vector::iterator constr=clist.begin(); constr != clist.end(); ++constr) { (*constr)->revertParams(); if ((*constr)->getTag() >= 0) { count++; - tags.push_back((*constr)->getTag()); - for (int j=0; j < int(params.size()); j++) - J(count-1,j) = (*constr)->grad(params[j]); + for (int j=0; j < int(plist.size()); j++) + J(count-1,j) = (*constr)->grad(plist[j]); } } @@ -1284,7 +1350,7 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags) R = qrJT.matrixQR().topRows(constrNum) .triangularView(); - if (constrNum > rank) { // conflicting constraints + if (constrNum > rank) { // conflicting or redundant constraints for (int i=1; i < rank; i++) { // eliminate non zeros above pivot assert(R(i,i) != 0); @@ -1296,43 +1362,139 @@ int System::diagnose(VEC_pD ¶ms, VEC_I &conflictingTags) } } } - conflictingIndex.resize(constrNum-rank); + std::vector< std::vector > conflictGroups(constrNum-rank); for (int j=rank; j < constrNum; j++) { for (int row=0; row < rank; row++) { if (fabs(R(row,j)) > 1e-10) { int origCol = qrJT.colsPermutation().indices()[row]; - conflictingIndex[j-rank].push_back(origCol); + conflictGroups[j-rank].push_back(clist[origCol]); } } int origCol = qrJT.colsPermutation().indices()[j]; - conflictingIndex[j-rank].push_back(origCol); + conflictGroups[j-rank].push_back(clist[origCol]); } - SET_I tags_set; - for (int i=0; i < conflictingIndex.size(); i++) { - for (int j=0; j < conflictingIndex[i].size(); j++) { - tags_set.insert(tags[conflictingIndex[i][j]]); + // try to remove the conflicting constraints and solve the + // system in order to check if the removed constraints were + // just redundant but not really conflicting + std::set skipped; + SET_I satisfiedGroups; + while (1) { + std::map< Constraint *, SET_I > conflictingMap; + for (int i=0; i < conflictGroups.size(); i++) { + if (satisfiedGroups.count(i) == 0) { + for (int j=0; j < conflictGroups[i].size(); j++) { + Constraint *constr = conflictGroups[i][j]; + if (constr->getTag() != 0) // exclude constraints tagged with zero + conflictingMap[constr].insert(i); + } + } + } + if (conflictingMap.empty()) + break; + + int maxPopularity = 0; + Constraint *mostPopular = NULL; + for (std::map< Constraint *, SET_I >::const_iterator it=conflictingMap.begin(); + it != conflictingMap.end(); it++) { + if (it->second.size() >= maxPopularity) { + mostPopular = it->first; + maxPopularity = it->second.size(); + } + } + if (maxPopularity > 0) { + skipped.insert(mostPopular); + for (SET_I::const_iterator it=conflictingMap[mostPopular].begin(); + it != conflictingMap[mostPopular].end(); it++) + satisfiedGroups.insert(*it); } } - tags_set.erase(0); // exclude constraints tagged with zero - conflictingTags.resize(tags_set.size()); - std::copy(tags_set.begin(), tags_set.end(), conflictingTags.begin()); - if (paramsNum == rank) // over-constrained - return paramsNum - constrNum; + std::vector clistTmp; + clistTmp.reserve(clist.size()); + for (std::vector::iterator constr=clist.begin(); + constr != clist.end(); ++constr) + if (skipped.count(*constr) == 0) + clistTmp.push_back(*constr); + + SubSystem *subSysTmp = new SubSystem(clistTmp, plist); + int res = solve(subSysTmp); + if (res == Success) { + subSysTmp->applySolution(); + for (std::set::const_iterator constr=skipped.begin(); + constr != skipped.end(); constr++) { + if ((*constr)->error() < XconvergenceFine) + redundant.insert(*constr); + } + resetToReference(); + + std::vector< std::vector > conflictGroupsOrig=conflictGroups; + conflictGroups.clear(); + for (int i=conflictGroupsOrig.size()-1; i >= 0; i--) { + bool isRedundant = false; + for (int j=0; j < conflictGroupsOrig[i].size(); j++) { + if (redundant.count(conflictGroupsOrig[i][j]) > 0) { + isRedundant = true; + break; + } + } + if (!isRedundant) + conflictGroups.push_back(conflictGroupsOrig[i]); + else + constrNum--; + } + } + delete subSysTmp; + + // simplified output of conflicting tags + SET_I conflictingTagsSet; + for (int i=0; i < conflictGroups.size(); i++) { + for (int j=0; j < conflictGroups[i].size(); j++) { + conflictingTagsSet.insert(conflictGroups[i][j]->getTag()); + } + } + conflictingTagsSet.erase(0); // exclude constraints tagged with zero + conflictingTags.resize(conflictingTagsSet.size()); + std::copy(conflictingTagsSet.begin(), conflictingTagsSet.end(), + conflictingTags.begin()); + + // output of redundant tags + SET_I redundantTagsSet; + for (std::set::iterator constr=redundant.begin(); + constr != redundant.end(); ++constr) + redundantTagsSet.insert((*constr)->getTag()); + // remove tags represented at least in one non-redundant constraint + for (std::vector::iterator constr=clist.begin(); + constr != clist.end(); ++constr) + if (redundant.count(*constr) == 0) + redundantTagsSet.erase((*constr)->getTag()); + redundantTags.resize(redundantTagsSet.size()); + std::copy(redundantTagsSet.begin(), redundantTagsSet.end(), + redundantTags.begin()); + + if (paramsNum == rank && constrNum > rank) { // over-constrained + hasDiagnosis = true; + dofs = paramsNum - constrNum; + return dofs; + } } - return paramsNum - rank; + hasDiagnosis = true; + dofs = paramsNum - rank; + return dofs; } - return params.size(); + hasDiagnosis = true; + dofs = plist.size(); + return dofs; } void System::clearSubSystems() { - init = false; - for (int i=0; i < int(subsyslist.size()); i++) - free(subsyslist[i]); - subsyslist.clear(); + isInit = false; + free(subSystems); + free(subSystemsAux); + subSystems.clear(); + subSystemsAux.clear(); } double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir) diff --git a/src/Mod/Sketcher/App/freegcs/GCS.h b/src/Mod/Sketcher/App/freegcs/GCS.h index 5cd1466eaf..f0d87906fb 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.h +++ b/src/Mod/Sketcher/App/freegcs/GCS.h @@ -49,25 +49,31 @@ namespace GCS // This is the main class. It holds all constraints and information // about partitioning into subsystems and solution strategies private: - std::vector clist; + VEC_pD plist; // list of the unknown parameters + MAP_pD_I pIndex; + std::vector clist; std::map c2p; // constraint to parameter adjacency list std::map > p2c; // parameter to constraint adjacency list - // each row of subsyslist contains up to 3 subsystems. - // the first one has the highest priority, always used as the primary subsystem - // the second one is used as secondary subsystem - // the third one is used as secondary system and serves as a preconditioner - std::vector< std::vector > subsyslist; + std::vector subSystems, subSystemsAux; void clearSubSystems(); - MAP_pD_D reference; - void clearReference(); - void resetToReference(); + VEC_D reference; + void setReference(); // copies the current parameter values to reference + void resetToReference(); // reverts all parameter values to the stored reference - MAP_pD_pD reductionmap; // for simplification of equality constraints + std::vector< VEC_pD > plists; // partitioned plist except equality constraints + std::vector< std::vector > clists; // partitioned clist except equality constraints + std::vector< MAP_pD_pD > reductionmaps; // for simplification of equality constraints - bool init; + int dofs; + std::set redundant; + VEC_I conflictingTags, redundantTags; + + bool hasUnknowns; // if plist is filled with the unknown parameters + bool hasDiagnosis; // if dofs, conflictingTags, redundantTags are up to date + bool isInit; // if plists, clists, reductionmaps are up to date int solve_BFGS(SubSystem *subsys, bool isFine); int solve_LM(SubSystem *subsys); @@ -147,7 +153,8 @@ namespace GCS int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0); void rescaleConstraint(int id, double coeff); - void initSolution(VEC_pD ¶ms); + void declareUnknowns(VEC_pD ¶ms); + void initSolution(); int solve(bool isFine=true, Algorithm alg=DogLeg); int solve(VEC_pD ¶ms, bool isFine=true, Algorithm alg=DogLeg); @@ -157,9 +164,12 @@ namespace GCS void applySolution(); void undoSolution(); - bool isInit() const { return init; } - - int diagnose(VEC_pD ¶ms, VEC_I &conflictingTags); + int diagnose(); + int dofsNumber() { return hasDiagnosis ? dofs : -1; } + void getConflicting(VEC_I &conflictingOut) const + { conflictingOut = hasDiagnosis ? conflictingTags : VEC_I(0); } + void getRedundant(VEC_I &redundantOut) const + { redundantOut = hasDiagnosis ? redundantTags : VEC_I(0); } }; /////////////////////////////////////// diff --git a/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp b/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp index 7061f3a97c..5ef6c65fb5 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp @@ -86,6 +86,9 @@ void TaskSketcherMessages::slotSetUp(int type, int dofs, const std::string &msg) case 3: ui->labelConstrainStatus->setText(QString::fromLatin1("Over-constrained sketch
%1
").arg(QString::fromStdString(msg))); break; + case 4: + ui->labelConstrainStatus->setText(QString::fromLatin1("Sketch contains redundant constraints
%1").arg(QString::fromStdString(msg))); + break; } } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 78841d18cb..2239f7445e 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -2825,21 +2825,30 @@ void ViewProviderSketch::solveSketch(void) signalSetUp(2, dofs, msg); signalSolved(-1, 0); } - else if (edit->ActSketch.solve() == 0) { // solving the sketch - if (dofs == 0) { - // color the sketch as fully constrained - edit->FullyConstrained = true; - //Base::Console().Message("Fully constrained sketch\n"); - signalSetUp(0, 0, msg); + else { + if (edit->ActSketch.hasRedundancies()) { // redundant constraints + SketchObject::appendRedundantMsg(edit->ActSketch.getRedundant(), msg); + //Base::Console().Warning("Sketch with redundant constraints\n%s",msg.c_str()); + signalSetUp(4, dofs, msg); + } + if (edit->ActSketch.solve() == 0) { // solving the sketch + if (dofs == 0) { + // color the sketch as fully constrained + edit->FullyConstrained = true; + if (!edit->ActSketch.hasRedundancies()) { + //Base::Console().Message("Fully constrained sketch\n"); + signalSetUp(0, 0, msg); + } + } + else if (!edit->ActSketch.hasRedundancies()) { + //Base::Console().Message("Under-constrained sketch with %d degrees of freedom\n", dofs); + signalSetUp(1, dofs, msg); + } + signalSolved(0, edit->ActSketch.SolveTime); } else { - //Base::Console().Message("Under-constrained sketch with %d degrees of freedom\n", dofs); - signalSetUp(1, dofs, msg); + signalSolved(1, edit->ActSketch.SolveTime); } - signalSolved(0, edit->ActSketch.SolveTime); - } - else { - signalSolved(1, edit->ActSketch.SolveTime); } } From 56758cab50935204d36eb39282af41de19ed6658 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 14 May 2012 11:13:19 -0300 Subject: [PATCH 192/351] Fixed bug in Draft Clone --- src/Mod/Draft/Draft.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 6f8250a3da..0014a45130 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -2853,8 +2853,9 @@ class _Clone: if o.isDerivedFrom("Part::Feature"): sh = o.Shape.copy() m = FreeCAD.Matrix() - m.scale(obj.Scale) - sh = sh.transformGeometry(m) + if hasattr(obj,"Scale") and not sh.isNull(): + m.scale(obj.Scale) + sh = sh.transformGeometry(m) shapes.append(sh) if shapes: obj.Shape = Part.makeCompound(shapes) From 57403910b0381afe3287e1e6f8b10b6991a195b1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 14 May 2012 19:15:11 +0200 Subject: [PATCH 193/351] Replace makeTube algorithm --- src/Mod/Part/App/AppPartPy.cpp | 29 +++++++++++++++++-- src/Mod/Part/App/TopoShape.cpp | 51 ++++++++++++++++++++++------------ src/Mod/Part/App/TopoShape.h | 3 +- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 2662593c58..2132042df4 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -1043,14 +1043,36 @@ static PyObject * makeTube(PyObject *self, PyObject *args) PyObject *pshape; double radius; double tolerance=0.001; + char* scont = "C0"; + int maxdegree = 3; + int maxsegment = 30; // Path + radius - if (!PyArg_ParseTuple(args, "O!d", &(TopoShapePy::Type), &pshape, &radius)) + if (!PyArg_ParseTuple(args, "O!d|sii", &(TopoShapePy::Type), &pshape, &radius, &scont, &maxdegree, &maxsegment)) return 0; + std::string str_cont = scont; + int cont; + if (str_cont == "C0") + cont = (int)GeomAbs_C0; + else if (str_cont == "C1") + cont = (int)GeomAbs_C1; + else if (str_cont == "C2") + cont = (int)GeomAbs_C2; + else if (str_cont == "C3") + cont = (int)GeomAbs_C3; + else if (str_cont == "CN") + cont = (int)GeomAbs_CN; + else if (str_cont == "G1") + cont = (int)GeomAbs_G1; + else if (str_cont == "G2") + cont = (int)GeomAbs_G2; + else + cont = (int)GeomAbs_C0; + try { const TopoDS_Shape& path_shape = static_cast(pshape)->getTopoShapePtr()->_Shape; TopoShape myShape(path_shape); - TopoDS_Shape face = myShape.makeTube(radius, tolerance); + TopoDS_Shape face = myShape.makeTube(radius, tolerance, cont, maxdegree, maxsegment); return new TopoShapeFacePy(new TopoShape(face)); } catch (Standard_Failure) { @@ -1465,7 +1487,8 @@ struct PyMethodDef Part_methods[] = { "these must have the same number of edges."}, {"makeTube" ,makeTube,METH_VARARGS, - "makeTube(edge,float) -- Create a tube."}, + "makeTube(edge,radius,[continuity,max degree,max segments]) -- Create a tube.\n" + "continuity is a string which must be 'C0','C1','C2','C3','CN','G1' or 'G1',"}, {"makeSweepSurface" ,makeSweepSurface,METH_VARARGS, "makeSweepSurface(edge(path),edge(profile),[float]) -- Create a profile along a path."}, diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index f78bc50262..22ccd16ad3 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -32,7 +32,9 @@ # include # include # include +# include # include +# include # include # include # include @@ -1343,7 +1345,8 @@ TopoDS_Shape TopoShape::makePipeShell(const TopTools_ListOfShape& profiles, return mkPipeShell.Shape(); } -TopoDS_Shape TopoShape::makeTube(double radius, double tol) const +#if 0 +TopoDS_Shape TopoShape::makeTube() const { // http://opencascade.blogspot.com/2009/11/surface-modeling-part3.html if (this->_Shape.IsNull()) @@ -1378,43 +1381,54 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol) const ); return mkBuilder.Face(); } - -// for testing -static Handle(Law_Function) CreateBsFunction (const Standard_Real theFirst, const Standard_Real theLast) +#else +static Handle(Law_Function) CreateBsFunction (const Standard_Real theFirst, const Standard_Real theLast, const Standard_Real theRadius) { //Handle_Law_BSpline aBs; //Handle_Law_BSpFunc aFunc = new Law_BSpFunc (aBs, theFirst, theLast); Handle_Law_Linear aFunc = new Law_Linear(); - aFunc->Set(theFirst, 2.0, theLast, 3.0); + aFunc->Set(theFirst, theRadius, theLast, theRadius); return aFunc; } -// for testing -TopoDS_Shape TopoShape::makeTube() const +TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdegree, int maxsegm) const { // http://opencascade.blogspot.com/2009/11/surface-modeling-part3.html - Standard_Real theTol = 0.001; + Standard_Real theTol = tol; Standard_Boolean theIsPolynomial = Standard_True; Standard_Boolean myIsElem = Standard_True; - GeomAbs_Shape theContinuity = GeomAbs_G1; - Standard_Integer theMaxDegree = 3; - Standard_Integer theMaxSegment = 1000; + GeomAbs_Shape theContinuity = GeomAbs_Shape(cont); + Standard_Integer theMaxDegree = maxdegree; + Standard_Integer theMaxSegment = maxsegm; if (this->_Shape.IsNull()) Standard_Failure::Raise("Cannot sweep along empty spine"); - if (this->_Shape.ShapeType() != TopAbs_EDGE) - Standard_Failure::Raise("Spine shape is not an edge"); - const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); - BRepAdaptor_Curve path_adapt(path_edge); + Handle(Adaptor3d_HCurve) myPath; + if (this->_Shape.ShapeType() == TopAbs_EDGE) { + const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); + BRepAdaptor_Curve path_adapt(path_edge); + myPath = new BRepAdaptor_HCurve(path_adapt); + theContinuity = GeomAbs_C0; + } + //else if (this->_Shape.ShapeType() == TopAbs_WIRE) { + // const TopoDS_Wire& path_wire = TopoDS::Wire(this->_Shape); + // BRepAdaptor_CompCurve path_adapt(path_wire); + // myPath = new BRepAdaptor_HCompCurve(path_adapt); + //} + //else { + // Standard_Failure::Raise("Spine shape is neither an edge nor a wire"); + //} + else { + Standard_Failure::Raise("Spine shape is not an edge"); + } //circular profile - Handle(Geom_Circle) aCirc = new Geom_Circle (gp::XOY(), 1.0); + Handle(Geom_Circle) aCirc = new Geom_Circle (gp::XOY(), radius); aCirc->Rotate (gp::OZ(), Standard_PI/2.); //perpendicular section - Handle(BRepAdaptor_HCurve) myPath = new BRepAdaptor_HCurve(path_adapt); - Handle(Law_Function) myEvol = ::CreateBsFunction (myPath->FirstParameter(), myPath->LastParameter()); + Handle(Law_Function) myEvol = ::CreateBsFunction (myPath->FirstParameter(), myPath->LastParameter(), radius); Handle(GeomFill_SectionLaw) aSec = new GeomFill_EvolvedSection(aCirc, myEvol); Handle(GeomFill_LocationLaw) aLoc = new GeomFill_CurveAndTrihedron(new GeomFill_CorrectedFrenet); aLoc->SetCurve (myPath); @@ -1438,6 +1452,7 @@ TopoDS_Shape TopoShape::makeTube() const return TopoDS_Shape(); } +#endif TopoDS_Shape TopoShape::makeSweep(const TopoDS_Shape& profile, double tol, int fillMode) const { diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 0cf1087f93..1de76b1cad 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -158,8 +158,7 @@ public: TopoDS_Shape makeThickSolid(const TopTools_ListOfShape& remFace, Standard_Real offset, Standard_Real tolerance) const; TopoDS_Shape makeSweep(const TopoDS_Shape& profile, double, int) const; - TopoDS_Shape makeTube(double radius, double tol) const; - TopoDS_Shape makeTube() const; + TopoDS_Shape makeTube(double radius, double tol, int cont, int maxdeg, int maxsegm) const; TopoDS_Shape makeHelix(Standard_Real pitch, Standard_Real height, Standard_Real radius, Standard_Real angle=0, Standard_Boolean left=Standard_False) const; TopoDS_Shape makeLoft(const TopTools_ListOfShape& profiles, Standard_Boolean isSolid, From e63eaf90755fb880441f3472d04c8d2387795fbc Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Tue, 15 May 2012 18:01:15 +0200 Subject: [PATCH 194/351] add isNull() method to Rotation --- src/Base/RotationPy.xml | 8 ++++++++ src/Base/RotationPyImp.cpp | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Base/RotationPy.xml b/src/Base/RotationPy.xml index 02dc34ee84..111cfb74c7 100644 --- a/src/Base/RotationPy.xml +++ b/src/Base/RotationPy.xml @@ -48,6 +48,14 @@ + + + + isNull() -> Bool + returns True if the rotation equals the unity matrix + + + The rotation elements (as quaternion) diff --git a/src/Base/RotationPyImp.cpp b/src/Base/RotationPyImp.cpp index 7abede54c7..159952c7e0 100644 --- a/src/Base/RotationPyImp.cpp +++ b/src/Base/RotationPyImp.cpp @@ -144,6 +144,17 @@ PyObject* RotationPy::toEuler(PyObject * args) return Py::new_reference_to(tuple); } +PyObject* RotationPy::isNull(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + Base::Rotation rot = * getRotationPtr(); + Base::Rotation nullrot(0,0,0,1); + Base::Rotation nullrotinv(0,0,0,-1); + bool null = (rot == nullrot) | (rot == nullrotinv); + return Py_BuildValue("O", (null ? Py_True : Py_False)); +} + Py::Tuple RotationPy::getQ(void) const { double q0, q1, q2, q3; From 1a79480bd61bda58381d48b1c1543f61273d2976 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 16 May 2012 16:31:02 -0300 Subject: [PATCH 195/351] Added 0000145 : Drawing clip objects --- src/Mod/Drawing/App/AppDrawing.cpp | 2 + src/Mod/Drawing/App/CMakeLists.txt | 2 + src/Mod/Drawing/App/FeatureClip.cpp | 111 +++ src/Mod/Drawing/App/FeatureClip.h | 71 ++ src/Mod/Drawing/App/FeaturePage.cpp | 7 +- src/Mod/Drawing/App/Makefile.am | 2 + src/Mod/Drawing/Gui/Command.cpp | 47 +- src/Mod/Drawing/Gui/Resources/Drawing.qrc | 1 + src/Mod/Drawing/Gui/Resources/Makefile.am | 1 + .../Resources/icons/actions/drawing-clip.svg | 710 ++++++++++++++++++ src/Mod/Drawing/Gui/Workbench.cpp | 4 + 11 files changed, 955 insertions(+), 3 deletions(-) create mode 100644 src/Mod/Drawing/App/FeatureClip.cpp create mode 100644 src/Mod/Drawing/App/FeatureClip.h create mode 100644 src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg diff --git a/src/Mod/Drawing/App/AppDrawing.cpp b/src/Mod/Drawing/App/AppDrawing.cpp index a581668bad..016abf81b6 100644 --- a/src/Mod/Drawing/App/AppDrawing.cpp +++ b/src/Mod/Drawing/App/AppDrawing.cpp @@ -22,6 +22,7 @@ #include "FeatureViewPart.h" #include "FeatureViewAnnotation.h" #include "FeatureProjection.h" +#include "FeatureClip.h" #include "PageGroup.h" extern struct PyMethodDef Drawing_methods[]; @@ -59,6 +60,7 @@ void DrawingExport initDrawing() Drawing::FeatureViewPartPython ::init(); Drawing::FeatureViewPython ::init(); Drawing::FeatureViewAnnotation ::init(); + Drawing::FeatureClip ::init(); } } // extern "C" diff --git a/src/Mod/Drawing/App/CMakeLists.txt b/src/Mod/Drawing/App/CMakeLists.txt index 98767a24a7..00710b75e0 100644 --- a/src/Mod/Drawing/App/CMakeLists.txt +++ b/src/Mod/Drawing/App/CMakeLists.txt @@ -29,6 +29,8 @@ SET(Features_SRCS FeatureViewPart.h FeatureViewAnnotation.cpp FeatureViewAnnotation.h + FeatureClip.cpp + FeatureClip.h PageGroup.cpp PageGroup.h ) diff --git a/src/Mod/Drawing/App/FeatureClip.cpp b/src/Mod/Drawing/App/FeatureClip.cpp new file mode 100644 index 0000000000..c45229929a --- /dev/null +++ b/src/Mod/Drawing/App/FeatureClip.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre 2012 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + + +#include +#include +#include +#include +#include +#include + +#include "FeatureClip.h" +#include "FeatureView.h" + +using namespace Drawing; +using namespace std; + + +//=========================================================================== +// FeaturePage +//=========================================================================== + +PROPERTY_SOURCE(Drawing::FeatureClip, App::DocumentObjectGroup) + +FeatureClip::FeatureClip(void) +{ + static const char *group = "Drawing view"; + App::PropertyType hidden = (App::PropertyType)(App::Prop_Hidden); + ADD_PROPERTY_TYPE(ViewResult ,(""),group,hidden,"Resulting SVG view of this clip"); + ADD_PROPERTY_TYPE(X ,(10),group,App::Prop_None ,"The left margin of the view area of this clip"); + ADD_PROPERTY_TYPE(Y ,(10),group,App::Prop_None ,"The top margin of the view area of this clip"); + ADD_PROPERTY_TYPE(Height ,(10),group,App::Prop_None ,"The height of the view area of this clip"); + ADD_PROPERTY_TYPE(Width ,(10),group,App::Prop_None ,"The width of the view area of this clip"); + ADD_PROPERTY_TYPE(ShowFrame ,(0),group,App::Prop_None,"Specifies if the clip frame appears on the page or not"); +} + +FeatureClip::~FeatureClip() +{ +} + +/// get called by the container when a Property was changed +void FeatureClip::onChanged(const App::Property* prop) +{ + App::DocumentObjectGroup::onChanged(prop); +} + +App::DocumentObjectExecReturn *FeatureClip::execute(void) +{ + ostringstream svg; + + // creating clip path + svg << "" + << "" << endl; + + // show clip frame on the page if needed + + if (ShowFrame.getValue()) { + svg << "" << endl; + } + + // create clipped group + svg << "" << endl; + + // get through the children and collect all the views + const std::vector &Grp = Group.getValues(); + for (std::vector::const_iterator It= Grp.begin();It!=Grp.end();++It) { + if ((*It)->getTypeId().isDerivedFrom(Drawing::FeatureView::getClassTypeId())) { + Drawing::FeatureView *View = dynamic_cast(*It); + svg << View->ViewResult.getValue() << endl; + } + } + + // closing clipped group + svg << "" << endl; + + ViewResult.setValue(svg.str().c_str()); + return App::DocumentObject::StdReturn; +} diff --git a/src/Mod/Drawing/App/FeatureClip.h b/src/Mod/Drawing/App/FeatureClip.h new file mode 100644 index 0000000000..ae1e6c0fc0 --- /dev/null +++ b/src/Mod/Drawing/App/FeatureClip.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre 2012 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef _FeatureClip_h_ +#define _FeatureClip_h_ + + +#include +#include + +namespace Drawing +{ + +/** Base class of all View Features in the drawing module + */ +class DrawingExport FeatureClip: public App::DocumentObjectGroup +{ + PROPERTY_HEADER(Drawing::FeatureClip); + +public: + /// Constructor + FeatureClip(void); + virtual ~FeatureClip(); + + App::PropertyFloat X; + App::PropertyFloat Y; + App::PropertyFloat Width; + App::PropertyFloat Height; + App::PropertyBool ShowFrame; + App::PropertyString ViewResult; + + /** @name methods overide Feature */ + //@{ + /// recalculate the Feature + virtual App::DocumentObjectExecReturn *execute(void); + //@} + + /// returns the type name of the ViewProvider + virtual const char* getViewProviderName(void) const { + return "DrawingGui::ViewProviderDrawingPage"; + } + +protected: + void onChanged(const App::Property* prop); +}; + + +} //namespace Drawing + + +#endif diff --git a/src/Mod/Drawing/App/FeaturePage.cpp b/src/Mod/Drawing/App/FeaturePage.cpp index 684fe28cf8..c1730ebc4a 100644 --- a/src/Mod/Drawing/App/FeaturePage.cpp +++ b/src/Mod/Drawing/App/FeaturePage.cpp @@ -37,6 +37,7 @@ #include "FeaturePage.h" #include "FeatureView.h" +#include "FeatureClip.h" using namespace Drawing; using namespace std; @@ -124,10 +125,14 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) // get through the children and collect all the views const std::vector &Grp = Group.getValues(); for (std::vector::const_iterator It= Grp.begin();It!=Grp.end();++It) { - if ((*It)->getTypeId().isDerivedFrom(Drawing::FeatureView::getClassTypeId())) { + if ( (*It)->getTypeId().isDerivedFrom(Drawing::FeatureView::getClassTypeId()) ) { Drawing::FeatureView *View = dynamic_cast(*It); ofile << View->ViewResult.getValue(); ofile << tempendl << tempendl << tempendl; + } else if ( (*It)->getTypeId().isDerivedFrom(Drawing::FeatureClip::getClassTypeId()) ) { + Drawing::FeatureClip *Clip = dynamic_cast(*It); + ofile << Clip->ViewResult.getValue(); + ofile << tempendl << tempendl << tempendl; } } } diff --git a/src/Mod/Drawing/App/Makefile.am b/src/Mod/Drawing/App/Makefile.am index 462017c0fd..098b9b786a 100644 --- a/src/Mod/Drawing/App/Makefile.am +++ b/src/Mod/Drawing/App/Makefile.am @@ -15,6 +15,8 @@ libDrawing_la_SOURCES=\ FeatureViewPart.h \ FeatureViewAnnotation.cpp \ FeatureViewAnnotation.h \ + FeatureClip.cpp \ + FeatureClip.h \ PageGroup.cpp \ PageGroup.h \ ProjectionAlgos.cpp \ diff --git a/src/Mod/Drawing/Gui/Command.cpp b/src/Mod/Drawing/Gui/Command.cpp index 2f9345b974..7ed5a4641a 100644 --- a/src/Mod/Drawing/Gui/Command.cpp +++ b/src/Mod/Drawing/Gui/Command.cpp @@ -366,9 +366,9 @@ CmdDrawingAnnotation::CmdDrawingAnnotation() // seting the sGroup = QT_TR_NOOP("Drawing"); sMenuText = QT_TR_NOOP("&Annotation"); - sToolTipText = QT_TR_NOOP("Inserts an Annotation view in the active document"); + sToolTipText = QT_TR_NOOP("Inserts an Annotation view in the active drawing"); sWhatsThis = "Drawing_Annotation"; - sStatusTip = QT_TR_NOOP("Inserts an Annotation view in the active document"); + sStatusTip = QT_TR_NOOP("Inserts an Annotation view in the active drawing"); sPixmap = "actions/drawing-annotation"; } @@ -398,6 +398,48 @@ bool CmdDrawingAnnotation::isActive(void) return (getActiveGuiDocument() ? true : false); } + +//=========================================================================== +// Drawing_Clip +//=========================================================================== + +DEF_STD_CMD_A(CmdDrawingClip); + +CmdDrawingClip::CmdDrawingClip() + : Command("Drawing_Clip") +{ + // seting the + sGroup = QT_TR_NOOP("Drawing"); + sMenuText = QT_TR_NOOP("&Clip"); + sToolTipText = QT_TR_NOOP("Inserts a clip group in the active drawing"); + sWhatsThis = "Drawing_Annotation"; + sStatusTip = QT_TR_NOOP("Inserts a clip group in the active drawing"); + sPixmap = "actions/drawing-clip"; +} + +void CmdDrawingClip::activated(int iMsg) +{ + + std::vector pages = this->getDocument()->getObjectsOfType(Drawing::FeaturePage::getClassTypeId()); + if (pages.empty()){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No page to insert"), + QObject::tr("Create a page to insert.")); + return; + } + std::string PageName = pages.front()->getNameInDocument(); + std::string FeatName = getUniqueObjectName("Clip"); + openCommand("Create Clip"); + doCommand(Doc,"App.activeDocument().addObject('Drawing::FeatureClip','%s')",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); + updateActive(); + commitCommand(); +} + +bool CmdDrawingClip::isActive(void) +{ + return (getActiveGuiDocument() ? true : false); +} + //=========================================================================== // Drawing_ExportPage //=========================================================================== @@ -495,6 +537,7 @@ void CreateDrawingCommands(void) rcCmdMgr.addCommand(new CmdDrawingOrthoViews()); rcCmdMgr.addCommand(new CmdDrawingOpenBrowserView()); rcCmdMgr.addCommand(new CmdDrawingAnnotation()); + rcCmdMgr.addCommand(new CmdDrawingClip()); rcCmdMgr.addCommand(new CmdDrawingExportPage()); rcCmdMgr.addCommand(new CmdDrawingProjectShape()); } diff --git a/src/Mod/Drawing/Gui/Resources/Drawing.qrc b/src/Mod/Drawing/Gui/Resources/Drawing.qrc index fad40eb814..bc0ae4cdfe 100644 --- a/src/Mod/Drawing/Gui/Resources/Drawing.qrc +++ b/src/Mod/Drawing/Gui/Resources/Drawing.qrc @@ -17,6 +17,7 @@ icons/actions/drawing-orthoviews.svg icons/actions/drawing-openbrowser.svg icons/actions/drawing-annotation.svg + icons/actions/drawing-clip.svg translations/Drawing_af.qm translations/Drawing_de.qm translations/Drawing_es.qm diff --git a/src/Mod/Drawing/Gui/Resources/Makefile.am b/src/Mod/Drawing/Gui/Resources/Makefile.am index e42a14b034..69b335394c 100644 --- a/src/Mod/Drawing/Gui/Resources/Makefile.am +++ b/src/Mod/Drawing/Gui/Resources/Makefile.am @@ -21,6 +21,7 @@ EXTRA_DIST = \ icons/actions/drawing-orthoviews.svg \ icons/actions/drawing-openbrowser.svg \ icons/actions/drawing-annotation.svg \ + icons/actions/drawing-clip.svg \ icons/Page.svg \ icons/Pages.svg \ icons/View.svg \ diff --git a/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg b/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg new file mode 100644 index 0000000000..dd58ec78ad --- /dev/null +++ b/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg @@ -0,0 +1,710 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/src/Mod/Drawing/Gui/Workbench.cpp b/src/Mod/Drawing/Gui/Workbench.cpp index b7bd8bbce4..e74f510e67 100644 --- a/src/Mod/Drawing/Gui/Workbench.cpp +++ b/src/Mod/Drawing/Gui/Workbench.cpp @@ -63,6 +63,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const *part << "Drawing_OrthoViews"; *part << "Drawing_OpenBrowserView"; *part << "Drawing_Annotation"; + *part << "Drawing_Clip"; *part << "Drawing_ExportPage"; return root; @@ -80,6 +81,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const *part << "Drawing_OrthoViews"; *part << "Drawing_OpenBrowserView"; *part << "Drawing_Annotation"; + *part << "Drawing_Clip"; *part << "Drawing_ExportPage"; return root; } @@ -97,6 +99,8 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const *img << "Drawing_NewPage"; *img << "Drawing_OrthoViews"; *img << "Drawing_OpenBrowserView"; + *img << "Drawing_Annotation"; + *img << "Drawing_Clip"; img = new Gui::ToolBarItem(root); img->setCommand("Views"); *img << "Drawing_NewView"; From 2edfd1428c1943fedb95895ae8bbf1a77ffe8bbb Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 00:12:30 +0200 Subject: [PATCH 196/351] fix in makeTube --- src/Mod/Part/App/TopoShape.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 22ccd16ad3..fd90af18f5 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1409,7 +1409,6 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdeg const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); BRepAdaptor_Curve path_adapt(path_edge); myPath = new BRepAdaptor_HCurve(path_adapt); - theContinuity = GeomAbs_C0; } //else if (this->_Shape.ShapeType() == TopAbs_WIRE) { // const TopoDS_Wire& path_wire = TopoDS::Wire(this->_Shape); From 23f4ce0d8f3af05dacb6a72656b42043fe21a54f Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 01:25:31 +0200 Subject: [PATCH 197/351] Mesh segmentation --- src/Mod/Mesh/App/CMakeLists.txt | 14 +- src/Mod/Mesh/App/Core/Algorithm.cpp | 37 ++-- src/Mod/Mesh/App/Core/Algorithm.h | 45 ++++- src/Mod/Mesh/App/Core/Approximation.cpp | 99 ++++----- src/Mod/Mesh/App/Core/Approximation.h | 203 +++++++++++-------- src/Mod/Mesh/App/Core/Curvature.cpp | 236 ++++++++++++++++++++++ src/Mod/Mesh/App/Core/Curvature.h | 75 +++++++ src/Mod/Mesh/App/Core/Segmentation.cpp | 228 +++++++++++++++++++++ src/Mod/Mesh/App/Core/Segmentation.h | 161 +++++++++++++++ src/Mod/Mesh/App/FeatureMeshCurvature.cpp | 50 ++--- src/Mod/Mesh/App/Makefile.am | 11 +- src/Mod/Mesh/App/Mesh.cpp | 12 +- src/Mod/Mesh/App/Mesh.h | 2 +- src/Mod/Mesh/App/MeshPy.xml | 17 +- src/Mod/Mesh/App/MeshPyImp.cpp | 51 ++++- 15 files changed, 1033 insertions(+), 208 deletions(-) create mode 100644 src/Mod/Mesh/App/Core/Curvature.cpp create mode 100644 src/Mod/Mesh/App/Core/Curvature.h create mode 100644 src/Mod/Mesh/App/Core/Segmentation.cpp create mode 100644 src/Mod/Mesh/App/Core/Segmentation.h diff --git a/src/Mod/Mesh/App/CMakeLists.txt b/src/Mod/Mesh/App/CMakeLists.txt index ee813be7bc..97e2856804 100644 --- a/src/Mod/Mesh/App/CMakeLists.txt +++ b/src/Mod/Mesh/App/CMakeLists.txt @@ -1,20 +1,26 @@ if(WIN32) - add_definitions(-DFCAppMesh -DWM4_FOUNDATION_DLL_EXPORT) + add_definitions(-DFCAppMesh -DWM4_FOUNDATION_DLL_EXPORT -DEIGEN2_SUPPORT) +else (Win32) + add_definitions(-DEIGEN2_SUPPORT) endif(WIN32) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/src/3rdParty ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_PATH} ${XERCESC_INCLUDE_DIR} + ${QT_QTCORE_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} - ${EIGEN2_INCLUDE_DIR} + ${EIGEN3_INCLUDE_DIR} ) set(Mesh_LIBS ${Boost_LIBRARIES} + ${QT_QTCORE_LIBRARY} + ${QT_QTCORE_LIBRARY_DEBUG} FreeCADBase FreeCADApp ) @@ -41,6 +47,8 @@ SET(Core_SRCS Core/Approximation.h Core/Builder.cpp Core/Builder.h + Core/Curvature.cpp + Core/Curvature.h Core/Definitions.cpp Core/Definitions.h Core/Degeneration.cpp @@ -61,6 +69,8 @@ SET(Core_SRCS Core/MeshKernel.h Core/Projection.cpp Core/Projection.h + Core/Segmentation.cpp + Core/Segmentation.h Core/SetOperations.cpp Core/SetOperations.h Core/Smoothing.cpp diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index 40d4907d4a..281fba7f7a 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -1156,7 +1156,6 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, const Base: { const MeshPointArray& p = _rclMesh.GetPoints(); const MeshFacetArray& f = _rclMesh.GetFacets(); - Base::SequencerLauncher seq("Check facets", f.size()); Base::Vector3f pt2d; unsigned long index=0; for (MeshFacetArray::_TConstIterator it = f.begin(); it != f.end(); ++it,++index) { @@ -1167,7 +1166,6 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, const Base: break; } } - seq.next(); } } @@ -1743,47 +1741,38 @@ std::set MeshRefPointToFacets::NeighbourPoints(const std::vector< return nb; } -// ermittelt alle Nachbarn zum Facet deren Schwerpunkt unterhalb der mpx. Distanz befindet. -// Facet deren VISIT-Flag gesetzt ist werden nicht beruecksichtig. -/// @todo -void MeshRefPointToFacets::Neighbours (unsigned long ulFacetInd, float fMpxDist, std::vector &rclNb) +void MeshRefPointToFacets::Neighbours (unsigned long ulFacetInd, float fMaxDist, MeshCollector& collect) const { - rclNb.clear(); + std::set visited; Base::Vector3f clCenter = _rclMesh.GetFacet(ulFacetInd).GetGravityPoint(); const MeshFacetArray& rFacets = _rclMesh.GetFacets(); - SearchNeighbours(rFacets.begin() + ulFacetInd, clCenter, fMpxDist * fMpxDist, rclNb); - - for (std::vector::iterator i = rclNb.begin(); i != rclNb.end(); i++) - (*i)->ResetFlag(MeshFacet::VISIT); + SearchNeighbours(rFacets, ulFacetInd, clCenter, fMaxDist * fMaxDist, visited, collect); } -/// @todo -void MeshRefPointToFacets::SearchNeighbours(MeshFacetArray::_TConstIterator f_it, const Base::Vector3f &rclCenter, float fMpxDist, std::vector &rclNb) +void MeshRefPointToFacets::SearchNeighbours(const MeshFacetArray& rFacets, unsigned long index, const Base::Vector3f &rclCenter, + float fMaxDist2, std::set& visited, MeshCollector& collect) const { - if (f_it->IsFlag(MeshFacet::VISIT) == true) + if (visited.find(index) != visited.end()) return; - if (Base::DistanceP2(rclCenter, _rclMesh.GetFacet(*f_it).GetGravityPoint()) > fMpxDist) + const MeshFacet& face = rFacets[index]; + if (Base::DistanceP2(rclCenter, _rclMesh.GetFacet(face).GetGravityPoint()) > fMaxDist2) return; - rclNb.push_back(f_it); - f_it->SetFlag(MeshFacet::VISIT); - - MeshPointArray::_TConstIterator p_beg = _rclMesh.GetPoints().begin(); - MeshFacetArray::_TConstIterator f_beg = _rclMesh.GetFacets().begin(); - + visited.insert(index); + collect.Append(_rclMesh, index); for (int i = 0; i < 3; i++) { - const std::set &f = (*this)[f_it->_aulPoints[i]]; + const std::set &f = (*this)[face._aulPoints[i]]; for (std::set::const_iterator j = f.begin(); j != f.end(); ++j) { - SearchNeighbours(f_beg+*j, rclCenter, fMpxDist, rclNb); + SearchNeighbours(rFacets, *j, rclCenter, fMaxDist2, visited, collect); } } } MeshFacetArray::_TConstIterator -MeshRefPointToFacets::getFacet (unsigned long index) const +MeshRefPointToFacets::GetFacet (unsigned long index) const { return _rclMesh.GetFacets().begin() + index; } diff --git a/src/Mod/Mesh/App/Core/Algorithm.h b/src/Mod/Mesh/App/Core/Algorithm.h index 9baa667e21..78a4caf5b7 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.h +++ b/src/Mod/Mesh/App/Core/Algorithm.h @@ -310,6 +310,43 @@ protected: const MeshKernel &_rclMesh; /**< The mesh kernel. */ }; +class MeshExport MeshCollector +{ +public: + MeshCollector(){} + virtual void Append(const MeshCore::MeshKernel&, unsigned long index) = 0; +}; + +class MeshExport PointCollector : public MeshCollector +{ +public: + PointCollector(std::vector& ind) : indices(ind){} + virtual void Append(const MeshCore::MeshKernel& kernel, unsigned long index) + { + unsigned long ulP1, ulP2, ulP3; + kernel.GetFacetPoints(index, ulP1, ulP2, ulP3); + indices.push_back(ulP1); + indices.push_back(ulP2); + indices.push_back(ulP3); + } + +private: + std::vector& indices; +}; + +class MeshExport FacetCollector : public MeshCollector +{ +public: + FacetCollector(std::vector& ind) : indices(ind){} + void Append(const MeshCore::MeshKernel&, unsigned long index) + { + indices.push_back(index); + } + +private: + std::vector& indices; +}; + /** * The MeshRefPointToFacets builds up a structure to have access to all facets indexing * a point. @@ -329,14 +366,14 @@ public: /// Rebuilds up data structure void Rebuild (void); const std::set& operator[] (unsigned long) const; - MeshFacetArray::_TConstIterator getFacet (unsigned long) const; + MeshFacetArray::_TConstIterator GetFacet (unsigned long) const; std::set NeighbourPoints(const std::vector& , int level) const; - void Neighbours (unsigned long ulFacetInd, float fMaxDist, std::vector &rclNb); + void Neighbours (unsigned long ulFacetInd, float fMaxDist, MeshCollector& collect) const; Base::Vector3f GetNormal(unsigned long) const; protected: - void SearchNeighbours(MeshFacetArray::_TConstIterator pFIter, const Base::Vector3f &rclCenter, - float fMaxDist, std::vector &rclNb); + void SearchNeighbours(const MeshFacetArray& rFacets, unsigned long index, const Base::Vector3f &rclCenter, + float fMaxDist, std::set &visit, MeshCollector& collect) const; protected: const MeshKernel &_rclMesh; /**< The mesh kernel. */ diff --git a/src/Mod/Mesh/App/Core/Approximation.cpp b/src/Mod/Mesh/App/Core/Approximation.cpp index ace1a796e3..15b0c522f5 100644 --- a/src/Mod/Mesh/App/Core/Approximation.cpp +++ b/src/Mod/Mesh/App/Core/Approximation.cpp @@ -37,6 +37,7 @@ #include //#define FC_USE_EIGEN +//#define FC_USE_BOOST #if defined(FC_USE_BOOST) #include #include @@ -54,25 +55,26 @@ extern "C" void LAPACK_DGESV (int const* n, int const* nrhs, #elif defined(FC_USE_EIGEN) # include #endif +# include using namespace MeshCore; -void Approximation::Convert( const Wm4::Vector3& Wm4, Base::Vector3f& pt) +void Approximation::Convert( const Wm4::Vector3& Wm4, Base::Vector3f& pt) { - pt.Set( Wm4.X(), Wm4.Y(), Wm4.Z() ); + pt.Set( (float)Wm4.X(), (float)Wm4.Y(), (float)Wm4.Z() ); } -void Approximation::Convert( const Base::Vector3f& pt, Wm4::Vector3& Wm4) +void Approximation::Convert( const Base::Vector3f& pt, Wm4::Vector3& Wm4) { Wm4.X() = pt.x; Wm4.Y() = pt.y; Wm4.Z() = pt.z; } -void Approximation::GetMgcVectorArray(std::vector< Wm4::Vector3 >& rcPts) const +void Approximation::GetMgcVectorArray(std::vector< Wm4::Vector3 >& rcPts) const { std::list< Base::Vector3f >::const_iterator It; for (It = _vPoints.begin(); It != _vPoints.end(); ++It) { - Wm4::Vector3 pt( (*It).x, (*It).y, (*It).z ); + Wm4::Vector3 pt( (*It).x, (*It).y, (*It).z ); rcPts.push_back( pt ); } } @@ -176,7 +178,7 @@ float PlaneFit::Fit() int r = lapack::syev('V','U',A,eigenval,lapack::optimal_workspace()); if (r) { } - float sigma; + float sigma = 0; #elif defined(FC_USE_EIGEN) Eigen::Matrix3d covMat = Eigen::Matrix3d::Zero(); covMat(0,0) = sxx; @@ -360,17 +362,15 @@ void PlaneFit::ProjectToPlane () // ------------------------------------------------------------------------------- -float FunctionContainer::dKoeff[]; // Koeffizienten der Quadrik - -bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance) +bool QuadraticFit::GetCurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance) { assert( _bIsFitted ); bool bResult = false; if (_bIsFitted) { - Wm4::Vector3 Dir0, Dir1; + Wm4::Vector3 Dir0, Dir1; FunctionContainer clFuncCont( _fCoeff ); bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1, Dir0, Dir1, dDistance ); @@ -382,7 +382,7 @@ bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, return bResult; } -bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1) +bool QuadraticFit::GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1) { bool bResult = false; @@ -394,12 +394,12 @@ bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, f return bResult; } -const float& QuadraticFit::GetCoeffArray() const +const double& QuadraticFit::GetCoeffArray() const { return _fCoeff[0]; } -float QuadraticFit::GetCoeff(unsigned long ulIndex) const +double QuadraticFit::GetCoeff(unsigned long ulIndex) const { assert( ulIndex >= 0 && ulIndex < 10 ); @@ -414,9 +414,9 @@ float QuadraticFit::Fit() float fResult = FLOAT_MAX; if (CountPoints() > 0) { - std::vector< Wm4::Vector3 > cPts; + std::vector< Wm4::Vector3 > cPts; GetMgcVectorArray( cPts ); - fResult = Wm4::QuadraticFit3( CountPoints(), &(cPts[0]), _fCoeff ); + fResult = Wm4::QuadraticFit3( CountPoints(), &(cPts[0]), _fCoeff ); _fLastResult = fResult; _bIsFitted = true; @@ -425,7 +425,7 @@ float QuadraticFit::Fit() return fResult; } -void QuadraticFit::CalcEigenValues(float &dLambda1, float &dLambda2, float &dLambda3, +void QuadraticFit::CalcEigenValues(double &dLambda1, double &dLambda2, double &dLambda3, Base::Vector3f &clEV1, Base::Vector3f &clEV2, Base::Vector3f &clEV3) const { assert( _bIsFitted ); @@ -451,16 +451,16 @@ void QuadraticFit::CalcEigenValues(float &dLambda1, float &dLambda2, float &dLam * */ - Wm4::Matrix3 akMat(_fCoeff[4], _fCoeff[7]/2.0f, _fCoeff[8]/2.0f, + Wm4::Matrix3 akMat(_fCoeff[4], _fCoeff[7]/2.0f, _fCoeff[8]/2.0f, _fCoeff[7]/2.0f, _fCoeff[5], _fCoeff[9]/2.0f, _fCoeff[8]/2.0f, _fCoeff[9]/2.0f, _fCoeff[6] ); - Wm4::Matrix3 rkRot, rkDiag; + Wm4::Matrix3 rkRot, rkDiag; akMat.EigenDecomposition( rkRot, rkDiag ); - Wm4::Vector3 vEigenU = rkRot.GetColumn(0); - Wm4::Vector3 vEigenV = rkRot.GetColumn(1); - Wm4::Vector3 vEigenW = rkRot.GetColumn(2); + Wm4::Vector3 vEigenU = rkRot.GetColumn(0); + Wm4::Vector3 vEigenV = rkRot.GetColumn(1); + Wm4::Vector3 vEigenW = rkRot.GetColumn(2); Convert( vEigenU, clEV1 ); Convert( vEigenV, clEV2 ); @@ -471,11 +471,11 @@ void QuadraticFit::CalcEigenValues(float &dLambda1, float &dLambda2, float &dLam dLambda3 = rkDiag[2][2]; } -void QuadraticFit::CalcZValues( float x, float y, float &dZ1, float &dZ2 ) const +void QuadraticFit::CalcZValues( double x, double y, double &dZ1, double &dZ2 ) const { assert( _bIsFitted ); - float dDisk = _fCoeff[3]*_fCoeff[3]+2*_fCoeff[3]*_fCoeff[8]*x+2*_fCoeff[3]*_fCoeff[9]*y+ + double dDisk = _fCoeff[3]*_fCoeff[3]+2*_fCoeff[3]*_fCoeff[8]*x+2*_fCoeff[3]*_fCoeff[9]*y+ _fCoeff[8]*_fCoeff[8]*x*x+2*_fCoeff[8]*x*_fCoeff[9]*y+_fCoeff[9]*_fCoeff[9]*y*y- 4*_fCoeff[6]*_fCoeff[0]-4*_fCoeff[6]*_fCoeff[1]*x-4*_fCoeff[6]*_fCoeff[2]*y- 4*_fCoeff[6]*_fCoeff[7]*x*y-4*_fCoeff[6]*_fCoeff[4]*x*x-4*_fCoeff[6]*_fCoeff[5]*y*y; @@ -494,8 +494,8 @@ void QuadraticFit::CalcZValues( float x, float y, float &dZ1, float &dZ2 ) const else dDisk = sqrt( dDisk ); - dZ1 = 0.5f * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y + dDisk ) / _fCoeff[6] ); - dZ2 = 0.5f * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y - dDisk ) / _fCoeff[6] ); + dZ1 = 0.5 * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y + dDisk ) / _fCoeff[6] ); + dZ2 = 0.5 * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y - dDisk ) / _fCoeff[6] ); } // ------------------------------------------------------------------------------- @@ -529,13 +529,13 @@ float SurfaceFit::Fit() return fResult; } -bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance ) +bool SurfaceFit::GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance ) { bool bResult = false; if (_bIsFitted) { - Wm4::Vector3 Dir0, Dir1; + Wm4::Vector3 Dir0, Dir1; FunctionContainer clFuncCont( _fCoeff ); bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1, Dir0, Dir1, dDistance ); @@ -547,7 +547,7 @@ bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, flo return bResult; } -bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1) +bool SurfaceFit::GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1) { assert( _bIsFitted ); bool bResult = false; @@ -560,18 +560,17 @@ bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, flo return bResult; } -float SurfaceFit::PolynomFit() +double SurfaceFit::PolynomFit() { if (PlaneFit::Fit() == FLOAT_MAX) return FLOAT_MAX; -#if 0 -#if defined(FC_USE_BOOST) Base::Vector3d bs(this->_vBase.x,this->_vBase.y,this->_vBase.z); Base::Vector3d ex(this->_vDirU.x,this->_vDirU.y,this->_vDirU.z); Base::Vector3d ey(this->_vDirV.x,this->_vDirV.y,this->_vDirV.z); Base::Vector3d ez(this->_vDirW.x,this->_vDirW.y,this->_vDirW.z); +#if defined(FC_USE_BOOST) ublas::matrix A(6,6); ublas::vector b(6); for (int i=0; i<6; i++) { @@ -580,6 +579,11 @@ float SurfaceFit::PolynomFit() } b(i) = 0.0; } +#else + Eigen::Matrix A = Eigen::Matrix::Zero(); + Eigen::Matrix b = Eigen::Matrix::Zero(); + Eigen::Matrix x = Eigen::Matrix::Zero(); +#endif for (std::list::const_iterator it = _vPoints.begin(); it != _vPoints.end(); it++) { Base::Vector3d clPoint(it->x,it->y,it->z); @@ -648,29 +652,34 @@ float SurfaceFit::PolynomFit() A(5,4) = A(4,5); - +#if defined(FC_USE_BOOST) namespace lapack= boost::numeric::bindings::lapack; //std::clog << A << std::endl; //std::clog << b << std::endl; - lapack::gesv(A,b); + //lapack::gesv(A,b); + ublas::vector x(6); + x = b; //std::clog << b << std::endl; +#else + // A.llt().solve(b,&x); // not sure if always positive definite + A.qr().solve(b,&x); +#endif - _fCoeff[0] = (float)(-b(5)); - _fCoeff[1] = (float)(-b(3)); - _fCoeff[2] = (float)(-b(4)); + _fCoeff[0] = (float)(-x(5)); + _fCoeff[1] = (float)(-x(3)); + _fCoeff[2] = (float)(-x(4)); _fCoeff[3] = 1.0f; - _fCoeff[4] = (float)(-b(0)); - _fCoeff[5] = (float)(-b(1)); + _fCoeff[4] = (float)(-x(0)); + _fCoeff[5] = (float)(-x(1)); _fCoeff[6] = 0.0f; - _fCoeff[7] = (float)(-b(2)); + _fCoeff[7] = (float)(-x(2)); _fCoeff[8] = 0.0f; _fCoeff[9] = 0.0f; -#endif -#endif + return 0.0f; } -float SurfaceFit::Value(float x, float y) const +double SurfaceFit::Value(double x, double y) const { float z = 0.0f; if (_bIsFitted) { diff --git a/src/Mod/Mesh/App/Core/Approximation.h b/src/Mod/Mesh/App/Core/Approximation.h index 74124f35eb..623a17daca 100644 --- a/src/Mod/Mesh/App/Core/Approximation.h +++ b/src/Mod/Mesh/App/Core/Approximation.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -34,8 +35,64 @@ #include #include -namespace MeshCore { +namespace Wm4 +{ +/** + * An implicit surface is defined by F(x,y,z) = 0. + * This polynomial surface is actually defined as z = f(x,y) = ax^2 + by^2 + cx + dy + exy + g. + * To use Wm3 routines for implicit surfaces we can write the surface also as F(x,y,z) = f(x,y) - z = 0. + * @author Werner Mayer + */ +template +class PolynomialSurface : public ImplicitSurface +{ +public: + PolynomialSurface (const Real afCoeff[6]) + { for (int i=0; i<6; i++) m_afCoeff[i] = afCoeff[i]; } + + virtual ~PolynomialSurface () {} + + // the function + virtual Real F (const Vector3& rkP) const + { + return ( m_afCoeff[0]*rkP.X()*rkP.X() + + m_afCoeff[1]*rkP.Y()*rkP.Y() + + m_afCoeff[2]*rkP.X() + + m_afCoeff[3]*rkP.Y() + + m_afCoeff[4]*rkP.X()*rkP.Y() + + m_afCoeff[5]-rkP.Z()) ; + } + + // first-order partial derivatives + virtual Real FX (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[0]*rkP.X() + m_afCoeff[2] + m_afCoeff[4]*rkP.Y()); } + virtual Real FY (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[1]*rkP.Y() + m_afCoeff[3] + m_afCoeff[4]*rkP.X()); } + virtual Real FZ (const Vector3& rkP) const + { return (Real)-1.0; } + + // second-order partial derivatives + virtual Real FXX (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[0]); } + virtual Real FXY (const Vector3& rkP) const + { return (Real)(m_afCoeff[4]); } + virtual Real FXZ (const Vector3& rkP) const + { return (Real)0.0; } + virtual Real FYY (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[1]); } + virtual Real FYZ (const Vector3& rkP) const + { return (Real)0.0; } + virtual Real FZZ (const Vector3& rkP) const + { return (Real)0.0; } + +protected: + Real m_afCoeff[6]; +}; + +} + +namespace MeshCore { /** * Abstract base class for approximation of a geometry to a given set of points. @@ -104,15 +161,15 @@ protected: /** * Converts point from Wm4::Vector3 to Base::Vector3f. */ - static void Convert( const Wm4::Vector3&, Base::Vector3f&); + static void Convert( const Wm4::Vector3&, Base::Vector3f&); /** * Converts point from Base::Vector3f to Wm4::Vector3. */ - static void Convert( const Base::Vector3f&, Wm4::Vector3&); + static void Convert( const Base::Vector3f&, Wm4::Vector3&); /** * Creates a vector of Wm4::Vector3 elements. */ - void GetMgcVectorArray( std::vector< Wm4::Vector3 >& rcPts ) const; + void GetMgcVectorArray( std::vector< Wm4::Vector3 >& rcPts ) const; protected: std::list< Base::Vector3f > _vPoints; /**< Holds the points for the fit algorithm. */ @@ -201,22 +258,22 @@ public: /** * Übertragen der Quadric-Koeffizienten * @param ulIndex Nummer des Koeffizienten (0..9) - * @return float Wert des Koeffizienten + * @return double Wert des Koeffizienten */ - float GetCoeff(unsigned long ulIndex) const; + double GetCoeff(unsigned long ulIndex) const; /** * Übertragen der Koeffizientan als Referenz * auf das interne Array - * @return const float& Referenz auf das float-Array + * @return const double& Referenz auf das double-Array */ - const float& GetCoeffArray() const; + const double& GetCoeffArray() const; /** * Aufruf des Fit-Algorithmus * @return float Qualität des Fits. */ float Fit(); - void CalcZValues(float x, float y, float &dZ1, float &dZ2) const; + void CalcZValues(double x, double y, double &dZ1, double &dZ2) const; /** * Berechnen der Krümmungswerte der Quadric in einem bestimmten Punkt. * @param x X-Koordinate @@ -229,12 +286,12 @@ public: * @param dDistance * @return bool Fehlerfreie Ausfürhung = true, ansonsten false */ - bool GetCurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance); + bool GetCurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance); - bool GetCurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfcurv1); + bool GetCurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfcurv1); /** * Aufstellen der Formanmatrix A und Berechnen der Eigenwerte. * @param dLambda1 Eigenwert 1 @@ -244,11 +301,11 @@ public: * @param clEV2 Eigenvektor 2 * @param clEV3 Eigenvektor 3 */ - void CalcEigenValues(float &dLambda1, float &dLambda2, float &dLambda3, + void CalcEigenValues(double &dLambda1, double &dLambda2, double &dLambda3, Base::Vector3f &clEV1, Base::Vector3f &clEV2, Base::Vector3f &clEV3) const; protected: - float _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ + double _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ }; // ------------------------------------------------------------------------------- @@ -275,15 +332,15 @@ public: */ virtual ~SurfaceFit(){}; - bool GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance); - bool GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfcurv1); + bool GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance); + bool GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfcurv1); float Fit(); - float Value(float x, float y) const; + double Value(double x, double y) const; protected: - float PolynomFit(); - float _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ + double PolynomFit(); + double _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ }; // ------------------------------------------------------------------------------- @@ -300,42 +357,24 @@ public: * Die MGC-Algorithmen arbeiten mit Funktionen dieses * Types */ - typedef float (*Function)(float,float,float); + typedef double (*Function)(double,double,double); /** * Der parametrisierte Konstruktor. Erwartet ein Array * mit den Quadric-Koeffizienten. * @param pKoef Zeiger auf die Quadric-Parameter - * (float [10]) + * (double [10]) */ - FunctionContainer(const float *pKoef) + FunctionContainer(const double *pKoef) { Assign( pKoef ); -/* - Function oF; - Function aoDF[3]; - Function aoD2F[6]; - - oF = &F; - aoDF[0] = &Fx; - aoDF[1] = &Fy; - aoDF[2] = &Fz; - aoD2F[0] = &Fxx; - aoD2F[1] = &Fxy; - aoD2F[2] = &Fxz; - aoD2F[3] = &Fyy; - aoD2F[4] = &Fyz; - aoD2F[5] = &Fzz; - - pImplSurf = new Wm4::QuadricSurface( oF, aoDF, aoD2F );*/ - - pImplSurf = new Wm4::QuadricSurface( dKoeff ); + pImplSurf = new Wm4::QuadricSurface( dKoeff ); } /** * Übernehmen der Quadric-Parameter * @param pKoef Zeiger auf die Quadric-Parameter - * (doube [10]) + * (double [10]) */ - void Assign( const float *pKoef ) + void Assign( const double *pKoef ) { for (long ct=0; ct < 10; ct++) dKoeff[ ct ] = pKoef[ ct ]; @@ -344,13 +383,13 @@ public: * Destruktor. Löscht die ImpicitSurface Klasse * der MGC-Bibliothek wieder */ - virtual ~FunctionContainer(){ delete pImplSurf; } + ~FunctionContainer(){ delete pImplSurf; } /** * Zugriff auf die Koeffizienten der Quadric * @param idx Index des Parameters - * @return float& Der Koeffizient + * @return double& Der Koeffizient */ - float& operator[](int idx){ return dKoeff[ idx ]; } + double& operator[](int idx){ return dKoeff[ idx ]; } /** * Redirector auf eine Methode der MGC Bibliothek. Ermittelt * die Hauptkrümmungen und ihre Richtungen im angegebenen Punkt. @@ -364,22 +403,22 @@ public: * @param dDistance Ergebnis das die Entfernung des Punktes von der Quadrik angibt. * @return bool Fehlerfreie Ausfürhung = true, ansonsten false */ - bool CurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1, - Wm4::Vector3 &rkDir0, Wm4::Vector3 &rkDir1, float &dDistance) + bool CurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1, + Wm4::Vector3 &rkDir0, Wm4::Vector3 &rkDir1, double &dDistance) { - return pImplSurf->ComputePrincipalCurvatureInfo( Wm4::Vector3(x, y, z),rfCurv0, rfCurv1, rkDir0, rkDir1 ); + return pImplSurf->ComputePrincipalCurvatureInfo( Wm4::Vector3(x, y, z),rfCurv0, rfCurv1, rkDir0, rkDir1 ); } - Base::Vector3f GetGradient( float x, float y, float z ) const + Base::Vector3f GetGradient( double x, double y, double z ) const { - Wm4::Vector3 grad = pImplSurf->GetGradient( Wm4::Vector3(x, y, z) ); + Wm4::Vector3 grad = pImplSurf->GetGradient( Wm4::Vector3(x, y, z) ); return Base::Vector3f( grad.X(), grad.Y(), grad.Z() ); } - Base::Matrix4D GetHessian( float x, float y, float z ) const + Base::Matrix4D GetHessian( double x, double y, double z ) const { - Wm4::Matrix3 hess = pImplSurf->GetHessian( Wm4::Vector3(x, y, z) ); + Wm4::Matrix3 hess = pImplSurf->GetHessian( Wm4::Vector3(x, y, z) ); Base::Matrix4D cMat; cMat.setToUnity(); cMat[0][0] = hess[0][0]; cMat[0][1] = hess[0][1]; cMat[0][2] = hess[0][2]; cMat[1][0] = hess[1][0]; cMat[1][1] = hess[1][1]; cMat[1][2] = hess[1][2]; @@ -387,23 +426,23 @@ public: return cMat; } - bool CurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1) + bool CurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1) { - float dQuot = Fz(x,y,z); - float zx = - ( Fx(x,y,z) / dQuot ); - float zy = - ( Fy(x,y,z) / dQuot ); + double dQuot = Fz(x,y,z); + double zx = - ( Fx(x,y,z) / dQuot ); + double zy = - ( Fy(x,y,z) / dQuot ); - float zxx = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zx * zx + dKoeff[8] * zx ) ) / dQuot; - float zyy = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zy * zy + dKoeff[9] * zy ) ) / dQuot; - float zxy = - ( dKoeff[6] * zx * zy + dKoeff[7] + dKoeff[8] * zy + dKoeff[9] * zx ) / dQuot; + double zxx = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zx * zx + dKoeff[8] * zx ) ) / dQuot; + double zyy = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zy * zy + dKoeff[9] * zy ) ) / dQuot; + double zxy = - ( dKoeff[6] * zx * zy + dKoeff[7] + dKoeff[8] * zy + dKoeff[9] * zx ) / dQuot; - float dNen = 1 + zx*zx + zy*zy; - float dNenSqrt = (float)sqrt( dNen ); - float K = ( zxx * zyy - zxy * zxy ) / ( dNen * dNen ); - float H = 0.5f * ( ( 1.0f+zx*zx - 2*zx*zy*zxy + (1.0f+zy*zy)*zxx ) / ( dNenSqrt * dNenSqrt * dNenSqrt ) ) ; + double dNen = 1 + zx*zx + zy*zy; + double dNenSqrt = (double)sqrt( dNen ); + double K = ( zxx * zyy - zxy * zxy ) / ( dNen * dNen ); + double H = 0.5f * ( ( 1.0f+zx*zx - 2*zx*zy*zxy + (1.0f+zy*zy)*zxx ) / ( dNenSqrt * dNenSqrt * dNenSqrt ) ) ; - float dDiscr = (float)sqrt(fabs(H*H-K)); + double dDiscr = (double)sqrt(fabs(H*H-K)); rfCurv0 = H - dDiscr; rfCurv1 = H + dDiscr; @@ -411,7 +450,7 @@ public: } //+++++++++ Quadric +++++++++++++++++++++++++++++++++++++++ - static float F ( float x, float y, float z ) + double F ( double x, double y, double z ) { return (dKoeff[0] + dKoeff[1]*x + dKoeff[2]*y + dKoeff[3]*z + dKoeff[4]*x*x + dKoeff[5]*y*y + dKoeff[6]*z*z + @@ -419,48 +458,48 @@ public: } //+++++++++ 1. derivations ++++++++++++++++++++++++++++++++ - static float Fx ( float x, float y, float z ) + double Fx ( double x, double y, double z ) { return( dKoeff[1] + 2.0f*dKoeff[4]*x + dKoeff[7]*y + dKoeff[8]*z ); } - static float Fy ( float x, float y, float z ) + double Fy ( double x, double y, double z ) { return( dKoeff[2] + 2.0f*dKoeff[5]*y + dKoeff[7]*x + dKoeff[9]*z ); } - static float Fz ( float x, float y, float z ) + double Fz ( double x, double y, double z ) { return( dKoeff[3] + 2.0f*dKoeff[6]*z + dKoeff[8]*x + dKoeff[9]*y ); } //+++++++++ 2. derivations ++++++++++++++++++++++++++++++++ - static float Fxx( float x, float y, float z ) + double Fxx( double x, double y, double z ) { return( 2.0f*dKoeff[4] ); } - static float Fxy( float x, float y, float z ) + double Fxy( double x, double y, double z ) { return( dKoeff[7] ); } - static float Fxz( float x, float y, float z ) + double Fxz( double x, double y, double z ) { return( dKoeff[8] ); } - static float Fyy( float x, float y, float z ) + double Fyy( double x, double y, double z ) { return( 2.0f*dKoeff[5] ); } - static float Fyz( float x, float y, float z ) + double Fyz( double x, double y, double z ) { return( dKoeff[9] ); } - static float Fzz( float x, float y, float z ) + double Fzz( double x, double y, double z ) { return( 2.0f*dKoeff[6] ); } protected: - static float dKoeff[ 10 ]; /**< Koeffizienten der Quadric */ - Wm4::ImplicitSurface *pImplSurf; /**< Zugriff auf die MGC-Bibliothek */ + double dKoeff[ 10 ]; /**< Koeffizienten der Quadric */ + Wm4::ImplicitSurface *pImplSurf; /**< Zugriff auf die MGC-Bibliothek */ private: /** diff --git a/src/Mod/Mesh/App/Core/Curvature.cpp b/src/Mod/Mesh/App/Core/Curvature.cpp new file mode 100644 index 0000000000..d0371da4b8 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Curvature.cpp @@ -0,0 +1,236 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "Curvature.h" +#include "Algorithm.h" +#include "Approximation.h" +#include "MeshKernel.h" +#include "Iterator.h" +#include "Tools.h" +#include +#include + +using namespace MeshCore; + +MeshCurvature::MeshCurvature(const MeshKernel& kernel) + : myKernel(kernel), myMinPoints(20), myRadius(0.5f) +{ + mySegment.resize(kernel.CountFacets()); + std::generate(mySegment.begin(), mySegment.end(), Base::iotaGen(0)); +} + +MeshCurvature::MeshCurvature(const MeshKernel& kernel, const std::vector& segm) + : myKernel(kernel), myMinPoints(20), myRadius(0.5f), mySegment(segm) +{ +} + +void MeshCurvature::ComputePerFace(bool parallel) +{ + Base::Vector3f rkDir0, rkDir1, rkPnt; + Base::Vector3f rkNormal; + myCurvature.clear(); + MeshRefPointToFacets search(myKernel); + FacetCurvature face(myKernel, search, myRadius, myMinPoints); + + if (!parallel) { + Base::SequencerLauncher seq("Curvature estimation", mySegment.size()); + for (std::vector::iterator it = mySegment.begin(); it != mySegment.end(); ++it) { + CurvatureInfo info = face.Compute(*it); + myCurvature.push_back(info); + seq.next(); + } + } + else { + QFuture future = QtConcurrent::mapped + (mySegment, boost::bind(&FacetCurvature::Compute, &face, _1)); + QFutureWatcher watcher; + watcher.setFuture(future); + watcher.waitForFinished(); + for (QFuture::const_iterator it = future.begin(); it != future.end(); ++it) { + myCurvature.push_back(*it); + } + } +} + +void MeshCurvature::ComputePerVertex() +{ + myCurvature.clear(); + + // get all points + std::vector< Wm4::Vector3 > aPnts; + aPnts.reserve(myKernel.CountPoints()); + MeshPointIterator cPIt(myKernel); + for (cPIt.Init(); cPIt.More(); cPIt.Next()) { + Wm4::Vector3 cP(cPIt->x, cPIt->y, cPIt->z); + aPnts.push_back(cP); + } + + // get all point connections + std::vector aIdx; + aIdx.reserve(3*myKernel.CountFacets()); + const MeshFacetArray& raFts = myKernel.GetFacets(); + for (MeshFacetArray::const_iterator jt = raFts.begin(); jt != raFts.end(); ++jt) { + for (int i=0; i<3; i++) { + aIdx.push_back((int)jt->_aulPoints[i]); + } + } + + // compute vertex based curvatures + Wm4::MeshCurvature meshCurv(myKernel.CountPoints(), &(aPnts[0]), myKernel.CountFacets(), &(aIdx[0])); + + // get curvature information now + const Wm4::Vector3* aMaxCurvDir = meshCurv.GetMaxDirections(); + const Wm4::Vector3* aMinCurvDir = meshCurv.GetMinDirections(); + const double* aMaxCurv = meshCurv.GetMaxCurvatures(); + const double* aMinCurv = meshCurv.GetMinCurvatures(); + + myCurvature.reserve(myKernel.CountPoints()); + for (unsigned long i=0; i& ind) : indices(ind){} + virtual void Append(const MeshCore::MeshKernel& kernel, unsigned long index) + { + unsigned long ulP1, ulP2, ulP3; + kernel.GetFacetPoints(index, ulP1, ulP2, ulP3); + indices.insert(ulP1); + indices.insert(ulP2); + indices.insert(ulP3); + } + +private: + std::set& indices; +}; +} + +// -------------------------------------------------------- + +FacetCurvature::FacetCurvature(const MeshKernel& kernel, const MeshRefPointToFacets& search, float r, unsigned long pt) + : myKernel(kernel), mySearch(search), myRadius(r), myMinPoints(pt) +{ +} + +CurvatureInfo FacetCurvature::Compute(unsigned long index) const +{ + Base::Vector3f rkDir0, rkDir1, rkPnt; + Base::Vector3f rkNormal; + + MeshGeomFacet face = myKernel.GetFacet(index); + Base::Vector3f face_gravity = face.GetGravityPoint(); + Base::Vector3f face_normal = face.GetNormal(); + std::set point_indices; + FitPointCollector collect(point_indices); + + float searchDist = myRadius; + int attempts=0; + do { + mySearch.Neighbours(index, searchDist, collect); + if (point_indices.empty()) + break; + float min_points = myMinPoints; + float use_points = point_indices.size(); + searchDist = searchDist * sqrt(min_points/use_points); + } + while((point_indices.size() < myMinPoints) && (attempts++ < 3)); + + std::vector fitPoints; + const MeshPointArray& verts = myKernel.GetPoints(); + fitPoints.reserve(point_indices.size()); + for (std::set::iterator it = point_indices.begin(); it != point_indices.end(); ++it) { + fitPoints.push_back(verts[*it] - face_gravity); + } + + float fMin, fMax; + if (fitPoints.size() >= myMinPoints) { + SurfaceFit surf_fit; + surf_fit.AddPoints(fitPoints); + surf_fit.Fit(); + rkNormal = surf_fit.GetNormal(); + double dMin, dMax, dDistance; + if (surf_fit.GetCurvatureInfo(0.0, 0.0, 0.0, dMin, dMax, rkDir1, rkDir0, dDistance)) { + fMin = (float)dMin; + fMax = (float)dMax; + } + else { + fMin = FLT_MAX; + fMax = FLT_MAX; + } + } + else { + // too few points => cannot calc any properties + fMin = FLT_MAX; + fMax = FLT_MAX; + } + + CurvatureInfo info; + if (fMin < fMax) { + info.fMaxCurvature = fMax; + info.fMinCurvature = fMin; + info.cMaxCurvDir = rkDir1; + info.cMinCurvDir = rkDir0; + } + else { + info.fMaxCurvature = fMin; + info.fMinCurvature = fMax; + info.cMaxCurvDir = rkDir0; + info.cMinCurvDir = rkDir1; + } + + // Reverse the direction of the normal vector if required + // (Z component of "local" normal vectors should be opposite in sign to the "local" view vector) + if (rkNormal * face_normal < 0.0) { + // Note: Changing the normal directions is similar to flipping over the object. + // In this case we must adjust the curvature information as well. + std::swap(info.cMaxCurvDir,info.cMinCurvDir); + std::swap(info.fMaxCurvature,info.fMinCurvature); + info.fMaxCurvature *= (-1.0); + info.fMinCurvature *= (-1.0); + } + + return info; +} diff --git a/src/Mod/Mesh/App/Core/Curvature.h b/src/Mod/Mesh/App/Core/Curvature.h new file mode 100644 index 0000000000..7c200946a4 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Curvature.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef MESHCORE_CURVATURE_H +#define MESHCORE_CURVATURE_H + +#include +#include + +namespace MeshCore { + +class MeshKernel; +class MeshRefPointToFacets; + +/** Curvature information. */ +struct MeshExport CurvatureInfo +{ + float fMaxCurvature, fMinCurvature; + Base::Vector3f cMaxCurvDir, cMinCurvDir; +}; + +class MeshExport FacetCurvature +{ +public: + FacetCurvature(const MeshKernel& kernel, const MeshRefPointToFacets& search, float, unsigned long); + CurvatureInfo Compute(unsigned long index) const; + +private: + const MeshKernel& myKernel; + const MeshRefPointToFacets& mySearch; + unsigned long myMinPoints; + float myRadius; +}; + +class MeshExport MeshCurvature +{ +public: + MeshCurvature(const MeshKernel& kernel); + MeshCurvature(const MeshKernel& kernel, const std::vector& segm); + float GetRadius() const { return myRadius; } + void SetRadius(float r) { myRadius = r; } + void ComputePerFace(bool parallel); + void ComputePerVertex(); + const std::vector& GetCurvature() const { return myCurvature; } + +private: + const MeshKernel& myKernel; + unsigned long myMinPoints; + float myRadius; + std::vector mySegment; + std::vector myCurvature; +}; + +} // MeshCore + +#endif // MESHCORE_CURVATURE_H diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp new file mode 100644 index 0000000000..4326457e56 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -0,0 +1,228 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + +#include "Segmentation.h" +#include "Algorithm.h" +#include "Approximation.h" + +using namespace MeshCore; + +void MeshSurfaceSegment::PrepareFacet(unsigned long) +{ +} + +void MeshSurfaceSegment::AddSegment(const std::vector& segm) +{ + if (segm.size() >= minFacets) { + segments.push_back(segm); + } +} + +// -------------------------------------------------------- + +MeshDistancePlanarSegment::MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol) + : MeshDistanceSurfaceSegment(mesh, minFacets, tol), fitter(new PlaneFit) +{ +} + +MeshDistancePlanarSegment::~MeshDistancePlanarSegment() +{ + delete fitter; +} + +void MeshDistancePlanarSegment::PrepareFacet(unsigned long index) +{ + fitter->Clear(); + + MeshGeomFacet triangle = kernel.GetFacet(index); + basepoint = triangle.GetGravityPoint(); + normal = triangle.GetNormal(); + fitter->AddPoint(triangle._aclPoints[0]); + fitter->AddPoint(triangle._aclPoints[1]); + fitter->AddPoint(triangle._aclPoints[2]); +} + +bool MeshDistancePlanarSegment::TestFacet (const MeshFacet& face) const +{ + if (!fitter->Done()) + fitter->Fit(); + MeshGeomFacet triangle = kernel.GetFacet(face); + for (int i=0; i<3; i++) { + if (fabs(fitter->GetDistanceToPlane(triangle._aclPoints[i])) > tolerance) + return false; + } + + fitter->AddPoint(triangle.GetGravityPoint()); + return true; +} + +// -------------------------------------------------------- + +bool MeshCurvaturePlanarSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (fabs(ci.fMinCurvature) > tolerance) + return false; + if (fabs(ci.fMaxCurvature) > tolerance) + return false; + } + + return true; +} + +bool MeshCurvatureCylindricalSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (ci.fMaxCurvature > ci.fMinCurvature) { + // convexe + if (fabs(ci.fMinCurvature) > tolerance) + return false; + float diff = ci.fMaxCurvature - curvature; + if (fabs(diff) > tolerance) + return false; + } + else { + // concave + if (fabs(ci.fMaxCurvature) > tolerance) + return false; + float diff = ci.fMinCurvature + curvature; + if (fabs(diff) > tolerance) + return false; + } + } + + return true; +} + +bool MeshCurvatureSphericalSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (ci.fMaxCurvature * ci.fMinCurvature < 0) + return false; + float diff; + diff = fabs(ci.fMinCurvature) - curvature; + if (fabs(diff) > tolerance) + return false; + diff = fabs(ci.fMaxCurvature) - curvature; + if (fabs(diff) > tolerance) + return false; + } + + return true; +} + +bool MeshCurvatureFreeformSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (fabs(ci.fMinCurvature-c2) > tolerance) + return false; + if (fabs(ci.fMaxCurvature-c1) > tolerance) + return false; + } + + return true; +} + +// -------------------------------------------------------- + +MeshSurfaceVisitor::MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices) + : indices(indices), segm(segm) +{ +} + +MeshSurfaceVisitor::~MeshSurfaceVisitor () +{ +} + +bool MeshSurfaceVisitor::AllowVisit (const MeshFacet& face, const MeshFacet&, + unsigned long, unsigned long, unsigned short) +{ + return segm.TestFacet(face); +} + +bool MeshSurfaceVisitor::Visit (const MeshFacet & face, const MeshFacet &, + unsigned long ulFInd, unsigned long) +{ + indices.push_back(ulFInd); + return true; +} + +// -------------------------------------------------------- + +void MeshSegmentAlgorithm::FindSegments(std::vector& segm) +{ + // reset VISIT flags + unsigned long startFacet; + MeshCore::MeshAlgorithm cAlgo(myKernel); + cAlgo.ResetFacetFlag(MeshCore::MeshFacet::VISIT); + + const MeshCore::MeshFacetArray& rFAry = myKernel.GetFacets(); + MeshCore::MeshFacetArray::_TConstIterator iCur = rFAry.begin(); + MeshCore::MeshFacetArray::_TConstIterator iBeg = rFAry.begin(); + MeshCore::MeshFacetArray::_TConstIterator iEnd = rFAry.end(); + + // start from the first not visited facet + cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); + std::vector resetVisited; + + for (std::vector::iterator it = segm.begin(); it != segm.end(); ++it) { + cAlgo.ResetFacetsFlag(resetVisited, MeshCore::MeshFacet::VISIT); + resetVisited.clear(); + + iCur = std::find_if(iBeg, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), + MeshCore::MeshFacet::VISIT)); + startFacet = iCur - iBeg; + while (startFacet != ULONG_MAX) { + // collect all facets of the same geometry + std::vector indices; + indices.push_back(startFacet); + (*it)->PrepareFacet(startFacet); + MeshSurfaceVisitor pv(**it, indices); + myKernel.VisitNeighbourFacets(pv, startFacet); + + // add or discard the segment + if (indices.size() == 1) { + resetVisited.push_back(startFacet); + } + else { + (*it)->AddSegment(indices); + } + + // search for the next start facet + iCur = std::find_if(iCur, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), + MeshCore::MeshFacet::VISIT)); + if (iCur < iEnd) + startFacet = iCur - iBeg; + else + startFacet = ULONG_MAX; + } + } +} diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h new file mode 100644 index 0000000000..e45ecff4c1 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -0,0 +1,161 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef MESHCORE_SEGMENTATION_H +#define MESHCORE_SEGMENTATION_H + +#include "MeshKernel.h" +#include "Curvature.h" +#include "Visitor.h" +#include + +namespace MeshCore { + +class PlaneFit; +class MeshFacet; +typedef std::vector MeshSegment; + +class MeshExport MeshSurfaceSegment +{ +public: + MeshSurfaceSegment(unsigned long minFacets) + : minFacets(minFacets) {} + virtual ~MeshSurfaceSegment() {} + virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; + virtual void PrepareFacet(unsigned long); + void AddSegment(const std::vector&); + const std::vector GetSegments() const { return segments; } + +protected: + std::vector segments; + unsigned long minFacets; +}; + +// -------------------------------------------------------- + +class MeshExport MeshDistanceSurfaceSegment : public MeshSurfaceSegment +{ +public: + MeshDistanceSurfaceSegment(const MeshKernel& mesh, unsigned long minFacets, float tol) + : MeshSurfaceSegment(minFacets), kernel(mesh), tolerance(tol) {} + +protected: + const MeshKernel& kernel; + float tolerance; +}; + +class MeshExport MeshDistancePlanarSegment : public MeshDistanceSurfaceSegment +{ +public: + MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); + virtual ~MeshDistancePlanarSegment(); + bool TestFacet (const MeshFacet &rclFacet) const; + void PrepareFacet(unsigned long); + +protected: + Base::Vector3f basepoint; + Base::Vector3f normal; + PlaneFit* fitter; +}; + +// -------------------------------------------------------- + +class MeshExport MeshCurvatureSurfaceSegment : public MeshSurfaceSegment +{ +public: + MeshCurvatureSurfaceSegment(const std::vector& ci, unsigned long minFacets, float tol) + : MeshSurfaceSegment(minFacets), info(ci), tolerance(tol) {} + +protected: + const std::vector& info; + float tolerance; +}; + +class MeshExport MeshCurvaturePlanarSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvaturePlanarSegment(const std::vector& ci, unsigned long minFacets, float tol) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol) {} + virtual bool TestFacet (const MeshFacet &rclFacet) const; +}; + +class MeshExport MeshCurvatureCylindricalSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvatureCylindricalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float curvature; +}; + +class MeshExport MeshCurvatureSphericalSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvatureSphericalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float curvature; +}; + +class MeshExport MeshCurvatureFreeformSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvatureFreeformSegment(const std::vector& ci, unsigned long minFacets, float tol, float c1, float c2) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol), c1(c1), c2(c2) {} + virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float c1, c2; +}; + +class MeshExport MeshSurfaceVisitor : public MeshFacetVisitor +{ +public: + MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices); + virtual ~MeshSurfaceVisitor (); + bool AllowVisit (const MeshFacet& face, const MeshFacet&, + unsigned long, unsigned long, unsigned short neighbourIndex); + bool Visit (const MeshFacet & face, const MeshFacet &, + unsigned long ulFInd, unsigned long); + +protected: + std::vector &indices; + const MeshSurfaceSegment& segm; +}; + +class MeshExport MeshSegmentAlgorithm +{ +public: + MeshSegmentAlgorithm(const MeshKernel& kernel) : myKernel(kernel) {} + void FindSegments(std::vector&); + +private: + const MeshKernel& myKernel; +}; + +} // MeshCore + +#endif // MESHCORE_SEGMENTATION_H diff --git a/src/Mod/Mesh/App/FeatureMeshCurvature.cpp b/src/Mod/Mesh/App/FeatureMeshCurvature.cpp index f618f2dea8..f7bc012058 100644 --- a/src/Mod/Mesh/App/FeatureMeshCurvature.cpp +++ b/src/Mod/Mesh/App/FeatureMeshCurvature.cpp @@ -29,18 +29,16 @@ #include #include #include -#include -#include #include "FeatureMeshCurvature.h" #include "MeshFeature.h" +#include "Core/Curvature.h" #include "Core/Elements.h" #include "Core/Iterator.h" using namespace Mesh; -using namespace MeshCore; PROPERTY_SOURCE(Mesh::Curvature, App::DocumentObject) @@ -68,42 +66,20 @@ App::DocumentObjectExecReturn *Curvature::execute(void) } // get all points - const MeshKernel& rMesh = pcFeat->Mesh.getValue().getKernel(); - std::vector< Wm4::Vector3 > aPnts; - aPnts.reserve(rMesh.CountPoints()); - MeshPointIterator cPIt( rMesh ); - for (cPIt.Init(); cPIt.More(); cPIt.Next()) { - Wm4::Vector3 cP(cPIt->x, cPIt->y, cPIt->z); - aPnts.push_back(cP); - } + const MeshCore::MeshKernel& rMesh = pcFeat->Mesh.getValue().getKernel(); + MeshCore::MeshCurvature meshCurv(rMesh); + meshCurv.ComputePerVertex(); + const std::vector& curv = meshCurv.GetCurvature(); - // get all point connections - std::vector aIdx; - aIdx.reserve(3*rMesh.CountFacets()); - const std::vector& raFts = rMesh.GetFacets(); - for (std::vector::const_iterator jt = raFts.begin(); jt != raFts.end(); ++jt) { - for (int i=0; i<3; i++) { - aIdx.push_back((int)jt->_aulPoints[i]); - } - } - - // compute vertex based curvatures - Wm4::MeshCurvature meshCurv(rMesh.CountPoints(), &(aPnts[0]), rMesh.CountFacets(), &(aIdx[0])); - - // get curvature information now - const Wm4::Vector3* aMaxCurvDir = meshCurv.GetMaxDirections(); - const Wm4::Vector3* aMinCurvDir = meshCurv.GetMinDirections(); - const float* aMaxCurv = meshCurv.GetMaxCurvatures(); - const float* aMinCurv = meshCurv.GetMinCurvatures(); - - std::vector values(rMesh.CountPoints()); - for (unsigned long i=0; i values; + values.reserve(curv.size()); + for (std::vector::const_iterator it = curv.begin(); it != curv.end(); ++it) { CurvatureInfo ci; - ci.cMaxCurvDir = Base::Vector3f(aMaxCurvDir[i].X(), aMaxCurvDir[i].Y(), aMaxCurvDir[i].Z()); - ci.cMinCurvDir = Base::Vector3f(aMinCurvDir[i].X(), aMinCurvDir[i].Y(), aMinCurvDir[i].Z()); - ci.fMaxCurvature = aMaxCurv[i]; - ci.fMinCurvature = aMinCurv[i]; - values[i] = ci; + ci.cMaxCurvDir = it->cMaxCurvDir; + ci.cMinCurvDir = it->cMinCurvDir; + ci.fMaxCurvature = it->fMaxCurvature; + ci.fMinCurvature = it->fMinCurvature; + values.push_back(ci); } CurvInfo.setValues(values); diff --git a/src/Mod/Mesh/App/Makefile.am b/src/Mod/Mesh/App/Makefile.am index 6309f0d912..27537e0605 100644 --- a/src/Mod/Mesh/App/Makefile.am +++ b/src/Mod/Mesh/App/Makefile.am @@ -22,6 +22,8 @@ libMesh_la_SOURCES=\ Core/Approximation.h \ Core/Builder.cpp \ Core/Builder.h \ + Core/Curvature.cpp \ + Core/Curvature.h \ Core/Definitions.cpp \ Core/Definitions.h \ Core/Degeneration.cpp \ @@ -42,6 +44,8 @@ libMesh_la_SOURCES=\ Core/MeshIO.h \ Core/Projection.cpp \ Core/Projection.h \ + Core/Segmentation.cpp \ + Core/Segmentation.h \ Core/SetOperations.cpp \ Core/SetOperations.h \ Core/Smoothing.cpp \ @@ -324,9 +328,9 @@ nobase_include_HEADERS = \ # the library search path. -libMesh_la_LDFLAGS = -L../../../Base -L../../../App $(all_libraries) $(GTS_LIBS) \ +libMesh_la_LDFLAGS = -L../../../Base -L../../../App $(QT4_CORE_LIBS) $(all_libraries) $(GTS_LIBS) \ -version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@ -libMesh_la_CPPFLAGS = -DMeshExport= +libMesh_la_CPPFLAGS = -DMeshExport= -DEIGEN2_SUPPORT libMesh_la_LIBADD = \ @BOOST_FILESYSTEM_LIB@ @BOOST_REGEX_LIB@ @BOOST_SYSTEM_LIB@ \ @@ -354,7 +358,8 @@ Mesh_la_DEPENDENCIES = libMesh.la #-------------------------------------------------------------------------------------- # set the include path found by configure -AM_CXXFLAGS = -I$(top_srcdir)/src/3rdParty -I$(top_srcdir)/src -I$(top_builddir)/src $(GTS_CFLAGS) $(all_includes) +AM_CXXFLAGS = -I$(top_srcdir)/src/3rdParty -I$(top_srcdir)/src -I$(top_builddir)/src $(GTS_CFLAGS) \ + $(all_includes) $(QT4_CORE_CXXFLAGS) includedir = @includedir@/Mod/Mesh/App libdir = $(prefix)/Mod/Mesh diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index bd7be06d0d..89f85856ad 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -1422,10 +1422,11 @@ MeshObject* MeshObject::meshFromSegment(const std::vector& indice return new MeshObject(kernel, _Mtrx); } -std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, const Segment& aSegment, float dev) const +std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, const Segment& aSegment, + float dev, unsigned long minFacets) const { std::vector segm; - unsigned long startFacet, visited; + unsigned long startFacet; if (this->_kernel.CountFacets() == 0) return segm; @@ -1445,7 +1446,7 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons MeshCore::MeshFacetArray::_TConstIterator iEnd = rFAry.end(); // start from the first not visited facet - visited = cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); + cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), MeshCore::MeshFacet::VISIT)); startFacet = iTri - iBeg; @@ -1455,7 +1456,7 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons std::vector indices; indices.push_back(startFacet); MeshCore::MeshPlaneVisitor pv(this->_kernel, startFacet, dev, indices); - visited += this->_kernel.VisitNeighbourFacets(pv, startFacet); + this->_kernel.VisitNeighbourFacets(pv, startFacet); iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), MeshCore::MeshFacet::VISIT)); @@ -1463,7 +1464,8 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons startFacet = iTri - iBeg; else startFacet = ULONG_MAX; - segm.push_back(Segment(const_cast(this), indices, false)); + if (indices.size() > minFacets) + segm.push_back(Segment(const_cast(this), indices, false)); } return segm; diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index dcd1ca19d2..3d884517fe 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -266,7 +266,7 @@ public: const Segment& getSegment(unsigned long) const; Segment& getSegment(unsigned long); MeshObject* meshFromSegment(const std::vector&) const; - std::vector getSegmentsFromType(Type, const Segment& aSegment, float dev) const; + std::vector getSegmentsFromType(Type, const Segment& aSegment, float dev, unsigned long minFacets) const; //@} /** @name Primitives */ diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index 6070d9fc1e..f29a59730a 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -370,13 +370,26 @@ an empty dictionary if there is no intersection. - + - Get all planes of the mesh as segment. + getPlanarSegments(dev,[min faces=0]) -> list +Get all planes of the mesh as segment. In the worst case each triangle can be regarded as single plane if none of its neighours is coplanar. + + + getSegmentsByCurvature(list) -> list +The argument list gives a list if tuples where it defines the preferred maximum curvature, +the preferred minumum curvature, the tolerance and the number of minimum faces for the segment. +Example: +c=(1.0, 0.0, 0.1, 500) # search for a cylinder with radius 1.0 +p=(0.0, 0.0, 0.1, 500) # search for a plane +mesh.getSegmentsByCurvature([c,p]) + + + A collection of the mesh points diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 143ff61f9d..1e32bf2f3e 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -41,6 +41,8 @@ #include "Core/Grid.h" #include "Core/MeshKernel.h" #include "Core/Triangulation.h" +#include "Core/Segmentation.h" +#include "Core/Curvature.h" using namespace Mesh; @@ -1356,15 +1358,16 @@ PyObject* MeshPy::nearestFacetOnRay(PyObject *args) } } -PyObject* MeshPy::getPlanes(PyObject *args) +PyObject* MeshPy::getPlanarSegments(PyObject *args) { float dev; - if (!PyArg_ParseTuple(args, "f",&dev)) + unsigned long minFacets=0; + if (!PyArg_ParseTuple(args, "f|k",&dev,&minFacets)) return NULL; Mesh::MeshObject* mesh = getMeshObjectPtr(); std::vector segments = mesh->getSegmentsFromType - (Mesh::MeshObject::PLANE, Mesh::Segment(mesh,false), dev); + (Mesh::MeshObject::PLANE, Mesh::Segment(mesh,false), dev, minFacets); Py::List s; for (std::vector::iterator it = segments.begin(); it != segments.end(); ++it) { @@ -1379,6 +1382,48 @@ PyObject* MeshPy::getPlanes(PyObject *args) return Py::new_reference_to(s); } +PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) +{ + PyObject* l; + if (!PyArg_ParseTuple(args, "O!",&PyList_Type,&l)) + return NULL; + + const MeshCore::MeshKernel& kernel = getMeshObjectPtr()->getKernel(); + MeshCore::MeshSegmentAlgorithm finder(kernel); + MeshCore::MeshCurvature meshCurv(kernel); + meshCurv.ComputePerVertex(); + + Py::List func(l); + std::vector segm; + //segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment(meshCurv.GetCurvature(), minFacets, dev, 4.75f)); + //segm.push_back(new MeshCore::MeshCurvaturePlanarSegment(meshCurv.GetCurvature(), minFacets, dev)); + for (Py::List::iterator it = func.begin(); it != func.end(); ++it) { + Py::Tuple t(*it); + float c1 = (float)Py::Float(t[0]); + float c2 = (float)Py::Float(t[1]); + float tol = (float)Py::Float(t[2]); + int num = (int)Py::Int(t[3]); + segm.push_back(new MeshCore::MeshCurvatureFreeformSegment(meshCurv.GetCurvature(), num, tol, c1, c2)); + } + + finder.FindSegments(segm); + + Py::List list; + for (std::vector::iterator segmIt = segm.begin(); segmIt != segm.end(); ++segmIt) { + std::vector data = (*segmIt)->GetSegments(); + delete (*segmIt); + for (std::vector::iterator it = data.begin(); it != data.end(); ++it) { + Py::List ary; + for (MeshCore::MeshSegment::const_iterator jt = it->begin(); jt != it->end(); ++jt) { + ary.append(Py::Int((int)*jt)); + } + list.append(ary); + } + } + + return Py::new_reference_to(list); +} + Py::Int MeshPy::getCountPoints(void) const { return Py::Int((long)getMeshObjectPtr()->countPoints()); From 886af5096c1c88aafbca0591efad2fa468a72364 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 01:40:05 +0200 Subject: [PATCH 198/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.cpp | 6 +++--- src/Mod/Mesh/App/Core/Segmentation.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 4326457e56..450a7a0674 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -31,7 +31,7 @@ using namespace MeshCore; -void MeshSurfaceSegment::PrepareFacet(unsigned long) +void MeshSurfaceSegment::Initialize(unsigned long) { } @@ -54,7 +54,7 @@ MeshDistancePlanarSegment::~MeshDistancePlanarSegment() delete fitter; } -void MeshDistancePlanarSegment::PrepareFacet(unsigned long index) +void MeshDistancePlanarSegment::Initialize(unsigned long index) { fitter->Clear(); @@ -204,7 +204,7 @@ void MeshSegmentAlgorithm::FindSegments(std::vector& segm) // collect all facets of the same geometry std::vector indices; indices.push_back(startFacet); - (*it)->PrepareFacet(startFacet); + (*it)->Initialize(startFacet); MeshSurfaceVisitor pv(**it, indices); myKernel.VisitNeighbourFacets(pv, startFacet); diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index e45ecff4c1..07e9fa9caf 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -41,7 +41,7 @@ public: : minFacets(minFacets) {} virtual ~MeshSurfaceSegment() {} virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; - virtual void PrepareFacet(unsigned long); + virtual void Initialize(unsigned long); void AddSegment(const std::vector&); const std::vector GetSegments() const { return segments; } @@ -69,7 +69,7 @@ public: MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); virtual ~MeshDistancePlanarSegment(); bool TestFacet (const MeshFacet &rclFacet) const; - void PrepareFacet(unsigned long); + void Initialize(unsigned long); protected: Base::Vector3f basepoint; From fc5328323964fb4f19f8e980521773a4204bd664 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 15:57:32 +0200 Subject: [PATCH 199/351] Mesh segmentation --- src/Mod/Complete/Gui/Workbench.cpp | 1 + src/Mod/Mesh/App/Core/Segmentation.h | 2 +- src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h | 6 +- src/Mod/Mesh/App/MeshPyImp.cpp | 8 +- src/Mod/Mesh/Gui/CMakeLists.txt | 4 + src/Mod/Mesh/Gui/Command.cpp | 35 +++ src/Mod/Mesh/Gui/Makefile.am | 2 + src/Mod/Mesh/Gui/Segmentation.cpp | 136 ++++++++++++ src/Mod/Mesh/Gui/Segmentation.h | 74 +++++++ src/Mod/Mesh/Gui/Segmentation.ui | 227 ++++++++++++++++++++ src/Mod/Mesh/Gui/Workbench.cpp | 3 +- 11 files changed, 488 insertions(+), 10 deletions(-) create mode 100644 src/Mod/Mesh/Gui/Segmentation.cpp create mode 100644 src/Mod/Mesh/Gui/Segmentation.h create mode 100644 src/Mod/Mesh/Gui/Segmentation.ui diff --git a/src/Mod/Complete/Gui/Workbench.cpp b/src/Mod/Complete/Gui/Workbench.cpp index d60424b2d7..9b0b0fcf0f 100644 --- a/src/Mod/Complete/Gui/Workbench.cpp +++ b/src/Mod/Complete/Gui/Workbench.cpp @@ -229,6 +229,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_ToolMesh" + << "Mesh_Segmentation" << "Mesh_VertexCurvature"; // Part **************************************************************************************************** diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index 07e9fa9caf..0219610014 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -43,7 +43,7 @@ public: virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; virtual void Initialize(unsigned long); void AddSegment(const std::vector&); - const std::vector GetSegments() const { return segments; } + const std::vector& GetSegments() const { return segments; } protected: std::vector segments; diff --git a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h index 16f6e1a576..76c51c54b1 100644 --- a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h +++ b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h @@ -21,8 +21,8 @@ ***************************************************************************/ -#ifndef FEATURE_MESH_SEGMENT_H -#define FEATURE_MESH_SEGMENT_H +#ifndef FEATURE_MESH_SEGMENTBYMESH_H +#define FEATURE_MESH_SEGMENTBYMESH_H #include @@ -63,4 +63,4 @@ public: } -#endif // FEATURE_MESH_SEGMENT_H +#endif // FEATURE_MESH_SEGMENTBYMESH_H diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 1e32bf2f3e..dd1f0e3e10 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -1395,8 +1395,6 @@ PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) Py::List func(l); std::vector segm; - //segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment(meshCurv.GetCurvature(), minFacets, dev, 4.75f)); - //segm.push_back(new MeshCore::MeshCurvaturePlanarSegment(meshCurv.GetCurvature(), minFacets, dev)); for (Py::List::iterator it = func.begin(); it != func.end(); ++it) { Py::Tuple t(*it); float c1 = (float)Py::Float(t[0]); @@ -1410,15 +1408,15 @@ PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) Py::List list; for (std::vector::iterator segmIt = segm.begin(); segmIt != segm.end(); ++segmIt) { - std::vector data = (*segmIt)->GetSegments(); - delete (*segmIt); - for (std::vector::iterator it = data.begin(); it != data.end(); ++it) { + const std::vector& data = (*segmIt)->GetSegments(); + for (std::vector::const_iterator it = data.begin(); it != data.end(); ++it) { Py::List ary; for (MeshCore::MeshSegment::const_iterator jt = it->begin(); jt != it->end(); ++jt) { ary.append(Py::Int((int)*jt)); } list.append(ary); } + delete (*segmIt); } return Py::new_reference_to(list); diff --git a/src/Mod/Mesh/Gui/CMakeLists.txt b/src/Mod/Mesh/Gui/CMakeLists.txt index 9941cac13b..ae4701a0f9 100644 --- a/src/Mod/Mesh/Gui/CMakeLists.txt +++ b/src/Mod/Mesh/Gui/CMakeLists.txt @@ -34,6 +34,7 @@ set(Dialogs_UIC_SRCS DlgSettingsMeshView.ui DlgSmoothing.ui RemoveComponents.ui + Segmentation.ui ) qt4_wrap_ui(Dialogs_UIC_HDRS ${Dialogs_UIC_SRCS}) SET(Dialogs_SRCS @@ -53,6 +54,9 @@ SET(Dialogs_SRCS RemoveComponents.ui RemoveComponents.cpp RemoveComponents.h + Segmentation.ui + Segmentation.cpp + Segmentation.h ) SOURCE_GROUP("Dialogs" FILES ${Dialogs_SRCS}) diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index 03d9714749..cc83bdaa0d 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -69,6 +69,7 @@ #include "ViewProviderMeshFaceSet.h" #include "ViewProviderCurvature.h" #include "MeshEditor.h" +#include "Segmentation.h" using namespace Mesh; @@ -1368,6 +1369,39 @@ bool CmdMeshFillInteractiveHole::isActive(void) return false; } +DEF_STD_CMD_A(CmdMeshSegmentation); + +CmdMeshSegmentation::CmdMeshSegmentation() + : Command("Mesh_Segmentation") +{ + sAppModule = "Mesh"; + sGroup = QT_TR_NOOP("Mesh"); + sMenuText = QT_TR_NOOP("Create mesh segments..."); + sToolTipText = QT_TR_NOOP("Create mesh segments"); + sWhatsThis = "Mesh_Segmentation"; + sStatusTip = QT_TR_NOOP("Create mesh segments"); +} + +void CmdMeshSegmentation::activated(int iMsg) +{ + std::vector objs = Gui::Selection().getObjectsOfType + (Mesh::Feature::getClassTypeId()); + Mesh::Feature* mesh = static_cast(objs.front()); + Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); + if (!dlg) { + dlg = new MeshGui::TaskSegmentation(mesh); + } + Gui::Control().showDialog(dlg); +} + +bool CmdMeshSegmentation::isActive(void) +{ + if (Gui::Control().activeDialog()) + return false; + return Gui::Selection().countObjectsOfType + (Mesh::Feature::getClassTypeId()) == 1; +} + void CreateMeshCommands(void) { Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); @@ -1400,4 +1434,5 @@ void CreateMeshCommands(void) rcCmdMgr.addCommand(new CmdMeshFillInteractiveHole()); rcCmdMgr.addCommand(new CmdMeshRemoveCompByHand()); rcCmdMgr.addCommand(new CmdMeshFromGeometry()); + rcCmdMgr.addCommand(new CmdMeshSegmentation()); } diff --git a/src/Mod/Mesh/Gui/Makefile.am b/src/Mod/Mesh/Gui/Makefile.am index 6b2066ff0e..46158d1e10 100644 --- a/src/Mod/Mesh/Gui/Makefile.am +++ b/src/Mod/Mesh/Gui/Makefile.am @@ -7,6 +7,7 @@ BUILT_SOURCES=\ ui_DlgSettingsMeshView.h \ ui_DlgSmoothing.h \ ui_RemoveComponents.h \ + ui_Segmentation.h \ moc_DlgEvaluateMeshImp.cpp \ moc_DlgRegularSolidImp.cpp \ moc_DlgSettingsMeshView.cpp \ @@ -127,6 +128,7 @@ EXTRA_DIST = \ DlgSettingsMeshView.ui \ DlgSmoothing.ui \ RemoveComponents.ui \ + Segmentation.ui \ Resources/Mesh.qrc \ Resources/translations/Mesh_af.qm \ Resources/translations/Mesh_af.ts \ diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp new file mode 100644 index 0000000000..962d65f2e5 --- /dev/null +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + * Copyright (c) 2012 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "Segmentation.h" +#include "ui_Segmentation.h" +#include +#include + +#include +#include +#include +#include +#include + +using namespace MeshGui; + +Segmentation::Segmentation(Mesh::Feature* mesh, QWidget* parent, Qt::WFlags fl) + : QWidget(parent, fl), myMesh(mesh) +{ + ui = new Ui_Segmentation; + ui->setupUi(this); + ui->numPln->setRange(1, INT_MAX); + ui->numPln->setValue(100); + ui->numCyl->setRange(1, INT_MAX); + ui->numCyl->setValue(100); + ui->numSph->setRange(1, INT_MAX); + ui->numSph->setValue(100); +} + +Segmentation::~Segmentation() +{ + // no need to delete child widgets, Qt does it all for us + delete ui; +} + +void Segmentation::accept() +{ + const Mesh::MeshObject* mesh = myMesh->Mesh.getValuePtr(); + // make a copy because we might smooth the mesh before + MeshCore::MeshKernel kernel = mesh->getKernel(); + + if (ui->checkBoxSmooth->isChecked()) { + MeshCore::LaplaceSmoothing smoother(kernel); + smoother.Smooth(ui->smoothSteps->value()); + } + + MeshCore::MeshSegmentAlgorithm finder(kernel); + MeshCore::MeshCurvature meshCurv(kernel); + meshCurv.ComputePerVertex(); + + std::vector segm; + if (ui->groupBoxCyl->isChecked()) { + segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment + (meshCurv.GetCurvature(), ui->numCyl->value(), ui->tolCyl->value(), ui->radCyl->value())); + } + if (ui->groupBoxSph->isChecked()) { + segm.push_back(new MeshCore::MeshCurvatureSphericalSegment + (meshCurv.GetCurvature(), ui->numSph->value(), ui->tolSph->value(), ui->radSph->value())); + } + if (ui->groupBoxPln->isChecked()) { + segm.push_back(new MeshCore::MeshCurvaturePlanarSegment + (meshCurv.GetCurvature(), ui->numPln->value(), ui->tolPln->value())); + } + finder.FindSegments(segm); + + App::Document* document = App::GetApplication().getActiveDocument(); + for (std::vector::iterator it = segm.begin(); it != segm.end(); ++it) { + const std::vector& data = (*it)->GetSegments(); + for (std::vector::const_iterator jt = data.begin(); jt != data.end(); ++jt) { + Mesh::MeshObject* segment = mesh->meshFromSegment(*jt); + Mesh::Feature* feaSegm = static_cast(document->addObject("Mesh::Feature", "Segment")); + Mesh::MeshObject* feaMesh = feaSegm->Mesh.startEditing(); + feaMesh->swap(*segment); + feaSegm->Mesh.finishEditing(); + delete segment; + } + delete (*it); + } +} + +void Segmentation::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + } + QWidget::changeEvent(e); +} + +// --------------------------------------- + +/* TRANSLATOR MeshGui::TaskRemoveComponents */ + +TaskSegmentation::TaskSegmentation(Mesh::Feature* mesh) +{ + widget = new Segmentation(mesh); + taskbox = new Gui::TaskView::TaskBox( + QPixmap(), widget->windowTitle(), false, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); +} + +TaskSegmentation::~TaskSegmentation() +{ + // automatically deleted in the sub-class +} + +bool TaskSegmentation::accept() +{ + widget->accept(); + return true; +} diff --git a/src/Mod/Mesh/Gui/Segmentation.h b/src/Mod/Mesh/Gui/Segmentation.h new file mode 100644 index 0000000000..95d1411635 --- /dev/null +++ b/src/Mod/Mesh/Gui/Segmentation.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (c) 2012 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef MESHGUI_SEGMENTATION_H +#define MESHGUI_SEGMENTATION_H + +#include +#include +#include + +// forward declarations +namespace Mesh { class Feature; } + +namespace MeshGui { +class Ui_Segmentation; + +class MeshGuiExport Segmentation : public QWidget +{ +public: + Segmentation(Mesh::Feature* mesh, QWidget* parent = 0, Qt::WFlags fl = 0); + ~Segmentation(); + void accept(); + +protected: + void changeEvent(QEvent *e); + +private: + Ui_Segmentation* ui; + Mesh::Feature* myMesh; +}; + +/** + * Embed the panel into a task dialog. + */ +class TaskSegmentation : public Gui::TaskView::TaskDialog +{ +public: + TaskSegmentation(Mesh::Feature* mesh); + ~TaskSegmentation(); + +public: + bool accept(); + + virtual QDialogButtonBox::StandardButtons getStandardButtons() const + { return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; } + +private: + Segmentation* widget; + Gui::TaskView::TaskBox* taskbox; +}; + +} + +#endif // MESHGUI_SEGMENTATION_H diff --git a/src/Mod/Mesh/Gui/Segmentation.ui b/src/Mod/Mesh/Gui/Segmentation.ui new file mode 100644 index 0000000000..129c89873c --- /dev/null +++ b/src/Mod/Mesh/Gui/Segmentation.ui @@ -0,0 +1,227 @@ + + + MeshGui::Segmentation + + + + 0 + 0 + 289 + 379 + + + + Mesh segmentation + + + + + + Smooth mesh + + + true + + + + + + + 3 + + + + + + + Plane + + + true + + + + + + Tolerance + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + Minumum number of faces + + + + + + + 100000 + + + 100 + + + + + + + + + + Cylinder + + + true + + + + + + Radius + + + + + + + 0.100000000000000 + + + 5.000000000000000 + + + + + + + Tolerance + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + Minimum number of faces + + + + + + + 100000 + + + 100 + + + + + + + + + + Sphere + + + true + + + + + + Radius + + + + + + + 0.100000000000000 + + + 5.000000000000000 + + + + + + + Tolerance + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + Minimum number of faces + + + + + + + 100000 + + + 100 + + + + + + + + + + + + checkBoxSmooth + toggled(bool) + smoothSteps + setEnabled(bool) + + + 75 + 24 + + + 188 + 19 + + + + + diff --git a/src/Mod/Mesh/Gui/Workbench.cpp b/src/Mod/Mesh/Gui/Workbench.cpp index a2a3fa0878..25b9bd6568 100644 --- a/src/Mod/Mesh/Gui/Workbench.cpp +++ b/src/Mod/Mesh/Gui/Workbench.cpp @@ -190,7 +190,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Mesh_FillupHoles" << "Mesh_FillInteractiveHole" << "Mesh_RemoveComponents" << "Mesh_RemoveCompByHand" << "Mesh_AddFacet" << "Mesh_Smoothing" << "Separator" << "Mesh_BuildRegularSolid" << boolean << "Separator" << "Mesh_PolySelect" << "Mesh_PolyCut" - << "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_PolyTrim" << "Mesh_VertexCurvature"; + << "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_PolyTrim" << "Mesh_Segmentation" + << "Mesh_VertexCurvature"; return root; } From e977602de26bf6aece5a0e96b8525f5b559f9290 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 12:57:48 -0300 Subject: [PATCH 200/351] Added 0000387 : Arch roof tool --- src/Mod/Arch/Arch.py | 1 + src/Mod/Arch/ArchRoof.py | 137 ++++ src/Mod/Arch/Arch_rc.py | 1014 +++++++++++++++++++----------- src/Mod/Arch/CMakeLists.txt | 1 + src/Mod/Arch/InitGui.py | 2 +- src/Mod/Arch/Makefile.am | 3 +- src/WindowsInstaller/ModArch.wxi | 1 + 7 files changed, 781 insertions(+), 378 deletions(-) create mode 100644 src/Mod/Arch/ArchRoof.py diff --git a/src/Mod/Arch/Arch.py b/src/Mod/Arch/Arch.py index 81bb29ffe5..fc537d85ae 100644 --- a/src/Mod/Arch/Arch.py +++ b/src/Mod/Arch/Arch.py @@ -39,3 +39,4 @@ from ArchCommands import * from ArchSectionPlane import * from ArchWindow import * from ArchAxis import * +from ArchRoof import * diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py new file mode 100644 index 0000000000..62850f243e --- /dev/null +++ b/src/Mod/Arch/ArchRoof.py @@ -0,0 +1,137 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2012 * +#* Yorik van Havre * +#* * +#* 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 * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Draft,ArchComponent +from draftlibs import fcvec +from FreeCAD import Vector +from PyQt4 import QtCore + +__title__="FreeCAD Roof" +__author__ = "Yorik van Havre" +__url__ = "http://free-cad.sourceforge.net" + +def makeRoof(baseobj,facenr=1,angle=45,name="Roof"): + '''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on a + face from an existing object. You can provide the number of the face + to build the roof on (default = 1), the angle (default=45) and a name (default + = roof).''' + obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) + _Roof(obj) + _ViewProviderRoof(obj.ViewObject) + obj.Base = baseobj + obj.Face = facenr + obj.Angle = angle + return obj + +class _CommandRoof: + "the Arch Roof command definition" + def GetResources(self): + return {'Pixmap' : 'Arch_Roof', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Roof","Roof"), + 'Accel': "R, F", + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Roof","Creates a roof object from the selected face of an object")} + + def IsActive(self): + if FreeCADGui.Selection.getSelection(): + return True + else: + return False + + def Activated(self): + sel = FreeCADGui.Selection.getSelectionEx() + if sel: + sel = sel[0] + if sel.HasSubObjects: + if "Face" in sel.SubElementNames[0]: + obj = sel.Object + idx = int(sel.SubElementNames[0][4:]) + FreeCAD.ActiveDocument.openTransaction("Create Roof") + makeRoof(obj,idx) + FreeCAD.ActiveDocument.commitTransaction() + +class _Roof(ArchComponent.Component): + "The Roof object" + def __init__(self,obj): + ArchComponent.Component.__init__(self,obj) + obj.addProperty("App::PropertyAngle","Angle","Base", + "The angle of this roof") + obj.addProperty("App::PropertyInteger","Face","Base", + "The face number of the base object used to build this roof") + obj.addProperty("App::PropertyLink","Base","Base", + "The base object this roof is built on") + self.Type = "Structure" + + def execute(self,obj): + self.createGeometry(obj) + + def onChanged(self,obj,prop): + if prop in ["Base","Face","Angle","Additions","Subtractions"]: + self.createGeometry(obj) + + def createGeometry(self,obj): + import Part,math + from draftlibs import fcgeo + pl = obj.Placement + + if obj.Base and obj.Face and obj.Angle: + if len(obj.Base.Shape.Faces) >= obj.Face: + f = obj.Base.Shape.Faces[obj.Face-1] + if len(f.Wires) == 1: + if f.Wires[0].isClosed(): + c = round(math.tan(math.radians(obj.Angle)),Draft.precision()) + norm = f.normalAt(0,0) + d = f.BoundBox.DiagonalLength + edges = fcgeo.sortEdges(f.Edges) + l = len(edges) + edges.append(edges[0]) + shps = [] + for i in range(l): + v = fcgeo.vec(fcgeo.angleBisection(edges[i],edges[i+1])) + v.normalize() + bis = v.getAngle(fcgeo.vec(edges[i])) + delta = 1/math.cos(bis) + v.multiply(delta) + n = (FreeCAD.Vector(norm)).multiply(c) + dv = v.add(n) + dv.normalize() + dv.scale(d,d,d) + shps.append(f.extrude(dv)) + c = shps.pop() + for s in shps: + c = c.common(s) + c = c.removeSplitter() + if not c.isNull(): + obj.Shape = c + if not fcgeo.isNull(pl): + obj.Placement = pl + +class _ViewProviderRoof(ArchComponent.ViewProviderComponent): + "A View Provider for the Roof object" + + def __init__(self,vobj): + ArchComponent.ViewProviderComponent.__init__(self,vobj) + + def getIcon(self): + return ":/icons/Arch_Roof_Tree.svg" + +FreeCADGui.addCommand('Arch_Roof',_CommandRoof()) diff --git a/src/Mod/Arch/Arch_rc.py b/src/Mod/Arch/Arch_rc.py index cfb5796f41..6e7f3870ae 100644 --- a/src/Mod/Arch/Arch_rc.py +++ b/src/Mod/Arch/Arch_rc.py @@ -2,8 +2,8 @@ # Resource object code # -# Created: Wed Apr 18 19:00:26 2012 -# by: The Resource Compiler for PyQt (Qt v4.7.4) +# Created: Sun May 13 20:45:11 2012 +# by: The Resource Compiler for PyQt (Qt v4.8.1) # # WARNING! All changes made in this file will be lost! @@ -6791,7 +6791,7 @@ qt_resource_data = "\ \x60\x24\x14\x71\x18\x20\xc8\x29\x21\x64\x0a\xba\x54\x4c\x69\x8a\ \x07\xa3\xfe\x50\x76\x18\x1a\x6f\x00\x69\x8d\xda\xda\x66\xb6\xba\ \xbe\xb8\xb2\x35\xc7\xf5\xc5\x7f\x01\x9a\x79\xce\xaf\ -\x00\x00\x12\x5a\ +\x00\x00\x12\x5c\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ \x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ @@ -6831,173 +6831,233 @@ qt_resource_data = "\ \x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x39\x38\ \x35\x22\x0a\x20\x20\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\ \x2e\x31\x22\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\ -\x72\x39\x37\x36\x30\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ -\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x41\x72\x63\x68\ -\x5f\x53\x69\x74\x65\x2e\x73\x76\x67\x22\x3e\x0a\x20\x20\x3c\x64\ -\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\ -\x73\x32\x39\x38\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\ -\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ -\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x22\x3e\x0a\x20\x20\x20\x20\ -\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\ -\x6f\x72\x3a\x23\x66\x66\x62\x34\x30\x30\x3b\x73\x74\x6f\x70\x2d\ -\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\ -\x70\x33\x37\x39\x36\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ -\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ -\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\ -\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\ -\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\ -\x37\x39\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\ -\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\ -\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ -\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\ -\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\ -\x38\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\ -\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x62\x34\ -\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\ -\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x36\x2d\x35\x22\ -\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\ -\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x65\x61\ -\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\ -\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x38\x2d\x38\x22\ -\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\ -\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x6c\ -\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x79\x32\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\ -\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x36\ -\x32\x2e\x36\x35\x32\x33\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x79\x31\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x31\x35\x2e\x31\x38\x34\ -\x39\x37\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\ -\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\ -\x61\x74\x72\x69\x78\x28\x31\x2e\x30\x32\x36\x35\x35\x36\x38\x2c\ -\x30\x2c\x30\x2c\x30\x2e\x39\x31\x34\x39\x30\x36\x32\x36\x2c\x2d\ -\x33\x2e\x32\x33\x36\x37\x30\x36\x2c\x2d\x31\x2e\x38\x30\x32\x37\ -\x30\x33\x32\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\ -\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\ -\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ -\x64\x69\x65\x6e\x74\x33\x38\x38\x36\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\ -\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\ -\x34\x2d\x38\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\ -\x77\x61\x79\x73\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\ -\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\ -\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\x31\x22\x3e\x0a\x20\ -\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\ -\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x62\x34\x30\x30\x3b\x73\x74\ -\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\ -\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ -\x73\x74\x6f\x70\x33\x37\x39\x36\x2d\x32\x22\x20\x2f\x3e\x0a\x20\ -\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\ -\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\x73\x74\ -\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\ -\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ -\x73\x74\x6f\x70\x33\x37\x39\x38\x2d\x32\x22\x20\x2f\x3e\x0a\x20\ +\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x33\x2e\ +\x31\x20\x72\x39\x38\x38\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\ +\x70\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x41\x72\ +\x63\x68\x5f\x53\x69\x74\x65\x5f\x54\x72\x65\x65\x2e\x73\x76\x67\ +\x22\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\ +\x69\x64\x3d\x22\x64\x65\x66\x73\x32\x39\x38\x37\x22\x3e\x0a\x20\ +\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\ +\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\ +\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\ +\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x62\x34\x30\ +\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\ +\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\ +\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x36\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x38\x22\x20\x2f\x3e\x0a\x20\ \x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\ \x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\ \x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x79\x32\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x36\x32\x2e\x36\x35\x32\ -\x33\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x32\ -\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x78\x31\x3d\x22\x31\x35\x2e\x31\x38\x34\x39\x37\x31\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\ -\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\ -\x28\x31\x2e\x30\x32\x36\x35\x35\x36\x38\x2c\x30\x2c\x30\x2c\x30\ -\x2e\x39\x31\x34\x39\x30\x36\x32\x36\x2c\x2d\x33\x2e\x32\x33\x36\ -\x37\x30\x36\x2c\x2d\x31\x2e\x38\x30\x32\x37\x30\x33\x32\x29\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\ -\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\ -\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\ -\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\ -\x33\x38\x38\x36\x2d\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\ -\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\ -\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\x31\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ -\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\ -\x73\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\ -\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\ -\x64\x76\x69\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\ -\x61\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\ -\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\ -\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\ -\x23\x36\x36\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\ -\x72\x64\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\ +\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x33\x37\x39\x34\x2d\x38\x22\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x66\x66\x62\x34\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\ +\x33\x37\x39\x36\x2d\x35\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\ +\x33\x37\x39\x38\x2d\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ +\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\ +\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\ +\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x78\x32\x3d\x22\x36\x32\x2e\x36\x35\x32\x33\x37\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x32\x33\x2e\x38\x34\ +\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\ +\x22\x31\x35\x2e\x31\x38\x34\x39\x37\x31\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\ +\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2e\x30\ +\x32\x36\x35\x35\x36\x38\x2c\x30\x2c\x30\x2c\x30\x2e\x39\x31\x34\ +\x39\x30\x36\x32\x36\x2c\x2d\x33\x2e\x32\x33\x36\x37\x30\x36\x2c\ +\x2d\x31\x2e\x38\x30\x32\x37\x30\x33\x32\x29\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\ +\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\ +\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x38\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\ +\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\x38\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\ +\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\ +\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\ +\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\ +\x34\x2d\x31\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\ +\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\ +\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\ +\x62\x34\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\ +\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x36\x2d\ +\x32\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\ +\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\ +\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\ +\x65\x61\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\ +\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x38\x2d\ +\x32\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\ +\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\ +\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\x32\x33\x2e\x38\x34\ +\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\ +\x22\x36\x32\x2e\x36\x35\x32\x33\x37\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x79\x31\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x31\x35\x2e\x31\ +\x38\x34\x39\x37\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\ +\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2e\x30\x32\x36\x35\x35\x36\ +\x38\x2c\x30\x2c\x30\x2c\x30\x2e\x39\x31\x34\x39\x30\x36\x32\x36\ +\x2c\x2d\x33\x2e\x32\x33\x36\x37\x30\x36\x2c\x2d\x31\x2e\x38\x30\ +\x32\x37\x30\x33\x32\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\ +\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\ +\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\ +\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x38\x36\x2d\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\ +\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x33\x37\x39\x34\x2d\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\ +\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x20\x2f\x3e\x0a\x20\x20\x3c\ +\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\ +\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0a\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\ +\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ +\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\x36\x22\x0a\ +\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\x61\x63\x69\ +\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\x61\x63\x69\ +\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\x61\x64\x6f\ +\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x37\x2e\x37\x37\x38\x31\ +\x37\x34\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x63\x78\x3d\x22\x32\x36\x2e\x34\x33\x31\x33\x36\x37\ \x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x70\x61\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\ -\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x70\x61\x67\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\ -\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\ -\x6d\x3d\x22\x32\x2e\x37\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ -\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x2d\x31\x32\x2e\x35\ -\x34\x31\x38\x31\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x32\x33\x2e\x38\x34\x36\x36\ -\x39\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ -\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\ -\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x73\x68\ -\x6f\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\ -\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\ -\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\ -\x69\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\ -\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\ -\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\ -\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\ -\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\ -\x38\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ -\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\ +\x63\x79\x3d\x22\x33\x30\x2e\x38\x30\x36\x36\x30\x38\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x75\x72\ +\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\x6c\x61\x79\x65\ +\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x73\x68\x6f\x77\x67\x72\x69\ +\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\ +\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x69\x64\x2d\x62\x62\ +\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\ +\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\x35\x22\x0a\x20\x20\ \x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\ -\x6f\x77\x2d\x79\x3d\x22\x31\x39\x22\x0a\x20\x20\x20\x20\x20\x69\ -\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\ -\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\ -\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\ -\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x39\x39\ -\x30\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\ -\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\ -\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\ -\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\ -\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\ -\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\ -\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\ -\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\ -\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\x63\ -\x3a\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\ -\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\ -\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\ -\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\ -\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\ -\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\x3d\ -\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x69\ -\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\ -\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\x3c\ +\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\x3d\ +\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\x78\x69\x6d\x69\ +\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\ +\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x39\x39\x30\x22\x3e\x0a\x20\ +\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\ +\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\ +\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\ +\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\ +\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\ +\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\ +\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\ +\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\ +\x3a\x74\x69\x74\x6c\x65\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\ +\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\ +\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\ +\x6c\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\ +\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\ +\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\ +\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\ +\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x62\x66\x62\x62\x62\x62\x3b\ +\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\ +\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\ +\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\ +\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\ +\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\ +\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\ +\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\ +\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\ +\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\ +\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\ +\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\ +\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\ +\x20\x35\x2e\x32\x39\x30\x30\x39\x32\x2c\x34\x31\x2e\x35\x33\x32\ +\x31\x34\x36\x20\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\ +\x35\x35\x35\x35\x36\x39\x20\x32\x39\x2e\x36\x30\x35\x38\x30\x33\ +\x2c\x35\x37\x2e\x30\x37\x34\x30\x38\x31\x20\x35\x2e\x35\x32\x32\ +\x37\x37\x38\x33\x2c\x34\x36\x2e\x39\x33\x38\x30\x33\x37\x20\x7a\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\ +\x68\x33\x39\x30\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\ +\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\ +\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\ +\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\ +\x66\x66\x66\x66\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\ +\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\ +\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ +\x68\x3a\x33\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\ +\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\ +\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\ +\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\ +\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\ +\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\ +\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\ +\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\ +\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\ +\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\ +\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x64\x3d\x22\x4d\x20\x35\x39\x2e\x35\x30\x35\x39\x38\x35\x2c\ +\x31\x32\x2e\x33\x36\x32\x38\x36\x32\x20\x35\x39\x2e\x30\x34\x30\ +\x36\x31\x32\x2c\x33\x34\x2e\x34\x33\x36\x39\x31\x35\x20\x32\x39\ +\x2e\x36\x30\x35\x38\x30\x33\x2c\x35\x36\x2e\x39\x36\x31\x34\x35\ +\x39\x20\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\x35\x35\ +\x35\x35\x36\x39\x20\x34\x30\x2e\x37\x37\x34\x37\x34\x33\x2c\x31\ +\x33\x2e\x39\x33\x39\x35\x38\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x38\x36\x39\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\ +\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ \x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\ -\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\ -\x3b\x66\x69\x6c\x6c\x3a\x23\x62\x66\x62\x62\x62\x62\x3b\x66\x69\ -\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\ -\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\ +\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x23\x39\x32\x62\x64\x38\x65\x3b\ +\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\ \x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\ \x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x3b\x73\x74\x72\ \x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\ @@ -7006,87 +7066,27 @@ qt_resource_data = "\ \x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\ \x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\ \x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\ -\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\ -\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\ -\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\ -\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\ -\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\ -\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\ -\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\ -\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x35\ -\x2e\x32\x39\x30\x30\x39\x32\x2c\x34\x31\x2e\x35\x33\x32\x31\x34\ -\x36\x20\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\x35\x35\ -\x35\x35\x36\x39\x20\x32\x39\x2e\x36\x30\x35\x38\x30\x33\x2c\x35\ -\x37\x2e\x30\x37\x34\x30\x38\x31\x20\x35\x2e\x35\x32\x32\x37\x37\ -\x38\x33\x2c\x34\x36\x2e\x39\x33\x38\x30\x33\x37\x20\x7a\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\ -\x39\x30\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\ -\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\ -\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\ -\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\x66\x66\ -\x66\x66\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\ -\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\ -\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\ -\x33\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ -\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ -\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\ -\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\ -\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\ -\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\ -\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\ -\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\ -\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\ -\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\ -\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\ -\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\ -\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\ -\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\ -\x3d\x22\x4d\x20\x35\x39\x2e\x35\x30\x35\x39\x38\x35\x2c\x31\x32\ -\x2e\x33\x36\x32\x38\x36\x32\x20\x35\x39\x2e\x30\x34\x30\x36\x31\ -\x32\x2c\x33\x34\x2e\x34\x33\x36\x39\x31\x35\x20\x32\x39\x2e\x36\ -\x30\x35\x38\x30\x33\x2c\x35\x36\x2e\x39\x36\x31\x34\x35\x39\x20\ -\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\x35\x35\x35\x35\ -\x36\x39\x20\x34\x30\x2e\x37\x37\x34\x37\x34\x33\x2c\x31\x33\x2e\ -\x39\x33\x39\x35\x38\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x38\x36\x39\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\ -\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\x75\x72\ -\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\ -\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\ -\x22\x66\x69\x6c\x6c\x3a\x23\x35\x35\x39\x61\x35\x36\x3b\x66\x69\ -\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\ -\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\ -\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x3b\x73\x74\x72\x6f\x6b\ -\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\ -\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\ -\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\ -\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x33\x36\x2e\ -\x35\x30\x32\x38\x38\x37\x2c\x36\x2e\x34\x34\x36\x38\x36\x38\x20\ -\x2d\x31\x31\x2e\x30\x38\x39\x35\x37\x32\x2c\x38\x2e\x35\x36\x35\ -\x35\x37\x33\x20\x2d\x38\x2e\x39\x39\x39\x33\x39\x2c\x31\x36\x2e\ -\x30\x32\x39\x31\x34\x33\x20\x30\x2e\x31\x37\x34\x31\x38\x31\x2c\ -\x30\x2e\x30\x37\x35\x31\x34\x20\x4c\x20\x35\x2e\x32\x30\x38\x32\ -\x33\x31\x36\x2c\x34\x31\x2e\x37\x33\x36\x30\x32\x37\x20\x32\x39\ -\x2e\x35\x33\x35\x36\x31\x37\x2c\x35\x31\x2e\x36\x35\x34\x30\x35\ -\x39\x20\x34\x30\x2e\x34\x35\x31\x30\x30\x36\x2c\x34\x30\x2e\x36\ -\x38\x34\x31\x31\x35\x20\x34\x30\x2e\x38\x35\x37\x34\x33\x31\x2c\ -\x34\x30\x2e\x32\x38\x33\x33\x38\x36\x20\x34\x30\x2e\x36\x38\x33\ -\x32\x35\x2c\x34\x30\x2e\x32\x30\x38\x32\x34\x39\x20\x34\x39\x2e\ -\x34\x32\x31\x33\x36\x37\x2c\x32\x33\x2e\x35\x37\x38\x30\x31\x34\ -\x20\x35\x39\x2e\x35\x38\x31\x39\x36\x39\x2c\x31\x32\x2e\x34\x33\ -\x32\x37\x35\x31\x20\x33\x36\x2e\x35\x30\x32\x38\x38\x37\x2c\x36\ -\x2e\x34\x34\x36\x38\x36\x38\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x37\x36\x33\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\ -\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\ -\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x33\ +\x36\x2e\x35\x30\x32\x38\x38\x37\x2c\x36\x2e\x34\x34\x36\x38\x36\ +\x38\x20\x2d\x31\x31\x2e\x30\x38\x39\x35\x37\x32\x2c\x38\x2e\x35\ +\x36\x35\x35\x37\x33\x20\x2d\x38\x2e\x39\x39\x39\x33\x39\x2c\x31\ +\x36\x2e\x30\x32\x39\x31\x34\x33\x20\x30\x2e\x31\x37\x34\x31\x38\ +\x31\x2c\x30\x2e\x30\x37\x35\x31\x34\x20\x4c\x20\x35\x2e\x32\x30\ +\x38\x32\x33\x31\x36\x2c\x34\x31\x2e\x37\x33\x36\x30\x32\x37\x20\ +\x32\x39\x2e\x35\x33\x35\x36\x31\x37\x2c\x35\x31\x2e\x36\x35\x34\ +\x30\x35\x39\x20\x34\x30\x2e\x34\x35\x31\x30\x30\x36\x2c\x34\x30\ +\x2e\x36\x38\x34\x31\x31\x35\x20\x34\x30\x2e\x38\x35\x37\x34\x33\ +\x31\x2c\x34\x30\x2e\x32\x38\x33\x33\x38\x36\x20\x34\x30\x2e\x36\ +\x38\x33\x32\x35\x2c\x34\x30\x2e\x32\x30\x38\x32\x34\x39\x20\x34\ +\x39\x2e\x34\x32\x31\x33\x36\x37\x2c\x32\x33\x2e\x35\x37\x38\x30\ +\x31\x34\x20\x35\x39\x2e\x35\x38\x31\x39\x36\x39\x2c\x31\x32\x2e\ +\x34\x33\x32\x37\x35\x31\x20\x33\x36\x2e\x35\x30\x32\x38\x38\x37\ +\x2c\x36\x2e\x34\x34\x36\x38\x36\x38\x20\x7a\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x37\x36\x33\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\ +\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\ +\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ \x00\x00\x0e\x6b\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ @@ -8358,6 +8358,133 @@ qt_resource_data = "\ \x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x6f\x64\x65\x74\x79\x70\ \x65\x73\x3d\x22\x63\x63\x63\x63\x63\x22\x20\x2f\x3e\x0a\x20\x20\ \x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ +\x00\x00\x07\xc4\ +\x00\ +\x00\x37\x1e\x78\x9c\xed\x5b\x6d\x8f\x9b\x48\x12\xfe\x3e\xbf\x82\ +\x65\xbe\x24\x3a\x83\xfb\x9d\x6e\x32\x9e\xd5\xdd\x46\xbb\x5a\xe9\ +\x4e\x27\x5d\x12\xdd\xc7\x88\x81\xb6\xcd\x0e\x06\x0b\xf0\xd8\xce\ +\xaf\xdf\x6a\xcc\x9b\x6d\x3c\x2f\xd9\x91\x6e\x77\x38\x4b\xc9\x40\ +\x55\x75\x77\xd5\xd3\x55\xd5\xd5\xd0\xdc\xfc\xb8\x5b\x25\xd6\x83\ +\xce\x8b\x38\x4b\x67\x36\x76\x91\x6d\xe9\x34\xcc\xa2\x38\x5d\xcc\ +\xec\x2f\x9f\x7f\x76\xa4\x6d\x15\x65\x90\x46\x41\x92\xa5\x7a\x66\ +\xa7\x99\xfd\xe3\xed\xd5\xcd\x0f\x8e\x63\xfd\x94\xeb\xa0\xd4\x91\ +\xb5\x8d\xcb\xa5\xf5\x6b\x7a\x5f\x84\xc1\x5a\x5b\xef\x96\x65\xb9\ +\xf6\xa7\xd3\xed\x76\xeb\xc6\x35\xd1\xcd\xf2\xc5\xf4\xbd\xe5\x38\ +\xb7\x57\x57\x37\xc5\xc3\xe2\xca\xb2\x2c\x18\x37\x2d\xfc\x28\x9c\ +\xd9\x75\x83\xf5\x26\x4f\x2a\xc1\x28\x9c\xea\x44\xaf\x74\x5a\x16\ +\x53\xec\xe2\xa9\xdd\x89\x87\x9d\x78\x68\x46\x8f\x1f\x74\x98\xad\ +\x56\x59\x5a\x54\x2d\xd3\xe2\xba\x27\x9c\x47\xf3\x56\xda\x68\xb3\ +\xa5\x95\x10\x56\x4a\x4d\x11\x99\x12\xe2\x80\x84\x53\xec\xd3\x32\ +\xd8\x39\xc7\x4d\x41\xc7\xa1\xa6\x04\x21\x34\x05\x5e\x27\xf9\x3c\ +\x29\x7f\x97\x00\x14\x17\x95\xa9\xb8\xfd\xd1\x01\xfe\x35\xfc\x6b\ +\x1b\x34\x04\xb7\xc8\x36\x79\xa8\xe7\xd0\x52\xbb\xa9\x2e\xa7\x1f\ +\x3f\x7f\x6c\x99\x0e\x72\xa3\x32\xea\x75\xd3\xa0\x7f\x34\xee\xd1\ +\x94\xa4\xc1\x4a\x17\xeb\x20\xd4\xc5\xb4\xa1\x57\xed\xb7\x71\x54\ +\x2e\x67\xb6\x60\xeb\x5d\x75\xbf\xd4\xf1\x62\x59\xf6\x08\x71\x34\ +\xb3\xc1\x42\x22\xb1\xa8\xee\x7b\x0e\x84\x0f\x02\x75\x77\x7e\xcb\ +\x41\x2e\x93\x2e\x75\xb1\x95\x2b\x29\x0f\xad\x1a\xcd\xfd\x28\x0b\ +\x8d\x2a\x33\xfb\xef\x79\xb8\xfc\xfa\x8f\x4d\x9c\x18\xff\x73\x0d\ +\x86\xb7\x20\x78\x13\xe9\x79\x61\x1a\x1c\x06\x36\x77\x30\xb2\xac\ +\x78\xc0\x05\xf4\x74\x90\xff\x92\x07\x51\x0c\x3e\x73\x90\x3b\x48\ +\x1e\x73\xa8\x90\xb8\x6e\x03\xad\x8a\x32\x5b\x37\xb2\xb5\x41\x40\ +\xa1\x42\x79\x76\x47\xce\xe6\xf3\x42\x83\xe1\xa8\x47\x2b\xca\x7d\ +\xa2\x0f\xd2\x4e\x98\x25\x59\xee\x5f\xcf\xe7\x73\x8c\xd1\x87\x8a\ +\x94\x01\x9e\x71\xb9\xf7\xf1\x07\xdb\x9a\x5e\x18\x6d\xa0\x8b\x70\ +\xee\x21\x24\xcf\xba\x38\x57\x05\xdb\x43\x5a\x4b\xde\x8e\x76\x33\ +\x3d\x36\xbb\xa6\xb6\x33\xb2\x86\x19\x59\xeb\xd0\xc4\x4e\xd3\x53\ +\x3b\x11\xe5\xde\xb8\xcb\xb1\x28\x8d\xda\x11\xbb\x59\x5d\x7f\xdd\ +\x01\x2a\x96\x6f\x51\x02\xff\xe1\x41\x89\xfd\x41\x02\x43\x38\xc0\ +\x1f\x34\x28\xf3\xcd\x38\xd5\x23\xdd\xd4\x1a\x38\x59\x1e\x2f\x62\ +\xf0\xa2\x4a\x8e\x60\x97\x56\xbf\xe3\x36\x00\x46\xcf\x36\x22\x09\ +\xeb\x30\x79\xcc\xfa\x93\x86\x54\x10\xf2\xb4\x22\xc8\xe5\xc6\xa8\ +\x5a\x91\x53\x55\x8e\x2d\xc4\x95\x24\xff\x43\x40\xd5\x70\x9f\x76\ +\xf3\xd4\xcc\x7d\x2f\x00\x8e\x1a\x39\x04\x9c\x8e\x1c\x00\x8f\x8f\ +\x1c\x80\xde\x42\x30\x4a\x00\x3c\x32\xa0\xc3\xa8\x00\x60\x23\x5f\ +\x07\x3c\xc1\x46\x0e\x80\x1c\x79\x12\x94\x48\x8c\x1e\x00\x67\xe4\ +\x95\x80\xa4\x23\x0f\x02\x81\x47\x9e\x06\x01\x00\x47\x8e\x1c\x02\ +\x36\xf2\x2c\x00\x00\x8c\x3d\x11\x0a\x6f\xe4\xf5\x20\x00\xe0\x8c\ +\x7c\x2d\xf0\xd0\x33\x1e\x52\xbd\x71\x00\xc6\xbe\x16\x78\xec\x0d\ +\x16\xc5\xeb\xa0\x2c\x75\x9e\x36\xed\xea\xdb\xcf\x79\x90\x16\xf3\ +\x2c\x5f\xcd\xec\x55\x50\xe6\xf1\xee\x1d\x72\x05\x6c\x0b\xa9\x47\ +\xe4\xc4\x41\xae\xc4\x92\x28\xcc\xf9\x84\xb8\x8c\x7b\x92\x62\x36\ +\xc1\xae\x94\x8c\x71\xce\x26\x0e\x11\x40\x45\x02\x89\x09\x96\x2e\ +\x51\x4c\x31\xef\xfd\xf1\xe3\xda\xc3\x28\x9c\xd0\x4e\xe3\xea\x65\ +\x88\xbf\xcc\xf5\x7c\x66\x5f\x7f\x82\x31\xd7\x05\xfe\x8a\x9d\x81\ +\x12\x2c\xcc\x92\x04\xa6\x64\x66\x07\xc9\x36\xd8\x17\xdf\x35\x99\ +\x9c\x90\x37\x58\xdc\x9d\x4c\x66\x2b\x58\x94\x59\x78\x6f\x10\xa8\ +\x70\xd5\x85\x85\xfd\xe3\xe7\xe7\x43\x78\x3f\xe6\x0a\xc2\x03\x47\ +\x60\x74\xe2\x60\x17\x21\xc8\x0d\xb2\xf2\x04\x22\xb0\xf4\x24\x5c\ +\x51\x8c\x19\x67\x72\x42\x5d\xe6\x09\xa4\xa4\x07\x57\x9c\x32\x45\ +\x68\xe7\x07\xcd\xbb\xa5\x4e\x91\xfa\xed\x13\x39\xd5\xe0\x4b\x1a\ +\x97\xc5\xcc\xde\x14\x3a\xff\x64\x5e\x5a\xfd\x3b\xfd\x52\xe8\xa7\ +\xdd\xa2\x7d\x07\x93\x03\xb5\x91\x3e\x98\x6b\x28\x8c\x49\xda\xb3\ +\xb6\x53\x88\xf4\x68\xb5\x4a\xfd\x77\x2f\x30\x8f\x10\x00\xbc\x47\ +\xd9\x0d\xbe\x27\x9a\xc7\x49\xe2\xdf\x25\x41\x78\xff\xa1\x28\xf3\ +\xec\x5e\xfb\x69\x96\xea\xde\xdb\x9a\xda\xba\xef\xf3\xdd\xb7\xf8\ +\x9c\xfe\x05\xa9\xe8\xb9\xfe\xa7\x5c\x20\x51\x89\x27\xd2\x55\x42\ +\x11\x89\xd8\xc5\x44\xd4\xf3\x85\x0b\xa9\x68\x20\xfb\xbf\x56\x2a\ +\x7a\x8b\x25\xf6\x2b\x24\x23\x31\xaa\x64\x84\xfe\x34\xc9\xe8\x25\ +\x91\xc8\x31\xa5\x92\x54\xe0\x0b\x8a\x89\x52\x06\x7c\x0c\xc5\x02\ +\xa2\xe6\x8a\x41\xa1\xe0\xc1\xdc\x30\xe5\x7a\x82\x70\x61\xd8\x8a\ +\x33\x21\xd1\xa5\x9a\x40\x89\xe1\x40\xec\xc7\xea\x40\xb8\xbc\x4e\ +\x28\xca\x37\x58\xe3\xbe\x7e\x5e\x35\x15\x1e\xa5\x02\x44\x27\x18\ +\x8a\x41\xe9\x61\x75\xb9\xc2\xeb\x4d\xd6\xa5\x1a\xef\x45\xf3\xf9\ +\x1a\x45\x4e\x6f\xc0\x31\x64\x16\xd6\xcb\xa4\x7f\x9d\xdc\xc2\x00\ +\x7b\x26\xa5\x30\x1b\x0e\x41\x60\xb7\x21\x99\x82\x6d\x06\xe7\x90\ +\x5c\x84\x07\x57\x8c\x62\xaa\xc4\x84\x78\xae\x62\x92\x99\x3d\x08\ +\x75\x29\x12\x8c\x8b\x61\x67\xa4\x14\x3d\xe5\x8a\x03\x65\xd5\xab\ +\x24\x16\x4a\xfe\xbf\xc2\x77\xc8\x0c\xe1\x3d\x86\x38\xa4\x7f\x9a\ +\x28\x7c\x91\xef\x8a\x71\x3f\xfb\xe2\x54\xbe\xc1\xe0\x7d\x09\x00\ +\x0c\xbf\x41\x0f\xb8\x70\x7c\xf4\x52\x7c\x0f\x2e\x1c\x03\x07\x4d\ +\xfb\x18\x9e\xb1\xbb\xa3\x45\x3b\x3c\xb3\xa9\xe7\x4a\xe5\xf1\x6e\ +\x6d\xde\x03\x91\x41\x8e\x83\xb4\xa6\xba\x42\x74\x47\x80\x0a\xd5\ +\x35\xe2\x1e\xee\xb2\xc5\xde\x50\x91\x8b\x85\xe4\xaa\xdb\xba\x2e\ +\xea\xb1\x86\x93\xd8\xff\xd2\x76\xc5\xcf\x6d\x87\x15\xde\x3b\x36\ +\xde\x9c\x16\x66\x5e\xef\x85\x8b\x31\x5e\x10\x17\x31\xe9\x79\xea\ +\xc8\x78\x81\x5c\xa8\x2e\x31\xf6\x9e\x69\xfc\xa9\xd4\xd0\x4a\x43\ +\x18\x21\x1e\xc2\xea\x50\x72\x30\x8e\x3d\x45\x26\xd5\x2e\x47\x50\ +\x04\xa5\x06\x48\x10\x0f\x4a\x0c\xc2\x27\xdc\x15\x88\x29\xc4\xe5\ +\x84\x11\x17\x88\x98\xca\xf7\x35\xc0\x37\x53\x73\x54\xb9\xba\x6a\ +\xbd\xd1\x9c\x73\x8e\x1e\x62\xbd\xbd\x6a\x11\xba\x0b\x5a\xad\xd6\ +\xc1\x42\x57\x07\x82\x01\xd7\x79\xf5\xab\x19\x77\x59\x1e\xe9\xbc\ +\x61\x89\xea\x77\xc4\xaa\xcf\x0c\x1f\x8e\xf0\x5f\x9d\x44\x28\xf4\ +\xda\xf2\xd1\x30\xbf\x58\x06\x51\xb6\xed\x96\xa1\x96\xf9\x2d\xcb\ +\x00\x19\x0a\xd5\xbd\x02\x7f\x3c\x63\x87\x10\x7e\xb4\x2a\xc1\x30\ +\xf2\xce\x98\x46\x1f\xe6\xc2\xae\x40\x12\x7c\xc6\xdc\xe4\x39\xc0\ +\xef\x24\xc1\x5e\x83\x51\xd5\x9f\x46\xa8\x58\x66\xdb\x45\x6e\xc0\ +\x29\xf3\x8d\x3e\x6d\x19\x65\xe1\xc6\x7c\x1e\xe0\x6c\x0e\x13\x5c\ +\x1f\x4a\xef\x49\x98\xb6\xce\xdd\x5d\xb6\x1b\xee\xa0\x48\x83\xf5\ +\x23\x6c\xc3\x71\x60\x9d\x5c\x16\x8f\xf0\xd3\x2c\xd2\x17\xf8\x6d\ +\xf7\x8e\x8e\x16\xda\x59\xc5\xd1\x3a\x8b\xd3\xf2\x49\xe9\x27\x04\ +\xb3\xbb\xdf\x20\x18\x1f\x53\xac\x96\x78\x44\xb5\x6d\x9c\xc2\x34\ +\x3b\x4d\x81\x41\xe4\x99\x33\xd4\x12\x4d\x59\xe2\x71\x79\x41\xa2\ +\x57\x7f\x9c\xb2\xcc\xb4\xab\x0b\xbc\x55\xb0\x8b\x57\xf1\x37\x1d\ +\x99\xe6\x75\x9c\xac\x74\x19\x44\x41\x19\x74\x31\xd1\x50\x88\x71\ +\x9c\x3a\x59\xe5\xd1\xdc\xff\xcf\xc7\x9f\xdb\x02\x2b\x0c\xfd\xff\ +\x66\xf9\x7d\x57\x02\x19\x81\xe0\x2e\xdb\x80\xda\x6d\x19\x66\xbe\ +\x1e\x08\x7d\x13\xde\x41\x79\x1b\xaf\xc0\xd3\xcd\xa7\x19\x7f\xdb\ +\xad\x12\x88\xce\x96\x71\x24\x6c\x16\x8c\xae\xd3\x43\xb7\xb9\x3e\ +\x7c\x7a\x31\xf8\xb5\x4a\x14\xae\x62\xd3\x68\xfa\xa9\x84\xea\xeb\ +\x57\x33\x48\xef\xec\x7f\xdd\x69\x5c\x26\xfa\xb6\x1a\xf3\x70\xd9\ +\x58\x31\xad\xcd\x68\xea\xb3\x9e\x95\x37\xd3\x06\x86\xea\x6e\xd1\ +\xc1\x73\x14\x2c\x2d\xc2\x49\x70\xa7\x93\x99\xfd\x4f\xc3\xb4\xce\ +\xb8\x8b\x3c\xdb\xac\x57\xe0\x1a\x75\x73\xbb\xab\xde\x97\xed\xa2\ +\xd9\x2b\x22\xaf\x55\x20\x38\x62\x1f\xcc\x4d\xef\x93\x84\xba\xaa\ +\xbc\xa6\x1a\x9c\x47\xd4\xb7\x07\x87\xf2\x21\xf7\x40\xa8\x23\xc8\ +\x87\x0d\xdd\x64\x7f\x18\xdd\xbf\xdb\x94\x65\x9f\xf6\x1b\xf8\xb9\ +\x0f\x0a\xa5\x51\x43\x05\x08\x75\x9e\x80\x6b\x94\x3e\x6b\x68\xa7\ +\xa3\x3a\x51\x00\x79\x2a\xcf\x83\xfd\xa1\xaa\x6d\xd4\x06\x44\xfe\ +\x65\x11\x48\xcf\x54\x21\x4f\x4c\x18\x77\xb9\x14\x1e\x22\x16\xa4\ +\x64\x89\x14\x57\xb0\x4f\xa0\x2e\x26\x9c\x23\x6c\x31\x05\x9b\x43\ +\xe5\x61\x6f\xa2\x5c\x05\x49\x4d\x51\x8b\x40\x3e\xc7\xb0\xad\x24\ +\x13\x02\xe9\x9c\xc3\x6a\x44\xad\x6f\xa7\x5b\xc7\x25\x51\x68\xa0\ +\x02\x09\xb3\x14\x4c\x2c\xb3\xdc\x81\x84\xf6\x10\x94\x9b\x5c\xf7\ +\x0b\xf3\x2e\xf1\x03\xf2\xc6\x49\x20\x30\x43\xf3\x3b\xda\x3e\x0d\ +\x4e\x00\x78\xd8\xbb\xb3\xd5\x55\xf1\xf7\x7f\x99\x19\x19\x40\xda\ +\x2c\xe1\x04\x33\x4a\x27\x44\x98\xe7\x7f\xb0\xa4\x58\x94\x03\xcd\ +\x83\xd5\x7e\xc2\x61\xba\xcc\x4a\xfe\xdc\x09\x91\x6a\xf0\x59\xfc\ +\x1f\x9a\x90\x9b\xe9\xe2\xf6\xea\xc6\x24\x89\xdb\xab\xdf\x01\x64\ +\xd9\x31\x4e\ \x00\x00\x13\xbe\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ @@ -9360,118 +9487,118 @@ qt_resource_data = "\ \x36\x14\x14\xa2\xad\xa3\xa0\xac\xa6\x04\x91\x00\x07\x92\x33\x46\ \x6d\xa5\x0d\x85\xb6\x3c\x63\xeb\xf9\x5a\xeb\xd5\x95\xd6\xd4\x5b\ \xcd\x6f\xa6\xf6\x72\x72\x7e\xf3\x07\x32\x2c\xc5\xda\ -\x00\x00\x06\xd7\ +\x00\x00\x06\xd6\ \x00\ -\x00\x27\xd0\x78\x9c\xed\x59\xdd\x6f\xe3\xb8\x11\x7f\xcf\x5f\xa1\ -\x7a\x5f\xee\x50\x93\xe2\xa7\x48\x2a\xb6\xef\xa1\x8b\x03\x0e\x68\ -\x5f\xda\x2b\xfa\x58\xc8\x12\x6d\xeb\x22\x4b\x86\x24\xc7\xc9\xfe\ -\xf5\x1d\xca\x92\x2c\x7f\xc4\xc9\x6d\x76\x7b\xc0\x39\x5a\x38\x12\ -\x39\x33\xe4\x70\x7e\x33\xe4\x0c\x77\xf2\xd3\xd3\x3a\xf3\x1e\x6d\ -\x59\xa5\x45\x3e\x1d\x51\x4c\x46\x9e\xcd\xe3\x22\x49\xf3\xe5\x74\ -\xf4\xef\x5f\x7f\x46\x7a\xe4\x55\x75\x94\x27\x51\x56\xe4\x76\x3a\ -\xca\x8b\xd1\x4f\xb3\xbb\xc9\x5f\x10\xf2\xfe\x56\xda\xa8\xb6\x89\ -\xb7\x4b\xeb\x95\xf7\x4b\xfe\x50\xc5\xd1\xc6\x7a\x3f\xac\xea\x7a\ -\x13\xfa\xfe\x6e\xb7\xc3\x69\xdb\x89\x8b\x72\xe9\xff\xe8\x21\x34\ -\xbb\xbb\x9b\x54\x8f\xcb\x3b\xcf\xf3\x60\xde\xbc\x0a\x93\x78\x3a\ -\x6a\x05\x36\xdb\x32\x6b\x18\x93\xd8\xb7\x99\x5d\xdb\xbc\xae\x7c\ -\x8a\xa9\x3f\x3a\xb0\xc7\x07\xf6\xd8\xcd\x9e\x3e\xda\xb8\x58\xaf\ -\x8b\xbc\x6a\x24\xf3\xea\xd3\x80\xb9\x4c\x16\x3d\xb7\xd3\x66\xc7\ -\x1b\x26\x6a\x8c\xf1\x09\xf3\x19\x43\xc0\x81\xaa\xe7\xbc\x8e\x9e\ -\xd0\xb1\x28\xe8\x78\x49\x94\x11\x42\x7c\xa0\x1d\x38\xdf\xc6\x15\ -\x56\x60\xd0\x0d\xfc\x7a\xf6\xae\x03\x57\xc5\xb6\x8c\xed\x02\xe4\ -\x2c\xce\x6d\xed\x7f\xfe\xf5\x73\x4f\x44\x04\x27\x75\x32\x18\xa6\ -\xb3\xe7\xd1\xac\x47\x46\xce\xa3\xb5\xad\x36\x51\x6c\x2b\xbf\xeb\ -\x6f\xe4\x77\x69\x52\xaf\xa6\xa3\x40\x6c\x9e\x9a\xf6\xca\xa6\xcb\ -\x55\x3d\xe8\x48\x93\xe9\x08\x74\x66\x9a\x06\x4d\x7b\xe0\x12\x74\ -\xcf\xd0\x0e\x17\xf6\x14\x82\x85\xc6\xd4\x2b\x8d\x0a\x48\xc3\xd2\ -\xe9\x1d\x26\x45\xec\x14\x99\x8e\x36\xa5\x5d\xd8\x12\x1c\xca\x56\ -\x28\x2a\xe3\x15\x76\x66\x99\x01\xef\x24\xb1\x8b\xca\xc9\xec\x67\ -\x76\x2d\x98\x5a\x37\x34\xa0\xf6\x93\x6d\x60\xb2\x8d\x8d\x1d\xd0\ -\x7b\xee\xc1\x2c\xf5\xb3\xb3\xc4\x31\x2b\xdf\x9b\xcb\x3b\x52\x78\ -\xf3\xdf\x27\xd0\xd6\x0b\x3d\xce\xe0\x0f\xbd\xc8\xf1\xbc\xe7\xa0\ -\x80\x1d\xbc\xc8\x45\x9e\x2f\xce\x5e\x57\x86\x69\x35\x40\x45\x99\ -\x2e\x53\x30\x50\xc3\xc7\x28\xe6\xcd\x73\x2c\x03\x8b\x1e\xac\x8d\ -\x69\x26\x46\x9e\xff\x86\xd5\x9f\x08\xf2\x80\xb1\xd7\x15\x21\x58\ -\xba\x45\xb5\x8a\x9c\xaa\x72\xbc\x42\xda\x70\xca\x77\x19\xaa\x35\ -\xf7\xe9\x30\xaf\x21\xf7\xb5\x06\x40\xe6\xc6\x4d\x20\xf9\x8d\x1b\ -\x40\xc9\x1b\x37\x80\x51\xb7\x6d\x00\xc5\x2e\xe8\x70\x53\x06\x10\ -\x37\x7e\x0e\xa8\x40\xdc\xb8\x01\xf4\x8d\x6f\x82\x9a\x04\x37\x6f\ -\x00\x74\xe3\x99\x80\xe6\x7f\xb6\x20\x98\xf8\xae\x38\x6a\xbe\x7a\ -\x01\x57\x5c\x25\x8f\xa9\xdd\x1d\x2a\xa8\x79\x54\xd9\x76\xe4\x4d\ -\xb4\x84\xaa\x38\x2b\xca\xe9\xe8\xd3\xa2\x79\x5a\xc2\xbc\x28\x13\ -\x5b\x76\xa4\xa0\x79\x8e\x48\x05\x54\x8e\x69\xfd\xbc\xbf\x07\xb8\ -\x3b\x31\x22\x8c\xda\xd3\xc9\x65\x7a\xb5\x8a\x92\x62\x37\x1d\xb1\ -\x53\xe2\x97\xa2\x58\x3b\x29\x26\x38\x09\x94\x09\x4e\xe9\x31\x98\ -\x08\x71\x26\x30\x64\xf3\xca\x9c\x51\x61\x46\xc4\x24\xc7\x84\x52\ -\x2a\xcf\xa8\xdb\x12\x2a\xcc\x1a\x65\xd1\xb3\x85\x75\x35\xaf\xce\ -\xc8\xd5\xaa\xd8\x2d\x4b\x67\x9f\xba\xdc\xda\x53\x49\x28\x53\xb7\ -\xee\x9a\x01\x6d\xf3\xb4\x86\x52\xbe\x2d\x85\x07\x1c\x4e\x16\xcd\ -\xe7\xc5\xd3\xe5\x01\xaa\x3c\xda\x5c\x21\x3b\x0a\xda\x44\xf5\xaa\ -\xba\x42\xcf\x8b\xc4\xbe\x40\xef\x87\x47\x36\x59\x5a\xb4\x4e\x93\ -\x4d\x91\xe6\xf5\xab\xdc\xaf\x30\x16\xf3\xdf\x20\x5a\xae\x29\xd6\ -\x72\x5c\x51\x6d\x97\xe6\x80\x34\x6a\xaf\x15\x28\xd3\x67\xfe\xd0\ -\x72\x74\x17\x0d\x4a\xea\x17\x38\x5c\x74\xbc\x40\x72\x9e\x78\xe6\ -\x0d\x2d\x6d\x1d\x3d\xa5\xeb\xf4\x8b\x4d\x9c\x78\x1b\x2a\x6b\x5b\ -\x47\x49\x54\x47\x87\xb0\xe8\x7a\xa0\xc0\xa6\xdd\xe5\x42\x99\x2c\ -\xc2\x7f\x7e\xfe\x79\xd6\xc6\xe1\x24\x8e\xc3\xff\x14\xe5\x43\x17\ -\x96\x9e\xe7\x18\xa2\x79\xb1\x05\xb5\x47\xb3\xbe\x7b\x92\xc4\xe1\ -\xa2\x28\xd7\x51\x3d\x4b\xd7\xe0\xec\xee\x8a\xe7\xaf\x4f\xeb\x0c\ -\x02\xb4\x27\x1c\x31\xbb\xb0\x3e\x0c\xba\x1f\xb6\xb4\xfb\x0b\x9f\ -\x8b\xb7\x5e\x49\xbc\x4e\x9d\x90\xff\xaf\x3a\xcd\xb2\x5f\xdc\x24\ -\xfd\x2e\xd8\x0f\x9a\xd6\x99\x9d\x35\x73\xee\x3f\xbb\x55\xf8\xed\ -\x32\xda\x45\xfa\x83\x55\x4e\xfc\xce\x0c\x4d\x6b\x79\x30\xcf\x51\ -\xb0\xf4\x16\xce\xa2\xb9\xcd\xa6\xa3\xbf\x3b\xa2\x77\x46\x5d\x96\ -\xc5\x76\xb3\x06\xd7\x68\xc5\x7b\xb3\x82\xcb\xf4\x5b\x5b\xfd\x9c\ -\x01\xbd\xd9\x6a\xc2\x4f\xa4\x79\xee\x17\xb0\xa8\xf0\x53\x14\x09\ -\xd1\x36\x50\xbb\x9f\x84\x74\xdf\x2c\xb7\x99\x0d\xed\xa3\x05\xbf\ -\x4b\xee\xab\xba\x2c\x1e\x6c\x2f\xbc\x6f\xee\x1d\x2e\xe4\x58\x88\ -\x40\x30\x46\x68\xd7\x9f\xa5\xb9\x05\xed\xc2\xf9\xb6\xae\x87\x7d\ -\xbf\x41\x1c\x84\xa0\x70\xde\x0d\x08\xc1\x51\xdb\x32\x03\xd7\xa9\ -\x43\xd1\xf5\x1d\xf4\x68\x3b\x92\x08\xb6\xb2\xb2\x8c\x9e\xc3\xbc\ -\xc8\xed\xb0\xb7\x58\x2c\x2a\x5b\x87\xe4\x7e\x1d\x95\x0f\xb6\xdc\ -\xd3\x1f\xd3\x2a\x9d\xa7\x99\x1b\xa2\xf9\xcc\xec\x7d\x92\x56\x1b\ -\x30\x4f\x98\xe6\x4e\x8d\xfb\xe2\xd1\x96\x8b\xac\xd8\xf5\x74\x9b\ -\x47\xf0\x42\xf3\x28\x7e\x58\x36\xfa\x85\x51\x0c\xbb\xd1\x36\x8b\ -\x6a\x7b\x38\x44\x00\x22\x67\x56\xa6\x05\x41\x1c\x09\x44\x90\xee\ -\x89\x5d\xec\x49\x6c\x78\xc0\xd9\xe1\x0e\xa4\x0b\x39\xca\xb0\xd4\ -\x52\x90\x83\xc8\x93\xbb\x93\xc2\xc6\x28\x33\x48\x95\x20\xc8\xa4\ -\xc1\x01\xc4\xf0\xa1\x82\xa8\xcb\x28\xaf\x9c\x4f\x43\x04\x45\x75\ -\x99\x3e\xfd\x40\xb0\x92\x4a\x51\x21\xc7\x88\xe0\x40\x32\xa9\x03\ -\x6a\xc6\x64\x4c\xe1\x47\x7e\x3c\x1c\xd6\x6f\xf4\x82\xc5\x42\x2d\ -\x58\xf4\x5e\x2f\x20\x46\xc3\xca\x95\xfe\xf6\x88\x7f\x47\x74\xaf\ -\xb9\xec\xd0\xc3\x2e\x7a\xc1\x29\xfa\x70\x64\xf2\x80\x99\x40\x5d\ -\x42\x5f\x68\x26\x8d\x18\xa2\xcf\x30\x87\x23\x94\x99\x23\xf4\x99\ -\xc6\x5a\x6b\x00\xf7\x2a\xfc\x86\x2b\x2e\x29\x01\xcc\x31\x17\x9a\ -\x7f\xc0\xff\x47\xc0\x3f\xb8\xe9\xfc\x4a\x07\xd0\xd8\x04\x80\xe3\ -\x99\x03\x04\x01\xf8\xc0\x37\x70\x00\x97\x55\xbc\xc9\x01\x8c\x91\ -\xf2\x9d\x0e\xf0\x1e\xdc\xff\x40\x84\xaf\x1f\x2c\x3d\x06\x00\xfb\ -\x3f\x3c\x2a\x20\x67\xa6\x92\xa9\x31\x35\x98\x19\x41\x89\xf6\xb8\ -\xc2\x44\x69\xaa\xc7\x4c\x61\xf7\x66\xc6\x63\x12\x13\xc2\x8c\xe1\ -\x63\xae\x31\xd5\x34\x90\xca\x63\x98\x06\x01\xe7\x06\xf8\x60\x7b\ -\x37\x1c\x4e\x89\x8b\xc3\x7d\x79\xe9\xb8\x91\xee\x77\x5e\xad\xb8\ -\xac\xd0\x65\x29\x90\x19\xc6\xee\xf9\xc0\xfe\x3b\x61\xcf\x01\x22\ -\x40\x4b\x89\x31\x04\xa8\x90\x42\x31\xe5\x05\x0c\x93\x80\x68\x00\ -\x90\x07\xd8\x08\x26\x84\xf6\x84\xc1\x46\xcb\x40\x8c\x85\x82\xc8\ -\x84\x02\x2a\xf0\xc0\x33\xa8\xd0\x46\x2b\xe7\x0f\x90\x03\x48\x29\ -\x2f\x0e\x77\x0d\xfb\x77\x22\xbf\xc7\xfa\x08\xbb\x37\x40\xf9\x62\ -\x0e\xd7\x20\x7a\x0e\x65\xf7\x05\x39\x09\xe1\x44\x72\x97\x5b\xee\ -\x1f\x79\xcd\x17\x8e\xa1\x18\x9a\x7d\xed\xec\xe4\xb6\x39\xad\xc7\ -\x02\xca\x60\x30\x23\xe7\x1e\xe5\x98\x13\x45\x8d\x18\x23\x0a\xd9\ -\x0f\xa5\x46\x79\x02\x83\x81\xe1\xdf\x18\x09\x4c\xb8\x94\xc6\x78\ -\x88\x81\x1e\x5c\x1b\xc3\xc6\x48\xe1\x40\x18\xc2\xb8\x87\x34\x86\ -\xca\x16\x1a\x63\x00\x25\x30\x01\x40\x41\x9b\x6c\x4a\x48\x3d\x0e\ -\x5c\x90\xd2\x40\x9c\x20\xe1\xec\xc9\xb5\x30\xaf\x63\x10\x7f\x9c\ -\xbd\xff\xaf\xb3\x97\xbf\xf3\xec\xa5\x6e\xbb\xd6\x4a\x0f\x8f\x5e\ -\x70\x2c\x2d\x14\x1d\xfc\x07\xde\x77\xcf\xbd\xbe\x5f\x01\xf6\x67\ -\xc7\x1f\x89\x53\x0f\xf8\x9d\xc5\x57\x00\xec\x81\x36\xf2\x28\xfb\ -\x32\x00\xaa\x61\x8a\x5c\xcf\xbe\xbe\x69\xf5\xf5\xe1\x02\x5f\xef\ -\x02\xe8\xac\x06\xfb\x9d\x4e\x20\x21\x31\x13\xc2\x48\x3a\x74\x02\ -\x38\xd7\xe1\x38\x10\x83\xc2\xec\xeb\x9d\xe0\x23\x0d\xfb\xa6\x69\ -\x18\x64\x4b\x0a\xe0\x62\x63\xc8\x0b\x04\xd5\x8a\x79\x92\x62\x67\ -\x7b\xc5\xc6\x54\x63\x48\xbb\xa5\xe1\x7d\xd6\x20\x9b\xec\x0a\x52\ -\x6b\x46\x3d\x1a\xe0\x40\x09\xce\x99\xcb\xb6\x21\xd9\x56\x17\xc6\ -\x7a\x39\x03\x7b\x73\xfe\x35\xf1\x97\xb3\xbb\x89\xbb\x8e\x9c\xdd\ -\xfd\x0f\x63\x62\xcf\x20\ +\x00\x27\xf1\x78\x9c\xed\x59\xdd\x6f\xdb\x36\x10\x7f\xcf\x5f\xa1\ +\xa9\x2f\x1b\x66\x51\xfc\x14\x49\xc5\xce\x30\xac\x28\x30\x60\x7b\ +\xd9\x3a\xec\xb1\x90\x25\xda\xd6\x22\x4b\x86\x24\xc7\x4e\xff\xfa\ +\x1d\x65\x49\x96\x1d\xc7\xc9\x9a\x74\x03\xe6\xc8\x48\x6d\xf1\x3e\ +\x78\xbc\xfb\x1d\x79\xc7\x8e\x7f\xd8\x2e\x33\xe7\xce\x94\x55\x5a\ +\xe4\x13\x97\x20\xec\x3a\x26\x8f\x8b\x24\xcd\xe7\x13\xf7\x8f\x8f\ +\x1f\x3c\xe5\x3a\x55\x1d\xe5\x49\x94\x15\xb9\x99\xb8\x79\xe1\xfe\ +\x70\x73\x35\xfe\xc6\xf3\x9c\x9f\x4a\x13\xd5\x26\x71\x36\x69\xbd\ +\x70\x7e\xce\x6f\xab\x38\x5a\x19\xe7\xdb\x45\x5d\xaf\x42\xdf\xdf\ +\x6c\x36\x28\x6d\x07\x51\x51\xce\xfd\xef\x1c\xcf\xbb\xb9\xba\x1a\ +\x57\x77\xf3\x2b\xc7\x71\x60\xde\xbc\x0a\x93\x78\xe2\xb6\x02\xab\ +\x75\x99\x35\x8c\x49\xec\x9b\xcc\x2c\x4d\x5e\x57\x3e\x41\xc4\x77\ +\xf7\xec\xf1\x9e\x3d\xb6\xb3\xa7\x77\x26\x2e\x96\xcb\x22\xaf\x1a\ +\xc9\xbc\x7a\x37\x60\x2e\x93\x59\xcf\x6d\xad\xd9\xb0\x86\x89\x68\ +\xad\x7d\x4c\x7d\x4a\x3d\xe0\xf0\xaa\xfb\xbc\x8e\xb6\xde\xa1\x28\ +\xd8\x78\x4a\x94\x62\x8c\x7d\xa0\xed\x39\x9f\xc7\x15\x56\xe0\xd0\ +\x15\xfc\xf5\xec\xdd\x00\xaa\x8a\x75\x19\x9b\x19\xc8\x19\x94\x9b\ +\xda\x7f\xff\xf1\x7d\x4f\xf4\x30\x4a\xea\x64\xa0\xa6\xf3\xe7\xc1\ +\xac\x07\x4e\xce\xa3\xa5\xa9\x56\x51\x6c\x2a\xbf\x1b\x6f\xe4\x37\ +\x69\x52\x2f\x26\x6e\xc0\x57\xdb\xe6\x7d\x61\xd2\xf9\xa2\x1e\x0c\ +\xa4\xc9\xc4\x05\x9b\xa9\x22\x41\xf3\x3e\x80\x04\xd9\x31\xb4\xea\ +\xc2\x9e\x82\x11\x57\x88\x21\xe2\x94\x5a\xa9\x9d\x54\x67\x79\x98\ +\x14\xb1\x35\x65\xe2\xfe\x58\xc6\x8b\x4f\x7f\x46\x59\xf6\xe9\x63\ +\x69\x0c\xb2\x6e\xb9\x01\xce\x71\x62\x66\x95\x95\xd8\xcd\x6c\xdf\ +\x60\x6a\xd5\xd0\x80\xda\x4f\xb6\x82\xc9\x56\x26\xb6\x81\xde\x71\ +\x0f\xe6\xa8\xef\xad\x27\x0e\x59\xd9\xce\x5d\xce\x81\xc1\xab\x4f\ +\x5b\xb0\xd6\x09\x1d\x46\xe1\x1f\x72\x92\xe3\x7e\xc7\x41\x20\x76\ +\xf0\x85\x4f\xf2\x7c\xb6\xfe\x3a\xa3\xa6\xb5\xc0\x2b\xca\x74\x9e\ +\x82\x83\x1a\x3e\x4a\x10\x6b\x9e\x43\x19\x58\xf4\x60\x6d\x54\x51\ +\xee\x3a\xfe\x33\x56\x7f\x24\xc8\x02\x4a\x9f\x36\x04\x23\x61\x17\ +\xd5\x1a\x72\x6c\xca\xe1\x0a\x49\xc3\x29\x5e\xe4\xa8\xd6\xdd\xc7\ +\x6a\x9e\x8a\xdc\x97\x3a\xc0\xd3\x17\xee\x02\xc1\x2e\xdc\x01\x52\ +\x5c\xb8\x03\xb4\xbc\x6c\x07\x48\x7a\xc2\x86\x8b\x72\x00\xbf\xf0\ +\x73\x40\x06\xfc\xc2\x1d\xa0\x2e\x7c\x13\x54\x38\xb8\x78\x07\x78\ +\x17\x5e\x09\x28\xf6\x7f\x4b\x82\xb1\x6f\x9b\xa3\xe6\x57\x2f\x60\ +\x5b\xab\xe4\x2e\x35\x9b\x7d\x07\x35\x8d\x2a\xd3\x6a\x5e\x45\x73\ +\xe8\x8a\xb3\xa2\x9c\xb8\xef\x66\xcd\xd3\x12\xa6\x45\x99\x98\xb2\ +\x23\x05\xcd\x73\x40\x2a\xa0\x73\x4c\xeb\xfb\xdd\x3d\xc0\xd5\x91\ +\x13\x41\x6b\x4f\xc7\xa7\xe9\xd5\x22\x4a\x8a\xcd\xc4\xa5\xc7\xc4\ +\xcf\x45\xb1\x9c\xb8\x02\x09\x6c\x1f\x72\x4c\x8e\xc1\x43\x5c\x20\ +\x4c\x45\xc0\x1f\x12\x61\x3e\x2a\x91\x22\x1a\x93\xe0\x01\x71\x5d\ +\x96\x26\xaf\xbd\x2c\xba\x37\xb0\xa8\xe6\xab\xd3\x50\x2d\x8a\xcd\ +\xbc\xb4\xce\xa9\xcb\xb5\x39\x96\x84\x0e\x75\x6d\xef\x18\xbc\x75\ +\x9e\xd6\xd0\xc7\xb7\x7d\xf0\x80\xc3\xca\x7a\xd3\x69\xb1\x3d\xad\ +\xa0\xca\xa3\xd5\x19\xb2\xa5\x78\xab\xa8\x5e\x54\x67\xe8\x79\x91\ +\x98\x47\xe8\xbd\x7a\xcf\x24\x73\xe3\x2d\xd3\x64\x55\xa4\x79\xfd\ +\x24\xf7\x13\x8c\xc5\xf4\x2f\x48\x95\x73\x86\xb5\x1c\x67\x4c\xdb\ +\xa4\x39\x84\xd9\x6b\xef\x14\x08\x55\x0f\xc0\xd0\x72\x74\xb7\x0c\ +\x52\xa8\x47\x38\x6c\x6a\x3c\x42\xb2\x30\xd4\x8f\xd0\x96\xd1\x36\ +\x5d\xa6\x9f\x4d\x62\xc5\xdb\x3c\x59\x9a\x3a\x4a\xa2\x3a\xda\xe7\ +\x44\x37\x02\xdd\x35\xe9\x6e\x16\xca\x64\x16\xfe\xf6\xfe\xc3\x4d\ +\x9b\x84\xe3\x38\x0e\xff\x2c\xca\xdb\x2e\x27\x1d\xc7\x32\x44\xd3\ +\x62\x0d\x66\xbb\x37\xfd\xf0\x38\x89\xc3\x59\x51\x2e\xa3\xfa\x26\ +\x5d\x02\xd2\xed\xfd\xce\xf7\xdb\x65\x06\xd9\xd9\x13\x0e\x98\x6d\ +\x4e\xef\x95\xee\xd4\x96\x66\x77\xdb\x73\xf2\xca\x2b\x89\x97\xa9\ +\x15\xf2\x7f\xaf\xd3\x2c\xfb\xd9\x4e\xd2\x6f\x81\xbd\xd2\xb4\xce\ +\xcc\x7e\x70\xec\xb7\xd6\xb7\x6b\xf3\x07\x8b\x1b\xfb\xdd\xea\x9b\ +\xb7\xf9\xde\x2b\x07\x39\xd2\x3b\x36\x8b\xa6\x26\x9b\xb8\xbf\x58\ +\xa2\xf3\x80\x3a\x2f\x8b\xf5\x6a\x09\x88\x68\xc5\x7b\x6f\x02\x52\ +\xfa\xed\xac\xbe\xcf\x80\xde\x6c\x2f\xe1\xbb\x26\xd1\xf1\xf5\x0c\ +\xd6\x12\xbe\x8b\x22\xce\xdb\x17\xaf\xdd\x43\x42\xb2\x7b\x2d\xd7\ +\x99\x09\xcd\x9d\x01\xb8\x25\xd7\x55\x5d\x16\xb7\xa6\x17\xde\xbd\ +\xee\x70\x16\x32\xc4\x79\xc0\x29\xc5\xa4\x1b\xcf\xd2\xdc\x80\x75\ +\xe1\x74\x5d\xd7\xc3\xb1\xbf\x00\xfe\x21\x18\x9c\x77\x0a\x21\x27\ +\x6a\x53\x66\x80\x98\x3a\xe4\xdd\xd8\xde\x8e\x76\x20\x89\x60\xfb\ +\x2a\xcb\xe8\x3e\xcc\x8b\xdc\x0c\x47\x8b\xd9\xac\x32\x75\x88\xaf\ +\x97\x51\x79\x6b\xca\x1d\xfd\x2e\xad\xd2\x69\x9a\x59\x15\xcd\xcf\ +\xcc\x5c\x27\x69\xb5\x02\xf7\x84\x69\x6e\xcd\xb8\x2e\xee\x4c\x39\ +\xcb\x8a\x4d\x4f\x37\x79\x04\x5f\xde\x34\x8a\x6f\xe7\x8d\x7d\x61\ +\x14\xc3\x26\xb4\xce\xa2\xda\xec\x0f\x0e\x08\x91\x75\x2b\x55\x1c\ +\x7b\xcc\xe3\x1e\xf6\x54\x4f\xec\x52\x4e\x20\xcd\x02\x46\xf7\xf7\ +\x1e\x5d\xa6\x11\x8a\x84\x12\x1c\xef\x45\xb6\xf6\x1e\x0a\x69\x2d\ +\xf5\xa0\x3c\x82\xdc\x12\x1a\x05\x90\xba\xfb\xae\xa1\x2e\xa3\xbc\ +\xb2\x50\x86\xc4\x89\xea\x32\xdd\x7e\x8b\x91\x14\x52\x12\x2e\x46\ +\x1e\x46\x81\xa0\x42\x05\x44\x8f\xf0\x88\xc0\x1f\xfe\x6e\x7f\x40\ +\x3f\x13\x05\xbb\xb3\xe8\xa5\x28\xc0\x5a\xc1\xca\xa5\xd4\xed\xa3\ +\x5e\x3f\xf4\x5f\x31\xcc\xe7\xb0\x3b\x84\xda\x49\x38\x1c\xc3\x80\ +\x72\xc4\x02\xaa\x03\x79\x0a\x06\x5c\x51\xa1\xf9\x10\x06\x14\x31\ +\x42\x08\xf0\x0f\x61\x40\x15\x52\x4a\x41\x94\xcf\xe2\x40\x33\xc9\ +\x04\xc1\x10\x7c\xc4\xb8\x62\x6f\x38\xf8\x4f\x71\x30\xb8\xef\xfc\ +\x42\x24\x28\xa4\x03\x08\xe8\x03\x24\x04\x01\x80\xe1\x15\x90\x60\ +\xcb\x8b\x67\x20\x21\x96\xf6\xf3\x42\x24\xbc\x24\xee\xff\x61\x84\ +\xcf\x1f\x35\x7d\x0c\x20\xec\xbf\x3a\x84\x23\xca\x89\xa0\x72\x44\ +\x34\xa2\x9a\x13\xac\x1c\x26\x11\x96\x8a\xa8\x11\xd4\xc6\xf6\x9b\ +\x6a\x87\x42\x09\x8d\xa9\xd6\x6c\xc4\x14\x22\x8a\x04\x42\x3a\x14\ +\x91\x20\x60\x4c\x03\x1f\x6c\xf8\x9a\xc1\xb9\x71\x52\xdd\xe7\xc7\ +\x0e\x20\x61\xff\x1e\xf6\x2c\xb6\x3c\xb4\xe5\x0a\x94\x88\xb1\x7d\ +\xde\x62\xff\x95\x62\xcf\x20\x44\x10\x2d\xc9\x47\x90\xa0\x5c\x70\ +\x49\xa5\x13\x50\x84\x03\xac\x20\x80\x2c\x40\x9a\x53\xce\x95\xc3\ +\x35\xd2\x0a\xfa\xa7\x11\x97\x90\x99\x94\xca\xc0\x01\x64\x10\xae\ +\xb4\x92\x16\x0f\x50\x15\x08\x21\x4e\xaa\x3b\x17\xfb\x17\x46\x7e\ +\x17\xeb\x83\xd8\x3d\x23\x94\x8f\x56\x75\x4d\x44\x1f\x86\xb2\xfb\ +\x05\x55\x0a\x66\x58\x30\x5b\x6d\xee\x1e\x71\x0e\x0b\x87\xa1\x18\ +\xba\x7d\x69\xfd\x64\xb7\x39\xa5\x46\x1c\x9a\x61\x70\x23\x63\x0e\ +\x61\x88\x61\x49\x34\x1f\x79\x04\xea\x21\x42\xb4\x74\x38\x02\x07\ +\xc3\x67\xe4\x71\x84\x99\x10\x5a\x3b\x1e\x05\x3b\x98\xd2\x9a\x8e\ +\x3c\x89\x02\xae\x31\x65\x8e\xa7\x10\xa3\x50\xc0\xea\x11\x04\x25\ +\xd0\x01\x84\x82\x34\xf5\x15\x17\x6a\x14\xd8\x24\x25\x01\x3f\x8a\ +\x84\xf5\x27\x53\x5c\x3f\x1d\x83\xf8\xed\x10\xfe\xd7\x0f\x61\xf6\ +\xc2\x43\x98\xd8\x7d\x5b\x49\x35\x3c\x83\x01\x61\x8a\x4b\x32\xf8\ +\xff\xbc\xaf\x5e\x8d\xc9\xc8\x7e\x5e\xab\x37\xeb\xf2\x8e\x5f\x12\ +\x10\x3c\x7e\x0c\x85\x7f\xd8\xa0\x05\xc0\x1e\x28\x2d\x0e\xea\x31\ +\x0d\xd1\xd5\x54\xe2\xf3\xf5\xd8\xab\x76\x68\x6f\x58\x78\x05\x2c\ +\x78\x0f\xfa\xb4\x7f\x88\x06\x01\x35\x1b\xe7\x5a\x90\x21\x1a\xe0\ +\xc8\x87\x93\x82\x0f\x9a\xb7\x2f\x47\xc3\x5b\x85\xf6\xaa\x15\x1a\ +\x14\x52\x12\xc2\x45\x47\x50\x32\x70\xa2\x24\x75\x04\x41\xd6\xf7\ +\x92\x8e\x88\x42\x50\x91\x0b\xcd\xfa\x82\x42\x34\x85\x17\x54\xdd\ +\x94\x38\x24\x40\x81\xe4\x8c\x51\x5b\x88\x43\x1d\x2e\x4f\xe8\x7a\ +\xbc\x38\x7b\x76\x69\x36\xf6\xe7\x37\x57\x63\x7b\x65\x79\x73\xf5\ +\x37\x0f\x85\xd5\xfb\ \x00\x00\x11\xff\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ @@ -10066,6 +10193,130 @@ qt_resource_data = "\ \x9a\x32\x44\x99\x70\x39\x33\x94\xd2\xeb\xa7\x55\xab\x4f\x8c\xe1\ \x70\xaa\x5e\x6a\x8c\x9b\xd9\xea\xf6\xea\xc6\x24\x6c\xb7\x57\xff\ \x06\x6a\xf1\x08\x6d\ +\x00\x00\x07\x91\ +\x00\ +\x00\x36\x0d\x78\x9c\xed\x5b\xdd\x6f\xdb\x38\x12\x7f\xcf\x5f\xa1\ +\x53\x5e\x5a\x9c\x25\xf3\x4b\x14\xa9\xda\x59\x1c\xae\xd8\xc3\x02\ +\x77\x38\x60\xdb\xe2\x1e\x0b\x59\xa2\x6d\x6d\x64\xd1\x90\xe4\xd8\ +\xee\x5f\x7f\x43\x59\x5f\x76\xe4\xa4\xe9\xe6\xa1\x17\x9d\x83\x24\ +\xd2\xcc\x90\x1c\xfe\x66\x38\x33\x94\xe8\xd9\x2f\x87\x4d\x6a\x3d\ +\xa8\xbc\x48\x74\x36\xb7\xb1\x8b\x6c\x4b\x65\x91\x8e\x93\x6c\x35\ +\xb7\xbf\x7c\xfe\xd5\x11\xb6\x55\x94\x61\x16\x87\xa9\xce\xd4\xdc\ +\xce\xb4\xfd\xcb\xdd\xcd\xec\x2f\x8e\x63\xfd\x3d\x57\x61\xa9\x62\ +\x6b\x9f\x94\x6b\xeb\xb7\xec\xbe\x88\xc2\xad\xb2\xde\xad\xcb\x72\ +\x1b\x4c\xa7\xfb\xfd\xde\x4d\x6a\xa2\xab\xf3\xd5\xf4\xbd\xe5\x38\ +\x77\x37\x37\xb3\xe2\x61\x75\x63\x59\x16\x8c\x9b\x15\x41\x1c\xcd\ +\xed\xba\xc1\x76\x97\xa7\x95\x60\x1c\x4d\x55\xaa\x36\x2a\x2b\x8b\ +\x29\x76\xf1\xd4\xee\xc4\xa3\x4e\x3c\x32\xa3\x27\x0f\x2a\xd2\x9b\ +\x8d\xce\x8a\xaa\x65\x56\xdc\xf6\x84\xf3\x78\xd9\x4a\x1b\x6d\xf6\ +\xb4\x12\xc2\x52\xca\x29\x22\x53\x42\x1c\x90\x70\x8a\x63\x56\x86\ +\x07\xe7\xbc\x29\xe8\x38\xd4\x94\x20\x84\xa6\xc0\xeb\x24\xbf\x4f\ +\x2a\x38\xa4\x00\xc5\x55\x65\x2a\x6e\x7f\x74\x80\x7f\x0b\xbf\x6d\ +\x83\x86\xe0\x16\x7a\x97\x47\x6a\x09\x2d\x95\x9b\xa9\x72\xfa\xf1\ +\xf3\xc7\x96\xe9\x20\x37\x2e\xe3\x5e\x37\x0d\xfa\x67\xe3\x9e\x99\ +\x24\x0b\x37\xaa\xd8\x86\x91\x2a\xa6\x0d\xbd\x6a\xbf\x4f\xe2\x72\ +\x3d\xb7\x39\xdb\x1e\xaa\xfb\xb5\x4a\x56\xeb\xb2\x47\x48\xe2\xb9\ +\x0d\x33\x24\x02\xf3\xea\xbe\xe7\x40\xf8\x24\x50\x77\x17\xb4\x1c\ +\xe4\x32\xe1\x52\x17\x5b\xb9\x14\xe2\xd4\xaa\xd1\x3c\x88\x75\x64\ +\x54\x99\xdb\x7f\xcb\xa3\xf5\xd7\xdf\xb5\x5e\xba\x06\xbf\x3b\x10\ +\x9a\xc5\x6a\x59\x18\xe1\xd3\xa0\xe6\x0e\x46\x15\x15\x0f\xb8\x80\ +\x9c\x0a\xf3\x7f\xe4\x61\x9c\x80\xbf\x9c\xe4\x4e\x92\xe7\x1c\xca\ +\x05\xae\xdb\x40\xab\xa2\xd4\xdb\x46\xb6\x9e\x0c\x50\x28\x97\xbe\ +\xdd\x91\xf5\x72\x59\x28\x98\x34\xea\xd1\x8a\xf2\x98\xaa\x93\xb4\ +\x13\xe9\x54\xe7\xc1\xed\xb2\xfa\x7c\xa8\x48\x1a\xb0\x4c\xca\x63\ +\x80\x3f\xd8\xd6\xf4\xca\x68\x03\x5d\x88\x85\xf9\x79\xd4\xc5\x63\ +\x55\xb0\x3d\xa4\xb5\xf0\xda\xd1\x66\xd3\xf3\x69\xd7\xd4\xd6\x1a\ +\x5b\xb0\xc6\x56\x45\x66\xdd\x34\x3d\xb5\x46\x28\x8f\xc6\x55\xce\ +\x45\x69\xdc\x8e\xd8\x59\x74\xfb\xf5\x00\xa8\x58\x81\x45\x09\xfc\ +\xc1\x83\x12\xc7\x93\x04\x86\xa5\x00\xff\xd0\xa0\xcc\x37\xe3\x50\ +\x4f\x74\x53\x6b\xe0\xe8\x3c\x59\x25\xe0\x41\x95\x1c\xc1\x2e\xad\ +\x3e\xe7\x6d\x00\x8c\xde\xdc\x88\x20\xac\xc3\xe4\xa9\xd9\x5f\x34\ +\xa4\x9c\x90\xe7\x15\x41\xae\x67\x26\x55\x2b\x72\xa9\xca\xf9\x0c\ +\x71\x25\xe9\xfd\x29\xa0\x6a\xb8\x2f\xbb\x79\xce\x72\x3f\x0a\x80\ +\x23\x47\x0e\x81\x47\x47\x0e\x80\xef\x8d\x1c\x80\x5e\x22\x18\x25\ +\x00\x3e\x19\xd0\x61\x54\x00\xb0\x91\xe7\x01\x9f\xb3\x91\x03\x20\ +\x46\x1e\x04\x05\xe2\xa3\x07\xc0\x19\x79\x25\x20\xe8\xc8\x17\x01\ +\xc7\x23\x0f\x83\x00\x80\x23\x46\x0e\x01\x1b\x79\x14\x00\x00\xc6\ +\x1e\x08\xb9\x3f\xf2\x7a\x10\x00\x70\x46\x9e\x0b\x7c\xf4\x1d\x0f\ +\xa9\xde\x38\x00\x63\xcf\x05\x3e\x7b\x83\x45\xf1\x36\x2c\x4b\x95\ +\x67\x4d\xbb\xfa\xf6\x73\x1e\x66\xc5\x52\xe7\x9b\xb9\xbd\x09\xcb\ +\x3c\x39\xbc\x43\x2e\x87\x6d\x21\xf5\x89\x98\x38\xc8\x15\x58\x10\ +\x89\x3d\x6f\x42\x5c\xe6\xf9\x82\x62\x36\xc1\xae\x10\x8c\x79\x1e\ +\x9b\x38\x84\x03\x15\x71\xc4\x27\x58\xb8\x44\x32\xc9\xfc\xf7\xe7\ +\x8f\x6b\x4f\xa3\x78\x84\x76\x1a\x57\x2f\x42\x82\x75\xae\x96\x73\ +\xfb\xf6\x13\x8c\xb9\x2d\xf0\x57\xec\x0c\x94\x60\x91\x4e\x53\x30\ +\xc9\xdc\x0e\xd3\x7d\x78\x2c\x7e\xc8\x98\x1e\x21\x6f\xb0\xb8\xbb\ +\x30\x66\x2b\x58\x94\x3a\xba\x37\x08\x54\xb8\xaa\xc2\xc2\xc1\xf9\ +\xf3\xf3\x21\xbc\x9f\x72\x05\xee\x83\x23\x30\x3a\x71\xb0\x8b\x10\ +\xc4\x06\x51\x79\x02\xe1\x58\xf8\x02\xae\x28\xc6\xcc\x63\x62\x42\ +\x5d\xe6\x73\x24\x85\x0f\x57\x1e\x65\x92\xd0\xce\x0f\x9a\xf7\x4a\ +\x9d\x22\xf5\x9b\x27\x72\xa9\xc1\x97\x2c\x29\x8b\xb9\xbd\x2b\x54\ +\xfe\xc9\xbc\xb0\xfa\x77\xf6\xa5\x50\xcf\xbb\x45\xfb\x0e\x26\x07\ +\x6a\x23\x7d\x9a\xae\xa1\x30\x26\x68\x6f\xb6\x9d\x42\xa4\x47\xab\ +\x55\xea\xbf\x7b\x01\x3b\xc2\x02\xf0\x7a\x94\xc3\xe0\x7b\xa2\x65\ +\x92\xa6\xc1\x22\x0d\xa3\xfb\x0f\x45\x99\xeb\x7b\x15\x64\x3a\x53\ +\xbd\xb7\x35\xf5\xec\x7e\xcc\x77\xdf\xe2\x73\xfa\x17\x84\xa2\xef\ +\xf5\x3f\xe9\x02\x89\x0a\x3c\x11\xae\xe4\x92\x08\xc4\xae\x06\xa2\ +\x9e\x2f\x5c\x09\x45\x03\xd1\xff\xb5\x42\xd1\x5b\x2c\xb1\x5f\x21\ +\x18\xf1\x51\x05\x23\xf4\xd3\x04\xa3\x97\xac\x44\x0f\x53\x2a\x48\ +\x05\x3e\xa7\x98\x48\x69\xc0\xc7\x50\x2c\x20\x6a\xae\x18\x14\x0a\ +\x3e\xd8\x86\x49\xd7\xe7\xc4\xe3\x86\x2d\x3d\xc6\x05\xba\x56\x13\ +\x48\x3e\xbc\x10\xfb\x6b\x75\x60\xb9\xbc\xce\x52\x14\x6f\xb0\xc6\ +\x7d\xfd\xb8\x6a\x2a\x3c\x4a\x39\x88\x4e\x30\x14\x83\xc2\xc7\xf2\ +\x7a\x85\xd7\x33\xd6\xb5\x1a\xef\x45\xf6\x7c\x8d\x22\xa7\x37\xe0\ +\x18\x22\x0b\xeb\x45\xd2\xff\x9d\xd8\xc2\x00\x7b\x26\x04\x37\x1b\ +\x0e\x4e\x60\xb7\x21\x98\x84\x6d\x86\xe7\x41\x70\xe1\x3e\x5c\x31\ +\x8a\xa9\xe4\x13\xe2\xbb\x92\x09\x66\xf6\x20\xd4\xa5\x88\x33\x8f\ +\x0f\x3b\x23\xa5\xe8\x39\x57\x1c\x28\xab\x5e\x25\xb0\x50\xf2\xff\ +\x0c\xdf\x21\x33\x84\xf7\x18\xd6\x21\xfd\x69\x56\xe1\x8b\x7c\x97\ +\x8f\xfb\xd9\x97\x47\xc5\x1b\x5c\xbc\x2f\x01\x80\xe1\x37\xe8\x01\ +\x57\x8e\x8f\x5e\x5b\xdf\x83\x89\x63\xe0\xa0\x69\x1f\xc3\x4b\xb6\ +\xec\xd6\xf1\x01\xcf\x6d\xea\xbb\x42\x42\x96\xeb\x0e\x1c\x1d\x81\ +\xca\xcc\x69\x59\xe6\xf7\x5e\x3a\x1c\xc8\xdc\xe6\xc4\x45\x4c\xf8\ +\x7e\x17\x30\x8f\x86\x8a\x5c\xa8\xb0\x30\xee\x7a\x58\xd5\x83\x3d\ +\x1d\xc5\x1a\xa9\xa1\x68\x4b\x18\x21\x3e\xc2\xf2\x94\x76\x99\x87\ +\x7d\x49\x26\x55\xa5\xcf\x29\x82\x74\x0b\x12\xc4\x87\x34\x4b\xbc\ +\x89\xe7\x72\xc4\x24\xf2\xc4\x84\x11\x17\x88\x98\x8a\xf7\x35\xc0\ +\xb3\xa9\x39\xae\x5b\x5d\xb5\x16\x31\xe7\x7c\xe3\x87\x44\xed\x6f\ +\x5a\x84\x16\x61\xab\xd5\x36\x5c\xa9\xea\x50\x2c\xe0\x7a\x3a\x58\ +\x5b\x33\x16\x3a\x8f\x55\xde\xb0\x78\xf5\x39\x63\xd5\xe7\x66\x4f\ +\x47\xd8\x6f\x2e\xbc\x14\x7a\x6d\xf9\x68\x98\x5f\xac\xc3\x58\xef\ +\xbb\x50\xdc\x32\xbf\x69\x0d\xc8\x50\xa8\x70\x25\x12\xfe\x23\x76\ +\x04\x2e\xe8\x60\xd8\xcf\x10\xea\xfb\xec\x11\xd7\x28\xc4\x5c\x28\ +\x8d\x05\xc1\x8f\x98\xbb\x3c\x07\xfc\x9d\x34\x3c\x2a\x98\x55\xf5\ +\xaf\x11\x2a\xd6\x7a\xbf\xca\x0d\x3a\x65\xbe\x53\x97\x2d\x63\x1d\ +\xed\xcc\xf9\x78\x67\x77\xb2\x70\x7d\x2a\xbb\x27\x61\xda\x3a\x8b\ +\x85\x3e\x0c\x77\x50\x64\xe1\xf6\x09\xb6\xe1\x38\x90\x2c\xd6\xc5\ +\x13\xfc\x4c\xc7\xea\x0a\xbf\xed\xde\x51\xf1\x4a\x39\x9b\x24\xde\ +\xea\x24\x2b\x9f\x95\x7e\x46\x50\x2f\xfe\x80\xd5\xf8\x94\x62\xb5\ +\xc4\x13\xaa\xed\x93\x0c\xec\xec\x34\x59\x96\x88\x47\xde\x50\x4b\ +\x34\xb9\xd9\xf7\xc4\x15\x89\x5e\x12\xbe\x64\x19\xb3\xcb\x2b\xbc\ +\x4d\x78\x48\x36\xc9\x37\x15\x9b\xe6\xf5\x42\xd9\xa8\x32\x8c\xc3\ +\x32\xec\x16\x45\x43\x21\xc6\x71\xea\x68\x95\xc7\xcb\xe0\xf7\x8f\ +\xbf\xb6\x55\x46\x14\x05\xff\xd1\xf9\x7d\x57\x07\x18\x81\x70\xa1\ +\x77\xa0\x76\x5b\x8b\x98\x23\xf4\x51\x60\xd6\x77\x58\xde\x25\x1b\ +\x70\x75\xf3\xdd\x84\xbf\x1e\x36\x29\x2c\xcf\x96\x71\x26\x6c\xa2\ +\x66\xd7\xe9\xa9\xdb\x5c\x9d\xbe\x7b\x30\xf8\x75\x8d\x38\xda\x24\ +\xa6\xd1\xf4\x53\x09\x25\xc8\x6f\x66\x90\xde\x01\xf8\xba\xd3\xa4\ +\x4c\xd5\x5d\x35\xe6\xe9\xb2\x99\xc5\xb4\x9e\x46\x53\xa4\xf4\x66\ +\x39\x9b\x36\x30\x54\x77\xab\x0e\x9e\xb3\xc5\xd2\x22\x9c\x86\x0b\ +\x95\xce\xed\x7f\x1a\xa6\xf5\x88\xbb\xca\xf5\x6e\xbb\x01\xd7\xa8\ +\x9b\xdb\x5d\x09\xbb\x6e\x33\x47\xaf\x92\xba\xe5\x0b\xf3\xf3\xc1\ +\xdc\xf4\xce\xe5\xd7\xa5\xd5\x2d\xaa\x3e\xf5\xed\xc9\xa1\x02\xda\ +\xdc\x9a\xa8\x0f\x83\x06\x8b\x5d\x59\xf6\x69\x7f\x80\x7b\x07\xa0\ +\x47\x16\x37\x54\x40\x4e\xe5\x29\x78\x44\x19\xb0\x86\x76\x39\x98\ +\x13\x87\x10\x9f\xf2\x3c\x3c\x9e\x2a\xba\x46\x5b\x00\xe2\x5f\x16\ +\x81\xb0\x4c\x25\xf2\xf9\x84\x79\xae\x27\xb8\x8f\x88\x05\xa1\x58\ +\x20\xe9\x49\xa8\x91\xa9\x8b\x89\xe7\x21\x6c\x31\x09\x1b\x23\xe9\ +\x63\x7f\x22\x5d\x09\xc1\x4c\x52\x8b\x40\x1c\xc7\xb0\xa5\x22\x13\ +\x02\x61\xdc\x83\x2c\x44\xad\x6f\x97\xdb\xa6\x35\x91\x68\x20\xfb\ +\x46\x3a\x83\x29\x96\x3a\x77\x20\x8e\x3d\x84\xe5\x2e\x57\xfd\xa2\ +\xb4\x0b\xf8\x00\xb8\xf1\x0d\x58\x8f\x91\xf9\x9c\x6d\x1d\x06\x71\ +\x07\xc7\x7a\xf7\x28\xab\x4a\xef\xfd\xcf\x6e\x88\x01\x80\x4d\xc6\ +\x26\x98\x51\x3a\x21\xdc\x3c\xf2\x82\x0c\x62\x51\x0f\x68\x3e\x24\ +\xf7\x89\x07\x56\x32\x89\xfb\x7b\xed\x20\xe4\xe0\xe3\xe7\x3f\x65\ +\x87\xd9\x74\x75\x77\x33\x33\x21\xe1\xee\xe6\xbf\x41\x63\xea\xe4\ +\ \x00\x00\x06\xdd\ \x00\ \x00\x22\x8f\x78\x9c\xed\x59\xdb\x6e\xe3\x46\x12\x7d\xf7\x57\xf4\ @@ -10327,6 +10578,10 @@ qt_resource_name = "\ \x00\x72\x00\x63\x00\x68\x00\x5f\x00\x53\x00\x70\x00\x6c\x00\x69\x00\x74\x00\x4d\x00\x65\x00\x73\x00\x68\x00\x2e\x00\x73\x00\x76\ \x00\x67\ \x00\x0d\ +\x07\x4a\x92\xc7\ +\x00\x41\ +\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x52\x00\x6f\x00\x6f\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0d\ \x01\xb7\x92\xa7\ \x00\x41\ \x00\x72\x00\x63\x00\x68\x00\x5f\x00\x53\x00\x69\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ @@ -10373,6 +10628,11 @@ qt_resource_name = "\ \x00\x41\ \x00\x72\x00\x63\x00\x68\x00\x5f\x00\x46\x00\x6c\x00\x6f\x00\x6f\x00\x72\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x2e\x00\x73\ \x00\x76\x00\x67\ +\x00\x12\ +\x08\x61\x2a\xa7\ +\x00\x41\ +\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x52\x00\x6f\x00\x6f\x00\x66\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x2e\x00\x73\x00\x76\ +\x00\x67\ \x00\x14\ \x02\xc8\x0e\x47\ \x00\x41\ @@ -10382,8 +10642,8 @@ qt_resource_name = "\ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x01\ -\x00\x00\x00\x10\x00\x02\x00\x00\x00\x01\x00\x00\x00\x2d\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x18\x00\x00\x00\x15\ +\x00\x00\x00\x10\x00\x02\x00\x00\x00\x01\x00\x00\x00\x2f\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1a\x00\x00\x00\x15\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x11\x00\x00\x00\x04\ \x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x01\x60\x78\ \x00\x00\x00\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x55\x20\ @@ -10402,29 +10662,31 @@ 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\x2c\x00\x01\x00\x00\x00\x01\x00\x02\x43\x52\ -\x00\x00\x04\x38\x00\x00\x00\x00\x00\x01\x00\x02\x05\x83\ -\x00\x00\x03\x16\x00\x00\x00\x00\x00\x01\x00\x01\xb7\x11\ -\x00\x00\x05\xcc\x00\x01\x00\x00\x00\x01\x00\x02\x6e\xe4\ -\x00\x00\x04\xfe\x00\x01\x00\x00\x00\x01\x00\x02\x3c\x80\ -\x00\x00\x03\x50\x00\x01\x00\x00\x00\x01\x00\x01\xc5\x80\ -\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x01\xd9\x07\ +\x00\x00\x05\x4c\x00\x01\x00\x00\x00\x01\x00\x02\x4b\x1c\ +\x00\x00\x04\x58\x00\x00\x00\x00\x00\x01\x00\x02\x0d\x4d\ +\x00\x00\x03\x16\x00\x00\x00\x00\x00\x01\x00\x01\xb7\x13\ +\x00\x00\x06\x16\x00\x01\x00\x00\x00\x01\x00\x02\x7e\x42\ +\x00\x00\x05\x1e\x00\x01\x00\x00\x00\x01\x00\x02\x44\x4a\ +\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\x04\x78\x00\x00\x00\x00\x00\x01\x00\x02\x1f\x5d\ +\x00\x00\x04\x98\x00\x00\x00\x00\x00\x01\x00\x02\x27\x27\ +\x00\x00\x04\x38\x00\x01\x00\x00\x00\x01\x00\x02\x05\x85\ \x00\x00\x02\x98\x00\x01\x00\x00\x00\x01\x00\x01\x93\x78\ -\x00\x00\x03\x7e\x00\x01\x00\x00\x00\x01\x00\x01\xce\xd8\ +\x00\x00\x05\xec\x00\x01\x00\x00\x00\x01\x00\x02\x76\xad\ +\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\xa8\x00\x01\x00\x00\x00\x01\x00\x02\x2e\xcb\ -\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x01\xf5\x02\ -\x00\x00\x04\xd6\x00\x01\x00\x00\x00\x01\x00\x02\x34\x1b\ -\x00\x00\x05\x56\x00\x00\x00\x00\x00\x01\x00\x02\x4a\x2d\ -\x00\x00\x03\xc6\x00\x01\x00\x00\x00\x01\x00\x01\xde\x1e\ -\x00\x00\x05\xa0\x00\x01\x00\x00\x00\x01\x00\x02\x66\x6a\ -\x00\x00\x05\x80\x00\x01\x00\x00\x00\x01\x00\x02\x5c\x30\ -\x00\x00\x04\x58\x00\x01\x00\x00\x00\x01\x00\x02\x19\x45\ +\x00\x00\x04\xc8\x00\x01\x00\x00\x00\x01\x00\x02\x36\x95\ +\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x01\xf5\x04\ +\x00\x00\x04\xf6\x00\x01\x00\x00\x00\x01\x00\x02\x3b\xe5\ +\x00\x00\x05\x76\x00\x00\x00\x00\x00\x01\x00\x02\x51\xf6\ +\x00\x00\x03\xc6\x00\x01\x00\x00\x00\x01\x00\x01\xde\x20\ +\x00\x00\x05\xc0\x00\x01\x00\x00\x00\x01\x00\x02\x6e\x33\ +\x00\x00\x05\xa0\x00\x01\x00\x00\x00\x01\x00\x02\x63\xf9\ +\x00\x00\x04\x78\x00\x01\x00\x00\x00\x01\x00\x02\x21\x0f\ \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\x06\ +\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\x01\xf2\x00\x01\x00\x00\x00\x01\x00\x01\x76\xac\ " diff --git a/src/Mod/Arch/CMakeLists.txt b/src/Mod/Arch/CMakeLists.txt index a7522a4137..fcfd728bb8 100644 --- a/src/Mod/Arch/CMakeLists.txt +++ b/src/Mod/Arch/CMakeLists.txt @@ -20,6 +20,7 @@ SET(Arch_SRCS ArchWindow.py ArchAxis.py ArchVRM.py + ArchRoof.py ) SOURCE_GROUP("" FILES ${Arch_SRCS}) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 066ee12b82..52bf671659 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -61,7 +61,7 @@ class ArchWorkbench(Workbench): self.archtools = ["Arch_Wall","Arch_Structure","Arch_Cell", "Arch_Floor","Arch_Building","Arch_Site", "Arch_Window","Arch_Axis", - "Arch_SectionPlane","Arch_Add","Arch_Remove"] + "Arch_SectionPlane","Arch_Roof","Arch_Add","Arch_Remove"] self.drafttools = ["Draft_Line","Draft_Wire","Draft_Rectangle", "Draft_Polygon","Draft_Arc", "Draft_Circle","Draft_Dimension", diff --git a/src/Mod/Arch/Makefile.am b/src/Mod/Arch/Makefile.am index 61917f8f7f..e30ec2a6a5 100644 --- a/src/Mod/Arch/Makefile.am +++ b/src/Mod/Arch/Makefile.am @@ -27,7 +27,8 @@ data_DATA = \ ArchWindow.py \ ArchCommands.py \ ArchAxis.py \ - ArchVRM.py + ArchVRM.py \ + ArchRoof.py CLEANFILES = $(BUILT_SOURCES) diff --git a/src/WindowsInstaller/ModArch.wxi b/src/WindowsInstaller/ModArch.wxi index 094c7c6174..f8bdd05c8b 100644 --- a/src/WindowsInstaller/ModArch.wxi +++ b/src/WindowsInstaller/ModArch.wxi @@ -45,6 +45,7 @@ + From 1b46fc55b7f3d8c7adb1d98738170b21243ae236 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 19:07:27 +0200 Subject: [PATCH 201/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.cpp | 14 ++++++++++++-- src/Mod/Mesh/App/Core/Segmentation.h | 8 +++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 450a7a0674..2e86fdb176 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -35,6 +35,10 @@ void MeshSurfaceSegment::Initialize(unsigned long) { } +void MeshSurfaceSegment::AddFacet(const MeshFacet&) +{ +} + void MeshSurfaceSegment::AddSegment(const std::vector& segm) { if (segm.size() >= minFacets) { @@ -76,10 +80,15 @@ bool MeshDistancePlanarSegment::TestFacet (const MeshFacet& face) const return false; } - fitter->AddPoint(triangle.GetGravityPoint()); return true; } +void MeshDistancePlanarSegment::AddFacet(const MeshFacet& face) +{ + MeshGeomFacet triangle = kernel.GetFacet(face); + fitter->AddPoint(triangle.GetGravityPoint()); +} + // -------------------------------------------------------- bool MeshCurvaturePlanarSegment::TestFacet (const MeshFacet &rclFacet) const @@ -153,7 +162,7 @@ bool MeshCurvatureFreeformSegment::TestFacet (const MeshFacet &rclFacet) const // -------------------------------------------------------- -MeshSurfaceVisitor::MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices) +MeshSurfaceVisitor::MeshSurfaceVisitor (MeshSurfaceSegment& segm, std::vector &indices) : indices(indices), segm(segm) { } @@ -172,6 +181,7 @@ bool MeshSurfaceVisitor::Visit (const MeshFacet & face, const MeshFacet &, unsigned long ulFInd, unsigned long) { indices.push_back(ulFInd); + segm.AddFacet(face); return true; } diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index 0219610014..561385c1c1 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -42,6 +42,7 @@ public: virtual ~MeshSurfaceSegment() {} virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; virtual void Initialize(unsigned long); + virtual void AddFacet(const MeshFacet& rclFacet); void AddSegment(const std::vector&); const std::vector& GetSegments() const { return segments; } @@ -68,8 +69,9 @@ class MeshExport MeshDistancePlanarSegment : public MeshDistanceSurfaceSegment public: MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); virtual ~MeshDistancePlanarSegment(); - bool TestFacet (const MeshFacet &rclFacet) const; + bool TestFacet (const MeshFacet& rclFacet) const; void Initialize(unsigned long); + void AddFacet(const MeshFacet& rclFacet); protected: Base::Vector3f basepoint; @@ -134,7 +136,7 @@ private: class MeshExport MeshSurfaceVisitor : public MeshFacetVisitor { public: - MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices); + MeshSurfaceVisitor (MeshSurfaceSegment& segm, std::vector &indices); virtual ~MeshSurfaceVisitor (); bool AllowVisit (const MeshFacet& face, const MeshFacet&, unsigned long, unsigned long, unsigned short neighbourIndex); @@ -143,7 +145,7 @@ public: protected: std::vector &indices; - const MeshSurfaceSegment& segm; + MeshSurfaceSegment& segm; }; class MeshExport MeshSegmentAlgorithm From 801196bb14a542c1129cea1b4f2c6799801cdffd Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 15:59:53 -0300 Subject: [PATCH 202/351] Cleaning in the Arch module --- src/Mod/Arch/ArchSectionPlane.py | 9 ++++++--- src/Mod/Arch/ArchWindow.py | 18 ++++++++++-------- src/Mod/Arch/InitGui.py | 16 +++++++++++----- src/Mod/Arch/importIFC.py | 4 ++-- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index d4ae54c21f..886cbb3480 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -34,7 +34,7 @@ class _CommandSectionPlane: return {'Pixmap' : 'Arch_SectionPlane', 'Accel': "S, P", 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_SectionPlane","Section Plane"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_SectionPlane","Adds a section plane object to the document")} + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_SectionPlane","Creates a section plane object, including the selected objects")} def Activated(self): sel = FreeCADGui.Selection.getSelection() @@ -47,6 +47,8 @@ class _CommandSectionPlane: for o in sel: if o.isDerivedFrom("Part::Feature"): g.append(o) + elif o.isDerivedFrom("App::DocumentObjectGroup"): + g.append(o) obj.Objects = g page = FreeCAD.ActiveDocument.addObject("Drawing::FeaturePage","Page") template = Draft.getParam("template") @@ -179,6 +181,7 @@ class _ArchDrawingView: if hasattr(obj,"Source"): if obj.Source: if obj.Source.Objects: + objs = Draft.getGroupContents(obj.Sourc.Objects) svg = '' # generating SVG @@ -188,7 +191,7 @@ class _ArchDrawingView: import ArchVRM render = ArchVRM.Renderer() render.setWorkingPlane(obj.Source.Placement) - render.addObjects(obj.Source.Objects) + render.addObjects(objs) render.cut(obj.Source.Shape) svg += render.getViewSVG(linewidth=linewidth) svg += render.getSectionSVG(linewidth=linewidth*2) @@ -197,7 +200,7 @@ class _ArchDrawingView: else: # render using the Drawing module shapes = [] - for o in obj.Source.Objects: + for o in objs: if o.isDerivedFrom("Part::Feature"): shapes.append(o.Shape) if shapes: diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 382d9e3f98..2cdf513c91 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -78,17 +78,19 @@ class _CommandWindow: return {'Pixmap' : 'Arch_Window', 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Window"), 'Accel': "W, N", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from scratch or from a selected object (wire, rectangle or sketch)")} + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from a selected object (wire, rectangle or sketch)")} + + def IsActive(self): + if FreeCADGui.Selection.getSelection(): + return True + else: + return False def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction("Window") - if sel: - for obj in sel: - makeWindow(obj) - else: - rect = Draft.makeRectangle(1,1) - makeWindow(rect) + FreeCAD.ActiveDocument.openTransaction("Create Window") + for obj in sel: + makeWindow(obj) FreeCAD.ActiveDocument.commitTransaction() class _Window(ArchComponent.Component): diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 52bf671659..1de87ed470 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -58,10 +58,10 @@ class ArchWorkbench(Workbench): def Initialize(self): import DraftTools,DraftGui,Arch_rc,Arch - self.archtools = ["Arch_Wall","Arch_Structure","Arch_Cell", + self.archtools = ["Arch_Wall","Arch_Structure", "Arch_Floor","Arch_Building","Arch_Site", - "Arch_Window","Arch_Axis", - "Arch_SectionPlane","Arch_Roof","Arch_Add","Arch_Remove"] + "Arch_Window","Arch_Roof","Arch_Axis", + "Arch_SectionPlane","Arch_Add","Arch_Remove"] self.drafttools = ["Draft_Line","Draft_Wire","Draft_Rectangle", "Draft_Polygon","Draft_Arc", "Draft_Circle","Draft_Dimension", @@ -100,6 +100,12 @@ class ArchWorkbench(Workbench): FreeCADGui.addWorkbench(ArchWorkbench) FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC") FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") -FreeCAD.addImportType("Collada (*.dae)","importDAE") -FreeCAD.addExportType("Collada (*.dae)","importDAE") +# check for pycollada +try: + import collada +except: + FreeCAD.Console.PrintError("pycollada not found, no collada support.\n") +else: + FreeCAD.addImportType("Collada (*.dae)","importDAE") + FreeCAD.addExportType("Collada (*.dae)","importDAE") diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index f4a8f8392f..7a0cf8ae07 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -108,7 +108,7 @@ def getIfcOpenShell(): return True def read(filename): - "Parses an IFC file with IfcOpenShell" + "Parses an IFC file" # parsing the IFC file t1 = time.time() @@ -186,7 +186,7 @@ def read(filename): IfcImport.CleanUp() else: - # use the internal python parser + # use only the internal python parser # getting walls for w in ifc.getEnt("IfcWallStandardCase"): From 1c1dbf0b2e6fb8f967e404b48f173b2ca782789b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 16:43:48 -0300 Subject: [PATCH 203/351] Fixed 0000708 - Draft DXF import --- src/Mod/Draft/importDXF.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index a03ec28aaf..97e01db7f2 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -1232,7 +1232,9 @@ def getWire(wire,nospline=False): points = [] for edge in edges: v1 = edge.Vertexes[0].Point - if (isinstance(edge.Curve,Part.Circle)): + if len(edge.Vertexes) < 2: + points.append((v1.x,v1.y,v1.z,None,None,0.0)) + elif (isinstance(edge.Curve,Part.Circle)): mp = fcgeo.findMidpoint(edge) v2 = edge.Vertexes[-1].Point c = edge.Curve.Center @@ -1251,14 +1253,12 @@ def getWire(wire,nospline=False): bul = -bul points.append((v1.x,v1.y,v1.z,None,None,bul)) elif (isinstance(edge.Curve,Part.BSplineCurve)) and (not nospline): - bul = 0.0 spline = getSplineSegs(edge) spline.pop() for p in spline: - points.append((p.x,p.y,p.z,None,None,bul)) + points.append((p.x,p.y,p.z,None,None,0.0)) else: - bul = 0.0 - points.append((v1.x,v1.y,v1.z,None,None,bul)) + points.append((v1.x,v1.y,v1.z,None,None,0.0)) if not fcgeo.isReallyClosed(wire): v = edges[-1].Vertexes[-1].Point points.append(fcvec.tup(v)) From 82265b4ea9929865f1ebb8a284230d21e2c94aca Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 17:43:57 -0300 Subject: [PATCH 204/351] Refining of Arch Roof tool --- src/Mod/Arch/ArchComponent.py | 2 -- src/Mod/Arch/ArchRoof.py | 21 ++++++++++++++++++--- src/Mod/Arch/ArchStructure.py | 2 ++ src/Mod/Arch/ArchWall.py | 2 ++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index b6065fa044..c9fa5a347e 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -260,8 +260,6 @@ class Component: "Other shapes that are appended to this wall") obj.addProperty("App::PropertyLinkList","Subtractions","Base", "Other shapes that are subtracted from this wall") - obj.addProperty("App::PropertyVector","Normal","Base", - "The normal extrusion direction of this wall (keep (0,0,0) for automatic normal)") obj.Proxy = self self.Type = "Component" self.Subvolume = None diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index 62850f243e..37d06b58e7 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -61,13 +61,30 @@ class _CommandRoof: sel = FreeCADGui.Selection.getSelectionEx() if sel: sel = sel[0] + obj = sel.Object if sel.HasSubObjects: if "Face" in sel.SubElementNames[0]: - obj = sel.Object idx = int(sel.SubElementNames[0][4:]) FreeCAD.ActiveDocument.openTransaction("Create Roof") makeRoof(obj,idx) FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + elif obj.isDerivedFrom("Part::Feature"): + if len(obj.Shape.Faces) == 1: + FreeCAD.ActiveDocument.openTransaction("Create Roof") + makeRoof(obj,1) + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + elif obj.isDerivedFrom("Part::Feature"): + if len(obj.Shape.Faces) == 1: + FreeCAD.ActiveDocument.openTransaction("Create Roof") + makeRoof(obj,1) + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + else: + FreeCAD.Console.PrintMessage("Unable to create a roof") + else: + FreeCAD.Console.PrintMessage("No object selected") class _Roof(ArchComponent.Component): "The Roof object" @@ -77,8 +94,6 @@ class _Roof(ArchComponent.Component): "The angle of this roof") obj.addProperty("App::PropertyInteger","Face","Base", "The face number of the base object used to build this roof") - obj.addProperty("App::PropertyLink","Base","Base", - "The base object this roof is built on") self.Type = "Structure" def execute(self,obj): diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 63d7b668c9..cd87115ebc 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -86,6 +86,8 @@ class _Structure(ArchComponent.Component): "The height or extrusion depth of this element. Keep 0 for automatic") obj.addProperty("App::PropertyLinkList","Axes","Base", "Axes systems this structure is built on") + obj.addProperty("App::PropertyVector","Normal","Base", + "The normal extrusion direction of this object (keep (0,0,0) for automatic normal)") self.Type = "Structure" def execute(self,obj): diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 108edabfc9..36c33e7a87 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -251,6 +251,8 @@ class _Wall(ArchComponent.Component): "The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid") obj.addProperty("App::PropertyEnumeration","Align","Base", "The alignment of this wall on its base object, if applicable") + obj.addProperty("App::PropertyVector","Normal","Base", + "The normal extrusion direction of this object (keep (0,0,0) for automatic normal)") obj.Align = ['Left','Right','Center'] self.Type = "Wall" obj.Width = 0.1 From 1b70aef0f2dda3db0639b706c48a2469688dc93c Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 19:01:01 -0300 Subject: [PATCH 205/351] Bugfixes in Arch --- src/Mod/Arch/ArchSectionPlane.py | 2 +- src/Mod/Arch/ArchVRM.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 886cbb3480..d1c1ada501 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -181,7 +181,7 @@ class _ArchDrawingView: if hasattr(obj,"Source"): if obj.Source: if obj.Source.Objects: - objs = Draft.getGroupContents(obj.Sourc.Objects) + objs = Draft.getGroupContents(obj.Source.Objects) svg = '' # generating SVG diff --git a/src/Mod/Arch/ArchVRM.py b/src/Mod/Arch/ArchVRM.py index c89776e62f..f7e5988abf 100644 --- a/src/Mod/Arch/ArchVRM.py +++ b/src/Mod/Arch/ArchVRM.py @@ -177,7 +177,8 @@ class Renderer: v = self.wp.getLocalCoords(v) verts.append(v) verts.append(verts[0]) - wires.append(Part.makePolygon(verts)) + if len(verts) > 2: + wires.append(Part.makePolygon(verts)) try: sh = ArchCommands.makeFace(wires) except: From 1de458a161a0cea2b28fb65ef9662764f448c2f8 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 19 May 2012 18:07:09 -0300 Subject: [PATCH 206/351] Allowed to drag&drop items on python groups too in tree --- src/Gui/Tree.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 03ca7cb2fc..2c5f0ea151 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -440,20 +440,39 @@ void TreeWidget::dropEvent(QDropEvent *event) ::getGroupOfObject(obj); if (par) { // allow an object to be in one group only - QString cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").removeObject(" + QString cmd; + if (par->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + // if this is a python group, call the method of its Proxy + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.removeObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") .arg(QString::fromAscii(doc->getName())) .arg(QString::fromAscii(par->getNameInDocument())) .arg(QString::fromAscii(obj->getNameInDocument())); + } else { + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").removeObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromAscii(doc->getName())) + .arg(QString::fromAscii(par->getNameInDocument())) + .arg(QString::fromAscii(obj->getNameInDocument())); + } Gui::Application::Instance->runPythonCode(cmd.toUtf8()); } // build Python command for execution - QString cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").addObject(" + QString cmd; + if (grp->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.addObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") .arg(QString::fromAscii(doc->getName())) .arg(QString::fromAscii(grp->getNameInDocument())) .arg(QString::fromAscii(obj->getNameInDocument())); + } else { + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").addObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromAscii(doc->getName())) + .arg(QString::fromAscii(grp->getNameInDocument())) + .arg(QString::fromAscii(obj->getNameInDocument())); + } Gui::Application::Instance->runPythonCode(cmd.toUtf8()); } gui->commitCommand(); From 30cdaf89430e065e75fd8057f23fac4892b31419 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 19 May 2012 18:18:02 -0300 Subject: [PATCH 207/351] Made Arch groups able to receive drops from the tree --- src/Mod/Arch/ArchBuilding.py | 19 +++++++++++++++++-- src/Mod/Arch/ArchFloor.py | 16 +++++++++++++++- src/Mod/Arch/ArchSite.py | 19 +++++++++++++++++-- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Mod/Arch/ArchBuilding.py b/src/Mod/Arch/ArchBuilding.py index 6a2cb2c33d..f8ed4e8ca3 100644 --- a/src/Mod/Arch/ArchBuilding.py +++ b/src/Mod/Arch/ArchBuilding.py @@ -68,12 +68,27 @@ class _Building: def __init__(self,obj): self.Type = "Building" obj.Proxy = self - + self.Object = obj + def execute(self,obj): - pass + self.Object = obj def onChanged(self,obj,prop): pass + + def addObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if not child in g: + g.append(child) + self.Object.Group = g + + def removeObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if child in g: + g.remove(child) + self.Object.Group = g class _ViewProviderBuilding: "A View Provider for the Building object" diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index f5b9d435e3..606395961d 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -71,13 +71,27 @@ class _Floor: "The height of this floor") self.Type = "Floor" obj.Proxy = self + self.Object = obj def execute(self,obj): - pass + self.Object = obj def onChanged(self,obj,prop): pass + def addObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if not child in g: + g.append(child) + self.Object.Group = g + + def removeObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if child in g: + g.remove(child) + self.Object.Group = g class _ViewProviderFloor: "A View Provider for the Cell object" diff --git a/src/Mod/Arch/ArchSite.py b/src/Mod/Arch/ArchSite.py index 5da538e5af..300fd09eff 100644 --- a/src/Mod/Arch/ArchSite.py +++ b/src/Mod/Arch/ArchSite.py @@ -68,13 +68,28 @@ class _Site: def __init__(self,obj): self.Type = "Site" obj.Proxy = self + self.Object = obj def execute(self,obj): - pass - + self.Object = obj + def onChanged(self,obj,prop): pass + def addObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if not child in g: + g.append(child) + self.Object.Group = g + + def removeObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if child in g: + g.remove(child) + self.Object.Group = g + class _ViewProviderSite: "A View Provider for the Site object" def __init__(self,vobj): From 6fd2aca5607d2f0deb723f7852df4938c02a3f74 Mon Sep 17 00:00:00 2001 From: msocorcim Date: Sun, 20 May 2012 23:00:23 -0400 Subject: [PATCH 208/351] Add new Mod/Mesh files to Makefile.am --- src/Mod/Mesh/Gui/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mod/Mesh/Gui/Makefile.am b/src/Mod/Mesh/Gui/Makefile.am index 46158d1e10..dd4405cd7c 100644 --- a/src/Mod/Mesh/Gui/Makefile.am +++ b/src/Mod/Mesh/Gui/Makefile.am @@ -35,6 +35,7 @@ libMeshGui_la_SOURCES=\ PropertyEditorMesh.cpp \ RemoveComponents.cpp \ RemoveComponents.h \ + Segmentation.cpp \ SoFCIndexedFaceSet.cpp \ SoFCMeshObject.cpp \ ViewProvider.cpp \ @@ -48,6 +49,7 @@ libMeshGui_la_SOURCES=\ include_HEADERS=\ PropertyEditorMesh.h \ + Segmentation.h \ SoFCIndexedFaceSet.h \ SoFCMeshObject.h \ ViewProvider.h \ From 82a985a77fbafbed2e20ebe99bc008ad2d2d5649 Mon Sep 17 00:00:00 2001 From: msocorcim Date: Sun, 20 May 2012 23:01:07 -0400 Subject: [PATCH 209/351] Replace Gui text View->Display mode with View->Document window --- src/Gui/CommandView.cpp | 2 +- src/Gui/DlgDisplayProperties.ui | 2 +- src/Gui/Language/FreeCAD.ts | 2 +- src/Gui/Language/FreeCAD_af.ts | 4 ++-- src/Gui/Language/FreeCAD_de.ts | 4 ++-- src/Gui/Language/FreeCAD_es.ts | 4 ++-- src/Gui/Language/FreeCAD_fi.ts | 4 ++-- src/Gui/Language/FreeCAD_fr.ts | 4 ++-- src/Gui/Language/FreeCAD_hr.ts | 4 ++-- src/Gui/Language/FreeCAD_hu.ts | 4 ++-- src/Gui/Language/FreeCAD_it.ts | 4 ++-- src/Gui/Language/FreeCAD_ja.ts | 4 ++-- src/Gui/Language/FreeCAD_nl.ts | 4 ++-- src/Gui/Language/FreeCAD_no.ts | 4 ++-- src/Gui/Language/FreeCAD_pl.ts | 4 ++-- src/Gui/Language/FreeCAD_pt.ts | 4 ++-- src/Gui/Language/FreeCAD_ru.ts | 4 ++-- src/Gui/Language/FreeCAD_se.ts | 4 ++-- src/Gui/Language/FreeCAD_uk.ts | 4 ++-- src/Gui/Language/FreeCAD_zh.ts | 4 ++-- src/Gui/TaskView/TaskAppearance.ui | 2 +- 21 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 1de74b6c30..712131d68b 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -1172,7 +1172,7 @@ StdViewDockUndockFullscreen::StdViewDockUndockFullscreen() : Command("Std_ViewDockUndockFullscreen") { sGroup = QT_TR_NOOP("Standard-View"); - sMenuText = QT_TR_NOOP("Display mode"); + sMenuText = QT_TR_NOOP("Document window"); sToolTipText= QT_TR_NOOP("Display the active view either in fullscreen, in undocked or docked mode"); sWhatsThis = "Std_ViewDockUndockFullscreen"; sStatusTip = QT_TR_NOOP("Display the active view either in fullscreen, in undocked or docked mode"); diff --git a/src/Gui/DlgDisplayProperties.ui b/src/Gui/DlgDisplayProperties.ui index 5143bf2a8a..58f4b62358 100644 --- a/src/Gui/DlgDisplayProperties.ui +++ b/src/Gui/DlgDisplayProperties.ui @@ -34,7 +34,7 @@ - Display mode: + Document window: diff --git a/src/Gui/Language/FreeCAD.ts b/src/Gui/Language/FreeCAD.ts index 3b452a8607..024b5a7f1b 100644 --- a/src/Gui/Language/FreeCAD.ts +++ b/src/Gui/Language/FreeCAD.ts @@ -5302,7 +5302,7 @@ You either have to finish or cancel the editing in the task panel.
- Display mode + Document window diff --git a/src/Gui/Language/FreeCAD_af.ts b/src/Gui/Language/FreeCAD_af.ts index 052ea4d8c1..4ba0e26ca1 100644 --- a/src/Gui/Language/FreeCAD_af.ts +++ b/src/Gui/Language/FreeCAD_af.ts @@ -5317,8 +5317,8 @@ You either have to finish or cancel the editing in the task panel. Standaardaansig - Display mode - Vertoningsmodus + Document window + Dokument venster Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_de.ts b/src/Gui/Language/FreeCAD_de.ts index be807a1b7e..79e5131c29 100644 --- a/src/Gui/Language/FreeCAD_de.ts +++ b/src/Gui/Language/FreeCAD_de.ts @@ -5325,8 +5325,8 @@ Sie müssen entweder den Bearbeitungsvorgang fertigstellen oder mittels des Aufg Standardansicht - Display mode - Anzeige-Modus + Document window + Dokumentfenster Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_es.ts b/src/Gui/Language/FreeCAD_es.ts index 173822aa00..089b96e95d 100644 --- a/src/Gui/Language/FreeCAD_es.ts +++ b/src/Gui/Language/FreeCAD_es.ts @@ -5323,8 +5323,8 @@ Tienes que finzalizar o cancelar la edición en el panel de tareas.Vista estándar - Display mode - Modo de visualización + Document window + Ventana de documento Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_fi.ts b/src/Gui/Language/FreeCAD_fi.ts index dab907d81d..ec9cde9a05 100644 --- a/src/Gui/Language/FreeCAD_fi.ts +++ b/src/Gui/Language/FreeCAD_fi.ts @@ -5314,8 +5314,8 @@ You either have to finish or cancel the editing in the task panel. Standardi-Näkymä - Display mode - Näyttötila + Document window + Asiakirjan ikkuna Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_fr.ts b/src/Gui/Language/FreeCAD_fr.ts index c65a10cdf9..f665da6bd2 100644 --- a/src/Gui/Language/FreeCAD_fr.ts +++ b/src/Gui/Language/FreeCAD_fr.ts @@ -5319,8 +5319,8 @@ You either have to finish or cancel the editing in the task panel. Vue standard - Display mode - Mode d'affichage + Document window + Fenêtre de document Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_hr.ts b/src/Gui/Language/FreeCAD_hr.ts index 790f209822..11e5c702ba 100644 --- a/src/Gui/Language/FreeCAD_hr.ts +++ b/src/Gui/Language/FreeCAD_hr.ts @@ -5311,8 +5311,8 @@ You either have to finish or cancel the editing in the task panel. Standardni pogled - Display mode - NaÄin prikaza + Document window + Dokument prozor Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_hu.ts b/src/Gui/Language/FreeCAD_hu.ts index cf6433c3a8..74d0db3b56 100644 --- a/src/Gui/Language/FreeCAD_hu.ts +++ b/src/Gui/Language/FreeCAD_hu.ts @@ -5318,8 +5318,8 @@ You either have to finish or cancel the editing in the task panel. Standard-nézet - Display mode - Megjelenítési mód + Document window + Dokumentum ablak Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_it.ts b/src/Gui/Language/FreeCAD_it.ts index 64b5bd7c3a..cb266b1d00 100644 --- a/src/Gui/Language/FreeCAD_it.ts +++ b/src/Gui/Language/FreeCAD_it.ts @@ -5325,8 +5325,8 @@ You either have to finish or cancel the editing in the task panel. Vista standard - Display mode - Modalità di visualizzazione + Document window + Finestra del documento Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_ja.ts b/src/Gui/Language/FreeCAD_ja.ts index 5773577fd4..0406284a60 100644 --- a/src/Gui/Language/FreeCAD_ja.ts +++ b/src/Gui/Language/FreeCAD_ja.ts @@ -5319,8 +5319,8 @@ You either have to finish or cancel the editing in the task panel. 標準ビュー - Display mode - 表示モード + Document window + ドキュメントウィンドウ Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_nl.ts b/src/Gui/Language/FreeCAD_nl.ts index 0a57b99f55..ea7ae833c4 100644 --- a/src/Gui/Language/FreeCAD_nl.ts +++ b/src/Gui/Language/FreeCAD_nl.ts @@ -5314,8 +5314,8 @@ You either have to finish or cancel the editing in the task panel. Standaard-aanzicht - Display mode - Weergavemodus + Document window + Documentvenster Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_no.ts b/src/Gui/Language/FreeCAD_no.ts index 948c209da5..56087e8fac 100644 --- a/src/Gui/Language/FreeCAD_no.ts +++ b/src/Gui/Language/FreeCAD_no.ts @@ -5315,8 +5315,8 @@ You either have to finish or cancel the editing in the task panel. Standardvisning - Display mode - Visningsmodus + Document window + Dokument-vinduet Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_pl.ts b/src/Gui/Language/FreeCAD_pl.ts index 064d5e00ea..0a428556ba 100644 --- a/src/Gui/Language/FreeCAD_pl.ts +++ b/src/Gui/Language/FreeCAD_pl.ts @@ -5305,8 +5305,8 @@ You either have to finish or cancel the editing in the task panel. Normalny widok - Display mode - Tryb wyÅ›wietlania + Document window + Okno dokumentu Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_pt.ts b/src/Gui/Language/FreeCAD_pt.ts index 2ed9d6bf6b..fd0cde9227 100644 --- a/src/Gui/Language/FreeCAD_pt.ts +++ b/src/Gui/Language/FreeCAD_pt.ts @@ -5307,8 +5307,8 @@ You either have to finish or cancel the editing in the task panel. Vista padrão - Display mode - Modo de exibição + Document window + Janela do documento Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_ru.ts b/src/Gui/Language/FreeCAD_ru.ts index 40667e37ac..b1e39e830f 100644 --- a/src/Gui/Language/FreeCAD_ru.ts +++ b/src/Gui/Language/FreeCAD_ru.ts @@ -5310,8 +5310,8 @@ You either have to finish or cancel the editing in the task panel. Стандартный вид - Display mode - Режим Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ + Document window + окно документа Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_se.ts b/src/Gui/Language/FreeCAD_se.ts index 1f51d82428..9b777ffac2 100644 --- a/src/Gui/Language/FreeCAD_se.ts +++ b/src/Gui/Language/FreeCAD_se.ts @@ -5324,8 +5324,8 @@ You either have to finish or cancel the editing in the task panel. Standardvy - Display mode - Visningsläge + Document window + Dokumentfönstret Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_uk.ts b/src/Gui/Language/FreeCAD_uk.ts index b9dbe90997..5e0b27cb6c 100644 --- a/src/Gui/Language/FreeCAD_uk.ts +++ b/src/Gui/Language/FreeCAD_uk.ts @@ -5325,8 +5325,8 @@ You either have to finish or cancel the editing in the task panel. Стандартні виглÑди - Display mode - Режим показу + Document window + вікно документа Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_zh.ts b/src/Gui/Language/FreeCAD_zh.ts index 18e102a1ee..a63f7f181a 100644 --- a/src/Gui/Language/FreeCAD_zh.ts +++ b/src/Gui/Language/FreeCAD_zh.ts @@ -5313,8 +5313,8 @@ You either have to finish or cancel the editing in the task panel. 标准视图 - Display mode - æ˜¾ç¤ºæ¨¡å¼ + Document window + æ–‡æ¡£çª—å£ Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/TaskView/TaskAppearance.ui b/src/Gui/TaskView/TaskAppearance.ui index 7955494699..e775af457c 100644 --- a/src/Gui/TaskView/TaskAppearance.ui +++ b/src/Gui/TaskView/TaskAppearance.ui @@ -33,7 +33,7 @@ - Display mode: + Document window: From 8ec91d29dd5604302ec4ce799e332cf91e61576c Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 14:08:57 +0200 Subject: [PATCH 210/351] Workaround for linker error with MSVC --- src/Gui/Tree.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 2c5f0ea151..ba3672d8cd 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -431,6 +431,7 @@ void TreeWidget::dropEvent(QDropEvent *event) // Open command App::Document* doc = grp->getDocument(); Gui::Document* gui = Gui::Application::Instance->getDocument(doc); + Base::Type DOGPython = Base::Type::fromName("App::DocumentObjectGroupPython"); gui->openCommand("Move object"); for (QList::Iterator it = items.begin(); it != items.end(); ++it) { // get document object @@ -441,7 +442,7 @@ void TreeWidget::dropEvent(QDropEvent *event) if (par) { // allow an object to be in one group only QString cmd; - if (par->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + if (par->getTypeId().isDerivedFrom(DOGPython)) { // if this is a python group, call the method of its Proxy cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.removeObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") @@ -460,7 +461,7 @@ void TreeWidget::dropEvent(QDropEvent *event) // build Python command for execution QString cmd; - if (grp->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + if (grp->getTypeId().isDerivedFrom(DOGPython)) { cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.addObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") .arg(QString::fromAscii(doc->getName())) From fc3a9903f832e636530e610624fadacff0e8a8d3 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 15:02:51 +0200 Subject: [PATCH 211/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.cpp | 26 +++++--------- src/Mod/Mesh/App/Core/Segmentation.h | 28 ++++++++++----- src/Mod/Mesh/App/Mesh.cpp | 50 +++++++------------------- src/Mod/Mesh/App/MeshPy.xml | 6 ++-- src/Mod/Mesh/App/MeshPyImp.cpp | 7 ++-- src/Mod/Mesh/Gui/Segmentation.cpp | 2 +- src/Mod/Mesh/Gui/Segmentation.ui | 23 ++++++++++-- 7 files changed, 67 insertions(+), 75 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 2e86fdb176..01d99fb11f 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -108,22 +108,12 @@ bool MeshCurvatureCylindricalSegment::TestFacet (const MeshFacet &rclFacet) cons { for (int i=0; i<3; i++) { const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; - if (ci.fMaxCurvature > ci.fMinCurvature) { - // convexe - if (fabs(ci.fMinCurvature) > tolerance) - return false; - float diff = ci.fMaxCurvature - curvature; - if (fabs(diff) > tolerance) - return false; - } - else { - // concave - if (fabs(ci.fMaxCurvature) > tolerance) - return false; - float diff = ci.fMinCurvature + curvature; - if (fabs(diff) > tolerance) - return false; - } + float fMax = std::max(fabs(ci.fMaxCurvature), fabs(ci.fMinCurvature)); + float fMin = std::min(fabs(ci.fMaxCurvature), fabs(ci.fMinCurvature)); + if (fMin > toleranceMin) + return false; + if (fabs(fMax - curvature) > toleranceMax) + return false; } return true; @@ -151,9 +141,9 @@ bool MeshCurvatureFreeformSegment::TestFacet (const MeshFacet &rclFacet) const { for (int i=0; i<3; i++) { const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; - if (fabs(ci.fMinCurvature-c2) > tolerance) + if (fabs(ci.fMinCurvature-c2) > toleranceMin) return false; - if (fabs(ci.fMaxCurvature-c1) > tolerance) + if (fabs(ci.fMaxCurvature-c1) > toleranceMax) return false; } diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index 561385c1c1..c894147adf 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -84,53 +84,63 @@ protected: class MeshExport MeshCurvatureSurfaceSegment : public MeshSurfaceSegment { public: - MeshCurvatureSurfaceSegment(const std::vector& ci, unsigned long minFacets, float tol) - : MeshSurfaceSegment(minFacets), info(ci), tolerance(tol) {} + MeshCurvatureSurfaceSegment(const std::vector& ci, unsigned long minFacets) + : MeshSurfaceSegment(minFacets), info(ci) {} protected: const std::vector& info; - float tolerance; }; class MeshExport MeshCurvaturePlanarSegment : public MeshCurvatureSurfaceSegment { public: MeshCurvaturePlanarSegment(const std::vector& ci, unsigned long minFacets, float tol) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol) {} + : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float tolerance; }; class MeshExport MeshCurvatureCylindricalSegment : public MeshCurvatureSurfaceSegment { public: - MeshCurvatureCylindricalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + MeshCurvatureCylindricalSegment(const std::vector& ci, unsigned long minFacets, + float tolMin, float tolMax, float radius) + : MeshCurvatureSurfaceSegment(ci, minFacets), toleranceMin(tolMin), toleranceMax(tolMax) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; private: float curvature; + float toleranceMin; + float toleranceMax; }; class MeshExport MeshCurvatureSphericalSegment : public MeshCurvatureSurfaceSegment { public: MeshCurvatureSphericalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; private: float curvature; + float tolerance; }; class MeshExport MeshCurvatureFreeformSegment : public MeshCurvatureSurfaceSegment { public: - MeshCurvatureFreeformSegment(const std::vector& ci, unsigned long minFacets, float tol, float c1, float c2) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol), c1(c1), c2(c2) {} + MeshCurvatureFreeformSegment(const std::vector& ci, unsigned long minFacets, + float tolMin, float tolMax, float c1, float c2) + : MeshCurvatureSurfaceSegment(ci, minFacets), c1(c1), c2(c2), + toleranceMin(tolMin), toleranceMax(tolMax) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; private: float c1, c2; + float toleranceMin; + float toleranceMax; }; class MeshExport MeshSurfaceVisitor : public MeshFacetVisitor diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index 89f85856ad..dec5da73bc 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -44,6 +44,7 @@ #include "Core/TopoAlgorithm.h" #include "Core/Evaluation.h" #include "Core/Degeneration.h" +#include "Core/Segmentation.h" #include "Core/SetOperations.h" #include "Core/Visitor.h" @@ -1426,48 +1427,21 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons float dev, unsigned long minFacets) const { std::vector segm; - unsigned long startFacet; if (this->_kernel.CountFacets() == 0) return segm; - // reset VISIT flags - MeshCore::MeshAlgorithm cAlgo(this->_kernel); - if (aSegment.isEmpty()) { - cAlgo.ResetFacetFlag(MeshCore::MeshFacet::VISIT); + MeshCore::MeshSegmentAlgorithm finder(this->_kernel); + MeshCore::MeshDistanceSurfaceSegment* surf; + surf = new MeshCore::MeshDistancePlanarSegment(this->_kernel, minFacets, dev); + std::vector surfaces; + surfaces.push_back(surf); + finder.FindSegments(surfaces); + + const std::vector& data = surf->GetSegments(); + for (std::vector::const_iterator it = data.begin(); it != data.end(); ++it) { + segm.push_back(Segment(const_cast(this), *it, false)); } - else { - cAlgo.SetFacetFlag(MeshCore::MeshFacet::VISIT); - cAlgo.ResetFacetsFlag(aSegment.getIndices(), MeshCore::MeshFacet::VISIT); - } - - const MeshCore::MeshFacetArray& rFAry = this->_kernel.GetFacets(); - MeshCore::MeshFacetArray::_TConstIterator iTri = rFAry.begin(); - MeshCore::MeshFacetArray::_TConstIterator iBeg = rFAry.begin(); - MeshCore::MeshFacetArray::_TConstIterator iEnd = rFAry.end(); - - // start from the first not visited facet - cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); - iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), - MeshCore::MeshFacet::VISIT)); - startFacet = iTri - iBeg; - - while (startFacet != ULONG_MAX) { - // collect all facets of the same geometry - std::vector indices; - indices.push_back(startFacet); - MeshCore::MeshPlaneVisitor pv(this->_kernel, startFacet, dev, indices); - this->_kernel.VisitNeighbourFacets(pv, startFacet); - - iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), - MeshCore::MeshFacet::VISIT)); - if (iTri < iEnd) - startFacet = iTri - iBeg; - else - startFacet = ULONG_MAX; - if (indices.size() > minFacets) - segm.push_back(Segment(const_cast(this), indices, false)); - } - + delete surf; return segm; } diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index f29a59730a..116979807f 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -382,10 +382,10 @@ plane if none of its neighours is coplanar. getSegmentsByCurvature(list) -> list The argument list gives a list if tuples where it defines the preferred maximum curvature, -the preferred minumum curvature, the tolerance and the number of minimum faces for the segment. +the preferred minumum curvature, the tolerances and the number of minimum faces for the segment. Example: -c=(1.0, 0.0, 0.1, 500) # search for a cylinder with radius 1.0 -p=(0.0, 0.0, 0.1, 500) # search for a plane +c=(1.0, 0.0, 0.1, 0.1, 500) # search for a cylinder with radius 1.0 +p=(0.0, 0.0, 0.1, 0.1, 500) # search for a plane mesh.getSegmentsByCurvature([c,p]) diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index dd1f0e3e10..a2a1e6302d 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -1399,9 +1399,10 @@ PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) Py::Tuple t(*it); float c1 = (float)Py::Float(t[0]); float c2 = (float)Py::Float(t[1]); - float tol = (float)Py::Float(t[2]); - int num = (int)Py::Int(t[3]); - segm.push_back(new MeshCore::MeshCurvatureFreeformSegment(meshCurv.GetCurvature(), num, tol, c1, c2)); + float tol1 = (float)Py::Float(t[2]); + float tol2 = (float)Py::Float(t[3]); + int num = (int)Py::Int(t[4]); + segm.push_back(new MeshCore::MeshCurvatureFreeformSegment(meshCurv.GetCurvature(), num, tol1, tol2, c1, c2)); } finder.FindSegments(segm); diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp index 962d65f2e5..223479c569 100644 --- a/src/Mod/Mesh/Gui/Segmentation.cpp +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -76,7 +76,7 @@ void Segmentation::accept() std::vector segm; if (ui->groupBoxCyl->isChecked()) { segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment - (meshCurv.GetCurvature(), ui->numCyl->value(), ui->tolCyl->value(), ui->radCyl->value())); + (meshCurv.GetCurvature(), ui->numCyl->value(), ui->tol1Cyl->value(), ui->tol2Cyl->value(), ui->radCyl->value())); } if (ui->groupBoxSph->isChecked()) { segm.push_back(new MeshCore::MeshCurvatureSphericalSegment diff --git a/src/Mod/Mesh/Gui/Segmentation.ui b/src/Mod/Mesh/Gui/Segmentation.ui index 129c89873c..b6ce13bd86 100644 --- a/src/Mod/Mesh/Gui/Segmentation.ui +++ b/src/Mod/Mesh/Gui/Segmentation.ui @@ -106,12 +106,12 @@ - Tolerance + Tolerance (Flat) - + 0.100000000000000 @@ -121,13 +121,30 @@ + + + Tolerance (Curved) + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + Minimum number of faces - + 100000 From 72b922a2349bbc2a73174461c80303107a025430 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 15:53:46 +0200 Subject: [PATCH 212/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.h | 6 ++++++ src/Mod/Mesh/Gui/Segmentation.cpp | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index c894147adf..1b29f4bff9 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -41,6 +41,7 @@ public: : minFacets(minFacets) {} virtual ~MeshSurfaceSegment() {} virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; + virtual const char* GetType() const = 0; virtual void Initialize(unsigned long); virtual void AddFacet(const MeshFacet& rclFacet); void AddSegment(const std::vector&); @@ -70,6 +71,7 @@ public: MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); virtual ~MeshDistancePlanarSegment(); bool TestFacet (const MeshFacet& rclFacet) const; + const char* GetType() const { return "Plane"; } void Initialize(unsigned long); void AddFacet(const MeshFacet& rclFacet); @@ -97,6 +99,7 @@ public: MeshCurvaturePlanarSegment(const std::vector& ci, unsigned long minFacets, float tol) : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Plane"; } private: float tolerance; @@ -109,6 +112,7 @@ public: float tolMin, float tolMax, float radius) : MeshCurvatureSurfaceSegment(ci, minFacets), toleranceMin(tolMin), toleranceMax(tolMax) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Cylinder"; } private: float curvature; @@ -122,6 +126,7 @@ public: MeshCurvatureSphericalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Sphere"; } private: float curvature; @@ -136,6 +141,7 @@ public: : MeshCurvatureSurfaceSegment(ci, minFacets), c1(c1), c2(c2), toleranceMin(tolMin), toleranceMax(tolMax) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Freeform"; } private: float c1, c2; diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp index 223479c569..de2b81d48e 100644 --- a/src/Mod/Mesh/Gui/Segmentation.cpp +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -24,12 +24,14 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include #endif #include "Segmentation.h" #include "ui_Segmentation.h" #include #include +#include #include #include @@ -89,18 +91,32 @@ void Segmentation::accept() finder.FindSegments(segm); App::Document* document = App::GetApplication().getActiveDocument(); + document->openTransaction("Segmentation"); + + std::string internalname = "Segments_"; + internalname += myMesh->getNameInDocument(); + App::DocumentObjectGroup* group = static_cast(document->addObject + ("App::DocumentObjectGroup", internalname.c_str())); + std::string labelname = "Segments "; + labelname += myMesh->Label.getValue(); + group->Label.setValue(labelname); for (std::vector::iterator it = segm.begin(); it != segm.end(); ++it) { const std::vector& data = (*it)->GetSegments(); for (std::vector::const_iterator jt = data.begin(); jt != data.end(); ++jt) { Mesh::MeshObject* segment = mesh->meshFromSegment(*jt); - Mesh::Feature* feaSegm = static_cast(document->addObject("Mesh::Feature", "Segment")); + Mesh::Feature* feaSegm = static_cast(group->addObject("Mesh::Feature", "Segment")); Mesh::MeshObject* feaMesh = feaSegm->Mesh.startEditing(); feaMesh->swap(*segment); feaSegm->Mesh.finishEditing(); delete segment; + + std::stringstream label; + label << feaSegm->Label.getValue() << " (" << (*it)->GetType() << ")"; + feaSegm->Label.setValue(label.str()); } delete (*it); } + document->commitTransaction(); } void Segmentation::changeEvent(QEvent *e) From f33a6b90a8779ac72742fb6b77da96394b291006 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 18:27:30 +0200 Subject: [PATCH 213/351] 0000712: Cad Navigation Zoom with Ctrl + causes shapes to pan off screen --- src/Gui/CommandView.cpp | 16 +++------------- src/Gui/NavigationStyle.cpp | 10 ++++++++++ src/Gui/NavigationStyle.h | 2 ++ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 1de74b6c30..525d7c266f 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -59,6 +59,7 @@ #include "DemoMode.h" #include "TextureMapping.h" #include "Utilities.h" +#include "NavigationStyle.h" #include #include @@ -1817,13 +1818,7 @@ void StdViewZoomIn::activated(int iMsg) View3DInventor* view = qobject_cast(getMainWindow()->activeWindow()); if ( view ) { View3DInventorViewer* viewer = view->getViewer(); - - // send an event to the GL widget to use the internal View3DInventorViewer::zoom() method - // do only one step to zoom in - SoMouseButtonEvent e; - e.setButton(SoMouseButtonEvent::BUTTON5); - e.setState(SoMouseButtonEvent::DOWN); - viewer->sendSoEvent(&e); + viewer->navigationStyle()->zoomIn(); } } @@ -1857,12 +1852,7 @@ void StdViewZoomOut::activated(int iMsg) View3DInventor* view = qobject_cast(getMainWindow()->activeWindow()); if (view) { View3DInventorViewer* viewer = view->getViewer(); - // send an event to the GL widget to use the internal View3DInventorViewer::zoom() method - // do only one step to zoom out - SoMouseButtonEvent e; - e.setButton(SoMouseButtonEvent::BUTTON4); - e.setState(SoMouseButtonEvent::DOWN); - viewer->sendSoEvent(&e); + viewer->navigationStyle()->zoomOut(); } } diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index 192cb7ae5a..30f5ecf402 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -721,6 +721,16 @@ void NavigationStyle::zoomByCursor(const SbVec2f & thispos, const SbVec2f & prev zoom(viewer->getCamera(), (thispos[1] - prevpos[1]) * 10.0f/*20.0f*/); } +void NavigationStyle::zoomIn() +{ + zoom(viewer->getCamera(), -this->zoomStep); +} + +void NavigationStyle::zoomOut() +{ + zoom(viewer->getCamera(), this->zoomStep); +} + void NavigationStyle::doZoom(SoCamera* camera, SbBool forward, const SbVec2f& pos) { SbBool zoomAtCur = this->zoomAtCursor; diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 7644a73403..b6d4e20e66 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -115,6 +115,8 @@ public: void setZoomStep(float); void setZoomAtCursor(SbBool); SbBool isZoomAtCursor() const; + void zoomIn(); + void zoomOut(); void updateAnimation(); void redraw(); From e607ddf55f03f03902a54b181a21c928ed63115e Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 21 May 2012 22:35:18 -0300 Subject: [PATCH 214/351] unified yorik's email --- src/Mod/Draft/DraftGui.py | 2 +- src/Mod/Draft/Init.py | 2 +- src/Mod/Draft/InitGui.py | 2 +- src/Mod/Draft/draftlibs/fcgeo.py | 2 +- src/Mod/Draft/draftlibs/fcvec.py | 2 +- src/Mod/Draft/importDXF.py | 4 ++-- src/Mod/Draft/importOCA.py | 4 ++-- src/Mod/Draft/importSVG.py | 2 +- src/Mod/Draft/macros.py | 2 +- src/Tools/offlinedoc/buildpdf.py | 2 +- src/Tools/offlinedoc/buildqhelp.py | 2 +- src/Tools/offlinedoc/buildwikiindex.py | 2 +- src/Tools/offlinedoc/downloadwiki.py | 2 +- src/Tools/updateTranslations.py | 2 +- src/Tools/wiki2qhelp.py | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 02c6c57d4a..752abb76bc 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/Init.py b/src/Mod/Draft/Init.py index 5069e5fd67..47fd3dc985 100644 --- a/src/Mod/Draft/Init.py +++ b/src/Mod/Draft/Init.py @@ -1,6 +1,6 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 1bcbadbc8c..84d0b9b868 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -1,6 +1,6 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/draftlibs/fcgeo.py index bf9f53e185..ccacbf62c9 100755 --- a/src/Mod/Draft/draftlibs/fcgeo.py +++ b/src/Mod/Draft/draftlibs/fcgeo.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * #* Copyright (c) 2009, 2010 * -#* Yorik van Havre , Ken Cline * +#* Yorik van Havre , Ken Cline * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/draftlibs/fcvec.py b/src/Mod/Draft/draftlibs/fcvec.py index 0f3358cfc7..1f10a2c7ea 100644 --- a/src/Mod/Draft/draftlibs/fcvec.py +++ b/src/Mod/Draft/draftlibs/fcvec.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * #* Copyright (c) 2009, 2010 * -#* Yorik van Havre , Ken Cline * +#* Yorik van Havre , Ken Cline * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 97e01db7f2..2c0474f8ed 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -3,7 +3,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (GPL) * @@ -24,7 +24,7 @@ #*************************************************************************** __title__="FreeCAD Draft Workbench - DXF importer/exporter" -__author__ = "Yorik van Havre " +__author__ = "Yorik van Havre " __url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"] ''' diff --git a/src/Mod/Draft/importOCA.py b/src/Mod/Draft/importOCA.py index 6324ce7100..58131d8300 100644 --- a/src/Mod/Draft/importOCA.py +++ b/src/Mod/Draft/importOCA.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU General Public License (GPL) * @@ -22,7 +22,7 @@ #*************************************************************************** __title__="FreeCAD Draft Workbench - OCA importer/exporter" -__author__ = "Yorik van Havre " +__author__ = "Yorik van Havre " __url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"] ''' diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index 5de678d519..b49d4735c7 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/macros.py b/src/Mod/Draft/macros.py index a2668dad8c..2b106d19fc 100644 --- a/src/Mod/Draft/macros.py +++ b/src/Mod/Draft/macros.py @@ -1,6 +1,6 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/buildpdf.py b/src/Tools/offlinedoc/buildpdf.py index ff9f53a15d..c6dbf246fd 100755 --- a/src/Tools/offlinedoc/buildpdf.py +++ b/src/Tools/offlinedoc/buildpdf.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/buildqhelp.py b/src/Tools/offlinedoc/buildqhelp.py index 4325ed9152..77fa1bcaef 100755 --- a/src/Tools/offlinedoc/buildqhelp.py +++ b/src/Tools/offlinedoc/buildqhelp.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/buildwikiindex.py b/src/Tools/offlinedoc/buildwikiindex.py index f7cee86c8b..e685aed48a 100755 --- a/src/Tools/offlinedoc/buildwikiindex.py +++ b/src/Tools/offlinedoc/buildwikiindex.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/downloadwiki.py b/src/Tools/offlinedoc/downloadwiki.py index 50f88a2eb4..4fc0bdadf9 100755 --- a/src/Tools/offlinedoc/downloadwiki.py +++ b/src/Tools/offlinedoc/downloadwiki.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/updateTranslations.py b/src/Tools/updateTranslations.py index 5e3e991beb..695a2f6335 100755 --- a/src/Tools/updateTranslations.py +++ b/src/Tools/updateTranslations.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Library General Public License (LGPL) * diff --git a/src/Tools/wiki2qhelp.py b/src/Tools/wiki2qhelp.py index 09c47139aa..dc52f38152 100755 --- a/src/Tools/wiki2qhelp.py +++ b/src/Tools/wiki2qhelp.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Library General Public License (LGPL) * From 7086b80cb3ffd322ef561fdf174acfe4dcf85f33 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 11:45:40 -0300 Subject: [PATCH 215/351] Renamed Draft fcvec and fcgeo modules Draft/draftlibs/fcvec becomes Draft/DraftVecUtils Draft/draftlibs/fcgeo becomes Draft/DraftGeomUtils --- src/Doc/sphinx/Draft.rst | 13 +- src/Mod/Arch/ArchAxis.py | 4 +- src/Mod/Arch/ArchCommands.py | 16 +- src/Mod/Arch/ArchRoof.py | 14 +- src/Mod/Arch/ArchSectionPlane.py | 8 +- src/Mod/Arch/ArchStructure.py | 12 +- src/Mod/Arch/ArchVRM.py | 29 +- src/Mod/Arch/ArchWall.py | 42 ++- src/Mod/Arch/ArchWindow.py | 12 +- src/Mod/Arch/importIFC.py | 5 +- src/Mod/Arch/importOBJ.py | 5 +- src/Mod/Draft/CMakeLists.txt | 4 +- src/Mod/Draft/Draft.py | 202 +++++++------- .../{draftlibs/fcgeo.py => DraftGeomUtils.py} | 0 src/Mod/Draft/DraftSnap.py | 42 ++- src/Mod/Draft/DraftTools.py | 251 +++++++++--------- src/Mod/Draft/DraftTrackers.py | 49 ++-- .../{draftlibs/fcvec.py => DraftVecUtils.py} | 0 src/Mod/Draft/Makefile.am | 4 +- src/Mod/Draft/WorkingPlane.py | 33 ++- src/Mod/Draft/importDXF.py | 70 ++--- src/Mod/Draft/importOCA.py | 13 +- src/Mod/Draft/importSVG.py | 32 ++- src/WindowsInstaller/ModDraft.wxi | 4 +- 24 files changed, 413 insertions(+), 451 deletions(-) rename src/Mod/Draft/{draftlibs/fcgeo.py => DraftGeomUtils.py} (100%) rename src/Mod/Draft/{draftlibs/fcvec.py => DraftVecUtils.py} (100%) diff --git a/src/Doc/sphinx/Draft.rst b/src/Doc/sphinx/Draft.rst index 2b41017809..4479028b14 100644 --- a/src/Doc/sphinx/Draft.rst +++ b/src/Doc/sphinx/Draft.rst @@ -12,10 +12,15 @@ The Draft module offer several convenient functions to work with simple objects. .. automodule:: DraftSnap :members: -The draftlibs contain two submodules, widely used throughout the Draft module: fcvec, which contains useful methods for dealing with vectors, and fcgeo, which offers many tools for working with Part shape objects. +The Draft module also contains two submodules, widely used throughout the Draft and Arch modules: DraftVecUtils, which contains useful methods for dealing with vectors, and DraftGeomUtils, which offers many tools for working with OpenCascade geometry. -.. automodule:: draftlibs.fcvec +.. automodule:: DraftVecUtils :members: -.. automodule:: draftlibs.fcgeo - :members: \ No newline at end of file +.. automodule:: DraftGeomUtils + :members: + +The Draft module also features a module that contains trackers, special objects made to display 3D temporary geometry in the 3D scene, that have no real existence in the FreeCAD document. + +.. automodule:: DraftTrackers + :members: diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index a56a50ff26..37cdf9f545 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -21,9 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,math - -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,math,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore, QtGui from pivy import coin diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 5802e5e0a6..2ebfad0d0b 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -170,7 +169,7 @@ def makeFace(wires,method=2,cleanup=False): # cleaning up rubbish in wires if cleanup: for i in range(len(wires)): - wires[i] = fcgeo.removeInterVertices(wires[i]) + wires[i] = DraftGeomUtils.removeInterVertices(wires[i]) print "garbage removed" for w in wires: # we assume that the exterior boundary is that one with @@ -210,8 +209,7 @@ def meshToShape(obj,mark=True): mark is True (default), non-solid objects will be marked in red''' name = obj.Name - import Part,MeshPart - from draftlibs import fcgeo + import Part, MeshPart, DraftGeomUtils if "Mesh" in obj.PropertiesList: faces = [] mesh = obj.Mesh @@ -249,12 +247,12 @@ def meshToShape(obj,mark=True): def removeShape(objs,mark=True): '''takes an arch object (wall or structure) built on a cubic shape, and removes the inner shape, keeping its length, width and height as parameters.''' - from draftlibs import fcgeo + import DraftGeomUtils if not isinstance(objs,list): objs = [objs] for obj in objs: - if fcgeo.isCubic(obj.Shape): - dims = fcgeo.getCubicDimensions(obj.Shape) + if DraftGeomUtils.isCubic(obj.Shape): + dims = DraftGeomUtils.getCubicDimensions(obj.Shape) if dims: name = obj.Name tp = Draft.getType(obj) @@ -270,7 +268,7 @@ def removeShape(objs,mark=True): length = dims[1] width = dims[2] v1 = Vector(length/2,0,0) - v2 = fcvec.neg(v1) + v2 = DraftVecUtils.neg(v1) v1 = dims[0].multVec(v1) v2 = dims[0].multVec(v2) line = Draft.makeLine(v1,v2) diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index 37d06b58e7..31515afbc8 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent, DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -104,8 +103,7 @@ class _Roof(ArchComponent.Component): self.createGeometry(obj) def createGeometry(self,obj): - import Part,math - from draftlibs import fcgeo + import Part, math, DraftGeomUtils pl = obj.Placement if obj.Base and obj.Face and obj.Angle: @@ -116,14 +114,14 @@ class _Roof(ArchComponent.Component): c = round(math.tan(math.radians(obj.Angle)),Draft.precision()) norm = f.normalAt(0,0) d = f.BoundBox.DiagonalLength - edges = fcgeo.sortEdges(f.Edges) + edges = DraftGeomUtils.sortEdges(f.Edges) l = len(edges) edges.append(edges[0]) shps = [] for i in range(l): - v = fcgeo.vec(fcgeo.angleBisection(edges[i],edges[i+1])) + v = DraftGeomUtils.vec(DraftGeomUtils.angleBisection(edges[i],edges[i+1])) v.normalize() - bis = v.getAngle(fcgeo.vec(edges[i])) + bis = v.getAngle(DraftGeomUtils.vec(edges[i])) delta = 1/math.cos(bis) v.multiply(delta) n = (FreeCAD.Vector(norm)).multiply(c) @@ -137,7 +135,7 @@ class _Roof(ArchComponent.Component): c = c.removeSplitter() if not c.isNull(): obj.Shape = c - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderRoof(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index d1c1ada501..59c8023827 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -21,11 +21,10 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,Drawing,math,Draft,ArchCommands +import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,Drawing,math,Draft,ArchCommands, DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore from pivy import coin -from draftlibs import fcvec class _CommandSectionPlane: @@ -176,8 +175,7 @@ class _ArchDrawingView: def updateSVG(self, obj,join=False): "encapsulates a svg fragment into a transformation node" - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils if hasattr(obj,"Source"): if obj.Source: if obj.Source.Objects: @@ -207,7 +205,7 @@ class _ArchDrawingView: base = shape.pop() for sh in shapes: base = base.fuse(sh) - svgf = Drawing.projectToSVG(base,fcvec.neg(direction)) + svgf = Drawing.projectToSVG(base,DraftVecUtils.neg(direction)) if svgf: svgf = svgf.replace('stroke-width="0.35"','stroke-width="' + str(linewidth) + 'px"') svg += svgf diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index cd87115ebc..2327ad7cac 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -99,7 +98,7 @@ class _Structure(ArchComponent.Component): def getAxisPoints(self,obj): "returns the gridpoints of linked axes" - from draftlibs import fcgeo + import DraftGeomUtils pts = [] if len(obj.Axes) == 1: for e in obj.Axes[0].Shape.Edges: @@ -109,12 +108,11 @@ class _Structure(ArchComponent.Component): set2 = obj.Axes[1].Shape.Edges for e1 in set1: for e2 in set2: - pts.extend(fcgeo.findIntersection(e1,e2)) + pts.extend(DraftGeomUtils.findIntersection(e1,e2)) return pts def createGeometry(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils # getting default values height = normal = None if obj.Length: @@ -187,7 +185,7 @@ class _Structure(ArchComponent.Component): obj.Shape = Part.makeCompound(fsh) else: obj.Shape = base - if not fcgeo.isNull(pl): obj.Placement = pl + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderStructure(ArchComponent.ViewProviderComponent): "A View Provider for the Structure object" diff --git a/src/Mod/Arch/ArchVRM.py b/src/Mod/Arch/ArchVRM.py index f7e5988abf..2de8ad0b3b 100644 --- a/src/Mod/Arch/ArchVRM.py +++ b/src/Mod/Arch/ArchVRM.py @@ -23,8 +23,7 @@ "The FreeCAD Arch Vector Rendering Module" -import FreeCAD,math,Part,ArchCommands -from draftlibs import fcvec,fcgeo +import FreeCAD,math,Part,ArchCommands,DraftVecUtils,DraftGeomUtils DEBUG = True # if we want debug messages MAXLOOP = 10 # the max number of loop before abort @@ -171,7 +170,7 @@ class Renderer: norm = face[0].normalAt(0,0) for w in face[0].Wires: verts = [] - edges = fcgeo.sortEdges(w.Edges) + edges = DraftGeomUtils.sortEdges(w.Edges) for e in edges: v = e.Vertexes[0].Point v = self.wp.getLocalCoords(v) @@ -196,7 +195,7 @@ class Renderer: wires = [] for w in face[0].Wires: verts = [] - edges = fcgeo.sortEdges(w.Edges) + edges = DraftGeomUtils.sortEdges(w.Edges) for e in edges: v = e.Vertexes[0].Point verts.append(FreeCAD.Vector(v.x,v.y,0)) @@ -239,11 +238,11 @@ class Renderer: FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)] for c in corners: dv = c.sub(placement.Base) - um1 = fcvec.project(dv,self.wp.u).Length + um1 = DraftVecUtils.project(dv,self.wp.u).Length um = max(um,um1) - vm1 = fcvec.project(dv,self.wp.v).Length + vm1 = DraftVecUtils.project(dv,self.wp.v).Length vm = max(vm,vm1) - wm1 = fcvec.project(dv,self.wp.axis).Length + wm1 = DraftVecUtils.project(dv,self.wp.axis).Length wm = max(wm,wm1) p1 = FreeCAD.Vector(-um,vm,0) p2 = FreeCAD.Vector(um,vm,0) @@ -252,7 +251,7 @@ class Renderer: cutface = Part.makePolygon([p1,p2,p3,p4,p1]) cutface = Part.Face(cutface) cutface.Placement = placement - cutnormal = fcvec.scaleTo(self.wp.axis,wm) + cutnormal = DraftVecUtils.scaleTo(self.wp.axis,wm) cutvolume = cutface.extrude(cutnormal) shapes = [] faces = [] @@ -265,7 +264,7 @@ class Renderer: faces.append([f]+sh[1:]) sec = sol.section(cutface) if sec.Edges: - wires = fcgeo.findWires(sec.Edges) + wires = DraftGeomUtils.findWires(sec.Edges) for w in wires: sec = Part.Face(w) sections.append([sec,fill]) @@ -313,7 +312,7 @@ class Renderer: # even so, faces can still overlap if their edges cross each other for e1 in face1[0].Edges: for e2 in face2[0].Edges: - if fcgeo.findIntersection(e1,e2): + if DraftGeomUtils.findIntersection(e1,e2): return True return False @@ -354,8 +353,8 @@ class Renderer: front = 0 for v in face1[0].Vertexes: dv = v.Point.sub(face2[0].Vertexes[0].Point) - dv = fcvec.project(dv,norm) - if fcvec.isNull(dv): + dv = DraftVecUtils.project(dv,norm) + if DraftVecUtils.isNull(dv): behind += 1 front += 1 else: @@ -377,8 +376,8 @@ class Renderer: front = 0 for v in face2[0].Vertexes: dv = v.Point.sub(face1[0].Vertexes[0].Point) - dv = fcvec.project(dv,norm) - if fcvec.isNull(dv): + dv = DraftVecUtils.project(dv,norm) + if DraftVecUtils.isNull(dv): behind += 1 front += 1 else: @@ -545,7 +544,7 @@ class Renderer: def getPathData(self,w): "Returns a SVG path data string from a 2D wire" - edges = fcgeo.sortEdges(w.Edges) + edges = DraftGeomUtils.sortEdges(w.Edges) v = edges[0].Vertexes[0].Point svg = 'M '+ str(v.x) +' '+ str(v.y) + ' ' for e in edges: diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 36c33e7a87..c26125136d 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -180,13 +179,13 @@ class _CommandWall: n = FreeCAD.DraftWorkingPlane.axis bv = point.sub(b) dv = bv.cross(n) - dv = fcvec.scaleTo(dv,self.Width/2) + dv = DraftVecUtils.scaleTo(dv,self.Width/2) if self.Align == "Center": self.tracker.update([b,point]) elif self.Align == "Left": self.tracker.update([b.add(dv),point.add(dv)]) else: - dv = fcvec.neg(dv) + dv = DraftVecUtils.neg(dv) self.tracker.update([b.add(dv),point.add(dv)]) def taskbox(self): @@ -275,10 +274,10 @@ class _Wall(ArchComponent.Component): f = w f = Part.Face(f) n = f.normalAt(0,0) - v1 = fcvec.scaleTo(n,width) + v1 = DraftVecUtils.scaleTo(n,width) f.translate(v1) - v2 = fcvec.neg(v1) - v2 = fcvec.scale(v1,-2) + v2 = DraftVecUtils.neg(v1) + v2 = DraftVecUtils.scale(v1,-2) f = f.extrude(v2) if delta: f.translate(delta) @@ -290,8 +289,7 @@ class _Wall(ArchComponent.Component): if not obj.Base: return - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils flat = False if hasattr(obj.ViewObject,"DisplayMode"): @@ -304,25 +302,25 @@ class _Wall(ArchComponent.Component): def getbase(wire): "returns a full shape from a base wire" - dvec = fcgeo.vec(wire.Edges[0]).cross(normal) + dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal) dvec.normalize() if obj.Align == "Left": dvec = dvec.multiply(width) - w2 = fcgeo.offsetWire(wire,dvec) - w1 = Part.Wire(fcgeo.sortEdges(wire.Edges)) - sh = fcgeo.bind(w1,w2) + w2 = DraftGeomUtils.offsetWire(wire,dvec) + w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges)) + sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Right": dvec = dvec.multiply(width) - dvec = fcvec.neg(dvec) - w2 = fcgeo.offsetWire(wire,dvec) - w1 = Part.Wire(fcgeo.sortEdges(wire.Edges)) - sh = fcgeo.bind(w1,w2) + dvec = DraftVecUtils.neg(dvec) + w2 = DraftGeomUtils.offsetWire(wire,dvec) + w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges)) + sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Center": dvec = dvec.multiply(width/2) - w1 = fcgeo.offsetWire(wire,dvec) - dvec = fcvec.neg(dvec) - w2 = fcgeo.offsetWire(wire,dvec) - sh = fcgeo.bind(w1,w2) + w1 = DraftGeomUtils.offsetWire(wire,dvec) + dvec = DraftVecUtils.neg(dvec) + w2 = DraftGeomUtils.offsetWire(wire,dvec) + sh = DraftGeomUtils.bind(w1,w2) # fixing self-intersections sh.fix(0.1,0,1) if height and (not flat): @@ -388,7 +386,7 @@ class _Wall(ArchComponent.Component): if base: obj.Shape = base - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderWall(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 2cdf513c91..35813ddfc8 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore,QtGui @@ -109,8 +108,7 @@ class _Window(ArchComponent.Component): self.createGeometry(obj) def createGeometry(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils pl = obj.Placement if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): @@ -135,7 +133,7 @@ class _Window(ArchComponent.Component): norm = shape.normalAt(0,0) thk = float(obj.WindowParts[(i*5)+3]) if thk: - exv = fcvec.scaleTo(norm,thk) + exv = DraftVecUtils.scaleTo(norm,thk) shape = shape.extrude(exv) for w in wires: f = Part.Face(w) @@ -144,12 +142,12 @@ class _Window(ArchComponent.Component): if obj.WindowParts[(i*5)+4]: zof = float(obj.WindowParts[(i*5)+4]) if zof: - zov = fcvec.scaleTo(norm,zof) + zov = DraftVecUtils.scaleTo(norm,zof) shape.translate(zov) print shape shapes.append(shape) obj.Shape = Part.makeCompound(shapes) - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderWindow(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index 7a0cf8ae07..17dc3d1662 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import ifcReader, FreeCAD, Arch, Draft, os, sys, time, Part -from draftlibs import fcvec +import ifcReader, FreeCAD, Arch, Draft, os, sys, time, Part, DraftVecUtils __title__="FreeCAD IFC importer" __author__ = "Yorik van Havre" @@ -448,7 +447,7 @@ def getPlacement(entity): z = getVector(entity.Axis) y = z.cross(x) loc = getVector(entity.Location) - m = fcvec.getPlaneRotation(x,y,z) + m = DraftVecUtils.getPlaneRotation(x,y,z) pl = FreeCAD.Placement(m) pl.move(loc) elif entity.type == "IFCLOCALPLACEMENT": diff --git a/src/Mod/Arch/importOBJ.py b/src/Mod/Arch/importOBJ.py index e5ddca4348..4622e1adfb 100644 --- a/src/Mod/Arch/importOBJ.py +++ b/src/Mod/Arch/importOBJ.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD -from draftlibs import fcgeo +import FreeCAD, DraftGeomUtils if open.__module__ == '__builtin__': pythonopen = open @@ -42,7 +41,7 @@ def getIndices(shape,offset): for f in shape.Faces: fi = "" # OCC vertices are unsorted. We need to sort in the right order... - edges = fcgeo.sortEdges(f.Wire.Edges) + edges = DraftGeomUtils.sortEdges(f.Wire.Edges) print edges for e in edges: print e.Vertexes[0].Point,e.Vertexes[1].Point diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index 99e27d0f96..3d12885618 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -7,6 +7,8 @@ SET(Draft_SRCS DraftGui.py DraftSnap.py DraftTrackers.py + DraftVecUtils.py + DraftGeomUtils.py WorkingPlane.py importDXF.py importOCA.py @@ -22,8 +24,6 @@ SET(DraftLibs_SRCS draftlibs/dxfImportObjects.py draftlibs/dxfLibrary.py draftlibs/dxfReader.py - draftlibs/fcgeo.py - draftlibs/fcvec.py draftlibs/__init__.py ) SOURCE_GROUP("draftlibs" FILES ${DraftLibs_SRCS}) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 0014a45130..300bc86923 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -54,9 +54,9 @@ How it works / how to extend: - DraftTools.py: Contains the user tools of the Draft module (the commands from the Draft menu), and a couple of helpers such as the "Trackers" (temporary geometry used while drawing) - - draftlibs/fcvec.py: a vector math library, contains functions that are not + - DraftVecUtils.py: a vector math library, contains functions that are not implemented in the standard FreeCAD vector - - draftlibs/fcgeo.py: a library of misc functions to manipulate shapes. + - DraftGeomUtils.py: a library of misc functions to manipulate shapes. The Draft.py contains everything to create geometry in the scene. You should start there if you intend to modify something. Then, the DraftTools @@ -72,9 +72,8 @@ How it works / how to extend: ''' # import FreeCAD modules -import FreeCAD, math, sys, os +import FreeCAD, math, sys, os, DraftVecUtils from FreeCAD import Vector -from draftlibs import fcvec from pivy import coin if FreeCAD.GuiUp: @@ -395,8 +394,8 @@ def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None ref = placement.multVec(FreeCAD.Vector(1,0,0)) v1 = (edge.Vertexes[0].Point).sub(edge.Curve.Center) v2 = (edge.Vertexes[-1].Point).sub(edge.Curve.Center) - a1 = -math.degrees(fcvec.angle(v1,ref)) - a2 = -math.degrees(fcvec.angle(v2,ref)) + a1 = -math.degrees(DraftVecUtils.angle(v1,ref)) + a2 = -math.degrees(DraftVecUtils.angle(v2,ref)) obj.FirstAngle = a1 obj.LastAngle = a2 else: @@ -514,15 +513,14 @@ def makeWire(pointslist,closed=False,placement=None,face=True,support=None): and last points are identical, the wire is closed. If face is true (and wire is closed), the wire will appear filled. Instead of a pointslist, you can also pass a Part Wire.''' - from draftlibs import fcgeo - import Part + import DraftGeomUtils, Part if not isinstance(pointslist,list): e = pointslist.Wires[0].Edges - pointslist = Part.Wire(fcgeo.sortEdges(e)) + pointslist = Part.Wire(DraftGeomUtils.sortEdges(e)) nlist = [] for v in pointslist.Vertexes: nlist.append(v.Point) - if fcgeo.isReallyClosed(pointslist): + if DraftGeomUtils.isReallyClosed(pointslist): closed = True pointslist = nlist print pointslist @@ -774,8 +772,7 @@ def fuse(object1,object2): the union of the 2 given objects. If the objects are coplanar, a special Draft Wire is used, otherwise we use a standard Part fuse.''' - from draftlibs import fcgeo - import Part + import DraftGeomUtils, Part # testing if we have holes: holes = False fshape = object1.Shape.fuse(object2.Shape) @@ -783,7 +780,7 @@ def fuse(object1,object2): for f in fshape.Faces: if len(f.Wires) > 1: holes = True - if fcgeo.isCoplanar(object1.Shape.fuse(object2.Shape).Faces) and not holes: + if DraftGeomUtils.isCoplanar(object1.Shape.fuse(object2.Shape).Faces) and not holes: obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Fusion") _Wire(obj) if gui: @@ -879,12 +876,12 @@ def array(objectslist,arg1,arg2,arg3,arg4=None): typecheck([(xvector,Vector), (yvector,Vector), (xnum,int), (ynum,int)], "rectArray") if not isinstance(objectslist,list): objectslist = [objectslist] for xcount in range(xnum): - currentxvector=fcvec.scale(xvector,xcount) + currentxvector=DraftVecUtils.scale(xvector,xcount) if not xcount==0: move(objectslist,currentxvector,True) for ycount in range(ynum): currentxvector=FreeCAD.Base.Vector(currentxvector) - currentyvector=currentxvector.add(fcvec.scale(yvector,ycount)) + currentyvector=currentxvector.add(DraftVecUtils.scale(yvector,ycount)) if not ycount==0: move(objectslist,currentyvector,True) def polarArray(objectslist,center,angle,num): @@ -918,7 +915,7 @@ def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False) newobj = obj if (obj.isDerivedFrom("Part::Feature")): shape = obj.Shape.copy() - shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) + shape.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), angle) newobj.Shape = shape elif (obj.isDerivedFrom("App::Annotation")): if axis.normalize() == Vector(1,0,0): @@ -939,7 +936,7 @@ def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False) elif hasattr(obj,"Placement"): shape = Part.Shape() shape.Placement = obj.Placement - shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) + shape.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), angle) newobj.Placement = shape.Placement if copy: formatObject(newobj,obj) @@ -972,7 +969,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy sh = sh.transformGeometry(m) corr = Vector(center.x,center.y,center.z) corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(center)) + corr = DraftVecUtils.neg(corr.sub(center)) sh.translate(corr) if getType(obj) == "Rectangle": p = [] @@ -982,8 +979,8 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy diag = p[2].sub(p[0]) bb = p[1].sub(p[0]) bh = p[3].sub(p[0]) - nb = fcvec.project(diag,bb) - nh = fcvec.project(diag,bh) + nb = DraftVecUtils.project(diag,bb) + nh = DraftVecUtils.project(diag,bh) if obj.Length < 0: l = -nb.Length else: l = nb.Length if obj.Height < 0: h = -nh.Length @@ -1016,7 +1013,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy obj.Scale = delta corr = Vector(center.x,center.y,center.z) corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(center)) + corr = DraftVecUtils.neg(corr.sub(center)) p = obj.Placement p.move(corr) obj.Placement = p @@ -1037,8 +1034,7 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): and the offsetted wires will be bound by their endpoints, forming a face if sym is True, bind must be true too, and the offset is made on both sides, the total width being the given delta length.''' - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils def getRect(p,obj): "returns length,heigh,placement" @@ -1047,8 +1043,8 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): diag = p[2].sub(p[0]) bb = p[1].sub(p[0]) bh = p[3].sub(p[0]) - nb = fcvec.project(diag,bb) - nh = fcvec.project(diag,bh) + nb = DraftVecUtils.project(diag,bb) + nh = DraftVecUtils.project(diag,bh) if obj.Length < 0: l = -nb.Length else: l = nb.Length if obj.Height < 0: h = -nh.Length @@ -1058,7 +1054,7 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): def getRadius(obj,delta): "returns a new radius for a regular polygon" an = math.pi/obj.FacesNumber - nr = fcvec.rotate(delta,-an) + nr = DraftVecUtils.rotate(delta,-an) nr.multiply(1/math.cos(an)) nr = obj.Shape.Vertexes[0].Point.add(nr) nr = nr.sub(obj.Placement.Base) @@ -1075,18 +1071,18 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): else: if sym: d1 = delta.multiply(0.5) - d2 = fcvec.neg(d1) - n1 = fcgeo.offsetWire(obj.Shape,d1) - n2 = fcgeo.offsetWire(obj.Shape,d2) + d2 = DraftVecUtils.neg(d1) + n1 = DraftGeomUtils.offsetWire(obj.Shape,d1) + n2 = DraftGeomUtils.offsetWire(obj.Shape,d2) else: - newwire = fcgeo.offsetWire(obj.Shape,delta) - p = fcgeo.getVerts(newwire) + newwire = DraftGeomUtils.offsetWire(obj.Shape,delta) + p = DraftGeomUtils.getVerts(newwire) if occ: newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset") - newobj.Shape = fcgeo.offsetWire(obj.Shape,delta,occ=True) + newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape,delta,occ=True) formatObject(newobj,obj) elif bind: - if not fcgeo.isReallyClosed(obj.Shape): + if not DraftGeomUtils.isReallyClosed(obj.Shape): if sym: s1 = n1 s2 = n2 @@ -1161,8 +1157,7 @@ def draftify(objectslist,makeblock=False): '''draftify(objectslist,[makeblock]): turns each object of the given list (objectslist can also be a single object) into a Draft parametric wire. If makeblock is True, multiple objects will be grouped in a block''' - from draftlibs import fcgeo - import Part + import DraftGeomUtils, Part if not isinstance(objectslist,list): objectslist = [objectslist] @@ -1170,7 +1165,7 @@ def draftify(objectslist,makeblock=False): for obj in objectslist: if obj.isDerivedFrom('Part::Feature'): for w in obj.Shape.Wires: - if fcgeo.hasCurves(w): + if DraftGeomUtils.hasCurves(w): if (len(w.Edges) == 1) and isinstance(w.Edges[0].Curve,Part.Circle): nobj = makeCircle(w.Edges[0]) else: @@ -1199,8 +1194,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct with the given linewidth and fontsize (used if the given object contains any text). You can also supply an arbitrary projection vector. the scale parameter allows to scale linewidths down, so they are resolution-independant.''' - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils svg = "" linewidth = linewidth/scale fontsize = (fontsize/scale)/2 @@ -1209,7 +1203,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct if isinstance(direction,FreeCAD.Vector): if direction != Vector(0,0,0): plane = WorkingPlane.plane() - plane.alignToPointAndAxis(Vector(0,0,0),fcvec.neg(direction),0) + plane.alignToPointAndAxis(Vector(0,0,0),DraftVecUtils.neg(direction),0) elif isinstance(direction,WorkingPlane.plane): plane = direction @@ -1240,10 +1234,10 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct def getProj(vec): if not plane: return vec - nx = fcvec.project(vec,plane.u) + nx = DraftVecUtils.project(vec,plane.u) lx = nx.Length if abs(nx.getAngle(plane.u)) > 0.1: lx = -lx - ny = fcvec.project(vec,plane.v) + ny = DraftVecUtils.project(vec,plane.v) ly = ny.Length if abs(ny.getAngle(plane.v)) > 0.1: ly = -ly return Vector(lx,ly,0) @@ -1255,7 +1249,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct def getPath(edges): svg =' dmax): - p1 = p2.add(fcvec.scaleTo(proj,dmax)) - p4 = p3.add(fcvec.scaleTo(proj,dmax)) - midpoint = p2.add(fcvec.scale(p3.sub(p2),0.5)) + p1 = p2.add(DraftVecUtils.scaleTo(proj,dmax)) + p4 = p3.add(DraftVecUtils.scaleTo(proj,dmax)) + midpoint = p2.add(DraftVecUtils.scale(p3.sub(p2),0.5)) if not proj: - ed = fcgeo.vec(base) + ed = DraftGeomUtils.vec(base) proj = ed.cross(Vector(0,0,1)) if not proj: norm = Vector(0,0,1) - else: norm = fcvec.neg(p3.sub(p2).cross(proj)) - if not fcvec.isNull(norm): + else: norm = DraftVecUtils.neg(p3.sub(p2).cross(proj)) + if not DraftVecUtils.isNull(norm): norm.normalize() va = get3DView().getViewDirection() if va.getAngle(norm) < math.pi/2: - norm = fcvec.neg(norm) + norm = DraftVecUtils.neg(norm) u = p3.sub(p2) u.normalize() c = get3DView().getCameraNode() r = c.orientation.getValue() ru = Vector(r.multVec(coin.SbVec3f(1,0,0)).getValue()) - if ru.getAngle(u) > math.pi/2: u = fcvec.neg(u) + if ru.getAngle(u) > math.pi/2: u = DraftVecUtils.neg(u) v = norm.cross(u) - offset = fcvec.scaleTo(v,obj.ViewObject.FontSize*.2) + offset = DraftVecUtils.scaleTo(v,obj.ViewObject.FontSize*.2) if obj.ViewObject: if hasattr(obj.ViewObject,"DisplayMode"): if obj.ViewObject.DisplayMode == "3D": - offset = fcvec.neg(offset) + offset = DraftVecUtils.neg(offset) if hasattr(obj.ViewObject,"TextPosition"): if obj.ViewObject.TextPosition == Vector(0,0,0): tbase = midpoint.add(offset) @@ -1839,7 +1831,7 @@ class _ViewProviderDimension: tbase = obj.ViewObject.TextPosition else: tbase = midpoint.add(offset) - rot = FreeCAD.Placement(fcvec.getPlaneRotation(u,v,norm)).Rotation.Q + rot = FreeCAD.Placement(DraftVecUtils.getPlaneRotation(u,v,norm)).Rotation.Q return p1,p2,p3,p4,tbase,norm,rot def attach(self, obj): @@ -1858,7 +1850,7 @@ class _ViewProviderDimension: self.text.string = self.text3d.string = '' self.textpos = coin.SoTransform() self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) - tm = fcvec.getPlaneRotation(p3.sub(p2),norm) + tm = DraftVecUtils.getPlaneRotation(p3.sub(p2),norm) rm = coin.SbRotation() self.textpos.rotation = rm label = coin.SoSeparator() @@ -1917,11 +1909,11 @@ class _ViewProviderDimension: # arc linked dimension e = obj.Base.Shape.Edges[obj.LinkedVertices[0]] c = e.Curve.Center - bray = fcvec.scaleTo(obj.Dimline.sub(c),e.Curve.Radius) + bray = DraftVecUtils.scaleTo(obj.Dimline.sub(c),e.Curve.Radius) if obj.LinkedVertices[1] == 1: v1 = c else: - v1 = c.add(fcvec.neg(bray)) + v1 = c.add(DraftVecUtils.neg(bray)) v2 = c.add(bray) else: # linear linked dimension @@ -1952,8 +1944,8 @@ class _ViewProviderDimension: else: ts = (len(text)*obj.ViewObject.FontSize)/4 rm = ((p3.sub(p2)).Length/2)-ts - p2a = p2.add(fcvec.scaleTo(p3.sub(p2),rm)) - p2b = p3.add(fcvec.scaleTo(p2.sub(p3),rm)) + p2a = p2.add(DraftVecUtils.scaleTo(p3.sub(p2),rm)) + p2b = p3.add(DraftVecUtils.scaleTo(p2.sub(p3),rm)) self.coords.point.setValues([[p1.x,p1.y,p1.z], [p2.x,p2.y,p2.z], [p2a.x,p2a.y,p2a.z], @@ -2149,15 +2141,14 @@ class _ViewProviderAngularDimension: self.onChanged(vobj,"FontName") def calcGeom(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils rad = (obj.Dimline.sub(obj.Center)).Length cir = Part.makeCircle(rad,obj.Center,Vector(0,0,1),obj.FirstAngle,obj.LastAngle) - cp = fcgeo.findMidpoint(cir.Edges[0]) + cp = DraftGeomUtils.findMidpoint(cir.Edges[0]) rv = cp.sub(obj.Center) - rv = fcvec.scaleTo(rv,rv.Length + obj.ViewObject.FontSize*.2) + rv = DraftVecUtils.scaleTo(rv,rv.Length + obj.ViewObject.FontSize*.2) tbase = obj.Center.add(rv) - trot = fcvec.angle(rv)-math.pi/2 + trot = DraftVecUtils.angle(rv)-math.pi/2 if (trot > math.pi/2) or (trot < -math.pi/2): trot = trot + math.pi s = getParam("dimorientation") @@ -2276,8 +2267,7 @@ class _Rectangle: self.createGeometry(fp) def createGeometry(self,fp): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils plm = fp.Placement p1 = Vector(0,0,0) p2 = Vector(p1.x+fp.Length,p1.y,p1.z) @@ -2286,7 +2276,7 @@ class _Rectangle: shape = Part.makePolygon([p1,p2,p3,p4,p1]) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w shape = Part.Face(shape) @@ -2399,8 +2389,7 @@ class _Wire: fp.Points = pts def createGeometry(self,fp): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils plm = fp.Placement if fp.Base and (not fp.Tool): if fp.Base.isDerivedFrom("Sketcher::SketchObject"): @@ -2416,8 +2405,8 @@ class _Wire: sh1 = fp.Base.Shape.copy() sh2 = fp.Tool.Shape.copy() shape = sh1.fuse(sh2) - if fcgeo.isCoplanar(shape.Faces): - shape = fcgeo.concatenate(shape) + if DraftGeomUtils.isCoplanar(shape.Faces): + shape = DraftGeomUtils.concatenate(shape) fp.Shape = shape p = [] for v in shape.Vertexes: p.append(v.Point) @@ -2430,7 +2419,7 @@ class _Wire: shape = Part.makePolygon(fp.Points+[fp.Points[0]]) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w shape = Part.Face(shape) @@ -2444,7 +2433,7 @@ class _Wire: shape = Part.Wire(edges) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w fp.Shape = shape @@ -2510,8 +2499,7 @@ class _Polygon: self.createGeometry(fp) def createGeometry(self,fp): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils plm = fp.Placement angle = (math.pi*2)/fp.FacesNumber if fp.DrawMode == 'inscribed': @@ -2526,7 +2514,7 @@ class _Polygon: shape = Part.makePolygon(pts) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w shape = Part.Face(shape) @@ -2690,16 +2678,15 @@ class _Shape2DView: self.createGeometry(obj) def createGeometry(self,obj): - import Drawing - from draftlibs import fcgeo + import Drawing, DraftGeomUtils pl = obj.Placement if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): - if not fcvec.isNull(obj.Projection): + if not DraftVecUtils.isNull(obj.Projection): [visibleG0,visibleG1,hiddenG0,hiddenG1] = Drawing.project(obj.Base.Shape,obj.Projection) if visibleG0: obj.Shape = visibleG0 - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _Array: @@ -2745,7 +2732,7 @@ class _Array: self.createGeometry(obj) def createGeometry(self,obj): - from draftlibs import fcgeo + import DraftGeomUtils if obj.Base: pl = obj.Placement if obj.ArrayType == "ortho": @@ -2753,21 +2740,21 @@ class _Array: else: sh = self.polarArray(obj.Base.Shape,obj.Center,obj.Angle,obj.NumberPolar,obj.Axis) obj.Shape = sh - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl def rectArray(self,shape,xvector,yvector,xnum,ynum): import Part base = [shape.copy()] for xcount in range(xnum): - currentxvector=fcvec.scale(xvector,xcount) + currentxvector=DraftVecUtils.scale(xvector,xcount) if not xcount==0: nshape = shape.copy() nshape.translate(currentxvector) base.append(nshape) for ycount in range(ynum): currentxvector=FreeCAD.Vector(currentxvector) - currentyvector=currentxvector.add(fcvec.scale(yvector,ycount)) + currentyvector=currentxvector.add(DraftVecUtils.scale(yvector,ycount)) if not ycount==0: nshape = shape.copy() nshape.translate(currentyvector) @@ -2781,7 +2768,7 @@ class _Array: for i in range(num): currangle = fraction + (i*fraction) nshape = shape.copy() - nshape.rotate(fcvec.tup(center), fcvec.tup(axis), currangle) + nshape.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), currangle) base.append(nshape) return Part.makeCompound(base) @@ -2845,8 +2832,7 @@ class _Clone: self.createGeometry(obj) def createGeometry(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils pl = obj.Placement shapes = [] for o in obj.Objects: @@ -2859,7 +2845,7 @@ class _Clone: shapes.append(sh) if shapes: obj.Shape = Part.makeCompound(shapes) - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderDraftPart(_ViewProviderDraft): diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/DraftGeomUtils.py similarity index 100% rename from src/Mod/Draft/draftlibs/fcgeo.py rename to src/Mod/Draft/DraftGeomUtils.py diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 50a0b19ba6..1479a65688 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -26,9 +26,8 @@ __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -import FreeCAD, FreeCADGui, math, Draft, DraftGui, DraftTrackers +import FreeCAD, FreeCADGui, math, Draft, DraftGui, DraftTrackers, DraftVecUtils from DraftGui import todo,getMainWindow -from draftlibs import fcvec from FreeCAD import Vector from pivy import coin from PyQt4 import QtCore,QtGui @@ -110,9 +109,8 @@ class Snapper: be True to constrain the point against the closest working plane axis. Screenpos can be a list, a tuple or a coin.SbVec2s object.""" - global Part,fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils if not hasattr(self,"toolbar"): self.makeSnapToolBar() @@ -355,7 +353,7 @@ class Snapper: for e in edges: if isinstance(e.Curve,Part.Line): np = self.getPerpendicular(e,point) - if not fcgeo.isPtOnEdge(np,e): + if not DraftGeomUtils.isPtOnEdge(np,e): if (np.sub(point)).Length < self.radius: if self.isEnabled('extension'): if np != e.Vertexes[0].Point: @@ -372,7 +370,7 @@ class Snapper: else: if self.isEnabled('parallel'): if last: - de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() + de = Part.Line(last,last.add(DraftGeomUtils.vec(e))).toShape() np = self.getPerpendicular(de,point) if (np.sub(point)).Length < self.radius: if self.tracker: @@ -398,13 +396,13 @@ class Snapper: FreeCAD.Vector(0,0,1)] for a in self.polarAngles: if a == 90: - vecs.extend([ax[0],fcvec.neg(ax[0])]) - vecs.extend([ax[1],fcvec.neg(ax[1])]) + vecs.extend([ax[0],DraftVecUtils.neg(ax[0])]) + vecs.extend([ax[1],DraftVecUtils.neg(ax[1])]) else: - v = fcvec.rotate(ax[0],math.radians(a),ax[2]) - vecs.extend([v,fcvec.neg(v)]) - v = fcvec.rotate(ax[1],math.radians(a),ax[2]) - vecs.extend([v,fcvec.neg(v)]) + v = DraftVecUtils.rotate(ax[0],math.radians(a),ax[2]) + vecs.extend([v,DraftVecUtils.neg(v)]) + v = DraftVecUtils.rotate(ax[1],math.radians(a),ax[2]) + vecs.extend([v,DraftVecUtils.neg(v)]) for v in vecs: de = Part.Line(last,last.add(v)).toShape() np = self.getPerpendicular(de,point) @@ -457,7 +455,7 @@ class Snapper: snaps = [] if self.isEnabled("midpoint"): if isinstance(shape,Part.Edge): - mp = fcgeo.findMidpoint(shape) + mp = DraftGeomUtils.findMidpoint(shape) if mp: snaps.append([mp,'midpoint',mp]) return snaps @@ -472,7 +470,7 @@ class Snapper: np = self.getPerpendicular(shape,last) elif isinstance(shape.Curve,Part.Circle): dv = last.sub(shape.Curve.Center) - dv = fcvec.scaleTo(dv,shape.Curve.Radius) + dv = DraftVecUtils.scaleTo(dv,shape.Curve.Radius) np = (shape.Curve.Center).add(dv) elif isinstance(shape.Curve,Part.BSplineCurve): pr = shape.Curve.parameter(last) @@ -493,7 +491,7 @@ class Snapper: if self.constraintAxis: tmpEdge = Part.Line(last,last.add(self.constraintAxis)).toShape() # get the intersection points - pt = fcgeo.findIntersection(tmpEdge,shape,True,True) + pt = DraftGeomUtils.findIntersection(tmpEdge,shape,True,True) if pt: for p in pt: snaps.append([p,'ortho',p]) @@ -506,14 +504,14 @@ class Snapper: tmpEdge1 = Part.Line(last,last.add(self.constraintAxis)).toShape() tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() # get the intersection points - pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True) + pt = DraftGeomUtils.findIntersection(tmpEdge1,tmpEdge2,True,True) if pt: return [pt[0],'ortho',pt[0]] if eline: try: tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() # get the intersection points - pt = fcgeo.findIntersection(eline,tmpEdge2,True,True) + pt = DraftGeomUtils.findIntersection(eline,tmpEdge2,True,True) if pt: return [pt[0],'ortho',pt[0]] except: @@ -526,7 +524,7 @@ class Snapper: if self.isEnabled("intersection") and self.isEnabled("extension"): if e1 and e2: # get the intersection points - pts = fcgeo.findIntersection(e1,e2,True,True) + pts = DraftGeomUtils.findIntersection(e1,e2,True,True) if pts: for p in pts: snaps.append([p,'intersection',p]) @@ -569,7 +567,7 @@ class Snapper: if (not self.maxEdges) or (len(obj.Shape.Edges) <= self.maxEdges): for e in obj.Shape.Edges: # get the intersection points - pt = fcgeo.findIntersection(e,shape) + pt = DraftGeomUtils.findIntersection(e,shape) if pt: for p in pt: snaps.append([p,'intersection',p]) @@ -597,7 +595,7 @@ class Snapper: def getPerpendicular(self,edge,pt): "returns a point on an edge, perpendicular to the given point" dv = pt.sub(edge.Vertexes[0].Point) - nv = fcvec.project(dv,fcgeo.vec(edge)) + nv = DraftVecUtils.project(dv,DraftGeomUtils.vec(edge)) np = (edge.Vertexes[0].Point).add(nv) return np @@ -690,7 +688,7 @@ class Snapper: self.constraintAxis = FreeCAD.DraftWorkingPlane.axis # calculating constrained point - cdelta = fcvec.project(delta,self.constraintAxis) + cdelta = DraftVecUtils.project(delta,self.constraintAxis) npoint = self.basepoint.add(cdelta) # setting constrain line diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index ad61cf65d0..bde2ad4a76 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -29,9 +29,8 @@ __url__ = "http://free-cad.sourceforge.net" # Generic stuff #--------------------------------------------------------------------------- -import os, FreeCAD, FreeCADGui, WorkingPlane, math, re, importSVG, Draft, Draft_rc +import os, FreeCAD, FreeCADGui, WorkingPlane, math, re, importSVG, Draft, Draft_rc, DraftVecUtils from functools import partial -from draftlibs import fcvec from FreeCAD import Vector from DraftGui import todo,QtCore,QtGui from DraftSnap import * @@ -283,7 +282,7 @@ class SelectPlane: self.display('side') self.finish() elif arg == "currentView": - viewDirection = fcvec.neg(self.view.getViewDirection()) + viewDirection = DraftVecUtils.neg(self.view.getViewDirection()) plane.alignToPointAndAxis(Vector(0,0,0), viewDirection, self.offset) self.display(viewDirection) self.finish() @@ -327,9 +326,8 @@ class Creator: def Activated(self,name="None"): if FreeCAD.activeDraftCommand: FreeCAD.activeDraftCommand.finish() - global Part, fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils self.ui = None self.call = None self.doc = None @@ -348,7 +346,7 @@ class Creator: self.ui.show() rot = self.view.getCameraNode().getField("orientation").getValue() upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) self.node = [] self.pos = [] self.constrain = None @@ -721,12 +719,12 @@ class Rectangle(Creator): p1 = self.node[0] p3 = self.node[-1] diagonal = p3.sub(p1) - p2 = p1.add(fcvec.project(diagonal, plane.v)) - p4 = p1.add(fcvec.project(diagonal, plane.u)) + p2 = p1.add(DraftVecUtils.project(diagonal, plane.v)) + p4 = p1.add(DraftVecUtils.project(diagonal, plane.u)) length = p4.sub(p1).Length - if abs(fcvec.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length + if abs(DraftVecUtils.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length height = p2.sub(p1).Length - if abs(fcvec.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height + if abs(DraftVecUtils.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height p = plane.getRotation() p.move(p1) try: @@ -847,10 +845,10 @@ class Arc(Creator): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen self.ui.cross(True) - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center if hasMod(arg,MODALT): if not self.altdown: @@ -864,12 +862,12 @@ class Arc(Creator): self.ui.switchUi(False) elif (self.step == 1): # choose radius if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) if hasMod(arg,MODALT): if not self.altdown: @@ -880,20 +878,20 @@ class Arc(Creator): num = int(info['Component'].lstrip('Edge'))-1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: - cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) - cl = fcgeo.findClosestCircle(point,cir) + cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], self.tangents[1], ed) + cl = DraftGeomUtils.findClosestCircle(point,cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: - self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length + self.rad = self.center.add(DraftGeomUtils.findDistance(self.center,ed).sub(self.center)).Length else: - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) else: if self.altdown: self.ui.cross(True) self.altdown = False - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) self.ui.setRadiusValue(self.rad) self.arctrack.setRadius(self.rad) # Draw constraint tracker line. @@ -907,11 +905,11 @@ class Arc(Creator): self.linetrack.p2(point) self.linetrack.on() elif (self.step == 2): # choose first angle - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if currentrad != 0: - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 - self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) + self.linetrack.p2(DraftVecUtils.scaleTo(point.sub(self.center),self.rad).add(self.center)) # Draw constraint tracker line. if hasMod(arg,MODCONSTRAIN): self.constraintrack.p1(point) @@ -922,11 +920,11 @@ class Arc(Creator): self.ui.setRadiusValue(math.degrees(angle)) self.firstangle = angle else: # choose second angle - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if currentrad != 0: - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 - self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) + self.linetrack.p2(DraftVecUtils.scaleTo(point.sub(self.center),self.rad).add(self.center)) # Draw constraint tracker line. if hasMod(arg,MODCONSTRAIN): self.constraintrack.p1(point) @@ -942,10 +940,10 @@ class Arc(Creator): if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center self.support = getSupport(arg) if hasMod(arg,MODALT): @@ -990,7 +988,7 @@ class Arc(Creator): self.ui.labelRadius.setText("Aperture") self.step = 3 # scale center->point vector for proper display - u = fcvec.scaleTo(point.sub(self.center), self.rad) + u = DraftVecUtils.scaleTo(point.sub(self.center), self.rad) self.arctrack.setStartAngle(self.firstangle) msg(translate("draft", "Pick aperture:\n")) else: # choose second angle @@ -1036,15 +1034,15 @@ class Arc(Creator): if (self.step == 1): self.rad = rad if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) + cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) + cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center if self.closedCircle: @@ -1061,9 +1059,9 @@ class Arc(Creator): elif (self.step == 2): self.ui.labelRadius.setText(str(translate("draft", "Aperture"))) self.firstangle = math.radians(rad) - if fcvec.equals(plane.axis, Vector(1,0,0)): u = Vector(0,self.rad,0) - else: u = fcvec.scaleTo(Vector(1,0,0).cross(plane.axis), self.rad) - urotated = fcvec.rotate(u, math.radians(rad), plane.axis) + if DraftVecUtils.equals(plane.axis, Vector(1,0,0)): u = Vector(0,self.rad,0) + else: u = DraftVecUtils.scaleTo(Vector(1,0,0).cross(plane.axis), self.rad) + urotated = DraftVecUtils.rotate(u, math.radians(rad), plane.axis) self.arctrack.setStartAngle(self.firstangle) self.step = 3 self.ui.radiusValue.setText("") @@ -1139,10 +1137,10 @@ class Polygon(Creator): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen self.ui.cross(True) - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center if hasMod(arg,MODALT): if not self.altdown: @@ -1156,12 +1154,12 @@ class Polygon(Creator): self.ui.switchUi(False) else: # choose radius if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) if hasMod(arg,MODALT): if not self.altdown: @@ -1173,20 +1171,20 @@ class Polygon(Creator): num = int(snapped['Component'].lstrip('Edge'))-1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: - cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) - cl = fcgeo.findClosestCircle(point,cir) + cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], self.tangents[1], ed) + cl = DraftGeomUtils.findClosestCircle(point,cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: - self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length + self.rad = self.center.add(DraftGeomUtils.findDistance(self.center,ed).sub(self.center)).Length else: - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) else: if self.altdown: self.ui.cross(True) self.altdown = False - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) self.ui.setRadiusValue(self.rad) self.arctrack.setRadius(self.rad) # Draw constraint tracker line. @@ -1203,10 +1201,10 @@ class Polygon(Creator): if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center if not self.node: self.support = getSupport(arg) if hasMod(arg,MODALT): @@ -1265,15 +1263,15 @@ class Polygon(Creator): "this function gets called by the toolbar when valid radius have been entered there" self.rad = rad if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) + cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) + cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center self.drawPolygon() @@ -1485,7 +1483,7 @@ class Dimension(Creator): r = point.sub(self.center) self.arctrack.setRadius(r.Length) a = self.arctrack.getAngle(point) - pair = fcgeo.getBoundaryAngles(a,self.pts) + pair = DraftGeomUtils.getBoundaryAngles(a,self.pts) if not (pair[0] < a < pair[1]): self.angledata = [4*math.pi-pair[0],2*math.pi-pair[1]] else: @@ -1496,14 +1494,14 @@ class Dimension(Creator): self.altdown = False self.ui.switchUi(False) if self.dir: - point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) + point = self.node[0].add(DraftVecUtils.project(point.sub(self.node[0]),self.dir)) if len(self.node) == 2: if self.arcmode and self.edges: cen = self.edges[0].Curve.Center rad = self.edges[0].Curve.Radius baseray = point.sub(cen) - v2 = fcvec.scaleTo(baseray,rad) - v1 = fcvec.neg(v2) + v2 = DraftVecUtils.scaleTo(baseray,rad) + v1 = DraftVecUtils.neg(v2) if shift: self.node = [cen,cen.add(v2)] self.arcmode = "radius" @@ -1574,7 +1572,7 @@ class Dimension(Creator): # there is already a snapped edge, so we start angular dimension self.edges.append(ed) self.node.extend([v1,v2]) # self.node now has the 4 endpoints - c = fcgeo.findIntersection(self.node[0], + c = DraftGeomUtils.findIntersection(self.node[0], self.node[1], self.node[2], self.node[3], @@ -1593,7 +1591,7 @@ class Dimension(Creator): self.dimtrack.on() else: if self.dir: - point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) + point = self.node[0].add(DraftVecUtils.project(point.sub(self.node[0]),self.dir)) self.node.append(point) print "node",self.node self.dimtrack.update(self.node) @@ -1610,7 +1608,7 @@ class Dimension(Creator): # for unlinked arc mode: # if self.arcmode: # v = self.node[1].sub(self.node[0]) - # v = fcvec.scale(v,0.5) + # v = DraftVecUtils.scale(v,0.5) # cen = self.node[0].add(v) # self.node = [self.node[0],self.node[1],cen] self.createObject() @@ -1651,9 +1649,8 @@ class Modifier: def Activated(self,name="None"): if FreeCAD.activeDraftCommand: FreeCAD.activeDraftCommand.finish() - global Part, fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils self.ui = None self.call = None self.commitList = [] @@ -1667,7 +1664,7 @@ class Modifier: FreeCADGui.draftToolBar.show() rot = self.view.getCameraNode().getField("orientation").getValue() upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) self.node = [] self.ui.sourceCmd = self self.constrain = None @@ -1931,10 +1928,10 @@ class Rotate(Modifier): point,ctrlPoint,info = getPoint(self,arg) self.ui.cross(True) # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center): - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center): + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if self.extendedCopy: if not hasMod(arg,MODALT): self.step = 3 @@ -1942,9 +1939,9 @@ class Rotate(Modifier): if (self.step == 0): pass elif (self.step == 1): - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if (currentrad != 0): - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 self.linetrack.p2(point) # Draw constraint tracker line. @@ -1959,16 +1956,16 @@ class Rotate(Modifier): self.ui.radiusValue.setFocus() self.ui.radiusValue.selectAll() elif (self.step == 2): - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if (currentrad != 0): - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 if (angle < self.firstangle): sweep = (2*math.pi-self.firstangle)+angle else: sweep = angle - self.firstangle self.arctrack.setApertureAngle(sweep) - self.ghost.trans.rotation.setValue(coin.SbVec3f(fcvec.tup(plane.axis)),sweep) + self.ghost.trans.rotation.setValue(coin.SbVec3f(DraftVecUtils.tup(plane.axis)),sweep) self.linetrack.p2(point) # Draw constraint tracker line. if hasMod(arg,MODCONSTRAIN): @@ -1984,9 +1981,9 @@ class Rotate(Modifier): elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): point,ctrlPoint,info = getPoint(self,arg) - if self.center and fcvec.dist(point,self.center): - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center): + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): self.center = point self.node = [point] @@ -2002,16 +1999,16 @@ class Rotate(Modifier): self.planetrack.set(point) elif (self.step == 1): self.ui.labelRadius.setText("Rotation") - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) self.arctrack.on() self.arctrack.setStartPoint(point) self.ghost.on() self.step = 2 msg(translate("draft", "Pick rotation angle:\n")) else: - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) angle = point.sub(self.center).getAngle(plane.u) - if fcvec.project(point.sub(self.center), plane.v).getAngle(plane.v) > 1: + if DraftVecUtils.project(point.sub(self.center), plane.v).getAngle(plane.v) > 1: angle = -angle if (angle < self.firstangle): sweep = (2*math.pi-self.firstangle)+angle @@ -2127,33 +2124,33 @@ class Offset(Modifier): self.ui.cross(True) point,ctrlPoint,info = getPoint(self,arg) if hasMod(arg,MODCONSTRAIN) and self.constrainSeg: - dist = fcgeo.findPerpendicular(point,self.shape,self.constrainSeg[1]) + dist = DraftGeomUtils.findPerpendicular(point,self.shape,self.constrainSeg[1]) e = self.shape.Edges[self.constrainSeg[1]] self.constraintrack.p1(e.Vertexes[0].Point) self.constraintrack.p2(point.add(dist[0])) self.constraintrack.on() else: - dist = fcgeo.findPerpendicular(point,self.shape.Edges) + dist = DraftGeomUtils.findPerpendicular(point,self.shape.Edges) self.constraintrack.off() if dist: self.ghost.on() if self.mode == "Wire": - d = fcvec.neg(dist[0]) - v1 = fcgeo.getTangent(self.shape.Edges[0],point) - v2 = fcgeo.getTangent(self.shape.Edges[dist[1]],point) - a = -fcvec.angle(v1,v2) - self.dvec = fcvec.rotate(d,a,plane.axis) + d = DraftVecUtils.neg(dist[0]) + v1 = DraftGeomUtils.getTangent(self.shape.Edges[0],point) + v2 = DraftGeomUtils.getTangent(self.shape.Edges[dist[1]],point) + a = -DraftVecUtils.angle(v1,v2) + self.dvec = DraftVecUtils.rotate(d,a,plane.axis) occmode = self.ui.occOffset.isChecked() - self.ghost.update(fcgeo.offsetWire(self.shape,self.dvec,occ=occmode),forceclosed=occmode) + self.ghost.update(DraftGeomUtils.offsetWire(self.shape,self.dvec,occ=occmode),forceclosed=occmode) elif self.mode == "BSpline": - d = fcvec.neg(dist[0]) + d = DraftVecUtils.neg(dist[0]) e = self.shape.Edges[0] - basetan = fcgeo.getTangent(e,point) + basetan = DraftGeomUtils.getTangent(e,point) self.npts = [] for p in self.sel.Points: - currtan = fcgeo.getTangent(e,p) - a = -fcvec.angle(currtan,basetan) - self.dvec = fcvec.rotate(d,a,plane.axis) + currtan = DraftGeomUtils.getTangent(e,p) + a = -DraftVecUtils.angle(currtan,basetan) + self.dvec = DraftVecUtils.rotate(d,a,plane.axis) self.npts.append(p.add(self.dvec)) self.ghost.update(self.npts) elif self.mode == "Circle": @@ -2329,12 +2326,12 @@ class Upgrade(Modifier): u = faces.pop(0) for f in faces: u = u.fuse(f) - if fcgeo.isCoplanar(faces): + if DraftGeomUtils.isCoplanar(faces): if self.sel[0].ViewObject.DisplayMode == "Wireframe": f = False else: f = True - u = fcgeo.concatenate(u) + u = DraftGeomUtils.concatenate(u) if not curves: # several coplanar and non-curved faces: they can becoem a Draft wire msg(translate("draft", "Found several objects or faces: making a parametric face\n")) @@ -2384,7 +2381,7 @@ class Upgrade(Modifier): else: # only closed wires for w in wires: - if fcgeo.isPlanar(w): + if DraftGeomUtils.isPlanar(w): f = Part.Face(w) faces.append(f) else: @@ -2405,7 +2402,7 @@ class Upgrade(Modifier): edges = openwires[0].Edges if len(edges) > 1: edges.append(Part.Line(p1,p0).toShape()) - w = Part.Wire(fcgeo.sortEdges(edges)) + w = Part.Wire(DraftGeomUtils.sortEdges(edges)) if len(edges) == 1: if len(w.Vertexes) == 2: msg(translate("draft", "Found 1 open edge: making a line\n")) @@ -2433,7 +2430,7 @@ class Upgrade(Modifier): for e in ob.Shape.Edges: edges.append(e) newob = None - nedges = fcgeo.sortEdges(edges[:]) + nedges = DraftGeomUtils.sortEdges(edges[:]) # for e in nedges: print "debug: ",e.Curve,e.Vertexes[0].Point,e.Vertexes[-1].Point w = Part.Wire(nedges) if len(w.Edges) == len(edges): @@ -2643,7 +2640,7 @@ class Trimex(Modifier): self.extrudeMode = False if self.obj.Shape.Wires: self.edges = self.obj.Shape.Wires[0].Edges - self.edges = fcgeo.sortEdges(self.edges) + self.edges = DraftGeomUtils.sortEdges(self.edges) else: self.edges = self.obj.Shape.Edges self.ghost = [] @@ -2707,7 +2704,7 @@ class Trimex(Modifier): "redraws the ghost in extrude mode" self.newpoint = self.obj.Shape.Faces[0].CenterOfMass dvec = self.point.sub(self.newpoint) - if not shift: delta = fcvec.project(dvec,self.normal) + if not shift: delta = DraftVecUtils.project(dvec,self.normal) else: delta = dvec if self.force: ratio = self.force/delta.Length @@ -2733,7 +2730,7 @@ class Trimex(Modifier): for e in self.edges: vlist.append(e.Vertexes[0].Point) vlist.append(self.edges[-1].Vertexes[-1].Point) if shift: npoint = self.activePoint - else: npoint = fcgeo.findClosest(point,vlist) + else: npoint = DraftGeomUtils.findClosest(point,vlist) if npoint > len(self.edges)/2: reverse = True if alt: reverse = not reverse self.activePoint = npoint @@ -2758,16 +2755,16 @@ class Trimex(Modifier): snapped = self.doc.getObject(snapped['Object']) pts = [] for e in snapped.Shape.Edges: - int = fcgeo.findIntersection(edge,e,True,True) + int = DraftGeomUtils.findIntersection(edge,e,True,True) if int: pts.extend(int) if pts: - point = pts[fcgeo.findClosest(point,pts)] + point = pts[DraftGeomUtils.findClosest(point,pts)] # modifying active edge if isinstance(edge.Curve,Part.Line): - perp = fcgeo.vec(edge).cross(Vector(0,0,1)) + perp = DraftGeomUtils.vec(edge).cross(Vector(0,0,1)) chord = v1.sub(point) - proj = fcvec.project(chord,perp) + proj = DraftVecUtils.project(chord,perp) self.newpoint = Vector.add(point,proj) dist = v1.sub(self.newpoint).Length ghost.p1(self.newpoint) @@ -2776,15 +2773,15 @@ class Trimex(Modifier): if real: if self.force: ray = self.newpoint.sub(v1) - ray = fcvec.scale(ray,self.force/ray.Length) + ray = DraftVecUtils.scale(ray,self.force/ray.Length) self.newpoint = Vector.add(v1,ray) newedges.append(Part.Line(self.newpoint,v2).toShape()) else: center = edge.Curve.Center rad = edge.Curve.Radius - ang1 = fcvec.angle(v2.sub(center)) - ang2 = fcvec.angle(point.sub(center)) - self.newpoint=Vector.add(center,fcvec.rotate(Vector(rad,0,0),-ang2)) + ang1 = DraftVecUtils.angle(v2.sub(center)) + ang2 = DraftVecUtils.angle(point.sub(center)) + self.newpoint=Vector.add(center,DraftVecUtils.rotate(Vector(rad,0,0),-ang2)) self.ui.labelRadius.setText("Angle") dist = math.degrees(-ang2) # if ang1 > ang2: ang1,ang2 = ang2,ang1 @@ -2796,11 +2793,11 @@ class Trimex(Modifier): if real: if self.force: angle = math.radians(self.force) - newray = fcvec.rotate(Vector(rad,0,0),-angle) + newray = DraftVecUtils.rotate(Vector(rad,0,0),-angle) self.newpoint = Vector.add(center,newray) chord = self.newpoint.sub(v2) perp = chord.cross(Vector(0,0,1)) - scaledperp = fcvec.scaleTo(perp,rad) + scaledperp = DraftVecUtils.scaleTo(perp,rad) midpoint = Vector.add(center,scaledperp) newedges.append(Part.Arc(self.newpoint,midpoint,v2).toShape()) ghost.on() @@ -2815,8 +2812,8 @@ class Trimex(Modifier): ghost.p1(edge.Vertexes[0].Point) ghost.p2(edge.Vertexes[-1].Point) else: - ang1 = fcvec.angle(edge.Vertexes[0].Point.sub(center)) - ang2 = fcvec.angle(edge.Vertexes[-1].Point.sub(center)) + ang1 = DraftVecUtils.angle(edge.Vertexes[0].Point.sub(center)) + ang2 = DraftVecUtils.angle(edge.Vertexes[-1].Point.sub(center)) # if ang1 > ang2: ang1,ang2 = ang2,ang1 ghost.setEndAngle(-ang2) ghost.setStartAngle(-ang1) @@ -2961,7 +2958,7 @@ class Scale(Modifier): self.ghost.trans.scaleFactor.setValue([delta.x,delta.y,delta.z]) corr = Vector(self.node[0].x,self.node[0].y,self.node[0].z) corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(self.node[0])) + corr = DraftVecUtils.neg(corr.sub(self.node[0])) self.ghost.trans.translation.setValue([corr.x,corr.y,corr.z]) if self.extendedCopy: if not hasMod(arg,MODALT): self.finish() @@ -3166,9 +3163,9 @@ class Edit(Modifier): self.editpoints.append(self.obj.Shape.Vertexes[2].Point) v = self.obj.Shape.Vertexes self.bx = v[1].Point.sub(v[0].Point) - if self.obj.Length < 0: self.bx = fcvec.neg(self.bx) + if self.obj.Length < 0: self.bx = DraftVecUtils.neg(self.bx) self.by = v[2].Point.sub(v[1].Point) - if self.obj.Height < 0: self.by = fcvec.neg(self.by) + if self.obj.Height < 0: self.by = DraftVecUtils.neg(self.by) elif Draft.getType(self.obj) == "Polygon": self.editpoints.append(self.obj.Placement.Base) self.editpoints.append(self.obj.Shape.Vertexes[0].Point) @@ -3292,8 +3289,8 @@ class Edit(Modifier): self.obj.Placement = p elif self.editing == 1: diag = v.sub(self.obj.Placement.Base) - nx = fcvec.project(diag,self.bx) - ny = fcvec.project(diag,self.by) + nx = DraftVecUtils.project(diag,self.bx) + ny = DraftVecUtils.project(diag,self.by) ax = nx.Length ay = ny.Length if ax and ay: diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 3cc6519d14..5223ebf667 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -25,18 +25,16 @@ __title__="FreeCAD Draft Trackers" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -import FreeCAD,FreeCADGui,math,Draft +import FreeCAD,FreeCADGui,math,Draft, DraftVecUtils from FreeCAD import Vector -from draftlibs import fcvec from pivy import coin from DraftGui import todo class Tracker: "A generic Draft Tracker, to be used by other specific trackers" def __init__(self,dotted=False,scolor=None,swidth=None,children=[],ontop=False): - global Part, fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils self.ontop = ontop color = coin.SoBaseColor() color.rgb = scolor or FreeCADGui.draftToolBar.getDefaultColor("ui") @@ -161,8 +159,8 @@ class rectangleTracker(Tracker): def update(self,point): "sets the opposite (diagonal) point of the rectangle" diagonal = point.sub(self.origin) - inpoint1 = self.origin.add(fcvec.project(diagonal,self.v)) - inpoint2 = self.origin.add(fcvec.project(diagonal,self.u)) + inpoint1 = self.origin.add(DraftVecUtils.project(diagonal,self.v)) + inpoint2 = self.origin.add(DraftVecUtils.project(diagonal,self.u)) self.coords.point.set1Value(1,inpoint1.x,inpoint1.y,inpoint1.z) self.coords.point.set1Value(2,point.x,point.y,point.z) self.coords.point.set1Value(3,inpoint2.x,inpoint2.y,inpoint2.z) @@ -204,7 +202,7 @@ class rectangleTracker(Tracker): p1 = Vector(self.coords.point.getValues()[0].getValue()) p2 = Vector(self.coords.point.getValues()[2].getValue()) diag = p2.sub(p1) - return ((fcvec.project(diag,self.u)).Length,(fcvec.project(diag,self.v)).Length) + return ((DraftVecUtils.project(diag,self.u)).Length,(DraftVecUtils.project(diag,self.v)).Length) def getNormal(self): "returns the normal of the rectangle" @@ -233,23 +231,23 @@ class dimTracker(Tracker): def calc(self): import Part if (self.p1 != None) and (self.p2 != None): - points = [fcvec.tup(self.p1,True),fcvec.tup(self.p2,True),\ - fcvec.tup(self.p1,True),fcvec.tup(self.p2,True)] + points = [DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True),\ + DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True)] if self.p3 != None: p1 = self.p1 p4 = self.p2 - if fcvec.equals(p1,p4): + if DraftVecUtils.equals(p1,p4): proj = None else: base = Part.Line(p1,p4).toShape() - proj = fcgeo.findDistance(self.p3,base) + proj = DraftGeomUtils.findDistance(self.p3,base) if not proj: p2 = p1 p3 = p4 else: - p2 = p1.add(fcvec.neg(proj)) - p3 = p4.add(fcvec.neg(proj)) - points = [fcvec.tup(p1),fcvec.tup(p2),fcvec.tup(p3),fcvec.tup(p4)] + p2 = p1.add(DraftVecUtils.neg(proj)) + p3 = p4.add(DraftVecUtils.neg(proj)) + points = [DraftVecUtils.tup(p1),DraftVecUtils.tup(p2),DraftVecUtils.tup(p3),DraftVecUtils.tup(p4)] self.coords.point.setValues(0,4,points) class bsplineTracker(Tracker): @@ -340,7 +338,7 @@ class arcTracker(Tracker): center = Vector(c[0],c[1],c[2]) base = FreeCAD.DraftWorkingPlane.u rad = pt.sub(center) - return(fcvec.angle(rad,base,FreeCAD.DraftWorkingPlane.axis)) + return(DraftVecUtils.angle(rad,base,FreeCAD.DraftWorkingPlane.axis)) def getAngles(self): "returns the start and end angles" @@ -496,7 +494,7 @@ class wireTracker(Tracker): "A wire tracker" def __init__(self,wire): self.line = coin.SoLineSet() - self.closed = fcgeo.isReallyClosed(wire) + self.closed = DraftGeomUtils.isReallyClosed(wire) if self.closed: self.line.numVertices.setValue(len(wire.Vertexes)+1) else: @@ -626,11 +624,11 @@ class gridTracker(Tracker): "returns the closest node from the given point" # get the 2D coords. point = FreeCAD.DraftWorkingPlane.projectPoint(point) - u = fcvec.project(point,FreeCAD.DraftWorkingPlane.u) + u = DraftVecUtils.project(point,FreeCAD.DraftWorkingPlane.u) lu = u.Length if u.getAngle(FreeCAD.DraftWorkingPlane.u) > 1.5: lu = -lu - v = fcvec.project(point,FreeCAD.DraftWorkingPlane.v) + v = DraftVecUtils.project(point,FreeCAD.DraftWorkingPlane.v) lv = v.Length if v.getAngle(FreeCAD.DraftWorkingPlane.v) > 1.5: lv = -lv @@ -659,8 +657,7 @@ class boxTracker(Tracker): Tracker.__init__(self,children=[self.trans,m,self.cube]) def update(self,line=None,normal=None): - import WorkingPlane - from draftlibs import fcgeo + import WorkingPlane, DraftGeomUtils if not normal: normal = FreeCAD.DraftWorkingPlane.axis if line: @@ -668,10 +665,10 @@ class boxTracker(Tracker): bp = line[0] lvec = line[1].sub(line[0]) else: - lvec = fcgeo.vec(line.Shape.Edges[0]) + lvec = DraftGeomUtils.vec(line.Shape.Edges[0]) bp = line.Shape.Edges[0].Vertexes[0].Point elif self.baseline: - lvec = fcgeo.vec(self.baseline.Shape.Edges[0]) + lvec = DraftGeomUtils.vec(self.baseline.Shape.Edges[0]) bp = self.baseline.Shape.Edges[0].Vertexes[0].Point else: return @@ -679,12 +676,12 @@ class boxTracker(Tracker): self.cube.width.setValue(lvec.Length) p = WorkingPlane.getPlacementFromPoints([bp,bp.add(lvec),bp.add(right)]) self.trans.rotation.setValue(p.Rotation.Q) - bp = bp.add(fcvec.scale(lvec,0.5)) - bp = bp.add(fcvec.scaleTo(normal,self.cube.depth.getValue()/2)) + bp = bp.add(DraftVecUtils.scale(lvec,0.5)) + bp = bp.add(DraftVecUtils.scaleTo(normal,self.cube.depth.getValue()/2)) self.pos(bp) def pos(self,p): - self.trans.translation.setValue(fcvec.tup(p)) + self.trans.translation.setValue(DraftVecUtils.tup(p)) def width(self,w=None): if w: diff --git a/src/Mod/Draft/draftlibs/fcvec.py b/src/Mod/Draft/DraftVecUtils.py similarity index 100% rename from src/Mod/Draft/draftlibs/fcvec.py rename to src/Mod/Draft/DraftVecUtils.py diff --git a/src/Mod/Draft/Makefile.am b/src/Mod/Draft/Makefile.am index 2502ec4d21..f93f64cfe2 100644 --- a/src/Mod/Draft/Makefile.am +++ b/src/Mod/Draft/Makefile.am @@ -13,6 +13,8 @@ data_DATA = \ DraftGui.py \ DraftSnap.py \ DraftTrackers.py \ + DraftVecUtils.py \ + DraftGeomUtils.py \ WorkingPlane.py \ importOCA.py \ importDXF.py \ @@ -28,8 +30,6 @@ nobase_data_DATA = \ draftlibs/dxfImportObjects.py \ draftlibs/dxfLibrary.py \ draftlibs/dxfReader.py \ - draftlibs/fcvec.py \ - draftlibs/fcgeo.py \ draftlibs/__init__.py CLEANFILES = $(BUILT_SOURCES) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index b722f22ff9..e41eaabf76 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -22,9 +22,8 @@ #*************************************************************************** -import FreeCAD, FreeCADGui, math +import FreeCAD, FreeCADGui, math, DraftVecUtils from FreeCAD import Vector -from draftlibs import fcvec __title__="FreeCAD Working Plane utility" __author__ = "Ken Cline" @@ -51,7 +50,7 @@ class plane: self.stored = None def __repr__(self): - return "Workplane x="+str(fcvec.rounded(self.u))+" y="+str(fcvec.rounded(self.v))+" z="+str(fcvec.rounded(self.axis)) + return "Workplane x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis)) def offsetToPoint(self, p, direction=None): ''' @@ -96,10 +95,10 @@ class plane: self.doc = FreeCAD.ActiveDocument self.axis = axis; self.axis.normalize() - if (fcvec.equals(axis, Vector(1,0,0))): + if (DraftVecUtils.equals(axis, Vector(1,0,0))): self.u = Vector(0,1,0) self.v = Vector(0,0,1) - elif (fcvec.equals(axis, Vector(-1,0,0))): + elif (DraftVecUtils.equals(axis, Vector(-1,0,0))): self.u = Vector(0,-1,0) self.v = Vector(0,0,1) elif upvec: @@ -109,12 +108,12 @@ class plane: else: self.v = axis.cross(Vector(1,0,0)) self.v.normalize() - self.u = fcvec.rotate(self.v, -math.pi/2, self.axis) + self.u = DraftVecUtils.rotate(self.v, -math.pi/2, self.axis) offsetVector = Vector(axis); offsetVector.multiply(offset) self.position = point.add(offsetVector) self.weak = False # FreeCAD.Console.PrintMessage("(position = " + str(self.position) + ")\n") - # FreeCAD.Console.PrintMessage("Current workplane: x="+str(fcvec.rounded(self.u))+" y="+str(fcvec.rounded(self.v))+" z="+str(fcvec.rounded(self.axis))+"\n") + # FreeCAD.Console.PrintMessage("Current workplane: x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis))+"\n") def alignToCurve(self, shape, offset): if shape.ShapeType == 'Edge': @@ -162,7 +161,7 @@ class plane: def getRotation(self): "returns a placement describing the working plane orientation ONLY" - m = fcvec.getPlaneRotation(self.u,self.v,self.axis) + m = DraftVecUtils.getPlaneRotation(self.u,self.v,self.axis) return FreeCAD.Placement(m) def getPlacement(self): @@ -197,15 +196,15 @@ class plane: def getLocalCoords(self,point): "returns the coordinates of a given point on the working plane" - xv = fcvec.project(point,self.u) + xv = DraftVecUtils.project(point,self.u) x = xv.Length if xv.getAngle(self.u) > 1: x = -x - yv = fcvec.project(point,self.v) + yv = DraftVecUtils.project(point,self.v) y = yv.Length if yv.getAngle(self.v) > 1: y = -y - zv = fcvec.project(point,self.axis) + zv = DraftVecUtils.project(point,self.axis) z = zv.Length if zv.getAngle(self.axis) > 1: z = -z @@ -213,9 +212,9 @@ class plane: def getGlobalCoords(self,point): "returns the global coordinates of the given point, taken relatively to this working plane" - vx = fcvec.scale(self.u,point.x) - vy = fcvec.scale(self.v,point.y) - vz = fcvec.scale(self.axis,point.z) + vx = DraftVecUtils.scale(self.u,point.x) + vy = DraftVecUtils.scale(self.v,point.y) + vz = DraftVecUtils.scale(self.axis,point.z) return (vx.add(vy)).add(vz) def getClosestAxis(self,point): @@ -223,9 +222,9 @@ class plane: ax = point.getAngle(self.u) ay = point.getAngle(self.v) az = point.getAngle(self.axis) - bx = point.getAngle(fcvec.neg(self.u)) - by = point.getAngle(fcvec.neg(self.v)) - bz = point.getAngle(fcvec.neg(self.axis)) + bx = point.getAngle(DraftVecUtils.neg(self.u)) + by = point.getAngle(DraftVecUtils.neg(self.v)) + bz = point.getAngle(DraftVecUtils.neg(self.axis)) b = min(ax,ay,az,bx,by,bz) if b in [ax,bx]: return "x" diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 2c0474f8ed..f71e101666 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -40,8 +40,8 @@ lines, polylines, lwpolylines, circles, arcs, texts, colors,layers (from groups) ''' -import FreeCAD, os, Part, math, re, string, Mesh, Draft -from draftlibs import fcvec, dxfColorMap, dxfLibrary, fcgeo +import FreeCAD, os, Part, math, re, string, Mesh, Draft, DraftVecUtils, DraftGeomUtils +from draftlibs import dxfColorMap, dxfLibrary from draftlibs.dxfReader import readDXF from Draft import _Dimension, _ViewProviderDimension from FreeCAD import Vector @@ -134,10 +134,10 @@ def calcBulge(v1,bulge,v2): ''' chord = v2.sub(v1) sagitta = (bulge * chord.Length)/2 - startpoint = v1.add(fcvec.scale(chord,0.5)) + startpoint = v1.add(DraftVecUtils.scale(chord,0.5)) perp = chord.cross(Vector(0,0,1)) - if not fcvec.isNull(perp): perp.normalize() - endpoint = fcvec.scale(perp,sagitta) + if not DraftVecUtils.isNull(perp): perp.normalize() + endpoint = DraftVecUtils.scale(perp,sagitta) return startpoint.add(endpoint) def getGroup(ob,exportList): @@ -218,7 +218,7 @@ class fcformat: v1 = FreeCAD.Vector(r1,g1,b1) v2 = FreeCAD.Vector(r2,g2,b2) v = v2.sub(v1) - v = fcvec.scale(v,0.5) + v = DraftVecUtils.scale(v,0.5) cv = v1.add(v) else: c1 = bparams.GetUnsigned("BackgroundColor") @@ -348,7 +348,7 @@ def drawLine(line,shapemode=False): if (len(line.points) > 1): v1=vec(line.points[0]) v2=vec(line.points[1]) - if not fcvec.equals(v1,v2): + if not DraftVecUtils.equals(v1,v2): try: if (fmt.paramstyle >= 4) and (not shapemode): return Draft.makeWire([v1,v2]) @@ -370,11 +370,11 @@ def drawPolyline(polyline,shapemode=False,num=None): v1 = vec(p1) v2 = vec(p2) verts.append(v1) - if not fcvec.equals(v1,v2): + if not DraftVecUtils.equals(v1,v2): if polyline.points[p].bulge: curves = True cv = calcBulge(v1,polyline.points[p].bulge,v2) - if fcvec.isColinear([v1,cv,v2]): + if DraftVecUtils.isColinear([v1,cv,v2]): try: edges.append(Part.Line(v1,v2).toShape()) except: warn(polyline,num) else: @@ -390,8 +390,8 @@ def drawPolyline(polyline,shapemode=False,num=None): v1 = vec(p1) v2 = vec(p2) cv = calcBulge(v1,polyline.points[-1].bulge,v2) - if not fcvec.equals(v1,v2): - if fcvec.isColinear([v1,cv,v2]): + if not DraftVecUtils.equals(v1,v2): + if DraftVecUtils.isColinear([v1,cv,v2]): try: edges.append(Part.Line(v1,v2).toShape()) except: @@ -722,11 +722,11 @@ def addText(text,attrib=False): rz = rawValue(text,31) if rx or ry or rz: xv = Vector(rx,ry,rz) - if not fcvec.isNull(xv): - ax = fcvec.neg(xv.cross(Vector(1,0,0))) - if fcvec.isNull(ax): + if not DraftVecUtils.isNull(xv): + ax = DraftVecUtils.neg(xv.cross(Vector(1,0,0))) + if DraftVecUtils.isNull(ax): ax = Vector(0,0,1) - ang = -math.degrees(fcvec.angle(xv,Vector(1,0,0),ax)) + ang = -math.degrees(DraftVecUtils.angle(xv,Vector(1,0,0),ax)) Draft.rotate(newob,ang,axis=ax) elif hasattr(text,"rotation"): if text.rotation: @@ -885,7 +885,7 @@ def processdxf(document,filename): edges = [] for s in shapes: edges.extend(s.Edges) - shapes = fcgeo.findWires(edges) + shapes = DraftGeomUtils.findWires(edges) for s in shapes: newob = addObject(s) @@ -1198,13 +1198,13 @@ def getArcData(edge): # check the midpoint seems more reliable ve1 = edge.Vertexes[0].Point ve2 = edge.Vertexes[-1].Point - ang1 = -math.degrees(fcvec.angle(ve1.sub(ce))) - ang2 = -math.degrees(fcvec.angle(ve2.sub(ce))) - ve3 = fcgeo.findMidpoint(edge) - ang3 = -math.degrees(fcvec.angle(ve3.sub(ce))) + ang1 = -math.degrees(DraftVecUtils.angle(ve1.sub(ce))) + ang2 = -math.degrees(DraftVecUtils.angle(ve2.sub(ce))) + ve3 = DraftGeomUtils.findMidpoint(edge) + ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce))) if (ang3 < ang1) and (ang2 < ang3): ang1, ang2 = ang2, ang1 - return fcvec.tup(ce), radius, ang1, ang2 + return DraftVecUtils.tup(ce), radius, ang1, ang2 def getSplineSegs(edge): "returns an array of vectors from a bSpline edge" @@ -1228,18 +1228,18 @@ def getSplineSegs(edge): def getWire(wire,nospline=False): "returns an array of dxf-ready points and bulges from a wire" - edges = fcgeo.sortEdges(wire.Edges) + edges = DraftGeomUtils.sortEdges(wire.Edges) points = [] for edge in edges: v1 = edge.Vertexes[0].Point if len(edge.Vertexes) < 2: points.append((v1.x,v1.y,v1.z,None,None,0.0)) elif (isinstance(edge.Curve,Part.Circle)): - mp = fcgeo.findMidpoint(edge) + mp = DraftGeomUtils.findMidpoint(edge) v2 = edge.Vertexes[-1].Point c = edge.Curve.Center - angle = abs(fcvec.angle(v1.sub(c),v2.sub(c))) - # if (fcvec.angle(v2.sub(c)) < fcvec.angle(v1.sub(c))): + angle = abs(DraftVecUtils.angle(v1.sub(c),v2.sub(c))) + # if (DraftVecUtils.angle(v2.sub(c)) < DraftVecUtils.angle(v1.sub(c))): # angle = -angle # polyline bulge -> negative makes the arc go clockwise bul = math.tan(angle/4) @@ -1259,9 +1259,9 @@ def getWire(wire,nospline=False): points.append((p.x,p.y,p.z,None,None,0.0)) else: points.append((v1.x,v1.y,v1.z,None,None,0.0)) - if not fcgeo.isReallyClosed(wire): + if not DraftGeomUtils.isReallyClosed(wire): v = edges[-1].Vertexes[-1].Point - points.append(fcvec.tup(v)) + points.append(DraftVecUtils.tup(v)) # print "wire verts: ",points return points @@ -1289,7 +1289,7 @@ def writeShape(ob,dxfobject,nospline=False): layer=getGroup(ob,exportList))) else: dxfobject.append(dxfLibrary.PolyLine(getWire(wire,nospline), [0.0,0.0,0.0], - int(fcgeo.isReallyClosed(wire)), color=getACI(ob), + int(DraftGeomUtils.isReallyClosed(wire)), color=getACI(ob), layer=getGroup(ob,exportList))) if len(processededges) < len(ob.Shape.Edges): # lone edges loneedges = [] @@ -1318,7 +1318,7 @@ def writeShape(ob,dxfobject,nospline=False): else: # anything else is treated as lines ve1=edge.Vertexes[0].Point ve2=edge.Vertexes[1].Point - dxfobject.append(dxfLibrary.Line([fcvec.tup(ve1), fcvec.tup(ve2)], + dxfobject.append(dxfLibrary.Line([DraftVecUtils.tup(ve1), DraftVecUtils.tup(ve2)], color=getACI(ob), layer=getGroup(ob,exportList))) @@ -1377,7 +1377,7 @@ def export(objectslist,filename,nospline=False): # 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 = fcvec.tup(FreeCAD.Vector(ob.Position.x, + 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) @@ -1388,14 +1388,14 @@ def export(objectslist,filename,nospline=False): layer=getGroup(ob,exportList))) elif 'Dimline' in ob.PropertiesList: - p1 = fcvec.tup(ob.Start) - p2 = fcvec.tup(ob.End) + p1 = DraftVecUtils.tup(ob.Start) + p2 = DraftVecUtils.tup(ob.End) base = Part.Line(ob.Start,ob.End).toShape() - proj = fcgeo.findDistance(ob.Dimline,base) + proj = DraftGeomUtils.findDistance(ob.Dimline,base) if not proj: - pbase = fcvec.tup(ob.End) + pbase = DraftVecUtils.tup(ob.End) else: - pbase = fcvec.tup(ob.End.add(fcvec.neg(proj))) + pbase = DraftVecUtils.tup(ob.End.add(DraftVecUtils.neg(proj))) dxf.append(dxfLibrary.Dimension(pbase,p1,p2,color=getACI(ob), layer=getGroup(ob,exportList))) diff --git a/src/Mod/Draft/importOCA.py b/src/Mod/Draft/importOCA.py index 58131d8300..79e769aa2f 100644 --- a/src/Mod/Draft/importOCA.py +++ b/src/Mod/Draft/importOCA.py @@ -29,8 +29,7 @@ __url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"] This script imports OCA/gcad files into FreeCAD. ''' -import FreeCAD, os, Part, math -from draftlibs import fcvec, fcgeo +import FreeCAD, os, Part, math, DraftVecUtils, DraftGeomUtils from FreeCAD import Vector try: import FreeCADGui @@ -56,7 +55,7 @@ def getpoint(data): if (data[1][0] == "R"): return objects[data[0]].add(objects[data[1]]) elif (data[1][0] == "C"): - return fcgeo.findProjection(objects[data[0]],objects[data[1]]) + return DraftGeomUtils.findProjection(objects[data[0]],objects[data[1]]) elif (data[0][0] == "C"): if objects[data[0]]: p1 = objects[data[0]].Curve.Position @@ -65,7 +64,7 @@ def getpoint(data): else: if (data[1][0] == "L"): l = objects[data[1]] - return p1.add(fcgeo.vec(l)) + return p1.add(DraftGeomUtils.vec(l)) def getarea(data): "turns an OCA area definition into a FreeCAD Part Wire" @@ -111,7 +110,7 @@ def getarc(data): c = Part.Circle() c.Center = verts[0] if rad: c.Radius = rad - else: c.Radius = fcvec.new(verts[0],verts[1]).Length + else: c.Radius = DraftVecUtils.new(verts[0],verts[1]).Length elif (data[0][0] == "L"): # 2-lines circle lines = [] @@ -121,7 +120,7 @@ def getarc(data): rad = float(data[p+1]) elif (data[p][0] == "L"): lines.append(objects[data[p]]) - circles = fcgeo.circleFrom2LinesRadius(lines[0],lines[1],rad) + circles = DraftGeomUtils.circleFrom2LinesRadius(lines[0],lines[1],rad) if circles: c = circles[0] if c: return c.toShape() @@ -268,7 +267,7 @@ def export(exportList,filename): oca.write("C"+str(count)+"=ARC ") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") - oca.write(writepoint(fcgeo.findMidpoint(e))) + oca.write(writepoint(DraftGeomUtils.findMidpoint(e))) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) else: diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index b49d4735c7..099041d0ad 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -38,9 +38,7 @@ currently unsupported: use, image # implement inherting fill style from group # handle relative units -import xml.sax, string, FreeCAD, os, math, re, Draft -from draftlibs import fcvec -from draftlibs import fcgeo +import xml.sax, string, FreeCAD, os, math, re, Draft, DraftVecUtils, DraftGeomUtils from FreeCAD import Vector try: import FreeCADGui @@ -271,7 +269,7 @@ def makewire(path,checkclosed=False,donttry=False): #ToDo Do not catch all exceptions if not donttry: try: - sh = Part.Wire(fcgeo.sortEdges(path)) + sh = Part.Wire(DraftGeomUtils.sortEdges(path)) #sh = Part.Wire(path) isok = (not checkclosed) or sh.isClosed() except:# BRep_API:command not done @@ -334,13 +332,13 @@ def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False): m2=FreeCAD.Matrix() m2.rotateZ(xrotation) centeroff = currentvec.add(lastvec) - centeroff = fcvec.scale(centeroff,.5) + centeroff = DraftVecUtils.scale(centeroff,.5) vcenter = m2.multiply(vcx1).add(centeroff) # Step3 F.6.5.3 #angle1 = Vector(1,0,0).getAngle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5 #angledelta = Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0).getAngle(Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6 #we need the right sign for the angle - angle1 = fcvec.angle(Vector(1,0,0),Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5 - angledelta = fcvec.angle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0),Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6 + angle1 = DraftVecUtils.angle(Vector(1,0,0),Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5 + angledelta = DraftVecUtils.angle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0),Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6 results.append((vcenter,angle1,angledelta)) return results,(rx,ry) @@ -558,7 +556,7 @@ class svgHandler(xml.sax.ContentHandler): currentvec = lastvec.add(Vector(x,-y,0)) else: currentvec = Vector(x,-y,0) - if not fcvec.equals(lastvec,currentvec): + if not DraftVecUtils.equals(lastvec,currentvec): seg = Part.Line(lastvec,currentvec).toShape() FreeCAD.Console.PrintMessage("line %s %s\n" %(lastvec,currentvec)) lastvec = currentvec @@ -599,15 +597,15 @@ class svgHandler(xml.sax.ContentHandler): # here is a better way to find the perpendicular if sweepflag == 1: # clockwise - perp = fcvec.rotate2D(chord,-math.pi/2) + perp = DraftVecUtils.rotate2D(chord,-math.pi/2) else: # anticlockwise - perp = fcvec.rotate2D(chord,math.pi/2) - chord = fcvec.scale(chord,.5) + perp = DraftVecUtils.rotate2D(chord,math.pi/2) + chord = DraftVecUtils.scale(chord,.5) if chord.Length > rx: a = 0 else: a = math.sqrt(rx**2-chord.Length**2) s = rx - a - perp = fcvec.scale(perp,s/perp.Length) + perp = DraftVecUtils.scale(perp,s/perp.Length) midpoint = lastvec.add(chord.add(perp)) seg = Part.Arc(lastvec,midpoint,currentvec).toShape() else:# big arc or elliptical arc @@ -676,7 +674,7 @@ class svgHandler(xml.sax.ContentHandler): currentvec = Vector(x,-y,0) pole2 = Vector(p2x,-p2y,0) - if not fcvec.equals(currentvec,lastvec): + if not DraftVecUtils.equals(currentvec,lastvec): mainv = currentvec.sub(lastvec) pole1v = lastvec.add(pole1) pole2v = currentvec.add(pole2) @@ -718,7 +716,7 @@ class svgHandler(xml.sax.ContentHandler): else: currentvec = Vector(x,-y,0) - if not fcvec.equals(currentvec,lastvec): + if not DraftVecUtils.equals(currentvec,lastvec): if True and \ pole.distanceToLine(lastvec,currentvec) < 20**(-1*(2+Draft.precision())): #print "straight segment" @@ -733,7 +731,7 @@ class svgHandler(xml.sax.ContentHandler): lastpole = ('quadratic',pole) path.append(seg) elif (d == "Z") or (d == "z"): - if not fcvec.equals(lastvec,firstvec): + if not DraftVecUtils.equals(lastvec,firstvec): seg = Part.Line(lastvec,firstvec).toShape() path.append(seg) if path: #the path should be closed by now @@ -821,7 +819,7 @@ class svgHandler(xml.sax.ContentHandler): esh.append(arc.toShape()) for esh1,esh2 in zip(esh[-1:]+esh[:-1],esh): p1,p2 = esh1.Vertexes[-1].Point,esh2.Vertexes[0].Point - if not fcvec.equals(p1,p2): + if not DraftVecUtils.equals(p1,p2): edges.append(Part.Line(esh1.Vertexes[-1].Point,esh2.Vertexes[0].Point).toShape()) #straight segments edges.append(esh2) # elliptical segments sh = Part.Wire(edges) @@ -859,7 +857,7 @@ class svgHandler(xml.sax.ContentHandler): points=points+points[:2] # emulate closepath for svgx,svgy in zip(points[2::2],points[3::2]): currentvec = Vector(svgx,-svgy,0) - if not fcvec.equals(lastvec,currentvec): + if not DraftVecUtils.equals(lastvec,currentvec): seg = Part.Line(lastvec,currentvec).toShape() #print "polyline seg ",lastvec,currentvec lastvec = currentvec diff --git a/src/WindowsInstaller/ModDraft.wxi b/src/WindowsInstaller/ModDraft.wxi index 13fcc92ff6..720a39810a 100644 --- a/src/WindowsInstaller/ModDraft.wxi +++ b/src/WindowsInstaller/ModDraft.wxi @@ -38,6 +38,8 @@ + + @@ -46,8 +48,6 @@ - - From 532d89ee3edc4162ea2367b0089df5fe2a99927a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 12:00:03 -0300 Subject: [PATCH 216/351] Further Draft lib name fixes --- src/Mod/Arch/ArchSectionPlane.py | 3 +- src/Mod/Draft/DraftGeomUtils.py | 170 +++++++++++++++---------------- 2 files changed, 87 insertions(+), 86 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 59c8023827..e1230e59f7 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,Drawing,math,Draft,ArchCommands, DraftVecUtils +import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,math,Draft,ArchCommands, DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore from pivy import coin @@ -197,6 +197,7 @@ class _ArchDrawingView: else: # render using the Drawing module + import Drawing shapes = [] for o in objs: if o.isDerivedFrom("Part::Feature"): diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index ccacbf62c9..16468ad0c1 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -27,7 +27,7 @@ __url__ = ["http://free-cad.sourceforge.net"] "this file contains generic geometry functions for manipulating Part shapes" -import FreeCAD, Part, fcvec, math, cmath +import FreeCAD, Part, DraftVecUtils, math, cmath from FreeCAD import Vector NORM = Vector(0,0,1) # provisory normal direction for all geometry ops. @@ -51,7 +51,7 @@ def vec(edge): def edg(p1,p2): "edg(Vector,Vector) -- returns an edge from 2 vectors" if isinstance(p1,FreeCAD.Vector) and isinstance(p2,FreeCAD.Vector): - if fcvec.equals(p1,p2): return None + if DraftVecUtils.equals(p1,p2): return None else: return Part.Line(p1,p2).toShape() def getVerts(shape): @@ -85,7 +85,7 @@ def isPtOnEdge(pt,edge) : '''isPtOnEdge(Vector,edge) -- Tests if a point is on an edge''' if isinstance(edge.Curve,Part.Line) : orig = edge.Vertexes[0].Point - if fcvec.isNull(pt.sub(orig).cross(vec(edge))) : + if DraftVecUtils.isNull(pt.sub(orig).cross(vec(edge))) : return pt.sub(orig).Length <= vec(edge).Length and pt.sub(orig).dot(vec(edge)) >= 0 else : return False @@ -101,16 +101,16 @@ def isPtOnEdge(pt,edge) : else : begin = edge.Vertexes[0].Point end = edge.Vertexes[-1].Point - if fcvec.isNull(pt.sub(begin)) or fcvec.isNull(pt.sub(end)) : + if DraftVecUtils.isNull(pt.sub(begin)) or DraftVecUtils.isNull(pt.sub(end)) : return True else : # newArc = Part.Arc(begin,pt,end) - # return fcvec.isNull(newArc.Center.sub(center)) \ - # and fcvec.isNull(newArc.Axis-axis) \ + # return DraftVecUtils.isNull(newArc.Center.sub(center)) \ + # and DraftVecUtils.isNull(newArc.Axis-axis) \ # and round(newArc.Radius-radius,precision) == 0 - angle1 = fcvec.angle(begin.sub(center)) - angle2 = fcvec.angle(end.sub(center)) - anglept = fcvec.angle(pt.sub(center)) + angle1 = DraftVecUtils.angle(begin.sub(center)) + angle2 = DraftVecUtils.angle(end.sub(center)) + anglept = DraftVecUtils.angle(pt.sub(center)) if (angle1 < anglept) and (anglept < angle2): return True return False @@ -165,8 +165,8 @@ def findEdge(anEdge,aList): '''findEdge(anEdge,aList): returns True if anEdge is found in aList of edges''' for e in range(len(aList)): if str(anEdge.Curve) == str(aList[e].Curve): - if fcvec.equals(anEdge.Vertexes[0].Point,aList[e].Vertexes[0].Point): - if fcvec.equals(anEdge.Vertexes[-1].Point,aList[e].Vertexes[-1].Point): + if DraftVecUtils.equals(anEdge.Vertexes[0].Point,aList[e].Vertexes[0].Point): + if DraftVecUtils.equals(anEdge.Vertexes[-1].Point,aList[e].Vertexes[-1].Point): return(e) return None @@ -202,13 +202,13 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F return [pt2] #we have 2 straight lines - if fcvec.isNull(pt2.sub(pt1).cross(pt3.sub(pt1)).cross(pt2.sub(pt4).cross(pt3.sub(pt4)))): + if DraftVecUtils.isNull(pt2.sub(pt1).cross(pt3.sub(pt1)).cross(pt2.sub(pt4).cross(pt3.sub(pt4)))): vec1 = pt2.sub(pt1) ; vec2 = pt4.sub(pt3) - if fcvec.isNull(vec1) or fcvec.isNull(vec2): + if DraftVecUtils.isNull(vec1) or DraftVecUtils.isNull(vec2): return [] vec1.normalize() ; vec2.normalize() cross = vec1.cross(vec2) - if not fcvec.isNull(cross) : + if not DraftVecUtils.isNull(cross) : k = ((pt3.z-pt1.z)*(vec2.x-vec2.y)+(pt3.y-pt1.y)*(vec2.z-vec2.x)+ \ (pt3.x-pt1.x)*(vec2.y-vec2.z))/(cross.x+cross.y+cross.z) vec1.scale(k,k,k) @@ -251,7 +251,7 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F elif (pt2 in [pt3,pt4]): return [pt2] - if fcvec.isNull(pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)) : + if DraftVecUtils.isNull(pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)) : # Line and Arc are on same plane dOnLine = center.sub(pt1).dot(dirVec) @@ -303,18 +303,18 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F axis1, axis2 = edge1.Curve.Axis , edge2.Curve.Axis c2c = cent2.sub(cent1) - if fcvec.isNull(axis1.cross(axis2)) : + if DraftVecUtils.isNull(axis1.cross(axis2)) : if round(c2c.dot(axis1),precision) == 0 : # circles are on same plane dc2c = c2c.Length ; - if not fcvec.isNull(c2c): c2c.normalize() + if not DraftVecUtils.isNull(c2c): c2c.normalize() if round(rad1+rad2-dc2c,precision) < 0 \ or round(rad1-dc2c-rad2,precision) > 0 or round(rad2-dc2c-rad1,precision) > 0 : return [] else : norm = c2c.cross(axis1) - if not fcvec.isNull(norm): norm.normalize() - if fcvec.isNull(norm): x = 0 + if not DraftVecUtils.isNull(norm): norm.normalize() + if DraftVecUtils.isNull(norm): x = 0 else: x = (dc2c**2 + rad1**2 - rad2**2)/(2*dc2c) y = abs(rad1**2 - x**2)**(0.5) c2c.scale(x,x,x) @@ -369,8 +369,8 @@ def geom(edge): v2 = edge.Vertexes[-1].Point c = edge.Curve.Center cu = Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius) - a1 = -fcvec.angle(v1.sub(c),ref,edge.Curve.Axis) - a2 = -fcvec.angle(v2.sub(c),ref,edge.Curve.Axis) + a1 = -DraftVecUtils.angle(v1.sub(c),ref,edge.Curve.Axis) + a2 = -DraftVecUtils.angle(v2.sub(c),ref,edge.Curve.Axis) 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 @@ -382,7 +382,7 @@ def mirror (point, edge): normPoint = point.add(findDistance(point, edge, False)) if normPoint: normPoint_point = Vector.sub(point, normPoint) - normPoint_refl = fcvec.neg(normPoint_point) + normPoint_refl = DraftVecUtils.neg(normPoint_point) refl = Vector.add(normPoint, normPoint_refl) return refl else: @@ -547,13 +547,13 @@ def findWires(edgeslist): return False if len(e2.Vertexes) < 2: return False - if fcvec.equals(e1.Vertexes[0].Point,e2.Vertexes[0].Point): + if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[0].Point): return True - if fcvec.equals(e1.Vertexes[0].Point,e2.Vertexes[-1].Point): + if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[-1].Point): return True - if fcvec.equals(e1.Vertexes[-1].Point,e2.Vertexes[0].Point): + if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[0].Point): return True - if fcvec.equals(e1.Vertexes[-1].Point,e2.Vertexes[-1].Point): + if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[-1].Point): return True return False @@ -656,7 +656,7 @@ def findMidpoint(edge): if len(edge.Vertexes) == 1: # Circle dv = first.sub(center) - dv = fcvec.neg(dv) + dv = DraftVecUtils.neg(dv) return center.add(dv) axis = edge.Curve.Axis chord = last.sub(first) @@ -665,12 +665,12 @@ def findMidpoint(edge): ray = first.sub(center) apothem = ray.dot(perp) sagitta = radius - apothem - startpoint = Vector.add(first, fcvec.scale(chord,0.5)) - endpoint = fcvec.scaleTo(perp,sagitta) + startpoint = Vector.add(first, DraftVecUtils.scale(chord,0.5)) + endpoint = DraftVecUtils.scaleTo(perp,sagitta) return Vector.add(startpoint,endpoint) elif isinstance(edge.Curve,Part.Line): - halfedge = fcvec.scale(last.sub(first),.5) + halfedge = DraftVecUtils.scale(last.sub(first),.5) return Vector.add(first,halfedge) else: @@ -759,7 +759,7 @@ def isReallyClosed(wire): if len(wire.Edges) == len(wire.Vertexes): return True v1 = wire.Vertexes[0].Point v2 = wire.Vertexes[-1].Point - if fcvec.equals(v1,v2): return True + if DraftVecUtils.equals(v1,v2): return True return False def getNormal(shape): @@ -784,7 +784,7 @@ def getNormal(shape): if FreeCAD.GuiUp: import Draft vdir = Draft.get3DView().getViewDirection() - if n.getAngle(vdir) < 0.78: n = fcvec.neg(n) + if n.getAngle(vdir) < 0.78: n = DraftVecUtils.neg(n) return n def offsetWire(wire,dvec,bind=False,occ=False): @@ -815,8 +815,8 @@ def offsetWire(wire,dvec,bind=False,occ=False): curredge = edges[i] delta = dvec if i != 0: - angle = fcvec.angle(vec(edges[0]),vec(curredge),norm) - delta = fcvec.rotate(delta,angle,norm) + angle = DraftVecUtils.angle(vec(edges[0]),vec(curredge),norm) + delta = DraftVecUtils.rotate(delta,angle,norm) nedge = offset(curredge,delta) nedges.append(nedge) nedges = connect(nedges,closed) @@ -890,7 +890,7 @@ def findDistance(point,edge,strict=False): chord = edge.Vertexes[0].Point.sub(point) norm = segment.cross(chord) perp = segment.cross(norm) - dist = fcvec.project(chord,perp) + dist = DraftVecUtils.project(chord,perp) if not dist: return None newpoint = point.add(dist) if (dist.Length == 0): @@ -912,14 +912,14 @@ def findDistance(point,edge,strict=False): center = edge.Curve.Center segment = center.sub(point) ratio = (segment.Length - edge.Curve.Radius) / segment.Length - dist = fcvec.scale(segment,ratio) + dist = DraftVecUtils.scale(segment,ratio) newpoint = Vector.add(point, dist) if (dist.Length == 0): return None if strict and ve2: - ang1 = fcvec.angle(ve1.sub(center)) - ang2 = fcvec.angle(ve2.sub(center)) - angpt = fcvec.angle(newpoint.sub(center)) + ang1 = DraftVecUtils.angle(ve1.sub(center)) + ang2 = DraftVecUtils.angle(ve2.sub(center)) + angpt = DraftVecUtils.angle(newpoint.sub(center)) if ((angpt <= ang2 and angpt >= ang1) or (angpt <= ang1 and angpt >= ang2)): return dist else: @@ -954,15 +954,15 @@ def angleBisection(edge1, edge2): int = findIntersection(edge1, edge2, True, True) if int: line1Dir = p2.sub(p1) - angleDiff = fcvec.angle(line1Dir, p4.sub(p3)) + angleDiff = DraftVecUtils.angle(line1Dir, p4.sub(p3)) ang = angleDiff * 0.5 origin = int[0] line1Dir.normalize() - dir = fcvec.rotate(line1Dir, ang) + dir = DraftVecUtils.rotate(line1Dir, ang) return Part.Line(origin,origin.add(dir)).toShape() else: diff = p3.sub(p1) - origin = p1.add(fcvec.scale(diff, 0.5)) + origin = p1.add(DraftVecUtils.scale(diff, 0.5)) dir = p2.sub(p1); dir.normalize() return Part.Line(origin,origin.add(dir)).toShape() else: @@ -998,8 +998,8 @@ def isPlanar(shape): n = bt.normalAt(0,0) for p in shape.Vertexes[3:]: pv = p.Point.sub(pts[0]) - rv = fcvec.project(pv,n) - if not fcvec.isNull(rv): + rv = DraftVecUtils.project(pv,n) + if not DraftVecUtils.isNull(rv): return False return True @@ -1216,9 +1216,9 @@ def getCubicDimensions(shape): vx = vec(base.Edges[0]) vy = vec(base.Edges[1]) # getting rotations - rotZ = fcvec.angle(vx) - rotY = fcvec.angle(vx,FreeCAD.Vector(vx.x,vx.y,0)) - rotX = fcvec.angle(vy,FreeCAD.Vector(vy.x,vy.y,0)) + rotZ = DraftVecUtils.angle(vx) + rotY = DraftVecUtils.angle(vx,FreeCAD.Vector(vx.x,vx.y,0)) + rotX = DraftVecUtils.angle(vy,FreeCAD.Vector(vy.x,vy.y,0)) # getting height vz = None rpi = round(math.pi/2,precision) @@ -1687,22 +1687,22 @@ def circlefrom1Line2Points(edge, p1, p2): v2 = p2.sub(s) projectedDist = math.sqrt(abs(v1.dot(v2))) edgeDir = vec(edge); edgeDir.normalize() - projectedCen1 = Vector.add(s, fcvec.scale(edgeDir, projectedDist)) - projectedCen2 = Vector.add(s, fcvec.scale(edgeDir, -projectedDist)) + projectedCen1 = Vector.add(s, DraftVecUtils.scale(edgeDir, projectedDist)) + projectedCen2 = Vector.add(s, DraftVecUtils.scale(edgeDir, -projectedDist)) perpEdgeDir = edgeDir.cross(Vector(0,0,1)) perpCen1 = Vector.add(projectedCen1, perpEdgeDir) perpCen2 = Vector.add(projectedCen2, perpEdgeDir) mid = findMidpoint(p1_p2) - x = fcvec.crossproduct(vec(p1_p2)); x.normalize() + x = DraftVecUtils.crossproduct(vec(p1_p2)); x.normalize() perp_mid = Vector.add(mid, x) cen1 = findIntersection(edg(projectedCen1, perpCen1), edg(mid, perp_mid), True, True) cen2 = findIntersection(edg(projectedCen2, perpCen2), edg(mid, perp_mid), True, True) circles = [] if cen1: - radius = fcvec.dist(projectedCen1, cen1[0]) + radius = DraftVecUtils.dist(projectedCen1, cen1[0]) circles.append(Part.Circle(cen1[0], NORM, radius)) if cen2: - radius = fcvec.dist(projectedCen2, cen2[0]) + radius = DraftVecUtils.dist(projectedCen2, cen2[0]) circles.append(Part.Circle(cen2[0], NORM, radius)) if circles: return circles @@ -1714,26 +1714,26 @@ def circleFrom2LinesRadius (edge1, edge2, radius): if not int: return None int = int[0] bis12 = angleBisection(edge1,edge2) - bis21 = Part.Line(bis12.Vertexes[0].Point,fcvec.rotate(vec(bis12), math.pi/2.0)) - ang12 = abs(fcvec.angle(vec(edge1),vec(edge2))) + bis21 = Part.Line(bis12.Vertexes[0].Point,DraftVecUtils.rotate(vec(bis12), math.pi/2.0)) + ang12 = abs(DraftVecUtils.angle(vec(edge1),vec(edge2))) ang21 = math.pi - ang12 dist12 = radius / math.sin(ang12 * 0.5) dist21 = radius / math.sin(ang21 * 0.5) circles = [] - cen = Vector.add(int, fcvec.scale(vec(bis12), dist12)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis12), dist12)) circles.append(Part.Circle(cen, NORM, radius)) - cen = Vector.add(int, fcvec.scale(vec(bis12), -dist12)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis12), -dist12)) circles.append(Part.Circle(cen, NORM, radius)) - cen = Vector.add(int, fcvec.scale(vec(bis21), dist21)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis21), dist21)) circles.append(Part.Circle(cen, NORM, radius)) - cen = Vector.add(int, fcvec.scale(vec(bis21), -dist21)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis21), -dist21)) circles.append(Part.Circle(cen, NORM, radius)) return circles def circleFrom3LineTangents (edge1, edge2, edge3): "circleFrom3LineTangents(edge,edge,edge)" def rot(ed): - return Part.Line(v1(ed),v1(ed).add(fcvec.rotate(vec(ed),math.pi/2))).toShape() + return Part.Line(v1(ed),v1(ed).add(DraftVecUtils.rotate(vec(ed),math.pi/2))).toShape() bis12 = angleBisection(edge1,edge2) bis23 = angleBisection(edge2,edge3) bis31 = angleBisection(edge3,edge1) @@ -1766,7 +1766,7 @@ def circleFrom3LineTangents (edge1, edge2, edge3): for int in intersections: exists = False for cir in circles: - if fcvec.equals(cir.Center, int.Center): + if DraftVecUtils.equals(cir.Center, int.Center): exists = True break if not exists: @@ -1783,16 +1783,16 @@ def circleFromPointLineRadius (point, edge, radius): center2 = None if dist.Length == 0: segment = vec(edge) - perpVec = fcvec.crossproduct(segment); perpVec.normalize() - normPoint_c1 = fcvec.scale(perpVec, radius) - normPoint_c2 = fcvec.scale(perpVec, -radius) + perpVec = DraftVecUtils.crossproduct(segment); perpVec.normalize() + normPoint_c1 = DraftVecUtils.scale(perpVec, radius) + normPoint_c2 = DraftVecUtils.scale(perpVec, -radius) center1 = point.add(normPoint_c1) center2 = point.add(normPoint_c2) elif dist.Length > 2 * radius: return None elif dist.Length == 2 * radius: normPoint = point.add(findDistance(point, edge, False)) - dummy = fcvec.scale(normPoint.sub(point), 0.5) + dummy = DraftVecUtils.scale(normPoint.sub(point), 0.5) cen = point.add(dummy) circ = Part.Circle(cen, NORM, radius) if circ: @@ -1801,12 +1801,12 @@ def circleFromPointLineRadius (point, edge, radius): return None else: normPoint = point.add(findDistance(point, edge, False)) - normDist = fcvec.dist(normPoint, point) + normDist = DraftVecUtils.dist(normPoint, point) dist = math.sqrt(radius**2 - (radius - normDist)**2) - centerNormVec = fcvec.scaleTo(point.sub(normPoint), radius) + centerNormVec = DraftVecUtils.scaleTo(point.sub(normPoint), radius) edgeDir = edge.Vertexes[0].Point.sub(normPoint); edgeDir.normalize() - center1 = centerNormVec.add(normPoint.add(fcvec.scale(edgeDir, dist))) - center2 = centerNormVec.add(normPoint.add(fcvec.scale(edgeDir, -dist))) + center1 = centerNormVec.add(normPoint.add(DraftVecUtils.scale(edgeDir, dist))) + center2 = centerNormVec.add(normPoint.add(DraftVecUtils.scale(edgeDir, -dist))) circles = [] if center1: circ = Part.Circle(center1, NORM, radius) @@ -1824,10 +1824,10 @@ def circleFromPointLineRadius (point, edge, radius): def circleFrom2PointsRadius(p1, p2, radius): "circleFrom2PointsRadiust(Vector, Vector, radius)" - if fcvec.equals(p1, p2): return None + if DraftVecUtils.equals(p1, p2): return None p1_p2 = Part.Line(p1, p2).toShape() - dist_p1p2 = fcvec.dist(p1, p1) + dist_p1p2 = DraftVecUtils.dist(p1, p1) mid = findMidpoint(p1_p2) if dist_p1p2 == 2*radius: circle = Part.Circle(mid, norm, radius) @@ -1836,8 +1836,8 @@ def circleFrom2PointsRadius(p1, p2, radius): dir = vec(p1_p2); dir.normalize() perpDir = dir.cross(Vector(0,0,1)); perpDir.normailze() dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0)**2) - cen1 = Vector.add(mid, fcvec.scale(perpDir, dist)) - cen2 = Vector.add(mid, fcvec.scale(perpDir, -dist)) + cen1 = Vector.add(mid, DraftVecUtils.scale(perpDir, dist)) + cen2 = Vector.add(mid, DraftVecUtils.scale(perpDir, -dist)) circles = [] if cen1: circles.append(Part.Circle(cen1, norm, radius)) if cen2: circles.append(Part.Circle(cen2, norm, radius)) @@ -2069,7 +2069,7 @@ def findHomotheticCenterOfCircles(circle1, circle2): ''' if isinstance(circle1.Curve, Part.Circle) and isinstance(circle2.Curve, Part.Circle): - if fcvec.equals(circle1.Curve.Center, circle2.Curve.Center): + if DraftVecUtils.equals(circle1.Curve.Center, circle2.Curve.Center): return None cen1_cen2 = Part.Line(circle1.Curve.Center, circle2.Curve.Center).toShape() @@ -2079,21 +2079,21 @@ def findHomotheticCenterOfCircles(circle1, circle2): perpCenDir = cenDir.cross(Vector(0,0,1)); perpCenDir.normalize() # Get point on first circle - p1 = Vector.add(circle1.Curve.Center, fcvec.scale(perpCenDir, circle1.Curve.Radius)) + p1 = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, circle1.Curve.Radius)) centers = [] # Calculate inner homothetic center # Get point on second circle - p2_inner = Vector.add(circle1.Curve.Center, fcvec.scale(perpCenDir, -circle1.Curve.Radius)) - hCenterInner = fcvec.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_inner, True, True) + p2_inner = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, -circle1.Curve.Radius)) + hCenterInner = DraftVecUtils.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_inner, True, True) if hCenterInner: centers.append(hCenterInner) # Calculate outer homothetic center (only exists of the circles have different radii) if circle1.Curve.Radius != circle2.Curve.Radius: # Get point on second circle - p2_outer = Vector.add(circle1.Curve.Center, fcvec.scale(perpCenDir, circle1.Curve.Radius)) - hCenterOuter = fcvec.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_outer, True, True) + p2_outer = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, circle1.Curve.Radius)) + hCenterOuter = DraftVecUtils.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_outer, True, True) if hCenterOuter: centers.append(hCenterOuter) @@ -2121,13 +2121,13 @@ def findRadicalAxis(circle1, circle2): ''' if isinstance(circle1.Curve, Part.Circle) and isinstance(circle2.Curve, Part.Circle): - if fcvec.equals(circle1.Curve.Center, circle2.Curve.Center): + if DraftVecUtils.equals(circle1.Curve.Center, circle2.Curve.Center): return None r1 = circle1.Curve.Radius r2 = circle1.Curve.Radius cen1 = circle1.Curve.Center # dist .. the distance from cen1 to cen2. - dist = fcvec.dist(cen1, circle2.Curve.Center) + dist = DraftVecUtils.dist(cen1, circle2.Curve.Center) cenDir = cen1.sub(circle2.Curve.Center); cenDir.normalize() # Get the perpedicular vector. @@ -2142,7 +2142,7 @@ def findRadicalAxis(circle1, circle2): k1 = (dist + (r1^2 - r2^2) / dist) / 2.0 #k2 = dist - k1 - K = Vector.add(cen1, fcvec.scale(cenDir, k1)) + K = Vector.add(cen1, DraftVecUtils.scale(cenDir, k1)) # K_ .. A point somewhere between K and J (actually with a distance of 1 unit from K). K_ = Vector,add(K, perpCenDir) @@ -2208,13 +2208,13 @@ def pointInversion(circle, point): cen = circle.Curve.Center rad = circle.Curve.Radius - if fcvec.equals(cen, point): + if DraftVecUtils.equals(cen, point): return None # Inverse the distance of the point # dist(cen -> P) = r^2 / dist(cen -> invP) - dist = fcvec.dist(point, cen) + dist = DraftVecUtils.dist(point, cen) invDist = rad**2 / d invPoint = Vector(0, 0, point.z) @@ -2260,7 +2260,7 @@ def circleInversion(circle, circle2): cen1 = circle.Curve.Center rad1 = circle.Curve.Radius - if fcvec.equals(cen1, point): + if DraftVecUtils.equals(cen1, point): return None invCen2 = Inversion(circle, circle2.Curve.Center) @@ -2268,7 +2268,7 @@ def circleInversion(circle, circle2): pointOnCircle2 = Vector.add(circle2.Curve.Center, Vector(circle2.Curve.Radius, 0, 0)) invPointOnCircle2 = Inversion(circle, pointOnCircle2) - return Part.Circle(invCen2, norm, fcvec.dist(invCen2, invPointOnCircle2)) + return Part.Circle(invCen2, norm, DraftVecUtils.dist(invCen2, invPointOnCircle2)) else: print "debug: circleInversion bad parameters!\n" From 5c696b181fdefc39896781ffaf0c74433594408c Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 17:09:06 -0300 Subject: [PATCH 217/351] Added 0000680 : DXF polylines with defined width --- src/Mod/Draft/Draft.py | 3 +- src/Mod/Draft/Draft_rc.py | 410 +++++++++--------- .../Draft/Resources/ui/userprefs-import.ui | 20 + src/Mod/Draft/importDXF.py | 17 +- 4 files changed, 246 insertions(+), 204 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 300bc86923..2e7cf692dd 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -107,7 +107,8 @@ def getParamType(param): elif param in ["textheight","tolerance","gridSpacing"]: return "float" elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit","maxSnap", - "SvgLinesBlack","dxfStdSize","showSnapBar","hideSnapBar","alwaysShowGrid"]: + "SvgLinesBlack","dxfStdSize","showSnapBar","hideSnapBar","alwaysShowGrid", + "renderPolylineWidth"]: return "bool" elif param in ["color","constructioncolor","snapcolor"]: return "unsigned" diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 7ef42e43f0..e1f587ddd4 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,8 +2,8 @@ # Resource object code # -# Created: Fri May 4 19:15:01 2012 -# by: The Resource Compiler for PyQt (Qt v4.7.4) +# Created: Tue May 22 16:46:43 2012 +# by: The Resource Compiler for PyQt (Qt v4.8.1) # # WARNING! All changes made in this file will be lost! @@ -26543,153 +26543,159 @@ qt_resource_data = "\ \x93\x83\x1e\x48\xef\x57\xc6\xa2\x49\xdb\x13\x44\xd4\xba\x3f\x06\ \x46\x3f\xfe\x6c\x03\x93\xf1\x73\xb1\x4b\x54\x79\xc9\xd8\x04\x84\ \x23\xc5\xbe\x37\x98\x7a\x44\xf4\xff\x03\x15\x2c\x14\x99\ -\x00\x00\x09\x10\ +\x00\x00\x09\x69\ \x00\ -\x00\x45\x1d\x78\x9c\xed\x5c\x6d\x73\xdb\x36\x12\xfe\xee\x5f\x81\ -\xd1\x87\xbb\xb4\xe3\x5a\x96\x5f\x93\x9c\xac\x4e\x62\xd7\x49\x6e\ -\x92\x6b\x7a\x72\xd3\xfb\xe6\x81\x48\x48\x44\x4d\x12\x2a\x00\x5a\ -\x52\x7f\xfd\xed\x02\xa0\xf8\x22\xea\xdd\x92\x1c\x8f\x66\x3c\x23\ -\x11\x00\x77\x17\x8b\x67\x17\x8b\xc5\x5a\xcd\x9f\x87\x51\x48\x1e\ -\x99\x54\x5c\xc4\x57\xb5\xc6\xd1\x71\x8d\xb0\xd8\x13\x3e\x8f\x7b\ -\x57\xb5\xdf\xef\x6e\x7f\x7a\x5d\xfb\xb9\x75\xd0\x4c\x78\x36\xe8\ -\x0c\x06\xb5\x0e\x48\xd3\x0b\xa9\x52\xad\x0f\x09\x7f\xfb\xf6\x86\ -\xd3\x50\xf4\xe0\x33\xec\xb5\x99\xd6\xf0\xb2\xba\x91\xb4\xab\x9b\ -\x75\x3b\x08\x46\x0f\xb8\xdf\x63\x9a\x98\xe7\xab\xda\x6f\x7f\x98\ -\xc7\x1a\x89\x69\xc4\xae\x6a\x33\x89\x20\x33\xd2\xec\x4b\xd1\x67\ -\x52\x8f\xdc\x1b\x3d\x26\x22\xa6\xe5\xc8\x74\x92\xa6\x64\x9e\x36\ -\xdf\x48\x73\xd8\x3a\x6e\xd6\x87\xee\x61\x84\x0f\x23\xf7\x00\x22\ -\xe8\xa0\x75\x7e\x79\xde\xac\xdb\xaf\xb6\x39\x60\xbc\x17\xe8\xd6\ -\xc5\xc9\x9b\x66\xdd\x7d\x37\x34\xeb\x29\xd1\x66\x3d\x65\x5e\x25\ -\xc9\x80\xc7\xbe\x18\xdc\x71\x1d\x32\x27\x8c\xd2\x12\x84\x6f\x7d\ -\x8a\xfa\x42\xea\xfa\x2f\x43\xfc\x68\xd6\x5d\xeb\x24\xbd\x90\x8e\ -\x44\x92\x69\xe6\xdb\x7b\x31\xfc\x6c\x9a\x1c\xb9\x12\x3f\xd5\xa7\ -\x1e\x10\xaa\x39\xe9\xe3\x24\xea\x30\xd9\xba\x68\xd6\xdd\x37\x2b\ -\x7b\x9e\xc3\x04\x89\x88\xca\x1e\x8f\x4b\x14\xde\xcc\xa4\xc0\x35\ -\x8b\x32\x35\xe6\x57\xf2\x83\x14\x49\x1f\x64\x1e\xaf\xa5\x7b\x6e\ -\x9c\x38\x06\x13\xec\x75\xa6\xab\x9c\xba\x6e\xfe\x77\x4b\xba\x42\ -\x46\x54\x13\xd1\xd7\x80\x34\x95\xd7\xd9\xa4\x48\xf3\x35\x37\x57\ -\x79\x53\xf5\x57\xc5\x6d\xb6\x16\xa7\x2a\xb2\x9a\x54\xa6\xce\x8a\ -\x79\x7c\x9c\x9c\xc7\x02\x33\x99\x31\x97\x2a\x11\xe6\xcf\x27\x23\ -\x78\xbc\x20\xc1\xc2\xac\x26\x91\xf2\x99\x76\x58\x98\xc2\x44\xb3\ -\xa1\x36\x0d\x8d\xfb\xd3\x3c\xcf\x49\xb4\xc0\xc0\xc2\x80\x92\x81\ -\x11\xa5\x47\x21\x2b\x61\x65\xaa\x8c\xc4\xd8\x3e\x48\x95\x9f\x4a\ -\x51\xee\x39\xd3\x30\xbe\xea\xab\x64\xdd\x6b\x11\x75\x44\x0e\xf8\ -\x3d\xec\xe8\x43\x87\x87\x1d\x1d\xe8\x98\x39\x2d\x21\xc2\x3b\xde\ -\xaf\x9e\xd9\x5d\xc0\x15\x81\x3f\x1d\x30\x02\x6e\x2e\x10\x3e\xf1\ -\x02\x21\x14\xf3\xd1\x44\x08\x37\x13\x87\x81\x04\x1e\xb4\xa4\xb1\ -\x0a\xa9\x79\x44\x1b\x12\x9d\x3f\xc1\x6f\x11\x4f\x84\x38\x32\xd6\ -\x82\xdc\x4a\xc6\xae\xdf\xdd\x1c\x91\x83\x4f\x5d\xd7\x1e\xd1\x7e\ -\x1f\x5f\x00\x1e\x8e\xf0\x21\x01\xc0\x91\x28\x51\xda\xb5\x10\x5a\ -\x1a\xdb\xe5\x21\x83\xa6\x58\x53\x1e\xe3\x33\xcd\x58\x8b\x98\x68\ -\xda\x81\x6e\x1d\x80\xf9\x0e\x78\x18\xe2\x40\xd8\x31\x9c\x1c\xca\ -\x0a\x12\xf2\x98\x19\xcf\xab\x8e\x0e\x16\x5e\xb0\x09\xcd\x79\x89\ -\x94\x2c\xd6\x9f\x62\x9f\x0d\x4b\xea\x9b\x8e\xd7\x45\x89\xe3\xfa\ -\xfd\x12\xe3\xc6\x02\xb8\xf2\x15\xd3\x57\xb5\xe3\x12\x13\xcf\x09\ -\xee\x0f\xbb\x0e\x7a\xde\xaa\x53\x41\x6e\x5f\xa9\x0e\xe6\x33\xfb\ -\x22\xfc\x7a\xba\xa5\x2e\xcc\xad\x04\xe4\x45\x6c\x6b\x0c\xc1\xff\ -\x88\x98\x91\x57\x5d\xaa\x34\x53\xfa\x87\xaa\xd5\x9a\xc6\xb5\x5e\ -\x66\xbb\x96\x1c\xbf\x03\x12\x7d\xd6\xa5\x49\x98\x62\x9a\xc6\x7e\ -\x86\xa4\xdd\x09\xf6\xab\xe4\xe0\x2e\x69\xf8\xbc\xa4\xba\x1e\x9b\ -\x2c\xf8\x8a\xbc\xc9\xed\x50\x24\xc9\xa8\x66\xa4\x4f\x25\xc5\x90\ -\x8d\x7b\xce\x45\x95\xf7\xf7\xed\x8b\xd4\x7e\x60\xda\x0b\xd8\x5a\ -\x82\xcc\xdd\x4f\x9a\x75\xbb\xbd\x67\xd1\x40\xbe\x7b\xe1\x48\xc0\ -\x4d\x2a\x10\x92\xff\x8d\x3e\x38\x9c\x8c\x10\x96\xd9\x7e\x43\x7c\ -\xb8\xbf\x5c\x71\xe7\xfd\x42\x87\xa4\xdd\x47\x6c\x91\x36\xeb\x45\ -\xe0\x8d\x77\xb0\xff\xb6\x61\x57\xaa\xda\x7e\x15\xb4\xc3\xee\x7b\ -\x7f\x32\x73\x72\x11\x1d\xf2\x28\x89\xda\xfc\x6f\x56\x9e\x23\x34\ -\x95\x60\x63\x8f\x0b\x17\xc7\x85\x83\xc3\xb8\xd7\x1d\x1a\x1a\x17\ -\x97\x97\x97\x27\x8d\xf3\xc2\x29\x22\x9b\x64\x99\xec\x62\x3b\xc4\ -\xcc\x30\xe1\x8f\x80\xc5\x84\x0d\xd3\x60\x40\x99\x15\x51\x68\xf6\ -\x10\x08\x1c\x62\xf4\x30\x22\x54\x32\xbb\x4f\x63\x6c\x0d\x3e\x81\ -\xc7\xa4\x2f\xc2\x91\x19\x79\x44\x4c\xa0\xf1\x48\xc3\x84\x8d\xc3\ -\x0d\xab\x17\x12\xb2\xb8\xa7\x03\x22\xba\x84\x51\xcf\x7c\x62\x6f\ -\xfa\x2a\x51\x76\xd9\x81\x04\xc4\x14\xc7\x86\x57\x6c\x46\x0c\x02\ -\x01\x71\x80\x15\xc5\xd0\x34\xa6\xe6\x13\xaa\x20\x60\x00\xb9\x29\ -\xaa\x26\x7d\xfd\x68\xf5\x28\xc0\x08\x5d\xbd\xfd\x9f\x6f\x65\xfb\ -\x07\x45\x39\x85\xa7\x16\xf0\x3c\xc3\x80\x1d\x3b\xa8\x42\x74\xbf\ -\xbc\x8b\x5a\xd1\x41\x5d\x4f\x44\xae\x3b\x70\x50\xb7\xc0\xf6\xda\ -\xc4\xd2\x72\xc2\x49\xa1\x48\x9e\xeb\x9b\xe9\xa6\x20\xd6\x5e\xd2\ -\x4d\x9d\x1e\xcf\xf6\x53\xc7\xdb\x73\x50\x77\x01\xab\x3a\x44\x74\ -\x4b\xc7\x16\x88\xa4\xa7\x9c\x13\x56\xf7\x0f\xcb\x05\xf2\x4e\x3c\ -\x0b\x94\xbd\x1d\x57\xd9\xf1\xe5\xe2\x76\x9c\x1d\x91\x03\xe6\x3d\ -\x54\x1e\x91\xb1\x63\xfe\x26\x3d\x13\x5c\x1c\xb7\x24\x7b\x4e\x4e\ -\x62\x43\x10\x4f\xb1\xe8\x13\x54\x3d\x32\x1f\x64\x20\xe2\x7f\x6a\ -\xd2\x61\xee\xc4\xcc\xfc\xd5\xf1\x34\x37\x0d\x61\x39\xe2\x31\xc0\ -\xe7\xb0\x1f\xa8\x8a\x0c\xd6\x92\x50\x5a\x1c\xbe\xc8\x7b\x8f\xdb\ -\x6a\xdc\x9e\x6c\x04\xb7\x73\x72\x56\x0b\xe2\x76\x8c\xda\x3e\x85\ -\xd7\x09\xe6\xf4\x58\x7a\x3a\xb2\x69\x94\x1c\x76\x21\xae\x13\x1b\ -\xc4\xaf\xd5\xec\xd6\x20\x6b\xd9\xed\x41\x5b\x0d\xda\xb3\x8d\x80\ -\x76\xce\x71\x6f\x16\x68\x0d\x71\x87\xdb\xae\x49\x15\x0e\x68\xac\ -\x4d\xc4\x1f\x8b\xf8\x27\xa4\xe0\x93\x4e\x28\xbc\x07\x45\x5e\x75\ -\x58\x8f\xc7\x26\x47\x38\xe0\x70\x86\xa0\xe4\xc7\x1f\xf0\x50\xb2\ -\x3d\x2c\xff\x68\x25\xd9\x16\x96\x95\xa6\x32\xe5\xb8\xc7\x73\x15\ -\x9e\x5f\x6f\x04\xcf\xe7\x4f\xeb\x84\x53\xc7\xdb\x95\x22\x32\xc8\ -\x56\x40\x07\xfd\x22\x93\x99\x37\xfe\x53\x40\x70\xea\xdb\x38\xd5\ -\x2c\x02\x79\x6f\x56\x1e\x22\x8f\x44\x1a\xcc\xe3\x9b\x3e\x87\xb3\ -\x21\x1d\x11\x93\x3f\x95\x87\xa4\x03\xea\x8a\xe8\x83\xeb\xc6\xd3\ -\xb5\x52\x70\xb0\x56\x3c\x1c\x11\xe6\x73\x93\x3c\xdf\x84\x3d\x98\ -\xcb\xb8\x74\x0a\x46\xe6\x2d\x5a\x46\x0f\x99\x7f\x36\xbc\xf7\x76\ -\x51\x6d\x17\xe7\x1b\xb1\x8b\x37\xab\xdb\x05\xde\x10\xa5\xf6\xd0\ -\x95\x8c\x79\xd4\xb7\xd0\x87\x15\x47\x1f\x8e\xf0\xc7\x44\x3c\x8f\ -\x3d\xee\x33\xf8\x9a\x1a\x8d\x01\xd7\x80\x4b\xcc\x2a\xbd\x67\x03\ -\x2a\xd9\xa1\xb5\x30\x8f\xe2\xe5\xd0\x03\xde\x27\x0d\x02\x38\x5f\ -\x1d\x1d\xad\x91\xf5\x99\x8e\xf4\x7f\x83\x48\x24\xad\x0a\xd8\x0a\ -\xbc\x51\x15\x19\xc3\x3d\xbe\xab\xf0\x7d\xb1\x09\x7c\xaf\x85\xee\ -\x09\xaf\x4f\x01\xdc\x29\x88\x73\xb7\x9b\x5d\x08\xc5\x33\xaf\x6f\ -\x93\xac\x36\x8d\x79\xea\x9b\x34\xa8\x19\xb0\x09\x24\xdb\x82\x11\ -\x72\x7a\x33\x16\x0b\x98\xa6\x1c\x49\xc4\xd4\x94\x1b\x8b\x8d\xe4\ -\x45\x80\xdb\x1e\xdb\xd5\xd8\x6e\x34\x36\xe2\xbc\x5f\x3f\x2d\xbc\ -\xb3\x88\xdb\x66\x44\x10\xd0\x28\x98\x89\x6f\x34\x8d\x7d\x2a\x7d\ -\x17\xc8\xe0\x08\x82\x59\x40\x78\x2b\x86\xb8\x05\x5c\xbf\x4b\xfb\ -\x63\xa3\xbd\x4e\x08\xe8\x23\xc3\x3b\x04\x6c\xc5\x6a\x03\x5f\x78\ -\xc9\x52\xf7\x3f\x4b\x18\x02\x5e\xfd\x8e\x45\xec\x82\xea\xad\x1c\ -\x26\x7b\x88\x93\xd9\x96\x11\xb4\xb5\x8f\xf9\xd7\xbd\x1d\x4c\xb1\ -\x83\xcd\x64\x58\x1a\xc7\x4f\x6b\x08\x01\x35\x77\xbd\x63\x97\xee\ -\x0a\x54\xd2\x58\x5e\x81\xa1\x84\xcc\x46\x30\x1b\x3c\x99\x1a\x29\ -\x48\x47\x24\x88\x6a\xce\x8c\x6f\x5f\x93\xe7\x12\x60\xb6\xce\xe0\ -\x66\xd8\xfd\x48\xdd\xc5\xf7\x4b\x84\x74\xb1\xb3\x40\x2b\x37\x6e\ -\xa5\x92\xc6\xfb\x25\x8b\x1a\xdb\xdf\x3e\x3c\x5d\x51\xa3\xe3\x94\ -\xcb\x3d\x7e\xef\xe5\x8d\xe9\x8c\x0a\xe9\xae\x97\x5b\xe8\x38\x27\ -\x5f\xb1\xf3\x42\x47\x93\x7f\x96\x13\x7e\xbe\x6d\x9a\x0b\xb1\xfc\ -\xa4\xf4\x30\x1a\xc2\x00\x53\x0b\x58\x9a\x04\x03\x95\xb6\x7e\xd3\ -\x6f\xdf\x7e\x1c\x53\x6c\xd6\x4d\xe3\xd2\x4e\x07\xf7\xff\x8f\xe0\ -\xae\xa7\x3b\x9d\xa9\xb7\xa2\x67\xb3\x2f\x45\x4f\xd6\xba\x15\x85\ -\x61\x46\x47\x4b\xe8\x7a\xd5\xa2\xd2\x75\x6e\x1e\x16\x2e\x2b\x45\ -\xb7\x35\xbd\x8e\xf4\xfb\x2f\xdd\x54\x8f\xbd\x7d\xe9\xe6\xbe\x74\ -\xf3\xa9\xa5\xda\x75\x24\xfe\x66\xf1\x40\xbc\xaa\x1a\x70\xce\x5d\ -\xfc\xbc\x84\x45\xfb\x99\xd4\xe1\x83\x71\xdf\xdb\x7c\xcd\xbd\x31\ -\xf2\xfb\xf5\xeb\xf1\xcd\xd4\xf0\x30\x6c\xe2\x39\x2c\x61\xc1\x64\ -\xa7\x04\x01\xc9\xa0\x58\x83\x47\x5d\x51\xe9\xcb\x70\x92\x05\x3d\ -\xbe\x4c\x67\x79\xe7\xea\x90\x60\x0f\x7c\x85\x9b\x60\x5f\x62\x82\ -\xfb\x1f\x34\xea\xff\x2b\xbd\xc5\xd9\xa1\x0b\xfd\x2f\x1d\x58\xb1\ -\xae\xdf\x7d\x59\x4b\x8c\x5d\xbb\xa6\xc2\x69\xfe\xe9\x92\x04\xb3\ -\x63\xd2\x65\x8a\x67\xd1\xb2\x1f\x39\x1b\xa8\x43\xbc\xa8\x63\x26\ -\x2d\x3c\x08\xd0\xc2\xcd\xd6\x20\xe4\x03\xc1\xa2\x7a\x8a\xb1\x10\ -\xe9\x84\xd4\x7b\x38\x34\x41\x53\x87\x69\x0d\x31\xb3\x64\xd4\xa7\ -\x1d\x1e\x72\x60\x4e\x7b\x14\xf3\x67\xee\xf5\x0e\x0c\xc5\x9b\xb0\ -\xd8\xdf\x48\x5e\x61\x8c\xdf\x9c\xb4\x6e\x5f\x33\xb7\x7d\xc0\x7d\ -\x0d\x57\x64\x93\x27\x25\xce\x1d\x50\x6b\x4b\xcb\x04\x3c\x82\xf9\ -\xba\x49\x27\xd4\x7e\xec\x7d\xc6\x1a\xdb\xf7\x76\x22\xcf\xd3\x03\ -\x3d\xdf\x74\xc5\xf8\xb0\xb0\x58\xba\xe2\xd7\xeb\x77\x4f\x9f\xae\ -\xc8\x6c\xf4\xa5\xa4\x2b\x0a\xa5\x90\xdf\x7d\xba\x62\x09\x77\x7b\ -\xb6\xba\xbb\x9d\x51\x40\x44\xc1\x79\x2a\xf2\xea\xf4\xc6\x5e\xba\ -\x55\xd5\x0a\x6d\xe4\xca\xd8\xa5\x55\x10\xf4\x46\x84\xad\xa4\x60\ -\x85\x47\x1d\xb3\xbd\x2f\x33\x6b\x91\xcf\x39\x61\x42\x9e\x7b\x69\ -\xc6\x69\x9a\xef\xaa\x4a\x35\x65\x59\xa6\x6f\x8e\x46\x21\xc7\x34\ -\xe9\xb7\x96\xc8\x2c\x15\x93\x4a\x2e\x9f\x74\x32\x91\x4f\x4a\x53\ -\x49\x67\x13\xa9\xa4\x42\x16\xa9\x2c\x4a\x21\x77\x94\x29\x29\xa7\ -\xc9\x9c\x1a\x9d\x73\x4a\x4f\xd5\xce\xd9\x5c\xd5\x2e\x6a\xc4\xba\ -\x89\xab\x5a\xa3\x51\xab\xe3\xc8\x3e\x1f\x46\xb4\xdf\x4d\x62\x0f\ -\x15\xd5\xfa\xeb\xab\x79\xbe\x95\x22\xfa\xc2\x23\xd6\x16\x89\xf4\ -\x60\x03\x2f\x8d\xc2\x9f\x75\x48\x94\x16\x91\xe5\xa8\x8c\x24\xf9\ -\x16\x2b\x65\xee\xa7\x1f\x72\xff\xe4\x90\xfd\xda\x03\xae\xc7\x50\ -\x33\x08\x79\x5a\xee\x97\x1e\x60\x35\x5c\xc3\x81\x55\x15\xf5\x61\ -\xca\x40\xa1\x8e\x04\xec\x4f\x3f\x1c\x05\xa8\x38\xd3\x61\x14\x50\ -\xe6\x3b\x5b\x90\xd2\x7f\x5c\x54\x0a\x33\x29\xf1\x34\xa9\x90\x9a\ -\x95\x5c\xad\x2f\x96\xfb\x4f\xb5\x6a\xfd\x8c\x3b\xb7\x22\x4a\xea\ -\xe3\xab\x65\xc9\x7a\xb7\x23\x8c\x3b\xb9\x4f\x11\x66\xdc\xbb\xbe\ -\x30\xc5\x06\xf3\x83\x24\x92\x29\x63\x03\xca\x58\x8b\x27\xe2\x98\ -\x19\x1b\xc0\xe7\x66\x3d\xe1\xad\x83\xff\x03\xad\x19\x30\x45\ +\x00\x48\x24\x78\x9c\xed\x5c\x5b\x73\xdb\xb6\x12\x7e\xf7\xaf\xc0\ +\xe8\xe1\x9c\xb4\xe3\x5a\x92\xaf\x49\x8e\xac\x4e\x62\xd7\x49\x3a\ +\xc9\x69\x5a\xb9\x49\xdf\x3c\x10\x09\x89\xa8\x49\x42\x05\x40\x4b\ +\xea\xaf\xef\x2e\x00\x8a\x14\x45\xdd\x2d\xc9\x71\x35\xe3\x19\x8b\ +\x00\x88\x5d\x2c\xbe\x5d\xec\x2e\x56\x6a\xfc\x38\x88\x42\xf2\xc0\ +\xa4\xe2\x22\xbe\xac\xd4\x8f\x6a\x15\xc2\x62\x4f\xf8\x3c\xee\x5e\ +\x56\x7e\xbf\xbd\xf9\xe1\x65\xe5\xc7\xe6\x41\x23\xe1\xd9\xa0\x53\ +\x18\xd4\x3c\x20\x0d\x2f\xa4\x4a\x35\xdf\x25\xfc\xf5\xeb\x6b\x4e\ +\x43\xd1\x85\xff\x61\xb7\xc5\xb4\x86\x97\xd5\xb5\xa4\x1d\xdd\xa8\ +\xda\x41\x30\xba\xcf\xfd\x2e\xd3\xc4\x3c\x5f\x56\x7e\xfd\x6a\x1e\ +\x2b\x24\xa6\x11\xbb\xac\xcc\x9c\x04\x89\x91\x46\x4f\x8a\x1e\x93\ +\x7a\xe8\xde\xe8\x32\x11\x31\x2d\x87\xa6\x93\x34\x24\xf3\xb4\xf9\ +\x44\x1a\x83\x66\xad\x51\x1d\xb8\x87\x21\x3e\x0c\xdd\x03\xb0\xa0\ +\x83\xe6\xd9\xc5\x59\xa3\x6a\x3f\xda\xe6\x80\xf1\x6e\xa0\x9b\xe7\ +\xc7\xaf\x1a\x55\xf7\xd9\xcc\x59\x4d\x27\x6d\x54\x53\xe2\x65\x9c\ +\xf4\x79\xec\x8b\xfe\x2d\xd7\x21\x73\xcc\x28\x2d\x81\xf9\xe6\x87\ +\xa8\x27\xa4\xae\xfe\x34\xc0\x7f\x8d\xaa\x6b\x9d\x9c\x2f\xa4\x43\ +\x91\x64\x92\xf9\xf2\x56\x0c\x3e\x9a\x26\x37\x5d\x81\x9e\xea\x51\ +\x0f\x26\xaa\x38\xee\xe3\x24\x6a\x33\xd9\x3c\x6f\x54\xdd\x27\xcb\ +\x7b\x9e\xc2\xc4\x14\x11\x95\x5d\x1e\x17\x66\x78\x35\x73\x06\xae\ +\x59\x94\x89\x31\xbf\x93\xef\xa4\x48\x7a\xc0\xf3\x68\x2f\xdd\x73\ +\xfd\xd8\x11\x98\x20\xaf\x33\x59\xe5\xc4\x75\xfd\xc7\x0d\xe9\x08\ +\x19\x51\x4d\x44\x4f\x03\xd2\x54\x5e\x66\x93\x2c\xcd\x97\xdc\x5c\ +\xe1\x4d\x95\x5f\x19\xb5\xd9\x52\x9c\x2a\xc8\xf2\xa9\x32\x71\x96\ +\xac\xe3\xfd\xe4\x3a\x16\x58\xc9\x8c\xb5\x94\xb1\x30\x7f\x3d\xd9\ +\x84\xb5\x05\x27\x1c\x5b\xd5\x24\x52\x3e\xd2\x36\x0b\x53\x98\x68\ +\x36\xd0\xa6\xa1\x7e\x77\x92\xa7\x39\x89\x16\x18\x38\x36\xa0\xa0\ +\x60\x44\xe9\x61\xc8\x0a\x58\x99\xca\x23\x31\xba\x0f\x5c\xe5\x97\ +\x32\xce\xf7\x9c\x65\x18\x5b\xf5\x59\xb2\xce\x95\x88\xda\x22\x07\ +\xfc\x2e\x76\xf4\xa0\xc3\xc3\x8e\x36\x74\xcc\x5c\x96\x10\xe1\x2d\ +\xef\x95\xaf\xec\x36\xe0\x8a\xc0\x9f\x0e\x18\x01\x33\x17\x08\x9f\ +\x78\x81\x10\x8a\xf9\xa8\x22\x84\x9b\x85\xc3\x40\x02\x0f\x5a\xd2\ +\x58\x85\xd4\x3c\xa2\x0e\x89\xf6\x9f\x60\xb7\x88\x27\x42\x1c\x19\ +\x6b\x41\x6e\x24\x63\x57\x6f\xae\x8f\xc8\xc1\x87\x8e\x6b\x8f\x68\ +\xaf\x87\x2f\x00\x0d\x37\xf1\x21\x01\xc0\x91\x28\x51\xda\xb5\x10\ +\x5a\x18\xdb\xe1\x21\x83\xa6\x58\x53\x1e\xe3\x33\xcd\x48\x8b\x98\ +\x68\xda\x86\x6e\x1d\x80\xfa\xf6\x79\x18\xe2\x40\x38\x31\x1c\x1f\ +\xca\x32\x12\xf2\x98\x19\xcb\xab\x8e\x0e\x16\xde\xb0\x09\xc9\x79\ +\x89\x94\x2c\xd6\x1f\x62\x9f\x0d\x0a\xe2\x9b\x8e\xd7\x45\x27\xc7\ +\xfd\xfb\x29\xc6\x83\x05\x70\xe5\x2b\xa6\x2f\x2b\xb5\x02\x11\xcf\ +\x31\xee\x0f\x3a\x0e\x7a\xde\xaa\x4b\x41\x6a\x9f\xa9\x0e\xe6\x13\ +\xfb\x24\xfc\x6a\x7a\xa4\x2e\x4c\xad\x00\xe4\x45\x74\x6b\x04\xc1\ +\xff\x8b\x98\x91\x17\x1d\xaa\x34\x53\xfa\xbb\xb2\xdd\x9a\x46\xb5\ +\x5a\x24\xbb\x16\x1f\xbf\x03\x12\x7d\xd6\xa1\x49\x98\x62\x9a\xc6\ +\x7e\x86\xa4\xdd\x31\xf6\x8b\xe4\x60\x2e\x69\xf8\xb4\xb8\xba\x1a\ +\xa9\x2c\xd8\x8a\xbc\xca\xed\x90\x25\xc9\xa8\x66\xa4\x47\x25\x45\ +\x97\x8d\x7b\xce\x44\x15\xcf\xf7\xed\xb3\xd4\xba\x67\xda\x0b\xd8\ +\x5a\x8c\xcc\x3d\x4f\x1a\x55\x7b\xbc\x67\xde\x40\xbe\x7b\x61\x4f\ +\xc0\x2d\x2a\x10\x92\xff\x8d\x36\x38\x9c\xf4\x10\x96\x39\x7e\x43\ +\x7c\xb8\xbb\x58\xf1\xe4\xfd\x44\x07\xa4\xd5\x43\x6c\x91\x16\xeb\ +\x46\x60\x8d\x77\x70\xfe\xb6\xe0\x54\x2a\x3b\x7e\x15\xb4\xc3\xe9\ +\x7b\x77\x3c\x73\x71\x11\x1d\xf0\x28\x89\x5a\xfc\x6f\x56\x5c\x23\ +\x34\x15\x60\x63\xc3\x85\xf3\xda\x58\xe0\x30\xea\x75\x41\x43\xfd\ +\xfc\xe2\xe2\xe2\xb8\x7e\x36\x16\x45\x64\x8b\x2c\x4e\xbb\xd8\x09\ +\x31\xd3\x4d\xf8\x1a\xb0\x98\xb0\x41\xea\x0c\x28\xb3\x23\x0a\xd5\ +\x1e\x1c\x81\x43\xf4\x1e\x86\x84\x4a\x66\xcf\x69\xf4\xad\xc1\x26\ +\xf0\x98\xf4\x44\x38\x34\x23\x8f\x88\x71\x34\x1e\x68\x98\xb0\x91\ +\xbb\x61\xe5\x42\x42\x16\x77\x75\x40\x44\x87\x30\xea\x99\xff\xd8\ +\x9b\xbe\x4a\x94\xdd\x76\x98\x02\x7c\x8a\x9a\xa1\x15\x9b\x11\xfd\ +\x40\x80\x1f\x60\x59\x31\x73\x1a\x55\xf3\x09\x55\xe0\x30\x00\xdf\ +\x14\x45\x93\xbe\x7e\xb4\xba\x17\x60\x98\x2e\x3f\xfe\xcf\xb6\x72\ +\xfc\x83\xa0\x9c\xc0\x53\x0d\x78\x9a\x6e\xc0\x8e\x0d\xd4\x98\x77\ +\xbf\xbc\x89\x5a\xd1\x40\x5d\x4d\x78\xae\x3b\x30\x50\x37\x40\xf6\ +\xca\xf8\xd2\x72\xc2\x48\x21\x4b\x9e\xeb\x9b\x69\xa6\xc0\xd7\x5e\ +\xd2\x4c\x9d\xd4\x66\xdb\xa9\xda\xf6\x0c\xd4\x6d\xc0\xca\x82\x88\ +\x4e\x21\x6c\x01\x4f\x7a\x4a\x9c\xb0\xba\x7d\x58\xce\x91\x77\xec\ +\x59\xa0\xec\xf5\xb8\x4c\x8f\x2f\x16\xd7\xe3\x2c\x44\x0e\x98\x77\ +\x5f\x1a\x22\x63\xc7\xfc\x43\x7a\x26\xb8\x38\x1e\x49\x36\x4e\x4e\ +\x62\x33\x21\x46\xb1\x68\x13\x54\x35\x32\xff\x48\x5f\xc4\xff\xd5\ +\xa4\xcd\x5c\xc4\xcc\xfc\xd5\xf1\x34\x37\x0d\x61\x29\x62\x18\xe0\ +\x73\x38\x0f\x54\x49\x06\x6b\x49\x28\x2d\x0e\x5f\xa4\xbd\xc7\x6d\ +\x39\x6e\x8f\x37\x82\xdb\x39\x39\xab\x05\x71\x3b\x42\x6d\x8f\xc2\ +\xeb\x04\x73\x7a\x2c\x8d\x8e\x6c\x1a\x25\x87\x5d\xf0\xeb\xc4\x06\ +\xf1\x6b\x25\xbb\x35\xc8\x5a\x72\x7b\xd0\x96\x83\xf6\x74\x23\xa0\ +\x9d\x13\xee\xcd\x02\xad\x99\xdc\xe1\xb6\x63\x52\x85\x7d\x1a\x6b\ +\xe3\xf1\xc7\x22\xfe\x01\x67\xf0\x49\x3b\x14\xde\xbd\x22\x2f\xda\ +\xac\xcb\x63\x93\x23\xec\x73\x88\x21\x28\xf9\xfe\x3b\x0c\x4a\xb6\ +\x87\xe5\xef\x2d\x27\xdb\xc2\xb2\xd2\x54\xa6\x14\xf7\x78\x2e\xc3\ +\xf3\xcb\x8d\xe0\xf9\xec\x71\x8d\x70\x6a\x78\x3b\x52\x44\x06\xd9\ +\x0a\xe6\x41\xbb\xc8\x64\x66\x8d\xff\x14\xe0\x9c\xfa\xd6\x4f\x35\ +\x9b\x40\xde\x9a\x9d\x07\xcf\x23\x91\x06\xf3\xf8\xa6\xcf\x21\x36\ +\xa4\x43\x62\xf2\xa7\xf2\x90\xb4\x41\x5c\x11\xbd\x77\xdd\x18\x5d\ +\x2b\x05\x81\xb5\xe2\xe1\x90\x30\x9f\x9b\xe4\xf9\x26\xf4\xc1\x5c\ +\xc6\xa5\x4b\x30\x3c\x6f\x51\x33\xba\x48\xfc\xa3\xa1\xbd\xd7\x8b\ +\x72\xbd\x38\xdb\x88\x5e\xbc\x5a\x5d\x2f\xf0\x86\x28\xd5\x87\x8e\ +\x64\xcc\xa3\xbe\x85\x3e\xec\x38\xda\x70\x84\x3f\x26\xe2\x79\xec\ +\x71\x9f\xc1\xc7\x54\x69\x0c\xb8\xfa\x5c\x62\x56\xe9\x2d\xeb\x53\ +\xc9\x0e\xad\x86\x79\x14\x2f\x87\xee\xf1\x3e\xa9\x1f\x40\x7c\x75\ +\x74\xb4\x46\xd6\x67\x3a\xd2\x7f\x06\x96\x48\x5a\x15\xb0\x15\x78\ +\xa3\x28\x32\x82\x7b\x7c\x97\xe1\xfb\x7c\x13\xf8\x5e\x0b\xdd\x13\ +\x56\x9f\x02\xb8\x53\x10\xe7\x6e\x37\x3b\xe0\x8a\x67\x56\xdf\x26\ +\x59\x6d\x1a\xf3\xc4\x37\x69\x50\x33\x60\x13\x48\xb6\x05\x23\xe4\ +\xe4\x7a\xc4\x16\x10\x4d\x29\x92\x88\xa9\x29\x37\x16\x1b\xc9\x8b\ +\x00\xb5\x3d\xb6\xcb\xb1\x5d\xaf\x6f\xc4\x78\xbf\x7c\x5c\x78\x67\ +\x1e\xb7\xcd\x88\x20\xa0\x91\x31\xe3\xdf\x68\x1a\xfb\x54\xfa\xce\ +\x91\xc1\x11\x04\xb3\x80\xf0\x56\x0c\x7e\x0b\x98\x7e\x97\xf6\xc7\ +\x46\x7b\x9d\x10\xd0\x07\x86\x77\x08\xd8\x8a\xd5\x06\xbe\xf0\x92\ +\xa5\xee\x7f\x96\x50\x04\xbc\xfa\x1d\xb1\xd8\x01\xd1\x5b\x3e\x4c\ +\xf6\x10\x17\xb3\x2d\x25\x68\x69\x1f\xf3\xaf\x7b\x3d\x98\xa2\x07\ +\x9b\xc9\xb0\xd4\x6b\x8f\xab\x08\x01\x35\x77\xbd\x23\x93\xee\x0a\ +\x54\x52\x5f\x5e\x81\xa2\x84\xcc\x7a\x30\x1b\x8c\x4c\x0d\x17\xa4\ +\x2d\x12\x44\x35\x67\xc6\xb6\xaf\x49\x73\x09\x30\x5b\x63\x70\x3d\ +\xe8\xbc\xa7\xee\xe2\x7b\x0f\xe9\x52\x48\x2f\x71\x69\xb5\x0c\xa4\ +\xeb\x8f\x0b\xe9\x3e\x5e\xba\x8e\x6e\x73\xad\x6d\x06\x2f\x1b\x6f\ +\x4e\xb0\x66\x06\x03\x55\x77\x0b\x9c\x82\x5e\xb2\xd8\x67\xd2\xfa\ +\x31\x5e\x68\x0a\xca\x0c\xfa\x6c\xa2\x46\x9b\xeb\x1a\x89\x75\xaf\ +\x64\x6a\xd1\xc8\xba\x8a\xf0\x9b\x61\x21\xc7\xb6\x21\xbd\x26\xb9\ +\x25\x74\xc0\x8a\xe0\xb3\x23\xff\xd5\xd2\x7d\x8e\x6a\x30\xde\x39\ +\x36\x57\x6e\xdc\x4a\x95\xbd\x77\x4b\xd6\xf6\xb6\xbe\xbc\x7b\xbc\ +\xda\x5e\x47\x29\x97\x82\xff\xd6\xab\x7c\xd3\x15\x8d\x65\x7d\x9f\ +\x6f\xbd\xef\x9c\xb4\xdd\xce\xeb\x7d\xcd\x35\x8c\x9c\x38\x1b\x5a\ +\xa6\x79\x2c\xa4\x9d\xe4\x1e\x46\x83\x37\x6c\x4a\x62\x0b\x8b\x60\ +\x20\xd2\xe6\xaf\xfa\xf5\xeb\xf7\xa3\x19\x1b\x55\xd3\xb8\xb4\xd1\ +\x41\x37\xf8\x3d\x78\x2d\xd3\x8d\xce\xd4\xe2\x80\xd3\xd9\xb5\x01\ +\xc7\x6b\x15\x07\xc0\x30\x23\xa3\x25\x64\xbd\x6a\x6d\xf5\x3a\x17\ +\x70\x0b\x57\x57\xa3\xd9\x9a\x5e\x4e\xfd\xed\x57\x30\xab\x87\xee\ +\xbe\x82\x79\xe3\xc5\xa6\xff\xba\x0a\xe6\x5d\x7b\xef\xaf\x16\x77\ +\xde\xcb\x8a\x62\xe7\x94\xa4\xcc\xcb\xdb\xb5\x9e\xc8\xd7\x51\x40\ +\xb9\xef\x6c\xda\xf2\xce\x28\xf9\xdd\xfa\x5f\x4b\x31\x4b\xc3\x9c\ +\x90\xf1\xe7\xb0\x92\x0b\x73\xfe\x12\x18\xb4\xa1\x48\x56\x8a\x4a\ +\x5d\x6d\xf5\xf3\x30\x92\x63\x72\x7c\x9e\xc6\xf2\xd6\x95\xe3\xc1\ +\x19\xf8\x02\x0f\xc1\x9e\xc4\x7b\x9e\xff\xd0\xa8\xf7\xbf\xf4\x32\ +\x73\x87\x26\xf4\x37\xda\xb7\x6c\x5d\xbd\xf9\xb4\x16\x1b\xbb\x36\ +\x4d\x63\x49\xad\xc7\x4b\x2c\xcc\xf6\x49\x97\xa9\x21\x47\xcd\x7e\ +\xe0\xac\xaf\x0e\xf1\xbe\x9a\x99\xdb\x91\x7e\x80\x1a\x6e\x8e\x06\ +\x21\xef\x09\x7e\xb7\x84\xa2\x2f\x44\xda\x21\xf5\xee\x0f\x8d\xd3\ +\xd4\x66\x5a\x83\xcf\x2c\x19\xf5\x69\x9b\x87\x1c\x88\xd3\x2e\xc5\ +\x34\xb2\x7b\xbd\x0d\x43\xf1\x42\x38\xf6\x37\x92\x5e\x1b\xe1\x37\ +\xc7\xad\x3b\xd7\xcc\xa5\x37\x50\x5f\xc3\x14\xd9\x84\x4b\x81\x72\ +\x1b\xc4\xda\xd4\x32\x01\x8b\x60\x3e\x6e\xd2\x08\xb5\x1e\xba\x1f\ +\x31\x59\xf2\xd6\x2e\xe4\x69\x5a\xa0\xa7\x9b\xae\x18\x05\x0b\x8b\ +\xa5\x2b\x7e\xb9\x7a\xf3\xf8\xe9\x8a\x4c\x47\x9f\x4b\xba\x62\xac\ +\x22\xf8\x9b\x4f\x57\x2c\x61\x6e\x4f\x57\x37\xb7\x33\xea\xe8\x28\ +\x18\x4f\x45\x5e\x9c\x5c\xdb\xbb\xe7\xb2\x92\xb9\x8d\x54\x4e\xb8\ +\xb4\x0a\x82\xde\xb0\xb0\x95\x2c\xac\xf0\xa8\x23\xb6\xb7\x65\x66\ +\x2f\xf2\x39\x27\xbc\x97\xe2\x5e\x9a\x71\x9a\x66\xbb\xca\x52\x4d\ +\x59\x96\xe9\x8b\x9b\x63\x2c\xc7\x34\x69\xb7\x96\xc8\x2c\x8d\x27\ +\x95\x5c\x3e\xe9\x78\x22\x9f\x94\xa6\x92\x4e\x27\x52\x49\x63\x59\ +\xa4\x22\x2b\x63\xb9\xa3\x4c\x48\x39\x49\xe6\xc4\xe8\x8c\x53\x1a\ +\x55\x3b\x63\x73\x59\x39\xaf\x10\x6b\x26\x2e\x2b\xf5\x7a\xa5\x8a\ +\x23\x7b\x7c\x10\xd1\x5e\x27\x89\x3d\x14\x54\xf3\xaf\xcf\xe6\xf9\ +\x46\x8a\xe8\x13\x8f\x58\x4b\x24\xd2\x83\x03\xbc\x30\x0a\x7f\xdd\ +\x24\x51\x5a\x44\x96\xa2\x32\x9c\xe4\x5b\x2c\x97\xb9\x5f\x40\xc9\ +\x7d\xd7\x27\xfb\xd1\x13\xdc\x8f\x81\x66\xe0\xf2\x34\xdd\x0f\x9e\ +\xc0\x6e\xb8\x86\x03\x2b\x2a\xea\xc3\x92\x61\x86\x2a\x4e\x60\x7f\ +\x01\xe5\x28\x40\xc1\x99\x0e\x23\x80\x22\xdd\xd9\x8c\x14\xbe\x78\ +\x54\xca\xcc\x24\xc7\xd3\xb8\xc2\xd9\x2c\xe7\x6a\x7d\xb6\xdc\x17\ +\x36\xcb\xe5\x33\xea\xdc\x0a\x2b\xa9\x8d\x2f\xe7\x25\xeb\xdd\x0e\ +\x33\x2e\x72\x9f\xc2\xcc\xa8\x77\x7d\x66\xc6\x1b\xcc\xef\xf2\x48\ +\xa6\x8c\x0e\x28\xa3\x2d\x9e\x88\x63\x66\x74\x00\x9f\x1b\xd5\x84\ +\x37\x0f\xfe\x01\xbd\x89\x17\xfc\ \x00\x00\x0f\x9f\ \x00\ \x00\xa2\x2c\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ @@ -37791,61 +37797,61 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x6b\xbd\ -\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xbd\x6a\ -\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x1f\x87\ -\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xde\x6f\ -\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x08\x51\ -\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x89\x07\ -\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe1\xa5\ -\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb2\xd6\ -\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x59\x16\ -\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xfa\x7f\ -\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xd6\x8c\ -\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xe7\x69\ -\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x76\x71\ -\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xdc\x0b\ -\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa1\xcc\ -\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xcc\x20\ -\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc0\xb5\ -\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x97\xb4\ -\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x23\x70\ -\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xac\xbf\ -\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xb7\x21\ -\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x11\x57\ -\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x8f\xfb\ -\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x08\x5d\ -\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x69\x5e\ -\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x34\xe0\ -\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x80\x11\ -\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xc9\x78\ -\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xf7\x73\ -\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xe9\x09\ -\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x4c\x1f\ -\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\x9f\xbb\ -\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x06\x58\ -\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\x9d\x98\ -\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb4\xdb\ -\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x28\x30\ -\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xc9\x42\ -\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x5e\x5e\ -\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xbf\xc7\ -\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x44\x85\ -\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x06\xfe\x10\ -\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xdb\x30\ -\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x61\ -\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x5f\x8b\ -\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x07\xfc\xeb\ -\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x0f\xb1\ -\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd3\xed\ -\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x92\xe8\ -\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xef\x2a\ -\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xed\x19\ -\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x3c\xc5\ -\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x98\x58\ -\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x2f\x81\ +\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x6c\x16\ +\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xbd\xc3\ +\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x1f\xe0\ +\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xde\xc8\ +\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x08\xaa\ +\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x89\x60\ +\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe1\xfe\ +\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb3\x2f\ +\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x59\x6f\ +\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xfa\xd8\ +\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xd6\xe5\ +\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xe7\xc2\ +\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x76\xca\ +\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xdc\x64\ +\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa2\x25\ +\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xcc\x79\ +\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc1\x0e\ +\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x98\x0d\ +\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x23\xc9\ +\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xad\x18\ +\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xb7\x7a\ +\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x11\xb0\ +\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x90\x54\ +\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x08\xb6\ +\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x69\xb7\ +\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x35\x39\ +\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x80\x6a\ +\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xc9\xd1\ +\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xf7\xcc\ +\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xe9\x62\ +\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x4c\x78\ +\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x14\ +\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x06\xb1\ +\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\x9d\xf1\ +\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb5\x34\ +\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x28\x89\ +\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xc9\x9b\ +\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x5e\xb7\ +\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xc0\x20\ +\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x44\xde\ +\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x06\xfe\x69\ +\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xdb\x89\ +\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x2f\xba\ +\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x5f\xe4\ +\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x07\xfd\x44\ +\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x10\x0a\ +\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd4\x46\ +\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x93\x41\ +\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xef\x83\ +\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xed\x72\ +\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x3d\x1e\ +\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x98\xb1\ +\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x2f\xda\ \x00\x00\x02\xaa\x00\x01\x00\x00\x00\x01\x00\x06\x77\x44\ -\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x80\x58\ +\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x80\xb1\ " def qInitResources(): diff --git a/src/Mod/Draft/Resources/ui/userprefs-import.ui b/src/Mod/Draft/Resources/ui/userprefs-import.ui index 09d5ee1c21..a14084d3b3 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-import.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-import.ui @@ -320,6 +320,26 @@ If color mapping is choosed, you must choose a color mapping file containing a t + + + + + + If this is checked, when polylines have a width defined, they will be rendered as closed wires with the correct width + + + Render polylines with width + + + renderPolylineWidth + + + Mod/Draft + + + + + diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index f71e101666..ba8fa2909d 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -202,6 +202,7 @@ class fcformat: self.makeBlocks = params.GetBool("groupLayers") self.stdSize = params.GetBool("dxfStdSize") self.importDxfHatches = params.GetBool("importDxfHatches") + self.renderPolylineWidth = params.GetBool("renderPolylineWidth") bparams = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View") if self.paramstyle > 1: @@ -403,7 +404,21 @@ def drawPolyline(polyline,shapemode=False,num=None): warn(polyline,num) if edges: try: - if (fmt.paramstyle >= 4) and (not curves) and (not shapemode): + width = rawValue(polyline,43) + if width and fmt.renderPolylineWidth: + w = Part.Wire(edges) + w1 = w.makeOffset(width/2) + if polyline.closed: + w2 = w.makeOffset(-width/2) + w1 = Part.Face(w1) + w2 = Part.Face(w2) + if w1.BoundBox.DiagonalLength > w2.BoundBox.DiagonalLength: + return w1.cut(w2) + else: + return w2.cut(w1) + else: + return Part.Face(w1) + elif (fmt.paramstyle >= 4) and (not curves) and (not shapemode): ob = Draft.makeWire(verts) ob.Closed = polyline.closed return ob From 84d8605b83b1f839590cb4c6c6842f7ff570219f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 17:29:50 -0300 Subject: [PATCH 218/351] Fixed 0000701 : Draft Wire naming --- src/Mod/Draft/Draft.py | 2 +- src/Mod/Draft/DraftTools.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 2e7cf692dd..7b1c5dc8f3 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -528,7 +528,7 @@ def makeWire(pointslist,closed=False,placement=None,face=True,support=None): print closed if placement: typecheck([(placement,FreeCAD.Placement)], "makeWire") if len(pointslist) == 2: fname = "Line" - else: fname = "Wire" + else: fname = "DWire" obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) _Wire(obj) obj.Points = pointslist diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index bde2ad4a76..d137c5228c 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -416,7 +416,7 @@ class Line(Creator): todo.delay(self.doc.removeObject,old) self.obj = None if (len(self.node) > 1): - self.commit(translate("draft","Create Wire"), + self.commit(translate("draft","Create DWire"), partial(Draft.makeWire,self.node,closed, face=self.ui.fillmode,support=self.support)) if self.ui: @@ -456,7 +456,7 @@ class Line(Creator): if ((point-self.node[0]).Length < Draft.tolerance()): self.undolast() self.finish(True,cont=True) - msg(translate("draft", "Wire has been closed\n")) + msg(translate("draft", "DWire has been closed\n")) def undolast(self): "undoes last line segment" @@ -523,10 +523,10 @@ class Wire(Line): def GetResources(self): return {'Pixmap' : 'Draft_Wire', 'Accel' : "W, I", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Wire"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Creates a multiple-point wire. CTRL to snap, SHIFT to constrain")} + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "DWire"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Creates a multiple-point DraftWire (DWire). CTRL to snap, SHIFT to constrain")} def Activated(self): - Line.Activated(self,name=str(translate("draft","Wire"))) + Line.Activated(self,name=str(translate("draft","DWire"))) class BSpline(Line): From 4c0da720b024cb13e125db989eae5157cabfc977 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 11:48:43 +0200 Subject: [PATCH 219/351] 0000710: merge project annoyance --- src/Gui/CommandDoc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index 02e0434902..46c5f56819 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -281,7 +281,7 @@ void StdCmdMergeProjects::activated(int iMsg) { QString exe = QString::fromUtf8(App::GetApplication().getExecutableName()); QString project = QFileDialog::getOpenFileName(Gui::getMainWindow(), - QString::fromUtf8(QT_TR_NOOP("Merge project")), QString(), + QString::fromUtf8(QT_TR_NOOP("Merge project")), QDir::homePath(), QString::fromUtf8(QT_TR_NOOP("%1 document (*.fcstd)")).arg(exe)); if (!project.isEmpty()) { App::Document* doc = App::GetApplication().getActiveDocument(); From 27aef69cd95f5daacba2d964ab8d6bce2de309ac Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 12:07:04 +0200 Subject: [PATCH 220/351] 0000717: Version info causes crash --- src/App/ApplicationPy.cpp | 41 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/App/ApplicationPy.cpp b/src/App/ApplicationPy.cpp index d74b1b4a75..15781cc3d0 100644 --- a/src/App/ApplicationPy.cpp +++ b/src/App/ApplicationPy.cpp @@ -383,23 +383,36 @@ PyObject* Application::sGetVersion(PyObject * /*self*/, PyObject *args,PyObject if (!PyArg_ParseTuple(args, "")) // convert args: Python->C return NULL; // NULL triggers exception - PyObject* pList = PyList_New(5); - PyObject *pItem; - pItem = PyString_FromString(Application::Config()["BuildVersionMajor"].c_str()); - PyList_SetItem(pList, 0, pItem); - pItem = PyString_FromString(Application::Config()["BuildVersionMinor"].c_str()); - PyList_SetItem(pList, 1, pItem); - pItem = PyString_FromString(Application::Config()["BuildRevision"].c_str()); - PyList_SetItem(pList, 2, pItem); - pItem = PyString_FromString(Application::Config()["BuildRepositoryURL"].c_str()); - PyList_SetItem(pList, 4, pItem); - pItem = PyString_FromString(Application::Config()["BuildCurrentDate"].c_str()); - PyList_SetItem(pList, 6, pItem); + Py::List list; + const std::map& cfg = Application::Config(); + std::map::const_iterator it; - return pList; + it = cfg.find("BuildVersionMajor"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildVersionMinor"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRevision"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRepositoryURL"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRevisionDate"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRevisionBranch"); + if (it != cfg.end()) + list.append(Py::String(it->second)); + + it = cfg.find("BuildRevisionHash"); + if (it != cfg.end()) + list.append(Py::String(it->second)); + + return Py::new_reference_to(list); } - PyObject* Application::sAddImportType(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) { char *psKey,*psMod; From a077d4f1788d055cdf0c732e2190e13bc4f33cf1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 15:03:19 +0200 Subject: [PATCH 221/351] 0000716: src/Tools/PyTools.c: strange assignment and a memory leak --- src/Base/PyTools.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Base/PyTools.c b/src/Base/PyTools.c index 2346f80cc3..d204ae72d2 100644 --- a/src/Base/PyTools.c +++ b/src/Base/PyTools.c @@ -377,8 +377,10 @@ const char *PP_Init(const char *modname) { //#ifdef FC_OS_LINUX /* cannot convert `const char *' to `char *' in assignment */ if (modname!=NULL) return modname; { /* we assume here that the caller frees allocated memory */ - char* __main__=(char *)malloc(sizeof("__main__")); - return __main__="__main__"; + // #0000716: strange assignment and a memory leak + return "__main__"; + //char* __main__=(char *)malloc(sizeof("__main__")); + //return __main__="__main__"; } //#else // return modname == NULL ? "__main__" : modname; /* default to '__main__' */ From e499e3344419fb93d77a2f82460ccdf1bc6c3f78 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 15:03:48 +0200 Subject: [PATCH 222/351] Expose merge project function to python --- src/Gui/CommandDoc.cpp | 3 --- src/Gui/DocumentPy.xml | 5 +++++ src/Gui/DocumentPyImp.cpp | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index 46c5f56819..b9d0ea68b0 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -294,9 +294,6 @@ void StdCmdMergeProjects::activated(int iMsg) return; } - QString dir1 = proj.absoluteDir().filePath(proj.baseName()); - QString dir2 = info.absoluteDir().filePath(info.baseName()); - Base::FileInfo fi((const char*)project.toUtf8()); Base::ifstream str(fi, std::ios::in | std::ios::binary); MergeDocuments md(doc); diff --git a/src/Gui/DocumentPy.xml b/src/Gui/DocumentPy.xml index 75ac71a546..c76e101cf0 100644 --- a/src/Gui/DocumentPy.xml +++ b/src/Gui/DocumentPy.xml @@ -77,6 +77,11 @@ Send a message to all views of the document + + + + Merges this document with another project file + diff --git a/src/Gui/DocumentPyImp.cpp b/src/Gui/DocumentPyImp.cpp index 4d30e7cc5c..67b66f36a7 100644 --- a/src/Gui/DocumentPyImp.cpp +++ b/src/Gui/DocumentPyImp.cpp @@ -32,6 +32,7 @@ #include #include "Document.h" +#include "MergeDocuments.h" #include "ViewProviderExtern.h" // inclusion of the generated files (generated out of DocumentPy.xml) @@ -234,6 +235,22 @@ PyObject* DocumentPy::sendMsgToViews(PyObject *args) } PY_CATCH; } +PyObject* DocumentPy::mergeProject(PyObject *args) +{ + char* filename; + if (!PyArg_ParseTuple(args, "s", &filename)) // convert args: Python->C + return NULL; // NULL triggers exception + + PY_TRY { + Base::FileInfo fi(filename); + Base::ifstream str(fi, std::ios::in | std::ios::binary); + App::Document* doc = getDocumentPtr()->getDocument(); + MergeDocuments md(doc); + md.importObjects(str); + Py_Return; + } PY_CATCH; +} + Py::Object DocumentPy::getActiveObject(void) const { App::DocumentObject *object = getDocumentPtr()->getDocument()->getActiveObject(); From c1f8018a1242ec5ab0fbe94334aca8a155d12119 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 16:57:36 +0200 Subject: [PATCH 223/351] Add method Document::findObject() --- src/App/Document.cpp | 15 +++++++++ src/App/Document.h | 1 + src/App/DocumentPyImp.cpp | 66 ++++++++++++++++++--------------------- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 519f5d7e4e..f130bb35a5 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -63,6 +63,7 @@ recompute path. Also enables more complicated dependencies beyond trees. #include #include #include +#include #include "Document.h" @@ -1689,6 +1690,20 @@ std::vector Document::getObjectsOfType(const Base::Type& typeId return Objects; } +std::vector Document::findObjects(const Base::Type& typeId, const char* objname) const +{ + boost::regex rx(objname); + boost::cmatch what; + std::vector Objects; + for (std::vector::const_iterator it = d->objectArray.begin(); it != d->objectArray.end(); ++it) { + if ((*it)->getTypeId().isDerivedFrom(typeId)) { + if (boost::regex_match((*it)->getNameInDocument(), what, rx)) + Objects.push_back(*it); + } + } + return Objects; +} + int Document::countObjectsOfType(const Base::Type& typeId) const { int ct=0; diff --git a/src/App/Document.h b/src/App/Document.h index dcf56d670d..d1675001e6 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -161,6 +161,7 @@ public: /// Returns a list of all Objects std::vector getObjects() const; std::vector getObjectsOfType(const Base::Type& typeId) const; + std::vector findObjects(const Base::Type& typeId, const char* objname) const; /// Returns an array with the correct types already. template inline std::vector getObjectsOfType() const; int countObjectsOfType(const Base::Type& typeId) const; diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 3b7fdd289d..6bd02f51ca 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -290,42 +290,36 @@ PyObject* DocumentPy::findObjects(PyObject *args) char *sType="App::DocumentObject", *sName=0; if (!PyArg_ParseTuple(args, "|ss",&sType, &sName)) // convert args: Python->C return NULL; // NULL triggers exception - - Base::Type type = Base::Type::fromName(sType); - if (type == Base::Type::badType()) { - PyErr_Format(PyExc_Exception, "'%s' is not a valid type", sType); - return NULL; - } - - if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) { - PyErr_Format(PyExc_Exception, "Type '%s' does not inherit from 'App::DocumentObject'", sType); - return NULL; - } - - std::vector res; - std::vector objs = getDocumentPtr()->getObjectsOfType(type); - - if (sName) { - try { - boost::regex rx(sName); - boost::cmatch what; - for (std::vector::const_iterator It = objs.begin();It != objs.end();++It) { - if (boost::regex_match((*It)->getNameInDocument(), what, rx)) - res.push_back(*It); - } - } - catch (const boost::regex_error& e) { - PyErr_SetString(PyExc_RuntimeError, e.what()); - return 0; - } - } - else { - res = objs; - } - - Py_ssize_t index=0; - PyObject* list = PyList_New((Py_ssize_t)res.size()); - for (std::vector::const_iterator It = res.begin();It != res.end();++It, index++) + + Base::Type type = Base::Type::fromName(sType); + if (type == Base::Type::badType()) { + PyErr_Format(PyExc_Exception, "'%s' is not a valid type", sType); + return NULL; + } + + if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) { + PyErr_Format(PyExc_Exception, "Type '%s' does not inherit from 'App::DocumentObject'", sType); + return NULL; + } + + std::vector res; + + if (sName) { + try { + res = getDocumentPtr()->findObjects(type, sName); + } + catch (const boost::regex_error& e) { + PyErr_SetString(PyExc_RuntimeError, e.what()); + return 0; + } + } + else { + res = getDocumentPtr()->getObjectsOfType(type); + } + + Py_ssize_t index=0; + PyObject* list = PyList_New((Py_ssize_t)res.size()); + for (std::vector::const_iterator It = res.begin();It != res.end();++It, index++) PyList_SetItem(list, index, (*It)->getPyObject()); return list; } From 555c7ca51689bfda84f74255e6489dfc22c73f58 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 23 May 2012 18:03:25 -0300 Subject: [PATCH 224/351] Small GUI adjustments in Draft --- src/Mod/Draft/DraftGui.py | 15 ++++++++++++++- src/Mod/Draft/DraftTools.py | 5 ++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 752abb76bc..13517f4785 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -523,13 +523,24 @@ class DraftToolBar: self.xValue.setEnabled(True) self.yValue.setEnabled(True) self.isRelative.show() + self.undoButton.show() + self.continueCmd.show() + + def wireUi(self,title=None): + if title: + self.pointUi(title) + else: + self.pointUi(translate("draft", "DWire")) + self.xValue.setEnabled(True) + self.yValue.setEnabled(True) + self.isRelative.show() self.hasFill.show() self.finishButton.show() self.closeButton.show() self.wipeButton.show() self.undoButton.show() self.continueCmd.show() - + def circleUi(self): self.pointUi(translate("draft", "Circle")) self.continueCmd.show() @@ -935,6 +946,8 @@ class DraftToolBar: if self.finishButton.isVisible(): self.finish() spec = True + elif txt.endsWith("t"): + self.continueCmd.setChecked(not self.continueCmd.isChecked()) elif txt.endsWith("w"): self.wipeLine() elif txt.endsWith("s"): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index d137c5228c..885e781c64 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -400,7 +400,10 @@ class Line(Creator): Creator.Activated(self,name) if self.doc: self.obj = None - self.ui.lineUi(name) + if self.isWire: + self.ui.wireUi(name) + else: + self.ui.lineUi(name) self.linetrack = lineTracker() self.constraintrack = lineTracker(dotted=True) self.obj=self.doc.addObject("Part::Feature",self.featureName) From f19a0d20dacfebb8587155de1935e6dd3941cc5f Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 25 May 2012 12:12:30 +0200 Subject: [PATCH 225/351] Add parameter to keep trailing digits in object name of copy, other little fix --- src/App/Document.cpp | 13 ++++++++----- src/App/Document.h | 4 ++-- src/App/DocumentPyImp.cpp | 6 +++--- src/Mod/Part/Gui/Command.cpp | 2 -- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index f130bb35a5..61d1b7921e 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1484,15 +1484,18 @@ void Document::breakDependency(DocumentObject* pcObject, bool clear) } DocumentObject* Document::_copyObject(DocumentObject* obj, std::map& copy_map, bool recursive) + DocumentObject*>& copy_map, bool recursive, + bool keepdigitsatend) { if (!obj) return 0; // remove number from end to avoid lengthy names std::string objname = obj->getNameInDocument(); + if (!keepdigitsatend) { size_t lastpos = objname.length()-1; while (objname[lastpos] >= 48 && objname[lastpos] <= 57) lastpos--; objname = objname.substr(0, lastpos+1); + } DocumentObject* copy = addObject(obj->getTypeId().getName(),objname.c_str()); if (!copy) return 0; copy->addDynamicProperties(obj); @@ -1512,7 +1515,7 @@ DocumentObject* Document::_copyObject(DocumentObject* obj, std::map(it->second)->setValue(pt->second); } else if (recursive) { - DocumentObject* link_copy = _copyObject(link, copy_map, recursive); + DocumentObject* link_copy = _copyObject(link, copy_map, recursive, keepdigitsatend); copy_map[link] = link_copy; static_cast(it->second)->setValue(link_copy); } @@ -1531,7 +1534,7 @@ DocumentObject* Document::_copyObject(DocumentObject* obj, std::mapsecond); } else { - links_copy.push_back(_copyObject(*jt, copy_map, recursive)); + links_copy.push_back(_copyObject(*jt, copy_map, recursive, keepdigitsatend)); copy_map[*jt] = links_copy.back(); } } @@ -1561,10 +1564,10 @@ DocumentObject* Document::_copyObject(DocumentObject* obj, std::map copy_map; - DocumentObject* copy = _copyObject(obj, copy_map, recursive); + DocumentObject* copy = _copyObject(obj, copy_map, recursive, keepdigitsatend); return copy; } diff --git a/src/App/Document.h b/src/App/Document.h index d1675001e6..38b247a20e 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -140,7 +140,7 @@ public: * are copied as well. By default \a recursive is false. * Returns the copy of the object or 0 if the creation failed. */ - DocumentObject* copyObject(DocumentObject* obj, bool recursive=false); + DocumentObject* copyObject(DocumentObject* obj, bool recursive=false, bool keepdigitsatend=false); /** Move an object from another document to this document * If \a recursive is true then all objects this object depends on * are moved as well. By default \a recursive is false. @@ -261,7 +261,7 @@ protected: void _remObject(DocumentObject* pcObject); void _addObject(DocumentObject* pcObject, const char* pObjectName); DocumentObject* _copyObject(DocumentObject* obj, std::map&, bool recursive=false); + DocumentObject*>&, bool recursive=false, bool keepdigitsatend=false); /// checks if a valid transaction is open void _checkTransaction(void); void breakDependency(DocumentObject* pcObject, bool clear); diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 6bd02f51ca..64b04d8b99 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -163,12 +163,12 @@ PyObject* DocumentPy::removeObject(PyObject *args) PyObject* DocumentPy::copyObject(PyObject *args) { - PyObject *obj, *rec=0; - if (!PyArg_ParseTuple(args, "O!|O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec)) + PyObject *obj, *rec=0, *keep=0; + if (!PyArg_ParseTuple(args, "O!|O!O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec,&PyBool_Type,&keep)) return NULL; // NULL triggers exception DocumentObjectPy* docObj = static_cast(obj); - DocumentObject* copy = getDocumentPtr()->copyObject(docObj->getDocumentObjectPtr(), rec==Py_True); + DocumentObject* copy = getDocumentPtr()->copyObject(docObj->getDocumentObjectPtr(), rec==Py_True, keep==Py_True); if (copy) { return copy->getPyObject(); } diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 1b616525a7..33cd008ee7 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -511,7 +511,6 @@ void CmdPartExport::activated(int iMsg) if (!fn.isEmpty()) { App::Document* pDoc = getDocument(); if (!pDoc) return; // no document - openCommand("Import Part"); QString ext = QFileInfo(fn).suffix().toLower(); if (ext == QLatin1String("step") || ext == QLatin1String("stp") || @@ -522,7 +521,6 @@ void CmdPartExport::activated(int iMsg) else { Gui::Application::Instance->exportTo((const char*)fn.toUtf8(),pDoc->getName(),"Part"); } - commitCommand(); } } From 5833e85f00c8ae9fbd1a9816e3d32f5044fa8d71 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 14 May 2012 11:13:19 -0300 Subject: [PATCH 226/351] Fixed bug in Draft Clone --- src/Mod/Draft/Draft.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 6f8250a3da..0014a45130 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -2853,8 +2853,9 @@ class _Clone: if o.isDerivedFrom("Part::Feature"): sh = o.Shape.copy() m = FreeCAD.Matrix() - m.scale(obj.Scale) - sh = sh.transformGeometry(m) + if hasattr(obj,"Scale") and not sh.isNull(): + m.scale(obj.Scale) + sh = sh.transformGeometry(m) shapes.append(sh) if shapes: obj.Shape = Part.makeCompound(shapes) From 0778aef53bf9c0d82f24d18384bdd11ee328f783 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 14 May 2012 19:15:11 +0200 Subject: [PATCH 227/351] Replace makeTube algorithm --- src/Mod/Part/App/AppPartPy.cpp | 29 +++++++++++++++++-- src/Mod/Part/App/TopoShape.cpp | 51 ++++++++++++++++++++++------------ src/Mod/Part/App/TopoShape.h | 3 +- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 2662593c58..2132042df4 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -1043,14 +1043,36 @@ static PyObject * makeTube(PyObject *self, PyObject *args) PyObject *pshape; double radius; double tolerance=0.001; + char* scont = "C0"; + int maxdegree = 3; + int maxsegment = 30; // Path + radius - if (!PyArg_ParseTuple(args, "O!d", &(TopoShapePy::Type), &pshape, &radius)) + if (!PyArg_ParseTuple(args, "O!d|sii", &(TopoShapePy::Type), &pshape, &radius, &scont, &maxdegree, &maxsegment)) return 0; + std::string str_cont = scont; + int cont; + if (str_cont == "C0") + cont = (int)GeomAbs_C0; + else if (str_cont == "C1") + cont = (int)GeomAbs_C1; + else if (str_cont == "C2") + cont = (int)GeomAbs_C2; + else if (str_cont == "C3") + cont = (int)GeomAbs_C3; + else if (str_cont == "CN") + cont = (int)GeomAbs_CN; + else if (str_cont == "G1") + cont = (int)GeomAbs_G1; + else if (str_cont == "G2") + cont = (int)GeomAbs_G2; + else + cont = (int)GeomAbs_C0; + try { const TopoDS_Shape& path_shape = static_cast(pshape)->getTopoShapePtr()->_Shape; TopoShape myShape(path_shape); - TopoDS_Shape face = myShape.makeTube(radius, tolerance); + TopoDS_Shape face = myShape.makeTube(radius, tolerance, cont, maxdegree, maxsegment); return new TopoShapeFacePy(new TopoShape(face)); } catch (Standard_Failure) { @@ -1465,7 +1487,8 @@ struct PyMethodDef Part_methods[] = { "these must have the same number of edges."}, {"makeTube" ,makeTube,METH_VARARGS, - "makeTube(edge,float) -- Create a tube."}, + "makeTube(edge,radius,[continuity,max degree,max segments]) -- Create a tube.\n" + "continuity is a string which must be 'C0','C1','C2','C3','CN','G1' or 'G1',"}, {"makeSweepSurface" ,makeSweepSurface,METH_VARARGS, "makeSweepSurface(edge(path),edge(profile),[float]) -- Create a profile along a path."}, diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index f78bc50262..22ccd16ad3 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -32,7 +32,9 @@ # include # include # include +# include # include +# include # include # include # include @@ -1343,7 +1345,8 @@ TopoDS_Shape TopoShape::makePipeShell(const TopTools_ListOfShape& profiles, return mkPipeShell.Shape(); } -TopoDS_Shape TopoShape::makeTube(double radius, double tol) const +#if 0 +TopoDS_Shape TopoShape::makeTube() const { // http://opencascade.blogspot.com/2009/11/surface-modeling-part3.html if (this->_Shape.IsNull()) @@ -1378,43 +1381,54 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol) const ); return mkBuilder.Face(); } - -// for testing -static Handle(Law_Function) CreateBsFunction (const Standard_Real theFirst, const Standard_Real theLast) +#else +static Handle(Law_Function) CreateBsFunction (const Standard_Real theFirst, const Standard_Real theLast, const Standard_Real theRadius) { //Handle_Law_BSpline aBs; //Handle_Law_BSpFunc aFunc = new Law_BSpFunc (aBs, theFirst, theLast); Handle_Law_Linear aFunc = new Law_Linear(); - aFunc->Set(theFirst, 2.0, theLast, 3.0); + aFunc->Set(theFirst, theRadius, theLast, theRadius); return aFunc; } -// for testing -TopoDS_Shape TopoShape::makeTube() const +TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdegree, int maxsegm) const { // http://opencascade.blogspot.com/2009/11/surface-modeling-part3.html - Standard_Real theTol = 0.001; + Standard_Real theTol = tol; Standard_Boolean theIsPolynomial = Standard_True; Standard_Boolean myIsElem = Standard_True; - GeomAbs_Shape theContinuity = GeomAbs_G1; - Standard_Integer theMaxDegree = 3; - Standard_Integer theMaxSegment = 1000; + GeomAbs_Shape theContinuity = GeomAbs_Shape(cont); + Standard_Integer theMaxDegree = maxdegree; + Standard_Integer theMaxSegment = maxsegm; if (this->_Shape.IsNull()) Standard_Failure::Raise("Cannot sweep along empty spine"); - if (this->_Shape.ShapeType() != TopAbs_EDGE) - Standard_Failure::Raise("Spine shape is not an edge"); - const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); - BRepAdaptor_Curve path_adapt(path_edge); + Handle(Adaptor3d_HCurve) myPath; + if (this->_Shape.ShapeType() == TopAbs_EDGE) { + const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); + BRepAdaptor_Curve path_adapt(path_edge); + myPath = new BRepAdaptor_HCurve(path_adapt); + theContinuity = GeomAbs_C0; + } + //else if (this->_Shape.ShapeType() == TopAbs_WIRE) { + // const TopoDS_Wire& path_wire = TopoDS::Wire(this->_Shape); + // BRepAdaptor_CompCurve path_adapt(path_wire); + // myPath = new BRepAdaptor_HCompCurve(path_adapt); + //} + //else { + // Standard_Failure::Raise("Spine shape is neither an edge nor a wire"); + //} + else { + Standard_Failure::Raise("Spine shape is not an edge"); + } //circular profile - Handle(Geom_Circle) aCirc = new Geom_Circle (gp::XOY(), 1.0); + Handle(Geom_Circle) aCirc = new Geom_Circle (gp::XOY(), radius); aCirc->Rotate (gp::OZ(), Standard_PI/2.); //perpendicular section - Handle(BRepAdaptor_HCurve) myPath = new BRepAdaptor_HCurve(path_adapt); - Handle(Law_Function) myEvol = ::CreateBsFunction (myPath->FirstParameter(), myPath->LastParameter()); + Handle(Law_Function) myEvol = ::CreateBsFunction (myPath->FirstParameter(), myPath->LastParameter(), radius); Handle(GeomFill_SectionLaw) aSec = new GeomFill_EvolvedSection(aCirc, myEvol); Handle(GeomFill_LocationLaw) aLoc = new GeomFill_CurveAndTrihedron(new GeomFill_CorrectedFrenet); aLoc->SetCurve (myPath); @@ -1438,6 +1452,7 @@ TopoDS_Shape TopoShape::makeTube() const return TopoDS_Shape(); } +#endif TopoDS_Shape TopoShape::makeSweep(const TopoDS_Shape& profile, double tol, int fillMode) const { diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 0cf1087f93..1de76b1cad 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -158,8 +158,7 @@ public: TopoDS_Shape makeThickSolid(const TopTools_ListOfShape& remFace, Standard_Real offset, Standard_Real tolerance) const; TopoDS_Shape makeSweep(const TopoDS_Shape& profile, double, int) const; - TopoDS_Shape makeTube(double radius, double tol) const; - TopoDS_Shape makeTube() const; + TopoDS_Shape makeTube(double radius, double tol, int cont, int maxdeg, int maxsegm) const; TopoDS_Shape makeHelix(Standard_Real pitch, Standard_Real height, Standard_Real radius, Standard_Real angle=0, Standard_Boolean left=Standard_False) const; TopoDS_Shape makeLoft(const TopTools_ListOfShape& profiles, Standard_Boolean isSolid, From 3b81c25665a3f04ee4481e1a5d104f1d5bb2750e Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Tue, 15 May 2012 18:01:15 +0200 Subject: [PATCH 228/351] add isNull() method to Rotation --- src/Base/RotationPy.xml | 8 ++++++++ src/Base/RotationPyImp.cpp | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Base/RotationPy.xml b/src/Base/RotationPy.xml index 02dc34ee84..111cfb74c7 100644 --- a/src/Base/RotationPy.xml +++ b/src/Base/RotationPy.xml @@ -48,6 +48,14 @@ + + + + isNull() -> Bool + returns True if the rotation equals the unity matrix + + + The rotation elements (as quaternion) diff --git a/src/Base/RotationPyImp.cpp b/src/Base/RotationPyImp.cpp index 7abede54c7..159952c7e0 100644 --- a/src/Base/RotationPyImp.cpp +++ b/src/Base/RotationPyImp.cpp @@ -144,6 +144,17 @@ PyObject* RotationPy::toEuler(PyObject * args) return Py::new_reference_to(tuple); } +PyObject* RotationPy::isNull(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + Base::Rotation rot = * getRotationPtr(); + Base::Rotation nullrot(0,0,0,1); + Base::Rotation nullrotinv(0,0,0,-1); + bool null = (rot == nullrot) | (rot == nullrotinv); + return Py_BuildValue("O", (null ? Py_True : Py_False)); +} + Py::Tuple RotationPy::getQ(void) const { double q0, q1, q2, q3; From b6003874f2a36314996cdd1890b944baf9c2779d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 16 May 2012 16:31:02 -0300 Subject: [PATCH 229/351] Added 0000145 : Drawing clip objects --- src/Mod/Drawing/App/AppDrawing.cpp | 2 + src/Mod/Drawing/App/CMakeLists.txt | 2 + src/Mod/Drawing/App/FeatureClip.cpp | 111 +++ src/Mod/Drawing/App/FeatureClip.h | 71 ++ src/Mod/Drawing/App/FeaturePage.cpp | 7 +- src/Mod/Drawing/App/Makefile.am | 2 + src/Mod/Drawing/Gui/Command.cpp | 47 +- src/Mod/Drawing/Gui/Resources/Drawing.qrc | 1 + src/Mod/Drawing/Gui/Resources/Makefile.am | 1 + .../Resources/icons/actions/drawing-clip.svg | 710 ++++++++++++++++++ src/Mod/Drawing/Gui/Workbench.cpp | 4 + 11 files changed, 955 insertions(+), 3 deletions(-) create mode 100644 src/Mod/Drawing/App/FeatureClip.cpp create mode 100644 src/Mod/Drawing/App/FeatureClip.h create mode 100644 src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg diff --git a/src/Mod/Drawing/App/AppDrawing.cpp b/src/Mod/Drawing/App/AppDrawing.cpp index a581668bad..016abf81b6 100644 --- a/src/Mod/Drawing/App/AppDrawing.cpp +++ b/src/Mod/Drawing/App/AppDrawing.cpp @@ -22,6 +22,7 @@ #include "FeatureViewPart.h" #include "FeatureViewAnnotation.h" #include "FeatureProjection.h" +#include "FeatureClip.h" #include "PageGroup.h" extern struct PyMethodDef Drawing_methods[]; @@ -59,6 +60,7 @@ void DrawingExport initDrawing() Drawing::FeatureViewPartPython ::init(); Drawing::FeatureViewPython ::init(); Drawing::FeatureViewAnnotation ::init(); + Drawing::FeatureClip ::init(); } } // extern "C" diff --git a/src/Mod/Drawing/App/CMakeLists.txt b/src/Mod/Drawing/App/CMakeLists.txt index 98767a24a7..00710b75e0 100644 --- a/src/Mod/Drawing/App/CMakeLists.txt +++ b/src/Mod/Drawing/App/CMakeLists.txt @@ -29,6 +29,8 @@ SET(Features_SRCS FeatureViewPart.h FeatureViewAnnotation.cpp FeatureViewAnnotation.h + FeatureClip.cpp + FeatureClip.h PageGroup.cpp PageGroup.h ) diff --git a/src/Mod/Drawing/App/FeatureClip.cpp b/src/Mod/Drawing/App/FeatureClip.cpp new file mode 100644 index 0000000000..c45229929a --- /dev/null +++ b/src/Mod/Drawing/App/FeatureClip.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre 2012 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + + +#include +#include +#include +#include +#include +#include + +#include "FeatureClip.h" +#include "FeatureView.h" + +using namespace Drawing; +using namespace std; + + +//=========================================================================== +// FeaturePage +//=========================================================================== + +PROPERTY_SOURCE(Drawing::FeatureClip, App::DocumentObjectGroup) + +FeatureClip::FeatureClip(void) +{ + static const char *group = "Drawing view"; + App::PropertyType hidden = (App::PropertyType)(App::Prop_Hidden); + ADD_PROPERTY_TYPE(ViewResult ,(""),group,hidden,"Resulting SVG view of this clip"); + ADD_PROPERTY_TYPE(X ,(10),group,App::Prop_None ,"The left margin of the view area of this clip"); + ADD_PROPERTY_TYPE(Y ,(10),group,App::Prop_None ,"The top margin of the view area of this clip"); + ADD_PROPERTY_TYPE(Height ,(10),group,App::Prop_None ,"The height of the view area of this clip"); + ADD_PROPERTY_TYPE(Width ,(10),group,App::Prop_None ,"The width of the view area of this clip"); + ADD_PROPERTY_TYPE(ShowFrame ,(0),group,App::Prop_None,"Specifies if the clip frame appears on the page or not"); +} + +FeatureClip::~FeatureClip() +{ +} + +/// get called by the container when a Property was changed +void FeatureClip::onChanged(const App::Property* prop) +{ + App::DocumentObjectGroup::onChanged(prop); +} + +App::DocumentObjectExecReturn *FeatureClip::execute(void) +{ + ostringstream svg; + + // creating clip path + svg << "" + << "" << endl; + + // show clip frame on the page if needed + + if (ShowFrame.getValue()) { + svg << "" << endl; + } + + // create clipped group + svg << "" << endl; + + // get through the children and collect all the views + const std::vector &Grp = Group.getValues(); + for (std::vector::const_iterator It= Grp.begin();It!=Grp.end();++It) { + if ((*It)->getTypeId().isDerivedFrom(Drawing::FeatureView::getClassTypeId())) { + Drawing::FeatureView *View = dynamic_cast(*It); + svg << View->ViewResult.getValue() << endl; + } + } + + // closing clipped group + svg << "" << endl; + + ViewResult.setValue(svg.str().c_str()); + return App::DocumentObject::StdReturn; +} diff --git a/src/Mod/Drawing/App/FeatureClip.h b/src/Mod/Drawing/App/FeatureClip.h new file mode 100644 index 0000000000..ae1e6c0fc0 --- /dev/null +++ b/src/Mod/Drawing/App/FeatureClip.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre 2012 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef _FeatureClip_h_ +#define _FeatureClip_h_ + + +#include +#include + +namespace Drawing +{ + +/** Base class of all View Features in the drawing module + */ +class DrawingExport FeatureClip: public App::DocumentObjectGroup +{ + PROPERTY_HEADER(Drawing::FeatureClip); + +public: + /// Constructor + FeatureClip(void); + virtual ~FeatureClip(); + + App::PropertyFloat X; + App::PropertyFloat Y; + App::PropertyFloat Width; + App::PropertyFloat Height; + App::PropertyBool ShowFrame; + App::PropertyString ViewResult; + + /** @name methods overide Feature */ + //@{ + /// recalculate the Feature + virtual App::DocumentObjectExecReturn *execute(void); + //@} + + /// returns the type name of the ViewProvider + virtual const char* getViewProviderName(void) const { + return "DrawingGui::ViewProviderDrawingPage"; + } + +protected: + void onChanged(const App::Property* prop); +}; + + +} //namespace Drawing + + +#endif diff --git a/src/Mod/Drawing/App/FeaturePage.cpp b/src/Mod/Drawing/App/FeaturePage.cpp index 684fe28cf8..c1730ebc4a 100644 --- a/src/Mod/Drawing/App/FeaturePage.cpp +++ b/src/Mod/Drawing/App/FeaturePage.cpp @@ -37,6 +37,7 @@ #include "FeaturePage.h" #include "FeatureView.h" +#include "FeatureClip.h" using namespace Drawing; using namespace std; @@ -124,10 +125,14 @@ App::DocumentObjectExecReturn *FeaturePage::execute(void) // get through the children and collect all the views const std::vector &Grp = Group.getValues(); for (std::vector::const_iterator It= Grp.begin();It!=Grp.end();++It) { - if ((*It)->getTypeId().isDerivedFrom(Drawing::FeatureView::getClassTypeId())) { + if ( (*It)->getTypeId().isDerivedFrom(Drawing::FeatureView::getClassTypeId()) ) { Drawing::FeatureView *View = dynamic_cast(*It); ofile << View->ViewResult.getValue(); ofile << tempendl << tempendl << tempendl; + } else if ( (*It)->getTypeId().isDerivedFrom(Drawing::FeatureClip::getClassTypeId()) ) { + Drawing::FeatureClip *Clip = dynamic_cast(*It); + ofile << Clip->ViewResult.getValue(); + ofile << tempendl << tempendl << tempendl; } } } diff --git a/src/Mod/Drawing/App/Makefile.am b/src/Mod/Drawing/App/Makefile.am index 462017c0fd..098b9b786a 100644 --- a/src/Mod/Drawing/App/Makefile.am +++ b/src/Mod/Drawing/App/Makefile.am @@ -15,6 +15,8 @@ libDrawing_la_SOURCES=\ FeatureViewPart.h \ FeatureViewAnnotation.cpp \ FeatureViewAnnotation.h \ + FeatureClip.cpp \ + FeatureClip.h \ PageGroup.cpp \ PageGroup.h \ ProjectionAlgos.cpp \ diff --git a/src/Mod/Drawing/Gui/Command.cpp b/src/Mod/Drawing/Gui/Command.cpp index 2f9345b974..7ed5a4641a 100644 --- a/src/Mod/Drawing/Gui/Command.cpp +++ b/src/Mod/Drawing/Gui/Command.cpp @@ -366,9 +366,9 @@ CmdDrawingAnnotation::CmdDrawingAnnotation() // seting the sGroup = QT_TR_NOOP("Drawing"); sMenuText = QT_TR_NOOP("&Annotation"); - sToolTipText = QT_TR_NOOP("Inserts an Annotation view in the active document"); + sToolTipText = QT_TR_NOOP("Inserts an Annotation view in the active drawing"); sWhatsThis = "Drawing_Annotation"; - sStatusTip = QT_TR_NOOP("Inserts an Annotation view in the active document"); + sStatusTip = QT_TR_NOOP("Inserts an Annotation view in the active drawing"); sPixmap = "actions/drawing-annotation"; } @@ -398,6 +398,48 @@ bool CmdDrawingAnnotation::isActive(void) return (getActiveGuiDocument() ? true : false); } + +//=========================================================================== +// Drawing_Clip +//=========================================================================== + +DEF_STD_CMD_A(CmdDrawingClip); + +CmdDrawingClip::CmdDrawingClip() + : Command("Drawing_Clip") +{ + // seting the + sGroup = QT_TR_NOOP("Drawing"); + sMenuText = QT_TR_NOOP("&Clip"); + sToolTipText = QT_TR_NOOP("Inserts a clip group in the active drawing"); + sWhatsThis = "Drawing_Annotation"; + sStatusTip = QT_TR_NOOP("Inserts a clip group in the active drawing"); + sPixmap = "actions/drawing-clip"; +} + +void CmdDrawingClip::activated(int iMsg) +{ + + std::vector pages = this->getDocument()->getObjectsOfType(Drawing::FeaturePage::getClassTypeId()); + if (pages.empty()){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No page to insert"), + QObject::tr("Create a page to insert.")); + return; + } + std::string PageName = pages.front()->getNameInDocument(); + std::string FeatName = getUniqueObjectName("Clip"); + openCommand("Create Clip"); + doCommand(Doc,"App.activeDocument().addObject('Drawing::FeatureClip','%s')",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); + updateActive(); + commitCommand(); +} + +bool CmdDrawingClip::isActive(void) +{ + return (getActiveGuiDocument() ? true : false); +} + //=========================================================================== // Drawing_ExportPage //=========================================================================== @@ -495,6 +537,7 @@ void CreateDrawingCommands(void) rcCmdMgr.addCommand(new CmdDrawingOrthoViews()); rcCmdMgr.addCommand(new CmdDrawingOpenBrowserView()); rcCmdMgr.addCommand(new CmdDrawingAnnotation()); + rcCmdMgr.addCommand(new CmdDrawingClip()); rcCmdMgr.addCommand(new CmdDrawingExportPage()); rcCmdMgr.addCommand(new CmdDrawingProjectShape()); } diff --git a/src/Mod/Drawing/Gui/Resources/Drawing.qrc b/src/Mod/Drawing/Gui/Resources/Drawing.qrc index fad40eb814..bc0ae4cdfe 100644 --- a/src/Mod/Drawing/Gui/Resources/Drawing.qrc +++ b/src/Mod/Drawing/Gui/Resources/Drawing.qrc @@ -17,6 +17,7 @@ icons/actions/drawing-orthoviews.svg icons/actions/drawing-openbrowser.svg icons/actions/drawing-annotation.svg + icons/actions/drawing-clip.svg translations/Drawing_af.qm translations/Drawing_de.qm translations/Drawing_es.qm diff --git a/src/Mod/Drawing/Gui/Resources/Makefile.am b/src/Mod/Drawing/Gui/Resources/Makefile.am index e42a14b034..69b335394c 100644 --- a/src/Mod/Drawing/Gui/Resources/Makefile.am +++ b/src/Mod/Drawing/Gui/Resources/Makefile.am @@ -21,6 +21,7 @@ EXTRA_DIST = \ icons/actions/drawing-orthoviews.svg \ icons/actions/drawing-openbrowser.svg \ icons/actions/drawing-annotation.svg \ + icons/actions/drawing-clip.svg \ icons/Page.svg \ icons/Pages.svg \ icons/View.svg \ diff --git a/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg b/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg new file mode 100644 index 0000000000..dd58ec78ad --- /dev/null +++ b/src/Mod/Drawing/Gui/Resources/icons/actions/drawing-clip.svg @@ -0,0 +1,710 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/src/Mod/Drawing/Gui/Workbench.cpp b/src/Mod/Drawing/Gui/Workbench.cpp index b7bd8bbce4..e74f510e67 100644 --- a/src/Mod/Drawing/Gui/Workbench.cpp +++ b/src/Mod/Drawing/Gui/Workbench.cpp @@ -63,6 +63,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const *part << "Drawing_OrthoViews"; *part << "Drawing_OpenBrowserView"; *part << "Drawing_Annotation"; + *part << "Drawing_Clip"; *part << "Drawing_ExportPage"; return root; @@ -80,6 +81,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const *part << "Drawing_OrthoViews"; *part << "Drawing_OpenBrowserView"; *part << "Drawing_Annotation"; + *part << "Drawing_Clip"; *part << "Drawing_ExportPage"; return root; } @@ -97,6 +99,8 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const *img << "Drawing_NewPage"; *img << "Drawing_OrthoViews"; *img << "Drawing_OpenBrowserView"; + *img << "Drawing_Annotation"; + *img << "Drawing_Clip"; img = new Gui::ToolBarItem(root); img->setCommand("Views"); *img << "Drawing_NewView"; From abbb19987f7821991f4d97e63ea413afd74bf16b Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 00:12:30 +0200 Subject: [PATCH 230/351] fix in makeTube --- src/Mod/Part/App/TopoShape.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 22ccd16ad3..fd90af18f5 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -1409,7 +1409,6 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdeg const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape); BRepAdaptor_Curve path_adapt(path_edge); myPath = new BRepAdaptor_HCurve(path_adapt); - theContinuity = GeomAbs_C0; } //else if (this->_Shape.ShapeType() == TopAbs_WIRE) { // const TopoDS_Wire& path_wire = TopoDS::Wire(this->_Shape); From d81094cd78398bdf7cd548bd4644404ee6bd1768 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 01:25:31 +0200 Subject: [PATCH 231/351] Mesh segmentation --- src/Mod/Mesh/App/CMakeLists.txt | 14 +- src/Mod/Mesh/App/Core/Algorithm.cpp | 37 ++-- src/Mod/Mesh/App/Core/Algorithm.h | 45 ++++- src/Mod/Mesh/App/Core/Approximation.cpp | 99 ++++----- src/Mod/Mesh/App/Core/Approximation.h | 203 +++++++++++-------- src/Mod/Mesh/App/Core/Curvature.cpp | 236 ++++++++++++++++++++++ src/Mod/Mesh/App/Core/Curvature.h | 75 +++++++ src/Mod/Mesh/App/Core/Segmentation.cpp | 228 +++++++++++++++++++++ src/Mod/Mesh/App/Core/Segmentation.h | 161 +++++++++++++++ src/Mod/Mesh/App/FeatureMeshCurvature.cpp | 50 ++--- src/Mod/Mesh/App/Makefile.am | 11 +- src/Mod/Mesh/App/Mesh.cpp | 12 +- src/Mod/Mesh/App/Mesh.h | 2 +- src/Mod/Mesh/App/MeshPy.xml | 17 +- src/Mod/Mesh/App/MeshPyImp.cpp | 51 ++++- 15 files changed, 1033 insertions(+), 208 deletions(-) create mode 100644 src/Mod/Mesh/App/Core/Curvature.cpp create mode 100644 src/Mod/Mesh/App/Core/Curvature.h create mode 100644 src/Mod/Mesh/App/Core/Segmentation.cpp create mode 100644 src/Mod/Mesh/App/Core/Segmentation.h diff --git a/src/Mod/Mesh/App/CMakeLists.txt b/src/Mod/Mesh/App/CMakeLists.txt index ee813be7bc..97e2856804 100644 --- a/src/Mod/Mesh/App/CMakeLists.txt +++ b/src/Mod/Mesh/App/CMakeLists.txt @@ -1,20 +1,26 @@ if(WIN32) - add_definitions(-DFCAppMesh -DWM4_FOUNDATION_DLL_EXPORT) + add_definitions(-DFCAppMesh -DWM4_FOUNDATION_DLL_EXPORT -DEIGEN2_SUPPORT) +else (Win32) + add_definitions(-DEIGEN2_SUPPORT) endif(WIN32) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/src/3rdParty ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_PATH} ${XERCESC_INCLUDE_DIR} + ${QT_QTCORE_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} - ${EIGEN2_INCLUDE_DIR} + ${EIGEN3_INCLUDE_DIR} ) set(Mesh_LIBS ${Boost_LIBRARIES} + ${QT_QTCORE_LIBRARY} + ${QT_QTCORE_LIBRARY_DEBUG} FreeCADBase FreeCADApp ) @@ -41,6 +47,8 @@ SET(Core_SRCS Core/Approximation.h Core/Builder.cpp Core/Builder.h + Core/Curvature.cpp + Core/Curvature.h Core/Definitions.cpp Core/Definitions.h Core/Degeneration.cpp @@ -61,6 +69,8 @@ SET(Core_SRCS Core/MeshKernel.h Core/Projection.cpp Core/Projection.h + Core/Segmentation.cpp + Core/Segmentation.h Core/SetOperations.cpp Core/SetOperations.h Core/Smoothing.cpp diff --git a/src/Mod/Mesh/App/Core/Algorithm.cpp b/src/Mod/Mesh/App/Core/Algorithm.cpp index 40d4907d4a..281fba7f7a 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.cpp +++ b/src/Mod/Mesh/App/Core/Algorithm.cpp @@ -1156,7 +1156,6 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, const Base: { const MeshPointArray& p = _rclMesh.GetPoints(); const MeshFacetArray& f = _rclMesh.GetFacets(); - Base::SequencerLauncher seq("Check facets", f.size()); Base::Vector3f pt2d; unsigned long index=0; for (MeshFacetArray::_TConstIterator it = f.begin(); it != f.end(); ++it,++index) { @@ -1167,7 +1166,6 @@ void MeshAlgorithm::CheckFacets(const Base::ViewProjMethod* pclProj, const Base: break; } } - seq.next(); } } @@ -1743,47 +1741,38 @@ std::set MeshRefPointToFacets::NeighbourPoints(const std::vector< return nb; } -// ermittelt alle Nachbarn zum Facet deren Schwerpunkt unterhalb der mpx. Distanz befindet. -// Facet deren VISIT-Flag gesetzt ist werden nicht beruecksichtig. -/// @todo -void MeshRefPointToFacets::Neighbours (unsigned long ulFacetInd, float fMpxDist, std::vector &rclNb) +void MeshRefPointToFacets::Neighbours (unsigned long ulFacetInd, float fMaxDist, MeshCollector& collect) const { - rclNb.clear(); + std::set visited; Base::Vector3f clCenter = _rclMesh.GetFacet(ulFacetInd).GetGravityPoint(); const MeshFacetArray& rFacets = _rclMesh.GetFacets(); - SearchNeighbours(rFacets.begin() + ulFacetInd, clCenter, fMpxDist * fMpxDist, rclNb); - - for (std::vector::iterator i = rclNb.begin(); i != rclNb.end(); i++) - (*i)->ResetFlag(MeshFacet::VISIT); + SearchNeighbours(rFacets, ulFacetInd, clCenter, fMaxDist * fMaxDist, visited, collect); } -/// @todo -void MeshRefPointToFacets::SearchNeighbours(MeshFacetArray::_TConstIterator f_it, const Base::Vector3f &rclCenter, float fMpxDist, std::vector &rclNb) +void MeshRefPointToFacets::SearchNeighbours(const MeshFacetArray& rFacets, unsigned long index, const Base::Vector3f &rclCenter, + float fMaxDist2, std::set& visited, MeshCollector& collect) const { - if (f_it->IsFlag(MeshFacet::VISIT) == true) + if (visited.find(index) != visited.end()) return; - if (Base::DistanceP2(rclCenter, _rclMesh.GetFacet(*f_it).GetGravityPoint()) > fMpxDist) + const MeshFacet& face = rFacets[index]; + if (Base::DistanceP2(rclCenter, _rclMesh.GetFacet(face).GetGravityPoint()) > fMaxDist2) return; - rclNb.push_back(f_it); - f_it->SetFlag(MeshFacet::VISIT); - - MeshPointArray::_TConstIterator p_beg = _rclMesh.GetPoints().begin(); - MeshFacetArray::_TConstIterator f_beg = _rclMesh.GetFacets().begin(); - + visited.insert(index); + collect.Append(_rclMesh, index); for (int i = 0; i < 3; i++) { - const std::set &f = (*this)[f_it->_aulPoints[i]]; + const std::set &f = (*this)[face._aulPoints[i]]; for (std::set::const_iterator j = f.begin(); j != f.end(); ++j) { - SearchNeighbours(f_beg+*j, rclCenter, fMpxDist, rclNb); + SearchNeighbours(rFacets, *j, rclCenter, fMaxDist2, visited, collect); } } } MeshFacetArray::_TConstIterator -MeshRefPointToFacets::getFacet (unsigned long index) const +MeshRefPointToFacets::GetFacet (unsigned long index) const { return _rclMesh.GetFacets().begin() + index; } diff --git a/src/Mod/Mesh/App/Core/Algorithm.h b/src/Mod/Mesh/App/Core/Algorithm.h index 9baa667e21..78a4caf5b7 100644 --- a/src/Mod/Mesh/App/Core/Algorithm.h +++ b/src/Mod/Mesh/App/Core/Algorithm.h @@ -310,6 +310,43 @@ protected: const MeshKernel &_rclMesh; /**< The mesh kernel. */ }; +class MeshExport MeshCollector +{ +public: + MeshCollector(){} + virtual void Append(const MeshCore::MeshKernel&, unsigned long index) = 0; +}; + +class MeshExport PointCollector : public MeshCollector +{ +public: + PointCollector(std::vector& ind) : indices(ind){} + virtual void Append(const MeshCore::MeshKernel& kernel, unsigned long index) + { + unsigned long ulP1, ulP2, ulP3; + kernel.GetFacetPoints(index, ulP1, ulP2, ulP3); + indices.push_back(ulP1); + indices.push_back(ulP2); + indices.push_back(ulP3); + } + +private: + std::vector& indices; +}; + +class MeshExport FacetCollector : public MeshCollector +{ +public: + FacetCollector(std::vector& ind) : indices(ind){} + void Append(const MeshCore::MeshKernel&, unsigned long index) + { + indices.push_back(index); + } + +private: + std::vector& indices; +}; + /** * The MeshRefPointToFacets builds up a structure to have access to all facets indexing * a point. @@ -329,14 +366,14 @@ public: /// Rebuilds up data structure void Rebuild (void); const std::set& operator[] (unsigned long) const; - MeshFacetArray::_TConstIterator getFacet (unsigned long) const; + MeshFacetArray::_TConstIterator GetFacet (unsigned long) const; std::set NeighbourPoints(const std::vector& , int level) const; - void Neighbours (unsigned long ulFacetInd, float fMaxDist, std::vector &rclNb); + void Neighbours (unsigned long ulFacetInd, float fMaxDist, MeshCollector& collect) const; Base::Vector3f GetNormal(unsigned long) const; protected: - void SearchNeighbours(MeshFacetArray::_TConstIterator pFIter, const Base::Vector3f &rclCenter, - float fMaxDist, std::vector &rclNb); + void SearchNeighbours(const MeshFacetArray& rFacets, unsigned long index, const Base::Vector3f &rclCenter, + float fMaxDist, std::set &visit, MeshCollector& collect) const; protected: const MeshKernel &_rclMesh; /**< The mesh kernel. */ diff --git a/src/Mod/Mesh/App/Core/Approximation.cpp b/src/Mod/Mesh/App/Core/Approximation.cpp index ace1a796e3..15b0c522f5 100644 --- a/src/Mod/Mesh/App/Core/Approximation.cpp +++ b/src/Mod/Mesh/App/Core/Approximation.cpp @@ -37,6 +37,7 @@ #include //#define FC_USE_EIGEN +//#define FC_USE_BOOST #if defined(FC_USE_BOOST) #include #include @@ -54,25 +55,26 @@ extern "C" void LAPACK_DGESV (int const* n, int const* nrhs, #elif defined(FC_USE_EIGEN) # include #endif +# include using namespace MeshCore; -void Approximation::Convert( const Wm4::Vector3& Wm4, Base::Vector3f& pt) +void Approximation::Convert( const Wm4::Vector3& Wm4, Base::Vector3f& pt) { - pt.Set( Wm4.X(), Wm4.Y(), Wm4.Z() ); + pt.Set( (float)Wm4.X(), (float)Wm4.Y(), (float)Wm4.Z() ); } -void Approximation::Convert( const Base::Vector3f& pt, Wm4::Vector3& Wm4) +void Approximation::Convert( const Base::Vector3f& pt, Wm4::Vector3& Wm4) { Wm4.X() = pt.x; Wm4.Y() = pt.y; Wm4.Z() = pt.z; } -void Approximation::GetMgcVectorArray(std::vector< Wm4::Vector3 >& rcPts) const +void Approximation::GetMgcVectorArray(std::vector< Wm4::Vector3 >& rcPts) const { std::list< Base::Vector3f >::const_iterator It; for (It = _vPoints.begin(); It != _vPoints.end(); ++It) { - Wm4::Vector3 pt( (*It).x, (*It).y, (*It).z ); + Wm4::Vector3 pt( (*It).x, (*It).y, (*It).z ); rcPts.push_back( pt ); } } @@ -176,7 +178,7 @@ float PlaneFit::Fit() int r = lapack::syev('V','U',A,eigenval,lapack::optimal_workspace()); if (r) { } - float sigma; + float sigma = 0; #elif defined(FC_USE_EIGEN) Eigen::Matrix3d covMat = Eigen::Matrix3d::Zero(); covMat(0,0) = sxx; @@ -360,17 +362,15 @@ void PlaneFit::ProjectToPlane () // ------------------------------------------------------------------------------- -float FunctionContainer::dKoeff[]; // Koeffizienten der Quadrik - -bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance) +bool QuadraticFit::GetCurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance) { assert( _bIsFitted ); bool bResult = false; if (_bIsFitted) { - Wm4::Vector3 Dir0, Dir1; + Wm4::Vector3 Dir0, Dir1; FunctionContainer clFuncCont( _fCoeff ); bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1, Dir0, Dir1, dDistance ); @@ -382,7 +382,7 @@ bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, return bResult; } -bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1) +bool QuadraticFit::GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1) { bool bResult = false; @@ -394,12 +394,12 @@ bool QuadraticFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, f return bResult; } -const float& QuadraticFit::GetCoeffArray() const +const double& QuadraticFit::GetCoeffArray() const { return _fCoeff[0]; } -float QuadraticFit::GetCoeff(unsigned long ulIndex) const +double QuadraticFit::GetCoeff(unsigned long ulIndex) const { assert( ulIndex >= 0 && ulIndex < 10 ); @@ -414,9 +414,9 @@ float QuadraticFit::Fit() float fResult = FLOAT_MAX; if (CountPoints() > 0) { - std::vector< Wm4::Vector3 > cPts; + std::vector< Wm4::Vector3 > cPts; GetMgcVectorArray( cPts ); - fResult = Wm4::QuadraticFit3( CountPoints(), &(cPts[0]), _fCoeff ); + fResult = Wm4::QuadraticFit3( CountPoints(), &(cPts[0]), _fCoeff ); _fLastResult = fResult; _bIsFitted = true; @@ -425,7 +425,7 @@ float QuadraticFit::Fit() return fResult; } -void QuadraticFit::CalcEigenValues(float &dLambda1, float &dLambda2, float &dLambda3, +void QuadraticFit::CalcEigenValues(double &dLambda1, double &dLambda2, double &dLambda3, Base::Vector3f &clEV1, Base::Vector3f &clEV2, Base::Vector3f &clEV3) const { assert( _bIsFitted ); @@ -451,16 +451,16 @@ void QuadraticFit::CalcEigenValues(float &dLambda1, float &dLambda2, float &dLam * */ - Wm4::Matrix3 akMat(_fCoeff[4], _fCoeff[7]/2.0f, _fCoeff[8]/2.0f, + Wm4::Matrix3 akMat(_fCoeff[4], _fCoeff[7]/2.0f, _fCoeff[8]/2.0f, _fCoeff[7]/2.0f, _fCoeff[5], _fCoeff[9]/2.0f, _fCoeff[8]/2.0f, _fCoeff[9]/2.0f, _fCoeff[6] ); - Wm4::Matrix3 rkRot, rkDiag; + Wm4::Matrix3 rkRot, rkDiag; akMat.EigenDecomposition( rkRot, rkDiag ); - Wm4::Vector3 vEigenU = rkRot.GetColumn(0); - Wm4::Vector3 vEigenV = rkRot.GetColumn(1); - Wm4::Vector3 vEigenW = rkRot.GetColumn(2); + Wm4::Vector3 vEigenU = rkRot.GetColumn(0); + Wm4::Vector3 vEigenV = rkRot.GetColumn(1); + Wm4::Vector3 vEigenW = rkRot.GetColumn(2); Convert( vEigenU, clEV1 ); Convert( vEigenV, clEV2 ); @@ -471,11 +471,11 @@ void QuadraticFit::CalcEigenValues(float &dLambda1, float &dLambda2, float &dLam dLambda3 = rkDiag[2][2]; } -void QuadraticFit::CalcZValues( float x, float y, float &dZ1, float &dZ2 ) const +void QuadraticFit::CalcZValues( double x, double y, double &dZ1, double &dZ2 ) const { assert( _bIsFitted ); - float dDisk = _fCoeff[3]*_fCoeff[3]+2*_fCoeff[3]*_fCoeff[8]*x+2*_fCoeff[3]*_fCoeff[9]*y+ + double dDisk = _fCoeff[3]*_fCoeff[3]+2*_fCoeff[3]*_fCoeff[8]*x+2*_fCoeff[3]*_fCoeff[9]*y+ _fCoeff[8]*_fCoeff[8]*x*x+2*_fCoeff[8]*x*_fCoeff[9]*y+_fCoeff[9]*_fCoeff[9]*y*y- 4*_fCoeff[6]*_fCoeff[0]-4*_fCoeff[6]*_fCoeff[1]*x-4*_fCoeff[6]*_fCoeff[2]*y- 4*_fCoeff[6]*_fCoeff[7]*x*y-4*_fCoeff[6]*_fCoeff[4]*x*x-4*_fCoeff[6]*_fCoeff[5]*y*y; @@ -494,8 +494,8 @@ void QuadraticFit::CalcZValues( float x, float y, float &dZ1, float &dZ2 ) const else dDisk = sqrt( dDisk ); - dZ1 = 0.5f * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y + dDisk ) / _fCoeff[6] ); - dZ2 = 0.5f * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y - dDisk ) / _fCoeff[6] ); + dZ1 = 0.5 * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y + dDisk ) / _fCoeff[6] ); + dZ2 = 0.5 * ( ( -_fCoeff[3] - _fCoeff[8]*x - _fCoeff[9]*y - dDisk ) / _fCoeff[6] ); } // ------------------------------------------------------------------------------- @@ -529,13 +529,13 @@ float SurfaceFit::Fit() return fResult; } -bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance ) +bool SurfaceFit::GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance ) { bool bResult = false; if (_bIsFitted) { - Wm4::Vector3 Dir0, Dir1; + Wm4::Vector3 Dir0, Dir1; FunctionContainer clFuncCont( _fCoeff ); bResult = clFuncCont.CurvatureInfo( x, y, z, rfCurv0, rfCurv1, Dir0, Dir1, dDistance ); @@ -547,7 +547,7 @@ bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, flo return bResult; } -bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1) +bool SurfaceFit::GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1) { assert( _bIsFitted ); bool bResult = false; @@ -560,18 +560,17 @@ bool SurfaceFit::GetCurvatureInfo(float x, float y, float z, float &rfCurv0, flo return bResult; } -float SurfaceFit::PolynomFit() +double SurfaceFit::PolynomFit() { if (PlaneFit::Fit() == FLOAT_MAX) return FLOAT_MAX; -#if 0 -#if defined(FC_USE_BOOST) Base::Vector3d bs(this->_vBase.x,this->_vBase.y,this->_vBase.z); Base::Vector3d ex(this->_vDirU.x,this->_vDirU.y,this->_vDirU.z); Base::Vector3d ey(this->_vDirV.x,this->_vDirV.y,this->_vDirV.z); Base::Vector3d ez(this->_vDirW.x,this->_vDirW.y,this->_vDirW.z); +#if defined(FC_USE_BOOST) ublas::matrix A(6,6); ublas::vector b(6); for (int i=0; i<6; i++) { @@ -580,6 +579,11 @@ float SurfaceFit::PolynomFit() } b(i) = 0.0; } +#else + Eigen::Matrix A = Eigen::Matrix::Zero(); + Eigen::Matrix b = Eigen::Matrix::Zero(); + Eigen::Matrix x = Eigen::Matrix::Zero(); +#endif for (std::list::const_iterator it = _vPoints.begin(); it != _vPoints.end(); it++) { Base::Vector3d clPoint(it->x,it->y,it->z); @@ -648,29 +652,34 @@ float SurfaceFit::PolynomFit() A(5,4) = A(4,5); - +#if defined(FC_USE_BOOST) namespace lapack= boost::numeric::bindings::lapack; //std::clog << A << std::endl; //std::clog << b << std::endl; - lapack::gesv(A,b); + //lapack::gesv(A,b); + ublas::vector x(6); + x = b; //std::clog << b << std::endl; +#else + // A.llt().solve(b,&x); // not sure if always positive definite + A.qr().solve(b,&x); +#endif - _fCoeff[0] = (float)(-b(5)); - _fCoeff[1] = (float)(-b(3)); - _fCoeff[2] = (float)(-b(4)); + _fCoeff[0] = (float)(-x(5)); + _fCoeff[1] = (float)(-x(3)); + _fCoeff[2] = (float)(-x(4)); _fCoeff[3] = 1.0f; - _fCoeff[4] = (float)(-b(0)); - _fCoeff[5] = (float)(-b(1)); + _fCoeff[4] = (float)(-x(0)); + _fCoeff[5] = (float)(-x(1)); _fCoeff[6] = 0.0f; - _fCoeff[7] = (float)(-b(2)); + _fCoeff[7] = (float)(-x(2)); _fCoeff[8] = 0.0f; _fCoeff[9] = 0.0f; -#endif -#endif + return 0.0f; } -float SurfaceFit::Value(float x, float y) const +double SurfaceFit::Value(double x, double y) const { float z = 0.0f; if (_bIsFitted) { diff --git a/src/Mod/Mesh/App/Core/Approximation.h b/src/Mod/Mesh/App/Core/Approximation.h index 74124f35eb..623a17daca 100644 --- a/src/Mod/Mesh/App/Core/Approximation.h +++ b/src/Mod/Mesh/App/Core/Approximation.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -34,8 +35,64 @@ #include #include -namespace MeshCore { +namespace Wm4 +{ +/** + * An implicit surface is defined by F(x,y,z) = 0. + * This polynomial surface is actually defined as z = f(x,y) = ax^2 + by^2 + cx + dy + exy + g. + * To use Wm3 routines for implicit surfaces we can write the surface also as F(x,y,z) = f(x,y) - z = 0. + * @author Werner Mayer + */ +template +class PolynomialSurface : public ImplicitSurface +{ +public: + PolynomialSurface (const Real afCoeff[6]) + { for (int i=0; i<6; i++) m_afCoeff[i] = afCoeff[i]; } + + virtual ~PolynomialSurface () {} + + // the function + virtual Real F (const Vector3& rkP) const + { + return ( m_afCoeff[0]*rkP.X()*rkP.X() + + m_afCoeff[1]*rkP.Y()*rkP.Y() + + m_afCoeff[2]*rkP.X() + + m_afCoeff[3]*rkP.Y() + + m_afCoeff[4]*rkP.X()*rkP.Y() + + m_afCoeff[5]-rkP.Z()) ; + } + + // first-order partial derivatives + virtual Real FX (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[0]*rkP.X() + m_afCoeff[2] + m_afCoeff[4]*rkP.Y()); } + virtual Real FY (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[1]*rkP.Y() + m_afCoeff[3] + m_afCoeff[4]*rkP.X()); } + virtual Real FZ (const Vector3& rkP) const + { return (Real)-1.0; } + + // second-order partial derivatives + virtual Real FXX (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[0]); } + virtual Real FXY (const Vector3& rkP) const + { return (Real)(m_afCoeff[4]); } + virtual Real FXZ (const Vector3& rkP) const + { return (Real)0.0; } + virtual Real FYY (const Vector3& rkP) const + { return (Real)(2.0*m_afCoeff[1]); } + virtual Real FYZ (const Vector3& rkP) const + { return (Real)0.0; } + virtual Real FZZ (const Vector3& rkP) const + { return (Real)0.0; } + +protected: + Real m_afCoeff[6]; +}; + +} + +namespace MeshCore { /** * Abstract base class for approximation of a geometry to a given set of points. @@ -104,15 +161,15 @@ protected: /** * Converts point from Wm4::Vector3 to Base::Vector3f. */ - static void Convert( const Wm4::Vector3&, Base::Vector3f&); + static void Convert( const Wm4::Vector3&, Base::Vector3f&); /** * Converts point from Base::Vector3f to Wm4::Vector3. */ - static void Convert( const Base::Vector3f&, Wm4::Vector3&); + static void Convert( const Base::Vector3f&, Wm4::Vector3&); /** * Creates a vector of Wm4::Vector3 elements. */ - void GetMgcVectorArray( std::vector< Wm4::Vector3 >& rcPts ) const; + void GetMgcVectorArray( std::vector< Wm4::Vector3 >& rcPts ) const; protected: std::list< Base::Vector3f > _vPoints; /**< Holds the points for the fit algorithm. */ @@ -201,22 +258,22 @@ public: /** * Übertragen der Quadric-Koeffizienten * @param ulIndex Nummer des Koeffizienten (0..9) - * @return float Wert des Koeffizienten + * @return double Wert des Koeffizienten */ - float GetCoeff(unsigned long ulIndex) const; + double GetCoeff(unsigned long ulIndex) const; /** * Übertragen der Koeffizientan als Referenz * auf das interne Array - * @return const float& Referenz auf das float-Array + * @return const double& Referenz auf das double-Array */ - const float& GetCoeffArray() const; + const double& GetCoeffArray() const; /** * Aufruf des Fit-Algorithmus * @return float Qualität des Fits. */ float Fit(); - void CalcZValues(float x, float y, float &dZ1, float &dZ2) const; + void CalcZValues(double x, double y, double &dZ1, double &dZ2) const; /** * Berechnen der Krümmungswerte der Quadric in einem bestimmten Punkt. * @param x X-Koordinate @@ -229,12 +286,12 @@ public: * @param dDistance * @return bool Fehlerfreie Ausfürhung = true, ansonsten false */ - bool GetCurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance); + bool GetCurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance); - bool GetCurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfcurv1); + bool GetCurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfcurv1); /** * Aufstellen der Formanmatrix A und Berechnen der Eigenwerte. * @param dLambda1 Eigenwert 1 @@ -244,11 +301,11 @@ public: * @param clEV2 Eigenvektor 2 * @param clEV3 Eigenvektor 3 */ - void CalcEigenValues(float &dLambda1, float &dLambda2, float &dLambda3, + void CalcEigenValues(double &dLambda1, double &dLambda2, double &dLambda3, Base::Vector3f &clEV1, Base::Vector3f &clEV2, Base::Vector3f &clEV3) const; protected: - float _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ + double _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ }; // ------------------------------------------------------------------------------- @@ -275,15 +332,15 @@ public: */ virtual ~SurfaceFit(){}; - bool GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfCurv1, - Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, float &dDistance); - bool GetCurvatureInfo(float x, float y, float z, float &rfCurv0, float &rfcurv1); + bool GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfCurv1, + Base::Vector3f &rkDir0, Base::Vector3f &rkDir1, double &dDistance); + bool GetCurvatureInfo(double x, double y, double z, double &rfCurv0, double &rfcurv1); float Fit(); - float Value(float x, float y) const; + double Value(double x, double y) const; protected: - float PolynomFit(); - float _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ + double PolynomFit(); + double _fCoeff[ 10 ]; /**< Ziel der Koeffizienten aus dem Fit */ }; // ------------------------------------------------------------------------------- @@ -300,42 +357,24 @@ public: * Die MGC-Algorithmen arbeiten mit Funktionen dieses * Types */ - typedef float (*Function)(float,float,float); + typedef double (*Function)(double,double,double); /** * Der parametrisierte Konstruktor. Erwartet ein Array * mit den Quadric-Koeffizienten. * @param pKoef Zeiger auf die Quadric-Parameter - * (float [10]) + * (double [10]) */ - FunctionContainer(const float *pKoef) + FunctionContainer(const double *pKoef) { Assign( pKoef ); -/* - Function oF; - Function aoDF[3]; - Function aoD2F[6]; - - oF = &F; - aoDF[0] = &Fx; - aoDF[1] = &Fy; - aoDF[2] = &Fz; - aoD2F[0] = &Fxx; - aoD2F[1] = &Fxy; - aoD2F[2] = &Fxz; - aoD2F[3] = &Fyy; - aoD2F[4] = &Fyz; - aoD2F[5] = &Fzz; - - pImplSurf = new Wm4::QuadricSurface( oF, aoDF, aoD2F );*/ - - pImplSurf = new Wm4::QuadricSurface( dKoeff ); + pImplSurf = new Wm4::QuadricSurface( dKoeff ); } /** * Übernehmen der Quadric-Parameter * @param pKoef Zeiger auf die Quadric-Parameter - * (doube [10]) + * (double [10]) */ - void Assign( const float *pKoef ) + void Assign( const double *pKoef ) { for (long ct=0; ct < 10; ct++) dKoeff[ ct ] = pKoef[ ct ]; @@ -344,13 +383,13 @@ public: * Destruktor. Löscht die ImpicitSurface Klasse * der MGC-Bibliothek wieder */ - virtual ~FunctionContainer(){ delete pImplSurf; } + ~FunctionContainer(){ delete pImplSurf; } /** * Zugriff auf die Koeffizienten der Quadric * @param idx Index des Parameters - * @return float& Der Koeffizient + * @return double& Der Koeffizient */ - float& operator[](int idx){ return dKoeff[ idx ]; } + double& operator[](int idx){ return dKoeff[ idx ]; } /** * Redirector auf eine Methode der MGC Bibliothek. Ermittelt * die Hauptkrümmungen und ihre Richtungen im angegebenen Punkt. @@ -364,22 +403,22 @@ public: * @param dDistance Ergebnis das die Entfernung des Punktes von der Quadrik angibt. * @return bool Fehlerfreie Ausfürhung = true, ansonsten false */ - bool CurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1, - Wm4::Vector3 &rkDir0, Wm4::Vector3 &rkDir1, float &dDistance) + bool CurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1, + Wm4::Vector3 &rkDir0, Wm4::Vector3 &rkDir1, double &dDistance) { - return pImplSurf->ComputePrincipalCurvatureInfo( Wm4::Vector3(x, y, z),rfCurv0, rfCurv1, rkDir0, rkDir1 ); + return pImplSurf->ComputePrincipalCurvatureInfo( Wm4::Vector3(x, y, z),rfCurv0, rfCurv1, rkDir0, rkDir1 ); } - Base::Vector3f GetGradient( float x, float y, float z ) const + Base::Vector3f GetGradient( double x, double y, double z ) const { - Wm4::Vector3 grad = pImplSurf->GetGradient( Wm4::Vector3(x, y, z) ); + Wm4::Vector3 grad = pImplSurf->GetGradient( Wm4::Vector3(x, y, z) ); return Base::Vector3f( grad.X(), grad.Y(), grad.Z() ); } - Base::Matrix4D GetHessian( float x, float y, float z ) const + Base::Matrix4D GetHessian( double x, double y, double z ) const { - Wm4::Matrix3 hess = pImplSurf->GetHessian( Wm4::Vector3(x, y, z) ); + Wm4::Matrix3 hess = pImplSurf->GetHessian( Wm4::Vector3(x, y, z) ); Base::Matrix4D cMat; cMat.setToUnity(); cMat[0][0] = hess[0][0]; cMat[0][1] = hess[0][1]; cMat[0][2] = hess[0][2]; cMat[1][0] = hess[1][0]; cMat[1][1] = hess[1][1]; cMat[1][2] = hess[1][2]; @@ -387,23 +426,23 @@ public: return cMat; } - bool CurvatureInfo(float x, float y, float z, - float &rfCurv0, float &rfCurv1) + bool CurvatureInfo(double x, double y, double z, + double &rfCurv0, double &rfCurv1) { - float dQuot = Fz(x,y,z); - float zx = - ( Fx(x,y,z) / dQuot ); - float zy = - ( Fy(x,y,z) / dQuot ); + double dQuot = Fz(x,y,z); + double zx = - ( Fx(x,y,z) / dQuot ); + double zy = - ( Fy(x,y,z) / dQuot ); - float zxx = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zx * zx + dKoeff[8] * zx ) ) / dQuot; - float zyy = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zy * zy + dKoeff[9] * zy ) ) / dQuot; - float zxy = - ( dKoeff[6] * zx * zy + dKoeff[7] + dKoeff[8] * zy + dKoeff[9] * zx ) / dQuot; + double zxx = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zx * zx + dKoeff[8] * zx ) ) / dQuot; + double zyy = - ( 2.0f * ( dKoeff[5] + dKoeff[6] * zy * zy + dKoeff[9] * zy ) ) / dQuot; + double zxy = - ( dKoeff[6] * zx * zy + dKoeff[7] + dKoeff[8] * zy + dKoeff[9] * zx ) / dQuot; - float dNen = 1 + zx*zx + zy*zy; - float dNenSqrt = (float)sqrt( dNen ); - float K = ( zxx * zyy - zxy * zxy ) / ( dNen * dNen ); - float H = 0.5f * ( ( 1.0f+zx*zx - 2*zx*zy*zxy + (1.0f+zy*zy)*zxx ) / ( dNenSqrt * dNenSqrt * dNenSqrt ) ) ; + double dNen = 1 + zx*zx + zy*zy; + double dNenSqrt = (double)sqrt( dNen ); + double K = ( zxx * zyy - zxy * zxy ) / ( dNen * dNen ); + double H = 0.5f * ( ( 1.0f+zx*zx - 2*zx*zy*zxy + (1.0f+zy*zy)*zxx ) / ( dNenSqrt * dNenSqrt * dNenSqrt ) ) ; - float dDiscr = (float)sqrt(fabs(H*H-K)); + double dDiscr = (double)sqrt(fabs(H*H-K)); rfCurv0 = H - dDiscr; rfCurv1 = H + dDiscr; @@ -411,7 +450,7 @@ public: } //+++++++++ Quadric +++++++++++++++++++++++++++++++++++++++ - static float F ( float x, float y, float z ) + double F ( double x, double y, double z ) { return (dKoeff[0] + dKoeff[1]*x + dKoeff[2]*y + dKoeff[3]*z + dKoeff[4]*x*x + dKoeff[5]*y*y + dKoeff[6]*z*z + @@ -419,48 +458,48 @@ public: } //+++++++++ 1. derivations ++++++++++++++++++++++++++++++++ - static float Fx ( float x, float y, float z ) + double Fx ( double x, double y, double z ) { return( dKoeff[1] + 2.0f*dKoeff[4]*x + dKoeff[7]*y + dKoeff[8]*z ); } - static float Fy ( float x, float y, float z ) + double Fy ( double x, double y, double z ) { return( dKoeff[2] + 2.0f*dKoeff[5]*y + dKoeff[7]*x + dKoeff[9]*z ); } - static float Fz ( float x, float y, float z ) + double Fz ( double x, double y, double z ) { return( dKoeff[3] + 2.0f*dKoeff[6]*z + dKoeff[8]*x + dKoeff[9]*y ); } //+++++++++ 2. derivations ++++++++++++++++++++++++++++++++ - static float Fxx( float x, float y, float z ) + double Fxx( double x, double y, double z ) { return( 2.0f*dKoeff[4] ); } - static float Fxy( float x, float y, float z ) + double Fxy( double x, double y, double z ) { return( dKoeff[7] ); } - static float Fxz( float x, float y, float z ) + double Fxz( double x, double y, double z ) { return( dKoeff[8] ); } - static float Fyy( float x, float y, float z ) + double Fyy( double x, double y, double z ) { return( 2.0f*dKoeff[5] ); } - static float Fyz( float x, float y, float z ) + double Fyz( double x, double y, double z ) { return( dKoeff[9] ); } - static float Fzz( float x, float y, float z ) + double Fzz( double x, double y, double z ) { return( 2.0f*dKoeff[6] ); } protected: - static float dKoeff[ 10 ]; /**< Koeffizienten der Quadric */ - Wm4::ImplicitSurface *pImplSurf; /**< Zugriff auf die MGC-Bibliothek */ + double dKoeff[ 10 ]; /**< Koeffizienten der Quadric */ + Wm4::ImplicitSurface *pImplSurf; /**< Zugriff auf die MGC-Bibliothek */ private: /** diff --git a/src/Mod/Mesh/App/Core/Curvature.cpp b/src/Mod/Mesh/App/Core/Curvature.cpp new file mode 100644 index 0000000000..d0371da4b8 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Curvature.cpp @@ -0,0 +1,236 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "Curvature.h" +#include "Algorithm.h" +#include "Approximation.h" +#include "MeshKernel.h" +#include "Iterator.h" +#include "Tools.h" +#include +#include + +using namespace MeshCore; + +MeshCurvature::MeshCurvature(const MeshKernel& kernel) + : myKernel(kernel), myMinPoints(20), myRadius(0.5f) +{ + mySegment.resize(kernel.CountFacets()); + std::generate(mySegment.begin(), mySegment.end(), Base::iotaGen(0)); +} + +MeshCurvature::MeshCurvature(const MeshKernel& kernel, const std::vector& segm) + : myKernel(kernel), myMinPoints(20), myRadius(0.5f), mySegment(segm) +{ +} + +void MeshCurvature::ComputePerFace(bool parallel) +{ + Base::Vector3f rkDir0, rkDir1, rkPnt; + Base::Vector3f rkNormal; + myCurvature.clear(); + MeshRefPointToFacets search(myKernel); + FacetCurvature face(myKernel, search, myRadius, myMinPoints); + + if (!parallel) { + Base::SequencerLauncher seq("Curvature estimation", mySegment.size()); + for (std::vector::iterator it = mySegment.begin(); it != mySegment.end(); ++it) { + CurvatureInfo info = face.Compute(*it); + myCurvature.push_back(info); + seq.next(); + } + } + else { + QFuture future = QtConcurrent::mapped + (mySegment, boost::bind(&FacetCurvature::Compute, &face, _1)); + QFutureWatcher watcher; + watcher.setFuture(future); + watcher.waitForFinished(); + for (QFuture::const_iterator it = future.begin(); it != future.end(); ++it) { + myCurvature.push_back(*it); + } + } +} + +void MeshCurvature::ComputePerVertex() +{ + myCurvature.clear(); + + // get all points + std::vector< Wm4::Vector3 > aPnts; + aPnts.reserve(myKernel.CountPoints()); + MeshPointIterator cPIt(myKernel); + for (cPIt.Init(); cPIt.More(); cPIt.Next()) { + Wm4::Vector3 cP(cPIt->x, cPIt->y, cPIt->z); + aPnts.push_back(cP); + } + + // get all point connections + std::vector aIdx; + aIdx.reserve(3*myKernel.CountFacets()); + const MeshFacetArray& raFts = myKernel.GetFacets(); + for (MeshFacetArray::const_iterator jt = raFts.begin(); jt != raFts.end(); ++jt) { + for (int i=0; i<3; i++) { + aIdx.push_back((int)jt->_aulPoints[i]); + } + } + + // compute vertex based curvatures + Wm4::MeshCurvature meshCurv(myKernel.CountPoints(), &(aPnts[0]), myKernel.CountFacets(), &(aIdx[0])); + + // get curvature information now + const Wm4::Vector3* aMaxCurvDir = meshCurv.GetMaxDirections(); + const Wm4::Vector3* aMinCurvDir = meshCurv.GetMinDirections(); + const double* aMaxCurv = meshCurv.GetMaxCurvatures(); + const double* aMinCurv = meshCurv.GetMinCurvatures(); + + myCurvature.reserve(myKernel.CountPoints()); + for (unsigned long i=0; i& ind) : indices(ind){} + virtual void Append(const MeshCore::MeshKernel& kernel, unsigned long index) + { + unsigned long ulP1, ulP2, ulP3; + kernel.GetFacetPoints(index, ulP1, ulP2, ulP3); + indices.insert(ulP1); + indices.insert(ulP2); + indices.insert(ulP3); + } + +private: + std::set& indices; +}; +} + +// -------------------------------------------------------- + +FacetCurvature::FacetCurvature(const MeshKernel& kernel, const MeshRefPointToFacets& search, float r, unsigned long pt) + : myKernel(kernel), mySearch(search), myRadius(r), myMinPoints(pt) +{ +} + +CurvatureInfo FacetCurvature::Compute(unsigned long index) const +{ + Base::Vector3f rkDir0, rkDir1, rkPnt; + Base::Vector3f rkNormal; + + MeshGeomFacet face = myKernel.GetFacet(index); + Base::Vector3f face_gravity = face.GetGravityPoint(); + Base::Vector3f face_normal = face.GetNormal(); + std::set point_indices; + FitPointCollector collect(point_indices); + + float searchDist = myRadius; + int attempts=0; + do { + mySearch.Neighbours(index, searchDist, collect); + if (point_indices.empty()) + break; + float min_points = myMinPoints; + float use_points = point_indices.size(); + searchDist = searchDist * sqrt(min_points/use_points); + } + while((point_indices.size() < myMinPoints) && (attempts++ < 3)); + + std::vector fitPoints; + const MeshPointArray& verts = myKernel.GetPoints(); + fitPoints.reserve(point_indices.size()); + for (std::set::iterator it = point_indices.begin(); it != point_indices.end(); ++it) { + fitPoints.push_back(verts[*it] - face_gravity); + } + + float fMin, fMax; + if (fitPoints.size() >= myMinPoints) { + SurfaceFit surf_fit; + surf_fit.AddPoints(fitPoints); + surf_fit.Fit(); + rkNormal = surf_fit.GetNormal(); + double dMin, dMax, dDistance; + if (surf_fit.GetCurvatureInfo(0.0, 0.0, 0.0, dMin, dMax, rkDir1, rkDir0, dDistance)) { + fMin = (float)dMin; + fMax = (float)dMax; + } + else { + fMin = FLT_MAX; + fMax = FLT_MAX; + } + } + else { + // too few points => cannot calc any properties + fMin = FLT_MAX; + fMax = FLT_MAX; + } + + CurvatureInfo info; + if (fMin < fMax) { + info.fMaxCurvature = fMax; + info.fMinCurvature = fMin; + info.cMaxCurvDir = rkDir1; + info.cMinCurvDir = rkDir0; + } + else { + info.fMaxCurvature = fMin; + info.fMinCurvature = fMax; + info.cMaxCurvDir = rkDir0; + info.cMinCurvDir = rkDir1; + } + + // Reverse the direction of the normal vector if required + // (Z component of "local" normal vectors should be opposite in sign to the "local" view vector) + if (rkNormal * face_normal < 0.0) { + // Note: Changing the normal directions is similar to flipping over the object. + // In this case we must adjust the curvature information as well. + std::swap(info.cMaxCurvDir,info.cMinCurvDir); + std::swap(info.fMaxCurvature,info.fMinCurvature); + info.fMaxCurvature *= (-1.0); + info.fMinCurvature *= (-1.0); + } + + return info; +} diff --git a/src/Mod/Mesh/App/Core/Curvature.h b/src/Mod/Mesh/App/Core/Curvature.h new file mode 100644 index 0000000000..7c200946a4 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Curvature.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef MESHCORE_CURVATURE_H +#define MESHCORE_CURVATURE_H + +#include +#include + +namespace MeshCore { + +class MeshKernel; +class MeshRefPointToFacets; + +/** Curvature information. */ +struct MeshExport CurvatureInfo +{ + float fMaxCurvature, fMinCurvature; + Base::Vector3f cMaxCurvDir, cMinCurvDir; +}; + +class MeshExport FacetCurvature +{ +public: + FacetCurvature(const MeshKernel& kernel, const MeshRefPointToFacets& search, float, unsigned long); + CurvatureInfo Compute(unsigned long index) const; + +private: + const MeshKernel& myKernel; + const MeshRefPointToFacets& mySearch; + unsigned long myMinPoints; + float myRadius; +}; + +class MeshExport MeshCurvature +{ +public: + MeshCurvature(const MeshKernel& kernel); + MeshCurvature(const MeshKernel& kernel, const std::vector& segm); + float GetRadius() const { return myRadius; } + void SetRadius(float r) { myRadius = r; } + void ComputePerFace(bool parallel); + void ComputePerVertex(); + const std::vector& GetCurvature() const { return myCurvature; } + +private: + const MeshKernel& myKernel; + unsigned long myMinPoints; + float myRadius; + std::vector mySegment; + std::vector myCurvature; +}; + +} // MeshCore + +#endif // MESHCORE_CURVATURE_H diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp new file mode 100644 index 0000000000..4326457e56 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -0,0 +1,228 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#endif + +#include "Segmentation.h" +#include "Algorithm.h" +#include "Approximation.h" + +using namespace MeshCore; + +void MeshSurfaceSegment::PrepareFacet(unsigned long) +{ +} + +void MeshSurfaceSegment::AddSegment(const std::vector& segm) +{ + if (segm.size() >= minFacets) { + segments.push_back(segm); + } +} + +// -------------------------------------------------------- + +MeshDistancePlanarSegment::MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol) + : MeshDistanceSurfaceSegment(mesh, minFacets, tol), fitter(new PlaneFit) +{ +} + +MeshDistancePlanarSegment::~MeshDistancePlanarSegment() +{ + delete fitter; +} + +void MeshDistancePlanarSegment::PrepareFacet(unsigned long index) +{ + fitter->Clear(); + + MeshGeomFacet triangle = kernel.GetFacet(index); + basepoint = triangle.GetGravityPoint(); + normal = triangle.GetNormal(); + fitter->AddPoint(triangle._aclPoints[0]); + fitter->AddPoint(triangle._aclPoints[1]); + fitter->AddPoint(triangle._aclPoints[2]); +} + +bool MeshDistancePlanarSegment::TestFacet (const MeshFacet& face) const +{ + if (!fitter->Done()) + fitter->Fit(); + MeshGeomFacet triangle = kernel.GetFacet(face); + for (int i=0; i<3; i++) { + if (fabs(fitter->GetDistanceToPlane(triangle._aclPoints[i])) > tolerance) + return false; + } + + fitter->AddPoint(triangle.GetGravityPoint()); + return true; +} + +// -------------------------------------------------------- + +bool MeshCurvaturePlanarSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (fabs(ci.fMinCurvature) > tolerance) + return false; + if (fabs(ci.fMaxCurvature) > tolerance) + return false; + } + + return true; +} + +bool MeshCurvatureCylindricalSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (ci.fMaxCurvature > ci.fMinCurvature) { + // convexe + if (fabs(ci.fMinCurvature) > tolerance) + return false; + float diff = ci.fMaxCurvature - curvature; + if (fabs(diff) > tolerance) + return false; + } + else { + // concave + if (fabs(ci.fMaxCurvature) > tolerance) + return false; + float diff = ci.fMinCurvature + curvature; + if (fabs(diff) > tolerance) + return false; + } + } + + return true; +} + +bool MeshCurvatureSphericalSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (ci.fMaxCurvature * ci.fMinCurvature < 0) + return false; + float diff; + diff = fabs(ci.fMinCurvature) - curvature; + if (fabs(diff) > tolerance) + return false; + diff = fabs(ci.fMaxCurvature) - curvature; + if (fabs(diff) > tolerance) + return false; + } + + return true; +} + +bool MeshCurvatureFreeformSegment::TestFacet (const MeshFacet &rclFacet) const +{ + for (int i=0; i<3; i++) { + const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; + if (fabs(ci.fMinCurvature-c2) > tolerance) + return false; + if (fabs(ci.fMaxCurvature-c1) > tolerance) + return false; + } + + return true; +} + +// -------------------------------------------------------- + +MeshSurfaceVisitor::MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices) + : indices(indices), segm(segm) +{ +} + +MeshSurfaceVisitor::~MeshSurfaceVisitor () +{ +} + +bool MeshSurfaceVisitor::AllowVisit (const MeshFacet& face, const MeshFacet&, + unsigned long, unsigned long, unsigned short) +{ + return segm.TestFacet(face); +} + +bool MeshSurfaceVisitor::Visit (const MeshFacet & face, const MeshFacet &, + unsigned long ulFInd, unsigned long) +{ + indices.push_back(ulFInd); + return true; +} + +// -------------------------------------------------------- + +void MeshSegmentAlgorithm::FindSegments(std::vector& segm) +{ + // reset VISIT flags + unsigned long startFacet; + MeshCore::MeshAlgorithm cAlgo(myKernel); + cAlgo.ResetFacetFlag(MeshCore::MeshFacet::VISIT); + + const MeshCore::MeshFacetArray& rFAry = myKernel.GetFacets(); + MeshCore::MeshFacetArray::_TConstIterator iCur = rFAry.begin(); + MeshCore::MeshFacetArray::_TConstIterator iBeg = rFAry.begin(); + MeshCore::MeshFacetArray::_TConstIterator iEnd = rFAry.end(); + + // start from the first not visited facet + cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); + std::vector resetVisited; + + for (std::vector::iterator it = segm.begin(); it != segm.end(); ++it) { + cAlgo.ResetFacetsFlag(resetVisited, MeshCore::MeshFacet::VISIT); + resetVisited.clear(); + + iCur = std::find_if(iBeg, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), + MeshCore::MeshFacet::VISIT)); + startFacet = iCur - iBeg; + while (startFacet != ULONG_MAX) { + // collect all facets of the same geometry + std::vector indices; + indices.push_back(startFacet); + (*it)->PrepareFacet(startFacet); + MeshSurfaceVisitor pv(**it, indices); + myKernel.VisitNeighbourFacets(pv, startFacet); + + // add or discard the segment + if (indices.size() == 1) { + resetVisited.push_back(startFacet); + } + else { + (*it)->AddSegment(indices); + } + + // search for the next start facet + iCur = std::find_if(iCur, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), + MeshCore::MeshFacet::VISIT)); + if (iCur < iEnd) + startFacet = iCur - iBeg; + else + startFacet = ULONG_MAX; + } + } +} diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h new file mode 100644 index 0000000000..e45ecff4c1 --- /dev/null +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -0,0 +1,161 @@ +/*************************************************************************** + * Copyright (c) 2012 Imetric 3D GmbH * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef MESHCORE_SEGMENTATION_H +#define MESHCORE_SEGMENTATION_H + +#include "MeshKernel.h" +#include "Curvature.h" +#include "Visitor.h" +#include + +namespace MeshCore { + +class PlaneFit; +class MeshFacet; +typedef std::vector MeshSegment; + +class MeshExport MeshSurfaceSegment +{ +public: + MeshSurfaceSegment(unsigned long minFacets) + : minFacets(minFacets) {} + virtual ~MeshSurfaceSegment() {} + virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; + virtual void PrepareFacet(unsigned long); + void AddSegment(const std::vector&); + const std::vector GetSegments() const { return segments; } + +protected: + std::vector segments; + unsigned long minFacets; +}; + +// -------------------------------------------------------- + +class MeshExport MeshDistanceSurfaceSegment : public MeshSurfaceSegment +{ +public: + MeshDistanceSurfaceSegment(const MeshKernel& mesh, unsigned long minFacets, float tol) + : MeshSurfaceSegment(minFacets), kernel(mesh), tolerance(tol) {} + +protected: + const MeshKernel& kernel; + float tolerance; +}; + +class MeshExport MeshDistancePlanarSegment : public MeshDistanceSurfaceSegment +{ +public: + MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); + virtual ~MeshDistancePlanarSegment(); + bool TestFacet (const MeshFacet &rclFacet) const; + void PrepareFacet(unsigned long); + +protected: + Base::Vector3f basepoint; + Base::Vector3f normal; + PlaneFit* fitter; +}; + +// -------------------------------------------------------- + +class MeshExport MeshCurvatureSurfaceSegment : public MeshSurfaceSegment +{ +public: + MeshCurvatureSurfaceSegment(const std::vector& ci, unsigned long minFacets, float tol) + : MeshSurfaceSegment(minFacets), info(ci), tolerance(tol) {} + +protected: + const std::vector& info; + float tolerance; +}; + +class MeshExport MeshCurvaturePlanarSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvaturePlanarSegment(const std::vector& ci, unsigned long minFacets, float tol) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol) {} + virtual bool TestFacet (const MeshFacet &rclFacet) const; +}; + +class MeshExport MeshCurvatureCylindricalSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvatureCylindricalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float curvature; +}; + +class MeshExport MeshCurvatureSphericalSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvatureSphericalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float curvature; +}; + +class MeshExport MeshCurvatureFreeformSegment : public MeshCurvatureSurfaceSegment +{ +public: + MeshCurvatureFreeformSegment(const std::vector& ci, unsigned long minFacets, float tol, float c1, float c2) + : MeshCurvatureSurfaceSegment(ci, minFacets, tol), c1(c1), c2(c2) {} + virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float c1, c2; +}; + +class MeshExport MeshSurfaceVisitor : public MeshFacetVisitor +{ +public: + MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices); + virtual ~MeshSurfaceVisitor (); + bool AllowVisit (const MeshFacet& face, const MeshFacet&, + unsigned long, unsigned long, unsigned short neighbourIndex); + bool Visit (const MeshFacet & face, const MeshFacet &, + unsigned long ulFInd, unsigned long); + +protected: + std::vector &indices; + const MeshSurfaceSegment& segm; +}; + +class MeshExport MeshSegmentAlgorithm +{ +public: + MeshSegmentAlgorithm(const MeshKernel& kernel) : myKernel(kernel) {} + void FindSegments(std::vector&); + +private: + const MeshKernel& myKernel; +}; + +} // MeshCore + +#endif // MESHCORE_SEGMENTATION_H diff --git a/src/Mod/Mesh/App/FeatureMeshCurvature.cpp b/src/Mod/Mesh/App/FeatureMeshCurvature.cpp index f618f2dea8..f7bc012058 100644 --- a/src/Mod/Mesh/App/FeatureMeshCurvature.cpp +++ b/src/Mod/Mesh/App/FeatureMeshCurvature.cpp @@ -29,18 +29,16 @@ #include #include #include -#include -#include #include "FeatureMeshCurvature.h" #include "MeshFeature.h" +#include "Core/Curvature.h" #include "Core/Elements.h" #include "Core/Iterator.h" using namespace Mesh; -using namespace MeshCore; PROPERTY_SOURCE(Mesh::Curvature, App::DocumentObject) @@ -68,42 +66,20 @@ App::DocumentObjectExecReturn *Curvature::execute(void) } // get all points - const MeshKernel& rMesh = pcFeat->Mesh.getValue().getKernel(); - std::vector< Wm4::Vector3 > aPnts; - aPnts.reserve(rMesh.CountPoints()); - MeshPointIterator cPIt( rMesh ); - for (cPIt.Init(); cPIt.More(); cPIt.Next()) { - Wm4::Vector3 cP(cPIt->x, cPIt->y, cPIt->z); - aPnts.push_back(cP); - } + const MeshCore::MeshKernel& rMesh = pcFeat->Mesh.getValue().getKernel(); + MeshCore::MeshCurvature meshCurv(rMesh); + meshCurv.ComputePerVertex(); + const std::vector& curv = meshCurv.GetCurvature(); - // get all point connections - std::vector aIdx; - aIdx.reserve(3*rMesh.CountFacets()); - const std::vector& raFts = rMesh.GetFacets(); - for (std::vector::const_iterator jt = raFts.begin(); jt != raFts.end(); ++jt) { - for (int i=0; i<3; i++) { - aIdx.push_back((int)jt->_aulPoints[i]); - } - } - - // compute vertex based curvatures - Wm4::MeshCurvature meshCurv(rMesh.CountPoints(), &(aPnts[0]), rMesh.CountFacets(), &(aIdx[0])); - - // get curvature information now - const Wm4::Vector3* aMaxCurvDir = meshCurv.GetMaxDirections(); - const Wm4::Vector3* aMinCurvDir = meshCurv.GetMinDirections(); - const float* aMaxCurv = meshCurv.GetMaxCurvatures(); - const float* aMinCurv = meshCurv.GetMinCurvatures(); - - std::vector values(rMesh.CountPoints()); - for (unsigned long i=0; i values; + values.reserve(curv.size()); + for (std::vector::const_iterator it = curv.begin(); it != curv.end(); ++it) { CurvatureInfo ci; - ci.cMaxCurvDir = Base::Vector3f(aMaxCurvDir[i].X(), aMaxCurvDir[i].Y(), aMaxCurvDir[i].Z()); - ci.cMinCurvDir = Base::Vector3f(aMinCurvDir[i].X(), aMinCurvDir[i].Y(), aMinCurvDir[i].Z()); - ci.fMaxCurvature = aMaxCurv[i]; - ci.fMinCurvature = aMinCurv[i]; - values[i] = ci; + ci.cMaxCurvDir = it->cMaxCurvDir; + ci.cMinCurvDir = it->cMinCurvDir; + ci.fMaxCurvature = it->fMaxCurvature; + ci.fMinCurvature = it->fMinCurvature; + values.push_back(ci); } CurvInfo.setValues(values); diff --git a/src/Mod/Mesh/App/Makefile.am b/src/Mod/Mesh/App/Makefile.am index 6309f0d912..27537e0605 100644 --- a/src/Mod/Mesh/App/Makefile.am +++ b/src/Mod/Mesh/App/Makefile.am @@ -22,6 +22,8 @@ libMesh_la_SOURCES=\ Core/Approximation.h \ Core/Builder.cpp \ Core/Builder.h \ + Core/Curvature.cpp \ + Core/Curvature.h \ Core/Definitions.cpp \ Core/Definitions.h \ Core/Degeneration.cpp \ @@ -42,6 +44,8 @@ libMesh_la_SOURCES=\ Core/MeshIO.h \ Core/Projection.cpp \ Core/Projection.h \ + Core/Segmentation.cpp \ + Core/Segmentation.h \ Core/SetOperations.cpp \ Core/SetOperations.h \ Core/Smoothing.cpp \ @@ -324,9 +328,9 @@ nobase_include_HEADERS = \ # the library search path. -libMesh_la_LDFLAGS = -L../../../Base -L../../../App $(all_libraries) $(GTS_LIBS) \ +libMesh_la_LDFLAGS = -L../../../Base -L../../../App $(QT4_CORE_LIBS) $(all_libraries) $(GTS_LIBS) \ -version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@ -libMesh_la_CPPFLAGS = -DMeshExport= +libMesh_la_CPPFLAGS = -DMeshExport= -DEIGEN2_SUPPORT libMesh_la_LIBADD = \ @BOOST_FILESYSTEM_LIB@ @BOOST_REGEX_LIB@ @BOOST_SYSTEM_LIB@ \ @@ -354,7 +358,8 @@ Mesh_la_DEPENDENCIES = libMesh.la #-------------------------------------------------------------------------------------- # set the include path found by configure -AM_CXXFLAGS = -I$(top_srcdir)/src/3rdParty -I$(top_srcdir)/src -I$(top_builddir)/src $(GTS_CFLAGS) $(all_includes) +AM_CXXFLAGS = -I$(top_srcdir)/src/3rdParty -I$(top_srcdir)/src -I$(top_builddir)/src $(GTS_CFLAGS) \ + $(all_includes) $(QT4_CORE_CXXFLAGS) includedir = @includedir@/Mod/Mesh/App libdir = $(prefix)/Mod/Mesh diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index bd7be06d0d..89f85856ad 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -1422,10 +1422,11 @@ MeshObject* MeshObject::meshFromSegment(const std::vector& indice return new MeshObject(kernel, _Mtrx); } -std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, const Segment& aSegment, float dev) const +std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, const Segment& aSegment, + float dev, unsigned long minFacets) const { std::vector segm; - unsigned long startFacet, visited; + unsigned long startFacet; if (this->_kernel.CountFacets() == 0) return segm; @@ -1445,7 +1446,7 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons MeshCore::MeshFacetArray::_TConstIterator iEnd = rFAry.end(); // start from the first not visited facet - visited = cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); + cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), MeshCore::MeshFacet::VISIT)); startFacet = iTri - iBeg; @@ -1455,7 +1456,7 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons std::vector indices; indices.push_back(startFacet); MeshCore::MeshPlaneVisitor pv(this->_kernel, startFacet, dev, indices); - visited += this->_kernel.VisitNeighbourFacets(pv, startFacet); + this->_kernel.VisitNeighbourFacets(pv, startFacet); iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), MeshCore::MeshFacet::VISIT)); @@ -1463,7 +1464,8 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons startFacet = iTri - iBeg; else startFacet = ULONG_MAX; - segm.push_back(Segment(const_cast(this), indices, false)); + if (indices.size() > minFacets) + segm.push_back(Segment(const_cast(this), indices, false)); } return segm; diff --git a/src/Mod/Mesh/App/Mesh.h b/src/Mod/Mesh/App/Mesh.h index dcd1ca19d2..3d884517fe 100644 --- a/src/Mod/Mesh/App/Mesh.h +++ b/src/Mod/Mesh/App/Mesh.h @@ -266,7 +266,7 @@ public: const Segment& getSegment(unsigned long) const; Segment& getSegment(unsigned long); MeshObject* meshFromSegment(const std::vector&) const; - std::vector getSegmentsFromType(Type, const Segment& aSegment, float dev) const; + std::vector getSegmentsFromType(Type, const Segment& aSegment, float dev, unsigned long minFacets) const; //@} /** @name Primitives */ diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index 6070d9fc1e..f29a59730a 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -370,13 +370,26 @@ an empty dictionary if there is no intersection. - + - Get all planes of the mesh as segment. + getPlanarSegments(dev,[min faces=0]) -> list +Get all planes of the mesh as segment. In the worst case each triangle can be regarded as single plane if none of its neighours is coplanar. + + + getSegmentsByCurvature(list) -> list +The argument list gives a list if tuples where it defines the preferred maximum curvature, +the preferred minumum curvature, the tolerance and the number of minimum faces for the segment. +Example: +c=(1.0, 0.0, 0.1, 500) # search for a cylinder with radius 1.0 +p=(0.0, 0.0, 0.1, 500) # search for a plane +mesh.getSegmentsByCurvature([c,p]) + + + A collection of the mesh points diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 143ff61f9d..1e32bf2f3e 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -41,6 +41,8 @@ #include "Core/Grid.h" #include "Core/MeshKernel.h" #include "Core/Triangulation.h" +#include "Core/Segmentation.h" +#include "Core/Curvature.h" using namespace Mesh; @@ -1356,15 +1358,16 @@ PyObject* MeshPy::nearestFacetOnRay(PyObject *args) } } -PyObject* MeshPy::getPlanes(PyObject *args) +PyObject* MeshPy::getPlanarSegments(PyObject *args) { float dev; - if (!PyArg_ParseTuple(args, "f",&dev)) + unsigned long minFacets=0; + if (!PyArg_ParseTuple(args, "f|k",&dev,&minFacets)) return NULL; Mesh::MeshObject* mesh = getMeshObjectPtr(); std::vector segments = mesh->getSegmentsFromType - (Mesh::MeshObject::PLANE, Mesh::Segment(mesh,false), dev); + (Mesh::MeshObject::PLANE, Mesh::Segment(mesh,false), dev, minFacets); Py::List s; for (std::vector::iterator it = segments.begin(); it != segments.end(); ++it) { @@ -1379,6 +1382,48 @@ PyObject* MeshPy::getPlanes(PyObject *args) return Py::new_reference_to(s); } +PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) +{ + PyObject* l; + if (!PyArg_ParseTuple(args, "O!",&PyList_Type,&l)) + return NULL; + + const MeshCore::MeshKernel& kernel = getMeshObjectPtr()->getKernel(); + MeshCore::MeshSegmentAlgorithm finder(kernel); + MeshCore::MeshCurvature meshCurv(kernel); + meshCurv.ComputePerVertex(); + + Py::List func(l); + std::vector segm; + //segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment(meshCurv.GetCurvature(), minFacets, dev, 4.75f)); + //segm.push_back(new MeshCore::MeshCurvaturePlanarSegment(meshCurv.GetCurvature(), minFacets, dev)); + for (Py::List::iterator it = func.begin(); it != func.end(); ++it) { + Py::Tuple t(*it); + float c1 = (float)Py::Float(t[0]); + float c2 = (float)Py::Float(t[1]); + float tol = (float)Py::Float(t[2]); + int num = (int)Py::Int(t[3]); + segm.push_back(new MeshCore::MeshCurvatureFreeformSegment(meshCurv.GetCurvature(), num, tol, c1, c2)); + } + + finder.FindSegments(segm); + + Py::List list; + for (std::vector::iterator segmIt = segm.begin(); segmIt != segm.end(); ++segmIt) { + std::vector data = (*segmIt)->GetSegments(); + delete (*segmIt); + for (std::vector::iterator it = data.begin(); it != data.end(); ++it) { + Py::List ary; + for (MeshCore::MeshSegment::const_iterator jt = it->begin(); jt != it->end(); ++jt) { + ary.append(Py::Int((int)*jt)); + } + list.append(ary); + } + } + + return Py::new_reference_to(list); +} + Py::Int MeshPy::getCountPoints(void) const { return Py::Int((long)getMeshObjectPtr()->countPoints()); From 8c3b83a451d152547988c61c346ea999b01068ba Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 01:40:05 +0200 Subject: [PATCH 232/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.cpp | 6 +++--- src/Mod/Mesh/App/Core/Segmentation.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 4326457e56..450a7a0674 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -31,7 +31,7 @@ using namespace MeshCore; -void MeshSurfaceSegment::PrepareFacet(unsigned long) +void MeshSurfaceSegment::Initialize(unsigned long) { } @@ -54,7 +54,7 @@ MeshDistancePlanarSegment::~MeshDistancePlanarSegment() delete fitter; } -void MeshDistancePlanarSegment::PrepareFacet(unsigned long index) +void MeshDistancePlanarSegment::Initialize(unsigned long index) { fitter->Clear(); @@ -204,7 +204,7 @@ void MeshSegmentAlgorithm::FindSegments(std::vector& segm) // collect all facets of the same geometry std::vector indices; indices.push_back(startFacet); - (*it)->PrepareFacet(startFacet); + (*it)->Initialize(startFacet); MeshSurfaceVisitor pv(**it, indices); myKernel.VisitNeighbourFacets(pv, startFacet); diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index e45ecff4c1..07e9fa9caf 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -41,7 +41,7 @@ public: : minFacets(minFacets) {} virtual ~MeshSurfaceSegment() {} virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; - virtual void PrepareFacet(unsigned long); + virtual void Initialize(unsigned long); void AddSegment(const std::vector&); const std::vector GetSegments() const { return segments; } @@ -69,7 +69,7 @@ public: MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); virtual ~MeshDistancePlanarSegment(); bool TestFacet (const MeshFacet &rclFacet) const; - void PrepareFacet(unsigned long); + void Initialize(unsigned long); protected: Base::Vector3f basepoint; From 26a06cc91a737389ac2bad44a6dae12fabeee1d4 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 15:57:32 +0200 Subject: [PATCH 233/351] Mesh segmentation --- src/Mod/Complete/Gui/Workbench.cpp | 1 + src/Mod/Mesh/App/Core/Segmentation.h | 2 +- src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h | 6 +- src/Mod/Mesh/App/MeshPyImp.cpp | 8 +- src/Mod/Mesh/Gui/CMakeLists.txt | 4 + src/Mod/Mesh/Gui/Command.cpp | 35 +++ src/Mod/Mesh/Gui/Makefile.am | 2 + src/Mod/Mesh/Gui/Segmentation.cpp | 136 ++++++++++++ src/Mod/Mesh/Gui/Segmentation.h | 74 +++++++ src/Mod/Mesh/Gui/Segmentation.ui | 227 ++++++++++++++++++++ src/Mod/Mesh/Gui/Workbench.cpp | 3 +- 11 files changed, 488 insertions(+), 10 deletions(-) create mode 100644 src/Mod/Mesh/Gui/Segmentation.cpp create mode 100644 src/Mod/Mesh/Gui/Segmentation.h create mode 100644 src/Mod/Mesh/Gui/Segmentation.ui diff --git a/src/Mod/Complete/Gui/Workbench.cpp b/src/Mod/Complete/Gui/Workbench.cpp index d60424b2d7..9b0b0fcf0f 100644 --- a/src/Mod/Complete/Gui/Workbench.cpp +++ b/src/Mod/Complete/Gui/Workbench.cpp @@ -229,6 +229,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_ToolMesh" + << "Mesh_Segmentation" << "Mesh_VertexCurvature"; // Part **************************************************************************************************** diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index 07e9fa9caf..0219610014 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -43,7 +43,7 @@ public: virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; virtual void Initialize(unsigned long); void AddSegment(const std::vector&); - const std::vector GetSegments() const { return segments; } + const std::vector& GetSegments() const { return segments; } protected: std::vector segments; diff --git a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h index 16f6e1a576..76c51c54b1 100644 --- a/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h +++ b/src/Mod/Mesh/App/FeatureMeshSegmentByMesh.h @@ -21,8 +21,8 @@ ***************************************************************************/ -#ifndef FEATURE_MESH_SEGMENT_H -#define FEATURE_MESH_SEGMENT_H +#ifndef FEATURE_MESH_SEGMENTBYMESH_H +#define FEATURE_MESH_SEGMENTBYMESH_H #include @@ -63,4 +63,4 @@ public: } -#endif // FEATURE_MESH_SEGMENT_H +#endif // FEATURE_MESH_SEGMENTBYMESH_H diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index 1e32bf2f3e..dd1f0e3e10 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -1395,8 +1395,6 @@ PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) Py::List func(l); std::vector segm; - //segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment(meshCurv.GetCurvature(), minFacets, dev, 4.75f)); - //segm.push_back(new MeshCore::MeshCurvaturePlanarSegment(meshCurv.GetCurvature(), minFacets, dev)); for (Py::List::iterator it = func.begin(); it != func.end(); ++it) { Py::Tuple t(*it); float c1 = (float)Py::Float(t[0]); @@ -1410,15 +1408,15 @@ PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) Py::List list; for (std::vector::iterator segmIt = segm.begin(); segmIt != segm.end(); ++segmIt) { - std::vector data = (*segmIt)->GetSegments(); - delete (*segmIt); - for (std::vector::iterator it = data.begin(); it != data.end(); ++it) { + const std::vector& data = (*segmIt)->GetSegments(); + for (std::vector::const_iterator it = data.begin(); it != data.end(); ++it) { Py::List ary; for (MeshCore::MeshSegment::const_iterator jt = it->begin(); jt != it->end(); ++jt) { ary.append(Py::Int((int)*jt)); } list.append(ary); } + delete (*segmIt); } return Py::new_reference_to(list); diff --git a/src/Mod/Mesh/Gui/CMakeLists.txt b/src/Mod/Mesh/Gui/CMakeLists.txt index 9941cac13b..ae4701a0f9 100644 --- a/src/Mod/Mesh/Gui/CMakeLists.txt +++ b/src/Mod/Mesh/Gui/CMakeLists.txt @@ -34,6 +34,7 @@ set(Dialogs_UIC_SRCS DlgSettingsMeshView.ui DlgSmoothing.ui RemoveComponents.ui + Segmentation.ui ) qt4_wrap_ui(Dialogs_UIC_HDRS ${Dialogs_UIC_SRCS}) SET(Dialogs_SRCS @@ -53,6 +54,9 @@ SET(Dialogs_SRCS RemoveComponents.ui RemoveComponents.cpp RemoveComponents.h + Segmentation.ui + Segmentation.cpp + Segmentation.h ) SOURCE_GROUP("Dialogs" FILES ${Dialogs_SRCS}) diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index 03d9714749..cc83bdaa0d 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -69,6 +69,7 @@ #include "ViewProviderMeshFaceSet.h" #include "ViewProviderCurvature.h" #include "MeshEditor.h" +#include "Segmentation.h" using namespace Mesh; @@ -1368,6 +1369,39 @@ bool CmdMeshFillInteractiveHole::isActive(void) return false; } +DEF_STD_CMD_A(CmdMeshSegmentation); + +CmdMeshSegmentation::CmdMeshSegmentation() + : Command("Mesh_Segmentation") +{ + sAppModule = "Mesh"; + sGroup = QT_TR_NOOP("Mesh"); + sMenuText = QT_TR_NOOP("Create mesh segments..."); + sToolTipText = QT_TR_NOOP("Create mesh segments"); + sWhatsThis = "Mesh_Segmentation"; + sStatusTip = QT_TR_NOOP("Create mesh segments"); +} + +void CmdMeshSegmentation::activated(int iMsg) +{ + std::vector objs = Gui::Selection().getObjectsOfType + (Mesh::Feature::getClassTypeId()); + Mesh::Feature* mesh = static_cast(objs.front()); + Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); + if (!dlg) { + dlg = new MeshGui::TaskSegmentation(mesh); + } + Gui::Control().showDialog(dlg); +} + +bool CmdMeshSegmentation::isActive(void) +{ + if (Gui::Control().activeDialog()) + return false; + return Gui::Selection().countObjectsOfType + (Mesh::Feature::getClassTypeId()) == 1; +} + void CreateMeshCommands(void) { Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); @@ -1400,4 +1434,5 @@ void CreateMeshCommands(void) rcCmdMgr.addCommand(new CmdMeshFillInteractiveHole()); rcCmdMgr.addCommand(new CmdMeshRemoveCompByHand()); rcCmdMgr.addCommand(new CmdMeshFromGeometry()); + rcCmdMgr.addCommand(new CmdMeshSegmentation()); } diff --git a/src/Mod/Mesh/Gui/Makefile.am b/src/Mod/Mesh/Gui/Makefile.am index 6b2066ff0e..46158d1e10 100644 --- a/src/Mod/Mesh/Gui/Makefile.am +++ b/src/Mod/Mesh/Gui/Makefile.am @@ -7,6 +7,7 @@ BUILT_SOURCES=\ ui_DlgSettingsMeshView.h \ ui_DlgSmoothing.h \ ui_RemoveComponents.h \ + ui_Segmentation.h \ moc_DlgEvaluateMeshImp.cpp \ moc_DlgRegularSolidImp.cpp \ moc_DlgSettingsMeshView.cpp \ @@ -127,6 +128,7 @@ EXTRA_DIST = \ DlgSettingsMeshView.ui \ DlgSmoothing.ui \ RemoveComponents.ui \ + Segmentation.ui \ Resources/Mesh.qrc \ Resources/translations/Mesh_af.qm \ Resources/translations/Mesh_af.ts \ diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp new file mode 100644 index 0000000000..962d65f2e5 --- /dev/null +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + * Copyright (c) 2012 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "Segmentation.h" +#include "ui_Segmentation.h" +#include +#include + +#include +#include +#include +#include +#include + +using namespace MeshGui; + +Segmentation::Segmentation(Mesh::Feature* mesh, QWidget* parent, Qt::WFlags fl) + : QWidget(parent, fl), myMesh(mesh) +{ + ui = new Ui_Segmentation; + ui->setupUi(this); + ui->numPln->setRange(1, INT_MAX); + ui->numPln->setValue(100); + ui->numCyl->setRange(1, INT_MAX); + ui->numCyl->setValue(100); + ui->numSph->setRange(1, INT_MAX); + ui->numSph->setValue(100); +} + +Segmentation::~Segmentation() +{ + // no need to delete child widgets, Qt does it all for us + delete ui; +} + +void Segmentation::accept() +{ + const Mesh::MeshObject* mesh = myMesh->Mesh.getValuePtr(); + // make a copy because we might smooth the mesh before + MeshCore::MeshKernel kernel = mesh->getKernel(); + + if (ui->checkBoxSmooth->isChecked()) { + MeshCore::LaplaceSmoothing smoother(kernel); + smoother.Smooth(ui->smoothSteps->value()); + } + + MeshCore::MeshSegmentAlgorithm finder(kernel); + MeshCore::MeshCurvature meshCurv(kernel); + meshCurv.ComputePerVertex(); + + std::vector segm; + if (ui->groupBoxCyl->isChecked()) { + segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment + (meshCurv.GetCurvature(), ui->numCyl->value(), ui->tolCyl->value(), ui->radCyl->value())); + } + if (ui->groupBoxSph->isChecked()) { + segm.push_back(new MeshCore::MeshCurvatureSphericalSegment + (meshCurv.GetCurvature(), ui->numSph->value(), ui->tolSph->value(), ui->radSph->value())); + } + if (ui->groupBoxPln->isChecked()) { + segm.push_back(new MeshCore::MeshCurvaturePlanarSegment + (meshCurv.GetCurvature(), ui->numPln->value(), ui->tolPln->value())); + } + finder.FindSegments(segm); + + App::Document* document = App::GetApplication().getActiveDocument(); + for (std::vector::iterator it = segm.begin(); it != segm.end(); ++it) { + const std::vector& data = (*it)->GetSegments(); + for (std::vector::const_iterator jt = data.begin(); jt != data.end(); ++jt) { + Mesh::MeshObject* segment = mesh->meshFromSegment(*jt); + Mesh::Feature* feaSegm = static_cast(document->addObject("Mesh::Feature", "Segment")); + Mesh::MeshObject* feaMesh = feaSegm->Mesh.startEditing(); + feaMesh->swap(*segment); + feaSegm->Mesh.finishEditing(); + delete segment; + } + delete (*it); + } +} + +void Segmentation::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + } + QWidget::changeEvent(e); +} + +// --------------------------------------- + +/* TRANSLATOR MeshGui::TaskRemoveComponents */ + +TaskSegmentation::TaskSegmentation(Mesh::Feature* mesh) +{ + widget = new Segmentation(mesh); + taskbox = new Gui::TaskView::TaskBox( + QPixmap(), widget->windowTitle(), false, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); +} + +TaskSegmentation::~TaskSegmentation() +{ + // automatically deleted in the sub-class +} + +bool TaskSegmentation::accept() +{ + widget->accept(); + return true; +} diff --git a/src/Mod/Mesh/Gui/Segmentation.h b/src/Mod/Mesh/Gui/Segmentation.h new file mode 100644 index 0000000000..95d1411635 --- /dev/null +++ b/src/Mod/Mesh/Gui/Segmentation.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (c) 2012 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef MESHGUI_SEGMENTATION_H +#define MESHGUI_SEGMENTATION_H + +#include +#include +#include + +// forward declarations +namespace Mesh { class Feature; } + +namespace MeshGui { +class Ui_Segmentation; + +class MeshGuiExport Segmentation : public QWidget +{ +public: + Segmentation(Mesh::Feature* mesh, QWidget* parent = 0, Qt::WFlags fl = 0); + ~Segmentation(); + void accept(); + +protected: + void changeEvent(QEvent *e); + +private: + Ui_Segmentation* ui; + Mesh::Feature* myMesh; +}; + +/** + * Embed the panel into a task dialog. + */ +class TaskSegmentation : public Gui::TaskView::TaskDialog +{ +public: + TaskSegmentation(Mesh::Feature* mesh); + ~TaskSegmentation(); + +public: + bool accept(); + + virtual QDialogButtonBox::StandardButtons getStandardButtons() const + { return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; } + +private: + Segmentation* widget; + Gui::TaskView::TaskBox* taskbox; +}; + +} + +#endif // MESHGUI_SEGMENTATION_H diff --git a/src/Mod/Mesh/Gui/Segmentation.ui b/src/Mod/Mesh/Gui/Segmentation.ui new file mode 100644 index 0000000000..129c89873c --- /dev/null +++ b/src/Mod/Mesh/Gui/Segmentation.ui @@ -0,0 +1,227 @@ + + + MeshGui::Segmentation + + + + 0 + 0 + 289 + 379 + + + + Mesh segmentation + + + + + + Smooth mesh + + + true + + + + + + + 3 + + + + + + + Plane + + + true + + + + + + Tolerance + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + Minumum number of faces + + + + + + + 100000 + + + 100 + + + + + + + + + + Cylinder + + + true + + + + + + Radius + + + + + + + 0.100000000000000 + + + 5.000000000000000 + + + + + + + Tolerance + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + Minimum number of faces + + + + + + + 100000 + + + 100 + + + + + + + + + + Sphere + + + true + + + + + + Radius + + + + + + + 0.100000000000000 + + + 5.000000000000000 + + + + + + + Tolerance + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + Minimum number of faces + + + + + + + 100000 + + + 100 + + + + + + + + + + + + checkBoxSmooth + toggled(bool) + smoothSteps + setEnabled(bool) + + + 75 + 24 + + + 188 + 19 + + + + + diff --git a/src/Mod/Mesh/Gui/Workbench.cpp b/src/Mod/Mesh/Gui/Workbench.cpp index a2a3fa0878..25b9bd6568 100644 --- a/src/Mod/Mesh/Gui/Workbench.cpp +++ b/src/Mod/Mesh/Gui/Workbench.cpp @@ -190,7 +190,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Mesh_FillupHoles" << "Mesh_FillInteractiveHole" << "Mesh_RemoveComponents" << "Mesh_RemoveCompByHand" << "Mesh_AddFacet" << "Mesh_Smoothing" << "Separator" << "Mesh_BuildRegularSolid" << boolean << "Separator" << "Mesh_PolySelect" << "Mesh_PolyCut" - << "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_PolyTrim" << "Mesh_VertexCurvature"; + << "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_PolyTrim" << "Mesh_Segmentation" + << "Mesh_VertexCurvature"; return root; } From 837ceccfc76cbe126713116e7e94c48c33b2685d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 12:57:48 -0300 Subject: [PATCH 234/351] Added 0000387 : Arch roof tool --- src/Mod/Arch/Arch.py | 1 + src/Mod/Arch/ArchRoof.py | 137 ++++ src/Mod/Arch/Arch_rc.py | 1014 +++++++++++++++++++----------- src/Mod/Arch/CMakeLists.txt | 1 + src/Mod/Arch/InitGui.py | 2 +- src/Mod/Arch/Makefile.am | 3 +- src/WindowsInstaller/ModArch.wxi | 1 + 7 files changed, 781 insertions(+), 378 deletions(-) create mode 100644 src/Mod/Arch/ArchRoof.py diff --git a/src/Mod/Arch/Arch.py b/src/Mod/Arch/Arch.py index 81bb29ffe5..fc537d85ae 100644 --- a/src/Mod/Arch/Arch.py +++ b/src/Mod/Arch/Arch.py @@ -39,3 +39,4 @@ from ArchCommands import * from ArchSectionPlane import * from ArchWindow import * from ArchAxis import * +from ArchRoof import * diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py new file mode 100644 index 0000000000..62850f243e --- /dev/null +++ b/src/Mod/Arch/ArchRoof.py @@ -0,0 +1,137 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2012 * +#* Yorik van Havre * +#* * +#* 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 * +#* * +#*************************************************************************** + +import FreeCAD,FreeCADGui,Draft,ArchComponent +from draftlibs import fcvec +from FreeCAD import Vector +from PyQt4 import QtCore + +__title__="FreeCAD Roof" +__author__ = "Yorik van Havre" +__url__ = "http://free-cad.sourceforge.net" + +def makeRoof(baseobj,facenr=1,angle=45,name="Roof"): + '''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on a + face from an existing object. You can provide the number of the face + to build the roof on (default = 1), the angle (default=45) and a name (default + = roof).''' + obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) + _Roof(obj) + _ViewProviderRoof(obj.ViewObject) + obj.Base = baseobj + obj.Face = facenr + obj.Angle = angle + return obj + +class _CommandRoof: + "the Arch Roof command definition" + def GetResources(self): + return {'Pixmap' : 'Arch_Roof', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Roof","Roof"), + 'Accel': "R, F", + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Roof","Creates a roof object from the selected face of an object")} + + def IsActive(self): + if FreeCADGui.Selection.getSelection(): + return True + else: + return False + + def Activated(self): + sel = FreeCADGui.Selection.getSelectionEx() + if sel: + sel = sel[0] + if sel.HasSubObjects: + if "Face" in sel.SubElementNames[0]: + obj = sel.Object + idx = int(sel.SubElementNames[0][4:]) + FreeCAD.ActiveDocument.openTransaction("Create Roof") + makeRoof(obj,idx) + FreeCAD.ActiveDocument.commitTransaction() + +class _Roof(ArchComponent.Component): + "The Roof object" + def __init__(self,obj): + ArchComponent.Component.__init__(self,obj) + obj.addProperty("App::PropertyAngle","Angle","Base", + "The angle of this roof") + obj.addProperty("App::PropertyInteger","Face","Base", + "The face number of the base object used to build this roof") + obj.addProperty("App::PropertyLink","Base","Base", + "The base object this roof is built on") + self.Type = "Structure" + + def execute(self,obj): + self.createGeometry(obj) + + def onChanged(self,obj,prop): + if prop in ["Base","Face","Angle","Additions","Subtractions"]: + self.createGeometry(obj) + + def createGeometry(self,obj): + import Part,math + from draftlibs import fcgeo + pl = obj.Placement + + if obj.Base and obj.Face and obj.Angle: + if len(obj.Base.Shape.Faces) >= obj.Face: + f = obj.Base.Shape.Faces[obj.Face-1] + if len(f.Wires) == 1: + if f.Wires[0].isClosed(): + c = round(math.tan(math.radians(obj.Angle)),Draft.precision()) + norm = f.normalAt(0,0) + d = f.BoundBox.DiagonalLength + edges = fcgeo.sortEdges(f.Edges) + l = len(edges) + edges.append(edges[0]) + shps = [] + for i in range(l): + v = fcgeo.vec(fcgeo.angleBisection(edges[i],edges[i+1])) + v.normalize() + bis = v.getAngle(fcgeo.vec(edges[i])) + delta = 1/math.cos(bis) + v.multiply(delta) + n = (FreeCAD.Vector(norm)).multiply(c) + dv = v.add(n) + dv.normalize() + dv.scale(d,d,d) + shps.append(f.extrude(dv)) + c = shps.pop() + for s in shps: + c = c.common(s) + c = c.removeSplitter() + if not c.isNull(): + obj.Shape = c + if not fcgeo.isNull(pl): + obj.Placement = pl + +class _ViewProviderRoof(ArchComponent.ViewProviderComponent): + "A View Provider for the Roof object" + + def __init__(self,vobj): + ArchComponent.ViewProviderComponent.__init__(self,vobj) + + def getIcon(self): + return ":/icons/Arch_Roof_Tree.svg" + +FreeCADGui.addCommand('Arch_Roof',_CommandRoof()) diff --git a/src/Mod/Arch/Arch_rc.py b/src/Mod/Arch/Arch_rc.py index cfb5796f41..6e7f3870ae 100644 --- a/src/Mod/Arch/Arch_rc.py +++ b/src/Mod/Arch/Arch_rc.py @@ -2,8 +2,8 @@ # Resource object code # -# Created: Wed Apr 18 19:00:26 2012 -# by: The Resource Compiler for PyQt (Qt v4.7.4) +# Created: Sun May 13 20:45:11 2012 +# by: The Resource Compiler for PyQt (Qt v4.8.1) # # WARNING! All changes made in this file will be lost! @@ -6791,7 +6791,7 @@ qt_resource_data = "\ \x60\x24\x14\x71\x18\x20\xc8\x29\x21\x64\x0a\xba\x54\x4c\x69\x8a\ \x07\xa3\xfe\x50\x76\x18\x1a\x6f\x00\x69\x8d\xda\xda\x66\xb6\xba\ \xbe\xb8\xb2\x35\xc7\xf5\xc5\x7f\x01\x9a\x79\xce\xaf\ -\x00\x00\x12\x5a\ +\x00\x00\x12\x5c\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ \x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ @@ -6831,173 +6831,233 @@ qt_resource_data = "\ \x78\x22\x0a\x20\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x32\x39\x38\ \x35\x22\x0a\x20\x20\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\ \x2e\x31\x22\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\ -\x72\x39\x37\x36\x30\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\ -\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x41\x72\x63\x68\ -\x5f\x53\x69\x74\x65\x2e\x73\x76\x67\x22\x3e\x0a\x20\x20\x3c\x64\ -\x65\x66\x73\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\ -\x73\x32\x39\x38\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\ -\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ -\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x22\x3e\x0a\x20\x20\x20\x20\ -\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\ -\x6f\x72\x3a\x23\x66\x66\x62\x34\x30\x30\x3b\x73\x74\x6f\x70\x2d\ -\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\ -\x70\x33\x37\x39\x36\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ -\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\ -\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\ -\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\ -\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\ -\x37\x39\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\ -\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\ -\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ -\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\ -\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\ -\x38\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\ -\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x62\x34\ -\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\ -\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x36\x2d\x35\x22\ -\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\ -\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x65\x61\ -\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\ -\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x38\x2d\x38\x22\ -\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\ -\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x6c\ -\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x79\x32\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\ -\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x36\ -\x32\x2e\x36\x35\x32\x33\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x79\x31\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x31\x35\x2e\x31\x38\x34\ -\x39\x37\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\ -\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\ -\x61\x74\x72\x69\x78\x28\x31\x2e\x30\x32\x36\x35\x35\x36\x38\x2c\ -\x30\x2c\x30\x2c\x30\x2e\x39\x31\x34\x39\x30\x36\x32\x36\x2c\x2d\ -\x33\x2e\x32\x33\x36\x37\x30\x36\x2c\x2d\x31\x2e\x38\x30\x32\x37\ -\x30\x33\x32\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\ -\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\ -\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\ -\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\ -\x64\x69\x65\x6e\x74\x33\x38\x38\x36\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\ -\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\ -\x34\x2d\x38\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\ -\x77\x61\x79\x73\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\ -\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\ -\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\ -\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\x31\x22\x3e\x0a\x20\ -\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\ -\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x62\x34\x30\x30\x3b\x73\x74\ -\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\ -\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ -\x73\x74\x6f\x70\x33\x37\x39\x36\x2d\x32\x22\x20\x2f\x3e\x0a\x20\ -\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\ -\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\x73\x74\ -\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\ -\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ -\x73\x74\x6f\x70\x33\x37\x39\x38\x2d\x32\x22\x20\x2f\x3e\x0a\x20\ +\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x33\x2e\ +\x31\x20\x72\x39\x38\x38\x36\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\ +\x70\x6f\x64\x69\x3a\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x41\x72\ +\x63\x68\x5f\x53\x69\x74\x65\x5f\x54\x72\x65\x65\x2e\x73\x76\x67\ +\x22\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\x0a\x20\x20\x20\x20\x20\ +\x69\x64\x3d\x22\x64\x65\x66\x73\x32\x39\x38\x37\x22\x3e\x0a\x20\ +\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\ +\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\ +\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\ +\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x62\x34\x30\ +\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\ +\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\ +\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x36\x22\x20\x2f\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\ +\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\ +\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\ +\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\ +\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x38\x22\x20\x2f\x3e\x0a\x20\ \x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\ \x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\ \x47\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x79\x32\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\ -\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x36\x32\x2e\x36\x35\x32\ -\x33\x37\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x32\ -\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x78\x31\x3d\x22\x31\x35\x2e\x31\x38\x34\x39\x37\x31\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\ -\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\ -\x28\x31\x2e\x30\x32\x36\x35\x35\x36\x38\x2c\x30\x2c\x30\x2c\x30\ -\x2e\x39\x31\x34\x39\x30\x36\x32\x36\x2c\x2d\x33\x2e\x32\x33\x36\ -\x37\x30\x36\x2c\x2d\x31\x2e\x38\x30\x32\x37\x30\x33\x32\x29\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\ -\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\ -\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\ -\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\ -\x33\x38\x38\x36\x2d\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\ -\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\ -\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\x31\ -\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ -\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\ -\x73\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\ -\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\ -\x64\x76\x69\x65\x77\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\ -\x61\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\ -\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\ -\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\ -\x23\x36\x36\x36\x36\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\ -\x72\x64\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\ +\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\ +\x6e\x74\x33\x37\x39\x34\x2d\x38\x22\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x66\x66\x62\x34\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\ +\x33\x37\x39\x36\x2d\x35\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\ +\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\ +\x72\x3a\x23\x66\x66\x65\x61\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\ +\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\ +\x33\x37\x39\x38\x2d\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ +\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\ +\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\ +\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x78\x32\x3d\x22\x36\x32\x2e\x36\x35\x32\x33\x37\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x32\x33\x2e\x38\x34\ +\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\ +\x22\x31\x35\x2e\x31\x38\x34\x39\x37\x31\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\ +\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2e\x30\ +\x32\x36\x35\x35\x36\x38\x2c\x30\x2c\x30\x2c\x30\x2e\x39\x31\x34\ +\x39\x30\x36\x32\x36\x2c\x2d\x33\x2e\x32\x33\x36\x37\x30\x36\x2c\ +\x2d\x31\x2e\x38\x30\x32\x37\x30\x33\x32\x29\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\ +\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\ +\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x38\x36\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\ +\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\ +\x69\x65\x6e\x74\x33\x37\x39\x34\x2d\x38\x22\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\ +\x65\x63\x74\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x20\x2f\x3e\x0a\ +\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\ +\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\ +\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x37\x39\ +\x34\x2d\x31\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\ +\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\ +\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\ +\x62\x34\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\ +\x66\x66\x73\x65\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x36\x2d\ +\x32\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\ +\x70\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\ +\x3d\x22\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x66\x66\ +\x65\x61\x30\x30\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\ +\x66\x66\x73\x65\x74\x3d\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x73\x74\x6f\x70\x33\x37\x39\x38\x2d\ +\x32\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x6c\x69\x6e\x65\ +\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\ +\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\x22\x32\x33\x2e\x38\x34\ +\x38\x36\x38\x36\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\ +\x22\x36\x32\x2e\x36\x35\x32\x33\x37\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x79\x31\x3d\x22\x32\x33\x2e\x38\x34\x38\x36\x38\x36\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\x22\x31\x35\x2e\x31\ +\x38\x34\x39\x37\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\ +\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x6d\x61\x74\x72\x69\x78\x28\x31\x2e\x30\x32\x36\x35\x35\x36\ +\x38\x2c\x30\x2c\x30\x2c\x30\x2e\x39\x31\x34\x39\x30\x36\x32\x36\ +\x2c\x2d\x33\x2e\x32\x33\x36\x37\x30\x36\x2c\x2d\x31\x2e\x38\x30\ +\x32\x37\x30\x33\x32\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\ +\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\ +\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\x61\x72\x47\ +\x72\x61\x64\x69\x65\x6e\x74\x33\x38\x38\x36\x2d\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\ +\x3d\x22\x23\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\ +\x74\x33\x37\x39\x34\x2d\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\ +\x3d\x22\x61\x6c\x77\x61\x79\x73\x22\x20\x2f\x3e\x0a\x20\x20\x3c\ +\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\x64\x69\x70\x6f\ +\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0a\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\x20\x20\x20\x20\ +\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\ +\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ +\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\x36\x22\x0a\ +\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\x61\x63\x69\ +\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\x61\x63\x69\ +\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\x61\x64\x6f\ +\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x37\x2e\x37\x37\x38\x31\ +\x37\x34\x36\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x63\x78\x3d\x22\x32\x36\x2e\x34\x33\x31\x33\x36\x37\ \x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x70\x61\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\ -\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x70\x61\x67\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\ -\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\ -\x6d\x3d\x22\x32\x2e\x37\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ -\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x2d\x31\x32\x2e\x35\ -\x34\x31\x38\x31\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x79\x3d\x22\x32\x33\x2e\x38\x34\x36\x36\ -\x39\x34\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ -\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\ -\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x73\x68\ -\x6f\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\ -\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\ -\x6d\x65\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\ -\x69\x64\x2d\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\ -\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\ -\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\ -\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\ -\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\ -\x38\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ -\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\ +\x63\x79\x3d\x22\x33\x30\x2e\x38\x30\x36\x36\x30\x38\x22\x0a\x20\ +\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x75\x72\ +\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\x6c\x61\x79\x65\ +\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x73\x68\x6f\x77\x67\x72\x69\ +\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2d\ +\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x69\x64\x2d\x62\x62\ +\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x77\ +\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\ +\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\x35\x22\x0a\x20\x20\ \x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\ -\x6f\x77\x2d\x79\x3d\x22\x31\x39\x22\x0a\x20\x20\x20\x20\x20\x69\ -\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\ -\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\ -\x20\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\ -\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x39\x39\ -\x30\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\ -\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\ -\x6f\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ -\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\ -\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\ -\x6d\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\ -\x3a\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ -\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\ -\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\ -\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\ -\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\x63\ -\x3a\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\ -\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\ -\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\ -\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\ -\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\ -\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\x3d\ -\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x69\ -\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\ -\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\x20\x3c\ +\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\x3d\ +\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\x78\x69\x6d\x69\ +\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x6d\x65\ +\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\ +\x6d\x65\x74\x61\x64\x61\x74\x61\x32\x39\x39\x30\x22\x3e\x0a\x20\ +\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x20\ +\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\ +\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x66\ +\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\x2b\ +\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\x74\x79\x70\x65\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\ +\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\ +\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\ +\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\ +\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\ +\x3a\x74\x69\x74\x6c\x65\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\ +\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\ +\x74\x61\x64\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\ +\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\ +\x6c\x3d\x22\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\ +\x6f\x64\x65\x3d\x22\x6c\x61\x79\x65\x72\x22\x3e\x0a\x20\x20\x20\ +\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\ +\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\ +\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x62\x66\x62\x62\x62\x62\x3b\ +\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\ +\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\ +\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\ +\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x3b\x73\ +\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\ +\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\ +\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\ +\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\ +\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\ +\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\ +\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\ +\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\ +\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\ +\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\ +\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\ +\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\ +\x20\x35\x2e\x32\x39\x30\x30\x39\x32\x2c\x34\x31\x2e\x35\x33\x32\ +\x31\x34\x36\x20\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\ +\x35\x35\x35\x35\x36\x39\x20\x32\x39\x2e\x36\x30\x35\x38\x30\x33\ +\x2c\x35\x37\x2e\x30\x37\x34\x30\x38\x31\x20\x35\x2e\x35\x32\x32\ +\x37\x37\x38\x33\x2c\x34\x36\x2e\x39\x33\x38\x30\x33\x37\x20\x7a\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\ +\x68\x33\x39\x30\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\ +\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\ +\x2d\x63\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\ +\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\ +\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\ +\x66\x66\x66\x66\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\ +\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\ +\x6e\x7a\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\ +\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ +\x68\x3a\x33\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\ +\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ +\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\ +\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\ +\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\ +\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ +\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\ +\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\ +\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\ +\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\ +\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\ +\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\ +\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x64\x3d\x22\x4d\x20\x35\x39\x2e\x35\x30\x35\x39\x38\x35\x2c\ +\x31\x32\x2e\x33\x36\x32\x38\x36\x32\x20\x35\x39\x2e\x30\x34\x30\ +\x36\x31\x32\x2c\x33\x34\x2e\x34\x33\x36\x39\x31\x35\x20\x32\x39\ +\x2e\x36\x30\x35\x38\x30\x33\x2c\x35\x36\x2e\x39\x36\x31\x34\x35\ +\x39\x20\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\x35\x35\ +\x35\x35\x36\x39\x20\x34\x30\x2e\x37\x37\x34\x37\x34\x33\x2c\x31\ +\x33\x2e\x39\x33\x39\x35\x38\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x38\x36\x39\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\ +\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\ \x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\ -\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\ -\x3b\x66\x69\x6c\x6c\x3a\x23\x62\x66\x62\x62\x62\x62\x3b\x66\x69\ -\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\ -\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\x65\x72\x6f\x3b\x73\ +\x65\x3d\x22\x66\x69\x6c\x6c\x3a\x23\x39\x32\x62\x64\x38\x65\x3b\ +\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\ \x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\ \x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x3b\x73\x74\x72\ \x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\ @@ -7006,87 +7066,27 @@ qt_resource_data = "\ \x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\ \x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\ \x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\ -\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\ -\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\ -\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\ -\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\ -\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\ -\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\ -\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\ -\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x4d\x20\x35\ -\x2e\x32\x39\x30\x30\x39\x32\x2c\x34\x31\x2e\x35\x33\x32\x31\x34\ -\x36\x20\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\x35\x35\ -\x35\x35\x36\x39\x20\x32\x39\x2e\x36\x30\x35\x38\x30\x33\x2c\x35\ -\x37\x2e\x30\x37\x34\x30\x38\x31\x20\x35\x2e\x35\x32\x32\x37\x37\ -\x38\x33\x2c\x34\x36\x2e\x39\x33\x38\x30\x33\x37\x20\x7a\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\ -\x39\x30\x34\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\ -\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\ -\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\ -\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\ -\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\x66\x66\ -\x66\x66\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ -\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x6e\x6f\x6e\x7a\ -\x65\x72\x6f\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\ -\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\ -\x33\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ -\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ -\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\ -\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\ -\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\ -\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\ -\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\ -\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\ -\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\ -\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\ -\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\ -\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\ -\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\ -\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\ -\x3d\x22\x4d\x20\x35\x39\x2e\x35\x30\x35\x39\x38\x35\x2c\x31\x32\ -\x2e\x33\x36\x32\x38\x36\x32\x20\x35\x39\x2e\x30\x34\x30\x36\x31\ -\x32\x2c\x33\x34\x2e\x34\x33\x36\x39\x31\x35\x20\x32\x39\x2e\x36\ -\x30\x35\x38\x30\x33\x2c\x35\x36\x2e\x39\x36\x31\x34\x35\x39\x20\ -\x32\x39\x2e\x34\x38\x39\x34\x36\x2c\x35\x31\x2e\x35\x35\x35\x35\ -\x36\x39\x20\x34\x30\x2e\x37\x37\x34\x37\x34\x33\x2c\x31\x33\x2e\ -\x39\x33\x39\x35\x38\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\x20\x20\ -\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x38\x36\x39\x22\x0a\x20\x20\ -\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\ -\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\x75\x72\ -\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\ -\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\ -\x22\x66\x69\x6c\x6c\x3a\x23\x35\x35\x39\x61\x35\x36\x3b\x66\x69\ -\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\ -\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\ -\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x3b\x73\x74\x72\x6f\x6b\ -\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\ -\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\ -\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\ -\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x22\ -\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x33\x36\x2e\ -\x35\x30\x32\x38\x38\x37\x2c\x36\x2e\x34\x34\x36\x38\x36\x38\x20\ -\x2d\x31\x31\x2e\x30\x38\x39\x35\x37\x32\x2c\x38\x2e\x35\x36\x35\ -\x35\x37\x33\x20\x2d\x38\x2e\x39\x39\x39\x33\x39\x2c\x31\x36\x2e\ -\x30\x32\x39\x31\x34\x33\x20\x30\x2e\x31\x37\x34\x31\x38\x31\x2c\ -\x30\x2e\x30\x37\x35\x31\x34\x20\x4c\x20\x35\x2e\x32\x30\x38\x32\ -\x33\x31\x36\x2c\x34\x31\x2e\x37\x33\x36\x30\x32\x37\x20\x32\x39\ -\x2e\x35\x33\x35\x36\x31\x37\x2c\x35\x31\x2e\x36\x35\x34\x30\x35\ -\x39\x20\x34\x30\x2e\x34\x35\x31\x30\x30\x36\x2c\x34\x30\x2e\x36\ -\x38\x34\x31\x31\x35\x20\x34\x30\x2e\x38\x35\x37\x34\x33\x31\x2c\ -\x34\x30\x2e\x32\x38\x33\x33\x38\x36\x20\x34\x30\x2e\x36\x38\x33\ -\x32\x35\x2c\x34\x30\x2e\x32\x30\x38\x32\x34\x39\x20\x34\x39\x2e\ -\x34\x32\x31\x33\x36\x37\x2c\x32\x33\x2e\x35\x37\x38\x30\x31\x34\ -\x20\x35\x39\x2e\x35\x38\x31\x39\x36\x39\x2c\x31\x32\x2e\x34\x33\ -\x32\x37\x35\x31\x20\x33\x36\x2e\x35\x30\x32\x38\x38\x37\x2c\x36\ -\x2e\x34\x34\x36\x38\x36\x38\x20\x7a\x22\x0a\x20\x20\x20\x20\x20\ -\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x37\x36\x33\x22\x0a\ -\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ -\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\x74\ -\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\ -\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ +\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x33\ +\x36\x2e\x35\x30\x32\x38\x38\x37\x2c\x36\x2e\x34\x34\x36\x38\x36\ +\x38\x20\x2d\x31\x31\x2e\x30\x38\x39\x35\x37\x32\x2c\x38\x2e\x35\ +\x36\x35\x35\x37\x33\x20\x2d\x38\x2e\x39\x39\x39\x33\x39\x2c\x31\ +\x36\x2e\x30\x32\x39\x31\x34\x33\x20\x30\x2e\x31\x37\x34\x31\x38\ +\x31\x2c\x30\x2e\x30\x37\x35\x31\x34\x20\x4c\x20\x35\x2e\x32\x30\ +\x38\x32\x33\x31\x36\x2c\x34\x31\x2e\x37\x33\x36\x30\x32\x37\x20\ +\x32\x39\x2e\x35\x33\x35\x36\x31\x37\x2c\x35\x31\x2e\x36\x35\x34\ +\x30\x35\x39\x20\x34\x30\x2e\x34\x35\x31\x30\x30\x36\x2c\x34\x30\ +\x2e\x36\x38\x34\x31\x31\x35\x20\x34\x30\x2e\x38\x35\x37\x34\x33\ +\x31\x2c\x34\x30\x2e\x32\x38\x33\x33\x38\x36\x20\x34\x30\x2e\x36\ +\x38\x33\x32\x35\x2c\x34\x30\x2e\x32\x30\x38\x32\x34\x39\x20\x34\ +\x39\x2e\x34\x32\x31\x33\x36\x37\x2c\x32\x33\x2e\x35\x37\x38\x30\ +\x31\x34\x20\x35\x39\x2e\x35\x38\x31\x39\x36\x39\x2c\x31\x32\x2e\ +\x34\x33\x32\x37\x35\x31\x20\x33\x36\x2e\x35\x30\x32\x38\x38\x37\ +\x2c\x36\x2e\x34\x34\x36\x38\x36\x38\x20\x7a\x22\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x61\x74\x68\x33\x37\x36\x33\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\ +\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\ +\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ \x00\x00\x0e\x6b\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ @@ -8358,6 +8358,133 @@ qt_resource_data = "\ \x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x6f\x64\x65\x74\x79\x70\ \x65\x73\x3d\x22\x63\x63\x63\x63\x63\x22\x20\x2f\x3e\x0a\x20\x20\ \x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ +\x00\x00\x07\xc4\ +\x00\ +\x00\x37\x1e\x78\x9c\xed\x5b\x6d\x8f\x9b\x48\x12\xfe\x3e\xbf\x82\ +\x65\xbe\x24\x3a\x83\xfb\x9d\x6e\x32\x9e\xd5\xdd\x46\xbb\x5a\xe9\ +\x4e\x27\x5d\x12\xdd\xc7\x88\x81\xb6\xcd\x0e\x06\x0b\xf0\xd8\xce\ +\xaf\xdf\x6a\xcc\x9b\x6d\x3c\x2f\xd9\x91\x6e\x77\x38\x4b\xc9\x40\ +\x55\x75\x77\xd5\xd3\x55\xd5\xd5\xd0\xdc\xfc\xb8\x5b\x25\xd6\x83\ +\xce\x8b\x38\x4b\x67\x36\x76\x91\x6d\xe9\x34\xcc\xa2\x38\x5d\xcc\ +\xec\x2f\x9f\x7f\x76\xa4\x6d\x15\x65\x90\x46\x41\x92\xa5\x7a\x66\ +\xa7\x99\xfd\xe3\xed\xd5\xcd\x0f\x8e\x63\xfd\x94\xeb\xa0\xd4\x91\ +\xb5\x8d\xcb\xa5\xf5\x6b\x7a\x5f\x84\xc1\x5a\x5b\xef\x96\x65\xb9\ +\xf6\xa7\xd3\xed\x76\xeb\xc6\x35\xd1\xcd\xf2\xc5\xf4\xbd\xe5\x38\ +\xb7\x57\x57\x37\xc5\xc3\xe2\xca\xb2\x2c\x18\x37\x2d\xfc\x28\x9c\ +\xd9\x75\x83\xf5\x26\x4f\x2a\xc1\x28\x9c\xea\x44\xaf\x74\x5a\x16\ +\x53\xec\xe2\xa9\xdd\x89\x87\x9d\x78\x68\x46\x8f\x1f\x74\x98\xad\ +\x56\x59\x5a\x54\x2d\xd3\xe2\xba\x27\x9c\x47\xf3\x56\xda\x68\xb3\ +\xa5\x95\x10\x56\x4a\x4d\x11\x99\x12\xe2\x80\x84\x53\xec\xd3\x32\ +\xd8\x39\xc7\x4d\x41\xc7\xa1\xa6\x04\x21\x34\x05\x5e\x27\xf9\x3c\ +\x29\x7f\x97\x00\x14\x17\x95\xa9\xb8\xfd\xd1\x01\xfe\x35\xfc\x6b\ +\x1b\x34\x04\xb7\xc8\x36\x79\xa8\xe7\xd0\x52\xbb\xa9\x2e\xa7\x1f\ +\x3f\x7f\x6c\x99\x0e\x72\xa3\x32\xea\x75\xd3\xa0\x7f\x34\xee\xd1\ +\x94\xa4\xc1\x4a\x17\xeb\x20\xd4\xc5\xb4\xa1\x57\xed\xb7\x71\x54\ +\x2e\x67\xb6\x60\xeb\x5d\x75\xbf\xd4\xf1\x62\x59\xf6\x08\x71\x34\ +\xb3\xc1\x42\x22\xb1\xa8\xee\x7b\x0e\x84\x0f\x02\x75\x77\x7e\xcb\ +\x41\x2e\x93\x2e\x75\xb1\x95\x2b\x29\x0f\xad\x1a\xcd\xfd\x28\x0b\ +\x8d\x2a\x33\xfb\xef\x79\xb8\xfc\xfa\x8f\x4d\x9c\x18\xff\x73\x0d\ +\x86\xb7\x20\x78\x13\xe9\x79\x61\x1a\x1c\x06\x36\x77\x30\xb2\xac\ +\x78\xc0\x05\xf4\x74\x90\xff\x92\x07\x51\x0c\x3e\x73\x90\x3b\x48\ +\x1e\x73\xa8\x90\xb8\x6e\x03\xad\x8a\x32\x5b\x37\xb2\xb5\x41\x40\ +\xa1\x42\x79\x76\x47\xce\xe6\xf3\x42\x83\xe1\xa8\x47\x2b\xca\x7d\ +\xa2\x0f\xd2\x4e\x98\x25\x59\xee\x5f\xcf\xe7\x73\x8c\xd1\x87\x8a\ +\x94\x01\x9e\x71\xb9\xf7\xf1\x07\xdb\x9a\x5e\x18\x6d\xa0\x8b\x70\ +\xee\x21\x24\xcf\xba\x38\x57\x05\xdb\x43\x5a\x4b\xde\x8e\x76\x33\ +\x3d\x36\xbb\xa6\xb6\x33\xb2\x86\x19\x59\xeb\xd0\xc4\x4e\xd3\x53\ +\x3b\x11\xe5\xde\xb8\xcb\xb1\x28\x8d\xda\x11\xbb\x59\x5d\x7f\xdd\ +\x01\x2a\x96\x6f\x51\x02\xff\xe1\x41\x89\xfd\x41\x02\x43\x38\xc0\ +\x1f\x34\x28\xf3\xcd\x38\xd5\x23\xdd\xd4\x1a\x38\x59\x1e\x2f\x62\ +\xf0\xa2\x4a\x8e\x60\x97\x56\xbf\xe3\x36\x00\x46\xcf\x36\x22\x09\ +\xeb\x30\x79\xcc\xfa\x93\x86\x54\x10\xf2\xb4\x22\xc8\xe5\xc6\xa8\ +\x5a\x91\x53\x55\x8e\x2d\xc4\x95\x24\xff\x43\x40\xd5\x70\x9f\x76\ +\xf3\xd4\xcc\x7d\x2f\x00\x8e\x1a\x39\x04\x9c\x8e\x1c\x00\x8f\x8f\ +\x1c\x80\xde\x42\x30\x4a\x00\x3c\x32\xa0\xc3\xa8\x00\x60\x23\x5f\ +\x07\x3c\xc1\x46\x0e\x80\x1c\x79\x12\x94\x48\x8c\x1e\x00\x67\xe4\ +\x95\x80\xa4\x23\x0f\x02\x81\x47\x9e\x06\x01\x00\x47\x8e\x1c\x02\ +\x36\xf2\x2c\x00\x00\x8c\x3d\x11\x0a\x6f\xe4\xf5\x20\x00\xe0\x8c\ +\x7c\x2d\xf0\xd0\x33\x1e\x52\xbd\x71\x00\xc6\xbe\x16\x78\xec\x0d\ +\x16\xc5\xeb\xa0\x2c\x75\x9e\x36\xed\xea\xdb\xcf\x79\x90\x16\xf3\ +\x2c\x5f\xcd\xec\x55\x50\xe6\xf1\xee\x1d\x72\x05\x6c\x0b\xa9\x47\ +\xe4\xc4\x41\xae\xc4\x92\x28\xcc\xf9\x84\xb8\x8c\x7b\x92\x62\x36\ +\xc1\xae\x94\x8c\x71\xce\x26\x0e\x11\x40\x45\x02\x89\x09\x96\x2e\ +\x51\x4c\x31\xef\xfd\xf1\xe3\xda\xc3\x28\x9c\xd0\x4e\xe3\xea\x65\ +\x88\xbf\xcc\xf5\x7c\x66\x5f\x7f\x82\x31\xd7\x05\xfe\x8a\x9d\x81\ +\x12\x2c\xcc\x92\x04\xa6\x64\x66\x07\xc9\x36\xd8\x17\xdf\x35\x99\ +\x9c\x90\x37\x58\xdc\x9d\x4c\x66\x2b\x58\x94\x59\x78\x6f\x10\xa8\ +\x70\xd5\x85\x85\xfd\xe3\xe7\xe7\x43\x78\x3f\xe6\x0a\xc2\x03\x47\ +\x60\x74\xe2\x60\x17\x21\xc8\x0d\xb2\xf2\x04\x22\xb0\xf4\x24\x5c\ +\x51\x8c\x19\x67\x72\x42\x5d\xe6\x09\xa4\xa4\x07\x57\x9c\x32\x45\ +\x68\xe7\x07\xcd\xbb\xa5\x4e\x91\xfa\xed\x13\x39\xd5\xe0\x4b\x1a\ +\x97\xc5\xcc\xde\x14\x3a\xff\x64\x5e\x5a\xfd\x3b\xfd\x52\xe8\xa7\ +\xdd\xa2\x7d\x07\x93\x03\xb5\x91\x3e\x98\x6b\x28\x8c\x49\xda\xb3\ +\xb6\x53\x88\xf4\x68\xb5\x4a\xfd\x77\x2f\x30\x8f\x10\x00\xbc\x47\ +\xd9\x0d\xbe\x27\x9a\xc7\x49\xe2\xdf\x25\x41\x78\xff\xa1\x28\xf3\ +\xec\x5e\xfb\x69\x96\xea\xde\xdb\x9a\xda\xba\xef\xf3\xdd\xb7\xf8\ +\x9c\xfe\x05\xa9\xe8\xb9\xfe\xa7\x5c\x20\x51\x89\x27\xd2\x55\x42\ +\x11\x89\xd8\xc5\x44\xd4\xf3\x85\x0b\xa9\x68\x20\xfb\xbf\x56\x2a\ +\x7a\x8b\x25\xf6\x2b\x24\x23\x31\xaa\x64\x84\xfe\x34\xc9\xe8\x25\ +\x91\xc8\x31\xa5\x92\x54\xe0\x0b\x8a\x89\x52\x06\x7c\x0c\xc5\x02\ +\xa2\xe6\x8a\x41\xa1\xe0\xc1\xdc\x30\xe5\x7a\x82\x70\x61\xd8\x8a\ +\x33\x21\xd1\xa5\x9a\x40\x89\xe1\x40\xec\xc7\xea\x40\xb8\xbc\x4e\ +\x28\xca\x37\x58\xe3\xbe\x7e\x5e\x35\x15\x1e\xa5\x02\x44\x27\x18\ +\x8a\x41\xe9\x61\x75\xb9\xc2\xeb\x4d\xd6\xa5\x1a\xef\x45\xf3\xf9\ +\x1a\x45\x4e\x6f\xc0\x31\x64\x16\xd6\xcb\xa4\x7f\x9d\xdc\xc2\x00\ +\x7b\x26\xa5\x30\x1b\x0e\x41\x60\xb7\x21\x99\x82\x6d\x06\xe7\x90\ +\x5c\x84\x07\x57\x8c\x62\xaa\xc4\x84\x78\xae\x62\x92\x99\x3d\x08\ +\x75\x29\x12\x8c\x8b\x61\x67\xa4\x14\x3d\xe5\x8a\x03\x65\xd5\xab\ +\x24\x16\x4a\xfe\xbf\xc2\x77\xc8\x0c\xe1\x3d\x86\x38\xa4\x7f\x9a\ +\x28\x7c\x91\xef\x8a\x71\x3f\xfb\xe2\x54\xbe\xc1\xe0\x7d\x09\x00\ +\x0c\xbf\x41\x0f\xb8\x70\x7c\xf4\x52\x7c\x0f\x2e\x1c\x03\x07\x4d\ +\xfb\x18\x9e\xb1\xbb\xa3\x45\x3b\x3c\xb3\xa9\xe7\x4a\xe5\xf1\x6e\ +\x6d\xde\x03\x91\x41\x8e\x83\xb4\xa6\xba\x42\x74\x47\x80\x0a\xd5\ +\x35\xe2\x1e\xee\xb2\xc5\xde\x50\x91\x8b\x85\xe4\xaa\xdb\xba\x2e\ +\xea\xb1\x86\x93\xd8\xff\xd2\x76\xc5\xcf\x6d\x87\x15\xde\x3b\x36\ +\xde\x9c\x16\x66\x5e\xef\x85\x8b\x31\x5e\x10\x17\x31\xe9\x79\xea\ +\xc8\x78\x81\x5c\xa8\x2e\x31\xf6\x9e\x69\xfc\xa9\xd4\xd0\x4a\x43\ +\x18\x21\x1e\xc2\xea\x50\x72\x30\x8e\x3d\x45\x26\xd5\x2e\x47\x50\ +\x04\xa5\x06\x48\x10\x0f\x4a\x0c\xc2\x27\xdc\x15\x88\x29\xc4\xe5\ +\x84\x11\x17\x88\x98\xca\xf7\x35\xc0\x37\x53\x73\x54\xb9\xba\x6a\ +\xbd\xd1\x9c\x73\x8e\x1e\x62\xbd\xbd\x6a\x11\xba\x0b\x5a\xad\xd6\ +\xc1\x42\x57\x07\x82\x01\xd7\x79\xf5\xab\x19\x77\x59\x1e\xe9\xbc\ +\x61\x89\xea\x77\xc4\xaa\xcf\x0c\x1f\x8e\xf0\x5f\x9d\x44\x28\xf4\ +\xda\xf2\xd1\x30\xbf\x58\x06\x51\xb6\xed\x96\xa1\x96\xf9\x2d\xcb\ +\x00\x19\x0a\xd5\xbd\x02\x7f\x3c\x63\x87\x10\x7e\xb4\x2a\xc1\x30\ +\xf2\xce\x98\x46\x1f\xe6\xc2\xae\x40\x12\x7c\xc6\xdc\xe4\x39\xc0\ +\xef\x24\xc1\x5e\x83\x51\xd5\x9f\x46\xa8\x58\x66\xdb\x45\x6e\xc0\ +\x29\xf3\x8d\x3e\x6d\x19\x65\xe1\xc6\x7c\x1e\xe0\x6c\x0e\x13\x5c\ +\x1f\x4a\xef\x49\x98\xb6\xce\xdd\x5d\xb6\x1b\xee\xa0\x48\x83\xf5\ +\x23\x6c\xc3\x71\x60\x9d\x5c\x16\x8f\xf0\xd3\x2c\xd2\x17\xf8\x6d\ +\xf7\x8e\x8e\x16\xda\x59\xc5\xd1\x3a\x8b\xd3\xf2\x49\xe9\x27\x04\ +\xb3\xbb\xdf\x20\x18\x1f\x53\xac\x96\x78\x44\xb5\x6d\x9c\xc2\x34\ +\x3b\x4d\x81\x41\xe4\x99\x33\xd4\x12\x4d\x59\xe2\x71\x79\x41\xa2\ +\x57\x7f\x9c\xb2\xcc\xb4\xab\x0b\xbc\x55\xb0\x8b\x57\xf1\x37\x1d\ +\x99\xe6\x75\x9c\xac\x74\x19\x44\x41\x19\x74\x31\xd1\x50\x88\x71\ +\x9c\x3a\x59\xe5\xd1\xdc\xff\xcf\xc7\x9f\xdb\x02\x2b\x0c\xfd\xff\ +\x66\xf9\x7d\x57\x02\x19\x81\xe0\x2e\xdb\x80\xda\x6d\x19\x66\xbe\ +\x1e\x08\x7d\x13\xde\x41\x79\x1b\xaf\xc0\xd3\xcd\xa7\x19\x7f\xdb\ +\xad\x12\x88\xce\x96\x71\x24\x6c\x16\x8c\xae\xd3\x43\xb7\xb9\x3e\ +\x7c\x7a\x31\xf8\xb5\x4a\x14\xae\x62\xd3\x68\xfa\xa9\x84\xea\xeb\ +\x57\x33\x48\xef\xec\x7f\xdd\x69\x5c\x26\xfa\xb6\x1a\xf3\x70\xd9\ +\x58\x31\xad\xcd\x68\xea\xb3\x9e\x95\x37\xd3\x06\x86\xea\x6e\xd1\ +\xc1\x73\x14\x2c\x2d\xc2\x49\x70\xa7\x93\x99\xfd\x4f\xc3\xb4\xce\ +\xb8\x8b\x3c\xdb\xac\x57\xe0\x1a\x75\x73\xbb\xab\xde\x97\xed\xa2\ +\xd9\x2b\x22\xaf\x55\x20\x38\x62\x1f\xcc\x4d\xef\x93\x84\xba\xaa\ +\xbc\xa6\x1a\x9c\x47\xd4\xb7\x07\x87\xf2\x21\xf7\x40\xa8\x23\xc8\ +\x87\x0d\xdd\x64\x7f\x18\xdd\xbf\xdb\x94\x65\x9f\xf6\x1b\xf8\xb9\ +\x0f\x0a\xa5\x51\x43\x05\x08\x75\x9e\x80\x6b\x94\x3e\x6b\x68\xa7\ +\xa3\x3a\x51\x00\x79\x2a\xcf\x83\xfd\xa1\xaa\x6d\xd4\x06\x44\xfe\ +\x65\x11\x48\xcf\x54\x21\x4f\x4c\x18\x77\xb9\x14\x1e\x22\x16\xa4\ +\x64\x89\x14\x57\xb0\x4f\xa0\x2e\x26\x9c\x23\x6c\x31\x05\x9b\x43\ +\xe5\x61\x6f\xa2\x5c\x05\x49\x4d\x51\x8b\x40\x3e\xc7\xb0\xad\x24\ +\x13\x02\xe9\x9c\xc3\x6a\x44\xad\x6f\xa7\x5b\xc7\x25\x51\x68\xa0\ +\x02\x09\xb3\x14\x4c\x2c\xb3\xdc\x81\x84\xf6\x10\x94\x9b\x5c\xf7\ +\x0b\xf3\x2e\xf1\x03\xf2\xc6\x49\x20\x30\x43\xf3\x3b\xda\x3e\x0d\ +\x4e\x00\x78\xd8\xbb\xb3\xd5\x55\xf1\xf7\x7f\x99\x19\x19\x40\xda\ +\x2c\xe1\x04\x33\x4a\x27\x44\x98\xe7\x7f\xb0\xa4\x58\x94\x03\xcd\ +\x83\xd5\x7e\xc2\x61\xba\xcc\x4a\xfe\xdc\x09\x91\x6a\xf0\x59\xfc\ +\x1f\x9a\x90\x9b\xe9\xe2\xf6\xea\xc6\x24\x89\xdb\xab\xdf\x01\x64\ +\xd9\x31\x4e\ \x00\x00\x13\xbe\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ @@ -9360,118 +9487,118 @@ qt_resource_data = "\ \x36\x14\x14\xa2\xad\xa3\xa0\xac\xa6\x04\x91\x00\x07\x92\x33\x46\ \x6d\xa5\x0d\x85\xb6\x3c\x63\xeb\xf9\x5a\xeb\xd5\x95\xd6\xd4\x5b\ \xcd\x6f\xa6\xf6\x72\x72\x7e\xf3\x07\x32\x2c\xc5\xda\ -\x00\x00\x06\xd7\ +\x00\x00\x06\xd6\ \x00\ -\x00\x27\xd0\x78\x9c\xed\x59\xdd\x6f\xe3\xb8\x11\x7f\xcf\x5f\xa1\ -\x7a\x5f\xee\x50\x93\xe2\xa7\x48\x2a\xb6\xef\xa1\x8b\x03\x0e\x68\ -\x5f\xda\x2b\xfa\x58\xc8\x12\x6d\xeb\x22\x4b\x86\x24\xc7\xc9\xfe\ -\xf5\x1d\xca\x92\x2c\x7f\xc4\xc9\x6d\x76\x7b\xc0\x39\x5a\x38\x12\ -\x39\x33\xe4\x70\x7e\x33\xe4\x0c\x77\xf2\xd3\xd3\x3a\xf3\x1e\x6d\ -\x59\xa5\x45\x3e\x1d\x51\x4c\x46\x9e\xcd\xe3\x22\x49\xf3\xe5\x74\ -\xf4\xef\x5f\x7f\x46\x7a\xe4\x55\x75\x94\x27\x51\x56\xe4\x76\x3a\ -\xca\x8b\xd1\x4f\xb3\xbb\xc9\x5f\x10\xf2\xfe\x56\xda\xa8\xb6\x89\ -\xb7\x4b\xeb\x95\xf7\x4b\xfe\x50\xc5\xd1\xc6\x7a\x3f\xac\xea\x7a\ -\x13\xfa\xfe\x6e\xb7\xc3\x69\xdb\x89\x8b\x72\xe9\xff\xe8\x21\x34\ -\xbb\xbb\x9b\x54\x8f\xcb\x3b\xcf\xf3\x60\xde\xbc\x0a\x93\x78\x3a\ -\x6a\x05\x36\xdb\x32\x6b\x18\x93\xd8\xb7\x99\x5d\xdb\xbc\xae\x7c\ -\x8a\xa9\x3f\x3a\xb0\xc7\x07\xf6\xd8\xcd\x9e\x3e\xda\xb8\x58\xaf\ -\x8b\xbc\x6a\x24\xf3\xea\xd3\x80\xb9\x4c\x16\x3d\xb7\xd3\x66\xc7\ -\x1b\x26\x6a\x8c\xf1\x09\xf3\x19\x43\xc0\x81\xaa\xe7\xbc\x8e\x9e\ -\xd0\xb1\x28\xe8\x78\x49\x94\x11\x42\x7c\xa0\x1d\x38\xdf\xc6\x15\ -\x56\x60\xd0\x0d\xfc\x7a\xf6\xae\x03\x57\xc5\xb6\x8c\xed\x02\xe4\ -\x2c\xce\x6d\xed\x7f\xfe\xf5\x73\x4f\x44\x04\x27\x75\x32\x18\xa6\ -\xb3\xe7\xd1\xac\x47\x46\xce\xa3\xb5\xad\x36\x51\x6c\x2b\xbf\xeb\ -\x6f\xe4\x77\x69\x52\xaf\xa6\xa3\x40\x6c\x9e\x9a\xf6\xca\xa6\xcb\ -\x55\x3d\xe8\x48\x93\xe9\x08\x74\x66\x9a\x06\x4d\x7b\xe0\x12\x74\ -\xcf\xd0\x0e\x17\xf6\x14\x82\x85\xc6\xd4\x2b\x8d\x0a\x48\xc3\xd2\ -\xe9\x1d\x26\x45\xec\x14\x99\x8e\x36\xa5\x5d\xd8\x12\x1c\xca\x56\ -\x28\x2a\xe3\x15\x76\x66\x99\x01\xef\x24\xb1\x8b\xca\xc9\xec\x67\ -\x76\x2d\x98\x5a\x37\x34\xa0\xf6\x93\x6d\x60\xb2\x8d\x8d\x1d\xd0\ -\x7b\xee\xc1\x2c\xf5\xb3\xb3\xc4\x31\x2b\xdf\x9b\xcb\x3b\x52\x78\ -\xf3\xdf\x27\xd0\xd6\x0b\x3d\xce\xe0\x0f\xbd\xc8\xf1\xbc\xe7\xa0\ -\x80\x1d\xbc\xc8\x45\x9e\x2f\xce\x5e\x57\x86\x69\x35\x40\x45\x99\ -\x2e\x53\x30\x50\xc3\xc7\x28\xe6\xcd\x73\x2c\x03\x8b\x1e\xac\x8d\ -\x69\x26\x46\x9e\xff\x86\xd5\x9f\x08\xf2\x80\xb1\xd7\x15\x21\x58\ -\xba\x45\xb5\x8a\x9c\xaa\x72\xbc\x42\xda\x70\xca\x77\x19\xaa\x35\ -\xf7\xe9\x30\xaf\x21\xf7\xb5\x06\x40\xe6\xc6\x4d\x20\xf9\x8d\x1b\ -\x40\xc9\x1b\x37\x80\x51\xb7\x6d\x00\xc5\x2e\xe8\x70\x53\x06\x10\ -\x37\x7e\x0e\xa8\x40\xdc\xb8\x01\xf4\x8d\x6f\x82\x9a\x04\x37\x6f\ -\x00\x74\xe3\x99\x80\xe6\x7f\xb6\x20\x98\xf8\xae\x38\x6a\xbe\x7a\ -\x01\x57\x5c\x25\x8f\xa9\xdd\x1d\x2a\xa8\x79\x54\xd9\x76\xe4\x4d\ -\xb4\x84\xaa\x38\x2b\xca\xe9\xe8\xd3\xa2\x79\x5a\xc2\xbc\x28\x13\ -\x5b\x76\xa4\xa0\x79\x8e\x48\x05\x54\x8e\x69\xfd\xbc\xbf\x07\xb8\ -\x3b\x31\x22\x8c\xda\xd3\xc9\x65\x7a\xb5\x8a\x92\x62\x37\x1d\xb1\ -\x53\xe2\x97\xa2\x58\x3b\x29\x26\x38\x09\x94\x09\x4e\xe9\x31\x98\ -\x08\x71\x26\x30\x64\xf3\xca\x9c\x51\x61\x46\xc4\x24\xc7\x84\x52\ -\x2a\xcf\xa8\xdb\x12\x2a\xcc\x1a\x65\xd1\xb3\x85\x75\x35\xaf\xce\ -\xc8\xd5\xaa\xd8\x2d\x4b\x67\x9f\xba\xdc\xda\x53\x49\x28\x53\xb7\ -\xee\x9a\x01\x6d\xf3\xb4\x86\x52\xbe\x2d\x85\x07\x1c\x4e\x16\xcd\ -\xe7\xc5\xd3\xe5\x01\xaa\x3c\xda\x5c\x21\x3b\x0a\xda\x44\xf5\xaa\ -\xba\x42\xcf\x8b\xc4\xbe\x40\xef\x87\x47\x36\x59\x5a\xb4\x4e\x93\ -\x4d\x91\xe6\xf5\xab\xdc\xaf\x30\x16\xf3\xdf\x20\x5a\xae\x29\xd6\ -\x72\x5c\x51\x6d\x97\xe6\x80\x34\x6a\xaf\x15\x28\xd3\x67\xfe\xd0\ -\x72\x74\x17\x0d\x4a\xea\x17\x38\x5c\x74\xbc\x40\x72\x9e\x78\xe6\ -\x0d\x2d\x6d\x1d\x3d\xa5\xeb\xf4\x8b\x4d\x9c\x78\x1b\x2a\x6b\x5b\ -\x47\x49\x54\x47\x87\xb0\xe8\x7a\xa0\xc0\xa6\xdd\xe5\x42\x99\x2c\ -\xc2\x7f\x7e\xfe\x79\xd6\xc6\xe1\x24\x8e\xc3\xff\x14\xe5\x43\x17\ -\x96\x9e\xe7\x18\xa2\x79\xb1\x05\xb5\x47\xb3\xbe\x7b\x92\xc4\xe1\ -\xa2\x28\xd7\x51\x3d\x4b\xd7\xe0\xec\xee\x8a\xe7\xaf\x4f\xeb\x0c\ -\x02\xb4\x27\x1c\x31\xbb\xb0\x3e\x0c\xba\x1f\xb6\xb4\xfb\x0b\x9f\ -\x8b\xb7\x5e\x49\xbc\x4e\x9d\x90\xff\xaf\x3a\xcd\xb2\x5f\xdc\x24\ -\xfd\x2e\xd8\x0f\x9a\xd6\x99\x9d\x35\x73\xee\x3f\xbb\x55\xf8\xed\ -\x32\xda\x45\xfa\x83\x55\x4e\xfc\xce\x0c\x4d\x6b\x79\x30\xcf\x51\ -\xb0\xf4\x16\xce\xa2\xb9\xcd\xa6\xa3\xbf\x3b\xa2\x77\x46\x5d\x96\ -\xc5\x76\xb3\x06\xd7\x68\xc5\x7b\xb3\x82\xcb\xf4\x5b\x5b\xfd\x9c\ -\x01\xbd\xd9\x6a\xc2\x4f\xa4\x79\xee\x17\xb0\xa8\xf0\x53\x14\x09\ -\xd1\x36\x50\xbb\x9f\x84\x74\xdf\x2c\xb7\x99\x0d\xed\xa3\x05\xbf\ -\x4b\xee\xab\xba\x2c\x1e\x6c\x2f\xbc\x6f\xee\x1d\x2e\xe4\x58\x88\ -\x40\x30\x46\x68\xd7\x9f\xa5\xb9\x05\xed\xc2\xf9\xb6\xae\x87\x7d\ -\xbf\x41\x1c\x84\xa0\x70\xde\x0d\x08\xc1\x51\xdb\x32\x03\xd7\xa9\ -\x43\xd1\xf5\x1d\xf4\x68\x3b\x92\x08\xb6\xb2\xb2\x8c\x9e\xc3\xbc\ -\xc8\xed\xb0\xb7\x58\x2c\x2a\x5b\x87\xe4\x7e\x1d\x95\x0f\xb6\xdc\ -\xd3\x1f\xd3\x2a\x9d\xa7\x99\x1b\xa2\xf9\xcc\xec\x7d\x92\x56\x1b\ -\x30\x4f\x98\xe6\x4e\x8d\xfb\xe2\xd1\x96\x8b\xac\xd8\xf5\x74\x9b\ -\x47\xf0\x42\xf3\x28\x7e\x58\x36\xfa\x85\x51\x0c\xbb\xd1\x36\x8b\ -\x6a\x7b\x38\x44\x00\x22\x67\x56\xa6\x05\x41\x1c\x09\x44\x90\xee\ -\x89\x5d\xec\x49\x6c\x78\xc0\xd9\xe1\x0e\xa4\x0b\x39\xca\xb0\xd4\ -\x52\x90\x83\xc8\x93\xbb\x93\xc2\xc6\x28\x33\x48\x95\x20\xc8\xa4\ -\xc1\x01\xc4\xf0\xa1\x82\xa8\xcb\x28\xaf\x9c\x4f\x43\x04\x45\x75\ -\x99\x3e\xfd\x40\xb0\x92\x4a\x51\x21\xc7\x88\xe0\x40\x32\xa9\x03\ -\x6a\xc6\x64\x4c\xe1\x47\x7e\x3c\x1c\xd6\x6f\xf4\x82\xc5\x42\x2d\ -\x58\xf4\x5e\x2f\x20\x46\xc3\xca\x95\xfe\xf6\x88\x7f\x47\x74\xaf\ -\xb9\xec\xd0\xc3\x2e\x7a\xc1\x29\xfa\x70\x64\xf2\x80\x99\x40\x5d\ -\x42\x5f\x68\x26\x8d\x18\xa2\xcf\x30\x87\x23\x94\x99\x23\xf4\x99\ -\xc6\x5a\x6b\x00\xf7\x2a\xfc\x86\x2b\x2e\x29\x01\xcc\x31\x17\x9a\ -\x7f\xc0\xff\x47\xc0\x3f\xb8\xe9\xfc\x4a\x07\xd0\xd8\x04\x80\xe3\ -\x99\x03\x04\x01\xf8\xc0\x37\x70\x00\x97\x55\xbc\xc9\x01\x8c\x91\ -\xf2\x9d\x0e\xf0\x1e\xdc\xff\x40\x84\xaf\x1f\x2c\x3d\x06\x00\xfb\ -\x3f\x3c\x2a\x20\x67\xa6\x92\xa9\x31\x35\x98\x19\x41\x89\xf6\xb8\ -\xc2\x44\x69\xaa\xc7\x4c\x61\xf7\x66\xc6\x63\x12\x13\xc2\x8c\xe1\ -\x63\xae\x31\xd5\x34\x90\xca\x63\x98\x06\x01\xe7\x06\xf8\x60\x7b\ -\x37\x1c\x4e\x89\x8b\xc3\x7d\x79\xe9\xb8\x91\xee\x77\x5e\xad\xb8\ -\xac\xd0\x65\x29\x90\x19\xc6\xee\xf9\xc0\xfe\x3b\x61\xcf\x01\x22\ -\x40\x4b\x89\x31\x04\xa8\x90\x42\x31\xe5\x05\x0c\x93\x80\x68\x00\ -\x90\x07\xd8\x08\x26\x84\xf6\x84\xc1\x46\xcb\x40\x8c\x85\x82\xc8\ -\x84\x02\x2a\xf0\xc0\x33\xa8\xd0\x46\x2b\xe7\x0f\x90\x03\x48\x29\ -\x2f\x0e\x77\x0d\xfb\x77\x22\xbf\xc7\xfa\x08\xbb\x37\x40\xf9\x62\ -\x0e\xd7\x20\x7a\x0e\x65\xf7\x05\x39\x09\xe1\x44\x72\x97\x5b\xee\ -\x1f\x79\xcd\x17\x8e\xa1\x18\x9a\x7d\xed\xec\xe4\xb6\x39\xad\xc7\ -\x02\xca\x60\x30\x23\xe7\x1e\xe5\x98\x13\x45\x8d\x18\x23\x0a\xd9\ -\x0f\xa5\x46\x79\x02\x83\x81\xe1\xdf\x18\x09\x4c\xb8\x94\xc6\x78\ -\x88\x81\x1e\x5c\x1b\xc3\xc6\x48\xe1\x40\x18\xc2\xb8\x87\x34\x86\ -\xca\x16\x1a\x63\x00\x25\x30\x01\x40\x41\x9b\x6c\x4a\x48\x3d\x0e\ -\x5c\x90\xd2\x40\x9c\x20\xe1\xec\xc9\xb5\x30\xaf\x63\x10\x7f\x9c\ -\xbd\xff\xaf\xb3\x97\xbf\xf3\xec\xa5\x6e\xbb\xd6\x4a\x0f\x8f\x5e\ -\x70\x2c\x2d\x14\x1d\xfc\x07\xde\x77\xcf\xbd\xbe\x5f\x01\xf6\x67\ -\xc7\x1f\x89\x53\x0f\xf8\x9d\xc5\x57\x00\xec\x81\x36\xf2\x28\xfb\ -\x32\x00\xaa\x61\x8a\x5c\xcf\xbe\xbe\x69\xf5\xf5\xe1\x02\x5f\xef\ -\x02\xe8\xac\x06\xfb\x9d\x4e\x20\x21\x31\x13\xc2\x48\x3a\x74\x02\ -\x38\xd7\xe1\x38\x10\x83\xc2\xec\xeb\x9d\xe0\x23\x0d\xfb\xa6\x69\ -\x18\x64\x4b\x0a\xe0\x62\x63\xc8\x0b\x04\xd5\x8a\x79\x92\x62\x67\ -\x7b\xc5\xc6\x54\x63\x48\xbb\xa5\xe1\x7d\xd6\x20\x9b\xec\x0a\x52\ -\x6b\x46\x3d\x1a\xe0\x40\x09\xce\x99\xcb\xb6\x21\xd9\x56\x17\xc6\ -\x7a\x39\x03\x7b\x73\xfe\x35\xf1\x97\xb3\xbb\x89\xbb\x8e\x9c\xdd\ -\xfd\x0f\x63\x62\xcf\x20\ +\x00\x27\xf1\x78\x9c\xed\x59\xdd\x6f\xdb\x36\x10\x7f\xcf\x5f\xa1\ +\xa9\x2f\x1b\x66\x51\xfc\x14\x49\xc5\xce\x30\xac\x28\x30\x60\x7b\ +\xd9\x3a\xec\xb1\x90\x25\xda\xd6\x22\x4b\x86\x24\xc7\x4e\xff\xfa\ +\x1d\x65\x49\x96\x1d\xc7\xc9\x9a\x74\x03\xe6\xc8\x48\x6d\xf1\x3e\ +\x78\xbc\xfb\x1d\x79\xc7\x8e\x7f\xd8\x2e\x33\xe7\xce\x94\x55\x5a\ +\xe4\x13\x97\x20\xec\x3a\x26\x8f\x8b\x24\xcd\xe7\x13\xf7\x8f\x8f\ +\x1f\x3c\xe5\x3a\x55\x1d\xe5\x49\x94\x15\xb9\x99\xb8\x79\xe1\xfe\ +\x70\x73\x35\xfe\xc6\xf3\x9c\x9f\x4a\x13\xd5\x26\x71\x36\x69\xbd\ +\x70\x7e\xce\x6f\xab\x38\x5a\x19\xe7\xdb\x45\x5d\xaf\x42\xdf\xdf\ +\x6c\x36\x28\x6d\x07\x51\x51\xce\xfd\xef\x1c\xcf\xbb\xb9\xba\x1a\ +\x57\x77\xf3\x2b\xc7\x71\x60\xde\xbc\x0a\x93\x78\xe2\xb6\x02\xab\ +\x75\x99\x35\x8c\x49\xec\x9b\xcc\x2c\x4d\x5e\x57\x3e\x41\xc4\x77\ +\xf7\xec\xf1\x9e\x3d\xb6\xb3\xa7\x77\x26\x2e\x96\xcb\x22\xaf\x1a\ +\xc9\xbc\x7a\x37\x60\x2e\x93\x59\xcf\x6d\xad\xd9\xb0\x86\x89\x68\ +\xad\x7d\x4c\x7d\x4a\x3d\xe0\xf0\xaa\xfb\xbc\x8e\xb6\xde\xa1\x28\ +\xd8\x78\x4a\x94\x62\x8c\x7d\xa0\xed\x39\x9f\xc7\x15\x56\xe0\xd0\ +\x15\xfc\xf5\xec\xdd\x00\xaa\x8a\x75\x19\x9b\x19\xc8\x19\x94\x9b\ +\xda\x7f\xff\xf1\x7d\x4f\xf4\x30\x4a\xea\x64\xa0\xa6\xf3\xe7\xc1\ +\xac\x07\x4e\xce\xa3\xa5\xa9\x56\x51\x6c\x2a\xbf\x1b\x6f\xe4\x37\ +\x69\x52\x2f\x26\x6e\xc0\x57\xdb\xe6\x7d\x61\xd2\xf9\xa2\x1e\x0c\ +\xa4\xc9\xc4\x05\x9b\xa9\x22\x41\xf3\x3e\x80\x04\xd9\x31\xb4\xea\ +\xc2\x9e\x82\x11\x57\x88\x21\xe2\x94\x5a\xa9\x9d\x54\x67\x79\x98\ +\x14\xb1\x35\x65\xe2\xfe\x58\xc6\x8b\x4f\x7f\x46\x59\xf6\xe9\x63\ +\x69\x0c\xb2\x6e\xb9\x01\xce\x71\x62\x66\x95\x95\xd8\xcd\x6c\xdf\ +\x60\x6a\xd5\xd0\x80\xda\x4f\xb6\x82\xc9\x56\x26\xb6\x81\xde\x71\ +\x0f\xe6\xa8\xef\xad\x27\x0e\x59\xd9\xce\x5d\xce\x81\xc1\xab\x4f\ +\x5b\xb0\xd6\x09\x1d\x46\xe1\x1f\x72\x92\xe3\x7e\xc7\x41\x20\x76\ +\xf0\x85\x4f\xf2\x7c\xb6\xfe\x3a\xa3\xa6\xb5\xc0\x2b\xca\x74\x9e\ +\x82\x83\x1a\x3e\x4a\x10\x6b\x9e\x43\x19\x58\xf4\x60\x6d\x54\x51\ +\xee\x3a\xfe\x33\x56\x7f\x24\xc8\x02\x4a\x9f\x36\x04\x23\x61\x17\ +\xd5\x1a\x72\x6c\xca\xe1\x0a\x49\xc3\x29\x5e\xe4\xa8\xd6\xdd\xc7\ +\x6a\x9e\x8a\xdc\x97\x3a\xc0\xd3\x17\xee\x02\xc1\x2e\xdc\x01\x52\ +\x5c\xb8\x03\xb4\xbc\x6c\x07\x48\x7a\xc2\x86\x8b\x72\x00\xbf\xf0\ +\x73\x40\x06\xfc\xc2\x1d\xa0\x2e\x7c\x13\x54\x38\xb8\x78\x07\x78\ +\x17\x5e\x09\x28\xf6\x7f\x4b\x82\xb1\x6f\x9b\xa3\xe6\x57\x2f\x60\ +\x5b\xab\xe4\x2e\x35\x9b\x7d\x07\x35\x8d\x2a\xd3\x6a\x5e\x45\x73\ +\xe8\x8a\xb3\xa2\x9c\xb8\xef\x66\xcd\xd3\x12\xa6\x45\x99\x98\xb2\ +\x23\x05\xcd\x73\x40\x2a\xa0\x73\x4c\xeb\xfb\xdd\x3d\xc0\xd5\x91\ +\x13\x41\x6b\x4f\xc7\xa7\xe9\xd5\x22\x4a\x8a\xcd\xc4\xa5\xc7\xc4\ +\xcf\x45\xb1\x9c\xb8\x02\x09\x6c\x1f\x72\x4c\x8e\xc1\x43\x5c\x20\ +\x4c\x45\xc0\x1f\x12\x61\x3e\x2a\x91\x22\x1a\x93\xe0\x01\x71\x5d\ +\x96\x26\xaf\xbd\x2c\xba\x37\xb0\xa8\xe6\xab\xd3\x50\x2d\x8a\xcd\ +\xbc\xb4\xce\xa9\xcb\xb5\x39\x96\x84\x0e\x75\x6d\xef\x18\xbc\x75\ +\x9e\xd6\xd0\xc7\xb7\x7d\xf0\x80\xc3\xca\x7a\xd3\x69\xb1\x3d\xad\ +\xa0\xca\xa3\xd5\x19\xb2\xa5\x78\xab\xa8\x5e\x54\x67\xe8\x79\x91\ +\x98\x47\xe8\xbd\x7a\xcf\x24\x73\xe3\x2d\xd3\x64\x55\xa4\x79\xfd\ +\x24\xf7\x13\x8c\xc5\xf4\x2f\x48\x95\x73\x86\xb5\x1c\x67\x4c\xdb\ +\xa4\x39\x84\xd9\x6b\xef\x14\x08\x55\x0f\xc0\xd0\x72\x74\xb7\x0c\ +\x52\xa8\x47\x38\x6c\x6a\x3c\x42\xb2\x30\xd4\x8f\xd0\x96\xd1\x36\ +\x5d\xa6\x9f\x4d\x62\xc5\xdb\x3c\x59\x9a\x3a\x4a\xa2\x3a\xda\xe7\ +\x44\x37\x02\xdd\x35\xe9\x6e\x16\xca\x64\x16\xfe\xf6\xfe\xc3\x4d\ +\x9b\x84\xe3\x38\x0e\xff\x2c\xca\xdb\x2e\x27\x1d\xc7\x32\x44\xd3\ +\x62\x0d\x66\xbb\x37\xfd\xf0\x38\x89\xc3\x59\x51\x2e\xa3\xfa\x26\ +\x5d\x02\xd2\xed\xfd\xce\xf7\xdb\x65\x06\xd9\xd9\x13\x0e\x98\x6d\ +\x4e\xef\x95\xee\xd4\x96\x66\x77\xdb\x73\xf2\xca\x2b\x89\x97\xa9\ +\x15\xf2\x7f\xaf\xd3\x2c\xfb\xd9\x4e\xd2\x6f\x81\xbd\xd2\xb4\xce\ +\xcc\x7e\x70\xec\xb7\xd6\xb7\x6b\xf3\x07\x8b\x1b\xfb\xdd\xea\x9b\ +\xb7\xf9\xde\x2b\x07\x39\xd2\x3b\x36\x8b\xa6\x26\x9b\xb8\xbf\x58\ +\xa2\xf3\x80\x3a\x2f\x8b\xf5\x6a\x09\x88\x68\xc5\x7b\x6f\x02\x52\ +\xfa\xed\xac\xbe\xcf\x80\xde\x6c\x2f\xe1\xbb\x26\xd1\xf1\xf5\x0c\ +\xd6\x12\xbe\x8b\x22\xce\xdb\x17\xaf\xdd\x43\x42\xb2\x7b\x2d\xd7\ +\x99\x09\xcd\x9d\x01\xb8\x25\xd7\x55\x5d\x16\xb7\xa6\x17\xde\xbd\ +\xee\x70\x16\x32\xc4\x79\xc0\x29\xc5\xa4\x1b\xcf\xd2\xdc\x80\x75\ +\xe1\x74\x5d\xd7\xc3\xb1\xbf\x00\xfe\x21\x18\x9c\x77\x0a\x21\x27\ +\x6a\x53\x66\x80\x98\x3a\xe4\xdd\xd8\xde\x8e\x76\x20\x89\x60\xfb\ +\x2a\xcb\xe8\x3e\xcc\x8b\xdc\x0c\x47\x8b\xd9\xac\x32\x75\x88\xaf\ +\x97\x51\x79\x6b\xca\x1d\xfd\x2e\xad\xd2\x69\x9a\x59\x15\xcd\xcf\ +\xcc\x5c\x27\x69\xb5\x02\xf7\x84\x69\x6e\xcd\xb8\x2e\xee\x4c\x39\ +\xcb\x8a\x4d\x4f\x37\x79\x04\x5f\xde\x34\x8a\x6f\xe7\x8d\x7d\x61\ +\x14\xc3\x26\xb4\xce\xa2\xda\xec\x0f\x0e\x08\x91\x75\x2b\x55\x1c\ +\x7b\xcc\xe3\x1e\xf6\x54\x4f\xec\x52\x4e\x20\xcd\x02\x46\xf7\xf7\ +\x1e\x5d\xa6\x11\x8a\x84\x12\x1c\xef\x45\xb6\xf6\x1e\x0a\x69\x2d\ +\xf5\xa0\x3c\x82\xdc\x12\x1a\x05\x90\xba\xfb\xae\xa1\x2e\xa3\xbc\ +\xb2\x50\x86\xc4\x89\xea\x32\xdd\x7e\x8b\x91\x14\x52\x12\x2e\x46\ +\x1e\x46\x81\xa0\x42\x05\x44\x8f\xf0\x88\xc0\x1f\xfe\x6e\x7f\x40\ +\x3f\x13\x05\xbb\xb3\xe8\xa5\x28\xc0\x5a\xc1\xca\xa5\xd4\xed\xa3\ +\x5e\x3f\xf4\x5f\x31\xcc\xe7\xb0\x3b\x84\xda\x49\x38\x1c\xc3\x80\ +\x72\xc4\x02\xaa\x03\x79\x0a\x06\x5c\x51\xa1\xf9\x10\x06\x14\x31\ +\x42\x08\xf0\x0f\x61\x40\x15\x52\x4a\x41\x94\xcf\xe2\x40\x33\xc9\ +\x04\xc1\x10\x7c\xc4\xb8\x62\x6f\x38\xf8\x4f\x71\x30\xb8\xef\xfc\ +\x42\x24\x28\xa4\x03\x08\xe8\x03\x24\x04\x01\x80\xe1\x15\x90\x60\ +\xcb\x8b\x67\x20\x21\x96\xf6\xf3\x42\x24\xbc\x24\xee\xff\x61\x84\ +\xcf\x1f\x35\x7d\x0c\x20\xec\xbf\x3a\x84\x23\xca\x89\xa0\x72\x44\ +\x34\xa2\x9a\x13\xac\x1c\x26\x11\x96\x8a\xa8\x11\xd4\xc6\xf6\x9b\ +\x6a\x87\x42\x09\x8d\xa9\xd6\x6c\xc4\x14\x22\x8a\x04\x42\x3a\x14\ +\x91\x20\x60\x4c\x03\x1f\x6c\xf8\x9a\xc1\xb9\x71\x52\xdd\xe7\xc7\ +\x0e\x20\x61\xff\x1e\xf6\x2c\xb6\x3c\xb4\xe5\x0a\x94\x88\xb1\x7d\ +\xde\x62\xff\x95\x62\xcf\x20\x44\x10\x2d\xc9\x47\x90\xa0\x5c\x70\ +\x49\xa5\x13\x50\x84\x03\xac\x20\x80\x2c\x40\x9a\x53\xce\x95\xc3\ +\x35\xd2\x0a\xfa\xa7\x11\x97\x90\x99\x94\xca\xc0\x01\x64\x10\xae\ +\xb4\x92\x16\x0f\x50\x15\x08\x21\x4e\xaa\x3b\x17\xfb\x17\x46\x7e\ +\x17\xeb\x83\xd8\x3d\x23\x94\x8f\x56\x75\x4d\x44\x1f\x86\xb2\xfb\ +\x05\x55\x0a\x66\x58\x30\x5b\x6d\xee\x1e\x71\x0e\x0b\x87\xa1\x18\ +\xba\x7d\x69\xfd\x64\xb7\x39\xa5\x46\x1c\x9a\x61\x70\x23\x63\x0e\ +\x61\x88\x61\x49\x34\x1f\x79\x04\xea\x21\x42\xb4\x74\x38\x02\x07\ +\xc3\x67\xe4\x71\x84\x99\x10\x5a\x3b\x1e\x05\x3b\x98\xd2\x9a\x8e\ +\x3c\x89\x02\xae\x31\x65\x8e\xa7\x10\xa3\x50\xc0\xea\x11\x04\x25\ +\xd0\x01\x84\x82\x34\xf5\x15\x17\x6a\x14\xd8\x24\x25\x01\x3f\x8a\ +\x84\xf5\x27\x53\x5c\x3f\x1d\x83\xf8\xed\x10\xfe\xd7\x0f\x61\xf6\ +\xc2\x43\x98\xd8\x7d\x5b\x49\x35\x3c\x83\x01\x61\x8a\x4b\x32\xf8\ +\xff\xbc\xaf\x5e\x8d\xc9\xc8\x7e\x5e\xab\x37\xeb\xf2\x8e\x5f\x12\ +\x10\x3c\x7e\x0c\x85\x7f\xd8\xa0\x05\xc0\x1e\x28\x2d\x0e\xea\x31\ +\x0d\xd1\xd5\x54\xe2\xf3\xf5\xd8\xab\x76\x68\x6f\x58\x78\x05\x2c\ +\x78\x0f\xfa\xb4\x7f\x88\x06\x01\x35\x1b\xe7\x5a\x90\x21\x1a\xe0\ +\xc8\x87\x93\x82\x0f\x9a\xb7\x2f\x47\xc3\x5b\x85\xf6\xaa\x15\x1a\ +\x14\x52\x12\xc2\x45\x47\x50\x32\x70\xa2\x24\x75\x04\x41\xd6\xf7\ +\x92\x8e\x88\x42\x50\x91\x0b\xcd\xfa\x82\x42\x34\x85\x17\x54\xdd\ +\x94\x38\x24\x40\x81\xe4\x8c\x51\x5b\x88\x43\x1d\x2e\x4f\xe8\x7a\ +\xbc\x38\x7b\x76\x69\x36\xf6\xe7\x37\x57\x63\x7b\x65\x79\x73\xf5\ +\x37\x0f\x85\xd5\xfb\ \x00\x00\x11\xff\ \x3c\ \x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ @@ -10066,6 +10193,130 @@ qt_resource_data = "\ \x9a\x32\x44\x99\x70\x39\x33\x94\xd2\xeb\xa7\x55\xab\x4f\x8c\xe1\ \x70\xaa\x5e\x6a\x8c\x9b\xd9\xea\xf6\xea\xc6\x24\x6c\xb7\x57\xff\ \x06\x6a\xf1\x08\x6d\ +\x00\x00\x07\x91\ +\x00\ +\x00\x36\x0d\x78\x9c\xed\x5b\xdd\x6f\xdb\x38\x12\x7f\xcf\x5f\xa1\ +\x53\x5e\x5a\x9c\x25\xf3\x4b\x14\xa9\xda\x59\x1c\xae\xd8\xc3\x02\ +\x77\x38\x60\xdb\xe2\x1e\x0b\x59\xa2\x6d\x6d\x64\xd1\x90\xe4\xd8\ +\xee\x5f\x7f\x43\x59\x5f\x76\xe4\xa4\xe9\xe6\xa1\x17\x9d\x83\x24\ +\xd2\xcc\x90\x1c\xfe\x66\x38\x33\x94\xe8\xd9\x2f\x87\x4d\x6a\x3d\ +\xa8\xbc\x48\x74\x36\xb7\xb1\x8b\x6c\x4b\x65\x91\x8e\x93\x6c\x35\ +\xb7\xbf\x7c\xfe\xd5\x11\xb6\x55\x94\x61\x16\x87\xa9\xce\xd4\xdc\ +\xce\xb4\xfd\xcb\xdd\xcd\xec\x2f\x8e\x63\xfd\x3d\x57\x61\xa9\x62\ +\x6b\x9f\x94\x6b\xeb\xb7\xec\xbe\x88\xc2\xad\xb2\xde\xad\xcb\x72\ +\x1b\x4c\xa7\xfb\xfd\xde\x4d\x6a\xa2\xab\xf3\xd5\xf4\xbd\xe5\x38\ +\x77\x37\x37\xb3\xe2\x61\x75\x63\x59\x16\x8c\x9b\x15\x41\x1c\xcd\ +\xed\xba\xc1\x76\x97\xa7\x95\x60\x1c\x4d\x55\xaa\x36\x2a\x2b\x8b\ +\x29\x76\xf1\xd4\xee\xc4\xa3\x4e\x3c\x32\xa3\x27\x0f\x2a\xd2\x9b\ +\x8d\xce\x8a\xaa\x65\x56\xdc\xf6\x84\xf3\x78\xd9\x4a\x1b\x6d\xf6\ +\xb4\x12\xc2\x52\xca\x29\x22\x53\x42\x1c\x90\x70\x8a\x63\x56\x86\ +\x07\xe7\xbc\x29\xe8\x38\xd4\x94\x20\x84\xa6\xc0\xeb\x24\xbf\x4f\ +\x2a\x38\xa4\x00\xc5\x55\x65\x2a\x6e\x7f\x74\x80\x7f\x0b\xbf\x6d\ +\x83\x86\xe0\x16\x7a\x97\x47\x6a\x09\x2d\x95\x9b\xa9\x72\xfa\xf1\ +\xf3\xc7\x96\xe9\x20\x37\x2e\xe3\x5e\x37\x0d\xfa\x67\xe3\x9e\x99\ +\x24\x0b\x37\xaa\xd8\x86\x91\x2a\xa6\x0d\xbd\x6a\xbf\x4f\xe2\x72\ +\x3d\xb7\x39\xdb\x1e\xaa\xfb\xb5\x4a\x56\xeb\xb2\x47\x48\xe2\xb9\ +\x0d\x33\x24\x02\xf3\xea\xbe\xe7\x40\xf8\x24\x50\x77\x17\xb4\x1c\ +\xe4\x32\xe1\x52\x17\x5b\xb9\x14\xe2\xd4\xaa\xd1\x3c\x88\x75\x64\ +\x54\x99\xdb\x7f\xcb\xa3\xf5\xd7\xdf\xb5\x5e\xba\x06\xbf\x3b\x10\ +\x9a\xc5\x6a\x59\x18\xe1\xd3\xa0\xe6\x0e\x46\x15\x15\x0f\xb8\x80\ +\x9c\x0a\xf3\x7f\xe4\x61\x9c\x80\xbf\x9c\xe4\x4e\x92\xe7\x1c\xca\ +\x05\xae\xdb\x40\xab\xa2\xd4\xdb\x46\xb6\x9e\x0c\x50\x28\x97\xbe\ +\xdd\x91\xf5\x72\x59\x28\x98\x34\xea\xd1\x8a\xf2\x98\xaa\x93\xb4\ +\x13\xe9\x54\xe7\xc1\xed\xb2\xfa\x7c\xa8\x48\x1a\xb0\x4c\xca\x63\ +\x80\x3f\xd8\xd6\xf4\xca\x68\x03\x5d\x88\x85\xf9\x79\xd4\xc5\x63\ +\x55\xb0\x3d\xa4\xb5\xf0\xda\xd1\x66\xd3\xf3\x69\xd7\xd4\xd6\x1a\ +\x5b\xb0\xc6\x56\x45\x66\xdd\x34\x3d\xb5\x46\x28\x8f\xc6\x55\xce\ +\x45\x69\xdc\x8e\xd8\x59\x74\xfb\xf5\x00\xa8\x58\x81\x45\x09\xfc\ +\xc1\x83\x12\xc7\x93\x04\x86\xa5\x00\xff\xd0\xa0\xcc\x37\xe3\x50\ +\x4f\x74\x53\x6b\xe0\xe8\x3c\x59\x25\xe0\x41\x95\x1c\xc1\x2e\xad\ +\x3e\xe7\x6d\x00\x8c\xde\xdc\x88\x20\xac\xc3\xe4\xa9\xd9\x5f\x34\ +\xa4\x9c\x90\xe7\x15\x41\xae\x67\x26\x55\x2b\x72\xa9\xca\xf9\x0c\ +\x71\x25\xe9\xfd\x29\xa0\x6a\xb8\x2f\xbb\x79\xce\x72\x3f\x0a\x80\ +\x23\x47\x0e\x81\x47\x47\x0e\x80\xef\x8d\x1c\x80\x5e\x22\x18\x25\ +\x00\x3e\x19\xd0\x61\x54\x00\xb0\x91\xe7\x01\x9f\xb3\x91\x03\x20\ +\x46\x1e\x04\x05\xe2\xa3\x07\xc0\x19\x79\x25\x20\xe8\xc8\x17\x01\ +\xc7\x23\x0f\x83\x00\x80\x23\x46\x0e\x01\x1b\x79\x14\x00\x00\xc6\ +\x1e\x08\xb9\x3f\xf2\x7a\x10\x00\x70\x46\x9e\x0b\x7c\xf4\x1d\x0f\ +\xa9\xde\x38\x00\x63\xcf\x05\x3e\x7b\x83\x45\xf1\x36\x2c\x4b\x95\ +\x67\x4d\xbb\xfa\xf6\x73\x1e\x66\xc5\x52\xe7\x9b\xb9\xbd\x09\xcb\ +\x3c\x39\xbc\x43\x2e\x87\x6d\x21\xf5\x89\x98\x38\xc8\x15\x58\x10\ +\x89\x3d\x6f\x42\x5c\xe6\xf9\x82\x62\x36\xc1\xae\x10\x8c\x79\x1e\ +\x9b\x38\x84\x03\x15\x71\xc4\x27\x58\xb8\x44\x32\xc9\xfc\xf7\xe7\ +\x8f\x6b\x4f\xa3\x78\x84\x76\x1a\x57\x2f\x42\x82\x75\xae\x96\x73\ +\xfb\xf6\x13\x8c\xb9\x2d\xf0\x57\xec\x0c\x94\x60\x91\x4e\x53\x30\ +\xc9\xdc\x0e\xd3\x7d\x78\x2c\x7e\xc8\x98\x1e\x21\x6f\xb0\xb8\xbb\ +\x30\x66\x2b\x58\x94\x3a\xba\x37\x08\x54\xb8\xaa\xc2\xc2\xc1\xf9\ +\xf3\xf3\x21\xbc\x9f\x72\x05\xee\x83\x23\x30\x3a\x71\xb0\x8b\x10\ +\xc4\x06\x51\x79\x02\xe1\x58\xf8\x02\xae\x28\xc6\xcc\x63\x62\x42\ +\x5d\xe6\x73\x24\x85\x0f\x57\x1e\x65\x92\xd0\xce\x0f\x9a\xf7\x4a\ +\x9d\x22\xf5\x9b\x27\x72\xa9\xc1\x97\x2c\x29\x8b\xb9\xbd\x2b\x54\ +\xfe\xc9\xbc\xb0\xfa\x77\xf6\xa5\x50\xcf\xbb\x45\xfb\x0e\x26\x07\ +\x6a\x23\x7d\x9a\xae\xa1\x30\x26\x68\x6f\xb6\x9d\x42\xa4\x47\xab\ +\x55\xea\xbf\x7b\x01\x3b\xc2\x02\xf0\x7a\x94\xc3\xe0\x7b\xa2\x65\ +\x92\xa6\xc1\x22\x0d\xa3\xfb\x0f\x45\x99\xeb\x7b\x15\x64\x3a\x53\ +\xbd\xb7\x35\xf5\xec\x7e\xcc\x77\xdf\xe2\x73\xfa\x17\x84\xa2\xef\ +\xf5\x3f\xe9\x02\x89\x0a\x3c\x11\xae\xe4\x92\x08\xc4\xae\x06\xa2\ +\x9e\x2f\x5c\x09\x45\x03\xd1\xff\xb5\x42\xd1\x5b\x2c\xb1\x5f\x21\ +\x18\xf1\x51\x05\x23\xf4\xd3\x04\xa3\x97\xac\x44\x0f\x53\x2a\x48\ +\x05\x3e\xa7\x98\x48\x69\xc0\xc7\x50\x2c\x20\x6a\xae\x18\x14\x0a\ +\x3e\xd8\x86\x49\xd7\xe7\xc4\xe3\x86\x2d\x3d\xc6\x05\xba\x56\x13\ +\x48\x3e\xbc\x10\xfb\x6b\x75\x60\xb9\xbc\xce\x52\x14\x6f\xb0\xc6\ +\x7d\xfd\xb8\x6a\x2a\x3c\x4a\x39\x88\x4e\x30\x14\x83\xc2\xc7\xf2\ +\x7a\x85\xd7\x33\xd6\xb5\x1a\xef\x45\xf6\x7c\x8d\x22\xa7\x37\xe0\ +\x18\x22\x0b\xeb\x45\xd2\xff\x9d\xd8\xc2\x00\x7b\x26\x04\x37\x1b\ +\x0e\x4e\x60\xb7\x21\x98\x84\x6d\x86\xe7\x41\x70\xe1\x3e\x5c\x31\ +\x8a\xa9\xe4\x13\xe2\xbb\x92\x09\x66\xf6\x20\xd4\xa5\x88\x33\x8f\ +\x0f\x3b\x23\xa5\xe8\x39\x57\x1c\x28\xab\x5e\x25\xb0\x50\xf2\xff\ +\x0c\xdf\x21\x33\x84\xf7\x18\xd6\x21\xfd\x69\x56\xe1\x8b\x7c\x97\ +\x8f\xfb\xd9\x97\x47\xc5\x1b\x5c\xbc\x2f\x01\x80\xe1\x37\xe8\x01\ +\x57\x8e\x8f\x5e\x5b\xdf\x83\x89\x63\xe0\xa0\x69\x1f\xc3\x4b\xb6\ +\xec\xd6\xf1\x01\xcf\x6d\xea\xbb\x42\x42\x96\xeb\x0e\x1c\x1d\x81\ +\xca\xcc\x69\x59\xe6\xf7\x5e\x3a\x1c\xc8\xdc\xe6\xc4\x45\x4c\xf8\ +\x7e\x17\x30\x8f\x86\x8a\x5c\xa8\xb0\x30\xee\x7a\x58\xd5\x83\x3d\ +\x1d\xc5\x1a\xa9\xa1\x68\x4b\x18\x21\x3e\xc2\xf2\x94\x76\x99\x87\ +\x7d\x49\x26\x55\xa5\xcf\x29\x82\x74\x0b\x12\xc4\x87\x34\x4b\xbc\ +\x89\xe7\x72\xc4\x24\xf2\xc4\x84\x11\x17\x88\x98\x8a\xf7\x35\xc0\ +\xb3\xa9\x39\xae\x5b\x5d\xb5\x16\x31\xe7\x7c\xe3\x87\x44\xed\x6f\ +\x5a\x84\x16\x61\xab\xd5\x36\x5c\xa9\xea\x50\x2c\xe0\x7a\x3a\x58\ +\x5b\x33\x16\x3a\x8f\x55\xde\xb0\x78\xf5\x39\x63\xd5\xe7\x66\x4f\ +\x47\xd8\x6f\x2e\xbc\x14\x7a\x6d\xf9\x68\x98\x5f\xac\xc3\x58\xef\ +\xbb\x50\xdc\x32\xbf\x69\x0d\xc8\x50\xa8\x70\x25\x12\xfe\x23\x76\ +\x04\x2e\xe8\x60\xd8\xcf\x10\xea\xfb\xec\x11\xd7\x28\xc4\x5c\x28\ +\x8d\x05\xc1\x8f\x98\xbb\x3c\x07\xfc\x9d\x34\x3c\x2a\x98\x55\xf5\ +\xaf\x11\x2a\xd6\x7a\xbf\xca\x0d\x3a\x65\xbe\x53\x97\x2d\x63\x1d\ +\xed\xcc\xf9\x78\x67\x77\xb2\x70\x7d\x2a\xbb\x27\x61\xda\x3a\x8b\ +\x85\x3e\x0c\x77\x50\x64\xe1\xf6\x09\xb6\xe1\x38\x90\x2c\xd6\xc5\ +\x13\xfc\x4c\xc7\xea\x0a\xbf\xed\xde\x51\xf1\x4a\x39\x9b\x24\xde\ +\xea\x24\x2b\x9f\x95\x7e\x46\x50\x2f\xfe\x80\xd5\xf8\x94\x62\xb5\ +\xc4\x13\xaa\xed\x93\x0c\xec\xec\x34\x59\x96\x88\x47\xde\x50\x4b\ +\x34\xb9\xd9\xf7\xc4\x15\x89\x5e\x12\xbe\x64\x19\xb3\xcb\x2b\xbc\ +\x4d\x78\x48\x36\xc9\x37\x15\x9b\xe6\xf5\x42\xd9\xa8\x32\x8c\xc3\ +\x32\xec\x16\x45\x43\x21\xc6\x71\xea\x68\x95\xc7\xcb\xe0\xf7\x8f\ +\xbf\xb6\x55\x46\x14\x05\xff\xd1\xf9\x7d\x57\x07\x18\x81\x70\xa1\ +\x77\xa0\x76\x5b\x8b\x98\x23\xf4\x51\x60\xd6\x77\x58\xde\x25\x1b\ +\x70\x75\xf3\xdd\x84\xbf\x1e\x36\x29\x2c\xcf\x96\x71\x26\x6c\xa2\ +\x66\xd7\xe9\xa9\xdb\x5c\x9d\xbe\x7b\x30\xf8\x75\x8d\x38\xda\x24\ +\xa6\xd1\xf4\x53\x09\x25\xc8\x6f\x66\x90\xde\x01\xf8\xba\xd3\xa4\ +\x4c\xd5\x5d\x35\xe6\xe9\xb2\x99\xc5\xb4\x9e\x46\x53\xa4\xf4\x66\ +\x39\x9b\x36\x30\x54\x77\xab\x0e\x9e\xb3\xc5\xd2\x22\x9c\x86\x0b\ +\x95\xce\xed\x7f\x1a\xa6\xf5\x88\xbb\xca\xf5\x6e\xbb\x01\xd7\xa8\ +\x9b\xdb\x5d\x09\xbb\x6e\x33\x47\xaf\x92\xba\xe5\x0b\xf3\xf3\xc1\ +\xdc\xf4\xce\xe5\xd7\xa5\xd5\x2d\xaa\x3e\xf5\xed\xc9\xa1\x02\xda\ +\xdc\x9a\xa8\x0f\x83\x06\x8b\x5d\x59\xf6\x69\x7f\x80\x7b\x07\xa0\ +\x47\x16\x37\x54\x40\x4e\xe5\x29\x78\x44\x19\xb0\x86\x76\x39\x98\ +\x13\x87\x10\x9f\xf2\x3c\x3c\x9e\x2a\xba\x46\x5b\x00\xe2\x5f\x16\ +\x81\xb0\x4c\x25\xf2\xf9\x84\x79\xae\x27\xb8\x8f\x88\x05\xa1\x58\ +\x20\xe9\x49\xa8\x91\xa9\x8b\x89\xe7\x21\x6c\x31\x09\x1b\x23\xe9\ +\x63\x7f\x22\x5d\x09\xc1\x4c\x52\x8b\x40\x1c\xc7\xb0\xa5\x22\x13\ +\x02\x61\xdc\x83\x2c\x44\xad\x6f\x97\xdb\xa6\x35\x91\x68\x20\xfb\ +\x46\x3a\x83\x29\x96\x3a\x77\x20\x8e\x3d\x84\xe5\x2e\x57\xfd\xa2\ +\xb4\x0b\xf8\x00\xb8\xf1\x0d\x58\x8f\x91\xf9\x9c\x6d\x1d\x06\x71\ +\x07\xc7\x7a\xf7\x28\xab\x4a\xef\xfd\xcf\x6e\x88\x01\x80\x4d\xc6\ +\x26\x98\x51\x3a\x21\xdc\x3c\xf2\x82\x0c\x62\x51\x0f\x68\x3e\x24\ +\xf7\x89\x07\x56\x32\x89\xfb\x7b\xed\x20\xe4\xe0\xe3\xe7\x3f\x65\ +\x87\xd9\x74\x75\x77\x33\x33\x21\xe1\xee\xe6\xbf\x41\x63\xea\xe4\ +\ \x00\x00\x06\xdd\ \x00\ \x00\x22\x8f\x78\x9c\xed\x59\xdb\x6e\xe3\x46\x12\x7d\xf7\x57\xf4\ @@ -10327,6 +10578,10 @@ qt_resource_name = "\ \x00\x72\x00\x63\x00\x68\x00\x5f\x00\x53\x00\x70\x00\x6c\x00\x69\x00\x74\x00\x4d\x00\x65\x00\x73\x00\x68\x00\x2e\x00\x73\x00\x76\ \x00\x67\ \x00\x0d\ +\x07\x4a\x92\xc7\ +\x00\x41\ +\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x52\x00\x6f\x00\x6f\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x0d\ \x01\xb7\x92\xa7\ \x00\x41\ \x00\x72\x00\x63\x00\x68\x00\x5f\x00\x53\x00\x69\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ @@ -10373,6 +10628,11 @@ qt_resource_name = "\ \x00\x41\ \x00\x72\x00\x63\x00\x68\x00\x5f\x00\x46\x00\x6c\x00\x6f\x00\x6f\x00\x72\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x2e\x00\x73\ \x00\x76\x00\x67\ +\x00\x12\ +\x08\x61\x2a\xa7\ +\x00\x41\ +\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x52\x00\x6f\x00\x6f\x00\x66\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x2e\x00\x73\x00\x76\ +\x00\x67\ \x00\x14\ \x02\xc8\x0e\x47\ \x00\x41\ @@ -10382,8 +10642,8 @@ qt_resource_name = "\ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x01\ -\x00\x00\x00\x10\x00\x02\x00\x00\x00\x01\x00\x00\x00\x2d\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x18\x00\x00\x00\x15\ +\x00\x00\x00\x10\x00\x02\x00\x00\x00\x01\x00\x00\x00\x2f\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1a\x00\x00\x00\x15\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x11\x00\x00\x00\x04\ \x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x01\x60\x78\ \x00\x00\x00\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x55\x20\ @@ -10402,29 +10662,31 @@ 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\x2c\x00\x01\x00\x00\x00\x01\x00\x02\x43\x52\ -\x00\x00\x04\x38\x00\x00\x00\x00\x00\x01\x00\x02\x05\x83\ -\x00\x00\x03\x16\x00\x00\x00\x00\x00\x01\x00\x01\xb7\x11\ -\x00\x00\x05\xcc\x00\x01\x00\x00\x00\x01\x00\x02\x6e\xe4\ -\x00\x00\x04\xfe\x00\x01\x00\x00\x00\x01\x00\x02\x3c\x80\ -\x00\x00\x03\x50\x00\x01\x00\x00\x00\x01\x00\x01\xc5\x80\ -\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x01\xd9\x07\ +\x00\x00\x05\x4c\x00\x01\x00\x00\x00\x01\x00\x02\x4b\x1c\ +\x00\x00\x04\x58\x00\x00\x00\x00\x00\x01\x00\x02\x0d\x4d\ +\x00\x00\x03\x16\x00\x00\x00\x00\x00\x01\x00\x01\xb7\x13\ +\x00\x00\x06\x16\x00\x01\x00\x00\x00\x01\x00\x02\x7e\x42\ +\x00\x00\x05\x1e\x00\x01\x00\x00\x00\x01\x00\x02\x44\x4a\ +\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\x04\x78\x00\x00\x00\x00\x00\x01\x00\x02\x1f\x5d\ +\x00\x00\x04\x98\x00\x00\x00\x00\x00\x01\x00\x02\x27\x27\ +\x00\x00\x04\x38\x00\x01\x00\x00\x00\x01\x00\x02\x05\x85\ \x00\x00\x02\x98\x00\x01\x00\x00\x00\x01\x00\x01\x93\x78\ -\x00\x00\x03\x7e\x00\x01\x00\x00\x00\x01\x00\x01\xce\xd8\ +\x00\x00\x05\xec\x00\x01\x00\x00\x00\x01\x00\x02\x76\xad\ +\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\xa8\x00\x01\x00\x00\x00\x01\x00\x02\x2e\xcb\ -\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x01\xf5\x02\ -\x00\x00\x04\xd6\x00\x01\x00\x00\x00\x01\x00\x02\x34\x1b\ -\x00\x00\x05\x56\x00\x00\x00\x00\x00\x01\x00\x02\x4a\x2d\ -\x00\x00\x03\xc6\x00\x01\x00\x00\x00\x01\x00\x01\xde\x1e\ -\x00\x00\x05\xa0\x00\x01\x00\x00\x00\x01\x00\x02\x66\x6a\ -\x00\x00\x05\x80\x00\x01\x00\x00\x00\x01\x00\x02\x5c\x30\ -\x00\x00\x04\x58\x00\x01\x00\x00\x00\x01\x00\x02\x19\x45\ +\x00\x00\x04\xc8\x00\x01\x00\x00\x00\x01\x00\x02\x36\x95\ +\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x01\xf5\x04\ +\x00\x00\x04\xf6\x00\x01\x00\x00\x00\x01\x00\x02\x3b\xe5\ +\x00\x00\x05\x76\x00\x00\x00\x00\x00\x01\x00\x02\x51\xf6\ +\x00\x00\x03\xc6\x00\x01\x00\x00\x00\x01\x00\x01\xde\x20\ +\x00\x00\x05\xc0\x00\x01\x00\x00\x00\x01\x00\x02\x6e\x33\ +\x00\x00\x05\xa0\x00\x01\x00\x00\x00\x01\x00\x02\x63\xf9\ +\x00\x00\x04\x78\x00\x01\x00\x00\x00\x01\x00\x02\x21\x0f\ \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\x06\ +\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\x01\xf2\x00\x01\x00\x00\x00\x01\x00\x01\x76\xac\ " diff --git a/src/Mod/Arch/CMakeLists.txt b/src/Mod/Arch/CMakeLists.txt index a7522a4137..fcfd728bb8 100644 --- a/src/Mod/Arch/CMakeLists.txt +++ b/src/Mod/Arch/CMakeLists.txt @@ -20,6 +20,7 @@ SET(Arch_SRCS ArchWindow.py ArchAxis.py ArchVRM.py + ArchRoof.py ) SOURCE_GROUP("" FILES ${Arch_SRCS}) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 066ee12b82..52bf671659 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -61,7 +61,7 @@ class ArchWorkbench(Workbench): self.archtools = ["Arch_Wall","Arch_Structure","Arch_Cell", "Arch_Floor","Arch_Building","Arch_Site", "Arch_Window","Arch_Axis", - "Arch_SectionPlane","Arch_Add","Arch_Remove"] + "Arch_SectionPlane","Arch_Roof","Arch_Add","Arch_Remove"] self.drafttools = ["Draft_Line","Draft_Wire","Draft_Rectangle", "Draft_Polygon","Draft_Arc", "Draft_Circle","Draft_Dimension", diff --git a/src/Mod/Arch/Makefile.am b/src/Mod/Arch/Makefile.am index 61917f8f7f..e30ec2a6a5 100644 --- a/src/Mod/Arch/Makefile.am +++ b/src/Mod/Arch/Makefile.am @@ -27,7 +27,8 @@ data_DATA = \ ArchWindow.py \ ArchCommands.py \ ArchAxis.py \ - ArchVRM.py + ArchVRM.py \ + ArchRoof.py CLEANFILES = $(BUILT_SOURCES) diff --git a/src/WindowsInstaller/ModArch.wxi b/src/WindowsInstaller/ModArch.wxi index 094c7c6174..f8bdd05c8b 100644 --- a/src/WindowsInstaller/ModArch.wxi +++ b/src/WindowsInstaller/ModArch.wxi @@ -45,6 +45,7 @@ + From 03fa473ac24ceaf2946e5530fcb2d2857a2a5a68 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 18 May 2012 19:07:27 +0200 Subject: [PATCH 235/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.cpp | 14 ++++++++++++-- src/Mod/Mesh/App/Core/Segmentation.h | 8 +++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 450a7a0674..2e86fdb176 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -35,6 +35,10 @@ void MeshSurfaceSegment::Initialize(unsigned long) { } +void MeshSurfaceSegment::AddFacet(const MeshFacet&) +{ +} + void MeshSurfaceSegment::AddSegment(const std::vector& segm) { if (segm.size() >= minFacets) { @@ -76,10 +80,15 @@ bool MeshDistancePlanarSegment::TestFacet (const MeshFacet& face) const return false; } - fitter->AddPoint(triangle.GetGravityPoint()); return true; } +void MeshDistancePlanarSegment::AddFacet(const MeshFacet& face) +{ + MeshGeomFacet triangle = kernel.GetFacet(face); + fitter->AddPoint(triangle.GetGravityPoint()); +} + // -------------------------------------------------------- bool MeshCurvaturePlanarSegment::TestFacet (const MeshFacet &rclFacet) const @@ -153,7 +162,7 @@ bool MeshCurvatureFreeformSegment::TestFacet (const MeshFacet &rclFacet) const // -------------------------------------------------------- -MeshSurfaceVisitor::MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices) +MeshSurfaceVisitor::MeshSurfaceVisitor (MeshSurfaceSegment& segm, std::vector &indices) : indices(indices), segm(segm) { } @@ -172,6 +181,7 @@ bool MeshSurfaceVisitor::Visit (const MeshFacet & face, const MeshFacet &, unsigned long ulFInd, unsigned long) { indices.push_back(ulFInd); + segm.AddFacet(face); return true; } diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index 0219610014..561385c1c1 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -42,6 +42,7 @@ public: virtual ~MeshSurfaceSegment() {} virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; virtual void Initialize(unsigned long); + virtual void AddFacet(const MeshFacet& rclFacet); void AddSegment(const std::vector&); const std::vector& GetSegments() const { return segments; } @@ -68,8 +69,9 @@ class MeshExport MeshDistancePlanarSegment : public MeshDistanceSurfaceSegment public: MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); virtual ~MeshDistancePlanarSegment(); - bool TestFacet (const MeshFacet &rclFacet) const; + bool TestFacet (const MeshFacet& rclFacet) const; void Initialize(unsigned long); + void AddFacet(const MeshFacet& rclFacet); protected: Base::Vector3f basepoint; @@ -134,7 +136,7 @@ private: class MeshExport MeshSurfaceVisitor : public MeshFacetVisitor { public: - MeshSurfaceVisitor (const MeshSurfaceSegment& segm, std::vector &indices); + MeshSurfaceVisitor (MeshSurfaceSegment& segm, std::vector &indices); virtual ~MeshSurfaceVisitor (); bool AllowVisit (const MeshFacet& face, const MeshFacet&, unsigned long, unsigned long, unsigned short neighbourIndex); @@ -143,7 +145,7 @@ public: protected: std::vector &indices; - const MeshSurfaceSegment& segm; + MeshSurfaceSegment& segm; }; class MeshExport MeshSegmentAlgorithm From 6d8de2f1ab8e179010d92083a5cbaa6af5555bc2 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 15:59:53 -0300 Subject: [PATCH 236/351] Cleaning in the Arch module --- src/Mod/Arch/ArchSectionPlane.py | 9 ++++++--- src/Mod/Arch/ArchWindow.py | 18 ++++++++++-------- src/Mod/Arch/InitGui.py | 16 +++++++++++----- src/Mod/Arch/importIFC.py | 4 ++-- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index d4ae54c21f..886cbb3480 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -34,7 +34,7 @@ class _CommandSectionPlane: return {'Pixmap' : 'Arch_SectionPlane', 'Accel': "S, P", 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_SectionPlane","Section Plane"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_SectionPlane","Adds a section plane object to the document")} + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_SectionPlane","Creates a section plane object, including the selected objects")} def Activated(self): sel = FreeCADGui.Selection.getSelection() @@ -47,6 +47,8 @@ class _CommandSectionPlane: for o in sel: if o.isDerivedFrom("Part::Feature"): g.append(o) + elif o.isDerivedFrom("App::DocumentObjectGroup"): + g.append(o) obj.Objects = g page = FreeCAD.ActiveDocument.addObject("Drawing::FeaturePage","Page") template = Draft.getParam("template") @@ -179,6 +181,7 @@ class _ArchDrawingView: if hasattr(obj,"Source"): if obj.Source: if obj.Source.Objects: + objs = Draft.getGroupContents(obj.Sourc.Objects) svg = '' # generating SVG @@ -188,7 +191,7 @@ class _ArchDrawingView: import ArchVRM render = ArchVRM.Renderer() render.setWorkingPlane(obj.Source.Placement) - render.addObjects(obj.Source.Objects) + render.addObjects(objs) render.cut(obj.Source.Shape) svg += render.getViewSVG(linewidth=linewidth) svg += render.getSectionSVG(linewidth=linewidth*2) @@ -197,7 +200,7 @@ class _ArchDrawingView: else: # render using the Drawing module shapes = [] - for o in obj.Source.Objects: + for o in objs: if o.isDerivedFrom("Part::Feature"): shapes.append(o.Shape) if shapes: diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 382d9e3f98..2cdf513c91 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -78,17 +78,19 @@ class _CommandWindow: return {'Pixmap' : 'Arch_Window', 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Window"), 'Accel': "W, N", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from scratch or from a selected object (wire, rectangle or sketch)")} + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from a selected object (wire, rectangle or sketch)")} + + def IsActive(self): + if FreeCADGui.Selection.getSelection(): + return True + else: + return False def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction("Window") - if sel: - for obj in sel: - makeWindow(obj) - else: - rect = Draft.makeRectangle(1,1) - makeWindow(rect) + FreeCAD.ActiveDocument.openTransaction("Create Window") + for obj in sel: + makeWindow(obj) FreeCAD.ActiveDocument.commitTransaction() class _Window(ArchComponent.Component): diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 52bf671659..1de87ed470 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -58,10 +58,10 @@ class ArchWorkbench(Workbench): def Initialize(self): import DraftTools,DraftGui,Arch_rc,Arch - self.archtools = ["Arch_Wall","Arch_Structure","Arch_Cell", + self.archtools = ["Arch_Wall","Arch_Structure", "Arch_Floor","Arch_Building","Arch_Site", - "Arch_Window","Arch_Axis", - "Arch_SectionPlane","Arch_Roof","Arch_Add","Arch_Remove"] + "Arch_Window","Arch_Roof","Arch_Axis", + "Arch_SectionPlane","Arch_Add","Arch_Remove"] self.drafttools = ["Draft_Line","Draft_Wire","Draft_Rectangle", "Draft_Polygon","Draft_Arc", "Draft_Circle","Draft_Dimension", @@ -100,6 +100,12 @@ class ArchWorkbench(Workbench): FreeCADGui.addWorkbench(ArchWorkbench) FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC") FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") -FreeCAD.addImportType("Collada (*.dae)","importDAE") -FreeCAD.addExportType("Collada (*.dae)","importDAE") +# check for pycollada +try: + import collada +except: + FreeCAD.Console.PrintError("pycollada not found, no collada support.\n") +else: + FreeCAD.addImportType("Collada (*.dae)","importDAE") + FreeCAD.addExportType("Collada (*.dae)","importDAE") diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index f4a8f8392f..7a0cf8ae07 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -108,7 +108,7 @@ def getIfcOpenShell(): return True def read(filename): - "Parses an IFC file with IfcOpenShell" + "Parses an IFC file" # parsing the IFC file t1 = time.time() @@ -186,7 +186,7 @@ def read(filename): IfcImport.CleanUp() else: - # use the internal python parser + # use only the internal python parser # getting walls for w in ifc.getEnt("IfcWallStandardCase"): From 8b191077923aea4e5afc1025967d282c2f6b2c83 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 16:43:48 -0300 Subject: [PATCH 237/351] Fixed 0000708 - Draft DXF import --- src/Mod/Draft/importDXF.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index a03ec28aaf..97e01db7f2 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -1232,7 +1232,9 @@ def getWire(wire,nospline=False): points = [] for edge in edges: v1 = edge.Vertexes[0].Point - if (isinstance(edge.Curve,Part.Circle)): + if len(edge.Vertexes) < 2: + points.append((v1.x,v1.y,v1.z,None,None,0.0)) + elif (isinstance(edge.Curve,Part.Circle)): mp = fcgeo.findMidpoint(edge) v2 = edge.Vertexes[-1].Point c = edge.Curve.Center @@ -1251,14 +1253,12 @@ def getWire(wire,nospline=False): bul = -bul points.append((v1.x,v1.y,v1.z,None,None,bul)) elif (isinstance(edge.Curve,Part.BSplineCurve)) and (not nospline): - bul = 0.0 spline = getSplineSegs(edge) spline.pop() for p in spline: - points.append((p.x,p.y,p.z,None,None,bul)) + points.append((p.x,p.y,p.z,None,None,0.0)) else: - bul = 0.0 - points.append((v1.x,v1.y,v1.z,None,None,bul)) + points.append((v1.x,v1.y,v1.z,None,None,0.0)) if not fcgeo.isReallyClosed(wire): v = edges[-1].Vertexes[-1].Point points.append(fcvec.tup(v)) From d56e08e47fadd9006994988c69bcc7e1d05c816a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 17:43:57 -0300 Subject: [PATCH 238/351] Refining of Arch Roof tool --- src/Mod/Arch/ArchComponent.py | 2 -- src/Mod/Arch/ArchRoof.py | 21 ++++++++++++++++++--- src/Mod/Arch/ArchStructure.py | 2 ++ src/Mod/Arch/ArchWall.py | 2 ++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index b6065fa044..c9fa5a347e 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -260,8 +260,6 @@ class Component: "Other shapes that are appended to this wall") obj.addProperty("App::PropertyLinkList","Subtractions","Base", "Other shapes that are subtracted from this wall") - obj.addProperty("App::PropertyVector","Normal","Base", - "The normal extrusion direction of this wall (keep (0,0,0) for automatic normal)") obj.Proxy = self self.Type = "Component" self.Subvolume = None diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index 62850f243e..37d06b58e7 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -61,13 +61,30 @@ class _CommandRoof: sel = FreeCADGui.Selection.getSelectionEx() if sel: sel = sel[0] + obj = sel.Object if sel.HasSubObjects: if "Face" in sel.SubElementNames[0]: - obj = sel.Object idx = int(sel.SubElementNames[0][4:]) FreeCAD.ActiveDocument.openTransaction("Create Roof") makeRoof(obj,idx) FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + elif obj.isDerivedFrom("Part::Feature"): + if len(obj.Shape.Faces) == 1: + FreeCAD.ActiveDocument.openTransaction("Create Roof") + makeRoof(obj,1) + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + elif obj.isDerivedFrom("Part::Feature"): + if len(obj.Shape.Faces) == 1: + FreeCAD.ActiveDocument.openTransaction("Create Roof") + makeRoof(obj,1) + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + else: + FreeCAD.Console.PrintMessage("Unable to create a roof") + else: + FreeCAD.Console.PrintMessage("No object selected") class _Roof(ArchComponent.Component): "The Roof object" @@ -77,8 +94,6 @@ class _Roof(ArchComponent.Component): "The angle of this roof") obj.addProperty("App::PropertyInteger","Face","Base", "The face number of the base object used to build this roof") - obj.addProperty("App::PropertyLink","Base","Base", - "The base object this roof is built on") self.Type = "Structure" def execute(self,obj): diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 63d7b668c9..cd87115ebc 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -86,6 +86,8 @@ class _Structure(ArchComponent.Component): "The height or extrusion depth of this element. Keep 0 for automatic") obj.addProperty("App::PropertyLinkList","Axes","Base", "Axes systems this structure is built on") + obj.addProperty("App::PropertyVector","Normal","Base", + "The normal extrusion direction of this object (keep (0,0,0) for automatic normal)") self.Type = "Structure" def execute(self,obj): diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 108edabfc9..36c33e7a87 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -251,6 +251,8 @@ class _Wall(ArchComponent.Component): "The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid") obj.addProperty("App::PropertyEnumeration","Align","Base", "The alignment of this wall on its base object, if applicable") + obj.addProperty("App::PropertyVector","Normal","Base", + "The normal extrusion direction of this object (keep (0,0,0) for automatic normal)") obj.Align = ['Left','Right','Center'] self.Type = "Wall" obj.Width = 0.1 From bd43641457770d651527dc8e11b99ec090381d85 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 May 2012 19:01:01 -0300 Subject: [PATCH 239/351] Bugfixes in Arch --- src/Mod/Arch/ArchSectionPlane.py | 2 +- src/Mod/Arch/ArchVRM.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 886cbb3480..d1c1ada501 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -181,7 +181,7 @@ class _ArchDrawingView: if hasattr(obj,"Source"): if obj.Source: if obj.Source.Objects: - objs = Draft.getGroupContents(obj.Sourc.Objects) + objs = Draft.getGroupContents(obj.Source.Objects) svg = '' # generating SVG diff --git a/src/Mod/Arch/ArchVRM.py b/src/Mod/Arch/ArchVRM.py index c89776e62f..f7e5988abf 100644 --- a/src/Mod/Arch/ArchVRM.py +++ b/src/Mod/Arch/ArchVRM.py @@ -177,7 +177,8 @@ class Renderer: v = self.wp.getLocalCoords(v) verts.append(v) verts.append(verts[0]) - wires.append(Part.makePolygon(verts)) + if len(verts) > 2: + wires.append(Part.makePolygon(verts)) try: sh = ArchCommands.makeFace(wires) except: From 75a9c444ede4202980eb2acfc109b5198abfc18b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 19 May 2012 18:07:09 -0300 Subject: [PATCH 240/351] Allowed to drag&drop items on python groups too in tree --- src/Gui/Tree.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 03ca7cb2fc..2c5f0ea151 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -440,20 +440,39 @@ void TreeWidget::dropEvent(QDropEvent *event) ::getGroupOfObject(obj); if (par) { // allow an object to be in one group only - QString cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").removeObject(" + QString cmd; + if (par->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + // if this is a python group, call the method of its Proxy + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.removeObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") .arg(QString::fromAscii(doc->getName())) .arg(QString::fromAscii(par->getNameInDocument())) .arg(QString::fromAscii(obj->getNameInDocument())); + } else { + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").removeObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromAscii(doc->getName())) + .arg(QString::fromAscii(par->getNameInDocument())) + .arg(QString::fromAscii(obj->getNameInDocument())); + } Gui::Application::Instance->runPythonCode(cmd.toUtf8()); } // build Python command for execution - QString cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").addObject(" + QString cmd; + if (grp->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.addObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") .arg(QString::fromAscii(doc->getName())) .arg(QString::fromAscii(grp->getNameInDocument())) .arg(QString::fromAscii(obj->getNameInDocument())); + } else { + cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").addObject(" + "App.getDocument(\"%1\").getObject(\"%3\"))") + .arg(QString::fromAscii(doc->getName())) + .arg(QString::fromAscii(grp->getNameInDocument())) + .arg(QString::fromAscii(obj->getNameInDocument())); + } Gui::Application::Instance->runPythonCode(cmd.toUtf8()); } gui->commitCommand(); From dcc7eea7149f385b9f801ae553ebbfbf980a652d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 19 May 2012 18:18:02 -0300 Subject: [PATCH 241/351] Made Arch groups able to receive drops from the tree --- src/Mod/Arch/ArchBuilding.py | 19 +++++++++++++++++-- src/Mod/Arch/ArchFloor.py | 16 +++++++++++++++- src/Mod/Arch/ArchSite.py | 19 +++++++++++++++++-- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Mod/Arch/ArchBuilding.py b/src/Mod/Arch/ArchBuilding.py index 6a2cb2c33d..f8ed4e8ca3 100644 --- a/src/Mod/Arch/ArchBuilding.py +++ b/src/Mod/Arch/ArchBuilding.py @@ -68,12 +68,27 @@ class _Building: def __init__(self,obj): self.Type = "Building" obj.Proxy = self - + self.Object = obj + def execute(self,obj): - pass + self.Object = obj def onChanged(self,obj,prop): pass + + def addObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if not child in g: + g.append(child) + self.Object.Group = g + + def removeObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if child in g: + g.remove(child) + self.Object.Group = g class _ViewProviderBuilding: "A View Provider for the Building object" diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index f5b9d435e3..606395961d 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -71,13 +71,27 @@ class _Floor: "The height of this floor") self.Type = "Floor" obj.Proxy = self + self.Object = obj def execute(self,obj): - pass + self.Object = obj def onChanged(self,obj,prop): pass + def addObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if not child in g: + g.append(child) + self.Object.Group = g + + def removeObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if child in g: + g.remove(child) + self.Object.Group = g class _ViewProviderFloor: "A View Provider for the Cell object" diff --git a/src/Mod/Arch/ArchSite.py b/src/Mod/Arch/ArchSite.py index 5da538e5af..300fd09eff 100644 --- a/src/Mod/Arch/ArchSite.py +++ b/src/Mod/Arch/ArchSite.py @@ -68,13 +68,28 @@ class _Site: def __init__(self,obj): self.Type = "Site" obj.Proxy = self + self.Object = obj def execute(self,obj): - pass - + self.Object = obj + def onChanged(self,obj,prop): pass + def addObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if not child in g: + g.append(child) + self.Object.Group = g + + def removeObject(self,child): + if hasattr(self,"Object"): + g = self.Object.Group + if child in g: + g.remove(child) + self.Object.Group = g + class _ViewProviderSite: "A View Provider for the Site object" def __init__(self,vobj): From cd1910a7056636959c625fc956f189e8c35ec57e Mon Sep 17 00:00:00 2001 From: msocorcim Date: Sun, 20 May 2012 23:00:23 -0400 Subject: [PATCH 242/351] Add new Mod/Mesh files to Makefile.am --- src/Mod/Mesh/Gui/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mod/Mesh/Gui/Makefile.am b/src/Mod/Mesh/Gui/Makefile.am index 46158d1e10..dd4405cd7c 100644 --- a/src/Mod/Mesh/Gui/Makefile.am +++ b/src/Mod/Mesh/Gui/Makefile.am @@ -35,6 +35,7 @@ libMeshGui_la_SOURCES=\ PropertyEditorMesh.cpp \ RemoveComponents.cpp \ RemoveComponents.h \ + Segmentation.cpp \ SoFCIndexedFaceSet.cpp \ SoFCMeshObject.cpp \ ViewProvider.cpp \ @@ -48,6 +49,7 @@ libMeshGui_la_SOURCES=\ include_HEADERS=\ PropertyEditorMesh.h \ + Segmentation.h \ SoFCIndexedFaceSet.h \ SoFCMeshObject.h \ ViewProvider.h \ From a94897b92e98e325220e75ffbda9238ed0f84f55 Mon Sep 17 00:00:00 2001 From: msocorcim Date: Sun, 20 May 2012 23:01:07 -0400 Subject: [PATCH 243/351] Replace Gui text View->Display mode with View->Document window --- src/Gui/CommandView.cpp | 2 +- src/Gui/DlgDisplayProperties.ui | 2 +- src/Gui/Language/FreeCAD.ts | 2 +- src/Gui/Language/FreeCAD_af.ts | 4 ++-- src/Gui/Language/FreeCAD_de.ts | 4 ++-- src/Gui/Language/FreeCAD_es.ts | 4 ++-- src/Gui/Language/FreeCAD_fi.ts | 4 ++-- src/Gui/Language/FreeCAD_fr.ts | 4 ++-- src/Gui/Language/FreeCAD_hr.ts | 4 ++-- src/Gui/Language/FreeCAD_hu.ts | 4 ++-- src/Gui/Language/FreeCAD_it.ts | 4 ++-- src/Gui/Language/FreeCAD_ja.ts | 4 ++-- src/Gui/Language/FreeCAD_nl.ts | 4 ++-- src/Gui/Language/FreeCAD_no.ts | 4 ++-- src/Gui/Language/FreeCAD_pl.ts | 4 ++-- src/Gui/Language/FreeCAD_pt.ts | 4 ++-- src/Gui/Language/FreeCAD_ru.ts | 4 ++-- src/Gui/Language/FreeCAD_se.ts | 4 ++-- src/Gui/Language/FreeCAD_uk.ts | 4 ++-- src/Gui/Language/FreeCAD_zh.ts | 4 ++-- src/Gui/TaskView/TaskAppearance.ui | 2 +- 21 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 1de74b6c30..712131d68b 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -1172,7 +1172,7 @@ StdViewDockUndockFullscreen::StdViewDockUndockFullscreen() : Command("Std_ViewDockUndockFullscreen") { sGroup = QT_TR_NOOP("Standard-View"); - sMenuText = QT_TR_NOOP("Display mode"); + sMenuText = QT_TR_NOOP("Document window"); sToolTipText= QT_TR_NOOP("Display the active view either in fullscreen, in undocked or docked mode"); sWhatsThis = "Std_ViewDockUndockFullscreen"; sStatusTip = QT_TR_NOOP("Display the active view either in fullscreen, in undocked or docked mode"); diff --git a/src/Gui/DlgDisplayProperties.ui b/src/Gui/DlgDisplayProperties.ui index 5143bf2a8a..58f4b62358 100644 --- a/src/Gui/DlgDisplayProperties.ui +++ b/src/Gui/DlgDisplayProperties.ui @@ -34,7 +34,7 @@ - Display mode: + Document window: diff --git a/src/Gui/Language/FreeCAD.ts b/src/Gui/Language/FreeCAD.ts index 3b452a8607..024b5a7f1b 100644 --- a/src/Gui/Language/FreeCAD.ts +++ b/src/Gui/Language/FreeCAD.ts @@ -5302,7 +5302,7 @@ You either have to finish or cancel the editing in the task panel. - Display mode + Document window diff --git a/src/Gui/Language/FreeCAD_af.ts b/src/Gui/Language/FreeCAD_af.ts index 052ea4d8c1..4ba0e26ca1 100644 --- a/src/Gui/Language/FreeCAD_af.ts +++ b/src/Gui/Language/FreeCAD_af.ts @@ -5317,8 +5317,8 @@ You either have to finish or cancel the editing in the task panel. Standaardaansig - Display mode - Vertoningsmodus + Document window + Dokument venster Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_de.ts b/src/Gui/Language/FreeCAD_de.ts index be807a1b7e..79e5131c29 100644 --- a/src/Gui/Language/FreeCAD_de.ts +++ b/src/Gui/Language/FreeCAD_de.ts @@ -5325,8 +5325,8 @@ Sie müssen entweder den Bearbeitungsvorgang fertigstellen oder mittels des Aufg Standardansicht - Display mode - Anzeige-Modus + Document window + Dokumentfenster Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_es.ts b/src/Gui/Language/FreeCAD_es.ts index 173822aa00..089b96e95d 100644 --- a/src/Gui/Language/FreeCAD_es.ts +++ b/src/Gui/Language/FreeCAD_es.ts @@ -5323,8 +5323,8 @@ Tienes que finzalizar o cancelar la edición en el panel de tareas.Vista estándar - Display mode - Modo de visualización + Document window + Ventana de documento Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_fi.ts b/src/Gui/Language/FreeCAD_fi.ts index dab907d81d..ec9cde9a05 100644 --- a/src/Gui/Language/FreeCAD_fi.ts +++ b/src/Gui/Language/FreeCAD_fi.ts @@ -5314,8 +5314,8 @@ You either have to finish or cancel the editing in the task panel. Standardi-Näkymä - Display mode - Näyttötila + Document window + Asiakirjan ikkuna Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_fr.ts b/src/Gui/Language/FreeCAD_fr.ts index c65a10cdf9..f665da6bd2 100644 --- a/src/Gui/Language/FreeCAD_fr.ts +++ b/src/Gui/Language/FreeCAD_fr.ts @@ -5319,8 +5319,8 @@ You either have to finish or cancel the editing in the task panel. Vue standard - Display mode - Mode d'affichage + Document window + Fenêtre de document Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_hr.ts b/src/Gui/Language/FreeCAD_hr.ts index 790f209822..11e5c702ba 100644 --- a/src/Gui/Language/FreeCAD_hr.ts +++ b/src/Gui/Language/FreeCAD_hr.ts @@ -5311,8 +5311,8 @@ You either have to finish or cancel the editing in the task panel. Standardni pogled - Display mode - NaÄin prikaza + Document window + Dokument prozor Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_hu.ts b/src/Gui/Language/FreeCAD_hu.ts index cf6433c3a8..74d0db3b56 100644 --- a/src/Gui/Language/FreeCAD_hu.ts +++ b/src/Gui/Language/FreeCAD_hu.ts @@ -5318,8 +5318,8 @@ You either have to finish or cancel the editing in the task panel. Standard-nézet - Display mode - Megjelenítési mód + Document window + Dokumentum ablak Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_it.ts b/src/Gui/Language/FreeCAD_it.ts index 64b5bd7c3a..cb266b1d00 100644 --- a/src/Gui/Language/FreeCAD_it.ts +++ b/src/Gui/Language/FreeCAD_it.ts @@ -5325,8 +5325,8 @@ You either have to finish or cancel the editing in the task panel. Vista standard - Display mode - Modalità di visualizzazione + Document window + Finestra del documento Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_ja.ts b/src/Gui/Language/FreeCAD_ja.ts index 5773577fd4..0406284a60 100644 --- a/src/Gui/Language/FreeCAD_ja.ts +++ b/src/Gui/Language/FreeCAD_ja.ts @@ -5319,8 +5319,8 @@ You either have to finish or cancel the editing in the task panel. 標準ビュー - Display mode - 表示モード + Document window + ドキュメントウィンドウ Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_nl.ts b/src/Gui/Language/FreeCAD_nl.ts index 0a57b99f55..ea7ae833c4 100644 --- a/src/Gui/Language/FreeCAD_nl.ts +++ b/src/Gui/Language/FreeCAD_nl.ts @@ -5314,8 +5314,8 @@ You either have to finish or cancel the editing in the task panel. Standaard-aanzicht - Display mode - Weergavemodus + Document window + Documentvenster Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_no.ts b/src/Gui/Language/FreeCAD_no.ts index 948c209da5..56087e8fac 100644 --- a/src/Gui/Language/FreeCAD_no.ts +++ b/src/Gui/Language/FreeCAD_no.ts @@ -5315,8 +5315,8 @@ You either have to finish or cancel the editing in the task panel. Standardvisning - Display mode - Visningsmodus + Document window + Dokument-vinduet Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_pl.ts b/src/Gui/Language/FreeCAD_pl.ts index 064d5e00ea..0a428556ba 100644 --- a/src/Gui/Language/FreeCAD_pl.ts +++ b/src/Gui/Language/FreeCAD_pl.ts @@ -5305,8 +5305,8 @@ You either have to finish or cancel the editing in the task panel. Normalny widok - Display mode - Tryb wyÅ›wietlania + Document window + Okno dokumentu Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_pt.ts b/src/Gui/Language/FreeCAD_pt.ts index 2ed9d6bf6b..fd0cde9227 100644 --- a/src/Gui/Language/FreeCAD_pt.ts +++ b/src/Gui/Language/FreeCAD_pt.ts @@ -5307,8 +5307,8 @@ You either have to finish or cancel the editing in the task panel. Vista padrão - Display mode - Modo de exibição + Document window + Janela do documento Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_ru.ts b/src/Gui/Language/FreeCAD_ru.ts index 40667e37ac..b1e39e830f 100644 --- a/src/Gui/Language/FreeCAD_ru.ts +++ b/src/Gui/Language/FreeCAD_ru.ts @@ -5310,8 +5310,8 @@ You either have to finish or cancel the editing in the task panel. Стандартный вид - Display mode - Режим Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ + Document window + окно документа Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_se.ts b/src/Gui/Language/FreeCAD_se.ts index 1f51d82428..9b777ffac2 100644 --- a/src/Gui/Language/FreeCAD_se.ts +++ b/src/Gui/Language/FreeCAD_se.ts @@ -5324,8 +5324,8 @@ You either have to finish or cancel the editing in the task panel. Standardvy - Display mode - Visningsläge + Document window + Dokumentfönstret Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_uk.ts b/src/Gui/Language/FreeCAD_uk.ts index b9dbe90997..5e0b27cb6c 100644 --- a/src/Gui/Language/FreeCAD_uk.ts +++ b/src/Gui/Language/FreeCAD_uk.ts @@ -5325,8 +5325,8 @@ You either have to finish or cancel the editing in the task panel. Стандартні виглÑди - Display mode - Режим показу + Document window + вікно документа Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/Language/FreeCAD_zh.ts b/src/Gui/Language/FreeCAD_zh.ts index 18e102a1ee..a63f7f181a 100644 --- a/src/Gui/Language/FreeCAD_zh.ts +++ b/src/Gui/Language/FreeCAD_zh.ts @@ -5313,8 +5313,8 @@ You either have to finish or cancel the editing in the task panel. 标准视图 - Display mode - æ˜¾ç¤ºæ¨¡å¼ + Document window + æ–‡æ¡£çª—å£ Display the active view either in fullscreen, in undocked or docked mode diff --git a/src/Gui/TaskView/TaskAppearance.ui b/src/Gui/TaskView/TaskAppearance.ui index 7955494699..e775af457c 100644 --- a/src/Gui/TaskView/TaskAppearance.ui +++ b/src/Gui/TaskView/TaskAppearance.ui @@ -33,7 +33,7 @@ - Display mode: + Document window: From a87f55812575975a9328c0abc29381b96c11cf3f Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 14:08:57 +0200 Subject: [PATCH 244/351] Workaround for linker error with MSVC --- src/Gui/Tree.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 2c5f0ea151..ba3672d8cd 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -431,6 +431,7 @@ void TreeWidget::dropEvent(QDropEvent *event) // Open command App::Document* doc = grp->getDocument(); Gui::Document* gui = Gui::Application::Instance->getDocument(doc); + Base::Type DOGPython = Base::Type::fromName("App::DocumentObjectGroupPython"); gui->openCommand("Move object"); for (QList::Iterator it = items.begin(); it != items.end(); ++it) { // get document object @@ -441,7 +442,7 @@ void TreeWidget::dropEvent(QDropEvent *event) if (par) { // allow an object to be in one group only QString cmd; - if (par->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + if (par->getTypeId().isDerivedFrom(DOGPython)) { // if this is a python group, call the method of its Proxy cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.removeObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") @@ -460,7 +461,7 @@ void TreeWidget::dropEvent(QDropEvent *event) // build Python command for execution QString cmd; - if (grp->getTypeId().isDerivedFrom(App::DocumentObjectGroupPython::getClassTypeId())) { + if (grp->getTypeId().isDerivedFrom(DOGPython)) { cmd = QString::fromAscii("App.getDocument(\"%1\").getObject(\"%2\").Proxy.addObject(" "App.getDocument(\"%1\").getObject(\"%3\"))") .arg(QString::fromAscii(doc->getName())) From d6b6f6b37956a6f9a4f98745c2715ea00c5aba0c Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 15:02:51 +0200 Subject: [PATCH 245/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.cpp | 26 +++++--------- src/Mod/Mesh/App/Core/Segmentation.h | 28 ++++++++++----- src/Mod/Mesh/App/Mesh.cpp | 50 +++++++------------------- src/Mod/Mesh/App/MeshPy.xml | 6 ++-- src/Mod/Mesh/App/MeshPyImp.cpp | 7 ++-- src/Mod/Mesh/Gui/Segmentation.cpp | 2 +- src/Mod/Mesh/Gui/Segmentation.ui | 23 ++++++++++-- 7 files changed, 67 insertions(+), 75 deletions(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 2e86fdb176..01d99fb11f 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -108,22 +108,12 @@ bool MeshCurvatureCylindricalSegment::TestFacet (const MeshFacet &rclFacet) cons { for (int i=0; i<3; i++) { const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; - if (ci.fMaxCurvature > ci.fMinCurvature) { - // convexe - if (fabs(ci.fMinCurvature) > tolerance) - return false; - float diff = ci.fMaxCurvature - curvature; - if (fabs(diff) > tolerance) - return false; - } - else { - // concave - if (fabs(ci.fMaxCurvature) > tolerance) - return false; - float diff = ci.fMinCurvature + curvature; - if (fabs(diff) > tolerance) - return false; - } + float fMax = std::max(fabs(ci.fMaxCurvature), fabs(ci.fMinCurvature)); + float fMin = std::min(fabs(ci.fMaxCurvature), fabs(ci.fMinCurvature)); + if (fMin > toleranceMin) + return false; + if (fabs(fMax - curvature) > toleranceMax) + return false; } return true; @@ -151,9 +141,9 @@ bool MeshCurvatureFreeformSegment::TestFacet (const MeshFacet &rclFacet) const { for (int i=0; i<3; i++) { const CurvatureInfo& ci = info[rclFacet._aulPoints[i]]; - if (fabs(ci.fMinCurvature-c2) > tolerance) + if (fabs(ci.fMinCurvature-c2) > toleranceMin) return false; - if (fabs(ci.fMaxCurvature-c1) > tolerance) + if (fabs(ci.fMaxCurvature-c1) > toleranceMax) return false; } diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index 561385c1c1..c894147adf 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -84,53 +84,63 @@ protected: class MeshExport MeshCurvatureSurfaceSegment : public MeshSurfaceSegment { public: - MeshCurvatureSurfaceSegment(const std::vector& ci, unsigned long minFacets, float tol) - : MeshSurfaceSegment(minFacets), info(ci), tolerance(tol) {} + MeshCurvatureSurfaceSegment(const std::vector& ci, unsigned long minFacets) + : MeshSurfaceSegment(minFacets), info(ci) {} protected: const std::vector& info; - float tolerance; }; class MeshExport MeshCurvaturePlanarSegment : public MeshCurvatureSurfaceSegment { public: MeshCurvaturePlanarSegment(const std::vector& ci, unsigned long minFacets, float tol) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol) {} + : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; + +private: + float tolerance; }; class MeshExport MeshCurvatureCylindricalSegment : public MeshCurvatureSurfaceSegment { public: - MeshCurvatureCylindricalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + MeshCurvatureCylindricalSegment(const std::vector& ci, unsigned long minFacets, + float tolMin, float tolMax, float radius) + : MeshCurvatureSurfaceSegment(ci, minFacets), toleranceMin(tolMin), toleranceMax(tolMax) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; private: float curvature; + float toleranceMin; + float toleranceMax; }; class MeshExport MeshCurvatureSphericalSegment : public MeshCurvatureSurfaceSegment { public: MeshCurvatureSphericalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol) { curvature = 1/radius;} + : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; private: float curvature; + float tolerance; }; class MeshExport MeshCurvatureFreeformSegment : public MeshCurvatureSurfaceSegment { public: - MeshCurvatureFreeformSegment(const std::vector& ci, unsigned long minFacets, float tol, float c1, float c2) - : MeshCurvatureSurfaceSegment(ci, minFacets, tol), c1(c1), c2(c2) {} + MeshCurvatureFreeformSegment(const std::vector& ci, unsigned long minFacets, + float tolMin, float tolMax, float c1, float c2) + : MeshCurvatureSurfaceSegment(ci, minFacets), c1(c1), c2(c2), + toleranceMin(tolMin), toleranceMax(tolMax) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; private: float c1, c2; + float toleranceMin; + float toleranceMax; }; class MeshExport MeshSurfaceVisitor : public MeshFacetVisitor diff --git a/src/Mod/Mesh/App/Mesh.cpp b/src/Mod/Mesh/App/Mesh.cpp index 89f85856ad..dec5da73bc 100644 --- a/src/Mod/Mesh/App/Mesh.cpp +++ b/src/Mod/Mesh/App/Mesh.cpp @@ -44,6 +44,7 @@ #include "Core/TopoAlgorithm.h" #include "Core/Evaluation.h" #include "Core/Degeneration.h" +#include "Core/Segmentation.h" #include "Core/SetOperations.h" #include "Core/Visitor.h" @@ -1426,48 +1427,21 @@ std::vector MeshObject::getSegmentsFromType(MeshObject::Type type, cons float dev, unsigned long minFacets) const { std::vector segm; - unsigned long startFacet; if (this->_kernel.CountFacets() == 0) return segm; - // reset VISIT flags - MeshCore::MeshAlgorithm cAlgo(this->_kernel); - if (aSegment.isEmpty()) { - cAlgo.ResetFacetFlag(MeshCore::MeshFacet::VISIT); + MeshCore::MeshSegmentAlgorithm finder(this->_kernel); + MeshCore::MeshDistanceSurfaceSegment* surf; + surf = new MeshCore::MeshDistancePlanarSegment(this->_kernel, minFacets, dev); + std::vector surfaces; + surfaces.push_back(surf); + finder.FindSegments(surfaces); + + const std::vector& data = surf->GetSegments(); + for (std::vector::const_iterator it = data.begin(); it != data.end(); ++it) { + segm.push_back(Segment(const_cast(this), *it, false)); } - else { - cAlgo.SetFacetFlag(MeshCore::MeshFacet::VISIT); - cAlgo.ResetFacetsFlag(aSegment.getIndices(), MeshCore::MeshFacet::VISIT); - } - - const MeshCore::MeshFacetArray& rFAry = this->_kernel.GetFacets(); - MeshCore::MeshFacetArray::_TConstIterator iTri = rFAry.begin(); - MeshCore::MeshFacetArray::_TConstIterator iBeg = rFAry.begin(); - MeshCore::MeshFacetArray::_TConstIterator iEnd = rFAry.end(); - - // start from the first not visited facet - cAlgo.CountFacetFlag(MeshCore::MeshFacet::VISIT); - iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), - MeshCore::MeshFacet::VISIT)); - startFacet = iTri - iBeg; - - while (startFacet != ULONG_MAX) { - // collect all facets of the same geometry - std::vector indices; - indices.push_back(startFacet); - MeshCore::MeshPlaneVisitor pv(this->_kernel, startFacet, dev, indices); - this->_kernel.VisitNeighbourFacets(pv, startFacet); - - iTri = std::find_if(iTri, iEnd, std::bind2nd(MeshCore::MeshIsNotFlag(), - MeshCore::MeshFacet::VISIT)); - if (iTri < iEnd) - startFacet = iTri - iBeg; - else - startFacet = ULONG_MAX; - if (indices.size() > minFacets) - segm.push_back(Segment(const_cast(this), indices, false)); - } - + delete surf; return segm; } diff --git a/src/Mod/Mesh/App/MeshPy.xml b/src/Mod/Mesh/App/MeshPy.xml index f29a59730a..116979807f 100644 --- a/src/Mod/Mesh/App/MeshPy.xml +++ b/src/Mod/Mesh/App/MeshPy.xml @@ -382,10 +382,10 @@ plane if none of its neighours is coplanar. getSegmentsByCurvature(list) -> list The argument list gives a list if tuples where it defines the preferred maximum curvature, -the preferred minumum curvature, the tolerance and the number of minimum faces for the segment. +the preferred minumum curvature, the tolerances and the number of minimum faces for the segment. Example: -c=(1.0, 0.0, 0.1, 500) # search for a cylinder with radius 1.0 -p=(0.0, 0.0, 0.1, 500) # search for a plane +c=(1.0, 0.0, 0.1, 0.1, 500) # search for a cylinder with radius 1.0 +p=(0.0, 0.0, 0.1, 0.1, 500) # search for a plane mesh.getSegmentsByCurvature([c,p]) diff --git a/src/Mod/Mesh/App/MeshPyImp.cpp b/src/Mod/Mesh/App/MeshPyImp.cpp index dd1f0e3e10..a2a1e6302d 100644 --- a/src/Mod/Mesh/App/MeshPyImp.cpp +++ b/src/Mod/Mesh/App/MeshPyImp.cpp @@ -1399,9 +1399,10 @@ PyObject* MeshPy::getSegmentsByCurvature(PyObject *args) Py::Tuple t(*it); float c1 = (float)Py::Float(t[0]); float c2 = (float)Py::Float(t[1]); - float tol = (float)Py::Float(t[2]); - int num = (int)Py::Int(t[3]); - segm.push_back(new MeshCore::MeshCurvatureFreeformSegment(meshCurv.GetCurvature(), num, tol, c1, c2)); + float tol1 = (float)Py::Float(t[2]); + float tol2 = (float)Py::Float(t[3]); + int num = (int)Py::Int(t[4]); + segm.push_back(new MeshCore::MeshCurvatureFreeformSegment(meshCurv.GetCurvature(), num, tol1, tol2, c1, c2)); } finder.FindSegments(segm); diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp index 962d65f2e5..223479c569 100644 --- a/src/Mod/Mesh/Gui/Segmentation.cpp +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -76,7 +76,7 @@ void Segmentation::accept() std::vector segm; if (ui->groupBoxCyl->isChecked()) { segm.push_back(new MeshCore::MeshCurvatureCylindricalSegment - (meshCurv.GetCurvature(), ui->numCyl->value(), ui->tolCyl->value(), ui->radCyl->value())); + (meshCurv.GetCurvature(), ui->numCyl->value(), ui->tol1Cyl->value(), ui->tol2Cyl->value(), ui->radCyl->value())); } if (ui->groupBoxSph->isChecked()) { segm.push_back(new MeshCore::MeshCurvatureSphericalSegment diff --git a/src/Mod/Mesh/Gui/Segmentation.ui b/src/Mod/Mesh/Gui/Segmentation.ui index 129c89873c..b6ce13bd86 100644 --- a/src/Mod/Mesh/Gui/Segmentation.ui +++ b/src/Mod/Mesh/Gui/Segmentation.ui @@ -106,12 +106,12 @@ - Tolerance + Tolerance (Flat) - + 0.100000000000000 @@ -121,13 +121,30 @@ + + + Tolerance (Curved) + + + + + + + 0.100000000000000 + + + 0.100000000000000 + + + + Minimum number of faces - + 100000 From 87f1e93feaf208561e1bd190d7661e9791f1b9bd Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 15:53:46 +0200 Subject: [PATCH 246/351] Mesh segmentation --- src/Mod/Mesh/App/Core/Segmentation.h | 6 ++++++ src/Mod/Mesh/Gui/Segmentation.cpp | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index c894147adf..1b29f4bff9 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -41,6 +41,7 @@ public: : minFacets(minFacets) {} virtual ~MeshSurfaceSegment() {} virtual bool TestFacet (const MeshFacet &rclFacet) const = 0; + virtual const char* GetType() const = 0; virtual void Initialize(unsigned long); virtual void AddFacet(const MeshFacet& rclFacet); void AddSegment(const std::vector&); @@ -70,6 +71,7 @@ public: MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol); virtual ~MeshDistancePlanarSegment(); bool TestFacet (const MeshFacet& rclFacet) const; + const char* GetType() const { return "Plane"; } void Initialize(unsigned long); void AddFacet(const MeshFacet& rclFacet); @@ -97,6 +99,7 @@ public: MeshCurvaturePlanarSegment(const std::vector& ci, unsigned long minFacets, float tol) : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Plane"; } private: float tolerance; @@ -109,6 +112,7 @@ public: float tolMin, float tolMax, float radius) : MeshCurvatureSurfaceSegment(ci, minFacets), toleranceMin(tolMin), toleranceMax(tolMax) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Cylinder"; } private: float curvature; @@ -122,6 +126,7 @@ public: MeshCurvatureSphericalSegment(const std::vector& ci, unsigned long minFacets, float tol, float radius) : MeshCurvatureSurfaceSegment(ci, minFacets), tolerance(tol) { curvature = 1/radius;} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Sphere"; } private: float curvature; @@ -136,6 +141,7 @@ public: : MeshCurvatureSurfaceSegment(ci, minFacets), c1(c1), c2(c2), toleranceMin(tolMin), toleranceMax(tolMax) {} virtual bool TestFacet (const MeshFacet &rclFacet) const; + virtual const char* GetType() const { return "Freeform"; } private: float c1, c2; diff --git a/src/Mod/Mesh/Gui/Segmentation.cpp b/src/Mod/Mesh/Gui/Segmentation.cpp index 223479c569..de2b81d48e 100644 --- a/src/Mod/Mesh/Gui/Segmentation.cpp +++ b/src/Mod/Mesh/Gui/Segmentation.cpp @@ -24,12 +24,14 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include #endif #include "Segmentation.h" #include "ui_Segmentation.h" #include #include +#include #include #include @@ -89,18 +91,32 @@ void Segmentation::accept() finder.FindSegments(segm); App::Document* document = App::GetApplication().getActiveDocument(); + document->openTransaction("Segmentation"); + + std::string internalname = "Segments_"; + internalname += myMesh->getNameInDocument(); + App::DocumentObjectGroup* group = static_cast(document->addObject + ("App::DocumentObjectGroup", internalname.c_str())); + std::string labelname = "Segments "; + labelname += myMesh->Label.getValue(); + group->Label.setValue(labelname); for (std::vector::iterator it = segm.begin(); it != segm.end(); ++it) { const std::vector& data = (*it)->GetSegments(); for (std::vector::const_iterator jt = data.begin(); jt != data.end(); ++jt) { Mesh::MeshObject* segment = mesh->meshFromSegment(*jt); - Mesh::Feature* feaSegm = static_cast(document->addObject("Mesh::Feature", "Segment")); + Mesh::Feature* feaSegm = static_cast(group->addObject("Mesh::Feature", "Segment")); Mesh::MeshObject* feaMesh = feaSegm->Mesh.startEditing(); feaMesh->swap(*segment); feaSegm->Mesh.finishEditing(); delete segment; + + std::stringstream label; + label << feaSegm->Label.getValue() << " (" << (*it)->GetType() << ")"; + feaSegm->Label.setValue(label.str()); } delete (*it); } + document->commitTransaction(); } void Segmentation::changeEvent(QEvent *e) From 27de3f76f4c400ba00e1178b175b1173f07b0217 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 21 May 2012 18:27:30 +0200 Subject: [PATCH 247/351] 0000712: Cad Navigation Zoom with Ctrl + causes shapes to pan off screen --- src/Gui/CommandView.cpp | 16 +++------------- src/Gui/NavigationStyle.cpp | 10 ++++++++++ src/Gui/NavigationStyle.h | 2 ++ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Gui/CommandView.cpp b/src/Gui/CommandView.cpp index 712131d68b..33da94c7c1 100644 --- a/src/Gui/CommandView.cpp +++ b/src/Gui/CommandView.cpp @@ -59,6 +59,7 @@ #include "DemoMode.h" #include "TextureMapping.h" #include "Utilities.h" +#include "NavigationStyle.h" #include #include @@ -1817,13 +1818,7 @@ void StdViewZoomIn::activated(int iMsg) View3DInventor* view = qobject_cast(getMainWindow()->activeWindow()); if ( view ) { View3DInventorViewer* viewer = view->getViewer(); - - // send an event to the GL widget to use the internal View3DInventorViewer::zoom() method - // do only one step to zoom in - SoMouseButtonEvent e; - e.setButton(SoMouseButtonEvent::BUTTON5); - e.setState(SoMouseButtonEvent::DOWN); - viewer->sendSoEvent(&e); + viewer->navigationStyle()->zoomIn(); } } @@ -1857,12 +1852,7 @@ void StdViewZoomOut::activated(int iMsg) View3DInventor* view = qobject_cast(getMainWindow()->activeWindow()); if (view) { View3DInventorViewer* viewer = view->getViewer(); - // send an event to the GL widget to use the internal View3DInventorViewer::zoom() method - // do only one step to zoom out - SoMouseButtonEvent e; - e.setButton(SoMouseButtonEvent::BUTTON4); - e.setState(SoMouseButtonEvent::DOWN); - viewer->sendSoEvent(&e); + viewer->navigationStyle()->zoomOut(); } } diff --git a/src/Gui/NavigationStyle.cpp b/src/Gui/NavigationStyle.cpp index 192cb7ae5a..30f5ecf402 100644 --- a/src/Gui/NavigationStyle.cpp +++ b/src/Gui/NavigationStyle.cpp @@ -721,6 +721,16 @@ void NavigationStyle::zoomByCursor(const SbVec2f & thispos, const SbVec2f & prev zoom(viewer->getCamera(), (thispos[1] - prevpos[1]) * 10.0f/*20.0f*/); } +void NavigationStyle::zoomIn() +{ + zoom(viewer->getCamera(), -this->zoomStep); +} + +void NavigationStyle::zoomOut() +{ + zoom(viewer->getCamera(), this->zoomStep); +} + void NavigationStyle::doZoom(SoCamera* camera, SbBool forward, const SbVec2f& pos) { SbBool zoomAtCur = this->zoomAtCursor; diff --git a/src/Gui/NavigationStyle.h b/src/Gui/NavigationStyle.h index 7644a73403..b6d4e20e66 100644 --- a/src/Gui/NavigationStyle.h +++ b/src/Gui/NavigationStyle.h @@ -115,6 +115,8 @@ public: void setZoomStep(float); void setZoomAtCursor(SbBool); SbBool isZoomAtCursor() const; + void zoomIn(); + void zoomOut(); void updateAnimation(); void redraw(); From d3fecc2b5e3f3ae1a1994d5e24f9e3d94d24dab8 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 21 May 2012 22:35:18 -0300 Subject: [PATCH 248/351] unified yorik's email --- src/Mod/Draft/DraftGui.py | 2 +- src/Mod/Draft/Init.py | 2 +- src/Mod/Draft/InitGui.py | 2 +- src/Mod/Draft/draftlibs/fcgeo.py | 2 +- src/Mod/Draft/draftlibs/fcvec.py | 2 +- src/Mod/Draft/importDXF.py | 4 ++-- src/Mod/Draft/importOCA.py | 4 ++-- src/Mod/Draft/importSVG.py | 2 +- src/Mod/Draft/macros.py | 2 +- src/Tools/offlinedoc/buildpdf.py | 2 +- src/Tools/offlinedoc/buildqhelp.py | 2 +- src/Tools/offlinedoc/buildwikiindex.py | 2 +- src/Tools/offlinedoc/downloadwiki.py | 2 +- src/Tools/updateTranslations.py | 2 +- src/Tools/wiki2qhelp.py | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 02c6c57d4a..752abb76bc 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/Init.py b/src/Mod/Draft/Init.py index 5069e5fd67..47fd3dc985 100644 --- a/src/Mod/Draft/Init.py +++ b/src/Mod/Draft/Init.py @@ -1,6 +1,6 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 1bcbadbc8c..84d0b9b868 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -1,6 +1,6 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/draftlibs/fcgeo.py index bf9f53e185..ccacbf62c9 100755 --- a/src/Mod/Draft/draftlibs/fcgeo.py +++ b/src/Mod/Draft/draftlibs/fcgeo.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * #* Copyright (c) 2009, 2010 * -#* Yorik van Havre , Ken Cline * +#* Yorik van Havre , Ken Cline * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/draftlibs/fcvec.py b/src/Mod/Draft/draftlibs/fcvec.py index 0f3358cfc7..1f10a2c7ea 100644 --- a/src/Mod/Draft/draftlibs/fcvec.py +++ b/src/Mod/Draft/draftlibs/fcvec.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * #* Copyright (c) 2009, 2010 * -#* Yorik van Havre , Ken Cline * +#* Yorik van Havre , Ken Cline * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 97e01db7f2..2c0474f8ed 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -3,7 +3,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (GPL) * @@ -24,7 +24,7 @@ #*************************************************************************** __title__="FreeCAD Draft Workbench - DXF importer/exporter" -__author__ = "Yorik van Havre " +__author__ = "Yorik van Havre " __url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"] ''' diff --git a/src/Mod/Draft/importOCA.py b/src/Mod/Draft/importOCA.py index 6324ce7100..58131d8300 100644 --- a/src/Mod/Draft/importOCA.py +++ b/src/Mod/Draft/importOCA.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU General Public License (GPL) * @@ -22,7 +22,7 @@ #*************************************************************************** __title__="FreeCAD Draft Workbench - OCA importer/exporter" -__author__ = "Yorik van Havre " +__author__ = "Yorik van Havre " __url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"] ''' diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index 5de678d519..b49d4735c7 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -1,7 +1,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Mod/Draft/macros.py b/src/Mod/Draft/macros.py index a2668dad8c..2b106d19fc 100644 --- a/src/Mod/Draft/macros.py +++ b/src/Mod/Draft/macros.py @@ -1,6 +1,6 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/buildpdf.py b/src/Tools/offlinedoc/buildpdf.py index ff9f53a15d..c6dbf246fd 100755 --- a/src/Tools/offlinedoc/buildpdf.py +++ b/src/Tools/offlinedoc/buildpdf.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/buildqhelp.py b/src/Tools/offlinedoc/buildqhelp.py index 4325ed9152..77fa1bcaef 100755 --- a/src/Tools/offlinedoc/buildqhelp.py +++ b/src/Tools/offlinedoc/buildqhelp.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/buildwikiindex.py b/src/Tools/offlinedoc/buildwikiindex.py index f7cee86c8b..e685aed48a 100755 --- a/src/Tools/offlinedoc/buildwikiindex.py +++ b/src/Tools/offlinedoc/buildwikiindex.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/offlinedoc/downloadwiki.py b/src/Tools/offlinedoc/downloadwiki.py index 50f88a2eb4..4fc0bdadf9 100755 --- a/src/Tools/offlinedoc/downloadwiki.py +++ b/src/Tools/offlinedoc/downloadwiki.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Lesser General Public License (LGPL) * diff --git a/src/Tools/updateTranslations.py b/src/Tools/updateTranslations.py index 5e3e991beb..695a2f6335 100755 --- a/src/Tools/updateTranslations.py +++ b/src/Tools/updateTranslations.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Library General Public License (LGPL) * diff --git a/src/Tools/wiki2qhelp.py b/src/Tools/wiki2qhelp.py index 09c47139aa..dc52f38152 100755 --- a/src/Tools/wiki2qhelp.py +++ b/src/Tools/wiki2qhelp.py @@ -2,7 +2,7 @@ #*************************************************************************** #* * -#* Copyright (c) 2009 Yorik van Havre * +#* Copyright (c) 2009 Yorik van Havre * #* * #* This program is free software; you can redistribute it and/or modify * #* it under the terms of the GNU Library General Public License (LGPL) * From 335d6cdfdb673ff48525c97b363dae0d0f54b26b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 11:45:40 -0300 Subject: [PATCH 249/351] Renamed Draft fcvec and fcgeo modules Draft/draftlibs/fcvec becomes Draft/DraftVecUtils Draft/draftlibs/fcgeo becomes Draft/DraftGeomUtils --- src/Doc/sphinx/Draft.rst | 13 +- src/Mod/Arch/ArchAxis.py | 4 +- src/Mod/Arch/ArchCommands.py | 16 +- src/Mod/Arch/ArchRoof.py | 14 +- src/Mod/Arch/ArchSectionPlane.py | 8 +- src/Mod/Arch/ArchStructure.py | 12 +- src/Mod/Arch/ArchVRM.py | 29 +- src/Mod/Arch/ArchWall.py | 42 ++- src/Mod/Arch/ArchWindow.py | 12 +- src/Mod/Arch/importIFC.py | 5 +- src/Mod/Arch/importOBJ.py | 5 +- src/Mod/Draft/CMakeLists.txt | 4 +- src/Mod/Draft/Draft.py | 202 +++++++------- .../{draftlibs/fcgeo.py => DraftGeomUtils.py} | 0 src/Mod/Draft/DraftSnap.py | 42 ++- src/Mod/Draft/DraftTools.py | 251 +++++++++--------- src/Mod/Draft/DraftTrackers.py | 49 ++-- .../{draftlibs/fcvec.py => DraftVecUtils.py} | 0 src/Mod/Draft/Makefile.am | 4 +- src/Mod/Draft/WorkingPlane.py | 33 ++- src/Mod/Draft/importDXF.py | 70 ++--- src/Mod/Draft/importOCA.py | 13 +- src/Mod/Draft/importSVG.py | 32 ++- src/WindowsInstaller/ModDraft.wxi | 4 +- 24 files changed, 413 insertions(+), 451 deletions(-) rename src/Mod/Draft/{draftlibs/fcgeo.py => DraftGeomUtils.py} (100%) rename src/Mod/Draft/{draftlibs/fcvec.py => DraftVecUtils.py} (100%) diff --git a/src/Doc/sphinx/Draft.rst b/src/Doc/sphinx/Draft.rst index 2b41017809..4479028b14 100644 --- a/src/Doc/sphinx/Draft.rst +++ b/src/Doc/sphinx/Draft.rst @@ -12,10 +12,15 @@ The Draft module offer several convenient functions to work with simple objects. .. automodule:: DraftSnap :members: -The draftlibs contain two submodules, widely used throughout the Draft module: fcvec, which contains useful methods for dealing with vectors, and fcgeo, which offers many tools for working with Part shape objects. +The Draft module also contains two submodules, widely used throughout the Draft and Arch modules: DraftVecUtils, which contains useful methods for dealing with vectors, and DraftGeomUtils, which offers many tools for working with OpenCascade geometry. -.. automodule:: draftlibs.fcvec +.. automodule:: DraftVecUtils :members: -.. automodule:: draftlibs.fcgeo - :members: \ No newline at end of file +.. automodule:: DraftGeomUtils + :members: + +The Draft module also features a module that contains trackers, special objects made to display 3D temporary geometry in the 3D scene, that have no real existence in the FreeCAD document. + +.. automodule:: DraftTrackers + :members: diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index a56a50ff26..37cdf9f545 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -21,9 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,math - -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,math,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore, QtGui from pivy import coin diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 5802e5e0a6..2ebfad0d0b 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -170,7 +169,7 @@ def makeFace(wires,method=2,cleanup=False): # cleaning up rubbish in wires if cleanup: for i in range(len(wires)): - wires[i] = fcgeo.removeInterVertices(wires[i]) + wires[i] = DraftGeomUtils.removeInterVertices(wires[i]) print "garbage removed" for w in wires: # we assume that the exterior boundary is that one with @@ -210,8 +209,7 @@ def meshToShape(obj,mark=True): mark is True (default), non-solid objects will be marked in red''' name = obj.Name - import Part,MeshPart - from draftlibs import fcgeo + import Part, MeshPart, DraftGeomUtils if "Mesh" in obj.PropertiesList: faces = [] mesh = obj.Mesh @@ -249,12 +247,12 @@ def meshToShape(obj,mark=True): def removeShape(objs,mark=True): '''takes an arch object (wall or structure) built on a cubic shape, and removes the inner shape, keeping its length, width and height as parameters.''' - from draftlibs import fcgeo + import DraftGeomUtils if not isinstance(objs,list): objs = [objs] for obj in objs: - if fcgeo.isCubic(obj.Shape): - dims = fcgeo.getCubicDimensions(obj.Shape) + if DraftGeomUtils.isCubic(obj.Shape): + dims = DraftGeomUtils.getCubicDimensions(obj.Shape) if dims: name = obj.Name tp = Draft.getType(obj) @@ -270,7 +268,7 @@ def removeShape(objs,mark=True): length = dims[1] width = dims[2] v1 = Vector(length/2,0,0) - v2 = fcvec.neg(v1) + v2 = DraftVecUtils.neg(v1) v1 = dims[0].multVec(v1) v2 = dims[0].multVec(v2) line = Draft.makeLine(v1,v2) diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index 37d06b58e7..31515afbc8 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent, DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -104,8 +103,7 @@ class _Roof(ArchComponent.Component): self.createGeometry(obj) def createGeometry(self,obj): - import Part,math - from draftlibs import fcgeo + import Part, math, DraftGeomUtils pl = obj.Placement if obj.Base and obj.Face and obj.Angle: @@ -116,14 +114,14 @@ class _Roof(ArchComponent.Component): c = round(math.tan(math.radians(obj.Angle)),Draft.precision()) norm = f.normalAt(0,0) d = f.BoundBox.DiagonalLength - edges = fcgeo.sortEdges(f.Edges) + edges = DraftGeomUtils.sortEdges(f.Edges) l = len(edges) edges.append(edges[0]) shps = [] for i in range(l): - v = fcgeo.vec(fcgeo.angleBisection(edges[i],edges[i+1])) + v = DraftGeomUtils.vec(DraftGeomUtils.angleBisection(edges[i],edges[i+1])) v.normalize() - bis = v.getAngle(fcgeo.vec(edges[i])) + bis = v.getAngle(DraftGeomUtils.vec(edges[i])) delta = 1/math.cos(bis) v.multiply(delta) n = (FreeCAD.Vector(norm)).multiply(c) @@ -137,7 +135,7 @@ class _Roof(ArchComponent.Component): c = c.removeSplitter() if not c.isNull(): obj.Shape = c - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderRoof(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index d1c1ada501..59c8023827 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -21,11 +21,10 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,Drawing,math,Draft,ArchCommands +import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,Drawing,math,Draft,ArchCommands, DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore from pivy import coin -from draftlibs import fcvec class _CommandSectionPlane: @@ -176,8 +175,7 @@ class _ArchDrawingView: def updateSVG(self, obj,join=False): "encapsulates a svg fragment into a transformation node" - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils if hasattr(obj,"Source"): if obj.Source: if obj.Source.Objects: @@ -207,7 +205,7 @@ class _ArchDrawingView: base = shape.pop() for sh in shapes: base = base.fuse(sh) - svgf = Drawing.projectToSVG(base,fcvec.neg(direction)) + svgf = Drawing.projectToSVG(base,DraftVecUtils.neg(direction)) if svgf: svgf = svgf.replace('stroke-width="0.35"','stroke-width="' + str(linewidth) + 'px"') svg += svgf diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index cd87115ebc..2327ad7cac 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -99,7 +98,7 @@ class _Structure(ArchComponent.Component): def getAxisPoints(self,obj): "returns the gridpoints of linked axes" - from draftlibs import fcgeo + import DraftGeomUtils pts = [] if len(obj.Axes) == 1: for e in obj.Axes[0].Shape.Edges: @@ -109,12 +108,11 @@ class _Structure(ArchComponent.Component): set2 = obj.Axes[1].Shape.Edges for e1 in set1: for e2 in set2: - pts.extend(fcgeo.findIntersection(e1,e2)) + pts.extend(DraftGeomUtils.findIntersection(e1,e2)) return pts def createGeometry(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils # getting default values height = normal = None if obj.Length: @@ -187,7 +185,7 @@ class _Structure(ArchComponent.Component): obj.Shape = Part.makeCompound(fsh) else: obj.Shape = base - if not fcgeo.isNull(pl): obj.Placement = pl + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderStructure(ArchComponent.ViewProviderComponent): "A View Provider for the Structure object" diff --git a/src/Mod/Arch/ArchVRM.py b/src/Mod/Arch/ArchVRM.py index f7e5988abf..2de8ad0b3b 100644 --- a/src/Mod/Arch/ArchVRM.py +++ b/src/Mod/Arch/ArchVRM.py @@ -23,8 +23,7 @@ "The FreeCAD Arch Vector Rendering Module" -import FreeCAD,math,Part,ArchCommands -from draftlibs import fcvec,fcgeo +import FreeCAD,math,Part,ArchCommands,DraftVecUtils,DraftGeomUtils DEBUG = True # if we want debug messages MAXLOOP = 10 # the max number of loop before abort @@ -171,7 +170,7 @@ class Renderer: norm = face[0].normalAt(0,0) for w in face[0].Wires: verts = [] - edges = fcgeo.sortEdges(w.Edges) + edges = DraftGeomUtils.sortEdges(w.Edges) for e in edges: v = e.Vertexes[0].Point v = self.wp.getLocalCoords(v) @@ -196,7 +195,7 @@ class Renderer: wires = [] for w in face[0].Wires: verts = [] - edges = fcgeo.sortEdges(w.Edges) + edges = DraftGeomUtils.sortEdges(w.Edges) for e in edges: v = e.Vertexes[0].Point verts.append(FreeCAD.Vector(v.x,v.y,0)) @@ -239,11 +238,11 @@ class Renderer: FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)] for c in corners: dv = c.sub(placement.Base) - um1 = fcvec.project(dv,self.wp.u).Length + um1 = DraftVecUtils.project(dv,self.wp.u).Length um = max(um,um1) - vm1 = fcvec.project(dv,self.wp.v).Length + vm1 = DraftVecUtils.project(dv,self.wp.v).Length vm = max(vm,vm1) - wm1 = fcvec.project(dv,self.wp.axis).Length + wm1 = DraftVecUtils.project(dv,self.wp.axis).Length wm = max(wm,wm1) p1 = FreeCAD.Vector(-um,vm,0) p2 = FreeCAD.Vector(um,vm,0) @@ -252,7 +251,7 @@ class Renderer: cutface = Part.makePolygon([p1,p2,p3,p4,p1]) cutface = Part.Face(cutface) cutface.Placement = placement - cutnormal = fcvec.scaleTo(self.wp.axis,wm) + cutnormal = DraftVecUtils.scaleTo(self.wp.axis,wm) cutvolume = cutface.extrude(cutnormal) shapes = [] faces = [] @@ -265,7 +264,7 @@ class Renderer: faces.append([f]+sh[1:]) sec = sol.section(cutface) if sec.Edges: - wires = fcgeo.findWires(sec.Edges) + wires = DraftGeomUtils.findWires(sec.Edges) for w in wires: sec = Part.Face(w) sections.append([sec,fill]) @@ -313,7 +312,7 @@ class Renderer: # even so, faces can still overlap if their edges cross each other for e1 in face1[0].Edges: for e2 in face2[0].Edges: - if fcgeo.findIntersection(e1,e2): + if DraftGeomUtils.findIntersection(e1,e2): return True return False @@ -354,8 +353,8 @@ class Renderer: front = 0 for v in face1[0].Vertexes: dv = v.Point.sub(face2[0].Vertexes[0].Point) - dv = fcvec.project(dv,norm) - if fcvec.isNull(dv): + dv = DraftVecUtils.project(dv,norm) + if DraftVecUtils.isNull(dv): behind += 1 front += 1 else: @@ -377,8 +376,8 @@ class Renderer: front = 0 for v in face2[0].Vertexes: dv = v.Point.sub(face1[0].Vertexes[0].Point) - dv = fcvec.project(dv,norm) - if fcvec.isNull(dv): + dv = DraftVecUtils.project(dv,norm) + if DraftVecUtils.isNull(dv): behind += 1 front += 1 else: @@ -545,7 +544,7 @@ class Renderer: def getPathData(self,w): "Returns a SVG path data string from a 2D wire" - edges = fcgeo.sortEdges(w.Edges) + edges = DraftGeomUtils.sortEdges(w.Edges) v = edges[0].Vertexes[0].Point svg = 'M '+ str(v.x) +' '+ str(v.y) + ' ' for e in edges: diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 36c33e7a87..c26125136d 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore @@ -180,13 +179,13 @@ class _CommandWall: n = FreeCAD.DraftWorkingPlane.axis bv = point.sub(b) dv = bv.cross(n) - dv = fcvec.scaleTo(dv,self.Width/2) + dv = DraftVecUtils.scaleTo(dv,self.Width/2) if self.Align == "Center": self.tracker.update([b,point]) elif self.Align == "Left": self.tracker.update([b.add(dv),point.add(dv)]) else: - dv = fcvec.neg(dv) + dv = DraftVecUtils.neg(dv) self.tracker.update([b.add(dv),point.add(dv)]) def taskbox(self): @@ -275,10 +274,10 @@ class _Wall(ArchComponent.Component): f = w f = Part.Face(f) n = f.normalAt(0,0) - v1 = fcvec.scaleTo(n,width) + v1 = DraftVecUtils.scaleTo(n,width) f.translate(v1) - v2 = fcvec.neg(v1) - v2 = fcvec.scale(v1,-2) + v2 = DraftVecUtils.neg(v1) + v2 = DraftVecUtils.scale(v1,-2) f = f.extrude(v2) if delta: f.translate(delta) @@ -290,8 +289,7 @@ class _Wall(ArchComponent.Component): if not obj.Base: return - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils flat = False if hasattr(obj.ViewObject,"DisplayMode"): @@ -304,25 +302,25 @@ class _Wall(ArchComponent.Component): def getbase(wire): "returns a full shape from a base wire" - dvec = fcgeo.vec(wire.Edges[0]).cross(normal) + dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal) dvec.normalize() if obj.Align == "Left": dvec = dvec.multiply(width) - w2 = fcgeo.offsetWire(wire,dvec) - w1 = Part.Wire(fcgeo.sortEdges(wire.Edges)) - sh = fcgeo.bind(w1,w2) + w2 = DraftGeomUtils.offsetWire(wire,dvec) + w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges)) + sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Right": dvec = dvec.multiply(width) - dvec = fcvec.neg(dvec) - w2 = fcgeo.offsetWire(wire,dvec) - w1 = Part.Wire(fcgeo.sortEdges(wire.Edges)) - sh = fcgeo.bind(w1,w2) + dvec = DraftVecUtils.neg(dvec) + w2 = DraftGeomUtils.offsetWire(wire,dvec) + w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges)) + sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Center": dvec = dvec.multiply(width/2) - w1 = fcgeo.offsetWire(wire,dvec) - dvec = fcvec.neg(dvec) - w2 = fcgeo.offsetWire(wire,dvec) - sh = fcgeo.bind(w1,w2) + w1 = DraftGeomUtils.offsetWire(wire,dvec) + dvec = DraftVecUtils.neg(dvec) + w2 = DraftGeomUtils.offsetWire(wire,dvec) + sh = DraftGeomUtils.bind(w1,w2) # fixing self-intersections sh.fix(0.1,0,1) if height and (not flat): @@ -388,7 +386,7 @@ class _Wall(ArchComponent.Component): if base: obj.Shape = base - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderWall(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 2cdf513c91..35813ddfc8 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchComponent -from draftlibs import fcvec +import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore,QtGui @@ -109,8 +108,7 @@ class _Window(ArchComponent.Component): self.createGeometry(obj) def createGeometry(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils pl = obj.Placement if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): @@ -135,7 +133,7 @@ class _Window(ArchComponent.Component): norm = shape.normalAt(0,0) thk = float(obj.WindowParts[(i*5)+3]) if thk: - exv = fcvec.scaleTo(norm,thk) + exv = DraftVecUtils.scaleTo(norm,thk) shape = shape.extrude(exv) for w in wires: f = Part.Face(w) @@ -144,12 +142,12 @@ class _Window(ArchComponent.Component): if obj.WindowParts[(i*5)+4]: zof = float(obj.WindowParts[(i*5)+4]) if zof: - zov = fcvec.scaleTo(norm,zof) + zov = DraftVecUtils.scaleTo(norm,zof) shape.translate(zov) print shape shapes.append(shape) obj.Shape = Part.makeCompound(shapes) - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderWindow(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index 7a0cf8ae07..17dc3d1662 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import ifcReader, FreeCAD, Arch, Draft, os, sys, time, Part -from draftlibs import fcvec +import ifcReader, FreeCAD, Arch, Draft, os, sys, time, Part, DraftVecUtils __title__="FreeCAD IFC importer" __author__ = "Yorik van Havre" @@ -448,7 +447,7 @@ def getPlacement(entity): z = getVector(entity.Axis) y = z.cross(x) loc = getVector(entity.Location) - m = fcvec.getPlaneRotation(x,y,z) + m = DraftVecUtils.getPlaneRotation(x,y,z) pl = FreeCAD.Placement(m) pl.move(loc) elif entity.type == "IFCLOCALPLACEMENT": diff --git a/src/Mod/Arch/importOBJ.py b/src/Mod/Arch/importOBJ.py index e5ddca4348..4622e1adfb 100644 --- a/src/Mod/Arch/importOBJ.py +++ b/src/Mod/Arch/importOBJ.py @@ -21,8 +21,7 @@ #* * #*************************************************************************** -import FreeCAD -from draftlibs import fcgeo +import FreeCAD, DraftGeomUtils if open.__module__ == '__builtin__': pythonopen = open @@ -42,7 +41,7 @@ def getIndices(shape,offset): for f in shape.Faces: fi = "" # OCC vertices are unsorted. We need to sort in the right order... - edges = fcgeo.sortEdges(f.Wire.Edges) + edges = DraftGeomUtils.sortEdges(f.Wire.Edges) print edges for e in edges: print e.Vertexes[0].Point,e.Vertexes[1].Point diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index 99e27d0f96..3d12885618 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -7,6 +7,8 @@ SET(Draft_SRCS DraftGui.py DraftSnap.py DraftTrackers.py + DraftVecUtils.py + DraftGeomUtils.py WorkingPlane.py importDXF.py importOCA.py @@ -22,8 +24,6 @@ SET(DraftLibs_SRCS draftlibs/dxfImportObjects.py draftlibs/dxfLibrary.py draftlibs/dxfReader.py - draftlibs/fcgeo.py - draftlibs/fcvec.py draftlibs/__init__.py ) SOURCE_GROUP("draftlibs" FILES ${DraftLibs_SRCS}) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 0014a45130..300bc86923 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -54,9 +54,9 @@ How it works / how to extend: - DraftTools.py: Contains the user tools of the Draft module (the commands from the Draft menu), and a couple of helpers such as the "Trackers" (temporary geometry used while drawing) - - draftlibs/fcvec.py: a vector math library, contains functions that are not + - DraftVecUtils.py: a vector math library, contains functions that are not implemented in the standard FreeCAD vector - - draftlibs/fcgeo.py: a library of misc functions to manipulate shapes. + - DraftGeomUtils.py: a library of misc functions to manipulate shapes. The Draft.py contains everything to create geometry in the scene. You should start there if you intend to modify something. Then, the DraftTools @@ -72,9 +72,8 @@ How it works / how to extend: ''' # import FreeCAD modules -import FreeCAD, math, sys, os +import FreeCAD, math, sys, os, DraftVecUtils from FreeCAD import Vector -from draftlibs import fcvec from pivy import coin if FreeCAD.GuiUp: @@ -395,8 +394,8 @@ def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None ref = placement.multVec(FreeCAD.Vector(1,0,0)) v1 = (edge.Vertexes[0].Point).sub(edge.Curve.Center) v2 = (edge.Vertexes[-1].Point).sub(edge.Curve.Center) - a1 = -math.degrees(fcvec.angle(v1,ref)) - a2 = -math.degrees(fcvec.angle(v2,ref)) + a1 = -math.degrees(DraftVecUtils.angle(v1,ref)) + a2 = -math.degrees(DraftVecUtils.angle(v2,ref)) obj.FirstAngle = a1 obj.LastAngle = a2 else: @@ -514,15 +513,14 @@ def makeWire(pointslist,closed=False,placement=None,face=True,support=None): and last points are identical, the wire is closed. If face is true (and wire is closed), the wire will appear filled. Instead of a pointslist, you can also pass a Part Wire.''' - from draftlibs import fcgeo - import Part + import DraftGeomUtils, Part if not isinstance(pointslist,list): e = pointslist.Wires[0].Edges - pointslist = Part.Wire(fcgeo.sortEdges(e)) + pointslist = Part.Wire(DraftGeomUtils.sortEdges(e)) nlist = [] for v in pointslist.Vertexes: nlist.append(v.Point) - if fcgeo.isReallyClosed(pointslist): + if DraftGeomUtils.isReallyClosed(pointslist): closed = True pointslist = nlist print pointslist @@ -774,8 +772,7 @@ def fuse(object1,object2): the union of the 2 given objects. If the objects are coplanar, a special Draft Wire is used, otherwise we use a standard Part fuse.''' - from draftlibs import fcgeo - import Part + import DraftGeomUtils, Part # testing if we have holes: holes = False fshape = object1.Shape.fuse(object2.Shape) @@ -783,7 +780,7 @@ def fuse(object1,object2): for f in fshape.Faces: if len(f.Wires) > 1: holes = True - if fcgeo.isCoplanar(object1.Shape.fuse(object2.Shape).Faces) and not holes: + if DraftGeomUtils.isCoplanar(object1.Shape.fuse(object2.Shape).Faces) and not holes: obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Fusion") _Wire(obj) if gui: @@ -879,12 +876,12 @@ def array(objectslist,arg1,arg2,arg3,arg4=None): typecheck([(xvector,Vector), (yvector,Vector), (xnum,int), (ynum,int)], "rectArray") if not isinstance(objectslist,list): objectslist = [objectslist] for xcount in range(xnum): - currentxvector=fcvec.scale(xvector,xcount) + currentxvector=DraftVecUtils.scale(xvector,xcount) if not xcount==0: move(objectslist,currentxvector,True) for ycount in range(ynum): currentxvector=FreeCAD.Base.Vector(currentxvector) - currentyvector=currentxvector.add(fcvec.scale(yvector,ycount)) + currentyvector=currentxvector.add(DraftVecUtils.scale(yvector,ycount)) if not ycount==0: move(objectslist,currentyvector,True) def polarArray(objectslist,center,angle,num): @@ -918,7 +915,7 @@ def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False) newobj = obj if (obj.isDerivedFrom("Part::Feature")): shape = obj.Shape.copy() - shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) + shape.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), angle) newobj.Shape = shape elif (obj.isDerivedFrom("App::Annotation")): if axis.normalize() == Vector(1,0,0): @@ -939,7 +936,7 @@ def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False) elif hasattr(obj,"Placement"): shape = Part.Shape() shape.Placement = obj.Placement - shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle) + shape.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), angle) newobj.Placement = shape.Placement if copy: formatObject(newobj,obj) @@ -972,7 +969,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy sh = sh.transformGeometry(m) corr = Vector(center.x,center.y,center.z) corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(center)) + corr = DraftVecUtils.neg(corr.sub(center)) sh.translate(corr) if getType(obj) == "Rectangle": p = [] @@ -982,8 +979,8 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy diag = p[2].sub(p[0]) bb = p[1].sub(p[0]) bh = p[3].sub(p[0]) - nb = fcvec.project(diag,bb) - nh = fcvec.project(diag,bh) + nb = DraftVecUtils.project(diag,bb) + nh = DraftVecUtils.project(diag,bh) if obj.Length < 0: l = -nb.Length else: l = nb.Length if obj.Height < 0: h = -nh.Length @@ -1016,7 +1013,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy obj.Scale = delta corr = Vector(center.x,center.y,center.z) corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(center)) + corr = DraftVecUtils.neg(corr.sub(center)) p = obj.Placement p.move(corr) obj.Placement = p @@ -1037,8 +1034,7 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): and the offsetted wires will be bound by their endpoints, forming a face if sym is True, bind must be true too, and the offset is made on both sides, the total width being the given delta length.''' - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils def getRect(p,obj): "returns length,heigh,placement" @@ -1047,8 +1043,8 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): diag = p[2].sub(p[0]) bb = p[1].sub(p[0]) bh = p[3].sub(p[0]) - nb = fcvec.project(diag,bb) - nh = fcvec.project(diag,bh) + nb = DraftVecUtils.project(diag,bb) + nh = DraftVecUtils.project(diag,bh) if obj.Length < 0: l = -nb.Length else: l = nb.Length if obj.Height < 0: h = -nh.Length @@ -1058,7 +1054,7 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): def getRadius(obj,delta): "returns a new radius for a regular polygon" an = math.pi/obj.FacesNumber - nr = fcvec.rotate(delta,-an) + nr = DraftVecUtils.rotate(delta,-an) nr.multiply(1/math.cos(an)) nr = obj.Shape.Vertexes[0].Point.add(nr) nr = nr.sub(obj.Placement.Base) @@ -1075,18 +1071,18 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False): else: if sym: d1 = delta.multiply(0.5) - d2 = fcvec.neg(d1) - n1 = fcgeo.offsetWire(obj.Shape,d1) - n2 = fcgeo.offsetWire(obj.Shape,d2) + d2 = DraftVecUtils.neg(d1) + n1 = DraftGeomUtils.offsetWire(obj.Shape,d1) + n2 = DraftGeomUtils.offsetWire(obj.Shape,d2) else: - newwire = fcgeo.offsetWire(obj.Shape,delta) - p = fcgeo.getVerts(newwire) + newwire = DraftGeomUtils.offsetWire(obj.Shape,delta) + p = DraftGeomUtils.getVerts(newwire) if occ: newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Offset") - newobj.Shape = fcgeo.offsetWire(obj.Shape,delta,occ=True) + newobj.Shape = DraftGeomUtils.offsetWire(obj.Shape,delta,occ=True) formatObject(newobj,obj) elif bind: - if not fcgeo.isReallyClosed(obj.Shape): + if not DraftGeomUtils.isReallyClosed(obj.Shape): if sym: s1 = n1 s2 = n2 @@ -1161,8 +1157,7 @@ def draftify(objectslist,makeblock=False): '''draftify(objectslist,[makeblock]): turns each object of the given list (objectslist can also be a single object) into a Draft parametric wire. If makeblock is True, multiple objects will be grouped in a block''' - from draftlibs import fcgeo - import Part + import DraftGeomUtils, Part if not isinstance(objectslist,list): objectslist = [objectslist] @@ -1170,7 +1165,7 @@ def draftify(objectslist,makeblock=False): for obj in objectslist: if obj.isDerivedFrom('Part::Feature'): for w in obj.Shape.Wires: - if fcgeo.hasCurves(w): + if DraftGeomUtils.hasCurves(w): if (len(w.Edges) == 1) and isinstance(w.Edges[0].Curve,Part.Circle): nobj = makeCircle(w.Edges[0]) else: @@ -1199,8 +1194,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct with the given linewidth and fontsize (used if the given object contains any text). You can also supply an arbitrary projection vector. the scale parameter allows to scale linewidths down, so they are resolution-independant.''' - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils svg = "" linewidth = linewidth/scale fontsize = (fontsize/scale)/2 @@ -1209,7 +1203,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct if isinstance(direction,FreeCAD.Vector): if direction != Vector(0,0,0): plane = WorkingPlane.plane() - plane.alignToPointAndAxis(Vector(0,0,0),fcvec.neg(direction),0) + plane.alignToPointAndAxis(Vector(0,0,0),DraftVecUtils.neg(direction),0) elif isinstance(direction,WorkingPlane.plane): plane = direction @@ -1240,10 +1234,10 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct def getProj(vec): if not plane: return vec - nx = fcvec.project(vec,plane.u) + nx = DraftVecUtils.project(vec,plane.u) lx = nx.Length if abs(nx.getAngle(plane.u)) > 0.1: lx = -lx - ny = fcvec.project(vec,plane.v) + ny = DraftVecUtils.project(vec,plane.v) ly = ny.Length if abs(ny.getAngle(plane.v)) > 0.1: ly = -ly return Vector(lx,ly,0) @@ -1255,7 +1249,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct def getPath(edges): svg =' dmax): - p1 = p2.add(fcvec.scaleTo(proj,dmax)) - p4 = p3.add(fcvec.scaleTo(proj,dmax)) - midpoint = p2.add(fcvec.scale(p3.sub(p2),0.5)) + p1 = p2.add(DraftVecUtils.scaleTo(proj,dmax)) + p4 = p3.add(DraftVecUtils.scaleTo(proj,dmax)) + midpoint = p2.add(DraftVecUtils.scale(p3.sub(p2),0.5)) if not proj: - ed = fcgeo.vec(base) + ed = DraftGeomUtils.vec(base) proj = ed.cross(Vector(0,0,1)) if not proj: norm = Vector(0,0,1) - else: norm = fcvec.neg(p3.sub(p2).cross(proj)) - if not fcvec.isNull(norm): + else: norm = DraftVecUtils.neg(p3.sub(p2).cross(proj)) + if not DraftVecUtils.isNull(norm): norm.normalize() va = get3DView().getViewDirection() if va.getAngle(norm) < math.pi/2: - norm = fcvec.neg(norm) + norm = DraftVecUtils.neg(norm) u = p3.sub(p2) u.normalize() c = get3DView().getCameraNode() r = c.orientation.getValue() ru = Vector(r.multVec(coin.SbVec3f(1,0,0)).getValue()) - if ru.getAngle(u) > math.pi/2: u = fcvec.neg(u) + if ru.getAngle(u) > math.pi/2: u = DraftVecUtils.neg(u) v = norm.cross(u) - offset = fcvec.scaleTo(v,obj.ViewObject.FontSize*.2) + offset = DraftVecUtils.scaleTo(v,obj.ViewObject.FontSize*.2) if obj.ViewObject: if hasattr(obj.ViewObject,"DisplayMode"): if obj.ViewObject.DisplayMode == "3D": - offset = fcvec.neg(offset) + offset = DraftVecUtils.neg(offset) if hasattr(obj.ViewObject,"TextPosition"): if obj.ViewObject.TextPosition == Vector(0,0,0): tbase = midpoint.add(offset) @@ -1839,7 +1831,7 @@ class _ViewProviderDimension: tbase = obj.ViewObject.TextPosition else: tbase = midpoint.add(offset) - rot = FreeCAD.Placement(fcvec.getPlaneRotation(u,v,norm)).Rotation.Q + rot = FreeCAD.Placement(DraftVecUtils.getPlaneRotation(u,v,norm)).Rotation.Q return p1,p2,p3,p4,tbase,norm,rot def attach(self, obj): @@ -1858,7 +1850,7 @@ class _ViewProviderDimension: self.text.string = self.text3d.string = '' self.textpos = coin.SoTransform() self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) - tm = fcvec.getPlaneRotation(p3.sub(p2),norm) + tm = DraftVecUtils.getPlaneRotation(p3.sub(p2),norm) rm = coin.SbRotation() self.textpos.rotation = rm label = coin.SoSeparator() @@ -1917,11 +1909,11 @@ class _ViewProviderDimension: # arc linked dimension e = obj.Base.Shape.Edges[obj.LinkedVertices[0]] c = e.Curve.Center - bray = fcvec.scaleTo(obj.Dimline.sub(c),e.Curve.Radius) + bray = DraftVecUtils.scaleTo(obj.Dimline.sub(c),e.Curve.Radius) if obj.LinkedVertices[1] == 1: v1 = c else: - v1 = c.add(fcvec.neg(bray)) + v1 = c.add(DraftVecUtils.neg(bray)) v2 = c.add(bray) else: # linear linked dimension @@ -1952,8 +1944,8 @@ class _ViewProviderDimension: else: ts = (len(text)*obj.ViewObject.FontSize)/4 rm = ((p3.sub(p2)).Length/2)-ts - p2a = p2.add(fcvec.scaleTo(p3.sub(p2),rm)) - p2b = p3.add(fcvec.scaleTo(p2.sub(p3),rm)) + p2a = p2.add(DraftVecUtils.scaleTo(p3.sub(p2),rm)) + p2b = p3.add(DraftVecUtils.scaleTo(p2.sub(p3),rm)) self.coords.point.setValues([[p1.x,p1.y,p1.z], [p2.x,p2.y,p2.z], [p2a.x,p2a.y,p2a.z], @@ -2149,15 +2141,14 @@ class _ViewProviderAngularDimension: self.onChanged(vobj,"FontName") def calcGeom(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils rad = (obj.Dimline.sub(obj.Center)).Length cir = Part.makeCircle(rad,obj.Center,Vector(0,0,1),obj.FirstAngle,obj.LastAngle) - cp = fcgeo.findMidpoint(cir.Edges[0]) + cp = DraftGeomUtils.findMidpoint(cir.Edges[0]) rv = cp.sub(obj.Center) - rv = fcvec.scaleTo(rv,rv.Length + obj.ViewObject.FontSize*.2) + rv = DraftVecUtils.scaleTo(rv,rv.Length + obj.ViewObject.FontSize*.2) tbase = obj.Center.add(rv) - trot = fcvec.angle(rv)-math.pi/2 + trot = DraftVecUtils.angle(rv)-math.pi/2 if (trot > math.pi/2) or (trot < -math.pi/2): trot = trot + math.pi s = getParam("dimorientation") @@ -2276,8 +2267,7 @@ class _Rectangle: self.createGeometry(fp) def createGeometry(self,fp): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils plm = fp.Placement p1 = Vector(0,0,0) p2 = Vector(p1.x+fp.Length,p1.y,p1.z) @@ -2286,7 +2276,7 @@ class _Rectangle: shape = Part.makePolygon([p1,p2,p3,p4,p1]) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w shape = Part.Face(shape) @@ -2399,8 +2389,7 @@ class _Wire: fp.Points = pts def createGeometry(self,fp): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils plm = fp.Placement if fp.Base and (not fp.Tool): if fp.Base.isDerivedFrom("Sketcher::SketchObject"): @@ -2416,8 +2405,8 @@ class _Wire: sh1 = fp.Base.Shape.copy() sh2 = fp.Tool.Shape.copy() shape = sh1.fuse(sh2) - if fcgeo.isCoplanar(shape.Faces): - shape = fcgeo.concatenate(shape) + if DraftGeomUtils.isCoplanar(shape.Faces): + shape = DraftGeomUtils.concatenate(shape) fp.Shape = shape p = [] for v in shape.Vertexes: p.append(v.Point) @@ -2430,7 +2419,7 @@ class _Wire: shape = Part.makePolygon(fp.Points+[fp.Points[0]]) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w shape = Part.Face(shape) @@ -2444,7 +2433,7 @@ class _Wire: shape = Part.Wire(edges) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w fp.Shape = shape @@ -2510,8 +2499,7 @@ class _Polygon: self.createGeometry(fp) def createGeometry(self,fp): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils plm = fp.Placement angle = (math.pi*2)/fp.FacesNumber if fp.DrawMode == 'inscribed': @@ -2526,7 +2514,7 @@ class _Polygon: shape = Part.makePolygon(pts) if "FilletRadius" in fp.PropertiesList: if fp.FilletRadius != 0: - w = fcgeo.filletWire(shape,fp.FilletRadius) + w = DraftGeomUtils.filletWire(shape,fp.FilletRadius) if w: shape = w shape = Part.Face(shape) @@ -2690,16 +2678,15 @@ class _Shape2DView: self.createGeometry(obj) def createGeometry(self,obj): - import Drawing - from draftlibs import fcgeo + import Drawing, DraftGeomUtils pl = obj.Placement if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): - if not fcvec.isNull(obj.Projection): + if not DraftVecUtils.isNull(obj.Projection): [visibleG0,visibleG1,hiddenG0,hiddenG1] = Drawing.project(obj.Base.Shape,obj.Projection) if visibleG0: obj.Shape = visibleG0 - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _Array: @@ -2745,7 +2732,7 @@ class _Array: self.createGeometry(obj) def createGeometry(self,obj): - from draftlibs import fcgeo + import DraftGeomUtils if obj.Base: pl = obj.Placement if obj.ArrayType == "ortho": @@ -2753,21 +2740,21 @@ class _Array: else: sh = self.polarArray(obj.Base.Shape,obj.Center,obj.Angle,obj.NumberPolar,obj.Axis) obj.Shape = sh - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl def rectArray(self,shape,xvector,yvector,xnum,ynum): import Part base = [shape.copy()] for xcount in range(xnum): - currentxvector=fcvec.scale(xvector,xcount) + currentxvector=DraftVecUtils.scale(xvector,xcount) if not xcount==0: nshape = shape.copy() nshape.translate(currentxvector) base.append(nshape) for ycount in range(ynum): currentxvector=FreeCAD.Vector(currentxvector) - currentyvector=currentxvector.add(fcvec.scale(yvector,ycount)) + currentyvector=currentxvector.add(DraftVecUtils.scale(yvector,ycount)) if not ycount==0: nshape = shape.copy() nshape.translate(currentyvector) @@ -2781,7 +2768,7 @@ class _Array: for i in range(num): currangle = fraction + (i*fraction) nshape = shape.copy() - nshape.rotate(fcvec.tup(center), fcvec.tup(axis), currangle) + nshape.rotate(DraftVecUtils.tup(center), DraftVecUtils.tup(axis), currangle) base.append(nshape) return Part.makeCompound(base) @@ -2845,8 +2832,7 @@ class _Clone: self.createGeometry(obj) def createGeometry(self,obj): - import Part - from draftlibs import fcgeo + import Part, DraftGeomUtils pl = obj.Placement shapes = [] for o in obj.Objects: @@ -2859,7 +2845,7 @@ class _Clone: shapes.append(sh) if shapes: obj.Shape = Part.makeCompound(shapes) - if not fcgeo.isNull(pl): + if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderDraftPart(_ViewProviderDraft): diff --git a/src/Mod/Draft/draftlibs/fcgeo.py b/src/Mod/Draft/DraftGeomUtils.py similarity index 100% rename from src/Mod/Draft/draftlibs/fcgeo.py rename to src/Mod/Draft/DraftGeomUtils.py diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 50a0b19ba6..1479a65688 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -26,9 +26,8 @@ __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -import FreeCAD, FreeCADGui, math, Draft, DraftGui, DraftTrackers +import FreeCAD, FreeCADGui, math, Draft, DraftGui, DraftTrackers, DraftVecUtils from DraftGui import todo,getMainWindow -from draftlibs import fcvec from FreeCAD import Vector from pivy import coin from PyQt4 import QtCore,QtGui @@ -110,9 +109,8 @@ class Snapper: be True to constrain the point against the closest working plane axis. Screenpos can be a list, a tuple or a coin.SbVec2s object.""" - global Part,fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils if not hasattr(self,"toolbar"): self.makeSnapToolBar() @@ -355,7 +353,7 @@ class Snapper: for e in edges: if isinstance(e.Curve,Part.Line): np = self.getPerpendicular(e,point) - if not fcgeo.isPtOnEdge(np,e): + if not DraftGeomUtils.isPtOnEdge(np,e): if (np.sub(point)).Length < self.radius: if self.isEnabled('extension'): if np != e.Vertexes[0].Point: @@ -372,7 +370,7 @@ class Snapper: else: if self.isEnabled('parallel'): if last: - de = Part.Line(last,last.add(fcgeo.vec(e))).toShape() + de = Part.Line(last,last.add(DraftGeomUtils.vec(e))).toShape() np = self.getPerpendicular(de,point) if (np.sub(point)).Length < self.radius: if self.tracker: @@ -398,13 +396,13 @@ class Snapper: FreeCAD.Vector(0,0,1)] for a in self.polarAngles: if a == 90: - vecs.extend([ax[0],fcvec.neg(ax[0])]) - vecs.extend([ax[1],fcvec.neg(ax[1])]) + vecs.extend([ax[0],DraftVecUtils.neg(ax[0])]) + vecs.extend([ax[1],DraftVecUtils.neg(ax[1])]) else: - v = fcvec.rotate(ax[0],math.radians(a),ax[2]) - vecs.extend([v,fcvec.neg(v)]) - v = fcvec.rotate(ax[1],math.radians(a),ax[2]) - vecs.extend([v,fcvec.neg(v)]) + v = DraftVecUtils.rotate(ax[0],math.radians(a),ax[2]) + vecs.extend([v,DraftVecUtils.neg(v)]) + v = DraftVecUtils.rotate(ax[1],math.radians(a),ax[2]) + vecs.extend([v,DraftVecUtils.neg(v)]) for v in vecs: de = Part.Line(last,last.add(v)).toShape() np = self.getPerpendicular(de,point) @@ -457,7 +455,7 @@ class Snapper: snaps = [] if self.isEnabled("midpoint"): if isinstance(shape,Part.Edge): - mp = fcgeo.findMidpoint(shape) + mp = DraftGeomUtils.findMidpoint(shape) if mp: snaps.append([mp,'midpoint',mp]) return snaps @@ -472,7 +470,7 @@ class Snapper: np = self.getPerpendicular(shape,last) elif isinstance(shape.Curve,Part.Circle): dv = last.sub(shape.Curve.Center) - dv = fcvec.scaleTo(dv,shape.Curve.Radius) + dv = DraftVecUtils.scaleTo(dv,shape.Curve.Radius) np = (shape.Curve.Center).add(dv) elif isinstance(shape.Curve,Part.BSplineCurve): pr = shape.Curve.parameter(last) @@ -493,7 +491,7 @@ class Snapper: if self.constraintAxis: tmpEdge = Part.Line(last,last.add(self.constraintAxis)).toShape() # get the intersection points - pt = fcgeo.findIntersection(tmpEdge,shape,True,True) + pt = DraftGeomUtils.findIntersection(tmpEdge,shape,True,True) if pt: for p in pt: snaps.append([p,'ortho',p]) @@ -506,14 +504,14 @@ class Snapper: tmpEdge1 = Part.Line(last,last.add(self.constraintAxis)).toShape() tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() # get the intersection points - pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True) + pt = DraftGeomUtils.findIntersection(tmpEdge1,tmpEdge2,True,True) if pt: return [pt[0],'ortho',pt[0]] if eline: try: tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() # get the intersection points - pt = fcgeo.findIntersection(eline,tmpEdge2,True,True) + pt = DraftGeomUtils.findIntersection(eline,tmpEdge2,True,True) if pt: return [pt[0],'ortho',pt[0]] except: @@ -526,7 +524,7 @@ class Snapper: if self.isEnabled("intersection") and self.isEnabled("extension"): if e1 and e2: # get the intersection points - pts = fcgeo.findIntersection(e1,e2,True,True) + pts = DraftGeomUtils.findIntersection(e1,e2,True,True) if pts: for p in pts: snaps.append([p,'intersection',p]) @@ -569,7 +567,7 @@ class Snapper: if (not self.maxEdges) or (len(obj.Shape.Edges) <= self.maxEdges): for e in obj.Shape.Edges: # get the intersection points - pt = fcgeo.findIntersection(e,shape) + pt = DraftGeomUtils.findIntersection(e,shape) if pt: for p in pt: snaps.append([p,'intersection',p]) @@ -597,7 +595,7 @@ class Snapper: def getPerpendicular(self,edge,pt): "returns a point on an edge, perpendicular to the given point" dv = pt.sub(edge.Vertexes[0].Point) - nv = fcvec.project(dv,fcgeo.vec(edge)) + nv = DraftVecUtils.project(dv,DraftGeomUtils.vec(edge)) np = (edge.Vertexes[0].Point).add(nv) return np @@ -690,7 +688,7 @@ class Snapper: self.constraintAxis = FreeCAD.DraftWorkingPlane.axis # calculating constrained point - cdelta = fcvec.project(delta,self.constraintAxis) + cdelta = DraftVecUtils.project(delta,self.constraintAxis) npoint = self.basepoint.add(cdelta) # setting constrain line diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index ad61cf65d0..bde2ad4a76 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -29,9 +29,8 @@ __url__ = "http://free-cad.sourceforge.net" # Generic stuff #--------------------------------------------------------------------------- -import os, FreeCAD, FreeCADGui, WorkingPlane, math, re, importSVG, Draft, Draft_rc +import os, FreeCAD, FreeCADGui, WorkingPlane, math, re, importSVG, Draft, Draft_rc, DraftVecUtils from functools import partial -from draftlibs import fcvec from FreeCAD import Vector from DraftGui import todo,QtCore,QtGui from DraftSnap import * @@ -283,7 +282,7 @@ class SelectPlane: self.display('side') self.finish() elif arg == "currentView": - viewDirection = fcvec.neg(self.view.getViewDirection()) + viewDirection = DraftVecUtils.neg(self.view.getViewDirection()) plane.alignToPointAndAxis(Vector(0,0,0), viewDirection, self.offset) self.display(viewDirection) self.finish() @@ -327,9 +326,8 @@ class Creator: def Activated(self,name="None"): if FreeCAD.activeDraftCommand: FreeCAD.activeDraftCommand.finish() - global Part, fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils self.ui = None self.call = None self.doc = None @@ -348,7 +346,7 @@ class Creator: self.ui.show() rot = self.view.getCameraNode().getField("orientation").getValue() upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) self.node = [] self.pos = [] self.constrain = None @@ -721,12 +719,12 @@ class Rectangle(Creator): p1 = self.node[0] p3 = self.node[-1] diagonal = p3.sub(p1) - p2 = p1.add(fcvec.project(diagonal, plane.v)) - p4 = p1.add(fcvec.project(diagonal, plane.u)) + p2 = p1.add(DraftVecUtils.project(diagonal, plane.v)) + p4 = p1.add(DraftVecUtils.project(diagonal, plane.u)) length = p4.sub(p1).Length - if abs(fcvec.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length + if abs(DraftVecUtils.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length height = p2.sub(p1).Length - if abs(fcvec.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height + if abs(DraftVecUtils.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height p = plane.getRotation() p.move(p1) try: @@ -847,10 +845,10 @@ class Arc(Creator): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen self.ui.cross(True) - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center if hasMod(arg,MODALT): if not self.altdown: @@ -864,12 +862,12 @@ class Arc(Creator): self.ui.switchUi(False) elif (self.step == 1): # choose radius if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) if hasMod(arg,MODALT): if not self.altdown: @@ -880,20 +878,20 @@ class Arc(Creator): num = int(info['Component'].lstrip('Edge'))-1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: - cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) - cl = fcgeo.findClosestCircle(point,cir) + cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], self.tangents[1], ed) + cl = DraftGeomUtils.findClosestCircle(point,cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: - self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length + self.rad = self.center.add(DraftGeomUtils.findDistance(self.center,ed).sub(self.center)).Length else: - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) else: if self.altdown: self.ui.cross(True) self.altdown = False - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) self.ui.setRadiusValue(self.rad) self.arctrack.setRadius(self.rad) # Draw constraint tracker line. @@ -907,11 +905,11 @@ class Arc(Creator): self.linetrack.p2(point) self.linetrack.on() elif (self.step == 2): # choose first angle - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if currentrad != 0: - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 - self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) + self.linetrack.p2(DraftVecUtils.scaleTo(point.sub(self.center),self.rad).add(self.center)) # Draw constraint tracker line. if hasMod(arg,MODCONSTRAIN): self.constraintrack.p1(point) @@ -922,11 +920,11 @@ class Arc(Creator): self.ui.setRadiusValue(math.degrees(angle)) self.firstangle = angle else: # choose second angle - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if currentrad != 0: - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 - self.linetrack.p2(fcvec.scaleTo(point.sub(self.center),self.rad).add(self.center)) + self.linetrack.p2(DraftVecUtils.scaleTo(point.sub(self.center),self.rad).add(self.center)) # Draw constraint tracker line. if hasMod(arg,MODCONSTRAIN): self.constraintrack.p1(point) @@ -942,10 +940,10 @@ class Arc(Creator): if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center self.support = getSupport(arg) if hasMod(arg,MODALT): @@ -990,7 +988,7 @@ class Arc(Creator): self.ui.labelRadius.setText("Aperture") self.step = 3 # scale center->point vector for proper display - u = fcvec.scaleTo(point.sub(self.center), self.rad) + u = DraftVecUtils.scaleTo(point.sub(self.center), self.rad) self.arctrack.setStartAngle(self.firstangle) msg(translate("draft", "Pick aperture:\n")) else: # choose second angle @@ -1036,15 +1034,15 @@ class Arc(Creator): if (self.step == 1): self.rad = rad if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) + cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) + cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center if self.closedCircle: @@ -1061,9 +1059,9 @@ class Arc(Creator): elif (self.step == 2): self.ui.labelRadius.setText(str(translate("draft", "Aperture"))) self.firstangle = math.radians(rad) - if fcvec.equals(plane.axis, Vector(1,0,0)): u = Vector(0,self.rad,0) - else: u = fcvec.scaleTo(Vector(1,0,0).cross(plane.axis), self.rad) - urotated = fcvec.rotate(u, math.radians(rad), plane.axis) + if DraftVecUtils.equals(plane.axis, Vector(1,0,0)): u = Vector(0,self.rad,0) + else: u = DraftVecUtils.scaleTo(Vector(1,0,0).cross(plane.axis), self.rad) + urotated = DraftVecUtils.rotate(u, math.radians(rad), plane.axis) self.arctrack.setStartAngle(self.firstangle) self.step = 3 self.ui.radiusValue.setText("") @@ -1139,10 +1137,10 @@ class Polygon(Creator): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen self.ui.cross(True) - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center if hasMod(arg,MODALT): if not self.altdown: @@ -1156,12 +1154,12 @@ class Polygon(Creator): self.ui.switchUi(False) else: # choose radius if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], self.tangents[1], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) - self.center = fcgeo.findClosestCircle(point,cir).Center + cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], point) + self.center = DraftGeomUtils.findClosestCircle(point,cir).Center self.arctrack.setCenter(self.center) if hasMod(arg,MODALT): if not self.altdown: @@ -1173,20 +1171,20 @@ class Polygon(Creator): num = int(snapped['Component'].lstrip('Edge'))-1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: - cir = fcgeo.circleFrom3tan(self.tangents[0], self.tangents[1], ed) - cl = fcgeo.findClosestCircle(point,cir) + cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], self.tangents[1], ed) + cl = DraftGeomUtils.findClosestCircle(point,cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: - self.rad = self.center.add(fcgeo.findDistance(self.center,ed).sub(self.center)).Length + self.rad = self.center.add(DraftGeomUtils.findDistance(self.center,ed).sub(self.center)).Length else: - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) else: if self.altdown: self.ui.cross(True) self.altdown = False - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) self.ui.setRadiusValue(self.rad) self.arctrack.setRadius(self.rad) # Draw constraint tracker line. @@ -1203,10 +1201,10 @@ class Polygon(Creator): if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): point,ctrlPoint,info = getPoint(self,arg) # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center) > 0: - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center) > 0: + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center if not self.node: self.support = getSupport(arg) if hasMod(arg,MODALT): @@ -1265,15 +1263,15 @@ class Polygon(Creator): "this function gets called by the toolbar when valid radius have been entered there" self.rad = rad if len(self.tangents) == 2: - cir = fcgeo.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) + cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center elif self.tangents and self.tanpoints: - cir = fcgeo.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) + cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0],self.tanpoints[0],rad) if self.center: - self.center = fcgeo.findClosestCircle(self.center,cir).Center + self.center = DraftGeomUtils.findClosestCircle(self.center,cir).Center else: self.center = cir[-1].Center self.drawPolygon() @@ -1485,7 +1483,7 @@ class Dimension(Creator): r = point.sub(self.center) self.arctrack.setRadius(r.Length) a = self.arctrack.getAngle(point) - pair = fcgeo.getBoundaryAngles(a,self.pts) + pair = DraftGeomUtils.getBoundaryAngles(a,self.pts) if not (pair[0] < a < pair[1]): self.angledata = [4*math.pi-pair[0],2*math.pi-pair[1]] else: @@ -1496,14 +1494,14 @@ class Dimension(Creator): self.altdown = False self.ui.switchUi(False) if self.dir: - point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) + point = self.node[0].add(DraftVecUtils.project(point.sub(self.node[0]),self.dir)) if len(self.node) == 2: if self.arcmode and self.edges: cen = self.edges[0].Curve.Center rad = self.edges[0].Curve.Radius baseray = point.sub(cen) - v2 = fcvec.scaleTo(baseray,rad) - v1 = fcvec.neg(v2) + v2 = DraftVecUtils.scaleTo(baseray,rad) + v1 = DraftVecUtils.neg(v2) if shift: self.node = [cen,cen.add(v2)] self.arcmode = "radius" @@ -1574,7 +1572,7 @@ class Dimension(Creator): # there is already a snapped edge, so we start angular dimension self.edges.append(ed) self.node.extend([v1,v2]) # self.node now has the 4 endpoints - c = fcgeo.findIntersection(self.node[0], + c = DraftGeomUtils.findIntersection(self.node[0], self.node[1], self.node[2], self.node[3], @@ -1593,7 +1591,7 @@ class Dimension(Creator): self.dimtrack.on() else: if self.dir: - point = self.node[0].add(fcvec.project(point.sub(self.node[0]),self.dir)) + point = self.node[0].add(DraftVecUtils.project(point.sub(self.node[0]),self.dir)) self.node.append(point) print "node",self.node self.dimtrack.update(self.node) @@ -1610,7 +1608,7 @@ class Dimension(Creator): # for unlinked arc mode: # if self.arcmode: # v = self.node[1].sub(self.node[0]) - # v = fcvec.scale(v,0.5) + # v = DraftVecUtils.scale(v,0.5) # cen = self.node[0].add(v) # self.node = [self.node[0],self.node[1],cen] self.createObject() @@ -1651,9 +1649,8 @@ class Modifier: def Activated(self,name="None"): if FreeCAD.activeDraftCommand: FreeCAD.activeDraftCommand.finish() - global Part, fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils self.ui = None self.call = None self.commitList = [] @@ -1667,7 +1664,7 @@ class Modifier: FreeCADGui.draftToolBar.show() rot = self.view.getCameraNode().getField("orientation").getValue() upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(fcvec.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) self.node = [] self.ui.sourceCmd = self self.constrain = None @@ -1931,10 +1928,10 @@ class Rotate(Modifier): point,ctrlPoint,info = getPoint(self,arg) self.ui.cross(True) # this is to make sure radius is what you see on screen - if self.center and fcvec.dist(point,self.center): - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): - point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center): + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): + point = point.add(DraftVecUtils.neg(viewdelta)) if self.extendedCopy: if not hasMod(arg,MODALT): self.step = 3 @@ -1942,9 +1939,9 @@ class Rotate(Modifier): if (self.step == 0): pass elif (self.step == 1): - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if (currentrad != 0): - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 self.linetrack.p2(point) # Draw constraint tracker line. @@ -1959,16 +1956,16 @@ class Rotate(Modifier): self.ui.radiusValue.setFocus() self.ui.radiusValue.selectAll() elif (self.step == 2): - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) if (currentrad != 0): - angle = fcvec.angle(plane.u, point.sub(self.center), plane.axis) + angle = DraftVecUtils.angle(plane.u, point.sub(self.center), plane.axis) else: angle = 0 if (angle < self.firstangle): sweep = (2*math.pi-self.firstangle)+angle else: sweep = angle - self.firstangle self.arctrack.setApertureAngle(sweep) - self.ghost.trans.rotation.setValue(coin.SbVec3f(fcvec.tup(plane.axis)),sweep) + self.ghost.trans.rotation.setValue(coin.SbVec3f(DraftVecUtils.tup(plane.axis)),sweep) self.linetrack.p2(point) # Draw constraint tracker line. if hasMod(arg,MODCONSTRAIN): @@ -1984,9 +1981,9 @@ class Rotate(Modifier): elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): point,ctrlPoint,info = getPoint(self,arg) - if self.center and fcvec.dist(point,self.center): - viewdelta = fcvec.project(point.sub(self.center), plane.axis) - if not fcvec.isNull(viewdelta): point = point.add(fcvec.neg(viewdelta)) + if self.center and DraftVecUtils.dist(point,self.center): + viewdelta = DraftVecUtils.project(point.sub(self.center), plane.axis) + if not DraftVecUtils.isNull(viewdelta): point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): self.center = point self.node = [point] @@ -2002,16 +1999,16 @@ class Rotate(Modifier): self.planetrack.set(point) elif (self.step == 1): self.ui.labelRadius.setText("Rotation") - self.rad = fcvec.dist(point,self.center) + self.rad = DraftVecUtils.dist(point,self.center) self.arctrack.on() self.arctrack.setStartPoint(point) self.ghost.on() self.step = 2 msg(translate("draft", "Pick rotation angle:\n")) else: - currentrad = fcvec.dist(point,self.center) + currentrad = DraftVecUtils.dist(point,self.center) angle = point.sub(self.center).getAngle(plane.u) - if fcvec.project(point.sub(self.center), plane.v).getAngle(plane.v) > 1: + if DraftVecUtils.project(point.sub(self.center), plane.v).getAngle(plane.v) > 1: angle = -angle if (angle < self.firstangle): sweep = (2*math.pi-self.firstangle)+angle @@ -2127,33 +2124,33 @@ class Offset(Modifier): self.ui.cross(True) point,ctrlPoint,info = getPoint(self,arg) if hasMod(arg,MODCONSTRAIN) and self.constrainSeg: - dist = fcgeo.findPerpendicular(point,self.shape,self.constrainSeg[1]) + dist = DraftGeomUtils.findPerpendicular(point,self.shape,self.constrainSeg[1]) e = self.shape.Edges[self.constrainSeg[1]] self.constraintrack.p1(e.Vertexes[0].Point) self.constraintrack.p2(point.add(dist[0])) self.constraintrack.on() else: - dist = fcgeo.findPerpendicular(point,self.shape.Edges) + dist = DraftGeomUtils.findPerpendicular(point,self.shape.Edges) self.constraintrack.off() if dist: self.ghost.on() if self.mode == "Wire": - d = fcvec.neg(dist[0]) - v1 = fcgeo.getTangent(self.shape.Edges[0],point) - v2 = fcgeo.getTangent(self.shape.Edges[dist[1]],point) - a = -fcvec.angle(v1,v2) - self.dvec = fcvec.rotate(d,a,plane.axis) + d = DraftVecUtils.neg(dist[0]) + v1 = DraftGeomUtils.getTangent(self.shape.Edges[0],point) + v2 = DraftGeomUtils.getTangent(self.shape.Edges[dist[1]],point) + a = -DraftVecUtils.angle(v1,v2) + self.dvec = DraftVecUtils.rotate(d,a,plane.axis) occmode = self.ui.occOffset.isChecked() - self.ghost.update(fcgeo.offsetWire(self.shape,self.dvec,occ=occmode),forceclosed=occmode) + self.ghost.update(DraftGeomUtils.offsetWire(self.shape,self.dvec,occ=occmode),forceclosed=occmode) elif self.mode == "BSpline": - d = fcvec.neg(dist[0]) + d = DraftVecUtils.neg(dist[0]) e = self.shape.Edges[0] - basetan = fcgeo.getTangent(e,point) + basetan = DraftGeomUtils.getTangent(e,point) self.npts = [] for p in self.sel.Points: - currtan = fcgeo.getTangent(e,p) - a = -fcvec.angle(currtan,basetan) - self.dvec = fcvec.rotate(d,a,plane.axis) + currtan = DraftGeomUtils.getTangent(e,p) + a = -DraftVecUtils.angle(currtan,basetan) + self.dvec = DraftVecUtils.rotate(d,a,plane.axis) self.npts.append(p.add(self.dvec)) self.ghost.update(self.npts) elif self.mode == "Circle": @@ -2329,12 +2326,12 @@ class Upgrade(Modifier): u = faces.pop(0) for f in faces: u = u.fuse(f) - if fcgeo.isCoplanar(faces): + if DraftGeomUtils.isCoplanar(faces): if self.sel[0].ViewObject.DisplayMode == "Wireframe": f = False else: f = True - u = fcgeo.concatenate(u) + u = DraftGeomUtils.concatenate(u) if not curves: # several coplanar and non-curved faces: they can becoem a Draft wire msg(translate("draft", "Found several objects or faces: making a parametric face\n")) @@ -2384,7 +2381,7 @@ class Upgrade(Modifier): else: # only closed wires for w in wires: - if fcgeo.isPlanar(w): + if DraftGeomUtils.isPlanar(w): f = Part.Face(w) faces.append(f) else: @@ -2405,7 +2402,7 @@ class Upgrade(Modifier): edges = openwires[0].Edges if len(edges) > 1: edges.append(Part.Line(p1,p0).toShape()) - w = Part.Wire(fcgeo.sortEdges(edges)) + w = Part.Wire(DraftGeomUtils.sortEdges(edges)) if len(edges) == 1: if len(w.Vertexes) == 2: msg(translate("draft", "Found 1 open edge: making a line\n")) @@ -2433,7 +2430,7 @@ class Upgrade(Modifier): for e in ob.Shape.Edges: edges.append(e) newob = None - nedges = fcgeo.sortEdges(edges[:]) + nedges = DraftGeomUtils.sortEdges(edges[:]) # for e in nedges: print "debug: ",e.Curve,e.Vertexes[0].Point,e.Vertexes[-1].Point w = Part.Wire(nedges) if len(w.Edges) == len(edges): @@ -2643,7 +2640,7 @@ class Trimex(Modifier): self.extrudeMode = False if self.obj.Shape.Wires: self.edges = self.obj.Shape.Wires[0].Edges - self.edges = fcgeo.sortEdges(self.edges) + self.edges = DraftGeomUtils.sortEdges(self.edges) else: self.edges = self.obj.Shape.Edges self.ghost = [] @@ -2707,7 +2704,7 @@ class Trimex(Modifier): "redraws the ghost in extrude mode" self.newpoint = self.obj.Shape.Faces[0].CenterOfMass dvec = self.point.sub(self.newpoint) - if not shift: delta = fcvec.project(dvec,self.normal) + if not shift: delta = DraftVecUtils.project(dvec,self.normal) else: delta = dvec if self.force: ratio = self.force/delta.Length @@ -2733,7 +2730,7 @@ class Trimex(Modifier): for e in self.edges: vlist.append(e.Vertexes[0].Point) vlist.append(self.edges[-1].Vertexes[-1].Point) if shift: npoint = self.activePoint - else: npoint = fcgeo.findClosest(point,vlist) + else: npoint = DraftGeomUtils.findClosest(point,vlist) if npoint > len(self.edges)/2: reverse = True if alt: reverse = not reverse self.activePoint = npoint @@ -2758,16 +2755,16 @@ class Trimex(Modifier): snapped = self.doc.getObject(snapped['Object']) pts = [] for e in snapped.Shape.Edges: - int = fcgeo.findIntersection(edge,e,True,True) + int = DraftGeomUtils.findIntersection(edge,e,True,True) if int: pts.extend(int) if pts: - point = pts[fcgeo.findClosest(point,pts)] + point = pts[DraftGeomUtils.findClosest(point,pts)] # modifying active edge if isinstance(edge.Curve,Part.Line): - perp = fcgeo.vec(edge).cross(Vector(0,0,1)) + perp = DraftGeomUtils.vec(edge).cross(Vector(0,0,1)) chord = v1.sub(point) - proj = fcvec.project(chord,perp) + proj = DraftVecUtils.project(chord,perp) self.newpoint = Vector.add(point,proj) dist = v1.sub(self.newpoint).Length ghost.p1(self.newpoint) @@ -2776,15 +2773,15 @@ class Trimex(Modifier): if real: if self.force: ray = self.newpoint.sub(v1) - ray = fcvec.scale(ray,self.force/ray.Length) + ray = DraftVecUtils.scale(ray,self.force/ray.Length) self.newpoint = Vector.add(v1,ray) newedges.append(Part.Line(self.newpoint,v2).toShape()) else: center = edge.Curve.Center rad = edge.Curve.Radius - ang1 = fcvec.angle(v2.sub(center)) - ang2 = fcvec.angle(point.sub(center)) - self.newpoint=Vector.add(center,fcvec.rotate(Vector(rad,0,0),-ang2)) + ang1 = DraftVecUtils.angle(v2.sub(center)) + ang2 = DraftVecUtils.angle(point.sub(center)) + self.newpoint=Vector.add(center,DraftVecUtils.rotate(Vector(rad,0,0),-ang2)) self.ui.labelRadius.setText("Angle") dist = math.degrees(-ang2) # if ang1 > ang2: ang1,ang2 = ang2,ang1 @@ -2796,11 +2793,11 @@ class Trimex(Modifier): if real: if self.force: angle = math.radians(self.force) - newray = fcvec.rotate(Vector(rad,0,0),-angle) + newray = DraftVecUtils.rotate(Vector(rad,0,0),-angle) self.newpoint = Vector.add(center,newray) chord = self.newpoint.sub(v2) perp = chord.cross(Vector(0,0,1)) - scaledperp = fcvec.scaleTo(perp,rad) + scaledperp = DraftVecUtils.scaleTo(perp,rad) midpoint = Vector.add(center,scaledperp) newedges.append(Part.Arc(self.newpoint,midpoint,v2).toShape()) ghost.on() @@ -2815,8 +2812,8 @@ class Trimex(Modifier): ghost.p1(edge.Vertexes[0].Point) ghost.p2(edge.Vertexes[-1].Point) else: - ang1 = fcvec.angle(edge.Vertexes[0].Point.sub(center)) - ang2 = fcvec.angle(edge.Vertexes[-1].Point.sub(center)) + ang1 = DraftVecUtils.angle(edge.Vertexes[0].Point.sub(center)) + ang2 = DraftVecUtils.angle(edge.Vertexes[-1].Point.sub(center)) # if ang1 > ang2: ang1,ang2 = ang2,ang1 ghost.setEndAngle(-ang2) ghost.setStartAngle(-ang1) @@ -2961,7 +2958,7 @@ class Scale(Modifier): self.ghost.trans.scaleFactor.setValue([delta.x,delta.y,delta.z]) corr = Vector(self.node[0].x,self.node[0].y,self.node[0].z) corr.scale(delta.x,delta.y,delta.z) - corr = fcvec.neg(corr.sub(self.node[0])) + corr = DraftVecUtils.neg(corr.sub(self.node[0])) self.ghost.trans.translation.setValue([corr.x,corr.y,corr.z]) if self.extendedCopy: if not hasMod(arg,MODALT): self.finish() @@ -3166,9 +3163,9 @@ class Edit(Modifier): self.editpoints.append(self.obj.Shape.Vertexes[2].Point) v = self.obj.Shape.Vertexes self.bx = v[1].Point.sub(v[0].Point) - if self.obj.Length < 0: self.bx = fcvec.neg(self.bx) + if self.obj.Length < 0: self.bx = DraftVecUtils.neg(self.bx) self.by = v[2].Point.sub(v[1].Point) - if self.obj.Height < 0: self.by = fcvec.neg(self.by) + if self.obj.Height < 0: self.by = DraftVecUtils.neg(self.by) elif Draft.getType(self.obj) == "Polygon": self.editpoints.append(self.obj.Placement.Base) self.editpoints.append(self.obj.Shape.Vertexes[0].Point) @@ -3292,8 +3289,8 @@ class Edit(Modifier): self.obj.Placement = p elif self.editing == 1: diag = v.sub(self.obj.Placement.Base) - nx = fcvec.project(diag,self.bx) - ny = fcvec.project(diag,self.by) + nx = DraftVecUtils.project(diag,self.bx) + ny = DraftVecUtils.project(diag,self.by) ax = nx.Length ay = ny.Length if ax and ay: diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 3cc6519d14..5223ebf667 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -25,18 +25,16 @@ __title__="FreeCAD Draft Trackers" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -import FreeCAD,FreeCADGui,math,Draft +import FreeCAD,FreeCADGui,math,Draft, DraftVecUtils from FreeCAD import Vector -from draftlibs import fcvec from pivy import coin from DraftGui import todo class Tracker: "A generic Draft Tracker, to be used by other specific trackers" def __init__(self,dotted=False,scolor=None,swidth=None,children=[],ontop=False): - global Part, fcgeo - import Part - from draftlibs import fcgeo + global Part, DraftGeomUtils + import Part, DraftGeomUtils self.ontop = ontop color = coin.SoBaseColor() color.rgb = scolor or FreeCADGui.draftToolBar.getDefaultColor("ui") @@ -161,8 +159,8 @@ class rectangleTracker(Tracker): def update(self,point): "sets the opposite (diagonal) point of the rectangle" diagonal = point.sub(self.origin) - inpoint1 = self.origin.add(fcvec.project(diagonal,self.v)) - inpoint2 = self.origin.add(fcvec.project(diagonal,self.u)) + inpoint1 = self.origin.add(DraftVecUtils.project(diagonal,self.v)) + inpoint2 = self.origin.add(DraftVecUtils.project(diagonal,self.u)) self.coords.point.set1Value(1,inpoint1.x,inpoint1.y,inpoint1.z) self.coords.point.set1Value(2,point.x,point.y,point.z) self.coords.point.set1Value(3,inpoint2.x,inpoint2.y,inpoint2.z) @@ -204,7 +202,7 @@ class rectangleTracker(Tracker): p1 = Vector(self.coords.point.getValues()[0].getValue()) p2 = Vector(self.coords.point.getValues()[2].getValue()) diag = p2.sub(p1) - return ((fcvec.project(diag,self.u)).Length,(fcvec.project(diag,self.v)).Length) + return ((DraftVecUtils.project(diag,self.u)).Length,(DraftVecUtils.project(diag,self.v)).Length) def getNormal(self): "returns the normal of the rectangle" @@ -233,23 +231,23 @@ class dimTracker(Tracker): def calc(self): import Part if (self.p1 != None) and (self.p2 != None): - points = [fcvec.tup(self.p1,True),fcvec.tup(self.p2,True),\ - fcvec.tup(self.p1,True),fcvec.tup(self.p2,True)] + points = [DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True),\ + DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True)] if self.p3 != None: p1 = self.p1 p4 = self.p2 - if fcvec.equals(p1,p4): + if DraftVecUtils.equals(p1,p4): proj = None else: base = Part.Line(p1,p4).toShape() - proj = fcgeo.findDistance(self.p3,base) + proj = DraftGeomUtils.findDistance(self.p3,base) if not proj: p2 = p1 p3 = p4 else: - p2 = p1.add(fcvec.neg(proj)) - p3 = p4.add(fcvec.neg(proj)) - points = [fcvec.tup(p1),fcvec.tup(p2),fcvec.tup(p3),fcvec.tup(p4)] + p2 = p1.add(DraftVecUtils.neg(proj)) + p3 = p4.add(DraftVecUtils.neg(proj)) + points = [DraftVecUtils.tup(p1),DraftVecUtils.tup(p2),DraftVecUtils.tup(p3),DraftVecUtils.tup(p4)] self.coords.point.setValues(0,4,points) class bsplineTracker(Tracker): @@ -340,7 +338,7 @@ class arcTracker(Tracker): center = Vector(c[0],c[1],c[2]) base = FreeCAD.DraftWorkingPlane.u rad = pt.sub(center) - return(fcvec.angle(rad,base,FreeCAD.DraftWorkingPlane.axis)) + return(DraftVecUtils.angle(rad,base,FreeCAD.DraftWorkingPlane.axis)) def getAngles(self): "returns the start and end angles" @@ -496,7 +494,7 @@ class wireTracker(Tracker): "A wire tracker" def __init__(self,wire): self.line = coin.SoLineSet() - self.closed = fcgeo.isReallyClosed(wire) + self.closed = DraftGeomUtils.isReallyClosed(wire) if self.closed: self.line.numVertices.setValue(len(wire.Vertexes)+1) else: @@ -626,11 +624,11 @@ class gridTracker(Tracker): "returns the closest node from the given point" # get the 2D coords. point = FreeCAD.DraftWorkingPlane.projectPoint(point) - u = fcvec.project(point,FreeCAD.DraftWorkingPlane.u) + u = DraftVecUtils.project(point,FreeCAD.DraftWorkingPlane.u) lu = u.Length if u.getAngle(FreeCAD.DraftWorkingPlane.u) > 1.5: lu = -lu - v = fcvec.project(point,FreeCAD.DraftWorkingPlane.v) + v = DraftVecUtils.project(point,FreeCAD.DraftWorkingPlane.v) lv = v.Length if v.getAngle(FreeCAD.DraftWorkingPlane.v) > 1.5: lv = -lv @@ -659,8 +657,7 @@ class boxTracker(Tracker): Tracker.__init__(self,children=[self.trans,m,self.cube]) def update(self,line=None,normal=None): - import WorkingPlane - from draftlibs import fcgeo + import WorkingPlane, DraftGeomUtils if not normal: normal = FreeCAD.DraftWorkingPlane.axis if line: @@ -668,10 +665,10 @@ class boxTracker(Tracker): bp = line[0] lvec = line[1].sub(line[0]) else: - lvec = fcgeo.vec(line.Shape.Edges[0]) + lvec = DraftGeomUtils.vec(line.Shape.Edges[0]) bp = line.Shape.Edges[0].Vertexes[0].Point elif self.baseline: - lvec = fcgeo.vec(self.baseline.Shape.Edges[0]) + lvec = DraftGeomUtils.vec(self.baseline.Shape.Edges[0]) bp = self.baseline.Shape.Edges[0].Vertexes[0].Point else: return @@ -679,12 +676,12 @@ class boxTracker(Tracker): self.cube.width.setValue(lvec.Length) p = WorkingPlane.getPlacementFromPoints([bp,bp.add(lvec),bp.add(right)]) self.trans.rotation.setValue(p.Rotation.Q) - bp = bp.add(fcvec.scale(lvec,0.5)) - bp = bp.add(fcvec.scaleTo(normal,self.cube.depth.getValue()/2)) + bp = bp.add(DraftVecUtils.scale(lvec,0.5)) + bp = bp.add(DraftVecUtils.scaleTo(normal,self.cube.depth.getValue()/2)) self.pos(bp) def pos(self,p): - self.trans.translation.setValue(fcvec.tup(p)) + self.trans.translation.setValue(DraftVecUtils.tup(p)) def width(self,w=None): if w: diff --git a/src/Mod/Draft/draftlibs/fcvec.py b/src/Mod/Draft/DraftVecUtils.py similarity index 100% rename from src/Mod/Draft/draftlibs/fcvec.py rename to src/Mod/Draft/DraftVecUtils.py diff --git a/src/Mod/Draft/Makefile.am b/src/Mod/Draft/Makefile.am index 2502ec4d21..f93f64cfe2 100644 --- a/src/Mod/Draft/Makefile.am +++ b/src/Mod/Draft/Makefile.am @@ -13,6 +13,8 @@ data_DATA = \ DraftGui.py \ DraftSnap.py \ DraftTrackers.py \ + DraftVecUtils.py \ + DraftGeomUtils.py \ WorkingPlane.py \ importOCA.py \ importDXF.py \ @@ -28,8 +30,6 @@ nobase_data_DATA = \ draftlibs/dxfImportObjects.py \ draftlibs/dxfLibrary.py \ draftlibs/dxfReader.py \ - draftlibs/fcvec.py \ - draftlibs/fcgeo.py \ draftlibs/__init__.py CLEANFILES = $(BUILT_SOURCES) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index b722f22ff9..e41eaabf76 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -22,9 +22,8 @@ #*************************************************************************** -import FreeCAD, FreeCADGui, math +import FreeCAD, FreeCADGui, math, DraftVecUtils from FreeCAD import Vector -from draftlibs import fcvec __title__="FreeCAD Working Plane utility" __author__ = "Ken Cline" @@ -51,7 +50,7 @@ class plane: self.stored = None def __repr__(self): - return "Workplane x="+str(fcvec.rounded(self.u))+" y="+str(fcvec.rounded(self.v))+" z="+str(fcvec.rounded(self.axis)) + return "Workplane x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis)) def offsetToPoint(self, p, direction=None): ''' @@ -96,10 +95,10 @@ class plane: self.doc = FreeCAD.ActiveDocument self.axis = axis; self.axis.normalize() - if (fcvec.equals(axis, Vector(1,0,0))): + if (DraftVecUtils.equals(axis, Vector(1,0,0))): self.u = Vector(0,1,0) self.v = Vector(0,0,1) - elif (fcvec.equals(axis, Vector(-1,0,0))): + elif (DraftVecUtils.equals(axis, Vector(-1,0,0))): self.u = Vector(0,-1,0) self.v = Vector(0,0,1) elif upvec: @@ -109,12 +108,12 @@ class plane: else: self.v = axis.cross(Vector(1,0,0)) self.v.normalize() - self.u = fcvec.rotate(self.v, -math.pi/2, self.axis) + self.u = DraftVecUtils.rotate(self.v, -math.pi/2, self.axis) offsetVector = Vector(axis); offsetVector.multiply(offset) self.position = point.add(offsetVector) self.weak = False # FreeCAD.Console.PrintMessage("(position = " + str(self.position) + ")\n") - # FreeCAD.Console.PrintMessage("Current workplane: x="+str(fcvec.rounded(self.u))+" y="+str(fcvec.rounded(self.v))+" z="+str(fcvec.rounded(self.axis))+"\n") + # FreeCAD.Console.PrintMessage("Current workplane: x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis))+"\n") def alignToCurve(self, shape, offset): if shape.ShapeType == 'Edge': @@ -162,7 +161,7 @@ class plane: def getRotation(self): "returns a placement describing the working plane orientation ONLY" - m = fcvec.getPlaneRotation(self.u,self.v,self.axis) + m = DraftVecUtils.getPlaneRotation(self.u,self.v,self.axis) return FreeCAD.Placement(m) def getPlacement(self): @@ -197,15 +196,15 @@ class plane: def getLocalCoords(self,point): "returns the coordinates of a given point on the working plane" - xv = fcvec.project(point,self.u) + xv = DraftVecUtils.project(point,self.u) x = xv.Length if xv.getAngle(self.u) > 1: x = -x - yv = fcvec.project(point,self.v) + yv = DraftVecUtils.project(point,self.v) y = yv.Length if yv.getAngle(self.v) > 1: y = -y - zv = fcvec.project(point,self.axis) + zv = DraftVecUtils.project(point,self.axis) z = zv.Length if zv.getAngle(self.axis) > 1: z = -z @@ -213,9 +212,9 @@ class plane: def getGlobalCoords(self,point): "returns the global coordinates of the given point, taken relatively to this working plane" - vx = fcvec.scale(self.u,point.x) - vy = fcvec.scale(self.v,point.y) - vz = fcvec.scale(self.axis,point.z) + vx = DraftVecUtils.scale(self.u,point.x) + vy = DraftVecUtils.scale(self.v,point.y) + vz = DraftVecUtils.scale(self.axis,point.z) return (vx.add(vy)).add(vz) def getClosestAxis(self,point): @@ -223,9 +222,9 @@ class plane: ax = point.getAngle(self.u) ay = point.getAngle(self.v) az = point.getAngle(self.axis) - bx = point.getAngle(fcvec.neg(self.u)) - by = point.getAngle(fcvec.neg(self.v)) - bz = point.getAngle(fcvec.neg(self.axis)) + bx = point.getAngle(DraftVecUtils.neg(self.u)) + by = point.getAngle(DraftVecUtils.neg(self.v)) + bz = point.getAngle(DraftVecUtils.neg(self.axis)) b = min(ax,ay,az,bx,by,bz) if b in [ax,bx]: return "x" diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 2c0474f8ed..f71e101666 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -40,8 +40,8 @@ lines, polylines, lwpolylines, circles, arcs, texts, colors,layers (from groups) ''' -import FreeCAD, os, Part, math, re, string, Mesh, Draft -from draftlibs import fcvec, dxfColorMap, dxfLibrary, fcgeo +import FreeCAD, os, Part, math, re, string, Mesh, Draft, DraftVecUtils, DraftGeomUtils +from draftlibs import dxfColorMap, dxfLibrary from draftlibs.dxfReader import readDXF from Draft import _Dimension, _ViewProviderDimension from FreeCAD import Vector @@ -134,10 +134,10 @@ def calcBulge(v1,bulge,v2): ''' chord = v2.sub(v1) sagitta = (bulge * chord.Length)/2 - startpoint = v1.add(fcvec.scale(chord,0.5)) + startpoint = v1.add(DraftVecUtils.scale(chord,0.5)) perp = chord.cross(Vector(0,0,1)) - if not fcvec.isNull(perp): perp.normalize() - endpoint = fcvec.scale(perp,sagitta) + if not DraftVecUtils.isNull(perp): perp.normalize() + endpoint = DraftVecUtils.scale(perp,sagitta) return startpoint.add(endpoint) def getGroup(ob,exportList): @@ -218,7 +218,7 @@ class fcformat: v1 = FreeCAD.Vector(r1,g1,b1) v2 = FreeCAD.Vector(r2,g2,b2) v = v2.sub(v1) - v = fcvec.scale(v,0.5) + v = DraftVecUtils.scale(v,0.5) cv = v1.add(v) else: c1 = bparams.GetUnsigned("BackgroundColor") @@ -348,7 +348,7 @@ def drawLine(line,shapemode=False): if (len(line.points) > 1): v1=vec(line.points[0]) v2=vec(line.points[1]) - if not fcvec.equals(v1,v2): + if not DraftVecUtils.equals(v1,v2): try: if (fmt.paramstyle >= 4) and (not shapemode): return Draft.makeWire([v1,v2]) @@ -370,11 +370,11 @@ def drawPolyline(polyline,shapemode=False,num=None): v1 = vec(p1) v2 = vec(p2) verts.append(v1) - if not fcvec.equals(v1,v2): + if not DraftVecUtils.equals(v1,v2): if polyline.points[p].bulge: curves = True cv = calcBulge(v1,polyline.points[p].bulge,v2) - if fcvec.isColinear([v1,cv,v2]): + if DraftVecUtils.isColinear([v1,cv,v2]): try: edges.append(Part.Line(v1,v2).toShape()) except: warn(polyline,num) else: @@ -390,8 +390,8 @@ def drawPolyline(polyline,shapemode=False,num=None): v1 = vec(p1) v2 = vec(p2) cv = calcBulge(v1,polyline.points[-1].bulge,v2) - if not fcvec.equals(v1,v2): - if fcvec.isColinear([v1,cv,v2]): + if not DraftVecUtils.equals(v1,v2): + if DraftVecUtils.isColinear([v1,cv,v2]): try: edges.append(Part.Line(v1,v2).toShape()) except: @@ -722,11 +722,11 @@ def addText(text,attrib=False): rz = rawValue(text,31) if rx or ry or rz: xv = Vector(rx,ry,rz) - if not fcvec.isNull(xv): - ax = fcvec.neg(xv.cross(Vector(1,0,0))) - if fcvec.isNull(ax): + if not DraftVecUtils.isNull(xv): + ax = DraftVecUtils.neg(xv.cross(Vector(1,0,0))) + if DraftVecUtils.isNull(ax): ax = Vector(0,0,1) - ang = -math.degrees(fcvec.angle(xv,Vector(1,0,0),ax)) + ang = -math.degrees(DraftVecUtils.angle(xv,Vector(1,0,0),ax)) Draft.rotate(newob,ang,axis=ax) elif hasattr(text,"rotation"): if text.rotation: @@ -885,7 +885,7 @@ def processdxf(document,filename): edges = [] for s in shapes: edges.extend(s.Edges) - shapes = fcgeo.findWires(edges) + shapes = DraftGeomUtils.findWires(edges) for s in shapes: newob = addObject(s) @@ -1198,13 +1198,13 @@ def getArcData(edge): # check the midpoint seems more reliable ve1 = edge.Vertexes[0].Point ve2 = edge.Vertexes[-1].Point - ang1 = -math.degrees(fcvec.angle(ve1.sub(ce))) - ang2 = -math.degrees(fcvec.angle(ve2.sub(ce))) - ve3 = fcgeo.findMidpoint(edge) - ang3 = -math.degrees(fcvec.angle(ve3.sub(ce))) + ang1 = -math.degrees(DraftVecUtils.angle(ve1.sub(ce))) + ang2 = -math.degrees(DraftVecUtils.angle(ve2.sub(ce))) + ve3 = DraftGeomUtils.findMidpoint(edge) + ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce))) if (ang3 < ang1) and (ang2 < ang3): ang1, ang2 = ang2, ang1 - return fcvec.tup(ce), radius, ang1, ang2 + return DraftVecUtils.tup(ce), radius, ang1, ang2 def getSplineSegs(edge): "returns an array of vectors from a bSpline edge" @@ -1228,18 +1228,18 @@ def getSplineSegs(edge): def getWire(wire,nospline=False): "returns an array of dxf-ready points and bulges from a wire" - edges = fcgeo.sortEdges(wire.Edges) + edges = DraftGeomUtils.sortEdges(wire.Edges) points = [] for edge in edges: v1 = edge.Vertexes[0].Point if len(edge.Vertexes) < 2: points.append((v1.x,v1.y,v1.z,None,None,0.0)) elif (isinstance(edge.Curve,Part.Circle)): - mp = fcgeo.findMidpoint(edge) + mp = DraftGeomUtils.findMidpoint(edge) v2 = edge.Vertexes[-1].Point c = edge.Curve.Center - angle = abs(fcvec.angle(v1.sub(c),v2.sub(c))) - # if (fcvec.angle(v2.sub(c)) < fcvec.angle(v1.sub(c))): + angle = abs(DraftVecUtils.angle(v1.sub(c),v2.sub(c))) + # if (DraftVecUtils.angle(v2.sub(c)) < DraftVecUtils.angle(v1.sub(c))): # angle = -angle # polyline bulge -> negative makes the arc go clockwise bul = math.tan(angle/4) @@ -1259,9 +1259,9 @@ def getWire(wire,nospline=False): points.append((p.x,p.y,p.z,None,None,0.0)) else: points.append((v1.x,v1.y,v1.z,None,None,0.0)) - if not fcgeo.isReallyClosed(wire): + if not DraftGeomUtils.isReallyClosed(wire): v = edges[-1].Vertexes[-1].Point - points.append(fcvec.tup(v)) + points.append(DraftVecUtils.tup(v)) # print "wire verts: ",points return points @@ -1289,7 +1289,7 @@ def writeShape(ob,dxfobject,nospline=False): layer=getGroup(ob,exportList))) else: dxfobject.append(dxfLibrary.PolyLine(getWire(wire,nospline), [0.0,0.0,0.0], - int(fcgeo.isReallyClosed(wire)), color=getACI(ob), + int(DraftGeomUtils.isReallyClosed(wire)), color=getACI(ob), layer=getGroup(ob,exportList))) if len(processededges) < len(ob.Shape.Edges): # lone edges loneedges = [] @@ -1318,7 +1318,7 @@ def writeShape(ob,dxfobject,nospline=False): else: # anything else is treated as lines ve1=edge.Vertexes[0].Point ve2=edge.Vertexes[1].Point - dxfobject.append(dxfLibrary.Line([fcvec.tup(ve1), fcvec.tup(ve2)], + dxfobject.append(dxfLibrary.Line([DraftVecUtils.tup(ve1), DraftVecUtils.tup(ve2)], color=getACI(ob), layer=getGroup(ob,exportList))) @@ -1377,7 +1377,7 @@ def export(objectslist,filename,nospline=False): # 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 = fcvec.tup(FreeCAD.Vector(ob.Position.x, + 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) @@ -1388,14 +1388,14 @@ def export(objectslist,filename,nospline=False): layer=getGroup(ob,exportList))) elif 'Dimline' in ob.PropertiesList: - p1 = fcvec.tup(ob.Start) - p2 = fcvec.tup(ob.End) + p1 = DraftVecUtils.tup(ob.Start) + p2 = DraftVecUtils.tup(ob.End) base = Part.Line(ob.Start,ob.End).toShape() - proj = fcgeo.findDistance(ob.Dimline,base) + proj = DraftGeomUtils.findDistance(ob.Dimline,base) if not proj: - pbase = fcvec.tup(ob.End) + pbase = DraftVecUtils.tup(ob.End) else: - pbase = fcvec.tup(ob.End.add(fcvec.neg(proj))) + pbase = DraftVecUtils.tup(ob.End.add(DraftVecUtils.neg(proj))) dxf.append(dxfLibrary.Dimension(pbase,p1,p2,color=getACI(ob), layer=getGroup(ob,exportList))) diff --git a/src/Mod/Draft/importOCA.py b/src/Mod/Draft/importOCA.py index 58131d8300..79e769aa2f 100644 --- a/src/Mod/Draft/importOCA.py +++ b/src/Mod/Draft/importOCA.py @@ -29,8 +29,7 @@ __url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"] This script imports OCA/gcad files into FreeCAD. ''' -import FreeCAD, os, Part, math -from draftlibs import fcvec, fcgeo +import FreeCAD, os, Part, math, DraftVecUtils, DraftGeomUtils from FreeCAD import Vector try: import FreeCADGui @@ -56,7 +55,7 @@ def getpoint(data): if (data[1][0] == "R"): return objects[data[0]].add(objects[data[1]]) elif (data[1][0] == "C"): - return fcgeo.findProjection(objects[data[0]],objects[data[1]]) + return DraftGeomUtils.findProjection(objects[data[0]],objects[data[1]]) elif (data[0][0] == "C"): if objects[data[0]]: p1 = objects[data[0]].Curve.Position @@ -65,7 +64,7 @@ def getpoint(data): else: if (data[1][0] == "L"): l = objects[data[1]] - return p1.add(fcgeo.vec(l)) + return p1.add(DraftGeomUtils.vec(l)) def getarea(data): "turns an OCA area definition into a FreeCAD Part Wire" @@ -111,7 +110,7 @@ def getarc(data): c = Part.Circle() c.Center = verts[0] if rad: c.Radius = rad - else: c.Radius = fcvec.new(verts[0],verts[1]).Length + else: c.Radius = DraftVecUtils.new(verts[0],verts[1]).Length elif (data[0][0] == "L"): # 2-lines circle lines = [] @@ -121,7 +120,7 @@ def getarc(data): rad = float(data[p+1]) elif (data[p][0] == "L"): lines.append(objects[data[p]]) - circles = fcgeo.circleFrom2LinesRadius(lines[0],lines[1],rad) + circles = DraftGeomUtils.circleFrom2LinesRadius(lines[0],lines[1],rad) if circles: c = circles[0] if c: return c.toShape() @@ -268,7 +267,7 @@ def export(exportList,filename): oca.write("C"+str(count)+"=ARC ") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") - oca.write(writepoint(fcgeo.findMidpoint(e))) + oca.write(writepoint(DraftGeomUtils.findMidpoint(e))) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) else: diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index b49d4735c7..099041d0ad 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -38,9 +38,7 @@ currently unsupported: use, image # implement inherting fill style from group # handle relative units -import xml.sax, string, FreeCAD, os, math, re, Draft -from draftlibs import fcvec -from draftlibs import fcgeo +import xml.sax, string, FreeCAD, os, math, re, Draft, DraftVecUtils, DraftGeomUtils from FreeCAD import Vector try: import FreeCADGui @@ -271,7 +269,7 @@ def makewire(path,checkclosed=False,donttry=False): #ToDo Do not catch all exceptions if not donttry: try: - sh = Part.Wire(fcgeo.sortEdges(path)) + sh = Part.Wire(DraftGeomUtils.sortEdges(path)) #sh = Part.Wire(path) isok = (not checkclosed) or sh.isClosed() except:# BRep_API:command not done @@ -334,13 +332,13 @@ def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False): m2=FreeCAD.Matrix() m2.rotateZ(xrotation) centeroff = currentvec.add(lastvec) - centeroff = fcvec.scale(centeroff,.5) + centeroff = DraftVecUtils.scale(centeroff,.5) vcenter = m2.multiply(vcx1).add(centeroff) # Step3 F.6.5.3 #angle1 = Vector(1,0,0).getAngle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5 #angledelta = Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0).getAngle(Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6 #we need the right sign for the angle - angle1 = fcvec.angle(Vector(1,0,0),Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5 - angledelta = fcvec.angle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0),Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6 + angle1 = DraftVecUtils.angle(Vector(1,0,0),Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5 + angledelta = DraftVecUtils.angle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0),Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6 results.append((vcenter,angle1,angledelta)) return results,(rx,ry) @@ -558,7 +556,7 @@ class svgHandler(xml.sax.ContentHandler): currentvec = lastvec.add(Vector(x,-y,0)) else: currentvec = Vector(x,-y,0) - if not fcvec.equals(lastvec,currentvec): + if not DraftVecUtils.equals(lastvec,currentvec): seg = Part.Line(lastvec,currentvec).toShape() FreeCAD.Console.PrintMessage("line %s %s\n" %(lastvec,currentvec)) lastvec = currentvec @@ -599,15 +597,15 @@ class svgHandler(xml.sax.ContentHandler): # here is a better way to find the perpendicular if sweepflag == 1: # clockwise - perp = fcvec.rotate2D(chord,-math.pi/2) + perp = DraftVecUtils.rotate2D(chord,-math.pi/2) else: # anticlockwise - perp = fcvec.rotate2D(chord,math.pi/2) - chord = fcvec.scale(chord,.5) + perp = DraftVecUtils.rotate2D(chord,math.pi/2) + chord = DraftVecUtils.scale(chord,.5) if chord.Length > rx: a = 0 else: a = math.sqrt(rx**2-chord.Length**2) s = rx - a - perp = fcvec.scale(perp,s/perp.Length) + perp = DraftVecUtils.scale(perp,s/perp.Length) midpoint = lastvec.add(chord.add(perp)) seg = Part.Arc(lastvec,midpoint,currentvec).toShape() else:# big arc or elliptical arc @@ -676,7 +674,7 @@ class svgHandler(xml.sax.ContentHandler): currentvec = Vector(x,-y,0) pole2 = Vector(p2x,-p2y,0) - if not fcvec.equals(currentvec,lastvec): + if not DraftVecUtils.equals(currentvec,lastvec): mainv = currentvec.sub(lastvec) pole1v = lastvec.add(pole1) pole2v = currentvec.add(pole2) @@ -718,7 +716,7 @@ class svgHandler(xml.sax.ContentHandler): else: currentvec = Vector(x,-y,0) - if not fcvec.equals(currentvec,lastvec): + if not DraftVecUtils.equals(currentvec,lastvec): if True and \ pole.distanceToLine(lastvec,currentvec) < 20**(-1*(2+Draft.precision())): #print "straight segment" @@ -733,7 +731,7 @@ class svgHandler(xml.sax.ContentHandler): lastpole = ('quadratic',pole) path.append(seg) elif (d == "Z") or (d == "z"): - if not fcvec.equals(lastvec,firstvec): + if not DraftVecUtils.equals(lastvec,firstvec): seg = Part.Line(lastvec,firstvec).toShape() path.append(seg) if path: #the path should be closed by now @@ -821,7 +819,7 @@ class svgHandler(xml.sax.ContentHandler): esh.append(arc.toShape()) for esh1,esh2 in zip(esh[-1:]+esh[:-1],esh): p1,p2 = esh1.Vertexes[-1].Point,esh2.Vertexes[0].Point - if not fcvec.equals(p1,p2): + if not DraftVecUtils.equals(p1,p2): edges.append(Part.Line(esh1.Vertexes[-1].Point,esh2.Vertexes[0].Point).toShape()) #straight segments edges.append(esh2) # elliptical segments sh = Part.Wire(edges) @@ -859,7 +857,7 @@ class svgHandler(xml.sax.ContentHandler): points=points+points[:2] # emulate closepath for svgx,svgy in zip(points[2::2],points[3::2]): currentvec = Vector(svgx,-svgy,0) - if not fcvec.equals(lastvec,currentvec): + if not DraftVecUtils.equals(lastvec,currentvec): seg = Part.Line(lastvec,currentvec).toShape() #print "polyline seg ",lastvec,currentvec lastvec = currentvec diff --git a/src/WindowsInstaller/ModDraft.wxi b/src/WindowsInstaller/ModDraft.wxi index 13fcc92ff6..720a39810a 100644 --- a/src/WindowsInstaller/ModDraft.wxi +++ b/src/WindowsInstaller/ModDraft.wxi @@ -38,6 +38,8 @@ + + @@ -46,8 +48,6 @@ - - From b1de8d217e20ce36cca92b42e3c667db6fef7bfc Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 12:00:03 -0300 Subject: [PATCH 250/351] Further Draft lib name fixes --- src/Mod/Arch/ArchSectionPlane.py | 3 +- src/Mod/Draft/DraftGeomUtils.py | 170 +++++++++++++++---------------- 2 files changed, 87 insertions(+), 86 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 59c8023827..e1230e59f7 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,Drawing,math,Draft,ArchCommands, DraftVecUtils +import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,math,Draft,ArchCommands, DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore from pivy import coin @@ -197,6 +197,7 @@ class _ArchDrawingView: else: # render using the Drawing module + import Drawing shapes = [] for o in objs: if o.isDerivedFrom("Part::Feature"): diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index ccacbf62c9..16468ad0c1 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -27,7 +27,7 @@ __url__ = ["http://free-cad.sourceforge.net"] "this file contains generic geometry functions for manipulating Part shapes" -import FreeCAD, Part, fcvec, math, cmath +import FreeCAD, Part, DraftVecUtils, math, cmath from FreeCAD import Vector NORM = Vector(0,0,1) # provisory normal direction for all geometry ops. @@ -51,7 +51,7 @@ def vec(edge): def edg(p1,p2): "edg(Vector,Vector) -- returns an edge from 2 vectors" if isinstance(p1,FreeCAD.Vector) and isinstance(p2,FreeCAD.Vector): - if fcvec.equals(p1,p2): return None + if DraftVecUtils.equals(p1,p2): return None else: return Part.Line(p1,p2).toShape() def getVerts(shape): @@ -85,7 +85,7 @@ def isPtOnEdge(pt,edge) : '''isPtOnEdge(Vector,edge) -- Tests if a point is on an edge''' if isinstance(edge.Curve,Part.Line) : orig = edge.Vertexes[0].Point - if fcvec.isNull(pt.sub(orig).cross(vec(edge))) : + if DraftVecUtils.isNull(pt.sub(orig).cross(vec(edge))) : return pt.sub(orig).Length <= vec(edge).Length and pt.sub(orig).dot(vec(edge)) >= 0 else : return False @@ -101,16 +101,16 @@ def isPtOnEdge(pt,edge) : else : begin = edge.Vertexes[0].Point end = edge.Vertexes[-1].Point - if fcvec.isNull(pt.sub(begin)) or fcvec.isNull(pt.sub(end)) : + if DraftVecUtils.isNull(pt.sub(begin)) or DraftVecUtils.isNull(pt.sub(end)) : return True else : # newArc = Part.Arc(begin,pt,end) - # return fcvec.isNull(newArc.Center.sub(center)) \ - # and fcvec.isNull(newArc.Axis-axis) \ + # return DraftVecUtils.isNull(newArc.Center.sub(center)) \ + # and DraftVecUtils.isNull(newArc.Axis-axis) \ # and round(newArc.Radius-radius,precision) == 0 - angle1 = fcvec.angle(begin.sub(center)) - angle2 = fcvec.angle(end.sub(center)) - anglept = fcvec.angle(pt.sub(center)) + angle1 = DraftVecUtils.angle(begin.sub(center)) + angle2 = DraftVecUtils.angle(end.sub(center)) + anglept = DraftVecUtils.angle(pt.sub(center)) if (angle1 < anglept) and (anglept < angle2): return True return False @@ -165,8 +165,8 @@ def findEdge(anEdge,aList): '''findEdge(anEdge,aList): returns True if anEdge is found in aList of edges''' for e in range(len(aList)): if str(anEdge.Curve) == str(aList[e].Curve): - if fcvec.equals(anEdge.Vertexes[0].Point,aList[e].Vertexes[0].Point): - if fcvec.equals(anEdge.Vertexes[-1].Point,aList[e].Vertexes[-1].Point): + if DraftVecUtils.equals(anEdge.Vertexes[0].Point,aList[e].Vertexes[0].Point): + if DraftVecUtils.equals(anEdge.Vertexes[-1].Point,aList[e].Vertexes[-1].Point): return(e) return None @@ -202,13 +202,13 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F return [pt2] #we have 2 straight lines - if fcvec.isNull(pt2.sub(pt1).cross(pt3.sub(pt1)).cross(pt2.sub(pt4).cross(pt3.sub(pt4)))): + if DraftVecUtils.isNull(pt2.sub(pt1).cross(pt3.sub(pt1)).cross(pt2.sub(pt4).cross(pt3.sub(pt4)))): vec1 = pt2.sub(pt1) ; vec2 = pt4.sub(pt3) - if fcvec.isNull(vec1) or fcvec.isNull(vec2): + if DraftVecUtils.isNull(vec1) or DraftVecUtils.isNull(vec2): return [] vec1.normalize() ; vec2.normalize() cross = vec1.cross(vec2) - if not fcvec.isNull(cross) : + if not DraftVecUtils.isNull(cross) : k = ((pt3.z-pt1.z)*(vec2.x-vec2.y)+(pt3.y-pt1.y)*(vec2.z-vec2.x)+ \ (pt3.x-pt1.x)*(vec2.y-vec2.z))/(cross.x+cross.y+cross.z) vec1.scale(k,k,k) @@ -251,7 +251,7 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F elif (pt2 in [pt3,pt4]): return [pt2] - if fcvec.isNull(pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)) : + if DraftVecUtils.isNull(pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)) : # Line and Arc are on same plane dOnLine = center.sub(pt1).dot(dirVec) @@ -303,18 +303,18 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F axis1, axis2 = edge1.Curve.Axis , edge2.Curve.Axis c2c = cent2.sub(cent1) - if fcvec.isNull(axis1.cross(axis2)) : + if DraftVecUtils.isNull(axis1.cross(axis2)) : if round(c2c.dot(axis1),precision) == 0 : # circles are on same plane dc2c = c2c.Length ; - if not fcvec.isNull(c2c): c2c.normalize() + if not DraftVecUtils.isNull(c2c): c2c.normalize() if round(rad1+rad2-dc2c,precision) < 0 \ or round(rad1-dc2c-rad2,precision) > 0 or round(rad2-dc2c-rad1,precision) > 0 : return [] else : norm = c2c.cross(axis1) - if not fcvec.isNull(norm): norm.normalize() - if fcvec.isNull(norm): x = 0 + if not DraftVecUtils.isNull(norm): norm.normalize() + if DraftVecUtils.isNull(norm): x = 0 else: x = (dc2c**2 + rad1**2 - rad2**2)/(2*dc2c) y = abs(rad1**2 - x**2)**(0.5) c2c.scale(x,x,x) @@ -369,8 +369,8 @@ def geom(edge): v2 = edge.Vertexes[-1].Point c = edge.Curve.Center cu = Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius) - a1 = -fcvec.angle(v1.sub(c),ref,edge.Curve.Axis) - a2 = -fcvec.angle(v2.sub(c),ref,edge.Curve.Axis) + a1 = -DraftVecUtils.angle(v1.sub(c),ref,edge.Curve.Axis) + a2 = -DraftVecUtils.angle(v2.sub(c),ref,edge.Curve.Axis) 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 @@ -382,7 +382,7 @@ def mirror (point, edge): normPoint = point.add(findDistance(point, edge, False)) if normPoint: normPoint_point = Vector.sub(point, normPoint) - normPoint_refl = fcvec.neg(normPoint_point) + normPoint_refl = DraftVecUtils.neg(normPoint_point) refl = Vector.add(normPoint, normPoint_refl) return refl else: @@ -547,13 +547,13 @@ def findWires(edgeslist): return False if len(e2.Vertexes) < 2: return False - if fcvec.equals(e1.Vertexes[0].Point,e2.Vertexes[0].Point): + if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[0].Point): return True - if fcvec.equals(e1.Vertexes[0].Point,e2.Vertexes[-1].Point): + if DraftVecUtils.equals(e1.Vertexes[0].Point,e2.Vertexes[-1].Point): return True - if fcvec.equals(e1.Vertexes[-1].Point,e2.Vertexes[0].Point): + if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[0].Point): return True - if fcvec.equals(e1.Vertexes[-1].Point,e2.Vertexes[-1].Point): + if DraftVecUtils.equals(e1.Vertexes[-1].Point,e2.Vertexes[-1].Point): return True return False @@ -656,7 +656,7 @@ def findMidpoint(edge): if len(edge.Vertexes) == 1: # Circle dv = first.sub(center) - dv = fcvec.neg(dv) + dv = DraftVecUtils.neg(dv) return center.add(dv) axis = edge.Curve.Axis chord = last.sub(first) @@ -665,12 +665,12 @@ def findMidpoint(edge): ray = first.sub(center) apothem = ray.dot(perp) sagitta = radius - apothem - startpoint = Vector.add(first, fcvec.scale(chord,0.5)) - endpoint = fcvec.scaleTo(perp,sagitta) + startpoint = Vector.add(first, DraftVecUtils.scale(chord,0.5)) + endpoint = DraftVecUtils.scaleTo(perp,sagitta) return Vector.add(startpoint,endpoint) elif isinstance(edge.Curve,Part.Line): - halfedge = fcvec.scale(last.sub(first),.5) + halfedge = DraftVecUtils.scale(last.sub(first),.5) return Vector.add(first,halfedge) else: @@ -759,7 +759,7 @@ def isReallyClosed(wire): if len(wire.Edges) == len(wire.Vertexes): return True v1 = wire.Vertexes[0].Point v2 = wire.Vertexes[-1].Point - if fcvec.equals(v1,v2): return True + if DraftVecUtils.equals(v1,v2): return True return False def getNormal(shape): @@ -784,7 +784,7 @@ def getNormal(shape): if FreeCAD.GuiUp: import Draft vdir = Draft.get3DView().getViewDirection() - if n.getAngle(vdir) < 0.78: n = fcvec.neg(n) + if n.getAngle(vdir) < 0.78: n = DraftVecUtils.neg(n) return n def offsetWire(wire,dvec,bind=False,occ=False): @@ -815,8 +815,8 @@ def offsetWire(wire,dvec,bind=False,occ=False): curredge = edges[i] delta = dvec if i != 0: - angle = fcvec.angle(vec(edges[0]),vec(curredge),norm) - delta = fcvec.rotate(delta,angle,norm) + angle = DraftVecUtils.angle(vec(edges[0]),vec(curredge),norm) + delta = DraftVecUtils.rotate(delta,angle,norm) nedge = offset(curredge,delta) nedges.append(nedge) nedges = connect(nedges,closed) @@ -890,7 +890,7 @@ def findDistance(point,edge,strict=False): chord = edge.Vertexes[0].Point.sub(point) norm = segment.cross(chord) perp = segment.cross(norm) - dist = fcvec.project(chord,perp) + dist = DraftVecUtils.project(chord,perp) if not dist: return None newpoint = point.add(dist) if (dist.Length == 0): @@ -912,14 +912,14 @@ def findDistance(point,edge,strict=False): center = edge.Curve.Center segment = center.sub(point) ratio = (segment.Length - edge.Curve.Radius) / segment.Length - dist = fcvec.scale(segment,ratio) + dist = DraftVecUtils.scale(segment,ratio) newpoint = Vector.add(point, dist) if (dist.Length == 0): return None if strict and ve2: - ang1 = fcvec.angle(ve1.sub(center)) - ang2 = fcvec.angle(ve2.sub(center)) - angpt = fcvec.angle(newpoint.sub(center)) + ang1 = DraftVecUtils.angle(ve1.sub(center)) + ang2 = DraftVecUtils.angle(ve2.sub(center)) + angpt = DraftVecUtils.angle(newpoint.sub(center)) if ((angpt <= ang2 and angpt >= ang1) or (angpt <= ang1 and angpt >= ang2)): return dist else: @@ -954,15 +954,15 @@ def angleBisection(edge1, edge2): int = findIntersection(edge1, edge2, True, True) if int: line1Dir = p2.sub(p1) - angleDiff = fcvec.angle(line1Dir, p4.sub(p3)) + angleDiff = DraftVecUtils.angle(line1Dir, p4.sub(p3)) ang = angleDiff * 0.5 origin = int[0] line1Dir.normalize() - dir = fcvec.rotate(line1Dir, ang) + dir = DraftVecUtils.rotate(line1Dir, ang) return Part.Line(origin,origin.add(dir)).toShape() else: diff = p3.sub(p1) - origin = p1.add(fcvec.scale(diff, 0.5)) + origin = p1.add(DraftVecUtils.scale(diff, 0.5)) dir = p2.sub(p1); dir.normalize() return Part.Line(origin,origin.add(dir)).toShape() else: @@ -998,8 +998,8 @@ def isPlanar(shape): n = bt.normalAt(0,0) for p in shape.Vertexes[3:]: pv = p.Point.sub(pts[0]) - rv = fcvec.project(pv,n) - if not fcvec.isNull(rv): + rv = DraftVecUtils.project(pv,n) + if not DraftVecUtils.isNull(rv): return False return True @@ -1216,9 +1216,9 @@ def getCubicDimensions(shape): vx = vec(base.Edges[0]) vy = vec(base.Edges[1]) # getting rotations - rotZ = fcvec.angle(vx) - rotY = fcvec.angle(vx,FreeCAD.Vector(vx.x,vx.y,0)) - rotX = fcvec.angle(vy,FreeCAD.Vector(vy.x,vy.y,0)) + rotZ = DraftVecUtils.angle(vx) + rotY = DraftVecUtils.angle(vx,FreeCAD.Vector(vx.x,vx.y,0)) + rotX = DraftVecUtils.angle(vy,FreeCAD.Vector(vy.x,vy.y,0)) # getting height vz = None rpi = round(math.pi/2,precision) @@ -1687,22 +1687,22 @@ def circlefrom1Line2Points(edge, p1, p2): v2 = p2.sub(s) projectedDist = math.sqrt(abs(v1.dot(v2))) edgeDir = vec(edge); edgeDir.normalize() - projectedCen1 = Vector.add(s, fcvec.scale(edgeDir, projectedDist)) - projectedCen2 = Vector.add(s, fcvec.scale(edgeDir, -projectedDist)) + projectedCen1 = Vector.add(s, DraftVecUtils.scale(edgeDir, projectedDist)) + projectedCen2 = Vector.add(s, DraftVecUtils.scale(edgeDir, -projectedDist)) perpEdgeDir = edgeDir.cross(Vector(0,0,1)) perpCen1 = Vector.add(projectedCen1, perpEdgeDir) perpCen2 = Vector.add(projectedCen2, perpEdgeDir) mid = findMidpoint(p1_p2) - x = fcvec.crossproduct(vec(p1_p2)); x.normalize() + x = DraftVecUtils.crossproduct(vec(p1_p2)); x.normalize() perp_mid = Vector.add(mid, x) cen1 = findIntersection(edg(projectedCen1, perpCen1), edg(mid, perp_mid), True, True) cen2 = findIntersection(edg(projectedCen2, perpCen2), edg(mid, perp_mid), True, True) circles = [] if cen1: - radius = fcvec.dist(projectedCen1, cen1[0]) + radius = DraftVecUtils.dist(projectedCen1, cen1[0]) circles.append(Part.Circle(cen1[0], NORM, radius)) if cen2: - radius = fcvec.dist(projectedCen2, cen2[0]) + radius = DraftVecUtils.dist(projectedCen2, cen2[0]) circles.append(Part.Circle(cen2[0], NORM, radius)) if circles: return circles @@ -1714,26 +1714,26 @@ def circleFrom2LinesRadius (edge1, edge2, radius): if not int: return None int = int[0] bis12 = angleBisection(edge1,edge2) - bis21 = Part.Line(bis12.Vertexes[0].Point,fcvec.rotate(vec(bis12), math.pi/2.0)) - ang12 = abs(fcvec.angle(vec(edge1),vec(edge2))) + bis21 = Part.Line(bis12.Vertexes[0].Point,DraftVecUtils.rotate(vec(bis12), math.pi/2.0)) + ang12 = abs(DraftVecUtils.angle(vec(edge1),vec(edge2))) ang21 = math.pi - ang12 dist12 = radius / math.sin(ang12 * 0.5) dist21 = radius / math.sin(ang21 * 0.5) circles = [] - cen = Vector.add(int, fcvec.scale(vec(bis12), dist12)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis12), dist12)) circles.append(Part.Circle(cen, NORM, radius)) - cen = Vector.add(int, fcvec.scale(vec(bis12), -dist12)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis12), -dist12)) circles.append(Part.Circle(cen, NORM, radius)) - cen = Vector.add(int, fcvec.scale(vec(bis21), dist21)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis21), dist21)) circles.append(Part.Circle(cen, NORM, radius)) - cen = Vector.add(int, fcvec.scale(vec(bis21), -dist21)) + cen = Vector.add(int, DraftVecUtils.scale(vec(bis21), -dist21)) circles.append(Part.Circle(cen, NORM, radius)) return circles def circleFrom3LineTangents (edge1, edge2, edge3): "circleFrom3LineTangents(edge,edge,edge)" def rot(ed): - return Part.Line(v1(ed),v1(ed).add(fcvec.rotate(vec(ed),math.pi/2))).toShape() + return Part.Line(v1(ed),v1(ed).add(DraftVecUtils.rotate(vec(ed),math.pi/2))).toShape() bis12 = angleBisection(edge1,edge2) bis23 = angleBisection(edge2,edge3) bis31 = angleBisection(edge3,edge1) @@ -1766,7 +1766,7 @@ def circleFrom3LineTangents (edge1, edge2, edge3): for int in intersections: exists = False for cir in circles: - if fcvec.equals(cir.Center, int.Center): + if DraftVecUtils.equals(cir.Center, int.Center): exists = True break if not exists: @@ -1783,16 +1783,16 @@ def circleFromPointLineRadius (point, edge, radius): center2 = None if dist.Length == 0: segment = vec(edge) - perpVec = fcvec.crossproduct(segment); perpVec.normalize() - normPoint_c1 = fcvec.scale(perpVec, radius) - normPoint_c2 = fcvec.scale(perpVec, -radius) + perpVec = DraftVecUtils.crossproduct(segment); perpVec.normalize() + normPoint_c1 = DraftVecUtils.scale(perpVec, radius) + normPoint_c2 = DraftVecUtils.scale(perpVec, -radius) center1 = point.add(normPoint_c1) center2 = point.add(normPoint_c2) elif dist.Length > 2 * radius: return None elif dist.Length == 2 * radius: normPoint = point.add(findDistance(point, edge, False)) - dummy = fcvec.scale(normPoint.sub(point), 0.5) + dummy = DraftVecUtils.scale(normPoint.sub(point), 0.5) cen = point.add(dummy) circ = Part.Circle(cen, NORM, radius) if circ: @@ -1801,12 +1801,12 @@ def circleFromPointLineRadius (point, edge, radius): return None else: normPoint = point.add(findDistance(point, edge, False)) - normDist = fcvec.dist(normPoint, point) + normDist = DraftVecUtils.dist(normPoint, point) dist = math.sqrt(radius**2 - (radius - normDist)**2) - centerNormVec = fcvec.scaleTo(point.sub(normPoint), radius) + centerNormVec = DraftVecUtils.scaleTo(point.sub(normPoint), radius) edgeDir = edge.Vertexes[0].Point.sub(normPoint); edgeDir.normalize() - center1 = centerNormVec.add(normPoint.add(fcvec.scale(edgeDir, dist))) - center2 = centerNormVec.add(normPoint.add(fcvec.scale(edgeDir, -dist))) + center1 = centerNormVec.add(normPoint.add(DraftVecUtils.scale(edgeDir, dist))) + center2 = centerNormVec.add(normPoint.add(DraftVecUtils.scale(edgeDir, -dist))) circles = [] if center1: circ = Part.Circle(center1, NORM, radius) @@ -1824,10 +1824,10 @@ def circleFromPointLineRadius (point, edge, radius): def circleFrom2PointsRadius(p1, p2, radius): "circleFrom2PointsRadiust(Vector, Vector, radius)" - if fcvec.equals(p1, p2): return None + if DraftVecUtils.equals(p1, p2): return None p1_p2 = Part.Line(p1, p2).toShape() - dist_p1p2 = fcvec.dist(p1, p1) + dist_p1p2 = DraftVecUtils.dist(p1, p1) mid = findMidpoint(p1_p2) if dist_p1p2 == 2*radius: circle = Part.Circle(mid, norm, radius) @@ -1836,8 +1836,8 @@ def circleFrom2PointsRadius(p1, p2, radius): dir = vec(p1_p2); dir.normalize() perpDir = dir.cross(Vector(0,0,1)); perpDir.normailze() dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0)**2) - cen1 = Vector.add(mid, fcvec.scale(perpDir, dist)) - cen2 = Vector.add(mid, fcvec.scale(perpDir, -dist)) + cen1 = Vector.add(mid, DraftVecUtils.scale(perpDir, dist)) + cen2 = Vector.add(mid, DraftVecUtils.scale(perpDir, -dist)) circles = [] if cen1: circles.append(Part.Circle(cen1, norm, radius)) if cen2: circles.append(Part.Circle(cen2, norm, radius)) @@ -2069,7 +2069,7 @@ def findHomotheticCenterOfCircles(circle1, circle2): ''' if isinstance(circle1.Curve, Part.Circle) and isinstance(circle2.Curve, Part.Circle): - if fcvec.equals(circle1.Curve.Center, circle2.Curve.Center): + if DraftVecUtils.equals(circle1.Curve.Center, circle2.Curve.Center): return None cen1_cen2 = Part.Line(circle1.Curve.Center, circle2.Curve.Center).toShape() @@ -2079,21 +2079,21 @@ def findHomotheticCenterOfCircles(circle1, circle2): perpCenDir = cenDir.cross(Vector(0,0,1)); perpCenDir.normalize() # Get point on first circle - p1 = Vector.add(circle1.Curve.Center, fcvec.scale(perpCenDir, circle1.Curve.Radius)) + p1 = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, circle1.Curve.Radius)) centers = [] # Calculate inner homothetic center # Get point on second circle - p2_inner = Vector.add(circle1.Curve.Center, fcvec.scale(perpCenDir, -circle1.Curve.Radius)) - hCenterInner = fcvec.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_inner, True, True) + p2_inner = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, -circle1.Curve.Radius)) + hCenterInner = DraftVecUtils.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_inner, True, True) if hCenterInner: centers.append(hCenterInner) # Calculate outer homothetic center (only exists of the circles have different radii) if circle1.Curve.Radius != circle2.Curve.Radius: # Get point on second circle - p2_outer = Vector.add(circle1.Curve.Center, fcvec.scale(perpCenDir, circle1.Curve.Radius)) - hCenterOuter = fcvec.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_outer, True, True) + p2_outer = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, circle1.Curve.Radius)) + hCenterOuter = DraftVecUtils.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_outer, True, True) if hCenterOuter: centers.append(hCenterOuter) @@ -2121,13 +2121,13 @@ def findRadicalAxis(circle1, circle2): ''' if isinstance(circle1.Curve, Part.Circle) and isinstance(circle2.Curve, Part.Circle): - if fcvec.equals(circle1.Curve.Center, circle2.Curve.Center): + if DraftVecUtils.equals(circle1.Curve.Center, circle2.Curve.Center): return None r1 = circle1.Curve.Radius r2 = circle1.Curve.Radius cen1 = circle1.Curve.Center # dist .. the distance from cen1 to cen2. - dist = fcvec.dist(cen1, circle2.Curve.Center) + dist = DraftVecUtils.dist(cen1, circle2.Curve.Center) cenDir = cen1.sub(circle2.Curve.Center); cenDir.normalize() # Get the perpedicular vector. @@ -2142,7 +2142,7 @@ def findRadicalAxis(circle1, circle2): k1 = (dist + (r1^2 - r2^2) / dist) / 2.0 #k2 = dist - k1 - K = Vector.add(cen1, fcvec.scale(cenDir, k1)) + K = Vector.add(cen1, DraftVecUtils.scale(cenDir, k1)) # K_ .. A point somewhere between K and J (actually with a distance of 1 unit from K). K_ = Vector,add(K, perpCenDir) @@ -2208,13 +2208,13 @@ def pointInversion(circle, point): cen = circle.Curve.Center rad = circle.Curve.Radius - if fcvec.equals(cen, point): + if DraftVecUtils.equals(cen, point): return None # Inverse the distance of the point # dist(cen -> P) = r^2 / dist(cen -> invP) - dist = fcvec.dist(point, cen) + dist = DraftVecUtils.dist(point, cen) invDist = rad**2 / d invPoint = Vector(0, 0, point.z) @@ -2260,7 +2260,7 @@ def circleInversion(circle, circle2): cen1 = circle.Curve.Center rad1 = circle.Curve.Radius - if fcvec.equals(cen1, point): + if DraftVecUtils.equals(cen1, point): return None invCen2 = Inversion(circle, circle2.Curve.Center) @@ -2268,7 +2268,7 @@ def circleInversion(circle, circle2): pointOnCircle2 = Vector.add(circle2.Curve.Center, Vector(circle2.Curve.Radius, 0, 0)) invPointOnCircle2 = Inversion(circle, pointOnCircle2) - return Part.Circle(invCen2, norm, fcvec.dist(invCen2, invPointOnCircle2)) + return Part.Circle(invCen2, norm, DraftVecUtils.dist(invCen2, invPointOnCircle2)) else: print "debug: circleInversion bad parameters!\n" From 3b67a56b1ee3cff12b78040c03688d4cb862f22a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 17:09:06 -0300 Subject: [PATCH 251/351] Added 0000680 : DXF polylines with defined width --- src/Mod/Draft/Draft.py | 3 +- src/Mod/Draft/Draft_rc.py | 410 +++++++++--------- .../Draft/Resources/ui/userprefs-import.ui | 20 + src/Mod/Draft/importDXF.py | 17 +- 4 files changed, 246 insertions(+), 204 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 300bc86923..2e7cf692dd 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -107,7 +107,8 @@ def getParamType(param): elif param in ["textheight","tolerance","gridSpacing"]: return "float" elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit","maxSnap", - "SvgLinesBlack","dxfStdSize","showSnapBar","hideSnapBar","alwaysShowGrid"]: + "SvgLinesBlack","dxfStdSize","showSnapBar","hideSnapBar","alwaysShowGrid", + "renderPolylineWidth"]: return "bool" elif param in ["color","constructioncolor","snapcolor"]: return "unsigned" diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index 7ef42e43f0..e1f587ddd4 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,8 +2,8 @@ # Resource object code # -# Created: Fri May 4 19:15:01 2012 -# by: The Resource Compiler for PyQt (Qt v4.7.4) +# Created: Tue May 22 16:46:43 2012 +# by: The Resource Compiler for PyQt (Qt v4.8.1) # # WARNING! All changes made in this file will be lost! @@ -26543,153 +26543,159 @@ qt_resource_data = "\ \x93\x83\x1e\x48\xef\x57\xc6\xa2\x49\xdb\x13\x44\xd4\xba\x3f\x06\ \x46\x3f\xfe\x6c\x03\x93\xf1\x73\xb1\x4b\x54\x79\xc9\xd8\x04\x84\ \x23\xc5\xbe\x37\x98\x7a\x44\xf4\xff\x03\x15\x2c\x14\x99\ -\x00\x00\x09\x10\ +\x00\x00\x09\x69\ \x00\ -\x00\x45\x1d\x78\x9c\xed\x5c\x6d\x73\xdb\x36\x12\xfe\xee\x5f\x81\ -\xd1\x87\xbb\xb4\xe3\x5a\x96\x5f\x93\x9c\xac\x4e\x62\xd7\x49\x6e\ -\x92\x6b\x7a\x72\xd3\xfb\xe6\x81\x48\x48\x44\x4d\x12\x2a\x00\x5a\ -\x52\x7f\xfd\xed\x02\xa0\xf8\x22\xea\xdd\x92\x1c\x8f\x66\x3c\x23\ -\x11\x00\x77\x17\x8b\x67\x17\x8b\xc5\x5a\xcd\x9f\x87\x51\x48\x1e\ -\x99\x54\x5c\xc4\x57\xb5\xc6\xd1\x71\x8d\xb0\xd8\x13\x3e\x8f\x7b\ -\x57\xb5\xdf\xef\x6e\x7f\x7a\x5d\xfb\xb9\x75\xd0\x4c\x78\x36\xe8\ -\x0c\x06\xb5\x0e\x48\xd3\x0b\xa9\x52\xad\x0f\x09\x7f\xfb\xf6\x86\ -\xd3\x50\xf4\xe0\x33\xec\xb5\x99\xd6\xf0\xb2\xba\x91\xb4\xab\x9b\ -\x75\x3b\x08\x46\x0f\xb8\xdf\x63\x9a\x98\xe7\xab\xda\x6f\x7f\x98\ -\xc7\x1a\x89\x69\xc4\xae\x6a\x33\x89\x20\x33\xd2\xec\x4b\xd1\x67\ -\x52\x8f\xdc\x1b\x3d\x26\x22\xa6\xe5\xc8\x74\x92\xa6\x64\x9e\x36\ -\xdf\x48\x73\xd8\x3a\x6e\xd6\x87\xee\x61\x84\x0f\x23\xf7\x00\x22\ -\xe8\xa0\x75\x7e\x79\xde\xac\xdb\xaf\xb6\x39\x60\xbc\x17\xe8\xd6\ -\xc5\xc9\x9b\x66\xdd\x7d\x37\x34\xeb\x29\xd1\x66\x3d\x65\x5e\x25\ -\xc9\x80\xc7\xbe\x18\xdc\x71\x1d\x32\x27\x8c\xd2\x12\x84\x6f\x7d\ -\x8a\xfa\x42\xea\xfa\x2f\x43\xfc\x68\xd6\x5d\xeb\x24\xbd\x90\x8e\ -\x44\x92\x69\xe6\xdb\x7b\x31\xfc\x6c\x9a\x1c\xb9\x12\x3f\xd5\xa7\ -\x1e\x10\xaa\x39\xe9\xe3\x24\xea\x30\xd9\xba\x68\xd6\xdd\x37\x2b\ -\x7b\x9e\xc3\x04\x89\x88\xca\x1e\x8f\x4b\x14\xde\xcc\xa4\xc0\x35\ -\x8b\x32\x35\xe6\x57\xf2\x83\x14\x49\x1f\x64\x1e\xaf\xa5\x7b\x6e\ -\x9c\x38\x06\x13\xec\x75\xa6\xab\x9c\xba\x6e\xfe\x77\x4b\xba\x42\ -\x46\x54\x13\xd1\xd7\x80\x34\x95\xd7\xd9\xa4\x48\xf3\x35\x37\x57\ -\x79\x53\xf5\x57\xc5\x6d\xb6\x16\xa7\x2a\xb2\x9a\x54\xa6\xce\x8a\ -\x79\x7c\x9c\x9c\xc7\x02\x33\x99\x31\x97\x2a\x11\xe6\xcf\x27\x23\ -\x78\xbc\x20\xc1\xc2\xac\x26\x91\xf2\x99\x76\x58\x98\xc2\x44\xb3\ -\xa1\x36\x0d\x8d\xfb\xd3\x3c\xcf\x49\xb4\xc0\xc0\xc2\x80\x92\x81\ -\x11\xa5\x47\x21\x2b\x61\x65\xaa\x8c\xc4\xd8\x3e\x48\x95\x9f\x4a\ -\x51\xee\x39\xd3\x30\xbe\xea\xab\x64\xdd\x6b\x11\x75\x44\x0e\xf8\ -\x3d\xec\xe8\x43\x87\x87\x1d\x1d\xe8\x98\x39\x2d\x21\xc2\x3b\xde\ -\xaf\x9e\xd9\x5d\xc0\x15\x81\x3f\x1d\x30\x02\x6e\x2e\x10\x3e\xf1\ -\x02\x21\x14\xf3\xd1\x44\x08\x37\x13\x87\x81\x04\x1e\xb4\xa4\xb1\ -\x0a\xa9\x79\x44\x1b\x12\x9d\x3f\xc1\x6f\x11\x4f\x84\x38\x32\xd6\ -\x82\xdc\x4a\xc6\xae\xdf\xdd\x1c\x91\x83\x4f\x5d\xd7\x1e\xd1\x7e\ -\x1f\x5f\x00\x1e\x8e\xf0\x21\x01\xc0\x91\x28\x51\xda\xb5\x10\x5a\ -\x1a\xdb\xe5\x21\x83\xa6\x58\x53\x1e\xe3\x33\xcd\x58\x8b\x98\x68\ -\xda\x81\x6e\x1d\x80\xf9\x0e\x78\x18\xe2\x40\xd8\x31\x9c\x1c\xca\ -\x0a\x12\xf2\x98\x19\xcf\xab\x8e\x0e\x16\x5e\xb0\x09\xcd\x79\x89\ -\x94\x2c\xd6\x9f\x62\x9f\x0d\x4b\xea\x9b\x8e\xd7\x45\x89\xe3\xfa\ -\xfd\x12\xe3\xc6\x02\xb8\xf2\x15\xd3\x57\xb5\xe3\x12\x13\xcf\x09\ -\xee\x0f\xbb\x0e\x7a\xde\xaa\x53\x41\x6e\x5f\xa9\x0e\xe6\x33\xfb\ -\x22\xfc\x7a\xba\xa5\x2e\xcc\xad\x04\xe4\x45\x6c\x6b\x0c\xc1\xff\ -\x88\x98\x91\x57\x5d\xaa\x34\x53\xfa\x87\xaa\xd5\x9a\xc6\xb5\x5e\ -\x66\xbb\x96\x1c\xbf\x03\x12\x7d\xd6\xa5\x49\x98\x62\x9a\xc6\x7e\ -\x86\xa4\xdd\x09\xf6\xab\xe4\xe0\x2e\x69\xf8\xbc\xa4\xba\x1e\x9b\ -\x2c\xf8\x8a\xbc\xc9\xed\x50\x24\xc9\xa8\x66\xa4\x4f\x25\xc5\x90\ -\x8d\x7b\xce\x45\x95\xf7\xf7\xed\x8b\xd4\x7e\x60\xda\x0b\xd8\x5a\ -\x82\xcc\xdd\x4f\x9a\x75\xbb\xbd\x67\xd1\x40\xbe\x7b\xe1\x48\xc0\ -\x4d\x2a\x10\x92\xff\x8d\x3e\x38\x9c\x8c\x10\x96\xd9\x7e\x43\x7c\ -\xb8\xbf\x5c\x71\xe7\xfd\x42\x87\xa4\xdd\x47\x6c\x91\x36\xeb\x45\ -\xe0\x8d\x77\xb0\xff\xb6\x61\x57\xaa\xda\x7e\x15\xb4\xc3\xee\x7b\ -\x7f\x32\x73\x72\x11\x1d\xf2\x28\x89\xda\xfc\x6f\x56\x9e\x23\x34\ -\x95\x60\x63\x8f\x0b\x17\xc7\x85\x83\xc3\xb8\xd7\x1d\x1a\x1a\x17\ -\x97\x97\x97\x27\x8d\xf3\xc2\x29\x22\x9b\x64\x99\xec\x62\x3b\xc4\ -\xcc\x30\xe1\x8f\x80\xc5\x84\x0d\xd3\x60\x40\x99\x15\x51\x68\xf6\ -\x10\x08\x1c\x62\xf4\x30\x22\x54\x32\xbb\x4f\x63\x6c\x0d\x3e\x81\ -\xc7\xa4\x2f\xc2\x91\x19\x79\x44\x4c\xa0\xf1\x48\xc3\x84\x8d\xc3\ -\x0d\xab\x17\x12\xb2\xb8\xa7\x03\x22\xba\x84\x51\xcf\x7c\x62\x6f\ -\xfa\x2a\x51\x76\xd9\x81\x04\xc4\x14\xc7\x86\x57\x6c\x46\x0c\x02\ -\x01\x71\x80\x15\xc5\xd0\x34\xa6\xe6\x13\xaa\x20\x60\x00\xb9\x29\ -\xaa\x26\x7d\xfd\x68\xf5\x28\xc0\x08\x5d\xbd\xfd\x9f\x6f\x65\xfb\ -\x07\x45\x39\x85\xa7\x16\xf0\x3c\xc3\x80\x1d\x3b\xa8\x42\x74\xbf\ -\xbc\x8b\x5a\xd1\x41\x5d\x4f\x44\xae\x3b\x70\x50\xb7\xc0\xf6\xda\ -\xc4\xd2\x72\xc2\x49\xa1\x48\x9e\xeb\x9b\xe9\xa6\x20\xd6\x5e\xd2\ -\x4d\x9d\x1e\xcf\xf6\x53\xc7\xdb\x73\x50\x77\x01\xab\x3a\x44\x74\ -\x4b\xc7\x16\x88\xa4\xa7\x9c\x13\x56\xf7\x0f\xcb\x05\xf2\x4e\x3c\ -\x0b\x94\xbd\x1d\x57\xd9\xf1\xe5\xe2\x76\x9c\x1d\x91\x03\xe6\x3d\ -\x54\x1e\x91\xb1\x63\xfe\x26\x3d\x13\x5c\x1c\xb7\x24\x7b\x4e\x4e\ -\x62\x43\x10\x4f\xb1\xe8\x13\x54\x3d\x32\x1f\x64\x20\xe2\x7f\x6a\ -\xd2\x61\xee\xc4\xcc\xfc\xd5\xf1\x34\x37\x0d\x61\x39\xe2\x31\xc0\ -\xe7\xb0\x1f\xa8\x8a\x0c\xd6\x92\x50\x5a\x1c\xbe\xc8\x7b\x8f\xdb\ -\x6a\xdc\x9e\x6c\x04\xb7\x73\x72\x56\x0b\xe2\x76\x8c\xda\x3e\x85\ -\xd7\x09\xe6\xf4\x58\x7a\x3a\xb2\x69\x94\x1c\x76\x21\xae\x13\x1b\ -\xc4\xaf\xd5\xec\xd6\x20\x6b\xd9\xed\x41\x5b\x0d\xda\xb3\x8d\x80\ -\x76\xce\x71\x6f\x16\x68\x0d\x71\x87\xdb\xae\x49\x15\x0e\x68\xac\ -\x4d\xc4\x1f\x8b\xf8\x27\xa4\xe0\x93\x4e\x28\xbc\x07\x45\x5e\x75\ -\x58\x8f\xc7\x26\x47\x38\xe0\x70\x86\xa0\xe4\xc7\x1f\xf0\x50\xb2\ -\x3d\x2c\xff\x68\x25\xd9\x16\x96\x95\xa6\x32\xe5\xb8\xc7\x73\x15\ -\x9e\x5f\x6f\x04\xcf\xe7\x4f\xeb\x84\x53\xc7\xdb\x95\x22\x32\xc8\ -\x56\x40\x07\xfd\x22\x93\x99\x37\xfe\x53\x40\x70\xea\xdb\x38\xd5\ -\x2c\x02\x79\x6f\x56\x1e\x22\x8f\x44\x1a\xcc\xe3\x9b\x3e\x87\xb3\ -\x21\x1d\x11\x93\x3f\x95\x87\xa4\x03\xea\x8a\xe8\x83\xeb\xc6\xd3\ -\xb5\x52\x70\xb0\x56\x3c\x1c\x11\xe6\x73\x93\x3c\xdf\x84\x3d\x98\ -\xcb\xb8\x74\x0a\x46\xe6\x2d\x5a\x46\x0f\x99\x7f\x36\xbc\xf7\x76\ -\x51\x6d\x17\xe7\x1b\xb1\x8b\x37\xab\xdb\x05\xde\x10\xa5\xf6\xd0\ -\x95\x8c\x79\xd4\xb7\xd0\x87\x15\x47\x1f\x8e\xf0\xc7\x44\x3c\x8f\ -\x3d\xee\x33\xf8\x9a\x1a\x8d\x01\xd7\x80\x4b\xcc\x2a\xbd\x67\x03\ -\x2a\xd9\xa1\xb5\x30\x8f\xe2\xe5\xd0\x03\xde\x27\x0d\x02\x38\x5f\ -\x1d\x1d\xad\x91\xf5\x99\x8e\xf4\x7f\x83\x48\x24\xad\x0a\xd8\x0a\ -\xbc\x51\x15\x19\xc3\x3d\xbe\xab\xf0\x7d\xb1\x09\x7c\xaf\x85\xee\ -\x09\xaf\x4f\x01\xdc\x29\x88\x73\xb7\x9b\x5d\x08\xc5\x33\xaf\x6f\ -\x93\xac\x36\x8d\x79\xea\x9b\x34\xa8\x19\xb0\x09\x24\xdb\x82\x11\ -\x72\x7a\x33\x16\x0b\x98\xa6\x1c\x49\xc4\xd4\x94\x1b\x8b\x8d\xe4\ -\x45\x80\xdb\x1e\xdb\xd5\xd8\x6e\x34\x36\xe2\xbc\x5f\x3f\x2d\xbc\ -\xb3\x88\xdb\x66\x44\x10\xd0\x28\x98\x89\x6f\x34\x8d\x7d\x2a\x7d\ -\x17\xc8\xe0\x08\x82\x59\x40\x78\x2b\x86\xb8\x05\x5c\xbf\x4b\xfb\ -\x63\xa3\xbd\x4e\x08\xe8\x23\xc3\x3b\x04\x6c\xc5\x6a\x03\x5f\x78\ -\xc9\x52\xf7\x3f\x4b\x18\x02\x5e\xfd\x8e\x45\xec\x82\xea\xad\x1c\ -\x26\x7b\x88\x93\xd9\x96\x11\xb4\xb5\x8f\xf9\xd7\xbd\x1d\x4c\xb1\ -\x83\xcd\x64\x58\x1a\xc7\x4f\x6b\x08\x01\x35\x77\xbd\x63\x97\xee\ -\x0a\x54\xd2\x58\x5e\x81\xa1\x84\xcc\x46\x30\x1b\x3c\x99\x1a\x29\ -\x48\x47\x24\x88\x6a\xce\x8c\x6f\x5f\x93\xe7\x12\x60\xb6\xce\xe0\ -\x66\xd8\xfd\x48\xdd\xc5\xf7\x4b\x84\x74\xb1\xb3\x40\x2b\x37\x6e\ -\xa5\x92\xc6\xfb\x25\x8b\x1a\xdb\xdf\x3e\x3c\x5d\x51\xa3\xe3\x94\ -\xcb\x3d\x7e\xef\xe5\x8d\xe9\x8c\x0a\xe9\xae\x97\x5b\xe8\x38\x27\ -\x5f\xb1\xf3\x42\x47\x93\x7f\x96\x13\x7e\xbe\x6d\x9a\x0b\xb1\xfc\ -\xa4\xf4\x30\x1a\xc2\x00\x53\x0b\x58\x9a\x04\x03\x95\xb6\x7e\xd3\ -\x6f\xdf\x7e\x1c\x53\x6c\xd6\x4d\xe3\xd2\x4e\x07\xf7\xff\x8f\xe0\ -\xae\xa7\x3b\x9d\xa9\xb7\xa2\x67\xb3\x2f\x45\x4f\xd6\xba\x15\x85\ -\x61\x46\x47\x4b\xe8\x7a\xd5\xa2\xd2\x75\x6e\x1e\x16\x2e\x2b\x45\ -\xb7\x35\xbd\x8e\xf4\xfb\x2f\xdd\x54\x8f\xbd\x7d\xe9\xe6\xbe\x74\ -\xf3\xa9\xa5\xda\x75\x24\xfe\x66\xf1\x40\xbc\xaa\x1a\x70\xce\x5d\ -\xfc\xbc\x84\x45\xfb\x99\xd4\xe1\x83\x71\xdf\xdb\x7c\xcd\xbd\x31\ -\xf2\xfb\xf5\xeb\xf1\xcd\xd4\xf0\x30\x6c\xe2\x39\x2c\x61\xc1\x64\ -\xa7\x04\x01\xc9\xa0\x58\x83\x47\x5d\x51\xe9\xcb\x70\x92\x05\x3d\ -\xbe\x4c\x67\x79\xe7\xea\x90\x60\x0f\x7c\x85\x9b\x60\x5f\x62\x82\ -\xfb\x1f\x34\xea\xff\x2b\xbd\xc5\xd9\xa1\x0b\xfd\x2f\x1d\x58\xb1\ -\xae\xdf\x7d\x59\x4b\x8c\x5d\xbb\xa6\xc2\x69\xfe\xe9\x92\x04\xb3\ -\x63\xd2\x65\x8a\x67\xd1\xb2\x1f\x39\x1b\xa8\x43\xbc\xa8\x63\x26\ -\x2d\x3c\x08\xd0\xc2\xcd\xd6\x20\xe4\x03\xc1\xa2\x7a\x8a\xb1\x10\ -\xe9\x84\xd4\x7b\x38\x34\x41\x53\x87\x69\x0d\x31\xb3\x64\xd4\xa7\ -\x1d\x1e\x72\x60\x4e\x7b\x14\xf3\x67\xee\xf5\x0e\x0c\xc5\x9b\xb0\ -\xd8\xdf\x48\x5e\x61\x8c\xdf\x9c\xb4\x6e\x5f\x33\xb7\x7d\xc0\x7d\ -\x0d\x57\x64\x93\x27\x25\xce\x1d\x50\x6b\x4b\xcb\x04\x3c\x82\xf9\ -\xba\x49\x27\xd4\x7e\xec\x7d\xc6\x1a\xdb\xf7\x76\x22\xcf\xd3\x03\ -\x3d\xdf\x74\xc5\xf8\xb0\xb0\x58\xba\xe2\xd7\xeb\x77\x4f\x9f\xae\ -\xc8\x6c\xf4\xa5\xa4\x2b\x0a\xa5\x90\xdf\x7d\xba\x62\x09\x77\x7b\ -\xb6\xba\xbb\x9d\x51\x40\x44\xc1\x79\x2a\xf2\xea\xf4\xc6\x5e\xba\ -\x55\xd5\x0a\x6d\xe4\xca\xd8\xa5\x55\x10\xf4\x46\x84\xad\xa4\x60\ -\x85\x47\x1d\xb3\xbd\x2f\x33\x6b\x91\xcf\x39\x61\x42\x9e\x7b\x69\ -\xc6\x69\x9a\xef\xaa\x4a\x35\x65\x59\xa6\x6f\x8e\x46\x21\xc7\x34\ -\xe9\xb7\x96\xc8\x2c\x15\x93\x4a\x2e\x9f\x74\x32\x91\x4f\x4a\x53\ -\x49\x67\x13\xa9\xa4\x42\x16\xa9\x2c\x4a\x21\x77\x94\x29\x29\xa7\ -\xc9\x9c\x1a\x9d\x73\x4a\x4f\xd5\xce\xd9\x5c\xd5\x2e\x6a\xc4\xba\ -\x89\xab\x5a\xa3\x51\xab\xe3\xc8\x3e\x1f\x46\xb4\xdf\x4d\x62\x0f\ -\x15\xd5\xfa\xeb\xab\x79\xbe\x95\x22\xfa\xc2\x23\xd6\x16\x89\xf4\ -\x60\x03\x2f\x8d\xc2\x9f\x75\x48\x94\x16\x91\xe5\xa8\x8c\x24\xf9\ -\x16\x2b\x65\xee\xa7\x1f\x72\xff\xe4\x90\xfd\xda\x03\xae\xc7\x50\ -\x33\x08\x79\x5a\xee\x97\x1e\x60\x35\x5c\xc3\x81\x55\x15\xf5\x61\ -\xca\x40\xa1\x8e\x04\xec\x4f\x3f\x1c\x05\xa8\x38\xd3\x61\x14\x50\ -\xe6\x3b\x5b\x90\xd2\x7f\x5c\x54\x0a\x33\x29\xf1\x34\xa9\x90\x9a\ -\x95\x5c\xad\x2f\x96\xfb\x4f\xb5\x6a\xfd\x8c\x3b\xb7\x22\x4a\xea\ -\xe3\xab\x65\xc9\x7a\xb7\x23\x8c\x3b\xb9\x4f\x11\x66\xdc\xbb\xbe\ -\x30\xc5\x06\xf3\x83\x24\x92\x29\x63\x03\xca\x58\x8b\x27\xe2\x98\ -\x19\x1b\xc0\xe7\x66\x3d\xe1\xad\x83\xff\x03\xad\x19\x30\x45\ +\x00\x48\x24\x78\x9c\xed\x5c\x5b\x73\xdb\xb6\x12\x7e\xf7\xaf\xc0\ +\xe8\xe1\x9c\xb4\xe3\x5a\x92\xaf\x49\x8e\xac\x4e\x62\xd7\x49\x3a\ +\xc9\x69\x5a\xb9\x49\xdf\x3c\x10\x09\x89\xa8\x49\x42\x05\x40\x4b\ +\xea\xaf\xef\x2e\x00\x8a\x14\x45\xdd\x2d\xc9\x71\x35\xe3\x19\x8b\ +\x00\x88\x5d\x2c\xbe\x5d\xec\x2e\x56\x6a\xfc\x38\x88\x42\xf2\xc0\ +\xa4\xe2\x22\xbe\xac\xd4\x8f\x6a\x15\xc2\x62\x4f\xf8\x3c\xee\x5e\ +\x56\x7e\xbf\xbd\xf9\xe1\x65\xe5\xc7\xe6\x41\x23\xe1\xd9\xa0\x53\ +\x18\xd4\x3c\x20\x0d\x2f\xa4\x4a\x35\xdf\x25\xfc\xf5\xeb\x6b\x4e\ +\x43\xd1\x85\xff\x61\xb7\xc5\xb4\x86\x97\xd5\xb5\xa4\x1d\xdd\xa8\ +\xda\x41\x30\xba\xcf\xfd\x2e\xd3\xc4\x3c\x5f\x56\x7e\xfd\x6a\x1e\ +\x2b\x24\xa6\x11\xbb\xac\xcc\x9c\x04\x89\x91\x46\x4f\x8a\x1e\x93\ +\x7a\xe8\xde\xe8\x32\x11\x31\x2d\x87\xa6\x93\x34\x24\xf3\xb4\xf9\ +\x44\x1a\x83\x66\xad\x51\x1d\xb8\x87\x21\x3e\x0c\xdd\x03\xb0\xa0\ +\x83\xe6\xd9\xc5\x59\xa3\x6a\x3f\xda\xe6\x80\xf1\x6e\xa0\x9b\xe7\ +\xc7\xaf\x1a\x55\xf7\xd9\xcc\x59\x4d\x27\x6d\x54\x53\xe2\x65\x9c\ +\xf4\x79\xec\x8b\xfe\x2d\xd7\x21\x73\xcc\x28\x2d\x81\xf9\xe6\x87\ +\xa8\x27\xa4\xae\xfe\x34\xc0\x7f\x8d\xaa\x6b\x9d\x9c\x2f\xa4\x43\ +\x91\x64\x92\xf9\xf2\x56\x0c\x3e\x9a\x26\x37\x5d\x81\x9e\xea\x51\ +\x0f\x26\xaa\x38\xee\xe3\x24\x6a\x33\xd9\x3c\x6f\x54\xdd\x27\xcb\ +\x7b\x9e\xc2\xc4\x14\x11\x95\x5d\x1e\x17\x66\x78\x35\x73\x06\xae\ +\x59\x94\x89\x31\xbf\x93\xef\xa4\x48\x7a\xc0\xf3\x68\x2f\xdd\x73\ +\xfd\xd8\x11\x98\x20\xaf\x33\x59\xe5\xc4\x75\xfd\xc7\x0d\xe9\x08\ +\x19\x51\x4d\x44\x4f\x03\xd2\x54\x5e\x66\x93\x2c\xcd\x97\xdc\x5c\ +\xe1\x4d\x95\x5f\x19\xb5\xd9\x52\x9c\x2a\xc8\xf2\xa9\x32\x71\x96\ +\xac\xe3\xfd\xe4\x3a\x16\x58\xc9\x8c\xb5\x94\xb1\x30\x7f\x3d\xd9\ +\x84\xb5\x05\x27\x1c\x5b\xd5\x24\x52\x3e\xd2\x36\x0b\x53\x98\x68\ +\x36\xd0\xa6\xa1\x7e\x77\x92\xa7\x39\x89\x16\x18\x38\x36\xa0\xa0\ +\x60\x44\xe9\x61\xc8\x0a\x58\x99\xca\x23\x31\xba\x0f\x5c\xe5\x97\ +\x32\xce\xf7\x9c\x65\x18\x5b\xf5\x59\xb2\xce\x95\x88\xda\x22\x07\ +\xfc\x2e\x76\xf4\xa0\xc3\xc3\x8e\x36\x74\xcc\x5c\x96\x10\xe1\x2d\ +\xef\x95\xaf\xec\x36\xe0\x8a\xc0\x9f\x0e\x18\x01\x33\x17\x08\x9f\ +\x78\x81\x10\x8a\xf9\xa8\x22\x84\x9b\x85\xc3\x40\x02\x0f\x5a\xd2\ +\x58\x85\xd4\x3c\xa2\x0e\x89\xf6\x9f\x60\xb7\x88\x27\x42\x1c\x19\ +\x6b\x41\x6e\x24\x63\x57\x6f\xae\x8f\xc8\xc1\x87\x8e\x6b\x8f\x68\ +\xaf\x87\x2f\x00\x0d\x37\xf1\x21\x01\xc0\x91\x28\x51\xda\xb5\x10\ +\x5a\x18\xdb\xe1\x21\x83\xa6\x58\x53\x1e\xe3\x33\xcd\x48\x8b\x98\ +\x68\xda\x86\x6e\x1d\x80\xfa\xf6\x79\x18\xe2\x40\x38\x31\x1c\x1f\ +\xca\x32\x12\xf2\x98\x19\xcb\xab\x8e\x0e\x16\xde\xb0\x09\xc9\x79\ +\x89\x94\x2c\xd6\x1f\x62\x9f\x0d\x0a\xe2\x9b\x8e\xd7\x45\x27\xc7\ +\xfd\xfb\x29\xc6\x83\x05\x70\xe5\x2b\xa6\x2f\x2b\xb5\x02\x11\xcf\ +\x31\xee\x0f\x3a\x0e\x7a\xde\xaa\x4b\x41\x6a\x9f\xa9\x0e\xe6\x13\ +\xfb\x24\xfc\x6a\x7a\xa4\x2e\x4c\xad\x00\xe4\x45\x74\x6b\x04\xc1\ +\xff\x8b\x98\x91\x17\x1d\xaa\x34\x53\xfa\xbb\xb2\xdd\x9a\x46\xb5\ +\x5a\x24\xbb\x16\x1f\xbf\x03\x12\x7d\xd6\xa1\x49\x98\x62\x9a\xc6\ +\x7e\x86\xa4\xdd\x31\xf6\x8b\xe4\x60\x2e\x69\xf8\xb4\xb8\xba\x1a\ +\xa9\x2c\xd8\x8a\xbc\xca\xed\x90\x25\xc9\xa8\x66\xa4\x47\x25\x45\ +\x97\x8d\x7b\xce\x44\x15\xcf\xf7\xed\xb3\xd4\xba\x67\xda\x0b\xd8\ +\x5a\x8c\xcc\x3d\x4f\x1a\x55\x7b\xbc\x67\xde\x40\xbe\x7b\x61\x4f\ +\xc0\x2d\x2a\x10\x92\xff\x8d\x36\x38\x9c\xf4\x10\x96\x39\x7e\x43\ +\x7c\xb8\xbb\x58\xf1\xe4\xfd\x44\x07\xa4\xd5\x43\x6c\x91\x16\xeb\ +\x46\x60\x8d\x77\x70\xfe\xb6\xe0\x54\x2a\x3b\x7e\x15\xb4\xc3\xe9\ +\x7b\x77\x3c\x73\x71\x11\x1d\xf0\x28\x89\x5a\xfc\x6f\x56\x5c\x23\ +\x34\x15\x60\x63\xc3\x85\xf3\xda\x58\xe0\x30\xea\x75\x41\x43\xfd\ +\xfc\xe2\xe2\xe2\xb8\x7e\x36\x16\x45\x64\x8b\x2c\x4e\xbb\xd8\x09\ +\x31\xd3\x4d\xf8\x1a\xb0\x98\xb0\x41\xea\x0c\x28\xb3\x23\x0a\xd5\ +\x1e\x1c\x81\x43\xf4\x1e\x86\x84\x4a\x66\xcf\x69\xf4\xad\xc1\x26\ +\xf0\x98\xf4\x44\x38\x34\x23\x8f\x88\x71\x34\x1e\x68\x98\xb0\x91\ +\xbb\x61\xe5\x42\x42\x16\x77\x75\x40\x44\x87\x30\xea\x99\xff\xd8\ +\x9b\xbe\x4a\x94\xdd\x76\x98\x02\x7c\x8a\x9a\xa1\x15\x9b\x11\xfd\ +\x40\x80\x1f\x60\x59\x31\x73\x1a\x55\xf3\x09\x55\xe0\x30\x00\xdf\ +\x14\x45\x93\xbe\x7e\xb4\xba\x17\x60\x98\x2e\x3f\xfe\xcf\xb6\x72\ +\xfc\x83\xa0\x9c\xc0\x53\x0d\x78\x9a\x6e\xc0\x8e\x0d\xd4\x98\x77\ +\xbf\xbc\x89\x5a\xd1\x40\x5d\x4d\x78\xae\x3b\x30\x50\x37\x40\xf6\ +\xca\xf8\xd2\x72\xc2\x48\x21\x4b\x9e\xeb\x9b\x69\xa6\xc0\xd7\x5e\ +\xd2\x4c\x9d\xd4\x66\xdb\xa9\xda\xf6\x0c\xd4\x6d\xc0\xca\x82\x88\ +\x4e\x21\x6c\x01\x4f\x7a\x4a\x9c\xb0\xba\x7d\x58\xce\x91\x77\xec\ +\x59\xa0\xec\xf5\xb8\x4c\x8f\x2f\x16\xd7\xe3\x2c\x44\x0e\x98\x77\ +\x5f\x1a\x22\x63\xc7\xfc\x43\x7a\x26\xb8\x38\x1e\x49\x36\x4e\x4e\ +\x62\x33\x21\x46\xb1\x68\x13\x54\x35\x32\xff\x48\x5f\xc4\xff\xd5\ +\xa4\xcd\x5c\xc4\xcc\xfc\xd5\xf1\x34\x37\x0d\x61\x29\x62\x18\xe0\ +\x73\x38\x0f\x54\x49\x06\x6b\x49\x28\x2d\x0e\x5f\xa4\xbd\xc7\x6d\ +\x39\x6e\x8f\x37\x82\xdb\x39\x39\xab\x05\x71\x3b\x42\x6d\x8f\xc2\ +\xeb\x04\x73\x7a\x2c\x8d\x8e\x6c\x1a\x25\x87\x5d\xf0\xeb\xc4\x06\ +\xf1\x6b\x25\xbb\x35\xc8\x5a\x72\x7b\xd0\x96\x83\xf6\x74\x23\xa0\ +\x9d\x13\xee\xcd\x02\xad\x99\xdc\xe1\xb6\x63\x52\x85\x7d\x1a\x6b\ +\xe3\xf1\xc7\x22\xfe\x01\x67\xf0\x49\x3b\x14\xde\xbd\x22\x2f\xda\ +\xac\xcb\x63\x93\x23\xec\x73\x88\x21\x28\xf9\xfe\x3b\x0c\x4a\xb6\ +\x87\xe5\xef\x2d\x27\xdb\xc2\xb2\xd2\x54\xa6\x14\xf7\x78\x2e\xc3\ +\xf3\xcb\x8d\xe0\xf9\xec\x71\x8d\x70\x6a\x78\x3b\x52\x44\x06\xd9\ +\x0a\xe6\x41\xbb\xc8\x64\x66\x8d\xff\x14\xe0\x9c\xfa\xd6\x4f\x35\ +\x9b\x40\xde\x9a\x9d\x07\xcf\x23\x91\x06\xf3\xf8\xa6\xcf\x21\x36\ +\xa4\x43\x62\xf2\xa7\xf2\x90\xb4\x41\x5c\x11\xbd\x77\xdd\x18\x5d\ +\x2b\x05\x81\xb5\xe2\xe1\x90\x30\x9f\x9b\xe4\xf9\x26\xf4\xc1\x5c\ +\xc6\xa5\x4b\x30\x3c\x6f\x51\x33\xba\x48\xfc\xa3\xa1\xbd\xd7\x8b\ +\x72\xbd\x38\xdb\x88\x5e\xbc\x5a\x5d\x2f\xf0\x86\x28\xd5\x87\x8e\ +\x64\xcc\xa3\xbe\x85\x3e\xec\x38\xda\x70\x84\x3f\x26\xe2\x79\xec\ +\x71\x9f\xc1\xc7\x54\x69\x0c\xb8\xfa\x5c\x62\x56\xe9\x2d\xeb\x53\ +\xc9\x0e\xad\x86\x79\x14\x2f\x87\xee\xf1\x3e\xa9\x1f\x40\x7c\x75\ +\x74\xb4\x46\xd6\x67\x3a\xd2\x7f\x06\x96\x48\x5a\x15\xb0\x15\x78\ +\xa3\x28\x32\x82\x7b\x7c\x97\xe1\xfb\x7c\x13\xf8\x5e\x0b\xdd\x13\ +\x56\x9f\x02\xb8\x53\x10\xe7\x6e\x37\x3b\xe0\x8a\x67\x56\xdf\x26\ +\x59\x6d\x1a\xf3\xc4\x37\x69\x50\x33\x60\x13\x48\xb6\x05\x23\xe4\ +\xe4\x7a\xc4\x16\x10\x4d\x29\x92\x88\xa9\x29\x37\x16\x1b\xc9\x8b\ +\x00\xb5\x3d\xb6\xcb\xb1\x5d\xaf\x6f\xc4\x78\xbf\x7c\x5c\x78\x67\ +\x1e\xb7\xcd\x88\x20\xa0\x91\x31\xe3\xdf\x68\x1a\xfb\x54\xfa\xce\ +\x91\xc1\x11\x04\xb3\x80\xf0\x56\x0c\x7e\x0b\x98\x7e\x97\xf6\xc7\ +\x46\x7b\x9d\x10\xd0\x07\x86\x77\x08\xd8\x8a\xd5\x06\xbe\xf0\x92\ +\xa5\xee\x7f\x96\x50\x04\xbc\xfa\x1d\xb1\xd8\x01\xd1\x5b\x3e\x4c\ +\xf6\x10\x17\xb3\x2d\x25\x68\x69\x1f\xf3\xaf\x7b\x3d\x98\xa2\x07\ +\x9b\xc9\xb0\xd4\x6b\x8f\xab\x08\x01\x35\x77\xbd\x23\x93\xee\x0a\ +\x54\x52\x5f\x5e\x81\xa2\x84\xcc\x7a\x30\x1b\x8c\x4c\x0d\x17\xa4\ +\x2d\x12\x44\x35\x67\xc6\xb6\xaf\x49\x73\x09\x30\x5b\x63\x70\x3d\ +\xe8\xbc\xa7\xee\xe2\x7b\x0f\xe9\x52\x48\x2f\x71\x69\xb5\x0c\xa4\ +\xeb\x8f\x0b\xe9\x3e\x5e\xba\x8e\x6e\x73\xad\x6d\x06\x2f\x1b\x6f\ +\x4e\xb0\x66\x06\x03\x55\x77\x0b\x9c\x82\x5e\xb2\xd8\x67\xd2\xfa\ +\x31\x5e\x68\x0a\xca\x0c\xfa\x6c\xa2\x46\x9b\xeb\x1a\x89\x75\xaf\ +\x64\x6a\xd1\xc8\xba\x8a\xf0\x9b\x61\x21\xc7\xb6\x21\xbd\x26\xb9\ +\x25\x74\xc0\x8a\xe0\xb3\x23\xff\xd5\xd2\x7d\x8e\x6a\x30\xde\x39\ +\x36\x57\x6e\xdc\x4a\x95\xbd\x77\x4b\xd6\xf6\xb6\xbe\xbc\x7b\xbc\ +\xda\x5e\x47\x29\x97\x82\xff\xd6\xab\x7c\xd3\x15\x8d\x65\x7d\x9f\ +\x6f\xbd\xef\x9c\xb4\xdd\xce\xeb\x7d\xcd\x35\x8c\x9c\x38\x1b\x5a\ +\xa6\x79\x2c\xa4\x9d\xe4\x1e\x46\x83\x37\x6c\x4a\x62\x0b\x8b\x60\ +\x20\xd2\xe6\xaf\xfa\xf5\xeb\xf7\xa3\x19\x1b\x55\xd3\xb8\xb4\xd1\ +\x41\x37\xf8\x3d\x78\x2d\xd3\x8d\xce\xd4\xe2\x80\xd3\xd9\xb5\x01\ +\xc7\x6b\x15\x07\xc0\x30\x23\xa3\x25\x64\xbd\x6a\x6d\xf5\x3a\x17\ +\x70\x0b\x57\x57\xa3\xd9\x9a\x5e\x4e\xfd\xed\x57\x30\xab\x87\xee\ +\xbe\x82\x79\xe3\xc5\xa6\xff\xba\x0a\xe6\x5d\x7b\xef\xaf\x16\x77\ +\xde\xcb\x8a\x62\xe7\x94\xa4\xcc\xcb\xdb\xb5\x9e\xc8\xd7\x51\x40\ +\xb9\xef\x6c\xda\xf2\xce\x28\xf9\xdd\xfa\x5f\x4b\x31\x4b\xc3\x9c\ +\x90\xf1\xe7\xb0\x92\x0b\x73\xfe\x12\x18\xb4\xa1\x48\x56\x8a\x4a\ +\x5d\x6d\xf5\xf3\x30\x92\x63\x72\x7c\x9e\xc6\xf2\xd6\x95\xe3\xc1\ +\x19\xf8\x02\x0f\xc1\x9e\xc4\x7b\x9e\xff\xd0\xa8\xf7\xbf\xf4\x32\ +\x73\x87\x26\xf4\x37\xda\xb7\x6c\x5d\xbd\xf9\xb4\x16\x1b\xbb\x36\ +\x4d\x63\x49\xad\xc7\x4b\x2c\xcc\xf6\x49\x97\xa9\x21\x47\xcd\x7e\ +\xe0\xac\xaf\x0e\xf1\xbe\x9a\x99\xdb\x91\x7e\x80\x1a\x6e\x8e\x06\ +\x21\xef\x09\x7e\xb7\x84\xa2\x2f\x44\xda\x21\xf5\xee\x0f\x8d\xd3\ +\xd4\x66\x5a\x83\xcf\x2c\x19\xf5\x69\x9b\x87\x1c\x88\xd3\x2e\xc5\ +\x34\xb2\x7b\xbd\x0d\x43\xf1\x42\x38\xf6\x37\x92\x5e\x1b\xe1\x37\ +\xc7\xad\x3b\xd7\xcc\xa5\x37\x50\x5f\xc3\x14\xd9\x84\x4b\x81\x72\ +\x1b\xc4\xda\xd4\x32\x01\x8b\x60\x3e\x6e\xd2\x08\xb5\x1e\xba\x1f\ +\x31\x59\xf2\xd6\x2e\xe4\x69\x5a\xa0\xa7\x9b\xae\x18\x05\x0b\x8b\ +\xa5\x2b\x7e\xb9\x7a\xf3\xf8\xe9\x8a\x4c\x47\x9f\x4b\xba\x62\xac\ +\x22\xf8\x9b\x4f\x57\x2c\x61\x6e\x4f\x57\x37\xb7\x33\xea\xe8\x28\ +\x18\x4f\x45\x5e\x9c\x5c\xdb\xbb\xe7\xb2\x92\xb9\x8d\x54\x4e\xb8\ +\xb4\x0a\x82\xde\xb0\xb0\x95\x2c\xac\xf0\xa8\x23\xb6\xb7\x65\x66\ +\x2f\xf2\x39\x27\xbc\x97\xe2\x5e\x9a\x71\x9a\x66\xbb\xca\x52\x4d\ +\x59\x96\xe9\x8b\x9b\x63\x2c\xc7\x34\x69\xb7\x96\xc8\x2c\x8d\x27\ +\x95\x5c\x3e\xe9\x78\x22\x9f\x94\xa6\x92\x4e\x27\x52\x49\x63\x59\ +\xa4\x22\x2b\x63\xb9\xa3\x4c\x48\x39\x49\xe6\xc4\xe8\x8c\x53\x1a\ +\x55\x3b\x63\x73\x59\x39\xaf\x10\x6b\x26\x2e\x2b\xf5\x7a\xa5\x8a\ +\x23\x7b\x7c\x10\xd1\x5e\x27\x89\x3d\x14\x54\xf3\xaf\xcf\xe6\xf9\ +\x46\x8a\xe8\x13\x8f\x58\x4b\x24\xd2\x83\x03\xbc\x30\x0a\x7f\xdd\ +\x24\x51\x5a\x44\x96\xa2\x32\x9c\xe4\x5b\x2c\x97\xb9\x5f\x40\xc9\ +\x7d\xd7\x27\xfb\xd1\x13\xdc\x8f\x81\x66\xe0\xf2\x34\xdd\x0f\x9e\ +\xc0\x6e\xb8\x86\x03\x2b\x2a\xea\xc3\x92\x61\x86\x2a\x4e\x60\x7f\ +\x01\xe5\x28\x40\xc1\x99\x0e\x23\x80\x22\xdd\xd9\x8c\x14\xbe\x78\ +\x54\xca\xcc\x24\xc7\xd3\xb8\xc2\xd9\x2c\xe7\x6a\x7d\xb6\xdc\x17\ +\x36\xcb\xe5\x33\xea\xdc\x0a\x2b\xa9\x8d\x2f\xe7\x25\xeb\xdd\x0e\ +\x33\x2e\x72\x9f\xc2\xcc\xa8\x77\x7d\x66\xc6\x1b\xcc\xef\xf2\x48\ +\xa6\x8c\x0e\x28\xa3\x2d\x9e\x88\x63\x66\x74\x00\x9f\x1b\xd5\x84\ +\x37\x0f\xfe\x01\xbd\x89\x17\xfc\ \x00\x00\x0f\x9f\ \x00\ \x00\xa2\x2c\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ @@ -37791,61 +37797,61 @@ qt_resource_struct = "\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x6b\xbd\ -\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xbd\x6a\ -\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x1f\x87\ -\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xde\x6f\ -\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x08\x51\ -\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x89\x07\ -\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe1\xa5\ -\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb2\xd6\ -\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x59\x16\ -\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xfa\x7f\ -\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xd6\x8c\ -\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xe7\x69\ -\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x76\x71\ -\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xdc\x0b\ -\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa1\xcc\ -\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xcc\x20\ -\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc0\xb5\ -\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x97\xb4\ -\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x23\x70\ -\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xac\xbf\ -\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xb7\x21\ -\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x11\x57\ -\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x8f\xfb\ -\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x08\x5d\ -\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x69\x5e\ -\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x34\xe0\ -\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x80\x11\ -\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xc9\x78\ -\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xf7\x73\ -\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xe9\x09\ -\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x4c\x1f\ -\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\x9f\xbb\ -\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x06\x58\ -\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\x9d\x98\ -\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb4\xdb\ -\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x28\x30\ -\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xc9\x42\ -\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x5e\x5e\ -\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xbf\xc7\ -\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x44\x85\ -\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x06\xfe\x10\ -\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xdb\x30\ -\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x2f\x61\ -\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x5f\x8b\ -\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x07\xfc\xeb\ -\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x0f\xb1\ -\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd3\xed\ -\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x92\xe8\ -\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xef\x2a\ -\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xed\x19\ -\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x3c\xc5\ -\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x98\x58\ -\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x2f\x81\ +\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x6c\x16\ +\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xbd\xc3\ +\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x1f\xe0\ +\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xde\xc8\ +\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x08\xaa\ +\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x89\x60\ +\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe1\xfe\ +\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb3\x2f\ +\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x59\x6f\ +\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xfa\xd8\ +\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xd6\xe5\ +\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xe7\xc2\ +\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x76\xca\ +\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xdc\x64\ +\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa2\x25\ +\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xcc\x79\ +\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc1\x0e\ +\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x98\x0d\ +\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x23\xc9\ +\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xad\x18\ +\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xb7\x7a\ +\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x11\xb0\ +\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x90\x54\ +\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x08\xb6\ +\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x69\xb7\ +\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x35\x39\ +\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x80\x6a\ +\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xc9\xd1\ +\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xf7\xcc\ +\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xe9\x62\ +\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x4c\x78\ +\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x14\ +\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x06\xb1\ +\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\x9d\xf1\ +\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb5\x34\ +\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x28\x89\ +\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xc9\x9b\ +\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x5e\xb7\ +\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xc0\x20\ +\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x44\xde\ +\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x06\xfe\x69\ +\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xdb\x89\ +\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x2f\xba\ +\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x5f\xe4\ +\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x07\xfd\x44\ +\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x10\x0a\ +\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd4\x46\ +\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x93\x41\ +\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xef\x83\ +\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xed\x72\ +\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x3d\x1e\ +\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x98\xb1\ +\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x2f\xda\ \x00\x00\x02\xaa\x00\x01\x00\x00\x00\x01\x00\x06\x77\x44\ -\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x80\x58\ +\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x80\xb1\ " def qInitResources(): diff --git a/src/Mod/Draft/Resources/ui/userprefs-import.ui b/src/Mod/Draft/Resources/ui/userprefs-import.ui index 09d5ee1c21..a14084d3b3 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-import.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-import.ui @@ -320,6 +320,26 @@ If color mapping is choosed, you must choose a color mapping file containing a t + + + + + + If this is checked, when polylines have a width defined, they will be rendered as closed wires with the correct width + + + Render polylines with width + + + renderPolylineWidth + + + Mod/Draft + + + + + diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index f71e101666..ba8fa2909d 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -202,6 +202,7 @@ class fcformat: self.makeBlocks = params.GetBool("groupLayers") self.stdSize = params.GetBool("dxfStdSize") self.importDxfHatches = params.GetBool("importDxfHatches") + self.renderPolylineWidth = params.GetBool("renderPolylineWidth") bparams = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View") if self.paramstyle > 1: @@ -403,7 +404,21 @@ def drawPolyline(polyline,shapemode=False,num=None): warn(polyline,num) if edges: try: - if (fmt.paramstyle >= 4) and (not curves) and (not shapemode): + width = rawValue(polyline,43) + if width and fmt.renderPolylineWidth: + w = Part.Wire(edges) + w1 = w.makeOffset(width/2) + if polyline.closed: + w2 = w.makeOffset(-width/2) + w1 = Part.Face(w1) + w2 = Part.Face(w2) + if w1.BoundBox.DiagonalLength > w2.BoundBox.DiagonalLength: + return w1.cut(w2) + else: + return w2.cut(w1) + else: + return Part.Face(w1) + elif (fmt.paramstyle >= 4) and (not curves) and (not shapemode): ob = Draft.makeWire(verts) ob.Closed = polyline.closed return ob From 7e028e94704da6a216f8e328a1b432430e46ec84 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 22 May 2012 17:29:50 -0300 Subject: [PATCH 252/351] Fixed 0000701 : Draft Wire naming --- src/Mod/Draft/Draft.py | 2 +- src/Mod/Draft/DraftTools.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 2e7cf692dd..7b1c5dc8f3 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -528,7 +528,7 @@ def makeWire(pointslist,closed=False,placement=None,face=True,support=None): print closed if placement: typecheck([(placement,FreeCAD.Placement)], "makeWire") if len(pointslist) == 2: fname = "Line" - else: fname = "Wire" + else: fname = "DWire" obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",fname) _Wire(obj) obj.Points = pointslist diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index bde2ad4a76..d137c5228c 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -416,7 +416,7 @@ class Line(Creator): todo.delay(self.doc.removeObject,old) self.obj = None if (len(self.node) > 1): - self.commit(translate("draft","Create Wire"), + self.commit(translate("draft","Create DWire"), partial(Draft.makeWire,self.node,closed, face=self.ui.fillmode,support=self.support)) if self.ui: @@ -456,7 +456,7 @@ class Line(Creator): if ((point-self.node[0]).Length < Draft.tolerance()): self.undolast() self.finish(True,cont=True) - msg(translate("draft", "Wire has been closed\n")) + msg(translate("draft", "DWire has been closed\n")) def undolast(self): "undoes last line segment" @@ -523,10 +523,10 @@ class Wire(Line): def GetResources(self): return {'Pixmap' : 'Draft_Wire', 'Accel' : "W, I", - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Wire"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Creates a multiple-point wire. CTRL to snap, SHIFT to constrain")} + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "DWire"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Wire", "Creates a multiple-point DraftWire (DWire). CTRL to snap, SHIFT to constrain")} def Activated(self): - Line.Activated(self,name=str(translate("draft","Wire"))) + Line.Activated(self,name=str(translate("draft","DWire"))) class BSpline(Line): From 260d12bc9f47b047f71ddf7c03ce2cd22bd1d1d9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 11:48:43 +0200 Subject: [PATCH 253/351] 0000710: merge project annoyance --- src/Gui/CommandDoc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index 02e0434902..46c5f56819 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -281,7 +281,7 @@ void StdCmdMergeProjects::activated(int iMsg) { QString exe = QString::fromUtf8(App::GetApplication().getExecutableName()); QString project = QFileDialog::getOpenFileName(Gui::getMainWindow(), - QString::fromUtf8(QT_TR_NOOP("Merge project")), QString(), + QString::fromUtf8(QT_TR_NOOP("Merge project")), QDir::homePath(), QString::fromUtf8(QT_TR_NOOP("%1 document (*.fcstd)")).arg(exe)); if (!project.isEmpty()) { App::Document* doc = App::GetApplication().getActiveDocument(); From c156fc6e9c6c9b2b682393b7cd7212164720b61f Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 12:07:04 +0200 Subject: [PATCH 254/351] 0000717: Version info causes crash --- src/App/ApplicationPy.cpp | 41 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/App/ApplicationPy.cpp b/src/App/ApplicationPy.cpp index d74b1b4a75..15781cc3d0 100644 --- a/src/App/ApplicationPy.cpp +++ b/src/App/ApplicationPy.cpp @@ -383,23 +383,36 @@ PyObject* Application::sGetVersion(PyObject * /*self*/, PyObject *args,PyObject if (!PyArg_ParseTuple(args, "")) // convert args: Python->C return NULL; // NULL triggers exception - PyObject* pList = PyList_New(5); - PyObject *pItem; - pItem = PyString_FromString(Application::Config()["BuildVersionMajor"].c_str()); - PyList_SetItem(pList, 0, pItem); - pItem = PyString_FromString(Application::Config()["BuildVersionMinor"].c_str()); - PyList_SetItem(pList, 1, pItem); - pItem = PyString_FromString(Application::Config()["BuildRevision"].c_str()); - PyList_SetItem(pList, 2, pItem); - pItem = PyString_FromString(Application::Config()["BuildRepositoryURL"].c_str()); - PyList_SetItem(pList, 4, pItem); - pItem = PyString_FromString(Application::Config()["BuildCurrentDate"].c_str()); - PyList_SetItem(pList, 6, pItem); + Py::List list; + const std::map& cfg = Application::Config(); + std::map::const_iterator it; - return pList; + it = cfg.find("BuildVersionMajor"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildVersionMinor"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRevision"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRepositoryURL"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRevisionDate"); + list.append(Py::String(it != cfg.end() ? it->second : "")); + + it = cfg.find("BuildRevisionBranch"); + if (it != cfg.end()) + list.append(Py::String(it->second)); + + it = cfg.find("BuildRevisionHash"); + if (it != cfg.end()) + list.append(Py::String(it->second)); + + return Py::new_reference_to(list); } - PyObject* Application::sAddImportType(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) { char *psKey,*psMod; From 6774f160beb26022f7940b2e585bddfe4bb7dacb Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 15:03:19 +0200 Subject: [PATCH 255/351] 0000716: src/Tools/PyTools.c: strange assignment and a memory leak --- src/Base/PyTools.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Base/PyTools.c b/src/Base/PyTools.c index 2346f80cc3..d204ae72d2 100644 --- a/src/Base/PyTools.c +++ b/src/Base/PyTools.c @@ -377,8 +377,10 @@ const char *PP_Init(const char *modname) { //#ifdef FC_OS_LINUX /* cannot convert `const char *' to `char *' in assignment */ if (modname!=NULL) return modname; { /* we assume here that the caller frees allocated memory */ - char* __main__=(char *)malloc(sizeof("__main__")); - return __main__="__main__"; + // #0000716: strange assignment and a memory leak + return "__main__"; + //char* __main__=(char *)malloc(sizeof("__main__")); + //return __main__="__main__"; } //#else // return modname == NULL ? "__main__" : modname; /* default to '__main__' */ From 432a460fda32347b3884135f9ba5904e44e375d9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 15:03:48 +0200 Subject: [PATCH 256/351] Expose merge project function to python --- src/Gui/CommandDoc.cpp | 3 --- src/Gui/DocumentPy.xml | 5 +++++ src/Gui/DocumentPyImp.cpp | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index 46c5f56819..b9d0ea68b0 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -294,9 +294,6 @@ void StdCmdMergeProjects::activated(int iMsg) return; } - QString dir1 = proj.absoluteDir().filePath(proj.baseName()); - QString dir2 = info.absoluteDir().filePath(info.baseName()); - Base::FileInfo fi((const char*)project.toUtf8()); Base::ifstream str(fi, std::ios::in | std::ios::binary); MergeDocuments md(doc); diff --git a/src/Gui/DocumentPy.xml b/src/Gui/DocumentPy.xml index 75ac71a546..c76e101cf0 100644 --- a/src/Gui/DocumentPy.xml +++ b/src/Gui/DocumentPy.xml @@ -77,6 +77,11 @@ Send a message to all views of the document + + + + Merges this document with another project file + diff --git a/src/Gui/DocumentPyImp.cpp b/src/Gui/DocumentPyImp.cpp index 4d30e7cc5c..67b66f36a7 100644 --- a/src/Gui/DocumentPyImp.cpp +++ b/src/Gui/DocumentPyImp.cpp @@ -32,6 +32,7 @@ #include #include "Document.h" +#include "MergeDocuments.h" #include "ViewProviderExtern.h" // inclusion of the generated files (generated out of DocumentPy.xml) @@ -234,6 +235,22 @@ PyObject* DocumentPy::sendMsgToViews(PyObject *args) } PY_CATCH; } +PyObject* DocumentPy::mergeProject(PyObject *args) +{ + char* filename; + if (!PyArg_ParseTuple(args, "s", &filename)) // convert args: Python->C + return NULL; // NULL triggers exception + + PY_TRY { + Base::FileInfo fi(filename); + Base::ifstream str(fi, std::ios::in | std::ios::binary); + App::Document* doc = getDocumentPtr()->getDocument(); + MergeDocuments md(doc); + md.importObjects(str); + Py_Return; + } PY_CATCH; +} + Py::Object DocumentPy::getActiveObject(void) const { App::DocumentObject *object = getDocumentPtr()->getDocument()->getActiveObject(); From 6a264ac2a5b6bed5269477c8de3769bdc0893358 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 May 2012 16:57:36 +0200 Subject: [PATCH 257/351] Add method Document::findObject() --- src/App/Document.cpp | 15 +++++++++ src/App/Document.h | 1 + src/App/DocumentPyImp.cpp | 66 ++++++++++++++++++--------------------- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 519f5d7e4e..f130bb35a5 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -63,6 +63,7 @@ recompute path. Also enables more complicated dependencies beyond trees. #include #include #include +#include #include "Document.h" @@ -1689,6 +1690,20 @@ std::vector Document::getObjectsOfType(const Base::Type& typeId return Objects; } +std::vector Document::findObjects(const Base::Type& typeId, const char* objname) const +{ + boost::regex rx(objname); + boost::cmatch what; + std::vector Objects; + for (std::vector::const_iterator it = d->objectArray.begin(); it != d->objectArray.end(); ++it) { + if ((*it)->getTypeId().isDerivedFrom(typeId)) { + if (boost::regex_match((*it)->getNameInDocument(), what, rx)) + Objects.push_back(*it); + } + } + return Objects; +} + int Document::countObjectsOfType(const Base::Type& typeId) const { int ct=0; diff --git a/src/App/Document.h b/src/App/Document.h index dcf56d670d..d1675001e6 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -161,6 +161,7 @@ public: /// Returns a list of all Objects std::vector getObjects() const; std::vector getObjectsOfType(const Base::Type& typeId) const; + std::vector findObjects(const Base::Type& typeId, const char* objname) const; /// Returns an array with the correct types already. template inline std::vector getObjectsOfType() const; int countObjectsOfType(const Base::Type& typeId) const; diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 3b7fdd289d..6bd02f51ca 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -290,42 +290,36 @@ PyObject* DocumentPy::findObjects(PyObject *args) char *sType="App::DocumentObject", *sName=0; if (!PyArg_ParseTuple(args, "|ss",&sType, &sName)) // convert args: Python->C return NULL; // NULL triggers exception - - Base::Type type = Base::Type::fromName(sType); - if (type == Base::Type::badType()) { - PyErr_Format(PyExc_Exception, "'%s' is not a valid type", sType); - return NULL; - } - - if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) { - PyErr_Format(PyExc_Exception, "Type '%s' does not inherit from 'App::DocumentObject'", sType); - return NULL; - } - - std::vector res; - std::vector objs = getDocumentPtr()->getObjectsOfType(type); - - if (sName) { - try { - boost::regex rx(sName); - boost::cmatch what; - for (std::vector::const_iterator It = objs.begin();It != objs.end();++It) { - if (boost::regex_match((*It)->getNameInDocument(), what, rx)) - res.push_back(*It); - } - } - catch (const boost::regex_error& e) { - PyErr_SetString(PyExc_RuntimeError, e.what()); - return 0; - } - } - else { - res = objs; - } - - Py_ssize_t index=0; - PyObject* list = PyList_New((Py_ssize_t)res.size()); - for (std::vector::const_iterator It = res.begin();It != res.end();++It, index++) + + Base::Type type = Base::Type::fromName(sType); + if (type == Base::Type::badType()) { + PyErr_Format(PyExc_Exception, "'%s' is not a valid type", sType); + return NULL; + } + + if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) { + PyErr_Format(PyExc_Exception, "Type '%s' does not inherit from 'App::DocumentObject'", sType); + return NULL; + } + + std::vector res; + + if (sName) { + try { + res = getDocumentPtr()->findObjects(type, sName); + } + catch (const boost::regex_error& e) { + PyErr_SetString(PyExc_RuntimeError, e.what()); + return 0; + } + } + else { + res = getDocumentPtr()->getObjectsOfType(type); + } + + Py_ssize_t index=0; + PyObject* list = PyList_New((Py_ssize_t)res.size()); + for (std::vector::const_iterator It = res.begin();It != res.end();++It, index++) PyList_SetItem(list, index, (*It)->getPyObject()); return list; } From c7c874a705e4b69b045befeb1c222aeb32368280 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 23 May 2012 18:03:25 -0300 Subject: [PATCH 258/351] Small GUI adjustments in Draft --- src/Mod/Draft/DraftGui.py | 15 ++++++++++++++- src/Mod/Draft/DraftTools.py | 5 ++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 752abb76bc..13517f4785 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -523,13 +523,24 @@ class DraftToolBar: self.xValue.setEnabled(True) self.yValue.setEnabled(True) self.isRelative.show() + self.undoButton.show() + self.continueCmd.show() + + def wireUi(self,title=None): + if title: + self.pointUi(title) + else: + self.pointUi(translate("draft", "DWire")) + self.xValue.setEnabled(True) + self.yValue.setEnabled(True) + self.isRelative.show() self.hasFill.show() self.finishButton.show() self.closeButton.show() self.wipeButton.show() self.undoButton.show() self.continueCmd.show() - + def circleUi(self): self.pointUi(translate("draft", "Circle")) self.continueCmd.show() @@ -935,6 +946,8 @@ class DraftToolBar: if self.finishButton.isVisible(): self.finish() spec = True + elif txt.endsWith("t"): + self.continueCmd.setChecked(not self.continueCmd.isChecked()) elif txt.endsWith("w"): self.wipeLine() elif txt.endsWith("s"): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index d137c5228c..885e781c64 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -400,7 +400,10 @@ class Line(Creator): Creator.Activated(self,name) if self.doc: self.obj = None - self.ui.lineUi(name) + if self.isWire: + self.ui.wireUi(name) + else: + self.ui.lineUi(name) self.linetrack = lineTracker() self.constraintrack = lineTracker(dotted=True) self.obj=self.doc.addObject("Part::Feature",self.featureName) From 50bbf527dd79d15d8b1596ab1678bfe40eb1aece Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 25 May 2012 12:12:30 +0200 Subject: [PATCH 259/351] Add parameter to keep trailing digits in object name of copy, other little fix --- src/App/Document.cpp | 13 ++++++++----- src/App/Document.h | 4 ++-- src/App/DocumentPyImp.cpp | 6 +++--- src/Mod/Part/Gui/Command.cpp | 2 -- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index f130bb35a5..61d1b7921e 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1484,15 +1484,18 @@ void Document::breakDependency(DocumentObject* pcObject, bool clear) } DocumentObject* Document::_copyObject(DocumentObject* obj, std::map& copy_map, bool recursive) + DocumentObject*>& copy_map, bool recursive, + bool keepdigitsatend) { if (!obj) return 0; // remove number from end to avoid lengthy names std::string objname = obj->getNameInDocument(); + if (!keepdigitsatend) { size_t lastpos = objname.length()-1; while (objname[lastpos] >= 48 && objname[lastpos] <= 57) lastpos--; objname = objname.substr(0, lastpos+1); + } DocumentObject* copy = addObject(obj->getTypeId().getName(),objname.c_str()); if (!copy) return 0; copy->addDynamicProperties(obj); @@ -1512,7 +1515,7 @@ DocumentObject* Document::_copyObject(DocumentObject* obj, std::map(it->second)->setValue(pt->second); } else if (recursive) { - DocumentObject* link_copy = _copyObject(link, copy_map, recursive); + DocumentObject* link_copy = _copyObject(link, copy_map, recursive, keepdigitsatend); copy_map[link] = link_copy; static_cast(it->second)->setValue(link_copy); } @@ -1531,7 +1534,7 @@ DocumentObject* Document::_copyObject(DocumentObject* obj, std::mapsecond); } else { - links_copy.push_back(_copyObject(*jt, copy_map, recursive)); + links_copy.push_back(_copyObject(*jt, copy_map, recursive, keepdigitsatend)); copy_map[*jt] = links_copy.back(); } } @@ -1561,10 +1564,10 @@ DocumentObject* Document::_copyObject(DocumentObject* obj, std::map copy_map; - DocumentObject* copy = _copyObject(obj, copy_map, recursive); + DocumentObject* copy = _copyObject(obj, copy_map, recursive, keepdigitsatend); return copy; } diff --git a/src/App/Document.h b/src/App/Document.h index d1675001e6..38b247a20e 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -140,7 +140,7 @@ public: * are copied as well. By default \a recursive is false. * Returns the copy of the object or 0 if the creation failed. */ - DocumentObject* copyObject(DocumentObject* obj, bool recursive=false); + DocumentObject* copyObject(DocumentObject* obj, bool recursive=false, bool keepdigitsatend=false); /** Move an object from another document to this document * If \a recursive is true then all objects this object depends on * are moved as well. By default \a recursive is false. @@ -261,7 +261,7 @@ protected: void _remObject(DocumentObject* pcObject); void _addObject(DocumentObject* pcObject, const char* pObjectName); DocumentObject* _copyObject(DocumentObject* obj, std::map&, bool recursive=false); + DocumentObject*>&, bool recursive=false, bool keepdigitsatend=false); /// checks if a valid transaction is open void _checkTransaction(void); void breakDependency(DocumentObject* pcObject, bool clear); diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 6bd02f51ca..64b04d8b99 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -163,12 +163,12 @@ PyObject* DocumentPy::removeObject(PyObject *args) PyObject* DocumentPy::copyObject(PyObject *args) { - PyObject *obj, *rec=0; - if (!PyArg_ParseTuple(args, "O!|O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec)) + PyObject *obj, *rec=0, *keep=0; + if (!PyArg_ParseTuple(args, "O!|O!O!",&(DocumentObjectPy::Type),&obj,&PyBool_Type,&rec,&PyBool_Type,&keep)) return NULL; // NULL triggers exception DocumentObjectPy* docObj = static_cast(obj); - DocumentObject* copy = getDocumentPtr()->copyObject(docObj->getDocumentObjectPtr(), rec==Py_True); + DocumentObject* copy = getDocumentPtr()->copyObject(docObj->getDocumentObjectPtr(), rec==Py_True, keep==Py_True); if (copy) { return copy->getPyObject(); } diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 1b616525a7..33cd008ee7 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -511,7 +511,6 @@ void CmdPartExport::activated(int iMsg) if (!fn.isEmpty()) { App::Document* pDoc = getDocument(); if (!pDoc) return; // no document - openCommand("Import Part"); QString ext = QFileInfo(fn).suffix().toLower(); if (ext == QLatin1String("step") || ext == QLatin1String("stp") || @@ -522,7 +521,6 @@ void CmdPartExport::activated(int iMsg) else { Gui::Application::Instance->exportTo((const char*)fn.toUtf8(),pDoc->getName(),"Part"); } - commitCommand(); } } From b7965052a3535ecc25c70c84c805f8754675f258 Mon Sep 17 00:00:00 2001 From: logari81 Date: Fri, 25 May 2012 18:04:29 +0200 Subject: [PATCH 260/351] Sketcher: skip the latest added one of the detected redundant constraints --- src/Mod/Sketcher/App/freegcs/GCS.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/App/freegcs/GCS.cpp b/src/Mod/Sketcher/App/freegcs/GCS.cpp index aa850c9a2e..7b9455ddc7 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/freegcs/GCS.cpp @@ -1397,7 +1397,9 @@ int System::diagnose() Constraint *mostPopular = NULL; for (std::map< Constraint *, SET_I >::const_iterator it=conflictingMap.begin(); it != conflictingMap.end(); it++) { - if (it->second.size() >= maxPopularity) { + if (it->second.size() > maxPopularity || + (it->second.size() == maxPopularity && mostPopular && + it->first->getTag() > mostPopular->getTag())) { mostPopular = it->first; maxPopularity = it->second.size(); } From 7cbb16f2e840eac3e65a696d3a2a6e121c07df9e Mon Sep 17 00:00:00 2001 From: logari81 Date: Fri, 25 May 2012 18:18:51 +0200 Subject: [PATCH 261/351] Sketcher: include coincident constraints in the sketch diagnosis --- src/Mod/Sketcher/App/Sketch.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 59b6410a7a..1898955f3e 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -743,10 +743,7 @@ int Sketch::addPointCoincidentConstraint(int geoId1, PointPos pos1, int geoId2, GCS::Point &p1 = Points[pointId1]; GCS::Point &p2 = Points[pointId2]; int tag = ++ConstraintsCounter; - // trick: we do not tag coincidence constraints in order to exclude - // them from the diagnosing of conflicts - //GCSsys.addConstraintP2PCoincident(p1, p2, tag); - GCSsys.addConstraintP2PCoincident(p1, p2); + GCSsys.addConstraintP2PCoincident(p1, p2, tag); return ConstraintsCounter; } return -1; From 8078b7e0a7a810a44ff2d273b7e020e65452bf63 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 26 May 2012 00:29:29 +0200 Subject: [PATCH 262/351] Handle OCC exception in exportStl --- src/Mod/Part/App/TopoShapePyImp.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index 3aef9eab90..8f641a2f7e 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -347,7 +347,12 @@ PyObject* TopoShapePy::exportStl(PyObject *args) } catch (const Base::Exception& e) { PyErr_SetString(PyExc_Exception,e.what()); - return NULL; + return 0; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + PyErr_SetString(PyExc_Exception, e->GetMessageString()); + return 0; } Py_Return; From 1e60d45dd4740707ca2d3ed60d5e51fd7d161faf Mon Sep 17 00:00:00 2001 From: logari81 Date: Sat, 26 May 2012 19:23:38 +0200 Subject: [PATCH 263/351] Sketcher: fix minor issue in sketch diagnostics --- src/Mod/Sketcher/App/freegcs/GCS.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/App/freegcs/GCS.cpp b/src/Mod/Sketcher/App/freegcs/GCS.cpp index 7b9455ddc7..ffab4c579f 100644 --- a/src/Mod/Sketcher/App/freegcs/GCS.cpp +++ b/src/Mod/Sketcher/App/freegcs/GCS.cpp @@ -1425,7 +1425,8 @@ int System::diagnose() subSysTmp->applySolution(); for (std::set::const_iterator constr=skipped.begin(); constr != skipped.end(); constr++) { - if ((*constr)->error() < XconvergenceFine) + double err = (*constr)->error(); + if (err * err < XconvergenceFine) redundant.insert(*constr); } resetToReference(); From d92f627a8d206fbf76aaf948e97293346333b012 Mon Sep 17 00:00:00 2001 From: logari81 Date: Sat, 26 May 2012 20:02:57 +0200 Subject: [PATCH 264/351] Sketcher: simplify sketch solver messages --- src/Mod/Sketcher/App/SketchObject.cpp | 14 ++++-- src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp | 44 +++-------------- src/Mod/Sketcher/Gui/TaskSketcherMessages.h | 4 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 48 ++++++++++--------- src/Mod/Sketcher/Gui/ViewProviderSketch.h | 4 +- 5 files changed, 46 insertions(+), 68 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 8d75c5f24c..c09cd69639 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1393,10 +1393,14 @@ void SketchObject::appendConflictMsg(const std::vector &conflicting, std::s if (msg.length() > 0) ss << msg; if (conflicting.size() > 0) { - ss << "Please remove at least one of the constraints (" << conflicting[0]; + if (conflicting.size() == 1) + ss << "Please remove the following constraint:\n"; + else + ss << "Please remove at least one of the following constraints:\n"; + ss << conflicting[0]; for (unsigned int i=1; i < conflicting.size(); i++) ss << ", " << conflicting[i]; - ss << ")\n"; + ss << "\n"; } msg = ss.str(); } @@ -1407,7 +1411,11 @@ void SketchObject::appendRedundantMsg(const std::vector &redundant, std::st if (msg.length() > 0) ss << msg; if (redundant.size() > 0) { - ss << "The following constraints were identified as redundant and should be removed:\n" << redundant[0]; + if (redundant.size() == 1) + ss << "Please remove the following redundant constraint:\n"; + else + ss << "Please remove the following redundant constraints:\n"; + ss << redundant[0]; for (unsigned int i=1; i < redundant.size(); i++) ss << ", " << redundant[i]; ss << "\n"; diff --git a/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp b/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp index 5ef6c65fb5..dc006117a7 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp @@ -54,8 +54,8 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch *sketchView) this->groupLayout()->addWidget(proxy); - connectionSetUp = sketchView->signalSetUp.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSetUp, this,_1,_2,_3)); - connectionSolved = sketchView->signalSolved.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSolved, this,_1,_2)); + connectionSetUp = sketchView->signalSetUp.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSetUp, this,_1)); + connectionSolved = sketchView->signalSolved.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSolved, this,_1)); } TaskSketcherMessages::~TaskSketcherMessages() @@ -65,46 +65,14 @@ TaskSketcherMessages::~TaskSketcherMessages() delete ui; } -void TaskSketcherMessages::slotSetUp(int type, int dofs, const std::string &msg) +void TaskSketcherMessages::slotSetUp(QString msg) { - switch(type){ - case -1: - ui->labelConstrainStatus->setText(QString::fromLatin1("Empty sketch")); - break; - case 0: - ui->labelConstrainStatus->setText(QString::fromLatin1("Fully constrained sketch ")); - break; - case 1: - if (dofs==1) - ui->labelConstrainStatus->setText(QString::fromLatin1("Under-constrained sketch with 1 degree of freedom")); - else - ui->labelConstrainStatus->setText(QString::fromLatin1("Under-constrained sketch with %1 degrees of freedom").arg(dofs)); - break; - case 2: - ui->labelConstrainStatus->setText(QString::fromLatin1("Sketch contains conflicting constraints
%1
").arg(QString::fromStdString(msg))); - break; - case 3: - ui->labelConstrainStatus->setText(QString::fromLatin1("Over-constrained sketch
%1
").arg(QString::fromStdString(msg))); - break; - case 4: - ui->labelConstrainStatus->setText(QString::fromLatin1("Sketch contains redundant constraints
%1").arg(QString::fromStdString(msg))); - break; - } + ui->labelConstrainStatus->setText(msg); } -void TaskSketcherMessages::slotSolved(int type, float time) +void TaskSketcherMessages::slotSolved(QString msg) { - switch(type){ - case -1: - ui->labelSolverStatus->setText(QString()); - break; - case 0: - ui->labelSolverStatus->setText(QString::fromLatin1("Solved in %1 sec").arg(time)); - break; - case 1: - ui->labelSolverStatus->setText(QString::fromLatin1("Unsolved (%1)").arg(time)); - break; - } + ui->labelSolverStatus->setText(msg); } #include "moc_TaskSketcherMessages.cpp" diff --git a/src/Mod/Sketcher/Gui/TaskSketcherMessages.h b/src/Mod/Sketcher/Gui/TaskSketcherMessages.h index 7cdc104a7a..cdf5f907bd 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherMessages.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherMessages.h @@ -47,8 +47,8 @@ public: TaskSketcherMessages(ViewProviderSketch *sketchView); ~TaskSketcherMessages(); - void slotSetUp(int type, int dofs, const std::string &msg); - void slotSolved(int type, float time); + void slotSetUp(QString msg); + void slotSolved(QString msg); private Q_SLOTS: diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 2239f7445e..4b6cc1988e 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -822,9 +822,9 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal, if (edit->ActSketch.movePoint(GeoId, PosId, vec, relative) == 0) { setPositionText(Base::Vector2D(x,y)); draw(true); - signalSolved(0, edit->ActSketch.SolveTime); + signalSolved(QString::fromLatin1("Solved in %1 sec").arg(edit->ActSketch.SolveTime)); } else { - signalSolved(1, edit->ActSketch.SolveTime); + signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(edit->ActSketch.SolveTime)); //Base::Console().Log("Error solving:%d\n",ret); } } @@ -835,9 +835,9 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal, if (edit->ActSketch.movePoint(edit->DragCurve, Sketcher::none, vec, relative) == 0) { setPositionText(Base::Vector2D(x,y)); draw(true); - signalSolved(0, edit->ActSketch.SolveTime); + signalSolved(QString::fromLatin1("Solved in %1 sec").arg(edit->ActSketch.SolveTime)); } else { - signalSolved(1, edit->ActSketch.SolveTime); + signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(edit->ActSketch.SolveTime)); } } return true; @@ -2808,46 +2808,48 @@ void ViewProviderSketch::solveSketch(void) int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(), getSketchObject()->Constraints.getValues(), getSketchObject()->getExternalGeometryCount()); - std::string msg; if (getSketchObject()->Geometry.getSize() == 0) { - signalSetUp(-1, 0, msg); - signalSolved(-1, 0); + signalSetUp(QString::fromLatin1("Empty sketch")); + signalSolved(QString()); } else if (dofs < 0) { // over-constrained sketch + std::string msg; SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg); - //Base::Console().Warning("Over-constrained sketch\n%s",msg.c_str()); - signalSetUp(3, 0, msg); - signalSolved(-1, 0); + signalSetUp(QString::fromLatin1("Over-constrained sketch
%1
") + .arg(QString::fromStdString(msg))); + signalSolved(QString()); } else if (edit->ActSketch.hasConflicts()) { // conflicting constraints + std::string msg; SketchObject::appendConflictMsg(edit->ActSketch.getConflicting(), msg); - //Base::Console().Warning("Sketch with conflicting constraints\n%s",msg.c_str()); - signalSetUp(2, dofs, msg); - signalSolved(-1, 0); + signalSetUp(QString::fromLatin1("Sketch contains conflicting constraints
%1
") + .arg(QString::fromStdString(msg))); + signalSolved(QString()); } else { if (edit->ActSketch.hasRedundancies()) { // redundant constraints + std::string msg; SketchObject::appendRedundantMsg(edit->ActSketch.getRedundant(), msg); - //Base::Console().Warning("Sketch with redundant constraints\n%s",msg.c_str()); - signalSetUp(4, dofs, msg); + signalSetUp(QString::fromLatin1("Sketch contains redundant constraints
%1
") + .arg(QString::fromStdString(msg))); } if (edit->ActSketch.solve() == 0) { // solving the sketch if (dofs == 0) { // color the sketch as fully constrained edit->FullyConstrained = true; - if (!edit->ActSketch.hasRedundancies()) { - //Base::Console().Message("Fully constrained sketch\n"); - signalSetUp(0, 0, msg); - } + if (!edit->ActSketch.hasRedundancies()) + signalSetUp(QString::fromLatin1("Fully constrained sketch ")); } else if (!edit->ActSketch.hasRedundancies()) { - //Base::Console().Message("Under-constrained sketch with %d degrees of freedom\n", dofs); - signalSetUp(1, dofs, msg); + if (dofs == 1) + signalSetUp(QString::fromLatin1("Under-constrained sketch with 1 degree of freedom")); + else + signalSetUp(QString::fromLatin1("Under-constrained sketch with %1 degrees of freedom").arg(dofs)); } - signalSolved(0, edit->ActSketch.SolveTime); + signalSolved(QString::fromLatin1("Solved in %1 sec").arg(edit->ActSketch.SolveTime)); } else { - signalSolved(1, edit->ActSketch.SolveTime); + signalSolved(QString::fromLatin1("Unsolved (%1 sec)").arg(edit->ActSketch.SolveTime)); } } } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index 234ede976c..2c98d71eb8 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -174,9 +174,9 @@ public: /// signals if the constraints list has changed boost::signal signalConstraintsChanged; /// signals if the sketch has been set up - boost::signal signalSetUp; + boost::signal signalSetUp; /// signals if the sketch has been solved - boost::signal signalSolved; + boost::signal signalSolved; protected: virtual bool setEdit(int ModNum); From 455f5a67c30d5381dc6446c86e78d42d3c827f5e Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 26 May 2012 00:29:29 +0200 Subject: [PATCH 265/351] Handle OCC exception in exportStl --- src/Mod/Part/App/TopoShapePyImp.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShapePyImp.cpp b/src/Mod/Part/App/TopoShapePyImp.cpp index 3aef9eab90..8f641a2f7e 100644 --- a/src/Mod/Part/App/TopoShapePyImp.cpp +++ b/src/Mod/Part/App/TopoShapePyImp.cpp @@ -347,7 +347,12 @@ PyObject* TopoShapePy::exportStl(PyObject *args) } catch (const Base::Exception& e) { PyErr_SetString(PyExc_Exception,e.what()); - return NULL; + return 0; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + PyErr_SetString(PyExc_Exception, e->GetMessageString()); + return 0; } Py_Return; From bfd64a98e87d46224804748be8a0080cb86a67ee Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 27 May 2012 13:01:13 +0200 Subject: [PATCH 266/351] Add new Qt options --- src/App/Application.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index a622eecf2a..30033380a1 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -1450,6 +1450,9 @@ void Application::ParseOptions(int ac, char ** av) ("hidden", "don't show the main window") // this are to ignore for the window system (QApplication) ("style", boost::program_options::value< string >(), "set the application GUI style") + ("stylesheet", boost::program_options::value< string >(), "set the application stylesheet") + ("session", boost::program_options::value< string >(), "restore the application from an earlier session") + ("reverse", "set the application's layout direction from right to left") ("display", boost::program_options::value< string >(), "set the X-Server") ("geometry ", boost::program_options::value< string >(), "set the X-Window geometry") ("font", boost::program_options::value< string >(), "set the X-Window font") From ffb5cba1e3b20aa76fc8df8f9626faa80c889894 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 27 May 2012 23:04:04 +0200 Subject: [PATCH 267/351] 0000723: improper handling of qt specific comand line arguments --- src/App/Application.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 30033380a1..17b99601fb 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -1475,6 +1475,28 @@ void Application::ParseOptions(int ac, char ** av) //x11.add_options() // ("display", boost::program_options::value< string >(), "set the X-Server") // ; + //0000723: improper handling of qt specific comand line arguments + std::vector args; + bool merge=false; + for (int i=1; i args; copy(tok.begin(), tok.end(), back_inserter(args)); // Parse the file and store the options - store( boost::program_options::command_line_parser(ac, av). + store( boost::program_options::command_line_parser(args). options(cmdline_options).positional(p).extra_parser(customSyntax).run(), vm); } From cb9ddda7c8ad5f78468f8c58a6d37efd32f58a5b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 28 May 2012 16:02:26 -0300 Subject: [PATCH 268/351] Added FreeCADGui.doCommand() python command --- src/Gui/Application.h | 2 ++ src/Gui/ApplicationPy.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/Gui/Application.h b/src/Gui/Application.h index 74b3dbb64b..44a73d0c67 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -231,6 +231,8 @@ public: PYFUNCDEF_S(sActiveDocument); PYFUNCDEF_S(sGetDocument); + PYFUNCDEF_S(sDoCommand); + static PyMethodDef Methods[]; private: diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index 9ca9ee3afe..9a2a51af4e 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -128,6 +128,9 @@ PyMethodDef Application::Methods[] = { {"getDocument", (PyCFunction) Application::sGetDocument, 1, "getDocument(string) -> object\n\n" "Get a document by its name"}, + {"doCommand", (PyCFunction) Application::sDoCommand, 1, + "doCommand(string) -> None\n\n" + "Prints the given string in the python console and runs it"}, {NULL, NULL} /* Sentinel */ }; @@ -765,3 +768,12 @@ PyObject* Application::sRunCommand(PyObject * /*self*/, PyObject *args,PyObject return 0; } } + +PyObject* Application::sDoCommand(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) +{ + char *pstr=0; + if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C + return NULL; // NULL triggers exception + Command::doCommand(Command::Doc,pstr); + return Py_None; +} From 486efd665c3b71f9d5200365c62a6795dbbf8a6f Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 28 May 2012 16:02:56 -0300 Subject: [PATCH 269/351] Testing python Gui.doCommand with the Draft Line tool --- src/Mod/Draft/DraftGui.py | 6 +++++- src/Mod/Draft/DraftTools.py | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 13517f4785..7e651a6986 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -78,7 +78,11 @@ class todo: try: name = str(name) FreeCAD.ActiveDocument.openTransaction(name) - func() + if isinstance(func,list): + for l in func: + FreeCADGui.doCommand(l) + else: + func() FreeCAD.ActiveDocument.commitTransaction() except: wrn = "[Draft.todo.commit] Unexpected error:", sys.exc_info()[0], "in ", f, "(", arg, ")" diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 885e781c64..81d1bc05d1 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -415,13 +415,26 @@ class Line(Creator): def finish(self,closed=False,cont=False): "terminates the operation and closes the poly if asked" if self.obj: + # remove temporary object, if any old = self.obj.Name todo.delay(self.doc.removeObject,old) self.obj = None if (len(self.node) > 1): + # building command string + if self.support: + sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' + else: + sup = 'None' + points='[' + for n in self.node: + if len(points) > 1: + points += ',' + points += 'FreeCAD.Vector('+str(n.x) + ',' + str(n.y) + ',' + str(n.z) + ')' + points += ']' self.commit(translate("draft","Create DWire"), - partial(Draft.makeWire,self.node,closed, - face=self.ui.fillmode,support=self.support)) + ['import Draft', + 'points='+points, + 'Draft.makeWire(points,closed='+str(closed)+',face='+str(bool(self.ui.fillmode))+',support='+sup+')']) if self.ui: self.linetrack.finalize() self.constraintrack.finalize() From dcffcbe1687da2b0636d445e80e52b3e971a73e9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 28 May 2012 23:39:36 +0200 Subject: [PATCH 270/351] 0000726: Fails to compile GIT --- src/Mod/Mesh/App/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Mesh/App/Makefile.am b/src/Mod/Mesh/App/Makefile.am index 27537e0605..5ba606444c 100644 --- a/src/Mod/Mesh/App/Makefile.am +++ b/src/Mod/Mesh/App/Makefile.am @@ -359,7 +359,7 @@ Mesh_la_DEPENDENCIES = libMesh.la # set the include path found by configure AM_CXXFLAGS = -I$(top_srcdir)/src/3rdParty -I$(top_srcdir)/src -I$(top_builddir)/src $(GTS_CFLAGS) \ - $(all_includes) $(QT4_CORE_CXXFLAGS) + $(all_includes) -I$(EIGEN3_INC) $(QT4_CORE_CXXFLAGS) includedir = @includedir@/Mod/Mesh/App libdir = $(prefix)/Mod/Mesh From 141cd5029a74d5a2136a9e238a9ec22017a69c0e Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 29 May 2012 11:40:51 +0200 Subject: [PATCH 271/351] 0000714: Merge project does not include DiffuseColor --- src/Gui/Document.cpp | 2 +- src/Gui/MergeDocuments.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index 4a0880ffa8..0192d3e86e 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -748,7 +748,7 @@ void Document::exportObjects(const std::vector& obj, Base: << views.size() <<"\">" << std::endl; bool xml = writer.isForceXML(); - writer.setForceXML(true); + //writer.setForceXML(true); writer.incInd(); // indention for 'ViewProvider name' std::map::const_iterator jt; for (jt = views.begin(); jt != views.end(); ++jt) { diff --git a/src/Gui/MergeDocuments.cpp b/src/Gui/MergeDocuments.cpp index a1fc7172a7..7addd29bed 100644 --- a/src/Gui/MergeDocuments.cpp +++ b/src/Gui/MergeDocuments.cpp @@ -235,4 +235,8 @@ void MergeDocuments::RestoreDocFile(Base::Reader & reader) } xmlReader.readEndElement("Document"); + + // In the file GuiDocument.xml new data files might be added + if (!xmlReader.getFilenames().empty()) + xmlReader.readFiles(static_cast(reader)); } From 96f6c42b40ac08bb2c09cbca7bcae8b21c1d2aa7 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 29 May 2012 22:17:12 -0300 Subject: [PATCH 272/351] Used Gui.doCommand() in all Draft commands --- src/Mod/Draft/DraftTools.py | 186 +++++++++++++++++++++++---------- src/Mod/Draft/DraftVecUtils.py | 4 + 2 files changed, 136 insertions(+), 54 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 81d1bc05d1..93fb74fcc5 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -380,8 +380,38 @@ class Creator: todo.delayCommit(self.commitList) self.commitList = [] + def getStrings(self): + "returns a couple of useful strings fro building python commands" + + # current plane rotation + p = plane.getRotation() + qr = p.Rotation.Q + qr = '('+str(qr[0])+','+str(qr[1])+','+str(qr[2])+','+str(qr[3])+')' + + # support object + if self.support: + sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' + else: + sup = 'None' + + # contents of self.node + points='[' + for n in self.node: + if len(points) > 1: + points += ',' + points += DraftVecUtils.toString(n) + points += ']' + + # fill mode + if self.ui: + fil = str(bool(self.ui.fillmode)) + else: + fil = "True" + + return qr,sup,points,fil + def commit(self,name,func): - "stores partial actions to be committed to the FreeCAD document" + "stores actions to be committed to the FreeCAD document" self.commitList.append((name,func)) class Line(Creator): @@ -421,20 +451,11 @@ class Line(Creator): self.obj = None if (len(self.node) > 1): # building command string - if self.support: - sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' - else: - sup = 'None' - points='[' - for n in self.node: - if len(points) > 1: - points += ',' - points += 'FreeCAD.Vector('+str(n.x) + ',' + str(n.y) + ',' + str(n.z) + ')' - points += ']' + rot,sup,pts,fil = self.getStrings() self.commit(translate("draft","Create DWire"), ['import Draft', - 'points='+points, - 'Draft.makeWire(points,closed='+str(closed)+',face='+str(bool(self.ui.fillmode))+',support='+sup+')']) + 'points='+pts, + 'Draft.makeWire(points,closed='+str(closed)+',face='+fil+',support='+sup+')']) if self.ui: self.linetrack.finalize() self.constraintrack.finalize() @@ -628,9 +649,12 @@ class BSpline(Line): old = self.obj.Name self.doc.removeObject(old) try: + # building command string + rot,sup,pts,fil = self.getStrings() self.commit(translate("draft","Create BSpline"), - partial(Draft.makeBSpline,self.node,closed, - face=self.ui.fillmode,support=self.support)) + ['import Draft', + 'points='+pts, + 'Draft.makeBSpline(points,closed='+str(closed)+',face='+fil+',support='+sup+')']) except: print "Draft: error delaying commit" if self.ui: @@ -741,12 +765,15 @@ class Rectangle(Creator): if abs(DraftVecUtils.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length height = p2.sub(p1).Length if abs(DraftVecUtils.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height - p = plane.getRotation() - p.move(p1) try: + # building command string + rot,sup,pts,fil = self.getStrings() self.commit(translate("draft","Create Rectangle"), - partial(Draft.makeRectangle,length,height, - p,self.ui.fillmode,support=self.support)) + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(p1), + 'Draft.makeRectangle(length='+str(length)+',height='+str(height)+',placement=pl,face='+fil+',support='+sup+')']) except: print "Draft: error delaying commit" self.finish(cont=True) @@ -1013,23 +1040,30 @@ class Arc(Creator): def drawArc(self): "actually draws the FreeCAD object" - p = plane.getRotation() - p.move(self.center) + rot,sup,pts,fil = self.getStrings() if self.closedCircle: try: - self.commit(translate("draft","Create Circle"), - partial(Draft.makeCircle,self.rad,p, - self.ui.fillmode,support=self.support)) + # building command string + self.commit(translate("draft","Create Circle"), + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(self.center), + 'Draft.makeCircle(radius='+str(self.rad)+',placement=pl,face='+fil+',support='+sup+')']) except: - print "Draft: error delaying commit" + print "Draft: error delaying commit" else: sta = math.degrees(self.firstangle) end = math.degrees(self.firstangle+self.angle) if end < sta: sta,end = end,sta try: - self.commit(translate("draft","Create Arc"), - partial(Draft.makeCircle,self.rad,p,self.ui.fillmode, - sta,end,support=self.support)) + # building command string + self.commit(translate("draft","Create Arc"), + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(self.center), + 'Draft.makeCircle(radius='+str(self.rad)+',placement=pl,face='+fil+',startangle='+str(sta)+',endangle='+str(end)+',support='+sup+')']) except: print "Draft: error delaying commit" self.finish(cont=True) @@ -1257,11 +1291,14 @@ class Polygon(Creator): def drawPolygon(self): "actually draws the FreeCAD object" - p = plane.getRotation() - p.move(self.center) + rot,sup,pts,fil = self.getStrings() + # building command string self.commit(translate("draft","Create Polygon"), - partial(Draft.makePolygon,self.ui.numFaces.value(),self.rad, - True,p,face=self.ui.fillmode,support=self.support)) + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(self.center), + 'Draft.makePolygon('+str(self.ui.numFaces.value())+',radius='+str(self.rad)+',inscribed=True,placement=pl,face='+fil+',support='+sup+')']) self.finish(cont=True) def numericInput(self,numx,numy,numz): @@ -1326,8 +1363,16 @@ class Text(Creator): def createObject(self): "creates an object in the current doc" - self.commit(translate("draft","Create Text"), - partial(Draft.makeText,self.text,self.node[0])) + tx = '' + for l in self.text: + if tx: + tx += ',' + tx += '"'+l+'"' +# self.commit(translate("draft","Create Text"), +# ['import Draft', +# 'Draft.makeText(['+tx+'],'+DraftVecUtils.toString(self.node[0])+')']) + self.commit(translate("draft","Create Text"),partial(Draft.makeText,self.text,self.node[0])) + self.finish(cont=True) def action(self,arg): @@ -1429,9 +1474,9 @@ class Dimension(Creator): pt = o.ViewObject.RootNode.getChildren()[1].getChildren()[0].getChildren()[0].getChildren()[3] p3 = Vector(pt.point.getValues()[2].getValue()) self.commit(translate("draft","Create Dimension"), - partial(Draft.makeDimension,p1,p2,p3)) - self.commit(translate("draft","Delete Measurement"), - partial(FreeCAD.ActiveDocument.removeObject,o.Name)) + ['import Draft', + 'Draft.makeDimension('+DraftVecUtils.toString(p1)+','+DraftVecUtils.toString(p2)+','+DraftVecUtils.toString(p3)+')', + 'FreeCAD.ActiveDocument.removeObject("'+o.Name+'")']) def createObject(self): "creates an object in the current doc" @@ -1449,8 +1494,8 @@ class Dimension(Creator): self.arcmode,self.node[2])) else: self.commit(translate("draft","Create Dimension"), - partial(Draft.makeDimension,self.node[0],self.node[1], - self.node[2])) + ['import Draft', + 'Draft.makeDimension('+DraftVecUtils.toString(self.node[0])+','+DraftVecUtils.toString(self.node[1])+','+DraftVecUtils.toString(self.node[2])+')']) if self.ui.continueMode: self.cont = self.node[2] if not self.dir: @@ -1712,7 +1757,7 @@ class Modifier: self.commitList = [] def commit(self,name,func): - "stores partial actions to be committed to the FreeCAD document" + "stores actions to be committed to the FreeCAD document" # print "committing" self.commitList.append((name,func)) @@ -1768,10 +1813,20 @@ class Move(Modifier): def move(self,delta,copy=False): "moving the real shapes" + sel = '[' + for o in self.sel: + if len(sel) > 1: + sel += ',' + sel += 'FreeCAD.ActiveDocument.'+o.Name + sel += ']' if copy: - self.commit(translate("draft","Copy"),partial(Draft.move,self.sel,delta,copy)) + self.commit(translate("draft","Copy"), + ['import Draft', + 'Draft.move('+sel+','+DraftVecUtils.toString(delta)+',copy='+str(copy)+')']) else: - self.commit(translate("draft","Move"),partial(Draft.move,self.sel,delta,copy)) + self.commit(translate("draft","Move"), + ['import Draft', + 'Draft.move('+sel+','+DraftVecUtils.toString(delta)+',copy='+str(copy)+')']) self.doc.recompute() def action(self,arg): @@ -1926,14 +1981,20 @@ class Rotate(Modifier): def rot (self,angle,copy=False): "rotating the real shapes" + sel = '[' + for o in self.sel: + if len(sel) > 1: + sel += ',' + sel += 'FreeCAD.ActiveDocument.'+o.Name + sel += ']' if copy: self.commit(translate("draft","Copy"), - partial(Draft.rotate,self.sel, - math.degrees(angle),self.center,plane.axis,copy)) + ['import Draft', + 'Draft.rotate('+sel+','+str(math.degrees(angle))+','+DraftVecUtils.toString(self.center)+',axis='+DraftVecUtils.toString(plane.axis)+',copy='+str(copy)+')']) else: self.commit(translate("draft","Rotate"), - partial(Draft.rotate,self.sel, - math.degrees(angle),self.center,plane.axis,copy)) + ['import Draft', + 'Draft.rotate('+sel+','+str(math.degrees(angle))+','+DraftVecUtils.toString(self.center)+',axis='+DraftVecUtils.toString(plane.axis)+',copy='+str(copy)+')']) def action(self,arg): "scene event handler" @@ -2194,13 +2255,18 @@ class Offset(Modifier): occmode = self.ui.occOffset.isChecked() if hasMod(arg,MODALT) or self.ui.isCopy.isChecked(): copymode = True if self.npts: + print "offset:npts=",self.npts self.commit(translate("draft","Offset"), - partial(Draft.offset,self.sel, - self.npts,copymode,occ=False)) + ['import Draft', + 'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+DraftVecUtils.toString(self.ntps)+',copy='+str(copymode)+')']) elif self.dvec: + if isinstance(self.dvec,float): + d = str(self.dvec) + else: + d = DraftVecUtils.toString(self.dvec) self.commit(translate("draft","Offset"), - partial(Draft.offset,self.sel, - self.dvec,copymode,occ=occmode)) + ['import Draft', + 'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+d+',copy='+str(copymode)+',occ='+str(occmode)+')']) if hasMod(arg,MODALT): self.extendedCopy = True else: @@ -2222,9 +2288,13 @@ class Offset(Modifier): copymode = False occmode = self.ui.occOffset.isChecked() if self.ui.isCopy.isChecked(): copymode = True + if isinstance(self.dvec,float): + d = str(self.dvec) + else: + d = DraftVecUtils.toString(self.dvec) self.commit(translate("draft","Offset"), - partial(Draft.offset,self.sel, - self.dvec,copymode,occ=occmode)) + ['import Draft', + 'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+d+',copy='+str(copymode)+',occ='+str(occmode)+')']) self.finish() @@ -2946,12 +3016,20 @@ class Scale(Modifier): def scale(self,delta,copy=False): "moving the real shapes" + sel = '[' + for o in self.sel: + if len(sel) > 1: + sel += ',' + sel += 'FreeCAD.ActiveDocument.'+o.Name + sel += ']' if copy: self.commit(translate("draft","Copy"), - partial(Draft.scale,self.sel,delta,self.node[0],copy)) + ['import Draft', + 'Draft.scale('+sel+',delta='+DraftVecUtils.toString(delta)+',center='+DraftVecUtils.toString(self.node[0])+',copy='+str(copy)+')']) else: self.commit(translate("draft","Scale"), - partial(Draft.scale,self.sel,delta,self.node[0],copy)) + ['import Draft', + 'Draft.scale('+sel+',delta='+DraftVecUtils.toString(delta)+',center='+DraftVecUtils.toString(self.node[0])+',copy='+str(copy)+')']) def action(self,arg): "scene event handler" diff --git a/src/Mod/Draft/DraftVecUtils.py b/src/Mod/Draft/DraftVecUtils.py index 1f10a2c7ea..678965e85a 100644 --- a/src/Mod/Draft/DraftVecUtils.py +++ b/src/Mod/Draft/DraftVecUtils.py @@ -40,6 +40,10 @@ def typecheck (args_and_types, name="?"): FreeCAD.Console.PrintWarning("typecheck[" + str(name) + "]: " + str(v) + " is not " + str(t) + "\n") raise TypeError("fcvec." + str(name)) +def toString(u): + "returns a string containing a python command to recreate this vector" + return "FreeCAD.Vector("+str(u.x)+","+str(u.y)+","+str(u.z)+")" + def tup(u,array=False): "returns a tuple (x,y,z) with the vector coords, or an array if array=true" typecheck ([(u,Vector)], "tup"); From 54d4e2cab9b0b6080e2e79d06a3a7f7ff9d54211 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 29 May 2012 22:25:01 -0300 Subject: [PATCH 273/351] Draft: Small fix in Offset tool --- src/Mod/Draft/DraftGeomUtils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py index 16468ad0c1..7ce4a57f00 100755 --- a/src/Mod/Draft/DraftGeomUtils.py +++ b/src/Mod/Draft/DraftGeomUtils.py @@ -765,7 +765,7 @@ def isReallyClosed(wire): def getNormal(shape): "finds the normal of a shape, if possible" n = Vector(0,0,1) - if shape.ShapeType == "Face": + 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): From 93e0c6688d1473ab771dc2040d03f73464d2582a Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 30 May 2012 15:55:06 +0200 Subject: [PATCH 274/351] Handle expections in PointsPy class --- src/Mod/Points/App/PointsPyImp.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Mod/Points/App/PointsPyImp.cpp b/src/Mod/Points/App/PointsPyImp.cpp index 75df742c8e..b0b2819ac8 100644 --- a/src/Mod/Points/App/PointsPyImp.cpp +++ b/src/Mod/Points/App/PointsPyImp.cpp @@ -59,14 +59,20 @@ int PointsPy::PyInit(PyObject* args, PyObject* /*kwd*/) *getPointKernelPtr() = *(static_cast(pcObj)->getPointKernelPtr()); } else if (PyList_Check(pcObj)) { - addPoints(args); + if (!addPoints(args)) + return -1; } else if (PyTuple_Check(pcObj)) { - addPoints(args); + if (!addPoints(args)) + return -1; } else if (PyString_Check(pcObj)) { getPointKernelPtr()->load(PyString_AsString(pcObj)); } + else { + PyErr_SetString(PyExc_TypeError, "optional argument must be list, tuple or string"); + return -1; + } return 0; } From 1cc99939547cf6f45e745ae10d58e9ebf3ad3f4e Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 30 May 2012 17:32:55 +0200 Subject: [PATCH 275/351] Add method to find segment of a facet index --- src/Mod/Mesh/App/Core/Segmentation.cpp | 10 ++++++++++ src/Mod/Mesh/App/Core/Segmentation.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/Mod/Mesh/App/Core/Segmentation.cpp b/src/Mod/Mesh/App/Core/Segmentation.cpp index 01d99fb11f..9d0d69f325 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.cpp +++ b/src/Mod/Mesh/App/Core/Segmentation.cpp @@ -46,6 +46,16 @@ void MeshSurfaceSegment::AddSegment(const std::vector& segm) } } +MeshSegment MeshSurfaceSegment::FindSegment(unsigned long index) const +{ + for (std::vector::const_iterator it = segments.begin(); it != segments.end(); ++it) { + if (std::find(it->begin(), it->end(), index) != it->end()) + return *it; + } + + return MeshSegment(); +} + // -------------------------------------------------------- MeshDistancePlanarSegment::MeshDistancePlanarSegment(const MeshKernel& mesh, unsigned long minFacets, float tol) diff --git a/src/Mod/Mesh/App/Core/Segmentation.h b/src/Mod/Mesh/App/Core/Segmentation.h index 1b29f4bff9..9416028b69 100644 --- a/src/Mod/Mesh/App/Core/Segmentation.h +++ b/src/Mod/Mesh/App/Core/Segmentation.h @@ -46,6 +46,7 @@ public: virtual void AddFacet(const MeshFacet& rclFacet); void AddSegment(const std::vector&); const std::vector& GetSegments() const { return segments; } + MeshSegment FindSegment(unsigned long) const; protected: std::vector segments; From fc4d253e3d7537d1711fe6b9237bb7bf9dc724d3 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 30 May 2012 12:58:08 -0300 Subject: [PATCH 276/351] Draft: fixes in commands --- src/Mod/Draft/DraftTools.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 93fb74fcc5..9135588a76 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -1363,15 +1363,15 @@ class Text(Creator): def createObject(self): "creates an object in the current doc" - tx = '' + tx = '[' for l in self.text: - if tx: + if len(tx) > 1: tx += ',' - tx += '"'+l+'"' -# self.commit(translate("draft","Create Text"), -# ['import Draft', -# 'Draft.makeText(['+tx+'],'+DraftVecUtils.toString(self.node[0])+')']) - self.commit(translate("draft","Create Text"),partial(Draft.makeText,self.text,self.node[0])) + tx += '"'+str(l)+'"' + tx += ']' + self.commit(translate("draft","Create Text"), + ['import Draft', + 'Draft.makeText('+tx+',point='+DraftVecUtils.toString(self.node[0])+')']) self.finish(cont=True) @@ -1911,19 +1911,21 @@ class ApplyStyle(Modifier): if self.ui: self.sel = Draft.getSelection() if (len(self.sel)>0): + c = ['import Draft'] for ob in self.sel: if (ob.Type == "App::DocumentObjectGroup"): - self.formatGroup(ob) + c.extend(self.formatGroup(ob)) else: - self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) + c.append('Draft.formatObject(FreeCAD.ActiveDocument.'+ob.Name+')') + self.commit(translate("draft","Change Style"),c) def formatGroup(self,grpob): + c=[] for ob in grpob.Group: if (ob.Type == "App::DocumentObjectGroup"): - self.formatGroup(ob) + c.extend(self.formatGroup(ob)) else: - self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) - + c.append('Draft.formatObject(FreeCAD.ActiveDocument.'+ob.Name+')') class Rotate(Modifier): "The Draft_Rotate FreeCAD command definition" From f0b234f9e0bdcf05774813e77dfb11d2b18ab58d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Tue, 1 May 2012 14:39:19 +0200 Subject: [PATCH 277/351] Removed faces as class stored variable (PropertyPythonObject::fromString warning). --- src/Mod/Ship/Instance.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Mod/Ship/Instance.py b/src/Mod/Ship/Instance.py index 64eecd5cc7..104d2f24eb 100644 --- a/src/Mod/Ship/Instance.py +++ b/src/Mod/Ship/Instance.py @@ -39,7 +39,6 @@ class Ship: """ Creates a new ship on active document. @param faces Ship faces (Part::Shape entities). """ - self.faces = faces # Add uniqueness property to identify Ship instances obj.addProperty("App::PropertyBool","IsShip","Ship", str(Translator.translate("True if is a valid ship instance"))).IsShip=True # Add main dimensions @@ -47,7 +46,7 @@ class Ship: obj.addProperty("App::PropertyLength","Beam","Ship", str(Translator.translate("Ship beam (B) [m]"))).Beam=0.0 obj.addProperty("App::PropertyLength","Draft","Ship", str(Translator.translate("Ship draft (T) [m]"))).Draft=0.0 # Add shapes - obj.addProperty("Part::PropertyPartShape","Shape","Ship", str(Translator.translate("Ship surfaces"))).Shape = Part.makeShell(self.faces) + obj.addProperty("Part::PropertyPartShape","Shape","Ship", str(Translator.translate("Ship surfaces"))).Shape = Part.makeShell(faces) obj.Proxy = self self.obj = obj @@ -55,12 +54,12 @@ class Ship: ''' Print the name of the property that has changed ''' # FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n") if prop == "Length" or prop == "Beam" or prop == "Draft": - fp.Shape = Part.makeShell(self.faces) + fp.Shape = Part.makeShell(obj.Shape.Faces) def execute(self, obj): ''' Print a short message when doing a recomputation, this method is mandatory ''' # FreeCAD.Console.PrintMessage("Recompute Ship\n") - obj.Shape = Part.makeShell(self.faces) + obj.Shape = Part.makeShell(obj.Shape.Faces) def lineFaceSection(self,line,surface): """ Returns the point of section of a line with a face @@ -147,7 +146,7 @@ class Ship: wire = wires[j].Edges for k in range(0,len(wire)): edges.append(wire[k]) - # Slice curves to get points (Length based) + # Slice curves to get points points = [] for k in range(0,nP): planePoints = [] From c5739c8829f3b7c25d1342f6590eee5dbf46f725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Tue, 1 May 2012 17:08:07 +0200 Subject: [PATCH 278/351] Removed shape duplicities. --- src/Mod/Ship/Instance.py | 4 ++-- src/Mod/Ship/shipCreateShip/TaskPanel.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Mod/Ship/Instance.py b/src/Mod/Ship/Instance.py index 104d2f24eb..16d77f8689 100644 --- a/src/Mod/Ship/Instance.py +++ b/src/Mod/Ship/Instance.py @@ -46,7 +46,7 @@ class Ship: obj.addProperty("App::PropertyLength","Beam","Ship", str(Translator.translate("Ship beam (B) [m]"))).Beam=0.0 obj.addProperty("App::PropertyLength","Draft","Ship", str(Translator.translate("Ship draft (T) [m]"))).Draft=0.0 # Add shapes - obj.addProperty("Part::PropertyPartShape","Shape","Ship", str(Translator.translate("Ship surfaces"))).Shape = Part.makeShell(faces) + obj.Shape = Part.makeShell(faces) obj.Proxy = self self.obj = obj @@ -54,7 +54,7 @@ class Ship: ''' Print the name of the property that has changed ''' # FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n") if prop == "Length" or prop == "Beam" or prop == "Draft": - fp.Shape = Part.makeShell(obj.Shape.Faces) + pass def execute(self, obj): ''' Print a short message when doing a recomputation, this method is mandatory ''' diff --git a/src/Mod/Ship/shipCreateShip/TaskPanel.py b/src/Mod/Ship/shipCreateShip/TaskPanel.py index bec74302ad..cbb5319c84 100644 --- a/src/Mod/Ship/shipCreateShip/TaskPanel.py +++ b/src/Mod/Ship/shipCreateShip/TaskPanel.py @@ -49,6 +49,7 @@ class TaskPanel: obj.Draft = self.form.draft.value() # Discretize it ship.discretize(self.form.nSections.value(), self.form.nPoints.value()) + App.ActiveDocument.recompute() return True def reject(self): From f46c60679a3f11afbdc58126e64856f72036ffe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Tue, 1 May 2012 17:13:44 +0200 Subject: [PATCH 279/351] Added tank creator. --- src/Mod/Ship/CMakeLists.txt | 20 +- src/Mod/Ship/Icons/Tank.png | Bin 0 -> 10163 bytes src/Mod/Ship/Icons/Tank.xcf | Bin 0 -> 74661 bytes src/Mod/Ship/Icons/Tank.xpm | 1736 +++++++++++++++++++ src/Mod/Ship/InitGui.py | 4 + src/Mod/Ship/Makefile.am | 11 +- src/Mod/Ship/ShipGui.py | 13 + src/Mod/Ship/TankInstance.py | 1886 +++++++++++++++++++++ src/Mod/Ship/shipLoadExample/TaskPanel.ui | 4 +- src/Mod/Ship/tankCreateTank/TaskPanel.py | 167 ++ src/Mod/Ship/tankCreateTank/TaskPanel.ui | 141 ++ src/Mod/Ship/tankCreateTank/__init__.py | 36 + 12 files changed, 4013 insertions(+), 5 deletions(-) create mode 100644 src/Mod/Ship/Icons/Tank.png create mode 100644 src/Mod/Ship/Icons/Tank.xcf create mode 100644 src/Mod/Ship/Icons/Tank.xpm create mode 100644 src/Mod/Ship/TankInstance.py create mode 100644 src/Mod/Ship/tankCreateTank/TaskPanel.py create mode 100644 src/Mod/Ship/tankCreateTank/TaskPanel.ui create mode 100644 src/Mod/Ship/tankCreateTank/__init__.py diff --git a/src/Mod/Ship/CMakeLists.txt b/src/Mod/Ship/CMakeLists.txt index 058b9aec1b..a362a0c6a6 100644 --- a/src/Mod/Ship/CMakeLists.txt +++ b/src/Mod/Ship/CMakeLists.txt @@ -2,6 +2,7 @@ SET(ShipMain_SRCS InitGui.py ShipGui.py Instance.py + TankInstance.py ) SOURCE_GROUP("" FILES ${ShipMain_SRCS}) @@ -32,6 +33,9 @@ SET(ShipIcons_SRCS Icons/ReparametrizeIco.xpm Icons/Ship.xcf Icons/Ship.xpm + Icons/Tank.png + Icons/Tank.xcf + Icons/Tank.xpm ) SOURCE_GROUP("shipicons" FILES ${ShipIcons_SRCS}) @@ -92,7 +96,14 @@ SET(ShipUtils_SRCS ) SOURCE_GROUP("shiputils" FILES ${ShipUtils_SRCS}) -SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS}) +SET(ShipCreateTank_SRCS + tankCreateTank/__init__.py + tankCreateTank/TaskPanel.py + tankCreateTank/TaskPanel.ui +) +SOURCE_GROUP("shipcreatetank" FILES ${ShipCreateTank_SRCS}) + +SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipCreateTank_SRCS}) ADD_CUSTOM_TARGET(Ship ALL SOURCES ${all_files} @@ -148,6 +159,12 @@ INSTALL( DESTINATION Mod/Ship/shipUtils ) +INSTALL( + FILES + ${ShipCreateTank_SRCS} + DESTINATION + Mod/Ship/tankCreateTank +) INSTALL( FILES ${ShipMain_SRCS} @@ -155,3 +172,4 @@ INSTALL( Mod/Ship ) + diff --git a/src/Mod/Ship/Icons/Tank.png b/src/Mod/Ship/Icons/Tank.png new file mode 100644 index 0000000000000000000000000000000000000000..d8efae6a5662cb8dc6f4e26e5f27df74bd1ea3fe GIT binary patch literal 10163 zcmV;kCrsFhP)Px#24YJ`L;yzsngHlc#b`6}sk000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}001BWNklA&qrM=yugeGxy%^+uh$ezw-kUjdX2TdxVFNf9z&``{n15l*)~(2Z z;PJr#sGtNHQDFcX1tWm_fBN)~Gz{SsF@SRcECFz(f8qJ(Hv=GKSsYLW{U9JCWB?!r z-@Z=-OuJxO0~N-p0bB}T1%UJX3!64=Dm)zkWmz%6qz#~O@~j3jcyyow6(}o?<=#8* zyz?5yQ0EIL0KWxb8Gvs8;Q_rqYL@NjYiECxLDpLhGhy-xxW3Zo#L zd+x8F)`oDhFE|76Spfe6pw+*)VZ(;twUOXCVrSTXi19=yY{Za4a)S&wZlDQcff^n` z;=UjL@P|)JRG^bM@bjFHhcpfc`B?@{4E+F8`RnAop0X@4 z9*r*1ctC_-JL{|uv@!guE~X8@p91)5t$`O7Pz*Q-S%}#-<`Z!G9}FfSV;ArJG5jIjIgvdlqHt~?;O)2H4o1_})um43 zbV7g+0eJm=d%rt{gwVOTTaY>f??NMp-XFt6s11m0B0zn3pArp0kwFzY;=Y9}VJuEy6M!ps|75o-$rguY z5(g*3jH94}F5bY9F4CfoGz=<%caX{Twc${ih$KRTl8&Wk*V>PKY8naUv24Z|=u|a; zvjDsa05AUJ#dz^PZSyzCI|dUNz>FEGF>KiIjLO?BylUu82cf(mWQ<4E4^mh!kiov@ zzZYqm=(&OqTfrEQeXBProamRW0dW0`FT4Ob(iB*`VEFkm3$_z<|0-dTJ|1B*shN}TQH(m{(0^ltG*tKg{ zByokKBLjgc0;0V!;csUo(@Ric)22ZP%=P7wYrI{`j;757~*wO8iTDN zl!XTxgMpWuy9XBmcyYWKz)}F827v9`cZke~K;+{;ftaH->xR4-fB6}x{Xx*=(Y;n? z2s^fKFV_f!H)kdA4O2EIlOY6IIurE(p)(YmL1!9K2+D9QQQ%kxzQhQ60K8pq1Ly?M z4*=V?ZHwM7;(7w}1pPTh1|$4OAR)yS*rNrho1wN{yLRc?epx2qNuSB>RhE%al7`l- zSJcQ7=oqzt<;$1jqKhs%rkj4xJ@;VAk|pn==%5;@rvWSmFuyQ>twNWFA%YYKnnYG0 zho4vx27=BO{DB2vB%d!c2A`6ucrFJrA#D~ZQUi!`v*iTtYAk9TW#D)3*^^{M$FjL= z-2>o4jL}4x_iF%607gSB-m)b!JB|ZX)Jx(}1FT}R%>?AYdOSc-0Y$igsMHXPK`u9h z-Me=SUEf2wVeiU|%UOLWM=Rry0ud#dNZG&#t%L&Q6^4Io+`(PvG60{chXFJL7)WtjAEz^s>wt_U_%A6o+)r041&Ev5AyQ zJCj2pi%d&8;46b7JjH^Sb^r?KCQaaIVZ>eEy#T&Y7Xx_Wi6^2*GH~-Pw`gP7x<#da zUeA~HRVo|AghL3KSJr0Blt!~ZQ|&C`<(FSJ@^RWrm?;_92tqQf2x*#`(bLl-Na~I# z4@+)>l5>_w5XF?5DW$uvTLCS8bKl*XR7GLIit6?Hyn4{)@^Pd8NMtT_Nbxx zkqwI^kf(+bGy|xfTmyLgadiN8=^Wx%rpB;!iy(#Z1~736%nP)Tq|k;1Ni5Bcl*So^ zrlX+3tFOMQIYF3qhC~APa9yodah7NreSXUpk;QNn$7GraZJ07^DI0i=f>3F-yN(vg z%T9^`tX{p^h&!wxpP|`%Y7ARN_?Ljl!qSEJ5)zI;C2FGFj~OwqPxwdt-ZEo&?X{m3 zb%11EL9x%s@G#C1^9VL=-UPvHoZO+gj#5iWb0Cr?EqRd*m-4ejm@#8UeGp*P>ea?8 z8N~huv+-6p7zEsM%e++8bH)&N$s8)6G(`+IRzaeGQjoSO=$i(lGBq7VUwGqmnIABR6ofpzB}&t5%74Y*@L2^`d2t zTv*_Q%*>lNuQZFWg(7fq6Daf;m@1ZnWC8tRVhr2L1Yo2@)S|4j$}wA zVcnap;qSS>Hlou@aidWy?Q~x#jA8rw_3JN7Gz%(;-^qZA_YEJh=#U_WG*o6)^qN(u zh$r6wzPoaz8dvBj4zhoH!!Y(Bc|t^nTayr>KbuzEyju748*K&JkRHSkSBWrpsx$_! zAx1@`VlZaTC>EUf(T{!Lq* z+1)?<;SXlY-U8V>o@JyBpGs0cKa^zHeF$?k5KfU>A!mbe$)%T`umK$3yZ}FVjsmdz zr7(m%WC36nACEa=p0gVhhRBRuPdn1Kq6^id5%bi12f`SCn1QV8lucG ziz=?4Yl=Vq`f`1CCsY$SE(Cb&vBxa#r>tC_8zG^ALG28GE*EFy(yRTBf5Q6#B}cw?2zl1`}@ zwoGbEHe|&2Kl;&+`ua?MQVrnI#~up^8$5fUJK6~m z9(dq^z_I~g;oWyfen4EJxg(OQpc1kg6cxJ(_> zfkk3afrSh2Rw$q)1)VXF%^=)9U;N@1(KNC1r9b%(e=vUKAg zlVBILhP=2Tciwp?h=2zcEdn!e-+f;W2P%vqLM}_f;n9G_;BzsjkQt~RJ~)l@93aBR zfk~lRbk2l>;zBuiFH7VK#_oBE|5HO}F0~1t9(#U-EPOu7TnuyLPkuFU`SRr^uZCi? z?8%+(2+-bcvj75~+20en1L?Lf)()gSyQCv&(SwVUD_nTb-A2GMsNfE~a@9(_@Y1U< z|IzQyzo4VNUFYLjjLCB*_NzVx8OMpBg{zW=7%werk2hh&w8;4b69HFUbya;3z$f+E zql+7nb94;V1VC-7Squoy<1!MW7; zS^Bp+29dvSge>EjIMfXRmMu#pV3Z0xHS&Bn!0Y$*BwD^qn>1^8z>t~uq{3)CTOG%p z>!L-A6nZRNxKMfCeP8|(nkP-!dDTT9xn%b2D+HTo(J_SNTxCDOmF@ioS$6^z$<_0`wZivz^CokhPZ#x;+PoHno%2tR(aJEU3hEe?5n&Z;0BMJ4ZvxoZdG zBJGNjGrMppJWzbMKb1T0yt5#V4=w^RaNm9R1p~P2uDbvLqlbQR$>o&O5*d@YQQ!wqMtJ+R;#5JU}(JMXwNgq=kXJ_u&u zt6%*pnkV({7#%opDYGPtIt*D6B$%5s3V0_VVDn%!hS{zCq797WWhXJhyOj>1lmndk zUAcZCV9C;@j-^rpwKAt8FrIm{xAe={#6&VRa@7HriQ6CGxC9yrrDb0(YfD$DpjRk! z{KG%~1Maxv4xRFmkZo-hP)fU^g-eAhLo%;y?N2&@bdv~5#39>ZM7Zv{--u<#lS%?} zj<6?yD8zkcJoDxh5uOUaAd^ZR#3+ccYOjNk71G z&QY@U^em>n9E_7Gf;ENkV)q{oZZszI6y=vSwNEkK_^aQg8*Zr z1LVbsZg{iTU<${)JH$wt$BHD_T&(;aCZy{J1+}q=jbNx;pS|+PB2)-Y;X{cJStJz) zcE&C02gLxg2x>8aam;O9_!GwC-pkzev(p~@0B;`d3Wzeh`Cwf8NaVf2IJ^Te*;+*% zIDiFOaVY{s{Kb6@0a=k=Q6{(w`QIs~ zRL*FnH^*m>xZ~x{b4}_QYTKD;e{;lCu;a+s1=#p=CHTdzBC&jaq%(wx+0E|+p6B=T z&OkC7s)qrbJ4X^L{s0bEWmcu2_ci8Yc5eE@FoNg9GPm(8PHfnUsS z>W2hUxa+8!0c_Y;F}Zj&3TfR(JJApcLB6zo{aNVUY$~JiG`XbcMFJtB;PX5enZ)d@-@sKJ44`|) z?P#wS12mW^8W?Krp%%~Lh9g?P%mPZgg*@T$AIt>As~Rzq=2S*Bgg78(pYWX|Ud~1T z0w<}SJRVTgAvlAsf5=?jqliNdYY3jkkm9)})ilVkrP>v;lFPIHF)@Jb_&7lE(_SU_ zlj%_Jy~sSvivm51-jg$f-9`H2YNfb<_28ZE;8LSu7OyeH?;h4U9Nd4N+35%FeG&SL zco_f z-ClHevPXTF_Uc`S@#FME~cwhG-v&uB0qQ-1= z7&ox7#a&ED^&yF@hKYzgq_df1@l$u40?8vij4X-`5a@!!@ZqXibDUjto;QiA|LXX#$^Q1M?`iNRi!m?+kf&hM3+Ni5jYW zQ;<$?P+q*!Wn7^N7@eW`VD3n&F$4le-(y{})^hO4Gk^fO(!q5C?FOwl`}R=^UVWsA zRSxX?|9r})_?#p{RtDf0PuZ_TBE8J@3FHi9qMjbqHNjINQ6!=L=g2)uupok=*1^a# z-FrxaYleFw{$`dFLs;iXat&gN`oi#_Q7eP)0jCAjO$Uf<))p~+K2HKA{BNEs0F1#V z1{HTxrD=XGK`se9EHnlt7|#~>F@8`PC_x%8neuHse$E`PFBj!$Khc8$a$zD31@7NG z3Q-hfT$wYNY3(BI9U1gZr?OEN5iFFzCWW zSRov8jv+^DC(%7?LIH$06p{eXQ(Rv@ht_b(^o139LYP~v8b-~GT4g2}y;QJm;u?DW z!{-YlW-%8aAIf!DV*4knjASez;P^v;OzniyrBhTksgIR~i@(}O(>q9#6lrU38!c}7U^B}qQ9_Po4V|II1SX-S zi^25@pezonfp%|7r82O7Rq4!CcR#Dyj~ofFFj{$Umu5O0(Lsa7q? z0*d@Sh82qeHL7v3UM+eeqxXY=YE@h-Wl8!PPAv09pI8Bn1ucSETdz(e(3EGTj*ILZ3#jdV~O$gDSOi+sI|2w6D(D)GU;Kp`?=# zqlrUTRoh4wptA@Qx?(8XzKO&nEM^n;b*V>jDo(QnWGs+HlS6X%LuLU0fk$(*f_Q}b zSSl6@sq}Ky$Kbx#hd5?g1g#$l)H=4ld{87~#)QM9Q46Om;lqXxktKK%)ix4u?4Sq} zVZn+VYL=3$O8Y75eiRr{rpqui) z13K{#ke-aBdAcfQnQWXKDzr4xoKKAwSc@uBk#k|FZ6v-n)WQ)?IiiT?EwN2ZOdbV= z*v|~0%CXrhBO!f@IG?eRyan+k9qRP+rV3t=n<%cCS(K=Y6r4&JGM=-B z(~|aaorW6{Bs@9f%=UFAJxhin{I`un)orkabtthsgoG{-IDiqTad4L6Du)TpuZz!|WeFTSbe(%8_$Z)w0bZwvEhaUXk@Ctk6Mn%IvwsHT>sVhYI!a zr$;8?oUViV6QVgJG`))MAHV9DEDXu%h2mD|A{Prn%2L>JvNy+Uf`kB+rq7J>a#UTi z00vv7kAR$QTNo!b53ng3l~^+=U7tkW&RSt4r`wCr6L7^1Om6dR0Oz+4fQO1ae7K#% z=jAjoFp8G1CYi*rS{uV>87v4}NQCgBxy(1D!P$7m;(aa*);% zM6Wifz>&716PcK9T)-~1$D%-_f}FXOlZ*fqX5y$R;Uv5_>L2O+Uz=W5F9cxS!!Ogf0DqK_-&_s8oJVNH6ID=QBh_j`NRs{A>JFPw zYAS!SYbd~TwW_4r8(I$VL%sEHg9i(j!yL#@YzxryGRl|={zRW;K1 zFUX;u#L8nU2%bPsAgR(Pkt`IIOxLoLK}A>yO;sh3trimFi0iDD1`&lIz|;pg)Z4=Z z4PVZ+1Hx=-8@1AMi7cFmmTA7vHJUy}xIj#e!-Uh&6XDKVq#(p~ECw+{d$=mFa8er! zvZf$(9#Yjh0xW0oin;jiSUFSDWFi^5?E{GD66I%B%_*^%6PyiB2?U8a?vX^P`qA)7 zcz@^^%H!;1AzYtC+?)T*1PU@1ayL?>kVNlRTr)^^0+p=&#qoK9q2tV@THf!ilE8*f zXsBj2lSpBcT7;5i1j<;=cvs;> zyivD~Ae4zb9KAd!g2^f%P|X}x)neIgB4TbXX6fgg_Cu2D12E-jB9+#$Oc7;D>86#* zws(Xk(`a&$kBH15X#*kTLa6eSQsrDoRYE2?v4lmfBbhg^!YtK|1BikP%LWhDB^gPS zbk)w*jmq1rBxJM6Lgeb7Y#R$H_Tc7r-5_P8T)IvnvlM@P1|Vl8M_3Nc86?*(WYL{W zaTPE&tECzqcnoT@-O- z+UpxjNIC>`*BgigFOc0o6iH|vyOK0J;*)Oxt!G??6{}yy@W5s)xa~I4r)Q*I*%c$} z;6@N(LDupTu|*Ok)rTPBAxo%~=U`P;qh88|C!$qKbY=C>E7h(hR_ahHWMCgg2CtR0gS>X)&2@x$&$ z=E0M4h=m`x>}EqP4xyArmOpX91mCq2_vNrCLs$et%q?K?<#vGv&fT#PkC%sq8KA#E zk3vWu7IVmBbny#H_%I~TUo0G@&K27+`DCv|GH40E{reT+b8kUP+kY0|>tm2oDRy#|YN-Lu>jYaW1KwlGK*;)|iHY$O^ zw-FNq$VT7%m*4;Mla2s>8+iS1J~qr#*KFUu1BVYE1^~>txFh@&T;UZw^2lQ6R&M1D z;r4177w-+e=gxZrn`Kq}0Er$xzYI+9b_lPMo(zv1ak-T+=QbWZcx7Jl{rYvYL=AKp zVYO6^Lk_jXOdh>HTtCA3spE+Aeq`|@=s5qn|1lOUu<1m09zL}GJFVTncgcbMduE!?_lTFr~I?-G?^`{a>(Ug1xe$Q22{PsR{3*i zYAvv-Bx267>y;NVZQ2DTReFwI385<_=T3V42b;E<^#Pa+IblO+khY}#L@xoo;$*q000L9Nkl@EQFx3Y%oRl^oPDO za(MgI7~S`qlO|0As2Rtzx@kBDJ zb;V&3N=CI>#p0(P!A&>a9C`@!14q+^oI_&gpYKb$h?6`4J$Y7utXpJSM3RQ?&U5*S zWf<7{a2tT(ac2Nxo7{E&-+yKFz1`PlG%%~uTS28#!I@{CnSAiMov|(VQ}fO<)Q?rE zSnK^z)5)VGs2;PdTd(Abqh_!GpjsWp;-{A4rkiili$5ktC>{a@V~=DW{ciUo^Iq~< zvAfV^78;x&)p#v5T2%L6chnFOjDaxx z?k3EiKfe}j6Y6j7J}R3@tt9u6<|SU)?aKgM#{Ole*6P`qxH}{GU0*2QTXG?nYl`XXOWV@BivU_gwzmJh?s9uf?9Pl)wIow)S@P zRr=7|+l%Jr=3_I4^f9D0LWf?=(r1_jAH|kMaRh(eDiNd-h1&H%71x9clTse`uZ@r ztIMTIsWBv|P%}H=nm3}FSF!ZzWte;Y^{HpWq<`wsuEMZLl1*zATmt{aACEu&II`A> zKbvsT?|t*Ff4=#?lSa%i&bLV)zV}kfI__%EUb%f}Xb_c3ANu+#m@r{tZB!W8jQI=Z z*OrK=j6V?ae6%otx!0F#5R?)}ow^+*?n@+bM)Ty8PZnxiN6)T_moE7BzHeT4|H;0; zZJ?jLz?*ELi(-OO%mCcBZrxfSYdO?0{Zn86<+9)X%kenyA9MqdTX)xa ze|P`H=9m89(4j+^GGz)Xl?pmLJC*AA+>Rq)&N0%l<+u&N4g5g+1-C4E`_bF}>v$gc z)5!p$>UhbIKR?v}^lvottG@#Pl}ZJbz6v_pJHlr+zWvV9kpsIv^L~tA-MY1)<_Y^d zW`61$zgYaqFP=*G@7{NIM(-8Lu7_kFyhqXSc?PDM{o51N~s@m&AF{~ms8 z+wK29BUra?EvRMU8xv+NSajf_8~*B4ybq_X0f?<_@&(`c+Qg<^cl7rkL{Co-`uh5? zH*5J{Bm1|0uFMG5ty>FfoAiGt%v$h|2fp+1ubj#k-!K4~Ma=x}XGV_f{#1MR)7u6I z2T?t%#@5&x hTVrc%jqQ}){vUIWRAbs7Kw002ovPDHLkV1mlw2cZA} literal 0 HcmV?d00001 diff --git a/src/Mod/Ship/Icons/Tank.xcf b/src/Mod/Ship/Icons/Tank.xcf new file mode 100644 index 0000000000000000000000000000000000000000..bd306edc19a166e351a2da2d58cb4ac9ecb9fbc5 GIT binary patch literal 74661 zcmeEv2b@$z)^Ana+cN`*x`<(jL(WMZbE4P0=CJFU!|J|$A7Mnyfe{r0N+Ur@k`0I$ zFruqsKrta8Dt^0PPXg1LP++FJZ{Pd=|5J5)dJOx8_rCZ0z4vpVr)zGVI;pBool58a z`7a}@Dz3Wdl8Q_IGU8%|pKAAE`ZxG!jbFRqQW8COPf)`wHnb6Bi9%Yw;wT)21lhg5A9ZG-kI9 zf5q%RPcp-gI$~Y&*@a&qZCa!!KR+b->N(H^V4BmWIGwzE_al>EelB=y`uQQmW788C zA>D$Nz3>3p^1G$x9>+61eB#0{lCO+ChcLzI1NZ&SbQLtu7< z6sLzD3p~#Vi@GRniqb9E-BZy09J`B!-J_o$GCUM1&G4dh@^)zDRMDs|N}Cqx+o0Y0 z!FLi*vN;WQ3(w8)Bi4;gK6}JEq1Bu&e%^xJVZX@kEJ1Pa5$lHIgS6pyoK8+3drq?R zy0L^QN}CpGigc3IoQPr5RwS1me)8CJhUa%bQfM`&P0{lf><$HBb7Sa$blfg)Mp`Ft ztyam?2%^kS(s4x-#-=SyoSus3UstoNPEJK{|C&kQnS$qERonE(c>b=Wb+S2aTBK_M zv%FI#)nveAPHhtguD!HkeX`Nh9tCIgVpJ|hP z0M9>K$#e@cG*`%$-}XBua}A!M4^*h+KWdqc22)74K(Q}#3n+>?y%f)N@&WYjPGXF} zMN#@u*uqKD1$DAHZHm$@$n4XCOd0-)IUOZr<|vh{TuC64EKbh`*N4b+oor5<7U?DE zB3*57O)}lZS_Vnm?$v^omZJ!j7qfB+(wa>wc`8z5r8(UKMN7+Gth9>+#o_1do*ZV) zX|gyy8W#UR$7yrgB%9MM$h5TD#Y#I*$RrL^$^8yP5}X#NOINC7cRq$R&1usj-40TA zT4`aL(HQ@QRtjmbQk32u>0u70Ic<{7 z=@zUE0}+ss-*77M9oOF4=O)<^IQtxC@ieE4pBJ+`?3b<5@xn?skm*fqV0Z6ol^jrQ)0IeD zgQt_|Jq4{0W(+}ESfybttx|FCI2NEf*%>HMN%%1>(iM2#N1p3sbJ`T8TS&97fX3~h zm<(%EC$EK1Ge|~7(<0pgzDPUg05qpjL51fn$h5Rv#blrgka-AP-@KB%nB-C@cuwb}P8YKsU#l`{83@#b#Le!=6GKd4xIibD*AW z{nnLukX#^^t_2zL{PWTbz;m7a2-3`RoW2jPXNfCol27J$Pu}aKSvp@OXIebTMaeIc zvwljZrBy0cT0bH4A-J=Sze&CWz0Y>&oDA0I$@`GLN75~%p=y3!8uk{Q z+@@6W0SlA-4C(t^dM(m(C9RXIkX~HPKTPs@q?a<;vfm7qM{(U0TN89lkXct97c zfMTJAmzIVxQ(*4F^9Ant4M@jq9ZmRZ3)2H>3vY%8NIU6=Pe6K>l-0xgBE87sISeg2 z`G}<37R|1!Y0W>_7M^rt-_Sq?2Hv zWxRxifVmaY|6|<)SI6dQ~6~>vYSx32H0GKP8O#x z#q-}gS(?)(*_vbR7Q`Q6f7wG}GQ0vr1vHHNmvQBKmgAkFqcd9Om+;b9#nIXbkg z{a-dC>>Zl3h~!yP$|T=J+73pB9nJN7Oss%;K{bI)@)kT_%w&r;_RCfTtp!w`1BTvG z3jGck2D|jzcz&Fub@Dx=&vwt*?MFzuSYuA-^1P+S&^thd8jGnsTdk76bJ!N*`Sfc3 zVP(PJ_`!S?&oP$Zr%iLOsp87NjQt-KM;&wgNi4Fn zfc|CV1%JMH(4WWrdvL1X@W z;RO{#2M?8>pGgdJS^ZG-!k;M`=U4o4f<>>otm=Y`{xa&%6~kg$czE^CJ#^0oT|VkB zV=MkL>Z1Q~@ntMO`jSg7yLfDYL6-jMBm1OfQR>0{?1FAS;1i`z{fAQj^J1k&tx;+= z%+;fBDD`4%rT*-uo`}LQ{dQdoch#u0aDm)lcc1dl$x~i&ApT7P2^&c=`pdP3PWd{!#GIS`4_{i10 zOmEZI^beW0eb8XZ8@6YasR|E6hv}3Gd-T*jzv|VyPwzf`LBf(AL@+&64-5B%)E!dW zyLIp0qi4@v0MmWKzWsDR-TzzR(c&An=bn4*4Q}>G=?dLVci(1#dy_B18nC4Y>ml2R z4kPGZd+(iUpW52FOP8({72O24?x}m}-roxk6lCBa@Suk@vVg$1OJzHDW(nO@S7cbG zN6%imR}Osl5gPdc0|${xNY1lDCbe@a)1hO>PMtb;(Otr>6}sXJTTmn+Em4}NIzMFS zFg;A~8Sa&8oASyVT)EC&x^}fJf?TiOB2mBoy1yQfmtsv&HDyY*Nqtw|pXy;Cj zQ{AmmIAu}Y=j#H+xF&|BTBQP((;c!>xTEfv=>$Q$b^*KjZryw69=d1PtGDj0`)p_N zxNV4>;jmO`%9Mv4%1ycHpv!d!-BEY?hI%TfR@l~kbl*Ir)dTdvyr@(vhsX~ z@(ws9z?%}LJ~o##nRM)6%2)$uDYA) zo@3Jk<&0}e6qtR2bfIJ^>DiLN;Ufi&>rT3Ju2}Z3fuoo_T4TyfeQ#^nRdaa(4KReA zI_u7P5g_c=U3bqEx{L1HDBTLpGgXpmbSOHMC(6GAN5tit8k=^$f`zRNrnm0P&O-@W zr%E7p8C2C|r6q6Yk?e_C9@`;YjV2 z$^%rFqb;(2w#0n7HlZs_cikgok28HTwiTz^flS4B~dDY+HF!QLZcNZW-6JbnhH1JJkXGRvISi)BscrjBtYH zsC(w9q`taumsCK#$K(r8R+$E7NcZUmRHnmsVmi!Y;PCaQfT&4ap-Nj zcb}B$(CC^aC9_SUrSY*rF7?v?c-Q_sZ3EPm^{aW%G7Doe>|w@l)gKQ=l9O2YSTQbY?*lHU8%{Fr!eE* znX{_O;!)*Gj4HR?e#gYS?wXXk`)*|4bMFk~+d<{Cn{JtKD|7EG&YeB`zUE=2zWT=T zH{I-@CZ#6defJcLWA>am_sx|-MPFYtj!?JUGU2w{TH=~DYxaF}=gnUrL(0Z$uD$m9 z8vuIKO*h{Xlbt;I?x|BPQvjVifBwQn7*amG{EDlt0{C^;6Z6dgzm;50nq)t?zx>LpuDJ&IZx~00DVJqMbRt5}o%=I^jURsiw7L%EaQRLkbBl&OSsL_{R z%7Ry3g>u(Xeqrx6(3&V(r#|l?tvPc!hOm$~a{UMtB*C#@^6G1@yN-IZ1*N`F6H}&u zNm~$Ohm_MJy%Fn2ju?TWpb7aXU|iHz;+?2aYKKB3CUr0_)UO{m4hW<|ti(bcjL%4= zY*EL$e3_AYgdVxk@&IiYlm;F|*>~J|CtD!}xOc|Lgn*Zj3*chW4@7j9yy|MFZnjLc zhC85caL+DsPby^vHY47al4KO$v<#V@Xb`$c)U&xA0tp)>&xPwp@|0P&CF9N6jNOZ)9zOlI?ENEZOs|6`9Pz zWF*x>mDG$Fg|5cl>AITq{+j_V-5Je)SD<%t)JW4|XCZWRn=e3P6cHVp5jD^k`^Tk) z4jDIcVn!#%5Mnu~xBW;u`_)&|{@9K?ffj9Isxy1`h)p9$i&U^7tTWmW+eyJ?sv_m1 z^M5X#Kkme~FS24VfanpQT3#IA((0TIO7%{CHlolVY-5)GfX1Bam-;d$OJiqk9n_EE z_Fqk-;B}YTlT6eu7n)dkwqCk8sknP!$*J)Q#5=u)Yt!b_$aB@4MnpN zU6-k^tE;bXsMqzTp)eO|#Hhi?b@iq7xrX|N1~*`YwRMTQJRT?Ny@p^Do)_jHrdHP> zTh{?modFfE-fsvu$q3=s=IfZ1udS;m0~%R+Q_!$!lbvhShBdVo#zXP2uHLT?Ek}A& z*s#fL+BIcrG@-oOu&!3u26eT>mjfqt^_EZr&;l6kuXT-QdGUqS65#{c;U?IAozB;! zYy6rLVW~_YJc!-|Avb{`8vAq(AnBTfC8=w(q*hyJ>RQ*AHtdipN$VOf?ISm+5jI3C zS#W~?y1t|#zo`NJv`xCSCakT|H9ok>)k2-%xK(`~>eLNosU3xpL`}YyQk4R?%}Jzo zNw=y=2z$QOh6j~}EajzkPX{&WG>|5&A`Erzl&0&OP~i;?sZ@FoLGIOLfn4xY|6ZL( z-J1FUETlVHOdiB&q!=P%qOPPq3nW0%NhE~Ijn#H3c*(G(G}OcT?UCL}KA@$VTKq4G zD?eas^6N_h;K$N?by<-fx)JiNQ@f?D+$FUMi>9aZmWSJf}tMGc64qXtDgs-e*iYR{;(+B+&!`$P$~f8?nHBdxB-=ita!2SlZ6 zU&(K)hDAH8!BTcN)i>G$xH_sHQ5RJabyJ||f`|fA< z3lG3qE6&>SY#W~eXuksvP&=s%77hSPMEmG{GyCm-!2Smui1nV_P_7N=y&Ctn;QQ^b z_tyvNgIcRCh1H2l!LIky2bcqcgAP6zOH7#gVs$|8rT5+vm)rk<0}ed!po8_n;UQ3R zI9OIp0xnnRy}z#{EBoyang_Rju-+`s$3qW2yc7*-%iMVj7D(npOCEk?8AyM7-@JMA7cK-mK^|H5D4Nk%bM7M? zA3nGQaCrJS#Q8$z5kSc2D8F>sqmMoQ#BwO$)0wkSWPWkhvd12KV)>I#p%pd2VRr}@ z6$(E3_~XcZ`dKuhx_f8Z8H%uRzhHi3*<%*qnP)NVRjV86L>I^}w&ckcX*~VRvn!sr z^CHp_E`UbFA%g<(oSljZC)COPPT)t0WBHRZCcp65nIaVko+RtX063&=0s|d$~ z4?+#lV?upaG&!4t$r(vJz-+XgFW^)*W4~`6XKsrhcmRs~$~x$7Qa1-#3l>7t-@x6Y z`yD@@I~VO{3um4(-;%i#>h6a-I4uJ1sne(5%XV`|qrl(++D#Mu%sb(RquFHX)8C1v z5x|!#G#kCCi}E*hR3)3j&1fpE_yt>oq21qPHV2zFZw3w1;B5*vZ`!ok+Z=w1wxKy> zZ}K+fH*eZpvbint`FCPd$>!kG&7VRfub~vB^(Jq#{xpv#B>o=Ta63mkNx3#rd(|r1O_fCDg40Cflx!^xRra(lz7%)5&c%nj2yJAm z;m9$g?Y_@{=VrriL9QI1pWAF$hv)8RV6{ucY+|!v;0)}h)U}!O0^gy2f2 zunTiP*s$S4{h|3N{CK0@SON^c!Bf4?tamxVM;|jMft($g^S)Wj-0*`9dPCEPA2E01 zCmwR!AUFT+du#L>^S)W9*Xs}T1|lXka@va2-hStuclEnX@2y$${`+g!uG8y+^&b!u z0kgmao;9jkuhwscZ@;78$-es@Va@x&+I8#J$4E7}#XgXJL%-R$`mNP(y=~Fz_w<_Z z{k3{+X5IRA>(^VnzRG;C;RB^!U!_;EfL?9h`j+tTzGrcRjdknIdc7g{p;8}^#yYLC zufF!$>nviVfPP!QvyBDTyuZfs-2}dsTD$gr{k~TEmGITq%xha$y}oMI8*jY%=4!B{ z-!|`r@4iQ#%=>yR(5i3^{@ng9&U(MH@|9O#eNDd>zP`$=3g38BzZtB4%a#eqm0r`d z_WiYJDDOfC!2gndIb8XQc_sVWtClS*iGGVz^t<}KaE)c;Eoe^Z7tKpsUtYQLm6agk z#CRiob2YWV+5n`l5bOzhp>5zoK6aUwhrWu2*?)hO6HqiI8;` zVE^lN{W`EeuV2uAWdZ%NS!pP`ehnF`474jHzNdPXdhOL$)gvobJl|a4hnH89Ey^y+ zwNiL*HNLIX%9oXT_Bs9B_7%^sc>a0tWSPp^0>YGj-6?A;>RhRpUR38}kkrox&w+}0 zK78S?QtrGoa(`uz&Q0l3t_0#4V{cM(Ho_~R&gfG5iUJ74c z$ujy?^O`|B`Qc5aRw(u4lTSVM^wZDiXR^;e_v~{N1w>3Uk%IL3Rc~M{4WC%9mxoV2 zrJu4y^mArKSRg`$#Wcd#0iMGMTvS4XE&ZHcp`SND;VOI$@ZMwFSzx(vWu6WxySE~s zvM6})(#sSgfO-LJ9@UTO$MqAQWhi+1nP;9g&*nu4N^PV9^DAEgtbQa|_UNOJnaA?* z8q9M2WN6joJr~4Evi0q$EF1%PDBh#q<05U7)zH&m#XPq)uDKUqdI@Or@FMim@R4PD znFcoo+-M-DcJwpm+3>j)dPURoFFcQ`evuq6F%SPh?8_b{H&Bj#B3%BYK>^|3Y9|YE z;c%iIKBynkOZ3Bfsd+>%3m<({0z_ z_}JsrQRDI_;ZE6_&J2@nKol_d>j$>L;ac(#yv3!KG4p5>TsWx&{p7Z%hQPreIt+d_ zz{5q0_2TgU2lNBsgAb841J;@-4P_yja5>!UU??_Zy`g9<3m54{;o|%C{pJBrBr!|# zP%SIYV0#Wz3=dAZQ2{(ifSSb`3|Serlb>aeEW>72VsL)Q;2~y6IFvHZHw*MaL2K^M z!k>h%rL4!STi$*lZ+!xNBr{`to!^tLKuozpMdO#yKvbYaC zV4y!R7&Mr39-}g|X3PG8o~!2(alihiKW762O0h>448pFlKgg)2nQ&YQr|%2EGxsmK z{p9x#1_0C>P%_W}Dx5J>&(yPW1nlc!bF^>2L_fcO$p9bwg<$MnJtId%eN3M`w#mG{ zSwQsb4{TfelO%T9D7!Zhu=fyJW8Wz3-N)}^ux*D;av#`A2ZRHu;py3XdiTcGkl)+K ztVOn~Fp=>w)hQi-x|)V7J#%61@$mU@~O- zmV!!?&9QmDV9|XNB9h-P4{k9jQ+^M>XCAw%rdMh2QsjEvT2w*z9^HF*JrX^AJoa26 zWGT}k}K)s_1#MOBh|edH_A$ZtqItAQ7X&021|L_@XtgFK->TfdH`1U2zr8X z)6?_{Sc2#bW^sVxW@I;>7|4Mb$@w@3fNe$}+iXD}?AImw1d*!fmgrU@{Ad7__9}t+ zL0>%gEBtPy-MtLy|5o!IjU>EvnExaK{0PZ;Il z#OPNw{Ds`AH&(sT?D#Z`iA9fh-+2cf0mpIidc?yBIFO6TbYl!0GUr{<0c(Oofbsps zm#k9~zVfOi61#l*E$?lsA(%6IJsEmEf3@&-OwPUbs`w=0jTw-j&sXI3{Mf(1F#Afu z@sWxMD7m<6uQt7+mSUt`0skVTA7fr}evEmQo|SoH3w^}5-hK;WzD&o*IWf(y5`8QE zO2G})Zv=0yev{r9oWZ<0Uj{cBK%GkhCx)_T;PlbGqK38gEQ=f;j)*c!udoi*i!Z%w z3N8r?z#&rs{T`0eZqRL{r^JC>oQ#4b`qkjI*I$E&j5$HkuucMWVXTj6#N~nCDt;)( zcYevqHk^h2kp3-VA*>v-CUb_Cbt$?z#7#d+(irQ5a)7lG{Eeg$ov$MS5{?{{s(9Hj~ZWW{RGgpEh-x zo|c&o-1po|>EH%=fOeRJ#aPS2HaVd66f-pd^mK2!QQM$5R1OyQ=FKN?_RhPosx`?> z!s!mc22-$3W~Tbnpn#cqtPz?y)&-iVCwh14ySzy;PJe1RjTM09NcuRazVP-t%pLwj zEnqs8n~Y;2cU$rh{2u5lWX+k|%{B5`1rU7m4&=YfaPQ)Iz25>Gl3ERpV1)!km=4O41nP6`9Zqv8>caX*0Bdhd0pxI1gYAnX;3Wy79*Gdc3|VxEVX42GIJ} z?1Woyz3sN!$$^1fTc9dIo>Hp1`o{6z_{>cNzWEmNpl@vgzgQ)tXtB1m@~X{^255b7 z-~lKAkYEfZLL@3Hn55J=GtR5_#+#eW%?4m((!1TeBZg7t1`PmWB8Vp<2e;jR+wB@q zdSc_9k-Gi{ZXXjYBy0Mn9C)K7W~2tm~p0B-$=M@EQ1E!Eo6@} z+!3j3uWJVV;l^s{XZ%e#2?B}rEtv_oK$*AR#@cL*6gH6w?Om^dScB1EJT{`uO`elF zL$mZCbFI0~yWYDY99M0s1JFnHn42`D z_aM=K!3onF+qmT@EFgXS5f_l+!TRUjfp7)bj`pS+@eOVwP2LyLY8AIE@M5^Eu;aD zZ_OI(omp3?QHpRSi_2x9U6*RIE+d!MFrK^<&_UBLZN)%p7j%S(_<;1!xGv?^?#M{^ z78jos#zt{BIJk2yiT(yCK>t(i3?4Xf`TbIgMm%uG$ zWi40wHRm^)H;p)rVB*#9)KXdep$7;bFkUZexyEFq2Hm<8)_%+iudwW;SH@l}eYx+% zmxK5DqPn2q(a?9`LXkK$R;|`2(}0JkY!{>G1aTF|twxy_0y3myZ&APc9T&>jMC^Lh za`-fKA@s9N&#jOZEUZQaRs^iYVeyJuwH{dz`x~;-V&Kil0$G;OcCjnN1+v#y!T)G1 z^0Ca*O?1nE-Y$2=Ykd^D;FWPL$F0qfpO9`Gd@@u4yhJZvipsz8D&3}K+hsKe4$5*k zmXtueIQ?8`7YB1v4XkOq93?A8vY?|M|MZFFPhfGzuFjAzyKZNf2f1tq0=cD+h)?6z zb7WnLbhbNR4wdb^cd7~n%)?nJf)ya^on$QqisII#^z+#l{t7C9&M$fBVJSfuC0@u9 z2eW9I$%u2-(14LsmVd$}4_hyg{+yAOII}!>3Y&HX>9Z>uu+u`90gjD+C`+&DVXREa z0?^~%+l4+9U=wNZc#;M^nvNOPbskz`mV|V&3JXlE5i3SRiG>v}i@r*+Q>Gs=;$Z5> zn?L}&I`s{S2Dca$EWUp+mV&ZGAG0sZWb{WH3{Rkx05(5=!9u;zEH?LtL>+R8sUWKy z7UD@2w}SdV^wAFI*?P%oLLG%%a7Md1$CKh6DrH{;L+(oZU*Xuf*M5?Rb!EJddj~;Kl9))uoJW7JECOJceLoBj4=2I$AmW8Qs)@(f+ zJk)I^434?r7kAqXjsn?zG-d9!khAN2Y_9PDRs6wu8!3^1(B_^14jB$1>DrPy95!MG z{-_TKQwD%w+Vtso;?=fcHVMUua1I9A0L0Wfo?_CqV4UYp64;vqO$b3)*}gM4Q>9d0 ztq&Me>jAbkfjl`UB``p$!n#^_Os9nBk4mWk5CkX20S0wS0S17i#`8b5Jm(?@#PF-6 zZi|3hJ_(zs-7ZIvmB% zp;mpA$FH6$Ohi6Y-EsT}UlrI$?W)2ZqBc=y?4@>4p&#vx?bY_!8r==&c*54v?l=b2 z5yyZ+FY1JoKo!_X?H-k?uq^6ZY{H^luilaB>f>$%kJ7gSRFCeudqUPM17vkEU3Ay50yw;iL^sbZ zCGzS4RvwL8^Mqyrm&Z|l;}C`2fQ?sOy6J9ycOOKz%I$-mJtKu%52i~N!1%Ab`nZQv z(am(jeFj`G;j*ZQWk_JeQT?Vaa{RwbSFbCM`FE`_SaY;+Zs`;E4tgknmUPYlln8N8 z#X@F)mCK}_TiV>-vquyuTxRLi+3)NNvkAZk-Ef)0IOUigIYl7TDeR0pH@p@QlG&23 z3E@(A3%UcT>29J>0RT61OeY^VQ+Nf6;+J$a0_b(ifiyQxbBY&G5}op(>vi^ulw@$> zAgq9XLadoaf$GS675PrQ?4vu&jhC=XXTzHbT|+7=sK7lADWm`&D%`gz>6ifdpbIpr zyCg*QUIiMW!ljfv@cA8m;0ky-CDA1V{_Itdd{-5Dy9BkKD8_dh}b>{la4Y-Pc*_*~JGGEQPS;kEcy<36_k-ExU zWvJzg?66l3E20TjbbudT|It0y4z*?vS94xV+CVKE{%xpfkOjHban1V z^rFkmW!_kQxd&_-5FX?pgpcX^wrX}WoGQoJX~LK*@>gDQr3RdLbt9#aX)vea;W+f6 zP+e*+)noK!`LUOc)qwY}$X~H(G}(jZDseb39h}49WA3qj~WFyoT(<-rpv%{jMoQV zeRWpQN{<=|P;a!Z(wFAI#2Bc+j5QFCNX^yYk=+ir1V))rdUU>Obd|0$mxg1YP%}0m ziq}^GioI~8KhlgMF0#jb1F?};iacC#@JH%V{^+3UQc6r|_1HWP-s{T&!cK@g2=;1$ z9+??MwkUyjsTpISMRvp{^1&Mmns*3rFn^SB9EqGj!=4C;kt4hj-bh>o899nDrYe6a zJ0rNzBffAKHF)$NfFnU^^r+G7ju~4Nh$<>vs<)P*$l^5 zMxfX`nc^S3OT)`8?4Q6X+&9TL9(9d07?tZ6z}7tyrbnQsvc$-!A6Q0TZB#hV%fTI9 z3C8vvYIEWyc(ph~A1Ms^a*$Yl899VaP&yuPPw2;J`b79wR|{yKH}`5X0zr2nb~*r{ zYw6SxWeI?E4bCl-uC5VB2hI$=9nf|FrlyHl94Y4x`L&rk9Q~+I6#AU(FohFlJ~}~IswAs-SJlViwXjU>%oL>YR6C|1p~h)Wq#(6M+)bol9yAWy?S!L+ zJ4D@Z&a5Yn1kzjXufh`5izn%J$7cu=_}L$yQ}E%5z}9ji@YKKj36Tqw`tLjt$mj$W z`25^~K08U%zK{-4bT;8WVuXyqVfepNY2^>=yRNfQC2N+z; zA22ZC9(BVboDtCjLY^sM4lkmkm^Y|vc~14m*$C4=fkPU|^?5L5;GptOC?j{?aoU5Y z*-_NT@sjNfN+AEr%L$Q?lNDb7JWghm3@8EG^4;(pM>6bD65T)3kB3D1gQYA8{pn>H(1B{13>@kiKobt#51poa3-oPEp1BJs8CCJ4M zaUA8~ArGE5$&rjWg}seEK;iXig>xoBe+XlF^(;37;ecio4n<&kWzTOU`Z%Ua`X&08 zK;i^6)THh?N^Rt`$yp1igCp?B(?;k+UbB9GLM%4+e}E z379QcJ>?7wPoj9e0-nk+IKGcx2`R;MA-Kz33KsGMR1Y7sJPY~*_~idSxR%dDHawG~ zaYzOSZAc?CK;fhbXJ&|&z=JTlm&UP=us6!#60{mo#vkg<9#aFafj2 zPjrub&mKKXdU`xALTWlb(o+UKBLauQ(HBmxNiAJ7QA#;68Ah_z5 z=++8HPfFeN6NnIqgTX3#_wk_TMuoW_W`CSq>F!OK1@`Cx{(YQPp|}YE%kdWvm+kwg zu9*2IFhBOX<084~URF5o;>mfJQfQr1Xikt5n9^!Y+hi7)0HgN&PM|Qc@&uv;lVnXq zUU$<&0zKGsL2~ZK^vXeOH>G9?W2dT|0NeR_N%uymnWFPVPf4$UljV4_N)Eh=vTg~P z(I$F$QVpT%oRAr4Jhv>98E692ZpVR~57IpYPJaE)WnB#Clb)SViZq-kBLV?5V0uVE zjh-q>aW=+Du;00)3#NvgS(jCmfVkHKqm_v?W_6s@8X=zO5_IiCnAXswQvkpckpWoH z8I(0BbBgSy@?1^Ga5CMEBXcH&c`yDOOjj}IOn0T@tc2}lSOe}uG z#8!%lMH(g+zr(0<$4YBrD`8?QVPY#`Vk=={D`8?Q!#!zYD`8?QVPY$-iLHc*t%QlK zgo&+$iLIoGt=y;bpa06Ki!b?ef%3Le96U^R1U4otBd|*{$wr=FR2`aKQ6q; zTx9;_T|A&NP#0Wqp}EkzNF%o|5TCEl*B5vf<}SMMA{GfRuIyQvRp*^|{(0wn$RVit zQ+Jd*=bUr(x#m25e)fX%≤HNV+2D?6c3&=a_T7^R}W8vo6H{i}XdED>Le>v(G}d zImbUYAWD6{e?iE+4j_G|KGU3K&i2j;&OPVc^UQhX{QL#yUtliK7ls#A?gqqX{P9fh zOz$jxwttR3H*sEYKC;PD`^ud9!x?A%(fgx5GkeyVXP$M|+4}74IcJ{>Jmk@w?*Ykg zfZ_MQ|AYC1KEwN?0jWHAF=vz2{CVe|ry&aI=?iv*=1xBypuhiv{)2yp{v(MJFb8}D z%nRq{f;N>~)oG^@^mGdxobd;+@iX>S?C}>1n6`-T;i`gERm5N9aZiPEU010rq5bvUduR`lp-UZv(Sb z!5IKGXXej3^DGV2`Wz3{kgHTDo_LZz$()=!<>XUNIn|tMPRoOUKAntsXXH^zLn9Q@ zoRb%&Wz`8MppZGq1CiXRr<{7~Y2@DfeeMrufRGlgG=dDPll2{_S*t1?-=h`{X6eC4X*qX!;?-Du47*N9&{YG5KSUIaWg|b6oy-vKO9kqAzOoPVr9t z;WTylZx28Gh$Ezsf0Q}e9OECm%~Cr4IMF}`q$rI(DLff1DtD?%CV#7cs}B#3KuLXs zKGFk+20F<9?%3ZMXxW1fawnq7QRDu}p&E{GiOJuxP;mGWEaD$Yp)^P}lGO2F%++?N z4%3Hu!*wz*@aAyu2=7RJR00|Zjs6S9O@sYhkMBYm=7mnb7bzQBT*4rgeLP^v?MdELk`u428SJb z*l=&SNqWEa4-bzxGI3UFy(2O@-$3&8m2rAQ=Sgj(v+uR%F{6AX=}>UFy(2O z@-$3&8m2r=Q=Z-jldOOCE2pqSmEJ4e#Bc0YrH7&bc3?bgn+;~taC1sFvFg+P(|OfU zFSo<2lftYioYAb2E% z0k((S2HFk+S5nV=@dPyW*}D3);`SMDp!-;rk)0gul2IM9TgV+Yf@6P;LSn~I)s_ml zfO6G`Wm~a`0e+u5hoV7HP~4j0YL46BG6Ku3x^|XCBl)PSS2eXeThgcm%H{rJd&*Ld zt4-Cmt^Gk(rL6SayuuC@Id4sEl4eb9JMNV^0Jqo#lsna7$pj4LWF#@?4t)HbmYS(F_@19932Ze7b&FGf(n@>wfNZUr{7DMyw{ z5K}^79jC0;)W{-R8R|y1;B@U)Cl>%}xwukWlPFp{5}Z2YQ@xu~Hd zS=OVq%%!;SWNLg_cxneC+la^hQ{zfJWui)zi1x%L;}G2K8;IL~{ctz1H}(~K;5udn zu4Q(?ZNrYLEA|?@<0@w_T;=SGtC<6^!#Frw+?1M$4ab6ev-UrJ=d*kUa z|0@93j0b}p^}ZDj@WMU9ap9^aCO2q4YKgdW&t5F5+RCpGD$90>guz1o8kRC}b-Nt7$2Om}781Mt=iPzsSX_(;X21Ohp5ut+G!f zzf?3B3PY0f`Dj=q8&P{l*auV5J`pa#M&ZGS=tJB<=_d^aO84O5kM&- zCXxmh_Kfw0L6Inll{RPR8c;%q0XM*3Sk~SNxLG+m9TMvn7QsKeu+5T)c!IxCh?P{D z29%D2$5=2~6YqpIX%|uk#qnQ*j=|85`YDwpm&kQZMzFDB!W8xlAOs(9^MF-SX3=Nl zDeDA4ZPGzansp&d-~;Uv_+VQc=+Q?=1$~5HqH#44rzQH~UV0xKpy&zX)*VK!D~w$y zoU!NtGFM2 zp7P80!f&iM`{l!s&{&E_m`$jmtUSCs)gMWZ>(co4qc(ih3(1mbhw`5I#xWLE-liOp z8eyGwDDR5zw)RmcB)R*?b0^BMzRN!t;)-g?2X(6zWdr-gX9348>UbRgTb`V;R}nVSdNeOWS)n0+PhU$8HIar zCm#`XG*qN3Mfgf9e5GIMgs*hMS2hb@>4fJaCwyfrd}W(TCwyfrJRZfuSGKNf7QWI6 zUl|LJTqiu1lq#L@m9g-66boP3s?rHx84HixSa{^d!dHs$SbK?uuk^6QVujz6L3k*9 zC4^6l@M$YNcFvseX(xQTS@^UQo{yaH=~#GlPbYjj79Njc;kk)csQI)LJ{=2>Tqpcr zk#xeRW8v{A7Czl7?SxOq!Xq~p9=WmbX%QaIek^?2!z{@P{~=8hg-=6xL_G4N{m|L> zMW?TnNKCEK`P<;LLp02u#~Nmn8omymw2la{Lk!@{pW#XJ#bTkcPju4JKZ|!UgNW^qjq;6j%prIfeH$W%f8zk$^U-q<+73sa6%6mM@h;+<1^SI& z<6Yoh0q<)38t>xA_fdb1cfq6l|Nq6i$nnxDyb_*+{||(_V89VVyFd~DPOuAJ5)D@X z-r#oSKaF)^p33kZ!gJ37_}`CoVPkOcIt84%Hy9j4uHE9o z3GZp-5&8`x-uH7cFPd*Vn5ElD0{44y@0PsG`El?Ijr$QU6v%daw-OD=NYGKm5AY%ABC>9pep}S0~aq`{53~vonHFAMjV9gWnDNNxqv!1eT z>Xd0yrx(ln1+Rn8xsTxXE-J77;_9uQ)MRDm6=hyJxyOc0F*BP`g5bC`j9anx0&Ykt zLf!-ps3$!or0BT2%|I(Nv$F_4K~Kot%B!hbF2~|BH17^;dv{plmbHPdLR;7QnLNMt zpY;lV4g7)YkG}@~_%-l{guwVU@P`dD_Ww%Y4~Z3mf%iWa_Cv48KmP&;$$vNMM^0|Y z7QDcJFYL!wdkq(toS%CZ`2XFYA9{KIsVARiG!pQ>u*k!)uB=(wSa72Bhfz_o)X$?t+#(3bd^6vIyDPY{IuSk&utlLjjD$^_ zFR@GL4mH_3wKhH-@9aV&g@7Q|Juq|Wnq?p`oIm(}j)c`Iu;;`_b1_6%#K0fQ+FQGH z|0n}uufVg0ODBW8bNuLOW#-Ovq2~g6mJ)jouHr**jS8NMcs7=ot#j`qxDD!}7iBE> zRL7KWrpEr?jM$mevjh5n606QSmxv$@?-*?lky^aigD^JyiJoodn7IfU1NK}`(8VO*A|9=D>agO1CG~@_l+F_J?z`%p~ zQM{2KTErVExP<>a;7C&(nS~)~!ou3%F9#iglgC)Qbn_6x&@B%Blei;X(KU=iYHrDeD zmLg8FSq2v?jz=P%Ex|Jj7tyzZwW4>!l9Q@E>kDHMFeJ&d8P2db??5xjUNmrjcv#0;G*@shF< zhmSG#Aa@?`1EKfkoH1j|d{OWaQG%iK;J0#x(`w30&%+VZGmI=kQiva9i4gD0yTdwS zB8GT~;`04?8B$dB59cJJlq?gH3OzoJScdR+>G6>nO><@bN*H;zC2^Gn13cXN4`LEoIi>;D)G zF^j;7Xd?Q~oHTcKD>wBhOw_V$fj8Z(5$G|8na8cN_UujEh6V0P=u)8vO5g8<45lh3253RC7c6B!woCx$} zCcILjo&?t-z9oZ>#B50s3NFz#Avunkfy9*|qoic{3fUMw))QiTBEn{Xb0<7Ztr)39 zUlrI0DItM_8^+yGt*a5glkrTP)M)Qopk%-}jiUx|4!;{!xVLDwWCgJd8; zhK-jZ!kTNdgpP#`#{;qikd1iZC4+oieuYNt4s%sb0*8n$`Lft?04oF7)+&i%5{b zvM~raLQcXfk?|X3w2q^OKz2OZ1&`YD(Pj8!SNyRP-a(ARpLpouXe8l1yuODBdHxPz z1MuAg-}$Oz(M1^|z(pNEmEJ53P%2K^hnX1I1&M9!f0ON|n(cwuvttWJtCcd1t^?Y! z!!}xD`*?t*A=xLBAqfqgky6=}Sj6s0akOz8Uv`xQ%MsFF89&Fh!MLGogs9bb26jVA zPu|L%L{K0&+K9O^WM|bkhcpY?c2>Nxia}*5N@4s*J)=Z(=g>Df>GiD!{S`)mp=~M1 z50st9&(L4lxFnFQM#vmQk+novAnr_enMvCb2bVptsG%FzTk&Qr*ZE9rskXWP%AUbE zKWOZX9)!j&G(bfJu|}kcF2G%`2eQd)+vFJs7eR!q-N`WYF7&H!-A-TiD!n(L>DTLEM2TH8sVUx>+&LX!`8A zW{fvBh+`uC$k>F{0Ajz@h=XH|0b?Brbs{uCX#1>Z`($OBez{T;Rs9#GcZUbZUJw{=m1zrwEZp1K%&g{H{!sx|em1f}EqF#DE zN^sO@q`Vxt;ZTUVaU)(MdK|0`@XMerz0~#W8>-nC92s*90&l}PvfhLP53Z6R&$flL zTj#_*C^CaB#?^q`&42{DTcMBAKM)$!Y?ByTV7Ftdj54lM+fF2QfL)F;zO6-*5ffp) z><|c+u0jvpE~;|D&77Sr>Z2T9%@x9rHB7{gc-r7akLTfXj4up!#a@A7*meB4>zNz! zM=PE=Kx~|-2oj|kMaKZ2G#KAymC1I+o5879fmK2@5wNl557;fVSH>jAIu^C z#5qK9L?6sG$R3^{<%0TPPBIB%<5|xrf041tZc&gq)`j-z8U}N;d-k0Hi z!ZSHn`?xP&5gML=cdF#qcU2WCJTgi|`PH3N4;Ai*7MOo=chy_v`bJCJ;~K`#g#*HC z@(@$go`m*Kvj>#p3mE9G|Hn^Cw*$@uK0kK>Lry#+4?lBe*>4r|hm+ECmMit>^DUpx zc|)m3c;*||A2i=J1&vC-@g@U(0}S*@1@YSP`an`kDnfJJ7G|Rr<~KqEaZwHc6|}LcLL=1?7DG%{Nt?Uf>}7 z>JN%4LL&d$=3)7a731iATg4aNud}U>l}8@=wg4%^8fOc!mG?O-?;m856PpdJZCh__ zQ_@?|T>p+MXAp|KL5sHDzNu=50w1%M*#h}Or?_zgS}F?-N-FCgP(jtMfc{r#OByR$ zgmfs&N z1eqk|zY@J8cT-IHtFKduRCu%GerpxXEE2_qkkV9s(q)pjoeh{7?44~=;azy@s~j5& zR?v1#g%j|gjrvV0ya9Db{=g+H;6tXx_P zbm70F1nuKzuA912E)%*%zSu`t8{3g-L7jDCBS%ZBZD}9HzVM9|wz}E<{`NQ6BsMr; zqka73b?IwE?W6zt1{j}$t+NI= z?k<0Groi>+&%Z#SmIm@|8h9%}p-_vK_!-PVY#>X;2&{1fgIGukP7P8$&8;);X$o7#p(~-P!|t0F|W=j#Foxcv?ekGUf)C;(C>UK2Ew&C)NWB7z?{%5)1J`O zSsMxC`lG7AuIG`CBQyqb zv~yGhTA(#d?8=VC*hbPfa6=TdAyvmA9aaxLHMV-RP|ijQPtI)Hisq;e^bMkRwhuy! zjfAgayNt7ug_@Otft(POHuCS%X>8wgjfY5`efi=`0c>F-(FI*|wjDrp2n!}QlCOXH zlwC?%p_n7K2@Vh##0oZ&Dy7d51BiBr!`jHWICV$oKrHCj-xS$MHLMHY>F57>8)0Cdy6E-a5I~xguW{bo4S%YRF;E(~x`H*PV&ee2dr)zL-PzGR;jkKU^(3lHGkJaUD zBwle|WFy~*o!Ho=H z&O~zjfNtU@+dS^XJ>EK>a5JRG7fd8xiRrvT`UrL;B`HoE#6*gjU>R6(nn=7$^4*P8 z2YHJdc1*;&kRZScSn$q#OCAkSgkOQukl# zF9Wjg{75^{x3Hk#q}fKwluQh$8+?#i@FR8l8><-GHpD^wkss;ICz?$QKTiV+W!y?*k(+4DQuHgn{S_%hUrVtP5@{cfbzEt}u{0W9r>TRpMRt z`=j37|br%J?Vy>lpgS0 zdn3+4KbW-vSST8dHKjeV*|RV1o*$_4h^3RjCLrVM>=K3FK@KdJe7j`}mSx&T`a5q6 zr@Y~}TS}0?a`bnt@SVVS8+?0F{@d@iwB6z>e(#7U!8hN1x24UN1QK}CYD=koQo5y; zeUjMH#wNTi*z_ih-m;U*F@YWN{5RjKaq8ZmvV+`WcJz0a8?a^BA^Fxn%Mf#R06!Lj z?BGEQcJ#Li@S?vB|6{y-=TrmQRyQ#-KUR(YZpUK9eCrewGXhz+l!;o9LA3}6R10&= z&uayZXBTMwH)udRB2aZ3tR0piuu=(D1U)n)v=7vw!eIl}A|^7(Ap{}^pzd~%Qiykr zK>@+ABd!xDH2@#3De>nJe0t!+d;evOYW;sw_B45!pTV2|ybZ<{wzRO?spJiL>wJ0BpZ+lS5zW0O4!m&C zgQdVu==*&2a@M|+kna!l@q%d&&ZbAsga|iQJ-lHskM|pDzH*tw$f^0r!z&4)8+thy zSk~m;=VFw`+o3UBSeE!ILeCk0Mf0 zji>;C0En6pxpw6eCMtv#RiG*?;w9M4TH}ipeMsWR>d03yWD$%Sgf)0E zBRMP7Evv^MXbdhItTB@93F8JBNGSLi?P<3tzk#aYs~rQb;^?&=n9uRml6b$PPp!ca z2k*VJ8tNC-1IW^1?F1iU-fBJy5asSSN*Ei6~>cbw< z_EoRF^3q>dJohx|Qa%Hcti=of4#OtO9?`a!Uwr<#XP$iGu}2;TF2eA=;@WRmeEq&)z>8CQq7p`>nT(=gtbXSOTce=iN6uS|%{_?wd8^ zo~d_Fx)U%racAmfY$L3~__a&)`5a_LOCAJY_syDl&$KD2yY9Gc!p%1VDl_Uuydba& z76!W{_k1;N%7gb?wjxXJ=JC~jbxytT{PQc!ijso;kYyWZKU|mJ3*FPcSyU_lEr_)f z=n4h%kyBi~<~u^+B)Nj};)4%1u%WX9>W%qNHbO*1{8Dh}_zHMWIk<^xrOUM4S>&!c15J}G>4j$CP9voZ7eB9oE9TV`1$ z))=^ob+ty5vF4q(&|c#DutqT}MpnkEVw3R-O@W&v%`lU0%Ng+e2KA`oDySkV>R}eUv9P*ha9+HWwW)IN^5cZEjNv~ z*5bv#I&1OeK6?!v2x|cgH1po*Zm@Ox1hE!)yDVOA`b*X#?%sRBmB7&LdPBkA2-%Wc z!yABC{Loy)o`rQcLUwEMO}rM~2D-b)=WM&S@motFHpKRFH*Oa^4YMx09)?7W%!hdy zUpRKN2gl9^2Mjw1TVrONn;|1B8{{@%pdGOzy7)RR%mmB;J%oY}!REAuV;P2Pm=sRH zQSU$Qr|em@Iz`4p>bKV9O>3!5hiX z{&B{R7Aqk~cysZaHot0pOlTu-eSxCzT_Q){I-_Wgc)Ki5qY&q7P3W=2{#;^j$D~}D zHR}rzl~9v!uIWS{mUOHG*9`>7!kXCqt@vYUT7E~pRkb%JCj%gHHqn^1tZi`)5ZGba zD$&PR`{+a2l5eJQ>Xq5Lf5B+>p~tfkdRUba7&XgRi~n}(76fv>oKZ9y>Zzd7yU!_o z2$GcWwMjRYP>4+{%s%I)d#6v0A7xsJC?w9tH%%+Q`pW_#lM_qR%JwA?ay`PSrJ3cI z;>>dT#4%vVUV|Z;HU9XIY`Q98h-Q`uRW!5g6b$*o=M9E*uDn3TJ`nlEkN*6J`!gO* z+g6b6PyghHfe2H}2Oib52tL}?+gALyFMj?{!9D3`+wQXF7B3{iN4=lt!}f>ysP_aP z3 zvZf+MQR+B3B6aXkPcF1$)(1x04tJ)2JdzyibS1d^(14#$=lyv|B_;W-d^;D5AUV+I2UGvGWogTdBvEfwl%a1ZK9k@-MLv$(b;^9OA=1HottLDO!Ztc+nST}lRT_Q z()q4#HDUXvo1U3LbIH$i@P$v$Rc0%5&G|XGZc)N=Ix;n#PIqRM1NVAn!88V8S zoIE>)+tcJ!N(gIws}v~P!h~1P5smyDy-eo(Y{%4|2#e@EUS5RA&L;ho2`RPJoOHTH zJ7&%e)7&tZIzLf48wiS>kSm*hN7ra69g=p`B2C~gp{?y%=O)sL^lXP<<9-r+A%->Dg=CrnZxWDQk(Ee_ckoQJHh6&*Wz^Y8jzP z-RUVm)tQ$0+G~i{X);zFvrbbTrQ~Ef%rKtPhB6O9 ze+JQ~AaAoXL^O{r3uklsp<03l$+?rK0{R1|PG_gfoPOfENh3s|EP}1mlQ3C!!cSx8 zlkHPP8IQNgeas_8rHb;2tlzN3IC2CZcb$_bPNpZbQ>bs9N=|2IIw&usXc4Fz8Qq5Y zKs5npv=b*)YaeWIAHCKX_(`fCZ=b-KE1byXT!wFBijUlBe>y$$jx-(4 zaEERRXIqob9Ul+oh$JDHwppT>EwY!4Q7aw$7{EF4?p4*vY{WPH(l*iPhhymLyj5&7u_V#Oicb;Pu| z&=pHi-JqKEcxAkELOy|3e%TQuy>wUmH2363GOHl5CY7B|#!-KeWi@1pyhdeV=jGvc zIN^@&F)GTAWyh;@dvV-)ot-4dq4aPEWd(m^QH_Z{hRM-ztbH6+iEz9_Z@slBoOoNN zI^mpL^9~)Z9!@E@MOW4Misekl(-RO>c<&+a5DsNlbatdld8IYN@ocG%4<8AVA#?fOY+s798h(+{ zYZ28h>Cw@>l+w~8SZ^;<3zCg!@58+@-Pb`bE!*EB|AB*fw3$EDqMe5hhr`Vy&h0^0 zBkZZ{%_$k5KzvfGWp5BabJ^~6PlxgXHT(Uc>`8hcJD4E`;v9aFDH?I5xEbDviBvT9 zqI-vV_U)Iv8=Vf;rLv_A%dS#NjIHAtcjq`H;`>Pd6Z#)b^|o2*pmVrhO3JOho2v5N z)jjFniX_zJCs~$_g%K6$kS*Vp@AiA5>Kn2aYK@vrX6qZ$bJd;ct`2$>mE9R7nT;wE zp>w!xrbv6Byb*Syqk&+X)fmvnK)ga?b$&11OZS>dSsJB?hJQ%DBekl-F29@ZB)eN= zmY1bv5A>`_&j|Ry;@3giBiWwCYBE}4Rirc-`z4G4UkN1o9JH;y-DK>nhOncvbH~oi zYDuhvmb=A3D{c<^^6*i$oY{_SXA3jPUit2YJ!tI7nWlmQI<<#w`SwLMSv`%#g ztMt}xz^Dj}3`SkNC`cq2)pbv&H!xIkp|b?4S|F(N7XUX;cfeE_QUI#!mhh9e^ND+a zlk)(E^KAjB)X)=N;Rfbsk|MFwoMa4Wms5^Z?6*xsKhe z3>oS`?*po61@CYzox934VHo|IOF0cIQIw<~1xwPomSsu|zX@lp8ErY?ftbV3w&gNz zs4PUlX240fssm~YGg*WqC35p~IVI70Mb~UQ*5#@Joa9_)jmp4Xd^u)_Dkup|I{g#AK^{rY|J0IKd;+|9kg zq{`%9Y1s!`=r2MT!O0Sp0;`8xK z;ULwG94L}o6@UaCI+IQe(S0jN=0R=Nv3y3*V**U4uK{|Hk&=>B0xUy`G@PwW3al>D zACOhbx?ZKqA;X;SL`Xz?oI}Ahk;JCf;}S2lD6N#}1QB)&!BnZ=GFN{HwuFf6ngTrJ z%w-wJ(w(1JwB?o6J4Nx+O0R;;DrdQTd^~4?zaBGywGx97DKG+rsXnOF;4*hJd`L`! z({PheVtzV7EkKF^Ot<}IQh+IpSJ8nIE(wy$5}q_WI>8vN?0_D*;QR4_<`u}q;8;q( z7ARJdS)d=35nO7xBtt252_~fmNCNU^NG@dHJ;5FpOu-%?i3AN;?^*DHNr;pQTM7Gs z%f^K@_|3S@aF1O3K`4Rc+hka^&`V38t(&BNmGEfUJ-$R)OqndHTA)J&K(XIB7zFvQ z@e{Fi!dT87t{e_Wu3FQCCypMg&<~2`fiRVD4QL4f5>Np!1&4^5x<`Rdf(o8?2~>7v zD4`&OD*<@bT*4~Wfd~&X8v)Zo&L$bkThhXGfm45`7Q9LSc8w~mhknbHH{U|Yy4 z15_-kRKbeaJ&Ypwm>m~p0$qdyIci_DSF&idHy9L4jCvn7P-X|V><^N$5F7~y zo6_a78ibhy9~T6)G+-4vc{QRYaDi6u9MuKGFIJJX#b|q!ZR6HxcueCuhKtfzOL`!s zVGGn^C^C!a$R7!0)MASUSws=l5=9v}5|+HGhM)-n;sG78lnc^y_oDzI!39Gq3t$d| z9g;e0NkfAEdm91gcJImdgg#l~>?LIfbIa9`Hqp`+h)G`a`Q9 z^ZP8@s&X`8yx!aH+ZFs#t{h+b>Nl4&4?(%qXk1lFhTG-PlE*n zhOU_u6QC!;9%GWu&r8$rRxYXI=H{~!@Q6&h6%1u_VSWU7QBp`SAfk{`%b!NkoCtw} zp^Y#%1lB@JhiPYtJ`%qn_DRSoKv@a$z$=N$@DNCXPB|#WpYIs^WBgG%Q{hqyF9Io4 zoiFi?08k=QCd}mEn+ifaT=oWV+QKX%J^Zw2AQR^fL3k}n6 zx`5eDY!RRSb23LDB3zLftfA3@HEEwX0@Wmw-6?WsXh+fpR(B(gGWe8gA6!L*6LCu# zmwBz+e;tvCu{6{W${MbhszI}SWv-<;jdVnb50a_sbW;cdW=EZ%5|>YifH=!hJ{Nm3dWIh4g1tNkU|^Ng_9LgJ!cZu{}%W}-3*ZyieM8nyK?c*PhGX8pZfSqj2a5oOli8) zG4W0mDO4kRB_ftS@iYWnQI|49KVnlN)g%xCZy^wp(hxYX6hxJs{i{h4JQ0Qn8VK4f z2pya<)RM=%!Z&Xl=9GaWB_#eLEg6;S$wjjBm(a}!+N9o2>xGFBN)qAG779tm-w^;2 zO%l1GiZMw>=cRB$XT%Bx$Qsi#QXOG@=tSCw9cup)`N!+U*c~NSM^aKHqIpsnp^~bC zJA*ocuVJ12fdGhBXCWf>Tl$*@a!T`8BPL2qE+~z3jW0`XQL>CwVdQ~j_y)My*%Ne*^cdUF)2SkD7RN5)0yG$kWd zLiHfWe&AqaaT16Wqg)cp8Bu9syb@qXJOW@RfdDaNk(BI^-61-OPNqn6VGS4^6XM+0 zgnJQT6K>p8(n%GDYvCA>q|bdUh^G-%16Lx_YN^@jk?Vq9f-jI7thFA(rUWiQF$p50 z6xq0Ngg2U2?=)tLTuEDPNJ?0Q^$y8^eJ&^kzd$R5lI)3?3sosmIH{yxF_G*j?8uBE zK~GcgFX^U$Y^}t!jB5!I$fO6Z3QwsPZbbgd1@J-z`6&~v%Jx;nWU0FeCVo(d3gi5E(@ zBa#Axl<&0uBqg{~R0lv<#6tmKlkY%AUwv1o1^xt?g7j2NF39kY-`)Z^2?C`?G5K38 z70?!A11eHgPv{#&?-cZ|n-S4zSejQ`6uQmx%_G4%GhDCv0y1GwDqlx>r?7e5=lQA< zp{#^2E;q1SnlCR`Be8X#&aAc=qPU?aZiPf*yc=loKNe)V6w83CJ!J-a`5};XtK~8vx6r&9Rd%b6 zb*#S{$q>z&%1Sa_b;;n__7=BA+bxTh_Npt|ZN*r|;6{V3#D?nVdt)!vBOX_s5aVh# z6RW&rvL>$(y+{(vskfIA%a!UFkCwf*f|4JV2B zIL79PwlCZWulZi8I%pHaj|!`Kk!$5oW3)VYlK*${V9Q10Ki_(;u|v;0|Ki^j^#Y&f z)xWWIYwoInt^56Tg}_;3I2XZR21v>94*V1Mg6KqF<@@8&nPmuuzE_xZeNKm7)> zVtoHu=Wn~`*7M(g)A_Wib3b`(thV;s4we2f-RO$o->Py#yKmdtHmqH=?0fca<=^w> ztfsB$<(0Oadi+}%S5}a}?|s82X#een@32Ex#RskmSa!bt=WlBNsJ5)iZz6gwcs4Y9 zc1cp3+;RQa7yjI~(|_~7`{)7@GcHmRuSSncoPXWF(fulN3XAf@ee)X$JI(R9=oji~ zEvi%g)j`D6uMQ%nUTi;e>C&@>S?B25DGczIf zm#^cY__euUL1O=Gw!P>tCeOU1+?Stw?)m4xEH{@JvC=kYilJtEBXqpJ0r407(+Lp; zF8NCf&t863H>ky;VpY0rDS%yP%ct#^EnBas1^!Y?HK@&ESM}9BU)zfc7wNA%VsO%~ zcK_;zLB!NS#8e267*Yu`)OH5y`(|wo;M?pN(n|YE2N6^CZLcU_1ual)4K^qcewX*! zAYv-J_59vJ#8d#CTxaoi@8iMil05;MML$_xPUL6R2ZVAblJ8j`5JsoTMLB>uusqc3 z*Fu@a+~9GamYxZ*EN^U@1o7{YWKC*lh<2sNC_t) zlYg_@cTy7yO}>-5=C{A~Erb_eNnTl$bk^%{_%{X-Q(yIih^d2!sZ8(-CFo)&rn%XG z(XLzYP(s23(jsCM1nj(UMcB(QmoS|LWD=;;M&5|Hlsz$k$)`naFr56K>~PSw4DDmp zeiA`O%|XP} zLB!O!rIS4rgNUgffiXNpAl>fae}(`0lDRwez3TVcD2^jL!_@rNNXZGp;zbPWp4d)gulTFnp}zGNTg5&$aCBP?Vp1g3U!3kdw{H_<8~lW7!2r4_@G za>$R&UZA1)qzWps4T~dSHS6}n5`PbhT zB$Rls3HteOn6gt;)aZO?5Ha=Tub4d0~a*g~cl`LPl{*`zx=!LV3w+38)(& z?~<2(;LgI@MY`xY_@Wp53;v3K(ZAGHtCCl21QQ!U=WyY77cV|@DY+DuxF~-mA-8{7 zT}WR2fiV3W&cP)8HWAD(J|mbQ+>#h|)fF?Q(qn#4em({`H;9<}OgA!ugNUi-T*GE! zF{jD7wvJE%}kgNUixWs1wrQgGQp#MD8= z)OU;4^#3Yusx~_eBBm|{G#x}t9YjnWL`-F?(;p8ardqh-LB!NS#MD8=RDx;xKS>4= zQ@`-VFWS~aT<8W7QwI@K6Ltpoa8>&>AiDeiSH#rMvdLHvZI#ad=^y<5r~iP1_jIqc z%Gb}k?UiOA${&B*o8{4G`L9RHKI#AA{HFeX>UiGY&iB)6$DF@wv-2B2K|TVO{60P* zF?#9<{voSyPP)Tlv1~$}bz^TMzKZvvu(}D=)(7xnd=Q7mhu9sxg}u=2&y0=|TlTgX zM!}ChsL&mw>}^CaX%ok}j+0S$FD{Y89Q)CY94)sTDNaBudaH<%qulE_UTrzn;zhaE zj_%;-eU|r00<0|Wt=F+1#X)je?;gvsjH6AKV+EVkM|!^K{uc|YL(GJn=V{UX9M4s8 z%F|rY7nNUvP9wdcelSKh^AGoy#o&v&u)=~Z-iv}NQ563xk$gsacPOsndJfhquHwqk zq?YrfrV@rntF^$B^+osdquJ>4niaRPX#e5pXl-R}q_?qHO}e32LwZ-Smb6yXNbfAx zlipF>O?rEA59!Kc6Y28e0n(A;LDHe(A=12fgfuN4BTb4Al6H&Q<4aGn;!%#P#lxiW zwiU(wwZXv3OXDXV*!s-_Tfcc=>o*N-eP!JSmXv`dWnf7eSW*U-lz}B>U`ZKRQU;ck z5h7(^Nf}sD29}h8CG8gV$CsWkupBe6r13TewmulxpK4$mHxF#%=7DY8G_Z}84I5Ze z29}h8C1qeq8CX&VmXv`dWnf7eSW-ralz}B>U`ZKRQU;c^TQnYDdcweR%)pYy+Zfo! zQ>&PclPf3-ma(!jq5=IRv9dO!uC0gSWj##91I5gG1V8jgnW7(KKGs7@+&Ggz#)R8u zB6N>%U?FDw=))W;l3i!?N!-_0^fEhBMV@aRvf3+pRVH|)-6!1x9CT|;cbho~%zxdF z*)4hPAx;d{bo;W}CejtPdr5Dr-A#H&O>_R*nr8d=)z*-%udOECSX)JUUu`+*1GQn& z%{5}A_a3ehi>&u(4X5}r-BMF%sE2Af>HBL#q<^0bR__~(d8Kc#x*4o)2CJLF>SnOI z8LVywtDC{O7;j5K zfqPkA<7&OOxQpYsimxy3fB@kUmlL zAKl*N_-Kyq}9Ji-+RVk>U{!hKtAI)4X^*9)#jU93;hu?I~Wy+1N*E@Gthd zW4))sKkAv0S?c1-iIF*uD=J3j7$cKnWKxVwijhe%GASk|#l)mP&Sw9oYySXk$|@5V zEo{nhT+Fa3$Jmq~ifeLo;0En=$R8)t^+OY4y55kZk_$ z=}%|IA9dH?ee*WVytZs^v?X*y!^~?->$--Sw_)aOn0ajxUfD47+TuLiF!MG_^EP-< zx5^iFt9((n$`^I3d{Hy8#20mIxIE-VT^{kGwroGjqW?GN|IS-o(+NKxD c #D6D6D6", +", c #D7D7D7", +"' c #CDCECE", +") c #CFCECE", +"! c #D0CFCF", +"~ c #D3D3D2", +"{ c #D3D3D4", +"] c #D5D4D5", +"^ c #D6D7D6", +"/ c #D8D8D8", +"( c #D8D8D9", +"_ c #D9D9DA", +": c #CCCCCB", +"< c #CCCCCC", +"[ c #CECECD", +"} c #CECECE", +"| c #CFCFCF", +"1 c #D1D2D2", +"2 c #D5D4D4", +"3 c #D8D9D9", +"4 c #DAD9DA", +"5 c #DADBDB", +"6 c #DBDCDB", +"7 c #CACACA", +"8 c #CACBCB", +"9 c #CBCBCB", +"0 c #CCCDCD", +"a c #CECDCD", +"b c #D2D2D1", +"c c #D2D3D3", +"d c #D4D3D3", +"e c #D9D9D8", +"f c #D9D9D9", +"g c #DADBDA", +"h c #DBDCDC", +"i c #DCDCDC", +"j c #DDDDDD", +"k c #DEDEDE", +"l c #C7C8C8", +"m c #C9C9C9", +"n c #CAC9CA", +"o c #CBCBCC", +"p c #CCCDCC", +"q c #CDCDCD", +"r c #D0D1D1", +"s c #D1D2D1", +"t c #D3D2D2", +"u c #D4D4D5", +"v c #D5D5D6", +"w c #D6D7D7", +"x c #D8D7D8", +"y c #D9D8D9", +"z c #DADAD9", +"A c #DBDADA", +"B c #DBDBDC", +"C c #DDDCDD", +"D c #DDDEDE", +"E c #DEDFDE", +"F c #DFE0E0", +"G c #E0E0E1", +"H c #C6C6C6", +"I c #C7C7C7", +"J c #C8C8C7", +"K c #C9C9C8", +"L c #CACAC9", +"M c #CBCACB", +"N c #D0CFD0", +"O c #D1D0D1", +"P c #D1D1D2", +"Q c #D4D4D4", +"R c #D6D5D6", +"S c #D7D6D7", +"T c #D7D8D8", +"U c #DAD9D9", +"V c #DADADA", +"W c #DBDBDB", +"X c #DCDBDC", +"Y c #DDDDDC", +"Z c #DFDEDF", +"` c #E0DFDF", +" . c #E0E0E0", +".. c #E1E1E1", +"+. c #E2E2E2", +"@. c #C5C4C4", +"#. c #C5C5C5", +"$. c #C8C8C8", +"%. c #C9C8C8", +"&. c #D5D5D4", +"*. c #D8D7D7", +"=. c #D9D8D8", +"-. c #DCDDDD", +";. c #DEDDDD", +">. c #E3E4E3", +",. c #E5E4E4", +"'. c #C4C4C4", +"). c #C6C7C6", +"!. c #C7C8C7", +"~. c #C8C8C9", +"{. c #CACACB", +"]. c #CCCBCB", +"^. c #D0D0D1", +"/. c #D5D6D6", +"(. c #D7D7D6", +"_. c #DFDFDF", +":. c #E1E2E2", +"<. c #E3E3E3", +"[. c #E4E3E4", +"}. c #E6E5E5", +"|. c #E6E6E6", +"1. c #E6E7E7", +"2. c #C4C5C5", +"3. c #C6C6C7", +"4. c #CFD0D0", +"5. c #D1D0D0", +"6. c #D6D5D5", +"7. c #DADADB", +"8. c #DCDDDC", +"9. c #DDDDDE", +"0. c #DEDFDF", +"a. c #E1E1E2", +"b. c #E3E2E2", +"c. c #E4E4E4", +"d. c #E5E5E5", +"e. c #E8E8E7", +"f. c #E9E8E9", +"g. c #EAE9EA", +"h. c #C5C5C4", +"i. c #C6C6C5", +"j. c #C7C7C6", +"k. c #CBCACA", +"l. c #CDCDCC", +"m. c #CECFCF", +"n. c #DBDADB", +"o. c #E0E0DF", +"p. c #E1E1E0", +"q. c #E1E2E1", +"r. c #E3E3E4", +"s. c #E4E5E5", +"t. c #E7E6E7", +"u. c #E7E7E8", +"v. c #E9E9E8", +"w. c #E9EAE9", +"x. c #EAEAEA", +"y. c #EBEBEA", +"z. c #C4C5C4", +"A. c #C6C5C5", +"B. c #C6C7C7", +"C. c #CCCCCD", +"D. c #CECECF", +"E. c #D9DAD9", +"F. c #DBDBDA", +"G. c #DEDEDD", +"H. c #E0DFE0", +"I. c #E0E1E0", +"J. c #E6E5E6", +"K. c #E7E7E6", +"L. c #E7E8E7", +"M. c #E8E8E9", +"N. c #E9E9E9", +"O. c #ECECEC", +"P. c #ECEDED", +"Q. c #EDEDEE", +"R. c #010101", +"S. c #C5C4C5", +"T. c #CBCCCB", +"U. c #CDCCCC", +"V. c #CECFCE", +"W. c #CFCFCE", +"X. c #CFCFD0", +"Y. c #D7D8D7", +"Z. c #DEDDDE", +"`. c #E1E0E0", +" + c #E5E6E6", +".+ c #EBEBEB", +"++ c #ECEBEC", +"@+ c #EDEDED", +"#+ c #EEEEEE", +"$+ c #EFEFEF", +"%+ c #F0F0F0", +"&+ c #C4C4C5", +"*+ c #CFCECF", +"=+ c #D2D1D1", +"-+ c #D6D6D5", +";+ c #D8D9D8", +">+ c #DDDEDD", +",+ c #DFDEDE", +"'+ c #E2E3E3", +")+ c #E7E7E7", +"!+ c #E8E8E8", +"~+ c #EBECEC", +"{+ c #ECEDEC", +"]+ c #EFEFF0", +"^+ c #F1F0F1", +"/+ c #F1F1F1", +"(+ c #C7C6C6", +"_+ c #C9C8C9", +":+ c #C9CAC9", +"<+ c #CACBCA", +"[+ c #D2D2D3", +"}+ c #D4D5D5", +"|+ c #DCDCDB", +"1+ c #E3E3E2", +"2+ c #E4E3E3", +"3+ c #E4E4E5", +"4+ c #E5E5E6", +"5+ c #EAEAE9", +"6+ c #ECEBEB", +"7+ c #F0F0EF", +"8+ c #F0F0F1", +"9+ c #C8C7C8", +"0+ c #C8C9C9", +"a+ c #CBCBCA", +"b+ c #CCCBCC", +"c+ c #D7D6D6", +"d+ c #DDDCDC", +"e+ c #E2E2E1", +"f+ c #E2E3E2", +"g+ c #E3E4E4", +"h+ c #E8E7E8", +"i+ c #E9E8E8", +"j+ c #EAE9E9", +"k+ c #EDECEC", +"l+ c #EEEEED", +"m+ c #EFEEEF", +"n+ c #EFF0F0", +"o+ c #F1F0F0", +"p+ c #C5C6C6", +"q+ c #C7C6C7", +"r+ c #D0D0CF", +"s+ c #D4D5D4", +"t+ c #E1E0E1", +"u+ c #E8E9E9", +"v+ c #EDECED", +"w+ c #EEEDED", +"x+ c #EEEFEF", +"y+ c #F0EFF0", +"z+ c #F0F1F0", +"A+ c #D7D7D8", +"B+ c #C8C7C7", +"C+ c #C9C9CA", +"D+ c #D2D1D2", +"E+ c #D9DADA", +"F+ c #E2E1E1", +"G+ c #E9E9EA", +"H+ c #EAEBEB", +"I+ c #D8D8D7", +"J+ c #CBCCCC", +"K+ c #CDCCCD", +"L+ c #D6D6D7", +"M+ c #E6E6E5", +"N+ c #E7E6E6", +"O+ c #E8E7E7", +"P+ c #EFEEEE", +"Q+ c #CDCECD", +"R+ c #D1D1D0", +"S+ c #D2D3D2", +"T+ c #DFE0DF", +"U+ c #E3E2E3", +"V+ c #E4E5E4", +"W+ c #E5E6E5", +"X+ c #ECECED", +"Y+ c #D4D3D4", +"Z+ c #CECDCE", +"`+ c #E6E6E7", +" @ c #EBEAEB", +".@ c #ECECEB", +"+@ c #F0F1F1", +"@@ c #DCDCDD", +"#@ c #EBEAEA", +"$@ c #F0EFEF", +"%@ c #D3D4D3", +"&@ c #E6E7E6", +"*@ c #EEEDEE", +"=@ c #ADADAD", +"-@ c #565656", +";@ c #DCDBDB", +">@ c #DFDFE0", +",@ c #E7E8E8", +"'@ c #E8E9E8", +")@ c #EDEDEC", +"!@ c #EBEBEC", +"~@ c #EEEFEE", +"{@ c #B7B6B7", +"]@ c #E5E4E5", +"^@ c #EDEEED", +"/@ c #B6B6B6", +"(@ c #B6B7B7", +"_@ c #B7B7B6", +":@ c #B7B6B6", +"<@ c #E5E5E4", +"[@ c #B5B6B5", +"}@ c #B5B6B6", +"|@ c #B5B5B5", +"1@ c #B6B5B5", +"2@ c #B6B5B6", +"3@ c #E2E1E2", +"4@ c #E4E4E3", +"5@ c #B4B4B4", +"6@ c #B4B5B5", +"7@ c #B5B5B4", +"8@ c #B6B6B5", +"9@ c #E2E2E3", +"0@ c #B3B4B4", +"a@ c #B4B4B5", +"b@ c #B4B5B4", +"c@ c #B5B4B4", +"d@ c #B3B3B3", +"e@ c #B3B3B4", +"f@ c #B4B3B3", +"g@ c #B4B4B3", +"h@ c #B5B4B5", +"i@ c #D0D1D0", +"j@ c #B3B3B2", +"k@ c #B3B2B3", +"l@ c #B4B3B4", +"m@ c #90B9D9", +"n@ c #91BAD9", +"o@ c #C6C5C6", +"p@ c #B1B2B2", +"q@ c #B2B2B2", +"r@ c #B2B3B2", +"s@ c #B2B3B3", +"t@ c #8FB7D8", +"u@ c #8EB7D7", +"v@ c #8FB8D8", +"w@ c #90B8D8", +"x@ c #91BBD9", +"y@ c #91BCDA", +"z@ c #C2C2C2", +"A@ c #C3C4C3", +"B@ c #C3C4C4", +"C@ c #C8C9C8", +"D@ c #CDCDCE", +"E@ c #B1B1B1", +"F@ c #B1B2B1", +"G@ c #B2B1B2", +"H@ c #B2B2B3", +"I@ c #B3B2B2", +"J@ c #8CB4D6", +"K@ c #8DB4D6", +"L@ c #8DB5D7", +"M@ c #8EB6D7", +"N@ c #8EB7D8", +"O@ c #8FB7D7", +"P@ c #90B9D8", +"Q@ c #91BBDA", +"R@ c #92BCD9", +"S@ c #92BCDA", +"T@ c #C1C1C0", +"U@ c #C1C1C1", +"V@ c #C2C2C1", +"W@ c #C3C3C2", +"X@ c #C3C3C3", +"Y@ c #C3C3C4", +"Z@ c #CAC9C9", +"`@ c #B1B0B0", +" # c #B2B2B1", +".# c #8BB2D5", +"+# c #8BB2D6", +"@# c #8CB3D6", +"## c #8CB3D7", +"$# c #8DB5D6", +"%# c #8EB5D7", +"&# c #8FB8D7", +"*# c #92BBD9", +"=# c #92BBDA", +"-# c #BFC0C0", +";# c #C0C1C0", +"># c #C2C1C1", +",# c #C3C2C2", +"'# c #C4C4C3", +")# c #C5C6C5", +"!# c #C5C5C6", +"~# c #B0B0B0", +"{# c #B0B1B0", +"]# c #B1B1B2", +"^# c #B2B1B1", +"/# c #0E3459", +"(# c #0E355A", +"_# c #0F355A", +":# c #0F365A", +"<# c #8AB2D5", +"[# c #8CB3D5", +"}# c #8BB3D6", +"|# c #8FB6D7", +"1# c #8FB9D7", +"2# c #90B9D7", +"3# c #90BAD8", +"4# c #90BBD9", +"5# c #92BDDA", +"6# c #93BEDA", +"7# c #BEBEBE", +"8# c #BEBFBE", +"9# c #BFBFBE", +"0# c #BFBFC0", +"a# c #C0C0BF", +"b# c #C2C3C2", +"c# c #C4C3C3", +"d# c #AFB0B0", +"e# c #AFAFB0", +"f# c #B0AFB0", +"g# c #B0B1B1", +"h# c #B0B0B1", +"i# c #B1B0B1", +"j# c #7A9EC5", +"k# c #799FC5", +"l# c #7A9FC5", +"m# c #7AA0C6", +"n# c #0E345A", +"o# c #0F3559", +"p# c #8BB1D5", +"q# c #8CB4D5", +"r# c #8FB9D8", +"s# c #90BAD7", +"t# c #91BBD8", +"u# c #91BCD9", +"v# c #91BDD9", +"w# c #92BEDA", +"x# c #93BFDA", +"y# c #BDBDBD", +"z# c #BDBEBD", +"A# c #BEBEBD", +"B# c #BEBEBF", +"C# c #BEBFBF", +"D# c #BFBFBF", +"E# c #C0C0C0", +"F# c #C1C0C0", +"G# c #C0C1C1", +"H# c #C3C2C3", +"I# c #C4C3C4", +"J# c #AFAEAF", +"K# c #AFAFAF", +"L# c #B0AFAF", +"M# c #789DC5", +"N# c #789EC5", +"O# c #799EC5", +"P# c #7AA1C5", +"Q# c #7BA1C5", +"R# c #0F3659", +"S# c #10375A", +"T# c #8DB6D6", +"U# c #8EB8D7", +"V# c #92BDD9", +"W# c #143F5B", +"X# c #174A6A", +"Y# c #84B0CB", +"Z# c #85B0CC", +"`# c #BCBCBC", +" $ c #BDBCBC", +".$ c #C0C0C1", +"+$ c #C1C2C1", +"@$ c #C2C3C3", +"#$ c #AEAEAE", +"$$ c #AEAFAF", +"%$ c #AFAFAE", +"&$ c #779BC4", +"*$ c #779CC4", +"=$ c #789CC4", +"-$ c #789DC4", +";$ c #789EC4", +">$ c #799FC4", +",$ c #7AA0C5", +"'$ c #10385A", +")$ c #8DB7D7", +"!$ c #8EB7D6", +"~$ c #90BBD8", +"{$ c #133E5B", +"]$ c #83AEC9", +"^$ c #84AFCA", +"/$ c #85B1CB", +"($ c #85B2CB", +"_$ c #BDBCBD", +":$ c #BEBDBD", +"<$ c #C0BFBF", +"[$ c #C1C1C2", +"}$ c #C9CACA", +"|$ c #AEAEAD", +"1$ c #AEAFAE", +"2$ c #AEAEAF", +"3$ c #7599C3", +"4$ c #7699C3", +"5$ c #7699C2", +"6$ c #769AC3", +"7$ c #779BC3", +"8$ c #789BC4", +"9$ c #799EC4", +"0$ c #79A0C4", +"a$ c #8CB5D5", +"b$ c #8CB5D6", +"c$ c #8DB7D6", +"d$ c #426D8A", +"e$ c #16486A", +"f$ c #7AA5C1", +"g$ c #83ADC9", +"h$ c #84B1CB", +"i$ c #85B1CC", +"j$ c #BCBDBD", +"k$ c #BDBDBC", +"l$ c #BFBEBF", +"m$ c #BFC0BF", +"n$ c #ADADAC", +"o$ c #AEADAD", +"p$ c #ADAEAD", +"q$ c #ADAEAE", +"r$ c #7496C2", +"s$ c #7597C2", +"t$ c #7598C2", +"u$ c #769BC2", +"v$ c #779BC2", +"w$ c #779CC3", +"x$ c #789DC3", +"y$ c #7AA0C4", +"z$ c #7AA1C4", +"A$ c #7AA2C5", +"B$ c #7BA2C5", +"C$ c #10395A", +"D$ c #8EB6D6", +"E$ c #8EB8D6", +"F$ c #133D5A", +"G$ c #81ABC8", +"H$ c #82ACC9", +"I$ c #82ADC9", +"J$ c #82AEC9", +"K$ c #83AFC9", +"L$ c #83B0CA", +"M$ c #BDBEBE", +"N$ c #C1C0C1", +"O$ c #C7C7C8", +"P$ c #ADACAC", +"Q$ c #AFAEAE", +"R$ c #7395C1", +"S$ c #7395C2", +"T$ c #7496C1", +"U$ c #7599C2", +"V$ c #769BC3", +"W$ c #779DC3", +"X$ c #789EC3", +"Y$ c #7AA2C4", +"Z$ c #7BA3C4", +"`$ c #7BA3C5", +" % c #11395A", +".% c #113A5A", +"+% c #123C5A", +"@% c #164A6E", +"#% c #4C7694", +"$% c #80AAC7", +"%% c #80ABC8", +"&% c #81ACC9", +"*% c #81ACC8", +"=% c #81ADC9", +"-% c #83AFCA", +";% c #84B0CA", +">% c #84B1CA", +",% c #86B3CB", +"'% c #87B4CC", +")% c #BFBEBE", +"!% c #ACACAC", +"~% c #ABACAC", +"{% c #ACACAD", +"]% c #7294C0", +"^% c #7194C0", +"/% c #7294C1", +"(% c #7394C1", +"_% c #7396C1", +":% c #7497C2", +"<% c #7498C2", +"[% c #799FC3", +"}% c #7CA3C5", +"|% c #123B5A", +"1% c #88B1D0", +"2% c #7EA8C6", +"3% c #7FA9C6", +"4% c #7FAAC7", +"5% c #81ADC8", +"6% c #85B1CA", +"7% c #86B2CB", +"8% c #86B4CB", +"9% c #87B5CB", +"0% c #BCBCBD", +"a% c #C0BFC0", +"b% c #ABABAB", +"c% c #ACABAC", +"d% c #ABABAC", +"e% c #ACADAC", +"f% c #ACADAD", +"g% c #7193C0", +"h% c #7293C0", +"i% c #7193C1", +"j% c #7293C1", +"k% c #7498C1", +"l% c #789FC4", +"m% c #79A1C3", +"n% c #79A1C4", +"o% c #7BA2C4", +"p% c #7CA4C5", +"q% c #7CA4C4", +"r% c #16496F", +"s% c #7DA7C5", +"t% c #7FAAC6", +"u% c #80ABC7", +"v% c #80ACC7", +"w% c #82AFC9", +"x% c #84B1C9", +"y% c #85B2CA", +"z% c #87B5CC", +"A% c #88B6CC", +"B% c #BDBDBE", +"C% c #C1C2C2", +"D% c #AAABAB", +"E% c #AAAAAA", +"F% c #ABAAAB", +"G% c #ABACAB", +"H% c #ACACAB", +"I% c #7192C0", +"J% c #7292C0", +"K% c #7598C1", +"L% c #7599C1", +"M% c #759AC1", +"N% c #769AC2", +"O% c #779CC2", +"P% c #779DC2", +"Q% c #789DC2", +"R% c #78A0C3", +"S% c #7CA3C4", +"T% c #7AA2C2", +"U% c #7CA5C4", +"V% c #7DA5C4", +"W% c #7DA6C5", +"X% c #7EA8C5", +"Y% c #82ADC8", +"Z% c #83B0C9", +"`% c #85B3CA", +" & c #86B5CB", +".& c #87B6CC", +"+& c #BCBDBC", +"@& c #C2C1C2", +"#& c #C2C2C3", +"$& c #AAA9AA", +"%& c #AAABAA", +"&& c #ABAAAA", +"*& c #7091BF", +"=& c #7092BF", +"-& c #7191C0", +";& c #7192BF", +">& c #7092C0", +",& c #7295C0", +"'& c #7497C1", +")& c #759AC2", +"!& c #769CC2", +"~& c #789FC3", +"{& c #79A0C3", +"]& c #79A2C4", +"^& c #7AA4C3", +"/& c #7BA4C4", +"(& c #7DA8C5", +"_& c #7EA9C6", +":& c #80AAC6", +"<& c #81ADC7", +"[& c #82ADC7", +"}& c #82AEC8", +"|& c #88B7CC", +"1& c #A9A9A9", +"2& c #A9AAAA", +"3& c #A9A9AA", +"4& c #A9AAA9", +"5& c #7090BE", +"6& c #7091BE", +"7& c #7092BE", +"8& c #7191BF", +"9& c #7397C1", +"0& c #7499C1", +"a& c #7AA1C3", +"b& c #7AA2C3", +"c& c #79A2C2", +"d& c #7AA3C3", +"e& c #7BA5C4", +"f& c #80ABC6", +"g& c #81ACC7", +"h& c #81AEC8", +"i& c #82AFC8", +"j& c #83B1CA", +"k& c #85B3CB", +"l& c #85B4CA", +"m& c #87B6CB", +"n& c #88B8CC", +"o& c #A8A8A8", +"p& c #6F90BE", +"q& c #6F91BE", +"r& c #7192BE", +"s& c #7193BF", +"t& c #769BC1", +"u& c #779EC3", +"v& c #789FC2", +"w& c #79A1C2", +"x& c #7AA3C2", +"y& c #7BA4C3", +"z& c #7CA6C5", +"A& c #7DA7C4", +"B& c #7EA7C5", +"C& c #7EA9C5", +"D& c #7EAAC6", +"E& c #7FACC6", +"F& c #81AEC7", +"G& c #82AFC7", +"H& c #83B1C9", +"I& c #84B2C9", +"J& c #84B3C9", +"K& c #86B4CA", +"L& c #89B7CC", +"M& c #89B8CD", +"N& c #A8A8A7", +"O& c #6F90BD", +"P& c #6E90BD", +"Q& c #6E90BE", +"R& c #7293BF", +"S& c #7396C0", +"T& c #7397C0", +"U& c #7498C0", +"V& c #759BC1", +"W& c #769CC1", +"X& c #779EC2", +"Y& c #789EC2", +"Z& c #78A0C1", +"`& c #78A1C2", +" * c #7BA6C3", +".* c #7BA6C4", +"+* c #7CA6C4", +"@* c #7FABC6", +"#* c #82AEC7", +"$* c #83AFC8", +"%* c #83B0C8", +"&* c #88B7CB", +"** c #89B9CC", +"=* c #89BACD", +"-* c #6E8FBD", +";* c #6F91BD", +">* c #7093BF", +",* c #7194BF", +"'* c #7294BF", +")* c #7395C0", +"!* c #7398C0", +"~* c #779FC1", +"{* c #77A0C1", +"]* c #78A1C1", +"^* c #7AA4C2", +"/* c #7CA7C4", +"(* c #7DA8C4", +"_* c #7DA9C5", +":* c #7FAAC5", +"<* c #80ACC6", +"[* c #80ADC7", +"}* c #84B1C8", +"|* c #88B8CB", +"1* c #89BACC", +"2* c #BEBDBE", +"3* c #12285A", +"4* c #768CBE", +"5* c #768DBE", +"6* c #6E91BD", +"7* c #7193BE", +"8* c #7295BF", +"9* c #7396BF", +"0* c #7398BF", +"a* c #7499C0", +"b* c #749AC1", +"c* c #779DC1", +"d* c #789FC1", +"e* c #779EC0", +"f* c #769EC0", +"g* c #769FC0", +"h* c #77A0C0", +"i* c #79A2C1", +"j* c #79A3C2", +"k* c #7BA4C2", +"l* c #7CA7C3", +"m* c #7EAAC5", +"n* c #80ADC6", +"o* c #82B0C7", +"p* c #85B2C9", +"q* c #85B3C9", +"r* c #85B4C9", +"s* c #86B5CA", +"t* c #87B6CA", +"u* c #88B9CC", +"v* c #8AB9CC", +"w* c #8ABACC", +"x* c #8BBBCC", +"y* c #758BBE", +"z* c #758CBE", +"A* c #768CBF", +"B* c #6E91BE", +"C* c #7093BE", +"D* c #7397BF", +"E* c #7497BF", +"F* c #749AC0", +"G* c #759AC0", +"H* c #769BC0", +"I* c #769CC0", +"J* c #779EC1", +"K* c #769DC0", +"L* c #759DBF", +"M* c #769DBE", +"N* c #77A1C0", +"O* c #7AA5C2", +"P* c #7DA7C3", +"Q* c #7EA9C4", +"R* c #7EAAC4", +"S* c #7FABC5", +"T* c #81ADC6", +"U* c #81AFC7", +"V* c #82B0C8", +"W* c #83B1C8", +"X* c #84B2C8", +"Y* c #86B6CB", +"Z* c #87B7CA", +"`* c #87B7CB", +" = c #84AFCB", +".= c #143F5A", +"+= c #12275A", +"@= c #758BBD", +"#= c #768BBE", +"$= c #6E8FBC", +"%= c #6E8EBD", +"&= c #7296BF", +"*= c #7297BF", +"== c #779CC1", +"-= c #749BBE", +";= c #749CBF", +">= c #759EBE", +",= c #769FBF", +"'= c #76A0C0", +")= c #779FC0", +"!= c #7BA5C3", +"~= c #7CA6C3", +"{= c #7CA8C4", +"]= c #7DA9C3", +"^= c #7FAAC4", +"/= c #81AFC6", +"(= c #82B1C7", +"_= c #85B5C9", +":= c #86B6CA", +"<= c #82AECA", +"[= c #758ABD", +"}= c #748ABD", +"|= c #758CBD", +"1= c #6D8FBC", +"2= c #759CC1", +"3= c #769DC1", +"4= c #759BBF", +"5= c #739ABE", +"6= c #759DBE", +"7= c #769EBE", +"8= c #769EBF", +"9= c #779FBF", +"0= c #78A1C0", +"a= c #78A2C1", +"b= c #79A2C0", +"c= c #7AA3C1", +"d= c #7CA8C3", +"e= c #7DA9C4", +"f= c #82B0C6", +"g= c #83B2C8", +"h= c #84B3C8", +"i= c #143E5B", +"j= c #11265A", +"k= c #7489BC", +"l= c #748ABC", +"m= c #758ABC", +"n= c #6D8EBC", +"o= c #6E8EBC", +"p= c #6D8FBD", +"q= c #6F8FBD", +"r= c #7092BD", +"s= c #7294BE", +"t= c #7194BE", +"u= c #7295BE", +"v= c #7196BF", +"w= c #759BC0", +"x= c #749ABE", +"y= c #7399BC", +"z= c #729ABD", +"A= c #739ABD", +"B= c #749CBD", +"C= c #769DBF", +"D= c #779EBF", +"E= c #78A2C0", +"F= c #79A3C1", +"G= c #7AA4C1", +"H= c #7BA6C2", +"I= c #7CA9C4", +"J= c #7EABC4", +"K= c #7FACC4", +"L= c #80ADC5", +"M= c #80AEC6", +"N= c #81AEC6", +"O= c #83B1C7", +"P= c #7EA9C7", +"Q= c #7FAAC8", +"R= c #80AAC8", +"S= c #7388BC", +"T= c #7488BC", +"U= c #7389BC", +"V= c #7489BD", +"W= c #6E8EBB", +"X= c #6D8EBD", +"Y= c #7195BE", +"Z= c #7499BF", +"`= c #749ABF", +" - c #749BC0", +".- c #7198BB", +"+- c #7298BC", +"@- c #7299BC", +"#- c #729ABC", +"$- c #739BBD", +"%- c #749BBD", +"&- c #749DBE", +"*- c #76A0BF", +"=- c #77A2C0", +"-- c #78A3C1", +";- c #79A4C1", +">- c #7CA8C2", +",- c #7DAAC4", +"'- c #7FACC5", +")- c #7DA7C6", +"!- c #7FA9C7", +"~- c #133E5A", +"{- c #7387BC", +"]- c #6F92BD", +"^- c #7094BE", +"/- c #7296BE", +"(- c #7399BD", +"_- c #0E3559", +":- c #7096BB", +"<- c #7197BB", +"[- c #7199BB", +"}- c #739BBC", +"|- c #749CBE", +"1- c #749EBE", +"2- c #769FBE", +"3- c #77A0BF", +"4- c #77A1BF", +"5- c #78A3C0", +"6- c #79A4C0", +"7- c #7AA6C2", +"8- c #7BA7C2", +"9- c #7DA8C3", +"0- c #7EACC5", +"a- c #7CA5C5", +"b- c #10255A", +"c- c #7286BB", +"d- c #7287BC", +"e- c #6D8EBB", +"f- c #7093BD", +"g- c #7094BD", +"h- c #7195BF", +"i- c #7399BF", +"j- c #739ABF", +"k- c #7398BE", +"l- c #6F95BA", +"m- c #7096BA", +"n- c #7097BB", +"o- c #739ABC", +"p- c #739CBD", +"q- c #759EBF", +"r- c #78A2BF", +"s- c #7CA7C2", +"t- c #10245A", +"u- c #7185BB", +"v- c #7286BC", +"w- c #7387BB", +"x- c #7487BC", +"y- c #6E90BC", +"z- c #6F93BE", +"A- c #7196BE", +"B- c #7297BE", +"C- c #7298BF", +"D- c #7297BD", +"E- c #6E94BA", +"F- c #6F95B9", +"G- c #6F96BA", +"H- c #7097BA", +"I- c #729ABB", +"J- c #749DBD", +"K- c #77A0BE", +"L- c #78A4C0", +"M- c #7AA5C0", +"N- c #7CA7C5", +"O- c #7185BA", +"P- c #7286BA", +"Q- c #7285BB", +"R- c #7386BB", +"S- c #7288BC", +"T- c #7589BD", +"U- c #6E91BC", +"V- c #6F91BC", +"W- c #6E92BC", +"X- c #6F93BD", +"Y- c #7194BD", +"Z- c #7195BD", +"`- c #7298BE", +" ; c #7297BC", +".; c #6D93B8", +"+; c #6E94B8", +"@; c #6E95B9", +"#; c #7096B9", +"$; c #739CBC", +"%; c #76A0BE", +"&; c #78A1BF", +"*; c #79A1C1", +"=; c #79A4C2", +"-; c #7BA3C3", +";; c #7084BA", +">; c #7184BB", +",; c #7085BB", +"'; c #7186BB", +"); c #7287BB", +"!; c #7388BB", +"~; c #6C8EBB", +"{; c #6D8FBB", +"]; c #6F92BC", +"^; c #7095BD", +"/; c #7196BD", +"(; c #7195BC", +"_; c #0E3359", +":; c #6C92B7", +"<; c #6D94B8", +"[; c #6F96B9", +"}; c #6F97BA", +"|; c #7299BB", +"1; c #729BBB", +"2; c #749DBC", +"3; c #759EBD", +"4; c #759FBE", +"5; c #10235A", +"6; c #7083BA", +"7; c #7084BB", +"8; c #7085BA", +"9; c #7093BC", +"0; c #7095BC", +"a; c #6C91B7", +"b; c #6E95B8", +"c; c #7198BA", +"d; c #739BBB", +"e; c #78A2C2", +"f; c #0F225A", +"g; c #6F82B9", +"h; c #7083B9", +"i; c #6F83B9", +"j; c #6F83BA", +"k; c #7184BA", +"l; c #6C8DBB", +"m; c #6C8FBB", +"n; c #6D90BB", +"o; c #6E91BB", +"p; c #6F93BC", +"q; c #7094BC", +"r; c #6F94BB", +"s; c #0D3259", +"t; c #6A8FB6", +"u; c #6B91B7", +"v; c #6E93B8", +"w; c #7098BA", +"x; c #7099BA", +"y; c #7199BA", +"z; c #729BBC", +"A; c #6E81B9", +"B; c #6E82B9", +"C; c #6E90BB", +"D; c #6E93BA", +"E; c #698EB6", +"F; c #6A8EB6", +"G; c #6A90B6", +"H; c #6B90B6", +"I; c #6B92B7", +"J; c #6D93B7", +"K; c #6E96B8", +"L; c #6F97B9", +"M; c #7098BB", +"N; c #78A0C0", +"O; c #6E80B8", +"P; c #6E81B8", +"Q; c #6F81B8", +"R; c #6F81B9", +"S; c #6F82B8", +"T; c #6F92BB", +"U; c #6E92BA", +"V; c #0D3159", +"W; c #688DB4", +"X; c #698EB5", +"Y; c #698FB5", +"Z; c #6A90B7", +"`; c #6C93B7", +" > c #518FC8", +".> c #6F96B8", +"+> c #123A5A", +"@> c #0F215A", +"#> c #6D80B8", +"$> c #6D81B8", +"%> c #6C8FBA", +"&> c #6E90BA", +"*> c #6E92BB", +"=> c #6E93BC", +"-> c #0C3159", +";> c #678CB4", +">> c #678DB4", +",> c #688EB4", +"'> c #698EB4", +")> c #6A90B5", +"!> c #6B91B6", +"~> c #6D94B7", +"{> c #6D95B8", +"]> c #6E96B9", +"^> c #0E2159", +"/> c #6C7FB8", +"(> c #6D7FB7", +"_> c #6D7FB8", +":> c #507FC9", +"<> c #6D8FBA", +"[> c #6D91BB", +"}> c #6D91B9", +"|> c #0C3059", +"1> c #678AB3", +"2> c #678BB3", +"3> c #678DB3", +"4> c #6B91B5", +"5> c #6B92B5", +"6> c #6C92B6", +"7> c #6B92B6", +"8> c #6C93B6", +"9> c #0E2059", +"0> c #6C7EB7", +"a> c #6D7EB7", +"b> c #6E80B7", +"c> c #6E82B8", +"d> c #7084B9", +"e> c #6F84BA", +"f> c #6C90B9", +"g> c #668AB2", +"h> c #698FB4", +"i> c #6A90B4", +"j> c #719ABB", +"k> c #749BBC", +"l> c #6B7EB7", +"m> c #6B7DB6", +"n> c #6C7DB7", +"o> c #6C7FB7", +"p> c #6D80B7", +"q> c #6F84B9", +"r> c #7186BA", +"s> c #6C8EB9", +"t> c #6589B1", +"u> c #678CB2", +"v> c #678DB2", +"w> c #688EB3", +"x> c #6A8FB5", +"y> c #6A91B5", +"z> c #6C92B5", +"A> c #6C94B7", +"B> c #6D95B7", +"C> c #759DBD", +"D> c #0E1F5A", +"E> c #6A7CB6", +"F> c #6A7DB6", +"G> c #6C7EB6", +"H> c #7082B9", +"I> c #7285BA", +"J> c #7085B9", +"K> c #0E335A", +"L> c #658BB1", +"M> c #668BB1", +"N> c #668CB1", +"O> c #678CB1", +"P> c #688DB3", +"Q> c #688FB3", +"R> c #698FB3", +"S> c #6990B4", +"T> c #7097B9", +"U> c #7197BA", +"V> c #739CBE", +"W> c #0E1F59", +"X> c #6A7BB6", +"Y> c #6B7CB6", +"Z> c #6C7DB6", +"`> c #6B7DB7", +" , c #6F82B6", +"., c #648AB0", +"+, c #658AB1", +"@, c #658BB0", +"#, c #668CB2", +"$, c #688FB4", +"%, c #6B90B5", +"&, c #0D1E59", +"*, c #697BB5", +"=, c #6A7CB7", +"-, c #6B7EB6", +";, c #6C7EB8", +">, c #6E82B7", +",, c #6389B0", +"', c #6489B0", +"), c #658AB0", +"!, c #668AB1", +"~, c #688DB2", +"{, c #6990B5", +"], c #697AB5", +"^, c #697BB6", +"/, c #6A7BB5", +"(, c #6D7EB8", +"_, c #6D81B6", +":, c #6388AE", +"<, c #6388AF", +"[, c #6389AF", +"}, c #6489AF", +"|, c #668BB0", +"1, c #6979B4", +"2, c #6879B5", +"3, c #6879B4", +"4, c #6979B5", +"5, c #6A7AB5", +"6, c #6B7CB7", +"7, c #6D80B5", +"8, c #6287AE", +"9, c #6288AE", +"0, c #0D1D59", +"a, c #6878B4", +"b, c #6778B4", +"c, c #6C7EB5", +"d, c #6186AC", +"e, c #6186AD", +"f, c #6286AE", +"g, c #668DB1", +"h, c #678EB3", +"i, c #0D1C59", +"j, c #6777B3", +"k, c #6777B4", +"l, c #697AB4", +"m, c #6A7CB5", +"n, c #6E81B7", +"o, c #6084AC", +"p, c #6185AC", +"q, c #6086AD", +"r, c #6187AE", +"s, c #6387AE", +"t, c #0C1C59", +"u, c #6676B3", +"v, c #6776B3", +"w, c #6877B4", +"x, c #687AB5", +"y, c #697CB6", +"z, c #6A7DB7", +"A, c #6B7DB5", +"B, c #5F83AC", +"C, c #6083AC", +"D, c #6185AD", +"E, c #6288AD", +"F, c #668BB2", +"G, c #6A91B4", +"H, c #6675B3", +"I, c #6575B3", +"J, c #6677B3", +"K, c #6677B4", +"L, c #6A7DB4", +"M, c #5E82AB", +"N, c #5F83AB", +"O, c #5F84AC", +"P, c #6085AD", +"Q, c #6085AC", +"R, c #10365A", +"S, c #0C1B59", +"T, c #6575B2", +"U, c #6675B2", +"V, c #6676B2", +"W, c #6676B4", +"X, c #6776B4", +"Y, c #687AB4", +"Z, c #5D81AA", +"`, c #5D81AB", +" ' c #5D82AA", +".' c #5E83AB", +"+' c #6083AB", +"@' c #6286AD", +"#' c #648AB1", +"$' c #6473B3", +"%' c #6474B2", +"&' c #697CB3", +"*' c #5D80A9", +"=' c #5E82AA", +"-' c #5F84AB", +";' c #6287AD", +">' c #6389AE", +",' c #0B1A59", +"'' c #6473B2", +")' c #6574B2", +"!' c #6574B3", +"~' c #6778B3", +"{' c #6779B4", +"]' c #687BB2", +"^' c #5B7FA9", +"/' c #5B80A9", +"(' c #5C80A9", +"_' c #5D81A9", +":' c #5E81AA", +"<' c #6184AC", +"[' c #638AB0", +"}' c #678DB1", +"|' c #0B1A58", +"1' c #6372B1", +"2' c #6472B2", +"3' c #6472B1", +"4' c #6473B1", +"5' c #6573B2", +"6' c #6576B3", +"7' c #6878B3", +"8' c #687AB3", +"9' c #5B7EA7", +"0' c #5B7FA8", +"a' c #5B80A8", +"b' c #5C81AA", +"c' c #5F82AB", +"d' c #668DB2", +"e' c #11268E", +"f' c #11268D", +"g' c #0B1958", +"h' c #6373B2", +"i' c #6877B3", +"j' c #6879B2", +"k' c #0C2F59", +"l' c #5A7DA7", +"m' c #5A7EA7", +"n' c #5B7FA7", +"o' c #5B7EA8", +"p' c #5C7FA8", +"q' c #5F83AA", +"r' c #6084AB", +"s' c #6589B0", +"t' c #0C196C", +"u' c #152064", +"v' c #11258D", +"w' c #6371B1", +"x' c #6271B1", +"y' c #6372B2", +"z' c #6778B1", +"A' c #0C2E59", +"B' c #597CA6", +"C' c #5A7CA6", +"D' c #597DA6", +"E' c #5D80AA", +"F' c #5E83AA", +"G' c #0E355B", +"H' c #0C1A6F", +"I' c #131E62", +"J' c #414C90", +"K' c #10258E", +"L' c #6271B0", +"M' c #6272B1", +"N' c #6373B1", +"O' c #6677B1", +"P' c #0B2E59", +"Q' c #577BA5", +"R' c #587BA6", +"S' c #587CA6", +"T' c #5A7EA8", +"U' c #5D82AB", +"V' c #6289AE", +"W' c #1A5FA3", +"X' c #0D1C75", +"Y' c #131E61", +"Z' c #404B8E", +"`' c #475296", +" ) c #10258D", +".) c #6270B0", +"+) c #6272B0", +"@) c #6576B2", +"#) c #6576B1", +"$) c #577AA4", +"%) c #577BA4", +"&) c #587BA5", +"*) c #5C81A9", +"=) c #648AAF", +"-) c #0E345B", +";) c #0D1D79", +">) c #101B5F", +",) c #3C478B", +"') c #11258E", +")) c #6371B0", +"!) c #6575B1", +"~) c #0B2E58", +"{) c #5679A3", +"]) c #5779A4", +"^) c #567AA4", +"/) c #577AA5", +"() c #577BA6", +"_) c #597BA6", +":) c #175797", +"<) c #0E1F82", +"[) c #101B5E", +"}) c #384487", +"|) c #0B1858", +"1) c #6170B0", +"2) c #6575B0", +"3) c #5578A2", +"4) c #5678A3", +"5) c #5679A4", +"6) c #5A7DA6", +"7) c #102394", +"8) c #111C60", +"9) c #141F63", +"0) c #293578", +"a) c #0A1859", +"b) c #616FAF", +"c) c #616FB0", +"d) c #6270AF", +"e) c #6372B0", +"f) c #6474AF", +"g) c #0B2D58", +"h) c #5576A2", +"i) c #5577A2", +"j) c #5577A3", +"k) c #5578A4", +"l) c #5578A3", +"m) c #587CA5", +"n) c #597DA7", +"o) c #5D82A9", +"p) c #6187AD", +"q) c #154F8D", +"r) c #1227A5", +"s) c #0D185C", +"t) c #1B266A", +"u) c #313C80", +"v) c #445093", +"w) c #10248D", +"x) c #6170AF", +"y) c #6474B1", +"z) c #6373AF", +"A) c #5375A1", +"B) c #5476A2", +"C) c #587AA4", +"D) c #5C7FA9", +"E) c #6084AD", +"F) c #102393", +"G) c #0C196A", +"H) c #0E1A5D", +"I) c #242F73", +"J) c #3A4589", +"K) c #626FAF", +"L) c #626FB0", +"M) c #6475B2", +"N) c #6272AE", +"O) c #0A2C59", +"P) c #5275A1", +"Q) c #5376A2", +"R) c #5477A2", +"S) c #144A84", +"T) c #0E1E7F", +"U) c #121D61", +"V) c #2B3679", +"W) c #0A1858", +"X) c #6370B0", +"Y) c #6271AF", +"Z) c #0A2C58", +"`) c #5173A0", +" ! c #5274A1", +".! c #5274A0", +"+! c #0D1B74", +"@! c #10248E", +"#! c #6171AE", +"$! c #51729F", +"%! c #51739F", +"&! c #5273A0", +"*! c #5476A1", +"=! c #5576A3", +"-! c #114379", +";! c #102291", +">! c #0C196B", +",! c #1F2A6E", +"'! c #364185", +")! c #465195", +"!! c #10238D", +"~! c #616EAF", +"{! c #616FAD", +"]! c #0A2B59", +"^! c #50729E", +"/! c #50729F", +"(! c #5375A0", +"_! c #134C8D", +":! c #0E1E81", +"~ c #323D81", +",~ c #0A2D5D", +"'~ c #1354AE", +")~ c #10228F", +"!~ c #212C70", +"~~ c #374286", +"{~ c #0F228B", +"]~ c #1251A7", +"^~ c #283377", +"/~ c #3E4A8D", +"(~ c #0F4085", +"_~ c #0B2F62", +":~ c #1328A8", +"<~ c #0D1C77", +"[~ c #303B7F", +"}~ c #104289", +"|~ c #0B3063", +"1~ c #112497", +"2~ c #1C276A", +"3~ c #0C175B", +"4~ c #0F438A", +"5~ c #0B3266", +"6~ c #0F2088", +"7~ c #0C3367", +"8~ c #365885", +"9~ c #0B3369", +"0~ c #0E1D7C", +"a~ c #0B2F60", +"b~ c #0C366E", +" ", +" ", +" ", +" ", +" ", +" . . ", +" . . . . . . . ", +" . . . . + @ # $ % . . . . ", +" . . . . & * + @ = - % ; > , . . . . ", +" . . . . ' ) ! * + @ ~ { ] % ^ , / ( _ . . . ", +" . . . . : < [ } | * + 1 = $ 2 ; > , / 3 4 5 6 . . . . ", +" . . . . 7 8 9 0 a } | * + b c d 2 % > , / e f g h i j k . . . . ", +" . . . . l m n 9 o p q } | * r s t # u % v w x y z A B i C D E F G . . . ", +" . . . . H I J K L M 9 < q ' | N O P t # Q % R S T / U V W X Y D Z ` ...+.. . . . ", +" . . . . @.#.H I $.%.L M 9 < q } } N r + @ # Q &.R S *.=.f V W X -.;.k ` ...+.+.>.,.. . . . ", +" . . . . '.'.'.#.H ).!.~.n {.].< 0 ' } | ^.b @ # Q ] /.(., / f 4 5 B i D k _. ...:.<.[.,.}.|.1.. . . . ", +" . . . . '.'.'.'.'.2.H 3.J %.m 7 9 < p } ) 4.5.+ @ ~ Q Q 6.> , / 3 4 7.X 8.9.k 0. ...a.b.<.c.d.|.1.e.f.g.. . . ", +" . . . . . '.'.'.'.'.'.'.h.i.j.$.$.m 7 k.< l.a m.| * + @ c Q Q % > , / f f n.B i j k _.o.p.q.+.r.c.s.|.t.u.v.w.x.y.. . . . ", +" . . . . . '.'.'.'.'.'.'.'.z.A.B.I $.m 7 9 ].C.q D.| * + P t # Q 6.> (.T f E.F.6 i j G.0.H.I...+.<.c.d.J.K.L.M.N.x.y.O.P.Q.. . . . ", +" R.. . '.'.'.'.'.'.'.'.'.'.'.S.A.3.I $.m n k.T.U.q V.W.X.+ + t # Q % /.S Y./ z F.W i -.Z.k _.`.a.+.<.r.s. +|.L.M.N.g..+++O.@+#+$+%+. . . ", +" . . . . . '.'.'.'.'.'.'.'.'.&+i.H I $.K n 8 < < q } *+* ^.=+@ { Q ] -+, , ;+_ V W B 8.>+,+_.G ..+.'+c.d.d.t.)+!+M.x.x.~+{+Q.#+$+]+^+/+. . . . ", +" . . =.f . . . . . '.'.'.'.'.'.2.A.H (+$._+:+<+].< q } | N ^.s [+# Q }+6.> *./ f V 5 |+C D 0._. ...q.1+2+3+4+|.1.!+N.5+y.6+O.Q.#+$+7+8+/+/+/+/+. . . . ", +" . . / / y e . . . . . '.'.'.'.&+#.H I 9+0+m a+9 b+l.} m.X.5.+ @ = $ % > c+Y./ f U W X d+k k _. ...e+f+g+c.d.J.)+h+i+j+x.6+k+@+l+m+n+o+/+/+/+/+/+/+/+. . . . ", +" . . S , *.x T / / 3 . . . . . '.'.#.p+q+!.~.m 7 9 < 0 ' } r+* P @ # { s+% w , / e V 5 B -.j k _. .t+e+1+2+3+d.|.K.u.u+N.x..+O.v+w+x+y+z+/+/+/+/+/+/+/+/+/+/+. . . ", +" . . ; > > ^ , A+/ / e y ( . . . . . i.).B+$.C+7 9 : l.a } | * + D+t d Q % > , / f E+5 6 d+j k _.o.p.F+<.r.c.d.J.)+h+!+G+x.H+O.@+@+$+y+%+/+/+/+/+/+/+/+/+/+/+/+/+. . . . ", +" . . 2 % % /.-+> ^ S , Y.I+/ =.e . . . . . I $.C+L 9 J+K+a } & 4.+ P c d Q v L+S / f f g |+i j k ,+H.t+:.+.<.c.s.M+N+O+i+N.x..+~+@+#+P+]+%+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+. . . . ", +" . . # $ Q 2 s+6./.> > , , , , / / ;+y . . . . . 7 a+< U.Q+} | N R+P S+# u % > , / ( f V W i -.Z._.T+I...+.U+c.V+W+t.O+!+N.x.y.++X+@+#+$+%+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+. . . . ", +" . . @ t # Y+Y+Q Q &.% v v > c+c+S , , / =.( f . . . . . < q Z+) X.^.D+c Q Q % /., Y./ 4 V W i d+k Z T+`.q.+.<.r.d.}.`+)+!+N.x. @.+k+@+#+x+%+z+/+/+/+/+/+/+/+/+/+/+/+/+/+. . . . f f . ", +" . . + D+@ c # # $ Q Q Q }+% % /./.S S , *.T / ;+;+f . . . . . m.4.5.b @ # Q % R > , e f V W i 8.j k _.G ..+.'+<.c.4+`+)+h+v.w.y..@O.@+#+x+n++@/+/+/+/+/+/+/+/+/+/+/+. . . . f f f f f . ", +" . . . ^.+ + P b @ c t # - - u u &.% /.R c+c+S , A+/ / y f . . . . . 5.+ @ # Q ] /.L+A+=.f V W |+@@9.k _. .t++.b.g+c.W+|.1.!+u+j+#@~+O.@+l+#+$@8+/+/+/+/+/+/+/+/+/+. . . . f f f f f f f f . ", +" . . | N * * + + =+=+D+@ S+# %@%@- Q 2 % 6.v /.> , , , / T y f f . . . . . # Q % % > , / f E+V B -.9.k _.o.p.F+f+r.c.d.|.&@O+u+N.x..+++@+*@#+]+%+/+/+/+/+/+/+/+. . . =@f f f f f f f f f f -@. ", +" . . . W.D.| | 4.* 5.r + P b @ S+# # Y+- Q Q }+% ; -+> w w S , I+/ / 3 f . . . . . ; > , A+f V g ;@i j k _.>@`...+.r.c.d.|.&@,@'@G+x..+O.)@@+x+$+z+/+/+/+/+/+. . . T / ( y f f f f f f f f f f . . ", +" . . . a } V.} W.| r+4.* ^.* + D+@ @ @ # # - Q Q ] 2 ; /.-+> w (., A+Y./ f f . . . . . , / / U V X @@j k Z .t+a.+.<.c.d.|.K.O+!+G+x.y.!@P.Q.~@$+8+/+/+/+. . . ; > w ^ , T / 3 f f f f f f f f f . . ", +" . {@. . . . Z+} ) D.m.| r+* * 5.r + D+@ S+c # # - Q Q s+% % -+> c+(., , / / / / f . . . . . f g B i j k _._.`.q.+.<.c.]@ +1.O+!+N.x..+!@)@^@#+$+%+%+. . . # - Q % % % > L+w Y./ / / f f f f f f f . . ", +" . /@(@_@:@. . . . [ } } W.| N ! * * R++ + @ @ c c # # # Q u 2 % % ; > L+, , *./ / =.;+f . . . . . i j 9.E >@G ..+.'+c.<@4+&@)+!+N.G+.+O.O.l+#+@+. . . O s @ c c $ Q Q 2 % % > c+, I+x ;+f f f f f f . ", +" . [@/@}@/@/@/@. . . . q } } W.V.! ! N * + O + b b [+t c # $ Q u 2 ] % v R > > ^ *.A+I+/ e f f . . . . 9.E _. ...+.'+[.V+}.|.)+!+v.x..+6+{+.+. . . *+X.r+* r + s @ S+c { - Q s+% > > (., *./ f f f f f . ", +" . |@|@|@1@}@2@/@}@/@. . . . Q+[ } W.| N & * * R++ D+=+@ S+~ # # %@Q Q ] % R -+> ^ , w , , / =.;+f . . . . . ...3@<.4@3+}.|.)+!+u+w.x.)+. . . 0 q } [ V.| & 4.+ R++ b @ # # Q Q &.% 6.> > , A+x ( f f . ", +" . 5@5@6@|@7@|@|@8@}@}@2@/@. . . . ' } ) | | X.| * * ^.+ P 1 @ @ ~ # d Y+Q Q % % v > v w , , *.T / =.f f . . . . . 9@2+,.d.|.t.!+!+b.. . . <+9 o b+p 0 q Z+} ) | N * O + s @ t = d - Q % % -+> ^ , *./ . ", +" . 0@5@a@a@b@c@6@7@|@|@[@8@|@8@. . . . . } ) W.W.N & r+* * r + s 1 @ # # # { - Q u % % ; ; > c+, , , I+/ ( f f . . . . . d.M+t.j . . . $.0+m :+7 M 9 9 < U.q Z+} ) *+& 4.* O + @ @ c # { - }+% % R ^ , . ", +" . d@e@f@f@g@5@5@h@b@5@h@|@b@|@|@|@|@. . . . Z+} } | | & X.r+5.i@+ s D+@ [+t # # Q Q 2 &.% % /.R > c+, , T T / y f . . . . . . . . H 3.I !.$.%.~.C+7 {.a+T.: C.< q q } D.| r+* ^.+ =+1 @ c # - Q s+% v . ", +" . j@k@d@d@d@d@g@f@e@d@l@5@5@a@b@6@c@6@|@|@. . . . [ } } m.| | r+* * + + =+D+@ ~ ~ # m@n@n@Q &.% % v > c+(., , Y./ / =.f . . . '.h.#.#.o@H I I J $.K m C+7 M M ].< U.p q ' D.m.| ! * O + @ @ c @ d d 2 . ", +" . p@q@q@r@r@r@j@s@d@d@f@e@5@l@0@5@5@b@b@c@7@7@7@. . . . } V.V.) | & * * * + s t@u@v@v@w@m@n@x@y@u % v % > > (., , *.x / Y.. . z@A@B@'.2.#.#.p+j.I !.$.C@_+:+C+<+8 9 o < U.0 D@} W.m.| r+* O + s @ t # . ", +" . E@E@F@F@G@q@q@H@H@I@d@H@d@d@d@d@5@f@5@5@5@5@5@c@h@. . . . [ Z+) ) m.| 4.J@K@L@M@N@O@v@w@m@P@x@Q@R@S@] % 6.6.> > w , , . . T@U@V@W@X@Y@X@h.2.#.#.H B.I !.$.$._+Z@7 7 9 T.o < l.q q } } | | X.^.r D+=+. ", +" . `@E@E@E@E@F@G@ #p@q@q@q@q@d@k@d@H@d@d@g@f@g@d@5@0@5@5@6@. . . . Z+} .#+#@###$#L@%#M@O@O@&#P@P@n@n@*#=#S@&.}+% 6.-+> > . . -#T@;#U@>#z@,#X@Y@'#@.#.)#!#H I I I $.K m 7 7 7 9 9 T.< q q } } D.r+4.* 5.. ", +" . ~#~#~#{#~#E@E@E@]#G@^#^# #p@q@q@q@j@k@j@k@d@d@d@d@0@0@e@l@0@5@/#(#_#:#<#.#[#}#K@K@L@M@|#O@#2#3#4#4#x@R@5#6#% }+v . . 7#8#9#0#a#U@T@U@U@,#b#X@c#'.#.#.)#H 3.I l $.$.m m 7 7 M 9 9 < 0 q D@} *+| | . ", +" . d#e#f#~#~#~#g#h#{#{#E@i#E@E@q@F@p@]#q@q@q@q@q@j@d@k@d@d@d@j#k#l#m#n#o#:#:#p#+#}#q#$#$#$#M@M@u@v@1#r#s#3#t#u#v#5#w#x#. . y#z#A#B#C#D#a#E#F#G#V@z@H#X@I#'.@.#.#.H H B.I $.$.0+K :+7 M M : : < q q ' } . ", +" . J#K#K#K#K#L#~#~#~#~#~#~#{#{#i#E@E@^#]#G@]#q@q@^#q@I@H@M#M#N#O#k#k#l#P#Q#_#R#:#S#[#[#J@$#$#T#T#u@U#1#1#P@3#t#t#u#V#W#X#Y#Z#`# $y#z#7#7#D#D#-#.$U@U@+$z@@$H#'#'.2.2.#.p+j.I I l $.%.m m 7 7 9 ].< C.q . ", +" . #$J#K#$$$$%$K#K#L#K#L#f#~#f#~#~#`@`@E@E@E@E@E@E@q@&$*$=$=$-$-$;$O#>$>$,$,$Q#:#:#S#S#'$q#J@$#$#T#)$!$U#1#1#s#~$t#t#{$W#]$^$^$/$($`#_$y#:$7#9#D#<$a#E#U@+$[$b#X@X@A@'.2.#.p+H H B.!.!.~._+m }$7 a+9 ].. ", +" . =@|$#$#$#$1$2$K##$%$K#K#L#e#f#e#~#L#~#~#~#{#3$4$5$6$7$7$8$&$*$-$-$9$9$>$0$0$P#P#Q#S#S#'$'$'$a$b$T#c$!$!$#2#3#d$e$f$g$]$^$^$h$/$i$`#j$k$y#7#7#l$<$m$E#;#U@+$z@z@H#'.'.@.#.#.i.H q+I J $.K K :+C+7 . ", +" . n$o$p$=@o$q$#$q$#$#$#$J##$$$%$$$K#K#e#e#r$s$s$t$4$5$5$u$v$7$w$w$w$-$x$9$>$>$0$y$P#z$A$B$'$'$'$C$b$T#D$D$!$E$#F$F$G$H$I$J$K$^$L$Y#h$($($`#`#y#y#M$7#C#D#E#E#N$U@>#z@b#X@'#'.z.#.#.p+H j.!.O$K 0+m . ", +" . P$P$n$=@=@=@=@p$p$o$#$#$#$#$#$Q$K#Q$R$R$S$T$r$s$t$t$U$5$6$V$6$w$w$W$x$-$X$;$>$0$y$y$z$z$Y$Z$`$'$ % %.%T#T#!$u@+%@%#%$%%%&%*%=%J$K$-%;%>%>%($,%'%`#`#y#z#7#)%D#0#E#;#N$U@z@,#@$X@Y@'.S.#.o@H I j.I J . ", +" . !%!%~%P${%!%n$!%=@=@=@=@=@p$#$]%^%/%/%/%(%S$T$_%:%s$<%t$5$5$5$6$u$7$w$w$-$X$X$>$[%>$y$y$Y$Y$A$`$}%C$ %.%.%|%1%+%+%2%3%4%$%%%*%5%I$J$K$^$;%>%6%7%,%8%9%0%k$:$7#8#8#D#a%E#.$U@[$z@z@X@Y@Y@S.@.#.A.H q+. ", +" . b%b%c%b%d%d%!%!%!%e%f%e%n$g%g%g%^%h%h%i%j%/%R$R$T$_%:%s$k%U$U$4$6$u$V$w$7$w$x$X$X$l%l%0$m%n%z$A$o%`$p%q%.%.%|%r%+%s%2%2%3%t%u%v%*%5%J$]$w%L$x%y%6%7%,%'%z%A%`#y#B%7#l$l$D#E#E#T@[$C%z@H#X@A@I#z.#.A.. ", +" . D%E%F%F%b%b%G%b%~%~%H%I%I%I%J%J%J%g%I%I%g%]%(%R$_%R$T$T$K%k%K%U$L%M%N%u$w$O%P%Q%X$X$X$[%R%0$n%n%z$Y$Z$Z$S%q%T%|%U%V%W%s%X%3%t%4%u%v%*%Y%J$J$Z%;%;%y%y%`%8% &9%.&`#+&y#7#7#B#D#0#E#E#U@U@@&#&W@X@B@&+. ", +" . $&E%E%E%%&E%&&b%b%*&=&-&;&I%;&I%>&I%I%I%I%g%h%]%/%,&_%_%'&'&k%k%L%U$M%)&N%u$!&O%x$x$W$X$~&~&{&{&0$]&z$Y$Z$Z$T%.%^&/&U%W%s%(&2%_&3%:&u%v%<&[&}&K$K$;%>%y%y%,%8%9%9%z%|&`#y#:$7#7#C#m$E#E#.$U@U@z@@$X@. ", +" . 1&$&E%2&3&4&5&6&6&*&7&6&=&=&*&=&>&-&8&-&I%I%J%g%h%]%,&(%R$_%9&9&'&k%0&L%)&)&u$v$O%!&W$P%W$X$~&~&[%a&z$Y$b&o%c&.%d&d&e&/&U%W%s%X%2%3%t%f&f&g&<&<&h&i&Z%Z%j&y%y%k&l& &m&.&|&n&0%y#z#A#)%D#<$E#;#T@>#@&. ", +" . o&1&1&1&p&p&q&q&p&6&6&6&6&6&*&*&r&8&7&=&8&8&I%;&s&g%]%]%]%,&,&_%9&'&:%K%L%L%U$t&)&!&!&!&W$P%u&v&~&[%{&{&a&Y$w& %T%T%x&y&y&U%z&A&A&B&C&D&D&E&v%v%v%F&G&i&Z%H&x%I&J&K&8%9%m&.&|&L&M& $y#M$7#8#D#m$a%U@. ", +" . N&o&O&O&P&Q&q&q&p&6&q&q&6&6&5&6&6&6&6&=&7&*&*&=&;&;&g%R&^%^%,&,&S&T&T&U&U&k%L%L%M%N%V&W&O%!&X&u&v&Y&v&{&m%m%Z&C$Z&`&c&x&x&y&y& *.*+*s%2%C&D&t%@*f&v%<&#*G&$*%*H&x%y%`%l&8%9%m&A%&*n&**=*y#y#7#7#9#m$. ", +" . -*-*P&O&P&P&P&P&O&p&;*Q&p&p&p&q&q&5&6&q&6&6&6&6&*&=&=&>*s&s&,*'*,&)*S&T&T&!*k%k%L%M%M%V&t&!&O%P%P%X&Y&v&v&{&~*'$~*{*]*]*c&x&x&^*^& *+*/*(*_*D&t%:*E&<*[*F&#*G&$*%*}*I&I&`%K& &9%m&&*|*n&**1* $y#2*2*. ", +" 3*4*5*-*-*-*-*O&-*P&O&P&6*P&P&Q&p&p&q&p&6&5&q&6&6&6&q&6&*&7*7*>*s&,*8*8*9*S&T&U&0*U&a*b*M%M%V&W&W&c*c*X&X&Y&d*e*'$f*g*h*{*]*i*j*x&x&k* * *l*(*(*_*C&m*@*f&n*[*F&#*G&o*%*}*p*q*r*K&s*t*m&&*|*u*v*w*x*k$. ", +" 3*y*z*4*4*A*-*-*-*-*-*-*P&P&P&O&P&p&p&P&P&;*B*p&p&q&q&q&6&6&7&=&C*7*,*8*8*8*9*T&D*E*!*a*a*F*G*H*V&I*W&W&c*J*~*K*'$L*M*f*g*h*N*]*i*c&x&^*y&O* *l*P*(*Q*R*m*S*E&<*T*F&U*G&V*W*X*X*q*r*l&s*Y*Z*`*|***** =.= ", +" +=y*@=@=#=4*4*4*5*$=%=-*-*-*-*O&O&P&-*P&P&Q&Q&P&q&p&;*q&q&q&7&q&7&C*s&,*,*'*8*9*&=*=D*!*U&a*F*G*M%V&t&W&W&==c*I*S#-=;=L*>=,='=)=h*]*i*j*j*^*O*!=~=/*{=]=Q*^=S*S*<*<*T*F&/=o*(=W*X*X*J&r*_=s*:=`*I$<=-%.= ", +" +=[=}=}=[=y*@=y*z*|=z*4*1=1=-*$=-*%=-*-*-*P&P&-*P&P&P&Q&p&q&q&p&q&7&7&C*7*,*,*8*8*D*&=D*!*!*a*a*a*F*G*V&2=W&3=4=:#5=-=-=6=7=>=8=9=h*0=a=b=c=^*O*O*!=l*d={=e=R*R*R*S*E&n*F&U*U*f=o*W*g=X*h=r*G$G$&%H$I$i= ", +" j=k=l=m=l=}=}=}=}=[=@=#=@=4*#=n=1=$=o=-*1=p=-*-*P&q=-*q=-*P&O&O&;*q&6&r=C*7*7*s=t=u=&=v=9*D*0*0*a*a*F*w=w=w=2=x=:#y=z=A=B=B=6=8=C=D='=h*N*E=F=F=G=^*H=H=l*d={=I=e=R*J=K=L=L=M=N=U*o*O=P=4%Q=R=R=G$*%H${$ ", +" j=S=T=k=U=k=V=k=k=}=m=[=[=@=@=y*y*@=n=W=1=X=X=$=-*-*p=-*-*-*q=-*-*O&;*;*7&7&7&C*t=t=Y=v=&=&=*=D*D*0*a*Z=G*`= -5=_#.-+-@-#-$-%-B=&-6=7=,=*-N*=-E=----;-O*O* *l*>-d=]=,-J='-'-L=n*N=)-B&X%X%_&_&!-Q=R=R=~- ", +" j={-S={-S=S=T=S=T=k=k=V=k=V=l=[=[=[=y*y*y*n=n=o=o=n=$=p=1=%=%=$=-*-*P&O&;*;*]-r=r&C*^-t=t=/-&=/-0*0*0*0*Z=`=F*(-_-:-<-.-[-#-A=}-$-|-&-1-2-*-3-4-0=E=5-6-;-f$7-8-l*d=9-]=,-J=0-U%a-z&W%W%s%2%2%2%_&3%4%F$ ", +" b-c-c-c-d-{-d-{-S=S=S=S=T=T=k=k=V=k=V=}=[=[=y*@=n=o=e-n=1=o=1=$=p=%=-*-*P&O&;*r=]-7&f-g-t=t=Y=h-&=D**=0*0*i-j-k-(#l-m-n-.-[-@-#-o-$-p-B=&-q-2-2-3-4-r-E=5-;-G=f$H=s-8-d=x&x&y&y&q%U%U%z&W%s%s%X%2%_&2%F$ ", +" t-c-u-c-c-c-v-d-{-w-{-w-S=x-S=S=S=U=k=l=k=k=V=}=}=[=e-e-e-W=e-e-o=o=n=$=$=-*y-O&;*]-]-z-C*g-^-Y=Y=A-&=B-B-C-i-D-n#E-F-l-G-H-.-.-@-I-}-}-B=J-1->=2-3-K-4-r-5-L-6-M-f$]*]*i*c&j*x&^*^*y&e&q%z&z&N-A&s%B&+% ", +" t-O-u-u-u-u-P-Q-c-c-c-v-c-R-{-S-{-S=S=T=S=k=S=k=k=T-}=m=}=e-e-e-e-e-n=1=n=$=$=y-U-6*V-W-X-f-f-g-Y-Z-A-/-B-B-`- ;/#.;+;@;l-#;H-H-.-[-I-I-}-$;p-J->=>=2-%;4-&;r-,=3-,={*Z&]**;a=i*c&=;x&-;y&!=/&U%a-+*s%+% ", +" t-;;>;,;;;O-u-u-';Q-u-Q-Q-P-c-d-);d-);w-!;S=S=U=T=T=k=T=k=V=}=l=e-~;e-e-e-n=$={;y-$=y-U-V-];]-f-f-Y-^;Z-/;/;/;(;_;:;.;.;<;@;l-[;};n-.-|;I-1;}-$;2;J-3;4;%;6=6=6=8=8=,=3-3-h*]*a=a=i*c&j*x&x&^&!=y&U%+*+% ", +" 5;6;;;;;;;;;;;7;8;O-u-O-O-';';';';Q-c-c-);{-);w-{-{-S=k=S=U=T=k=V=k=m=e-e-~;e-e-{;1={;U-U-];V-];9;9;g-Y-^;^;/;0;_;a;a;:;.;.;b;@;[;G-H-c;[-|;I-d;$;$;J-o-}-B=B=|-&-6=8=8=,=9=3-h*0=]*`&e;a=c&x&d&^&^&y&|% ", +" f;g;g;h;h;i;j;j;;;;;8;>;k;O-u-u-O-c-u-u-';c-c-c-);c-d-w-w-S=S=S=S=T=U=k=k=V=l;l;~;m;e-1=n;o;V-U-];p;9;g-q;g-0;r;s;t;u;u;:;:;.;v;+;b;[;};w;w;x;y;[-|;|;I-o-z;}-$-%-B=&-6=6=8=8=,=*-h*h*0=]*]*i*j*j*j*x&|% ", +" f;A;B;g;g;g;g;g;h;j;6;6;;;k;;;;;O-;;O-k;u-u-c-Q-';';';c-v-);c-w-);d-S=S=U=S=S=T=S=l;~;m;{;{;C;y-y-V-];9;p;p;g-D;s;E;F;G;H;I;:;:;J;<;<;K;[;L;L;H-H-M;y;[-|;I-I-}-}-$-%-p-B=6=6=C=7=8=,=)=h*N;0=]*]*i*c&|% ", +" f;O;P;Q;R;P;Q;S;g;g;g;g;g;i;j;j;;;;;;;;;7;k;O-O-u-u-u-P-';P-u-c-c-);d-w-S={-S=!;S=S=U=k=~;{;{;n;y-o;U-T;p;p;p;U;V;W;X;Y;Y;G;Z;u;:;`;J; >b;b;.>[;};H-n-n-c;[-[-I-#-#-o-$-$-p-|-&-6=6=q-8=8=9=9=h*h*0=]*+> ", +" @>O;#>O;$>#>O;P;P;P;P;S;g;g;g;g;i;h;j;6;6;6;;;;;;;,;>;k;u-u-u-u-';u-';c-c-c-);{-);{-{-S-S=S=U=%>{;&>&>o;*>W-=>U;->;>>>,>'>Y;)>)>!>`;J;~>~>{>{>K;@;]>[;G-H-M;w;y;|;[-@-I-d;z;$-p-B=B=|-6=6=M*8=9=9=h*h*.% ", +" ^>/>(>_>(>_>_>O;O;O;$>O;A;A;P;P;S;R;g;g;i;i;i;6;6;;;;;;;;;k;k;u-O-u-O-u-Q-u-c-c-';c-c-);w-d-S=S-S-:><>n;[>[>o;}>|>1>2>3>W;'>'>)>4>5>6>7>8>J;~>~>{>{>b;K;[;[;H-H-.-c;y;[-[-#-#-}-}-p-$-B=|-&-6=>=8=,=,=.% ", +" 9>0>0>0>a>a>(>/>_>_>#>b>O;O;P;$>P;P;P;Q;g;S;c>g;g;h;i;d>j;6;e>;;;;;;k;u-;;O-u-O-Q-Q-';c-';c-);););{-S-S=n;n;[>f>|>g>g>2>'>h>h>h>h>i>)>!>7>7>8>`;`;~>~>b;b;K;.>[;[;m-w;w;c;.-[-j>I-#-z;}-k>B=B=B=&->=>=.% ", +" 9>l>m>n>0>0>0>0>a>o>(>(>_>_>p>#>p>O;O;P;P;Q;P;Q;g;g;g;g;i;g;i;h;e>j;q>;;;;;;8;7;8;>;u-O-u-u-O-';r>c-c-););w-);s>|>t>u>v>3>w>,>,>'>h>x>)>i>y>5>z>7>`;`;A>~>B>{>K;b;[;L;};H-<-w;c;[-|;#-I-#-}-}-$-B=B=C> % ", +" D>E>F>m>m>m>G>0>0>n>0>0>0>o>_>o>(>_>_>#>#>#>O;#>P;P;P;A;P;B;g;B;g;i;H>i;i;6;;;h;;;;;8;7;O-O-O-u-u-Q-I>';Q-c-c-J>K>L>M>N>O>u>v>w>P>w>Q>R>S>h>)>)>4>!>7>6>`;`;J;~>b;{>b;.>K;[;T>H-U>c;c;[-|;@-#-#-$-}-V> % ", +" W>X>E>E>m>Y>m>Y>Z>`>n>0>0>0>l>0>0>0>(>0>(>/>(>_>_>#>#>O;P;P;P;P;A;B;A;R;g;g;g;j;i;i;i;;;;;;;;;;;8;k;8;O-u-O-u- ,K>.,+,@,M>M>#,u>v>3>P>,>Q>$,$,h>)>i>%,4>6>7>6>`;J;~>~>+;b;]>]>[;L;H-w;w;y;.-[-|;#-#-o-'$ ", +" &,X>X>*,X>X>X>X>E>E>=,m>`>m>`>l>-,l>n>0>0>0>;,;,a>o>(>_>_>O;P;#>#>P;O;P;c>B;P;c>B;g;i;i;i;6;;;e>6;;;7;;;,;O-O->,_;,,',.,),!,L>N>N>#,v>v>~,w>w>w>h>h>{,i>y>4>4>7>6>:;`;J;~>{>{>b;]>.>[;L;w;w;c;[-.-[-#-'$ ", +" &,],],],],^,*,],/,X>X>E>E>E>Y>m>m>m>`>n>`>l>G>l>0>0>0>(,;,o>(>_>(>#>O;p>#>#>P;P;P;c>A;S;g;g;g;g;i;j;i;;;;;6;;;_,s;:,<,[,},.,),+,|,L>M>N>#,v>v>P>w>w>$,h>h>S>)>)>4>7>7>6>`;A>~>{>b;b;b;]>.>[;L;w;H-c;[-'$ ", +" &,1,2,3,4,2,],],],5,^,^,X>X>E>E>E>F>6,E>Y>`>`>l>`>`>`>n>l>0>o>a>_>(>_>_>_>#>p>O;O;P;$>P;P;P;g;c>g;c>g;g;i;q>i;7,s;8,8,9,:,[,[,',),.,),M>N>N>N>v>v>v>w>w>,>Q>$,Y;i>)>y>!>5>6>:;`;`;~>{>{>b;K;[;[;};H-U>'$ ", +" 0,a,a,b,a,3,3,2,3,4,],],],*,^,],^,X>X>E>E>E>E>E>6,`>m>m>`>Z>G>`>l>0>0>0>a>_>(>p>(>#>#>#>$>P;#>P;P;P;P;P;B;g;i;c,s;d,e,f,8,:,<,:,[,[,',',),@,M>N>M>#,g,v>h,P>w>'>$,h>S>)>y>y>4>6>7>`;`;~>B>b;b;b;]>[;L;S# ", +" i,j,k,k,b,j,b,a,3,3,3,2,l,3,],l,],],*,/,/,X>m,E>X>Y>Y>=,F>F>F>m>-,-,l>n>`>0>0>0>o>o>o>p>(>#>p>#>#>b>O;P;n,P;c>c,V;o,p,q,e,r,r,s,9,9,<,,,},.,.,+,L>M>M>N>O>v>v>3>w>Q>'>h>h>{,)>y>4>4>6>6>`;`;~>~>b;b;b;S# ", +" t,u,u,j,v,k,k,j,k,a,w,a,b,a,a,3,1,4,x,],l,],],/,X>X>^,y,E>Y>=,=,m>z,`>`>m>l>n>n>l>0>G>0>0>o>(>/>_>#>#>#>O;$>$>A,V;B,C,o,p,D,e,e,r,8,E,9,<,[,},',.,.,!,M>M>F,O>O>~,3>P>w>$,Q>h>S>Y;G,y>4>7>6>8>`;J;~>~>:# ", +" t,H,I,u,u,J,u,j,j,K,k,j,j,k,k,b,b,a,a,3,1,4,4,],4,],],/,/,^,X>/,*,E>E>E>E>`>m>`>`>`>`>m>0>-,0>0>0>0>(>/>_>/>p>L,|>M,N,N,C,O,P,Q,D,e,f,e,8,9,9,<,[,',.,),),|,M>N>N>u>u>v>P>w>w>,>$,h>S>)>y>4>4>7>:;8>`;R, ", +" S,T,H,H,I,U,V,V,u,v,W,u,X,j,k,k,b,b,b,b,a,a,a,3,3,3,Y,x,x,],],],],],X>X>E>E>E>E>=,F>`>`>z,`>m>`>0>G>l>0>0>0>0>L,|>Z,`, '.'N,N,+'o,P,P,e,e,@'8,9,8,:,<,[,,,#'),),M>M>F,N>u>v>3>w>,>,>h>h>h>S>i>y>4>4>6>:# ", +" S,$'%'%'T,T,I,U,I,V,U,H,u,u,J,J,u,v,v,j,j,k,b,b,a,a,b,3,3,1,l,3,],l,x,*,],*,*,/,m,X>m,E>F>Y>`>z,m>m>`>`>m>-,G>&'|>*'Z,Z,Z,=' 'M,N,B,-'o,o,d,D,e,;'8,8,9,>'[,,,',),),+,M>M>N>N>v>v>h,w>$,h>h>h>{,)>)>%,:# ", +" ,''''''''')')')'!')'I,T,T,I,H,u,u,u,u,v,W,v,j,j,j,j,k,~'~'{'a,3,3,3,2,x,4,],],],],/,*,y,/,X>m,E>z,E>F>F>Y>`>`>]'|>^'/'('*'Z,_':'M,M,M,N,o,o,<'P,D,D,e,8,s,9,:,<,[,['.,.,),M>@,M>#,O>}'v>3>w>w>h>h>h>S>_# ", +" |'1'2'3'4'''''''5'''%'T,)'T,T,I,H,u,I,6'u,u,u,v,u,u,X,v,j,j,j,7'b,a,a,b,3,3,3,Y,l,],Y,],*,*,*,*,*,X>X>E>E>E>Y>8'|>9'9'0'a'('('b'*'Z,='M,N,c'B,o,o,Q,P,Q,q,e,8,8,9,<,<,[,.,.,),),M>M>F,N>d'u>h,w>w>,>$,o# ", +" e'f'g'1'1'1'2'h'4'''4'''''''%'%'%'I,T,T,I,T,u,6'u,u,u,u,J,v,j,J,j,k,k,j,i'b,a,a,3,3,2,],4,x,],],],],^,/,/,*,X>j'k'l'l'm'n'o'p'/'('('*'_'Z,='M,q'.'-'r'o,Q,D,e,e,8,8,8,9,<,[,',',s'),L>M>M>N>O>v>3>3>w>/# ", +" t'u'v'v'e'w'x'w'1'y'1'3'3'4'4'''''5'%''')')'T,T,T,T,I,u,u,u,u,u,v,J,K,j,v,k,k,b,b,a,a,b,3,3,3,3,1,l,l,],*,*,],z'A'B'C'D'l'l'9'n'0'^'('('E'*'_'='='='F'N,O,o,P,P,P,D,e,f,8,9,:,[,[,,,.,),L>@,M>N>O>u>u>G' ", +" H'I'J'K'K'v'g'L'L'w'w'M'1'1'y'''3'N'2'''%'%'%')'%'T,T,T,T,I,T,I,u,H,u,u,u,u,j,j,k,~'b,b,~'7'3,7'3,3,3,2,1,Y,O'P'Q'R'S'B'B'l'l'o'o'T'0'p'('*'E'_' 'U'='.'N,N,O,o,D,e,D,e,f,8,8,:,V'[,[,.,',),@,|,M>/#W' ", +" X'Y'Z'`'`' ) ) )g'L'.)L'+)1'w'1'1'3'1'2'''''''''%'%'%'!')'T,)'I,T,H,@)u,H,u,u,u,J,j,j,j,k,k,b,b,a,a,b,a,3,#)P'$)%)&)R'R'S'B'D'l'l'9'9'0'0'p'('*)Z,Z, 'U'='.'N,N,r'P,D,P,D,@'e,8,s,9,<,[,=)',),@,-) ", +" ;)>),)`'`'`'`'') )g'.).).)L'))w'w'))w'1'1'4'1'3'4'N'''''%'%')'%'T,T,T,T,I,T,V,H,u,u,u,u,K,v,J,J,k,~'b,~'!)~){)])^)/)/)()R'_)S'B'l'l'm'9'n'0'('('('b'Z,Z,=' 'M,N,N,C,o,o,p,e,e,e,8,8,9,:,<,[,_;:) ", +" <)[)})`'`'`'`'`' ) ) )|)1).).)L'L'L'L'L'w'))1'1'1'3'2'3'h'h'''%'%')')'T,!'T,T,T,T,6'u,u,H,u,u,u,j,J,j,2)P'3)4){)5)5)$)$)Q'Q'S'S'B'D'6)l'T'o'o'0'0'('('*)Z,Z,M,M,.'N,-'o,o,o,P,d,e,;'8,8,:,K> ", +" 7)8)9)0)J'`'`'`'`'`' ) )a)b)c)d).).)d).)L'.)e)1'))x'1'1'1'4'''''''''%'%')'%'!')')'I,I,U,U,V,u,I,u,u,f)g)h)i)j)4)k)l)5)])$)&)&)m)S'B'D'n)6)l'9'n'o'0'p'('E'_'o)Z,M,.'F'N,r'o,P,o,e,D,p)s;q) ", +" r)X's)t)u)v)`'`'`'`'K'w)K'a)b)b)x)1).).).).).)L'w'))))1'1'1'3'1'N'1'4'''y)''%')')'T,T,T,T,6'I,V,z)g)A)A)B)h)i)i)l){){)$)$)/)C)()R'S'B'B'C'l'm'9'o'0'a'D)('_'Z,_'M,='F'N,N,r'o,P,E)s; ", +" F)G)H)I)J)`'`'`'`'`'w) )w)b)b)b)c)K)L)d).).)d).)L'))))w'e)e)1'1'y'2'''4'4'%''')'%'M)T,T,T,N)O)P)A)A)Q)B)B)R)j)j){)5)5)5)$)$)Q'&)S'S'B'D'l'l'9'0'0'p'p'('('*'Z,:'M,F'M,N,-'V;S) ", +" T)U)I'V)J'`'`'`'`'w)w)w)W)c)c)b)c)c)c)L)b)d).).).)X)L'+)w'e)e)1'1'1'h'2'4'''''%')'%'Y)Z)`) !.!P)A)A)A)B)i)j)4)4)4)4)5)$)$)/)Q'&)S'S'B'D'l'm'9'0'0'p'a'('*'_'Z,Z,:'M,V; ", +" r)+!s)t)u)v)`'`'`'`'w)w)@!W)b)b)b)c)b)c)b)L)K).).)d)d)L'L'L'w'w'1'e)1'1'1'3'4'''#!Z)$!$!%!&!.! ! !P)A)*!B)=!i)l)l)4)5)5)$)$)Q'R'S'S'B'6)l'l'l'9'n'0'D)('*)E'_'|>-! ", +" ;!>!s),!'!)!`'`'`'`'!!w)W)b)~!b)b)b)c)b)b)b)c)b)K).).)L'.).)L'))))e)+)1'1'{!]!^!/!$!$!%!%!&!.! !P)(!Q)B)B)h)j)l){)5)^)$)$)Q'&)R'S'S'B'D'6)m'm'9'9'p'|>|>_! ", +" :!)[!}!`'`'`'`'!!!!!!|!~!~!~!c)b)b)c)c)b)b)c)K)x)L).)1).)X)L'L'))1!2!3!3!4!^!/!/!$!%!5!&!.!.! !A)A)B)h)i)i)l)4)5)5)$)$)%)R'&)R'S'B'n)l'k'6!7! ", +" 8!9![)0!a!b!`'`'`'`'!!!!!!|!~!~!b)~!c)c)b)b)b)c)b)c)c)L)d).).).)c!2!d!e!3!f!4!4!g!/!%!`)`)&!.!.!P)A)h!B)B)i)i!4)4){)5)])$)$)%)&)S'k'j!k! ", +" l!H's)m!n!o!`'`'`'`'!!!!|!~!~!~!~!p!b)b)c)c)b)b)b)b)b)b)K)q!2!r!r!s!e!e!3!3!4!4!/!/!`)%!`)`).!P)t!A)Q)B)u!i)j)l)l)4)5)5)P'v! ", +" w!x![)y!z!`'`'`'`'!!!!!!A!~!~!~!~!~!p!~!b)b)c)b)b)c)q!2!B!B!B!B!r!C!e!e!3!f!D!4!/!$!%!`)E!.!.!P)A)F!B)B)G!R)P'P'H! ", +" I!>)J!K!L!`'`'`'`'!!!!|!~!~!~!~!~!~!~!b)~!b)c)M!2!B!B!B!B!B!r!r!N!C!e!3!O!3!4!^!/!/!%!P!`).!.!t!(!Q!g)R! ", +" S!T!s)U!V!o!`'`'`'!!!!!!|!W!~!~!W!~!~!~!~!X!2!B!B!B!B!B!B!B!r!B!r!Y!e!Z!e!`!D!4!^!$!$!%!5!Z)O) ~ ", +" .~+~@~I)#~`'`'`'`'!!!!A!|!W!~!W!W!W!X!2!B!B!B!B!B!B!B!B!B!B!r!r!r!r!e!Z!3!D!D!g!Z)O)$~ ", +" %~8)u'&~L!`'`'`'`'!!!!|!W!~!W!X!2!B!B!B!B!B!B!B!B!B!B!B!B!B!B!r!r!d!3!2!*~=~ ", +" -~T!s);~>~v)`'`'`'!!!!!!A!X!2!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!2!,~'~ ", +" )~t)s)!~~~)!`'`'`'!!{~2!B!B!B!B!B!B!B!B!B!B!B!B!B!B!2!,~]~ ", +" :!U)U)^~/~`'`'`'(~2!B!B!B!B!B!B!B!B!B!B!B!2!_~ ", +" :~<~@~+~[~b!`'}~2!B!B!B!B!B!B!B!B!2!|~ ", +" 1~2~3~,!'!4~2!B!B!B!B!B!2!5~ ", +" 6~x!@~7~2!B!8~2!9~ ", +" 0~a~2!b~ ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/src/Mod/Ship/InitGui.py b/src/Mod/Ship/InitGui.py index b20c552af2..05dbfecb5f 100644 --- a/src/Mod/Ship/InitGui.py +++ b/src/Mod/Ship/InitGui.py @@ -34,9 +34,13 @@ class ShipWorkbench ( Workbench ): # ToolBar list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"] self.appendToolbar("Ship design",list) + list = ["Ship_CreateTank"] + self.appendToolbar("Loading",list) # Menu list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"] self.appendMenu("Ship design",list) + list = ["Ship_CreateTank"] + self.appendToolbar("Loading",list) Gui.addWorkbench(ShipWorkbench()) diff --git a/src/Mod/Ship/Makefile.am b/src/Mod/Ship/Makefile.am index 380d8aed84..0251da41d6 100644 --- a/src/Mod/Ship/Makefile.am +++ b/src/Mod/Ship/Makefile.am @@ -4,7 +4,8 @@ datadir = $(prefix)/Mod/Ship data_DATA = \ InitGui.py \ ShipGui.py \ - Instance.py + Instance.py \ + TankInstance.py nobase_data_DATA = \ Icons/AreaCurveIco.png \ @@ -33,6 +34,9 @@ nobase_data_DATA = \ Icons/ReparametrizeIco.xpm \ Icons/Ship.xcf \ Icons/Ship.xpm \ + Icons/Tank.png \ + Icons/Tank.xcf \ + Icons/Tank.xpm \ Examples/s60.fcstd \ Examples/barehull5415.fcstd \ Examples/s60_katamaran.fcstd \ @@ -61,7 +65,10 @@ nobase_data_DATA = \ shipUtils/__init__.py \ shipUtils/Math.py \ shipUtils/Paths.py \ - shipUtils/Translator.py + shipUtils/Translator.py \ + tankCreateTank/__init__.py \ + tankCreateTank/TaskPanel.py \ + tankCreateTank/TaskPanel.ui CLEANFILES = $(BUILT_SOURCES) diff --git a/src/Mod/Ship/ShipGui.py b/src/Mod/Ship/ShipGui.py index 8f50b4be07..f62bebfb4d 100644 --- a/src/Mod/Ship/ShipGui.py +++ b/src/Mod/Ship/ShipGui.py @@ -84,8 +84,21 @@ class Hydrostatics: ToolTip = str(Translator.translate('Plot ship hydrostatics')) 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} + 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_CreateTank', CreateTank()) diff --git a/src/Mod/Ship/TankInstance.py b/src/Mod/Ship/TankInstance.py new file mode 100644 index 0000000000..584aa0f974 --- /dev/null +++ b/src/Mod/Ship/TankInstance.py @@ -0,0 +1,1886 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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 * +#* * +#*************************************************************************** + +import time + +# COIN +from pivy.coin import * +from pivy import coin + +# FreeCAD +import FreeCAD,FreeCADGui +from FreeCAD import Part, Base, Vector + +# Ship design module +from shipUtils import Paths, Translator, Math + +class ShipTank: + def __init__(self, obj, solid, level=0, density=998.0): + """ Creates a new tank on active document. + @param obj Created Part::FeaturePython object. + @param solid Solid shape that represent the tank. + @param level Tank filling level. + @param density Fluid density. + """ + # Add uniqueness property to identify Tank instances + obj.addProperty("App::PropertyBool","IsShipTank","ShipTank", str(Translator.translate("True if is a valid ship tank instance"))).IsShipTank=True + # Add general options + obj.addProperty("App::PropertyFloat","Level","ShipTank", str(Translator.translate("Filling level"))).Level=level + obj.addProperty("App::PropertyFloat","Density","ShipTank", str(Translator.translate("Inside fluid density"))).Density=density + # Add shapes + shape = self.computeShape(solid) + if not shape: + obj.IsShipTank=False + return + # obj.addProperty("Part::PropertyPartShape","Shape","ShipTank", str(Translator.translate("Tank solid"))).Shape = shape + obj.Shape = shape + obj.Proxy = self + self.obj = obj + + def onChanged(self, fp, prop): + """ Property changed, tank must be recomputed """ + if prop == "IsShipTank": + FreeCAD.Console.PrintWarning("Ussually you don't want to modify manually this option.\n") + elif prop == "Level": + if fp.Level > 100.0: + fp.Level = 100.0 + elif fp.Level < 0.0: + fp.Level = 0.0 + + def execute(self, obj): + """ Shape recomputation called """ + obj.Shape = self.computeShape(obj.Shape) + + def computeShape(self, solid): + """ Create faces shape. This method also calls to generate boxes. + @param solid Solid shape that represent the tank. + @return Computed solid shape. None if can't build it. + """ + # Study input to try to build a solid + if solid.isDerivedFrom('Part::Feature'): + # Get shape + shape = solid.Shape + if not shape: + return None + solid = shape + if not solid.isDerivedFrom('Part::TopoShape'): + return None + # Get shells + shells = solid.Shells + if not shells: + return None + # Build solids + solids = [] + for s in shells: + solid = Part.Solid(s) + if solid.Volume < 0.0: + solid.reverse() + solids.append(solid) + # Create compound + shape = Part.CompSolid(solids) + return shape + +class ViewProviderShipTank: + def __init__(self, obj): + """ Set this object to the proxy object of the actual view provider """ + obj.Proxy = self + + def attach(self, obj): + """ Setup the scene sub-graph of the view provider, this method is mandatory """ + return + + def updateData(self, fp, prop): + """ If a property of the handled feature has changed we have the chance to handle this here """ + return + + def getDisplayModes(self,obj): + ''' Return a list of display modes. ''' + modes=[] + return modes + + def getDefaultDisplayMode(self): + ''' Return the name of the default display mode. It must be defined in getDisplayModes. ''' + return "Shaded" + + def setDisplayMode(self,mode): + ''' Map the display mode defined in attach with those defined in getDisplayModes. + Since they have the same names nothing needs to be done. This method is optinal. + ''' + return mode + + def onChanged(self, vp, prop): + ''' Print the name of the property that has changed ''' + # FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n") + + def __getstate__(self): + ''' When saving the document this object gets stored using Python's cPickle module. + Since we have some un-pickable here -- the Coin stuff -- we must define this method + to return a tuple of all pickable objects or None. + ''' + return None + + def __setstate__(self,state): + ''' When restoring the pickled object from document we have the chance to set some + internals here. Since no data were pickled nothing needs to be done here. + ''' + return None + + def getIcon(self): + return """ + /* XPM */ + static char * Tank_xpm[] = { + "128 128 1605 2", + " c None", + ". c #000000", + "+ c #D1D1D1", + "@ c #D2D2D2", + "# c #D3D3D3", + "$ c #D3D4D4", + "% c #D5D5D5", + "& c #CFD0CF", + "* c #D0D0D0", + "= c #D3D2D3", + "- c #D4D4D3", + "; c #D5D6D5", + "> c #D6D6D6", + ", c #D7D7D7", + "' c #CDCECE", + ") c #CFCECE", + "! c #D0CFCF", + "~ c #D3D3D2", + "{ c #D3D3D4", + "] c #D5D4D5", + "^ c #D6D7D6", + "/ c #D8D8D8", + "( c #D8D8D9", + "_ c #D9D9DA", + ": c #CCCCCB", + "< c #CCCCCC", + "[ c #CECECD", + "} c #CECECE", + "| c #CFCFCF", + "1 c #D1D2D2", + "2 c #D5D4D4", + "3 c #D8D9D9", + "4 c #DAD9DA", + "5 c #DADBDB", + "6 c #DBDCDB", + "7 c #CACACA", + "8 c #CACBCB", + "9 c #CBCBCB", + "0 c #CCCDCD", + "a c #CECDCD", + "b c #D2D2D1", + "c c #D2D3D3", + "d c #D4D3D3", + "e c #D9D9D8", + "f c #D9D9D9", + "g c #DADBDA", + "h c #DBDCDC", + "i c #DCDCDC", + "j c #DDDDDD", + "k c #DEDEDE", + "l c #C7C8C8", + "m c #C9C9C9", + "n c #CAC9CA", + "o c #CBCBCC", + "p c #CCCDCC", + "q c #CDCDCD", + "r c #D0D1D1", + "s c #D1D2D1", + "t c #D3D2D2", + "u c #D4D4D5", + "v c #D5D5D6", + "w c #D6D7D7", + "x c #D8D7D8", + "y c #D9D8D9", + "z c #DADAD9", + "A c #DBDADA", + "B c #DBDBDC", + "C c #DDDCDD", + "D c #DDDEDE", + "E c #DEDFDE", + "F c #DFE0E0", + "G c #E0E0E1", + "H c #C6C6C6", + "I c #C7C7C7", + "J c #C8C8C7", + "K c #C9C9C8", + "L c #CACAC9", + "M c #CBCACB", + "N c #D0CFD0", + "O c #D1D0D1", + "P c #D1D1D2", + "Q c #D4D4D4", + "R c #D6D5D6", + "S c #D7D6D7", + "T c #D7D8D8", + "U c #DAD9D9", + "V c #DADADA", + "W c #DBDBDB", + "X c #DCDBDC", + "Y c #DDDDDC", + "Z c #DFDEDF", + "` c #E0DFDF", + " . c #E0E0E0", + ".. c #E1E1E1", + "+. c #E2E2E2", + "@. c #C5C4C4", + "#. c #C5C5C5", + "$. c #C8C8C8", + "%. c #C9C8C8", + "&. c #D5D5D4", + "*. c #D8D7D7", + "=. c #D9D8D8", + "-. c #DCDDDD", + ";. c #DEDDDD", + ">. c #E3E4E3", + ",. c #E5E4E4", + "'. c #C4C4C4", + "). c #C6C7C6", + "!. c #C7C8C7", + "~. c #C8C8C9", + "{. c #CACACB", + "]. c #CCCBCB", + "^. c #D0D0D1", + "/. c #D5D6D6", + "(. c #D7D7D6", + "_. c #DFDFDF", + ":. c #E1E2E2", + "<. c #E3E3E3", + "[. c #E4E3E4", + "}. c #E6E5E5", + "|. c #E6E6E6", + "1. c #E6E7E7", + "2. c #C4C5C5", + "3. c #C6C6C7", + "4. c #CFD0D0", + "5. c #D1D0D0", + "6. c #D6D5D5", + "7. c #DADADB", + "8. c #DCDDDC", + "9. c #DDDDDE", + "0. c #DEDFDF", + "a. c #E1E1E2", + "b. c #E3E2E2", + "c. c #E4E4E4", + "d. c #E5E5E5", + "e. c #E8E8E7", + "f. c #E9E8E9", + "g. c #EAE9EA", + "h. c #C5C5C4", + "i. c #C6C6C5", + "j. c #C7C7C6", + "k. c #CBCACA", + "l. c #CDCDCC", + "m. c #CECFCF", + "n. c #DBDADB", + "o. c #E0E0DF", + "p. c #E1E1E0", + "q. c #E1E2E1", + "r. c #E3E3E4", + "s. c #E4E5E5", + "t. c #E7E6E7", + "u. c #E7E7E8", + "v. c #E9E9E8", + "w. c #E9EAE9", + "x. c #EAEAEA", + "y. c #EBEBEA", + "z. c #C4C5C4", + "A. c #C6C5C5", + "B. c #C6C7C7", + "C. c #CCCCCD", + "D. c #CECECF", + "E. c #D9DAD9", + "F. c #DBDBDA", + "G. c #DEDEDD", + "H. c #E0DFE0", + "I. c #E0E1E0", + "J. c #E6E5E6", + "K. c #E7E7E6", + "L. c #E7E8E7", + "M. c #E8E8E9", + "N. c #E9E9E9", + "O. c #ECECEC", + "P. c #ECEDED", + "Q. c #EDEDEE", + "R. c #010101", + "S. c #C5C4C5", + "T. c #CBCCCB", + "U. c #CDCCCC", + "V. c #CECFCE", + "W. c #CFCFCE", + "X. c #CFCFD0", + "Y. c #D7D8D7", + "Z. c #DEDDDE", + "`. c #E1E0E0", + " + c #E5E6E6", + ".+ c #EBEBEB", + "++ c #ECEBEC", + "@+ c #EDEDED", + "#+ c #EEEEEE", + "$+ c #EFEFEF", + "%+ c #F0F0F0", + "&+ c #C4C4C5", + "*+ c #CFCECF", + "=+ c #D2D1D1", + "-+ c #D6D6D5", + ";+ c #D8D9D8", + ">+ c #DDDEDD", + ",+ c #DFDEDE", + "'+ c #E2E3E3", + ")+ c #E7E7E7", + "!+ c #E8E8E8", + "~+ c #EBECEC", + "{+ c #ECEDEC", + "]+ c #EFEFF0", + "^+ c #F1F0F1", + "/+ c #F1F1F1", + "(+ c #C7C6C6", + "_+ c #C9C8C9", + ":+ c #C9CAC9", + "<+ c #CACBCA", + "[+ c #D2D2D3", + "}+ c #D4D5D5", + "|+ c #DCDCDB", + "1+ c #E3E3E2", + "2+ c #E4E3E3", + "3+ c #E4E4E5", + "4+ c #E5E5E6", + "5+ c #EAEAE9", + "6+ c #ECEBEB", + "7+ c #F0F0EF", + "8+ c #F0F0F1", + "9+ c #C8C7C8", + "0+ c #C8C9C9", + "a+ c #CBCBCA", + "b+ c #CCCBCC", + "c+ c #D7D6D6", + "d+ c #DDDCDC", + "e+ c #E2E2E1", + "f+ c #E2E3E2", + "g+ c #E3E4E4", + "h+ c #E8E7E8", + "i+ c #E9E8E8", + "j+ c #EAE9E9", + "k+ c #EDECEC", + "l+ c #EEEEED", + "m+ c #EFEEEF", + "n+ c #EFF0F0", + "o+ c #F1F0F0", + "p+ c #C5C6C6", + "q+ c #C7C6C7", + "r+ c #D0D0CF", + "s+ c #D4D5D4", + "t+ c #E1E0E1", + "u+ c #E8E9E9", + "v+ c #EDECED", + "w+ c #EEEDED", + "x+ c #EEEFEF", + "y+ c #F0EFF0", + "z+ c #F0F1F0", + "A+ c #D7D7D8", + "B+ c #C8C7C7", + "C+ c #C9C9CA", + "D+ c #D2D1D2", + "E+ c #D9DADA", + "F+ c #E2E1E1", + "G+ c #E9E9EA", + "H+ c #EAEBEB", + "I+ c #D8D8D7", + "J+ c #CBCCCC", + "K+ c #CDCCCD", + "L+ c #D6D6D7", + "M+ c #E6E6E5", + "N+ c #E7E6E6", + "O+ c #E8E7E7", + "P+ c #EFEEEE", + "Q+ c #CDCECD", + "R+ c #D1D1D0", + "S+ c #D2D3D2", + "T+ c #DFE0DF", + "U+ c #E3E2E3", + "V+ c #E4E5E4", + "W+ c #E5E6E5", + "X+ c #ECECED", + "Y+ c #D4D3D4", + "Z+ c #CECDCE", + "`+ c #E6E6E7", + " @ c #EBEAEB", + ".@ c #ECECEB", + "+@ c #F0F1F1", + "@@ c #DCDCDD", + "#@ c #EBEAEA", + "$@ c #F0EFEF", + "%@ c #D3D4D3", + "&@ c #E6E7E6", + "*@ c #EEEDEE", + "=@ c #ADADAD", + "-@ c #565656", + ";@ c #DCDBDB", + ">@ c #DFDFE0", + ",@ c #E7E8E8", + "'@ c #E8E9E8", + ")@ c #EDEDEC", + "!@ c #EBEBEC", + "~@ c #EEEFEE", + "{@ c #B7B6B7", + "]@ c #E5E4E5", + "^@ c #EDEEED", + "/@ c #B6B6B6", + "(@ c #B6B7B7", + "_@ c #B7B7B6", + ":@ c #B7B6B6", + "<@ c #E5E5E4", + "[@ c #B5B6B5", + "}@ c #B5B6B6", + "|@ c #B5B5B5", + "1@ c #B6B5B5", + "2@ c #B6B5B6", + "3@ c #E2E1E2", + "4@ c #E4E4E3", + "5@ c #B4B4B4", + "6@ c #B4B5B5", + "7@ c #B5B5B4", + "8@ c #B6B6B5", + "9@ c #E2E2E3", + "0@ c #B3B4B4", + "a@ c #B4B4B5", + "b@ c #B4B5B4", + "c@ c #B5B4B4", + "d@ c #B3B3B3", + "e@ c #B3B3B4", + "f@ c #B4B3B3", + "g@ c #B4B4B3", + "h@ c #B5B4B5", + "i@ c #D0D1D0", + "j@ c #B3B3B2", + "k@ c #B3B2B3", + "l@ c #B4B3B4", + "m@ c #90B9D9", + "n@ c #91BAD9", + "o@ c #C6C5C6", + "p@ c #B1B2B2", + "q@ c #B2B2B2", + "r@ c #B2B3B2", + "s@ c #B2B3B3", + "t@ c #8FB7D8", + "u@ c #8EB7D7", + "v@ c #8FB8D8", + "w@ c #90B8D8", + "x@ c #91BBD9", + "y@ c #91BCDA", + "z@ c #C2C2C2", + "A@ c #C3C4C3", + "B@ c #C3C4C4", + "C@ c #C8C9C8", + "D@ c #CDCDCE", + "E@ c #B1B1B1", + "F@ c #B1B2B1", + "G@ c #B2B1B2", + "H@ c #B2B2B3", + "I@ c #B3B2B2", + "J@ c #8CB4D6", + "K@ c #8DB4D6", + "L@ c #8DB5D7", + "M@ c #8EB6D7", + "N@ c #8EB7D8", + "O@ c #8FB7D7", + "P@ c #90B9D8", + "Q@ c #91BBDA", + "R@ c #92BCD9", + "S@ c #92BCDA", + "T@ c #C1C1C0", + "U@ c #C1C1C1", + "V@ c #C2C2C1", + "W@ c #C3C3C2", + "X@ c #C3C3C3", + "Y@ c #C3C3C4", + "Z@ c #CAC9C9", + "`@ c #B1B0B0", + " # c #B2B2B1", + ".# c #8BB2D5", + "+# c #8BB2D6", + "@# c #8CB3D6", + "## c #8CB3D7", + "$# c #8DB5D6", + "%# c #8EB5D7", + "&# c #8FB8D7", + "*# c #92BBD9", + "=# c #92BBDA", + "-# c #BFC0C0", + ";# c #C0C1C0", + "># c #C2C1C1", + ",# c #C3C2C2", + "'# c #C4C4C3", + ")# c #C5C6C5", + "!# c #C5C5C6", + "~# c #B0B0B0", + "{# c #B0B1B0", + "]# c #B1B1B2", + "^# c #B2B1B1", + "/# c #0E3459", + "(# c #0E355A", + "_# c #0F355A", + ":# c #0F365A", + "<# c #8AB2D5", + "[# c #8CB3D5", + "}# c #8BB3D6", + "|# c #8FB6D7", + "1# c #8FB9D7", + "2# c #90B9D7", + "3# c #90BAD8", + "4# c #90BBD9", + "5# c #92BDDA", + "6# c #93BEDA", + "7# c #BEBEBE", + "8# c #BEBFBE", + "9# c #BFBFBE", + "0# c #BFBFC0", + "a# c #C0C0BF", + "b# c #C2C3C2", + "c# c #C4C3C3", + "d# c #AFB0B0", + "e# c #AFAFB0", + "f# c #B0AFB0", + "g# c #B0B1B1", + "h# c #B0B0B1", + "i# c #B1B0B1", + "j# c #7A9EC5", + "k# c #799FC5", + "l# c #7A9FC5", + "m# c #7AA0C6", + "n# c #0E345A", + "o# c #0F3559", + "p# c #8BB1D5", + "q# c #8CB4D5", + "r# c #8FB9D8", + "s# c #90BAD7", + "t# c #91BBD8", + "u# c #91BCD9", + "v# c #91BDD9", + "w# c #92BEDA", + "x# c #93BFDA", + "y# c #BDBDBD", + "z# c #BDBEBD", + "A# c #BEBEBD", + "B# c #BEBEBF", + "C# c #BEBFBF", + "D# c #BFBFBF", + "E# c #C0C0C0", + "F# c #C1C0C0", + "G# c #C0C1C1", + "H# c #C3C2C3", + "I# c #C4C3C4", + "J# c #AFAEAF", + "K# c #AFAFAF", + "L# c #B0AFAF", + "M# c #789DC5", + "N# c #789EC5", + "O# c #799EC5", + "P# c #7AA1C5", + "Q# c #7BA1C5", + "R# c #0F3659", + "S# c #10375A", + "T# c #8DB6D6", + "U# c #8EB8D7", + "V# c #92BDD9", + "W# c #143F5B", + "X# c #174A6A", + "Y# c #84B0CB", + "Z# c #85B0CC", + "`# c #BCBCBC", + " $ c #BDBCBC", + ".$ c #C0C0C1", + "+$ c #C1C2C1", + "@$ c #C2C3C3", + "#$ c #AEAEAE", + "$$ c #AEAFAF", + "%$ c #AFAFAE", + "&$ c #779BC4", + "*$ c #779CC4", + "=$ c #789CC4", + "-$ c #789DC4", + ";$ c #789EC4", + ">$ c #799FC4", + ",$ c #7AA0C5", + "'$ c #10385A", + ")$ c #8DB7D7", + "!$ c #8EB7D6", + "~$ c #90BBD8", + "{$ c #133E5B", + "]$ c #83AEC9", + "^$ c #84AFCA", + "/$ c #85B1CB", + "($ c #85B2CB", + "_$ c #BDBCBD", + ":$ c #BEBDBD", + "<$ c #C0BFBF", + "[$ c #C1C1C2", + "}$ c #C9CACA", + "|$ c #AEAEAD", + "1$ c #AEAFAE", + "2$ c #AEAEAF", + "3$ c #7599C3", + "4$ c #7699C3", + "5$ c #7699C2", + "6$ c #769AC3", + "7$ c #779BC3", + "8$ c #789BC4", + "9$ c #799EC4", + "0$ c #79A0C4", + "a$ c #8CB5D5", + "b$ c #8CB5D6", + "c$ c #8DB7D6", + "d$ c #426D8A", + "e$ c #16486A", + "f$ c #7AA5C1", + "g$ c #83ADC9", + "h$ c #84B1CB", + "i$ c #85B1CC", + "j$ c #BCBDBD", + "k$ c #BDBDBC", + "l$ c #BFBEBF", + "m$ c #BFC0BF", + "n$ c #ADADAC", + "o$ c #AEADAD", + "p$ c #ADAEAD", + "q$ c #ADAEAE", + "r$ c #7496C2", + "s$ c #7597C2", + "t$ c #7598C2", + "u$ c #769BC2", + "v$ c #779BC2", + "w$ c #779CC3", + "x$ c #789DC3", + "y$ c #7AA0C4", + "z$ c #7AA1C4", + "A$ c #7AA2C5", + "B$ c #7BA2C5", + "C$ c #10395A", + "D$ c #8EB6D6", + "E$ c #8EB8D6", + "F$ c #133D5A", + "G$ c #81ABC8", + "H$ c #82ACC9", + "I$ c #82ADC9", + "J$ c #82AEC9", + "K$ c #83AFC9", + "L$ c #83B0CA", + "M$ c #BDBEBE", + "N$ c #C1C0C1", + "O$ c #C7C7C8", + "P$ c #ADACAC", + "Q$ c #AFAEAE", + "R$ c #7395C1", + "S$ c #7395C2", + "T$ c #7496C1", + "U$ c #7599C2", + "V$ c #769BC3", + "W$ c #779DC3", + "X$ c #789EC3", + "Y$ c #7AA2C4", + "Z$ c #7BA3C4", + "`$ c #7BA3C5", + " % c #11395A", + ".% c #113A5A", + "+% c #123C5A", + "@% c #164A6E", + "#% c #4C7694", + "$% c #80AAC7", + "%% c #80ABC8", + "&% c #81ACC9", + "*% c #81ACC8", + "=% c #81ADC9", + "-% c #83AFCA", + ";% c #84B0CA", + ">% c #84B1CA", + ",% c #86B3CB", + "'% c #87B4CC", + ")% c #BFBEBE", + "!% c #ACACAC", + "~% c #ABACAC", + "{% c #ACACAD", + "]% c #7294C0", + "^% c #7194C0", + "/% c #7294C1", + "(% c #7394C1", + "_% c #7396C1", + ":% c #7497C2", + "<% c #7498C2", + "[% c #799FC3", + "}% c #7CA3C5", + "|% c #123B5A", + "1% c #88B1D0", + "2% c #7EA8C6", + "3% c #7FA9C6", + "4% c #7FAAC7", + "5% c #81ADC8", + "6% c #85B1CA", + "7% c #86B2CB", + "8% c #86B4CB", + "9% c #87B5CB", + "0% c #BCBCBD", + "a% c #C0BFC0", + "b% c #ABABAB", + "c% c #ACABAC", + "d% c #ABABAC", + "e% c #ACADAC", + "f% c #ACADAD", + "g% c #7193C0", + "h% c #7293C0", + "i% c #7193C1", + "j% c #7293C1", + "k% c #7498C1", + "l% c #789FC4", + "m% c #79A1C3", + "n% c #79A1C4", + "o% c #7BA2C4", + "p% c #7CA4C5", + "q% c #7CA4C4", + "r% c #16496F", + "s% c #7DA7C5", + "t% c #7FAAC6", + "u% c #80ABC7", + "v% c #80ACC7", + "w% c #82AFC9", + "x% c #84B1C9", + "y% c #85B2CA", + "z% c #87B5CC", + "A% c #88B6CC", + "B% c #BDBDBE", + "C% c #C1C2C2", + "D% c #AAABAB", + "E% c #AAAAAA", + "F% c #ABAAAB", + "G% c #ABACAB", + "H% c #ACACAB", + "I% c #7192C0", + "J% c #7292C0", + "K% c #7598C1", + "L% c #7599C1", + "M% c #759AC1", + "N% c #769AC2", + "O% c #779CC2", + "P% c #779DC2", + "Q% c #789DC2", + "R% c #78A0C3", + "S% c #7CA3C4", + "T% c #7AA2C2", + "U% c #7CA5C4", + "V% c #7DA5C4", + "W% c #7DA6C5", + "X% c #7EA8C5", + "Y% c #82ADC8", + "Z% c #83B0C9", + "`% c #85B3CA", + " & c #86B5CB", + ".& c #87B6CC", + "+& c #BCBDBC", + "@& c #C2C1C2", + "#& c #C2C2C3", + "$& c #AAA9AA", + "%& c #AAABAA", + "&& c #ABAAAA", + "*& c #7091BF", + "=& c #7092BF", + "-& c #7191C0", + ";& c #7192BF", + ">& c #7092C0", + ",& c #7295C0", + "'& c #7497C1", + ")& c #759AC2", + "!& c #769CC2", + "~& c #789FC3", + "{& c #79A0C3", + "]& c #79A2C4", + "^& c #7AA4C3", + "/& c #7BA4C4", + "(& c #7DA8C5", + "_& c #7EA9C6", + ":& c #80AAC6", + "<& c #81ADC7", + "[& c #82ADC7", + "}& c #82AEC8", + "|& c #88B7CC", + "1& c #A9A9A9", + "2& c #A9AAAA", + "3& c #A9A9AA", + "4& c #A9AAA9", + "5& c #7090BE", + "6& c #7091BE", + "7& c #7092BE", + "8& c #7191BF", + "9& c #7397C1", + "0& c #7499C1", + "a& c #7AA1C3", + "b& c #7AA2C3", + "c& c #79A2C2", + "d& c #7AA3C3", + "e& c #7BA5C4", + "f& c #80ABC6", + "g& c #81ACC7", + "h& c #81AEC8", + "i& c #82AFC8", + "j& c #83B1CA", + "k& c #85B3CB", + "l& c #85B4CA", + "m& c #87B6CB", + "n& c #88B8CC", + "o& c #A8A8A8", + "p& c #6F90BE", + "q& c #6F91BE", + "r& c #7192BE", + "s& c #7193BF", + "t& c #769BC1", + "u& c #779EC3", + "v& c #789FC2", + "w& c #79A1C2", + "x& c #7AA3C2", + "y& c #7BA4C3", + "z& c #7CA6C5", + "A& c #7DA7C4", + "B& c #7EA7C5", + "C& c #7EA9C5", + "D& c #7EAAC6", + "E& c #7FACC6", + "F& c #81AEC7", + "G& c #82AFC7", + "H& c #83B1C9", + "I& c #84B2C9", + "J& c #84B3C9", + "K& c #86B4CA", + "L& c #89B7CC", + "M& c #89B8CD", + "N& c #A8A8A7", + "O& c #6F90BD", + "P& c #6E90BD", + "Q& c #6E90BE", + "R& c #7293BF", + "S& c #7396C0", + "T& c #7397C0", + "U& c #7498C0", + "V& c #759BC1", + "W& c #769CC1", + "X& c #779EC2", + "Y& c #789EC2", + "Z& c #78A0C1", + "`& c #78A1C2", + " * c #7BA6C3", + ".* c #7BA6C4", + "+* c #7CA6C4", + "@* c #7FABC6", + "#* c #82AEC7", + "$* c #83AFC8", + "%* c #83B0C8", + "&* c #88B7CB", + "** c #89B9CC", + "=* c #89BACD", + "-* c #6E8FBD", + ";* c #6F91BD", + ">* c #7093BF", + ",* c #7194BF", + "'* c #7294BF", + ")* c #7395C0", + "!* c #7398C0", + "~* c #779FC1", + "{* c #77A0C1", + "]* c #78A1C1", + "^* c #7AA4C2", + "/* c #7CA7C4", + "(* c #7DA8C4", + "_* c #7DA9C5", + ":* c #7FAAC5", + "<* c #80ACC6", + "[* c #80ADC7", + "}* c #84B1C8", + "|* c #88B8CB", + "1* c #89BACC", + "2* c #BEBDBE", + "3* c #12285A", + "4* c #768CBE", + "5* c #768DBE", + "6* c #6E91BD", + "7* c #7193BE", + "8* c #7295BF", + "9* c #7396BF", + "0* c #7398BF", + "a* c #7499C0", + "b* c #749AC1", + "c* c #779DC1", + "d* c #789FC1", + "e* c #779EC0", + "f* c #769EC0", + "g* c #769FC0", + "h* c #77A0C0", + "i* c #79A2C1", + "j* c #79A3C2", + "k* c #7BA4C2", + "l* c #7CA7C3", + "m* c #7EAAC5", + "n* c #80ADC6", + "o* c #82B0C7", + "p* c #85B2C9", + "q* c #85B3C9", + "r* c #85B4C9", + "s* c #86B5CA", + "t* c #87B6CA", + "u* c #88B9CC", + "v* c #8AB9CC", + "w* c #8ABACC", + "x* c #8BBBCC", + "y* c #758BBE", + "z* c #758CBE", + "A* c #768CBF", + "B* c #6E91BE", + "C* c #7093BE", + "D* c #7397BF", + "E* c #7497BF", + "F* c #749AC0", + "G* c #759AC0", + "H* c #769BC0", + "I* c #769CC0", + "J* c #779EC1", + "K* c #769DC0", + "L* c #759DBF", + "M* c #769DBE", + "N* c #77A1C0", + "O* c #7AA5C2", + "P* c #7DA7C3", + "Q* c #7EA9C4", + "R* c #7EAAC4", + "S* c #7FABC5", + "T* c #81ADC6", + "U* c #81AFC7", + "V* c #82B0C8", + "W* c #83B1C8", + "X* c #84B2C8", + "Y* c #86B6CB", + "Z* c #87B7CA", + "`* c #87B7CB", + " = c #84AFCB", + ".= c #143F5A", + "+= c #12275A", + "@= c #758BBD", + "#= c #768BBE", + "$= c #6E8FBC", + "%= c #6E8EBD", + "&= c #7296BF", + "*= c #7297BF", + "== c #779CC1", + "-= c #749BBE", + ";= c #749CBF", + ">= c #759EBE", + ",= c #769FBF", + "'= c #76A0C0", + ")= c #779FC0", + "!= c #7BA5C3", + "~= c #7CA6C3", + "{= c #7CA8C4", + "]= c #7DA9C3", + "^= c #7FAAC4", + "/= c #81AFC6", + "(= c #82B1C7", + "_= c #85B5C9", + ":= c #86B6CA", + "<= c #82AECA", + "[= c #758ABD", + "}= c #748ABD", + "|= c #758CBD", + "1= c #6D8FBC", + "2= c #759CC1", + "3= c #769DC1", + "4= c #759BBF", + "5= c #739ABE", + "6= c #759DBE", + "7= c #769EBE", + "8= c #769EBF", + "9= c #779FBF", + "0= c #78A1C0", + "a= c #78A2C1", + "b= c #79A2C0", + "c= c #7AA3C1", + "d= c #7CA8C3", + "e= c #7DA9C4", + "f= c #82B0C6", + "g= c #83B2C8", + "h= c #84B3C8", + "i= c #143E5B", + "j= c #11265A", + "k= c #7489BC", + "l= c #748ABC", + "m= c #758ABC", + "n= c #6D8EBC", + "o= c #6E8EBC", + "p= c #6D8FBD", + "q= c #6F8FBD", + "r= c #7092BD", + "s= c #7294BE", + "t= c #7194BE", + "u= c #7295BE", + "v= c #7196BF", + "w= c #759BC0", + "x= c #749ABE", + "y= c #7399BC", + "z= c #729ABD", + "A= c #739ABD", + "B= c #749CBD", + "C= c #769DBF", + "D= c #779EBF", + "E= c #78A2C0", + "F= c #79A3C1", + "G= c #7AA4C1", + "H= c #7BA6C2", + "I= c #7CA9C4", + "J= c #7EABC4", + "K= c #7FACC4", + "L= c #80ADC5", + "M= c #80AEC6", + "N= c #81AEC6", + "O= c #83B1C7", + "P= c #7EA9C7", + "Q= c #7FAAC8", + "R= c #80AAC8", + "S= c #7388BC", + "T= c #7488BC", + "U= c #7389BC", + "V= c #7489BD", + "W= c #6E8EBB", + "X= c #6D8EBD", + "Y= c #7195BE", + "Z= c #7499BF", + "`= c #749ABF", + " - c #749BC0", + ".- c #7198BB", + "+- c #7298BC", + "@- c #7299BC", + "#- c #729ABC", + "$- c #739BBD", + "%- c #749BBD", + "&- c #749DBE", + "*- c #76A0BF", + "=- c #77A2C0", + "-- c #78A3C1", + ";- c #79A4C1", + ">- c #7CA8C2", + ",- c #7DAAC4", + "'- c #7FACC5", + ")- c #7DA7C6", + "!- c #7FA9C7", + "~- c #133E5A", + "{- c #7387BC", + "]- c #6F92BD", + "^- c #7094BE", + "/- c #7296BE", + "(- c #7399BD", + "_- c #0E3559", + ":- c #7096BB", + "<- c #7197BB", + "[- c #7199BB", + "}- c #739BBC", + "|- c #749CBE", + "1- c #749EBE", + "2- c #769FBE", + "3- c #77A0BF", + "4- c #77A1BF", + "5- c #78A3C0", + "6- c #79A4C0", + "7- c #7AA6C2", + "8- c #7BA7C2", + "9- c #7DA8C3", + "0- c #7EACC5", + "a- c #7CA5C5", + "b- c #10255A", + "c- c #7286BB", + "d- c #7287BC", + "e- c #6D8EBB", + "f- c #7093BD", + "g- c #7094BD", + "h- c #7195BF", + "i- c #7399BF", + "j- c #739ABF", + "k- c #7398BE", + "l- c #6F95BA", + "m- c #7096BA", + "n- c #7097BB", + "o- c #739ABC", + "p- c #739CBD", + "q- c #759EBF", + "r- c #78A2BF", + "s- c #7CA7C2", + "t- c #10245A", + "u- c #7185BB", + "v- c #7286BC", + "w- c #7387BB", + "x- c #7487BC", + "y- c #6E90BC", + "z- c #6F93BE", + "A- c #7196BE", + "B- c #7297BE", + "C- c #7298BF", + "D- c #7297BD", + "E- c #6E94BA", + "F- c #6F95B9", + "G- c #6F96BA", + "H- c #7097BA", + "I- c #729ABB", + "J- c #749DBD", + "K- c #77A0BE", + "L- c #78A4C0", + "M- c #7AA5C0", + "N- c #7CA7C5", + "O- c #7185BA", + "P- c #7286BA", + "Q- c #7285BB", + "R- c #7386BB", + "S- c #7288BC", + "T- c #7589BD", + "U- c #6E91BC", + "V- c #6F91BC", + "W- c #6E92BC", + "X- c #6F93BD", + "Y- c #7194BD", + "Z- c #7195BD", + "`- c #7298BE", + " ; c #7297BC", + ".; c #6D93B8", + "+; c #6E94B8", + "@; c #6E95B9", + "#; c #7096B9", + "$; c #739CBC", + "%; c #76A0BE", + "&; c #78A1BF", + "*; c #79A1C1", + "=; c #79A4C2", + "-; c #7BA3C3", + ";; c #7084BA", + ">; c #7184BB", + ",; c #7085BB", + "'; c #7186BB", + "); c #7287BB", + "!; c #7388BB", + "~; c #6C8EBB", + "{; c #6D8FBB", + "]; c #6F92BC", + "^; c #7095BD", + "/; c #7196BD", + "(; c #7195BC", + "_; c #0E3359", + ":; c #6C92B7", + "<; c #6D94B8", + "[; c #6F96B9", + "}; c #6F97BA", + "|; c #7299BB", + "1; c #729BBB", + "2; c #749DBC", + "3; c #759EBD", + "4; c #759FBE", + "5; c #10235A", + "6; c #7083BA", + "7; c #7084BB", + "8; c #7085BA", + "9; c #7093BC", + "0; c #7095BC", + "a; c #6C91B7", + "b; c #6E95B8", + "c; c #7198BA", + "d; c #739BBB", + "e; c #78A2C2", + "f; c #0F225A", + "g; c #6F82B9", + "h; c #7083B9", + "i; c #6F83B9", + "j; c #6F83BA", + "k; c #7184BA", + "l; c #6C8DBB", + "m; c #6C8FBB", + "n; c #6D90BB", + "o; c #6E91BB", + "p; c #6F93BC", + "q; c #7094BC", + "r; c #6F94BB", + "s; c #0D3259", + "t; c #6A8FB6", + "u; c #6B91B7", + "v; c #6E93B8", + "w; c #7098BA", + "x; c #7099BA", + "y; c #7199BA", + "z; c #729BBC", + "A; c #6E81B9", + "B; c #6E82B9", + "C; c #6E90BB", + "D; c #6E93BA", + "E; c #698EB6", + "F; c #6A8EB6", + "G; c #6A90B6", + "H; c #6B90B6", + "I; c #6B92B7", + "J; c #6D93B7", + "K; c #6E96B8", + "L; c #6F97B9", + "M; c #7098BB", + "N; c #78A0C0", + "O; c #6E80B8", + "P; c #6E81B8", + "Q; c #6F81B8", + "R; c #6F81B9", + "S; c #6F82B8", + "T; c #6F92BB", + "U; c #6E92BA", + "V; c #0D3159", + "W; c #688DB4", + "X; c #698EB5", + "Y; c #698FB5", + "Z; c #6A90B7", + "`; c #6C93B7", + " > c #518FC8", + ".> c #6F96B8", + "+> c #123A5A", + "@> c #0F215A", + "#> c #6D80B8", + "$> c #6D81B8", + "%> c #6C8FBA", + "&> c #6E90BA", + "*> c #6E92BB", + "=> c #6E93BC", + "-> c #0C3159", + ";> c #678CB4", + ">> c #678DB4", + ",> c #688EB4", + "'> c #698EB4", + ")> c #6A90B5", + "!> c #6B91B6", + "~> c #6D94B7", + "{> c #6D95B8", + "]> c #6E96B9", + "^> c #0E2159", + "/> c #6C7FB8", + "(> c #6D7FB7", + "_> c #6D7FB8", + ":> c #507FC9", + "<> c #6D8FBA", + "[> c #6D91BB", + "}> c #6D91B9", + "|> c #0C3059", + "1> c #678AB3", + "2> c #678BB3", + "3> c #678DB3", + "4> c #6B91B5", + "5> c #6B92B5", + "6> c #6C92B6", + "7> c #6B92B6", + "8> c #6C93B6", + "9> c #0E2059", + "0> c #6C7EB7", + "a> c #6D7EB7", + "b> c #6E80B7", + "c> c #6E82B8", + "d> c #7084B9", + "e> c #6F84BA", + "f> c #6C90B9", + "g> c #668AB2", + "h> c #698FB4", + "i> c #6A90B4", + "j> c #719ABB", + "k> c #749BBC", + "l> c #6B7EB7", + "m> c #6B7DB6", + "n> c #6C7DB7", + "o> c #6C7FB7", + "p> c #6D80B7", + "q> c #6F84B9", + "r> c #7186BA", + "s> c #6C8EB9", + "t> c #6589B1", + "u> c #678CB2", + "v> c #678DB2", + "w> c #688EB3", + "x> c #6A8FB5", + "y> c #6A91B5", + "z> c #6C92B5", + "A> c #6C94B7", + "B> c #6D95B7", + "C> c #759DBD", + "D> c #0E1F5A", + "E> c #6A7CB6", + "F> c #6A7DB6", + "G> c #6C7EB6", + "H> c #7082B9", + "I> c #7285BA", + "J> c #7085B9", + "K> c #0E335A", + "L> c #658BB1", + "M> c #668BB1", + "N> c #668CB1", + "O> c #678CB1", + "P> c #688DB3", + "Q> c #688FB3", + "R> c #698FB3", + "S> c #6990B4", + "T> c #7097B9", + "U> c #7197BA", + "V> c #739CBE", + "W> c #0E1F59", + "X> c #6A7BB6", + "Y> c #6B7CB6", + "Z> c #6C7DB6", + "`> c #6B7DB7", + " , c #6F82B6", + "., c #648AB0", + "+, c #658AB1", + "@, c #658BB0", + "#, c #668CB2", + "$, c #688FB4", + "%, c #6B90B5", + "&, c #0D1E59", + "*, c #697BB5", + "=, c #6A7CB7", + "-, c #6B7EB6", + ";, c #6C7EB8", + ">, c #6E82B7", + ",, c #6389B0", + "', c #6489B0", + "), c #658AB0", + "!, c #668AB1", + "~, c #688DB2", + "{, c #6990B5", + "], c #697AB5", + "^, c #697BB6", + "/, c #6A7BB5", + "(, c #6D7EB8", + "_, c #6D81B6", + ":, c #6388AE", + "<, c #6388AF", + "[, c #6389AF", + "}, c #6489AF", + "|, c #668BB0", + "1, c #6979B4", + "2, c #6879B5", + "3, c #6879B4", + "4, c #6979B5", + "5, c #6A7AB5", + "6, c #6B7CB7", + "7, c #6D80B5", + "8, c #6287AE", + "9, c #6288AE", + "0, c #0D1D59", + "a, c #6878B4", + "b, c #6778B4", + "c, c #6C7EB5", + "d, c #6186AC", + "e, c #6186AD", + "f, c #6286AE", + "g, c #668DB1", + "h, c #678EB3", + "i, c #0D1C59", + "j, c #6777B3", + "k, c #6777B4", + "l, c #697AB4", + "m, c #6A7CB5", + "n, c #6E81B7", + "o, c #6084AC", + "p, c #6185AC", + "q, c #6086AD", + "r, c #6187AE", + "s, c #6387AE", + "t, c #0C1C59", + "u, c #6676B3", + "v, c #6776B3", + "w, c #6877B4", + "x, c #687AB5", + "y, c #697CB6", + "z, c #6A7DB7", + "A, c #6B7DB5", + "B, c #5F83AC", + "C, c #6083AC", + "D, c #6185AD", + "E, c #6288AD", + "F, c #668BB2", + "G, c #6A91B4", + "H, c #6675B3", + "I, c #6575B3", + "J, c #6677B3", + "K, c #6677B4", + "L, c #6A7DB4", + "M, c #5E82AB", + "N, c #5F83AB", + "O, c #5F84AC", + "P, c #6085AD", + "Q, c #6085AC", + "R, c #10365A", + "S, c #0C1B59", + "T, c #6575B2", + "U, c #6675B2", + "V, c #6676B2", + "W, c #6676B4", + "X, c #6776B4", + "Y, c #687AB4", + "Z, c #5D81AA", + "`, c #5D81AB", + " ' c #5D82AA", + ".' c #5E83AB", + "+' c #6083AB", + "@' c #6286AD", + "#' c #648AB1", + "$' c #6473B3", + "%' c #6474B2", + "&' c #697CB3", + "*' c #5D80A9", + "=' c #5E82AA", + "-' c #5F84AB", + ";' c #6287AD", + ">' c #6389AE", + ",' c #0B1A59", + "'' c #6473B2", + ")' c #6574B2", + "!' c #6574B3", + "~' c #6778B3", + "{' c #6779B4", + "]' c #687BB2", + "^' c #5B7FA9", + "/' c #5B80A9", + "(' c #5C80A9", + "_' c #5D81A9", + ":' c #5E81AA", + "<' c #6184AC", + "[' c #638AB0", + "}' c #678DB1", + "|' c #0B1A58", + "1' c #6372B1", + "2' c #6472B2", + "3' c #6472B1", + "4' c #6473B1", + "5' c #6573B2", + "6' c #6576B3", + "7' c #6878B3", + "8' c #687AB3", + "9' c #5B7EA7", + "0' c #5B7FA8", + "a' c #5B80A8", + "b' c #5C81AA", + "c' c #5F82AB", + "d' c #668DB2", + "e' c #11268E", + "f' c #11268D", + "g' c #0B1958", + "h' c #6373B2", + "i' c #6877B3", + "j' c #6879B2", + "k' c #0C2F59", + "l' c #5A7DA7", + "m' c #5A7EA7", + "n' c #5B7FA7", + "o' c #5B7EA8", + "p' c #5C7FA8", + "q' c #5F83AA", + "r' c #6084AB", + "s' c #6589B0", + "t' c #0C196C", + "u' c #152064", + "v' c #11258D", + "w' c #6371B1", + "x' c #6271B1", + "y' c #6372B2", + "z' c #6778B1", + "A' c #0C2E59", + "B' c #597CA6", + "C' c #5A7CA6", + "D' c #597DA6", + "E' c #5D80AA", + "F' c #5E83AA", + "G' c #0E355B", + "H' c #0C1A6F", + "I' c #131E62", + "J' c #414C90", + "K' c #10258E", + "L' c #6271B0", + "M' c #6272B1", + "N' c #6373B1", + "O' c #6677B1", + "P' c #0B2E59", + "Q' c #577BA5", + "R' c #587BA6", + "S' c #587CA6", + "T' c #5A7EA8", + "U' c #5D82AB", + "V' c #6289AE", + "W' c #1A5FA3", + "X' c #0D1C75", + "Y' c #131E61", + "Z' c #404B8E", + "`' c #475296", + " ) c #10258D", + ".) c #6270B0", + "+) c #6272B0", + "@) c #6576B2", + "#) c #6576B1", + "$) c #577AA4", + "%) c #577BA4", + "&) c #587BA5", + "*) c #5C81A9", + "=) c #648AAF", + "-) c #0E345B", + ";) c #0D1D79", + ">) c #101B5F", + ",) c #3C478B", + "') c #11258E", + ")) c #6371B0", + "!) c #6575B1", + "~) c #0B2E58", + "{) c #5679A3", + "]) c #5779A4", + "^) c #567AA4", + "/) c #577AA5", + "() c #577BA6", + "_) c #597BA6", + ":) c #175797", + "<) c #0E1F82", + "[) c #101B5E", + "}) c #384487", + "|) c #0B1858", + "1) c #6170B0", + "2) c #6575B0", + "3) c #5578A2", + "4) c #5678A3", + "5) c #5679A4", + "6) c #5A7DA6", + "7) c #102394", + "8) c #111C60", + "9) c #141F63", + "0) c #293578", + "a) c #0A1859", + "b) c #616FAF", + "c) c #616FB0", + "d) c #6270AF", + "e) c #6372B0", + "f) c #6474AF", + "g) c #0B2D58", + "h) c #5576A2", + "i) c #5577A2", + "j) c #5577A3", + "k) c #5578A4", + "l) c #5578A3", + "m) c #587CA5", + "n) c #597DA7", + "o) c #5D82A9", + "p) c #6187AD", + "q) c #154F8D", + "r) c #1227A5", + "s) c #0D185C", + "t) c #1B266A", + "u) c #313C80", + "v) c #445093", + "w) c #10248D", + "x) c #6170AF", + "y) c #6474B1", + "z) c #6373AF", + "A) c #5375A1", + "B) c #5476A2", + "C) c #587AA4", + "D) c #5C7FA9", + "E) c #6084AD", + "F) c #102393", + "G) c #0C196A", + "H) c #0E1A5D", + "I) c #242F73", + "J) c #3A4589", + "K) c #626FAF", + "L) c #626FB0", + "M) c #6475B2", + "N) c #6272AE", + "O) c #0A2C59", + "P) c #5275A1", + "Q) c #5376A2", + "R) c #5477A2", + "S) c #144A84", + "T) c #0E1E7F", + "U) c #121D61", + "V) c #2B3679", + "W) c #0A1858", + "X) c #6370B0", + "Y) c #6271AF", + "Z) c #0A2C58", + "`) c #5173A0", + " ! c #5274A1", + ".! c #5274A0", + "+! c #0D1B74", + "@! c #10248E", + "#! c #6171AE", + "$! c #51729F", + "%! c #51739F", + "&! c #5273A0", + "*! c #5476A1", + "=! c #5576A3", + "-! c #114379", + ";! c #102291", + ">! c #0C196B", + ",! c #1F2A6E", + "'! c #364185", + ")! c #465195", + "!! c #10238D", + "~! c #616EAF", + "{! c #616FAD", + "]! c #0A2B59", + "^! c #50729E", + "/! c #50729F", + "(! c #5375A0", + "_! c #134C8D", + ":! c #0E1E81", + "~ c #323D81", + ",~ c #0A2D5D", + "'~ c #1354AE", + ")~ c #10228F", + "!~ c #212C70", + "~~ c #374286", + "{~ c #0F228B", + "]~ c #1251A7", + "^~ c #283377", + "/~ c #3E4A8D", + "(~ c #0F4085", + "_~ c #0B2F62", + ":~ c #1328A8", + "<~ c #0D1C77", + "[~ c #303B7F", + "}~ c #104289", + "|~ c #0B3063", + "1~ c #112497", + "2~ c #1C276A", + "3~ c #0C175B", + "4~ c #0F438A", + "5~ c #0B3266", + "6~ c #0F2088", + "7~ c #0C3367", + "8~ c #365885", + "9~ c #0B3369", + "0~ c #0E1D7C", + "a~ c #0B2F60", + "b~ c #0C366E", + " ", + " ", + " ", + " ", + " ", + " . . ", + " . . . . . . . ", + " . . . . + @ # $ % . . . . ", + " . . . . & * + @ = - % ; > , . . . . ", + " . . . . ' ) ! * + @ ~ { ] % ^ , / ( _ . . . ", + " . . . . : < [ } | * + 1 = $ 2 ; > , / 3 4 5 6 . . . . ", + " . . . . 7 8 9 0 a } | * + b c d 2 % > , / e f g h i j k . . . . ", + " . . . . l m n 9 o p q } | * r s t # u % v w x y z A B i C D E F G . . . ", + " . . . . H I J K L M 9 < q ' | N O P t # Q % R S T / U V W X Y D Z ` ...+.. . . . ", + " . . . . @.#.H I $.%.L M 9 < q } } N r + @ # Q &.R S *.=.f V W X -.;.k ` ...+.+.>.,.. . . . ", + " . . . . '.'.'.#.H ).!.~.n {.].< 0 ' } | ^.b @ # Q ] /.(., / f 4 5 B i D k _. ...:.<.[.,.}.|.1.. . . . ", + " . . . . '.'.'.'.'.2.H 3.J %.m 7 9 < p } ) 4.5.+ @ ~ Q Q 6.> , / 3 4 7.X 8.9.k 0. ...a.b.<.c.d.|.1.e.f.g.. . . ", + " . . . . . '.'.'.'.'.'.'.h.i.j.$.$.m 7 k.< l.a m.| * + @ c Q Q % > , / f f n.B i j k _.o.p.q.+.r.c.s.|.t.u.v.w.x.y.. . . . ", + " . . . . . '.'.'.'.'.'.'.'.z.A.B.I $.m 7 9 ].C.q D.| * + P t # Q 6.> (.T f E.F.6 i j G.0.H.I...+.<.c.d.J.K.L.M.N.x.y.O.P.Q.. . . . ", + " R.. . '.'.'.'.'.'.'.'.'.'.'.S.A.3.I $.m n k.T.U.q V.W.X.+ + t # Q % /.S Y./ z F.W i -.Z.k _.`.a.+.<.r.s. +|.L.M.N.g..+++O.@+#+$+%+. . . ", + " . . . . . '.'.'.'.'.'.'.'.'.&+i.H I $.K n 8 < < q } *+* ^.=+@ { Q ] -+, , ;+_ V W B 8.>+,+_.G ..+.'+c.d.d.t.)+!+M.x.x.~+{+Q.#+$+]+^+/+. . . . ", + " . . =.f . . . . . '.'.'.'.'.'.2.A.H (+$._+:+<+].< q } | N ^.s [+# Q }+6.> *./ f V 5 |+C D 0._. ...q.1+2+3+4+|.1.!+N.5+y.6+O.Q.#+$+7+8+/+/+/+/+. . . . ", + " . . / / y e . . . . . '.'.'.'.&+#.H I 9+0+m a+9 b+l.} m.X.5.+ @ = $ % > c+Y./ f U W X d+k k _. ...e+f+g+c.d.J.)+h+i+j+x.6+k+@+l+m+n+o+/+/+/+/+/+/+/+. . . . ", + " . . S , *.x T / / 3 . . . . . '.'.#.p+q+!.~.m 7 9 < 0 ' } r+* P @ # { s+% w , / e V 5 B -.j k _. .t+e+1+2+3+d.|.K.u.u+N.x..+O.v+w+x+y+z+/+/+/+/+/+/+/+/+/+/+. . . ", + " . . ; > > ^ , A+/ / e y ( . . . . . i.).B+$.C+7 9 : l.a } | * + D+t d Q % > , / f E+5 6 d+j k _.o.p.F+<.r.c.d.J.)+h+!+G+x.H+O.@+@+$+y+%+/+/+/+/+/+/+/+/+/+/+/+/+. . . . ", + " . . 2 % % /.-+> ^ S , Y.I+/ =.e . . . . . I $.C+L 9 J+K+a } & 4.+ P c d Q v L+S / f f g |+i j k ,+H.t+:.+.<.c.s.M+N+O+i+N.x..+~+@+#+P+]+%+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+. . . . ", + " . . # $ Q 2 s+6./.> > , , , , / / ;+y . . . . . 7 a+< U.Q+} | N R+P S+# u % > , / ( f V W i -.Z._.T+I...+.U+c.V+W+t.O+!+N.x.y.++X+@+#+$+%+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+. . . . ", + " . . @ t # Y+Y+Q Q &.% v v > c+c+S , , / =.( f . . . . . < q Z+) X.^.D+c Q Q % /., Y./ 4 V W i d+k Z T+`.q.+.<.r.d.}.`+)+!+N.x. @.+k+@+#+x+%+z+/+/+/+/+/+/+/+/+/+/+/+/+/+. . . . f f . ", + " . . + D+@ c # # $ Q Q Q }+% % /./.S S , *.T / ;+;+f . . . . . m.4.5.b @ # Q % R > , e f V W i 8.j k _.G ..+.'+<.c.4+`+)+h+v.w.y..@O.@+#+x+n++@/+/+/+/+/+/+/+/+/+/+/+. . . . f f f f f . ", + " . . . ^.+ + P b @ c t # - - u u &.% /.R c+c+S , A+/ / y f . . . . . 5.+ @ # Q ] /.L+A+=.f V W |+@@9.k _. .t++.b.g+c.W+|.1.!+u+j+#@~+O.@+l+#+$@8+/+/+/+/+/+/+/+/+/+. . . . f f f f f f f f . ", + " . . | N * * + + =+=+D+@ S+# %@%@- Q 2 % 6.v /.> , , , / T y f f . . . . . # Q % % > , / f E+V B -.9.k _.o.p.F+f+r.c.d.|.&@O+u+N.x..+++@+*@#+]+%+/+/+/+/+/+/+/+. . . =@f f f f f f f f f f -@. ", + " . . . W.D.| | 4.* 5.r + P b @ S+# # Y+- Q Q }+% ; -+> w w S , I+/ / 3 f . . . . . ; > , A+f V g ;@i j k _.>@`...+.r.c.d.|.&@,@'@G+x..+O.)@@+x+$+z+/+/+/+/+/+. . . T / ( y f f f f f f f f f f . . ", + " . . . a } V.} W.| r+4.* ^.* + D+@ @ @ # # - Q Q ] 2 ; /.-+> w (., A+Y./ f f . . . . . , / / U V X @@j k Z .t+a.+.<.c.d.|.K.O+!+G+x.y.!@P.Q.~@$+8+/+/+/+. . . ; > w ^ , T / 3 f f f f f f f f f . . ", + " . {@. . . . Z+} ) D.m.| r+* * 5.r + D+@ S+c # # - Q Q s+% % -+> c+(., , / / / / f . . . . . f g B i j k _._.`.q.+.<.c.]@ +1.O+!+N.x..+!@)@^@#+$+%+%+. . . # - Q % % % > L+w Y./ / / f f f f f f f . . ", + " . /@(@_@:@. . . . [ } } W.| N ! * * R++ + @ @ c c # # # Q u 2 % % ; > L+, , *./ / =.;+f . . . . . i j 9.E >@G ..+.'+c.<@4+&@)+!+N.G+.+O.O.l+#+@+. . . O s @ c c $ Q Q 2 % % > c+, I+x ;+f f f f f f . ", + " . [@/@}@/@/@/@. . . . q } } W.V.! ! N * + O + b b [+t c # $ Q u 2 ] % v R > > ^ *.A+I+/ e f f . . . . 9.E _. ...+.'+[.V+}.|.)+!+v.x..+6+{+.+. . . *+X.r+* r + s @ S+c { - Q s+% > > (., *./ f f f f f . ", + " . |@|@|@1@}@2@/@}@/@. . . . Q+[ } W.| N & * * R++ D+=+@ S+~ # # %@Q Q ] % R -+> ^ , w , , / =.;+f . . . . . ...3@<.4@3+}.|.)+!+u+w.x.)+. . . 0 q } [ V.| & 4.+ R++ b @ # # Q Q &.% 6.> > , A+x ( f f . ", + " . 5@5@6@|@7@|@|@8@}@}@2@/@. . . . ' } ) | | X.| * * ^.+ P 1 @ @ ~ # d Y+Q Q % % v > v w , , *.T / =.f f . . . . . 9@2+,.d.|.t.!+!+b.. . . <+9 o b+p 0 q Z+} ) | N * O + s @ t = d - Q % % -+> ^ , *./ . ", + " . 0@5@a@a@b@c@6@7@|@|@[@8@|@8@. . . . . } ) W.W.N & r+* * r + s 1 @ # # # { - Q u % % ; ; > c+, , , I+/ ( f f . . . . . d.M+t.j . . . $.0+m :+7 M 9 9 < U.q Z+} ) *+& 4.* O + @ @ c # { - }+% % R ^ , . ", + " . d@e@f@f@g@5@5@h@b@5@h@|@b@|@|@|@|@. . . . Z+} } | | & X.r+5.i@+ s D+@ [+t # # Q Q 2 &.% % /.R > c+, , T T / y f . . . . . . . . H 3.I !.$.%.~.C+7 {.a+T.: C.< q q } D.| r+* ^.+ =+1 @ c # - Q s+% v . ", + " . j@k@d@d@d@d@g@f@e@d@l@5@5@a@b@6@c@6@|@|@. . . . [ } } m.| | r+* * + + =+D+@ ~ ~ # m@n@n@Q &.% % v > c+(., , Y./ / =.f . . . '.h.#.#.o@H I I J $.K m C+7 M M ].< U.p q ' D.m.| ! * O + @ @ c @ d d 2 . ", + " . p@q@q@r@r@r@j@s@d@d@f@e@5@l@0@5@5@b@b@c@7@7@7@. . . . } V.V.) | & * * * + s t@u@v@v@w@m@n@x@y@u % v % > > (., , *.x / Y.. . z@A@B@'.2.#.#.p+j.I !.$.C@_+:+C+<+8 9 o < U.0 D@} W.m.| r+* O + s @ t # . ", + " . E@E@F@F@G@q@q@H@H@I@d@H@d@d@d@d@5@f@5@5@5@5@5@c@h@. . . . [ Z+) ) m.| 4.J@K@L@M@N@O@v@w@m@P@x@Q@R@S@] % 6.6.> > w , , . . T@U@V@W@X@Y@X@h.2.#.#.H B.I !.$.$._+Z@7 7 9 T.o < l.q q } } | | X.^.r D+=+. ", + " . `@E@E@E@E@F@G@ #p@q@q@q@q@d@k@d@H@d@d@g@f@g@d@5@0@5@5@6@. . . . Z+} .#+#@###$#L@%#M@O@O@&#P@P@n@n@*#=#S@&.}+% 6.-+> > . . -#T@;#U@>#z@,#X@Y@'#@.#.)#!#H I I I $.K m 7 7 7 9 9 T.< q q } } D.r+4.* 5.. ", + " . ~#~#~#{#~#E@E@E@]#G@^#^# #p@q@q@q@j@k@j@k@d@d@d@d@0@0@e@l@0@5@/#(#_#:#<#.#[#}#K@K@L@M@|#O@#2#3#4#4#x@R@5#6#% }+v . . 7#8#9#0#a#U@T@U@U@,#b#X@c#'.#.#.)#H 3.I l $.$.m m 7 7 M 9 9 < 0 q D@} *+| | . ", + " . d#e#f#~#~#~#g#h#{#{#E@i#E@E@q@F@p@]#q@q@q@q@q@j@d@k@d@d@d@j#k#l#m#n#o#:#:#p#+#}#q#$#$#$#M@M@u@v@1#r#s#3#t#u#v#5#w#x#. . y#z#A#B#C#D#a#E#F#G#V@z@H#X@I#'.@.#.#.H H B.I $.$.0+K :+7 M M : : < q q ' } . ", + " . J#K#K#K#K#L#~#~#~#~#~#~#{#{#i#E@E@^#]#G@]#q@q@^#q@I@H@M#M#N#O#k#k#l#P#Q#_#R#:#S#[#[#J@$#$#T#T#u@U#1#1#P@3#t#t#u#V#W#X#Y#Z#`# $y#z#7#7#D#D#-#.$U@U@+$z@@$H#'#'.2.2.#.p+j.I I l $.%.m m 7 7 9 ].< C.q . ", + " . #$J#K#$$$$%$K#K#L#K#L#f#~#f#~#~#`@`@E@E@E@E@E@E@q@&$*$=$=$-$-$;$O#>$>$,$,$Q#:#:#S#S#'$q#J@$#$#T#)$!$U#1#1#s#~$t#t#{$W#]$^$^$/$($`#_$y#:$7#9#D#<$a#E#U@+$[$b#X@X@A@'.2.#.p+H H B.!.!.~._+m }$7 a+9 ].. ", + " . =@|$#$#$#$1$2$K##$%$K#K#L#e#f#e#~#L#~#~#~#{#3$4$5$6$7$7$8$&$*$-$-$9$9$>$0$0$P#P#Q#S#S#'$'$'$a$b$T#c$!$!$#2#3#d$e$f$g$]$^$^$h$/$i$`#j$k$y#7#7#l$<$m$E#;#U@+$z@z@H#'.'.@.#.#.i.H q+I J $.K K :+C+7 . ", + " . n$o$p$=@o$q$#$q$#$#$#$J##$$$%$$$K#K#e#e#r$s$s$t$4$5$5$u$v$7$w$w$w$-$x$9$>$>$0$y$P#z$A$B$'$'$'$C$b$T#D$D$!$E$#F$F$G$H$I$J$K$^$L$Y#h$($($`#`#y#y#M$7#C#D#E#E#N$U@>#z@b#X@'#'.z.#.#.p+H j.!.O$K 0+m . ", + " . P$P$n$=@=@=@=@p$p$o$#$#$#$#$#$Q$K#Q$R$R$S$T$r$s$t$t$U$5$6$V$6$w$w$W$x$-$X$;$>$0$y$y$z$z$Y$Z$`$'$ % %.%T#T#!$u@+%@%#%$%%%&%*%=%J$K$-%;%>%>%($,%'%`#`#y#z#7#)%D#0#E#;#N$U@z@,#@$X@Y@'.S.#.o@H I j.I J . ", + " . !%!%~%P${%!%n$!%=@=@=@=@=@p$#$]%^%/%/%/%(%S$T$_%:%s$<%t$5$5$5$6$u$7$w$w$-$X$X$>$[%>$y$y$Y$Y$A$`$}%C$ %.%.%|%1%+%+%2%3%4%$%%%*%5%I$J$K$^$;%>%6%7%,%8%9%0%k$:$7#8#8#D#a%E#.$U@[$z@z@X@Y@Y@S.@.#.A.H q+. ", + " . b%b%c%b%d%d%!%!%!%e%f%e%n$g%g%g%^%h%h%i%j%/%R$R$T$_%:%s$k%U$U$4$6$u$V$w$7$w$x$X$X$l%l%0$m%n%z$A$o%`$p%q%.%.%|%r%+%s%2%2%3%t%u%v%*%5%J$]$w%L$x%y%6%7%,%'%z%A%`#y#B%7#l$l$D#E#E#T@[$C%z@H#X@A@I#z.#.A.. ", + " . D%E%F%F%b%b%G%b%~%~%H%I%I%I%J%J%J%g%I%I%g%]%(%R$_%R$T$T$K%k%K%U$L%M%N%u$w$O%P%Q%X$X$X$[%R%0$n%n%z$Y$Z$Z$S%q%T%|%U%V%W%s%X%3%t%4%u%v%*%Y%J$J$Z%;%;%y%y%`%8% &9%.&`#+&y#7#7#B#D#0#E#E#U@U@@&#&W@X@B@&+. ", + " . $&E%E%E%%&E%&&b%b%*&=&-&;&I%;&I%>&I%I%I%I%g%h%]%/%,&_%_%'&'&k%k%L%U$M%)&N%u$!&O%x$x$W$X$~&~&{&{&0$]&z$Y$Z$Z$T%.%^&/&U%W%s%(&2%_&3%:&u%v%<&[&}&K$K$;%>%y%y%,%8%9%9%z%|&`#y#:$7#7#C#m$E#E#.$U@U@z@@$X@. ", + " . 1&$&E%2&3&4&5&6&6&*&7&6&=&=&*&=&>&-&8&-&I%I%J%g%h%]%,&(%R$_%9&9&'&k%0&L%)&)&u$v$O%!&W$P%W$X$~&~&[%a&z$Y$b&o%c&.%d&d&e&/&U%W%s%X%2%3%t%f&f&g&<&<&h&i&Z%Z%j&y%y%k&l& &m&.&|&n&0%y#z#A#)%D#<$E#;#T@>#@&. ", + " . o&1&1&1&p&p&q&q&p&6&6&6&6&6&*&*&r&8&7&=&8&8&I%;&s&g%]%]%]%,&,&_%9&'&:%K%L%L%U$t&)&!&!&!&W$P%u&v&~&[%{&{&a&Y$w& %T%T%x&y&y&U%z&A&A&B&C&D&D&E&v%v%v%F&G&i&Z%H&x%I&J&K&8%9%m&.&|&L&M& $y#M$7#8#D#m$a%U@. ", + " . N&o&O&O&P&Q&q&q&p&6&q&q&6&6&5&6&6&6&6&=&7&*&*&=&;&;&g%R&^%^%,&,&S&T&T&U&U&k%L%L%M%N%V&W&O%!&X&u&v&Y&v&{&m%m%Z&C$Z&`&c&x&x&y&y& *.*+*s%2%C&D&t%@*f&v%<&#*G&$*%*H&x%y%`%l&8%9%m&A%&*n&**=*y#y#7#7#9#m$. ", + " . -*-*P&O&P&P&P&P&O&p&;*Q&p&p&p&q&q&5&6&q&6&6&6&6&*&=&=&>*s&s&,*'*,&)*S&T&T&!*k%k%L%M%M%V&t&!&O%P%P%X&Y&v&v&{&~*'$~*{*]*]*c&x&x&^*^& *+*/*(*_*D&t%:*E&<*[*F&#*G&$*%*}*I&I&`%K& &9%m&&*|*n&**1* $y#2*2*. ", + " 3*4*5*-*-*-*-*O&-*P&O&P&6*P&P&Q&p&p&q&p&6&5&q&6&6&6&q&6&*&7*7*>*s&,*8*8*9*S&T&U&0*U&a*b*M%M%V&W&W&c*c*X&X&Y&d*e*'$f*g*h*{*]*i*j*x&x&k* * *l*(*(*_*C&m*@*f&n*[*F&#*G&o*%*}*p*q*r*K&s*t*m&&*|*u*v*w*x*k$. ", + " 3*y*z*4*4*A*-*-*-*-*-*-*P&P&P&O&P&p&p&P&P&;*B*p&p&q&q&q&6&6&7&=&C*7*,*8*8*8*9*T&D*E*!*a*a*F*G*H*V&I*W&W&c*J*~*K*'$L*M*f*g*h*N*]*i*c&x&^*y&O* *l*P*(*Q*R*m*S*E&<*T*F&U*G&V*W*X*X*q*r*l&s*Y*Z*`*|***** =.= ", + " +=y*@=@=#=4*4*4*5*$=%=-*-*-*-*O&O&P&-*P&P&Q&Q&P&q&p&;*q&q&q&7&q&7&C*s&,*,*'*8*9*&=*=D*!*U&a*F*G*M%V&t&W&W&==c*I*S#-=;=L*>=,='=)=h*]*i*j*j*^*O*!=~=/*{=]=Q*^=S*S*<*<*T*F&/=o*(=W*X*X*J&r*_=s*:=`*I$<=-%.= ", + " +=[=}=}=[=y*@=y*z*|=z*4*1=1=-*$=-*%=-*-*-*P&P&-*P&P&P&Q&p&q&q&p&q&7&7&C*7*,*,*8*8*D*&=D*!*!*a*a*a*F*G*V&2=W&3=4=:#5=-=-=6=7=>=8=9=h*0=a=b=c=^*O*O*!=l*d={=e=R*R*R*S*E&n*F&U*U*f=o*W*g=X*h=r*G$G$&%H$I$i= ", + " j=k=l=m=l=}=}=}=}=[=@=#=@=4*#=n=1=$=o=-*1=p=-*-*P&q=-*q=-*P&O&O&;*q&6&r=C*7*7*s=t=u=&=v=9*D*0*0*a*a*F*w=w=w=2=x=:#y=z=A=B=B=6=8=C=D='=h*N*E=F=F=G=^*H=H=l*d={=I=e=R*J=K=L=L=M=N=U*o*O=P=4%Q=R=R=G$*%H${$ ", + " j=S=T=k=U=k=V=k=k=}=m=[=[=@=@=y*y*@=n=W=1=X=X=$=-*-*p=-*-*-*q=-*-*O&;*;*7&7&7&C*t=t=Y=v=&=&=*=D*D*0*a*Z=G*`= -5=_#.-+-@-#-$-%-B=&-6=7=,=*-N*=-E=----;-O*O* *l*>-d=]=,-J='-'-L=n*N=)-B&X%X%_&_&!-Q=R=R=~- ", + " j={-S={-S=S=T=S=T=k=k=V=k=V=l=[=[=[=y*y*y*n=n=o=o=n=$=p=1=%=%=$=-*-*P&O&;*;*]-r=r&C*^-t=t=/-&=/-0*0*0*0*Z=`=F*(-_-:-<-.-[-#-A=}-$-|-&-1-2-*-3-4-0=E=5-6-;-f$7-8-l*d=9-]=,-J=0-U%a-z&W%W%s%2%2%2%_&3%4%F$ ", + " b-c-c-c-d-{-d-{-S=S=S=S=T=T=k=k=V=k=V=}=[=[=y*@=n=o=e-n=1=o=1=$=p=%=-*-*P&O&;*r=]-7&f-g-t=t=Y=h-&=D**=0*0*i-j-k-(#l-m-n-.-[-@-#-o-$-p-B=&-q-2-2-3-4-r-E=5-;-G=f$H=s-8-d=x&x&y&y&q%U%U%z&W%s%s%X%2%_&2%F$ ", + " t-c-u-c-c-c-v-d-{-w-{-w-S=x-S=S=S=U=k=l=k=k=V=}=}=[=e-e-e-W=e-e-o=o=n=$=$=-*y-O&;*]-]-z-C*g-^-Y=Y=A-&=B-B-C-i-D-n#E-F-l-G-H-.-.-@-I-}-}-B=J-1->=2-3-K-4-r-5-L-6-M-f$]*]*i*c&j*x&^*^*y&e&q%z&z&N-A&s%B&+% ", + " t-O-u-u-u-u-P-Q-c-c-c-v-c-R-{-S-{-S=S=T=S=k=S=k=k=T-}=m=}=e-e-e-e-e-n=1=n=$=$=y-U-6*V-W-X-f-f-g-Y-Z-A-/-B-B-`- ;/#.;+;@;l-#;H-H-.-[-I-I-}-$;p-J->=>=2-%;4-&;r-,=3-,={*Z&]**;a=i*c&=;x&-;y&!=/&U%a-+*s%+% ", + " t-;;>;,;;;O-u-u-';Q-u-Q-Q-P-c-d-);d-);w-!;S=S=U=T=T=k=T=k=V=}=l=e-~;e-e-e-n=$={;y-$=y-U-V-];]-f-f-Y-^;Z-/;/;/;(;_;:;.;.;<;@;l-[;};n-.-|;I-1;}-$;2;J-3;4;%;6=6=6=8=8=,=3-3-h*]*a=a=i*c&j*x&x&^&!=y&U%+*+% ", + " 5;6;;;;;;;;;;;7;8;O-u-O-O-';';';';Q-c-c-);{-);w-{-{-S=k=S=U=T=k=V=k=m=e-e-~;e-e-{;1={;U-U-];V-];9;9;g-Y-^;^;/;0;_;a;a;:;.;.;b;@;[;G-H-c;[-|;I-d;$;$;J-o-}-B=B=|-&-6=8=8=,=9=3-h*0=]*`&e;a=c&x&d&^&^&y&|% ", + " f;g;g;h;h;i;j;j;;;;;8;>;k;O-u-u-O-c-u-u-';c-c-c-);c-d-w-w-S=S=S=S=T=U=k=k=V=l;l;~;m;e-1=n;o;V-U-];p;9;g-q;g-0;r;s;t;u;u;:;:;.;v;+;b;[;};w;w;x;y;[-|;|;I-o-z;}-$-%-B=&-6=6=8=8=,=*-h*h*0=]*]*i*j*j*j*x&|% ", + " f;A;B;g;g;g;g;g;h;j;6;6;;;k;;;;;O-;;O-k;u-u-c-Q-';';';c-v-);c-w-);d-S=S=U=S=S=T=S=l;~;m;{;{;C;y-y-V-];9;p;p;g-D;s;E;F;G;H;I;:;:;J;<;<;K;[;L;L;H-H-M;y;[-|;I-I-}-}-$-%-p-B=6=6=C=7=8=,=)=h*N;0=]*]*i*c&|% ", + " f;O;P;Q;R;P;Q;S;g;g;g;g;g;i;j;j;;;;;;;;;7;k;O-O-u-u-u-P-';P-u-c-c-);d-w-S={-S=!;S=S=U=k=~;{;{;n;y-o;U-T;p;p;p;U;V;W;X;Y;Y;G;Z;u;:;`;J; >b;b;.>[;};H-n-n-c;[-[-I-#-#-o-$-$-p-|-&-6=6=q-8=8=9=9=h*h*0=]*+> ", + " @>O;#>O;$>#>O;P;P;P;P;S;g;g;g;g;i;h;j;6;6;6;;;;;;;,;>;k;u-u-u-u-';u-';c-c-c-);{-);{-{-S-S=S=U=%>{;&>&>o;*>W-=>U;->;>>>,>'>Y;)>)>!>`;J;~>~>{>{>K;@;]>[;G-H-M;w;y;|;[-@-I-d;z;$-p-B=B=|-6=6=M*8=9=9=h*h*.% ", + " ^>/>(>_>(>_>_>O;O;O;$>O;A;A;P;P;S;R;g;g;i;i;i;6;6;;;;;;;;;k;k;u-O-u-O-u-Q-u-c-c-';c-c-);w-d-S=S-S-:><>n;[>[>o;}>|>1>2>3>W;'>'>)>4>5>6>7>8>J;~>~>{>{>b;K;[;[;H-H-.-c;y;[-[-#-#-}-}-p-$-B=|-&-6=>=8=,=,=.% ", + " 9>0>0>0>a>a>(>/>_>_>#>b>O;O;P;$>P;P;P;Q;g;S;c>g;g;h;i;d>j;6;e>;;;;;;k;u-;;O-u-O-Q-Q-';c-';c-);););{-S-S=n;n;[>f>|>g>g>2>'>h>h>h>h>i>)>!>7>7>8>`;`;~>~>b;b;K;.>[;[;m-w;w;c;.-[-j>I-#-z;}-k>B=B=B=&->=>=.% ", + " 9>l>m>n>0>0>0>0>a>o>(>(>_>_>p>#>p>O;O;P;P;Q;P;Q;g;g;g;g;i;g;i;h;e>j;q>;;;;;;8;7;8;>;u-O-u-u-O-';r>c-c-););w-);s>|>t>u>v>3>w>,>,>'>h>x>)>i>y>5>z>7>`;`;A>~>B>{>K;b;[;L;};H-<-w;c;[-|;#-I-#-}-}-$-B=B=C> % ", + " D>E>F>m>m>m>G>0>0>n>0>0>0>o>_>o>(>_>_>#>#>#>O;#>P;P;P;A;P;B;g;B;g;i;H>i;i;6;;;h;;;;;8;7;O-O-O-u-u-Q-I>';Q-c-c-J>K>L>M>N>O>u>v>w>P>w>Q>R>S>h>)>)>4>!>7>6>`;`;J;~>b;{>b;.>K;[;T>H-U>c;c;[-|;@-#-#-$-}-V> % ", + " W>X>E>E>m>Y>m>Y>Z>`>n>0>0>0>l>0>0>0>(>0>(>/>(>_>_>#>#>O;P;P;P;P;A;B;A;R;g;g;g;j;i;i;i;;;;;;;;;;;8;k;8;O-u-O-u- ,K>.,+,@,M>M>#,u>v>3>P>,>Q>$,$,h>)>i>%,4>6>7>6>`;J;~>~>+;b;]>]>[;L;H-w;w;y;.-[-|;#-#-o-'$ ", + " &,X>X>*,X>X>X>X>E>E>=,m>`>m>`>l>-,l>n>0>0>0>;,;,a>o>(>_>_>O;P;#>#>P;O;P;c>B;P;c>B;g;i;i;i;6;;;e>6;;;7;;;,;O-O->,_;,,',.,),!,L>N>N>#,v>v>~,w>w>w>h>h>{,i>y>4>4>7>6>:;`;J;~>{>{>b;]>.>[;L;w;w;c;[-.-[-#-'$ ", + " &,],],],],^,*,],/,X>X>E>E>E>Y>m>m>m>`>n>`>l>G>l>0>0>0>(,;,o>(>_>(>#>O;p>#>#>P;P;P;c>A;S;g;g;g;g;i;j;i;;;;;6;;;_,s;:,<,[,},.,),+,|,L>M>N>#,v>v>P>w>w>$,h>h>S>)>)>4>7>7>6>`;A>~>{>b;b;b;]>.>[;L;w;H-c;[-'$ ", + " &,1,2,3,4,2,],],],5,^,^,X>X>E>E>E>F>6,E>Y>`>`>l>`>`>`>n>l>0>o>a>_>(>_>_>_>#>p>O;O;P;$>P;P;P;g;c>g;c>g;g;i;q>i;7,s;8,8,9,:,[,[,',),.,),M>N>N>N>v>v>v>w>w>,>Q>$,Y;i>)>y>!>5>6>:;`;`;~>{>{>b;K;[;[;};H-U>'$ ", + " 0,a,a,b,a,3,3,2,3,4,],],],*,^,],^,X>X>E>E>E>E>E>6,`>m>m>`>Z>G>`>l>0>0>0>a>_>(>p>(>#>#>#>$>P;#>P;P;P;P;P;B;g;i;c,s;d,e,f,8,:,<,:,[,[,',',),@,M>N>M>#,g,v>h,P>w>'>$,h>S>)>y>y>4>6>7>`;`;~>B>b;b;b;]>[;L;S# ", + " i,j,k,k,b,j,b,a,3,3,3,2,l,3,],l,],],*,/,/,X>m,E>X>Y>Y>=,F>F>F>m>-,-,l>n>`>0>0>0>o>o>o>p>(>#>p>#>#>b>O;P;n,P;c>c,V;o,p,q,e,r,r,s,9,9,<,,,},.,.,+,L>M>M>N>O>v>v>3>w>Q>'>h>h>{,)>y>4>4>6>6>`;`;~>~>b;b;b;S# ", + " t,u,u,j,v,k,k,j,k,a,w,a,b,a,a,3,1,4,x,],l,],],/,X>X>^,y,E>Y>=,=,m>z,`>`>m>l>n>n>l>0>G>0>0>o>(>/>_>#>#>#>O;$>$>A,V;B,C,o,p,D,e,e,r,8,E,9,<,[,},',.,.,!,M>M>F,O>O>~,3>P>w>$,Q>h>S>Y;G,y>4>7>6>8>`;J;~>~>:# ", + " t,H,I,u,u,J,u,j,j,K,k,j,j,k,k,b,b,a,a,3,1,4,4,],4,],],/,/,^,X>/,*,E>E>E>E>`>m>`>`>`>`>m>0>-,0>0>0>0>(>/>_>/>p>L,|>M,N,N,C,O,P,Q,D,e,f,e,8,9,9,<,[,',.,),),|,M>N>N>u>u>v>P>w>w>,>$,h>S>)>y>4>4>7>:;8>`;R, ", + " S,T,H,H,I,U,V,V,u,v,W,u,X,j,k,k,b,b,b,b,a,a,a,3,3,3,Y,x,x,],],],],],X>X>E>E>E>E>=,F>`>`>z,`>m>`>0>G>l>0>0>0>0>L,|>Z,`, '.'N,N,+'o,P,P,e,e,@'8,9,8,:,<,[,,,#'),),M>M>F,N>u>v>3>w>,>,>h>h>h>S>i>y>4>4>6>:# ", + " S,$'%'%'T,T,I,U,I,V,U,H,u,u,J,J,u,v,v,j,j,k,b,b,a,a,b,3,3,1,l,3,],l,x,*,],*,*,/,m,X>m,E>F>Y>`>z,m>m>`>`>m>-,G>&'|>*'Z,Z,Z,=' 'M,N,B,-'o,o,d,D,e,;'8,8,9,>'[,,,',),),+,M>M>N>N>v>v>h,w>$,h>h>h>{,)>)>%,:# ", + " ,''''''''')')')'!')'I,T,T,I,H,u,u,u,u,v,W,v,j,j,j,j,k,~'~'{'a,3,3,3,2,x,4,],],],],/,*,y,/,X>m,E>z,E>F>F>Y>`>`>]'|>^'/'('*'Z,_':'M,M,M,N,o,o,<'P,D,D,e,8,s,9,:,<,[,['.,.,),M>@,M>#,O>}'v>3>w>w>h>h>h>S>_# ", + " |'1'2'3'4'''''''5'''%'T,)'T,T,I,H,u,I,6'u,u,u,v,u,u,X,v,j,j,j,7'b,a,a,b,3,3,3,Y,l,],Y,],*,*,*,*,*,X>X>E>E>E>Y>8'|>9'9'0'a'('('b'*'Z,='M,N,c'B,o,o,Q,P,Q,q,e,8,8,9,<,<,[,.,.,),),M>M>F,N>d'u>h,w>w>,>$,o# ", + " e'f'g'1'1'1'2'h'4'''4'''''''%'%'%'I,T,T,I,T,u,6'u,u,u,u,J,v,j,J,j,k,k,j,i'b,a,a,3,3,2,],4,x,],],],],^,/,/,*,X>j'k'l'l'm'n'o'p'/'('('*'_'Z,='M,q'.'-'r'o,Q,D,e,e,8,8,8,9,<,[,',',s'),L>M>M>N>O>v>3>3>w>/# ", + " t'u'v'v'e'w'x'w'1'y'1'3'3'4'4'''''5'%''')')'T,T,T,T,I,u,u,u,u,u,v,J,K,j,v,k,k,b,b,a,a,b,3,3,3,3,1,l,l,],*,*,],z'A'B'C'D'l'l'9'n'0'^'('('E'*'_'='='='F'N,O,o,P,P,P,D,e,f,8,9,:,[,[,,,.,),L>@,M>N>O>u>u>G' ", + " H'I'J'K'K'v'g'L'L'w'w'M'1'1'y'''3'N'2'''%'%'%')'%'T,T,T,T,I,T,I,u,H,u,u,u,u,j,j,k,~'b,b,~'7'3,7'3,3,3,2,1,Y,O'P'Q'R'S'B'B'l'l'o'o'T'0'p'('*'E'_' 'U'='.'N,N,O,o,D,e,D,e,f,8,8,:,V'[,[,.,',),@,|,M>/#W' ", + " X'Y'Z'`'`' ) ) )g'L'.)L'+)1'w'1'1'3'1'2'''''''''%'%'%'!')'T,)'I,T,H,@)u,H,u,u,u,J,j,j,j,k,k,b,b,a,a,b,a,3,#)P'$)%)&)R'R'S'B'D'l'l'9'9'0'0'p'('*)Z,Z, 'U'='.'N,N,r'P,D,P,D,@'e,8,s,9,<,[,=)',),@,-) ", + " ;)>),)`'`'`'`'') )g'.).).)L'))w'w'))w'1'1'4'1'3'4'N'''''%'%')'%'T,T,T,T,I,T,V,H,u,u,u,u,K,v,J,J,k,~'b,~'!)~){)])^)/)/)()R'_)S'B'l'l'm'9'n'0'('('('b'Z,Z,=' 'M,N,N,C,o,o,p,e,e,e,8,8,9,:,<,[,_;:) ", + " <)[)})`'`'`'`'`' ) ) )|)1).).)L'L'L'L'L'w'))1'1'1'3'2'3'h'h'''%'%')')'T,!'T,T,T,T,6'u,u,H,u,u,u,j,J,j,2)P'3)4){)5)5)$)$)Q'Q'S'S'B'D'6)l'T'o'o'0'0'('('*)Z,Z,M,M,.'N,-'o,o,o,P,d,e,;'8,8,:,K> ", + " 7)8)9)0)J'`'`'`'`'`' ) )a)b)c)d).).)d).)L'.)e)1'))x'1'1'1'4'''''''''%'%')'%'!')')'I,I,U,U,V,u,I,u,u,f)g)h)i)j)4)k)l)5)])$)&)&)m)S'B'D'n)6)l'9'n'o'0'p'('E'_'o)Z,M,.'F'N,r'o,P,o,e,D,p)s;q) ", + " r)X's)t)u)v)`'`'`'`'K'w)K'a)b)b)x)1).).).).).)L'w'))))1'1'1'3'1'N'1'4'''y)''%')')'T,T,T,T,6'I,V,z)g)A)A)B)h)i)i)l){){)$)$)/)C)()R'S'B'B'C'l'm'9'o'0'a'D)('_'Z,_'M,='F'N,N,r'o,P,E)s; ", + " F)G)H)I)J)`'`'`'`'`'w) )w)b)b)b)c)K)L)d).).)d).)L'))))w'e)e)1'1'y'2'''4'4'%''')'%'M)T,T,T,N)O)P)A)A)Q)B)B)R)j)j){)5)5)5)$)$)Q'&)S'S'B'D'l'l'9'0'0'p'p'('('*'Z,:'M,F'M,N,-'V;S) ", + " T)U)I'V)J'`'`'`'`'w)w)w)W)c)c)b)c)c)c)L)b)d).).).)X)L'+)w'e)e)1'1'1'h'2'4'''''%')'%'Y)Z)`) !.!P)A)A)A)B)i)j)4)4)4)4)5)$)$)/)Q'&)S'S'B'D'l'm'9'0'0'p'a'('*'_'Z,Z,:'M,V; ", + " r)+!s)t)u)v)`'`'`'`'w)w)@!W)b)b)b)c)b)c)b)L)K).).)d)d)L'L'L'w'w'1'e)1'1'1'3'4'''#!Z)$!$!%!&!.! ! !P)A)*!B)=!i)l)l)4)5)5)$)$)Q'R'S'S'B'6)l'l'l'9'n'0'D)('*)E'_'|>-! ", + " ;!>!s),!'!)!`'`'`'`'!!w)W)b)~!b)b)b)c)b)b)b)c)b)K).).)L'.).)L'))))e)+)1'1'{!]!^!/!$!$!%!%!&!.! !P)(!Q)B)B)h)j)l){)5)^)$)$)Q'&)R'S'S'B'D'6)m'm'9'9'p'|>|>_! ", + " :!)[!}!`'`'`'`'!!!!!!|!~!~!~!c)b)b)c)c)b)b)c)K)x)L).)1).)X)L'L'))1!2!3!3!4!^!/!/!$!%!5!&!.!.! !A)A)B)h)i)i)l)4)5)5)$)$)%)R'&)R'S'B'n)l'k'6!7! ", + " 8!9![)0!a!b!`'`'`'`'!!!!!!|!~!~!b)~!c)c)b)b)b)c)b)c)c)L)d).).).)c!2!d!e!3!f!4!4!g!/!%!`)`)&!.!.!P)A)h!B)B)i)i!4)4){)5)])$)$)%)&)S'k'j!k! ", + " l!H's)m!n!o!`'`'`'`'!!!!|!~!~!~!~!p!b)b)c)c)b)b)b)b)b)b)K)q!2!r!r!s!e!e!3!3!4!4!/!/!`)%!`)`).!P)t!A)Q)B)u!i)j)l)l)4)5)5)P'v! ", + " w!x![)y!z!`'`'`'`'!!!!!!A!~!~!~!~!~!p!~!b)b)c)b)b)c)q!2!B!B!B!B!r!C!e!e!3!f!D!4!/!$!%!`)E!.!.!P)A)F!B)B)G!R)P'P'H! ", + " I!>)J!K!L!`'`'`'`'!!!!|!~!~!~!~!~!~!~!b)~!b)c)M!2!B!B!B!B!B!r!r!N!C!e!3!O!3!4!^!/!/!%!P!`).!.!t!(!Q!g)R! ", + " S!T!s)U!V!o!`'`'`'!!!!!!|!W!~!~!W!~!~!~!~!X!2!B!B!B!B!B!B!B!r!B!r!Y!e!Z!e!`!D!4!^!$!$!%!5!Z)O) ~ ", + " .~+~@~I)#~`'`'`'`'!!!!A!|!W!~!W!W!W!X!2!B!B!B!B!B!B!B!B!B!B!r!r!r!r!e!Z!3!D!D!g!Z)O)$~ ", + " %~8)u'&~L!`'`'`'`'!!!!|!W!~!W!X!2!B!B!B!B!B!B!B!B!B!B!B!B!B!B!r!r!d!3!2!*~=~ ", + " -~T!s);~>~v)`'`'`'!!!!!!A!X!2!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!2!,~'~ ", + " )~t)s)!~~~)!`'`'`'!!{~2!B!B!B!B!B!B!B!B!B!B!B!B!B!B!2!,~]~ ", + " :!U)U)^~/~`'`'`'(~2!B!B!B!B!B!B!B!B!B!B!B!2!_~ ", + " :~<~@~+~[~b!`'}~2!B!B!B!B!B!B!B!B!2!|~ ", + " 1~2~3~,!'!4~2!B!B!B!B!B!2!5~ ", + " 6~x!@~7~2!B!8~2!9~ ", + " 0~a~2!b~ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " "}; + """ diff --git a/src/Mod/Ship/shipLoadExample/TaskPanel.ui b/src/Mod/Ship/shipLoadExample/TaskPanel.ui index 77d7441895..3c875d905a 100644 --- a/src/Mod/Ship/shipLoadExample/TaskPanel.ui +++ b/src/Mod/Ship/shipLoadExample/TaskPanel.ui @@ -76,7 +76,7 @@ - Serie 60 from Iowa University + Series 60 from Iowa University @@ -86,7 +86,7 @@ - Serie 60 (Katamaran) + Series 60 (Katamaran) diff --git a/src/Mod/Ship/tankCreateTank/TaskPanel.py b/src/Mod/Ship/tankCreateTank/TaskPanel.py new file mode 100644 index 0000000000..ec6394638e --- /dev/null +++ b/src/Mod/Ship/tankCreateTank/TaskPanel.py @@ -0,0 +1,167 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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 +from TankInstance import * +from shipUtils import Paths, Translator + +class TaskPanel: + def __init__(self): + self.ui = Paths.modulePath() + "/tankCreateTank/TaskPanel.ui" + + def accept(self): + # Create new ship instance + obj = App.ActiveDocument.addObject("Part::FeaturePython","Tank") + ShipTank(obj, self.solid, self.form.level.value(), self.form.dens.value()) + if not obj.IsShipTank: + msg = Translator.translate("Tank has not been created.\n") + App.Console.PrintError(msg) + ViewProviderShipTank(obj.ViewObject) + App.ActiveDocument.recompute() + 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.level = form.findChild(QtGui.QDoubleSpinBox, "Level") + form.dens = form.findChild(QtGui.QDoubleSpinBox, "Density") + self.form = form + # Initial values + if self.initValues(): + return True + self.retranslateUi() + # Connect Signals and Slots + QtCore.QObject.connect(form.level, QtCore.SIGNAL("valueChanged(double)"), self.onLevel) + QtCore.QObject.connect(form.dens , QtCore.SIGNAL("valueChanged(double)"), self.onDens) + + 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): + """ Get selected geometry. + @return False if sucessfully find valid geometry. + """ + self.solid = None + solids = [] + selObjs = Gui.Selection.getSelection() + if not selObjs: + msg = Translator.translate("Tank objects can only be created on top of structure geometry (no object selected).\n") + App.Console.PrintError(msg) + msg = Translator.translate("Please create a tank geometry before using this tool.\n") + App.Console.PrintError(msg) + return True + for i in range(0, len(selObjs)): + solid = selObjs[i] + if solid.isDerivedFrom('Part::Feature'): + # Get shape + shape = solid.Shape + if not shape: + continue + solid = shape + if not solid.isDerivedFrom('Part::TopoShape'): + return None + # Get shells + shells = solid.Shells + if not shells: + continue + # Build solids + for s in shells: + solids.append(Part.Solid(s)) + if not solids: + msg = Translator.translate("Ship objects can only be created on top of structure geometry (no solids can't be computed).\n") + App.Console.PrintError(msg) + msg = Translator.translate("Please create or download a tank geometry before using this tool\n") + App.Console.PrintError(msg) + return True + self.solid = Part.CompSolid(solids) + 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 tank")) + name = Translator.translate("Filling level") + " (\%)" + self.form.findChild(QtGui.QLabel, "LevelLabel").setText(name) + name = '\n' + name = name + Translator.translate("Density") + name = name + '(kg/m3)' + self.form.findChild(QtGui.QLabel, "DensityLabel").setText(name) + + def onLevel(self, value): + """ Method called when tank filling level has been modified. + @param value Changed value. + """ + pass + + def onDens(self, value): + """ Method called when fluid density has been modified. + @param value Changed value. + """ + pass + +def createTask(): + panel = TaskPanel() + Gui.Control.showDialog(panel) + if panel.setupUi(): + Gui.Control.closeDialog(panel) + return None + return panel diff --git a/src/Mod/Ship/tankCreateTank/TaskPanel.ui b/src/Mod/Ship/tankCreateTank/TaskPanel.ui new file mode 100644 index 0000000000..635af00900 --- /dev/null +++ b/src/Mod/Ship/tankCreateTank/TaskPanel.ui @@ -0,0 +1,141 @@ + + + TaskPanel + + + + 0 + 0 + 260 + 180 + + + + Create new ship tank + + + + + + + + + 240 + 160 + + + + Fluid + + + false + + + + + 0 + 20 + 241 + 141 + + + + + 6 + + + QLayout::SetDefaultConstraint + + + + + QLayout::SetDefaultConstraint + + + 10 + + + 0 + + + 10 + + + 0 + + + + + Filling level (%) + + + + + + + 1 + + + 100.000000000000000 + + + 1.000000000000000 + + + + + + + + + 10 + + + 0 + + + 10 + + + 0 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Density (kg/m<span style=" vertical-align:super;">3</span>)</p></body></html> + + + + + + + 1 + + + 1000000.000000000000000 + + + 10.000000000000000 + + + 998.000000000000000 + + + + + + + + + + + + + + + + diff --git a/src/Mod/Ship/tankCreateTank/__init__.py b/src/Mod/Ship/tankCreateTank/__init__.py new file mode 100644 index 0000000000..cbfb57d75d --- /dev/null +++ b/src/Mod/Ship/tankCreateTank/__init__.py @@ -0,0 +1,36 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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() From cb418f02b1be6fb0ee0de9741c39d4ace5c09d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Mon, 14 May 2012 14:06:07 +0200 Subject: [PATCH 280/351] Added tool to setup ship weights (structural based) --- src/Mod/Ship/CMakeLists.txt | 18 +- src/Mod/Ship/Icons/Weight.png | Bin 0 -> 7327 bytes src/Mod/Ship/Icons/Weight.xcf | Bin 0 -> 32353 bytes src/Mod/Ship/Icons/Weight.xpm | 721 +++++++++++++++++++++++++ src/Mod/Ship/InitGui.py | 4 +- src/Mod/Ship/Instance.py | 41 +- src/Mod/Ship/Makefile.am | 6 + src/Mod/Ship/ShipGui.py | 13 + src/Mod/Ship/shipHydrostatics/Tools.py | 2 +- src/Mod/Ship/tankWeights/TaskPanel.py | 212 ++++++++ src/Mod/Ship/tankWeights/TaskPanel.ui | 97 ++++ src/Mod/Ship/tankWeights/__init__.py | 36 ++ 12 files changed, 1145 insertions(+), 5 deletions(-) create mode 100644 src/Mod/Ship/Icons/Weight.png create mode 100644 src/Mod/Ship/Icons/Weight.xcf create mode 100644 src/Mod/Ship/Icons/Weight.xpm create mode 100644 src/Mod/Ship/tankWeights/TaskPanel.py create mode 100644 src/Mod/Ship/tankWeights/TaskPanel.ui create mode 100644 src/Mod/Ship/tankWeights/__init__.py diff --git a/src/Mod/Ship/CMakeLists.txt b/src/Mod/Ship/CMakeLists.txt index a362a0c6a6..a3c14ce960 100644 --- a/src/Mod/Ship/CMakeLists.txt +++ b/src/Mod/Ship/CMakeLists.txt @@ -33,6 +33,9 @@ SET(ShipIcons_SRCS Icons/ReparametrizeIco.xpm Icons/Ship.xcf Icons/Ship.xpm + Icons/Weight.png + Icons/Weight.xcf + Icons/Weight.xpm Icons/Tank.png Icons/Tank.xcf Icons/Tank.xpm @@ -96,6 +99,13 @@ SET(ShipUtils_SRCS ) SOURCE_GROUP("shiputils" FILES ${ShipUtils_SRCS}) +SET(ShipWeights_SRCS + tankWeights/__init__.py + tankWeights/TaskPanel.py + tankWeights/TaskPanel.ui +) +SOURCE_GROUP("shipweights" FILES ${ShipWeights_SRCS}) + SET(ShipCreateTank_SRCS tankCreateTank/__init__.py tankCreateTank/TaskPanel.py @@ -103,7 +113,7 @@ SET(ShipCreateTank_SRCS ) SOURCE_GROUP("shipcreatetank" FILES ${ShipCreateTank_SRCS}) -SET(all_files ${ShipMain_SRCS} ${ShipIcons_SRCS} ${ShipExamples_SRCS} ${ShipLoadExample_SRCS} ${ShipCreateShip_SRCS} ${ShipOutlineDraw_SRCS} ${ShipAreasCurve_SRCS} ${ShipHydrostatics_SRCS} ${ShipUtils_SRCS} ${ShipCreateTank_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}) ADD_CUSTOM_TARGET(Ship ALL SOURCES ${all_files} @@ -159,6 +169,12 @@ INSTALL( DESTINATION Mod/Ship/shipUtils ) +INSTALL( + FILES + ${ShipWeights_SRCS} + DESTINATION + Mod/Ship/tankWeights +) INSTALL( FILES ${ShipCreateTank_SRCS} diff --git a/src/Mod/Ship/Icons/Weight.png b/src/Mod/Ship/Icons/Weight.png new file mode 100644 index 0000000000000000000000000000000000000000..b613fa569e1ba8860e75b14b7ae9f17fcd46dd34 GIT binary patch literal 7327 zcmbt(`KRC2F1Smy=6eyv%LkUnqf#T4j#frOA+%*)3 z;QaXh0ne*vcJ4WI&+Lnxoilgt-Tkbitx5={1p@#8LbcaQdQS}dU*KXt;U5|6!6yPj z^;8uA6(jU}PYJe-hN=>v_J8Y@fpgcBg6Hwt1PTD)ll?D%fUF$qClSY6O-mVP5sL_q zTGZ5SPvJ?T@m4nWR&;lDwRiIdD0ZiqwJRHa9|fJE54Z%jb&1$E8kCJs_do#5uU7{^!i{3i3Q>GI!&@ zd`@Y{Bln~G-zW=|$!L>HUg}%Z_sIVTWR56=s1rBa^(Wy2&9SY3Bthf}a{va)RU^y; z;9B+3zlY_?a*(EQ<~40- z*-YI|1~^U+xzNoyJBi1cWTL!(4~Unq!ePT#@}Pm?PgaJUz%5si>Ho#VglRDPt%kCH zN1;Wa^G;%hf0$P>pl^D6M`h@S2mqtF0(HA^%fPn`H&QTHS^slYD%^euCjQRwEr*I~ z{OZN*BY=e#``FGISd?HMG(2qtIClqBt+t$boc6P0B(PKQng*&>LLcv=WCKAF@Rh(b zf#AzUXu|RHppU)x=tnEbV58~tsr`LDmQI{e35;6DQS4fnGWPAubY<*JtXhY!5yUwU zKm$XpEL{sp3*PoR1DF%`S2L2ey2)*YjAxy)R}<^}_bmu0f7{(DqPCBiIZXe}*YFrF z1B0&%T;pifiOlA*dUcriamg85Sw>KxkfXFl+lhZQU zVD#Y<6*F5bB^Z`&8B7yJ+=d6b545w}bT@-YTzIrI!`PRfF8IHXTNF8-H#88dXY#po zzXQ;dASrAsVmwORO(Bv-fp(SEpR@n{*-iXYTnvKAYuaYc^ye9J8!bo5ZQ0C}nPj~B zz~?ZW^(l!oA>xLaIW~^56_1fjZ+!@mjBILo$z!1R@ zfM%eV^yaV%s}=-+N^#xW?!}0hWMYGEFV|K>F{lI377&u+0<*)`+rwtT;jIP}*mI4v zzD+6SX9q`Db=Ak=5vP+owz!Z4`JMuN)l<%skO(=pEoaT%m=qMbT^7KpTIQO%^ZwP* zcUe5FjJ{9b8#t<0*=2KzKe3)|+9zU0n3JbaSquqY+D)Kh3@miG;OqQYDry`IYFmMc zUjG?BK1n`hLK&qQ{gXPC4Nn#wrh=}TLlYLa> zhXOP3m+Okkq&Dz;{mo`4+|(SGnT=WA8>BY`)x-UazmbA9&P$F}1tZy~2g);o*Ywsv{DHRT+q4rqo>DJXsBotH(PXmOFFDj6$PU+9u<&&fp{$egz@F|S z4T0Kg4e}Ia4SXspTTM(|;!{B#IC9kbQ9Q{j!dZZo8y^nvKT+oYRX7E0RgvuFfN&#Y zV?wW>4%oU_1>iyV7Ee97)1iJZ5lpM`g6^P9kC>unW6jS+hBO;ZuZA7oPMq{CQT_Qk z#IH=o5QNnbKFZ&deHQQZV#%b)X1iOD=;k8_N3ky};^Dl}@1ZROJCkigiW3Z>7Tv?o zLq3wZfwbq%k{={pQ!8cPhKqLtvCa^|eZGRoGGiSTAydcTnLLT44cz|xd|gaZ82m=P z)$;ROtE>hXQX?Hq5?ZWK)zxwEoGjz6T5NczyD%*Ev#1Q>?7IIhDugN-e`|7b$5Uuh z$YIFm;dfOhuv_%?UE_m^&RyT?fkP5JHmftkt%~8oqw^r; zL+I+GpcM8_O`p@b7U(v;VOaUzW^x8z_sFkd=>(@lI#)@eDo1mpEFZj%B7{ZB z$^hiEtihg%B-VuSN;xl6!s>-u9K%xxGuFKW<v>i z*JR2p%0@_ALOry*8Ukc2dVG->)6HF^`Ek^Ay$P+f%@Zv;`ZoH<3HI zx&Zq{V9v+wOusF3CF}(*p=LBl$8ak_<&U%0QBfhi`@YCJ1XhlR0*F@GWe z1#Mp73zJK}Z$6&jRC2leDFQj=rDVzP93R6$TRZs#LVu*IBy)9iu`;>%RwL=$qK6Rb zGjiRNJze`*azhZA=5e|n!=~f+-1cMni{`l(o9Z2CbJ^0qfwXI}g;UY-@ z8rW_4n&68lMA-q1&rCREh1EGWmXLEy3A5Q7`WW)zzyAU&TY+RXL{m2cfc09L)hrVV ztY17YaVQ)e#TACtXiwV5K0%R%Fce^9{clqDP%J_;w39I~ZFH^AGsl0wM8abg@B&0Q zk^{J9>Oe>&^*D?PrGHCk^cM7fS^FXl?mEy(p`izURk;19#46eJ*T{|Qu(XIh2L8)J z3+%=S((loNT=CSPekcoOjJ2y8#6E0Y$p<)?&Y#W|84^1GN#mTn)}(mB#-aITQ_k+1 z zyGW5qqKuxIPAJ6WcHR!SC_X&khz(~%-RV(OU~dl~Vg@-k{biKts5Z6dgzyZcsEsS)@w)Shj6v^=urqg{YoSW(5`m{zg?aSD-E`+8+E}mTIspe(Qnd*EnsxO#+pnKO#su zhcbkb`^_vQLm7gsg)zP3gt2fflb`-Sb;=yHvPOw;k?X32s}en9ItEU?{0q7rIGFIw*LIV+ahVaKRnUPym&m1IvCMaKS50bBGU@dTo8LgCqqGJ&;Z3J$>3f*X}m6oW=gC2Wv zUwkccx%2l9Of~ycLN2a~e55|swI~hdX99u_BRMbKNY<`6bzyd{ASXlo62A zGze8;QcAeFZE~(eRd8U=0_kny><80)T6*f+?p>iwgYKrw7rDkF#Bu_uM8BGNN#9Ur z&cKQ*$Uf<@q(qpmR=!&VE62@YE&8Lxkt_vem zA5^ky>U;Wj$RHp{Fk4SL!mu6!ZL$Z)D!P=y7tb7ucFIN)P&ZV zvA9&nkm7JDu#)}*zFaX3eAO2vYd*T-IK^apXV8<10(P;vHrcn3hI;=Y{7UjNyNS=J z46oyKOZ;MSxUk)%(jtxLKi=ew)!&YHg?2>389r+HMGx{-UlN|?1*=Q7+TLz3eJxgA zjGSTW4@bREaA0WW$7D_S{VwhKXFQ8rgWGZNkd+|xw6Dg4I9gj|srJ2o`8+$YCsB)4 zx{UOP5c*wdqf~swasQB=`rB&kp8c-3i) zFXZy_r+GPWvRM+91mp2`-mSLY{_6A8hvj{W5FU}z_guA6%u#W(xajQ=^<@ltkhf6% zmnS$oHO|`!FbI!v7yCDiu^UOgnG+5+>E05+B)tFZ!u2JO&XOPvymPS7MywP;L&3m= zU*-GnU*iT&BZ0=&`dSvp#;AJGZ;Prf{1z(C<`VKiAvO{qk}7{gd*%z`fQRM-PN>b< zHIE0qP#q@T$(9liLYvAfflO|iGa8ib1nX*E~3o| zp4BkC-}mQzeYh$rV!l!i)BDp~8b0^8{cRt*0a+th+_cT&#LSWoqZsTW$iZLQ zp(Lp1#^e15SCDv$zl2$H~`D8o3 zSgo&WVLzQ`e23rI;T!!p_&llHP?fY6B|!h#`pvUaM}<%o@optE16&-wNSH-4ql6Q; zz}fDHkX@sImD^=1)vPO1BC};fE~r6Jjy0;!>yn|(e<=VyJAX^fYhSY4@uc@Ymhz_SqV#4dlA@W zoP+vrGukLa+7Ra%ZGdoee_n`Kcfyjdxw^3P`tAr(v(s>v=*#oEmT;@3F`Zs#0zyLTcT13&a=OkY zAC&(Yabz(K_nf>htR{-oQ`@}cy)6s1a2LtWE~vCx^ix}CV)^mv;gXOwIKlTZmPYuC zWt7di@iU7zK*a{iSE%kiTI?Cgu<+AG&t8TvQ7f&!<%8nn_R{K2%?qbAcEsW$3h^C# z-^Y~E5^0_vBvb5Dp(JFXzpvKeB>0dQI>6GTtNzc7f=dFe>(333cKr~@(7k=@nM~f5 zG5%inzPu~PfAgY2(nqfKOEdRpbE5F3YM-oe6va{%=hq!czY)TUEXB~hXci@u6bV?M z#?yA_mI|8lnPHM}Fm34!pU5{n*Z8_^xsLlb8Wg+W?k-3*cDvbjQuSd(lrwa#O2!M)d7{`VZ&g@bi@M3x*G8yssH}>_rl- zHhLUpJf}-jBU_%;eA|vtFSjbYjM`2`EomaZ3v5AfgVP`bj++IhboNg#7M54HXH>EL z*nQ2G(1pb5Fl=d2reU#G*J7GtLcO=l(H*5>FHTPR2H*Acm)tcYR^W#vON4Y{#R+_i zy**#(0s!q{%X7omq3U;XJj^bbevN((Jh>PczEFxpy40OyCF>jG$8ovQZ({DtJSD7K zV{}nvD+LZA*_P431-0)BO(h-mp9q=V{Ot0HyU|d6{n4+5LXxuPe27WT^s&mahU@L^ z2f4o!$EVT_B)^=@rT0j^E;4n>5C|VTnejFpc}#pNz9Dy!#=Droy$l{XijR-tM6Kfz zSr)X|GSN)Yea~6NUv%qLjkdv=Mpi$1iM37kGZu~?eDpW^Bc~P-VE)r-T96aAE#&Pt zFZFYXumfi2Ta%I~zf@mt<6s2Q+h+eL_R~%_1BL-b>WGPKx0$%8h~|!% z`-TqG2eYu$#?{PVx@a|_82V+h^x3eD9ZLK zzym~g=XvVBN*WuZwrL0|4uy0pY!=as+xI_@c{YvO4PZKj(c~|x`f2i6p=Mn3RnuUy zcWW1sB>SKvyh7`n?|3Jta?v&er?6-#koNBgWm*MBC!x<RQ3sfyiLSHFE=;d zcCPq+BYtaf{jw2f#_Fdx?e`fHCvbLii*DijXskxgZM>_Z-kZf8nRH9}+IJ@`{%^ol zt_xz%Ku=BY&r@XP-#K(|z!vk_&(BwWZSNg&v)LS2h~RLfAl#UVc*Cr-TtTd*7suv1 zOw2?&HQ$+F@5n;}J#`(ic6UL(2Y++d z-~u?w1M9e1H#Yk?q|?rpJC23F8iFCL=P80*&(bBHpTAHw`-XinCTxyki(@a3Kw&WC zn30jzX4p)uY|%hrd)pw-eO9ui!D0nzb$ZaLSznhGYTe)h1NojeUivb_+;`62+W?%v zrTK95p>5ERf2+~QQNtDH|IYgD;2w_h=d5b>aTWdC`L*>M5v#DJ;27!aNLT2$`MRTe zdmJbBnxC{ckPXSZypqkyi#(36B^qQpi*WYW`wSZE4rJNaN{y5S$2>!fic^+J&mdCQ zQ^^gRNgB{04{tDp4su4WRqV?jz2G^IP8{&chY54?S~D_{i)8ch`C5_c|0}off6eXu zR_zY8szZz@# zouVoOi_-?S)}FnhnXN+f|G2Z=5P?h$S7pwkdaAA~m)piVJWw>duXAY@2^Ui>cG*2d z1(PqpNXaV0hKMe&TNhxScRQOFkJTX`WkqA+Hkxpnxny6wF0CwPyj}l|^mEIrPO4&l ztk)+Sl_B@eW;f(og34@eVz7{-_{=@Wg-%f~@f%(T?q+_ztRMHxh)5b1u_2niV z^Q_y2xe4C{wa0TbRhg}9wIR2Db%Ynd=q$e{24m(>cvx82`Qp0-BDQA{Wp%`KeAT}&i zx~3=N51~S5X97Ovkq zl88VogJvatm(Oa$cv(}34zZQh>>fAY&Y|N~wr+K+31%rJ0?uEF#+pH0TsUT|03C{~ zXr%|W=5*1eG&3&jU0TM{m)#-fbO*HFfNh-@S`eiUoNzh{*hEMP+ z?LVYVNA6UTKQfDGm6>#V(@NW}q(PUBZKM~vr&!-PMH9h7ox_X;Ca!3Uxq%)Rms zVrfB%KkP`h&R*%Yd0@tYf*H1f&ItbH9k_ttsqo%sAI{7KTn&p%$7kx>CeAJYR{mmka0 zXj1yp6M{|(;-^KaRw7sz>t17+-ZzMqvO&4<@@3+pC3OqwaLcS=NFzRE zDc7`Yk)%pJ&(;8Q!w^%p;BoO6CuiFDB5YNGC_dKI1@{5?w>?8wY@>#uf>ItX<RLZ;|~~!I39h zR{>m}P2z|zY7p`3$@px362PpnsMbw1x5P!}5IsqXxS1d0Zp42F!M-80c4L259)s(C zr(||)K9#~PS1d5~7>lw#G5c zDW6!K>_{pXh*WbgwaLo=aEfx)!r804DzBSR=l=f(O~LDsfKMQqaib#O(^nxtO<7y1 JLcuER{{W=4{qg_+ literal 0 HcmV?d00001 diff --git a/src/Mod/Ship/Icons/Weight.xcf b/src/Mod/Ship/Icons/Weight.xcf new file mode 100644 index 0000000000000000000000000000000000000000..e10ea8e991301b56e4a9a30104fe9db7056c8776 GIT binary patch literal 32353 zcmeI4dvG1sec$&y7NjYWB1MT5Bw3;!*25O{umwrB<5;|nlQfMpY0@-y8xQe*kRSl! z4Zd(e5`2>&2=E0y01zO+_p_~AYdldi({?6pnm98}{|d*G$xPxrT3Z$g;O^eN{eFLE z_u^hzN<6I{J5z&P+#hz&p7T5B?4JGX_jk^%YuM1Ts=KOoRc%9KjfbCfywP5UO)30Z zj%{J;u;+2Z&qLTOw(nwF5!+0+66d%Sp7$*NUhU*#?RWW^`ux=0x37NZo3M4Ez2>Ortr^8$q$#jyk8acOm{t-2DcNS@TO@`c~@e=e`457ukou@k;9V zzJ``Snt59n+Nr^nznJ=~zm$BO{f$?ckF)nrz%Fv-GuVN{^1Ha@ZeX8Uv;W+8Qvb32 zYfMvUr;faQAobU>UlrK8$lkMmBK2pIvr5g|y3k(pE6C^HiHoYh)&+KvyPuZqKFr-o zarc+M@yeP=YN^*0*r~l}mEV*WRRy*#viG2M|Lo-h%qKN(!`=LTz2-~bYEOOrOW%^R z=Iz4$Mee@#k?xL27RSHztu@$SYknqn>S+7dQXl_TJJS@{y2xgge%-a4RKwY>O0m7> zpSOQ)O?KrkN?G%^F4$k>?yE>Re=$4?JGm}*!d9u>X)pCJn8edRU?&~TG|qNu5_<^y z|2EBYRcZ)#``^+;K1Z{GpVnv3i#`6R)VK3C z(iGT#nD*BEew=3B)~Q1KDAGS3r{z{s7 zGi;SYL#O`gZ6?yGLu0VZoqeXx$+tcK{4_hP=U{+ z|9%^`NwFR4ME)q?t&k9)kU)I6duuCALZ}PkX7VH2=`4 z<=DSL_7}NQJd)mr1c@uZ0b8XWeb-AZf1BsQl>(dDtxR)2ipkrq7`NZK^PRy-;d-W|V!q$>4sWPwh?k1n!TVgK{8U!~@4U0@g0=1obOTnB~4us2m|Gni(z zJQa13{U})E!59GMZFEq6e^D{TBUfQDXbKc_0bcKXm%ixKWi-ehny{~8|A91ZmAd*a zxL0fpkVrEuc2P0R45!I&&nqnEGuWp%sHFyl6?Ezq3?ql620C>RsL~XV!_(Nm!*NFH zUEs`s*hR&>E(Ls8F}$sS$H?xq8}8S%V-!2#(!c$0VB;9meDN=l^(n`#?_x)4Tt>R0 zV(9aS*XC2$uTp=4+Kk4Y{vo^`5tP-b+u4<=<8f^+k9nz+E}zsy>N}~CA1tPLR4Qz= z7p0j00q-36>(qZmyPt})yA9j*0s0U2(KHX})EU^v#4f50o94r7!@EVL?s{Ho%B4yD z1?)4i{YS9Rimg)r3HD@~f9TXVU|*(LeBZn(yOO>s98GXzqL^=`lhbtSKO>8CF1=i7 zcxFnPW7t0)@81SHaqE|vKJC&x1KXw7YeLv@?bqyrJtF6-H7~%PaQVEAD>`*W?8OCd zV;?=3V4%g7G>fx#r+J!AmB2no6E^SuLuuNIcYD6E(8#=h@KadIM~@|sOAZ_vYk3lK z{uu1_&R+B9u=~VTYcjC+r1^(VErfko_7|4&(L>3jNb5!;Ui-{p6>>;yj@^~A-;LwW zcH_9S3rqRvk>nBNp;92BJa`n^Y%y1&8#|NI=l2(u^3emy3Mpk1a*HqMRH3~Q`~PKJ zmw8*K=Iz2#UYC?weisi{i=~vWBRAfIY%yGGe9DR451ZEq>)Q=G&WC-N;?tqH_dj|V z;oYJ57Loeba+Xg07ufD$q z{KM4+f8z)5tJsfc34ZRIzbpCYhdx9M_N&yt#W|mJX~cFdu2Yw=|3sPx@S30Y_&0uZ zsuTO)Nz;B9hkgm4i|ZiwtgdR_u%V_&u0w^L5B`(Znu_+C>Q!A0?e(jE>7Rc2*LliP zN!qZXqON9jU28)%_aU|NUTACYX{=e**4)@o{otPw}a2hxljtZ$R<-isyZGf#)?1CwuYv3)tSm#@4m#>*R{# zWn!`Au<^pA&EpvM#KwoWsKDke!ZiH3A6sJc22Jb-U^B0$uzeC6{Ky}BD7ODMKH2^7 zGw##&n(p@1jTJpLa=*a`^>Z(9->RqK>eFb6+U6$w@v9A$HLVrx4b4rfzTDi@yeie) zSe+bQ-PW+FX4UHjZO?OLuWPNAhVGh1HgtVMQ#<>qN1DB&qrI7Xl0R{*qOqZ(4H_ZR zHdZv%b>Mni^>j_!>Y6qdR$0+jv%0#WwWdlOX>4!B&JSL2`Cj}%gV)Nsj<)uO+MZR7 zHMQ-`vblTphUV%TD4yLlyn?x-tDzd#{u^&4SEt)sU(--m-@dBsjpE&MDJ3;TvnD?e z<9d*vU%+qnKl$}6<v3CqN00Smm6obeXO-^_%W`Pj$In8`xe$={O6$FOq&wuij? za*Oiz{ki%5h4x~}(4}8MFHFG>=QaN+*uO0RkF`HVoq65 zUhmsQ8#?r9Y>%^N@v{Znm$30J_rF}x)`m~-$2kmWb% z$TH9SN>IH2k=35}CZ1!zwF<{L#CVT+rE9b0Ys+=Hu81nVN4ynlRr&1N@`?)luQZiW z6(Rs;?PIs?t?bPkhz#hpD{dRuw{Du7>PB=OyVTm{*foP)H*egye&f2j9$veC4MUV( zyX3Z(wEAYqBj&okrmwE>vTMt4FSwn(b^DgSrEi)W0ghe2X0FX#y>|7=75vA^s-on! zx)n&S`i8x3uBog36@6JWkrpix&|1(A7F$qDBJ$vcBYBR2TGgG=;;eCPQzoU(+bjqC|5kd-2jm zb5UPV)Be;$o~oU@cJh6E9!E1^>tUT z=qn|cXD?kuF7QBKut;OhtI1$ua&iKRRDDDj=Pq5obn()qiyFSnOkcP#H9b8wb>5yg zOgJ%dPMt&2hU_{PXD%8P&FW8-6^qhp8$WgFMSAw8X)nx4{A>byT`CbH+oky$v7L~1NMIyS0C)!Aj9+7LBP z>*>rCGCV(7GKnJ1x$OA4aW$^T%xL!P=vj4EpFzSVHDyt~468SB&YrVKphjnr;OrUv zS7*%WW!`L43;aR~HIX?tfq&y>+#nx&)}GO)&8cX_d%)8z77p9-a7^4VXMLQjPGv_< zjhK<>BvPo2b39kv$co1r-ri$5XHK6vefpF+rAM+SM^37f=EPD@wff`H*eHupXR=73 zk=@@SyOERle}ex`96x^SxVOYpZBaWKz>EgsxH=P_MwaTdK4nG%WO(v~J)w@z9Xo#P z*wLd*-yV)4rH22}=~F&Zsgorq^l@{{996?hJl(g>Xy)2H|^_D92Kb6g+G9zAx{9F2yD%#c134SI_`)n!hpk?7QjLMgr^GRUW7NFC9G z>hNMu_sBtuLJVB+kA}lTJYO9t!ErT!EHj&hxL#>VsKOslpInA@AuS}?AGJQj8w)B88~54NN{N2 z(4m9opgxe@e*p2p%+_s3(OT-Lj~e?&lw@xXg$EBEJYWy#{c7KRp4yh}WeEnkm_dEm z4BVAm4jwvm;NSsuU~d0`1N-;w-)Htkdx2M~7tNyS@8FR^HR!`5|ByzBYJYeD$@D(G zH@j!=9<}E_Z?-SZTDf{9>EPLZwLgobYMR0`Gr;ikVUzEnfL+zg1b6`JPP34<|H3<55 z_4n^IJF`1>?m$hp-|O4n*OyM?f3NCA)_W8(R&o1fcJJAP>Zn~=oTdAfoTYcz?Yd8= zO|RLu(6jK;hYz;@9%`~<$Ik6Lc5J5?CLQ%|v)lC6XbYZ~dcT3Ic9-rqJM9j$UG>?t zMFw^&E~Cv%p$>$*rL6fj$!_1V-Jr^8rqz zovI`11V`fHN43!`YTIlt(r%UFEsEDYez)$jow`G}`(7|~1l?g!y4vb*QJb@ySnh03 zcXtoAF5Q*w?CNB$ciTJK+uQiB4XU>q$`1E#(>N()-fD~8{2tES)U&CFC&HJch%C;~ zZMrquh|_}MqwvLSWkc9a1`T1w<*>7(qusWvwxG4GwRNM}s9I3QvEb;|En7C*%?b`7 zZ|1DK6@0fHs(nG5YPB0pi)u#F;|jh9;(_T2yWxT9($W?ks>8JFwhS`f*t$_~%(iT7 zLGI1E38$S1Hq&L(qtPU@sA*>h{ww5e+p;)AwVI6J%$SSd!**3Hz`)q399QCDNO zzHauL^ac&TqsH}WyP?-gRW*-!kFO1c_f$nG@GmT1yS7}F+X_?p2*~eI zke|M}5-j(~?eG?8Ox>KjLC$mJw@fI`+)_8Q*h@|$A}+oifbDMG)PiE>S_l*)(v^Qq zlB-)}w1nIMkQKg^qHdG`^R&=h40+_k%nboc2aozn2tK^5z=4^|fTc^Axe``YCVpKP z{$wVZD*!ZNmA({`suZZ|Ax~F-_a;g7`ZWL^C=O{1*ii|;X&|1%CO}>d8PWm|?d9Oo zWuTh|RGDcj02uOAvSS8t32ajUvH)y%VcGz>^!X5EL$IsM){_!Rm@~+N_{Ss}&=x3) zxD^oq!}IRpNKkN>TPHRx41tGxI z#>a8;o;hoT^@y?-)My+r65%ussna1~2B)iLx~7CH9i$S|^q565i)2~gjy{EAS~8?X zCMg-ukoQK<8UT|oz@<+jr;P?>`%*xj#w<9Cn6%WxZ~zo_nXA#6vpD|@A<#cP3!FLy zzykwj!8;n*79A@jJbgBcq`1#cho?YbBs_i6p0EI?2fVPoWAv;KPZC^o=w?Af>Zk_T z-Nl&XaFclG=u{&EmZeT)1+PNll?4X|ps*nUICaJXa~+)OlfPQ6(6thW(-F$RH`rAJCw# z=l~#3Z;6f{bIhtyt{J*3EO}&b@bKVa@?2JcDm(~Q(g&jbI0cWWV@EaWoq(qr43PNn zfI+tRK!;3w@W6h5|9xJtt#{keVKtnUy3I>K?T_K0abcWw3`swHy8V;B&U)?SrjL%nWv_^;64Bt5ey2S>YLq;4B;ev zG(g}PI(dL>>R?jOlcEq4&dF@w;p#+Ev;b7Q&llj-AfaFJ>3t321>I1%vP-hBXCwAG&7YIgvJ+tqLT ztz?2$7PKVI=xt^zxO88%U*Ol|b2Gruuy6bJKGT;Wzx8e-7n&{6W?&&&1Gzc^wf#QW zlLeEFNGt{z0vyDZ662uW5uoeVDpG8IZ z4zd+s7H!>P0YVO2G+-#|LL?a1?+(2~16xDlGU1mFkRORz_XsRtAutZ855xl4n;AGf z2uB1u%k$nY@`HJN0xcuvQ?5qdI)>p+<)UeZ2zX1YRQmt9!DNGwDWk2$vBP z)sWz>YuOO4AZLe)rbop%q&jE2I>=8Q?IbQR=ukL}7G`I#`CNJ>1t{>A>ZJRit=V>* zLb4Qa0sny%=Rk^%aan0ctwcK0;UjO;syBuJImA9N6iCbH%|4nuK{LN|uEXU@%JPY3 z;2__vh>JvS)9%9`wJ`(d1Qh&JG2U-(cp*m_;} zy*wYb3CL^Evu!p_283wV&jLHio%JR4VI5McS`9udT^p6JRnP@viE!oGl5$g_V>~ps zjNsu)NPX&NaO>ucn>X^pV1kFy%^Us=1*y)_p%1Df0Fu+FA1=bV`sM=2i4XzxRYk_T z3}DPwl;5^EW^QVvj%7K86chp<_P!4p@HUu~!XpdK#_&gKQ$Q|#F(MwSDyJeEqo zdFqI@?>oS}3JhgFRPFSIIWQNMy#($=Ce(HMss@MZOBP8S)qwyZ{yBJ36U)79eS>78 zE@m7_Dk;mJ*C0EBVF0Wriq477NMAI3A^G_@ZX6P#i{-!@ ze|V!hKk0~+v{?ccRFuX5U+PqF8oVar-|WOBiI7Za#uF{l354oY222O4Q$mIcMX2%M z+?Ys!pjWUfn2b^)wKmcm#Xl`xP^z3S5N~lKAq6)B2(yk1@jg5jAQMWOKuuz#0f$m| zR3k<-wJeZH0}t``I*J5m&*%gn33Ucsg^}!7hN>EQi3%VF>rTng2PIlK6@btPRX#|P zk{Cq9E?=PV9_2`$8U1o0}EMs;@f_)I6&=eZ}-*rw3oKkJfIDyScbr$H; z-_J8ZAmCVvjaH~r?Nj@seS0kcECfvMGO-A!b^;K0?4&%Hc;Fb6pc?JnV<8b52x|%` z6+-1A(e;C6jW`1c_zDsBK6D7N*LX zudxvz1m_XXv=EnpHmJ5N@Iq*mC|N-rWL|1Vc4s2!DdY)?gQ8cg6tY}$D)mk$)MfFC zK&F`^27&fOGy}Nda-=k>cFsVY+nLZy?F=RnQbrQLe zV-y6v?rvm?D;W}|j+=$jq()8_(j-Nz*)C{wU^*~hED;(>snLMqrA6Y<@hG)Ks%_bh zL?6^ZMUzKMq9W4-(6+idEl5id{EjI2=c81;B@kg!ZwkPlq)#J~8CeLV5)$A@eHq;Q zpgskpq$V1GR-M8|e9Is$5XC^!QmxsIt&|dnRe?MjQutJG#B|?mEsA(nu#d{% zJq&ti{4LU4D)z^AXLv$arxwm~vYctP07W4!s)P}_Rc*qnX%9&A^Oy2Xd;Czv&_651H~l8i}1WW+g$gH50; z-I!fZQIXVVyNoEZ-)n;>4xRwQ%s7DejuB0xKM#CRW zbaTxBP3>hP7NjTEXCOgJEeOTAl_i+HrYj;_VGA9FY;#(!(00kC3~?o3w~nR)X2 zE@&(fUFNPv5&I>E*)tOP?e1ZA)HoSc&Ww)nCs+Y^-J)aNq#oj*^~2O27khM8AG#}`CK4Sehw<5%Nfcx-bpR!USIxmWcnlRUPT~T`1SSQ@ z(ESKh6Moe}fEOdP^vCS=fhz_$rFVuq1_p3EI(Wc{yho{wGFzs97v((#DkJqA9z>!* zqS!9xd=H^j#5*aLk=?#4XhJyJ-j_ze8VV@@4_L;aG6Sau3`6S3Fac>y^+FCsGCFL8 zo=ks+1jD$l6TuWh!F`adTu?Lvj2=D;pneaPW2jXk!3-=jqU-l*W(hzcm*H|Ic{}g) z&Y8S-76KKCOapoXghm+~#YBPQ&|QH~P$?mk888_owImAbv>-}#`UHemvqlPHjxWyHu(Y zflC6Ar$6Sga3_J?-3(+Q-yk#6nJfG zoeYB-us3pnR40yENP&PKrZNDNS%67f>)0rgiCAag7i2(I!9ZZrgg^*yBna(<9X{N{ zmho|Byk!$(vpSab7_@XqW!h|O0Ae7OgcxTbnMMwz7!Re7E=vkf1TQK|2s}jbgiV<&5C+jsCOVJ!eH1o1s$9qUk36ISM;ZNZN1WUO!-Q57CP1LZ)^#)L68uUfq zi^z!Z_H*;Bbw)ft?G^njO2Re>PyjhobC<5srtnerk2!xvp^ae}GJR#sK2N?kEi zUQv#Dfj4;udnBYXsL^&7QR4va)Ku$gNM=sfRyaznUPs-~)RrKvFG%aED!GR`+u3-p3-K5C)MF?n$9 z!^i_zj_iHxH#o(XKj!vHO4dRnwJCo}_C}n`h-RzK)>NY`RU6fy#;Pu4{Z;*AURVhi zZM6mBp%>v80`Ga8^C2ASYd#b@3;vpgezqR{4xV!%Z2wBgC~y)(HW1bz(Sq4H12F+Q zP9fy9JRh-C0XlUhVrW=j_Msj6fH^ajfs_W0Q_U+pd)dlv4JI>r5m2>&5wU+(;>f^5 z3UHiirzRp79_AYxLgx%Lb3)?+AXzf;&jQOR5EIreU?QKvnR@ar;Lsr%H9rMx%k!K9 zJ%&>fSLUR^2|$}5pBl5H(OJA>L0U~Xaz2~!F@xj!tbYb$4q0t-!cMSkI~LE6lR13d z4|#I{L9!qZ@eB+J==F-U7h zW=@WrK(s(qG<|GN=E-rE8Xu>GGcX`$(8Lq6k4$Kesue&@X5BIRY6Qc` za|!|%&_{#ApmObfz(Y2Kv`iBEC5Jh2jg#6KWz_qYcy>^f#Y2<}iFur7=hP}3XVCM2 z&>lj}OyQ;p&h8h%i=3x+N5nHF5H~BpDEgg|*r{^`f}28KBDm>YGr~HD4iVKfCLao< z1|l8meZgLUD6)0XXEB|QQBF*e8=#_!>M4+27VM@F;1$iyK_U?_KlRQ)H&TO$-BS}J z;xP>svSiAg1!e)u5Sm4hk25+ULV_esTr34G25%XYqynYW0Rq`WOocRRcL~I?U?=9+ z0kB-m()I@19MC1SO8HD9bn7HB&K?W4Y!#AY*w?3A)~BFbQHe@B(2H@30B8CmX6}Nb zZaSS~J%@$Vj?|VCObW#$T*!Wst5N*rnUmSrX zjUj*zFV&{VO%623xTI6H&kzfRVmJ*Ab5xMGo65(S86e`d>F157>kIR5w$^!*>s%i=H{X0GZXb|`U1F3QW3)}z{)hw ziB!k1DCf^H!Wq=#2?d&B)RM5~CjHHcl142p1lKhhpp5}ESwtg+*EAF>&aksk&@618M}`C#a74`vd8o#*maasQ@j9@{YzSm}p_LjtGE;Rv zU`AC303sp^far$tSWydbLWmFGq3Z}dS;0MDc*vHkn*ct^2L#CqE5H@$kv!<2i3Aqj zx_ujZCECThc2RX!AV~v~G;nCKz*iy#Y8+G55mC-U@lx zLs3<=fpfK}L7l44@JM}wYS8OSA+Q+`nYtQay$C7F0GBcs*FjPhD$63ut8h4rgBpkx zi)Q+wy%0Jy1|S;;C2Go{Z5lejpYz{VvZRMNNrLxZ8P zJfmeJ4snf1R>&)4kXIAvNOZ}(JcKAAwFMV1NSb672+&Coj3|T<<`~8aAQ~5&P>y5V z)grVRjo~20Fj3nq%2kum`3XHSi?IP`5~F051hGd0%`{GRD?aqO0EfrNEZ~l__QKPm zwE@iZ1Q$>6WQ8erLR6H#++;WeDSICB>^T$9spAn72Wc6BJT-#20Z7b_Q%PfF*Tq`x zNws;oH%Ivm|CO9&08z=*Wdm-e*n4?=ipe25Z`DR>90yp#lUno(~Oy;&h z0dq6E$Ud=>Mx^BOhx|GT9nUEv!MMq7BBsTl1yPUUAETgLdBMn~FA5XIFR&x=)a5+|4W z0#|n_LFH)#6U-owQE(%mAvEWvh^b9J!k-BN&4H{sL>yya)-AQ53^+p_4PnSlm|?{= z5>&o)d(eh?xqu&+jx*Y*@|ASolR#n|NmNJ%Tq3OisJ_oAE-Nqj5xxj?@ys+EC*^!I zHNFtDR57)WOl7*~Kvax2GHhpo89tI|gu5`A1m(joCc=CRiR$@?hDijCx)DV&H3|A- z4Ap6XE)xo&nIJrm(U^aFor# zz}=j{o13nMa-CkKK{uGHKMk=BdZ7VtxrGs=ABF-MLv(bZ04<0k0$RXS7cNqva`Vxs zX=NBZWcZMwLy?QPCPA&sBF?9wSjAjLPIE$>$%hOf!XcQ|Q190(@JLuE;ukCL1LvIb zrre?eatW0o9}HGkTcc~jE5b~yx|=;WABcpn$kdUJ!Wo1oArJ-9!Xg1sj)ZAB6Yf36 zM^Q8QN@+{O5yBIdAShH&z*@@M3pisdL#EZ`HrBl$Ki1EI z%qVGbVTGyIRe^Ai1$f;j;00X_aYDHG9$Wq7Y@b3%m)lDS=_cE1gmjbbWrTFOy@HT# zvb~CsF1ObZ(oMEcBcz*bpFv2M+v^DFCR-Uoy2 zSeZ<%?}C5PUZU6ts>S5PYgsH)R@dZf(_%3;xTQ+&P03=L@fPChP2HVumu`GevPfy&y7jy_dFxYj zR=BJU?hm}OcvwC>fePbo6b;K)E4_X$zLnXmh@#7Dg@&XnRgES9$r;oZ>rB*?orWHI z(OjAXhqJN>iC@Kvo2y)recj&RLUfE1=QZjZOkqYQq)yA}mzTJP2I;R{_0c%y`V6OY zVruA3EHhUg=JSnliI$SrR!)*|E3Vv3U7cv$yp1`Cn3{n1r}X-J97f}JQ&fn-0gLo} z1>_LMT8nZnUHv{rdyLQ*nICTQLWG-)RPN|kgz#PU&bAADO+rNNU zl}nfha0QcLuYK<-IuEauShd93@NHE3n$dq$9ie_nn#HRS)=pis*P|O)oS((SSa$Un zWM%_rH*m&-%zWUxS`~+z1?A7kP-8Jl>T<<-zR$}z#Xnzh($#R^49CO@n~@` zo2nwi5v8JBm48Aq;G5wb{zk-L?F*8Fg3=#U@b8!6d@^w8_O08mAhS1;tZXI6ESHCl z$3VZ_`5MOEmoQFqN{(Ku%AevV+r7LZ_XNguQxS9?9>0=%9Ao`Ggg83S z;0n5tdlbVzq=Q}jMut*64j^D`#wEt(aJdz^$30yej$vh-z7k!|J(PQb>)3kTQo7~2 zRs0TuA$|vezPKzGu5W3I%{ahEL}1 z&pj$xegT3c7oEE7|RJ(HOomBj4?a(4pHoQ|a=h+=J+OEF2vYVI;bM zZjSpNkH0a@d}p|6Sz*^lV_4~^Fc&`eKw;-M-8+Iop5I9^i33I5zx@NOQ@4>$L-j8~)$oi+D-|55O z)%W=FmfR}b^^gcFp2QtLLx$}fNV*>U*?ESmBiub-74F6Y2OZz^(UxoWTI6o|SzyQ* z#Wa28VczleVK3&J;p$i)o`J?k^#JS*%Bx{tPFA=5FiP)vL zVh=x;xZJz2*Xz~kTmTX%&wVaO+4r-#aD1Q(vl!mWaY@hVPQ2f|nY+ga(A8addCHaL z;^26=rM@1IlF#Js${=+4ED#F#^J+?%f7yQJT-=8G>VNylHE#TaxY>375N=PdLBi%uuu12Wj}jd8zouEh~don^O& zT*E`C5j)zpwj@Ou{8g7q!9n$(3zVPS-R?)HF=@TDY7c=bS&D8dc3Ek-}RG9{YWpSsM#hqT3bh;`3JZ^JQG;(j{X2%CQ zF}3Ccoo=rMyD{+xclteOMR?F`sdG2FOkYO0Cg11o3$eo9_*TD*&+$Eacj8{Z6ZiU^xYxbldw(#L@;>L8 zT=w0!@u2Z@_?DYDy^nnULt)_K>`=3^$ijU5p0V~c0r6gIG%@(~_PagdVIwUBuqVz%8 zpPA)Z$~_0IhurjmCS;P=9JeEeSY zj=}Hya1XxX;bvSU2EH*>K1*^IhlyK1%$DF8QH`4&cpl)E{C*A~X9wKxXYs(d15bM^ z@q3k5ir-HF5$(WZ-V^v;3XZe`E1|I4frp{1+kxd!(iv&pHvsl{A!i0Dmm_%W4I=FK zGXADTi5p8VU>PV|m=s3Q4&S%ht2;n-A1{lWIDSw+5hH?qXKnX?uPy(q?fxIy4kJ{rewWYJFGysJ>w~$5 zm}`x>9+_*DxsI7@ow)}3G2F~g;KBYBZsuojGrxfMLT)eOX8t7J`#<&nt c #767576", +", c #90908F", +"' c #A1A2A2", +") c #ACACAC", +"! c #A1A1A1", +"~ c #8F8E8F", +"{ c #777776", +"] c #636363", +"^ c #636364", +"/ c #636263", +"( c #636362", +"_ c #767676", +": c #9D9D9D", +"< c #B0B0B1", +"[ c #B1B1B0", +"} c #B0B0B0", +"| c #AFAFAF", +"1 c #9C9C9C", +"2 c #767777", +"3 c #656565", +"4 c #646463", +"5 c #868787", +"6 c #AFAFB0", +"7 c #AEAEAE", +"8 c #ADAEAE", +"9 c #ADADAE", +"0 c #868687", +"a c #666667", +"b c #676766", +"c c #656665", +"d c #7B7B7C", +"e c #AFAEAE", +"f c #ACADAC", +"g c #ACACAB", +"h c #7C7C7C", +"i c #686867", +"j c #686868", +"k c #666767", +"l c #A0A0A0", +"m c #ADADAD", +"n c #ADADAC", +"o c #ABAAAA", +"p c #ABABAA", +"q c #9E9E9E", +"r c #6A6969", +"s c #696969", +"t c #676768", +"u c #676868", +"v c #7F7F7F", +"w c #ABABAC", +"x c #A9A9A9", +"y c #A8A8A9", +"z c #80807F", +"A c #6B6B6B", +"B c #6B6C6B", +"C c #696A69", +"D c #939394", +"E c #AAAAAA", +"F c #A7A8A8", +"G c #A8A7A8", +"H c #929292", +"I c #6D6C6D", +"J c #6D6D6D", +"K c #6A6A6A", +"L c #A6A6A6", +"M c #9D9E9E", +"N c #6D6E6E", +"O c #6E6E6D", +"P c #6C6C6C", +"Q c #A0A09F", +"R c #A8A7A7", +"S c #A4A4A5", +"T c #706F6F", +"U c #706F70", +"V c #6D6E6D", +"W c #A6A5A6", +"X c #A3A3A3", +"Y c #919191", +"Z c #717070", +"` c #707171", +" . c #6F6F6F", +".. c #6F6F6E", +"+. c #818281", +"@. c #A4A4A4", +"#. c #A2A2A2", +"$. c #A2A2A1", +"%. c #727272", +"&. c #707071", +"*. c #717071", +"=. c #9A9A9A", +"-. c #A2A2A3", +";. c #A0A1A0", +">. c #989897", +",. c #737473", +"'. c #737474", +"). c #727172", +"!. c #808080", +"~. c #9F9F9F", +"{. c #9E9F9F", +"]. c #808181", +"^. c #747574", +"/. c #757575", +"(. c #737373", +"_. c #737374", +":. c #888888", +"<. c #A09FA0", +"[. c #9F9FA0", +"}. c #A09F9F", +"|. c #878888", +"1. c #767675", +"2. c #949494", +"3. c #9D9D9E", +"4. c #9D9C9C", +"5. c #9C9C9D", +"6. c #787778", +"7. c #777778", +"8. c #777777", +"9. c #8C8C8C", +"0. c #999A99", +"a. c #818181", +"b. c #797878", +"c. c #797879", +"d. c #605F60", +"e. c #605F5F", +"f. c #606160", +"g. c #616061", +"h. c #626162", +"i. c #616262", +"j. c #636262", +"k. c #626363", +"l. c #636463", +"m. c #646464", +"n. c #646564", +"o. c #646465", +"p. c #656564", +"q. c #656666", +"r. c #666666", +"s. c #666565", +"t. c #676666", +"u. c #676767", +"v. c #686768", +"w. c #686767", +"x. c #696869", +"y. c #5F5F60", +"z. c #616060", +"A. c #626161", +"B. c #626263", +"C. c #636464", +"D. c #656464", +"E. c #656566", +"F. c #696868", +"G. c #6A6A69", +"H. c #69696A", +"I. c #B3B3B3", +"J. c #B3B2B2", +"K. c #B2B2B2", +"L. c #B2B2B1", +"M. c #B2B1B1", +"N. c #B1B1B1", +"O. c #B0B1B1", +"P. c #AFB0AF", +"Q. c #AEAFAF", +"R. c #ACADAD", +"S. c #ABABAB", +"T. c #AAABAA", +"U. c #AAA9AA", +"V. c #6B6B6A", +"W. c #6B6C6C", +"X. c #6C6B6C", +"Y. c #B2B3B3", +"Z. c #B2B3B2", +"`. c #B2B1B2", +" + c #B1B2B1", +".+ c #B1B1B2", +"++ c #B1B0B0", +"@+ c #B0AFB0", +"#+ c #AFAEAF", +"$+ c #AEADAE", +"%+ c #ADACAC", +"&+ c #ACACAD", +"*+ c #ABACAC", +"=+ c #ACABAB", +"-+ c #AAAAAB", +";+ c #A9A9AA", +">+ c #A8A8A8", +",+ c #6D6C6C", +"'+ c #6C6D6D", +")+ c #B1B2B2", +"!+ c #B0B1B0", +"~+ c #AFB0B0", +"{+ c #AEAFAE", +"]+ c #AFAFAE", +"^+ c #AEADAD", +"/+ c #ACABAC", +"(+ c #A9AAAA", +"_+ c #A9A8A9", +":+ c #A7A7A7", +"<+ c #A6A7A6", +"[+ c #6E6E6E", +"}+ c #B1B0B1", +"|+ c #ADAEAD", +"1+ c #ADACAD", +"2+ c #A9A8A8", +"3+ c #A7A8A7", +"4+ c #A7A6A7", +"5+ c #A5A5A6", +"6+ c #A6A6A5", +"7+ c #A6A5A5", +"8+ c #A5A5A5", +"9+ c #6F6F70", +"0+ c #5F605F", +"a+ c #B3B2B3", +"b+ c #AAABAB", +"c+ c #A9AAA9", +"d+ c #A4A5A5", +"e+ c #A3A4A4", +"f+ c #A4A3A3", +"g+ c #A3A3A4", +"h+ c #B0AFAF", +"i+ c #AEAEAF", +"j+ c #A8A9A8", +"k+ c #A7A7A8", +"l+ c #A7A7A6", +"m+ c #A7A6A6", +"n+ c #A5A4A4", +"o+ c #A4A3A4", +"p+ c #A3A4A3", +"q+ c #A3A3A2", +"r+ c #B2B2B3", +"s+ c #AAAAA9", +"t+ c #A6A6A7", +"u+ c #A5A6A6", +"v+ c #A5A6A5", +"w+ c #A4A5A4", +"x+ c #A4A4A3", +"y+ c #A1A2A1", +"z+ c #A1A1A0", +"A+ c #737273", +"B+ c #747374", +"C+ c #AEAEAD", +"D+ c #A6A7A7", +"E+ c #A2A3A2", +"F+ c #A2A1A2", +"G+ c #A0A1A1", +"H+ c #A1A0A1", +"I+ c #A0A0A1", +"J+ c #747474", +"K+ c #B0B0AF", +"L+ c #ABACAB", +"M+ c #ABAAAB", +"N+ c #A5A4A5", +"O+ c #A3A2A3", +"P+ c #A2A1A1", +"Q+ c #9FA09F", +"R+ c #9E9F9E", +"S+ c #757676", +"T+ c #AAA9A9", +"U+ c #A5A5A4", +"V+ c #A2A3A3", +"W+ c #A1A1A2", +"X+ c #9F9E9E", +"Y+ c #9E9D9D", +"Z+ c #9C9D9D", +"`+ c #9D9D9C", +" @ c #777877", +".@ c #A8A8A7", +"+@ c #9FA0A0", +"@@ c #9F9E9F", +"#@ c #9D9E9D", +"$@ c #9C9D9C", +"%@ c #9B9C9C", +"&@ c #787879", +"*@ c #676867", +"=@ c #A9A9A8", +"-@ c #9E9E9D", +";@ c #9C9C9B", +">@ c #9B9B9B", +",@ c #9B9B9A", +"'@ c #9A9B9B", +")@ c #797A79", +"!@ c #797A7A", +"~@ c #7A797A", +"{@ c #686969", +"]@ c #9D9C9D", +"^@ c #9A9B9A", +"/@ c #999A9A", +"(@ c #999999", +"_@ c #999899", +":@ c #7A7B7B", +"<@ c #7B7B7B", +"[@ c #A3A2A2", +"}@ c #A1A0A0", +"|@ c #9E9E9F", +"1@ c #9C9B9C", +"2@ c #9C9B9B", +"3@ c #9A9A99", +"4@ c #9A999A", +"5@ c #989998", +"6@ c #989898", +"7@ c #979898", +"8@ c #989797", +"9@ c #979797", +"0@ c #7C7C7D", +"a@ c #6B6A6A", +"b@ c #6B6A6B", +"c@ c #000000", +"d@ c #9F9F9E", +"e@ c #9B9A9A", +"f@ c #9A9999", +"g@ c #989899", +"h@ c #969796", +"i@ c #969696", +"j@ c #7D7E7D", +"k@ c #7E7E7E", +"l@ c #9B9B9C", +"m@ c #999898", +"n@ c #979897", +"o@ c #969697", +"p@ c #969595", +"q@ c #959596", +"r@ c #959595", +"s@ c #959594", +"t@ c #959495", +"u@ c #7E7F7F", +"v@ c #6C6D6C", +"w@ c #9E9D9E", +"x@ c #979798", +"y@ c #969596", +"z@ c #969695", +"A@ c #949594", +"B@ c #939494", +"C@ c #949493", +"D@ c #939493", +"E@ c #807F80", +"F@ c #9B9C9B", +"G@ c #969797", +"H@ c #959696", +"I@ c #959494", +"J@ c #949394", +"K@ c #939393", +"L@ c #939293", +"M@ c #929392", +"N@ c #939292", +"O@ c #818282", +"P@ c #6E6F6F", +"Q@ c #989999", +"R@ c #979696", +"S@ c #939392", +"T@ c #929393", +"U@ c #919291", +"V@ c #919190", +"W@ c #828283", +"X@ c #828382", +"Y@ c #707070", +"Z@ c #9B9A9B", +"`@ c #9A9A9B", +" # c #949595", +".# c #929291", +"+# c #929191", +"@# c #919091", +"## c #909090", +"$# c #908F90", +"%# c #8F8F90", +"&# c #848383", +"*# c #838384", +"=# c #848484", +"-# c #717171", +";# c #999998", +"># c #979697", +",# c #909190", +"'# c #919090", +")# c #8F8F8F", +"!# c #8E8E8E", +"~# c #8E8F8E", +"{# c #858484", +"]# c #858585", +"^# c #727372", +"/# c #99999A", +"(# c #959695", +"_# c #949495", +":# c #949393", +"<# c #919292", +"[# c #908F8F", +"}# c #8F8F8E", +"|# c #8F8E8E", +"1# c #8E8F8F", +"2# c #8E8D8E", +"3# c #8E8D8D", +"4# c #8D8E8D", +"5# c #8D8C8D", +"6# c #8D8D8D", +"7# c #868686", +"8# c #747473", +"9# c #929192", +"0# c #909091", +"a# c #8D8E8E", +"b# c #8D8D8E", +"c# c #8C8D8D", +"d# c #8B8C8B", +"e# c #878787", +"f# c #878887", +"g# c #747475", +"h# c #747575", +"i# c #979796", +"j# c #8E8E8F", +"k# c #8E8E8D", +"l# c #8D8D8C", +"m# c #8B8C8C", +"n# c #8B8B8B", +"o# c #8A8B8B", +"p# c #8B8A8A", +"q# c #8A8A8A", +"r# c #888988", +"s# c #898989", +"t# c #8F9090", +"u# c #8D8C8C", +"v# c #8C8B8C", +"w# c #8B8B8A", +"x# c #8C8C8B", +"y# c #8A8A8B", +"z# c #89898A", +"A# c #898A89", +"B# c #8A8989", +"C# c #888788", +"D# c #8C8B8B", +"E# c #777878", +"F# c #8B8A8B", +"G# c #8A8B8A", +"H# c #8A898A", +"I# c #8A8A89", +"J# c #888989", +"K# c #898888", +"L# c #888887", +"M# c #868786", +"N# c #797978", +"O# c #797979", +"P# c #929293", +"Q# c #878788", +"R# c #878687", +"S# c #868586", +"T# c #858485", +"U# c #7A7A7A", +"V# c #898A8A", +"W# c #898889", +"X# c #888889", +"Y# c #888787", +"Z# c #878786", +"`# c #868685", +" $ c #858685", +".$ c #838483", +"+$ c #8F908F", +"@$ c #7B7C7C", +"#$ c #8C8C8D", +"$$ c #898988", +"%$ c #878686", +"&$ c #868585", +"*$ c #848585", +"=$ c #858584", +"-$ c #838383", +";$ c #828282", +">$ c #838282", +",$ c #7D7C7C", +"'$ c #858586", +")$ c #838484", +"!$ c #838382", +"~$ c #818182", +"{$ c #828181", +"]$ c #808180", +"^$ c #919192", +"/$ c #7E7D7D", +"($ c #8C8D8C", +"_$ c #838283", +":$ c #828383", +"<$ c #828281", +"[$ c #818180", +"}$ c #7F807F", +"|$ c #7E7E7F", +"1$ c #7E7F7E", +"2$ c #7F7E7F", +"3$ c #858686", +"4$ c #848384", +"5$ c #818081", +"6$ c #818080", +"7$ c #807F7F", +"8$ c #7F7F7E", +"9$ c #7F7F80", +"0$ c #909191", +"a$ c #8B8B8C", +"b$ c #848584", +"c$ c #848483", +"d$ c #7E7E7D", +"e$ c #7E7D7E", +"f$ c #7D7D7D", +"g$ c #828182", +"h$ c #7F8080", +"i$ c #7D7C7D", +"j$ c #7C7D7D", +"k$ c #7C7D7C", +"l$ c #7C7C7B", +"m$ c #7B7C7B", +"n$ c #7D7E7E", +"o$ c #7D7D7E", +"p$ c #7D7D7C", +"q$ c #7C7B7C", +"r$ c #7B7B7A", +"s$ c #7A7B7A", +"t$ c #7A7A7B", +"u$ c #7A7A79", +"v$ c #787979", +"w$ c #848485", +"x$ c #7F7E7E", +"y$ c #7C7B7B", +"z$ c #7A7979", +"A$ c #787878", +"B$ c #787777", +"C$ c #787877", +"D$ c #808081", +"E$ c #787978", +"F$ c #777677", +"G$ c #767776", +"H$ c #7B7A7A", +"I$ c #767677", +"J$ c #757576", +"K$ c #757475", +"L$ c #747373", +"M$ c #727373", +"N$ c #737372", +"O$ c #737272", +"P$ c #7B7A7B", +"Q$ c #757675", +"R$ c #757574", +"S$ c #717272", +"T$ c #717172", +"U$ c #777676", +"V$ c #70706F", +"W$ c #79797A", +"X$ c #757474", +"Y$ c #727271", +"Z$ c #727171", +"`$ c #6F6E6F", +" % c #767575", +".% c #6F6E6E", +"+% c #6E6F6E", +"@% c #6E6D6D", +"#% c #6D6D6E", +"$% c #6D6D6C", +"%% c #717271", +"&% c #6C6C6D", +"*% c #6B6B6C", +"=% c #717170", +"-% c #6F706F", +";% c #6E6D6E", +">% c #6C6C6B", +",% c #6A6B6B", +"'% c #6A6B6A", +")% c #707170", +"!% c #6F7070", +"~% c #6A6A6B", +"{% c #6E6E6F", +"]% c #696A6A", +"^% c #696968", +"/% c #686968", +"(% c #666766", +"_% c #6C6B6B", +":% c #676667", +"<% c #6A696A", +"[% c #656465", +"}% c #666566", +"|% c #666665", +"1% c #646565", +"2% c #646364", +"3% c #646363", +"4% c #989798", +"5% c #686869", +"6% c #626362", +"7% c #606061", +"8% c #B3B3B2", +"9% c #A8A9A9", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" . . + @ + # + ", +" + + $ + % & & & * * = ", +" - - ; > , ' ) ! ~ { ] ] ^ ", +" / ( _ : < [ < } } | | 1 2 3 3 ", +" 4 4 5 } 6 | | 7 7 8 9 0 a b ", +" 3 c d e 7 7 f ) g h i j ", +" k k l m n o p q r s ", +" t u v ) w x y z A B ", +" C s D o E F G H I J ", +" K A l x L M N O ", +" P P Q R S 1 T U ", +" V V H L W X X Y Z ` ", +" ...+.@.S #.$.+.%.%. ", +" &.*.=.-.X ;.l >.,.'. ", +" ).%.!.! ! ! ~.~.{.].^./. ", +" (._.:.<.[.}.~. q q q M |.1._ ", +" /./.v 2.q M 3.: : 4.5.H !.6.7. ", +" 2 { 8.!.9.2.0.2.9.a.b.b.c. ", +" . . . . . . . . . . . . . . . . . . . . . . . . . . d.. e.@ f.f.g.& & h.& = i.j.j.j.k.] ] l.4 m.n.o.p.3 3 q.r.s.r.r.t.t.u.u.j v.w.j j x. ", +" . . . . . . . . . . . . . . . . . . . . . . . @ d.y.+ z.z.f.$ & A.A.= * * j.B.] ] C.m.4 m.m.D.p.p.3 E.E.r.r.t.r.u.u.u.u t i j j x.F.s s G.H.K K ", +" . . . . I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.J.K.K.K.L.M.N.O.} } } } } P.| | Q.7 7 8 m m 9 m f R.) ) ) S.S.S.S.T.E E U.E x V.A W.X. ", +" . . . I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.Y.Z.K.`. +M..+N.++N.++} @+| | | | e #+7 $+$+m m %+&+) ) ) *+=+g S.o E -+;+E ;+x x x >+>+>+F G ,+'+J ", +" . . I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.J.I.K.K.K.K.)+M.[ ++!+} ~+} ~+| | {+]+{+$+7 $+^+m n n %+) /+w S.S.S.o E E E U.(+x x x _+>+>+>+:+R :+:+<+:+L O [+ ", +" . . . I.I.I.I.I.I.I.I.I.I.I.I.I.I.J.Z.K.K..+`.N.N.}+++} ~+} 6 | | | e 7 7 7 m |+m &+1+f ) *+*+w S.T.-+o E E E (+x x 2+2+>+>+3+F R :+4+L L L 5+6+7+8+@. .9+T ", +" 0+@ I.I.I.I.I.I.I.I.I.Y.a+Z.K.K.L.N.N.[ !+} } } ~+} 6 | {+7 7 7 $+m ^+m ) ) 1+) g /+S.S.S.b+E E E (+c+x x y >+>+>+F F :+:+:+L L L W W 5+8+S d+@.@.e+f+g+Z &. ", +" & $ I.I.I.I.I.I.J.K.K. +L.N.N.!+} } h+| | 6 | | {+i+7 7 8 m R.R.) ) ) ) *+w S.b+b+E E E (+x x _+j+y >+G G 3+k+:+l+m+m+L 7+5+5+d+8+n+@.o+o+p+X q+X #.#.#.).%. ", +" & * * r+K.L.)+.+N.N.++N.!+} } h+@+| | | 7 7 7 9 m m 1+&+&+f ) ) w S.S.o E T.s+s+x (+x 2+j+y >+F k+:+:+4+t+t+L u+u+v+v+8+8+w+@.x+o+@.X X q+-.-.#.' y+! ! z+A+(.B+ ", +" ] / +.+N.N.} !+} @+@+P.| | ]+i+7 |+C+m m m &+f f g *+=+S.S.S.o E E U.s+(+x x j+2+>+F k+k+:+D+m+L L 6+8+7+8+8+8+n+@.@.o+x+f+X -.E+#.' F+' ! ! ;.G+H+I+}.}.<.J+/. ", +" 4 m.m.!+K+@+~+h+| #+7 {+7 C+^+8 m m &+&+) g L+S.S.S.p M+E U.s+x x x x 2+2+>+R F k+:+<+l+L L L W 8+v+N+w+@.S x+x+X X q+X O+E+F+P+F+! ! H+I+;.Q l Q+~.~.{.~.R+q S+_ _ ", +" 3 3 h+| | {+e 7 ^+^+^+m m ) ) ) ) =+w S.S.b+-+T.U.c+T+;+x x 2+2+>+>+R :+:+D+L L L L 6+7+8+N+U+w+@.e+x+o+p+V+X #.E+' y+W+! H+l l l l [.[.~.{.~.q X+q 3.Y+: : Z+`+8. @ ", +" r.r.7 m 7 ^+m n R.) ) L+*+=+L+S.-+b+E E (+T+x x x >+j+>+.@G :+l+:+D+L L u+7+5+8+N+8+@.@.f+X f+f+q+X #.#.y+' $.! ! ;.I+l Q +@Q+}.@@~.q q q #@3.: : : $@$@1 1 %@%@&@c. ", +" u.w.*@m &+&+) /+w S.S.S.S.o o E x c+T+x y =@>+>+R G :+:+:+m+:+6+7+6+8+8+8+n+S @.e+@.x+X q+#.#.E+#.y+! ! ! z+I+l l +@l }.~.~.R+R+q -@#@: : `+5.1 1 ;@>@>@>@>@,@'@=.)@!@~@ ", +" j {@g S.S.S.S.E p E c+T+U.x x 2+_+>+>+F R R t+:+m+L L 5+v+8+8+8+N+w+@.@.f+p+f+X X #.#.#.! ! ! ! I+z+l l [.~.~.~.{.X+q q M M : : ]@5.1 1 %@;@>@>@>@>@^@=./@(@(@0.(@_@:@<@ ", +" H.s r M+T.E E T+;+x =@x y >+>+G F :+:+D+L L L L 7+8+8+n+U+@.@.p+p+X X O+V+#.[@#.$.P+! ! }@G+l <.Q [.[.~.@@|@q q M #@: : : 4.1 1 1@2@>@>@>@=.=.=.3@4@3@(@(@_@5@6@7@8@9@h h 0@ ", +" a@b@T+;+x =@y >+>+>+3+G :+:+l+c@c@c@c@c@c@d+8+N+@.@.@.X o+X X q+#.#.P+P+W+! ! G+H+l +@+@<.~.~.d@R+q q 3.M 3.: ]@Z+5.1@2@1 >@>@=.=.e@=.=.f@(@(@(@g@6@6@6@6@9@8@h@9@i@i@i@j@k@ ", +" P W.j+>+G R 3+:+:+t+:+L L 7+7+c@c@c@c@c@c@@.@.X X O+X #.' #.F+P+! G+H+l l l ~.Q ~.~.X+q R+-@M M #@Z+]@4.1 1 ;@2@l@>@e@^@^@=.4@=.0.(@(@5@m@6@>.8@n@9@9@i@o@i@p@q@p@r@s@t@v u@ ", +" J J v@:+:+:+l+L 5+6+5+8+d+d+@.@.c@c@c@c@c@c@#.#.#.#.' P+! ! ! I+l Q ~.~.~.d@q X+q q w@3.: : 5.1 4.1 %@2@>@>@>@e@=.=.3@4@0._@_@5@5@6@6@x@9@8@9@9@i@i@i@y@z@r@r@t@A@2.B@C@D@!.E@!. ", +" O [+L L v+8+8+8+8+S @.e+x+x+X X c@c@c@c@c@c@! H+! }@}@l l l [.~.{.d@q q M w@Y+: : ]@1 $@1 1 %@F@>@'@'@=.=.4@=.(@(@g@(@6@6@7@9@n@9@9@o@G@i@z@H@y@r@r@I@r@2.2.2.J@K@K@L@M@N@H a.O@ ", +" P@T N+w+n+@.@.g+X X V+O+V+[@#.y+c@c@c@c@c@c@l Q Q+~.~.~.{.{.q q q : : `+: `+1 ;@2@F@l@>@,@^@=.=./@/@(@Q@Q@m@5@6@x@x@x@9@9@i@R@i@z@r@q@r@r@t@A@A@D 2.K@D@K@S@T@H H U@H Y Y V@W@X@ ", +" Y@Y@Y@p+g+X [@X #.-.#.F+W+! ! ! ! c@c@c@c@c@c@|@q q q M 3.: : ]@]@5.1 1 1 >@>@^@Z@=.`@=.f@f@(@Q@m@6@Q@6@x@9@8@9@9@o@R@i@i@y@q@r@ #I@I@2.J@B@K@K@S@N@M@H .#+#.#Y Y V@@#####$#%#&#*#=# ", +" -#-#-.O+#.' ! P+W+z+}@I+}@l l Q [.c@c@c@c@c@c@Y+: ]@Z+: 1 1 %@>@>@>@>@'@=.=./@3@(@(@;#6@6@6@6@7@9@n@>#9@i@R@i@i@q@r@r@ #s@2.2.J@D D@K@S@K@H N@H +#Y Y Y ,#'#####, $#)#)#)#!#~#!#{#]# ", +" %.^#! ! ! }@z+}@l +@+@~.~.X+{.R+q c@c@c@c@c@c@1 1 ;@;@F@>@=.e@'@=./#3@f@(@Q@_@5@m@>.>.n@9@G@R@>#o@i@(#z@H@r@t@2._#2.:#B@D K@N@T@H H .#<#Y Y Y Y ######$#[#)#}#|#1#|#!#2#3#4#5#6#7#7# ", +" (.(.8#l l l ~.[.d@~.q X+q Y+#@3.: Z+c@c@c@c@c@c@>@>@^@`@=.=./@c@c@c@c@c@c@6@>.8@9@9@h@9@i@i@c@c@c@c@c@c@2.2.2.c@c@c@c@c@c@H U@9#U@Y Y Y 0#####%#)#)#)#)#!#}#a#b#b#6#c#5#c#9.9.9.d#e#f#e# ", +" g#h#~.|@@@|@q -@q #@: : : 4.$@F@%@%@c@c@c@c@c@c@4@4@(@(@Q@Q@c@c@c@c@c@c@i#i#o@i@z@i@H@r@c@c@c@c@c@c@c@c@c@N@M@c@c@c@c@c@c@Y '#'#####%#%#)#)#j#!#!#!#k#!#6#6#5#9.l#9.9.m#d#n#o#o#p#q#r#s# ", +" S+/.S+q q 3.: ]@$@`+4.1 %@l@>@Z@,@e@=.c@c@c@c@c@c@(@m@6@>.8@n@c@c@c@c@c@i@y@q@r@r@s@s@2.c@c@c@c@c@c@c@c@c@c@c@U@c@c@c@c@c@c@t#, )#1#}#|#!#!#2#4#6#6#c#u#9.9.v#n#n#n#w#q#q#q#q#q#s#s#s#q#q#p# ", +" 2 8.`+`+1 1 %@1 F@2@>@>@^@=./@3@4@/@(@c@c@c@c@c@c@9@9@9@>#h@c@c@c@c@c@r@r@t@I@2.B@D@K@K@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@|#!#!#6#b#6#5#l#9.9.9.x#9.n#n#n#o#y#q#z#A#B#s#s#r#:.:.f#C#f#d#D# ", +" 7.E#%@l@>@>@`@'@e@3@=.4@(@(@5@5@6@6@6@c@c@c@c@c@c@i@i@r@r@c@c@c@c@c@c@K@K@D@K@S@S@L@H c@c@c@c@c@c@c@##$#$#$#c@c@c@c@c@c@c@c@6#6#9.5#9.9.d#D#n#n#F#q#G#q#H#I#A#s#J#K#K#:.C#C#L#e#e#M#7#7#9.9. ", +" N#c.O#e@=.=.=.(@0.(@(@_@5@>.6@7@9@9@9@G@c@c@c@c@c@c@s@r@r@c@c@c@c@c@c@S@S@P#H U@Y Y Y Y c@c@c@c@c@c@)#~ 1#~#!#2#c@c@c@c@c@c@c@x#n#9.n#n#w#G#q#I#H#B#A#s#r#s#:.:.:.Q#L#e#R#R#7#7#S#7#]#]#T#a#!#~# ", +" ~@U#f@f@(@Q@m@g@7@>.x@n@9@i@9@i@H@y@r@y@c@c@c@c@c@c@2.D c@c@c@c@c@c@H U@Y Y V@,#,###, c@c@c@c@c@c@c@a#a#k#6#5#6#c@c@c@c@c@c@c@o#y#q#q#I#s#V#W#s#X#:.:.Y#:.C#e#Z#7#7#`#7# $]#]#T#]#{#=#=#=#.$)#+$ ", +" <@@$6@8@9@x@9@9@o@o@i@i@y@H@r@r@ #I@A@2.c@c@c@c@c@c@M@c@c@c@c@c@c@Y 0#####$#)#)#)#1#~#c@c@c@c@c@c@u#6##$9.9.D#D#d#c@c@c@c@c@c@A#s#$$J#X#r#:.:.f#e#e#%$R#7#7#&$]#`#*$=$=$=#=#=#*#-$-$-$;$W@>$,#Y ", +" h h ,$9@i@i@i@i@y@H@r@r@r@r@_#2.J@:#K@K@N@c@c@c@c@c@c@c@c@c@c@c@c@##$#%#)#1#|#~#!#a#a#6#c@c@c@c@c@c@D#9.n#o#p#q#q#B#c@c@c@c@c@c@:.|.:.L#e#5 Z#R#7#7#'$ $]#]#{#=#=#=#=#)$&#-$-$W@!$X@;$~${$a.]$H H ^$ ", +" j@/$H@y@p@r@r@t@2.2.2.2.J@:#K@K@P#M@H H +#c@c@c@c@c@c@c@c@c@c@c@c@c@!#2#k#b#3#5#c##$($9.c@c@c@c@c@c@o#q#V#z#B#s#s#W#c@c@c@c@c@c@e#e#0 7#`#`#S#]#]#=$T#=#=#)$*#-$-$_$:$;$;$<$O@{$a.]$[$!.!.!.v }$K@:# ", +" |$1$2$s@2.2.C@:#D@K@K@K@H M@H H U@Y Y Y 0###c@c@c@c@c@c@c@c@c@c@c@c@c@c#5##$9.9.m#D#v#n#o#c@c@c@c@c@c@s#J#$$:.:.:.L#Y#c@c@c@c@c@c@`#3$]#]#]#*$]#=#*#4$)$-$!$X@!$;$;$~$a.a.].5$5$6$!.}$7$v 8$v u@2$2.2.r@ ", +" 9$}$:#B@K@K@L@H N@<#H <#<#@#0$0$######, +$)#c@c@c@c@c@c@c@c@c@c@c@c@c@c@a$D#y#p#q#q#q#q#s#c@c@c@c@c@c@C#e#:.e#e#5 %$7#c@c@c@c@c@c@b$=#c$=#-$-$-$W@;$;$;$;$+.a.a.a.[$[$!.!.!.}$v u@2$k@k@k@d$e$f$,$f$r@z@ ", +" a.].L@T@H U@+#U@Y Y Y ######, +$)#)#j#!#!#k#c@c@c@c@c@c@c@c@a$c@c@c@c@c@p#q#I#B#s#s#K#s#K#c@c@c@c@c@c@%$%$7#7#'$'$]#{#c@c@c@c@c@c@-$-$:$!$X@g$~$O@+.a.a.[$!.!.}$E@h$v 2$2$|$k@k@f$/$f$i$j$k$h l$@$m$9@9@ ", +" g$~$<$+#Y @#'#V@t#[#[#%#)#1#|#j#!#k#b#6#4#l#l#c@c@c@c@c@c@n#w#y#c@c@c@c@c@c@W#J#:.:.:.|.e#e#c@c@c@c@c@c@3$]#*$=$=$=#4$*#c@c@c@c@c@c@<$a.+.a.a.[$].!.z E@z v v v |$1$k@n$k@f$o$f$j$p$0@h q$<@<@r$r$s$s$6@6@5@ ", +" >$-$,###+$[#[#)#}#}#!#!#b#b#6#6#6#6##$u#9.x#d#c@c@c@c@c@c@I#B#s#s#c@c@c@c@c@c@Q#5 Z#M#7#7#7#c@c@c@c@c@c@=#c$c$-$-$-$>$X@c@c@c@c@c@c@a.[$!.!.7$h$v 8$8$8$1$k@n$j@/$f$f$j$0@h q$<@l$<@<@t$U#U#~@u$O#O#O#v$f@/@ ", +" c$)$=#)#)#!#~#!#3#a#4#6#5#9.#$9.v#m#n#n#n#w#G#q#c@c@c@c@c@c@$$K#:.C#c@c@c@c@c@c@7#7# $ $]#T#w$c@c@c@c@c@c@c@!$X@;$;$a.<$c@c@c@c@c@c@c@v v v k@x$k@k@k@o$o$f$k$f$i$h l$q$y$<@<@<@t$U#U#u$O#z$c.&@b.A$E#B$C$,@^@,@ ", +" ]#]#!#6#k#3#6#6#l#($9.9.m#n#n#n#F#y#q#I#V#z#s#s#c@c@c@c@c@c@e#e#M#M#7#c@c@c@c@c@c@b$=#=#)$.$-$-$c@c@c@c@c@c@g${$a.!.a.D$c@c@c@c@c@c@c@x$k@d$/$f$f$j$p$h h h c@c@c@c@c@c@U#U#z$~@O#b.E$c.A$A$C$7.8.8.F$G$_ _ 1 1 ", +" 7#7##$9.c#9.x#n#n#n#n#n#p#q#I#H#s#s#s#s#J#:.:.L#c@c@c@c@c@c@3$ $&$]#]#c@c@c@c@c@c@-$-$>$>$;$;$O@c@c@c@c@c@c@c@!.E@9$v c@c@c@c@c@c@c@c@f$f$0@0@h <@l$y$<@t$H$c@c@c@c@c@c@c.O#c.&@A$A$8.B$8.{ I$_ > S+/.J$/.h#: #@ ", +" e#e#Y#v#n#n#o#p#q#q#q#A#z#s#J#K#X#:.:.Q#e#e#e#Z#0 c@c@c@c@c@c@b$*$b$=#=#)$c@c@c@c@c@c@O@;$a.a.]$].6$c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@d <@<@r$:@<@H$U#u$u$U#c@c@c@c@c@c@7.7.8.I$2 I$_ S+S+S+/.g#/./.^.J+'.8#q @@{. ", +" :.:.F#p#q#q#q#A#s#J#s#X#:.:.|.L#Y#5 %$7#7#7# $`#]#c@c@c@c@c@c@c$-$-$-$>$;$;$c@c@c@c@c@c@!.!.!.}$v v c@c@c@c@c@c@c@c@c@c@c@h c@c@c@c@c@c@r$U#U#~@u$O#O#N#E$A$A$c@c@c@c@c@c@2 _ _ 1.J$J$/.K$h#J+J+L$'.(.M$N$%.O$%.l +@ ", +" z#V#z#$$W#X#r#:.:.Q#e#Q#R#Z#%$7#S#'$]#]#]#]#=#{#=#c@c@c@c@c@c@W@;$;$+.a.a.5$c@c@c@c@c@c@v u@1$1$k@k@d$c@c@c@c@c@c@c@c@c@<@P$c@c@c@c@c@c@z$O#v$b.A$A$A$B$B$8.8.c@c@c@c@c@c@Q$K$J+R$J+J+B+L$'.(.(.%.O$%.S$T$-#-#` H+! ", +" p#F#w#:.:.:.Y#e#Z#Z#7#7#7#`#&$]#]#T#b$=#=#c$-$*#-$!$c@c@c@c@c@c@a.].]$]$!.E@}$9$c@c@c@c@c@c@e$f$f$f$f$i$h h c@c@c@c@c@s$U#U#u$c@c@c@c@c@c@A$ @6. @8.{ 2 U$_ _ _ c@c@c@c@c@c@B+J+_.(.A+A+^#%.%.%.%.S$` *.-#Y@Y@U V$#.q+E+ ", +" v#9.e#5 e#7#7#S#3$]#]#]#*$=$b$4$&#-$-$-$:$_$;$;$<$<${$a.].]$!.!.!.z v 8$v 8$x$k@k@d$j@f$f$p$f$h l$m$d <@<@:@U#t$u$W$O#O#O#v$v$c@c@c@c@c@c@{ { G$_ _ _ /./.h#X$^.^.8#(.,.(.(.A+%.%.Y$Z$S$-#-#*.Z Y@Y@U U . .`$`$[+[+e+o+ ", +" c#5#6#7#`#]#]#=$=$w$=#c$=#-$4$-$_$X@;$;${$a.{$a.a.a.6$!.h$7$}$2$2$k@k@k@n$/$f$f$f$k$k$h h q$m$<@P$r$U#U#U#U#u$O#O#c.E$A$E#7. @7.c@c@c@c@c@c@J$ %/./.X$J+J+_.B+(.(.A+M$^#%.%.S$S$-#-#*.&.Z Y@U . ....%+%[+[+@%#%#%J $%U+8+8+ ", +" 2#!#*$b$w$=#.$-$-$-$W@-$;$;$;${${$a.a.!.!.!.h$h$9$v v 2$2$1$e$k@k@j@p$h ,$h h l$h <@<@<@U#s$U#U#W$W$O#c@c@c@c@c@c@8.E#8.2 8._ c@c@c@c@c@c@R$g#J+_.8#,.(.A+M$%.A+%%S$-#-#-#` Y@Y@Y@V$ .9+ .[+`$.%[+[+N J J I &%,+P P P *%<+<+ ", +" ~ )#-$-$-$:$_$>$;$g$g$+.a.a.6$5$!.!.E@7$v v |$|$k@k@k@f$/$f$k$h k$h @$l$<@<@:@<@r$U#~@u$z$)@O#b.A$E$C$c@c@c@c@c@c@c@S+1.S+Q$c@c@c@c@c@c@c@L$(.(.N$%.%.%.Z$).-#-#=%*.Y@Y@U -% . . .[++%O V ;%J J J v@P W.>%A A A ,%'%V.K :+3+ ", +" )###,#;$;$g$a.+.a.a.[$a.!.h$9$E@v 8$v x$x$n$e$/$f$f$i$0@k$h q$q$d <@H$t$U#U#~@U#!@O#v$&@A$b.7.6.7.8.8.F$8.c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@O$%.S$Y$-#-#=%` )%Y@!%9+T T ..%P@[+N ;%O J J '+$%I P P B A A a@b@~%K r s s s F.2+=@_+ ", +" Y Y a.a.a.5$!.]$E@z z v u@u@k@x$k@e$f$f$j$f$h 0@h h d <@<@<@H$U#U#U#u$O#O#N#A$E$A$A$C$A$8.8.U$_ _ > > _ /./.c@c@c@c@c@c@c@c@c@c@c@c@c@c@c@-#Z )%&.Y@Y@T !% . .{%+%[+[+N V @%I $%,+&%P W.P A A A ,%K K G.]%s s s x.j j j u w.E E ", +" S@M@!.E@}$v v v 8$1$k@k@k@e$f$f$j$h k$h y$q$<@<@U#r$U#U#u$U#O#v$E$N#b.A$B$ @8.8.{ I$U$2 > %S+Q$h#/.g#J+,.J+,.c@c@c@c@c@c@c@c@c@c@c@c@` Y@!%!%T . .`$[+[+N O J J J $%I P P P P A A A ,%'%K s H.H.s ^%/%^%j t u t u.u.(%b a S.L+ ", +" D K@C@v u@k@k@k@j@f$/$f$f$h h h d d <@<@P$:@H$u$U#!@z$O#&@O#c.A$E#6.8.8.F$F$G$_ _ %> /.X$/.^.J+J+_.J+(.(.(.A+^#%.Y$c@c@c@c@c@c@c@c@T . .P@P@{%[+O N N J J $%P ,+B _%*%_%,%b@,%K K K H.s s s j j j i *@u.u.k :%(%a r.3 c s.3 ) R.1+ ", +" 2.s@k@e$j@j@p$f$p$h h q$<@<@<@s$t$t$U#U#W$O#O#c.A$A$A$A$ @7.8.{ { I$_ Q$J$> /./.g#J+J+J+J+8#(.(.M$A+%.%.S$T$-#-#*.)%Y@Y@U Y@-% .+%{%+%[+[+;%@%J $%&%P P X.X._%A A A V.,%K <%C C s /%s ^%u j u.u.u.u.a :%r.r.E.3 3 p.p.[%m.m.m.] 9 ^+ ", +" z@i@H@,$j$h @$m$d <@<@P$U#U#)@U#u$O#E$b.b.A$A$6.C$7.8.G$I$_ _ _ S+Q$/.K$R$^.J+'.(._.(.(.(.O$O$%.%.-#-#-#-#-#)%V$Y@T -% . . .{%[+N N J J J v@,+P _%>%X.B A '%A K G.G.<%r s /%{@j j j v.*@u.t.t.r.r.}%E.|%3 1%o.p.m.2%m.] 3%] / j.j.#+| | ", +" 9@9@h l$<@<@t$H$U#u$W$O#O#O#O#A$b.A$E# @8.8.8.I$_ _ /.S+1./.R$/.J+J+L$8#(.(.(.^#A+%.S$Z$%%-#*.-#)%=%Y@T V$-% ...`$+%[+O J J J '+&%J P P X._%A A V.A K K ]%C r ^%{@^%j j v.*@w.u.u.:%t.r.r.c q.3 1%1%3 m.4 ] 4 ] ] / * * * A.& & f.& < ++ ", +" 4%6@H$U#!@z$W$O#O#b.c.A$A$C$7.7.8.I$U$G$_ /.1.1././.R$^.J+_._.'.(.(.^#A+%.%.Z$T$-#-#=%)%Y@Y@T T . .`$`$+%[+[+O @%J ,+&%P P P W._%A A A K K K K G.s ^%F.s j u u j u u.k b r.|%s.s.3 3 [%p.[%m.m.] ^ ] ] k.( * = * - & $ % z.+ + # + .+.+ ", +" _@(@(@O#E$E$A$A$6.8.C$8.8.8._ _ _ S+S+/././.X$X$J+J+(.L$(.(.N$M$%.%.%%%%-#-#Y@)%Z 9+Y@ . . .`$+%[+O N O #%J J v@$%P P A *%A V.,%~%a@K K s s ^%^%5%/%i u.*@u.u.b r.r.r.|%3 s.3 3 1%m.m.m.] m.] 6%] * * i.- - - & + 7%+ + + y.. . . . . a+I.I. ", +" =.=.A$A$B$8. @I$F$G$G$_ S+ %/./.^.J+^.8#J+B+(.(.O$A+%.%.Y$%.T$-#-#=%Y@Y@!%-%U . ...[++%[+O @%J J '+P v@P W.B _%A A ,%,%K K <%s s {@{@^%j v.i t u.u.t.a r.r.r.E.E.3 o.D.m.m.C.l.3%] ( / j.* = A.& & g.g.z.+ d.y.. . . . . . . . . . . . I.I. ", +" >@>@>@8.8._ G$> > _ S+R$g#^.J+J+8#_.(.(.N$^#O$%.T$-#-#-#-#=%Y@Y@Y@!%9+ .[+P@..[+[+O J J J ,+$%P P B W.*%A ~%K K K <%s <%s F.5%/%j u v.u.w.u.k t.r.r.3 }%3 [%D.1%m.m.4 C.2%] ] ( 6%* A.- & & & + + + d.0+y.. . . . . . . . . . . . . . . . I.I.I. ", +" 1 1 _ J$/.J$/.R$J+R$J+8#_.(.(.M$O$O$%.Y$S$T$=%-#Z &.Y@Y@ .T ...`$[+[+N [+N J I '+v@P P W._%A A ,%A K ]%K C s s s s /%j v.w.j u.u.k :%r.|%r.q.3 3 3 n.m.m.2%C.] ] / B.* * * A.h.& z.+ + + 0++ 0+0+. . . . . . . . . . . . . . . . . . . . . I.I. ", +" : 3.R$K$J+J+(.L$(.A+N$N$%.%.Y$-#T$-#&.&.` Y@-%V$ . ...+%{%[+N [+J J ,+&%P P P P A A A A K K K K G.s s x.F.5%j j w.u.u.a u.r.r.r.3 q.c 1%1%o.m.m.2%C.] ] ] k.6%* = & ; & $ f.f.d.@ d.. . . . . . . . . . . . . . . . . . . . . . . . . . . . I.I. ", +" |@d@8#(.(.A+^#%.Y$-#-#-#-#*.&.Y@Y@Y@9+9+ .+%+%[+[+[+[+#%J J v@P P W.*%_%A A a@'%K K H.C <%x.F.5%j j i i *@u.:%b r.r.r.}%3 3 3 [%o.o.2%m.^ ^ ] / 6%j.= h.= h.& & f.+ + + y.y.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I.I. ", +" Q+[.l %.Y$Y$-#-#-#&.Z !%V$9+ . . . ..%[+V [+J J J v@J P P X._%A A a@V.~%]%K r s s s {@j j j i u.u.u.k (%r.}%|%c 3 1%p.3 m.^ C.] ] ] * * j.h.- ; & % 7%f.+ + + e.e.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I.I.I. ", +" ! ! -#)%Y@V$V$9+ . ...{%[+O [+@%J J '+I $%P P P A B A ~%b@V.<%r C s s s /%j j *@w.i u.u.k r.r.r.3 3 3 3 D.m.m.] 3%] ] 6%k.* * * = h.& & g.f.+ + y.# d.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I.I. ", +" #.#.E+U ..%[+{%[+V @%[+J J v@v@P B W.*%A V.a@'%K r <%C H.s /%j j j i *@u.u.k b t.r.q.|%|%3 3 n.1%4 m.3%] ] j.B.j.* * * & & & g.+ f.+ . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I.I.I. ", +" f+x+@.@.N+d+N+8+u+5+u+L L l+l+<+:+:+F >+>+>+2+2+x x c+(+E E T.E b+S.g S.g ) ) f n m m m 8 $+^+7 i+e 7 | | ~+K+K+++}+[ }+N.N.K.`.K.Z.K.8%I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I. ", +" 8+8+5+L L L <+D+:+4+F .@:+>+>+>+9%x x T+U.E U.E b+b+S.S.g w ) ) f R.n m m m ^+7 8 7 7 ]+Q.| | P.h+} < N.}+N.N.)+ +)+K.Z.Y.8%I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I. ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/src/Mod/Ship/InitGui.py b/src/Mod/Ship/InitGui.py index 05dbfecb5f..6cf4c9689e 100644 --- a/src/Mod/Ship/InitGui.py +++ b/src/Mod/Ship/InitGui.py @@ -34,13 +34,13 @@ class ShipWorkbench ( Workbench ): # ToolBar list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"] self.appendToolbar("Ship design",list) - list = ["Ship_CreateTank"] + list = ["Ship_Weights", "Ship_CreateTank"] self.appendToolbar("Loading",list) # Menu list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"] self.appendMenu("Ship design",list) - list = ["Ship_CreateTank"] + list = ["Ship_Weights", "Ship_CreateTank"] self.appendToolbar("Loading",list) Gui.addWorkbench(ShipWorkbench()) diff --git a/src/Mod/Ship/Instance.py b/src/Mod/Ship/Instance.py index 16d77f8689..adba4d22b1 100644 --- a/src/Mod/Ship/Instance.py +++ b/src/Mod/Ship/Instance.py @@ -663,7 +663,7 @@ class ViewProviderShip: def sections(obj): """ Returns the discretization points of sections, with the advantage that is a list of nSections lists, with the points. - @param Ship object + @param obj Ship object @return Sections points """ histogram = obj.nPoints[:] @@ -674,3 +674,42 @@ def sections(obj): for j in range(histogram[i],histogram[i+1]): sections[i].append(points[j]) return sections + +def weights(obj): + """ Returns Ship weights list. If weights has not been sets, + this tool creates it. + @param obj Ship object + @return Weights list. None if errors + """ + # Test if is a ship instance + props = obj.PropertiesList + try: + props.index("IsShip") + except ValueError: + return None + if not obj.IsShip: + return None + # Test if properties already exist + try: + props.index("WeightNames") + except ValueError: + obj.addProperty("App::PropertyStringList","WeightNames","Ship", str(Translator.translate("Ship Weights names"))).WeightNames=[Translator.translate("Lightweight").__str__()] + try: + props.index("WeightMass") + except ValueError: + # Compute mass aproximation + from shipHydrostatics import Tools + disp = Tools.Displacement(obj,obj.Draft,0.0) + obj.addProperty("App::PropertyFloatList","WeightMass","Ship", str(Translator.translate("Ship Weights masses"))).WeightMass=[1000.0 * disp[1]] + try: + props.index("WeightPos") + except ValueError: + # Compute mass aproximation + from shipHydrostatics import Tools + disp = Tools.Displacement(obj,obj.Draft,0.0) + obj.addProperty("App::PropertyVectorList","WeightPos","Ship", str(Translator.translate("Ship Weights centers of gravity"))).WeightPos=[Vector(disp[2],0.0,obj.Draft)] + # Setup list + weights = [] + for i in range(0,len(obj.WeightNames)): + weights.append([obj.WeightNames[i], obj.WeightMass[i], obj.WeightPos[i]]) + return weights diff --git a/src/Mod/Ship/Makefile.am b/src/Mod/Ship/Makefile.am index 0251da41d6..35c1957b7a 100644 --- a/src/Mod/Ship/Makefile.am +++ b/src/Mod/Ship/Makefile.am @@ -34,6 +34,9 @@ nobase_data_DATA = \ Icons/ReparametrizeIco.xpm \ Icons/Ship.xcf \ Icons/Ship.xpm \ + Icons/Weight.png \ + Icons/Weight.xcf \ + Icons/Weight.xpm \ Icons/Tank.png \ Icons/Tank.xcf \ Icons/Tank.xpm \ @@ -66,6 +69,9 @@ nobase_data_DATA = \ shipUtils/Math.py \ shipUtils/Paths.py \ shipUtils/Translator.py \ + tankWeights/__init__.py \ + tankWeights/TaskPanel.py \ + tankWeights/TaskPanel.ui \ tankCreateTank/__init__.py \ tankCreateTank/TaskPanel.py \ tankCreateTank/TaskPanel.ui diff --git a/src/Mod/Ship/ShipGui.py b/src/Mod/Ship/ShipGui.py index f62bebfb4d..71a9e75e49 100644 --- a/src/Mod/Ship/ShipGui.py +++ b/src/Mod/Ship/ShipGui.py @@ -84,6 +84,18 @@ class 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 @@ -101,4 +113,5 @@ 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()) diff --git a/src/Mod/Ship/shipHydrostatics/Tools.py b/src/Mod/Ship/shipHydrostatics/Tools.py index a2b1f2c65f..3db0039573 100644 --- a/src/Mod/Ship/shipHydrostatics/Tools.py +++ b/src/Mod/Ship/shipHydrostatics/Tools.py @@ -116,7 +116,7 @@ def Displacement(ship, draft, trim): @param ship Selected ship instance @param draft Draft. @param trim Trim in degrees. - @return [areas,disp,xcb]: \n + @return [areas,disp,xcb,Cb]: \n areas : Area of each section \n disp: Ship displacement \n xcb: X bouyance center coordinate diff --git a/src/Mod/Ship/tankWeights/TaskPanel.py b/src/Mod/Ship/tankWeights/TaskPanel.py new file mode 100644 index 0000000000..14cda21e57 --- /dev/null +++ b/src/Mod/Ship/tankWeights/TaskPanel.py @@ -0,0 +1,212 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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 +from Instance import * +from shipUtils import Paths, Translator + +class TaskPanel: + def __init__(self): + self.ui = Paths.modulePath() + "/tankWeights/TaskPanel.ui" + self.ship = None + + def accept(self): + if not self.ship: + return False + # Setup lists + name = [] + mass = [] + pos = [] + for i in range(0,self.form.weights.rowCount() - 1): + item = self.form.weights.item(i,0) + name.append(item.text().__str__()) + item = self.form.weights.item(i,1) + mass.append(item.text().toFloat()[0]) + vec = [] + item = self.form.weights.item(i,2) + vec.append(item.text().toFloat()[0]) + item = self.form.weights.item(i,3) + vec.append(item.text().toFloat()[0]) + item = self.form.weights.item(i,4) + vec.append(item.text().toFloat()[0]) + pos.append(App.Base.Vector(vec[0],vec[1],vec[2])) + # Send to ship + self.ship.WeightNames = name[:] + self.ship.WeightMass = mass[:] + self.ship.WeightPos = pos[:] + return True + + def reject(self): + if not self.ship: + return False + 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.weights = form.findChild(QtGui.QTableWidget, "Weights") + self.form = form + # Initial values + if self.initValues(): + return True + self.retranslateUi() + # Connect Signals and Slots + QtCore.QObject.connect(form.weights,QtCore.SIGNAL("cellChanged(int,int)"),self.onTableItem); + + 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): + """ Get selected geometry. + @return False if sucessfully values initialized. + """ + # Get selected objects + selObjs = FreeCADGui.Selection.getSelection() + if not selObjs: + msg = Translator.translate("Ship instance must be selected (no object selected)\n") + App.Console.PrintError(msg) + return True + for i in range(0,len(selObjs)): + obj = selObjs[i] + # Test if is a ship instance + props = obj.PropertiesList + try: + props.index("IsShip") + except ValueError: + continue + if obj.IsShip: + # Test if another ship already selected + if self.ship: + msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n") + App.Console.PrintWarning(msg) + break + self.ship = obj + # Test if any valid ship was selected + if not self.ship: + msg = Translator.translate("Ship instance must be selected (no valid ship found at selected objects)\n") + App.Console.PrintError(msg) + return True + # Get weights + w = weights(self.ship) + # Set the items + self.form.weights.setRowCount(len(w)+1) + for i in range(0,len(w)): + item = QtGui.QTableWidgetItem(w[i][0]) + self.form.weights.setItem(i,0,item) + string = '%g' % (w[i][1]) + item = QtGui.QTableWidgetItem(string) + self.form.weights.setItem(i,1,item) + string = '%g' % (w[i][2].x) + item = QtGui.QTableWidgetItem(string) + self.form.weights.setItem(i,2,item) + string = '%g' % (w[i][2].y) + item = QtGui.QTableWidgetItem(string) + self.form.weights.setItem(i,3,item) + string = '%g' % (w[i][2].z) + item = QtGui.QTableWidgetItem(string) + self.form.weights.setItem(i,4,item) + 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("Set weights")) + labels = [] + labels.append(Translator.translate("Name")) + labels.append(Translator.translate("Mass") + " [kg]") + labels.append(QtCore.QString("g.x [m]")) + labels.append(QtCore.QString("g.y [m]")) + labels.append(QtCore.QString("g.z [m]")) + self.form.weights.setHorizontalHeaderLabels(labels) + + def onTableItem(self, row, column): + """ Function called when an item of table is changed. + @param row Changed item row + @param column Changed item column + """ + item = self.form.weights.item(row,column) + # Row deletion + if column == 0: + if not item.text(): + self.form.weights.removeRow(row) + # Ensure that exist one empty item at the end + nRow = self.form.weights.rowCount() + last = self.form.weights.item(nRow-1,0) + if last: + if(last.text() != ''): + self.form.weights.setRowCount(nRow+1) + # Fields must be numbers + for i in range(0,self.form.weights.rowCount()-1): # Avoid last row + for j in range(1,self.form.weights.columnCount()): # Avoid name column + item = self.form.weights.item(i,j) + if not item: + item = QtGui.QTableWidgetItem('0.0') + self.form.weights.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 diff --git a/src/Mod/Ship/tankWeights/TaskPanel.ui b/src/Mod/Ship/tankWeights/TaskPanel.ui new file mode 100644 index 0000000000..23dc4ff1bb --- /dev/null +++ b/src/Mod/Ship/tankWeights/TaskPanel.ui @@ -0,0 +1,97 @@ + + + TaskPanel + + + + 0 + 0 + 260 + 256 + + + + Set wieghts + + + + + + true + + + 1 + + + 5 + + + false + + + 20 + + + false + + + false + + + + + Name + + + + + Mass [kg] + + + + + g.x [m] + + + + + g.y [m] + + + + + g.z [m] + + + + + Lightweight + + + + + 0.0 + + + + + 0.0 + + + + + 0.0 + + + + + 0.0 + + + + + + + + + diff --git a/src/Mod/Ship/tankWeights/__init__.py b/src/Mod/Ship/tankWeights/__init__.py new file mode 100644 index 0000000000..cbfb57d75d --- /dev/null +++ b/src/Mod/Ship/tankWeights/__init__.py @@ -0,0 +1,36 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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() From 4601fea5542beb62d54050eb31e4e35d92ade3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Mon, 14 May 2012 14:42:14 +0200 Subject: [PATCH 281/351] Added annotations to ship weights definition tool --- src/Mod/Ship/CMakeLists.txt | 1 + src/Mod/Ship/Makefile.am | 1 + src/Mod/Ship/tankWeights/Preview.py | 106 ++++++++++++++++++++++++++ src/Mod/Ship/tankWeights/TaskPanel.py | 34 +++++++++ 4 files changed, 142 insertions(+) create mode 100644 src/Mod/Ship/tankWeights/Preview.py diff --git a/src/Mod/Ship/CMakeLists.txt b/src/Mod/Ship/CMakeLists.txt index a3c14ce960..c44e313aba 100644 --- a/src/Mod/Ship/CMakeLists.txt +++ b/src/Mod/Ship/CMakeLists.txt @@ -101,6 +101,7 @@ SOURCE_GROUP("shiputils" FILES ${ShipUtils_SRCS}) SET(ShipWeights_SRCS tankWeights/__init__.py + tankWeights/Preview.py tankWeights/TaskPanel.py tankWeights/TaskPanel.ui ) diff --git a/src/Mod/Ship/Makefile.am b/src/Mod/Ship/Makefile.am index 35c1957b7a..01b296c011 100644 --- a/src/Mod/Ship/Makefile.am +++ b/src/Mod/Ship/Makefile.am @@ -70,6 +70,7 @@ nobase_data_DATA = \ shipUtils/Paths.py \ shipUtils/Translator.py \ tankWeights/__init__.py \ + tankWeights/Preview.py \ tankWeights/TaskPanel.py \ tankWeights/TaskPanel.ui \ tankCreateTank/__init__.py \ diff --git a/src/Mod/Ship/tankWeights/Preview.py b/src/Mod/Ship/tankWeights/Preview.py new file mode 100644 index 0000000000..571155bb9d --- /dev/null +++ b/src/Mod/Ship/tankWeights/Preview.py @@ -0,0 +1,106 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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,FreeCADGui +from FreeCAD import Base +from FreeCAD import Part +# FreeCADShip modules +from shipUtils import Paths, Translator + +class Preview(object): + def __init__(self): + """ Constructor. + """ + self.objects = [] + + def reinit(self): + """ Reinitializate drawer. + """ + self.clean() + + def update(self, names, pos): + """ Update the 3D view printing annotations. + @param names Weight names. + @param pos Weight positions (FreeCAD::Base::Vector). + """ + # Destroy all previous entities + self.clean() + for i in range(0, len(names)): + # Draw gravity line + line = Part.makeLine((pos[i].x,pos[i].y,pos[i].z),(pos[i].x,pos[i].y,pos[i].z - 9.81)) + Part.show(line) + objs = FreeCAD.ActiveDocument.Objects + self.objects.append(objs[-1]) + objs[-1].Label = names[i] + 'Line' + # Draw circles + circle = Part.makeCircle(0.5, pos[i], Base.Vector(1.0,0.0,0.0)) + Part.show(circle) + objs = FreeCAD.ActiveDocument.Objects + self.objects.append(objs[-1]) + objs[-1].Label = names[i] + 'CircleX' + circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,1.0,0.0)) + Part.show(circle) + objs = FreeCAD.ActiveDocument.Objects + self.objects.append(objs[-1]) + objs[-1].Label = names[i] + 'CircleY' + circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,0.0,1.0)) + Part.show(circle) + objs = FreeCAD.ActiveDocument.Objects + self.objects.append(objs[-1]) + objs[-1].Label = names[i] + 'CircleZ' + # Draw annotation + self.objects.append(DrawText(names[i] + 'Text', names[i], Base.Vector(pos[i].x+1.0,pos[i].y,pos[i].z))) + + def clean(self): + """ Erase all annotations from screen. + """ + for i in range(0,len(self.objects)): + if not FreeCAD.ActiveDocument.getObject(self.objects[i].Name): + continue + FreeCAD.ActiveDocument.removeObject(self.objects[i].Name) + self.objects = [] + +def DrawText(name, string, position, displayMode="Screen", angle=0.0, justification="Left", colour=(0.00,0.00,0.00), size=12): + """ Draws a text in a desired position. + @param name Name of the object + @param string Text to draw (recommended format u'') + @param position Point to draw the text + @param angle Counter clockwise rotation of text + @param justification Alignement of the text ("Left", "Right" or "Center") + @param colour Colour of the text + @param size Font size + @return FreeCAD annotation object + """ + # Create the object + text = FreeCAD.ActiveDocument.addObject("App::Annotation",name) + # Set the text + text.LabelText = [string, u''] + # Set the options + text.Position = position + FreeCADGui.ActiveDocument.getObject(text.Name).Rotation = angle + FreeCADGui.ActiveDocument.getObject(text.Name).Justification = justification + FreeCADGui.ActiveDocument.getObject(text.Name).FontSize = size + FreeCADGui.ActiveDocument.getObject(text.Name).TextColor = colour + FreeCADGui.ActiveDocument.getObject(text.Name).DisplayMode = displayMode + return FreeCAD.ActiveDocument.getObject(text.Name) diff --git a/src/Mod/Ship/tankWeights/TaskPanel.py b/src/Mod/Ship/tankWeights/TaskPanel.py index 14cda21e57..a01f7c73c2 100644 --- a/src/Mod/Ship/tankWeights/TaskPanel.py +++ b/src/Mod/Ship/tankWeights/TaskPanel.py @@ -27,6 +27,7 @@ import FreeCADGui as Gui # Qt library from PyQt4 import QtGui,QtCore # Module +import Preview from Instance import * from shipUtils import Paths, Translator @@ -34,8 +35,10 @@ class TaskPanel: def __init__(self): self.ui = Paths.modulePath() + "/tankWeights/TaskPanel.ui" self.ship = None + self.preview = Preview.Preview() def accept(self): + self.preview.clean() if not self.ship: return False # Setup lists @@ -62,6 +65,7 @@ class TaskPanel: return True def reject(self): + self.preview.clean() if not self.ship: return False return True @@ -98,6 +102,21 @@ class TaskPanel: self.retranslateUi() # Connect Signals and Slots QtCore.QObject.connect(form.weights,QtCore.SIGNAL("cellChanged(int,int)"),self.onTableItem); + # Update screen + name = [] + pos = [] + for i in range(0,self.form.weights.rowCount() - 1): + item = self.form.weights.item(i,0) + name.append(item.text().__str__()) + vec = [] + item = self.form.weights.item(i,2) + vec.append(item.text().toFloat()[0]) + item = self.form.weights.item(i,3) + vec.append(item.text().toFloat()[0]) + item = self.form.weights.item(i,4) + vec.append(item.text().toFloat()[0]) + pos.append(App.Base.Vector(vec[0],vec[1],vec[2])) + self.preview.update(name, pos) def getMainWindow(self): "returns the main window" @@ -202,6 +221,21 @@ class TaskPanel: (number,flag) = item.text().toFloat() if not flag: item.setText('0.0') + # Update screen annotations + name = [] + pos = [] + for i in range(0,self.form.weights.rowCount() - 1): + item = self.form.weights.item(i,0) + name.append(item.text().__str__()) + vec = [] + item = self.form.weights.item(i,2) + vec.append(item.text().toFloat()[0]) + item = self.form.weights.item(i,3) + vec.append(item.text().toFloat()[0]) + item = self.form.weights.item(i,4) + vec.append(item.text().toFloat()[0]) + pos.append(App.Base.Vector(vec[0],vec[1],vec[2])) + self.preview.update(name, pos) def createTask(): panel = TaskPanel() From e30bc42696d15a8601e9eb48848c18b3360aad67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Tue, 22 May 2012 11:10:17 +0200 Subject: [PATCH 282/351] Fixed UI symbol --- src/Mod/Ship/tankCreateTank/TaskPanel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Ship/tankCreateTank/TaskPanel.py b/src/Mod/Ship/tankCreateTank/TaskPanel.py index ec6394638e..4eddbd03e7 100644 --- a/src/Mod/Ship/tankCreateTank/TaskPanel.py +++ b/src/Mod/Ship/tankCreateTank/TaskPanel.py @@ -139,7 +139,7 @@ class TaskPanel: """ Set user interface locale strings. """ self.form.setWindowTitle(Translator.translate("Create a new tank")) - name = Translator.translate("Filling level") + " (\%)" + name = Translator.translate("Filling level") + " (%)" self.form.findChild(QtGui.QLabel, "LevelLabel").setText(name) name = '\n' name = name + Translator.translate("Density") From 3c0b8af49dae7c6e82765c2565121817bd682ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Tue, 22 May 2012 11:10:55 +0200 Subject: [PATCH 283/351] Started GZ curves computation tool development --- src/Mod/Ship/CMakeLists.txt | 15 +- src/Mod/Ship/InitGui.py | 4 +- src/Mod/Ship/Makefile.am | 5 +- src/Mod/Ship/ShipGui.py | 13 ++ src/Mod/Ship/TankInstance.py | 62 +++++++- src/Mod/Ship/tankGZ/TaskPanel.py | 233 +++++++++++++++++++++++++++++++ src/Mod/Ship/tankGZ/TaskPanel.ui | 140 +++++++++++++++++++ src/Mod/Ship/tankGZ/__init__.py | 36 +++++ 8 files changed, 503 insertions(+), 5 deletions(-) create mode 100644 src/Mod/Ship/tankGZ/TaskPanel.py create mode 100644 src/Mod/Ship/tankGZ/TaskPanel.ui create mode 100644 src/Mod/Ship/tankGZ/__init__.py diff --git a/src/Mod/Ship/CMakeLists.txt b/src/Mod/Ship/CMakeLists.txt index c44e313aba..3106dbc47b 100644 --- a/src/Mod/Ship/CMakeLists.txt +++ b/src/Mod/Ship/CMakeLists.txt @@ -114,7 +114,14 @@ SET(ShipCreateTank_SRCS ) SOURCE_GROUP("shipcreatetank" FILES ${ShipCreateTank_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}) +SET(ShipGZ_SRCS + tankGZ/__init__.py + tankGZ/TaskPanel.py + tankGZ/TaskPanel.ui +) +SOURCE_GROUP("shipcreatetank" FILES ${ShipCreateTank_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}) ADD_CUSTOM_TARGET(Ship ALL SOURCES ${all_files} @@ -182,6 +189,12 @@ INSTALL( DESTINATION Mod/Ship/tankCreateTank ) +INSTALL( + FILES + ${ShipGZ_SRCS} + DESTINATION + Mod/Ship/tankGZ +) INSTALL( FILES ${ShipMain_SRCS} diff --git a/src/Mod/Ship/InitGui.py b/src/Mod/Ship/InitGui.py index 6cf4c9689e..aa8a409aff 100644 --- a/src/Mod/Ship/InitGui.py +++ b/src/Mod/Ship/InitGui.py @@ -34,13 +34,13 @@ class ShipWorkbench ( Workbench ): # ToolBar list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"] self.appendToolbar("Ship design",list) - list = ["Ship_Weights", "Ship_CreateTank"] + list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"] self.appendToolbar("Loading",list) # Menu list = ["Ship_LoadExample", "Ship_CreateShip", "Ship_OutlineDraw", "Ship_AreasCurve", "Ship_Hydrostatics"] self.appendMenu("Ship design",list) - list = ["Ship_Weights", "Ship_CreateTank"] + list = ["Ship_Weights", "Ship_CreateTank", "Ship_GZ"] self.appendToolbar("Loading",list) Gui.addWorkbench(ShipWorkbench()) diff --git a/src/Mod/Ship/Makefile.am b/src/Mod/Ship/Makefile.am index 01b296c011..54b7ecf6a5 100644 --- a/src/Mod/Ship/Makefile.am +++ b/src/Mod/Ship/Makefile.am @@ -75,7 +75,10 @@ nobase_data_DATA = \ tankWeights/TaskPanel.ui \ tankCreateTank/__init__.py \ tankCreateTank/TaskPanel.py \ - tankCreateTank/TaskPanel.ui + tankCreateTank/TaskPanel.ui \ + tankGZ/__init__.py \ + tankGZ/TaskPanel.py \ + tankGZ/TaskPanel.ui CLEANFILES = $(BUILT_SOURCES) diff --git a/src/Mod/Ship/ShipGui.py b/src/Mod/Ship/ShipGui.py index 71a9e75e49..c97f1e9087 100644 --- a/src/Mod/Ship/ShipGui.py +++ b/src/Mod/Ship/ShipGui.py @@ -108,6 +108,18 @@ class CreateTank: 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} + FreeCADGui.addCommand('Ship_LoadExample', LoadExample()) FreeCADGui.addCommand('Ship_CreateShip', CreateShip()) FreeCADGui.addCommand('Ship_OutlineDraw', OutlineDraw()) @@ -115,3 +127,4 @@ 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()) diff --git a/src/Mod/Ship/TankInstance.py b/src/Mod/Ship/TankInstance.py index 584aa0f974..6e44795f86 100644 --- a/src/Mod/Ship/TankInstance.py +++ b/src/Mod/Ship/TankInstance.py @@ -45,7 +45,7 @@ class ShipTank: # Add uniqueness property to identify Tank instances obj.addProperty("App::PropertyBool","IsShipTank","ShipTank", str(Translator.translate("True if is a valid ship tank instance"))).IsShipTank=True # Add general options - obj.addProperty("App::PropertyFloat","Level","ShipTank", str(Translator.translate("Filling level"))).Level=level + obj.addProperty("App::PropertyFloat","Level","ShipTank", str(Translator.translate("Fluid filling level percentage"))).Level=level obj.addProperty("App::PropertyFloat","Density","ShipTank", str(Translator.translate("Inside fluid density"))).Density=density # Add shapes shape = self.computeShape(solid) @@ -1884,3 +1884,63 @@ class ViewProviderShipTank: " ", " "}; """ + +def tankWeight(obj, angles=Vector(0.0,0.0,0.0), cor=Vector(0.0,0.0,0.0)): + """ Compute tank fluid weight and their center of gravity. + @param obj Tank object. + @param angles Tank angles, Roll, Pitch and Yaw. + @param cor Center or rotation. + @return Weight and center of gravity. None if errors detected + """ + # Test if is a tank instance + props = obj.PropertiesList + try: + props.index("IsShipTank") + except ValueError: + return None + if not obj.IsShipTank: + return None + # Get object solids + Solids = obj.Shape.Solids + W = [0.0, 0.0, 0.0, 0.0] + for s in Solids: + # Get fluid volume + bbox = s.BoundBox + z0 = bbox.ZMin + z1 = bbox.ZMax + dz = obj.Level/100.0 * (z1-z0) + z = z0 + dz + dx = bbox.XMax-bbox.XMin + dy = bbox.YMax-bbox.YMin + box = Part.makeBox(3.0*(dx), 3.0*(dy), (z1-z0)+dz, Vector(bbox.XMin-dx, bbox.YMin-dy, bbox.ZMin-(z1-z0))) + fluid = s.common(box) + vol = fluid.Volume + W[0] = W[0] + vol*obj.Density + # Compute fluid solid in rotated position (non linear rotation + # are ussually computed as Roll -> Pitch -> Yaw). + s.rotate(cor, Vector(1.0,0.0,0.0), angles.x) + s.rotate(cor, Vector(0.0,1.0,0.0), angles.y) + s.rotate(cor, Vector(0.0,0.0,1.0), angles.z) + bbox = s.BoundBox + z0 = bbox.ZMin + z1 = bbox.ZMax + dx = bbox.XMax-bbox.XMin + dy = bbox.YMax-bbox.YMin + Error = 0.01*vol + z = 0.0 + v = 0.0 + while(abs(vol - v) > Error): + z = z + (vol - v) / (dx*dy) + dz = z - z0 + box = Part.makeBox(3.0*(dx), 3.0*(dy), (z1-z0)+dz, Vector(bbox.XMin-dx, bbox.YMin-dy, bbox.ZMin-(z1-z0))) + fluid = s.common(box) + v = fluid.Volume + if(abs(vol - v) / (dx*dy) <= 0.000001): + break + # Add fluid moments + for f in fluid.Solids: + cog = f.CenterOfMass + W[1] = W[1] + f.Volume*obj.Density*cog.x + W[2] = W[2] + f.Volume*obj.Density*cog.y + W[3] = W[3] + f.Volume*obj.Density*cog.z + return [W[0], W[1]/W[0], W[2]/W[0], W[3]/W[0]] diff --git a/src/Mod/Ship/tankGZ/TaskPanel.py b/src/Mod/Ship/tankGZ/TaskPanel.py new file mode 100644 index 0000000000..8a47e67ae0 --- /dev/null +++ b/src/Mod/Ship/tankGZ/TaskPanel.py @@ -0,0 +1,233 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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 +from Instance import * +from TankInstance import * +from shipUtils import Paths, Translator + +class TaskPanel: + def __init__(self): + self.ui = Paths.modulePath() + "/tankGZ/TaskPanel.ui" + self.ship = None + self.tanks = {} + + def accept(self): + if not self.ship: + return False + return True + + def reject(self): + if not self.ship: + return False + 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.tanks = form.findChild(QtGui.QListWidget, "Tanks") + form.disp = form.findChild(QtGui.QLabel, "DisplacementLabel") + form.draft = form.findChild(QtGui.QLabel, "DraftLabel") + self.form = form + # Initial values + if self.initValues(): + return True + self.retranslateUi() + self.onTanksSelection() + # Connect Signals and Slots + QtCore.QObject.connect(form.tanks,QtCore.SIGNAL("itemSelectionChanged()"),self.onTanksSelection) + return False + + 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): + """ Get selected geometry. + @return False if sucessfully values initialized. + """ + # Get selected objects + selObjs = FreeCADGui.Selection.getSelection() + if not selObjs: + msg = Translator.translate("Ship instance must be selected (no object selected)\n") + App.Console.PrintError(msg) + return True + for i in range(0,len(selObjs)): + obj = selObjs[i] + # Test if is a ship instance + props = obj.PropertiesList + try: + props.index("IsShip") + except ValueError: + continue + if obj.IsShip: + # Test if another ship already selected + if self.ship: + msg = Translator.translate("More than one ship selected (extra ship will be neglected)\n") + App.Console.PrintWarning(msg) + break + self.ship = obj + # Test if any valid ship was selected + if not self.ship: + msg = Translator.translate("Ship instance must be selected (no valid ship found at selected objects)\n") + App.Console.PrintError(msg) + return True + props = self.ship.PropertiesList + try: + props.index("WeightNames") + except: + msg = Translator.translate("Ship weights has not been set. You need to set weights before use this tool.\n") + App.Console.PrintError(msg) + return True + # Setup available tanks list + objs = App.ActiveDocument.Objects + iconPath = Paths.iconsPath() + "/Tank.xpm" + icon = QtGui.QIcon(QtGui.QPixmap(iconPath)) + for obj in objs: + # Try to get valid tank property + props = obj.PropertiesList + try: + props.index("IsShipTank") + except ValueError: + continue + if not obj.IsShipTank: + continue + # Add tank to list + name = obj.Name + label = obj.Label + tag = label + ' (' + name + ')' + self.tanks[tag] = name + # self.tanks.append([name, tag]) + item = QtGui.QListWidgetItem(tag) + item.setIcon(icon) + self.form.tanks.addItem(item) + 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("GZ curve computation")) + self.form.findChild(QtGui.QGroupBox, "LoadConditionGroup").setTitle(Translator.translate("Loading condition.")) + + def onTanksSelection(self): + """ Called when tanks are selected or deselected. + """ + # Set displacement label + disp = self.computeDisplacement() + self.form.disp.setText(Translator.translate("Displacement") + ' %g [kg]' % (disp[0])) + + def getTanks(self): + """ Get the selected tanks objects list. + @return Selected tanks list. + """ + items = self.form.tanks.selectedItems() + tanks = [] + for item in items: + tag = str(item.text()) + name = self.tanks[tag] + t = App.ActiveDocument.getObject('Tank') + if not t: + continue + tanks.append(t) + return tanks + + def computeDisplacement(self): + """ Computes ship displacement. + @return Ship displacement and center of gravity. None if errors detected. + """ + if not self.ship: + return None + # Test if is a ship instance + obj = self.ship + props = obj.PropertiesList + try: + props.index("IsShip") + except ValueError: + return None + if not obj.IsShip: + return None + # Test if properties already exist + try: + props.index("WeightNames") + except: + return None + # Get ship structure weights + W = [0.0, 0.0, 0.0, 0.0] + sWeights = weights(obj) + for w in sWeights: + W[0] = W[0] + w[1] + W[1] = W[1] + w[1]*w[2][0] + W[2] = W[2] + w[1]*w[2][1] + W[3] = W[3] + w[1]*w[2][2] + # Get selected tanks weights + tanks = self.getTanks() + for t in tanks: + w = tankWeight(t) + W[0] = W[0] + w[0] + W[1] = W[1] + w[0]*w[1] + W[2] = W[2] + w[0]*w[2] + W[3] = W[3] + w[0]*w[3] + return [W[0], W[1]/W[0], W[2]/W[0], W[3]/W[0]] + +def createTask(): + panel = TaskPanel() + Gui.Control.showDialog(panel) + if panel.setupUi(): + Gui.Control.closeDialog(panel) + return None + return panel diff --git a/src/Mod/Ship/tankGZ/TaskPanel.ui b/src/Mod/Ship/tankGZ/TaskPanel.ui new file mode 100644 index 0000000000..a1f16c39b7 --- /dev/null +++ b/src/Mod/Ship/tankGZ/TaskPanel.ui @@ -0,0 +1,140 @@ + + + TaskPanel + + + + 0 + 0 + 256 + 368 + + + + + 256 + 368 + + + + GZ curve computation + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Loading condition + + + + + 0 + 20 + 231 + 151 + + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::MultiSelection + + + + + + + Displacement = 0 [kg] + + + + + + + Draft = 0 [m] + + + + + + + + + + + + 0 + 0 + + + + Roll angles + + + + + 0 + 20 + 231 + 141 + + + + + QLayout::SetMinimumSize + + + + + Start [deg] + + + + + + + End [deg] + + + + + + + Number of points + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Ship/tankGZ/__init__.py b/src/Mod/Ship/tankGZ/__init__.py new file mode 100644 index 0000000000..cbfb57d75d --- /dev/null +++ b/src/Mod/Ship/tankGZ/__init__.py @@ -0,0 +1,36 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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() From bdd5e0bc999d917727287ca76dd848ce24f8bc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Wed, 23 May 2012 19:04:35 +0200 Subject: [PATCH 284/351] Added draft computation to GZ tool. --- src/Mod/Ship/tankGZ/TaskPanel.py | 47 ++++++++++++++++++++------------ src/Mod/Ship/tankGZ/TaskPanel.ui | 2 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/Mod/Ship/tankGZ/TaskPanel.py b/src/Mod/Ship/tankGZ/TaskPanel.py index 8a47e67ae0..9864bfd10c 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.py +++ b/src/Mod/Ship/tankGZ/TaskPanel.py @@ -30,12 +30,14 @@ from PyQt4 import QtGui,QtCore from Instance import * from TankInstance import * from shipUtils import Paths, Translator +from shipHydrostatics import Tools as Hydrostatics class TaskPanel: def __init__(self): self.ui = Paths.modulePath() + "/tankGZ/TaskPanel.ui" self.ship = None self.tanks = {} + self.trim = 0.0 def accept(self): if not self.ship: @@ -163,14 +165,18 @@ class TaskPanel: """ self.form.setWindowTitle(Translator.translate("GZ curve computation")) self.form.findChild(QtGui.QGroupBox, "LoadConditionGroup").setTitle(Translator.translate("Loading condition.")) + self.form.findChild(QtGui.QGroupBox, "AnglesGroup").setTitle(Translator.translate("Roll angles.")) def onTanksSelection(self): """ Called when tanks are selected or deselected. """ # Set displacement label disp = self.computeDisplacement() - self.form.disp.setText(Translator.translate("Displacement") + ' %g [kg]' % (disp[0])) - + self.form.disp.setText(Translator.translate("Displacement") + ' = %g [kg]' % (disp[0])) + # Set draft label + draft = self.computeDraft(disp[0]) + self.form.draft.setText(Translator.translate("Draft") + ' = %g [m]' % (draft)) + def getTanks(self): """ Get the selected tanks objects list. @return Selected tanks list. @@ -192,23 +198,9 @@ class TaskPanel: """ if not self.ship: return None - # Test if is a ship instance - obj = self.ship - props = obj.PropertiesList - try: - props.index("IsShip") - except ValueError: - return None - if not obj.IsShip: - return None - # Test if properties already exist - try: - props.index("WeightNames") - except: - return None # Get ship structure weights W = [0.0, 0.0, 0.0, 0.0] - sWeights = weights(obj) + sWeights = weights(self.ship) for w in sWeights: W[0] = W[0] + w[1] W[1] = W[1] + w[1]*w[2][0] @@ -224,6 +216,27 @@ class TaskPanel: W[3] = W[3] + w[0]*w[3] return [W[0], W[1]/W[0], W[2]/W[0], W[3]/W[0]] + def computeDraft(self, disp): + """ Computes ship draft. + @param disp Ship displacement. + @return Ship draft. None if errors detected. + @note 0 trim will be assumed. + """ + if not self.ship: + return None + # Initial condition + trim = 0.0 + dens = 1025 + bbox = self.ship.Shape.BoundBox + draft = bbox.ZMin + dx = bbox.XMax - bbox.XMin + dy = bbox.YMax - bbox.YMin + w = 0.0 + while(abs(disp - w)/disp > 0.01): + draft = draft + (disp - w) / (dens*dx*dy) + w = 1000.0*Hydrostatics.Displacement(self.ship, draft, trim)[1] + return draft + def createTask(): panel = TaskPanel() Gui.Control.showDialog(panel) diff --git a/src/Mod/Ship/tankGZ/TaskPanel.ui b/src/Mod/Ship/tankGZ/TaskPanel.ui index a1f16c39b7..41823bf714 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.ui +++ b/src/Mod/Ship/tankGZ/TaskPanel.ui @@ -76,7 +76,7 @@ - + 0 From 6bc60de9bd04ecc7f1bfc2caa7b126ad6b3582f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Sat, 26 May 2012 15:33:29 +0200 Subject: [PATCH 285/351] Added trim option to GZ curves tool --- src/Mod/Ship/shipHydrostatics/Tools.py | 6 +- src/Mod/Ship/tankGZ/TaskPanel.py | 106 ++++++++++++++++++++----- src/Mod/Ship/tankGZ/TaskPanel.ui | 84 +++++++++++++++++--- 3 files changed, 163 insertions(+), 33 deletions(-) diff --git a/src/Mod/Ship/shipHydrostatics/Tools.py b/src/Mod/Ship/shipHydrostatics/Tools.py index 3db0039573..2c0e5aa36b 100644 --- a/src/Mod/Ship/shipHydrostatics/Tools.py +++ b/src/Mod/Ship/shipHydrostatics/Tools.py @@ -439,9 +439,9 @@ def KBT(ship, draft, trim, roll=0.0): @param draft Draft. @param trim Trim in degrees. @param roll Roll angle in degrees. - @return [KBTx, KBTy]: \n - KBTy : TRansversal KB y coordinate \n - KBTz : TRansversal KB z coordinate + @return [KBTy, KBTz]: \n + KBTy : Transversal KB y coordinate \n + KBTz : Transversal KB z coordinate """ angle = math.radians(trim) rAngle = math.radians(roll) diff --git a/src/Mod/Ship/tankGZ/TaskPanel.py b/src/Mod/Ship/tankGZ/TaskPanel.py index 9864bfd10c..48a23242bb 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.py +++ b/src/Mod/Ship/tankGZ/TaskPanel.py @@ -21,6 +21,7 @@ #* * #*************************************************************************** +import math # FreeCAD modules import FreeCAD as App import FreeCADGui as Gui @@ -37,7 +38,6 @@ class TaskPanel: self.ui = Paths.modulePath() + "/tankGZ/TaskPanel.ui" self.ship = None self.tanks = {} - self.trim = 0.0 def accept(self): if not self.ship: @@ -71,11 +71,13 @@ class TaskPanel: pass def setupUi(self): - mw = self.getMainWindow() - form = mw.findChild(QtGui.QWidget, "TaskPanel") - form.tanks = form.findChild(QtGui.QListWidget, "Tanks") - form.disp = form.findChild(QtGui.QLabel, "DisplacementLabel") - form.draft = form.findChild(QtGui.QLabel, "DraftLabel") + mw = self.getMainWindow() + form = mw.findChild(QtGui.QWidget, "TaskPanel") + form.tanks = form.findChild(QtGui.QListWidget, "Tanks") + form.disp = form.findChild(QtGui.QLabel, "DisplacementLabel") + form.draft = form.findChild(QtGui.QLabel, "DraftLabel") + form.trim = form.findChild(QtGui.QDoubleSpinBox, "Trim") + form.autoTrim = form.findChild(QtGui.QPushButton, "TrimAutoCompute") self.form = form # Initial values if self.initValues(): @@ -84,6 +86,8 @@ class TaskPanel: self.onTanksSelection() # Connect Signals and Slots QtCore.QObject.connect(form.tanks,QtCore.SIGNAL("itemSelectionChanged()"),self.onTanksSelection) + QtCore.QObject.connect(form.trim,QtCore.SIGNAL("valueChanged(double)"),self.onTrim) + QtCore.QObject.connect(form.autoTrim,QtCore.SIGNAL("pressed()"),self.onAutoTrim) return False def getMainWindow(self): @@ -166,6 +170,10 @@ class TaskPanel: self.form.setWindowTitle(Translator.translate("GZ curve computation")) self.form.findChild(QtGui.QGroupBox, "LoadConditionGroup").setTitle(Translator.translate("Loading condition.")) self.form.findChild(QtGui.QGroupBox, "AnglesGroup").setTitle(Translator.translate("Roll angles.")) + self.form.findChild(QtGui.QLabel, "TrimLabel").setText(Translator.translate("Trim") + " [deg]") + self.form.findChild(QtGui.QLabel, "StartAngleLabel").setText(Translator.translate("Start") + " [deg]") + self.form.findChild(QtGui.QLabel, "EndAngleLabel").setText(Translator.translate("Start") + " [deg]") + self.form.findChild(QtGui.QLabel, "NAngleLabel").setText(Translator.translate("Number of points")) def onTanksSelection(self): """ Called when tanks are selected or deselected. @@ -174,8 +182,59 @@ class TaskPanel: disp = self.computeDisplacement() self.form.disp.setText(Translator.translate("Displacement") + ' = %g [kg]' % (disp[0])) # Set draft label - draft = self.computeDraft(disp[0]) - self.form.draft.setText(Translator.translate("Draft") + ' = %g [m]' % (draft)) + draft = self.computeDraft(disp[0], self.form.trim.value()) + self.form.draft.setText(Translator.translate("Draft") + ' = %g [m]' % (draft[0])) + + def onTrim(self, trim): + """ Called when trim angle value is changed. + @param trim Selected trim angle. + """ + self.onTanksSelection() + + def onAutoTrim(self): + """ Called when trim angle must be auto computed. + """ + # Start at null trim angle + trim = 0.0 + # Get center of gravity + disp = self.computeDisplacement(trim) + G = [disp[1], disp[2], disp[3]] + disp = disp[0] + # Get bouyancy center + draft = self.computeDraft(disp) + xcb = draft[1] + draft = draft[0] + KBT = Hydrostatics.KBT(self.ship, draft, trim) + B = [xcb, KBT[0], KBT[1]] + # Get stability initial condition + BG = [G[0]-B[0], G[1]-B[1], G[2]-B[2]] + x = BG[0]*math.cos(math.radians(trim)) - BG[2]*math.sin(math.radians(trim)) + y = BG[1] + z = BG[0]*math.sin(math.radians(trim)) + BG[2]*math.cos(math.radians(trim)) + var = math.degrees(math.atan2(x,z)) + # Iterate looking stability point + dVar = math.copysign(0.0033, var) + while True: + if (dVar*math.copysign(dVar, var) < 0.0): + break + trim = trim - math.copysign(dVar, var) + # Get center of gravity + disp = self.computeDisplacement(trim) + G = [disp[1], disp[2], disp[3]] + disp = disp[0] + # Get bouyancy center + draft = self.computeDraft(disp, trim) + xcb = draft[1] + draft = draft[0] + KBT = Hydrostatics.KBT(self.ship, draft, trim) + B = [xcb, KBT[0], KBT[1]] + # Get stability initial condition + BG = [G[0]-B[0], G[1]-B[1], G[2]-B[2]] + x = BG[0]*math.cos(math.radians(trim)) - BG[2]*math.sin(math.radians(trim)) + y = BG[1] + z = BG[0]*math.sin(math.radians(trim)) + BG[2]*math.cos(math.radians(trim)) + var = math.degrees(math.atan2(x,z)) + self.form.trim.setValue(trim) def getTanks(self): """ Get the selected tanks objects list. @@ -186,14 +245,15 @@ class TaskPanel: for item in items: tag = str(item.text()) name = self.tanks[tag] - t = App.ActiveDocument.getObject('Tank') + t = App.ActiveDocument.getObject(name) if not t: continue tanks.append(t) return tanks - def computeDisplacement(self): + def computeDisplacement(self, trim=0.0): """ Computes ship displacement. + @param trim Trim angle [degrees]. @return Ship displacement and center of gravity. None if errors detected. """ if not self.ship: @@ -209,33 +269,39 @@ class TaskPanel: # Get selected tanks weights tanks = self.getTanks() for t in tanks: - w = tankWeight(t) + w = tankWeight(t, App.Base.Vector(0.0,-trim,0.0)) + # Unrotate center of gravity + x = w[1]*math.cos(math.radians(-trim)) - w[3]*math.sin(math.radians(-trim)) + y = w[2] + z = w[1]*math.sin(math.radians(-trim)) + w[3]*math.cos(math.radians(-trim)) W[0] = W[0] + w[0] - W[1] = W[1] + w[0]*w[1] - W[2] = W[2] + w[0]*w[2] - W[3] = W[3] + w[0]*w[3] + W[1] = W[1] + w[0]*x + W[2] = W[2] + w[0]*y + W[3] = W[3] + w[0]*z return [W[0], W[1]/W[0], W[2]/W[0], W[3]/W[0]] - def computeDraft(self, disp): + def computeDraft(self, disp, trim=0.0): """ Computes ship draft. @param disp Ship displacement. - @return Ship draft. None if errors detected. - @note 0 trim will be assumed. + @param trim Trim angle [degrees]. + @return Ship draft, and longitudinal bouyance center position. None if errors detected. """ if not self.ship: return None # Initial condition - trim = 0.0 dens = 1025 bbox = self.ship.Shape.BoundBox draft = bbox.ZMin dx = bbox.XMax - bbox.XMin dy = bbox.YMax - bbox.YMin w = 0.0 + xcb = 0.0 while(abs(disp - w)/disp > 0.01): draft = draft + (disp - w) / (dens*dx*dy) - w = 1000.0*Hydrostatics.Displacement(self.ship, draft, trim)[1] - return draft + ww = Hydrostatics.Displacement(self.ship, draft, trim) + w = 1000.0*ww[1] + xcb = ww[2] + return [draft,xcb] def createTask(): panel = TaskPanel() diff --git a/src/Mod/Ship/tankGZ/TaskPanel.ui b/src/Mod/Ship/tankGZ/TaskPanel.ui index 41823bf714..3742ecb820 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.ui +++ b/src/Mod/Ship/tankGZ/TaskPanel.ui @@ -7,13 +7,13 @@ 0 0 256 - 368 + 408 256 - 368 + 408 @@ -25,7 +25,7 @@ 0 - 0 + 6 @@ -43,7 +43,7 @@ 0 20 231 - 151 + 231 @@ -71,6 +71,55 @@ + + + + + + + 3 + 0 + + + + Trim [deg] + + + + + + + + 3 + 0 + + + + -45.000000000000000 + + + 45.000000000000000 + + + 0.100000000000000 + + + + + + + + 1 + 0 + + + + Auto + + + + + @@ -78,9 +127,9 @@ - + 0 - 0 + 3 @@ -92,7 +141,7 @@ 0 20 231 - 141 + 101 @@ -121,13 +170,28 @@ - + + + 0.000000000000000 + + + 90.000000000000000 + + - + + + 90.000000000000000 + + - + + + 10000 + + From e16ea9d29c186cf60e51d19250a67de233b57ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Sun, 27 May 2012 14:31:10 +0200 Subject: [PATCH 286/351] Added roll angles options controller at GZ curves tool --- src/Mod/Ship/tankGZ/TaskPanel.py | 20 +++++++++++++++++++- src/Mod/Ship/tankGZ/TaskPanel.ui | 9 +++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Mod/Ship/tankGZ/TaskPanel.py b/src/Mod/Ship/tankGZ/TaskPanel.py index 48a23242bb..a577ee53c1 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.py +++ b/src/Mod/Ship/tankGZ/TaskPanel.py @@ -78,6 +78,9 @@ class TaskPanel: form.draft = form.findChild(QtGui.QLabel, "DraftLabel") form.trim = form.findChild(QtGui.QDoubleSpinBox, "Trim") form.autoTrim = form.findChild(QtGui.QPushButton, "TrimAutoCompute") + form.roll0 = form.findChild(QtGui.QDoubleSpinBox, "StartAngle") + form.roll1 = form.findChild(QtGui.QDoubleSpinBox, "EndAngle") + form.nRoll = form.findChild(QtGui.QSpinBox, "NAngle") self.form = form # Initial values if self.initValues(): @@ -88,6 +91,9 @@ class TaskPanel: QtCore.QObject.connect(form.tanks,QtCore.SIGNAL("itemSelectionChanged()"),self.onTanksSelection) QtCore.QObject.connect(form.trim,QtCore.SIGNAL("valueChanged(double)"),self.onTrim) QtCore.QObject.connect(form.autoTrim,QtCore.SIGNAL("pressed()"),self.onAutoTrim) + QtCore.QObject.connect(form.roll0,QtCore.SIGNAL("valueChanged(double)"),self.onRoll) + QtCore.QObject.connect(form.roll1,QtCore.SIGNAL("valueChanged(double)"),self.onRoll) + QtCore.QObject.connect(form.nRoll,QtCore.SIGNAL("valueChanged(int)"),self.onRoll) return False def getMainWindow(self): @@ -236,6 +242,15 @@ class TaskPanel: var = math.degrees(math.atan2(x,z)) self.form.trim.setValue(trim) + def onRoll(self, value): + """ Called when roll angles options are modified. + @param value Dummy changed value. + """ + roll0 = self.form.roll0.value() + self.form.roll1.setMinimum(roll0) + roll1 = self.form.roll1.value() + self.form.roll0.setMaximum(roll1) + def getTanks(self): """ Get the selected tanks objects list. @return Selected tanks list. @@ -254,7 +269,10 @@ class TaskPanel: def computeDisplacement(self, trim=0.0): """ Computes ship displacement. @param trim Trim angle [degrees]. - @return Ship displacement and center of gravity. None if errors detected. + @return Ship displacement and center of gravity. None if errors + detected. + @note Returned center of gravity is refered to ship attached + axis coordinates. """ if not self.ship: return None diff --git a/src/Mod/Ship/tankGZ/TaskPanel.ui b/src/Mod/Ship/tankGZ/TaskPanel.ui index 3742ecb820..c1cad3e014 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.ui +++ b/src/Mod/Ship/tankGZ/TaskPanel.ui @@ -184,13 +184,22 @@ 90.000000000000000 + + 90.000000000000000 + + + 2 + 10000 + + 90 + From 506d638c8eafb2dfa8c50911e970395b46831ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Sun, 27 May 2012 15:41:57 +0200 Subject: [PATCH 287/351] Added GZ computation capabilities. --- src/Mod/Ship/tankGZ/TaskPanel.py | 47 ++++++++++++++++++++++++++++---- src/Mod/Ship/tankGZ/TaskPanel.ui | 6 ++-- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/Mod/Ship/tankGZ/TaskPanel.py b/src/Mod/Ship/tankGZ/TaskPanel.py index a577ee53c1..72a7ef057c 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.py +++ b/src/Mod/Ship/tankGZ/TaskPanel.py @@ -42,6 +42,20 @@ class TaskPanel: def accept(self): if not self.ship: return False + # Get general data + disp = self.computeDisplacement() + draft = self.computeDraft(disp[0], self.form.trim.value()) + trim = self.form.trim.value() + # Get roll angles + roll0 = self.form.roll0.value() + roll1 = self.form.roll1.value() + nRoll = self.form.nRoll.value() + dRoll = (roll1 - roll0) / (nRoll - 1) + roll = [] + GZ = [] + for i in range(0, nRoll): + roll.append(i*dRoll) + GZ.append(self.computeGZ(draft[0], trim, roll[-1])) return True def reject(self): @@ -266,7 +280,7 @@ class TaskPanel: tanks.append(t) return tanks - def computeDisplacement(self, trim=0.0): + def computeDisplacement(self, trim=0.0, roll=0.0): """ Computes ship displacement. @param trim Trim angle [degrees]. @return Ship displacement and center of gravity. None if errors @@ -287,15 +301,18 @@ class TaskPanel: # Get selected tanks weights tanks = self.getTanks() for t in tanks: - w = tankWeight(t, App.Base.Vector(0.0,-trim,0.0)) + w = tankWeight(t, App.Base.Vector(roll,-trim,0.0)) # Unrotate center of gravity x = w[1]*math.cos(math.radians(-trim)) - w[3]*math.sin(math.radians(-trim)) y = w[2] z = w[1]*math.sin(math.radians(-trim)) + w[3]*math.cos(math.radians(-trim)) + w[1] = x + w[2] = y*math.cos(math.radians(-roll)) - z*math.sin(math.radians(-roll)) + w[3] = y*math.sin(math.radians(-roll)) + z*math.cos(math.radians(-roll)) W[0] = W[0] + w[0] - W[1] = W[1] + w[0]*x - W[2] = W[2] + w[0]*y - W[3] = W[3] + w[0]*z + W[1] = W[1] + w[0]*w[1] + W[2] = W[2] + w[0]*w[2] + W[3] = W[3] + w[0]*w[3] return [W[0], W[1]/W[0], W[2]/W[0], W[3]/W[0]] def computeDraft(self, disp, trim=0.0): @@ -321,6 +338,26 @@ class TaskPanel: xcb = ww[2] return [draft,xcb] + def computeGZ(self, draft, trim, roll): + """ Compute GZ value. + @param draft Ship draft. + @param trim Ship trim angle [degrees]. + @param roll Ship roll angle [degrees]. + @return GZ value [m]. + """ + # Get center of gravity (x coordinate not relevant) + disp = self.computeDisplacement(trim, roll) + G = [disp[2], disp[3]] + disp = disp[0] + # Get bouyancy center (x coordinate not relevant) + KBT = Hydrostatics.KBT(self.ship, draft, trim, roll) + B = [KBT[0], KBT[1]] + # GZ computation + BG = [G[0] - B[0], G[1] - B[1]] + y = BG[0]*math.cos(math.radians(-roll)) - BG[1]*math.sin(math.radians(-roll)) + z = BG[0]*math.sin(math.radians(-roll)) + BG[1]*math.cos(math.radians(-roll)) + return -y + def createTask(): panel = TaskPanel() Gui.Control.showDialog(panel) diff --git a/src/Mod/Ship/tankGZ/TaskPanel.ui b/src/Mod/Ship/tankGZ/TaskPanel.ui index c1cad3e014..ce59e5d2b5 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.ui +++ b/src/Mod/Ship/tankGZ/TaskPanel.ui @@ -182,10 +182,10 @@ - 90.000000000000000 + 89.000000000000000 - 90.000000000000000 + 45.000000000000000 @@ -198,7 +198,7 @@ 10000 - 90 + 46 From 3b381f84053294cd6c15b713488d5e18b3aeecf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Cerc=C3=B3s=20pita?= Date: Sun, 27 May 2012 16:39:30 +0200 Subject: [PATCH 288/351] GZ curve plotting --- src/Mod/Ship/CMakeLists.txt | 1 + src/Mod/Ship/Makefile.am | 1 + src/Mod/Ship/tankGZ/Plot.py | 186 +++++++++++++++++++++++++++++++ src/Mod/Ship/tankGZ/TaskPanel.py | 2 + 4 files changed, 190 insertions(+) create mode 100644 src/Mod/Ship/tankGZ/Plot.py diff --git a/src/Mod/Ship/CMakeLists.txt b/src/Mod/Ship/CMakeLists.txt index 3106dbc47b..7944e4c38e 100644 --- a/src/Mod/Ship/CMakeLists.txt +++ b/src/Mod/Ship/CMakeLists.txt @@ -116,6 +116,7 @@ SOURCE_GROUP("shipcreatetank" FILES ${ShipCreateTank_SRCS}) SET(ShipGZ_SRCS tankGZ/__init__.py + tankGZ/Plot.py tankGZ/TaskPanel.py tankGZ/TaskPanel.ui ) diff --git a/src/Mod/Ship/Makefile.am b/src/Mod/Ship/Makefile.am index 54b7ecf6a5..a6d38f5002 100644 --- a/src/Mod/Ship/Makefile.am +++ b/src/Mod/Ship/Makefile.am @@ -77,6 +77,7 @@ nobase_data_DATA = \ tankCreateTank/TaskPanel.py \ tankCreateTank/TaskPanel.ui \ tankGZ/__init__.py \ + tankGZ/Plot.py \ tankGZ/TaskPanel.py \ tankGZ/TaskPanel.ui diff --git a/src/Mod/Ship/tankGZ/Plot.py b/src/Mod/Ship/tankGZ/Plot.py new file mode 100644 index 0000000000..1ce11d344a --- /dev/null +++ b/src/Mod/Ship/tankGZ/Plot.py @@ -0,0 +1,186 @@ +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* 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 * +#* * +#*************************************************************************** + +import os +# FreeCAD modules +import FreeCAD,FreeCADGui +from FreeCAD import Part, Base +from FreeCAD import Image, ImageGui +# FreeCADShip modules +from shipUtils import Paths, Translator + +header = """ ################################################################# + + ##### #### ### #### ##### # # ### #### + # # # # # # # # # # # # + # ## #### #### # # # # # # # # # # # + #### # # # # # # # ##### # # ## ## ##### # #### + # # #### #### # # # # # # # # # # + # # # # # # # # # # # # # # + # # #### #### ### # # #### ##### # # ### # + + ################################################################# +""" + +class Plot(object): + def __init__(self, x, y, disp, draft, trim): + """ Constructor. performs plot and show it (Using pyxplot). + @param x Roll angles [deg]. + @param y GZ value [m]. + @param disp Ship displacement [tons]. + @param draft Ship draft [m]. + @param trim Ship trim angle [deg]. + """ + if self.createDirectory(): + return + if self.saveData(x,y): + return + if self.saveLayout(x,y, disp, draft, trim): + return + if self.execute(): + return + ImageGui.open(self.path + 'gz.png') + + def createDirectory(self): + """ Create needed folder to write data and scripts. + @return True if error happens. + """ + self.path = FreeCAD.ConfigGet("UserAppData") + "ShipOutput/" + if not os.path.exists(self.path): + os.makedirs(self.path) + if not os.path.exists(self.path): + msg = Translator.translate("Can't create '" + self.path + "' folder.\n") + FreeCAD.Console.PrintError(msg) + return False + + def saveData(self,x,y): + """ Write data file. + @param x Roll angles. + @param y GZ value. + @return True if error happens. + """ + # Open the file + filename = self.path + 'gz.dat' + try: + Output = open(filename, "w") + except IOError: + msg = Translator.translate("Can't write '" + filename + "' file.\n") + FreeCAD.Console.PrintError(msg) + return True + # Print header + Output.write(header) + Output.write(" #\n") + Output.write(" # File automatically exported by FreeCAD-Ship\n") + Output.write(" # This file contains transversal GZ stability parameter, filled with following columns:\n") + Output.write(" # 1: Roll angles [deg]\n") + Output.write(" # 2: GZ [m]\n") + Output.write(" #\n") + Output.write(" #################################################################\n") + # Print data + if len(x) < 2: + msg = Translator.translate("Not enough data to plot.\n") + FreeCAD.Console.PrintError(msg) + return True + for i in range(0, len(x)): + string = "%f %f\n" % (x[i], y[i]) + Output.write(string) + # Close file + Output.close() + self.dataFile = filename + msg = Translator.translate("Data saved at '" + self.dataFile + "'.\n") + FreeCAD.Console.PrintMessage(msg) + return False + + def saveLayout(self, x, y, disp, draft, trim): + """ Prints the data output. + @param x Roll angles. + @param y GZ value. + @param disp Ship displacement. + @param draft Ship draft. + @param trim Ship trim angle. + @return True if error happens. + """ + filename = self.path + 'gz.pyxplot' + # Open the file + try: + Output = open(filename, "w") + except IOError: + msg = Translator.translate("Can't write '" + filename + "' file.\n") + FreeCAD.Console.PrintError(msg) + return True + # Write header + Output.write(header) + Output.write(" #\n") + Output.write(" # File automatically exported by FreeCAD-Ship\n") + Output.write(" # This file contains a script to plot transversal GZ stability parameter.\n") + Output.write(" # To use it execute:\n") + Output.write(" #\n") + Output.write(" # pyxplot %s\n" % (filename)) + Output.write(" #\n") + Output.write(" #################################################################\n") + # Write general options for hydrostatics + Output.write("set numeric display latex\n") + Output.write("set output '%s'\n" % (self.path + 'gz.eps')) + Output.write("set nokey\n") + Output.write("set grid\n") + Output.write("# X axis\n") + Output.write("set xlabel '$roll$ / degrees'\n") + Output.write("set xtic\n") + Output.write("# Y axis\n") + Output.write("set ylabel '$GZ$ / m'\n") + Output.write("set ytic\n") + Output.write("# Line styles\n") + Output.write("set style 1 line linetype 1 linewidth 2 colour rgb (0):(0):(0)\n") + # Additional data + Output.write("# Additional data\n") + Output.write("set label (1) '$\\Delta = %g \\mathrm{tons}$' %f,%f\n" % (disp, x[0] + 0.65*(x[-1] - x[0]), min(y) + 0.95*(max(y)-min(y)))) + Output.write("set label (2) '$T = %g \\mathrm{m}$' %f,%f\n" % (draft, x[0] + 0.65*(x[-1] - x[0]), min(y) + 0.85*(max(y)-min(y)))) + Output.write("set label (3) '$Trim = %g^\\circ$' %f,%f\n" % (trim, x[0] + 0.65*(x[-1] - x[0]), min(y) + 0.75*(max(y)-min(y)))) + # Write plot call + Output.write("# Plot\n") + Output.write("plot '%s' using 1:2 title 'GZ' axes x1y1 with lines style 1\n" % (self.dataFile)) + # Close file + self.layoutFile = filename + Output.close() + return False + + def execute(self): + """ Calls pyxplot in order to plot an save an image. + @return True if error happens. + """ + filename = self.path + 'gz' + comm = "pyxplot %s" % (self.layoutFile) + if os.system(comm): + msg = Translator.translate("Can't execute pyxplot. Maybe is not installed?\n") + FreeCAD.Console.PrintError(msg) + msg = Translator.translate("Plot will not generated\n") + FreeCAD.Console.PrintError(msg) + return True + comm = "gs -r300 -dEPSCrop -dTextAlphaBits=4 -sDEVICE=png16m -sOutputFile=%s.png -dBATCH -dNOPAUSE %s.eps" % (filename,filename) + if os.system(comm): + msg = Translator.translate("Can't execute ghostscript. Maybe is not installed?\n") + FreeCAD.Console.PrintError(msg) + msg = Translator.translate("Generated image will not converted to png\n") + FreeCAD.Console.PrintError(msg) + return True + return False diff --git a/src/Mod/Ship/tankGZ/TaskPanel.py b/src/Mod/Ship/tankGZ/TaskPanel.py index 72a7ef057c..5fefccafb9 100644 --- a/src/Mod/Ship/tankGZ/TaskPanel.py +++ b/src/Mod/Ship/tankGZ/TaskPanel.py @@ -28,6 +28,7 @@ import FreeCADGui as Gui # Qt library from PyQt4 import QtGui,QtCore # Module +from Plot import * from Instance import * from TankInstance import * from shipUtils import Paths, Translator @@ -56,6 +57,7 @@ class TaskPanel: for i in range(0, nRoll): roll.append(i*dRoll) GZ.append(self.computeGZ(draft[0], trim, roll[-1])) + Plot(roll, GZ, disp[0]/1000.0, draft[0], trim) return True def reject(self): From ef24e4d2e6e5bae765a869008320030c6cdaa319 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 31 May 2012 11:50:25 +0200 Subject: [PATCH 289/351] Implement CDATA reader, fix bugs in Writer::insertBinFile --- src/App/PropertyFile.cpp | 52 +++++++++++++++++++++++++++------------- src/Base/Reader.cpp | 43 +++++++++++++++++++++++++++++---- src/Base/Reader.h | 15 ++++++++++-- src/Base/Writer.cpp | 24 +++++++------------ 4 files changed, 96 insertions(+), 38 deletions(-) diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 13599c88a6..52278ea991 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -257,13 +257,18 @@ void PropertyFileIncluded::setPyObject(PyObject *value) void PropertyFileIncluded::Save (Base::Writer &writer) const { if (writer.isForceXML()) { - writer.Stream() << writer.ind() << "" << endl; - - // write the file in the XML stream - if (!_cValue.empty()) + if (!_cValue.empty()) { + Base::FileInfo file(_cValue.c_str()); + writer.Stream() << writer.ind() << "" << std::endl; + // write the file in the XML stream + writer.incInd(); writer.insertBinFile(_cValue.c_str()); - - writer.Stream() << writer.ind() <<"" << endl ; + writer.decInd(); + writer.Stream() << writer.ind() <<"" << endl; + } + else + writer.Stream() << writer.ind() << "" << std::endl; } else { // instead initiate an extra file @@ -280,17 +285,30 @@ void PropertyFileIncluded::Save (Base::Writer &writer) const void PropertyFileIncluded::Restore(Base::XMLReader &reader) { reader.readElement("FileIncluded"); - string file (reader.getAttribute("file") ); - - if (!file.empty()) { - // initate a file read - reader.addFile(file.c_str(),this); - - // is in the document transient path - aboutToSetValue(); - _cValue = getDocTransientPath() + "/" + file; - _BaseFileName = file; - hasSetValue(); + if (reader.hasAttribute("file")) { + string file (reader.getAttribute("file") ); + if (!file.empty()) { + // initate a file read + reader.addFile(file.c_str(),this); + // is in the document transient path + aboutToSetValue(); + _cValue = getDocTransientPath() + "/" + file; + _BaseFileName = file; + hasSetValue(); + } + } + // section is XML stream + else if (reader.hasAttribute("data")) { + string file (reader.getAttribute("data") ); + if (!file.empty()) { + // is in the document transient path + aboutToSetValue(); + _cValue = getDocTransientPath() + "/" + file; + reader.readBinFile(_cValue.c_str()); + reader.readEndElement("FileIncluded"); + _BaseFileName = file; + hasSetValue(); + } } } diff --git a/src/Base/Reader.cpp b/src/Base/Reader.cpp index db355f723f..6791b99f62 100644 --- a/src/Base/Reader.cpp +++ b/src/Base/Reader.cpp @@ -34,6 +34,7 @@ /// Here the FreeCAD includes sorted by Base,App,Gui...... #include "Reader.h" +#include "Base64.h" #include "Exception.h" #include "Persistence.h" #include "InputSource.h" @@ -79,6 +80,7 @@ Base::XMLReader::XMLReader(const char* FileName, std::istream& str) //parser->setFeature(XMLUni::fgXercesDynamic, true); parser->setContentHandler(this); + parser->setLexicalHandler(this); parser->setErrorHandler(this); try { @@ -127,7 +129,7 @@ long Base::XMLReader::getAttributeAsInteger(const char* AttrName) const if (pos != AttrMap.end()) return atol(pos->second.c_str()); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return 0; @@ -140,7 +142,7 @@ unsigned long Base::XMLReader::getAttributeAsUnsigned(const char* AttrName) cons if (pos != AttrMap.end()) return strtoul(pos->second.c_str(),0,10); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return 0; @@ -153,7 +155,7 @@ double Base::XMLReader::getAttributeAsFloat (const char* AttrName) const if (pos != AttrMap.end()) return atof(pos->second.c_str()); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return 0.0; @@ -166,7 +168,7 @@ const char* Base::XMLReader::getAttribute (const char* AttrName) const if (pos != AttrMap.end()) return pos->second.c_str(); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return ""; @@ -255,6 +257,22 @@ void Base::XMLReader::readCharacters(void) { } +void Base::XMLReader::readBinFile(const char* filename) +{ + Base::FileInfo fi(filename); + Base::ofstream to(fi, std::ios::out | std::ios::binary); + if (!to) + throw Base::Exception("XMLReader::readBinFile() Could not open file!"); + + bool ok; + do { + ok = read(); if (!ok) break; + } while (ReadType != EndCDATA); + + to << Base::base64_decode(Characters); + to.close(); +} + void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const { // It's possible that not all objects inside the document could be created, e.g. if a module @@ -370,15 +388,32 @@ void Base::XMLReader::endElement (const XMLCh* const /*uri*/, const XMLCh *cons ReadType = EndElement; } +void Base::XMLReader::startCDATA () +{ + ReadType = StartCDATA; +} +void Base::XMLReader::endCDATA () +{ + ReadType = EndCDATA; +} + +#if (XERCES_VERSION_MAJOR == 2) void Base::XMLReader::characters(const XMLCh* const chars, const unsigned int length) +#else +void Base::XMLReader::characters(const XMLCh* const chars, const XMLSize_t length) +#endif { Characters = StrX(chars).c_str(); ReadType = Chars; CharacterCount += length; } +#if (XERCES_VERSION_MAJOR == 2) void Base::XMLReader::ignorableWhitespace( const XMLCh* const /*chars*/, const unsigned int /*length*/) +#else +void Base::XMLReader::ignorableWhitespace( const XMLCh* const /*chars*/, const XMLSize_t /*length*/) +#endif { //fSpaceCount += length; } diff --git a/src/Base/Reader.h b/src/Base/Reader.h index 3ced7241b5..7e55575d42 100644 --- a/src/Base/Reader.h +++ b/src/Base/Reader.h @@ -131,6 +131,8 @@ public: void readEndElement(const char* ElementName=0); /// read until characters are found void readCharacters(void); + /// read binary file + void readBinFile(const char*); //@} /** @name Attribute handling */ @@ -171,8 +173,15 @@ protected: // ----------------------------------------------------------------------- virtual void startElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const XERCES_CPP_NAMESPACE_QUALIFIER Attributes& attrs); virtual void endElement (const XMLCh* const uri, const XMLCh *const localname, const XMLCh *const qname); - virtual void characters (const XMLCh* const chars, const unsigned int length); + virtual void startCDATA (); + virtual void endCDATA (); +#if (XERCES_VERSION_MAJOR == 2) + virtual void characters (const XMLCh* const chars, const unsigned int length); virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length); +#else + virtual void characters (const XMLCh* const chars, const XMLSize_t length); + virtual void ignorableWhitespace(const XMLCh* const chars, const XMLSize_t length); +#endif virtual void resetDocument(); @@ -198,7 +207,9 @@ protected: Chars, StartElement, StartEndElement, - EndElement + EndElement, + StartCDATA, + EndCDATA } ReadType; diff --git a/src/Base/Writer.cpp b/src/Base/Writer.cpp index 01eecef6b5..621893a8a3 100644 --- a/src/Base/Writer.cpp +++ b/src/Base/Writer.cpp @@ -65,32 +65,26 @@ void Writer::insertAsciiFile(const char* FileName) if (!from) throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); - Stream() << "" << endl; + Stream() << "]]>" << endl; } void Writer::insertBinFile(const char* FileName) { Base::FileInfo fi(FileName); - Base::ifstream from(fi, std::ios::in | std::ios::binary); + Base::ifstream from(fi, std::ios::in | std::ios::binary | std::ios::ate); if (!from) throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); - Stream() << " bytes(fileSize); + from.read((char*)&bytes[0], fileSize); + Stream() << Base::base64_encode(&bytes[0], fileSize); Stream() << "]]>" << endl; } From 4f91a5a71b42c9de264339434540f9efda55b86b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 28 May 2012 16:02:26 -0300 Subject: [PATCH 290/351] Added FreeCADGui.doCommand() python command --- src/Gui/Application.h | 2 ++ src/Gui/ApplicationPy.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/Gui/Application.h b/src/Gui/Application.h index 74b3dbb64b..44a73d0c67 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -231,6 +231,8 @@ public: PYFUNCDEF_S(sActiveDocument); PYFUNCDEF_S(sGetDocument); + PYFUNCDEF_S(sDoCommand); + static PyMethodDef Methods[]; private: diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index 9ca9ee3afe..9a2a51af4e 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -128,6 +128,9 @@ PyMethodDef Application::Methods[] = { {"getDocument", (PyCFunction) Application::sGetDocument, 1, "getDocument(string) -> object\n\n" "Get a document by its name"}, + {"doCommand", (PyCFunction) Application::sDoCommand, 1, + "doCommand(string) -> None\n\n" + "Prints the given string in the python console and runs it"}, {NULL, NULL} /* Sentinel */ }; @@ -765,3 +768,12 @@ PyObject* Application::sRunCommand(PyObject * /*self*/, PyObject *args,PyObject return 0; } } + +PyObject* Application::sDoCommand(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) +{ + char *pstr=0; + if (!PyArg_ParseTuple(args, "s", &pstr)) // convert args: Python->C + return NULL; // NULL triggers exception + Command::doCommand(Command::Doc,pstr); + return Py_None; +} From d9aa2712bb87d900e7b1c7b5109805ea39b6e35c Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 28 May 2012 16:02:56 -0300 Subject: [PATCH 291/351] Testing python Gui.doCommand with the Draft Line tool --- src/Mod/Draft/DraftGui.py | 6 +++++- src/Mod/Draft/DraftTools.py | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 13517f4785..7e651a6986 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -78,7 +78,11 @@ class todo: try: name = str(name) FreeCAD.ActiveDocument.openTransaction(name) - func() + if isinstance(func,list): + for l in func: + FreeCADGui.doCommand(l) + else: + func() FreeCAD.ActiveDocument.commitTransaction() except: wrn = "[Draft.todo.commit] Unexpected error:", sys.exc_info()[0], "in ", f, "(", arg, ")" diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 885e781c64..81d1bc05d1 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -415,13 +415,26 @@ class Line(Creator): def finish(self,closed=False,cont=False): "terminates the operation and closes the poly if asked" if self.obj: + # remove temporary object, if any old = self.obj.Name todo.delay(self.doc.removeObject,old) self.obj = None if (len(self.node) > 1): + # building command string + if self.support: + sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' + else: + sup = 'None' + points='[' + for n in self.node: + if len(points) > 1: + points += ',' + points += 'FreeCAD.Vector('+str(n.x) + ',' + str(n.y) + ',' + str(n.z) + ')' + points += ']' self.commit(translate("draft","Create DWire"), - partial(Draft.makeWire,self.node,closed, - face=self.ui.fillmode,support=self.support)) + ['import Draft', + 'points='+points, + 'Draft.makeWire(points,closed='+str(closed)+',face='+str(bool(self.ui.fillmode))+',support='+sup+')']) if self.ui: self.linetrack.finalize() self.constraintrack.finalize() From 77e618cb92757ae48ef0863fc680291dd7644578 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 29 May 2012 22:17:12 -0300 Subject: [PATCH 292/351] Used Gui.doCommand() in all Draft commands --- src/Mod/Draft/DraftTools.py | 186 +++++++++++++++++++++++---------- src/Mod/Draft/DraftVecUtils.py | 4 + 2 files changed, 136 insertions(+), 54 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 81d1bc05d1..93fb74fcc5 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -380,8 +380,38 @@ class Creator: todo.delayCommit(self.commitList) self.commitList = [] + def getStrings(self): + "returns a couple of useful strings fro building python commands" + + # current plane rotation + p = plane.getRotation() + qr = p.Rotation.Q + qr = '('+str(qr[0])+','+str(qr[1])+','+str(qr[2])+','+str(qr[3])+')' + + # support object + if self.support: + sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' + else: + sup = 'None' + + # contents of self.node + points='[' + for n in self.node: + if len(points) > 1: + points += ',' + points += DraftVecUtils.toString(n) + points += ']' + + # fill mode + if self.ui: + fil = str(bool(self.ui.fillmode)) + else: + fil = "True" + + return qr,sup,points,fil + def commit(self,name,func): - "stores partial actions to be committed to the FreeCAD document" + "stores actions to be committed to the FreeCAD document" self.commitList.append((name,func)) class Line(Creator): @@ -421,20 +451,11 @@ class Line(Creator): self.obj = None if (len(self.node) > 1): # building command string - if self.support: - sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' - else: - sup = 'None' - points='[' - for n in self.node: - if len(points) > 1: - points += ',' - points += 'FreeCAD.Vector('+str(n.x) + ',' + str(n.y) + ',' + str(n.z) + ')' - points += ']' + rot,sup,pts,fil = self.getStrings() self.commit(translate("draft","Create DWire"), ['import Draft', - 'points='+points, - 'Draft.makeWire(points,closed='+str(closed)+',face='+str(bool(self.ui.fillmode))+',support='+sup+')']) + 'points='+pts, + 'Draft.makeWire(points,closed='+str(closed)+',face='+fil+',support='+sup+')']) if self.ui: self.linetrack.finalize() self.constraintrack.finalize() @@ -628,9 +649,12 @@ class BSpline(Line): old = self.obj.Name self.doc.removeObject(old) try: + # building command string + rot,sup,pts,fil = self.getStrings() self.commit(translate("draft","Create BSpline"), - partial(Draft.makeBSpline,self.node,closed, - face=self.ui.fillmode,support=self.support)) + ['import Draft', + 'points='+pts, + 'Draft.makeBSpline(points,closed='+str(closed)+',face='+fil+',support='+sup+')']) except: print "Draft: error delaying commit" if self.ui: @@ -741,12 +765,15 @@ class Rectangle(Creator): if abs(DraftVecUtils.angle(p4.sub(p1),plane.u,plane.axis)) > 1: length = -length height = p2.sub(p1).Length if abs(DraftVecUtils.angle(p2.sub(p1),plane.v,plane.axis)) > 1: height = -height - p = plane.getRotation() - p.move(p1) try: + # building command string + rot,sup,pts,fil = self.getStrings() self.commit(translate("draft","Create Rectangle"), - partial(Draft.makeRectangle,length,height, - p,self.ui.fillmode,support=self.support)) + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(p1), + 'Draft.makeRectangle(length='+str(length)+',height='+str(height)+',placement=pl,face='+fil+',support='+sup+')']) except: print "Draft: error delaying commit" self.finish(cont=True) @@ -1013,23 +1040,30 @@ class Arc(Creator): def drawArc(self): "actually draws the FreeCAD object" - p = plane.getRotation() - p.move(self.center) + rot,sup,pts,fil = self.getStrings() if self.closedCircle: try: - self.commit(translate("draft","Create Circle"), - partial(Draft.makeCircle,self.rad,p, - self.ui.fillmode,support=self.support)) + # building command string + self.commit(translate("draft","Create Circle"), + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(self.center), + 'Draft.makeCircle(radius='+str(self.rad)+',placement=pl,face='+fil+',support='+sup+')']) except: - print "Draft: error delaying commit" + print "Draft: error delaying commit" else: sta = math.degrees(self.firstangle) end = math.degrees(self.firstangle+self.angle) if end < sta: sta,end = end,sta try: - self.commit(translate("draft","Create Arc"), - partial(Draft.makeCircle,self.rad,p,self.ui.fillmode, - sta,end,support=self.support)) + # building command string + self.commit(translate("draft","Create Arc"), + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(self.center), + 'Draft.makeCircle(radius='+str(self.rad)+',placement=pl,face='+fil+',startangle='+str(sta)+',endangle='+str(end)+',support='+sup+')']) except: print "Draft: error delaying commit" self.finish(cont=True) @@ -1257,11 +1291,14 @@ class Polygon(Creator): def drawPolygon(self): "actually draws the FreeCAD object" - p = plane.getRotation() - p.move(self.center) + rot,sup,pts,fil = self.getStrings() + # building command string self.commit(translate("draft","Create Polygon"), - partial(Draft.makePolygon,self.ui.numFaces.value(),self.rad, - True,p,face=self.ui.fillmode,support=self.support)) + ['import Draft', + 'pl=FreeCAD.Placement()', + 'pl.Rotation.Q='+rot, + 'pl.Base='+DraftVecUtils.toString(self.center), + 'Draft.makePolygon('+str(self.ui.numFaces.value())+',radius='+str(self.rad)+',inscribed=True,placement=pl,face='+fil+',support='+sup+')']) self.finish(cont=True) def numericInput(self,numx,numy,numz): @@ -1326,8 +1363,16 @@ class Text(Creator): def createObject(self): "creates an object in the current doc" - self.commit(translate("draft","Create Text"), - partial(Draft.makeText,self.text,self.node[0])) + tx = '' + for l in self.text: + if tx: + tx += ',' + tx += '"'+l+'"' +# self.commit(translate("draft","Create Text"), +# ['import Draft', +# 'Draft.makeText(['+tx+'],'+DraftVecUtils.toString(self.node[0])+')']) + self.commit(translate("draft","Create Text"),partial(Draft.makeText,self.text,self.node[0])) + self.finish(cont=True) def action(self,arg): @@ -1429,9 +1474,9 @@ class Dimension(Creator): pt = o.ViewObject.RootNode.getChildren()[1].getChildren()[0].getChildren()[0].getChildren()[3] p3 = Vector(pt.point.getValues()[2].getValue()) self.commit(translate("draft","Create Dimension"), - partial(Draft.makeDimension,p1,p2,p3)) - self.commit(translate("draft","Delete Measurement"), - partial(FreeCAD.ActiveDocument.removeObject,o.Name)) + ['import Draft', + 'Draft.makeDimension('+DraftVecUtils.toString(p1)+','+DraftVecUtils.toString(p2)+','+DraftVecUtils.toString(p3)+')', + 'FreeCAD.ActiveDocument.removeObject("'+o.Name+'")']) def createObject(self): "creates an object in the current doc" @@ -1449,8 +1494,8 @@ class Dimension(Creator): self.arcmode,self.node[2])) else: self.commit(translate("draft","Create Dimension"), - partial(Draft.makeDimension,self.node[0],self.node[1], - self.node[2])) + ['import Draft', + 'Draft.makeDimension('+DraftVecUtils.toString(self.node[0])+','+DraftVecUtils.toString(self.node[1])+','+DraftVecUtils.toString(self.node[2])+')']) if self.ui.continueMode: self.cont = self.node[2] if not self.dir: @@ -1712,7 +1757,7 @@ class Modifier: self.commitList = [] def commit(self,name,func): - "stores partial actions to be committed to the FreeCAD document" + "stores actions to be committed to the FreeCAD document" # print "committing" self.commitList.append((name,func)) @@ -1768,10 +1813,20 @@ class Move(Modifier): def move(self,delta,copy=False): "moving the real shapes" + sel = '[' + for o in self.sel: + if len(sel) > 1: + sel += ',' + sel += 'FreeCAD.ActiveDocument.'+o.Name + sel += ']' if copy: - self.commit(translate("draft","Copy"),partial(Draft.move,self.sel,delta,copy)) + self.commit(translate("draft","Copy"), + ['import Draft', + 'Draft.move('+sel+','+DraftVecUtils.toString(delta)+',copy='+str(copy)+')']) else: - self.commit(translate("draft","Move"),partial(Draft.move,self.sel,delta,copy)) + self.commit(translate("draft","Move"), + ['import Draft', + 'Draft.move('+sel+','+DraftVecUtils.toString(delta)+',copy='+str(copy)+')']) self.doc.recompute() def action(self,arg): @@ -1926,14 +1981,20 @@ class Rotate(Modifier): def rot (self,angle,copy=False): "rotating the real shapes" + sel = '[' + for o in self.sel: + if len(sel) > 1: + sel += ',' + sel += 'FreeCAD.ActiveDocument.'+o.Name + sel += ']' if copy: self.commit(translate("draft","Copy"), - partial(Draft.rotate,self.sel, - math.degrees(angle),self.center,plane.axis,copy)) + ['import Draft', + 'Draft.rotate('+sel+','+str(math.degrees(angle))+','+DraftVecUtils.toString(self.center)+',axis='+DraftVecUtils.toString(plane.axis)+',copy='+str(copy)+')']) else: self.commit(translate("draft","Rotate"), - partial(Draft.rotate,self.sel, - math.degrees(angle),self.center,plane.axis,copy)) + ['import Draft', + 'Draft.rotate('+sel+','+str(math.degrees(angle))+','+DraftVecUtils.toString(self.center)+',axis='+DraftVecUtils.toString(plane.axis)+',copy='+str(copy)+')']) def action(self,arg): "scene event handler" @@ -2194,13 +2255,18 @@ class Offset(Modifier): occmode = self.ui.occOffset.isChecked() if hasMod(arg,MODALT) or self.ui.isCopy.isChecked(): copymode = True if self.npts: + print "offset:npts=",self.npts self.commit(translate("draft","Offset"), - partial(Draft.offset,self.sel, - self.npts,copymode,occ=False)) + ['import Draft', + 'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+DraftVecUtils.toString(self.ntps)+',copy='+str(copymode)+')']) elif self.dvec: + if isinstance(self.dvec,float): + d = str(self.dvec) + else: + d = DraftVecUtils.toString(self.dvec) self.commit(translate("draft","Offset"), - partial(Draft.offset,self.sel, - self.dvec,copymode,occ=occmode)) + ['import Draft', + 'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+d+',copy='+str(copymode)+',occ='+str(occmode)+')']) if hasMod(arg,MODALT): self.extendedCopy = True else: @@ -2222,9 +2288,13 @@ class Offset(Modifier): copymode = False occmode = self.ui.occOffset.isChecked() if self.ui.isCopy.isChecked(): copymode = True + if isinstance(self.dvec,float): + d = str(self.dvec) + else: + d = DraftVecUtils.toString(self.dvec) self.commit(translate("draft","Offset"), - partial(Draft.offset,self.sel, - self.dvec,copymode,occ=occmode)) + ['import Draft', + 'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+d+',copy='+str(copymode)+',occ='+str(occmode)+')']) self.finish() @@ -2946,12 +3016,20 @@ class Scale(Modifier): def scale(self,delta,copy=False): "moving the real shapes" + sel = '[' + for o in self.sel: + if len(sel) > 1: + sel += ',' + sel += 'FreeCAD.ActiveDocument.'+o.Name + sel += ']' if copy: self.commit(translate("draft","Copy"), - partial(Draft.scale,self.sel,delta,self.node[0],copy)) + ['import Draft', + 'Draft.scale('+sel+',delta='+DraftVecUtils.toString(delta)+',center='+DraftVecUtils.toString(self.node[0])+',copy='+str(copy)+')']) else: self.commit(translate("draft","Scale"), - partial(Draft.scale,self.sel,delta,self.node[0],copy)) + ['import Draft', + 'Draft.scale('+sel+',delta='+DraftVecUtils.toString(delta)+',center='+DraftVecUtils.toString(self.node[0])+',copy='+str(copy)+')']) def action(self,arg): "scene event handler" diff --git a/src/Mod/Draft/DraftVecUtils.py b/src/Mod/Draft/DraftVecUtils.py index 1f10a2c7ea..678965e85a 100644 --- a/src/Mod/Draft/DraftVecUtils.py +++ b/src/Mod/Draft/DraftVecUtils.py @@ -40,6 +40,10 @@ def typecheck (args_and_types, name="?"): FreeCAD.Console.PrintWarning("typecheck[" + str(name) + "]: " + str(v) + " is not " + str(t) + "\n") raise TypeError("fcvec." + str(name)) +def toString(u): + "returns a string containing a python command to recreate this vector" + return "FreeCAD.Vector("+str(u.x)+","+str(u.y)+","+str(u.z)+")" + def tup(u,array=False): "returns a tuple (x,y,z) with the vector coords, or an array if array=true" typecheck ([(u,Vector)], "tup"); From f82fb927bc1b44fb52a5bfef23984c8529fd4a40 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 30 May 2012 12:58:08 -0300 Subject: [PATCH 293/351] Draft: fixes in commands --- src/Mod/Draft/DraftTools.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 93fb74fcc5..9135588a76 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -1363,15 +1363,15 @@ class Text(Creator): def createObject(self): "creates an object in the current doc" - tx = '' + tx = '[' for l in self.text: - if tx: + if len(tx) > 1: tx += ',' - tx += '"'+l+'"' -# self.commit(translate("draft","Create Text"), -# ['import Draft', -# 'Draft.makeText(['+tx+'],'+DraftVecUtils.toString(self.node[0])+')']) - self.commit(translate("draft","Create Text"),partial(Draft.makeText,self.text,self.node[0])) + tx += '"'+str(l)+'"' + tx += ']' + self.commit(translate("draft","Create Text"), + ['import Draft', + 'Draft.makeText('+tx+',point='+DraftVecUtils.toString(self.node[0])+')']) self.finish(cont=True) @@ -1911,19 +1911,21 @@ class ApplyStyle(Modifier): if self.ui: self.sel = Draft.getSelection() if (len(self.sel)>0): + c = ['import Draft'] for ob in self.sel: if (ob.Type == "App::DocumentObjectGroup"): - self.formatGroup(ob) + c.extend(self.formatGroup(ob)) else: - self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) + c.append('Draft.formatObject(FreeCAD.ActiveDocument.'+ob.Name+')') + self.commit(translate("draft","Change Style"),c) def formatGroup(self,grpob): + c=[] for ob in grpob.Group: if (ob.Type == "App::DocumentObjectGroup"): - self.formatGroup(ob) + c.extend(self.formatGroup(ob)) else: - self.commit(translate("draft","Change Style"),partial(Draft.formatObject,ob)) - + c.append('Draft.formatObject(FreeCAD.ActiveDocument.'+ob.Name+')') class Rotate(Modifier): "The Draft_Rotate FreeCAD command definition" From 7defe80054a1f71c1a0630299e0461d6dfbafa1e Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 30 May 2012 19:40:23 -0300 Subject: [PATCH 294/351] Draft: finished the switch to Gui.doCommand() --- src/Mod/Draft/DraftTools.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 9135588a76..b37e07c00f 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -30,7 +30,6 @@ __url__ = "http://free-cad.sourceforge.net" #--------------------------------------------------------------------------- import os, FreeCAD, FreeCADGui, WorkingPlane, math, re, importSVG, Draft, Draft_rc, DraftVecUtils -from functools import partial from FreeCAD import Vector from DraftGui import todo,QtCore,QtGui from DraftSnap import * @@ -1482,16 +1481,16 @@ class Dimension(Creator): "creates an object in the current doc" if self.angledata: self.commit(translate("draft","Create Dimension"), - partial(Draft.makeAngularDimension,self.center, - self.angledata,self.node[-1])) + ['import Draft', + 'Draft.makeAngularDimension(center='+DraftVecUtils.toString(self.center)+',angles=['+str(self.angledata[0])+','+str(self.angledata[1])+'],p3='+DraftVecUtils.toString(self.node[-1])+')']) elif self.link and (not self.arcmode): self.commit(translate("draft","Create Dimension"), - partial(Draft.makeDimension,self.link[0],self.link[1], - self.link[2],self.node[2])) + ['import Draft', + 'Draft.makeDimension(FreeCAD.ActiveDocument.'+self.link[0].Name+','+str(self.link[1])+','+str(self.link[2])+','+DraftVecUtils.toString(self.node[2])+')']) elif self.arcmode: self.commit(translate("draft","Create Dimension"), - partial(Draft.makeDimension,self.link[0],self.link[1], - self.arcmode,self.node[2])) + ['import Draft', + 'Draft.makeDimension(FreeCAD.ActiveDocument.'+self.link[0].Name+','+str(self.link[1])+',"'+str(self.arcmode)+'",'+DraftVecUtils.toString(self.node[2])+')']) else: self.commit(translate("draft","Create Dimension"), ['import Draft', From 539cad092a533efd067081b19178bc4448b38a7a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 30 May 2012 21:34:51 -0300 Subject: [PATCH 295/351] Arch: Wall tool is now translatable + uses Gui.doCommand --- src/Mod/Arch/ArchWall.py | 48 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index c26125136d..4b9db7ee03 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -24,12 +24,13 @@ import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore +from DraftTools import translate __title__="FreeCAD Wall" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeWall(baseobj=None,width=None,height=None,align="Center",name="Wall"): +def makeWall(baseobj=None,width=None,height=None,align="Center",name=str(translate("Arch","Wall"))): '''makeWall(obj,[width],[height],[align],[name]): creates a wall based on the given object, which can be a sketch, a draft object, a face or a solid. align can be "Center","Left" or "Right"''' @@ -117,10 +118,12 @@ class _CommandWall: if sel: import Draft if Draft.getType(sel[0]) != "Wall": - FreeCAD.ActiveDocument.openTransaction("Wall") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Wall"))) + FreeCADGui.doCommand('import Arch') for obj in sel: - makeWall(obj) + FreeCADGui.doCommand('Arch.makeWall(FreeCAD.ActiveDocument.'+obj.Name+')') FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() done = True if not done: import DraftTrackers @@ -146,32 +149,33 @@ class _CommandWall: add = False l = Part.Line(self.points[0],self.points[1]) self.tracker.finalize() - FreeCAD.ActiveDocument.openTransaction("Wall") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Wall"))) + FreeCADGui.doCommand('import Arch') + FreeCADGui.doCommand('import Part') + FreeCADGui.doCommand('trace=Part.Line(FreeCAD.'+str(l.StartPoint)+',FreeCAD.'+str(l.EndPoint)+')') if not self.existing: self.addDefault(l) else: w = joinWalls(self.existing) if w: if areSameWallTypes([w,self]): - w.Base.addGeometry(l) + FreeCADGui.doCommand('FreeCAD.ActiveDocument.'+w.Name+'.Base.addGeometry(trace)') else: - nw = self.addDefault(l) + self.addDefault(l) add = True else: self.addDefault(l) + if add: + FreeCADGui.doCommand('Arch.addComponents(FreeCAD.ActiveDocument.'+FreeCAD.ActiveDocument.Objects[-1].Name+',FreeCAD.ActiveDocument.'+w.Name+')') FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() - if add: - import ArchCommands - ArchCommands.addComponents(nw,w) if self.continueCmd: self.Activated() def addDefault(self,l): - s = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","WallTrace") - s.addGeometry(l) - w = makeWall(s,width=self.Width,height=self.Height,align=self.Align) - return w + FreeCADGui.doCommand('base=FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject","'+str(translate('Arch','WallTrace'))+'")') + FreeCADGui.doCommand('base.addGeometry(trace)') + FreeCADGui.doCommand('Arch.makeWall(base,width='+str(self.Width)+',height='+str(self.Height)+',align="'+str(self.Align)+'")') def update(self,point): "this function is called by the Snapper when the mouse is moved" @@ -191,11 +195,11 @@ class _CommandWall: def taskbox(self): "sets up a taskbox widget" w = QtGui.QWidget() - w.setWindowTitle("Wall options") + w.setWindowTitle(str(translate("Arch","Wall options"))) lay0 = QtGui.QVBoxLayout(w) lay1 = QtGui.QHBoxLayout() lay0.addLayout(lay1) - label1 = QtGui.QLabel("Width") + label1 = QtGui.QLabel(str(translate("Arch","Width"))) lay1.addWidget(label1) value1 = QtGui.QDoubleSpinBox() value1.setDecimals(2) @@ -203,7 +207,7 @@ class _CommandWall: lay1.addWidget(value1) lay2 = QtGui.QHBoxLayout() lay0.addLayout(lay2) - label2 = QtGui.QLabel("Height") + label2 = QtGui.QLabel(str(translate("Arch","Height"))) lay2.addWidget(label2) value2 = QtGui.QDoubleSpinBox() value2.setDecimals(2) @@ -211,14 +215,14 @@ class _CommandWall: lay2.addWidget(value2) lay3 = QtGui.QHBoxLayout() lay0.addLayout(lay3) - label3 = QtGui.QLabel("Alignment") + label3 = QtGui.QLabel(str(translate("Arch","Alignment"))) lay3.addWidget(label3) value3 = QtGui.QComboBox() items = ["Center","Left","Right"] value3.addItems(items) value3.setCurrentIndex(items.index(self.Align)) lay3.addWidget(value3) - value4 = QtGui.QCheckBox("Continue") + value4 = QtGui.QCheckBox(str(translate("Arch","Continue"))) lay0.addWidget(value4) QtCore.QObject.connect(value1,QtCore.SIGNAL("valueChanged(double)"),self.setWidth) QtCore.QObject.connect(value2,QtCore.SIGNAL("valueChanged(double)"),self.setHeight) @@ -245,13 +249,13 @@ class _Wall(ArchComponent.Component): def __init__(self,obj): ArchComponent.Component.__init__(self,obj) obj.addProperty("App::PropertyLength","Width","Base", - "The width of this wall. Not used if this wall is based on a face") + str(translate("Arch","The width of this wall. Not used if this wall is based on a face"))) obj.addProperty("App::PropertyLength","Height","Base", - "The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid") + str(translate("Arch","The height of this wall. Keep 0 for automatic. Not used if this wall is based on a solid"))) obj.addProperty("App::PropertyEnumeration","Align","Base", - "The alignment of this wall on its base object, if applicable") + str(translate("Arch","The alignment of this wall on its base object, if applicable"))) obj.addProperty("App::PropertyVector","Normal","Base", - "The normal extrusion direction of this object (keep (0,0,0) for automatic normal)") + str(translate("Arch","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))) obj.Align = ['Left','Right','Center'] self.Type = "Wall" obj.Width = 0.1 From 2a3ff10d84bd358f9b42126d544c71fbf5c257fb Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 31 May 2012 12:30:20 -0300 Subject: [PATCH 296/351] Arch: Adapted all other tools to doCommand() + translatable --- src/Mod/Arch/ArchAxis.py | 18 ++++---- src/Mod/Arch/ArchBuilding.py | 24 +++++++--- src/Mod/Arch/ArchCommands.py | 34 ++++++++++++--- src/Mod/Arch/ArchFloor.py | 27 ++++++++---- src/Mod/Arch/ArchRoof.py | 26 ++++++----- src/Mod/Arch/ArchSectionPlane.py | 75 +++++++++++++++++++++----------- src/Mod/Arch/ArchSite.py | 21 +++++++-- src/Mod/Arch/ArchStructure.py | 24 +++++----- src/Mod/Arch/ArchWindow.py | 10 +++-- 9 files changed, 173 insertions(+), 86 deletions(-) diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index 37cdf9f545..d165e69eaf 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -25,12 +25,13 @@ import FreeCAD,FreeCADGui,Draft,math,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore, QtGui from pivy import coin +from DraftTools import translate __title__="FreeCAD Axis System" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeAxis(num=0,size=0,name="Axes"): +def makeAxis(num=5,size=1,name=str(translate("Arch","Axes"))): '''makeAxis(num,size): makes an Axis System based on the given number of axes and interval distances''' obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) @@ -56,16 +57,17 @@ class _CommandAxis: 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Axis","Creates an axis system.")} def Activated(self): - FreeCAD.ActiveDocument.openTransaction("Axis") - makeAxis(5,1) + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Axis"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.makeAxis()") FreeCAD.ActiveDocument.commitTransaction() class _Axis: "The Axis object" def __init__(self,obj): - obj.addProperty("App::PropertyFloatList","Distances","Base", "The intervals between axes") - obj.addProperty("App::PropertyFloatList","Angles","Base", "The angles of each axis") - obj.addProperty("App::PropertyFloat","Length","Base", "The length of the axes") + obj.addProperty("App::PropertyFloatList","Distances","Base", str(translate("Arch","The intervals between axes"))) + obj.addProperty("App::PropertyFloatList","Angles","Base", str(translate("Arch","The angles of each axis"))) + obj.addProperty("App::PropertyFloat","Length","Base", str(translate("Arch","The length of the axes"))) self.Type = "Axis" obj.Length=1.0 obj.Proxy = self @@ -98,8 +100,8 @@ class _ViewProviderAxis: "A View Provider for the Axis object" def __init__(self,vobj): - vobj.addProperty("App::PropertyLength","BubbleSize","Base", "The size of the axis bubbles") - vobj.addProperty("App::PropertyEnumeration","NumerationStyle","Base", "The numeration style") + vobj.addProperty("App::PropertyLength","BubbleSize","Base", str(translate("Arch","The size of the axis bubbles"))) + vobj.addProperty("App::PropertyEnumeration","NumerationStyle","Base", str(translate("Arch","The numeration style"))) vobj.NumerationStyle = ["1,2,3","01,02,03","001,002,003","A,B,C","a,b,c","I,II,III","L0,L1,L2"] vobj.Proxy = self vobj.BubbleSize = .1 diff --git a/src/Mod/Arch/ArchBuilding.py b/src/Mod/Arch/ArchBuilding.py index f8ed4e8ca3..4b0011b34d 100644 --- a/src/Mod/Arch/ArchBuilding.py +++ b/src/Mod/Arch/ArchBuilding.py @@ -23,12 +23,13 @@ import FreeCAD,FreeCADGui,Draft,ArchCommands from PyQt4 import QtCore +from DraftTools import translate __title__="FreeCAD Building" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeBuilding(objectslist=None,join=False,name="Building"): +def makeBuilding(objectslist=None,join=False,name=str(translate("Arch","Building"))): '''makeBuilding(objectslist,[joinmode]): creates a building including the objects from the given list. If joinmode is True, components will be joined.''' obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) @@ -51,15 +52,24 @@ class _CommandBuilding: ok = False if (len(sel) == 1): if Draft.getType(sel[0]) in ["Cell","Site","Floor"]: - FreeCAD.ActiveDocument.openTransaction("Type conversion") - nobj = makeBuilding() - ArchCommands.copyProperties(sel[0],nobj) - FreeCAD.ActiveDocument.removeObject(sel[0].Name) + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Type conversion"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("obj = Arch.makeBuilding()") + FreeCADGui.doCommand("Arch.copyProperties(FreeCAD.ActiveDocument."+sel[0].Name+",obj)") + FreeCADGui.doCommand("FreeCAD.ActiveDocument.removeObject("+sel[0].Name+")") FreeCAD.ActiveDocument.commitTransaction() ok = True if not ok: - FreeCAD.ActiveDocument.openTransaction("Building") - makeBuilding(sel) + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch"," Create Building"))) + ss = "[" + for o in sel: + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Floor"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.makeBuilding("+ss+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 2ebfad0d0b..2025a6f308 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -24,6 +24,7 @@ import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore +from DraftTools import translate __title__="FreeCAD Arch Commands" __author__ = "Yorik van Havre" @@ -341,11 +342,20 @@ class _CommandAdd: def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction("Grouping") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Grouping"))) if not mergeCells(sel): host = sel.pop() - addComponents(sel,host) + ss = "[" + for o in sel: + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.addComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")") FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + class _CommandRemove: "the Arch Add command definition" @@ -362,13 +372,22 @@ class _CommandRemove: def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction("Ungrouping") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping"))) if Draft.getType(sel[-1]) in ["Wall","Structure"]: host = sel.pop() - removeComponents(sel,host) + ss = "[" + for o in sel: + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")") else: - removeComponents(sel) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.removeComponents("+ss+")") FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() class _CommandSplitMesh: @@ -387,7 +406,7 @@ class _CommandSplitMesh: def Activated(self): if FreeCADGui.Selection.getSelection(): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction("Split Mesh") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Split Mesh"))) for obj in sel: n = obj.Name nobjs = splitMesh(obj) @@ -396,6 +415,7 @@ class _CommandSplitMesh: for o in nobjs: g.addObject(o) FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() class _CommandMeshToShape: @@ -424,7 +444,7 @@ class _CommandMeshToShape: if f.InList: if f.InList[0].isDerivedFrom("App::DocumentObjectGroup"): g = f.InList[0] - FreeCAD.ActiveDocument.openTransaction("Mesh to Shape") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Mesh to Shape"))) for obj in FreeCADGui.Selection.getSelection(): newobj = meshToShape(obj) if g and newobj: diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index 606395961d..922d8aca0c 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -23,12 +23,13 @@ import FreeCAD,FreeCADGui,Draft,ArchCommands from PyQt4 import QtCore +from DraftTools import translate __title__="FreeCAD Arch Floor" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeFloor(objectslist=None,join=True,name="Floor"): +def makeFloor(objectslist=None,join=True,name=str(translate("Arch","Floor"))): '''makeFloor(objectslist,[joinmode]): creates a floor including the objects from the given list. If joinmode is False, components will not be joined.''' @@ -52,23 +53,31 @@ class _CommandFloor: ok = False if (len(sel) == 1): if Draft.getType(sel[0]) in ["Cell","Site","Building"]: - FreeCAD.ActiveDocument.openTransaction("Type conversion") - nobj = makeFloor() - ArchCommands.copyProperties(sel[0],nobj) - FreeCAD.ActiveDocument.removeObject(sel[0].Name) + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Type conversion"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("obj = Arch.makeFloor()") + FreeCADGui.doCommand("Arch.copyProperties(FreeCAD.ActiveDocument."+sel[0].Name+",obj)") + FreeCADGui.doCommand("FreeCAD.ActiveDocument.removeObject("+sel[0].Name+")") FreeCAD.ActiveDocument.commitTransaction() ok = True if not ok: - FreeCAD.ActiveDocument.openTransaction("Floor") - makeFloor(sel) + ss = "[" + for o in sel: + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Floor"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.makeFloor("+ss+")") FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() + FreeCAD.ActiveDocument.recompute() class _Floor: "The Cell object" def __init__(self,obj): obj.addProperty("App::PropertyLength","Height","Base", - "The height of this floor") + str(translate("Arch","The height of this floor"))) self.Type = "Floor" obj.Proxy = self self.Object = obj diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index 31515afbc8..4c8d6964c1 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -24,12 +24,13 @@ import FreeCAD,FreeCADGui,Draft,ArchComponent, DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore +from DraftTools import translate __title__="FreeCAD Roof" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeRoof(baseobj,facenr=1,angle=45,name="Roof"): +def makeRoof(baseobj,facenr=1,angle=45,name=str(translate("Arch","Roof"))): '''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on a face from an existing object. You can provide the number of the face to build the roof on (default = 1), the angle (default=45) and a name (default @@ -64,35 +65,38 @@ class _CommandRoof: if sel.HasSubObjects: if "Face" in sel.SubElementNames[0]: idx = int(sel.SubElementNames[0][4:]) - FreeCAD.ActiveDocument.openTransaction("Create Roof") - makeRoof(obj,idx) + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Roof"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.makeRoof(FreeCAD.ActiveDocument."+obj.Name+","+str(idx)+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() elif obj.isDerivedFrom("Part::Feature"): if len(obj.Shape.Faces) == 1: - FreeCAD.ActiveDocument.openTransaction("Create Roof") - makeRoof(obj,1) + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Roof"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.makeRoof(FreeCAD.ActiveDocument."+obj.Name+",1)") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() elif obj.isDerivedFrom("Part::Feature"): if len(obj.Shape.Faces) == 1: - FreeCAD.ActiveDocument.openTransaction("Create Roof") - makeRoof(obj,1) + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Roof"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.makeRoof(FreeCAD.ActiveDocument."+obj.Name+",1)") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() else: - FreeCAD.Console.PrintMessage("Unable to create a roof") + FreeCAD.Console.PrintMessage(str(translate("Arch","Unable to create a roof"))) else: - FreeCAD.Console.PrintMessage("No object selected") + FreeCAD.Console.PrintMessage(str(translate("Arch","No object selected"))) class _Roof(ArchComponent.Component): "The Roof object" def __init__(self,obj): ArchComponent.Component.__init__(self,obj) obj.addProperty("App::PropertyAngle","Angle","Base", - "The angle of this roof") + str(translate("Arch","The angle of this roof"))) obj.addProperty("App::PropertyInteger","Face","Base", - "The face number of the base object used to build this roof") + str(translate("Arch","The face number of the base object used to build this roof"))) self.Type = "Structure" def execute(self,obj): diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index e1230e59f7..8f695d7082 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -25,7 +25,45 @@ import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,math,Draft,ArchCommands, Dr from FreeCAD import Vector from PyQt4 import QtCore from pivy import coin +from DraftTools import translate +def makeSectionPlane(objectslist=None): + """makeSectionPlane([objectslist]) : Creates a Section plane objects including the + given objects. If no object is given, the whole document will be considered.""" + obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Section") + _SectionPlane(obj) + _ViewProviderSectionPlane(obj.ViewObject) + if objectslist: + g = [] + for o in objectslist: + if o.isDerivedFrom("Part::Feature"): + g.append(o) + elif o.isDerivedFrom("App::DocumentObjectGroup"): + g.append(o) + obj.Objects = g + +def makeSectionView(section): + """makeSectionView(section) : Creates a Drawing view of the given Section Plane + in the active Page object (a new page will be created if none exists""" + page = None + for o in FreeCAD.ActiveDocument.Objects: + if o.isDerivedFrom("Drawing::FeaturePage"): + page = o + break + if not page: + page = FreeCAD.ActiveDocument.addObject("Drawing::FeaturePage",str(translate("Arch","Page"))) + template = Draft.getParam("template") + if not template: + template = FreeCAD.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg' + page.ViewObject.HintOffsetX = 200 + page.ViewObject.HintOffsetY = 100 + page.ViewObject.HintScale = 20 + page.Template = template + + view = FreeCAD.ActiveDocument.addObject("Drawing::FeatureViewPython","View") + page.addObject(view) + _ArchDrawingView(view) + view.Source = section class _CommandSectionPlane: "the Arch SectionPlane command definition" @@ -37,30 +75,17 @@ class _CommandSectionPlane: def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction("Section Plane") - obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Section") - _SectionPlane(obj) - _ViewProviderSectionPlane(obj.ViewObject) - FreeCAD.ActiveDocument.commitTransaction() - g = [] + ss = "[" for o in sel: - if o.isDerivedFrom("Part::Feature"): - g.append(o) - elif o.isDerivedFrom("App::DocumentObjectGroup"): - g.append(o) - obj.Objects = g - page = FreeCAD.ActiveDocument.addObject("Drawing::FeaturePage","Page") - template = Draft.getParam("template") - if not template: - template = FreeCAD.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg' - page.ViewObject.HintOffsetX = 200 - page.ViewObject.HintOffsetY = 100 - page.ViewObject.HintScale = 20 - page.Template = template - view = FreeCAD.ActiveDocument.addObject("Drawing::FeatureViewPython","View") - page.addObject(view) - _ArchDrawingView(view) - view.Source = obj + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Section Plane"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("section = Arch.makeSectionPlane("+ss+")") + FreeCADGui.doCommand("Arch.makeSectionView(section)") + FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() class _SectionPlane: @@ -68,7 +93,7 @@ class _SectionPlane: def __init__(self,obj): obj.Proxy = self obj.addProperty("App::PropertyLinkList","Objects","Base", - "The objects that must be considered by this section plane. Empty means all document") + str(translate("Arch","The objects that must be considered by this section plane. Empty means all document"))) self.Type = "SectionPlane" def execute(self,obj): @@ -89,7 +114,7 @@ class _ViewProviderSectionPlane(ArchComponent.ViewProviderComponent): "A View Provider for Section Planes" def __init__(self,vobj): vobj.addProperty("App::PropertyLength","DisplaySize","Base", - "The display size of the section plane") + str(translate("Arch","The display size of this section plane"))) vobj.DisplaySize = 1 vobj.Transparency = 85 vobj.LineWidth = 1 diff --git a/src/Mod/Arch/ArchSite.py b/src/Mod/Arch/ArchSite.py index 300fd09eff..d05a7e8ffa 100644 --- a/src/Mod/Arch/ArchSite.py +++ b/src/Mod/Arch/ArchSite.py @@ -23,12 +23,13 @@ import FreeCAD,FreeCADGui,Draft,ArchCommands from PyQt4 import QtCore +from DraftTools import translate __title__="FreeCAD Site" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeSite(objectslist=None,name="Site"): +def makeSite(objectslist=None,name=str(translate("Arch","Site"))): '''makeBuilding(objectslist): creates a site including the objects from the given list.''' obj = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",name) @@ -51,15 +52,27 @@ class _CommandSite: ok = False if (len(sel) == 1): if Draft.getType(sel[0]) in ["Cell","Building","Floor"]: - FreeCAD.ActiveDocument.openTransaction("Type conversion") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Type conversion"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("obj = Arch.makeSite()") + FreeCADGui.doCommand("Arch.copyProperties(FreeCAD.ActiveDocument."+sel[0].Name+",obj)") + FreeCADGui.doCommand("FreeCAD.ActiveDocument.removeObject("+sel[0].Name+")") + nobj = makeSite() ArchCommands.copyProperties(sel[0],nobj) FreeCAD.ActiveDocument.removeObject(sel[0].Name) FreeCAD.ActiveDocument.commitTransaction() ok = True if not ok: - FreeCAD.ActiveDocument.openTransaction("Site") - makeSite(sel) + ss = "[" + for o in sel: + if len(ss) > 1: + ss += "," + ss += "FreeCAD.ActiveDocument."+o.Name + ss += "]" + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Site"))) + FreeCADGui.doCommand("import Arch") + FreeCADGui.doCommand("Arch.makeSite("+ss+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 2327ad7cac..7bf73cc1e0 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -24,12 +24,13 @@ import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore +from DraftTools import translate __title__="FreeCAD Structure" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeStructure(baseobj=None,length=None,width=None,height=None,name="Structure"): +def makeStructure(baseobj=None,length=None,width=None,height=None,name=str(translate("Arch","Structure"))): '''makeStructure([obj],[length],[width],[heigth],[swap]): creates a structure element based on the given profile object and the given extrusion height. If no base object is given, you can also specify @@ -64,29 +65,31 @@ class _CommandStructure: 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Structure","Creates a structure object from scratch or from a selected object (sketch, wire, face or solid)")} def Activated(self): + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure"))) + FreeCADGui.doCommand("import Arch") sel = FreeCADGui.Selection.getSelection() if sel: - FreeCAD.ActiveDocument.openTransaction("Structure") for obj in sel: - makeStructure(obj) - FreeCAD.ActiveDocument.commitTransaction() + FreeCADGui.doCommand("Arch.makeStructure(FreeCAD.ActiveDocument."+obj.Name+")") else: - makeStructure() + FreeCADGui.doCommand("Arch.makeStructure()") + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() class _Structure(ArchComponent.Component): "The Structure object" def __init__(self,obj): ArchComponent.Component.__init__(self,obj) obj.addProperty("App::PropertyLength","Length","Base", - "The length of this element, if not based on a profile") + str(translate("Arch","The length of this element, if not based on a profile"))) obj.addProperty("App::PropertyLength","Width","Base", - "The width of this element, if not based on a profile") + str(translate("Arch","The width of this element, if not based on a profile"))) obj.addProperty("App::PropertyLength","Height","Base", - "The height or extrusion depth of this element. Keep 0 for automatic") + str(translate("Arch","The height or extrusion depth of this element. Keep 0 for automatic"))) obj.addProperty("App::PropertyLinkList","Axes","Base", - "Axes systems this structure is built on") + str(translate("Arch","Axes systems this structure is built on"))) obj.addProperty("App::PropertyVector","Normal","Base", - "The normal extrusion direction of this object (keep (0,0,0) for automatic normal)") + str(translate("Arch","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))) self.Type = "Structure" def execute(self,obj): @@ -167,7 +170,6 @@ class _Structure(ArchComponent.Component): if hasattr(hole,"Proxy"): if hasattr(hole.Proxy,"Subvolume"): if hole.Proxy.Subvolume: - print "cutting subvolume",hole.Proxy.Subvolume base = base.cut(hole.Proxy.Subvolume) cut = True if not cut: diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 35813ddfc8..40b038aed0 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -24,12 +24,13 @@ import FreeCAD,FreeCADGui,Draft,ArchComponent,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore,QtGui +from DraftTools import translate __title__="FreeCAD Wall" __author__ = "Yorik van Havre" __url__ = "http://free-cad.sourceforge.net" -def makeWindow(baseobj=None,width=None,name="Window"): +def makeWindow(baseobj=None,width=None,name=str(translate("Arch","Window"))): '''makeWindow(obj,[name]): creates a window based on the given object''' if baseobj: @@ -87,9 +88,10 @@ class _CommandWindow: def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction("Create Window") + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Window"))) + FreeCADGui.doCommand("import Arch") for obj in sel: - makeWindow(obj) + FreeCADGui.doCommand("Arch.makeWindow(FreeCAD.ActiveDocument."+obj.Name+")") FreeCAD.ActiveDocument.commitTransaction() class _Window(ArchComponent.Component): @@ -97,7 +99,7 @@ class _Window(ArchComponent.Component): def __init__(self,obj): ArchComponent.Component.__init__(self,obj) obj.addProperty("App::PropertyStringList","WindowParts","Base", - "the components of this window") + str(translate("Arch","the components of this window"))) self.Type = "Window" def execute(self,obj): From 8c3f97c98e73c8e3dda7ed13270d0cc7a5a2cdb7 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 30 May 2012 15:18:37 +0200 Subject: [PATCH 297/351] Keep faces colors on boolean operations --- src/Mod/Part/App/FeaturePartBoolean.cpp | 18 ++++- src/Mod/Part/App/FeaturePartBoolean.h | 8 ++- src/Mod/Part/App/FeaturePartCommon.cpp | 8 +-- src/Mod/Part/App/FeaturePartCommon.h | 2 +- src/Mod/Part/App/FeaturePartCut.cpp | 8 +-- src/Mod/Part/App/FeaturePartCut.h | 2 +- src/Mod/Part/App/FeaturePartFuse.cpp | 8 +-- src/Mod/Part/App/FeaturePartFuse.h | 2 +- src/Mod/Part/App/FeaturePartSection.cpp | 8 +-- src/Mod/Part/App/FeaturePartSection.h | 2 +- src/Mod/Part/Gui/ViewProviderBoolean.cpp | 84 ++++++++++++++++++++++++ src/Mod/Part/Gui/ViewProviderBoolean.h | 1 + 12 files changed, 119 insertions(+), 32 deletions(-) diff --git a/src/Mod/Part/App/FeaturePartBoolean.cpp b/src/Mod/Part/App/FeaturePartBoolean.cpp index f21296a8b2..7418db97a6 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.cpp +++ b/src/Mod/Part/App/FeaturePartBoolean.cpp @@ -23,6 +23,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include +#include #endif #include "FeaturePartBoolean.h" @@ -33,7 +35,7 @@ using namespace Part; PROPERTY_SOURCE_ABSTRACT(Part::Boolean, Part::Feature) -Boolean::Boolean(void) +Boolean::Boolean(void) : myBoolOp(0) { ADD_PROPERTY(Base,(0)); ADD_PROPERTY(Tool,(0)); @@ -66,13 +68,23 @@ App::DocumentObjectExecReturn *Boolean::execute(void) TopoDS_Shape BaseShape = base->Shape.getValue(); TopoDS_Shape ToolShape = tool->Shape.getValue(); - TopoDS_Shape resShape = runOperation(BaseShape, ToolShape); - if (resShape.IsNull()) + std::auto_ptr mkBool(makeOperation(BaseShape, ToolShape)); + if (!mkBool->IsDone()) { + return new App::DocumentObjectExecReturn("Boolean operation failed"); + } + const TopoDS_Shape& resShape = mkBool->Shape(); + if (resShape.IsNull()) { return new App::DocumentObjectExecReturn("Resulting shape is invalid"); + } + + // tmp. set boolean operation pointer + this->myBoolOp = mkBool.get(); this->Shape.setValue(resShape); + this->myBoolOp = 0; return App::DocumentObject::StdReturn; } catch (...) { + this->myBoolOp = 0; return new App::DocumentObjectExecReturn("A fatal error occurred when running boolean operation"); } } diff --git a/src/Mod/Part/App/FeaturePartBoolean.h b/src/Mod/Part/App/FeaturePartBoolean.h index 742af5098e..13305dffe5 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.h +++ b/src/Mod/Part/App/FeaturePartBoolean.h @@ -27,6 +27,8 @@ #include #include "PartFeature.h" +class BRepAlgoAPI_BooleanOperation; + namespace Part { @@ -51,9 +53,13 @@ public: const char* getViewProviderName(void) const { return "PartGui::ViewProviderBoolean"; } + BRepAlgoAPI_BooleanOperation* getBooleanOperation() const { return myBoolOp; } protected: - virtual TopoDS_Shape runOperation(const TopoDS_Shape&, const TopoDS_Shape&) const = 0; + virtual BRepAlgoAPI_BooleanOperation* makeOperation(const TopoDS_Shape&, const TopoDS_Shape&) const = 0; + +private: + BRepAlgoAPI_BooleanOperation* myBoolOp; }; } diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index 828512bc35..1835cdfc14 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -41,14 +41,10 @@ Common::Common(void) { } -TopoDS_Shape Common::runOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const +BRepAlgoAPI_BooleanOperation* Common::makeOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const { // Let's call algorithm computing a section operation: - BRepAlgoAPI_Common mkCommon(base, tool); - // Let's check if the section has been successful - if (!mkCommon.IsDone()) - throw Base::Exception("Intersection failed"); - return mkCommon.Shape(); + return new BRepAlgoAPI_Common(base, tool); } // ---------------------------------------------------- diff --git a/src/Mod/Part/App/FeaturePartCommon.h b/src/Mod/Part/App/FeaturePartCommon.h index 295ec2e4f2..19df8cdebb 100644 --- a/src/Mod/Part/App/FeaturePartCommon.h +++ b/src/Mod/Part/App/FeaturePartCommon.h @@ -41,7 +41,7 @@ public: //@{ /// recalculate the Feature protected: - TopoDS_Shape runOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; + BRepAlgoAPI_BooleanOperation* makeOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; //@} }; diff --git a/src/Mod/Part/App/FeaturePartCut.cpp b/src/Mod/Part/App/FeaturePartCut.cpp index 1d48c1783f..6b6d792c5e 100644 --- a/src/Mod/Part/App/FeaturePartCut.cpp +++ b/src/Mod/Part/App/FeaturePartCut.cpp @@ -40,12 +40,8 @@ Cut::Cut(void) { } -TopoDS_Shape Cut::runOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const +BRepAlgoAPI_BooleanOperation* Cut::makeOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const { // Let's call algorithm computing a cut operation: - BRepAlgoAPI_Cut mkCut(base, tool); - // Let's check if the cut has been successful - if (!mkCut.IsDone()) - throw Base::Exception("Cut failed"); - return mkCut.Shape(); + return new BRepAlgoAPI_Cut(base, tool); } diff --git a/src/Mod/Part/App/FeaturePartCut.h b/src/Mod/Part/App/FeaturePartCut.h index 63b0de61a6..11187781c9 100644 --- a/src/Mod/Part/App/FeaturePartCut.h +++ b/src/Mod/Part/App/FeaturePartCut.h @@ -42,7 +42,7 @@ public: //@{ /// recalculate the Feature protected: - TopoDS_Shape runOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; + BRepAlgoAPI_BooleanOperation* makeOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; //@} }; diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index d0f4a0e972..ea25450fc6 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -41,14 +41,10 @@ Fuse::Fuse(void) { } -TopoDS_Shape Fuse::runOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const +BRepAlgoAPI_BooleanOperation* Fuse::makeOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const { // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Fuse mkFuse(base, tool); - // Let's check if the fusion has been successful - if (!mkFuse.IsDone()) - throw Base::Exception("Fusion failed"); - return mkFuse.Shape(); + return new BRepAlgoAPI_Fuse(base, tool); } // ---------------------------------------------------- diff --git a/src/Mod/Part/App/FeaturePartFuse.h b/src/Mod/Part/App/FeaturePartFuse.h index 251d7ec580..7e2e88d322 100644 --- a/src/Mod/Part/App/FeaturePartFuse.h +++ b/src/Mod/Part/App/FeaturePartFuse.h @@ -42,7 +42,7 @@ public: //@{ /// recalculate the Feature protected: - TopoDS_Shape runOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; + BRepAlgoAPI_BooleanOperation* makeOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; //@} }; diff --git a/src/Mod/Part/App/FeaturePartSection.cpp b/src/Mod/Part/App/FeaturePartSection.cpp index 6beb1eeef3..55cd6da6ea 100644 --- a/src/Mod/Part/App/FeaturePartSection.cpp +++ b/src/Mod/Part/App/FeaturePartSection.cpp @@ -39,12 +39,8 @@ Section::Section(void) { } -TopoDS_Shape Section::runOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const +BRepAlgoAPI_BooleanOperation* Section::makeOperation(const TopoDS_Shape& base, const TopoDS_Shape& tool) const { // Let's call algorithm computing a section operation: - BRepAlgoAPI_Section mkSection(base, tool); - // Let's check if the section has been successful - if (!mkSection.IsDone()) - throw Base::Exception("Section failed"); - return mkSection.Shape(); + return new BRepAlgoAPI_Section(base, tool); } diff --git a/src/Mod/Part/App/FeaturePartSection.h b/src/Mod/Part/App/FeaturePartSection.h index 911c2a5b7d..69ec64c927 100644 --- a/src/Mod/Part/App/FeaturePartSection.h +++ b/src/Mod/Part/App/FeaturePartSection.h @@ -42,7 +42,7 @@ public: //@{ /// recalculate the Feature protected: - TopoDS_Shape runOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; + BRepAlgoAPI_BooleanOperation* makeOperation(const TopoDS_Shape&, const TopoDS_Shape&) const; //@} }; diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.cpp b/src/Mod/Part/Gui/ViewProviderBoolean.cpp index 5857b2ef71..d35cd0dde2 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/Part/Gui/ViewProviderBoolean.cpp @@ -24,9 +24,15 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include +# include +# include +# include +# include #endif #include "ViewProviderBoolean.h" +#include #include #include #include @@ -71,6 +77,84 @@ QIcon ViewProviderBoolean::getIcon(void) const return ViewProviderPart::getIcon(); } +void findFaces(BRepAlgoAPI_BooleanOperation* mkBool, + const TopTools_IndexedMapOfShape& M1, + const TopTools_IndexedMapOfShape& M3, + const std::vector& colBase, + std::vector& colBool) +{ + for (int i=1; i<=M1.Extent(); i++) { + bool modified=false, generated=false; + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(mkBool->Modified(M1(i))); it.More(); it.Next()) { + modified = true; + for (int j=1; j<=M3.Extent(); j++) { + if (M3(j).IsPartner(it.Value())) { + colBool[j-1] = colBase[i-1]; + break; + } + } + } + + for (it.Initialize(mkBool->Generated(M1(i))); it.More(); it.Next()) { + generated = true; + for (int j=1; j<=M3.Extent(); j++) { + if (M3(j).IsPartner(it.Value())) { + colBool[j-1] = colBase[i-1]; + break; + } + } + } + + if (!modified && !generated && !mkBool->IsDeleted(M1(i))) { + for (int j=1; j<=M3.Extent(); j++) { + if (M3(j).IsPartner(M1(i))) { + colBool[j-1] = colBase[i-1]; + break; + } + } + } + } +} + +void ViewProviderBoolean::updateData(const App::Property* prop) +{ + PartGui::ViewProviderPart::updateData(prop); + if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId()) { + Part::Boolean* objBool = dynamic_cast(getObject()); + Part::Feature* objBase = dynamic_cast(objBool->Base.getValue()); + Part::Feature* objTool = dynamic_cast(objBool->Tool.getValue()); + + BRepAlgoAPI_BooleanOperation* mkBool = objBool->getBooleanOperation(); + if (mkBool && objBase && objTool) { + const TopoDS_Shape& baseShape = objBase->Shape.getValue(); + const TopoDS_Shape& toolShape = objTool->Shape.getValue(); + const TopoDS_Shape& boolShape = objBool->Shape.getValue(); + + TopTools_IndexedMapOfShape M1, M2, M3; + TopExp::MapShapes(baseShape, TopAbs_FACE, M1); + TopExp::MapShapes(toolShape, TopAbs_FACE, M2); + TopExp::MapShapes(boolShape, TopAbs_FACE, M3); + Gui::ViewProvider* vpBase = Gui::Application::Instance->getViewProvider(objBase); + Gui::ViewProvider* vpTool = Gui::Application::Instance->getViewProvider(objTool); + std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); + std::vector colTool = static_cast(vpTool)->DiffuseColor.getValues(); + std::vector colBool; + colBool.resize(M3.Extent(), this->ShapeColor.getValue()); + bool applyColor=false; + if (colBase.size() == M1.Extent()) { + findFaces(mkBool, M1, M3, colBase, colBool); + applyColor = true; + } + if (colTool.size() == M2.Extent()) { + findFaces(mkBool, M2, M3, colTool, colBool); + applyColor = true; + } + if (applyColor) + this->DiffuseColor.setValues(colBool); + } + } +} PROPERTY_SOURCE(PartGui::ViewProviderMultiFuse,PartGui::ViewProviderPart) diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.h b/src/Mod/Part/Gui/ViewProviderBoolean.h index 0fb245bb4e..0a34127b16 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.h +++ b/src/Mod/Part/Gui/ViewProviderBoolean.h @@ -42,6 +42,7 @@ public: /// grouping handling std::vector claimChildren(void) const; QIcon getIcon(void) const; + void updateData(const App::Property*); }; /// ViewProvider for the MultiFuse feature From 9e872e4987c491128688ad6371ecb31df75c6b96 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 30 May 2012 21:39:01 +0200 Subject: [PATCH 298/351] Keep faces colors on boolean operations --- src/Mod/Part/App/AppPart.cpp | 1 + src/Mod/Part/App/FeaturePartBoolean.cpp | 16 ++- src/Mod/Part/App/FeaturePartBoolean.h | 5 +- src/Mod/Part/App/FeaturePartCommon.cpp | 7 + src/Mod/Part/App/FeaturePartCommon.h | 1 + src/Mod/Part/App/FeaturePartFuse.cpp | 7 + src/Mod/Part/App/FeaturePartFuse.h | 1 + src/Mod/Part/App/PartFeature.cpp | 55 ++++++++ src/Mod/Part/App/PartFeature.h | 6 +- src/Mod/Part/App/PropertyTopoShape.cpp | 66 +++++++++ src/Mod/Part/App/PropertyTopoShape.h | 62 +++++++- src/Mod/Part/Gui/ViewProviderBoolean.cpp | 171 ++++++++++++++++------- src/Mod/Part/Gui/ViewProviderBoolean.h | 2 + 13 files changed, 334 insertions(+), 66 deletions(-) diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 875f04cd4c..716597e2b1 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -134,6 +134,7 @@ void PartExport initPart() Part::TopoShape ::init(); Part::PropertyPartShape ::init(); Part::PropertyGeometryList ::init(); + Part::PropertyShapeHistory ::init(); Part::PropertyFilletEdges ::init(); Part::Feature ::init(); diff --git a/src/Mod/Part/App/FeaturePartBoolean.cpp b/src/Mod/Part/App/FeaturePartBoolean.cpp index 7418db97a6..1a2608797b 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.cpp +++ b/src/Mod/Part/App/FeaturePartBoolean.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include -#include +# include #endif #include "FeaturePartBoolean.h" @@ -35,10 +35,13 @@ using namespace Part; PROPERTY_SOURCE_ABSTRACT(Part::Boolean, Part::Feature) -Boolean::Boolean(void) : myBoolOp(0) +Boolean::Boolean(void) { ADD_PROPERTY(Base,(0)); ADD_PROPERTY(Tool,(0)); + ADD_PROPERTY_TYPE(History,(ShapeHistory()), "Boolean", (App::PropertyType) + (App::Prop_Output|App::Prop_Transient|App::Prop_Hidden), "Shape history"); + History.setSize(0); } short Boolean::mustExecute() const @@ -77,14 +80,15 @@ App::DocumentObjectExecReturn *Boolean::execute(void) return new App::DocumentObjectExecReturn("Resulting shape is invalid"); } - // tmp. set boolean operation pointer - this->myBoolOp = mkBool.get(); + std::vector history; + history.push_back(buildHistory(*mkBool.get(), TopAbs_FACE, resShape, BaseShape)); + history.push_back(buildHistory(*mkBool.get(), TopAbs_FACE, resShape, ToolShape)); + this->Shape.setValue(resShape); - this->myBoolOp = 0; + this->History.setValues(history); return App::DocumentObject::StdReturn; } catch (...) { - this->myBoolOp = 0; return new App::DocumentObjectExecReturn("A fatal error occurred when running boolean operation"); } } diff --git a/src/Mod/Part/App/FeaturePartBoolean.h b/src/Mod/Part/App/FeaturePartBoolean.h index 13305dffe5..2730af82f2 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.h +++ b/src/Mod/Part/App/FeaturePartBoolean.h @@ -41,6 +41,7 @@ public: App::PropertyLink Base; App::PropertyLink Tool; + PropertyShapeHistory History; /** @name methods overide Feature */ //@{ @@ -53,13 +54,9 @@ public: const char* getViewProviderName(void) const { return "PartGui::ViewProviderBoolean"; } - BRepAlgoAPI_BooleanOperation* getBooleanOperation() const { return myBoolOp; } protected: virtual BRepAlgoAPI_BooleanOperation* makeOperation(const TopoDS_Shape&, const TopoDS_Shape&) const = 0; - -private: - BRepAlgoAPI_BooleanOperation* myBoolOp; }; } diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index 1835cdfc14..ea4be0edd8 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -56,6 +56,9 @@ MultiCommon::MultiCommon(void) { ADD_PROPERTY(Shapes,(0)); Shapes.setSize(0); + ADD_PROPERTY_TYPE(History,(ShapeHistory()), "Boolean", (App::PropertyType) + (App::Prop_Output|App::Prop_Transient|App::Prop_Hidden), "Shape history"); + History.setSize(0); } short MultiCommon::mustExecute() const @@ -78,6 +81,7 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void) } if (s.size() >= 2) { + std::vector history; TopoDS_Shape res = s.front(); for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { // Let's call algorithm computing a fuse operation: @@ -86,10 +90,13 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void) if (!mkCommon.IsDone()) throw Base::Exception("Intersection failed"); res = mkCommon.Shape(); + history.push_back(buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape1())); + history.push_back(buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape2())); } if (res.IsNull()) throw Base::Exception("Resulting shape is invalid"); this->Shape.setValue(res); + this->History.setValues(history); } else { throw Base::Exception("Not enough shape objects linked"); diff --git a/src/Mod/Part/App/FeaturePartCommon.h b/src/Mod/Part/App/FeaturePartCommon.h index 19df8cdebb..ccb568aed9 100644 --- a/src/Mod/Part/App/FeaturePartCommon.h +++ b/src/Mod/Part/App/FeaturePartCommon.h @@ -53,6 +53,7 @@ public: MultiCommon(); App::PropertyLinkList Shapes; + PropertyShapeHistory History; /** @name methods override feature */ //@{ diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index ea25450fc6..8493b7b88b 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -56,6 +56,9 @@ MultiFuse::MultiFuse(void) { ADD_PROPERTY(Shapes,(0)); Shapes.setSize(0); + ADD_PROPERTY_TYPE(History,(ShapeHistory()), "Boolean", (App::PropertyType) + (App::Prop_Output|App::Prop_Transient|App::Prop_Hidden), "Shape history"); + History.setSize(0); } short MultiFuse::mustExecute() const @@ -79,6 +82,7 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void) if (s.size() >= 2) { try { + std::vector history; TopoDS_Shape res = s.front(); for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { // Let's call algorithm computing a fuse operation: @@ -87,10 +91,13 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void) if (!mkFuse.IsDone()) throw Base::Exception("Fusion failed"); res = mkFuse.Shape(); + history.push_back(buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape1())); + history.push_back(buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape2())); } if (res.IsNull()) throw Base::Exception("Resulting shape is invalid"); this->Shape.setValue(res); + this->History.setValues(history); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); diff --git a/src/Mod/Part/App/FeaturePartFuse.h b/src/Mod/Part/App/FeaturePartFuse.h index 7e2e88d322..f1c83bb6f8 100644 --- a/src/Mod/Part/App/FeaturePartFuse.h +++ b/src/Mod/Part/App/FeaturePartFuse.h @@ -54,6 +54,7 @@ public: MultiFuse(); App::PropertyLinkList Shapes; + PropertyShapeHistory History; /** @name methods override feature */ //@{ diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index c9483f37c1..e71edcc7d9 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -26,6 +26,10 @@ #ifndef _PreComp_ # include # include +# include +# include +# include +# include #endif @@ -128,6 +132,57 @@ TopLoc_Location Feature::getLocation() const return TopLoc_Location(trf); } +ShapeHistory Feature::buildHistory(BRepBuilderAPI_MakeShape& mkShape, TopAbs_ShapeEnum type, + const TopoDS_Shape& newS, const TopoDS_Shape& oldS) +{ + ShapeHistory history; + history.type = type; + + TopTools_IndexedMapOfShape newM, oldM; + TopExp::MapShapes(newS, type, newM); + TopExp::MapShapes(oldS, type, oldM); + + for (int i=1; i<=oldM.Extent(); i++) { + bool modified=false, generated=false; + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(mkShape.Modified(oldM(i))); it.More(); it.Next()) { + modified = true; + for (int j=1; j<=newM.Extent(); j++) { + if (newM(j).IsPartner(it.Value())) { + history.modified[i-1].push_back(j-1); + break; + } + } + } + + for (it.Initialize(mkShape.Generated(oldM(i))); it.More(); it.Next()) { + generated = true; + for (int j=1; j<=newM.Extent(); j++) { + if (newM(j).IsPartner(it.Value())) { + history.generated[i-1].push_back(j-1); + break; + } + } + } + + if (!modified && !generated) { + if (mkShape.IsDeleted(oldM(i))) { + history.deleted.insert(i-1); + } + else { + for (int j=1; j<=newM.Extent(); j++) { + if (newM(j).IsPartner(oldM(i))) { + history.accepted[i-1] = j-1; + break; + } + } + } + } + } + + return history; +} + /// returns the type name of the ViewProvider const char* Feature::getViewProviderName(void) const { return "PartGui::ViewProviderPart"; diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index efa0b7a836..159f0473e1 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -30,6 +30,8 @@ #include #include +class BRepBuilderAPI_MakeShape; + namespace Part { @@ -63,9 +65,9 @@ public: protected: void onChanged(const App::Property* prop); - -protected: TopLoc_Location getLocation() const; + ShapeHistory buildHistory(BRepBuilderAPI_MakeShape&, TopAbs_ShapeEnum type, + const TopoDS_Shape& newS, const TopoDS_Shape& oldS); }; class FilletBase : public Part::Feature diff --git a/src/Mod/Part/App/PropertyTopoShape.cpp b/src/Mod/Part/App/PropertyTopoShape.cpp index d0cc3981c2..f3e83a809a 100644 --- a/src/Mod/Part/App/PropertyTopoShape.cpp +++ b/src/Mod/Part/App/PropertyTopoShape.cpp @@ -343,6 +343,72 @@ void PropertyPartShape::RestoreDocFile(Base::Reader &reader) // ------------------------------------------------------------------------- +TYPESYSTEM_SOURCE(Part::PropertyShapeHistory , App::PropertyLists); + +PropertyShapeHistory::PropertyShapeHistory() +{ +} + +PropertyShapeHistory::~PropertyShapeHistory() +{ +} + +void PropertyShapeHistory::setValue(const ShapeHistory& sh) +{ + aboutToSetValue(); + _lValueList.resize(1); + _lValueList[0] = sh; + hasSetValue(); +} + +void PropertyShapeHistory::setValues(const std::vector& values) +{ + aboutToSetValue(); + _lValueList = values; + hasSetValue(); +} + +PyObject *PropertyShapeHistory::getPyObject(void) +{ + return Py::new_reference_to(Py::None()); +} + +void PropertyShapeHistory::setPyObject(PyObject *value) +{ +} + +void PropertyShapeHistory::Save (Base::Writer &writer) const +{ +} + +void PropertyShapeHistory::Restore(Base::XMLReader &reader) +{ +} + +void PropertyShapeHistory::SaveDocFile (Base::Writer &writer) const +{ +} + +void PropertyShapeHistory::RestoreDocFile(Base::Reader &reader) +{ +} + +App::Property *PropertyShapeHistory::Copy(void) const +{ + PropertyShapeHistory *p= new PropertyShapeHistory(); + p->_lValueList = _lValueList; + return p; +} + +void PropertyShapeHistory::Paste(const Property &from) +{ + aboutToSetValue(); + _lValueList = dynamic_cast(from)._lValueList; + hasSetValue(); +} + +// ------------------------------------------------------------------------- + TYPESYSTEM_SOURCE(Part::PropertyFilletEdges , App::PropertyLists); PropertyFilletEdges::PropertyFilletEdges() diff --git a/src/Mod/Part/App/PropertyTopoShape.h b/src/Mod/Part/App/PropertyTopoShape.h index 3113ed4561..190a82d2a6 100644 --- a/src/Mod/Part/App/PropertyTopoShape.h +++ b/src/Mod/Part/App/PropertyTopoShape.h @@ -21,12 +21,15 @@ ***************************************************************************/ -#ifndef PROPERTYTOPOSHAPE_H -#define PROPERTYTOPOSHAPE_H +#ifndef PART_PROPERTYTOPOSHAPE_H +#define PART_PROPERTYTOPOSHAPE_H #include "TopoShape.h" +#include #include #include +#include +#include namespace Part { @@ -95,6 +98,59 @@ private: TopoShape _Shape; }; +struct PartExport ShapeHistory { + TopAbs_ShapeEnum type; + std::map > modified; + std::map > generated; + std::map accepted; + std::set deleted; +}; + +class PartExport PropertyShapeHistory : public App::PropertyLists +{ + TYPESYSTEM_HEADER(); + +public: + PropertyShapeHistory(); + ~PropertyShapeHistory(); + + virtual void setSize(int newSize) { + _lValueList.resize(newSize); + } + virtual int getSize(void) const { + return _lValueList.size(); + } + + /** Sets the property + */ + void setValue(const ShapeHistory&); + + void setValues (const std::vector& values); + + const std::vector &getValues(void) const { + return _lValueList; + } + + virtual PyObject *getPyObject(void); + virtual void setPyObject(PyObject *); + + virtual void Save (Base::Writer &writer) const; + virtual void Restore(Base::XMLReader &reader); + + virtual void SaveDocFile (Base::Writer &writer) const; + virtual void RestoreDocFile(Base::Reader &reader); + + virtual Property *Copy(void) const; + virtual void Paste(const Property &from); + + virtual unsigned int getMemSize (void) const { + return _lValueList.size() * sizeof(ShapeHistory); + } + +private: + std::vector _lValueList; +}; + /** A property class to store hash codes and two radii for the fillet algorithm. * @author Werner Mayer */ @@ -151,4 +207,4 @@ private: } //namespace Part -#endif // PROPERTYTOPOSHAPE_H +#endif // PART_PROPERTYTOPOSHAPE_H diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.cpp b/src/Mod/Part/Gui/ViewProviderBoolean.cpp index d35cd0dde2..46c85bb658 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/Part/Gui/ViewProviderBoolean.cpp @@ -77,80 +77,69 @@ QIcon ViewProviderBoolean::getIcon(void) const return ViewProviderPart::getIcon(); } -void findFaces(BRepAlgoAPI_BooleanOperation* mkBool, - const TopTools_IndexedMapOfShape& M1, - const TopTools_IndexedMapOfShape& M3, - const std::vector& colBase, - std::vector& colBool) +void applyColor(const Part::ShapeHistory& hist, + const std::vector& colBase, + std::vector& colBool) { - for (int i=1; i<=M1.Extent(); i++) { - bool modified=false, generated=false; - TopTools_ListIteratorOfListOfShape it; - for (it.Initialize(mkBool->Modified(M1(i))); it.More(); it.Next()) { - modified = true; - for (int j=1; j<=M3.Extent(); j++) { - if (M3(j).IsPartner(it.Value())) { - colBool[j-1] = colBase[i-1]; - break; - } - } + std::map >::const_iterator jt; + // apply color from modified faces + for (jt = hist.modified.begin(); jt != hist.modified.end(); ++jt) { + std::vector::const_iterator kt; + for (kt = jt->second.begin(); kt != jt->second.end(); ++kt) { + colBool[*kt] = colBase[jt->first]; } - - for (it.Initialize(mkBool->Generated(M1(i))); it.More(); it.Next()) { - generated = true; - for (int j=1; j<=M3.Extent(); j++) { - if (M3(j).IsPartner(it.Value())) { - colBool[j-1] = colBase[i-1]; - break; - } - } - } - - if (!modified && !generated && !mkBool->IsDeleted(M1(i))) { - for (int j=1; j<=M3.Extent(); j++) { - if (M3(j).IsPartner(M1(i))) { - colBool[j-1] = colBase[i-1]; - break; - } - } + } + // apply color from generated faces + for (jt = hist.generated.begin(); jt != hist.generated.end(); ++jt) { + std::vector::const_iterator kt; + for (kt = jt->second.begin(); kt != jt->second.end(); ++kt) { + colBool[*kt] = colBase[jt->first]; } } + // apply data from accepted faces + for (std::map::const_iterator kt = hist.accepted.begin(); kt != hist.accepted.end(); ++kt) { + colBool[kt->second] = colBase[kt->first]; + } } void ViewProviderBoolean::updateData(const App::Property* prop) { PartGui::ViewProviderPart::updateData(prop); - if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId()) { + if (prop->getTypeId() == Part::PropertyShapeHistory::getClassTypeId()) { + const std::vector& hist = static_cast + (prop)->getValues(); + if (hist.size() != 2) + return; Part::Boolean* objBool = dynamic_cast(getObject()); Part::Feature* objBase = dynamic_cast(objBool->Base.getValue()); Part::Feature* objTool = dynamic_cast(objBool->Tool.getValue()); - - BRepAlgoAPI_BooleanOperation* mkBool = objBool->getBooleanOperation(); - if (mkBool && objBase && objTool) { + if (objBase && objTool) { const TopoDS_Shape& baseShape = objBase->Shape.getValue(); const TopoDS_Shape& toolShape = objTool->Shape.getValue(); const TopoDS_Shape& boolShape = objBool->Shape.getValue(); - TopTools_IndexedMapOfShape M1, M2, M3; - TopExp::MapShapes(baseShape, TopAbs_FACE, M1); - TopExp::MapShapes(toolShape, TopAbs_FACE, M2); - TopExp::MapShapes(boolShape, TopAbs_FACE, M3); + TopTools_IndexedMapOfShape baseMap, toolMap, boolMap; + TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap); + TopExp::MapShapes(toolShape, TopAbs_FACE, toolMap); + TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); + Gui::ViewProvider* vpBase = Gui::Application::Instance->getViewProvider(objBase); Gui::ViewProvider* vpTool = Gui::Application::Instance->getViewProvider(objTool); std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); std::vector colTool = static_cast(vpTool)->DiffuseColor.getValues(); std::vector colBool; - colBool.resize(M3.Extent(), this->ShapeColor.getValue()); - bool applyColor=false; - if (colBase.size() == M1.Extent()) { - findFaces(mkBool, M1, M3, colBase, colBool); - applyColor = true; + colBool.resize(boolMap.Extent(), this->ShapeColor.getValue()); + + bool setColor=false; + if (colBase.size() == baseMap.Extent()) { + applyColor(hist[0], colBase, colBool); + setColor = true; } - if (colTool.size() == M2.Extent()) { - findFaces(mkBool, M2, M3, colTool, colBool); - applyColor = true; + if (colTool.size() == toolMap.Extent()) { + applyColor(hist[1], colTool, colBool); + setColor = true; } - if (applyColor) + if (setColor) this->DiffuseColor.setValues(colBool); } } @@ -176,6 +165,46 @@ QIcon ViewProviderMultiFuse::getIcon(void) const return Gui::BitmapFactory().pixmap("Part_Fuse"); } +void ViewProviderMultiFuse::updateData(const App::Property* prop) +{ + PartGui::ViewProviderPart::updateData(prop); + if (prop->getTypeId() == Part::PropertyShapeHistory::getClassTypeId()) { + const std::vector& hist = static_cast + (prop)->getValues(); + Part::MultiFuse* objBool = dynamic_cast(getObject()); + std::vector sources = objBool->Shapes.getValues(); + if (hist.size() != sources.size()) + return; + + const TopoDS_Shape& boolShape = objBool->Shape.getValue(); + TopTools_IndexedMapOfShape boolMap; + TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); + + std::vector colBool; + colBool.resize(boolMap.Extent(), this->ShapeColor.getValue()); + + bool setColor=false; + int index=0; + for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it, ++index) { + Part::Feature* objBase = dynamic_cast(*it); + const TopoDS_Shape& baseShape = objBase->Shape.getValue(); + + TopTools_IndexedMapOfShape baseMap; + TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap); + + Gui::ViewProvider* vpBase = Gui::Application::Instance->getViewProvider(objBase); + std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); + if (colBase.size() == baseMap.Extent()) { + applyColor(hist[index], colBase, colBool); + setColor = true; + } + } + + if (setColor) + this->DiffuseColor.setValues(colBool); + } +} + PROPERTY_SOURCE(PartGui::ViewProviderMultiCommon,PartGui::ViewProviderPart) @@ -196,3 +225,43 @@ QIcon ViewProviderMultiCommon::getIcon(void) const { return Gui::BitmapFactory().pixmap("Part_Common"); } + +void ViewProviderMultiCommon::updateData(const App::Property* prop) +{ + PartGui::ViewProviderPart::updateData(prop); + if (prop->getTypeId() == Part::PropertyShapeHistory::getClassTypeId()) { + const std::vector& hist = static_cast + (prop)->getValues(); + Part::MultiCommon* objBool = dynamic_cast(getObject()); + std::vector sources = objBool->Shapes.getValues(); + if (hist.size() != sources.size()) + return; + + const TopoDS_Shape& boolShape = objBool->Shape.getValue(); + TopTools_IndexedMapOfShape boolMap; + TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); + + std::vector colBool; + colBool.resize(boolMap.Extent(), this->ShapeColor.getValue()); + + bool setColor=false; + int index=0; + for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it, ++index) { + Part::Feature* objBase = dynamic_cast(*it); + const TopoDS_Shape& baseShape = objBase->Shape.getValue(); + + TopTools_IndexedMapOfShape baseMap; + TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap); + + Gui::ViewProvider* vpBase = Gui::Application::Instance->getViewProvider(objBase); + std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); + if (colBase.size() == baseMap.Extent()) { + applyColor(hist[index], colBase, colBool); + setColor = true; + } + } + + if (setColor) + this->DiffuseColor.setValues(colBool); + } +} diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.h b/src/Mod/Part/Gui/ViewProviderBoolean.h index 0a34127b16..29c5311092 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.h +++ b/src/Mod/Part/Gui/ViewProviderBoolean.h @@ -59,6 +59,7 @@ public: /// grouping handling std::vector claimChildren(void) const; QIcon getIcon(void) const; + void updateData(const App::Property*); }; /// ViewProvider for the MultiFuse feature @@ -75,6 +76,7 @@ public: /// grouping handling std::vector claimChildren(void) const; QIcon getIcon(void) const; + void updateData(const App::Property*); }; From 20fcef29c7fdb7e1f38543066586bd946e94acdb Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 31 May 2012 15:28:15 +0200 Subject: [PATCH 299/351] Keep faces colors on boolean operations --- src/Mod/Part/App/FeaturePartCommon.cpp | 47 ++++++++++++++++-------- src/Mod/Part/App/FeaturePartFuse.cpp | 14 ++++++- src/Mod/Part/App/PartFeature.cpp | 37 +++++++++++++++---- src/Mod/Part/App/PartFeature.h | 1 + src/Mod/Part/App/PropertyTopoShape.h | 8 ++-- src/Mod/Part/Gui/ViewProviderBoolean.cpp | 13 +------ 6 files changed, 79 insertions(+), 41 deletions(-) diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index ea4be0edd8..44c93a01c3 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -25,6 +25,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include #endif @@ -81,22 +82,38 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void) } if (s.size() >= 2) { - std::vector history; - TopoDS_Shape res = s.front(); - for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { - // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Common mkCommon(res, *it); - // Let's check if the fusion has been successful - if (!mkCommon.IsDone()) - throw Base::Exception("Intersection failed"); - res = mkCommon.Shape(); - history.push_back(buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape1())); - history.push_back(buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape2())); + try { + std::vector history; + TopoDS_Shape res = s.front(); + for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { + // Let's call algorithm computing a fuse operation: + BRepAlgoAPI_Common mkCommon(res, *it); + // Let's check if the fusion has been successful + if (!mkCommon.IsDone()) + throw Base::Exception("Intersection failed"); + res = mkCommon.Shape(); + + ShapeHistory hist1 = buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape1()); + ShapeHistory hist2 = buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape2()); + if (history.empty()) { + history.push_back(hist1); + history.push_back(hist2); + } + else { + for (std::vector::iterator jt = history.begin(); jt != history.end(); ++jt) + *jt = joinHistory(*jt, hist1); + history.push_back(hist2); + } + } + if (res.IsNull()) + throw Base::Exception("Resulting shape is invalid"); + this->Shape.setValue(res); + this->History.setValues(history); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); } - if (res.IsNull()) - throw Base::Exception("Resulting shape is invalid"); - this->Shape.setValue(res); - this->History.setValues(history); } else { throw Base::Exception("Not enough shape objects linked"); diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index 8493b7b88b..47efb7a445 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -91,8 +91,18 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void) if (!mkFuse.IsDone()) throw Base::Exception("Fusion failed"); res = mkFuse.Shape(); - history.push_back(buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape1())); - history.push_back(buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape2())); + + ShapeHistory hist1 = buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape1()); + ShapeHistory hist2 = buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape2()); + if (history.empty()) { + history.push_back(hist1); + history.push_back(hist2); + } + else { + for (std::vector::iterator jt = history.begin(); jt != history.end(); ++jt) + *jt = joinHistory(*jt, hist1); + history.push_back(hist2); + } } if (res.IsNull()) throw Base::Exception("Resulting shape is invalid"); diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index e71edcc7d9..ef43452df9 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -143,36 +143,36 @@ ShapeHistory Feature::buildHistory(BRepBuilderAPI_MakeShape& mkShape, TopAbs_Sha TopExp::MapShapes(oldS, type, oldM); for (int i=1; i<=oldM.Extent(); i++) { - bool modified=false, generated=false; + bool found = false; TopTools_ListIteratorOfListOfShape it; for (it.Initialize(mkShape.Modified(oldM(i))); it.More(); it.Next()) { - modified = true; + found = true; for (int j=1; j<=newM.Extent(); j++) { if (newM(j).IsPartner(it.Value())) { - history.modified[i-1].push_back(j-1); + history.shapeMap[i-1].push_back(j-1); break; } } } for (it.Initialize(mkShape.Generated(oldM(i))); it.More(); it.Next()) { - generated = true; + found = true; for (int j=1; j<=newM.Extent(); j++) { if (newM(j).IsPartner(it.Value())) { - history.generated[i-1].push_back(j-1); + history.shapeMap[i-1].push_back(j-1); break; } } } - if (!modified && !generated) { + if (!found) { if (mkShape.IsDeleted(oldM(i))) { - history.deleted.insert(i-1); + history.shapeMap[i-1] = std::vector(); } else { for (int j=1; j<=newM.Extent(); j++) { if (newM(j).IsPartner(oldM(i))) { - history.accepted[i-1] = j-1; + history.shapeMap[i-1].push_back(j-1); break; } } @@ -183,6 +183,27 @@ ShapeHistory Feature::buildHistory(BRepBuilderAPI_MakeShape& mkShape, TopAbs_Sha return history; } +ShapeHistory Feature::joinHistory(const ShapeHistory& oldH, const ShapeHistory& newH) +{ + ShapeHistory join; + join.type = oldH.type; + + for (ShapeHistory::MapList::const_iterator it = oldH.shapeMap.begin(); it != oldH.shapeMap.end(); ++it) { + int old_shape_index = it->first; + if (it->second.empty()) + join.shapeMap[old_shape_index] = ShapeHistory::List(); + for (ShapeHistory::List::const_iterator jt = it->second.begin(); jt != it->second.end(); ++jt) { + ShapeHistory::MapList::const_iterator kt = newH.shapeMap.find(*jt); + if (kt != newH.shapeMap.end()) { + ShapeHistory::List& ary = join.shapeMap[old_shape_index]; + ary.insert(ary.end(), kt->second.begin(), kt->second.end()); + } + } + } + + return join; +} + /// returns the type name of the ViewProvider const char* Feature::getViewProviderName(void) const { return "PartGui::ViewProviderPart"; diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index 159f0473e1..689736a420 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -68,6 +68,7 @@ protected: TopLoc_Location getLocation() const; ShapeHistory buildHistory(BRepBuilderAPI_MakeShape&, TopAbs_ShapeEnum type, const TopoDS_Shape& newS, const TopoDS_Shape& oldS); + ShapeHistory joinHistory(const ShapeHistory&, const ShapeHistory&); }; class FilletBase : public Part::Feature diff --git a/src/Mod/Part/App/PropertyTopoShape.h b/src/Mod/Part/App/PropertyTopoShape.h index 190a82d2a6..a75c85ccd0 100644 --- a/src/Mod/Part/App/PropertyTopoShape.h +++ b/src/Mod/Part/App/PropertyTopoShape.h @@ -99,11 +99,11 @@ private: }; struct PartExport ShapeHistory { + typedef std::map > MapList; + typedef std::vector List; + TopAbs_ShapeEnum type; - std::map > modified; - std::map > generated; - std::map accepted; - std::set deleted; + MapList shapeMap; }; class PartExport PropertyShapeHistory : public App::PropertyLists diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.cpp b/src/Mod/Part/Gui/ViewProviderBoolean.cpp index 46c85bb658..22a9c8a4ea 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/Part/Gui/ViewProviderBoolean.cpp @@ -83,23 +83,12 @@ void applyColor(const Part::ShapeHistory& hist, { std::map >::const_iterator jt; // apply color from modified faces - for (jt = hist.modified.begin(); jt != hist.modified.end(); ++jt) { + for (jt = hist.shapeMap.begin(); jt != hist.shapeMap.end(); ++jt) { std::vector::const_iterator kt; for (kt = jt->second.begin(); kt != jt->second.end(); ++kt) { colBool[*kt] = colBase[jt->first]; } } - // apply color from generated faces - for (jt = hist.generated.begin(); jt != hist.generated.end(); ++jt) { - std::vector::const_iterator kt; - for (kt = jt->second.begin(); kt != jt->second.end(); ++kt) { - colBool[*kt] = colBase[jt->first]; - } - } - // apply data from accepted faces - for (std::map::const_iterator kt = hist.accepted.begin(); kt != hist.accepted.end(); ++kt) { - colBool[kt->second] = colBase[kt->first]; - } } void ViewProviderBoolean::updateData(const App::Property* prop) From f2b4f5c18e23b034c1d1cbb9322e7aa0852647c8 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 31 May 2012 23:44:50 +0200 Subject: [PATCH 300/351] Keep faces colors on boolean operations --- src/Mod/Part/Gui/ViewProviderBoolean.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.cpp b/src/Mod/Part/Gui/ViewProviderBoolean.cpp index 22a9c8a4ea..d73afe2966 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/Part/Gui/ViewProviderBoolean.cpp @@ -124,10 +124,20 @@ void ViewProviderBoolean::updateData(const App::Property* prop) applyColor(hist[0], colBase, colBool); setColor = true; } + else if (!colBase.empty() && colBase[0] != this->ShapeColor.getValue()) { + colBase.resize(baseMap.Extent(), colBase[0]); + applyColor(hist[0], colBase, colBool); + setColor = true; + } if (colTool.size() == toolMap.Extent()) { applyColor(hist[1], colTool, colBool); setColor = true; } + else if (!colTool.empty() && colTool[0] != this->ShapeColor.getValue()) { + colTool.resize(toolMap.Extent(), colTool[0]); + applyColor(hist[1], colTool, colBool); + setColor = true; + } if (setColor) this->DiffuseColor.setValues(colBool); } @@ -187,6 +197,11 @@ void ViewProviderMultiFuse::updateData(const App::Property* prop) applyColor(hist[index], colBase, colBool); setColor = true; } + else if (!colBase.empty() && colBase[0] != this->ShapeColor.getValue()) { + colBase.resize(baseMap.Extent(), colBase[0]); + applyColor(hist[index], colBase, colBool); + setColor = true; + } } if (setColor) @@ -248,6 +263,11 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop) applyColor(hist[index], colBase, colBool); setColor = true; } + else if (!colBase.empty() && colBase[0] != this->ShapeColor.getValue()) { + colBase.resize(baseMap.Extent(), colBase[0]); + applyColor(hist[index], colBase, colBool); + setColor = true; + } } if (setColor) From 4c566a6113c2c2c3326d2722604039f6d8bb4b3e Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 1 Jun 2012 16:44:57 +0200 Subject: [PATCH 301/351] Make a convenient function to convert between gp_Trsf and Base::Matrix4D --- src/Mod/Part/App/TopoShape.cpp | 38 ++++++++++++++++++++-------------- src/Mod/Part/App/TopoShape.h | 2 ++ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index fd90af18f5..9bf4870744 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -433,25 +433,19 @@ void TopoShape::operator = (const TopoShape& sh) } } -void TopoShape::setTransform(const Base::Matrix4D& rclTrf) +void TopoShape::convertTogpTrsf(const Base::Matrix4D& mtrx, gp_Trsf& trsf) { - gp_Trsf mov; - mov.SetValues(rclTrf[0][0],rclTrf[0][1],rclTrf[0][2],rclTrf[0][3], - rclTrf[1][0],rclTrf[1][1],rclTrf[1][2],rclTrf[1][3], - rclTrf[2][0],rclTrf[2][1],rclTrf[2][2],rclTrf[2][3], - 0.00001,0.00001); - TopLoc_Location loc(mov); - _Shape.Location(loc); + trsf.SetValues(mtrx[0][0],mtrx[0][1],mtrx[0][2],mtrx[0][3], + mtrx[1][0],mtrx[1][1],mtrx[1][2],mtrx[1][3], + mtrx[2][0],mtrx[2][1],mtrx[2][2],mtrx[2][3], + 0.00001,0.00001); } -Base::Matrix4D TopoShape::getTransform(void) const +void TopoShape::convertToMatrix(const gp_Trsf& trsf, Base::Matrix4D& mtrx) { - Base::Matrix4D mtrx; - gp_Trsf Trf = _Shape.Location().Transformation(); - - gp_Mat m = Trf._CSFDB_Getgp_Trsfmatrix(); - gp_XYZ p = Trf._CSFDB_Getgp_Trsfloc(); - Standard_Real scale = Trf._CSFDB_Getgp_Trsfscale(); + gp_Mat m = trsf._CSFDB_Getgp_Trsfmatrix(); + gp_XYZ p = trsf._CSFDB_Getgp_Trsfloc(); + Standard_Real scale = trsf._CSFDB_Getgp_Trsfscale(); // set Rotation matrix mtrx[0][0] = scale * m._CSFDB_Getgp_Matmatrix(0,0); @@ -470,7 +464,21 @@ Base::Matrix4D TopoShape::getTransform(void) const mtrx[0][3] = p._CSFDB_Getgp_XYZx(); mtrx[1][3] = p._CSFDB_Getgp_XYZy(); mtrx[2][3] = p._CSFDB_Getgp_XYZz(); +} +void TopoShape::setTransform(const Base::Matrix4D& rclTrf) +{ + gp_Trsf mov; + convertTogpTrsf(rclTrf, mov); + TopLoc_Location loc(mov); + _Shape.Location(loc); +} + +Base::Matrix4D TopoShape::getTransform(void) const +{ + Base::Matrix4D mtrx; + gp_Trsf Trf = _Shape.Location().Transformation(); + convertToMatrix(Trf, mtrx); return mtrx; } diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 1de76b1cad..1d16b9e073 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -73,6 +73,8 @@ public: Base::Matrix4D getTransform(void) const; /// Bound box from the CasCade shape Base::BoundBox3d getBoundBox(void)const; + static void convertTogpTrsf(const Base::Matrix4D& mtrx, gp_Trsf& trsf); + static void convertToMatrix(const gp_Trsf& trsf, Base::Matrix4D& mtrx); //@} /** @name Subelement management */ From fbd3556aaf64e13ee2975a08278bae52a72e071b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 1 Jun 2012 15:19:21 -0300 Subject: [PATCH 302/351] Draft: Added Draft_ToggleGrid() command to toggle the Draft grid --- src/Mod/Arch/InitGui.py | 5 ++-- src/Mod/Draft/DraftSnap.py | 54 ++++++++++++++++++++----------------- src/Mod/Draft/DraftTools.py | 23 +++++++++++++++- src/Mod/Draft/InitGui.py | 6 ++--- 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 1de87ed470..32e9d70db5 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -69,8 +69,9 @@ class ArchWorkbench(Workbench): "Draft_Offset","Draft_Upgrade", "Draft_Downgrade","Draft_Trimex"] self.draftcontexttools = ["Draft_ApplyStyle","Draft_ToggleDisplayMode", - "Draft_AddToGroup","Draft_SelectGroup", - "Draft_SelectPlane","Draft_ToggleSnap"] + "Draft_AddToGroup","Draft_SelectGroup", + "Draft_SelectPlane","Draft_ToggleSnap", + "Draft_ShowSnapBar","Draft_ToggleGrid"] self.meshtools = ["Arch_SplitMesh","Arch_MeshToShape", "Arch_SelectNonSolidMeshes","Arch_RemoveShape"] self.appendToolbar(str(DraftTools.translate("arch","Arch tools")),self.archtools) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 1479a65688..183f20a52d 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -73,6 +73,7 @@ class Snapper: self.snapInfo = None self.lastSnappedObject = None self.active = True + self.forceGridOff = False self.trackers = [[],[],[],[]] # view, grid, snap, extline self.polarAngles = [90,45] @@ -166,7 +167,7 @@ class Snapper: self.radius = self.getScreenDist(Draft.getParam("snapRange"),screenpos) # set the grid - if self.grid and Draft.getParam("grid"): + if self.grid and Draft.getParam("grid") and (not self.forceGridOff): self.grid.set() # activate snap @@ -243,18 +244,20 @@ class Snapper: if (not self.maxEdges) or (len(obj.Edges) <= self.maxEdges): if "Edge" in comp: # we are snapping to an edge - edge = obj.Shape.Edges[int(comp[4:])-1] - snaps.extend(self.snapToEndpoints(edge)) - snaps.extend(self.snapToMidpoint(edge)) - snaps.extend(self.snapToPerpendicular(edge,lastpoint)) - #snaps.extend(self.snapToOrtho(edge,lastpoint,constrain)) # now part of snapToPolar - snaps.extend(self.snapToIntersection(edge)) - snaps.extend(self.snapToElines(edge,eline)) + en = int(comp[4:])-1 + if len(obj.Shape.Edges) > en: + edge = obj.Shape.Edges[en] + snaps.extend(self.snapToEndpoints(edge)) + snaps.extend(self.snapToMidpoint(edge)) + snaps.extend(self.snapToPerpendicular(edge,lastpoint)) + #snaps.extend(self.snapToOrtho(edge,lastpoint,constrain)) # now part of snapToPolar + snaps.extend(self.snapToIntersection(edge)) + snaps.extend(self.snapToElines(edge,eline)) - if isinstance (edge.Curve,Part.Circle): - # the edge is an arc, we have extra options - snaps.extend(self.snapToAngles(edge)) - snaps.extend(self.snapToCenter(edge)) + if isinstance (edge.Curve,Part.Circle): + # the edge is an arc, we have extra options + snaps.extend(self.snapToAngles(edge)) + snaps.extend(self.snapToCenter(edge)) elif "Vertex" in comp: # directly snapped to a vertex @@ -418,18 +421,19 @@ class Snapper: def snapToGrid(self,point): "returns a grid snap point if available" if self.grid: - if self.isEnabled("grid"): - np = self.grid.getClosestNode(point) - if np: - if self.radius != 0: - dv = point.sub(np) - if dv.Length <= self.radius: - if self.tracker: - self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['grid']) - self.tracker.on() - self.setCursor('grid') - return np + if self.grid.Visible: + if self.isEnabled("grid"): + np = self.grid.getClosestNode(point) + if np: + if self.radius != 0: + dv = point.sub(np) + if dv.Length <= self.radius: + if self.tracker: + self.tracker.setCoords(np) + self.tracker.setMarker(self.mk['grid']) + self.tracker.on() + self.setCursor('grid') + return np return point def snapToEndpoints(self,shape): @@ -889,7 +893,7 @@ class Snapper: if self.grid: if self.grid.Visible: self.grid.set() - + if not hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper = Snapper() if not hasattr(FreeCAD,"DraftWorkingPlane"): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index b37e07c00f..559e75e268 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -3828,7 +3828,27 @@ class Draft_Clone(): return True else: return False - + + +class ToggleGrid(): + "The Draft ToggleGrid command definition" + + def GetResources(self): + return {'Pixmap' : 'Snap_Grid', + 'Accel' : "G,R", + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleGrid", "Toggle Grid"), + 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ToggleGrid", "Toggles the Draft gid on/off")} + + def Activated(self): + if hasattr(FreeCADGui,"Snapper"): + if FreeCADGui.Snapper.grid: + if FreeCADGui.Snapper.grid.Visible: + FreeCADGui.Snapper.grid.off() + FreeCADGui.Snapper.forceGridOff=True + else: + FreeCADGui.Snapper.grid.on() + FreeCADGui.Snapper.forceGridOff=False + #--------------------------------------------------------------------------- # Adds the icons & commands to the FreeCAD command manager, and sets defaults #--------------------------------------------------------------------------- @@ -3876,6 +3896,7 @@ FreeCADGui.addCommand('Draft_SelectGroup',SelectGroup()) FreeCADGui.addCommand('Draft_Shape2DView',Shape2DView()) FreeCADGui.addCommand('Draft_ToggleSnap',ToggleSnap()) FreeCADGui.addCommand('Draft_ShowSnapBar',ShowSnapBar()) +FreeCADGui.addCommand('Draft_ToggleGrid',ToggleGrid()) # a global place to look for active draft Command FreeCAD.activeDraftCommand = None diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 84d0b9b868..3e2bd5696d 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -192,12 +192,12 @@ class DraftWorkbench (Workbench): "Draft_Clone"] self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup", "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap", - "Draft_ShowSnapBar"] + "Draft_ShowSnapBar","Draft_ToggleGrid"] self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"] self.appendToolbar(str(DraftTools.translate("draft","Draft creation tools")),self.cmdList) self.appendToolbar(str(DraftTools.translate("draft","Draft modification tools")),self.modList) self.appendMenu(str(DraftTools.translate("draft","&Draft")),self.cmdList+self.modList) - self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Display options"))],self.treecmdList) + self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Context tools"))],self.treecmdList) self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Wire tools"))],self.lineList) def Activated(self): @@ -211,7 +211,7 @@ class DraftWorkbench (Workbench): if (FreeCAD.activeDraftCommand == None): if (FreeCADGui.Selection.getSelection()): self.appendContextMenu("Draft",self.cmdList+self.modList) - self.appendContextMenu("Display options",self.treecmdList) + self.appendContextMenu("Draft context tools",self.treecmdList) else: self.appendContextMenu("Draft",self.cmdList) else: From 0e8648126c7954dd6fea6329c641c705a01c880e Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 1 Jun 2012 16:26:31 -0300 Subject: [PATCH 303/351] Arch: Small fix in menu name --- src/Mod/Arch/InitGui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 32e9d70db5..4c5384ff08 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -76,7 +76,7 @@ class ArchWorkbench(Workbench): "Arch_SelectNonSolidMeshes","Arch_RemoveShape"] self.appendToolbar(str(DraftTools.translate("arch","Arch tools")),self.archtools) self.appendToolbar(str(DraftTools.translate("arch","Draft tools")),self.drafttools) - self.appendMenu([str(DraftTools.translate("arch","&Architecture")),str(DraftTools.translate("arch","Tools"))],self.meshtools) + self.appendMenu([str(DraftTools.translate("arch","&Architecture")),str(DraftTools.translate("arch","Conversion Tools"))],self.meshtools) self.appendMenu(str(DraftTools.translate("arch","&Architecture")),self.archtools) self.appendMenu(str(DraftTools.translate("arch","&Draft")),self.drafttools+self.draftcontexttools) FreeCADGui.addIconPath(":/icons") From 1b8998f77da1f237e310c6beef9ab246f99b3a21 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 2 Jun 2012 18:52:47 +0200 Subject: [PATCH 304/351] 0000631: Support of more sophisticated switch to configure with cmake --- CMakeLists.txt | 13 ++++++++++++- src/3rdParty/CMakeLists.txt | 4 ++-- src/Base/CMakeLists.txt | 15 +++++---------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dda4867a28..2d2eaf6849 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,10 @@ if(CMAKE_COMPILER_IS_GNUCXX) add_definitions(-Wno-write-strings) add_definitions(-Wno-deprecated) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + # get linker errors as soon as possible and not at runtime e.g. for modules + if(UNIX) + SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") + endif(UNIX) endif(CMAKE_COMPILER_IS_GNUCXX) @@ -98,7 +102,14 @@ OPTION(FREECAD_BUILD_FEM "Build the FreeCAD FEM module, be aware, unfinished cod OPTION(FREECAD_BUILD_SANDBOX "Build the FreeCAD Sandbox module which is only for testing purposes" OFF) OPTION(FREECAD_BUILD_TEMPLATE "Build the FreeCAD template module which is only for testing purposes" OFF) OPTION(FREECAD_BUILD_DEBIAN "Prepare for a build of a Debian package" OFF) -OPTION(USE_EXTERNAL_ZIPIOS "Use system installed zipios++ instead of the bundled." OFF) +OPTION(FREECAD_USE_EXTERNAL_ZIPIOS "Use system installed zipios++ instead of the bundled." OFF) +OPTION(FREECAD_USE_EXTERNAL_PIVY "Use system installed python-pivy instead of the bundled." OFF) + +# if this is set override some options +if (FREECAD_BUILD_DEBIAN) + set(FREECAD_USE_EXTERNAL_ZIPIOS ON) + set(FREECAD_USE_EXTERNAL_PIVY ON) +endif (FREECAD_BUILD_DEBIAN) # ============================================================================== diff --git a/src/3rdParty/CMakeLists.txt b/src/3rdParty/CMakeLists.txt index 5309c7a1fa..456c1f3253 100644 --- a/src/3rdParty/CMakeLists.txt +++ b/src/3rdParty/CMakeLists.txt @@ -20,7 +20,7 @@ elseif(FREECAD_BUILD_GUI AND FREECAD_LIBPACK_CHECKFILE7X) #endif(MINGW) # applies for Unix, MinGW and Windows with custom LibPack elseif(FREECAD_BUILD_GUI) - if (NOT FREECAD_BUILD_DEBIAN) + if (NOT FREECAD_USE_EXTERNAL_PIVY) find_path(COIN_VERSION3 Inventor/scxml/ScXML.h ${COIN3D_INCLUDE_DIR}) if (COIN_VERSION3) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy-0.5) @@ -31,7 +31,7 @@ elseif(FREECAD_BUILD_GUI) add_subdirectory(Pivy) endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy) endif(COIN_VERSION3) - endif (NOT FREECAD_BUILD_DEBIAN) + endif (NOT FREECAD_USE_EXTERNAL_PIVY) endif(FREECAD_BUILD_GUI AND FREECAD_LIBPACK_CHECKFILE6X) # For Windows we have all stuff in the LibPack diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt index fdfb8a2b10..3cab433544 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -68,7 +68,7 @@ if(SWIG_FOUND) add_definitions(-DHAVE_SWIG=1) endif(SWIG_FOUND) -if (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++ AND NOT FREECAD_BUILD_DEBIAN) +if (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++ AND NOT FREECAD_USE_EXTERNAL_ZIPIOS) SET(zipios_SRCS ../zipios++/backbuffer.h ../zipios++/basicentry.cpp @@ -122,12 +122,7 @@ SET(zipios_SRCS ../zipios++/zipoutputstream.h ) SOURCE_GROUP("zipios" FILES ${zipios_SRCS}) -else (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++ AND NOT FREECAD_BUILD_DEBIAN) - set(FreeCADBase_LIBS - ${FreeCADBase_LIBS} - -lzipios - ) -endif (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++ AND NOT FREECAD_BUILD_DEBIAN) +endif () SET(pycxx_SRCS ../CXX/Config.hxx @@ -293,7 +288,7 @@ SET(FreeCADBase_SRCS ) # Use external zipios++ if specified. -if(USE_EXTERNAL_ZIPIOS) +if(FREECAD_USE_EXTERNAL_ZIPIOS) find_library(ZIPIOS_LIBRARY zipios) find_path(ZIPIOS_INCLUDES zipios++/zipios-config.h) if(ZIPIOS_LIBRARY) @@ -308,9 +303,9 @@ if(USE_EXTERNAL_ZIPIOS) else() message(FATAL_ERROR "Using external zipios++ was specified but was not found.") endif() -else(USE_EXTERNAL_ZIPIOS) +else(FREECAD_USE_EXTERNAL_ZIPIOS) list(APPEND FreeCADBase_SRCS ${zipios_SRCS}) -endif(USE_EXTERNAL_ZIPIOS) +endif(FREECAD_USE_EXTERNAL_ZIPIOS) if(MSVC) From 495c4016549f1af1bc7f778849dd5c65fc27a74a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 2 Jun 2012 14:12:43 -0300 Subject: [PATCH 305/351] Arch: Windows are now autosubtracted from support walls on creation --- src/Mod/Arch/ArchWindow.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 40b038aed0..de7df1b6e1 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -88,11 +88,27 @@ class _CommandWindow: def Activated(self): sel = FreeCADGui.Selection.getSelection() - FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Window"))) - FreeCADGui.doCommand("import Arch") - for obj in sel: - FreeCADGui.doCommand("Arch.makeWindow(FreeCAD.ActiveDocument."+obj.Name+")") - FreeCAD.ActiveDocument.commitTransaction() + if sel: + if Draft.getType(sel[0]) == "Wall": + FreeCADGui.activateWorkbench("SketcherWorkbench") + FreeCADGui.runCommand("Sketcher_NewSketch") + else: + FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Window"))) + FreeCADGui.doCommand("import Arch") + for obj in sel: + FreeCADGui.doCommand("Arch.makeWindow(FreeCAD.ActiveDocument."+obj.Name+")") + if hasattr(obj,"Support"): + if obj.Support: + if isinstance(obj.Support,tuple): + s = obj.Support[0] + else: + s = obj.Support + w = FreeCAD.ActiveDocument.Objects[-1] # last created object + FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+w.Name+",host=FreeCAD.ActiveDocument."+s.Name+")") + elif Draft.isClone(w,"Window"): + if w.Objects[0].Inlist: + FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+w.Name+",host=FreeCAD.ActiveDocument."+w.Objects[0].Inlist[0].Name+")") + FreeCAD.ActiveDocument.commitTransaction() class _Window(ArchComponent.Component): "The Window object" From 3858f8a2684a19487c131ac1170334fe526e8b09 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Jun 2012 01:26:55 +0200 Subject: [PATCH 306/351] Start implementing ActionSelector class --- src/3rdParty/Pivy-0.5/CMakeLists.txt | 2 +- src/Gui/Widgets.cpp | 111 +++++++++++++++++++++++---- src/Gui/Widgets.h | 24 ++++++ 3 files changed, 120 insertions(+), 17 deletions(-) diff --git a/src/3rdParty/Pivy-0.5/CMakeLists.txt b/src/3rdParty/Pivy-0.5/CMakeLists.txt index 3b71e24a17..fc810fb790 100644 --- a/src/3rdParty/Pivy-0.5/CMakeLists.txt +++ b/src/3rdParty/Pivy-0.5/CMakeLists.txt @@ -88,7 +88,7 @@ if(MSVC) debug ${PYTHON_DEBUG_LIBRARY} optimized ${PYTHON_LIBRARY}) else(MSVC) - set(CoinPy_LIBS + set(SoQtPy_LIBS ${SOQT_LIBRARIES} ${COIN3D_LIBRARY} ${PYTHON_LIBRARY}) diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp index 1db07b7cd9..714774d061 100644 --- a/src/Gui/Widgets.cpp +++ b/src/Gui/Widgets.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +# include # include # include # include @@ -102,6 +102,85 @@ void CommandIconView::onSelectionChanged(QListWidgetItem * item, QListWidgetItem emitSelectionChanged(item->toolTip()); } +// ------------------------------------------------------------------------------ + +ActionSelector::ActionSelector(QWidget* parent) + : QWidget(parent) +{ + moveActionRightButton = new QPushButton(this); + moveActionRightButton->setMinimumSize(QSize(30, 30)); + QIcon icon; + icon.addFile(QString::fromUtf8(":/icons/button_right.xpm"), QSize(), QIcon::Normal, QIcon::Off); + moveActionRightButton->setIcon(icon); + gridLayout->addWidget(moveActionRightButton, 1, 1, 1, 1); + + spacerItem = new QSpacerItem(33, 57, QSizePolicy::Minimum, QSizePolicy::Expanding); + gridLayout->addItem(spacerItem, 5, 1, 1, 1); + spacerItem1 = new QSpacerItem(33, 58, QSizePolicy::Minimum, QSizePolicy::Expanding); + gridLayout->addItem(spacerItem1, 0, 1, 1, 1); + + moveActionLeftButton = new QPushButton(this); + moveActionLeftButton->setMinimumSize(QSize(30, 30)); + QIcon icon1; + icon1.addFile(QString::fromUtf8(":/icons/button_left.xpm"), QSize(), QIcon::Normal, QIcon::Off); + moveActionLeftButton->setIcon(icon1); + moveActionLeftButton->setAutoDefault(true); + moveActionLeftButton->setDefault(false); + + gridLayout->addWidget(moveActionLeftButton, 2, 1, 1, 1); + + moveActionDownButton = new QPushButton(this); + moveActionDownButton->setMinimumSize(QSize(30, 30)); + QIcon icon2; + icon2.addFile(QString::fromUtf8(":/icons/button_down.xpm"), QSize(), QIcon::Normal, QIcon::Off); + moveActionDownButton->setIcon(icon2); + moveActionDownButton->setAutoDefault(true); + + gridLayout->addWidget(moveActionDownButton, 4, 1, 1, 1); + + moveActionUpButton = new QPushButton(this); + moveActionUpButton->setMinimumSize(QSize(30, 30)); + QIcon icon3; + icon3.addFile(QString::fromUtf8(":/icons/button_up.xpm"), QSize(), QIcon::Normal, QIcon::Off); + moveActionUpButton->setIcon(icon3); + + gridLayout->addWidget(moveActionUpButton, 3, 1, 1, 1); + + vboxLayout = new QVBoxLayout(); + vboxLayout->setContentsMargins(0, 0, 0, 0); + label_2 = new QLabel(this); + vboxLayout->addWidget(label_2); + + avalableTreeWidget = new QTreeWidget(this); + avalableTreeWidget->setRootIsDecorated(false); + avalableTreeWidget->setColumnCount(0); + vboxLayout->addWidget(avalableTreeWidget); + + gridLayout->addLayout(vboxLayout, 0, 0, 6, 1); + + vboxLayout1 = new QVBoxLayout(); + vboxLayout1->setContentsMargins(0, 0, 0, 0); + label = new QLabel(this); + vboxLayout1->addWidget(label); + + selectedTreeWidget = new QTreeWidget(this); + vboxLayout1->addWidget(selectedTreeWidget); + + gridLayout->addLayout(vboxLayout1, 0, 2, 6, 1); + + moveActionRightButton->setText(QString()); + moveActionLeftButton->setText(QString()); + moveActionDownButton->setText(QString()); + moveActionUpButton->setText(QString()); + label_2->setText(QApplication::translate("Gui::ActionSelector", "Available:", 0, QApplication::UnicodeUTF8)); + label->setText(QApplication::translate("Gui::ActionSelector", "Selected:", 0, QApplication::UnicodeUTF8)); +} + +ActionSelector::~ActionSelector() +{ +} + + // ------------------------------------------------------------------------------ /* TRANSLATOR Gui::AccelLineEdit */ @@ -628,10 +707,10 @@ StatusWidget::StatusWidget(QWidget* parent) label = new QLabel(this); label->setAlignment(Qt::AlignCenter); - QGridLayout* gridLayout = new QGridLayout(this); - gridLayout->setSpacing(6); - gridLayout->setMargin(9); - gridLayout->addWidget(label, 0, 0, 1, 1); + QGridLayout* gridLayout = new QGridLayout(this); + gridLayout->setSpacing(6); + gridLayout->setMargin(9); + gridLayout->addWidget(label, 0, 0, 1, 1); } StatusWidget::~StatusWidget() @@ -775,20 +854,20 @@ void LabelEditor::setText(const QString& s) void LabelEditor::changeText() { QDialog dlg(this); - QVBoxLayout* hboxLayout = new QVBoxLayout(&dlg); - QDialogButtonBox* buttonBox = new QDialogButtonBox(&dlg); - buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Close); + QVBoxLayout* hboxLayout = new QVBoxLayout(&dlg); + QDialogButtonBox* buttonBox = new QDialogButtonBox(&dlg); + buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Close); QPlainTextEdit *edit = new QPlainTextEdit(&dlg); edit->setPlainText(this->lineEdit->text()); - - hboxLayout->addWidget(edit); - hboxLayout->addWidget(buttonBox); - connect(buttonBox, SIGNAL(accepted()), &dlg, SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), &dlg, SLOT(reject())); - if (dlg.exec() == QDialog::Accepted) { - this->lineEdit->setText(edit->toPlainText()); - } + + hboxLayout->addWidget(edit); + hboxLayout->addWidget(buttonBox); + connect(buttonBox, SIGNAL(accepted()), &dlg, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), &dlg, SLOT(reject())); + if (dlg.exec() == QDialog::Accepted) { + this->lineEdit->setText(edit->toPlainText()); + } } /** diff --git a/src/Gui/Widgets.h b/src/Gui/Widgets.h index 16baf74b7a..a13e407c6e 100644 --- a/src/Gui/Widgets.h +++ b/src/Gui/Widgets.h @@ -63,6 +63,30 @@ Q_SIGNALS: // ------------------------------------------------------------------------------ +class ActionSelector : public QWidget +{ +public: + ActionSelector(QWidget* parent=0); + ~ActionSelector(); + +private: + QGridLayout *gridLayout; + QPushButton *moveActionRightButton; + QSpacerItem *spacerItem; + QSpacerItem *spacerItem1; + QPushButton *moveActionLeftButton; + QPushButton *moveActionDownButton; + QPushButton *moveActionUpButton; + QVBoxLayout *vboxLayout; + QLabel *label_2; + QTreeWidget *avalableTreeWidget; + QVBoxLayout *vboxLayout1; + QLabel *label; + QTreeWidget *selectedTreeWidget; +}; + +// ------------------------------------------------------------------------------ + /** * The AccelLineEdit class provides a lineedit to specfify shortcuts. * \author Werner Mayer From 5174778cc01c99697e1cb85a62239de89362151c Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Jun 2012 12:11:38 +0200 Subject: [PATCH 307/351] 0000719: Implement a KActionSelector-like widget --- src/Gui/Widgets.cpp | 225 +++++++++++++++---- src/Gui/Widgets.h | 43 +++- src/Tools/plugins/widget/FreeCAD_widgets.sln | 20 -- src/Tools/plugins/widget/customwidgets.cpp | 88 ++++++++ src/Tools/plugins/widget/customwidgets.h | 27 +++ src/Tools/plugins/widget/plugin.cpp | 74 ++++++ 6 files changed, 407 insertions(+), 70 deletions(-) delete mode 100644 src/Tools/plugins/widget/FreeCAD_widgets.sln diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp index 714774d061..98a87442c5 100644 --- a/src/Gui/Widgets.cpp +++ b/src/Gui/Widgets.cpp @@ -104,82 +104,229 @@ void CommandIconView::onSelectionChanged(QListWidgetItem * item, QListWidgetItem // ------------------------------------------------------------------------------ +/* TRANSLATOR Gui::ActionSelector */ + ActionSelector::ActionSelector(QWidget* parent) : QWidget(parent) { - moveActionRightButton = new QPushButton(this); - moveActionRightButton->setMinimumSize(QSize(30, 30)); + addButton = new QPushButton(this); + addButton->setMinimumSize(QSize(30, 30)); QIcon icon; icon.addFile(QString::fromUtf8(":/icons/button_right.xpm"), QSize(), QIcon::Normal, QIcon::Off); - moveActionRightButton->setIcon(icon); - gridLayout->addWidget(moveActionRightButton, 1, 1, 1, 1); + addButton->setIcon(icon); + gridLayout = new QGridLayout(this); + gridLayout->addWidget(addButton, 1, 1, 1, 1); spacerItem = new QSpacerItem(33, 57, QSizePolicy::Minimum, QSizePolicy::Expanding); gridLayout->addItem(spacerItem, 5, 1, 1, 1); spacerItem1 = new QSpacerItem(33, 58, QSizePolicy::Minimum, QSizePolicy::Expanding); gridLayout->addItem(spacerItem1, 0, 1, 1, 1); - moveActionLeftButton = new QPushButton(this); - moveActionLeftButton->setMinimumSize(QSize(30, 30)); + removeButton = new QPushButton(this); + removeButton->setMinimumSize(QSize(30, 30)); QIcon icon1; icon1.addFile(QString::fromUtf8(":/icons/button_left.xpm"), QSize(), QIcon::Normal, QIcon::Off); - moveActionLeftButton->setIcon(icon1); - moveActionLeftButton->setAutoDefault(true); - moveActionLeftButton->setDefault(false); + removeButton->setIcon(icon1); + removeButton->setAutoDefault(true); + removeButton->setDefault(false); - gridLayout->addWidget(moveActionLeftButton, 2, 1, 1, 1); + gridLayout->addWidget(removeButton, 2, 1, 1, 1); - moveActionDownButton = new QPushButton(this); - moveActionDownButton->setMinimumSize(QSize(30, 30)); - QIcon icon2; - icon2.addFile(QString::fromUtf8(":/icons/button_down.xpm"), QSize(), QIcon::Normal, QIcon::Off); - moveActionDownButton->setIcon(icon2); - moveActionDownButton->setAutoDefault(true); - - gridLayout->addWidget(moveActionDownButton, 4, 1, 1, 1); - - moveActionUpButton = new QPushButton(this); - moveActionUpButton->setMinimumSize(QSize(30, 30)); + upButton = new QPushButton(this); + upButton->setMinimumSize(QSize(30, 30)); QIcon icon3; icon3.addFile(QString::fromUtf8(":/icons/button_up.xpm"), QSize(), QIcon::Normal, QIcon::Off); - moveActionUpButton->setIcon(icon3); + upButton->setIcon(icon3); - gridLayout->addWidget(moveActionUpButton, 3, 1, 1, 1); + gridLayout->addWidget(upButton, 3, 1, 1, 1); + + downButton = new QPushButton(this); + downButton->setMinimumSize(QSize(30, 30)); + QIcon icon2; + icon2.addFile(QString::fromUtf8(":/icons/button_down.xpm"), QSize(), QIcon::Normal, QIcon::Off); + downButton->setIcon(icon2); + downButton->setAutoDefault(true); + + gridLayout->addWidget(downButton, 4, 1, 1, 1); vboxLayout = new QVBoxLayout(); vboxLayout->setContentsMargins(0, 0, 0, 0); - label_2 = new QLabel(this); - vboxLayout->addWidget(label_2); + labelAvailable = new QLabel(this); + vboxLayout->addWidget(labelAvailable); - avalableTreeWidget = new QTreeWidget(this); - avalableTreeWidget->setRootIsDecorated(false); - avalableTreeWidget->setColumnCount(0); - vboxLayout->addWidget(avalableTreeWidget); + availableWidget = new QTreeWidget(this); + availableWidget->setRootIsDecorated(false); + availableWidget->setHeaderLabels(QStringList() << QString()); + availableWidget->header()->hide(); + vboxLayout->addWidget(availableWidget); gridLayout->addLayout(vboxLayout, 0, 0, 6, 1); vboxLayout1 = new QVBoxLayout(); vboxLayout1->setContentsMargins(0, 0, 0, 0); - label = new QLabel(this); - vboxLayout1->addWidget(label); + labelSelected = new QLabel(this); + vboxLayout1->addWidget(labelSelected); - selectedTreeWidget = new QTreeWidget(this); - vboxLayout1->addWidget(selectedTreeWidget); + selectedWidget = new QTreeWidget(this); + selectedWidget->setRootIsDecorated(false); + selectedWidget->setHeaderLabels(QStringList() << QString()); + selectedWidget->header()->hide(); + vboxLayout1->addWidget(selectedWidget); gridLayout->addLayout(vboxLayout1, 0, 2, 6, 1); - moveActionRightButton->setText(QString()); - moveActionLeftButton->setText(QString()); - moveActionDownButton->setText(QString()); - moveActionUpButton->setText(QString()); - label_2->setText(QApplication::translate("Gui::ActionSelector", "Available:", 0, QApplication::UnicodeUTF8)); - label->setText(QApplication::translate("Gui::ActionSelector", "Selected:", 0, QApplication::UnicodeUTF8)); + addButton->setText(QString()); + removeButton->setText(QString()); + upButton->setText(QString()); + downButton->setText(QString()); + + connect(addButton, SIGNAL(clicked()), + this, SLOT(on_addButton_clicked()) ); + connect(removeButton, SIGNAL(clicked()), + this, SLOT(on_removeButton_clicked()) ); + connect(upButton, SIGNAL(clicked()), + this, SLOT(on_upButton_clicked()) ); + connect(downButton, SIGNAL(clicked()), + this, SLOT(on_downButton_clicked()) ); + connect(availableWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), + this, SLOT(onItemDoubleClicked(QTreeWidgetItem*,int)) ); + connect(selectedWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), + this, SLOT(onItemDoubleClicked(QTreeWidgetItem*,int)) ); + connect(availableWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), + this, SLOT(onItemChanged(QTreeWidgetItem *,int)) ); + connect(selectedWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), + this, SLOT(onItemChanged(QTreeWidgetItem *,int)) ); + retranslateUi(); } ActionSelector::~ActionSelector() { } +void ActionSelector::retranslateUi() +{ + labelAvailable->setText(QApplication::translate("Gui::ActionSelector", "Available:", 0, QApplication::UnicodeUTF8)); + labelSelected->setText(QApplication::translate("Gui::ActionSelector", "Selected:", 0, QApplication::UnicodeUTF8)); + addButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Add", 0, QApplication::UnicodeUTF8)); + removeButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Remove", 0, QApplication::UnicodeUTF8)); + upButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Move up", 0, QApplication::UnicodeUTF8)); + downButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Move down", 0, QApplication::UnicodeUTF8)); +} + +void ActionSelector::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::LanguageChange) { + retranslateUi(); + } + QWidget::changeEvent(event); +} + +void ActionSelector::keyPressEvent(QKeyEvent* event) +{ + if ((event->modifiers() & Qt::ControlModifier)) { + switch (event->key()) + { + case Qt::Key_Right: + on_addButton_clicked(); + break; + case Qt::Key_Left: + on_removeButton_clicked(); + break; + case Qt::Key_Up: + on_upButton_clicked(); + break; + case Qt::Key_Down: + on_downButton_clicked(); + break; + default: + event->ignore(); + return; + } + } +} + +void ActionSelector::setButtonsEnabled() +{ + addButton->setEnabled(availableWidget->indexOfTopLevelItem(availableWidget->currentItem()) > -1); + removeButton->setEnabled(selectedWidget->indexOfTopLevelItem(selectedWidget->currentItem()) > -1); + upButton->setEnabled(selectedWidget->indexOfTopLevelItem(selectedWidget->currentItem()) > 0); + downButton->setEnabled(selectedWidget->indexOfTopLevelItem(selectedWidget->currentItem()) > -1 && + selectedWidget->indexOfTopLevelItem(selectedWidget->currentItem()) < selectedWidget->topLevelItemCount() - 1); +} + +void ActionSelector::onItemChanged(QTreeWidgetItem * /*item*/, int /*column*/) +{ + setButtonsEnabled(); +} + +void ActionSelector::onItemDoubleClicked(QTreeWidgetItem * item, int column) +{ + QTreeWidget* treeWidget = item->treeWidget(); + if (treeWidget == availableWidget) { + int index = availableWidget->indexOfTopLevelItem(item); + item = availableWidget->takeTopLevelItem(index); + availableWidget->setCurrentItem(0); + selectedWidget->addTopLevelItem(item); + selectedWidget->setCurrentItem(item); + } + else if (treeWidget == selectedWidget) { + int index = selectedWidget->indexOfTopLevelItem(item); + item = selectedWidget->takeTopLevelItem(index); + selectedWidget->setCurrentItem(0); + availableWidget->addTopLevelItem(item); + availableWidget->setCurrentItem(item); + } +} + +void ActionSelector::on_addButton_clicked() +{ + QTreeWidgetItem* item = availableWidget->currentItem(); + if (item) { + int index = availableWidget->indexOfTopLevelItem(item); + item = availableWidget->takeTopLevelItem(index); + availableWidget->setCurrentItem(0); + selectedWidget->addTopLevelItem(item); + selectedWidget->setCurrentItem(item); + } +} + +void ActionSelector::on_removeButton_clicked() +{ + QTreeWidgetItem* item = selectedWidget->currentItem(); + if (item) { + int index = selectedWidget->indexOfTopLevelItem(item); + item = selectedWidget->takeTopLevelItem(index); + selectedWidget->setCurrentItem(0); + availableWidget->addTopLevelItem(item); + availableWidget->setCurrentItem(item); + } +} + +void ActionSelector::on_upButton_clicked() +{ + QTreeWidgetItem* item = selectedWidget->currentItem(); + if (item && selectedWidget->isItemSelected(item)) { + int index = selectedWidget->indexOfTopLevelItem(item); + if (index > 0) { + selectedWidget->takeTopLevelItem(index); + selectedWidget->insertTopLevelItem(index-1, item); + selectedWidget->setCurrentItem(item); + } + } +} + +void ActionSelector::on_downButton_clicked() +{ + QTreeWidgetItem* item = selectedWidget->currentItem(); + if (item && selectedWidget->isItemSelected(item)) { + int index = selectedWidget->indexOfTopLevelItem(item); + if (index < selectedWidget->topLevelItemCount()-1) { + selectedWidget->takeTopLevelItem(index); + selectedWidget->insertTopLevelItem(index+1, item); + selectedWidget->setCurrentItem(item); + } + } +} // ------------------------------------------------------------------------------ diff --git a/src/Gui/Widgets.h b/src/Gui/Widgets.h index a13e407c6e..afdddba89f 100644 --- a/src/Gui/Widgets.h +++ b/src/Gui/Widgets.h @@ -63,26 +63,47 @@ Q_SIGNALS: // ------------------------------------------------------------------------------ -class ActionSelector : public QWidget +class GuiExport ActionSelector : public QWidget { + Q_OBJECT + public: ActionSelector(QWidget* parent=0); ~ActionSelector(); + QTreeWidget* availableTreeWidget() const + { return availableWidget; } + QTreeWidget* selectedTreeWidget() const + { return selectedWidget; } + +private: + void keyPressEvent(QKeyEvent *); + void changeEvent(QEvent*); + void retranslateUi(); + void setButtonsEnabled(); + +private Q_SLOTS: + void on_addButton_clicked(); + void on_removeButton_clicked(); + void on_upButton_clicked(); + void on_downButton_clicked(); + void onItemChanged(QTreeWidgetItem * item, int column); + void onItemDoubleClicked(QTreeWidgetItem * item, int column); + private: QGridLayout *gridLayout; - QPushButton *moveActionRightButton; + QVBoxLayout *vboxLayout; + QVBoxLayout *vboxLayout1; + QPushButton *addButton; + QPushButton *removeButton; + QPushButton *upButton; + QPushButton *downButton; + QLabel *labelAvailable; + QLabel *labelSelected; + QTreeWidget *availableWidget; + QTreeWidget *selectedWidget; QSpacerItem *spacerItem; QSpacerItem *spacerItem1; - QPushButton *moveActionLeftButton; - QPushButton *moveActionDownButton; - QPushButton *moveActionUpButton; - QVBoxLayout *vboxLayout; - QLabel *label_2; - QTreeWidget *avalableTreeWidget; - QVBoxLayout *vboxLayout1; - QLabel *label; - QTreeWidget *selectedTreeWidget; }; // ------------------------------------------------------------------------------ diff --git a/src/Tools/plugins/widget/FreeCAD_widgets.sln b/src/Tools/plugins/widget/FreeCAD_widgets.sln deleted file mode 100644 index 98489c937f..0000000000 --- a/src/Tools/plugins/widget/FreeCAD_widgets.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeCAD_widgets", "FreeCAD_widgets.vcproj", "{50CDC58F-0FF6-3CFA-BF66-E79DA98E7DF0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {50CDC58F-0FF6-3CFA-BF66-E79DA98E7DF0}.Debug|Win32.ActiveCfg = Debug|Win32 - {50CDC58F-0FF6-3CFA-BF66-E79DA98E7DF0}.Debug|Win32.Build.0 = Debug|Win32 - {50CDC58F-0FF6-3CFA-BF66-E79DA98E7DF0}.Release|Win32.ActiveCfg = Release|Win32 - {50CDC58F-0FF6-3CFA-BF66-E79DA98E7DF0}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/Tools/plugins/widget/customwidgets.cpp b/src/Tools/plugins/widget/customwidgets.cpp index 6a2280377e..9de8c0f823 100644 --- a/src/Tools/plugins/widget/customwidgets.cpp +++ b/src/Tools/plugins/widget/customwidgets.cpp @@ -330,6 +330,94 @@ void AccelLineEdit::keyPressEvent ( QKeyEvent * e) // ------------------------------------------------------------------------------ +ActionSelector::ActionSelector(QWidget* parent) + : QWidget(parent) +{ + addButton = new QPushButton(this); + addButton->setMinimumSize(QSize(30, 30)); + QIcon icon; + icon.addFile(QString::fromUtf8(":/icons/button_right.xpm"), QSize(), QIcon::Normal, QIcon::Off); + addButton->setIcon(icon); + gridLayout = new QGridLayout(this); + gridLayout->addWidget(addButton, 1, 1, 1, 1); + + spacerItem = new QSpacerItem(33, 57, QSizePolicy::Minimum, QSizePolicy::Expanding); + gridLayout->addItem(spacerItem, 5, 1, 1, 1); + spacerItem1 = new QSpacerItem(33, 58, QSizePolicy::Minimum, QSizePolicy::Expanding); + gridLayout->addItem(spacerItem1, 0, 1, 1, 1); + + removeButton = new QPushButton(this); + removeButton->setMinimumSize(QSize(30, 30)); + QIcon icon1; + icon1.addFile(QString::fromUtf8(":/icons/button_left.xpm"), QSize(), QIcon::Normal, QIcon::Off); + removeButton->setIcon(icon1); + removeButton->setAutoDefault(true); + removeButton->setDefault(false); + + gridLayout->addWidget(removeButton, 2, 1, 1, 1); + + upButton = new QPushButton(this); + upButton->setMinimumSize(QSize(30, 30)); + QIcon icon3; + icon3.addFile(QString::fromUtf8(":/icons/button_up.xpm"), QSize(), QIcon::Normal, QIcon::Off); + upButton->setIcon(icon3); + + gridLayout->addWidget(upButton, 3, 1, 1, 1); + + downButton = new QPushButton(this); + downButton->setMinimumSize(QSize(30, 30)); + QIcon icon2; + icon2.addFile(QString::fromUtf8(":/icons/button_down.xpm"), QSize(), QIcon::Normal, QIcon::Off); + downButton->setIcon(icon2); + downButton->setAutoDefault(true); + + gridLayout->addWidget(downButton, 4, 1, 1, 1); + + vboxLayout = new QVBoxLayout(); + vboxLayout->setContentsMargins(0, 0, 0, 0); + labelAvailable = new QLabel(this); + vboxLayout->addWidget(labelAvailable); + + availableWidget = new QTreeWidget(this); + availableWidget->setRootIsDecorated(false); + availableWidget->setHeaderLabels(QStringList() << QString()); + availableWidget->header()->hide(); + vboxLayout->addWidget(availableWidget); + + gridLayout->addLayout(vboxLayout, 0, 0, 6, 1); + + vboxLayout1 = new QVBoxLayout(); + vboxLayout1->setContentsMargins(0, 0, 0, 0); + labelSelected = new QLabel(this); + vboxLayout1->addWidget(labelSelected); + + selectedWidget = new QTreeWidget(this); + selectedWidget->setRootIsDecorated(false); + selectedWidget->setHeaderLabels(QStringList() << QString()); + selectedWidget->header()->hide(); + vboxLayout1->addWidget(selectedWidget); + + gridLayout->addLayout(vboxLayout1, 0, 2, 6, 1); + + addButton->setText(QString()); + removeButton->setText(QString()); + upButton->setText(QString()); + downButton->setText(QString()); + + labelAvailable->setText(QApplication::translate("Gui::ActionSelector", "Available:", 0, QApplication::UnicodeUTF8)); + labelSelected->setText(QApplication::translate("Gui::ActionSelector", "Selected:", 0, QApplication::UnicodeUTF8)); + addButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Add", 0, QApplication::UnicodeUTF8)); + removeButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Remove", 0, QApplication::UnicodeUTF8)); + upButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Move up", 0, QApplication::UnicodeUTF8)); + downButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Move down", 0, QApplication::UnicodeUTF8)); +} + +ActionSelector::~ActionSelector() +{ +} + +// -------------------------------------------------------------------- + CommandIconView::CommandIconView ( QWidget * parent ) : QListWidget(parent) { diff --git a/src/Tools/plugins/widget/customwidgets.h b/src/Tools/plugins/widget/customwidgets.h index 2543a119ef..013f6ba4ad 100644 --- a/src/Tools/plugins/widget/customwidgets.h +++ b/src/Tools/plugins/widget/customwidgets.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace Gui { @@ -176,6 +177,32 @@ protected: // ------------------------------------------------------------------------------ +class ActionSelector : public QWidget +{ + Q_OBJECT + +public: + ActionSelector(QWidget* parent=0); + ~ActionSelector(); + +private: + QGridLayout *gridLayout; + QVBoxLayout *vboxLayout; + QVBoxLayout *vboxLayout1; + QPushButton *addButton; + QPushButton *removeButton; + QPushButton *upButton; + QPushButton *downButton; + QLabel *labelAvailable; + QLabel *labelSelected; + QTreeWidget *availableWidget; + QTreeWidget *selectedWidget; + QSpacerItem *spacerItem; + QSpacerItem *spacerItem1; +}; + +// ------------------------------------------------------------------------------ + class CommandIconView : public QListWidget { Q_OBJECT diff --git a/src/Tools/plugins/widget/plugin.cpp b/src/Tools/plugins/widget/plugin.cpp index d0a2aca923..3769f37d48 100644 --- a/src/Tools/plugins/widget/plugin.cpp +++ b/src/Tools/plugins/widget/plugin.cpp @@ -340,6 +340,79 @@ public: } }; +/* XPM */ +static const char *actionselector_pixmap[]={ +"22 22 6 1", +"a c #000000", +"# c #000080", +"b c #008080", +"c c #808080", +"d c #c0c0c0", +". c #ffffff", +"......................", +"......................", +"......................", +"...#aaaaaaaaaaaaaa#...", +".baccccccccccccccccab.", +".acccddddddddddddddca.", +"#ccd................d#", +"acc.................da", +"acd.......d....ca.ac.a", +"acd......db......a...a", +"acd.dbbb.dbbbd...a...a", +"acd.ccdbddb.db...a...a", +"acd.dbbbddb..b...a...a", +"acd.bd.bddb..b...a...a", +"acd.bbbbddbbbc...a...a", +"acd..d.....dd..ca.acda", +"#cd.................d#", +".ac................da.", +".badd............dda#.", +"...#aaaaaaaaaaaaaa#...", +"......................", +"......................"}; + +class ActionSelectorPlugin : public QDesignerCustomWidgetInterface +{ + Q_INTERFACES(QDesignerCustomWidgetInterface) +public: + ActionSelectorPlugin() + { + } + QWidget *createWidget(QWidget *parent) + { + return new Gui::ActionSelector(parent); + } + QString group() const + { + return QLatin1String("Input Widgets"); + } + QIcon icon() const + { + return QIcon( QPixmap( actionselector_pixmap ) ); + } + QString includeFile() const + { + return QLatin1String("Gui/Widgets.h"); + } + QString toolTip() const + { + return QLatin1String("Action Selector"); + } + QString whatsThis() const + { + return QLatin1String("A widget to select actions."); + } + bool isContainer() const + { + return false; + } + QString name() const + { + return QLatin1String("Gui::ActionSelector"); + } +}; + /* XPM */ static const char *iconview_pixmap[]={ "22 22 10 1", @@ -1061,6 +1134,7 @@ QList CustomWidgetPlugin::customWidgets () con cw.append(new LocationWidgetPlugin); cw.append(new FileChooserPlugin); cw.append(new AccelLineEditPlugin); + cw.append(new ActionSelectorPlugin); cw.append(new CommandIconViewPlugin); cw.append(new UIntSpinBoxPlugin); cw.append(new ColorButtonPlugin); From 0623cd9b5e604dcf4def465e2c598ef9be68f7ae Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Jun 2012 14:22:05 +0200 Subject: [PATCH 308/351] Use ActionSelector in Loft panel and expose to Python by UiLoader --- src/Gui/Application.cpp | 4 + src/Gui/WidgetFactory.cpp | 74 +++++++++++++ src/Gui/WidgetFactory.h | 23 +++- src/Gui/Widgets.cpp | 38 ++++++- src/Gui/Widgets.h | 6 +- src/Gui/resource.cpp | 1 + src/Mod/Part/Gui/TaskLoft.cpp | 66 ++---------- src/Mod/Part/Gui/TaskLoft.h | 4 - src/Mod/Part/Gui/TaskLoft.ui | 192 +++++----------------------------- 9 files changed, 174 insertions(+), 234 deletions(-) diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index d62c36b4ef..a4c3542b39 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -341,6 +341,10 @@ Application::Application(bool GUIenabled) "workbenches."); Py::Module(module).setAttr(std::string("ActiveDocument"),Py::None()); + UiLoaderPy::init_type(); + Base::Interpreter().addType(UiLoaderPy::type_object(), + module,"UiLoader"); + //insert Selection module PyObject* pSelectionModule = Py_InitModule3("Selection", SelectionSingleton::Methods, "Selection module"); diff --git a/src/Gui/WidgetFactory.cpp b/src/Gui/WidgetFactory.cpp index c074fcd7e3..fd734154f2 100644 --- a/src/Gui/WidgetFactory.cpp +++ b/src/Gui/WidgetFactory.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" +#include #include #include #include @@ -194,6 +195,79 @@ QWidget* UiLoader::createWidget(const QString & className, QWidget * parent, // ---------------------------------------------------- +PyObject *UiLoaderPy::PyMake(struct _typeobject *type, PyObject * args, PyObject * kwds) +{ + if (!PyArg_ParseTuple(args, "")) + return 0; + return new UiLoaderPy(); +} + +void UiLoaderPy::init_type() +{ + behaviors().name("UiLoader"); + behaviors().doc("UiLoader to create widgets"); + behaviors().type_object()->tp_new = &PyMake; + // you must have overwritten the virtual functions + behaviors().supportRepr(); + behaviors().supportGetattr(); + behaviors().supportSetattr(); + add_varargs_method("createWidget",&UiLoaderPy::createWidget,"createWidget()"); +} + +UiLoaderPy::UiLoaderPy() +{ +} + +UiLoaderPy::~UiLoaderPy() +{ +} + +Py::Object UiLoaderPy::repr() +{ + std::string s; + std::ostringstream s_out; + s_out << "Ui loader"; + return Py::String(s_out.str()); +} + +Py::Object UiLoaderPy::createWidget(const Py::Tuple& args) +{ + Py::Module sipmod(PyImport_AddModule((char*)"sip")); + Py::Module qtmod(PyImport_ImportModule((char*)"PyQt4.Qt")); + + // 1st argument + std::string className = (std::string)Py::String(args[0]); + + // 2nd argument + QWidget* parent = 0; + if (args.size() > 1) { + Py::Callable func = sipmod.getDict().getItem("unwrapinstance"); + Py::Tuple arguments(1); + arguments[0] = args[1]; //PyQt pointer + Py::Object result = func.apply(arguments); + void* ptr = PyLong_AsVoidPtr(result.ptr()); + QObject* object = reinterpret_cast(ptr); + if (object) + parent = qobject_cast(object); + } + + // 3rd argument + std::string objectName; + if (args.size() > 2) { + objectName = (std::string)Py::String(args[2]); + } + + QWidget* widget = loader.createWidget(QString::fromAscii(className.c_str()), parent, + QString::fromAscii(objectName.c_str())); + Py::Callable func = sipmod.getDict().getItem("wrapinstance"); + Py::Tuple arguments(2); + arguments[0] = Py::asObject(PyLong_FromVoidPtr(widget)); + arguments[1] = qtmod.getDict().getItem("QWidget"); + return func.apply(arguments); +} + +// ---------------------------------------------------- + WidgetFactorySupplier* WidgetFactorySupplier::_pcSingleton = 0L; WidgetFactorySupplier & WidgetFactorySupplier::instance() diff --git a/src/Gui/WidgetFactory.h b/src/Gui/WidgetFactory.h index 8f20c88643..705e4c36b1 100644 --- a/src/Gui/WidgetFactory.h +++ b/src/Gui/WidgetFactory.h @@ -32,6 +32,7 @@ #include "DlgPreferencesImp.h" #include "DlgCustomizeImp.h" #include "PropertyPage.h" +#include namespace Gui { namespace Dialog{ @@ -85,13 +86,33 @@ public: * Fore more details see the documentation to QWidgetFactory. */ QWidget* createWidget(const QString & className, QWidget * parent=0, - const QString& name =QString()); + const QString& name = QString()); private: QStringList cw; }; // -------------------------------------------------------------------- +class UiLoaderPy : public Py::PythonExtension +{ +public: + static void init_type(void); // announce properties and methods + + UiLoaderPy(); + ~UiLoaderPy(); + + Py::Object repr(); + Py::Object createWidget(const Py::Tuple&); + +private: + static PyObject *PyMake(struct _typeobject *, PyObject *, PyObject *); + +private: + UiLoader loader; +}; + +// -------------------------------------------------------------------- + /** * The WidgetProducer class is a value-based template class that provides * the ability to create widgets dynamically. diff --git a/src/Gui/Widgets.cpp b/src/Gui/Widgets.cpp index 98a87442c5..d4e66e3bea 100644 --- a/src/Gui/Widgets.cpp +++ b/src/Gui/Widgets.cpp @@ -110,6 +110,7 @@ ActionSelector::ActionSelector(QWidget* parent) : QWidget(parent) { addButton = new QPushButton(this); + addButton->setObjectName(QLatin1String("addButton")); addButton->setMinimumSize(QSize(30, 30)); QIcon icon; icon.addFile(QString::fromUtf8(":/icons/button_right.xpm"), QSize(), QIcon::Normal, QIcon::Off); @@ -123,6 +124,7 @@ ActionSelector::ActionSelector(QWidget* parent) gridLayout->addItem(spacerItem1, 0, 1, 1, 1); removeButton = new QPushButton(this); + removeButton->setObjectName(QLatin1String("removeButton")); removeButton->setMinimumSize(QSize(30, 30)); QIcon icon1; icon1.addFile(QString::fromUtf8(":/icons/button_left.xpm"), QSize(), QIcon::Normal, QIcon::Off); @@ -133,6 +135,7 @@ ActionSelector::ActionSelector(QWidget* parent) gridLayout->addWidget(removeButton, 2, 1, 1, 1); upButton = new QPushButton(this); + upButton->setObjectName(QLatin1String("upButton")); upButton->setMinimumSize(QSize(30, 30)); QIcon icon3; icon3.addFile(QString::fromUtf8(":/icons/button_up.xpm"), QSize(), QIcon::Normal, QIcon::Off); @@ -141,6 +144,7 @@ ActionSelector::ActionSelector(QWidget* parent) gridLayout->addWidget(upButton, 3, 1, 1, 1); downButton = new QPushButton(this); + downButton->setObjectName(QLatin1String("downButton")); downButton->setMinimumSize(QSize(30, 30)); QIcon icon2; icon2.addFile(QString::fromUtf8(":/icons/button_down.xpm"), QSize(), QIcon::Normal, QIcon::Off); @@ -155,6 +159,7 @@ ActionSelector::ActionSelector(QWidget* parent) vboxLayout->addWidget(labelAvailable); availableWidget = new QTreeWidget(this); + availableWidget->setObjectName(QLatin1String("availableTreeWidget")); availableWidget->setRootIsDecorated(false); availableWidget->setHeaderLabels(QStringList() << QString()); availableWidget->header()->hide(); @@ -168,6 +173,7 @@ ActionSelector::ActionSelector(QWidget* parent) vboxLayout1->addWidget(labelSelected); selectedWidget = new QTreeWidget(this); + selectedWidget->setObjectName(QLatin1String("selectedTreeWidget")); selectedWidget->setRootIsDecorated(false); selectedWidget->setHeaderLabels(QStringList() << QString()); selectedWidget->header()->hide(); @@ -192,17 +198,39 @@ ActionSelector::ActionSelector(QWidget* parent) this, SLOT(onItemDoubleClicked(QTreeWidgetItem*,int)) ); connect(selectedWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(onItemDoubleClicked(QTreeWidgetItem*,int)) ); - connect(availableWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this, SLOT(onItemChanged(QTreeWidgetItem *,int)) ); - connect(selectedWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this, SLOT(onItemChanged(QTreeWidgetItem *,int)) ); + connect(availableWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem *)), + this, SLOT(onCurrentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *)) ); + connect(selectedWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem *)), + this, SLOT(onCurrentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *)) ); retranslateUi(); + setButtonsEnabled(); } ActionSelector::~ActionSelector() { } +void ActionSelector::setSelectedLabel(const QString& label) +{ + labelSelected->setText(label); +} + +QString ActionSelector::selectedLabel() const +{ + return labelSelected->text(); +} + +void ActionSelector::setAvailableLabel(const QString& label) +{ + labelAvailable->setText(label); +} + +QString ActionSelector::availableLabel() const +{ + return labelAvailable->text(); +} + + void ActionSelector::retranslateUi() { labelAvailable->setText(QApplication::translate("Gui::ActionSelector", "Available:", 0, QApplication::UnicodeUTF8)); @@ -254,7 +282,7 @@ void ActionSelector::setButtonsEnabled() selectedWidget->indexOfTopLevelItem(selectedWidget->currentItem()) < selectedWidget->topLevelItemCount() - 1); } -void ActionSelector::onItemChanged(QTreeWidgetItem * /*item*/, int /*column*/) +void ActionSelector::onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*) { setButtonsEnabled(); } diff --git a/src/Gui/Widgets.h b/src/Gui/Widgets.h index afdddba89f..70366a67f6 100644 --- a/src/Gui/Widgets.h +++ b/src/Gui/Widgets.h @@ -75,6 +75,10 @@ public: { return availableWidget; } QTreeWidget* selectedTreeWidget() const { return selectedWidget; } + void setSelectedLabel(const QString&); + QString selectedLabel() const; + void setAvailableLabel(const QString&); + QString availableLabel() const; private: void keyPressEvent(QKeyEvent *); @@ -87,7 +91,7 @@ private Q_SLOTS: void on_removeButton_clicked(); void on_upButton_clicked(); void on_downButton_clicked(); - void onItemChanged(QTreeWidgetItem * item, int column); + void onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*); void onItemDoubleClicked(QTreeWidgetItem * item, int column); private: diff --git a/src/Gui/resource.cpp b/src/Gui/resource.cpp index 3143f1502a..b7f3ce8fbd 100644 --- a/src/Gui/resource.cpp +++ b/src/Gui/resource.cpp @@ -91,6 +91,7 @@ WidgetFactorySupplier::WidgetFactorySupplier() new WidgetProducer; new WidgetProducer; new WidgetProducer; + new WidgetProducer; new WidgetProducer; new WidgetProducer; new WidgetProducer; diff --git a/src/Mod/Part/Gui/TaskLoft.cpp b/src/Mod/Part/Gui/TaskLoft.cpp index b6d58885df..96c3417a27 100644 --- a/src/Mod/Part/Gui/TaskLoft.cpp +++ b/src/Mod/Part/Gui/TaskLoft.cpp @@ -68,10 +68,14 @@ LoftWidget::LoftWidget(QWidget* parent) Gui::Application::Instance->runPythonCode("import Part"); d->ui.setupUi(this); - connect(d->ui.treeWidgetWire, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + d->ui.selector->setAvailableLabel(tr("Vertex/Wire")); + d->ui.selector->setSelectedLabel(tr("Loft")); + + connect(d->ui.selector->availableTreeWidget(), SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); - connect(d->ui.treeWidgetLoft, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + connect(d->ui.selector->selectedTreeWidget(), SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + findShapes(); } @@ -105,7 +109,7 @@ void LoftWidget::findShapes() child->setData(0, Qt::UserRole, name); Gui::ViewProvider* vp = activeGui->getViewProvider(*it); if (vp) child->setIcon(0, vp->getIcon()); - d->ui.treeWidgetWire->addTopLevelItem(child); + d->ui.selector->availableTreeWidget()->addTopLevelItem(child); } } } @@ -125,13 +129,13 @@ bool LoftWidget::accept() QTextStream str(&list); - int count = d->ui.treeWidgetLoft->topLevelItemCount(); + int count = d->ui.selector->selectedTreeWidget()->topLevelItemCount(); if (count < 2) { QMessageBox::critical(this, tr("Too few elements"), tr("At least two vertices, edges or wires are required.")); return false; } for (int i=0; iui.treeWidgetLoft->topLevelItem(i); + QTreeWidgetItem* child = d->ui.selector->selectedTreeWidget()->topLevelItem(i); QString name = child->data(0, Qt::UserRole).toString(); str << "App.getDocument('" << d->document.c_str() << "')." << name << ", "; } @@ -177,61 +181,13 @@ void LoftWidget::onCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* } } -void LoftWidget::on_addButton_clicked() -{ - QTreeWidgetItem* item = d->ui.treeWidgetWire->currentItem(); - if (item) { - int index = d->ui.treeWidgetWire->indexOfTopLevelItem(item); - item = d->ui.treeWidgetWire->takeTopLevelItem(index); - d->ui.treeWidgetWire->setCurrentItem(0); - d->ui.treeWidgetLoft->addTopLevelItem(item); - d->ui.treeWidgetLoft->setCurrentItem(item); - } -} - -void LoftWidget::on_removeButton_clicked() -{ - QTreeWidgetItem* item = d->ui.treeWidgetLoft->currentItem(); - if (item) { - int index = d->ui.treeWidgetLoft->indexOfTopLevelItem(item); - item = d->ui.treeWidgetLoft->takeTopLevelItem(index); - d->ui.treeWidgetLoft->setCurrentItem(0); - d->ui.treeWidgetWire->addTopLevelItem(item); - d->ui.treeWidgetWire->setCurrentItem(item); - } -} - -void LoftWidget::on_upButton_clicked() -{ - QTreeWidgetItem* item = d->ui.treeWidgetLoft->currentItem(); - if (item && d->ui.treeWidgetLoft->isItemSelected(item)) { - int index = d->ui.treeWidgetLoft->indexOfTopLevelItem(item); - if (index > 0) { - d->ui.treeWidgetLoft->takeTopLevelItem(index); - d->ui.treeWidgetLoft->insertTopLevelItem(index-1, item); - d->ui.treeWidgetLoft->setCurrentItem(item); - } - } -} - -void LoftWidget::on_downButton_clicked() -{ - QTreeWidgetItem* item = d->ui.treeWidgetLoft->currentItem(); - if (item && d->ui.treeWidgetLoft->isItemSelected(item)) { - int index = d->ui.treeWidgetLoft->indexOfTopLevelItem(item); - if (index < d->ui.treeWidgetLoft->topLevelItemCount()-1) { - d->ui.treeWidgetLoft->takeTopLevelItem(index); - d->ui.treeWidgetLoft->insertTopLevelItem(index+1, item); - d->ui.treeWidgetLoft->setCurrentItem(item); - } - } -} - void LoftWidget::changeEvent(QEvent *e) { QWidget::changeEvent(e); if (e->type() == QEvent::LanguageChange) { d->ui.retranslateUi(this); + d->ui.selector->setAvailableLabel(tr("Vertex/Wire")); + d->ui.selector->setSelectedLabel(tr("Loft")); } } diff --git a/src/Mod/Part/Gui/TaskLoft.h b/src/Mod/Part/Gui/TaskLoft.h index 82ac877a51..50d30771d1 100644 --- a/src/Mod/Part/Gui/TaskLoft.h +++ b/src/Mod/Part/Gui/TaskLoft.h @@ -43,10 +43,6 @@ public: bool reject(); private Q_SLOTS: - void on_addButton_clicked(); - void on_removeButton_clicked(); - void on_upButton_clicked(); - void on_downButton_clicked(); void onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*); private: diff --git a/src/Mod/Part/Gui/TaskLoft.ui b/src/Mod/Part/Gui/TaskLoft.ui index 1dd0c6159f..dd461047d9 100644 --- a/src/Mod/Part/Gui/TaskLoft.ui +++ b/src/Mod/Part/Gui/TaskLoft.ui @@ -6,7 +6,7 @@ 0 0 - 324 + 336 326 @@ -14,172 +14,8 @@ Loft - - - - - Vertex/Wire - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 33 - 58 - - - - - - - - true - - - - 30 - 30 - - - - Move right - - - <b>Move the selected item one level down.</b><p>This will also change the level of the parent item.</p> - - - - - - - :/icons/button_right.xpm:/icons/button_right.xpm - - - - - - - true - - - - 30 - 30 - - - - Move left - - - <b>Move the selected item one level up.</b><p>This will also change the level of the parent item.</p> - - - - - - - :/icons/button_left.xpm:/icons/button_left.xpm - - - true - - - false - - - - - - - true - - - - 30 - 30 - - - - Move up - - - <b>Move the selected item up.</b><p>The item will be moved within the hierarchy level.</p> - - - - - - - :/icons/button_up.xpm:/icons/button_up.xpm - - - - - - - true - - - - 30 - 30 - - - - Move down - - - <b>Move the selected item down.</b><p>The item will be moved within the hierarchy level.</p> - - - - - - - :/icons/button_down.xpm:/icons/button_down.xpm - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 33 - 57 - - - - - - - - - - - Loft - - - + + @@ -188,15 +24,35 @@ - + Ruled surface + + + + Qt::Horizontal + + + + 130 + 20 + + + + + + + Gui::ActionSelector + QWidget +

Gui/Widgets.h
+ + From 50a9ddee434719cedeb39d1ff8c1d43cd49af156 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 3 Jun 2012 16:36:00 +0200 Subject: [PATCH 309/351] 0000706: copy- paste- crash --- src/App/PropertyLinks.cpp | 14 ++++++++++---- src/Gui/MergeDocuments.cpp | 13 +++++-------- src/Gui/Tree.cpp | 11 ++++++++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 6cc1058083..9ffb1d0336 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -130,12 +130,18 @@ void PropertyLink::Restore(Base::XMLReader &reader) assert(getContainer()->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId()) ); if (name != "") { - DocumentObject *pcObject = static_cast(getContainer())-> - getDocument()->getObject(name.c_str()); - if (!pcObject) + DocumentObject* parent = static_cast(getContainer()); + DocumentObject* object = parent->getDocument()->getObject(name.c_str()); + if (!object) { Base::Console().Warning("Lost link to '%s' while loading, maybe " "an object was not loaded correctly\n",name.c_str()); - setValue(pcObject); + } + else if (parent == object) { + Base::Console().Warning("Object '%s' links to itself, nullify it\n",name.c_str()); + object = 0; + } + + setValue(object); } else { setValue(0); diff --git a/src/Gui/MergeDocuments.cpp b/src/Gui/MergeDocuments.cpp index 7addd29bed..52713fa474 100644 --- a/src/Gui/MergeDocuments.cpp +++ b/src/Gui/MergeDocuments.cpp @@ -122,16 +122,13 @@ MergeDocuments::importObjects(std::istream& input) reader.readElement("Object"); std::string type = reader.getAttribute("type"); std::string name = reader.getAttribute("name"); - std::string docn = name; - - // remove number from end to avoid lengthy names - size_t lastpos = docn.length()-1; - while (docn[lastpos] >= 48 && docn[lastpos] <= 57) - lastpos--; - docn = docn.substr(0, lastpos+1); try { - App::DocumentObject* o = appdoc->addObject(type.c_str(),docn.c_str()); + // Use name from XML as is and do NOT remove trailing digits because + // otherwise we may cause a dependency to itself + // Example: Object 'Cut001' references object 'Cut' and removing the + // digits we make an object 'Cut' referencing itself. + App::DocumentObject* o = appdoc->addObject(type.c_str(),name.c_str()); objs.push_back(o); // use this name for the later access because an object with // the given name may already exist diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index ba3672d8cd..c453662a59 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -830,9 +830,14 @@ void DocumentItem::slotChangeObject(const Gui::ViewProviderDocumentObject& view) children.insert(kt->second); QTreeWidgetItem* parent = kt->second->parent(); if (parent && parent != it->second) { - int index = parent->indexOfChild(kt->second); - parent->takeChild(index); - it->second->addChild(kt->second); + if (it->second != kt->second) { + int index = parent->indexOfChild(kt->second); + parent->takeChild(index); + it->second->addChild(kt->second); + } + else { + Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Object references to itself.\n"); + } } } else { From 8941868e0d9c4f356f62f5451e76bbfa547843bf Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 4 Jun 2012 01:31:26 +0200 Subject: [PATCH 310/351] Tmp. switch off gcc linker settings --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d2eaf6849..6461a3e103 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) # get linker errors as soon as possible and not at runtime e.g. for modules if(UNIX) - SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") + # SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") endif(UNIX) endif(CMAKE_COMPILER_IS_GNUCXX) From b701bfd1e1d665b0744c07c8618bd75682f3914b Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 3 Jun 2012 23:44:20 -0300 Subject: [PATCH 311/351] Arch: Several bugfixes in arch objects --- src/Mod/Arch/ArchComponent.py | 4 +- src/Mod/Arch/ArchStructure.py | 20 +++++----- src/Mod/Arch/ArchWall.py | 33 ++++++++------- src/Mod/Arch/ArchWindow.py | 75 ++++++++++++++++++----------------- 4 files changed, 69 insertions(+), 63 deletions(-) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index c9fa5a347e..13ad37204e 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -257,9 +257,9 @@ class Component: obj.addProperty("App::PropertyLink","Base","Base", "The base object this component is built upon") obj.addProperty("App::PropertyLinkList","Additions","Base", - "Other shapes that are appended to this wall") + "Other shapes that are appended to this object") obj.addProperty("App::PropertyLinkList","Subtractions","Base", - "Other shapes that are subtracted from this wall") + "Other shapes that are subtracted from this object") obj.Proxy = self self.Type = "Component" self.Subvolume = None diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index 7bf73cc1e0..d257c4d92f 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -163,17 +163,13 @@ class _Structure(ArchComponent.Component): base = Part.Face(base) base = base.extrude(normal) for app in obj.Additions: - base = base.oldFuse(app.Shape) - app.ViewObject.hide() # to be removed + if hasattr(app,"Shape"): + if not app.Shape.isNull(): + base = base.fuse(app.Shape) + app.ViewObject.hide() # to be removed for hole in obj.Subtractions: - cut = False - if hasattr(hole,"Proxy"): - if hasattr(hole.Proxy,"Subvolume"): - if hole.Proxy.Subvolume: - base = base.cut(hole.Proxy.Subvolume) - cut = True - if not cut: - if hasattr(obj,"Shape"): + if hasattr(hole,"Shape"): + if not hole.Shape.isNull(): base = base.cut(hole.Shape) hole.ViewObject.hide() # to be removed if base: @@ -186,7 +182,9 @@ class _Structure(ArchComponent.Component): fsh.append(sh) obj.Shape = Part.makeCompound(fsh) else: - obj.Shape = base + if not base.isNull(): + base = base.removeSplitter() + obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl class _ViewProviderStructure(ArchComponent.ViewProviderComponent): diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 4b9db7ee03..0bfa8f6e48 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -272,20 +272,23 @@ class _Wall(ArchComponent.Component): "returns a subvolume from a base object" import Part max_length = 0 + f = None for w in base.Shape.Wires: if w.BoundBox.DiagonalLength > max_length: max_length = w.BoundBox.DiagonalLength f = w - f = Part.Face(f) - n = f.normalAt(0,0) - v1 = DraftVecUtils.scaleTo(n,width) - f.translate(v1) - v2 = DraftVecUtils.neg(v1) - v2 = DraftVecUtils.scale(v1,-2) - f = f.extrude(v2) - if delta: - f.translate(delta) - return f + if f: + f = Part.Face(f) + n = f.normalAt(0,0) + v1 = DraftVecUtils.scaleTo(n,width) + f.translate(v1) + v2 = DraftVecUtils.neg(v1) + v2 = DraftVecUtils.scale(v1,-2) + f = f.extrude(v2) + if delta: + f.translate(delta) + return f + return None def createGeometry(self,obj): "builds the wall shape" @@ -368,27 +371,29 @@ class _Wall(ArchComponent.Component): else: temp = sh base = temp - base = base.removeSplitter() for app in obj.Additions: - base = base.oldFuse(app.Shape) + base = base.fuse(app.Shape) app.ViewObject.hide() #to be removed for hole in obj.Subtractions: if Draft.getType(hole) == "Window": # window if hole.Base and obj.Width: f = self.getSubVolume(hole.Base,width) - base = base.cut(f) + if f: + base = base.cut(f) elif Draft.isClone(hole,"Window"): if hole.Objects[0].Base and width: f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement.Base) - base = base.cut(f) + if f: + base = base.cut(f) elif hasattr(hole,"Shape"): if not hole.Shape.isNull(): base = base.cut(hole.Shape) hole.ViewObject.hide() # to be removed if base: + base.removeSplitter() obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index de7df1b6e1..2c20b03ca2 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -117,6 +117,7 @@ class _Window(ArchComponent.Component): obj.addProperty("App::PropertyStringList","WindowParts","Base", str(translate("Arch","the components of this window"))) self.Type = "Window" + obj.Proxy = self def execute(self,obj): self.createGeometry(obj) @@ -130,43 +131,45 @@ class _Window(ArchComponent.Component): pl = obj.Placement if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): - if obj.WindowParts and (len(obj.WindowParts)%5 == 0): - shapes = [] - for i in range(len(obj.WindowParts)/5): - wires = [] - wstr = obj.WindowParts[(i*5)+2].split(',') - for s in wstr: - j = int(s[4:]) - if obj.Base.Shape.Wires: - if len(obj.Base.Shape.Wires) >= j: - wires.append(obj.Base.Shape.Wires[j]) - if wires: - max_length = 0 - for w in wires: - if w.BoundBox.DiagonalLength > max_length: - max_length = w.BoundBox.DiagonalLength - ext = w - wires.remove(ext) - shape = Part.Face(ext) - norm = shape.normalAt(0,0) - thk = float(obj.WindowParts[(i*5)+3]) - if thk: - exv = DraftVecUtils.scaleTo(norm,thk) - shape = shape.extrude(exv) + if hasattr(obj,"WindowParts"): + if obj.WindowParts and (len(obj.WindowParts)%5 == 0): + shapes = [] + for i in range(len(obj.WindowParts)/5): + wires = [] + wstr = obj.WindowParts[(i*5)+2].split(',') + for s in wstr: + j = int(s[4:]) + if obj.Base.Shape.Wires: + if len(obj.Base.Shape.Wires) >= j: + wires.append(obj.Base.Shape.Wires[j]) + if wires: + max_length = 0 for w in wires: - f = Part.Face(w) - f = f.extrude(exv) - shape = shape.cut(f) - if obj.WindowParts[(i*5)+4]: - zof = float(obj.WindowParts[(i*5)+4]) - if zof: - zov = DraftVecUtils.scaleTo(norm,zof) - shape.translate(zov) - print shape - shapes.append(shape) - obj.Shape = Part.makeCompound(shapes) - if not DraftGeomUtils.isNull(pl): - obj.Placement = pl + if w.BoundBox.DiagonalLength > max_length: + max_length = w.BoundBox.DiagonalLength + ext = w + wires.remove(ext) + shape = Part.Face(ext) + norm = shape.normalAt(0,0) + thk = float(obj.WindowParts[(i*5)+3]) + if thk: + exv = DraftVecUtils.scaleTo(norm,thk) + shape = shape.extrude(exv) + for w in wires: + f = Part.Face(w) + f = f.extrude(exv) + shape = shape.cut(f) + if obj.WindowParts[(i*5)+4]: + zof = float(obj.WindowParts[(i*5)+4]) + if zof: + zov = DraftVecUtils.scaleTo(norm,zof) + shape.translate(zov) + print shape + shapes.append(shape) + if shapes: + obj.Shape = Part.makeCompound(shapes) + if not DraftGeomUtils.isNull(pl): + obj.Placement = pl class _ViewProviderWindow(ArchComponent.ViewProviderComponent): "A View Provider for the Window object" From f8f498a4f9e4748f9172d96eb84b420d0297449f Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 4 Jun 2012 11:43:20 +0200 Subject: [PATCH 312/351] 0000727: Keep faces colors on boolean operations --- src/Mod/Part/App/FeaturePartBoolean.cpp | 16 ++- src/Mod/Part/App/FeaturePartCommon.cpp | 30 +++-- src/Mod/Part/App/FeaturePartFuse.cpp | 30 +++-- src/Mod/Part/App/modelRefine.cpp | 147 ++++++++++++++++++++++++ src/Mod/Part/App/modelRefine.h | 31 ++++- src/Mod/Part/Gui/DlgSettingsGeneral.cpp | 2 + src/Mod/Part/Gui/DlgSettingsGeneral.ui | 110 ++++++++++-------- 7 files changed, 302 insertions(+), 64 deletions(-) diff --git a/src/Mod/Part/App/FeaturePartBoolean.cpp b/src/Mod/Part/App/FeaturePartBoolean.cpp index 1a2608797b..2a1781b6cf 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.cpp +++ b/src/Mod/Part/App/FeaturePartBoolean.cpp @@ -28,6 +28,9 @@ #endif #include "FeaturePartBoolean.h" +#include "modelRefine.h" +#include +#include using namespace Part; @@ -75,7 +78,7 @@ App::DocumentObjectExecReturn *Boolean::execute(void) if (!mkBool->IsDone()) { return new App::DocumentObjectExecReturn("Boolean operation failed"); } - const TopoDS_Shape& resShape = mkBool->Shape(); + TopoDS_Shape resShape = mkBool->Shape(); if (resShape.IsNull()) { return new App::DocumentObjectExecReturn("Resulting shape is invalid"); } @@ -84,6 +87,17 @@ App::DocumentObjectExecReturn *Boolean::execute(void) history.push_back(buildHistory(*mkBool.get(), TopAbs_FACE, resShape, BaseShape)); history.push_back(buildHistory(*mkBool.get(), TopAbs_FACE, resShape, ToolShape)); + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); + if (hGrp->GetBool("RefineModel", false)) { + TopoDS_Shape oldShape = resShape; + BRepBuilderAPI_RefineModel mkRefine(oldShape); + resShape = mkRefine.Shape(); + ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape); + history[0] = joinHistory(history[0], hist); + history[1] = joinHistory(history[1], hist); + } + this->Shape.setValue(resShape); this->History.setValues(history); return App::DocumentObject::StdReturn; diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index 44c93a01c3..01ef09e417 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -30,7 +30,9 @@ #include "FeaturePartCommon.h" - +#include "modelRefine.h" +#include +#include #include using namespace Part; @@ -84,17 +86,17 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void) if (s.size() >= 2) { try { std::vector history; - TopoDS_Shape res = s.front(); + TopoDS_Shape resShape = s.front(); for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Common mkCommon(res, *it); + BRepAlgoAPI_Common mkCommon(resShape, *it); // Let's check if the fusion has been successful if (!mkCommon.IsDone()) throw Base::Exception("Intersection failed"); - res = mkCommon.Shape(); + resShape = mkCommon.Shape(); - ShapeHistory hist1 = buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape1()); - ShapeHistory hist2 = buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape2()); + ShapeHistory hist1 = buildHistory(mkCommon, TopAbs_FACE, resShape, mkCommon.Shape1()); + ShapeHistory hist2 = buildHistory(mkCommon, TopAbs_FACE, resShape, mkCommon.Shape2()); if (history.empty()) { history.push_back(hist1); history.push_back(hist2); @@ -105,9 +107,21 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void) history.push_back(hist2); } } - if (res.IsNull()) + if (resShape.IsNull()) throw Base::Exception("Resulting shape is invalid"); - this->Shape.setValue(res); + + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); + if (hGrp->GetBool("RefineModel", false)) { + TopoDS_Shape oldShape = resShape; + BRepBuilderAPI_RefineModel mkRefine(oldShape); + resShape = mkRefine.Shape(); + ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape); + for (std::vector::iterator jt = history.begin(); jt != history.end(); ++jt) + *jt = joinHistory(*jt, hist); + } + + this->Shape.setValue(resShape); this->History.setValues(history); } catch (Standard_Failure) { diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index 47efb7a445..ba73877ea5 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -29,7 +29,9 @@ #include "FeaturePartFuse.h" - +#include "modelRefine.h" +#include +#include #include using namespace Part; @@ -83,17 +85,17 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void) if (s.size() >= 2) { try { std::vector history; - TopoDS_Shape res = s.front(); + TopoDS_Shape resShape = s.front(); for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Fuse mkFuse(res, *it); + BRepAlgoAPI_Fuse mkFuse(resShape, *it); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) throw Base::Exception("Fusion failed"); - res = mkFuse.Shape(); + resShape = mkFuse.Shape(); - ShapeHistory hist1 = buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape1()); - ShapeHistory hist2 = buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape2()); + ShapeHistory hist1 = buildHistory(mkFuse, TopAbs_FACE, resShape, mkFuse.Shape1()); + ShapeHistory hist2 = buildHistory(mkFuse, TopAbs_FACE, resShape, mkFuse.Shape2()); if (history.empty()) { history.push_back(hist1); history.push_back(hist2); @@ -104,9 +106,21 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void) history.push_back(hist2); } } - if (res.IsNull()) + if (resShape.IsNull()) throw Base::Exception("Resulting shape is invalid"); - this->Shape.setValue(res); + + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); + if (hGrp->GetBool("RefineModel", false)) { + TopoDS_Shape oldShape = resShape; + BRepBuilderAPI_RefineModel mkRefine(oldShape); + resShape = mkRefine.Shape(); + ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape); + for (std::vector::iterator jt = history.begin(); jt != history.end(); ++jt) + *jt = joinHistory(*jt, hist); + } + + this->Shape.setValue(resShape); this->History.setValues(history); } catch (Standard_Failure) { diff --git a/src/Mod/Part/App/modelRefine.cpp b/src/Mod/Part/App/modelRefine.cpp index 1a68b8ffea..516cf0551b 100644 --- a/src/Mod/Part/App/modelRefine.cpp +++ b/src/Mod/Part/App/modelRefine.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -547,6 +548,8 @@ bool FaceUniter::process() { if (workShell.IsNull()) return false; + modifiedShapes.clear(); + deletedShapes.clear(); typeObjects.push_back(&getPlaneObject()); typeObjects.push_back(&getCylinderObject()); //add more face types. @@ -583,6 +586,12 @@ bool FaceUniter::process() facesToRemove.reserve(facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size()); FaceVectorType temp = adjacencySplitter.getGroup(adjacentIndex); facesToRemove.insert(facesToRemove.end(), temp.begin(), temp.end()); + // the first shape will be marked as modified, i.e. replaced by newFace, all others are marked as deleted + if (!temp.empty()) + { + modifiedShapes.push_back(std::make_pair(temp.front(), newFace)); + deletedShapes.insert(deletedShapes.end(), temp.begin()+1, temp.end()); + } } } } @@ -632,3 +641,141 @@ bool FaceUniter::process() } return true; } + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//TODO: Implement a way to log all modifications + +Part::BRepBuilderAPI_RefineModel::BRepBuilderAPI_RefineModel(const TopoDS_Shape& shape) +{ + myShape = shape; + Build(); +} + +void Part::BRepBuilderAPI_RefineModel::Build() +{ + if (myShape.IsNull()) + Standard_Failure::Raise("Cannot remove splitter from empty shape"); + + if (myShape.ShapeType() == TopAbs_SOLID) { + const TopoDS_Solid &solid = TopoDS::Solid(myShape); + BRepTools_ReShape reshape; + TopExp_Explorer it; + for (it.Init(solid, TopAbs_SHELL); it.More(); it.Next()) { + const TopoDS_Shell ¤tShell = TopoDS::Shell(it.Current()); + ModelRefine::FaceUniter uniter(currentShell); + if (uniter.process()) { + if (uniter.isModified()) { + const TopoDS_Shell &newShell = uniter.getShell(); + reshape.Replace(currentShell, newShell); + LogModifications(uniter); + } + } + else { + Standard_Failure::Raise("Removing splitter failed"); + } + } + myShape = reshape.Apply(solid); + } + else if (myShape.ShapeType() == TopAbs_SHELL) { + const TopoDS_Shell& shell = TopoDS::Shell(myShape); + ModelRefine::FaceUniter uniter(shell); + if (uniter.process()) { + myShape = uniter.getShell(); + LogModifications(uniter); + } + else { + Standard_Failure::Raise("Removing splitter failed"); + } + } + else if (myShape.ShapeType() == TopAbs_COMPOUND) { + BRep_Builder builder; + TopoDS_Compound comp; + builder.MakeCompound(comp); + + TopExp_Explorer xp; + // solids + for (xp.Init(myShape, TopAbs_SOLID); xp.More(); xp.Next()) { + const TopoDS_Solid &solid = TopoDS::Solid(xp.Current()); + BRepTools_ReShape reshape; + TopExp_Explorer it; + for (it.Init(solid, TopAbs_SHELL); it.More(); it.Next()) { + const TopoDS_Shell ¤tShell = TopoDS::Shell(it.Current()); + ModelRefine::FaceUniter uniter(currentShell); + if (uniter.process()) { + if (uniter.isModified()) { + const TopoDS_Shell &newShell = uniter.getShell(); + reshape.Replace(currentShell, newShell); + LogModifications(uniter); + } + } + } + builder.Add(comp, reshape.Apply(solid)); + } + // free shells + for (xp.Init(myShape, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next()) { + const TopoDS_Shell& shell = TopoDS::Shell(xp.Current()); + ModelRefine::FaceUniter uniter(shell); + if (uniter.process()) { + builder.Add(comp, uniter.getShell()); + LogModifications(uniter); + } + } + // the rest + for (xp.Init(myShape, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next()) { + if (!xp.Current().IsNull()) + builder.Add(comp, xp.Current()); + } + for (xp.Init(myShape, TopAbs_WIRE, TopAbs_FACE); xp.More(); xp.Next()) { + if (!xp.Current().IsNull()) + builder.Add(comp, xp.Current()); + } + for (xp.Init(myShape, TopAbs_EDGE, TopAbs_WIRE); xp.More(); xp.Next()) { + if (!xp.Current().IsNull()) + builder.Add(comp, xp.Current()); + } + for (xp.Init(myShape, TopAbs_VERTEX, TopAbs_EDGE); xp.More(); xp.Next()) { + if (!xp.Current().IsNull()) + builder.Add(comp, xp.Current()); + } + + myShape = comp; + } + + Done(); +} + +void Part::BRepBuilderAPI_RefineModel::LogModifications(const ModelRefine::FaceUniter& uniter) +{ + const std::vector& modShapes = uniter.getModifiedShapes(); + for (std::vector::const_iterator it = modShapes.begin(); it != modShapes.end(); ++it) { + TopTools_ListOfShape list; + list.Append(it->second); + myModified.Bind(it->first, list); + } + const ShapeVectorType& delShapes = uniter.getDeletedShapes(); + for (ShapeVectorType::const_iterator it = delShapes.begin(); it != delShapes.end(); ++it) { + myDeleted.Append(*it); + } +} + +const TopTools_ListOfShape& Part::BRepBuilderAPI_RefineModel::Modified(const TopoDS_Shape& S) +{ + if (myModified.IsBound(S)) + return myModified.Find(S); + else + return myEmptyList; +} + +Standard_Boolean Part::BRepBuilderAPI_RefineModel::IsDeleted(const TopoDS_Shape& S) +{ + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(myDeleted); it.More(); it.Next()) + { + if (it.Value().IsSame(S)) + return Standard_True; + } + + return Standard_False; +} + diff --git a/src/Mod/Part/App/modelRefine.h b/src/Mod/Part/App/modelRefine.h index ed1267f984..32c897ff70 100644 --- a/src/Mod/Part/App/modelRefine.h +++ b/src/Mod/Part/App/modelRefine.h @@ -36,12 +36,15 @@ #include #include #include +#include namespace ModelRefine { - typedef std::vector FaceVectorType; - typedef std::vector EdgeVectorType; + typedef std::vector FaceVectorType; + typedef std::vector EdgeVectorType; + typedef std::vector ShapeVectorType; + typedef std::pair ShapePairType; void getFaceEdges(const TopoDS_Face &face, EdgeVectorType &edges); void boundaryEdges(const FaceVectorType &faces, EdgeVectorType &edgesOut); @@ -147,10 +150,16 @@ namespace ModelRefine bool process(); const TopoDS_Shell& getShell() const {return workShell;} bool isModified(){return modifiedSignal;} + const std::vector& getModifiedShapes() const + {return modifiedShapes;} + const ShapeVectorType& getDeletedShapes() const + {return deletedShapes;} private: TopoDS_Shell workShell; std::vector typeObjects; + std::vector modifiedShapes; + ShapeVectorType deletedShapes; bool modifiedSignal; }; } @@ -170,5 +179,23 @@ GeomAbs_OffsetSurface, GeomAbs_OtherSurface }; */ +namespace Part { +class BRepBuilderAPI_RefineModel : public BRepBuilderAPI_MakeShape +{ +public: + BRepBuilderAPI_RefineModel(const TopoDS_Shape&); + void Build(); + const TopTools_ListOfShape& Modified(const TopoDS_Shape& S); + Standard_Boolean IsDeleted(const TopoDS_Shape& S); + +private: + void LogModifications(const ModelRefine::FaceUniter& uniter); + +private: + TopTools_DataMapOfShapeListOfShape myModified; + TopTools_ListOfShape myEmptyList; + TopTools_ListOfShape myDeleted; +}; +} #endif // MODELREFINE_H diff --git a/src/Mod/Part/Gui/DlgSettingsGeneral.cpp b/src/Mod/Part/Gui/DlgSettingsGeneral.cpp index 61bce31f2f..a9c917a86e 100644 --- a/src/Mod/Part/Gui/DlgSettingsGeneral.cpp +++ b/src/Mod/Part/Gui/DlgSettingsGeneral.cpp @@ -69,6 +69,7 @@ void DlgSettingsGeneral::saveSettings() Interface_Static::SetCVal("write.step.unit","MM"); break; } + ui->checkBooleanRefine->onSave(); } void DlgSettingsGeneral::loadSettings() @@ -77,6 +78,7 @@ void DlgSettingsGeneral::loadSettings() .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part"); int unit = hGrp->GetInt("Unit", 0); ui->comboBoxUnits->setCurrentIndex(unit); + ui->checkBooleanRefine->onRestore(); } /** diff --git a/src/Mod/Part/Gui/DlgSettingsGeneral.ui b/src/Mod/Part/Gui/DlgSettingsGeneral.ui index 4bca9519f0..4ea3f5222d 100644 --- a/src/Mod/Part/Gui/DlgSettingsGeneral.ui +++ b/src/Mod/Part/Gui/DlgSettingsGeneral.ui @@ -1,10 +1,8 @@ - - - - + + PartGui::DlgSettingsGeneral - - + + 0 0 @@ -12,73 +10,54 @@ 333 - + General - - - 9 - - - 6 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - + + + + Export - - + + 9 - + 6 - - + + - + Millimeter - + Meter - + Inch - - - + + + Units for export of STEP/IGES - + - + Qt::Horizontal - + 40 20 @@ -89,9 +68,50 @@ + + + + Boolean operation + + + + + + Automatically refine model after boolean operation + + + RefineModel + + + Mod/Part/Boolean + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + - + + + Gui::PrefCheckBox + QCheckBox +
Gui/PrefWidgets.h
+
+
From 4f154d399366abb41efa6517997b4d42bfdd9d74 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 4 Jun 2012 22:58:37 +0200 Subject: [PATCH 313/351] 0000727: Keep faces colors on boolean operations --- src/Mod/Part/App/modelRefine.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/modelRefine.cpp b/src/Mod/Part/App/modelRefine.cpp index 516cf0551b..25bb9378ac 100644 --- a/src/Mod/Part/App/modelRefine.cpp +++ b/src/Mod/Part/App/modelRefine.cpp @@ -617,6 +617,15 @@ bool FaceUniter::process() sew.Add(*sewIt); sew.Perform(); workShell = TopoDS::Shell(sew.SewedShape()); + // update the list of modifications + for (std::vector::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it) + { + if (sew.IsModified(it->second)) + { + it->second = sew.Modified(it->second); + break; + } + } } else { @@ -638,13 +647,25 @@ bool FaceUniter::process() faceFixer.Perform(); } workShell = TopoDS::Shell(edgeFuse.Shape()); + // update the list of modifications + TopTools_DataMapOfShapeShape faceMap; + edgeFuse.Faces(faceMap); + for (std::vector::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it) + { + if (faceMap.IsBound(it->second)) + { + const TopoDS_Shape& value = faceMap.Find(it->second); + if (!value.IsSame(it->second)) + it->second = value; + } + } } return true; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// -//TODO: Implement a way to log all modifications +//BRepBuilderAPI_RefineModel implement a way to log all modifications on the faces Part::BRepBuilderAPI_RefineModel::BRepBuilderAPI_RefineModel(const TopoDS_Shape& shape) { From 8a92115ec6a47103acd5f0c957860af2e85d1124 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 4 Jun 2012 18:08:10 -0300 Subject: [PATCH 314/351] Arch: more bugfixing --- src/Mod/Arch/ArchBuilding.py | 44 +++++++--------------------------- src/Mod/Arch/ArchFloor.py | 22 +++++++++++++---- src/Mod/Arch/ArchSite.py | 46 ++++++++---------------------------- src/Mod/Arch/ArchWall.py | 16 +++++++++---- 4 files changed, 46 insertions(+), 82 deletions(-) diff --git a/src/Mod/Arch/ArchBuilding.py b/src/Mod/Arch/ArchBuilding.py index 4b0011b34d..0d6d5cc403 100644 --- a/src/Mod/Arch/ArchBuilding.py +++ b/src/Mod/Arch/ArchBuilding.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchCommands +import FreeCAD,FreeCADGui,Draft,ArchCommands,ArchFloor from PyQt4 import QtCore from DraftTools import translate @@ -56,7 +56,7 @@ class _CommandBuilding: FreeCADGui.doCommand("import Arch") FreeCADGui.doCommand("obj = Arch.makeBuilding()") FreeCADGui.doCommand("Arch.copyProperties(FreeCAD.ActiveDocument."+sel[0].Name+",obj)") - FreeCADGui.doCommand("FreeCAD.ActiveDocument.removeObject("+sel[0].Name+")") + FreeCADGui.doCommand('FreeCAD.ActiveDocument.removeObject("'+sel[0].Name+'")') FreeCAD.ActiveDocument.commitTransaction() ok = True if not ok: @@ -73,47 +73,19 @@ class _CommandBuilding: FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() -class _Building: +class _Building(ArchFloor._Floor): "The Building object" def __init__(self,obj): + ArchFloor._Floor.__init__(self,obj) self.Type = "Building" - obj.Proxy = self - self.Object = obj - - def execute(self,obj): - self.Object = obj - - def onChanged(self,obj,prop): - pass - - def addObject(self,child): - if hasattr(self,"Object"): - g = self.Object.Group - if not child in g: - g.append(child) - self.Object.Group = g - - def removeObject(self,child): - if hasattr(self,"Object"): - g = self.Object.Group - if child in g: - g.remove(child) - self.Object.Group = g - -class _ViewProviderBuilding: + obj.setEditorMode('Height',2) + +class _ViewProviderBuilding(ArchFloor._ViewProviderFloor): "A View Provider for the Building object" def __init__(self,vobj): - vobj.Proxy = self + ArchFloor._ViewProviderFloor.__init__(self,vobj) def getIcon(self): return ":/icons/Arch_Building_Tree.svg" - def attach(self,vobj): - self.Object = vobj.Object - return - - def claimChildren(self): - return self.Object.Group - - FreeCADGui.addCommand('Arch_Building',_CommandBuilding()) diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index 922d8aca0c..f7ccab17ae 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -57,7 +57,7 @@ class _CommandFloor: FreeCADGui.doCommand("import Arch") FreeCADGui.doCommand("obj = Arch.makeFloor()") FreeCADGui.doCommand("Arch.copyProperties(FreeCAD.ActiveDocument."+sel[0].Name+",obj)") - FreeCADGui.doCommand("FreeCAD.ActiveDocument.removeObject("+sel[0].Name+")") + FreeCADGui.doCommand('FreeCAD.ActiveDocument.removeObject("'+sel[0].Name+'")') FreeCAD.ActiveDocument.commitTransaction() ok = True if not ok: @@ -74,7 +74,7 @@ class _CommandFloor: FreeCAD.ActiveDocument.recompute() class _Floor: - "The Cell object" + "The Floor object" def __init__(self,obj): obj.addProperty("App::PropertyLength","Height","Base", str(translate("Arch","The height of this floor"))) @@ -82,11 +82,17 @@ class _Floor: obj.Proxy = self self.Object = obj + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + def execute(self,obj): - self.Object = obj + pass def onChanged(self,obj,prop): - pass + self.Object = obj def addObject(self,child): if hasattr(self,"Object"): @@ -103,7 +109,7 @@ class _Floor: self.Object.Group = g class _ViewProviderFloor: - "A View Provider for the Cell object" + "A View Provider for the Floor object" def __init__(self,vobj): vobj.Proxy = self @@ -117,4 +123,10 @@ class _ViewProviderFloor: def claimChildren(self): return self.Object.Group + def __getstate__(self): + return None + + def __setstate__(self,state): + return None + FreeCADGui.addCommand('Arch_Floor',_CommandFloor()) diff --git a/src/Mod/Arch/ArchSite.py b/src/Mod/Arch/ArchSite.py index d05a7e8ffa..69cfda8bab 100644 --- a/src/Mod/Arch/ArchSite.py +++ b/src/Mod/Arch/ArchSite.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,Draft,ArchCommands +import FreeCAD,FreeCADGui,Draft,ArchCommands,ArchFloor from PyQt4 import QtCore from DraftTools import translate @@ -56,7 +56,7 @@ class _CommandSite: FreeCADGui.doCommand("import Arch") FreeCADGui.doCommand("obj = Arch.makeSite()") FreeCADGui.doCommand("Arch.copyProperties(FreeCAD.ActiveDocument."+sel[0].Name+",obj)") - FreeCADGui.doCommand("FreeCAD.ActiveDocument.removeObject("+sel[0].Name+")") + FreeCADGui.doCommand('FreeCAD.ActiveDocument.removeObject("'+sel[0].Name+'")') nobj = makeSite() ArchCommands.copyProperties(sel[0],nobj) @@ -75,47 +75,21 @@ class _CommandSite: FreeCADGui.doCommand("Arch.makeSite("+ss+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() - -class _Site: + +class _Site(ArchFloor._Floor): "The Site object" def __init__(self,obj): + ArchFloor._Floor.__init__(self,obj) self.Type = "Site" - obj.Proxy = self - self.Object = obj - - def execute(self,obj): - self.Object = obj - - def onChanged(self,obj,prop): - pass - - def addObject(self,child): - if hasattr(self,"Object"): - g = self.Object.Group - if not child in g: - g.append(child) - self.Object.Group = g - - def removeObject(self,child): - if hasattr(self,"Object"): - g = self.Object.Group - if child in g: - g.remove(child) - self.Object.Group = g - -class _ViewProviderSite: + obj.setEditorMode('Height',2) + +class _ViewProviderSite(ArchFloor._ViewProviderFloor): "A View Provider for the Site object" def __init__(self,vobj): - vobj.Proxy = self + ArchFloor._ViewProviderFloor.__init__(self,vobj) def getIcon(self): return ":/icons/Arch_Site_Tree.svg" - def attach(self,vobj): - self.Object = vobj.Object - return - - def claimChildren(self): - return self.Object.Group - + FreeCADGui.addCommand('Arch_Site',_CommandSite()) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 0bfa8f6e48..19b3b29bad 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -265,6 +265,7 @@ class _Wall(ArchComponent.Component): self.createGeometry(obj) def onChanged(self,obj,prop): + print prop if prop in ["Base","Height","Width","Align","Additions","Subtractions"]: self.createGeometry(obj) @@ -373,7 +374,8 @@ class _Wall(ArchComponent.Component): base = temp for app in obj.Additions: - base = base.fuse(app.Shape) + if hasattr(app,"Shape"): + base = base.fuse(app.Shape) app.ViewObject.hide() #to be removed for hole in obj.Subtractions: if Draft.getType(hole) == "Window": @@ -393,10 +395,14 @@ class _Wall(ArchComponent.Component): hole.ViewObject.hide() # to be removed if base: - base.removeSplitter() - obj.Shape = base - if not DraftGeomUtils.isNull(pl): - obj.Placement = pl + if not base.isNull(): + try: + base.removeSplitter() + except: + print "Wall: Error removing splitter" + obj.Shape = base + if not DraftGeomUtils.isNull(pl): + obj.Placement = pl class _ViewProviderWall(ArchComponent.ViewProviderComponent): "A View Provider for the Wall object" From e1c3f5ed58c9a5ca5f6db9a694b77fa942c74475 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 4 Jun 2012 23:06:12 -0300 Subject: [PATCH 315/351] Arch: Fixed bug in wall --- src/Mod/Arch/ArchWall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 19b3b29bad..a6e1cc1f73 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -397,7 +397,7 @@ class _Wall(ArchComponent.Component): if base: if not base.isNull(): try: - base.removeSplitter() + base = base.removeSplitter() except: print "Wall: Error removing splitter" obj.Shape = base From a589b39872ce80947700d95b99412cb6fec491ff Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 5 Jun 2012 00:00:43 -0300 Subject: [PATCH 316/351] Arch: Small improvements to section plane --- src/Mod/Arch/ArchSectionPlane.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 8f695d7082..ea9fac7dcf 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -41,6 +41,7 @@ def makeSectionPlane(objectslist=None): elif o.isDerivedFrom("App::DocumentObjectGroup"): g.append(o) obj.Objects = g + return obj def makeSectionView(section): """makeSectionView(section) : Creates a Drawing view of the given Section Plane @@ -55,15 +56,14 @@ def makeSectionView(section): template = Draft.getParam("template") if not template: template = FreeCAD.getResourceDir()+'Mod/Drawing/Templates/A3_Landscape.svg' - page.ViewObject.HintOffsetX = 200 - page.ViewObject.HintOffsetY = 100 - page.ViewObject.HintScale = 20 page.Template = template view = FreeCAD.ActiveDocument.addObject("Drawing::FeatureViewPython","View") page.addObject(view) _ArchDrawingView(view) view.Source = section + view.Label = str(translate("Arch","View of"))+" "+section.Name + return view class _CommandSectionPlane: "the Arch SectionPlane command definition" From fac54a4306825c3dd2aeda9d1c836bdc0fa83a6c Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Jun 2012 11:55:45 +0200 Subject: [PATCH 317/351] Method Part.Edge.split added --- src/Mod/Part/App/TopoShapeEdgePy.xml | 12 ++- src/Mod/Part/App/TopoShapeEdgePyImp.cpp | 103 ++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShapeEdgePy.xml b/src/Mod/Part/App/TopoShapeEdgePy.xml index 873b3fb726..40def10305 100644 --- a/src/Mod/Part/App/TopoShapeEdgePy.xml +++ b/src/Mod/Part/App/TopoShapeEdgePy.xml @@ -24,7 +24,12 @@ Vector = valueAt(pos) - Get the point at the given parameter [0|Length] if defined - + + + Float = parameterAt(Vertex) - Get the parameter at the given vertex if lying on the edge + + + Vector = normalAt(pos) - Get the normal vector at the given parameter [0|Length] if defined @@ -64,6 +69,11 @@ Discretizes the edge using a given deflection or number of points and returns a list of points + + + Splits the edge at the given parameter values and builds a wire out of it + + Set or get the tolerance of the vertex diff --git a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp index ec5bc09054..329c6bd6c6 100644 --- a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp @@ -23,10 +23,13 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include # include +# include +# include # include # include # include @@ -47,6 +50,7 @@ # include # include # include +# include # include #endif @@ -55,12 +59,14 @@ #include #include +#include #include #include #include "TopoShape.h" #include "TopoShapeFacePy.h" #include "TopoShapeVertexPy.h" +#include "TopoShapeWirePy.h" #include "TopoShapeEdgePy.h" #include "TopoShapeEdgePy.cpp" @@ -185,6 +191,35 @@ PyObject* TopoShapeEdgePy::valueAt(PyObject *args) return new Base::VectorPy(new Base::Vector3d(V.X(),V.Y(),V.Z())); } +PyObject* TopoShapeEdgePy::parameterAt(PyObject *args) +{ + PyObject* pnt; + PyObject* face=0; + if (!PyArg_ParseTuple(args, "O!|O!",&TopoShapeVertexPy::Type,&pnt, + &TopoShapeFacePy::Type,&face)) + return 0; + + try { + const TopoDS_Shape& v = static_cast(pnt)->getTopoShapePtr()->_Shape; + const TopoDS_Edge& e = TopoDS::Edge(getTopoShapePtr()->_Shape); + + if (face) { + const TopoDS_Shape& f = static_cast(face)->getTopoShapePtr()->_Shape; + Standard_Real par = BRep_Tool::Parameter(TopoDS::Vertex(v), e, TopoDS::Face(f)); + return PyFloat_FromDouble(par); + } + else { + Standard_Real par = BRep_Tool::Parameter(TopoDS::Vertex(v), e); + return PyFloat_FromDouble(par); + } + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + PyErr_SetString(PyExc_Exception, e->GetMessageString()); + return 0; + } +} + PyObject* TopoShapeEdgePy::tangentAt(PyObject *args) { double u; @@ -443,6 +478,74 @@ PyObject* TopoShapeEdgePy::discretize(PyObject *args) return 0; } +PyObject* TopoShapeEdgePy::split(PyObject *args) +{ + PyObject* float_or_list; + if (!PyArg_ParseTuple(args, "O", &float_or_list)) + return 0; + + try { + BRepAdaptor_Curve adapt(TopoDS::Edge(getTopoShapePtr()->_Shape)); + Standard_Real f = adapt.FirstParameter(); + Standard_Real l = adapt.LastParameter(); + + std::vector par; + par.push_back(f); + if (PyFloat_Check(float_or_list)) { + double val = PyFloat_AsDouble(float_or_list); + if (val == f || val == l) { + PyErr_SetString(PyExc_ValueError, "Cannot split edge at start or end point"); + return 0; + } + else if (val < f || val > l) { + PyErr_SetString(PyExc_ValueError, "Value out of parameter range"); + return 0; + } + par.push_back(val); + } + else if (PyList_Check(float_or_list)) { + Py::List list(float_or_list); + for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { + double val = (double)Py::Float(*it); + if (val == f || val == l) { + PyErr_SetString(PyExc_ValueError, "Cannot split edge at start or end point"); + return 0; + } + else if (val < f || val > l) { + PyErr_SetString(PyExc_ValueError, "Value out of parameter range"); + return 0; + } + par.push_back(val); + } + } + else { + PyErr_SetString(PyExc_TypeError, "Either float or list of floats expected"); + return 0; + } + + par.push_back(l); + std::sort(par.begin(), par.end()); + + BRepBuilderAPI_MakeWire mkWire; + Handle_Geom_Curve c = adapt.Curve().Curve(); + std::vector::iterator end = par.end() - 1; + for (std::vector::iterator it = par.begin(); it != end; ++it) { + BRepBuilderAPI_MakeEdge mkBuilder(c, it[0], it[1]); + mkWire.Add(mkBuilder.Edge()); + } + + return new TopoShapeWirePy(new TopoShape(mkWire.Shape())); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + PyErr_SetString(PyExc_Exception, e->GetMessageString()); + return 0; + } + + PyErr_SetString(PyExc_Exception, "Geometry is not a curve"); + return 0; +} + PyObject* TopoShapeEdgePy::setTolerance(PyObject *args) { double tol; From ff187c13a9cb4758a8e86309d3676a086c7c8cc8 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Jun 2012 13:42:21 +0200 Subject: [PATCH 318/351] 0000734: Cannot export Drawing Page to SVG --- src/Gui/ApplicationPy.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index 9a2a51af4e..6f0bfd5ba2 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -362,10 +362,18 @@ PyObject* Application::sExport(PyObject * /*self*/, PyObject *args,PyObject * /* if (ext == QLatin1String("iv") || ext == QLatin1String("wrl") || ext == QLatin1String("vrml") || ext == QLatin1String("wrz") || ext == QLatin1String("svg") || ext == QLatin1String("idtf")) { - QString cmd = QString::fromLatin1( - "Gui.getDocument(\"%1\").ActiveView.dump(\"%2\")" - ).arg(QLatin1String(doc->getName())).arg(fi.absoluteFilePath()); - Base::Interpreter().runString(cmd.toUtf8()); + Gui::Document* gui_doc = Application::Instance->getDocument(doc); + std::list view3d = gui_doc->getMDIViewsOfType(View3DInventor::getClassTypeId()); + if (view3d.empty()) { + PyErr_SetString(PyExc_Exception, "Cannot export to SVG because document doesn't have a 3d view"); + return 0; + } + else { + QString cmd = QString::fromLatin1( + "Gui.getDocument(\"%1\").mdiViewsOfType('Gui::View3DInventor')[0].dump(\"%2\")" + ).arg(QLatin1String(doc->getName())).arg(fi.absoluteFilePath()); + Base::Interpreter().runString(cmd.toUtf8()); + } } else if (ext == QLatin1String("pdf")) { Gui::Document* gui_doc = Application::Instance->getDocument(doc); From 3bd569252cd9b2d38b0f0da2f2a2c17e54ed0ac1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Jun 2012 13:55:56 +0200 Subject: [PATCH 319/351] Raise exception in Drawing module for unsupported objects --- src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp b/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp index 07aa2c4717..a4cb65ef90 100644 --- a/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp +++ b/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp @@ -139,6 +139,10 @@ exporter(PyObject *self, PyObject *args) str_out.close(); break; } + else { + PyErr_SetString(PyExc_TypeError, "Export as SVG of this object type is not supported by Drawing module"); + return 0; + } } } } PY_CATCH; From 73ee872301b1a51c55f2dd97ac1b978fe85a6e53 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 5 Jun 2012 12:37:17 -0300 Subject: [PATCH 320/351] Arch: Friendlier pycollada warning --- src/Mod/Arch/InitGui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 4c5384ff08..6267d9077e 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -105,7 +105,7 @@ FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") try: import collada except: - FreeCAD.Console.PrintError("pycollada not found, no collada support.\n") + FreeCAD.Console.PrintMessage(str(DraftTools.translate("arch","pycollada not found, collada support will be disabled.\n"))) else: FreeCAD.addImportType("Collada (*.dae)","importDAE") FreeCAD.addExportType("Collada (*.dae)","importDAE") From a26daf5d231b8881044b555b1f97d1c0b53a1109 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 5 Jun 2012 13:31:34 -0300 Subject: [PATCH 321/351] Arch: More bugfixes --- src/Mod/Arch/ArchComponent.py | 15 +++++++++++---- src/Mod/Arch/ArchSectionPlane.py | 1 + src/Mod/Arch/ArchVRM.py | 4 ++-- src/Mod/Arch/ArchWall.py | 15 ++++++++++++--- src/Mod/Arch/ArchWindow.py | 2 ++ 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index 13ad37204e..5e0206fe93 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -308,16 +308,23 @@ class ViewProviderComponent: return False class ArchSelectionObserver: - def __init__(self,origin,watched): + def __init__(self,origin,watched,hide=True,nextCommand=None): self.origin = origin self.watched = watched + self.hide = hide + self.nextCommand = nextCommand def addSelection(self,document, object, element, position): if object == self.watched.Name: if not element: print "closing Sketch edit" - self.origin.ViewObject.Transparency = 0 - self.origin.ViewObject.Selectable = True - self.watched.ViewObject.hide() + if self.hide: + self.origin.ViewObject.Transparency = 0 + self.origin.ViewObject.Selectable = True + self.watched.ViewObject.hide() FreeCADGui.activateWorkbench("ArchWorkbench") FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver) + if self.nextCommand: + FreeCADGui.Selection.clearSelection() + FreeCADGui.Selection.addSelection(self.watched) + FreeCADGui.runCommand(self.nextCommand) del FreeCAD.ArchObserver diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index ea9fac7dcf..aa1d8bb990 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -234,6 +234,7 @@ class _ArchDrawingView: svgf = Drawing.projectToSVG(base,DraftVecUtils.neg(direction)) if svgf: svgf = svgf.replace('stroke-width="0.35"','stroke-width="' + str(linewidth) + 'px"') + svgf = svgf.replace('stroke-width:0.01','stroke-width:' + str(linewidth) + 'px') svg += svgf result = '' diff --git a/src/Mod/Arch/ArchVRM.py b/src/Mod/Arch/ArchVRM.py index 2de8ad0b3b..2eefd8f279 100644 --- a/src/Mod/Arch/ArchVRM.py +++ b/src/Mod/Arch/ArchVRM.py @@ -574,7 +574,7 @@ class Renderer: svg += '" ' svg += 'stroke="#000000" ' svg += 'stroke-width="' + str(linewidth) + '" ' - svg += 'style="stroke-width:0.01;' + svg += 'style="stroke-width:' + str(linewidth) + ';' svg += 'stroke-miterlimit:1;' svg += 'stroke-linejoin:round;' svg += 'stroke-dasharray:none;' @@ -598,7 +598,7 @@ class Renderer: svg += '" ' svg += 'stroke="#000000" ' svg += 'stroke-width="' + str(linewidth) + '" ' - svg += 'style="stroke-width:0.01;' + svg += 'style="stroke-width:' + str(linewidth) + ';' svg += 'stroke-miterlimit:1;' svg += 'stroke-linejoin:round;' svg += 'stroke-dasharray:none;' diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index a6e1cc1f73..25fb891eee 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -256,7 +256,10 @@ class _Wall(ArchComponent.Component): str(translate("Arch","The alignment of this wall on its base object, if applicable"))) obj.addProperty("App::PropertyVector","Normal","Base", str(translate("Arch","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)"))) + obj.addProperty("App::PropertyBool","ForceWire","Base", + str(translate("Arch","If True, if this wall is based on a face, it will use its border wire as trace, and disconsider the face."))) obj.Align = ['Left','Right','Center'] + obj.ForceWire = False self.Type = "Wall" obj.Width = 0.1 obj.Height = 0 @@ -265,7 +268,6 @@ class _Wall(ArchComponent.Component): self.createGeometry(obj) def onChanged(self,obj,prop): - print prop if prop in ["Base","Height","Width","Align","Additions","Subtractions"]: self.createGeometry(obj) @@ -359,7 +361,7 @@ class _Wall(ArchComponent.Component): base = obj.Base.Shape.copy() if base.Solids: pass - elif base.Faces: + elif base.Faces and (not obj.ForceWire): if height: norm = normal.multiply(height) base = base.extrude(norm) @@ -372,6 +374,13 @@ class _Wall(ArchComponent.Component): else: temp = sh base = temp + elif base.Edges: + wire = Part.Wire(base.Edges) + sh = getbase(wire) + if sh: + base = sh + else: + FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object"))) for app in obj.Additions: if hasattr(app,"Shape"): @@ -399,7 +408,7 @@ class _Wall(ArchComponent.Component): try: base = base.removeSplitter() except: - print "Wall: Error removing splitter" + FreeCAD.Console.PrintError(str(translate("Arch","Error removing splitter from wall shape"))) obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 2c20b03ca2..2f593257fb 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -92,6 +92,8 @@ class _CommandWindow: if Draft.getType(sel[0]) == "Wall": FreeCADGui.activateWorkbench("SketcherWorkbench") FreeCADGui.runCommand("Sketcher_NewSketch") + FreeCAD.ArchObserver = ArchComponent.ArchSelectionObserver(sel[0],FreeCAD.ActiveDocument.Objects[-1],hide=False,nextCommand="Arch_Window") + FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver) else: FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Window"))) FreeCADGui.doCommand("import Arch") From 19e747d770268064c350e22ab8bfa6a97e746d36 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 5 Jun 2012 16:33:01 -0300 Subject: [PATCH 322/351] 0000722: Deleting Draft dimensions --- src/Mod/Draft/Draft.py | 36 +++++++++++++++++++++++++----------- src/Mod/Draft/DraftTools.py | 2 +- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 7b1c5dc8f3..49ff4ad04b 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1782,7 +1782,6 @@ class _ViewProviderDimension: obj.Proxy = self obj.FontSize=getParam("textheight") obj.FontName=getParam("textfont") - obj.DisplayMode = ["2D","3D"] obj.ExtLines=0.3 obj.Override = '' @@ -1825,18 +1824,19 @@ class _ViewProviderDimension: if hasattr(obj.ViewObject,"DisplayMode"): if obj.ViewObject.DisplayMode == "3D": offset = DraftVecUtils.neg(offset) - if hasattr(obj.ViewObject,"TextPosition"): - if obj.ViewObject.TextPosition == Vector(0,0,0): - tbase = midpoint.add(offset) + if hasattr(obj.ViewObject,"TextPosition"): + if obj.ViewObject.TextPosition == Vector(0,0,0): + tbase = midpoint.add(offset) + else: + tbase = obj.ViewObject.TextPosition else: - tbase = obj.ViewObject.TextPosition + tbase = midpoint.add(offset) else: - tbase = midpoint.add(offset) + tbase = midpoint rot = FreeCAD.Placement(DraftVecUtils.getPlaneRotation(u,v,norm)).Rotation.Q return p1,p2,p3,p4,tbase,norm,rot def attach(self, obj): - obj.DisplayMode = ["2D","3D"] self.Object = obj.Object p1,p2,p3,p4,tbase,norm,rot = self.calcGeom(obj.Object) self.color = coin.SoBaseColor() @@ -1903,6 +1903,10 @@ class _ViewProviderDimension: self.onChanged(obj,"FontName") def updateData(self, obj, prop): + try: + dm = obj.ViewObject.DisplayMode + except: + dm = "2D" text = None if obj.Base and obj.LinkedVertices: if "Shape" in obj.Base.PropertiesList: @@ -1936,7 +1940,7 @@ class _ViewProviderDimension: self.text.string = self.text3d.string = text self.textpos.rotation = coin.SbRotation(rot[0],rot[1],rot[2],rot[3]) self.textpos.translation.setValue([tbase.x,tbase.y,tbase.z]) - if obj.ViewObject.DisplayMode == "2D": + if dm == "2D": self.coords.point.setValues([[p1.x,p1.y,p1.z], [p2.x,p2.y,p2.z], [p3.x,p3.y,p3.z], @@ -1958,6 +1962,7 @@ class _ViewProviderDimension: self.coord2.point.setValue((p3.x,p3.y,p3.z)) def onChanged(self, vp, prop): + self.Object = vp.Object if prop == "FontSize": self.font.size = vp.FontSize self.font3d.size = vp.FontSize*100 @@ -1969,13 +1974,20 @@ class _ViewProviderDimension: elif prop == "LineWidth": self.drawstyle.lineWidth = vp.LineWidth else: + self.drawstyle.lineWidth = vp.LineWidth self.updateData(vp.Object, None) def getDisplayModes(self,obj): return ["2D","3D"] def getDefaultDisplayMode(self): - return "2D" + if hasattr(self,"defaultmode"): + return self.defaultmode + else: + return "2D" + + def setDisplayMode(self,mode): + return mode def getIcon(self): if self.Object.Base: @@ -2034,10 +2046,12 @@ class _ViewProviderDimension: """ def __getstate__(self): - return None + return self.Object.ViewObject.DisplayMode def __setstate__(self,state): - return None + if state: + self.defaultmode = state + self.setDisplayMode(state) class _AngularDimension: "The AngularDimension object" diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 559e75e268..a5f52576c9 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -1653,7 +1653,7 @@ class Dimension(Creator): if self.dir: point = self.node[0].add(DraftVecUtils.project(point.sub(self.node[0]),self.dir)) self.node.append(point) - print "node",self.node + #print "node",self.node self.dimtrack.update(self.node) if (len(self.node) == 2): self.point2 = self.node[1] From f4f132540c2af3bf20f724e8978afaf8724ef803 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 5 Jun 2012 18:53:48 -0300 Subject: [PATCH 323/351] Draft: Fixes in working plane --- src/Mod/Draft/DraftTools.py | 11 +++++++++++ src/Mod/Draft/DraftTrackers.py | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index a5f52576c9..06cffa4720 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -231,6 +231,17 @@ class SelectPlane: self.call = None self.doc = FreeCAD.ActiveDocument if self.doc: + sel = FreeCADGui.Selection.getSelectionEx() + if len(sel) == 1: + sel = sel[0] + if sel.HasSubObjects: + if len(sel.SubElementNames) == 1: + if "Face" in sel.SubElementNames[0]: + self.ui = FreeCADGui.draftToolBar + plane.alignToFace(sel.SubObjects[0], self.offset) + self.display(plane.axis) + self.finish() + return FreeCAD.activeDraftCommand = self self.view = Draft.get3DView() self.ui = FreeCADGui.draftToolBar diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 5223ebf667..ab556e095c 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -617,7 +617,9 @@ class gridTracker(Tracker): def set(self): Q = FreeCAD.DraftWorkingPlane.getRotation().Rotation.Q + P = FreeCAD.DraftWorkingPlane.position self.trans.rotation.setValue([Q[0],Q[1],Q[2],Q[3]]) + self.trans.translation.setValue([P.x,P.y,P.z]) self.on() def getClosestNode(self,point): From a4b593ddd38e1b7b617c279c0fb8ea3c1160bcf7 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 5 Jun 2012 20:11:47 -0300 Subject: [PATCH 324/351] Draft: Fixed concrete hatch pattern --- src/Mod/Draft/Draft_rc.py | 365 +++++++++++------- src/Mod/Draft/Resources/patterns/concrete.svg | 112 +----- 2 files changed, 234 insertions(+), 243 deletions(-) diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index e1f587ddd4..e74a2fc93b 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Tue May 22 16:46:43 2012 +# Created: Tue Jun 5 20:09:57 2012 # by: The Resource Compiler for PyQt (Qt v4.8.1) # # WARNING! All changes made in this file will be lost! @@ -117,79 +117,150 @@ qt_resource_data = "\ \x0a\x20\x20\x20\x20\x3c\x2f\x70\x61\x74\x74\x65\x72\x6e\x3e\x0a\ \x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\ \ -\x00\x00\x04\x69\ -\x00\ -\x00\x15\x07\x78\x9c\xbd\x58\xdb\x6e\x1b\x37\x10\x7d\xef\x57\x2c\ -\x36\x2f\x2d\xb0\xa1\x78\xbf\xb8\x52\x7e\xa1\x0f\x45\x3e\x40\xb0\ -\xd7\xb2\x10\x47\x0e\x24\xb5\x49\xfa\xf5\x1d\xde\x96\xb4\xe1\x59\ -\xcf\x4b\x2c\x01\xc2\x90\x7b\x20\x9e\x1d\xce\x99\x19\x72\x7b\xf9\ -\xf7\xf0\xe9\xb7\x61\xd8\xde\xcd\xf7\x97\x68\x80\xf9\x6d\x7f\xbd\ -\xce\xe7\x53\x1a\xc0\xe7\x78\xb7\x1b\x6f\x9f\x4e\xb7\xe7\xf9\x3a\ -\x8f\x75\xb2\x60\x3e\x9f\x8e\xd7\xcb\x6e\xfc\xe7\x32\x9f\xff\xfe\ -\xb6\xbf\x9d\xff\x3a\x7d\xbe\x34\xd0\x8f\xdd\xc8\x97\xc1\xcf\x7e\ -\xf0\xfd\x78\x77\x7d\xd8\x8d\xcc\x2c\x33\x0f\xf3\xf1\xf0\x70\x4d\ -\x53\x9f\xca\xdc\xf6\x50\x1f\x0e\xc3\xe5\xfa\xf3\x71\xde\x8d\xf7\ -\xc7\xc7\xc7\x9b\xd3\xd3\x69\xfe\x13\x66\xce\x4f\x5f\xe6\x9b\x0f\ -\x3c\x7d\xea\xf8\x63\xfa\xe7\x9b\xee\x8f\x87\xe1\x7a\xde\x9f\x2e\ -\xf7\x4f\xe7\xaf\xbb\xf1\x72\xbb\x7f\x9c\x7f\x67\x5c\xfc\xd1\x3d\ -\x8f\x2f\x78\x50\x9a\x8b\x65\xe5\xec\x84\x87\x06\x19\x06\xc0\x7c\ -\x1d\x0c\x53\xc6\x09\x2d\xfd\xa4\x98\x91\xd2\x07\x6d\x87\xfd\x20\ -\x98\x52\x41\x7a\xe3\xa6\xc5\x1a\xf8\x20\xe0\xfb\x51\x32\xeb\x60\ -\x28\xcc\xc4\x57\x60\x3d\xea\xbf\xb1\x5f\x35\x52\x8b\x4c\xa4\xd7\ -\x7c\x1c\x36\x6f\xf1\x13\x9a\x09\x0e\x04\xd5\x64\x99\x97\x56\x5b\ -\x2b\x80\x9f\x62\x32\x72\x36\x76\x5a\xac\xca\xcf\xb2\x38\x74\x42\ -\xc0\xca\x38\xac\x47\xa1\xfc\x24\x8d\x9f\x97\xd9\x7f\x9c\x05\xa5\ -\x2c\x0f\xc0\x8f\xb3\xe4\x53\xe3\xd4\xd4\xcc\xca\x50\x94\xb5\x61\ -\xe9\x35\x5c\x07\x43\x19\x6a\x02\x43\xe9\x59\xd9\x61\x61\x99\xe4\ -\x02\x5c\x08\x0c\x25\x93\x2a\xf2\x0e\xd3\x62\x55\x7e\x9a\x69\x0b\ -\x70\x0b\x0b\xe3\xa8\x0e\x84\xb2\xb3\x04\x76\x40\xc9\xc4\x68\x97\ -\x93\xe4\x8c\x7b\xa3\x82\x4e\xfe\xd3\xa1\x6c\x7b\x33\x2b\x3f\xf0\ -\xb3\xcf\xa4\xf8\x2a\xb0\xc7\xa1\x1c\x3d\x81\xa3\xd2\xcc\xc5\x97\ -\xd7\x93\x74\x20\x12\xe7\xa4\x49\x1c\x65\x8e\xf1\xb4\xb4\x8a\x6a\ -\x0b\xae\x71\x34\x49\x57\x89\x22\x8e\xeb\x60\x18\x43\x43\x51\x89\ -\xe6\x4c\xc4\x35\xe4\x14\x98\x82\xa8\xe6\x5e\x24\x86\xa2\xea\x13\ -\x48\xe4\xfd\xf3\x8d\x61\xa6\x95\x18\xe2\xb8\x0e\x86\x32\xa4\xe8\ -\x44\x97\xdd\xd0\x93\xf2\xcc\x69\x2b\x8a\x4e\xea\x72\xaf\x32\xd4\ -\x29\xc6\xb2\x0f\x51\x5c\x07\x43\x19\x52\x74\xa2\x04\x13\x96\xc7\ -\x94\x05\x5c\x8d\xb3\x59\x27\x8a\x25\xc7\xc0\xec\x62\x55\x7e\x8e\ -\xc5\x61\x8c\xbc\x15\x54\x07\x42\xd9\x51\x74\x22\x8b\x00\x55\xf4\ -\x9f\x34\x86\x2b\x93\xf2\x74\x64\x9c\xb4\x5d\xad\xca\xae\x64\x3c\ -\x9b\xd2\x34\x86\xea\x40\x28\x3b\x8a\x42\xb4\x60\x21\xee\x01\x14\ -\x02\x58\x42\x3b\x1f\xb2\x42\x7c\x76\x46\x8c\xfc\x6a\xb6\x2c\x98\ -\x44\x91\x15\x82\xe3\x3a\x18\xc6\xd0\x52\x14\xa2\x2c\xcb\x69\x42\ -\x1a\xe6\xa2\xfb\x5c\x22\x58\x8a\x5f\x0c\xfc\x6a\xb6\xf0\x73\xd5\ -\x37\x6b\xb8\x0e\x86\x12\xa4\x08\x24\x26\xc2\x49\x4b\x50\x89\x13\ -\x2e\x6b\xc3\xc2\x4c\xfa\x6d\x3e\x8b\x33\xaf\x3c\x29\x0f\x50\x02\ -\x94\xf8\x17\x8e\x15\x89\x89\xc0\x82\x29\x75\x82\xd0\x09\x90\x1a\ -\x81\x35\x76\x94\xf8\x17\x25\xc2\xec\x24\x3c\xe8\xd4\x38\x23\x73\ -\x9d\x48\xda\x4f\x99\xab\x9a\x6d\x03\x7d\x49\x6a\xab\xb8\x0e\x86\ -\x32\xa4\x68\x00\xaa\xab\xcd\x21\x06\x9a\x0f\x20\x01\x9d\x77\x31\ -\x67\x78\x19\x57\xae\x66\xdb\xcf\xa4\xc6\x5c\xc8\x70\x5c\x07\xc3\ -\x18\x3a\x92\x06\x96\x72\x23\x14\xb3\x42\x8a\x52\x25\xde\x66\xe8\ -\x69\x0c\xd7\x72\xb0\xa3\x88\x00\x2a\x6d\x52\xbf\x8d\x4a\x70\x22\ -\x28\x29\x89\xdd\x94\xa4\x75\x53\x72\x8d\x21\x45\x25\x7a\xf1\x61\ -\xec\xab\x52\xc3\x9c\x54\x62\x4a\xfd\x5d\xac\x96\x87\xb9\x5a\xda\ -\x65\x0c\xd5\x81\x50\x76\x14\x95\xa8\x90\xbb\x51\x37\x41\xbd\xe0\ -\xbc\xa4\xb9\x9a\x43\xd5\xb4\x58\x8d\x9d\xa9\x1b\x87\xa3\x3a\x10\ -\xca\x8e\xa2\x10\x59\x8a\xe1\x73\xdf\x41\xca\xcb\x82\x9c\x16\xab\ -\xb2\x33\x4d\x9a\x38\xca\xbc\xad\x5f\x4f\x51\x47\xd7\x89\x7a\xc8\ -\x35\x10\x7b\x79\x67\x75\xa9\xec\x8b\xd5\xf2\x5f\x7a\x9b\xa4\x4b\ -\x1c\xd6\xa3\x50\x7e\x24\x6d\xe4\x18\x89\x1d\x80\x62\xf0\x4a\x5c\ -\xe5\xfc\xe2\x79\x69\x21\xab\xd5\x94\x61\x3b\xf1\x62\xb0\x1e\x85\ -\xf2\x23\x29\x23\x9f\x33\x54\x4c\xd0\x9d\xfb\x7e\x79\x83\xe2\x49\ -\xc2\x50\x85\x1c\xb4\x01\x29\xf0\xb2\xef\xf2\x01\x21\x95\xf5\x6a\ -\x36\xef\x85\x7a\xc0\x59\xc3\x75\x30\x94\x20\x49\x1b\xa6\x64\xac\ -\x98\x1b\x8c\xaf\xc7\xc8\x77\x29\x6f\x81\x22\x0f\xb9\x64\x01\xcd\ -\x78\x23\xf8\x2e\x1e\x0c\x14\x7d\x80\x6a\x4b\x12\x85\xfe\xc5\xf0\ -\xf7\x6d\xf1\x02\xe9\x84\x01\x39\x59\x7b\x13\xe0\x94\x60\xfa\xbb\ -\x02\xe3\x9c\x07\xc1\xbc\x42\x10\x8e\x24\x06\x6a\x58\x29\xbf\x18\ -\xac\x43\xa1\xfc\x28\x22\xd1\x70\xba\x9d\xb4\x01\x92\x3c\xb7\x57\ -\xa9\xad\x8c\x3f\x2d\xe5\xe5\x3a\xf6\x7c\x3a\xcf\xa2\x4b\x93\x0e\ -\x10\xe5\x1a\x25\xc0\x01\xca\x05\x58\x5e\xbc\xdf\x35\x4a\xe0\x94\ -\xf8\x8f\xa7\xd6\x00\x1f\x68\x4d\x80\x62\xbd\x46\x79\x76\xb8\xaf\ -\xe6\xcb\x4b\x00\xf5\xf2\x16\xe0\x05\xb0\xc7\xa1\x1c\x7b\x09\x6c\ -\x37\x87\x72\xb1\xb9\x29\xb7\x96\xe9\xc2\x73\x93\x6f\x3c\xb7\x9b\ -\x78\x03\xfa\x3f\xe0\xde\x25\x35\ +\x00\x00\x08\xd7\ +\x3c\ +\x73\x76\x67\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\x3e\x0a\x20\x20\ +\x20\x20\x3c\x70\x61\x74\x74\x65\x72\x6e\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x69\x64\x3d\x22\x63\x6f\x6e\x63\x72\x65\x74\x65\x22\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x70\x61\x74\x74\x65\x72\x6e\x55\x6e\ +\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\ +\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x30\ +\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x3d\x22\x30\x22\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x2e\x35\x22\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\ +\x2e\x35\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x67\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x66\x69\ +\x6c\x6c\x3a\x6e\x6f\x6e\x65\x3b\x20\x73\x74\x72\x6f\x6b\x65\x3a\ +\x23\x30\x30\x30\x30\x30\x30\x3b\x20\x73\x74\x72\x6f\x6b\x65\x2d\ +\x77\x69\x64\x74\x68\x3a\x2e\x35\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x73\x63\ +\x61\x6c\x65\x28\x2e\x30\x31\x29\x22\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x69\x64\x3d\x22\x67\x33\x34\x30\x31\x22\x3e\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ +\x6d\x20\x35\x2e\x33\x35\x37\x31\x34\x32\x38\x2c\x33\x2e\x35\x32\ +\x32\x38\x39\x34\x36\x20\x61\x20\x31\x2e\x33\x33\x39\x32\x38\x35\ +\x37\x2c\x31\x2e\x33\x33\x39\x32\x38\x35\x37\x20\x30\x20\x31\x20\ +\x31\x20\x2d\x32\x2e\x36\x37\x38\x35\x37\x31\x35\x2c\x30\x20\x31\ +\x2e\x33\x33\x39\x32\x38\x35\x37\x2c\x31\x2e\x33\x33\x39\x32\x38\ +\x35\x37\x20\x30\x20\x31\x20\x31\x20\x32\x2e\x36\x37\x38\x35\x37\ +\x31\x35\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x20\x31\x34\x2e\ +\x31\x30\x37\x31\x34\x33\x2c\x36\x2e\x38\x32\x36\x34\x36\x36\x31\ +\x20\x61\x20\x33\x2e\x32\x31\x34\x32\x38\x35\x36\x2c\x33\x2e\x32\ +\x31\x34\x32\x38\x35\x36\x20\x30\x20\x31\x20\x31\x20\x2d\x36\x2e\ +\x34\x32\x38\x35\x37\x31\x31\x2c\x30\x20\x33\x2e\x32\x31\x34\x32\ +\x38\x35\x36\x2c\x33\x2e\x32\x31\x34\x32\x38\x35\x36\x20\x30\x20\ +\x31\x20\x31\x20\x36\x2e\x34\x32\x38\x35\x37\x31\x31\x2c\x30\x20\ +\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\ +\x74\x68\x20\x64\x3d\x22\x6d\x20\x31\x34\x2e\x38\x32\x31\x34\x32\ +\x38\x2c\x33\x30\x2e\x39\x33\x33\x36\x30\x39\x20\x61\x20\x30\x2e\ +\x37\x31\x34\x32\x38\x35\x37\x33\x2c\x30\x2e\x37\x31\x34\x32\x38\ +\x35\x37\x33\x20\x30\x20\x31\x20\x31\x20\x2d\x31\x2e\x34\x32\x38\ +\x35\x37\x31\x2c\x30\x20\x30\x2e\x37\x31\x34\x32\x38\x35\x37\x33\ +\x2c\x30\x2e\x37\x31\x34\x32\x38\x35\x37\x33\x20\x30\x20\x31\x20\ +\x31\x20\x31\x2e\x34\x32\x38\x35\x37\x31\x2c\x30\x20\x7a\x22\x2f\ +\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\ +\x64\x3d\x22\x6d\x20\x32\x38\x2e\x35\x37\x31\x34\x32\x38\x2c\x31\ +\x36\x2e\x32\x30\x31\x34\x36\x36\x20\x61\x20\x32\x2e\x32\x33\x32\ +\x31\x34\x32\x39\x2c\x32\x2e\x32\x33\x32\x31\x34\x32\x39\x20\x30\ +\x20\x31\x20\x31\x20\x2d\x34\x2e\x34\x36\x34\x32\x38\x36\x2c\x30\ +\x20\x32\x2e\x32\x33\x32\x31\x34\x32\x39\x2c\x32\x2e\x32\x33\x32\ +\x31\x34\x32\x39\x20\x30\x20\x31\x20\x31\x20\x34\x2e\x34\x36\x34\ +\x32\x38\x36\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x20\x36\x2e\ +\x32\x35\x30\x30\x30\x30\x32\x2c\x32\x30\x2e\x30\x38\x35\x33\x39\ +\x34\x20\x61\x20\x30\x2e\x34\x39\x31\x30\x37\x31\x34\x33\x2c\x30\ +\x2e\x34\x39\x31\x30\x37\x31\x34\x33\x20\x30\x20\x31\x20\x31\x20\ +\x2d\x30\x2e\x39\x38\x32\x31\x34\x32\x39\x2c\x30\x20\x30\x2e\x34\ +\x39\x31\x30\x37\x31\x34\x33\x2c\x30\x2e\x34\x39\x31\x30\x37\x31\ +\x34\x33\x20\x30\x20\x31\x20\x31\x20\x30\x2e\x39\x38\x32\x31\x34\ +\x32\x39\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x20\x33\x34\x2e\ +\x37\x33\x32\x31\x34\x34\x2c\x32\x37\x2e\x35\x32\x37\x37\x32\x35\ +\x20\x61\x20\x30\x2e\x32\x36\x37\x38\x35\x37\x31\x33\x2c\x30\x2e\ +\x34\x33\x33\x34\x30\x31\x39\x37\x20\x30\x20\x31\x20\x31\x20\x2d\ +\x30\x2e\x35\x33\x35\x37\x31\x34\x2c\x30\x20\x30\x2e\x32\x36\x37\ +\x38\x35\x37\x31\x33\x2c\x30\x2e\x34\x33\x33\x34\x30\x31\x39\x37\ +\x20\x30\x20\x31\x20\x31\x20\x30\x2e\x35\x33\x35\x37\x31\x34\x2c\ +\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\ +\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x20\x34\x30\x2e\x31\x37\x38\ +\x35\x37\x32\x2c\x39\x2e\x33\x37\x31\x31\x30\x38\x31\x20\x61\x20\ +\x30\x2e\x31\x33\x33\x39\x32\x38\x35\x37\x2c\x30\x2e\x32\x32\x33\ +\x32\x31\x34\x32\x38\x20\x30\x20\x31\x20\x31\x20\x2d\x30\x2e\x32\ +\x36\x37\x38\x35\x37\x2c\x30\x20\x30\x2e\x31\x33\x33\x39\x32\x38\ +\x35\x37\x2c\x30\x2e\x32\x32\x33\x32\x31\x34\x32\x38\x20\x30\x20\ +\x31\x20\x31\x20\x30\x2e\x32\x36\x37\x38\x35\x37\x2c\x30\x20\x7a\ +\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\ +\x68\x20\x64\x3d\x22\x6d\x20\x34\x30\x2e\x39\x38\x32\x31\x34\x34\ +\x2c\x33\x38\x2e\x37\x34\x36\x31\x30\x39\x20\x61\x20\x30\x2e\x32\ +\x32\x33\x32\x31\x34\x32\x38\x2c\x30\x2e\x32\x32\x33\x32\x31\x34\ +\x32\x38\x20\x30\x20\x31\x20\x31\x20\x2d\x30\x2e\x34\x34\x36\x34\ +\x32\x38\x2c\x30\x20\x30\x2e\x32\x32\x33\x32\x31\x34\x32\x38\x2c\ +\x30\x2e\x32\x32\x33\x32\x31\x34\x32\x38\x20\x30\x20\x31\x20\x31\ +\x20\x30\x2e\x34\x34\x36\x34\x32\x38\x2c\x30\x20\x7a\x22\x2f\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\ +\x3d\x22\x6d\x20\x33\x31\x2e\x31\x36\x30\x37\x31\x35\x2c\x34\x30\ +\x2e\x35\x37\x36\x34\x36\x36\x20\x61\x20\x33\x2e\x39\x32\x38\x35\ +\x37\x31\x35\x2c\x33\x2e\x39\x32\x38\x35\x37\x31\x35\x20\x30\x20\ +\x31\x20\x31\x20\x2d\x37\x2e\x38\x35\x37\x31\x34\x33\x2c\x30\x20\ +\x33\x2e\x39\x32\x38\x35\x37\x31\x35\x2c\x33\x2e\x39\x32\x38\x35\ +\x37\x31\x35\x20\x30\x20\x31\x20\x31\x20\x37\x2e\x38\x35\x37\x31\ +\x34\x33\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x20\x32\x32\x2e\ +\x32\x33\x32\x31\x34\x33\x2c\x33\x38\x2e\x32\x35\x35\x30\x33\x35\ +\x20\x61\x20\x31\x2e\x36\x30\x37\x31\x34\x32\x38\x2c\x31\x2e\x36\ +\x30\x37\x31\x34\x32\x38\x20\x30\x20\x31\x20\x31\x20\x2d\x33\x2e\ +\x32\x31\x34\x32\x38\x36\x2c\x30\x20\x31\x2e\x36\x30\x37\x31\x34\ +\x32\x38\x2c\x31\x2e\x36\x30\x37\x31\x34\x32\x38\x20\x30\x20\x31\ +\x20\x31\x20\x33\x2e\x32\x31\x34\x32\x38\x36\x2c\x30\x20\x7a\x22\ +\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\ +\x20\x64\x3d\x22\x6d\x20\x34\x31\x2e\x39\x36\x34\x32\x38\x37\x2c\ +\x31\x31\x2e\x36\x34\x37\x38\x39\x35\x20\x61\x20\x30\x2e\x38\x39\ +\x32\x38\x35\x37\x31\x33\x2c\x30\x2e\x38\x39\x32\x38\x35\x37\x31\ +\x33\x20\x30\x20\x31\x20\x31\x20\x2d\x31\x2e\x37\x38\x35\x37\x31\ +\x34\x2c\x30\x20\x30\x2e\x38\x39\x32\x38\x35\x37\x31\x33\x2c\x30\ +\x2e\x38\x39\x32\x38\x35\x37\x31\x33\x20\x30\x20\x31\x20\x31\x20\ +\x31\x2e\x37\x38\x35\x37\x31\x34\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\ +\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\ +\x22\x6d\x20\x33\x36\x2e\x30\x37\x31\x34\x33\x2c\x32\x35\x2e\x37\ +\x35\x35\x30\x33\x37\x20\x61\x20\x30\x2e\x33\x35\x37\x31\x34\x32\ +\x38\x37\x2c\x30\x2e\x33\x35\x37\x31\x34\x32\x38\x37\x20\x30\x20\ +\x31\x20\x31\x20\x2d\x30\x2e\x37\x31\x34\x32\x38\x36\x2c\x30\x20\ +\x30\x2e\x33\x35\x37\x31\x34\x32\x38\x37\x2c\x30\x2e\x33\x35\x37\ +\x31\x34\x32\x38\x37\x20\x30\x20\x31\x20\x31\x20\x30\x2e\x37\x31\ +\x34\x32\x38\x36\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\ +\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x20\x36\ +\x2e\x32\x35\x2c\x34\x32\x2e\x39\x38\x37\x31\x37\x39\x20\x61\x20\ +\x30\x2e\x36\x32\x35\x2c\x30\x2e\x36\x32\x35\x20\x30\x20\x31\x20\ +\x31\x20\x2d\x31\x2e\x32\x35\x2c\x30\x20\x30\x2e\x36\x32\x35\x2c\ +\x30\x2e\x36\x32\x35\x20\x30\x20\x31\x20\x31\x20\x31\x2e\x32\x35\ +\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\x20\x31\x37\x2e\x33\x32\ +\x31\x34\x32\x38\x2c\x31\x39\x2e\x39\x35\x31\x34\x36\x36\x20\x61\ +\x20\x31\x2e\x33\x33\x39\x32\x38\x35\x37\x2c\x31\x2e\x33\x33\x39\ +\x32\x38\x35\x37\x20\x30\x20\x31\x20\x31\x20\x2d\x32\x2e\x36\x37\ +\x38\x35\x37\x31\x2c\x30\x20\x31\x2e\x33\x33\x39\x32\x38\x35\x37\ +\x2c\x31\x2e\x33\x33\x39\x32\x38\x35\x37\x20\x30\x20\x31\x20\x31\ +\x20\x32\x2e\x36\x37\x38\x35\x37\x31\x2c\x30\x20\x7a\x22\x2f\x3e\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\ +\x3d\x22\x6d\x20\x31\x31\x2e\x39\x36\x34\x32\x38\x36\x2c\x31\x38\ +\x2e\x31\x36\x35\x37\x35\x32\x20\x61\x20\x30\x2e\x34\x34\x36\x34\ +\x32\x38\x35\x37\x2c\x30\x2e\x34\x34\x36\x34\x32\x38\x35\x37\x20\ +\x30\x20\x31\x20\x31\x20\x2d\x30\x2e\x38\x39\x32\x38\x35\x37\x2c\ +\x30\x20\x30\x2e\x34\x34\x36\x34\x32\x38\x35\x37\x2c\x30\x2e\x34\ +\x34\x36\x34\x32\x38\x35\x37\x20\x30\x20\x31\x20\x31\x20\x30\x2e\ +\x38\x39\x32\x38\x35\x37\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\ +\x20\x20\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x6d\ +\x20\x31\x36\x2e\x36\x30\x37\x31\x34\x33\x2c\x37\x2e\x38\x39\x37\ +\x38\x39\x34\x39\x20\x61\x20\x30\x2e\x35\x33\x35\x37\x31\x34\x32\ +\x37\x2c\x30\x2e\x35\x33\x35\x37\x31\x34\x32\x37\x20\x30\x20\x31\ +\x20\x31\x20\x2d\x31\x2e\x30\x37\x31\x34\x32\x39\x2c\x30\x20\x30\ +\x2e\x35\x33\x35\x37\x31\x34\x32\x37\x2c\x30\x2e\x35\x33\x35\x37\ +\x31\x34\x32\x37\x20\x30\x20\x31\x20\x31\x20\x31\x2e\x30\x37\x31\ +\x34\x32\x39\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x0a\x20\x20\x20\x20\ +\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x70\x61\x74\ +\x74\x65\x72\x6e\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\ +\x3c\x2f\x73\x76\x67\x3e\ \x00\x00\x74\xe7\ \x3c\ \xb8\x64\x18\xca\xef\x9c\x95\xcd\x21\x1c\xbf\x60\xa1\xbd\xdd\x42\ @@ -37775,83 +37846,83 @@ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x35\x00\x00\x00\x1b\ \x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x16\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x11\x00\x00\x00\x05\ -\x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x06\x43\xc1\ -\x00\x00\x02\x02\x00\x01\x00\x00\x00\x01\x00\x05\x40\x4a\ -\x00\x00\x01\x92\x00\x00\x00\x00\x00\x01\x00\x03\x79\xe8\ -\x00\x00\x02\x56\x00\x01\x00\x00\x00\x01\x00\x05\xdd\x0d\ -\x00\x00\x02\x3a\x00\x01\x00\x00\x00\x01\x00\x05\xa8\x51\ -\x00\x00\x01\x3e\x00\x01\x00\x00\x00\x01\x00\x02\x06\xcc\ -\x00\x00\x02\x1e\x00\x01\x00\x00\x00\x01\x00\x05\x73\x1f\ -\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x96\ -\x00\x00\x02\x72\x00\x01\x00\x00\x00\x01\x00\x06\x10\xb8\ -\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x02\x39\x0a\ -\x00\x00\x01\x22\x00\x00\x00\x00\x00\x01\x00\x01\x5e\x55\ -\x00\x00\x01\xae\x00\x01\x00\x00\x00\x01\x00\x04\x2a\x0f\ -\x00\x00\x01\x76\x00\x00\x00\x00\x00\x01\x00\x02\xe4\x37\ -\x00\x00\x01\x06\x00\x01\x00\x00\x00\x01\x00\x01\x2b\x46\ -\x00\x00\x00\xea\x00\x00\x00\x00\x00\x01\x00\x00\x7f\x81\ -\x00\x00\x01\xca\x00\x00\x00\x00\x00\x01\x00\x04\x5d\x63\ -\x00\x00\x01\xe6\x00\x01\x00\x00\x00\x01\x00\x05\x0e\x32\ +\x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x06\x48\x2f\ +\x00\x00\x02\x02\x00\x01\x00\x00\x00\x01\x00\x05\x44\xb8\ +\x00\x00\x01\x92\x00\x00\x00\x00\x00\x01\x00\x03\x7e\x56\ +\x00\x00\x02\x56\x00\x01\x00\x00\x00\x01\x00\x05\xe1\x7b\ +\x00\x00\x02\x3a\x00\x01\x00\x00\x00\x01\x00\x05\xac\xbf\ +\x00\x00\x01\x3e\x00\x01\x00\x00\x00\x01\x00\x02\x0b\x3a\ +\x00\x00\x02\x1e\x00\x01\x00\x00\x00\x01\x00\x05\x77\x8d\ +\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x04\ +\x00\x00\x02\x72\x00\x01\x00\x00\x00\x01\x00\x06\x15\x26\ +\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x02\x3d\x78\ +\x00\x00\x01\x22\x00\x00\x00\x00\x00\x01\x00\x01\x62\xc3\ +\x00\x00\x01\xae\x00\x01\x00\x00\x00\x01\x00\x04\x2e\x7d\ +\x00\x00\x01\x76\x00\x00\x00\x00\x00\x01\x00\x02\xe8\xa5\ +\x00\x00\x01\x06\x00\x01\x00\x00\x00\x01\x00\x01\x2f\xb4\ +\x00\x00\x00\xea\x00\x00\x00\x00\x00\x01\x00\x00\x83\xef\ +\x00\x00\x01\xca\x00\x00\x00\x00\x00\x01\x00\x04\x61\xd1\ +\x00\x00\x01\xe6\x00\x01\x00\x00\x00\x01\x00\x05\x12\xa0\ \x00\x00\x00\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x00\xb0\x00\x01\x00\x00\x00\x01\x00\x00\x06\x29\ +\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x06\x29\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x6c\x16\ -\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xbd\xc3\ -\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x1f\xe0\ -\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xde\xc8\ -\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x08\xaa\ -\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x89\x60\ -\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe1\xfe\ -\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb3\x2f\ -\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x59\x6f\ -\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xfa\xd8\ -\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xd6\xe5\ -\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xe7\xc2\ -\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x76\xca\ -\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xdc\x64\ -\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa2\x25\ -\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xcc\x79\ -\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc1\x0e\ -\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x98\x0d\ -\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x23\xc9\ -\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xad\x18\ -\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xb7\x7a\ -\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x11\xb0\ -\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x90\x54\ -\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x08\xb6\ -\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x69\xb7\ -\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x35\x39\ -\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x80\x6a\ -\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xc9\xd1\ -\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xf7\xcc\ -\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xe9\x62\ -\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x4c\x78\ -\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x14\ -\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x06\xb1\ -\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\x9d\xf1\ -\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb5\x34\ -\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x28\x89\ -\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xc9\x9b\ -\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x5e\xb7\ -\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xc0\x20\ -\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x44\xde\ -\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x06\xfe\x69\ -\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xdb\x89\ -\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x2f\xba\ -\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x5f\xe4\ -\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x07\xfd\x44\ -\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x10\x0a\ -\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd4\x46\ -\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x93\x41\ -\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xef\x83\ -\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xed\x72\ -\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x3d\x1e\ -\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x98\xb1\ -\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x2f\xda\ -\x00\x00\x02\xaa\x00\x01\x00\x00\x00\x01\x00\x06\x77\x44\ -\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x80\xb1\ +\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x70\x84\ +\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xc2\x31\ +\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x24\x4e\ +\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xe3\x36\ +\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x0d\x18\ +\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x8d\xce\ +\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe6\x6c\ +\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb7\x9d\ +\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x5d\xdd\ +\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xff\x46\ +\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xdb\x53\ +\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xec\x30\ +\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x7b\x38\ +\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xe0\xd2\ +\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa6\x93\ +\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xd0\xe7\ +\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc5\x7c\ +\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x9c\x7b\ +\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x28\x37\ +\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xb1\x86\ +\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xbb\xe8\ +\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x16\x1e\ +\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x94\xc2\ +\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x0d\x24\ +\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x6e\x25\ +\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x39\xa7\ +\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x84\xd8\ +\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xce\x3f\ +\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xfc\x3a\ +\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xed\xd0\ +\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x50\xe6\ +\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\xa4\x82\ +\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x0b\x1f\ +\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\xa2\x5f\ +\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb9\xa2\ +\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x2c\xf7\ +\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xce\x09\ +\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x63\x25\ +\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xc4\x8e\ +\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x49\x4c\ +\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x07\x02\xd7\ +\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xdf\xf7\ +\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x34\x28\ +\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x64\x52\ +\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x08\x01\xb2\ +\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x14\x78\ +\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd8\xb4\ +\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x97\xaf\ +\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xf3\xf1\ +\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xf1\xe0\ +\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x41\x8c\ +\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x9d\x1f\ +\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x34\x48\ +\x00\x00\x02\xaa\x00\x01\x00\x00\x00\x01\x00\x06\x7b\xb2\ +\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x85\x1f\ " def qInitResources(): diff --git a/src/Mod/Draft/Resources/patterns/concrete.svg b/src/Mod/Draft/Resources/patterns/concrete.svg index 8c2fd6c616..2aa5e9565e 100644 --- a/src/Mod/Draft/Resources/patterns/concrete.svg +++ b/src/Mod/Draft/Resources/patterns/concrete.svg @@ -11,102 +11,22 @@ style="fill:none; stroke:#000000; stroke-width:.5" transform="scale(.01)" id="g3401"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + From 01681d66ec1ce35959f5c9b82e478ba17f65d63d Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 6 Jun 2012 16:45:34 -0300 Subject: [PATCH 325/351] Arch: Bugfix in wall object --- src/Mod/Arch/ArchWall.py | 46 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 25fb891eee..1d6f8e5e07 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -382,28 +382,32 @@ class _Wall(ArchComponent.Component): else: FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object"))) - for app in obj.Additions: - if hasattr(app,"Shape"): - base = base.fuse(app.Shape) - app.ViewObject.hide() #to be removed - for hole in obj.Subtractions: - if Draft.getType(hole) == "Window": - # window - if hole.Base and obj.Width: - f = self.getSubVolume(hole.Base,width) - if f: - base = base.cut(f) - elif Draft.isClone(hole,"Window"): - if hole.Objects[0].Base and width: - f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement.Base) - if f: - base = base.cut(f) - elif hasattr(hole,"Shape"): - if not hole.Shape.isNull(): - base = base.cut(hole.Shape) - hole.ViewObject.hide() # to be removed - if base: + for app in obj.Additions: + if hasattr(app,"Shape"): + if app.Shape: + if not app.Shape.isNull(): + base = base.fuse(app.Shape) + app.ViewObject.hide() #to be removed + + for hole in obj.Subtractions: + if Draft.getType(hole) == "Window": + # window + if hole.Base and obj.Width: + f = self.getSubVolume(hole.Base,width) + if f: + base = base.cut(f) + elif Draft.isClone(hole,"Window"): + if hole.Objects[0].Base and width: + f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement.Base) + if f: + base = base.cut(f) + elif hasattr(hole,"Shape"): + if hole.Shape: + if not hole.Shape.isNull(): + base = base.cut(hole.Shape) + hole.ViewObject.hide() # to be removed + if not base.isNull(): try: base = base.removeSplitter() From 46b7d598ee4a5bd489d8adeb25994abfe7bf1dec Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 6 Jun 2012 16:45:54 -0300 Subject: [PATCH 326/351] Draft: Fixes in trackers * Plane tracker can now be turned off in preferences * Grid no longer stays in front of new objects --- src/Mod/Draft/Draft.py | 2 +- src/Mod/Draft/DraftGui.py | 3 + src/Mod/Draft/DraftSnap.py | 4 + src/Mod/Draft/DraftTools.py | 193 +++--- src/Mod/Draft/DraftTrackers.py | 16 + src/Mod/Draft/Draft_rc.py | 663 ++++++++++--------- src/Mod/Draft/Resources/ui/userprefs-base.ui | 51 +- 7 files changed, 468 insertions(+), 464 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 49ff4ad04b..fc2596bebc 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -108,7 +108,7 @@ def getParamType(param): return "float" elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit","maxSnap", "SvgLinesBlack","dxfStdSize","showSnapBar","hideSnapBar","alwaysShowGrid", - "renderPolylineWidth"]: + "renderPolylineWidth","showPlaneTracker"]: return "bool" elif param in ["color","constructioncolor","snapcolor"]: return "unsigned" diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 7e651a6986..663c57fe9d 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -87,6 +87,9 @@ class todo: except: wrn = "[Draft.todo.commit] Unexpected error:", sys.exc_info()[0], "in ", f, "(", arg, ")" FreeCAD.Console.PrintWarning (wrn) + # restack Draft screen widgets after creation + if hasattr(FreeCADGui,"Snapper"): + FreeCADGui.Snapper.restack() todo.commitlist = [] @staticmethod diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 183f20a52d..3918be2b2f 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -631,6 +631,10 @@ class Snapper: v.setCursor(cur) self.cursorMode = mode + def restack(self): + if self.grid: + self.grid.lowerTracker() + def off(self): "finishes snapping" if self.tracker: diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 06cffa4720..1a55ee3cf4 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -327,62 +327,65 @@ class SelectPlane: # Geometry constructors #--------------------------------------------------------------------------- -class Creator: - "A generic Draft Creator Tool used by creation tools such as line or arc" +class DraftTool: + "The base class of all Draft Tools" def __init__(self): self.commitList = [] - + def Activated(self,name="None"): if FreeCAD.activeDraftCommand: FreeCAD.activeDraftCommand.finish() + global Part, DraftGeomUtils import Part, DraftGeomUtils + self.ui = None self.call = None - self.doc = None - self.support = None + self.support = None self.commitList = [] self.doc = FreeCAD.ActiveDocument - self.view = Draft.get3DView() - self.featureName = name if not self.doc: self.finish() - else: - FreeCAD.activeDraftCommand = self - self.ui = FreeCADGui.draftToolBar - self.ui.sourceCmd = self - self.ui.setTitle(name) - self.ui.show() - rot = self.view.getCameraNode().getField("orientation").getValue() - upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) - self.node = [] - self.pos = [] - self.constrain = None - self.obj = None - self.snap = snapTracker() - self.extsnap = lineTracker(dotted=True) - self.planetrack = PlaneTracker() - - def IsActive(self): - if FreeCADGui.ActiveDocument: - return True - else: - return False + return + FreeCAD.activeDraftCommand = self + self.view = Draft.get3DView() + self.ui = FreeCADGui.draftToolBar + self.ui.sourceCmd = self + self.ui.setTitle(name) + self.ui.show() + rot = self.view.getCameraNode().getField("orientation").getValue() + upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) + plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + self.node = [] + self.pos = [] + self.constrain = None + self.obj = None + self.extendedCopy = False + self.ui.setTitle(name) + self.featureName = name + #self.snap = snapTracker() + #self.extsnap = lineTracker(dotted=True) + self.planetrack = None + if Draft.getParam("showPlaneTracker"): + self.planetrack = PlaneTracker() + def finish(self): - self.snap.finalize() - self.extsnap.finalize() - self.node=[] - self.planetrack.finalize() - if self.support: plane.restore() - FreeCADGui.Snapper.off() + self.node = [] + #self.snap.finalize() + #self.extsnap.finalize() FreeCAD.activeDraftCommand = None if self.ui: self.ui.offUi() - self.ui.sourceCmd = None + self.ui.sourceCmd=None + #self.ui.cross(False) msg("") + if self.planetrack: + self.planetrack.finalize() + if self.support: + plane.restore() + FreeCADGui.Snapper.off() if self.call: self.view.removeEventCallback("SoEvent",self.call) self.call = None @@ -390,6 +393,11 @@ class Creator: todo.delayCommit(self.commitList) self.commitList = [] + def commit(self,name,func): + "stores actions to be committed to the FreeCAD document" + # print "committing" + self.commitList.append((name,func)) + def getStrings(self): "returns a couple of useful strings fro building python commands" @@ -419,10 +427,19 @@ class Creator: fil = "True" return qr,sup,points,fil - - def commit(self,name,func): - "stores actions to be committed to the FreeCAD document" - self.commitList.append((name,func)) + + +class Creator(DraftTool): + "A generic Draft Creator Tool used by creation tools such as line or arc" + + def __init__(self): + DraftTool.__init__(self) + + def IsActive(self): + if FreeCADGui.ActiveDocument: + return True + else: + return False class Line(Creator): "The Line FreeCAD command definition" @@ -527,7 +544,8 @@ class Line(Creator): if (len(self.node) == 1): self.linetrack.on() msg(translate("draft", "Pick next point:\n")) - self.planetrack.set(self.node[0]) + if self.planetrack: + self.planetrack.set(self.node[0]) elif (len(self.node) == 2): last = self.node[len(self.node)-2] newseg = Part.Line(last,point).toShape() @@ -550,7 +568,8 @@ class Line(Creator): self.obj.ViewObject.Visibility = False self.node = [self.node[-1]] self.linetrack.p1(self.node[0]) - self.planetrack.set(self.node[0]) + if self.planetrack: + self.planetrack.set(self.node[0]) msg(translate("draft", "Pick next point:\n")) def numericInput(self,numx,numy,numz): @@ -643,7 +662,8 @@ class BSpline(Line): def drawUpdate(self,point): if (len(self.node) == 1): self.bsplinetrack.on() - self.planetrack.set(self.node[0]) + if self.planetrack: + self.planetrack.set(self.node[0]) msg(translate("draft", "Pick next point:\n")) else: spline = Part.BSplineCurve() @@ -821,7 +841,8 @@ class Rectangle(Creator): self.ui.setRelative() self.rect.setorigin(point) self.rect.on() - self.planetrack.set(point) + if self.planetrack: + self.planetrack.set(point) class Arc(Creator): @@ -1026,7 +1047,8 @@ class Arc(Creator): self.step = 1 self.linetrack.on() msg(translate("draft", "Pick radius:\n")) - self.planetrack.set(point) + if self.planetrack: + self.planetrack.set(point) elif (self.step == 1): # choose radius if self.closedCircle: self.ui.cross(False) @@ -1294,7 +1316,8 @@ class Polygon(Creator): self.step = 1 self.linetrack.on() msg(translate("draft", "Pick radius:\n")) - self.planetrack.set(point) + if self.planetrack: + self.planetrack.set(point) elif (self.step == 1): # choose radius self.ui.cross(False) self.drawPolygon() @@ -1670,7 +1693,8 @@ class Dimension(Creator): self.point2 = self.node[1] if (len(self.node) == 1): self.dimtrack.on() - self.planetrack.set(self.node[0]) + if self.planetrack: + self.planetrack.set(self.node[0]) elif (len(self.node) == 2) and self.cont: self.node.append(self.cont) self.createObject() @@ -1705,73 +1729,18 @@ class Dimension(Creator): # Modifier functions #--------------------------------------------------------------------------- -class Modifier: +class Modifier(DraftTool): "A generic Modifier Tool, used by modification tools such as move" - - def __init__(self): - self.commitList = [] + def __init__(self): + DraftTool.__init__(self) + def IsActive(self): if Draft.getSelection(): return True else: return False - def Activated(self,name="None"): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() - global Part, DraftGeomUtils - import Part, DraftGeomUtils - self.ui = None - self.call = None - self.commitList = [] - self.doc = FreeCAD.ActiveDocument - if not self.doc: - self.finish() - else: - FreeCAD.activeDraftCommand = self - self.view = Draft.get3DView() - self.ui = FreeCADGui.draftToolBar - FreeCADGui.draftToolBar.show() - rot = self.view.getCameraNode().getField("orientation").getValue() - upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) - self.node = [] - self.ui.sourceCmd = self - self.constrain = None - self.obj = None - self.extendedCopy = False - self.ui.setTitle(name) - self.featureName = name - #self.snap = snapTracker() - #self.extsnap = lineTracker(dotted=True) - self.planetrack = PlaneTracker() - - def finish(self): - self.node = [] - #self.snap.finalize() - #self.extsnap.finalize() - FreeCAD.activeDraftCommand = None - if self.ui: - self.ui.offUi() - self.ui.sourceCmd=None - self.ui.cross(False) - msg("") - self.planetrack.finalize() - FreeCADGui.Snapper.off() - if self.call: - self.view.removeEventCallback("SoEvent",self.call) - self.call = None - if self.commitList: - todo.delayCommit(self.commitList) - self.commitList = [] - - def commit(self,name,func): - "stores actions to be committed to the FreeCAD document" - # print "committing" - self.commitList.append((name,func)) - - class Move(Modifier): "The Draft_Move FreeCAD command definition" @@ -1870,7 +1839,8 @@ class Move(Modifier): self.ghost.on() self.linetrack.p1(point) msg(translate("draft", "Pick end point:\n")) - self.planetrack.set(point) + if self.planetrack: + self.planetrack.set(point) else: last = self.node[0] if self.ui.isCopy.isChecked() or hasMod(arg,MODALT): @@ -2085,7 +2055,8 @@ class Rotate(Modifier): self.linetrack.on() self.step = 1 msg(translate("draft", "Pick base angle:\n")) - self.planetrack.set(point) + if self.planetrack: + self.planetrack.set(point) elif (self.step == 1): self.ui.labelRadius.setText("Rotation") self.rad = DraftVecUtils.dist(point,self.center) @@ -2201,7 +2172,8 @@ class Offset(Modifier): self.call = self.view.addEventCallback("SoEvent",self.action) msg(translate("draft", "Pick distance:\n")) self.ui.cross(True) - self.planetrack.set(self.shape.Vertexes[0].Point) + if self.planetrack: + self.planetrack.set(self.shape.Vertexes[0].Point) self.running = True def action(self,arg): @@ -3293,7 +3265,8 @@ class Edit(Modifier): plane.save() if "Shape" in self.obj.PropertiesList: plane.alignToFace(self.obj.Shape) - self.planetrack.set(self.editpoints[0]) + if self.planetrack: + self.planetrack.set(self.editpoints[0]) else: msg(translate("draft", "This object type is not editable\n"),'warning') self.finish() diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index ab556e095c..47e378a348 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -81,6 +81,22 @@ class Tracker: self.switch.whichChild = -1 self.Visible = False + def lowerTracker(self): + '''lowers the tracker to the bottom of the scenegraph, so + it doesn't obscure the other objects''' + if self.switch: + sg=Draft.get3DView().getSceneGraph() + sg.removeChild(self.switch) + sg.addChild(self.switch) + + def raiseTracker(self): + '''raises the tracker to the top of the scenegraph, so + it obscures the other objects''' + if self.switch: + sg=Draft.get3DView().getSceneGraph() + sg.removeChild(self.switch) + sg.insertChild(self.switch,0) + class snapTracker(Tracker): "A Snap Mark tracker, used by tools that support snapping" def __init__(self): diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py index e74a2fc93b..4028d367e7 100644 --- a/src/Mod/Draft/Draft_rc.py +++ b/src/Mod/Draft/Draft_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Tue Jun 5 20:09:57 2012 +# Created: Wed Jun 6 16:21:23 2012 # by: The Resource Compiler for PyQt (Qt v4.8.1) # # WARNING! All changes made in this file will be lost! @@ -117,7 +117,7 @@ qt_resource_data = "\ \x0a\x20\x20\x20\x20\x3c\x2f\x70\x61\x74\x74\x65\x72\x6e\x3e\x0a\ \x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\ \ -\x00\x00\x08\xd7\ +\x00\x00\x08\xd6\ \x3c\ \x73\x76\x67\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\x3e\x0a\x20\x20\ \x20\x20\x3c\x70\x61\x74\x74\x65\x72\x6e\x0a\x20\x20\x20\x20\x20\ @@ -257,10 +257,10 @@ qt_resource_data = "\ \x20\x31\x20\x2d\x31\x2e\x30\x37\x31\x34\x32\x39\x2c\x30\x20\x30\ \x2e\x35\x33\x35\x37\x31\x34\x32\x37\x2c\x30\x2e\x35\x33\x35\x37\ \x31\x34\x32\x37\x20\x30\x20\x31\x20\x31\x20\x31\x2e\x30\x37\x31\ -\x34\x32\x39\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x0a\x20\x20\x20\x20\ -\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x70\x61\x74\ -\x74\x65\x72\x6e\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\ -\x3c\x2f\x73\x76\x67\x3e\ +\x34\x32\x39\x2c\x30\x20\x7a\x22\x2f\x3e\x0a\x20\x20\x20\x20\x20\ +\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x70\x61\x74\x74\ +\x65\x72\x6e\x3e\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x3c\ +\x2f\x73\x76\x67\x3e\ \x00\x00\x74\xe7\ \x3c\ \xb8\x64\x18\xca\xef\x9c\x95\xcd\x21\x1c\xbf\x60\xa1\xbd\xdd\x42\ @@ -26767,258 +26767,263 @@ qt_resource_data = "\ \x33\x2e\x72\x9f\xc2\xcc\xa8\x77\x7d\x66\xc6\x1b\xcc\xef\xf2\x48\ \xa6\x8c\x0e\x28\xa3\x2d\x9e\x88\x63\x66\x74\x00\x9f\x1b\xd5\x84\ \x37\x0f\xfe\x01\xbd\x89\x17\xfc\ -\x00\x00\x0f\x9f\ +\x00\x00\x0f\xe1\ \x00\ -\x00\xa2\x2c\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ -\x0f\x45\x0e\xc8\xc6\xb1\xf3\x6e\x1d\x2f\xda\xf4\x09\x74\x77\xbb\ -\x75\xda\xbd\xbd\x2f\x0b\x5a\xa2\x6d\x5e\x65\xd1\x4b\xd2\x49\xbc\ -\xb8\x1f\x7f\x33\xa4\x64\x4b\xb2\x2c\xc7\xa6\x65\x39\xad\x8b\x02\ -\xb1\x48\x8a\x1c\x0e\xe7\xc5\x99\x21\xd5\xfc\xf9\x61\x10\x90\x3b\ -\x26\x15\x17\xe1\xf5\x7e\xfd\xe8\x78\x9f\xb0\xd0\x13\x3e\x0f\x7b\ -\xd7\xfb\x5f\x6e\xdf\xfe\x74\xb9\xff\x73\x6b\xaf\x39\xe2\xd3\x46\ -\xa7\xd0\xa8\xb5\x47\x9a\x5e\x40\x95\x6a\xbd\x1b\xf1\xe7\xcf\x5f\ -\x73\x1a\x88\x1e\xfc\x0d\x7a\x6d\xa6\x35\xbc\xac\x5e\x4b\xda\xd5\ -\xcd\x9a\x6d\x04\xad\xef\xb9\xdf\x63\x9a\x98\xe7\xeb\xfd\xdf\xff\ -\x30\x8f\xfb\x24\xa4\x03\x76\xbd\x5f\xd8\x09\x0e\x46\x9a\x43\x29\ -\x86\x4c\xea\x71\xf4\x46\x8f\x89\x01\xd3\x72\x6c\x2a\x49\x53\x32\ -\x4f\x9b\x5f\xa4\xf9\xd0\x3a\x6e\xd6\x1e\xa2\x87\x31\x3e\x8c\xa3\ -\x07\x00\x41\xf7\x5b\x67\x57\x50\x64\x7f\xda\xe2\x3e\xe3\xbd\xbe\ -\x6e\x9d\x9f\x34\x9a\xb5\xe8\xb7\xe9\xb3\x16\x77\xda\xac\xc5\x83\ -\xe7\x41\x72\xcf\x43\x5f\xdc\xdf\x72\x1d\xb0\x08\x18\xa5\x25\x00\ -\xdf\x7a\xc7\x42\x26\x69\x40\x54\x34\x99\x66\x2d\xaa\x98\xed\x32\ -\xa0\x63\x31\x9a\x22\xe7\xeb\x2b\xf1\xf0\xd1\x14\x45\x3d\x66\x86\ -\x54\x43\xea\x41\x47\xfb\xd1\x04\xc2\xd1\xa0\xc3\x64\xeb\xbc\x59\ -\x8b\x7e\x59\xf0\x93\x23\xcc\x74\x31\xa0\xb2\xc7\xc3\x4c\x0f\x57\ -\x85\x3d\x70\xcd\x06\x53\x4c\x26\x17\xf3\x9d\x14\xa3\x21\xc0\x1c\ -\x2f\x67\x2f\x7e\xb6\xcd\x67\x06\xd7\x53\x64\xe5\xe0\xcb\x2c\x3a\ -\x69\xe7\x60\x6d\x16\xa8\x42\xdc\x45\xa3\x01\xe1\x6a\xee\xd1\xc0\ -\x96\xfe\xd5\x98\x0e\x3c\x9d\x51\x4e\x47\xef\x67\x3a\xea\x0b\xc9\ -\xff\x11\xa1\x9e\x74\x55\xbf\x9a\xf4\x95\xed\x6d\x16\x49\x1f\x69\ -\x87\x05\x71\x57\x01\x3e\xa4\xdf\xcf\x41\x13\x7b\xd0\xa9\x06\x13\ -\x54\x59\x14\xf1\x50\x33\xd9\xa5\x1e\x23\x03\xe1\xb3\x0c\xa2\xf2\ -\xb1\x65\x0b\x2d\x64\x09\xd0\x6b\x69\xd8\x17\x4c\xc5\x70\xeb\x27\ -\xc9\xba\x37\x62\xd0\x11\xc9\x75\xc7\x8a\x21\x54\x78\x58\xd1\x11\ -\x0f\x7f\x9d\x16\x4f\x50\x88\xe0\x96\x0f\xf3\xe7\x78\xdb\xe7\x8a\ -\xc0\x7f\xdd\x67\xe4\xcb\x07\x33\x45\x98\x31\xb9\xef\x73\xaf\x6f\ -\x0a\x2d\x12\xa0\x7c\x14\x30\x72\xcf\x83\x80\xdc\x0b\xf9\xed\x39\ -\xb9\x85\x5e\x3b\x54\xda\x37\x4c\xf9\x30\x40\x24\xd1\x20\xa6\xad\ -\x98\x23\xb1\x3f\x0a\x4f\x43\x2a\xa9\x66\x44\xdb\x17\x0f\x71\x0c\ -\xe8\x52\x53\xf5\x2d\xdd\xcf\x48\x31\x33\xf2\x5b\xc9\xd8\xcd\xcb\ -\xd7\xe4\x16\x5a\xdc\x71\x76\x4f\xd4\x58\x01\xc6\x48\x57\x48\x33\ -\x0a\xd7\x0a\xdb\x4a\xbb\x42\xd4\xd3\x20\x37\x1f\xbd\x3c\x33\x58\ -\x42\x84\xbe\x09\x51\xd6\x11\xa5\x7d\x80\xfd\x7a\xff\x38\x83\x32\ -\x2f\xea\xfb\x0b\xff\xc5\x50\x82\xe7\x32\xd6\x27\xaa\xfb\x8b\x87\ -\x82\x81\x6a\xb1\x8c\x7f\xf4\x68\x19\xba\x7a\x0c\xc9\x4f\xe9\xc1\ -\xae\x4e\x1e\x1e\xe7\x0d\x57\xcb\x8e\xe7\x06\x40\xb4\xda\x2e\x10\ -\x2c\xe4\xbd\x66\xcd\x8a\xa1\x89\x8c\x4a\x55\x3b\x4b\xac\x86\x9b\ -\xc0\x6a\xac\x2a\xaf\x58\x97\x8e\x02\xe8\x5a\x04\x22\x77\x05\x4b\ -\x17\x54\x30\xee\xab\x91\xd6\x22\xcc\x91\x55\x50\xd7\xb1\x75\x2b\ -\x0b\x2b\x94\x0a\x7e\x72\x92\x46\x16\x84\x20\x1a\x44\xe7\xbf\x60\ -\x46\x64\xd5\x58\x11\xcd\x64\xc6\x35\xdd\x65\x99\x10\xcb\x32\x54\ -\x2a\x99\x8f\xc6\x0e\xfe\x49\x57\xf4\x40\x5a\x85\x58\x65\x7f\xa4\ -\x2b\x3b\xc1\x88\x61\x9d\xf9\x9b\x26\xe8\x99\x41\xd6\x2e\xae\x22\ -\x72\xd8\x4e\x69\xe5\x4c\x7d\x79\x0c\xb4\x40\x1f\xce\x65\xa0\x76\ -\x48\x87\xdb\xce\x3d\x8b\xa4\xc3\xf2\xfc\xa3\x70\xd6\x6a\x0c\xb6\ -\x44\xb0\x63\xa0\x14\xf8\x11\x2e\x10\x41\x3f\x1e\x13\xad\x6a\x35\ -\xdf\x88\x10\x7e\x8d\x8c\x39\xb6\xf5\xcc\x74\xb2\x1e\xcb\x79\x96\ -\xa9\x22\x85\x44\x3a\x0c\xda\x12\x5f\xd2\xfb\x30\x32\x78\x39\x62\ -\x25\x81\x22\x34\x7c\x8f\x36\xc3\x77\xa7\xa7\xf3\x19\xaf\xde\x38\ -\x2b\x60\xbd\xc6\xd9\x59\x65\xda\x6b\x8a\xab\x1f\x8f\x09\x17\xd0\ -\xe7\x42\x53\x30\xe0\x60\x1d\xa1\x17\xa6\x02\x1e\x6c\x0f\x79\x98\ -\xb7\x6d\x55\x50\xde\x99\xba\x2d\xf2\x67\xf6\x58\x35\x36\x99\xe0\ -\xfa\x4c\xc1\x3b\x0a\x74\x9e\x19\x39\x72\xd8\x34\x52\xae\x9b\xa5\ -\x7a\x5d\x82\xe4\x13\x8b\xf6\x44\x49\xbd\xe4\xfd\xd5\x89\xe3\xfe\ -\xea\xd8\x49\xb5\x51\x6e\x84\xf6\x56\x7a\x82\xce\x5c\xf4\x19\x23\ -\x93\x09\xa2\xd2\x82\x39\xf2\x2e\x67\x92\x7c\x63\xe3\x8d\xf8\x55\ -\x60\x40\x2f\x06\x60\x5b\x49\xdf\xcd\xb9\xa1\xfa\x1c\x07\xab\xca\ -\xb7\xe2\x69\x19\x54\x37\x3a\x0d\x9c\xa6\xbe\x02\x1b\xa1\x07\x1f\ -\xe8\x37\x2b\x45\xda\xa6\x78\x01\xaf\x40\x6b\x06\x8d\xd1\xec\xc8\ -\x50\x0f\x03\x15\xd0\xfa\x5d\x3f\x7f\xfe\x7e\xd2\x63\xb3\x66\x0a\ -\x97\x26\x55\xc5\xff\x61\xef\x79\xa8\xe7\x93\x2a\xb6\xc8\xa0\xd3\ -\x46\x55\x4e\xd3\xf1\x95\x49\x6d\x14\x5b\x69\x1c\xa7\xc2\x2c\x53\ -\xb0\xb2\x1d\xce\x11\x59\x16\x75\x6b\xb5\x65\x1a\x75\x97\x6d\xf9\ -\xb6\x4a\xdc\x73\x37\x89\xab\xa2\xb9\xad\x41\xd2\x7a\x23\x29\x81\ -\x64\x3f\x84\x3e\x7b\xc8\x37\x5f\xea\x1b\x31\x5f\x60\x36\x38\xab\ -\x9d\x04\xb7\xa5\x3b\x09\x3e\x2d\x58\xb3\x04\x2f\xe6\xbd\x9d\x04\ -\x5f\xbb\x04\x5f\x35\x32\xf1\x32\xd0\x5b\x2b\xc0\x2f\xdc\x04\x38\ -\xb5\x53\xdb\x88\xfc\xde\xcc\xf6\x13\x66\x63\x18\x7d\x27\xbe\x77\ -\xe2\x7b\x9b\xa2\xaa\xf5\x24\x15\xad\x92\x07\xe2\xb6\xed\x8f\xdc\ -\xb5\x26\xeb\xc6\xbc\x52\x81\x34\xfb\xc8\x43\xf6\xc6\xe7\x7a\x46\ -\x9a\xa1\xcb\x88\x41\x85\x4b\x74\x28\xcf\xa1\x3d\x9d\xad\xf1\xaf\ -\xa5\x1c\xd7\x71\x72\xd8\xea\x12\xef\x71\x28\xdf\x88\xef\x21\x39\ -\x33\x33\x69\xbb\xc2\xdb\x29\x03\xab\xe6\xc4\xd3\xc7\x33\xe2\x54\ -\x11\xf7\x99\xf7\x2d\x57\x11\x63\x85\x93\x3f\xd8\xf4\x00\x64\x8b\ -\xe4\xdb\x25\x00\x21\xb9\xa7\xa1\x26\x5a\x4c\x52\x89\x4c\xe0\xa0\ -\x96\xf0\x15\x4b\x31\x30\x15\x51\x32\x12\xa1\x2a\x26\xf9\x32\xa8\ -\xb9\x4d\xef\x00\x06\xab\xde\xa3\x18\x11\x0d\xfd\x84\xef\x9a\x7a\ -\x52\x28\x45\x14\x53\x98\xfc\xe9\xe0\xbb\x5e\x26\xaa\x09\x40\x89\ -\x90\x3d\xf0\xad\x55\xf5\x55\x93\xf9\x45\x19\x64\xee\xe2\xa2\xfd\ -\xd0\x8d\xa8\x5c\x11\xd3\x1d\xf3\x0f\x81\x9c\x86\xe3\x44\xf2\x5c\ -\x87\x81\x11\x3a\xd4\x31\x45\x81\x95\x3b\x00\x52\x3b\x24\x02\xa8\ -\x5d\xde\x73\xc5\xe2\x22\x65\xdb\xd3\xe0\x9e\x8e\x81\xf2\x34\x95\ -\x98\xea\x48\x42\xf1\xd3\xa4\xc7\x32\x58\xe1\x5d\x20\x3a\x34\x20\ -\x6b\x18\x23\xc2\x40\x66\x98\x0e\xe0\xaf\x05\x82\x1c\x3a\x36\x3f\ -\xcb\xd5\x19\xc3\xf1\x60\x8b\x33\x01\xab\xe6\x9f\xfa\x65\x29\x0c\ -\xe4\x10\xb3\xff\x55\xc8\x01\x0d\x82\xf1\x21\x01\x44\x32\x69\xc8\ -\x10\x43\x1d\x51\xcc\xf0\x30\x52\x16\x43\xce\x14\x41\xe0\x14\x0b\ -\xa0\x9c\xf9\x47\x24\x66\x3d\x31\x34\xb6\x4f\x92\x03\xf1\x9d\x0e\ -\x05\xce\x8a\x63\xfe\x31\x23\xc6\x6f\x03\x5f\x29\xcd\xa8\xef\x10\ -\xe5\x2f\xd0\x2d\x66\x90\x34\x00\xa9\xc9\x6d\x46\x99\x18\x28\x5e\ -\x01\x10\xbf\xc5\xe1\xd7\x1d\x4f\xe4\xf1\xc4\x59\x29\x2c\x71\xb9\ -\x5e\x9d\x62\x4c\xa8\xa4\x76\x40\x27\x35\x98\x53\x60\x2c\x28\x9d\ -\xe0\x97\x28\xa3\x05\xb3\x5b\xa0\xd4\x30\x49\x28\x74\xe2\xfd\x8e\ -\x75\x70\x0f\xcd\x3b\x61\x30\x86\x17\x58\x48\x00\x74\xb0\x73\xa0\ -\xe8\xe6\xf6\xf3\xc7\x52\x98\xe2\x65\x1a\xee\x18\xdc\x03\x9f\x2b\ -\xda\x09\xa6\x5e\x77\x74\xd8\xfc\xeb\x29\xab\x20\xbb\x40\xed\x2d\ -\x76\xb7\xaf\xdd\xe9\x5b\xbc\xc3\xdd\x39\x7d\xd7\xed\xf4\xad\x3b\ -\x3a\x48\x25\xf5\xf9\x48\x4d\x32\x4d\x8d\x2c\x00\x9e\x54\x43\xe6\ -\x71\xb0\x04\x87\x02\x10\xa9\x8e\xf0\x24\x12\x16\x1f\xdb\x3c\x1e\ -\x41\x80\x55\x35\x0d\x3d\x46\x0e\x78\xd8\xe5\x21\xc0\xed\xc0\xa8\ -\x0b\x62\x8b\x92\x86\xbd\x2a\xdc\x39\x0b\x32\xa4\x16\x90\xba\x1a\ -\x75\xbb\x3c\xeb\x29\x8e\xe6\x30\x7c\xd8\x8c\xda\x07\xec\x7d\xb6\ -\xc8\x7b\xa2\xd2\xa7\xec\x93\x20\x4b\xf8\x2c\x97\xd0\xf7\x0e\x07\ -\xbe\xf2\xf4\xfd\x84\x2f\x8d\xd2\x06\x15\x4e\x84\xe7\x8d\x24\xa1\ -\x3d\x8a\xa6\x6b\xc2\xb0\xd5\x7d\x50\x9b\x12\x9d\x2a\x34\x34\x86\ -\x2f\x0f\x7d\xee\x51\x34\x72\x6d\x64\x82\x88\x2e\x61\x30\x2b\x07\ -\x1f\xc6\xa2\x44\x00\xfa\xc0\x07\xa3\x41\x29\x5a\xbb\x4b\x03\xb5\ -\x09\xb5\x0d\x73\xf8\x91\x74\xf6\x4e\x63\xcf\xc7\x74\x19\x61\xda\ -\xe2\x1d\x32\x0b\xd1\x06\x5e\x3f\xfd\x17\x8a\x9d\x5f\x2c\xd7\x66\ -\xa5\x04\xaa\xfc\x0e\x33\x71\x05\xee\x33\x09\x62\x24\x69\x27\x94\ -\x21\x43\xe6\x00\xb2\x85\xda\xbf\x38\xbb\xa1\xac\x55\x8c\xc4\x6b\ -\x7e\x00\xfa\xea\xea\x6a\xf5\x10\x74\x51\x5e\xf5\xe9\x66\x22\xdb\ -\x56\xec\xbe\xb1\x0b\xfe\x44\x65\x6f\xd9\x16\x4b\xbd\x14\x8b\xc5\ -\x61\x13\x01\x16\x4b\xca\xd7\xd6\xb6\xbb\x7a\x1b\xb8\x99\xb8\x19\ -\xfa\xc2\x9c\xb0\x61\x21\xbb\x03\xb6\x46\x0f\x04\x06\x7f\xca\x94\ -\x24\x6d\x18\x32\xbe\x46\x21\x01\xd2\x53\x76\x27\x20\x16\x71\x2e\ -\xaf\xe8\xf7\x7b\xcc\x66\x09\xa2\x5d\xf5\x08\xdc\x7b\xd0\x65\xf1\ -\x25\x08\x49\x62\xb5\x7e\xd9\x91\x72\x88\x7a\x2c\xb1\x98\x7d\x80\ -\xe2\xa9\x2f\x66\xc9\xc2\xae\x9c\x00\x85\x43\x4a\x70\xde\xee\x2c\ -\x15\x56\x00\x71\xc6\x6c\xbc\xba\x0b\x8f\x60\x2f\x4d\x23\xd7\x47\ -\xe4\xb7\x38\xc8\x67\x04\xe5\x38\xfb\xc6\x3d\x07\x28\xe5\x32\x99\ -\x2b\x4b\xd0\xfc\x5b\x1c\x6b\x72\xea\x71\xec\x1e\x4e\x5f\x82\xd2\ -\x11\x15\xbb\x40\xdc\x7c\x32\x77\xbd\x40\xc7\xf5\x42\x0a\xbc\x31\ -\x06\xdd\x0b\xc3\x80\x86\xdb\x79\x83\x4e\xf1\x0c\x97\x20\xc5\x88\ -\xec\xff\xf8\xb4\xad\xb4\xe8\x96\x42\xf8\xab\xc8\x5f\xc0\xcd\x24\ -\x30\xfe\xfb\x4f\x72\x70\x2b\x86\xb9\x8e\xe0\x0d\x41\xf0\x1f\x72\ -\xf0\x56\x02\x6f\x55\x08\xc3\x9f\x00\x43\x1b\x74\xbb\x13\x08\x55\ -\x8b\xa4\x7a\x39\xc9\x35\x0e\xe9\x8f\xc9\x6d\x06\x25\x3d\xc9\xfd\ -\x94\xfe\x34\x91\xcb\x28\xd2\x59\x86\xfe\xfc\x02\xbb\x15\x1c\xf4\ -\x49\xfb\x35\xed\x04\xb6\x53\xf0\xad\x3d\x10\x59\xbc\xa5\xdd\xb9\ -\x35\x5d\xdc\x9a\x4b\xb0\xfc\x82\xb4\xee\x4a\xbc\x9d\x59\x97\x85\ -\xdd\x0b\x26\x64\x8a\xcd\x4f\xe8\x30\x72\xc7\x15\xc7\x8c\x04\x23\ -\x5e\xa6\x4d\xd1\x62\xea\xb0\xd0\xeb\xe3\x4e\x00\xaf\xb6\xbb\x63\ -\x09\xf3\x3e\x91\x4b\x31\x32\x89\x14\x34\xce\xea\x2b\x33\x99\xa2\ -\x2f\x72\x2f\x65\x2b\x2b\xa7\x01\x86\x7b\xf7\x7d\x89\x93\x47\x58\ -\xda\xc5\xc9\xa1\xa5\xd1\xf2\xfc\x74\x4d\x24\xd9\xe8\x22\xd4\x0a\ -\x0c\xf7\xd7\x62\x04\x13\x9e\xe7\x28\xf7\x4d\x6d\xec\x2e\xdf\xc2\ -\xa0\x87\x39\xe0\x6b\x91\x07\xbc\xae\xef\x19\x30\x2c\xa3\xc0\xd4\ -\x46\x12\x60\xfa\xf7\xea\x0c\xe5\x33\x8f\x0f\x00\xf2\x7c\x87\xba\ -\x83\x3f\x3d\x3f\x00\x60\x71\x8d\x01\x80\xab\xa3\xab\xcb\xab\xc9\ -\xbf\x8b\xcb\x46\xb3\x16\x55\x2e\x3d\x54\x5e\x44\x20\xea\xab\x7e\ -\x74\x9c\xfe\xb7\xfa\x28\x4b\xda\x2f\xed\x98\xda\x7f\x24\xb9\x53\ -\x4d\xac\xa9\x28\x4a\xc7\x43\xc3\x20\x8a\xa0\x3f\xff\xf1\x67\x8c\ -\x36\x17\x9e\x2b\xce\xc1\xa8\x28\xc8\xca\x43\x8b\xb4\x38\x2c\x62\ -\x2f\x1e\xd3\x7d\x0e\xb6\x88\x3c\x22\x6d\x4c\xba\xea\x8e\x09\xd8\ -\x11\x8c\x60\xf8\x02\x6c\x86\x31\x51\x7f\x8f\xa8\x64\x6a\x22\xa2\ -\x06\x71\x37\x0e\xb9\x99\x05\xc1\xbe\xfa\xf1\x46\x82\x7d\xc8\xcb\ -\x6f\x2c\xed\x3c\x51\x4e\x2e\x7b\x0b\xee\x78\x8d\xd2\x82\xa4\xe3\ -\xb9\xbc\xfd\x01\xaf\x6b\x0e\x31\xf5\x4f\x02\x35\xe2\x81\x27\x12\ -\x00\x93\xe7\x1e\x8c\xad\x98\xc7\x8b\x6d\x8a\x48\x53\xb6\x61\x47\ -\xf4\xd8\x5d\xd7\x79\xf1\xae\xab\x7e\x7e\x71\x71\xd1\xa8\x9f\xb9\ -\xec\xbd\x96\x37\x51\xa6\xa9\x10\xb1\x51\x81\x27\x81\x78\xbc\x4c\ -\x9e\x10\xd2\xe7\x21\xd5\x0c\x8f\x3f\x30\x69\xf6\xb4\x8a\x1c\x60\ -\xa6\x06\x7b\x38\x22\x27\xe4\x9a\x1c\x83\xba\xae\x3b\x24\x68\x16\ -\x88\x8b\xf3\x8d\x48\x8b\x09\x2d\x3e\x59\x69\xb1\xac\xfb\xa2\x58\ -\x7f\xed\xdc\x17\x6b\xcf\xa3\x5e\x55\x5e\xbe\xe6\x03\x16\x9a\x73\ -\xa1\x4f\x40\x62\x16\x6f\x60\x0b\x93\x8b\x2e\xcb\x49\x2d\xda\x88\ -\xf8\xf0\xf9\xe0\xd3\x93\x97\x20\x65\xdb\x1b\x4b\x9c\x7d\xca\x63\ -\xa0\x05\x29\x44\x73\xf9\xe7\x56\x04\xa0\xb4\x42\xaf\xd4\xc8\x63\ -\xb1\xac\x2d\x66\xfd\x9d\xac\x5d\x8b\xab\x78\x09\x67\xd1\x0f\x60\ -\xd6\x4d\xef\xf2\x30\xc2\x11\xb3\x8e\x7c\xcc\xcb\xe8\x8e\x42\xcf\ -\x1a\x70\xba\x4f\xb5\x49\x92\xa3\x44\xc7\x2c\x72\xb4\xf7\x15\x5b\ -\x47\xa9\xfe\x3e\xef\x76\x61\xa7\x08\xe5\xb8\x39\x0c\x60\xbf\x68\ -\x92\x53\x6c\x87\xf1\x16\x53\x4b\x66\xf2\xff\xa9\x22\x0a\x00\x73\ -\xd8\x33\x16\x1c\x68\xa9\xad\x42\xf0\x61\x0f\xc8\x41\xb3\x2c\x8a\ -\x22\x3f\x12\x98\xac\xf5\x35\x79\x98\x0a\xfc\x58\x30\xca\xd9\xe6\ -\xfd\x58\x7a\x2a\xf2\x76\xba\x28\x4f\x17\x9d\xbb\xa9\xa2\x05\x19\ -\x5e\x0b\x13\x62\xb0\x05\xb1\xb2\xa0\x3a\xa5\x54\x9c\xdd\xb8\x53\ -\x4a\x9b\x56\x4a\x0b\x92\x17\xbe\x07\xb5\x14\xd3\xbf\x1d\xcf\x9c\ -\xf5\x40\x56\x50\xe6\x3a\x1c\x7f\xb2\xcf\x59\xaf\x1f\x61\x22\x89\ -\x1b\x15\x44\x14\x70\x7a\x31\xa3\xef\x44\x71\xee\xb6\xc0\xf1\x6b\ -\x59\x0b\xee\xd3\x79\x9c\x2c\xee\x02\x44\xd5\x49\xe2\x62\x37\xe3\ -\x4e\x12\xaf\x45\x12\x2f\xbc\x3b\x6f\xf5\xd4\xb1\xbc\x9b\xf3\x90\ -\xa2\xcc\xbb\x93\xef\x15\xda\xcc\x8e\x3c\x79\x77\xb4\xf7\x01\xe0\ -\xa5\x21\x9a\xd3\x34\xf1\xa6\x1a\x79\x7d\xb4\xab\x9f\xfd\x3d\x12\ -\xfa\xc5\x4b\xc9\x69\x60\x7f\x62\x86\x5a\x3c\x90\xd2\xe3\x20\xdb\ -\x54\xd1\x50\xc5\x2d\xa3\x12\x26\x79\xd7\xfe\xdc\x03\x78\xec\xaf\ -\x81\x08\x45\xdc\x0c\x81\x24\x5d\x3a\xe0\xc1\x38\x6f\xdc\xc3\xf7\ -\x2c\xb8\x63\xf8\x85\xcf\xc3\x69\xe7\xf6\x25\x03\xaa\xd9\x2f\x50\ -\x0b\xcc\x5e\xce\xfb\xcf\x5f\x89\xc0\xb7\xcf\xa5\xe4\xa8\xe0\x18\ -\xab\x77\x4c\x03\xde\x0b\x61\x35\x66\x7a\x07\x26\x47\xfe\x7a\x89\ -\xf5\x9f\x91\x86\xff\x37\x79\xbc\x95\x94\x03\xe9\xf4\xa6\x25\x5f\ -\x6f\x18\xfa\xcc\x01\x0c\xa6\x97\x87\x61\x49\xa5\x62\x25\xd6\x4e\ -\xa5\xe4\xaa\x94\x25\xce\xb0\xe5\xba\x6a\x57\xbd\xa9\x7e\xaa\x53\ -\x06\xc3\x00\x3f\x76\xaa\xfa\x8c\x55\xa8\x58\x16\x4c\x64\xa7\x59\ -\xd6\xa2\x59\xde\xf2\x80\xdd\xf4\x85\x00\x19\x3b\xa3\x5c\xba\x50\ -\xe7\xd9\xba\x45\xf6\x3d\x0f\x97\xb5\xef\x4f\x8e\x8b\x11\xe4\x84\ -\x9f\xe5\xe3\x88\x7e\x96\xfa\xa3\x1b\x38\x4d\xa2\xa2\x87\x6e\x22\ -\x9b\xab\x88\x5f\x69\x8a\x32\xa9\x97\x64\x10\x37\xa1\x69\xa1\xda\ -\x09\xcd\x39\x42\x73\x89\x5b\x5d\x73\x84\xa6\x7b\x70\xeb\x19\x1d\ -\x0c\x5f\x90\x8f\x8c\xfa\x20\xd0\xa8\x94\xe2\xde\x9a\x13\xdb\x78\ -\x60\x68\x6d\xc7\x85\xf8\xc0\x7e\x79\x73\x5b\xa9\xd2\xed\xa8\xca\ -\x6b\xa1\xc9\x59\x75\x27\x65\x70\xf8\x8b\x6a\x87\xbf\xaa\x6e\xf8\ -\x1b\x2e\x3d\xd8\x19\x54\x88\xff\x08\x82\x0a\x97\x20\x82\xa0\xc2\ -\x55\x68\x83\x68\xe9\x57\xb9\x08\x16\x80\x0a\xd7\xc0\x02\x50\xe1\ -\x12\xbc\xa2\xde\x37\x55\xf5\x32\x4c\x81\xa8\x70\x29\xa6\x40\x38\ -\x2d\x47\xe5\xa6\x8a\x63\xf8\xa6\x5e\x9c\xfb\x34\xdf\x5a\xf9\x0a\ -\xad\xb8\x47\x83\x84\xef\xc6\xfa\x0f\x13\x3b\xa9\x6d\x34\x57\xd6\ -\xf5\x9d\xe3\xc4\x34\x31\x5d\xd0\xf8\xbb\x62\x4c\x44\x9e\xad\xe8\ -\x20\x13\x6c\x78\x92\x48\xa2\x92\x91\xbb\x08\x79\x47\x24\xde\x26\ -\x43\xaf\x01\xeb\xea\x43\xbc\x47\xd6\x1e\x75\xc2\x1e\x3f\xb4\x7f\ -\xc3\xfb\xc8\x43\x9f\x4a\x97\x2b\x93\x97\xb3\xc2\x52\x0b\xf8\x3d\ -\x9a\x62\x1f\x01\xd1\xe4\x20\x89\xdb\x0a\x8f\x30\x7f\x9e\x17\xf9\ -\x7c\x22\x12\xc8\x51\xfc\xac\xfa\x55\xe7\x97\x81\x49\xc9\x85\x9d\ -\x75\xfb\xeb\x3b\x02\x84\x86\x8f\xc0\x43\xc2\x2b\x5d\xf2\x2c\xf0\ -\x33\x15\x9f\xc1\xdc\xf9\x99\x36\xea\x67\x5a\x90\xb5\xfe\xa4\xfd\ -\x4c\xef\xf1\xe4\x0a\xde\xee\x85\xe1\x12\x15\x1d\x67\xa1\xa0\x6a\ -\x24\xf3\xb4\x90\x63\xbc\x4a\x50\x47\x1f\x30\x46\x26\x41\xbc\xa8\ -\x64\xe1\xb3\x40\xbf\x18\x5a\xce\x79\xd6\xd3\x2f\xd0\x69\x85\xb7\ -\x0b\x4f\x33\xa2\xe2\x38\x8c\xef\x33\x1f\x3d\x58\xa8\x92\x62\x91\ -\x19\xc5\x70\xa0\x19\xa8\xab\xa8\x97\xcd\x7c\xad\x25\x1a\x0c\x49\ -\x60\x5b\xf5\x93\x9b\x4c\x4e\x57\xa6\xfa\x9a\xb6\x4b\x34\x4a\xb4\ -\x88\xe4\xf7\x24\x20\x66\x0f\xf0\x5d\xef\x9f\xef\x93\x01\x95\x3d\ -\x1e\x5e\xef\xd7\xeb\xfb\x98\x42\xd6\x1c\xf2\x87\x01\x1d\xc6\x39\ -\x70\xad\xbf\x3f\x99\xe7\xb7\x52\x0c\x7e\x01\x63\xa5\x2d\x46\x12\ -\x73\xa6\x32\xad\xe0\x3d\x6f\xa4\xb4\x18\xd8\x11\x95\x81\x24\x59\ -\x62\xa1\x34\xec\xda\x32\xdc\x9a\xe0\x54\xc0\x9f\x29\x37\x4d\x40\ -\xb2\xb3\xd0\x57\xad\xdf\xff\x30\xef\x81\xa8\x8b\x0a\xf6\x2c\x37\ -\xa1\xeb\x0b\x7b\xa8\x61\x07\xaf\x39\x0d\x44\xef\xa8\x8f\xcc\x65\ -\x2a\x0c\x02\xb2\xe3\x16\x03\x72\x83\x1f\x1b\x7a\x35\xd2\xda\x98\ -\x35\x39\x80\x7c\x1a\xa9\x7e\x5c\x3f\x0f\x18\x0b\xac\x72\x83\x24\ -\x23\xc0\x72\xa1\x99\xc5\xdd\x3c\x90\xb0\xb7\xb5\x81\x15\x65\xe7\ -\xe4\x23\x68\x52\xb9\x11\x50\x16\xad\xd7\xec\xa2\x6e\x06\xac\xe8\ -\x16\x86\x7c\x14\x4d\x6b\x37\x84\x23\xbb\xdb\x99\x03\xcc\xa4\x76\ -\x23\xc0\xc4\x59\x05\xf9\xc0\x4c\x6b\x37\x02\x4c\x2a\xd9\x2c\x1f\ -\xa2\x4c\x13\x77\xb0\xd2\x05\xd8\x53\x53\x32\x65\x04\xa9\x32\x22\ -\x17\x74\x6f\xc8\x6c\xca\xb1\x9d\xc5\xe4\xd9\x8e\xaa\x00\x00\xe8\ -\x3b\xe7\x2e\x1f\x0c\xa4\x87\xd1\xb8\x68\x9d\xf4\x42\x1a\xb4\xbc\ -\x00\xcf\xb2\xfa\x07\x78\x7c\x16\x77\x30\xb6\xd4\xb4\x00\x13\x80\ -\xf1\xbb\x64\x5f\x99\x1b\x02\x9a\xb5\x49\x13\xdb\x65\x20\x74\x0b\ -\xd4\xe0\x1b\x7b\x58\x77\xd2\x27\x16\x5b\x8c\xe0\xb7\x09\x22\x8d\ -\x84\xbf\x89\x1e\x0f\xd1\xd4\x34\xd3\x4b\x85\x3d\x9a\x0f\xad\x2b\ -\x00\xf8\x21\x7e\x1c\xb7\x4e\x2e\xae\x9a\xb5\x71\xac\xce\xf0\xed\ -\xd9\x8e\x7c\x86\xdf\x53\x31\x86\x71\xb6\xb7\xd3\xfa\x45\xba\xbb\ -\xcb\x7a\x5e\x77\xf6\xa7\x8a\x96\x26\x85\xda\x8d\x62\x7a\x72\x2a\ -\xba\x5c\x1c\x23\x4e\x53\x38\x3e\x71\xc1\xf1\xd9\x45\x3d\xd3\xdd\ -\x69\x69\x38\x3e\x5d\x1f\x8e\xcf\xcb\xc5\xf1\x79\x9a\xf0\x1a\x17\ -\xc7\xeb\xc4\x71\xe3\xa2\xb1\x85\x38\x8e\x2f\x4e\x2f\x19\xb3\x8d\ -\xb5\x62\xb6\x7e\xbe\x31\xcc\xae\x2e\x21\xe2\x8b\x6d\xca\xc5\xec\ -\xd9\x65\x9a\x91\xcf\xcf\x5c\x30\x7b\x72\x76\xfa\x04\x64\x6f\x7c\ -\x75\x47\xb9\x98\x3d\x39\xc9\x60\xf6\x62\x9d\x34\x5b\x26\x66\x2f\ -\xdc\x25\xee\xf4\x26\xe8\x72\x91\x5c\xcf\xd0\x6f\xe3\xca\x49\x32\ -\x9c\xa2\xbf\x26\xd5\x5d\xae\x9a\xdc\x16\xdb\x21\x71\x95\x5b\xc9\ -\xd6\x43\xd6\x42\x73\x92\x12\x8d\xc6\xf9\x63\x8c\x91\xf9\x58\x4e\ -\x3e\x42\x7d\xb3\x36\xe2\xad\xbd\xff\x03\x0c\xba\x22\x38\ +\x00\xa3\x4a\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\ +\x0f\x45\x0f\xc8\xc6\xb1\xf3\x6e\x1d\x2f\xda\xf4\x09\x74\x77\xbb\ +\x75\xda\xde\xde\x97\x05\x2d\xd1\x36\xaf\xb2\xe8\x8a\x74\x12\x2f\ +\xee\xc7\xdf\x0c\x49\x59\x8f\xc8\x72\x64\x59\x96\xdd\xba\x28\x10\ +\x89\xa4\xc8\xe1\x70\x5e\x9c\x19\xd2\xed\x5f\xef\x47\x1e\xb9\x65\ +\x81\xe4\xc2\xbf\xda\x6f\x1e\x1e\xed\x13\xe6\x3b\xc2\xe5\xfe\xe0\ +\x6a\xff\xf3\xcd\x9b\x5f\x2e\xf6\x7f\xed\xec\xb5\x27\x3c\x6a\x74\ +\x02\x8d\x3a\x7b\xa4\xed\x78\x54\xca\xce\xdb\x09\x7f\xf6\xec\x15\ +\xa7\x9e\x18\xc0\x5f\x6f\xd0\x65\x4a\xc1\xc7\xf2\x55\x40\xfb\xaa\ +\xdd\x30\x8d\xa0\xf5\x1d\x77\x07\x4c\x11\xfd\x7e\xb5\xff\xe7\x57\ +\xfd\xba\x4f\x7c\x3a\x62\x57\xfb\xb9\x9d\xe0\x60\xa4\x3d\x0e\xc4\ +\x98\x05\x6a\x6a\xbf\x18\x30\x31\x62\x2a\x98\xea\x4a\xd2\x0e\x98\ +\xa3\xf4\x13\x69\xdf\x77\x8e\xda\x8d\x7b\xfb\x32\xc5\x97\xa9\x7d\ +\x01\x10\xd4\xb0\x73\x7a\x09\x45\xe6\xd1\x14\x0f\x19\x1f\x0c\x55\ +\xe7\xec\xb8\xd5\x6e\xd8\x67\xdd\x67\x23\xec\xb4\xdd\x08\x07\xcf\ +\x82\xe4\x8e\xfb\xae\xb8\xbb\xe1\xca\x63\x16\x18\xa9\x02\x00\xbe\ +\xf3\x96\xf9\x2c\xa0\x1e\x91\x76\x32\xed\x86\xad\x78\xd8\xa5\x47\ +\xa7\x62\x12\x21\xe7\xcb\x4b\x71\xff\x41\x17\xd9\x1e\x53\x43\xca\ +\x31\x75\xa0\xa3\x7d\x3b\x01\x7f\x32\xea\xb1\xa0\x73\xd6\x6e\xd8\ +\x27\x03\x7e\x7c\x84\x07\x5d\x8c\x68\x30\xe0\x7e\xaa\x87\xcb\xdc\ +\x1e\xb8\x62\xa3\x08\x93\xf1\xc5\x7c\x1b\x88\xc9\x18\x60\x0e\x97\ +\x73\x10\xbe\x9b\xe6\x0f\x06\x57\x11\xb2\x32\xf0\xa5\x17\x9d\x74\ +\x33\xb0\xf6\x10\xa8\x5c\xdc\xd9\xd1\x80\x70\x15\x77\xa8\x67\x4a\ +\xff\x6e\x45\x03\x47\x33\xca\xe8\xe8\xdd\x83\x8e\x86\x22\xe0\xff\ +\x08\x5f\xcd\xba\x6a\x5e\xce\xfa\x4a\xf7\xf6\x10\x49\x1f\x68\x8f\ +\x79\x61\x57\x1e\xbe\x24\xbf\xcf\x40\x13\xbb\x57\x89\x06\x33\x54\ +\x19\x14\x71\x5f\xb1\xa0\x4f\x1d\x46\x46\xc2\x65\x29\x44\x65\x63\ +\xcb\x14\x1a\xc8\x62\xa0\x37\x92\xb0\x2f\x98\x8a\xe6\xd6\x8f\x01\ +\xeb\x5f\x8b\x51\x4f\xc4\xd7\x1d\x2b\xc6\x50\xe1\x60\x45\x4f\xdc\ +\xff\x7d\x92\x3f\x41\x21\xbc\x1b\x3e\xce\x9e\xe3\xcd\x90\x4b\x02\ +\xff\xd5\x90\x91\xcf\xef\xf5\x14\x61\xc6\xe4\x6e\xc8\x9d\xa1\x2e\ +\x34\x48\x80\xf2\x89\xc7\xc8\x1d\xf7\x3c\x72\x27\x82\x6f\xcf\xc8\ +\x0d\xf4\xda\xa3\x81\xf9\x42\x97\x8f\x3d\x44\x12\xf5\x42\xda\x0a\ +\x39\x12\xfb\xa3\xf0\x36\xa6\x01\x55\x8c\x28\xf3\xe1\x01\x8e\x01\ +\x5d\x2a\x2a\xbf\x25\xfb\x99\x48\xa6\x47\x7e\x13\x30\x76\xfd\xe2\ +\x15\xb9\x81\x16\xb7\x9c\xdd\x11\x39\x95\x80\x31\xd2\x17\x81\x1e\ +\x85\x2b\x89\x6d\x03\xb3\x42\xd4\x51\x20\x37\x1f\xbd\x3c\x0f\xb0\ +\x84\x08\x7d\xed\xa3\xac\x23\x52\xb9\x00\xfb\xd5\xfe\x51\x0a\x65\ +\x8e\xed\xfb\x33\xff\x4d\x53\x82\x53\x66\xac\x8f\x54\x0d\x17\x0f\ +\x05\x03\x35\x42\x19\xff\xe8\xd1\x52\x74\xf5\x18\x92\x8f\xe8\xc1\ +\xac\x4e\x16\x1e\xe7\x0d\xd7\x48\x8f\x57\x0e\x00\xbb\xda\x65\x20\ +\x58\xc8\x7b\xed\x86\x11\x43\x33\x19\x95\xa8\x2e\x2d\xb1\x5a\xe5\ +\x04\x56\x6b\x59\x79\xc5\xfa\x74\xe2\x41\xd7\xc2\x13\x99\x2b\x58\ +\xb9\xa0\x82\x71\x5f\x4e\x94\x12\x7e\x86\xac\x82\xba\x9e\xa9\x5b\ +\x5a\x58\xa1\x54\x70\xe3\x93\xd4\xb2\xc0\x07\xd1\x20\x7a\xff\x05\ +\x33\x22\xad\xc6\xf2\x68\x26\x35\xae\xee\x2e\xcd\x84\x58\x96\xa2\ +\xd2\x80\xb9\x68\xec\xe0\x9f\x64\xc5\x00\xa4\x95\x8f\x55\xe6\x21\ +\x59\xd9\xf3\x26\x0c\xeb\xf4\xdf\x24\x41\x3f\x18\x64\xe5\xe2\xca\ +\x92\xc3\x66\x4a\xab\xd2\xd4\x97\xc5\x40\x0b\xf4\xe1\x5c\x06\xea\ +\xfa\x74\xbc\xe9\xdc\xb3\x48\x3a\x14\xe7\x1f\x89\xb3\x96\x53\xb0\ +\x25\xbc\x1d\x03\x25\xc0\xb7\xb8\x40\x04\xfd\x7c\x4c\xb4\xac\xd5\ +\x7c\x2d\x7c\x78\x9a\x68\x73\x6c\xe3\x99\xe9\x78\x35\x96\xf3\x43\ +\xa6\xb2\x0a\x89\xf4\x18\xb4\x25\x6e\x40\xef\x7c\x6b\xf0\x72\xc4\ +\x4a\x0c\x45\x68\xf8\x1e\xae\x87\xef\x4e\x4e\xe6\x33\x5e\xb3\x75\ +\x9a\xc3\x7a\xad\xd3\xd3\xda\xb4\x57\x84\xab\x9f\x8f\x09\x17\xd0\ +\xe7\x42\x53\xd0\xe3\x60\x1d\xa1\x17\xa6\x06\x1e\xec\x8e\xb9\x9f\ +\xb5\x6d\x95\x50\xde\x8b\xdc\x16\xd9\x33\x7b\xac\x1a\x9b\x4d\x70\ +\x75\xa6\xe0\x2d\x05\x3a\x4f\x8d\x6c\x1d\x36\xad\x84\xeb\xa6\x50\ +\xaf\x05\x48\x3e\xb6\x68\x5b\x4a\xea\x15\xef\xaf\x8e\x4b\xee\xaf\ +\x8e\x4a\xa9\x36\xca\xb5\xd0\xde\x48\x4f\xd0\x69\x19\x7d\xc6\xc8\ +\x6c\x82\xa8\xb4\x60\x8e\xbc\xcf\x59\x40\xbe\xb1\xe9\x5a\xfc\x2a\ +\x30\xa0\x13\x02\xb0\xa9\xa4\x5f\xce\xb9\x21\x87\x1c\x07\xab\xcb\ +\xb7\xe2\xa8\xc0\xab\x6f\x74\xea\x95\x9a\xfa\x12\x6c\x84\x1e\x7c\ +\xa0\xdf\xb4\x14\xe9\xea\xe2\x05\xbc\x02\xad\x19\x34\x46\xb3\x23\ +\x45\x3d\x0c\x54\x40\xe7\x4f\xf5\xec\xd9\xbb\x59\x8f\xed\x86\x2e\ +\x2c\x4c\xaa\x92\xff\xc3\xde\x71\x5f\xcd\x27\x55\x6c\x91\x42\xa7\ +\x89\xaa\x9c\x24\xe3\x2b\xb3\x5a\x1b\x5b\x69\x1d\x25\xc2\x2c\x11\ +\x58\xe9\x0e\xe7\x88\x2c\x83\xba\x95\xda\x32\xad\x66\x99\x6d\xf9\ +\xa6\x4a\xdc\xb3\x72\x12\x57\xda\xb9\xad\x40\xd2\x3a\x93\x20\x00\ +\x92\x7d\xef\xbb\xec\x3e\xdb\x7c\x69\xae\xc5\x7c\x81\xd9\xe0\xac\ +\x76\x12\xdc\x94\xee\x24\x78\x54\xb0\x62\x09\x9e\xcf\x7b\x3b\x09\ +\xbe\x72\x09\xbe\x6c\x64\xe2\x85\xa7\x36\x56\x80\x9f\x97\x13\xe0\ +\xd4\x4c\x6d\x2d\xf2\x7b\x3d\xdb\x4f\x98\x8d\x66\xf4\x9d\xf8\xde\ +\x89\xef\x4d\x8a\xaa\x36\xe3\x54\xb4\x4c\x1e\x48\xb9\x6d\xbf\x75\ +\xd7\xea\xac\x1b\xfd\x49\x0d\xd2\xec\x03\xf7\xd9\x6b\x97\xab\x07\ +\xd2\x0c\x5d\x46\x0c\x2a\xca\x44\x87\xb2\x1c\xda\xd1\x6c\xb5\x7f\ +\x2d\xe1\xb8\x0e\x93\xc3\x96\x97\x78\x8f\x43\xf9\x5a\x7c\x0f\xf1\ +\x99\xe9\x49\x9b\x15\xde\x4c\x19\x58\x37\x27\x9e\x3c\x9e\x11\x23\ +\x45\x3c\x64\xce\xb7\x4c\x45\x8c\x15\xa5\xfc\xc1\xba\x07\x20\x5b\ +\x24\xdf\x3e\x01\x08\xc9\x1d\xf5\x15\x51\x62\x96\x4a\xa4\x03\x07\ +\x8d\x98\xaf\x38\x10\x23\x5d\x61\x93\x91\x08\x95\x21\xc9\x57\x41\ +\xcd\x5d\x7a\x0b\x30\x18\xf5\x6e\x63\x44\xd4\x77\x63\xbe\x6b\xea\ +\x04\x42\x4a\x22\x99\xc4\xe4\xcf\x12\xbe\xeb\x22\x51\x4d\x00\x4a\ +\xf8\xec\x9e\x6f\xac\xaa\xaf\x9b\xcc\xcf\xab\x20\xf3\x32\x2e\xda\ +\xf7\x7d\x4b\xe5\x92\xe8\xee\x98\x7b\x00\xe4\x34\x9e\xc6\x92\xe7\ +\x7a\x0c\x8c\xd0\xb1\x0a\x29\x0a\xac\xdc\x11\x90\xda\x01\x11\x40\ +\xed\xc1\x1d\x97\x2c\x2c\x92\xa6\x3d\xf5\xee\xe8\x14\x28\x4f\xd1\ +\x00\x53\x1d\x89\x2f\x7e\x99\xf5\x58\x05\x2b\xbc\xf5\x44\x8f\x7a\ +\x64\x05\x63\x58\x0c\xa4\x86\xe9\x01\xfe\x3a\x20\xc8\xa1\x63\xfd\ +\x58\xad\xce\x18\x4f\x47\x1b\x9c\x09\x58\x37\xff\x34\x2f\x2a\x61\ +\xa0\x12\x31\xfb\xdf\x45\x30\xa2\x9e\x37\x3d\x20\x80\x48\x16\x68\ +\x32\xc4\x50\x87\x8d\x19\x1e\x58\x65\x31\xe6\x4c\x12\x04\x4e\x32\ +\x0f\xca\x99\x7b\x48\x42\xd6\x13\x63\x6d\xfb\xc4\x39\x10\xbf\xe9\ +\x51\xe0\xac\x30\xe6\x1f\x32\x62\xf8\x35\xf0\x95\x54\x8c\xba\x25\ +\xa2\xfc\x39\xba\x45\x0f\x92\x04\x20\x31\xb9\xf5\x28\x13\x0d\xc5\ +\x4b\x00\xe2\x8f\x30\xfc\xba\xe3\x89\x2c\x9e\x38\xad\x84\x25\x2e\ +\x56\xab\x53\xb4\x09\x15\xd7\x0e\xe8\xa4\x06\x73\x0a\x8c\x05\xa9\ +\x62\xfc\x62\x33\x5a\x30\xbb\x05\x4a\x35\x93\xf8\x42\xc5\xbe\xef\ +\x19\x07\xf7\x58\x7f\xe3\x7b\x53\xf8\x80\xf9\x04\x40\x07\x3b\x07\ +\x8a\xae\x6f\x3e\x7d\xa8\x84\x29\x5e\x24\xe1\x0e\xc1\x7d\xea\x72\ +\x49\x7b\x5e\xe4\x75\x47\x87\xcd\xbf\xb6\x59\x05\x99\x05\xea\x6e\ +\xb0\xbb\x7d\xe5\x4e\xdf\xfc\x1d\xee\xce\xe9\xbb\x6a\xa7\x6f\xb3\ +\xa4\x83\x34\xa0\x2e\x9f\xc8\x59\xa6\xa9\x96\x05\xc0\x93\x72\xcc\ +\x1c\x0e\x96\xe0\x58\x00\x22\xe5\x21\x9e\x44\xc2\xe2\x23\x93\xc7\ +\x23\x08\xb0\xaa\xa2\xbe\xc3\xc8\x53\xee\xf7\xb9\x0f\x70\x97\x60\ +\xd4\x05\xb1\xc5\x80\xfa\x83\x3a\xdc\x39\x0b\x32\xa4\x16\x90\xba\ +\x9c\xf4\xfb\x3c\xed\x29\xb6\x73\x18\xdf\xaf\x47\xed\x03\xf6\x3e\ +\x19\xe4\x6d\xa9\xf4\xa9\xfa\x24\x48\x01\x9f\x65\x01\x7d\x5f\xe2\ +\xc0\x57\x96\xbe\x9f\xf1\xa5\x56\xda\xa0\xc2\x89\x70\x9c\x49\x40\ +\xe8\x80\xa2\xe9\x1a\x33\x6c\xd5\x10\xd4\x66\x80\x4e\x15\xea\x6b\ +\xc3\x97\xfb\x2e\x77\x28\x1a\xb9\x26\x32\x41\x44\x9f\x30\x98\x55\ +\x09\x1f\xc6\xa2\x44\x00\x7a\xcf\x47\x93\x51\x25\x5a\xbb\x4f\x3d\ +\xb9\x0e\xb5\x0d\x73\xf8\x99\x74\xf6\x4e\x63\xcf\xc7\x74\x15\x61\ +\xda\xfc\x1d\x32\xf3\xd1\x06\x5e\x3d\xfd\xe7\x8a\x9d\xdf\x0c\xd7\ +\xa6\xa5\x04\xaa\xfc\x1e\xd3\x71\x05\xee\xb2\x00\xc4\x48\xdc\x4e\ +\xa8\x42\x86\xcc\x01\x64\x03\xb5\x7f\x7e\x76\x43\x55\xab\x68\xc5\ +\x6b\x76\x00\xfa\xf2\xf2\x72\xf9\x10\x74\x5e\x5e\xf5\xc9\x7a\x22\ +\xdb\x46\xec\xbe\x36\x0b\xbe\xa5\xb2\xb7\x6a\x8b\xa5\x59\x89\xc5\ +\x52\x62\x13\x01\x16\x4b\xc2\xd7\xd6\x35\xbb\x7a\x13\xb8\x99\xb9\ +\x19\x86\x42\x9f\xb0\x61\x3e\xbb\x05\xb6\x46\x0f\x04\x06\x7f\xaa\ +\x94\x24\x5d\x18\x32\xbc\x46\x21\x06\xd2\x36\xbb\x13\x10\x8b\x38\ +\x97\x97\xf4\xc7\x3d\x66\x53\x80\x68\x97\x3d\x02\xf7\x0e\x74\x59\ +\x78\x09\x42\x9c\x58\x8d\x5f\x76\x22\x4b\x44\x3d\x0a\x2c\xe6\x10\ +\xa0\xd8\xf6\xc5\xac\x3a\x42\x51\xe0\xa4\x7e\x01\xba\x69\x2e\xc8\ +\x74\xce\x93\x76\x3c\x26\xed\x28\xb1\x20\xd8\x5d\x96\x76\x9d\x0c\ +\xa3\x50\x32\xde\xc4\x81\x65\x63\x8f\xfa\x8c\xc4\x0c\x69\x02\x52\ +\x8f\xd1\x40\x12\x77\x82\x9d\x86\x1e\x5a\x82\x60\xe8\x06\xd5\x6c\ +\xcf\x50\x20\x7e\xb5\x30\x7d\xd4\x30\xa9\x80\xc2\x54\x4a\xc8\xc4\ +\x82\xc2\x4b\x8f\x7a\x13\x0e\xba\x23\xfa\x2c\xa2\xaf\x26\x2a\x57\ +\x22\x0f\x3e\xcb\x25\x91\x88\xa5\x19\x6a\xc6\x24\x8d\x3e\xbc\xc2\ +\x26\x21\x4a\xd7\x38\x24\x7f\x84\x91\x6d\x6d\x1d\x4c\xd3\x5f\xdc\ +\x71\x80\x32\x28\x92\xae\x55\x80\xe2\xdf\xe0\x58\xb3\xa3\xbe\xd3\ +\xf2\x39\x24\x05\xc8\x1d\x51\xb1\x8b\x3e\xcf\x27\xf3\xb2\xb7\x46\ +\x95\xbd\x85\x25\x21\x9c\x37\x32\xf3\x39\x7f\x86\x05\x48\xd1\x92\ +\xfd\xd7\x8f\x9b\x4a\x8b\xe5\xf2\x66\x7f\x17\xd9\x0b\xb8\x9e\xac\ +\xdd\x7f\xff\x45\x9e\xde\x88\x71\x66\xf4\x63\x4d\x10\xfc\x87\x3c\ +\x7d\x13\x00\x6f\xd5\x08\xc3\x5f\x00\x43\x17\x0c\xda\x52\x20\xd4\ +\x2d\x92\x9a\xd5\x64\x94\x95\xc8\xf9\x7d\x9f\xb0\x36\x07\x01\x77\ +\x13\xfa\x53\x87\xeb\xad\xf1\x58\x85\xfe\xfc\x0c\x5b\x74\x1c\x74\ +\xab\x9d\xf9\x66\x02\x9b\x29\xf8\x56\x1e\x7d\xcf\xf7\xe3\xec\x7c\ +\xf9\x65\x7c\xf9\x45\x76\x98\xf9\x67\x19\x6a\x71\xf1\xa7\xfd\x74\ +\xc6\x01\x12\x93\x29\x26\x29\xa7\xc7\xc8\x2d\x97\x1c\xd3\x70\xb4\ +\x78\x89\x9a\xa2\xc5\xd4\x63\xbe\x33\xc4\x9d\x00\xde\xe7\x78\xcb\ +\x62\xe6\x7d\x2c\x81\x68\xa2\xb3\x87\x68\x98\xca\x5a\x65\x06\x11\ +\xec\x29\xd7\x62\xcd\xdb\x44\x1e\x18\xee\xed\x8f\x25\x4e\x1e\x61\ +\x69\xe7\x67\x44\x57\x46\xcb\xf3\x73\x94\x91\x64\xed\xed\xbf\x35\ +\x18\xee\xaf\xc4\x04\x26\x3c\x2f\x3a\xe4\xea\xda\x30\x46\xb4\x81\ +\x91\x3e\x7d\xaa\xdd\x20\x0f\x78\x5d\xdd\x31\x60\x58\x46\x81\xa9\ +\xb5\x24\xc0\x33\x0f\xcb\x33\x94\xcb\x1c\x3e\x02\xc8\xb3\xa3\x48\ +\x25\x82\x48\xd9\x51\x2f\x83\x6b\x8c\x7a\x5d\x1e\x5e\x5e\x5c\xce\ +\xfe\x9d\x5f\xb4\xda\x0d\x5b\x59\x78\xa8\xac\x30\x98\xed\xab\x79\ +\x78\x94\xfc\xb7\xfc\x28\x05\xed\x97\x6e\x48\xed\x3f\x93\xdc\xa9\ +\x27\xc0\x9a\x17\x9a\xe6\xbe\x66\x10\x49\x30\x88\xf5\xf8\x83\x75\ +\xeb\x8b\x49\xe7\x27\x1e\xd5\x94\x59\xc0\x7d\x83\xb4\x30\x16\x68\ +\x6e\xdb\x53\x43\x8e\x5e\xe0\x43\xd2\xc5\x4c\xc3\xfe\x94\x80\x1d\ +\xc1\x08\xba\xa8\xc1\x66\x98\x12\xf9\x7d\x42\x03\x26\x67\x22\x6a\ +\x14\x76\x53\x22\x21\x39\x27\xc2\xdd\x3c\x5a\x4b\x84\x1b\x79\xf9\ +\xb5\xa1\x9d\x2d\xe5\xe4\xaa\xb7\xe0\x25\xef\x0e\x5b\x90\x69\x3f\ +\x97\xb7\xdf\xe3\x1d\xe5\x3e\xe6\xbb\x06\x40\x8d\x78\xca\x8f\x78\ +\xc0\xe4\x99\xa7\xc1\x6b\xe6\xf1\x7c\x9b\xc2\x6a\xca\x2e\xec\x88\ +\x1e\xbb\xeb\x3a\xcb\xdf\x75\x35\xcf\xce\xcf\xcf\x5b\xcd\xd3\x32\ +\x7b\xaf\xe2\x26\x4a\x94\xff\x13\x1a\x15\x78\xfc\x8d\x87\xcb\xe4\ +\x08\x11\xb8\xdc\xa7\x8a\xc9\x58\xd4\x8c\x3c\xc5\xf4\x24\x76\x7f\ +\x48\x8e\xc9\x15\x39\x02\x75\xdd\x2c\x91\x95\x9c\x23\x2e\xce\xd6\ +\x22\x2d\x66\xb4\xb8\xb5\xd2\xa2\xa8\xfb\x22\x5f\x7f\xed\xdc\x17\ +\x2b\x3f\x3c\xb0\xac\xbc\x7c\xc5\x47\xcc\xd7\x87\xa1\xb7\x40\x62\ +\xe6\x6f\x60\x73\x33\xea\x2e\xaa\xc9\xa7\x5b\x8b\xf8\x70\xf9\xe8\ +\xe3\xd6\x4b\x90\xaa\xed\x8d\x02\x07\xfe\xb2\x18\x68\x41\xde\xdc\ +\x5c\xfe\xb9\x11\x1e\x28\x2d\xdf\xa9\x34\xf2\x98\x2f\x6b\xf3\x59\ +\x7f\x27\x6b\x57\xe2\x2a\x2e\xe0\x2c\xfa\x09\xcc\xba\xe8\x02\x1b\ +\x2d\x1c\x31\xd5\xce\xc5\xbc\x8c\xfe\xc4\x77\x8c\x01\xa7\x86\x54\ +\xe9\xcc\x50\x4a\x54\xc8\x22\x87\x7b\x5f\xb0\xb5\x3d\xdf\xe2\xf2\ +\x7e\x1f\x76\x8a\x50\x8e\x9b\x43\x0f\xf6\x8b\x3a\x39\xc5\x74\x18\ +\x6e\x31\x55\xc0\xf4\xa1\x17\x2a\x89\x04\xc0\x4a\xec\x19\x73\x4e\ +\x71\x35\x96\x21\x78\x7f\x00\xe4\xa0\x58\x1a\x45\xd6\x8f\x04\x26\ +\x6b\x73\x45\x1e\xa6\x1c\x3f\x16\x8c\x72\xba\x7e\x3f\x96\x8a\x44\ +\xde\x4e\x17\x65\xe9\xa2\xb3\x72\xaa\x68\x41\x86\xd7\xc2\x84\x18\ +\x6c\x41\x8c\x2c\xd8\x70\xaf\x7a\x7e\x40\xfd\x47\x10\x95\xe1\x9a\ +\x98\xf1\xf4\xa1\x1b\x5c\x1e\xa9\xef\x25\x72\x67\xb6\xf7\x6a\xf7\ +\xb6\x33\xe9\xd0\xaa\xc1\xcb\x8d\xd3\x0b\x89\x6f\x4b\xc5\x43\x51\ +\x03\x2c\xdf\x91\xb3\x33\xc0\x56\xbd\xd9\x5d\x70\xb3\xd3\xe3\x04\ +\x64\x1f\xf0\xbd\x89\x37\x0b\x2e\x9f\x63\x94\x75\xaf\x20\xce\x52\ +\x7f\x3b\xfb\x35\x47\x93\x02\x90\x25\x84\x0e\xf7\xde\x03\xbc\xd4\ +\x47\xbb\x8b\xc6\xbe\x94\x13\x67\x88\x06\xd8\x93\xef\x13\xa1\x9e\ +\xbf\x08\x38\xf5\xcc\x23\xa6\x32\x85\x03\x49\x35\xf5\xd2\x4d\x25\ +\xf5\x65\xd8\xd2\x96\xb0\x80\xf7\xcd\xe3\x1e\xc0\x63\x9e\x46\xc2\ +\x17\x61\x33\x04\x92\xf4\xe9\x88\x7b\xd3\xac\x71\x0f\xde\x31\xef\ +\x96\xe1\xef\x9f\x1e\x44\x9d\x9b\x8f\x34\xa8\xda\xb0\xa4\x06\x98\ +\xbd\x8c\xef\x9f\xbd\x14\x9e\x6b\xde\x2b\x49\x66\xc0\x31\x96\xef\ +\x98\x7a\x7c\xe0\xc3\x6a\x3c\xe8\x1d\x08\x0f\xc5\xc4\x0b\xac\xff\ +\x84\xac\xf8\xbf\xd9\xeb\x4d\x40\x39\x90\xce\x20\x2a\xf9\x72\xcd\ +\xd0\xb9\x0a\x60\x30\x55\x1c\x86\x82\x92\xde\x70\xd1\x96\xca\xf9\ +\xaa\x5d\x12\x05\x4e\xf8\x65\xfa\xf4\x96\xbd\xc7\x3f\x92\x73\xa3\ +\xb1\x87\x3f\x05\x2b\x87\x8c\x55\x2a\xec\xf2\xf5\xe3\x82\x89\xec\ +\x14\xe4\x4a\x3c\x14\x6f\xb8\xc7\xae\x87\x42\x80\x8c\x7d\xa0\x5c\ +\xfa\x50\xe7\x98\xba\x45\x46\x37\xf7\x8b\x1a\xdd\xc7\x47\xf9\x08\ +\x2a\x85\x9f\xe2\x01\x27\x37\x4d\xfd\xf6\x7e\x52\x9d\xd1\xe6\xa0\ +\x3f\xc1\x24\xb5\xe1\x6f\x58\x85\xe7\xb5\x8a\x31\x48\x39\xa1\x69\ +\xa0\xda\x09\xcd\x39\x42\xb3\xc0\x9d\xb7\x19\x42\xb3\x7c\x14\xe4\ +\x09\x1d\x8d\x9f\x93\x0f\x8c\xba\x20\xd0\x68\x10\x88\x3b\x63\x4e\ +\x6c\xe2\xc9\x92\x95\x9d\x2b\xe1\x23\xf3\xbb\xa4\x9b\x4a\x95\xe5\ +\xce\x34\xbc\x12\x8a\x9c\xd6\x77\xa4\x02\x87\x3f\xaf\x77\xf8\xcb\ +\xfa\x86\xbf\xe6\x81\x03\x3b\x83\x1a\xf1\x6f\x21\xa8\x71\x09\x2c\ +\x04\x35\xae\x42\x17\x44\xcb\xb0\xce\x45\x30\x00\xd4\xb8\x06\x06\ +\x80\x1a\x97\xe0\x25\x75\xbe\xc9\xba\x97\x21\x02\xa2\xc6\xa5\x88\ +\x80\x28\xb5\x1c\xb5\x9b\x2a\x25\xfd\xfc\xcd\xfc\x24\x99\xf9\xd6\ +\xca\x17\x68\xc5\x1d\xea\xc5\x7c\x37\xc6\xa7\x15\xdb\x49\x6d\xa2\ +\xb9\xb2\xaa\x5f\x81\x8e\x5f\xc0\x20\xfa\xc6\xdf\x15\x62\xc2\x7a\ +\xb6\xec\x89\x17\xd8\xf0\xc4\x91\x44\x03\x46\x6e\x2d\xf2\x0e\x49\ +\xb8\x4d\x86\x5e\x3d\xd6\x57\x07\x78\xcb\xae\x39\x13\x83\x3d\xbe\ +\xef\xfe\x81\xb7\xb5\xfb\x2e\x0d\xca\x5c\x28\x5d\xcc\x0a\x4b\x2c\ +\xe0\x8f\x68\x8a\x7d\x00\x44\x93\xa7\x71\xdc\xd6\x78\xd6\xf5\xd3\ +\xbc\x10\xd9\x96\x48\xa0\x92\xe2\x67\xd9\xdf\xbc\x7e\xe1\xe9\xdc\ +\x4d\xd8\x59\x77\xbf\xbc\x25\x40\x68\xf8\x0a\x3c\x24\x9c\xca\x25\ +\xcf\x02\x3f\x53\xfe\x61\xbd\x9d\x9f\x69\xad\x7e\xa6\x05\xe9\xcd\ +\x5b\xed\x67\x7a\x87\x47\x1c\xf0\xee\x33\x0c\x97\x48\x7b\xee\x81\ +\x82\xaa\x09\x98\xa3\x44\x30\xc5\x8b\x16\x95\xfd\x79\x67\x64\x12\ +\xc4\x8b\x8c\x17\x3e\xf1\xd4\xf3\xb1\xe1\x9c\x27\x03\xf5\x1c\x9d\ +\x56\x78\xf7\x72\x94\x3a\x13\xc6\x61\x5c\x97\xb9\xe8\xc1\x42\x95\ +\x14\x8a\x4c\x1b\xc3\x81\x66\xa0\xae\x6c\x2f\xeb\xf9\x2d\x1b\x3b\ +\x18\x92\xc0\xa6\xea\xa7\x72\x32\x39\x59\x99\xe8\x2b\x6a\x17\x6b\ +\x14\x6b\x61\xe5\xf7\x2c\x20\x66\x4e\x7a\x5d\xed\x9f\xed\x93\x11\ +\x0d\x06\xdc\xbf\xda\x6f\x36\xf7\x31\xd7\xa8\x3d\xe6\xf7\x23\x3a\ +\x0e\x93\xa5\x3a\xdf\x3f\xea\xf7\x37\x81\x18\xfd\x06\xc6\x4a\x57\ +\x4c\x02\x4c\xae\x49\xb5\x82\xef\x9c\x89\x54\x62\x64\x46\x94\x1a\ +\x92\x78\x89\x81\x52\xb3\x6b\x47\x73\x6b\x8c\x53\x01\x7f\xba\x5c\ +\x37\x01\xc9\xce\x7c\x57\x76\xfe\xfc\xaa\xbf\x03\x51\x67\x0b\xf6\ +\x0c\x37\xa1\xeb\x0b\x7b\x68\x60\x07\xaf\x38\xf5\xc4\xe0\x70\x88\ +\xcc\xa5\x2b\x34\x02\xd2\xe3\xe6\x03\x72\x8d\x3f\xc5\xf4\x72\xa2\ +\x94\x36\x6b\x32\x00\xf9\x38\x91\xc3\xb0\x7e\x1e\x30\x06\x58\x59\ +\x0e\x92\x94\x00\xcb\x84\xe6\x21\xee\xe6\x81\x84\xbd\xad\x0c\x2c\ +\x9b\x32\x93\x8d\xa0\x59\xe5\x5a\x40\x59\xb4\x5e\x0f\x17\x75\x3d\ +\x60\xd9\xe3\xfa\xd9\x28\x8a\x6a\xd7\x84\x23\xb3\xdb\x99\x03\xcc\ +\xac\x76\x2d\xc0\x84\x59\x05\xd9\xc0\x44\xb5\x6b\x01\x26\x91\x01\ +\x96\x0d\x51\xaa\x49\x79\xb0\x92\x05\xd8\x53\x3b\x60\x52\x0b\x52\ +\xa9\x45\x2e\xe8\x5e\x9f\x99\xdc\x54\x33\x8b\xd9\xbb\x19\x55\x02\ +\x00\xd0\x77\xc6\xa5\x2f\x18\x48\xf7\xed\xb8\x68\x9d\x0c\x7c\xea\ +\x75\x1c\x0f\x0f\x3d\xba\x4f\xf1\x9c\x25\xee\x60\x4c\xa9\x6e\x01\ +\x26\x00\xe3\xb7\xf1\xbe\x52\x47\xc9\xdb\x8d\x59\x13\xd3\xa5\x27\ +\x54\x07\xd4\xe0\x6b\x73\xaa\x73\xd6\x27\x16\x1b\x8c\xe0\x2f\x37\ +\x58\x8d\x84\xcf\x44\x4d\xc7\x68\x6a\xea\xe9\x25\xc2\x1e\xed\xfb\ +\xce\x25\x00\x7c\x1f\xbe\x4e\x3b\xc7\xe7\x97\xed\xc6\x34\x54\x67\ +\xf8\xf5\xc3\x8e\x5c\x86\xbf\x36\xa3\x0d\xe3\x74\x6f\x27\xcd\xf3\ +\x64\x77\x17\xcd\xac\xee\xcc\xa3\xb4\x4b\x93\x40\xed\x5a\x31\x3d\ +\x3b\x3e\x5b\x2d\x8e\x11\xa7\x09\x1c\x1f\x97\xc1\xf1\xe9\x79\x33\ +\xd5\xdd\x49\x65\x38\x3e\x59\x1d\x8e\xcf\xaa\xc5\xf1\x59\x92\xf0\ +\x5a\xe7\x47\xab\xc4\x71\xeb\xbc\xb5\x81\x38\x0e\xaf\x95\xaf\x18\ +\xb3\xad\x95\x62\xb6\x79\xb6\x36\xcc\x2e\x2f\x21\xc2\x1b\x50\xaa\ +\xc5\xec\xe9\x45\x92\x91\xcf\x4e\xcb\x60\xf6\xf8\xf4\x64\x0b\x64\ +\x6f\x78\xc7\x43\xb5\x98\x3d\x3e\x4e\x61\xf6\x7c\x95\x34\x5b\x25\ +\x66\xcf\xcb\x4b\xdc\xe8\x9e\xec\x6a\x91\xdc\x4c\xd1\x6f\xeb\xb2\ +\x94\x64\x38\x41\x7f\x4d\xa2\xbb\x4c\x35\xb9\x29\xb6\x43\xec\xce\ +\xaf\x8a\xad\x87\xb4\x85\x56\x4a\x4a\xb4\x5a\x67\x8f\x31\x46\xe6\ +\x63\x39\xfe\x0a\xf5\xed\xc6\x84\x77\xf6\xfe\x0f\x9b\x41\x85\x54\ +\ \x00\x00\x07\xb5\ \x00\ \x00\x1a\x6e\x78\x9c\xed\x58\x5d\x6f\xe3\xb8\x15\x7d\xcf\xaf\x50\ @@ -37846,83 +37851,83 @@ qt_resource_struct = "\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x35\x00\x00\x00\x1b\ \x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x16\ \x00\x00\x00\x1a\x00\x02\x00\x00\x00\x11\x00\x00\x00\x05\ -\x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x06\x48\x2f\ -\x00\x00\x02\x02\x00\x01\x00\x00\x00\x01\x00\x05\x44\xb8\ -\x00\x00\x01\x92\x00\x00\x00\x00\x00\x01\x00\x03\x7e\x56\ -\x00\x00\x02\x56\x00\x01\x00\x00\x00\x01\x00\x05\xe1\x7b\ -\x00\x00\x02\x3a\x00\x01\x00\x00\x00\x01\x00\x05\xac\xbf\ -\x00\x00\x01\x3e\x00\x01\x00\x00\x00\x01\x00\x02\x0b\x3a\ -\x00\x00\x02\x1e\x00\x01\x00\x00\x00\x01\x00\x05\x77\x8d\ -\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x04\ -\x00\x00\x02\x72\x00\x01\x00\x00\x00\x01\x00\x06\x15\x26\ -\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x02\x3d\x78\ -\x00\x00\x01\x22\x00\x00\x00\x00\x00\x01\x00\x01\x62\xc3\ -\x00\x00\x01\xae\x00\x01\x00\x00\x00\x01\x00\x04\x2e\x7d\ -\x00\x00\x01\x76\x00\x00\x00\x00\x00\x01\x00\x02\xe8\xa5\ -\x00\x00\x01\x06\x00\x01\x00\x00\x00\x01\x00\x01\x2f\xb4\ -\x00\x00\x00\xea\x00\x00\x00\x00\x00\x01\x00\x00\x83\xef\ -\x00\x00\x01\xca\x00\x00\x00\x00\x00\x01\x00\x04\x61\xd1\ -\x00\x00\x01\xe6\x00\x01\x00\x00\x00\x01\x00\x05\x12\xa0\ +\x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x06\x48\x2e\ +\x00\x00\x02\x02\x00\x01\x00\x00\x00\x01\x00\x05\x44\xb7\ +\x00\x00\x01\x92\x00\x00\x00\x00\x00\x01\x00\x03\x7e\x55\ +\x00\x00\x02\x56\x00\x01\x00\x00\x00\x01\x00\x05\xe1\x7a\ +\x00\x00\x02\x3a\x00\x01\x00\x00\x00\x01\x00\x05\xac\xbe\ +\x00\x00\x01\x3e\x00\x01\x00\x00\x00\x01\x00\x02\x0b\x39\ +\x00\x00\x02\x1e\x00\x01\x00\x00\x00\x01\x00\x05\x77\x8c\ +\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x03\ +\x00\x00\x02\x72\x00\x01\x00\x00\x00\x01\x00\x06\x15\x25\ +\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x02\x3d\x77\ +\x00\x00\x01\x22\x00\x00\x00\x00\x00\x01\x00\x01\x62\xc2\ +\x00\x00\x01\xae\x00\x01\x00\x00\x00\x01\x00\x04\x2e\x7c\ +\x00\x00\x01\x76\x00\x00\x00\x00\x00\x01\x00\x02\xe8\xa4\ +\x00\x00\x01\x06\x00\x01\x00\x00\x00\x01\x00\x01\x2f\xb3\ +\x00\x00\x00\xea\x00\x00\x00\x00\x00\x01\x00\x00\x83\xee\ +\x00\x00\x01\xca\x00\x00\x00\x00\x00\x01\x00\x04\x61\xd0\ +\x00\x00\x01\xe6\x00\x01\x00\x00\x00\x01\x00\x05\x12\x9f\ \x00\x00\x00\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x06\x29\ \x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\ \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\ \x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\ -\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x70\x84\ -\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xc2\x31\ -\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x24\x4e\ -\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xe3\x36\ -\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x0d\x18\ -\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x8d\xce\ -\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe6\x6c\ -\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb7\x9d\ -\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x5d\xdd\ -\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xff\x46\ -\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xdb\x53\ -\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xec\x30\ -\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x7b\x38\ -\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xe0\xd2\ -\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa6\x93\ -\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xd0\xe7\ -\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc5\x7c\ -\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x9c\x7b\ -\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x28\x37\ -\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xb1\x86\ -\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xbb\xe8\ -\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x16\x1e\ -\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x94\xc2\ -\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x0d\x24\ -\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x6e\x25\ -\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x39\xa7\ -\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x84\xd8\ -\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xce\x3f\ -\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xfc\x3a\ -\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xed\xd0\ -\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x50\xe6\ -\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\xa4\x82\ -\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x0b\x1f\ -\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\xa2\x5f\ -\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb9\xa2\ -\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x2c\xf7\ -\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xce\x09\ -\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x63\x25\ -\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xc4\x8e\ -\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x49\x4c\ -\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x07\x02\xd7\ -\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xdf\xf7\ -\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x34\x28\ -\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x64\x52\ -\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x08\x01\xb2\ -\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x14\x78\ -\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd8\xb4\ -\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x97\xaf\ -\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xf3\xf1\ -\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xf1\xe0\ -\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x41\x8c\ -\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x9d\x1f\ -\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x34\x48\ -\x00\x00\x02\xaa\x00\x01\x00\x00\x00\x01\x00\x06\x7b\xb2\ -\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x85\x1f\ +\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x07\x70\xc5\ +\x00\x00\x03\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xc2\x72\ +\x00\x00\x08\x38\x00\x01\x00\x00\x00\x01\x00\x08\x24\x8f\ +\x00\x00\x0a\x7e\x00\x01\x00\x00\x00\x01\x00\x08\xe3\x77\ +\x00\x00\x04\xba\x00\x01\x00\x00\x00\x01\x00\x07\x0d\x59\ +\x00\x00\x06\x4a\x00\x00\x00\x00\x00\x01\x00\x07\x8e\x0f\ +\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xe6\xad\ +\x00\x00\x06\xbe\x00\x00\x00\x00\x00\x01\x00\x07\xb7\xde\ +\x00\x00\x08\xd2\x00\x01\x00\x00\x00\x01\x00\x08\x5e\x1e\ +\x00\x00\x0a\xce\x00\x01\x00\x00\x00\x01\x00\x08\xff\x87\ +\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x06\xdb\x94\ +\x00\x00\x07\x84\x00\x01\x00\x00\x00\x01\x00\x07\xec\x71\ +\x00\x00\x06\x24\x00\x00\x00\x00\x00\x01\x00\x07\x7b\x79\ +\x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xe1\x13\ +\x00\x00\x06\x92\x00\x01\x00\x00\x00\x01\x00\x07\xa6\xd4\ +\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x06\xd1\x28\ +\x00\x00\x0a\x08\x00\x00\x00\x00\x00\x01\x00\x08\xc5\xbd\ +\x00\x00\x03\x30\x00\x01\x00\x00\x00\x01\x00\x06\x9c\xbc\ +\x00\x00\x05\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x28\x78\ +\x00\x00\x09\xc0\x00\x01\x00\x00\x00\x01\x00\x08\xb1\xc7\ +\x00\x00\x09\xe2\x00\x01\x00\x00\x00\x01\x00\x08\xbc\x29\ +\x00\x00\x04\xe8\x00\x00\x00\x00\x00\x01\x00\x07\x16\x5f\ +\x00\x00\x02\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x95\x03\ +\x00\x00\x07\xee\x00\x01\x00\x00\x00\x01\x00\x08\x0d\x65\ +\x00\x00\x09\x2c\x00\x00\x00\x00\x00\x01\x00\x08\x6e\x66\ +\x00\x00\x05\x5e\x00\x01\x00\x00\x00\x01\x00\x07\x39\xe8\ +\x00\x00\x09\x50\x00\x00\x00\x00\x00\x01\x00\x08\x85\x19\ +\x00\x00\x07\x18\x00\x00\x00\x00\x00\x01\x00\x07\xce\x80\ +\x00\x00\x04\x6c\x00\x01\x00\x00\x00\x01\x00\x06\xfc\x7b\ +\x00\x00\x0a\x9e\x00\x00\x00\x00\x00\x01\x00\x08\xee\x11\ +\x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x07\x51\x27\ +\x00\x00\x03\x5c\x00\x00\x00\x00\x00\x01\x00\x06\xa4\xc3\ +\x00\x00\x0a\xfe\x00\x00\x00\x00\x00\x01\x00\x09\x0b\x60\ +\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x08\xa2\xa0\ +\x00\x00\x03\x80\x00\x01\x00\x00\x00\x01\x00\x06\xb9\xe3\ +\x00\x00\x08\x5a\x00\x01\x00\x00\x00\x01\x00\x08\x2d\x38\ +\x00\x00\x0a\x2e\x00\x00\x00\x00\x00\x01\x00\x08\xce\x4a\ +\x00\x00\x05\xe0\x00\x01\x00\x00\x00\x01\x00\x07\x63\x66\ +\x00\x00\x06\xf0\x00\x01\x00\x00\x00\x01\x00\x07\xc4\xcf\ +\x00\x00\x08\xb0\x00\x00\x00\x00\x00\x01\x00\x08\x49\x8d\ +\x00\x00\x04\x90\x00\x01\x00\x00\x00\x01\x00\x07\x03\x18\ +\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x07\xe0\x38\ +\x00\x00\x05\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x34\x69\ +\x00\x00\x08\xfc\x00\x01\x00\x00\x00\x01\x00\x08\x64\x93\ +\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x08\x01\xf3\ +\x00\x00\x08\x10\x00\x01\x00\x00\x00\x01\x00\x08\x14\xb9\ +\x00\x00\x0a\x54\x00\x01\x00\x00\x00\x01\x00\x08\xd8\xf5\ +\x00\x00\x09\x74\x00\x01\x00\x00\x00\x01\x00\x08\x97\xf0\ +\x00\x00\x04\x3c\x00\x01\x00\x00\x00\x01\x00\x06\xf4\x32\ +\x00\x00\x07\xa6\x00\x00\x00\x00\x00\x01\x00\x07\xf2\x21\ +\x00\x00\x05\x8c\x00\x00\x00\x00\x00\x01\x00\x07\x41\xcd\ +\x00\x00\x06\x72\x00\x01\x00\x00\x00\x01\x00\x07\x9d\x60\ +\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x08\x34\x89\ +\x00\x00\x02\xaa\x00\x01\x00\x00\x00\x01\x00\x06\x7b\xb1\ +\x00\x00\x02\xd6\x00\x01\x00\x00\x00\x01\x00\x06\x85\x1e\ " def qInitResources(): diff --git a/src/Mod/Draft/Resources/ui/userprefs-base.ui b/src/Mod/Draft/Resources/ui/userprefs-base.ui index 1928878206..ebf2bdbd97 100755 --- a/src/Mod/Draft/Resources/ui/userprefs-base.ui +++ b/src/Mod/Draft/Resources/ui/userprefs-base.ui @@ -562,6 +562,26 @@ + + + + + + if checked, a widget indicating the current working plane orientation appears during drawing operations + + + Show Working Plane tracker + + + showPlaneTracker + + + Mod/Draft + + + + + @@ -873,19 +893,6 @@ Values with differences below this value will be treated as same. - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -908,17 +915,6 @@ Values with differences below this value will be treated as same. - - - - - - - - Default text font - - - @@ -932,6 +928,13 @@ Values with differences below this value will be treated as same. + + + + Default text font + + + From fb3f051563a79e3ae4095d37a3b9cf093c72a5a8 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 6 Jun 2012 17:04:24 -0300 Subject: [PATCH 327/351] Draft: snap toolbar now appears on WB activation --- src/Mod/Arch/InitGui.py | 8 ++++++-- src/Mod/Draft/DraftSnap.py | 4 ++-- src/Mod/Draft/InitGui.py | 12 +++++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 6267d9077e..2701e5616c 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -85,11 +85,15 @@ class ArchWorkbench(Workbench): Log ('Loading Arch module... done\n') def Activated(self): - FreeCADGui.draftToolBar.Activated() + if hasattr(FreeCADGui,"draftToolBar"): + FreeCADGui.draftToolBar.Activated() + if hasattr(FreeCADGui,"Snapper"): + FreeCADGui.Snapper.show() Msg("Arch workbench activated\n") def Deactivated(self): - FreeCADGui.draftToolBar.Deactivated() + if hasattr(FreeCADGui,"draftToolBar"): + FreeCADGui.draftToolBar.Deactivated() Msg("Arch workbench deactivated\n") def ContextMenu(self, recipient): diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 3918be2b2f..746bb7bc94 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -167,7 +167,7 @@ class Snapper: self.radius = self.getScreenDist(Draft.getParam("snapRange"),screenpos) # set the grid - if self.grid and Draft.getParam("grid") and (not self.forceGridOff): + if self.grid and (not self.forceGridOff): self.grid.set() # activate snap @@ -894,7 +894,7 @@ class Snapper: def setGrid(self): "sets the grid, if visible" - if self.grid: + if self.grid and (not self.forceGridOff): if self.grid.Visible: self.grid.set() diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 3e2bd5696d..b4b83ee359 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -201,10 +201,16 @@ class DraftWorkbench (Workbench): self.appendMenu([str(DraftTools.translate("draft","&Draft")),str(DraftTools.translate("draft","Wire tools"))],self.lineList) def Activated(self): - FreeCADGui.draftToolBar.Activated() - + if hasattr(FreeCADGui,"draftToolBar"): + FreeCADGui.draftToolBar.Activated() + if hasattr(FreeCADGui,"Snapper"): + FreeCADGui.Snapper.show() + Msg("Draft workbench activated\n") + def Deactivated(self): - FreeCADGui.draftToolBar.Deactivated() + if hasattr(FreeCADGui,"draftToolBar"): + FreeCADGui.draftToolBar.Deactivated() + Msg("Draft workbench deactivated\n") def ContextMenu(self, recipient): if (recipient == "View"): From db8ebb31e63af9aff2073eb1a276e9a82f2e69a3 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 7 Jun 2012 10:42:55 -0300 Subject: [PATCH 328/351] Arch: fixed import error --- src/Mod/Arch/InitGui.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index 2701e5616c..7f4c510795 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -109,7 +109,8 @@ FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ") try: import collada except: - FreeCAD.Console.PrintMessage(str(DraftTools.translate("arch","pycollada not found, collada support will be disabled.\n"))) + from DraftTools import translate + FreeCAD.Console.PrintMessage(str(translate("arch","pycollada not found, collada support will be disabled.\n"))) else: FreeCAD.addImportType("Collada (*.dae)","importDAE") FreeCAD.addExportType("Collada (*.dae)","importDAE") From 04d21035669c99e77e5b2b5c4a01d678e0181456 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 7 Jun 2012 10:43:32 -0300 Subject: [PATCH 329/351] Draft: Made the grid appear on module activation --- src/Mod/Draft/DraftSnap.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 746bb7bc94..846cb522c1 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -883,7 +883,7 @@ class Snapper: return False def show(self): - "shows the toolbar" + "shows the toolbar and the grid" if not hasattr(self,"toolbar"): self.makeSnapToolBar() mw = getMainWindow() @@ -891,6 +891,11 @@ class Snapper: if not bt: mw.addToolBar(self.toolbar) self.toolbar.show() + if FreeCADGui.ActiveDocument: + if not self.forceGridOff: + if not self.grid: + self.grid = DraftTrackers.gridTracker() + self.grid.set() def setGrid(self): "sets the grid, if visible" From cfee1c192fad0b323d838181e6b5aeb5747e0131 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 7 Jun 2012 20:17:38 +0200 Subject: [PATCH 330/351] 0000738: Compress stuff in Tree view --- src/Gui/CombiView.cpp | 2 ++ src/Gui/Tree.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Gui/CombiView.cpp b/src/Gui/CombiView.cpp index 1632c4a749..b7cdb1f7f9 100644 --- a/src/Gui/CombiView.cpp +++ b/src/Gui/CombiView.cpp @@ -64,6 +64,8 @@ CombiView::CombiView(Gui::Document* pcDocument, QWidget *parent) // tree widget tree = new TreeWidget(this); //tree->setRootIsDecorated(false); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/TreeView"); + tree->setIndentation(hGrp->GetInt("Indentation", tree->indentation())); splitter->addWidget(tree); // property view diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index c453662a59..48d27f3256 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -726,6 +726,8 @@ TreeDockWidget::TreeDockWidget(Gui::Document* pcDocument,QWidget *parent) setWindowTitle(tr("Tree view")); this->treeWidget = new TreeWidget(this); this->treeWidget->setRootIsDecorated(false); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/TreeView"); + this->treeWidget->setIndentation(hGrp->GetInt("Indentation", this->treeWidget->indentation())); QGridLayout* pLayout = new QGridLayout(this); pLayout->setSpacing(0); From 10de9074c6c5d23c7a081485c5ba4c495095a9a2 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 7 Jun 2012 22:14:58 +0200 Subject: [PATCH 331/351] 0000739: Chamfer/Fillet(PartDesign) on whole body produces infinite loop --- src/Mod/PartDesign/Gui/Command.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index c5fa4d2ad1..37e02dc6a9 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -428,11 +428,15 @@ void CmdPartDesignFillet::activated(int iMsg) SubNames.erase(SubNames.begin()+i); } + // empty name or any other sub-element + else { + SubNames.erase(SubNames.begin()+i); + } } - if(SubNames.size() == 0){ + if (SubNames.size() == 0) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("No Fillet possilbe on seleced faces/edges")); + QObject::tr("No fillet possible on selected faces/edges")); return; } @@ -571,11 +575,15 @@ void CmdPartDesignChamfer::activated(int iMsg) SubNames.erase(SubNames.begin()+i); } + // empty name or any other sub-element + else { + SubNames.erase(SubNames.begin()+i); + } } - if(SubNames.size() == 0){ + if (SubNames.size() == 0) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("No Fillet possilbe on seleced faces/edges")); + QObject::tr("No chamfer possible on selected faces/edges")); return; } From e848b1e96a59a3bf861f640ca7dd70fe5d2ee32f Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 7 Jun 2012 23:19:00 +0200 Subject: [PATCH 332/351] Add missing export macro for Box class --- src/Mod/Part/App/FeaturePartBox.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Part/App/FeaturePartBox.h b/src/Mod/Part/App/FeaturePartBox.h index 0349bb2111..086fa40cd4 100644 --- a/src/Mod/Part/App/FeaturePartBox.h +++ b/src/Mod/Part/App/FeaturePartBox.h @@ -32,7 +32,7 @@ namespace Part { -class Box :public Part::Primitive +class PartExport Box :public Part::Primitive { PROPERTY_HEADER(Part::Box); From fd29f4aa079ce19d07347e64af5193f138488d69 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 7 Jun 2012 18:20:42 -0300 Subject: [PATCH 333/351] Draft: Huge bugfixing in snap and grid behaviour --- src/Mod/Draft/DraftGui.py | 9 + src/Mod/Draft/DraftSnap.py | 42 ++++- src/Mod/Draft/DraftTools.py | 303 ++++++++++++++++----------------- src/Mod/Draft/DraftTrackers.py | 50 ++++-- src/Mod/Draft/WorkingPlane.py | 57 ++++++- 5 files changed, 275 insertions(+), 186 deletions(-) diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index 663c57fe9d..d68a981a74 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -959,6 +959,10 @@ class DraftToolBar: self.wipeLine() elif txt.endsWith("s"): self.togglesnap() + elif txt.endsWith("["): + self.toggleradius(1) + elif txt.endsWith("]"): + self.toggleradius(-1) elif txt.endsWith("c"): if self.closeButton.isVisible(): self.closeLine() @@ -1158,6 +1162,11 @@ class DraftToolBar: if hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper.toggle() + def toggleradius(self,val): + if hasattr(FreeCADGui,"Snapper"): + par = Draft.getParam("snapRange") + Draft.setParam("snapRange",par+val) + FreeCADGui.Snapper.showradius() #--------------------------------------------------------------------------- # TaskView operations diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 846cb522c1..3e1673460e 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -70,11 +70,12 @@ class Snapper: self.grid = None self.constrainLine = None self.trackLine = None + self.radiusTracker = None self.snapInfo = None self.lastSnappedObject = None self.active = True self.forceGridOff = False - self.trackers = [[],[],[],[]] # view, grid, snap, extline + self.trackers = [[],[],[],[],[]] # view, grid, snap, extline, radius self.polarAngles = [90,45] @@ -126,10 +127,13 @@ class Snapper: def cstr(point): "constrains if needed" if constrain: - return self.constrain(point,lastpoint) + fpt = self.constrain(point,lastpoint) else: self.unconstrain() - return point + fpt = point + if self.radiusTracker: + self.radiusTracker.update(fpt) + return fpt snaps = [] self.snapInfo = None @@ -150,6 +154,7 @@ class Snapper: self.grid = self.trackers[1][i] self.tracker = self.trackers[2][i] self.extLine = self.trackers[3][i] + self.radiusTracker = self.trackers[4][i] else: if Draft.getParam("grid"): self.grid = DraftTrackers.gridTracker() @@ -157,19 +162,23 @@ class Snapper: self.grid = None self.tracker = DraftTrackers.snapTracker() self.extLine = DraftTrackers.lineTracker(dotted=True) + self.radiusTracker = DraftTrackers.radiusTracker() self.trackers[0].append(v) self.trackers[1].append(self.grid) self.trackers[2].append(self.tracker) self.trackers[3].append(self.extLine) + self.trackers[4].append(self.radiusTracker) # getting current snap Radius - if not self.radius: - self.radius = self.getScreenDist(Draft.getParam("snapRange"),screenpos) + self.radius = self.getScreenDist(Draft.getParam("snapRange"),screenpos) + if self.radiusTracker: + self.radiusTracker.update(self.radius) + self.radiusTracker.off() # set the grid if self.grid and (not self.forceGridOff): self.grid.set() - + # activate snap oldActive = False if Draft.getParam("alwaysSnap"): @@ -195,7 +204,7 @@ class Snapper: eline = None point,eline = self.snapToPolar(point,lastpoint) point,eline = self.snapToExtensions(point,lastpoint,constrain,eline) - + if not self.snapInfo: # nothing has been snapped, check fro grid snap @@ -223,6 +232,9 @@ class Snapper: snaps = [self.snapToVertex(self.snapInfo)] else: + + # first stick to the snapped object + point = self.snapToVertex(self.snapInfo)[0] # active snapping comp = self.snapInfo['Component'] @@ -324,7 +336,12 @@ class Snapper: view = Draft.get3DView() pt = view.getPoint(x,y) if hasattr(FreeCAD,"DraftWorkingPlane"): - dv = view.getViewDirection() + if view.getCameraType() == "Perspective": + camera = view.getCameraNode() + p = camera.getField("position").getValue() + vd = pt.sub(Vector(p[0],p[1],p[2])) + else: + dv = view.getViewDirection() return FreeCAD.DraftWorkingPlane.projectPoint(pt,dv) else: return pt @@ -641,6 +658,8 @@ class Snapper: self.tracker.off() if self.extLine: self.extLine.off() + if self.radiusTracker: + self.radiusTracker.off() if self.grid: if not Draft.getParam("alwaysShowGrid"): self.grid.off() @@ -875,6 +894,13 @@ class Snapper: self.toolbarButtons[i].setEnabled(False) self.saveSnapModes() + def showradius(self): + "shows the snap radius indicator" + self.radius = self.getScreenDist(Draft.getParam("snapRange"),(400,300)) + if self.radiusTracker: + self.radiusTracker.update(self.radius) + self.radiusTracker.on() + def isEnabled(self,but): "returns true if the given button is turned on" for b in self.toolbarButtons: diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 1a55ee3cf4..9f31ff1e81 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -143,22 +143,6 @@ def getPoint(target,args,mobile=False,sym=False,workingplane=True): cmod = hasMod(args,MODCONSTRAIN) point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod) info = FreeCADGui.Snapper.snapInfo - # project onto working plane if needed - if (not plane.weak) and workingplane: - # working plane was explicitely selected - project onto it - viewDirection = view.getViewDirection() - if view.getCameraType() == "Perspective": - camera = view.getCameraNode() - p = camera.getField("position").getValue() - # view is from camera to point: - viewDirection = point.sub(Vector(p[0],p[1],p[2])) - # if we are not snapping to anything, project along view axis, - # otherwise perpendicularly - if view.getObjectInfo((args["Position"][0],args["Position"][1])): - pass - # point = plane.projectPoint(point) - else: - point = plane.projectPoint(point, viewDirection) ctrlPoint = Vector(point) mask = FreeCADGui.Snapper.affinity if target.node: @@ -169,8 +153,19 @@ def getPoint(target,args,mobile=False,sym=False,workingplane=True): else: ui.displayPoint(point, plane=plane, mask=mask) return point,ctrlPoint,info -def getSupport(args): +def getSupport(args=None): "returns the supporting object and sets the working plane" + if not args: + sel = FreeCADGui.Selection.getSelectionEx() + if len(sel) == 1: + sel = sel[0] + if sel.HasSubObjects: + if len(sel.SubElementNames) == 1: + if "Face" in sel.SubElementNames[0]: + plane.alignToFace(sel.SubObjects[0]) + return sel.Object + return None + snapped = Draft.get3DView().getObjectInfo((args["Position"][0],args["Position"][1])) if not snapped: return None obj = None @@ -204,11 +199,125 @@ def setMod(args,mod,state): elif mod == "alt": args["AltDown"] = state + + + +#--------------------------------------------------------------------------- +# Base Class +#--------------------------------------------------------------------------- + +class DraftTool: + "The base class of all Draft Tools" + + def __init__(self): + self.commitList = [] + + def IsActive(self): + if FreeCADGui.ActiveDocument: + return True + else: + return False + + def Activated(self,name="None"): + if FreeCAD.activeDraftCommand: + FreeCAD.activeDraftCommand.finish() + + global Part, DraftGeomUtils + import Part, DraftGeomUtils + + self.ui = None + self.call = None + self.support = None + self.commitList = [] + self.doc = FreeCAD.ActiveDocument + if not self.doc: + self.finish() + return + + FreeCAD.activeDraftCommand = self + self.view = Draft.get3DView() + self.ui = FreeCADGui.draftToolBar + self.ui.sourceCmd = self + self.ui.setTitle(name) + self.ui.show() + rot = self.view.getCameraNode().getField("orientation").getValue() + upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) + plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) + self.node = [] + self.pos = [] + self.constrain = None + self.obj = None + self.extendedCopy = False + self.ui.setTitle(name) + self.featureName = name + #self.snap = snapTracker() + #self.extsnap = lineTracker(dotted=True) + self.planetrack = None + if Draft.getParam("showPlaneTracker"): + self.planetrack = PlaneTracker() + + def finish(self): + self.node = [] + #self.snap.finalize() + #self.extsnap.finalize() + FreeCAD.activeDraftCommand = None + if self.ui: + self.ui.offUi() + self.ui.sourceCmd = None + #self.ui.cross(False) + msg("") + if self.planetrack: + self.planetrack.finalize() + if self.support: + plane.restore() + FreeCADGui.Snapper.off() + if self.call: + self.view.removeEventCallback("SoEvent",self.call) + self.call = None + if self.commitList: + todo.delayCommit(self.commitList) + self.commitList = [] + + def commit(self,name,func): + "stores actions to be committed to the FreeCAD document" + # print "committing" + self.commitList.append((name,func)) + + def getStrings(self): + "returns a couple of useful strings fro building python commands" + + # current plane rotation + p = plane.getRotation() + qr = p.Rotation.Q + qr = '('+str(qr[0])+','+str(qr[1])+','+str(qr[2])+','+str(qr[3])+')' + + # support object + if self.support: + sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' + else: + sup = 'None' + + # contents of self.node + points='[' + for n in self.node: + if len(points) > 1: + points += ',' + points += DraftVecUtils.toString(n) + points += ']' + + # fill mode + if self.ui: + fil = str(bool(self.ui.fillmode)) + else: + fil = "True" + + return qr,sup,points,fil + #--------------------------------------------------------------------------- # Helper tools -#--------------------------------------------------------------------------- - -class SelectPlane: +#--------------------------------------------------------------------------- + +class SelectPlane(DraftTool): "The Draft_SelectPlane FreeCAD command definition" def GetResources(self): @@ -216,20 +325,10 @@ class SelectPlane: 'Accel' : "W, P", 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_SelectPlane", "SelectPlane"), 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_SelectPlane", "Select a working plane for geometry creation")} - - def IsActive(self): - if FreeCADGui.ActiveDocument: - return True - else: - return False def Activated(self): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() + DraftTool.Activated(self) self.offset = 0 - self.ui = None - self.call = None - self.doc = FreeCAD.ActiveDocument if self.doc: sel = FreeCADGui.Selection.getSelectionEx() if len(sel) == 1: @@ -242,12 +341,8 @@ class SelectPlane: self.display(plane.axis) self.finish() return - FreeCAD.activeDraftCommand = self - self.view = Draft.get3DView() - self.ui = FreeCADGui.draftToolBar self.ui.selectPlaneUi() msg(translate("draft", "Pick a face to define the drawing plane\n")) - self.ui.sourceCmd = self if plane.alignToSelection(self.offset): FreeCADGui.Selection.clearSelection() self.display(plane.axis) @@ -316,135 +411,25 @@ class SelectPlane: self.ui.wplabel.setText(plv+suffix) FreeCADGui.Snapper.setGrid() - def finish(self): - if self.call: - self.view.removeEventCallback("SoEvent",self.call) - FreeCAD.activeDraftCommand = None - if self.ui: - self.ui.offUi() - #--------------------------------------------------------------------------- # Geometry constructors #--------------------------------------------------------------------------- - -class DraftTool: - "The base class of all Draft Tools" - - def __init__(self): - self.commitList = [] - - def Activated(self,name="None"): - if FreeCAD.activeDraftCommand: - FreeCAD.activeDraftCommand.finish() - - global Part, DraftGeomUtils - import Part, DraftGeomUtils - - self.ui = None - self.call = None - self.support = None - self.commitList = [] - self.doc = FreeCAD.ActiveDocument - if not self.doc: - self.finish() - return - - FreeCAD.activeDraftCommand = self - self.view = Draft.get3DView() - self.ui = FreeCADGui.draftToolBar - self.ui.sourceCmd = self - self.ui.setTitle(name) - self.ui.show() - rot = self.view.getCameraNode().getField("orientation").getValue() - upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue()) - plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv) - self.node = [] - self.pos = [] - self.constrain = None - self.obj = None - self.extendedCopy = False - self.ui.setTitle(name) - self.featureName = name - #self.snap = snapTracker() - #self.extsnap = lineTracker(dotted=True) - self.planetrack = None - if Draft.getParam("showPlaneTracker"): - self.planetrack = PlaneTracker() - - def finish(self): - self.node = [] - #self.snap.finalize() - #self.extsnap.finalize() - FreeCAD.activeDraftCommand = None - if self.ui: - self.ui.offUi() - self.ui.sourceCmd=None - #self.ui.cross(False) - msg("") - if self.planetrack: - self.planetrack.finalize() - if self.support: - plane.restore() - FreeCADGui.Snapper.off() - if self.call: - self.view.removeEventCallback("SoEvent",self.call) - self.call = None - if self.commitList: - todo.delayCommit(self.commitList) - self.commitList = [] - - def commit(self,name,func): - "stores actions to be committed to the FreeCAD document" - # print "committing" - self.commitList.append((name,func)) - - def getStrings(self): - "returns a couple of useful strings fro building python commands" - - # current plane rotation - p = plane.getRotation() - qr = p.Rotation.Q - qr = '('+str(qr[0])+','+str(qr[1])+','+str(qr[2])+','+str(qr[3])+')' - - # support object - if self.support: - sup = 'FreeCAD.ActiveDocument.getObject("' + self.support.Name + '")' - else: - sup = 'None' - - # contents of self.node - points='[' - for n in self.node: - if len(points) > 1: - points += ',' - points += DraftVecUtils.toString(n) - points += ']' - - # fill mode - if self.ui: - fil = str(bool(self.ui.fillmode)) - else: - fil = "True" - - return qr,sup,points,fil - class Creator(DraftTool): "A generic Draft Creator Tool used by creation tools such as line or arc" def __init__(self): DraftTool.__init__(self) - - def IsActive(self): - if FreeCADGui.ActiveDocument: - return True - else: - return False + def Activated(self,name="None"): + DraftTool.Activated(self) + self.support = getSupport() + class Line(Creator): "The Line FreeCAD command definition" def __init__(self, wiremode=False): + Creator.__init__(self) self.isWire = wiremode def GetResources(self): @@ -508,7 +493,8 @@ class Line(Creator): if (arg["Position"] == self.pos): self.finish(False,cont=True) else: - if not self.node: self.support = getSupport(arg) + if (not self.node) and (not self.support): + self.support = getSupport(arg) point,ctrlPoint,info = getPoint(self,arg) self.pos = arg["Position"] self.node.append(point) @@ -632,7 +618,8 @@ class BSpline(Line): if (arg["Position"] == self.pos): self.finish(False,cont=True) else: - if not self.node: self.support = getSupport(arg) + if (not self.node) and (not self.support): + self.support = getSupport(arg) point,ctrlPoint,info = getPoint(self,arg) self.pos = arg["Position"] self.node.append(point) @@ -822,7 +809,8 @@ class Rectangle(Creator): if (arg["Position"] == self.pos): self.finish() else: - if not self.node: self.support = getSupport(arg) + if (not self.node) and (not self.support): + self.support = getSupport(arg) point,ctrlPoint,info = getPoint(self,arg) self.appendPoint(point) @@ -1019,7 +1007,8 @@ class Arc(Creator): if not DraftVecUtils.isNull(viewdelta): point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center - self.support = getSupport(arg) + if not self.support: + self.support = getSupport(arg) if hasMod(arg,MODALT): snapped=self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) if snapped: @@ -1288,7 +1277,8 @@ class Polygon(Creator): if not DraftVecUtils.isNull(viewdelta): point = point.add(DraftVecUtils.neg(viewdelta)) if (self.step == 0): # choose center - if not self.node: self.support = getSupport(arg) + if (not self.node) and (not self.support): + self.support = getSupport(arg) if hasMod(arg,MODALT): snapped=self.view.getObjectInfo((arg["Position"][0],arg["Position"][1])) if snapped: @@ -1635,7 +1625,8 @@ class Dimension(Creator): elif arg["Type"] == "SoMouseButtonEvent": if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"): point,ctrlPoint,info = getPoint(self,arg) - if not self.node: self.support = getSupport(arg) + if (not self.node) and (not self.support): + self.support = getSupport(arg) if hasMod(arg,MODALT) and (len(self.node)<3): print "snapped: ",info if info: diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 47e378a348..1d9ba2b6cf 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -640,24 +640,16 @@ class gridTracker(Tracker): def getClosestNode(self,point): "returns the closest node from the given point" + print "in:",point # get the 2D coords. - point = FreeCAD.DraftWorkingPlane.projectPoint(point) - u = DraftVecUtils.project(point,FreeCAD.DraftWorkingPlane.u) - lu = u.Length - if u.getAngle(FreeCAD.DraftWorkingPlane.u) > 1.5: - lu = -lu - v = DraftVecUtils.project(point,FreeCAD.DraftWorkingPlane.v) - lv = v.Length - if v.getAngle(FreeCAD.DraftWorkingPlane.v) > 1.5: - lv = -lv - # print "u = ",u," v = ",v - # find nearest grid node - pu = (round(lu/self.space,0))*self.space - pv = (round(lv/self.space,0))*self.space - rot = FreeCAD.Rotation() - rot.Q = self.trans.rotation.getValue().getValue() - return rot.multVec(Vector(pu,pv,0)) - + # point = FreeCAD.DraftWorkingPlane.projectPoint(point) + pt = FreeCAD.DraftWorkingPlane.getLocalCoords(point) + pu = (round(pt.x/self.space,0))*self.space + pv = (round(pt.y/self.space,0))*self.space + pt = FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(pu,pv,0)) + print "out:",pt + return pt + class boxTracker(Tracker): "A box tracker, can be based on a line object" def __init__(self,line=None,width=0.1,height=1): @@ -719,3 +711,27 @@ class boxTracker(Tracker): self.update() else: return self.cube.depth.getValue() + +class radiusTracker(Tracker): + "A tracker that displays a transparent sphere to inicate a radius" + def __init__(self,position=FreeCAD.Vector(0,0,0),radius=1): + self.trans = coin.SoTransform() + self.trans.translation.setValue([position.x,position.y,position.z]) + m = coin.SoMaterial() + m.transparency.setValue(0.9) + m.diffuseColor.setValue([0,1,0]) + self.sphere = coin.SoSphere() + self.sphere.radius.setValue(radius) + self.baseline = None + Tracker.__init__(self,children=[self.trans,m,self.sphere]) + + def update(self,arg1,arg2=None): + if isinstance(arg1,FreeCAD.Vector): + self.trans.translation.setValue([arg1.x,arg1.y,arg1.z]) + else: + self.sphere.radius.setValue(arg1) + if arg2 != None: + if isinstance(arg2,FreeCAD.Vector): + self.trans.translation.setValue([arg2.x,arg2.y,arg2.z]) + else: + self.sphere.radius.setValue(arg2) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index e41eaabf76..6c1d6066b9 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -86,8 +86,29 @@ class plane: def projectPoint(self, p, direction=None): '''project point onto plane, default direction is orthogonal''' - if not direction: direction = self.axis + if not direction: + direction = self.axis + lp = self.getLocalCoords(p) + gp = self.getGlobalCoords(Vector(lp.x,lp.y,0)) + a = direction.getAngle(gp.sub(p)) + if a > math.pi/2: + direction = DraftVecUtils.neg(direction) + a = math.pi - a + ld = self.getLocalRot(direction) + gd = self.getGlobalRot(Vector(ld.x,ld.y,0)) + hyp = abs(math.tan(a) * lp.z) + return gp.add(DraftVecUtils.scaleTo(gd,hyp)) + + def projectPointOld(self, p, direction=None): + '''project point onto plane, default direction is orthogonal. Obsolete''' + if not direction: + direction = self.axis t = Vector(direction) + #t.normalize() + a = round(t.getAngle(self.axis),DraftVecUtils.precision()) + pp = round((math.pi)/2,DraftVecUtils.precision()) + if a == pp: + return p t.multiply(self.offsetToPoint(p, direction)) return p.add(t) @@ -196,6 +217,31 @@ class plane: def getLocalCoords(self,point): "returns the coordinates of a given point on the working plane" + pt = point.sub(self.position) + xv = DraftVecUtils.project(pt,self.u) + x = xv.Length + if xv.getAngle(self.u) > 1: + x = -x + yv = DraftVecUtils.project(pt,self.v) + y = yv.Length + if yv.getAngle(self.v) > 1: + y = -y + zv = DraftVecUtils.project(pt,self.axis) + z = zv.Length + if zv.getAngle(self.axis) > 1: + z = -z + return Vector(x,y,z) + + def getGlobalCoords(self,point): + "returns the global coordinates of the given point, taken relatively to this working plane" + vx = DraftVecUtils.scale(self.u,point.x) + vy = DraftVecUtils.scale(self.v,point.y) + vz = DraftVecUtils.scale(self.axis,point.z) + pt = (vx.add(vy)).add(vz) + return pt.add(self.position) + + def getLocalRot(self,point): + "Same as getLocalCoords, but discards the WP position" xv = DraftVecUtils.project(point,self.u) x = xv.Length if xv.getAngle(self.u) > 1: @@ -210,13 +256,14 @@ class plane: z = -z return Vector(x,y,z) - def getGlobalCoords(self,point): - "returns the global coordinates of the given point, taken relatively to this working plane" + def getGlobalRot(self,point): + "Same as getGlobalCoords, but discards the WP position" vx = DraftVecUtils.scale(self.u,point.x) vy = DraftVecUtils.scale(self.v,point.y) vz = DraftVecUtils.scale(self.axis,point.z) - return (vx.add(vy)).add(vz) - + pt = (vx.add(vy)).add(vz) + return pt + def getClosestAxis(self,point): "returns which of the workingplane axes is closest from the given vector" ax = point.getAngle(self.u) From 79db35a6b575305c79cc3cd2b36736f199641242 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 7 Jun 2012 18:23:50 -0300 Subject: [PATCH 334/351] Draft: Removed debug message --- src/Mod/Draft/DraftTrackers.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index 1d9ba2b6cf..c36d031522 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -640,14 +640,12 @@ class gridTracker(Tracker): def getClosestNode(self,point): "returns the closest node from the given point" - print "in:",point # get the 2D coords. # point = FreeCAD.DraftWorkingPlane.projectPoint(point) pt = FreeCAD.DraftWorkingPlane.getLocalCoords(point) pu = (round(pt.x/self.space,0))*self.space pv = (round(pt.y/self.space,0))*self.space pt = FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(pu,pv,0)) - print "out:",pt return pt class boxTracker(Tracker): From e7644fd3b32e487b915249ac86949495e9401ae6 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Thu, 7 Jun 2012 19:58:56 -0300 Subject: [PATCH 335/351] Draft: remaining fixes --- src/Mod/Draft/DraftSnap.py | 22 ++++++++++++---------- src/Mod/Draft/DraftTools.py | 2 ++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index 3e1673460e..ee2e2aab97 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -339,7 +339,7 @@ class Snapper: if view.getCameraType() == "Perspective": camera = view.getCameraNode() p = camera.getField("position").getValue() - vd = pt.sub(Vector(p[0],p[1],p[2])) + dv = pt.sub(Vector(p[0],p[1],p[2])) else: dv = view.getViewDirection() return FreeCAD.DraftWorkingPlane.projectPoint(pt,dv) @@ -390,15 +390,17 @@ class Snapper: else: if self.isEnabled('parallel'): if last: - de = Part.Line(last,last.add(DraftGeomUtils.vec(e))).toShape() - np = self.getPerpendicular(de,point) - if (np.sub(point)).Length < self.radius: - if self.tracker: - self.tracker.setCoords(np) - self.tracker.setMarker(self.mk['parallel']) - self.tracker.on() - self.setCursor('parallel') - return np,de + ve = DraftGeomUtils.vec(e) + if not DraftVecUtils.isNull(ve): + de = Part.Line(last,last.add(ve)).toShape() + np = self.getPerpendicular(de,point) + if (np.sub(point)).Length < self.radius: + if self.tracker: + self.tracker.setCoords(np) + self.tracker.setMarker(self.mk['parallel']) + self.tracker.on() + self.setCursor('parallel') + return np,de return point,eline def snapToPolar(self,point,last): diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index 9f31ff1e81..0407369277 100644 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -3823,6 +3823,8 @@ class ToggleGrid(): else: FreeCADGui.Snapper.grid.on() FreeCADGui.Snapper.forceGridOff=False + else: + FreeCADGui.Snapper.show() #--------------------------------------------------------------------------- # Adds the icons & commands to the FreeCAD command manager, and sets defaults From cf31d43e54063f20ab40710c328f288048e80e4b Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Jun 2012 15:19:53 +0200 Subject: [PATCH 336/351] Add support of number of decimals to unit system --- src/Base/UnitsApi.cpp | 11 ++++++++ src/Base/UnitsApi.h | 6 +++++ src/Gui/Application.cpp | 5 ++++ src/Gui/propertyeditor/PropertyItem.cpp | 35 +++++++++++++++++-------- src/Gui/propertyeditor/PropertyItem.h | 3 +++ 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/Base/UnitsApi.cpp b/src/Base/UnitsApi.cpp index ceb7734737..91b71eba87 100644 --- a/src/Base/UnitsApi.cpp +++ b/src/Base/UnitsApi.cpp @@ -85,6 +85,7 @@ UnitsSchema *UnitsApi::UserPrefSystem = new UnitsSchemaInternal(); double UnitsApi::UserPrefFactor [50]; QString UnitsApi::UserPrefUnit [50]; +int UnitsApi::UserPrefDecimals = 2; UnitsApi::UnitsApi(const char* filter) { @@ -196,6 +197,16 @@ const double UnitsApi::getPrefFactorOf(QuantityType t) return UserPrefFactor[t]; } +void UnitsApi::setDecimals(int prec) +{ + UserPrefDecimals = prec; +} + +int UnitsApi::getDecimals() +{ + return UserPrefDecimals; +} + void UnitsApi::setDefaults(void) { setPrefOf( Length ,"mm" ); diff --git a/src/Base/UnitsApi.h b/src/Base/UnitsApi.h index e3beae5d5f..1b2fdcd64f 100644 --- a/src/Base/UnitsApi.h +++ b/src/Base/UnitsApi.h @@ -101,6 +101,10 @@ public: static const QString getQuantityName(QuantityType t); /// get the translation factor for the default unit of a quantity static const double getPrefFactorOf(QuantityType t); + // set the number of decimals + static void setDecimals(int); + // fet the number of decimals + static int getDecimals(); /// set the application defaults static void setDefaults(void); //@} @@ -119,6 +123,8 @@ protected: static double UserPrefFactor [50] ; /// name of the unit the user wants to use as quantities static QString UserPrefUnit [50] ; + /// number of decimals for floats + static int UserPrefDecimals; // do the real work static double parse(const char*,bool &UsedUnit); diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index a4c3542b39..ad56639024 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -328,6 +329,10 @@ Application::Application(bool GUIenabled) Translator::instance()->activateLanguage(hPGrp->GetASCII("Language", (const char*)lang.toAscii()).c_str()); GetWidgetFactorySupplier(); + ParameterGrp::handle hUnits = App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/Units"); + Base::UnitsApi::setDecimals(hUnits->GetInt("Decimals", Base::UnitsApi::getDecimals())); + // setting up Python binding Base::PyGILStateLocker lock; PyObject* module = Py_InitModule3("FreeCADGui", Application::Methods, diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index 3f0e5b08f5..eab7c4c20c 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -57,6 +57,7 @@ TYPESYSTEM_SOURCE(Gui::PropertyEditor::PropertyItem, Base::BaseClass); PropertyItem::PropertyItem() : parentItem(0), readonly(false) { + precision = Base::UnitsApi::getDecimals(); } PropertyItem::~PropertyItem() @@ -130,6 +131,16 @@ bool PropertyItem::isReadOnly() const return readonly; } +void PropertyItem::setDecimals(int prec) +{ + precision = prec; +} + +int PropertyItem::decimals() const +{ + return precision; +} + QVariant PropertyItem::toolTip(const App::Property* prop) const { return QVariant(QString::fromUtf8(prop->getDocumentation())); @@ -574,7 +585,7 @@ void PropertyFloatItem::setValue(const QVariant& value) if (!value.canConvert(QVariant::Double)) return; double val = value.toDouble(); - QString data = QString::fromAscii("%1").arg(val,0,'f',2); + QString data = QString::fromAscii("%1").arg(val,0,'f',decimals()); setPropertyValue(data); } @@ -582,6 +593,7 @@ QWidget* PropertyFloatItem::createEditor(QWidget* parent, const QObject* receive { QDoubleSpinBox *sb = new QDoubleSpinBox(parent); sb->setFrame(false); + sb->setDecimals(decimals()); QObject::connect(sb, SIGNAL(valueChanged(double)), receiver, method); return sb; } @@ -703,13 +715,14 @@ void PropertyFloatConstraintItem::setValue(const QVariant& value) if (!value.canConvert(QVariant::Double)) return; double val = value.toDouble(); - QString data = QString::fromAscii("%1").arg(val,0,'f',2); + QString data = QString::fromAscii("%1").arg(val,0,'f',decimals()); setPropertyValue(data); } QWidget* PropertyFloatConstraintItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { QDoubleSpinBox *sb = new QDoubleSpinBox(parent); + sb->setDecimals(decimals()); sb->setFrame(false); QObject::connect(sb, SIGNAL(valueChanged(double)), receiver, method); return sb; @@ -873,9 +886,9 @@ void PropertyVectorItem::setValue(const QVariant& value) return; const Base::Vector3f& val = value.value(); QString data = QString::fromAscii("(%1, %2, %3)") - .arg(val.x,0,'f',2) - .arg(val.y,0,'f',2) - .arg(val.z,0,'f',2); + .arg(val.x,0,'f',decimals()) + .arg(val.y,0,'f',decimals()) + .arg(val.z,0,'f',decimals()); setPropertyValue(data); } @@ -976,9 +989,9 @@ void PropertyDoubleVectorItem::setValue(const QVariant& value) return; const Base::Vector3d& val = value.value(); QString data = QString::fromAscii("(%1, %2, %3)") - .arg(val.x,0,'f',2) - .arg(val.y,0,'f',2) - .arg(val.z,0,'f',2); + .arg(val.x,0,'f',decimals()) + .arg(val.y,0,'f',decimals()) + .arg(val.z,0,'f',decimals()); setPropertyValue(data); } @@ -1503,9 +1516,9 @@ void PropertyColorItem::setValue(const QVariant& value) val.g = (float)col.green()/255.0f; val.b = (float)col.blue()/255.0f; QString data = QString::fromAscii("(%1,%2,%3)") - .arg(val.r,0,'f',2) - .arg(val.g,0,'f',2) - .arg(val.b,0,'f',2); + .arg(val.r,0,'f',decimals()) + .arg(val.g,0,'f',decimals()) + .arg(val.b,0,'f',decimals()); setPropertyValue(data); } diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index d334d8ced2..bc247966fc 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -69,6 +69,8 @@ public: void setReadOnly(bool); bool isReadOnly() const; + void setDecimals(int); + int decimals() const; PropertyItem *child(int row); int childCount() const; @@ -99,6 +101,7 @@ private: PropertyItem *parentItem; QList childItems; bool readonly; + int precision; }; /** From 33ecf9e76844c755bf947f9e6001d2fd8798e6c4 Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Fri, 8 Jun 2012 19:11:09 +0430 Subject: [PATCH 337/351] Groove feature (code is 99% identical to Revolution feature) --- src/Mod/PartDesign/App/AppPartDesign.cpp | 2 + src/Mod/PartDesign/App/CMakeLists.txt | 2 + src/Mod/PartDesign/App/FeatureGroove.cpp | 207 +++++++++++++ src/Mod/PartDesign/App/FeatureGroove.h | 66 ++++ src/Mod/PartDesign/Gui/AppPartDesignGui.cpp | 2 + src/Mod/PartDesign/Gui/CMakeLists.txt | 7 + src/Mod/PartDesign/Gui/Command.cpp | 77 +++++ .../PartDesign/Gui/TaskGrooveParameters.cpp | 287 ++++++++++++++++++ src/Mod/PartDesign/Gui/TaskGrooveParameters.h | 115 +++++++ .../PartDesign/Gui/TaskGrooveParameters.ui | 93 ++++++ src/Mod/PartDesign/Gui/ViewProviderGroove.cpp | 141 +++++++++ src/Mod/PartDesign/Gui/ViewProviderGroove.h | 59 ++++ src/Mod/PartDesign/Gui/Workbench.cpp | 3 + 13 files changed, 1061 insertions(+) create mode 100644 src/Mod/PartDesign/App/FeatureGroove.cpp create mode 100644 src/Mod/PartDesign/App/FeatureGroove.h create mode 100644 src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp create mode 100644 src/Mod/PartDesign/Gui/TaskGrooveParameters.h create mode 100644 src/Mod/PartDesign/Gui/TaskGrooveParameters.ui create mode 100644 src/Mod/PartDesign/Gui/ViewProviderGroove.cpp create mode 100644 src/Mod/PartDesign/Gui/ViewProviderGroove.h diff --git a/src/Mod/PartDesign/App/AppPartDesign.cpp b/src/Mod/PartDesign/App/AppPartDesign.cpp index debb60f26b..16620762f6 100644 --- a/src/Mod/PartDesign/App/AppPartDesign.cpp +++ b/src/Mod/PartDesign/App/AppPartDesign.cpp @@ -34,6 +34,7 @@ #include "FeatureFillet.h" #include "FeatureSketchBased.h" #include "FeatureRevolution.h" +#include "FeatureGroove.h" #include "Body.h" #include "FeatureDressUp.h" #include "FeatureChamfer.h" @@ -82,6 +83,7 @@ void PartDesignExport initPartDesign() PartDesign::Pocket ::init(); PartDesign::Fillet ::init(); PartDesign::Revolution ::init(); + PartDesign::Groove ::init(); PartDesign::Chamfer ::init(); PartDesign::Face ::init(); } diff --git a/src/Mod/PartDesign/App/CMakeLists.txt b/src/Mod/PartDesign/App/CMakeLists.txt index 49af698364..837189bb1e 100644 --- a/src/Mod/PartDesign/App/CMakeLists.txt +++ b/src/Mod/PartDesign/App/CMakeLists.txt @@ -50,6 +50,8 @@ SET(FeaturesSketchBased_SRCS FeaturePocket.h FeatureRevolution.cpp FeatureRevolution.h + FeatureGroove.cpp + FeatureGroove.h FeatureAdditive.cpp FeatureAdditive.h FeatureSubtractive.h diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp new file mode 100644 index 0000000000..1e7f7d6603 --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -0,0 +1,207 @@ +/*************************************************************************** + * Copyright (c) 2010 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include +#include +#include + +#include "FeatureGroove.h" + + +using namespace PartDesign; + +namespace PartDesign { + + +PROPERTY_SOURCE(PartDesign::Groove, PartDesign::SketchBased) + +Groove::Groove() +{ + ADD_PROPERTY(Base,(Base::Vector3f(0.0f,0.0f,0.0f))); + ADD_PROPERTY(Axis,(Base::Vector3f(0.0f,1.0f,0.0f))); + ADD_PROPERTY(Angle,(360.0)); + ADD_PROPERTY_TYPE(ReferenceAxis,(0),"Groove",(App::PropertyType)(App::Prop_None),"Reference axis of Groove"); + ADD_PROPERTY(Midplane,(0)); + ADD_PROPERTY(Reversed, (0)); +} + +short Groove::mustExecute() const +{ + if (Placement.isTouched() || + Sketch.isTouched() || + ReferenceAxis.isTouched() || + Axis.isTouched() || + Base.isTouched() || + Angle.isTouched() || + Midplane.isTouched()) + return 1; + return 0; +} + +App::DocumentObjectExecReturn *Groove::execute(void) +{ + App::DocumentObject* link = Sketch.getValue(); + if (!link) + return new App::DocumentObjectExecReturn("No sketch linked"); + if (!link->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) + return new App::DocumentObjectExecReturn("Linked object is not a Sketch or Part2DObject"); + + Part::Part2DObject* pcSketch=static_cast(link); + + TopoDS_Shape shape = pcSketch->Shape.getShape()._Shape; + if (shape.IsNull()) + return new App::DocumentObjectExecReturn("Linked shape object is empty"); + + // this is a workaround for an obscure OCC bug which leads to empty tessellations + // for some faces. Making an explicit copy of the linked shape seems to fix it. + // The error only happens when re-computing the shape. + if (!this->Shape.getValue().IsNull()) { + BRepBuilderAPI_Copy copy(shape); + shape = copy.Shape(); + if (shape.IsNull()) + return new App::DocumentObjectExecReturn("Linked shape object is empty"); + } + + TopExp_Explorer ex; + std::vector wires; + for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) { + wires.push_back(TopoDS::Wire(ex.Current())); + } + if (wires.empty()) // there can be several wires + return new App::DocumentObjectExecReturn("Linked shape object is not a wire"); + + // get the Sketch plane + Base::Placement SketchPlm = pcSketch->Placement.getValue(); + + // get reference axis + App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); + const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); + if (pcReferenceAxis && pcReferenceAxis == pcSketch) { + bool hasValidAxis=false; + Base::Axis axis; + if (subReferenceAxis[0] == "V_Axis") { + hasValidAxis = true; + axis = pcSketch->getAxis(Part::Part2DObject::V_Axis); + } + else if (subReferenceAxis[0] == "H_Axis") { + hasValidAxis = true; + axis = pcSketch->getAxis(Part::Part2DObject::H_Axis); + } + else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { + int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); + if (AxId >= 0 && AxId < pcSketch->getAxisCount()) { + hasValidAxis = true; + axis = pcSketch->getAxis(AxId); + } + } + if (hasValidAxis) { + axis *= SketchPlm; + Base::Vector3d base=axis.getBase(); + Base::Vector3d dir=axis.getDirection(); + Base.setValue(base.x,base.y,base.z); + Axis.setValue(dir.x,dir.y,dir.z); + } + } + + // get revolve axis + Base::Vector3f b = Base.getValue(); + gp_Pnt pnt(b.x,b.y,b.z); + Base::Vector3f v = Axis.getValue(); + gp_Dir dir(v.x,v.y,v.z); + + // get the support of the Sketch if any + App::DocumentObject* pcSupport = pcSketch->Support.getValue(); + Part::Feature *SupportObject = 0; + if (pcSupport && pcSupport->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + SupportObject = static_cast(pcSupport); + + TopoDS_Shape aFace = makeFace(wires); + if (aFace.IsNull()) + return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); + + // Rotate the face by half the angle to get Groove symmetric to sketch plane + if (Midplane.getValue()) { + gp_Trsf mov; + mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians(Angle.getValue()) * (-1.0) / 2.0); + TopLoc_Location loc(mov); + aFace.Move(loc); + } + + this->positionBySketch(); + TopLoc_Location invObjLoc = this->getLocation().Inverted(); + pnt.Transform(invObjLoc.Transformation()); + dir.Transform(invObjLoc.Transformation()); + + // Reverse angle if selected + double angle = Base::toRadians(Angle.getValue()); + if (Reversed.getValue() && !Midplane.getValue()) + angle *= (-1.0); + + try { + // revolve the face to a solid + BRepPrimAPI_MakeRevol RevolMaker(aFace.Moved(invObjLoc), gp_Ax1(pnt, dir), angle); + + if (RevolMaker.IsDone()) { + TopoDS_Shape result = RevolMaker.Shape(); + // if the sketch has a support fuse them to get one result object (PAD!) + if (SupportObject) { + const TopoDS_Shape& support = SupportObject->Shape.getValue(); + if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) { + // Let's call algorithm computing a fuse operation: + BRepAlgoAPI_Cut mkCut(support.Moved(invObjLoc), result); + // Let's check if the fusion has been successful + if (!mkCut.IsDone()) + throw Base::Exception("Cut out of support failed"); + result = mkCut.Shape(); + } + } + + this->Shape.setValue(result); + } + else + return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); + + return App::DocumentObject::StdReturn; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); + } +} + +} diff --git a/src/Mod/PartDesign/App/FeatureGroove.h b/src/Mod/PartDesign/App/FeatureGroove.h new file mode 100644 index 0000000000..782e728cbc --- /dev/null +++ b/src/Mod/PartDesign/App/FeatureGroove.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (c) 2010 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef PARTDESIGN_Groove_H +#define PARTDESIGN_Groove_H + +#include +#include "FeatureSketchBased.h" + +namespace PartDesign +{ + +class Groove : public SketchBased +{ + PROPERTY_HEADER(PartDesign::Groove); + +public: + Groove(); + + App::PropertyVector Base; + App::PropertyVector Axis; + App::PropertyAngle Angle; + App::PropertyBool Midplane; + App::PropertyBool Reversed; + + /** if this property is set to a valid link, both Axis and Base properties + * are calculated according to the linked line + */ + App::PropertyLinkSub ReferenceAxis; + + /** @name methods override feature */ + //@{ + /// recalculate the feature + App::DocumentObjectExecReturn *execute(void); + short mustExecute() const; + /// returns the type name of the view provider + const char* getViewProviderName(void) const { + return "PartDesignGui::ViewProviderGroove"; + } + //@} +}; + +} //namespace PartDesign + + +#endif // PART_Groove_H diff --git a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp index d86285fbee..32e7187786 100644 --- a/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp +++ b/src/Mod/PartDesign/Gui/AppPartDesignGui.cpp @@ -37,6 +37,7 @@ #include "ViewProviderChamfer.h" #include "ViewProviderFillet.h" #include "ViewProviderRevolution.h" +#include "ViewProviderGroove.h" //#include "resources/qrc_PartDesign.cpp" @@ -83,6 +84,7 @@ void PartDesignGuiExport initPartDesignGui() PartDesignGui::ViewProviderPocket ::init(); PartDesignGui::ViewProviderPad ::init(); PartDesignGui::ViewProviderRevolution::init(); + PartDesignGui::ViewProviderGroove ::init(); PartDesignGui::ViewProviderChamfer ::init(); PartDesignGui::ViewProviderFillet ::init(); diff --git a/src/Mod/PartDesign/Gui/CMakeLists.txt b/src/Mod/PartDesign/Gui/CMakeLists.txt index 8f6e265565..0aa1cb9189 100644 --- a/src/Mod/PartDesign/Gui/CMakeLists.txt +++ b/src/Mod/PartDesign/Gui/CMakeLists.txt @@ -32,6 +32,7 @@ set(PartDesignGui_MOC_HDRS TaskFilletParameters.h TaskHoleParameters.h TaskRevolutionParameters.h + TaskGrooveParameters.h ) fc_wrap_cpp(PartDesignGui_MOC_SRCS ${PartDesignGui_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${PartDesignGui_MOC_SRCS}) @@ -46,6 +47,7 @@ set(PartDesignGui_UIC_SRCS TaskFilletParameters.ui TaskHoleParameters.ui TaskRevolutionParameters.ui + TaskGrooveParameters.ui ) qt4_wrap_ui(PartDesignGui_UIC_HDRS ${PartDesignGui_UIC_SRCS}) @@ -64,6 +66,8 @@ SET(PartDesignGuiViewProvider_SRCS ViewProviderFillet.h ViewProviderRevolution.cpp ViewProviderRevolution.h + ViewProviderGroove.cpp + ViewProviderGroove.h ViewProviderPatternRectangular.cpp ViewProviderPatternRectangular.h ) @@ -88,6 +92,9 @@ SET(PartDesignGuiTaskDlgs_SRCS TaskRevolutionParameters.ui TaskRevolutionParameters.cpp TaskRevolutionParameters.h + TaskGrooveParameters.ui + TaskGrooveParameters.cpp + TaskGrooveParameters.h TaskHoleParameters.ui TaskHoleParameters.cpp TaskHoleParameters.h diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 37e02dc6a9..d671fbe46e 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -327,6 +327,82 @@ bool CmdPartDesignRevolution::isActive(void) return hasActiveDocument(); } +//=========================================================================== +// PartDesign_Groove +//=========================================================================== +DEF_STD_CMD_A(CmdPartDesignGroove); + +CmdPartDesignGroove::CmdPartDesignGroove() + : Command("PartDesign_Groove") +{ + sAppModule = "PartDesign"; + sGroup = QT_TR_NOOP("PartDesign"); + sMenuText = QT_TR_NOOP("Groove"); + sToolTipText = QT_TR_NOOP("Revolve a selected sketch"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = "PartDesign_Groove"; +} + +void CmdPartDesignGroove::activated(int iMsg) +{ + unsigned int n = getSelection().countObjectsOfType(Part::Part2DObject::getClassTypeId()); + if (n != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select a sketch or 2D object.")); + return; + } + + std::string FeatName = getUniqueObjectName("Groove"); + + std::vector Sel = getSelection().getObjectsOfType(Part::Part2DObject::getClassTypeId()); + Part::Part2DObject* sketch = static_cast(Sel.front()); + const TopoDS_Shape& shape = sketch->Shape.getValue(); + if (shape.IsNull()) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The shape of the selected object is empty.")); + return; + } + + // count free wires + int ctWires=0; + TopExp_Explorer ex; + for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) { + ctWires++; + } + if (ctWires == 0) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("The shape of the selected object is not a wire.")); + return; + } + + App::DocumentObject* support = sketch->Support.getValue(); + + openCommand("Make Groove"); + doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Groove\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",FeatName.c_str(),sketch->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])", + FeatName.c_str(), sketch->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.Angle = 360.0",FeatName.c_str()); + updateActive(); + if (isActiveObjectValid()) { + doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",sketch->getNameInDocument()); + if (support) + doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",support->getNameInDocument()); + } + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + + if (support) { + copyVisual(FeatName.c_str(), "ShapeColor", support->getNameInDocument()); + copyVisual(FeatName.c_str(), "LineColor", support->getNameInDocument()); + copyVisual(FeatName.c_str(), "PointColor", support->getNameInDocument()); + } +} + +bool CmdPartDesignGroove::isActive(void) +{ + return hasActiveDocument(); +} //=========================================================================== // PartDesign_Fillet //=========================================================================== @@ -628,6 +704,7 @@ void CreatePartDesignCommands(void) rcCmdMgr.addCommand(new CmdPartDesignPad()); rcCmdMgr.addCommand(new CmdPartDesignPocket()); rcCmdMgr.addCommand(new CmdPartDesignRevolution()); + rcCmdMgr.addCommand(new CmdPartDesignGroove()); rcCmdMgr.addCommand(new CmdPartDesignFillet()); //rcCmdMgr.addCommand(new CmdPartDesignNewSketch()); rcCmdMgr.addCommand(new CmdPartDesignChamfer()); diff --git a/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp b/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp new file mode 100644 index 0000000000..79b0278fe8 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp @@ -0,0 +1,287 @@ +/*************************************************************************** + * Copyright (c) 2011 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "ui_TaskGrooveParameters.h" +#include "TaskGrooveParameters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace PartDesignGui; +using namespace Gui; + +/* TRANSLATOR PartDesignGui::TaskGrooveParameters */ + +TaskGrooveParameters::TaskGrooveParameters(ViewProviderGroove *GrooveView,QWidget *parent) + : TaskBox(Gui::BitmapFactory().pixmap("PartDesign_Groove"),tr("Groove parameters"),true, parent),GrooveView(GrooveView) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskGrooveParameters(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + connect(ui->doubleSpinBox, SIGNAL(valueChanged(double)), + this, SLOT(onAngleChanged(double))); + connect(ui->axis, SIGNAL(activated(int)), + this, SLOT(onAxisChanged(int))); + connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), + this, SLOT(onMidplane(bool))); + connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), + this, SLOT(onReversed(bool))); + + this->groupLayout()->addWidget(proxy); + + PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); + double l = pcGroove->Angle.getValue(); + bool mirrored = pcGroove->Midplane.getValue(); + bool reversed = pcGroove->Reversed.getValue(); + + ui->doubleSpinBox->setValue(l); + + int count=pcGroove->getSketchAxisCount(); + + for (int i=ui->axis->count()-1; i >= count+2; i--) + ui->axis->removeItem(i); + for (int i=ui->axis->count(); i < count+2; i++) + ui->axis->addItem(QString::fromAscii("Sketch axis %1").arg(i-2)); + + int pos=-1; + + App::DocumentObject *pcReferenceAxis = pcGroove->ReferenceAxis.getValue(); + const std::vector &subReferenceAxis = pcGroove->ReferenceAxis.getSubValues(); + if (pcReferenceAxis && pcReferenceAxis == pcGroove->Sketch.getValue()) { + assert(subReferenceAxis.size()==1); + if (subReferenceAxis[0] == "V_Axis") + pos = 0; + else if (subReferenceAxis[0] == "H_Axis") + pos = 1; + else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") + pos = 2 + std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); + } + + if (pos < 0 || pos >= ui->axis->count()) { + ui->axis->addItem(QString::fromAscii("Undefined")); + pos = ui->axis->count()-1; + } + + ui->axis->setCurrentIndex(pos); + + ui->checkBoxMidplane->setChecked(mirrored); + ui->checkBoxReversed->setChecked(reversed); + + setFocus (); +} + +void TaskGrooveParameters::onAngleChanged(double len) +{ + PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); + pcGroove->Angle.setValue((float)len); + pcGroove->getDocument()->recomputeFeature(pcGroove); +} + +void TaskGrooveParameters::onAxisChanged(int num) +{ + PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); + Sketcher::SketchObject *pcSketch = static_cast(pcGroove->Sketch.getValue()); + if (pcSketch) { + int maxcount = pcSketch->getAxisCount()+2; + if (num == 0) + pcGroove->ReferenceAxis.setValue(pcSketch, std::vector(1,"V_Axis")); + else if (num == 1) + pcGroove->ReferenceAxis.setValue(pcSketch, std::vector(1,"H_Axis")); + else if (num >= 2 && num < maxcount) { + QString buf = QString::fromUtf8("Axis%1").arg(num-2); + std::string str = buf.toStdString(); + pcGroove->ReferenceAxis.setValue(pcSketch, std::vector(1,str)); + } + if (num < maxcount && ui->axis->count() > maxcount) + ui->axis->setMaxCount(maxcount); + } + pcGroove->getDocument()->recomputeFeature(pcGroove); +} + +void TaskGrooveParameters::onMidplane(bool on) +{ + PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); + pcGroove->Midplane.setValue(on); + pcGroove->getDocument()->recomputeFeature(pcGroove); +} + +void TaskGrooveParameters::onReversed(bool on) +{ + PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); + pcGroove->Reversed.setValue(on); + pcGroove->getDocument()->recomputeFeature(pcGroove); +} + + +double TaskGrooveParameters::getAngle(void) const +{ + return ui->doubleSpinBox->value(); +} + +QString TaskGrooveParameters::getReferenceAxis(void) const +{ + // get the support and Sketch + PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); + Sketcher::SketchObject *pcSketch = static_cast(pcGroove->Sketch.getValue()); + + QString buf; + if (pcSketch) { + buf = QString::fromUtf8("(App.ActiveDocument.%1,[%2])"); + buf = buf.arg(QString::fromUtf8(pcSketch->getNameInDocument())); + if (ui->axis->currentIndex() == 0) + buf = buf.arg(QString::fromUtf8("'V_Axis'")); + else if (ui->axis->currentIndex() == 1) + buf = buf.arg(QString::fromUtf8("'H_Axis'")); + else if (ui->axis->currentIndex() >= 2) { + buf = buf.arg(QString::fromUtf8("'Axis%1'")); + buf = buf.arg(ui->axis->currentIndex()-2); + } + } + else + buf = QString::fromUtf8("''"); + + return buf; +} + +bool TaskGrooveParameters::getMidplane(void) const +{ + return ui->checkBoxMidplane->isChecked(); +} + +bool TaskGrooveParameters::getReversed(void) const +{ + return ui->checkBoxReversed->isChecked(); +} + +TaskGrooveParameters::~TaskGrooveParameters() +{ + delete ui; +} + +void TaskGrooveParameters::changeEvent(QEvent *e) +{ + TaskBox::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(proxy); + } +} + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgGrooveParameters::TaskDlgGrooveParameters(ViewProviderGroove *GrooveView) + : TaskDialog(),GrooveView(GrooveView) +{ + assert(GrooveView); + parameter = new TaskGrooveParameters(GrooveView); + + Content.push_back(parameter); +} + +TaskDlgGrooveParameters::~TaskDlgGrooveParameters() +{ + +} + +//==== calls from the TaskView =============================================================== + + +void TaskDlgGrooveParameters::open() +{ + +} + +void TaskDlgGrooveParameters::clicked(int) +{ + +} + +bool TaskDlgGrooveParameters::accept() +{ + std::string name = GrooveView->getObject()->getNameInDocument(); + + //Gui::Command::openCommand("Groove changed"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Angle = %f",name.c_str(),parameter->getAngle()); + std::string axis = parameter->getReferenceAxis().toStdString(); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.ReferenceAxis = %s",name.c_str(),axis.c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Midplane = %i",name.c_str(),parameter->getMidplane()?1:0); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %i",name.c_str(),parameter->getReversed()?1:0); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + Gui::Command::commitCommand(); + + return true; +} + +bool TaskDlgGrooveParameters::reject() +{ + // get the support and Sketch + PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); + Sketcher::SketchObject *pcSketch; + App::DocumentObject *pcSupport; + if (pcGroove->Sketch.getValue()) { + pcSketch = static_cast(pcGroove->Sketch.getValue()); + pcSupport = pcSketch->Support.getValue(); + } + + // role back the done things + Gui::Command::abortCommand(); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + // if abort command deleted the object the support is visible again + if (!Gui::Application::Instance->getViewProvider(pcGroove)) { + if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch)) + Gui::Application::Instance->getViewProvider(pcSketch)->show(); + if (pcSupport && Gui::Application::Instance->getViewProvider(pcSupport)) + Gui::Application::Instance->getViewProvider(pcSupport)->show(); + } + + //Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); + //Gui::Command::commitCommand(); + + return true; +} + + + +#include "moc_TaskGrooveParameters.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskGrooveParameters.h b/src/Mod/PartDesign/Gui/TaskGrooveParameters.h new file mode 100644 index 0000000000..8b82f01872 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskGrooveParameters.h @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (c) 2011 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef GUI_TASKVIEW_TaskGrooveParameters_H +#define GUI_TASKVIEW_TaskGrooveParameters_H + +#include +#include +#include + +#include "ViewProviderGroove.h" + +class Ui_TaskGrooveParameters; + +namespace App { +class Property; +} + +namespace Gui { +class ViewProvider; +} + +namespace PartDesignGui { + + + +class TaskGrooveParameters : public Gui::TaskView::TaskBox +{ + Q_OBJECT + +public: + TaskGrooveParameters(ViewProviderGroove *GrooveView,QWidget *parent = 0); + ~TaskGrooveParameters(); + + QString getReferenceAxis(void) const; + double getAngle(void) const; + bool getMidplane(void) const; + bool getReversed(void) const; + +private Q_SLOTS: + void onAngleChanged(double); + void onAxisChanged(int); + void onMidplane(bool); + void onReversed(bool); + +protected: + void changeEvent(QEvent *e); + +private: + +private: + QWidget* proxy; + Ui_TaskGrooveParameters* ui; + ViewProviderGroove *GrooveView; +}; + +/// simulation dialog for the TaskView +class TaskDlgGrooveParameters : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgGrooveParameters(ViewProviderGroove *GrooveView); + ~TaskDlgGrooveParameters(); + + ViewProviderGroove* getGrooveView() const + { return GrooveView; } + + +public: + /// is called the TaskView when the dialog is opened + virtual void open(); + /// is called by the framework if an button is clicked which has no accept or reject role + virtual void clicked(int); + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); + /// is called by the framework if the dialog is rejected (Cancel) + virtual bool reject(); + /// is called by the framework if the user presses the help button + virtual bool isAllowedAlterDocument(void) const + { return false; } + + /// returns for Close and Help button + virtual QDialogButtonBox::StandardButtons getStandardButtons(void) const + { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } + +protected: + ViewProviderGroove *GrooveView; + + TaskGrooveParameters *parameter; +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TASKAPPERANCE_H diff --git a/src/Mod/PartDesign/Gui/TaskGrooveParameters.ui b/src/Mod/PartDesign/Gui/TaskGrooveParameters.ui new file mode 100644 index 0000000000..d7a68d6c20 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskGrooveParameters.ui @@ -0,0 +1,93 @@ + + + PartDesignGui::TaskGrooveParameters + + + + 0 + 0 + 278 + 158 + + + + Form + + + + + + + + Axis: + + + + + + + + Vertical sketch axis + + + + + Horizontal sketch axis + + + + + + + + + + + + Angle: + + + + + + + 1 + + + 0.000000000000000 + + + 360.000000000000000 + + + 10.000000000000000 + + + 360.000000000000000 + + + + + + + + + true + + + Symmetric to plane + + + + + + + Reversed + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/ViewProviderGroove.cpp b/src/Mod/PartDesign/Gui/ViewProviderGroove.cpp new file mode 100644 index 0000000000..af7a248547 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderGroove.cpp @@ -0,0 +1,141 @@ +/*************************************************************************** + * Copyright (c) 2011 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include +#include +#include +#include +#include + +#include "ViewProviderGroove.h" +#include "TaskGrooveParameters.h" + +using namespace PartDesignGui; + +PROPERTY_SOURCE(PartDesignGui::ViewProviderGroove,PartDesignGui::ViewProvider) + +ViewProviderGroove::ViewProviderGroove() +{ +} + +ViewProviderGroove::~ViewProviderGroove() +{ +} + +std::vector ViewProviderGroove::claimChildren(void)const +{ + std::vector temp; + temp.push_back(static_cast(getObject())->Sketch.getValue()); + + return temp; +} + +void ViewProviderGroove::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) +{ + QAction* act; + act = menu->addAction(QObject::tr("Edit Groove"), receiver, member); + act->setData(QVariant((int)ViewProvider::Default)); + PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member); +} + +bool ViewProviderGroove::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + // When double-clicking on the item for this pad the + // object unsets and sets its edit mode without closing + // the task panel + Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); + TaskDlgGrooveParameters *padDlg = qobject_cast(dlg); + if (padDlg && padDlg->getGrooveView() != this) + padDlg = 0; // another pad left open its task panel + if (dlg && !padDlg) { + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().closeDialog(); + else + return false; + } + + // clear the selection (convenience) + Gui::Selection().clearSelection(); + //if (ModNum == 1) + // Gui::Command::openCommand("Change Groove parameters"); + + // start the edit dialog + if (padDlg) + Gui::Control().showDialog(padDlg); + else + Gui::Control().showDialog(new TaskDlgGrooveParameters(this)); + + return true; + } + else { + return PartGui::ViewProviderPart::setEdit(ModNum); + } +} + +void ViewProviderGroove::unsetEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default) { + // and update the pad + //getSketchObject()->getDocument()->recompute(); + + // when pressing ESC make sure to close the dialog + Gui::Control().closeDialog(); + } + else { + PartGui::ViewProviderPart::unsetEdit(ModNum); + } +} + +bool ViewProviderGroove::onDelete(const std::vector &) +{ + // get the support and Sketch + PartDesign::Groove* pcGroove = static_cast(getObject()); + Sketcher::SketchObject *pcSketch; + App::DocumentObject *pcSupport; + if (pcGroove->Sketch.getValue()){ + pcSketch = static_cast(pcGroove->Sketch.getValue()); + pcSupport = pcSketch->Support.getValue(); + } + + // if abort command deleted the object the support is visible again + if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch)) + Gui::Application::Instance->getViewProvider(pcSketch)->show(); + if (pcSupport && Gui::Application::Instance->getViewProvider(pcSupport)) + Gui::Application::Instance->getViewProvider(pcSupport)->show(); + + return true; +} + + diff --git a/src/Mod/PartDesign/Gui/ViewProviderGroove.h b/src/Mod/PartDesign/Gui/ViewProviderGroove.h new file mode 100644 index 0000000000..51b1adca49 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ViewProviderGroove.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (c) 2011 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef PARTGUI_ViewProviderGroove_H +#define PARTGUI_ViewProviderGroove_H + +#include "ViewProvider.h" + + +namespace PartDesignGui { + +class PartDesignGuiExport ViewProviderGroove : public ViewProvider +{ + PROPERTY_HEADER(PartGui::ViewProviderGroove); + +public: + /// constructor + ViewProviderGroove(); + /// destructor + virtual ~ViewProviderGroove(); + + /// grouping handling + std::vector claimChildren(void)const; + + void setupContextMenu(QMenu*, QObject*, const char*); + + virtual bool onDelete(const std::vector &); + +protected: + virtual bool setEdit(int ModNum); + virtual void unsetEdit(int ModNum); + +}; + + +} // namespace PartDesignGui + + +#endif // PARTGUI_ViewProviderGroove_H diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index 50f9f9adfd..961393e703 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -86,6 +86,7 @@ void Workbench::activated() "PartDesign_Pad", "PartDesign_Pocket", "PartDesign_Revolution", + "PartDesign_Groove", 0}; Watcher.push_back(new Gui::TaskView::TaskWatcherCommands( "SELECT Sketcher::SketchObject COUNT 1", @@ -169,6 +170,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "PartDesign_Pad" << "PartDesign_Pocket" << "PartDesign_Revolution" + << "PartDesign_Groove" << "PartDesign_Fillet" << "PartDesign_Chamfer"; @@ -186,6 +188,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const << "PartDesign_Pad" << "PartDesign_Pocket" << "PartDesign_Revolution" + << "PartDesign_Groove" << "PartDesign_Fillet" << "PartDesign_Chamfer"; From d5c7c1ea45f68ffd96758d81a317ec4d5b4605c3 Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Fri, 8 Jun 2012 19:51:53 +0430 Subject: [PATCH 338/351] Pad feature: Midplane, two-sided dimensions, up to first/last/face options --- data/tests/PadTest.fcstd | Bin 0 -> 14782 bytes src/Mod/Part/App/PartFeature.cpp | 74 +++++- src/Mod/Part/App/PartFeature.h | 32 +++ src/Mod/PartDesign/App/FeaturePad.cpp | 231 +++++++++++++++---- src/Mod/PartDesign/App/FeaturePad.h | 12 +- src/Mod/PartDesign/Gui/TaskPadParameters.cpp | 156 +++++++++++-- src/Mod/PartDesign/Gui/TaskPadParameters.h | 14 +- src/Mod/PartDesign/Gui/TaskPadParameters.ui | 57 ++++- 8 files changed, 499 insertions(+), 77 deletions(-) create mode 100644 data/tests/PadTest.fcstd diff --git a/data/tests/PadTest.fcstd b/data/tests/PadTest.fcstd new file mode 100644 index 0000000000000000000000000000000000000000..8a7223083d43f88af19d30fa4f4f7e9512152815 GIT binary patch literal 14782 zcmbW8V~`-*)8^Z@ZQHiHr)}G|ZBN_wv~AnAIo&;NyL;!}ci;WrI~%*Pv8O&%L`D57 zPMpefG9&Xz`ES4=C;$Ke5CC!+{Q{3a%P<7M0RZOs0RUirKNYbva*bSg2M$7`9s*WN~nL)OIRA#mIOd~MJM8O;M|cIcP> z07;1F^Et0}ZJM~BIRCVmeUe0DJrU4yLtB6S?nTrQOw=kwJwra~u;&;;IY}~c zn@-Z#YE8k?f;S4~C*yw)*0o|*Q^LHXg`CSpB9OX0T#Vl3u$tp)9UrB3Sm1VACB(xk z(qh%>)1fOzHrBAg`CvdhXH-*i1N$0~iv6r77XhZUss}1uQ`cc*VxFrnb?$Zn3n#7D zha%JWC1ZV$XcxaNzV2RtiL4^rUVd5zXRtDz;2qd9@2q&#r-gWg?J6wk=!+C4Mg)pf zyqabhlHdPe@to6_wA@TTYn{ypf{3? zdLxBt4gljZVm$KNl4*U_UgCg zLyRW#z*i4m$*OSo;wIE*`J5=}jmkg&&01)4S-38C#Ahss`Fw#IiQ|bb4H5r-Dk=p7JTO5~+q&vo!%WbJR!;k61<}ZL@_avBmIm^`LY+;6vTPy#JUFHhJEdL`{h|bG@O{CVn0N;b(x*1Nd2_EwR<+Renufmx>AN(^kg zpffXh%JDinuVk2CgVwUg+wQZ5p7TgMQAh{S>}r!fn~huh$&y%SQPf%h)Kx8@GH(zR z{BRjDjr|IhblS5;8UVq5GjOz{yi;^ZD!D)&5Cu5P*ttDP%&NvhfKuwe!C2XG^WtcrtZIgF!6`<|tfV=q{{=4cP!=XL zLD{$WQ-HIMoIDprtBzCjo!XIM%Kisyc&oE z7zY*zoRboGELre6{EdM^g1fLN2{6lITu@`j^wX#LtsOn^nk zK^r1{_rRODls7v47eU;5p|3~I z-LON?47;0lJ>kkQ6Rc%MguG+dgZ=q5{!hPp5XQ43ghOmh5Sf_-+)Df-MX5x|Rj8BE ztWEJ3^Avl1%&-_#vL20BjhF^+2PvW_j0`1!XLu5UXq`-~hj*>XB9V(P)Qz1E*HeyJ zxIz?Vw2Y`Ar@UnXk11p zAvCOC!i0(^NfYt{J*6WA`uT(U-2z_<5<)-P%+E#fCHh$&$_D_7bOn@Z8f)dRGLm9Q z;du3)G^4jozgZ(1XxJ=gf&f>-*Z? z`!x=xLlt(+N7M((ACBp{XK=y3xKcwM@34;RQe*9Cm3oM(0{r$xxO{3dTc)~m76-I8!@MsOKWyfcS=c&|Y> zroqZDVAp1+0!+)W-iO!HJ%6e<@Ln$FxR%kdx=kNgGb<7f!f#y!PVfNxb)1MpxN;QIFu;Ufc|+l@xI>Ao)h`&KKQ$W+AUTf+e(RzUKmeDW&$r`GXx@-| z^zW4c8bBiTMS4l39)F4?d(g=Myv-kV2fuCYN zH^;+g^SK`jmyH$h*KOO+%w1VYpdhH;3^-KCu`VoRUMK!&yPXt@QEYCMSVr|yMtB~W ziUmf47@hspxkFSTQiV*loh)+6K0FUKlrZQD z@+UjF3JgxncSBnyDM{@3G>!!rPW{k28O#O4N5Nn+JUBTyKUA-BTOJ5$DdD!>RtDPF zUIrfPuax!mT`YXxWQO{%R`qFti0e4q%K)ftpicTBf`J&!<9r#QFQQ(EW@K^_5V9Ck z*a`{{M!YWZ1tXNkA;@DJ`xK6&1dp@!K_gtosce`%yFnG|OM+eVrmpm zqM)LPNtmcq+j`Cj?W`(1wB zKX!axh0)J|KiEGzK3{wsKgr>D^ze4^diUYydht59pP|!t;XDpFRz@=N=|T0P-}8xC zH9~IxGQij@oX?L_tWhjepewA2lWMo#lx^#>t&n8uaikgs>q9z{%C zTw1LB7OWlJmmW-OVWv~R8hxtvI0_!4q`o89G-`g@O1SD_BxZ%61qL4GymwC2EVghp zWuEl}XNw!eCfmE|f3#L;p4FhM6mRWdw|U~t0NDO~f`j=>qfAS@!C?+b5XaV_B2~t# zIn?pg_%)P`o;`Tuh}~MC3Zw7HriDk7)%iY#!Ex?1v93>(m+LGM4-uYDy`Oj4W^~kM zueo)WBP3NzXuy(v+)iC+^UU12Rx^{Ogb)Oznp-SLKC`doI~X=PYcXVSsyHz3x!_xU z>M8bm=O&nK>P{?}XE+}Sf?5q?toY#u`mx*6Y@M{T2-PJX>}8#;3DjjQO}+yZeM_(y z%PK`rpOI?#HmEItt(z3I*_dFEhwqzxt;1Ya1ra{n90;$bmG^8AB(b|rqF~L9hQX5A z7+!3p>EZDqM+ za3OUW?&{%$%IpNQKiE)WD9{rypw*2dIdNGIjN2eiKXh;fd8NEd*5Xnth&ia)L!KZJ z)=Qag7MDn>T8&5@`0bvfJ?EE)a7#y@wHg|Kf$s}+G3quWlKxGx!Xo^yCGtXEWF8$* zzq_#{H1eeD#X_9+6}{XqFZU?*nk~!9 z+`wpeO&bG>s~>j@_3x*|vJj;7S(b)q-3byL%~KyGrseU6ZeG=t*zp>4nQ~3AEA2om zGeMQyQ5no4_S+m}gFq9!%?URWKdo7o4}ml4sAw;g8s~xp^5%trU>BPut-$ZXX3v_> zc~}Y8oX6iW2Y=FO6t;8n?pQLlkRFe*+TM<;YME$lcHh9T6(4i^Z%dHEz9Pp`-VI-D zrPN;qTu(*33?rKlzQcmKGViN2pKV`0Q*m>jooAifiWTY!ake?vGxgZ+4wE2CVS;+jOrsPV`Z<>q zroMtk0gH_I`>2mC1aW{3;20UiB7=B;=@OVc&N8o-Vi6}@-=)(SeeZrd0|fUJVOoKE zm`6gP>|hHdN~{JBY2?P5P0JT}WZ6Z@EUN_-t;++Wx}#x}B2fqhWnX4tL8il?bCnG* z3r^cYqjd95gn^ECZe57;|4CGYAek1I!pamaY3yxCVr*Cz7hqwcFP4$e5tUR(s#p9N zsON^B?u^S+v^Cb`0|tsqe7X@xmLOh6;kxKARt=l2kGS?Nc7R1NNDh4#fdVQ}EiZli zQ1T~4dQm$JtaN-Gr7;s#k!i?OFqF7iu&h4vFcdb1dZ_RSyjO%Vxv68INXT=iev#oo~pCbdG`CxNoH4pOt>L;hME|^Y+?l3_@32PD%5xHiWh`b^Yh5J_gB{TZrrN&RwP1Vh` zeB)^sLWD75Udd4m^0VJ&|0FY3cEHA7X7@z?l7XXks>gv$O zB*+j}$Sbsbh&Ld4%A`C(8EStJtY_XXFCd8cVxVxUGGq;L8Y;l`tfC@rFH!+=QyH(| zV)}97v_@Ms5ecM5+Pc!;-!>cy;)%}AI^f8W6xkDmf!#{40VKI`L4vYE3T2KlLsNhv zHJ4a`A_xfe>o1We@{cQ`_O~a%6xgML_AfH&s$xpuR0DD*f^?3ny$|_D_;Jf?C_^l; zXs%@_SC!xrn+<~y%}f7Xo&e%I1roGyVH$9A$aHYhH$8PFU4noDR%nvYP?joyjJ&G0^~dw$>D|Ie=~GWMe;I#_pZn9uja>)*4EIg#Tm9S1 zz(iQ7+<;#0_C@z@YO2DTAnd`p_!PZ3XAjyED_<^jFZv=INMZ8hGzDd`56ZZjq9$!J zW)qf6fO5U)_d=`?tfQ-oKGl8YgXP^|_TY6-Ohb8vinwJf$at+mfwBm+gR?{TMu^n9mPSg-5Lm|#g|(khW^JN-mRK;;$lO?rDIee_6^_3G$@-AV}-v+G+bnOrj&F@sqd_+*6~Es ztJvTK4T{_Z=k0pXL|@ptyLm;cl*`XnnN)CjGE=-_RUOYyx&wTw5mqC>J3!@%{L=(_ zf|$M!pN{K__vU5L%*p7?E>sppTiq`*{Aw)7rNnC2J)ZYDsfd!QNqGu?4i1!+qejbE z*UM+NSikY-`>EwdMx9K@YB*Am*TPkfGE1e~;}sugl&jG`4)@nhC?Tv%zL zT_*dl_Ec%+mOa60wX4VVyIGKrC2m|`OResKa8HvZ}UZj?+y^+?nrd zKs((_b8c$Lz2%qzL7>0iwt0#IJTY_`Au!*L|0{H)4$gF2%>z@gG@k)n*I((Jb4DFy zZX1HCdp-?LET!%9xQL;c?&Yn&*G?{9JI39(1Z&Wc_Z9efM_>0n&sm-d0$NtKyYJ{* zc(K8L?zoaho=Eb0mUMidUcXI0%xVE0XBIy|jCiS^QB|q?v@)!kD((c&C1s=kIA==kNpKi|o9;iVK-y z)4w;~<>Q|7=d@^HYa7oF7E=rAF(s?*xI`tM8TVzduQ4w3_DPV+(F_cZBzJ_ACB0v-~ttH$2=fSs=`>9rU$lP>mcL&o+A_J)K;w|5`K8vwPtzcCU5NR)WM6wbj zy)Wpw1$_KnA4d;Mkw~LWDir#8ZF+Trk=8uJOO<8KAODcV3#wjAROPC8TLGK>={yqGYF>l=VkgMy6|Jz+sq@?OdUp>9-r zu}^ZKs9IE3MT_#BCDMlP6tH+Vkl3B`E$vR+S#x7A(|b`@5!_kc-MeNmE3tsE(^AZZ#WgGf^r>#!0tRi%pyNPUZuX_C+IWtOrB|^h;87VTD5PRPPDFB-zjLqH0%I)IzU_ zvW!9x8tD{!D(H&8D@ef8iK9?lyFo*b4MimhACgP(nxcb!O$MtFG03N}q3w;IXEZ>L zP}EJ*O-62=k8{Kq(`sWBsrs?s*t(U+GGQ9z2XZIY@r!DFXjp2$VTnoOK?M{809 ziKH~E%TU}ml<1u zZ$wko)%mLg({5irBrq;lbD<-; zw}>sV?a5@PFdCECa=HiXPXtSDwuHnxgV zABH*a%;z?LAbuxN90xQx0&8WaL2;c%&`O6(LlYjuayU^pB6q6V#X z`^lo$KJ*joNpEDZ&>OcM?VR<48=JY6`AkpeD@BL1<*{|!hq}5SgFH~dZ>xO5$EyQ< z<+2rE5OPr?z$E8uwNoX~M!N$f${q)%g9-qnJE292mMrVJPJcx9m>pS6wE)FtZy%=N z5Vcqmx`Te=lopM-6S2!L_5MTU& zics_pYKkAE3pBSGuo{LHf~X4w@5{Ft7xLnOkv74q;qieUnLNpfS?ok`a%#Ca@%sIKs z8@&T}4=ah=1U_mX*PhZKZ4HDLU4{t+M79R62mGQ3mt{3~#{%1x;13!N07afN{lx!w zsL4rV8Y2h@0ATSu>-?{LA@g6MX0k$`Z9fA{*BiC>rv8ufV7AkE1=~zE*uhvOFw6?& zrZP~nPhVN^M1SNNg+mID8G6^7XEZi^(KEkyGgQ+ZUt|EXgEeDqX@_m=jB*Wp`#yO0 zmd+8g9-A(z_vNdJYHLe(%M@Q~$uKMoj=E*@Wev-;a4|uL(Br(j!u^H@L!s6X|6hvN zin|3sMEU!J#wk@3GCA`SXI8mH&{*+Dv`Esf7knowZc^OFZ7RbgNt!lHFIMnDp-4o{ zDR;<4x-cnm;~$afGL^2x&4YnFj(bf%;Lb|eLXtRt(m!<4`gCopjL;!Zx?ZH}g`OP! zg8TUaz|B$%(JL4qva0A(U#w6XF*jW|k?k+o35XB{YlzY747z&v2@@1e-cCA+bOF<` z7{@{<=k#2P2m?E8JIdz&ghXID_HIxX!U2FGR;Bmv#m099xNQLj05JTW+yB>Mv-};` ztIF76vmyXZVkbN<&F$W$$bdfkc{Y`QN#icFd1`;e){a#lWM#Xs>99VNnt-; zCg60l-0b&!P4xG*p!QzTl!S|Fjo&2lWqHDYaU=tKd}xvYs7ksPGp_Luv9 zm9LhZaG2^#4JpudWyN}ft<>R5QkAD+zWdxu2S_Py8iYRmAdzEz+Ci!c^sL2mv=q^V z8k5}gOdPz#ndHt*trB6`B1n3zkYnas+)Z@JM@`)uPhgY}d0#XyBeM+sX7MDx1g?+K zClp6sTRxcIlw}auDw*!7-)CK$@zH^AP#s zBXb^G7xS@L@oi>L$B>^v8Se!nWmdv^tabq#>cxNvxUrg^?2sE?wrN7#H!Qr+ zgB~suP2L*n#ZPxyUSnWy;g6jJQqi4=_~d2Aw{;b87Q4tv&*cW#1YWld*%yRbf`aay zUm`hadzD1>MpaS!0mfADgzxu>En(e*lT}sAYW^!NQs1w+l)5E zlUG@uoHj?z|UbRUA*`P1G>-HC$OnZK@SPM(L2Zcm0@9GNl9fHmmvy{#_u#};S(Yl~lKZzN#1Ao?7uT{AK=E4Aw3 z;f{HXR}rOtq^+-FYp76FeXGyD-8pte=4zdA+=Rd)vAkIZC|e);&McjNEu z!PedWuzy;}gtx=nzW98e%aBLwW>;Yu{WAElK;C5!?`)k@f}VoA?;)P{9#)txT}C# z#!us&$?@!KxT3!Zw(7f0C&0I%#2cdO{?lLYYBq~wrF4y#XnMXd?WWb2SdG7=>)FV5 zqqm-mAZ6fayC?aysf$%buaGOJxhS5|zH9C9Pqo>1+(FF989Zfcc9f}|n4J)lRB@TL{5H{%Muw*e98%z59^omyXYr4b zbKzR94dcLvv9mWqGOTgTssuL$uR;b?6BY59JFRKWnjqP}pK%Kx2sE&4$O2{_RP0vv zApJc2^G^#uGpb7q3k(Fst*Ef}%aYy5H1UIk&g-5(D`{XX6Q<`#ONHb)xivjUd?6<0 zhU0kLBbMYR^gZmQ4p$~CDQKDT z>T?nU`L9|*9+Snp?SY_&;hN1`J1?i)iqA$ul|D$nMhmtyZ=MZYLyCDTf>c-SQ!;uG z6YJo0pl2NPn|E*Gz{pZt7r=5R$|;jvTwo-~s&?%5b}Pps^}8<0zDdjA<~mN&756j>$QZr#(N1cW z9MptK!RP_a5WQBa&llM3>!X-&c_yF36Uc_hD(rwP4e$+lzp>8Ol8|2JtVz6_SJ}>0 znGfqM3ZDG%GaVfn_qtGwHPD}d@ip^il!mi^S7d}8X9~r63Ih%yfrHUQu z1tj$qcn2<`6@_*s6d%>=S%E%#)!kZ2tnSVJgrfv@8D`zKg8;#RB9T`!NQ)ti8dbza zz$4x^=Udn!0*8tqQuX%->tblnj zBCJ)f&};O(}FfFwOwNb$2Wqi379GLqEfv@ zI2$_{8;1}FyLKu+?IaeOy2_uj6mF}Lw}hKQqJ-^n+^vV)D%g2==4>#$^ZGoQdmLpt z&%G9K-g!Ad>j&6PW!YM};rF%3+SWLLn)u(4obkD`?PGZ-6q7XoHkxhA`3#I?`H49QVyq7?KvoKP1)dodzGf}i=8{Ez zvMmSLoVD@VqFe|$M&nmWo}8GR%K(NYpMiSkGx+(rzuldMxjmA~!Y1{6Jzh>c*(tPY2~CO?EwVs4fi7qft`f#-EtMPcHws3T7M4bH5^8dCD~fcIy#8XDUSNuNp4iDqtBY;y8yClpe(nWoyWT_QGD;6gXc z@uf|_quc5Oyq4PQCCnQsSa0vVmsJI^HPh|MPf_Zy5Hhb)bCmAcswT5ZlP6OA6mX|G z->0PyxS8_SLNuh$wK+fTEaru0wZSFzzoy$j_Fy;8s>S7HLJTmaS zi9P-{5bo3jMaUCbivc$b6rQZ@{8SG|u?Mw} zr=c*J<{6i@Y1N~VJGmF#zDhDufrhdMu2e=@!0T9EHaBzpTYdNBN^1T6&z6=f7HM=` z*xTLdH43!u_3}9!=xun@(hsyHgKP2>H0qT+r9&a7Sxjp%8I;F)QA;OcRgfpyQ^P$S z(*o^W@Fu4aENBsn4HE-pwTDRWB#kP}Sq$Zyb1>*}g{zlpg4g})Ql;I_ zOC|);0Rm;nM?-h1Q>=_IRS_J#7)Sa-eb_x8jGJKIn#F=N$;1w9qA4YWzAOfRpgI#e zI3k(Jv0U`UacJ#o%1@6`)ou}1P^^HF5nSxmBLy_E7}LbOzh{|WpQ9E)d_sj|T9;?Z zM_1!ED&;jGg_vL{UWV7tC3;Cp^VFI5v1>vi6cwVz8%WeT7bi~z}xi1wl3IT}}YBUEn1Sb3gialA+!kk0#5jN0L{d zA4QOf)P{IMhgBORHoD-6g$Nl6z(^g#lP*VKku^7uIEBna`kF5jsx+NLB?5v0#AlyW z2%jp)n&|I72X~Vq8C&eLD71qehUjsk#na^JFE58GBA^vFmyM%VT}LTL5^ijhr$~Y! zbk?RL*!&VD&}=@Ki_@ZQlp|EF854dyZxA+a(9Sx?H)bS{<5PHhzbej zJrn_Yx|9IaQ+&?dX4p17w`*%Y?ysGxY+biYa)5_Hl#d_sNyy*`ra4H+fUqCsa6f+K z>ASMf(Gg_EP+X8VB+0|xCwYZQ?)8le$x1;sYf;Tvr`J?>3;11Bt)U$hYD5jje|PtY zgg~8jS(Y6WA67j7o?&#bw87${WX7`2!*~1#BUzS0qvJ16VD8W`VytrDgO7#%%J@mt zkLB-C@HX%7DAfq`qXNMDs6DT=;7pEQul2ljGRGTF_9*dfe6`D8G~zoc@M`n*X+aQM zi&g#v&m;)7E|Q}xKiqkaeaU@7b;F7+Hwl2IU5IJpsltr1*OK58zMJ_{f?^^;5Ym=W zhHX^R4A3AG;)a;$b(U9(rm33H%YWjip$d|E|6I^xZmQECy>bUt3Uu!cNOw;&p~@Nb znc`vtSC%_XSj<2U-d9#;aiqKKhR*AqE4th${UkBZANnnYe^KF{)?dI&Dy+FErvw>N zE)z`>Ue($N5}6{=HmB2(QlC>w{URo4A-Czg~qA&_TjuqMYB5udY5C4Y4VqMaJy({44lKn;D9y&9dn{EL> z*&Ropfdpt$zQp2nT7G%Z2^JYke?TZWIjEz!Ln6c`nM_{Fv7<2vWKcZfVj3hw{ty7D zGYkD>;<*8$BD2!GJQ*VM7IS|(bMFZy`#~x74s$Vl;{~QkY?Mh05*G9NBK%_Tx1$hm&=F+7+(C%<(sUA1E6Kt61$YfEaBWF z*vX;W1lVq@NCBdoNWtDuk%BEA&%9)dGre`P`ES+iffNN`@=l!vBSJw$qh_+YE^4(w z?AYP48wfIlo#sH8b-Xs_GbS8ApDZ_ikcC89$3O?EixPcTQ+4O=Ai+*^<^p zCyA2W?HjGj!)RsP}

PRq*>42O03P1^v|#P$@HIIK6?4UliZ_|#7K$qdn3G;9~A0F zD0_!zIH6~4Re1-^I;CZ1GsZcllr}Kcl_TzeT(SF%Vu*h8Vbk0>7EiB5l=Ou#d|f-& z+1#vc#Qv9S%$1&ic2K!A@XGVzSV~P4>;^Ry3sZIM1fMhl=C)u6Z$hEmJlojxtDiaU z`GGf0moI(K`>U^K4&Hkqd_0)3U!neG8<5sJfGFw=*Ia~fI`CEJ`HFqB7y5;jF>(5+=o2VBRSIc*Acae{@BZevMCN<_eIS%iwfbKgh zfuWJFAzL~pK<6|}9GeB??})YDq95HEF2BWY&KjDv1-@>ig{bT4VReDxqXHCG2a&J5 zE*X-dAF7L2u7-wtN*6n=Z9CoLD{Z}8{O$mpJwU=}_46-oagd?2GeV-?RQ5=7_9`Fb zLgsMkgOKQPhe;&Yl)vEpUQL|8HuC)5Zk+IcA=CYsUKfEKVe_dt;Iuge<7yy>09w42 z*|Bh;LGL~kGHWoQ%z;px;2G7mY2t$GY_XZSyKn`l!R zO&V>Q?7iJ!^9~}zK4OEo+w85+$2k+>c+h|re*Fp# # include # include +// includes for findAllFacesCutBy() +# include +# include +# include // for Precision::Confusion() #endif @@ -139,22 +143,25 @@ ShapeHistory Feature::buildHistory(BRepBuilderAPI_MakeShape& mkShape, TopAbs_Sha history.type = type; TopTools_IndexedMapOfShape newM, oldM; - TopExp::MapShapes(newS, type, newM); - TopExp::MapShapes(oldS, type, oldM); + TopExp::MapShapes(newS, type, newM); // map containing all old objects of type "type" + TopExp::MapShapes(oldS, type, oldM); // map containing all new objects of type "type" + // Look at all objects in the old shape and try to find the modified object in the new shape for (int i=1; i<=oldM.Extent(); i++) { bool found = false; TopTools_ListIteratorOfListOfShape it; + // Find all new objects that are a modification of the old object (e.g. a face was resized) for (it.Initialize(mkShape.Modified(oldM(i))); it.More(); it.Next()) { found = true; - for (int j=1; j<=newM.Extent(); j++) { + for (int j=1; j<=newM.Extent(); j++) { // one old object might create several new ones! if (newM(j).IsPartner(it.Value())) { - history.shapeMap[i-1].push_back(j-1); + history.shapeMap[i-1].push_back(j-1); // adjust indices to start at zero break; } } } + // Find all new objects that were generated from an old object (e.g. a face generated from an edge) for (it.Initialize(mkShape.Generated(oldM(i))); it.More(); it.Next()) { found = true; for (int j=1; j<=newM.Extent(); j++) { @@ -166,10 +173,12 @@ ShapeHistory Feature::buildHistory(BRepBuilderAPI_MakeShape& mkShape, TopAbs_Sha } if (!found) { + // Find all old objects that don't exist any more (e.g. a face was completely cut away) if (mkShape.IsDeleted(oldM(i))) { history.shapeMap[i-1] = std::vector(); } else { + // Mop up the rest (will this ever be reached?) for (int j=1; j<=newM.Extent(); j++) { if (newM(j).IsPartner(oldM(i))) { history.shapeMap[i-1].push_back(j-1); @@ -204,6 +213,15 @@ ShapeHistory Feature::joinHistory(const ShapeHistory& oldH, const ShapeHistory& return join; } +const TopoDS_Shape Feature::findOriginOf(const TopoDS_Shape& reference) { +/* Base::Console().Error("Looking for origin of face in %s\n", this->getName()); + if (reference.ShapeType() == TopAbs_FACE) { + // Find index of reference in the history + } +*/ + return TopoDS_Shape(); +} + /// returns the type name of the ViewProvider const char* Feature::getViewProviderName(void) const { return "PartGui::ViewProviderPart"; @@ -253,3 +271,51 @@ template<> PyObject* Part::FeaturePython::getPyObject(void) { template class PartExport FeaturePythonT; } +// ---------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +std::vector Part::findAllFacesCutBy( + const TopoDS_Shape& shape, const TopoDS_Shape& face, const gp_Dir& dir) +{ + // Find the centre of gravity of the face + GProp_GProps props; + BRepGProp::SurfaceProperties(face,props); + gp_Pnt cog = props.CentreOfMass(); + + // create a line through the centre of gravity + gp_Lin line = gce_MakeLin(cog, dir); + + // Find intersection of line with all faces of the shape + std::vector result; + BRepIntCurveSurface_Inter mkSection; + // TODO: Less precision than Confusion() should be OK? + + for (mkSection.Init(shape, line, Precision::Confusion()); mkSection.More(); mkSection.Next()) { + gp_Pnt iPnt = mkSection.Pnt(); + double dsq = cog.SquareDistance(iPnt); + + if (dsq < Precision::Confusion()) + continue; // intersection with original face + + // Find out which side of the original face the intersection is on + gce_MakeDir mkDir(cog, iPnt); + if (!mkDir.IsDone()) + continue; // some error (appears highly unlikely to happen, though...) + + if (mkDir.Value().IsOpposite(dir, Precision::Confusion())) + continue; // wrong side of face (opposite to extrusion direction) + + cutFaces newF; + newF.face = mkSection.Face(); + newF.distsq = dsq; + result.push_back(newF); + } + + return result; +} +// -------------------------------------------------------------------- diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index 689736a420..ed3de37376 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -29,9 +29,16 @@ #include #include #include +// includes for findAllFacesCutBy() +#include +class gp_Dir; class BRepBuilderAPI_MakeShape; +// includes for findAllFacesCutBy() +#include +class gp_Dir; + namespace Part { @@ -63,9 +70,22 @@ public: virtual PyObject* getPyObject(void); virtual std::vector getPySubObjects(const std::vector&) const; + /** + /* Find the origin of a reference, e.g. the vertex or edge in a sketch that + /* produced a face + */ + const TopoDS_Shape findOriginOf(const TopoDS_Shape& reference); + protected: void onChanged(const App::Property* prop); TopLoc_Location getLocation() const; + /** + /* Build a history of changes + /* MakeShape: The operation that created the changes, e.g. BRepAlgoAPI_Common + /* type: The type of object we are interested in, e.g. TopAbs_FACE + /* newS: The new shape that was created by the operation + /* oldS: The original shape prior to the operation + */ ShapeHistory buildHistory(BRepBuilderAPI_MakeShape&, TopAbs_ShapeEnum type, const TopoDS_Shape& newS, const TopoDS_Shape& oldS); ShapeHistory joinHistory(const ShapeHistory&, const ShapeHistory&); @@ -99,6 +119,18 @@ public: } }; +// Utility methods +/** +/* Find all faces cut by a line through the centre of gravity of a given face +/* Useful for the "up to face" options to pocket or pad +*/ +struct cutFaces { + TopoDS_Face face; + double distsq; +}; +std::vector findAllFacesCutBy(const TopoDS_Shape& shape, + const TopoDS_Shape& face, const gp_Dir& dir); + } //namespace Part diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index 1a12c45565..c7742c1f4b 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -39,23 +39,32 @@ # include # include # include +# include +# include #endif #include #include +#include #include "FeaturePad.h" using namespace PartDesign; +const char* Pad::TypeEnums[]= {"Length","UpToLast","UpToFirst","UpToFace","TwoLengths",NULL}; + PROPERTY_SOURCE(PartDesign::Pad, PartDesign::Additive) Pad::Pad() { + ADD_PROPERTY(Type,((long)0)); + Type.setEnums(TypeEnums); ADD_PROPERTY(Length,(100.0)); ADD_PROPERTY(Reversed,(0)); - ADD_PROPERTY(MirroredExtent,(0)); + ADD_PROPERTY(Midplane,(0)); + ADD_PROPERTY(Length2,(100.0)); + ADD_PROPERTY(FaceName,("")); } short Pad::mustExecute() const @@ -63,8 +72,10 @@ short Pad::mustExecute() const if (Placement.isTouched() || Sketch.isTouched() || Length.isTouched() || - MirroredExtent.isTouched() || - Reversed.isTouched()) + Midplane.isTouched() || + Reversed.isTouched() || + Length2.isTouched() || + FaceName.isTouched()) return 1; return 0; } @@ -74,6 +85,10 @@ App::DocumentObjectExecReturn *Pad::execute(void) double L = Length.getValue(); if (L < Precision::Confusion()) return new App::DocumentObjectExecReturn("Length of pad too small"); + double L2 = Length2.getValue(); + if ((std::string(Type.getValueAsString()) == "TwoLengths") && (L < Precision::Confusion())) + return new App::DocumentObjectExecReturn("Second length of pad too small"); + App::DocumentObject* link = Sketch.getValue(); if (!link) return new App::DocumentObjectExecReturn("No sketch linked"); @@ -103,10 +118,8 @@ App::DocumentObjectExecReturn *Pad::execute(void) // get the Sketch plane Base::Placement SketchPos = static_cast(link)->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); - Base::Vector3d SketchOrientationVector(0,0,1); - if (Reversed.getValue()) // negative direction - SketchOrientationVector *= -1; - SketchOrientation.multVec(SketchOrientationVector,SketchOrientationVector); + Base::Vector3d SketchVector(0,0,1); + SketchOrientation.multVec(SketchVector,SketchVector); // get the support of the Sketch if any App::DocumentObject* SupportLink = static_cast(link)->Support.getValue(); @@ -118,27 +131,159 @@ App::DocumentObjectExecReturn *Pad::execute(void) if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); - // lengthen the vector - SketchOrientationVector *= L; - this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); try { // extrude the face to a solid - gp_Vec vec(SketchOrientationVector.x,SketchOrientationVector.y,SketchOrientationVector.z); - vec.Transform(invObjLoc.Transformation()); - BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),vec,0,1); - if (PrismMaker.IsDone()) { - // if the sketch has a support fuse them to get one result object (PAD!) - if (SupportObject) { - // At this point the prism can be a compound - TopoDS_Shape result = PrismMaker.Shape(); - // set the additive shape property for later usage in e.g. pattern - this->AddShape.setValue(result); + TopoDS_Shape prism; + bool isSolid = false; // support is a solid? + bool isSolidChecked = false; // not checked yet + + if ((std::string(Type.getValueAsString()) == "UpToLast") || + (std::string(Type.getValueAsString()) == "UpToFirst") || + (std::string(Type.getValueAsString()) == "UpToFace")) + { + TopoDS_Face upToFace; + gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); + + if ((std::string(Type.getValueAsString()) == "UpToLast") || + (std::string(Type.getValueAsString()) == "UpToFirst")) + { + // Check for valid support object + if (!SupportObject) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: No support in Sketch!"); const TopoDS_Shape& support = SupportObject->Shape.getValue(); - bool isSolid = false; + if (support.IsNull()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Support shape is invalid"); + TopExp_Explorer xp (support, TopAbs_SOLID); + if (!xp.More()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Support shape is not a solid"); + isSolid = true; + isSolidChecked = true; + + TopoDS_Shape origFace = makeFace(wires); // original sketch face before moving one unit + std::vector cfaces = Part::findAllFacesCutBy(support, origFace, dir); + if (cfaces.empty()) + return new App::DocumentObjectExecReturn("No faces found in this direction"); + + // Find nearest/furthest face + std::vector::const_iterator it, it_near, it_far; + it_near = it_far = cfaces.begin(); + for (it = cfaces.begin(); it != cfaces.end(); it++) + if (it->distsq > it_far->distsq) + it_far = it; + else if (it->distsq < it_near->distsq) + it_near = it; + upToFace = (std::string(Type.getValueAsString()) == "UpToLast" ? it_far->face : it_near->face); + } else { + if (FaceName.getValue() == "") + return new App::DocumentObjectExecReturn("Cannot extrude up to face: No face selected"); + + // Get active object, this is the object that the user referenced when he clicked on the face! + App::DocumentObject* baseLink = this->getDocument()->getActiveObject(); + + if (!baseLink) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: No object linked"); + if (!baseLink->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Linked object is not a Part object"); + Part::Feature *base = static_cast(baseLink); + const Part::TopoShape& baseShape = base->Shape.getShape(); + if (baseShape._Shape.IsNull()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Cannot work on invalid shape"); + + TopoDS_Shape sub = baseShape.getSubShape(FaceName.getValue()); + if (!sub.IsNull() && sub.ShapeType() == TopAbs_FACE) + upToFace = TopoDS::Face(sub); + else + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Selection is not a face"); + + // Validate face + // TODO: This would also exclude faces that are valid but not cut by the line + // So for now we trust to the intelligence of the user when picking the face + /*std::vector cfaces = findAllFacesCutBy(upToFace, origFace, dir); + if (cfaces.empty()) + return new App::DocumentObjectExecReturn("No faces found in this direction");*/ + } + + // Create semi-infinite prism from sketch in direction dir + // Hack, because the two lines commented out below do NOT work!!! + SketchVector *= 1E6; + gp_Vec vec(SketchVector.x,SketchVector.y,SketchVector.z); + vec.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),vec,0,1); // very long, but finite prism + //dir.Transform(invObjLoc.Transformation()); + //BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),dir,0,0,1); + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Could not extrude the sketch!"); + + // Cut off the prism at the face we found + // Grab any point from the sketch + TopExp_Explorer exp; + exp.Init(aFace, TopAbs_VERTEX); + if (!exp.More()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Sketch without points?"); + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current())); + + // Create a halfspace from the face, extending in direction of sketch plane + BRepPrimAPI_MakeHalfSpace mkHalfSpace(upToFace, aPnt); + if (!mkHalfSpace.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: HalfSpace creation failed"); + + // Find common material between halfspace and prism + BRepAlgoAPI_Common mkCommon(PrismMaker.Shape(), mkHalfSpace.Solid().Moved(invObjLoc)); + if (!mkCommon.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Common creation failed"); + + prism = this->getSolid(mkCommon.Shape()); + if (prism.IsNull()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Resulting shape is not a solid"); + } else if ((std::string(Type.getValueAsString()) == "Length") || + (std::string(Type.getValueAsString()) == "TwoLengths")) { + if (std::string(Type.getValueAsString()) == "Length") { + if (Midplane.getValue()) { + // Move face by half the extrusion distance to get pad symmetric to sketch plane + gp_Trsf mov; + mov.SetTranslation(gp_Vec(SketchVector.x,SketchVector.y,SketchVector.z) * (-1.0) * L/2.0); + TopLoc_Location loc(mov); + aFace.Move(loc); + } else if (Reversed.getValue()) { // negative direction + SketchVector *= -1.0; + } + + // lengthen the vector + SketchVector *= L; + } else { + // Move face by the second length to get pad extending to both sides of sketch plane + gp_Trsf mov; + mov.SetTranslation(gp_Vec(SketchVector.x,SketchVector.y,SketchVector.z) * (-1.0) * L2); + TopLoc_Location loc(mov); + aFace.Move(loc); + + // lengthen the vector + SketchVector *= (L + L2); + } + + // create the extrusion + gp_Vec vec(SketchVector.x,SketchVector.y,SketchVector.z); + vec.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),vec,0,1); // finite prism + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); + prism = PrismMaker.Shape(); + } else { + return new App::DocumentObjectExecReturn("Internal error: Unknown type for Pad feature"); + } + + // if the sketch has a support fuse them to get one result object (PAD!) + if (SupportObject) { + // set the additive shape property for later usage in e.g. pattern + this->AddShape.setValue(prism); + + const TopoDS_Shape& support = SupportObject->Shape.getValue(); + + if (!isSolidChecked) { // we haven't checked for solid, yet if (!support.IsNull()) { TopExp_Explorer xp; xp.Init(support,TopAbs_SOLID); @@ -147,32 +292,30 @@ App::DocumentObjectExecReturn *Pad::execute(void) break; } } - if (isSolid) { - // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result); - // Let's check if the fusion has been successful - if (!mkFuse.IsDone()) - return new App::DocumentObjectExecReturn("Fusion with support failed"); - result = mkFuse.Shape(); - // we have to get the solids (fuse create seldomly compounds) - TopoDS_Shape solRes = this->getSolid(result); - // lets check if the result is a solid - if (solRes.IsNull()) - return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); - this->Shape.setValue(solRes); - } - else + + if (!isSolid) return new App::DocumentObjectExecReturn("Support is not a solid"); } - else { - TopoDS_Shape result = this->getSolid(PrismMaker.Shape()); - // set the additive shape property for later usage in e.g. pattern - this->AddShape.setValue(result); - this->Shape.setValue(result); - } + + // Let's call algorithm computing a fuse operation: + BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), prism); + // Let's check if the fusion has been successful + if (!mkFuse.IsDone()) + return new App::DocumentObjectExecReturn("Fusion with support failed"); + TopoDS_Shape result = mkFuse.Shape(); + // we have to get the solids (fuse create seldomly compounds) + TopoDS_Shape solRes = this->getSolid(result); + // lets check if the result is a solid + if (solRes.IsNull()) + return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); + this->Shape.setValue(solRes); + } + else { + TopoDS_Shape result = this->getSolid(prism); + // set the additive shape property for later usage in e.g. pattern + this->AddShape.setValue(result); + this->Shape.setValue(result); } - else - return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); return App::DocumentObject::StdReturn; } diff --git a/src/Mod/PartDesign/App/FeaturePad.h b/src/Mod/PartDesign/App/FeaturePad.h index c758c94f7e..91bdeff59f 100644 --- a/src/Mod/PartDesign/App/FeaturePad.h +++ b/src/Mod/PartDesign/App/FeaturePad.h @@ -38,10 +38,13 @@ class Pad : public Additive public: Pad(); - App::PropertyLength Length; + App::PropertyEnumeration Type; + App::PropertyLength Length; //App::PropertyEnumeration Side; - App::PropertyBool Reversed; - App::PropertyBool MirroredExtent; + App::PropertyBool Reversed; + App::PropertyBool Midplane; + App::PropertyLength Length2; + App::PropertyString FaceName; /** @name methods override feature */ //@{ @@ -54,7 +57,8 @@ public: } //@} private: - static const char* SideEnums[]; + static const char* TypeEnums[]; + //static const char* SideEnums[]; }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index 8a902b2b96..d7c37b7b3b 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -59,30 +59,106 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,QWidget *parent) connect(ui->doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onLengthChanged(double))); - connect(ui->checkBoxMirrored, SIGNAL(toggled(bool)), - this, SLOT(onMirrored(bool))); + connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), + this, SLOT(onMidplane(bool))); connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), this, SLOT(onReversed(bool))); + connect(ui->doubleSpinBox2, SIGNAL(valueChanged(double)), + this, SLOT(onLength2Changed(double))); + connect(ui->changeMode, SIGNAL(currentIndexChanged(int)), + this, SLOT(onModeChanged(int))); + connect(ui->lineFaceName, SIGNAL(textEdited(QString)), + this, SLOT(onFaceName(QString))); this->groupLayout()->addWidget(proxy); + // Get the feature data PartDesign::Pad* pcPad = static_cast(PadView->getObject()); double l = pcPad->Length.getValue(); - bool mirrored = pcPad->MirroredExtent.getValue(); + bool midplane = pcPad->Midplane.getValue(); bool reversed = pcPad->Reversed.getValue(); + double l2 = pcPad->Length2.getValue(); + int index = pcPad->Type.getValue(); // must extract value here, clear() kills it! + const char* upToFace = pcPad->FaceName.getValue(); + // Fill data into dialog elements ui->doubleSpinBox->setMinimum(0); + ui->doubleSpinBox->setMaximum(INT_MAX); ui->doubleSpinBox->setValue(l); - ui->doubleSpinBox->selectAll(); - ui->checkBoxMirrored->setChecked(mirrored); + ui->doubleSpinBox2->setMinimum(0); + ui->doubleSpinBox2->setMaximum(INT_MAX); + ui->doubleSpinBox2->setValue(l2); + ui->checkBoxMidplane->setChecked(midplane); // According to bug #0000521 the reversed option // shouldn't be de-activated if the pad has a support face ui->checkBoxReversed->setChecked(reversed); + ui->lineFaceName->setText(upToFace == "" ? tr("No face selected") : tr(upToFace)); + ui->changeMode->clear(); + ui->changeMode->insertItem(0, tr("Dimension")); + ui->changeMode->insertItem(1, tr("To last")); + ui->changeMode->insertItem(2, tr("To first")); + ui->changeMode->insertItem(3, tr("Up to face")); + ui->changeMode->insertItem(4, tr("Two dimensions")); + ui->changeMode->setCurrentIndex(index); - // Make sure that the spin box has the focus to get key events - // Calling setFocus() directly doesn't work because the spin box is not - // yet visible. - QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); + // activate and de-activate dialog elements as appropriate + updateUI(index); +} + +void TaskPadParameters::updateUI(int index) +{ + if (index == 0) { // dimension + ui->doubleSpinBox->setEnabled(true); + ui->doubleSpinBox->selectAll(); + // Make sure that the spin box has the focus to get key events + // Calling setFocus() directly doesn't work because the spin box is not + // yet visible. + QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); + ui->checkBoxMidplane->setEnabled(true); + ui->checkBoxReversed->setEnabled(true); + ui->doubleSpinBox2->setEnabled(false); + ui->lineFaceName->setEnabled(false); + } else if ((index == 1) || (index == 2)) { // up to first/last + ui->doubleSpinBox->setEnabled(false); + ui->checkBoxMidplane->setEnabled(false); + ui->checkBoxReversed->setEnabled(false); + ui->doubleSpinBox2->setEnabled(false); + ui->lineFaceName->setEnabled(false); + } else if (index == 3) { // up to face + ui->doubleSpinBox->setEnabled(false); + ui->checkBoxMidplane->setEnabled(false); + ui->checkBoxReversed->setEnabled(false); + ui->doubleSpinBox2->setEnabled(false); + ui->lineFaceName->setEnabled(true); + QMetaObject::invokeMethod(ui->lineFaceName, "setFocus", Qt::QueuedConnection); + } else { // two dimensions + ui->doubleSpinBox->setEnabled(true); + ui->doubleSpinBox->selectAll(); + QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); + ui->checkBoxMidplane->setEnabled(false); + ui->checkBoxReversed->setEnabled(false); + ui->doubleSpinBox2->setEnabled(true); + ui->lineFaceName->setEnabled(false); + } +} + +void TaskPadParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::Pad* pcPad = static_cast(PadView->getObject()); + if (pcPad->Type.getValue() != 3) // ignore user selections if mode is not upToFace + return; + + if (!msg.pSubName || msg.pSubName[0] == '\0') + return; + std::string element(msg.pSubName); + if (element.substr(0,4) != "Face") + return; + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + pcPad->FaceName.setValue(element); + pcPad->getDocument()->recomputeFeature(pcPad); + ui->lineFaceName->setText(tr(element.c_str())); + } } void TaskPadParameters::onLengthChanged(double len) @@ -92,10 +168,10 @@ void TaskPadParameters::onLengthChanged(double len) pcPad->getDocument()->recomputeFeature(pcPad); } -void TaskPadParameters::onMirrored(bool on) +void TaskPadParameters::onMidplane(bool on) { PartDesign::Pad* pcPad = static_cast(PadView->getObject()); - pcPad->MirroredExtent.setValue(on); + pcPad->Midplane.setValue(on); pcPad->getDocument()->recomputeFeature(pcPad); } @@ -106,6 +182,40 @@ void TaskPadParameters::onReversed(bool on) pcPad->getDocument()->recomputeFeature(pcPad); } +void TaskPadParameters::onLength2Changed(double len) +{ + PartDesign::Pad* pcPad = static_cast(PadView->getObject()); + pcPad->Length2.setValue((float)len); + pcPad->getDocument()->recomputeFeature(pcPad); +} + +void TaskPadParameters::onModeChanged(int index) +{ + PartDesign::Pad* pcPad = static_cast(PadView->getObject()); + + switch (index) { + case 0: pcPad->Type.setValue("Length"); break; + case 1: pcPad->Type.setValue("UpToLast"); break; + case 2: pcPad->Type.setValue("UpToFirst"); break; + case 3: pcPad->Type.setValue("UpToFace"); break; + default: pcPad->Type.setValue("TwoLengths"); + } + + updateUI(index); + + pcPad->getDocument()->recomputeFeature(pcPad); +} + +void TaskPadParameters::onFaceName(const QString& text) +{ + if (text.left(4) != tr("Face")) + return; + + PartDesign::Pad* pcPad = static_cast(PadView->getObject()); + pcPad->FaceName.setValue(text.toUtf8()); + pcPad->getDocument()->recomputeFeature(pcPad); +} + double TaskPadParameters::getLength(void) const { return ui->doubleSpinBox->value(); @@ -116,9 +226,24 @@ bool TaskPadParameters::getReversed(void) const return ui->checkBoxReversed->isChecked(); } -bool TaskPadParameters::getMirroredExtent(void) const +bool TaskPadParameters::getMidplane(void) const { - return ui->checkBoxMirrored->isChecked(); + return ui->checkBoxMidplane->isChecked(); +} + +double TaskPadParameters::getLength2(void) const +{ + return ui->doubleSpinBox2->value(); +} + +int TaskPadParameters::getMode(void) const +{ + return ui->changeMode->currentIndex(); +} + +const QString TaskPadParameters::getFaceName(void) const +{ + return ui->lineFaceName->text(); } TaskPadParameters::~TaskPadParameters() @@ -174,7 +299,10 @@ bool TaskDlgPadParameters::accept() //Gui::Command::openCommand("Pad changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length = %f",name.c_str(),parameter->getLength()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %i",name.c_str(),parameter->getReversed()?1:0); - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.MirroredExtent = %i",name.c_str(),parameter->getMirroredExtent()?1:0); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Midplane = %i",name.c_str(),parameter->getMidplane()?1:0); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length2 = %f",name.c_str(),parameter->getLength2()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Type = %u",name.c_str(),parameter->getMode()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.FaceName = \"%s\"",name.c_str(),parameter->getFaceName().toAscii().data()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); if (!PadView->getObject()->isValid()) throw Base::Exception(PadView->getObject()->getStatusString()); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.h b/src/Mod/PartDesign/Gui/TaskPadParameters.h index c16493cadf..53afdacd06 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.h @@ -44,7 +44,7 @@ namespace PartDesignGui { -class TaskPadParameters : public Gui::TaskView::TaskBox +class TaskPadParameters : public Gui::TaskView::TaskBox, public Gui::SelectionObserver { Q_OBJECT @@ -52,19 +52,27 @@ public: TaskPadParameters(ViewProviderPad *PadView,QWidget *parent = 0); ~TaskPadParameters(); + int getMode(void) const; double getLength(void) const; + double getLength2(void) const; bool getReversed(void) const; - bool getMirroredExtent(void) const; + bool getMidplane(void) const; + const QString getFaceName(void) const; private Q_SLOTS: void onLengthChanged(double); - void onMirrored(bool); + void onMidplane(bool); void onReversed(bool); + void onLength2Changed(double); + void onModeChanged(int); + void onFaceName(const QString& text); protected: void changeEvent(QEvent *e); private: + void onSelectionChanged(const Gui::SelectionChanges& msg); + void updateUI(int index); private: QWidget* proxy; diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.ui b/src/Mod/PartDesign/Gui/TaskPadParameters.ui index d407bbf316..d1f2601cb4 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.ui @@ -6,8 +6,8 @@ 0 0 - 158 - 116 + 272 + 238 @@ -19,7 +19,7 @@ - Type: + Type @@ -39,7 +39,7 @@ - Length: + Length @@ -55,19 +55,19 @@ 5.000000000000000 - 20.000000000000000 + 10.000000000000000 - + - false + true - Mirrored extent + Symmetric to plane @@ -78,6 +78,47 @@ + + + + + + 2nd length + + + + + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + 5.000000000000000 + + + 0.000000000000000 + + + + + + + + + + + Face + + + + + + + + From 3e5c374a9bb84434c129f8d7bc1b721bb3978144 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Jun 2012 18:02:35 +0200 Subject: [PATCH 339/351] Fix build errors on Windows, fix a couple of bugs --- src/Mod/Part/App/PartFeature.cpp | 2 +- src/Mod/Part/App/PartFeature.h | 2 ++ src/Mod/PartDesign/App/FeaturePad.cpp | 5 +++-- src/Mod/PartDesign/App/FeaturePocket.cpp | 1 + src/Mod/PartDesign/Gui/Command.cpp | 5 +++-- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index ed936a46b1..45e0076e95 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -272,6 +272,7 @@ template class PartExport FeaturePythonT; } // ---------------------------------------------------------------- + #include #include #include @@ -318,4 +319,3 @@ std::vector Part::findAllFacesCutBy( return result; } -// -------------------------------------------------------------------- diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index ed3de37376..9bb4bd49ae 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -128,6 +128,8 @@ struct cutFaces { TopoDS_Face face; double distsq; }; + +PartExport std::vector findAllFacesCutBy(const TopoDS_Shape& shape, const TopoDS_Shape& face, const gp_Dir& dir); diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index c7742c1f4b..c5791abcd7 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -26,6 +26,7 @@ //# include //# include # include +# include # include # include # include @@ -87,7 +88,7 @@ App::DocumentObjectExecReturn *Pad::execute(void) return new App::DocumentObjectExecReturn("Length of pad too small"); double L2 = Length2.getValue(); if ((std::string(Type.getValueAsString()) == "TwoLengths") && (L < Precision::Confusion())) - return new App::DocumentObjectExecReturn("Second length of pad too small"); + return new App::DocumentObjectExecReturn("Second length of pad too small"); App::DocumentObject* link = Sketch.getValue(); if (!link) @@ -178,7 +179,7 @@ App::DocumentObjectExecReturn *Pad::execute(void) it_near = it; upToFace = (std::string(Type.getValueAsString()) == "UpToLast" ? it_far->face : it_near->face); } else { - if (FaceName.getValue() == "") + if (FaceName.isEmpty()) return new App::DocumentObjectExecReturn("Cannot extrude up to face: No face selected"); // Get active object, this is the object that the user referenced when he clicked on the face! diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp index c7f4fa8ace..b6aec7dcdd 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.cpp +++ b/src/Mod/PartDesign/App/FeaturePocket.cpp @@ -27,6 +27,7 @@ # include # include # include +# include # include # include # include diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index d671fbe46e..c69df762fc 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -338,10 +338,11 @@ CmdPartDesignGroove::CmdPartDesignGroove() sAppModule = "PartDesign"; sGroup = QT_TR_NOOP("PartDesign"); sMenuText = QT_TR_NOOP("Groove"); - sToolTipText = QT_TR_NOOP("Revolve a selected sketch"); + sToolTipText = QT_TR_NOOP("Groove a selected sketch"); sWhatsThis = sToolTipText; sStatusTip = sToolTipText; - sPixmap = "PartDesign_Groove"; + //sPixmap = "PartDesign_Groove"; + sPixmap = "PartDesign_Revolution"; } void CmdPartDesignGroove::activated(int iMsg) From 85342cd8ae1eae7673717a3295948178a869038e Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Fri, 8 Jun 2012 20:00:44 +0430 Subject: [PATCH 340/351] Pocket Feature: up to first/last/face and through all options --- data/tests/PocketTest.fcstd | Bin 0 -> 13766 bytes src/Mod/PartDesign/App/FeaturePocket.cpp | 174 ++++++++++++++---- src/Mod/PartDesign/App/FeaturePocket.h | 1 + .../PartDesign/Gui/TaskPocketParameters.cpp | 102 +++++++++- src/Mod/PartDesign/Gui/TaskPocketParameters.h | 7 +- .../PartDesign/Gui/TaskPocketParameters.ui | 120 ++++++++---- 6 files changed, 329 insertions(+), 75 deletions(-) create mode 100644 data/tests/PocketTest.fcstd diff --git a/data/tests/PocketTest.fcstd b/data/tests/PocketTest.fcstd new file mode 100644 index 0000000000000000000000000000000000000000..6acf91ba055c2b8fd6614aecde44c161b3f5d616 GIT binary patch literal 13766 zcmbWeb8u%{_wF0x8{4*R+qP}nwrx8dJL%X?$F`G>JMQTAe$V}#ckf+wZ=E`G{jsXn zTAx|7MvaWukSj;n2jW%Qkz=WCf{SrRhitf&+7@eMFx8iRBqLIeIJuyKQMrl zNUyZ6McFpwggFXgu!k&30FI% zH+b3Ienh*0FFD)?^qWL}(GAn8EEP48&Z_fDXruP)=|PVmZwb8@4Hbl zBuOAq%DA$P!cvkVX4jhrP#;iz$7OiR70|^T@;bCn!waLo*V1u)xRPOOw3E#^<4b>% zt6q@QaG9qh-Q4nNwc_#S7&j9M|3+VOJ9j6O^5DeTN3_zm<$IubCrKoCsrt6K-=UnX ztOu560kK#AHalGY?MXsCXq9}j7sv}}6G^t>uKp!W$QbLO6F8cU&t679_b_lLanA3y zU(+x#X)Rq;KnCA|IljvJQA7+mH$FXeEs%vQ%bwk3565MZLY^NYN0x!zUd+a7#Jql3 z-8Edu13imj)b z*31XoTrE!MTvYaZ_M4HaCgSFEZgo)U&|>#EjsSnB&XK}T3CPMW}2C`X-a@9 z7-9j6F0tAcW-aRfdz!r5w0UhTa85rX)xhlM+Y!l98;m}6$yR(ZIpP)GZ>MoN)j!ShkP*g93*xCyXBAb_7GZ{C%7uReN$SL3B^ z5daxQVxVND#(_npTVL1}Y9q87YwNr^hy!=9)NF^_mWV9qpOwM$@xiAih43_m?neb} z5mn1|-_)2=N&Wp2lTHl20`5Vzq*c3|RmGdw zmgI(-Y9>S@6gC02XpMMb6<3WbFg9sr$)W{6SqHgQhCjZJe1$lL>GCo8H)0xtWi@?#i#cA z^Fkbdk{s519s_@}LWezQ$nz}5ukxsBSp!EQQLDyB9&RD&jury4bD1) z3=0!gFSVh0Fc$;eFmh(sJIMZRx_(AG#W3)+=xPC-^-Dcg@}w)d^Jb*;nYx-qO+{s_ zyvz#ylB8#qkbI-!tw&#-i?(~)b;Um$hvEpOqS<)f0z0NDI8(j5KvVa~?JknTD!T?V zx=DE}HyOZY3H`m5R)ona^(F)k0q=tUz_@GuMaV1K6a>kGjl9D%VQi zgddz`s4Y38cTV375+vKo%`J>DHY<4B=!V9Sb2I`Cf z)d#NXx1dJt3X)#&pH}?a^C!X%CiI?@URh@vbXZsDrs?u}RoeA@9T_O19Jb0q0f$Pz z1cL|l4|js+w=BmrwW{7`6?kUtAig#-!d>qn-Wpf!4eOQrh-ZSn2I5`cAv(k3Y>^xE zj`kJRCCd46$E4mvN}-7lDc2TcQ^+n)wWW2>Jua!&0N$G(hX>)wwO1X$oxw8JgI7Ta zYfkNnb`F!}_E_29tZz9co|ag~vg@5rpIWk-SarD+nx`eh5DUI{uEk8BWG6?OCv`!dShqD zva|vFO-9)88(#q4swY5ny=l<|#^@?`DcQFI?zx!Hy2mU-u($bhfc)(?oLN9779KV zuUo1SZolumu=M1nf`g&?GU8IB#JjPQ`^@ z2t}z(LQ%xG3@Dw(2%Y90fJeDaQroe3_kt@mm512o^g|6p*XD04w zfEkA;r^EGJWYWmEZIePz3VqPn*pA`tY`uKYIdpYoeL>4FLTZ5B%abEzmnZjWD-L z7K##;>y;~&=u7Gor8{l6p9 z;NC63%b8v>LK@5ubr9TZ4AW+d5_BFkhiX~Xf9%yhkAh1@CQ9lRBeMN+;RZ z5DJ9NW!B(8;OR0mS>@oX^&7Pvd0XCiv!#14p6gPzWO8Ra6&YN0#*mPdRg|f|h3du* zWQEdMS?D#b#hz z%lB^u9x=>7XgRbz$k+pq;~7P6P&4$0Hu1m^09x0D*(SRt6oKApy#FDfHHqagMXmy#-;P zu^SKJ9mx-ds8Np;FLAVqaq6)=*C^{MN_~wFcim`j2Dpx=Eph@dw1B~4wKfHCmKk-lC4(EmdFIRn`JaOr)&VT=l~;Bg6NAvrxHIk z3kLPFZtBg;jUEAYg(066)lw1I?3w+XC@7PL zqh7QT^4GqzBiEOgNPE|Stp>V4vHvSf8QKmLvf*8s(h|bYWr`9$6ka{>fcuG5bc)p5 zwD$pl0{-{U>+=#nK}d_=Zv+IpynO<`zR!&8w1*Jbdb?aFVp>a}-+PRy#phXG3auVzOC8 z9d|g%he4+J+LG@iPi$FNjzF^;sp+m%TINFp3m1ez;Fj8?Y#{F=<}TVUdD)28T_@kM zhEM3VN;zL_m_1?j#aDA!2fZ(%yzvwmaFLI&@iAi&w zOz3mvgE{UZ)dgB0Lphc6_2_h(42NiExOddX&damsXcCU1M+C45vY)xzC^0GZxT<@| zcFM1&u+J^it9f|NEwIgR#|!s`x!PSCn0xK?Mo1E;GXq|7GO5HzPUiC?G*{6n;ZTtN zZ1wRaU`}vBoMXe-wae%&YK^3&^NcUF^Zc zDRrP>Ej-wBnMHz6tb3?Al?~uxjfD`@_q6QNq)Or794oA>DD;^0?(&h9p_$w0R35%5 zurNuk9gB&9C&Z6?n{BUo4Z5f1u z(FN96y4I4ONVzzn$j~X;Vzd<$`>>eM3oegW6dNI{BGFu!r<{qt)FKZ4Fxbc5n}TC& zKf5E=s$m)zFI%~=nXg=m<4D?-G*Urpemq{`a480*p+QzjAt4RJ#JY&2(V5wnc`xOr zkTJtmWsU1F*xC>c4?2w)#RHw{9xv5dZr4axau$F$Fyiv#A!zOn?1lNzFyOV^N;>=p z%&!@AQ+c77CmR-0%gcDWc4Ta4*yE98?YU{FdnWHlJ~Lb%mLOt2M#@PQe(R~++E6p` zao#dqo|GVE@*rVv^*Px>#{<_?3y;bo8OsJ^h`5p=WXlsBt~diL&4gXdKu!A?r)uOC z-72PiQ68ifmV_pgcpQ0{o?=>I`lsQn)u?&4KvrbU5dz$8Ra5yB^J_&;ER)Jy0}uyj2@+5! ziRNj|mvy*EO&X}dCMgD{9&|xuomwEUaN1lS>{(clArLnpuz8xg@Rn5QFgEBL^dhJ? z5JjrgLLxbuKrrkVz8)VCsH8HGNa{)yEeTp`;EmkUQXU^NK?-v@pU^UfNs`PKdks-Z z>lQ;w;dW0A!YuivYr)@PNT` zS>nLNQkpN z^HA9V?A$Usi0jo3h%0U7Q<%3y7U=^u|HT@Y@T3`i9G%BQEyf`BM1zM$DsuMx zE#9R_o%%(5#yA(;4TYPWek>*kdY*?~#3}~U6fE1=K&ybhI{7A^=>wuU;B@vs24^)d1C{F;c16dXr?>;Zn_Th%uex1S3+5dvTLclUh+`5s@JAE$?hIR)+o z1QGj>9uE2e&$k~hPv`fGV-?SRu>zF>aRHvsV|NZ+46{6U4R1|vuR~K26$(QJ1v^*0 zdl?x@>q2mcml87!5?p=g%WV7wF#Q-y>|iBnPd_NB%KT6#HI%jK(y&^w-GWq`#1cxd z!?2HUt_IW(R1a77LODV=ys?ZGm8uip{S3KjT!klqC~}fO%+WPY9NpgI8fp38A@n&h zKI2ks(eCgx3X-Ez_Zay&3HR66p}%>r`O$jpFz`Vlm?72o@qfKn2KZuy;5+6a=c2UZ#@xde7oGp@vD`3#~_re?(#*4%!A*k!m-s%A(=Oc?BW4 zQ(l9NsZᦼtE8*hggt3Jh9hHn$wfCOYY8^9hq8CUpQvfhHn5p>3uOuH3{M5!Iv zqNf>9_392pBAoE)!Z?yqb!js~*k;{$DzygZOQZ?mpA)`_cp#_IN zbg@_V-d;YjTGgtHHDtj)s``t;|>m(XB&1se414TB;UtBt!r{u3P! za+)-HHsi74!glT|)H!OUR=Ejfjg2g}TSvdrUo{PDcXaJ|4Mq5t^3?lQ=Vq+=OUtOk zbQtAe+UBV&O{wGwitCd&ayPRfndG%b#vGNoRn~q_<2>Jz!kbN42ifgip7+o|>94{H z3IYG~wcT?J@R_mO7@_4((qFA3O=ynCS|NmzwdE}EhT&@Wyerx`%l8pL%)^;5jfYlvnoMSsDMcZ?1H%lws@5ResBhlj3##aBC=m#!OGl&RE! z7wOkgfqeeYU!UhGUj0utzdvpYcK8F<{Jg&&4_gk?hjQv?zqWfoR~I{df-WeMC$d(; zIpRJH7xa%52%Ll}aikD`4eWu}nb;p{tJujSl$lpWa;#>Hfv*SKz!r8jgd}NBdmV~_gl_DYE#Tgk1+wz4<5siy4$|}<@bB@^Oak8Il9)!n*dz# z6`@6Hysiac+6<+M2yHK%fR16Ng?(pc@R{ufDP)4k%v#F#suW?^@)eopo^dM@LJq4i>#TmXwL}A_mxU2(%+ct|;uy6Zr43m5K*d4p&R7)n zj$9)#N@ys3$ttVy{7_O!(}rKI;{J`_(&l23u{MI)28JKxeNvnb@2;?EG4%tFC-lfP zS$*rlW6JNnrB;O6B{p4()xo)sz~FWtq2^E?p>NXXf*s;R%iv1!sT4Q)A(<6Hk~8+G zwbW2J!C|a-D+Xdwv^Iibf(E51d$7Y{cI)8GQ&FDE&Z z%II{lC?(3FBpe-Zl{Ce|93_D>N_+qvE2}ltH0Y95fuorq*v?R&mLv#!qNyw?Q6OO| zF`8FI7Jb~2eCl+~4h&UQBb3k*>sw?Rtq3^jSZ4|`@n%z(Jh9r8A)@JRnsStPlr|_v zVc&ZO0NOA$v|O|%t-BLc{FLxpGj+uyy@4@YO)hVZi(+P!L1y6$KH`Gjq|57|$a(;q zjKt;Fwm%}&4~1yfmbdUyX%PrD&2}(4%5KC-JAI{NLsPOkP`XWR zw}glv!8-Cg`)E;;7sF|4@a?*=d%o;Kz|_DXHq%x3pM<7W8gBH&4_5Kz_I)`VlxC!B zro$bCO3d=BZ*5>1YM4Mwk@}M2scpiP6~vo4Wya7sNY!P`s-`wEnxlXt!TNZ_sRtDz z@suqmNg$Ku$XYsAywXWD3IHL(#ZKTdPzAS^n3=(FiADGZ>6=+=HxjHeJ_TQZa zb3P*tt=|T|zy*)2=e`;}vb5xUDHDrjnjiA@u$W3kxXO*B&*QCP(*(Wg3BzX-T(I%f zW+B*Gg0_X|M8w+KBIPudG69HOM57hvYVk7^Y;|2O!;$O=OImccoo7ov2QbfUXZ_Kk z!f!kdbn~{49_*Gjma~1`zbU(1txs*ge`sn3Fe-u+|H;Z{0{lks-`w_sjKXdjgjf{( z9S-V*y6E@7#CemT^nf4;`ZGG@SgFds+pH%Pueq_M3@dOPj?Ph9PBE)x;X4$Vnt}9u zpW*>2SSKC(>2eNuC+(>joUm@ts&s+Ztb0JD`Ha(ImeT2Pvc%E{AWGRcq%~=nKG@Q3 z$YvBy7^r9R+Ed?JWdE02*~P> z>iiGAkmavdGfip0evlEi=Z(g9%kbM}DEoPml6?+4+;F@K1Xi_bYb7}Or@uU8N+8Ot z(h;TCEQ9;q3pzW2*hRp*1)BM;KMD}};kv1=tkaHdc9j-^;{bwZd-s?{pIs02`^wE! zovpQ}b-F)|R0K9AXXA?Hik5X|q_~h%_-WyN$w70ov2aIN;7{dS<-KAM;-Z6L)AZUY zx%>sm3!4IB80@5DI%HY*EB-Sz4{09L?`or@soHkTuQmuF;mE{o>Gvq5`mpJVlONGp zay9NGZNtI5&ik$3;4jMA!&13U7#_Rn{CalO#^_O|-LEnX!q1L>!k>Hq@vt^P^$R71 zttq=Tl_^z3&Hree$_o_g21bm5Gsf(91z)@Wgbj(M=p>s)zJl#qN@S&1aCxaff`uEk zA7>AIMkchLcsHsH;{?JKuQm8*unms~3z`2!*M)YZpYqwlz4hJF$6lhx2k`2R@dEmaRK!fz9H7kk0Pkk zlx>+*__0m;rUS(J;&vFRjb3;4UTF{Ow4maf;wJOuc&9d>V0)`981 zLYQvbW&9=sg4c8W8Tqlxj1^a^2Z()jv?bA&=pf;-%CX7dnQ}tRb$l>McuLf8b>~8q zGP97wODZ@EZ@RE1MIEyd_Iu&@;l~BkH-#Y42zYK7QQ=x16syqpD9N`y?2}%jVOy&N zU$n!6C7-QscYd0d+_^`F_+JX^B1QTh(U$JJJ+QxuGB=ipPO8?TO!ev{LDicGy;Qq| z=~oYA8Aj}(@kX6uKW)#^6r{rF>o^3@W8WG&(O_Gy;Xs>Pr8O#ObD_1kxjW92MaGi% z%3fi}Tc6e~m+=!n8s{;(I`F2`(&#b8Z0X$j?$<(xZwt2m1hppkjR{QhZJ_^(&`y#B z#ls}Ns4;auXT$usP^muFjmo;x{r05M<#THqj>F+c_w_zeKaFq81eF;CTSJwGNmK!Y z!%TK3&6Q@gpGi5(BscKbVQUYuHpypQ2S>!tvET}>gIK3Uc#asObU01psWeyij%Xgp zduA*xnZ!IS%JLmbbNebWmyJ{$Mb!4l=1TB1pKhFsG&8rA4D_sxSgb!^aDcEx7h}2p znYRYmuj+1lJG9l8{k&Ay?|u4}@i2TZ&TjqRuaC-UXm~^%yTHS{(!*>LqS&}}irk$X zdi5-a7Hhf$MdDoJ9mmJws|%4HL**Q@YtslXIXKIe5oUidvr z{DxhifT+nywTzEso|SSR21Fs{Ywl7Q6Swt1;#K5!xch-xkgGs|7{8!N{7UvO#6UWN z7!M2w#)YwqIr^qM+kv`_XU;6Ap+`XOb!wrUdF)H0RnXe?jqFx~p8P-rB%&BU`+s1! zwOe{)=S%f`K5=i78g$@z6I(evE3y-Rj4MrWe~6Pz~e9ZX966oq<-A6szU-p(^W$0 z#N&WY2&g0&x(_9!GUzh9Iul%FzOidR26W78eSX z=~a0Um&TegTqHr0$m5>ot<-xNbb|LS${n0J>Ca0_k&_fKxnzq7lS^PWP*E4T@@N8E zQ!pXrQJ3+riY=70G zL=kTnA=DL#9vjo5#m>;-Pje9{i}SlfM^^1Qx)8$p4Y&5lMO2PHc$^pJVJV3h#Rhy`T}^q^6YTgu z-_3YN%U|jL5%O;$G%DF2{Ho%_E8K{$Q6_8`8=M@fwGd-T^&{_jB@=45)ZgugD%sJ?9*v&l=;C81q>{I*ga!<_TRG{*1INoc-mIr%HO58}POus#R%GH>R z^1CyaFW3&U&G-;5Sblou$Y>|KP#11~Uii%W#7d+&Kcs|P*n){l=<1{T zQ(OM9;o*DS#E^Kl`Fjg4`m;pM%g4xd&gw`hE6B+aCvZqVC#37h6VTnrwE}|Thtl#$ zWwiINw5votJ#(GMe5S`u4o#f2cL}_*>FzU9cKD4}xANhw)Jz=_i(j~xdErHiOQkJ$ z3$ofI9^>GVN@6zeU0n9#W38^zIidXUm*hP&5cviEx=`Zo zX$OJb{W95g-E>c!p}|kQ@^%M=QRMLwqb))xO)Q6^rfbF)NpTqxB4ch=Nw#~A8cAzZ z=4^SMDDdm7xD?`O^u+k}33W`MAm8St3_BKrrDS#BOblhTcnhDk9P`_(Y&5fDHyt^1 zyT&9e5k(xJ#X(!kjLO+;iOsZSTC#POk1922;`02M1w}kPvy2l*4dqJqPqk6(+@OhR z(!wn`#4pr$63=L&nKfGkvFh=P=Peb%QAg*dSht0fKfrpb{R7ph0oDUE{q zy_}A9!nuRKP|`OR(Xxn^*D+*WvJ(B;6fkgvc$5eSs(y9wGVU7WuwB zUI6ji)dT9?i7+oC7p&JQ*$M-~usZlC7sXzh0_rl$l`7K$37K1X5L3ky37#{-6?naZ zw55eknP7K&v>GW-Aw1rMlLV2;*8-8CLNo&u2@Ef9h&E6c!Gw5%m(FRImYbWoH7W|7 z(bGS-mvg`}V$7zMl*tDbV!o5sYcCFko0@SU5I24A{5|tA;QQNlnj}B@;9t$ zxB09gp_(NsSRMiN4tJuQ878s@c~Z%Cbf{x+&xXcKq41PT5)C%=gh?rG{1fN) z?ZW{jhV62dnQWabpj=>7{uf`}1f_MdE`sM{#OKufk_+pjFM&hoe88)Uqg8a?JM)QA zAzMZxN_z6hkDz|Gn2bB#9nB4sLKQc$U)Z3DswQFgC>P{TGn9;`vaRIQnD4@>5+hMY z7T^>o6UgMKVl}>~c{a;-D`*v!z>(Zvia({{pYnjtfJaZ(1G7^L39Q1@d$v|!;6p|IsH$GnI zve@DBV<5FjC93m;O1xX!Bq!LY*269_z|Pqq`wT-5=;GVj1z>#A2G06@7o1|Wa)_8e zkwfv$O5!gT+PvUoi-WpI)FRY_3Ci|?{fQ;D;gYbQjiei8E#ASm96LVfR)&ydN*>h$ zI}0hHDa^%|Qc6Q6wmYAIsNS^EUPVXxZPpM3c_K{wT=0C4lT~_Ka*!2ETBaGj6t4b? zD&osea@dMGmo`1aO+nsu6o(q2d-zMc(JW^_@x2gNF$qpRoFN6!9;X{AExT}VwvjA7 z!FbV5kbT3SI2nZxIQo?rdJM_DI=fqMDWE85F^xAFmBoRl*xfI$M1_a3Oc+%m&oVkb zotkNn^aZ-=N%t(wL|fxv-%c6^e+>B@V=H9~M$Gg|pR{Jn`Mcu2;$}QZMYqV{=$V)e zRuqD54Roq@@G!ta5E!6*6uVUba@!(5wLMo!e7VOI87MT3;w9?^E1 zmGX_S=qf8pdTs((o?(lQv{zWzIFE2vCVqtJ$`^!)j|3j-%w-+Ip!}BsV!@j;aE6n+ zrSyzSiji`d_(rf&ap-h6q?)^V2v}s4{34}QMF@3hmXb3?Wl7PvPbtET+{h&L6hG@m z>@9v>bI#6?*F|QW;UyM52zT;>7kZd%S#Tz38XvrK1iUrz&A=hc&A{(_|L=^aCU)X! zP^$y z--f)>nqdry(e71;+1(8@DxY;C?cGt643AVF`p1>Vreks2qqo`c9oEN>zvPM@e+XMx zGF4jypqck`;9Po1e}WSnBQwa9K(gNjm!b1`iJf~Of;uD;;0Jok!y=?9GK1Z?wj+s9 zxKQ3Y1<#uL?15B6se$)4{X#LmJ$N%liTRz3So46A<*s~CA&s0~a2sQMJD_CA?KsV& zxv&Qe9b0Am0CeU>|E-bmeTGX-zF@*vftTQ8@4^?xPxkD%@1K8{WaBqVPGCSl2XsI{ z2!E_U5^h%iFluXWyBx41288z+Uu1Nn9y-WEIE(CEm*<&I;#&P)Q;LmbV@sAmKe9ai zeAdB{B@7!rftt~~!ieovuTInG)BE7Q;a4EZRLNo-=&~rc&jmgX!esH^<;(ddH6-BU zp>*@UWVy5-QrfbM(=Q0tOm+OzLXt8}@!L!Hdaj`v384ue5)0N`RN}MhsVZ>qfT|=Q z_V6N=GPU%=yJx=N>AuJiHPltwUIS%b_NrL_VvG4VW2*6wQC0Xz;yDbKy3XvB6?+X( z3YCpz@c<>XP%XFG5IqxWv=XVEdF?0P8l9TokLJ=~!4%TSqiV%L+QXc>4DqwG8bh@7 zVUge4?dS9IaFrgLu4U8Ar|V|=LiGfmj1=49CKzU6^3zN zVtR=5=F?87s)d9RUTWYcq098S5O1JE z^(?$zH~XA#(wf({%A7kGE-j{yB1T3sFaNQU_Ub+heu^eo?g5JsV@s?zFeOuxcN~4~ zsSq!l`V$hT`qpvQ9FLUqex2c^)kKFY<+YF1rTkTYSK|!G1)ljnQk+%s$UebG0I-4? zM*7JfVZ_t6X}_LthxT}xHN9wC7B`Xhh^Zhrro=l+iHdMubRTW8A?Ll2nxO;==k7y_{_IVVhypKY^ z($Kf|{>jkS$@b%lv-ehC%TLgTDK|vGQWajOw{vn&MbafDo-#FVJ#eutX-96 z*{W%WwAbwuGIajs&zP9EtDN^#K<+}wo8)U6nAA9R*)9>kHAVJ8MD+$KY{4+Nm; zBuQMDDBKFp(egQ*_up@4C$s)HzdtJQSH_5qsH{-1+p0IquU-saJI}T14h5%{`ReU7 z(b-X%kDJWE6f6mwYwU>fYR%gE=k%J*uJ{<%8=$_t18_!9q|DEWWSkXV_UySbQ&IM_Nko0tLxvsnE2<9Gds8}{$WUv5~@ zzadQj7Yy_N1;g?;1{eet^#A)%%%27RXS4+Ub^H6yt0?nN^4~7s|HT0TwFFuH@%{e8 z^ZRe~-}cV`qSb$b`@hlum_7f^{@YdXU)B-jZ|r|O2LERNEffEj-NgGF`ybKx-|W9t z&;PQL1b<`yqk;aL{dZ0KFI)bn%KfXt{Tu#!{`_@p>3>E`kSOy%v+4hj{44YRXS4)) z{EKAzKS!(og);x2qr3k?Srlc!A^utv%%3ank93dn$0>pcB<^fxCL$zC_&>?_{{S(} B3F80& literal 0 HcmV?d00001 diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp index b6aec7dcdd..a0ef1cdd4b 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.cpp +++ b/src/Mod/PartDesign/App/FeaturePocket.cpp @@ -41,17 +41,20 @@ # include # include # include +# include +# include #endif #include #include +#include #include "FeaturePocket.h" using namespace PartDesign; -const char* Pocket::TypeEnums[]= {"Length","UpToLast","UpToFirst",NULL}; +const char* Pocket::TypeEnums[]= {"Length","UpToLast","UpToFirst","ThroughAll","UpToFace",NULL}; PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::SketchBased) @@ -60,13 +63,15 @@ Pocket::Pocket() ADD_PROPERTY(Type,((long)0)); Type.setEnums(TypeEnums); ADD_PROPERTY(Length,(100.0)); + ADD_PROPERTY(FaceName,("")); } short Pocket::mustExecute() const { if (Placement.isTouched() || Sketch.isTouched() || - Length.isTouched()) + Length.isTouched() || + FaceName.isTouched()) return 1; return 0; } @@ -114,13 +119,22 @@ App::DocumentObjectExecReturn *Pocket::execute(void) if (!SupportObject) return new App::DocumentObjectExecReturn("No support in Sketch!"); + const TopoDS_Shape& support = SupportObject->Shape.getValue(); + if (support.IsNull()) + return new App::DocumentObjectExecReturn("Support shape is invalid"); + TopExp_Explorer xp (support, TopAbs_SOLID); + if (!xp.More()) + return new App::DocumentObjectExecReturn("Support shape is not a solid"); + TopoDS_Shape aFace = makeFace(wires); if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // This is a trick to avoid problems with the cut operation. Sometimes a cut doesn't - // work as expected if faces or coincident. Thus, we move the face in normal direction + // work as expected if faces are coincident. Thus, we move the face in normal direction // but make it longer by one unit in the opposite direction. + // TODO: Isn't one unit (one millimeter) a lot, assuming someone models a really tiny solid? + // What about using 2 * Precision::Confusion() ? gp_Trsf mov; mov.SetTranslation(gp_Vec(SketchVector.x,SketchVector.y,SketchVector.z)); TopLoc_Location loc(mov); @@ -135,39 +149,133 @@ App::DocumentObjectExecReturn *Pocket::execute(void) this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); - // extrude the face to a solid - gp_Vec vec(SketchVector.x,SketchVector.y,SketchVector.z); - vec.Transform(invObjLoc.Transformation()); - BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),vec,0,1); - if (PrismMaker.IsDone()) { - // if the sketch has a support fuse them to get one result object (PAD!) - if (SupportObject) { - const TopoDS_Shape& support = SupportObject->Shape.getValue(); - if (support.IsNull()) - return new App::DocumentObjectExecReturn("Support shape is invalid"); - TopExp_Explorer xp (support, TopAbs_SOLID); - if (!xp.More()) - return new App::DocumentObjectExecReturn("Support shape is not a solid"); - // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Cut mkCut(support.Moved(invObjLoc), PrismMaker.Shape()); - // Let's check if the fusion has been successful - if (!mkCut.IsDone()) - return new App::DocumentObjectExecReturn("Cut with support failed"); + try { + // extrude the face to a solid + TopoDS_Shape prism; - // we have to get the solids (fuse create seldomly compounds) - TopoDS_Shape solRes = this->getSolid(mkCut.Shape()); - if (solRes.IsNull()) - return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); + if ((std::string(Type.getValueAsString()) == "UpToLast") || + (std::string(Type.getValueAsString()) == "UpToFirst") || + (std::string(Type.getValueAsString()) == "UpToFace")) + { + TopoDS_Face upToFace; + gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); - this->Shape.setValue(solRes); - } - else { - return new App::DocumentObjectExecReturn("Cannot create a tool out of sketch with no support"); + if ((std::string(Type.getValueAsString()) == "UpToLast") || + (std::string(Type.getValueAsString()) == "UpToFirst")) + { + TopoDS_Shape origFace = makeFace(wires); // original sketch face before moving one unit + std::vector cfaces = Part::findAllFacesCutBy(support, origFace, dir); + if (cfaces.empty()) + return new App::DocumentObjectExecReturn("No faces found in this direction"); + + // Find nearest/furthest face + std::vector::const_iterator it, it_near, it_far; + it_near = it_far = cfaces.begin(); + for (it = cfaces.begin(); it != cfaces.end(); it++) + if (it->distsq > it_far->distsq) + it_far = it; + else if (it->distsq < it_near->distsq) + it_near = it; + upToFace = (std::string(Type.getValueAsString()) == "UpToLast" ? it_far->face : it_near->face); + } else { + if (FaceName.getValue() == "") + return new App::DocumentObjectExecReturn("Cannot extrude up to face: No face selected"); + + // Get active object, this is the object that the user referenced when he clicked on the face! + App::DocumentObject* baseLink = this->getDocument()->getActiveObject(); + + if (!baseLink) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: No object linked"); + if (!baseLink->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Linked object is not a Part object"); + Part::Feature *base = static_cast(baseLink); + const Part::TopoShape& baseShape = base->Shape.getShape(); + if (baseShape._Shape.IsNull()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Cannot work on invalid shape"); + + TopoDS_Shape sub = baseShape.getSubShape(FaceName.getValue()); + if (!sub.IsNull() && sub.ShapeType() == TopAbs_FACE) + upToFace = TopoDS::Face(sub); + else + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Selection is not a face"); + + // Find the origin of this face (i.e. a vertex or a edge in a sketch) + TopoDS_Shape origin = base->findOriginOf(sub); + + // Validate face + // TODO: This would also exclude faces that are valid but not cut by the line + // So for now we trust to the intelligence of the user when picking the face + /*std::vector cfaces = findAllFacesCutBy(upToFace, origFace, dir); + if (cfaces.empty()) + return new App::DocumentObjectExecReturn("No faces found in this direction");*/ + } + + // Create semi-infinite prism from sketch in direction dir + dir.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),dir,0,0,1); + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Could not extrude the sketch!"); + + // Cut off the prism at the face we found + // Grab any point from the sketch + TopExp_Explorer exp; + exp.Init(aFace, TopAbs_VERTEX); + if (!exp.More()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Sketch without points?"); + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current())); + + // Create a halfspace from the face, extending in direction of sketch plane + BRepPrimAPI_MakeHalfSpace mkHalfSpace(upToFace, aPnt); + if (!mkHalfSpace.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: HalfSpace creation failed"); + + // Find common material between halfspace and prism + BRepAlgoAPI_Common mkCommon(PrismMaker.Shape(), mkHalfSpace.Solid().Moved(invObjLoc)); + if (!mkCommon.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Common creation failed"); + + prism = this->getSolid(mkCommon.Shape()); + if (prism.IsNull()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Resulting shape is not a solid"); + } else if (std::string(Type.getValueAsString()) == "ThroughAll") { + gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); + dir.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),dir,1,0,1); // infinite prism (in both directions!) + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); + prism = PrismMaker.Shape(); + } else if (std::string(Type.getValueAsString()) == "Length") { + gp_Vec vec(SketchVector.x,SketchVector.y,SketchVector.z); + vec.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),vec,0,1); // finite prism + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); + prism = PrismMaker.Shape(); + } else { + return new App::DocumentObjectExecReturn("Internal error: Unknown type for Pocket feature"); } + + // TODO: Set the subtractive shape property for later usage in e.g. pattern + //this->SubShape.setValue(prism); // This crashes with "Illegal storage access". Why? + + // Cut out the pocket + BRepAlgoAPI_Cut mkCut(support.Moved(invObjLoc), prism); + + // Let's check if the fusion has been successful + if (!mkCut.IsDone()) + return new App::DocumentObjectExecReturn("Cut with support failed"); + + // we have to get the solids (fuse sometimes creates compounds) + TopoDS_Shape solRes = this->getSolid(mkCut.Shape()); + if (solRes.IsNull()) + return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); + + this->Shape.setValue(solRes); + + return App::DocumentObject::StdReturn; + } catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); } - else - return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); - - return App::DocumentObject::StdReturn; } diff --git a/src/Mod/PartDesign/App/FeaturePocket.h b/src/Mod/PartDesign/App/FeaturePocket.h index 7a7d579628..b9b47aa72d 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.h +++ b/src/Mod/PartDesign/App/FeaturePocket.h @@ -39,6 +39,7 @@ public: App::PropertyEnumeration Type; App::PropertyLength Length; + App::PropertyString FaceName; /** @name methods override feature */ //@{ diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp index 30618f6214..2122bafd1e 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp @@ -58,16 +58,39 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge connect(ui->doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onLengthChanged(double))); + connect(ui->changeMode, SIGNAL(currentIndexChanged(int)), + this, SLOT(onModeChanged(int))); + connect(ui->lineFaceName, SIGNAL(textEdited(QString)), + this, SLOT(onFaceName(QString))); this->groupLayout()->addWidget(proxy); PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); double l = pcPocket->Length.getValue(); + int index = pcPocket->Type.getValue(); // must extract value here, clear() kills it! + const char* upToFace = pcPocket->FaceName.getValue(); - ui->doubleSpinBox->setMaximum(INT_MAX); - ui->doubleSpinBox->setValue(l); - ui->doubleSpinBox->selectAll(); - QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); + ui->changeMode->clear(); + ui->changeMode->insertItem(0, tr("Dimension")); + ui->changeMode->insertItem(1, tr("To last")); + ui->changeMode->insertItem(2, tr("To first")); + ui->changeMode->insertItem(3, tr("Through all")); + ui->changeMode->insertItem(4, tr("Up to face")); + ui->changeMode->setCurrentIndex(index); + + if (index == 0) { // Only this option requires a numeric value + ui->doubleSpinBox->setMaximum(INT_MAX); + ui->doubleSpinBox->setValue(l); + ui->doubleSpinBox->selectAll(); + QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); + ui->lineFaceName->setEnabled(false); + } else if (index == 4) { // Only this option requires to select a face + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setText(upToFace == "" ? tr("No face selected") : tr(upToFace)); + } else { // Neither value nor face required + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setEnabled(false); + } //// check if the sketch has support //Sketcher::SketchObject *pcSketch; @@ -81,6 +104,25 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge //} } +void TaskPocketParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); + if (pcPocket->Type.getValue() != 4) // ignore user selections if mode is not upToFace + return; + + if (!msg.pSubName || msg.pSubName[0] == '\0') + return; + std::string element(msg.pSubName); + if (element.substr(0,4) != "Face") + return; + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + pcPocket->FaceName.setValue(element); + pcPocket->getDocument()->recomputeFeature(pcPocket); + ui->lineFaceName->setText(tr(element.c_str())); + } +} + void TaskPocketParameters::onLengthChanged(double len) { PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); @@ -88,11 +130,59 @@ void TaskPocketParameters::onLengthChanged(double len) pcPocket->getDocument()->recomputeFeature(pcPocket); } +void TaskPocketParameters::onModeChanged(int index) +{ + PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); + + switch (index) { + case 0: pcPocket->Type.setValue("Length"); break; + case 1: pcPocket->Type.setValue("UpToLast"); break; + case 2: pcPocket->Type.setValue("UpToFirst"); break; + case 3: pcPocket->Type.setValue("ThroughAll"); break; + case 4: pcPocket->Type.setValue("UpToFace"); break; + default: pcPocket->Type.setValue("Length"); + } + + if (index == 0) { + ui->doubleSpinBox->setEnabled(true); + ui->lineFaceName->setEnabled(false); + ui->doubleSpinBox->setValue(pcPocket->Length.getValue()); + } else if (index == 4) { + ui->lineFaceName->setEnabled(true); + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setText(tr(pcPocket->FaceName.getValue())); + } else { + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setEnabled(false); + } + + pcPocket->getDocument()->recomputeFeature(pcPocket); +} + +void TaskPocketParameters::onFaceName(const QString& text) +{ + if (text.left(4) != tr("Face")) + return; + + PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); + pcPocket->FaceName.setValue(text.toUtf8()); + pcPocket->getDocument()->recomputeFeature(pcPocket); +} + double TaskPocketParameters::getLength(void) const { return ui->doubleSpinBox->value(); } +int TaskPocketParameters::getMode(void) const +{ + return ui->changeMode->currentIndex(); +} + +const QString TaskPocketParameters::getFaceName(void) const +{ + return ui->lineFaceName->text(); +} TaskPocketParameters::~TaskPocketParameters() { @@ -145,6 +235,8 @@ bool TaskDlgPocketParameters::accept() //Gui::Command::openCommand("Pocket changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length = %f",name.c_str(),parameter->getLength()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Type = %u",name.c_str(),parameter->getMode()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.FaceName = \"%s\"",name.c_str(),parameter->getFaceName().toAscii().data()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); Gui::Command::commitCommand(); @@ -163,7 +255,7 @@ bool TaskDlgPocketParameters::reject() pcSupport = pcSketch->Support.getValue(); } - // role back the done things + // roll back the done things Gui::Command::abortCommand(); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.h b/src/Mod/PartDesign/Gui/TaskPocketParameters.h index 077a9ef0c9..bbb6bbb3fe 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.h @@ -44,7 +44,7 @@ namespace PartDesignGui { -class TaskPocketParameters : public Gui::TaskView::TaskBox +class TaskPocketParameters : public Gui::TaskView::TaskBox, public Gui::SelectionObserver { Q_OBJECT @@ -53,14 +53,19 @@ public: ~TaskPocketParameters(); double getLength(void) const; + int getMode(void) const; + const QString getFaceName(void) const; private Q_SLOTS: void onLengthChanged(double); + void onModeChanged(int); + void onFaceName(const QString& text); protected: void changeEvent(QEvent *e); private: + void onSelectionChanged(const Gui::SelectionChanges& msg); private: QWidget* proxy; diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui index 34c8979a17..4f313be764 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui @@ -6,49 +6,97 @@ 0 0 - 137 - 68 + 241 + 134 + + + 0 + 0 + + + + + 233 + 134 + + Form - - - - - + + + + 10 + 10 + 211 + 34 + + + + + + + Type + + + + + + - Type: + Dimension - - - - - - - Dimension - - - - - - - - - - - - Length - - - - - - - - - + + + + + + + + + 10 + 90 + 211 + 34 + + + + + + + Face + + + + + + + + + + + + 10 + 50 + 211 + 34 + + + + + + + Length + + + + + + + + From 58a02d24ae2ad93a6d8a7321d44a37fc88c105b7 Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Fri, 8 Jun 2012 20:07:18 +0430 Subject: [PATCH 341/351] Revolution feature: Midplane and Reversed options --- src/Mod/PartDesign/App/FeatureRevolution.cpp | 62 +++++++++++++------ src/Mod/PartDesign/App/FeatureRevolution.h | 4 +- .../Gui/TaskRevolutionParameters.cpp | 35 +++++++++++ .../PartDesign/Gui/TaskRevolutionParameters.h | 4 ++ .../Gui/TaskRevolutionParameters.ui | 23 ++++++- 5 files changed, 104 insertions(+), 24 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 317aa52d19..1a14783ae5 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -56,6 +56,8 @@ Revolution::Revolution() ADD_PROPERTY(Axis,(Base::Vector3f(0.0f,1.0f,0.0f))); ADD_PROPERTY(Angle,(360.0)); ADD_PROPERTY_TYPE(ReferenceAxis,(0),"Revolution",(App::PropertyType)(App::Prop_None),"Reference axis of revolution"); + ADD_PROPERTY(Midplane,(0)); + ADD_PROPERTY(Reversed, (0)); } short Revolution::mustExecute() const @@ -65,7 +67,8 @@ short Revolution::mustExecute() const ReferenceAxis.isTouched() || Axis.isTouched() || Base.isTouched() || - Angle.isTouched()) + Angle.isTouched() || + Midplane.isTouched()) return 1; return 0; } @@ -151,35 +154,54 @@ App::DocumentObjectExecReturn *Revolution::execute(void) if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); + // Rotate the face by half the angle to get revolution symmetric to sketch plane + if (Midplane.getValue()) { + gp_Trsf mov; + mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians(Angle.getValue()) * (-1.0) / 2.0); + TopLoc_Location loc(mov); + aFace.Move(loc); + } + this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); - // revolve the face to a solid - BRepPrimAPI_MakeRevol RevolMaker(aFace.Moved(invObjLoc), gp_Ax1(pnt, dir), Base::toRadians(Angle.getValue())); + // Reverse angle if selected + double angle = Base::toRadians(Angle.getValue()); + if (Reversed.getValue() && !Midplane.getValue()) + angle *= (-1.0); - if (RevolMaker.IsDone()) { - TopoDS_Shape result = RevolMaker.Shape(); - // if the sketch has a support fuse them to get one result object (PAD!) - if (SupportObject) { - const TopoDS_Shape& support = SupportObject->Shape.getValue(); - if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) { - // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result); - // Let's check if the fusion has been successful - if (!mkFuse.IsDone()) - throw Base::Exception("Fusion with support failed"); - result = mkFuse.Shape(); + try { + // revolve the face to a solid + BRepPrimAPI_MakeRevol RevolMaker(aFace.Moved(invObjLoc), gp_Ax1(pnt, dir), angle); + + if (RevolMaker.IsDone()) { + TopoDS_Shape result = RevolMaker.Shape(); + // if the sketch has a support fuse them to get one result object (PAD!) + if (SupportObject) { + const TopoDS_Shape& support = SupportObject->Shape.getValue(); + if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) { + // Let's call algorithm computing a fuse operation: + BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result); + // Let's check if the fusion has been successful + if (!mkFuse.IsDone()) + throw Base::Exception("Fusion with support failed"); + result = mkFuse.Shape(); + } } + + this->Shape.setValue(result); } + else + return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); - this->Shape.setValue(result); + return App::DocumentObject::StdReturn; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); } - else - return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); - - return App::DocumentObject::StdReturn; } } diff --git a/src/Mod/PartDesign/App/FeatureRevolution.h b/src/Mod/PartDesign/App/FeatureRevolution.h index 4d6677d545..ed11adc068 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.h +++ b/src/Mod/PartDesign/App/FeatureRevolution.h @@ -39,7 +39,9 @@ public: App::PropertyVector Base; App::PropertyVector Axis; - App::PropertyAngle Angle; + App::PropertyAngle Angle; + App::PropertyBool Midplane; + App::PropertyBool Reversed; /** if this property is set to a valid link, both Axis and Base properties * are calculated according to the linked line diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index 05b01058f1..f78134b743 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -60,11 +60,18 @@ TaskRevolutionParameters::TaskRevolutionParameters(ViewProviderRevolution *Revol this, SLOT(onAngleChanged(double))); connect(ui->axis, SIGNAL(activated(int)), this, SLOT(onAxisChanged(int))); + connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), + this, SLOT(onMidplane(bool))); + connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), + this, SLOT(onReversed(bool))); this->groupLayout()->addWidget(proxy); PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); double l = pcRevolution->Angle.getValue(); + bool mirrored = pcRevolution->Midplane.getValue(); + bool reversed = pcRevolution->Reversed.getValue(); + ui->doubleSpinBox->setValue(l); int count=pcRevolution->getSketchAxisCount(); @@ -95,6 +102,9 @@ TaskRevolutionParameters::TaskRevolutionParameters(ViewProviderRevolution *Revol ui->axis->setCurrentIndex(pos); + ui->checkBoxMidplane->setChecked(mirrored); + ui->checkBoxReversed->setChecked(reversed); + setFocus (); } @@ -126,6 +136,19 @@ void TaskRevolutionParameters::onAxisChanged(int num) pcRevolution->getDocument()->recomputeFeature(pcRevolution); } +void TaskRevolutionParameters::onMidplane(bool on) +{ + PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); + pcRevolution->Midplane.setValue(on); + pcRevolution->getDocument()->recomputeFeature(pcRevolution); +} + +void TaskRevolutionParameters::onReversed(bool on) +{ + PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); + pcRevolution->Reversed.setValue(on); + pcRevolution->getDocument()->recomputeFeature(pcRevolution); +} double TaskRevolutionParameters::getAngle(void) const { @@ -157,6 +180,16 @@ QString TaskRevolutionParameters::getReferenceAxis(void) const return buf; } +bool TaskRevolutionParameters::getMidplane(void) const +{ + return ui->checkBoxMidplane->isChecked(); +} + +bool TaskRevolutionParameters::getReversed(void) const +{ + return ui->checkBoxReversed->isChecked(); +} + TaskRevolutionParameters::~TaskRevolutionParameters() { delete ui; @@ -210,6 +243,8 @@ bool TaskDlgRevolutionParameters::accept() Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Angle = %f",name.c_str(),parameter->getAngle()); std::string axis = parameter->getReferenceAxis().toStdString(); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.ReferenceAxis = %s",name.c_str(),axis.c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Midplane = %i",name.c_str(),parameter->getMidplane()?1:0); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %i",name.c_str(),parameter->getReversed()?1:0); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); Gui::Command::commitCommand(); diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h index dcafbd6186..1d9eb71a86 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h @@ -54,10 +54,14 @@ public: QString getReferenceAxis(void) const; double getAngle(void) const; + bool getMidplane(void) const; + bool getReversed(void) const; private Q_SLOTS: void onAngleChanged(double); void onAxisChanged(int); + void onMidplane(bool); + void onReversed(bool); protected: void changeEvent(QEvent *e); diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui index a80c300fef..dac292f995 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui @@ -6,8 +6,8 @@ 0 0 - 182 - 68 + 278 + 158 @@ -54,7 +54,7 @@ 1 - -360.000000000000000 + 0.000000000000000 360.000000000000000 @@ -69,6 +69,23 @@ + + + + true + + + Symmetric to plane + + + + + + + Reversed + + + From 2e89e0015d0fc426cd264234d4243679d348d783 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 8 Jun 2012 21:33:37 +0200 Subject: [PATCH 342/351] Cleanup, add method getStrValue() --- src/App/PropertyStandard.h | 6 ++---- src/Mod/PartDesign/App/FeaturePad.cpp | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index bff973cb26..fc29893794 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -394,9 +394,6 @@ protected: const Constraints* _ConstStruct; }; - - - class AppExport PropertyFloatList: public PropertyLists { TYPESYSTEM_HEADER(); @@ -470,10 +467,11 @@ public: */ virtual ~PropertyString(); - void setValue(const char* sString); void setValue(const std::string &sString); const char* getValue(void) const; + const std::string& getStrValue(void) const + { return _cValue; } bool isEmpty(void){return _cValue.empty();} virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyStringItem"; } diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index c5791abcd7..8335668aeb 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -23,15 +23,12 @@ #include "PreCompiled.h" #ifndef _PreComp_ -//# include -//# include # include # include # include # include # include # include -//# include # include # include # include From 7144890c93c084fae8eedc4e7c595ce5bc0d05b5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Jun 2012 11:21:56 +0200 Subject: [PATCH 343/351] Add groove icon --- src/Mod/PartDesign/Gui/Command.cpp | 3 +- src/Mod/PartDesign/Gui/Resources/Makefile.am | 1 + .../PartDesign/Gui/Resources/PartDesign.qrc | 1 + .../Gui/Resources/icons/PartDesign_Groove.svg | 144 ++++++++++++++++++ 4 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Groove.svg diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index c69df762fc..335d6d5dd6 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -341,8 +341,7 @@ CmdPartDesignGroove::CmdPartDesignGroove() sToolTipText = QT_TR_NOOP("Groove a selected sketch"); sWhatsThis = sToolTipText; sStatusTip = sToolTipText; - //sPixmap = "PartDesign_Groove"; - sPixmap = "PartDesign_Revolution"; + sPixmap = "PartDesign_Groove"; } void CmdPartDesignGroove::activated(int iMsg) diff --git a/src/Mod/PartDesign/Gui/Resources/Makefile.am b/src/Mod/PartDesign/Gui/Resources/Makefile.am index 3320073356..79bee06393 100644 --- a/src/Mod/PartDesign/Gui/Resources/Makefile.am +++ b/src/Mod/PartDesign/Gui/Resources/Makefile.am @@ -37,6 +37,7 @@ EXTRA_DIST = \ translations/PartDesign_uk.ts \ translations/PartDesign_zh.qm \ translations/PartDesign_zh.ts \ + icons/PartDesign_Groove.svg \ icons/PartDesign_Pad.svg \ icons/PartDesign_Pocket.svg \ icons/PartDesign_Revolution.svg \ diff --git a/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc b/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc index caff25cabd..37804e4039 100644 --- a/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc +++ b/src/Mod/PartDesign/Gui/Resources/PartDesign.qrc @@ -1,5 +1,6 @@ + icons/PartDesign_Groove.svg icons/PartDesign_Pad.svg icons/PartDesign_Pocket.svg icons/PartDesign_Revolution.svg diff --git a/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Groove.svg b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Groove.svg new file mode 100644 index 0000000000..2c1ca60aa8 --- /dev/null +++ b/src/Mod/PartDesign/Gui/Resources/icons/PartDesign_Groove.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + From 0bf33b646694e28c3604d4dc118cfc7c6d09a267 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Jun 2012 11:50:02 +0200 Subject: [PATCH 344/351] 0000740: work bench initiation from in fcstd file --- src/Mod/Arch/ArchAxis.py | 3 ++- src/Mod/Arch/ArchBuilding.py | 1 + src/Mod/Arch/ArchCell.py | 1 + src/Mod/Arch/ArchFloor.py | 1 + src/Mod/Arch/ArchRoof.py | 3 ++- src/Mod/Arch/ArchSectionPlane.py | 1 + src/Mod/Arch/ArchSite.py | 1 + src/Mod/Arch/ArchStructure.py | 3 ++- src/Mod/Arch/ArchWall.py | 3 ++- src/Mod/Arch/ArchWindow.py | 3 ++- 10 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Mod/Arch/ArchAxis.py b/src/Mod/Arch/ArchAxis.py index d165e69eaf..a2ea310331 100644 --- a/src/Mod/Arch/ArchAxis.py +++ b/src/Mod/Arch/ArchAxis.py @@ -109,7 +109,8 @@ class _ViewProviderAxis: vobj.LineColor = (0.13,0.15,0.37) vobj.DrawStyle = "Dashdot" - def getIcon(self): + def getIcon(self): + import Arch_rc return ":/icons/Arch_Axis_Tree.svg" def claimChildren(self): diff --git a/src/Mod/Arch/ArchBuilding.py b/src/Mod/Arch/ArchBuilding.py index 0d6d5cc403..968165527a 100644 --- a/src/Mod/Arch/ArchBuilding.py +++ b/src/Mod/Arch/ArchBuilding.py @@ -86,6 +86,7 @@ class _ViewProviderBuilding(ArchFloor._ViewProviderFloor): ArchFloor._ViewProviderFloor.__init__(self,vobj) def getIcon(self): + import Arch_rc return ":/icons/Arch_Building_Tree.svg" FreeCADGui.addCommand('Arch_Building',_CommandBuilding()) diff --git a/src/Mod/Arch/ArchCell.py b/src/Mod/Arch/ArchCell.py index 8783602ccf..6c4527ce5c 100644 --- a/src/Mod/Arch/ArchCell.py +++ b/src/Mod/Arch/ArchCell.py @@ -121,6 +121,7 @@ class _ViewProviderCell(ArchComponent.ViewProviderComponent): self.Object = vobj.Object def getIcon(self): + import Arch_rc return ":/icons/Arch_Cell_Tree.svg" def updateData(self,obj,prop): diff --git a/src/Mod/Arch/ArchFloor.py b/src/Mod/Arch/ArchFloor.py index f7ccab17ae..be99561074 100644 --- a/src/Mod/Arch/ArchFloor.py +++ b/src/Mod/Arch/ArchFloor.py @@ -114,6 +114,7 @@ class _ViewProviderFloor: vobj.Proxy = self def getIcon(self): + import Arch_rc return ":/icons/Arch_Floor_Tree.svg" def attach(self,vobj): diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py index 4c8d6964c1..e85581e606 100644 --- a/src/Mod/Arch/ArchRoof.py +++ b/src/Mod/Arch/ArchRoof.py @@ -148,7 +148,8 @@ class _ViewProviderRoof(ArchComponent.ViewProviderComponent): def __init__(self,vobj): ArchComponent.ViewProviderComponent.__init__(self,vobj) - def getIcon(self): + def getIcon(self): + import Arch_rc return ":/icons/Arch_Roof_Tree.svg" FreeCADGui.addCommand('Arch_Roof',_CommandRoof()) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index aa1d8bb990..460d3a7d17 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -123,6 +123,7 @@ class _ViewProviderSectionPlane(ArchComponent.ViewProviderComponent): self.Object = vobj.Object def getIcon(self): + import Arch_rc return ":/icons/Arch_SectionPlane_Tree.svg" def claimChildren(self): diff --git a/src/Mod/Arch/ArchSite.py b/src/Mod/Arch/ArchSite.py index 69cfda8bab..f6c6e9acbb 100644 --- a/src/Mod/Arch/ArchSite.py +++ b/src/Mod/Arch/ArchSite.py @@ -89,6 +89,7 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor): ArchFloor._ViewProviderFloor.__init__(self,vobj) def getIcon(self): + import Arch_rc return ":/icons/Arch_Site_Tree.svg" diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py index d257c4d92f..1a9f51c071 100644 --- a/src/Mod/Arch/ArchStructure.py +++ b/src/Mod/Arch/ArchStructure.py @@ -193,7 +193,8 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent): def __init__(self,vobj): ArchComponent.ViewProviderComponent.__init__(self,vobj) - def getIcon(self): + def getIcon(self): + import Arch_rc return ":/icons/Arch_Structure_Tree.svg" FreeCADGui.addCommand('Arch_Structure',_CommandStructure()) diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py index 1d6f8e5e07..e8236af3fc 100644 --- a/src/Mod/Arch/ArchWall.py +++ b/src/Mod/Arch/ArchWall.py @@ -423,7 +423,8 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent): def __init__(self,vobj): ArchComponent.ViewProviderComponent.__init__(self,vobj) - def getIcon(self): + def getIcon(self): + import Arch_rc return ":/icons/Arch_Wall_Tree.svg" def getDisplayModes(self,vobj): diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 2f593257fb..ad9d493699 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -179,7 +179,8 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent): def __init__(self,vobj): ArchComponent.ViewProviderComponent.__init__(self,vobj) - def getIcon(self): + def getIcon(self): + import Arch_rc return ":/icons/Arch_Window_Tree.svg" def setEdit(self,vobj,mode): From 245cae03ef6c1f30a2a1c89d955c0a383fd22f29 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Jun 2012 13:50:33 +0200 Subject: [PATCH 345/351] 0000144: Add several tools to Part module --- src/Gui/SelectionObject.h | 6 +- src/Mod/Part/App/AppPart.cpp | 1 + src/Mod/Part/App/PartFeatures.cpp | 95 ++++++++++++ src/Mod/Part/App/PartFeatures.h | 23 +++ src/Mod/Part/Gui/CMakeLists.txt | 5 + src/Mod/Part/Gui/Command.cpp | 27 ++++ src/Mod/Part/Gui/TaskSweep.cpp | 243 ++++++++++++++++++++++++++++++ src/Mod/Part/Gui/TaskSweep.h | 81 ++++++++++ src/Mod/Part/Gui/TaskSweep.ui | 60 ++++++++ src/Mod/Part/Gui/Workbench.cpp | 2 +- 10 files changed, 539 insertions(+), 4 deletions(-) create mode 100644 src/Mod/Part/Gui/TaskSweep.cpp create mode 100644 src/Mod/Part/Gui/TaskSweep.h create mode 100644 src/Mod/Part/Gui/TaskSweep.ui diff --git a/src/Gui/SelectionObject.h b/src/Gui/SelectionObject.h index 784b89f27d..5c871594c6 100644 --- a/src/Gui/SelectionObject.h +++ b/src/Gui/SelectionObject.h @@ -55,11 +55,11 @@ public: /// are there any SubNames selected bool hasSubNames(void)const { return SubNames.size() != 0; } /// get the name of the Document of this SelctionObject - inline const char* getDocName(void) { return DocName.c_str(); } + inline const char* getDocName(void) const { return DocName.c_str(); } /// get the name of the Document Object of this SelectionObject - inline const char* getFeatName(void) { return FeatName.c_str(); } + inline const char* getFeatName(void) const { return FeatName.c_str(); } /// get the Type of the selcted Object - inline const char* getTypeName(void) { return TypeName.c_str(); } + inline const char* getTypeName(void) const { return TypeName.c_str(); } /// returns the selected DocumentObject or NULL if the object is already deleted const App::DocumentObject *getObject(void) const; diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 716597e2b1..4980b0be11 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -179,6 +179,7 @@ void PartExport initPart() Part::Part2DObjectPython ::init(); Part::RuledSurface ::init(); Part::Loft ::init(); + Part::Sweep ::init(); // Geometry types Part::Geometry ::init(); diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index 1f2088874e..c50c854bbe 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -196,3 +196,98 @@ App::DocumentObjectExecReturn *Loft::execute(void) return new App::DocumentObjectExecReturn(e->GetMessageString()); } } + +// ---------------------------------------------------------------------------- + +PROPERTY_SOURCE(Part::Sweep, Part::Feature) + +Sweep::Sweep() +{ + ADD_PROPERTY_TYPE(Sections,(0),"Sweep",App::Prop_None,"List of sections"); + Sections.setSize(0); + ADD_PROPERTY_TYPE(Spine,(0),"Sweep",App::Prop_None,"Path to sweep along"); + ADD_PROPERTY_TYPE(Solid,(false),"Sweep",App::Prop_None,"Create solid"); + ADD_PROPERTY_TYPE(Fresnet,(false),"Sweep",App::Prop_None,"Fresnet"); +} + +short Sweep::mustExecute() const +{ + if (Sections.isTouched()) + return 1; + if (Spine.isTouched()) + return 1; + if (Solid.isTouched()) + return 1; + if (Fresnet.isTouched()) + return 1; + return 0; +} + +void Sweep::onChanged(const App::Property* prop) +{ + Part::Feature::onChanged(prop); +} + +App::DocumentObjectExecReturn *Sweep::execute(void) +{ + if (Sections.getSize() == 0) + return new App::DocumentObjectExecReturn("No sections linked."); + App::DocumentObject* spine = Spine.getValue(); + if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) + return new App::DocumentObjectExecReturn("No shape linked."); + const std::vector& subedge = Spine.getSubValues(); + if (subedge.size() != 1) + return new App::DocumentObjectExecReturn("Not exactly one sub-shape linked."); + + TopoDS_Shape edge; + const Part::TopoShape& shape = static_cast(spine)->Shape.getValue(); + if (!shape._Shape.IsNull()) { + if (!subedge[0].empty()) { + edge = shape.getSubShape(subedge[0].c_str()); + } + else { + if (shape._Shape.ShapeType() == TopAbs_EDGE) + edge = shape._Shape; + else if (shape._Shape.ShapeType() == TopAbs_WIRE) + edge = shape._Shape; + } + } + + try { + TopTools_ListOfShape profiles; + const std::vector& shapes = Sections.getValues(); + std::vector::const_iterator it; + for (it = shapes.begin(); it != shapes.end(); ++it) { + if (!(*it)->isDerivedFrom(Part::Feature::getClassTypeId())) + return new App::DocumentObjectExecReturn("Linked object is not a shape."); + const TopoDS_Shape& shape = static_cast(*it)->Shape.getValue(); + if (shape.IsNull()) + return new App::DocumentObjectExecReturn("Linked shape is invalid."); + if (shape.ShapeType() == TopAbs_WIRE) { + profiles.Append(shape); + } + else if (shape.ShapeType() == TopAbs_EDGE) { + BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(shape)); + profiles.Append(mkWire.Wire()); + } + else if (shape.ShapeType() == TopAbs_VERTEX) { + profiles.Append(shape); + } + else { + return new App::DocumentObjectExecReturn("Linked shape is not a vertex, edge nor wire."); + } + } + + Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False; + Standard_Boolean isFresnet = Fresnet.getValue() ? Standard_True : Standard_False; + + BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(edge)); + TopoShape myShape(mkWire.Wire()); + this->Shape.setValue(myShape.makePipeShell(profiles, isSolid, isFresnet)); + return App::DocumentObject::StdReturn; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); + } +} diff --git a/src/Mod/Part/App/PartFeatures.h b/src/Mod/Part/App/PartFeatures.h index f01fde5752..25d2050a5b 100644 --- a/src/Mod/Part/App/PartFeatures.h +++ b/src/Mod/Part/App/PartFeatures.h @@ -73,6 +73,29 @@ protected: void onChanged (const App::Property* prop); }; +class Sweep : public Part::Feature +{ + PROPERTY_HEADER(Part::Sweep); + +public: + Sweep(); + + App::PropertyLinkList Sections; + App::PropertyLinkSub Spine; + App::PropertyBool Solid; + App::PropertyBool Fresnet; + + /** @name methods override feature */ + //@{ + /// recalculate the feature + App::DocumentObjectExecReturn *execute(void); + short mustExecute() const; + //@} + +protected: + void onChanged (const App::Property* prop); +}; + } //namespace Part diff --git a/src/Mod/Part/Gui/CMakeLists.txt b/src/Mod/Part/Gui/CMakeLists.txt index d9ff99f955..ec068eb957 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -41,6 +41,7 @@ set(PartGui_MOC_HDRS TaskFaceColors.h TaskShapeBuilder.h TaskLoft.h + TaskSweep.h ) fc_wrap_cpp(PartGui_MOC_SRCS ${PartGui_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${PartGui_MOC_SRCS}) @@ -65,6 +66,7 @@ set(PartGui_UIC_SRCS TaskFaceColors.ui TaskShapeBuilder.ui TaskLoft.ui + TaskSweep.ui ) qt4_wrap_ui(PartGui_UIC_HDRS ${PartGui_UIC_SRCS}) @@ -155,6 +157,9 @@ SET(PartGui_SRCS TaskLoft.cpp TaskLoft.h TaskLoft.ui + TaskSweep.cpp + TaskSweep.h + TaskSweep.ui ) SET(PartGui_Scripts diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 33cd008ee7..5020e48724 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -61,6 +61,7 @@ #include "ViewProvider.h" #include "TaskShapeBuilder.h" #include "TaskLoft.h" +#include "TaskSweep.h" //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -960,6 +961,31 @@ bool CmdPartLoft::isActive(void) //-------------------------------------------------------------------------------------- +DEF_STD_CMD_A(CmdPartSweep); + +CmdPartSweep::CmdPartSweep() + : Command("Part_Sweep") +{ + sAppModule = "Part"; + sGroup = QT_TR_NOOP("Part"); + sMenuText = QT_TR_NOOP("Sweep..."); + sToolTipText = QT_TR_NOOP("Advanced utility to sweep"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; +} + +void CmdPartSweep::activated(int iMsg) +{ + Gui::Control().showDialog(new PartGui::TaskSweep()); +} + +bool CmdPartSweep::isActive(void) +{ + return (hasActiveDocument() && !Gui::Control().activeDialog()); +} + +//-------------------------------------------------------------------------------------- + DEF_STD_CMD_A(CmdShapeInfo); CmdShapeInfo::CmdShapeInfo() @@ -1194,5 +1220,6 @@ void CreatePartCommands(void) rcCmdMgr.addCommand(new CmdPartRuledSurface()); rcCmdMgr.addCommand(new CmdPartBuilder()); rcCmdMgr.addCommand(new CmdPartLoft()); + rcCmdMgr.addCommand(new CmdPartSweep()); } diff --git a/src/Mod/Part/Gui/TaskSweep.cpp b/src/Mod/Part/Gui/TaskSweep.cpp new file mode 100644 index 0000000000..0639c28a23 --- /dev/null +++ b/src/Mod/Part/Gui/TaskSweep.cpp @@ -0,0 +1,243 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +#endif + +#include "ui_TaskSweep.h" +#include "TaskSweep.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +using namespace PartGui; + +class SweepWidget::Private +{ +public: + Ui_TaskSweep ui; + std::string document; + Private() + { + } + ~Private() + { + } +}; + +/* TRANSLATOR PartGui::SweepWidget */ + +SweepWidget::SweepWidget(QWidget* parent) + : d(new Private()) +{ + Gui::Application::Instance->runPythonCode("from FreeCAD import Base"); + Gui::Application::Instance->runPythonCode("import Part"); + + d->ui.setupUi(this); + d->ui.selector->setAvailableLabel(tr("Vertex/Wire")); + d->ui.selector->setSelectedLabel(tr("Sweep")); + + connect(d->ui.selector->availableTreeWidget(), SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + connect(d->ui.selector->selectedTreeWidget(), SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + + findShapes(); +} + +SweepWidget::~SweepWidget() +{ + delete d; +} + +void SweepWidget::findShapes() +{ + App::Document* activeDoc = App::GetApplication().getActiveDocument(); + Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc); + if (!activeGui) return; + d->document = activeDoc->getName(); + + std::vector objs = activeDoc->getObjectsOfType(); + + for (std::vector::iterator it = objs.begin(); it!=objs.end(); ++it) { + const TopoDS_Shape& shape = (*it)->Shape.getValue(); + if (shape.IsNull()) continue; + + if (shape.ShapeType() == TopAbs_WIRE || + shape.ShapeType() == TopAbs_EDGE || + shape.ShapeType() == TopAbs_VERTEX) { + QString label = QString::fromUtf8((*it)->Label.getValue()); + QString name = QString::fromAscii((*it)->getNameInDocument()); + + QTreeWidgetItem* child = new QTreeWidgetItem(); + child->setText(0, label); + child->setToolTip(0, label); + child->setData(0, Qt::UserRole, name); + Gui::ViewProvider* vp = activeGui->getViewProvider(*it); + if (vp) child->setIcon(0, vp->getIcon()); + d->ui.selector->availableTreeWidget()->addTopLevelItem(child); + } + } +} + +bool SweepWidget::accept() +{ + Gui::SelectionFilter edgeFilter ("SELECT Part::Feature SUBELEMENT Edge COUNT 1"); + if (!edgeFilter.match()) { + QMessageBox::critical(this, tr("Sweep path"), tr("Select an edge you want to sweep along.")); + return false; + } + + // get the selected object + const std::vector& result = edgeFilter.Result[0]; + const std::vector& edges = result[0].getSubNames(); + + QString list, solid, fresnet; + if (d->ui.checkSolid->isChecked()) + solid = QString::fromAscii("True"); + else + solid = QString::fromAscii("False"); + + if (d->ui.checkFresnet->isChecked()) + fresnet = QString::fromAscii("True"); + else + fresnet = QString::fromAscii("False"); + + QTextStream str(&list); + + int count = d->ui.selector->selectedTreeWidget()->topLevelItemCount(); + if (count < 1) { + QMessageBox::critical(this, tr("Too few elements"), tr("At least one edge or wire is required.")); + return false; + } + for (int i=0; iui.selector->selectedTreeWidget()->topLevelItem(i); + QString name = child->data(0, Qt::UserRole).toString(); + str << "App.getDocument('" << d->document.c_str() << "')." << name << ", "; + } + + try { + QString cmd; + cmd = QString::fromAscii( + "App.getDocument('%6').addObject('Part::Sweep','Sweep')\n" + "App.getDocument('%6').ActiveObject.Sections=[%1]\n" + "App.getDocument('%6').ActiveObject.Spine=(FreeCAD.ActiveDocument.%2,['%3'])\n" + "App.getDocument('%6').ActiveObject.Solid=%4\n" + "App.getDocument('%6').ActiveObject.Fresnet=%5\n" + ) + .arg(list).arg(QLatin1String(result.front().getFeatName())) + .arg(QLatin1String(edges.front().c_str())) + .arg(solid).arg(fresnet).arg(QString::fromAscii(d->document.c_str())); + + Gui::Document* doc = Gui::Application::Instance->getDocument(d->document.c_str()); + if (!doc) throw Base::Exception("Document doesn't exist anymore"); + doc->openCommand("Sweep"); + Gui::Application::Instance->runPythonCode((const char*)cmd.toAscii(), false, false); + doc->commitCommand(); + doc->getDocument()->recompute(); + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + return false; + } + + return true; +} + +bool SweepWidget::reject() +{ + return true; +} + +void SweepWidget::onCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous) +{ + if (previous) { + Gui::Selection().rmvSelection(d->document.c_str(), + (const char*)previous->data(0,Qt::UserRole).toByteArray()); + } + if (current) { + Gui::Selection().addSelection(d->document.c_str(), + (const char*)current->data(0,Qt::UserRole).toByteArray()); + } +} + +void SweepWidget::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + d->ui.retranslateUi(this); + d->ui.selector->setAvailableLabel(tr("Vertex/Wire")); + d->ui.selector->setSelectedLabel(tr("Sweep")); + } +} + + +/* TRANSLATOR PartGui::TaskSweep */ + +TaskSweep::TaskSweep() +{ + widget = new SweepWidget(); + taskbox = new Gui::TaskView::TaskBox( + QPixmap(), widget->windowTitle(), true, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); +} + +TaskSweep::~TaskSweep() +{ +} + +void TaskSweep::open() +{ +} + +void TaskSweep::clicked(int) +{ +} + +bool TaskSweep::accept() +{ + return widget->accept(); +} + +bool TaskSweep::reject() +{ + return widget->reject(); +} + +#include "moc_TaskSweep.cpp" diff --git a/src/Mod/Part/Gui/TaskSweep.h b/src/Mod/Part/Gui/TaskSweep.h new file mode 100644 index 0000000000..f0c6fc5921 --- /dev/null +++ b/src/Mod/Part/Gui/TaskSweep.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef PARTGUI_TASKSWEEP_H +#define PARTGUI_TASKSWEEP_H + +#include +#include + +class QTreeWidgetItem; + +namespace PartGui { + +class SweepWidget : public QWidget +{ + Q_OBJECT + +public: + SweepWidget(QWidget* parent = 0); + ~SweepWidget(); + + bool accept(); + bool reject(); + +private Q_SLOTS: + void onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*); + +private: + void changeEvent(QEvent *e); + void findShapes(); + +private: + class Private; + Private* d; +}; + +class TaskSweep : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskSweep(); + ~TaskSweep(); + +public: + void open(); + bool accept(); + bool reject(); + void clicked(int); + + QDialogButtonBox::StandardButtons getStandardButtons() const + { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } + +private: + SweepWidget* widget; + Gui::TaskView::TaskBox* taskbox; +}; + +} //namespace PartGui + +#endif // PARTGUI_TASKSWEEP_H diff --git a/src/Mod/Part/Gui/TaskSweep.ui b/src/Mod/Part/Gui/TaskSweep.ui new file mode 100644 index 0000000000..f91e754f53 --- /dev/null +++ b/src/Mod/Part/Gui/TaskSweep.ui @@ -0,0 +1,60 @@ + + + PartGui::TaskSweep + + + + 0 + 0 + 336 + 326 + + + + Sweep + + + + + + + + + Create solid + + + + + + + Qt::Horizontal + + + + 130 + 20 + + + + + + + + Fresnet + + + + + + + + Gui::ActionSelector + QWidget +

Gui/Widgets.h
+ + + + + + +
diff --git a/src/Mod/Part/Gui/Workbench.cpp b/src/Mod/Part/Gui/Workbench.cpp index ea42cb9f32..9997750b2f 100644 --- a/src/Mod/Part/Gui/Workbench.cpp +++ b/src/Mod/Part/Gui/Workbench.cpp @@ -72,7 +72,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Part_RefineShape" << "Separator" << "Part_Boolean" << "Part_CrossSections" << "Part_Extrude" << "Part_Revolve" << "Part_Mirror" << "Part_Fillet" << "Part_Chamfer" - << "Part_RuledSurface" << "Part_Loft" + << "Part_RuledSurface" << "Part_Loft" << "Part_Sweep" << "Part_Builder"; //Gui::MenuItem* partSimple = new Gui::MenuItem; From 2a7e6f3e96995bb1a7871b4574a96979f93f3a8b Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Jun 2012 15:55:11 +0200 Subject: [PATCH 346/351] 0000144: Add several tools to Part module --- src/Mod/Part/App/PartFeatures.cpp | 58 +++++++++++++++++++++++++------ src/Mod/Part/App/PartFeatures.h | 6 +++- src/Mod/Part/Gui/TaskSweep.cpp | 36 ++++++++++++------- src/Mod/Part/Gui/TaskSweep.ui | 4 +-- 4 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index c50c854bbe..1bf2ce8740 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -28,6 +28,8 @@ # include # include # include +# include +# include #endif @@ -199,6 +201,8 @@ App::DocumentObjectExecReturn *Loft::execute(void) // ---------------------------------------------------------------------------- +const char* Part::Sweep::TransitionEnums[]= {"Transformed","Right corner", "Round corner",NULL}; + PROPERTY_SOURCE(Part::Sweep, Part::Feature) Sweep::Sweep() @@ -207,7 +211,9 @@ Sweep::Sweep() Sections.setSize(0); ADD_PROPERTY_TYPE(Spine,(0),"Sweep",App::Prop_None,"Path to sweep along"); ADD_PROPERTY_TYPE(Solid,(false),"Sweep",App::Prop_None,"Create solid"); - ADD_PROPERTY_TYPE(Fresnet,(false),"Sweep",App::Prop_None,"Fresnet"); + ADD_PROPERTY_TYPE(Frenet,(false),"Sweep",App::Prop_None,"Frenet"); + ADD_PROPERTY_TYPE(Transition,(long(0)),"Sweep",App::Prop_None,"Transition mode"); + Transition.setEnums(TransitionEnums); } short Sweep::mustExecute() const @@ -218,7 +224,9 @@ short Sweep::mustExecute() const return 1; if (Solid.isTouched()) return 1; - if (Fresnet.isTouched()) + if (Frenet.isTouched()) + return 1; + if (Transition.isTouched()) return 1; return 0; } @@ -234,22 +242,24 @@ App::DocumentObjectExecReturn *Sweep::execute(void) return new App::DocumentObjectExecReturn("No sections linked."); App::DocumentObject* spine = Spine.getValue(); if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) - return new App::DocumentObjectExecReturn("No shape linked."); + return new App::DocumentObjectExecReturn("No spine linked."); const std::vector& subedge = Spine.getSubValues(); if (subedge.size() != 1) return new App::DocumentObjectExecReturn("Not exactly one sub-shape linked."); - TopoDS_Shape edge; + TopoDS_Shape path; const Part::TopoShape& shape = static_cast(spine)->Shape.getValue(); if (!shape._Shape.IsNull()) { if (!subedge[0].empty()) { - edge = shape.getSubShape(subedge[0].c_str()); + path = shape.getSubShape(subedge[0].c_str()); } else { if (shape._Shape.ShapeType() == TopAbs_EDGE) - edge = shape._Shape; + path = shape._Shape; else if (shape._Shape.ShapeType() == TopAbs_WIRE) - edge = shape._Shape; + path = shape._Shape; + else + return new App::DocumentObjectExecReturn("Spine is neither an edge nor a wire."); } } @@ -279,11 +289,37 @@ App::DocumentObjectExecReturn *Sweep::execute(void) } Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False; - Standard_Boolean isFresnet = Fresnet.getValue() ? Standard_True : Standard_False; + Standard_Boolean isFrenet = Frenet.getValue() ? Standard_True : Standard_False; + BRepBuilderAPI_TransitionMode transMode; + switch (Transition.getValue()) { + case 1: transMode = BRepBuilderAPI_RightCorner; + break; + case 2: transMode = BRepBuilderAPI_RoundCorner; + break; + default: transMode = BRepBuilderAPI_Transformed; + break; + } - BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(edge)); - TopoShape myShape(mkWire.Wire()); - this->Shape.setValue(myShape.makePipeShell(profiles, isSolid, isFresnet)); + if (path.ShapeType() == TopAbs_EDGE) { + BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(path)); + path = mkWire.Wire(); + } + + BRepOffsetAPI_MakePipeShell mkPipeShell(TopoDS::Wire(path)); + mkPipeShell.SetMode(isFrenet); + mkPipeShell.SetTransitionMode(transMode); + TopTools_ListIteratorOfListOfShape iter; + for (iter.Initialize(profiles); iter.More(); iter.Next()) { + mkPipeShell.Add(TopoDS_Shape(iter.Value())); + } + + if (!mkPipeShell.IsReady()) + Standard_Failure::Raise("shape is not ready to build"); + mkPipeShell.Build(); + if (isSolid) + mkPipeShell.MakeSolid(); + + this->Shape.setValue(mkPipeShell.Shape()); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { diff --git a/src/Mod/Part/App/PartFeatures.h b/src/Mod/Part/App/PartFeatures.h index 25d2050a5b..ddaae9627d 100644 --- a/src/Mod/Part/App/PartFeatures.h +++ b/src/Mod/Part/App/PartFeatures.h @@ -83,7 +83,8 @@ public: App::PropertyLinkList Sections; App::PropertyLinkSub Spine; App::PropertyBool Solid; - App::PropertyBool Fresnet; + App::PropertyBool Frenet; + App::PropertyEnumeration Transition; /** @name methods override feature */ //@{ @@ -94,6 +95,9 @@ public: protected: void onChanged (const App::Property* prop); + +private: + static const char* TransitionEnums[]; }; } //namespace Part diff --git a/src/Mod/Part/Gui/TaskSweep.cpp b/src/Mod/Part/Gui/TaskSweep.cpp index 0639c28a23..effd5c28b5 100644 --- a/src/Mod/Part/Gui/TaskSweep.cpp +++ b/src/Mod/Part/Gui/TaskSweep.cpp @@ -118,25 +118,37 @@ void SweepWidget::findShapes() bool SweepWidget::accept() { Gui::SelectionFilter edgeFilter ("SELECT Part::Feature SUBELEMENT Edge COUNT 1"); - if (!edgeFilter.match()) { - QMessageBox::critical(this, tr("Sweep path"), tr("Select an edge you want to sweep along.")); + Gui::SelectionFilter partFilter ("SELECT Part::Feature COUNT 1"); + bool matchEdge = edgeFilter.match(); + bool matchPart = partFilter.match(); + if (!matchEdge && !matchPart) { + QMessageBox::critical(this, tr("Sweep path"), tr("Select an edge or wire you want to sweep along.")); return false; } // get the selected object - const std::vector& result = edgeFilter.Result[0]; - const std::vector& edges = result[0].getSubNames(); + std::string objectName, subShape; + if (matchEdge) { + const std::vector& result = edgeFilter.Result[0]; + const std::vector& edges = result[0].getSubNames(); + objectName = result.front().getFeatName(); + subShape = edges.front(); + } + else { + const std::vector& result = partFilter.Result[0]; + objectName = result.front().getFeatName(); + } - QString list, solid, fresnet; + QString list, solid, frenet; if (d->ui.checkSolid->isChecked()) solid = QString::fromAscii("True"); else solid = QString::fromAscii("False"); - if (d->ui.checkFresnet->isChecked()) - fresnet = QString::fromAscii("True"); + if (d->ui.checkFrenet->isChecked()) + frenet = QString::fromAscii("True"); else - fresnet = QString::fromAscii("False"); + frenet = QString::fromAscii("False"); QTextStream str(&list); @@ -158,11 +170,11 @@ bool SweepWidget::accept() "App.getDocument('%6').ActiveObject.Sections=[%1]\n" "App.getDocument('%6').ActiveObject.Spine=(FreeCAD.ActiveDocument.%2,['%3'])\n" "App.getDocument('%6').ActiveObject.Solid=%4\n" - "App.getDocument('%6').ActiveObject.Fresnet=%5\n" + "App.getDocument('%6').ActiveObject.Frenet=%5\n" ) - .arg(list).arg(QLatin1String(result.front().getFeatName())) - .arg(QLatin1String(edges.front().c_str())) - .arg(solid).arg(fresnet).arg(QString::fromAscii(d->document.c_str())); + .arg(list).arg(QLatin1String(objectName.c_str())) + .arg(QLatin1String(subShape.c_str())) + .arg(solid).arg(frenet).arg(QString::fromAscii(d->document.c_str())); Gui::Document* doc = Gui::Application::Instance->getDocument(d->document.c_str()); if (!doc) throw Base::Exception("Document doesn't exist anymore"); diff --git a/src/Mod/Part/Gui/TaskSweep.ui b/src/Mod/Part/Gui/TaskSweep.ui index f91e754f53..8985963657 100644 --- a/src/Mod/Part/Gui/TaskSweep.ui +++ b/src/Mod/Part/Gui/TaskSweep.ui @@ -38,9 +38,9 @@ - + - Fresnet + Frenet From 6a2a72627635d9b72d24fa90312586e7967e6f8c Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Jun 2012 16:37:06 +0200 Subject: [PATCH 347/351] Fix bugs in Groove and Revolution --- src/Mod/PartDesign/App/FeatureGroove.cpp | 13 +++++++------ src/Mod/PartDesign/App/FeatureRevolution.cpp | 15 ++++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp index 1e7f7d6603..1cf17541d2 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.cpp +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -52,12 +52,12 @@ PROPERTY_SOURCE(PartDesign::Groove, PartDesign::SketchBased) Groove::Groove() { - ADD_PROPERTY(Base,(Base::Vector3f(0.0f,0.0f,0.0f))); - ADD_PROPERTY(Axis,(Base::Vector3f(0.0f,1.0f,0.0f))); - ADD_PROPERTY(Angle,(360.0)); + ADD_PROPERTY_TYPE(Base,(Base::Vector3f(0.0f,0.0f,0.0f)),"Groove", App::Prop_ReadOnly, "Base"); + ADD_PROPERTY_TYPE(Axis,(Base::Vector3f(0.0f,1.0f,0.0f)),"Groove", App::Prop_ReadOnly, "Axis"); + ADD_PROPERTY_TYPE(Angle,(360.0),"Groove", App::Prop_None, "Angle"); ADD_PROPERTY_TYPE(ReferenceAxis,(0),"Groove",(App::PropertyType)(App::Prop_None),"Reference axis of Groove"); - ADD_PROPERTY(Midplane,(0)); - ADD_PROPERTY(Reversed, (0)); + ADD_PROPERTY_TYPE(Midplane,(0),"Groove", App::Prop_None, "Mid plane"); + ADD_PROPERTY_TYPE(Reversed, (0),"Groove", App::Prop_None, "Reversed"); } short Groove::mustExecute() const @@ -68,7 +68,8 @@ short Groove::mustExecute() const Axis.isTouched() || Base.isTouched() || Angle.isTouched() || - Midplane.isTouched()) + Midplane.isTouched() || + Reversed.isTouched()) return 1; return 0; } diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 1a14783ae5..a31bebf439 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -52,12 +52,12 @@ PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::SketchBased) Revolution::Revolution() { - ADD_PROPERTY(Base,(Base::Vector3f(0.0f,0.0f,0.0f))); - ADD_PROPERTY(Axis,(Base::Vector3f(0.0f,1.0f,0.0f))); - ADD_PROPERTY(Angle,(360.0)); - ADD_PROPERTY_TYPE(ReferenceAxis,(0),"Revolution",(App::PropertyType)(App::Prop_None),"Reference axis of revolution"); - ADD_PROPERTY(Midplane,(0)); - ADD_PROPERTY(Reversed, (0)); + ADD_PROPERTY_TYPE(Base,(Base::Vector3f(0.0f,0.0f,0.0f)),"Revolution", App::Prop_ReadOnly, "Base"); + ADD_PROPERTY_TYPE(Axis,(Base::Vector3f(0.0f,1.0f,0.0f)),"Revolution", App::Prop_ReadOnly, "Axis"); + ADD_PROPERTY_TYPE(Angle,(360.0),"Revolution", App::Prop_None, "Angle"); + ADD_PROPERTY_TYPE(ReferenceAxis,(0),"Revolution",(App::Prop_None),"Reference axis of revolution"); + ADD_PROPERTY_TYPE(Midplane,(0),"Revolution", App::Prop_None, "Mid plane"); + ADD_PROPERTY_TYPE(Reversed, (0),"Revolution", App::Prop_None, "Reversed"); } short Revolution::mustExecute() const @@ -68,7 +68,8 @@ short Revolution::mustExecute() const Axis.isTouched() || Base.isTouched() || Angle.isTouched() || - Midplane.isTouched()) + Midplane.isTouched() || + Reversed.isTouched()) return 1; return 0; } From 55a205062a9660f7c9bef116505a2e7a8c342d00 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Jun 2012 17:16:41 +0200 Subject: [PATCH 348/351] Show some help text in sweep panel --- src/Mod/Part/Gui/TaskSweep.ui | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Mod/Part/Gui/TaskSweep.ui b/src/Mod/Part/Gui/TaskSweep.ui index 8985963657..6cfab459d1 100644 --- a/src/Mod/Part/Gui/TaskSweep.ui +++ b/src/Mod/Part/Gui/TaskSweep.ui @@ -14,17 +14,17 @@ Sweep - + - + Create solid - + Qt::Horizontal @@ -37,13 +37,21 @@ - + Frenet + + + + Select one or more profiles and select an edge or wire +in the 3D view for the sweep path. + + + From 152ed0f77cb3ca9af31216a07b385dbdddff4612 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 9 Jun 2012 15:19:57 -0300 Subject: [PATCH 349/351] Start: Small fixes to the start page --- src/Mod/Start/Gui/CMakeLists.txt | 2 ++ src/Mod/Start/StartPage/CMakeLists.txt | 2 ++ src/Mod/Start/StartPage/Makefile.am | 4 +++- src/Mod/Start/StartPage/StartPage.py | 19 ++++++++++++------- src/Mod/Start/StartPage/blank.png | Bin 0 -> 302 bytes src/Mod/Start/StartPage/complete.jpg | Bin 0 -> 12532 bytes 6 files changed, 19 insertions(+), 8 deletions(-) create mode 100755 src/Mod/Start/StartPage/blank.png create mode 100644 src/Mod/Start/StartPage/complete.jpg diff --git a/src/Mod/Start/Gui/CMakeLists.txt b/src/Mod/Start/Gui/CMakeLists.txt index 54bdc5c5eb..339c9ad500 100644 --- a/src/Mod/Start/Gui/CMakeLists.txt +++ b/src/Mod/Start/Gui/CMakeLists.txt @@ -54,6 +54,8 @@ SET(StartPage_Resources StartPage/PartDesignExample.png StartPage/ArchExample.png StartPage/web.png + StartPage/blank.png + StartPage/complete.jpg ) add_library(StartGui SHARED ${StartGui_SRCS}) diff --git a/src/Mod/Start/StartPage/CMakeLists.txt b/src/Mod/Start/StartPage/CMakeLists.txt index 19c59fcf32..7a798c98e4 100644 --- a/src/Mod/Start/StartPage/CMakeLists.txt +++ b/src/Mod/Start/StartPage/CMakeLists.txt @@ -24,6 +24,8 @@ SET(StartPage_DATA PartDesignExample.png ArchExample.png web.png + blank.png + complete.jpg ) INSTALL(FILES ${StartPage_SRCS} diff --git a/src/Mod/Start/StartPage/Makefile.am b/src/Mod/Start/StartPage/Makefile.am index de35b6d452..57ffd74ee3 100644 --- a/src/Mod/Start/StartPage/Makefile.am +++ b/src/Mod/Start/StartPage/Makefile.am @@ -28,7 +28,9 @@ data_DATA = \ Complete.png \ PartDesignExample.png \ ArchExample.png \ - web.png + web.png \ + blank.png \ + complete.jpg EXTRA_DIST = \ $(data_DATA) $(python_DATA) diff --git a/src/Mod/Start/StartPage/StartPage.py b/src/Mod/Start/StartPage/StartPage.py index c3983a86f5..978cae6b7b 100644 --- a/src/Mod/Start/StartPage/StartPage.py +++ b/src/Mod/Start/StartPage/StartPage.py @@ -309,10 +309,10 @@ def getWebExamples(): def getExamples(): return """ """ def getLinks(): @@ -366,7 +366,7 @@ def getWorkbenches():
  •   \

    This is the """ + text31 + """, \ - """ + text32 + """

    ')" + """ + text32 + """

    ')" onMouseout="show('')" href="DefaultWorkbench.py">""" + text31 + """
  • @@ -399,7 +399,7 @@ def getInfo(filename): html += text35 + " " + getLocalTime(s.st_mtime) + "
    " html += "" + text36 + " " + filename + "

    " # get additional info from fcstd files - if os.path.splitext(filename)[1] in [".fcstd",".FcStd"]: + if os.path.splitext(filename)[1].upper() in [".FCSTD"]: zfile=zipfile.ZipFile(filename) files=zfile.namelist() # check for meta-file if it's really a FreeCAD document @@ -429,7 +429,12 @@ def getRecentFiles(): if i < ct: mr = rf.GetString("MRU%d" % (i)) fn = os.path.basename(mr) - html += '
  • ' diff --git a/src/Mod/Start/StartPage/blank.png b/src/Mod/Start/StartPage/blank.png new file mode 100755 index 0000000000000000000000000000000000000000..4b794044844fceb5d8172c69f0cdf2b0c6fac6e0 GIT binary patch literal 302 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ zFqeTaW9`+ZGeAMf64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1T6d%8G= zSoFT_Gvqqtz`*id`yKnJ7n~Tz3KkOO(JhZgR&oJb#qKos@3rkw&+Wk zvNhn~IhE37_iqZSESxgS^Z3lgZ09${ylqP0pCqyS-7*cXFxB(Lep8~DUzEMt^RMXi zCc%cp_s_R!%T|HersIRCQ;IfjOq8tE$Kmc>_4?rOS zlG|=pW*%0S4BmDgwhZ!$D)#`?EJ3)ekDWCDC@OLSH~;{k0sIg&fCMbDfv4S53;+WD z7Y9!n@Z`V2$1i?ESp0?<1D~L{kbt-VKUjNlpabZTpR`!u9R%%X*&ZyT{VG!sT+o4< z{9QYc^r8dQIB*-l!obAB#K6MB#KOkL!oj1053+0|TTE z0NVi!V$3Uyd^fSKs+(amxsvb)#k|E~zE#phs?op2B4F+ojEhG`PC-e<%Er!djZ;ua zSVUAz{PrDLIe7&|B~2}D9bLWq`WBW});6|w_U;~@Ufw>wej%ZcpFDjQ79Jb-GCm>k z)$62p=^2?>**UrIOUueDDyyn%YCnDc(%jP8*4{BNI5a#m`gII3`)zK1VR7mE^2+wk z?%w{v;nDHQ1uh8q*nS^Bf&Bw6Vh|S^1_n9?_605onm2f&6Jua9@?l-Msg7;tdXTI|69oZ0Q(CU0w6$#fDaFy7=QwM zt56(~7wnDqugu&T|748zrc`02frtkFy7|5uo=i8|6So1hFZh|u@Vp)OX3wh~`Eg$k zN;}a$DyMEH6UE58$?8;b#@W5~7-KfdhY)^2FE$&DL8=I;A6|{zFA04}_lAYhTJ$t^ znQPa5dVVgtfN&N=FXgorLG{N|rJ1N>3DJVpycT3PE4NLo$`PMctNG2IiMdDOohJTHJIf3Y^bnNClcATI2l7Z$1 zg&b?CX0taVVWZ!PL*n{rYLB3|476*I{k5l($=q36q+(KGa|H%;!~>n81GBQsURL6deh|@XumwBtD8^1PUIfRa*E1<>qX+Hgp%R#0^<`NI~23N7#59C(h35 z8}r_!T;pkBKVz)*>YKK$MYx76@?7%s%5=f9Tfw#4_(&6LX$)1W%Qf=Vw@!NguG@<> zNwhu!>$2(AI{c9-&2VR3L$OJ%UN2YcV?;WZi%NF&V);^>k`cwRMU^JyL(1&Z;IhdV zayPH=LNgh*ypr#~G@M9KkChy5qdU{R>DX*hh4xkMVe%aFyeK^ntXHY4)(hF1u%bex z=fuH3E&#zLGIYkjMc`&bcCNnxT*;KVQ+S zlS_kLCR=$sf-fezDo^ftl!gcwTD89VdYT?39s~FDA1MgU^4GIY5FjW_E4SRq9(Xce zQT@`~-KHtYhf-kD0$Iy@q+_>bXze{Fn02R#>mVo|Bc!c0t#I=C`rM_Gv%0T!X2pt9 zDrh)Y>}=Hb3+wJzd7>i{C2LD|(o@7Azo_vPj@uN&STt2!jc}S1E5IQPec|h#5UeQE zCFeaQ*0zDOtZiMLfGdxn@1(|OjJZtkK%lxx_2#NOh-I5u{n zovnJ69f8-j)8h;d)wQ~^)b21Lmi$#pJ`V4-j5%oJ-6Z$-oC~59v(K^vg4MK9zz4(& znuF~83B7hIp;~9FcIvVy6-^WnnglyOP&@rTa1_PFd#j}Vp1k2g2*)S@vXv%X-H= zlIh+c-z;BrYf!fe*}HdqxRu;>VVIfba;j>p+GnZuZp}|1#wlPaj^ zH$Zfl4--r-Z95!B%y1#Rteo+a6tivqsLmqGqey{l6%;+-!LX~pmX=( zDo!hTA5M(L`A9W84vI{OBs3LTlr^F4>FotXT!?5cMCC!~*WMl59f#W;2kGDsff<1U z*rM6WC5!CApH!OOf4P;5^zDMbhM=BiGrOjYLVwjjkyX_bg^f9FO9FI8_Ur)ug<8)&U6wR_g+^7q!tV&>rq1`zk35Z&kJDYpwD<`Ugc5B_ zCUBM{nbZfuv^@y=w;LQ|%&3?3jaB$-WP@+s zjsmRJHd0RyQNT$0TKhTZ z>VYWWWC-HdmliuO0X!U830P?{N1h-(yG?9kjEoJ8a0?leCT`rO;@u{odvDK}W)?yy zf3I!%6KtDQ@i;`hzWIFr?ECrj;plGub5SY;Q>5VF75CaZlqjH8hE!VZ)a0<~-5Md$ zBxpI9IMf@YUWKxs7oE-wT$!wbO=Berpvxb^rcHXHf0FcI)@^{Jfsp41Yx?V;x2KJp zMN9G*m5nJj^C+MK1w5qUhaoPgXu5O+e+d1h!ddD;<7SB5FW!j0ABv^_kYBd*lZ6tx z4t5)5%|%6DcL7vQ{R+j0WDtd>nH0e9OLKZJ?EMj3D-!W-J!pF$#cl z)KS)0pa41@6tLe7i&rt^i28nuSg200iJg((cfAw-a@(=Alcq|4#7I4zivX^FLv%hO z^_4|1pJLE>zo9jBJn3Pp z)T5&+6wny_NSulbeyW{#c4mMArkmvd&;Z|U3;ox1Om?@y@dm@Bw=V^Q$aC1~5eNF) zcQu<8_hG%wjpt`10a=~M!0RYrb0+Q5lklYvgH|X2N`?Xsx6}{vz)02lg9_4j(SQE$ z{{JGnhkaYtefp2^YjMV7Ep?$WP$|+;XwM^YrC=0*lyru!zJYNrk!x0P;@-Xbwbm5{ zL~G7{C`-cP>2Fb$8})2I3rizHjs3s21}KMc|IZrW$J*xq`!&GI>;Uh60l$BWgjTW7 zyi>4ejbRJ&DFY4M@8m=$!kBdATUDs)f$A5`U4oUj#x20I^I@UX(ijq ztWa0w%z=ZRJoB*oBf zgkYtc{#90UI&!N<11j!)##GxgFz$E|6dTxAjaGZi)IYn`728bB^9t&xL*pe04@@2| zU{@Wms1WhfQY6tOMgjQ|PTch|qbv3`^R-vo>XMm!EOZ_`CVY-fX=s=`AthfxzZGGB zY=#VpKmEMU)jB#**LfXZ={CW^K~7;PKlFjTpCg=ZV1t((?x4=H;kGvO07jISxlZ9P zG%-8+skZZxy5m>knCFir{RS82OA8~3dC@_zcP8uzXYky5RIlkS>gyk;bq>WB_M7h#4O0neqJN6q{nq)PWdj;11E3AooYk| z_EUG;qH_d%o4kSf^EHk+Z}+HxRR_(6s=;($9-~i8iC%Mf0DDmpHhO`yuNP^0VI7?< z5@(xBp{wfNySNu``{s5@nzuy4np8&nZ(xv7MmW#=T@t77X`t60cG_DP;-%xNiRlwn zV450N6_a|ZuFDwDQmUMARW9O9hxo(QHJM)NA@`2aVpg)X*NdGq>kn0X0=q1jA(FFA zbE$nuPu?>o@ujmJaAIzpJL4+t7h0t?Kh!9%6v#*TVim$lvzhbM;$o7t;ef zI&fabiK;;XlIyU|BNTuK{kulSK{>_-%LfHgoo&Rb(%S88sZz}a4Mhl>YP}g|#)(Hn zRilX1a&vIdEv0TfTTR{V7)64!>Q*|EnARQX3%>bGZzD;^k6`ypMm-)66;OTSGH+I> ziSDps&SBVF;p~oF&pb<1v=fUjNM;GWgiicIU^<*uuH05CNfMm0|0aaw?n zVtA{U#;VSz0=rSucLPbM#|Sy+v}(#j6{-?Gy69j$%zklmZ&led6Y;SvM!v#p2{=u1 zb~D0AOV!jDqPy!{N`er05m2+Ly;N2*!tHc6teodeCp;k|X(2|Dzi#GOxPFDYTY0Ur z|MKCz{5H5faY~f?3vrJn8t-g-FF()4*G}2Z?u79#RbM^9jwFo{XP7thSzo^Iu4o_W z2#+YKQbvAZ;(GRWupkUeVG)s|_2OgI&~8$~*D-_T>w?~;4p}@w`{c4uTJQv=ME4MjfMUFpjPT}lh50vh`_IUciEZgL!RJ)wDRn)af~I5Rf2bn;yYw zrM9&b_(lM)nu>SxX;32@7dCrO)9UiP9E2hyAouO z^!Pn&O?p)`K6TU5enrG9;T}uU<1fNnW%>3yANuY`0lm4oyc=o7WeJNXw(INfC}R~b zk;<#8m>%_h@(Sdvs#GqMW;UR|dmlC;R9&OkyU%t^ZY(c?!c zw8A9UIQhPWYwgC3VpS@M8^z?h&D|T^J7=w+exBzexN!4Y$}|qi9Jcf^#YwnRX7iIq z3)<%7?MVZ&W6Q8trpQqG0`qAf@u|a)TRzT|8Y4)*t{TGqR+O_nGy5#;t2kZ3sYO z_~~8$;cEZh%Sf8^ZzImxn87-pAnO|R^Dm%K+# zbSX-TGcl;19y=6PE?d59czvR&-w^Y1i$LWKk;|@eyPksjWX>mhSL;e0RI}hgY%iaC zW-N>FDUA><^a5_(xQ=H9%YAdp$_@dUgt83bCnEJP1l3!5+`O(<^T>;~vcuz3(tM_>(R zuJc}ZW^QD-$>Pu28Bg%K9eaF#u~hQ@?9*+`;fVHJ6T6l%BegL-w3&Fxd)VOi5Vj%ehO6a7fC&U@EL+;<^Lao*0g zTFlUOI%qU$A$0rt;8J*HJ!0*|pr$@ud1@gLZdv)<;ox};K^V(=5HCX|@R44%v4D)s zE5T(RfpMF}{yD`mmHQ)XQ&^^M`GC&2hDc1Wn|wn5v->a7FhZ8$e67$FiBqwb9A2H3 z1z(AG)WX%sWzimSkEXc-ElzVWi(XQ%{jxC!o29-)Jnuu3GcgT9X8F=>%0|sdB`rRV zSZh;=n8eMQt7o-3@OMtkCDl%{X=D*~R=Xv|AuX2z+#|H9&o6Ox%Ta$8n&6k~Xg2r2 zTTqpABgz(Su}_UUmWK603Mtsyl#KURt~z zVOKQi(&(fTDVCo;$b1R}OHd5G=Oldph=w@otB|0&EX{Qi^?VM2cy#ND!-ISW7-5sk ztf(Lb3tZGJQr#NUJ63GMy@_Q%FEXKP!xMGZf@Dd^QoB{T7^6jdZTF zrWX(FlZV~eG+GwIg+s}wHwNh0Zu*A6cRcD!87O*n0A@gf`~{DzdBiny+S4T&4qb`&SY?JRX4C7`wUDxuOwMj zEb)>XrWO?dHq#EpW0R6Z1QDGR=6TUq$H6=^E=;Lo8!aU7uDmKV-o~-WISMOcxkb$@ zf>k}+0?Z7D!l#iw$|vez{#UB;Y%6iE(87wEOKt50?VwZ~cBHrtrmaI8Guh8r4#4#A zCzFAil$Va_r_zu7@6$s6RDxONUxe<|9Aoka0RYJD@~4vb4`EH@AMR`0f+o8yY9Q1i zB}p|bv0%ef^WVZ7@}p9bSNvhev%Je-!u)sFznIVev(~43pAl`#Ps4uc^H00}?<@XO zItrL&2lHp}E6A6rTXDb4yy&G~8vT!UbED(wJLCJ-?V>VV@kU~)VQ~AvD=Hwo+UYZc z=VHENx)uG{9`?GWLuZbiyAkV`N{K}oz)O}rq$R+0T#A!=JcWM;zb*U8TEX8?otl>V0E(rUg7D3Oz(E6&M`iY|#W5Ca9fnPL97In$}5d*spgGmyR8wU?FOt#b8tHB3D2#z1#qmeAzG=fI9Ii!!s z`CjAPy(wAI^5j=~KxACCUx0(Hc7Qxmk_WaL2V<6@!78m8vXuUOtbIK``#q0K@+r}R zwwG>SU*bmk_b5B(j&Y7L9q<8HE)pA9QFHcm2&;EtI=ytvlel(K3b-hNj(>x+QoS^P zE!~RdqYn6tN=g%dmC8yZU%Es7f%V^IP=OD*LrkpHaK4zQlqO@5z~KAs5%J53ggu9H zV3uAs@!VByo^wI7zj2-z%)c6H9^=&*Q&y{oOZ0~We6rY?B*5RW>R{>)!R9_KA!|f- z1R*W<_;0E%a0kTuZM#2cUB0(gWFOJ!O@AA!f(rzq2f`Rk*7;q0*kt~pLs6FHv%dvp|5Yg#+blDiqHgA=;3jvnPY(A0qQy)zVWN|o)J zSAUgT(?q|S*%ZSYfWxQ0fr)1>EX2vmEdFPAjP}^NbW=Hb^%tBj(x<1(V4nU!5K_$f z0em~4BZuy{H^$^|{%#N=-0wz=^;lY2eszPa@FCX$8zm9xP4&CuI!dN92N~nWDPsQ5 z+6$CUZO3(l`zy;AiA|iS?OPDS{h$w(JLOT^j)OjQ&|jJFl~D5cBI8~ijK7-UPIhJycAAfEUT>$ ze=FXs;<8(V_@%F;B2Q7kJnn_7J+{?_+iRZUEuDKbW*=$$M_%fg{X8L8T1`R7V*AB& zLw5q{nL8B@^oA$}Pe~;#yt}((&zaNPhZna7?lehdoXQ8uI&B(X~Dq`x#X(yiuD@H~DT*FWdUZ^z4f^~Xj3 zaw7Q~zrB%T5ufw`9GPIirTNc2_@6rKzaz4J_zBO|^WGH)e=GA<3vzHm9fhtqh{x7a z$t%vHfMc}#uu(>R($v3|+w{EOg>wM!LSzBbi~P?Esiku_mj&I&>Z8zkB7e}lZ;tO_ z`g?YngdsiIIy{pWA^Xst>@odZTQ1TAfAwO&i-DNk1>R^l(#6|YQD5M!BvKM4Qu+~a zz#)j8$=2~#nOf@o?_rqnRqAILBja+Ud-*qZjkSY|5qM#|V!uB&t87}9Yg)btfuMy9 zO!v}F_kKpaA5=dzxd;hgr8q#rzd8Y>27QA(Z$kmAuaMT2o_Rxqf`>IRF*2M%$+KD| zAKAy3do#@(67Q*bQij{kqcPy#j)AM~FlA|c2vPW6j%#5=)g|~0=h*{2?Oj)#Rc_c} zU!kPlRJ#=h*&!OotRa`I05ic3DwuPwMw^;RBX3QiFHuxaz^Ymx#U0|NQ0#1h5ClQP_H3KXm3LKQC7-)S?$ zv0~+UzVKlAnG$#a5E)wXKU~q}O`zkx1NR1-%>v#aU)?^2?dP0|oZoo51H!zA^}Qwp z=`Rb;KjE1LhPMzZGxsf6zI=r|&9piHMV(7n!YT9QvO{#qG^vlVoFA4@lTZ35UGb?r8!xsJb?c6;^*M+W9WVk+94wDv_Ssia(^65=fmZZC)rqT(BZl53p-+h+pz41`q3Ac zoDJB2?05*`zpi*bl74Y{FOhm00`7CJYJl;m8VW^L04ApzFwdNe%loKbst!5-5+OtW zVJLOdUi#wl7EGW1;Nba9_0Qz0|E22qf$l3%I&6o@PU~lB&6Q7HxXEB7)2RZh21$R-m>lR= zTIKzzT`_Zlm+lFGmTs6qjL(>wOk zt)A!Kp=<@>9OwdT-ms~vv!v*sPc!5se;}>}B`JrFv{{1S}sc6=*(B65G zm*az*1XK&2)ta*PWZSpNSWLumvzS(&Y9N5tm@g*)+-9Q+bJ9m%beu4z8K=Pfg%3qqELq%ACaQlcbK9_xLVA{>%@DX+##-4Z!cKd%CplD%LA2pm7-N_qb2#Dkx!6)%tDW0ND% zXYU5S`fFLqapYn>-XHudPKQ1&$LSZlq229LlVP?<9mqfqR_-Sv&l-<(=n~V%?UMBi zo4E}m;@T-T)a(b+@J$e2Qy1&t#EV^y^7RIAoHz0!NwxYBkFLY)#{Iw*WT43z#~&%$ z`hHLq5oWK{kVpIu3SUTzeYOHhnc!A;c_3g31WRr|2N5bO15ad ze*ua9i%Lfj{;%M^Ps-)Vw7J?AJHb?ISuEDpgnk?&L)G{rL~7{iY~#^;=&UIC ziQ7_S>iO36nKsEi2$f>@#+%)U)j} zaC)ak0paP$tC4C*pE1z;z$Im~x-9TN3jANTK#oCkm19@8MYe#j@>K}S5@oOS=bd-q zfXR{aCSP=k-PgHj=DvCF{lynPmEU>#Ewa}4c0`eZOS>RV%tNP~mRC_z&06k{BZ5%C hTb+dXd?WjVZdccZ^gNO;4na{w4^R4K8B Date: Sat, 9 Jun 2012 15:57:09 -0300 Subject: [PATCH 350/351] Draft: Added exttension X perpendicular snap location --- src/Mod/Draft/DraftSnap.py | 79 ++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index ee2e2aab97..c4bacf77a0 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -148,26 +148,7 @@ class Snapper: return None # setup trackers if needed - v = Draft.get3DView() - if v in self.trackers[0]: - i = self.trackers[0].index(v) - self.grid = self.trackers[1][i] - self.tracker = self.trackers[2][i] - self.extLine = self.trackers[3][i] - self.radiusTracker = self.trackers[4][i] - else: - if Draft.getParam("grid"): - self.grid = DraftTrackers.gridTracker() - else: - self.grid = None - self.tracker = DraftTrackers.snapTracker() - self.extLine = DraftTrackers.lineTracker(dotted=True) - self.radiusTracker = DraftTrackers.radiusTracker() - self.trackers[0].append(v) - self.trackers[1].append(self.grid) - self.trackers[2].append(self.tracker) - self.trackers[3].append(self.extLine) - self.trackers[4].append(self.radiusTracker) + self.setTrackers() # getting current snap Radius self.radius = self.getScreenDist(Draft.getParam("snapRange"),screenpos) @@ -175,10 +156,6 @@ class Snapper: self.radiusTracker.update(self.radius) self.radiusTracker.off() - # set the grid - if self.grid and (not self.forceGridOff): - self.grid.set() - # activate snap oldActive = False if Draft.getParam("alwaysSnap"): @@ -362,6 +339,19 @@ class Snapper: self.extLine.on() self.setCursor(tsnap[1]) return tsnap[2],eline + else: + tsnap = self.snapToExtPerpendicular(last) + if tsnap: + if (tsnap[0].sub(point)).Length < self.radius: + if self.tracker: + self.tracker.setCoords(tsnap[2]) + self.tracker.setMarker(self.mk[tsnap[1]]) + self.tracker.on() + if self.extLine: + self.extLine.p2(tsnap[2]) + self.extLine.on() + self.setCursor(tsnap[1]) + return tsnap[2],eline for o in [self.lastObj[1],self.lastObj[0]]: if o: @@ -541,6 +531,14 @@ class Snapper: return None return None + def snapToExtPerpendicular(self,last): + "returns a perpendicular X extension snap location" + if self.isEnabled("extension") and self.isEnabled("perpendicular"): + if last and self.extLine: + tmpEdge = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape() + np = self.getPerpendicular(tmpEdge,last) + return [np,'perpendicular',np] + def snapToElines(self,e1,e2): "returns a snap location at the infinite intersection of the given edges" snaps = [] @@ -920,16 +918,31 @@ class Snapper: mw.addToolBar(self.toolbar) self.toolbar.show() if FreeCADGui.ActiveDocument: - if not self.forceGridOff: - if not self.grid: - self.grid = DraftTrackers.gridTracker() - self.grid.set() + self.setTrackers() - def setGrid(self): - "sets the grid, if visible" - if self.grid and (not self.forceGridOff): - if self.grid.Visible: - self.grid.set() + def setTrackers(self): + v = Draft.get3DView() + if v in self.trackers[0]: + i = self.trackers[0].index(v) + self.grid = self.trackers[1][i] + self.tracker = self.trackers[2][i] + self.extLine = self.trackers[3][i] + self.radiusTracker = self.trackers[4][i] + else: + if Draft.getParam("grid"): + self.grid = DraftTrackers.gridTracker() + else: + self.grid = None + self.tracker = DraftTrackers.snapTracker() + self.extLine = DraftTrackers.lineTracker(dotted=True) + self.radiusTracker = DraftTrackers.radiusTracker() + self.trackers[0].append(v) + self.trackers[1].append(self.grid) + self.trackers[2].append(self.tracker) + self.trackers[3].append(self.extLine) + self.trackers[4].append(self.radiusTracker) + if not self.forceGridOff: + self.grid.set() if not hasattr(FreeCADGui,"Snapper"): FreeCADGui.Snapper = Snapper() From f2c63b90ab03778d038ff393cee2882a999da12f Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 10 Jun 2012 10:18:54 +0200 Subject: [PATCH 351/351] Add icons for loft and sweep --- src/Mod/Part/App/PartFeatures.cpp | 2 +- src/Mod/Part/Gui/Command.cpp | 2 + src/Mod/Part/Gui/Makefile.am | 2 + src/Mod/Part/Gui/Resources/Part.qrc | 2 + .../Part/Gui/Resources/icons/Part_Loft.svg | 280 ++++++++++++++++++ .../Part/Gui/Resources/icons/Part_Sweep.svg | 226 ++++++++++++++ src/Mod/Part/Gui/TaskLoft.cpp | 4 +- src/Mod/Part/Gui/TaskSweep.cpp | 4 +- 8 files changed, 519 insertions(+), 3 deletions(-) create mode 100644 src/Mod/Part/Gui/Resources/icons/Part_Loft.svg create mode 100644 src/Mod/Part/Gui/Resources/icons/Part_Sweep.svg diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index 1bf2ce8740..431e157414 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -212,7 +212,7 @@ Sweep::Sweep() ADD_PROPERTY_TYPE(Spine,(0),"Sweep",App::Prop_None,"Path to sweep along"); ADD_PROPERTY_TYPE(Solid,(false),"Sweep",App::Prop_None,"Create solid"); ADD_PROPERTY_TYPE(Frenet,(false),"Sweep",App::Prop_None,"Frenet"); - ADD_PROPERTY_TYPE(Transition,(long(0)),"Sweep",App::Prop_None,"Transition mode"); + ADD_PROPERTY_TYPE(Transition,(long(1)),"Sweep",App::Prop_None,"Transition mode"); Transition.setEnums(TransitionEnums); } diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 5020e48724..e713331d9f 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -947,6 +947,7 @@ CmdPartLoft::CmdPartLoft() sToolTipText = QT_TR_NOOP("Advanced utility to lofts"); sWhatsThis = sToolTipText; sStatusTip = sToolTipText; + sPixmap = "Part_Loft"; } void CmdPartLoft::activated(int iMsg) @@ -972,6 +973,7 @@ CmdPartSweep::CmdPartSweep() sToolTipText = QT_TR_NOOP("Advanced utility to sweep"); sWhatsThis = sToolTipText; sStatusTip = sToolTipText; + sPixmap = "Part_Sweep"; } void CmdPartSweep::activated(int iMsg) diff --git a/src/Mod/Part/Gui/Makefile.am b/src/Mod/Part/Gui/Makefile.am index ca433d86f5..15a2a094ab 100644 --- a/src/Mod/Part/Gui/Makefile.am +++ b/src/Mod/Part/Gui/Makefile.am @@ -200,12 +200,14 @@ EXTRA_DIST = \ Resources/icons/Part_Fillet.svg \ Resources/icons/Part_Revolve.svg \ Resources/icons/Part_Import.svg \ + Resources/icons/Part_Loft.svg \ Resources/icons/Part_Mirror.svg \ Resources/icons/Part_MirrorPNG.png \ Resources/icons/Part_RuledSurface.svg \ Resources/icons/Part_Shapebuilder.png \ Resources/icons/Part_Shapebuilder.svg \ Resources/icons/Part_ShapeInfo.svg \ + Resources/icons/Part_Sweep.svg \ Resources/icons/Tree_Part.svg \ Resources/icons/preferences-part_design.svg \ Resources/icons/PartFeature.svg \ diff --git a/src/Mod/Part/Gui/Resources/Part.qrc b/src/Mod/Part/Gui/Resources/Part.qrc index 82c60f77a2..f6fbdf0c33 100644 --- a/src/Mod/Part/Gui/Resources/Part.qrc +++ b/src/Mod/Part/Gui/Resources/Part.qrc @@ -16,6 +16,7 @@ icons/Part_Fillet.svg icons/Part_Fuse.svg icons/Part_Import.svg + icons/Part_Loft.svg icons/Part_Mirror.svg icons/Part_MirrorPNG.png icons/Part_Revolve.svg @@ -24,6 +25,7 @@ icons/Part_Shapebuilder.png icons/Part_ShapeInfo.svg icons/Part_Sphere.svg + icons/Part_Sweep.svg icons/Part_Torus.svg icons/preferences-part_design.svg icons/Tree_Part.svg diff --git a/src/Mod/Part/Gui/Resources/icons/Part_Loft.svg b/src/Mod/Part/Gui/Resources/icons/Part_Loft.svg new file mode 100644 index 0000000000..72df9ab92a --- /dev/null +++ b/src/Mod/Part/Gui/Resources/icons/Part_Loft.svg @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/src/Mod/Part/Gui/Resources/icons/Part_Sweep.svg b/src/Mod/Part/Gui/Resources/icons/Part_Sweep.svg new file mode 100644 index 0000000000..33a9f428ab --- /dev/null +++ b/src/Mod/Part/Gui/Resources/icons/Part_Sweep.svg @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/src/Mod/Part/Gui/TaskLoft.cpp b/src/Mod/Part/Gui/TaskLoft.cpp index 96c3417a27..7192c27c42 100644 --- a/src/Mod/Part/Gui/TaskLoft.cpp +++ b/src/Mod/Part/Gui/TaskLoft.cpp @@ -32,6 +32,7 @@ #include "TaskLoft.h" #include +#include #include #include #include @@ -198,7 +199,8 @@ TaskLoft::TaskLoft() { widget = new LoftWidget(); taskbox = new Gui::TaskView::TaskBox( - QPixmap(), widget->windowTitle(), true, 0); + Gui::BitmapFactory().pixmap("Part_Loft"), + widget->windowTitle(), true, 0); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } diff --git a/src/Mod/Part/Gui/TaskSweep.cpp b/src/Mod/Part/Gui/TaskSweep.cpp index effd5c28b5..64e9995e46 100644 --- a/src/Mod/Part/Gui/TaskSweep.cpp +++ b/src/Mod/Part/Gui/TaskSweep.cpp @@ -32,6 +32,7 @@ #include "TaskSweep.h" #include +#include #include #include #include @@ -225,7 +226,8 @@ TaskSweep::TaskSweep() { widget = new SweepWidget(); taskbox = new Gui::TaskView::TaskBox( - QPixmap(), widget->windowTitle(), true, 0); + Gui::BitmapFactory().pixmap("Part_Sweep"), + widget->windowTitle(), true, 0); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); }