Merge branch 'master' of ssh://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad into freecad-ship

This commit is contained in:
Jose Luis Cercós pita 2012-03-09 10:21:10 +01:00
commit 7b8503712e
211 changed files with 10971 additions and 6434 deletions

View File

@ -59,17 +59,24 @@ endif(CMAKE_COMPILER_IS_GNUCXX)
# Output directories for install target
if(WIN32)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "Installation root directory")
else(WIN32)
SET(CMAKE_INSTALL_PREFIX "/usr/lib${LIB_SUFFIX}/freecad" CACHE PATH "Installation root directory")
SET(INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
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")
# used as compiler defines
SET(RESOURCEDIR "${CMAKE_INSTALL_DATADIR}")
SET(DOCDIR "${CMAKE_INSTALL_DOCDIR}")
MESSAGE("prefix: ${CMAKE_INSTALL_PREFIX}")
MESSAGE("datadir: ${CMAKE_INSTALL_DATADIR}")
MESSAGE("docdir: ${CMAKE_INSTALL_DOCDIR}")
MESSAGE("includedir: ${CMAKE_INSTALL_INCLUDEDIR}")
# ==============================================================================
# == Win32 is default behaviour use the LibPack copied in Source tree ==========
@ -89,8 +96,7 @@ OPTION(FREECAD_MAINTAINERS_BUILD "Build FreeCAD for Maintainers, with Docu and 3
OPTION(FREECAD_BUILD_CAM "Build the FreeCAD CAM module and the needed libs, be aware, unfinished code!" OFF)
OPTION(FREECAD_BUILD_FEM "Build the FreeCAD FEM module, be aware, unfinished code!" ON)
OPTION(FREECAD_BUILD_SANDBOX "Build the FreeCAD Sandbox module which is only for testing purposes" OFF)
SET(RESOURCEDIR "${CMAKE_INSTALL_PREFIX}/data" CACHE PATH "Absolute path to the data directory.")
SET(DOCDIR "" CACHE PATH "Absolute path to the documentation directory.")
OPTION(FREECAD_BUILD_DEBIAN "Prepare for a build of a Debian package" OFF)
# ==============================================================================
@ -449,7 +455,6 @@ if(FREECAD_MAINTAINERS_BUILD AND NOT WIN32)
"Makefile$"
"\\\\.sh$"
"_CPack_"
"71"
"config.h$"
"config.log$"
"config.status$"
@ -473,6 +478,7 @@ if(FREECAD_MAINTAINERS_BUILD AND NOT WIN32)
#ADD_CUSTOM_TARGET(DIST make package_source)
endif(FREECAD_MAINTAINERS_BUILD AND NOT WIN32)
#add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
add_custom_target(dist-git
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py
--srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR}

View File

@ -30,7 +30,7 @@ fi
if which glibtoolize > /dev/null 2>&1; then
echo "calling glibtoolize"
glibtoolize --force --copy
elif which libtoolize > /dev/null 2>71; then
elif which libtoolize > /dev/null 2>&1; then
echo "calling libtoolize"
libtoolize --force --copy
else

View File

@ -38,37 +38,9 @@ ENDFOREACH(SRC ${FILES})
SET(${TARGETS} ${AddTargets})
ENDMACRO(COPY_IF_DIFFERENT FROM_DIR TO_DIR FILES TARGETS TAGS)
MACRO (fc_copy_to_mod_path mod_name )
FOREACH (it ${ARGN})
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${it}" NATIVE_SOURCE)
file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/Mod/${mod_name}/" NATIVE_DEST)
message(STATUS "${PLATFORM_CP} ${NATIVE_SOURCE} ${NATIVE_DEST}")
if (WIN32)
else (WIN32)
execute_process( COMMAND ${PLATFORM_MK} ${NATIVE_DEST} )
endif (WIN32)
execute_process( COMMAND ${PLATFORM_CP} ${NATIVE_SOURCE} ${NATIVE_DEST} )
ENDFOREACH(it)
ENDMACRO(fc_copy_to_mod_path)
MACRO (fc_copy_to_path path_name)
FOREACH (it ${ARGN})
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${it}" NATIVE_SOURCE)
file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/${path_name}/" NATIVE_DEST)
message(STATUS "${PLATFORM_CP} ${NATIVE_SOURCE} ${NATIVE_DEST}")
if (WIN32)
else (WIN32)
execute_process( COMMAND ${PLATFORM_MK} ${NATIVE_DEST} )
endif (WIN32)
execute_process( COMMAND ${PLATFORM_CP} ${NATIVE_SOURCE} ${NATIVE_DEST} )
ENDFOREACH(it)
ENDMACRO(fc_copy_to_path)
MACRO (fc_copy_sources path_name mod_name)
MACRO (fc_copy_sources target_name outpath)
foreach(it ${ARGN})
file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/${path_name}/${it}" outfile)
file(TO_NATIVE_PATH "${outpath}/${it}" outfile)
get_filename_component(infile ${it} ABSOLUTE)
get_filename_component(outfile ${outfile} ABSOLUTE)
add_file_dependencies(${infile} ${outfile})
@ -76,42 +48,21 @@ MACRO (fc_copy_sources path_name mod_name)
SOURCE ${infile}
COMMAND ${CMAKE_COMMAND}
ARGS -E copy ${infile} ${outfile}
TARGET ${mod_name}
TARGET ${target_name}
OUTPUTS ${outfile}
)
endforeach(it)
ADD_CUSTOM_COMMAND(
SOURCE ${mod_name}
TARGET ${mod_name}
SOURCE ${target_name}
TARGET ${target_name}
DEPENDS ${ARGN}
)
ENDMACRO(fc_copy_sources)
MACRO (fc_copy_sources_outpath out_path mod_name)
MACRO (fc_target_copy_resource target_name inpath outpath)
foreach(it ${ARGN})
file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/${out_path}/${it}" outfile)
get_filename_component(infile ${it} ABSOLUTE)
get_filename_component(outfile ${outfile} ABSOLUTE)
add_file_dependencies(${infile} ${outfile})
ADD_CUSTOM_COMMAND(
SOURCE ${infile}
COMMAND ${CMAKE_COMMAND}
ARGS -E copy ${infile} ${outfile}
TARGET ${mod_name}
OUTPUTS ${outfile}
)
endforeach(it)
ADD_CUSTOM_COMMAND(
SOURCE ${mod_name}
TARGET ${mod_name}
DEPENDS ${ARGN}
)
ENDMACRO(fc_copy_sources_outpath)
MACRO (fc_copy_script path_name mod_name)
foreach(it ${ARGN})
file(TO_NATIVE_PATH "${CMAKE_SOURCE_DIR}/src/${path_name}/${it}" infile)
file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/${path_name}/${it}" outfile)
file(TO_NATIVE_PATH "${inpath}/${it}" infile)
file(TO_NATIVE_PATH "${outpath}/${it}" outfile)
get_filename_component(infile ${infile} ABSOLUTE)
get_filename_component(outfile ${outfile} ABSOLUTE)
add_file_dependencies(${infile} ${outfile})
@ -119,16 +70,16 @@ MACRO (fc_copy_script path_name mod_name)
SOURCE ${infile}
COMMAND ${CMAKE_COMMAND}
ARGS -E copy ${infile} ${outfile}
TARGET ${mod_name}
TARGET ${target_name}
OUTPUTS ${outfile}
)
endforeach(it)
ADD_CUSTOM_COMMAND(
SOURCE ${mod_name}
TARGET ${mod_name}
SOURCE ${target_name}
TARGET ${target_name}
DEPENDS ${ARGN}
)
ENDMACRO(fc_copy_script)
ENDMACRO(fc_target_copy_resource)
macro(copy_to_local_output_paths SOURCE_PATHS)
if(CMAKE_CFG_INTDIR STREQUAL .)

View File

@ -11,7 +11,7 @@ ADD_CUSTOM_TARGET(Example_data ALL
SOURCES ${Examples_Files}
)
fc_copy_sources("data/examples" "Examples" ${Examples_Files})
fc_copy_sources(Examples "${CMAKE_BINARY_DIR}/data/examples" ${Examples_Files})
INSTALL(
FILES

View File

@ -20,16 +20,18 @@ elseif(FREECAD_BUILD_GUI AND FREECAD_LIBPACK_CHECKFILE7X)
#endif(MINGW)
# applies for Unix, MinGW and Windows with custom LibPack
elseif(FREECAD_BUILD_GUI)
find_path(COIN_VERSION3 Inventor/scxml/ScXML.h ${COIN3D_INCLUDE_DIR})
if (COIN_VERSION3)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy-0.5)
add_subdirectory(Pivy-0.5)
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy-0.5)
else (COIN_VERSION3)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy)
add_subdirectory(Pivy)
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy)
endif(COIN_VERSION3)
if (NOT FREECAD_BUILD_DEBIAN)
find_path(COIN_VERSION3 Inventor/scxml/ScXML.h ${COIN3D_INCLUDE_DIR})
if (COIN_VERSION3)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy-0.5)
add_subdirectory(Pivy-0.5)
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy-0.5)
else (COIN_VERSION3)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy)
add_subdirectory(Pivy)
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy)
endif(COIN_VERSION3)
endif (NOT FREECAD_BUILD_DEBIAN)
endif(FREECAD_BUILD_GUI AND FREECAD_LIBPACK_CHECKFILE6X)
# For Windows we have all stuff in the LibPack

View File

