diff --git a/.gitignore b/.gitignore
index 761f4120f..a850113c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,13 @@
# file types to ignore
*.pyc
+*~
+CMakeFiles/
+*qrc.depends
+qrc_*.cpp
+ui_*.h
+moc_*.cpp
+Makefile
+CMakeCache.txt
+config.h
+install_manifest.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 91d447c10..a3867b17a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,6 +71,13 @@ endif(WIN32)
SET(CMAKE_INSTALL_DATADIR data CACHE PATH "Output directory for data and resource files")
SET(CMAKE_INSTALL_INCLUDEDIR include CACHE PATH "Output directory for header files")
SET(CMAKE_INSTALL_DOCDIR doc CACHE PATH "Output directory for documentation and license files")
+
+SET(PYCXX_INCLUDE_DIR
+ "${CMAKE_SOURCE_DIR}/src" CACHE PATH
+ "Path to the directory containing PyCXX's CXX/Config.hxx include file")
+SET(PYCXX_SOURCE_DIR
+ "${CMAKE_SOURCE_DIR}/src/CXX" CACHE PATH
+ "Path to the directory containing PyCXX's cxxextensions.c source file")
# used as compiler defines
SET(RESOURCEDIR "${CMAKE_INSTALL_DATADIR}")
@@ -152,6 +159,10 @@ if(FREECAD_LIBPACK_USE)
message(SEND_ERROR "Could not find neither LibPack 6.x nor 7.x in specified location:" ${FREECAD_LIBPACK_DIR})
ENDIF(FREECAD_LIBPACK_CHECKFILE6X)
+# -------------------------------- PyCXX --------------------------------
+
+ find_package(PyCXX REQUIRED)
+
# -------------------------------- Swig ----------------------------------
find_package(SWIG)
@@ -204,6 +215,10 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
find_package(ZLIB REQUIRED)
+# -------------------------------- PyCXX --------------------------------
+
+ find_package(PyCXX REQUIRED)
+
# -------------------------------- OpenCasCade --------------------------------
#first, look for OpenCASCADE Community Edition (OCE)
diff --git a/cMake/FindPyCXX.cmake b/cMake/FindPyCXX.cmake
new file mode 100644
index 000000000..37d1f8147
--- /dev/null
+++ b/cMake/FindPyCXX.cmake
@@ -0,0 +1,108 @@
+# Locate PyCXX headers and source files
+
+# This module defines
+# PYCXX_INCLUDE_DIR
+# PYCXX_SOURCE_DIR
+# PYCXX_FOUND
+# PYCXX_SOURCES
+#
+# The PYCXX_*_DIR variables can be set to tell this module where
+# the files are.
+
+
+# There's no standard location for PyCXX.
+#
+# The authors' example is to put it in "~\" [sic].
+#
+# Ubuntu puts the includes into /usr/include/python2.7/CXX and sources into
+# /usr/share/python2.7/CXX.
+#
+# The Zultron Fedora RPM does the same as Ubuntu.
+
+set(PYCXX_FOUND "YES")
+
+# find the header directory
+if(PYCXX_INCLUDE_DIR)
+ # headers better be in there
+ if(NOT EXISTS "${PYCXX_INCLUDE_DIR}/CXX/Config.hxx")
+ if(PyCXX_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR
+ "PyCXX: could not find CXX/Config.hxx in PYCXX_INCLUDE_DIR "
+ "${PYCXX_INCLUDE_DIR}")
+ else(PyCXX_FIND_REQUIRED)
+ MESSAGE(WARNING
+ "PyCXX: could not find CXX/Config.hxx in PYCXX_INCLUDE_DIR "
+ "${PYCXX_INCLUDE_DIR}")
+ unset(PYCXX_FOUND)
+ endif(PyCXX_FIND_REQUIRED)
+ endif(NOT EXISTS "${PYCXX_INCLUDE_DIR}/CXX/Config.hxx")
+else(PYCXX_INCLUDE_DIR)
+ # check in 'standard' places
+ find_path(PYCXX_INCLUDE_DIR CXX/Config.hxx
+ ${PYTHON_INCLUDE_DIR}
+ "${CMAKE_CURRENT_LIST_DIR}/..")
+ if(NOT PYCXX_INCLUDE_DIR)
+ if(PyCXX_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR
+ "PyCXX not found; please set PYCXX_INCLUDE_DIR to "
+ "the location of CXX/Config.hxx")
+ else(PyCXX_FIND_REQUIRED)
+ MESSAGE(STATUS "PyCXX not found")
+ unset(PYCXX_FOUND)
+ endif(PyCXX_FIND_REQUIRED)
+ endif(NOT PYCXX_INCLUDE_DIR)
+endif(PYCXX_INCLUDE_DIR)
+
+# find the sources directory
+if(PYCXX_SOURCE_DIR)
+ # source directory specified, they'd better be there
+ if(NOT EXISTS "${PYCXX_SOURCE_DIR}/cxxextensions.c")
+ if(PyCXX_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR
+ "PyCXX: cxxextensions.c not found in PYCXX_INCLUDE_DIR "
+ "${PYCXX_INCLUDE_DIR}")
+ else(PyCXX_FIND_REQUIRED)
+ MESSAGE(WARNING
+ "PyCXX: cxxextensions.c not found in PYCXX_INCLUDE_DIR "
+ "${PYCXX_INCLUDE_DIR}")
+ unset(PYCXX_FOUND)
+ endif(PyCXX_FIND_REQUIRED)
+ endif(NOT EXISTS "${PYCXX_SOURCE_DIR}/cxxextensions.c")
+else(PYCXX_SOURCE_DIR)
+ # check in 'standard' places
+ find_path(PYCXX_SOURCE_DIR cxxextensions.c
+ "${PYCXX_INCLUDE_DIR}/CXX"
+ "${PYCXX_INCLUDE_DIR}/Src"
+ "${PYTHON_INCLUDE_DIR}/CXX"
+ "${PYTHON_INCLUDE_DIR}/Src"
+ "${CMAKE_CURRENT_LIST_DIR}/../Src"
+ "${CMAKE_CURRENT_LIST_DIR}/../CXX")
+ if(NOT PYCXX_SOURCE_DIR)
+ if(PyCXX_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR
+ "PyCXX not found; please set PYCXX_SOURCE_DIR to "
+ "the location of cxxextensions.c")
+ else(PyCXX_FIND_REQUIRED)
+ MESSAGE(STATUS "PyCXX not found")
+ unset(PYCXX_FOUND)
+ endif(PyCXX_FIND_REQUIRED)
+ endif(NOT PYCXX_SOURCE_DIR)
+endif(PYCXX_SOURCE_DIR)
+
+# see what we've got
+if(PYCXX_FOUND)
+ MESSAGE(STATUS "PyCXX found:")
+ MESSAGE(STATUS " Headers: ${PYCXX_INCLUDE_DIR}")
+ MESSAGE(STATUS " Sources: ${PYCXX_SOURCE_DIR}")
+
+ # Build the list of sources for convenience
+ set(PYCXX_SOURCES
+ ${PYCXX_SOURCE_DIR}/cxxextensions.c
+ ${PYCXX_SOURCE_DIR}/cxx_extensions.cxx
+ ${PYCXX_SOURCE_DIR}/cxxsupport.cxx
+ ${PYCXX_SOURCE_DIR}/IndirectPythonInterface.cxx
+ )
+else(PYCXX_FOUND)
+ MESSAGE(STATUS "PyCXX not found")
+endif(PYCXX_FOUND)
+
diff --git a/src/3rdParty/salomesmesh/CMakeLists.txt b/src/3rdParty/salomesmesh/CMakeLists.txt
index 21e321308..79381c68c 100644
--- a/src/3rdParty/salomesmesh/CMakeLists.txt
+++ b/src/3rdParty/salomesmesh/CMakeLists.txt
@@ -140,13 +140,13 @@ if(MSVC)
elseif(MINGW)
set_target_properties(SMDS PROPERTIES COMPILE_FLAGS "-DSMDS_EXPORTS")
set_target_properties(SMDS PROPERTIES OUTPUT_NAME "SMDS")
- set_target_properties(SMDS PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(SMDS PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(SMDS PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(SMDS PROPERTIES OUTPUT_NAME "SMDS")
- set_target_properties(SMDS PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(SMDS PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(SMDS PROPERTIES PREFIX "")
- set_target_properties(SMDS PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(SMDS PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
##########
@@ -165,13 +165,13 @@ if(MSVC)
elseif(MINGW)
set_target_properties(Driver PROPERTIES COMPILE_FLAGS "-DMESHDRIVER_EXPORTS")
set_target_properties(Driver PROPERTIES OUTPUT_NAME "Driver")
- set_target_properties(Driver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(Driver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(Driver PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(Driver PROPERTIES OUTPUT_NAME "Driver")
- set_target_properties(Driver PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(Driver PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(Driver PROPERTIES PREFIX "")
- set_target_properties(Driver PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(Driver PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
@@ -199,13 +199,13 @@ if(MSVC)
elseif(MINGW)
set_target_properties(DriverSTL PROPERTIES COMPILE_FLAGS "-DMESHDRIVERSTL_EXPORTS")
set_target_properties(DriverSTL PROPERTIES OUTPUT_NAME "DriverSTL")
- set_target_properties(DriverSTL PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(DriverSTL PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(DriverSTL PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(DriverSTL PROPERTIES OUTPUT_NAME "DriverSTL")
- set_target_properties(DriverSTL PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(DriverSTL PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(DriverSTL PROPERTIES PREFIX "")
- set_target_properties(DriverSTL PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(DriverSTL PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
@@ -233,13 +233,13 @@ if(MSVC)
elseif(MINGW)
set_target_properties(DriverDAT PROPERTIES COMPILE_FLAGS "-DMESHDRIVERDAT_EXPORTS")
set_target_properties(DriverDAT PROPERTIES OUTPUT_NAME "DriverDAT")
- set_target_properties(DriverDAT PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(DriverDAT PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(DriverDAT PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(DriverDAT PROPERTIES OUTPUT_NAME "DriverDAT")
- set_target_properties(DriverDAT PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(DriverDAT PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(DriverDAT PROPERTIES PREFIX "")
- set_target_properties(DriverDAT PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(DriverDAT PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
@@ -267,13 +267,13 @@ if(MSVC)
elseif(MINGW)
set_target_properties(DriverUNV PROPERTIES COMPILE_FLAGS "-DMESHDRIVERUNV_EXPORTS")
set_target_properties(DriverUNV PROPERTIES OUTPUT_NAME "DriverUNV")
- set_target_properties(DriverUNV PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(DriverUNV PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(DriverUNV PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(DriverUNV PROPERTIES OUTPUT_NAME "DriverUNV")
- set_target_properties(DriverUNV PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(DriverUNV PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(DriverUNV PROPERTIES PREFIX "")
- set_target_properties(DriverUNV PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(DriverUNV PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
@@ -299,13 +299,13 @@ if(MSVC)
set_target_properties(SMESHDS PROPERTIES PREFIX "../")
elseif(MINGW)
set_target_properties(SMESHDS PROPERTIES OUTPUT_NAME "SMESHDS")
- set_target_properties(SMESHDS PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(SMESHDS PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(SMESHDS PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(SMESHDS PROPERTIES OUTPUT_NAME "SMESHDS")
- set_target_properties(SMESHDS PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(SMESHDS PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(SMESHDS PROPERTIES PREFIX "")
- set_target_properties(SMESHDS PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(SMESHDS PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
@@ -330,12 +330,13 @@ if(MSVC)
elseif(MINGW)
set_target_properties(SMESH PROPERTIES COMPILE_FLAGS "-DSMESH_EXPORTS -DSMESHCONTROLS_EXPORTS -DSMESHimpl_EXPORTS")
set_target_properties(SMESH PROPERTIES OUTPUT_NAME "SMESH")
- set_target_properties(SMESH PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(SMESH PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(SMESH PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(SMESH PROPERTIES OUTPUT_NAME "SMESH")
+ set_target_properties(SMESH PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(SMESH PROPERTIES PREFIX "")
- set_target_properties(SMESH PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(SMESH PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
@@ -379,14 +380,15 @@ elseif(MINGW)
TARGET_LINK_LIBRARIES(MEFISTO2 ${SMESH_LIBS} gfortran)
set_target_properties(MEFISTO2 PROPERTIES COMPILE_FLAGS "-DMEFISTO2D_EXPORTS")
set_target_properties(MEFISTO2 PROPERTIES OUTPUT_NAME "MEFISTO2")
- set_target_properties(MEFISTO2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(MEFISTO2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(MEFISTO2 PROPERTIES PREFIX "")
else(MSVC)
TARGET_LINK_LIBRARIES(MEFISTO2 ${SMESH_LIBS} gfortran)
set_target_properties(MEFISTO2 PROPERTIES COMPILE_FLAGS "${MEFISTO2_CFLAGS}")
set_target_properties(MEFISTO2 PROPERTIES OUTPUT_NAME "MEFISTO2")
+ set_target_properties(MEFISTO2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(MEFISTO2 PROPERTIES PREFIX "")
- set_target_properties(MEFISTO2 PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(MEFISTO2 PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
@@ -407,7 +409,7 @@ elseif(MINGW)
TARGET_LINK_LIBRARIES(StdMeshers SMESH ${SMESH_LIBS} MEFISTO2)
set_target_properties(StdMeshers PROPERTIES COMPILE_FLAGS "-DSTDMESHERS_EXPORTS")
set_target_properties(StdMeshers PROPERTIES OUTPUT_NAME "StdMeshers")
- set_target_properties(StdMeshers PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(StdMeshers PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(StdMeshers PROPERTIES PREFIX "")
else(MSVC)
TARGET_LINK_LIBRARIES(StdMeshers SMESH ${SMESH_LIBS} MEFISTO2)
@@ -419,8 +421,9 @@ else(MSVC)
ENDIF(${CMAKE_SIZEOF_VOID_P} MATCHES "8")
set_target_properties(StdMeshers PROPERTIES COMPILE_FLAGS "${StdMeshers_CFLAGS}")
set_target_properties(StdMeshers PROPERTIES OUTPUT_NAME "StdMeshers")
+ set_target_properties(StdMeshers PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(StdMeshers PROPERTIES PREFIX "")
- set_target_properties(StdMeshers PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(StdMeshers PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
#SET(StdMeshers_CFLAGS "")
@@ -450,12 +453,13 @@ if(MSVC)
elseif(MINGW)
set_target_properties(NETGENPlugin PROPERTIES COMPILE_FLAGS "-DNETGENPLUGIN_EXPORTS -DNO_PARALLEL_THREADS -DOCCGEOMETRY")
set_target_properties(NETGENPlugin PROPERTIES OUTPUT_NAME "NETGENPlugin")
- set_target_properties(NETGENPlugin PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set_target_properties(NETGENPlugin PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(NETGENPlugin PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(NETGENPlugin PROPERTIES OUTPUT_NAME "NETGENPlugin")
+ set_target_properties(NETGENPlugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set_target_properties(NETGENPlugin PROPERTIES PREFIX "")
- set_target_properties(NETGENPlugin PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin)
+ set_target_properties(NETGENPlugin PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
endif(MSVC)
endif (FREECAD_BUILD_FEM_NETGEN)
@@ -468,4 +472,27 @@ endif (FREECAD_BUILD_FEM_NETGEN)
#ENDIF(MINGW)
+if(WIN32)
+ INSTALL(TARGETS SMDS Driver DriverSTL DriverDAT DriverUNV SMESHDS SMESH MEFISTO2 StdMeshers
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ )
+else(WIN32)
+ INSTALL(TARGETS SMDS Driver DriverSTL DriverDAT DriverUNV SMESHDS SMESH MEFISTO2 StdMeshers
+ LIBRARY DESTINATION lib
+ )
+endif(WIN32)
+
+if (FREECAD_BUILD_FEM_NETGEN)
+ if(WIN32)
+ INSTALL(TARGETS NETGENPlugin
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ )
+ else(WIN32)
+ INSTALL(TARGETS NETGENPlugin
+ LIBRARY DESTINATION lib
+ )
+ endif(WIN32)
+endif (FREECAD_BUILD_FEM_NETGEN)
diff --git a/src/App/Application.cpp b/src/App/Application.cpp
index f1b526f56..db242cddb 100644
--- a/src/App/Application.cpp
+++ b/src/App/Application.cpp
@@ -1385,6 +1385,10 @@ namespace boost { namespace filesystem {
pair customSyntax(const string& s)
{
+#if defined(FC_OS_MACOSX)
+ if (s.find("-psn_") == 0)
+ return make_pair(string("psn"), s.substr(5));
+#endif
if (s.find("-display") == 0)
return make_pair(string("display"), string("null"));
else if (s.find("-style") == 0)
@@ -1493,6 +1497,9 @@ void Application::ParseOptions(int ac, char ** av)
("visual", boost::program_options::value< string >(), "set the X-Window to color scema")
("ncols", boost::program_options::value< int >(), "set the X-Window to color scema")
("cmap", "set the X-Window to color scema")
+#if defined(FC_OS_MACOSX)
+ ("psn", boost::program_options::value< string >(), "process serial number")
+#endif
;
// Ignored options, will be savely ignored. Mostly uses by underlaying libs.
diff --git a/src/App/Document.cpp b/src/App/Document.cpp
index ee92e46da..5f476c04c 100644
--- a/src/App/Document.cpp
+++ b/src/App/Document.cpp
@@ -229,8 +229,8 @@ bool Document::undo(void)
if (d->iUndoMode) {
if (d->activeUndoTransaction)
commitTransaction();
- else
- assert(mUndoTransactions.size()!=0);
+ else if (mUndoTransactions.empty())
+ return false;
// redo
d->activeUndoTransaction = new Transaction();
@@ -313,12 +313,21 @@ void Document::openTransaction(const char* name)
}
}
-void Document::_checkTransaction(void)
+void Document::_checkTransaction(DocumentObject* pcObject)
{
// if the undo is active but no transaction open, open one!
if (d->iUndoMode) {
- if (!d->activeUndoTransaction)
- openTransaction();
+ if (!d->activeUndoTransaction) {
+ // When the object is going to be deleted we have to check if it has already been added to
+ // the undo transactions
+ std::list::iterator it;
+ for (it = mUndoTransactions.begin(); it != mUndoTransactions.end(); ++it) {
+ if ((*it)->hasObject(pcObject)) {
+ openTransaction();
+ break;
+ }
+ }
+ }
}
}
@@ -1440,14 +1449,14 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName)
/// Remove an object out of the document
void Document::remObject(const char* sName)
{
- _checkTransaction();
-
std::map::iterator pos = d->objectMap.find(sName);
// name not found?
if (pos == d->objectMap.end())
return;
+ _checkTransaction(pos->second);
+
if (d->activeObject == pos->second)
d->activeObject = 0;
@@ -1499,7 +1508,7 @@ void Document::remObject(const char* sName)
/// Remove an object out of the document (internal)
void Document::_remObject(DocumentObject* pcObject)
{
- _checkTransaction();
+ _checkTransaction(pcObject);
std::map::iterator pos = d->objectMap.find(pcObject->getNameInDocument());
diff --git a/src/App/Document.h b/src/App/Document.h
index 3ab0cb639..f192244e8 100644
--- a/src/App/Document.h
+++ b/src/App/Document.h
@@ -293,7 +293,7 @@ protected:
DocumentObject* _copyObject(DocumentObject* obj, std::map&, bool recursive=false, bool keepdigitsatend=false);
/// checks if a valid transaction is open
- void _checkTransaction(void);
+ void _checkTransaction(DocumentObject* pcObject);
void breakDependency(DocumentObject* pcObject, bool clear);
std::vector readObjects(Base::XMLReader& reader);
void writeObjects(const std::vector&, Base::Writer &writer) const;
diff --git a/src/App/Transactions.cpp b/src/App/Transactions.cpp
index f61b97be9..d52376370 100644
--- a/src/App/Transactions.cpp
+++ b/src/App/Transactions.cpp
@@ -102,6 +102,12 @@ int Transaction::getPos(void) const
return iPos;
}
+bool Transaction::hasObject(DocumentObject *Obj) const
+{
+ std::map::const_iterator it;
+ it = _Objects.find(Obj);
+ return (it != _Objects.end());
+}
//**************************************************************************
// separator for other implemetation aspects
diff --git a/src/App/Transactions.h b/src/App/Transactions.h
index d9657ed3c..5c66fa6f2 100644
--- a/src/App/Transactions.h
+++ b/src/App/Transactions.h
@@ -93,6 +93,8 @@ public:
/// get the position in the transaction history
int getPos(void) const;
+ /// check if this object is used in a transaction
+ bool hasObject(DocumentObject *Obj) const;
friend class Document;
diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt
index 4b5a06170..fca1e2784 100644
--- a/src/Base/CMakeLists.txt
+++ b/src/Base/CMakeLists.txt
@@ -14,6 +14,7 @@ include_directories(
${XERCESC_INCLUDE_DIR}
${QT_QTCORE_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
+ ${PYCXX_INCLUDE_DIR}
)
if(MSVC)
@@ -62,6 +63,8 @@ generate_from_xml(MatrixPy)
generate_from_xml(RotationPy)
generate_from_xml(PlacementPy)
generate_from_xml(AxisPy)
+generate_from_xml(UnitPy)
+generate_from_xml(QuantityPy)
if(SWIG_FOUND)
execute_process(COMMAND ${SWIG_EXECUTABLE} -python -external-runtime ${CMAKE_CURRENT_BINARY_DIR}/swigpyrun.h)
@@ -124,20 +127,7 @@ SET(zipios_SRCS
SOURCE_GROUP("zipios" FILES ${zipios_SRCS})
endif ()
-SET(pycxx_SRCS
- ../CXX/Config.hxx
- ../CXX/cxxextensions.c
- ../CXX/cxx_extensions.cxx
- ../CXX/cxxsupport.cxx
- ../CXX/Exception.hxx
- ../CXX/Extensions.hxx
- ../CXX/IndirectPythonInterface.cxx
- ../CXX/IndirectPythonInterface.hxx
- ../CXX/Objects.hxx
- ../CXX/Version.hxx
- ../CXX/WrapPython.h
-)
-SOURCE_GROUP("pycxx" FILES ${pycxx_SRCS})
+SOURCE_GROUP("pycxx" FILES ${PYCXX_SOURCES})
SET(FreeCADBase_XML_SRCS
AxisPy.xml
@@ -148,6 +138,8 @@ SET(FreeCADBase_XML_SRCS
PlacementPy.xml
RotationPy.xml
VectorPy.xml
+ QuantityPy.xml
+ UnitPy.xml
)
SOURCE_GROUP("XML" FILES ${FreeCADBase_XML_SRCS})
@@ -171,6 +163,15 @@ SET(FreeCADBase_UNITAPI_SRCS
UnitsSchemaImperial1.cpp
UnitsApi.y
UnitsApi.l
+ Quantity.h
+ Quantity.cpp
+ QuantityPyImp.cpp
+ QuantityParser.l
+ QuantityParser.y
+ Unit.h
+ Unit.cpp
+ UnitPyImp.cpp
+
)
SOURCE_GROUP("Units" FILES ${FreeCADBase_UNITAPI_SRCS})
@@ -279,7 +280,7 @@ SET(FreeCADBase_HPP_SRCS
)
SET(FreeCADBase_SRCS
- ${pycxx_SRCS}
+ ${PYCXX_SOURCES}
${FreeCADBase_CPP_SRCS}
${FreeCADBase_HPP_SRCS}
${FreeCADBase_XML_SRCS}
diff --git a/src/Base/Console.cpp b/src/Base/Console.cpp
index 7c5c82535..197594364 100644
--- a/src/Base/Console.cpp
+++ b/src/Base/Console.cpp
@@ -133,6 +133,28 @@ ConsoleMsgFlags ConsoleSingleton::SetEnabledMsgType(const char* sObs, ConsoleMsg
}
}
+bool ConsoleSingleton::IsMsgTypeEnabled(const char* sObs, FreeCAD_ConsoleMsgType type) const
+{
+ ConsoleObserver* pObs = Get(sObs);
+ if (pObs) {
+ switch (type) {
+ case MsgType_Txt:
+ return pObs->bMsg;
+ case MsgType_Log:
+ return pObs->bLog;
+ case MsgType_Wrn:
+ return pObs->bWrn;
+ case MsgType_Err:
+ return pObs->bErr;
+ default:
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+}
+
/** Prints a Message
* This method issues a Message.
* Messages are used show some non vital information. That means in the
@@ -207,7 +229,7 @@ void ConsoleSingleton::Error( const char *pMsg, ... )
/** Prints a Message
* this method is more for devlopment and tracking purpos.
- * It can be used to track execution of algorithems and functions
+ * It can be used to track execution of algorithms and functions
* and put it in files. The normal user dont need to see it, its more
* for developers and experinced users. So in normal user modes the
* logging is switched of.
@@ -282,37 +304,40 @@ void ConsoleSingleton::DetachObserver(ConsoleObserver *pcObserver)
void ConsoleSingleton::NotifyMessage(const char *sMsg)
{
- for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
+ for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++) {
if((*Iter)->bMsg)
(*Iter)->Message(sMsg); // send string to the listener
+ }
}
void ConsoleSingleton::NotifyWarning(const char *sMsg)
{
- for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
+ for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++) {
if((*Iter)->bWrn)
(*Iter)->Warning(sMsg); // send string to the listener
+ }
}
void ConsoleSingleton::NotifyError(const char *sMsg)
{
- for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
+ for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++) {
if((*Iter)->bErr)
(*Iter)->Error(sMsg); // send string to the listener
+ }
}
void ConsoleSingleton::NotifyLog(const char *sMsg)
{
- for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
+ for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++) {
if((*Iter)->bLog)
(*Iter)->Log(sMsg); // send string to the listener
+ }
}
-ConsoleObserver *ConsoleSingleton::Get(const char *Name)
+ConsoleObserver *ConsoleSingleton::Get(const char *Name) const
{
const char* OName;
- for(std::set::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
- {
+ for(std::set::const_iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++) {
OName = (*Iter)->Name(); // get the name
if(OName && strcmp(OName,Name) == 0)
return *Iter;
@@ -539,13 +564,13 @@ PyObject *ConsoleSingleton::sPySetStatus(PyObject * /*self*/, PyObject *args, Py
if(pObs)
{
if(strcmp(pstr2,"Log") == 0)
- pObs->bLog = (Bool==0)?false:true;
+ pObs->bLog = (Bool==0)?false:true;
else if(strcmp(pstr2,"Wrn") == 0)
- pObs->bWrn = (Bool==0)?false:true;
+ pObs->bWrn = (Bool==0)?false:true;
else if(strcmp(pstr2,"Msg") == 0)
- pObs->bMsg = (Bool==0)?false:true;
+ pObs->bMsg = (Bool==0)?false:true;
else if(strcmp(pstr2,"Err") == 0)
- pObs->bErr = (Bool==0)?false:true;
+ pObs->bErr = (Bool==0)?false:true;
else
Py_Error(PyExc_Exception,"Unknown Message Type (use Log,Err,Msg or Wrn)");
diff --git a/src/Base/Console.h b/src/Base/Console.h
index b51183b13..8b2e04eac 100644
--- a/src/Base/Console.h
+++ b/src/Base/Console.h
@@ -56,7 +56,7 @@ class ConsoleSingleton;
typedef Base::ConsoleSingleton ConsoleMsgType;
typedef unsigned int ConsoleMsgFlags;
-
+
namespace Base {
/** The console observer class
@@ -141,12 +141,14 @@ public:
void UnsetMode(ConsoleMode m);
/// Enables or disables message types of a cetain console observer
ConsoleMsgFlags SetEnabledMsgType(const char* sObs, ConsoleMsgFlags type, bool b);
+ /// Enables or disables message types of a cetain console observer
+ bool IsMsgTypeEnabled(const char* sObs, FreeCAD_ConsoleMsgType type) const;
/// singleton
static ConsoleSingleton &Instance(void);
// retrieval of an observer by name
- ConsoleObserver *Get(const char *Name);
+ ConsoleObserver *Get(const char *Name) const;
static PyMethodDef Methods[];
diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp
index 548265d98..812b7c625 100644
--- a/src/Base/Interpreter.cpp
+++ b/src/Base/Interpreter.cpp
@@ -71,12 +71,16 @@ PyException::PyException(void)
_stackTrace = PP_last_error_trace; /* exception traceback text */
+
+ // This should be done in the constructor because when doing
+ // in the destructor it's not always clear when it is called
+ // and thus may clear a Python exception when it should not.
+ PyGILStateLocker locker;
+ PyErr_Clear(); // must be called to keep Python interpreter in a valid state (Werner)
}
PyException::~PyException() throw()
{
- PyGILStateLocker locker;
- PyErr_Clear(); // must be called to keep Python interpreter in a valid state (Werner)
}
void PyException::ReportException (void) const
diff --git a/src/Base/Matrix.cpp b/src/Base/Matrix.cpp
index 18072b6b0..65968afcc 100644
--- a/src/Base/Matrix.cpp
+++ b/src/Base/Matrix.cpp
@@ -23,8 +23,8 @@
#include "PreCompiled.h"
#ifndef _PreComp_
-# include
-# include
+# include
+# include
# include
#endif
@@ -80,6 +80,14 @@ void Matrix4D::setToUnity (void)
dMtrx4D[3][0] = 0.0; dMtrx4D[3][1] = 0.0; dMtrx4D[3][2] = 0.0; dMtrx4D[3][3] = 1.0;
}
+void Matrix4D::nullify(void)
+{
+ dMtrx4D[0][0] = 0.0; dMtrx4D[0][1] = 0.0; dMtrx4D[0][2] = 0.0; dMtrx4D[0][3] = 0.0;
+ dMtrx4D[1][0] = 0.0; dMtrx4D[1][1] = 0.0; dMtrx4D[1][2] = 0.0; dMtrx4D[1][3] = 0.0;
+ dMtrx4D[2][0] = 0.0; dMtrx4D[2][1] = 0.0; dMtrx4D[2][2] = 0.0; dMtrx4D[2][3] = 0.0;
+ dMtrx4D[3][0] = 0.0; dMtrx4D[3][1] = 0.0; dMtrx4D[3][2] = 0.0; dMtrx4D[3][3] = 0.0;
+}
+
double Matrix4D::determinant() const
{
double fA0 = dMtrx4D[0][0]*dMtrx4D[1][1] - dMtrx4D[0][1]*dMtrx4D[1][0];
@@ -701,8 +709,8 @@ void Matrix4D::fromString(const std::string &str)
input >> dMtrx4D[i][j];
}
}
-
-// Analyse the a transformation Matrix and describe the transformation
+
+// Analyse the a transformation Matrix and describe the transformation
std::string Matrix4D::analyse(void) const
{
const double eps=1.0e-06;
@@ -723,22 +731,22 @@ std::string Matrix4D::analyse(void) const
}
else //translation and affine
{
- if (dMtrx4D[0][1] == 0.0 && dMtrx4D[0][2] == 0.0 &&
- dMtrx4D[1][0] == 0.0 && dMtrx4D[1][2] == 0.0 &&
+ if (dMtrx4D[0][1] == 0.0 && dMtrx4D[0][2] == 0.0 &&
+ dMtrx4D[1][0] == 0.0 && dMtrx4D[1][2] == 0.0 &&
dMtrx4D[2][0] == 0.0 && dMtrx4D[2][1] == 0.0) //scaling
{
- std::ostringstream stringStream;
- stringStream << "Scale [" << dMtrx4D[0][0] << ", " <<
+ std::ostringstream stringStream;
+ stringStream << "Scale [" << dMtrx4D[0][0] << ", " <<
dMtrx4D[1][1] << ", " << dMtrx4D[2][2] << "]";
- text = stringStream.str();
+ text = stringStream.str();
}
else
{
Base::Matrix4D sub;
- sub[0][0] = dMtrx4D[0][0]; sub[0][1] = dMtrx4D[0][1];
- sub[0][2] = dMtrx4D[0][2]; sub[1][0] = dMtrx4D[1][0];
+ sub[0][0] = dMtrx4D[0][0]; sub[0][1] = dMtrx4D[0][1];
+ sub[0][2] = dMtrx4D[0][2]; sub[1][0] = dMtrx4D[1][0];
sub[1][1] = dMtrx4D[1][1]; sub[1][2] = dMtrx4D[1][2];
- sub[2][0] = dMtrx4D[2][0]; sub[2][1] = dMtrx4D[2][1];
+ sub[2][0] = dMtrx4D[2][0]; sub[2][1] = dMtrx4D[2][1];
sub[2][2] = dMtrx4D[2][2];
Base::Matrix4D trp = sub;
@@ -771,23 +779,23 @@ std::string Matrix4D::analyse(void) const
}
else //scaling with rotation
{
- std::ostringstream stringStream;
- stringStream << "Scale and Rotate ";
+ std::ostringstream stringStream;
+ stringStream << "Scale and Rotate ";
if (determinant<0.0 )
- stringStream << "and Invert ";
- stringStream << "[ " <<
- sqrt(trp[0][0]) << ", " << sqrt(trp[1][1]) << ", " <<
+ stringStream << "and Invert ";
+ stringStream << "[ " <<
+ sqrt(trp[0][0]) << ", " << sqrt(trp[1][1]) << ", " <<
sqrt(trp[2][2]) << "]";
- text = stringStream.str();
+ text = stringStream.str();
}
}
}
else
{
- std::ostringstream stringStream;
- stringStream << "Affine with det= " <<
+ std::ostringstream stringStream;
+ stringStream << "Affine with det= " <<
determinant;
- text = stringStream.str();
+ text = stringStream.str();
}
}
}
@@ -795,4 +803,4 @@ std::string Matrix4D::analyse(void) const
text += " with Translation";
}
return text;
-}
+}
diff --git a/src/Base/Matrix.h b/src/Base/Matrix.h
index 36444c667..f53019a4a 100644
--- a/src/Base/Matrix.h
+++ b/src/Base/Matrix.h
@@ -26,7 +26,7 @@
#include
#include
-#include
+#include
#include
#include "Vector3D.h"
@@ -104,7 +104,9 @@ public:
/** @name Manipulation */
//@{
/// Makes unity matrix
- void setToUnity (void);
+ void setToUnity(void);
+ /// Makes a null matrix
+ void nullify(void);
/// moves the coordinatesystem for the x,y,z value
void move (float x, float y, float z)
{ move(Vector3f(x,y,z)); }
diff --git a/src/Base/Parser.bat b/src/Base/Parser.bat
new file mode 100644
index 000000000..8d9394cf2
--- /dev/null
+++ b/src/Base/Parser.bat
@@ -0,0 +1,2 @@
+C:\Tools\GnuWin32\bin\flex.exe -oQuantityLexer.c QuantityParser.l
+C:\Tools\GnuWin32\bin\bison -oQuantityParser.c QuantityParser.y
\ No newline at end of file
diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp
new file mode 100644
index 000000000..29e6e4bfb
--- /dev/null
+++ b/src/Base/Quantity.cpp
@@ -0,0 +1,157 @@
+/***************************************************************************
+ * Copyright (c) 2013 Juergen Riegel *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+#include "PreCompiled.h"
+#ifndef _PreComp_
+#endif
+
+#include
+#include "Quantity.h"
+#include "Exception.h"
+
+using namespace Base;
+
+Quantity::Quantity()
+{
+ this->_Value = 0.0;
+}
+
+Quantity::Quantity(const Quantity& that)
+{
+ *this = that ;
+}
+
+Quantity::Quantity(double Value, const Unit& unit)
+{
+ this->_Unit = unit;
+ this->_Value = Value;
+}
+
+
+bool Quantity::operator ==(const Quantity& that) const
+{
+ return (this->_Value == that._Value) && (this->_Unit == that._Unit) ;
+}
+
+
+Quantity Quantity::operator *(const Quantity &p) const
+{
+ return Quantity(this->_Value * p._Value,this->_Unit * p._Unit);
+}
+Quantity Quantity::operator /(const Quantity &p) const
+{
+ return Quantity(this->_Value / p._Value,this->_Unit / p._Unit);
+}
+
+Quantity Quantity::pow(const Quantity &p) const
+{
+ if(!p._Unit.isEmpty())
+ throw Base::Exception("Quantity::pow(): exponent must not have a unit");
+ return Quantity(
+ std::pow(this->_Value, p._Value),
+ this->_Unit.pow((short)p._Value)
+ );
+}
+
+
+Quantity Quantity::operator +(const Quantity &p) const
+{
+ if(this->_Unit != p._Unit)
+ throw Base::Exception("Quantity::operator +(): Unit missmatch in plus operation");
+ return Quantity(this->_Value + p._Value,this->_Unit);
+}
+Quantity Quantity::operator -(const Quantity &p) const
+{
+ if(this->_Unit != p._Unit)
+ throw Base::Exception("Quantity::operator +(): Unit missmatch in plus operation");
+ return Quantity(this->_Value - p._Value,this->_Unit);
+}
+
+Quantity Quantity::operator -(void) const
+{
+ return Quantity(-(this->_Value),this->_Unit);
+}
+
+Quantity& Quantity::operator = (const Quantity &New)
+{
+ this->_Value = New._Value;
+ this->_Unit = New._Unit;
+ return *this;
+}
+
+// === Parser & Scanner stuff ===============================================
+
+// include the Scanner and the Parser for the Quantitys
+
+Quantity QuantResult;
+
+#ifndef DOUBLE_MAX
+# define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/
+#endif
+#ifndef DOUBLE_MIN
+# define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/
+#endif
+
+
+// error func
+void Quantity_yyerror(char *errorinfo)
+{
+ throw Base::Exception(errorinfo);
+}
+
+
+// for VC9 (isatty and fileno not supported anymore)
+//#ifdef _MSC_VER
+//int isatty (int i) {return _isatty(i);}
+//int fileno(FILE *stream) {return _fileno(stream);}
+//#endif
+
+namespace QuantityParser {
+
+// show the parser the lexer method
+#define yylex QuantityLexer
+int QuantityLexer(void);
+
+// Parser, defined in QuantityParser.y
+#include "QuantityParser.c"
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+// Scanner, defined in QuantityParser.l
+#include "QuantityLexer.c"
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+}
+
+Quantity Quantity::parse(const char* buffer)
+{
+ // parse from buffer
+ QuantityParser::YY_BUFFER_STATE my_string_buffer = QuantityParser::yy_scan_string (buffer);
+ // set the global return variables
+ QuantResult = Quantity(DOUBLE_MIN);
+ // run the parser
+ QuantityParser::yyparse ();
+ // free the scan buffer
+ QuantityParser::yy_delete_buffer (my_string_buffer);
+
+ if (QuantResult == Quantity(DOUBLE_MIN))
+ throw Base::Exception("Unknown error in Quantity expression");
+ return QuantResult;
+}
diff --git a/src/Base/Quantity.h b/src/Base/Quantity.h
new file mode 100644
index 000000000..8f5646cd9
--- /dev/null
+++ b/src/Base/Quantity.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * Copyright (c) 2013 Juergen Riegel *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+
+#ifndef BASE_Quantity_H
+#define BASE_Quantity_H
+
+#include "Unit.h"
+
+namespace Base {
+
+/**
+ * The Quantity class.
+ */
+class BaseExport Quantity
+{
+public:
+ /// default constructor
+ Quantity(void);
+ Quantity(const Quantity&);
+ Quantity(double Value, const Unit& unit=Unit());
+ /// Destruction
+ ~Quantity () {};
+
+ /** Operators. */
+ //@{
+ Quantity operator *(const Quantity &p) const;
+ Quantity operator +(const Quantity &p) const;
+ Quantity operator -(const Quantity &p) const;
+ Quantity operator -(void) const;
+ Quantity operator /(const Quantity &p) const;
+ bool operator ==(const Quantity&) const;
+ Quantity& operator =(const Quantity&);
+ Quantity pow(const Quantity&)const;
+ //@}
+
+protected:
+ double _Value;
+ Unit _Unit;
+
+ static Quantity parse(const char* buffer);
+};
+
+} // namespace Base
+
+#endif // BASE_Quantity_H
diff --git a/src/Base/QuantityLexer.c b/src/Base/QuantityLexer.c
new file mode 100644
index 000000000..3ed01975a
--- /dev/null
+++ b/src/Base/QuantityLexer.c
@@ -0,0 +1,1743 @@
+#line 2 "QuantityLexer.c"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include
+#include
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 40
+#define YY_END_OF_BUFFER 41
+static yyconst short int yy_accept[63] =
+ { 0,
+ 0, 0, 41, 40, 1, 2, 10, 12, 3, 37,
+ 29, 30, 40, 40, 39, 40, 16, 28, 40, 40,
+ 35, 5, 40, 40, 40, 26, 18, 40, 2, 36,
+ 37, 31, 6, 0, 0, 7, 11, 0, 9, 15,
+ 8, 19, 17, 0, 34, 4, 0, 20, 38, 0,
+ 21, 13, 33, 14, 36, 22, 23, 25, 27, 32,
+ 24, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 4, 1, 1, 1, 1, 5, 6,
+ 6, 6, 6, 1, 6, 7, 6, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 1, 1, 1,
+ 6, 1, 1, 1, 9, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 10, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 6, 1, 1, 11, 12, 13, 14,
+
+ 15, 16, 17, 18, 19, 1, 20, 21, 22, 23,
+ 24, 25, 1, 26, 27, 28, 1, 1, 29, 1,
+ 30, 31, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[32] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1
+ } ;
+
+static yyconst short int yy_base[63] =
+ { 0,
+ 0, 0, 69, 70, 70, 65, 70, 70, 70, 25,
+ 70, 70, 20, 21, 70, 43, 42, 70, 42, 18,
+ 52, 33, 32, 43, 50, 32, 41, 18, 55, 48,
+ 30, 70, 70, 25, 34, 70, 70, 25, 70, 70,
+ 70, 70, 70, 24, 70, 70, 25, 70, 70, 31,
+ 70, 70, 70, 70, 33, 70, 70, 70, 70, 70,
+ 70, 70
+ } ;
+
+static yyconst short int yy_def[63] =
+ { 0,
+ 62, 1, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 0
+ } ;
+
+static yyconst short int yy_nxt[102] =
+ { 0,
+ 4, 5, 6, 7, 8, 9, 4, 10, 11, 12,
+ 4, 4, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 4, 23, 24, 25, 26, 27, 4, 28,
+ 4, 30, 31, 32, 40, 35, 30, 31, 53, 41,
+ 55, 33, 36, 54, 61, 60, 59, 58, 34, 43,
+ 57, 44, 56, 45, 46, 55, 47, 29, 52, 51,
+ 50, 49, 48, 42, 39, 38, 37, 29, 62, 3,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+
+ 62
+ } ;
+
+static yyconst short int yy_chk[102] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 10, 10, 13, 20, 14, 31, 31, 28, 20,
+ 55, 13, 14, 28, 50, 47, 44, 38, 13, 22,
+ 35, 22, 34, 22, 22, 30, 22, 29, 27, 26,
+ 25, 24, 23, 21, 19, 17, 16, 6, 3, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+
+ 62
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "QuantityParser.l"
+#define INITIAL 0
+#line 2 "QuantityParser.l"
+/* Lexer for the FreeCAD Units language */
+/* (c) 2013 Juergen Riegel LGPL */
+
+
+/* This disables inclusion of unistd.h, which is not available under Visual C++
+ * on Win32. The C++ scanner uses STL streams instead. */
+#define YY_NO_UNISTD_H
+
+/*** Flex Declarations and Options ***/
+/* the manual says "somewhat more optimized" */
+#define YY_NEVER_INTERACTIVE 1
+/* no support for include files is planned */
+#define YY_NO_UNPUT 1
+#line 424 "QuantityLexer.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 27 "QuantityParser.l"
+
+
+
+#line 579 "QuantityLexer.c"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 63 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 62 );
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 30 "QuantityParser.l"
+;
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 31 "QuantityParser.l"
+;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 33 "QuantityParser.l"
+{ return *yytext; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 35 "QuantityParser.l"
+yylval = 1.0; return UNIT; // millimeter (internal standard length)
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 36 "QuantityParser.l"
+yylval = 1000.0; return UNIT; // meter
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 37 "QuantityParser.l"
+yylval = 10.0; return UNIT; // centimeter
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 38 "QuantityParser.l"
+yylval = 100.0; return UNIT; // decimeter
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 39 "QuantityParser.l"
+yylval = 1000000.0; return UNIT; // kilometer
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 41 "QuantityParser.l"
+yylval = 25.4; return UNIT; // inch
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 42 "QuantityParser.l"
+yylval = 25.4; return UNIT; // inch
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 43 "QuantityParser.l"
+yylval = 304.8; return UNIT; // foot
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 44 "QuantityParser.l"
+yylval = 304.8; return UNIT; // foot
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 45 "QuantityParser.l"
+yylval = 0.0254; return UNIT; // thou
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 46 "QuantityParser.l"
+yylval = 914.4; return UNIT; // yard
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 48 "QuantityParser.l"
+yylval = 1.0; return UNIT; // kilogram (internal standard mass)
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 49 "QuantityParser.l"
+yylval = 0.001; return UNIT; // gram
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 50 "QuantityParser.l"
+yylval = 0.000001; return UNIT; // milligram
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 51 "QuantityParser.l"
+yylval = 1000.0; return UNIT; // ton
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 53 "QuantityParser.l"
+yylval = 0.45359237; return UNIT; // pound
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 54 "QuantityParser.l"
+yylval = 0.45359237; return UNIT; // ounce
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 55 "QuantityParser.l"
+yylval = 6.35029318; return UNIT; // Stone
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 56 "QuantityParser.l"
+yylval = 50.80234544;return UNIT; // hundredweights
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 58 "QuantityParser.l"
+yylval = 1.0; return UNIT; // degree (internal standard angle)
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 59 "QuantityParser.l"
+yylval = 180/M_PI; return UNIT; // radian
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 60 "QuantityParser.l"
+yylval = 360.0/400.0;return UNIT; // gon
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 62 "QuantityParser.l"
+yylval = 1.0; return UNIT; // second (internal standard time)
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 63 "QuantityParser.l"
+yylval = 60.0; return UNIT; // minute
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 64 "QuantityParser.l"
+yylval = 3600.0; return UNIT; // hour
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 66 "QuantityParser.l"
+yylval = 1.0; return UNIT; // Ampere (internal standard electric current)
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 67 "QuantityParser.l"
+yylval = 1.0; return UNIT; // Kelvin (internal standard thermodynamic temperature)
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 68 "QuantityParser.l"
+yylval = 1.0; return UNIT; // Candela (internal standard luminous intensity)
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 69 "QuantityParser.l"
+yylval = 1.0; return UNIT; // Mole (internal standard amount of substance)
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 71 "QuantityParser.l"
+yylval = 1.0; return UNIT; // microliter mm^3(derived standard volume)
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 72 "QuantityParser.l"
+yylval = 1000.0; return UNIT; // milliliter cm^3
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 73 "QuantityParser.l"
+yylval = 1000000.0; return UNIT; // Liter dm^3
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 78 "QuantityParser.l"
+{yylval = atof( yytext ); return NUM;}
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 79 "QuantityParser.l"
+{yylval = atof( yytext ); return NUM;}
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 81 "QuantityParser.l"
+{yylval = M_PI ; return NUM;} // constant pi
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 82 "QuantityParser.l"
+{yylval = M_E ; return NUM;} // constant e
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 86 "QuantityParser.l"
+ECHO;
+ YY_BREAK
+#line 858 "QuantityLexer.c"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 63 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 63 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 62);
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 86 "QuantityParser.l"
diff --git a/src/Base/QuantityParser.c b/src/Base/QuantityParser.c
new file mode 100644
index 000000000..0410baa6c
--- /dev/null
+++ b/src/Base/QuantityParser.c
@@ -0,0 +1,1615 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 6 "QuantityParser.y"
+
+ #define YYSTYPE Quantity
+ #define yyparse Quantity_yyparse
+ #define yyerror Quantity_yyerror
+
+
+/* Line 189 of yacc.c */
+#line 80 "QuantityParser.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ UNIT = 258,
+ NUM = 259,
+ NEG = 260
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 264 of yacc.c */
+#line 127 "QuantityParser.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 10
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 30
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 13
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 3
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 12
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 22
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 260
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 11, 12, 7, 6, 2, 5, 2, 8, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 10, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 9
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 5, 7, 9, 12, 16, 20, 24,
+ 28, 31, 35
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 14, 0, -1, 15, -1, 4, -1, 3, -1, 4,
+ 3, -1, 15, 6, 15, -1, 15, 5, 15, -1,
+ 15, 7, 15, -1, 15, 8, 15, -1, 5, 15,
+ -1, 15, 10, 4, -1, 11, 15, 12, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint8 yyrline[] =
+{
+ 0, 25, 25, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "UNIT", "NUM", "'-'", "'+'", "'*'",
+ "'/'", "NEG", "'^'", "'('", "')'", "$accept", "input", "exp", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 45, 43, 42, 47, 260,
+ 94, 40, 41
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 13, 14, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 1, 2, 3, 3, 3, 3,
+ 2, 3, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 4, 3, 0, 0, 0, 2, 5, 10, 0,
+ 1, 0, 0, 0, 0, 0, 12, 7, 6, 8,
+ 9, 11
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 5, 6
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -4
+static const yytype_int8 yypact[] =
+{
+ 1, -4, -1, 1, 1, 3, 16, -4, 7, 8,
+ -4, 1, 1, 1, 1, 15, -4, 20, 20, 7,
+ 7, -4
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -4, -4, -3
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 8, 9, 7, 10, 1, 2, 3, 0, 17, 18,
+ 19, 20, 4, 11, 12, 13, 14, 15, 15, 21,
+ 16, 11, 12, 13, 14, 0, 15, 13, 14, 0,
+ 15
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 3, 4, 3, 0, 3, 4, 5, -1, 11, 12,
+ 13, 14, 11, 5, 6, 7, 8, 10, 10, 4,
+ 12, 5, 6, 7, 8, -1, 10, 7, 8, -1,
+ 10
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 4, 5, 11, 14, 15, 3, 15, 15,
+ 0, 5, 6, 7, 8, 10, 12, 15, 15, 15,
+ 15, 4
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+
+/* Line 1455 of yacc.c */
+#line 25 "QuantityParser.y"
+ { QuantResult = (yyvsp[(1) - (1)]) ; ;}
+ break;
+
+ case 3:
+
+/* Line 1455 of yacc.c */
+#line 28 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (1)]); ;}
+ break;
+
+ case 4:
+
+/* Line 1455 of yacc.c */
+#line 29 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (1)]); ;}
+ break;
+
+ case 5:
+
+/* Line 1455 of yacc.c */
+#line 30 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (2)])*(yyvsp[(2) - (2)]); ;}
+ break;
+
+ case 6:
+
+/* Line 1455 of yacc.c */
+#line 31 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (3)]) + (yyvsp[(3) - (3)]); ;}
+ break;
+
+ case 7:
+
+/* Line 1455 of yacc.c */
+#line 32 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (3)]) - (yyvsp[(3) - (3)]); ;}
+ break;
+
+ case 8:
+
+/* Line 1455 of yacc.c */
+#line 33 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (3)]) * (yyvsp[(3) - (3)]); ;}
+ break;
+
+ case 9:
+
+/* Line 1455 of yacc.c */
+#line 34 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (3)]) / (yyvsp[(3) - (3)]); ;}
+ break;
+
+ case 10:
+
+/* Line 1455 of yacc.c */
+#line 35 "QuantityParser.y"
+ { (yyval) = -(yyvsp[(2) - (2)]); ;}
+ break;
+
+ case 11:
+
+/* Line 1455 of yacc.c */
+#line 36 "QuantityParser.y"
+ { (yyval) = (yyvsp[(1) - (3)]).pow((yyvsp[(3) - (3)])); ;}
+ break;
+
+ case 12:
+
+/* Line 1455 of yacc.c */
+#line 37 "QuantityParser.y"
+ { (yyval) = (yyvsp[(2) - (3)]); ;}
+ break;
+
+
+
+/* Line 1455 of yacc.c */
+#line 1402 "QuantityParser.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1675 of yacc.c */
+#line 41 "QuantityParser.y"
+
+
diff --git a/src/Base/QuantityParser.l b/src/Base/QuantityParser.l
new file mode 100644
index 000000000..07434bac3
--- /dev/null
+++ b/src/Base/QuantityParser.l
@@ -0,0 +1,85 @@
+%{
+/* Lexer for the FreeCAD Units language */
+/* (c) 2013 Juergen Riegel LGPL */
+
+
+/* This disables inclusion of unistd.h, which is not available under Visual C++
+ * on Win32. The C++ scanner uses STL streams instead. */
+#define YY_NO_UNISTD_H
+
+%}
+
+/*** Flex Declarations and Options ***/
+
+
+/* the manual says "somewhat more optimized" */
+%option batch
+%option never-interactive
+
+
+/* no support for include files is planned */
+%option noyywrap nounput
+
+DIGIT [0-9]
+ID [a-z][a-z0-9]*
+
+
+%% /*** Filter language Part ***/
+
+
+[ \t] ;
+[\n]+ ;
+
+[-+()=/*^] { return *yytext; }
+
+"mm" yylval = 1.0; return UNIT; // millimeter (internal standard length)
+"m" yylval = 1000.0; return UNIT; // meter
+"cm" yylval = 10.0; return UNIT; // centimeter
+"dm" yylval = 100.0; return UNIT; // decimeter
+"km" yylval = 1000000.0; return UNIT; // kilometer
+
+"in" yylval = 25.4; return UNIT; // inch
+"\"" yylval = 25.4; return UNIT; // inch
+"fo" yylval = 304.8; return UNIT; // foot
+"'" yylval = 304.8; return UNIT; // foot
+"th" yylval = 0.0254; return UNIT; // thou
+"yr" yylval = 914.4; return UNIT; // yard
+
+"kg" yylval = 1.0; return UNIT; // kilogram (internal standard mass)
+"g" yylval = 0.001; return UNIT; // gram
+"mg" yylval = 0.000001; return UNIT; // milligram
+"t" yylval = 1000.0; return UNIT; // ton
+
+"lb" yylval = 0.45359237; return UNIT; // pound
+"oz" yylval = 0.45359237; return UNIT; // ounce
+"st" yylval = 6.35029318; return UNIT; // Stone
+"cwt" yylval = 50.80234544;return UNIT; // hundredweights
+
+"deg" yylval = 1.0; return UNIT; // degree (internal standard angle)
+"rad" yylval = 180/M_PI; return UNIT; // radian
+"gon" yylval = 360.0/400.0;return UNIT; // gon
+
+"s" yylval = 1.0; return UNIT; // second (internal standard time)
+"min" yylval = 60.0; return UNIT; // minute
+"h" yylval = 3600.0; return UNIT; // hour
+
+"A" yylval = 1.0; return UNIT; // Ampere (internal standard electric current)
+"K" yylval = 1.0; return UNIT; // Kelvin (internal standard thermodynamic temperature)
+"cd" yylval = 1.0; return UNIT; // Candela (internal standard luminous intensity)
+"mol" yylval = 1.0; return UNIT; // Mole (internal standard amount of substance)
+
+"yl" yylval = 1.0; return UNIT; // microliter mm^3(derived standard volume)
+"ml" yylval = 1000.0; return UNIT; // milliliter cm^3
+"l" yylval = 1000000.0; return UNIT; // Liter dm^3
+
+
+
+
+{DIGIT}+"."{DIGIT}* {yylval = atof( yytext ); return NUM;}
+{DIGIT}+ {yylval = atof( yytext ); return NUM;}
+
+"pi" {yylval = M_PI ; return NUM;} // constant pi
+"e" {yylval = M_E ; return NUM;} // constant e
+
+
+
diff --git a/src/Base/QuantityParser.y b/src/Base/QuantityParser.y
new file mode 100644
index 000000000..5ab6b1723
--- /dev/null
+++ b/src/Base/QuantityParser.y
@@ -0,0 +1,41 @@
+/* Parser for the FreeCAD Units language */
+/* (c) 2013 Juergen Riegel LGPL */
+
+
+/* Represents the many different ways we can access our data */
+%{
+ #define YYSTYPE Quantity
+ #define yyparse Quantity_yyparse
+ #define yyerror Quantity_yyerror
+%}
+
+ /* Bison declarations. */
+ %token UNIT NUM
+ %left '-' '+'
+ %left '*' '/'
+ %left NEG /* negation--unary minus */
+ %right '^' /* exponentiation */
+
+
+
+%start input
+
+%%
+
+ input: exp { QuantResult = $1 ; }
+ ;
+
+ exp: NUM { $$ = $1; }
+ | UNIT { $$ = $1; }
+ | NUM UNIT { $$ = $1*$2; }
+ | exp '+' exp { $$ = $1 + $3; }
+ | exp '-' exp { $$ = $1 - $3; }
+ | exp '*' exp { $$ = $1 * $3; }
+ | exp '/' exp { $$ = $1 / $3; }
+ | '-' exp %prec NEG { $$ = -$2; }
+ | exp '^' NUM { $$ = $1.pow($3); }
+ | '(' exp ')' { $$ = $2; }
+;
+
+
+%%
diff --git a/src/Base/QuantityPy.xml b/src/Base/QuantityPy.xml
new file mode 100644
index 000000000..5f12089fe
--- /dev/null
+++ b/src/Base/QuantityPy.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+ Quantity
+defined by a value and a unit.
+
+The following constructors are supported:
+Quantity() -- empty constructor
+Quantity(Value) -- empty constructor
+Quantity(Value,Unit) -- empty constructor
+Quantity(Quantity) -- copy constructor
+Quantity(string) -- arbitrary mixture of numbers and chars defining a Quantity
+
+ Quantity
+
+
+
+
+ multiply two quantities
+
+
+
+
+
+ Vector to the Base position of the Quantity
+
+
+
+
+
+ Direction vector of the Quantity
+
+
+
+
+
diff --git a/src/Base/QuantityPyImp.cpp b/src/Base/QuantityPyImp.cpp
new file mode 100644
index 000000000..26240ce6d
--- /dev/null
+++ b/src/Base/QuantityPyImp.cpp
@@ -0,0 +1,73 @@
+
+#include "PreCompiled.h"
+
+#include "Base/Quantity.h"
+
+// inclusion of the generated files (generated out of QuantityPy.xml)
+#include "QuantityPy.h"
+#include "QuantityPy.cpp"
+
+using namespace Base;
+
+// returns a string which represents the object e.g. when printed in python
+std::string QuantityPy::representation(void) const
+{
+ return std::string("");
+}
+
+PyObject *QuantityPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
+{
+ // create a new instance of QuantityPy and the Twin object
+ return new QuantityPy(new Quantity);
+}
+
+// constructor method
+int QuantityPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
+{
+ return 0;
+}
+
+
+PyObject* QuantityPy::multiply(PyObject * /*args*/)
+{
+ PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented");
+ return 0;
+}
+
+
+
+
+
+Py::Float QuantityPy::getValue(void) const
+{
+ //return Py::Float();
+ throw Py::AttributeError("Not yet implemented");
+}
+
+void QuantityPy::setValue(Py::Float /*arg*/)
+{
+ throw Py::AttributeError("Not yet implemented");
+}
+
+Py::Object QuantityPy::getUnit(void) const
+{
+ //return Py::Object();
+ throw Py::AttributeError("Not yet implemented");
+}
+
+void QuantityPy::setUnit(Py::Object /*arg*/)
+{
+ throw Py::AttributeError("Not yet implemented");
+}
+
+PyObject *QuantityPy::getCustomAttributes(const char* /*attr*/) const
+{
+ return 0;
+}
+
+int QuantityPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
+{
+ return 0;
+}
+
+
diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp
new file mode 100644
index 000000000..cc2d37847
--- /dev/null
+++ b/src/Base/Unit.cpp
@@ -0,0 +1,151 @@
+/***************************************************************************
+ * Copyright (c) 2011 Juergen Riegel *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+#include "PreCompiled.h"
+#ifndef _PreComp_
+#endif
+
+#include "Unit.h"
+
+using namespace Base;
+
+
+Unit::Unit(int8_t Length,
+ int8_t Mass,
+ int8_t Time,
+ int8_t ElectricCurrent,
+ int8_t ThermodynamicTemperature,
+ int8_t AmountOfSubstance,
+ int8_t LuminoseIntensity,
+ int8_t Angle)
+{
+ Sig.Length = Length;
+ Sig.Mass = Mass;
+ Sig.Time = Time;
+ Sig.ElectricCurrent = ElectricCurrent;
+ Sig.ThermodynamicTemperature = ThermodynamicTemperature;
+ Sig.AmountOfSubstance = AmountOfSubstance;
+ Sig.LuminoseIntensity = LuminoseIntensity;
+ Sig.Angle = Angle;
+}
+
+
+Unit::Unit()
+{
+
+}
+
+Unit::Unit(const Unit& that)
+{
+ this->Sig = that.Sig;
+}
+
+Unit::Unit(const std::string& Pars)
+{
+
+}
+
+
+Unit Unit::pow(char exp)const
+{
+ Unit result;
+ result.Sig.Length = Sig.Length * exp;
+ result.Sig.Mass = Sig.Mass * exp;
+ result.Sig.Time = Sig.Time * exp;
+ result.Sig.ElectricCurrent = Sig.ElectricCurrent * exp;
+ result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature * exp;
+ result.Sig.AmountOfSubstance = Sig.AmountOfSubstance * exp;
+ result.Sig.LuminoseIntensity = Sig.LuminoseIntensity * exp;
+ result.Sig.Angle = Sig.Angle * exp;
+
+ return result;
+
+}
+
+bool Unit::isEmpty(void)const
+{
+ return (this->Sig.Length == 0)
+ && (this->Sig.Mass == 0)
+ && (this->Sig.Time == 0)
+ && (this->Sig.ElectricCurrent == 0)
+ && (this->Sig.ThermodynamicTemperature == 0)
+ && (this->Sig.AmountOfSubstance == 0)
+ && (this->Sig.LuminoseIntensity == 0)
+ && (this->Sig.Angle == 0);
+}
+
+bool Unit::operator ==(const Unit& that) const
+{
+ return (this->Sig.Length == that.Sig.Length)
+ && (this->Sig.Mass == that.Sig.Mass)
+ && (this->Sig.Time == that.Sig.Time)
+ && (this->Sig.ElectricCurrent == that.Sig.ElectricCurrent)
+ && (this->Sig.ThermodynamicTemperature == that.Sig.ThermodynamicTemperature)
+ && (this->Sig.AmountOfSubstance == that.Sig.AmountOfSubstance)
+ && (this->Sig.LuminoseIntensity == that.Sig.LuminoseIntensity)
+ && (this->Sig.Angle == that.Sig.Angle);
+}
+
+
+Unit Unit::operator *(const Unit &right) const
+{
+ Unit result;
+ result.Sig.Length = Sig.Length + right.Sig.Length;
+ result.Sig.Mass = Sig.Mass + right.Sig.Mass;
+ result.Sig.Time = Sig.Time + right.Sig.Time;
+ result.Sig.ElectricCurrent = Sig.ElectricCurrent + right.Sig.ElectricCurrent;
+ result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature + right.Sig.ThermodynamicTemperature;
+ result.Sig.AmountOfSubstance = Sig.AmountOfSubstance + right.Sig.AmountOfSubstance;
+ result.Sig.LuminoseIntensity = Sig.LuminoseIntensity + right.Sig.LuminoseIntensity;
+ result.Sig.Angle = Sig.Angle + right.Sig.Angle;
+
+ return result;
+}
+
+Unit Unit::operator /(const Unit &right) const
+{
+ Unit result;
+ result.Sig.Length = Sig.Length - right.Sig.Length;
+ result.Sig.Mass = Sig.Mass - right.Sig.Mass;
+ result.Sig.Time = Sig.Time - right.Sig.Time;
+ result.Sig.ElectricCurrent = Sig.ElectricCurrent - right.Sig.ElectricCurrent;
+ result.Sig.ThermodynamicTemperature = Sig.ThermodynamicTemperature - right.Sig.ThermodynamicTemperature;
+ result.Sig.AmountOfSubstance = Sig.AmountOfSubstance - right.Sig.AmountOfSubstance;
+ result.Sig.LuminoseIntensity = Sig.LuminoseIntensity - right.Sig.LuminoseIntensity;
+ result.Sig.Angle = Sig.Angle - right.Sig.Angle;
+
+ return result;
+}
+
+Unit& Unit::operator = (const Unit &New)
+{
+ Sig.Length = New.Sig.Length;
+ Sig.Mass = New.Sig.Mass ;
+ Sig.Time = New.Sig.Time ;
+ Sig.ElectricCurrent = New.Sig.ElectricCurrent ;
+ Sig.ThermodynamicTemperature = New.Sig.ThermodynamicTemperature;
+ Sig.AmountOfSubstance = New.Sig.AmountOfSubstance ;
+ Sig.LuminoseIntensity = New.Sig.LuminoseIntensity ;
+ Sig.Angle = New.Sig.Angle ;
+
+ return *this;
+}
\ No newline at end of file
diff --git a/src/Base/Unit.h b/src/Base/Unit.h
new file mode 100644
index 000000000..8c1f92701
--- /dev/null
+++ b/src/Base/Unit.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * Copyright (c) 2011 Juergen Riegel *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+
+#ifndef BASE_Unit_H
+#define BASE_Unit_H
+
+#ifdef _MSC_VER
+# include
+#else
+# include
+#endif
+#include
+
+namespace Base {
+
+
+struct UnitSignature{
+ int32_t Length:4;
+ int32_t Mass:4;
+ int32_t Time:4;
+ int32_t ElectricCurrent:4;
+ int32_t ThermodynamicTemperature:4;
+ int32_t AmountOfSubstance:4;
+ int32_t LuminoseIntensity:4;
+ int32_t Angle:4;
+};
+/**
+ * The Unit class.
+ */
+class BaseExport Unit
+{
+public:
+ /// default constructor
+ Unit(int8_t Length,int8_t Mass=0,int8_t Time=0,int8_t ElectricCurrent=0,int8_t ThermodynamicTemperature=0,int8_t AmountOfSubstance=0,int8_t LuminoseIntensity=0,int8_t Angle=0);
+ Unit(void);
+ Unit(const Unit&);
+ Unit(const std::string& Pars);
+ /// Destruction
+ ~Unit () {};
+
+
+ /** Operators. */
+ //@{
+ inline Unit& operator *=(const Unit& that);
+ inline Unit& operator /=(const Unit& that);
+ Unit operator *(const Unit&) const;
+ Unit operator /(const Unit&) const;
+ bool operator ==(const Unit&) const;
+ bool operator !=(const Unit&that) const {return !(*this == that);}
+ Unit& operator =(const Unit&);
+ Unit pow(char exp)const;
+ //@}
+
+ bool isEmpty(void)const;
+ char getLengthDimension(void){return Sig.Length;}
+
+protected:
+ UnitSignature Sig;
+};
+
+inline Unit& Unit::operator *=(const Unit& that)
+{
+ *this = *this * that;
+ return *this;
+}
+
+inline Unit& Unit::operator /=(const Unit& that)
+{
+ *this = *this / that;
+ return *this;
+}
+
+} // namespace Base
+
+#endif // BASE_Unit_H
diff --git a/src/Base/UnitPy.xml b/src/Base/UnitPy.xml
new file mode 100644
index 000000000..5ba7fcc65
--- /dev/null
+++ b/src/Base/UnitPy.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+ Unit
+defines a unit type and calculate and compare.
+
+The following constructors are supported:
+Unit() -- empty constructor
+Unit(Unit) -- copy constructor
+Unit(string) -- parse the string for units
+
+ Unit
+
+
+
+
+ multiply(Placement)
+ Multiply this axis with a placement
+
+
+
+
+
+
+ get the type of the unit as string
+
+
+
+
+
+ get the dimension as a vector with 8 fields
+
+
+
+
+
diff --git a/src/Base/UnitPyImp.cpp b/src/Base/UnitPyImp.cpp
new file mode 100644
index 000000000..aaabc2cf8
--- /dev/null
+++ b/src/Base/UnitPyImp.cpp
@@ -0,0 +1,68 @@
+
+#include "PreCompiled.h"
+
+#include "Base/Unit.h"
+
+// inclusion of the generated files (generated out of UnitPy.xml)
+#include "UnitPy.h"
+#include "UnitPy.cpp"
+
+using namespace Base;
+
+// returns a string which represents the object e.g. when printed in python
+std::string UnitPy::representation(void) const
+{
+ return std::string("");
+}
+
+PyObject *UnitPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
+{
+ // create a new instance of UnitPy and the Twin object
+ return new UnitPy(new Unit);
+}
+
+// constructor method
+int UnitPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
+{
+ return 0;
+}
+
+
+PyObject* UnitPy::multiply(PyObject * /*args*/)
+{
+ PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented");
+ return 0;
+}
+
+PyObject* UnitPy::getType(PyObject * /*args*/)
+{
+ PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented");
+ return 0;
+}
+
+
+
+
+
+Py::Object UnitPy::getDimensions(void) const
+{
+ //return Py::Object();
+ throw Py::AttributeError("Not yet implemented");
+}
+
+void UnitPy::setDimensions(Py::Object /*arg*/)
+{
+ throw Py::AttributeError("Not yet implemented");
+}
+
+PyObject *UnitPy::getCustomAttributes(const char* /*attr*/) const
+{
+ return 0;
+}
+
+int UnitPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
+{
+ return 0;
+}
+
+
diff --git a/src/Base/VectorPy.xml b/src/Base/VectorPy.xml
index 6286e4b27..2549c5bfb 100644
--- a/src/Base/VectorPy.xml
+++ b/src/Base/VectorPy.xml
@@ -32,6 +32,13 @@
+
+
+ negative()
+ returns the negative (opposite) of this vector
+
+
+
scale(Float,Float,Float)
@@ -88,6 +95,14 @@
+
+
+
+ distanceToPoint(Vector)
+ returns the distance to another point
+
+
+
distanceToLine(Vector,Vector)
diff --git a/src/Base/VectorPyImp.cpp b/src/Base/VectorPyImp.cpp
index 4a1bae849..c86902c68 100644
--- a/src/Base/VectorPyImp.cpp
+++ b/src/Base/VectorPyImp.cpp
@@ -215,6 +215,16 @@ PyObject* VectorPy::sub(PyObject *args)
return new VectorPy(v);
}
+PyObject* VectorPy::negative(PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return 0;
+
+ VectorPy::PointerType this_ptr = reinterpret_cast(_pcTwinPointer);
+ Base::Vector3d v = -(*this_ptr);
+ return new VectorPy(v);
+}
+
PyObject* VectorPy::richCompare(PyObject *v, PyObject *w, int op)
{
if (PyObject_TypeCheck(v, &(VectorPy::Type)) &&
@@ -380,6 +390,20 @@ PyObject* VectorPy::projectToPlane(PyObject *args)
return Py::new_reference_to(this);
}
+PyObject* VectorPy::distanceToPoint(PyObject *args)
+{
+ PyObject *pnt;
+ if (!PyArg_ParseTuple(args, "O!",&(VectorPy::Type),&pnt))
+ return 0;
+
+ VectorPy* base_vec = static_cast(pnt);
+ VectorPy::PointerType this_ptr = reinterpret_cast(_pcTwinPointer);
+ VectorPy::PointerType base_ptr = reinterpret_cast(base_vec->_pcTwinPointer);
+
+ Py::Float dist(Base::Distance(*this_ptr, *base_ptr));
+ return Py::new_reference_to(dist);
+}
+
PyObject* VectorPy::distanceToLine(PyObject *args)
{
PyObject *base, *line;
diff --git a/src/Doc/sphinx/Document.rst b/src/Doc/sphinx/Document.rst
index 2b8a9d365..86f096883 100644
--- a/src/Doc/sphinx/Document.rst
+++ b/src/Doc/sphinx/Document.rst
@@ -1,9 +1,12 @@
The FreeCAD Document
====================
+.. currentmodule:: FreeCAD
+
.. toctree::
:maxdepth: 4
-.. automodule:: DocumentObject
+.. autoclass:: ActiveDocument
+ :members:
diff --git a/src/Doc/sphinx/_static/favicon.ico b/src/Doc/sphinx/_static/favicon.ico
new file mode 100644
index 000000000..dcefbc956
Binary files /dev/null and b/src/Doc/sphinx/_static/favicon.ico differ
diff --git a/src/Doc/sphinx/_static/freecad.css b/src/Doc/sphinx/_static/freecad.css
index 4f78bb38e..f7a7e94a7 100644
--- a/src/Doc/sphinx/_static/freecad.css
+++ b/src/Doc/sphinx/_static/freecad.css
@@ -1,5 +1,7 @@
/* FreeCAD sphinx CSS file */
+@import url("/freecad.css");
+
body {
background: #191b26;
background-attachment: fixed;
@@ -31,12 +33,8 @@ a.headerlink {
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;
+ letter-spacing: 1px;
+ border-bottom: 1px solid #888;
}
h2 {
@@ -44,6 +42,10 @@ h2 {
margin: 30px 0 0 0;
}
+ul {
+ margin: 0px 0px 0px;
+}
+
.document {
background-color: #eee;
display: table;
@@ -86,6 +88,11 @@ h2 {
padding: 10px;
}
+.footer {
+ background: transparent;
+ color: #aaa;
+}
+
@media print {
.document {
diff --git a/src/Doc/sphinx/conf.py b/src/Doc/sphinx/conf.py
index 52c32f05d..6146780a8 100644
--- a/src/Doc/sphinx/conf.py
+++ b/src/Doc/sphinx/conf.py
@@ -60,6 +60,7 @@ if commands.getstatusoutput("locate TemplatePyMod")[0] == 0:
import FreeCAD, FreeCADGui
FreeCADGui.showMainWindow() # this is needed for complete import of GUI modules
+doc = FreeCAD.newDocument("doc")
# -- General configuration -----------------------------------------------------
@@ -84,16 +85,16 @@ master_doc = 'index'
# General information about the project.
project = u'FreeCAD'
-copyright = u'2011, Jürgen Riegel, Werner Mayer, Yorik van Havre'
+copyright = u'2013, Jürgen Riegel, Werner Mayer, Yorik van Havre'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '0.13'
+version = '0.14'
# The full version, including alpha/beta/rc tags.
-release = '0.13'
+release = '0.14'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -160,7 +161,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 = "favicon.ico"
# 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,
diff --git a/src/Gui/CommandStd.cpp b/src/Gui/CommandStd.cpp
index 4bb0148a2..5ba4beddd 100644
--- a/src/Gui/CommandStd.cpp
+++ b/src/Gui/CommandStd.cpp
@@ -277,7 +277,7 @@ StdCmdWhatsThis::StdCmdWhatsThis()
sToolTipText = QT_TR_NOOP("What's This");
sWhatsThis = "Std_WhatsThis";
sStatusTip = QT_TR_NOOP("What's This");
- sAccel = keySequenceToAccel(QKeySequence::WhatsThis);
+ sAccel = keySequenceToAccel(QKeySequence::WhatsThis);
sPixmap = "WhatsThis";
eType = 0;
}
@@ -421,7 +421,7 @@ StdCmdOnlineHelp::StdCmdOnlineHelp()
sWhatsThis = "Std_OnlineHelp";
sStatusTip = QT_TR_NOOP("Help");
sPixmap = "help-browser";
- sAccel = keySequenceToAccel(QKeySequence::HelpContents);
+ sAccel = keySequenceToAccel(QKeySequence::HelpContents);
eType = 0;
}
@@ -449,9 +449,9 @@ StdCmdOnlineHelpWebsite::StdCmdOnlineHelpWebsite()
void StdCmdOnlineHelpWebsite::activated(int iMsg)
{
- ParameterGrp::handle hURLGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/OnlineHelp");
- std::string url = hURLGrp->GetASCII("DownloadURL", "http://apps.sourceforge.net/mediawiki/free-cad/index.php?title=Online_Help_Toc");
- OpenURLInBrowser(url.c_str());
+ ParameterGrp::handle hURLGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/OnlineHelp");
+ std::string url = hURLGrp->GetASCII("DownloadURL", "http://www.freecadweb.org/wiki/index.php?title=Online_Help_Toc");
+ OpenURLInBrowser(url.c_str());
}
//===========================================================================
@@ -468,12 +468,105 @@ StdCmdFreeCADWebsite::StdCmdFreeCADWebsite()
sToolTipText = QT_TR_NOOP("The FreeCAD website");
sWhatsThis = "Std_FreeCADWebsite";
sStatusTip = QT_TR_NOOP("FreeCAD Website");
+ sPixmap = "internet-web-browser";
eType = 0;
}
void StdCmdFreeCADWebsite::activated(int iMsg)
{
- OpenURLInBrowser("http://apps.sourceforge.net/mediawiki/free-cad/index.php?title=Main_Page");
+ OpenURLInBrowser("http://www.freecadweb.org");
+}
+
+//===========================================================================
+// Std_FreeCADUserHub
+//===========================================================================
+
+DEF_STD_CMD(StdCmdFreeCADUserHub);
+
+StdCmdFreeCADUserHub::StdCmdFreeCADUserHub()
+ :Command("Std_FreeCADUserHub")
+{
+ sGroup = QT_TR_NOOP("Help");
+ sMenuText = QT_TR_NOOP("Users documentation");
+ sToolTipText = QT_TR_NOOP("Documentation for users on the FreeCAD website");
+ sWhatsThis = "Std_FreeCADUserHub";
+ sStatusTip = QT_TR_NOOP("Users documentation");
+ sPixmap = "internet-web-browser";
+ eType = 0;
+}
+
+void StdCmdFreeCADUserHub::activated(int iMsg)
+{
+ OpenURLInBrowser("http://www.freecadweb.org/wiki/index.php?title=User_hub");
+}
+
+//===========================================================================
+// Std_FreeCADPowerUserHub
+//===========================================================================
+
+DEF_STD_CMD(StdCmdFreeCADPowerUserHub);
+
+StdCmdFreeCADPowerUserHub::StdCmdFreeCADPowerUserHub()
+ :Command("Std_FreeCADPowerUserHub")
+{
+ sGroup = QT_TR_NOOP("Help");
+ sMenuText = QT_TR_NOOP("Python scripting documentation");
+ sToolTipText = QT_TR_NOOP("Python scripting documentation on the FreeCAD website");
+ sWhatsThis = "Std_FreeCADPowerUserHub";
+ sStatusTip = QT_TR_NOOP("PowerUsers documentation");
+ sPixmap = "internet-web-browser";
+ eType = 0;
+}
+
+void StdCmdFreeCADPowerUserHub::activated(int iMsg)
+{
+ OpenURLInBrowser("http://www.freecadweb.org/wiki/index.php?title=Power_users_hub");
+}
+
+//===========================================================================
+// Std_FreeCADForum
+//===========================================================================
+
+DEF_STD_CMD(StdCmdFreeCADForum);
+
+StdCmdFreeCADForum::StdCmdFreeCADForum()
+ :Command("Std_FreeCADForum")
+{
+ sGroup = QT_TR_NOOP("Help");
+ sMenuText = QT_TR_NOOP("FreeCAD Forum");
+ sToolTipText = QT_TR_NOOP("The FreeCAD forum, where you can find help from other users");
+ sWhatsThis = "Std_FreeCADForum";
+ sStatusTip = QT_TR_NOOP("The FreeCAD Forum");
+ sPixmap = "internet-web-browser";
+ eType = 0;
+}
+
+void StdCmdFreeCADForum::activated(int iMsg)
+{
+ OpenURLInBrowser("http://sourceforge.net/apps/phpbb/free-cad");
+}
+
+//===========================================================================
+// Std_FreeCADFAQ
+//===========================================================================
+
+DEF_STD_CMD(StdCmdFreeCADFAQ);
+
+StdCmdFreeCADFAQ::StdCmdFreeCADFAQ()
+ :Command("Std_FreeCADFAQ")
+{
+ sGroup = QT_TR_NOOP("Help");
+ sMenuText = QT_TR_NOOP("FreeCAD FAQ");
+ sToolTipText = QT_TR_NOOP("Frequently Asked Questions on the FreeCAD website");
+ sWhatsThis = "Std_FreeCADFAQ";
+ sStatusTip = QT_TR_NOOP("Frequently Asked Questions");
+ sPixmap = "internet-web-browser";
+ eType = 0;
+}
+
+void StdCmdFreeCADFAQ::activated(int iMsg)
+{
+ OpenURLInBrowser("http://www.freecadweb.org/wiki/index.php?title=FAQ");
}
//===========================================================================
@@ -490,13 +583,13 @@ StdCmdPythonWebsite::StdCmdPythonWebsite()
sToolTipText = QT_TR_NOOP("The official Python website");
sWhatsThis = "Std_PythonWebsite";
sStatusTip = QT_TR_NOOP("Python Website");
- sPixmap = "python";
+ sPixmap = "applications-python";
eType = 0;
}
void StdCmdPythonWebsite::activated(int iMsg)
{
- OpenURLInBrowser("http://python.org");
+ OpenURLInBrowser("http://python.org");
}
//===========================================================================
@@ -575,6 +668,10 @@ void CreateStdCommands(void)
rcCmdMgr.addCommand(new StdCmdOnlineHelp());
rcCmdMgr.addCommand(new StdCmdOnlineHelpWebsite());
rcCmdMgr.addCommand(new StdCmdFreeCADWebsite());
+ rcCmdMgr.addCommand(new StdCmdFreeCADUserHub());
+ rcCmdMgr.addCommand(new StdCmdFreeCADPowerUserHub());
+ rcCmdMgr.addCommand(new StdCmdFreeCADForum());
+ rcCmdMgr.addCommand(new StdCmdFreeCADFAQ());
rcCmdMgr.addCommand(new StdCmdPythonWebsite());
//rcCmdMgr.addCommand(new StdCmdMeasurementSimple());
//rcCmdMgr.addCommand(new StdCmdDownloadOnlineHelp());
diff --git a/src/Gui/DlgProjectInformation.ui b/src/Gui/DlgProjectInformation.ui
index f080e6233..df33f5517 100644
--- a/src/Gui/DlgProjectInformation.ui
+++ b/src/Gui/DlgProjectInformation.ui
@@ -1,10 +1,8 @@
-
-
-
-
+
+
Gui::Dialog::DlgProjectInformation
-
-
+
+
0
0
@@ -12,220 +10,148 @@
540
-
+
Project information
-
+
true
-
+
true
-
-
+
+
9
-
+
6
- -
-
-
+
-
+
+
Information
-
-
+
+
9
-
+
6
-
-
-
-
- &Name:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- lineEditName
-
-
-
- -
-
-
-
- 0
- 25
-
-
-
- true
-
-
-
- -
-
-
- Path:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 0
- 25
-
-
-
- true
-
-
-
- -
-
-
- UUID:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 0
- 25
-
-
-
- true
-
-
-
- -
-
-
- Created &by:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- lineEditCreator
-
-
-
- -
-
-
-
- 0
- 25
-
-
-
-
- -
-
-
- Creation &date:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- lineEditDate
-
-
-
- -
-
-
-
- 0
- 25
-
-
-
- true
-
-
-
- -
-
-
- &Last modified by:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- lineEditLastMod
-
-
-
- -
-
-
-
- 0
- 25
-
-
-
-
- -
-
-
+
-
+
+
Last &modification date:
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
+
lineEditLastModDate
- -
-
-
+
-
+
+
+ &Name:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ lineEditName
+
+
+
+ -
+
+
0
25
-
+
true
- -
-
-
- Com&pany:
+
-
+
+
+ Commen&t:
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
- lineEditCompany
+
+ textEditComment
- -
-
-
+
-
+
+
+ Path:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 0
+ 25
+
+
+
+ true
+
+
+
+ -
+
+
+ UUID:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 0
+ 25
+
+
+
+ true
+
+
+
+ -
+
+
+ Created &by:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ lineEditCreator
+
+
+
+ -
+
+
0
25
@@ -233,31 +159,103 @@
- -
-
-
- Commen&t:
+
-
+
+
+ Creation &date:
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
- textEditComment
+
+ lineEditDate
- -
-
+
-
+
+
+
+ 0
+ 25
+
+
+
+ true
+
+
- -
+
-
+
+
+ &Last modified by:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ lineEditLastMod
+
+
+
+ -
+
+
+
+ 0
+ 25
+
+
+
+
+ -
+
+
+
+ 0
+ 25
+
+
+
+ true
+
+
+
+ -
+
+
+ Com&pany:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ lineEditCompany
+
+
+
+ -
+
+
+
+ 0
+ 25
+
+
+
+
+ -
+
+
+ -
-
+
Qt::Vertical
-
+
QSizePolicy::Expanding
-
+
91
240
@@ -265,26 +263,63 @@
+ -
+
+
+ License information:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ License URL
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ -
+
+
+ Open in browser
+
+
+
+
+
- -
-
-
- 0
-
-
+
-
+
+
6
+
+ 0
+
-
-
+
Qt::Horizontal
-
+
QSizePolicy::Expanding
-
+
20
20
@@ -293,30 +328,30 @@
-
-
-
+
+
&OK
-
+
-
+
true
-
+
true
-
-
-
+
+
&Cancel
-
+
-
+
true
@@ -325,9 +360,7 @@
-
-
-
+
@@ -336,11 +369,11 @@
Gui::Dialog::DlgProjectInformation
accept()
-
+
20
20
-
+
20
20
@@ -352,11 +385,11 @@
Gui::Dialog::DlgProjectInformation
reject()
-
+
20
20
-
+
20
20
diff --git a/src/Gui/DlgProjectInformationImp.cpp b/src/Gui/DlgProjectInformationImp.cpp
index c5f878693..fd58c674d 100644
--- a/src/Gui/DlgProjectInformationImp.cpp
+++ b/src/Gui/DlgProjectInformationImp.cpp
@@ -28,6 +28,8 @@
#include "DlgProjectInformationImp.h"
#include "Document.h"
+#include
+#include
using namespace Gui::Dialog;
@@ -52,6 +54,8 @@ DlgProjectInformationImp::DlgProjectInformationImp( App::Document* doc, QWidget*
lineEditLastMod->setText(QString::fromUtf8(doc->LastModifiedBy.getValue()));
lineEditLastModDate->setText(QString::fromUtf8(doc->LastModifiedDate.getValue()));
lineEditCompany->setText(QString::fromUtf8(doc->Company.getValue()));
+ lineEditLicense->setText(QString::fromUtf8(doc->License.getValue()));
+ lineEditLicenseURL->setText(QString::fromUtf8(doc->LicenseURL.getValue()));
// When saving the text to XML the newlines get lost. So we store also the newlines as '\n'.
// See also accept().
@@ -59,6 +63,7 @@ DlgProjectInformationImp::DlgProjectInformationImp( App::Document* doc, QWidget*
QStringList lines = comment.split(QLatin1String("\\n"), QString::KeepEmptyParts);
QString text = lines.join(QLatin1String("\n"));
textEditComment->setPlainText( text );
+ connect(pushButtonOpenURL, SIGNAL(clicked()),this, SLOT(open_url()));
}
/**
@@ -77,6 +82,8 @@ void DlgProjectInformationImp::accept()
_doc->CreatedBy.setValue(lineEditCreator->text().toUtf8());
_doc->LastModifiedBy.setValue(lineEditCreator->text().toUtf8());
_doc->Company.setValue(lineEditCompany->text().toUtf8());
+ _doc->License.setValue(lineEditLicense->text().toUtf8());
+ _doc->LicenseURL.setValue(lineEditLicenseURL->text().toUtf8());
// Replace newline escape sequence trough '\\n' string
QStringList lines = textEditComment->toPlainText().split
@@ -87,3 +94,11 @@ void DlgProjectInformationImp::accept()
QDialog::accept();
}
+/**
+ * Opens the text in the LicenseURL property in external browser.
+ */
+void DlgProjectInformationImp::open_url()
+{
+ QString url = QString::fromUtf8(_doc->LicenseURL.getValue());
+ QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
+}
diff --git a/src/Gui/DlgProjectInformationImp.h b/src/Gui/DlgProjectInformationImp.h
index e7f3b7903..cda120e7c 100644
--- a/src/Gui/DlgProjectInformationImp.h
+++ b/src/Gui/DlgProjectInformationImp.h
@@ -42,6 +42,7 @@ public:
protected:
void accept();
+ void open_url();
App::Document* _doc;
};
diff --git a/src/Gui/DlgSettingsMacroImp.cpp b/src/Gui/DlgSettingsMacroImp.cpp
index ce79fba28..afc9fb7e3 100644
--- a/src/Gui/DlgSettingsMacroImp.cpp
+++ b/src/Gui/DlgSettingsMacroImp.cpp
@@ -39,8 +39,8 @@ DlgSettingsMacroImp::DlgSettingsMacroImp( QWidget* parent )
{
this->setupUi(this);
if (MacroPath->fileName().isEmpty()) {
- QDir d(QString::fromUtf8(App::GetApplication().GetHomePath()));
- MacroPath->setFileName( d.path() );
+ QDir d(QString::fromUtf8(App::GetApplication().getUserAppDataDir().c_str()));
+ MacroPath->setFileName(d.path());
}
}
diff --git a/src/Gui/DlgSettingsViewColor.cpp b/src/Gui/DlgSettingsViewColor.cpp
index bf8f3e216..28fcee439 100644
--- a/src/Gui/DlgSettingsViewColor.cpp
+++ b/src/Gui/DlgSettingsViewColor.cpp
@@ -66,15 +66,6 @@ void DlgSettingsViewColor::saveSettings()
checkBoxSelection->onSave();
HighlightColor->onSave();
SelectionColor->onSave();
- CursorTextColor->onSave();
- EditedEdgeColor->onSave();
- EditedVertexColor->onSave();
- ConstructionColor->onSave();
- FullyConstrainedColor->onSave();
- BoundingBoxColor->onSave();
- DefaultShapeColor->onSave();
- DefaultShapeLineColor->onSave();
- DefaultShapeLineWidth->onSave();
}
void DlgSettingsViewColor::loadSettings()
@@ -90,15 +81,6 @@ void DlgSettingsViewColor::loadSettings()
checkBoxSelection->onRestore();
HighlightColor->onRestore();
SelectionColor->onRestore();
- CursorTextColor->onRestore();
- EditedEdgeColor->onRestore();
- EditedVertexColor->onRestore();
- ConstructionColor->onRestore();
- FullyConstrainedColor->onRestore();
- BoundingBoxColor->onRestore();
- DefaultShapeColor->onRestore();
- DefaultShapeLineColor->onRestore();
- DefaultShapeLineWidth->onRestore();
}
/**
diff --git a/src/Gui/DlgSettingsViewColor.ui b/src/Gui/DlgSettingsViewColor.ui
index 8a7d92e6f..9b2f5301e 100644
--- a/src/Gui/DlgSettingsViewColor.ui
+++ b/src/Gui/DlgSettingsViewColor.ui
@@ -148,7 +148,7 @@
- -
+
-
Background color
@@ -342,7 +342,7 @@
- -
+
-
Qt::Vertical
@@ -355,296 +355,6 @@
- -
-
-
- Default colors
-
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- 0
-
-
- 6
-
-
-
-
-
-
- 240
- 0
-
-
-
- Edited edge color
-
-
-
- -
-
-
- Edited vertex color
-
-
-
- -
-
-
- Construction geometry
-
-
-
- -
-
-
- Fully constrained geometry
-
-
-
- -
-
-
- The color of construction geometry in edit mode
-
-
-
- 0
- 0
- 220
-
-
-
- ConstructionColor
-
-
- View
-
-
-
- -
-
-
- The color of fully constrained geometry in edit mode
-
-
-
- 0
- 255
- 0
-
-
-
- FullyConstrainedColor
-
-
- View
-
-
-
- -
-
-
- The color of vertices being edited
-
-
-
- 255
- 38
- 0
-
-
-
- EditedVertexColor
-
-
- View
-
-
-
- -
-
-
- The color of edges being edited
-
-
-
- 255
- 255
- 255
-
-
-
- EditedEdgeColor
-
-
- View
-
-
-
- -
-
-
- Cursor text color
-
-
-
- -
-
-
-
- 0
- 0
- 255
-
-
-
- CursorTextColor
-
-
- View
-
-
-
- -
-
-
- Bounding box color
-
-
-
- -
-
-
- The color of bounding boxes in the 3D view
-
-
-
- 255
- 255
- 255
-
-
-
- BoundingBoxColor
-
-
- View
-
-
-
-
-
- -
-
-
-
-
-
-
- 240
- 0
-
-
-
- Default shape color
-
-
-
- -
-
-
- The default color for new shapes
-
-
-
- 204
- 204
- 204
-
-
-
- DefaultShapeColor
-
-
- View
-
-
-
-
-
- -
-
-
-
-
-
-
- 182
- 0
-
-
-
- Default line width and color
-
-
-
- -
-
-
- The default line color for new shapes
-
-
-
- 25
- 25
- 25
-
-
-
- DefaultShapeLineColor
-
-
- View
-
-
-
- -
-
-
- The default line thickness for new shapes
-
-
- px
-
-
- 2
-
-
- DefaultShapeLineWidth
-
-
- View
-
-
-
-
-
-
-
-
@@ -653,11 +363,6 @@
QPushButton
-
- Gui::PrefSpinBox
- QSpinBox
-
-
Gui::PrefColorButton
Gui::ColorButton
@@ -679,15 +384,6 @@
checkBoxSelection
HighlightColor
SelectionColor
- DefaultShapeColor
- DefaultShapeLineWidth
- DefaultShapeLineColor
- CursorTextColor
- EditedEdgeColor
- EditedVertexColor
- ConstructionColor
- FullyConstrainedColor
- BoundingBoxColor
radioButtonSimple
SelectionColor_Background
radioButtonGradient
diff --git a/src/Gui/Icons/applications-python.svg b/src/Gui/Icons/applications-python.svg
new file mode 100644
index 000000000..d782f8dde
--- /dev/null
+++ b/src/Gui/Icons/applications-python.svg
@@ -0,0 +1,142 @@
+
+
+
+
diff --git a/src/Gui/Icons/internet-web-browser.svg b/src/Gui/Icons/internet-web-browser.svg
new file mode 100644
index 000000000..d2366a9dc
--- /dev/null
+++ b/src/Gui/Icons/internet-web-browser.svg
@@ -0,0 +1,982 @@
+
+
+
diff --git a/src/Gui/Icons/resource.qrc b/src/Gui/Icons/resource.qrc
index e27da77af..bb248ed5e 100644
--- a/src/Gui/Icons/resource.qrc
+++ b/src/Gui/Icons/resource.qrc
@@ -53,7 +53,9 @@
window-new.svg
camera-photo.svg
applications-accessories.svg
+ applications-python.svg
accessories-text-editor.svg
+ internet-web-browser.svg
view-unselectable.svg
view-refresh.svg
view-fullscreen.svg
diff --git a/src/Gui/OnlineDocumentation.cpp b/src/Gui/OnlineDocumentation.cpp
index 985b9c0d1..8f932b262 100644
--- a/src/Gui/OnlineDocumentation.cpp
+++ b/src/Gui/OnlineDocumentation.cpp
@@ -407,10 +407,11 @@ StdCmdPythonHelp::StdCmdPythonHelp()
: Command("Std_PythonHelp"), server(0)
{
sGroup = QT_TR_NOOP("Tools");
- sMenuText = QT_TR_NOOP("Python Modules");
- sToolTipText = QT_TR_NOOP("Opens a browser to show the Python modules");
- sWhatsThis = QT_TR_NOOP("Opens a browser to show the Python modules");
- sStatusTip = QT_TR_NOOP("Opens a browser to show the Python modules");
+ sMenuText = QT_TR_NOOP("Automatic python modules documentation");
+ sToolTipText = QT_TR_NOOP("Opens a browser to show the Python modules documentation");
+ sWhatsThis = QT_TR_NOOP("Opens a browser to show the Python modules documentation");
+ sStatusTip = QT_TR_NOOP("Opens a browser to show the Python modules documentation");
+ sPixmap = "applications-python";
}
StdCmdPythonHelp::~StdCmdPythonHelp()
diff --git a/src/Gui/TouchpadNavigationStyle.cpp b/src/Gui/TouchpadNavigationStyle.cpp
index a8552ac79..f7fecdb25 100644
--- a/src/Gui/TouchpadNavigationStyle.cpp
+++ b/src/Gui/TouchpadNavigationStyle.cpp
@@ -71,7 +71,7 @@ const char* TouchpadNavigationStyle::mouseButtons(ViewerMode mode)
case NavigationStyle::DRAGGING:
return QT_TR_NOOP("Press ALT button");
case NavigationStyle::ZOOMING:
- return QT_TR_NOOP("Press PgUp/PgDown button");
+ return QT_TR_NOOP("Press CTRL and SHIFT buttons");
default:
return "No description";
}
@@ -310,12 +310,12 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev)
newmode = NavigationStyle::PANNING;
break;
case ALTDOWN:
- case CTRLDOWN|SHIFTDOWN:
if (newmode != NavigationStyle::DRAGGING) {
saveCursorPosition(ev);
}
newmode = NavigationStyle::DRAGGING;
break;
+ case CTRLDOWN|SHIFTDOWN:
case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
newmode = NavigationStyle::ZOOMING;
break;
diff --git a/src/Gui/View3DInventor.cpp b/src/Gui/View3DInventor.cpp
index 72d31f318..30b13e21e 100644
--- a/src/Gui/View3DInventor.cpp
+++ b/src/Gui/View3DInventor.cpp
@@ -681,10 +681,14 @@ bool View3DInventor::onHasMsg(const char* pMsg) const
return true;
else if (strcmp("SaveAs",pMsg) == 0)
return true;
- else if (strcmp("Undo",pMsg) == 0)
- return getAppDocument() && getAppDocument()->getAvailableUndos() > 0;
- else if (strcmp("Redo",pMsg) == 0)
- return getAppDocument() && getAppDocument()->getAvailableRedos() > 0;
+ else if (strcmp("Undo",pMsg) == 0) {
+ App::Document* doc = getAppDocument();
+ return doc && doc->getAvailableUndos() > 0;
+ }
+ else if (strcmp("Redo",pMsg) == 0) {
+ App::Document* doc = getAppDocument();
+ return doc && doc->getAvailableRedos() > 0;
+ }
else if (strcmp("Print",pMsg) == 0)
return true;
else if (strcmp("PrintPreview",pMsg) == 0)
diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp
index f3580a814..13ee7d523 100644
--- a/src/Gui/Workbench.cpp
+++ b/src/Gui/Workbench.cpp
@@ -449,9 +449,9 @@ MenuItem* StdWorkbench::setupMenuBar() const
MenuItem* stdviews = new MenuItem;
stdviews->setCommand("Standard views");
*stdviews << "Std_ViewFitAll" << "Std_ViewFitSelection" << "Std_ViewAxo"
- << "Separator" << "Std_ViewFront" << "Std_ViewRight"
- << "Std_ViewTop" << "Separator" << "Std_ViewRear"
- << "Std_ViewLeft" << "Std_ViewBottom"
+ << "Separator" << "Std_ViewFront" << "Std_ViewTop"
+ << "Std_ViewRight" << "Separator" << "Std_ViewRear"
+ << "Std_ViewBottom" << "Std_ViewLeft"
<< "Separator" << "Std_ViewRotateLeft" << "Std_ViewRotateRight";
// stereo
@@ -514,15 +514,12 @@ MenuItem* StdWorkbench::setupMenuBar() const
sep->setCommand( "Separator" );
// Help
- MenuItem* helpWebsites = new MenuItem;
- helpWebsites->setCommand("&On-line help");
- *helpWebsites << "Std_OnlineHelpWebsite" << "Std_FreeCADWebsite" << "Std_PythonWebsite";
-
MenuItem* help = new MenuItem( menuBar );
help->setCommand("&Help");
- *help << "Std_OnlineHelp" << "Std_PythonHelp"
- << helpWebsites << "Separator" << "Std_About"
- << "Std_AboutQt" << "Separator" << "Std_WhatsThis";
+ *help << "Std_OnlineHelp" << "Std_FreeCADWebsite"
+ << "Std_FreeCADUserHub" << "Std_FreeCADPowerUserHub"
+ << "Std_PythonHelp" << "Std_FreeCADForum"
+ << "Std_FreeCADFAQ" << "Std_About" << "Std_WhatsThis";
return menuBar;
}
@@ -547,9 +544,9 @@ ToolBarItem* StdWorkbench::setupToolBars() const
// View
ToolBarItem* view = new ToolBarItem( root );
view->setCommand("View");
- *view << "Std_ViewFitAll" << "Separator" << "Std_ViewAxo" << "Separator" << "Std_ViewFront"
- << "Std_ViewRight" << "Std_ViewTop" << "Separator" << "Std_ViewRear" << "Std_ViewLeft"
- << "Std_ViewBottom" << "Separator" << "Std_MeasureDistance" ;
+ *view << "Std_ViewFitAll" << "Separator" << "Std_ViewAxo" << "Separator" << "Std_ViewFront"
+ << "Std_ViewTop" << "Std_ViewRight" << "Separator" << "Std_ViewRear" << "Std_ViewBottom"
+ << "Std_ViewLeft" << "Separator" << "Std_MeasureDistance" ;
return root;
}
diff --git a/src/Gui/propertyeditor/PropertyItemDelegate.cpp b/src/Gui/propertyeditor/PropertyItemDelegate.cpp
index 2b79de29c..f6ca91506 100644
--- a/src/Gui/propertyeditor/PropertyItemDelegate.cpp
+++ b/src/Gui/propertyeditor/PropertyItemDelegate.cpp
@@ -36,7 +36,7 @@ using namespace Gui::PropertyEditor;
PropertyItemDelegate::PropertyItemDelegate(QObject* parent)
- : QItemDelegate(parent)
+ : QItemDelegate(parent), pressed(false)
{
}
@@ -89,6 +89,16 @@ void PropertyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
painter->setPen(savedPen);
}
+bool PropertyItemDelegate::editorEvent (QEvent * event, QAbstractItemModel* model,
+ const QStyleOptionViewItem& option, const QModelIndex& index)
+{
+ if (event && event->type() == QEvent::MouseButtonPress)
+ this->pressed = true;
+ else
+ this->pressed = false;
+ return QItemDelegate::editorEvent(event, model, option, index);
+}
+
QWidget * PropertyItemDelegate::createEditor (QWidget * parent, const QStyleOptionViewItem & /*option*/,
const QModelIndex & index ) const
{
@@ -101,6 +111,9 @@ QWidget * PropertyItemDelegate::createEditor (QWidget * parent, const QStyleOpti
QWidget* editor = childItem->createEditor(parent, this, SLOT(valueChanged()));
if (editor && childItem->isReadOnly())
editor->setDisabled(true);
+ else if (editor && this->pressed)
+ editor->setFocus();
+ this->pressed = false;
return editor;
}
diff --git a/src/Gui/propertyeditor/PropertyItemDelegate.h b/src/Gui/propertyeditor/PropertyItemDelegate.h
index b3086f65e..236020bd2 100644
--- a/src/Gui/propertyeditor/PropertyItemDelegate.h
+++ b/src/Gui/propertyeditor/PropertyItemDelegate.h
@@ -42,9 +42,14 @@ public:
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const;
virtual void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index ) const;
virtual QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const;
+ virtual bool editorEvent (QEvent *event, QAbstractItemModel *model,
+ const QStyleOptionViewItem& option, const QModelIndex& index);
public Q_SLOTS:
void valueChanged();
+
+private:
+ mutable bool pressed;
};
} // namespace PropertyEditor
diff --git a/src/Mod/Arch/Arch.py b/src/Mod/Arch/Arch.py
index 77c0b9534..0a32f924b 100644
--- a/src/Mod/Arch/Arch.py
+++ b/src/Mod/Arch/Arch.py
@@ -39,3 +39,4 @@ from ArchSectionPlane import *
from ArchWindow import *
from ArchAxis import *
from ArchRoof import *
+from ArchSpace import *
diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py
index 8212772fa..63dd4e159 100644
--- a/src/Mod/Arch/ArchCommands.py
+++ b/src/Mod/Arch/ArchCommands.py
@@ -67,25 +67,24 @@ def addComponents(objectsList,host):
example to add windows to a wall, or to add walls to a cell or floor.'''
if not isinstance(objectsList,list):
objectsList = [objectsList]
- tp = Draft.getType(host)
- if tp in ["Cell"]:
- c = host.Components
- for o in objectsList:
- if not o in c:
- c.append(o)
- host.Components = c
- elif tp in ["Floor","Building","Site"]:
+ hostType = Draft.getType(host)
+ if hostType in ["Floor","Building","Site"]:
c = host.Group
for o in objectsList:
if not o in c:
c.append(o)
host.Group = c
- elif tp in ["Wall","Structure","Window","Roof"]:
+ elif hostType in ["Wall","Structure","Window","Roof"]:
+ import DraftGeomUtils
a = host.Additions
if hasattr(host,"Axes"):
x = host.Axes
for o in objectsList:
- if Draft.getType(o) == "Axis":
+ if DraftGeomUtils.isValidPath(o.Shape) and (hostType == "Structure"):
+ if o.Support == host:
+ o.Support = None
+ host.Tool = o
+ elif Draft.getType(o) == "Axis":
if not o in x:
x.append(o)
elif not o in a:
@@ -94,7 +93,7 @@ def addComponents(objectsList,host):
host.Additions = a
if hasattr(host,"Axes"):
host.Axes = x
- elif tp in ["SectionPlane"]:
+ elif hostType in ["SectionPlane"]:
a = host.Objects
for o in objectsList:
if not o in a:
@@ -117,6 +116,9 @@ def removeComponents(objectsList,host=None):
objectsList = [objectsList]
if host:
if Draft.getType(host) in ["Wall","Structure"]:
+ if hasattr(host,"Tool"):
+ if objectsList[0] == host.Tool:
+ host.Tool = None
if hasattr(host,"Axes"):
a = host.Axes
for o in objectsList[:]:
@@ -150,7 +152,7 @@ def removeComponents(objectsList,host=None):
if o.InList:
h = o.InList[0]
tp = Draft.getType(h)
- if tp in ["Cell","Floor","Building","Site"]:
+ if tp in ["Floor","Building","Site"]:
c = h.Components
if o in c:
c.remove(o)
@@ -271,8 +273,8 @@ def makeFace(wires,method=2,cleanup=False):
#print "makeFace: reversing",w
w.reverse()
# make sure that the exterior wires comes as first in the list
- wires.insert(0, ext)
- #print "makeFace: done sorting", wires
+ wires.insert(0, ext)
+ #print "makeFace: done sorting", wires
if wires:
return Part.Face(wires)
else:
@@ -317,17 +319,29 @@ def getCutVolume(cutplane,shapes):
"""getCutVolume(cutplane,shapes): returns a cut face and a cut volume
from the given shapes and the given cutting plane"""
import Part
- placement = FreeCAD.Placement(cutplane.Placement)
+ if not isinstance(shapes,list):
+ shapes = [shapes]
# building boundbox
- bb = shapes[0].BoundBox
+ bb = shapes[0].BoundBox
for sh in shapes[1:]:
bb.add(sh.BoundBox)
bb.enlarge(1)
+ # building cutplane space
+ placement = None
um = vm = wm = 0
- ax = placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
- u = placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
- v = placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
- if not bb.isCutPlane(placement.Base,ax):
+ try:
+ if hasattr(cutplane,"Shape"):
+ p = cutplane.Shape.copy().Faces[0]
+ else:
+ p = cutplane.copy().Faces[0]
+ except:
+ FreeCAD.Console.PrintMessage(str(translate("Arch","Invalid cutplane")))
+ return None,None,None
+ ce = p.CenterOfMass
+ ax = p.normalAt(0,0)
+ u = p.Vertexes[1].Point.sub(p.Vertexes[0].Point).normalize()
+ v = u.cross(ax)
+ if not bb.isCutPlane(ce,ax):
FreeCAD.Console.PrintMessage(str(translate("Arch","No objects are cut by the plane")))
return None,None,None
else:
@@ -340,23 +354,26 @@ def getCutVolume(cutplane,shapes):
FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax),
FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)]
for c in corners:
- dv = c.sub(placement.Base)
+ dv = c.sub(ce)
um1 = DraftVecUtils.project(dv,u).Length
um = max(um,um1)
vm1 = DraftVecUtils.project(dv,v).Length
vm = max(vm,vm1)
wm1 = DraftVecUtils.project(dv,ax).Length
wm = max(wm,wm1)
- p1 = FreeCAD.Vector(-um,vm,0)
- p2 = FreeCAD.Vector(um,vm,0)
- p3 = FreeCAD.Vector(um,-vm,0)
- p4 = FreeCAD.Vector(-um,-vm,0)
+ vu = DraftVecUtils.scaleTo(u,um)
+ vui = vu.negative()
+ vv = DraftVecUtils.scaleTo(v,vm)
+ vvi = vv.negative()
+ p1 = ce.add(vu.add(vvi))
+ p2 = ce.add(vu.add(vv))
+ p3 = ce.add(vui.add(vv))
+ p4 = ce.add(vui.add(vvi))
cutface = Part.makePolygon([p1,p2,p3,p4,p1])
cutface = Part.Face(cutface)
- cutface.Placement = placement
cutnormal = DraftVecUtils.scaleTo(ax,wm)
cutvolume = cutface.extrude(cutnormal)
- cutnormal = DraftVecUtils.neg(cutnormal)
+ cutnormal = cutnormal.negative()
invcutvolume = cutface.extrude(cutnormal)
return cutface,cutvolume,invcutvolume
@@ -442,7 +459,7 @@ def removeShape(objs,mark=True):
length = dims[1]
width = dims[2]
v1 = Vector(length/2,0,0)
- v2 = DraftVecUtils.neg(v1)
+ v2 = v1.negative()
v1 = dims[0].multVec(v1)
v2 = dims[0].multVec(v2)
line = Draft.makeLine(v1,v2)
@@ -556,17 +573,22 @@ class _CommandAdd:
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
- FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Grouping")))
- if not mergeCells(sel):
- host = sel.pop()
- ss = "["
- for o in sel:
- if len(ss) > 1:
- ss += ","
- ss += "FreeCAD.ActiveDocument."+o.Name
- ss += "]"
+ if Draft.getType(sel[-1]) == "Space":
+ FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Add space boundary")))
FreeCADGui.doCommand("import Arch")
- FreeCADGui.doCommand("Arch.addComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")")
+ FreeCADGui.doCommand("Arch.addSpaceBoundaries( FreeCAD.ActiveDocument."+sel[-1].Name+", FreeCADGui.Selection.getSelectionEx() )")
+ else:
+ FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Grouping")))
+ if not mergeCells(sel):
+ host = sel.pop()
+ ss = "["
+ for o in sel:
+ if len(ss) > 1:
+ ss += ","
+ ss += "FreeCAD.ActiveDocument."+o.Name
+ ss += "]"
+ FreeCADGui.doCommand("import Arch")
+ FreeCADGui.doCommand("Arch.addComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")")
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
@@ -586,20 +608,25 @@ class _CommandRemove:
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
- FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping")))
- if (Draft.getType(sel[-1]) in ["Wall","Structure"]) and (len(sel) > 1):
- host = sel.pop()
- ss = "["
- for o in sel:
- if len(ss) > 1:
- ss += ","
- ss += "FreeCAD.ActiveDocument."+o.Name
- ss += "]"
+ if Draft.getType(sel[-1]) == "Space":
+ FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Remove space boundary")))
FreeCADGui.doCommand("import Arch")
- FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")")
+ FreeCADGui.doCommand("Arch.removeSpaceBoundaries( FreeCAD.ActiveDocument."+sel[-1].Name+", FreeCADGui.Selection.getSelection() )")
else:
- FreeCADGui.doCommand("import Arch")
- FreeCADGui.doCommand("Arch.removeComponents(Arch.ActiveDocument."+sel[-1].Name+")")
+ FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping")))
+ if (Draft.getType(sel[-1]) in ["Wall","Structure"]) and (len(sel) > 1):
+ host = sel.pop()
+ ss = "["
+ for o in sel:
+ if len(ss) > 1:
+ ss += ","
+ ss += "FreeCAD.ActiveDocument."+o.Name
+ ss += "]"
+ FreeCADGui.doCommand("import Arch")
+ FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")")
+ else:
+ FreeCADGui.doCommand("import Arch")
+ FreeCADGui.doCommand("Arch.removeComponents(Arch.ActiveDocument."+sel[-1].Name+")")
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py
index 786f48914..f6bc68143 100644
--- a/src/Mod/Arch/ArchComponent.py
+++ b/src/Mod/Arch/ArchComponent.py
@@ -26,6 +26,7 @@ __author__ = "Yorik van Havre"
__url__ = "http://free-cad.sourceforge.net"
import FreeCAD,FreeCADGui,Draft
+from FreeCAD import Vector
from PyQt4 import QtGui,QtCore
from DraftTools import translate
@@ -104,6 +105,22 @@ def removeFromComponent(compobject,subobject):
compobject.Subtractions = l
if Draft.getType(subobject) != "Window":
subobject.ViewObject.hide()
+
+
+class SelectionTaskPanel:
+ """A temp taks panel to wait for a selection"""
+ def __init__(self):
+ self.form = QtGui.QLabel()
+ self.form.setText(QtGui.QApplication.translate("Arch", "Please select a base object", None, QtGui.QApplication.UnicodeUTF8))
+
+ def getStandardButtons(self):
+ return int(QtGui.QDialogButtonBox.Cancel)
+
+ def reject(self):
+ if hasattr(FreeCAD,"ArchObserver"):
+ FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
+ del FreeCAD.ArchObserver
+ return True
class ComponentTaskPanel:
@@ -270,11 +287,12 @@ class Component:
self.Type = "Component"
self.Subvolume = None
+ def execute(self,obj):
+ return
def __getstate__(self):
return self.Type
-
def __setstate__(self,state):
if state:
self.Type = state
@@ -307,8 +325,8 @@ class Component:
n = f.normalAt(0,0)
v1 = DraftVecUtils.scaleTo(n,width*1.1) # we extrude a little more to avoid face-on-face
f.translate(v1)
- v2 = DraftVecUtils.neg(v1)
- v2 = DraftVecUtils.scale(v1,-2)
+ v2 = v1.negative()
+ v2 = Vector(v1).multiply(-2)
f = f.extrude(v2)
if plac:
f.Placement = plac
@@ -408,7 +426,7 @@ class ViewProviderComponent:
vobj.Proxy = self
self.Object = vobj.Object
- def updateData(self,vobj,prop):
+ def updateData(self,obj,prop):
return
def onChanged(self,vobj,prop):
@@ -443,10 +461,15 @@ class ViewProviderComponent:
return None
def claimChildren(self):
- c = [self.Object.Base]+self.Object.Additions+self.Object.Subtractions
- if hasattr(self.Object,"Fixtures"):
- c.extend(self.Object.Fixtures)
- return c
+ if hasattr(self,"Object"):
+ c = [self.Object.Base]+self.Object.Additions+self.Object.Subtractions
+ if hasattr(self.Object,"Fixtures"):
+ c.extend(self.Object.Fixtures)
+ if hasattr(self.Object,"Tool"):
+ if self.Object.Tool:
+ c.append(self.Object.Tool)
+ return c
+ return []
def setEdit(self,vobj,mode):
taskd = ComponentTaskPanel()
@@ -460,18 +483,32 @@ class ViewProviderComponent:
return False
class ArchSelectionObserver:
- def __init__(self,origin,watched,hide=True,nextCommand=None):
+ """ArchSelectionObserver([origin,watched,hide,nextCommand]): The ArchSelectionObserver
+ object can be added as a selection observer to the FreeCAD Gui. If watched is given (a
+ document object), the observer will be triggered only when that object is selected/unselected.
+ If hide is True, the watched object will be hidden. If origin is given (a document
+ object), that object will have its visibility/selectability restored. If nextCommand
+ is given (a FreeCAD command), it will be executed on leave."""
+
+ def __init__(self,origin=None,watched=None,hide=True,nextCommand=None):
self.origin = origin
self.watched = watched
self.hide = hide
self.nextCommand = nextCommand
+
def addSelection(self,document, object, element, position):
- if object == self.watched.Name:
+ if not self.watched:
+ FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
+ if self.nextCommand:
+ FreeCADGui.runCommand(self.nextCommand)
+ del FreeCAD.ArchObserver
+ elif object == self.watched.Name:
if not element:
FreeCAD.Console.PrintMessage(str(translate("Arch","closing Sketch edit")))
if self.hide:
- self.origin.ViewObject.Transparency = 0
- self.origin.ViewObject.Selectable = True
+ if self.origin:
+ self.origin.ViewObject.Transparency = 0
+ self.origin.ViewObject.Selectable = True
self.watched.ViewObject.hide()
FreeCADGui.activateWorkbench("ArchWorkbench")
FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
diff --git a/src/Mod/Arch/ArchRoof.py b/src/Mod/Arch/ArchRoof.py
index 8b20daf5a..505a0a915 100644
--- a/src/Mod/Arch/ArchRoof.py
+++ b/src/Mod/Arch/ArchRoof.py
@@ -52,17 +52,12 @@ class _CommandRoof:
'Accel': "R, F",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Roof","Creates a roof object from the selected face of an object")}
- def IsActive(self):
- if FreeCADGui.Selection.getSelection():
- return True
- else:
- return False
-
def Activated(self):
sel = FreeCADGui.Selection.getSelectionEx()
if sel:
sel = sel[0]
obj = sel.Object
+ FreeCADGui.Control.closeDialog()
if sel.HasSubObjects:
if "Face" in sel.SubElementNames[0]:
idx = int(sel.SubElementNames[0][4:])
@@ -83,7 +78,10 @@ class _CommandRoof:
else:
FreeCAD.Console.PrintMessage(str(translate("Arch","Unable to create a roof")))
else:
- FreeCAD.Console.PrintMessage(str(translate("Arch","No object selected")))
+ FreeCAD.Console.PrintMessage(str(translate("Arch","Please select a base object\n")))
+ FreeCADGui.Control.showDialog(ArchComponent.SelectionTaskPanel())
+ FreeCAD.ArchObserver = ArchComponent.ArchSelectionObserver(nextCommand="Arch_Roof")
+ FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
class _Roof(ArchComponent.Component):
"The Roof object"
diff --git a/src/Mod/Arch/ArchSpace.py b/src/Mod/Arch/ArchSpace.py
new file mode 100644
index 000000000..d3161e555
--- /dev/null
+++ b/src/Mod/Arch/ArchSpace.py
@@ -0,0 +1,288 @@
+#***************************************************************************
+#* *
+#* Copyright (c) 2013 *
+#* Yorik van Havre *
+#* *
+#* This program is free software; you can redistribute it and/or modify *
+#* it under the terms of the GNU Lesser General Public License (LGPL) *
+#* as published by the Free Software Foundation; either version 2 of *
+#* the License, or (at your option) any later version. *
+#* for detail see the LICENCE text file. *
+#* *
+#* This program is distributed in the hope that it will be useful, *
+#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+#* GNU Library General Public License for more details. *
+#* *
+#* You should have received a copy of the GNU Library General Public *
+#* License along with this program; if not, write to the Free Software *
+#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+#* USA *
+#* *
+#***************************************************************************
+
+import FreeCAD,FreeCADGui,ArchComponent,ArchCommands,math,Draft
+from DraftTools import translate
+from PyQt4 import QtCore
+
+def makeSpace(objects=None):
+ """makeSpace([objects]): Creates a space object from the given objects. Objects can be one
+ document object, in which case it becomes the base shape of the space object, or a list of
+ selection objects as got from getSelectionEx(), or a list of tuples (object, subobjectname)"""
+ obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Space")
+ _Space(obj)
+ _ViewProviderSpace(obj.ViewObject)
+ if objects:
+ if not isinstance(objects,list):
+ objects = [objects]
+ if len(objects) == 1:
+ obj.Base = objects[0]
+ objects[0].ViewObject.hide()
+ else:
+ obj.Proxy.addSubobjects(obj,objects)
+
+def addSpaceBoundaries(space,subobjects):
+ """addSpaceBoundaries(space,subobjects): adds the given subobjects to the given space"""
+ import Draft
+ if Draft.getType(space) == "Space":
+ space.Proxy.addSubobjects(space,subobjects)
+
+def removeSpaceBoundaries(space,objects):
+ """removeSpaceBoundaries(space,objects): removes the given objects from the given spaces boundaries"""
+ import Draft
+ if Draft.getType(space) == "Space":
+ bounds = space.Boundaries
+ for o in objects:
+ for b in bounds:
+ if o.Name == b[0].Name:
+ bounds.remove(b)
+ break
+ space.Boundaries = bounds
+
+class _CommandSpace:
+ "the Arch Space command definition"
+ def GetResources(self):
+ return {'Pixmap' : 'Arch_Space',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Space","Space"),
+ 'Accel': "S, P",
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Space","Creates a space object from selected boundary objects")}
+
+ def Activated(self):
+ FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Space")))
+ FreeCADGui.doCommand("import Arch")
+ sel = FreeCADGui.Selection.getSelection()
+ if sel:
+ FreeCADGui.Control.closeDialog()
+ if len(sel) == 1:
+ FreeCADGui.doCommand("Arch.makeSpace(FreeCADGui.Selection.getSelection())")
+ else:
+ FreeCADGui.doCommand("Arch.makeSpace(FreeCADGui.Selection.getSelectionEx())")
+ FreeCAD.ActiveDocument.commitTransaction()
+ FreeCAD.ActiveDocument.recompute()
+ else:
+ FreeCAD.Console.PrintMessage(str(translate("Arch","Please select a base object\n")))
+ FreeCADGui.Control.showDialog(ArchComponent.SelectionTaskPanel())
+ FreeCAD.ArchObserver = ArchComponent.ArchSelectionObserver(nextCommand="Arch_Space")
+ FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
+
+
+class _Space(ArchComponent.Component):
+ "A space object"
+ def __init__(self,obj):
+ obj.Proxy = self
+ obj.addProperty("App::PropertyLink","Base","Base",
+ str(translate("Arch","A base shape defining this space")))
+ obj.addProperty("App::PropertyLinkSubList","Boundaries","Base",
+ str(translate("Arch","The objects that make the boundaries of this space object")))
+ self.Type = "Space"
+
+ def execute(self,obj):
+ self.getShape(obj)
+
+ def onChanged(self,obj,prop):
+ if prop in ["Boundaries","Base"]:
+ self.getShape(obj)
+
+ def addSubobjects(self,obj,subobjects):
+ "adds subobjects to this space"
+ objs = obj.Boundaries
+ for o in subobjects:
+ if isinstance(o,tuple) or isinstance(o,list):
+ if o[0].Name != obj.Name:
+ objs.append(tuple(o))
+ else:
+ for el in o.SubElementNames:
+ if "Face" in el:
+ if o.Object.Name != obj.Name:
+ objs.append((o.Object,el))
+ obj.Boundaries = objs
+
+ def getShape(self,obj):
+ "computes a shape from a base shape and/or bounday faces"
+ import Part
+ shape = None
+ faces = []
+
+ #print "starting compute"
+ # 1: if we have a base shape, we use it
+
+ if obj.Base:
+ if obj.Base.isDerivedFrom("Part::Feature"):
+ if obj.Base.Shape.Solids:
+ shape = obj.Base.Shape.Solids[0].copy()
+
+ # 2: if not, add all bounding boxes of considered objects and build a first shape
+ if shape:
+ #print "got shape from base object"
+ bb = shape.BoundBox
+ else:
+ bb = None
+ for b in obj.Boundaries:
+ if b[0].isDerivedFrom("Part::Feature"):
+ if not bb:
+ bb = b[0].Shape.BoundBox
+ else:
+ bb.add(b[0].Shape.BoundBox)
+ if not bb:
+ return
+ shape = Part.makeBox(bb.XLength,bb.YLength,bb.ZLength,FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin))
+ #print "created shape from boundbox"
+
+ # 3: identifing boundary faces
+ goodfaces = []
+ for b in obj.Boundaries:
+ if b[0].isDerivedFrom("Part::Feature"):
+ if "Face" in b[1]:
+ fn = int(b[1][4:])-1
+ faces.append(b[0].Shape.Faces[fn])
+ #print "adding face ",fn," of object ",b[0].Name
+
+ #print "total: ", len(faces), " faces"
+
+ # 4: get cutvolumes from faces
+ cutvolumes = []
+ for f in faces:
+ f = f.copy()
+ f.reverse()
+ cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(f,shape)
+ if cutvolume:
+ #print "generated 1 cutvolume"
+ cutvolumes.append(cutvolume.copy())
+ #Part.show(cutvolume)
+ for v in cutvolumes:
+ #print "cutting"
+ shape = shape.cut(v)
+
+ # 5: get the final shape
+ if shape:
+ if shape.Solids:
+ #print "setting objects shape"
+ shape = shape.Solids[0]
+ obj.Shape = shape
+ return
+
+ print "Arch: error computing space boundary"
+
+ def getArea(self,obj):
+ "returns the horizontal area at the center of the space"
+ import Part,DraftGeomUtils
+ try:
+ pl = Part.makePlane(1,1)
+ sh = obj.Shape.copy()
+ cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
+ e = sh.section(cutplane)
+ e = DraftGeomUtils.sortEdges(e.Edges)
+ w = Part.Wire(e)
+ f = Part.Face(w)
+ return round(f.Area,Draft.getParam("dimPrecision"))
+ except:
+ return 0
+
+
+class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
+ "A View Provider for Section Planes"
+ def __init__(self,vobj):
+ vobj.Transparency = 85
+ vobj.LineWidth = 1
+ vobj.LineColor = (1.0,0.0,0.0,1.0)
+ vobj.DrawStyle = "Dotted"
+ vobj.addProperty("App::PropertyString","Override","Base",
+ "Text override. Use $area to insert the area")
+ vobj.addProperty("App::PropertyColor","TextColor","Base",
+ "The color of the area text")
+ vobj.TextColor = (1.0,0.0,0.0,1.0)
+ vobj.Override = "$area m2"
+ ArchComponent.ViewProviderComponent.__init__(self,vobj)
+
+ def getIcon(self):
+ import Arch_rc
+ return ":/icons/Arch_Space_Tree.svg"
+
+ def claimChildren(self):
+ if self.Object.Base:
+ return [self.Object.Base]
+ else:
+ return []
+
+ def setDisplayMode(self,mode):
+ if mode == "Detailed":
+ self.setAnnotation(True)
+ return "Flat Lines"
+ else:
+ self.setAnnotation(False)
+ return mode
+
+ def getArea(self,obj):
+ "returns a formatted area text"
+ area = str(obj.Proxy.getArea(obj))
+ if obj.ViewObject.Override:
+ text = obj.ViewObject.Override
+ area = text.replace("$area",str(area))
+ return str(area)
+
+ def setAnnotation(self,recreate=True):
+ if hasattr(self,"Object"):
+ if hasattr(self,"area"):
+ if self.area:
+ self.Object.ViewObject.Annotation.removeChild(self.area)
+ self.area = None
+ self.coords = None
+ self.anno = None
+ if recreate:
+ area = self.getArea(self.Object)
+ if area:
+ from pivy import coin
+ import SketcherGui
+ self.area = coin.SoSeparator()
+ self.coords = coin.SoTransform()
+ if self.Object.Shape:
+ if not self.Object.Shape.isNull():
+ c = self.Object.Shape.CenterOfMass
+ self.coords.translation.setValue([c.x,c.y,c.z])
+ self.anno = coin.SoType.fromName("SoDatumLabel").createInstance()
+ self.anno.string.setValue(area)
+ self.anno.datumtype.setValue(6)
+ color = coin.SbVec3f(self.Object.ViewObject.TextColor[:3])
+ self.anno.textColor.setValue(color)
+ self.area.addChild(self.coords)
+ self.area.addChild(self.anno)
+ self.Object.ViewObject.Annotation.addChild(self.area)
+
+ def updateData(self,obj,prop):
+ if prop == "Shape":
+ if hasattr(self,"area"):
+ if self.area:
+ area = self.getArea(obj)
+ self.anno.string.setValue(area)
+ if not obj.Shape.isNull():
+ c = obj.Shape.CenterOfMass
+ self.coords.translation.setValue([c.x,c.y,c.z])
+
+ def onChanged(self,vobj,prop):
+ if prop in ["Override","TextColor"]:
+ if vobj.DisplayMode == "Detailed":
+ self.setAnnotation(True)
+ return
+
+
+FreeCADGui.addCommand('Arch_Space',_CommandSpace())
diff --git a/src/Mod/Arch/ArchStructure.py b/src/Mod/Arch/ArchStructure.py
index 379730903..677205ec3 100644
--- a/src/Mod/Arch/ArchStructure.py
+++ b/src/Mod/Arch/ArchStructure.py
@@ -30,7 +30,80 @@ __title__="FreeCAD Structure"
__author__ = "Yorik van Havre"
__url__ = "http://free-cad.sourceforge.net"
-def makeStructure(baseobj=None,length=1,width=1,height=1,name=str(translate("Arch","Structure"))):
+# Make some strings picked by the translator
+QtCore.QT_TRANSLATE_NOOP("Arch","Wood")
+QtCore.QT_TRANSLATE_NOOP("Arch","Steel")
+
+# Presets in the form: Class, Name, Width, Height, [Web thickness, Flange thickness]
+Presets = [None,
+
+ # wood sections
+
+ ["Wood","1x2in",19,28],
+ ["Wood","1x3in",19,64],
+ ["Wood","1x4in",19,89],
+ ["Wood","1x6in",19,89],
+ ["Wood","1x8in",19,140],
+ ["Wood","1x10in",19,184],
+ ["Wood","1x12in",19,286],
+
+ ["Wood","2x2in",38,38],
+ ["Wood","2x3in",38,64],
+ ["Wood","2x4in",38,89],
+ ["Wood","2x6in",38,140],
+ ["Wood","2x8in",38,184],
+ ["Wood","2x10in",38,235],
+ ["Wood","2x12in",38,286],
+
+ ["Wood","4x4in",89,89],
+ ["Wood","4x6in",89,140],
+ ["Wood","6x6in",140,140],
+ ["Wood","8x8in",184,184],
+
+ # IPE beams
+
+ ["Steel","IPE90",46,80,3.8,5.2],
+ ["Steel","IPE100",55,100,4.1,5.7],
+ ["Steel","IPE120",64,120,4.4,6.3],
+ ["Steel","IPE140",73,140,4.7,6.9],
+ ["Steel","IPE160",82,160,5,7.4],
+ ["Steel","IPE180",91,180,5.3,8],
+ ["Steel","IPE200",100,200,5.6,8.5],
+ ["Steel","IPE220",110,220,5.9,9.2],
+ ["Steel","IPE240",120,240,6.2,9.8],
+ ["Steel","IPE270",135,270,6.6,10.2],
+ ["Steel","IPE300",150,300,7.1,10.7],
+ ["Steel","IPE330",160,330,7.5,11.5],
+ ["Steel","IPE360",170,360,8,12.7],
+ ["Steel","IPE400",180,400,8.6,13.5],
+ ["Steel","IPE450",190,450,9.4,14.6],
+ ["Steel","IPE500",200,500,10.2,16],
+ ["Steel","IPE550",210,550,11.1,17.2],
+ ["Steel","IPE600",220,600,12,19],
+
+ # INP beams
+
+ ["Steel","INP80",42,80,3.9,5.9],
+ ["Steel","INP100",50,100,4.5,6.8],
+ ["Steel","INP120",58,120,5.1,7.7],
+ ["Steel","INP140",66,140,5.7,8.6],
+ ["Steel","INP160",74,160,6.3,9.5],
+ ["Steel","INP180",82,180,6.9,10.4],
+ ["Steel","INP200",90,200,7.5,11.3],
+ ["Steel","INP220",98,220,8.1,12.2],
+ ["Steel","INP240",106,240,8.7,13.1],
+ ["Steel","INP260",113,260,9.4,14.1],
+ ["Steel","INP280",119,280,10.1,15.2],
+ ["Steel","INP300",125,300,10.8,16.2],
+ ["Steel","INP320",131,320,11.5,17.3],
+ ["Steel","INP340",137,340,12.2,18.3],
+ ["Steel","INP360",143,360,13,19.5],
+ ["Steel","INP380",149,380,13.7,20.5],
+ ["Steel","INP400",155,400,14.4,21.6]
+
+ ]
+
+def makeStructure(baseobj=None,length=0,width=0,height=0,name=str(translate("Arch","Structure"))):
'''makeStructure([obj],[length],[width],[heigth],[swap]): creates a
structure element based on the given profile object and the given
extrusion height. If no base object is given, you can also specify
@@ -41,9 +114,12 @@ def makeStructure(baseobj=None,length=1,width=1,height=1,name=str(translate("Arc
if baseobj:
obj.Base = baseobj
obj.Base.ViewObject.hide()
- obj.Width = width
- obj.Height = height
- obj.Length = length
+ if width:
+ obj.Width = width
+ if height:
+ obj.Height = height
+ if length:
+ obj.Length = length
obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Structure")
return obj
@@ -58,6 +134,21 @@ def makeStructuralSystem(objects,axes):
result.append(s)
FreeCAD.ActiveDocument.recompute()
return result
+
+def makeProfile(W=46,H=80,tw=3.8,tf=5.2):
+ '''makeProfile(W,H,tw,tf): returns a shape with one face describing
+ the profile of a steel beam (IPE, IPN, HE, etc...) based on the following
+ dimensions: W = total width, H = total height, tw = web thickness
+ tw = flange thickness (see http://en.wikipedia.org/wiki/I-beam for
+ reference)'''
+ obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Profile")
+ _Profile(obj)
+ obj.Width = W
+ obj.Height = H
+ obj.WebThickness = tw
+ obj.FlangeThickness = tf
+ Draft._ViewProviderDraft(obj.ViewObject)
+ return obj
class _CommandStructure:
"the Arch Structure command definition"
@@ -72,9 +163,11 @@ class _CommandStructure:
global QtGui, QtCore
from PyQt4 import QtGui, QtCore
- self.Length = 0.5
- self.Width = 0.2
- self.Height = 1
+ p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
+ self.Length = p.GetFloat("StructureLength",100)
+ self.Width = p.GetFloat("StructureWidth",100)
+ self.Height = p.GetFloat("StructureHeight",1000)
+ self.Profile = 0
self.continueCmd = False
sel = FreeCADGui.Selection.getSelection()
if sel:
@@ -94,6 +187,8 @@ class _CommandStructure:
FreeCAD.ActiveDocument.recompute()
else:
# interactive mode
+ if hasattr(FreeCAD,"DraftWorkingPlane"):
+ FreeCAD.DraftWorkingPlane.setup()
import DraftTrackers
self.points = []
self.tracker = DraftTrackers.boxTracker()
@@ -110,7 +205,18 @@ class _CommandStructure:
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)+')')
+ if self.Profile:
+ pr = Presets[self.Profile]
+ FreeCADGui.doCommand('p = Arch.makeProfile('+str(pr[2])+','+str(pr[3])+','+str(pr[4])+','+str(pr[5])+')')
+ if self.Length == pr[2]:
+ # vertical
+ FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Height)+')')
+ else:
+ # horizontal
+ FreeCADGui.doCommand('s = Arch.makeStructure(p,height='+str(self.Length)+')')
+ FreeCADGui.doCommand('s.Placement.Rotation = FreeCAD.Rotation(-0.5,0.5,-0.5,0.5)')
+ else:
+ 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()
@@ -123,45 +229,74 @@ class _CommandStructure:
w.setWindowTitle(str(translate("Arch","Structure options")))
lay0 = QtGui.QVBoxLayout(w)
+ # presets box
+ layp = QtGui.QHBoxLayout()
+ lay0.addLayout(layp)
+ labelp = QtGui.QLabel(str(translate("Arch","Preset")))
+ layp.addWidget(labelp)
+ valuep = QtGui.QComboBox()
+ fpresets = [" "]
+ for p in Presets[1:]:
+ fpresets.append(str(translate("Arch",p[0]))+" "+p[1]+" ("+str(p[2])+"x"+str(p[3])+"mm)")
+ valuep.addItems(fpresets)
+ layp.addWidget(valuep)
+
+ # length
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)
+ self.vLength = QtGui.QDoubleSpinBox()
+ self.vLength.setDecimals(2)
+ self.vLength.setMaximum(99999.99)
+ self.vLength.setValue(self.Length)
+ lay1.addWidget(self.vLength)
+ # width
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)
+ self.vWidth = QtGui.QDoubleSpinBox()
+ self.vWidth.setDecimals(2)
+ self.vWidth.setMaximum(99999.99)
+ self.vWidth.setValue(self.Width)
+ lay2.addWidget(self.vWidth)
+ # height
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)
+ self.vHeight = QtGui.QDoubleSpinBox()
+ self.vHeight.setDecimals(2)
+ self.vHeight.setMaximum(99999.99)
+ self.vHeight.setValue(self.Height)
+ lay3.addWidget(self.vHeight)
+
+ # horizontal button
+ value5 = QtGui.QPushButton(str(translate("Arch","Rotate")))
+ lay0.addWidget(value5)
+ # continue button
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(valuep,QtCore.SIGNAL("currentIndexChanged(int)"),self.setPreset)
+ QtCore.QObject.connect(self.vLength,QtCore.SIGNAL("valueChanged(double)"),self.setLength)
+ QtCore.QObject.connect(self.vWidth,QtCore.SIGNAL("valueChanged(double)"),self.setWidth)
+ QtCore.QObject.connect(self.vHeight,QtCore.SIGNAL("valueChanged(double)"),self.setHeight)
QtCore.QObject.connect(value4,QtCore.SIGNAL("stateChanged(int)"),self.setContinue)
+ QtCore.QObject.connect(value5,QtCore.SIGNAL("pressed()"),self.rotate)
return w
def update(self,point):
"this function is called by the Snapper when the mouse is moved"
- self.tracker.pos(point)
+ if self.Height >= self.Length:
+ delta = Vector(0,0,self.Height/2)
+ else:
+ delta = Vector(self.Length/2,0,0)
+ self.tracker.pos(point.add(delta))
def setWidth(self,d):
self.Width = d
@@ -177,11 +312,30 @@ class _CommandStructure:
def setContinue(self,i):
self.continueCmd = bool(i)
+
+ def setPreset(self,i):
+ if i > 0:
+ self.vLength.setValue(float(Presets[i][2]))
+ self.vWidth.setValue(float(Presets[i][3]))
+ if len(Presets[i]) == 6:
+ self.Profile = i
+ else:
+ self.Profile = 0
+
+ def rotate(self):
+ l = self.Length
+ w = self.Width
+ h = self.Height
+ self.vLength.setValue(h)
+ self.vHeight.setValue(w)
+ self.vWidth.setValue(l)
class _Structure(ArchComponent.Component):
"The Structure object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
+ obj.addProperty("App::PropertyLink","Tool","Base",
+ "An optional extrusion path for this element")
obj.addProperty("App::PropertyLength","Length","Base",
str(translate("Arch","The length of this element, if not based on a profile")))
obj.addProperty("App::PropertyLength","Width","Base",
@@ -195,13 +349,16 @@ class _Structure(ArchComponent.Component):
obj.addProperty("App::PropertyIntegerList","Exclude","Base",
str(translate("Arch","The element numbers to exclude when this structure is based on axes")))
self.Type = "Structure"
+ obj.Length = 1
+ obj.Width = 1
+ obj.Height = 1
def execute(self,obj):
self.createGeometry(obj)
def onChanged(self,obj,prop):
self.hideSubobjects(obj,prop)
- if prop in ["Base","Length","Width","Height","Normal","Additions","Subtractions","Axes"]:
+ if prop in ["Base","Tool","Length","Width","Height","Normal","Additions","Subtractions","Axes"]:
self.createGeometry(obj)
def getAxisPoints(self,obj):
@@ -245,21 +402,30 @@ class _Structure(ArchComponent.Component):
base = None
if obj.Base:
if obj.Base.isDerivedFrom("Part::Feature"):
- if obj.Normal == Vector(0,0,0):
- p = FreeCAD.Placement(obj.Base.Placement)
- normal = p.Rotation.multVec(Vector(0,0,1))
- else:
- normal = Vector(obj.Normal)
- normal = normal.multiply(height)
- base = obj.Base.Shape.copy()
- if base.Solids:
- pass
- elif base.Faces:
- base = base.extrude(normal)
- elif (len(base.Wires) == 1):
- if base.Wires[0].isClosed():
- base = Part.Face(base.Wires[0])
+ if hasattr(obj,"Tool"):
+ if obj.Tool:
+ try:
+ base = obj.Tool.Shape.copy().makePipe(obj.Base.Shape.copy())
+ except:
+ FreeCAD.Console.PrintError(str(translate("Arch","Error: The base shape couldn't be extruded along this tool object")))
+ return
+ if not base:
+ if obj.Normal == Vector(0,0,0):
+ p = FreeCAD.Placement(obj.Base.Placement)
+ normal = p.Rotation.multVec(Vector(0,0,1))
+ else:
+ normal = Vector(obj.Normal)
+ normal = normal.multiply(height)
+ base = obj.Base.Shape.copy()
+ if base.Solids:
+ pass
+ elif base.Faces:
base = base.extrude(normal)
+ elif (len(base.Wires) == 1):
+ if base.Wires[0].isClosed():
+ base = Part.Face(base.Wires[0])
+ base = base.extrude(normal)
+
elif obj.Base.isDerivedFrom("Mesh::Feature"):
if obj.Base.Mesh.isSolid():
if obj.Base.Mesh.countComponents() == 1:
@@ -310,13 +476,14 @@ class _Structure(ArchComponent.Component):
if base.Volume < 0:
base.reverse()
if base.Volume < 0:
- FreeCAD.Console.PrintError(str(translate("Arch","Couldn't compute the wall shape")))
+ FreeCAD.Console.PrintError(str(translate("Arch","Couldn't compute a shape")))
return
base = base.removeSplitter()
obj.Shape = base
if not DraftGeomUtils.isNull(pl):
obj.Placement = pl
-
+
+
class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
"A View Provider for the Structure object"
@@ -327,4 +494,43 @@ class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
import Arch_rc
return ":/icons/Arch_Structure_Tree.svg"
+
+class _Profile(Draft._DraftObject):
+ "A parametric beam profile object"
+
+ def __init__(self,obj):
+ obj.addProperty("App::PropertyDistance","Width","Base","Width of the beam").Width = 10
+ obj.addProperty("App::PropertyDistance","Height","Base","Height of the beam").Height = 30
+ obj.addProperty("App::PropertyDistance","WebThickness","Base","Thickness of the webs").WebThickness = 3
+ obj.addProperty("App::PropertyDistance","FlangeThickness","Base","Thickness of the flange").FlangeThickness = 2
+ Draft._DraftObject.__init__(self,obj,"Profile")
+
+ def execute(self,obj):
+ self.createGeometry(obj)
+
+ def onChanged(self,obj,prop):
+ if prop in ["Width","Height","WebThickness","FlangeThickness"]:
+ self.createGeometry(obj)
+
+ def createGeometry(self,obj):
+ import Part
+ pl = obj.Placement
+ p1 = Vector(-obj.Width/2,-obj.Height/2,0)
+ p2 = Vector(obj.Width/2,-obj.Height/2,0)
+ p3 = Vector(obj.Width/2,(-obj.Height/2)+obj.FlangeThickness,0)
+ p4 = Vector(obj.WebThickness/2,(-obj.Height/2)+obj.FlangeThickness,0)
+ p5 = Vector(obj.WebThickness/2,obj.Height/2-obj.FlangeThickness,0)
+ p6 = Vector(obj.Width/2,obj.Height/2-obj.FlangeThickness,0)
+ p7 = Vector(obj.Width/2,obj.Height/2,0)
+ p8 = Vector(-obj.Width/2,obj.Height/2,0)
+ p9 = Vector(-obj.Width/2,obj.Height/2-obj.FlangeThickness,0)
+ p10 = Vector(-obj.WebThickness/2,obj.Height/2-obj.FlangeThickness,0)
+ p11 = Vector(-obj.WebThickness/2,(-obj.Height/2)+obj.FlangeThickness,0)
+ p12 = Vector(-obj.Width/2,(-obj.Height/2)+obj.FlangeThickness,0)
+ p = Part.makePolygon([p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p1])
+ p = Part.Face(p)
+ obj.Shape = p
+ obj.Placement = pl
+
+
FreeCADGui.addCommand('Arch_Structure',_CommandStructure())
diff --git a/src/Mod/Arch/ArchWall.py b/src/Mod/Arch/ArchWall.py
index 5f0ca5cb0..8de79cc5c 100644
--- a/src/Mod/Arch/ArchWall.py
+++ b/src/Mod/Arch/ArchWall.py
@@ -30,15 +30,18 @@ __title__="FreeCAD Wall"
__author__ = "Yorik van Havre"
__url__ = "http://free-cad.sourceforge.net"
-def makeWall(baseobj=None,width=None,height=None,align="Center",name=str(translate("Arch","Wall"))):
- '''makeWall(obj,[width],[height],[align],[name]): creates a wall based on the
- given object, which can be a sketch, a draft object, a face or a solid. align
+def makeWall(baseobj=None,length=None,width=None,height=None,align="Center",name=str(translate("Arch","Wall"))):
+ '''makeWall([obj],[length],[width],[height],[align],[name]): creates a wall based on the
+ given object, which can be a sketch, a draft object, a face or a solid, or no object at
+ all, then you must provide length, width and height. Align
can be "Center","Left" or "Right"'''
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
_Wall(obj)
_ViewProviderWall(obj.ViewObject)
if baseobj:
obj.Base = baseobj
+ if length:
+ obj.Length = length
if width:
obj.Width = width
if height:
@@ -95,7 +98,7 @@ def mergeShapes(w1,w2):
w = DraftGeomUtils.findWires(eds)
if len(w) == 1:
print "found common wire"
- normal,width,height = w1.Proxy.getDefaultValues(w1)
+ normal,length,width,height = w1.Proxy.getDefaultValues(w1)
print w[0].Edges
sh = w1.Proxy.getBase(w1,w[0],normal,width,height)
print sh
@@ -133,12 +136,12 @@ class _CommandWall:
global QtGui, QtCore
from PyQt4 import QtGui, QtCore
- self.Width = 0.1
- self.Height = 1
self.Align = "Center"
self.Length = None
self.continueCmd = False
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
+ self.Width = p.GetFloat("WallWidth",200)
+ self.Height = p.GetFloat("WallHeight",3000)
self.JOIN_WALLS = p.GetBool("joinWallSketches")
sel = FreeCADGui.Selection.getSelection()
done = False
@@ -157,6 +160,8 @@ class _CommandWall:
import DraftTrackers
self.points = []
self.tracker = DraftTrackers.boxTracker()
+ if hasattr(FreeCAD,"DraftWorkingPlane"):
+ FreeCAD.DraftWorkingPlane.setup()
FreeCADGui.Snapper.getPoint(callback=self.getPoint,extradlg=self.taskbox())
def getPoint(self,point=None,obj=None):
@@ -222,7 +227,7 @@ class _CommandWall:
elif self.Align == "Left":
self.tracker.update([b.add(dv),point.add(dv)])
else:
- dv = DraftVecUtils.neg(dv)
+ dv = dv.negative()
self.tracker.update([b.add(dv),point.add(dv)])
if self.Length:
self.Length.setValue(bv.Length)
@@ -328,6 +333,8 @@ class _Wall(ArchComponent.Component):
"The Wall object"
def __init__(self,obj):
ArchComponent.Component.__init__(self,obj)
+ obj.addProperty("App::PropertyLength","Length","Base",
+ str(translate("Arch","The length of this wall. Not used if this wall is based on an underlying object")))
obj.addProperty("App::PropertyLength","Width","Base",
str(translate("Arch","The width of this wall. Not used if this wall is based on a face")))
obj.addProperty("App::PropertyLength","Height","Base",
@@ -341,8 +348,9 @@ class _Wall(ArchComponent.Component):
obj.Align = ['Left','Right','Center']
obj.ForceWire = False
self.Type = "Wall"
- obj.Width = 0.1
- obj.Height = 0
+ obj.Width = 1
+ obj.Height = 1
+ obj.Length = 1
def execute(self,obj):
self.createGeometry(obj)
@@ -366,7 +374,11 @@ class _Wall(ArchComponent.Component):
def getDefaultValues(self,obj):
"returns normal,width,height values from this wall"
- width = 1.0
+ length = 1
+ if hasattr(obj,"Length"):
+ if obj.Length:
+ length = obj.Length
+ width = 1
if hasattr(obj,"Width"):
if obj.Width:
width = obj.Width
@@ -379,7 +391,7 @@ class _Wall(ArchComponent.Component):
if Draft.getType(p) == "Floor":
height = p.Height
if not height:
- height = 1.0
+ height = 1
if hasattr(obj,"Normal"):
if obj.Normal == Vector(0,0,0):
normal = Vector(0,0,1)
@@ -387,7 +399,7 @@ class _Wall(ArchComponent.Component):
normal = Vector(obj.Normal)
else:
normal = Vector(0,0,1)
- return normal,width,height
+ return normal,length,width,height
def getBase(self,obj,wire,normal,width,height):
"returns a full shape from a base wire"
@@ -399,20 +411,20 @@ class _Wall(ArchComponent.Component):
if not DraftVecUtils.isNull(dvec):
dvec.normalize()
if obj.Align == "Left":
- dvec = dvec.multiply(width)
+ dvec.multiply(width)
w2 = DraftGeomUtils.offsetWire(wire,dvec)
w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
sh = DraftGeomUtils.bind(w1,w2)
elif obj.Align == "Right":
- dvec = dvec.multiply(width)
- dvec = DraftVecUtils.neg(dvec)
+ dvec.multiply(width)
+ dvec = dvec.negative()
w2 = DraftGeomUtils.offsetWire(wire,dvec)
w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
sh = DraftGeomUtils.bind(w1,w2)
elif obj.Align == "Center":
- dvec = dvec.multiply(width/2)
+ dvec.multiply(width/2)
w1 = DraftGeomUtils.offsetWire(wire,dvec)
- dvec = DraftVecUtils.neg(dvec)
+ dvec = dvec.negative()
w2 = DraftGeomUtils.offsetWire(wire,dvec)
sh = DraftGeomUtils.bind(w1,w2)
# fixing self-intersections
@@ -425,54 +437,58 @@ class _Wall(ArchComponent.Component):
def createGeometry(self,obj):
"builds the wall shape"
- if not obj.Base:
- return
-
import Part, DraftGeomUtils
-
pl = obj.Placement
- normal,width,height = self.getDefaultValues(obj)
-
- # computing shape
+ normal,length,width,height = self.getDefaultValues(obj)
base = None
- if obj.Base.isDerivedFrom("Part::Feature"):
- if not obj.Base.Shape.isNull():
- if obj.Base.Shape.isValid():
- base = obj.Base.Shape.copy()
- if base.Solids:
- pass
- elif (len(base.Faces) == 1) and (not obj.ForceWire):
- if height:
- norm = normal.multiply(height)
- base = base.extrude(norm)
- elif len(base.Wires) >= 1:
- temp = None
- for wire in obj.Base.Shape.Wires:
- sh = self.getBase(obj,wire,normal,width,height)
- if temp:
- temp = temp.fuse(sh)
- else:
- temp = sh
- base = temp
- elif base.Edges:
- wire = Part.Wire(base.Edges)
- if wire:
- sh = self.getBase(obj,wire,normal,width,height)
- if sh:
- base = sh
- else:
- base = None
- FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object")))
-
- elif obj.Base.isDerivedFrom("Mesh::Feature"):
- if obj.Base.Mesh.isSolid():
- if obj.Base.Mesh.countComponents() == 1:
- sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
- if sh.isClosed() and sh.isValid() and sh.Solids and (not sh.isNull()):
- base = sh
- else:
- FreeCAD.Console.PrintWarning(str(translate("Arch","This mesh is an invalid solid")))
- obj.Base.ViewObject.show()
+
+ # computing a shape from scratch
+ if not obj.Base:
+ if length and width and height:
+ base = Part.makeBox(length,width,height)
+ else:
+ FreeCAD.Console.PrintError(str(translate("Arch","Error: Unable to compute a base shape")))
+ return
+ else:
+ # computing a shape from a base object
+ if obj.Base.isDerivedFrom("Part::Feature"):
+ if not obj.Base.Shape.isNull():
+ if obj.Base.Shape.isValid():
+ base = obj.Base.Shape.copy()
+ if base.Solids:
+ pass
+ elif (len(base.Faces) == 1) and (not obj.ForceWire):
+ if height:
+ normal.multiply(height)
+ base = base.extrude(normal)
+ elif len(base.Wires) >= 1:
+ temp = None
+ for wire in obj.Base.Shape.Wires:
+ sh = self.getBase(obj,wire,normal,width,height)
+ if temp:
+ temp = temp.fuse(sh)
+ else:
+ temp = sh
+ base = temp
+ elif base.Edges:
+ wire = Part.Wire(base.Edges)
+ if wire:
+ sh = self.getBase(obj,wire,normal,width,height)
+ if sh:
+ base = sh
+ else:
+ base = None
+ FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object")))
+
+ elif obj.Base.isDerivedFrom("Mesh::Feature"):
+ if obj.Base.Mesh.isSolid():
+ if obj.Base.Mesh.countComponents() == 1:
+ sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
+ if sh.isClosed() and sh.isValid() and sh.Solids and (not sh.isNull()):
+ base = sh
+ else:
+ FreeCAD.Console.PrintWarning(str(translate("Arch","This mesh is an invalid solid")))
+ obj.Base.ViewObject.show()
base = self.processSubShapes(obj,base)
diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py
index c3d72f30a..ab58b74a9 100644
--- a/src/Mod/Arch/ArchWindow.py
+++ b/src/Mod/Arch/ArchWindow.py
@@ -51,7 +51,7 @@ def makeWindow(baseobj=None,width=None,name=str(translate("Arch","Window"))):
if obj.Base:
obj.Base.ViewObject.DisplayMode = "Wireframe"
obj.Base.ViewObject.hide()
- obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Window")
+ #obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Window")
return obj
def makeDefaultWindowPart(obj):
@@ -77,38 +77,40 @@ class _CommandWindow:
'Accel': "W, N",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from a selected object (wire, rectangle or sketch)")}
- def IsActive(self):
- if FreeCADGui.Selection.getSelection():
- return True
- else:
- return False
-
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
if sel:
- if Draft.getType(sel[0]) == "Wall":
+ obj = sel[0]
+ if Draft.getType(obj) == "Wall":
FreeCADGui.activateWorkbench("SketcherWorkbench")
FreeCADGui.runCommand("Sketcher_NewSketch")
- FreeCAD.ArchObserver = ArchComponent.ArchSelectionObserver(sel[0],FreeCAD.ActiveDocument.Objects[-1],hide=False,nextCommand="Arch_Window")
+ FreeCAD.ArchObserver = ArchComponent.ArchSelectionObserver(obj,FreeCAD.ActiveDocument.Objects[-1],hide=False,nextCommand="Arch_Window")
FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
else:
+ FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Window")))
FreeCADGui.doCommand("import Arch")
- for obj in sel:
- FreeCADGui.doCommand("Arch.makeWindow(FreeCAD.ActiveDocument."+obj.Name+")")
- if hasattr(obj,"Support"):
- if obj.Support:
- if isinstance(obj.Support,tuple):
- s = obj.Support[0]
- else:
- s = obj.Support
- w = FreeCAD.ActiveDocument.Objects[-1] # last created object
- FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+w.Name+",host=FreeCAD.ActiveDocument."+s.Name+")")
- elif Draft.isClone(obj,"Window"):
- if obj.Objects[0].Inlist:
- FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+obj.Name+",host=FreeCAD.ActiveDocument."+obj.Objects[0].Inlist[0].Name+")")
+ FreeCADGui.doCommand("Arch.makeWindow(FreeCAD.ActiveDocument."+obj.Name+")")
+ if hasattr(obj,"Support"):
+ if obj.Support:
+ if isinstance(obj.Support,tuple):
+ s = obj.Support[0]
+ else:
+ s = obj.Support
+ w = FreeCAD.ActiveDocument.Objects[-1] # last created object
+ FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+w.Name+",host=FreeCAD.ActiveDocument."+s.Name+")")
+ elif Draft.isClone(obj,"Window"):
+ if obj.Objects[0].Inlist:
+ FreeCADGui.doCommand("Arch.removeComponents(FreeCAD.ActiveDocument."+obj.Name+",host=FreeCAD.ActiveDocument."+obj.Objects[0].Inlist[0].Name+")")
FreeCAD.ActiveDocument.commitTransaction()
-
+ FreeCAD.ActiveDocument.recompute()
+ else:
+ FreeCAD.Console.PrintMessage(str(translate("Arch","Please select a base object\n")))
+ FreeCADGui.Control.showDialog(ArchComponent.SelectionTaskPanel())
+ FreeCAD.ArchObserver = ArchComponent.ArchSelectionObserver(nextCommand="Arch_Window")
+ FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
+
+
class _Window(ArchComponent.Component):
"The Window object"
def __init__(self,obj):
@@ -122,6 +124,7 @@ class _Window(ArchComponent.Component):
self.createGeometry(obj)
def onChanged(self,obj,prop):
+ print prop
self.hideSubobjects(obj,prop)
if prop in ["Base","WindowParts"]:
self.createGeometry(obj)
@@ -170,6 +173,11 @@ class _Window(ArchComponent.Component):
base = Part.makeCompound(shapes)
if not DraftGeomUtils.isNull(pl):
base.Placement = pl
+ elif not obj.WindowParts:
+ # create default parts
+ obj.WindowParts = makeDefaultWindowPart(obj.Base)
+ else:
+ print "Arch: Bad formatting of window parts definitions"
base = self.processSubShapes(obj,base)
if base:
@@ -188,12 +196,16 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
def updateData(self,obj,prop):
if (prop in ["WindowParts","Shape"]) and obj.ViewObject:
- self.colorize(obj)
+ if obj.Shape:
+ if not obj.Shape.isNull():
+ self.colorize(obj)
def onChanged(self,vobj,prop):
if (prop == "DiffuseColor") and vobj.Object:
if len(vobj.DiffuseColor) < 2:
- self.colorize(vobj.Object)
+ if vobj.Object.Shape:
+ if not vobj.Object.Shape.isNull():
+ self.colorize(vobj.Object)
def setEdit(self,vobj,mode):
taskd = _ArchWindowTaskPanel()
@@ -217,20 +229,22 @@ class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
def colorize(self,obj):
"setting different part colors"
- print "Colorizing ", obj.Shape.Solids
+ solids = obj.Shape.copy().Solids
+ #print "Colorizing ", solids
colors = []
base = obj.ViewObject.ShapeColor
- for i in range(len(obj.Shape.Solids)):
+ for i in range(len(solids)):
ccol = base
typeidx = (i*5)+1
if typeidx < len(obj.WindowParts):
typ = obj.WindowParts[typeidx]
if typ == WindowPartTypes[2]: # transparent parts
ccol = ArchCommands.getDefaultColor("WindowGlass")
- for f in obj.Shape.Solids[i].Faces:
+ for f in solids[i].Faces:
colors.append(ccol)
- print "colors: ",colors
- obj.ViewObject.DiffuseColor = colors
+ #print "colors: ",colors
+ if colors:
+ obj.ViewObject.DiffuseColor = colors
class _ArchWindowTaskPanel:
'''The TaskPanel for Arch Windows'''
diff --git a/src/Mod/Arch/Arch_rc.py b/src/Mod/Arch/Arch_rc.py
index 37b7e01be..28b593b4c 100644
--- a/src/Mod/Arch/Arch_rc.py
+++ b/src/Mod/Arch/Arch_rc.py
@@ -2,8 +2,8 @@
# Resource object code
#
-# Created: Sun Jul 7 11:06:17 2013
-# by: The Resource Compiler for PyQt (Qt v4.8.4)
+# Created: Fri Aug 16 18:34:56 2013
+# by: The Resource Compiler for PyQt (Qt v4.8.5)
#
# WARNING! All changes made in this file will be lost!
@@ -27568,133 +27568,143 @@ qt_resource_data = "\
\x6c\x6c\x61\x64\x61\x20\x73\x75\x70\x70\x6f\x72\x74\x20\x77\x69\
\x6c\x6c\x20\x62\x65\x20\x64\x69\x73\x61\x62\x6c\x65\x64\x2e\x0a\
\x07\x00\x00\x00\x04\x61\x72\x63\x68\x01\
-\x00\x00\x07\xcc\
+\x00\x00\x08\x6e\
\x00\
-\x00\x3d\x0e\x78\x9c\xed\x5b\x6d\x6f\xdb\x36\x10\xfe\xde\x5f\x41\
-\xf8\xd3\x06\x74\xb5\x9d\xb7\x26\x81\xe2\x61\x6d\x9a\x36\x43\xbb\
-\xa5\x73\xd6\x7e\x1c\x68\xe9\x6c\x71\xa1\x48\x8d\xa4\x62\xbb\xbf\
-\x7e\x47\x4a\xb2\x2c\x5b\x52\xe2\xf8\x25\x40\xe0\xa2\x45\x25\x1e\
-\x7d\x77\x3c\xdd\x3d\x77\x47\x4a\xde\xaf\x93\x88\x93\x7b\x50\x9a\
-\x49\x71\xd1\xea\xbe\xe9\xb4\x08\x08\x5f\x06\x4c\x8c\x2e\x5a\x7f\
-\xdf\x5e\xfd\x72\xda\xfa\xb5\xf7\xca\x4b\x58\x31\xe9\x08\x27\xf5\
-\x5e\x11\xcf\xe7\x54\xeb\xde\xc7\x84\x9d\x9f\x5f\x32\xca\xe5\x08\
-\xff\xe7\xa3\x3e\x18\x83\x3f\xd6\xbf\x29\x3f\xf4\xda\xe9\x1c\x9c\
-\x3c\x66\xc1\x08\x0c\x71\xf7\x17\xad\xaf\xdf\xdd\x6d\x8b\x08\x1a\
-\xc1\x45\xab\x89\x87\x15\x45\xbc\x58\xc9\x18\x94\x99\x66\x3f\x18\
-\x81\x8c\xc0\xa8\xa9\x23\x12\x4f\x81\x6f\xdc\x15\xf1\x26\xbd\x8e\
-\xd7\x9e\x64\x37\x53\x7b\x33\xcd\x6e\x50\x03\x13\xf6\x8e\xdf\x1e\
-\x7b\xed\xf4\x32\x1d\x0e\x81\x8d\x42\xd3\x3b\x39\x38\xf3\xda\xd9\
-\xb5\xe3\xd9\xce\x99\x7a\xed\x5c\x78\x95\x26\x63\x26\x02\x39\xbe\
-\x65\x86\x43\xa6\x8c\x36\x0a\x75\xef\x7d\x04\x01\x8a\x72\xa2\xb3\
-\xb5\x78\xed\x8c\xb0\xcc\x92\xd3\xa9\x4c\x0a\xdb\x7c\x7b\x27\x27\
-\x9f\xdd\x50\xc6\x71\x41\xa4\x8e\xa9\x8f\x8c\x5a\xd9\x02\x44\x12\
-\x0d\x40\xf5\x4e\xbc\x76\x76\x95\xaa\x3f\x2f\x61\x89\x45\x44\xd5\
-\x88\x89\x05\x0e\x67\x8d\x1c\x98\x81\xa8\xb0\xe4\xfc\xb3\xfc\xa8\
-\x64\x12\xa3\xce\xf9\xd3\x1c\xe5\xf7\xe9\xf4\x25\xe1\xa6\x30\x56\
-\x85\xbd\xec\x33\x27\xfd\x0a\xa3\x2d\xeb\xd4\x68\xba\x4c\x18\x7a\
-\xad\x61\x3e\xe5\xe9\xe8\x3f\x07\x85\xdc\x62\x41\x15\x8c\x3e\x2d\
-\x31\x0a\xa5\x62\x3f\xa4\x30\x15\xac\x16\x99\x2d\x9b\xe8\x33\x1d\
-\x00\xcf\x39\x71\x7b\x53\xfa\x79\x85\x8d\x60\x62\x4a\x13\x66\x76\
-\xba\x84\x21\x4d\x38\xb2\x96\x5c\x2a\x32\xc4\x7f\x63\xca\xf9\xa2\
-\xa5\xaa\xcd\x95\x0e\xa6\xba\xcd\x29\xdf\x2e\x6b\xbf\xb4\x18\xeb\
-\x70\xa0\x96\xec\xd0\x77\xc3\x8d\xcb\xc0\xb9\x80\x53\x0d\xe2\xc6\
-\xc2\x6a\x00\x5d\xad\xf7\xd5\x9c\x9f\x7f\x9a\xf1\xf3\xda\x6e\xf0\
-\xa1\x05\x2c\xc7\x03\xfb\x01\x9f\x98\xc0\x27\xa5\x4d\x80\xe1\x76\
-\xd1\xea\x2c\x9a\x0e\x67\x94\x46\x72\x34\x38\xea\x94\xc0\x60\x46\
-\xcd\x80\xe0\xa0\x53\xc2\x84\x42\xad\x45\x86\x35\x96\x4e\x0d\xb7\
-\x82\xa5\xcb\x6e\xe3\x60\xf1\x46\xc1\xf0\xbd\x7d\xd6\xef\x12\x63\
-\xd0\x8c\x79\x90\x59\x5a\x8c\x34\xe7\x07\x83\x94\xd6\xe8\x51\x52\
-\xf2\x5b\x16\x57\x3b\xd5\x6d\xc8\x34\xc1\xbf\x26\x04\x12\x2c\x39\
-\x98\x80\x31\xf9\x8e\x4e\x46\xe4\xe0\x5f\x04\xc5\xc7\xfb\xda\x92\
-\x12\x8e\xe7\x82\x0a\x6e\x6c\xc1\xfe\x0a\x82\xde\x41\xf7\xc8\x82\
-\x70\xb0\x40\x1a\x29\x00\x91\x12\xd3\xcb\x32\x79\xc0\x13\x48\xa9\
-\xee\xaa\xfc\xd8\x96\x44\x3d\x4e\x6b\x6b\xe6\x0f\xc2\xa6\x9b\x5a\
-\x0f\xf3\x33\x8b\x58\x33\xb9\xa7\x85\xc2\x9e\x6a\x24\x2b\xee\x86\
-\x9a\xf0\x61\x69\x5f\x64\xd0\xce\xf2\xec\xa6\xa2\xdf\x6b\xa7\x48\
-\x38\x83\xc9\x12\x79\x5d\xd0\x5c\x0b\x32\x37\x06\x98\x48\x48\x7c\
-\x93\x28\x78\x3e\xd4\x7c\x00\xfe\xf7\xb8\xb9\x4b\xdc\x7c\x28\x17\
-\xaf\x87\x9c\xfd\xdc\xdb\x76\x0b\x9f\xdd\xe3\x4e\x3d\x7c\x76\x4f\
-\xce\x1a\xe0\xb3\x7b\x7a\xf2\x4c\xf0\x39\xb3\xd5\x1e\x43\xeb\x0b\
-\xcf\x93\xf5\x0a\xcf\xe3\xcd\x15\x9e\xae\xf7\x79\x46\x10\x3d\xda\
-\x83\x68\xbd\xad\x77\x0d\xa2\x87\x8d\x0f\x63\x15\xe8\x3a\x3c\xac\
-\x47\xae\xa3\xe3\x06\xe0\x3a\x79\x2e\xdc\xfa\xee\x22\x61\x0f\x5a\
-\xf5\xa0\xd5\x3d\x5a\x0f\xb5\x4e\x36\x8c\x5a\x64\x64\x65\x3d\x1f\
-\x74\x35\xa3\xf0\x1e\xba\x76\x0a\x5d\xcd\x79\x64\x15\xe8\x3a\x6b\
-\x80\xae\xee\xe9\x61\x53\xcf\xda\x39\x7c\x56\xf0\xfa\x68\x6d\xb7\
-\x47\xb0\x06\x04\xeb\x3c\x1e\xc1\x0a\x0f\x0c\xc1\xbf\x9b\xdf\x1b\
-\x9d\xb9\x9f\x25\x0c\xe4\xe4\x9f\xd3\xa7\xf7\x1e\xd7\x43\x6c\x3b\
-\xd2\xf6\xc3\xb1\x83\xe0\x35\x19\x87\x20\xc8\x01\xd1\x2c\x62\x9c\
-\x66\x7b\x83\x84\x62\xf3\x31\x00\xfc\x09\xc2\xa0\x10\xd8\x83\xd8\
-\x99\xd8\xb1\x30\x45\x12\x11\x80\xe2\x53\x4b\xd3\x77\x60\x90\x8f\
-\x46\x84\xe4\x1c\xe7\x93\x7f\x25\x13\x10\x10\x84\x08\x49\xa4\x80\
-\xd7\x84\x8a\xc0\x35\x3a\x66\x2c\x33\xce\xd9\x54\x5f\x46\x60\xa7\
-\x3c\xbd\xb5\xa9\x47\xf0\xdf\x51\x8b\x4c\xda\x80\x6a\x98\x53\xd3\
-\x2e\x35\x96\x5a\xb3\x01\x5f\x43\xf2\x0a\x91\x62\x0d\x62\x77\x78\
-\xfa\x99\x0a\x2f\x32\x52\xca\xc4\x12\xaf\xb9\x79\x4f\x38\x0f\x28\
-\xda\xec\xc7\x9d\x08\x5c\x5f\xbd\x27\x2c\x8a\xa5\x32\x9b\x3e\x06\
-\xd8\xdc\x21\xc0\xd9\x56\x30\xe1\x81\x16\xad\x09\x13\x1c\xf3\x14\
-\x16\x30\x6a\x03\xa6\x63\x5c\x14\x09\x60\x90\x8c\x48\x04\x5a\xd3\
-\x91\x8b\x1c\xc6\x21\xb3\xad\x8d\x7c\x6b\xe9\x21\x0e\xad\xb1\x35\
-\x51\x1f\xbf\xfd\x10\xab\xad\xb2\x02\x3b\x09\x56\x36\xf4\x2f\xad\
-\xd4\x17\x19\xa4\xeb\x7b\xee\xf1\x36\x3c\x77\xb3\xb9\x6c\xe6\x96\
-\x69\x9a\xa1\x7c\x4c\xa7\xda\x26\xa6\xd4\x73\x31\x35\x8d\x99\x09\
-\x5d\x46\xc2\x1c\x05\x4a\x50\x4e\xe2\xa9\x09\x25\xa6\x05\xaa\x34\
-\xa8\xd7\x04\xee\x31\x47\xb0\x21\xb9\x1e\xfa\x7f\xc6\x20\xfa\x21\
-\x20\x23\x2b\x46\x68\x34\x05\x87\x60\x1b\x1e\x7f\x25\x95\x0f\x65\
-\x4d\x76\xe2\xf1\x43\x2b\x17\x57\x7a\xe3\x24\xdf\x64\x82\xf7\xde\
-\x5f\xe1\xfd\x87\x5b\xc1\xed\x35\xf6\x91\xdf\x2b\xa0\x06\x3d\xdd\
-\x25\x4b\xed\x1a\x55\xa0\x7e\x98\x1e\x87\xa7\x1b\xc7\xc4\x4c\xe3\
-\xad\x54\x58\x2e\x61\x63\x69\x88\x51\x25\xb0\xed\xc4\x10\x9b\x3a\
-\x59\xbb\xc1\x69\xdf\xad\x1c\xdd\xd6\xa9\xf1\x32\x6b\xaa\xf5\x1d\
-\x76\x85\xed\x93\x15\x1c\xb6\x79\xcf\xae\xde\x63\xae\x1d\x00\x93\
-\x61\xa2\x04\x73\x47\x1b\x3f\xf9\x54\x90\x88\xde\x81\x43\xe3\x48\
-\x06\xc0\x49\x08\xf4\x7e\xfa\xf3\x6e\x72\xbd\xd3\x07\x7d\xe8\x2a\
-\xd7\x68\xef\x46\xd5\x4d\x6c\x77\x2b\x7e\xf4\xc0\xee\xdc\xaa\x89\
-\x1f\x7f\x2d\xec\xeb\x3f\xb3\x4e\x74\x96\xf0\xa9\x26\x3a\x19\x18\
-\x45\x7d\xbb\x37\xa6\x71\x2a\xfa\x9b\x1a\x33\xec\x0b\x6d\x8b\x48\
-\x74\x48\xe3\xa2\x5e\x40\x64\x09\xa6\x24\xa4\xf7\x90\x75\xbb\x33\
-\xc6\x39\x93\xed\x14\x00\x7d\xc0\xac\x8f\xa0\x36\x93\xb7\xab\x82\
-\x37\x17\xfc\xe7\x4c\xee\x3e\x0a\xaa\xa2\x60\x85\x77\xb7\x56\x88\
-\x82\xb7\x1b\x8e\x82\x34\xeb\xdb\x5f\x17\x91\x60\x05\xb2\xc9\x7c\
-\xe9\x6b\xab\xe4\xeb\x4b\x92\xbe\xba\xb7\x0d\x6f\xbe\x71\x22\x67\
-\x7a\xa0\xd8\x0d\x88\x5b\xcd\xaf\x53\x15\xfe\x70\x32\xf7\x4e\x5d\
-\xe3\xd4\x2b\xd4\xb4\x55\x27\x2c\xcd\x9b\xe0\xf5\xee\xf1\x61\xe2\
-\xf3\x24\x00\xc2\x99\x36\xe7\x64\x9b\x27\x2a\x35\x81\xf9\x99\x09\
-\xf8\x10\x30\xb3\x14\x98\x1c\x09\x60\x09\x4f\x0e\xcb\xdf\x6c\x55\
-\x1c\xd1\x5f\x74\x86\xab\x81\x5b\x25\x91\xae\xa1\x24\x58\x2b\x33\
-\xc3\xc0\xed\xb4\x40\x66\x85\xa1\x92\x51\xf5\xae\x55\xbd\x29\x1e\
-\x6f\xec\xf6\x13\x5c\x9e\x53\x1f\x42\xc9\x03\x50\xb7\xf5\xf5\x1c\
-\xa6\x0e\x7b\xe6\xf2\x1a\x2f\xde\x25\x8c\xdb\xd7\xbf\x3f\x70\x88\
-\x70\x85\x37\x4a\x4e\xa6\x76\xfc\x8a\xcb\xf1\x2d\xa8\x88\x09\x7b\
-\xe4\xb4\xa3\x7c\x76\xc7\xe2\x17\x19\xee\xdb\xdb\x64\x9d\xa1\xc0\
-\xe3\x36\x59\x0f\x2e\x89\x02\x7b\x06\x80\x37\x1b\x7f\xdb\xba\x40\
-\xa4\xb5\xd1\xed\xed\x56\x32\xf6\x03\x98\xd7\x04\x0d\x73\xdb\x9a\
-\x4c\x60\xbb\x1e\xb9\xd3\x5a\x12\x24\x96\x4a\x1a\xcc\xba\x82\xff\
-\x3e\xb0\xa9\x9a\x4a\x00\xf5\x1c\xbb\xab\x56\x81\x6f\x7f\x7d\xd9\
-\xef\xb0\xd6\xbb\xec\xe9\x7a\xf9\xf8\xa9\xbd\xf9\x7b\xd4\x92\x62\
-\xe7\xa3\x89\xcd\x7f\xb6\xac\xf4\xef\x04\xba\x06\x51\xd6\x43\x9f\
-\xef\x8d\x87\xe6\xf5\xec\xdf\x78\xd8\xc8\x1b\x0f\x97\x32\x19\x70\
-\xe8\xc7\x4c\x54\xe1\x5e\xe0\xa8\x1a\xa9\x6b\xed\xd5\xf7\x63\xf0\
-\xd9\xd0\x16\x3e\x16\x85\x22\x2a\xa6\xc4\x30\xdb\x1c\xd8\x76\xe4\
-\x9e\xc1\xd8\xd5\x49\x25\xdf\x8b\x12\x2c\x9b\xb0\x7d\xa1\x71\xcc\
-\x19\x92\xb1\x62\xf2\xd1\x4f\xed\xac\x35\xf0\xea\x9e\xf2\x04\x16\
-\x74\x4c\xd7\xd8\x3b\x78\xd3\x29\xff\xf1\xda\x19\x65\x9b\xa8\x88\
-\xb1\x67\xab\xd1\xdb\x7c\xdd\x2f\x12\x19\x57\xaf\x5d\x4a\xc0\x90\
-\xd7\x08\xe5\xcf\x87\x1e\x83\x07\x05\x14\x7c\xcb\x78\x94\x80\x60\
-\xb9\x5e\x59\x21\xfc\xcb\x91\x9f\x05\xfd\xc1\x52\xd0\xe7\xf1\x7e\
-\xb4\x14\xef\xa5\x50\x5f\x54\xa5\x14\xe0\x85\x91\xe6\x2c\x39\x67\
-\xc6\x2c\xd5\xe4\x6f\x93\x67\x9f\xfb\x5d\xb4\x4e\x5a\x24\xfd\x6e\
-\xef\xa2\xd5\xed\xb6\x6c\x2b\xe0\xc5\x6c\x12\xd1\x78\x98\x08\xb7\
-\x1d\xd6\xfb\xef\xc6\xdd\x5f\x61\x0f\xf2\x05\x03\xb2\x2f\x13\xe5\
-\x03\xea\x52\x9e\x65\x3f\xdd\xc4\x70\x94\x51\x2a\x51\x3b\x4d\xe6\
-\x47\x52\x2d\xe7\x3e\xef\x9c\x7b\x8f\xaa\xf8\xa4\xd3\x3e\x8f\x89\
-\xc1\x12\x44\xf7\xbe\xde\x24\x3a\xcc\xe9\xf9\xe0\xab\xd4\x5c\x14\
-\x4b\x14\xcb\xa5\x9d\x7e\xf2\xa9\xdf\x84\xd6\x72\x6e\xd4\x59\x60\
-\x51\x70\xb3\x26\x0b\x6f\x75\x55\x6a\xb3\xac\x72\x9d\x4a\x96\xdb\
-\xe6\xd4\xca\xaa\xcd\x6a\x0b\x15\xd4\x9d\x28\x93\xf7\xc4\xd5\xca\
-\x14\xd4\x9d\x28\x53\x4a\x4a\xd5\x1a\x2d\x4c\x59\x5f\xad\xf2\x80\
-\xfb\x04\x59\x81\x76\x01\xa1\x5d\xe8\x64\x6f\x42\xd9\x5d\x64\xbc\
-\xf7\xda\x09\xeb\xbd\xfa\x1f\x60\x53\xb8\xc3\
+\x00\x4d\x6d\x78\x9c\xed\x5c\xeb\x73\xd3\x38\x10\xff\xce\x5f\xa1\
+\xc9\x67\x20\x8f\x3e\x68\x3a\x6e\x18\xa0\x14\xb8\x81\xbb\x72\xed\
+\x71\x1f\x6f\x14\x7b\x13\xeb\x90\x2d\x9f\x24\x37\x09\x7f\xfd\xad\
+\x64\xe7\x61\xc7\x71\x1a\xe7\x45\x4a\x32\x30\xb5\x25\x79\x77\xb5\
+\xfe\xed\x4b\x96\xed\xbc\x1e\x06\x9c\x3c\x80\x54\x4c\x84\x57\xb5\
+\xe6\xcb\x46\x8d\x40\xe8\x0a\x8f\x85\xfd\xab\xda\x5f\xf7\x37\x2f\
+\x2e\x6a\xaf\x3b\xcf\x9c\x98\x4d\x07\x9d\xe2\xa0\xce\x33\xe2\xb8\
+\x9c\x2a\xd5\xf9\x10\xb3\xcb\xcb\x6b\x46\xb9\xe8\xe3\x5f\xde\xbf\
+\x03\xad\xf1\x62\xf5\x46\xba\xbe\x53\x4f\xc6\xe0\xe0\x01\xf3\xfa\
+\xa0\x89\x3d\xbf\xaa\x7d\xfd\xdb\x9e\xd6\x48\x48\x03\xb8\xaa\x95\
+\xd1\x30\xac\x88\x13\x49\x11\x81\xd4\xa3\xf4\x82\x3e\x88\x00\xb4\
+\x1c\xd9\x4e\xe2\x48\x70\xb5\x3d\x22\xce\xb0\xd3\x70\xea\xc3\xf4\
+\x64\x64\x4e\x46\xe9\x09\x4a\xa0\xfd\xce\xd9\xab\x33\xa7\x9e\x1c\
+\x26\xcd\x3e\xb0\xbe\xaf\x3b\xe7\xad\xb6\x53\x4f\x8f\x2d\xcd\xfa\
+\x98\xa8\x53\x1f\x33\x2f\x92\x64\xc0\x42\x4f\x0c\xee\x99\xe6\x90\
+\x0a\xa3\xb4\x44\xd9\x3b\x1f\x20\x04\x49\x39\x51\xe9\x5c\x9c\x7a\
+\xda\x31\x4f\x92\xd3\x91\x88\xa7\xba\xf9\xf6\x56\x0c\x3f\xdb\xa6\
+\x94\x62\x8e\xa5\x8a\xa8\x8b\x84\x6a\xe9\x04\xc2\x38\xe8\x82\xec\
+\x9c\x3b\xf5\xf4\x28\x11\x7f\x96\xc3\x1c\x89\x80\xca\x3e\x0b\x73\
+\x14\xda\xa5\x14\x98\x86\x60\xaa\xc9\xd9\x7b\xf9\x41\x8a\x38\x42\
+\x99\xc7\x77\xb3\x3f\x3e\x4f\x86\xcf\x31\xd7\x53\x65\xcd\xe8\xeb\
+\x1a\x7a\x34\xe6\xba\x50\x5f\xf3\xe2\x94\x6a\x2d\xe5\x83\x80\xd5\
+\xcc\xa5\x3c\x69\xfd\xa7\x35\x65\x39\x9d\x4b\x01\xa1\x8f\x73\x84\
+\x7c\x21\xd9\x0f\x11\xea\x02\x52\x79\x62\xf3\xda\xf9\x4c\xbb\xc0\
+\xc7\x94\xb8\x39\xc9\x5c\x5e\xa0\x1e\x18\xea\xcc\x80\x89\x8a\xfe\
+\xa6\x9c\xe7\xd4\x52\xac\x9b\xa4\x31\x11\x64\x46\xd2\x7a\x56\xd4\
+\x39\xc9\x0d\xb0\x40\xce\x4d\xfa\xce\x36\x97\xca\x8c\x63\x01\x87\
+\x6a\xf4\x0f\x39\xd1\x01\x21\xd5\xf9\xaa\x2f\x2f\x3f\x4e\xe8\x39\
+\x75\xdb\xb8\x6c\x02\xf3\xb8\x67\x3f\xe0\x23\x0b\xf1\xb6\x28\xed\
+\x21\x4c\xae\x6a\x8d\xbc\x9e\x70\x44\xa6\x65\x6c\xf5\xa7\x8d\x8c\
+\xd1\x4f\x7a\x53\x83\x6f\x35\x32\xb6\x3f\x15\x2b\x4f\x70\x81\xa6\
+\x13\xc5\xad\xa0\xe9\xe5\x18\x69\x36\xaa\x82\xc4\x4c\xf3\x72\x9b\
+\x30\xc9\x0a\x6f\x7d\xf7\xad\x84\xde\xb5\x88\xbb\x1c\xee\x22\x16\
+\xce\xfa\x02\xd3\x1b\x61\xaf\x67\x7b\x15\xf6\x76\xc5\x70\x89\x05\
+\x04\x74\xc8\x82\x38\xc8\xcd\x2f\xa1\xd0\x69\xe3\xef\x65\xfb\xa2\
+\x3d\xf9\xbd\xba\x68\x39\xf5\xb4\x73\x65\x4c\x3d\x50\x1e\x43\x31\
+\xa3\x56\xa3\xf1\xb2\x91\xfd\x55\xe7\x63\x54\xf0\x3e\x34\x11\x6b\
+\x21\x78\xdd\x19\x2b\xb7\x37\x11\xa3\xe7\x23\x6f\x62\x21\xbb\x5b\
+\xaa\xfd\xe5\xdc\xbe\x08\xaf\x9e\x86\xea\x5d\x21\xa6\x08\xee\x17\
+\x15\xd1\xfe\xd1\x5a\xed\xcf\x0e\xf7\x93\x03\x80\xfb\x49\x63\x8f\
+\x78\x4f\x6e\xe3\xaf\x04\xf8\x76\x45\xc0\xbf\x13\x5c\xc8\x7d\xe0\
+\xdd\x32\x7e\x1b\x6b\x8d\x21\x3e\x8f\x76\xd7\xf4\x75\x93\xbe\xd2\
+\x69\x09\xc1\xef\x59\x54\x3c\xb3\x7b\x9f\x29\x82\xff\xb4\x0f\xc4\
+\x4b\x93\x41\x4b\x98\xf4\xf0\x7f\x08\x03\x62\x90\x42\x44\xf7\x5f\
+\x4c\xcc\xf3\xe9\xe1\x0a\x50\xb1\x34\xf3\xe0\x30\x6d\xb9\xdc\x40\
+\x82\xd7\x69\x35\x4f\x4d\x21\xe0\xe5\xba\xfa\x12\x20\x4c\x3a\x93\
+\xc3\x6c\x77\x17\x8d\x2c\xe9\xb5\x47\xd9\x94\x62\x8e\xd5\x56\x0c\
+\xca\xde\xad\x43\xb5\x27\xa7\x9e\xa4\xe4\x93\x7c\x3d\xd3\xbd\x6e\
+\xf6\xbe\x56\xee\x5e\xd1\x6a\xef\xb4\x8c\x5d\x1d\x4b\xd8\x5b\xfa\
+\xbe\x24\xe5\x3a\x26\xf0\x1b\x4f\xe0\xab\x56\x79\x9f\x21\xec\xff\
+\xfc\x19\xfc\xe9\x01\xa4\x34\xcd\x3d\x65\x34\x13\x6b\x4f\x6e\xe5\
+\xa1\xba\xe1\x4a\xa8\x2f\x4f\x75\x0f\xbc\x6c\x3d\x3b\x82\x7e\x39\
+\xe8\x7f\xb9\xda\xb5\x59\xee\x0b\x0f\xbd\x78\x3d\x3f\x0c\xd0\xef\
+\x19\xf5\xbf\x5e\x05\xdb\x6c\x3e\xd1\x12\x76\xd9\xfa\xfc\x7a\x45\
+\xec\x04\x31\xbb\xad\x64\x9b\x67\x8d\xc5\x95\x6c\xf3\xbc\x5d\x52\
+\xc9\x36\x2f\xce\xf7\x54\xc9\x4e\x74\x75\x2c\x67\x17\x3f\x8c\x9a\
+\xf5\xcf\x15\xcc\xb8\x3c\xa7\x29\x4b\xd8\xcc\x83\xcf\xfd\xd5\xb3\
+\xe5\x41\xf7\x58\xcf\x6e\xba\x9e\x2d\x4f\x03\x16\xe3\xe4\x46\xe2\
+\x80\xc4\x07\xfe\xcc\x3e\xbf\xbc\x6e\x59\xc5\xd3\x9e\x9c\x2c\x76\
+\xb4\xa7\x67\x25\x7e\xf6\x7c\x5f\x6e\x36\x31\xe5\x83\xf6\xb1\x95\
+\x12\x98\xaa\xae\xef\x83\xa1\xf9\xf3\x43\xba\xdc\x43\xae\x02\xe9\
+\x76\x09\xa4\x9b\x17\x27\x65\xab\xe0\x8d\x93\xbd\x82\xda\xde\xaa\
+\x83\x46\xf6\x96\xb3\x87\xcc\x3e\x83\x47\x23\xd0\x07\xf7\x7b\x51\
+\xe5\xe8\x9a\x0e\x53\x34\x2e\x79\x9e\x5b\x96\x42\x7f\xea\x61\xf6\
+\x9c\x64\xd1\x96\x1c\x78\xcf\xc9\xc0\x87\x90\xb4\x88\x62\x01\xe3\
+\x54\x92\x01\xe5\x5c\x11\x8a\x39\x74\x17\xf0\x12\x34\xc5\x30\xc4\
+\x54\xda\x8c\xc4\xc4\x9b\x49\x12\x87\x1e\x48\x3e\x32\x7d\xea\x3b\
+\x68\xa4\xa3\xc8\x80\x71\x8e\xe3\xc9\xbf\x82\x85\xe0\x11\x8c\xdb\
+\x82\x88\x10\x9e\x13\x1a\x7a\x36\x5f\xd7\x03\x91\x52\x4e\x87\xba\
+\x02\x23\x17\x0e\xa9\x9e\xa1\x2f\xf6\x21\xbf\xa1\x14\x29\xb7\x2e\
+\x55\x30\x23\xa6\x99\x6a\x24\x94\x62\x58\xbb\x56\xe7\xbc\x82\xa5\
+\x18\x85\x98\x67\x46\x77\xa9\x08\x4f\xd2\x52\xb2\x9d\x19\x5a\x33\
+\xe3\x2a\xec\x72\x9b\x56\x8b\x8f\xdb\xe7\xf6\xe9\xe6\x1d\x61\x41\
+\x24\xa4\xde\xf4\x0e\xb7\xcd\xed\x6f\x6b\x6f\xc5\x27\x2c\x09\xb7\
+\x65\x3e\xc1\x12\x4f\xdc\x02\x5a\xad\xc7\x54\x84\x93\xc2\x02\xbb\
+\x1b\xf7\x49\x00\x4a\xd1\xbe\xb5\x1c\xc6\x21\xd5\xad\xb1\x7c\xa3\
+\xe9\x1e\x36\xad\x51\x61\x97\x3c\xd1\xf3\xc5\x20\x27\xc0\x4e\x8c\
+\x95\xf5\xdc\x6b\xc3\xf5\x49\x1a\xe9\xfa\xc8\x3d\xdb\x06\x72\x37\
+\x1b\xcb\x26\xb0\x4c\xc2\x0c\xe5\x03\x3a\x52\x26\x30\x25\xc8\xc5\
+\xd0\x34\x60\xda\xb7\x11\x09\x63\x14\xc8\x90\x72\x12\x8d\xb4\x2f\
+\x30\x2c\x50\xa9\x40\x3e\x27\xf0\x80\x31\x82\xf5\xc8\xa7\x9e\xfb\
+\x47\x04\xe1\x9d\x0f\x48\xc8\xb0\x09\x15\xaa\x82\x83\xb7\x0d\xc4\
+\xdf\x08\xe9\x42\x56\x92\x9d\x20\xbe\x67\xf8\xe2\x4c\x6f\x2d\xe7\
+\xdb\x94\xf1\x11\xfd\x05\xe8\x3f\xd9\x8a\xdf\x5e\x63\x39\xf4\x9d\
+\x04\xaa\x11\xe9\x36\x58\x2a\xbb\x06\x0a\xd4\xf5\x89\x51\x6b\xba\
+\xfe\x49\xf4\x28\xda\x4a\x86\x65\x03\x36\xa6\x86\x68\x55\x21\x84\
+\x1a\x4d\x6c\x64\x79\xed\xc6\x4f\xbb\x76\xe6\x08\x5b\x2b\xc6\xd3\
+\xcc\xa9\x36\x50\x7d\x34\xb7\x82\xd8\x25\x6b\x55\xab\x7a\x6c\xbc\
+\x3a\x34\xaf\x24\x4c\x4a\x88\x89\xa7\xa6\x8a\xa8\xb8\xab\x25\x75\
+\xcd\x4a\xa3\xc2\xa1\xe8\xb6\xe5\x80\x61\x42\x6f\x72\x7b\xa2\x7c\
+\x1a\x4d\x1d\x3d\x42\xc2\x1b\x11\x9f\x3e\x40\x5a\xa6\x4c\x08\x8f\
+\x89\x6c\xc7\x73\xdf\x01\xba\x6b\x44\xe3\x84\xdf\xae\x32\x95\x31\
+\xe3\x3f\x26\x7c\x8f\x56\x50\x64\x05\x2b\xbc\x4f\xb2\x82\x15\xbc\
+\xda\xb0\x15\x24\xee\xda\x5c\x3d\xb5\x04\xc3\x90\x0d\x67\x73\x16\
+\x93\xde\x7c\xba\x26\xc9\x9b\x44\xdb\x40\xf3\xad\x65\x39\x91\x03\
+\xd9\x6e\x80\xdd\x6a\xb8\x4e\x44\xf8\xdd\xf2\x3c\x82\x7a\x01\xa8\
+\x57\x48\x46\x8a\x56\x67\xab\x6e\xaa\x78\x3f\x74\x79\xec\x01\xe1\
+\x4c\xe9\x4b\xb2\x87\xe5\xd9\xcf\x2c\x84\xf7\x1e\xd3\x73\x86\xc9\
+\xb1\x03\x4c\x47\x65\xb3\x7c\x63\xd2\x99\x80\xbe\x50\xa9\x5f\xf5\
+\xec\x2c\x89\xb0\x95\x00\xc1\x24\x87\x69\x06\xb6\x44\x86\x54\x0b\
+\x3d\x29\x82\xe2\xe5\x86\xc5\xaa\x78\xbc\xb2\xeb\x15\x20\xcf\xa9\
+\x0b\xbe\xe0\x1e\xc8\xfb\x85\xf7\x10\x67\x63\x9f\xf2\x3d\xc7\x83\
+\xb7\x31\xe3\xe6\x6d\xd4\xf7\x1c\x02\x9c\xe1\xad\x14\xc3\x91\x69\
+\xbf\xe1\x62\x70\x0f\x32\x60\x58\x1f\xd9\xf3\x58\x86\x4c\xf9\xd3\
+\x91\x3b\x0b\x72\xdf\x59\x74\xf4\x01\xc5\x3e\x60\xcd\x67\xd3\x4b\
+\x22\xd8\x62\xfc\x58\xc0\x9b\xec\x0c\x63\x84\x0f\x6a\x1f\x4f\x69\
+\x96\xba\x81\x75\xea\xaa\x12\x47\x80\xe1\xd7\x56\x39\x18\x8c\xa9\
+\x26\x41\x8c\xcd\xb9\x8c\x35\xd1\xc9\x1a\xe6\xf1\x48\x13\xde\x9b\
+\x45\xbe\x51\x5f\x70\x8a\x4f\xd2\x26\xb7\xb7\x8c\x3d\x09\xd7\x8f\
+\x5b\xc6\x6e\x5d\x13\x09\xe6\x29\x0b\x9e\x6c\xfc\x55\xed\x69\xea\
+\xb0\xb6\x0b\x7a\xb5\x95\xd4\x7a\x49\x72\x52\x66\xba\x33\x0b\xc7\
+\x2c\xec\x09\x19\xd8\x4d\x2a\xc4\x8b\x4d\x2f\x29\x51\xeb\x0a\xf8\
+\x5d\xb2\x6c\x9d\x70\x00\xb9\x8f\xf5\x6b\x23\xc0\xb7\x3f\xbf\x1c\
+\xd7\xb0\x17\x43\xf6\x62\xbd\xa0\x59\x75\x07\xfe\x3b\x94\x92\x4a\
+\xc0\x00\x61\x22\x94\xa9\xff\xdc\xef\x21\x42\x83\x48\x83\xd0\xfd\
+\x6d\xf4\x2a\x9f\xcf\x71\xa3\xd7\x3a\x1b\xbd\xaa\x6c\x08\x5f\xc3\
+\xf5\x45\xe0\xb2\x9e\xa9\x50\x8c\x17\x0a\x68\x38\x22\x9a\x05\x90\
+\xec\x96\x7d\x60\x30\xb0\x79\x4c\x06\x7b\xe3\xfc\x85\x46\x11\x67\
+\xd8\x8d\xa5\x8d\x8b\x38\x35\xa3\xd6\xf0\x57\x65\x6f\xfd\xef\x65\
+\x1b\x39\xda\x9e\xc9\x17\xef\xc7\xf3\xfe\x25\x3c\x63\xc6\xec\xc7\
+\x19\xc0\xdc\xc7\x46\x1e\x69\xf0\x53\x73\xff\x96\x52\xca\x1b\x7b\
+\xd1\x8c\x56\x34\xf4\x39\x33\x4f\x8d\xbc\x55\x64\xe4\x63\x13\x3f\
+\x2d\x32\xf1\xbc\x81\x17\x08\x97\x37\xee\xd5\xf3\xc0\x99\x41\x33\
+\x23\xd2\x88\x34\xde\x9d\x9e\x7e\x4d\xe8\xaa\x76\x5e\x23\xc9\x67\
+\x81\xae\x6a\xcd\x66\xcd\x94\xf6\x4e\xc4\x86\x01\x8d\x7a\x71\x68\
+\x97\xb7\x3b\xff\xdd\xda\xf3\x1b\x29\x82\x2f\x68\xb7\x77\x22\x96\
+\x2e\xa0\xe4\xd9\x51\xe6\xcb\x50\x68\xb5\x22\x48\x38\x2a\x2b\xc9\
+\x6c\x4b\x22\xe5\xcc\xd7\xa3\x66\x36\xb4\x4d\xbf\x18\x65\x6e\xe9\
+\x50\x63\xa6\xa2\x3a\x5f\x6f\x63\xe5\x8f\xfb\xc7\x8d\xcf\x12\x15\
+\x53\xcc\x64\x0c\x95\x7a\xf2\x45\x29\xf5\xd2\x37\xda\xb6\xad\x56\
+\x03\x79\xc6\xe5\x92\xe4\xb6\xd7\x15\x4a\x33\x2f\xf2\x22\x91\x0c\
+\xb5\xcd\x89\x95\x26\xa5\xc5\x1a\x9a\xf6\xee\x44\x98\x71\x71\x5b\
+\x2c\xcc\xb4\x77\x27\xc2\x64\x62\x57\xb1\x44\xb9\x21\xeb\x8b\x95\
+\x6d\xb0\x5f\x38\x93\xa0\xac\x41\x28\x6b\x3a\xe9\x96\x34\xf3\x54\
+\x08\xcf\x9d\x7a\xcc\x3a\xcf\xfe\x07\xb7\xee\x27\xe9\
\x00\x00\x07\x4c\
\x00\
\x00\x29\xd1\x78\x9c\xed\x59\x5b\x8f\xe2\x46\x16\x7e\xef\x5f\xe1\
@@ -31365,6 +31375,116 @@ qt_resource_data = "\
\x55\x4c\x69\x8a\x07\xe9\x7b\x88\xe6\x87\xfa\x1b\xc0\x5e\xa3\xb6\
\x8e\x99\x2c\x6e\xae\xae\x6d\x7d\x71\x73\xf5\x1f\x81\x50\x39\x69\
\
+\x00\x00\x06\xbf\
+\x00\
+\x00\x19\x91\x78\x9c\xed\x57\xdd\x6f\xe3\x44\x10\x7f\xef\x5f\x61\
+\x7c\x2f\x20\x62\x7b\xbf\x6c\xef\xba\x49\x11\xe2\x04\x42\x02\x21\
+\xc1\x9d\x78\x3c\x6d\xec\x4d\x62\xea\xd8\xd1\xda\x69\x92\xfe\xf5\
+\xcc\xfa\xdb\x8d\xdb\xde\x01\xc7\x0b\x38\x6a\x13\xcf\xc7\xce\xce\
+\xcc\x6f\x66\x67\x97\xdf\x9c\xf7\x99\xf5\xa0\x74\x99\x16\xf9\xca\
+\xc6\x2e\xb2\x2d\x95\xc7\x45\x92\xe6\xdb\x95\xfd\xfe\xdd\xf7\x0e\
+\xb7\xad\xb2\x92\x79\x22\xb3\x22\x57\x2b\x3b\x2f\xec\x6f\xee\x6e\
+\x96\x5f\x38\x8e\xf5\x9d\x56\xb2\x52\x89\x75\x4a\xab\x9d\xf5\x63\
+\x7e\x5f\xc6\xf2\xa0\xac\x2f\x77\x55\x75\x88\x3c\xef\x74\x3a\xb9\
+\x69\x4b\x74\x0b\xbd\xf5\xbe\xb2\x1c\xe7\xee\xe6\x66\x59\x3e\x6c\
+\x6f\x2c\xcb\x02\xbb\x79\x19\x25\xf1\xca\x6e\x15\x0e\x47\x9d\xd5\
+\x82\x49\xec\xa9\x4c\xed\x55\x5e\x95\x1e\x76\xb1\x67\x0f\xe2\xf1\
+\x20\x1e\x1b\xeb\xe9\x83\x8a\x8b\xfd\xbe\xc8\xcb\x5a\x33\x2f\xdf\
+\x8c\x84\x75\xb2\xe9\xa5\xcd\x6e\x4e\xb4\x16\xc2\x42\x08\x0f\x11\
+\x8f\x10\x07\x24\x9c\xf2\x92\x57\xf2\xec\x4c\x55\x61\x8f\x73\xaa\
+\x04\x21\xe4\x01\x6f\x90\xfc\x38\xa9\xe8\x9c\x41\x28\x9e\xdd\x4c\
+\xcd\x1d\x5b\x87\xf0\x1f\xe0\xaf\x57\xe8\x08\x6e\x59\x1c\x75\xac\
+\x36\xa0\xa9\xdc\x5c\x55\xde\xdb\x77\x6f\x7b\xa6\x83\xdc\xa4\x4a\
+\x46\xcb\x74\xd1\x9f\xd8\x9d\xa4\x24\x97\x7b\x55\x1e\x64\xac\x4a\
+\xaf\xa3\xd7\xfa\xa7\x34\xa9\x76\x2b\x3b\x60\x87\x73\xfd\xbe\x53\
+\xe9\x76\x57\x8d\x08\x69\xb2\xb2\xc1\x43\xc2\x03\x54\xbf\x77\x7b\
+\x88\x7a\x24\x21\x97\x92\x46\xb4\x5d\x78\xcc\x62\xdc\x65\x96\x16\
+\x82\x8a\xa9\x76\x52\xc4\x66\x4b\x2b\xfb\x5b\x1d\xef\x3e\xfc\x66\
+\x76\xe6\x76\x81\xec\xd7\x29\x8e\xd5\xe1\x58\x7d\x50\xe7\x4a\xe5\
+\xcd\x82\xe0\xca\xc8\xaf\x9a\x6d\xd4\xdc\x89\x4f\x23\x8c\x63\xfb\
+\x0e\x28\xcb\x44\x6d\x4a\xc3\x69\xdc\x31\x6f\xe0\x0f\xa9\x79\xc0\
+\x85\x9c\x28\xa9\x7f\xd0\x32\x49\x01\x89\x8d\x5c\x23\x39\xe5\x50\
+\x1a\x86\xad\x0e\x68\x95\x55\x71\xe8\x64\xdb\x30\x01\x05\x64\x1a\
+\x4f\x9b\xa7\xd8\x6c\x4a\x05\xe1\x44\x23\x5a\x59\x5d\x32\xd5\x48\
+\x3b\x71\x91\x15\x3a\x7a\xb3\x91\x9b\x0d\x59\xdf\xd6\xa4\x02\x62\
+\x91\x56\x97\x08\xdf\xda\x96\xf7\xaa\x35\x8e\x67\xac\xe1\x57\xac\
+\x6d\xa4\x44\xe8\x59\x6b\x4b\x6f\xea\x76\x4b\xed\xb3\x72\x80\xf0\
+\x1e\x54\x6c\x2a\xb2\x33\xd3\xa7\xb5\xba\x18\x10\x4e\x45\x69\xd2\
+\x6f\x67\x40\xc8\xe1\xc3\x19\xa2\x62\x45\x16\x25\xf0\x0f\xcf\x4a\
+\x5c\x1a\x09\x0c\x45\x06\x5f\x68\x56\xe6\xd1\x40\xf5\x85\x65\xda\
+\x1d\x38\x85\x4e\xb7\x29\x40\xa2\x96\x23\xd8\xa5\xf5\x33\xd5\x81\
+\xa0\x8e\x7c\x03\x84\xf0\x21\x26\x26\x16\x32\xbb\xc2\x48\x67\x06\
+\x22\x9b\x81\xda\xca\x96\xd9\x49\x5e\xca\x7e\xcd\xba\xde\xa3\x9d\
+\x56\xd0\x9f\xde\x5c\xa3\xc9\x99\x5a\x9f\x1a\xa1\x48\xf8\x4e\xd0\
+\x0b\x6c\x5b\xf2\xfb\x3c\xad\xa0\x19\x1d\x4b\xa5\xeb\xb2\xf9\x25\
+\x7f\x5f\xaa\x2b\xa9\x77\x5a\xe6\x25\x74\x8f\xfd\xca\xde\xcb\x4a\
+\xa7\xe7\x2f\xa1\xe1\x53\x9f\x84\xdc\x5f\x20\x97\x50\x81\x21\xac\
+\x7c\x01\x9d\x84\x09\x4c\xa0\x37\xd1\x05\x71\x31\x09\x38\x23\x6c\
+\xe1\x70\xea\x22\x82\xfc\x20\x58\x38\x04\x23\x17\x0b\x5f\xf8\x5f\
+\xf5\x36\x62\x48\x1d\xa6\xbe\x4b\x39\x84\x70\xa0\x42\xba\x44\xe8\
+\xd2\x40\xf8\x10\xb8\x8e\xba\x99\x95\xdd\xcc\xca\x6a\x10\x15\x2e\
+\x0b\x42\x46\x83\x21\xf2\x9f\x52\x9d\x0e\xfe\x98\xfa\x74\xe6\x6a\
+\xe6\x33\x56\xa8\x83\xfe\xad\x1a\xfd\x0c\x28\xc5\x8c\xbd\x80\x51\
+\x86\x11\xff\xe7\x10\xba\x40\xe6\xe3\x06\x82\xfb\x44\x30\xf8\x4d\
+\x10\x71\x39\x14\x22\x9d\x82\x8f\x10\xdf\x25\x01\x43\x64\x02\xbe\
+\x20\x24\x6e\x28\x42\x1a\x4c\xc0\x77\x2d\xbb\x99\x95\x05\xf0\x51\
+\xe6\x52\xe6\x63\xce\x5f\x05\xdf\x6b\x01\x9d\x41\xa7\x89\xe3\x33\
+\x58\x99\x4d\xbf\x79\xae\xd2\xff\x32\x6c\x7b\xcc\x61\x16\x3c\x8f\
+\xcc\x8f\xb4\x86\xe6\xac\xe1\x79\x6b\xfc\xaf\xe1\x72\x12\xf2\x97\
+\xb3\x33\x9f\xc9\xf9\xac\xcf\x23\xe4\x6f\xc2\xee\xe3\xb0\x3d\x57\
+\x20\x94\x7d\x7a\x9d\x3d\x87\xaf\x26\xcc\x4b\xcf\x4c\x30\xf5\xaf\
+\xfe\xe0\x35\xc3\x54\xf2\x90\xaa\xd3\x30\xe6\xac\x65\xbf\xb3\x83\
+\xdc\xaa\x3a\xd7\x60\xb7\x49\x76\xcb\x58\x17\x3a\x51\xba\x63\x05\
+\xf5\x33\x61\xb5\x70\x68\xee\x0b\x37\xd3\xdd\x99\x55\x7b\x3e\x9a\
+\xe7\x97\x3b\x99\x14\x27\x48\xc8\x53\xe6\x63\x51\x40\x0a\xa8\xcb\
+\xb9\x40\x3c\xa4\x4f\xd9\x75\x12\xa9\x1b\xc0\x98\x46\xaf\x74\x4d\
+\xde\x71\x00\xc7\x52\x88\xc4\x35\xf3\xa8\x35\x04\xd4\xc9\xe4\x45\
+\x81\x53\xf5\x57\x87\xdb\x72\x57\x9c\xb6\xda\x04\xa7\xd2\x47\xf5\
+\x54\x13\x66\xd2\xa3\xb9\x8b\x38\xc7\x26\xc9\xed\x04\x3c\x92\x30\
+\xba\xce\x7a\x5d\x9c\xe7\x17\x38\xa5\x39\x38\xeb\xb4\x33\x35\x16\
+\xe4\x2a\x24\xad\x44\x37\x65\x63\xe4\x87\xcf\x88\x9c\x87\xda\x7e\
+\xca\xba\xcc\xb0\x8a\xf5\x1f\x00\x14\xe7\x20\xab\x1d\xec\x7c\x23\
+\xb3\xf2\x6a\x77\x65\x2e\x0f\x4e\x5e\x24\xaa\x9c\xdf\x7d\xbb\xc4\
+\x0b\x12\xad\xfd\xbd\x3c\xa7\xfb\xf4\x51\x25\xa6\x21\xb4\x90\xdc\
+\xab\x4a\x26\xb2\x92\x03\xfc\x3a\x0a\xd4\x91\xdf\x4d\xda\x70\x0b\
+\x8b\x7e\x7d\xfb\x7d\xdf\x99\xe2\x38\xfa\xbd\xd0\xf7\x43\x53\x31\
+\x02\x72\x0d\x83\xfd\xca\xee\xbb\xa5\x99\xdf\xe3\xc8\x94\xac\xac\
+\xee\xd2\x3d\x80\xca\x5c\xb9\xbe\x86\x9b\x0f\x14\x42\xcf\x98\x08\
+\x9b\x31\x74\x58\xb4\x59\x56\xab\xe6\x4a\x35\x7b\x0b\x4d\xe2\x7d\
+\x6a\x94\xbc\xdf\xaa\x34\xcb\x7e\x34\x46\x46\x1d\xb4\x5d\x34\xad\
+\x32\x75\x57\xdb\x6c\x7e\x76\x5e\x78\xad\x1b\x5d\x0b\x1c\x79\xb9\
+\xf4\xba\x30\xd4\x6f\xdb\x21\x3c\x13\x5c\xf6\x11\xce\xe4\x5a\x65\
+\x2b\xfb\x27\xc3\xb4\xae\xb8\x5b\x5d\x1c\x0f\x7b\xc8\x4f\xab\xde\
+\x85\xd5\x64\xbd\x1f\xc5\x9b\xf6\xde\x76\x76\x54\x3f\xb7\x1b\x70\
+\x6a\xd4\xe6\x75\x71\xaf\xa2\x37\xdc\x37\x9f\xf6\xb5\x01\x6d\xc4\
+\xba\x57\xd3\x9d\xc0\x66\xb4\x3e\x56\xd5\x98\xf6\x47\x91\xe6\x11\
+\x6c\x23\x4f\x3a\x2a\x04\x4e\xe9\x0c\x00\x51\x0d\xda\xc3\x91\xd5\
+\x12\x12\x09\x8d\x40\x6b\x79\x89\xf8\x82\x8d\x89\xcd\xc9\x02\xa7\
+\xcd\x5e\xea\x7b\xa5\xa3\xbc\xc8\xd5\xed\x43\x5a\xa6\xeb\x34\x33\
+\x2b\xd4\x3f\x33\x75\x9b\xa4\xe5\x01\x7c\x86\x9b\xae\xd9\xc5\x6d\
+\x01\x77\xbc\x4d\x56\x9c\x7a\xbe\xca\x25\x7c\x39\x6b\x19\xdf\x6f\
+\xeb\xed\x45\x32\x86\x6a\x3e\x66\xb2\x52\xb5\xfb\xc3\xc1\xe6\x9a\
+\xa1\x05\xe6\x5f\x8e\xda\x67\x38\x24\x20\x2f\x3f\x5b\x04\x06\x53\
+\x1c\x08\x1a\x2c\x18\x34\x20\xc4\x18\x66\x16\x73\x91\x2f\x04\x47\
+\x78\xe1\xfb\x30\x26\x23\x1c\xf2\x49\xd3\x37\x19\xa0\x02\xd1\xb9\
+\x16\x9e\x43\x24\xab\x42\x3b\xd0\x98\x1e\x64\x75\xd4\xca\x94\x6f\
+\x7f\x60\x8e\x73\xf7\x9a\xd2\xd5\x75\xcb\xd4\xaa\x81\x2d\xd4\x6b\
+\x6c\x9e\xe9\x41\x04\x2b\xc0\xc4\x8f\x46\xe3\x67\xe7\x1f\x0b\x84\
+\x08\xc3\x85\xef\x42\xbb\x0f\x11\x62\x96\x2f\x5c\x81\x42\xce\x17\
+\xdc\xcc\xdf\x84\xf3\x9a\x04\xb7\x84\x00\xae\x03\xe6\x0e\xcf\x45\
+\xe0\xf3\xd9\xd0\x3c\xda\x4f\xa0\xf7\x3f\xd8\x5e\x06\xdb\xe7\x49\
+\xfd\x7c\xf2\xaf\xa1\x7d\x95\x7a\xe6\x12\x02\xd0\x16\xfe\x02\x03\
+\xca\x79\x88\x42\x66\x51\x80\x03\x48\x61\xb1\xc0\xdc\x15\x3e\x25\
+\x38\xb4\x18\x72\xfd\x80\xf9\x22\x58\x04\x30\x0b\x04\x70\x72\xd1\
+\x59\x8c\x04\x30\x09\xc0\xca\x3e\x01\x2c\xe1\x00\x11\x16\xfa\xaf\
+\x60\xe4\xb5\x88\xfd\xf7\x40\xf4\x6f\xb6\x87\x31\x42\xf6\xf3\x68\
+\x08\x5c\x4a\x59\x80\x02\x7f\xc1\x60\xe8\x42\x08\x73\x0b\x2d\x18\
+\xcc\xdd\x9c\x32\x8e\x2d\x07\x04\x7c\xc4\x02\xec\x8b\x85\xe3\xbb\
+\x82\x21\x2a\x66\x72\xfe\xc2\x91\xf4\x2a\x02\x6a\x01\x7d\xcc\x94\
+\x09\xf7\x23\x8c\xa5\xff\x63\xe2\xd3\x30\xd1\x1f\x52\xfe\xe8\xa6\
+\x54\xf7\x04\xa8\x6b\x22\x10\x09\x4c\xa9\x53\x22\xe0\xde\x33\x73\
+\x1a\xfc\xbd\xfa\x1d\xb2\xa7\x1e\x14\x80\x32\xf9\xcf\x66\x6f\xe9\
+\x6d\xef\x6e\x96\x66\x7e\xbd\xbb\xf9\x13\xf5\x97\x97\x20\
\x00\x00\x0b\x26\
\x00\
\x00\x5f\x19\x78\x9c\xed\x5c\xdb\x72\xe3\x36\x12\x7d\xf7\x57\x70\
@@ -31546,6 +31666,151 @@ qt_resource_data = "\
\xd6\x3c\x7b\x1b\x0c\x34\xd1\xc5\x5a\x70\x62\x48\x7c\x18\x6c\xc7\
\xb1\x5f\x18\x9d\x9e\xf6\x47\xe7\x27\xa7\xfe\x9b\xbd\xce\x4f\xfe\
\x06\xf2\x9a\xfe\xf0\
+\x00\x00\x08\xea\
+\x00\
+\x00\x21\x8a\x78\x9c\xe5\x59\x6d\x8f\xa3\x38\x12\xfe\xde\xbf\x82\
+\xcb\x7c\x99\xd6\x05\xe3\x17\x6c\x70\xa6\xd3\x2b\xdd\x8d\xf6\xb4\
+\xd2\x9e\x76\x75\x3b\xa3\xfb\x38\x72\xc0\x49\xb3\x4d\x20\x02\xd2\
+\x49\xe6\xd7\x5f\x99\x17\x07\x1a\x92\xee\x7d\x99\xd6\x49\xcb\x68\
+\x26\xe0\x2a\x53\x76\xd5\x53\x8f\xab\x98\xbb\xef\x8e\xdb\xd4\x79\
+\xd2\x45\x99\xe4\xd9\x72\x46\x10\x9e\x39\x3a\x8b\xf2\x38\xc9\x36\
+\xcb\xd9\xe7\x4f\xdf\xbb\xe1\xcc\x29\x2b\x95\xc5\x2a\xcd\x33\xbd\
+\x9c\x65\xf9\xec\xbb\xfb\x9b\xbb\xbf\xb9\xae\xf3\xcf\x42\xab\x4a\
+\xc7\xce\x21\xa9\x1e\x9c\x1f\xb2\xc7\x32\x52\x3b\xed\xbc\x7f\xa8\
+\xaa\xdd\xc2\xf3\x0e\x87\x03\x4a\xda\x41\x94\x17\x1b\xef\xd6\x71\
+\xdd\xfb\x9b\x9b\xbb\xf2\x69\x73\xe3\x38\x0e\xd8\xcd\xca\x45\x1c\
+\x2d\x67\xed\x84\xdd\xbe\x48\x6b\xc5\x38\xf2\x74\xaa\xb7\x3a\xab\
+\x4a\x8f\x20\xe2\xcd\xce\xea\xd1\x59\x3d\x32\xd6\x93\x27\x1d\xe5\
+\xdb\x6d\x9e\x95\xf5\xcc\xac\x7c\xd7\x53\x2e\xe2\xb5\xd5\x36\xab\
+\x39\xb0\x5a\x89\x48\x29\x3d\x4c\x3d\x4a\x5d\xd0\x70\xcb\x53\x56\
+\xa9\xa3\x3b\x9c\x0a\x6b\x9c\x9a\x4a\x31\xc6\x1e\xc8\xce\x9a\xaf\
+\xd3\x5a\x1c\x53\x70\xc5\xc5\xc5\xd4\xd2\xbe\x75\x70\xff\x0e\xfe\
+\xda\x09\xdd\x00\x2a\xf3\x7d\x11\xe9\x35\xcc\xd4\x28\xd3\x95\xf7\
+\xf1\xd3\x47\x2b\x74\x31\x8a\xab\xb8\xf7\x9a\xce\xfb\x03\xbb\x83\
+\x90\x64\x6a\xab\xcb\x9d\x8a\x74\xe9\x75\xe3\xf5\xfc\x43\x12\x57\
+\x0f\xcb\x99\xf0\x77\xc7\xfa\xf9\x41\x27\x9b\x87\xaa\x37\x90\xc4\
+\xcb\x19\xec\x90\x86\x02\xd7\xcf\xdd\x1a\x16\x16\x49\x18\x31\xda\
+\xa8\xb6\x2f\xee\x8b\xfc\x10\xf9\x4e\x21\x25\x93\xc3\xd9\x71\x1e\
+\x99\x25\x2d\x67\x3f\xab\xa2\xfa\xf2\x8f\xfc\x88\x3a\x37\xda\xb7\
+\xe4\xfb\x6a\xb7\xaf\xbe\xe8\x63\xa5\xb3\xe6\x75\xb0\x91\xde\xae\
+\x6a\xb1\x99\x86\x06\x3b\xea\x21\x9c\xcc\xee\x61\xe4\x2e\xd6\xeb\
+\xd2\x48\x9a\xcd\x98\x27\xd8\x0d\xad\x65\x20\x85\x88\x68\x55\xfc\
+\xab\x50\x71\x02\x38\x6c\xf4\x1a\xcd\xa1\x84\xb1\x20\x68\xe7\xc0\
+\xac\xb2\xca\x77\x9d\x6e\xeb\x24\x18\x01\x9d\x66\x9f\xcd\x95\xaf\
+\xd7\xa5\x06\x67\xe2\xde\x58\x59\x9d\x52\xdd\x68\xbb\x51\x9e\xe6\
+\xc5\xe2\xdd\x5a\xad\xd7\x74\xf5\xa1\x1e\xca\x21\x46\x49\x75\x5a\
+\x90\x0f\x33\xc7\x7b\xd1\x5a\x48\x26\xac\x91\x17\xac\xad\x95\xc2\
+\xf8\xa2\xb5\x3b\x6f\xb8\xed\x76\xd4\x46\x65\x07\xee\xdd\xe9\xc8\
+\xe4\x63\x67\xc6\x06\xb5\x3a\x19\x08\x0e\x55\x59\x6c\x97\x73\xc6\
+\xc7\xee\xcb\x11\xbc\xe2\x2c\x1c\x46\xe1\x1f\x32\xa9\x71\x6a\x34\
+\x08\xa4\x18\xfc\xe0\x49\x9d\xaf\x06\xa8\x57\x5e\xd3\xae\xc0\xcd\
+\x8b\x64\x93\x00\x24\x6a\x3d\x4a\x10\xab\xaf\xe1\x1c\x70\x6a\x6f\
+\x6f\x80\x90\xf0\xec\x13\xe3\x0b\x95\x8e\x30\xd2\x99\x01\xcf\xa6\
+\x30\x6d\x39\x53\xe9\x41\x9d\x4a\xfb\xce\x3a\xdb\x17\x0f\x85\x06\
+\x76\x7a\x37\x81\xa6\xbe\xed\xa1\x09\x86\x25\xb5\xe2\x4d\x3b\xf8\
+\x39\x4b\x2a\xa0\xa1\x7d\xa9\x8b\x5f\x4c\x2a\xff\x94\x7d\x2e\xb5\
+\xd5\x8a\xc0\xa5\x3e\x47\x61\xc8\x18\x3d\xbf\x3a\x02\x37\xd2\x10\
+\x85\x42\x72\xd8\x50\x37\xba\x9e\xd4\x5d\x4f\xea\x16\x80\x28\x89\
+\x7c\x11\xf8\x4c\x8c\x96\xf4\xa9\x50\x59\x09\x24\xb5\x5d\xce\xb6\
+\xaa\x2a\x92\xe3\x7b\x38\x57\x04\xe5\x8c\xf2\x39\x86\x3f\xe7\x27\
+\x97\x30\x1f\x71\x1f\x13\x31\x77\x03\x1f\x11\xc9\xb0\x4f\x6f\xbf\
+\xb5\x8b\x5d\x72\xdd\xc9\xdc\x1d\xef\xe9\xba\x9b\xaf\xee\x9c\x71\
+\x1a\x84\xb0\x73\x44\x99\x24\x80\xdc\x70\x0e\x54\xed\x4b\x42\x81\
+\xfc\xd9\x9c\x22\x42\x45\xe8\x53\x7f\xee\x86\x0c\x61\x8a\xb9\x00\
+\x67\x50\x82\xc1\x1b\x5c\xf2\xdb\x41\x28\x09\xe3\x88\x41\x7c\xd8\
+\x20\x94\x32\x40\x6c\x1c\xca\xb1\xee\x7a\x52\x77\x10\x4a\xeb\xf9\
+\xdf\x42\x80\x2e\x79\x0d\x05\xba\x53\xb4\xf4\x0d\x49\xd0\xc5\x6f\
+\x45\x83\xdf\x00\xa5\xc4\xf7\xaf\x60\xd4\x27\x38\xfc\xf3\x10\x5a\
+\xe7\x24\x46\x42\x86\x9c\x4a\x1f\xee\x29\xa6\x28\x04\xae\x63\x43\
+\xf0\x51\xca\x11\x15\x3e\xa6\x03\xf0\x89\x80\xa2\x40\x06\x3d\x1a\
+\x58\x4f\xea\xae\x27\x75\x01\x7c\xc0\x00\xcc\xe7\x24\x0c\x5f\x04\
+\xdf\x4b\x0e\x9d\x40\xa7\xf1\xe3\x05\xac\x4c\x86\xdf\x5c\xa3\xf0\
+\x5f\x87\xad\xc5\x1c\xf1\xc5\x65\x64\xbe\xd2\x1a\x9e\xb2\x46\xa6\
+\xad\x85\xbf\x0f\x97\x03\x97\x5f\x8f\xce\x74\x24\xa7\xa3\x3e\x8d\
+\x90\x3f\x08\xbb\xd7\x61\x7b\x2a\x41\x98\xff\xdb\xf3\xec\x12\xbe\
+\x1a\x37\xdf\x79\xa6\x48\xac\xef\x6c\x6d\x63\xaa\xd5\xf8\x29\xd1\
+\x87\x73\x25\xb9\x52\x76\x65\x3b\xb5\xd1\x75\xac\xc1\x6e\x13\xec\
+\x56\xb0\xca\x8b\x58\x17\x9d\x48\xd4\xd7\x40\xd4\xc2\xa1\x69\xc8\
+\x6e\x86\xab\x33\x6f\xb5\x72\x3c\x2d\x2f\x1f\x54\x9c\x1f\x20\x20\
+\xcf\x85\x5f\xf3\x1c\x42\xc0\x11\x7f\x2e\x30\xe1\xe3\x12\x51\x0e\
+\xb8\x92\x23\x21\x58\x62\x50\xd1\xcb\x80\xe3\xf1\xcc\x7d\x51\x80\
+\x2b\xdd\x54\x9d\x34\x6c\xa7\xfe\xe9\x10\x5b\x3e\xe4\x87\x4d\x61\
+\xdc\x52\x15\x7b\xfd\x7c\x26\x94\xfb\x7b\xd3\xe6\xb9\xfb\x26\xbc\
+\x6d\x73\xd1\xd3\x30\x73\xdd\xd5\x2a\x3f\x4e\xbf\xe0\x90\x64\xb0\
+\x4d\xb7\x6d\x57\x88\xa4\x23\x67\xb4\x1a\x5d\x03\x43\x30\x0f\x2e\
+\xa8\x1c\xcf\x59\xfd\x5c\x74\x9a\x10\xe5\xab\x5f\x01\x22\xee\x4e\
+\x55\x0f\xb0\xf2\xb5\x4a\xcb\xd1\xea\xca\x4c\xed\xdc\x2c\x8f\x75\
+\x39\xbd\xfa\xf6\x15\x57\x34\x5a\xfb\x5b\x75\x4c\xb6\xc9\x57\x1d\
+\x1b\x2a\x68\xc1\xb8\xd5\x95\x8a\x55\xa5\xce\xc0\xeb\x46\x20\x83\
+\x78\xd7\xc6\x40\x83\xbb\xf8\xcf\xc7\xef\x2d\x27\x45\xd1\xe2\xbf\
+\x79\xf1\x78\xa6\x13\xa3\xa0\x56\xd0\x35\x2d\x67\x96\x27\x4d\x73\
+\x14\x2d\x4c\xb2\xaa\xea\x3e\xd9\x02\x9c\x4c\x37\xfb\x77\x68\x2a\
+\x21\x05\xac\x60\xa0\x6c\x6a\xfc\xf3\x4b\x9b\xd7\x16\xba\xe9\x56\
+\x27\x1b\xfc\x38\xda\x26\x66\x92\xf7\x4b\x95\xa4\xe9\x0f\xc6\x48\
+\x8f\x3b\xdb\x97\x26\x55\xaa\xef\x6b\x9b\xcd\x6d\xb7\x0b\xaf\xdd\
+\x46\x47\x7e\xbd\x5d\xde\x79\x9d\x1b\xea\xa7\xcd\xd9\x3d\x03\x5c\
+\x5a\x0f\xa7\x6a\xa5\xd3\xe5\xec\x47\x23\x74\x46\xd2\x4d\x91\xef\
+\x77\x5b\x88\x4f\x3b\xbd\x73\xab\x89\xba\xed\x73\x1a\x62\x5f\xc3\
+\x36\x16\x59\x9e\x69\xe0\xf3\x22\x7f\xd4\x86\xde\x57\xac\xae\x25\
+\xcc\x63\x83\xd1\x05\x85\x26\x23\xec\x86\x0c\x15\x81\x99\xc5\x6a\
+\x5f\x55\xfd\xb1\x5f\xf3\x24\x5b\x80\xe5\x2c\xee\x46\xcf\x67\x51\
+\x7b\x74\xe0\xfa\xea\xc4\xe0\x4a\x5d\xa4\x00\x91\x6a\xe1\x77\x63\
+\xb1\x02\x0e\x28\x0a\x75\x5a\xf8\x48\x04\x62\x3e\xb0\x6c\x84\xcd\
+\xe1\x02\x07\xce\x56\x15\x8f\xba\x68\xd6\xfe\x94\x94\xc9\x2a\x49\
+\x8d\xad\xfa\x36\xd5\x1f\xe2\xa4\xdc\xc1\xe6\x17\x49\x66\xd6\xf6\
+\x21\x87\x4e\x7a\x9d\xe6\x07\x2b\xd7\x99\x82\x1f\x77\xa5\xa2\xc7\
+\x4d\xbd\xe8\x85\x8a\x20\xad\xf7\xa9\xaa\xce\x0c\x0d\xfe\xff\xb7\
+\x43\x03\x14\x08\xc6\x49\x30\xf7\x29\x82\x53\x02\x8a\x61\x47\x00\
+\xff\xfb\x42\x12\x36\xe7\x50\xfc\x06\x8c\x12\x3e\xa0\x75\xe3\x69\
+\x26\x31\x9b\x22\xe9\x0c\xdc\x57\xe5\x85\x0b\x04\xf4\xa4\xaa\x7d\
+\xa1\x4d\x9a\xda\x23\xb1\x1f\xa3\x97\x26\x8d\x7a\x56\x93\x93\x06\
+\x9e\x90\x97\x91\xb9\x86\x47\x0d\xbc\x01\x6a\x7a\xdc\x2b\x30\xbb\
+\xfd\x49\x4c\xa1\x95\x09\x11\x0d\x28\x17\x9c\x38\x3c\x40\x34\x0c\
+\x89\xcf\xe7\x50\xcf\x87\x58\x0a\xe1\x70\x01\x87\x1c\xf6\x05\x99\
+\xfb\x01\xf4\x41\x02\x9a\x83\x49\xcf\x7c\x9d\xbd\x25\xc2\xa6\x20\
+\x74\x46\xdd\xff\x15\xa6\x6c\x84\x37\xfd\xa0\x6c\x18\x11\xe7\x78\
+\x54\xa3\x72\x03\x5a\x2e\x22\x28\x86\xea\x22\x30\xed\x17\xc6\x4c\
+\x84\xa6\x1d\xb5\x77\x7d\x05\x01\xc5\x0d\x0b\x70\xe0\xcf\x09\x04\
+\xc4\x67\x92\x89\xdb\x31\x02\xf5\x71\x97\x17\x95\x0b\x71\xd1\xcd\
+\x57\x2b\xef\x21\xdf\x6a\xef\x94\x17\xc9\xa3\xf7\xb1\x3d\xdb\x4a\
+\xef\x47\xb5\xf2\x3e\x16\x6a\x5d\x79\x09\xc0\xaf\xac\x4b\x35\xb4\
+\xcb\x36\x17\x5f\x78\x8c\x77\xc9\x72\x06\xe0\x08\xa0\x43\xe4\x13\
+\x1f\x30\x5a\xbd\xd3\x33\x3d\xcb\x8f\x7d\xe8\xd7\xd8\xdc\x3a\x14\
+\x1a\xfb\x00\x36\x13\xce\x05\x87\x1a\x0d\x1a\x6d\x27\x72\xa0\xe4\
+\x32\x60\xe4\x54\x38\xd0\x70\xa2\x00\x40\x09\x08\x0c\x11\x07\x4d\
+\xe6\xb8\xdd\x5d\x6f\xa8\xd3\x9f\xe3\x9e\xd8\xce\xed\x8f\xd9\x39\
+\x78\x6e\x67\x39\xd6\xc8\x59\x3c\x31\xa3\x67\xc4\x4a\xad\x89\xf1\
+\xa2\xce\x89\xd2\x4b\xe0\x02\xce\xec\x4e\x63\x52\x7e\xbc\x2e\xaf\
+\x6b\xdc\xd6\x53\x93\x72\xd3\x60\x43\x2f\x6d\x5c\xca\x7b\x0a\x96\
+\xb3\x00\x4b\xe3\x56\xb3\x4e\x61\xd3\x64\x4a\x48\x5b\xf3\xd0\xcb\
+\xb1\xfa\xb1\xd8\xa7\xda\x64\xcd\x57\x28\x01\x6d\x9a\x0f\xc9\xbe\
+\x49\x73\x0e\x6c\x62\x2e\x22\x5f\x95\xeb\x75\x7a\xff\xce\x5c\xef\
+\x51\xce\xdb\x1f\x1c\xa3\xef\x88\xaa\x88\xfa\x4d\xd6\x10\xea\xe3\
+\xb4\x07\xd6\xe5\x84\x61\xca\x4c\x7e\x73\xea\x8b\x80\x43\xab\xd1\
+\xbb\xb3\x62\xa0\x32\x38\x8b\x84\xa4\x80\xb5\xfa\x4b\x14\x0d\x6f\
+\x67\xcf\xb3\x08\x2a\x64\x81\x25\x25\x73\xdb\xff\xd4\x69\x44\x18\
+\xa2\xbe\x84\x9c\x72\x09\x47\x2c\x10\x21\x70\x23\x43\x12\x68\x1c\
+\x86\xda\x66\x4b\xf6\x86\x48\x88\xa4\x08\x19\x35\x69\x64\xc5\x2e\
+\x1c\x11\x81\x4f\x68\x7f\xc8\x4e\xc1\xe6\x53\x59\x6b\xa4\xb5\x11\
+\x58\x31\x75\x46\x33\xa8\xd3\xda\x60\x60\xc3\x4a\x1b\x0b\x44\x3a\
+\xcf\xd7\x44\x2f\x67\x51\xa7\x71\x31\x8d\xc6\xcd\xe4\xf3\x3c\x1a\
+\xf5\x8a\xcf\x12\x69\xdc\x36\x0e\x12\xc9\xbf\x90\x48\x50\x4e\xbe\
+\x7f\x37\xee\xfb\x6e\x9f\x67\x56\x9b\x47\x06\xa7\xaf\xc3\xd5\x9d\
+\xb7\xf9\x16\x45\xc4\x74\x19\x41\x5f\x2c\x22\x80\x0e\xfd\x30\xc0\
+\x00\x57\x88\x3c\x30\x47\x80\x21\x80\x75\xab\x06\xb8\xa5\xd0\x96\
+\x61\x98\xe1\xa4\x0e\xc0\x9a\x30\x0e\xd4\x08\x48\x86\x92\x43\x84\
+\xa1\x43\xe0\x74\xe0\xe6\x0e\xe0\x43\x10\x83\x52\x24\x24\xa0\x27\
+\x08\x31\x43\x4c\x20\xce\x38\xa6\x17\x6a\x0d\x53\x5f\x48\x4b\x3c\
+\x57\xca\x0d\xdc\xbf\xde\xa8\xf8\xe8\x9b\x04\x6f\x39\x57\x16\xf2\
+\x56\xa4\x35\xc4\x1d\x46\xe6\x2b\x9d\x24\x58\xbe\x65\x4d\xda\x07\
+\xd3\x76\x1a\x39\x14\x49\x28\x95\x4c\xfd\xc6\x20\x2d\x79\x08\xdc\
+\x02\x80\x09\x78\x48\xa4\x04\xee\x31\x65\x38\x38\xcf\x1c\xd2\xe6\
+\xfb\x31\xf1\x25\xfb\x33\xf0\x21\x6c\xac\xfe\xba\xf8\x18\x36\x6f\
+\x93\x68\x21\x54\x76\xd7\xb8\x22\xf8\x63\x40\xb2\x8c\xca\x7b\x4c\
+\x5c\x73\x0e\x90\x09\x87\x7a\xc5\x0f\xe6\x44\xc2\x01\x01\x25\x0d\
+\x9b\xe8\x5c\x26\x31\x30\xc1\xc1\xe6\x7f\xa9\x46\x1c\x7c\xde\x8b\
+\x7e\xd2\x80\xe4\xf8\x65\xd4\xfc\x05\x9a\x98\xfa\xa0\xb9\x33\x5f\
+\x57\xee\x6f\xfe\x07\xcd\x1d\xa1\x65\
\x00\x00\x06\xd1\
\x00\
\x00\x27\xd8\x78\x9c\xed\x59\x5b\x6f\xe3\xb6\x12\x7e\xcf\xaf\xd0\
@@ -33405,10 +33670,19 @@ qt_resource_name = "\
\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x42\x00\x75\x00\x69\x00\x6c\x00\x64\x00\x69\x00\x6e\x00\x67\x00\x2e\x00\x73\x00\x76\x00\x67\
\
\x00\x13\
+\x06\x64\xa3\x67\
+\x00\x41\
+\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x53\x00\x70\x00\x61\x00\x63\x00\x65\x00\x5f\x00\x54\x00\x72\x00\x65\x00\x65\x00\x2e\x00\x73\
+\x00\x76\x00\x67\
+\x00\x13\
\x08\x0a\x92\x67\
\x00\x41\
\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x4d\x00\x65\x00\x72\x00\x67\x00\x65\x00\x57\x00\x61\x00\x6c\x00\x6c\x00\x73\x00\x2e\x00\x73\
\x00\x76\x00\x67\
+\x00\x0e\
+\x06\xac\xdc\x27\
+\x00\x41\
+\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x53\x00\x70\x00\x61\x00\x63\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
\x00\x14\
\x03\x50\x84\x07\
\x00\x70\
@@ -33457,8 +33731,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\x3b\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x20\x00\x00\x00\x1b\
+\x00\x00\x00\x10\x00\x02\x00\x00\x00\x01\x00\x00\x00\x3d\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x22\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\
@@ -33483,38 +33757,40 @@ 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\x05\x56\x00\x01\x00\x00\x00\x01\x00\x07\x5b\xb5\
-\x00\x00\x06\xbc\x00\x01\x00\x00\x00\x01\x00\x07\xb3\x28\
-\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x07\x6a\x2c\
-\x00\x00\x04\x12\x00\x00\x00\x00\x00\x01\x00\x07\x05\x81\
-\x00\x00\x07\xec\x00\x01\x00\x00\x00\x01\x00\x08\x0a\xfd\
-\x00\x00\x06\x8e\x00\x01\x00\x00\x00\x01\x00\x07\xac\x53\
-\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x07\x13\xf0\
-\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x07\x27\x77\
-\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\xea\xdf\
-\x00\x00\x07\x86\x00\x00\x00\x00\x00\x01\x00\x07\xe7\xb9\
-\x00\x00\x05\xdc\x00\x00\x00\x00\x00\x01\x00\x07\x84\x06\
-\x00\x00\x05\x7c\x00\x01\x00\x00\x00\x01\x00\x07\x62\x64\
-\x00\x00\x03\x94\x00\x01\x00\x00\x00\x01\x00\x06\xe1\xe6\
-\x00\x00\x06\x62\x00\x01\x00\x00\x00\x01\x00\x07\xa1\x29\
-\x00\x00\x03\x38\x00\x01\x00\x00\x00\x01\x00\x06\xcf\xc5\
-\x00\x00\x07\x5c\x00\x01\x00\x00\x00\x01\x00\x07\xe0\x24\
-\x00\x00\x04\x7a\x00\x01\x00\x00\x00\x01\x00\x07\x1d\x48\
-\x00\x00\x03\x0e\x00\x01\x00\x00\x00\x01\x00\x06\xc6\x1d\
-\x00\x00\x03\x74\x00\x01\x00\x00\x00\x01\x00\x06\xd9\x78\
-\x00\x00\x06\x0c\x00\x01\x00\x00\x00\x01\x00\x07\x93\x74\
-\x00\x00\x05\x0a\x00\x00\x00\x00\x00\x01\x00\x07\x43\x72\
-\x00\x00\x06\x3a\x00\x01\x00\x00\x00\x01\x00\x07\x98\xc4\
-\x00\x00\x05\x34\x00\x01\x00\x00\x00\x01\x00\x07\x53\xf3\
-\x00\x00\x06\xe6\x00\x00\x00\x00\x00\x01\x00\x07\xbb\x6d\
-\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x07\x2c\x8e\
-\x00\x00\x07\x30\x00\x01\x00\x00\x00\x01\x00\x07\xd7\xaa\
-\x00\x00\x07\x10\x00\x01\x00\x00\x00\x01\x00\x07\xcd\x70\
-\x00\x00\x05\xbc\x00\x01\x00\x00\x00\x01\x00\x07\x7d\xee\
-\x00\x00\x07\xb2\x00\x00\x00\x00\x00\x01\x00\x07\xf9\x88\
-\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x06\xf3\x21\
-\x00\x00\x04\xec\x00\x00\x00\x00\x00\x01\x00\x07\x34\x76\
-\x00\x00\x02\xda\x00\x01\x00\x00\x00\x01\x00\x06\xbe\xcd\
+\x00\x00\x05\x56\x00\x01\x00\x00\x00\x01\x00\x07\x5c\x57\
+\x00\x00\x07\x0a\x00\x01\x00\x00\x00\x01\x00\x07\xc3\x7b\
+\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x07\x6a\xce\
+\x00\x00\x04\x12\x00\x00\x00\x00\x00\x01\x00\x07\x06\x23\
+\x00\x00\x08\x3a\x00\x01\x00\x00\x00\x01\x00\x08\x1b\x50\
+\x00\x00\x06\xdc\x00\x01\x00\x00\x00\x01\x00\x07\xbc\xa6\
+\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x07\x14\x92\
+\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x07\x28\x19\
+\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\xeb\x81\
+\x00\x00\x07\xd4\x00\x00\x00\x00\x00\x01\x00\x07\xf8\x0c\
+\x00\x00\x06\x62\x00\x01\x00\x00\x00\x01\x00\x07\xa1\xcb\
+\x00\x00\x06\xba\x00\x01\x00\x00\x00\x01\x00\x07\xb3\xb8\
+\x00\x00\x05\xdc\x00\x00\x00\x00\x00\x01\x00\x07\x84\xa8\
+\x00\x00\x05\x7c\x00\x01\x00\x00\x00\x01\x00\x07\x63\x06\
+\x00\x00\x03\x94\x00\x01\x00\x00\x00\x01\x00\x06\xe2\x88\
+\x00\x00\x06\x8e\x00\x01\x00\x00\x00\x01\x00\x07\xa8\x8e\
+\x00\x00\x03\x38\x00\x01\x00\x00\x00\x01\x00\x06\xd0\x67\
+\x00\x00\x07\xaa\x00\x01\x00\x00\x00\x01\x00\x07\xf0\x77\
+\x00\x00\x04\x7a\x00\x01\x00\x00\x00\x01\x00\x07\x1d\xea\
+\x00\x00\x03\x0e\x00\x01\x00\x00\x00\x01\x00\x06\xc6\xbf\
+\x00\x00\x03\x74\x00\x01\x00\x00\x00\x01\x00\x06\xda\x1a\
+\x00\x00\x06\x0c\x00\x01\x00\x00\x00\x01\x00\x07\x94\x16\
+\x00\x00\x05\x0a\x00\x00\x00\x00\x00\x01\x00\x07\x44\x14\
+\x00\x00\x06\x3a\x00\x01\x00\x00\x00\x01\x00\x07\x99\x66\
+\x00\x00\x05\x34\x00\x01\x00\x00\x00\x01\x00\x07\x54\x95\
+\x00\x00\x07\x34\x00\x00\x00\x00\x00\x01\x00\x07\xcb\xc0\
+\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x07\x2d\x30\
+\x00\x00\x07\x7e\x00\x01\x00\x00\x00\x01\x00\x07\xe7\xfd\
+\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x07\xdd\xc3\
+\x00\x00\x05\xbc\x00\x01\x00\x00\x00\x01\x00\x07\x7e\x90\
+\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x00\x08\x09\xdb\
+\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x06\xf3\xc3\
+\x00\x00\x04\xec\x00\x00\x00\x00\x00\x01\x00\x07\x35\x18\
+\x00\x00\x02\xda\x00\x01\x00\x00\x00\x01\x00\x06\xbf\x6f\
\x00\x00\x02\xb2\x00\x01\x00\x00\x00\x01\x00\x06\xb6\xfd\
"
diff --git a/src/Mod/Arch/CMakeLists.txt b/src/Mod/Arch/CMakeLists.txt
index 76d09e80d..e55bf558f 100644
--- a/src/Mod/Arch/CMakeLists.txt
+++ b/src/Mod/Arch/CMakeLists.txt
@@ -21,6 +21,8 @@ SET(Arch_SRCS
ArchVRM.py
ArchRoof.py
importWebGL.py
+ ArchSpace.py
+ TestArch.py
)
SOURCE_GROUP("" FILES ${Arch_SRCS})
diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py
index 7d7fd9f5e..ccd46e51d 100644
--- a/src/Mod/Arch/InitGui.py
+++ b/src/Mod/Arch/InitGui.py
@@ -72,8 +72,8 @@ class ArchWorkbench(Workbench):
self.archtools = ["Arch_Wall","Arch_Structure",
"Arch_Floor","Arch_Building","Arch_Site",
"Arch_Window","Arch_Roof","Arch_Axis",
- "Arch_SectionPlane","Arch_Add","Arch_Remove",
- "Arch_Fixture"]
+ "Arch_SectionPlane","Arch_Space","Arch_Add",
+ "Arch_Remove","Arch_Fixture"]
self.meshtools = ["Arch_SplitMesh","Arch_MeshToShape",
"Arch_SelectNonSolidMeshes","Arch_RemoveShape",
"Arch_CloseHoles","Arch_MergeWalls"]
@@ -85,13 +85,14 @@ class ArchWorkbench(Workbench):
"Draft_Dimension", "Draft_BSpline","Draft_Point"]
self.draftmodtools = ["Draft_Move","Draft_Rotate","Draft_Offset",
"Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale",
- "Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint",
- "Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array",
- "Draft_Clone","Draft_Heal"]
+ "Draft_Drawing","Draft_Edit","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array",
+ "Draft_Clone"]
+ self.extramodtools = ["Draft_WireToBSpline","Draft_AddPoint","Draft_DelPoint"]
self.draftcontexttools = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup",
- "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap",
+ "Draft_SelectGroup","Draft_SelectPlane",
"Draft_ShowSnapBar","Draft_ToggleGrid","Draft_UndoLine",
"Draft_FinishLine","Draft_CloseLine"]
+ self.draftutils = ["Draft_Heal"]
self.snapList = ['Draft_Snap_Lock','Draft_Snap_Midpoint','Draft_Snap_Perpendicular',
'Draft_Snap_Grid','Draft_Snap_Intersection','Draft_Snap_Parallel',
'Draft_Snap_Endpoint','Draft_Snap_Angle','Draft_Snap_Center',
@@ -103,8 +104,9 @@ class ArchWorkbench(Workbench):
self.appendMenu([str(translate("arch","&Architecture")),str(translate("arch","Conversion Tools"))],self.meshtools)
self.appendMenu([str(translate("arch","&Architecture")),str(translate("arch","Calculation Tools"))],self.calctools)
self.appendMenu(str(translate("arch","&Architecture")),self.archtools)
- self.appendMenu(str(translate("arch","&Draft")),self.drafttools+self.draftmodtools)
+ self.appendMenu(str(translate("arch","&Draft")),self.drafttools+self.draftmodtools+self.extramodtools)
self.appendMenu([str(translate("arch","&Draft")),str(translate("arch","Context Tools"))],self.draftcontexttools)
+ self.appendMenu([str(translate("arch","&Draft")),str(translate("arch","Utilities"))],self.draftutils)
self.appendMenu([str(translate("arch","&Draft")),str(translate("arch","Snapping"))],self.snapList)
FreeCADGui.addIconPath(":/icons")
FreeCADGui.addLanguagePath(":/translations")
@@ -112,6 +114,7 @@ class ArchWorkbench(Workbench):
if hasattr(FreeCADGui,"draftToolBar"):
if not hasattr(FreeCADGui.draftToolBar,"loadedPreferences"):
FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft")
+ FreeCADGui.addPreferencePage(":/ui/userprefs-visual.ui","Draft")
FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft")
FreeCADGui.draftToolBar.loadedPreferences = True
Log ('Loading Arch module... done\n')
@@ -142,14 +145,7 @@ FreeCADGui.addWorkbench(ArchWorkbench)
FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC")
FreeCAD.addExportType("Wavefront OBJ - Arch module (*.obj)","importOBJ")
FreeCAD.addExportType("WebGL file (*.html)","importWebGL")
+FreeCAD.addImportType("Collada (*.dae)","importDAE")
+FreeCAD.addExportType("Collada (*.dae)","importDAE")
-# check for pycollada
-try:
- import collada
-except:
- from DraftTools import translate
- FreeCAD.Console.PrintMessage(str(translate("arch","pycollada not found, collada support will be disabled.\n")))
-else:
- FreeCAD.addImportType("Collada (*.dae)","importDAE")
- FreeCAD.addExportType("Collada (*.dae)","importDAE")
diff --git a/src/Mod/Arch/Resources/Arch.qrc b/src/Mod/Arch/Resources/Arch.qrc
index 4aafc08b0..304c659ae 100644
--- a/src/Mod/Arch/Resources/Arch.qrc
+++ b/src/Mod/Arch/Resources/Arch.qrc
@@ -32,6 +32,8 @@
icons/Arch_MergeWalls.svg
icons/Arch_Wall_Tree_Assembly.svg
icons/Arch_Fixture.svg
+ icons/Arch_Space.svg
+ icons/Arch_Space_Tree.svg
ui/archprefs-base.ui
translations/Arch_af.qm
translations/Arch_de.qm
diff --git a/src/Mod/Arch/Resources/icons/Arch_Space.svg b/src/Mod/Arch/Resources/icons/Arch_Space.svg
new file mode 100644
index 000000000..1e302c4dd
--- /dev/null
+++ b/src/Mod/Arch/Resources/icons/Arch_Space.svg
@@ -0,0 +1,202 @@
+
+
+
+
diff --git a/src/Mod/Arch/Resources/icons/Arch_Space_Tree.svg b/src/Mod/Arch/Resources/icons/Arch_Space_Tree.svg
new file mode 100644
index 000000000..65ca3cf5e
--- /dev/null
+++ b/src/Mod/Arch/Resources/icons/Arch_Space_Tree.svg
@@ -0,0 +1,165 @@
+
+
+
+
diff --git a/src/Mod/Arch/Resources/ui/archprefs-base.ui b/src/Mod/Arch/Resources/ui/archprefs-base.ui
index 4741046ae..8093699d0 100644
--- a/src/Mod/Arch/Resources/ui/archprefs-base.ui
+++ b/src/Mod/Arch/Resources/ui/archprefs-base.ui
@@ -23,7 +23,7 @@
-
- General Arch Settings
+ Default settings
-
@@ -31,7 +31,7 @@
-
- Default color for walls
+ Wall
@@ -48,6 +48,59 @@
+ -
+
+
+ Width:
+
+
+
+ -
+
+
+ 9999.989999999999782
+
+
+ 200.000000000000000
+
+
+ WallWidth
+
+
+ Mod/Arch
+
+
+
+ -
+
+
+ Height:
+
+
+
+ -
+
+
+ 9999.989999999999782
+
+
+ 3000.000000000000000
+
+
+ WallHeight
+
+
+ Mod/Arch
+
+
+
+ -
+
+
+ Color:
+
+
+
-
@@ -75,7 +128,7 @@
-
- Default color for structures
+ Structure
@@ -92,6 +145,82 @@
+ -
+
+
+ Length:
+
+
+
+ -
+
+
+ 9999.989999999999782
+
+
+ 100.000000000000000
+
+
+ StructureLength
+
+
+ Mod/Arch
+
+
+
+ -
+
+
+ Width:
+
+
+
+ -
+
+
+ 9999.989999999999782
+
+
+ 100.000000000000000
+
+
+ StructureWidth
+
+
+ Mod/Arch
+
+
+
+ -
+
+
+ Height:
+
+
+
+ -
+
+
+ 9999.989999999999782
+
+
+ 1000.000000000000000
+
+
+ StructureHeight
+
+
+ Mod/Arch
+
+
+
+ -
+
+
+ Color:
+
+
+
-
@@ -119,7 +248,7 @@
-
- Default color for windows
+ Window
@@ -136,6 +265,13 @@
+ -
+
+
+ Frame color:
+
+
+
-
@@ -153,30 +289,13 @@
-
-
- -
-
-
-
+
- Default color for window glass
+ Glass color:
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
@@ -285,23 +404,6 @@
- -
-
-
-
-
-
- Import furniture (can make the model heavy)
-
-
- importIfcFurniture
-
-
- Mod/Arch
-
-
-
-
-
-
-
@@ -360,7 +462,7 @@
- IfcSpace,IfcBuildingElementProxy,IfcFlowTerminal
+ IfcSpace,IfcBuildingElementProxy,IfcFlowTerminal,IfcFurnishingElement
ifcSkip
@@ -372,6 +474,33 @@
+ -
+
+
-
+
+
+ Import as meshes:
+
+
+
+ -
+
+
+ A comma-separated list of IFC types that must be imported as meshes
+
+
+ IfcFurnishingElement
+
+
+ ifcAsMesh
+
+
+ Mod/Arch
+
+
+
+
+
@@ -441,22 +570,22 @@
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
diff --git a/src/Mod/Arch/TestArch.py b/src/Mod/Arch/TestArch.py
new file mode 100644
index 000000000..7f86153e4
--- /dev/null
+++ b/src/Mod/Arch/TestArch.py
@@ -0,0 +1,53 @@
+# Unit test for the Arch module
+
+#***************************************************************************
+#* (c) Yorik van Havre 2013 *
+#* *
+#* This file is part of the FreeCAD CAx development system. *
+#* *
+#* 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. *
+#* *
+#* FreeCAD 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 FreeCAD; if not, write to the Free Software *
+#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+#* USA *
+#* *
+#***************************************************************************/
+
+import FreeCAD, os, unittest, FreeCADGui, Arch, Draft
+
+class ArchTest(unittest.TestCase):
+
+ def setUp(self):
+ # setting a new document to hold the tests
+ if FreeCAD.ActiveDocument:
+ if FreeCAD.ActiveDocument.Name != "ArchTest":
+ FreeCAD.newDocument("ArchTest")
+ else:
+ FreeCAD.newDocument("ArchTest")
+ FreeCAD.setActiveDocument("ArchTest")
+
+ def testWall(self):
+ FreeCAD.Console.PrintLog ('Checking Arch Wall...\n')
+ l=Draft.makeLine(FreeCAD.Vector(0,0,0),FreeCAD.Vector(-2,0,0))
+ w = Arch.makeWall(l)
+ self.failUnless(w,"Arch Wall failed")
+
+ def testStructure(self):
+ FreeCAD.Console.PrintLog ('Checking Arch Structure...\n')
+ s = Arch.makeStructure(length=2,width=3,hright=5)
+ self.failUnless(s,"Arch Structure failed")
+
+ def tearDown(self):
+ FreeCAD.closeDocument("ArchTest")
+ pass
+
diff --git a/src/Mod/Arch/importDAE.py b/src/Mod/Arch/importDAE.py
index 4ffa2bde6..94ad0cd1b 100644
--- a/src/Mod/Arch/importDAE.py
+++ b/src/Mod/Arch/importDAE.py
@@ -37,14 +37,15 @@ def checkCollada():
try:
import collada
except:
- FreeCAD.Console.PrintError(str(translate("Arch","pycollada not found, no collada support.\n")))
+ FreeCAD.Console.PrintError(str(translate("Arch","pycollada not found, collada support is disabled.\n")))
return False
else:
return True
def open(filename):
"called when freecad wants to open a file"
- if not checkCollada(): return
+ if not checkCollada():
+ return
docname = os.path.splitext(os.path.basename(filename))[0]
doc = FreeCAD.newDocument(docname)
doc.Label = decode(docname)
@@ -54,7 +55,8 @@ def open(filename):
def insert(filename,docname):
"called when freecad wants to import a file"
- if not checkCollada(): return
+ if not checkCollada():
+ return
try:
doc = FreeCAD.getDocument(docname)
except:
diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py
index 140119ed0..313050fbd 100644
--- a/src/Mod/Arch/importIFC.py
+++ b/src/Mod/Arch/importIFC.py
@@ -59,17 +59,17 @@ def insert(filename,docname):
def getConfig():
"Gets Arch IFC import preferences"
- global CREATE_IFC_GROUPS, IMPORT_IFC_FURNITURE, DEBUG, SKIP, PREFIX_NUMBERS, FORCE_PYTHON_PARSER, SEPARATE_OPENINGS
+ global CREATE_IFC_GROUPS, ASMESH, DEBUG, SKIP, PREFIX_NUMBERS, FORCE_PYTHON_PARSER, SEPARATE_OPENINGS
CREATE_IFC_GROUPS = False
IMPORT_IFC_FURNITURE = False
DEBUG = False
- SKIP = ["IfcSpace","IfcBuildingElementProxy","IfcFlowTerminal"]
+ SKIP = ["IfcBuildingElementProxy","IfcFlowTerminal","IfcFurnishingElement"]
+ ASMESH = ["IfcFurnishingElement"]
PREFIX_NUMBERS = False
FORCE_PYTHON_PARSER = False
SEPARATE_OPENINGS = False
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
CREATE_IFC_GROUPS = p.GetBool("createIfcGroups")
- IMPORT_IFC_FURNITURE = p.GetBool("importIfcFurniture")
FORCE_PYTHON_PARSER = p.GetBool("forceIfcPythonParser")
DEBUG = p.GetBool("ifcDebug")
SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings")
@@ -77,7 +77,9 @@ def getConfig():
skiplist = p.GetString("ifcSkip")
if skiplist:
SKIP = skiplist.split(",")
-
+ asmeshlist = p.GetString("ifcAsMesh")
+ if asmeshlist:
+ ASMESH = asmeshlist.split(",")
def getIfcOpenShell():
"locates and imports ifcopenshell"
@@ -104,8 +106,6 @@ def read(filename):
if DEBUG: global ifcObjects,ifcParents
ifcObjects = {} # a table to relate ifc id with freecad object
ifcParents = {} # a table to relate ifc id with parent id
- if not IMPORT_IFC_FURNITURE:
- SKIP.append("IfcFurnishingElement")
if hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS") and SEPARATE_OPENINGS:
IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS,True)
else:
@@ -123,7 +123,6 @@ def read(filename):
obj = IfcImport.Get()
if DEBUG: print "["+str(int((float(obj.id)/num_lines)*100))+"%] parsing ",obj.id,": ",obj.name," of type ",obj.type
- meshdata = []
# retrieving name
n = getName(obj)
@@ -164,6 +163,10 @@ def read(filename):
elif obj.type in ["IfcSite"]:
nobj = makeSite(obj.id,shape,n)
+ # spaces
+ elif obj.type in ["IfcSpace"]:
+ nobj = makeSpace(obj.id,shape,n)
+
elif shape:
# treat as dumb parts
#if DEBUG: print "Fixme: Shape-containing object not handled: ",obj.id, " ", obj.type
@@ -185,7 +188,7 @@ def read(filename):
if not IfcImport.Next():
break
-
+
# processing non-geometry and relationships
parents_temp = dict(ifcParents)
import ArchCommands
@@ -239,7 +242,7 @@ def read(filename):
ArchCommands.addComponents(ifcObjects[id],parent)
else:
ArchCommands.removeComponents(ifcObjects[id],parent)
-
+
IfcImport.CleanUp()
else:
@@ -282,7 +285,7 @@ def read(filename):
for s in ifc.getEnt("IfcSite"):
group(s,ifc,"Site")
- if DEBUG: print "done parsing. Recomputing..."
+ if DEBUG: print "done parsing. Recomputing..."
FreeCAD.ActiveDocument.recompute()
t3 = time.time()
if DEBUG: print "done processing IFC file in %s s" % ((t3-t1))
@@ -306,8 +309,12 @@ def makeWall(entity,shape=None,name="Wall"):
try:
if shape:
# use ifcopenshell
- body = FreeCAD.ActiveDocument.addObject("Part::Feature","WallBody")
- body.Shape = shape
+ if isinstance(shape,Part.Shape):
+ body = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
+ body.Shape = shape
+ else:
+ body = FreeCAD.ActiveDocument.addObject("Mesh::Feature",name+"_body")
+ body.Mesh = shape
wall = Arch.makeWall(body,name=name)
wall.Label = name
if DEBUG: print "made wall object ",entity,":",wall
@@ -352,11 +359,12 @@ def makeWindow(entity,shape=None,name="Window"):
try:
if shape:
# use ifcopenshell
- window = Arch.makeWindow(name=name)
- window.Shape = shape
- window.Label = name
- if DEBUG: print "made window object ",entity,":",window
- return window
+ if isinstance(shape,Part.Shape):
+ window = Arch.makeWindow(name=name)
+ window.Shape = shape
+ window.Label = name
+ if DEBUG: print "made window object ",entity,":",window
+ return window
# use internal parser
if DEBUG: print "=====> making window",entity.id
@@ -386,9 +394,13 @@ def makeStructure(entity,shape=None,name="Structure"):
try:
if shape:
# use ifcopenshell
- sh = FreeCAD.ActiveDocument.addObject("Part::Feature","StructureBody")
- sh.Shape = shape
- structure = Arch.makeStructure(sh,name=name)
+ if isinstance(shape,Part.Shape):
+ body = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
+ body.Shape = shape
+ else:
+ body = FreeCAD.ActiveDocument.addObject("Mesh::Feature",name+"_body")
+ body.Mesh = shape
+ structure = Arch.makeStructure(body,name=name)
structure.Label = name
if DEBUG: print "made structure object ",entity,":",structure
return structure
@@ -419,15 +431,37 @@ def makeStructure(entity,shape=None,name="Structure"):
def makeSite(entity,shape=None,name="Site"):
"makes a site in the freecad document"
try:
+ body = None
if shape:
# use ifcopenshell
- site = Arch.makeSite(name=name)
- site.Label = name
- body = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
- body.Shape = shape
+ if isinstance(shape,Part.Shape):
+ body = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
+ body.Shape = shape
+ else:
+ body = FreeCAD.ActiveDocument.addObject("Mesh::Feature",name+"_body")
+ body.Mesh = shape
+ site = Arch.makeSite(name=name)
+ site.Label = name
+ if body:
site.Terrain = body
- if DEBUG: print "made site object ",entity,":",site
- return site
+ if DEBUG: print "made site object ",entity,":",site
+ return site
+ except:
+ return None
+
+def makeSpace(entity,shape=None,name="Space"):
+ "makes a space in the freecad document"
+ try:
+ if shape:
+ # use ifcopenshell
+ if isinstance(shape,Part.Shape):
+ space = Arch.makeSpace(name=name)
+ space.Label = name
+ body = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
+ body.Shape = shape
+ space.Base = body
+ if DEBUG: print "made space object ",entity,":",space
+ return site
except:
return None
@@ -437,11 +471,12 @@ def makeRoof(entity,shape=None,name="Roof"):
try:
if shape:
# use ifcopenshell
- roof = Arch.makeRoof(name=name)
- roof.Label = name
- roof.Shape = shape
- if DEBUG: print "made roof object ",entity,":",roof
- return roof
+ if isinstance(shape,Part.Shape):
+ roof = Arch.makeRoof(name=name)
+ roof.Label = name
+ roof.Shape = shape
+ if DEBUG: print "made roof object ",entity,":",roof
+ return roof
except:
return None
@@ -450,6 +485,9 @@ def makeRoof(entity,shape=None,name="Roof"):
def getMesh(obj):
"gets mesh and placement from an IfcOpenShell object"
import Mesh
+ meshdata = []
+ print obj.mesh.faces
+ print obj.mesh.verts
f = obj.mesh.faces
v = obj.mesh.verts
for i in range(0, len(f), 3):
@@ -458,6 +496,7 @@ def getMesh(obj):
vi = f[i+j]*3
face.append([v[vi],v[vi+1],v[vi+2]])
meshdata.append(face)
+ print meshdata
me = Mesh.Mesh(meshdata)
# get transformation matrix
m = obj.matrix
@@ -470,9 +509,15 @@ def getMesh(obj):
def getShape(obj):
"gets a shape from an IfcOpenShell object"
- import StringIO,Part
+ #print "retrieving shape from obj ",obj.id
+ import Part
sh=Part.Shape()
- sh.importBrep(StringIO.StringIO(obj.mesh.brep_data))
+ try:
+ sh.importBrepFromString(obj.mesh.brep_data)
+ #sh = Part.makeBox(2,2,2)
+ except:
+ print "Error: malformed shape"
+ return None
if not sh.Solids:
# try to extract a solid shape
if sh.Faces:
@@ -494,6 +539,8 @@ def getShape(obj):
0, 0, 0, 1)
sh.Placement = FreeCAD.Placement(mat)
# if DEBUG: print "getting Shape from ",obj
+ #print "getting shape: ",sh,sh.Solids,sh.Volume,sh.isValid(),sh.isNull()
+ #for v in sh.Vertexes: print v.Point
return sh
# below is only used by the internal parser #########################################
diff --git a/src/Mod/CMakeLists.txt b/src/Mod/CMakeLists.txt
index b63fac633..99ba91dd5 100644
--- a/src/Mod/CMakeLists.txt
+++ b/src/Mod/CMakeLists.txt
@@ -51,5 +51,7 @@ add_subdirectory(OpenSCAD)
add_subdirectory(Plot)
+add_subdirectory(Spreadsheet)
+
diff --git a/src/Mod/Complete/App/AppComplete.cpp b/src/Mod/Complete/App/AppComplete.cpp
index 057e8296e..2385ff17b 100644
--- a/src/Mod/Complete/App/AppComplete.cpp
+++ b/src/Mod/Complete/App/AppComplete.cpp
@@ -60,7 +60,7 @@ void AppCompleteExport initComplete()
try {
Base::Interpreter().loadModule("Draft");
}
- catch (const Base::PyException& e) {
+ catch (const Base::Exception& e) {
// If called from console then issue a message but don't stop with an error
PySys_WriteStdout("Import error: %s\n", e.what());
}
diff --git a/src/Mod/Complete/Gui/Workbench.cpp b/src/Mod/Complete/Gui/Workbench.cpp
index 6ccb6b12b..ebc9b06b7 100644
--- a/src/Mod/Complete/Gui/Workbench.cpp
+++ b/src/Mod/Complete/Gui/Workbench.cpp
@@ -140,9 +140,9 @@ Gui::MenuItem* Workbench::setupMenuBar() const
Gui::MenuItem* stdviews = new Gui::MenuItem;
stdviews->setCommand("Standard views");
*stdviews << "Std_ViewFitAll" << "Std_ViewFitSelection" << "Std_ViewAxo"
- << "Separator" << "Std_ViewFront" << "Std_ViewRight"
- << "Std_ViewTop" << "Separator" << "Std_ViewRear"
- << "Std_ViewLeft" << "Std_ViewBottom";
+ << "Separator" << "Std_ViewFront" << "Std_ViewTop"
+ << "Std_ViewRight" << "Separator" << "Std_ViewRear"
+ << "Std_ViewBottom" << "Std_ViewLeft";
// stereo
Gui::MenuItem* view3d = new Gui::MenuItem;
@@ -209,7 +209,6 @@ Gui::MenuItem* Workbench::setupMenuBar() const
mesh->setCommand("&Meshes");
*mesh << "Mesh_Import"
<< "Mesh_Export"
- << "Mesh_FromGeometry"
<< "MeshPart_Mesher"
<< "Separator"
<< analyze
@@ -470,8 +469,8 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
Gui::ToolBarItem* view = new Gui::ToolBarItem( root );
view->setCommand("View");
*view << "Std_ViewFitAll" << "Separator" << "Std_ViewAxo" << "Separator" << "Std_ViewFront"
- << "Std_ViewRight" << "Std_ViewTop" << "Separator" << "Std_ViewRear" << "Std_ViewLeft"
- << "Std_ViewBottom" << "Separator" << "Std_MeasureDistance";
+ << "Std_ViewTop" << "Std_ViewRight" << "Separator" << "Std_ViewRear" << "Std_ViewBottom"
+ << "Std_ViewLeft" << "Separator" << "Std_MeasureDistance";
// Part Design
Gui::ToolBarItem* part_design = new Gui::ToolBarItem( root );
diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt
index e380eb193..95a21c33f 100644
--- a/src/Mod/Draft/CMakeLists.txt
+++ b/src/Mod/Draft/CMakeLists.txt
@@ -17,6 +17,7 @@ SET(Draft_SRCS
importAirfoilDAT.py
macros.py
Draft_rc.py
+ TestDraft.py
)
SOURCE_GROUP("" FILES ${Draft_SRCS})
diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py
index 9f9379d50..9b8161a3e 100644
--- a/src/Mod/Draft/Draft.py
+++ b/src/Mod/Draft/Draft.py
@@ -1,3 +1,5 @@
+# -*- coding: utf8 -*-
+
#***************************************************************************
#* *
#* Copyright (c) 2009, 2010 *
@@ -98,7 +100,7 @@ def typecheck (args_and_types, name="?"):
def getParamType(param):
if param in ["dimsymbol","dimPrecision","dimorientation","precision","defaultWP",
"snapRange","gridEvery","linewidth","UiMode","modconstrain","modsnap",
- "modalt"]:
+ "modalt","HatchPatternResolution"]:
return "int"
elif param in ["constructiongroupname","textfont","patternFile","template","maxSnapEdges",
"snapModes","FontFile"]:
@@ -278,7 +280,11 @@ def getGroupContents(objectslist,walls=False):
newlist = []
for obj in objectslist:
if obj.isDerivedFrom("App::DocumentObjectGroup"):
- newlist.extend(getGroupContents(obj.Group))
+ if obj.isDerivedFrom("Drawing::FeaturePage"):
+ # skip if the grou is a page
+ newlist.append(obj)
+ else:
+ newlist.extend(getGroupContents(obj.Group))
else:
newlist.append(obj)
if walls:
@@ -414,10 +420,13 @@ def loadSvgPatterns():
# getting default patterns
patfiles = QtCore.QDir(":/patterns").entryList()
for fn in patfiles:
- f = QtCore.QFile(":/patterns/"+str(fn))
+ fn = ":/patterns/"+str(fn)
+ f = QtCore.QFile(fn)
f.open(QtCore.QIODevice.ReadOnly)
p = importSVG.getContents(str(f.readAll()),'pattern',True)
if p:
+ for k in p:
+ p[k] = [p[k],fn]
FreeCAD.svgpatterns.update(p)
# looking for user patterns
altpat = getParam("patternFile")
@@ -426,7 +435,19 @@ def loadSvgPatterns():
if f[-4:].upper() == ".SVG":
p = importSVG.getContents(altpat+os.sep+f,'pattern')
if p:
+ for k in p:
+ p[k] = [p[k],fn]
FreeCAD.svgpatterns.update(p)
+
+def svgpatterns():
+ """svgpatterns(): returns a dictionnary with installed SVG patterns"""
+ if hasattr(FreeCAD,"svgpatterns"):
+ return FreeCAD.svgpatterns
+ else:
+ loadSvgPatterns()
+ if hasattr(FreeCAD,"svgpatterns"):
+ return FreeCAD.svgpatterns
+ return {}
def loadTexture(filename,size=None):
"""loadTexture(filename,[size]): returns a SoSFImage from a file. If size
@@ -437,11 +458,11 @@ def loadTexture(filename,size=None):
from PyQt4 import QtGui,QtSvg
try:
if size and (".svg" in filename.lower()):
- # we need to resize
+ # this is a pattern, not a texture
if isinstance(size,int):
size = (size,size)
svgr = QtSvg.QSvgRenderer(filename)
- p = QtGui.QImage(size[0],size[1],QtGui.QImage.Format_ARGB32_Premultiplied)
+ p = QtGui.QImage(size[0],size[1],QtGui.QImage.Format_ARGB32)
pa = QtGui.QPainter()
pa.begin(p)
svgr.render(pa)
@@ -495,7 +516,11 @@ def makeCircle(radius, placement=None, face=True, startangle=None, endangle=None
is passed, its Curve must be a Part.Circle'''
import Part, DraftGeomUtils
if placement: typecheck([(placement,FreeCAD.Placement)], "makeCircle")
- obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Circle")
+ if startangle != endangle:
+ n = "Arc"
+ else:
+ n = "Circle"
+ obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython",n)
_Circle(obj)
if isinstance(radius,Part.Edge):
edge = radius
@@ -587,10 +612,10 @@ def makeDimension(p1,p2,p3=None,p4=None):
obj.Base = p1
if p3 == "radius":
obj.LinkedVertices = [p2,1,1]
- obj.ViewObject.Override = "Rdim"
+ obj.ViewObject.Override = "R$dim"
elif p3 == "diameter":
obj.LinkedVertices = [p2,2,1]
- obj.ViewObject.Override = "Ddim"
+ obj.ViewObject.Override = "Ø$dim"
p3 = p4
if not p3:
p3 = obj.Base.Shape.Edges[0].Curve.Center.add(Vector(1,0,0))
@@ -637,8 +662,8 @@ def makeWire(pointslist,closed=False,placement=None,face=True,support=None):
if DraftGeomUtils.isReallyClosed(pointslist):
closed = True
pointslist = nlist
- print pointslist
- print closed
+ #print pointslist
+ #print closed
if placement: typecheck([(placement,FreeCAD.Placement)], "makeWire")
if len(pointslist) == 2: fname = "Line"
else: fname = "DWire"
@@ -708,7 +733,7 @@ def makeBSpline(pointslist,closed=False,placement=None,face=True,support=None):
obj.Support = support
if placement: obj.Placement = placement
if gui:
- _ViewProviderBSpline(obj.ViewObject)
+ _ViewProviderWire(obj.ViewObject)
if not face: obj.ViewObject.DisplayMode = "Wireframe"
formatObject(obj)
select(obj)
@@ -724,7 +749,9 @@ def makeText(stringslist,point=Vector(0,0,0),screen=False):
typecheck([(point,Vector)], "makeText")
if not isinstance(stringslist,list): stringslist = [stringslist]
textbuffer = []
- for l in stringslist: textbuffer.append(unicode(l).encode('utf-8'))
+ for l in stringslist:
+ #textbuffer.append(l.decode("utf8").encode('latin1'))
+ textbuffer.append(str(l))
obj=FreeCAD.ActiveDocument.addObject("App::Annotation","Text")
obj.LabelText=textbuffer
obj.Position=point
@@ -769,12 +796,15 @@ def makeCopy(obj,force=None,reparent=False):
newobj = FreeCAD.ActiveDocument.addObject(obj.TypeId,getRealName(obj.Name))
_BSpline(newobj)
if gui:
- _ViewProviderBSpline(newobj.ViewObject)
+ _ViewProviderWire(newobj.ViewObject)
elif (getType(obj) == "Block") or (force == "BSpline"):
newobj = FreeCAD.ActiveDocument.addObject(obj.TypeId,getRealName(obj.Name))
_Block(newobj)
if gui:
_ViewProviderDraftPart(newobj.ViewObject)
+ elif (getType(obj) == "DrawingView") or (force == "DrawingView"):
+ newobj = FreeCAD.ActiveDocument.addObject(obj.TypeId,getRealName(obj.Name))
+ _DrawingView(newobj)
elif (getType(obj) == "Structure") or (force == "Structure"):
import ArchStructure
newobj = FreeCAD.ActiveDocument.addObject(obj.TypeId,getRealName(obj.Name))
@@ -793,12 +823,6 @@ def makeCopy(obj,force=None,reparent=False):
ArchWindow._Window(newobj)
if gui:
Archwindow._ViewProviderWindow(newobj.ViewObject)
- elif (getType(obj) == "Cell") or (force == "Cell"):
- import ArchCell
- newobj = FreeCAD.ActiveDocument.addObject(obj.TypeId,getRealName(obj.Name))
- ArchCell._Cell(newobj)
- if gui:
- ArchCell._ViewProviderCell(newobj.ViewObject)
elif (getType(obj) == "Sketch") or (force == "Sketch"):
newobj = FreeCAD.ActiveDocument.addObject("Sketcher::SketchObject",getRealName(obj.Name))
for geo in obj.Geometries:
@@ -819,7 +843,7 @@ def makeCopy(obj,force=None,reparent=False):
parents = obj.InList
if parents:
for par in parents:
- if par.TypeId == "App::DocumentObjectGroup":
+ if par.isDerivedFrom("App::DocumentObjectGroup"):
par.addObject(newobj)
else:
for prop in par.PropertiesList:
@@ -875,6 +899,8 @@ def makeEllipse(majradius,minradius,placement=None,face=True,support=None):
a placement.'''
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Ellipse")
_Ellipse(obj)
+ if minradius > majradius:
+ majradius,minradius = minradius,majradius
obj.MajorRadius = majradius
obj.MinorRadius = minradius
obj.Support = support
@@ -1009,12 +1035,12 @@ def array(objectslist,arg1,arg2,arg3,arg4=None):
typecheck([(xvector,Vector), (yvector,Vector), (xnum,int), (ynum,int)], "rectArray")
if not isinstance(objectslist,list): objectslist = [objectslist]
for xcount in range(xnum):
- currentxvector=DraftVecUtils.scale(xvector,xcount)
+ currentxvector=Vector(xvector).multiply(xcount)
if not xcount==0:
move(objectslist,currentxvector,True)
for ycount in range(ynum):
currentxvector=FreeCAD.Base.Vector(currentxvector)
- currentyvector=currentxvector.add(DraftVecUtils.scale(yvector,ycount))
+ currentyvector=currentxvector.add(Vector(yvector).multiply(ycount))
if not ycount==0:
move(objectslist,currentyvector,True)
def polarArray(objectslist,center,angle,num):
@@ -1102,7 +1128,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy
sh = sh.transformGeometry(m)
corr = Vector(center.x,center.y,center.z)
corr.scale(delta.x,delta.y,delta.z)
- corr = DraftVecUtils.neg(corr.sub(center))
+ corr = (corr.sub(center)).negative()
sh.translate(corr)
if getType(obj) == "Rectangle":
p = []
@@ -1146,7 +1172,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy
obj.Scale = delta
corr = Vector(center.x,center.y,center.z)
corr.scale(delta.x,delta.y,delta.z)
- corr = DraftVecUtils.neg(corr.sub(center))
+ corr = (corr.sub(center)).negative()
p = obj.Placement
p.move(corr)
obj.Placement = p
@@ -1203,8 +1229,8 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False):
pass
else:
if sym:
- d1 = delta.multiply(0.5)
- d2 = DraftVecUtils.neg(d1)
+ d1 = Vector(delta).multiply(0.5)
+ d2 = d1.negative()
n1 = DraftGeomUtils.offsetWire(obj.Shape,d1)
n2 = DraftGeomUtils.offsetWire(obj.Shape,d2)
else:
@@ -1265,9 +1291,9 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False):
obj.Tool = None
obj.Points = p
elif getType(obj) == "BSpline":
- print delta
+ #print delta
obj.Points = delta
- print "done"
+ #print "done"
elif getType(obj) == "Rectangle":
length,height,plac = getRect(p,obj)
obj.Placement = plac
@@ -1323,8 +1349,8 @@ def draftify(objectslist,makeblock=False,delete=True):
return newobjlist[0]
return newobjlist
-def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direction=None):
- '''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction]):
+def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direction=None,linestyle=None):
+ '''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction],[linestyle]):
returns a string containing a SVG representation of the given object,
with the given linewidth and fontsize (used if the given object contains
any text). You can also supply an arbitrary projection vector. the
@@ -1339,22 +1365,18 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
if isinstance(direction,FreeCAD.Vector):
if direction != Vector(0,0,0):
plane = WorkingPlane.plane()
- plane.alignToPointAndAxis(Vector(0,0,0),DraftVecUtils.neg(direction),0)
+ plane.alignToPointAndAxis(Vector(0,0,0),direction.negative(),0)
elif isinstance(direction,WorkingPlane.plane):
plane = direction
- def getLineStyle(obj):
- "returns a linestyle pattern for a given object"
- if gui:
- if obj.ViewObject:
- if hasattr(obj.ViewObject,"DrawStyle"):
- ds = obj.ViewObject.DrawStyle
- if ds == "Dashed":
- return "0.09,0.05"
- elif ds == "Dashdot":
- return "0.09,0.05,0.02,0.05"
- elif ds == "Dotted":
- return "0.02,0.02"
+ def getLineStyle():
+ "returns a linestyle"
+ if linestyle == "Dashed":
+ return "0.09,0.05"
+ elif linestyle == "Dashdot":
+ return "0.09,0.05,0.02,0.05"
+ elif linestyle == "Dotted":
+ return "0.02,0.02"
return "none"
def getProj(vec):
@@ -1368,44 +1390,51 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
return Vector(lx,ly,0)
def getPattern(pat):
- if not hasattr(FreeCAD,"svgpatterns"):
- loadSvgPatterns()
- if pat in FreeCAD.svgpatterns:
- return FreeCAD.svgpatterns[pat]
+ if pat in svgpatterns():
+ return svgpatterns()[pat][0]
return ''
- def getPath(edges):
+ def getPath(edges=[],wires=[]):
import DraftGeomUtils
svg =' 1
- flag_sweep = e.Curve.Axis * drawing_plane_normal >= 0
- v = getProj(e.Vertexes[-1].Point)
- svg += 'A ' + str(r) + ' ' + str(r) + ' '
- svg += '0 ' + str(int(flag_large_arc)) + ' ' + str(int(flag_sweep)) + ' '
- svg += str(v.x) + ' ' + str(v.y) + ' '
- if fill != 'none': svg += 'Z'
+ svg += 'd="'
+ if not wires:
+ egroups = [edges]
+ else:
+ egroups = []
+ for w in wires:
+ egroups.append(w.Edges)
+ for g in egroups:
+ edges = DraftGeomUtils.sortEdges(g)
+ v = getProj(edges[0].Vertexes[0].Point)
+ svg += 'M '+ str(v.x) +' '+ str(v.y) + ' '
+ for e in edges:
+ if DraftGeomUtils.geomType(e) == "Circle":
+ if len(e.Vertexes) == 1:
+ # complete circle
+ svg = getCircle(e)
+ return svg
+ r = e.Curve.Radius
+ drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
+ if plane: drawing_plane_normal = plane.axis
+ flag_large_arc = (((e.ParameterRange[1] - e.ParameterRange[0]) / math.pi) % 2) > 1
+ flag_sweep = e.Curve.Axis * drawing_plane_normal >= 0
+ v = getProj(e.Vertexes[-1].Point)
+ svg += 'A ' + str(r) + ' ' + str(r) + ' '
+ svg += '0 ' + str(int(flag_large_arc)) + ' ' + str(int(flag_sweep)) + ' '
+ svg += str(v.x) + ' ' + str(v.y) + ' '
+ else:
+ v = getProj(e.Vertexes[-1].Point)
+ svg += 'L '+ str(v.x) +' '+ str(v.y) + ' '
+ if fill != 'none': svg += 'Z '
svg += '" '
svg += 'stroke="' + stroke + '" '
svg += 'stroke-width="' + str(linewidth) + ' px" '
svg += 'style="stroke-width:'+ str(linewidth)
svg += ';stroke-miterlimit:4'
svg += ';stroke-dasharray:' + lstyle
- svg += ';fill:' + fill + '"'
+ svg += ';fill:' + fill
+ svg += ';fill-rule: evenodd "'
svg += '/>\n'
return svg
@@ -1428,84 +1457,91 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
pass
elif getType(obj) == "Dimension":
- p1,p2,p3,p4,tbase,norm,rot = obj.ViewObject.Proxy.calcGeom(obj)
- dimText = getParam("dimPrecision")
- dimText = "%."+str(dimText)+"f"
- p1 = getProj(p1)
- p2 = getProj(p2)
- p3 = getProj(p3)
- p4 = getProj(p4)
- tbase = getProj(tbase)
- svg = '\n'
- svg += '\n'
- svg += '\n'
- svg += '\n'
- svg += dimText % p3.sub(p2).Length
- svg += '\n\n'
+ ts = (len(dimText)*obj.ViewObject.FontSize)/4
+ rm = ((p3.sub(p2)).Length/2)-ts
+ p2a = getProj(p2.add(DraftVecUtils.scaleTo(p3.sub(p2),rm)))
+ p2b = getProj(p3.add(DraftVecUtils.scaleTo(p2.sub(p3),rm)))
+ angle = 0
+ svg += 'd="M '+str(p1.x)+' '+str(p1.y)+' '
+ svg += 'L '+str(p2.x)+' '+str(p2.y)+' '
+ svg += 'L '+str(p2a.x)+' '+str(p2a.y)+' '
+ svg += 'M '+str(p2b.x)+' '+str(p2b.y)+' '
+ svg += 'L '+str(p3.x)+' '+str(p3.y)+' '
+ svg += 'L '+str(p4.x)+' '+str(p4.y)+'" '
+ svg += 'fill="none" stroke="'
+ svg += getrgb(obj.ViewObject.LineColor) + '" '
+ svg += 'stroke-width="' + str(linewidth) + ' px" '
+ svg += 'style="stroke-width:'+ str(linewidth)
+ svg += ';stroke-miterlimit:4;stroke-dasharray:none" '
+ svg += 'freecad:basepoint1="'+str(p1.x)+' '+str(p1.y)+'" '
+ svg += 'freecad:basepoint2="'+str(p4.x)+' '+str(p4.y)+'" '
+ svg += 'freecad:dimpoint="'+str(p2.x)+' '+str(p2.y)+'"'
+ svg += '/>\n'
+ svg += '\n'
+ svg += '\n'
+ svg += '\n'
+ svg += dimText % p3.sub(p2).Length
+ svg += '\n\n'
elif getType(obj) == "Annotation":
"returns an svg representation of a document annotation"
p = getProj(obj.Position)
svg = '\n'
- for l in obj.LabelText:
- svg += ''+l+'\n'
+ for i in range(len(obj.LabelText)):
+ if i == 0:
+ svg += ''
+ else:
+ svg += ''
+ svg += obj.LabelText[i]+'\n'
svg += '\n'
+ #print svg
elif getType(obj) == "Axis":
"returns the SVG representation of an Arch Axis system"
color = getrgb(obj.ViewObject.LineColor)
- lorig = getLineStyle(obj)
+ lorig = getLineStyle()
name = obj.Name
stroke = getrgb(obj.ViewObject.LineColor)
fill = 'none'
@@ -1573,13 +1614,16 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
fill = "#888888"
else:
fill = 'none'
- lstyle = getLineStyle(obj)
+ lstyle = getLineStyle()
name = obj.Name
if gui:
- if obj.ViewObject.DisplayMode == "Shaded":
- stroke = "none"
- else:
- stroke = getrgb(obj.ViewObject.LineColor)
+ try:
+ if obj.ViewObject.DisplayMode == "Shaded":
+ stroke = "none"
+ else:
+ stroke = getrgb(obj.ViewObject.LineColor)
+ except:
+ stroke = "#000000"
else:
stroke = "#000000"
@@ -1587,7 +1631,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
wiredEdges = []
if obj.Shape.Faces:
for f in obj.Shape.Faces:
- svg += getPath(f.Edges)
+ svg += getPath(wires=f.Wires)
wiredEdges.extend(f.Edges)
else:
for w in obj.Shape.Wires:
@@ -1638,6 +1682,11 @@ def makeDrawingView(obj,page,lwmod=None,tmod=None):
viewobj.Source = obj
if lwmod: viewobj.LineweightModifier = lwmod
if tmod: viewobj.TextModifier = tmod
+ if hasattr(obj.ViewObject,"Pattern"):
+ if str(obj.ViewObject.Pattern) in svgpatterns().keys():
+ viewobj.FillStyle = str(obj.ViewObject.Pattern)
+ if hasattr(obj.ViewObject,"DrawStyle"):
+ viewobj.LineStyle = obj.ViewObject.DrawStyle
return viewobj
def makeShape2DView(baseobj,projectionVector=None,facenumbers=[]):
@@ -1819,10 +1868,15 @@ def heal(objlist=None,delete=True,reparent=True):
the damaged objects are deleted (default). If ran without arguments, all the objects
in the document will be healed if they are damaged. If reparent is True (default),
new objects go at the very same place in the tree than their original.'''
+
+ auto = False
if not objlist:
objlist = FreeCAD.ActiveDocument.Objects
- print "Healing whole document..."
+ print "Automatic mode: Healing whole document..."
+ auto = True
+ else:
+ print "Manual mode: Force-healing selected objects..."
if not isinstance(objlist,list):
objlist = [objlist]
@@ -1833,8 +1887,12 @@ def heal(objlist=None,delete=True,reparent=True):
for obj in objlist:
dtype = getType(obj)
ftype = obj.TypeId
- if ftype in ["Part::FeaturePython","App::FeaturePython","Part::Part2DObjectPython"]:
- if obj.ViewObject.Proxy == 1 and dtype in ["Unknown","Part"]:
+ if ftype in ["Part::FeaturePython","App::FeaturePython","Part::Part2DObjectPython","Drawing::FeatureViewPython"]:
+ proxy = obj.Proxy
+ if hasattr(obj,"ViewObject"):
+ if hasattr(obj.ViewObject,"Proxy"):
+ proxy = obj.ViewObject.Proxy
+ if (proxy == 1) or (dtype in ["Unknown","Part"]) or (not auto):
got = True
dellist.append(obj.Name)
props = obj.PropertiesList
@@ -1857,6 +1915,8 @@ def heal(objlist=None,delete=True,reparent=True):
elif ("DrawMode" in props) and ("FacesNumber" in props):
print "Healing " + obj.Name + " of type Polygon"
nobj = makeCopy(obj,force="Polygon",reparent=reparent)
+ elif ("FillStyle" in props) and ("FontSize" in props):
+ nobj = makeCopy(obj,force="DrawingView",reparent=reparent)
else:
dellist.pop()
print "Object " + obj.Name + " is not healable"
@@ -2165,7 +2225,7 @@ def upgrade(objects,delete=False,force=None):
elif wires and (not faces) and (not openwires):
# we have a sketch: Extract a face
- if (len(objects) == 1) and objects[0].isDerivedFrom("Sketcher::SketchObject") and (not curves):
+ if (len(objects) == 1) and objects[0].isDerivedFrom("Sketcher::SketchObject"):
result = makeSketchFace(objects[0])
if result: msg(translate("draft", "Found 1 closed sketch object: making a face from it\n"))
@@ -2410,41 +2470,100 @@ class _DraftObject:
class _ViewProviderDraft:
"The base class for Draft Viewproviders"
- def __init__(self, obj):
- obj.Proxy = self
- self.Object = obj.Object
+ def __init__(self, vobj):
+ from DraftTools import translate
+ vobj.Proxy = self
+ self.Object = vobj.Object
+ vobj.addProperty("App::PropertyEnumeration","Pattern",
+ "Pattern","Defines a hatch pattern")
+ vobj.addProperty("App::PropertyFloat","PatternSize",
+ "Pattern","Sets the size of the pattern")
+ vobj.Pattern = [str(translate("draft","None"))]+svgpatterns().keys()
+ vobj.PatternSize = 1
def __getstate__(self):
return None
- def __setstate__(self,state):
+ def __setstate__(self, state):
return None
- def attach(self, obj):
- self.Object = obj.Object
+ def attach(self,vobj):
+ self.texture = None
+ self.texcoords = None
+ self.Object = vobj.Object
return
- def updateData(self, fp, prop):
+ def updateData(self, obj, prop):
return
- def getDisplayModes(self,obj):
+ def getDisplayModes(self, vobj):
modes=[]
return modes
- def setDisplayMode(self,mode):
+ def setDisplayMode(self, mode):
return mode
- def onChanged(self, vp, prop):
+ def onChanged(self, vobj, prop):
+ # treatment of patterns and image textures
+ if prop in ["TextureImage","Pattern"]:
+ if hasattr(self.Object,"Shape"):
+ if self.Object.Shape.Faces:
+ from pivy import coin
+ from PyQt4 import QtCore
+ path = None
+ if hasattr(vobj,"TextureImage"):
+ if vobj.TextureImage:
+ path = vobj.TextureImage
+ if not path:
+ if str(vobj.Pattern) in svgpatterns().keys():
+ path = svgpatterns()[vobj.Pattern][1]
+ if path:
+ r = vobj.RootNode.getChild(2).getChild(0).getChild(2)
+ i = QtCore.QFileInfo(path)
+ if self.texture:
+ r.removeChild(self.texture)
+ self.texture = None
+ if self.texcoords:
+ r.removeChild(self.texcoords)
+ self.texcoords = None
+ if i.exists():
+ size = None
+ if ":/patterns" in path:
+ size = getParam("HatchPAtternResolution")
+ if not size:
+ size = 128
+ im = loadTexture(path, size)
+ if im:
+ self.texture = coin.SoTexture2()
+ self.texture.image = im
+ r.insertChild(self.texture,1)
+ if size:
+ s =1
+ if hasattr(vobj,"PatternSize"):
+ if vobj.PatternSize:
+ s = vobj.PatternSize
+ self.texcoords = coin.SoTextureCoordinatePlane()
+ self.texcoords.directionS.setValue(s,0,0)
+ self.texcoords.directionT.setValue(0,s,0)
+ r.insertChild(self.texcoords,2)
+ elif prop == "PatternSize":
+ if hasattr(self,"texcoords"):
+ if self.texcoords:
+ s = 1
+ if vobj.PatternSize:
+ s = vobj.PatternSize
+ self.texcoords.directionS.setValue(s,0,0)
+ self.texcoords.directionT.setValue(0,s,0)
return
- def execute(self,obj):
+ def execute(self,vobj):
return
- def setEdit(self,vp,mode):
+ def setEdit(self,vobj,mode):
FreeCADGui.runCommand("Draft_Edit")
return True
- def unsetEdit(self,vp,mode):
+ def unsetEdit(self,vobj,mode):
if FreeCAD.activeDraftCommand:
FreeCAD.activeDraftCommand.finish()
FreeCADGui.Control.closeDialog()
@@ -2467,7 +2586,8 @@ class _ViewProviderDraftAlt(_ViewProviderDraft):
"a view provider that doesn't swallow its base object"
def __init__(self,vobj):
- _ViewProviderDraft.__init__(self,vobj)
+ vobj.Proxy = self
+ self.Object = vobj.Object
def claimChildren(self):
return []
@@ -2476,7 +2596,8 @@ class _ViewProviderDraftPart(_ViewProviderDraftAlt):
"a view provider that displays a Part icon instead of a Draft icon"
def __init__(self,vobj):
- _ViewProviderDraftAlt.__init__(self,vobj)
+ vobj.Proxy = self
+ self.Object = vobj.Object
def getIcon(self):
return ":/icons/Tree_Part.svg"
@@ -2517,7 +2638,7 @@ class _ViewProviderDimension(_ViewProviderDraft):
obj.addProperty("App::PropertyColor","LineColor","Base","Line color")
obj.addProperty("App::PropertyLength","ExtLines","Base","Ext lines")
obj.addProperty("App::PropertyVector","TextPosition","Base","The position of the text. Leave (0,0,0) for automatic position")
- obj.addProperty("App::PropertyString","Override","Base","Text override. Use 'dim' to insert the dimension length")
+ obj.addProperty("App::PropertyString","Override","Base","Text override. Use $dim to insert the dimension length")
obj.FontSize=getParam("textheight")
obj.FontName=getParam("textfont")
obj.ExtLines=0.3
@@ -2535,35 +2656,35 @@ class _ViewProviderDimension(_ViewProviderDraft):
p2 = p1
p3 = p4
else:
- p2 = p1.add(DraftVecUtils.neg(proj))
- p3 = p4.add(DraftVecUtils.neg(proj))
+ p2 = p1.add(proj.negative())
+ p3 = p4.add(proj.negative())
dmax = obj.ViewObject.ExtLines
if dmax and (proj.Length > dmax):
p1 = p2.add(DraftVecUtils.scaleTo(proj,dmax))
p4 = p3.add(DraftVecUtils.scaleTo(proj,dmax))
- midpoint = p2.add(DraftVecUtils.scale(p3.sub(p2),0.5))
+ midpoint = p2.add((p3.sub(p2).multiply(0.5)))
if not proj:
ed = DraftGeomUtils.vec(base)
proj = ed.cross(Vector(0,0,1))
if not proj: norm = Vector(0,0,1)
- else: norm = DraftVecUtils.neg(p3.sub(p2).cross(proj))
+ else: norm = (p3.sub(p2).cross(proj)).negative()
if not DraftVecUtils.isNull(norm):
norm.normalize()
va = get3DView().getViewDirection()
if va.getAngle(norm) < math.pi/2:
- norm = DraftVecUtils.neg(norm)
+ norm = norm.negative()
u = p3.sub(p2)
u.normalize()
c = get3DView().getCameraNode()
r = c.orientation.getValue()
ru = Vector(r.multVec(coin.SbVec3f(1,0,0)).getValue())
- if ru.getAngle(u) > math.pi/2: u = DraftVecUtils.neg(u)
+ if ru.getAngle(u) > math.pi/2: u = u.negative()
v = norm.cross(u)
offset = DraftVecUtils.scaleTo(v,obj.ViewObject.FontSize*.2)
if obj.ViewObject:
if hasattr(obj.ViewObject,"DisplayMode"):
if obj.ViewObject.DisplayMode == "3D":
- offset = DraftVecUtils.neg(offset)
+ offset = offset.negative()
if hasattr(obj.ViewObject,"TextPosition"):
if obj.ViewObject.TextPosition == Vector(0,0,0):
tbase = midpoint.add(offset)
@@ -2644,7 +2765,7 @@ class _ViewProviderDimension(_ViewProviderDraft):
self.onChanged(obj,"FontName")
def updateData(self, obj, prop):
- if not prop in ["Start","End","Dimline"]:
+ if not prop in ["Start","End","Dimline","DisplayMode","ExtLines","FontSize","Override"]:
return
from pivy import coin
try:
@@ -2662,7 +2783,7 @@ class _ViewProviderDimension(_ViewProviderDraft):
if obj.LinkedVertices[1] == 1:
v1 = c
else:
- v1 = c.add(DraftVecUtils.neg(bray))
+ v1 = c.add(bray.negative())
v2 = c.add(bray)
else:
# linear linked dimension
@@ -2673,12 +2794,12 @@ class _ViewProviderDimension(_ViewProviderDraft):
p1,p2,p3,p4,tbase,norm,rot = self.calcGeom(obj)
# print p1,p2,p3,p4,tbase,norm,rot
if 'Override' in obj.ViewObject.PropertiesList:
- text = str(obj.ViewObject.Override)
+ text = unicode(obj.ViewObject.Override).encode("latin1")
dtext = getParam("dimPrecision")
dtext = "%."+str(dtext)+"f"
dtext = (dtext % p3.sub(p2).Length)
if text:
- text = text.replace("dim",dtext)
+ text = text.replace("$dim",dtext)
else:
text = dtext
if hasattr(self,"text"):
@@ -2717,6 +2838,7 @@ class _ViewProviderDimension(_ViewProviderDraft):
self.font.size = vp.FontSize
if hasattr(self,"font3d"):
self.font3d.size = vp.FontSize*100
+ self.updateData(vp.Object, prop)
elif prop == "FontName":
if hasattr(self,"font") and hasattr(self,"font3d"):
self.font.name = self.font3d.name = str(vp.FontName)
@@ -2730,7 +2852,7 @@ class _ViewProviderDimension(_ViewProviderDraft):
else:
if hasattr(self,"drawstyle"):
self.drawstyle.lineWidth = vp.LineWidth
- self.updateData(vp.Object, None)
+ self.updateData(vp.Object, prop)
def getDisplayModes(self,obj):
return ["2D","3D"]
@@ -2944,7 +3066,7 @@ class _ViewProviderAngularDimension(_ViewProviderDraft):
self.arc = arc
self.selnode.addChild(self.arc)
if 'Override' in obj.ViewObject.PropertiesList:
- text = str(obj.ViewObject.Override)
+ text = unicode(obj.ViewObject.Override).encode("latin1")
dtext = getParam("dimPrecision")
dtext = "%."+str(dtext)+"f"
if obj.LastAngle > obj.FirstAngle:
@@ -3058,37 +3180,11 @@ class _Rectangle(_DraftObject):
fp.Placement = plm
class _ViewProviderRectangle(_ViewProviderDraft):
- "A View Provider for the Rectangle object"
- def __init__(self, vobj):
+ def __init__(self,vobj):
_ViewProviderDraft.__init__(self,vobj)
vobj.addProperty("App::PropertyFile","TextureImage",
- "Base","Uses an image as a texture map")
+ "Pattern","Defines a texture image (overrides hatch patterns)")
- def attach(self,vobj):
- self.texture = None
- self.Object = vobj.Object
-
- def onChanged(self, vp, prop):
- from pivy import coin
- from PyQt4 import QtCore
- if prop == "TextureImage":
- r = vp.RootNode
- i = QtCore.QFileInfo(vp.TextureImage)
- if i.exists():
- size = None
- if ":/patterns" in vp.TextureImage:
- size = 128
- im = loadTexture(vp.TextureImage, size)
- if im:
- self.texture = coin.SoTexture2()
- self.texture.image = im
- r.insertChild(self.texture,1)
- else:
- if self.texture:
- r.removeChild(self.texture)
- self.texture = None
- return
-
class _Circle(_DraftObject):
"The Circle object"
@@ -3220,9 +3316,6 @@ class _Wire(_DraftObject):
if fp.Base.Shape.isClosed():
shape = Part.Face(shape)
fp.Shape = shape
- p = []
- for v in shape.Vertexes: p.append(v.Point)
- if fp.Points != p: fp.Points = p
elif fp.Base and fp.Tool:
if fp.Base.isDerivedFrom("Part::Feature") and fp.Tool.isDerivedFrom("Part::Feature"):
if (not fp.Base.Shape.isNull()) and (not fp.Tool.Shape.isNull()):
@@ -3290,6 +3383,7 @@ class _ViewProviderWire(_ViewProviderDraft):
self.pt.addChild(col)
self.pt.addChild(self.coords)
self.pt.addChild(dimSymbol())
+ _ViewProviderDraft.attach(self,obj)
def updateData(self, obj, prop):
if prop == "Points":
@@ -3305,10 +3399,13 @@ class _ViewProviderWire(_ViewProviderDraft):
rn.addChild(self.pt)
else:
rn.removeChild(self.pt)
+ _ViewProviderDraft.onChanged(self,vp,prop)
return
def claimChildren(self):
- return [self.Object.Base,self.Object.Tool]
+ if hasattr(self.Object,"Base"):
+ return [self.Object.Base,self.Object.Tool]
+ return []
class _Polygon(_DraftObject):
"The Polygon object"
@@ -3365,16 +3462,13 @@ class _DrawingView(_DraftObject):
def __init__(self, obj):
_DraftObject.__init__(self,obj,"DrawingView")
obj.addProperty("App::PropertyVector","Direction","Shape View","Projection direction")
- obj.addProperty("App::PropertyFloat","LineWidth","Drawing View","The width of the lines inside this object")
- obj.addProperty("App::PropertyFloat","FontSize","Drawing View","The size of the texts inside this object")
+ obj.addProperty("App::PropertyFloat","LineWidth","View Style","The width of the lines inside this object")
+ obj.addProperty("App::PropertyFloat","FontSize","View Style","The size of the texts inside this object")
obj.addProperty("App::PropertyLink","Source","Base","The linked object")
- obj.addProperty("App::PropertyEnumeration","FillStyle","Drawing View","Shape Fill Style")
- fills = ['shape color']
- if not hasattr(FreeCAD,"svgpatterns"):
- loadSvgPatterns()
- for f in FreeCAD.svgpatterns.keys():
- fills.append(f)
- obj.FillStyle = fills
+ obj.addProperty("App::PropertyEnumeration","FillStyle","View Style","Shape Fill Style")
+ obj.addProperty("App::PropertyEnumeration","LineStyle","View Style","Line Style")
+ obj.FillStyle = ['shape color'] + svgpatterns().keys()
+ obj.LineStyle = ['Solid','Dashed','Dotted','Dashdot']
obj.LineWidth = 0.35
obj.FontSize = 12
@@ -3383,21 +3477,35 @@ class _DrawingView(_DraftObject):
obj.ViewResult = self.updateSVG(obj)
def onChanged(self, obj, prop):
- if prop in ["X","Y","Scale","LineWidth","FontSize","FillStyle","Direction"]:
+ if prop in ["X","Y","Scale","LineWidth","FontSize","FillStyle","Direction","LineStyle"]:
obj.ViewResult = self.updateSVG(obj)
def updateSVG(self, obj):
"encapsulates a svg fragment into a transformation node"
- svg = getSVG(obj.Source,obj.Scale,obj.LineWidth,obj.FontSize,obj.FillStyle,obj.Direction)
- result = ''
- result += ''
- result += svg
- result += ''
+ result = ""
+ if hasattr(obj,"Source"):
+ if obj.Source:
+ if hasattr(obj,"LineStyle"):
+ ls = obj.LineStyle
+ else:
+ ls = None
+ if obj.Source.isDerivedFrom("App::DocumentObjectGroup"):
+ svg = ""
+ shapes = []
+ others = []
+ for o in obj.Source.Group:
+ if o.ViewObject.isVisible():
+ svg += getSVG(o,obj.Scale,obj.LineWidth,obj.FontSize,obj.FillStyle,obj.Direction,ls)
+ else:
+ svg = getSVG(obj.Source,obj.Scale,obj.LineWidth,obj.FontSize,obj.FillStyle,obj.Direction,ls)
+ result += ''
+ result += svg
+ result += ''
return result
class _BSpline(_DraftObject):
@@ -3438,39 +3546,8 @@ class _BSpline(_DraftObject):
fp.Shape = spline.toShape()
fp.Placement = plm
-class _ViewProviderBSpline(_ViewProviderDraft):
- "A View Provider for the BSPline object"
- def __init__(self, obj):
- from pivy import coin
- _ViewProviderDraft.__init__(self,obj)
- obj.addProperty("App::PropertyBool","EndArrow",
- "Base","Displays a dim symbol at the end of the wire")
- col = coin.SoBaseColor()
- col.rgb.setValue(obj.LineColor[0],
- obj.LineColor[1],
- obj.LineColor[2])
- self.coords = coin.SoCoordinate3()
- self.pt = coin.SoAnnotation()
- self.pt.addChild(col)
- self.pt.addChild(self.coords)
- self.pt.addChild(dimSymbol())
-
- def updateData(self, obj, prop):
- if prop == "Points":
- if obj.Points:
- p = obj.Points[-1]
- if hasattr(self,"coords"):
- self.coords.point.setValue((p.x,p.y,p.z))
- return
-
- def onChanged(self, vp, prop):
- if prop == "EndArrow":
- rn = vp.RootNode
- if vp.EndArrow:
- rn.addChild(self.pt)
- else:
- rn.removeChild(self.pt)
- return
+# for compatibility with older versions
+_ViewProviderBSpline = _ViewProviderWire
class _Block(_DraftObject):
"The Block object"
@@ -3684,21 +3761,21 @@ class _Array(_DraftObject):
import Part
base = [shape.copy()]
for xcount in range(xnum):
- currentxvector=DraftVecUtils.scale(xvector,xcount)
+ currentxvector=Vector(xvector).multiply(xcount)
if not xcount==0:
nshape = shape.copy()
nshape.translate(currentxvector)
base.append(nshape)
for ycount in range(ynum):
currentyvector=FreeCAD.Vector(currentxvector)
- currentyvector=currentyvector.add(DraftVecUtils.scale(yvector,ycount))
+ currentyvector=currentyvector.add(Vector(yvector).multiply(ycount))
if not ycount==0:
nshape = shape.copy()
nshape.translate(currentyvector)
base.append(nshape)
for zcount in range(znum):
currentzvector=FreeCAD.Vector(currentyvector)
- currentzvector=currentzvector.add(DraftVecUtils.scale(zvector,zcount))
+ currentzvector=currentzvector.add(Vector(zvector).multiply(zcount))
if not zcount==0:
nshape = shape.copy()
nshape.translate(currentzvector)
@@ -3706,7 +3783,7 @@ class _Array(_DraftObject):
return Part.makeCompound(base)
def polarArray(self,shape,center,angle,num,axis):
- print "angle ",angle," num ",num
+ #print "angle ",angle," num ",num
import Part
if angle == 360:
fraction = angle/num
diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py
index 1f81d6ed3..d35122965 100755
--- a/src/Mod/Draft/DraftGeomUtils.py
+++ b/src/Mod/Draft/DraftGeomUtils.py
@@ -177,6 +177,19 @@ def geomType(edge):
return "Unknown"
except:
return "Unknown"
+
+def isValidPath(shape):
+ "isValidPath(shape): returns True if the shape can be used as an extrusion path"
+ if shape.Faces:
+ return False
+ if len(shape.Wires) > 1:
+ return False
+ if shape.Wires:
+ if shape.Wires[0].isClosed():
+ return False
+ if shape.isClosed():
+ return False
+ return True
# edge functions *****************************************************************
@@ -400,8 +413,8 @@ def geom(edge,plac=FreeCAD.Placement()):
c = edge.Curve.Center
cu = Part.Circle(edge.Curve.Center,normal,edge.Curve.Radius)
ref = plac.Rotation.multVec(Vector(1,0,0))
- a1 = DraftVecUtils.angle(v1.sub(c),ref,DraftVecUtils.neg(normal))
- a2 = DraftVecUtils.angle(v2.sub(c),ref,DraftVecUtils.neg(normal))
+ a1 = DraftVecUtils.angle(v1.sub(c),ref,normal.negative())
+ a2 = DraftVecUtils.angle(v2.sub(c),ref,normal.negative())
# direction check
if edge.Curve.Axis.getAngle(normal) > 1:
@@ -418,7 +431,7 @@ def mirror (point, edge):
normPoint = point.add(findDistance(point, edge, False))
if normPoint:
normPoint_point = Vector.sub(point, normPoint)
- normPoint_refl = DraftVecUtils.neg(normPoint_point)
+ normPoint_refl = normPoint_point.negative()
refl = Vector.add(normPoint, normPoint_refl)
return refl
else:
@@ -438,7 +451,7 @@ def isClockwise(edge,ref=None):
if not ref:
ref = Vector(0,0,1)
if n.getAngle(ref) > math.pi/2:
- n = DraftVecUtils.neg(n)
+ n = n.negative()
if DraftVecUtils.angle(v1,v2,n) < 0:
return False
if n.z < 0:
@@ -721,7 +734,7 @@ def findMidpoint(edge):
if len(edge.Vertexes) == 1:
# Circle
dv = first.sub(center)
- dv = DraftVecUtils.neg(dv)
+ dv = dv.negative()
return center.add(dv)
axis = edge.Curve.Axis
chord = last.sub(first)
@@ -730,12 +743,12 @@ def findMidpoint(edge):
ray = first.sub(center)
apothem = ray.dot(perp)
sagitta = radius - apothem
- startpoint = Vector.add(first, DraftVecUtils.scale(chord,0.5))
+ startpoint = Vector.add(first, chord.multiply(0.5))
endpoint = DraftVecUtils.scaleTo(perp,sagitta)
return Vector.add(startpoint,endpoint)
elif geomType(edge) == "Line":
- halfedge = DraftVecUtils.scale(last.sub(first),.5)
+ halfedge = (last.sub(first)).multiply(.5)
return Vector.add(first,halfedge)
else:
@@ -850,7 +863,8 @@ def getNormal(shape):
if FreeCAD.GuiUp:
import Draft
vdir = Draft.get3DView().getViewDirection()
- if n.getAngle(vdir) < 0.78: n = DraftVecUtils.neg(n)
+ if n.getAngle(vdir) < 0.78:
+ n = n.negative()
return n
def getRotation(v1,v2=FreeCAD.Vector(0,0,1)):
@@ -1003,7 +1017,7 @@ def findDistance(point,edge,strict=False):
center = edge.Curve.Center
segment = center.sub(point)
ratio = (segment.Length - edge.Curve.Radius) / segment.Length
- dist = DraftVecUtils.scale(segment,ratio)
+ dist = segment.multiply(ratio)
newpoint = Vector.add(point, dist)
if (dist.Length == 0):
return None
@@ -1053,7 +1067,7 @@ def angleBisection(edge1, edge2):
return Part.Line(origin,origin.add(dir)).toShape()
else:
diff = p3.sub(p1)
- origin = p1.add(DraftVecUtils.scale(diff, 0.5))
+ origin = p1.add(diff.multiply(0.5))
dir = p2.sub(p1); dir.normalize()
return Part.Line(origin,origin.add(dir)).toShape()
else:
@@ -1857,8 +1871,8 @@ def circlefrom1Line2Points(edge, p1, p2):
v2 = p2.sub(s)
projectedDist = math.sqrt(abs(v1.dot(v2)))
edgeDir = vec(edge); edgeDir.normalize()
- projectedCen1 = Vector.add(s, DraftVecUtils.scale(edgeDir, projectedDist))
- projectedCen2 = Vector.add(s, DraftVecUtils.scale(edgeDir, -projectedDist))
+ projectedCen1 = Vector.add(s, Vector(edgeDir).multiply(projectedDist))
+ projectedCen2 = Vector.add(s, Vector(edgeDir).multiply(-projectedDist))
perpEdgeDir = edgeDir.cross(Vector(0,0,1))
perpCen1 = Vector.add(projectedCen1, perpEdgeDir)
perpCen2 = Vector.add(projectedCen2, perpEdgeDir)
@@ -1890,13 +1904,13 @@ def circleFrom2LinesRadius (edge1, edge2, radius):
dist12 = radius / math.sin(ang12 * 0.5)
dist21 = radius / math.sin(ang21 * 0.5)
circles = []
- cen = Vector.add(int, DraftVecUtils.scale(vec(bis12), dist12))
+ cen = Vector.add(int, vec(bis12).multiply(dist12))
circles.append(Part.Circle(cen, NORM, radius))
- cen = Vector.add(int, DraftVecUtils.scale(vec(bis12), -dist12))
+ cen = Vector.add(int, vec(bis12).multiply(-dist12))
circles.append(Part.Circle(cen, NORM, radius))
- cen = Vector.add(int, DraftVecUtils.scale(vec(bis21), dist21))
+ cen = Vector.add(int, vec(bis21).multiply(dist21))
circles.append(Part.Circle(cen, NORM, radius))
- cen = Vector.add(int, DraftVecUtils.scale(vec(bis21), -dist21))
+ cen = Vector.add(int, vec(bis21).multiply(-dist21))
circles.append(Part.Circle(cen, NORM, radius))
return circles
@@ -1954,15 +1968,15 @@ def circleFromPointLineRadius (point, edge, radius):
if dist.Length == 0:
segment = vec(edge)
perpVec = DraftVecUtils.crossproduct(segment); perpVec.normalize()
- normPoint_c1 = DraftVecUtils.scale(perpVec, radius)
- normPoint_c2 = DraftVecUtils.scale(perpVec, -radius)
+ normPoint_c1 = Vector(perpVec).multiply(radius)
+ normPoint_c2 = Vector(perpVec).multiply(-radius)
center1 = point.add(normPoint_c1)
center2 = point.add(normPoint_c2)
elif dist.Length > 2 * radius:
return None
elif dist.Length == 2 * radius:
normPoint = point.add(findDistance(point, edge, False))
- dummy = DraftVecUtils.scale(normPoint.sub(point), 0.5)
+ dummy = (normPoint.sub(point)).multiply(0.5)
cen = point.add(dummy)
circ = Part.Circle(cen, NORM, radius)
if circ:
@@ -1975,8 +1989,8 @@ def circleFromPointLineRadius (point, edge, radius):
dist = math.sqrt(radius**2 - (radius - normDist)**2)
centerNormVec = DraftVecUtils.scaleTo(point.sub(normPoint), radius)
edgeDir = edge.Vertexes[0].Point.sub(normPoint); edgeDir.normalize()
- center1 = centerNormVec.add(normPoint.add(DraftVecUtils.scale(edgeDir, dist)))
- center2 = centerNormVec.add(normPoint.add(DraftVecUtils.scale(edgeDir, -dist)))
+ center1 = centerNormVec.add(normPoint.add(Vector(edgeDir).multiply(dist)))
+ center2 = centerNormVec.add(normPoint.add(Vector(edgeDir).multiply(-dist)))
circles = []
if center1:
circ = Part.Circle(center1, NORM, radius)
@@ -2006,8 +2020,8 @@ def circleFrom2PointsRadius(p1, p2, radius):
dir = vec(p1_p2); dir.normalize()
perpDir = dir.cross(Vector(0,0,1)); perpDir.normailze()
dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0)**2)
- cen1 = Vector.add(mid, DraftVecUtils.scale(perpDir, dist))
- cen2 = Vector.add(mid, DraftVecUtils.scale(perpDir, -dist))
+ cen1 = Vector.add(mid, Vector(perpDir).multiply(dist))
+ cen2 = Vector.add(mid, Vector(perpDir).multiply(-dist))
circles = []
if cen1: circles.append(Part.Circle(cen1, norm, radius))
if cen2: circles.append(Part.Circle(cen2, norm, radius))
@@ -2252,12 +2266,12 @@ def findHomotheticCenterOfCircles(circle1, circle2):
perpCenDir = cenDir.cross(Vector(0,0,1)); perpCenDir.normalize()
# Get point on first circle
- p1 = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, circle1.Curve.Radius))
+ p1 = Vector.add(circle1.Curve.Center, Vector(perpCenDir).multiply(circle1.Curve.Radius))
centers = []
# Calculate inner homothetic center
# Get point on second circle
- p2_inner = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, -circle1.Curve.Radius))
+ p2_inner = Vector.add(circle1.Curve.Center, Vector(perpCenDir).multiply(-circle1.Curve.Radius))
hCenterInner = DraftVecUtils.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_inner, True, True)
if hCenterInner:
centers.append(hCenterInner)
@@ -2265,7 +2279,7 @@ def findHomotheticCenterOfCircles(circle1, circle2):
# Calculate outer homothetic center (only exists of the circles have different radii)
if circle1.Curve.Radius != circle2.Curve.Radius:
# Get point on second circle
- p2_outer = Vector.add(circle1.Curve.Center, DraftVecUtils.scale(perpCenDir, circle1.Curve.Radius))
+ p2_outer = Vector.add(circle1.Curve.Center, Vector(perpCenDir).multiply(circle1.Curve.Radius))
hCenterOuter = DraftVecUtils.intersect(circle1.Curve.Center, circle2.Curve.Center, p1, p2_outer, True, True)
if hCenterOuter:
centers.append(hCenterOuter)
@@ -2315,7 +2329,7 @@ def findRadicalAxis(circle1, circle2):
k1 = (dist + (r1^2 - r2^2) / dist) / 2.0
#k2 = dist - k1
- K = Vector.add(cen1, DraftVecUtils.scale(cenDir, k1))
+ K = Vector.add(cen1, cenDir.multiply(k1))
# K_ .. A point somewhere between K and J (actually with a distance of 1 unit from K).
K_ = Vector,add(K, perpCenDir)
diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py
index ff4d9e0da..45d816428 100644
--- a/src/Mod/Draft/DraftGui.py
+++ b/src/Mod/Draft/DraftGui.py
@@ -978,13 +978,13 @@ class DraftToolBar:
last = self.sourceCmd.node[0]
else:
last = self.sourceCmd.node[-1]
- print "last:",last
+ #print "last:",last
v = FreeCAD.Vector(numx,numy,numz)
- print "orig:",v
+ #print "orig:",v
if FreeCAD.DraftWorkingPlane:
v = FreeCAD.Vector(numx,numy,numz)
v = FreeCAD.DraftWorkingPlane.getGlobalRot(v)
- print "rotated:",v
+ #print "rotated:",v
numx = last.x + v.x
numy = last.y + v.y
numz = last.z + v.z
@@ -1418,7 +1418,7 @@ class DraftToolBar:
def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange:
- print "Language changed!"
+ #print "Language changed!"
self.ui.retranslateUi(self)
def Activated(self):
diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py
index 9f5d98202..b8c0fe03a 100644
--- a/src/Mod/Draft/DraftSnap.py
+++ b/src/Mod/Draft/DraftSnap.py
@@ -258,7 +258,7 @@ class Snapper:
elif (Draft.getType(obj) == "Structure") and not oldActive:
# special snapping for struct: only to its base point (except when CTRL is pressed)
if obj.Base:
- for edge in o.Base.Shape.Edges:
+ for edge in obj.Base.Shape.Edges:
snaps.extend(self.snapToEndpoints(edge))
snaps.extend(self.snapToMidpoint(edge))
snaps.extend(self.snapToPerpendicular(edge,lastpoint))
@@ -466,13 +466,13 @@ class Snapper:
FreeCAD.Vector(0,0,1)]
for a in self.polarAngles:
if a == 90:
- vecs.extend([ax[0],DraftVecUtils.neg(ax[0])])
- vecs.extend([ax[1],DraftVecUtils.neg(ax[1])])
+ vecs.extend([ax[0],ax[0].negative()])
+ vecs.extend([ax[1],ax[1].negative()])
else:
v = DraftVecUtils.rotate(ax[0],math.radians(a),ax[2])
- vecs.extend([v,DraftVecUtils.neg(v)])
+ vecs.extend([v,v.negative()])
v = DraftVecUtils.rotate(ax[1],math.radians(a),ax[2])
- vecs.extend([v,DraftVecUtils.neg(v)])
+ vecs.extend([v,v.negative()])
for v in vecs:
de = Part.Line(last,last.add(v)).toShape()
np = self.getPerpendicular(de,point)
@@ -1054,5 +1054,5 @@ if not hasattr(FreeCADGui,"Snapper"):
if not hasattr(FreeCAD,"DraftWorkingPlane"):
import WorkingPlane, Draft_rc
FreeCAD.DraftWorkingPlane = WorkingPlane.plane()
- print FreeCAD.DraftWorkingPlane
+ #print FreeCAD.DraftWorkingPlane
FreeCADGui.addIconPath(":/icons")
diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py
index fe67b50f9..089d80e63 100644
--- a/src/Mod/Draft/DraftTools.py
+++ b/src/Mod/Draft/DraftTools.py
@@ -232,12 +232,7 @@ class DraftTool:
self.ui.sourceCmd = self
self.ui.setTitle(name)
self.ui.show()
- try:
- rot = self.view.getCameraNode().getField("orientation").getValue()
- upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue())
- plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv)
- except:
- pass
+ plane.setup()
self.node = []
self.pos = []
self.constrain = None
@@ -382,7 +377,7 @@ class SelectPlane(DraftTool):
self.display('side')
self.finish()
elif arg == "currentView":
- viewDirection = DraftVecUtils.neg(self.view.getViewDirection())
+ viewDirection = self.view.getViewDirection().negative()
plane.alignToPointAndAxis(Vector(0,0,0), viewDirection, self.offset)
self.display(viewDirection)
self.finish()
@@ -780,10 +775,10 @@ class Rectangle(Creator):
base = p1
if length < 0:
length = -length
- base = base.add(DraftVecUtils.neg(p1.sub(p4)))
+ base = base.add((p1.sub(p4)).negative())
if height < 0:
height = -height
- base = base.add(DraftVecUtils.neg(p1.sub(p2)))
+ base = base.add((p1.sub(p2)).negative())
self.commit(translate("draft","Create Plane"),
['plane = FreeCAD.ActiveDocument.addObject("Part::Plane","Plane")',
'plane.Length = '+str(length),
@@ -915,7 +910,7 @@ class Arc(Creator):
if self.center and DraftVecUtils.dist(self.point,self.center) > 0:
viewdelta = DraftVecUtils.project(self.point.sub(self.center), plane.axis)
if not DraftVecUtils.isNull(viewdelta):
- self.point = self.point.add(DraftVecUtils.neg(viewdelta))
+ self.point = self.point.add(viewdelta.negative())
if (self.step == 0): # choose center
if hasMod(arg,MODALT):
if not self.altdown:
@@ -1202,7 +1197,7 @@ class Polygon(Creator):
if self.center and DraftVecUtils.dist(self.point,self.center) > 0:
viewdelta = DraftVecUtils.project(self.point.sub(self.center), plane.axis)
if not DraftVecUtils.isNull(viewdelta):
- self.point = self.point.add(DraftVecUtils.neg(viewdelta))
+ self.point = self.point.add(viewdelta.negative())
if (self.step == 0): # choose center
if hasMod(arg,MODALT):
if not self.altdown:
@@ -1356,7 +1351,7 @@ class Ellipse(Creator):
p1 = self.node[0]
p3 = self.node[-1]
diagonal = p3.sub(p1)
- halfdiag = DraftVecUtils.scale(diagonal,0.5)
+ halfdiag = Vector(diagonal).multiply(0.5)
center = p1.add(halfdiag)
p2 = p1.add(DraftVecUtils.project(diagonal, plane.v))
p4 = p1.add(DraftVecUtils.project(diagonal, plane.u))
@@ -1452,6 +1447,7 @@ class Text(Creator):
self.ui.sourceCmd = self
self.ui.pointUi(name)
self.call = self.view.addEventCallback("SoEvent",self.action)
+ self.active = True
self.ui.xValue.setFocus()
self.ui.xValue.selectAll()
msg(translate("draft", "Pick location point:\n"))
@@ -1471,7 +1467,7 @@ class Text(Creator):
for l in self.text:
if len(tx) > 1:
tx += ','
- tx += '"'+str(l)+'"'
+ tx += '"'+str(unicode(l).encode("utf8"))+'"'
tx += ']'
self.commit(translate("draft","Create Text"),
['import Draft',
@@ -1485,10 +1481,13 @@ class Text(Creator):
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
- self.point,ctrlPoint,info = getPoint(self,arg)
+ if self.active:
+ self.point,ctrlPoint,info = getPoint(self,arg)
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
if self.point:
+ self.active = False
+ FreeCADGui.Snapper.off()
self.node.append(self.point)
self.ui.textUi()
self.ui.textValue.setFocus()
@@ -1660,7 +1659,7 @@ class Dimension(Creator):
rad = self.edges[0].Curve.Radius
baseray = self.point.sub(cen)
v2 = DraftVecUtils.scaleTo(baseray,rad)
- v1 = DraftVecUtils.neg(v2)
+ v1 = v2.negative()
if shift:
self.node = [cen,cen.add(v2)]
self.arcmode = "radius"
@@ -1701,7 +1700,7 @@ class Dimension(Creator):
if (not self.node) and (not self.support):
self.support = getSupport(arg)
if hasMod(arg,MODALT) and (len(self.node)<3):
- print "snapped: ",self.info
+ #print "snapped: ",self.info
if self.info:
ob = self.doc.getObject(self.info['Object'])
if 'Edge' in self.info['Component']:
@@ -1736,7 +1735,7 @@ class Dimension(Creator):
self.node[3],
True,True)
if c:
- print "centers:",c
+ #print "centers:",c
self.center = c[0]
self.arctrack.setCenter(self.center)
self.arctrack.on()
@@ -1766,7 +1765,7 @@ class Dimension(Creator):
# for unlinked arc mode:
# if self.arcmode:
# v = self.node[1].sub(self.node[0])
- # v = DraftVecUtils.scale(v,0.5)
+ # v.multiply(0.5)
# cen = self.node[0].add(v)
# self.node = [self.node[0],self.node[1],cen]
self.createObject()
@@ -1805,6 +1804,7 @@ class ShapeString(Creator):
self.text = ''
self.ui.sourceCmd = self
self.ui.pointUi(name)
+ self.active = True
self.call = self.view.addEventCallback("SoEvent",self.action)
self.ui.xValue.setFocus()
self.ui.xValue.selectAll()
@@ -1813,7 +1813,7 @@ class ShapeString(Creator):
def createObject(self):
"creates object in the current doc"
-# print "debug: D_T ShapeString.createObject type(self.SString): " str(type(self.SString))
+ #print "debug: D_T ShapeString.createObject type(self.SString): " str(type(self.SString))
# temporary code
#import platform
#if not (platform.system() == 'Linux'):
@@ -1842,8 +1842,8 @@ class ShapeString(Creator):
'ss.Support='+sup])
except Exception as e:
msg("Draft_ShapeString: error delaying commit", "error")
- print type(e)
- print e.args
+ #print type(e)
+ #print e.args
self.finish()
def action(self,arg):
@@ -1852,11 +1852,14 @@ class ShapeString(Creator):
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
- self.point,ctrlPoint,info = getPoint(self,arg)
+ if self.active:
+ 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.active = False
+ FreeCADGui.Snapper.off()
self.ui.SSUi()
def numericInput(self,numx,numy,numz):
@@ -2148,7 +2151,7 @@ class Rotate(Modifier):
if self.center and DraftVecUtils.dist(self.point,self.center):
viewdelta = DraftVecUtils.project(self.point.sub(self.center), plane.axis)
if not DraftVecUtils.isNull(viewdelta):
- self.point = self.point.add(DraftVecUtils.neg(viewdelta))
+ self.point = self.point.add(viewdelta.negative())
if self.extendedCopy:
if not hasMod(arg,MODALT):
self.step = 3
@@ -2327,7 +2330,7 @@ class Offset(Modifier):
if dist:
self.ghost.on()
if self.mode == "Wire":
- d = DraftVecUtils.neg(dist[0])
+ d = dist[0].negative()
v1 = DraftGeomUtils.getTangent(self.shape.Edges[0],self.point)
v2 = DraftGeomUtils.getTangent(self.shape.Edges[dist[1]],self.point)
a = -DraftVecUtils.angle(v1,v2)
@@ -2335,7 +2338,7 @@ class Offset(Modifier):
occmode = self.ui.occOffset.isChecked()
self.ghost.update(DraftGeomUtils.offsetWire(self.shape,self.dvec,occ=occmode),forceclosed=occmode)
elif self.mode == "BSpline":
- d = DraftVecUtils.neg(dist[0])
+ d = dist[0].negative()
e = self.shape.Edges[0]
basetan = DraftGeomUtils.getTangent(e,self.point)
self.npts = []
@@ -2370,7 +2373,7 @@ class Offset(Modifier):
occmode = self.ui.occOffset.isChecked()
if hasMod(arg,MODALT) or self.ui.isCopy.isChecked(): copymode = True
if self.npts:
- print "offset:npts=",self.npts
+ #print "offset:npts=",self.npts
self.commit(translate("draft","Offset"),
['import Draft',
'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+DraftVecUtils.toString(self.ntps)+',copy='+str(copymode)+')'])
@@ -2661,7 +2664,7 @@ class Trimex(Modifier):
if real:
if self.force:
ray = self.newpoint.sub(v1)
- ray = DraftVecUtils.scale(ray,self.force/ray.Length)
+ ray.multiply(self.force/ray.Length)
self.newpoint = Vector.add(v1,ray)
newedges.append(Part.Line(self.newpoint,v2).toShape())
else:
@@ -2673,7 +2676,7 @@ class Trimex(Modifier):
self.ui.labelRadius.setText("Angle")
dist = math.degrees(-ang2)
# if ang1 > ang2: ang1,ang2 = ang2,ang1
- print "last calculated:",math.degrees(-ang1),math.degrees(-ang2)
+ #print "last calculated:",math.degrees(-ang1),math.degrees(-ang2)
ghost.setEndAngle(-ang2)
ghost.setStartAngle(-ang1)
ghost.setCenter(center)
@@ -2718,7 +2721,7 @@ class Trimex(Modifier):
"trims the actual object"
if self.extrudeMode:
delta = self.extrude(self.shift,real=True)
- print "delta",delta
+ #print "delta",delta
self.doc.openTransaction("Extrude")
obj = Draft.extrude(self.obj,delta)
self.doc.commitTransaction()
@@ -2764,8 +2767,8 @@ class Trimex(Modifier):
self.obj.Z1 = p[0].z
elif Draft.getType(self.obj) == "Circle":
angles = self.ghost[0].getAngles()
- print "original",self.obj.FirstAngle," ",self.obj.LastAngle
- print "new",angles
+ #print "original",self.obj.FirstAngle," ",self.obj.LastAngle
+ #print "new",angles
if angles[0] > angles[1]: angles = (angles[1],angles[0])
self.obj.FirstAngle = angles[0]
self.obj.LastAngle = angles[1]
@@ -2870,7 +2873,7 @@ class Scale(Modifier):
# calculate a correction factor depending on the scaling center
corr = Vector(self.node[0].x,self.node[0].y,self.node[0].z)
corr.scale(delta.x,delta.y,delta.z)
- corr = DraftVecUtils.neg(corr.sub(self.node[0]))
+ corr = (corr.sub(self.node[0])).negative()
self.ghost.move(corr)
self.ghost.on()
if self.extendedCopy:
@@ -2948,14 +2951,19 @@ class Drawing(Modifier):
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Drawing", "Drawing"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Drawing", "Puts the selected objects on a Drawing sheet.")}
- def IsActive(self):
- if Draft.getSelection():
- return True
- else:
- return False
-
def Activated(self):
Modifier.Activated(self,"Drawing")
+ if not Draft.getSelection():
+ self.ghost = None
+ self.ui.selectUi()
+ msg(translate("draft", "Select an object to project\n"))
+ self.call = self.view.addEventCallback("SoEvent",selectObject)
+ else:
+ self.proceed()
+
+ def proceed(self):
+ if self.call:
+ self.view.removeEventCallback("SoEvent",self.call)
sel = Draft.getSelection()
if not sel:
self.page = self.createDefaultPage()
@@ -3030,19 +3038,25 @@ class Edit(Modifier):
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edit"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Edit", "Edits the active object")}
- def IsActive(self):
- if Draft.getSelection():
- self.selection = Draft.getSelection()
- if "Proxy" in self.selection[0].PropertiesList:
- if hasattr(self.selection[0].Proxy,"Type"):
- return True
- return False
-
def Activated(self):
if self.running:
self.finish()
else:
Modifier.Activated(self,"Edit")
+ if Draft.getSelection():
+ self.selection = Draft.getSelection()
+ if "Proxy" in self.selection[0].PropertiesList:
+ if hasattr(self.selection[0].Proxy,"Type"):
+ self.proceed()
+ return
+ self.ghost = None
+ self.ui.selectUi()
+ msg(translate("draft", "Select a Draft object to edit\n"))
+ self.call = self.view.addEventCallback("SoEvent",selectObject)
+
+ def proceed(self):
+ if self.call:
+ self.view.removeEventCallback("SoEvent",self.call)
self.ui.editUi()
if self.doc:
self.obj = Draft.getSelection()
@@ -3075,9 +3089,11 @@ class Edit(Modifier):
self.editpoints.append(self.obj.Shape.Vertexes[2].Point)
v = self.obj.Shape.Vertexes
self.bx = v[1].Point.sub(v[0].Point)
- if self.obj.Length < 0: self.bx = DraftVecUtils.neg(self.bx)
+ if self.obj.Length < 0:
+ self.bx = self.bx.negative()
self.by = v[2].Point.sub(v[1].Point)
- if self.obj.Height < 0: self.by = DraftVecUtils.neg(self.by)
+ if self.obj.Height < 0:
+ self.by = self.by.negative()
elif Draft.getType(self.obj) == "Polygon":
self.editpoints.append(self.obj.Placement.Base)
self.editpoints.append(self.obj.Shape.Vertexes[0].Point)
@@ -3442,8 +3458,6 @@ class WireToBSpline(Modifier):
Draft.formatObject(n,self.selection[0])
else:
self.finish()
- def finish(self):
- Modifier.finish(self)
class SelectGroup():
@@ -3478,20 +3492,27 @@ class SelectGroup():
FreeCADGui.Selection.addSelection(child)
-class Shape2DView():
+class Shape2DView(Modifier):
"The Shape2DView FreeCAD command definition"
+
def GetResources(self):
return {'Pixmap' : 'Draft_2DShapeView',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Shape2DView", "Shape 2D view"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Shape2DView", "Creates Shape 2D views of selected objects")}
-
- def IsActive(self):
- if FreeCADGui.Selection.getSelection():
- return True
- else:
- return False
def Activated(self):
+ Modifier.Activated(self)
+ if not Draft.getSelection():
+ if self.ui:
+ self.ui.selectUi()
+ msg(translate("draft", "Select an object to project\n"))
+ self.call = self.view.addEventCallback("SoEvent",selectObject)
+ else:
+ self.proceed()
+
+ def proceed(self):
+ if self.call:
+ self.view.removeEventCallback("SoEvent",self.call)
faces = []
objs = []
sel = FreeCADGui.Selection.getSelectionEx()
@@ -3500,28 +3521,37 @@ class Shape2DView():
for e in s.SubElementNames:
if "Face" in e:
faces.append(int(e[4:])-1)
- print objs,faces
+ #print objs,faces
if len(objs) == 1:
if faces:
Draft.makeShape2DView(objs[0],facenumbers=faces)
return
for o in objs:
Draft.makeShape2DView(o)
+ self.finish()
-class Draft2Sketch():
+
+class Draft2Sketch(Modifier):
"The Draft2Sketch FreeCAD command definition"
+
def GetResources(self):
return {'Pixmap' : 'Draft_Draft2Sketch',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Draft2Sketch", "Draft to Sketch"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Shape2DView", "Convert bidirectionally between Draft and Sketch objects")}
- def IsActive(self):
- if Draft.getSelection():
- return True
- else:
- return False
-
def Activated(self):
+ Modifier.Activated(self)
+ if not Draft.getSelection():
+ if self.ui:
+ self.ui.selectUi()
+ msg(translate("draft", "Select an object to convert\n"))
+ self.call = self.view.addEventCallback("SoEvent",selectObject)
+ else:
+ self.proceed()
+
+ def proceed(self):
+ if self.call:
+ self.view.removeEventCallback("SoEvent",self.call)
sel = Draft.getSelection()
allSketches = True
allDraft = True
@@ -3554,26 +3584,37 @@ class Draft2Sketch():
if (len(obj.Shape.Wires) == 1) or (len(obj.Shape.Edges) == 1):
Draft.makeSketch(obj,autoconstraints=False)
FreeCAD.ActiveDocument.commitTransaction()
+ self.finish()
-
-class Array():
+
+class Array(Modifier):
"The Shape2DView FreeCAD command definition"
+
def GetResources(self):
return {'Pixmap' : 'Draft_Array',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Array", "Array"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_Array", "Creates a polar or rectangular array from a selected object")}
- def IsActive(self):
- if len(Draft.getSelection()) == 1:
- return True
- else:
- return False
-
def Activated(self):
- obj = Draft.getSelection()[0]
- FreeCAD.ActiveDocument.openTransaction("Array")
- Draft.makeArray(obj,Vector(1,0,0),Vector(0,1,0),2,2)
- FreeCAD.ActiveDocument.commitTransaction()
+ Modifier.Activated(self)
+ if not Draft.getSelection():
+ if self.ui:
+ self.ui.selectUi()
+ msg(translate("draft", "Select an object to array\n"))
+ self.call = self.view.addEventCallback("SoEvent",selectObject)
+ else:
+ self.proceed()
+
+ def proceed(self):
+ if self.call:
+ self.view.removeEventCallback("SoEvent",self.call)
+ if Draft.getSelection():
+ obj = Draft.getSelection()[0]
+ FreeCAD.ActiveDocument.openTransaction("Array")
+ Draft.makeArray(obj,Vector(1,0,0),Vector(0,1,0),2,2)
+ FreeCAD.ActiveDocument.commitTransaction()
+ self.finish()
+
class Point:
"this class will create a vertex after the user clicks a point on the screen"
@@ -3594,7 +3635,7 @@ class Point:
self.stack = []
rot = self.view.getCameraNode().getField("orientation").getValue()
upv = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue())
- plane.setup(DraftVecUtils.neg(self.view.getViewDirection()), Vector(0,0,0), upv)
+ plane.setup(self.view.getViewDirection().negative(), Vector(0,0,0), upv)
self.point = None
# adding 2 callback functions
self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.click)
@@ -3630,19 +3671,6 @@ class Point:
todo.delayCommit(commitlist)
FreeCADGui.Snapper.off()
-class ToggleSnap():
- "The ToggleSnap FreeCAD command definition"
-
- def GetResources(self):
- return {'Pixmap' : 'Snap_Lock',
- 'Accel' : "Shift+S",
- 'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggle snap"),
- 'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggles Draft snap on or off")}
-
- def Activated(self):
- if hasattr(FreeCADGui,"Snapper"):
- FreeCADGui.Snapper.toggle()
-
class ShowSnapBar():
"The ShowSnapBar FreeCAD command definition"
@@ -3655,7 +3683,7 @@ class ShowSnapBar():
FreeCADGui.Snapper.show()
-class Draft_Clone():
+class Draft_Clone(Modifier):
"The Draft Clone command definition"
def GetResources(self):
@@ -3665,17 +3693,24 @@ class Draft_Clone():
'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_Clone", "Clones the selected object(s)")}
def Activated(self):
+ Modifier.Activated(self)
+ if not Draft.getSelection():
+ if self.ui:
+ self.ui.selectUi()
+ msg(translate("draft", "Select an object to clone\n"))
+ self.call = self.view.addEventCallback("SoEvent",selectObject)
+ else:
+ self.proceed()
+
+ def proceed(self):
+ if self.call:
+ self.view.removeEventCallback("SoEvent",self.call)
if FreeCADGui.Selection.getSelection():
FreeCAD.ActiveDocument.openTransaction("Clone")
for obj in FreeCADGui.Selection.getSelection():
Draft.clone(obj)
FreeCAD.ActiveDocument.commitTransaction()
-
- def IsActive(self):
- if FreeCADGui.Selection.getSelection():
- return True
- else:
- return False
+ self.finish()
class ToggleGrid():
@@ -3723,12 +3758,12 @@ class Heal():
class Draft_Snap_Lock():
def GetResources(self):
return {'Pixmap' : 'Snap_Lock',
+ 'Accel' : "Shift+S",
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_Snap_Lock", "Toggle On/Off"),
'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_Snap_Lock", "Activates/deactivates all snap tools at once")}
def Activated(self):
if hasattr(FreeCADGui,"Snapper"):
if hasattr(FreeCADGui.Snapper,"masterbutton"):
- print FreeCADGui.Snapper.masterbutton
FreeCADGui.Snapper.masterbutton.toggle()
class Draft_Snap_Midpoint():
@@ -3911,7 +3946,6 @@ FreeCADGui.addCommand('Draft_ToggleDisplayMode',ToggleDisplayMode())
FreeCADGui.addCommand('Draft_AddToGroup',AddToGroup())
FreeCADGui.addCommand('Draft_SelectGroup',SelectGroup())
FreeCADGui.addCommand('Draft_Shape2DView',Shape2DView())
-FreeCADGui.addCommand('Draft_ToggleSnap',ToggleSnap())
FreeCADGui.addCommand('Draft_ShowSnapBar',ShowSnapBar())
FreeCADGui.addCommand('Draft_ToggleGrid',ToggleGrid())
diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py
index 960f281d2..7bbb7882a 100644
--- a/src/Mod/Draft/DraftTrackers.py
+++ b/src/Mod/Draft/DraftTrackers.py
@@ -272,8 +272,8 @@ class dimTracker(Tracker):
p2 = p1
p3 = p4
else:
- p2 = p1.add(DraftVecUtils.neg(proj))
- p3 = p4.add(DraftVecUtils.neg(proj))
+ p2 = p1.add(proj.negative())
+ p3 = p4.add(proj.negative())
points = [DraftVecUtils.tup(p1),DraftVecUtils.tup(p2),DraftVecUtils.tup(p3),DraftVecUtils.tup(p4)]
self.coords.point.setValues(0,4,points)
@@ -743,7 +743,7 @@ class boxTracker(Tracker):
self.cube.width.setValue(lvec.Length)
p = WorkingPlane.getPlacementFromPoints([bp,bp.add(lvec),bp.add(right)])
self.trans.rotation.setValue(p.Rotation.Q)
- bp = bp.add(DraftVecUtils.scale(lvec,0.5))
+ bp = bp.add(lvec.multiply(0.5))
bp = bp.add(DraftVecUtils.scaleTo(normal,self.cube.depth.getValue()/2))
self.pos(bp)
diff --git a/src/Mod/Draft/Draft_rc.py b/src/Mod/Draft/Draft_rc.py
index 7375cb072..53977b3cf 100644
--- a/src/Mod/Draft/Draft_rc.py
+++ b/src/Mod/Draft/Draft_rc.py
@@ -2,8 +2,8 @@
# Resource object code
#
-# Created: Sat Jul 6 16:32:11 2013
-# by: The Resource Compiler for PyQt (Qt v4.8.4)
+# Created: Sat Aug 24 18:47:43 2013
+# by: The Resource Compiler for PyQt (Qt v4.8.5)
#
# WARNING! All changes made in this file will be lost!
@@ -41485,434 +41485,515 @@ qt_resource_data = "\
\x00\x6c\x00\x6b\x00\x79\x08\x00\x00\x00\x00\x06\x00\x00\x00\x11\
\x64\x72\x61\x66\x74\x20\x43\x6f\x6d\x6d\x61\x6e\x64\x20\x42\x61\
\x72\x07\x00\x00\x00\x05\x64\x72\x61\x66\x74\x01\
-\x00\x00\x09\xb5\
+\x00\x00\x0b\x42\
\x00\
-\x00\x4b\x27\x78\x9c\xed\x5c\x5b\x73\xdb\xb6\x12\x7e\xf7\xaf\xc0\
-\xe8\xe1\x34\xed\xb8\x96\xe5\x6b\x92\x23\xab\x93\xd8\x71\x92\x4e\
-\xd2\xba\x95\x9b\x9c\x37\x0f\x44\x42\x22\x6a\x92\x50\x01\xd0\x92\
-\xfa\xeb\xcf\x2e\x00\x8a\x14\x49\xdd\x2d\xd9\xc9\x68\xc6\x33\x16\
-\x01\x10\xbb\x58\x7e\xbb\xd8\x5d\x2c\xd9\xfc\x65\x18\x85\xe4\x81\
-\x49\xc5\x45\x7c\x51\x6b\x1c\x1c\xd6\x08\x8b\x3d\xe1\xf3\xb8\x77\
-\x51\xfb\xeb\xf6\xfa\xe7\x97\xb5\x5f\x5a\x7b\xcd\x84\x67\x83\x4e\
-\x60\x50\x6b\x8f\x34\xbd\x90\x2a\xd5\x7a\x9f\xf0\xd7\xaf\xaf\x38\
-\x0d\x45\x0f\xfe\x87\xbd\x36\xd3\x1a\x6e\x56\x57\x92\x76\x75\xb3\
-\x6e\x07\xc1\xe8\x01\xf7\x7b\x4c\x13\x73\x7d\x51\xfb\xe3\xab\xb9\
-\xac\x91\x98\x46\xec\xa2\x36\x73\x12\x24\x46\x9a\x7d\x29\xfa\x4c\
-\xea\x91\xbb\xa3\xc7\x44\xc4\xb4\x1c\x99\x4e\xd2\x94\xcc\xd3\xe6\
-\x17\x69\x0e\x5b\x87\xcd\xfa\xd0\x5d\x8c\xf0\x62\xe4\x2e\x80\x05\
-\x1d\xb4\x4e\xcf\x4f\x9b\x75\xfb\xd3\x36\x07\x8c\xf7\x02\xdd\x3a\
-\x3b\x7a\xd5\xac\xbb\xdf\x66\xce\x7a\x3a\x69\xb3\x9e\x12\xaf\xe2\
-\x64\xc0\x63\x5f\x0c\x6e\xb9\x0e\x99\x63\x46\x69\x09\xcc\xb7\x3e\
-\x46\x7d\x21\x75\xfd\xdd\x10\xff\x35\xeb\xae\xb5\x3c\x5f\x48\x47\
-\x22\xc9\x24\xf3\xe5\xad\x18\x7e\x32\x4d\x6e\xba\x02\x3d\xd5\xa7\
-\x1e\x4c\x54\x73\xdc\xc7\x49\xd4\x61\xb2\x75\xd6\xac\xbb\x5f\x96\
-\xf7\x3c\x85\xd2\x14\x11\x95\x3d\x1e\x17\x66\x78\x35\x73\x06\xae\
-\x59\x94\x89\x31\xff\x24\xdf\x4b\x91\xf4\x81\xe7\xf1\xb3\x74\xd7\
-\x8d\x23\x47\xa0\x44\x5e\x67\xb2\xca\x89\xeb\xea\x7f\xd7\xa4\x2b\
-\x64\x44\x35\x11\x7d\x0d\x48\x53\x79\x99\x95\x59\x9a\x2f\xb9\xb9\
-\xc2\x9b\x2a\xbf\x2a\x6a\xb3\xa5\x38\x55\x90\xd5\x53\x65\xe2\xac\
-\x58\xc7\x87\xf2\x3a\x16\x58\xc9\x8c\xb5\x54\xb1\x30\x7f\x3d\xd9\
-\x84\x87\x0b\x4e\x38\xb1\xaa\x32\x52\x3e\xd1\x0e\x0b\x53\x98\x68\
-\x36\xd4\xa6\xa1\x71\x77\x9c\xa7\x59\x46\x0b\x0c\x9c\x18\x50\x50\
-\x30\xa2\xf4\x28\x64\x05\xac\x4c\xe5\x91\x18\xdd\x07\xae\xf2\x4b\
-\x99\xe4\x7b\xce\x32\x8c\xad\xba\x91\xac\x7b\x29\xa2\x8e\xc8\x01\
-\xbf\x87\x1d\x7d\xe8\xf0\xb0\xa3\x03\x1d\x33\x97\x25\x44\x78\xcb\
-\xfb\xd5\x2b\xbb\x0d\xb8\x22\xf0\xa7\x03\x46\xc0\xcc\x05\xc2\x27\
-\x5e\x20\x84\x62\x3e\xaa\x08\xe1\x66\xe1\x30\x90\xc0\x85\x96\x34\
-\x56\x21\x35\x97\xa8\x43\xa2\xf3\x37\xd8\x2d\xe2\x89\x10\x47\xc6\
-\x5a\x90\x6b\xc9\xd8\xe5\x9b\xab\x03\xb2\xf7\xb1\xeb\xda\x23\xda\
-\xef\xe3\x0d\x40\xc3\x4d\xbc\x4f\x00\x70\x24\x4a\x94\x76\x2d\x84\
-\x16\xc6\x76\x79\xc8\xa0\x29\xd6\x94\xc7\x78\x4d\x33\xd2\x22\x26\
-\x9a\x76\xa0\x5b\x07\xa0\xbe\x03\x1e\x86\x38\x10\x76\x0c\xc7\x87\
-\xb2\x8c\x84\x3c\x66\xc6\xf2\xaa\x83\xbd\x85\x1f\x58\x49\x72\x5e\
-\x22\x25\x8b\xf5\xc7\xd8\x67\xc3\x82\xf8\xa6\xe3\x75\xd1\xc9\xf1\
-\xf9\xbd\x8b\x71\x63\x01\x5c\xf9\x8a\xe9\x8b\xda\x61\x81\x88\xe7\
-\x18\xf7\x87\x5d\x07\x3d\x6f\xd5\xa5\x20\xb5\x1b\xaa\x83\xf9\xc4\
-\x3e\x0b\xbf\x9e\x6e\xa9\x0b\x53\x2b\x00\x79\x11\xdd\x1a\x43\xf0\
-\x37\x11\x33\xf2\xa2\x4b\x95\x66\x4a\xff\x58\xf5\xb4\xa6\x51\xad\
-\x17\xc9\xae\xc5\xc7\x5f\x80\x44\x9f\x75\x69\x12\xa6\x98\xa6\xb1\
-\x9f\x21\xe9\xe9\x18\xfb\x5d\x72\x30\x97\x34\x7c\x5e\x5c\x5d\x8e\
-\x55\x16\x6c\x45\x5e\xe5\x9e\x90\x25\xc9\xa8\x66\xa4\x4f\x25\x45\
-\x97\x8d\x7b\xce\x44\x15\xf7\xf7\xed\xb3\xd4\xbe\x67\xda\x0b\xd8\
-\x5a\x8c\xcc\xdd\x4f\x9a\x75\xbb\xbd\x67\xde\x40\xbe\x7b\x61\x4f\
-\xc0\x2d\x2a\x10\x92\xff\x8b\x36\x38\x2c\x7b\x08\xcb\x6c\xbf\x21\
-\x5e\xdc\x9d\xaf\xb8\xf3\x7e\xa6\x43\xd2\xee\x23\xb6\x48\x9b\xf5\
-\x22\xb0\xc6\x4f\xb0\xff\xb6\x61\x57\xaa\xda\x7e\x15\xb4\xc3\xee\
-\x7b\x77\x34\x73\x71\x11\x1d\xf2\x28\x89\xda\xfc\x5f\x56\x5c\x23\
-\x34\x15\x60\x63\xc3\x85\xb3\xc3\x89\xc0\x61\xdc\xeb\x82\x86\xc6\
-\xd9\xf9\xf9\xf9\x51\xe3\x74\x22\x8a\xc8\x16\x59\x9c\x76\xb1\x1d\
-\x62\xa6\x9b\xf0\x35\x60\x31\x61\xc3\xd4\x19\x50\xe6\x89\x28\x54\
-\x7b\x70\x04\xf6\xd1\x7b\x18\x11\x2a\x99\xdd\xa7\xd1\xb7\x06\x9b\
-\xc0\x63\xd2\x17\xe1\xc8\x8c\x3c\x20\xc6\xd1\x78\xa0\x61\xc2\xc6\
-\xee\x86\x95\x0b\x09\x59\xdc\xd3\x01\x11\x5d\xc2\xa8\x67\xfe\x63\
-\x6f\x7a\x2b\x51\xf6\xb1\xc3\x14\xe0\x53\x1c\x1a\x5a\xb1\x19\x31\
-\x08\x04\xf8\x01\x96\x15\x33\xa7\x51\x35\x9f\x50\x05\x0e\x03\xf0\
-\x4d\x51\x34\xe9\xed\x07\xab\x7b\x01\x86\xe9\xea\xed\xff\x74\x2b\
-\xdb\x3f\x08\xca\x09\x3c\xd5\x80\xe7\xe9\x06\x3c\xb1\x81\x9a\xf0\
-\xee\x97\x37\x51\x2b\x1a\xa8\xcb\x92\xe7\xfa\x04\x06\xea\x1a\xc8\
-\x5e\x1a\x5f\x5a\x96\x8c\x14\xb2\xe4\xb9\xbe\x99\x66\x0a\x7c\xed\
-\x25\xcd\xd4\xf1\xe1\x6c\x3b\x75\xb8\x3d\x03\x75\x1b\xb0\xaa\x20\
-\xa2\x5b\x08\x5b\xc0\x93\x9e\x12\x27\xac\x6e\x1f\x96\x73\xe4\x1d\
-\x7b\x16\x28\x3b\x3d\xae\xd2\xe3\xf3\xc5\xf5\x38\x0b\x91\x03\xe6\
-\xdd\x57\x86\xc8\xd8\x31\x7f\x93\x9e\x09\x2e\x8e\x5b\x92\x8d\x93\
-\x93\xd8\x4c\x88\x51\x2c\xda\x04\x55\x8f\xcc\x3f\x32\x10\xf1\x0f\
-\x9a\x74\x98\x8b\x98\x99\xbf\x3a\x9e\xe6\xa6\x21\x2c\x45\x0c\x03\
-\x7c\x0e\xfb\x81\xaa\xc8\x60\x2d\x09\xa5\xc5\xe1\x8b\xb4\x77\xb8\
-\xad\xc6\xed\xd1\x46\x70\x3b\x27\x67\xb5\x20\x6e\xc7\xa8\xed\x53\
-\xb8\x9d\x60\x4e\x8f\xa5\xd1\x91\x4d\xa3\xe4\xb0\x0b\x7e\x9d\xd8\
-\x20\x7e\xad\x64\xb7\x06\x59\x4b\x6e\x07\xda\x6a\xd0\x9e\x6c\x04\
-\xb4\x73\xc2\xbd\x59\xa0\x35\x93\x3b\xdc\x76\x4d\xaa\x70\x40\x63\
-\x6d\x3c\xfe\x58\xc4\x3f\xe3\x0c\x3e\xe9\x84\xc2\xbb\x57\xe4\x45\
-\x87\xf5\x78\x6c\x72\x84\x03\x0e\x31\x04\x25\x3f\xfd\x88\x41\xc9\
-\xf6\xb0\xfc\x93\xe5\x64\x5b\x58\x56\x9a\xca\x94\xe2\x0e\xcf\x55\
-\x78\x7e\xb9\x11\x3c\x9f\x3e\xae\x11\x4e\x0d\x6f\x57\x8a\xc8\x20\
-\x5b\xc1\x3c\x68\x17\x99\xcc\xac\xf1\xdf\x02\x9c\x53\xdf\xfa\xa9\
-\xe6\x21\x90\xb7\xe6\xc9\x83\xe7\x91\x48\x83\x79\xbc\xd3\xe7\x10\
-\x1b\xd2\x11\x31\xf9\x53\xb9\x4f\x3a\x20\xae\x88\xde\xbb\x6e\x8c\
-\xae\x95\x82\xc0\x5a\xf1\x70\x44\x98\xcf\x4d\xf2\x7c\x13\xfa\x60\
-\x0e\xe3\xd2\x25\x18\x9e\xb7\xa8\x19\x3d\x24\xfe\xc9\xd0\xde\xe9\
-\x45\xb5\x5e\x9c\x6e\x44\x2f\x5e\xad\xae\x17\x78\x42\x94\xea\x43\
-\x57\x32\xe6\x51\xdf\x42\x1f\x9e\x38\xda\x70\x84\x3f\x26\xe2\x79\
-\xec\x71\x9f\xc1\xcf\x54\x69\x0c\xb8\x06\x5c\x62\x56\xe9\x2d\x1b\
-\x50\xc9\xf6\xad\x86\x79\x14\x0f\x87\xee\xf1\x3c\x69\x10\x40\x7c\
-\x75\x70\xb0\x46\xd6\x67\x3a\xd2\x7f\x05\x96\x48\x5a\x15\xb0\x15\
-\x78\xa3\x28\x32\x82\x3b\x7c\x57\xe1\xfb\x6c\x13\xf8\x5e\x0b\xdd\
-\x25\xab\x4f\x01\xdc\x29\x88\x73\xa7\x9b\x5d\x70\xc5\x33\xab\x6f\
-\x93\xac\x36\x8d\x79\xec\x9b\x34\xa8\x19\xb0\x09\x24\xdb\x82\x11\
-\x72\x7c\x35\x66\x0b\x88\xa6\x14\x49\xc4\xd4\x94\x13\x8b\x8d\xe4\
-\x45\x80\xda\x0e\xdb\xd5\xd8\x6e\x6c\xc6\x49\x6f\xac\x91\x12\xa9\
-\xc2\x37\xba\x23\x63\xf8\x16\x63\x4b\x98\x1c\x1b\xec\x59\x21\x70\
-\x11\x62\xe9\x00\xde\xe1\x0e\xd9\xc9\x03\x67\x03\xf0\x66\xb0\x14\
-\x8a\x8b\x78\x13\x70\xbf\xb1\x2c\x94\x79\xa4\xa1\x00\x3d\x7c\x6c\
-\x46\x96\xc3\xbf\x93\xcf\x4e\x05\xa6\xa8\x40\x63\x23\x2a\xf0\xf2\
-\x71\x35\x20\x0b\x3a\x6d\x52\x10\xb1\x8f\x8c\x19\x17\x5f\xd3\xd8\
-\xa7\xd2\x77\xbe\x3c\x8e\x20\x98\x08\x87\xbb\x62\x70\xdd\xc1\xfb\
-\x71\x27\x5f\xd8\x68\x4f\xd4\x02\xfa\xc0\xf0\x18\x0d\x5b\xb1\xe0\
-\xc6\x17\x5e\xb2\xd4\x11\xe8\x12\xca\x81\xd5\x0f\x63\x16\xbb\x20\
-\x7a\xcb\x87\x49\xa0\xe3\x62\xb6\xa5\x07\x6d\xed\xe3\x11\xc4\x4e\
-\x0f\xa6\xe8\xc1\x66\x92\x8c\x8d\xc3\xc7\x55\x84\x80\x9a\x72\x87\
-\xb1\xf5\x77\x35\x5a\x69\x38\xab\x40\x51\x42\x66\x9d\xf8\x0d\x26\
-\x67\x0c\x17\xa4\x23\x12\x44\x35\x67\xc6\xbd\x59\x93\xe6\x12\x60\
-\xb6\xc6\xe0\x6a\xd8\xfd\x40\x5d\xed\xc7\x0e\xd2\x95\x90\x5e\xe2\
-\xdc\x76\x19\x48\x37\x1e\x17\xd2\x03\xac\x3b\x18\x17\x34\x58\xdb\
-\x0c\x81\x26\x1e\x1e\x62\xd9\x18\xe6\x6a\x5c\x21\x44\x0a\x7a\xf0\
-\x26\x7c\x26\xad\x2b\xef\x85\xa6\xa6\xd2\xa0\xcf\xe6\x2a\x8d\xef\
-\x23\x24\xba\x19\x64\x6a\xdd\xd4\xba\x8a\xf0\xa7\x61\x21\xc7\xb6\
-\x21\xbd\x26\xb9\x25\x74\xc0\x8a\xe0\xc6\x91\xff\x6a\xe9\x7e\x8f\
-\x6a\x30\xd9\x39\x31\x57\x6e\xdc\x4a\xc5\xed\x77\x4b\x96\xb7\xb7\
-\xbf\xbc\x7f\xbc\xf2\x76\x47\x29\x77\x0a\xf5\xad\x17\xba\xa7\x2b\
-\x9a\x88\xa9\xe6\xad\x69\xc6\xaa\xaa\xe1\xf4\x6c\x4a\xde\xe7\x64\
-\xae\x9f\xbc\xe4\xdd\x9c\x44\xca\xd2\xde\xd0\x36\xcd\x13\x59\x9d\
-\x32\xf7\x30\x1a\xbc\x61\x53\x15\x5e\x58\x04\x03\x91\xb6\xfe\xd0\
-\xaf\x5f\x7f\x18\xcf\xd8\xac\x9b\xc6\xa5\x8d\x0e\xba\xc1\x1f\xc0\
-\x6b\x99\x6e\x74\xa6\xd6\xc7\x9c\xcc\x2e\x8f\x39\x5a\xab\x3e\x06\
-\x86\x19\x19\x2d\x21\xeb\x55\x5f\x2f\x58\xe7\x0c\x7a\xe1\x17\x0c\
-\xd0\x6c\x4d\x7f\xa3\xe0\xdb\x2f\xe2\x57\x0f\xbd\x5d\x11\xff\x02\
-\x65\xce\xbb\x22\xfe\xa5\xb8\x7a\x6a\xef\xfd\xd5\xe2\xce\x7b\x55\
-\x5d\xf8\x9c\x14\xe4\xbc\xd4\x75\xfb\x99\xbc\x91\x05\xca\x7d\x67\
-\xd3\x8a\x77\x46\xc9\xef\xd6\x7f\x33\xcb\x2c\x0d\x73\x42\xc6\x9f\
-\xc3\x62\x46\x3c\xf6\x92\xc0\xa0\x0d\x45\xb2\x6a\x6c\xea\x5e\x2f\
-\xf8\x3e\x8c\xe4\x84\x1c\xbf\x4f\x63\x79\xeb\x2a\x52\x61\x0f\x7c\
-\x81\x9b\x60\x5f\xe2\x51\xe7\x7f\x68\xd4\xff\x6f\x7a\x9e\xff\x84\
-\x26\xf4\x4f\x3a\xb0\x6c\x5d\xbe\xf9\xbc\x16\x1b\x4f\x6d\x9a\x26\
-\x92\x5a\x8f\x97\x58\x98\xed\x93\x2e\xf3\x1a\x05\x6a\x36\x9e\x36\
-\xa8\x7d\x2c\xd9\x60\xe6\x80\x70\x10\xa0\x86\x9b\xad\x41\xc8\x7b\
-\x82\xaf\x57\x51\xf4\x85\x48\x27\xa4\xde\xfd\xbe\x71\x9a\x3a\x4c\
-\x6b\xf0\x99\x25\xa3\x3e\xed\xf0\x90\x03\x71\xda\xa3\x98\x46\x76\
-\xb7\x77\x60\x28\xd6\x44\xc4\xfe\x46\xd2\x6b\x63\xfc\xe6\xb8\x75\
-\xfb\x9a\xa9\xfb\x00\xea\x6b\x98\x22\x9b\x70\x29\x50\xee\x80\x58\
-\x5b\x5a\x26\x60\x11\xcc\xcf\x4d\x1a\xa1\xf6\x43\xef\x13\x26\x4b\
-\xde\xda\x85\x3c\x4f\x0b\xf4\x7c\xd3\x15\xe3\x60\x61\xb1\x74\xc5\
-\xef\x97\x6f\x1e\x3f\x5d\x91\xe9\xe8\xf7\x92\xae\x98\x28\x8a\xff\
-\xe6\xd3\x15\x4b\x98\xdb\x93\xd5\xcd\xed\x8c\x52\x52\x0a\xc6\x53\
-\x91\x17\xc7\x57\xb6\xfc\xa2\xaa\x6a\x74\x23\xc5\x43\x2e\xad\x82\
-\xa0\x37\x2c\x6c\x25\x0b\x2b\x3c\xea\x88\xed\x6c\x99\x79\x16\xf9\
-\x9c\x13\x9e\x4b\x71\x2f\xcd\x38\x4d\xb3\x5d\x55\xa9\xa6\x2c\xcb\
-\xf4\xc5\xcd\x31\x91\x63\x2a\xdb\xad\x25\x32\x4b\x93\x49\x25\x97\
-\x4f\x3a\x2a\xe5\x93\xd2\x54\xd2\x49\x29\x95\x34\x91\x45\x2a\xb2\
-\x32\x91\x3b\xca\x84\x94\x93\x64\x4e\x8c\xce\x38\xa5\x51\xb5\x33\
-\x36\x17\xb5\xb3\x1a\xb1\x66\xe2\xa2\xd6\x68\xd4\xea\x38\xb2\xcf\
-\x87\x11\xed\x77\x93\xd8\x94\x4e\xb4\xfe\xb9\x31\xd7\xd7\x52\x44\
-\x9f\x79\xc4\xda\x22\x91\x1e\x6c\xe0\x85\x51\xf8\x81\x9f\x44\x69\
-\x11\x59\x8a\xca\x70\x92\x6f\xb1\x5c\xe6\x3e\x02\x94\x7b\xdd\x2d\
-\xfb\xee\x0f\x3e\x8f\xa1\x66\xe0\xf2\xb4\xdc\x37\x7f\xe0\x69\xb8\
-\x86\x3d\x2b\x2a\xea\xc3\x92\x61\x86\x3a\x4e\x60\x3f\x02\x74\x10\
-\xa0\xe0\x4c\x87\x11\x40\x91\xee\x6c\x46\x0a\xef\xde\x55\x32\x53\
-\xe6\x78\x1a\x57\x38\x9b\xe5\x5c\xad\xcf\x96\x7b\x67\xb9\x5a\x3e\
-\xe3\xce\xad\xb0\x92\xda\xf8\x6a\x5e\xb2\xde\xed\x30\xe3\x22\xf7\
-\x29\xcc\x8c\x7b\xd7\x67\x66\xb2\xc1\x7c\x9a\x4a\x32\x65\x74\x40\
-\x19\x6d\xf1\x44\x1c\xdb\x22\x23\xbc\x6e\xd6\x13\xde\xda\xfb\x3f\
-\x76\xfc\xff\x17\
-\x00\x00\x10\xc0\
+\x00\x6a\x6f\x78\x9c\xed\x5d\x5b\x93\xda\xb8\x12\x7e\x9f\x5f\xa1\
+\xe2\x21\xb5\xa7\x2a\x67\xb8\xcc\x85\x99\x84\x61\x2b\xf7\x49\x55\
+\x52\x9b\x0d\xb3\xd9\xc7\x2d\x61\x0b\xd0\x59\xdb\x22\x92\x3c\xc0\
+\xd6\xf9\xf1\xa7\x75\x31\xbe\x60\x0c\xc6\x80\x93\x39\xa4\x2a\x35\
+\xb6\x24\xb7\xda\xad\xee\x4f\xdd\x2d\xc9\xf4\x7e\x9d\xfb\x1e\x7a\
+\x24\x5c\x50\x16\xdc\x35\xda\xe7\xad\x06\x22\x81\xc3\x5c\x1a\x8c\
+\xef\x1a\x7f\x3c\xbc\xff\xf7\x4d\xe3\xd7\xfe\x59\x2f\xa4\x71\xa3\
+\x4b\x68\xd4\x3f\x43\x3d\xc7\xc3\x42\xf4\x3f\x84\xf4\xc5\x8b\xb7\
+\x14\x7b\x6c\x0c\x7f\xbd\xf1\x80\x48\x09\x0f\x8b\xb7\x1c\x8f\x64\
+\xaf\x69\x1a\x41\xeb\x19\x75\xc7\x44\x22\x7d\x7f\xd7\xf8\xfd\x4f\
+\x7d\xdb\x40\x01\xf6\xc9\x5d\xa3\x90\x88\xea\x0c\xf5\xa6\x9c\x4d\
+\x09\x97\x0b\xfb\xc4\x98\x30\x9f\x48\xbe\xd0\x95\xa8\xc7\x89\x23\
+\xf5\x15\xea\xcd\xfb\xad\x5e\x73\x6e\x6f\x16\xea\x66\x61\x6f\x80\
+\x05\x39\xe9\x77\xdb\x37\xbd\xa6\xb9\x34\xc5\x13\x42\xc7\x13\xd9\
+\xbf\x69\x41\xb9\xbd\xd6\x34\x9b\x11\xd1\x5e\x33\xea\x3c\x8f\x93\
+\x19\x0d\x5c\x36\x7b\xa0\xd2\x23\x96\x19\x21\x39\x30\xdf\xff\x46\
+\x45\x88\x3d\x24\xec\xbb\xf4\x9a\xb6\x7c\x95\xa2\x87\x17\x2c\x8c\
+\x65\xf3\xed\x35\x9b\x7f\xd2\x45\x96\x60\xa6\x47\x31\xc5\x0e\x10\
+\x6a\x58\xfe\x83\xd0\x1f\x12\xde\xbf\xee\x35\xed\x95\xe1\x3e\xd9\
+\xc3\x0a\x09\x1f\xf3\x31\x0d\x32\x14\x6e\x0b\x29\x50\x49\xfc\x58\
+\x90\xc9\xb1\xfc\xc0\x59\x38\x05\x9e\xa3\xd1\x1c\x47\xf7\xa6\xf9\
+\x4a\xe7\x32\x96\xd5\xaa\xb8\x06\x39\xe2\x5a\xe5\xa6\x50\x68\xb6\
+\x1b\x50\x58\x49\x1d\xec\x99\xd2\xbf\x3a\x71\x8f\xf1\xab\xe4\x10\
+\xba\x5f\x21\x34\x61\x9c\xfe\xc3\x02\x99\x43\x2a\x4b\x6c\x55\x38\
+\x9f\xf0\x90\x78\x11\x25\x4f\xdd\xa4\x1e\xcf\x91\x0e\x99\xcb\x54\
+\x83\xa5\x84\xde\x92\x11\x0e\x3d\x89\x3c\x1a\x10\xe4\x30\x8f\xf1\
+\x8c\x90\xf2\x25\x65\x0a\x0d\x5b\x09\xbe\x9b\x69\xc6\x57\xde\x43\
+\x69\x19\xe1\x2b\x22\x18\xe8\xe2\xc2\x37\x80\xb6\x04\x9a\x4a\x40\
+\x8b\xcc\x8b\x10\xd0\xaf\xfe\xef\xf2\xc5\x8b\xfb\x25\xbd\x5e\x53\
+\x17\x6e\x7a\x81\x55\x23\xa0\xff\x90\x7b\x1a\xc0\x20\x09\xe9\x82\
+\x8d\xdd\x35\x5a\x59\xa9\x41\x8b\x54\x49\x84\x00\x97\xad\x14\x00\
+\x2c\x6b\xad\xf1\x77\x5a\x29\x1c\x88\xd9\xca\x12\x5c\x23\x69\x23\
+\xb8\x12\x92\x4e\x6b\x8c\xc6\xc2\x2f\x9c\x8c\xde\xa8\x11\x7e\x1d\
+\x4a\x09\x62\x8c\x2c\x4b\xd5\x4d\xa1\x4e\x8f\xfe\xd0\xd4\x15\x2a\
+\x13\x63\xde\x03\x9d\xe6\xeb\x93\x9c\x10\xe4\x5a\x9d\xd2\x04\xd1\
+\x08\xfe\x07\x64\x86\xd8\xf0\x3f\x80\x7d\x59\x1b\x2c\x31\x3a\x9a\
+\x5c\xa6\x57\x5d\x96\x11\x39\x27\xae\x42\x68\xf5\x27\x5d\x31\xe6\
+\x84\x04\xaa\xca\x5c\xa4\x2b\x87\x5e\x48\x54\x9d\xfe\x9b\x1e\xa3\
+\x95\x4e\xb6\xe3\x57\xc9\xf4\x5d\xa0\xe6\x93\xb5\xea\xe4\x58\x59\
+\x58\xc3\x73\x76\x15\x8d\xea\xea\x0b\x96\x93\xcd\x3d\x7d\x66\x6e\
+\x33\x9a\x46\xf7\x65\xe7\xbd\xa6\x81\xbb\x25\x16\xa6\xaa\x2b\x23\
+\x63\xb7\x1a\x32\x5e\xec\x03\x19\xb5\x69\xd7\x86\x8c\x1b\xd0\xfd\
+\x84\x8d\x7b\xc1\xc6\xc1\x94\x06\x49\x8f\x23\xc2\x45\x01\xe5\xc3\
+\xd8\xf3\xc8\x95\xce\xd6\x98\xa8\xb4\x49\xcb\x62\x7f\xb8\xf8\x88\
+\x01\xb2\x32\x3d\x5b\x9f\xab\x93\xf2\xbe\x4a\x51\x2d\x81\x5e\xcb\
+\x77\x3a\x21\x58\x3e\x82\x5d\x54\x43\xb0\xcb\x1d\x11\x6c\x10\xe0\
+\x29\x12\x0b\x7f\xc8\x3c\x51\xb3\x6f\xb7\xe1\x1d\x4e\x08\x76\x4c\
+\xef\x6e\x53\xb0\x50\xde\xbf\x13\x09\x4d\x3b\x39\x78\x49\xf6\xad\
+\x2c\x94\x80\x4e\x4e\x5e\x01\x44\x5e\x6e\x0f\x91\xb1\xba\x4f\x88\
+\xf3\x77\xde\x8c\xed\xa8\x8a\x4a\x53\xb6\xa6\x80\xe4\x84\x0a\x44\
+\x47\x08\x38\x44\x33\x1c\x48\x24\x19\x0a\x05\x41\xca\x08\xf4\x68\
+\x36\x13\xd3\x39\x67\xbe\xae\x50\x74\x87\x98\x23\x2c\x22\x43\xd9\
+\xdd\x22\x0a\xb0\x1d\x3f\x02\x0f\x21\xe7\x80\x9b\xd6\x10\x71\xe0\
+\x26\xdc\x0b\xec\x70\x26\x04\x12\x44\xa8\x0c\x5b\x05\xab\x2c\xa3\
+\xe5\xc0\x14\x0b\xc8\x9c\x96\x50\xbc\xff\x2f\x35\x6f\x97\x48\xf3\
+\x6c\xaf\xe7\x7f\xb5\xdb\xbb\xab\x3a\xe8\xb7\xa6\x43\xdc\xe7\x08\
+\x23\xcb\x02\x0d\x5c\xea\x60\x95\x34\x33\xca\x6e\x15\x6d\xc6\xf8\
+\xdf\xaa\x6c\xea\x61\x08\x8a\x12\xb3\x36\xc2\xd3\x29\xc1\x1c\x54\
+\x3e\x54\x44\x91\xcb\xf1\x4c\xfd\x55\x6c\xe8\x06\x15\x14\xb0\xc0\
+\x08\x26\x6c\x86\xfe\xb4\x3c\x7d\xd1\x3c\x49\x8e\xe1\x55\xb6\x77\
+\x74\x2a\xa9\x3b\x74\xaf\x7b\x7d\x88\x3a\x3d\x29\x7d\x9e\xd2\xdf\
+\x1c\x44\xe7\xaf\x77\x57\xf9\x8f\x23\x0b\xed\x22\x56\x7d\x1b\x86\
+\x81\x01\x78\x9e\xd5\x66\x05\xe1\x23\xb8\x25\x6e\x02\xcc\xcf\xd1\
+\x6f\x60\x11\x7c\x46\x05\x79\xae\x6c\x63\x91\x7d\x62\x46\x81\x4b\
+\x0e\x4c\x1c\x42\xe3\xdf\xab\xbe\x22\x56\x87\x8b\xea\x33\x4c\x09\
+\x75\x57\xa2\xf0\x99\x4b\x4e\x6a\xbe\x06\xdb\xdb\xd5\xc2\xbc\x4d\
+\x20\xbe\x31\x53\x05\x3d\x02\x30\x4b\x82\xc4\x84\x90\xed\x75\x62\
+\xef\xb1\xde\x86\x17\x39\x05\x7b\x7b\x09\xf6\x00\x0a\xc8\x9b\x09\
+\x63\x82\xf0\x15\x90\x04\x53\x25\x8e\xa9\xdb\x10\xec\xf9\x34\xa0\
+\x7e\xe8\x0f\x80\xf7\x6d\xe5\x73\xd1\x2a\x16\x50\x25\xf9\x94\x03\
+\xf2\x87\x44\x34\xba\xd4\x7e\xeb\xa4\xcf\x26\x24\x40\x0e\x27\xc6\
+\x8b\xc1\x3a\xd7\x16\xb9\x25\xe5\x0c\xa4\x0a\x68\x46\x5c\x9d\x40\
+\x33\x17\x34\x2b\x22\xe6\xae\xb9\xfd\x57\x9e\x24\x3c\x50\xca\x32\
+\xf8\xf6\x01\x81\x70\xd5\xad\x40\x1e\x73\x34\x2c\xd5\x08\x9d\xad\
+\x13\x74\xae\x17\xf6\xb1\xa1\xb3\x58\xbd\x7e\x6e\xe8\xbc\x27\x9c\
+\xe8\xc4\x86\x83\x03\x24\xa6\xc4\xa1\xa3\x05\xa0\xa4\x4b\xd5\x0e\
+\x15\xc6\x17\xc8\x51\x4a\x04\xaf\x08\x70\xa9\x8c\x44\xc9\x45\x24\
+\x0b\x9f\x79\xf2\xe5\xd4\x58\xce\xb3\xb1\x7c\xa9\x70\x18\x2a\x74\
+\xac\x07\x7e\x31\x96\x9a\xf0\x90\x20\xec\xba\xe0\x40\x03\x28\xab\
+\x40\x52\x48\x1c\xb8\x98\xbb\x48\xc3\x14\x82\x66\xce\x04\x59\x2a\
+\xc7\xc9\x51\xd8\xce\x94\x0a\x9c\x30\x79\x8d\x23\x5b\x22\x60\xcb\
+\x83\xe5\xee\x8e\xa8\x7c\x9f\xd2\x06\xc4\x89\x60\x5e\x58\x33\x1e\
+\x9f\x56\x5e\x0b\x84\x7d\xa4\x95\xd7\x4d\x2e\x2c\x9e\x2b\x1c\xce\
+\x5f\x01\xbd\x6a\x57\x58\x03\x2d\x58\x59\x6d\x77\x6e\x8e\xb2\xb6\
+\xaa\x6d\xc2\x3a\x28\x5f\x13\x06\xf1\x14\x91\x2b\x5d\x99\xa2\x95\
+\x68\xb7\xc3\xa6\xc1\x78\x22\xdf\x6e\xdb\xe0\x07\x4e\xdd\xbd\xef\
+\x15\x8c\x9d\x89\xea\x00\x5d\x62\x4b\x4c\x89\x8c\x5a\x85\x65\xc1\
+\x8f\xa9\x24\xf2\x18\xe4\x97\x4a\x8b\xe9\x58\xcc\x06\x5f\x87\x48\
+\x8b\xfd\x01\xf1\xde\x78\x75\xd0\x4a\xd0\xb6\xdc\x67\xc8\x0f\xe1\
+\x9d\xfb\x23\xec\x09\xf0\x15\xf4\xf5\x21\x4d\xdd\xbc\xc0\x53\x34\
+\xec\x3d\x68\xfc\xd5\x61\xd6\x4d\x8a\xc3\x2d\x12\xe0\xa1\x77\x00\
+\xa5\xd8\xda\x94\x94\xcb\x6c\x3c\xe5\x84\x49\x79\x33\xbc\x10\xca\
+\xb3\x7e\xa4\x82\x02\x7f\xc6\xba\xe2\xa6\x6a\x91\x66\x48\x02\x70\
+\xa5\xa8\x40\xd8\x91\xf4\x91\x24\x92\xd6\x88\x05\xde\xc2\x3c\x12\
+\x0a\x93\x19\x71\x98\xef\x83\x5b\x7e\x08\xc3\x7c\x65\x98\x55\x2b\
+\x25\x9a\xc3\x6a\x46\x5a\xc2\x98\x8c\x94\xd4\x02\xd1\x87\x93\x59\
+\xad\x37\xab\x56\x35\x4f\x3f\x65\x96\x47\xb4\x9f\xb5\xfa\xa6\x06\
+\x1b\xd9\xb3\x0c\xf5\x45\x0d\xc5\x01\xd0\x29\x68\xd8\x4b\xd0\xf0\
+\x96\x85\xa0\x5c\xeb\x42\x07\x57\xd7\x46\x01\x44\x71\x22\xa7\x16\
+\x98\x57\xa9\x6b\xab\xa8\x80\xe5\x72\x46\x00\x90\x09\x06\xd0\xd6\
+\x48\xaf\xf6\x71\xec\x8e\x93\x2e\x71\xa8\x0f\x9c\xe7\x87\x2e\x97\
+\xbb\x07\x2e\xf9\xa1\x96\x91\x75\xff\x16\xfe\x9d\xdf\xde\xdc\x2e\
+\xff\x75\x6f\x20\xf6\xb2\x95\x7b\x89\xbd\x2c\xad\xf6\x79\x2b\xfd\
+\x6f\xf7\x5e\x4a\xba\x67\x83\x08\x59\x4e\xd3\x49\xee\x74\x52\x71\
+\xa3\x6b\xbb\x78\x4d\xff\xf8\xd3\xc9\x67\x4c\x03\x6d\x8b\x02\x11\
+\x08\xe7\x16\xf5\x4d\x29\x37\xa7\x29\x65\xbd\xac\x8f\x95\x87\x2a\
+\xde\xc4\x5c\xcb\x34\xa2\x34\xd4\x28\xa8\x0e\x0e\x20\x2a\x50\x61\
+\xb6\x0a\x07\xa8\xda\x92\x74\x8e\x06\x36\xb5\x3f\x51\xf9\x7e\xe5\
+\x86\x83\xab\xbf\x40\xe2\x7b\x88\x39\x11\xcb\x99\xc7\x8f\xc8\x9c\
+\x1f\xe4\x1c\x42\xbb\x75\x94\x64\x99\x82\xe8\x77\xc6\x4e\x9f\x22\
+\x40\x1f\x2e\x3f\xb6\xcc\xfc\x6c\x97\x1f\x7b\x00\xc0\x14\x7a\xbf\
+\xa9\x4b\x7d\x12\xe4\x6d\x30\xad\x9c\x2f\xdb\x5f\xb6\xec\xba\xda\
+\xa4\xb4\x61\x9f\xd9\x16\xbb\x72\xe6\x12\x19\x74\xab\x6f\xfa\x28\
+\x7e\x89\xd3\xf4\x71\xf4\x88\x64\xab\x25\x8d\x32\x4b\xcb\xd7\xc5\
+\x32\x6a\x5f\x77\xbb\xdd\x4e\xfb\xea\x78\x0b\xcc\x91\xfe\x9b\xfe\
+\xf4\x31\x11\xb9\x19\x37\x4a\xf4\x5e\x10\x21\xb4\xce\x3b\x35\x44\
+\x08\xea\xf5\x22\x43\x7f\x8a\xf3\x4f\x75\x28\xbe\xad\x06\xc5\xc5\
+\xd9\xa6\x2d\xa1\x78\x04\x0c\xd5\x07\xc4\xc5\x99\x88\x13\x10\xef\
+\x05\x88\x3f\x81\x27\xfb\xce\xa5\x72\x05\x83\x95\x8b\x4b\x54\xc5\
+\xce\xa8\xf6\x60\xf7\x8d\x27\xcf\xc1\x29\x8d\xd2\xcf\x6a\x90\xc3\
+\xe0\x86\x9b\x44\x7c\x1e\xdc\x9d\x9f\x7d\x8c\x77\xc6\x24\x9e\x14\
+\xa1\x33\x51\xbb\xc7\x9f\x7d\x0f\x99\x7c\xf9\x8a\x53\xec\x99\x4b\
+\xb5\x9e\x16\x75\x24\xe4\xc2\xcb\x36\x15\x38\x10\x51\x4b\x5b\x42\
+\x38\x1d\x99\xcb\x33\xe0\xc7\x5c\xf9\x2c\x60\x51\x33\xc5\x24\x1a\
+\x61\x9f\x7a\x8b\xbc\x7e\x9f\xdf\x13\xef\x91\x28\x57\xec\x79\x4c\
+\xdc\x3c\xa4\x59\x9d\x51\x75\xbc\xc8\x30\x73\x96\xf3\xfc\x8b\xd7\
+\xcc\x73\xcd\xfd\x41\x96\x14\x54\x1f\xbb\x13\xc6\x1e\x1d\x07\x30\
+\x1a\x2b\xd4\xc1\xc8\x95\x7d\xbd\x52\xf5\x5f\x95\x0e\xff\x77\x79\
+\xfb\xc0\x31\x05\xd5\x19\xc7\x25\xdf\xde\x00\x05\x7d\xcc\x84\xc8\
+\xf2\x3c\x94\x9c\x53\x0c\x62\x9d\x66\x94\xdc\x94\x53\x89\x83\x83\
+\x39\x53\xca\xae\x13\xca\xd2\x9e\xd1\x33\xec\x4f\x5f\xa2\x4f\x04\
+\xbb\x00\xfa\x98\x73\x88\xb0\xb5\x65\x1c\x72\x8a\x59\x7b\xfc\xd7\
+\x1f\xb2\xdc\xf5\x4e\x55\xb1\xe9\x3c\x64\x09\xa5\x04\x38\x33\x87\
+\x7d\x7f\x54\xad\x5c\x11\xd9\x36\x83\x1b\x8f\x2e\x93\xe8\x2a\x6f\
+\xfc\xd6\x75\xd6\xcc\xf6\x56\xb9\xfb\x6e\xbd\xdd\xdf\xd6\xd7\xfd\
+\x1b\xca\x1d\x98\xe4\x6a\x94\xbf\xe5\xa0\xc6\x21\xb0\x1c\xd4\x38\
+\x0a\x03\x80\x96\x49\x9d\x83\x60\x18\xa8\x71\x0c\x0c\x03\x35\x0e\
+\xc1\x6b\xec\xfc\x2d\xea\x1e\x86\x98\x89\x1a\x87\x22\x66\xa2\xd2\
+\x70\xd4\xee\xaa\x54\x4c\x44\xb6\x8b\x97\x1f\xd6\x7b\x2b\xdf\x6c\
+\x62\x35\x11\x86\x98\x50\x38\x11\x6e\xfe\x88\xee\xca\xa6\x4f\x77\
+\x6d\x1b\xa7\x25\xcf\xa9\xb3\x91\x09\xdd\x22\x49\xd8\x20\xcd\x6e\
+\xa1\x62\x82\x24\x85\x84\x39\x41\x51\x56\xfa\x1c\x45\x59\x04\xa0\
+\xea\x91\x91\x7c\x0e\x0f\x51\xb3\xc9\x4a\x51\xfc\x38\xf8\x6d\x79\
+\xba\xa1\xc2\x22\x4a\x39\x2f\x2c\x35\x80\x4f\xd1\x15\xfb\x04\x82\
+\x46\xbf\x24\x65\xfb\xaf\xfa\x70\xe8\xeb\xba\x1c\xfe\xcf\x82\x40\
+\x9d\x8a\xeb\xf3\x9d\x5d\x11\x28\x32\x9d\xc1\x04\x4f\xc9\x40\x97\
+\xa1\xf7\x2a\xf7\x61\x8e\xe1\xd4\x95\x8c\xbb\x2d\x7c\x9d\x53\x32\
+\xee\x98\x87\xed\x9e\xf0\x51\xbb\x01\x81\xb7\x94\x51\xba\x6f\x54\
+\x46\xe5\xab\xcc\x0f\xca\xc0\x9e\xee\x31\xb7\xf2\x8b\xe1\x29\x2c\
+\x88\xa6\xf5\xf4\xa7\x87\xb7\x81\x80\xd8\xfa\x23\xbf\x2a\x65\xfb\
+\xab\x0b\xdf\x25\x2c\x3e\xad\xce\x56\x93\x3b\x2b\x8a\x1c\xe9\xf0\
+\xe5\x8a\x12\xa7\xf4\x37\xcb\x4a\xca\xa6\x63\x21\x25\x24\x99\x10\
+\xa3\x9d\x5e\x96\xa9\x67\xb3\xf3\xed\xae\x71\xdd\x40\xe6\x43\xdf\
+\x77\x8d\x76\xbb\xd1\x54\x2d\xa7\x74\xee\xe3\xe9\x28\x0c\x1c\x25\
+\xa8\xfe\xf7\x2f\xfa\xfe\x3d\x67\xfe\x67\xf0\xa5\x06\x2c\xe4\x0e\
+\x28\x61\xa6\x95\xfa\xd8\x7b\x28\x24\xf3\x4d\x8f\x42\x73\x92\x2c\
+\x31\x5c\x26\x3e\x08\x9f\x00\x92\xf8\x1b\xf0\x6a\x3c\xe6\x92\x04\
+\xae\xe8\xdb\xef\xbf\xc3\x68\xd8\x82\x33\x23\x2a\x95\x99\x53\x14\
+\x9a\x8a\x80\xf9\x20\xfc\xf9\x44\x09\x4e\x57\x68\x01\x64\xfb\x2d\
+\x66\x24\xf1\x99\xbd\x7c\x46\xbe\x84\x62\x12\xd5\xaf\x63\xc6\x30\
+\x2b\xaa\x71\x92\xc1\xd7\x5c\x6e\x56\x65\xb7\x8e\x25\x45\x6d\x6f\
+\x6c\xd9\x65\xf0\x7c\x01\x2d\x2b\x8f\xc2\xca\xa6\xf1\x5a\x1d\xd4\
+\xe3\xb0\x65\x8f\xa7\xe4\x8b\x28\xae\x3d\x92\x8c\x4c\x30\xb6\x86\
+\x99\x65\xed\x51\x98\x89\xd6\xef\xf2\x99\x89\x6b\x8f\xc2\x4c\x6a\
+\x57\x47\x3e\x47\x99\x26\xd5\xd9\x4a\x17\xe8\xdf\xba\x50\xa7\xa1\
+\x15\x90\x0a\x0d\xb9\x0e\x0b\x02\xa2\x81\xd4\x02\xe7\xf2\xde\xf4\
+\x2a\x80\x01\xa0\x9d\x73\xc6\x4f\x2d\x59\x05\x6e\x34\x09\x08\x3a\
+\x0e\xb0\xd7\x77\x3c\xb5\x5b\xd0\xfd\x45\x6d\x50\x54\x01\x96\x29\
+\xd5\x2d\x38\x71\x08\x7d\x4c\xd2\xca\x6c\xad\xd7\xbf\x69\x61\x9a\
+\x18\x92\x1e\x93\x7d\x98\xd7\xde\x99\xed\x90\x4b\x9a\xaa\xd8\x48\
+\x04\x26\x3f\x61\x67\x24\x75\x8d\xe4\x62\xaa\xe6\x45\xfd\x7a\xa9\
+\x55\x99\xde\xbc\x7f\xdb\x59\xfe\xf0\x86\xfa\xe5\x8d\x8b\xee\x6d\
+\xfc\xdb\x1b\x4d\xf5\xf4\x2a\x21\x97\x08\x49\x03\x3d\x69\x67\xa9\
+\x5d\xb6\xbb\x69\x72\x37\xed\x3c\x72\xe6\x52\xd8\xa1\x49\x89\xf6\
+\xa8\x92\x5e\xee\x3b\x3d\xac\x8c\x95\x4c\x53\x32\xbe\xa8\x22\xe3\
+\xab\x6e\x3b\x43\xee\xf2\x07\x94\x71\x74\x7e\xe9\xb0\x92\xbd\xba\
+\x49\x8b\xe2\xfa\xaa\x8a\x64\x2f\xae\x2e\x7f\x02\xed\x8d\xb6\xf2\
+\x1f\x56\xb2\x17\x17\x19\xc9\x76\x2b\xe9\xac\x62\xf7\x87\x97\x6c\
+\xde\xf9\xd5\x03\x23\x43\x16\x7d\x2b\xe9\x6f\xa7\x73\xbd\x0d\xd0\
+\xac\x97\x72\xf2\x16\xea\x7b\xcd\x90\xf6\xcf\xfe\x07\xa5\x05\x6e\
+\x26\
+\x00\x00\x0a\x1d\
\x00\
-\x00\xae\x67\x78\x9c\xed\x1d\x6b\x6f\xdb\x38\xf2\x7b\x7e\x05\x91\
-\x0f\xbd\x1e\xd0\x8d\x63\xe7\xdd\x75\x7c\x68\xd3\x27\xd0\xee\xa6\
-\x75\xda\xde\xde\x97\x05\x2d\xd1\x36\xaf\xb2\xe4\x25\xe9\x24\x5e\
-\xdc\x8f\xbf\x19\x92\xb2\x1e\x91\xe5\xc8\xb2\x2c\xbb\x75\x51\x20\
-\x16\x49\x91\xc3\xe1\xbc\x38\x33\xa4\xda\xff\xba\x1f\x79\xe4\x96\
-\x09\xc9\x03\xff\x72\xbf\x79\x70\xb8\x4f\x98\xef\x04\x2e\xf7\x07\
-\x97\xfb\x5f\x6e\xde\xfc\x72\xbe\xff\xaf\xce\x5e\x7b\xc2\xa3\x46\
-\xc7\xd0\xa8\xb3\x47\xda\x8e\x47\xa5\xec\xbc\x9d\xf0\xe7\xcf\x5f\
-\x71\xea\x05\x03\xf8\xeb\x0d\xba\x4c\x29\x78\x59\xbe\x12\xb4\xaf\
-\xda\x0d\xd3\x08\x5a\xdf\x71\x77\xc0\x14\xd1\xcf\x97\xfb\x9f\xbe\
-\xe9\xc7\x7d\xe2\xd3\x11\xbb\xdc\xcf\xed\x04\x07\x23\xed\xb1\x08\
-\xc6\x4c\xa8\xa9\x7d\x63\xc0\x82\x11\x53\x62\xaa\x2b\x49\x5b\x30\
-\x47\xe9\x5f\xa4\x7d\xdf\x39\x6c\x37\xee\xed\xc3\x14\x1f\xa6\xf6\
-\x01\x40\x50\xc3\xce\x59\xf3\xbc\xdd\x30\x3f\x4d\xf1\x90\xf1\xc1\
-\x50\x75\xce\x0f\xa1\xdc\xfe\xd6\x7d\x36\xc2\x4e\xdb\x8d\x70\xf0\
-\x2c\x48\xee\xb8\xef\x06\x77\x37\x5c\x79\xcc\x02\x23\x95\x00\xe0\
-\x3b\x6f\x99\xcf\x04\xf5\x88\xb4\x93\x69\x37\x6c\xc5\xc3\x2e\x3d\
-\x3a\x0d\x26\x11\x72\xbe\xbe\x0c\xee\x3f\xe8\x22\xdb\x63\x6a\x48\
-\x39\xa6\x0e\x74\xb4\x6f\x27\xe0\x4f\x46\x3d\x26\x3a\xa7\xed\x86\
-\xfd\x65\xc0\x8f\x8f\xf0\xa0\x8b\x11\x15\x03\xee\xa7\x7a\xb8\xc8\
-\xed\x81\x2b\x36\x8a\x30\x19\x5f\xcc\xb7\x22\x98\x8c\x01\xe6\x70\
-\x39\x07\xe1\xb3\x69\xfe\x60\x70\x15\x21\x2b\x03\x5f\x7a\xd1\x49\
-\x37\x03\x6b\x0f\x81\xca\xc5\x9d\x1d\x0d\x08\x57\x71\x87\x7a\xa6\
-\xf4\xcf\x56\x34\x70\x34\xa3\x8c\x8e\xde\x3d\xe8\x68\x18\x08\xfe\
-\x77\xe0\xab\x59\x57\xcd\x8b\x59\x5f\xe9\xde\x1e\x20\x49\x93\xf8\
-\xb5\x60\xfd\xab\x21\x73\xbe\xc7\x91\x85\x15\x63\xa8\x70\xb0\xa2\
-\x17\xdc\xff\xd9\x6c\xc5\xba\xcd\xc0\x5e\x10\x78\x37\x7c\x9c\x68\
-\x33\x43\xe2\xfb\x3e\x51\x43\x2e\x09\xfc\xd7\xfd\x31\xf7\x19\x14\
-\x30\x8b\xd4\xbb\x40\x7c\xef\x01\x7f\x0f\xe1\x97\xff\x0f\x45\xe8\
-\x78\xcc\xa8\x38\x20\x5f\x24\xeb\x4f\x80\x52\xb9\xef\x30\x42\x3d\
-\x8f\x04\xfd\xd8\x5b\x38\xa0\x24\x54\x60\x95\x0c\x08\xf7\x75\xdd\
-\x0b\xa1\xbb\xb1\x1d\x1e\xa4\xd6\x29\x7b\xb1\xb2\xe7\xc3\xee\x55\
-\xf6\x64\xde\x71\xf7\x01\xe4\xcb\x8f\x83\x38\x7e\xed\xa3\xcc\x20\
-\x52\xb9\xc0\x95\x97\xfb\x87\xa9\x71\x1d\xdb\xf7\x10\x06\xd6\xe3\
-\x7e\x8b\x86\x75\xca\x8c\x7b\x4d\xd5\x70\xf1\xb0\x1f\x03\xb7\x11\
-\xca\xcd\x47\x8e\xa6\x45\x19\x90\x59\x8c\x0e\x1b\x49\x42\x5c\x40\
-\x97\x9f\x3e\xd0\x1e\xf3\x42\x62\xf4\xf0\x21\x49\xd7\x45\x16\xcc\
-\xac\x15\xf7\x15\x13\x7d\x0a\xa4\x34\x0a\x5c\xb6\xfc\x82\x51\x8f\
-\x0f\xfc\x11\xf3\x1f\x0c\x06\xd3\xfd\xa4\x9e\x3f\x7f\x81\xf5\x9f\
-\x51\x60\xff\x6f\xf6\x78\x23\x28\xf7\x60\xb4\xa8\xe4\xeb\x15\x43\
-\x78\x00\x8c\x38\x96\xaa\x42\x67\xc4\xe6\xc1\xa8\x17\x64\xb2\x39\
-\x56\x20\x9b\x1f\x2f\xcf\xe5\x37\x96\xc5\x91\x0f\xbf\xbc\xd7\x68\
-\x46\xb6\xbc\x1b\x72\xe0\xc9\x88\x71\xa1\x7c\xe2\x31\x72\xc7\x81\
-\xa3\x91\x81\x9e\x93\x1b\xe8\xb5\x47\x85\x79\x43\x97\x8f\x3d\x6a\
-\x79\xde\xbc\x13\x6a\x2b\xec\x8f\xc2\xd3\x98\x0a\xaa\x98\x96\x01\
-\xf0\xe2\x33\x1c\x03\xba\x54\x54\x7e\x4f\xf6\x33\x91\x4c\x8f\xfc\
-\x46\x30\x76\xf5\xe2\x15\xb9\x81\x16\xb7\x9c\xdd\x11\x39\x95\x80\
-\x31\xd2\x0f\x84\x1e\x85\x2b\x89\x6d\x85\xa1\x12\xea\x28\xb0\x29\
-\xd6\xc2\xd3\x5f\xf8\x47\x4d\x8d\x9b\xc9\xc7\x0f\xe8\xea\x31\x6c\
-\x17\xd1\x83\x59\x9d\x2c\x3c\xce\x1b\xae\x91\x1e\xaf\x1c\x00\x76\
-\xb5\xcb\x40\xb0\x90\xf7\xda\x0d\xa3\xa2\x67\xfa\x3b\x51\x5d\x5a\
-\x9b\xb7\x1e\xaf\xcc\xb3\x84\xe6\x02\xa5\x3d\x5f\x66\xb2\x3e\x9d\
-\x78\xd0\x75\xe0\x05\x99\x2b\x58\xb9\xa0\x82\x71\x5f\x4e\x94\x0a\
-\xfc\x0c\x59\x05\x75\x3d\x53\xb7\xb4\xb0\x42\xa9\xe0\xc6\x27\xa9\
-\x65\x81\x0f\xa2\x21\xe8\xfd\x17\x4c\xec\xb4\x89\x97\x47\x33\xa9\
-\x71\x75\x77\x69\x26\xc4\xb2\x14\x95\x0a\xe6\xe2\x46\x00\xff\x24\
-\x2b\x06\x20\xad\x7c\xac\x32\x3f\x92\x95\x3d\x6f\xc2\xb0\x4e\xff\
-\x4d\x12\xf4\x83\x41\x56\x2e\xae\x2c\x39\x6c\xa6\xb4\xaa\xc4\xea\
-\x58\xa0\x0f\xe7\x32\x50\xd7\xa7\xe3\x4d\xe7\x9e\x45\xd2\xa1\x38\
-\xff\x48\x9c\xb5\x9c\x82\x2d\xe1\xed\x18\x28\x01\xbe\xc5\x05\x22\
-\xe8\xe7\x63\xa2\x65\x2d\xf7\xab\xc0\x87\x5f\x13\x6d\x8e\x6d\x3c\
-\x33\x1d\xad\xc6\x72\x7e\xc8\x54\x56\x21\x91\x1e\x83\xb6\xc4\x15\
-\xf4\xce\xb7\x06\x2f\x47\xac\xc4\x50\x84\x86\x6f\x89\x3d\x6f\x11\
-\xbe\x3b\x3e\x9e\xcf\x78\xcd\xd6\x49\x0e\xeb\xb5\x4e\x4e\x6a\xd3\
-\x5e\x11\xae\x7e\x3e\x26\x5c\x40\x9f\x0b\x4d\x41\xd8\xc0\x32\xed\
-\xa1\xac\x81\x07\xbb\x63\xee\x67\x6d\x5b\x25\x94\xf7\x22\x97\x5e\
-\xf6\xcc\x1e\xab\xc6\x66\x13\x5c\x9d\x29\x78\x4b\x81\xce\x53\x23\
-\x5b\x67\x66\x2b\xe1\xd6\x2c\xd4\x6b\x01\x92\x8f\x2d\xda\x96\x92\
-\x7a\xc5\xfb\xab\xa3\x92\xfb\xab\xc3\x52\xaa\x8d\x72\x2d\xb4\x6b\
-\xd1\x6a\x8b\x3c\x41\x27\x65\xf4\x19\x23\xb3\x09\xa2\xd2\x82\x39\
-\xf2\x3e\x67\x82\x7c\x67\xd3\xb5\xf8\x55\x60\x40\x27\x04\x60\x53\
-\x49\xbf\x9c\x73\x43\x0e\x39\x0e\x56\x97\x6f\xc5\x51\xc2\xab\x6f\
-\x74\xea\x95\x9a\xfa\x12\x6c\x84\xd1\x2d\xa0\xdf\xb4\x14\xe9\xea\
-\xe2\x05\xbc\x02\xad\x19\x34\x46\xb3\x23\x45\x3d\x0c\x54\x80\xf6\
-\x1a\xbf\x9b\xf5\xd8\x6e\xe8\xc2\xc2\xa4\x2a\xf9\xdf\xec\x1d\xf7\
-\xd5\x7c\x52\xc5\x16\x29\x74\x9a\x88\xe3\xf1\x61\x22\xf6\x38\xab\
-\xb5\x71\xc7\xd6\x61\x22\x04\x19\x81\x95\xee\x70\x8e\xc8\x32\xa8\
-\x5b\xa9\x2d\xd3\x6a\x96\xd9\x96\x6f\xaa\xc4\x3d\x2d\x27\x71\xa5\
-\x9d\xdb\x0a\x24\xad\x33\x11\x02\x48\xf6\xbd\xef\xb2\xfb\x6c\xf3\
-\xa5\xb9\x16\xf3\x05\x66\x83\xb3\xda\x49\x70\x53\xba\x93\xe0\x51\
-\xc1\x8a\x25\x78\x3e\xef\xed\x24\xf8\xca\x25\xf8\xb2\x91\x89\x17\
-\x9e\xda\x58\x01\x7e\x56\x4e\x80\x53\x33\xb5\xb5\xc8\xef\xf5\x6c\
-\x3f\x61\x36\x9a\xd1\x77\xe2\x7b\x27\xbe\x37\x29\xaa\xda\x8c\x53\
-\xd1\x32\xb9\x28\xe5\xb6\xfd\xd6\x5d\xab\x33\xd2\xf4\x2b\x35\x48\
-\xb3\x0f\xdc\x67\xaf\x5d\xae\x1e\x48\x33\x74\x19\x31\xa8\x28\x13\
-\x1d\xca\x72\x68\x47\xb3\xd5\xfe\xb5\x84\xe3\x3a\x4c\x9c\xac\x22\
-\x5f\x2b\x8e\xf2\xb5\xf8\x1e\xe2\x33\xd3\x93\x36\x2b\xbc\x99\x32\
-\xb0\x6e\x4e\x3c\x7e\x3c\x23\x3e\x3e\x59\x71\x79\xc2\xd5\x3d\xd8\
-\x64\xc5\x3e\x01\x08\xc9\x1d\xf5\x31\xd9\x70\x96\x4a\xa4\x03\x07\
-\x8d\x98\xaf\x58\x04\x23\x5d\x61\x93\x91\x08\x95\x21\xc9\x57\x41\
-\xcd\x5d\x7a\x0b\x30\x18\xf5\x6e\x63\x44\xd4\x77\x63\xbe\x6b\xea\
-\x88\x40\x4a\x22\x99\xc4\xc4\xe8\x12\xbe\xeb\x22\x51\x4d\x00\x2a\
-\xf0\xd9\x3d\xdf\x58\x55\x5f\x37\x99\x9f\x55\x41\xe6\x65\x5c\xb4\
-\x59\x29\xb9\x4e\x30\x9e\xc6\x92\xe7\x7a\x0c\x8c\xd0\xb1\x0a\x29\
-\x0a\xac\xdc\x11\x90\xda\x33\x12\x00\xb5\x8b\x3b\x2e\x59\x58\x24\
-\x4d\x7b\xea\xdd\xd1\x29\x50\x9e\xa2\x02\xd3\x2d\x89\x1f\xfc\x32\
-\xeb\xb1\x0a\x56\x78\xeb\x05\x3d\xea\x91\x15\x8c\x61\x31\x90\x1a\
-\xa6\x07\xf8\xeb\x80\x20\x87\x8e\xf5\xcf\x6a\x75\xc6\x78\x3a\xda\
-\xe0\x4c\xc0\xba\xf9\xa7\x79\x5e\x09\x03\x95\x88\xd9\xff\x16\x88\
-\x11\xf5\xbc\xe9\x33\x02\x88\x64\x42\x93\x21\x86\x3a\x6c\xcc\xf0\
-\x99\x55\x16\x63\xce\x24\x41\xe0\x24\xf3\xa0\x9c\xb9\x07\x24\x64\
-\xbd\x60\xac\x6d\x9f\x74\x52\x7c\x8f\x02\x67\x85\x31\xff\x90\x11\
-\xc3\xb7\x81\xaf\xa4\x62\xd4\xad\x24\xb3\xbd\xab\x07\x49\x02\x90\
-\x98\xdc\x7a\x94\x89\x86\xe2\x25\x00\xf1\x7b\x18\x7e\xdd\xf1\x44\
-\x16\x4f\x9c\x54\xc2\x12\xe7\xab\xd5\x29\xda\x84\x8a\x6b\x07\x74\
-\x52\x83\x39\x05\xc6\x82\x54\x31\x7e\xb1\x19\x2d\x98\xdd\x02\xa5\
-\x9a\x49\xfc\x40\xc5\xde\xef\x19\x07\xf7\x58\xbf\xe3\x7b\x53\x78\
-\x81\xf9\x04\x40\x07\x3b\x07\x8a\xae\x6e\x3e\x7f\xa8\x84\x29\x5e\
-\x24\xe1\x0e\xc1\x7d\xea\x72\x49\x7b\x5e\xe4\x75\x47\x87\xcd\x3f\
-\xb7\x59\x05\x99\x05\xea\x6e\xb0\xbb\x7d\xe5\x4e\xdf\xfc\x1d\xee\
-\xce\xe9\xbb\x6a\xa7\x6f\xb3\xa4\x83\x54\x50\x97\x4f\xe4\x2c\xd3\
-\x54\xcb\x02\xe0\x49\x39\x66\x0e\x07\x4b\x70\x1c\x00\x22\xe5\x01\
-\x9e\xd2\xc3\xe2\x43\x93\xc7\x13\x10\x60\x55\x45\xf1\x10\xd9\x53\
-\xee\xf7\xb9\x0f\x70\x97\x60\xd4\x05\xb1\x45\x41\xfd\x41\x1d\xee\
-\x9c\x05\x19\x52\x0b\x48\x5d\x4e\xfa\x7d\x9e\xf6\x14\xdb\x39\x8c\
-\xef\xd7\xa3\xf6\x01\x7b\x9f\x0d\xf2\xb6\x54\xfa\x54\x7d\x12\xa4\
-\x80\xcf\xb2\x80\xbe\x2f\x71\xe0\x2b\x4b\xdf\xcf\xf8\x52\x2b\x6d\
-\x50\xe1\x24\x70\x9c\x89\x20\x74\x40\xd1\x74\x8d\x19\xb6\x6a\x08\
-\x6a\x53\xa0\x53\x85\x9a\xb3\x9b\xdc\x77\xb9\x43\xd1\xc8\x35\x91\
-\x09\x3c\xef\xc9\x60\x56\x25\x7c\x18\x8b\x12\x01\xe8\x3d\x1f\x4d\
-\x46\x95\x68\xed\x3e\xf5\xe4\x3a\xd4\x36\xcc\xe1\x67\xd2\xd9\x3b\
-\x8d\x3d\x1f\xd3\x55\x84\x69\xf3\x77\xc8\xcc\x47\x1b\x78\xf5\xf4\
-\x9f\x2b\x76\x3e\x1a\xae\x4d\x4b\x09\x54\xf9\x3d\xa6\xe3\x0a\xdc\
-\x65\x02\xc4\x48\xdc\x4e\xa8\x42\x86\xcc\x01\x64\x03\xb5\x7f\x7e\
-\x76\x43\x55\xab\x68\xc5\x6b\x76\x00\xfa\xe2\xe2\x62\xf9\x10\x74\
-\x5e\x5e\xf5\xf1\x7a\x22\xdb\x46\xec\xbe\x36\x0b\xbe\xa5\xb2\xb7\
-\x6a\x8b\xa5\x59\x89\xc5\x52\x62\x13\x01\x16\x4b\xc2\xd7\xd6\x35\
-\xbb\x7a\x13\xb8\x99\xb9\x19\x86\x81\x3e\x61\xc3\x7c\x76\x0b\x6c\
-\x8d\x1e\x08\x0c\xfe\x54\x29\x49\xba\x30\x64\x78\xc5\x48\x0c\xa4\
-\x6d\x76\x27\x20\x16\x71\x2e\x2f\xe9\x8f\x7b\xcc\xa6\x00\xd1\x2e\
-\x7b\x04\x2e\x76\xdb\x88\x8c\x13\xab\xf1\xcb\x4e\x64\x89\xa8\x47\
-\xc1\xab\x47\xb6\x7d\x31\xab\x8e\x50\x14\x38\xa9\x5f\xe4\xda\x9d\
-\x05\x99\xce\x79\xd2\x8e\xc7\xa4\x1d\x25\x16\x04\xbb\xcb\xd2\xae\
-\x93\x61\x14\x4a\xc6\x9b\x38\xb0\x6c\xec\x51\x9f\x91\x98\x21\x6d\
-\xaf\xe3\x91\xc4\x9d\x60\xa7\xa1\x87\x96\x20\x18\xba\x41\x35\xdb\
-\x33\x14\x88\xdf\x2c\x4c\xd7\x1a\x26\x25\x28\x4c\xa5\x84\x4c\x2c\
-\x28\xbc\xf4\xa8\x37\xe1\xa0\x3b\xa2\xcf\x22\xfa\x6a\xa2\x72\x25\
-\xf2\xe0\xb3\x5c\x12\x89\x58\x9a\xa1\x66\x4c\xd2\xe8\xc3\x23\x6c\
-\x12\xa2\x74\x8d\x03\xf2\x7b\x18\xd9\xd6\xd6\xc1\x34\xfd\xc6\x1d\
-\x07\x28\x45\x91\x74\xad\x02\x14\xff\x06\xc7\x9a\x1d\xf5\x9d\x96\
-\xcf\x21\x29\x40\xee\x88\x8a\x5d\xf4\x79\x3e\x99\x17\xb8\x51\x2d\
-\xd3\xed\x5d\xf6\x16\x96\x84\x70\xde\xc8\xcc\xe7\xfc\x19\x16\x20\
-\x45\x4b\xf6\xdf\xae\x37\x95\x16\xcb\xe5\xcd\xfe\x16\x64\x2f\xe0\
-\x7a\xb2\x76\xff\xfd\x07\x79\x7a\x13\x8c\x33\xa3\x1f\x6b\x82\xe0\
-\x3f\xe4\xe9\x1b\x01\xbc\x55\x23\x0c\x7f\x00\x0c\x5d\x30\x68\x4b\
-\x81\x50\xb7\x48\x6a\x56\x93\x51\x56\xee\x92\xc7\x98\xb5\x39\x10\
-\xdc\x4d\xe8\x4f\x1d\xae\xb7\xc6\x63\x15\xfa\xf3\x0b\x6c\xd1\x71\
-\xd0\xad\x76\xe6\x9b\x09\x6c\xa6\xe0\x5b\x79\xf4\x3d\xdf\x8f\xb3\
-\xf3\xe5\x97\xf1\xe5\x17\xd9\x61\xe6\x9f\x65\xa8\xc5\xc5\x9f\xf6\
-\xd3\x19\x07\x48\x4c\xa6\x98\xa4\x9c\x1e\x23\xb7\x5c\x72\x4c\xc3\
-\xd1\xe2\x25\xeb\x4e\x59\xd8\x09\xe0\x7d\x8e\xb7\x2c\x66\xde\xc7\
-\x12\x88\x26\x3a\x7b\x88\x86\xa9\xac\x55\x66\x10\xc1\x9e\x72\x2d\
-\xd6\xbc\x4d\xe4\x81\xe1\xde\xfe\x58\xe2\xe4\x11\x96\x76\x7e\x46\
-\x74\x65\xb4\x3c\x3f\x47\x19\x49\xd6\xde\x8c\x5d\x83\xe1\xfe\x2a\
-\x98\xc0\x84\xe7\x45\x87\x5c\x5d\x1b\xc6\x88\x36\x30\xd2\xa7\x4f\
-\xb5\x1b\xe4\x01\xaf\xab\x3b\x06\x0c\xcb\x28\x30\xb5\x96\x04\x78\
-\xe6\x61\x79\x86\x72\x99\xc3\x47\x00\x79\x76\x14\xa9\x44\x10\x29\
-\x3b\xea\x65\x70\x8d\x51\xaf\x8b\x83\x8b\xf3\x8b\xd9\xbf\xb3\xf3\
-\x56\xbb\x61\x2b\x0b\x0f\x95\x15\x06\xb3\x7d\x35\x0f\x0e\x93\xff\
-\x96\x1f\xa5\xa0\xfd\xd2\x0d\xa9\xfd\x67\x92\x3b\xf5\x04\x58\xf3\
-\x42\xd3\xdc\xd7\x0c\x22\x09\x06\xb1\x1e\x7f\xb0\x6e\x7d\x31\xe9\
-\xfc\xc4\xa3\x9a\x32\x0b\xb8\x6f\x90\x16\xc6\x02\xcd\x6d\x7b\x6a\
-\xc8\xd1\x0b\x7c\x40\xba\x98\x69\xd8\x9f\x12\xb0\x23\x18\x41\x17\
-\x35\xd8\x0c\x53\x22\xff\x9a\x50\xc1\xe4\x4c\x44\x8d\xc2\x6e\x4a\
-\x24\x24\xe7\x44\xb8\x9b\x87\x6b\x89\x70\x23\x2f\xbf\x36\xb4\xb3\
-\xa5\x9c\x5c\xf5\x16\xbc\xe4\xdd\x61\x0b\x32\xed\xe7\xf2\xf6\x7b\
-\xbc\xa3\xdc\xc7\x7c\x57\x01\xd4\x88\xa7\xfc\x88\x07\x4c\x9e\x79\
-\x1a\xbc\x66\x1e\xcf\xb7\x29\xac\xa6\xec\xc2\x8e\xe8\xb1\xbb\xae\
-\xd3\xfc\x5d\x57\xf3\xf4\xec\xec\xac\xd5\x3c\x29\xb3\xf7\x2a\x6e\
-\xa2\x44\xf9\x3f\xa1\x51\x81\xc7\xdf\x78\xb8\x4c\x4e\x10\x08\x97\
-\xfb\x54\x31\x19\x8b\x9a\x91\xa7\x98\x9e\xc4\xee\x0f\xc8\x11\xb9\
-\x24\x87\xa0\xae\x9b\x25\xb2\x92\x73\xc4\xc5\xe9\x5a\xa4\xc5\x8c\
-\x16\xb7\x56\x5a\x14\x75\x5f\xe4\xeb\xaf\x9d\xfb\x62\xe5\x87\x07\
-\x96\x95\x97\xaf\xf8\x88\xf9\xfa\x30\xf4\x16\x48\xcc\xfc\x0d\x6c\
-\x6e\x46\xdd\x79\x35\xf9\x74\x6b\x11\x1f\x2e\x1f\x5d\x6f\xbd\x04\
-\xa9\xda\xde\x28\x70\xe0\x2f\x8b\x81\x16\xe4\xcd\xcd\xe5\x9f\x9b\
-\xc0\x03\xa5\xe5\x3b\x95\x46\x1e\xf3\x65\x6d\x3e\xeb\xef\x64\xed\
-\x4a\x5c\xc5\x05\x9c\x45\x3f\x81\x59\x17\x5d\x60\xa3\x85\x23\xa6\
-\xda\xb9\x98\x97\xd1\x9f\xf8\x8e\x31\xe0\xd4\x90\x2a\x9d\x19\x4a\
-\x89\x0a\x59\xe4\x60\xef\x2b\xb6\xb6\xe7\x5b\x5c\xde\xef\xc3\x4e\
-\x11\xca\x71\x73\xe8\xc1\x7e\x51\x27\xa7\x98\x0e\xc3\x2d\xa6\x12\
-\x4c\x1f\x7a\xa1\x92\x48\x00\xac\xc4\x9e\x31\xe7\x14\x57\x63\x19\
-\x82\xf7\x07\x40\x0e\x8a\xa5\x51\x64\xfd\x48\x60\xb2\x36\x57\xe4\
-\x61\xca\xf1\x63\xc1\x28\x27\xeb\xf7\x63\xa9\x48\xe4\xed\x74\x51\
-\x96\x2e\x3a\x2d\xa7\x8a\x16\x64\x78\x2d\x4c\x88\xc1\x16\xc4\xc8\
-\x82\x0d\xf7\xaa\xe7\x07\xd4\x7f\x04\x51\x19\xae\x89\x19\x4f\x1f\
-\xba\xc1\xe5\x91\xfa\x5e\x22\x77\x66\x7b\xaf\x76\x6f\x3b\x93\x0e\
-\xad\x1a\xbc\xdc\x38\xbd\x90\xf8\xb6\x54\x3c\x14\x35\xc0\xf2\x1d\
-\x39\x3b\x03\x6c\xd5\x9b\xdd\x05\x37\x3b\x3d\x4e\x40\xf6\x01\xdf\
-\x9b\x78\xb3\xe0\xf2\x39\x46\x59\xf7\x0a\xe2\x2c\xf5\xbb\xb3\xaf\
-\x39\xda\x0f\xc4\x66\x08\xa1\x83\xbd\xf7\x00\x2f\xf5\xd1\xee\xa2\
-\xb1\x37\xe5\xc4\x19\xa2\x01\xf6\xe4\xaf\x49\xa0\x7e\x7d\x21\x38\
-\xf5\xcc\x4f\x4c\x65\x0a\x07\x92\x6a\xea\xa5\x9b\x4a\xea\xcb\xb0\
-\xa5\x2d\x61\x82\xf7\xcd\xcf\x3d\x80\xc7\xfc\x1a\x05\x7e\x10\x36\
-\x43\x20\x49\x9f\x8e\xb8\x37\xcd\x1a\xf7\xd9\x3b\xe6\xdd\x32\xfc\
-\x36\xf0\xb3\xa8\x73\xf3\x92\x06\x55\x1b\x96\xd4\x00\xb3\x97\xf1\
-\xfe\xf3\x97\x81\xe7\x9a\xe7\x4a\x92\x19\x70\x8c\xad\xfa\x7a\x6a\
-\x59\x49\x6f\xb8\x68\x4b\xe5\x7c\xd5\x2e\x89\x02\x27\xfc\x32\x7d\
-\x7a\xcb\xde\xe3\x1f\xc9\xb9\xd1\xd8\xc3\x4f\xc1\xca\x21\x63\x95\
-\x0a\xbb\x7c\xfd\xb8\x60\x22\x3b\x05\xb9\x12\x0f\xc5\x1b\xee\xb1\
-\xab\x61\x10\x80\x8c\x7d\xa0\x5c\xfa\x50\xe7\x98\xba\x45\x46\x37\
-\xf7\x8b\x1a\xdd\x47\x87\xf9\x08\x2a\x85\x9f\xe2\x01\x27\x37\x4d\
-\xfd\xf6\x7e\x52\x9d\xd1\xe6\xa0\x3f\xc1\x24\xb5\xe1\x37\xac\xc2\
-\xf3\x5a\xc5\x18\xa4\x9c\xd0\x34\x50\xed\x84\x66\xb6\xd0\x6c\x55\
-\x74\x52\xb0\xc4\x65\x86\xdf\x4c\xf6\x64\xea\xe0\x54\x94\x4e\x89\
-\x2f\xdb\xa4\x08\x4d\x5e\x8c\x5c\xe3\x25\x9f\x63\xc1\x47\x1c\x73\
-\x2b\x65\x78\x2f\x21\x06\x41\xcd\x2b\xb3\x7b\x10\x35\x51\xd2\x5b\
-\xd0\xe1\x98\xd1\x51\xc9\x1d\x6d\x98\xfb\xad\x01\xba\x9e\x01\xb4\
-\x9e\xaf\x77\x4b\x86\xc3\xc6\x47\xdd\x91\x7c\xa6\x9d\x50\xe0\x9a\
-\xe7\x0c\x3b\xa1\x7c\xe0\xef\x09\x1d\x8d\x7f\x25\x1f\x80\x42\x41\
-\x87\x53\x21\x82\x3b\x63\x41\x6f\xe2\x61\xaa\x95\x1d\xa5\xe2\x23\
-\xf3\x29\xde\x4d\xa5\xca\x72\xc7\x78\x5e\x05\x8a\x9c\xd4\x77\x8a\
-\x08\x87\x3f\xab\x77\xf8\x8b\xfa\x86\xbf\xe2\xc2\x81\xcd\x70\x8d\
-\xf8\xb7\x10\xd4\xb8\x04\x16\x82\x1a\x57\xa1\x0b\xa2\x65\x58\xe7\
-\x22\x18\x00\x6a\x5c\x03\x03\x40\x8d\x4b\xf0\x92\x3a\xdf\x65\xdd\
-\xcb\x10\x01\x51\xe3\x52\x44\x40\x94\x5a\x8e\xda\x4d\x95\x92\xa1\
-\xad\x66\x7e\x5e\xd8\x7c\x6b\xe5\x2b\xb4\xe2\x0e\xf5\x62\xee\x4a\
-\xe3\xc6\x8d\x39\x0f\x36\xd1\x5c\x59\xd5\x87\xcf\xe3\x77\x8e\x04\
-\x7d\xe3\xe2\x0d\x31\x61\x9d\xb9\xf6\x90\x17\xec\xf1\xe3\x48\xa2\
-\x82\x91\x5b\x8b\xbc\x03\x12\x7a\x86\xa0\x57\x8f\xf5\x15\xee\x3f\
-\xb8\x39\x06\x86\x3d\xbe\xef\xfe\x8e\x1f\x28\xf0\x5d\x2a\xca\xdc\
-\xa1\x5e\xcc\x0a\x4b\x2c\xe0\x8f\x68\x8a\x7d\x00\x44\x93\xa7\x71\
-\xdc\xd6\x78\xbc\xfb\xf3\xbc\xa8\xf0\x96\x48\xa0\x92\xe2\x67\xd9\
-\xcf\xbc\xbf\xf0\x74\xba\x32\x6c\xed\xbb\x5f\xdf\xc2\x6e\x5a\xe1\
-\x23\xf0\x50\xe0\x54\x2e\x79\x16\xb8\x56\xf3\xcf\xa7\xee\x5c\xab\
-\x6b\x75\xad\x2e\xc8\xe8\xdf\x6a\xd7\xea\x3b\x3c\xd5\x83\xd7\xfd\
-\x61\x84\x50\xda\xa3\x3e\x14\x54\x8d\x60\x8e\x0a\xc4\x14\xef\x16\
-\x55\xf6\x8b\xe6\xc8\x24\x88\x17\x19\x2f\x7c\xe2\xa9\x5f\xc7\x86\
-\x73\x9e\x0c\xd4\xaf\xe8\xa7\xc5\xeb\xc6\xa3\x6c\xb1\x30\xf4\xe8\
-\xba\xcc\x45\xa7\x2d\xaa\xa4\x50\x64\x5a\xbf\x19\x34\x03\x75\x65\
-\x7b\x59\x8f\x1b\xcb\x0e\x86\x24\xb0\xa9\xfa\xa9\x6e\xab\xb0\x55\
-\xf2\xac\x4f\x6b\x59\xab\x30\x34\x67\xba\x43\x3a\x66\x5d\x5d\x46\
-\xde\x60\xdc\xda\xac\x56\x5d\x42\x39\xff\x3a\xc3\x9d\x4c\x5e\xa7\
-\x4c\xfe\x81\x25\xb2\xfd\x22\x91\x4d\xd5\xe8\x17\x21\xf9\x32\x02\
-\x11\x19\xec\xc7\x95\x86\xc9\xca\x44\x5f\x51\xbb\x58\xa3\x58\x0b\
-\x2b\x39\x67\x19\x31\xe6\xa8\xf7\xe5\xfe\xe9\x3e\x19\x51\x31\xe0\
-\xfe\xe5\x7e\xb3\xb9\x8f\xc9\xc6\xed\x31\xbf\x1f\xd1\x71\x98\x2d\
-\xdd\xf9\xeb\x5a\x3f\xbf\x11\xc1\xe8\x23\x6c\xdd\xba\xc1\x44\x60\
-\x76\x6d\xaa\x15\xbc\xe7\x4c\xa4\x0a\x46\x66\x44\xa9\x21\x89\x97\
-\x18\x28\x35\xa3\x74\x34\x9f\xc4\x78\x04\xf0\xa7\xcb\x75\x13\x10\
-\xa8\xcc\x77\x65\xe7\xd3\x37\xfd\x1e\x08\x19\x5b\xb0\x67\x28\x19\
-\x03\x01\xd8\x43\x03\x3b\x78\xc5\xa9\x17\x0c\x0e\x86\x48\xd8\xba\
-\x42\x23\x20\x3d\x6e\x3e\x20\x57\xf8\x2d\xc6\x97\x13\xa5\xf4\x26\
-\x2f\x03\x90\xeb\x89\x1c\x86\xf5\xf3\x80\x31\xc0\xca\x72\x90\xa4\
-\x44\x47\x26\x34\x0f\x71\x37\x0f\x24\xec\x6d\x65\x60\xd9\x9c\xd9\
-\x6c\x04\xcd\x2a\xd7\x02\xca\xa2\xf5\x7a\xb8\xa8\xeb\x01\xcb\xc6\
-\x79\xb3\x51\x14\xd5\xae\x09\x47\xc6\xf7\x33\x07\x98\x59\xed\x5a\
-\x80\x09\xd3\x0a\xb3\x81\x89\x6a\xd7\x02\x4c\x22\x05\x3c\x1b\xa2\
-\x54\x93\xf2\x60\x25\x0b\xb0\xa7\xb6\x60\x52\x0b\x52\xa9\x45\x2e\
-\xec\x44\x7c\x66\x0e\xa7\x98\x59\xcc\x9e\xcd\xa8\x12\x00\x80\xbe\
-\x33\x6e\x7d\xc3\x4c\x3a\xdf\x8e\x8b\x96\xc1\xc0\xa7\x5e\xc7\xf1\
-\xf0\xd6\x03\xf7\x29\x5e\xb4\x80\xfe\x1c\x53\xaa\x5b\xc0\x86\x88\
-\xf1\xdb\x78\x5f\xa9\xbb\x64\xda\x8d\x59\x13\xd3\xa5\x17\xa8\x0e\
-\xa8\xc1\xd7\xe6\x5a\x87\x59\x9f\x58\x6c\x30\x82\x9f\x6e\xb2\x1a\
-\x09\x7f\x13\x35\x1d\xa3\x91\xa7\xa7\x97\x08\x02\xb7\xef\x3b\x17\
-\x00\xf0\x7d\xf8\x38\xed\x1c\x9d\x5d\xb4\x1b\xd3\x50\x9d\xe1\xdb\
-\x0f\x3b\x72\x19\x7e\x6e\x4e\x9b\xa4\xe9\xde\x8e\x9b\x67\xc9\xee\
-\xce\x9b\x59\xdd\x99\x9f\xd2\x2e\x4d\x02\xb5\x6b\xc5\xf4\xec\xfe\
-\x8c\x6a\x71\x8c\x38\x4d\xe0\xf8\xa8\x0c\x8e\x4f\xce\x9a\xa9\xee\
-\x8e\x2b\xc3\xf1\xf1\xea\x70\x7c\x5a\x2d\x8e\x4f\x93\x84\xd7\x3a\
-\x3b\x5c\x25\x8e\x5b\x67\xad\x0d\xc4\x71\xf8\x5d\x99\x8a\x31\xdb\
-\x5a\x29\x66\x9b\xa7\x6b\xc3\xec\xf2\x12\x22\xbc\x02\xad\x5a\xcc\
-\x9e\x9c\x27\x19\xf9\xf4\xa4\x0c\x66\x8f\x4e\x8e\xb7\x40\xf6\x86\
-\x97\x3c\x55\x8b\xd9\xa3\xa3\x14\x66\xcf\x56\x49\xb3\x55\x62\xf6\
-\xac\xbc\xc4\x8d\x3e\x94\x51\x2d\x92\x9b\x29\xfa\x6d\x5d\x94\x92\
-\x0c\xc7\xe8\x2b\x49\x74\x97\xa9\x26\x37\xc5\x76\x88\x5d\xfa\x59\
-\xb1\xf5\x90\xb6\xd0\x4a\x49\x89\x56\xeb\xf4\x31\xc6\xc8\x7c\x2c\
-\xc7\x1f\xa1\xbe\xdd\x98\xf0\xce\xde\xff\x01\xff\x94\xb5\x4d\
+\x00\x50\xcd\x78\x9c\xed\x1c\x6b\x73\xdb\x36\xf2\xbb\x7f\x05\x46\
+\x1f\xee\xd2\x8e\x6b\x59\x7e\xe5\x71\xb2\x3a\x89\x5d\x27\xb9\x49\
+\xae\x6e\xe5\x26\xfd\xe6\x81\x48\x48\x44\x4d\x12\x2c\x08\x5a\x52\
+\x7f\xfd\xed\x02\xa0\x48\x91\xd4\x83\xa6\x25\x3b\x19\xcd\x78\xc6\
+\x22\x00\x62\x17\x8b\x7d\x2f\xc0\xee\xcf\x93\xc0\x27\xf7\x4c\xc6\
+\x5c\x84\xe7\xad\xce\xc1\x61\x8b\xb0\xd0\x11\x2e\x0f\x47\xe7\xad\
+\x3f\x6e\xae\x7e\x7a\xd5\xfa\xb9\xb7\xd7\x4d\x78\x36\xe8\x04\x06\
+\xf5\xf6\x48\xd7\xf1\x69\x1c\xf7\xde\x27\xfc\xcd\x9b\x4b\x4e\x7d\
+\x31\x82\xff\xfe\xa8\xcf\x94\x82\x97\xe3\x4b\x49\x87\xaa\xdb\x36\
+\x83\x60\xf4\x98\xbb\x23\xa6\x88\x7e\x3e\x6f\xfd\xf6\x55\x3f\xb6\
+\x48\x48\x03\x76\xde\x5a\x3a\x09\x02\x23\xdd\x48\x8a\x88\x49\x35\
+\xb5\x6f\x8c\x98\x08\x98\x92\x53\xdd\x49\xba\x92\x39\x4a\xff\x22\
+\xdd\x49\xef\xb0\xdb\x9e\xd8\x87\x29\x3e\x4c\xed\x03\xa0\xa0\xbc\
+\xde\xe9\xcb\xd3\x6e\xdb\xfc\x34\xcd\x1e\xe3\x23\x4f\xf5\xce\xce\
+\xce\xba\x6d\xfb\x5b\xcf\xd9\x4e\x27\xed\xb6\x53\xe0\x55\x98\x8c\
+\x79\xe8\x8a\xf1\x0d\x57\x3e\xb3\xc8\xc4\x4a\x02\xf2\xbd\x8f\x41\
+\x24\xa4\x6a\xff\x32\xc1\x7f\xdd\xb6\x6d\x2d\xcf\xe7\xd3\xa9\x48\
+\x32\xca\x7c\x79\x27\x26\x9f\x74\x93\x9d\xae\x00\x2f\x8e\xa8\x03\
+\x13\xb5\x2c\xf6\x61\x12\x0c\x98\xec\x01\xee\xf6\x97\xc1\x3d\x0f\
+\xa1\x34\x45\x40\xe5\x88\x87\x85\x19\x5e\x2f\x9d\x81\x2b\x16\x64\
+\x64\xcc\xef\xe4\x7b\x29\x92\x08\x70\x9e\xed\xa5\x7d\xee\x1c\x59\
+\x00\x25\xf0\x2a\xa3\x55\x8e\x5c\x97\x7f\x5e\x91\xa1\x90\x01\x55\
+\x44\x44\x0a\x38\x2d\xce\xd3\xac\x8c\xd2\x6a\xca\xad\x24\xde\x42\
+\xfa\x55\x41\x5b\x4e\xc5\x85\x84\xac\x9e\x2a\x23\x67\xc5\x3a\x3e\
+\x94\xd7\xb1\xc6\x4a\x96\xac\xa5\x0a\x85\xd5\xeb\xc9\x26\x3c\x5c\
+\x73\xc2\xb9\x55\x95\x39\xe5\x13\x1d\x30\x3f\x65\x13\xc5\x26\x4a\
+\x37\x74\x6e\x8f\xf3\x30\xcb\xdc\x02\x03\xe7\x06\x14\x04\x8c\xc4\
+\x6a\xea\xb3\x02\xaf\x2c\xc4\x91\x68\xd9\x07\xac\xf2\x4b\x99\xc7\
+\x7b\xc5\x32\xb4\xae\xba\x96\x6c\x78\x21\x82\x81\xc8\x31\xfe\x08\
+\x3b\x22\xe8\x70\xb0\x63\x00\x1d\x4b\x97\x25\x84\x7f\xc3\xa3\xea\
+\x95\xdd\x78\x3c\x26\xf0\xa7\x3c\x46\x40\xcd\x79\xc2\x25\x8e\x27\
+\x44\xcc\x5c\x14\x11\xc2\xf5\xc2\x61\x20\x81\x07\x25\x69\x18\xfb\
+\x54\x3f\xa2\x0c\x89\xc1\x5f\xa0\xb7\x88\x23\x7c\x1c\x19\x2a\x41\
+\xae\x24\x63\x17\x6f\x2f\x0f\xc8\xde\xc7\xa1\x6d\x0f\x68\x14\xe1\
+\x0b\x00\xc3\x4e\xbc\x4f\x80\xe1\x48\x90\xc4\xca\xb6\x10\x5a\x18\
+\x3b\xe4\x3e\x83\xa6\x50\x51\x1e\xe2\x33\xcd\x40\x8b\x90\x28\x3a\
+\x80\x6e\xe5\x81\xf8\x8e\xb9\xef\xe3\x40\xb0\x18\x16\x8f\xd8\x20\
+\xe2\xf3\x90\x69\xcd\x1b\x1f\xec\xad\xbd\x61\x25\xca\x39\x89\x94\
+\x2c\x54\x1f\x43\x97\x4d\x0a\xe4\x5b\xcc\xaf\xeb\x4e\x8e\xfb\xf7\
+\x4b\x88\x86\x05\xf8\xca\x8d\x99\x3a\x6f\x1d\x16\x80\x38\x16\x71\
+\x77\x32\xb4\xac\xe7\x3c\x74\x29\x08\xed\x9a\x2a\x6f\x35\xb0\xcf\
+\xc2\x6d\xa7\x26\x75\x6d\x68\x05\x46\x5e\x47\xb6\x66\x2c\xf8\x3f\
+\x11\x32\xf2\x62\x48\x63\xc5\x62\xf5\x43\xd5\x6e\x2d\x82\xda\x2e\
+\x82\x6d\x84\xc7\x1f\xc0\x89\x2e\x1b\xd2\xc4\x4f\x79\x9a\x86\x6e\
+\xc6\x49\x4f\x87\xd8\xaf\x92\x83\xba\xa4\xfe\xf3\xc2\xea\x62\x26\
+\xb2\xa0\x2b\xf2\x22\xf7\x84\x28\x49\x46\x15\x23\x11\x95\x14\x5d\
+\x36\xee\x58\x15\x55\xb4\xef\xdb\x47\xa9\x7f\xc7\x94\xe3\xb1\x46\
+\x88\xac\xb4\x27\xdd\xb6\x31\xef\x99\x37\x90\xef\x5e\xdb\x13\xb0\
+\x8b\xf2\x84\xe4\xff\xa0\x0e\xf6\x4d\xfb\xed\xcb\xbc\x8f\x50\xc7\
+\x00\xfb\xf8\xd0\xd0\xf6\x3e\x85\xd5\xf5\x98\x73\x57\x69\x75\xb1\
+\x03\xac\xee\xed\xd1\xc3\xed\x2e\x1f\x82\x05\x33\xa6\x37\x09\xf5\
+\x84\x68\x18\x91\x0a\x71\x3b\xd0\xff\xc8\x58\x84\xff\x56\x64\xc0\
+\xac\x11\x66\xee\xc3\x0d\xd9\x62\xea\x1a\x50\xa8\x52\x5c\x1e\xb0\
+\x30\xae\xf0\x86\x6b\xc0\xa9\x67\xd3\x10\xf6\x73\x35\x69\xdb\x64\
+\xa3\xce\x43\x45\x23\x12\xe0\xec\x6c\x6d\xbb\x8c\x20\x5e\x5b\x98\
+\xbb\x6d\x5b\xb1\x6b\x6b\x4a\xff\x4c\xf6\x23\x0a\xaf\x13\x0c\xb6\
+\x58\x6a\xb6\x8c\x7f\x9b\xd3\x00\x60\x67\xc5\x26\xb4\x80\x31\x06\
+\x5b\xe3\x24\x03\x6e\xc7\x43\x93\x39\x9b\x5a\x93\x87\xf4\xe4\x96\
+\x8d\x86\x3a\xa4\x1a\xd3\x50\xe9\x40\x2e\x14\xe1\x4f\x38\x83\x4b\
+\x06\xbe\x70\xee\x62\xf2\x62\xc0\xc0\x83\xd4\xb1\xd4\x98\x2b\x0f\
+\x02\xaa\x1f\x7f\x40\x9f\x6d\x0b\xac\xf5\xa3\x41\x61\x5b\xac\x15\
+\x2b\x2a\x53\x88\xdf\x28\x7b\x6d\xd6\x8d\x6b\xe6\xc4\xad\xe0\xd7\
+\x85\x5c\xf0\x99\x4e\x48\x3f\xc2\x10\x81\xf4\xd9\x08\x1c\x8d\xa7\
+\x70\xe8\xfa\x11\x0f\xab\xa4\x31\x86\xf6\xd5\xee\x5c\x40\x27\x3c\
+\x48\x82\x3e\xff\x87\x15\xd7\x08\x4d\x05\xef\xdf\x64\x7d\xcf\x0e\
+\xe7\xf2\xbf\xb3\x5e\x9b\xfb\xed\x9c\xbd\x7c\xf9\xf2\xa8\x73\x3a\
+\x97\x0c\xce\x16\x59\x9c\x76\x4d\x49\x5c\xa6\x33\xbe\x7a\x2c\x24\
+\x6c\x92\xe6\x74\x62\xbd\x23\x31\x6a\x82\xcb\x3f\xaf\xf6\x51\x77\
+\x4c\x09\x95\xcc\xa4\x5b\x30\x45\x0a\x7a\x81\x87\x24\x12\xfe\x54\
+\x8f\x3c\x20\x3a\x5f\x74\x4f\xfd\x84\xcd\xb2\x46\x86\x2e\xc4\x67\
+\xe1\x08\x54\x8b\x18\x12\x46\x1d\xfd\x1f\x7b\xd3\x57\x49\x6c\xb6\
+\x1d\xa6\xf8\x38\x24\x87\x1a\x56\xa8\x47\x8c\x3d\xe1\x33\x8b\x8a\
+\x9e\x53\x47\x4c\x2e\xa1\xe0\x96\x82\xfc\x49\x8a\xa4\x49\x5f\x3f\
+\x78\xb8\x1e\xd1\x48\x57\x67\x71\x4e\xb7\x92\xc5\x01\x42\x59\x82\
+\xa7\x12\xb0\x53\x50\x55\x71\xe6\x71\x23\x15\xf5\x40\x05\x75\x51\
+\x4a\x40\x3e\x81\x82\xba\x02\xb0\x17\x3a\x25\x2a\x4b\x4a\x0a\x51\
+\x72\x6c\xdf\x52\x35\xc5\xc3\xba\x6a\xea\xf8\x70\xb9\x9e\x3a\xdc\
+\x9e\x82\xba\xf1\x58\x55\x2e\x78\x58\xc8\x3e\x83\xa1\x5f\x90\xee\
+\xdd\x96\x9f\x61\xd1\x33\x8c\xb2\x93\xe3\x2a\x39\x7e\xb5\xbe\x1c\
+\xd7\xf0\x98\x4f\x1f\x37\xea\x4a\x23\xad\xa1\x14\x81\x36\x47\x31\
+\xcc\x43\x60\xb1\x4c\x66\xe1\xd7\x5f\x10\xf3\x6a\x4b\x88\x86\x12\
+\x37\x81\xbc\xd3\x2e\x26\x58\xb1\x44\x6a\xaf\x1a\xdf\x74\x39\xa8\
+\x77\x3a\x25\x3a\x93\x2d\xf7\xc9\x00\xc8\x15\xd0\x3b\xdb\x8d\x06\
+\x32\x8e\xc1\x36\xc6\xdc\x9f\x12\xe6\x72\x5d\xc6\xd8\x84\xc7\xad\
+\xcb\xa2\xe9\x12\x34\xce\x5b\x74\xc1\x47\x08\xfc\x93\x86\xbd\x93\
+\x8b\x6a\xb9\x38\xdd\x88\x5c\xbc\x7e\xb8\x5c\x60\xad\x2e\x95\x87\
+\xa1\x64\xcc\xa1\xae\x61\x7d\xd8\x71\xf4\x0d\x91\xfd\xb1\x24\xc2\
+\x43\x87\xbb\xe0\xb8\xcc\x84\x46\x33\xd7\x98\x4b\x74\x0c\xdf\xb1\
+\x31\x78\x8e\xfb\x46\xc2\x1c\x8a\x65\xba\x3b\xac\xec\x8d\x3d\x50\
+\x91\x07\x07\x0d\x1c\xb7\xc5\x9c\xfe\x5f\x40\x89\xa4\xe7\x33\xb6\
+\xc2\xde\x48\x8a\x0c\xe0\x8e\xbf\xab\xf8\xfb\x6c\x13\xfc\xdd\x88\
+\xbb\x4b\x5a\x9f\x02\x73\xa7\x4c\x9c\xab\x33\x0f\xa9\xc3\x32\xad\
+\x6f\xe2\x24\x13\x89\x1c\xbb\x3a\x92\xd1\x03\x36\xc1\xc9\xe6\xe8\
+\x0e\x39\xbe\x9c\xa1\x05\x40\x53\x88\x24\x60\xf1\x82\xda\xd1\x46\
+\x5c\x1b\x80\xb6\xe3\xed\x6a\xde\xee\x9c\x6c\x44\x79\x77\x1a\x54\
+\x92\xaa\xf8\x1b\xdd\x91\x19\xfb\x16\x93\xc9\x30\x39\x36\x98\xaa\
+\x2d\x60\xe1\xe3\x21\x0e\x7c\xc3\x1e\x77\x20\xf7\x9c\x8d\xc1\x9b\
+\xc1\x43\x69\x5c\x84\x9b\x60\xf7\x6b\x83\x42\x19\x47\xea\x0b\x90\
+\xc3\xc7\x46\xa4\x1e\xff\x5b\xfa\xec\x44\x60\x81\x08\x74\x36\x22\
+\x02\xaf\x1e\x57\x02\xb2\xb4\xb6\xa9\xa5\x22\xef\x23\x62\xda\xc5\
+\x57\x34\x74\xa9\x74\xad\x2f\x8f\x23\x08\xc6\xb2\xf0\x56\x08\xae\
+\x3b\x78\x3f\x36\x79\x85\x8d\x26\x29\xe6\xd1\x7b\x86\x99\x30\x6c\
+\xc5\xa3\x4f\xae\x70\x92\x5a\x59\xcc\x1a\xc2\x81\xe7\x50\x66\x28\
+\x0e\x81\xf4\x06\x0f\x1d\x03\xe3\x62\xb6\x25\x07\x7d\xe5\x62\x16\
+\x61\x27\x07\x0b\xe4\xe0\x68\x33\xa6\xe0\xf0\x71\x05\xc1\xa3\xfa\
+\xe0\xc9\x4c\xfb\xdb\xd3\x72\x69\x38\x1b\x83\xa0\xf8\xcc\x38\xf1\
+\x9b\x60\x66\x7b\x72\x52\x63\x41\x06\x22\x41\xae\xe6\x4c\xbb\x37\
+\x0d\x61\xd6\x60\x66\xa3\x0c\x2e\x27\xc3\x0f\xd4\x9e\xc2\xd9\xb1\
+\x74\x25\x4b\xd7\x48\xbd\xd6\x61\xe9\xce\xe3\xb2\xf4\x18\x4b\x07\
+\xb3\x9a\x84\xd1\xcd\x10\x68\x62\xfe\x0f\x0f\xf0\x61\xae\xc6\xd6\
+\x32\x52\xa6\x07\x6f\xc2\x65\xd2\xb8\xf2\x8e\xaf\x4f\xb7\x6a\xee\
+\x33\xd5\x50\xed\xfb\x08\x89\x6e\x06\x59\x78\x82\xad\xa9\x20\xfc\
+\xae\x51\xc8\xa1\xad\x41\x37\x04\x57\x43\x06\x0c\x09\xae\x2d\xf8\
+\xaf\x06\xee\xf7\x28\x06\xf3\x9d\x73\x73\xe5\xc6\xd5\xb8\x66\x30\
+\x4a\x9f\x53\x00\xc5\x3d\xaf\xbe\x64\xf0\xf5\xfd\xe3\x5d\x32\x48\
+\x4b\x58\x30\x9a\x3b\xa5\x4a\x6e\x63\xb9\xaf\x11\xd4\x54\x15\x85\
+\x4f\x96\x8b\xf7\xe2\x28\x80\xa2\xf0\x09\x72\x83\xc5\x05\x4a\xb0\
+\xfa\x41\x2e\xac\x79\x92\xcf\xb7\xfc\xd2\xe4\xd8\x1f\xd6\x37\x22\
+\xbb\x6c\x20\xbd\xac\x5e\x3b\xc4\x45\xcc\x49\x1a\x26\x88\x6b\xe8\
+\x06\x83\x84\x5e\x7e\x46\xfe\x9d\x6e\x28\xb3\xca\x92\x2b\x48\xb7\
+\x35\x2f\x21\xf5\xbf\x3c\xbe\x7e\xc8\x95\x4e\xbf\xf5\xeb\x48\xe9\
+\x8a\xe6\x54\xd3\xaa\x35\x2d\x59\x55\x35\x3b\x3d\x9b\x8b\x49\x2b\
+\xaa\x5a\x4f\x7e\x31\x49\x1f\x4b\x94\x25\xfb\xd1\xd7\xcd\x73\x19\
+\xdf\x32\xf6\x30\x1a\x22\x65\x7d\x77\xa7\xb0\x08\x06\x24\xed\xfd\
+\xa6\xde\xbc\xf9\x30\x9b\xb1\xdb\xd6\x8d\xb5\x95\x0e\x86\xc8\x1f\
+\x20\xa2\x59\xac\x74\x16\x96\xbf\x4f\x96\x57\xbf\x8f\x1a\x95\xbf\
+\x61\x98\xa6\x51\x73\xeb\xb4\xf2\x12\x58\x93\x03\xa9\x6b\x5f\x03\
+\x43\xb5\xb5\xf8\xde\xd7\xb7\x7f\xd5\x2a\xbe\x1f\xed\xae\x5a\x55\
+\x40\xdd\x5d\xb5\x6a\x84\xd5\x53\x47\xf6\xaf\x9b\x79\xf8\x2b\x3c\
+\xde\x55\x65\xad\xfe\x33\xb9\x37\x0b\xc2\x7d\x6b\x4a\x0e\xb7\x5a\
+\xc8\x6f\x9b\xdf\x9f\xd5\x4b\xc3\x7c\xb1\xf6\xe7\xd0\x8b\xc7\x92\
+\xb8\x04\x04\x4d\x9a\x22\x3b\x6c\x49\xed\x25\xb0\xef\x43\x49\xce\
+\xd1\xf1\xfb\x54\x96\x37\xf6\xc0\x19\xd8\xc0\x17\x68\x04\x23\x89\
+\xc7\x20\xfe\x45\x83\xe8\x3f\xe9\x59\x9f\x27\x54\xa1\xbf\xd3\xb1\
+\x41\xeb\xe2\xed\xe7\x46\x68\x3c\xb5\x6a\x9a\x4b\x78\x3f\x5e\xd2\
+\x71\xb9\x4f\x5a\xe7\x94\x34\x4a\x36\x56\x22\xe3\x7d\x3c\xce\xc5\
+\xf4\xe1\x81\xb1\x87\x12\xae\x4d\x83\x90\x77\x04\x2f\xc1\x52\xf4\
+\x85\xc8\xc0\xa7\xce\xdd\xbe\x76\x9a\x06\x4c\x61\x2c\x2f\x19\x75\
+\xe9\x80\xfb\x1c\x80\xd3\x11\xc5\x12\x93\x7d\x7d\x00\x43\x31\xb9\
+\x14\xba\x1b\x49\xbd\xcf\xf8\x37\x87\xad\xb5\x6b\xfa\x4c\x18\x40\
+\x6f\xa0\x8a\x4c\x32\xb6\x00\x79\x00\x64\xed\x29\x99\x80\x46\xd0\
+\x3f\x37\xa9\x84\xfa\xf7\xa3\x4f\x98\x48\x7d\x67\x16\xf2\x3c\x35\
+\xd0\xf3\x4d\x57\xcc\x82\x85\xf5\xd2\x15\xbf\x5e\xbc\x7d\xfc\x74\
+\x45\x26\xa3\xdf\x4b\xba\x62\xee\x8e\xf4\x37\x9f\xae\xa8\xa1\x6e\
+\x57\xe4\x80\x1f\x78\x91\x8d\x82\xf2\x8c\xc9\x8b\xe3\x4b\x73\x34\
+\xab\xea\xce\xda\x46\x0e\x16\xda\xb4\x0a\x32\xbd\x46\x61\x2b\x59\
+\x58\xe1\x50\x0b\x6c\xa7\xcb\xf4\x5e\xe4\x73\x4e\x69\xe9\xc3\x64\
+\x9c\x16\xe9\xae\xaa\x54\x53\x96\x65\xfa\x62\xe7\x98\xcb\x31\x95\
+\xf5\x56\x8d\xcc\xd2\x7c\x52\xc9\xe6\x93\x8e\x4a\xf9\xa4\x34\x95\
+\x74\x52\x4a\x25\xcd\x65\x91\x8a\xa8\xcc\xe5\x8e\x32\x22\xe5\x28\
+\x99\x23\xa3\x55\x4e\x69\x54\x6d\x95\xcd\x79\xeb\xac\x45\x8c\x9a\
+\x38\x6f\x75\x3a\xad\x36\x8e\x8c\xf8\x24\xa0\xd1\x30\x09\xf5\xb1\
+\xaa\xde\xdf\xd7\xfa\xf9\x4a\x8a\xe0\x33\x0f\x58\x5f\x24\xd2\x01\
+\x03\x5e\x18\x85\x9f\x61\x4b\x62\x25\x02\x03\x31\xd6\x98\xe4\x5b\
+\x0c\x96\xb9\x4f\xb5\xe5\xca\x29\xd9\xd7\xd9\x70\x3f\x26\x8a\x81\
+\xcb\xd3\xb3\x5f\x66\x83\xdd\xb0\x0d\x7b\x86\x54\xd4\x85\x25\xc3\
+\x0c\x6d\x9c\xc0\x7c\xaa\xed\xc0\x43\xc2\xe9\x0e\x4d\x80\x22\xdc\
+\xe5\x88\x14\x6a\x3b\x95\xc8\x94\x31\x5e\x84\x15\xce\x66\x30\x8f\
+\x9b\xa3\x65\xaf\x24\x56\xd3\x67\xd6\xb9\x15\x54\x52\x1d\x5f\x8d\
+\x4b\xd6\xbb\x1d\x64\x6c\xe4\xbe\x00\x99\x59\x6f\x73\x64\xe6\x1b\
+\xf4\x07\x04\x25\x8b\xb5\x0c\xc4\x5a\x5a\x1c\x11\x86\xe6\x00\x22\
+\x3e\x77\xdb\x09\xef\xed\xfd\x1f\x9d\xcd\x9d\x8f\
+\x00\x00\x09\xfb\
+\x00\
+\x00\x57\x7d\x78\x9c\xed\x5c\x5b\x6f\xdb\x3a\x12\x7e\xcf\xaf\x20\
+\xfc\xb2\x5d\xa0\x27\xbe\xe4\xda\xc0\xf1\x41\xdb\xf4\x12\xa0\x3d\
+\x9b\xc2\x49\xbb\x67\x5f\x02\x5a\xa2\x6d\x6e\x24\x51\x4b\x52\xb1\
+\x5d\xec\x8f\xdf\xe1\x45\xd6\xd5\x8e\x6d\x39\x72\xb6\xc7\x45\x80\
+\x4a\x24\x3d\x33\x1c\xce\x7c\x43\x0e\x49\x75\x7f\x9f\xfa\x1e\x7a\
+\x24\x5c\x50\x16\x5c\x36\xda\x87\xad\x06\x22\x81\xc3\x5c\x1a\x8c\
+\x2e\x1b\x77\xb7\x1f\x7f\x3b\x6f\xfc\xde\x3b\xe8\x46\x34\x69\x74\
+\x0c\x8d\x7a\x07\xa8\xeb\x78\x58\x88\xde\xa7\x88\x5e\x5c\x5c\x51\
+\xec\xb1\x11\xfc\xef\x8d\xfa\x44\x4a\xf8\xb1\xb8\xe2\x78\x28\xbb\
+\x4d\xd3\x08\x5a\x4f\xa8\x3b\x22\x12\xe9\xf7\xcb\xc6\xb7\x1f\xfa\
+\xb5\x81\x02\xec\x93\xcb\xc6\x52\x22\x8a\x19\xea\x86\x9c\x85\x84\
+\xcb\x99\xfd\xc5\x88\x30\x9f\x48\x3e\xd3\x95\xa8\xcb\x89\x23\xf5\
+\x13\xea\x4e\x7b\xad\x6e\x73\x6a\x5f\x66\xea\x65\x66\x5f\x40\x04\
+\x39\xee\x9d\xb5\xcf\xbb\x4d\xf3\x68\x8a\xc7\x84\x8e\xc6\xb2\x77\
+\xde\x82\x72\xfb\xac\x69\x36\x63\xa2\xdd\x66\xcc\xbc\x4c\x92\x09\
+\x0d\x5c\x36\xb9\xa5\xd2\x23\x56\x18\x21\x39\x08\xdf\xfb\x44\x02\
+\xc2\xb1\x87\x84\xed\x4c\xb7\x69\x2b\x8a\x24\x3d\x3c\x63\x51\xa2\
+\x9c\xef\xef\xd8\xf4\x8b\x2e\xb2\x14\x73\x2c\x45\x88\x1d\x20\xd4\
+\xb0\x1d\x08\x22\x7f\x40\x78\xef\xb4\xdb\xb4\x4f\x46\xfc\x34\x87\
+\x02\x09\x1f\xf3\x11\x0d\x72\x14\xde\x2c\xa5\x40\x25\xf1\x13\x4d\
+\xa6\x07\xf3\x13\x67\x51\x08\x32\xc7\xc3\x39\x8a\xdf\x4d\xf3\x02\
+\x73\x99\x28\xab\x44\x5f\x7a\xd0\x51\xbf\x44\x6b\x45\xa1\x96\xea\
+\xce\x72\x03\xc3\x95\xd4\xc1\x9e\x29\xbd\xef\x24\x8c\x93\x1e\x95\
+\x10\xfa\x5c\x20\x34\x66\x9c\xfe\x64\x81\x9c\x93\x6a\xbf\x99\xd3\
+\xca\x53\x2b\x28\x49\x9b\xf8\x0d\x27\xc3\xf7\x63\xe2\x3c\xa4\x95\
+\xa5\x2a\x42\xa8\x70\x54\xc5\x80\x4d\xef\xdb\x9d\x14\xd9\x12\xed\
+\x31\xe6\xdd\xd2\x30\xd3\x66\xae\xc4\xeb\x21\x92\x63\x2a\x10\xfc\
+\x69\x7a\xc4\x7d\x0d\x05\xc4\x2a\x75\xc2\xf8\xc3\x00\xfc\x7b\x0c\
+\x4f\xc1\xdf\x24\xc2\x61\x48\x30\x3f\x44\x77\x82\x0c\x23\xb0\x54\
+\x1a\x38\x04\x61\xcf\x43\x6c\x98\xfa\x95\x62\x28\x10\xe6\xaa\x4a\
+\x30\x44\x03\x5d\xf7\x96\x6b\x32\x96\xe0\x61\x6e\x9c\xca\x07\xab\
+\xbc\x3f\x64\x2a\xcb\x3b\xf3\x99\xba\x05\xc9\x37\xe7\xa3\x74\xfc\
+\x21\x50\x98\x81\x84\x74\xc1\x2b\x2f\x1b\xad\x1c\x5f\xc7\xd2\x1e\
+\x03\x63\xcd\xf7\x47\xc2\xd6\xa9\xc2\xf7\x06\xcb\xf1\xd3\x6c\xbf\
+\x32\xb7\x19\xe3\xe6\x8a\xdc\x34\x94\x81\x99\xa5\xec\xb0\x99\x35\
+\xeb\xa6\xb1\xeb\xb9\xd1\x67\xaa\xab\xba\xc0\xea\xf6\xff\xed\x0b\
+\x1e\x10\x2f\xa6\xe3\xa9\x97\xac\xff\xac\x63\x18\xc6\x26\x68\x20\
+\x09\x1f\x62\x30\x59\x9f\xb9\x64\x73\xc3\xc0\x1e\x1d\x05\x3e\x09\
+\x0a\xcc\x40\xad\xdf\xe4\xc5\xc5\x5b\x55\xff\x85\x60\x15\x14\xff\
+\x9b\x2a\x18\xca\xe4\xed\xfb\x7b\xa2\xa4\x01\x21\xd2\x63\xb1\xe9\
+\xa0\x15\x95\xa9\x20\x9f\xf0\xc2\x28\xf4\x75\xf1\xfd\xf1\x52\x3d\
+\x42\x6b\x10\x0e\x4b\x88\xde\xb9\x1e\x12\x80\x7b\xdd\xc5\xcf\x73\
+\x8a\xdd\xa6\x2e\x5c\x5b\x89\x82\xfe\x24\x9f\x61\x44\x16\x5b\xb9\
+\x6a\x91\x29\x89\x23\xf2\x71\x2b\x13\x90\xe7\xb5\x36\x18\x77\x5a\
+\x99\xb8\x9c\x88\x95\x27\xb8\x40\xd7\x46\x75\x6b\xe8\x7a\x11\x70\
+\x33\x7f\xc0\x4a\x81\x5b\x55\x28\xe0\x5e\x3e\x0c\x4b\x71\xfb\xd6\
+\x82\xb6\x42\xd6\xbb\x6b\x6d\xd0\x0a\x68\x27\x63\x0a\x28\x9b\x40\
+\x31\x94\x47\x1e\x41\x13\x0a\x18\xad\x20\xf1\x02\xdd\x02\xd5\x01\
+\xe6\xe6\x17\xba\x3c\xf4\xb0\x45\x71\xf3\x9b\x78\xfe\xa1\xe8\x61\
+\x78\x0b\x31\xc7\x92\x68\x54\x87\x1f\xbe\x56\x3c\x80\xa4\xc4\xe2\
+\x21\x4b\x27\x12\x44\x73\xfe\xc8\x09\x79\xff\xf6\x0a\xdd\x42\x8b\
+\x47\x4a\x26\x48\xcc\x04\x68\x0c\x0d\x19\xd7\x5c\xa8\x14\xaa\x2d\
+\x37\xfe\x88\x1d\x65\x67\xb5\xa0\xf4\x1d\xfd\xaa\xfd\xfe\x65\x22\
+\x73\xc1\xae\x56\x01\xb8\xc4\x1e\xcc\xe8\x94\xe9\x71\x11\xbb\x66\
+\x9e\x5f\x35\x01\xec\x68\x57\x91\x60\xc7\xc1\xe9\xfe\xec\x59\xa6\
+\x67\x27\xdb\x9d\x9d\x39\x2c\x9c\xa5\xbc\x6e\x40\xd0\x03\x09\x61\
+\x6a\xe6\x70\x26\xa0\x19\xf3\x7d\x1c\x40\x33\x06\xae\xc8\x27\x14\
+\x7c\xd2\x16\x09\xd3\x1e\x7b\x13\x3c\x13\x60\xc0\x98\xab\x88\x88\
+\x02\xf6\xdb\x9c\xe2\x73\xcc\xc9\x3e\x79\x6c\x00\x93\xf4\x2d\xf0\
+\xb0\x1a\xc8\xb1\x19\x80\xfe\x7a\x92\x47\x40\x58\x3f\x3e\x27\x80\
+\xa8\x4e\xf8\x2f\x18\x42\x76\xed\x3f\xed\xf3\x67\x71\xa0\xa3\xcd\
+\x1d\xe8\x0f\xc6\x7d\x88\x39\xb3\xd7\x08\x14\x09\x21\x47\x8d\x20\
+\x94\x23\x36\xf8\x37\x2c\xd6\x85\x59\xeb\x40\x21\x25\x02\x29\xe1\
+\x04\xf1\xa0\x9c\xb8\x87\x28\x76\x3d\x16\xaa\xf8\x54\x58\x1f\x0d\
+\x30\x78\x96\xa5\x32\x77\xc4\xf8\xd7\xe0\x57\x10\xf1\xb0\xfb\x2c\
+\x8b\x9c\xbe\x66\x92\x15\x20\xd3\xb9\x5a\x62\xa9\xe9\xea\x3b\x10\
+\xe2\x1f\x46\x86\xbd\x4f\x94\xfb\xc4\x1a\x4b\xfe\xd2\x25\xcf\x13\
+\x6b\xfb\xc5\x4b\x1e\x32\xc4\x91\x67\x16\xc2\xca\xe2\x61\x96\x17\
+\xac\x0e\xbe\x5b\x5f\x71\x9c\xed\x57\x1c\x8b\x75\x5d\xdf\x8a\x63\
+\xb9\x35\xad\xe1\xff\xae\x31\xaf\x1f\x37\x2f\xd5\xef\xab\xcd\x66\
+\xff\x60\xe5\xce\x52\xcf\x5c\xfa\x9f\x7f\xa2\x57\xb7\x2c\xfc\xfb\
+\x0e\x25\xf8\x17\x7a\xf5\x91\x83\xbb\xed\x50\x86\x3f\x41\x86\x3e\
+\x75\x49\x25\x11\x76\x0d\xff\xed\xa3\x6a\xf8\x7f\xbe\x21\xfc\x5f\
+\xab\xb5\x75\x00\x13\x6f\x70\x32\x87\xaa\x8d\x18\xe4\x91\x47\xe2\
+\xed\x2c\x02\xec\xf1\x7f\xb1\xa6\xb7\x85\xff\xfd\x90\x06\x65\xf0\
+\x2f\xa0\xfc\xe9\x89\xb4\x8f\xa7\xd4\x8f\xfc\x3e\xc8\xbc\xaa\x5e\
+\x4e\x97\xeb\xa5\x7d\x7a\x76\x76\xd6\x69\x9f\x54\xd1\xce\xba\x69\
+\x31\x82\xcc\x96\x94\xda\x92\x70\xc1\xf4\x61\xfa\xaf\x33\x59\x34\
+\x76\x08\x87\x31\xee\xd2\x00\x4b\xa2\x26\xf7\x84\x6b\xab\x13\xe8\
+\x95\x4a\x4f\x91\xe9\x21\x3a\x42\x97\xa8\x75\xd8\x6a\xb5\x4b\x71\
+\x67\x35\x19\x1f\xb1\x17\xe5\x95\x58\xba\xeb\xb6\x16\xd5\x35\xc2\
+\xf3\xdc\xeb\x5f\x6a\x78\xde\x35\x2e\x77\x2a\x4e\xcb\x37\xc5\xe5\
+\x2b\xea\x93\x40\x68\x8b\x7b\x29\xc8\xfc\xc4\xa4\x70\x8f\xcd\xb5\
+\x60\xf3\xf2\x2c\xa1\xc5\xe6\x72\x48\x39\xdf\x1c\x52\x96\x00\x55\
+\xa7\x16\xa0\x72\xa9\x7f\xb3\xc7\xaa\x27\xe6\x90\x27\xd5\xc0\x6a\
+\xf9\xda\x7b\x31\x56\xdd\x32\x0f\xc2\x63\xe0\xec\x30\x6d\xb0\x1c\
+\x66\xf7\xd0\xb4\x15\x68\xba\x62\xd1\xc0\x23\x8b\x00\xca\xd5\xb5\
+\x16\xa6\xfe\x02\x13\xc8\x64\x5f\x55\x83\xa3\xda\xaa\x74\xd1\x60\
+\x86\x86\x51\xe0\x98\xa9\xa2\x1c\x63\xa9\x77\x3b\x31\x92\xb1\x8b\
+\x1c\x1e\x7c\x57\xad\x55\x2e\x58\x8e\x91\x4b\x87\x43\xc2\x09\x94\
+\x0b\x04\x1e\xc8\x26\x26\x97\x6c\x08\xc6\xd9\x62\xc9\x09\x56\xc9\
+\x62\x2c\x90\x00\xc1\x2a\x24\x8b\x45\x34\x1c\xd2\x69\x69\x87\x9a\
+\x9b\x18\x7c\x30\x02\x73\x90\x24\xaf\x22\x63\x09\x3d\x98\x1c\xb7\
+\x5b\xe9\x7f\xdd\xa6\xad\xd9\x4a\xf8\x49\xb8\x9c\x6c\x89\xcb\x1a\
+\xe1\x48\x26\x90\xb7\x8f\x45\xa5\xf3\xe6\x35\x26\xce\xeb\x1c\x61\
+\xab\xb0\xc7\xf3\x63\x4c\x82\x65\x87\xd8\xcc\x71\x34\xed\x75\x8e\
+\x76\x39\x74\xa3\xf6\x3e\x43\x4e\x7d\x2a\xe9\x23\x11\xf1\x76\x8d\
+\x5a\x32\x9a\x9f\xcc\xb7\x87\x26\x8a\x36\x7e\xc4\x14\x22\xa9\x57\
+\xc5\x45\x17\x47\xd9\x3b\x61\x05\xba\x49\x04\xca\xb2\xad\xe7\x70\
+\x84\x20\x4a\x8a\x44\x88\x5f\xd3\x03\xb2\x95\x19\x5a\xa9\x76\x1b\
+\x9c\x5d\x4d\x56\x51\xab\x9d\x5e\xed\x07\x38\x0c\x8b\xbb\x75\x95\
+\xcf\xab\x6e\xef\xb4\x6a\xc5\xcc\x65\xa7\xb5\xe1\xb4\xf3\x3d\xc4\
+\x58\xc9\x31\x0d\xd4\x79\x81\xdd\x4d\x3d\x97\x2f\xc8\xf6\x53\xcf\
+\x9a\x76\xac\x2a\x9c\x9e\x51\xc9\xc0\xb9\x31\xa9\x3d\x50\xb0\x27\
+\x3a\xa4\x30\xe4\x0f\x64\x56\x0b\xa8\x02\x43\x27\x16\xe0\xa5\xe2\
+\x69\xb5\x4d\x1a\x31\xa6\x8a\xd9\xae\xf6\x88\x1c\xc9\x4b\x13\x67\
+\xf5\x70\xc7\x5e\xa5\xae\xef\x7a\x2e\x77\x5c\x11\xe0\xdb\x1b\x02\
+\xbc\x0a\x7d\xbb\xc5\xf6\xe5\xb3\xcd\x3d\xb6\xd7\x84\xed\xa7\xd5\
+\xb0\x5d\x58\x3b\xda\x02\xa6\x3b\x11\x87\xe5\xba\xbc\x0e\x5c\x92\
+\x5f\x47\xdb\x24\x68\xbb\x96\x74\x28\xf4\x46\xf5\x6a\x1f\x2b\x4c\
+\xe9\x3e\x56\x24\x05\xbb\x8d\x15\x15\x53\xd0\x9d\x4d\x8f\xb1\xbd\
+\xf5\xe4\x6e\x43\xc5\x72\x8c\xda\x87\x8a\x9a\x42\xc5\x13\x7b\x18\
+\x4f\x85\x0a\x6c\xcc\xa8\x96\x48\x51\xcf\xc6\x19\xf4\x46\x43\xca\
+\x3e\x50\xec\x03\xc5\x4b\x0a\x14\x99\x55\xc1\xf6\x12\xc4\x15\xfc\
+\xff\x7a\x98\xcd\x0a\xeb\xe5\x87\xbd\xcd\x96\x1c\xdd\x1f\xb3\x49\
+\xa0\xf3\xae\xe4\x11\x20\x02\xba\xa2\x77\x78\x44\x79\x96\x6e\xd9\
+\x80\xac\xbe\x0c\x02\x96\xf1\xe5\xf5\x94\x48\xff\xcf\x17\x64\x94\
+\x16\x55\x5f\xde\xa9\x6e\xbc\x4c\x64\xda\xb5\x7f\x9c\x3e\x8b\x7b\
+\x6c\x7a\x31\x3a\x75\x63\x5e\xa4\xdd\xc2\x5c\x28\x01\x0f\xa8\xed\
+\xfa\xfc\x2f\x6d\x36\xb9\xca\xee\x4f\xc6\x5d\x98\x1f\x74\x9b\xf6\
+\xa1\x4a\x71\xde\xc2\xcc\x97\x52\xee\x8f\xd6\x6b\x7e\xbc\x5e\xf3\
+\x93\x6c\xf3\x6d\xee\xa3\xcc\x73\x33\xab\xed\xa3\x98\x04\x6f\xa4\
+\xb7\xe6\x51\xfc\x95\x97\xad\x7f\x04\x24\x49\x18\x55\x3f\xcd\xd3\
+\xaa\xb6\x94\x6a\x57\xdb\x57\x89\x35\xa5\xd4\xad\x7f\xf2\x9c\x4b\
+\xab\x05\x78\xf6\x85\x06\xe4\x83\x4b\x65\x01\xcf\x3c\xa8\x20\x50\
+\xf1\xc4\x91\xc4\x95\x4f\x70\xd8\x5b\x2a\xa9\xde\xea\x5b\xe8\xce\
+\x0a\x36\xb3\x58\x0f\x1b\xaa\xbc\x16\x24\x4d\xf7\x4c\x77\xda\x8c\
+\xf0\xaf\x88\xa9\xd5\x3d\x71\x8d\xdb\xaa\x65\x8e\xb8\x69\xcc\x2d\
+\x45\x2c\xb0\x49\x8f\xad\x3e\xf7\xdb\x7a\x9a\x63\x79\x67\xf6\x69\
+\x8e\x2d\xa5\x39\x60\x8c\xdf\x45\x52\x82\x1a\x8b\x99\x0e\xa8\x1b\
+\xe8\xba\x2a\x17\x9e\xcb\xd0\x4f\x93\xd6\xc0\x17\xdf\x17\x1e\x10\
+\xb5\x1d\xea\x72\xac\xd7\x3c\xea\x73\x1e\x34\xc8\xa2\xa2\xba\xe6\
+\x5e\xe1\xb8\x8b\x66\x99\x47\x0a\x55\x96\x1b\x20\x4e\xdc\xde\xf1\
+\xb1\xfa\x74\x9a\x9b\xab\x19\x71\x42\x82\x5e\xbb\x03\x33\x0d\xf3\
+\x98\xad\x1e\x78\x11\xe9\x75\x4e\xa0\x56\x3f\x65\x87\xb5\xc0\xe9\
+\x59\x71\xd6\x7a\xee\x5f\x01\x63\x33\x18\x12\x4f\x91\x0a\xf7\xbb\
+\x56\x44\x8f\x04\x3b\xbe\x5b\x4a\x79\xe4\x28\xeb\xd1\x9a\xa8\x51\
+\xc0\x0c\x8b\x18\x9d\x32\xc4\x88\xf1\xe2\xb8\x0c\x2f\xf2\x68\x51\
+\x22\x5c\x1e\x29\xd6\x3f\x79\x94\x6a\x94\x6a\x61\x63\x5b\xec\xcf\
+\xf6\x73\x7e\x97\x8d\xd3\x06\x32\xdf\xe5\xbb\x6c\xb4\xdb\x0d\x75\
+\xd4\xb3\x1b\xd2\xa9\x8f\xc3\xf8\xac\x6a\xef\x3f\x37\xfa\xfd\x23\
+\x67\xfe\x57\xea\x93\x3e\x8b\xb8\x3a\xdb\x98\x6b\xa5\x3e\xce\x18\
+\x09\xc9\x7c\xc3\x51\x68\x49\xd2\x25\x46\xca\xd4\x07\x1c\x53\x48\
+\x96\x7c\xb3\x51\x0d\xe9\x54\x92\xc0\x15\xbd\x6f\x37\x91\x18\xc7\
+\xf5\x71\xe1\x81\x51\x31\x56\xcb\x06\xa0\xd2\x34\x6b\x09\x71\x38\
+\x56\xda\xc6\x76\x31\x01\xe4\x72\x8c\x97\x4b\x92\xba\x5b\x51\x2e\
+\xc9\xbc\x72\x91\x18\x8a\xc2\xd6\x44\x79\x4a\x31\x45\xed\xd5\x23\
+\x96\xcd\x20\x94\xab\x28\xa9\xad\x49\x47\x26\xdb\xbf\x40\x98\x79\
+\x6d\x2d\xc2\xc4\x6b\x91\x72\x61\x92\xda\x5a\x84\xc9\x9c\xc4\x2f\
+\x97\x28\xd7\xa4\xba\x58\xd9\x02\xfd\xed\x55\x4e\x84\x06\x0a\xa1\
+\x21\x05\x62\x5d\x40\xcc\xd1\x77\xd3\x8b\xf9\xbb\xe1\x2a\x40\x00\
+\xa0\x5d\x92\xb3\x55\x5f\xb7\x0b\xe2\x24\x01\x20\xf1\x28\xc0\x5e\
+\xcf\xf1\xa8\xca\x52\xbe\x52\xc9\x48\x75\xc5\xd2\x94\xea\x16\x9c\
+\x38\x84\x3e\x96\xd2\x7a\xa3\x3f\xaf\x6a\x6a\x0d\x35\x8f\xc9\x1e\
+\xe0\xfd\x87\x40\x1d\x91\x4d\xc8\xa9\x62\xa3\x0c\x08\x0a\xc2\x82\
+\xad\x7a\x46\x72\x16\xaa\x78\xa1\x7b\xa6\x67\xf0\xf3\x44\xc3\xb4\
+\xd7\x3e\x39\x9f\x7f\x04\x56\x7d\x05\xb6\xf3\x26\xf5\x1d\xd8\xa6\
+\xfa\x79\x91\x92\x4b\x84\x54\xf7\x48\x41\x11\x79\x72\xc7\xad\x56\
+\x8e\xdc\x51\x19\x39\xf3\x28\xec\xb0\xa4\xd5\x9a\x7e\x85\xfa\x6e\
+\x33\xa2\xbd\x83\xff\x01\x47\x37\x00\x13\
\x00\x00\x07\xb5\
\x00\
\x00\x1a\x6e\x78\x9c\xed\x58\x5d\x6f\xe3\xb8\x15\x7d\xcf\xaf\x50\
@@ -53366,6 +53447,11 @@ qt_resource_name = "\
\x00\x44\
\x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x63\x00\x73\x00\x2e\x00\x71\x00\x6d\
\x00\x13\
+\x0f\x69\x32\x79\
+\x00\x75\
+\x00\x73\x00\x65\x00\x72\x00\x70\x00\x72\x00\x65\x00\x66\x00\x73\x00\x2d\x00\x76\x00\x69\x00\x73\x00\x75\x00\x61\x00\x6c\x00\x2e\
+\x00\x75\x00\x69\
+\x00\x13\
\x02\xb7\x50\xf9\
\x00\x75\
\x00\x73\x00\x65\x00\x72\x00\x70\x00\x72\x00\x65\x00\x66\x00\x73\x00\x2d\x00\x69\x00\x6d\x00\x70\x00\x6f\x00\x72\x00\x74\x00\x2e\
@@ -53629,7 +53715,7 @@ qt_resource_name = "\
qt_resource_struct = "\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\
-\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x59\
+\x00\x00\x00\x10\x00\x02\x00\x00\x00\x03\x00\x00\x00\x59\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x38\x00\x00\x00\x21\
\x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x1c\
\x00\x00\x00\x1a\x00\x02\x00\x00\x00\x17\x00\x00\x00\x05\
@@ -53661,64 +53747,65 @@ qt_resource_struct = "\
\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x0a\xf1\
\x00\x00\x00\x96\x00\x01\x00\x00\x00\x01\x00\x00\x13\x00\
\x00\x00\x00\x7c\x00\x01\x00\x00\x00\x01\x00\x00\x0f\x23\
-\x00\x00\x06\xce\x00\x01\x00\x00\x00\x01\x00\x0b\x07\x34\
-\x00\x00\x04\x7c\x00\x00\x00\x00\x00\x01\x00\x0a\x64\x1d\
-\x00\x00\x09\x34\x00\x01\x00\x00\x00\x01\x00\x0b\xde\x2a\
-\x00\x00\x0b\xc4\x00\x01\x00\x00\x00\x01\x00\x0c\xba\x35\
-\x00\x00\x05\x86\x00\x01\x00\x00\x00\x01\x00\x0a\xa3\xc8\
-\x00\x00\x07\x16\x00\x00\x00\x00\x00\x01\x00\x0b\x24\x7e\
-\x00\x00\x08\x2a\x00\x01\x00\x00\x00\x01\x00\x0b\x8d\x2c\
-\x00\x00\x0b\x26\x00\x01\x00\x00\x00\x01\x00\x0c\x90\xf2\
-\x00\x00\x07\x8a\x00\x00\x00\x00\x00\x01\x00\x0b\x4e\x4d\
-\x00\x00\x09\xce\x00\x01\x00\x00\x00\x01\x00\x0c\x1e\xcb\
-\x00\x00\x0c\x14\x00\x01\x00\x00\x00\x01\x00\x0c\xd6\x59\
-\x00\x00\x04\xc2\x00\x01\x00\x00\x00\x01\x00\x0a\x7d\x3f\
-\x00\x00\x08\xdc\x00\x00\x00\x00\x00\x01\x00\x0b\xbb\xd0\
-\x00\x00\x08\x50\x00\x01\x00\x00\x00\x01\x00\x0b\x92\xf0\
-\x00\x00\x06\xf0\x00\x00\x00\x00\x00\x01\x00\x0b\x11\xe8\
-\x00\x00\x04\xe6\x00\x01\x00\x00\x00\x01\x00\x0a\x82\xbe\
-\x00\x00\x07\x5e\x00\x01\x00\x00\x00\x01\x00\x0b\x3d\x43\
-\x00\x00\x04\x9e\x00\x01\x00\x00\x00\x01\x00\x0a\x72\xd3\
-\x00\x00\x0b\x4e\x00\x00\x00\x00\x00\x01\x00\x0c\x9c\x61\
-\x00\x00\x03\xfc\x00\x01\x00\x00\x00\x01\x00\x0a\x3e\x8b\
-\x00\x00\x05\xd6\x00\x01\x00\x00\x00\x01\x00\x0a\xbe\xe7\
-\x00\x00\x0a\xde\x00\x01\x00\x00\x00\x01\x00\x0c\x79\xc3\
-\x00\x00\x0b\x00\x00\x01\x00\x00\x00\x01\x00\x0c\x87\x5e\
-\x00\x00\x05\xb4\x00\x00\x00\x00\x00\x01\x00\x0a\xac\xce\
-\x00\x00\x03\xca\x00\x01\x00\x00\x00\x01\x00\x0a\x36\xd2\
-\x00\x00\x08\xba\x00\x01\x00\x00\x00\x01\x00\x0b\xb4\x7c\
-\x00\x00\x0a\x28\x00\x00\x00\x00\x00\x01\x00\x0c\x2f\x13\
-\x00\x00\x06\x2a\x00\x01\x00\x00\x00\x01\x00\x0a\xd0\x57\
-\x00\x00\x0a\x4c\x00\x00\x00\x00\x00\x01\x00\x0c\x45\xc6\
-\x00\x00\x07\xe4\x00\x00\x00\x00\x00\x01\x00\x0b\x66\x00\
-\x00\x00\x05\x38\x00\x01\x00\x00\x00\x01\x00\x0a\x92\xbe\
-\x00\x00\x0b\xe4\x00\x00\x00\x00\x00\x01\x00\x0c\xc4\xe3\
-\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x0a\xe7\x96\
-\x00\x00\x04\x28\x00\x00\x00\x00\x00\x01\x00\x0a\x46\x92\
-\x00\x00\x0c\x44\x00\x00\x00\x00\x00\x01\x00\x0c\xe2\x32\
-\x00\x00\x0a\x94\x00\x00\x00\x00\x00\x01\x00\x0c\x63\x4d\
-\x00\x00\x04\x4c\x00\x01\x00\x00\x00\x01\x00\x0a\x5b\xb2\
-\x00\x00\x0a\xbc\x00\x01\x00\x00\x00\x01\x00\x0c\x72\x74\
-\x00\x00\x09\x56\x00\x01\x00\x00\x00\x01\x00\x0b\xe6\xd3\
-\x00\x00\x0b\x74\x00\x01\x00\x00\x00\x01\x00\x0c\xa4\xee\
-\x00\x00\x06\xac\x00\x01\x00\x00\x00\x01\x00\x0a\xf9\xd5\
-\x00\x00\x07\xbc\x00\x01\x00\x00\x00\x01\x00\x0b\x5c\x4f\
-\x00\x00\x09\xac\x00\x00\x00\x00\x00\x01\x00\x0c\x0a\x3a\
-\x00\x00\x05\x5c\x00\x01\x00\x00\x00\x01\x00\x0a\x99\x87\
-\x00\x00\x08\x0a\x00\x00\x00\x00\x00\x01\x00\x0b\x77\xb8\
-\x00\x00\x06\x0a\x00\x01\x00\x00\x00\x01\x00\x0a\xca\xd8\
-\x00\x00\x09\xf8\x00\x01\x00\x00\x00\x01\x00\x0c\x25\x40\
-\x00\x00\x08\x92\x00\x01\x00\x00\x00\x01\x00\x0b\xa9\x0a\
-\x00\x00\x09\x0c\x00\x01\x00\x00\x00\x01\x00\x0b\xce\x54\
-\x00\x00\x0b\x9a\x00\x01\x00\x00\x00\x01\x00\x0c\xaf\xb3\
-\x00\x00\x0a\x70\x00\x01\x00\x00\x00\x01\x00\x0c\x58\x9d\
-\x00\x00\x05\x08\x00\x01\x00\x00\x00\x01\x00\x0a\x8a\x9c\
-\x00\x00\x08\x72\x00\x00\x00\x00\x00\x01\x00\x0b\x99\x38\
-\x00\x00\x06\x58\x00\x00\x00\x00\x00\x01\x00\x0a\xd8\x3c\
-\x00\x00\x07\x3e\x00\x01\x00\x00\x00\x01\x00\x0b\x33\xcf\
-\x00\x00\x09\x7a\x00\x00\x00\x00\x00\x01\x00\x0b\xee\x24\
+\x00\x00\x06\xfa\x00\x01\x00\x00\x00\x01\x00\x0b\x0c\x1d\
+\x00\x00\x04\xa8\x00\x00\x00\x00\x00\x01\x00\x0a\x69\x06\
+\x00\x00\x09\x60\x00\x01\x00\x00\x00\x01\x00\x0b\xe3\x13\
+\x00\x00\x0b\xf0\x00\x01\x00\x00\x00\x01\x00\x0c\xbf\x1e\
+\x00\x00\x05\xb2\x00\x01\x00\x00\x00\x01\x00\x0a\xa8\xb1\
+\x00\x00\x07\x42\x00\x00\x00\x00\x00\x01\x00\x0b\x29\x67\
+\x00\x00\x08\x56\x00\x01\x00\x00\x00\x01\x00\x0b\x92\x15\
+\x00\x00\x0b\x52\x00\x01\x00\x00\x00\x01\x00\x0c\x95\xdb\
+\x00\x00\x07\xb6\x00\x00\x00\x00\x00\x01\x00\x0b\x53\x36\
+\x00\x00\x09\xfa\x00\x01\x00\x00\x00\x01\x00\x0c\x23\xb4\
+\x00\x00\x0c\x40\x00\x01\x00\x00\x00\x01\x00\x0c\xdb\x42\
+\x00\x00\x04\xee\x00\x01\x00\x00\x00\x01\x00\x0a\x82\x28\
+\x00\x00\x09\x08\x00\x00\x00\x00\x00\x01\x00\x0b\xc0\xb9\
+\x00\x00\x08\x7c\x00\x01\x00\x00\x00\x01\x00\x0b\x97\xd9\
+\x00\x00\x07\x1c\x00\x00\x00\x00\x00\x01\x00\x0b\x16\xd1\
+\x00\x00\x05\x12\x00\x01\x00\x00\x00\x01\x00\x0a\x87\xa7\
+\x00\x00\x07\x8a\x00\x01\x00\x00\x00\x01\x00\x0b\x42\x2c\
+\x00\x00\x04\xca\x00\x01\x00\x00\x00\x01\x00\x0a\x77\xbc\
+\x00\x00\x0b\x7a\x00\x00\x00\x00\x00\x01\x00\x0c\xa1\x4a\
+\x00\x00\x04\x28\x00\x01\x00\x00\x00\x01\x00\x0a\x43\x74\
+\x00\x00\x06\x02\x00\x01\x00\x00\x00\x01\x00\x0a\xc3\xd0\
+\x00\x00\x0b\x0a\x00\x01\x00\x00\x00\x01\x00\x0c\x7e\xac\
+\x00\x00\x0b\x2c\x00\x01\x00\x00\x00\x01\x00\x0c\x8c\x47\
+\x00\x00\x05\xe0\x00\x00\x00\x00\x00\x01\x00\x0a\xb1\xb7\
+\x00\x00\x03\xf6\x00\x01\x00\x00\x00\x01\x00\x0a\x3b\xbb\
+\x00\x00\x08\xe6\x00\x01\x00\x00\x00\x01\x00\x0b\xb9\x65\
+\x00\x00\x0a\x54\x00\x00\x00\x00\x00\x01\x00\x0c\x33\xfc\
+\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x0a\xd5\x40\
+\x00\x00\x0a\x78\x00\x00\x00\x00\x00\x01\x00\x0c\x4a\xaf\
+\x00\x00\x08\x10\x00\x00\x00\x00\x00\x01\x00\x0b\x6a\xe9\
+\x00\x00\x05\x64\x00\x01\x00\x00\x00\x01\x00\x0a\x97\xa7\
+\x00\x00\x0c\x10\x00\x00\x00\x00\x00\x01\x00\x0c\xc9\xcc\
+\x00\x00\x06\xb0\x00\x00\x00\x00\x00\x01\x00\x0a\xec\x7f\
+\x00\x00\x04\x54\x00\x00\x00\x00\x00\x01\x00\x0a\x4b\x7b\
+\x00\x00\x0c\x70\x00\x00\x00\x00\x00\x01\x00\x0c\xe7\x1b\
+\x00\x00\x0a\xc0\x00\x00\x00\x00\x00\x01\x00\x0c\x68\x36\
+\x00\x00\x04\x78\x00\x01\x00\x00\x00\x01\x00\x0a\x60\x9b\
+\x00\x00\x0a\xe8\x00\x01\x00\x00\x00\x01\x00\x0c\x77\x5d\
+\x00\x00\x09\x82\x00\x01\x00\x00\x00\x01\x00\x0b\xeb\xbc\
+\x00\x00\x0b\xa0\x00\x01\x00\x00\x00\x01\x00\x0c\xa9\xd7\
+\x00\x00\x06\xd8\x00\x01\x00\x00\x00\x01\x00\x0a\xfe\xbe\
+\x00\x00\x07\xe8\x00\x01\x00\x00\x00\x01\x00\x0b\x61\x38\
+\x00\x00\x09\xd8\x00\x00\x00\x00\x00\x01\x00\x0c\x0f\x23\
+\x00\x00\x05\x88\x00\x01\x00\x00\x00\x01\x00\x0a\x9e\x70\
+\x00\x00\x08\x36\x00\x00\x00\x00\x00\x01\x00\x0b\x7c\xa1\
+\x00\x00\x06\x36\x00\x01\x00\x00\x00\x01\x00\x0a\xcf\xc1\
+\x00\x00\x0a\x24\x00\x01\x00\x00\x00\x01\x00\x0c\x2a\x29\
+\x00\x00\x08\xbe\x00\x01\x00\x00\x00\x01\x00\x0b\xad\xf3\
+\x00\x00\x09\x38\x00\x01\x00\x00\x00\x01\x00\x0b\xd3\x3d\
+\x00\x00\x0b\xc6\x00\x01\x00\x00\x00\x01\x00\x0c\xb4\x9c\
+\x00\x00\x0a\x9c\x00\x01\x00\x00\x00\x01\x00\x0c\x5d\x86\
+\x00\x00\x05\x34\x00\x01\x00\x00\x00\x01\x00\x0a\x8f\x85\
+\x00\x00\x08\x9e\x00\x00\x00\x00\x00\x01\x00\x0b\x9e\x21\
+\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x0a\xdd\x25\
+\x00\x00\x07\x6a\x00\x01\x00\x00\x00\x01\x00\x0b\x38\xb8\
+\x00\x00\x09\xa6\x00\x00\x00\x00\x00\x01\x00\x0b\xf3\x0d\
+\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x0a\x27\x9b\
+\x00\x00\x03\xce\x00\x01\x00\x00\x00\x01\x00\x0a\x31\xbc\
\x00\x00\x03\x76\x00\x01\x00\x00\x00\x01\x00\x0a\x1c\x55\
-\x00\x00\x03\xa2\x00\x01\x00\x00\x00\x01\x00\x0a\x26\x0e\
"
def qInitResources():
diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py
index f1ae9612c..938680e59 100644
--- a/src/Mod/Draft/InitGui.py
+++ b/src/Mod/Draft/InitGui.py
@@ -112,11 +112,12 @@ class DraftWorkbench (Workbench):
"Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale",
"Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint",
"Draft_DelPoint","Draft_Shape2DView","Draft_Draft2Sketch","Draft_Array",
- "Draft_Clone","Draft_Heal"]
+ "Draft_Clone"]
self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup",
- "Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap",
+ "Draft_SelectGroup","Draft_SelectPlane",
"Draft_ShowSnapBar","Draft_ToggleGrid"]
self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"]
+ self.utils = ["Draft_Heal"]
self.snapList = ['Draft_Snap_Lock','Draft_Snap_Midpoint','Draft_Snap_Perpendicular',
'Draft_Snap_Grid','Draft_Snap_Intersection','Draft_Snap_Parallel',
'Draft_Snap_Endpoint','Draft_Snap_Angle','Draft_Snap_Center',
@@ -125,11 +126,13 @@ class DraftWorkbench (Workbench):
self.appendToolbar(QT_TRANSLATE_NOOP("Workbench","Draft modification tools"),self.modList)
self.appendMenu(str(translate("draft","&Draft")),self.cmdList+self.modList)
self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Context tools"))],self.treecmdList)
+ self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Utilities"))],self.utils)
self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Wire tools"))],self.lineList)
self.appendMenu([str(translate("draft","&Draft")),str(translate("draft","Snapping"))],self.snapList)
if hasattr(FreeCADGui,"draftToolBar"):
if not hasattr(FreeCADGui.draftToolBar,"loadedPreferences"):
FreeCADGui.addPreferencePage(":/ui/userprefs-base.ui","Draft")
+ FreeCADGui.addPreferencePage(":/ui/userprefs-visual.ui","Draft")
FreeCADGui.addPreferencePage(":/ui/userprefs-import.ui","Draft")
FreeCADGui.draftToolBar.loadedPreferences = True
Log ('Loading Draft module...done\n')
@@ -178,13 +181,5 @@ App.addImportType("Common airfoil data (*.dat)","importAirfoilDAT")
App.addExportType("Autodesk DXF (*.dxf)","importDXF")
App.addExportType("Flattened SVG (*.svg)","importSVG")
App.addExportType("Open CAD Format (*.oca)","importOCA")
-
-# add 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")))
-
+App.addImportType("Autodesk DWG (*.dwg)","importDWG")
+App.addExportType("Autodesk DWG (*.dwg)","importDWG")
diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc
index 2ab449808..62d171766 100644
--- a/src/Mod/Draft/Resources/Draft.qrc
+++ b/src/Mod/Draft/Resources/Draft.qrc
@@ -86,5 +86,6 @@
translations/Draft_pt-PT.qm
ui/userprefs-base.ui
ui/userprefs-import.ui
+ ui/userprefs-visual.ui
diff --git a/src/Mod/Draft/Resources/ui/userprefs-base.ui b/src/Mod/Draft/Resources/ui/userprefs-base.ui
index f373dda63..7a4e56e0c 100755
--- a/src/Mod/Draft/Resources/ui/userprefs-base.ui
+++ b/src/Mod/Draft/Resources/ui/userprefs-base.ui
@@ -44,16 +44,33 @@
+
+
+ -
+
-
Draft interface mode
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
-
@@ -79,302 +96,6 @@
- -
-
-
-
-
-
- Default color
-
-
-
- -
-
-
- the default color for new objects
-
-
-
- 0
- 0
- 0
-
-
-
- color
-
-
- Mod/Draft
-
-
-
- -
-
-
- Snap color
-
-
-
- -
-
-
- the default color for snap symbols
-
-
-
- 0
- 0
- 0
-
-
-
- snapcolor
-
-
- Mod/Draft
-
-
-
- -
-
-
- Construction color
-
-
-
- -
-
-
- This is the default color for objects being drawn while in construction mode.
-
-
-
- 44
- 125
- 255
-
-
-
- constructioncolor
-
-
- Mod/Draft
-
-
-
- -
-
-
- Default linewidth
-
-
-
- -
-
-
- the default linewidth for new objects
-
-
- 2
-
-
- linewidth
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- Constrain mod
-
-
-
- -
-
-
- The Constraining modifier key
-
-
- modconstrain
-
-
- Mod/Draft
-
-
-
-
- shift
-
-
- -
-
- ctrl
-
-
- -
-
- alt
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Snap mod
-
-
-
- -
-
-
- The snap modifier key
-
-
- 1
-
-
- modsnap
-
-
- Mod/Draft
-
-
-
-
- shift
-
-
- -
-
- ctrl
-
-
- -
-
- alt
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Alt mod
-
-
-
- -
-
-
- The alt modifier key
-
-
- 2
-
-
- modalt
-
-
- Mod/Draft
-
-
-
-
- shift
-
-
- -
-
- ctrl
-
-
- -
-
- alt
-
-
-
-
-
-
- -
-
-
-
-
-
- Construction group name
-
-
-
- -
-
-
- This is the default group name for construction geometry
-
-
- Construction
-
-
- constructiongroupname
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- check this if you want to use the color/linewidth from the toolbar as default
-
-
- Save current color and linewidth across sessions
-
-
- saveonexit
-
-
- Mod/Draft
-
-
-
-
-
-
-
@@ -418,209 +139,6 @@
- -
-
-
-
-
-
- If this is checked, you will always snap to existing objects while drawing. If not, you will be snapping only when pressing CTRL.
-
-
- Always snap to objects (disable snap mod key)
-
-
- true
-
-
- alwaysSnap
-
-
- Mod/Draft
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- The radius for snapping to special points. Set to 0 for no distance (infinite)
-
-
- Snap range
-
-
-
- -
-
-
- px
-
-
- snapRange
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- If this is checked, snapping will not occur against objects with more than the indicated number of edges
-
-
- Snap maximum
-
-
- false
-
-
- maxSnap
-
-
- Mod/Draft
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- false
-
-
- Maximum number of edges to be considered for snapping
-
-
- Maximum number of edges
-
-
-
- -
-
-
- false
-
-
- 999
-
-
- 24
-
-
- maxSnapEdges
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- If checked, the Snap toolbar will be shown whenever you use snapping
-
-
- Show Draft Snap toolbar
-
-
- true
-
-
- showSnapBar
-
-
- Mod/Draft
-
-
-
- -
-
-
- Hide Draft snap toolbar after use
-
-
- hideSnapBar
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- if checked, a widget indicating the current working plane orientation appears during drawing operations
-
-
- Show Working Plane tracker
-
-
- showPlaneTracker
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- If this is checked, objects will appear as filled as default. Otherwise, they will appear as wireframe
-
-
- Fill objects by default
-
-
- fillmode
-
-
- Mod/Draft
-
-
-
-
-
-
-
@@ -630,6 +148,19 @@
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
-
@@ -663,28 +194,16 @@
-
-
+
-
-
-
- If checked, a grid will appear when drawing
-
+
- Use grid
-
-
- false
-
-
- grid
-
-
- Mod/Draft
+ Internal precision level
-
-
+
Qt::Horizontal
@@ -696,100 +215,6 @@
- -
-
-
- false
-
-
- If checked, the Draft grid will always be visible when the Draft workbench is active. Otherwise only when using a command
-
-
- Always show
-
-
- alwaysShowGrid
-
-
- Mod/Draft
-
-
-
- -
-
-
- false
-
-
- Grid spacing
-
-
-
- -
-
-
- false
-
-
- The spacing between each grid line
-
-
- 4
-
-
- 9999.989999999999782
-
-
- 1.000000000000000
-
-
- gridSpacing
-
-
- Mod/Draft
-
-
-
- -
-
-
- false
-
-
- Main lines every
-
-
-
- -
-
-
- false
-
-
- Mainlines will be drawn thicker. Specify here how many squares between mainlines.
-
-
- 10
-
-
- gridEvery
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- Internal precision level
-
-
-
-
@@ -812,8 +237,19 @@
+
+
+ -
+
-
-
+
+
+ Dimensions precision level
+
+
+
+ -
+
Qt::Horizontal
@@ -825,13 +261,6 @@
- -
-
-
- Dimensions precision level
-
-
-
-
@@ -904,34 +333,93 @@ Values with differences below this value will be treated as same.
-
-
+
-
-
+
+
+ When this is checked, the Draft tools will create Part primitives instead of Draft objects, when available.
+
- Default text height
+ Use Part Primitives when available
+
+
+ UsePartPrimitives
+
+
+ Mod/Draft
+
+
+
+
+
+
+
+
+ -
+
+
+ Snapping
+
+
+
-
+
+
-
+
+
+ Constrain mod
-
-
-
+
+
+ Qt::Horizontal
+
+
- 60
- 16777215
+ 40
+ 20
+
+
+ -
+
- Default height for texts and dimensions
-
-
- 0.200000000000000
+ The Constraining modifier key
- textheight
+ modconstrain
Mod/Draft
+
-
+
+ shift
+
+
+ -
+
+ ctrl
+
+
+ -
+
+ alt
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Snap mod
+
-
@@ -948,47 +436,49 @@ Values with differences below this value will be treated as same.
-
-
-
- Default text font
-
-
-
- -
-
+
- This is the default font name for all Draft texts and dimensions.
-It can be a font name such as "Arial", a default style such as "sans", "serif"
-or "mono", or a family such as "Arial,Helvetica,sans" or a name with a style
-such as "Arial:Bold"
+ The snap modifier key
-
- Arial
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+ 1
- textfont
+ modsnap
Mod/Draft
+
-
+
+ shift
+
+
+ -
+
+ ctrl
+
+
+ -
+
+ alt
+
+
-
-
+
-
-
+
- Default template sheet
+ Alt mod
-
-
+
Qt::Horizontal
@@ -1001,38 +491,53 @@ such as "Arial:Bold"
-
-
-
-
- 300
- 0
-
-
+
- The default template to use when creating a new drawing sheet
+ The alt modifier key
+
+
+ 2
- template
+ modalt
Mod/Draft
+
-
+
+ shift
+
+
+ -
+
+ ctrl
+
+
+ -
+
+ alt
+
+
-
-
+
-
-
+
- When this is checked, the Draft tools will create Part primitives instead of Draft objects, when available.
+ If checked, the Snap toolbar will be shown whenever you use snapping
- Use Part Primitives
+ Show Draft Snap toolbar
+
+
+ true
- UsePartPrimitives
+ showSnapBar
Mod/Draft
@@ -1042,155 +547,56 @@ such as "Arial:Bold"
-
-
+
-
-
+
- Dimensions & Leader arrow style
+ Hide Draft snap toolbar after use
-
-
- -
-
- dimsymbol
+ hideSnapBar
Mod/Draft
-
-
-
- Dot 5
-
-
- -
-
- Dot 7
-
-
- -
-
- Dot 9
-
-
- -
-
- Circle 5
-
-
- -
-
- Circle 7
-
-
- -
-
- Circle 9
-
-
- -
-
- Slash 5
-
-
- -
-
- Slash 7
-
-
- -
-
- Slash 9
-
-
- -
-
- Backslash 5
-
-
- -
-
- Backslash 7
-
-
- -
-
- Backslash 9
-
-
+
+
+
+
+ horizontalLayoutWidget_3
+ horizontalLayoutWidget_4
+ horizontalLayoutWidget_5
+
+
+ -
+
+
+ Construction geometry
+
+
-
-
+
-
-
+
- Vertical dimensions text orientation
+ Construction group name
-
-
+
- This is the orientation of the dimension texts when those dimensions are vertical. Default is left, which is the ISO standard.
+ This is the default group name for construction geometry
-
- dimorientation
-
-
- Mod/Draft
-
-
-
-
- Left (ISO standard)
-
-
- -
-
- Right
-
-
-
-
-
-
- -
-
-
-
-
- Alternate SVG Patterns location
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 300
- 0
-
-
-
- Here you can specify a directory containing SVG files containing <pattern> definitions that can be added to the standard Draft hatch patterns
+ Construction
- patternFile
+ constructiongroupname
Mod/Draft
@@ -1200,11 +606,11 @@ such as "Arial:Bold"
-
-
+
-
-
+
- Default ShapeString Font File
+ Construction geometry color
@@ -1222,18 +628,19 @@ such as "Arial:Bold"
-
-
-
-
- 300
- 0
-
-
+
- Select a font file
+ This is the default color for objects being drawn while in construction mode.
+
+
+
+ 44
+ 125
+ 255
+
- FontFile
+ constructioncolor
Mod/Draft
@@ -1242,6 +649,19 @@ such as "Arial:Bold"
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
@@ -1250,21 +670,11 @@ such as "Arial:Bold"
qPixmapFromMimeSource
-
- Gui::FileChooser
- QWidget
-
-
Gui::ColorButton
QPushButton
-
- Gui::PrefFileChooser
- Gui::FileChooser
-
-
Gui::PrefSpinBox
QSpinBox
@@ -1298,102 +708,6 @@ such as "Arial:Bold"
-
- gui::prefcheckbox_2
- clicked(bool)
- gui::prefdoublespinbox_3
- setEnabled(bool)
-
-
- 92
- 379
-
-
- 417
- 381
-
-
-
-
- gui::prefcheckbox_2
- clicked(bool)
- gui::prefspinbox_4
- setEnabled(bool)
-
-
- 79
- 373
-
-
- 571
- 374
-
-
-
-
- gui::prefcheckbox_4
- clicked(bool)
- gui::prefspinbox_6
- setEnabled(bool)
-
-
- 67
- 270
-
-
- 571
- 272
-
-
-
-
- gui::prefcheckbox_4
- clicked(bool)
- label_23
- setEnabled(bool)
-
-
- 62
- 270
-
-
- 516
- 272
-
-
-
-
- gui::prefcheckbox_2
- clicked(bool)
- label_15
- setEnabled(bool)
-
-
- 58
- 365
-
-
- 354
- 381
-
-
-
-
- gui::prefcheckbox_2
- clicked(bool)
- label_16
- setEnabled(bool)
-
-
- 33
- 367
-
-
- 516
- 381
-
-
-
gui::prefcheckbox_7
clicked(bool)
@@ -1410,21 +724,5 @@ such as "Arial:Bold"
-
- gui::prefcheckbox_2
- clicked(bool)
- gui::prefcheckbox_10
- setEnabled(bool)
-
-
- 72
- 375
-
-
- 226
- 373
-
-
-
diff --git a/src/Mod/Draft/Resources/ui/userprefs-import.ui b/src/Mod/Draft/Resources/ui/userprefs-import.ui
index 95b64c308..20ebbe7cd 100755
--- a/src/Mod/Draft/Resources/ui/userprefs-import.ui
+++ b/src/Mod/Draft/Resources/ui/userprefs-import.ui
@@ -7,7 +7,7 @@
0
0
575
- 629
+ 666
@@ -97,6 +97,78 @@ If color mapping is choosed, you must choose a color mapping file containing a t
+ -
+
+
-
+
+
+ Import
+
+
+
+ -
+
+
+ if this is unchecked, texts/mtexts won't be imported
+
+
+ texts and dimensions
+
+
+ dxftext
+
+
+ Mod/Draft
+
+
+
+ -
+
+
+ points
+
+
+ dxfImportPoints
+
+
+ Mod/Draft
+
+
+
+ -
+
+
+ if this is checked, paper space objects will be imported too
+
+
+ layouts
+
+
+ dxflayout
+
+
+ Mod/Draft
+
+
+
+ -
+
+
+ Check this if you want the non-named blocks (beginning with a *) to be imported too
+
+
+ *blocks
+
+
+ dxfstarblocks
+
+
+ Mod/Draft
+
+
+
+
+
-
-
@@ -160,66 +232,6 @@ If color mapping is choosed, you must choose a color mapping file containing a t
- -
-
-
-
-
-
- if this is unchecked, texts/mtexts won't be imported
-
-
- Import texts and dimensions
-
-
- dxftext
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- if this is checked, paper space objects will be imported too
-
-
- Import layouts
-
-
- dxflayout
-
-
- Mod/Draft
-
-
-
-
-
- -
-
-
-
-
-
- Check this if you want the non-named blocks (beginning with a *) to be imported too
-
-
- Import *blocks
-
-
- dxfstarblocks
-
-
- Mod/Draft
-
-
-
-
-
-
-
@@ -363,6 +375,39 @@ If color mapping is choosed, you must choose a color mapping file containing a t
+ -
+
+
+ DWG format options
+
+
+
-
+
+
-
+
+
+ Path to Teigha File Converter
+
+
+
+ -
+
+
+ The path to your Teigha File Converter executable
+
+
+ TeighaFileConverter
+
+
+ Mod/Draft
+
+
+
+
+
+
+
+
-
diff --git a/src/Mod/Draft/Resources/ui/userprefs-visual.ui b/src/Mod/Draft/Resources/ui/userprefs-visual.ui
new file mode 100644
index 000000000..dca4dd81a
--- /dev/null
+++ b/src/Mod/Draft/Resources/ui/userprefs-visual.ui
@@ -0,0 +1,905 @@
+
+
+ Gui::Dialog::DlgSettingsDraft
+
+
+
+ 0
+ 0
+ 718
+ 808
+
+
+
+ Visual settings
+
+
+
+ 6
+
+
+ 9
+
+
-
+
+
+ Visual Settings
+
+
+
-
+
+
-
+
+
+ Default line color
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ the default color for new objects
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ color
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ Default line width
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ the default linewidth for new objects
+
+
+ 2
+
+
+ linewidth
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ Snap symbols color
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ the default color for snap symbols
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ snapcolor
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ check this if you want to use the color/linewidth from the toolbar as default
+
+
+ Save current color and linewidth across sessions
+
+
+ saveonexit
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ if checked, a widget indicating the current working plane orientation appears during drawing operations
+
+
+ Show Working Plane tracker
+
+
+ showPlaneTracker
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ If this is checked, objects will appear as filled as default. Otherwise, they will appear as wireframe
+
+
+ Fill objects by default
+
+
+ fillmode
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ Default template sheet
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 300
+ 0
+
+
+
+ The default template to use when creating a new drawing sheet
+
+
+ template
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ Alternate SVG Patterns location
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 300
+ 0
+
+
+
+ Here you can specify a directory containing SVG files containing <pattern> definitions that can be added to the standard Draft hatch patterns
+
+
+ patternFile
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ Hatch patterns resolution
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ 512
+
+
+ 128
+
+
+ HatchPatternResolution
+
+
+ Mod/Draft
+
+
+
+
+
+
+
+
+ -
+
+
+ Grid
+
+
+
-
+
+
-
+
+
+ If checked, a grid will appear when drawing
+
+
+ Use grid
+
+
+ false
+
+
+ grid
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ false
+
+
+ If checked, the Draft grid will always be visible when the Draft workbench is active. Otherwise only when using a command
+
+
+ Always show the grid
+
+
+ alwaysShowGrid
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ false
+
+
+ Grid spacing
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ false
+
+
+ The spacing between each grid line
+
+
+ 4
+
+
+ 9999.989999999999782
+
+
+ 1.000000000000000
+
+
+ gridSpacing
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ false
+
+
+ Main lines every
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ false
+
+
+ Mainlines will be drawn thicker. Specify here how many squares between mainlines.
+
+
+ 10
+
+
+ gridEvery
+
+
+ Mod/Draft
+
+
+
+
+
+
+
+
+ -
+
+
+ Texts and dimensions
+
+
+
-
+
+
-
+
+
+ Default text height
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 60
+ 16777215
+
+
+
+ Default height for texts and dimensions
+
+
+ 0.200000000000000
+
+
+ textheight
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ Default text font
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ This is the default font name for all Draft texts and dimensions.
+It can be a font name such as "Arial", a default style such as "sans", "serif"
+or "mono", or a family such as "Arial,Helvetica,sans" or a name with a style
+such as "Arial:Bold"
+
+
+ Arial
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ textfont
+
+
+ Mod/Draft
+
+
+
+
+
+ -
+
+
-
+
+
+ Dimensions & Leader arrow style
+
+
+
+ -
+
+
+ dimsymbol
+
+
+ Mod/Draft
+
+
-
+
+ Dot 5
+
+
+ -
+
+ Dot 7
+
+
+ -
+
+ Dot 9
+
+
+ -
+
+ Circle 5
+
+
+ -
+
+ Circle 7
+
+
+ -
+
+ Circle 9
+
+
+ -
+
+ Slash 5
+
+
+ -
+
+ Slash 7
+
+
+ -
+
+ Slash 9
+
+
+ -
+
+ Backslash 5
+
+
+ -
+
+ Backslash 7
+
+
+ -
+
+ Backslash 9
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Vertical dimensions text orientation
+
+
+
+ -
+
+
+ This is the orientation of the dimension texts when those dimensions are vertical. Default is left, which is the ISO standard.
+
+
+ dimorientation
+
+
+ Mod/Draft
+
+
-
+
+ Left (ISO standard)
+
+
+ -
+
+ Right
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Default ShapeString Font File
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 300
+ 0
+
+
+
+ Select a font file
+
+
+ FontFile
+
+
+ Mod/Draft
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+ qPixmapFromMimeSource
+
+
+ Gui::FileChooser
+ QWidget
+
+
+
+ Gui::ColorButton
+ QPushButton
+
+
+
+ Gui::PrefFileChooser
+ Gui::FileChooser
+
+
+
+ Gui::PrefSpinBox
+ QSpinBox
+
+
+
+ Gui::PrefColorButton
+ Gui::ColorButton
+
+
+
+ Gui::PrefCheckBox
+ QCheckBox
+
+
+
+ Gui::PrefComboBox
+ QComboBox
+
+
+
+ Gui::PrefLineEdit
+ QLineEdit
+
+
+
+ Gui::PrefDoubleSpinBox
+ QDoubleSpinBox
+
+
+
+
+
+
+ gui::prefcheckbox_2
+ clicked(bool)
+ gui::prefdoublespinbox_3
+ setEnabled(bool)
+
+
+ 92
+ 379
+
+
+ 417
+ 381
+
+
+
+
+ gui::prefcheckbox_2
+ clicked(bool)
+ gui::prefspinbox_4
+ setEnabled(bool)
+
+
+ 79
+ 373
+
+
+ 571
+ 374
+
+
+
+
+ gui::prefcheckbox_2
+ clicked(bool)
+ label_15
+ setEnabled(bool)
+
+
+ 58
+ 365
+
+
+ 354
+ 381
+
+
+
+
+ gui::prefcheckbox_2
+ clicked(bool)
+ label_16
+ setEnabled(bool)
+
+
+ 33
+ 367
+
+
+ 516
+ 381
+
+
+
+
+ gui::prefcheckbox_2
+ clicked(bool)
+ gui::prefcheckbox_10
+ setEnabled(bool)
+
+
+ 72
+ 375
+
+
+ 226
+ 373
+
+
+
+
+
diff --git a/src/Mod/Draft/TestDraft.py b/src/Mod/Draft/TestDraft.py
new file mode 100644
index 000000000..6c2f613bc
--- /dev/null
+++ b/src/Mod/Draft/TestDraft.py
@@ -0,0 +1,142 @@
+# Unit test for the Draft module
+
+#***************************************************************************
+#* (c) Yorik van Havre 2013 *
+#* *
+#* This file is part of the FreeCAD CAx development system. *
+#* *
+#* 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. *
+#* *
+#* FreeCAD 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 FreeCAD; if not, write to the Free Software *
+#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+#* USA *
+#* *
+#***************************************************************************/
+
+import FreeCAD, os, unittest, FreeCADGui, Draft
+
+class DraftTest(unittest.TestCase):
+
+ def setUp(self):
+ # setting a new document to hold the tests
+ if FreeCAD.ActiveDocument:
+ if FreeCAD.ActiveDocument.Name != "DraftTest":
+ FreeCAD.newDocument("DraftTest")
+ else:
+ FreeCAD.newDocument("DraftTest")
+ FreeCAD.setActiveDocument("DraftTest")
+
+ def testPivy(self):
+ FreeCAD.Console.PrintLog ('Checking Pivy...\n')
+ from pivy import coin
+ c = coin.SoCube()
+ FreeCADGui.ActiveDocument.ActiveView.getSceneGraph().addChild(c)
+ self.failUnless(c,"Pivy is not working properly")
+
+ # creation tools
+
+ def testLine(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Line...\n')
+ Draft.makeLine(FreeCAD.Vector(0,0,0),FreeCAD.Vector(-2,0,0))
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Line"),"Draft Line failed")
+
+ def testWire(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Wire...\n')
+ Draft.makeWire([FreeCAD.Vector(0,0,0),FreeCAD.Vector(2,0,0),FreeCAD.Vector(2,2,0)])
+ self.failUnless(FreeCAD.ActiveDocument.getObject("DWire"),"Draft Wire failed")
+
+ def testBSpline(self):
+ FreeCAD.Console.PrintLog ('Checking Draft BSpline...\n')
+ Draft.makeBSpline([FreeCAD.Vector(0,0,0),FreeCAD.Vector(2,0,0),FreeCAD.Vector(2,2,0)])
+ self.failUnless(FreeCAD.ActiveDocument.getObject("BSpline"),"Draft BSpline failed")
+
+ def testRectangle(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Rectangle...\n')
+ Draft.makeRectangle(4,2)
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Rectangle"),"Draft Rectangle failed")
+
+ def testArc(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Arc...\n')
+ Draft.makeCircle(2, startangle=0, endangle=90)
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Arc"),"Draft Arc failed")
+
+ def testCircle(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Circle...\n')
+ Draft.makeCircle(3)
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Circle"),"Draft Circle failed")
+
+ def testPolygon(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Polygon...\n')
+ Draft.makePolygon(5,5)
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Polygon"),"Draft Polygon failed")
+
+ def testEllipse(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Ellipse...\n')
+ Draft.makeEllipse(5,3)
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Ellipse"),"Draft Ellipse failed")
+
+ def testPoint(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Point...\n')
+ Draft.makePoint(5,3,2)
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Point"),"Draft Point failed")
+
+ def testText(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Text...\n')
+ Draft.makeText("Testing Draft")
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Text"),"Draft Text failed")
+
+ #def testShapeString(self):
+ # not working ATM because it needs a font file
+ # FreeCAD.Console.PrintLog ('Checking Draft ShapeString...\n')
+ # Draft.makeShapeString("Testing Draft")
+ # self.failUnless(FreeCAD.ActiveDocument.getObject("ShapeString"),"Draft ShapeString failed")
+
+ def testDimension(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Dimension...\n')
+ Draft.makeDimension(FreeCAD.Vector(0,0,0),FreeCAD.Vector(2,0,0),FreeCAD.Vector(1,-1,0))
+ self.failUnless(FreeCAD.ActiveDocument.getObject("Dimension"),"Draft Dimension failed")
+
+ # modification tools
+
+ def testMove(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Move...\n')
+ l = Draft.makeLine(FreeCAD.Vector(0,0,0),FreeCAD.Vector(-2,0,0))
+ Draft.move(l,FreeCAD.Vector(2,0,0))
+ self.failUnless(l.Start == FreeCAD.Vector(2,0,0),"Draft Move failed")
+
+ def testCopy(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Move with copy...\n')
+ l = Draft.makeLine(FreeCAD.Vector(0,0,0),FreeCAD.Vector(2,0,0))
+ l2 = Draft.move(l,FreeCAD.Vector(2,0,0),copy=True)
+ self.failUnless(l2,"Draft Move with copy failed")
+
+ def testRotate(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Rotate...\n')
+ l = Draft.makeLine(FreeCAD.Vector(2,0,0),FreeCAD.Vector(4,0,0))
+ Draft.rotate(l,90)
+ self.failUnless(l.Start == FreeCAD.Vector(0,2,0),"Draft Rotate failed")
+
+ def testOffset(self):
+ FreeCAD.Console.PrintLog ('Checking Draft Offset...\n')
+ r = Draft.makeRectangle(4,2)
+ r2 = Draft.offset(r,FreeCAD.Vector(-1,-1,0),copy=True)
+ self.failUnless(r2,"Draft Offset failed")
+
+ # modification tools
+
+ def tearDown(self):
+ FreeCAD.closeDocument("DraftTest")
+ pass
+
+
+
diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py
index a0057df5e..7a0274d0b 100644
--- a/src/Mod/Draft/WorkingPlane.py
+++ b/src/Mod/Draft/WorkingPlane.py
@@ -92,7 +92,7 @@ class plane:
gp = self.getGlobalCoords(Vector(lp.x,lp.y,0))
a = direction.getAngle(gp.sub(p))
if a > math.pi/2:
- direction = DraftVecUtils.neg(direction)
+ direction = direction.negative()
a = math.pi - a
ld = self.getLocalRot(direction)
gd = self.getGlobalRot(Vector(ld.x,ld.y,0))
@@ -158,7 +158,7 @@ class plane:
v1.normalize()
v2.normalize()
v3.normalize()
- print v1,v2,v3
+ #print v1,v2,v3
self.u = v1
self.v = v2
self.axis = v3
@@ -187,10 +187,20 @@ class plane:
# len(sex) > 2, look for point and line, three points, etc.
return False
- def setup(self, direction, point, upvec=None):
+ def setup(self, direction=None, point=None, upvec=None):
'''If working plane is undefined, define it!'''
if self.weak:
- self.alignToPointAndAxis(point, direction, 0, upvec)
+ if direction and point:
+ self.alignToPointAndAxis(point, direction, 0, upvec)
+ else:
+ try:
+ from pivy import coin
+ rot = FreeCADGui.ActiveDocument.ActiveView.getCameraNode().getField("orientation").getValue()
+ upvec = Vector(rot.multVec(coin.SbVec3f(0,1,0)).getValue())
+ vdir = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
+ self.alignToPointAndAxis(Vector(0,0,0), vdir.negative(), 0, upvec)
+ except:
+ print "Draft: Unable to align the working plane to the current view"
self.weak = True
def reset(self):
@@ -251,9 +261,9 @@ class plane:
def getGlobalCoords(self,point):
"returns the global coordinates of the given point, taken relatively to this working plane"
- vx = DraftVecUtils.scale(self.u,point.x)
- vy = DraftVecUtils.scale(self.v,point.y)
- vz = DraftVecUtils.scale(self.axis,point.z)
+ vx = Vector(self.u).multiply(point.x)
+ vy = Vector(self.v).multiply(point.y)
+ vz = Vector(self.axis).multiply(point.z)
pt = (vx.add(vy)).add(vz)
return pt.add(self.position)
@@ -275,9 +285,9 @@ class plane:
def getGlobalRot(self,point):
"Same as getGlobalCoords, but discards the WP position"
- vx = DraftVecUtils.scale(self.u,point.x)
- vy = DraftVecUtils.scale(self.v,point.y)
- vz = DraftVecUtils.scale(self.axis,point.z)
+ vx = Vector(self.u).multiply(point.x)
+ vy = Vector(self.v).multiply(point.y)
+ vz = Vector(self.axis).multiply(point.z)
pt = (vx.add(vy)).add(vz)
return pt
@@ -286,9 +296,9 @@ class plane:
ax = point.getAngle(self.u)
ay = point.getAngle(self.v)
az = point.getAngle(self.axis)
- bx = point.getAngle(DraftVecUtils.neg(self.u))
- by = point.getAngle(DraftVecUtils.neg(self.v))
- bz = point.getAngle(DraftVecUtils.neg(self.axis))
+ bx = point.getAngle(self.u.negative())
+ by = point.getAngle(self.v.negative())
+ bz = point.getAngle(self.axis.negative())
b = min(ax,ay,az,bx,by,bz)
if b in [ax,bx]:
return "x"
diff --git a/src/Mod/Draft/importDWG.py b/src/Mod/Draft/importDWG.py
index f976b1a01..f0f39b35a 100644
--- a/src/Mod/Draft/importDWG.py
+++ b/src/Mod/Draft/importDWG.py
@@ -30,16 +30,20 @@ if open.__module__ == '__builtin__':
def open(filename):
"called when freecad opens a file."
dxf = convertToDxf(filename)
- import importDXF
- doc = importDXF.open(dxf)
- return doc
+ if dxf:
+ import importDXF
+ doc = importDXF.open(dxf)
+ return doc
+ return
def insert(filename,docname):
"called when freecad imports a file"
dxf = convertToDxf(filemname)
- import importDXF
- doc = importDXF.insert(dxf,docname)
- return doc
+ if dxf:
+ import importDXF
+ doc = importDXF.insert(dxf,docname)
+ return doc
+ return
def export(objectslist,filename):
"called when freecad exports a file"
@@ -51,44 +55,64 @@ def export(objectslist,filename):
return filename
def getTeighaConverter():
+ import FreeCAD,os,platform
"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
+ p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
+ p = p.GetString("TeighaFileConverter")
+ if p:
+ # path set manually
+ teigha = p
+ else:
+ # try to find teigha
+ 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
+ from DraftTools import translate
+ FreeCAD.Console.PrintMessage(str(translate("draft","Teigha File Converter not found, DWG support is disabled.\n")))
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"
+ if teigha:
+ 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)
+ result = outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
+ if os.path.exists(result):
+ print "Conversion successful"
+ return result
+ else:
+ print "Error during DWG to DXF conversion. Try moving the DWG file to a directory path"
+ print "without spaces and non-english characters, or try saving to a lower DWG version"
+ return None
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
+ if teigha:
+ 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
+ return None
+
diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py
index 494c5166e..467e8d9a1 100644
--- a/src/Mod/Draft/importDXF.py
+++ b/src/Mod/Draft/importDXF.py
@@ -39,6 +39,8 @@ lines, polylines, lwpolylines, circles, arcs,
texts, colors,layers (from groups)
'''
+TEXTSCALING = 1.35 # scaling factor between autocad font sizes and coin font sizes
+
import sys, FreeCAD, os, Part, math, re, string, Mesh, Draft, DraftVecUtils, DraftGeomUtils
from Draft import _Dimension, _ViewProviderDimension
from FreeCAD import Vector
@@ -86,34 +88,24 @@ def deformat(text):
"removes weird formats in texts and wipes UTF characters"
# remove ACAD string formatation
#t = re.sub('{([^!}]([^}]|\n)*)}', '', text)
+ print "input text: ",text
t = text.strip("{}")
t = re.sub("\\\.*?;","",t)
- # replace UTF codes
- t = re.sub("\\\\U\+00e9","e",t)
- t = re.sub("\\\\U\+00e1","a",t)
- t = re.sub("\\\\U\+00e7","c",t)
- t = re.sub("\\\\U\+00e3","a",t)
- t = re.sub("\\\\U\+00e0","a",t)
- t = re.sub("\\\\U\+00c1","A",t)
- t = re.sub("\\\\U\+00ea","e",t)
- # replace non-UTF chars
- t = re.sub("ã","a",t)
- t = re.sub("ç","c",t)
- t = re.sub("õ","o",t)
- t = re.sub("Ã ","a",t)
- t = re.sub("á","a",t)
- t = re.sub("â","a",t)
- t = re.sub("é","e",t)
- t = re.sub("è","e",t)
- t = re.sub("ê","e",t)
- t = re.sub("Ã","i",t)
- t = re.sub("Ã","A",t)
- t = re.sub("À","A",t)
- t = re.sub("É","E",t)
- t = re.sub("È","E",t)
+ # replace UTF codes by utf chars
+ sts = re.split("\\\\(U\+....)",t)
+ ns = u""
+ for ss in sts:
+ print ss, type(ss)
+ if ss.startswith("U+"):
+ ucode = "0x"+ss[2:]
+ ns += unichr(eval(ucode))
+ else:
+ ns += ss.decode("utf8")
+ t = ns
# replace degrees, diameters chars
t = re.sub('%%d','°',t)
t = re.sub('%%c','Ø',t)
+ print "output text: ",t
return t
def locateLayer(wantedLayer):
@@ -145,10 +137,10 @@ def calcBulge(v1,bulge,v2):
'''
chord = v2.sub(v1)
sagitta = (bulge * chord.Length)/2
- startpoint = v1.add(DraftVecUtils.scale(chord,0.5))
perp = chord.cross(Vector(0,0,1))
+ startpoint = v1.add(chord.multiply(0.5))
if not DraftVecUtils.isNull(perp): perp.normalize()
- endpoint = DraftVecUtils.scale(perp,sagitta)
+ endpoint = perp.multiply(sagitta)
return startpoint.add(endpoint)
def getGroup(ob):
@@ -215,6 +207,7 @@ class fcformat:
self.stdSize = params.GetBool("dxfStdSize")
self.importDxfHatches = params.GetBool("importDxfHatches")
self.renderPolylineWidth = params.GetBool("renderPolylineWidth")
+ self.importPoints = params.GetBool("dxfImportPoints")
bparams = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View")
if self.paramstyle > 1:
@@ -231,7 +224,7 @@ class fcformat:
v1 = FreeCAD.Vector(r1,g1,b1)
v2 = FreeCAD.Vector(r2,g2,b2)
v = v2.sub(v1)
- v = DraftVecUtils.scale(v,0.5)
+ v.multiply(0.5)
cv = v1.add(v)
else:
c1 = bparams.GetUnsigned("BackgroundColor")
@@ -260,13 +253,13 @@ class fcformat:
if self.paramstyle == 3:
parammappingfile = params.GetString("dxfmappingfile")
self.table = self.buildTable(parammappingfile)
-
+
def buildTable(self,tablefile):
"builds a table for converting colors into linewidths"
try: f = pythonopen(tablefile)
except ValueError:
- print "error: ",tablefile, " not found"
- return None
+ print "error: ",tablefile, " not found"
+ return None
table = {}
header = len(f.readline().split("\t"))
if header == 15:
@@ -300,13 +293,12 @@ class fcformat:
table = None
print table
return table
-
+
def formatObject(self,obj,dxfobj=None):
"applies color and linetype to objects"
- if self.paramstyle == 0:
- if hasattr(obj.ViewObject,"TextColor"):
- obj.ViewObject.TextColor = (0.0,0.0,0.0)
- elif self.paramstyle == 1:
+ if hasattr(obj.ViewObject,"TextColor"):
+ obj.ViewObject.TextColor = (0.0,0.0,0.0)
+ if self.paramstyle == 1:
if hasattr(obj.ViewObject,"TextColor"):
obj.ViewObject.TextColor = self.col
else:
@@ -479,6 +471,38 @@ def drawCircle(circle,shapemode=False):
except:
warn(circle)
return None
+
+def drawEllipse(ellipse):
+ "returns a Part shape from a dxf arc"
+
+ try:
+ c = vec(ellipse.loc)
+ start = round(ellipse.start_angle,prec())
+ end = round(ellipse.end_angle,prec())
+ majv = vec(ellipse.major)
+ majr = majv.Length
+ minr = majr*ellipse.ratio
+ el = Part.Ellipse(vec((0,0,0)),majr,minr)
+ x = majv.normalize()
+ z = vec(ellipse.extrusion).normalize()
+ y = z.cross(x)
+ m = DraftVecUtils.getPlaneRotation(x,y,z)
+ pl = FreeCAD.Placement(m)
+ pl.move(c)
+ if (fmt.paramstyle >= 4) and (not shapemode):
+ if (start != 0.0) or ((end != 0.0) or (end != round(math.pi/2,prec()))):
+ shape = el.toShape(start,end)
+ shape.Placement = pl
+ return shape
+ else:
+ return Draft.makeEllipse(majr,minr,pl)
+ else:
+ shape = el.toShape(start,end)
+ shape.Placement = pl
+ return shape
+ except:
+ warn(arc)
+ return None
def drawFace(face):
"returns a Part face from a list of points"
@@ -605,7 +629,7 @@ def drawSpline(spline,shapemode=False):
warn(spline)
return None
-def drawBlock(blockref,num=None):
+def drawBlock(blockref,num=None,createObject=False):
"returns a shape from a dxf block reference"
if not fmt.paramstarblocks:
if blockref.name[0] == '*':
@@ -650,31 +674,52 @@ def drawBlock(blockref,num=None):
except: warn(blockref)
if shape:
blockshapes[blockref.name]=shape
+ if createObject:
+ newob=doc.addObject("Part::Feature",blockref.name)
+ newob.Shape = shape
+ blockobjects[blockref.name] = newob
+ return newob
return shape
return None
-def drawInsert(insert,num=None):
- if blockshapes.has_key(insert):
- shape = blockshapes[insert.block].copy()
- else:
- shape = None
- for b in drawing.blocks.data:
- if b.name == insert.block:
- shape = drawBlock(b,num)
+def drawInsert(insert,num=None,clone=False):
if fmt.paramtext:
attrs = attribs(insert)
for a in attrs:
addText(a,attrib=True)
- if shape:
- pos = vec(insert.loc)
- rot = math.radians(insert.rotation)
- scale = insert.scale
- tsf = FreeCAD.Matrix()
- tsf.scale(scale[0],scale[1],0) # for some reason z must be 0 to work
- tsf.rotateZ(rot)
- shape = shape.transformGeometry(tsf)
- shape.translate(pos)
- return shape
+ if clone:
+ if blockobjects.has_key(insert.block):
+ newob = Draft.clone(blockobjects[insert.block])
+ tsf = FreeCAD.Matrix()
+ rot = math.radians(insert.rotation)
+ pos = vec(insert.loc)
+ tsf.move(pos)
+ tsf.rotateZ(rot)
+ sc = insert.scale
+ sc = FreeCAD.Vector(sc[0],sc[1],0)
+ newob.Placement = FreeCAD.Placement(tsf)
+ newob.Scale = sc
+ return newob
+ else:
+ shape = None
+ else:
+ if blockshapes.has_key(insert):
+ shape = blockshapes[insert.block].copy()
+ else:
+ shape = None
+ for b in drawing.blocks.data:
+ if b.name == insert.block:
+ shape = drawBlock(b,num)
+ if shape:
+ pos = vec(insert.loc)
+ rot = math.radians(insert.rotation)
+ scale = insert.scale
+ tsf = FreeCAD.Matrix()
+ tsf.scale(scale[0],scale[1],0) # for some reason z must be 0 to work
+ tsf.rotateZ(rot)
+ shape = shape.transformGeometry(tsf)
+ shape.translate(pos)
+ return shape
return None
def drawLayerBlock(objlist):
@@ -743,28 +788,54 @@ def addText(text,attrib=False):
newob = doc.addObject("App::Annotation","Text")
lay.addObject(newob)
val = deformat(val)
- #val = val.decode("Latin1").encode("Latin1")
+ # the following stores text as Latin1 in annotations, which
+ # displays ok in coin texts, but causes errors later on.
+ # better store as utf8 always.
+ #try:
+ # val = val.decode("utf8").encode("Latin1")
+ #except:
+ # try:
+ # val = val.encode("latin1")
+ # except:
+ # pass
rx = rawValue(text,11)
ry = rawValue(text,21)
rz = rawValue(text,31)
+ xv = Vector(1,0,0)
+ ax = Vector(0,0,1)
if rx or ry or rz:
xv = Vector(rx,ry,rz)
if not DraftVecUtils.isNull(xv):
- ax = DraftVecUtils.neg(xv.cross(Vector(1,0,0)))
+ ax = (xv.cross(Vector(1,0,0))).negative()
if DraftVecUtils.isNull(ax):
ax = Vector(0,0,1)
ang = -math.degrees(DraftVecUtils.angle(xv,Vector(1,0,0),ax))
Draft.rotate(newob,ang,axis=ax)
+ if ax == Vector(0,0,-1): ax = Vector(0,0,1)
elif hasattr(text,"rotation"):
if text.rotation:
Draft.rotate(newob,text.rotation)
+ if attrib:
+ attrot = rawValue(text,50)
+ if attrot:
+ Draft.rotate(newob,attrot)
newob.LabelText = val.split("\n")
+ if gui and fmt.stdSize:
+ fsize = FreeCADGui.draftToolBar.fontsize
+ else:
+ fsize = float(hgt)*TEXTSCALING
+ if hasattr(text,"alignment"):
+ yv = ax.cross(xv)
+ if text.alignment in [1,2,3]:
+ sup = DraftVecUtils.scaleTo(yv,fsize/TEXTSCALING).negative()
+ print ax,sup
+ pos = pos.add(sup)
+ elif text.alignment in [4,5,6]:
+ sup = DraftVecUtils.scaleTo(yv,fsize/(2*TEXTSCALING)).negative()
+ pos = pos.add(sup)
newob.Position = pos
if gui:
- if fmt.stdSize:
- newob.ViewObject.FontSize = FreeCADGui.draftToolBar.fontsize
- else:
- newob.ViewObject.FontSize = float(hgt)
+ newob.ViewObject.FontSize = fsize
if hasattr(text,"alignment"):
if text.alignment in [2,5,8]:
newob.ViewObject.Justification = "Center"
@@ -791,6 +862,8 @@ def processdxf(document,filename):
doc = document
global blockshapes
blockshapes = {}
+ global blockobjects
+ blockobjects = {}
global badobjects
badobjects = []
global layerBlocks
@@ -830,7 +903,7 @@ def processdxf(document,filename):
else:
newob = addObject(shape,"Line",line.layer)
if gui: fmt.formatObject(newob,line)
-
+
# drawing polylines
pls = drawing.entities.get_type("lwpolyline")
@@ -876,7 +949,7 @@ def processdxf(document,filename):
newob = addObject(shape,"Polyline",polyline.layer)
if gui: fmt.formatObject(newob,polyline)
num += 1
-
+
# drawing arcs
arcs = drawing.entities.get_type("arc")
@@ -968,6 +1041,21 @@ def processdxf(document,filename):
else:
newob = addObject(shape,"Spline",lay)
if gui: fmt.formatObject(newob,spline)
+
+ # drawing ellipses
+
+ ellipses = drawing.entities.get_type("ellipse")
+ if ellipses: FreeCAD.Console.PrintMessage("drawing "+str(len(ellipses))+" ellipses...\n")
+ for ellipse in ellipses:
+ lay = rawValue(ellipse,8)
+ if fmt.dxflayout or (not rawValue(ellipse,67)):
+ shape = drawEllipse(ellipse)
+ if shape:
+ if fmt.makeBlocks:
+ addToBlock(shape,lay)
+ else:
+ newob = addObject(shape,"Ellipse",lay)
+ if gui: fmt.formatObject(newob,ellipse)
# drawing texts
@@ -979,7 +1067,7 @@ def processdxf(document,filename):
for text in texts:
if fmt.dxflayout or (not rawValue(text,67)):
addText(text)
-
+
else: FreeCAD.Console.PrintMessage("skipping texts...\n")
# drawing 3D objects
@@ -1032,6 +1120,12 @@ def processdxf(document,filename):
pt = FreeCAD.Vector(x1,y1,z1)
p1 = FreeCAD.Vector(x2,y2,z2)
p2 = FreeCAD.Vector(x3,y3,z3)
+ if align >= 128:
+ align -= 128
+ elif align >= 64:
+ align -= 64
+ elif align >= 32:
+ align -= 32
if align == 0:
if angle in [0,180]:
p2 = FreeCAD.Vector(x3,y2,z2)
@@ -1052,29 +1146,32 @@ def processdxf(document,filename):
newob.ViewObject.FontSize = FreeCADGui.draftToolBar.fontsize
else:
st = rawValue(dim,3)
- newob.ViewObject.FontSize = float(getdimheight(st))
-
- else: FreeCAD.Console.PrintMessage("skipping dimensions...\n")
+ newob.ViewObject.FontSize = float(getdimheight(st))*TEXTSCALING
+ else:
+ FreeCAD.Console.PrintMessage("skipping dimensions...\n")
# drawing points
- points = drawing.entities.get_type("point")
- if points: FreeCAD.Console.PrintMessage("drawing "+str(len(points))+" points...\n")
- for point in points:
- x = rawValue(point,10)
- y = rawValue(point,20)
- z = rawValue(point,30)
- lay = rawValue(point,8)
- if fmt.dxflayout or (not rawValue(point,67)):
- if fmt.makeBlocks:
- shape = Part.Vertex(x,y,z)
- addToBlock(shape,lay)
- else:
- newob = Draft.makePoint(x,y,z)
- lay = locateLayer(lay)
- lay.addObject(newob)
- if gui:
- fmt.formatObject(newob,point)
+ if fmt.importPoints:
+ points = drawing.entities.get_type("point")
+ if points: FreeCAD.Console.PrintMessage("drawing "+str(len(points))+" points...\n")
+ for point in points:
+ x = rawValue(point,10)
+ y = rawValue(point,20)
+ z = rawValue(point,30)
+ lay = rawValue(point,8)
+ if fmt.dxflayout or (not rawValue(point,67)):
+ if fmt.makeBlocks:
+ shape = Part.Vertex(x,y,z)
+ addToBlock(shape,lay)
+ else:
+ newob = Draft.makePoint(x,y,z)
+ lay = locateLayer(lay)
+ lay.addObject(newob)
+ if gui:
+ fmt.formatObject(newob,point)
+ else:
+ FreeCAD.Console.PrintMessage("skipping points...\n")
# drawing leaders
@@ -1139,10 +1236,16 @@ def processdxf(document,filename):
FreeCAD.Console.PrintMessage("drawing "+str(len(inserts))+" blocks...\n")
blockrefs = drawing.blocks.data
for ref in blockrefs:
- drawBlock(ref)
+ if fmt.paramstyle >= 4:
+ drawBlock(ref,createObject=True)
+ else:
+ drawBlock(ref,createObject=False)
num = 0
for insert in inserts:
- shape = drawInsert(insert,num)
+ if (fmt.paramstyle >= 4) and not(fmt.makeBlocks):
+ shape = drawInsert(insert,num,clone=True)
+ else:
+ shape = drawInsert(insert,num)
if shape:
if fmt.makeBlocks:
addToBlock(shape,insert.layer)
@@ -1160,7 +1263,14 @@ def processdxf(document,filename):
if shape:
newob = addObject(shape,k)
del layerBlocks
-
+
+ # hide block objects, if any
+
+ for k,o in blockobjects.iteritems():
+ if o.ViewObject:
+ o.ViewObject.hide()
+ del blockobjects
+
# finishing
print "done processing"
@@ -1396,6 +1506,22 @@ def writeShape(sh,ob,dxfobject,nospline=False):
dxfobject.append(dxfLibrary.Arc(center, radius,
ang1, ang2, color=getACI(ob),
layer=getGroup(ob)))
+ elif DraftGeomUtils.geomType(edge) == "Ellipse": # ellipses:
+ if hasattr(dxfLibrary,"Ellipse"):
+ center = DraftVecUtils.tup(edge.Curve.Center)
+ norm = DraftVecUtils.tup(edge.Curve.Axis)
+ start = edge.FirstParameter
+ end = edge.LastParameter
+ ax = edge.Curve.Focus1.sub(edge.Curve.Center)
+ major = DraftVecUtils.tup(DraftVecUtils.scaleTo(ax,edge.Curve.MajorRadius))
+ minor = edge.Curve.MinorRadius/edge.Curve.MajorRadius
+ dxfobject.append(dxfLibrary.Ellipse(center=center,majorAxis=major,normalAxis=norm,
+ minorAxisRatio=minor,startParameter=start,
+ endParameter=end,
+ color=getACI(ob),
+ layer=getGroup(ob)))
+ else:
+ FreeCAD.Console.PrintWarning("Ellipses support not found. Please delete dxfLibrary.py from your FreeCAD user directory to force auto-update\n")
else: # anything else is treated as lines
if len(edge.Vertexes) > 1:
ve1=edge.Vertexes[0].Point
@@ -1424,7 +1550,11 @@ def export(objectslist,filename,nospline=False):
global exportList
exportList = objectslist
+ print exportList
+
exportList = Draft.getGroupContents(exportList)
+
+ print exportList
if (len(exportList) == 1) and (Draft.getType(exportList[0]) == "ArchSectionView"):
# arch view: export it "as is"
@@ -1500,7 +1630,7 @@ def export(objectslist,filename,nospline=False):
if not proj:
pbase = DraftVecUtils.tup(ob.End)
else:
- pbase = DraftVecUtils.tup(ob.End.add(DraftVecUtils.neg(proj)))
+ pbase = DraftVecUtils.tup(ob.End.add(proj.negative()))
dxf.append(dxfLibrary.Dimension(pbase,p1,p2,color=getACI(ob),
layer=getGroup(ob)))
diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py
index 4eb5f3752..0b011e6a7 100644
--- a/src/Mod/Draft/importSVG.py
+++ b/src/Mod/Draft/importSVG.py
@@ -320,7 +320,7 @@ def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False):
rx = float(rx)
ry = float(ry)
v0 = lastvec.sub(currentvec)
- v0 = v0.multiply(0.5)
+ v0.multiply(0.5)
m1=FreeCAD.Matrix()
m1.rotateZ(-xrotation) #Formular 6.5.1
v1=m1.multiply(v0)
@@ -335,19 +335,19 @@ def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False):
results=[]
if abs(numer/denom) < 10**(-1*(Draft.precision())):
scalefacpos = 0
- else:
- try:
- scalefacpos = math.sqrt(numer/denom)
- except ValueError:
+ else:
+ try:
+ scalefacpos = math.sqrt(numer/denom)
+ except ValueError:
FreeCAD.Console.PrintMessage('sqrt(%f/%f)\n' % (numer,denom))
- scalefacpos = 0
+ scalefacpos = 0
for scalefacsign in (1,-1):
scalefac = scalefacpos * scalefacsign
vcx1 = Vector(v1.y*rx/ry,-v1.x*ry/rx,0).multiply(scalefac) # Step2 F.6.5.2
m2=FreeCAD.Matrix()
m2.rotateZ(xrotation)
centeroff = currentvec.add(lastvec)
- centeroff = DraftVecUtils.scale(centeroff,.5)
+ centeroff.multiply(.5)
vcenter = m2.multiply(vcx1).add(centeroff) # Step3 F.6.5.3
#angle1 = Vector(1,0,0).getAngle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5
#angledelta = Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0).getAngle(Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6
@@ -359,19 +359,19 @@ def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False):
def 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)
- return "#"+r+g+b
+ "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)
+ return "#"+r+g+b
class svgHandler(xml.sax.ContentHandler):
- "this handler parses the svg files and creates freecad objects"
+ "this handler parses the svg files and creates freecad objects"
- def __init__(self):
- "retrieving Draft parameters"
- params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
- self.style = params.GetInt("svgstyle")
+ def __init__(self):
+ "retrieving Draft parameters"
+ params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
+ self.style = params.GetInt("svgstyle")
self.count = 0
self.transform = None
self.grouptransform = []
@@ -380,42 +380,44 @@ class svgHandler(xml.sax.ContentHandler):
global Part
import Part
-
- if gui and draftui:
- r = float(draftui.color.red()/255.0)
- g = float(draftui.color.green()/255.0)
- b = float(draftui.color.blue()/255.0)
- self.lw = float(draftui.linewidth)
- else:
- self.lw = float(params.GetInt("linewidth"))
- c = params.GetUnsigned("color")
- r = float(((c>>24)&0xFF)/255)
- g = float(((c>>16)&0xFF)/255)
- b = float(((c>>8)&0xFF)/255)
- self.col = (r,g,b,0.0)
+
+ if gui and draftui:
+ r = float(draftui.color.red()/255.0)
+ g = float(draftui.color.green()/255.0)
+ b = float(draftui.color.blue()/255.0)
+ self.lw = float(draftui.linewidth)
+ else:
+ self.lw = float(params.GetInt("linewidth"))
+ c = params.GetUnsigned("color")
+ r = float(((c>>24)&0xFF)/255)
+ g = float(((c>>16)&0xFF)/255)
+ b = float(((c>>8)&0xFF)/255)
+ self.col = (r,g,b,0.0)
- def format(self,obj):
- "applies styles to passed object"
- if self.style and gui:
- v = obj.ViewObject
- if self.color: v.LineColor = self.color
- if self.width: v.LineWidth = self.width
- if self.fill: v.ShapeColor = self.fill
-
- def startElement(self, name, attrs):
+ def format(self,obj):
+ "applies styles to passed object"
+ if self.style and gui:
+ v = obj.ViewObject
+ if self.color: v.LineColor = self.color
+ if self.width: v.LineWidth = self.width
+ if self.fill: v.ShapeColor = self.fill
+
+ def startElement(self, name, attrs):
- # reorganizing data into a nice clean dictionary
+ # reorganizing data into a nice clean dictionary
self.count += 1
FreeCAD.Console.PrintMessage('processing element %d: %s\n'%(self.count,name))
FreeCAD.Console.PrintMessage('existing group transform: %s\n'%(str(self.grouptransform)))
-
- data = {}
- for (keyword,content) in attrs.items():
- content = content.replace(',',' ')
- content = content.split()
- data[keyword]=content
+
+ data = {}
+ for (keyword,content) in attrs.items():
+ #print keyword,content
+ content = content.replace(',',' ')
+ content = content.split()
+ #print keyword,content
+ data[keyword]=content
if 'style' in data:
if not data['style']:
@@ -425,24 +427,27 @@ class svgHandler(xml.sax.ContentHandler):
content = content.split(';')
for i in content:
pair = i.split(':')
- if len(pair)>1: data[pair[0]]=pair[1]
+ if len(pair)>1: data[pair[0]]=pair[1]
- for k in ['x','y','x1','y1','x2','y2','r','rx','ry','cx','cy','width','height']:
- if k in data:
- data[k] = getsize(data[k][0],'css')
+ for k in ['x','y','x1','y1','x2','y2','r','rx','ry','cx','cy','width','height']:
+ if k in data:
+ data[k] = getsize(data[k][0],'css')
- for k in ['fill','stroke','stroke-width','font-size']:
- if k in data:
- if isinstance(data[k],list):
- data[k]=data[k][0]
+ for k in ['fill','stroke','stroke-width','font-size']:
+ if k in data:
+ if isinstance(data[k],list):
+ if data[k][0].lower().startswith("rgb("):
+ data[k] = ",".join(data[k])
+ else:
+ data[k]=data[k][0]
- # extracting style info
-
- self.fill = None
- self.color = None
- self.width = None
- self.text = None
-
+ # extracting style info
+
+ self.fill = None
+ self.color = None
+ self.width = None
+ self.text = None
+
if name == 'svg':
m=FreeCAD.Matrix()
if 'width' in data and 'height' in data and \
@@ -481,16 +486,16 @@ class svgHandler(xml.sax.ContentHandler):
#fallback to 90 dpi
m.scale(Vector(25.4/90.0,25.4/90.0,1))
self.grouptransform.append(m)
- if 'fill' in data:
- if data['fill'][0] != 'none':
- self.fill = getcolor(data['fill'])
- if 'stroke' in data:
- if data['stroke'][0] != 'none':
- self.color = getcolor(data['stroke'])
- if 'stroke-width' in data:
- if data['stroke-width'] != 'none':
- self.width = getsize(data['stroke-width'],'css')
- if 'transform' in data:
+ if 'fill' in data:
+ if data['fill'][0] != 'none':
+ self.fill = getcolor(data['fill'])
+ if 'stroke' in data:
+ if data['stroke'][0] != 'none':
+ self.color = getcolor(data['stroke'])
+ if 'stroke-width' in data:
+ if data['stroke-width'] != 'none':
+ self.width = getsize(data['stroke-width'],'css')
+ if 'transform' in data:
m = self.getMatrix(attrs.getValue('transform'))
if name == "g":
self.grouptransform.append(m)
@@ -500,29 +505,29 @@ class svgHandler(xml.sax.ContentHandler):
if name == "g":
self.grouptransform.append(FreeCAD.Matrix())
- if (self.style == 1):
- self.color = self.col
- self.width = self.lw
+ if (self.style == 1):
+ self.color = self.col
+ self.width = self.lw
pathname = None
if 'id' in data:
pathname = data['id'][0]
FreeCAD.Console.PrintMessage('name: %s\n'%pathname)
- # processing paths
+ # processing paths
- if name == "path":
+ if name == "path":
FreeCAD.Console.PrintMessage('data: %s\n'%str(data))
if not pathname: pathname = 'Path'
- path = []
- point = []
- lastvec = Vector(0,0,0)
- lastpole = None
- command = None
- relative = False
- firstvec = None
+ path = []
+ point = []
+ lastvec = Vector(0,0,0)
+ lastpole = None
+ command = None
+ relative = False
+ firstvec = None
if "freecad:basepoint1" in data:
p1 = data["freecad:basepoint1"]
@@ -616,11 +621,11 @@ class svgHandler(xml.sax.ContentHandler):
else:
# anticlockwise
perp = DraftVecUtils.rotate2D(chord,math.pi/2)
- chord = DraftVecUtils.scale(chord,.5)
+ chord.multiply(.5)
if chord.Length > rx: a = 0
else: a = math.sqrt(rx**2-chord.Length**2)
s = rx - a
- perp = DraftVecUtils.scale(perp,s/perp.Length)
+ perp.multiply(s/perp.Length)
midpoint = lastvec.add(chord.add(perp))
seg = Part.Arc(lastvec,midpoint,currentvec).toShape()
else:# big arc or elliptical arc
@@ -748,7 +753,11 @@ class svgHandler(xml.sax.ContentHandler):
path.append(seg)
elif (d == "Z") or (d == "z"):
if not DraftVecUtils.equals(lastvec,firstvec):
+ try:
seg = Part.Line(lastvec,firstvec).toShape()
+ except:
+ pass
+ else:
path.append(seg)
if path: #the path should be closed by now
#sh=makewire(path,True)
@@ -774,9 +783,9 @@ class svgHandler(xml.sax.ContentHandler):
self.format(obj)
- # processing rects
+ # processing rects
- if name == "rect":
+ if name == "rect":
if not pathname: pathname = 'Rectangle'
edges = []
if ('rx' not in data or data['rx'] < 10**(-1*Draft.precision())) and \
@@ -847,37 +856,37 @@ class svgHandler(xml.sax.ContentHandler):
self.format(obj)
# processing lines
- if name == "line":
+ if name == "line":
if not pathname: pathname = 'Line'
- p1 = Vector(data['x1'],-data['y1'],0)
- p2 = Vector(data['x2'],-data['y2'],0)
- sh = Part.Line(p1,p2).toShape()
+ p1 = Vector(data['x1'],-data['y1'],0)
+ p2 = Vector(data['x2'],-data['y2'],0)
+ sh = Part.Line(p1,p2).toShape()
sh = self.applyTrans(sh)
- obj = self.doc.addObject("Part::Feature",pathname)
- obj.Shape = sh
- self.format(obj)
+ obj = self.doc.addObject("Part::Feature",pathname)
+ obj.Shape = sh
+ self.format(obj)
# processing polylines and polygons
- if name == "polyline" or name == "polygon":
- '''a simpler implementation would be sh = Part.makePolygon([Vector(svgx,-svgy,0) for svgx,svgy in zip(points[0::2],points[1::2])])
- but there would be more difficlult to search for duplicate points beforehand.'''
- if not pathname: pathname = 'Polyline'
- points=[float(d) for d in data['points']]
+ if name == "polyline" or name == "polygon":
+ '''a simpler implementation would be sh = Part.makePolygon([Vector(svgx,-svgy,0) for svgx,svgy in zip(points[0::2],points[1::2])])
+ but there would be more difficlult to search for duplicate points beforehand.'''
+ if not pathname: pathname = 'Polyline'
+ points=[float(d) for d in data['points']]
FreeCAD.Console.PrintMessage('points %s\n'%str(points))
- lenpoints=len(points)
- if lenpoints>=4 and lenpoints % 2 == 0:
- lastvec = Vector(points[0],-points[1],0)
- path=[]
+ lenpoints=len(points)
+ if lenpoints>=4 and lenpoints % 2 == 0:
+ lastvec = Vector(points[0],-points[1],0)
+ path=[]
if name == 'polygon':
points=points+points[:2] # emulate closepath
- for svgx,svgy in zip(points[2::2],points[3::2]):
- currentvec = Vector(svgx,-svgy,0)
- if not DraftVecUtils.equals(lastvec,currentvec):
- seg = Part.Line(lastvec,currentvec).toShape()
- #print "polyline seg ",lastvec,currentvec
- lastvec = currentvec
- path.append(seg)
+ for svgx,svgy in zip(points[2::2],points[3::2]):
+ currentvec = Vector(svgx,-svgy,0)
+ if not DraftVecUtils.equals(lastvec,currentvec):
+ seg = Part.Line(lastvec,currentvec).toShape()
+ #print "polyline seg ",lastvec,currentvec
+ lastvec = currentvec
+ path.append(seg)
if path:
sh = Part.Wire(path)
if self.fill and sh.isClosed():
@@ -908,9 +917,9 @@ class svgHandler(xml.sax.ContentHandler):
sh = Part.Wire([sh])
sh = Part.Face(sh)
sh = self.applyTrans(sh)
- obj = self.doc.addObject("Part::Feature",pathname)
- obj.Shape = sh
- self.format(obj)
+ obj = self.doc.addObject("Part::Feature",pathname)
+ obj.Shape = sh
+ self.format(obj)
# processing circles
@@ -925,13 +934,13 @@ class svgHandler(xml.sax.ContentHandler):
sh = Part.Face(sh)
sh.translate(c)
sh = self.applyTrans(sh)
- obj = self.doc.addObject("Part::Feature",pathname)
- obj.Shape = sh
- self.format(obj)
+ obj = self.doc.addObject("Part::Feature",pathname)
+ obj.Shape = sh
+ self.format(obj)
# processing texts
- if name in ["text","tspan"]:
+ if name in ["text","tspan"]:
if not("freecad:skip" in data):
FreeCAD.Console.PrintMessage("processing a text\n")
if 'x' in data:
@@ -953,12 +962,12 @@ class svgHandler(xml.sax.ContentHandler):
FreeCAD.Console.PrintMessage("done processing element %d\n"%self.count)
- def characters(self,content):
- if self.text:
+ def characters(self,content):
+ if self.text:
FreeCAD.Console.PrintMessage("reading characters %s\n" % str(content))
- obj=self.doc.addObject("App::Annotation",'Text')
- obj.LabelText = content.encode('latin1')
- vec = Vector(self.x,-self.y,0)
+ obj=self.doc.addObject("App::Annotation",'Text')
+ obj.LabelText = content.encode('latin1')
+ vec = Vector(self.x,-self.y,0)
if self.transform:
vec = self.translateVec(vec,self.transform)
#print "own transform: ",self.transform, vec
@@ -967,10 +976,10 @@ class svgHandler(xml.sax.ContentHandler):
vec = transform.multiply(vec)
#print "applying vector: ",vec
obj.Position = vec
- if gui:
- obj.ViewObject.FontSize = int(self.text)
- if self.fill: obj.ViewObject.TextColor = self.fill
- else: obj.ViewObject.TextColor = (0.0,0.0,0.0,0.0)
+ if gui:
+ obj.ViewObject.FontSize = int(self.text)
+ if self.fill: obj.ViewObject.TextColor = self.fill
+ else: obj.ViewObject.TextColor = (0.0,0.0,0.0,0.0)
def endElement(self, name):
if not name in ["tspan"]:
@@ -1010,41 +1019,41 @@ class svgHandler(xml.sax.ContentHandler):
def getMatrix(self,tr):
"returns a FreeCAD matrix from a svg transform attribute"
- transformre=re.compile('(matrix|translate|scale|rotate|skewX|skewY)\s*?\((.*?)\)',re.DOTALL)
+ transformre=re.compile('(matrix|translate|scale|rotate|skewX|skewY)\s*?\((.*?)\)',re.DOTALL)
m = FreeCAD.Matrix()
for transformation, arguments in transformre.findall(tr):
- argsplit=[float(arg) for arg in arguments.replace(',',' ').split()]
+ argsplit=[float(arg) for arg in arguments.replace(',',' ').split()]
#m.multiply(FreeCAD.Matrix (1,0,0,0,0,-1))
#print '%s:%s %s %d' % (transformation, arguments,argsplit,len(argsplit))
- if transformation == 'translate':
- tx = argsplit[0]
- ty = argsplit[1] if len(argsplit) > 1 else 0.0
- m.move(Vector(tx,-ty,0))
- elif transformation == 'scale':
- sx = argsplit[0]
- sy = argsplit[1] if len(argsplit) > 1 else sx
- m.scale(Vector(sx,sy,1))
- elif transformation == 'rotate':
- angle = argsplit[0]
- if len(argsplit) >= 3:
- cx = argsplit[1]
- cy = argsplit[2]
- m.move(Vector(cx,-cy,0))
+ if transformation == 'translate':
+ tx = argsplit[0]
+ ty = argsplit[1] if len(argsplit) > 1 else 0.0
+ m.move(Vector(tx,-ty,0))
+ elif transformation == 'scale':
+ sx = argsplit[0]
+ sy = argsplit[1] if len(argsplit) > 1 else sx
+ m.scale(Vector(sx,sy,1))
+ elif transformation == 'rotate':
+ angle = argsplit[0]
+ if len(argsplit) >= 3:
+ cx = argsplit[1]
+ cy = argsplit[2]
+ m.move(Vector(cx,-cy,0))
m.rotateZ(math.radians(-angle)) #mirroring one axis equals changing the direction of rotaion
- if len(argsplit) >= 3:
- m.move(Vector(-cx,cy,0))
- elif transformation == 'skewX':
- m=m.multiply(FreeCAD.Matrix(1,-math.tan(math.radians(argsplit[0]))))
- elif transformation == 'skewY':
- m=m.multiply(FreeCAD.Matrix(1,0,0,0,-math.tan(math.radians(argsplit[0]))))
- elif transformation == 'matrix':
+ if len(argsplit) >= 3:
+ m.move(Vector(-cx,cy,0))
+ elif transformation == 'skewX':
+ m=m.multiply(FreeCAD.Matrix(1,-math.tan(math.radians(argsplit[0]))))
+ elif transformation == 'skewY':
+ m=m.multiply(FreeCAD.Matrix(1,0,0,0,-math.tan(math.radians(argsplit[0]))))
+ elif transformation == 'matrix':
# '''transformation matrix:
# FreeCAD SVG
# (+A -C +0 +E) (A C 0 E)
# (-B +D -0 -F) = (-Y) * (B D 0 F) *(-Y)
# (+0 -0 +1 +0) (0 0 1 0)
# (+0 -0 +0 +1) (0 0 0 1)'''
- m=m.multiply(FreeCAD.Matrix(argsplit[0],-argsplit[2],0,argsplit[4],-argsplit[1],argsplit[3],0,-argsplit[5]))
+ m=m.multiply(FreeCAD.Matrix(argsplit[0],-argsplit[2],0,argsplit[4],-argsplit[1],argsplit[3],0,-argsplit[5]))
#else:
#print 'SKIPPED %s' % transformation
#print "m= ",m
@@ -1052,17 +1061,17 @@ class svgHandler(xml.sax.ContentHandler):
return m
def decodeName(name):
- "decodes encoded strings"
- try:
- decodedName = (name.decode("utf8"))
- except UnicodeDecodeError:
- try:
- decodedName = (name.decode("latin1"))
- except UnicodeDecodeError:
- FreeCAD.Console.PrintError("svg: error: couldn't determine character encoding\n")
+ "decodes encoded strings"
+ try:
+ decodedName = (name.decode("utf8"))
+ except UnicodeDecodeError:
+ try:
+ decodedName = (name.decode("latin1"))
+ except UnicodeDecodeError:
+ FreeCAD.Console.PrintError("svg: error: couldn't determine character encoding\n")
- decodedName = name
- return decodedName
+ decodedName = name
+ return decodedName
def getContents(filename,tag,stringmode=False):
"gets the contents of all the occurences of the given tag in the given file"
@@ -1087,50 +1096,50 @@ def getContents(filename,tag,stringmode=False):
return result
def open(filename):
- docname=os.path.split(filename)[1]
- doc=FreeCAD.newDocument(docname)
- doc.Label = decodeName(docname[:-4])
- parser = xml.sax.make_parser()
- parser.setContentHandler(svgHandler())
- parser._cont_handler.doc = doc
+ docname=os.path.split(filename)[1]
+ doc=FreeCAD.newDocument(docname)
+ doc.Label = decodeName(docname[:-4])
+ parser = xml.sax.make_parser()
+ parser.setContentHandler(svgHandler())
+ parser._cont_handler.doc = doc
f = pythonopen(filename)
- parser.parse(f)
+ parser.parse(f)
f.close()
- doc.recompute()
+ doc.recompute()
return doc
def insert(filename,docname):
- try:
- doc=FreeCAD.getDocument(docname)
- except:
- doc=FreeCAD.newDocument(docname)
- FreeCAD.ActiveDocument = doc
- parser = xml.sax.make_parser()
- parser.setContentHandler(svgHandler())
- parser._cont_handler.doc = doc
- parser.parse(pythonopen(filename))
- doc.recompute()
+ try:
+ doc=FreeCAD.getDocument(docname)
+ except:
+ doc=FreeCAD.newDocument(docname)
+ FreeCAD.ActiveDocument = doc
+ parser = xml.sax.make_parser()
+ parser.setContentHandler(svgHandler())
+ parser._cont_handler.doc = doc
+ parser.parse(pythonopen(filename))
+ doc.recompute()
def export(exportList,filename):
- "called when freecad exports a file"
+ "called when freecad exports a file"
svg_export_style = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetInt("svg_export_style")
if svg_export_style != 0 and svg_export_style != 1:
FreeCAD.Console.PrintMessage("unknown svg export style, switching to Translated\n")
svg_export_style = 0
- # finding sheet size
- minx = 10000
- miny = 10000
- maxx = 0
- maxy = 0
- for ob in exportList:
- if ob.isDerivedFrom("Part::Feature"):
- for v in ob.Shape.Vertexes:
- if v.Point.x < minx: minx = v.Point.x
- if v.Point.x > maxx: maxx = v.Point.x
- if v.Point.y < miny: miny = v.Point.y
- if v.Point.y > maxy: maxy = v.Point.y
+ # finding sheet size
+ minx = 10000
+ miny = 10000
+ maxx = 0
+ maxy = 0
+ for ob in exportList:
+ if ob.isDerivedFrom("Part::Feature"):
+ for v in ob.Shape.Vertexes:
+ if v.Point.x < minx: minx = v.Point.x
+ if v.Point.x > maxx: maxx = v.Point.x
+ if v.Point.y < miny: miny = v.Point.y
+ if v.Point.y > maxy: maxy = v.Point.y
if svg_export_style == 0:
# translated-style exports get a bit of a margin
margin = (maxx-minx)*.01
@@ -1138,23 +1147,23 @@ def export(exportList,filename):
# raw-style exports get no margin
margin = 0
- minx -= margin
- maxx += margin
- miny -= margin
- maxy += margin
- sizex = maxx-minx
- sizey = maxy-miny
- miny += margin
+ minx -= margin
+ maxx += margin
+ miny -= margin
+ maxy += margin
+ sizex = maxx-minx
+ sizey = maxy-miny
+ miny += margin
- # writing header
+ # writing header
# we specify the svg width and height in FreeCAD's physical units (mm),
# and specify the viewBox so that user units maps one-to-one to mm
- svg = pythonopen(filename,'wb')
- svg.write('\n')
- svg.write('\n')
- svg.write('')
+ svg.close()
diff --git a/src/Mod/Import/App/AppImport.cpp b/src/Mod/Import/App/AppImport.cpp
index 77b44caa4..c21b306b2 100644
--- a/src/Mod/Import/App/AppImport.cpp
+++ b/src/Mod/Import/App/AppImport.cpp
@@ -25,47 +25,29 @@
#include "PreCompiled.h"
#ifndef _PreComp_
-# include
-# if defined (_POSIX_C_SOURCE)
-# undef _POSIX_C_SOURCE
-# endif // (re-)defined in pyconfig.h
-# include
#endif
#include
#include
-#include
-#include
-
-#include "FeatureImportStep.h"
-#include "FeatureImportIges.h"
-
/* registration table */
-extern struct PyMethodDef Import_methods[];
+extern struct PyMethodDef Import_Import_methods[];
-
-// python entry
-#ifdef FC_OS_WIN32
-# define ModuleExport __declspec(dllexport)
-#else
-# define ModuleExport
-#endif
extern "C" {
-void ModuleExport initImport() {
+void ImportExport initImport()
+{
+ (void) Py_InitModule("Import", Import_Import_methods); /* mod name, table ptr */
- (void) Py_InitModule("Import", Import_methods); /* mod name, table ptr */
+ try {
+ Base::Interpreter().loadModule("Part");
+ }
+ catch(const Base::Exception& e) {
+ PyErr_SetString(PyExc_ImportError, e.what());
+ return;
+ }
- // load dependend module
- Base::Interpreter().loadModule("Part");
-
- App::AbstractFeatureFactory().AddProducer("ImportStep",new App::AbstractFeatureProducer);
- App::AbstractFeatureFactory().AddProducer("ImportIges",new App::AbstractFeatureProducer);
-
- Base::Console().Log("Import loaded\n");
-
- return;
+ Base::Console().Log("Loading Import module... done\n");
}
diff --git a/src/Mod/Import/App/AppImportPy.cpp b/src/Mod/Import/App/AppImportPy.cpp
index da82ca508..4399f17ba 100644
--- a/src/Mod/Import/App/AppImportPy.cpp
+++ b/src/Mod/Import/App/AppImportPy.cpp
@@ -1,118 +1,264 @@
/***************************************************************************
- * (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
+ * Copyright (c) 2013 Werner Mayer *
* *
* This file is part of the FreeCAD CAx development system. *
* *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Library 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 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. *
* *
- * FreeCAD is distributed in the hope that it will be useful, *
+ * 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 FreeCAD; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
- * USA *
+ * 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 *
* *
- * Juergen Riegel 2002 *
***************************************************************************/
#include "PreCompiled.h"
+#if defined(__MINGW32__)
+# define WNT // avoid conflict with GUID
+#endif
#ifndef _PreComp_
-# include
-# if defined (_POSIX_C_SOURCE)
-# undef _POSIX_C_SOURCE
-# endif // (re-)defined in pyconfig.h
-# include
-# include
-# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
#endif
+#include "ImportOCAF.h"
+#include
#include
-#include
-
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+#include
/* module functions */
-static PyObject *
-open(PyObject *self, PyObject *args)
+
+static PyObject * importer(PyObject *self, PyObject *args)
{
- const char* Name;
- if (! PyArg_ParseTuple(args, "s",&Name))
- return NULL;
+ char* Name;
+ char* DocName=0;
+ if (!PyArg_ParseTuple(args, "s|s",&Name,&DocName))
+ return 0;
- Base::Console().Log("Open in Import with %s",Name);
+ PY_TRY {
+ //Base::Console().Log("Insert in Part with %s",Name);
+ Base::FileInfo file(Name);
- // extract ending
- std::string cEnding(Name);
- unsigned int pos = cEnding.find_last_of('.');
- if(pos == cEnding.size())
- Py_Error(PyExc_Exception,"no file ending");
- cEnding.erase(0,pos+1);
+ App::Document *pcDoc = 0;
+ if (DocName) {
+ pcDoc = App::GetApplication().getDocument(DocName);
+ }
+ if (!pcDoc) {
+ pcDoc = App::GetApplication().newDocument("Unnamed");
+ }
- if(cEnding == "stp" || cEnding == "step")
- {
- // create new document and add Import feature
- App::Document *pcDoc = App::GetApplication().newDocument();
- App::AbstractFeature *pcFeature = pcDoc->addFeature("ImportStep","Step Import");
- pcFeature->setPropertyString (Name,"FileName");
- pcFeature->TouchProperty("FileName");
- pcDoc->recompute();
+ Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
+ Handle(TDocStd_Document) hDoc;
+ hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
- }else if(cEnding == "igs" || cEnding == "iges")
- {
- // create new document and add Import feature
- App::Document *pcDoc = App::GetApplication().newDocument();
- App::AbstractFeature *pcFeature = pcDoc->addFeature("ImportIges","Iges Import");
-assert(0);
-// pcFeature->GetProperty("FileName").Set(Name);
- pcFeature->TouchProperty("FileName");
- pcDoc->recompute();
+ if (file.hasExtension("stp") || file.hasExtension("step")) {
+ try {
+ STEPCAFControl_Reader aReader;
+ aReader.SetColorMode(true);
+ aReader.SetNameMode(true);
+ aReader.SetLayerMode(true);
+ if (aReader.ReadFile((Standard_CString)Name) != IFSelect_RetDone) {
+ PyErr_SetString(PyExc_Exception, "cannot read STEP file");
+ return 0;
+ }
- }else
+ Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100);
+ aReader.Reader().WS()->MapReader()->SetProgress(pi);
+ pi->NewScope(100, "Reading STEP file...");
+ pi->Show();
+ aReader.Transfer(hDoc);
+ pi->EndScope();
+ }
+ catch (OSD_Exception) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ Base::Console().Error("%s\n", e->GetMessageString());
+ Base::Console().Message("Try to load STEP file without colors...\n");
- Py_Error(PyExc_Exception,"unknown file ending");
+ Part::ImportStepParts(pcDoc,Name);
+ pcDoc->recompute();
+ }
+ }
+ else if (file.hasExtension("igs") || file.hasExtension("iges")) {
+ try {
+ IGESControl_Controller::Init();
+ Interface_Static::SetIVal("read.surfacecurve.mode",3);
+ IGESCAFControl_Reader aReader;
+ aReader.SetColorMode(true);
+ aReader.SetNameMode(true);
+ aReader.SetLayerMode(true);
+ if (aReader.ReadFile((Standard_CString)Name) != IFSelect_RetDone) {
+ PyErr_SetString(PyExc_Exception, "cannot read IGES file");
+ return 0;
+ }
+ Handle_Message_ProgressIndicator pi = new Part::ProgressIndicator(100);
+ aReader.WS()->MapReader()->SetProgress(pi);
+ pi->NewScope(100, "Reading IGES file...");
+ pi->Show();
+ aReader.Transfer(hDoc);
+ pi->EndScope();
+ }
+ catch (OSD_Exception) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ Base::Console().Error("%s\n", e->GetMessageString());
+ Base::Console().Message("Try to load IGES file without colors...\n");
- Py_Return;
+ Part::ImportIgesParts(pcDoc,Name);
+ pcDoc->recompute();
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_Exception, "no supported file format");
+ return 0;
+ }
+
+#if 1
+ Import::ImportOCAF ocaf(hDoc, pcDoc, file.fileNamePure());
+ ocaf.loadShapes();
+#else
+ Import::ImportXCAF xcaf(hDoc, pcDoc, file.fileNamePure());
+ xcaf.loadShapes();
+#endif
+ pcDoc->recompute();
+
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ PyErr_SetString(PyExc_Exception, e->GetMessageString());
+ return 0;
+ }
+ PY_CATCH
+
+ Py_Return;
}
-/* module functions */
-static PyObject *
-save(PyObject *self, PyObject *args)
+static PyObject * open(PyObject *self, PyObject *args)
{
- char* str;
+ return importer(self, args);
+}
- if (! PyArg_ParseTuple(args, "s",&str))
+static PyObject * exporter(PyObject *self, PyObject *args)
+{
+ PyObject* object;
+ const char* filename;
+ if (!PyArg_ParseTuple(args, "Os",&object,&filename))
return NULL;
- TopoDS_Shape ResultShape;
- BRep_Builder aBuilder;
+ PY_TRY {
+ Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
+ Handle(TDocStd_Document) hDoc;
+ hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
+ Import::ExportOCAF ocaf(hDoc);
- BRepTools::Read(ResultShape,(const Standard_CString)str,aBuilder);
+ Py::List list(object);
+ for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
+ PyObject* item = (*it).ptr();
+ if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
+ App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr();
+ if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
+ Part::Feature* part = static_cast(obj);
+ std::vector colors;
+ ocaf.saveShape(part, colors);
+ }
+ else {
+ Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue());
+ }
+ }
+ else if (PyTuple_Check(item) && PyTuple_Size(item) == 2) {
+ Py::Tuple tuple(*it);
+ Py::Object item0 = tuple.getItem(0);
+ Py::Object item1 = tuple.getItem(1);
+ if (PyObject_TypeCheck(item0.ptr(), &(App::DocumentObjectPy::Type))) {
+ App::DocumentObject* obj = static_cast(item0.ptr())->getDocumentObjectPtr();
+ if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
+ Part::Feature* part = static_cast(obj);
+ App::PropertyColorList colors;
+ colors.setPyObject(item1.ptr());
+ ocaf.saveShape(part, colors.getValues());
+ }
+ else {
+ Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue());
+ }
+ }
+ }
+ }
- return new Part::TopoShapePy(ResultShape); /* convert C -> Python */
+ Base::FileInfo file(filename);
+ if (file.hasExtension("stp") || file.hasExtension("step")) {
+ //Interface_Static::SetCVal("write.step.schema", "AP214IS");
+ STEPCAFControl_Writer writer;
+ writer.Transfer(hDoc, STEPControl_AsIs);
+ // edit STEP header
+#if OCC_VERSION_HEX >= 0x060500
+ APIHeaderSection_MakeHeader makeHeader(writer.ChangeWriter().Model());
+#else
+ APIHeaderSection_MakeHeader makeHeader(writer.Writer().Model());
+#endif
+ makeHeader.SetName(new TCollection_HAsciiString((const Standard_CString)filename));
+ makeHeader.SetAuthorValue (1, new TCollection_HAsciiString("FreeCAD"));
+ makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString("FreeCAD"));
+ makeHeader.SetOriginatingSystem(new TCollection_HAsciiString("FreeCAD"));
+ makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model"));
+ writer.Write(filename);
+ }
+ else if (file.hasExtension("igs") || file.hasExtension("iges")) {
+ IGESControl_Controller::Init();
+ IGESCAFControl_Writer writer;
+ writer.Transfer(hDoc);
+ writer.Write(filename);
+ }
+ }
+ catch (Standard_Failure) {
+ Handle_Standard_Failure e = Standard_Failure::Caught();
+ PyErr_SetString(PyExc_Exception, e->GetMessageString());
+ return 0;
+ }
+ PY_CATCH
+
+ Py_Return;
}
-
-
/* registration table */
-struct PyMethodDef Import_methods[] = {
- {"open", open, 1}, /* method name, C func ptr, always-tuple */
- {"save", save, 1},
-
+struct PyMethodDef Import_Import_methods[] = {
+ {"open" ,open ,METH_VARARGS,
+ "open(string) -- Open the file and create a new document."},
+ {"insert" ,importer ,METH_VARARGS,
+ "insert(string,string) -- Insert the file into the given document."},
+ {"export" ,exporter ,METH_VARARGS,
+ "export(list,string) -- Export a list of objects into a single file."},
{NULL, NULL} /* end of table marker */
};
diff --git a/src/Mod/Import/App/CMakeLists.txt b/src/Mod/Import/App/CMakeLists.txt
index 1ac7c717a..e89a76a2d 100644
--- a/src/Mod/Import/App/CMakeLists.txt
+++ b/src/Mod/Import/App/CMakeLists.txt
@@ -1,49 +1,55 @@
-add_definitions(-DFCAppImport -DFC_DEBUG)
+if(MSVC)
+ add_definitions(-DFCAppImport -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH)
+else(MSVC)
+ add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
+endif(MSVC)
+
include_directories(
-# ${CMAKE_SOURCE_DIR}/src
-# ${OPENCV_INCLUDE_DIR}
- ${OCC_INCLUDE_DIR}
-# ${PYTHON_INCLUDE_PATH}
- ${ZLIB_INCLUDE_DIR}
- ${XERCES_INCLUDE_DIR})
-
-if(WIN32)
- set(Import_LIBS
-# ${OPENCV_LIBRARIES}
-# -lTKIGES \
-# -lTKSTEP \
- Part
- FreeCADApp)
-else(WIN32)
- set(Import_LIBS
-# -lTKIGES \
-# -lTKSTEP \
-# -lFreeCADBase \
-# -lFreeCADApp \
-# -lPart
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${Boost_INCLUDE_DIRS}
+ ${OCC_INCLUDE_DIR}
+ ${ZLIB_INCLUDE_DIR}
+ ${PYTHON_INCLUDE_PATH}
+ ${XERCESC_INCLUDE_DIR}
)
-endif(WIN32)
-set(Import_SRCS
- AppImport.cpp
- AppImportPy.cpp
- FeatureImportIges.cpp
- FeatureImportIges.h
- FeatureImportStep.cpp
- FeatureImportStep.h
- PreCompiled.cpp
- PreCompiled.h
+link_directories(${OCC_LIBRARY_DIR})
+
+set(Import_LIBS
+ Part
+ ${OCC_OCAF_LIBRARIES}
+ ${OCC_OCAF_DEBUG_LIBRARIES}
+)
+
+SET(Import_SRCS
+ AppImport.cpp
+ AppImportPy.cpp
+ ImportOCAF.cpp
+ ImportOCAF.h
+ PreCompiled.cpp
+ PreCompiled.h
)
add_library(Import SHARED ${Import_SRCS})
-
target_link_libraries(Import ${Import_LIBS})
-set_target_properties(Import PROPERTIES SUFFIX ".pyd")
-
-if(UNIX)
+if(MSVC)
+ set_target_properties(Import PROPERTIES SUFFIX ".pyd")
+ set_target_properties(Import PROPERTIES DEBUG_OUTPUT_NAME "Import_d")
+ set_target_properties(Import PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Import)
+ set_target_properties(Import PROPERTIES PREFIX "../")
+ # Set special compiler flag to convert a SIGSEV into an exception
+ set_target_properties(Import PROPERTIES COMPILE_FLAGS "/EHa")
+elseif(MINGW)
+ set_target_properties(Import PROPERTIES SUFFIX ".pyd")
+ set_target_properties(Import PROPERTIES DEBUG_OUTPUT_NAME "Import_d")
+ set_target_properties(Import PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Import)
+ set_target_properties(Import PROPERTIES PREFIX "")
+else(MSVC)
+ set_target_properties(Import PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Import)
+ set_target_properties(Import PROPERTIES PREFIX "")
set_target_properties(Import PROPERTIES INSTALL_RPATH ${INSTALL_RPATH})
-endif(UNIX)
+endif(MSVC)
-install(TARGETS Import DESTINATION lib)
+INSTALL(TARGETS Import DESTINATION lib)
diff --git a/src/Mod/Import/App/ImportOCAF.cpp b/src/Mod/Import/App/ImportOCAF.cpp
new file mode 100644
index 000000000..ace94ec0c
--- /dev/null
+++ b/src/Mod/Import/App/ImportOCAF.cpp
@@ -0,0 +1,548 @@
+/***************************************************************************
+ * Copyright (c) 2013 Werner Mayer *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+
+#include "PreCompiled.h"
+#if defined(__MINGW32__)
+# define WNT // avoid conflict with GUID
+#endif
+#ifndef _PreComp_
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+#if OCC_VERSION_HEX >= 0x060500
+# include
+# else
+# include
+# endif
+#endif
+
+#include "ImportOCAF.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+using namespace Import;
+
+
+ImportOCAF::ImportOCAF(Handle_TDocStd_Document h, App::Document* d, const std::string& name)
+ : pDoc(h), doc(d), default_name(name)
+{
+ aShapeTool = XCAFDoc_DocumentTool::ShapeTool (pDoc->Main());
+ aColorTool = XCAFDoc_DocumentTool::ColorTool(pDoc->Main());
+}
+
+ImportOCAF::~ImportOCAF()
+{
+}
+
+void ImportOCAF::loadShapes()
+{
+ myRefShapes.clear();
+ loadShapes(pDoc->Main(), TopLoc_Location(), default_name, "", false);
+}
+
+void ImportOCAF::loadShapes(const TDF_Label& label, const TopLoc_Location& loc, const std::string& defaultname, const std::string& assembly, bool isRef)
+{
+ int hash = 0;
+ TopoDS_Shape aShape;
+ if (aShapeTool->GetShape(label,aShape)) {
+ hash = aShape.HashCode(HashUpper);
+ }
+
+ Handle(TDataStd_Name) name;
+ std::string part_name = defaultname;
+ if (label.FindAttribute(TDataStd_Name::GetID(),name)) {
+ TCollection_ExtendedString extstr = name->Get();
+ char* str = new char[extstr.LengthOfCString()+1];
+ extstr.ToUTF8CString(str);
+ part_name = str;
+ delete [] str;
+ if (part_name.empty()) {
+ part_name = defaultname;
+ }
+ else {
+ bool ws=true;
+ for (std::string::iterator it = part_name.begin(); it != part_name.end(); ++it) {
+ if (*it != ' ') {
+ ws = false;
+ break;
+ }
+ }
+ if (ws)
+ part_name = defaultname;
+ }
+ }
+
+ TopLoc_Location part_loc = loc;
+ Handle(XCAFDoc_Location) hLoc;
+ if (label.FindAttribute(XCAFDoc_Location::GetID(), hLoc)) {
+ if (isRef)
+ part_loc = part_loc * hLoc->Get();
+ else
+ part_loc = hLoc->Get();
+ }
+
+#ifdef FC_DEBUG
+ Base::Console().Message("H:%d, N:%s, T:%d, A:%d, S:%d, C:%d, SS:%d, F:%d, R:%d, C:%d, SS:%d\n",
+ hash,
+ part_name.c_str(),
+ aShapeTool->IsTopLevel(label),
+ aShapeTool->IsAssembly(label),
+ aShapeTool->IsShape(label),
+ aShapeTool->IsCompound(label),
+ aShapeTool->IsSimpleShape(label),
+ aShapeTool->IsFree(label),
+ aShapeTool->IsReference(label),
+ aShapeTool->IsComponent(label),
+ aShapeTool->IsSubShape(label)
+ );
+#endif
+
+ std::string asm_name = assembly;
+ if (aShapeTool->IsAssembly(label)) {
+ asm_name = part_name;
+ }
+
+ TDF_Label ref;
+ if (aShapeTool->IsReference(label) && aShapeTool->GetReferredShape(label, ref)) {
+ loadShapes(ref, part_loc, part_name, asm_name, true);
+ }
+
+ if (isRef || myRefShapes.find(hash) == myRefShapes.end()) {
+ TopoDS_Shape aShape;
+ if (isRef && aShapeTool->GetShape(label, aShape))
+ myRefShapes.insert(aShape.HashCode(HashUpper));
+
+ if (aShapeTool->IsSimpleShape(label) && (isRef || aShapeTool->IsFree(label))) {
+ if (!asm_name.empty())
+ part_name = asm_name;
+ if (isRef)
+ createShape(label, loc, part_name);
+ else
+ createShape(label, part_loc, part_name);
+ }
+ else {
+ for (TDF_ChildIterator it(label); it.More(); it.Next()) {
+ loadShapes(it.Value(), part_loc, part_name, asm_name, isRef);
+ }
+ }
+ }
+}
+
+void ImportOCAF::createShape(const TDF_Label& label, const TopLoc_Location& loc, const std::string& name)
+{
+ const TopoDS_Shape& aShape = aShapeTool->GetShape(label);
+ if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_COMPOUND) {
+ TopExp_Explorer xp;
+ int ctSolids = 0, ctShells = 0;
+ for (xp.Init(aShape, TopAbs_SOLID); xp.More(); xp.Next(), ctSolids++)
+ createShape(xp.Current(), loc, name);
+ for (xp.Init(aShape, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next(), ctShells++)
+ createShape(xp.Current(), loc, name);
+ if (ctSolids > 0 || ctShells > 0)
+ return;
+ }
+
+ createShape(aShape, loc, name);
+}
+
+void ImportOCAF::createShape(const TopoDS_Shape& aShape, const TopLoc_Location& loc, const std::string& name)
+{
+ Part::Feature* part = static_cast(doc->addObject("Part::Feature"));
+ if (!loc.IsIdentity())
+ part->Shape.setValue(aShape.Moved(loc));
+ else
+ part->Shape.setValue(aShape);
+ part->Label.setValue(name);
+
+ Quantity_Color aColor;
+ App::Color color(0.8f,0.8f,0.8f);
+ if (aColorTool->GetColor(aShape, XCAFDoc_ColorGen, aColor) ||
+ aColorTool->GetColor(aShape, XCAFDoc_ColorSurf, aColor) ||
+ aColorTool->GetColor(aShape, XCAFDoc_ColorCurv, aColor)) {
+ color.r = aColor.Red();
+ color.g = aColor.Green();
+ color.b = aColor.Blue();
+ std::vector colors;
+ colors.push_back(color);
+ applyColors(part, colors);
+#if 0//TODO
+ Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
+ if (vp && vp->isDerivedFrom(PartGui::ViewProviderPart::getClassTypeId())) {
+ color.r = aColor.Red();
+ color.g = aColor.Green();
+ color.b = aColor.Blue();
+ static_cast(vp)->ShapeColor.setValue(color);
+ }
+#endif
+ }
+
+ TopTools_IndexedMapOfShape faces;
+ TopExp_Explorer xp(aShape,TopAbs_FACE);
+ while (xp.More()) {
+ faces.Add(xp.Current());
+ xp.Next();
+ }
+ bool found_face_color = false;
+ std::vector faceColors;
+ faceColors.resize(faces.Extent(), color);
+ xp.Init(aShape,TopAbs_FACE);
+ while (xp.More()) {
+ if (aColorTool->GetColor(xp.Current(), XCAFDoc_ColorGen, aColor) ||
+ aColorTool->GetColor(xp.Current(), XCAFDoc_ColorSurf, aColor) ||
+ aColorTool->GetColor(xp.Current(), XCAFDoc_ColorCurv, aColor)) {
+ int index = faces.FindIndex(xp.Current());
+ color.r = aColor.Red();
+ color.g = aColor.Green();
+ color.b = aColor.Blue();
+ faceColors[index-1] = color;
+ found_face_color = true;
+ }
+ xp.Next();
+ }
+
+ if (found_face_color) {
+ applyColors(part, faceColors);
+#if 0//TODO
+ Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
+ if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) {
+ static_cast(vp)->DiffuseColor.setValues(faceColors);
+ }
+#endif
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+ExportOCAF::ExportOCAF(Handle_TDocStd_Document h)
+ : pDoc(h)
+{
+ aShapeTool = XCAFDoc_DocumentTool::ShapeTool(pDoc->Main());
+ aColorTool = XCAFDoc_DocumentTool::ColorTool(pDoc->Main());
+ rootLabel = TDF_TagSource::NewChild(pDoc->Main());
+}
+
+void ExportOCAF::saveShape(Part::Feature* part, const std::vector& colors)
+{
+ const TopoDS_Shape& shape = part->Shape.getValue();
+
+ // Add shape and name
+ //TDF_Label shapeLabel = hShapeTool->AddShape(shape, Standard_False);
+ TDF_Label shapeLabel= TDF_TagSource::NewChild(rootLabel);
+#if OCC_VERSION_HEX >= 0x060500
+ TDataXtd_Shape::Set(shapeLabel, shape);
+#else
+ TDataStd_Shape::Set(shapeLabel, shape);
+#endif
+ TDataStd_Name::Set(shapeLabel, TCollection_ExtendedString(part->Label.getValue(), 1));
+
+ // Add color information
+ Quantity_Color col;
+
+ std::set face_index;
+ TopTools_IndexedMapOfShape faces;
+ TopExp_Explorer xp(shape,TopAbs_FACE);
+ while (xp.More()) {
+ face_index.insert(faces.Add(xp.Current()));
+ xp.Next();
+ }
+
+ // define color per face?
+ if (colors.size() == face_index.size()) {
+ xp.Init(shape,TopAbs_FACE);
+ while (xp.More()) {
+ int index = faces.FindIndex(xp.Current());
+ if (face_index.find(index) != face_index.end()) {
+ face_index.erase(index);
+ TDF_Label faceLabel= TDF_TagSource::NewChild(shapeLabel);
+#if OCC_VERSION_HEX >= 0x060500
+ TDataXtd_Shape::Set(faceLabel, xp.Current());
+#else
+ TDataStd_Shape::Set(faceLabel, xp.Current());
+#endif
+ const App::Color& color = colors[index-1];
+ Quantity_Parameter mat[3];
+ mat[0] = color.r;
+ mat[1] = color.g;
+ mat[2] = color.b;
+ col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB);
+ aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf);
+ }
+ xp.Next();
+ }
+ }
+ else if (!colors.empty()) {
+ App::Color color = colors.front();
+ Quantity_Parameter mat[3];
+ mat[0] = color.r;
+ mat[1] = color.g;
+ mat[2] = color.b;
+ col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB);
+ aColorTool->SetColor(shapeLabel, col, XCAFDoc_ColorGen);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+ImportXCAF::ImportXCAF(Handle_TDocStd_Document h, App::Document* d, const std::string& name)
+ : hdoc(h), doc(d), default_name(name)
+{
+ aShapeTool = XCAFDoc_DocumentTool::ShapeTool (hdoc->Main());
+ hColors = XCAFDoc_DocumentTool::ColorTool(hdoc->Main());
+}
+
+ImportXCAF::~ImportXCAF()
+{
+}
+
+void ImportXCAF::loadShapes()
+{
+ // collect sequence of labels to display
+ TDF_LabelSequence shapeLabels, colorLabels;
+ aShapeTool->GetFreeShapes (shapeLabels);
+ hColors->GetColors(colorLabels);
+
+ // set presentations and show
+ for (Standard_Integer i=1; i <= shapeLabels.Length(); i++ ) {
+ // get the shapes and attributes
+ const TDF_Label& label = shapeLabels.Value(i);
+ loadShapes(label);
+ }
+ std::map::iterator it;
+ // go through solids
+ for (it = mySolids.begin(); it != mySolids.end(); ++it) {
+ createShape(it->second, true, true);
+ }
+ // go through shells
+ for (it = myShells.begin(); it != myShells.end(); ++it) {
+ createShape(it->second, true, true);
+ }
+ // go through compounds
+ for (it = myCompds.begin(); it != myCompds.end(); ++it) {
+ createShape(it->second, true, true);
+ }
+ // do the rest
+ if (!myShapes.empty()) {
+ BRep_Builder builder;
+ TopoDS_Compound comp;
+ builder.MakeCompound(comp);
+ for (it = myShapes.begin(); it != myShapes.end(); ++it) {
+ builder.Add(comp, it->second);
+ }
+ createShape(comp, true, false);
+ }
+}
+
+void ImportXCAF::createShape(const TopoDS_Shape& shape, bool perface, bool setname) const
+{
+ Part::Feature* part;
+ part = static_cast(doc->addObject("Part::Feature", default_name.c_str()));
+ part->Shape.setValue(shape);
+ std::map::const_iterator jt;
+ jt = myColorMap.find(shape.HashCode(INT_MAX));
+
+ App::Color partColor(0.8f,0.8f,0.8f);
+#if 0//TODO
+ Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
+ if (vp && vp->isDerivedFrom(PartGui::ViewProviderPart::getClassTypeId())) {
+ if (jt != myColorMap.end()) {
+ App::Color color;
+ color.r = jt->second.Red();
+ color.g = jt->second.Green();
+ color.b = jt->second.Blue();
+ static_cast(vp)->ShapeColor.setValue(color);
+ }
+
+ partColor = static_cast(vp)->ShapeColor.getValue();
+ }
+#endif
+
+ // set label name if defined
+ if (setname && !myNameMap.empty()) {
+ std::map::const_iterator jt;
+ jt = myNameMap.find(shape.HashCode(INT_MAX));
+ if (jt != myNameMap.end()) {
+ part->Label.setValue(jt->second);
+ }
+ }
+
+ // check for colors per face
+ if (perface && !myColorMap.empty()) {
+ TopTools_IndexedMapOfShape faces;
+ TopExp_Explorer xp(shape,TopAbs_FACE);
+ while (xp.More()) {
+ faces.Add(xp.Current());
+ xp.Next();
+ }
+
+ bool found_face_color = false;
+ std::vector faceColors;
+ faceColors.resize(faces.Extent(), partColor);
+ xp.Init(shape,TopAbs_FACE);
+ while (xp.More()) {
+ jt = myColorMap.find(xp.Current().HashCode(INT_MAX));
+ if (jt != myColorMap.end()) {
+ int index = faces.FindIndex(xp.Current());
+ App::Color color;
+ color.r = jt->second.Red();
+ color.g = jt->second.Green();
+ color.b = jt->second.Blue();
+ faceColors[index-1] = color;
+ found_face_color = true;
+ }
+ xp.Next();
+ }
+
+ if (found_face_color) {
+#if 0//TODO
+ Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
+ if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) {
+ static_cast(vp)->DiffuseColor.setValues(faceColors);
+ }
+#endif
+ }
+ }
+}
+
+void ImportXCAF::loadShapes(const TDF_Label& label)
+{
+ TopoDS_Shape aShape;
+ if (aShapeTool->GetShape(label,aShape)) {
+ //if (aShapeTool->IsReference(label)) {
+ // TDF_Label reflabel;
+ // if (aShapeTool->GetReferredShape(label, reflabel)) {
+ // loadShapes(reflabel);
+ // }
+ //}
+ if (aShapeTool->IsTopLevel(label)) {
+ int ctSolids = 0, ctShells = 0, ctComps = 0;
+ // add the shapes
+ TopExp_Explorer xp;
+ for (xp.Init(aShape, TopAbs_SOLID); xp.More(); xp.Next(), ctSolids++)
+ this->mySolids[xp.Current().HashCode(INT_MAX)] = (xp.Current());
+ for (xp.Init(aShape, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next(), ctShells++)
+ this->myShells[xp.Current().HashCode(INT_MAX)] = (xp.Current());
+ // if no solids and no shells were found then go for compounds
+ if (ctSolids == 0 && ctShells == 0) {
+ for (xp.Init(aShape, TopAbs_COMPOUND); xp.More(); xp.Next(), ctComps++)
+ this->myCompds[xp.Current().HashCode(INT_MAX)] = (xp.Current());
+ }
+ if (ctComps == 0) {
+ for (xp.Init(aShape, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next())
+ this->myShapes[xp.Current().HashCode(INT_MAX)] = (xp.Current());
+ for (xp.Init(aShape, TopAbs_WIRE, TopAbs_FACE); xp.More(); xp.Next())
+ this->myShapes[xp.Current().HashCode(INT_MAX)] = (xp.Current());
+ for (xp.Init(aShape, TopAbs_EDGE, TopAbs_WIRE); xp.More(); xp.Next())
+ this->myShapes[xp.Current().HashCode(INT_MAX)] = (xp.Current());
+ for (xp.Init(aShape, TopAbs_VERTEX, TopAbs_EDGE); xp.More(); xp.Next())
+ this->myShapes[xp.Current().HashCode(INT_MAX)] = (xp.Current());
+ }
+ }
+
+ // getting color
+ Quantity_Color col;
+ if (hColors->GetColor(label, XCAFDoc_ColorGen, col) ||
+ hColors->GetColor(label, XCAFDoc_ColorSurf, col) ||
+ hColors->GetColor(label, XCAFDoc_ColorCurv, col)) {
+ // add defined color
+ myColorMap[aShape.HashCode(INT_MAX)] = col;
+ }
+ else {
+ // http://www.opencascade.org/org/forum/thread_17107/
+ TopoDS_Iterator it;
+ for (it.Initialize(aShape);it.More(); it.Next()) {
+ if (hColors->GetColor(it.Value(), XCAFDoc_ColorGen, col) ||
+ hColors->GetColor(it.Value(), XCAFDoc_ColorSurf, col) ||
+ hColors->GetColor(it.Value(), XCAFDoc_ColorCurv, col)) {
+ // add defined color
+ myColorMap[it.Value().HashCode(INT_MAX)] = col;
+ }
+ }
+ }
+
+ // getting names
+ Handle(TDataStd_Name) name;
+ if (label.FindAttribute(TDataStd_Name::GetID(),name)) {
+ TCollection_ExtendedString extstr = name->Get();
+ char* str = new char[extstr.LengthOfCString()+1];
+ extstr.ToUTF8CString(str);
+ std::string label(str);
+ if (!label.empty())
+ myNameMap[aShape.HashCode(INT_MAX)] = label;
+ delete [] str;
+ }
+
+#if 0
+ // http://www.opencascade.org/org/forum/thread_15174/
+ if (aShapeTool->IsAssembly(label)) {
+ TDF_LabelSequence shapeLabels;
+ aShapeTool->GetComponents(label, shapeLabels);
+ Standard_Integer nbShapes = shapeLabels.Length();
+ for (Standard_Integer i = 1; i <= nbShapes; i++) {
+ loadShapes(shapeLabels.Value(i));
+ }
+ }
+#endif
+
+ if (label.HasChild()) {
+ TDF_ChildIterator it;
+ for (it.Initialize(label); it.More(); it.Next()) {
+ loadShapes(it.Value());
+ }
+ }
+ }
+}
diff --git a/src/Mod/Import/App/ImportOCAF.h b/src/Mod/Import/App/ImportOCAF.h
new file mode 100644
index 000000000..50b91bdf8
--- /dev/null
+++ b/src/Mod/Import/App/ImportOCAF.h
@@ -0,0 +1,117 @@
+/***************************************************************************
+ * Copyright (c) 2013 Werner Mayer *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+
+#ifndef IMPORT_IMPORTOCAF_H
+#define IMPORT_IMPORTOCAF_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include