Merge branch 'refs/heads/master' into jriegel/develop-fem
Conflicts: src/Mod/Fem/App/FemMeshShapeNetgenObject.cpp src/Mod/Fem/App/FemMeshShapeNetgenObject.h src/Mod/Fem/Gui/AppFemGuiPy.cpp src/Mod/Fem/Gui/Command.cpp src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.cpp src/Mod/Fem/Gui/TaskDlgMeshShapeNetgen.h src/Mod/Fem/Gui/TaskTetParameter.cpp src/Mod/Fem/Gui/TaskTetParameter.h src/Mod/Fem/Gui/TaskTetParameter.ui src/Mod/Fem/Gui/ViewProviderAnalysis.cpp src/Mod/Fem/Gui/ViewProviderAnalysis.h src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.cpp src/Mod/Fem/Gui/ViewProviderFemMeshShapeNetgen.h
This commit is contained in:
commit
83b956e908
|
@ -49,8 +49,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||
include(cMake/ConfigureChecks.cmake)
|
||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
add_definitions(-Wno-write-strings)
|
||||
add_definitions(-Wno-deprecated)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-write-strings")
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||
# get linker errors as soon as possible and not at runtime e.g. for modules
|
||||
if(UNIX)
|
||||
|
@ -271,7 +270,6 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
|
|||
|
||||
# -------------------------------- Eigen --------------------------------
|
||||
|
||||
#find_package(Eigen2)
|
||||
find_package(Eigen3)
|
||||
|
||||
# -------------------------------- ODE ----------------------------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Changelog you finde now here:
|
||||
Changelog you find now here:
|
||||
https://sourceforge.net/apps/mantisbt/free-cad/changelog_page.php
|
||||
|
||||
Version: 0.12
|
||||
|
|
35
README
35
README
|
@ -12,13 +12,20 @@ FreeCAD is based on OpenCasCade, a powerful geometry kernel, features an Open In
|
|||
The interface is built with Qt. FreeCAD runs exactly the same way on Windows, Mac OSX, BSD and
|
||||
Linux platforms.
|
||||
|
||||
Home page and wiki documentation: http://free-cad.sf.net
|
||||
Home page: http://www.freecadweb.org
|
||||
Documentation wiki: http://www.freecadweb.org/wiki
|
||||
Forum: http://sourceforge.net/apps/phpbb/free-cad/
|
||||
Bug tracker: http://sourceforge.net/apps/mantisbt/free-cad/
|
||||
Official git link: git://free-cad.git.sourceforge.net/free-cad/free-cad
|
||||
Git repository: http://sourceforge.net/p/free-cad/code/ci/master/tree/
|
||||
|
||||
Building
|
||||
========
|
||||
Installing
|
||||
==========
|
||||
|
||||
Precompiled (installable) packages are usually available to you from several sources and are
|
||||
described on the FreeCAD download page: http://www.freecadweb.org/wiki/index.php?title=Download
|
||||
|
||||
Compiling
|
||||
=========
|
||||
|
||||
Compiling FreeCAD requires to install several heavyweight libraries and their development
|
||||
files such as OpenCasCADe, Coin and Qt, listed in the pages below. Once this is done,
|
||||
|
@ -31,12 +38,26 @@ Note that autotools build system can still be used but will be obsoleted soon.
|
|||
|
||||
The pages below contain up-to-date build instructions:
|
||||
|
||||
For Linux: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnUnix
|
||||
For windows: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnWindows
|
||||
For Mac OSX: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnMac
|
||||
For Linux: http://www.freecadweb.org/wiki/index.php?title=CompileOnUnix
|
||||
For windows: http://www.freecadweb.org/wiki/index.php?title=CompileOnWindows
|
||||
For Mac OSX: http://www.freecadweb.org/wiki/index.php?title=CompileOnMac
|
||||
|
||||
In this folder you will also find additional README files, specific for each platform.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The FreeCAD documentation wiki contains sections for each category of users, and a manual,
|
||||
which is a compilation of the most useful articles of the wiki:
|
||||
|
||||
For users: General FreeCAD usage: http://www.freecadweb.org/wiki/index.php?title=User_hub
|
||||
For power-users: Python scripting: http://www.freecadweb.org/wiki/index.php?title=Power_users_hub
|
||||
For developers: C++ FreeCAD development: http://www.freecadweb.org/wiki/index.php?title=Developer_hub
|
||||
|
||||
The FreeCAD manual: http://www.freecadweb.org/wiki/index.php?title=Online_Help_Toc
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -467,7 +467,7 @@ void PropertyEnumeration::setPyObject(PyObject *value)
|
|||
{
|
||||
if (PyInt_Check(value)) {
|
||||
long val = PyInt_AsLong(value);
|
||||
if(_EnumArray){
|
||||
if (_EnumArray) {
|
||||
const char** plEnums = _EnumArray;
|
||||
long i=0;
|
||||
while(*(plEnums++) != NULL)i++;
|
||||
|
@ -478,10 +478,10 @@ void PropertyEnumeration::setPyObject(PyObject *value)
|
|||
}
|
||||
else if (PyString_Check(value)) {
|
||||
const char* str = PyString_AsString (value);
|
||||
if (isPartOf(str))
|
||||
if (_EnumArray && isPartOf(str))
|
||||
setValue(PyString_AsString (value));
|
||||
else
|
||||
throw Py::ValueError("not a member of the enum");
|
||||
throw Py::ValueError("not part of the enum");
|
||||
}
|
||||
else if (PyList_Check(value)) {
|
||||
Py_ssize_t nSize = PyList_Size(value);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
# endif
|
||||
# include <xercesc/framework/StdOutFormatTarget.hpp>
|
||||
# include <xercesc/framework/LocalFileFormatTarget.hpp>
|
||||
# include <xercesc/framework/LocalFileInputSource.hpp>
|
||||
# include <xercesc/parsers/XercesDOMParser.hpp>
|
||||
# include <xercesc/util/XMLUni.hpp>
|
||||
# include <xercesc/util/XMLUniDefs.hpp>
|
||||
|
@ -1080,7 +1081,23 @@ bool ParameterManager::LoadOrCreateDocument(const char* sFileName)
|
|||
int ParameterManager::LoadDocument(const char* sFileName)
|
||||
{
|
||||
Base::FileInfo file(sFileName);
|
||||
|
||||
|
||||
try {
|
||||
#if defined (FC_OS_WIN32)
|
||||
LocalFileInputSource inputSource((XMLCh*)file.toStdWString().c_str());
|
||||
#else
|
||||
LocalFileInputSource inputSource(XStr(file.filePath().c_str()).unicodeForm());
|
||||
#endif
|
||||
return LoadDocument(inputSource);
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "An error occurred during parsing\n " << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ParameterManager::LoadDocument(const XERCES_CPP_NAMESPACE_QUALIFIER InputSource& inputSource)
|
||||
{
|
||||
//
|
||||
// Create our parser, then attach an error handler to the parser.
|
||||
// The parser will call back to methods of the ErrorHandler if it
|
||||
|
@ -1102,11 +1119,7 @@ int ParameterManager::LoadDocument(const char* sFileName)
|
|||
//
|
||||
bool errorsOccured = false;
|
||||
try {
|
||||
#if defined (FC_OS_WIN32)
|
||||
parser->parse((XMLCh*)file.toStdWString().c_str());
|
||||
#else
|
||||
parser->parse(file.filePath().c_str());
|
||||
#endif
|
||||
parser->parse(inputSource);
|
||||
}
|
||||
|
||||
catch (const XMLException& e) {
|
||||
|
@ -1152,10 +1165,36 @@ int ParameterManager::LoadDocument(const char* sFileName)
|
|||
}
|
||||
|
||||
void ParameterManager::SaveDocument(const char* sFileName) const
|
||||
{
|
||||
Base::FileInfo file(sFileName);
|
||||
|
||||
try {
|
||||
//
|
||||
// Plug in a format target to receive the resultant
|
||||
// XML stream from the serializer.
|
||||
//
|
||||
// LocalFileFormatTarget prints the resultant XML stream
|
||||
// to a file once it receives any thing from the serializer.
|
||||
//
|
||||
#if defined (FC_OS_WIN32)
|
||||
XMLFormatTarget *myFormTarget = new LocalFileFormatTarget ((XMLCh*)file.toStdWString().c_str());
|
||||
#else
|
||||
XMLFormatTarget *myFormTarget = new LocalFileFormatTarget (file.filePath().c_str());
|
||||
#endif
|
||||
SaveDocument(myFormTarget);
|
||||
delete myFormTarget;
|
||||
}
|
||||
catch (XMLException& e) {
|
||||
std::cerr << "An error occurred during creation of output transcoder. Msg is:"
|
||||
<< std::endl
|
||||
<< StrX(e.getMessage()) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterManager::SaveDocument(XMLFormatTarget* pFormatTarget) const
|
||||
{
|
||||
#if (XERCES_VERSION_MAJOR == 2)
|
||||
DOMPrintFilter *myFilter = 0;
|
||||
Base::FileInfo file(sFileName);
|
||||
|
||||
try {
|
||||
// get a serializer, an instance of DOMWriter
|
||||
|
@ -1199,31 +1238,17 @@ void ParameterManager::SaveDocument(const char* sFileName) const
|
|||
if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint))
|
||||
theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint);
|
||||
|
||||
//
|
||||
// Plug in a format target to receive the resultant
|
||||
// XML stream from the serializer.
|
||||
//
|
||||
// LocalFileFormatTarget prints the resultant XML stream
|
||||
// to a file once it receives any thing from the serializer.
|
||||
//
|
||||
#if defined (FC_OS_WIN32)
|
||||
XMLFormatTarget *myFormTarget = new LocalFileFormatTarget ((XMLCh*)file.toStdWString().c_str());
|
||||
#else
|
||||
XMLFormatTarget *myFormTarget = new LocalFileFormatTarget (file.filePath().c_str());
|
||||
#endif
|
||||
|
||||
//
|
||||
// do the serialization through DOMWriter::writeNode();
|
||||
//
|
||||
theSerializer->writeNode(myFormTarget, *_pDocument);
|
||||
theSerializer->writeNode(pFormatTarget, *_pDocument);
|
||||
|
||||
delete theSerializer;
|
||||
|
||||
//
|
||||
// Filter, formatTarget and error handler
|
||||
// Filter and error handler
|
||||
// are NOT owned by the serializer.
|
||||
//
|
||||
delete myFormTarget;
|
||||
delete myErrorHandler;
|
||||
|
||||
if (gUseFilter)
|
||||
|
@ -1236,8 +1261,6 @@ void ParameterManager::SaveDocument(const char* sFileName) const
|
|||
<< StrX(e.getMessage()) << std::endl;
|
||||
}
|
||||
#else
|
||||
Base::FileInfo file(sFileName);
|
||||
|
||||
try {
|
||||
// get a serializer, an instance of DOMWriter
|
||||
XMLCh tempStr[100];
|
||||
|
@ -1250,70 +1273,15 @@ void ParameterManager::SaveDocument(const char* sFileName) const
|
|||
DOMConfiguration* config = theSerializer->getDomConfig();
|
||||
config->setParameter(XStr("format-pretty-print").unicodeForm(),true);
|
||||
|
||||
// plug in user's own filter
|
||||
if (gUseFilter) {
|
||||
// even we say to show attribute, but the DOMWriter
|
||||
// will not show attribute nodes to the filter as
|
||||
// the specs explicitly says that DOMWriter shall
|
||||
// NOT show attributes to DOMWriterFilter.
|
||||
//
|
||||
// so DOMNodeFilter::SHOW_ATTRIBUTE has no effect.
|
||||
// same DOMNodeFilter::SHOW_DOCUMENT_TYPE, no effect.
|
||||
//
|
||||
// myFilter = new DOMPrintFilter(DOMNodeFilter::SHOW_ELEMENT |
|
||||
// DOMNodeFilter::SHOW_ATTRIBUTE |
|
||||
// DOMNodeFilter::SHOW_DOCUMENT_TYPE
|
||||
// );
|
||||
// theSerializer->setFilter(myFilter);
|
||||
}
|
||||
|
||||
// plug in user's own error handler
|
||||
DOMErrorHandler *myErrorHandler = new DOMPrintErrorHandler();
|
||||
// theSerializer->setErrorHandler(myErrorHandler);
|
||||
|
||||
// set feature if the serializer supports the feature/mode
|
||||
// if (theSerializer->canSetFeature(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections))
|
||||
// theSerializer->setFeature(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections);
|
||||
|
||||
// if (theSerializer->canSetFeature(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent))
|
||||
// theSerializer->setFeature(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent);
|
||||
|
||||
// if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint))
|
||||
// theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint);
|
||||
|
||||
//
|
||||
// Plug in a format target to receive the resultant
|
||||
// XML stream from the serializer.
|
||||
//
|
||||
// LocalFileFormatTarget prints the resultant XML stream
|
||||
// to a file once it receives any thing from the serializer.
|
||||
//
|
||||
#if defined (FC_OS_WIN32)
|
||||
XMLFormatTarget *myFormTarget = new LocalFileFormatTarget ((XMLCh*)file.toStdWString().c_str());
|
||||
#else
|
||||
XMLFormatTarget *myFormTarget = new LocalFileFormatTarget (file.filePath().c_str());
|
||||
#endif
|
||||
|
||||
//
|
||||
// do the serialization through DOMWriter::writeNode();
|
||||
//
|
||||
DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput();
|
||||
theOutput->setEncoding(gOutputEncoding);
|
||||
theOutput->setByteStream(myFormTarget);
|
||||
theOutput->setByteStream(pFormatTarget);
|
||||
theSerializer->write(_pDocument, theOutput);
|
||||
|
||||
delete theSerializer;
|
||||
|
||||
//
|
||||
// Filter, formatTarget and error handler
|
||||
// are NOT owned by the serializer.
|
||||
//
|
||||
delete myFormTarget;
|
||||
delete myErrorHandler;
|
||||
|
||||
// if (gUseFilter)
|
||||
// delete myFilter;
|
||||
|
||||
}
|
||||
catch (XMLException& e) {
|
||||
std::cerr << "An error occurred during creation of output transcoder. Msg is:"
|
||||
|
@ -1327,6 +1295,7 @@ void ParameterManager::CreateDocument(void)
|
|||
{
|
||||
// creating a document from screatch
|
||||
DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(XStr("Core").unicodeForm());
|
||||
delete _pDocument;
|
||||
_pDocument = impl->createDocument(
|
||||
0, // root element namespace URI.
|
||||
XStr("FCParameters").unicodeForm(), // root element name
|
||||
|
@ -1337,11 +1306,8 @@ void ParameterManager::CreateDocument(void)
|
|||
_pGroupNode = _pDocument->createElement(XStr("FCParamGroup").unicodeForm());
|
||||
((DOMElement*)_pGroupNode)->setAttribute(XStr("Name").unicodeForm(), XStr("Root").unicodeForm());
|
||||
rootElem->appendChild(_pGroupNode);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ParameterManager::CheckDocument() const
|
||||
{
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ XERCES_CPP_NAMESPACE_BEGIN
|
|||
class DOMNode;
|
||||
class DOMElement;
|
||||
class DOMDocument;
|
||||
class XMLFormatTarget;
|
||||
class InputSource;
|
||||
XERCES_CPP_NAMESPACE_END
|
||||
|
||||
class ParameterManager;
|
||||
|
@ -266,13 +268,11 @@ public:
|
|||
static void Init(void);
|
||||
|
||||
int LoadDocument(const char* sFileName);
|
||||
|
||||
int LoadDocument(const XERCES_CPP_NAMESPACE_QUALIFIER InputSource&);
|
||||
bool LoadOrCreateDocument(const char* sFileName);
|
||||
|
||||
void SaveDocument(const char* sFileName) const;
|
||||
|
||||
void SaveDocument(XERCES_CPP_NAMESPACE_QUALIFIER XMLFormatTarget* pFormatTarget) const;
|
||||
void CreateDocument(void);
|
||||
|
||||
void CheckDocument() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#include <xercesc/dom/DOMText.hpp>
|
||||
#include <xercesc/framework/StdOutFormatTarget.hpp>
|
||||
#include <xercesc/framework/LocalFileFormatTarget.hpp>
|
||||
#include <xercesc/framework/LocalFileInputSource.hpp>
|
||||
#include <xercesc/parsers/XercesDOMParser.hpp>
|
||||
#include <xercesc/util/XMLUni.hpp>
|
||||
#include <xercesc/util/XMLUniDefs.hpp>
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <sstream>
|
||||
# include <locale>
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
# include <QTime>
|
||||
|
@ -122,6 +124,24 @@ std::string Base::Tools::getIdentifier(const std::string& name)
|
|||
return CleanName;
|
||||
}
|
||||
|
||||
std::wstring Base::Tools::widen(const std::string& str)
|
||||
{
|
||||
std::wostringstream wstm;
|
||||
const std::ctype<wchar_t>& ctfacet = std::use_facet< std::ctype<wchar_t> >(wstm.getloc());
|
||||
for (size_t i=0; i<str.size(); ++i)
|
||||
wstm << ctfacet.widen(str[i]);
|
||||
return wstm.str();
|
||||
}
|
||||
|
||||
std::string Base::Tools::narrow(const std::wstring& str)
|
||||
{
|
||||
std::ostringstream stm;
|
||||
const std::ctype<char>& ctfacet = std::use_facet< std::ctype<char> >(stm.getloc());
|
||||
for (size_t i=0; i<str.size(); ++i)
|
||||
stm << ctfacet.narrow(str[i], 0);
|
||||
return stm.str();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using namespace Base;
|
||||
|
|
|
@ -151,6 +151,8 @@ struct BaseExport Tools
|
|||
static std::string getUniqueName(const std::string&, const std::vector<std::string>&,int d=0);
|
||||
static std::string addNumber(const std::string&, unsigned int, int d=0);
|
||||
static std::string getIdentifier(const std::string&);
|
||||
static std::wstring widen(const std::string& str);
|
||||
static std::string narrow(const std::wstring& str);
|
||||
};
|
||||
|
||||
} // namespace Base
|
||||
|
|
|
@ -88,7 +88,7 @@ void Uuid::setValue(const char* sString)
|
|||
|
||||
void Uuid::setValue(const std::string &sString)
|
||||
{
|
||||
setValue(sString.c_str());
|
||||
setValue(sString.c_str());
|
||||
}
|
||||
|
||||
const std::string& Uuid::getValue(void) const
|
||||
|
|
9
src/Doc/sphinx/Document.rst
Normal file
9
src/Doc/sphinx/Document.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
The FreeCAD Document
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: DocumentObject
|
||||
|
||||
|
18
src/Doc/sphinx/DocumentObject.rst
Normal file
18
src/Doc/sphinx/DocumentObject.rst
Normal file
|
@ -0,0 +1,18 @@
|
|||
The FreeCAD Document Object
|
||||
===========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: DocumentObject
|
||||
|
||||
.. autoclass:: DocumentObject
|
||||
:members:
|
||||
|
||||
.. method:: __setstate__(value)
|
||||
|
||||
allows to save custom attributes of this object as strings, so they can be saved when saving the FreeCAD document
|
||||
|
||||
.. method:: __getstate__()
|
||||
|
||||
reads values previously saved with __setstate__()
|
|
@ -1,5 +1,5 @@
|
|||
The Draft module
|
||||
================
|
||||
Draft module
|
||||
============
|
||||
|
||||
The Draft module offer several convenient functions to work with simple objects.
|
||||
|
||||
|
@ -8,19 +8,3 @@ The Draft module offer several convenient functions to work with simple objects.
|
|||
|
||||
.. automodule:: Draft
|
||||
:members:
|
||||
|
||||
.. automodule:: DraftSnap
|
||||
:members:
|
||||
|
||||
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:: DraftVecUtils
|
||||
:members:
|
||||
|
||||
.. 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:
|
||||
|
|
10
src/Doc/sphinx/DraftGeomUtils.rst
Normal file
10
src/Doc/sphinx/DraftGeomUtils.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
Draft Geometry Utilities
|
||||
========================
|
||||
|
||||
The DraftGeomUtils module offer tools to manipulate Part geometry.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: DraftGeomUtils
|
||||
:members:
|
10
src/Doc/sphinx/DraftSnap.rst
Normal file
10
src/Doc/sphinx/DraftSnap.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
Draft Snapper
|
||||
=============
|
||||
|
||||
The Draft Snapper manages object snapping in Draft and Arch modules.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: DraftSnap
|
||||
:members:
|
10
src/Doc/sphinx/DraftTrackers.rst
Normal file
10
src/Doc/sphinx/DraftTrackers.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
Draft Trackers
|
||||
==============
|
||||
|
||||
Different trackers (temporary screen widgets) used in the Draft and Arch modules.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: DraftTrackers
|
||||
:members:
|
10
src/Doc/sphinx/DraftVecUtils.rst
Normal file
10
src/Doc/sphinx/DraftVecUtils.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
Draft Vector Utilities
|
||||
======================
|
||||
|
||||
The DraftVecUtils module offer several convenient utilities to deal with vectors
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: DraftVecUtils
|
||||
:members:
|
|
@ -7,14 +7,5 @@ The FreeCAD module
|
|||
.. automodule:: FreeCAD
|
||||
:members:
|
||||
|
||||
.. autoclass:: Vector
|
||||
:members:
|
||||
|
||||
.. autoclass:: Matrix
|
||||
:members:
|
||||
|
||||
.. autoclass:: Placement
|
||||
:members:
|
||||
|
||||
.. autoclass:: Console
|
||||
:members:
|
||||
|
|
10
src/Doc/sphinx/Matrix.rst
Normal file
10
src/Doc/sphinx/Matrix.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
The Matrix object
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: FreeCAD
|
||||
|
||||
.. autoclass:: Matrix
|
||||
:members:
|
10
src/Doc/sphinx/Placement.rst
Normal file
10
src/Doc/sphinx/Placement.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
The Placement object
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: FreeCAD
|
||||
|
||||
.. autoclass:: Placement
|
||||
:members:
|
10
src/Doc/sphinx/Vector.rst
Normal file
10
src/Doc/sphinx/Vector.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
The Vector object
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: FreeCAD
|
||||
|
||||
.. autoclass:: Vector
|
||||
:members:
|
10
src/Doc/sphinx/ViewProvider.rst
Normal file
10
src/Doc/sphinx/ViewProvider.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
The View Provider object
|
||||
========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
.. automodule:: DocumentObject
|
||||
|
||||
.. autoclass:: ViewProvider
|
||||
:members:
|
|
@ -1,526 +1,100 @@
|
|||
/* FreeCAD CSS template by Yorik */
|
||||
|
||||
/* general settings ******************************* */
|
||||
|
||||
a, #bodyContent a.external {
|
||||
color: #0092E8;
|
||||
}
|
||||
|
||||
a.new, .new a, #p-cactions .new a, #p-personal a.new {
|
||||
color: #FF1F00;
|
||||
}
|
||||
|
||||
h1 {
|
||||
background: #0092E8;
|
||||
border: none;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 90%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
border: 1px solid #AAAAAA;
|
||||
background: #EEEEEE;
|
||||
}
|
||||
|
||||
.docnav {
|
||||
background: #D3D7D9;
|
||||
padding: 3px;
|
||||
border: none;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.languages {
|
||||
font-size: 9px;
|
||||
padding:2px 5px;
|
||||
color: #666666;
|
||||
border: none;
|
||||
border-top: 1px solid #666666;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#bodyContent a[href^="https://"], .link-https {
|
||||
padding: 0 16px 0 0;
|
||||
}
|
||||
|
||||
/* homepage ******************************* */
|
||||
|
||||
body[class*='page-Main_Page'] {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] h1 {
|
||||
background: none;
|
||||
margin-bottom: 0;
|
||||
border-bottom: 1px solid #638C9C;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] h2 {
|
||||
color: #FFF;
|
||||
border-bottom: none;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] h3 {
|
||||
color: white;
|
||||
font-size: 105%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] h1 .mw-headline {
|
||||
font-size: 2em;
|
||||
letter-spacing: 20px;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] #bodyContent a:visited {
|
||||
color: #0092E8;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] h1.firstHeading {
|
||||
display:none;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] #content {
|
||||
background: transparent;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body[class*='page-Main_Page'] #content ul {
|
||||
list-style-type: none;
|
||||
list-style-image: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* homepage toolboxes & menus ******************************** */
|
||||
|
||||
.main-toolbox {
|
||||
float: right;
|
||||
width: 300px;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: table;
|
||||
}
|
||||
|
||||
#feedholder, #mantisholder, .sidebox, #fbholder {
|
||||
max-width: 300px;
|
||||
border: 1px solid #AAAAAA;
|
||||
background-color:#EEEEEE;
|
||||
padding:1.2em;
|
||||
color: black;
|
||||
margin-top: 10px;
|
||||
font-size: 0.85em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#feedholder .title, #mantisholder .title, .sidebox .title {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#feedholder .title a, #mantisholder .title a, .sidebox .title a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#fbholder {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.downloadbox {
|
||||
background: white url(/userapps/mediawiki/yorikvanhavre/nfs/user/y/yo/yorikvanhavre/6/65/Download.jpg) top left no-repeat;
|
||||
padding: 10px 10px 10px 80px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
text-align: left;
|
||||
margin-bottom: 15px;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#bodyContent .downloadbox li a.external {
|
||||
display: box;
|
||||
color: #005295;
|
||||
padding: 3px 13px 3px 3px;
|
||||
}
|
||||
|
||||
/* wikibars ******************************** */
|
||||
|
||||
#p-cactions {
|
||||
padding: 0 60px;
|
||||
/* top: 3px; */
|
||||
width: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#p-cactions li, #p-cactions li a, #p-personal li a {
|
||||
color: #0092E8;
|
||||
background: none;
|
||||
padding: 1px 5px !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
#globalWrapper {
|
||||
background: #171a2a url(/userapps/mediawiki/yorikvanhavre/nfs/user/y/yo/yorikvanhavre/1/1f/Background.jpg) top left no-repeat !important;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
width: auto !important;
|
||||
margin:5px;
|
||||
}
|
||||
|
||||
.portlet {
|
||||
width: auto;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.pBody {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0 }
|
||||
|
||||
.pBody a {
|
||||
color: white;
|
||||
padding: 1px 5px !important;
|
||||
}
|
||||
|
||||
.portlet ul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.portlet li {
|
||||
margin-left: 5px;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#column-one {
|
||||
margin-left: 3px;
|
||||
padding-top: 160px;
|
||||
}
|
||||
|
||||
#p-cactions li a:hover, #p-personal li a:hover, #p-cactions li.selected a, #bodyContent .downloadbox li a.external:hover {
|
||||
color: white;
|
||||
background: #0092E8;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* content ******************************** */
|
||||
|
||||
#column-content {
|
||||
margin:0 0 0.6em -12.2em !important;
|
||||
padding: 5px;
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
#content {
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
}
|
||||
|
||||
#content, #p-cactions li {
|
||||
border: none;
|
||||
padding: 0.6em 1em 1em;
|
||||
}
|
||||
|
||||
#footer {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* sidebar ******************************** */
|
||||
|
||||
.portlet h5 {
|
||||
color: #638C9C;
|
||||
text-transform: uppercase;
|
||||
font-size: 75%;
|
||||
height: 15px;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #638C9C;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#p- h5 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#p-search, #p-Documentation, #p-tb, #p-languages, #p-Meta, #p-Feedback, #p-Manual {
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
#n-Basic, #n-Advanced, #n-Development, #n-Using-FreeCAD, #n-Python-Scripting {
|
||||
list-style: none;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
#n-Home {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/9/9a/Home.png);
|
||||
}
|
||||
|
||||
#n-Features {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/5/53/Features16.png);
|
||||
}
|
||||
|
||||
#n-Screenshots {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/e/ef/Screenshots16.png);
|
||||
}
|
||||
|
||||
#n-Downloads {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/e/ed/Download16.png);
|
||||
}
|
||||
|
||||
#n-Getting-Started {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/b/b4/Gettingstarted16.png);
|
||||
}
|
||||
|
||||
#n-FAQ {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/8/86/Faq16.png);
|
||||
}
|
||||
|
||||
#n-Forum {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/6/6a/Forum16.png);
|
||||
}
|
||||
|
||||
#n-Tutorials {
|
||||
list-style-image: url(/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/4/46/Tutorials.png);
|
||||
}
|
||||
|
||||
/* Commands Template******************* */
|
||||
|
||||
.ct {
|
||||
padding: 5px;
|
||||
background: #eeeeee;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
margin: 5px 0 15px 8px;
|
||||
}
|
||||
|
||||
.ctEven {
|
||||
background-color:#F9F9F9;
|
||||
border:1px solid #AAAAAA;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.ctToc .toc {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* API ******************************** */
|
||||
|
||||
.api {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.api .function, dl dt {
|
||||
padding: 3px 2px 3px 20px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
dl.class dt {
|
||||
background: #dddddd url("http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/0/0f/Class.png") left center no-repeat;
|
||||
}
|
||||
|
||||
dl.function dt, dl.method dt {
|
||||
background: #dddddd url("http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/2/20/Method.png") left center no-repeat;
|
||||
}
|
||||
|
||||
dl.attribute dt {
|
||||
background: #dddddd url("http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/4/47/Property.png") left center no-repeat;
|
||||
}
|
||||
|
||||
dl dt tt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dl dt big {
|
||||
margin: 0 3px 0 3px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.api .description {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background: #ffffff !important;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.highlight pre {
|
||||
margin-left: 30px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
/* Screenshots ************************ */
|
||||
|
||||
.screenthumbs {
|
||||
padding: 5px;
|
||||
background: #eeeeee;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
/* Translations *********************** */
|
||||
|
||||
body[class*='_it'] h1.firstHeading, body[class*='_fr'] h1.firstHeading {
|
||||
display:none;
|
||||
}
|
||||
|
||||
h1 .editsection a:link {
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Charts *********************** */
|
||||
|
||||
.orgchart {
|
||||
margin: 10px;
|
||||
background: #EEEEEE;
|
||||
text-align: center;
|
||||
width: 800px;
|
||||
padding: 4px;
|
||||
border-radius: 5px;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.orgheader {
|
||||
background: #9FBDE0;
|
||||
}
|
||||
|
||||
.orgchart td {
|
||||
padding: 0;
|
||||
}
|
||||
/* Printing ************************ */
|
||||
|
||||
@media print {
|
||||
/* FreeCAD sphinx CSS file */
|
||||
|
||||
body {
|
||||
font: small sans-serif;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
a{
|
||||
color: blue;
|
||||
}
|
||||
|
||||
h1 {
|
||||
background: none;
|
||||
border: none;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#globalWrapper {
|
||||
backgound: none;
|
||||
}
|
||||
|
||||
#column-content {
|
||||
margin:0 !important;
|
||||
padding: 5px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.docnav, .languages, #sf_header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.toc {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.thumbcaption {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
background: #191b26;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
color: #eee;
|
||||
opacity: 0.9;
|
||||
text-align: justify;
|
||||
/* font-size: 0.9em; */
|
||||
}
|
||||
|
||||
/* sphinx-specific *****************************/
|
||||
|
||||
body {
|
||||
background: #171a2a url(http://www.sourceforge.net/userapps/mediawiki/yorikvanhavre/nfs/user/y/yo/yorikvanhavre/1/1f/Background.jpg) top left no-repeat !important;
|
||||
font-family: sans-serif;
|
||||
color: #ffffff;
|
||||
a {
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
color: #0F3472;
|
||||
}
|
||||
|
||||
.document {
|
||||
background: url(http://sourceforge.net/apps/mediawiki/free-cad/nfs/project/f/fr/free-cad/7/70/MediaWikiSidebarLogo.png) top left no-repeat;
|
||||
a img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.related ul {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.related ul li {
|
||||
display: inline;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.documentwrapper {
|
||||
color: #000000;
|
||||
background: none repeat scroll 0 0 white;
|
||||
border-radius: 5px;
|
||||
padding: 0.6em;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
float: right;
|
||||
width: 75%
|
||||
}
|
||||
|
||||
.sphinxsidebar {
|
||||
font-size: 0.8em;
|
||||
width: 220px;
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
.clearer {
|
||||
clear: both;
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.footer {
|
||||
clear: both;
|
||||
font-size: 0.7em;
|
||||
text-align: center;
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
background: url("/images/freecad.png") top left no-repeat;
|
||||
color: #000;
|
||||
padding-left: 40px;
|
||||
border-bottom: 1px solid #444;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 18px;
|
||||
margin: 30px 0 0 0;
|
||||
}
|
||||
|
||||
.document {
|
||||
background-color: #eee;
|
||||
display: table;
|
||||
width: 960px;
|
||||
box-shadow: 0 0 5px #000;
|
||||
padding: 10px;
|
||||
margin: auto;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.related {
|
||||
margin: auto;
|
||||
width: 960px;
|
||||
}
|
||||
|
||||
.related a {
|
||||
color: #1E90FF;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin: auto;
|
||||
width: 960px;
|
||||
}
|
||||
|
||||
.descname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.function, .attribute, .method {
|
||||
border-bottom: 1px solid #bbb;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
.document {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.related {
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
{{ _('Enter search terms or a module, class or function name.') }}
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://free-cad.sf.net">Go back to the FreeCAD wiki</a>
|
||||
<a href="http://www.freecadweb.org">Go back to the FreeCAD homepage</a>
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
|
|
|
@ -53,6 +53,11 @@ elif commands.getstatusoutput("locate FreeCAD/lib")[0] == 0:
|
|||
path = commands.getstatusoutput("locate FreeCAD/lib")[1].split()[0]
|
||||
sys.path.append(path)
|
||||
|
||||
# locate TemplatePyMod
|
||||
if commands.getstatusoutput("locate TemplatePyMod")[0] == 0:
|
||||
path = commands.getstatusoutput("locate TemplatePyMod")[1].split()[0]
|
||||
sys.path.append(path)
|
||||
|
||||
import FreeCAD, FreeCADGui
|
||||
FreeCADGui.showMainWindow() # this is needed for complete import of GUI modules
|
||||
|
||||
|
@ -86,9 +91,9 @@ copyright = u'2011, Jürgen Riegel, Werner Mayer, Yorik van Havre'
|
|||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.12'
|
||||
version = '0.13'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.12'
|
||||
release = '0.13'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -155,7 +160,7 @@ html_title = "FreeCAD API documentation"
|
|||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
|
|
|
@ -13,11 +13,21 @@ This is the complete python API reference of the FreeCAD appication
|
|||
|
||||
FreeCAD.rst
|
||||
FreeCADGui.rst
|
||||
Vector.rst
|
||||
Placement.rst
|
||||
Matrix.rst
|
||||
Document.rst
|
||||
DocumentObject.rst
|
||||
ViewProvider.rst
|
||||
Mesh.rst
|
||||
Part.rst
|
||||
Sketch.rst
|
||||
PartDesign.rst
|
||||
Draft.rst
|
||||
DraftVecUtils.rst
|
||||
DraftGeomUtils.rst
|
||||
DraftTrackers.rst
|
||||
DraftSnap.rst
|
||||
Arch.rst
|
||||
Drawing.rst
|
||||
RayTracing.rst
|
||||
|
@ -25,5 +35,4 @@ This is the complete python API reference of the FreeCAD appication
|
|||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
* `Go back to the FreeCAD wiki <http://free-cad.sf.net>`_
|
||||
* `FreeCAD homepage <http://www.freecadweb.org>`_
|
||||
|
|
|
@ -800,19 +800,19 @@ Gui::Document* Application::getDocument(const App::Document* pDoc) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Application::showViewProvider(App::DocumentObject* obj)
|
||||
void Application::showViewProvider(const App::DocumentObject* obj)
|
||||
{
|
||||
ViewProvider* vp = getViewProvider(obj);
|
||||
if (vp) vp->show();
|
||||
}
|
||||
|
||||
void Application::hideViewProvider(App::DocumentObject* obj)
|
||||
void Application::hideViewProvider(const App::DocumentObject* obj)
|
||||
{
|
||||
ViewProvider* vp = getViewProvider(obj);
|
||||
if (vp) vp->hide();
|
||||
}
|
||||
|
||||
Gui::ViewProvider* Application::getViewProvider(App::DocumentObject* obj) const
|
||||
Gui::ViewProvider* Application::getViewProvider(const App::DocumentObject* obj) const
|
||||
{
|
||||
App::Document* doc = obj->getDocument();
|
||||
if (doc) {
|
||||
|
|
|
@ -148,11 +148,11 @@ public:
|
|||
*/
|
||||
Gui::Document* getDocument(const App::Document* pDoc) const;
|
||||
/// Shows the associated view provider of the given object
|
||||
void showViewProvider(App::DocumentObject*);
|
||||
void showViewProvider(const App::DocumentObject*);
|
||||
/// Hides the associated view provider of the given object
|
||||
void hideViewProvider(App::DocumentObject*);
|
||||
void hideViewProvider(const App::DocumentObject*);
|
||||
/// Get the view provider of the given object
|
||||
Gui::ViewProvider* getViewProvider(App::DocumentObject*) const;
|
||||
Gui::ViewProvider* getViewProvider(const App::DocumentObject*) const;
|
||||
//@}
|
||||
|
||||
/// true when the application shuting down
|
||||
|
|
|
@ -576,6 +576,7 @@ SOURCE_GROUP("Widget\\iisTaskPanel\\Mocs" FILES ${iis_MOC_SRCS})
|
|||
# The 3d view
|
||||
SET(View3D_CPP_SRCS
|
||||
Flag.cpp
|
||||
GLPainter.cpp
|
||||
MouseSelection.cpp
|
||||
NavigationStyle.cpp
|
||||
InventorNavigationStyle.cpp
|
||||
|
@ -592,6 +593,7 @@ SET(View3D_CPP_SRCS
|
|||
SET(View3D_SRCS
|
||||
${View3D_CPP_SRCS}
|
||||
Flag.h
|
||||
GLPainter.h
|
||||
MouseSelection.h
|
||||
NavigationStyle.h
|
||||
SplitView3DInventor.h
|
||||
|
|
|
@ -184,7 +184,7 @@ public:
|
|||
/// Get pointer to the Application Window
|
||||
static Application* getGuiApplication(void);
|
||||
/// Get a reference to the selection
|
||||
Gui::SelectionSingleton& getSelection(void);
|
||||
static Gui::SelectionSingleton& getSelection(void);
|
||||
/// Get pointer to the active gui document
|
||||
Gui::Document* getActiveGuiDocument(void) const;
|
||||
/** Get pointer to the named or active App document
|
||||
|
|
|
@ -1437,10 +1437,16 @@ void StdCmdToggleNavigation::activated(int iMsg)
|
|||
|
||||
bool StdCmdToggleNavigation::isActive(void)
|
||||
{
|
||||
//#0001087: Inventor Navigation continues with released Mouse Button
|
||||
//This happens because 'Esc' is also used to close the task dialog.
|
||||
//Add also new method 'isRedirectToSceneGraphEnabled' to explicitly
|
||||
//check if this is allowed.
|
||||
if (Gui::Control().activeDialog())
|
||||
return false;
|
||||
Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
|
||||
if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
|
||||
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
|
||||
return viewer->isEditing();
|
||||
return viewer->isEditing() && viewer->isRedirectToSceneGraphEnabled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -82,15 +82,18 @@ DlgParameterImp::DlgParameterImp( QWidget* parent, Qt::WFlags fl )
|
|||
qApp->translate( "Gui::Dialog::DlgParameterImp", "User parameter" );
|
||||
#endif
|
||||
|
||||
const std::map<std::string,ParameterManager *> rcList = App::GetApplication().GetParameterSetList();
|
||||
ParameterManager* sys = App::GetApplication().GetParameterSet("System parameter");
|
||||
const std::map<std::string,ParameterManager *>& rcList = App::GetApplication().GetParameterSetList();
|
||||
for (std::map<std::string,ParameterManager *>::const_iterator it= rcList.begin();it!=rcList.end();++it) {
|
||||
parameterSet->addItem(tr(it->first.c_str()), QVariant(QByteArray(it->first.c_str())));
|
||||
if (it->second != sys) // for now ignore system parameters because they are nowhere used
|
||||
parameterSet->addItem(tr(it->first.c_str()), QVariant(QByteArray(it->first.c_str())));
|
||||
}
|
||||
|
||||
QByteArray cStr("User parameter");
|
||||
parameterSet->setCurrentIndex(parameterSet->findData(cStr));
|
||||
onChangeParameterSet(parameterSet->currentIndex());
|
||||
parameterSet->hide();
|
||||
if (parameterSet->count() < 2)
|
||||
parameterSet->hide();
|
||||
|
||||
connect(parameterSet, SIGNAL(activated(int)),
|
||||
this, SLOT(onChangeParameterSet(int)));
|
||||
|
@ -238,6 +241,13 @@ void DlgParameterImp::onChangeParameterSet(int index)
|
|||
if (!rcParMngr)
|
||||
return;
|
||||
|
||||
if (rcParMngr == App::GetApplication().GetParameterSet("System parameter"))
|
||||
buttonSaveToDisk->setEnabled(true);
|
||||
else if (rcParMngr == App::GetApplication().GetParameterSet("User parameter"))
|
||||
buttonSaveToDisk->setEnabled(true);
|
||||
else
|
||||
buttonSaveToDisk->setEnabled(false);
|
||||
|
||||
// remove all labels
|
||||
paramGroup->clear();
|
||||
paramValue->clear();
|
||||
|
@ -282,18 +292,19 @@ void DlgParameterImp::onChangeParameterSet(int index)
|
|||
|
||||
if (parent)
|
||||
paramGroup->setCurrentItem(parent);
|
||||
else if (paramGroup->topLevelItemCount() > 0)
|
||||
paramGroup->setCurrentItem(paramGroup->topLevelItem(0));
|
||||
}
|
||||
|
||||
void DlgParameterImp::on_buttonSaveToDisk_clicked()
|
||||
{
|
||||
ParameterManager* sys = App::GetApplication().GetParameterSet("System parameter");
|
||||
if (sys) {
|
||||
sys->SaveDocument(App::Application::Config()["SystemParameter"].c_str());
|
||||
}
|
||||
ParameterManager* user = App::GetApplication().GetParameterSet("User parameter");
|
||||
if (user) {
|
||||
user->SaveDocument(App::Application::Config()["UserParameter"].c_str());
|
||||
}
|
||||
int index = parameterSet->currentIndex();
|
||||
ParameterManager* parmgr = App::GetApplication().GetParameterSet(parameterSet->itemData(index).toByteArray());
|
||||
if (!parmgr) return;
|
||||
if (parmgr == App::GetApplication().GetParameterSet("System parameter"))
|
||||
parmgr->SaveDocument(App::Application::Config()["SystemParameter"].c_str());
|
||||
else if (parmgr == App::GetApplication().GetParameterSet("User parameter"))
|
||||
parmgr->SaveDocument(App::Application::Config()["UserParameter"].c_str());
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
|
|
|
@ -270,7 +270,7 @@ PyObject* DocumentPy::toggleTreeItem(PyObject *args)
|
|||
Gui::ViewProviderDocumentObject* ActiveVp = dynamic_cast<Gui::ViewProviderDocumentObject*> (getDocumentPtr()->getViewProvider(Object)) ;
|
||||
switch(mod) {
|
||||
case 0: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Toggle); break;
|
||||
case 1: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Collaps); break;
|
||||
case 1: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Collapse); break;
|
||||
case 2: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Expand); break;
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +278,6 @@ PyObject* DocumentPy::toggleTreeItem(PyObject *args)
|
|||
Py_Return;
|
||||
}
|
||||
|
||||
|
||||
Py::Object DocumentPy::getActiveObject(void) const
|
||||
{
|
||||
App::DocumentObject *object = getDocumentPtr()->getDocument()->getActiveObject();
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
# include <QMouseEvent>
|
||||
#endif
|
||||
#include <Inventor/SbVec2s.h>
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "GLPainter.h"
|
||||
|
||||
#include "Flag.h"
|
||||
|
||||
|
@ -192,7 +194,7 @@ const SbVec3f& Flag::getOrigin() const
|
|||
return this->coord;
|
||||
}
|
||||
|
||||
void Flag::drawLine (int tox, int toy)
|
||||
void Flag::drawLine (View3DInventorViewer* v, int tox, int toy)
|
||||
{
|
||||
if (!isVisible())
|
||||
return;
|
||||
|
@ -204,50 +206,17 @@ void Flag::drawLine (int tox, int toy)
|
|||
int fromy = pos().y() + height()/2;
|
||||
if (false) fromx += width();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, view[0], 0, view[1], -1, 1);
|
||||
|
||||
// Store GL state
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
GLfloat depthrange[2];
|
||||
glGetFloatv(GL_DEPTH_RANGE, depthrange);
|
||||
GLdouble projectionmatrix[16];
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix);
|
||||
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthRange(0,0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glColor4f(1.0, 1.0, 1.0, 0.0);
|
||||
glViewport(0, 0, view[0], view[1]);
|
||||
GLPainter p;
|
||||
p.begin(v);
|
||||
p.setDrawBuffer(GL_BACK);
|
||||
|
||||
// the line
|
||||
glLineWidth(1.0f);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3i(fromx, view[1]-fromy, 0);
|
||||
glVertex3i(tox , view[1]-toy , 0);
|
||||
glEnd();
|
||||
|
||||
glPointSize(3.0f);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3i(tox , view[1]-toy , 0);
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
|
||||
// Reset original state
|
||||
glDepthRange(depthrange[0], depthrange[1]);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixd(projectionmatrix);
|
||||
|
||||
glPopAttrib();
|
||||
glPopMatrix();
|
||||
p.setLineWidth(1.0f);
|
||||
p.drawLine(fromx, fromy, tox, toy);
|
||||
// the point
|
||||
p.setPointSize(3.0f);
|
||||
p.drawPoint(tox, toy);
|
||||
p.end();
|
||||
}
|
||||
|
||||
void Flag::setText(const QString& t)
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <Inventor/SbVec3f.h>
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class View3DInventorViewer;
|
||||
/**
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
|
@ -47,7 +47,7 @@ public:
|
|||
QSize sizeHint() const;
|
||||
void setOrigin(const SbVec3f&);
|
||||
const SbVec3f& getOrigin() const;
|
||||
void drawLine(int tox, int toy);
|
||||
void drawLine(Gui::View3DInventorViewer*, int tox, int toy);
|
||||
void setText(const QString&);
|
||||
|
||||
protected:
|
||||
|
|
184
src/Gui/GLPainter.cpp
Normal file
184
src/Gui/GLPainter.cpp
Normal file
|
@ -0,0 +1,184 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include "GLPainter.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
GLPainter::GLPainter() : viewer(0), logicOp(false), lineStipple(false)
|
||||
{
|
||||
}
|
||||
|
||||
GLPainter::~GLPainter()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
bool GLPainter::begin(View3DInventorViewer* v)
|
||||
{
|
||||
if (viewer)
|
||||
return false;
|
||||
viewer = v;
|
||||
|
||||
// Make current context
|
||||
SbVec2s view = viewer->getGLSize();
|
||||
this->width = view[0];
|
||||
this->height = view[1];
|
||||
|
||||
viewer->glLockNormal();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, this->width, 0, this->height, -1, 1);
|
||||
|
||||
// Store GL state
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
glGetFloatv(GL_DEPTH_RANGE, this->depthrange);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, this->projectionmatrix);
|
||||
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthRange(0,0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glLineWidth(1.0f);
|
||||
glColor4f(1.0, 1.0, 1.0, 0.0);
|
||||
glViewport(0, 0, this->width, this->height);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLPainter::end()
|
||||
{
|
||||
if (!viewer)
|
||||
return false;
|
||||
|
||||
glFlush();
|
||||
if (this->logicOp) {
|
||||
this->logicOp = false;
|
||||
glDisable(GL_COLOR_LOGIC_OP);
|
||||
}
|
||||
if (this->lineStipple) {
|
||||
this->lineStipple = false;
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
}
|
||||
|
||||
// Reset original state
|
||||
glDepthRange(this->depthrange[0], this->depthrange[1]);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixd(this->projectionmatrix);
|
||||
|
||||
glPopAttrib();
|
||||
glPopMatrix();
|
||||
|
||||
// Release the context
|
||||
viewer->glUnlockNormal();
|
||||
|
||||
viewer = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLPainter::isActive() const
|
||||
{
|
||||
return viewer != 0;
|
||||
}
|
||||
|
||||
void GLPainter::setLineWidth(float w)
|
||||
{
|
||||
glLineWidth(w);
|
||||
}
|
||||
|
||||
void GLPainter::setPointSize(float s)
|
||||
{
|
||||
glPointSize(s);
|
||||
}
|
||||
|
||||
void GLPainter::setColor(float r, float g, float b, float a)
|
||||
{
|
||||
glColor4f(r, g, b, a);
|
||||
}
|
||||
|
||||
void GLPainter::setLogicOp(GLenum mode)
|
||||
{
|
||||
glEnable(GL_COLOR_LOGIC_OP);
|
||||
glLogicOp(mode);
|
||||
this->logicOp = true;
|
||||
}
|
||||
|
||||
void GLPainter::setDrawBuffer(GLenum mode)
|
||||
{
|
||||
glDrawBuffer(mode);
|
||||
}
|
||||
|
||||
void GLPainter::setLineStipple(GLint factor, GLushort pattern)
|
||||
{
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
glLineStipple(factor, pattern);
|
||||
this->lineStipple = true;
|
||||
}
|
||||
|
||||
// Draw routines
|
||||
void GLPainter::drawRect(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if (!viewer)
|
||||
return;
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3i(x1, this->height-y1, 0);
|
||||
glVertex3i(x2, this->height-y1, 0);
|
||||
glVertex3i(x2, this->height-y2, 0);
|
||||
glVertex3i(x1, this->height-y2, 0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void GLPainter::drawLine (int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if (!viewer)
|
||||
return;
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3i(x1, this->height-y1, 0);
|
||||
glVertex3i(x2, this->height-y2, 0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void GLPainter::drawPoint(int x, int y)
|
||||
{
|
||||
if (!viewer)
|
||||
return;
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3i(x, this->height-y, 0);
|
||||
glEnd();
|
||||
}
|
77
src/Gui/GLPainter.h
Normal file
77
src/Gui/GLPainter.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_GLPAINTER_H
|
||||
#define GUI_GLPAINTER_H
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#ifdef FC_OS_MACOSX
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
namespace Gui {
|
||||
class View3DInventorViewer;
|
||||
class GuiExport GLPainter
|
||||
{
|
||||
public:
|
||||
GLPainter();
|
||||
virtual ~GLPainter();
|
||||
|
||||
bool begin(View3DInventorViewer*);
|
||||
bool end();
|
||||
bool isActive() const;
|
||||
|
||||
/** @name Setter methods */
|
||||
//@{
|
||||
void setLineWidth(float);
|
||||
void setPointSize(float);
|
||||
void setColor(float, float, float, float=0);
|
||||
void setLogicOp(GLenum);
|
||||
void setDrawBuffer(GLenum);
|
||||
void setLineStipple(GLint factor, GLushort pattern);
|
||||
//@}
|
||||
|
||||
/** @name Draw routines */
|
||||
//@{
|
||||
void drawRect (int x, int y, int w, int h);
|
||||
void drawLine (int x1, int y1, int x2, int y2);
|
||||
void drawPoint(int x, int y);
|
||||
//@}
|
||||
|
||||
private:
|
||||
View3DInventorViewer* viewer;
|
||||
GLfloat depthrange[2];
|
||||
GLdouble projectionmatrix[16];
|
||||
GLint width, height;
|
||||
bool logicOp;
|
||||
bool lineStipple;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_GLPAINTER_H
|
||||
|
|
@ -85,6 +85,14 @@ void MDIView::deleteSelf()
|
|||
delete this;
|
||||
}
|
||||
|
||||
void MDIView::setOverrideCursor(const QCursor& c)
|
||||
{
|
||||
}
|
||||
|
||||
void MDIView::restoreOverrideCursor()
|
||||
{
|
||||
}
|
||||
|
||||
void MDIView::onRelabel(Gui::Document *pDoc)
|
||||
{
|
||||
if (!bIsPassive) {
|
||||
|
|
|
@ -104,6 +104,10 @@ public:
|
|||
virtual void setCurrentViewMode(ViewMode mode);
|
||||
ViewMode currentViewMode() const { return currentMode; }
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void setOverrideCursor(const QCursor&);
|
||||
virtual void restoreOverrideCursor();
|
||||
|
||||
Q_SIGNALS:
|
||||
void message(const QString&, int);
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "MouseSelection.h"
|
||||
#include "View3DInventor.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "GLPainter.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
|
@ -263,10 +264,15 @@ void PolyPickerSelection::draw ()
|
|||
if (mustRedraw){
|
||||
if (_cNodeVector.size() > 1) {
|
||||
QPoint start = _cNodeVector.front();
|
||||
GLPainter p;
|
||||
p.begin(_pcView3D);
|
||||
p.setColor(1.0f,1.0f,1.0f);
|
||||
p.setLogicOp(GL_XOR);
|
||||
for (std::vector<QPoint>::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) {
|
||||
_pcView3D->drawLine(start.x(),start.y(),it->x(), it->y() );
|
||||
p.drawLine(start.x(),start.y(),it->x(), it->y());
|
||||
start = *it;
|
||||
}
|
||||
p.end();
|
||||
}
|
||||
|
||||
// recursive call, but no infinite loop
|
||||
|
@ -279,15 +285,25 @@ void PolyPickerSelection::draw ()
|
|||
|
||||
if (_cNodeVector.size() > 2) {
|
||||
QPoint start = _cNodeVector.front();
|
||||
_pcView3D->drawLine(m_iXnew,m_iYnew,start.x(), start.y() );
|
||||
GLPainter p;
|
||||
p.begin(_pcView3D);
|
||||
p.setColor(1.0f,1.0f,1.0f);
|
||||
p.setLogicOp(GL_XOR);
|
||||
p.drawLine(m_iXnew,m_iYnew,start.x(), start.y());
|
||||
p.end();
|
||||
}
|
||||
}
|
||||
else {
|
||||
_pcView3D->drawLine(m_iXnew,m_iYnew,m_iXold,m_iYold);
|
||||
GLPainter p;
|
||||
p.begin(_pcView3D);
|
||||
p.setColor(1.0f,1.0f,1.0f);
|
||||
p.setLogicOp(GL_XOR);
|
||||
p.drawLine(m_iXnew,m_iYnew,m_iXold,m_iYold);
|
||||
if (_cNodeVector.size() > 1) {
|
||||
QPoint start = _cNodeVector.front();
|
||||
_pcView3D->drawLine(m_iXnew,m_iYnew,start.x(), start.y());
|
||||
p.drawLine(m_iXnew,m_iYnew,start.x(), start.y());
|
||||
}
|
||||
p.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -458,6 +474,201 @@ int PolyClipSelection::popupMenu()
|
|||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
||||
BrushSelection::BrushSelection()
|
||||
: r(1.0f), g(0.0f), b(0.0f), a(0.0f), l(2.0f)
|
||||
{
|
||||
m_iNodes = 0;
|
||||
m_bWorking = false;
|
||||
}
|
||||
|
||||
void BrushSelection::initialize()
|
||||
{
|
||||
QPixmap p(cursor_cut_scissors);
|
||||
QCursor cursor(p, 4, 4);
|
||||
_pcView3D->getWidget()->setCursor(cursor);
|
||||
}
|
||||
|
||||
void BrushSelection::terminate()
|
||||
{
|
||||
}
|
||||
|
||||
void BrushSelection::setColor(float r, float g, float b, float a)
|
||||
{
|
||||
this->r = r;
|
||||
this->g = g;
|
||||
this->b = b;
|
||||
this->a = a;
|
||||
}
|
||||
|
||||
void BrushSelection::setLineWidth(float l)
|
||||
{
|
||||
this->l = l;
|
||||
}
|
||||
|
||||
void BrushSelection::draw ()
|
||||
{
|
||||
if (mustRedraw){
|
||||
if (_cNodeVector.size() > 1) {
|
||||
QPoint start = _cNodeVector.front();
|
||||
GLPainter p;
|
||||
p.begin(_pcView3D);
|
||||
p.setLineWidth(this->l);
|
||||
p.setColor(this->r, this->g, this->b, this->a);
|
||||
for (std::vector<QPoint>::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) {
|
||||
p.drawLine(start.x(),start.y(),it->x(), it->y());
|
||||
start = *it;
|
||||
}
|
||||
p.end();
|
||||
}
|
||||
|
||||
// recursive call, but no infinite loop
|
||||
mustRedraw = false;
|
||||
draw();
|
||||
}
|
||||
if (m_bWorking) {
|
||||
GLPainter p;
|
||||
p.begin(_pcView3D);
|
||||
p.setLineWidth(this->l);
|
||||
p.setColor(this->r, this->g, this->b, this->a);
|
||||
p.drawLine(m_iXnew, m_iYnew, m_iXold, m_iYold);
|
||||
p.end();
|
||||
}
|
||||
}
|
||||
|
||||
BrushSelection::~BrushSelection()
|
||||
{
|
||||
}
|
||||
|
||||
int BrushSelection::popupMenu()
|
||||
{
|
||||
QMenu menu;
|
||||
QAction* fi = menu.addAction(QObject::tr("Finish"));
|
||||
menu.addAction(QObject::tr("Clear"));
|
||||
QAction* ca = menu.addAction(QObject::tr("Cancel"));
|
||||
if (getPositions().size() < 3)
|
||||
fi->setEnabled(false);
|
||||
QAction* id = menu.exec(QCursor::pos());
|
||||
if (id == fi)
|
||||
return Finish;
|
||||
else if (id == ca)
|
||||
return Cancel;
|
||||
else
|
||||
return Restart;
|
||||
}
|
||||
|
||||
int BrushSelection::mouseButtonEvent(const SoMouseButtonEvent * const e, const QPoint& pos)
|
||||
{
|
||||
const int button = e->getButton();
|
||||
const SbBool press = e->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
|
||||
|
||||
if (press) {
|
||||
switch (button)
|
||||
{
|
||||
case SoMouseButtonEvent::BUTTON1:
|
||||
{
|
||||
// start working from now on
|
||||
if (!m_bWorking) {
|
||||
m_bWorking = true;
|
||||
// clear the old polygon
|
||||
_cNodeVector.clear();
|
||||
_pcView3D->getGLWidget()->update();
|
||||
|
||||
_cNodeVector.push_back(pos);
|
||||
|
||||
m_iXnew = pos.x(); m_iYnew = pos.y();
|
||||
m_iXold = pos.x(); m_iYold = pos.y();
|
||||
}
|
||||
} break;
|
||||
case SoMouseButtonEvent::BUTTON2:
|
||||
{
|
||||
if (_cNodeVector.size() > 0) {
|
||||
if (_cNodeVector.back() != pos)
|
||||
_cNodeVector.push_back(pos);
|
||||
m_iXnew = pos.x(); m_iYnew = pos.y();
|
||||
m_iXold = pos.x(); m_iYold = pos.y();
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
} break;
|
||||
}
|
||||
}
|
||||
// release
|
||||
else {
|
||||
switch (button)
|
||||
{
|
||||
case SoMouseButtonEvent::BUTTON1:
|
||||
return Finish;
|
||||
case SoMouseButtonEvent::BUTTON2:
|
||||
{
|
||||
QCursor cur = _pcView3D->getWidget()->cursor();
|
||||
_pcView3D->getWidget()->setCursor(m_cPrevCursor);
|
||||
|
||||
// The pop-up menu should be shown when releasing mouse button because
|
||||
// otherwise the navigation style doesn't get the UP event and gets into
|
||||
// an inconsistent state.
|
||||
int id = popupMenu();
|
||||
if (id == Finish || id == Cancel) {
|
||||
releaseMouseModel();
|
||||
}
|
||||
else if (id == Restart) {
|
||||
m_bWorking = false;
|
||||
m_iNodes = 0;
|
||||
_pcView3D->getWidget()->setCursor(cur);
|
||||
}
|
||||
return id;
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
return Continue;
|
||||
}
|
||||
|
||||
int BrushSelection::locationEvent(const SoLocation2Event * const e, const QPoint& pos)
|
||||
{
|
||||
// do all the drawing stuff for us
|
||||
QPoint clPoint = pos;
|
||||
|
||||
if (m_bWorking) {
|
||||
// check the position
|
||||
QRect r = _pcView3D->getGLWidget()->rect();
|
||||
if (!r.contains(clPoint)) {
|
||||
if (clPoint.x() < r.left())
|
||||
clPoint.setX( r.left());
|
||||
if (clPoint.x() > r.right())
|
||||
clPoint.setX(r.right());
|
||||
if (clPoint.y() < r.top())
|
||||
clPoint.setY(r.top());
|
||||
if (clPoint.y() > r.bottom())
|
||||
clPoint.setY(r.bottom());
|
||||
}
|
||||
|
||||
SbVec2s last = _clPoly.back();
|
||||
SbVec2s curr = e->getPosition();
|
||||
if (abs(last[0]-curr[0]) > 20 || abs(last[1]-curr[1]) > 20)
|
||||
_clPoly.push_back(curr);
|
||||
_cNodeVector.push_back(clPoint);
|
||||
}
|
||||
|
||||
m_iXnew = clPoint.x();
|
||||
m_iYnew = clPoint.y();
|
||||
draw();
|
||||
m_iXold = clPoint.x();
|
||||
m_iYold = clPoint.y();
|
||||
|
||||
return Continue;
|
||||
}
|
||||
|
||||
int BrushSelection::keyboardEvent( const SoKeyboardEvent * const e )
|
||||
{
|
||||
return Continue;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
||||
RectangleSelection::RectangleSelection()
|
||||
{
|
||||
m_bWorking = false;
|
||||
|
@ -477,8 +688,16 @@ void RectangleSelection::terminate()
|
|||
|
||||
void RectangleSelection::draw ()
|
||||
{
|
||||
if (m_bWorking)
|
||||
_pcView3D->drawRect(m_iXold, m_iYold, m_iXnew, m_iYnew);
|
||||
if (m_bWorking) {
|
||||
GLPainter p;
|
||||
p.begin(_pcView3D);
|
||||
p.setColor(1.0, 1.0, 0.0, 0.0);
|
||||
p.setLogicOp(GL_XOR);
|
||||
p.setLineWidth(3.0f);
|
||||
p.setLineStipple(2, 0x3F3F);
|
||||
p.drawRect(m_iXold, m_iYold, m_iXnew, m_iYnew);
|
||||
p.end();
|
||||
}
|
||||
}
|
||||
|
||||
int RectangleSelection::mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos )
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <vector>
|
||||
#include <Inventor/SbLinear.h>
|
||||
#include <Inventor/SbVec2f.h>
|
||||
#include <QCursor>
|
||||
|
||||
// forwards
|
||||
class QMouseEvent;
|
||||
|
@ -156,6 +157,45 @@ protected:
|
|||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The brush selection class
|
||||
* \author Werner Mayer
|
||||
*/
|
||||
class GuiExport BrushSelection : public BaseMouseSelection
|
||||
{
|
||||
public:
|
||||
BrushSelection();
|
||||
virtual ~BrushSelection();
|
||||
|
||||
/// set the new mouse cursor
|
||||
virtual void initialize();
|
||||
/// do nothing
|
||||
virtual void terminate();
|
||||
|
||||
// Settings
|
||||
void setColor(float r, float g, float b, float a=0);
|
||||
void setLineWidth(float);
|
||||
|
||||
protected:
|
||||
virtual int mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos );
|
||||
virtual int locationEvent ( const SoLocation2Event * const e, const QPoint& pos );
|
||||
virtual int keyboardEvent ( const SoKeyboardEvent * const e );
|
||||
|
||||
/// draw the polygon
|
||||
virtual void draw ();
|
||||
virtual int popupMenu();
|
||||
|
||||
protected:
|
||||
std::vector<QPoint> _cNodeVector;
|
||||
int m_iNodes;
|
||||
bool m_bWorking;
|
||||
|
||||
private:
|
||||
float r,g,b,a,l;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The selection mouse model class
|
||||
* Draws a rectangle for selection
|
||||
|
|
|
@ -465,32 +465,30 @@ bool SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectN
|
|||
if (DocName != "")
|
||||
rmvPreselect();
|
||||
|
||||
if(ActiveGate)
|
||||
{
|
||||
if (ActiveGate) {
|
||||
App::Document* pDoc = getDocument(pDocName);
|
||||
|
||||
if (pDoc) {
|
||||
if(pObjectName){
|
||||
if (pObjectName) {
|
||||
App::DocumentObject* pObject = pDoc->getObject(pObjectName);
|
||||
if(! ActiveGate->allow(pDoc,pObject,pSubName)){
|
||||
if (!ActiveGate->allow(pDoc,pObject,pSubName)) {
|
||||
snprintf(buf,512,"Not allowed: %s.%s.%s ",pDocName
|
||||
,pObjectName
|
||||
,pSubName
|
||||
);
|
||||
|
||||
if (getMainWindow()){
|
||||
if (getMainWindow()) {
|
||||
getMainWindow()->showMessage(QString::fromAscii(buf),3000);
|
||||
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
|
||||
static_cast<View3DInventor*>(mdi)->setCursor(Qt::ForbiddenCursor);
|
||||
}
|
||||
mdi->setOverrideCursor(QCursor(Qt::ForbiddenCursor));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}else
|
||||
}
|
||||
else
|
||||
return ActiveGate->allow(pDoc,0,0);
|
||||
}else
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
@ -520,13 +518,13 @@ bool SelectionSingleton::setPreselect(const char* pDocName, const char* pObjectN
|
|||
,Chng.pSubName
|
||||
,x,y,z);
|
||||
|
||||
if (getMainWindow()){
|
||||
getMainWindow()->showMessage(QString::fromAscii(buf),3000);
|
||||
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
|
||||
static_cast<View3DInventor*>(mdi)->setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
}
|
||||
//FIXME: We shouldn't replace the possibly defined edit cursor
|
||||
//with the arrow cursor. But it seems that we don't even have to.
|
||||
//if (getMainWindow()){
|
||||
// getMainWindow()->showMessage(QString::fromAscii(buf),3000);
|
||||
// Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
// mdi->restoreOverrideCursor();
|
||||
//}
|
||||
|
||||
Notify(Chng);
|
||||
signalSelectionChanged(Chng);
|
||||
|
@ -587,11 +585,9 @@ void SelectionSingleton::rmvPreselect()
|
|||
hy = 0;
|
||||
hz = 0;
|
||||
|
||||
if (getMainWindow()){
|
||||
if (ActiveGate && getMainWindow()) {
|
||||
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
|
||||
static_cast<View3DInventor*>(mdi)->setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
mdi->restoreOverrideCursor();
|
||||
}
|
||||
|
||||
//Base::Console().Log("Sel : Rmv preselect \n");
|
||||
|
@ -605,7 +601,7 @@ const SelectionChanges &SelectionSingleton::getPreselection(void) const
|
|||
// add a SelectionGate to control what is selectable
|
||||
void SelectionSingleton::addSelectionGate(Gui::SelectionGate *gate)
|
||||
{
|
||||
if(ActiveGate)
|
||||
if (ActiveGate)
|
||||
rmvSelectionGate();
|
||||
|
||||
ActiveGate = gate;
|
||||
|
@ -621,9 +617,7 @@ void SelectionSingleton::rmvSelectionGate(void)
|
|||
Gui::Document* doc = Gui::Application::Instance->activeDocument();
|
||||
if (doc) {
|
||||
Gui::MDIView* mdi = doc->getActiveView();
|
||||
if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
|
||||
static_cast<View3DInventor*>(mdi)->setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
mdi->restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,15 +648,12 @@ bool SelectionSingleton::addSelection(const char* pDocName, const char* pObjectN
|
|||
temp.pObject = 0;
|
||||
|
||||
// check for a Selection Gate
|
||||
if(ActiveGate)
|
||||
{
|
||||
if(! ActiveGate->allow(temp.pDoc,temp.pObject,pSubName)){
|
||||
if (getMainWindow()){
|
||||
if (ActiveGate) {
|
||||
if (!ActiveGate->allow(temp.pDoc,temp.pObject,pSubName)) {
|
||||
if (getMainWindow()) {
|
||||
getMainWindow()->showMessage(QString::fromAscii("Selection not allowed by filter"),5000);
|
||||
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
if (mdi && mdi->isDerivedFrom(View3DInventor::getClassTypeId())) {
|
||||
static_cast<View3DInventor*>(mdi)->setCursor(Qt::ForbiddenCursor);
|
||||
}
|
||||
mdi->setOverrideCursor(Qt::ForbiddenCursor);
|
||||
}
|
||||
QApplication::beep();
|
||||
return false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2009 Juergen Riegel (FreeCAD@juergen-riegel.net) *
|
||||
* Copyright (c) 2009 Juergen Riegel (FreeCAD@juergen-riegel.net) *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <Inventor/nodekits/SoSubKit.h>
|
||||
#include <Inventor/nodekits/SoBaseKit.h>
|
||||
#include <Inventor/nodes/SoShape.h>
|
||||
#include <Inventor/fields/SoSFFloat.h>
|
||||
#include <Inventor/fields/SoSFColor.h>
|
||||
#include <Inventor/fields/SoSFString.h>
|
||||
|
|
|
@ -204,7 +204,7 @@ void AbstractSplitView::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp
|
|||
}
|
||||
else if (strcmp(Reason,"Gradient") == 0) {
|
||||
for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it)
|
||||
(*it)->setGradientBackgroud((rGrp.GetBool("Gradient",true)));
|
||||
(*it)->setGradientBackground((rGrp.GetBool("Gradient",true)));
|
||||
}
|
||||
else if (strcmp(Reason,"UseAntialiasing") == 0) {
|
||||
for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it)
|
||||
|
@ -238,9 +238,9 @@ void AbstractSplitView::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp
|
|||
for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
|
||||
(*it)->setBackgroundColor(SbColor(r1, g1, b1));
|
||||
if (rGrp.GetBool("UseBackgroundColorMid",false) == false)
|
||||
(*it)->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3));
|
||||
(*it)->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3));
|
||||
else
|
||||
(*it)->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4));
|
||||
(*it)->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ bool AbstractSplitView::onHasMsg(const char* pMsg) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void AbstractSplitView::setCursor(const QCursor& aCursor)
|
||||
void AbstractSplitView::setOverrideCursor(const QCursor& aCursor)
|
||||
{
|
||||
//_viewer->getWidget()->setCursor(aCursor);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
|
||||
View3DInventorViewer *getViewer(unsigned int) const;
|
||||
|
||||
void setCursor(const QCursor&);
|
||||
void setOverrideCursor(const QCursor&);
|
||||
|
||||
protected:
|
||||
void setupSettings();
|
||||
|
|
|
@ -61,7 +61,72 @@ TaskWidget::~TaskWidget()
|
|||
{
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
// TaskGroup
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
TaskGroup::TaskGroup(QWidget *parent)
|
||||
: iisTaskGroup(parent, false)
|
||||
{
|
||||
setScheme(iisFreeCADTaskPanelScheme::defaultScheme());
|
||||
}
|
||||
|
||||
TaskGroup::~TaskGroup()
|
||||
{
|
||||
}
|
||||
|
||||
namespace Gui { namespace TaskView {
|
||||
class TaskIconLabel : public iisIconLabel {
|
||||
public:
|
||||
TaskIconLabel(const QIcon &icon,
|
||||
const QString &title,
|
||||
QWidget *parent = 0)
|
||||
: iisIconLabel(icon, title, parent) {
|
||||
// do not allow to get the focus because when hiding the task box
|
||||
// it could cause to activate another MDI view.
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
void setTitle(const QString &text) {
|
||||
myText = text;
|
||||
update();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void TaskGroup::actionEvent (QActionEvent* e)
|
||||
{
|
||||
QAction *action = e->action();
|
||||
switch (e->type()) {
|
||||
case QEvent::ActionAdded:
|
||||
{
|
||||
TaskIconLabel *label = new TaskIconLabel(
|
||||
action->icon(), action->text(), this);
|
||||
this->addIconLabel(label);
|
||||
connect(label,SIGNAL(clicked()),action,SIGNAL(triggered()));
|
||||
break;
|
||||
}
|
||||
case QEvent::ActionChanged:
|
||||
{
|
||||
// update label when action changes
|
||||
QBoxLayout* bl = this->groupLayout();
|
||||
int index = this->actions().indexOf(action);
|
||||
if (index < 0) break;
|
||||
QWidgetItem* item = static_cast<QWidgetItem*>(bl->itemAt(index));
|
||||
TaskIconLabel* label = static_cast<TaskIconLabel*>(item->widget());
|
||||
label->setTitle(action->text());
|
||||
break;
|
||||
}
|
||||
case QEvent::ActionRemoved:
|
||||
{
|
||||
// cannot change anything
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
|
@ -125,25 +190,6 @@ void TaskBox::hideGroupBox()
|
|||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
}
|
||||
|
||||
namespace Gui { namespace TaskView {
|
||||
class TaskIconLabel : public iisIconLabel {
|
||||
public:
|
||||
TaskIconLabel(const QIcon &icon,
|
||||
const QString &title,
|
||||
QWidget *parent = 0)
|
||||
: iisIconLabel(icon, title, parent) {
|
||||
// do not allow to get the focus because when hiding the task box
|
||||
// it could cause to activate another MDI view.
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
void setTitle(const QString &text) {
|
||||
myText = text;
|
||||
update();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void TaskBox::actionEvent (QActionEvent* e)
|
||||
{
|
||||
QAction *action = e->action();
|
||||
|
|
|
@ -57,6 +57,18 @@ public:
|
|||
//~TaskContent();
|
||||
};
|
||||
|
||||
class GuiExport TaskGroup : public iisTaskGroup, public TaskContent
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskGroup(QWidget *parent = 0);
|
||||
~TaskGroup();
|
||||
|
||||
protected:
|
||||
void actionEvent (QActionEvent*);
|
||||
};
|
||||
|
||||
/// Father class of content with header and Icon
|
||||
class GuiExport TaskBox : public iisTaskBox, public TaskContent
|
||||
{
|
||||
|
|
|
@ -87,6 +87,19 @@ void Thumbnail::SaveDocFile (Base::Writer &writer) const
|
|||
QImage img;
|
||||
try {
|
||||
this->viewer->savePicture(this->size, this->size, View3DInventorViewer::Current, img);
|
||||
// Alternative way of off-screen rendering
|
||||
#if 0
|
||||
QGLFramebufferObject fbo(this->size, this->size,QGLFramebufferObject::Depth);
|
||||
fbo.bind();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glDepthRange(0.1,1.0);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
SoGLRenderAction gl(SbViewportRegion(this->size,this->size));
|
||||
gl.apply(this->viewer->getSceneManager()->getSceneGraph());
|
||||
fbo.release();
|
||||
img = fbo.toImage();
|
||||
#endif
|
||||
}
|
||||
catch (...) {
|
||||
return; // offscreen rendering failed
|
||||
|
|
|
@ -893,7 +893,6 @@ void DocumentItem::slotActiveObject(const Gui::ViewProviderDocumentObject& obj)
|
|||
|
||||
void DocumentItem::slotHighlightObject (const Gui::ViewProviderDocumentObject& obj,const Gui::HighlightMode& high,bool set)
|
||||
{
|
||||
|
||||
std::string objectName = obj.getObject()->getNameInDocument();
|
||||
std::map<std::string, DocumentObjectItem*>::iterator jt = ObjectMap.find(objectName);
|
||||
if (jt == ObjectMap.end())
|
||||
|
@ -915,27 +914,26 @@ void DocumentItem::slotHighlightObject (const Gui::ViewProviderDocumentObject& o
|
|||
// not defined enum
|
||||
assert(0);
|
||||
}
|
||||
|
||||
jt->second->setFont(0,f);
|
||||
|
||||
}
|
||||
|
||||
void DocumentItem::slotExpandObject (const Gui::ViewProviderDocumentObject& obj,const Gui::TreeItemMode& mode)
|
||||
{
|
||||
|
||||
std::string objectName = obj.getObject()->getNameInDocument();
|
||||
std::map<std::string, DocumentObjectItem*>::iterator jt = ObjectMap.find(objectName);
|
||||
if (jt == ObjectMap.end())
|
||||
return; // signal is emitted before the item gets created
|
||||
|
||||
switch (mode) {
|
||||
case Gui::Expand:
|
||||
case Gui::Expand:
|
||||
jt->second->setExpanded(true);
|
||||
break;
|
||||
case Gui::Collaps:
|
||||
case Gui::Collapse:
|
||||
jt->second->setExpanded(false);
|
||||
break;
|
||||
case Gui::Toggle:
|
||||
if(jt->second->isExpanded())
|
||||
case Gui::Toggle:
|
||||
if (jt->second->isExpanded())
|
||||
jt->second->setExpanded(false);
|
||||
else
|
||||
jt->second->setExpanded(true);
|
||||
|
@ -945,10 +943,8 @@ void DocumentItem::slotExpandObject (const Gui::ViewProviderDocumentObject& obj,
|
|||
// not defined enum
|
||||
assert(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const Gui::Document* DocumentItem::document() const
|
||||
{
|
||||
return this->pDocument;
|
||||
|
|
|
@ -49,8 +49,8 @@ enum HighlightMode { Underlined,
|
|||
|
||||
/// highlight modes for the tree items
|
||||
enum TreeItemMode { Expand,
|
||||
Collaps,
|
||||
Toggle
|
||||
Collapse,
|
||||
Toggle
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
|||
_viewer->setAnimationEnabled(rGrp.GetBool("UseAutoRotation",true));
|
||||
}
|
||||
else if (strcmp(Reason,"Gradient") == 0) {
|
||||
_viewer->setGradientBackgroud((rGrp.GetBool("Gradient",true)));
|
||||
_viewer->setGradientBackground((rGrp.GetBool("Gradient",true)));
|
||||
}
|
||||
else if (strcmp(Reason,"UseAntialiasing") == 0) {
|
||||
_viewer->getGLRenderAction()->setSmoothing(rGrp.GetBool("UseAntialiasing",false));
|
||||
|
@ -357,9 +357,9 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
|
|||
r4 = ((col4 >> 24) & 0xff) / 255.0; g4 = ((col4 >> 16) & 0xff) / 255.0; b4 = ((col4 >> 8) & 0xff) / 255.0;
|
||||
_viewer->setBackgroundColor(SbColor(r1, g1, b1));
|
||||
if (rGrp.GetBool("UseBackgroundColorMid",false) == false)
|
||||
_viewer->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3));
|
||||
_viewer->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3));
|
||||
else
|
||||
_viewer->setGradientBackgroudColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4));
|
||||
_viewer->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,12 +772,9 @@ bool View3DInventor::hasClippingPlane() const
|
|||
return _viewer->hasClippingPlane();
|
||||
}
|
||||
|
||||
void View3DInventor::setOverlayWidget(GLOverlayWidget* widget)
|
||||
void View3DInventor::setOverlayWidget(QWidget* widget)
|
||||
{
|
||||
removeOverlayWidget();
|
||||
QGLWidget* w = static_cast<QGLWidget*>(_viewer->getGLWidget());
|
||||
QImage img = w->grabFrameBuffer();
|
||||
widget->setImage(img);
|
||||
stack->addWidget(widget);
|
||||
stack->setCurrentIndex(1);
|
||||
}
|
||||
|
@ -789,14 +786,14 @@ void View3DInventor::removeOverlayWidget()
|
|||
if (overlay) stack->removeWidget(overlay);
|
||||
}
|
||||
|
||||
void View3DInventor::setCursor(const QCursor& aCursor)
|
||||
void View3DInventor::setOverrideCursor(const QCursor& aCursor)
|
||||
{
|
||||
_viewer->getWidget()->setCursor(aCursor);
|
||||
}
|
||||
|
||||
void View3DInventor::setCursor(Qt::CursorShape aCursor)
|
||||
void View3DInventor::restoreOverrideCursor()
|
||||
{
|
||||
_viewer->getWidget()->setCursor(aCursor);
|
||||
_viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
|
||||
}
|
||||
|
||||
void View3DInventor::dump(const char* filename)
|
||||
|
|
|
@ -100,15 +100,15 @@ public:
|
|||
void toggleClippingPlane();
|
||||
bool hasClippingPlane() const;
|
||||
|
||||
void setOverlayWidget(GLOverlayWidget*);
|
||||
void setOverlayWidget(QWidget*);
|
||||
void removeOverlayWidget();
|
||||
|
||||
View3DInventorViewer *getViewer(void) const {return _viewer;}
|
||||
|
||||
public Q_SLOTS:
|
||||
/// override the cursor in this view
|
||||
void setCursor(const QCursor&);
|
||||
void setCursor(Qt::CursorShape s);
|
||||
void setOverrideCursor(const QCursor&);
|
||||
void restoreOverrideCursor();
|
||||
|
||||
void dump(const char* filename);
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ SOQT_OBJECT_ABSTRACT_SOURCE(View3DInventorViewer);
|
|||
View3DInventorViewer::View3DInventorViewer (QWidget *parent, const char *name,
|
||||
SbBool embed, Type type, SbBool build)
|
||||
: inherited (parent, name, embed, type, build), editViewProvider(0),navigation(0),
|
||||
editing(FALSE), redirected(FALSE)
|
||||
editing(FALSE), redirected(FALSE), allowredir(FALSE)
|
||||
{
|
||||
Gui::Selection().Attach(this);
|
||||
|
||||
|
@ -258,7 +258,7 @@ View3DInventorViewer::View3DInventorViewer (QWidget *parent, const char *name,
|
|||
setViewing(false);
|
||||
|
||||
setBackgroundColor(SbColor(0.1f, 0.1f, 0.1f));
|
||||
setGradientBackgroud(true);
|
||||
setGradientBackground(true);
|
||||
|
||||
// set some callback functions for user interaction
|
||||
addStartCallback(interactionStartCB);
|
||||
|
@ -420,7 +420,7 @@ void View3DInventorViewer::handleEventCB(void * ud, SoEventCallback * n)
|
|||
SoGLWidgetElement::set(action->getState(), qobject_cast<QGLWidget*>(that->getGLWidget()));
|
||||
}
|
||||
|
||||
void View3DInventorViewer::setGradientBackgroud(bool on)
|
||||
void View3DInventorViewer::setGradientBackground(bool on)
|
||||
{
|
||||
if (on && backgroundroot->findChild(pcBackGround) == -1)
|
||||
backgroundroot->addChild(pcBackGround);
|
||||
|
@ -428,15 +428,15 @@ void View3DInventorViewer::setGradientBackgroud(bool on)
|
|||
backgroundroot->removeChild(pcBackGround);
|
||||
}
|
||||
|
||||
void View3DInventorViewer::setGradientBackgroudColor(const SbColor& fromColor,
|
||||
const SbColor& toColor)
|
||||
void View3DInventorViewer::setGradientBackgroundColor(const SbColor& fromColor,
|
||||
const SbColor& toColor)
|
||||
{
|
||||
pcBackGround->setColorGradient(fromColor, toColor);
|
||||
}
|
||||
|
||||
void View3DInventorViewer::setGradientBackgroudColor(const SbColor& fromColor,
|
||||
const SbColor& toColor,
|
||||
const SbColor& midColor)
|
||||
void View3DInventorViewer::setGradientBackgroundColor(const SbColor& fromColor,
|
||||
const SbColor& toColor,
|
||||
const SbColor& midColor)
|
||||
{
|
||||
pcBackGround->setColorGradient(fromColor, toColor, midColor);
|
||||
}
|
||||
|
@ -948,7 +948,7 @@ void View3DInventorViewer::actualRedraw(void)
|
|||
vv.projectToScreen(pt, pt);
|
||||
int tox = (int)(pt[0] * size[0]);
|
||||
int toy = (int)((1.0f-pt[1]) * size[1]);
|
||||
flag->drawLine(tox, toy);
|
||||
flag->drawLine(this, tox, toy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1506,120 +1506,6 @@ void View3DInventorViewer::viewSelection()
|
|||
root->unref();
|
||||
}
|
||||
|
||||
// Draw routines
|
||||
void View3DInventorViewer::drawRect(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
// Make current context
|
||||
SbVec2s view = this->getGLSize();
|
||||
this->glLockNormal();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, view[0], 0, view[1], -1, 1);
|
||||
|
||||
// Store GL state
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
GLfloat depthrange[2];
|
||||
glGetFloatv(GL_DEPTH_RANGE, depthrange);
|
||||
GLdouble projectionmatrix[16];
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix);
|
||||
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthRange(0,0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glEnable(GL_COLOR_LOGIC_OP);
|
||||
glLogicOp(GL_XOR);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
glLineWidth(3.0f);
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
glLineStipple(2, 0x3F3F);
|
||||
glColor4f(1.0, 1.0, 0.0, 0.0);
|
||||
glViewport(0, 0, view[0], view[1]);
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3i(x1, view[1]-y1, 0);
|
||||
glVertex3i(x2, view[1]-y1, 0);
|
||||
glVertex3i(x2, view[1]-y2, 0);
|
||||
glVertex3i(x1, view[1]-y2, 0);
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
glDisable(GL_COLOR_LOGIC_OP);
|
||||
|
||||
// Reset original state
|
||||
glDepthRange(depthrange[0], depthrange[1]);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixd(projectionmatrix);
|
||||
|
||||
glPopAttrib();
|
||||
glPopMatrix();
|
||||
|
||||
// Release the context
|
||||
this->glUnlockNormal();
|
||||
}
|
||||
|
||||
void View3DInventorViewer::drawLine (int x1, int y1, int x2, int y2)
|
||||
{
|
||||
// Make current context
|
||||
SbVec2s view = this->getGLSize();
|
||||
this->glLockNormal();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, view[0], 0, view[1], -1, 1);
|
||||
|
||||
// Store GL state
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
GLfloat depthrange[2];
|
||||
glGetFloatv(GL_DEPTH_RANGE, depthrange);
|
||||
GLdouble projectionmatrix[16];
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix);
|
||||
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthRange(0,0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glLineWidth(1.0f);
|
||||
glColor4f(1.0, 1.0, 1.0, 0.0);
|
||||
glViewport(0, 0, view[0], view[1]);
|
||||
|
||||
glEnable(GL_COLOR_LOGIC_OP);
|
||||
glLogicOp(GL_XOR);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3i(x1, view[1]-y1, 0);
|
||||
glVertex3i(x2, view[1]-y2, 0);
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
glLogicOp(GL_COPY);
|
||||
glDisable(GL_COLOR_LOGIC_OP);
|
||||
|
||||
// Reset original state
|
||||
glDepthRange(depthrange[0], depthrange[1]);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadMatrixd(projectionmatrix);
|
||||
|
||||
glPopAttrib();
|
||||
glPopMatrix();
|
||||
|
||||
// Release the context
|
||||
this->glUnlockNormal();
|
||||
}
|
||||
|
||||
/*!
|
||||
Decide if it should be possible to start a spin animation of the
|
||||
model in the viewer by releasing the mouse button while dragging.
|
||||
|
|
|
@ -182,6 +182,8 @@ public:
|
|||
void setEditingCursor (const QCursor& cursor);
|
||||
void setRedirectToSceneGraph(SbBool redirect) { this->redirected = redirect; }
|
||||
SbBool isRedirectedToSceneGraph() const { return this->redirected; }
|
||||
void setRedirectToSceneGraphEnabled(SbBool enable) { this->allowredir = enable; }
|
||||
SbBool isRedirectToSceneGraphEnabled(void) const { return this->allowredir; }
|
||||
//@}
|
||||
|
||||
/** @name Pick actions */
|
||||
|
@ -252,18 +254,12 @@ public:
|
|||
*/
|
||||
void viewSelection();
|
||||
|
||||
/** @name Draw routines */
|
||||
//@{
|
||||
void drawRect (int x, int y, int w, int h);
|
||||
void drawLine (int x1, int y1, int x2, int y2);
|
||||
//@}
|
||||
|
||||
void setGradientBackgroud(bool b);
|
||||
void setGradientBackgroudColor(const SbColor& fromColor,
|
||||
const SbColor& toColor);
|
||||
void setGradientBackgroudColor(const SbColor& fromColor,
|
||||
const SbColor& toColor,
|
||||
const SbColor& midColor);
|
||||
void setGradientBackground(bool b);
|
||||
void setGradientBackgroundColor(const SbColor& fromColor,
|
||||
const SbColor& toColor);
|
||||
void setGradientBackgroundColor(const SbColor& fromColor,
|
||||
const SbColor& toColor,
|
||||
const SbColor& midColor);
|
||||
void setEnabledFPSCounter(bool b);
|
||||
void setNavigationType(Base::Type);
|
||||
NavigationStyle* navigationStyle() const;
|
||||
|
@ -317,6 +313,7 @@ private:
|
|||
SbBool editing;
|
||||
QCursor editCursor;
|
||||
SbBool redirected;
|
||||
SbBool allowredir;
|
||||
|
||||
void setCursorRepresentation(int mode);
|
||||
|
||||
|
@ -328,6 +325,7 @@ private:
|
|||
|
||||
// friends
|
||||
friend class NavigationStyle;
|
||||
friend class GLPainter;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
|
|
@ -165,6 +165,9 @@ def removeComponents(objectsList,host=None):
|
|||
s.remove(o)
|
||||
h.Subtractions = s
|
||||
o.ViewObject.show()
|
||||
elif o == s.Base:
|
||||
s.Base = None
|
||||
o.ViewObject.show()
|
||||
elif tp in ["SectionPlane"]:
|
||||
a = h.Objects
|
||||
if o in a:
|
||||
|
@ -569,7 +572,7 @@ class _CommandRemove:
|
|||
def Activated(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping")))
|
||||
if Draft.getType(sel[-1]) in ["Wall","Structure"]:
|
||||
if (Draft.getType(sel[-1]) in ["Wall","Structure"]) and (len(sel) > 1):
|
||||
host = sel.pop()
|
||||
ss = "["
|
||||
for o in sel:
|
||||
|
@ -581,7 +584,7 @@ class _CommandRemove:
|
|||
FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")")
|
||||
else:
|
||||
FreeCADGui.doCommand("import Arch")
|
||||
FreeCADGui.doCommand("Arch.removeComponents("+ss+")")
|
||||
FreeCADGui.doCommand("Arch.removeComponents(Arch.ActiveDocument."+sel[-1].Name+")")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ __title__="FreeCAD Arch Component"
|
|||
__author__ = "Yorik van Havre"
|
||||
__url__ = "http://free-cad.sourceforge.net"
|
||||
|
||||
import FreeCAD,FreeCADGui
|
||||
import FreeCAD,FreeCADGui,Draft
|
||||
from PyQt4 import QtGui,QtCore
|
||||
from DraftTools import translate
|
||||
|
||||
|
@ -101,7 +101,8 @@ def removeFromComponent(compobject,subobject):
|
|||
l = compobject.Subtractions
|
||||
l.append(subobject)
|
||||
compobject.Subtractions = l
|
||||
subobject.ViewObject.hide()
|
||||
if Draft.getType(subobject) != "Window":
|
||||
subobject.ViewObject.hide()
|
||||
|
||||
|
||||
class ComponentTaskPanel:
|
||||
|
@ -306,7 +307,8 @@ class Component:
|
|||
if prop in ["Additions","Subtractions"]:
|
||||
if hasattr(obj,prop):
|
||||
for o in getattr(obj,prop):
|
||||
o.ViewObject.hide()
|
||||
if Draft.getType(o) != "Window":
|
||||
o.ViewObject.hide()
|
||||
|
||||
def processSubShapes(self,obj,base):
|
||||
"Adds additions and subtractions to a base shape"
|
||||
|
|
|
@ -78,6 +78,8 @@ class _Floor:
|
|||
def __init__(self,obj):
|
||||
obj.addProperty("App::PropertyLength","Height","Base",
|
||||
str(translate("Arch","The height of this floor")))
|
||||
obj.addProperty("App::PropertyPlacement","Placement","Base",
|
||||
str(translate("Arch","The placement of this group")))
|
||||
self.Type = "Floor"
|
||||
obj.Proxy = self
|
||||
self.Object = obj
|
||||
|
@ -90,10 +92,18 @@ class _Floor:
|
|||
self.Type = state
|
||||
|
||||
def execute(self,obj):
|
||||
pass
|
||||
if hasattr(obj,"Placement"):
|
||||
self.OldPlacement = obj.Placement.copy()
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
self.Object = obj
|
||||
if prop == "Placement":
|
||||
if hasattr(self,"OldPlacement"):
|
||||
delta = obj.Placement.Base.sub(self.OldPlacement.Base)
|
||||
for o in obj.Group:
|
||||
if hasattr(o,"Placement"):
|
||||
o.Placement.move(delta)
|
||||
self.OldPlacement = FreeCAD.Placement(obj.Placement)
|
||||
|
||||
def addObject(self,child):
|
||||
if hasattr(self,"Object"):
|
||||
|
|
|
@ -68,10 +68,19 @@ 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")
|
||||
|
||||
global QtGui, QtCore
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
||||
self.Length = 0.5
|
||||
self.Width = 0.2
|
||||
self.Height = 1
|
||||
self.continueCmd = False
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if sel:
|
||||
# direct creation
|
||||
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure")))
|
||||
FreeCADGui.doCommand("import Arch")
|
||||
# if selection contains structs and axes, make a system
|
||||
st = Draft.getObjectsOfType(sel,"Structure")
|
||||
ax = Draft.getObjectsOfType(sel,"Axis")
|
||||
|
@ -81,10 +90,90 @@ class _CommandStructure:
|
|||
# else, do normal structs
|
||||
for obj in sel:
|
||||
FreeCADGui.doCommand("Arch.makeStructure(FreeCAD.ActiveDocument." + obj.Name + ")")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
else:
|
||||
FreeCADGui.doCommand("Arch.makeStructure()")
|
||||
# interactive mode
|
||||
import DraftTrackers
|
||||
self.points = []
|
||||
self.tracker = DraftTrackers.boxTracker()
|
||||
self.tracker.on()
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox())
|
||||
|
||||
def getPoint(self,point=None,obj=None):
|
||||
"this function is called by the snapper when it has a 3D point"
|
||||
self.tracker.finalize()
|
||||
if point == None:
|
||||
return
|
||||
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure")))
|
||||
FreeCADGui.doCommand('import Arch')
|
||||
FreeCADGui.doCommand('s = Arch.makeStructure(length='+str(self.Length)+',width='+str(self.Width)+',height='+str(self.Height)+')')
|
||||
FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(point))
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
if self.continueCmd:
|
||||
self.Activated()
|
||||
|
||||
def taskbox(self):
|
||||
"sets up a taskbox widget"
|
||||
w = QtGui.QWidget()
|
||||
w.setWindowTitle(str(translate("Arch","Structure options")))
|
||||
lay0 = QtGui.QVBoxLayout(w)
|
||||
|
||||
lay1 = QtGui.QHBoxLayout()
|
||||
lay0.addLayout(lay1)
|
||||
label1 = QtGui.QLabel(str(translate("Arch","Length")))
|
||||
lay1.addWidget(label1)
|
||||
value1 = QtGui.QDoubleSpinBox()
|
||||
value1.setDecimals(2)
|
||||
value1.setValue(self.Length)
|
||||
lay1.addWidget(value1)
|
||||
|
||||
lay2 = QtGui.QHBoxLayout()
|
||||
lay0.addLayout(lay2)
|
||||
label2 = QtGui.QLabel(str(translate("Arch","Width")))
|
||||
lay2.addWidget(label2)
|
||||
value2 = QtGui.QDoubleSpinBox()
|
||||
value2.setDecimals(2)
|
||||
value2.setValue(self.Width)
|
||||
lay2.addWidget(value2)
|
||||
|
||||
lay3 = QtGui.QHBoxLayout()
|
||||
lay0.addLayout(lay3)
|
||||
label3 = QtGui.QLabel(str(translate("Arch","Height")))
|
||||
lay3.addWidget(label3)
|
||||
value3 = QtGui.QDoubleSpinBox()
|
||||
value3.setDecimals(2)
|
||||
value3.setValue(self.Height)
|
||||
lay3.addWidget(value3)
|
||||
|
||||
value4 = QtGui.QCheckBox(str(translate("Arch","Continue")))
|
||||
lay0.addWidget(value4)
|
||||
|
||||
QtCore.QObject.connect(value1,QtCore.SIGNAL("valueChanged(double)"),self.setLength)
|
||||
QtCore.QObject.connect(value2,QtCore.SIGNAL("valueChanged(double)"),self.setWidth)
|
||||
QtCore.QObject.connect(value3,QtCore.SIGNAL("valueChanged(double)"),self.setHeight)
|
||||
QtCore.QObject.connect(value4,QtCore.SIGNAL("stateChanged(int)"),self.setContinue)
|
||||
return w
|
||||
|
||||
def update(self,point):
|
||||
"this function is called by the Snapper when the mouse is moved"
|
||||
self.tracker.pos(point)
|
||||
|
||||
def setWidth(self,d):
|
||||
self.Width = d
|
||||
self.tracker.width(d)
|
||||
|
||||
def setHeight(self,d):
|
||||
self.Height = d
|
||||
self.tracker.height(d)
|
||||
|
||||
def setLength(self,d):
|
||||
self.Length = d
|
||||
self.tracker.length(d)
|
||||
|
||||
def setContinue(self,i):
|
||||
self.continueCmd = bool(i)
|
||||
|
||||
class _Structure(ArchComponent.Component):
|
||||
"The Structure object"
|
||||
|
|
|
@ -335,6 +335,19 @@ class _Wall(ArchComponent.Component):
|
|||
self.hideSubobjects(obj,prop)
|
||||
if prop in ["Base","Height","Width","Align","Additions","Subtractions"]:
|
||||
self.createGeometry(obj)
|
||||
# propagate movements to children windows
|
||||
if prop == "Placement":
|
||||
if obj.Shape:
|
||||
if not obj.Shape.isNull():
|
||||
vo = obj.Shape.Placement.Base
|
||||
vn = obj.Placement.Base
|
||||
if not DraftVecUtils.equals(vo,vn):
|
||||
delta = vn.sub(vo)
|
||||
for o in obj.OutList:
|
||||
if (Draft.getType(o) == "Window") or Draft.isClone(o,"Window"):
|
||||
o.Placement.move(delta)
|
||||
|
||||
|
||||
|
||||
def getDefaultValues(self,obj):
|
||||
"returns normal,width,height values from this wall"
|
||||
|
@ -472,6 +485,10 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
|
|||
|
||||
def getIcon(self):
|
||||
import Arch_rc
|
||||
if hasattr(self,"Object"):
|
||||
for o in self.Object.OutList:
|
||||
if Draft.getType(o) == "Wall":
|
||||
return ":/icons/Arch_Wall_Tree_Assembly.svg"
|
||||
return ":/icons/Arch_Wall_Tree.svg"
|
||||
|
||||
def getDisplayModes(self,vobj):
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Resource object code
|
||||
#
|
||||
# Created: Sun Mar 24 15:50:46 2013
|
||||
# Created: Wed Apr 17 16:59:58 2013
|
||||
# by: The Resource Compiler for PyQt (Qt v4.8.2)
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -27968,6 +27968,163 @@ qt_resource_data = "\
|
|||
\xba\x70\x69\x20\x5a\xa2\xbd\xe0\xab\x69\x8b\x99\x5e\x5b\x43\xe6\
|
||||
\xc8\x70\xb7\x67\xbb\xbc\x3a\xbb\x70\x5b\x40\x57\x67\xff\x01\xbd\
|
||||
\xf5\xc0\x77\
|
||||
\x00\x00\x09\xaf\
|
||||
\x00\
|
||||
\x00\x5c\xa6\x78\x9c\xed\x5c\x6d\x6f\xdb\x38\x12\xfe\x9e\x5f\xa1\
|
||||
\x73\xbf\xec\xe2\x2c\x9a\xef\x2f\x6e\x92\xc5\xe1\x8a\x05\x16\xb8\
|
||||
\xfb\xb2\xdb\xc3\x7e\x2c\x64\x89\x76\xb4\x95\x25\x43\x92\xe3\xa4\
|
||||
\xbf\xfe\x86\xb2\x2c\x4b\xb6\xeb\xa4\x75\x92\x26\x6b\xb9\x48\x13\
|
||||
\x91\x43\x8a\x1c\x3e\x9c\x79\x66\xc8\xe4\xf2\x97\xbb\x79\xe2\xdd\
|
||||
\xda\xbc\x88\xb3\xf4\x6a\x40\x10\x1e\x78\x36\x0d\xb3\x28\x4e\x67\
|
||||
\x57\x83\xff\x7d\xfc\xd5\xd7\x03\xaf\x28\x83\x34\x0a\x92\x2c\xb5\
|
||||
\x57\x83\x34\x1b\xfc\x72\x7d\x71\xf9\x0f\xdf\xf7\xfe\x9d\xdb\xa0\
|
||||
\xb4\x91\xb7\x8a\xcb\x1b\xef\xb7\xf4\x73\x11\x06\x0b\xeb\xfd\x74\
|
||||
\x53\x96\x8b\xf1\x68\xb4\x5a\xad\x50\x5c\x17\xa2\x2c\x9f\x8d\x7e\
|
||||
\xf6\x7c\xff\xfa\xe2\xe2\xb2\xb8\x9d\x5d\x78\x9e\x07\xef\x4d\x8b\
|
||||
\x71\x14\x5e\x0d\xea\x06\x8b\x65\x9e\x54\x82\x51\x38\xb2\x89\x9d\
|
||||
\xdb\xb4\x2c\x46\x04\x91\xd1\x60\x2b\x1e\x6e\xc5\x43\xf7\xf6\xf8\
|
||||
\xd6\x86\xd9\x7c\x9e\xa5\x45\xd5\x32\x2d\xde\xb5\x84\xf3\x68\xda\
|
||||
\x48\xbb\xd1\xac\x58\x25\x44\x8c\x31\x23\x4c\x47\x94\xfa\x20\xe1\
|
||||
\x17\xf7\x69\x19\xdc\xf9\xdd\xa6\x30\xc6\x43\x4d\x29\xc6\x78\x04\
|
||||
\x75\x5b\xc9\xc7\x49\x8d\x0b\x50\xe8\x02\xbe\x1a\xf1\x4d\x01\x2a\
|
||||
\xb2\x65\x1e\xda\x29\xb4\xb3\x28\xb5\xe5\xe8\xc3\xc7\x0f\x4d\xa5\
|
||||
\x8f\x51\x54\x46\xad\x6e\x36\xfa\xec\xbc\xb5\xa3\xe4\x34\x98\xdb\
|
||||
\x62\x11\x84\xb6\x18\x6d\xca\xab\xf6\xab\x38\x2a\x6f\xae\x06\x92\
|
||||
\x2f\xee\xaa\xe7\x1b\x1b\xcf\x6e\xca\x56\x41\x1c\x5d\x0d\x60\xcc\
|
||||
\x54\x13\x59\x3d\xb7\x20\x41\xd6\x02\x75\x77\xe3\xa6\x06\x23\xae\
|
||||
\x11\x43\xc4\xcb\x8d\xd6\xeb\x56\x9b\x91\x8f\xa3\x2c\x74\x43\xb9\
|
||||
\x1a\xfc\x2b\x0f\x6f\x3e\xfd\x19\x24\xc9\xa7\x8f\xb9\xb5\xc8\xa9\
|
||||
\xe5\x1a\x24\x2f\x23\x3b\x2d\x5c\x8b\xf5\x9b\xdd\x13\xbc\x5a\x57\
|
||||
\x75\x50\xdb\xbc\x6c\x01\x2f\x5b\xd8\xd0\x2d\xf4\x5a\xba\xf5\x8e\
|
||||
\xf2\xde\x69\xa2\x2b\xca\xd6\xea\xf2\x3a\x03\x5e\x7c\xba\x83\xd1\
|
||||
\x7a\x63\x8f\x51\xf8\x8f\x1c\x94\xb8\x5f\x4b\x10\x58\x3b\xf8\x86\
|
||||
\x0f\xca\x7c\x71\xfa\x3a\xd2\x4d\x3d\x02\x3f\xcb\xe3\x59\x0c\x0a\
|
||||
\xaa\xe4\x28\x41\xac\xfa\x74\xdb\xc0\xa4\x5b\x73\xa3\x9a\xf2\x81\
|
||||
\x37\x7a\xc4\xec\x77\x1a\x32\x49\xe9\xc3\x03\xc1\x48\xb8\x49\xd5\
|
||||
\x03\xd9\x1d\x4a\x77\x86\xa4\x92\x14\x27\x29\xaa\x56\xf7\x6e\x37\
|
||||
\x0f\xad\xdc\xf7\x2a\xc0\x37\x67\xae\x02\xc1\xce\x5c\x01\x4a\x9c\
|
||||
\xb9\x02\x8c\x3a\x6f\x05\x28\x7a\x60\x0c\x67\xa5\x00\x7e\xe6\x7e\
|
||||
\x40\x49\x7e\xe6\x0a\xd0\x67\x6e\x04\x35\x96\x67\xaf\x00\xff\xcc\
|
||||
\x99\x80\x66\x7f\xb7\x4d\x70\x39\x72\xc1\x51\xf5\x53\xd3\xc0\x85\
|
||||
\x56\xd1\x6d\x6c\x57\xdb\x08\x6a\x12\x14\xb6\xee\x79\x11\xcc\x20\
|
||||
\x2a\x4e\xb2\xfc\x6a\xf0\x6e\x5a\x7d\xea\x8a\x49\x96\x47\x36\xdf\
|
||||
\x54\xc9\xea\xd3\xa9\xca\x20\x72\x8c\xcb\xfb\x75\x1e\xe0\x62\x47\
|
||||
\x89\xd0\x6b\x53\x8f\x0f\xd7\x17\x37\x41\x94\xad\xae\x06\x74\xb7\
|
||||
\xf2\x4b\x96\xcd\xa1\x57\xb2\x5b\x1e\x82\x6a\x88\x44\x04\x2b\x2e\
|
||||
\xcc\x5e\x25\xbc\x88\x31\x44\x89\x62\x8d\x69\xdb\x56\x2e\xf3\xdc\
|
||||
\xa6\xa5\x9f\x04\xf7\x16\x66\x53\x7d\xdb\x74\x5f\xdc\x64\xab\x59\
|
||||
\xee\xb4\x52\xe6\x4b\xbb\xdb\x12\x42\xd3\xa5\x4b\x2e\xf8\xcb\x34\
|
||||
\x2e\x21\x80\xaf\x03\xe0\x96\x84\x6b\xeb\x4f\x26\xd9\xdd\xe1\x0e\
|
||||
\x8a\x34\x58\x1c\xa9\x76\x35\xfe\x22\x28\x6f\x8a\x23\xf5\x69\x16\
|
||||
\xd9\xaf\xd4\x37\xdd\xfb\x36\x9a\x59\x7f\x1e\x47\x8b\x2c\x4e\xcb\
|
||||
\x07\xa5\x1f\x10\xcc\x26\x7f\xc1\x1e\x39\x36\xb0\x5a\xe2\xc8\xd0\
|
||||
\x56\x71\x0a\xeb\xeb\xd7\xc9\x04\x62\xe8\x1e\x0a\x6a\x89\x4d\x7a\
|
||||
\x81\x60\xa1\xbe\x22\xe2\x36\xc5\x57\xaa\xee\xbf\x5e\x35\x0f\xee\
|
||||
\xe2\x79\xfc\xc5\xc2\xda\xee\x81\xa9\x52\x45\x3d\xfa\x69\x90\x14\
|
||||
\x87\x75\x35\x4b\xb2\x49\x90\x6c\x24\xea\x3d\x36\xb7\x65\x10\x05\
|
||||
\x65\xb0\xdd\x4f\x9b\x12\x88\xcc\xc9\x26\x2b\x91\x47\xd3\xf1\xef\
|
||||
\x1f\x7e\xbd\xae\x37\xf0\x65\x18\x8e\xff\xcc\xf2\xcf\x9b\xfd\xec\
|
||||
\x79\x4e\x20\x98\x64\x4b\x98\xf9\xe0\xba\x29\xbe\x8c\xc2\xf1\x34\
|
||||
\xcb\xe7\x41\x79\x1d\xcf\x61\x97\xb8\xdc\xd0\x3f\xef\xe6\x09\xec\
|
||||
\xec\xa6\xa2\x23\xec\xec\xc1\xb6\xd3\x75\xb7\xb9\x5d\x67\x8a\x0e\
|
||||
\xa6\xcb\xa2\x70\x1e\xbb\x46\xa3\x3f\xca\x38\x49\x7e\x73\x2f\x69\
|
||||
\xcc\x67\xd3\x69\x5c\x26\xf6\xba\x7a\xe7\xfa\xc7\xcd\x2c\x46\xf5\
|
||||
\x34\xea\x49\x8e\x5a\xb3\xbc\x1c\x6d\xd4\x50\x3d\xcd\xb6\xea\xe9\
|
||||
\xec\xb7\x46\xc1\x49\x30\xb1\xa0\xda\xff\xb8\x4a\x6f\xaf\x76\x96\
|
||||
\x67\xcb\xc5\x1c\xd6\xa7\x6e\xde\xa8\x15\x50\xd7\xd8\xc4\xf2\x3e\
|
||||
\x81\xfa\xca\x46\x8d\xdf\xe1\xea\xf3\x7e\x0a\x93\x1a\xbf\x53\x81\
|
||||
\xfb\x57\x3d\xf8\xb5\x21\x1a\x93\xf5\x63\xbe\x4c\xec\xd8\xde\x5a\
|
||||
\x58\xfc\xe8\x7d\x51\xe6\xd9\x67\xdb\x34\x5e\x3f\xae\x31\x3b\x26\
|
||||
\xc8\x68\x0a\x56\x8f\x8a\x4d\x79\x12\xa7\x16\x46\x37\x9e\x2c\xcb\
|
||||
\xb2\x5d\xf6\x17\x6c\xa5\x31\x0c\x38\xdd\x74\x08\xfb\xab\xb4\x79\
|
||||
\x02\xe8\x2b\xc7\x7c\x53\xb6\x1d\x47\x5d\x10\x05\x60\x03\xf3\x3c\
|
||||
\xb8\x1f\xa7\x59\x6a\xdb\xa5\xd9\x74\x5a\xd8\x72\x8c\xdf\xcf\x83\
|
||||
\xfc\xb3\xcd\xd7\xf5\xb7\x71\x11\x4f\xe2\xc4\x75\x51\xfd\x98\xd8\
|
||||
\xf7\x51\x5c\x2c\x40\x3d\xe3\x38\x75\xc3\x78\x9f\xdd\xda\x7c\x9a\
|
||||
\x64\xab\xa6\xde\xa6\x01\x7c\xf3\x27\x41\xf8\x79\x56\x8d\x6f\x1c\
|
||||
\x84\x60\xd0\x96\x49\x50\xda\xad\xf7\x81\x25\x72\x6a\xa5\x9a\x63\
|
||||
\x9f\xf9\xdc\xc7\xbe\xf6\xb7\x9e\xb1\xde\xc0\x1a\x69\x23\x0d\xa3\
|
||||
\x5b\xda\xd4\xa4\x05\x11\x27\x42\x6a\xbc\xa5\xd4\xb0\x5d\x05\x58\
|
||||
\x7d\x8a\x25\xd1\x4d\x21\x6c\x54\x8d\x91\x26\x9a\xc8\x6d\x0a\xa6\
|
||||
\xcc\x83\xb4\x70\xb0\x86\x4d\x14\x94\x79\x7c\xf7\x13\x88\x60\x86\
|
||||
\x15\x36\x72\xe8\x83\x13\x34\x42\x6b\xc6\xc9\x10\x0f\xdd\x17\xfe\
|
||||
\x79\xeb\xe9\x1f\x89\x84\xb5\x53\x3b\x15\x09\x1a\xe6\xc2\x89\x31\
|
||||
\x67\x84\x04\xb5\x8b\x00\xc2\x11\xd1\x9a\x72\x7d\x00\x01\x4c\x02\
|
||||
\x32\x74\x07\x01\x54\x21\x63\x08\x26\xac\x8d\x00\xa6\x11\xc5\x84\
|
||||
\x6a\x79\x14\x01\x46\x50\x26\x25\x83\x15\x47\x0c\x73\x23\x24\xef\
|
||||
\xd7\xff\xc5\xd7\xdf\xf8\xf2\x44\x04\x70\x86\x04\xa1\x42\xec\x00\
|
||||
\x80\x18\x00\x05\x3d\x1d\x00\x8e\x9d\x3c\x02\x00\xa1\x72\xff\x4e\
|
||||
\x05\x80\x52\x52\x09\x82\xf9\xdf\x1b\x00\x8e\xcb\x78\x40\xa3\x35\
|
||||
\xa6\x42\x8a\x21\x27\x88\x33\xa1\x0c\xf3\x48\xb5\x94\x1c\x9b\x21\
|
||||
\x47\xb0\xce\xca\x48\xcf\x57\x88\x70\xae\xa5\x1e\x0a\x58\x24\x22\
|
||||
\x98\xf0\xfc\xad\x98\x5f\xcb\x29\xaf\x11\xf3\x6b\x39\xee\x7d\xf9\
|
||||
\x9a\xef\x11\xd5\xd7\x36\x30\xda\x06\x31\xc0\x04\x1c\x69\x01\xb6\
|
||||
\x16\xba\xcf\x7e\xe8\x14\x66\x29\xac\x48\x99\xe5\x3e\xb0\xfd\xdb\
|
||||
\xa0\x5c\xe6\xd6\x31\xc3\x1e\x2d\xcf\x8c\x16\xae\x91\xd0\x5c\x09\
|
||||
\x40\x8b\x8b\xcd\x84\x24\x7c\x1f\x2d\x6a\x1f\x2d\xfc\x69\xd0\xf2\
|
||||
\x2c\x58\xe9\x49\xe6\x4b\x90\x4c\xb1\xef\x60\xbe\x91\x64\x82\x7d\
|
||||
\x32\xc2\x28\x61\xda\x1e\x46\x3a\x5f\x24\x31\x16\x3d\xc9\x7c\x0b\
|
||||
\x48\xa0\x27\x92\x0c\xa6\x10\xc6\x5c\xd1\x2e\xcd\x84\x45\x65\x4c\
|
||||
\x60\xf6\x62\x34\xb3\xb7\x05\x27\xd8\x82\x53\x83\x4d\xa9\x11\xa7\
|
||||
\x4a\xea\x8e\x1d\x30\x12\x09\xac\xb5\x7c\x49\x3b\xd0\xa3\xe0\x24\
|
||||
\x8f\xb0\x17\x72\x7e\x2b\x0e\x30\x52\x04\xe3\x8e\x29\xd0\x14\x81\
|
||||
\xc9\x68\x1f\xf7\x9c\x00\x83\x9e\x44\x3e\x13\x89\xa4\x88\x69\x69\
|
||||
\x88\x19\x32\x58\x58\xc9\x99\xa6\xc7\x48\xa4\x7a\x1c\x89\x54\x8f\
|
||||
\x23\x91\xf4\xb9\xc3\x8d\x87\x1a\xf5\x88\x7a\x96\x20\xd6\x70\xc1\
|
||||
\xb4\x1a\xba\x70\x16\x48\x95\x22\x9e\x74\xd6\x84\x70\x39\x04\x93\
|
||||
\xc0\x09\x93\xe6\x60\x54\xd2\x48\xf9\xb5\x98\x3e\x06\x1e\xee\x1f\
|
||||
\x38\xa3\xdb\x83\x4f\xcf\x27\x5f\xcc\x8f\xec\xc5\x14\x1c\xc1\xfa\
|
||||
\x6a\xd1\xba\xf1\xd1\xe2\x93\x4a\x77\x2e\x45\xba\xc4\x35\x45\x0a\
|
||||
\x53\x2e\xd4\x0e\x9f\x94\x94\x51\x72\x3c\x71\xdd\xf3\xc9\x57\x81\
|
||||
\x80\x2a\xb6\x3c\x9d\x51\x52\x05\x9b\xbf\xc3\x28\x35\x74\x42\x25\
|
||||
\x7e\x1a\x46\xd9\x3b\x88\x1f\xeb\x20\x84\x42\x0c\x5c\x00\xe1\x2e\
|
||||
\xcb\x09\x7e\x42\x48\xe9\x71\x24\xa1\x88\xb1\x21\x41\xe0\x3b\x04\
|
||||
\x3f\xe8\x1f\x6a\x21\x3e\xf4\xd7\x52\xcc\x1c\xf5\x0f\xdf\xe2\x1d\
|
||||
\x7a\x4c\xfc\x60\xd2\x40\x91\x10\x8a\x4a\x3a\x24\xb0\xb6\xc0\x1f\
|
||||
\x04\xf1\x0c\xa2\x58\x70\xe0\x11\xe0\x17\x60\x51\x09\x90\x06\x42\
|
||||
\x11\x81\x7d\x6d\xd4\x50\x23\x77\x96\x01\x52\x7e\x23\xe6\x37\x72\
|
||||
\x47\xf3\x96\xa4\x75\xf9\xea\xe9\x78\x43\xef\x35\x4e\xf1\x1a\xc0\
|
||||
\xe5\x60\x6d\xc8\xae\xeb\x20\x02\x61\x89\xdb\x8c\x60\xe3\x3a\x34\
|
||||
\xe0\xc0\x18\xae\xba\x27\xdf\xcc\x79\x7f\x21\x3a\x27\xdf\x92\x23\
|
||||
\xc1\x01\x28\x7d\x2e\xe2\x4d\x61\x81\x9f\x88\x05\x2e\x20\x9a\xc5\
|
||||
\x58\x76\xb0\x20\xa0\x0f\xae\x0c\xe5\x3d\x18\xde\x0e\x18\x4e\x04\
|
||||
\x02\x83\xa8\x52\xb2\x4e\x62\x0a\xb0\x01\x51\x26\xe1\x7d\x7e\xf2\
|
||||
\xad\xc0\xc0\xd7\x27\x67\x28\xb9\x41\x46\x61\x4e\x3b\x77\x22\xa4\
|
||||
\x40\x82\x11\xfa\xa2\x99\xea\x3e\xc3\xf0\x9d\x48\x38\xf5\xbc\xca\
|
||||
\x5d\x8b\x72\x11\x45\x07\x01\x94\x22\x03\xc4\x13\xbf\x5c\x7e\xa1\
|
||||
\x5f\xff\xef\xbe\x16\x75\x2a\x02\x38\x43\x5c\x61\xda\x4a\x3b\xd5\
|
||||
\x08\x00\xaa\x20\x9e\xe0\xc4\xb2\x8f\x22\x7f\x78\xea\x59\x49\x4a\
|
||||
\x05\x1f\x52\x89\x88\xd2\x60\xb8\x1f\x75\x23\x66\x7b\x7f\x8a\xec\
|
||||
\x9f\x65\x98\xe6\x2c\x43\x3c\x74\x7d\xea\x9b\x12\xd2\x3d\x58\x7e\
|
||||
\xf0\xc9\x97\x86\xc0\x10\x3e\x6c\xc8\xc0\xc5\xc3\x42\xd3\xa3\xd7\
|
||||
\xa7\xd4\xe3\x2e\xdb\xa9\xc7\xa2\xe5\x39\x0e\x2f\x7a\x92\x79\x52\
|
||||
\xac\x71\x7a\xe6\x9a\x29\x05\xbe\xa1\x93\xb9\x26\x88\x52\xd2\xfa\
|
||||
\xbd\xef\x9e\x60\xbe\x5a\x14\xd0\x93\x6f\xde\xbb\xfc\x24\x66\x86\
|
||||
\xef\x51\x4c\xa0\x0e\x54\xf7\x04\xe3\x0d\x23\xa5\xf2\x19\x44\x23\
|
||||
\xa9\x80\x60\xa8\xa1\xfb\x7b\x31\x42\x18\xa9\x5f\x96\x60\xb4\x8e\
|
||||
\xd7\xfa\x33\xef\xd7\x60\x30\x0e\x9d\x77\x12\xc5\x05\x69\xb9\x81\
|
||||
\xad\xc9\x70\x8b\xac\xb8\x6a\x9b\x0c\xea\xd2\x53\x94\x28\xd9\x31\
|
||||
\x19\xcc\x41\xc3\xe8\x3e\x26\x79\xcb\x58\x59\x9b\x0c\x8c\x20\xb6\
|
||||
\x14\x44\x0f\xc1\x78\x30\x41\x9d\xc9\x50\x48\x62\xc6\x88\x19\x52\
|
||||
\x77\x51\x52\x12\x71\xd0\x62\xac\xa5\x28\x26\xee\x64\xab\x96\x7b\
|
||||
\xd8\x3e\xf4\xb7\x62\x5e\x93\x85\x60\x60\x23\x0e\x65\xb0\x15\x11\
|
||||
\x10\x7c\x1c\xb0\x10\x50\x21\x0d\x21\x1d\x52\x61\x10\x15\x44\x31\
|
||||
\xde\xb6\x10\x10\xb3\x30\x6a\xf8\x53\x58\x88\x1e\x03\xcf\x8f\x81\
|
||||
\xfd\x5f\xe8\x13\xee\xef\x5a\x28\x7a\x00\x02\x40\x2b\x78\x3b\x1d\
|
||||
\xb5\x76\x12\x20\x8d\xb1\xde\x81\x80\xd6\x44\xf3\xe3\xa7\x59\x3d\
|
||||
\x04\x5e\x01\x04\x54\xeb\xce\xc1\x77\x47\x16\x60\x18\x34\xe9\x1a\
|
||||
\x01\x77\x57\x4a\x52\xd9\x23\xe0\xd5\x23\xa0\xa2\x8a\xfb\x09\x6c\
|
||||
\x83\x08\x35\x58\x99\x7d\x14\x08\xa4\x09\xb0\x06\x46\xbb\x76\x40\
|
||||
\x1a\x4c\x88\x22\x3b\x28\xd0\x8c\x4b\xfc\xc4\xbf\xd8\xdb\x93\xc5\
|
||||
\x97\x26\x8b\xff\xf5\x38\x30\x03\xa9\x18\xa6\x43\x82\xa4\x06\x2e\
|
||||
\x60\x84\x27\x38\x32\x8a\x2a\xed\xe2\x4b\xae\x60\xf1\xb5\x74\xb7\
|
||||
\xf6\x35\x61\xda\x80\x1c\x43\xe0\x45\x04\x73\xb9\x6f\x89\x01\x69\
|
||||
\x7c\x08\x8c\x53\x68\x2d\x08\x79\xf0\x1e\x54\x7f\x13\xea\x35\x99\
|
||||
\x88\xed\xed\x97\x27\xb8\x07\x45\xa8\xc2\x9d\x90\xb2\xba\xf4\x80\
|
||||
\xa5\x3e\x6e\x25\xfa\x4b\x0f\xaf\x0c\x0a\xfb\x29\x49\x09\xe6\x40\
|
||||
\xb8\x7b\x8e\x07\xc0\xc0\xb5\xc0\x82\x76\xa2\x07\xe9\xee\xd8\x1a\
|
||||
\xa2\x3a\xf7\xa9\xc1\xa6\x28\x0c\x2e\xe3\xf4\x5b\x71\x97\xa3\xd9\
|
||||
\xf5\xc5\xa5\xfb\x5b\x49\xd7\x17\xff\x07\x1e\x03\x47\xa2\
|
||||
\x00\x00\x08\x6a\
|
||||
\x00\
|
||||
\x00\x47\x9a\x78\x9c\xed\x5a\xdd\x6f\xe3\x36\x12\x7f\xcf\x5f\xa1\
|
||||
|
@ -33045,6 +33202,11 @@ qt_resource_name = "\
|
|||
\x00\x41\
|
||||
\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x43\x00\x65\x00\x6c\x00\x6c\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x2e\x00\x73\x00\x76\
|
||||
\x00\x67\
|
||||
\x00\x1b\
|
||||
\x08\x25\x0d\x47\
|
||||
\x00\x41\
|
||||
\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x57\x00\x61\x00\x6c\x00\x6c\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x5f\x00\x41\x00\x73\
|
||||
\x00\x73\x00\x65\x00\x6d\x00\x62\x00\x6c\x00\x79\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x0d\
|
||||
\x09\x3c\x92\x47\
|
||||
\x00\x41\
|
||||
|
@ -33179,8 +33341,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\x39\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00\x1b\
|
||||
\x00\x00\x00\x10\x00\x02\x00\x00\x00\x01\x00\x00\x00\x3a\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1f\x00\x00\x00\x1b\
|
||||
\x00\x00\x00\x1a\x00\x02\x00\x00\x00\x17\x00\x00\x00\x04\
|
||||
\x00\x00\x01\x2e\x00\x00\x00\x00\x00\x01\x00\x02\x9d\x23\
|
||||
\x00\x00\x02\x92\x00\x00\x00\x00\x00\x01\x00\x06\x6c\x9e\
|
||||
|
@ -33205,35 +33367,36 @@ qt_resource_struct = "\
|
|||
\x00\x00\x01\x14\x00\x00\x00\x00\x00\x01\x00\x02\x52\xbc\
|
||||
\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x01\x00\x01\xbc\xaa\
|
||||
\x00\x00\x02\x3e\x00\x00\x00\x00\x00\x01\x00\x05\x84\xf1\
|
||||
\x00\x00\x06\x5a\x00\x01\x00\x00\x00\x01\x00\x07\xa2\x92\
|
||||
\x00\x00\x05\x3a\x00\x00\x00\x00\x00\x01\x00\x07\x59\x96\
|
||||
\x00\x00\x03\xd6\x00\x00\x00\x00\x00\x01\x00\x06\xfb\x9a\
|
||||
\x00\x00\x07\x8a\x00\x01\x00\x00\x00\x01\x00\x07\xfa\x67\
|
||||
\x00\x00\x06\x2c\x00\x01\x00\x00\x00\x01\x00\x07\x9b\xbd\
|
||||
\x00\x00\x04\x10\x00\x01\x00\x00\x00\x01\x00\x07\x0a\x09\
|
||||
\x00\x00\x04\x62\x00\x01\x00\x00\x00\x01\x00\x07\x1d\x90\
|
||||
\x00\x00\x03\x7a\x00\x01\x00\x00\x00\x01\x00\x06\xe0\xf8\
|
||||
\x00\x00\x07\x24\x00\x00\x00\x00\x00\x01\x00\x07\xd7\x23\
|
||||
\x00\x00\x05\x7a\x00\x00\x00\x00\x00\x01\x00\x07\x73\x70\
|
||||
\x00\x00\x05\x1a\x00\x01\x00\x00\x00\x01\x00\x07\x51\xce\
|
||||
\x00\x00\x03\x58\x00\x01\x00\x00\x00\x01\x00\x06\xd7\xff\
|
||||
\x00\x00\x06\x00\x00\x01\x00\x00\x00\x01\x00\x07\x90\x93\
|
||||
\x00\x00\x06\xfa\x00\x01\x00\x00\x00\x01\x00\x07\xcf\x8e\
|
||||
\x00\x00\x04\x3e\x00\x01\x00\x00\x00\x01\x00\x07\x13\x61\
|
||||
\x00\x00\x03\x0e\x00\x01\x00\x00\x00\x01\x00\x06\xc5\xe9\
|
||||
\x00\x00\x06\x96\x00\x01\x00\x00\x00\x01\x00\x07\xac\x45\
|
||||
\x00\x00\x05\x76\x00\x00\x00\x00\x00\x01\x00\x07\x63\x49\
|
||||
\x00\x00\x04\x12\x00\x00\x00\x00\x00\x01\x00\x07\x05\x4d\
|
||||
\x00\x00\x07\xc6\x00\x01\x00\x00\x00\x01\x00\x08\x04\x1a\
|
||||
\x00\x00\x06\x68\x00\x01\x00\x00\x00\x01\x00\x07\xa5\x70\
|
||||
\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x07\x13\xbc\
|
||||
\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x07\x27\x43\
|
||||
\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\xea\xab\
|
||||
\x00\x00\x07\x60\x00\x00\x00\x00\x00\x01\x00\x07\xe0\xd6\
|
||||
\x00\x00\x05\xb6\x00\x00\x00\x00\x00\x01\x00\x07\x7d\x23\
|
||||
\x00\x00\x05\x56\x00\x01\x00\x00\x00\x01\x00\x07\x5b\x81\
|
||||
\x00\x00\x03\x94\x00\x01\x00\x00\x00\x01\x00\x06\xe1\xb2\
|
||||
\x00\x00\x06\x3c\x00\x01\x00\x00\x00\x01\x00\x07\x9a\x46\
|
||||
\x00\x00\x03\x38\x00\x01\x00\x00\x00\x01\x00\x06\xcf\x91\
|
||||
\x00\x00\x05\xaa\x00\x01\x00\x00\x00\x01\x00\x07\x82\xde\
|
||||
\x00\x00\x04\xce\x00\x00\x00\x00\x00\x01\x00\x07\x39\x8b\
|
||||
\x00\x00\x05\xd8\x00\x01\x00\x00\x00\x01\x00\x07\x88\x2e\
|
||||
\x00\x00\x04\xf8\x00\x01\x00\x00\x00\x01\x00\x07\x4a\x0c\
|
||||
\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x07\xaa\xd7\
|
||||
\x00\x00\x04\x86\x00\x01\x00\x00\x00\x01\x00\x07\x22\xa7\
|
||||
\x00\x00\x06\xce\x00\x01\x00\x00\x00\x01\x00\x07\xc7\x14\
|
||||
\x00\x00\x06\xae\x00\x01\x00\x00\x00\x01\x00\x07\xbc\xda\
|
||||
\x00\x00\x05\x5a\x00\x01\x00\x00\x00\x01\x00\x07\x6d\x58\
|
||||
\x00\x00\x07\x50\x00\x00\x00\x00\x00\x01\x00\x07\xe8\xf2\
|
||||
\x00\x00\x03\xac\x00\x00\x00\x00\x00\x01\x00\x06\xe9\x3a\
|
||||
\x00\x00\x04\xb0\x00\x00\x00\x00\x00\x01\x00\x07\x2a\x8f\
|
||||
\x00\x00\x07\x36\x00\x01\x00\x00\x00\x01\x00\x07\xd9\x41\
|
||||
\x00\x00\x04\x7a\x00\x01\x00\x00\x00\x01\x00\x07\x1d\x14\
|
||||
\x00\x00\x03\x0e\x00\x01\x00\x00\x00\x01\x00\x06\xc5\xe9\
|
||||
\x00\x00\x03\x74\x00\x01\x00\x00\x00\x01\x00\x06\xd9\x44\
|
||||
\x00\x00\x05\xe6\x00\x01\x00\x00\x00\x01\x00\x07\x8c\x91\
|
||||
\x00\x00\x05\x0a\x00\x00\x00\x00\x00\x01\x00\x07\x43\x3e\
|
||||
\x00\x00\x06\x14\x00\x01\x00\x00\x00\x01\x00\x07\x91\xe1\
|
||||
\x00\x00\x05\x34\x00\x01\x00\x00\x00\x01\x00\x07\x53\xbf\
|
||||
\x00\x00\x06\xc0\x00\x00\x00\x00\x00\x01\x00\x07\xb4\x8a\
|
||||
\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x07\x2c\x5a\
|
||||
\x00\x00\x07\x0a\x00\x01\x00\x00\x00\x01\x00\x07\xd0\xc7\
|
||||
\x00\x00\x06\xea\x00\x01\x00\x00\x00\x01\x00\x07\xc6\x8d\
|
||||
\x00\x00\x05\x96\x00\x01\x00\x00\x00\x01\x00\x07\x77\x0b\
|
||||
\x00\x00\x07\x8c\x00\x00\x00\x00\x00\x01\x00\x07\xf2\xa5\
|
||||
\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x06\xf2\xed\
|
||||
\x00\x00\x04\xec\x00\x00\x00\x00\x00\x01\x00\x07\x34\x42\
|
||||
\x00\x00\x02\xda\x00\x01\x00\x00\x00\x01\x00\x06\xbe\x99\
|
||||
\x00\x00\x02\xb2\x00\x01\x00\x00\x00\x01\x00\x06\xb6\xfd\
|
||||
"
|
||||
|
|
|
@ -21,6 +21,7 @@ SET(Arch_SRCS
|
|||
ArchAxis.py
|
||||
ArchVRM.py
|
||||
ArchRoof.py
|
||||
importWebGL.py
|
||||
)
|
||||
SOURCE_GROUP("" FILES ${Arch_SRCS})
|
||||
|
||||
|
|
|
@ -129,6 +129,7 @@ class ArchWorkbench(Workbench):
|
|||
FreeCADGui.addWorkbench(ArchWorkbench)
|
||||
FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC")
|
||||
FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ")
|
||||
FreeCAD.addExportType("WebGL file (*.html)","importWebGL")
|
||||
# check for pycollada
|
||||
try:
|
||||
import collada
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
<file>icons/Arch_Check.svg</file>
|
||||
<file>icons/Arch_SelectNonManifold.svg</file>
|
||||
<file>icons/Arch_MergeWalls.svg</file>
|
||||
<file>icons/Arch_Wall_Tree_Assembly.svg</file>
|
||||
<file>ui/archprefs-base.ui</file>
|
||||
<file>translations/Arch_af.qm</file>
|
||||
<file>translations/Arch_de.qm</file>
|
||||
|
|
415
src/Mod/Arch/Resources/icons/Arch_Wall_Tree_Assembly.svg
Normal file
415
src/Mod/Arch/Resources/icons/Arch_Wall_Tree_Assembly.svg
Normal file
|
@ -0,0 +1,415 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2816"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="Arch_Wall_Tree.svg">
|
||||
<defs
|
||||
id="defs2818">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2824" />
|
||||
<inkscape:perspective
|
||||
id="perspective3622"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3622-9"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3653"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3675"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3697"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3720"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3742"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3764"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3785"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3806"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3806-3"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3835"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11"
|
||||
inkscape:cx="16.107459"
|
||||
inkscape:cy="33.217385"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1057"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-global="false" />
|
||||
<metadata
|
||||
id="metadata2821">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-0-8-5"
|
||||
width="8.8969326"
|
||||
height="6.4156804"
|
||||
x="50.020618"
|
||||
y="80.818169"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-7"
|
||||
width="14.188248"
|
||||
height="6.3632684"
|
||||
x="27.991013"
|
||||
y="38.201286"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-9-6"
|
||||
width="14.188248"
|
||||
height="6.3632684"
|
||||
x="43.51255"
|
||||
y="38.190132"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 33.802565,41.435793 13.512409,4.326796 -7.144868,5.301535 -13.512409,-4.326797 7.144868,-5.301534 z"
|
||||
id="rect2840-3-5-3-5-0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 48.584755,46.105614 13.512409,4.326797 -7.144868,5.301534 -13.512409,-4.326797 7.144868,-5.301534 z"
|
||||
id="rect2840-3-5-3-0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-0-5-6"
|
||||
width="8.8969326"
|
||||
height="6.4156804"
|
||||
x="41.959759"
|
||||
y="66.366005"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-3-2"
|
||||
width="14.188248"
|
||||
height="6.3632684"
|
||||
x="37.004723"
|
||||
y="30.533503"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-5"
|
||||
width="8.8969326"
|
||||
height="6.4156804"
|
||||
x="68.427689"
|
||||
y="96.508865"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-0-7"
|
||||
width="8.8969326"
|
||||
height="6.4156804"
|
||||
x="60.71003"
|
||||
y="82.268806"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 42.386919,36.464382 13.512409,4.326797 -7.144867,5.301534 -13.512409,-4.326797 7.144867,-5.301534 z"
|
||||
id="rect2840-3-5-2"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 33.945387,33.819971 6.896146,2.241369 -7.144868,5.301534 -6.896146,-2.241368 z"
|
||||
id="rect2840-3-5-4-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-3-6"
|
||||
width="4.8688564"
|
||||
height="6.3783622"
|
||||
x="52.702457"
|
||||
y="30.623219"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-0-5"
|
||||
width="8.8969326"
|
||||
height="6.4156804"
|
||||
x="68.274139"
|
||||
y="88.826065"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 57.336914,41.387566 4.636933,1.45354 -7.144868,5.301534 -4.636934,-1.453539 z"
|
||||
id="rect2840-3-5-4"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 32.557262,11.494551 9.205487,2.784019 -12.158897,8.901351 -9.205487,-2.784019 z"
|
||||
id="rect2840-3-5-3-1-3"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-04-1-5-1"
|
||||
width="15.060457"
|
||||
height="8.1599474"
|
||||
x="53.304558"
|
||||
y="64.54351"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-04-1-5-4"
|
||||
width="15.060457"
|
||||
height="8.1599474"
|
||||
x="45.460068"
|
||||
y="55.047924"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-04-1"
|
||||
width="15.060457"
|
||||
height="8.1599474"
|
||||
x="36.8633"
|
||||
y="45.146145"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-0-8-7"
|
||||
width="8.8969326"
|
||||
height="6.4156804"
|
||||
x="49.970425"
|
||||
y="65.531265"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-2"
|
||||
width="14.188248"
|
||||
height="6.3632684"
|
||||
x="27.948685"
|
||||
y="22.957209"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-9-2"
|
||||
width="14.188248"
|
||||
height="6.3632684"
|
||||
x="43.470222"
|
||||
y="22.946053"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 33.762254,26.178803 13.512409,4.326797 -7.144868,5.301535 -13.51241,-4.326797 7.144869,-5.301535 z"
|
||||
id="rect2840-3-5-3-5-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 48.544443,30.848624 13.512409,4.326797 -7.144867,5.301535 -13.512409,-4.326797 7.144867,-5.301535 z"
|
||||
id="rect2840-3-5-3-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-04"
|
||||
width="8.8969326"
|
||||
height="6.4156804"
|
||||
x="68.377495"
|
||||
y="81.22197"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-2-7"
|
||||
width="14.188248"
|
||||
height="6.3632684"
|
||||
x="12.103945"
|
||||
y="22.966328"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 18.672257,21.355968 13.512409,4.326797 -7.144868,5.301535 -13.51241,-4.326797 7.144869,-5.301535 z"
|
||||
id="rect2840-3-5-3-5-1-5"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-2-7-5"
|
||||
width="8.1745195"
|
||||
height="6.0153747"
|
||||
x="2.8632176"
|
||||
y="23.144983"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 10.053518,18.352968 7.603319,2.508615 -7.144868,5.301535 -7.6033201,-2.508615 z"
|
||||
id="rect2840-3-5-3-5-1-5-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-3-2-1"
|
||||
width="15.715544"
|
||||
height="6.7156911"
|
||||
x="19.251734"
|
||||
y="30.329483"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-3-2-6"
|
||||
width="15.33372"
|
||||
height="6.5594053"
|
||||
x="2.8333008"
|
||||
y="30.881844"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-7-3"
|
||||
width="14.188248"
|
||||
height="6.3632684"
|
||||
x="12.569814"
|
||||
y="38.276264"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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="rect2840-2-7-5-2"
|
||||
width="9.1290798"
|
||||
height="5.8151832"
|
||||
x="2.6901171"
|
||||
y="38.834602"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 45.767302,1.6871595 54.972789,4.4711786 42.813892,13.37253 33.608404,10.588511 z"
|
||||
id="rect2840-3-5-3-1-3-3"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-04-1-5"
|
||||
width="15.060457"
|
||||
height="8.1599474"
|
||||
x="53.312706"
|
||||
y="45.140682"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="rect2840-3-4-04-1-5-7"
|
||||
width="6.9758401"
|
||||
height="8.4850521"
|
||||
x="61.389179"
|
||||
y="54.704601"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 23 KiB |
228
src/Mod/Arch/importWebGL.py
Normal file
228
src/Mod/Arch/importWebGL.py
Normal file
|
@ -0,0 +1,228 @@
|
|||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2013 *
|
||||
#* Yorik van Havre <yorik@uncreated.net> *
|
||||
#* *
|
||||
#* 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 webgl exporter"
|
||||
|
||||
import FreeCAD,Draft,Part,DraftGeomUtils
|
||||
from DraftTools import translate
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
else:
|
||||
FreeCADGui = None
|
||||
|
||||
tab = " "
|
||||
addWireframe = False
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
pythonopen = open
|
||||
|
||||
def export(exportList,filename):
|
||||
"exports the given objects to a .html file"
|
||||
|
||||
html = getHTML(exportList)
|
||||
outfile = pythonopen(filename,"wb")
|
||||
outfile.write(html)
|
||||
outfile.close()
|
||||
FreeCAD.Console.PrintMessage(str(translate("Arch","successfully written "))+filename)
|
||||
|
||||
def getHTML(objectsList):
|
||||
"returns the complete HTML code of a viewer for the given objects"
|
||||
|
||||
# get objects data
|
||||
objectsData = ''
|
||||
for obj in objectsList:
|
||||
objectsData += getObjectData(obj)
|
||||
template = getTemplate()
|
||||
template = template.replace("$CameraData",getCameraData())
|
||||
template = template.replace("$ObjectsData",objectsData)
|
||||
return template
|
||||
|
||||
def getCameraData():
|
||||
"returns the position and direction of the camera as three.js snippet"
|
||||
|
||||
result = ""
|
||||
if FreeCADGui:
|
||||
# getting camera position
|
||||
pos = FreeCADGui.ActiveDocument.ActiveView.viewPosition().Base
|
||||
result += "camera.position.set( "
|
||||
result += str(pos.x) + ", "
|
||||
result += str(pos.y) + ", "
|
||||
result += str(pos.z) + " );\n"
|
||||
else:
|
||||
result += "camera.position.set(0,0,1000);\n"
|
||||
result += tab+"camera.lookAt( scene.position );\n"+tab
|
||||
# print result
|
||||
return result
|
||||
|
||||
def getObjectData(obj,wireframeMode="faceloop"):
|
||||
"""returns the geometry data of an object as three.js snippet. wireframeMode
|
||||
can be multimaterial, faceloop or None"""
|
||||
|
||||
result = ""
|
||||
wires = []
|
||||
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
fcmesh = obj.Shape.tessellate(0.1)
|
||||
result = "var geom = new THREE.Geometry();\n"
|
||||
# adding vertices data
|
||||
for i in range(len(fcmesh[0])):
|
||||
v = fcmesh[0][i]
|
||||
result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n"
|
||||
result += tab+"console.log(geom.vertices)\n"
|
||||
for i in range(len(fcmesh[0])):
|
||||
result += tab+"geom.vertices.push(v"+str(i)+");\n"
|
||||
# adding facets data
|
||||
for f in fcmesh[1]:
|
||||
result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n"
|
||||
for f in obj.Shape.Faces:
|
||||
for w in f.Wires:
|
||||
wo = Part.Wire(DraftGeomUtils.sortEdges(w.Edges))
|
||||
p = []
|
||||
for v in wo.Vertexes:
|
||||
p.append(v.Point)
|
||||
p.append(wo.Vertexes[0].Point)
|
||||
wires.append(p)
|
||||
|
||||
elif obj.isDerivedFrom("Mesh::Feature"):
|
||||
mesh = obj.Mesh
|
||||
result = "var geom = new THREE.Geometry();\n"
|
||||
# adding vertices data
|
||||
for p in mesh.Points:
|
||||
v = p.Vector
|
||||
i = p.Index
|
||||
result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n"
|
||||
result += tab+"console.log(geom.vertices)\n"
|
||||
for p in mesh.Points:
|
||||
result += tab+"geom.vertices.push(v"+str(p.Index)+");\n"
|
||||
# adding facets data
|
||||
for f in mesh.Facets:
|
||||
result += tab+"geom.faces.push( new THREE.Face3"+str(f.PointIndices)+" );\n"
|
||||
|
||||
if result:
|
||||
# adding a base material
|
||||
if FreeCADGui:
|
||||
col = obj.ViewObject.ShapeColor
|
||||
rgb = Draft.getrgb(col,testbw=False)
|
||||
else:
|
||||
rgb = "#888888" # test color
|
||||
result += tab+"var basematerial = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"
|
||||
#result += tab+"var basematerial = new THREE.MeshLambertMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"
|
||||
|
||||
if wireframeMode == "faceloop":
|
||||
# adding the mesh to the scene with a wireframe copy
|
||||
result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n"
|
||||
result += tab+"scene.add( mesh );\n"
|
||||
result += tab+"var linematerial = new THREE.LineBasicMaterial({color: 0x000000,});\n"
|
||||
for w in wires:
|
||||
result += tab+"var wire = new THREE.Geometry();\n"
|
||||
for p in w:
|
||||
result += tab+"wire.vertices.push(new THREE.Vector3("
|
||||
result += str(p.x)+", "+str(p.y)+", "+str(p.z)+"));\n"
|
||||
result += tab+"var line = new THREE.Line(wire, linematerial);\n"
|
||||
result += tab+"scene.add(line);\n"
|
||||
|
||||
elif wireframeMode == "multimaterial":
|
||||
# adding a wireframe material
|
||||
result += tab+"var wireframe = new THREE.MeshBasicMaterial( { color: "
|
||||
result += "0x000000, wireframe: true, transparent: true } );\n"
|
||||
result += tab+"var material = [ basematerial, wireframe ];\n"
|
||||
result += tab+"var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n"
|
||||
result += tab+"scene.add( mesh );\n"+tab
|
||||
|
||||
else:
|
||||
# adding the mesh to the scene with simple material
|
||||
result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n"
|
||||
result += tab+"scene.add( mesh );\n"+tab
|
||||
|
||||
return result
|
||||
|
||||
def getTemplate():
|
||||
"returns a html template"
|
||||
|
||||
result = """<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeCAD model</title>
|
||||
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r50/three.min.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var camera, controls, scene, renderer;
|
||||
|
||||
window.onload = function() {
|
||||
|
||||
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
|
||||
var VIEW_ANGLE = 35, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
|
||||
|
||||
renderer = new THREE.WebGLRenderer();
|
||||
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
|
||||
document.body.appendChild( renderer.domElement );
|
||||
|
||||
scene = new THREE.Scene();
|
||||
|
||||
camera = new THREE.PerspectiveCamera(
|
||||
VIEW_ANGLE, // Field of view
|
||||
ASPECT, // Aspect ratio
|
||||
NEAR, // Near plane
|
||||
FAR // Far plane
|
||||
);
|
||||
$CameraData // placeholder for the FreeCAD camera
|
||||
|
||||
controls = new THREE.TrackballControls( camera );
|
||||
controls.rotateSpeed = 1.0;
|
||||
controls.zoomSpeed = 1.2;
|
||||
controls.panSpeed = 0.8;
|
||||
controls.noZoom = false;
|
||||
controls.noPan = false;
|
||||
controls.staticMoving = true;
|
||||
controls.dynamicDampingFactor = 0.3;
|
||||
controls.keys = [ 65, 83, 68 ];
|
||||
|
||||
$ObjectsData // placeholder for the FreeCAD objects
|
||||
|
||||
var light = new THREE.PointLight( 0xFFFF00 );
|
||||
light.position.set( -10000, -10000, 10000 );
|
||||
scene.add( light );
|
||||
|
||||
renderer.render( scene, camera );
|
||||
|
||||
animate();
|
||||
};
|
||||
|
||||
function animate(){
|
||||
requestAnimationFrame( animate );
|
||||
render();
|
||||
};
|
||||
|
||||
function render(){
|
||||
controls.update();
|
||||
renderer.render( scene, camera );
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>"""
|
||||
|
||||
return result
|
||||
|
|
@ -13,6 +13,7 @@ SET(Draft_SRCS
|
|||
importDXF.py
|
||||
importOCA.py
|
||||
importSVG.py
|
||||
importDWG.py
|
||||
importAirfoilDAT.py
|
||||
macros.py
|
||||
Draft_rc.py
|
||||
|
|
|
@ -101,7 +101,7 @@ def getParamType(param):
|
|||
"modalt"]:
|
||||
return "int"
|
||||
elif param in ["constructiongroupname","textfont","patternFile","template","maxSnapEdges",
|
||||
"snapModes"]:
|
||||
"snapModes","FontFile"]:
|
||||
return "string"
|
||||
elif param in ["textheight","tolerance","gridSpacing"]:
|
||||
return "float"
|
||||
|
@ -142,6 +142,11 @@ def precision():
|
|||
def tolerance():
|
||||
"tolerance(): returns the tolerance value from Draft user settings"
|
||||
return getParam("tolerance")
|
||||
|
||||
def epsilon():
|
||||
''' epsilon(): returns a small number based on Draft.tolerance() for use in
|
||||
floating point comparisons. Use with caution. '''
|
||||
return (1.0/(10.0**tolerance()))
|
||||
|
||||
def getRealName(name):
|
||||
"getRealName(string): strips the trailing numbers from a string name"
|
||||
|
@ -803,17 +808,24 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None):
|
|||
select(obj)
|
||||
return obj
|
||||
|
||||
def makeEllipse(majradius,minradius,placement=None):
|
||||
'''makeEllipse(majradius,minradius,[placement]): makes
|
||||
def makeEllipse(majradius,minradius,placement=None,face=True,support=None):
|
||||
'''makeEllipse(majradius,minradius,[placement],[face],[support]): makes
|
||||
an ellipse with the given major and minor radius, and optionally
|
||||
a placement.'''
|
||||
import Part
|
||||
e = Part.Ellipse(FreeCAD.Vector(0,0,0),majradius,minradius)
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Ellipse")
|
||||
newobj.Shape = e.toShape()
|
||||
if placement: newobj.Placement = placement
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return newobj
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Ellipse")
|
||||
_Ellipse(obj)
|
||||
obj.MajorRadius = majradius
|
||||
obj.MinorRadius = minradius
|
||||
obj.Support = support
|
||||
if placement:
|
||||
obj.Placement = placement
|
||||
if gui:
|
||||
_ViewProviderDraft(obj.ViewObject)
|
||||
if not face:
|
||||
obj.ViewObject.DisplayMode = "Wireframe"
|
||||
formatObject(obj)
|
||||
select(obj)
|
||||
return obj
|
||||
|
||||
def extrude(obj,vector):
|
||||
'''makeExtrusion(object,vector): extrudes the given object
|
||||
|
@ -1283,18 +1295,6 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
|
|||
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)
|
||||
g = str(hex(int(color[1]*255)))[2:].zfill(2)
|
||||
b = str(hex(int(color[2]*255)))[2:].zfill(2)
|
||||
col = "#"+r+g+b
|
||||
if col == "#ffffff":
|
||||
print getParam('SvgLinesBlack')
|
||||
if getParam('SvgLinesBlack'):
|
||||
col = "#000000"
|
||||
return col
|
||||
|
||||
def getProj(vec):
|
||||
if not plane: return vec
|
||||
nx = DraftVecUtils.project(vec,plane.u)
|
||||
|
@ -1520,6 +1520,20 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
|
|||
else:
|
||||
svg = getCircle(obj.Shape.Edges[0])
|
||||
return svg
|
||||
|
||||
def getrgb(color,testbw=True):
|
||||
"""getRGB(color,[testbw]): returns a rgb value #000000 from a freecad color
|
||||
if testwb = True (default), pure white will be converted into pure black"""
|
||||
r = str(hex(int(color[0]*255)))[2:].zfill(2)
|
||||
g = str(hex(int(color[1]*255)))[2:].zfill(2)
|
||||
b = str(hex(int(color[2]*255)))[2:].zfill(2)
|
||||
col = "#"+r+g+b
|
||||
if testbw:
|
||||
if col == "#ffffff":
|
||||
#print getParam('SvgLinesBlack')
|
||||
if getParam('SvgLinesBlack'):
|
||||
col = "#000000"
|
||||
return col
|
||||
|
||||
def makeDrawingView(obj,page,lwmod=None,tmod=None):
|
||||
'''
|
||||
|
@ -1680,6 +1694,34 @@ def makePoint(X=0, Y=0, Z=0,color=None,name = "Point", point_size= 5):
|
|||
FreeCAD.ActiveDocument.recompute()
|
||||
return obj
|
||||
|
||||
def makeShapeString(String,FontFile,Size = 100,Tracking = 0):
|
||||
'''ShapeString(Text,FontFile,Height,Track): Turns a text string
|
||||
into a Compound Shape'''
|
||||
|
||||
# temporary code
|
||||
import platform
|
||||
if not (platform.system() == 'Linux'):
|
||||
# if (platform.system() == 'Linux'):
|
||||
FreeCAD.Console.PrintWarning("Sorry, ShapeString is not yet implemented for your platform.\n")
|
||||
return (None)
|
||||
# temporary code
|
||||
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","ShapeString")
|
||||
_ShapeString(obj)
|
||||
obj.String = String
|
||||
obj.FontFile = FontFile
|
||||
obj.Size = Size
|
||||
obj.Tracking = Tracking
|
||||
|
||||
if gui:
|
||||
_ViewProviderDraft(obj.ViewObject)
|
||||
formatObject(obj)
|
||||
obrep = obj.ViewObject
|
||||
if "PointSize" in obrep.PropertiesList: obrep.PointSize = 1 # hide the segment end points
|
||||
select(obj)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return obj
|
||||
|
||||
def clone(obj,delta=None):
|
||||
'''clone(obj,[delta]): makes a clone of the given object(s). The clone is an exact,
|
||||
linked copy of the given object. If the original object changes, the final object
|
||||
|
@ -2998,6 +3040,36 @@ class _Circle(_DraftObject):
|
|||
shape = Part.Face(shape)
|
||||
fp.Shape = shape
|
||||
fp.Placement = plm
|
||||
|
||||
class _Ellipse(_DraftObject):
|
||||
"The Circle object"
|
||||
|
||||
def __init__(self, obj):
|
||||
_DraftObject.__init__(self,obj,"Ellipse")
|
||||
obj.addProperty("App::PropertyDistance","MinorRadius","Base",
|
||||
"The minor radius of the ellipse")
|
||||
obj.addProperty("App::PropertyDistance","MajorRadius","Base",
|
||||
"The major radius of the ellipse")
|
||||
|
||||
def execute(self, fp):
|
||||
self.createGeometry(fp)
|
||||
|
||||
def onChanged(self, fp, prop):
|
||||
if prop in ["MinorRadius","MajorRadius"]:
|
||||
self.createGeometry(fp)
|
||||
|
||||
def createGeometry(self,fp):
|
||||
import Part
|
||||
plm = fp.Placement
|
||||
if fp.MajorRadius < fp.MinorRadius:
|
||||
msg(translate("Error: Major radius is smaller than the minor radius"))
|
||||
return
|
||||
if fp.MajorRadius and fp.MinorRadius:
|
||||
shape = Part.Ellipse(Vector(0,0,0),fp.MajorRadius,fp.MinorRadius).toShape()
|
||||
shape = Part.Wire(shape)
|
||||
shape = Part.Face(shape)
|
||||
fp.Shape = shape
|
||||
fp.Placement = plm
|
||||
|
||||
class _Wire(_DraftObject):
|
||||
"The Wire object"
|
||||
|
@ -3369,45 +3441,9 @@ class _Shape2DView(_DraftObject):
|
|||
if prop in ["Projection","Base","ProjectionMode","FaceNumbers"]:
|
||||
self.createGeometry(obj)
|
||||
|
||||
def clean(self,shape):
|
||||
"returns a valid compound of edges, by recreating them"
|
||||
# this is because the projection algorithm somehow creates wrong shapes.
|
||||
# they dispay fine, but on loading the file the shape is invalid
|
||||
import Part,DraftGeomUtils
|
||||
oldedges = shape.Edges
|
||||
newedges = []
|
||||
for e in oldedges:
|
||||
try:
|
||||
if DraftGeomUtils.geomType(e) == "Line":
|
||||
newedges.append(e.Curve.toShape())
|
||||
elif DraftGeomUtils.geomType(e) == "Circle":
|
||||
if len(e.Vertexes) > 1:
|
||||
mp = DraftGeomUtils.findMidpoint(e)
|
||||
a = Part.Arc(e.Vertexes[0].Point,mp,e.Vertexes[-1].Point).toShape()
|
||||
newedges.append(a)
|
||||
else:
|
||||
newedges.append(e.Curve.toShape())
|
||||
elif DraftGeomUtils.geomType(e) == "Ellipse":
|
||||
if len(e.Vertexes) > 1:
|
||||
a = Part.Arc(e.Curve,e.FirstParameter,e.LastParameter).toShape()
|
||||
newedges.append(a)
|
||||
else:
|
||||
newedges.append(e.Curve.toShape())
|
||||
elif DraftGeomUtils.geomType(e) == "BSplineCurve":
|
||||
if DraftGeomUtils.isLine(e.Curve):
|
||||
l = Part.Line(e.Vertexes[0].Point,e.Vertexes[-1].Point).toShape()
|
||||
newedges.append(l)
|
||||
else:
|
||||
newedges.append(e.Curve.toShape())
|
||||
else:
|
||||
newedges.append(e)
|
||||
except:
|
||||
print "Debug: error cleaning edge ",e
|
||||
return Part.makeCompound(newedges)
|
||||
|
||||
def getProjected(self,obj,shape,direction):
|
||||
"returns projected edges from a shape and a direction"
|
||||
import Part,Drawing
|
||||
import Part,Drawing,DraftGeomUtils
|
||||
edges = []
|
||||
groups = Drawing.projectEx(shape,direction)
|
||||
for g in groups[0:5]:
|
||||
|
@ -3418,7 +3454,7 @@ class _Shape2DView(_DraftObject):
|
|||
for g in groups[5:]:
|
||||
edges.append(g)
|
||||
#return Part.makeCompound(edges)
|
||||
return self.clean(Part.makeCompound(edges))
|
||||
return DraftGeomUtils.cleanProjection(Part.makeCompound(edges))
|
||||
|
||||
def createGeometry(self,obj):
|
||||
import DraftGeomUtils
|
||||
|
@ -3691,6 +3727,91 @@ class _ViewProviderClone(_ViewProviderDraftAlt):
|
|||
|
||||
def getIcon(self):
|
||||
return ":/icons/Draft_Clone.svg"
|
||||
|
||||
class _ShapeString(_DraftObject):
|
||||
"The ShapeString object"
|
||||
|
||||
def __init__(self, obj):
|
||||
_DraftObject.__init__(self,obj,"ShapeString")
|
||||
obj.addProperty("App::PropertyString","String","Base","Text string")
|
||||
obj.addProperty("App::PropertyString","FontFile","Base","Font file name")
|
||||
obj.addProperty("App::PropertyFloat","Size","Base","Height of text")
|
||||
obj.addProperty("App::PropertyInteger","Tracking","Base",
|
||||
"Inter-character spacing")
|
||||
|
||||
def execute(self, fp):
|
||||
self.createGeometry(fp)
|
||||
|
||||
def onChanged(self, fp, prop):
|
||||
pass
|
||||
|
||||
def createGeometry(self,fp):
|
||||
import Part
|
||||
# import OpenSCAD2Dgeom
|
||||
import os
|
||||
if fp.String and fp.FontFile:
|
||||
if fp.Placement:
|
||||
plm = fp.Placement
|
||||
# TODO: os.path.splitunc() for Win/Samba net files?
|
||||
head, tail = os.path.splitdrive(fp.FontFile) # os.path.splitdrive() for Win
|
||||
head, tail = os.path.split(tail)
|
||||
head = head + '/' # os.split drops last '/' from head
|
||||
CharList = Part.makeWireString(fp.String,
|
||||
head,
|
||||
tail,
|
||||
fp.Size,
|
||||
fp.Tracking)
|
||||
SSChars = []
|
||||
for char in CharList:
|
||||
CharFaces = []
|
||||
for CWire in char:
|
||||
f = Part.Face(CWire)
|
||||
if f:
|
||||
CharFaces.append(f)
|
||||
# whitespace (ex: ' ') has no faces. This breaks OpenSCAD2Dgeom...
|
||||
if CharFaces:
|
||||
# s = OpenSCAD2Dgeom.Overlappingfaces(CharFaces).makeshape()
|
||||
s = self.makeGlyph(CharFaces)
|
||||
SSChars.append(s)
|
||||
shape = Part.Compound(SSChars)
|
||||
fp.Shape = shape
|
||||
if plm:
|
||||
fp.Placement = plm
|
||||
|
||||
def makeGlyph(self, facelist):
|
||||
''' turn list of simple contour faces into a compound shape representing a glyph '''
|
||||
''' remove cuts, fuse overlapping contours, retain islands '''
|
||||
import Part
|
||||
if len(facelist) == 1:
|
||||
return(facelist[0])
|
||||
|
||||
sortedfaces = sorted(facelist,key=(lambda shape: shape.Area),reverse=True)
|
||||
|
||||
biggest = sortedfaces[0]
|
||||
result = biggest
|
||||
islands =[]
|
||||
for face in sortedfaces[1:]:
|
||||
bcfA = biggest.common(face).Area
|
||||
fA = face.Area
|
||||
difA = abs(bcfA - fA)
|
||||
eps = epsilon()
|
||||
# if biggest.common(face).Area == face.Area:
|
||||
if difA <= eps: # close enough to zero
|
||||
# biggest completely overlaps current face ==> cut
|
||||
result = result.cut(face)
|
||||
# elif biggest.common(face).Area == 0:
|
||||
elif bcfA <= eps:
|
||||
# island
|
||||
islands.append(face)
|
||||
else:
|
||||
# partial overlap - (font designer error?)
|
||||
result = result.fuse(face)
|
||||
glyphfaces = [result]
|
||||
glyphfaces.extend(islands)
|
||||
ret = Part.Compound(glyphfaces) # should we fuse these instead of making compound?
|
||||
return ret
|
||||
|
||||
#----End of Python Features Definitions----#
|
||||
|
||||
if gui:
|
||||
if not hasattr(FreeCADGui,"Snapper"):
|
||||
|
|
|
@ -195,30 +195,13 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F
|
|||
returns a list containing the intersection point(s) of 2 edges.
|
||||
You can also feed 4 points instead of edge1 and edge2'''
|
||||
|
||||
pt1 = None
|
||||
|
||||
if isinstance(edge1,FreeCAD.Vector) and isinstance(edge2,FreeCAD.Vector):
|
||||
# we got points directly
|
||||
pt1 = edge1
|
||||
pt2 = edge2
|
||||
pt3 = infinite1
|
||||
pt4 = infinite2
|
||||
infinite1 = ex1
|
||||
infinite2 = ex2
|
||||
|
||||
elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line") :
|
||||
# we have 2 straight lines
|
||||
pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point,
|
||||
edge1.Vertexes[1].Point,
|
||||
edge2.Vertexes[0].Point,
|
||||
edge2.Vertexes[1].Point]
|
||||
|
||||
def getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2):
|
||||
if pt1:
|
||||
# first check if we don't already have coincident endpoints
|
||||
if (pt1 in [pt3,pt4]):
|
||||
return [pt1]
|
||||
elif (pt2 in [pt3,pt4]):
|
||||
return [pt2]
|
||||
# first check if we don't already have coincident endpoints
|
||||
if (pt1 in [pt3,pt4]):
|
||||
return [pt1]
|
||||
elif (pt2 in [pt3,pt4]):
|
||||
return [pt2]
|
||||
norm1 = pt2.sub(pt1).cross(pt3.sub(pt1))
|
||||
norm2 = pt2.sub(pt4).cross(pt3.sub(pt4))
|
||||
if not DraftVecUtils.isNull(norm1):
|
||||
|
@ -250,6 +233,26 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F
|
|||
return [] # Lines have same direction
|
||||
else :
|
||||
return [] # Lines aren't on same plane
|
||||
|
||||
pt1 = None
|
||||
|
||||
if isinstance(edge1,FreeCAD.Vector) and isinstance(edge2,FreeCAD.Vector):
|
||||
# we got points directly
|
||||
pt1 = edge1
|
||||
pt2 = edge2
|
||||
pt3 = infinite1
|
||||
pt4 = infinite2
|
||||
infinite1 = ex1
|
||||
infinite2 = ex2
|
||||
return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2)
|
||||
|
||||
elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line") :
|
||||
# we have 2 straight lines
|
||||
pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point,
|
||||
edge1.Vertexes[1].Point,
|
||||
edge2.Vertexes[0].Point,
|
||||
edge2.Vertexes[1].Point]
|
||||
return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2)
|
||||
|
||||
elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Line") \
|
||||
or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle") :
|
||||
|
@ -419,7 +422,7 @@ def mirror (point, edge):
|
|||
else:
|
||||
return None
|
||||
|
||||
def isClockwise(edge):
|
||||
def isClockwise(edge,ref=None):
|
||||
"""Returns True if a circle-based edge has a clockwise direction"""
|
||||
if not geomType(edge) == "Circle":
|
||||
return True
|
||||
|
@ -429,11 +432,26 @@ def isClockwise(edge):
|
|||
# we take an arbitrary other point on the edge that has little chances to be aligned with the first one...
|
||||
v2 = edge.Curve.tangent(edge.ParameterRange[0]+0.01)[0]
|
||||
n = edge.Curve.Axis
|
||||
# if that axis points "the wrong way" from the reference, we invert it
|
||||
if not ref:
|
||||
ref = Vector(0,0,1)
|
||||
if n.getAngle(ref) > math.pi/2:
|
||||
n = DraftVecUtils.neg(n)
|
||||
if DraftVecUtils.angle(v1,v2,n) < 0:
|
||||
return False
|
||||
if n.z < 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def isWideAngle(edge):
|
||||
"""returns True if the given edge is an arc with angle > 180 degrees"""
|
||||
if geomType(edge) != "Circle":
|
||||
return False
|
||||
r = edge.Curve.Radius
|
||||
total = 2*r*math.pi
|
||||
if edge.Length > total/2:
|
||||
return True
|
||||
return False
|
||||
|
||||
def findClosest(basepoint,pointslist):
|
||||
'''
|
||||
|
@ -1652,6 +1670,71 @@ def filletWire(aWire,r,chamfer=False):
|
|||
filEdges[-1:] = result[0:2]
|
||||
filEdges[0] = result[2]
|
||||
return Part.Wire(filEdges)
|
||||
|
||||
def getCircleFromSpline(edge):
|
||||
"returns a circle-based edge from a bspline-based edge"
|
||||
if geomType(edge) != "BSplineCurve":
|
||||
return None
|
||||
if len(edge.Vertexes) != 1:
|
||||
return None
|
||||
# get 2 points
|
||||
p1 = edge.Curve.value(0)
|
||||
p2 = edge.Curve.value(math.pi/2)
|
||||
# get 2 tangents
|
||||
t1 = edge.Curve.tangent(0)[0]
|
||||
t2 = edge.Curve.tangent(math.pi/2)[0]
|
||||
# get normal
|
||||
n = p1.cross(p2)
|
||||
if DraftVecUtils.isNull(n):
|
||||
return None
|
||||
# get rays
|
||||
r1 = DraftVecUtils.rotate(t1,math.pi/2,n)
|
||||
r2 = DraftVecUtils.rotate(t2,math.pi/2,n)
|
||||
# get center (intersection of rays)
|
||||
i = findIntersection(p1,p1.add(r1),p2,p2.add(r2),True,True)
|
||||
if not i:
|
||||
return None
|
||||
c = i[0]
|
||||
r = (p1.sub(c)).Length
|
||||
circle = Part.makeCircle(r,c,n)
|
||||
#print circle.Curve
|
||||
return circle
|
||||
|
||||
def cleanProjection(shape):
|
||||
"returns a valid compound of edges, by recreating them"
|
||||
# this is because the projection algorithm somehow creates wrong shapes.
|
||||
# they dispay fine, but on loading the file the shape is invalid
|
||||
oldedges = shape.Edges
|
||||
newedges = []
|
||||
for e in oldedges:
|
||||
try:
|
||||
if geomType(e) == "Line":
|
||||
newedges.append(e.Curve.toShape())
|
||||
elif geomType(e) == "Circle":
|
||||
if len(e.Vertexes) > 1:
|
||||
mp = findMidpoint(e)
|
||||
a = Part.Arc(e.Vertexes[0].Point,mp,e.Vertexes[-1].Point).toShape()
|
||||
newedges.append(a)
|
||||
else:
|
||||
newedges.append(e.Curve.toShape())
|
||||
elif geomType(e) == "Ellipse":
|
||||
if len(e.Vertexes) > 1:
|
||||
a = Part.Arc(e.Curve,e.FirstParameter,e.LastParameter).toShape()
|
||||
newedges.append(a)
|
||||
else:
|
||||
newedges.append(e.Curve.toShape())
|
||||
elif geomType(e) == "BSplineCurve":
|
||||
if isLine(e.Curve):
|
||||
l = Part.Line(e.Vertexes[0].Point,e.Vertexes[-1].Point).toShape()
|
||||
newedges.append(l)
|
||||
else:
|
||||
newedges.append(e.Curve.toShape())
|
||||
else:
|
||||
newedges.append(e)
|
||||
except:
|
||||
print "Debug: error cleaning edge ",e
|
||||
return Part.makeCompound(newedges)
|
||||
|
||||
|
||||
# circle functions *********************************************************
|
||||
|
||||
|
|
|
@ -313,8 +313,29 @@ class DraftToolBar:
|
|||
self.zValue.setText("0.00")
|
||||
self.textValue = self._lineedit("textValue", self.layout)
|
||||
|
||||
# shapestring
|
||||
|
||||
self.labelSSize = self._label("labelSize", self.layout)
|
||||
self.SSizeValue = self._lineedit("SSizeValue", self.layout, width=60)
|
||||
self.SSizeValue.setText("200.0")
|
||||
self.labelSTrack = self._label("labelTracking", self.layout)
|
||||
self.STrackValue = self._lineedit("STrackValue", self.layout, width=60)
|
||||
self.STrackValue.setText("0")
|
||||
self.labelSString = self._label("labelString", self.layout)
|
||||
self.SStringValue = self._lineedit("SStringValue", self.layout)
|
||||
self.SStringValue.setText("")
|
||||
self.labelFFile = self._label("labelFFile", self.layout)
|
||||
self.FFileValue = self._lineedit("FFileValue", self.layout)
|
||||
defFile = Draft.getParam("FontFile")
|
||||
if defFile:
|
||||
self.FFileValue.setText(defFile)
|
||||
else:
|
||||
self.FFileValue.setText("")
|
||||
self.chooserButton = self._pushbutton("chooserButton", self.layout, width=26)
|
||||
self.chooserButton.setText("...")
|
||||
|
||||
# options
|
||||
|
||||
|
||||
self.numFaces = self._spinbox("numFaces", self.layout, 3)
|
||||
self.offsetLabel = self._label("offsetlabel", self.layout)
|
||||
self.offsetValue = self._lineedit("offsetValue", self.layout, width=60)
|
||||
|
@ -386,7 +407,20 @@ class DraftToolBar:
|
|||
QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("escaped()"),self.escape)
|
||||
QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("resized()"),self.relocate)
|
||||
QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("retranslate()"),self.retranslateUi)
|
||||
QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("returnPressed()"),self.validateSNumeric)
|
||||
QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("escaped()"),self.escape)
|
||||
QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("returnPressed()"),self.validateSNumeric)
|
||||
QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("escaped()"),self.escape)
|
||||
QtCore.QObject.connect(self.SStringValue,QtCore.SIGNAL("returnPressed()"),self.validateSString)
|
||||
QtCore.QObject.connect(self.SStringValue,QtCore.SIGNAL("escaped()"),self.escape)
|
||||
QtCore.QObject.connect(self.chooserButton,QtCore.SIGNAL("pressed()"),self.pickFile)
|
||||
QtCore.QObject.connect(self.FFileValue,QtCore.SIGNAL("returnPressed()"),self.validateFile)
|
||||
QtCore.QObject.connect(self.FFileValue,QtCore.SIGNAL("escaped()"),self.escape)
|
||||
|
||||
# if Ui changed to have Size & Track visible at same time, use this
|
||||
# QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("returnPressed()"),self.checkSSize)
|
||||
# QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("returnPressed()"),self.checkSTrack)
|
||||
|
||||
def setupTray(self):
|
||||
"sets draft tray buttons up"
|
||||
|
||||
|
@ -478,6 +512,15 @@ class DraftToolBar:
|
|||
self.resetPlaneButton.setToolTip(translate("draft", "Do not project points to a drawing plane"))
|
||||
self.isCopy.setText(translate("draft", "&Copy"))
|
||||
self.isCopy.setToolTip(translate("draft", "If checked, objects will be copied instead of moved (C)"))
|
||||
self.SStringValue.setToolTip(translate("draft", "Text string to draw"))
|
||||
self.labelSString.setText(translate("draft", "String"))
|
||||
self.SSizeValue.setToolTip(translate("draft", "Height of text"))
|
||||
self.labelSSize.setText(translate("draft", "Height"))
|
||||
self.STrackValue.setToolTip(translate("draft", "Intercharacter spacing"))
|
||||
self.labelSTrack.setText(translate("draft", "Tracking"))
|
||||
self.labelFFile.setText(translate("draft", "Pick a font file"))
|
||||
self.chooserButton.setToolTip(translate("draft", "Open a FileChooser for font file"))
|
||||
|
||||
if (not self.taskmode) or self.tray:
|
||||
self.wplabel.setToolTip(translate("draft", "Set/unset a working plane"))
|
||||
self.colorButton.setToolTip(translate("draft", "Line Color"))
|
||||
|
@ -528,6 +571,15 @@ class DraftToolBar:
|
|||
self.offsetLabel.show()
|
||||
self.offsetValue.show()
|
||||
|
||||
def hideXYZ(self):
|
||||
''' turn off all the point entry widgets '''
|
||||
self.labelx.hide()
|
||||
self.labely.hide()
|
||||
self.labelz.hide()
|
||||
self.xValue.hide()
|
||||
self.yValue.hide()
|
||||
self.zValue.hide()
|
||||
|
||||
def lineUi(self,title=None):
|
||||
if title:
|
||||
self.pointUi(title,icon="Draft_Line")
|
||||
|
@ -606,12 +658,7 @@ class DraftToolBar:
|
|||
else:
|
||||
self.setTitle(translate("draft", "None"))
|
||||
self.labelx.setText(translate("draft", "X"))
|
||||
self.labelx.hide()
|
||||
self.labely.hide()
|
||||
self.labelz.hide()
|
||||
self.xValue.hide()
|
||||
self.yValue.hide()
|
||||
self.zValue.hide()
|
||||
self.hideXYZ()
|
||||
self.numFaces.hide()
|
||||
self.isRelative.hide()
|
||||
self.hasFill.hide()
|
||||
|
@ -634,6 +681,15 @@ class DraftToolBar:
|
|||
self.textValue.hide()
|
||||
self.continueCmd.hide()
|
||||
self.occOffset.hide()
|
||||
self.labelSString.hide()
|
||||
self.SStringValue.hide()
|
||||
self.labelSSize.hide()
|
||||
self.SSizeValue.hide()
|
||||
self.labelSTrack.hide()
|
||||
self.STrackValue.hide()
|
||||
self.labelFFile.hide()
|
||||
self.FFileValue.hide()
|
||||
self.chooserButton.hide()
|
||||
|
||||
def trimUi(self,title=translate("draft","Trim")):
|
||||
self.taskUi(title)
|
||||
|
@ -643,29 +699,56 @@ class DraftToolBar:
|
|||
self.radiusValue.selectAll()
|
||||
|
||||
def radiusUi(self):
|
||||
self.labelx.hide()
|
||||
self.labely.hide()
|
||||
self.labelz.hide()
|
||||
self.xValue.hide()
|
||||
self.yValue.hide()
|
||||
self.zValue.hide()
|
||||
self.hideXYZ()
|
||||
self.labelRadius.setText(translate("draft", "Radius"))
|
||||
self.labelRadius.show()
|
||||
self.radiusValue.show()
|
||||
|
||||
def textUi(self):
|
||||
self.labelx.hide()
|
||||
self.labely.hide()
|
||||
self.labelz.hide()
|
||||
self.xValue.hide()
|
||||
self.yValue.hide()
|
||||
self.zValue.hide()
|
||||
self.hideXYZ()
|
||||
self.textValue.show()
|
||||
self.textValue.setText('')
|
||||
self.textValue.setFocus()
|
||||
self.textbuffer=[]
|
||||
self.textline=0
|
||||
self.continueCmd.show()
|
||||
|
||||
def SSUi(self):
|
||||
''' set up ui for ShapeString text entry '''
|
||||
self.hideXYZ()
|
||||
self.labelSString.show()
|
||||
self.SStringValue.show()
|
||||
self.SStringValue.setText('')
|
||||
self.SStringValue.setFocus()
|
||||
self.continueCmd.hide()
|
||||
|
||||
def SSizeUi(self):
|
||||
''' set up ui for ShapeString size entry '''
|
||||
self.labelSString.hide()
|
||||
self.SStringValue.hide()
|
||||
self.continueCmd.hide()
|
||||
self.labelSSize.show()
|
||||
self.SSizeValue.setText('200.0')
|
||||
self.SSizeValue.show()
|
||||
self.SSizeValue.setFocus()
|
||||
|
||||
def STrackUi(self):
|
||||
''' set up ui for ShapeString tracking entry '''
|
||||
self.labelSSize.hide()
|
||||
self.SSizeValue.hide()
|
||||
self.labelSTrack.show()
|
||||
self.STrackValue.setText('0')
|
||||
self.STrackValue.show()
|
||||
self.STrackValue.setFocus()
|
||||
|
||||
def SFileUi(self):
|
||||
''' set up UI for ShapeString font file selection '''
|
||||
self.labelSTrack.hide()
|
||||
self.STrackValue.hide()
|
||||
self.labelFFile.show()
|
||||
self.FFileValue.show()
|
||||
self.chooserButton.show()
|
||||
self.FFileValue.setFocus()
|
||||
|
||||
def switchUi(self,store=True):
|
||||
if store:
|
||||
|
@ -676,12 +759,7 @@ class DraftToolBar:
|
|||
self.state.append(self.xValue.isVisible())
|
||||
self.state.append(self.yValue.isVisible())
|
||||
self.state.append(self.zValue.isVisible())
|
||||
self.labelx.hide()
|
||||
self.labely.hide()
|
||||
self.labelz.hide()
|
||||
self.xValue.hide()
|
||||
self.yValue.hide()
|
||||
self.zValue.hide()
|
||||
self.hideXYZ()
|
||||
else:
|
||||
if self.state:
|
||||
if self.state[0]:self.labelx.show()
|
||||
|
@ -707,12 +785,7 @@ class DraftToolBar:
|
|||
|
||||
def editUi(self):
|
||||
self.taskUi(translate("draft", "Edit"))
|
||||
self.labelx.hide()
|
||||
self.labely.hide()
|
||||
self.labelz.hide()
|
||||
self.xValue.hide()
|
||||
self.yValue.hide()
|
||||
self.zValue.hide()
|
||||
self.hideXYZ()
|
||||
self.numFaces.hide()
|
||||
self.isRelative.hide()
|
||||
self.hasFill.hide()
|
||||
|
@ -902,6 +975,74 @@ class DraftToolBar:
|
|||
numz = last.z + v.z
|
||||
self.sourceCmd.numericInput(numx,numy,numz)
|
||||
|
||||
def validateSNumeric(self):
|
||||
''' send valid numeric parameters to ShapeString '''
|
||||
if self.sourceCmd:
|
||||
if (self.labelSSize.isVisible()):
|
||||
try:
|
||||
SSize=float(self.SSizeValue.text())
|
||||
except ValueError:
|
||||
FreeCAD.Console.PrintMessage(translate("draft", "Invalid Size value. Using 200.0."))
|
||||
self.sourceCmd.numericSSize(unicode("200.0"))
|
||||
else:
|
||||
self.sourceCmd.numericSSize(unicode(SSize))
|
||||
elif (self.labelSTrack.isVisible()):
|
||||
try:
|
||||
track=int(self.STrackValue.text())
|
||||
except ValueError:
|
||||
FreeCAD.Console.PrintMessage(translate("draft", "Invalid Tracking value. Using 0."))
|
||||
self.sourceCmd.numericSTrack(unicode("0"))
|
||||
else:
|
||||
self.sourceCmd.numericSTrack(unicode(track))
|
||||
|
||||
def validateSString(self):
|
||||
''' send a valid text string to ShapeString as unicode '''
|
||||
if self.sourceCmd:
|
||||
if (self.labelSString.isVisible()):
|
||||
if self.SStringValue.text():
|
||||
# print "debug: D_G DraftToolBar.validateSString type(SStringValue.text): " str(type(self.SStringValue.text))
|
||||
self.sourceCmd.validSString(str(self.SStringValue.text().toUtf8())) # QString to QByteArray to PyString
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(translate("draft", "Please enter a text string."))
|
||||
|
||||
|
||||
def pickFile(self):
|
||||
''' invoke a font file chooser dialog and send result to ShapeString to'''
|
||||
if self.sourceCmd:
|
||||
if (self.chooserButton.isVisible()):
|
||||
try:
|
||||
dialogCaption = translate("draft", "Select a Font file")
|
||||
dialogDir = os.path.dirname(Draft.getParam("FontFile"))
|
||||
if not dialogDir:
|
||||
dialogDir = os.getcwd() # reasonable default?
|
||||
dialogFilter = "Fonts (*.ttf *.pfb *.otf);;All files (*.*)"
|
||||
fname = QtGui.QFileDialog.getOpenFileName(self.baseWidget,
|
||||
dialogCaption,
|
||||
dialogDir,
|
||||
dialogFilter)
|
||||
fname = str(fname.toUtf8()) # QString to PyString
|
||||
# print "debug: D_G DraftToolBar.pickFile type(fname): " str(type(fname))
|
||||
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintMessage("DraftGui.pickFile: unable to select a font file.")
|
||||
print type(e)
|
||||
print e.args
|
||||
else:
|
||||
if fname:
|
||||
self.sourceCmd.validFFile(fname)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage("DraftGui.pickFile: no file selected.") # can this happen?
|
||||
|
||||
def validateFile(self):
|
||||
''' check and send font file parameter to ShapeString as unicode'''
|
||||
if self.sourceCmd:
|
||||
if (self.labelFFile.isVisible()):
|
||||
if self.FFileValue.text():
|
||||
self.sourceCmd.validFFile(str(self.FFileValue.text().toUtf8())) #QString to PyString
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(translate("draft", "Please enter a font file."))
|
||||
|
||||
|
||||
def finish(self):
|
||||
"finish button action"
|
||||
if self.sourceCmd:
|
||||
|
@ -1222,7 +1363,8 @@ class DraftToolBar:
|
|||
self.commands = ["Draft_Line","Draft_Wire",
|
||||
"Draft_Rectangle","Draft_Arc",
|
||||
"Draft_Circle","Draft_BSpline",
|
||||
"Draft_Text","Draft_Dimension"]
|
||||
"Draft_Text","Draft_Dimension",
|
||||
"Draft_ShapeString"]
|
||||
self.title = "Create objects"
|
||||
def shouldShow(self):
|
||||
return (FreeCAD.ActiveDocument != None) and (not FreeCADGui.Selection.getSelection())
|
||||
|
|
|
@ -104,13 +104,14 @@ class Snapper:
|
|||
'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
|
||||
def snap(self,screenpos,lastpoint=None,active=True,constrain=False,noTracker=False):
|
||||
"""snap(screenpos,lastpoint=None,active=True,constrain=False,noTracker=False): returns a snapped
|
||||
point from the given (x,y) screenpos (the position of the mouse cursor), active is to
|
||||
activate active point snapping or not (passive), lastpoint is an optional
|
||||
other point used to draw an imaginary segment and get additional snap locations. Constrain can
|
||||
be True to constrain the point against the closest working plane axis.
|
||||
Screenpos can be a list, a tuple or a coin.SbVec2s object."""
|
||||
Screenpos can be a list, a tuple or a coin.SbVec2s object. If noTracker is True,
|
||||
the tracking line is not displayed."""
|
||||
|
||||
global Part, DraftGeomUtils
|
||||
import Part, DraftGeomUtils
|
||||
|
@ -196,7 +197,7 @@ class Snapper:
|
|||
if active:
|
||||
point = self.snapToGrid(point)
|
||||
fp = cstr(point)
|
||||
if self.trackLine and lastpoint:
|
||||
if self.trackLine and lastpoint and (not noTracker):
|
||||
self.trackLine.p2(fp)
|
||||
self.trackLine.on()
|
||||
return fp
|
||||
|
|
|
@ -121,14 +121,15 @@ def selectObject(arg):
|
|||
FreeCAD.activeDraftCommand.component=snapped['Component']
|
||||
FreeCAD.activeDraftCommand.proceed()
|
||||
|
||||
def getPoint(target,args,mobile=False,sym=False,workingplane=True):
|
||||
def getPoint(target,args,mobile=False,sym=False,workingplane=True,noTracker=False):
|
||||
'''
|
||||
Function used by the Draft Tools.
|
||||
returns a constrained 3d point and its original point.
|
||||
if mobile=True, the constraining occurs from the location of
|
||||
mouse cursor when Shift is pressed, otherwise from last entered
|
||||
point. If sym=True, x and y values stay always equal. If workingplane=False,
|
||||
the point wont be projected on the Working Plane.
|
||||
the point wont be projected on the Working Plane. if noTracker is True, the
|
||||
tracking line will not be displayed
|
||||
'''
|
||||
|
||||
ui = FreeCADGui.draftToolBar
|
||||
|
@ -141,7 +142,7 @@ def getPoint(target,args,mobile=False,sym=False,workingplane=True):
|
|||
last = None
|
||||
amod = hasMod(args,MODSNAP)
|
||||
cmod = hasMod(args,MODCONSTRAIN)
|
||||
point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod)
|
||||
point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod,noTracker=noTracker)
|
||||
info = FreeCADGui.Snapper.snapInfo
|
||||
ctrlPoint = Vector(point)
|
||||
mask = FreeCADGui.Snapper.affinity
|
||||
|
@ -606,7 +607,7 @@ class BSpline(Line):
|
|||
if arg["Key"] == "ESCAPE":
|
||||
self.finish()
|
||||
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
|
||||
self.point,ctrlPoint,info = getPoint(self,arg)
|
||||
self.point,ctrlPoint,info = getPoint(self,arg,noTracker=True)
|
||||
self.bsplinetrack.update(self.node + [self.point])
|
||||
elif arg["Type"] == "SoMouseButtonEvent":
|
||||
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
||||
|
@ -813,7 +814,7 @@ class Rectangle(Creator):
|
|||
if arg["Key"] == "ESCAPE":
|
||||
self.finish()
|
||||
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
|
||||
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True)
|
||||
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True)
|
||||
self.rect.update(self.point)
|
||||
elif arg["Type"] == "SoMouseButtonEvent":
|
||||
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
||||
|
@ -1394,7 +1395,7 @@ class Ellipse(Creator):
|
|||
'pl = FreeCAD.Placement()',
|
||||
'pl.Rotation.Q='+rot,
|
||||
'pl.Base = '+DraftVecUtils.toString(center),
|
||||
'Draft.makeEllipse('+str(r1)+','+str(r2)+',placement=pl)'])
|
||||
'Draft.makeEllipse('+str(r1)+','+str(r2)+',placement=pl,face='+fil+',support='+sup+')'])
|
||||
except:
|
||||
print "Draft: Error: Unable to create object."
|
||||
self.finish(cont=True)
|
||||
|
@ -1405,7 +1406,7 @@ class Ellipse(Creator):
|
|||
if arg["Key"] == "ESCAPE":
|
||||
self.finish()
|
||||
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
|
||||
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True)
|
||||
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True)
|
||||
self.rect.update(self.point)
|
||||
elif arg["Type"] == "SoMouseButtonEvent":
|
||||
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
||||
|
@ -1616,8 +1617,9 @@ class Dimension(Creator):
|
|||
if arg["Key"] == "ESCAPE":
|
||||
self.finish()
|
||||
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
|
||||
import DraftGeomUtils
|
||||
shift = hasMod(arg,MODCONSTRAIN)
|
||||
self.point,ctrlPoint,self.info = getPoint(self,arg)
|
||||
self.point,ctrlPoint,self.info = getPoint(self,arg,noTracker=(len(self.node)>0))
|
||||
if self.arcmode or self.point2:
|
||||
setMod(arg,MODCONSTRAIN,False)
|
||||
if hasMod(arg,MODALT) and (len(self.node)<3):
|
||||
|
@ -1696,6 +1698,7 @@ class Dimension(Creator):
|
|||
self.dimtrack.update(self.node+[self.point]+[self.cont])
|
||||
elif arg["Type"] == "SoMouseButtonEvent":
|
||||
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
||||
import DraftGeomUtils
|
||||
if self.point:
|
||||
if (not self.node) and (not self.support):
|
||||
self.support = getSupport(arg)
|
||||
|
@ -1721,7 +1724,6 @@ class Dimension(Creator):
|
|||
self.node = [v1,v2]
|
||||
self.link = [ob,i1,i2]
|
||||
self.edges.append(ed)
|
||||
import DraftGeomUtils
|
||||
if DraftGeomUtils.geomType(ed) == "Circle":
|
||||
# snapped edge is an arc
|
||||
self.arcmode = "diameter"
|
||||
|
@ -1736,6 +1738,7 @@ class Dimension(Creator):
|
|||
self.node[3],
|
||||
True,True)
|
||||
if c:
|
||||
print "centers:",c
|
||||
self.center = c[0]
|
||||
self.arctrack.setCenter(self.center)
|
||||
self.arctrack.on()
|
||||
|
@ -1786,6 +1789,118 @@ class Dimension(Creator):
|
|||
self.createObject()
|
||||
if not self.cont: self.finish()
|
||||
|
||||
class ShapeString(Creator):
|
||||
"This class creates a shapestring feature."
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Draft_ShapeString',
|
||||
'Accel' : "S, S",
|
||||
'MenuShapeString': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "ShapeString"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "Creates text string in shapes.")}
|
||||
|
||||
def Activated(self):
|
||||
name = str(translate("draft","ShapeString"))
|
||||
Creator.Activated(self,name)
|
||||
if self.ui:
|
||||
self.ui.sourceCmd = self
|
||||
self.dialog = None
|
||||
self.text = ''
|
||||
self.ui.sourceCmd = self
|
||||
self.ui.pointUi(name)
|
||||
self.call = self.view.addEventCallback("SoEvent",self.action)
|
||||
self.ui.xValue.setFocus()
|
||||
self.ui.xValue.selectAll()
|
||||
msg(translate("draft", "Pick ShapeString location point:\n"))
|
||||
FreeCADGui.draftToolBar.show()
|
||||
|
||||
def createObject(self):
|
||||
"creates object in the current doc"
|
||||
# print "debug: D_T ShapeString.createObject type(self.SString): " str(type(self.SString))
|
||||
# temporary code
|
||||
import platform
|
||||
if not (platform.system() == 'Linux'):
|
||||
# if (platform.system() == 'Linux'):
|
||||
FreeCAD.Console.PrintWarning("Sorry, ShapeString is not yet fully implemented for your platform.\n")
|
||||
self.finish()
|
||||
return
|
||||
# temporary code
|
||||
|
||||
dquote = '"'
|
||||
String = dquote + self.SString + dquote
|
||||
Size = str(self.SSSize) # numbers are ascii so this should always work
|
||||
Tracking = str(self.SSTrack) # numbers are ascii so this should always work
|
||||
FFile = dquote + self.FFile + dquote
|
||||
# print "debug: D_T ShapeString.createObject type(String): " str(type(String))
|
||||
# print "debug: D_T ShapeString.createObject type(FFile): " str(type(FFile))
|
||||
|
||||
try:
|
||||
qr,sup,points,fil = self.getStrings()
|
||||
self.commit(translate("draft","Create ShapeString"),
|
||||
['import Draft',
|
||||
'ss=Draft.makeShapeString(String='+String+',FontFile='+FFile+',Size='+Size+',Tracking='+Tracking+')',
|
||||
'plm=FreeCAD.Placement()',
|
||||
'plm.Base='+DraftVecUtils.toString(self.point),
|
||||
'plm.Rotation.Q='+qr,
|
||||
'ss.Placement=plm',
|
||||
'ss.Support='+sup])
|
||||
except Exception as e:
|
||||
msg("Draft_ShapeString: error delaying commit", "error")
|
||||
print type(e)
|
||||
print e.args
|
||||
self.finish()
|
||||
|
||||
def action(self,arg):
|
||||
"scene event handler"
|
||||
if arg["Type"] == "SoKeyboardEvent":
|
||||
if arg["Key"] == "ESCAPE":
|
||||
self.finish()
|
||||
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
|
||||
self.point,ctrlPoint,info = getPoint(self,arg)
|
||||
elif arg["Type"] == "SoMouseButtonEvent":
|
||||
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
|
||||
if self.point:
|
||||
self.node.append(self.point)
|
||||
self.ui.SSUi()
|
||||
|
||||
def numericInput(self,numx,numy,numz):
|
||||
'''this function gets called by the toolbar when valid
|
||||
x, y, and z have been entered there'''
|
||||
self.point = Vector(numx,numy,numz)
|
||||
self.node.append(self.point)
|
||||
self.ui.SSUi() #move on to next step in parameter entry
|
||||
|
||||
def numericSSize(self,ssize):
|
||||
'''this function is called by the toolbar when valid size parameter
|
||||
has been entered. '''
|
||||
self.SSSize = ssize
|
||||
self.ui.STrackUi()
|
||||
|
||||
def numericSTrack(self,strack):
|
||||
'''this function is called by the toolbar when valid size parameter
|
||||
has been entered. ?'''
|
||||
self.SSTrack = strack
|
||||
self.ui.SFileUi()
|
||||
|
||||
def validSString(self,sstring):
|
||||
'''this function is called by the toolbar when a ?valid? string parameter
|
||||
has been entered. '''
|
||||
self.SString = sstring
|
||||
self.ui.SSizeUi()
|
||||
|
||||
def validFFile(self,FFile):
|
||||
'''this function is called by the toolbar when a ?valid? font file parameter
|
||||
has been entered. '''
|
||||
self.FFile = FFile
|
||||
# last step in ShapeString parm capture, create object
|
||||
self.createObject()
|
||||
|
||||
def finish(self, finishbool=False):
|
||||
"terminates the operation"
|
||||
Creator.finish(self)
|
||||
if self.ui:
|
||||
# del self.dialog # what does this do??
|
||||
if self.ui.continueMode:
|
||||
self.Activated()
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Modifier functions
|
||||
|
@ -1821,7 +1936,14 @@ class Move(Modifier):
|
|||
def proceed(self):
|
||||
if self.call: self.view.removeEventCallback("SoEvent",self.call)
|
||||
self.sel = Draft.getSelection()
|
||||
self.sel = Draft.getGroupContents(self.sel)
|
||||
# testing for special case: only Arch groups in selection
|
||||
onlyarchgroups = True
|
||||
for o in self.sel:
|
||||
if not(Draft.getType(o) in ["Floor","Building","Site"]):
|
||||
onlyarchgroups = False
|
||||
if not onlyarchgroups:
|
||||
# arch groups can be moved, no need to add their children
|
||||
self.sel = Draft.getGroupContents(self.sel)
|
||||
self.ui.pointUi(self.name)
|
||||
self.ui.modUi()
|
||||
self.ui.xValue.setFocus()
|
||||
|
@ -2972,7 +3094,8 @@ class Edit(Modifier):
|
|||
Modifier.finish(self)
|
||||
plane.restore()
|
||||
self.running = False
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
# following line causes crash
|
||||
# FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def action(self,arg):
|
||||
"scene event handler"
|
||||
|
@ -3584,6 +3707,7 @@ FreeCADGui.addCommand('Draft_Polygon',Polygon())
|
|||
FreeCADGui.addCommand('Draft_BSpline',BSpline())
|
||||
FreeCADGui.addCommand('Draft_Point',Point())
|
||||
FreeCADGui.addCommand('Draft_Ellipse',Ellipse())
|
||||
FreeCADGui.addCommand('Draft_ShapeString',ShapeString())
|
||||
|
||||
# modification commands
|
||||
FreeCADGui.addCommand('Draft_Move',Move())
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -104,7 +104,8 @@ class DraftWorkbench (Workbench):
|
|||
pass
|
||||
self.cmdList = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse",
|
||||
"Draft_Polygon","Draft_Rectangle", "Draft_Text",
|
||||
"Draft_Dimension", "Draft_BSpline","Draft_Point"]
|
||||
"Draft_Dimension", "Draft_BSpline","Draft_Point",
|
||||
"Draft_ShapeString"]
|
||||
self.modList = ["Draft_Move","Draft_Rotate","Draft_Offset",
|
||||
"Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale",
|
||||
"Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint",
|
||||
|
@ -161,3 +162,12 @@ App.addExportType("Autodesk DXF (*.dxf)","importDXF")
|
|||
App.addExportType("Flattened SVG (*.svg)","importSVG")
|
||||
App.addExportType("Open CAD Format (*.oca)","importOCA")
|
||||
|
||||
# DWG support
|
||||
import importDWG
|
||||
if importDWG.getTeighaConverter():
|
||||
App.addImportType("Autodesk DWG (*.dwg)","importDWG")
|
||||
App.addExportType("Autodesk DWG (*.dwg)","importDWG")
|
||||
else:
|
||||
from DraftTools import translate
|
||||
FreeCAD.Console.PrintMessage(str(translate("draft","Teigha File Converter not found, DWG support will be disabled.\n")))
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
<file>icons/Draft_Clone.svg</file>
|
||||
<file>icons/Draft_Heal.svg</file>
|
||||
<file>icons/Draft_Ellipse.svg</file>
|
||||
<file>icons/Draft_ShapeString.svg</file>
|
||||
<file>patterns/concrete.svg</file>
|
||||
<file>patterns/cross.svg</file>
|
||||
<file>patterns/line.svg</file>
|
||||
|
|
112
src/Mod/Draft/Resources/icons/Draft_ShapeString.svg
Normal file
112
src/Mod/Draft/Resources/icons/Draft_ShapeString.svg
Normal file
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg4594"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="Draft_ShapeString.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs4596">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective4602" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6568542"
|
||||
inkscape:cx="16.724718"
|
||||
inkscape:cy="24.831907"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="695"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata4599">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="15.684914"
|
||||
y="19.773684"
|
||||
id="text3097"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3099"
|
||||
x="15.684914"
|
||||
y="19.773684" /></text>
|
||||
<g
|
||||
id="g4061">
|
||||
<text
|
||||
transform="scale(1.2630773,0.79171719)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3892"
|
||||
y="69.508385"
|
||||
x="5.465425"
|
||||
style="font-size:77.39546203999999818px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;opacity:0.62711863999999995;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.191;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;font-family:Times New Roman;-inkscape-font-specification:'Times New Roman, Italic'"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:3.191;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="69.508385"
|
||||
x="5.465425"
|
||||
id="tspan3894"
|
||||
sodipodi:role="line">S</tspan><tspan
|
||||
style="stroke-width:3.191;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="tspan3896"
|
||||
y="166.25272"
|
||||
x="5.465425"
|
||||
sodipodi:role="line" /></text>
|
||||
<text
|
||||
inkscape:transform-center-y="17.646795"
|
||||
inkscape:transform-center-x="1.9859923"
|
||||
transform="scale(1.258685,0.79447996)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3103"
|
||||
y="65.225639"
|
||||
x="2.1774669"
|
||||
style="font-size:80.06713104px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffda04;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.57333159;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;font-family:Times New Roman;-inkscape-font-specification:'Times New Roman, Italic'"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:1.57333159"
|
||||
y="65.225639"
|
||||
x="2.1774669"
|
||||
id="tspan3105"
|
||||
sodipodi:role="line">S</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>590</width>
|
||||
<height>632</height>
|
||||
<width>718</width>
|
||||
<height>808</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -1199,6 +1199,49 @@ such as "Arial:Bold"</string>
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_23">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Default ShapeString Font File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefFileChooser" name="gui::preffilechooser">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select a font file</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>FontFile</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Draft</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -280,6 +280,26 @@ If color mapping is choosed, you must choose a color mapping file containing a t
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_14">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_12">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, the exported objects will be projected to reflect the current view direction</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Project exported objects along current view direction</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>dxfproject</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Draft</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
|
|
94
src/Mod/Draft/importDWG.py
Normal file
94
src/Mod/Draft/importDWG.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
# -*- coding: utf8 -*-
|
||||
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2009 Yorik van Havre <yorik@uncreated.net> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (GPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* 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 Draft Workbench - DWG importer/exporter"
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
pythonopen = open # to distinguish python built-in open function from the one declared here
|
||||
|
||||
def open(filename):
|
||||
"called when freecad opens a file."
|
||||
dxf = convertToDxf(filename)
|
||||
import importDXF
|
||||
doc = importDXF.open(dxf)
|
||||
return doc
|
||||
|
||||
def insert(filename,docname):
|
||||
"called when freecad imports a file"
|
||||
dxf = convertToDxf(filemname)
|
||||
import importDXF
|
||||
doc = importDXF.insert(dxf,docname)
|
||||
return doc
|
||||
|
||||
def export(objectslist,filename):
|
||||
"called when freecad exports a file"
|
||||
import importDXF,os,tempfile
|
||||
outdir = tempfile.mkdtemp()
|
||||
dxf = outdir + os.sep + os.path.splitext(os.path.basename(filename))[0] + ".dxf"
|
||||
importDXF.export(objectslist,dxf)
|
||||
convertToDwg(dxf,filename)
|
||||
return filename
|
||||
|
||||
def getTeighaConverter():
|
||||
"finds the Teigha Converter executable"
|
||||
import os,platform
|
||||
teigha = None
|
||||
if platform.system() == "Linux":
|
||||
teigha = "/usr/bin/TeighaFileConverter"
|
||||
elif platform.system() == "Windows":
|
||||
odadir = "C:\Program Files\ODA"
|
||||
if os.path.exists(odadir):
|
||||
subdirs = os.walk(odadir).next()[1]
|
||||
for sub in subdirs:
|
||||
t = odadir + os.sep + sub + os.sep + "TeighaFileConverter.exe"
|
||||
if os.path.exists(t):
|
||||
teigha = t
|
||||
if teigha:
|
||||
if os.path.exists(teigha):
|
||||
return teigha
|
||||
return None
|
||||
|
||||
def convertToDxf(dwgfilename):
|
||||
"converts a DWG file to DXF"
|
||||
import os,tempfile
|
||||
teigha = getTeighaConverter()
|
||||
indir = os.path.dirname(dwgfilename)
|
||||
outdir = tempfile.mkdtemp()
|
||||
basename = os.path.basename(dwgfilename)
|
||||
cmdline = teigha + ' "' + indir + '" "' + outdir + '" "ACAD2010" "DXF" "0" "1" "' + basename + '"'
|
||||
print "converting " + cmdline
|
||||
os.system(cmdline)
|
||||
return outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
|
||||
|
||||
def convertToDwg(dxffilename,dwgfilename):
|
||||
"converts a DXF file to DWG"
|
||||
import os
|
||||
teigha = getTeighaConverter()
|
||||
indir = os.path.dirname(dxffilename)
|
||||
outdir = os.path.dirname(dwgfilename)
|
||||
basename = os.path.basename(dxffilename)
|
||||
cmdline = teigha + ' "' + indir + '" "' + outdir + '" "ACAD2010" "DWG" "0" "1" "' + basename + '"'
|
||||
print "converting " + cmdline
|
||||
os.system(cmdline)
|
||||
return dwgfilename
|
|
@ -1190,18 +1190,31 @@ def insert(filename,docname):
|
|||
|
||||
# EXPORT ########################################################################
|
||||
|
||||
def projectShape(shape,direction):
|
||||
import Drawing
|
||||
edges = []
|
||||
try:
|
||||
groups = Drawing.projectEx(shape,direction)
|
||||
except:
|
||||
print "unable to project shape"
|
||||
return shape
|
||||
else:
|
||||
for g in groups[0:5]:
|
||||
if g:
|
||||
edges.append(g)
|
||||
return DraftGeomUtils.cleanProjection(Part.makeCompound(edges))
|
||||
|
||||
def getArcData(edge):
|
||||
"returns center, radius, start and end angles of a circle-based edge"
|
||||
ce = edge.Curve.Center
|
||||
radius = edge.Curve.Radius
|
||||
if len(edge.Vertexes) == 1:
|
||||
# closed circle
|
||||
return ce, radius, 0, 0
|
||||
return DraftVecUtils.tup(ce), radius, 0, 0
|
||||
else:
|
||||
# find direction of arc
|
||||
tang1 = edge.Curve.tangent(edge.ParameterRange[0])
|
||||
tang2 = edge.Curve.tangent(edge.ParameterRange[1])
|
||||
|
||||
# method 1 - find direction of arc from tangents - not reliable
|
||||
#tang1 = edge.Curve.tangent(edge.ParameterRange[0])
|
||||
#tang2 = edge.Curve.tangent(edge.ParameterRange[1])
|
||||
# following code doesn't seem to give right result?
|
||||
# cross1 = Vector.cross(Vector(tang1[0][0],tang1[0][1],tang1[0][2]),Vector(tang2[0][0],tang2[0][1],tang2[0][2]))
|
||||
# if cross1[2] > 0: # >0 ccw <0 cw
|
||||
|
@ -1211,15 +1224,31 @@ def getArcData(edge):
|
|||
# ve1 = edge.Vertexes[-1].Point
|
||||
# ve2 = edge.Vertexes[0].Point
|
||||
|
||||
# check the midpoint seems more reliable
|
||||
# method 3 - recreate an arc and check if the length is the same
|
||||
ve1 = edge.Vertexes[0].Point
|
||||
ve2 = edge.Vertexes[-1].Point
|
||||
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):
|
||||
|
||||
a1 = -DraftVecUtils.angle(ve1.sub(ce))
|
||||
a2 = -DraftVecUtils.angle(ve2.sub(ce))
|
||||
pseudoarc = Part.ArcOfCircle(edge.Curve,a1,a2).toShape()
|
||||
if round(pseudoarc.Length,Draft.precision()) != round(edge.Length,Draft.precision()):
|
||||
ang1, ang2 = ang2, ang1
|
||||
|
||||
# method 2 - check the midpoint - not reliable either
|
||||
#ve3 = DraftGeomUtils.findMidpoint(edge)
|
||||
#ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce)))
|
||||
#print "edge ",edge.hashCode()," data ",ang1, " , ",ang2," , ", ang3
|
||||
#if (ang3 < ang1) and (ang2 < ang3):
|
||||
# print "inverting, case1"
|
||||
# ang1, ang2 = ang2, ang1
|
||||
#elif (ang3 > ang1) and (ang3 > ang2):
|
||||
# print "inverting, case2"
|
||||
# ang1, ang2 = ang2, ang1
|
||||
#elif (ang3 < ang1) and (ang3 < ang2):
|
||||
# print "inverting, case3"
|
||||
# ang1, ang2 = ang2, ang1
|
||||
return DraftVecUtils.tup(ce), radius, ang1, ang2
|
||||
|
||||
def getSplineSegs(edge):
|
||||
|
@ -1246,6 +1275,7 @@ def getWire(wire,nospline=False):
|
|||
"returns an array of dxf-ready points and bulges from a wire"
|
||||
edges = DraftGeomUtils.sortEdges(wire.Edges)
|
||||
points = []
|
||||
# print "processing wire ",wire.Edges
|
||||
for edge in edges:
|
||||
v1 = edge.Vertexes[0].Point
|
||||
if len(edge.Vertexes) < 2:
|
||||
|
@ -1255,6 +1285,9 @@ def getWire(wire,nospline=False):
|
|||
v2 = edge.Vertexes[-1].Point
|
||||
c = edge.Curve.Center
|
||||
angle = abs(DraftVecUtils.angle(v1.sub(c),v2.sub(c)))
|
||||
if DraftGeomUtils.isWideAngle(edge):
|
||||
if angle < math.pi:
|
||||
angle = math.pi*2 - angle
|
||||
# if (DraftVecUtils.angle(v2.sub(c)) < DraftVecUtils.angle(v1.sub(c))):
|
||||
# angle = -angle
|
||||
# polyline bulge -> negative makes the arc go clockwise
|
||||
|
@ -1291,16 +1324,16 @@ def getWire(wire,nospline=False):
|
|||
# print "wire verts: ",points
|
||||
return points
|
||||
|
||||
def getBlock(obj):
|
||||
def getBlock(sh,obj):
|
||||
"returns a dxf block with the contents of the object"
|
||||
block = dxfLibrary.Block(name=obj.Name,layer=getGroup(obj,exportList))
|
||||
writeShape(obj,block)
|
||||
writeShape(sh,obj,block)
|
||||
return block
|
||||
|
||||
def writeShape(ob,dxfobject,nospline=False):
|
||||
def writeShape(sh,ob,dxfobject,nospline=False):
|
||||
"writes the object's shape contents in the given dxf object"
|
||||
processededges = []
|
||||
for wire in ob.Shape.Wires: # polylines
|
||||
for wire in sh.Wires: # polylines
|
||||
for e in wire.Edges:
|
||||
processededges.append(e.hashCode())
|
||||
if (len(wire.Edges) == 1) and (DraftGeomUtils.geomType(wire.Edges[0]) == "Circle"):
|
||||
|
@ -1317,22 +1350,32 @@ def writeShape(ob,dxfobject,nospline=False):
|
|||
dxfobject.append(dxfLibrary.PolyLine(getWire(wire,nospline), [0.0,0.0,0.0],
|
||||
int(DraftGeomUtils.isReallyClosed(wire)), color=getACI(ob),
|
||||
layer=getGroup(ob,exportList)))
|
||||
if len(processededges) < len(ob.Shape.Edges): # lone edges
|
||||
if len(processededges) < len(sh.Edges): # lone edges
|
||||
loneedges = []
|
||||
for e in ob.Shape.Edges:
|
||||
for e in sh.Edges:
|
||||
if not(e.hashCode() in processededges): loneedges.append(e)
|
||||
# print "lone edges ",loneedges
|
||||
for edge in loneedges:
|
||||
if (DraftGeomUtils.geomType(edge) == "BSplineCurve") and ((not nospline) or (len(edge.Vertexes) == 1)): # splines
|
||||
points = []
|
||||
spline = getSplineSegs(edge)
|
||||
for p in spline:
|
||||
points.append((p.x,p.y,p.z,None,None,0.0))
|
||||
dxfobject.append(dxfLibrary.PolyLine(points, [0.0,0.0,0.0],
|
||||
0, color=getACI(ob),
|
||||
layer=getGroup(ob,exportList)))
|
||||
if (len(edge.Vertexes) == 1) and (edge.Curve.isClosed()):
|
||||
# special case: 1-vert closed spline, approximate as a circle
|
||||
c = DraftGeomUtils.getCircleFromSpline(edge)
|
||||
if c:
|
||||
dxfobject.append(dxfLibrary.Circle(DraftVecUtils.tup(c.Curve.Center), c.Curve.Radius,
|
||||
color=getACI(ob),
|
||||
layer=getGroup(ob,exportList)))
|
||||
else:
|
||||
points = []
|
||||
spline = getSplineSegs(edge)
|
||||
for p in spline:
|
||||
points.append((p.x,p.y,p.z,None,None,0.0))
|
||||
dxfobject.append(dxfLibrary.PolyLine(points, [0.0,0.0,0.0],
|
||||
0, color=getACI(ob),
|
||||
layer=getGroup(ob,exportList)))
|
||||
elif DraftGeomUtils.geomType(edge) == "Circle": # curves
|
||||
center, radius, ang1, ang2 = getArcData(edge)
|
||||
if not isinstance(center,tuple):
|
||||
center = DraftVecUtils.tup(center)
|
||||
if len(edge.Vertexes) == 1: # circles
|
||||
dxfobject.append(dxfLibrary.Circle(center, radius,
|
||||
color=getACI(ob),
|
||||
|
@ -1387,27 +1430,37 @@ def export(objectslist,filename,nospline=False):
|
|||
for ob in exportList:
|
||||
print "processing ",ob.Name
|
||||
if ob.isDerivedFrom("Part::Feature"):
|
||||
if not ob.Shape.isNull():
|
||||
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"):
|
||||
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"):
|
||||
sh = None
|
||||
if not ob.Shape.isNull():
|
||||
writeMesh(ob,dxf)
|
||||
elif FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfproject"):
|
||||
direction = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
|
||||
sh = projectShape(ob.Shape,direction)
|
||||
else:
|
||||
if ob.Shape.Volume > 0:
|
||||
sh = projectShape(ob.Shape,Vector(0,0,1))
|
||||
else:
|
||||
if ob.Shape.ShapeType == 'Compound':
|
||||
if (len(ob.Shape.Wires) == 1):
|
||||
sh = ob.Shape
|
||||
if sh:
|
||||
if not sh.isNull():
|
||||
if sh.ShapeType == 'Compound':
|
||||
if (len(sh.Wires) == 1):
|
||||
# only one wire in this compound, no lone edge -> polyline
|
||||
if (len(ob.Shape.Wires[0].Edges) == len(ob.Shape.Edges)):
|
||||
writeShape(ob,dxf,nospline)
|
||||
if (len(sh.Wires[0].Edges) == len(sh.Edges)):
|
||||
writeShape(sh,ob,dxf,nospline)
|
||||
else:
|
||||
# 1 wire + lone edges -> block
|
||||
block = getBlock(ob)
|
||||
block = getBlock(sh,ob)
|
||||
dxf.blocks.append(block)
|
||||
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
|
||||
else:
|
||||
# all other cases: block
|
||||
block = getBlock(ob)
|
||||
block = getBlock(sh,ob)
|
||||
dxf.blocks.append(block)
|
||||
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
|
||||
else:
|
||||
writeShape(ob,dxf,nospline)
|
||||
writeShape(sh,ob,dxf,nospline)
|
||||
|
||||
elif Draft.getType(ob) == "Annotation":
|
||||
# texts
|
||||
|
|
|
@ -53,6 +53,7 @@ public:
|
|||
|
||||
virtual void attach(App::DocumentObject *);
|
||||
virtual void setDisplayMode(const char* ModeName);
|
||||
virtual bool useNewSelectionModel(void) const {return false;}
|
||||
/// returns a list of all possible modes
|
||||
virtual std::vector<std::string> getDisplayModes(void) const;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
|
||||
virtual void attach(App::DocumentObject *);
|
||||
virtual void setDisplayMode(const char* ModeName);
|
||||
virtual bool useNewSelectionModel(void) const {return false;}
|
||||
/// returns a list of all possible modes
|
||||
virtual std::vector<std::string> getDisplayModes(void) const;
|
||||
virtual void updateData(const App::Property*);
|
||||
|
|
|
@ -123,7 +123,7 @@ void ImageBase::clear()
|
|||
_setColorFormat(IB_CF_GREY8, 8);
|
||||
}
|
||||
|
||||
// Sets the color format and the dependant parameters
|
||||
// Sets the color format and the dependent parameters
|
||||
// Returns 0 for OK, -1 for invalid color format
|
||||
int ImageBase::_setColorFormat(int format, unsigned short numSigBitsPerSample)
|
||||
{
|
||||
|
@ -235,7 +235,7 @@ int ImageBase::createCopy(void* pSrcPixelData, unsigned long width, unsigned lon
|
|||
// Clear any existing data
|
||||
clear();
|
||||
|
||||
// Set the color format and the dependant parameters
|
||||
// Set the color format and the dependent parameters
|
||||
if (_setColorFormat(format, numSigBitsPerSample) != 0)
|
||||
return -1;
|
||||
|
||||
|
@ -273,7 +273,7 @@ int ImageBase::pointTo(void* pSrcPixelData, unsigned long width, unsigned long h
|
|||
// Clear any existing data
|
||||
clear();
|
||||
|
||||
// Set the color format and the dependant parameters
|
||||
// Set the color format and the dependent parameters
|
||||
if (_setColorFormat(format, numSigBitsPerSample) != 0)
|
||||
return -1;
|
||||
|
||||
|
@ -324,15 +324,15 @@ int ImageBase::getSample(int x, int y, unsigned short sampleIndex, double &value
|
|||
case IB_CF_RGBA64:
|
||||
case IB_CF_BGRA64:
|
||||
{
|
||||
unsigned short* pPix16 = (unsigned short *)_pPixelData;
|
||||
unsigned short* pSample = pPix16 + _numSamples * (y * _width + x) + sampleIndex;
|
||||
uint16_t* pPix16 = (uint16_t *)_pPixelData;
|
||||
uint16_t* pSample = pPix16 + _numSamples * (y * _width + x) + sampleIndex;
|
||||
value = (double)(*pSample);
|
||||
}
|
||||
break;
|
||||
case IB_CF_GREY32:
|
||||
{
|
||||
unsigned long* pPix32 = (unsigned long *)_pPixelData;
|
||||
unsigned long* pSample = pPix32 + y * _width + x;
|
||||
uint32_t* pPix32 = (uint32_t *)_pPixelData;
|
||||
uint32_t* pSample = pPix32 + y * _width + x;
|
||||
value = (double)(*pSample);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -71,7 +71,7 @@ protected:
|
|||
int _format; // colour format of the pixel data
|
||||
unsigned short _numSigBitsPerSample;// number of significant bits per sample (always <= _numBitsPerSample)
|
||||
|
||||
// Dependant parameters
|
||||
// Dependent parameters
|
||||
unsigned short _numSamples; // number of samples per pixel (e.g. 1 for grey, 3 for rgb, 4 for rgba)
|
||||
unsigned short _numBitsPerSample; // number of bits per sample (e.g. 8 for Grey8)
|
||||
unsigned short _numBytesPerPixel; // number of bytes per pixel (e.g. 1 for Grey8)
|
||||
|
|
|
@ -45,6 +45,8 @@ using namespace ImageGui;
|
|||
#pragma warning(disable:4305) // init: truncation from const double to float
|
||||
#endif
|
||||
|
||||
bool GLImageBox::haveMesa = false;
|
||||
|
||||
/* TRANSLATOR ImageGui::GLImageBox */
|
||||
|
||||
// Constructor
|
||||
|
@ -81,7 +83,13 @@ GLImageBox::~GLImageBox()
|
|||
// Set up the OpenGL rendering state
|
||||
void GLImageBox::initializeGL()
|
||||
{
|
||||
qglClearColor( Qt::black ); // Let OpenGL clear to black
|
||||
qglClearColor( Qt::black ); // Let OpenGL clear to black
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
init = true;
|
||||
std::string ver = (const char*)(glGetString(GL_VERSION));
|
||||
haveMesa = (ver.find("Mesa") != std::string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -170,7 +178,7 @@ void GLImageBox::drawImage()
|
|||
// Load the color map if present
|
||||
if (_pColorMap != 0)
|
||||
{
|
||||
glPixelTransferf(GL_MAP_COLOR, 1.0);
|
||||
if (!haveMesa) glPixelTransferf(GL_MAP_COLOR, 1.0);
|
||||
glPixelMapfv(GL_PIXEL_MAP_R_TO_R, _numMapEntries, _pColorMap);
|
||||
glPixelMapfv(GL_PIXEL_MAP_G_TO_G, _numMapEntries, _pColorMap + _numMapEntries);
|
||||
glPixelMapfv(GL_PIXEL_MAP_B_TO_B, _numMapEntries, _pColorMap + _numMapEntries * 2);
|
||||
|
|
|
@ -105,6 +105,7 @@ private:
|
|||
|
||||
float* _pColorMap; // a RGBA color map (to alter the intensity or colors)
|
||||
int _numMapEntries; // number of entries in color map
|
||||
static bool haveMesa;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
|||
|
||||
Gui::ToolBarItem* Workbench::setupCommandBars() const
|
||||
{
|
||||
// Part tools
|
||||
Gui::ToolBarItem* root = new Gui::ToolBarItem;
|
||||
Gui::ToolBarItem* img = new Gui::ToolBarItem(root);
|
||||
img->setCommand("Image");
|
||||
|
|
|
@ -87,6 +87,7 @@ void CmdInspectElement::activated(int iMsg)
|
|||
if (view) {
|
||||
Gui::View3DInventorViewer* viewer = view->getViewer();
|
||||
viewer->setEditing(true);
|
||||
viewer->setRedirectToSceneGraphEnabled(true);
|
||||
viewer->setRedirectToSceneGraph(true);
|
||||
viewer->setEditingCursor(QCursor(Gui::BitmapFactory().pixmap("mesh_pipette"),4,29));
|
||||
viewer->addEventCallback(SoButtonEvent::getClassTypeId(),
|
||||
|
|
|
@ -436,6 +436,7 @@ void ViewProviderInspection::inspectCallback(void * ud, SoEventCallback * n)
|
|||
view->setEditing(false);
|
||||
view->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
|
||||
view->setRedirectToSceneGraph(false);
|
||||
view->setRedirectToSceneGraphEnabled(false);
|
||||
view->removeEventCallback(SoButtonEvent::getClassTypeId(), inspectCallback);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -452,8 +452,8 @@ void QuadraticFit::CalcEigenValues(double &dLambda1, double &dLambda2, double &d
|
|||
*/
|
||||
|
||||
Wm4::Matrix3<double> 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] );
|
||||
_fCoeff[7]/2.0f, _fCoeff[5], _fCoeff[9]/2.0f,
|
||||
_fCoeff[8]/2.0f, _fCoeff[9]/2.0f, _fCoeff[6] );
|
||||
|
||||
Wm4::Matrix3<double> rkRot, rkDiag;
|
||||
akMat.EigenDecomposition( rkRot, rkDiag );
|
||||
|
@ -476,9 +476,9 @@ void QuadraticFit::CalcZValues( double x, double y, double &dZ1, double &dZ2 ) c
|
|||
assert( _bIsFitted );
|
||||
|
||||
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;
|
||||
_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;
|
||||
|
||||
if (fabs( _fCoeff[6] ) < 0.000005) {
|
||||
dZ1 = FLOAT_MAX;
|
||||
|
|
|
@ -795,17 +795,17 @@ bool MeshInput::LoadPLY (std::istream &inp)
|
|||
}
|
||||
}
|
||||
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);
|
||||
pt.y = (float)std::atof(what[4].first);
|
||||
pt.z = (float)std::atof(what[7].first);
|
||||
meshPoints.push_back(pt);
|
||||
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);
|
||||
pt.y = (float)std::atof(what[4].first);
|
||||
pt.z = (float)std::atof(what[7].first);
|
||||
meshPoints.push_back(pt);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
int f1, f2, f3;
|
||||
for (std::size_t i = 0; i < f_count && std::getline(inp, line); i++) {
|
||||
|
|
|
@ -587,6 +587,23 @@ void MeshObject::getPointsFromSelection(std::vector<unsigned long>& inds) const
|
|||
MeshCore::MeshAlgorithm(this->_kernel).GetPointsFlag(inds, MeshCore::MeshPoint::SELECTED);
|
||||
}
|
||||
|
||||
bool MeshObject::hasSelectedFacets() const
|
||||
{
|
||||
unsigned long ct = MeshCore::MeshAlgorithm(this->_kernel).CountFacetFlag(MeshCore::MeshFacet::SELECTED);
|
||||
return ct > 0;
|
||||
}
|
||||
|
||||
bool MeshObject::hasSelectedPoints() const
|
||||
{
|
||||
unsigned long ct = MeshCore::MeshAlgorithm(this->_kernel).CountPointFlag(MeshCore::MeshPoint::SELECTED);
|
||||
return ct > 0;
|
||||
}
|
||||
|
||||
std::vector<unsigned long> MeshObject::getPointsFromFacets(const std::vector<unsigned long>& facets) const
|
||||
{
|
||||
return _kernel.GetFacetPoints(facets);
|
||||
}
|
||||
|
||||
void MeshObject::updateMesh(const std::vector<unsigned long>& facets)
|
||||
{
|
||||
std::vector<unsigned long> points;
|
||||
|
|
|
@ -124,6 +124,7 @@ public:
|
|||
double getVolume() const;
|
||||
void getFaces(std::vector<Base::Vector3d> &Points,std::vector<Facet> &Topo,
|
||||
float Accuracy, uint16_t flags=0) const;
|
||||
std::vector<unsigned long> getPointsFromFacets(const std::vector<unsigned long>& facets) const;
|
||||
//@}
|
||||
|
||||
void setKernel(const MeshCore::MeshKernel& m);
|
||||
|
@ -211,6 +212,8 @@ public:
|
|||
void addPointsToSelection(const std::vector<unsigned long>&) const;
|
||||
void removeFacetsFromSelection(const std::vector<unsigned long>&) const;
|
||||
void removePointsFromSelection(const std::vector<unsigned long>&) const;
|
||||
bool hasSelectedFacets() const;
|
||||
bool hasSelectedPoints() const;
|
||||
void getFacetsFromSelection(std::vector<unsigned long>&) const;
|
||||
void getPointsFromSelection(std::vector<unsigned long>&) const;
|
||||
void clearFacetSelection() const;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "DlgSettingsMeshView.h"
|
||||
#include "SoFCMeshObject.h"
|
||||
#include "SoFCIndexedFaceSet.h"
|
||||
#include "SoPolygon.h"
|
||||
#include "ViewProvider.h"
|
||||
#include "ViewProviderMeshFaceSet.h"
|
||||
#include "ViewProviderCurvature.h"
|
||||
|
@ -111,6 +112,7 @@ void MeshGuiExport initMeshGui()
|
|||
MeshGui::SoFCIndexedFaceSet ::initClass();
|
||||
MeshGui::SoFCMeshPickNode ::initClass();
|
||||
MeshGui::SoFCMeshGridNode ::initClass();
|
||||
MeshGui::SoPolygon ::initClass();
|
||||
MeshGui::PropertyMeshKernelItem ::init();
|
||||
MeshGui::ViewProviderMesh ::init();
|
||||
MeshGui::ViewProviderMeshObject ::init();
|
||||
|
|
|
@ -24,6 +24,7 @@ set(Mesh_MOC_HDRS
|
|||
MeshEditor.h
|
||||
PropertyEditorMesh.h
|
||||
RemoveComponents.h
|
||||
Selection.h
|
||||
)
|
||||
fc_wrap_cpp(Mesh_MOC_SRCS ${Mesh_MOC_HDRS})
|
||||
SOURCE_GROUP("Moc" FILES ${Mesh_MOC_SRCS})
|
||||
|
@ -35,6 +36,7 @@ set(Dialogs_UIC_SRCS
|
|||
DlgSmoothing.ui
|
||||
RemoveComponents.ui
|
||||
Segmentation.ui
|
||||
Selection.ui
|
||||
)
|
||||
qt4_wrap_ui(Dialogs_UIC_HDRS ${Dialogs_UIC_SRCS})
|
||||
SET(Dialogs_SRCS
|
||||
|
@ -57,6 +59,9 @@ SET(Dialogs_SRCS
|
|||
Segmentation.ui
|
||||
Segmentation.cpp
|
||||
Segmentation.h
|
||||
Selection.ui
|
||||
Selection.cpp
|
||||
Selection.h
|
||||
)
|
||||
SOURCE_GROUP("Dialogs" FILES ${Dialogs_SRCS})
|
||||
|
||||
|
@ -65,6 +70,8 @@ SET(Inventor_SRCS
|
|||
SoFCIndexedFaceSet.h
|
||||
SoFCMeshObject.cpp
|
||||
SoFCMeshObject.h
|
||||
SoPolygon.cpp
|
||||
SoPolygon.h
|
||||
)
|
||||
SOURCE_GROUP("Inventor" FILES ${Inventor_SRCS})
|
||||
|
||||
|
@ -105,6 +112,8 @@ SET(MeshGui_SRCS
|
|||
PreCompiled.h
|
||||
MeshEditor.cpp
|
||||
MeshEditor.h
|
||||
MeshSelection.cpp
|
||||
MeshSelection.h
|
||||
PropertyEditorMesh.cpp
|
||||
PropertyEditorMesh.h
|
||||
Workbench.cpp
|
||||
|
|
|
@ -1019,9 +1019,19 @@ bool CmdMeshRemoveComponents::isActive(void)
|
|||
{
|
||||
// Check for the selected mesh feature (all Mesh types)
|
||||
App::Document* doc = getDocument();
|
||||
return (doc && doc->countObjectsOfType
|
||||
(Mesh::Feature::getClassTypeId()) > 0
|
||||
&& !Gui::Control().activeDialog());
|
||||
if (!(doc && doc->countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0))
|
||||
return false;
|
||||
Gui::Document* viewDoc = Gui::Application::Instance->getDocument(doc);
|
||||
Gui::View3DInventor* view = dynamic_cast<Gui::View3DInventor*>(viewDoc->getActiveView());
|
||||
if (view) {
|
||||
Gui::View3DInventorViewer* viewer = view->getViewer();
|
||||
if (viewer->isEditing())
|
||||
return false;
|
||||
}
|
||||
if (Gui::Control().activeDialog())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
@ -1046,7 +1056,7 @@ void CmdMeshRemoveCompByHand::activated(int iMsg)
|
|||
if (view) {
|
||||
Gui::View3DInventorViewer* viewer = view->getViewer();
|
||||
viewer->setEditing(true);
|
||||
//viewer->setEditingCursor(QCursor(Gui::BitmapFactory().pixmap("mesh_pipette"),4,29));
|
||||
viewer->setEditingCursor(QCursor(Qt::OpenHandCursor));
|
||||
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), MeshGui::ViewProviderMeshFaceSet::markPartCallback);
|
||||
}
|
||||
}
|
||||
|
@ -1120,7 +1130,8 @@ CmdMeshSmoothing::CmdMeshSmoothing()
|
|||
|
||||
void CmdMeshSmoothing::activated(int iMsg)
|
||||
{
|
||||
MeshGui::DlgSmoothing dlg(Gui::getMainWindow());
|
||||
#if 0
|
||||
MeshGui::SmoothingDialog dlg(Gui::getMainWindow());
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
Gui::WaitCursor wc;
|
||||
openCommand("Mesh Smoothing");
|
||||
|
@ -1149,10 +1160,17 @@ void CmdMeshSmoothing::activated(int iMsg)
|
|||
}
|
||||
commitCommand();
|
||||
}
|
||||
#else
|
||||
Gui::Control().showDialog(new MeshGui::TaskSmoothing());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CmdMeshSmoothing::isActive(void)
|
||||
{
|
||||
#if 1
|
||||
if (Gui::Control().activeDialog())
|
||||
return false;
|
||||
#endif
|
||||
// Check for the selected mesh feature (all Mesh types)
|
||||
return getSelection().countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0;
|
||||
}
|
||||
|
|
|
@ -23,17 +23,25 @@
|
|||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QButtonGroup>
|
||||
# include <QDialogButtonBox>
|
||||
#endif
|
||||
|
||||
#include "DlgSmoothing.h"
|
||||
#include "ui_DlgSmoothing.h"
|
||||
#include "Selection.h"
|
||||
|
||||
#include <Gui/WaitCursor.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Mod/Mesh/App/MeshFeature.h>
|
||||
#include <Mod/Mesh/App/Core/Smoothing.h>
|
||||
|
||||
using namespace MeshGui;
|
||||
|
||||
/* TRANSLATOR MeshGui::DlgSmoothing */
|
||||
|
||||
DlgSmoothing::DlgSmoothing(QWidget* parent, Qt::WFlags fl)
|
||||
: QDialog(parent, fl), ui(new Ui_DlgSmoothing())
|
||||
DlgSmoothing::DlgSmoothing(QWidget* parent)
|
||||
: QWidget(parent), ui(new Ui_DlgSmoothing())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
bg = new QButtonGroup(this);
|
||||
|
@ -92,4 +100,130 @@ DlgSmoothing::Smooth DlgSmoothing::method() const
|
|||
return DlgSmoothing::None;
|
||||
}
|
||||
|
||||
bool DlgSmoothing::smoothSelection() const
|
||||
{
|
||||
return ui->checkBoxSelection->isChecked();
|
||||
}
|
||||
|
||||
void DlgSmoothing::on_checkBoxSelection_toggled(bool on)
|
||||
{
|
||||
/*emit*/ toggledSelection(on);
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
|
||||
SmoothingDialog::SmoothingDialog(QWidget* parent, Qt::WFlags fl)
|
||||
: QDialog(parent, fl)
|
||||
{
|
||||
widget = new DlgSmoothing(this);
|
||||
this->setWindowTitle(widget->windowTitle());
|
||||
|
||||
QVBoxLayout* hboxLayout = new QVBoxLayout(this);
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(this);
|
||||
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
||||
|
||||
connect(buttonBox, SIGNAL(accepted()),
|
||||
this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()),
|
||||
this, SLOT(reject()));
|
||||
|
||||
hboxLayout->addWidget(widget);
|
||||
hboxLayout->addWidget(buttonBox);
|
||||
}
|
||||
|
||||
SmoothingDialog::~SmoothingDialog()
|
||||
{
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
|
||||
/* TRANSLATOR MeshGui::TaskSmoothing */
|
||||
|
||||
TaskSmoothing::TaskSmoothing()
|
||||
{
|
||||
widget = new DlgSmoothing();
|
||||
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
|
||||
QPixmap(), widget->windowTitle(), false, 0);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
|
||||
selection = new Selection();
|
||||
selection->setObjects(Gui::Selection().getSelectionEx(0, Mesh::Feature::getClassTypeId()));
|
||||
Gui::TaskView::TaskGroup* tasksel = new Gui::TaskView::TaskGroup();
|
||||
tasksel->groupLayout()->addWidget(selection);
|
||||
tasksel->hide();
|
||||
Content.push_back(tasksel);
|
||||
|
||||
connect(widget, SIGNAL(toggledSelection(bool)),
|
||||
tasksel, SLOT(setVisible(bool)));
|
||||
}
|
||||
|
||||
TaskSmoothing::~TaskSmoothing()
|
||||
{
|
||||
// automatically deleted in the sub-class
|
||||
}
|
||||
|
||||
bool TaskSmoothing::accept()
|
||||
{
|
||||
std::vector<App::DocumentObject*> meshes = selection->getObjects();
|
||||
if (meshes.empty())
|
||||
return true;
|
||||
|
||||
Gui::WaitCursor wc;
|
||||
Gui::Command::openCommand("Mesh Smoothing");
|
||||
|
||||
bool hasSelection = false;
|
||||
for (std::vector<App::DocumentObject*>::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
|
||||
Mesh::Feature* mesh = static_cast<Mesh::Feature*>(*it);
|
||||
std::vector<unsigned long> selection;
|
||||
if (widget->smoothSelection()) {
|
||||
// clear the selection before editing the mesh to avoid
|
||||
// to have coloured triangles when doing an 'undo'
|
||||
const Mesh::MeshObject* mm = mesh->Mesh.getValuePtr();
|
||||
mm->getFacetsFromSelection(selection);
|
||||
selection = mm->getPointsFromFacets(selection);
|
||||
mm->clearFacetSelection();
|
||||
if (!selection.empty())
|
||||
hasSelection = true;
|
||||
}
|
||||
Mesh::MeshObject* mm = mesh->Mesh.startEditing();
|
||||
switch (widget->method()) {
|
||||
case MeshGui::DlgSmoothing::Taubin:
|
||||
{
|
||||
MeshCore::TaubinSmoothing s(mm->getKernel());
|
||||
s.SetLambda(widget->lambdaStep());
|
||||
s.SetMicro(widget->microStep());
|
||||
if (widget->smoothSelection()) {
|
||||
s.SmoothPoints(widget->iterations(), selection);
|
||||
}
|
||||
else {
|
||||
s.Smooth(widget->iterations());
|
||||
}
|
||||
} break;
|
||||
case MeshGui::DlgSmoothing::Laplace:
|
||||
{
|
||||
MeshCore::LaplaceSmoothing s(mm->getKernel());
|
||||
s.SetLambda(widget->lambdaStep());
|
||||
if (widget->smoothSelection()) {
|
||||
s.SmoothPoints(widget->iterations(), selection);
|
||||
}
|
||||
else {
|
||||
s.Smooth(widget->iterations());
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mesh->Mesh.finishEditing();
|
||||
}
|
||||
|
||||
if (widget->smoothSelection() && !hasSelection) {
|
||||
Gui::Command::abortCommand();
|
||||
return false;
|
||||
}
|
||||
|
||||
Gui::Command::commitCommand();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "moc_DlgSmoothing.cpp"
|
||||
|
|
|
@ -25,13 +25,16 @@
|
|||
#define MESHGUI_DLGSMOOTHING_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
|
||||
class QButtonGroup;
|
||||
|
||||
namespace MeshGui {
|
||||
|
||||
class Selection;
|
||||
class Ui_DlgSmoothing;
|
||||
class DlgSmoothing : public QDialog
|
||||
class DlgSmoothing : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -42,21 +45,76 @@ public:
|
|||
Laplace
|
||||
};
|
||||
|
||||
DlgSmoothing(QWidget* parent = 0, Qt::WFlags fl = 0);
|
||||
DlgSmoothing(QWidget* parent = 0);
|
||||
~DlgSmoothing();
|
||||
int iterations() const;
|
||||
double lambdaStep() const;
|
||||
double microStep() const;
|
||||
Smooth method() const;
|
||||
bool smoothSelection() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void method_clicked(int);
|
||||
void on_checkBoxSelection_toggled(bool);
|
||||
|
||||
Q_SIGNALS:
|
||||
void toggledSelection(bool);
|
||||
|
||||
private:
|
||||
Ui_DlgSmoothing* ui;
|
||||
QButtonGroup* bg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Embed the panel into a dialog.
|
||||
*/
|
||||
class MeshGuiExport SmoothingDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SmoothingDialog(QWidget* parent = 0, Qt::WFlags fl = 0);
|
||||
~SmoothingDialog();
|
||||
|
||||
int iterations() const
|
||||
{ return widget->iterations(); }
|
||||
double lambdaStep() const
|
||||
{ return widget->lambdaStep(); }
|
||||
double microStep() const
|
||||
{ return widget->microStep(); }
|
||||
DlgSmoothing::Smooth method() const
|
||||
{ return widget->method(); }
|
||||
bool smoothSelection() const
|
||||
{ return widget->smoothSelection(); }
|
||||
|
||||
private:
|
||||
DlgSmoothing* widget;
|
||||
};
|
||||
|
||||
/**
|
||||
* Embed the panel into a task dialog.
|
||||
*/
|
||||
class TaskSmoothing : public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskSmoothing();
|
||||
~TaskSmoothing();
|
||||
|
||||
public:
|
||||
bool accept();
|
||||
|
||||
virtual QDialogButtonBox::StandardButtons getStandardButtons() const
|
||||
{ return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; }
|
||||
virtual bool isAllowedAlterDocument(void) const
|
||||
{ return true; }
|
||||
|
||||
private:
|
||||
DlgSmoothing* widget;
|
||||
Selection* selection;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MESHGUI_DLGSMOOTHING_H
|
||||
|
|
|
@ -1,172 +1,130 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MeshGui::DlgSmoothing</class>
|
||||
<widget class="QDialog" name="MeshGui::DlgSmoothing">
|
||||
<widget class="QWidget" name="MeshGui::DlgSmoothing">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>242</width>
|
||||
<height>251</height>
|
||||
<width>210</width>
|
||||
<height>227</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Smoothing</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<property name="sizeGripEnabled" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string/>
|
||||
<string>Method</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Method</string>
|
||||
<widget class="QRadioButton" name="radioButtonTaubin">
|
||||
<property name="text">
|
||||
<string>Taubin</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="radioButtonTaubin">
|
||||
<property name="text">
|
||||
<string>Taubin</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QRadioButton" name="radioButtonLaplace">
|
||||
<property name="text">
|
||||
<string>Laplace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Parameter</string>
|
||||
<item row="0" column="1">
|
||||
<widget class="QRadioButton" name="radioButtonLaplace">
|
||||
<property name="text">
|
||||
<string>Laplace</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Iterations:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="iterations">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelLambda">
|
||||
<property name="text">
|
||||
<string>Lambda:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinLambda">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.630700000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelMu">
|
||||
<property name="text">
|
||||
<string>Mu:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinMicro">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.042400000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Parameter</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Iterations:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="iterations">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelLambda">
|
||||
<property name="text">
|
||||
<string>Lambda:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinLambda">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.630700000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelMu">
|
||||
<property name="text">
|
||||
<string>Mu:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="spinMicro">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.042400000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxSelection">
|
||||
<property name="text">
|
||||
<string>Only selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MeshGui::DlgSmoothing</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>94</x>
|
||||
<y>191</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>-3</x>
|
||||
<y>193</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MeshGui::DlgSmoothing</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>190</x>
|
||||
<y>193</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>219</x>
|
||||
<y>151</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -40,15 +40,21 @@
|
|||
# include <Inventor/nodes/SoFaceSet.h>
|
||||
# include <Inventor/nodes/SoLineSet.h>
|
||||
# include <Inventor/nodes/SoMarkerSet.h>
|
||||
# include <Inventor/nodes/SoPickStyle.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
# include <Inventor/nodes/SoShapeHints.h>
|
||||
# include <boost/bind.hpp>
|
||||
#endif
|
||||
|
||||
#include "MeshEditor.h"
|
||||
#include "SoFCMeshObject.h"
|
||||
#include "SoPolygon.h"
|
||||
#include <App/Document.h>
|
||||
#include <Mod/Mesh/App/MeshFeature.h>
|
||||
#include <Mod/Mesh/App/Core/Algorithm.h>
|
||||
#include <Mod/Mesh/App/Core/Triangulation.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
|
||||
|
@ -278,8 +284,19 @@ void MeshFaceAddition::showMarker(SoPickedPoint* pp)
|
|||
return;
|
||||
// is a border facet picked?
|
||||
MeshCore::MeshFacet f = facets[face_index];
|
||||
if (!f.HasOpenEdge())
|
||||
return;
|
||||
if (!f.HasOpenEdge()) {
|
||||
// check if a neighbour facet is at the border
|
||||
bool ok=false;
|
||||
for (int i=0; i<3; i++) {
|
||||
if (facets[f._aulNeighbours[i]].HasOpenEdge()) {
|
||||
f = facets[f._aulNeighbours[i]];
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
return;
|
||||
}
|
||||
|
||||
int point_index = -1;
|
||||
float distance = FLT_MAX;
|
||||
|
@ -372,4 +389,326 @@ void MeshFaceAddition::addFacetCallback(void * ud, SoEventCallback * n)
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
namespace MeshGui {
|
||||
// for sorting of elements
|
||||
struct NofFacetsCompare : public std::binary_function<const std::vector<unsigned long>&,
|
||||
const std::vector<unsigned long>&, bool>
|
||||
{
|
||||
bool operator () (const std::vector<unsigned long> &rclC1,
|
||||
const std::vector<unsigned long> &rclC2)
|
||||
{
|
||||
return rclC1.size() < rclC2.size();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* TRANSLATOR MeshGui::MeshFillHole */
|
||||
|
||||
MeshFillHole::MeshFillHole(MeshHoleFiller& hf, Gui::View3DInventor* parent)
|
||||
: QObject(parent), myMesh(0), myNumPoints(0), myHoleFiller(hf)
|
||||
{
|
||||
myBoundariesRoot = new SoSeparator;
|
||||
myBoundariesRoot->ref();
|
||||
myBoundaryRoot = new SoSeparator;
|
||||
myBoundaryRoot->ref();
|
||||
myBoundariesGroup = new SoSeparator();
|
||||
myBoundariesGroup->ref();
|
||||
myBridgeRoot = new SoSeparator;
|
||||
myBridgeRoot->ref();
|
||||
|
||||
SoDrawStyle* pointStyle = new SoDrawStyle();
|
||||
pointStyle->style = SoDrawStyle::POINTS;
|
||||
pointStyle->pointSize = 8.0f;
|
||||
myBridgeRoot->addChild(pointStyle);
|
||||
|
||||
SoBaseColor * markcol = new SoBaseColor;
|
||||
markcol->rgb.setValue(1.0f, 1.0f, 0.0f);
|
||||
SoPointSet* marker = new SoPointSet();
|
||||
myBridgeRoot->addChild(markcol);
|
||||
|
||||
myVertex = new SoCoordinate3();
|
||||
myBridgeRoot->addChild(myVertex);
|
||||
myBridgeRoot->addChild(new SoPointSet);
|
||||
}
|
||||
|
||||
MeshFillHole::~MeshFillHole()
|
||||
{
|
||||
myBoundariesRoot->unref();
|
||||
myBoundariesGroup->unref();
|
||||
myBoundaryRoot->unref();
|
||||
myBridgeRoot->unref();
|
||||
}
|
||||
|
||||
void MeshFillHole::startEditing(MeshGui::ViewProviderMesh* vp)
|
||||
{
|
||||
this->myMesh = static_cast<Mesh::Feature*>(vp->getObject());
|
||||
|
||||
Gui::View3DInventor* view = static_cast<Gui::View3DInventor*>(parent());
|
||||
Gui::View3DInventorViewer* viewer = view->getViewer();
|
||||
viewer->setEditing(true);
|
||||
//viewer->setRedirectToSceneGraph(true);
|
||||
viewer->addEventCallback(SoEvent::getClassTypeId(),
|
||||
MeshFillHole::fileHoleCallback, this);
|
||||
myConnection = App::GetApplication().signalChangedObject.connect(
|
||||
boost::bind(&MeshFillHole::slotChangedObject, this, _1, _2));
|
||||
|
||||
myBoundariesRoot->removeAllChildren();
|
||||
myBoundariesRoot->addChild(viewer->getHeadlight());
|
||||
myBoundariesRoot->addChild(viewer->getCamera());
|
||||
myBoundariesRoot->addChild(myBoundariesGroup);
|
||||
myBoundaryRoot->removeAllChildren();
|
||||
myBoundaryRoot->addChild(viewer->getHeadlight());
|
||||
myBoundaryRoot->addChild(viewer->getCamera());
|
||||
createPolygons();
|
||||
static_cast<SoGroup*>(viewer->getSceneGraph())->addChild(myBridgeRoot);
|
||||
}
|
||||
|
||||
void MeshFillHole::finishEditing()
|
||||
{
|
||||
Gui::View3DInventor* view = static_cast<Gui::View3DInventor*>(parent());
|
||||
Gui::View3DInventorViewer* viewer = view->getViewer();
|
||||
viewer->setEditing(false);
|
||||
//viewer->setRedirectToSceneGraph(false);
|
||||
viewer->removeEventCallback(SoEvent::getClassTypeId(),
|
||||
MeshFillHole::fileHoleCallback, this);
|
||||
myConnection.disconnect();
|
||||
this->deleteLater();
|
||||
static_cast<SoGroup*>(viewer->getSceneGraph())->removeChild(myBridgeRoot);
|
||||
}
|
||||
|
||||
void MeshFillHole::closeBridge()
|
||||
{
|
||||
// Do the hole-filling
|
||||
Gui::WaitCursor wc;
|
||||
TBoundary::iterator it = std::find(myPolygon.begin(), myPolygon.end(), myVertex1);
|
||||
TBoundary::iterator jt = std::find(myPolygon.begin(), myPolygon.end(), myVertex2);
|
||||
if (it != myPolygon.end() && jt != myPolygon.end()) {
|
||||
// which iterator comes first
|
||||
if (jt < it)
|
||||
std::swap(it, jt);
|
||||
// split the boundary into two loops and take the shorter one
|
||||
std::list<TBoundary> bounds;
|
||||
TBoundary loop1, loop2;
|
||||
loop1.insert(loop1.end(), myPolygon.begin(), it);
|
||||
loop1.insert(loop1.end(), jt, myPolygon.end());
|
||||
loop2.insert(loop2.end(), it, jt);
|
||||
// this happens when myVertex1 == myVertex2
|
||||
if (loop2.empty())
|
||||
bounds.push_back(loop1);
|
||||
else if (loop1.size() < loop2.size())
|
||||
bounds.push_back(loop1);
|
||||
else
|
||||
bounds.push_back(loop2);
|
||||
|
||||
App::Document* doc = myMesh->getDocument();
|
||||
doc->openTransaction("Bridge && Fill hole");
|
||||
Mesh::MeshObject* pMesh = myMesh->Mesh.startEditing();
|
||||
bool ok = myHoleFiller.fillHoles(*pMesh, bounds, myVertex1, myVertex2);
|
||||
myMesh->Mesh.finishEditing();
|
||||
if (ok)
|
||||
doc->commitTransaction();
|
||||
else
|
||||
doc->abortTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void MeshFillHole::slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop)
|
||||
{
|
||||
if (&Obj == myMesh && strcmp(Prop.getName(),"Mesh") == 0) {
|
||||
myBoundariesGroup->removeAllChildren();
|
||||
myVertex->point.setNum(0);
|
||||
myNumPoints = 0;
|
||||
myPolygon.clear();
|
||||
|
||||
createPolygons();
|
||||
}
|
||||
}
|
||||
|
||||
void MeshFillHole::createPolygons()
|
||||
{
|
||||
Gui::WaitCursor wc;
|
||||
myPolygons.clear();
|
||||
|
||||
SoPickStyle* pickStyle = new SoPickStyle();
|
||||
pickStyle->style = SoPickStyle::BOUNDING_BOX;
|
||||
myBoundariesGroup->addChild(pickStyle);
|
||||
myBoundaryRoot->addChild(pickStyle);
|
||||
|
||||
// get mesh kernel
|
||||
const MeshCore::MeshKernel & rMesh = this->myMesh->Mesh.getValue().getKernel();
|
||||
|
||||
// get the mesh boundaries as an array of point indices
|
||||
std::list<std::vector<unsigned long> > borders;
|
||||
MeshCore::MeshAlgorithm cAlgo(rMesh);
|
||||
MeshCore::MeshPointIterator p_iter(rMesh);
|
||||
cAlgo.GetMeshBorders(borders);
|
||||
cAlgo.SplitBoundaryLoops(borders);
|
||||
|
||||
// sort the borders in ascending order of the number of edges
|
||||
borders.sort(NofFacetsCompare());
|
||||
|
||||
int32_t count=0;
|
||||
for (std::list<std::vector<unsigned long> >::iterator it =
|
||||
borders.begin(); it != borders.end(); ++it) {
|
||||
if (it->front() == it->back())
|
||||
it->pop_back();
|
||||
count += it->size();
|
||||
}
|
||||
|
||||
SoCoordinate3* coords = new SoCoordinate3();
|
||||
myBoundariesGroup->addChild(coords);
|
||||
myBoundaryRoot->addChild(coords);
|
||||
|
||||
coords->point.setNum(count);
|
||||
int32_t index = 0;
|
||||
for (std::list<std::vector<unsigned long> >::iterator it =
|
||||
borders.begin(); it != borders.end(); ++it) {
|
||||
SoPolygon* polygon = new SoPolygon();
|
||||
polygon->startIndex = index;
|
||||
polygon->numVertices = it->size();
|
||||
myBoundariesGroup->addChild(polygon);
|
||||
myPolygons[polygon] = *it;
|
||||
for (std::vector<unsigned long>::iterator jt = it->begin();
|
||||
jt != it->end(); ++jt) {
|
||||
p_iter.Set(*jt);
|
||||
coords->point.set1Value(index++,p_iter->x,p_iter->y,p_iter->z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SoNode* MeshFillHole::getPickedPolygon(const SoRayPickAction& action/*SoNode* root, const SbVec2s& pos, const SoQtViewer* viewer*/) const
|
||||
{
|
||||
SoPolygon* poly = 0;
|
||||
const SoPickedPointList & points = action.getPickedPointList();
|
||||
for (int i=0; i < points.getLength(); i++) {
|
||||
const SoPickedPoint * point = points[i];
|
||||
if (point && point->getPath()->getTail()->getTypeId() == MeshGui::SoPolygon::getClassTypeId()) {
|
||||
// we have something picked, now check if it was an SoPolygon node
|
||||
SoPolygon* node = static_cast<SoPolygon*>(point->getPath()->getTail());
|
||||
if (!poly) {
|
||||
poly = node;
|
||||
}
|
||||
// check which polygon has less edges
|
||||
else if (node->numVertices.getValue() < poly->numVertices.getValue()) {
|
||||
poly = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return poly;
|
||||
}
|
||||
|
||||
float MeshFillHole::findClosestPoint(const SbLine& ray, const TBoundary& polygon,
|
||||
unsigned long& vertex_index, SbVec3f& closestPoint) const
|
||||
{
|
||||
// now check which vertex of the polygon is closest to the ray
|
||||
float minDist = FLT_MAX;
|
||||
vertex_index = ULONG_MAX;
|
||||
|
||||
const MeshCore::MeshKernel & rMesh = myMesh->Mesh.getValue().getKernel();
|
||||
const MeshCore::MeshPointArray& pts = rMesh.GetPoints();
|
||||
for (TBoundary::const_iterator it = polygon.begin(); it != polygon.end(); ++it) {
|
||||
SbVec3f vertex;
|
||||
const Base::Vector3f& v = pts[*it];
|
||||
vertex.setValue(v.x,v.y,v.z);
|
||||
SbVec3f point = ray.getClosestPoint(vertex);
|
||||
float distance = (vertex-point).sqrLength();
|
||||
if (distance < minDist) {
|
||||
minDist = distance;
|
||||
vertex_index = *it;
|
||||
closestPoint = vertex;
|
||||
}
|
||||
}
|
||||
|
||||
return minDist;
|
||||
}
|
||||
|
||||
void MeshFillHole::fileHoleCallback(void * ud, SoEventCallback * n)
|
||||
{
|
||||
MeshFillHole* self = reinterpret_cast<MeshFillHole*>(ud);
|
||||
Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
|
||||
|
||||
const SoEvent* ev = n->getEvent();
|
||||
if (ev->getTypeId() == SoLocation2Event::getClassTypeId()) {
|
||||
n->setHandled();
|
||||
SoRayPickAction rp(view->getViewportRegion());
|
||||
rp.setPoint(ev->getPosition());
|
||||
rp.setPickAll(true);
|
||||
if (self->myNumPoints == 0)
|
||||
rp.apply(self->myBoundariesRoot);
|
||||
else
|
||||
rp.apply(self->myBoundaryRoot);
|
||||
SoNode* node = self->getPickedPolygon(rp);
|
||||
if (node) {
|
||||
std::map<SoNode*, TBoundary>::iterator it = self->myPolygons.find(node);
|
||||
if (it != self->myPolygons.end()) {
|
||||
// now check which vertex of the polygon is closest to the ray
|
||||
unsigned long vertex_index;
|
||||
SbVec3f closestPoint;
|
||||
float minDist = self->findClosestPoint(rp.getLine(), it->second, vertex_index, closestPoint);
|
||||
if (minDist < 1.0f) {
|
||||
if (self->myNumPoints == 0)
|
||||
self->myVertex->point.set1Value(0, closestPoint);
|
||||
else
|
||||
self->myVertex->point.set1Value(1, closestPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
|
||||
n->setHandled();
|
||||
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ev);
|
||||
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
|
||||
}
|
||||
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::UP) {
|
||||
if (self->myNumPoints > 1)
|
||||
return;
|
||||
SoRayPickAction rp(view->getViewportRegion());
|
||||
rp.setPoint(ev->getPosition());
|
||||
rp.setPickAll(true);
|
||||
if (self->myNumPoints == 0)
|
||||
rp.apply(self->myBoundariesRoot);
|
||||
else
|
||||
rp.apply(self->myBoundaryRoot);
|
||||
SoNode* node = self->getPickedPolygon(rp);
|
||||
if (node) {
|
||||
std::map<SoNode*, TBoundary>::iterator it = self->myPolygons.find(node);
|
||||
if (it != self->myPolygons.end()) {
|
||||
// now check which vertex of the polygon is closest to the ray
|
||||
unsigned long vertex_index;
|
||||
SbVec3f closestPoint;
|
||||
float minDist = self->findClosestPoint(rp.getLine(), it->second, vertex_index, closestPoint);
|
||||
if (minDist < 1.0f) {
|
||||
if (self->myNumPoints == 0) {
|
||||
self->myBoundaryRoot->addChild(node);
|
||||
self->myVertex->point.set1Value(0, closestPoint);
|
||||
self->myNumPoints = 1;
|
||||
self->myVertex1 = vertex_index;
|
||||
}
|
||||
else {
|
||||
// myVertex2 can be equal to myVertex1 which does a full hole-filling
|
||||
self->myBoundaryRoot->removeChild(node);
|
||||
self->myVertex->point.set1Value(1, closestPoint);
|
||||
self->myNumPoints = 2;
|
||||
self->myVertex2 = vertex_index;
|
||||
self->myPolygon = it->second;
|
||||
QTimer::singleShot(300, self, SLOT(closeBridge()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
|
||||
QMenu menu;
|
||||
QAction* fin = menu.addAction(MeshFillHole::tr("Finish"));
|
||||
QAction* act = menu.exec(QCursor::pos());
|
||||
if (act == fin) {
|
||||
QTimer::singleShot(300, self, SLOT(finishEditing()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_MeshEditor.cpp"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user