@ -56,15 +56,16 @@ else(MSVC)
set_target_properties(coin PROPERTIES OUTPUT_NAME "_coin")
set_target_properties(coin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/pivy)
set_target_properties(coin PROPERTIES PREFIX "")
install(TARGETS coin DESTINATION bin/pivy)
set_target_properties(coin PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin/pivy)
endif(MSVC)
fc_copy_sources_outpath("bin/pivy" "coin"
fc_copy_sources(coin "${CMAKE_BINARY_DIR}/bin/pivy"
__init__.py
coin.py
sogui.py
)
install(TARGETS coin DESTINATION bin/pivy)
install(FILES __init__.py coin.py sogui.py DESTINATION bin/pivy)
########################### SoQtPy ###########################
@ -113,11 +114,13 @@ else(MSVC)
set_target_properties(soqt PROPERTIES OUTPUT_NAME "_soqt")
set_target_properties(soqt PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/pivy/gui)
set_target_properties(soqt PROPERTIES PREFIX "")
set_target_properties(soqt PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin/pivy/gui)
endif(MSVC)
fc_copy_sources_outpath("bin/pivy" "soqt"
fc_copy_sources(soqt "${CMAKE_BINARY_DIR}/bin/pivy"
gui/soqt.py
gui/__init__.py
)
install(FILES __init__.py soqt.py DESTINATION bin/pivy/gui)
install(TARGETS soqt DESTINATION bin/pivy/gui)
install(FILES gui/__init__.py soqt.py DESTINATION bin/pivy/gui)

View File

@ -56,14 +56,16 @@ else(MSVC)
set_target_properties(coin PROPERTIES OUTPUT_NAME "_coin")
set_target_properties(coin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/pivy)
set_target_properties(coin PROPERTIES PREFIX "")
set_target_properties(coin PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin/pivy)
endif(MSVC)
fc_copy_sources_outpath("bin/pivy" "coin"
fc_copy_sources(coin "${CMAKE_BINARY_DIR}/bin/pivy"
__init__.py
coin.py
sogui.py
)
install(TARGETS coin DESTINATION bin/pivy)
install(FILES __init__.py coin.py sogui.py DESTINATION bin/pivy)
########################### SoQtPy ###########################
@ -112,11 +114,13 @@ else(MSVC)
set_target_properties(soqt PROPERTIES OUTPUT_NAME "_soqt")
set_target_properties(soqt PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/pivy/gui)
set_target_properties(soqt PROPERTIES PREFIX "")
set_target_properties(soqt PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/bin/pivy/gui)
endif(MSVC)
fc_copy_sources_outpath("bin/pivy" "soqt"
fc_copy_sources(soqt "${CMAKE_BINARY_DIR}/bin/pivy"
gui/soqt.py
gui/__init__.py
)
install(FILES __init__.py gui/soqt.py DESTINATION bin/pivy/gui)
install(TARGETS soqt DESTINATION bin/pivy/gui)
install(FILES gui/__init__.py gui/soqt.py DESTINATION bin/pivy/gui)

View File

@ -102,6 +102,7 @@
#include <boost/signals.hpp>
#include <boost/bind.hpp>
#include <boost/version.hpp>
#include <QDir>
using namespace App;
using namespace std;
@ -481,8 +482,14 @@ std::string Application::getUserAppDataDir()
std::string Application::getResourceDir()
{
# ifdef RESOURCEDIR
return std::string(RESOURCEDIR) + "/";
#ifdef RESOURCEDIR
std::string path(RESOURCEDIR);
path.append("/");
QDir dir(QString::fromUtf8(RESOURCEDIR));
if (dir.isAbsolute())
return path;
else
return mConfig["AppHomePath"] + path;
#else
return mConfig["AppHomePath"];
#endif
@ -490,8 +497,14 @@ std::string Application::getResourceDir()
std::string Application::getHelpDir()
{
# ifdef DOCDIR
return std::string(DOCDIR) + "/";
#ifdef DOCDIR
std::string path(DOCDIR);
path.append("/");
QDir dir(QString::fromUtf8(DOCDIR));
if (dir.isAbsolute())
return path;
else
return mConfig["AppHomePath"] + path;
#else
return mConfig["DocPath"];
#endif
@ -1082,7 +1095,7 @@ void Application::initConfig(int argc, char ** argv)
mConfig["BuildVersionMajor"].c_str(),
mConfig["BuildVersionMinor"].c_str(),
mConfig["BuildRevision"].c_str(),
mConfig["ConsoleBanner"].c_str());
mConfig["CopyrightInfo"].c_str());
else
Console().Message("%s %s, Libs: %s.%sB%s\n",mConfig["ExeName"].c_str(),
mConfig["ExeVersion"].c_str(),
@ -1178,7 +1191,10 @@ void Application::processCmdLineFiles(void)
Base::Interpreter().runFile(File.filePath().c_str(), false);
}
else if (File.hasExtension("py")) {
Base::Interpreter().loadModule(File.fileNamePure().c_str());
//FIXME: Does this make any sense? I think we should do the ame as for
// fcmacro or fcscript.
//Base::Interpreter().loadModule(File.fileNamePure().c_str());
Base::Interpreter().runFile(File.filePath().c_str(), false);
}
else {
std::vector<std::string> mods = App::GetApplication().getImportModules(Ext.c_str());

View File

@ -4,13 +4,13 @@ if(WIN32)
endif(WIN32)
# This causes some problems with the resource files to be found, especially with the StartPage
#IF(RESOURCEDIR)
# add_definitions(-DRESOURCEDIR="${RESOURCEDIR}")
#ENDIF(RESOURCEDIR)
IF(RESOURCEDIR)
add_definitions(-DRESOURCEDIR="${RESOURCEDIR}")
ENDIF(RESOURCEDIR)
#IF(DOCDIR)
# add_definitions(-DDOCDIR="${DOCDIR}")
#ENDIF(DOCDIR)
IF(DOCDIR)
add_definitions(-DDOCDIR="${DOCDIR}")
ENDIF(DOCDIR)
include_directories(
${CMAKE_BINARY_DIR}/src

View File

@ -1756,7 +1756,7 @@ void PropertyMaterial::setSpecularColor(const Color& col)
hasSetValue();
}
void PropertyMaterial::setEmmisiveColor(const Color& col)
void PropertyMaterial::setEmissiveColor(const Color& col)
{
aboutToSetValue();
_cMat.emissiveColor = col;

View File

@ -723,7 +723,7 @@ public:
void setAmbientColor(const Color& col);
void setDiffuseColor(const Color& col);
void setSpecularColor(const Color& col);
void setEmmisiveColor(const Color& col);
void setEmissiveColor(const Color& col);
void setShininess(float);
void setTransparency(float);

View File

@ -426,6 +426,17 @@ void InventorBuilder::endPoints(void)
result << Base::blanks(indent) << "]" << std::endl;
indent -= 2;
result << Base::blanks(indent) << "}" << std::endl;
}
/**
* Adds an SoPointSet node after creating an SoCordinate3 node with
* beginPoints() and endPoints().
* @see startPoints()
* @see beginPoints()
* @see endPoints()
*/
void InventorBuilder::addPointSet(void)
{
result << Base::blanks(indent) << "PointSet { } " << std::endl;
}

View File

@ -164,6 +164,8 @@ public:
void addPoint(const Vector3f &vec);
/// ends the points set operation
void endPoints(void);
/// add an SoPointSet node
void addPointSet(void);
//@}
/** @name Line/Direction handling */

View File

@ -68,7 +68,7 @@ if(SWIG_FOUND)
add_definitions(-DHAVE_SWIG=1)
endif(SWIG_FOUND)
if (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++)
if (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++ AND NOT FREECAD_BUILD_DEBIAN)
SET(zipios_SRCS
../zipios++/backbuffer.h
../zipios++/basicentry.cpp
@ -122,12 +122,12 @@ SET(zipios_SRCS
../zipios++/zipoutputstream.h
)
SOURCE_GROUP("zipios" FILES ${zipios_SRCS})
else (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++)
else (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++ AND NOT FREECAD_BUILD_DEBIAN)
set(FreeCADBase_LIBS
${FreeCADBase_LIBS}
-lzipios
)
endif (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++)
endif (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++ AND NOT FREECAD_BUILD_DEBIAN)
SET(pycxx_SRCS
../CXX/Config.hxx

View File

@ -508,7 +508,7 @@ int getSWIGVersionFromModule(const std::string& module)
// file can have the extension .py or .pyc
filename = filename.substr(0, filename.rfind("."));
filename += ".py";
boost::regex rx("^# Version ([1-9])\\.([1-9])\\.([1-9][0-9])");
boost::regex rx("^# Version ([1-9])\\.([0-9])\\.([0-9]+)");
boost::cmatch what;
std::string line;
@ -552,21 +552,21 @@ PyObject* InterpreterSingleton::createSWIGPointerObj(const char* Module, const c
PyObject* proxy=0;
PyGILStateLocker locker;
int version = getSWIGVersionFromModule(Module);
switch (version&0xff)
switch (version)
{
case 25:
case 66329:
result = Swig_1_3_25::createSWIGPointerObj_T(TypeName, Pointer, &proxy, own);
break;
case 33:
case 66337:
result = Swig_1_3_33::createSWIGPointerObj_T(TypeName, Pointer, &proxy, own);
break;
case 36:
case 66340:
result = Swig_1_3_36::createSWIGPointerObj_T(TypeName, Pointer, &proxy, own);
break;
case 38:
case 66342:
result = Swig_1_3_38::createSWIGPointerObj_T(TypeName, Pointer, &proxy, own);
break;
case 40:
case 66344:
result = Swig_1_3_40::createSWIGPointerObj_T(TypeName, Pointer, &proxy, own);
break;
default:

View File

@ -194,7 +194,7 @@ Vector3<_Precision>& Vector3<_Precision>::ProjToPlane (const Vector3<_Precision>
const Vector3<_Precision> &rclNorm)
{
Vector3<_Precision> clTemp(rclNorm);
*this = *this - (clTemp *= ((*this - rclBase) * clTemp));
*this = *this - (clTemp *= ((*this - rclBase) * clTemp) / clTemp.Sqr());
return *this;
}
@ -202,7 +202,7 @@ template <class _Precision>
_Precision Vector3<_Precision>::DistanceToPlane (const Vector3<_Precision> &rclBase,
const Vector3<_Precision> &rclNorm) const
{
return (*this - rclBase) * rclNorm;
return ((*this - rclBase) * rclNorm) / rclNorm.Length();
}
template <class _Precision>
@ -218,6 +218,28 @@ _Precision Vector3<_Precision>::DistanceToLine (const Vector3<_Precision> &rclBa
return (_Precision) fabs((rclDirect % Vector3(*this - rclBase)).Length() / rclDirect.Length());
}
template <class _Precision>
Vector3<_Precision> Vector3<_Precision>::DistanceToLineSegment (const Vector3& rclP1,
const Vector3& rclP2) const
{
Vector3<_Precision> dir = rclP2-rclP1;
Vector3<_Precision> beg = *this-rclP1;
Vector3<_Precision> end = beg+dir;
Vector3<_Precision> proj, len;
proj.ProjToLine(beg, dir);
len = proj + beg;
if (len * dir < 0 || len.Length() > dir.Length()) {
if (beg.Length() < end.Length())
return beg;
else
return end;
}
else {
return proj;
}
}
template <class _Precision>
Vector3<_Precision>& Vector3<_Precision>::ProjToLine (const Vector3<_Precision> &rclPoint,
const Vector3<_Precision> &rclLine)
@ -339,7 +361,7 @@ template <class _Precision>
Vector3<_Precision> & Vector3<_Precision>::Normalize (void)
{
_Precision fLen = Length ();
if (fLen != 0.0f) {
if (fLen != (_Precision)0.0 && fLen != (_Precision)1.0) {
x /= fLen;
y /= fLen;
z /= fLen;

View File

@ -180,6 +180,12 @@ public:
_Precision DistanceToPlane (const Vector3 &rclBase, const Vector3 &rclNorm) const;
/// Computes the distance from this point to the line given by \a rclBase and \a rclDirect.
_Precision DistanceToLine (const Vector3 &rclBase, const Vector3 &rclDirect) const;
/** Computes the vector from this point to the point on the line segment with the shortest
* distance. The line segment is defined by \a rclP1 and \a rclP2.
* Note: If the projection of this point is outside the segment then the shortest distance
* to \a rclP1 or \a rclP2 is computed.
*/
Vector3 DistanceToLineSegment (const Vector3& rclP1, const Vector3& rclP2) const;
//@}
};

View File

@ -73,6 +73,11 @@
<UserDocu>Deliver the distance of the point to a given line</UserDocu>
</Documentation>
</Methode>
<Methode Name="distanceToLineSegment" Const="true">
<Documentation>
<UserDocu>Deliver the distance of the point to a given line segment</UserDocu>
</Documentation>
</Methode>
<Methode Name="distanceToPlane" Const="true">
<Documentation>
<UserDocu>Deliver the distance of the point to a given plane</UserDocu>

View File

@ -401,6 +401,31 @@ PyObject* VectorPy::distanceToLine(PyObject *args)
return Py::new_reference_to(dist);
}
PyObject* VectorPy::distanceToLineSegment(PyObject *args)
{
PyObject *base, *line;
if (!PyArg_ParseTuple(args, "OO",&base, &line))
return 0;
if (!PyObject_TypeCheck(base, &(VectorPy::Type))) {
PyErr_SetString(PyExc_TypeError, "First arg must be Vector");
return 0;
}
if (!PyObject_TypeCheck(line, &(VectorPy::Type))) {
PyErr_SetString(PyExc_TypeError, "Second arg must be Vector");
return 0;
}
VectorPy* base_vec = static_cast<VectorPy*>(base);
VectorPy* line_vec = static_cast<VectorPy*>(line);
VectorPy::PointerType this_ptr = reinterpret_cast<VectorPy::PointerType>(_pcTwinPointer);
VectorPy::PointerType base_ptr = reinterpret_cast<VectorPy::PointerType>(base_vec->_pcTwinPointer);
VectorPy::PointerType line_ptr = reinterpret_cast<VectorPy::PointerType>(line_vec->_pcTwinPointer);
Vector3d v = this_ptr->DistanceToLineSegment(*base_ptr, *line_ptr);
return new VectorPy(v);
}
PyObject* VectorPy::distanceToPlane(PyObject *args)
{
PyObject *base, *line;

View File

@ -22,6 +22,9 @@
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="Icons/resource.qrc">:/icons/freecadsplash.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
@ -280,7 +283,7 @@
</customwidget>
</customwidgets>
<resources>
<include location="../../../FreeCAD/src/Gui/Icons/resource.qrc"/>
<include location="Icons/resource.qrc"/>
</resources>
<connections>
<connection>

View File

@ -30,6 +30,8 @@
# include <sstream>
# include <stdexcept>
# include <QCloseEvent>
# include <QDir>
# include <QFileInfo>
# include <QLocale>
# include <QMessageBox>
# include <QPointer>
@ -928,7 +930,7 @@ bool Application::activateWorkbench(const char* name)
Py::Tuple args;
Py::String result(method.apply(args));
type = result.as_std_string();
if (type == "Gui::PythonWorkbench") {
if (Base::Type::fromName(type.c_str()).isDerivedFrom(Gui::PythonBaseWorkbench::getClassTypeId())) {
Workbench* wb = WorkbenchManager::instance()->createWorkbench(name, type);
handler.setAttr(std::string("__Workbench__"), Py::Object(wb->getPyObject(), true));
}
@ -1411,6 +1413,8 @@ void Application::initTypes(void)
Gui::BlankWorkbench ::init();
Gui::NoneWorkbench ::init();
Gui::TestWorkbench ::init();
Gui::PythonBaseWorkbench ::init();
Gui::PythonBlankWorkbench ::init();
Gui::PythonWorkbench ::init();
}
@ -1567,6 +1571,8 @@ void Application::runApplication(void)
SoQt::init(&mw);
SoFCDB::init();
QString home = QString::fromUtf8(App::GetApplication().GetHomePath());
const std::map<std::string,std::string>& cfg = App::Application::Config();
std::map<std::string,std::string>::const_iterator it;
it = cfg.find("WindowTitle");
@ -1577,11 +1583,17 @@ void Application::runApplication(void)
it = cfg.find("WindowIcon");
if (it != cfg.end()) {
QString path = QString::fromUtf8(it->second.c_str());
if (QDir(path).isRelative()) {
path = QFileInfo(QDir(home), path).absoluteFilePath();
}
QApplication::setWindowIcon(QIcon(path));
}
it = cfg.find("ProgramLogo");
if (it != cfg.end()) {
QString path = QString::fromUtf8(it->second.c_str());
if (QDir(path).isRelative()) {
path = QFileInfo(QDir(home), path).absoluteFilePath();
}
QPixmap px(path);
if (!px.isNull()) {
QLabel* logo = new QLabel();

View File

@ -77,6 +77,16 @@ BitmapFactoryInst& BitmapFactoryInst::instance(void)
if (_pcSingleton == NULL)
{
_pcSingleton = new BitmapFactoryInst;
std::map<std::string,std::string>::const_iterator it;
it = App::GetApplication().Config().find("ProgramIcons");
if (it != App::GetApplication().Config().end()) {
QString home = QString::fromUtf8(App::GetApplication().GetHomePath());
QString path = QString::fromUtf8(it->second.c_str());
if (QDir(path).isRelative()) {
path = QFileInfo(QDir(home), path).absoluteFilePath();
}
_pcSingleton->addPath(path);
}
_pcSingleton->addPath(QLatin1String(":/icons/"));
_pcSingleton->addPath(QLatin1String(":/Icons/"));
_pcSingleton->addPath(QString::fromUtf8(App::GetApplication().GetHomePath()));

View File

@ -257,17 +257,11 @@ SbBool BlenderNavigationStyle::processSoEvent(const SoEvent * const ev)
this->button3down = press;
break;
case SoMouseButtonEvent::BUTTON4:
if (this->invertZoom)
zoom(viewer->getCamera(), -0.05f);
else
zoom(viewer->getCamera(), 0.05f);
doZoom(viewer->getCamera(), TRUE, posn);
processed = TRUE;
break;
case SoMouseButtonEvent::BUTTON5:
if (this->invertZoom)
zoom(viewer->getCamera(), 0.05f);
else
zoom(viewer->getCamera(), -0.05f);
doZoom(viewer->getCamera(), FALSE, posn);
processed = TRUE;
break;
default:

View File

@ -286,17 +286,11 @@ SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev)
this->button3down = press;
break;
case SoMouseButtonEvent::BUTTON4:
if (this->invertZoom)
zoom(viewer->getCamera(), -0.05f);
else
zoom(viewer->getCamera(), 0.05f);
doZoom(viewer->getCamera(), TRUE, posn);
processed = TRUE;
break;
case SoMouseButtonEvent::BUTTON5:
if (this->invertZoom)
zoom(viewer->getCamera(), 0.05f);
else
zoom(viewer->getCamera(), -0.05f);
doZoom(viewer->getCamera(), FALSE, posn);
processed = TRUE;
break;
default:

View File

@ -220,24 +220,15 @@ StdCmdExport::StdCmdExport()
void StdCmdExport::activated(int iMsg)
{
// fill the list of registered endings
QString formatList;
const char* supported = QT_TR_NOOP("Supported formats");
formatList = QObject::tr(supported);
formatList += QLatin1String(" (");
std::vector<std::string> filetypes = App::GetApplication().getExportTypes();
std::vector<std::string>::const_iterator it;
for (it=filetypes.begin();it != filetypes.end();++it) {
if (*it != "FCStd") {
// ignore the project file format
formatList += QLatin1String(" *.");
formatList += QLatin1String(it->c_str());
}
if (Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId()) == 0) {
QMessageBox::warning(Gui::getMainWindow(),
QString::fromUtf8(QT_TR_NOOP("No selection")),
QString::fromUtf8(QT_TR_NOOP("Please select first the objects you want to export.")));
return;
}
formatList += QLatin1String(");;");
// fill the list of registered endings
QString formatList;
std::map<std::string, std::string> FilterList = App::GetApplication().getExportFilters();
std::map<std::string, std::string>::const_iterator jt;
for (jt=FilterList.begin();jt != FilterList.end();++jt) {
@ -264,9 +255,7 @@ void StdCmdExport::activated(int iMsg)
bool StdCmdExport::isActive(void)
{
// at least one object should be selected otherwise it might be confusing to the user
return Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId()) > 0;
//return (getActiveGuiDocument() ? true : false);
return (getActiveGuiDocument() ? true : false);
}
//===========================================================================

View File

@ -193,7 +193,7 @@ Action * StdCmdAbout::createAction(void)
QString exe;
std::map<std::string,std::string>& cfg = App::Application::Config();
std::map<std::string,std::string>::iterator it = cfg.find("WindowTitle");
std::map<std::string,std::string>::iterator it = cfg.find("Application");
if (it != cfg.end())
exe = QString::fromUtf8(it->second.c_str());
else
@ -235,7 +235,7 @@ void StdCmdAbout::languageChange()
if (_pcAction) {
QString exe;
std::map<std::string,std::string>& cfg = App::Application::Config();
std::map<std::string,std::string>::iterator it = cfg.find("WindowTitle");
std::map<std::string,std::string>::iterator it = cfg.find("Application");
if (it != cfg.end())
exe = QString::fromUtf8(it->second.c_str());
else

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>477</width>
<height>442</height>
<height>495</height>
</rect>
</property>
<property name="windowTitle">
@ -25,7 +25,7 @@
<property name="title">
<string>3D View settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="Gui::PrefCheckBox" name="CheckBox_CornerCoordSystem">
<property name="text">
@ -130,6 +130,65 @@
</layout>
</item>
<item row="4" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="Gui::PrefCheckBox" name="checkBoxZoomAtCursor">
<property name="text">
<string>Zoom at cursor</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>ZoomAtCursor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>View</cstring>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Zoom step</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefDoubleSpinBox" name="spinBoxZoomStep">
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="value">
<double>0.050000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>ZoomStep</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>View</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="Gui::PrefCheckBox" name="checkBoxInvertZoom">
<property name="text">
<string>Invert zoom</string>
@ -142,7 +201,7 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="Gui::PrefCheckBox" name="checkBoxAntiAliasing">
<property name="text">
<string>Enable anti-aliasing (slower)</string>
@ -155,7 +214,7 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="Line" name="line1">
<property name="frameShape">
<enum>QFrame::HLine</enum>
@ -168,7 +227,7 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<layout class="QHBoxLayout" name="eyedistanceLayout">
<property name="spacing">
<number>6</number>
@ -210,7 +269,7 @@
</item>
</layout>
</item>
<item row="8" column="0">
<item row="9" column="0">
<layout class="QGridLayout" name="backlightLayout">
<property name="margin">
<number>11</number>
@ -399,6 +458,8 @@
<tabstop>comboNavigationStyle</tabstop>
<tabstop>mouseButton</tabstop>
<tabstop>comboOrbitStyle</tabstop>
<tabstop>checkBoxZoomAtCursor</tabstop>
<tabstop>spinBoxZoomStep</tabstop>
<tabstop>checkBoxInvertZoom</tabstop>
<tabstop>checkBoxAntiAliasing</tabstop>
<tabstop>FloatSpinBox_EyeDistance</tabstop>

View File

@ -72,7 +72,9 @@ void DlgSettings3DViewImp::saveSettings()
int index = comboOrbitStyle->currentIndex();
hGrp->SetInt("OrbitStyle", index);
checkBoxZoomAtCursor->onSave();
checkBoxInvertZoom->onSave();
spinBoxZoomStep->onSave();
checkBoxAntiAliasing->onSave();
CheckBox_CornerCoordSystem->onSave();
CheckBox_ShowFPS->onSave();
@ -87,7 +89,9 @@ void DlgSettings3DViewImp::saveSettings()
void DlgSettings3DViewImp::loadSettings()
{
checkBoxZoomAtCursor->onRestore();
checkBoxInvertZoom->onRestore();
spinBoxZoomStep->onRestore();
checkBoxAntiAliasing->onRestore();
CheckBox_CornerCoordSystem->onRestore();
CheckBox_ShowFPS->onRestore();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 119 KiB

View File

@ -251,17 +251,11 @@ SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev)
this->button3down = press;
break;
case SoMouseButtonEvent::BUTTON4:
if (this->invertZoom)
zoom(viewer->getCamera(), -0.05f);
else
zoom(viewer->getCamera(), 0.05f);
doZoom(viewer->getCamera(), TRUE, posn);
processed = TRUE;
break;
case SoMouseButtonEvent::BUTTON5:
if (this->invertZoom)
zoom(viewer->getCamera(), 0.05f);
else
zoom(viewer->getCamera(), -0.05f);
doZoom(viewer->getCamera(), FALSE, posn);
processed = TRUE;
break;
default:

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@
# include <QLabel>
# include <QMdiSubWindow>
# include <QMessageBox>
# include <QPainter>
# include <QSettings>
# include <QSignalMapper>
# include <QStatusBar>
@ -1302,7 +1303,45 @@ QPixmap MainWindow::splashImage() const
if (fi.isFile() && fi.exists())
splash_image.load(fi.filePath(), "PNG");
if (splash_image.isNull())
splash_image = Gui::BitmapFactory().pixmap(App::Application::Config()["SplashPicture"].c_str());
splash_image = Gui::BitmapFactory().pixmap(App::Application::Config()["SplashScreen"].c_str());
// include application name and version number
std::map<std::string,std::string>::const_iterator tc = App::Application::Config().find("SplashInfoColor");
if (tc != App::Application::Config().end()) {
QString title = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
std::map<std::string,std::string>::iterator it = App::Application::Config().find("Application");
if (it != App::Application::Config().end())
title = QString::fromUtf8(it->second.c_str());
QString major = QString::fromAscii(App::Application::Config()["BuildVersionMajor"].c_str());
QString minor = QString::fromAscii(App::Application::Config()["BuildVersionMinor"].c_str());
QString version = QString::fromAscii("%1.%2").arg(major).arg(minor);
QPainter painter;
painter.begin(&splash_image);
QFont fontExe = painter.font();
fontExe.setPointSize(20);
QFontMetrics metricExe(fontExe);
int l = metricExe.width(title);
int w = splash_image.width();
int h = splash_image.height();
QFont fontVer = painter.font();
fontVer.setPointSize(12);
QFontMetrics metricVer(fontVer);
int v = metricVer.width(version);
QColor color;
color.setNamedColor(QString::fromAscii(tc->second.c_str()));
if (color.isValid()) {
painter.setPen(color);
painter.setFont(fontExe);
painter.drawText(w-(l+v+10),h-20, title);
painter.setFont(fontVer);
painter.drawText(w-(v+5),h-20, version);
painter.end();
}
}
return splash_image;
}

View File

@ -113,8 +113,14 @@ public:
else {
SbVec3f zaxis(0,0,1);
this->worldToScreen.multDirMatrix(zaxis, zaxis);
if (dif[0] > 0)
angle = -angle;
if (zaxis[1] < 0) {
if (dif[0] < 0)
angle = -angle;
}
else {
if (dif[0] > 0)
angle = -angle;
}
rot.setValue(zaxis, angle);
}
@ -176,6 +182,8 @@ NavigationStyle& NavigationStyle::operator = (const NavigationStyle& ns)
this->panningplane = ns.panningplane;
this->menuenabled = ns.menuenabled;
this->spinanimatingallowed = ns.spinanimatingallowed;
static_cast<FCSphereSheetProjector*>(this->spinprojector)->setOrbitStyle
(static_cast<FCSphereSheetProjector*>(ns.spinprojector)->getOrbitStyle());
return *this;
}
@ -215,6 +223,10 @@ void NavigationStyle::initialize()
this->altdown = FALSE;
this->invertZoom = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/View")->GetBool("InvertZoom",false);
this->zoomAtCursor = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/View")->GetBool("ZoomAtCursor",false);
this->zoomStep = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/View")->GetFloat("ZoomStep",0.05f);
}
void NavigationStyle::finalize()
@ -709,6 +721,33 @@ void NavigationStyle::zoomByCursor(const SbVec2f & thispos, const SbVec2f & prev
zoom(viewer->getCamera(), (thispos[1] - prevpos[1]) * 10.0f/*20.0f*/);
}
void NavigationStyle::doZoom(SoCamera* camera, SbBool forward, const SbVec2f& pos)
{
SbBool zoomAtCur = this->zoomAtCursor;
if (zoomAtCur) {
const SbViewportRegion & vp = viewer->getViewportRegion();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = camera->getViewVolume(vp.getViewportAspectRatio());
SbPlane panplane = vv.getPlane(camera->focalDistance.getValue());
panCamera(viewer->getCamera(), ratio, panplane, SbVec2f(0.5,0.5), pos);
}
float value = this->zoomStep;
if (!forward)
value = -value;
if (this->invertZoom)
value = -value;
zoom(camera, value);
if (zoomAtCur) {
const SbViewportRegion & vp = viewer->getViewportRegion();
float ratio = vp.getViewportAspectRatio();
SbViewVolume vv = camera->getViewVolume(vp.getViewportAspectRatio());
SbPlane panplane = vv.getPlane(camera->focalDistance.getValue());
panCamera(viewer->getCamera(), ratio, panplane, pos, SbVec2f(0.5,0.5));
}
}
/** Uses the sphere sheet projector to map the mouseposition onto
* a 3D point and find a rotation from this and the last calculated point.
*/
@ -884,6 +923,21 @@ SbBool NavigationStyle::isZoomInverted() const
return this->invertZoom;
}
void NavigationStyle::setZoomStep(float val)
{
this->zoomStep = val;
}
void NavigationStyle::setZoomAtCursor(SbBool on)
{
this->zoomAtCursor = on;
}
SbBool NavigationStyle::isZoomAtCursor() const
{
return this->zoomAtCursor;
}
void NavigationStyle::startSelection(AbstractMouseSelection* mouse)
{
if (!mouse)

View File

@ -111,6 +111,9 @@ public:
void setZoomInverted(SbBool);
SbBool isZoomInverted() const;
void setZoomStep(float);
void setZoomAtCursor(SbBool);
SbBool isZoomAtCursor() const;
void updateAnimation();
void redraw();
@ -162,6 +165,7 @@ protected:
void panToCenter(const SbPlane & pplane, const SbVec2f & currpos);
void zoom(SoCamera * camera, float diffvalue);
void zoomByCursor(const SbVec2f & thispos, const SbVec2f & prevpos);
void doZoom(SoCamera * camera, SbBool forward, const SbVec2f& pos);
void spin(const SbVec2f & pointerpos);
SbBool doSpin();
@ -191,6 +195,8 @@ protected:
SbBool ctrldown, shiftdown, altdown;
SbBool button1down, button2down, button3down;
SbBool invertZoom;
SbBool zoomAtCursor;
float zoomStep;
/** @name Mouse model */
//@{

View File

@ -392,7 +392,7 @@ PythonConsole::PythonConsole(QWidget *parent)
"Type 'help', 'copyright', 'credits' or 'license' for more information.")
.arg(QString::fromAscii(version)).arg(QString::fromAscii(platform));
d->output = d->info;
printPrompt(false);
printPrompt(PythonConsole::Complete);
}
/** Destroys the object and frees any allocated resources */
@ -504,7 +504,9 @@ void PythonConsole::keyPressEvent(QKeyEvent * e)
d->history.append( QLatin1String("# ") + inputLine ); //< put line to history ...
inputLineBegin.insertText( QString::fromAscii("# ") ); //< but comment it on console
setTextCursor( inputLineBegin );
printPrompt( d->interpreter->hasPendingInput() ); //< print adequate prompt
printPrompt(d->interpreter->hasPendingInput() //< print adequate prompt
? PythonConsole::Incomplete
: PythonConsole::Complete);
}
} break;
@ -600,10 +602,15 @@ void PythonConsole::insertPythonError ( const QString& err )
d->error += err;
}
void PythonConsole::onFlush()
{
printPrompt(PythonConsole::Flush);
}
/** Prints the ps1 prompt (>>> ) for complete and ps2 prompt (... ) for
* incomplete commands to the console window.
*/
void PythonConsole::printPrompt(bool incomplete)
void PythonConsole::printPrompt(PythonConsole::Prompt mode)
{
// write normal messages
if (!d->output.isEmpty()) {
@ -632,8 +639,17 @@ void PythonConsole::printPrompt(bool incomplete)
else
block.setUserState(0);
incomplete ? cursor.insertText(QString::fromAscii("... "))
: cursor.insertText(QString::fromAscii(">>> "));
switch (mode)
{
case PythonConsole::Incomplete:
cursor.insertText(QString::fromAscii("... "));
break;
case PythonConsole::Complete:
cursor.insertText(QString::fromAscii(">>> "));
break;
default:
break;
}
cursor.endEditBlock();
// move cursor to the end
@ -706,9 +722,10 @@ void PythonConsole::runSource(const QString& line)
QMessageBox::critical(this, tr("Python console"), tr("Unhandled unknown C++ exception."));
}
printPrompt(incomplete ? PythonConsole::Incomplete
: PythonConsole::Complete);
PySys_SetObject("stdout", default_stdout);
PySys_SetObject("stderr", default_stderr);
printPrompt(incomplete);
d->interactive = false;
for (QStringList::Iterator it = d->statements.begin(); it != d->statements.end(); ++it)
printStatement(*it);
@ -751,7 +768,7 @@ void PythonConsole::printStatement( const QString& cmd )
cursor.movePosition(QTextCursor::End);
cursor.insertText( *it );
d->history.append( *it );
printPrompt(false);
printPrompt(PythonConsole::Complete);
}
}
@ -984,7 +1001,7 @@ void PythonConsole::runSourceFromMimeData(const QString& source)
buffer.append(line);
int ret = d->interpreter->compileCommand(buffer.join(QLatin1String("\n")).toUtf8());
if (ret == 1) { // incomplete
printPrompt(true);
printPrompt(PythonConsole::Incomplete);
}
else if (ret == 0) { // complete
// check if the following lines belong to the previous block
@ -1001,7 +1018,7 @@ void PythonConsole::runSourceFromMimeData(const QString& source)
// is finished
if (ret == -1) {
// the command is not finished yet
printPrompt(true);
printPrompt(PythonConsole::Incomplete);
}
else {
runSource(buffer.join(QLatin1String("\n")));
@ -1094,7 +1111,7 @@ void PythonConsole::onClearConsole()
{
clear();
d->output = d->info;
printPrompt(false);
printPrompt(PythonConsole::Complete);
}
void PythonConsole::onSaveHistoryAs()
@ -1312,6 +1329,7 @@ PythonInputField::PythonInputField(QWidget* parent)
editField = new PythonEditor(this);
gridLayout->addWidget(editField, 0, 0, 1, 1);
setFocusProxy(editField);
QHBoxLayout* hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(6);

View File

@ -96,6 +96,12 @@ class GuiExport PythonConsole : public TextEdit, public WindowParameter
Q_OBJECT
public:
enum Prompt {
Complete = 0,
Incomplete = 1,
Flush = 2
};
PythonConsole(QWidget *parent = 0);
~PythonConsole();
@ -108,6 +114,7 @@ public Q_SLOTS:
void onCopyHistory();
void onCopyCommand();
void onClearConsole();
void onFlush();
private Q_SLOTS:
void visibilityChanged (bool visible);
@ -131,7 +138,7 @@ protected:
private:
void runSource(const QString&);
bool isComment(const QString&) const;
void printPrompt(bool);
void printPrompt(Prompt);
void insertPythonOutput(const QString&);
void insertPythonError (const QString&);
void runSourceFromMimeData(const QString&);

View File

@ -26,6 +26,7 @@
# include <QByteArray>
# include <QInputDialog>
# include <QEventLoop>
# include <QTimer>
#endif
#include "PythonConsolePy.h"
@ -292,12 +293,18 @@ PythonStdin::PythonStdin(PythonConsole *pc)
: pyConsole(pc)
{
editField = new PythonInputField(/*getMainWindow()*/);
timer = new QTimer();
timer->setInterval(250);
QObject::connect(timer, SIGNAL(timeout()),
editField, SLOT(hide()));
console = getMainWindow()->findChild<PythonConsole*>();
}
PythonStdin::~PythonStdin()
{
// call deleteLater() because deleting immediately causes problems
editField->deleteLater();
timer->deleteLater();
}
Py::Object PythonStdin::repr()
@ -310,14 +317,16 @@ Py::Object PythonStdin::repr()
Py::Object PythonStdin::readline(const Py::Tuple& args)
{
if (console)
console->onFlush();
timer->stop();
QEventLoop loop;
QObject::connect(editField, SIGNAL(textEntered()), &loop, SLOT(quit()));
editField->clear();
editField->show();
editField->setFocus();
loop.exec();
QString txt = editField->getText();
if (txt.isEmpty())
editField->hide();
timer->start();
return Py::String((const char*)txt.toAscii());
}

View File

@ -26,6 +26,8 @@
#include <CXX/Extensions.hxx>
class QTimer;
namespace Gui {
class PythonConsole;
class PythonInputField;
@ -140,6 +142,8 @@ public:
private:
PythonInputField* editField;
PythonConsole* console;
QTimer* timer;
};
} // namespace Gui

View File

@ -3,8 +3,8 @@
<PythonExport
Father="WorkbenchPy"
Name="PythonWorkbenchPy"
Twin="PythonWorkbench"
TwinPointer="PythonWorkbench"
Twin="PythonBaseWorkbench"
TwinPointer="PythonBaseWorkbench"
Include="Gui/Workbench.h"
Namespace="Gui"
FatherInclude="Gui/WorkbenchPy.h"

View File

@ -96,7 +96,7 @@ PyObject* PythonWorkbenchPy::appendMenu(PyObject *args)
return NULL; // NULL triggers exception
}
getPythonWorkbenchPtr()->appendMenu( path, items );
getPythonBaseWorkbenchPtr()->appendMenu( path, items );
Py_Return;
} PY_CATCH;
@ -110,7 +110,7 @@ PyObject* PythonWorkbenchPy::removeMenu(PyObject *args)
if (!PyArg_ParseTuple(args, "s", &psMenu)) // convert args: Python->C
return NULL; // NULL triggers exception
getPythonWorkbenchPtr()->removeMenu( psMenu );
getPythonBaseWorkbenchPtr()->removeMenu( psMenu );
Py_Return;
} PY_CATCH;
}
@ -119,7 +119,7 @@ PyObject* PythonWorkbenchPy::removeMenu(PyObject *args)
PyObject* PythonWorkbenchPy::listMenus(PyObject *args)
{
PY_TRY {
std::list<std::string> menus = getPythonWorkbenchPtr()->listMenus();
std::list<std::string> menus = getPythonBaseWorkbenchPtr()->listMenus();
PyObject* pyList = PyList_New(menus.size());
int i=0;
@ -180,7 +180,7 @@ PyObject* PythonWorkbenchPy::appendContextMenu(PyObject *args)
return NULL; // NULL triggers exception
}
getPythonWorkbenchPtr()->appendContextMenu( path, items );
getPythonBaseWorkbenchPtr()->appendContextMenu( path, items );
Py_Return;
} PY_CATCH;
@ -194,7 +194,7 @@ PyObject* PythonWorkbenchPy::removeContextMenu(PyObject *args)
if (!PyArg_ParseTuple(args, "s", &psMenu)) // convert args: Python->C
return NULL; // NULL triggers exception
getPythonWorkbenchPtr()->removeContextMenu( psMenu );
getPythonBaseWorkbenchPtr()->removeContextMenu( psMenu );
Py_Return;
} PY_CATCH;
}
@ -222,7 +222,7 @@ PyObject* PythonWorkbenchPy::appendToolbar(PyObject *args)
items.push_back(pItem);
}
getPythonWorkbenchPtr()->appendToolbar( psToolBar, items );
getPythonBaseWorkbenchPtr()->appendToolbar( psToolBar, items );
Py_Return;
} PY_CATCH;
@ -236,7 +236,7 @@ PyObject* PythonWorkbenchPy::removeToolbar(PyObject *args)
if (!PyArg_ParseTuple(args, "s", &psToolBar)) // convert args: Python->C
return NULL; // NULL triggers exception
getPythonWorkbenchPtr()->removeToolbar( psToolBar );
getPythonBaseWorkbenchPtr()->removeToolbar( psToolBar );
Py_Return;
} PY_CATCH;
}
@ -245,7 +245,7 @@ PyObject* PythonWorkbenchPy::removeToolbar(PyObject *args)
PyObject* PythonWorkbenchPy::listToolbars(PyObject *args)
{
PY_TRY {
std::list<std::string> bars = getPythonWorkbenchPtr()->listToolbars();
std::list<std::string> bars = getPythonBaseWorkbenchPtr()->listToolbars();
PyObject* pyList = PyList_New(bars.size());
int i=0;
@ -280,7 +280,7 @@ PyObject* PythonWorkbenchPy::appendCommandbar(PyObject *args)
items.push_back(pItem);
}
getPythonWorkbenchPtr()->appendCommandbar( psToolBar, items );
getPythonBaseWorkbenchPtr()->appendCommandbar( psToolBar, items );
Py_Return;
} PY_CATCH;
@ -294,7 +294,7 @@ PyObject* PythonWorkbenchPy::removeCommandbar(PyObject *args)
if (!PyArg_ParseTuple(args, "s", &psToolBar)) // convert args: Python->C
return NULL; // NULL triggers exception
getPythonWorkbenchPtr()->removeCommandbar( psToolBar );
getPythonBaseWorkbenchPtr()->removeCommandbar( psToolBar );
Py_Return;
} PY_CATCH;
}
@ -303,7 +303,7 @@ PyObject* PythonWorkbenchPy::removeCommandbar(PyObject *args)
PyObject* PythonWorkbenchPy::listCommandbars(PyObject *args)
{
PY_TRY {
std::list<std::string> bars = getPythonWorkbenchPtr()->listCommandbars();
std::list<std::string> bars = getPythonBaseWorkbenchPtr()->listCommandbars();
PyObject* pyList = PyList_New(bars.size());
int i=0;

View File

@ -256,7 +256,7 @@ void AboutDialog::setupLabels()
std::map<std::string,std::string>::iterator it = config.find("WindowTitle");
if (it != config.end())
exeName = QString::fromUtf8(it->second.c_str());
QString banner = QString::fromUtf8(config["ConsoleBanner"].c_str());
QString banner = QString::fromUtf8(config["CopyrightInfo"].c_str());
banner = banner.left( banner.indexOf(QLatin1Char('\n')) );
QString major = QString::fromAscii(config["BuildVersionMajor"].c_str());
QString minor = QString::fromAscii(config["BuildVersionMinor"].c_str());
@ -266,7 +266,7 @@ void AboutDialog::setupLabels()
QString author = ui->labelAuthor->text();
author.replace(QString::fromAscii("Unknown Application"), exeName);
author.replace(QString::fromAscii("Unknown Author"), banner);
author.replace(QString::fromAscii("(c) Unknown Author"), banner);
ui->labelAuthor->setText(author);
ui->labelAuthor->setUrl(mturl);

View File

@ -154,17 +154,11 @@ SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev)
this->setViewing(true);
break;
case SoKeyboardEvent::PAGE_UP:
if (this->invertZoom)
zoom(viewer->getCamera(), 0.05f);
else
zoom(viewer->getCamera(), -0.05f);
doZoom(viewer->getCamera(), TRUE, posn);
processed = TRUE;
break;
case SoKeyboardEvent::PAGE_DOWN:
if (this->invertZoom)
zoom(viewer->getCamera(), -0.05f);
else
zoom(viewer->getCamera(), 0.05f);
doZoom(viewer->getCamera(), FALSE, posn);
processed = TRUE;
break;
default:

View File

@ -276,6 +276,14 @@ void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::M
bool on = rGrp.GetBool("InvertZoom", false);
_viewer->navigationStyle()->setZoomInverted(on);
}
else if (strcmp(Reason,"ZoomAtCursor") == 0) {
bool on = rGrp.GetBool("ZoomAtCursor", false);
_viewer->navigationStyle()->setZoomAtCursor(on);
}
else if (strcmp(Reason,"ZoomSetp") == 0) {
float val = rGrp.GetFloat("ZoomSetp", 0.0f);
_viewer->navigationStyle()->setZoomStep(val);
}
else if (strcmp(Reason,"EyeDistance") == 0) {
_viewer->setStereoOffset(rGrp.GetFloat("EyeDistance",65.0));
}

View File

@ -74,6 +74,7 @@
# include <Inventor/VRMLnodes/SoVRMLGroup.h>
# include <QEventLoop>
# include <QKeyEvent>
# include <QWheelEvent>
# include <QMessageBox>
# include <QTimer>
# include <QStatusBar>
@ -1033,6 +1034,14 @@ void View3DInventorViewer::selectAll()
*/
void View3DInventorViewer::processEvent(QEvent * event)
{
// Bug #0000607: Some mices also support horizontal scrolling which however might
// lead to some unwanted zooming when pressing the MMB for panning.
// Thus, we filter out horizontal scrolling.
if (event->type() == QEvent::Wheel) {
QWheelEvent* we = static_cast<QWheelEvent*>(event);
if (we->orientation() == Qt::Horizontal)
return;
}
if (event->type() == QEvent::KeyPress) {
QKeyEvent* ke = static_cast<QKeyEvent*>(event);
if (ke->matches(QKeySequence::SelectAll)) {

View File

@ -173,6 +173,7 @@ using namespace Gui;
* \section moredetails More details and limitations
* One of the key concepts of the workbench framework is to load a module at runtime when the user needs some function that it
* provides. So, if the user doesn't need a module it never gets loaded into RAM. This speeds up the startup procedure of
* FreeCAD and saves memory.
* At startup FreeCAD scans all module directories and invokes InitGui.py. So an item for a workbench gets created. If the user
* clicks on such an item the matching module gets loaded, the C++ workbench gets registered and activated.
@ -402,15 +403,16 @@ void StdWorkbench::setupContextMenu(const char* recipient, MenuItem* item) const
<< "Separator" << "Std_ViewDockUndockFullscreen";
if (Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId()) > 0 )
*item << "Separator" << "Std_SetAppearance" << "Std_ToggleVisibility" << "Std_TreeSelection"
*item << "Separator" << "Std_SetAppearance" << "Std_ToggleVisibility"
<< "Std_ToggleSelectability" << "Std_TreeSelection"
<< "Std_RandomColor" << "Separator" << "Std_Delete";
}
else if (strcmp(recipient,"Tree") == 0)
{
if (Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId()) > 0 )
*item << "Std_ToggleVisibility" << "Std_ShowSelection" << "Std_HideSelection"
<< "Separator" << "Std_SetAppearance" << "Std_RandomColor"
<< "Separator" << "Std_Delete";
<< "Std_ToggleSelectability" << "Separator" << "Std_SetAppearance"
<< "Std_RandomColor" << "Separator" << "Std_Delete";
}
}
@ -750,30 +752,26 @@ ToolBarItem* TestWorkbench::setupCommandBars() const
// -----------------------------------------------------------------------
TYPESYSTEM_SOURCE(Gui::PythonWorkbench, Gui::Workbench)
TYPESYSTEM_SOURCE(Gui::PythonBaseWorkbench, Gui::Workbench)
PythonWorkbench::PythonWorkbench() : _workbenchPy(0)
PythonBaseWorkbench::PythonBaseWorkbench()
: _menuBar(0), _contextMenu(0), _toolBar(0), _commandBar(0), _workbenchPy(0)
{
_menuBar = StdWorkbench::setupMenuBar();
_contextMenu = new MenuItem;
_toolBar = StdWorkbench::setupToolBars();
_commandBar = new ToolBarItem;
}
PythonWorkbench::~PythonWorkbench()
PythonBaseWorkbench::~PythonBaseWorkbench()
{
delete _menuBar;
delete _contextMenu;
delete _toolBar;
delete _commandBar;
if (_workbenchPy)
{
if (_workbenchPy) {
_workbenchPy->setInvalid();
_workbenchPy->DecRef();
}
}
PyObject* PythonWorkbench::getPyObject()
PyObject* PythonBaseWorkbench::getPyObject()
{
if (!_workbenchPy)
{
@ -786,31 +784,35 @@ PyObject* PythonWorkbench::getPyObject()
return _workbenchPy;
}
MenuItem* PythonWorkbench::setupMenuBar() const
MenuItem* PythonBaseWorkbench::setupMenuBar() const
{
return _menuBar->copy();
}
ToolBarItem* PythonWorkbench::setupToolBars() const
ToolBarItem* PythonBaseWorkbench::setupToolBars() const
{
return _toolBar->copy();
}
ToolBarItem* PythonWorkbench::setupCommandBars() const
ToolBarItem* PythonBaseWorkbench::setupCommandBars() const
{
return _commandBar->copy();
}
void PythonWorkbench::setupContextMenu(const char* recipient, MenuItem* item) const
DockWindowItems* PythonBaseWorkbench::setupDockWindows() const
{
return new DockWindowItems();
}
void PythonBaseWorkbench::setupContextMenu(const char* recipient, MenuItem* item) const
{
StdWorkbench::setupContextMenu(recipient, item);
QList<MenuItem*> items = _contextMenu->getItems();
for (QList<MenuItem*>::Iterator it = items.begin(); it != items.end(); ++it) {
item->appendItem((*it)->copy());
}
}
void PythonWorkbench::appendMenu(const std::list<std::string>& menu, const std::list<std::string>& items) const
void PythonBaseWorkbench::appendMenu(const std::list<std::string>& menu, const std::list<std::string>& items) const
{
if ( menu.empty() || items.empty() )
return;
@ -841,7 +843,7 @@ void PythonWorkbench::appendMenu(const std::list<std::string>& menu, const std::
*item << *it;
}
void PythonWorkbench::removeMenu(const std::string& menu) const
void PythonBaseWorkbench::removeMenu(const std::string& menu) const
{
MenuItem* item = _menuBar->findItem(menu);
if ( item ) {
@ -850,7 +852,7 @@ void PythonWorkbench::removeMenu(const std::string& menu) const
}
}
std::list<std::string> PythonWorkbench::listMenus() const
std::list<std::string> PythonBaseWorkbench::listMenus() const
{
std::list<std::string> menus;
QList<MenuItem*> items = _menuBar->getItems();
@ -859,7 +861,7 @@ std::list<std::string> PythonWorkbench::listMenus() const
return menus;
}
void PythonWorkbench::appendContextMenu(const std::list<std::string>& menu, const std::list<std::string>& items) const
void PythonBaseWorkbench::appendContextMenu(const std::list<std::string>& menu, const std::list<std::string>& items) const
{
MenuItem* item = _contextMenu;
for (std::list<std::string>::const_iterator jt=menu.begin();jt!=menu.end();++jt) {
@ -875,7 +877,7 @@ void PythonWorkbench::appendContextMenu(const std::list<std::string>& menu, cons
*item << *it;
}
void PythonWorkbench::removeContextMenu(const std::string& menu) const
void PythonBaseWorkbench::removeContextMenu(const std::string& menu) const
{
MenuItem* item = _contextMenu->findItem(menu);
if (item) {
@ -884,12 +886,12 @@ void PythonWorkbench::removeContextMenu(const std::string& menu) const
}
}
void PythonWorkbench::clearContextMenu()
void PythonBaseWorkbench::clearContextMenu()
{
_contextMenu->clear();
}
void PythonWorkbench::appendToolbar(const std::string& bar, const std::list<std::string>& items) const
void PythonBaseWorkbench::appendToolbar(const std::string& bar, const std::list<std::string>& items) const
{
ToolBarItem* item = _toolBar->findItem(bar);
if (!item)
@ -902,7 +904,7 @@ void PythonWorkbench::appendToolbar(const std::string& bar, const std::list<std:
*item << *it;
}
void PythonWorkbench::removeToolbar(const std::string& bar) const
void PythonBaseWorkbench::removeToolbar(const std::string& bar) const
{
ToolBarItem* item = _toolBar->findItem(bar);
if (item) {
@ -911,7 +913,7 @@ void PythonWorkbench::removeToolbar(const std::string& bar) const
}
}
std::list<std::string> PythonWorkbench::listToolbars() const
std::list<std::string> PythonBaseWorkbench::listToolbars() const
{
std::list<std::string> bars;
QList<ToolBarItem*> items = _toolBar->getItems();
@ -920,7 +922,7 @@ std::list<std::string> PythonWorkbench::listToolbars() const
return bars;
}
void PythonWorkbench::appendCommandbar(const std::string& bar, const std::list<std::string>& items) const
void PythonBaseWorkbench::appendCommandbar(const std::string& bar, const std::list<std::string>& items) const
{
ToolBarItem* item = _commandBar->findItem( bar );
if ( !item )
@ -933,7 +935,7 @@ void PythonWorkbench::appendCommandbar(const std::string& bar, const std::list<s
*item << *it;
}
void PythonWorkbench::removeCommandbar(const std::string& bar) const
void PythonBaseWorkbench::removeCommandbar(const std::string& bar) const
{
ToolBarItem* item = _commandBar->findItem(bar);
if ( item ) {
@ -942,7 +944,7 @@ void PythonWorkbench::removeCommandbar(const std::string& bar) const
}
}
std::list<std::string> PythonWorkbench::listCommandbars() const
std::list<std::string> PythonBaseWorkbench::listCommandbars() const
{
std::list<std::string> bars;
QList<ToolBarItem*> items = _commandBar->getItems();
@ -951,3 +953,69 @@ std::list<std::string> PythonWorkbench::listCommandbars() const
return bars;
}
// -----------------------------------------------------------------------
TYPESYSTEM_SOURCE(Gui::PythonBlankWorkbench, Gui::PythonBaseWorkbench)
PythonBlankWorkbench::PythonBlankWorkbench()
{
_menuBar = new MenuItem;
_contextMenu = new MenuItem;
_toolBar = new ToolBarItem;
_commandBar = new ToolBarItem;
}
PythonBlankWorkbench::~PythonBlankWorkbench()
{
}
// -----------------------------------------------------------------------
TYPESYSTEM_SOURCE(Gui::PythonWorkbench, Gui::PythonBaseWorkbench)
PythonWorkbench::PythonWorkbench()
{
StdWorkbench wb;
_menuBar = wb.setupMenuBar();
_contextMenu = new MenuItem;
_toolBar = wb.setupToolBars();
_commandBar = new ToolBarItem;
}
PythonWorkbench::~PythonWorkbench()
{
}
MenuItem* PythonWorkbench::setupMenuBar() const
{
return _menuBar->copy();
}
ToolBarItem* PythonWorkbench::setupToolBars() const
{
return _toolBar->copy();
}
ToolBarItem* PythonWorkbench::setupCommandBars() const
{
return _commandBar->copy();
}
DockWindowItems* PythonWorkbench::setupDockWindows() const
{
StdWorkbench wb;
return wb.setupDockWindows();
}
void PythonWorkbench::setupContextMenu(const char* recipient, MenuItem* item) const
{
StdWorkbench wb;
wb.setupContextMenu(recipient, item);
PythonBaseWorkbench::setupContextMenu(recipient, item);
}
void PythonWorkbench::createMainWindowPopupMenu(MenuItem* item) const
{
StdWorkbench wb;
wb.createMainWindowPopupMenu(item);
}

View File

@ -144,6 +144,8 @@ protected:
virtual ToolBarItem* setupCommandBars() const;
/** Returns a DockWindowItems structure of dock windows this workbench. */
virtual DockWindowItems* setupDockWindows() const;
friend class PythonWorkbench;
};
/**
@ -217,17 +219,17 @@ protected:
};
/**
* The PythonWorkbench class allows the manipulation of the workbench from Python.
* The PythonBaseWorkbench class allows the manipulation of the workbench from Python.
* Therefore PythonWorkbenchPy provides the required Python interface.
* @author Werner Mayer
*/
class GuiExport PythonWorkbench : public StdWorkbench
class GuiExport PythonBaseWorkbench : public Workbench
{
TYPESYSTEM_HEADER();
public:
PythonWorkbench();
~PythonWorkbench();
PythonBaseWorkbench();
~PythonBaseWorkbench();
/**
* Creates and returns immediately the corresponding Python workbench object.
*/
@ -268,8 +270,9 @@ protected:
MenuItem* setupMenuBar() const;
ToolBarItem* setupToolBars() const;
ToolBarItem* setupCommandBars() const;
DockWindowItems* setupDockWindows() const;
private:
protected:
MenuItem* _menuBar;
MenuItem* _contextMenu;
ToolBarItem* _toolBar;
@ -277,6 +280,39 @@ private:
Base::PyObjectBase* _workbenchPy;
};
class GuiExport PythonBlankWorkbench : public PythonBaseWorkbench
{
TYPESYSTEM_HEADER();
public:
PythonBlankWorkbench();
~PythonBlankWorkbench();
};
/**
* The PythonWorkbench class allows the manipulation of the workbench from Python.
* Therefore PythonWorkbenchPy provides the required Python interface.
* @author Werner Mayer
*/
class GuiExport PythonWorkbench : public PythonBaseWorkbench
{
TYPESYSTEM_HEADER();
public:
PythonWorkbench();
~PythonWorkbench();
/** Defines the standard context menu. */
virtual void setupContextMenu(const char* recipient, MenuItem*) const;
virtual void createMainWindowPopupMenu(MenuItem*) const;
protected:
MenuItem* setupMenuBar() const;
ToolBarItem* setupToolBars() const;
ToolBarItem* setupCommandBars() const;
DockWindowItems* setupDockWindows() const;
};
} // namespace Gui

View File

@ -303,8 +303,8 @@ PyMODINIT_FUNC initFreeCADGui()
try {
Base::Interpreter().loadModule("FreeCAD");
App::Application::Config()["AppIcon"] = "freecad";
App::Application::Config()["SplashPicture"] = "freecadsplash";
App::Application::Config()["ConsoleBanner"] = "\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre 2001-2011\n";
App::Application::Config()["SplashScreen"] = "freecadsplash";
App::Application::Config()["CopyrightInfo"] = "\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre 2001-2011\n";
Gui::Application::initApplication();
Py_InitModule("FreeCADGui", FreeCADGui_methods);
}

View File

@ -79,7 +79,7 @@ int main( int argc, char ** argv )
App::Application::Config()["AppDataSkipVendor"] = "true";
// set the banner (for logging and console)
App::Application::Config()["ConsoleBanner"] = sBanner;
App::Application::Config()["CopyrightInfo"] = sBanner;
try {
// Init phase ===========================================================

View File

@ -35,6 +35,10 @@
# include <config.h>
#endif // HAVE_CONFIG_H
#include <map>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <QApplication>
#include <QFile>
@ -74,16 +78,31 @@ const char sBanner[] = "\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre 2
class Branding
{
public:
struct UserDefines
{
std::string windowTitle;
std::string windowIcon;
std::string programLogo;
std::string splashScreen;
};
typedef std::map<std::string, std::string> XmlConfig;
Branding()
{
filter.push_back("Application");
filter.push_back("WindowTitle");
filter.push_back("CopyrightInfo");
filter.push_back("MaintainerUrl");
filter.push_back("WindowIcon");
filter.push_back("ProgramLogo");
filter.push_back("ProgramIcons");
filter.push_back("BuildVersionMajor");
filter.push_back("BuildVersionMinor");
filter.push_back("BuildRevision");
filter.push_back("BuildRevisionDate");
filter.push_back("SplashScreen");
filter.push_back("SplashAlignment");
filter.push_back("SplashTextColor");
filter.push_back("SplashInfoColor");
filter.push_back("StartWorkbench");
filter.push_back("ExeName");
filter.push_back("ExeVendor");
}
bool readFile(const QString& fn)
@ -96,29 +115,26 @@ public:
file.close();
return true;
}
UserDefines getUserDefines() const
XmlConfig getUserDefines() const
{
UserDefines ud;
XmlConfig cfg;
QDomElement root = domDocument.documentElement();
QDomElement child;
if (!root.isNull()) {
child = root.firstChildElement(QLatin1String("WindowTitle"));
if (!child.isNull())
ud.windowTitle = (const char*)child.text().toUtf8();
child = root.firstChildElement(QLatin1String("WindowIcon"));
if (!child.isNull())
ud.windowIcon = (const char*)child.text().toUtf8();
child = root.firstChildElement(QLatin1String("ProgramLogo"));
if (!child.isNull())
ud.programLogo = (const char*)child.text().toUtf8();
child = root.firstChildElement(QLatin1String("SplashScreen"));
if (!child.isNull())
ud.splashScreen = (const char*)child.text().toUtf8();
child = root.firstChildElement();
while (!child.isNull()) {
std::string name = (const char*)child.localName().toAscii();
std::string value = (const char*)child.text().toUtf8();
if (std::find(filter.begin(), filter.end(), name) != filter.end())
cfg[name] = value;
child = child.nextSiblingElement();
}
}
return ud;
return cfg;
}
private:
std::vector<std::string> filter;
bool evaluateXML(QIODevice *device, QDomDocument& xmlDocument)
{
QString errorStr;
@ -269,13 +285,14 @@ int main( int argc, char ** argv )
App::Application::Config()["MaintainerUrl"] = "http://apps.sourceforge.net/mediawiki/free-cad/index.php?title=Main_Page";
// set the banner (for logging and console)
App::Application::Config()["ConsoleBanner"] = sBanner;
App::Application::Config()["CopyrightInfo"] = sBanner;
App::Application::Config()["AppIcon"] = "freecad";
App::Application::Config()["SplashPicture"] = "freecadsplash";
App::Application::Config()["SplashScreen"] = "freecadsplash";
App::Application::Config()["StartWorkbench"] = "StartWorkbench";
//App::Application::Config()["HiddenDockWindow"] = "Property editor";
App::Application::Config()["SplashAlignment" ] = "Bottom|Left";
App::Application::Config()["SplashTextColor" ] = "#ffffff"; // white
App::Application::Config()["SplashInfoColor" ] = "#c8c8c8"; // light grey
try {
// Init phase ===========================================================
@ -325,15 +342,10 @@ int main( int argc, char ** argv )
QString path = QString::fromUtf8(App::GetApplication().GetHomePath());
QFileInfo fi(path, QString::fromAscii("branding.xml"));
if (brand.readFile(fi.absoluteFilePath())) {
Branding::UserDefines ud = brand.getUserDefines();
if (!ud.windowTitle.empty())
App::Application::Config()["WindowTitle"] = ud.windowTitle;
if (!ud.windowIcon.empty())
App::Application::Config()["WindowIcon"] = ud.windowIcon;
if (!ud.programLogo.empty())
App::Application::Config()["ProgramLogo"] = ud.programLogo;
if (!ud.splashScreen.empty())
App::Application::Config()["SplashPicture"] = ud.splashScreen;
Branding::XmlConfig cfg = brand.getUserDefines();
for (Branding::XmlConfig::iterator it = cfg.begin(); it != cfg.end(); ++it) {
App::Application::Config()[it->first] = it->second;
}
}
// Run phase ===========================================================

23
src/Main/res/branding.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Branding>
<!-- This is a full list of all elements for the branding. They are all optional.-->
<!-- This file must be put into the directory where the application is installed -->
<Application>Application</Application>
<BuildVersionMajor>1</BuildVersionMajor>
<BuildVersionMinor>0</BuildVersionMinor>
<BuildRevision>2000</BuildRevision>
<WindowTitle>My Application with some text</WindowTitle>
<CopyrightInfo>My copyright notice</CopyrightInfo>
<MaintainerUrl>http://www.something.com</MaintainerUrl>
<StartWorkbench>PartWorkbench</StartWorkbench>
<!--
<WindowIcon>Path to icon file</WindowIcon>
<ProgramLogo>Path to logo (appears in bottom right corner)</ProgramLogo>
<SplashScreen>Path to splash screen</SplashScreen>
<SplashAlignment>Bottom|Left</SplashAlignment>
<SplashTextColor>#ffffff</SplashTextColor>
<SplashInfoColor>#c8c8c8</SplashInfoColor>
<BuildRevisionDate>01/01/2012</BuildRevisionDate>
<ProgramIcons>Path to program icons</ProgramIcons>
-->
</Branding>

View File

@ -28,7 +28,7 @@ ADD_CUSTOM_TARGET(Arch ALL
SOURCES ${all_files}
)
fc_copy_sources("Mod/Arch" "Arch" ${all_files})
fc_copy_sources(Arch "${CMAKE_BINARY_DIR}/Mod/Arch" ${all_files})
INSTALL(
FILES ${Arch_SRCS}

View File

@ -23,7 +23,12 @@ SET(Assembly_SRCS
add_library(Assembly SHARED ${Assembly_SRCS})
target_link_libraries(Assembly ${Assembly_LIBS})
fc_copy_script("Mod/Assembly" "Assembly" Init.py)
fc_target_copy_resource(Assembly
${CMAKE_SOURCE_DIR}/src/Mod/Assembly
${CMAKE_BINARY_DIR}/Mod/Assembly
Init.py)
if(MSVC)
set_target_properties(Assembly PROPERTIES SUFFIX ".pyd")

View File

@ -33,7 +33,12 @@ SET(AssemblyGui_SRCS
add_library(AssemblyGui SHARED ${AssemblyGui_SRCS})
target_link_libraries(AssemblyGui ${AssemblyGui_LIBS})
fc_copy_script("Mod/Assembly" "AssemblyGui" InitGui.py)
fc_target_copy_resource(AssemblyGui
${CMAKE_SOURCE_DIR}/src/Mod/Assembly
${CMAKE_BINARY_DIR}/Mod/Assembly
InitGui.py)
if(MSVC)
set_target_properties(AssemblyGui PROPERTIES SUFFIX ".pyd")

View File

@ -23,7 +23,12 @@ SET(Complete_SRCS
add_library(Complete SHARED ${Complete_SRCS})
target_link_libraries(Complete ${Complete_LIBS})
fc_copy_script("Mod/Complete" "Complete" Init.py)
fc_target_copy_resource(Complete
${CMAKE_SOURCE_DIR}/src/Mod/Complete
${CMAKE_BINARY_DIR}/Mod/Complete
Init.py)
if(MSVC)
set_target_properties(Complete PROPERTIES SUFFIX ".pyd")

View File

@ -29,7 +29,12 @@ SET(CompleteGui_SRCS
add_library(CompleteGui SHARED ${CompleteGui_SRCS})
target_link_libraries(CompleteGui ${CompleteGui_LIBS})
fc_copy_script("Mod/Complete" "CompleteGui" InitGui.py)
fc_target_copy_resource(CompleteGui
${CMAKE_SOURCE_DIR}/src/Mod/Complete
${CMAKE_BINARY_DIR}/Mod/Complete
InitGui.py)
if(MSVC)
set_target_properties(CompleteGui PROPERTIES SUFFIX ".pyd")

View File

@ -89,25 +89,25 @@ void Workbench::setupContextMenu(const char* recipient,Gui::MenuItem* item) cons
*DraftContext << "Draft_ApplyStyle" << "Draft_ToggleDisplayMode"
<< "Draft_AddToGroup";
*item << "Separator" << "Std_SetAppearance" << "Std_ToggleVisibility" << "Std_TreeSelection"
*item << "Separator" << "Std_SetAppearance" << "Std_ToggleVisibility"
<< "Std_ToggleSelectability" << "Std_TreeSelection"
<< "Std_RandomColor" << "Separator" << "Std_Delete" << DraftContext;
}
}
else if (strcmp(recipient,"Tree") == 0)
{
if ( Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId()) > 0 )
{
if (Gui::Selection().countObjectsOfType(App::DocumentObject::getClassTypeId()) > 0 ) {
Gui::MenuItem* DraftContext = new Gui::MenuItem();
DraftContext->setCommand("Display options");
*DraftContext << "Draft_ApplyStyle" << "Draft_ToggleDisplayMode"
<< "Draft_AddToGroup";
*item << "Std_SetAppearance" << "Std_ToggleVisibility"
<< "Std_RandomColor" << "Separator" << "Std_Delete"
*item << "Std_ToggleVisibility" << "Std_ShowSelection" << "Std_HideSelection"
<< "Std_ToggleSelectability" << "Separator" << "Std_SetAppearance"
<< "Std_ToggleVisibility" << "Std_RandomColor" << "Separator" << "Std_Delete"
<< DraftContext;
}
}
}
}
@ -528,7 +528,11 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
raytracing->setCommand("Raytracing");
*raytracing << "Raytracing_WriteView"
<< "Raytracing_WriteCamera"
<< "Raytracing_WritePart";
<< "Raytracing_WritePart"
<< "Separator"
<< "Raytracing_NewPovrayProject"
<< "Raytracing_NewPartSegment"
<< "Raytracing_ExportProject";
// Drafting ****************************************************************************************************
# ifdef COMPLETE_USE_DRAFTING

View File

@ -34,7 +34,7 @@ ADD_CUSTOM_TARGET(Draft ALL
SOURCES ${all_files}
)
fc_copy_sources("Mod/Draft" "Draft" ${all_files})
fc_copy_sources(Draft "${CMAKE_BINARY_DIR}/Mod/Draft" ${all_files})
INSTALL(

View File

@ -100,7 +100,8 @@ def getParamType(param):
return "string"
elif param in ["textheight","tolerance","gridSpacing"]:
return "float"
elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit","maxSnap","SvgLinesBlack"]:
elif param in ["selectBaseObjects","alwaysSnap","grid","fillmode","saveonexit","maxSnap",
"SvgLinesBlack","dxfStdSize"]:
return "bool"
elif param in ["color","constructioncolor","snapcolor"]:
return "unsigned"
@ -767,6 +768,22 @@ def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False)
shape = obj.Shape.copy()
shape.rotate(fcvec.tup(center), fcvec.tup(axis), angle)
newobj.Shape = shape
elif (obj.isDerivedFrom("App::Annotation")):
if axis.normalize() == Vector(1,0,0):
newobj.ViewObject.RotationAxis = "X"
newobj.ViewObject.Rotation = angle
elif axis.normalize() == Vector(0,1,0):
newobj.ViewObject.RotationAxis = "Y"
newobj.ViewObject.Rotation = angle
elif axis.normalize() == Vector(0,-1,0):
newobj.ViewObject.RotationAxis = "Y"
newobj.ViewObject.Rotation = -angle
elif axis.normalize() == Vector(0,0,1):
newobj.ViewObject.RotationAxis = "Z"
newobj.ViewObject.Rotation = angle
elif axis.normalize() == Vector(0,0,-1):
newobj.ViewObject.RotationAxis = "Z"
newobj.ViewObject.Rotation = -angle
elif hasattr(obj,"Placement"):
shape = Part.Shape()
shape.Placement = obj.Placement
@ -782,7 +799,6 @@ def rotate(objectslist,angle,center=Vector(0,0,0),axis=Vector(0,0,1),copy=False)
if len(newobjlist) == 1: return newobjlist[0]
return newobjlist
def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy=False):
'''scale(objects,vector,[center,copy,legacy]): Scales the objects contained
in objects (that can be a list of objects or an object) of the given scale
@ -1390,7 +1406,7 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"):
FreeCAD.ActiveDocument.recompute()
return nobj
def makePoint(X=0, Y=0, Z=0,color=(0,1,0),name = "Point", point_size= 5):
def makePoint(X=0, Y=0, Z=0,color=None,name = "Point", point_size= 5):
''' make a point (at coordinates x,y,z ,color(r,g,b),point_size)
example usage:
p1 = makePoint()
@ -1401,6 +1417,8 @@ def makePoint(X=0, Y=0, Z=0,color=(0,1,0),name = "Point", point_size= 5):
p1.X = 1 #move it in x
p1.ViewObject.PointColor =(0.0,0.0,1.0) #change the color-make sure values are floats
'''
if not color:
color = FreeCADGui.draftToolBar.getDefaultColor('ui')
obj=FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
_Point(obj,X,Y,Z)
_ViewProviderPoint(obj.ViewObject)
@ -1488,6 +1506,8 @@ class _ViewProviderDraft:
def __init__(self, obj):
obj.Proxy = self
obj.addProperty("App::PropertyEnumeration","DrawStyle","Base",
"The line style of this object")
self.Object = obj.Object
def attach(self, obj):

View File

@ -906,6 +906,8 @@ class DraftToolBar:
spec = True
elif txt.endsWith("w"):
self.wipeLine()
elif txt.endsWith("s"):
self.togglesnap()
elif txt.endsWith("c"):
if self.closeButton.isVisible():
self.closeLine()
@ -1099,6 +1101,10 @@ class DraftToolBar:
b.close()
return str(a)
def togglesnap(self):
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.active = not FreeCADGui.Snapper.active
#---------------------------------------------------------------------------
# TaskView operations

View File

@ -69,6 +69,7 @@ class Snapper:
self.constrainLine = None
self.trackLine = None
self.lastSnappedObject = None
self.active = True
# the snapmarker has "dot","circle" and "square" available styles
self.mk = {'passive':'circle',
@ -141,11 +142,13 @@ class Snapper:
if self.grid and Draft.getParam("grid"):
self.grid.set()
# checking if alwaySnap setting is on
# activate snap
oldActive = False
if Draft.getParam("alwaysSnap"):
oldActive = active
active = True
if not self.active:
active = False
self.setCursor('passive')
if self.tracker:
@ -159,14 +162,17 @@ class Snapper:
info = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo((screenpos[0],screenpos[1]))
# checking if parallel to one of the edges of the last objects or to a polar direction
eline = None
point,eline = self.snapToPolar(point,lastpoint)
point,eline = self.snapToExtensions(point,lastpoint,constrain,eline)
if active:
eline = None
point,eline = self.snapToPolar(point,lastpoint)
point,eline = self.snapToExtensions(point,lastpoint,constrain,eline)
if not info:
# nothing has been snapped, check fro grid snap
point = self.snapToGrid(point)
if active:
point = self.snapToGrid(point)
return cstr(point)
else:

View File

@ -3631,6 +3631,18 @@ class Point:
Draft.makePoint((self.stack[0][0]),(self.stack[0][1]),0.0)
FreeCAD.ActiveDocument.commitTransaction()
FreeCADGui.Snapper.off()
class ToggleSnap():
"The ToggleSnap FreeCAD command definition"
def GetResources(self):
return {'Pixmap' : 'Draft_Snap',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggle snap"),
'ToolTip' : QtCore.QT_TRANSLATE_NOOP("Draft_ToggleSnap", "Toggles Draft snap on or off")}
def Activated(self):
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.active = not FreeCADGui.Snapper.active
#---------------------------------------------------------------------------
# Adds the icons & commands to the FreeCAD command manager, and sets defaults
@ -3676,6 +3688,7 @@ 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())
# a global place to look for active draft Command
FreeCAD.activeDraftCommand = None

View File

@ -2,7 +2,7 @@
# Resource object code
#
# Created: Mon Feb 13 10:34:22 2012
# Created: Sun Feb 26 13:28:36 2012
# by: The Resource Compiler for PyQt (Qt v4.7.4)
#
# WARNING! All changes made in this file will be lost!
@ -23802,144 +23802,153 @@ qt_resource_data = "\
\x93\x83\x1e\x48\xef\x57\xc6\xa2\x49\xdb\x13\x44\xd4\xba\x3f\x06\
\x46\x3f\xfe\x6c\x03\x93\xf1\x73\xb1\x4b\x54\x79\xc9\xd8\x04\x84\
\x23\xc5\xbe\x37\x98\x7a\x44\xf4\xff\x03\x15\x2c\x14\x99\
\x00\x00\x08\x78\
\x00\x00\x09\x10\
\x00\
\x00\x3f\x42\x78\x9c\xed\x5b\x5b\x73\xdb\xb6\x12\x7e\xf7\xaf\xc0\
\xe8\xa1\x27\xed\xb8\x96\x7c\x6f\x72\x64\x75\x12\x3b\x4e\xd2\x49\
\xda\xf4\xc8\x4d\xcf\x9b\x07\x22\x21\x11\x35\x09\xb0\x00\x68\x49\
\xfd\xf5\x5d\x5c\x28\x5e\x75\x8f\x24\xc7\xa3\x19\xcf\x58\x04\xc0\
\xdd\xc5\xf2\xdb\xc5\xee\x72\xd9\xfe\x79\x14\x85\xe8\x91\x08\x49\
\x39\xbb\x6a\x1c\x1f\xb5\x1a\x88\x30\x8f\xfb\x94\x0d\xae\x1a\x7f\
\xdc\xdd\xfe\xf8\x53\xe3\xe7\xce\x41\x3b\xa1\xd9\xa2\x33\x58\xd4\
\x39\x40\x6d\x2f\xc4\x52\x76\xde\x25\xf4\xd5\xab\x1b\x8a\x43\x3e\
\x80\xff\xe1\xa0\x4b\x94\x82\x9b\xe5\x8d\xc0\x7d\xd5\x6e\xda\x45\
\xb0\x7a\x48\xfd\x01\x51\xc8\x5c\x5f\x35\x7e\xff\xd3\x5c\x36\x10\
\xc3\x11\xb9\x6a\xcc\x24\xa2\x99\xa1\x76\x2c\x78\x4c\x84\x1a\xbb\
\x3b\x06\x84\x47\x44\x89\xb1\x99\x44\x6d\x41\x3c\x65\x7e\xa1\xf6\
\xa8\xd3\x6a\x37\x47\xee\x62\xac\x2f\xc6\xee\x02\x44\x50\x41\xe7\
\xfc\xf2\xbc\xdd\xb4\x3f\xed\x70\x40\xe8\x20\x50\x9d\x8b\x93\x97\
\xed\xa6\xfb\x6d\x68\x36\x53\xa2\xed\x66\xca\xbc\x4e\x92\x21\x65\
\x3e\x1f\xde\x51\x15\x12\x27\x8c\x54\x02\x84\xef\x7c\x88\x62\x2e\
\x54\xf3\xed\x48\xff\x6b\x37\xdd\x68\x95\x5e\x88\xc7\x3c\xc9\x34\
\xf3\xe5\x0d\x1f\x7d\x34\x43\x8e\x5c\x89\x9f\x8c\xb1\x07\x84\x1a\
\x4e\x7a\x96\x44\x3d\x22\x3a\x17\xed\xa6\xfb\x65\x65\xcf\x73\xa8\
\x90\x88\xb0\x18\x50\x56\xa2\xf0\x72\x26\x05\xaa\x48\x94\xa9\x31\
\xff\x24\xdf\x09\x9e\xc4\x20\xf3\xe4\x59\xba\xeb\xe3\x13\xc7\xa0\
\xc2\x5e\x65\xba\xca\xa9\xeb\xe6\xff\xb7\xa8\xcf\x45\x84\x15\xe2\
\xb1\x02\xa4\xc9\xbc\xce\xaa\x22\xcd\xd7\xdc\x5c\xe5\x4d\xd5\x5f\
\x1d\xb7\xd9\x5a\x9c\xaa\xc8\x7a\x52\x99\x3a\x6b\xf6\xf1\xbe\xba\
\x8f\x05\x76\x32\x63\x2f\x75\x22\xcc\xdf\x4f\x46\xb0\xb5\x20\xc1\
\xc2\xae\xaa\x48\xf9\x88\x7b\x24\x4c\x61\xa2\xc8\x48\x99\x81\xe3\
\xfb\xd3\x3c\xcf\x2a\x5a\x60\x61\x61\x41\xc9\xc0\x90\x54\xe3\x90\
\x94\xb0\x32\x55\x46\x64\x6c\x1f\xa4\xca\x6f\xa5\x28\xf7\x9c\x6d\
\x18\x5f\xf5\x59\x90\xfe\x35\x8f\x7a\x3c\x07\xfc\x81\x9e\x88\x61\
\xc2\xd3\x13\x3d\x98\x98\xb9\x2d\xce\xc3\x3b\x1a\xd7\xef\xec\x2e\
\xa0\x12\xc1\x9f\x0a\x08\x02\x37\x17\x70\x1f\x79\x01\xe7\x92\xf8\
\xda\x44\x10\x35\x1b\x87\x85\x08\x2e\x94\xc0\x4c\x86\xd8\x5c\x6a\
\x1b\xe2\xbd\xbf\xc0\x6f\x21\x8f\x87\x7a\x25\x53\x1c\xdd\x0a\x42\
\xae\x5f\xdf\x1c\xa1\x83\x0f\x7d\x37\x1e\xe1\x38\xd6\x37\x00\x0f\
\x47\xf8\x10\x01\xe0\x50\x94\x48\xe5\x46\x10\x2e\xad\xed\xd3\x90\
\xc0\x10\x53\x98\x32\x7d\x8d\x33\xd6\x9c\x21\x85\x7b\x30\xad\x02\
\x30\xdf\x21\x0d\x43\xbd\x10\x4e\x0c\x27\x87\xb4\x82\x84\x94\x11\
\xe3\x79\xe5\xd1\xc1\xc2\x0f\xac\xa2\x39\x2f\x11\x82\x30\xf5\x81\
\xf9\x64\x54\x52\xdf\x74\xbc\x2e\x4a\x5c\x3f\xbf\xb7\x4c\x1f\x2c\
\x80\x2b\x5f\x12\x75\xd5\x68\x95\x98\x78\x4e\x70\x7f\xd4\x77\xd0\
\xf3\x56\xdd\x8a\xe6\xf6\x19\xab\x60\x3e\xb3\x4f\xdc\x6f\xa6\x47\
\xea\xc2\xdc\x4a\x40\x5e\xc4\xb6\x26\x10\xfc\x95\x33\x82\x5e\xf4\
\xb1\x54\x44\xaa\xef\xeb\x9e\xd6\x34\xae\xcd\x32\xdb\xb5\xe4\xf8\
\x03\x90\xe8\x93\x3e\x4e\xc2\x14\xd3\x98\xf9\x19\x92\x76\x27\xd8\
\x6f\x82\x82\xbb\xc4\xe1\xd3\x92\xea\x7a\x62\xb2\xe0\x2b\xf2\x26\
\xb7\x43\x91\x04\xc1\x8a\xa0\x18\x0b\xac\x43\x36\xea\x39\x17\x55\
\x3e\xdf\xb7\x2f\x52\xf7\x81\x28\x2f\x20\x6b\x09\x32\xf7\x3c\x69\
\x37\xed\xf1\x9e\x45\x03\xf9\xe9\x85\x23\x01\xb7\xa9\x80\x0b\xfa\
\x8f\xf6\xc1\x61\x35\x42\x58\xe6\xf8\x0d\xf5\xc5\xfd\xe5\x8a\x27\
\xef\x27\x3c\x42\xdd\x58\x63\x0b\x75\xc9\x20\x02\x6f\xbc\x83\xf3\
\xb7\x0b\xa7\x52\xdd\xf1\x2b\x61\x1c\x4e\xdf\xfb\x93\x99\x9b\x8b\
\xf0\x88\x46\x49\xd4\xa5\xff\x90\xf2\x1e\x61\xa8\x04\x1b\x9b\x2e\
\x5c\xb4\x0a\x89\xc3\x64\xd6\x25\x0d\xc7\x17\x97\x97\x97\x27\xc7\
\xe7\x85\x2c\x22\xdb\x64\x99\xec\x62\x27\xc4\xcc\x30\xe1\xcf\x80\
\x30\x44\x46\x69\x30\x20\xcd\x13\x91\xda\xec\x21\x10\x38\xd4\xd1\
\xc3\x18\x61\x41\xec\x39\xad\x63\x6b\xf0\x09\x94\xa1\x98\x87\x63\
\xb3\xf2\x08\x99\x40\xe3\x11\x87\x09\x99\x84\x1b\x56\x2f\x28\x24\
\x6c\xa0\x02\xc4\xfb\x88\x60\xcf\xfc\xd7\xb3\xe9\xad\x48\xda\xc7\
\x0e\x24\x20\xa6\x68\x19\x5e\xcc\xac\x18\x06\x1c\xe2\x00\x2b\x8a\
\xa1\x69\x4c\xcd\x47\x58\x42\xc0\x00\x72\x63\xad\x9a\xf4\xf6\xa3\
\xd5\xa3\x00\x23\x74\xfd\xf1\x7f\xbe\x95\xe3\x1f\x14\xe5\x14\x9e\
\x5a\xc0\xd3\x0c\x03\x76\xec\xa0\x0a\xd1\xfd\xf2\x2e\x6a\x45\x07\
\x75\x5d\x89\x5c\x77\xe0\xa0\x6e\x81\xed\xb5\x89\xa5\x45\xc5\x49\
\x69\x91\x3c\x37\x37\xd3\x4d\x41\xac\xbd\xa4\x9b\x3a\x6d\xcd\xf6\
\x53\xad\xed\x39\xa8\xbb\x80\xd4\x25\x11\xfd\x52\xda\x02\x91\xf4\
\x94\x3c\x61\x75\xff\xb0\x5c\x20\xef\xc4\xb3\x40\xd9\xdb\x71\x9d\
\x1d\x5f\x2e\x6e\xc7\x59\x8a\x1c\x10\xef\xa1\x36\x45\xd6\x13\xf3\
\x0f\xe9\x99\xe0\xa2\xfa\x48\xb2\x79\x72\xc2\x0c\x41\x9d\xc5\x6a\
\x9f\x20\x9b\x91\xf9\x87\x86\x9c\xfd\x47\xa1\x1e\x71\x19\x33\xf1\
\x57\xc7\xd3\xdc\x32\x84\xe5\xa8\xd3\x00\x9f\xc2\x79\x20\x6b\x2a\
\x58\x4b\x42\x69\x71\xf8\x6a\xde\x7b\xdc\xd6\xe3\xf6\x64\x23\xb8\
\x9d\x53\xb3\x5a\x10\xb7\x13\xd4\xc6\x18\x6e\x47\xba\xa6\x47\xd2\
\xec\xc8\x96\x51\x72\xd8\x85\xb8\x8e\x6f\x10\xbf\x56\xb3\x5b\x83\
\xac\x65\xb7\x07\x6d\x3d\x68\xcf\x36\x02\xda\x39\xe9\xde\x2c\xd0\
\x1a\xe2\x0e\xb7\x7d\x53\x2a\x1c\x62\xa6\x4c\xc4\xcf\x38\xfb\x51\
\x53\xf0\x51\x2f\xe4\xde\x83\x44\x2f\x7a\x64\x40\x99\xa9\x11\x0e\
\x29\xe4\x10\x18\xfd\xf0\xbd\x4e\x4a\xb6\x87\xe5\x1f\xac\x24\xdb\
\xc2\xb2\x54\x58\xa4\x1c\xf7\x78\xae\xc3\xf3\x4f\x1b\xc1\xf3\xf9\
\xd7\x75\xc2\xa9\xe3\xed\x0b\x1e\x19\x64\x4b\xa0\xa3\xfd\x22\x11\
\x99\x37\xfe\x8b\x43\x70\xea\xdb\x38\xd5\x3c\x04\xf4\xc6\x3c\x79\
\x88\x3c\x12\x61\x30\xaf\xef\xf4\x29\xe4\x86\x78\x8c\x4c\xfd\x54\
\x1c\xa2\x1e\xa8\x2b\xc2\x0f\x6e\x5a\x67\xd7\x52\x42\x62\x2d\x69\
\x38\x46\xc4\xa7\xa6\x78\xbe\x09\x7b\x30\x2f\xe3\xd2\x2d\x18\x99\
\xb7\x68\x19\x03\xcd\xfc\xa3\xe1\xbd\xb7\x8b\x7a\xbb\x38\xdf\x88\
\x5d\xbc\x5c\xdd\x2e\xf4\x1b\xa2\xd4\x1e\xfa\x82\x10\x0f\xfb\x16\
\xfa\xf0\xc4\xb5\x0f\xd7\xf0\xd7\x85\x78\xca\x3c\xea\x13\xf8\x99\
\x1a\x8d\x01\xd7\x90\x0a\x5d\x55\x7a\x43\x86\x58\x90\x43\x6b\x61\
\x1e\xd6\x2f\x87\x1e\xf4\xfb\xa4\x61\x00\xf9\xd5\xd1\xd1\x1a\x55\
\x9f\xe9\x48\xff\x05\x44\x42\x69\x57\xc0\x56\xe0\xad\x55\x91\x31\
\xdc\xe3\xbb\x0e\xdf\x17\x9b\xc0\xf7\x5a\xe8\xae\x78\x7d\x0c\xe0\
\x4e\x41\x9c\x7b\xbb\xd9\x87\x50\x3c\xf3\xfa\xb6\xc8\x6a\xcb\x98\
\xa7\xbe\x29\x83\x9a\x05\x9b\x40\xb2\x6d\x18\x41\xa7\x37\x13\xb1\
\x80\x69\xca\x11\x45\x44\x4e\x79\x63\xb1\x91\xba\x08\x70\x7b\x9e\
\xd8\x2e\x4e\x16\x68\xe5\xd6\xad\xd4\xf7\x72\xbf\x64\xe7\x4b\xf7\
\xcb\xbb\xaf\xd7\xf9\xe2\x38\xe5\x12\xd4\x6f\xbd\x07\x26\xdd\x51\
\x21\x27\x7a\xbe\xdd\x30\x73\x82\xda\x9d\x77\xc3\x98\x22\x85\xa8\
\x38\xfc\xae\x19\x2e\x38\xfc\xaa\xf4\xb0\x1a\x62\x06\xd3\x30\x52\
\xda\x04\x01\x95\x76\x7e\x57\xaf\x5e\xbd\x9f\x50\x6c\x37\xcd\xe0\
\xd2\x4e\x47\xd7\xb1\xdf\x43\x38\x32\xdd\xe9\x4c\x2d\x9d\x9f\xcd\
\xae\x9c\x9f\xac\x55\x3a\x87\x65\x46\x47\x4b\xe8\x7a\xd5\xce\xa3\
\x75\xca\x53\x0b\xf7\x1e\x69\xb7\x35\xbd\xd9\xe8\xdb\xef\xef\x91\
\x8f\x83\x7d\x7f\xcf\xbe\xbf\xe7\x6b\x4b\xb5\xeb\x90\xfc\xe5\xe2\
\x21\x79\x5d\xcb\xc8\x9c\x17\x36\xf3\xa2\xda\xee\x13\x69\xd6\x04\
\xe3\xbe\xb7\x41\xfd\xbd\x31\xf2\xfb\xf5\x9b\x36\xcd\xd6\x74\xa3\
\x84\x89\xe7\xf4\x7b\x4e\x9d\x11\x0b\x10\x10\x12\xdf\x42\xa3\x06\
\x76\x9d\x47\xcf\xc3\x49\x16\xf4\xf8\x3c\x9d\xe5\x9d\x7b\x59\x0d\
\x67\xe0\x0b\x7d\x08\xc6\x42\x57\x41\xbe\xc3\x51\xfc\xdf\xb4\xd4\
\xb7\x43\x17\xfa\x3f\x3c\xb4\x62\x5d\xbf\xfe\xb4\x96\x18\xbb\x76\
\x4d\xc7\xad\xc5\x7d\xd3\x12\xe5\xb0\xd9\x31\xe9\x32\x1d\x56\xda\
\xb2\x1f\x29\x19\xca\x43\x5d\xcd\x25\xa6\x76\x30\x0c\xb4\x85\x9b\
\xa3\x81\x8b\x07\xa4\x3b\x2f\xb1\x8e\x85\x50\x2f\xc4\xde\xc3\xa1\
\x09\x9a\x7a\x44\x29\x88\x99\x05\xc1\x3e\xee\xd1\x90\x02\x73\x3c\
\xc0\x94\x49\xe5\x6e\xef\xc1\x52\x5d\x2e\x65\xfe\x46\x4a\x0a\x13\
\xfc\xe6\xa4\x75\xe7\x9a\x29\x09\x03\xf7\x35\x5c\x91\xad\xa4\x94\
\x38\xf7\x40\xad\x1d\x25\x12\xf0\x08\xe6\xe7\x26\x9d\x50\xf7\x71\
\xf0\x51\x37\x62\xbd\xb1\x1b\x79\x9a\x1e\xe8\xe9\x96\x2b\x26\xc9\
\xc2\x62\xe5\x8a\xdf\xae\x5f\x7f\xfd\x72\x45\x66\xa3\xcf\xa5\x5c\
\x51\xe8\x97\xf9\xe6\xcb\x15\x4b\xb8\xdb\xb3\xd5\xdd\xed\x8c\xb7\
\xcc\x18\x9c\xa7\x44\x2f\x4e\x6f\x6c\x65\xb6\xee\x85\xf2\x46\xde\
\x2b\xb8\xb2\x8a\x06\xbd\x11\x61\x2b\x95\x57\xee\x61\xc7\x6c\xef\
\xcb\xcc\xb3\xc8\xd7\x9c\xf4\x67\x45\xd4\x4b\x2b\x4e\xd3\x7c\x57\
\x5d\xa9\x29\xab\x32\x7d\x71\x34\x0a\x35\xa6\xaa\xdf\x5a\xa2\xb2\
\x54\x2c\x2a\xb9\x7a\xd2\x49\xa5\x9e\x94\x96\x92\xce\x2a\xa5\xa4\
\x42\x15\xa9\x2c\x4a\xa1\x76\x94\x29\x29\xa7\xc9\x9c\x1a\x9d\x73\
\x4a\xb3\x6a\xe7\x6c\xae\x1a\x17\x0d\x64\xdd\xc4\x55\xe3\xf8\xb8\
\xd1\xd4\x2b\x63\x3a\x8a\x70\xdc\x4f\x98\xa7\x15\xd5\xf9\xfb\xb3\
\xb9\xbe\x15\x3c\xfa\x44\x23\xd2\xe5\x89\xf0\xe0\x00\x2f\xad\xd2\
\xdf\xfe\x26\x52\xf1\xc8\x72\x94\x46\x92\xfc\x88\x95\x32\xf7\x7d\
\x70\xae\x13\x36\xfb\x24\x58\x3f\x8f\x91\x22\x10\xf2\x74\xdc\xe7\
\xc0\xf0\x34\xdc\xc0\x81\x55\x15\xf6\x61\xcb\x40\xa1\xa9\x09\xd8\
\xef\x83\x8f\x02\xad\x38\x33\x61\x14\x50\xe6\x3b\x5b\x90\x52\x5b\
\x6e\xad\x30\x55\x89\xa7\x49\xa5\xa9\x59\xc9\xe5\xfa\x62\xb9\xcf\
\x19\xea\xf5\x33\x99\xdc\x8a\x28\xa9\x8f\xaf\x97\x25\x9b\xdd\x8e\
\x30\x2e\x73\x9f\x22\xcc\x64\x76\x7d\x61\x8a\x03\xe6\xab\x75\x41\
\xa4\xb1\x01\x69\xac\xc5\xe3\x8c\x11\x63\x03\xfa\xba\xdd\x4c\x68\
\xe7\xe0\x5f\x12\x29\x74\x7c\
\x00\x45\x1d\x78\x9c\xed\x5c\x6d\x73\xdb\x36\x12\xfe\xee\x5f\x81\
\xd1\x87\xbb\xb4\xe3\x5a\x96\x5f\x93\x9c\xac\x4e\x62\xd7\x49\x6e\
\x92\x6b\x7a\x72\xd3\xfb\xe6\x81\x48\x48\x44\x4d\x12\x2a\x00\x5a\
\x52\x7f\xfd\xed\x02\xa0\xf8\x22\xea\xdd\x92\x1c\x8f\x66\x3c\x23\
\x11\x00\x77\x17\x8b\x67\x17\x8b\xc5\x5a\xcd\x9f\x87\x51\x48\x1e\
\x99\x54\x5c\xc4\x57\xb5\xc6\xd1\x71\x8d\xb0\xd8\x13\x3e\x8f\x7b\
\x57\xb5\xdf\xef\x6e\x7f\x7a\x5d\xfb\xb9\x75\xd0\x4c\x78\x36\xe8\
\x0c\x06\xb5\x0e\x48\xd3\x0b\xa9\x52\xad\x0f\x09\x7f\xfb\xf6\x86\
\xd3\x50\xf4\xe0\x33\xec\xb5\x99\xd6\xf0\xb2\xba\x91\xb4\xab\x9b\
\x75\x3b\x08\x46\x0f\xb8\xdf\x63\x9a\x98\xe7\xab\xda\x6f\x7f\x98\
\xc7\x1a\x89\x69\xc4\xae\x6a\x33\x89\x20\x33\xd2\xec\x4b\xd1\x67\
\x52\x8f\xdc\x1b\x3d\x26\x22\xa6\xe5\xc8\x74\x92\xa6\x64\x9e\x36\
\xdf\x48\x73\xd8\x3a\x6e\xd6\x87\xee\x61\x84\x0f\x23\xf7\x00\x22\
\xe8\xa0\x75\x7e\x79\xde\xac\xdb\xaf\xb6\x39\x60\xbc\x17\xe8\xd6\
\xc5\xc9\x9b\x66\xdd\x7d\x37\x34\xeb\x29\xd1\x66\x3d\x65\x5e\x25\
\xc9\x80\xc7\xbe\x18\xdc\x71\x1d\x32\x27\x8c\xd2\x12\x84\x6f\x7d\
\x8a\xfa\x42\xea\xfa\x2f\x43\xfc\x68\xd6\x5d\xeb\x24\xbd\x90\x8e\
\x44\x92\x69\xe6\xdb\x7b\x31\xfc\x6c\x9a\x1c\xb9\x12\x3f\xd5\xa7\
\x1e\x10\xaa\x39\xe9\xe3\x24\xea\x30\xd9\xba\x68\xd6\xdd\x37\x2b\
\x7b\x9e\xc3\x04\x89\x88\xca\x1e\x8f\x4b\x14\xde\xcc\xa4\xc0\x35\
\x8b\x32\x35\xe6\x57\xf2\x83\x14\x49\x1f\x64\x1e\xaf\xa5\x7b\x6e\
\x9c\x38\x06\x13\xec\x75\xa6\xab\x9c\xba\x6e\xfe\x77\x4b\xba\x42\
\x46\x54\x13\xd1\xd7\x80\x34\x95\xd7\xd9\xa4\x48\xf3\x35\x37\x57\
\x79\x53\xf5\x57\xc5\x6d\xb6\x16\xa7\x2a\xb2\x9a\x54\xa6\xce\x8a\
\x79\x7c\x9c\x9c\xc7\x02\x33\x99\x31\x97\x2a\x11\xe6\xcf\x27\x23\
\x78\xbc\x20\xc1\xc2\xac\x26\x91\xf2\x99\x76\x58\x98\xc2\x44\xb3\
\xa1\x36\x0d\x8d\xfb\xd3\x3c\xcf\x49\xb4\xc0\xc0\xc2\x80\x92\x81\
\x11\xa5\x47\x21\x2b\x61\x65\xaa\x8c\xc4\xd8\x3e\x48\x95\x9f\x4a\
\x51\xee\x39\xd3\x30\xbe\xea\xab\x64\xdd\x6b\x11\x75\x44\x0e\xf8\
\x3d\xec\xe8\x43\x87\x87\x1d\x1d\xe8\x98\x39\x2d\x21\xc2\x3b\xde\
\xaf\x9e\xd9\x5d\xc0\x15\x81\x3f\x1d\x30\x02\x6e\x2e\x10\x3e\xf1\
\x02\x21\x14\xf3\xd1\x44\x08\x37\x13\x87\x81\x04\x1e\xb4\xa4\xb1\
\x0a\xa9\x79\x44\x1b\x12\x9d\x3f\xc1\x6f\x11\x4f\x84\x38\x32\xd6\
\x82\xdc\x4a\xc6\xae\xdf\xdd\x1c\x91\x83\x4f\x5d\xd7\x1e\xd1\x7e\
\x1f\x5f\x00\x1e\x8e\xf0\x21\x01\xc0\x91\x28\x51\xda\xb5\x10\x5a\
\x1a\xdb\xe5\x21\x83\xa6\x58\x53\x1e\xe3\x33\xcd\x58\x8b\x98\x68\
\xda\x81\x6e\x1d\x80\xf9\x0e\x78\x18\xe2\x40\xd8\x31\x9c\x1c\xca\
\x0a\x12\xf2\x98\x19\xcf\xab\x8e\x0e\x16\x5e\xb0\x09\xcd\x79\x89\
\x94\x2c\xd6\x9f\x62\x9f\x0d\x4b\xea\x9b\x8e\xd7\x45\x89\xe3\xfa\
\xfd\x12\xe3\xc6\x02\xb8\xf2\x15\xd3\x57\xb5\xe3\x12\x13\xcf\x09\
\xee\x0f\xbb\x0e\x7a\xde\xaa\x53\x41\x6e\x5f\xa9\x0e\xe6\x33\xfb\
\x22\xfc\x7a\xba\xa5\x2e\xcc\xad\x04\xe4\x45\x6c\x6b\x0c\xc1\xff\
\x88\x98\x91\x57\x5d\xaa\x34\x53\xfa\x87\xaa\xd5\x9a\xc6\xb5\x5e\
\x66\xbb\x96\x1c\xbf\x03\x12\x7d\xd6\xa5\x49\x98\x62\x9a\xc6\x7e\
\x86\xa4\xdd\x09\xf6\xab\xe4\xe0\x2e\x69\xf8\xbc\xa4\xba\x1e\x9b\
\x2c\xf8\x8a\xbc\xc9\xed\x50\x24\xc9\xa8\x66\xa4\x4f\x25\xc5\x90\
\x8d\x7b\xce\x45\x95\xf7\xf7\xed\x8b\xd4\x7e\x60\xda\x0b\xd8\x5a\
\x82\xcc\xdd\x4f\x9a\x75\xbb\xbd\x67\xd1\x40\xbe\x7b\xe1\x48\xc0\
\x4d\x2a\x10\x92\xff\x8d\x3e\x38\x9c\x8c\x10\x96\xd9\x7e\x43\x7c\
\xb8\xbf\x5c\x71\xe7\xfd\x42\x87\xa4\xdd\x47\x6c\x91\x36\xeb\x45\
\xe0\x8d\x77\xb0\xff\xb6\x61\x57\xaa\xda\x7e\x15\xb4\xc3\xee\x7b\
\x7f\x32\x73\x72\x11\x1d\xf2\x28\x89\xda\xfc\x6f\x56\x9e\x23\x34\
\x95\x60\x63\x8f\x0b\x17\xc7\x85\x83\xc3\xb8\xd7\x1d\x1a\x1a\x17\
\x97\x97\x97\x27\x8d\xf3\xc2\x29\x22\x9b\x64\x99\xec\x62\x3b\xc4\
\xcc\x30\xe1\x8f\x80\xc5\x84\x0d\xd3\x60\x40\x99\x15\x51\x68\xf6\
\x10\x08\x1c\x62\xf4\x30\x22\x54\x32\xbb\x4f\x63\x6c\x0d\x3e\x81\
\xc7\xa4\x2f\xc2\x91\x19\x79\x44\x4c\xa0\xf1\x48\xc3\x84\x8d\xc3\
\x0d\xab\x17\x12\xb2\xb8\xa7\x03\x22\xba\x84\x51\xcf\x7c\x62\x6f\
\xfa\x2a\x51\x76\xd9\x81\x04\xc4\x14\xc7\x86\x57\x6c\x46\x0c\x02\
\x01\x71\x80\x15\xc5\xd0\x34\xa6\xe6\x13\xaa\x20\x60\x00\xb9\x29\
\xaa\x26\x7d\xfd\x68\xf5\x28\xc0\x08\x5d\xbd\xfd\x9f\x6f\x65\xfb\
\x07\x45\x39\x85\xa7\x16\xf0\x3c\xc3\x80\x1d\x3b\xa8\x42\x74\xbf\
\xbc\x8b\x5a\xd1\x41\x5d\x4f\x44\xae\x3b\x70\x50\xb7\xc0\xf6\xda\
\xc4\xd2\x72\xc2\x49\xa1\x48\x9e\xeb\x9b\xe9\xa6\x20\xd6\x5e\xd2\
\x4d\x9d\x1e\xcf\xf6\x53\xc7\xdb\x73\x50\x77\x01\xab\x3a\x44\x74\
\x4b\xc7\x16\x88\xa4\xa7\x9c\x13\x56\xf7\x0f\xcb\x05\xf2\x4e\x3c\
\x0b\x94\xbd\x1d\x57\xd9\xf1\xe5\xe2\x76\x9c\x1d\x91\x03\xe6\x3d\
\x54\x1e\x91\xb1\x63\xfe\x26\x3d\x13\x5c\x1c\xb7\x24\x7b\x4e\x4e\
\x62\x43\x10\x4f\xb1\xe8\x13\x54\x3d\x32\x1f\x64\x20\xe2\x7f\x6a\
\xd2\x61\xee\xc4\xcc\xfc\xd5\xf1\x34\x37\x0d\x61\x39\xe2\x31\xc0\
\xe7\xb0\x1f\xa8\x8a\x0c\xd6\x92\x50\x5a\x1c\xbe\xc8\x7b\x8f\xdb\
\x6a\xdc\x9e\x6c\x04\xb7\x73\x72\x56\x0b\xe2\x76\x8c\xda\x3e\x85\
\xd7\x09\xe6\xf4\x58\x7a\x3a\xb2\x69\x94\x1c\x76\x21\xae\x13\x1b\
\xc4\xaf\xd5\xec\xd6\x20\x6b\xd9\xed\x41\x5b\x0d\xda\xb3\x8d\x80\
\x76\xce\x71\x6f\x16\x68\x0d\x71\x87\xdb\xae\x49\x15\x0e\x68\xac\
\x4d\xc4\x1f\x8b\xf8\x27\xa4\xe0\x93\x4e\x28\xbc\x07\x45\x5e\x75\
\x58\x8f\xc7\x26\x47\x38\xe0\x70\x86\xa0\xe4\xc7\x1f\xf0\x50\xb2\
\x3d\x2c\xff\x68\x25\xd9\x16\x96\x95\xa6\x32\xe5\xb8\xc7\x73\x15\
\x9e\x5f\x6f\x04\xcf\xe7\x4f\xeb\x84\x53\xc7\xdb\x95\x22\x32\xc8\
\x56\x40\x07\xfd\x22\x93\x99\x37\xfe\x53\x40\x70\xea\xdb\x38\xd5\
\x2c\x02\x79\x6f\x56\x1e\x22\x8f\x44\x1a\xcc\xe3\x9b\x3e\x87\xb3\
\x21\x1d\x11\x93\x3f\x95\x87\xa4\x03\xea\x8a\xe8\x83\xeb\xc6\xd3\
\xb5\x52\x70\xb0\x56\x3c\x1c\x11\xe6\x73\x93\x3c\xdf\x84\x3d\x98\
\xcb\xb8\x74\x0a\x46\xe6\x2d\x5a\x46\x0f\x99\x7f\x36\xbc\xf7\x76\
\x51\x6d\x17\xe7\x1b\xb1\x8b\x37\xab\xdb\x05\xde\x10\xa5\xf6\xd0\
\x95\x8c\x79\xd4\xb7\xd0\x87\x15\x47\x1f\x8e\xf0\xc7\x44\x3c\x8f\
\x3d\xee\x33\xf8\x9a\x1a\x8d\x01\xd7\x80\x4b\xcc\x2a\xbd\x67\x03\
\x2a\xd9\xa1\xb5\x30\x8f\xe2\xe5\xd0\x03\xde\x27\x0d\x02\x38\x5f\
\x1d\x1d\xad\x91\xf5\x99\x8e\xf4\x7f\x83\x48\x24\xad\x0a\xd8\x0a\
\xbc\x51\x15\x19\xc3\x3d\xbe\xab\xf0\x7d\xb1\x09\x7c\xaf\x85\xee\
\x09\xaf\x4f\x01\xdc\x29\x88\x73\xb7\x9b\x5d\x08\xc5\x33\xaf\x6f\
\x93\xac\x36\x8d\x79\xea\x9b\x34\xa8\x19\xb0\x09\x24\xdb\x82\x11\
\x72\x7a\x33\x16\x0b\x98\xa6\x1c\x49\xc4\xd4\x94\x1b\x8b\x8d\xe4\
\x45\x80\xdb\x1e\xdb\xd5\xd8\x6e\x34\x36\xe2\xbc\x5f\x3f\x2d\xbc\
\xb3\x88\xdb\x66\x44\x10\xd0\x28\x98\x89\x6f\x34\x8d\x7d\x2a\x7d\
\x17\xc8\xe0\x08\x82\x59\x40\x78\x2b\x86\xb8\x05\x5c\xbf\x4b\xfb\
\x63\xa3\xbd\x4e\x08\xe8\x23\xc3\x3b\x04\x6c\xc5\x6a\x03\x5f\x78\
\xc9\x52\xf7\x3f\x4b\x18\x02\x5e\xfd\x8e\x45\xec\x82\xea\xad\x1c\
\x26\x7b\x88\x93\xd9\x96\x11\xb4\xb5\x8f\xf9\xd7\xbd\x1d\x4c\xb1\
\x83\xcd\x64\x58\x1a\xc7\x4f\x6b\x08\x01\x35\x77\xbd\x63\x97\xee\
\x0a\x54\xd2\x58\x5e\x81\xa1\x84\xcc\x46\x30\x1b\x3c\x99\x1a\x29\
\x48\x47\x24\x88\x6a\xce\x8c\x6f\x5f\x93\xe7\x12\x60\xb6\xce\xe0\
\x66\xd8\xfd\x48\xdd\xc5\xf7\x4b\x84\x74\xb1\xb3\x40\x2b\x37\x6e\
\xa5\x92\xc6\xfb\x25\x8b\x1a\xdb\xdf\x3e\x3c\x5d\x51\xa3\xe3\x94\
\xcb\x3d\x7e\xef\xe5\x8d\xe9\x8c\x0a\xe9\xae\x97\x5b\xe8\x38\x27\
\x5f\xb1\xf3\x42\x47\x93\x7f\x96\x13\x7e\xbe\x6d\x9a\x0b\xb1\xfc\
\xa4\xf4\x30\x1a\xc2\x00\x53\x0b\x58\x9a\x04\x03\x95\xb6\x7e\xd3\
\x6f\xdf\x7e\x1c\x53\x6c\xd6\x4d\xe3\xd2\x4e\x07\xf7\xff\x8f\xe0\
\xae\xa7\x3b\x9d\xa9\xb7\xa2\x67\xb3\x2f\x45\x4f\xd6\xba\x15\x85\
\x61\x46\x47\x4b\xe8\x7a\xd5\xa2\xd2\x75\x6e\x1e\x16\x2e\x2b\x45\
\xb7\x35\xbd\x8e\xf4\xfb\x2f\xdd\x54\x8f\xbd\x7d\xe9\xe6\xbe\x74\
\xf3\xa9\xa5\xda\x75\x24\xfe\x66\xf1\x40\xbc\xaa\x1a\x70\xce\x5d\
\xfc\xbc\x84\x45\xfb\x99\xd4\xe1\x83\x71\xdf\xdb\x7c\xcd\xbd\x31\
\xf2\xfb\xf5\xeb\xf1\xcd\xd4\xf0\x30\x6c\xe2\x39\x2c\x61\xc1\x64\
\xa7\x04\x01\xc9\xa0\x58\x83\x47\x5d\x51\xe9\xcb\x70\x92\x05\x3d\
\xbe\x4c\x67\x79\xe7\xea\x90\x60\x0f\x7c\x85\x9b\x60\x5f\x62\x82\
\xfb\x1f\x34\xea\xff\x2b\xbd\xc5\xd9\xa1\x0b\xfd\x2f\x1d\x58\xb1\
\xae\xdf\x7d\x59\x4b\x8c\x5d\xbb\xa6\xc2\x69\xfe\xe9\x92\x04\xb3\
\x63\xd2\x65\x8a\x67\xd1\xb2\x1f\x39\x1b\xa8\x43\xbc\xa8\x63\x26\
\x2d\x3c\x08\xd0\xc2\xcd\xd6\x20\xe4\x03\xc1\xa2\x7a\x8a\xb1\x10\
\xe9\x84\xd4\x7b\x38\x34\x41\x53\x87\x69\x0d\x31\xb3\x64\xd4\xa7\
\x1d\x1e\x72\x60\x4e\x7b\x14\xf3\x67\xee\xf5\x0e\x0c\xc5\x9b\xb0\
\xd8\xdf\x48\x5e\x61\x8c\xdf\x9c\xb4\x6e\x5f\x33\xb7\x7d\xc0\x7d\
\x0d\x57\x64\x93\x27\x25\xce\x1d\x50\x6b\x4b\xcb\x04\x3c\x82\xf9\
\xba\x49\x27\xd4\x7e\xec\x7d\xc6\x1a\xdb\xf7\x76\x22\xcf\xd3\x03\
\x3d\xdf\x74\xc5\xf8\xb0\xb0\x58\xba\xe2\xd7\xeb\x77\x4f\x9f\xae\
\xc8\x6c\xf4\xa5\xa4\x2b\x0a\xa5\x90\xdf\x7d\xba\x62\x09\x77\x7b\
\xb6\xba\xbb\x9d\x51\x40\x44\xc1\x79\x2a\xf2\xea\xf4\xc6\x5e\xba\
\x55\xd5\x0a\x6d\xe4\xca\xd8\xa5\x55\x10\xf4\x46\x84\xad\xa4\x60\
\x85\x47\x1d\xb3\xbd\x2f\x33\x6b\x91\xcf\x39\x61\x42\x9e\x7b\x69\
\xc6\x69\x9a\xef\xaa\x4a\x35\x65\x59\xa6\x6f\x8e\x46\x21\xc7\x34\
\xe9\xb7\x96\xc8\x2c\x15\x93\x4a\x2e\x9f\x74\x32\x91\x4f\x4a\x53\
\x49\x67\x13\xa9\xa4\x42\x16\xa9\x2c\x4a\x21\x77\x94\x29\x29\xa7\
\xc9\x9c\x1a\x9d\x73\x4a\x4f\xd5\xce\xd9\x5c\xd5\x2e\x6a\xc4\xba\
\x89\xab\x5a\xa3\x51\xab\xe3\xc8\x3e\x1f\x46\xb4\xdf\x4d\x62\x0f\
\x15\xd5\xfa\xeb\xab\x79\xbe\x95\x22\xfa\xc2\x23\xd6\x16\x89\xf4\
\x60\x03\x2f\x8d\xc2\x9f\x75\x48\x94\x16\x91\xe5\xa8\x8c\x24\xf9\
\x16\x2b\x65\xee\xa7\x1f\x72\xff\xe4\x90\xfd\xda\x03\xae\xc7\x50\
\x33\x08\x79\x5a\xee\x97\x1e\x60\x35\x5c\xc3\x81\x55\x15\xf5\x61\
\xca\x40\xa1\x8e\x04\xec\x4f\x3f\x1c\x05\xa8\x38\xd3\x61\x14\x50\
\xe6\x3b\x5b\x90\xd2\x7f\x5c\x54\x0a\x33\x29\xf1\x34\xa9\x90\x9a\
\x95\x5c\xad\x2f\x96\xfb\x4f\xb5\x6a\xfd\x8c\x3b\xb7\x22\x4a\xea\
\xe3\xab\x65\xc9\x7a\xb7\x23\x8c\x3b\xb9\x4f\x11\x66\xdc\xbb\xbe\
\x30\xc5\x06\xf3\x83\x24\x92\x29\x63\x03\xca\x58\x8b\x27\xe2\x98\
\x19\x1b\xc0\xe7\x66\x3d\xe1\xad\x83\xff\x03\xad\x19\x30\x45\
\x00\x00\x0e\x86\
\x00\
\x00\x94\xbb\x78\x9c\xed\x1d\xfd\x73\xda\xb8\xf2\xf7\xfc\x15\x9a\
@ -25068,6 +25077,314 @@ qt_resource_data = "\
\xca\x21\x00\xfc\xd8\x43\x38\x54\x2e\x1c\xb6\x35\x04\x87\x81\xed\
\x23\xdf\x83\x16\xc4\x9f\xef\x05\x11\xbe\xd5\x89\x78\xb3\x9a\x2d\
\xd4\xb1\xb7\x9a\xfd\x0b\xb3\xde\x14\xff\
\x00\x00\x13\x1b\
\x3c\
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\
\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\
\x6e\x6f\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x43\x72\x65\x61\x74\
\x65\x64\x20\x77\x69\x74\x68\x20\x49\x6e\x6b\x73\x63\x61\x70\x65\
\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x69\x6e\x6b\
\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x29\x20\x2d\x2d\x3e\x0a\
\x0a\x3c\x73\x76\x67\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\
\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\
\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\
\x2e\x31\x2f\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\
\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\
\x65\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\
\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\
\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\
\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x0a\x20\x20\x20\
\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\
\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\
\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\
\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x20\x20\
\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\
\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\
\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x0a\x20\x20\x20\x78\x6d\
\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\
\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\
\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\
\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\
\x22\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\x63\
\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\x6d\
\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\x65\
\x22\x0a\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x36\x34\x22\x0a\
\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x22\x0a\x20\
\x20\x20\x69\x64\x3d\x22\x73\x76\x67\x34\x30\x32\x35\x22\x0a\x20\
\x20\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x0a\
\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\
\x69\x6f\x6e\x3d\x22\x30\x2e\x34\x38\x2e\x31\x20\x72\x39\x37\x36\
\x30\x22\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\
\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x44\x72\x61\x66\x74\x5f\x45\x64\
\x69\x74\x2e\x73\x76\x67\x22\x3e\x0a\x20\x20\x3c\x64\x65\x66\x73\
\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\x73\x34\x30\
\x32\x37\x22\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x3a\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\
\x20\x20\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\
\x79\x70\x65\x3d\x22\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\
\x72\x73\x70\x33\x64\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\
\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\
\x20\x31\x36\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\
\x20\x3a\x20\x31\x30\x30\x30\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\
\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\
\x7a\x3d\x22\x33\x32\x20\x3a\x20\x31\x36\x20\x3a\x20\x31\x22\x0a\
\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\
\x70\x65\x72\x73\x70\x33\x64\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\
\x31\x36\x20\x3a\x20\x31\x30\x2e\x36\x36\x36\x36\x36\x37\x20\x3a\
\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x70\
\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x34\x30\x33\x33\x22\x20\
\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x69\x6e\x6b\x73\x63\x61\x70\x65\
\x3a\x70\x65\x72\x73\x70\x65\x63\x74\x69\x76\x65\x0a\x20\x20\x20\
\x20\x20\x20\x20\x69\x64\x3d\x22\x70\x65\x72\x73\x70\x65\x63\x74\
\x69\x76\x65\x34\x30\x31\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x33\x64\
\x2d\x6f\x72\x69\x67\x69\x6e\x3d\x22\x30\x2e\x35\x20\x3a\x20\x30\
\x2e\x33\x33\x33\x33\x33\x33\x33\x33\x20\x3a\x20\x31\x22\x0a\x20\
\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\
\x70\x5f\x7a\x3d\x22\x31\x20\x3a\x20\x30\x2e\x35\x20\x3a\x20\x31\
\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\
\x65\x3a\x76\x70\x5f\x79\x3d\x22\x30\x20\x3a\x20\x31\x30\x30\x30\
\x20\x3a\x20\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\
\x73\x63\x61\x70\x65\x3a\x76\x70\x5f\x78\x3d\x22\x30\x20\x3a\x20\
\x30\x2e\x35\x20\x3a\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x69\
\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x65\x72\x73\x70\x33\x64\x22\
\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\
\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x30\x39\x35\x22\
\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\
\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x33\x39\x39\x39\x22\x0a\
\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\
\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\
\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x31\x3d\
\x22\x39\x30\x31\x2e\x31\x38\x37\x35\x22\x0a\x20\x20\x20\x20\x20\
\x20\x20\x79\x31\x3d\x22\x31\x31\x39\x30\x2e\x38\x37\x35\x22\x0a\
\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x31\x32\x36\x37\x2e\
\x39\x30\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\x32\x3d\
\x22\x31\x31\x39\x30\x2e\x38\x37\x35\x22\x0a\x20\x20\x20\x20\x20\
\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\
\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x31\x30\
\x34\x35\x36\x37\x39\x31\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x30\x34\
\x35\x36\x37\x39\x31\x2c\x34\x32\x30\x2e\x39\x30\x30\x30\x36\x2c\
\x33\x31\x2e\x30\x32\x33\x36\x32\x29\x22\x20\x2f\x3e\x0a\x20\x20\
\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\
\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\
\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x30\x39\x35\x22\
\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\
\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\
\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x35\x62\x66\x66\
\x3b\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\
\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\
\x74\x3d\x22\x30\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\
\x64\x3d\x22\x73\x74\x6f\x70\x34\x30\x39\x37\x22\x20\x2f\x3e\x0a\
\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x0a\x20\x20\x20\x20\
\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x73\x74\x6f\x70\
\x2d\x63\x6f\x6c\x6f\x72\x3a\x23\x63\x31\x65\x33\x66\x37\x3b\x73\
\x74\x6f\x70\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x22\x0a\
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6f\x66\x66\x73\x65\x74\x3d\
\x22\x31\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\
\x22\x73\x74\x6f\x70\x34\x30\x39\x39\x22\x20\x2f\x3e\x0a\x20\x20\
\x20\x20\x3c\x2f\x6c\x69\x6e\x65\x61\x72\x47\x72\x61\x64\x69\x65\
\x6e\x74\x3e\x0a\x20\x20\x20\x20\x3c\x6c\x69\x6e\x65\x61\x72\x47\
\x72\x61\x64\x69\x65\x6e\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x6f\x6c\x6c\x65\x63\x74\x3d\
\x22\x61\x6c\x77\x61\x79\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x6c\x69\x6e\
\x65\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x34\x30\x39\x35\x22\
\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x6c\x69\x6e\x65\
\x61\x72\x47\x72\x61\x64\x69\x65\x6e\x74\x32\x39\x37\x39\x22\x0a\
\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\x64\x69\x65\x6e\x74\x55\
\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\x70\x61\x63\x65\x4f\
\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x67\x72\x61\
\x64\x69\x65\x6e\x74\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\
\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x31\x31\x31\x35\x34\x35\x38\
\x33\x2c\x30\x2c\x30\x2c\x30\x2e\x31\x30\x36\x33\x32\x38\x35\x34\
\x2c\x2d\x39\x39\x2e\x30\x33\x34\x32\x38\x31\x2c\x2d\x31\x33\x35\
\x2e\x37\x30\x34\x34\x39\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x78\x31\x3d\x22\x39\x30\x31\x2e\x31\x38\x37\x35\x22\x0a\x20\x20\
\x20\x20\x20\x20\x20\x79\x31\x3d\x22\x31\x31\x39\x30\x2e\x38\x37\
\x35\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x32\x3d\x22\x31\x32\
\x36\x37\x2e\x39\x30\x36\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x79\x32\x3d\x22\x31\x31\x39\x30\x2e\x38\x37\x35\x22\x20\x2f\x3e\
\x0a\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\x3c\x73\x6f\
\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\
\x0a\x20\x20\x20\x20\x20\x69\x64\x3d\x22\x62\x61\x73\x65\x22\x0a\
\x20\x20\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\
\x23\x66\x66\x66\x66\x66\x66\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\
\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\
\x36\x36\x22\x0a\x20\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\
\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x0a\x20\x20\x20\
\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\
\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x0a\x20\x20\x20\
\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\
\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0a\x20\x20\x20\x20\x20\x69\
\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x31\x2e\
\x39\x37\x39\x35\x31\x30\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x31\x31\x2e\x31\x33\
\x30\x36\x32\x35\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\
\x61\x70\x65\x3a\x63\x79\x3d\x22\x32\x31\x2e\x32\x32\x30\x32\x30\
\x37\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\
\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\x73\x68\x6f\
\x77\x67\x72\x69\x64\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\
\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x69\x64\x2d\
\x62\x62\x6f\x78\x3d\x22\x74\x72\x75\x65\x22\x0a\x20\x20\x20\x20\
\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x64\x6f\x63\x75\x6d\x65\
\x6e\x74\x2d\x75\x6e\x69\x74\x73\x3d\x22\x70\x78\x22\x0a\x20\x20\
\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\
\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\x30\x22\x0a\
\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\
\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x37\x35\x35\
\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\
\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x30\x22\x0a\x20\x20\x20\
\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\
\x77\x2d\x79\x3d\x22\x32\x32\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\
\x78\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x20\x2f\x3e\x0a\x20\
\x20\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0a\x20\x20\x20\x20\x20\
\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\x34\x30\x33\x30\
\x22\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\
\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0a\
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\
\x75\x74\x3d\x22\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\
\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\
\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\
\x61\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x64\x63\x3a\
\x74\x79\x70\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\
\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\
\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\
\x6d\x61\x67\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\
\x20\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\x63\x3a\
\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x63\
\x63\x3a\x57\x6f\x72\x6b\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\
\x66\x3a\x52\x44\x46\x3e\x0a\x20\x20\x3c\x2f\x6d\x65\x74\x61\x64\
\x61\x74\x61\x3e\x0a\x20\x20\x3c\x67\x0a\x20\x20\x20\x20\x20\x69\
\x64\x3d\x22\x6c\x61\x79\x65\x72\x31\x22\x0a\x20\x20\x20\x20\x20\
\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x6c\x61\x62\x65\x6c\x3d\x22\
\x4c\x61\x79\x65\x72\x20\x31\x22\x0a\x20\x20\x20\x20\x20\x69\x6e\
\x6b\x73\x63\x61\x70\x65\x3a\x67\x72\x6f\x75\x70\x6d\x6f\x64\x65\
\x3d\x22\x6c\x61\x79\x65\x72\x22\x0a\x20\x20\x20\x20\x20\x74\x72\
\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\
\x74\x65\x28\x30\x2c\x33\x32\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\
\x72\x65\x63\x74\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\
\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\
\x3b\x66\x69\x6c\x6c\x3a\x23\x66\x66\x66\x66\x66\x66\x3b\x66\x69\
\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\
\x6f\x6b\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\
\x6b\x65\x2d\x77\x69\x64\x74\x68\x3a\x33\x2e\x35\x34\x32\x39\x39\
\x39\x39\x38\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\
\x61\x70\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\
\x69\x6e\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\
\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\
\x34\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\
\x3a\x31\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\
\x72\x61\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\
\x64\x61\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\
\x6b\x65\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\
\x69\x74\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\
\x6c\x61\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\
\x6c\x6f\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\
\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\
\x63\x75\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\
\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x37\x38\x30\x22\x0a\x20\
\x20\x20\x20\x20\x20\x20\x77\x69\x64\x74\x68\x3d\x22\x35\x38\x2e\
\x32\x32\x35\x37\x31\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x68\
\x65\x69\x67\x68\x74\x3d\x22\x38\x2e\x35\x37\x33\x31\x31\x30\x36\
\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x78\x3d\x22\x2d\x35\x2e\x39\
\x35\x37\x37\x36\x30\x33\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x79\
\x3d\x22\x32\x31\x2e\x33\x32\x37\x34\x33\x33\x22\x0a\x20\x20\x20\
\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\
\x61\x74\x72\x69\x78\x28\x30\x2e\x38\x34\x33\x39\x32\x33\x38\x36\
\x2c\x2d\x30\x2e\x35\x33\x36\x34\x36\x32\x39\x38\x2c\x30\x2e\x35\
\x33\x36\x34\x36\x32\x39\x38\x2c\x30\x2e\x38\x34\x33\x39\x32\x33\
\x38\x36\x2c\x30\x2c\x30\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\
\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x6f\x64\
\x69\x70\x6f\x64\x69\x3a\x74\x79\x70\x65\x3d\x22\x61\x72\x63\x22\
\x0a\x20\x20\x20\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\
\x6f\x6c\x6f\x72\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\
\x6c\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\
\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\
\x6c\x65\x3a\x65\x76\x65\x6e\x6f\x64\x64\x3b\x73\x74\x72\x6f\x6b\
\x65\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\
\x2d\x77\x69\x64\x74\x68\x3a\x33\x2e\x35\x34\x32\x39\x39\x39\x39\
\x38\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\
\x3a\x62\x75\x74\x74\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\
\x65\x6a\x6f\x69\x6e\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\
\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\
\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\
\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\
\x79\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\
\x73\x68\x6f\x66\x66\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\
\x72\x3a\x6e\x6f\x6e\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\
\x79\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\
\x79\x3a\x69\x6e\x6c\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\
\x77\x3a\x76\x69\x73\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\
\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\
\x6d\x75\x6c\x61\x74\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x69\
\x64\x3d\x22\x70\x61\x74\x68\x33\x37\x38\x32\x22\x0a\x20\x20\x20\
\x20\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x78\x3d\
\x22\x32\x30\x2e\x36\x32\x39\x30\x34\x37\x22\x0a\x20\x20\x20\x20\
\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x63\x79\x3d\x22\
\x32\x39\x2e\x30\x38\x32\x34\x33\x34\x22\x0a\x20\x20\x20\x20\x20\
\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x78\x3d\x22\x31\
\x30\x2e\x39\x38\x34\x32\x39\x39\x22\x0a\x20\x20\x20\x20\x20\x20\
\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x72\x79\x3d\x22\x31\x30\
\x2e\x39\x38\x34\x32\x39\x39\x22\x0a\x20\x20\x20\x20\x20\x20\x20\
\x64\x3d\x22\x6d\x20\x33\x31\x2e\x36\x31\x33\x33\x34\x36\x2c\x32\
\x39\x2e\x30\x38\x32\x34\x33\x34\x20\x61\x20\x31\x30\x2e\x39\x38\
\x34\x32\x39\x39\x2c\x31\x30\x2e\x39\x38\x34\x32\x39\x39\x20\x30\
\x20\x31\x20\x31\x20\x2d\x32\x31\x2e\x39\x36\x38\x35\x39\x37\x33\
\x2c\x30\x20\x31\x30\x2e\x39\x38\x34\x32\x39\x39\x2c\x31\x30\x2e\
\x39\x38\x34\x32\x39\x39\x20\x30\x20\x31\x20\x31\x20\x32\x31\x2e\
\x39\x36\x38\x35\x39\x37\x33\x2c\x30\x20\x7a\x22\x0a\x20\x20\x20\
\x20\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\
\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x31\x32\x2e\x35\x36\x33\x37\
\x34\x32\x2c\x2d\x32\x31\x2e\x30\x34\x38\x39\x37\x34\x29\x22\x20\
\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x0a\x20\x20\x20\
\x20\x20\x20\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\
\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\x3a\x23\x66\
\x66\x30\x63\x30\x30\x3b\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\
\x74\x79\x3a\x31\x3b\x66\x69\x6c\x6c\x2d\x72\x75\x6c\x65\x3a\x65\
\x76\x65\x6e\x6f\x64\x64\x3b\x73\x74\x72\x6f\x6b\x65\x3a\x23\x34\
\x37\x30\x30\x30\x30\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\
\x74\x68\x3a\x33\x2e\x32\x33\x38\x36\x33\x32\x32\x3b\x73\x74\x72\
\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3a\x62\x75\x74\x74\
\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\
\x3a\x72\x6f\x75\x6e\x64\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\
\x74\x65\x72\x6c\x69\x6d\x69\x74\x3a\x34\x3b\x73\x74\x72\x6f\x6b\
\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x73\x74\x72\x6f\
\x6b\x65\x2d\x64\x61\x73\x68\x61\x72\x72\x61\x79\x3a\x6e\x6f\x6e\
\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x64\x61\x73\x68\x6f\x66\x66\
\x73\x65\x74\x3a\x30\x3b\x6d\x61\x72\x6b\x65\x72\x3a\x6e\x6f\x6e\
\x65\x3b\x76\x69\x73\x69\x62\x69\x6c\x69\x74\x79\x3a\x76\x69\x73\
\x69\x62\x6c\x65\x3b\x64\x69\x73\x70\x6c\x61\x79\x3a\x69\x6e\x6c\
\x69\x6e\x65\x3b\x6f\x76\x65\x72\x66\x6c\x6f\x77\x3a\x76\x69\x73\
\x69\x62\x6c\x65\x3b\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\
\x67\x72\x6f\x75\x6e\x64\x3a\x61\x63\x63\x75\x6d\x75\x6c\x61\x74\
\x65\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x64\x3d\x22\x6d\x20\x31\
\x34\x2e\x31\x38\x30\x33\x39\x32\x2c\x2d\x32\x38\x2e\x32\x34\x36\
\x32\x39\x35\x20\x30\x2c\x31\x32\x2e\x31\x39\x35\x39\x32\x38\x20\
\x2d\x39\x2e\x32\x39\x39\x36\x39\x2c\x30\x20\x30\x2c\x36\x2e\x35\
\x36\x37\x30\x33\x37\x38\x20\x39\x2e\x32\x39\x39\x36\x39\x2c\x30\
\x20\x37\x2e\x31\x33\x39\x31\x35\x35\x2c\x30\x20\x39\x2e\x36\x37\
\x35\x34\x33\x35\x2c\x30\x20\x30\x2c\x2d\x36\x2e\x35\x36\x37\x30\
\x33\x37\x38\x20\x2d\x39\x2e\x36\x37\x35\x34\x33\x35\x2c\x30\x20\
\x30\x2c\x2d\x31\x32\x2e\x31\x39\x35\x39\x32\x38\x20\x2d\x37\x2e\
\x31\x33\x39\x31\x35\x35\x2c\x30\x20\x7a\x22\x0a\x20\x20\x20\x20\
\x20\x20\x20\x69\x64\x3d\x22\x72\x65\x63\x74\x33\x37\x38\x34\x22\
\x0a\x20\x20\x20\x20\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\
\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\x75\x72\x76\x61\
\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\
\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\
\x00\x00\x08\x45\
\x00\
\x00\x26\xfb\x78\x9c\xed\x59\x6b\x6f\xdb\x38\x16\xfd\x9e\x5f\xa1\
@ -31812,6 +32129,10 @@ qt_resource_name = "\
\x03\xe2\xfa\x67\
\x00\x44\
\x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x50\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
\x00\x0e\
\x04\x78\x06\xe7\
\x00\x44\
\x00\x72\x00\x61\x00\x66\x00\x74\x00\x5f\x00\x53\x00\x6e\x00\x61\x00\x70\x00\x2e\x00\x73\x00\x76\x00\x67\
\x00\x15\
\x0e\x5a\x0f\xa7\
\x00\x44\
@ -31963,8 +32284,8 @@ qt_resource_name = "\
qt_resource_struct = "\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x01\
\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x41\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x27\x00\x00\x00\x1a\
\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x42\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x28\x00\x00\x00\x1a\
\x00\x00\x00\x38\x00\x02\x00\x00\x00\x05\x00\x00\x00\x15\
\x00\x00\x00\x1a\x00\x02\x00\x00\x00\x10\x00\x00\x00\x05\
\x00\x00\x02\x72\x00\x01\x00\x00\x00\x01\x00\x05\x98\x94\
@ -31988,47 +32309,48 @@ qt_resource_struct = "\
\x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x01\x64\
\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x04\xc4\
\x00\x00\x00\x7c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x12\
\x00\x00\x05\x78\x00\x01\x00\x00\x00\x01\x00\x06\x84\x61\
\x00\x00\x03\x70\x00\x00\x00\x00\x00\x01\x00\x05\xfb\x6c\
\x00\x00\x06\xf8\x00\x01\x00\x00\x00\x01\x00\x07\x07\xef\
\x00\x00\x04\x58\x00\x01\x00\x00\x00\x01\x00\x06\x33\x34\
\x00\x00\x05\xc0\x00\x00\x00\x00\x00\x01\x00\x06\xa1\xab\
\x00\x00\x06\x82\x00\x01\x00\x00\x00\x01\x00\x06\xe6\xe3\
\x00\x00\x08\xc8\x00\x01\x00\x00\x00\x01\x00\x07\xa6\x8b\
\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x14\x8e\
\x00\x00\x05\x9a\x00\x00\x00\x00\x00\x01\x00\x06\x8f\x15\
\x00\x00\x06\x08\x00\x01\x00\x00\x00\x01\x00\x06\xba\x70\
\x00\x00\x03\x92\x00\x01\x00\x00\x00\x01\x00\x06\x0a\x22\
\x00\x00\x08\x52\x00\x00\x00\x00\x00\x01\x00\x07\x88\xd1\
\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xea\xd6\
\x00\x00\x04\xa8\x00\x01\x00\x00\x00\x01\x00\x06\x4e\x53\
\x00\x00\x08\x0a\x00\x01\x00\x00\x00\x01\x00\x07\x74\xdb\
\x00\x00\x08\x2c\x00\x01\x00\x00\x00\x01\x00\x07\x7f\x3d\
\x00\x00\x04\x86\x00\x00\x00\x00\x00\x01\x00\x06\x3c\x3a\
\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe3\x1d\
\x00\x00\x07\xc2\x00\x00\x00\x00\x00\x01\x00\x07\x4b\x51\
\x00\x00\x04\xfc\x00\x01\x00\x00\x00\x01\x00\x06\x5f\xc3\
\x00\x00\x07\xe6\x00\x00\x00\x00\x00\x01\x00\x07\x62\x04\
\x00\x00\x06\x5c\x00\x00\x00\x00\x00\x01\x00\x06\xd5\x2b\
\x00\x00\x04\x0a\x00\x01\x00\x00\x00\x01\x00\x06\x22\x56\
\x00\x00\x03\x40\x00\x01\x00\x00\x00\x01\x00\x05\xf2\xdd\
\x00\x00\x07\x1a\x00\x01\x00\x00\x00\x01\x00\x07\x10\x98\
\x00\x00\x08\x78\x00\x00\x00\x00\x00\x01\x00\x07\x91\x5e\
\x00\x00\x05\x56\x00\x01\x00\x00\x00\x01\x00\x06\x77\x02\
\x00\x00\x06\x34\x00\x01\x00\x00\x00\x01\x00\x06\xcb\x7a\
\x00\x00\x07\x70\x00\x00\x00\x00\x00\x01\x00\x07\x2c\xed\
\x00\x00\x04\x2e\x00\x01\x00\x00\x00\x01\x00\x06\x28\xf3\
\x00\x00\x04\xdc\x00\x01\x00\x00\x00\x01\x00\x06\x5a\x44\
\x00\x00\x07\x92\x00\x01\x00\x00\x00\x01\x00\x07\x41\x7e\
\x00\x00\x06\xa8\x00\x01\x00\x00\x00\x01\x00\x06\xec\xa7\
\x00\x00\x06\xd0\x00\x01\x00\x00\x00\x01\x00\x06\xf8\x19\
\x00\x00\x08\x9e\x00\x01\x00\x00\x00\x01\x00\x07\x9c\x09\
\x00\x00\x03\xda\x00\x01\x00\x00\x00\x01\x00\x06\x1a\x0d\
\x00\x00\x05\x2a\x00\x00\x00\x00\x00\x01\x00\x06\x67\xa8\
\x00\x00\x05\xe8\x00\x01\x00\x00\x00\x01\x00\x06\xb0\xfc\
\x00\x00\x07\x3e\x00\x00\x00\x00\x00\x01\x00\x07\x17\xe9\
\x00\x00\x05\x9a\x00\x01\x00\x00\x00\x01\x00\x06\x98\x18\
\x00\x00\x03\x70\x00\x00\x00\x00\x00\x01\x00\x05\xfc\x04\
\x00\x00\x07\x1a\x00\x01\x00\x00\x00\x01\x00\x07\x1b\xa6\
\x00\x00\x04\x7a\x00\x01\x00\x00\x00\x01\x00\x06\x46\xeb\
\x00\x00\x05\xe2\x00\x00\x00\x00\x00\x01\x00\x06\xb5\x62\
\x00\x00\x06\xa4\x00\x01\x00\x00\x00\x01\x00\x06\xfa\x9a\
\x00\x00\x08\xea\x00\x01\x00\x00\x00\x01\x00\x07\xba\x42\
\x00\x00\x03\xb6\x00\x01\x00\x00\x00\x01\x00\x06\x15\x26\
\x00\x00\x05\xbc\x00\x00\x00\x00\x00\x01\x00\x06\xa2\xcc\
\x00\x00\x03\xda\x00\x00\x00\x00\x00\x01\x00\x06\x1a\xa5\
\x00\x00\x06\x2a\x00\x01\x00\x00\x00\x01\x00\x06\xce\x27\
\x00\x00\x03\x92\x00\x01\x00\x00\x00\x01\x00\x06\x0a\xba\
\x00\x00\x08\x74\x00\x00\x00\x00\x00\x01\x00\x07\x9c\x88\
\x00\x00\x03\x14\x00\x01\x00\x00\x00\x01\x00\x05\xeb\x6e\
\x00\x00\x04\xca\x00\x01\x00\x00\x00\x01\x00\x06\x62\x0a\
\x00\x00\x08\x2c\x00\x01\x00\x00\x00\x01\x00\x07\x88\x92\
\x00\x00\x08\x4e\x00\x01\x00\x00\x00\x01\x00\x07\x92\xf4\
\x00\x00\x04\xa8\x00\x00\x00\x00\x00\x01\x00\x06\x4f\xf1\
\x00\x00\x02\xe2\x00\x01\x00\x00\x00\x01\x00\x05\xe3\xb5\
\x00\x00\x07\xe4\x00\x00\x00\x00\x00\x01\x00\x07\x5f\x08\
\x00\x00\x05\x1e\x00\x01\x00\x00\x00\x01\x00\x06\x73\x7a\
\x00\x00\x08\x08\x00\x00\x00\x00\x00\x01\x00\x07\x75\xbb\
\x00\x00\x06\x7e\x00\x00\x00\x00\x00\x01\x00\x06\xe8\xe2\
\x00\x00\x04\x2c\x00\x01\x00\x00\x00\x01\x00\x06\x36\x0d\
\x00\x00\x03\x40\x00\x01\x00\x00\x00\x01\x00\x05\xf3\x75\
\x00\x00\x07\x3c\x00\x01\x00\x00\x00\x01\x00\x07\x24\x4f\
\x00\x00\x08\x9a\x00\x00\x00\x00\x00\x01\x00\x07\xa5\x15\
\x00\x00\x05\x78\x00\x01\x00\x00\x00\x01\x00\x06\x8a\xb9\
\x00\x00\x06\x56\x00\x01\x00\x00\x00\x01\x00\x06\xdf\x31\
\x00\x00\x07\x92\x00\x00\x00\x00\x00\x01\x00\x07\x40\xa4\
\x00\x00\x04\x50\x00\x01\x00\x00\x00\x01\x00\x06\x3c\xaa\
\x00\x00\x04\xfe\x00\x01\x00\x00\x00\x01\x00\x06\x6d\xfb\
\x00\x00\x07\xb4\x00\x01\x00\x00\x00\x01\x00\x07\x55\x35\
\x00\x00\x06\xca\x00\x01\x00\x00\x00\x01\x00\x07\x00\x5e\
\x00\x00\x06\xf2\x00\x01\x00\x00\x00\x01\x00\x07\x0b\xd0\
\x00\x00\x08\xc0\x00\x01\x00\x00\x00\x01\x00\x07\xaf\xc0\
\x00\x00\x03\xfc\x00\x01\x00\x00\x00\x01\x00\x06\x2d\xc4\
\x00\x00\x05\x4c\x00\x00\x00\x00\x00\x01\x00\x06\x7b\x5f\
\x00\x00\x06\x0a\x00\x01\x00\x00\x00\x01\x00\x06\xc4\xb3\
\x00\x00\x07\x60\x00\x00\x00\x00\x00\x01\x00\x07\x2b\xa0\
\x00\x00\x02\x8e\x00\x01\x00\x00\x00\x01\x00\x05\xcc\x17\
\x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x05\xd4\x93\
\x00\x00\x02\xba\x00\x01\x00\x00\x00\x01\x00\x05\xd5\x2b\
"
def qInitResources():

View File

@ -191,7 +191,8 @@ 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"]
self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup","Draft_SelectGroup","Draft_SelectPlane"]
self.treecmdList = ["Draft_ApplyStyle","Draft_ToggleDisplayMode","Draft_AddToGroup",
"Draft_SelectGroup","Draft_SelectPlane","Draft_ToggleSnap"]
self.lineList = ["Draft_UndoLine","Draft_FinishLine","Draft_CloseLine"]
self.appendToolbar(str(DraftTools.translate("draft","Draft creation tools")),self.cmdList)
self.appendToolbar(str(DraftTools.translate("draft","Draft modification tools")),self.modList)

View File

@ -39,6 +39,7 @@
<file>icons/Draft_Cursor.svg</file>
<file>icons/Draft_Dot.svg</file>
<file>icons/Draft_Point.svg</file>
<file>icons/Draft_Snap.svg</file>
<file>patterns/concrete.svg</file>
<file>patterns/cross.svg</file>
<file>patterns/line.svg</file>

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg4025"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="Draft_Edit.svg">
<defs
id="defs4027">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective4033" />
<inkscape:perspective
id="perspective4010"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4095"
id="linearGradient3999"
gradientUnits="userSpaceOnUse"
x1="901.1875"
y1="1190.875"
x2="1267.9062"
y2="1190.875"
gradientTransform="matrix(0.10456791,0,0,0.10456791,420.90006,31.02362)" />
<linearGradient
id="linearGradient4095">
<stop
style="stop-color:#005bff;stop-opacity:1;"
offset="0"
id="stop4097" />
<stop
style="stop-color:#c1e3f7;stop-opacity:1;"
offset="1"
id="stop4099" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4095"
id="linearGradient2979"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.11154583,0,0,0.10632854,-99.034281,-135.70449)"
x1="901.1875"
y1="1190.875"
x2="1267.9062"
y2="1190.875" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.9795105"
inkscape:cx="11.130625"
inkscape:cy="21.220207"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1280"
inkscape:window-height="755"
inkscape:window-x="0"
inkscape:window-y="22"
inkscape:window-maximized="1" />
<metadata
id="metadata4030">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,32)">
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.54299998;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3780"
width="58.225712"
height="8.5731106"
x="-5.9577603"
y="21.327433"
transform="matrix(0.84392386,-0.53646298,0.53646298,0.84392386,0,0)" />
<path
sodipodi:type="arc"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.54299998;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path3782"
sodipodi:cx="20.629047"
sodipodi:cy="29.082434"
sodipodi:rx="10.984299"
sodipodi:ry="10.984299"
d="m 31.613346,29.082434 a 10.984299,10.984299 0 1 1 -21.9685973,0 10.984299,10.984299 0 1 1 21.9685973,0 z"
transform="translate(12.563742,-21.048974)" />
<path
style="color:#000000;fill:#ff0c00;fill-opacity:1;fill-rule:evenodd;stroke:#470000;stroke-width:3.2386322;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 14.180392,-28.246295 0,12.195928 -9.29969,0 0,6.5670378 9.29969,0 7.139155,0 9.675435,0 0,-6.5670378 -9.675435,0 0,-12.195928 -7.139155,0 z"
id="rect3784"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -280,6 +280,46 @@ If color mapping is choosed, you must choose a color mapping file containing a t
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_8">
<property name="toolTip">
<string>If this is checked, imported texts will get the standard Draft text size, instead of the size they have in the DXF document</string>
</property>
<property name="text">
<string>Use standard font size for texts</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>dxfStdSize</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_10">
<property name="toolTip">
<string>If this is checked, hatches will be converted into simple wires</string>
</property>
<property name="text">
<string>Import hatch boundaries as wires</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>importDxfHatches</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>

View File

@ -83,7 +83,7 @@ class plane:
= (cp . axis) / (direction . axis)
'''
if direction == None: direction = self.axis
return self.axis.dot(self.position.sub(p))/self.axis.dot(direction)
return direction.dot(self.position.sub(p))
def projectPoint(self, p, direction=None):
'''project point onto plane, default direction is orthogonal'''

View File

@ -161,9 +161,10 @@ def isColinear(vlist):
'''isColinear(list_of_vectors): checks if vectors in given list are colinear'''
typecheck ([(vlist,list)], "isColinear");
if len(vlist) < 3: return True
p = precision()
first = vlist[1].sub(vlist[0])
for i in range(2,len(vlist)):
if angle(vlist[i].sub(vlist[0]),first) != 0:
if round(angle(vlist[i].sub(vlist[0]),first),p) != 0:
return False
return True

View File

@ -70,6 +70,40 @@ def decodeName(name):
decodedName = name
return decodedName
def deformat(text):
"removes weird formats in texts and wipes UTF characters"
# remove ACAD string formatation
#t = re.sub('{([^!}]([^}]|\n)*)}', '', 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 degrees, diameters chars
t = re.sub('%%d','°',t)
t = re.sub('%%c','Ø',t)
return t
def locateLayer(wantedLayer):
"returns layer group and creates it if needed"
wantedLayerName = decodeName(wantedLayer)
@ -81,6 +115,17 @@ def locateLayer(wantedLayer):
layers.append(newLayer)
return newLayer
def getdimheight(style):
"returns the dimension text height from the given dimstyle"
for t in drawing.tables.data:
if t.name == 'dimstyle':
for a in t.data:
if hasattr(a,"type"):
if a.type == "dimstyle":
if rawValue(a,2) == style:
return rawValue(a,140)
return None
def calcBulge(v1,bulge,v2):
'''
calculates intermediary vertex for curved segments.
@ -126,6 +171,23 @@ def rawValue(entity,code):
value = pair[1]
return value
def getMultiplePoints(entity):
"scans the given entity for multiple points (paths, leaders, etc)"
pts = []
for d in entity.data:
if d[0] == 10:
pts.append([d[1]])
elif d[0] in [20,30]:
pts[-1].append(d[1])
pts.reverse()
points = []
for p in pts:
if len(p) == 3:
points.append(Vector(p[0],p[1],p[2]))
else:
points.append(Vector(p[0],p[1],0))
return points
class fcformat:
"this contains everything related to color/lineweight formatting"
def __init__(self,drawing):
@ -137,6 +199,8 @@ class fcformat:
self.paramstyle = params.GetInt("dxfstyle")
self.join = params.GetBool("joingeometry")
self.makeBlocks = params.GetBool("groupLayers")
self.stdSize = params.GetBool("dxfStdSize")
self.importDxfHatches = params.GetBool("importDxfHatches")
bparams = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View")
if self.paramstyle > 1:
@ -223,16 +287,19 @@ class fcformat:
print table
return table
def formatObject(self,obj,dxfobj,textmode=False):
def formatObject(self,obj,dxfobj=None):
"applies color and linetype to objects"
if self.paramstyle == 1:
if textmode:
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 = self.col
else:
obj.ViewObject.LineColor = self.col
obj.ViewObject.LineWidth = self.lw
elif self.paramstyle == 2:
if textmode:
elif (self.paramstyle == 2) and dxfobj:
if hasattr(obj.ViewObject,"TextColor"):
if dxfobj.color_index == 256: cm = self.getGroupColor(dxfobj)[:3]
else: cm = dxfColorMap.color_map[dxfobj.color_index]
obj.ViewObject.TextColor = (cm[0],cm[1],cm[2])
@ -242,8 +309,8 @@ class fcformat:
else: cm = dxfColorMap.color_map[dxfobj.color_index]
obj.ViewObject.LineColor = (cm[0],cm[1],cm[2],0.0)
obj.ViewObject.LineWidth = self.lw
elif self.paramstyle == 3:
if textmode:
elif (self.paramstyle == 3) and dxfobj:
if hasattr(obj.ViewObject,"TextColor"):
cm = table[dxfobj.color_index][0]
wm = table[dxfobj.color_index][1]
obj.ViewObject.TextColor = (cm[0],cm[1],cm[2])
@ -290,7 +357,7 @@ def drawLine(line,shapemode=False):
warn(line)
return None
def drawPolyline(polyline,shapemode=False):
def drawPolyline(polyline,shapemode=False,num=None):
"returns a Part shape from a dxf polyline"
if (len(polyline.points) > 1):
edges = []
@ -308,13 +375,13 @@ def drawPolyline(polyline,shapemode=False):
cv = calcBulge(v1,polyline.points[p].bulge,v2)
if fcvec.isColinear([v1,cv,v2]):
try: edges.append(Part.Line(v1,v2).toShape())
except: warn(polyline)
except: warn(polyline,num)
else:
try: edges.append(Part.Arc(v1,cv,v2).toShape())
except: warn(polyline)
except: warn(polyline,num)
else:
try: edges.append(Part.Line(v1,v2).toShape())
except: warn(polyline)
except: warn(polyline,num)
verts.append(v2)
if polyline.closed:
p1 = polyline.points[len(polyline.points)-1]
@ -324,11 +391,15 @@ def drawPolyline(polyline,shapemode=False):
cv = calcBulge(v1,polyline.points[-1].bulge,v2)
if not fcvec.equals(v1,v2):
if fcvec.isColinear([v1,cv,v2]):
try: edges.append(Part.Line(v1,v2).toShape())
except: warn(polyline)
try:
edges.append(Part.Line(v1,v2).toShape())
except:
warn(polyline,num)
else:
try: edges.append(Part.Arc(v1,cv,v2).toShape())
except: warn(polyline)
try:
edges.append(Part.Arc(v1,cv,v2).toShape())
except:
warn(polyline,num)
if edges:
try:
if (fmt.paramstyle >= 4) and (not curves) and (not shapemode):
@ -342,7 +413,7 @@ def drawPolyline(polyline,shapemode=False):
else:
return Part.Wire(edges)
except:
warn(polyline)
warn(polyline,num)
return None
def drawArc(arc,shapemode=False):
@ -495,7 +566,7 @@ def drawSpline(spline,shapemode=False):
return ob
else:
sp = Part.BSplineCurve()
print knots
# print knots
sp.interpolate(verts)
sh = Part.Wire(sp.toShape())
if closed:
@ -506,8 +577,11 @@ def drawSpline(spline,shapemode=False):
warn(spline)
return None
def drawBlock(blockref):
def drawBlock(blockref,num=None):
"returns a shape from a dxf block reference"
if not fmt.paramstarblocks:
if blockref.name[0] == '*':
return None
shapes = []
for line in blockref.entities.get_type('line'):
s = drawLine(line,shapemode=True)
@ -525,8 +599,10 @@ def drawBlock(blockref):
s = drawCircle(circle,shapemode=True)
if s: shapes.append(s)
for insert in blockref.entities.get_type('insert'):
s = drawInsert(insert)
if s: shapes.append(s)
print "insert ",insert," in block ",insert.block[0]
if fmt.paramstarblocks or insert.block[0] != '*':
s = drawInsert(insert)
if s: shapes.append(s)
for solid in blockref.entities.get_type('solid'):
s = drawSolid(solid)
if s: shapes.append(s)
@ -534,11 +610,14 @@ def drawBlock(blockref):
s = drawSpline(spline,shapemode=True)
if s: shapes.append(s)
for text in blockref.entities.get_type('text'):
if fmt.dxflayout or (not rawValue(text,67)):
addText(text)
if fmt.paramtext:
if fmt.dxflayout or (not rawValue(text,67)):
addText(text)
for text in blockref.entities.get_type('mtext'):
if fmt.dxflayout or (not rawValue(text,67)):
addText(text)
if fmt.paramtext:
if fmt.dxflayout or (not rawValue(text,67)):
print "adding block text",text.value, " from ",blockref
addText(text)
try: shape = Part.makeCompound(shapes)
except: warn(blockref)
if shape:
@ -546,14 +625,14 @@ def drawBlock(blockref):
return shape
return None
def drawInsert(insert):
def drawInsert(insert,num=None):
if blockshapes.has_key(insert):
shape = blockshapes[insert.block]
shape = blockshapes[insert.block].copy()
else:
shape = None
for b in drawing.blocks.data:
if b.name == insert.block:
shape = drawBlock(b)
shape = drawBlock(b,num)
if fmt.paramtext:
attrs = attribs(insert)
for a in attrs:
@ -563,7 +642,7 @@ def drawInsert(insert):
rot = math.radians(insert.rotation)
scale = insert.scale
tsf = FreeCAD.Matrix()
tsf.scale(vec(scale))
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)
@ -598,7 +677,6 @@ def attribs(insert):
j = index+1
while True:
ent = drawing.entities.data[j]
print str(ent)
if str(ent) == 'seqend':
return atts
elif str(ent) == 'attrib':
@ -615,6 +693,7 @@ def addObject(shape,name="Shape",layer=None):
if layer:
lay=locateLayer(layer)
lay.addObject(newob)
fmt.formatObject(newob)
return newob
def addText(text,attrib=False):
@ -630,18 +709,41 @@ def addText(text,attrib=False):
pos = FreeCAD.Vector(text.loc[0],text.loc[1],text.loc[2])
hgt = text.height
if val:
newob=doc.addObject("App::Annotation","Text")
if attrib:
newob = doc.addObject("App::Annotation","Attribute")
else:
newob = doc.addObject("App::Annotation","Text")
lay.addObject(newob)
val = re.sub('{([^!}]([^}]|\n)*)}', '', val)
val = re.sub('%%d','°',val)
val = re.sub('%%c','Ø',val)
val = val.decode("Latin1").encode("Latin1")
newob.LabelText = val
val = deformat(val)
#val = val.decode("Latin1").encode("Latin1")
rx = rawValue(text,11)
ry = rawValue(text,21)
rz = rawValue(text,31)
if rx or ry or rz:
xv = Vector(rx,ry,rz)
if not fcvec.isNull(xv):
ax = fcvec.neg(xv.cross(Vector(1,0,0)))
if fcvec.isNull(ax):
ax = Vector(0,0,1)
ang = -math.degrees(fcvec.angle(xv,Vector(1,0,0),ax))
Draft.rotate(newob,ang,axis=ax)
elif hasattr(text,"rotation"):
if text.rotation:
Draft.rotate(newob,text.rotation)
newob.LabelText = val.split("\n")
newob.Position = pos
if gui:
newob.ViewObject.FontSize=float(hgt)
if fmt.stdSize:
newob.ViewObject.FontSize = FreeCADGui.draftToolBar.fontsize
else:
newob.ViewObject.FontSize = float(hgt)
if hasattr(text,"alignment"):
if text.alignment in [2,5,8]:
newob.ViewObject.Justification = "Center"
elif text.alignment in [3,6,9]:
newob.ViewObject.Justification = "Right"
newob.ViewObject.DisplayMode = "World"
fmt.formatObject(newob,text,textmode=True)
fmt.formatObject(newob,text)
def addToBlock(obj,layer):
"adds given shape to the layer dict"
@ -715,10 +817,12 @@ def processdxf(document,filename):
polylines.append(p)
else:
polylines.append(p)
if polylines: FreeCAD.Console.PrintMessage("drawing "+str(len(polylines))+" polylines...\n")
if polylines:
FreeCAD.Console.PrintMessage("drawing "+str(len(polylines))+" polylines...\n")
num = 0
for polyline in polylines:
if fmt.dxflayout or (not rawValue(polyline,67)):
shape = drawPolyline(polyline)
shape = drawPolyline(polyline,num)
if shape:
if fmt.paramstyle == 5:
if isinstance(shape,Part.Shape):
@ -743,6 +847,7 @@ def processdxf(document,filename):
else:
newob = addObject(shape,"Polyline",polyline.layer)
if gui: fmt.formatObject(newob,polyline)
num += 1
# drawing arcs
@ -841,7 +946,8 @@ def processdxf(document,filename):
if fmt.paramtext:
texts = drawing.entities.get_type("mtext")
texts.extend(drawing.entities.get_type("text"))
if texts: FreeCAD.Console.PrintMessage("drawing "+str(len(texts))+" texts...\n")
if texts:
FreeCAD.Console.PrintMessage("drawing "+str(len(texts))+" texts...\n")
for text in texts:
if fmt.dxflayout or (not rawValue(text,67)):
addText(text)
@ -899,9 +1005,9 @@ def processdxf(document,filename):
p1 = FreeCAD.Vector(x2,y2,z2)
p2 = FreeCAD.Vector(x3,y3,z3)
if align == 0:
if angle == 0:
if angle in [0,180]:
p2 = FreeCAD.Vector(x3,y2,z2)
else:
elif angle in [90,270]:
p2 = FreeCAD.Vector(x2,y3,z2)
newob = doc.addObject("App::FeaturePython","Dimension")
lay.addObject(newob)
@ -914,11 +1020,84 @@ def processdxf(document,filename):
dim.layer = layer
dim.color_index = 256
fmt.formatObject (newob,dim)
if fmt.stdSize:
newob.ViewObject.FontSize = FreeCADGui.draftToolBar.fontsize
else:
st = rawValue(dim,3)
newob.ViewObject.FontSize = float(getdimheight(st))
else: FreeCAD.Console.PrintMessage("skipping dimensions...\n")
# drawing blocks
# 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)
# drawing leaders
if fmt.paramtext:
leaders = drawing.entities.get_type("leader")
if leaders:
FreeCAD.Console.PrintMessage("drawing "+str(len(leaders))+" leaders...\n")
for leader in leaders:
if fmt.dxflayout or (not rawValue(leader,67)):
points = getMultiplePoints(leader)
newob = Draft.makeWire(points)
lay = locateLayer(rawValue(leader,8))
lay.addObject(newob)
if gui:
newob.ViewObject.EndArrow = True
fmt.formatObject(newob,leader)
else:
FreeCAD.Console.PrintMessage("skipping leaders...\n")
# drawing hatches
if fmt.importDxfHatches:
hatches = drawing.entities.get_type("hatch")
if hatches:
FreeCAD.Console.PrintMessage("drawing "+str(len(hatches))+" hatches...\n")
for hatch in hatches:
if fmt.dxflayout or (not rawValue(hatch,67)):
points = getMultiplePoints(hatch)
if len(points) > 1:
lay = rawValue(hatch,8)
points = points[:-1]
newob = None
if (fmt.paramstyle == 0) or fmt.makeBlocks:
points.append(points[0])
s = Part.makePolygon(points)
if fmt.makeBlocks:
addToBlock(s,lay)
else:
newob = doc.addObject("Part::Feature","Hatch")
newob.Shape = s
else:
newob = Draft.makeWire(points)
if newob:
locateLayer(lay).addObject(newob)
if gui:
fmt.formatObject(newob,hatch)
else:
FreeCAD.Console.PrintMessage("skipping hatches...\n")
# drawing blocks
inserts = drawing.entities.get_type("insert")
if not fmt.paramstarblocks:
FreeCAD.Console.PrintMessage("skipping *blocks...\n")
@ -933,18 +1112,21 @@ def processdxf(document,filename):
blockrefs = drawing.blocks.data
for ref in blockrefs:
drawBlock(ref)
num = 0
for insert in inserts:
shape = drawInsert(insert)
shape = drawInsert(insert,num)
if shape:
if fmt.makeBlocks:
addToBlock(shape,block.layer)
addToBlock(shape,insert.layer)
else:
newob = addObject(shape,"Block."+insert.block,insert.layer)
if gui: fmt.formatObject(newob,insert)
num += 1
# make blocks, if any
if fmt.makeBlocks:
print "creating layerblocks..."
for k,l in layerBlocks.iteritems():
shape = drawLayerBlock(l)
if shape:
@ -953,6 +1135,8 @@ def processdxf(document,filename):
# finishing
print "done processing"
doc.recompute()
FreeCAD.Console.PrintMessage("successfully imported "+filename+"\n")
if badobjects: print "dxf: ",len(badobjects)," objects were not imported"
@ -960,9 +1144,9 @@ def processdxf(document,filename):
del doc
del blockshapes
def warn(dxfobject):
def warn(dxfobject,num=None):
"outputs a warning if a dxf object couldn't be imported"
print "dxf: couldn't import ", dxfobject
print "dxf: couldn't import ", dxfobject, " (",num,")"
badobjects.append(dxfobject)
def open(filename):

View File

@ -36,7 +36,7 @@ currently unsupported: use, image
# debug Problem with 'Sans' font from Inkscape
# debug Problem with fill color
# implement inherting fill style from group
# handle viewbox and units
# handle relative units
import xml.sax, string, FreeCAD, os, math, re, Draft
from draftlibs import fcvec
@ -216,10 +216,50 @@ def getcolor(color):
b = float(v[2]/255.0)
return (r,g,b,0.0)
def getsize(length):
"""extracts a number from the given string (removes unit suffixes)"""
def getsize(length,mode='discard',base=None):
"""parses length values containing number and unit
with mode 'discard': extracts a number from the given string (removes unit suffixes)
with mode 'tuple': return number and unit as a tuple
with mode 'css': convert the unit to px assuming 90dpi
with mode 'mm': convert the unit to millimeter assuming 90dpi"""
tomm={
'' : 25.4/90, #default
'px' : 25.4/90,
'pt' : 1.25*25.4/90,
'pc' : 15*25.4/90,
'mm' : 1.0,
'cm' : 10.0,
'in' : 25.4,
'em': 15*2.54/90, #arbitrarily chosen; has to depend on font size
'ex': 10*2.54/90, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on vieport size or (for filling patterns) on bounding box
}
topx={
'' : 1.0, #default
'px' : 1.0,
'pt' : 1.25,
'pc' : 15,
'mm' : 90.0/25.4,
'cm' : 90.0/254.0,
'in' : 90,
'em': 15, #arbitrarily chosen; has to depend on font size
'ex': 10, #arbitrarily chosen; has to depend on font size
'%': 100 #arbitrarily chosen; has to depend on vieport size or (for filling patterns) on bounding box
}
number, exponent, unit=re.findall('([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)(px|pt|pc|mm|cm|in|em|ex|%)?',length)[0]
return float(number)
if mode =='discard':
return float(number)
elif mode == 'tuple':
return float(number),unit
elif mode == 'mm':
return float(number)*tomm[unit]
elif mode == 'css':
if unit != '%':
return float(number)*topx[unit]
else:
return float(number)*(base or 1)
def makewire(path,checkclosed=False,donttry=False):
'''try to make a wire out of the list of edges. If the 'Wire' functions fails or the wire is not
@ -281,7 +321,7 @@ def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False):
try:
scalefacpos = math.sqrt(numer/denom)
except ValueError:
print 'sqrt(%f/%f)' % (numer,denom)
FreeCAD.Console.PrintMessage('sqrt(%f/%f)\n' % (numer,denom))
scalefacpos = 0
for scalefacsign in (1,-1):
scalefac = scalefacpos * scalefacsign
@ -318,6 +358,7 @@ class svgHandler(xml.sax.ContentHandler):
self.transform = None
self.grouptransform = []
self.lastdim = None
self.viewbox = None
global Part
import Part
@ -349,8 +390,8 @@ class svgHandler(xml.sax.ContentHandler):
self.count += 1
print "processing element ",self.count,": ",name
print "existing group transform: ", self.grouptransform
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():
@ -370,7 +411,7 @@ class svgHandler(xml.sax.ContentHandler):
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])
data[k] = getsize(data[k][0],'css')
for k in ['fill','stroke','stroke-width','font-size']:
if k in data:
@ -384,6 +425,29 @@ class svgHandler(xml.sax.ContentHandler):
self.width = None
self.text = None
if name == 'svg':
m=FreeCAD.Matrix()
if 'width' in data and 'height' in data and \
'viewBox' in data:
x0,y0,x1,y1=[float(n) for n in data['viewBox']]
vbw = x1-x0
vbh = y1-y0
self.viewbox=(vbw,vbh)
abw = getsize(attrs.getValue('width'),'mm')
abh = getsize(attrs.getValue('height'),'mm')
sx=abw/vbw
sy=abh/vbh
m.scale(Vector(sx,sy,1))
if round(sx/sy,5) != 1:
FreeCAD.Console.PrintWarning('Scaling Factors do not match!!!\n')
#FreeCAD.Console.PrintMessage('attrs: %s %s\n'%(attrs.getValue('width'),attrs.getValue('height')))
#FreeCAD.Console.PrintMessage('vb: %f %f %f %f\n'%(x0,y0,x1,y1))
#FreeCAD.Console.PrintMessage('absolute: %f %f\n'%(abw,abh))
else:
#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'])
@ -392,7 +456,7 @@ class svgHandler(xml.sax.ContentHandler):
self.color = getcolor(data['stroke'])
if 'stroke-width' in data:
if data['stroke-width'] != 'none':
self.width = getsize(data['stroke-width'])
self.width = getsize(data['stroke-width'],'css')
if 'transform' in data:
m = self.getMatrix(attrs.getValue('transform'))
if name == "g":
@ -410,12 +474,12 @@ class svgHandler(xml.sax.ContentHandler):
pathname = None
if 'id' in data:
pathname = data['id'][0]
print "name: ",pathname
FreeCAD.Console.PrintMessage('name: %s\n'%pathname)
# processing paths
if name == "path":
print data
FreeCAD.Console.PrintMessage('data: %s\n'%str(data))
if not pathname: pathname = 'Path'
@ -462,7 +526,7 @@ class svgHandler(xml.sax.ContentHandler):
else:
lastvec = Vector(x,-y,0)
firstvec = lastvec
print "move ",lastvec
FreeCAD.Console.PrintMessage('move %s\n'%str(lastvec))
lastpole = None
if (d == "L" or d == "l") or \
((d == 'm' or d == 'M') and pointlist) :
@ -473,7 +537,7 @@ class svgHandler(xml.sax.ContentHandler):
currentvec = Vector(x,-y,0)
if not fcvec.equals(lastvec,currentvec):
seg = Part.Line(lastvec,currentvec).toShape()
print "line ",lastvec,currentvec
FreeCAD.Console.PrintMessage("line %s %s\n" %(lastvec,currentvec))
lastvec = currentvec
path.append(seg)
lastpole = None
@ -482,8 +546,7 @@ class svgHandler(xml.sax.ContentHandler):
if relative:
currentvec = lastvec.add(Vector(x,0,0))
else:
lasty = path[-1].y
currentvec = Vector(x,lasty,0)
currentvec = Vector(x,lastvec.y,0)
seg = Part.Line(lastvec,currentvec).toShape()
lastvec = currentvec
lastpole = None
@ -493,8 +556,7 @@ class svgHandler(xml.sax.ContentHandler):
if relative:
currentvec = lastvec.add(Vector(0,-y,0))
else:
lastx = path[-1].x
currentvec = Vector(lastx,-y,0)
currentvec = Vector(lastvec.x,-y,0)
seg = Part.Line(lastvec,currentvec).toShape()
lastvec = currentvec
lastpole = None
@ -529,14 +591,14 @@ class svgHandler(xml.sax.ContentHandler):
solution,(rx,ry) = arcend2center(lastvec,currentvec,rx,ry,math.radians(-xrotation),True)
negsol = (largeflag != sweepflag)
vcenter,angle1,angledelta = solution[negsol]
print angle1
print angledelta
#print angle1
#print angledelta
if ry > rx:
rx,ry=ry,rx
swapaxis = True
else:
swapaxis = False
print 'Elliptical arc %s rx=%f ry=%f' % (vcenter,rx,ry)
#print 'Elliptical arc %s rx=%f ry=%f' % (vcenter,rx,ry)
e1 = Part.Ellipse(vcenter,rx,ry)
if sweepflag:
#angledelta=-(-angledelta % (math.pi *2)) # Step4
@ -595,18 +657,18 @@ class svgHandler(xml.sax.ContentHandler):
mainv = currentvec.sub(lastvec)
pole1v = lastvec.add(pole1)
pole2v = currentvec.add(pole2)
print "cubic curve data:",mainv.normalize(),pole1v.normalize(),pole2v.normalize()
#print "cubic curve data:",mainv.normalize(),pole1v.normalize(),pole2v.normalize()
if True and \
pole1.distanceToLine(lastvec,currentvec) < 10**(-1*(2+Draft.precision())) and \
pole2.distanceToLine(lastvec,currentvec) < 10**(-1*(2+Draft.precision())):
print "straight segment"
#print "straight segment"
seg = Part.Line(lastvec,currentvec).toShape()
else:
print "cubic bezier segment"
#print "cubic bezier segment"
b = Part.BezierCurve()
b.setPoles([lastvec,pole1,pole2,currentvec])
seg = b.toShape()
print "connect ",lastvec,currentvec
#print "connect ",lastvec,currentvec
lastvec = currentvec
lastpole = ('cubic',pole2)
path.append(seg)
@ -636,14 +698,14 @@ class svgHandler(xml.sax.ContentHandler):
if not fcvec.equals(currentvec,lastvec):
if True and \
pole.distanceToLine(lastvec,currentvec) < 20**(-1*(2+Draft.precision())):
print "straight segment"
#print "straight segment"
seg = Part.Line(lastvec,currentvec).toShape()
else:
print "quadratic bezier segment"
#print "quadratic bezier segment"
b = Part.BezierCurve()
b.setPoles([lastvec,pole,currentvec])
seg = b.toShape()
print "connect ",lastvec,currentvec
#print "connect ",lastvec,currentvec
lastvec = currentvec
lastpole = ('quadratic',pole)
path.append(seg)
@ -765,7 +827,7 @@ class svgHandler(xml.sax.ContentHandler):
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']]
print 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)
@ -776,7 +838,7 @@ class svgHandler(xml.sax.ContentHandler):
currentvec = Vector(svgx,-svgy,0)
if not fcvec.equals(lastvec,currentvec):
seg = Part.Line(lastvec,currentvec).toShape()
print "polyline seg ",lastvec,currentvec
#print "polyline seg ",lastvec,currentvec
lastvec = currentvec
path.append(seg)
if path:
@ -793,11 +855,19 @@ class svgHandler(xml.sax.ContentHandler):
c = Vector(data.get('cx',0),-data.get('cy',0),0)
rx = data['rx']
ry = data['ry']
sh = Part.Ellipse(c,rx,ry).toShape() #needs a proxy object
if rx > ry:
sh = Part.Ellipse(c,rx,ry).toShape()
else:
sh = Part.Ellipse(c,ry,rx).toShape()
m3=FreeCAD.Matrix()
m3.move(c)
rot90=FreeCAD.Matrix(0,-1,0,0,1,0) #90
m3=m3.multiply(rot90)
m3.move(c.multiply(-1))
sh.transform(m3)
if self.fill:
sh = Part.Wire([sh])
sh = Part.Face(sh)
sh.translate(c)
sh = self.applyTrans(sh)
obj = self.doc.addObject("Part::Feature",pathname)
obj.Shape = sh
@ -824,7 +894,7 @@ class svgHandler(xml.sax.ContentHandler):
if name in ["text","tspan"]:
if not("freecad:skip" in data):
print "processing a text"
FreeCAD.Console.PrintMessage("processing a text\n")
if 'x' in data:
self.x = data['x']
else:
@ -835,28 +905,28 @@ class svgHandler(xml.sax.ContentHandler):
self.y = 0
if 'font-size' in data:
if data['font-size'] != 'none':
self.text = getsize(data['font-size'])
self.text = getsize(data['font-size'],'css')
else:
self.text = 1
else:
if self.lastdim:
self.lastdim.ViewObject.FontSize = int(getsize(data['font-size']))
print "done processing element ",self.count
FreeCAD.Console.PrintMessage("done processing element %d\n"%self.count)
def characters(self,content):
if self.text:
print "reading characters", str(content)
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)
if self.transform:
vec = self.translateVec(vec,self.transform)
print "own transform: ",self.transform, vec
#print "own transform: ",self.transform, vec
for transform in self.grouptransform[::-1]:
#vec = self.translateVec(vec,transform)
vec = transform.multiply(vec)
print "applying vector: ",vec
#print "applying vector: ",vec
obj.Position = vec
if gui:
obj.ViewObject.FontSize = int(self.text)
@ -867,17 +937,17 @@ class svgHandler(xml.sax.ContentHandler):
if not name in ["tspan"]:
self.transform = None
self.text = None
if name == "g":
print "closing group"
if name == "g" or name == "svg":
FreeCAD.Console.PrintMessage("closing group\n")
self.grouptransform.pop()
def applyTrans(self,sh):
if isinstance(sh,Part.Shape):
if self.transform:
print "applying object transform: ",self.transform
FreeCAD.Console.PrintMessage("applying object transform: %s\n" % self.transform)
sh = sh.transformGeometry(self.transform)
for transform in self.grouptransform[::-1]:
print "applying group transform: ", transform
FreeCAD.Console.PrintMessage("applying group transform: %s\n" % transform)
sh = sh.transformGeometry(transform)
return sh
elif Draft.getType(sh) == "Dimension":
@ -885,10 +955,10 @@ class svgHandler(xml.sax.ContentHandler):
for p in [sh.Start,sh.End,sh.Dimline]:
cp = Vector(p)
if self.transform:
print "applying object transform: ",self.transform
FreeCAD.Console.PrintMessage("applying object transform: %s\n" % self.transform)
cp = self.transform.multiply(cp)
for transform in self.grouptransform[::-1]:
print "applying group transform: ",transform
FreeCAD.Console.PrintMessage("applying group transform: %s\n" % transform)
cp = transform.multiply(cp)
pts.append(cp)
sh.Start = pts[0]
@ -906,7 +976,7 @@ class svgHandler(xml.sax.ContentHandler):
for transformation, arguments in transformre.findall(tr):
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))
#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
@ -936,10 +1006,10 @@ class svgHandler(xml.sax.ContentHandler):
# (+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]))
else:
print 'SKIPPED %s' % transformation
print "m= ",m
print "generating transformation: ",m
#else:
#print 'SKIPPED %s' % transformation
#print "m= ",m
#print "generating transformation: ",m
return m
def decodeName(name):
@ -950,7 +1020,8 @@ def decodeName(name):
try:
decodedName = (name.decode("latin1"))
except UnicodeDecodeError:
print "svg: error: couldn't determine character encoding"
FreeCAD.Console.PrintError("svg: error: couldn't determine character encoding\n")
decodedName = name
return decodedName
@ -1005,7 +1076,7 @@ def export(exportList,filename):
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:
print "unknown svg export style, switching to Translated"
FreeCAD.Console.PrintMessage("unknown svg export style, switching to Translated\n")
svg_export_style = 0
# finding sheet size

View File

@ -69,9 +69,21 @@ ENDIF(MSVC)
add_library(Drawing SHARED ${Drawing_SRCS} ${Features_SRCS} ${DrawingAlgos_SRCS})
target_link_libraries(Drawing ${Drawing_LIBS})
fc_copy_script("Mod/Drawing" "Drawing" Init.py)
fc_copy_script("Mod/Drawing" "Drawing" DrawingAlgos.py)
fc_copy_script("Mod/Drawing" "Drawing" ${Drawing_Templates})
SET(Drawing_Scripts
Init.py
DrawingAlgos.py
)
fc_target_copy_resource(Drawing
${CMAKE_SOURCE_DIR}/src/Mod/Drawing
${CMAKE_BINARY_DIR}/Mod/Drawing
${Drawing_Scripts})
fc_target_copy_resource(Drawing
${CMAKE_SOURCE_DIR}/src/Mod/Drawing
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Drawing
${Drawing_Templates})
if(MSVC)
set_target_properties(Drawing PROPERTIES SUFFIX ".pyd")

View File

@ -88,7 +88,12 @@ endif(MSVC)
add_library(DrawingGui SHARED ${DrawingGui_SRCS} ${DrawingGuiView_SRCS} ${DrawingGuiViewProvider_SRCS})
target_link_libraries(DrawingGui ${DrawingGui_LIBS})
fc_copy_script("Mod/Drawing" "DrawingGui" InitGui.py)
fc_target_copy_resource(DrawingGui
${CMAKE_SOURCE_DIR}/src/Mod/Drawing
${CMAKE_BINARY_DIR}/Mod/Drawing
InitGui.py)
if(MSVC)
set_target_properties(DrawingGui PROPERTIES SUFFIX ".pyd")

File diff suppressed because it is too large Load Diff

View File

@ -86,8 +86,7 @@ public:
protected Q_SLOTS:
void setPrimary(int);
void setRotate(int);
void setSecondary_1(int);
void setSecondary_2(int);
void cb_toggled(bool);
void projectionChanged(int);
void hidden(int);
void smooth(int);
@ -99,25 +98,37 @@ protected:
private:
void pagesize(std::string&);
void autodims();
void compute();
void autodims(float, float, float, float);
void populate_s1();
void populate_s2();
void validate_cbs();
void view_data(int, int, int &, int &);
void updateSecondaries();
private:
class Private;
Ui_TaskOrthoViews * ui;
orthoView * views[3];
int transform[7][7][3]; //matrix containing relative positions and rotations of secondary views depending upon primary view
orthoView * views[4];
QCheckBox * c_boxes[5][5]; //matrix of pointers to gui checkboxes
QLineEdit * inputs[5]; //pointers to manual position/scale boxes
float * data[5]; //pointers to scale, x_pos, y_pos, horiz, vert
int map1[4][3][2]; //contains view directions and rotations for vertical secondary positions, for primaries 1,2,3,4
int map2[4][3][2]; //contains view directions and rotations for H and V secondary positions, primaries 5,6
int view_status[4][4]; //matrix containing status of four orthoView objects (in use, axo, rel x, rel y)
int view_count; //number of active views
int primary; //view direction of primary view
int secondary_1, secondary_2; //view direction of secondary views
int spacing_1, spacing_2; //spacings of secondary view centre from primary view centre
float x_pos, y_pos; //x and y coords for primary view
int rotate; //rotate primary view clockwise by rotate*90
int proj; //first (=-1) or third (=1) angle projection
float scale; //scale of drawing
bool autoscale; //whether or not to run autodims
int pagewidth, pageh1, pageh2; //these are actually the available width and height, calculated in constructor.
float horiz, vert; //centre-centre distances
float pagewidth, pageheight; //these are actually the available width and height, calculated in constructor.
float pageh1, pageh2; //h1 - total usable page height, h2 - total height allowing for info box.
int margin;
int min_space; //minimum space between views, and page edge
};

View File

@ -6,21 +6,30 @@
<rect>
<x>0</x>
<y>0</y>
<width>272</width>
<height>394</height>
<width>250</width>
<height>491</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Orthographic Projection</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<property name="margin">
<number>4</number>
</property>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_7">
@ -48,7 +57,523 @@
</item>
</layout>
</item>
<item>
<item row="3" column="1">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="1">
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="QCheckBox" name="cb12">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="cb13">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="cb23">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QCheckBox" name="cb33">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="cb11">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QCheckBox" name="cb31">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="cb21">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QCheckBox" name="cb32">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="cb24">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="cb20">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QCheckBox" name="cb42">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="cb22">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Primary view</string>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Secondary Views</string>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="cb02">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="1">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>90</width>
<height>230</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>General</string>
</attribute>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>7</y>
<width>231</width>
<height>191</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="auto_tog">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Auto scale / position</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QLabel" name="label_4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Scale</string>
</property>
<property name="margin">
<number>2</number>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Primary x / y</string>
</property>
<property name="margin">
<number>2</number>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Secondary dx / dy</string>
</property>
<property name="margin">
<number>2</number>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QLineEdit" name="scale_0">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="0,0">
<item>
<widget class="QLineEdit" name="x_1">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="y_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="spacing_h_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="spacing_v_4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="hidden">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Show hidden</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="smooth">
<property name="text">
<string>Show smooth</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Axonometric</string>
</attribute>
</widget>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_8">
@ -93,12 +618,12 @@
</item>
<item>
<property name="text">
<string>Back</string>
<string>Right</string>
</property>
</item>
<item>
<property name="text">
<string>Right</string>
<string>Back</string>
</property>
</item>
<item>
@ -146,232 +671,6 @@
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Secondary views</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="secondary_1">
<item>
<property name="text">
<string/>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="secondary_2">
<item>
<property name="text">
<string/>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QCheckBox" name="auto_tog">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Auto scale / position</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QLabel" name="label_4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Scale</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Primary x / y</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Secondary spacings</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QLineEdit" name="scale">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="1,1">
<item>
<widget class="QLineEdit" name="x">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="y">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLineEdit" name="spacing1">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="spacing2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="hidden">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Show hidden</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="smooth">
<property name="text">
<string>Show smooth</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@ -580,6 +580,7 @@
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:current-layer="svg2"
inkscape:document-units="mm"
showgrid="false"
inkscape:window-maximized="1" />
<g

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:freecad="http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Svg_Namespace"
width="420mm"
height="297mm"
viewBox="0 0 420 297"
id="svg5211"
version="1.1"
inkscape:version="0.48.1 "
sodipodi:docname="iso7200-a4-portrait">
<defs
id="defs5213" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="10"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1280"
inkscape:window-height="962"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5216">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1">
<rect id="zeichenrahmen" y="10" x="20"
height="277"
width="390"
style="fill:none;stroke:#000000;stroke-width:0.35;stroke-linecap:miter;stroke-miterlimit:4" />
<!-- width-30, height-20 -->
<g id="schriftfeld"
transform="translate(210,0)">
<!-- A4 Portrait based for other formats width-210, height-297 -->
<!-- page rect translation
w h rw rh tx ty
A4-P 210 297 180 277 0 0
A4-L 297 210 267 190 87 -87
A3-L 420 297 390 277 210 0
A2-L 594 420 564 400 384 123
A1-L 841 594 811 574 631 297
A0-L 1189 841 1159 821 979 544
-->
<g id="schriftfeldrahmen"
style="fill:none;stroke:#000000;stroke-width:0.35;stroke-linecap:miter;stroke-miterlimit:4">
<rect id="schriftfeld-aussen"
width="180" height="36" x="20" y="251" />
<path id="schriftfeld-h1" d="M 20,260 H 200" />
<path d="M 89,269 H 200" id="schriftfeld-h2" />
<path id="schriftfeld-h3" d="m 149,278 h 51" />
<path id="schriftfeld-v1" d="m 89,251 v 36" />
<path d="m 45,251 v 9" id="schriftfeld-v2" />
<path id="schriftfeld-v3" d="m 132,251 v 9" />
<path d="m 175,251 v 9" id="schriftfeld-v4" />
<path id="schriftfeld-v5" d="m 89,251 v 36" />
<path d="m 149,260 v 27" id="schriftfeld-v6" />
<path id="schriftfeld-v7" d="m 156,278 v 9" />
<path d="m 181,278 v 9" id="schriftfeld-v8" />
<path id="schriftfeld-v9" d="m 191,278 v 9" />
</g>
<g id="schriftfeldtext2"
style="font-size:2;font-style:normal;font-weight:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:sans"
xml:space="preserve">
<text
xml:space="preserve"
x="20" y="251" id="textdesc"
sodipodi:linespacing="125%"><tspan
id="tspan5781" y="253" x="21">Responsible department</tspan><tspan
id="tspan5783" x="46" y="253">Technical reference</tspan><tspan
y="253" x="90" id="tspan5785">Created by</tspan><tspan
id="tspan5787" x="133" y="253">Approved by</tspan><tspan
y="253" x="176" id="tspan5789">Classification/key words</tspan><tspan
x="21" y="262" id="tspan5791">Legal owner</tspan><tspan
id="tspan5793" y="262" x="90">Document type</tspan><tspan
x="150" y="262" id="tspan5795">Document status</tspan><tspan
x="90" y="271" id="tspan5797">Title, Supplementary title</tspan><tspan
id="tspan5799" y="271" x="150">Identification number</tspan><tspan
x="150" y="280" id="tspan5801">Rev.</tspan><tspan
id="tspan5803" y="280" x="157">Date of issue</tspan><tspan
x="182" y="280" id="tspan5805">Language</tspan><tspan
id="tspan5807" y="280" x="192">Seg./Sh.</tspan></text>
</g>
<g id="schriftfeldtext4"
style="font-size:4;font-style:normal;font-weight:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:sans"
xml:space="preserve">
<text freecad:EditableText="Creator" x="90" y="258">
<tspan id="tspan5815" x="90" y="258">me</tspan> </text>
<text freecad:EditableText="ApprovalPerson" y="258" x="133">
<tspan y="258" x="133" id="tspan5817">myself</tspan> </text>
<text freecad:EditableText="LegalOwner" y="267" x="21">
<tspan id="tspan5821" y="267" x="21">my company</tspan> </text>
<text freecad:EditableText="DocumentType" x="90" y="267">
<tspan x="90" y="267" id="tspan5823">type</tspan></text>
<text freecad:EditableText="Title" y="276" x="90">
<tspan id="tspan5827" y="276" x="90">title</tspan></text>
<text freecad:EditableText="IdNumber" x="150" y="276">
<tspan x="150" y="276" id="tspan5829">0001</tspan></text>
<text freecad:EditableText="Date" x="157" y="285">
<tspan x="157" y="285" id="tspan5833">2000-00-00</tspan></text>
<text freecad:EditableText="OptResponsibleDept" y="258" x="21">
<tspan y="258" x="21"></tspan></text>
<text freecad:EditableText="OptTechnicalRef" x="46" y="258">
<tspan x="46" y="258"></tspan></text>
<text freecad:EditableText="Classification" y="258" x="176">
<tspan y="258" x="176"></tspan></text>
<text freecad:EditableText="OptDocumentStatus" x="150" y="267">
<tspan x="150" y="267"></tspan></text>
<text freecad:EditableText="OptRevison" x="150" y="285">
<tspan x="150" y="285"></tspan></text>
<text freecad:EditableText="OptLanguage" x="182" y="285">
<tspan x="182" y="285"></tspan></text>
<text freecad:EditableText="SegmentsOrSheets" y="285" x="192">
<tspan y="285" x="192"></tspan></text>
<text freecad:EditableText="OptSupTitle" y="281" x="90">
<tspan id="tspan5827" y="281" x="90"></tspan></text>
<text freecad:EditableText="OptSupTitle2" y="285" x="90">
<tspan id="tspan5827" y="285" x="90"></tspan></text>
</g>
</g>
<!-- DrawingContent -->
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -907,6 +907,7 @@
inkscape:window-x="0"
inkscape:window-y="22"
inkscape:current-layer="svg2"
inkscape:document-units="mm"
showgrid="false"
units="px"
inkscape:window-maximized="1" />

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:freecad="http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=Svg_Namespace"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
id="svg5211"
version="1.1"
inkscape:version="0.48.1 "
sodipodi:docname="iso7200-a4-portrait">
<defs
id="defs5213" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="10"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1280"
inkscape:window-height="962"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5216">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1">
<rect id="zeichenrahmen" y="10" x="20"
height="277"
width="180"
style="fill:none;stroke:#000000;stroke-width:0.35;stroke-linecap:miter;stroke-miterlimit:4" />
<!-- width-30, height-20 -->
<g id="schriftfeld"
transform="translate(0,0)">
<!-- A4 Portrait based for other formats width-210, height-297 -->
<!-- page rect translation
w h rw rh tx ty
A4-P 210 297 180 277 0 0
A4-L 297 210 267 190 87 -87
A3-L 420 297 390 277 210 0
A2-L 594 420 564 400 384 123
A1-L 841 594 811 574 631 297
A0-L 1189 841 1159 821 979 544
-->
<g id="schriftfeldrahmen"
style="fill:none;stroke:#000000;stroke-width:0.35;stroke-linecap:miter;stroke-miterlimit:4">
<rect id="schriftfeld-aussen"
width="180" height="36" x="20" y="251" />
<path id="schriftfeld-h1" d="M 20,260 H 200" />
<path d="M 89,269 H 200" id="schriftfeld-h2" />
<path id="schriftfeld-h3" d="m 149,278 h 51" />
<path id="schriftfeld-v1" d="m 89,251 v 36" />
<path d="m 45,251 v 9" id="schriftfeld-v2" />
<path id="schriftfeld-v3" d="m 132,251 v 9" />
<path d="m 175,251 v 9" id="schriftfeld-v4" />
<path id="schriftfeld-v5" d="m 89,251 v 36" />
<path d="m 149,260 v 27" id="schriftfeld-v6" />
<path id="schriftfeld-v7" d="m 156,278 v 9" />
<path d="m 181,278 v 9" id="schriftfeld-v8" />
<path id="schriftfeld-v9" d="m 191,278 v 9" />
</g>
<g id="schriftfeldtext2"
style="font-size:2;font-style:normal;font-weight:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:sans"
xml:space="preserve">
<text
xml:space="preserve"
x="20" y="251" id="textdesc"
sodipodi:linespacing="125%"><tspan
id="tspan5781" y="253" x="21">Responsible department</tspan><tspan
id="tspan5783" x="46" y="253">Technical reference</tspan><tspan
y="253" x="90" id="tspan5785">Created by</tspan><tspan
id="tspan5787" x="133" y="253">Approved by</tspan><tspan
y="253" x="176" id="tspan5789">Classification/key words</tspan><tspan
x="21" y="262" id="tspan5791">Legal owner</tspan><tspan
id="tspan5793" y="262" x="90">Document type</tspan><tspan
x="150" y="262" id="tspan5795">Document status</tspan><tspan
x="90" y="271" id="tspan5797">Title, Supplementary title</tspan><tspan
id="tspan5799" y="271" x="150">Identification number</tspan><tspan
x="150" y="280" id="tspan5801">Rev.</tspan><tspan
id="tspan5803" y="280" x="157">Date of issue</tspan><tspan
x="182" y="280" id="tspan5805">Language</tspan><tspan
id="tspan5807" y="280" x="192">Seg./Sh.</tspan></text>
</g>
<g id="schriftfeldtext4"
style="font-size:4;font-style:normal;font-weight:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:sans"
xml:space="preserve">
<text freecad:EditableText="Creator" x="90" y="258">
<tspan id="tspan5815" x="90" y="258">me</tspan> </text>
<text freecad:EditableText="ApprovalPerson" y="258" x="133">
<tspan y="258" x="133" id="tspan5817">myself</tspan> </text>
<text freecad:EditableText="LegalOwner" y="267" x="21">
<tspan id="tspan5821" y="267" x="21">my company</tspan> </text>
<text freecad:EditableText="DocumentType" x="90" y="267">
<tspan x="90" y="267" id="tspan5823">type</tspan></text>
<text freecad:EditableText="Title" y="276" x="90">
<tspan id="tspan5827" y="276" x="90">title</tspan></text>
<text freecad:EditableText="IdNumber" x="150" y="276">
<tspan x="150" y="276" id="tspan5829">0001</tspan></text>
<text freecad:EditableText="Date" x="157" y="285">
<tspan x="157" y="285" id="tspan5833">2000-00-00</tspan></text>
<text freecad:EditableText="OptResponsibleDept" y="258" x="21">
<tspan y="258" x="21"></tspan></text>
<text freecad:EditableText="OptTechnicalRef" x="46" y="258">
<tspan x="46" y="258"></tspan></text>
<text freecad:EditableText="Classification" y="258" x="176">
<tspan y="258" x="176"></tspan></text>
<text freecad:EditableText="OptDocumentStatus" x="150" y="267">
<tspan x="150" y="267"></tspan></text>
<text freecad:EditableText="OptRevison" x="150" y="285">
<tspan x="150" y="285"></tspan></text>
<text freecad:EditableText="OptLanguage" x="182" y="285">
<tspan x="182" y="285"></tspan></text>
<text freecad:EditableText="SegmentsOrSheets" y="285" x="192">
<tspan y="285" x="192"></tspan></text>
<text freecad:EditableText="OptSupTitle" y="281" x="90">
<tspan id="tspan5827" y="281" x="90"></tspan></text>
<text freecad:EditableText="OptSupTitle2" y="285" x="90">
<tspan id="tspan5827" y="285" x="90"></tspan></text>
</g>
</g>
<!-- DrawingContent -->
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -64,7 +64,12 @@ SOURCE_GROUP("Module" FILES ${Mod_SRCS})
add_library(Fem SHARED ${Fem_SRCS})
target_link_libraries(Fem ${Fem_LIBS})
fc_copy_script("Mod/Fem" "Fem" Init.py convert2TetGen.py)
fc_target_copy_resource(Fem
${CMAKE_SOURCE_DIR}/src/Mod/Fem
${CMAKE_BINARY_DIR}/Mod/Fem
Init.py convert2TetGen.py)
if(MSVC)
set_target_properties(Fem PROPERTIES SUFFIX ".pyd")

View File

@ -51,7 +51,12 @@ SET(FemGui_SRCS
add_library(FemGui SHARED ${FemGui_SRCS})
target_link_libraries(FemGui ${FemGui_LIBS})
fc_copy_script("Mod/Fem" "FemGui" InitGui.py)
fc_target_copy_resource(FemGui
${CMAKE_SOURCE_DIR}/src/Mod/Fem
${CMAKE_BINARY_DIR}/Mod/Fem
InitGui.py)
if(MSVC)
set_target_properties(FemGui PROPERTIES SUFFIX ".pyd")

View File

@ -49,7 +49,7 @@ ADD_CUSTOM_TARGET(Idf ALL
SOURCES ${all_files}
)
fc_copy_sources("Mod/Idf" "Idf" ${all_files})
fc_copy_sources(Idf "${CMAKE_BINARY_DIR}/Mod/Idf" ${all_files})
INSTALL(
FILES

View File

@ -29,7 +29,12 @@ set(Image_SRCS
add_library(Image SHARED ${Image_SRCS})
target_link_libraries(Image ${Image_LIBS})
fc_copy_script("Mod/Image" "Image" Init.py)
fc_target_copy_resource(Image
${CMAKE_SOURCE_DIR}/src/Mod/Image
${CMAKE_BINARY_DIR}/Mod/Image
Init.py)
if(MSVC)
set_target_properties(Image PROPERTIES SUFFIX ".pyd")

View File

@ -54,7 +54,12 @@ SET(ImageGui_SRCS
add_library(ImageGui SHARED ${ImageGui_SRCS})
target_link_libraries(ImageGui ${ImageGui_LIBS})
fc_copy_script("Mod/Image" "ImageGui" InitGui.py)
fc_target_copy_resource(ImageGui
${CMAKE_SOURCE_DIR}/src/Mod/Image
${CMAKE_BINARY_DIR}/Mod/Image
InitGui.py)
if(MSVC)
set_target_properties(ImageGui PROPERTIES SUFFIX ".pyd")

View File

@ -40,8 +40,12 @@ SET(ImportGui_SRCS
add_library(ImportGui SHARED ${ImportGui_SRCS})
target_link_libraries(ImportGui ${ImportGui_LIBS})
fc_copy_script("Mod/Import" "ImportGui" Init.py)
fc_copy_script("Mod/Import" "ImportGui" InitGui.py)
fc_target_copy_resource(ImportGui
${CMAKE_SOURCE_DIR}/src/Mod/Import
${CMAKE_BINARY_DIR}/Mod/Import
Init.py InitGui.py)
if(MSVC)
set_target_properties(ImportGui PROPERTIES SUFFIX ".pyd")

View File

@ -35,7 +35,12 @@ SET(Inspection_SRCS
add_library(Inspection SHARED ${Inspection_SRCS})
target_link_libraries(Inspection ${Inspection_LIBS})
fc_copy_script("Mod/Inspection" "Inspection" Init.py)
fc_target_copy_resource(Inspection
${CMAKE_SOURCE_DIR}/src/Mod/Inspection
${CMAKE_BINARY_DIR}/Mod/Inspection
Init.py)
if(MSVC)
set_target_properties(Inspection PROPERTIES SUFFIX ".pyd")

View File

@ -52,7 +52,12 @@ SET(InspectionGui_SRCS
add_library(InspectionGui SHARED ${InspectionGui_SRCS})
target_link_libraries(InspectionGui ${InspectionGui_LIBS})
fc_copy_script("Mod/Inspection" "InspectionGui" InitGui.py)
fc_target_copy_resource(InspectionGui
${CMAKE_SOURCE_DIR}/src/Mod/Inspection
${CMAKE_BINARY_DIR}/Mod/Inspection
InitGui.py)
if(MSVC)
set_target_properties(InspectionGui PROPERTIES SUFFIX ".pyd")

View File

@ -15,11 +15,11 @@ SET(MachDist_SRCS
SOURCE_GROUP("" FILES ${MachDist_SRCS})
ADD_CUSTOM_TARGET(MachDistortion ALL
ADD_CUSTOM_TARGET( ALL
SOURCES ${MachDist_SRCS}
)
fc_copy_sources("Mod/Machining_Distortion" ${MachDist_SRCS})
fc_copy_sources(MachDistortion "${CMAKE_BINARY_DIR}/Mod/Machining_Distortion" ${MachDist_SRCS})
INSTALL(

View File

@ -165,10 +165,12 @@ static PyObject * exporter(PyObject *self, PyObject *args)
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
if (obj->getTypeId().isDerivedFrom(meshId)) {
const MeshObject& mesh = static_cast<Mesh::Feature*>(obj)->Mesh.getValue();
MeshCore::MeshKernel kernel = mesh.getKernel();
kernel.Transform(mesh.getTransform());
if (global_mesh.countFacets() == 0)
global_mesh = mesh;
global_mesh.setKernel(kernel);
else
global_mesh.addMesh(mesh);
global_mesh.addMesh(kernel);
}
else if (obj->getTypeId().isDerivedFrom(partId)) {
App::Property* shape = obj->getPropertyByName("Shape");

View File

@ -71,6 +71,8 @@ SET(Core_SRCS
Core/TopoAlgorithm.h
Core/Triangulation.cpp
Core/Triangulation.h
Core/Trim.cpp
Core/Trim.h
Core/tritritest.h
Core/Visitor.cpp
Core/Visitor.h
@ -331,8 +333,16 @@ endif(MSVC)
add_library(Mesh SHARED ${Core_SRCS} ${WildMagic4_SRCS} ${Mesh_SRCS})
target_link_libraries(Mesh ${Mesh_LIBS})
fc_copy_script ("Mod/Mesh" "Mesh" Init.py BuildRegularGeoms.py)
fc_copy_sources("Mod/Mesh" "Mesh" MeshTestsApp.py)
fc_target_copy_resource(Mesh
${CMAKE_SOURCE_DIR}/src/Mod/Mesh
${CMAKE_BINARY_DIR}/Mod/Mesh
Init.py BuildRegularGeoms.py)
fc_target_copy_resource(Mesh
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_BINARY_DIR}/Mod/Mesh
MeshTestsApp.py)
if(MSVC)
set_target_properties(Mesh PROPERTIES SUFFIX ".pyd")

View File

@ -1603,40 +1603,36 @@ bool MeshAlgorithm::ConnectPolygons(std::list<std::vector<Base::Vector3f> > &clP
void MeshAlgorithm::GetFacetsFromPlane (const MeshFacetGrid &rclGrid, const Base::Vector3f& clNormal, float d, const Base::Vector3f &rclLeft,
const Base::Vector3f &rclRight, std::vector<unsigned long> &rclRes) const
{
std::vector<unsigned long> aulFacets;
std::vector<unsigned long> aulFacets;
Base::Vector3f clBase = d * clNormal;
Base::Vector3f clBase = d * clNormal;
Base::Vector3f clPtNormal(rclLeft - rclRight);
clPtNormal.Normalize();
Base::Vector3f clPtNormal(rclLeft - rclRight);
clPtNormal.Normalize();
// search grid
MeshGridIterator clGridIter(rclGrid);
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next())
{
// add facets from grid if the plane if cut the grid-voxel
if (clGridIter.GetBoundBox().IsCutPlane(clBase, clNormal) == true)
clGridIter.GetElements(aulFacets);
}
// testing facet against planes
for (std::vector<unsigned long>::iterator pI = aulFacets.begin(); pI != aulFacets.end(); pI++)
{
MeshGeomFacet clSFacet = _rclMesh.GetFacet(*pI);
if (clSFacet.IntersectWithPlane(clBase, clNormal) == true)
{
bool bInner = false;
for (int i = 0; (i < 3) && (bInner == false); i++)
{
Base::Vector3f clPt = clSFacet._aclPoints[i];
if ((clPt.DistanceToPlane(rclLeft, clPtNormal) <= 0.0f) && (clPt.DistanceToPlane(rclRight, clPtNormal) >= 0.0f))
bInner = true;
}
if (bInner == true)
rclRes.push_back(*pI);
// search grid
MeshGridIterator clGridIter(rclGrid);
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
// add facets from grid if the plane if cut the grid-voxel
if (clGridIter.GetBoundBox().IsCutPlane(clBase, clNormal) == true)
clGridIter.GetElements(aulFacets);
}
// testing facet against planes
for (std::vector<unsigned long>::iterator pI = aulFacets.begin(); pI != aulFacets.end(); ++pI) {
MeshGeomFacet clSFacet = _rclMesh.GetFacet(*pI);
if (clSFacet.IntersectWithPlane(clBase, clNormal) == true) {
bool bInner = false;
for (int i = 0; (i < 3) && (bInner == false); i++) {
Base::Vector3f clPt = clSFacet._aclPoints[i];
if ((clPt.DistanceToPlane(rclLeft, clPtNormal) <= 0.0f) && (clPt.DistanceToPlane(rclRight, clPtNormal) >= 0.0f))
bInner = true;
}
if (bInner == true)
rclRes.push_back(*pI);
}
}
}
}
void MeshAlgorithm::PointsFromFacetsIndices (const std::vector<unsigned long> &rvecIndices, std::vector<Base::Vector3f> &rvecPoints) const

View File

@ -380,6 +380,30 @@ bool MeshFixDuplicateFacets::Fixup()
// ----------------------------------------------------------------------
bool MeshEvalInternalFacets::Evaluate()
{
_indices.clear();
unsigned long uIndex=0;
const MeshFacetArray& rFaces = _rclMesh.GetFacets();
// get all facets
std::set<FaceIterator, MeshFacet_Less > aFaceSet;
MeshFacetArray::_TConstIterator first = rFaces.begin();
for (MeshFacetArray::_TConstIterator it = rFaces.begin(); it != rFaces.end(); ++it, uIndex++) {
std::pair<std::set<FaceIterator, MeshFacet_Less>::iterator, bool>
pI = aFaceSet.insert(it);
if (!pI.second) {
// collect both elements
_indices.push_back(*pI.first - first);
_indices.push_back(uIndex);
}
}
return _indices.empty();
}
// ----------------------------------------------------------------------
bool MeshEvalDegeneratedFacets::Evaluate()
{
MeshFacetIterator it(_rclMesh);

View File

@ -188,6 +188,35 @@ public:
bool Fixup ();
};
/**
* The MeshEvalInternalFacets class identifies internal facets of a volume mesh.
* @author Werner Mayer
*/
class MeshExport MeshEvalInternalFacets : public MeshEvaluation
{
public:
/**
* Construction.
*/
MeshEvalInternalFacets (const MeshKernel &rclM) : MeshEvaluation( rclM ) { }
/**
* Destruction.
*/
~MeshEvalInternalFacets () { }
/**
* Identifiy internal facets.
*/
bool Evaluate ();
/**
* Return the indices.
*/
const std::vector<unsigned long>& GetIndices() const
{ return _indices; }
private:
std::vector<unsigned long> _indices;
};
/**
* The MeshEvalDegeneratedFacets class searches for degenerated facets. A facet is degenerated either if its points
* are collinear, i.e. they lie on a line or two points are coincident. In the latter case these points are duplicated.

View File

@ -440,6 +440,7 @@ protected:
friend class MeshFixDegeneratedFacets;
friend class MeshFixDuplicatePoints;
friend class MeshBuilder;
friend class MeshTrimming;
};
inline MeshPoint MeshKernel::GetPoint (unsigned long ulIndex) const

View File

@ -0,0 +1,685 @@
/***************************************************************************
* Copyright (c) 2012 Imetric 3D GmbH *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#include <algorithm>
#include "Trim.h"
#include "Grid.h"
#include "Iterator.h"
#include <Base/Sequencer.h>
using namespace MeshCore;
MeshTrimming::MeshTrimming(MeshKernel &rclM, const Base::ViewProjMethod* pclProj,
const Base::Polygon2D& rclPoly)
: myMesh(rclM), myProj(pclProj), myPoly(rclPoly), myInner(true)
{
}
MeshTrimming::~MeshTrimming()
{
}
void MeshTrimming::SetInnerOrOuter(TMode tMode)
{
switch (tMode)
{
case INNER:
myInner = true;
break;
case OUTER:
myInner = false;
break;
}
}
void MeshTrimming::CheckFacets(const MeshFacetGrid& rclGrid, std::vector<unsigned long> &raulFacets) const
{
std::vector<unsigned long>::iterator it;
MeshFacetIterator clIter(myMesh, 0);
// cut inner: use grid to accelerate search
if (myInner) {
Base::BoundBox3f clBBox3d;
Base::BoundBox2D clViewBBox, clPolyBBox;
std::vector<unsigned long> aulAllElements;
// BBox of polygon
clPolyBBox = myPoly.CalcBoundBox();
MeshGridIterator clGridIter(rclGrid);
// traverse all BBoxes
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
clBBox3d = clGridIter.GetBoundBox();
clViewBBox = clBBox3d.ProjectBox(myProj);
if (clViewBBox || clPolyBBox) {
// save all elements in AllElements
clGridIter.GetElements(aulAllElements);
}
}
// remove double elements
std::sort(aulAllElements.begin(), aulAllElements.end());
aulAllElements.erase(std::unique(aulAllElements.begin(), aulAllElements.end()), aulAllElements.end());
Base::SequencerLauncher seq("Check facets for intersection...", aulAllElements.size());
for (it = aulAllElements.begin(); it != aulAllElements.end(); it++) {
MeshGeomFacet clFacet = myMesh.GetFacet(*it);
if (HasIntersection(clFacet))
raulFacets.push_back(*it);
seq.next();
}
}
// cut outer
else {
Base::SequencerLauncher seq("Check facets for intersection...", myMesh.CountFacets());
for (clIter.Init(); clIter.More(); clIter.Next()) {
if (HasIntersection(*clIter))
raulFacets.push_back(clIter.Position());
seq.next();
}
}
}
bool MeshTrimming::HasIntersection(const MeshGeomFacet& rclFacet) const
{
int i;
unsigned long j;
Base::Polygon2D clPoly;
Base::Line2D clFacLine, clPolyLine;
Base::Vector2D S;
// is corner of facet inside the polygon
for (i=0; i<3; i++) {
Base::Vector3f clPt2d = myProj->operator ()(rclFacet._aclPoints[i]);
if (myPoly.Contains(Base::Vector2D(clPt2d.x, clPt2d.y)) == myInner)
return true;
else
clPoly.Add(Base::Vector2D(clPt2d.x, clPt2d.y));
}
// is corner of polygon inside the facet
for (j=0; j<myPoly.GetCtVectors(); j++) {
if (clPoly.Contains(myPoly[j]))
return true;
}
// check for other intersections
for (j=0; j<myPoly.GetCtVectors(); j++) {
clPolyLine.clV1 = myPoly[j];
clPolyLine.clV2 = myPoly[(j+1)%myPoly.GetCtVectors()];
for (i=0; i<3; i++) {
clFacLine.clV1 = clPoly[i];
clFacLine.clV2 = clPoly[(i+1)%3];
if (clPolyLine.IntersectAndContain(clFacLine, S))
return true;
}
}
// no intersection
return false;
}
bool MeshTrimming::PolygonContainsCompleteFacet(bool bInner, unsigned long ulIndex) const
{
const MeshFacet &rclFacet = myMesh._aclFacetArray[ulIndex];
for (int i=0; i<3; i++) {
const MeshPoint &rclFacPt = myMesh._aclPointArray[rclFacet._aulPoints[i]];
Base::Vector3f clPt = (*myProj)(rclFacPt);
if (myPoly.Contains(Base::Vector2D(clPt.x, clPt.y)) != bInner)
return false;
}
return true;
}
bool MeshTrimming::IsPolygonPointInFacet(unsigned long ulIndex, Base::Vector3f& clPoint)
{
Base::Vector2D A, B, C, P;
float u,v,w, fDetPAC, fDetPBC, fDetPAB, fDetABC;
Base::Polygon2D clFacPoly;
const MeshGeomFacet &rclFacet = myMesh.GetFacet(ulIndex);
for (int i=0; i<3; i++) {
Base::Vector3f clPt = (*myProj)(rclFacet._aclPoints[i]);
clFacPoly.Add(Base::Vector2D(clPt.x, clPt.y));
}
A = clFacPoly[0];
B = clFacPoly[1];
C = clFacPoly[2];
fDetABC = A.fX*B.fY+A.fY*C.fX+B.fX*C.fY-(B.fY*C.fX+A.fY*B.fX+A.fX*C.fY);
for (unsigned long j=0; j<myPoly.GetCtVectors(); j++) {
// facet contains a polygon point -> calculate the corresponding 3d-point
if (clFacPoly.Contains(myPoly[j])) {
P = myPoly[j];
fDetPAC = A.fX*P.fY+A.fY*C.fX+P.fX*C.fY-(P.fY*C.fX+A.fY*P.fX+A.fX*C.fY);
fDetPBC = P.fX*B.fY+P.fY*C.fX+B.fX*C.fY-(B.fY*C.fX+P.fY*B.fX+P.fX*C.fY);
fDetPAB = A.fX*B.fY+A.fY*P.fX+B.fX*P.fY-(B.fY*P.fX+A.fY*B.fX+A.fX*P.fY);
u = fDetPBC / fDetABC;
v = fDetPAC / fDetABC;
w = fDetPAB / fDetABC;
// point is on edge or no valid convex combination
if (u == 0.0f || v == 0.0f || w == 0.0f || fabs(u+v+w-1.0f) >= 0.001)
return false;
// 3d point
clPoint = u*rclFacet._aclPoints[0]+v*rclFacet._aclPoints[1]+w*rclFacet._aclPoints[2];
return true;
}
}
return false;
}
bool MeshTrimming::GetIntersectionPointsOfPolygonAndFacet(unsigned long ulIndex, int& iSide, std::vector<Base::Vector3f>& raclPoints) const
{
MeshGeomFacet clFac(myMesh.GetFacet(ulIndex));
Base::Vector2D S;
Base::Line2D clFacLine, clPolyLine;
int iIntersections=0;
int iIntsctWithEdge0=0, iIntsctWithEdge1=0, iIntsctWithEdge2=0;
// Edge with no intersection
iSide = -1;
for (unsigned long i=0; i<myPoly.GetCtVectors(); i++) {
// totally only four intersections allowed
if (iIntersections == 4)
break;
Base::Vector2D P3(myPoly[i]), P4(myPoly[(i+1)%myPoly.GetCtVectors()]);
clPolyLine.clV1 = P3;
clPolyLine.clV2 = P4;
for (int j=0; j<3; j++) {
Base::Vector3f clP1((*myProj)(clFac._aclPoints[j]));
Base::Vector3f clP2((*myProj)(clFac._aclPoints[(j+1)%3]));
Base::Vector2D P1(clP1.x, clP1.y);
Base::Vector2D P2(clP2.x, clP2.y);
clFacLine.clV1 = P1;
clFacLine.clV2 = P2;
if (clPolyLine.Intersect(clFacLine, S)) {
bool bPushBack=true;
float fP1P2 = (P2-P1).Length();
float fSP1 = (P1-S).Length();
float fSP2 = (P2-S).Length();
float fP3P4 = (P4-P3).Length();
float fSP3 = (P3-S).Length();
float fSP4 = (P4-S).Length();
// compute propotion of length
float l = fSP1 / fP1P2;
float m = fSP2 / fP1P2;
float r = fSP3 / fP3P4;
float s = fSP4 / fP3P4;
// is intersection point convex combination?
if ((fabs(l+m-1.0f) < 0.001) && (fabs(r+s-1.0f) < 0.001)) {
#ifdef _DEBUG
Base::Vector3f clIntersection(m*clFac._aclPoints[j]+l*clFac._aclPoints[(j+1)%3]);
#endif
iIntersections++;
// only two intersections points per edge allowed
if (j == 0) {
if (iIntsctWithEdge0 == 2)
bPushBack = false;
else
iIntsctWithEdge0++;
}
else if (j == 1) {
if (iIntsctWithEdge1 == 2)
bPushBack = false;
else
iIntsctWithEdge1++;
}
else {
if (iIntsctWithEdge2 == 2)
bPushBack = false;
else
iIntsctWithEdge2++;
}
if (bPushBack == true)
raclPoints.push_back(m*clFac._aclPoints[j]+l*clFac._aclPoints[(j+1)%3]);
}
}
}
}
// check for rotating facet later
if (iIntsctWithEdge0 == 0)
iSide = 0;
else if (iIntsctWithEdge1 == 0)
iSide = 1;
else if (iIntsctWithEdge2 == 0)
iSide = 2;
// further check (for rotating the facet)
if (iIntsctWithEdge0 == 0 && iIntsctWithEdge1 == 0)
iSide = 1;
else if (iIntsctWithEdge0 == 0 && iIntsctWithEdge2 == 0)
iSide = 0;
else if (iIntsctWithEdge1 == 0 && iIntsctWithEdge2 == 0)
iSide = 2;
// and last another check
if (iIntsctWithEdge0 * iIntsctWithEdge1 * iIntsctWithEdge2 > 0) {
if (iIntsctWithEdge0 == 2)
iSide = 2;
else if (iIntsctWithEdge1 == 2)
iSide = 0;
else if (iIntsctWithEdge2 == 2)
iSide = 1;
}
return iIntersections > 0;
}
void MeshTrimming::AdjustFacet(MeshFacet& facet, int iInd)
{
unsigned long tmp;
if (iInd == 1) {
tmp = facet._aulPoints[0];
facet._aulPoints[0] = facet._aulPoints[1];
facet._aulPoints[1] = facet._aulPoints[2];
facet._aulPoints[2] = tmp;
tmp = facet._aulNeighbours[0];
facet._aulNeighbours[0] = facet._aulNeighbours[1];
facet._aulNeighbours[1] = facet._aulNeighbours[2];
facet._aulNeighbours[2] = tmp;
}
else if (iInd == 2) {
tmp = facet._aulPoints[0];
facet._aulPoints[0] = facet._aulPoints[2];
facet._aulPoints[2] = facet._aulPoints[1];
facet._aulPoints[1] = tmp;
tmp = facet._aulNeighbours[0];
facet._aulNeighbours[0] = facet._aulNeighbours[2];
facet._aulNeighbours[2] = facet._aulNeighbours[1];
facet._aulNeighbours[1] = tmp;
}
}
bool MeshTrimming::CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints, std::vector<MeshGeomFacet>& aclNewFacets)
{
MeshGeomFacet clFac;
// no valid triangulation possible
if (iSide == -1)
return false;
// two points found
if (raclPoints.size() == 2) {
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
AdjustFacet(facet, iSide);
Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]);
if (iSide == 1) {
// swap P1 and P2
clP1 = raclPoints[1];
clP2 = raclPoints[0];
}
// check which facets can be inserted
int iCtPts=0;
Base::Vector3f clFacPnt;
Base::Vector2D clProjPnt;
for (int i=0; i<3; i++) {
clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
if (myPoly.Contains(clProjPnt) == myInner)
++iCtPts;
}
if (iCtPts == 2) {
// erstes Dreieck
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[2]];
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
}
else if (iCtPts == 1) {
// erstes Dreieck
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
// zweites Dreieck
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[1]];
clFac._aclPoints[1] = clP1;
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
}
else
return false;
}
// four points found
else if (raclPoints.size() == 4) {
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
AdjustFacet(facet, iSide);
MeshFacet clOrg(myMesh._aclFacetArray[ulFacetPos]);
clFac = myMesh.GetFacet(ulFacetPos);
// intersection points
Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]), clP3(raclPoints[2]), clP4(raclPoints[3]);
// check which facets can be inserted
int iCtPts=0;
Base::Vector3f clFacPnt;
Base::Vector2D clProjPnt;
for (int i=0; i<3; i++) {
clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
if (myPoly.Contains(clProjPnt) == myInner)
++iCtPts;
}
// sort the intersection points in a certain order
if (iCtPts == 0 || iCtPts == 3) {
if (iSide == 1) {
// swap the points
clP1 = clP2;
clP2 = raclPoints[0];
clP3 = clP4;
clP4 = raclPoints[2];
}
if ((clP1-clFac._aclPoints[1]).Length() > (clP3-clFac._aclPoints[1]).Length()) {
// swap P1 and P3
Base::Vector3f tmp(clP1);
clP1 = clP3;
clP3 = tmp;
}
if ((clP2-clFac._aclPoints[0]).Length() > (clP4-clFac._aclPoints[0]).Length()) {
// swap P2 and P4
Base::Vector3f tmp(clP2);
clP2 = clP4;
clP4 = tmp;
}
}
else {
if (iSide == 0) {
Base::Vector3f clNormal(clFac.GetNormal());
MeshGeomFacet clTmpFac; clTmpFac._aclPoints[0] = clFac._aclPoints[1];
clTmpFac._aclPoints[1] = clP2; clTmpFac._aclPoints[2] = clP1;
if (clTmpFac.GetNormal() * clNormal > 0) {
Base::Vector3f tmp(clP1);
clP1 = clP2;
clP2 = tmp;
}
else {
Base::Vector3f tmp(clP1);
clP1 = clP4;
clP4 = clP2;
clP2 = clP3;
clP3 = tmp;
}
}
else if (iSide == 1) {
if ((clP2-clFac._aclPoints[1]).Length() > (clP4-clFac._aclPoints[1]).Length()) {
Base::Vector3f tmp(clP1);
clP1 = clP4;
clP4 = tmp;
tmp = clP2;
clP2 = clP3;
clP3 = tmp;
}
else {
Base::Vector3f tmp(clP1);
clP1 = clP2;
clP2 = tmp;
tmp = clP3;
clP3 = clP4;
clP4 = tmp;
}
}
else {
if ((clP1-clFac._aclPoints[1]).Length() > (clP3-clFac._aclPoints[1]).Length()) {
Base::Vector3f tmp(clP1);
clP1 = clP3;
clP3 = tmp;
tmp = clP2;
clP2 = clP4;
clP4 = tmp;
}
}
}
// now create the new facets
if (iCtPts == 0) {
// insert first facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
clFac._aclPoints[2] = clP1;
aclNewFacets.push_back(clFac);
// insert second facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[1] = clP1;
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
// finally insert third facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
clFac._aclPoints[1] = clP4;
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
}
else if (iCtPts == 1) {
// insert first facet
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = clP2;
clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[1]];
aclNewFacets.push_back(clFac);
// finally insert second facet
clFac._aclPoints[0] = clP4;
clFac._aclPoints[1] = clP3;
clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[2]];
aclNewFacets.push_back(clFac);
}
else if (iCtPts == 2) {
// insert first facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[1] = clP2;
clFac._aclPoints[2] = clP4;
aclNewFacets.push_back(clFac);
// insert second facet
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = clP4;
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
// finally insert third facet
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = clP3;
clFac._aclPoints[2] = clP4;
aclNewFacets.push_back(clFac);
}
else {
// insert first facet
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = clP3;
clFac._aclPoints[2] = clP4;
aclNewFacets.push_back(clFac);
// finally insert second facet
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = clP4;
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
}
}
else
return false;
return true;
}
bool MeshTrimming::CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints, Base::Vector3f& clP3,
std::vector<MeshGeomFacet>& aclNewFacets)
{
// no valid triangulation possible
if (iSide == -1 || raclPoints.size() < 2)
return false;
Base::Vector3f clP1(raclPoints[0]);
Base::Vector3f clP2(raclPoints[1]);
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
AdjustFacet(facet, iSide);
MeshGeomFacet clFac;
Base::Vector3f pnt = myMesh._aclPointArray[facet._aulPoints[1]];
Base::Vector3f dir = myMesh._aclPointArray[facet._aulPoints[2]] -
myMesh._aclPointArray[facet._aulPoints[1]];
float fDistEdgeP1 = clP1.DistanceToLineSegment(
myMesh._aclPointArray[facet._aulPoints[1]],
myMesh._aclPointArray[facet._aulPoints[2]]).Length();
float fDistEdgeP2 = clP2.DistanceToLineSegment(
myMesh._aclPointArray[facet._aulPoints[1]],
myMesh._aclPointArray[facet._aulPoints[2]]).Length();
// swap P1 and P2
if (fDistEdgeP2 < fDistEdgeP1) {
Base::Vector3f tmp(clP1);
clP1 = clP2;
clP2 = tmp;
}
// check which facets should be inserted
int iCtPts=0;
Base::Vector3f clFacPnt;
Base::Vector2D clProjPnt;
for (int i=0; i<3; i++) {
clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
if (myPoly.Contains(clProjPnt) == myInner)
++iCtPts;
}
if (iCtPts == 3) {
clFac = myMesh.GetFacet(ulFacetPos);
if ((clP1-clFac._aclPoints[1]).Length() > (clP2-clFac._aclPoints[1]).Length()) {
Base::Vector3f tmp(clP1);
clP1 = clP2;
clP2 = tmp;
}
// only one facet
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = clP2;
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
}
else if (iCtPts == 2) {
// first facet
clFac._aclPoints[0] = clP1;
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[2]];
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
// second facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
clFac._aclPoints[1] = clP2;
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
}
else if (iCtPts == 1) {
// first facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
// second facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[1]];
clFac._aclPoints[1] = clP1;
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
// third facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[1] = clP3;
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
}
else if (iCtPts == 0) {
clFac = myMesh.GetFacet(ulFacetPos);
if ((clP1-clFac._aclPoints[1]).Length() > (clP2-clFac._aclPoints[1]).Length()) {
Base::Vector3f tmp(clP1);
clP1 = clP2;
clP2 = tmp;
}
// first facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
clFac._aclPoints[1] = clP3;
clFac._aclPoints[2] = clP2;
aclNewFacets.push_back(clFac);
// second facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
// third facet
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
clFac._aclPoints[2] = clP3;
aclNewFacets.push_back(clFac);
// and finally fourth facet
clFac._aclPoints[0] = clP3;
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
clFac._aclPoints[2] = clP1;
aclNewFacets.push_back(clFac);
}
return true;
}
void MeshTrimming::TrimFacets(const std::vector<unsigned long>& raulFacets, std::vector<MeshGeomFacet>& aclNewFacets)
{
Base::Vector3f clP;
std::vector<Base::Vector3f> clIntsct;
int iSide;
Base::SequencerLauncher seq("trimming facets...", raulFacets.size());
for (std::vector<unsigned long>::const_iterator it=raulFacets.begin(); it!=raulFacets.end(); it++) {
clIntsct.clear();
if (IsPolygonPointInFacet(*it, clP) == false) {
// facet must be trimmed
if (PolygonContainsCompleteFacet(myInner, *it) == false) {
// generate new facets
if (GetIntersectionPointsOfPolygonAndFacet(*it, iSide, clIntsct))
CreateFacets(*it, iSide, clIntsct, myTriangles);
}
}
// facet contains a polygon point
else {
// generate new facets
if (GetIntersectionPointsOfPolygonAndFacet(*it, iSide, clIntsct))
CreateFacets(*it, iSide, clIntsct, clP, myTriangles);
}
seq.next();
}
aclNewFacets = myTriangles;
}

View File

@ -0,0 +1,108 @@
/***************************************************************************
* Copyright (c) 2012 Imetric 3D GmbH *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef MESHTRIM_H
#define MESHTRIM_H
#include <Mod/Mesh/App/Core/Elements.h>
#include <Mod/Mesh/App/Core/MeshKernel.h>
#include <Base/Tools2D.h>
#include <Base/ViewProj.h>
namespace MeshCore {
/**
* Checks the facets in 2D and then trim them in 3D
*/
class MeshExport MeshTrimming
{
public:
enum TMode {INNER, OUTER};
public:
MeshTrimming(MeshKernel& mesh, const Base::ViewProjMethod* pclProj, const Base::Polygon2D& rclPoly);
~MeshTrimming();
public:
/**
* Checks all facets for intersection with the polygon and writes all touched facets into the vector
*/
void CheckFacets(const MeshFacetGrid& rclGrid, std::vector<unsigned long>& raulFacets) const;
/**
* The facets from raulFacets will be trimmed or deleted and aclNewFacets gives the new generated facets
*/
void TrimFacets(const std::vector<unsigned long>& raulFacets, std::vector<MeshGeomFacet>& aclNewFacets);
/**
* Setter: Trimm INNER or OUTER
*/
void SetInnerOrOuter(TMode tMode);
private:
/**
* Checks if the polygon cuts the facet
*/
bool HasIntersection(const MeshGeomFacet& rclFacet) const;
/**
* Checks if a facet lies totally within a polygon
*/
bool PolygonContainsCompleteFacet(bool bInner, unsigned long ulIndex) const;
/**
* Creates new facets from edge points of the facet
*/
bool CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints,
std::vector<MeshGeomFacet>& aclNewFacets);
/**
* Creates new facets from edge points of the facet and a point inside the facet
*/
bool CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints,
Base::Vector3f& clP3, std::vector<MeshGeomFacet>& aclNewFacets);
/**
* Checks if a polygon point lies within a facet
*/
bool IsPolygonPointInFacet(unsigned long ulIndex, Base::Vector3f& clPoint);
/**
* Calculates the two intersection points between polygonline and facet in 2D
* and project the points back into 3D (not very exactly)
*/
bool GetIntersectionPointsOfPolygonAndFacet(unsigned long ulIndex, int& iSide,
std::vector<Base::Vector3f>& raclPoints) const;
void AdjustFacet(MeshFacet& facet, int iInd);
private:
MeshKernel& myMesh;
bool myInner;
std::vector<MeshGeomFacet> myTriangles;
const Base::ViewProjMethod* myProj;
const Base::Polygon2D& myPoly;
};
} //namespace MeshCore
#endif //MESHTRIM_H

View File

@ -49,6 +49,8 @@ libMesh_la_SOURCES=\
Core/tritritest.h \
Core/Triangulation.cpp \
Core/Triangulation.h \
Core/Trim.cpp \
Core/Trim.h \
Core/Tools.cpp \
Core/Tools.h \
Core/TopoAlgorithm.cpp \

View File

@ -34,6 +34,7 @@
#include <Base/Writer.h>
#include <Base/Reader.h>
#include <Base/Interpreter.h>
#include <Base/Sequencer.h>
#include "Core/Builder.h"
#include "Core/MeshKernel.h"
@ -1181,6 +1182,7 @@ MeshObject* MeshObject::createMeshFromList(Py::List& list)
}
}
Base::EmptySequencer seq;
std::auto_ptr<MeshObject> mesh(new MeshObject);
//mesh->addFacets(facets);
mesh->getKernel() = facets;

View File

@ -127,6 +127,16 @@ Example:
<UserDocu>Remove a list of facet indices from the mesh</UserDocu>
</Documentation>
</Methode>
<Methode Name="getInternalFacets" Const="true">
<Documentation>
<UserDocu>Builds a list of facet indices with triangles that are inside a volume mesh</UserDocu>
</Documentation>
</Methode>
<Methode Name="rebuildNeighbourHood">
<Documentation>
<UserDocu>Repairs the neighbourhood which might be broken</UserDocu>
</Documentation>
</Methode>
<Methode Name="addMesh">
<Documentation>
<UserDocu>Combine this mesh with another mesh.</UserDocu>

Some files were not shown because too many files have changed in this diff Show More