Merge branch 'master' into HEAD
git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5436 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
This commit is contained in:
commit
f53f1cee84
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -11,5 +11,6 @@ mkinstalldirs export-ignore
|
||||||
package export-ignore
|
package export-ignore
|
||||||
fc.sh export-ignore
|
fc.sh export-ignore
|
||||||
UpdateResources.bat export-ignore
|
UpdateResources.bat export-ignore
|
||||||
|
BuildVersion.bat export-ignore
|
||||||
*.sln export-ignore
|
*.sln export-ignore
|
||||||
WindowsInstaller export-ignore
|
WindowsInstaller export-ignore
|
||||||
|
|
|
@ -467,3 +467,26 @@ if(FREECAD_MAINTAINERS_BUILD AND NOT WIN32)
|
||||||
#ADD_CUSTOM_TARGET(DIST make package_source)
|
#ADD_CUSTOM_TARGET(DIST make package_source)
|
||||||
|
|
||||||
endif(FREECAD_MAINTAINERS_BUILD AND NOT WIN32)
|
endif(FREECAD_MAINTAINERS_BUILD AND NOT WIN32)
|
||||||
|
add_custom_target(dist-git
|
||||||
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py
|
||||||
|
--srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
add_custom_target(distdfsg-git
|
||||||
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py
|
||||||
|
--srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR} --dfsg
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX OR MINGW)
|
||||||
|
add_custom_target(distcheck-git
|
||||||
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py
|
||||||
|
--srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR} --check
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
add_custom_target(distcheckdfsg-git
|
||||||
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/Tools/makedist.py
|
||||||
|
--srcdir=${CMAKE_SOURCE_DIR} --bindir=${CMAKE_BINARY_DIR} --dfsg --check
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
endif(CMAKE_COMPILER_IS_GNUCXX OR MINGW)
|
||||||
|
|
||||||
|
|
4
src/3rdParty/CMakeLists.txt
vendored
4
src/3rdParty/CMakeLists.txt
vendored
|
@ -22,9 +22,13 @@ elseif(FREECAD_BUILD_GUI AND FREECAD_LIBPACK_CHECKFILE7X)
|
||||||
elseif(FREECAD_BUILD_GUI)
|
elseif(FREECAD_BUILD_GUI)
|
||||||
find_path(COIN_VERSION3 Inventor/scxml/ScXML.h ${COIN3D_INCLUDE_DIR})
|
find_path(COIN_VERSION3 Inventor/scxml/ScXML.h ${COIN3D_INCLUDE_DIR})
|
||||||
if (COIN_VERSION3)
|
if (COIN_VERSION3)
|
||||||
|
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy-0.5)
|
||||||
add_subdirectory(Pivy-0.5)
|
add_subdirectory(Pivy-0.5)
|
||||||
|
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy-0.5)
|
||||||
else (COIN_VERSION3)
|
else (COIN_VERSION3)
|
||||||
|
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy)
|
||||||
add_subdirectory(Pivy)
|
add_subdirectory(Pivy)
|
||||||
|
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Pivy)
|
||||||
endif(COIN_VERSION3)
|
endif(COIN_VERSION3)
|
||||||
endif(FREECAD_BUILD_GUI AND FREECAD_LIBPACK_CHECKFILE6X)
|
endif(FREECAD_BUILD_GUI AND FREECAD_LIBPACK_CHECKFILE6X)
|
||||||
|
|
||||||
|
|
|
@ -1033,7 +1033,13 @@ void Application::initConfig(int argc, char ** argv)
|
||||||
App::Application::Config()["BuildVersionMinor" ] = FCVersionMinor;
|
App::Application::Config()["BuildVersionMinor" ] = FCVersionMinor;
|
||||||
App::Application::Config()["BuildRevision" ] = FCRevision;
|
App::Application::Config()["BuildRevision" ] = FCRevision;
|
||||||
App::Application::Config()["BuildRepositoryURL" ] = FCRepositoryURL;
|
App::Application::Config()["BuildRepositoryURL" ] = FCRepositoryURL;
|
||||||
App::Application::Config()["BuildRevisionDate"] = FCCurrentDateT;
|
App::Application::Config()["BuildRevisionDate" ] = FCRevisionDate;
|
||||||
|
#if defined(FCRepositoryHash)
|
||||||
|
App::Application::Config()["BuildRevisionHash" ] = FCRepositoryHash;
|
||||||
|
#endif
|
||||||
|
#if defined(FCRepositoryBranch)
|
||||||
|
App::Application::Config()["BuildRevisionBranch"] = FCRepositoryBranch;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
_argc = argc;
|
_argc = argc;
|
||||||
|
|
|
@ -68,6 +68,7 @@ if(SWIG_FOUND)
|
||||||
add_definitions(-DHAVE_SWIG=1)
|
add_definitions(-DHAVE_SWIG=1)
|
||||||
endif(SWIG_FOUND)
|
endif(SWIG_FOUND)
|
||||||
|
|
||||||
|
if (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++)
|
||||||
SET(zipios_SRCS
|
SET(zipios_SRCS
|
||||||
../zipios++/backbuffer.h
|
../zipios++/backbuffer.h
|
||||||
../zipios++/basicentry.cpp
|
../zipios++/basicentry.cpp
|
||||||
|
@ -121,6 +122,12 @@ SET(zipios_SRCS
|
||||||
../zipios++/zipoutputstream.h
|
../zipios++/zipoutputstream.h
|
||||||
)
|
)
|
||||||
SOURCE_GROUP("zipios" FILES ${zipios_SRCS})
|
SOURCE_GROUP("zipios" FILES ${zipios_SRCS})
|
||||||
|
else (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++)
|
||||||
|
set(FreeCADBase_LIBS
|
||||||
|
${FreeCADBase_LIBS}
|
||||||
|
-lzipios
|
||||||
|
)
|
||||||
|
endif (EXISTS ${CMAKE_SOURCE_DIR}/src/zipios++)
|
||||||
|
|
||||||
SET(pycxx_SRCS
|
SET(pycxx_SRCS
|
||||||
../CXX/Config.hxx
|
../CXX/Config.hxx
|
||||||
|
|
|
@ -176,8 +176,11 @@ std::string FileInfo::getTempFileName(const char* FileName, const char* Path)
|
||||||
else
|
else
|
||||||
std::strcat(buf, "/fileXXXXXX");
|
std::strcat(buf, "/fileXXXXXX");
|
||||||
|
|
||||||
/*int id =*/ (void) mkstemp(buf);
|
int id = mkstemp(buf);
|
||||||
//FILE* file = fdopen(id, "w");
|
if (id > -1) {
|
||||||
|
FILE* file = fdopen(id, "w");
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,10 @@
|
||||||
|
|
||||||
/// Version Number
|
// Version Number
|
||||||
#define FCVersionMajor "0"
|
#define FCVersionMajor "0"
|
||||||
#define FCVersionMinor "13"
|
#define FCVersionMinor "13"
|
||||||
#define FCVersionName "Vulcan"
|
#define FCVersionName "Vulcan"
|
||||||
|
|
||||||
#define FCRevision "$WCREV$" //Highest committed revision number
|
#define FCRevision "$WCREV$" //Highest committed revision number
|
||||||
#define FCRevisionDate "$WCDATE$" //Date of highest committed revision
|
#define FCRevisionDate "$WCDATE$" //Date of highest committed revision
|
||||||
#define FCRevisionRange "$WCRANGE$" //Update revision range
|
|
||||||
#define FCRepositoryURL "$WCURL$" //Repository URL of the working copy
|
#define FCRepositoryURL "$WCURL$" //Repository URL of the working copy
|
||||||
#define FCCurrentDateT "$WCNOW$" //Current system date & time
|
|
||||||
|
|
||||||
//Placeholders of the form "$WCxxx?TrueText:FalseText$" are replaced with
|
|
||||||
//TrueText if the tested condition is true, and FalseText if false.
|
|
||||||
|
|
||||||
#define FCScrClean "$WCMODS?Src modified:Src not modified$" //True if local modifications found
|
|
||||||
#define FCScrMixed "$WCMIXED?Src mixed:Src not mixed$" //True if mixed update revisions found
|
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,17 @@
|
||||||
<property name="modal">
|
<property name="modal">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<property name="margin">
|
<item row="0" column="0" colspan="3">
|
||||||
<number>9</number>
|
<widget class="QLabel" name="labelSplashPicture">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="spacing">
|
<property name="alignment">
|
||||||
<number>6</number>
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -36,15 +40,18 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="3">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="labelSplashPicture">
|
<spacer>
|
||||||
<property name="text">
|
<property name="orientation">
|
||||||
<string/>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="sizeHint" stdset="0">
|
||||||
<set>Qt::AlignCenter</set>
|
<size>
|
||||||
|
<width>31</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<layout class="QVBoxLayout">
|
<layout class="QVBoxLayout">
|
||||||
|
@ -161,6 +168,34 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="labelBranch">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Branch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLabel" name="labelBuildBranch">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; font-size:7.8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Unknown</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QLabel" name="labelBuildHash">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; font-size:7.8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Unknown</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="labelHash">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Hash</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -178,19 +213,6 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>31</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -219,6 +241,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="copyButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Copy to clipboard</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -239,19 +268,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>181</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -264,7 +280,7 @@
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="Icons/resource.qrc"/>
|
<include location="../../../FreeCAD/src/Gui/Icons/resource.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|
|
@ -23,8 +23,11 @@
|
||||||
|
|
||||||
#include "PreCompiled.h"
|
#include "PreCompiled.h"
|
||||||
#ifndef _PreComp_
|
#ifndef _PreComp_
|
||||||
|
# include <QApplication>
|
||||||
|
# include <QClipboard>
|
||||||
# include <QMutex>
|
# include <QMutex>
|
||||||
# include <QSysInfo>
|
# include <QSysInfo>
|
||||||
|
# include <QTextStream>
|
||||||
# include <QWaitCondition>
|
# include <QWaitCondition>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -248,18 +251,18 @@ static QString getPlatform()
|
||||||
|
|
||||||
void AboutDialog::setupLabels()
|
void AboutDialog::setupLabels()
|
||||||
{
|
{
|
||||||
QString exeName = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
|
std::map<std::string, std::string>& config = App::Application::Config();
|
||||||
std::map<std::string,std::string>& cfg = App::Application::Config();
|
QString exeName = QString::fromAscii(config["ExeName"].c_str());
|
||||||
std::map<std::string,std::string>::iterator it = cfg.find("WindowTitle");
|
std::map<std::string,std::string>::iterator it = config.find("WindowTitle");
|
||||||
if (it != cfg.end())
|
if (it != config.end())
|
||||||
exeName = QString::fromUtf8(it->second.c_str());
|
exeName = QString::fromUtf8(it->second.c_str());
|
||||||
QString banner = QString::fromUtf8(App::Application::Config()["ConsoleBanner"].c_str());
|
QString banner = QString::fromUtf8(config["ConsoleBanner"].c_str());
|
||||||
banner = banner.left( banner.indexOf(QLatin1Char('\n')) );
|
banner = banner.left( banner.indexOf(QLatin1Char('\n')) );
|
||||||
QString major = QString::fromAscii(App::Application::Config()["BuildVersionMajor"].c_str());
|
QString major = QString::fromAscii(config["BuildVersionMajor"].c_str());
|
||||||
QString minor = QString::fromAscii(App::Application::Config()["BuildVersionMinor"].c_str());
|
QString minor = QString::fromAscii(config["BuildVersionMinor"].c_str());
|
||||||
QString build = QString::fromAscii(App::Application::Config()["BuildRevision"].c_str());
|
QString build = QString::fromAscii(config["BuildRevision"].c_str());
|
||||||
QString disda = QString::fromAscii(App::Application::Config()["BuildRevisionDate"].c_str());
|
QString disda = QString::fromAscii(config["BuildRevisionDate"].c_str());
|
||||||
QString mturl = QString::fromAscii(App::Application::Config()["MaintainerUrl"].c_str());
|
QString mturl = QString::fromAscii(config["MaintainerUrl"].c_str());
|
||||||
|
|
||||||
QString author = ui->labelAuthor->text();
|
QString author = ui->labelAuthor->text();
|
||||||
author.replace(QString::fromAscii("Unknown Application"), exeName);
|
author.replace(QString::fromAscii("Unknown Application"), exeName);
|
||||||
|
@ -283,10 +286,56 @@ void AboutDialog::setupLabels()
|
||||||
platform.replace(QString::fromAscii("Unknown"),
|
platform.replace(QString::fromAscii("Unknown"),
|
||||||
QString::fromAscii("%1 (%2-bit)").arg(getPlatform()).arg(QSysInfo::WordSize));
|
QString::fromAscii("%1 (%2-bit)").arg(getPlatform()).arg(QSysInfo::WordSize));
|
||||||
ui->labelBuildPlatform->setText(platform);
|
ui->labelBuildPlatform->setText(platform);
|
||||||
|
|
||||||
|
// branch name
|
||||||
|
it = config.find("BuildRevisionBranch");
|
||||||
|
if (it != config.end()) {
|
||||||
|
QString branch = ui->labelBuildBranch->text();
|
||||||
|
branch.replace(QString::fromAscii("Unknown"), QString::fromAscii(it->second.c_str()));
|
||||||
|
ui->labelBuildBranch->setText(branch);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui->labelBranch->hide();
|
||||||
|
ui->labelBuildBranch->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
// hash id
|
||||||
|
it = config.find("BuildRevisionHash");
|
||||||
|
if (it != config.end()) {
|
||||||
|
QString hash = ui->labelBuildHash->text();
|
||||||
|
hash.replace(QString::fromAscii("Unknown"), QString::fromAscii(it->second.c_str()));
|
||||||
|
ui->labelBuildHash->setText(hash);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui->labelHash->hide();
|
||||||
|
ui->labelBuildHash->hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AboutDialog::on_licenseButton_clicked()
|
void AboutDialog::on_licenseButton_clicked()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AboutDialog::on_copyButton_clicked()
|
||||||
|
{
|
||||||
|
QString data;
|
||||||
|
QTextStream str(&data);
|
||||||
|
std::map<std::string, std::string>& config = App::Application::Config();
|
||||||
|
std::map<std::string,std::string>::iterator it;
|
||||||
|
|
||||||
|
QString major = QString::fromAscii(config["BuildVersionMajor"].c_str());
|
||||||
|
QString minor = QString::fromAscii(config["BuildVersionMinor"].c_str());
|
||||||
|
QString build = QString::fromAscii(config["BuildRevision"].c_str());
|
||||||
|
str << "Version: " << major << "." << minor << "." << build << endl;
|
||||||
|
it = config.find("BuildRevisionBranch");
|
||||||
|
if (it != config.end())
|
||||||
|
str << "Branch: " << it->second.c_str() << endl;
|
||||||
|
it = config.find("BuildRevisionHash");
|
||||||
|
if (it != config.end())
|
||||||
|
str << "Hash: " << it->second.c_str() << endl;
|
||||||
|
|
||||||
|
QClipboard* cb = QApplication::clipboard();
|
||||||
|
cb->setText(data);
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_Splashscreen.cpp"
|
#include "moc_Splashscreen.cpp"
|
||||||
|
|
|
@ -85,6 +85,7 @@ protected:
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
virtual void on_licenseButton_clicked();
|
virtual void on_licenseButton_clicked();
|
||||||
|
virtual void on_copyButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_AboutApplication* ui;
|
Ui_AboutApplication* ui;
|
||||||
|
|
|
@ -140,6 +140,7 @@ class ComponentTaskPanel:
|
||||||
QtCore.QObject.connect(self.addButton, QtCore.SIGNAL("clicked()"), self.addElement)
|
QtCore.QObject.connect(self.addButton, QtCore.SIGNAL("clicked()"), self.addElement)
|
||||||
QtCore.QObject.connect(self.delButton, QtCore.SIGNAL("clicked()"), self.removeElement)
|
QtCore.QObject.connect(self.delButton, QtCore.SIGNAL("clicked()"), self.removeElement)
|
||||||
QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.check)
|
QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.check)
|
||||||
|
QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemDoubleClicked(QTreeWidgetItem *,int)"), self.editObject)
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def isAllowedAlterSelection(self):
|
def isAllowedAlterSelection(self):
|
||||||
|
@ -225,6 +226,20 @@ class ComponentTaskPanel:
|
||||||
self.obj.ViewObject.finishEditing()
|
self.obj.ViewObject.finishEditing()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def editObject(self,wid,col):
|
||||||
|
if wid.parent():
|
||||||
|
obj = FreeCAD.ActiveDocument.getObject(str(wid.text(0)))
|
||||||
|
if obj:
|
||||||
|
self.obj.ViewObject.Transparency = 80
|
||||||
|
self.obj.ViewObject.Selectable = False
|
||||||
|
obj.ViewObject.show()
|
||||||
|
self.accept()
|
||||||
|
if obj.isDerivedFrom("Sketcher::SketchObject"):
|
||||||
|
FreeCADGui.activateWorkbench("SketcherWorkbench")
|
||||||
|
FreeCAD.ArchObserver = ArchSelectionObserver(self.obj,obj)
|
||||||
|
FreeCADGui.Selection.addObserver(FreeCAD.ArchObserver)
|
||||||
|
FreeCADGui.ActiveDocument.setEdit(obj.Name,0)
|
||||||
|
|
||||||
def retranslateUi(self, TaskPanel):
|
def retranslateUi(self, TaskPanel):
|
||||||
TaskPanel.setWindowTitle(QtGui.QApplication.translate("Arch", "Components", None, QtGui.QApplication.UnicodeUTF8))
|
TaskPanel.setWindowTitle(QtGui.QApplication.translate("Arch", "Components", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None, QtGui.QApplication.UnicodeUTF8))
|
self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
@ -252,7 +267,6 @@ class Component:
|
||||||
self.Type = "Component"
|
self.Type = "Component"
|
||||||
self.Subvolume = None
|
self.Subvolume = None
|
||||||
|
|
||||||
|
|
||||||
class ViewProviderComponent:
|
class ViewProviderComponent:
|
||||||
"A default View Provider for Component objects"
|
"A default View Provider for Component objects"
|
||||||
def __init__(self,vobj):
|
def __init__(self,vobj):
|
||||||
|
@ -296,3 +310,17 @@ class ViewProviderComponent:
|
||||||
FreeCADGui.Control.closeDialog()
|
FreeCADGui.Control.closeDialog()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
class ArchSelectionObserver:
|
||||||
|
def __init__(self,origin,watched):
|
||||||
|
self.origin = origin
|
||||||
|
self.watched = watched
|
||||||
|
def addSelection(self,document, object, element, position):
|
||||||
|
if object == self.watched.Name:
|
||||||
|
if not element:
|
||||||
|
print "closing Sketch edit"
|
||||||
|
self.origin.ViewObject.Transparency = 0
|
||||||
|
self.origin.ViewObject.Selectable = True
|
||||||
|
self.watched.ViewObject.hide()
|
||||||
|
FreeCADGui.activateWorkbench("ArchWorkbench")
|
||||||
|
FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver)
|
||||||
|
del FreeCAD.ArchObserver
|
||||||
|
|
|
@ -256,18 +256,11 @@ def formatObject(target,origin=None):
|
||||||
if "ShapeColor" in obrep.PropertiesList: obrep.ShapeColor = fcol
|
if "ShapeColor" in obrep.PropertiesList: obrep.ShapeColor = fcol
|
||||||
else:
|
else:
|
||||||
matchrep = origin.ViewObject
|
matchrep = origin.ViewObject
|
||||||
if ("LineWidth" in obrep.PropertiesList) and \
|
for p in matchrep.PropertiesList:
|
||||||
("LineWidth" in matchrep.PropertiesList):
|
if not p in ["DisplayMode","BoundingBox","Proxy","RootNode"]:
|
||||||
obrep.LineWidth = matchrep.LineWidth
|
if p in obrep.PropertiesList:
|
||||||
if ("PointColor" in obrep.PropertiesList) and \
|
val = getattr(matchrep,p)
|
||||||
("PointColor" in matchrep.PropertiesList):
|
setattr(obrep,p,val)
|
||||||
obrep.PointColor = matchrep.PointColor
|
|
||||||
if ("LineColor" in obrep.PropertiesList) and \
|
|
||||||
("LineColor" in matchrep.PropertiesList):
|
|
||||||
obrep.LineColor = matchrep.LineColor
|
|
||||||
if ("ShapeColor" in obrep.PropertiesList) and \
|
|
||||||
("ShapeColor" in matchrep.PropertiesList):
|
|
||||||
obrep.ShapeColor = matchrep.ShapeColor
|
|
||||||
if matchrep.DisplayMode in obrep.listDisplayModes():
|
if matchrep.DisplayMode in obrep.listDisplayModes():
|
||||||
obrep.DisplayMode = matchrep.DisplayMode
|
obrep.DisplayMode = matchrep.DisplayMode
|
||||||
|
|
||||||
|
@ -516,48 +509,52 @@ def makeText(stringslist,point=Vector(0,0,0),screen=False):
|
||||||
select(obj)
|
select(obj)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def makeCopy(obj):
|
def makeCopy(obj,force=None,reparent=False):
|
||||||
'''makeCopy(object): returns an exact copy of an object'''
|
'''makeCopy(object): returns an exact copy of an object'''
|
||||||
if getType(obj) == "Rectangle":
|
if (getType(obj) == "Rectangle") or (force == "Rectangle"):
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
_Rectangle(newobj)
|
_Rectangle(newobj)
|
||||||
_ViewProviderRectangle(newobj.ViewObject)
|
_ViewProviderRectangle(newobj.ViewObject)
|
||||||
elif getType(obj) == "Wire":
|
elif (getType(obj) == "Dimension") or (force == "Dimension"):
|
||||||
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
|
_Dimension(newobj)
|
||||||
|
_ViewProviderDimension(newobj.ViewObject)
|
||||||
|
elif (getType(obj) == "Wire") or (force == "Wire"):
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
_Wire(newobj)
|
_Wire(newobj)
|
||||||
_ViewProviderWire(newobj.ViewObject)
|
_ViewProviderWire(newobj.ViewObject)
|
||||||
elif getType(obj) == "Circle":
|
elif (getType(obj) == "Circle") or (force == "Circle"):
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
_Circle(newobj)
|
_Circle(newobj)
|
||||||
_ViewProviderCircle(newobj.ViewObject)
|
_ViewProviderDraft(newobj.ViewObject)
|
||||||
elif getType(obj) == "Polygon":
|
elif (getType(obj) == "Polygon") or (force == "Polygon"):
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
_Polygon(newobj)
|
_Polygon(newobj)
|
||||||
_ViewProviderPolygon(newobj.ViewObject)
|
_ViewProviderPolygon(newobj.ViewObject)
|
||||||
elif getType(obj) == "BSpline":
|
elif (getType(obj) == "BSpline") or (force == "BSpline"):
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
_BSpline(newobj)
|
_BSpline(newobj)
|
||||||
_ViewProviderBSpline(newobj.ViewObject)
|
_ViewProviderBSpline(newobj.ViewObject)
|
||||||
elif getType(obj) == "Block":
|
elif (getType(obj) == "Block") or (force == "BSpline"):
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
_Block(newobj)
|
_Block(newobj)
|
||||||
_ViewProviderDraftPart(newobj.ViewObject)
|
_ViewProviderDraftPart(newobj.ViewObject)
|
||||||
elif getType(obj) == "Structure":
|
elif (getType(obj) == "Structure") or (force == "Structure"):
|
||||||
import ArchStructure
|
import ArchStructure
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
ArchStructure._Structure(newobj)
|
ArchStructure._Structure(newobj)
|
||||||
ArchStructure._ViewProviderStructure(newobj.ViewObject)
|
ArchStructure._ViewProviderStructure(newobj.ViewObject)
|
||||||
elif getType(obj) == "Wall":
|
elif (getType(obj) == "Wall") or (force == "Wall"):
|
||||||
import ArchWall
|
import ArchWall
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
ArchWall._Wall(newobj)
|
ArchWall._Wall(newobj)
|
||||||
ArchWall._ViewProviderWall(newobj.ViewObject)
|
ArchWall._ViewProviderWall(newobj.ViewObject)
|
||||||
elif getType(obj) == "Window":
|
elif (getType(obj) == "Window") or (force == "Window"):
|
||||||
import ArchWindow
|
import ArchWindow
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
ArchWindow._Window(newobj)
|
ArchWindow._Window(newobj)
|
||||||
Archwindow._ViewProviderWindow(newobj.ViewObject)
|
Archwindow._ViewProviderWindow(newobj.ViewObject)
|
||||||
elif getType(obj) == "Cell":
|
elif (getType(obj) == "Cell") or (force == "Cell"):
|
||||||
import ArchCell
|
import ArchCell
|
||||||
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject(obj.Type,getRealName(obj.Name))
|
||||||
ArchCell._Cell(newobj)
|
ArchCell._Cell(newobj)
|
||||||
|
@ -569,8 +566,19 @@ def makeCopy(obj):
|
||||||
print "Error: Object type cannot be copied"
|
print "Error: Object type cannot be copied"
|
||||||
return None
|
return None
|
||||||
for p in obj.PropertiesList:
|
for p in obj.PropertiesList:
|
||||||
|
if not p in ["Proxy"]:
|
||||||
if p in newobj.PropertiesList:
|
if p in newobj.PropertiesList:
|
||||||
setattr(newobj,p,obj.getPropertyByName(p))
|
setattr(newobj,p,obj.getPropertyByName(p))
|
||||||
|
if reparent:
|
||||||
|
parents = obj.InList
|
||||||
|
if parents:
|
||||||
|
for par in parents:
|
||||||
|
if par.Type == "App::DocumentObjectGroup":
|
||||||
|
par.addObject(newobj)
|
||||||
|
else:
|
||||||
|
for prop in par.PropertiesList:
|
||||||
|
if getattr(par,prop) == obj:
|
||||||
|
setattr(par,prop,newobj)
|
||||||
formatObject(newobj,obj)
|
formatObject(newobj,obj)
|
||||||
return newobj
|
return newobj
|
||||||
|
|
||||||
|
@ -685,7 +693,7 @@ def move(objectslist,vector,copy=False):
|
||||||
if copy:
|
if copy:
|
||||||
newobj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",getRealName(obj.Name))
|
newobj = FreeCAD.ActiveDocument.addObject("App::FeaturePython",getRealName(obj.Name))
|
||||||
_Dimension(newobj)
|
_Dimension(newobj)
|
||||||
_DimensionViewProvider(newobj.ViewObject)
|
_ViewProviderDimension(newobj.ViewObject)
|
||||||
else:
|
else:
|
||||||
newobj = obj
|
newobj = obj
|
||||||
newobj.Start = obj.Start.add(vector)
|
newobj.Start = obj.Start.add(vector)
|
||||||
|
@ -1402,6 +1410,57 @@ def clone(obj,delta=None):
|
||||||
cl.Placement.move(delta)
|
cl.Placement.move(delta)
|
||||||
return cl
|
return cl
|
||||||
|
|
||||||
|
def heal(objlist=None,delete=True,reparent=True):
|
||||||
|
'''heal([objlist],[delete],[reparent]) - recreates Draft objects that are damaged,
|
||||||
|
for example if created from an earlier version. If delete is True,
|
||||||
|
the damaged objects are deleted (default). If ran without arguments, all the objects
|
||||||
|
in the document will be healed if they are damaged. If reparent is True (default),
|
||||||
|
new objects go at the very same place in the tree than their original.'''
|
||||||
|
|
||||||
|
if not objlist:
|
||||||
|
objlist = FreeCAD.ActiveDocument.Objects
|
||||||
|
print "Healing whole document..."
|
||||||
|
|
||||||
|
if not isinstance(objlist,list):
|
||||||
|
objlist = [objlist]
|
||||||
|
|
||||||
|
dellist = []
|
||||||
|
got = False
|
||||||
|
|
||||||
|
for obj in objlist:
|
||||||
|
dtype = getType(obj)
|
||||||
|
ftype = obj.Type
|
||||||
|
if ftype in ["Part::FeaturePython","App::FeaturePython"]:
|
||||||
|
if obj.ViewObject.Proxy == 1 and dtype in ["Unknown","Part"]:
|
||||||
|
got = True
|
||||||
|
dellist.append(obj.Name)
|
||||||
|
props = obj.PropertiesList
|
||||||
|
if ("Dimline" in props) and ("Start" in props):
|
||||||
|
print "Healing " + obj.Name + " of type Dimension"
|
||||||
|
nobj = makeCopy(obj,force="Dimension",reparent=reparent)
|
||||||
|
elif ("Height" in props) and ("Length" in props):
|
||||||
|
print "Healing " + obj.Name + " of type Rectangle"
|
||||||
|
nobj = makeCopy(obj,force="Rectangle",reparent=reparent)
|
||||||
|
elif ("Points" in props) and ("Closed" in props):
|
||||||
|
print "Healing " + obj.Name + " of type Wire"
|
||||||
|
nobj = makeCopy(obj,force="Wire",reparent=reparent)
|
||||||
|
elif ("Radius" in props) and ("FirstAngle" in props):
|
||||||
|
print "Healing " + obj.Name + " of type Circle"
|
||||||
|
nobj = makeCopy(obj,force="Circle",reparent=reparent)
|
||||||
|
else:
|
||||||
|
dellist.pop()
|
||||||
|
print "Object " + obj.Name + " is not healable"
|
||||||
|
|
||||||
|
if not got:
|
||||||
|
print "No object seems to need healing"
|
||||||
|
else:
|
||||||
|
print "Healed ",len(dellist)," objects"
|
||||||
|
|
||||||
|
if dellist and delete:
|
||||||
|
for n in dellist:
|
||||||
|
FreeCAD.ActiveDocument.removeObject(n)
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Python Features definitions
|
# Python Features definitions
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
@ -1539,10 +1598,13 @@ class _ViewProviderDimension:
|
||||||
if hasattr(obj.ViewObject,"DisplayMode"):
|
if hasattr(obj.ViewObject,"DisplayMode"):
|
||||||
if obj.ViewObject.DisplayMode == "3D":
|
if obj.ViewObject.DisplayMode == "3D":
|
||||||
offset = fcvec.neg(offset)
|
offset = fcvec.neg(offset)
|
||||||
|
if hasattr(obj.ViewObject,"TextPosition"):
|
||||||
if obj.ViewObject.TextPosition == Vector(0,0,0):
|
if obj.ViewObject.TextPosition == Vector(0,0,0):
|
||||||
tbase = midpoint.add(offset)
|
tbase = midpoint.add(offset)
|
||||||
else:
|
else:
|
||||||
tbase = obj.ViewObject.TextPosition
|
tbase = obj.ViewObject.TextPosition
|
||||||
|
else:
|
||||||
|
tbase = midpoint.add(offset)
|
||||||
rot = FreeCAD.Placement(fcvec.getPlaneRotation(u,v,norm)).Rotation.Q
|
rot = FreeCAD.Placement(fcvec.getPlaneRotation(u,v,norm)).Rotation.Q
|
||||||
return p1,p2,p3,p4,tbase,norm,rot
|
return p1,p2,p3,p4,tbase,norm,rot
|
||||||
|
|
||||||
|
@ -1966,6 +2028,7 @@ class _Rectangle:
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
obj.addProperty("App::PropertyDistance","Length","Base","Length of the rectangle")
|
obj.addProperty("App::PropertyDistance","Length","Base","Length of the rectangle")
|
||||||
obj.addProperty("App::PropertyDistance","Height","Base","Height of the rectange")
|
obj.addProperty("App::PropertyDistance","Height","Base","Height of the rectange")
|
||||||
|
obj.addProperty("App::PropertyDistance","FilletRadius","Base","Radius to use to fillet the corners")
|
||||||
obj.Proxy = self
|
obj.Proxy = self
|
||||||
obj.Length=1
|
obj.Length=1
|
||||||
obj.Height=1
|
obj.Height=1
|
||||||
|
@ -1980,12 +2043,18 @@ class _Rectangle:
|
||||||
|
|
||||||
def createGeometry(self,fp):
|
def createGeometry(self,fp):
|
||||||
import Part
|
import Part
|
||||||
|
from draftlibs import fcgeo
|
||||||
plm = fp.Placement
|
plm = fp.Placement
|
||||||
p1 = Vector(0,0,0)
|
p1 = Vector(0,0,0)
|
||||||
p2 = Vector(p1.x+fp.Length,p1.y,p1.z)
|
p2 = Vector(p1.x+fp.Length,p1.y,p1.z)
|
||||||
p3 = Vector(p1.x+fp.Length,p1.y+fp.Height,p1.z)
|
p3 = Vector(p1.x+fp.Length,p1.y+fp.Height,p1.z)
|
||||||
p4 = Vector(p1.x,p1.y+fp.Height,p1.z)
|
p4 = Vector(p1.x,p1.y+fp.Height,p1.z)
|
||||||
shape = Part.makePolygon([p1,p2,p3,p4,p1])
|
shape = Part.makePolygon([p1,p2,p3,p4,p1])
|
||||||
|
if "FilletRadius" in fp.PropertiesList:
|
||||||
|
if fp.FilletRadius != 0:
|
||||||
|
w = fcgeo.filletWire(shape,fp.FilletRadius)
|
||||||
|
if w:
|
||||||
|
shape = w
|
||||||
shape = Part.Face(shape)
|
shape = Part.Face(shape)
|
||||||
fp.Shape = shape
|
fp.Shape = shape
|
||||||
fp.Placement = plm
|
fp.Placement = plm
|
||||||
|
@ -2017,9 +2086,9 @@ class _Circle:
|
||||||
"The Circle object"
|
"The Circle object"
|
||||||
|
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
obj.addProperty("App::PropertyAngle","FirstAngle","Arc",
|
obj.addProperty("App::PropertyAngle","FirstAngle","Base",
|
||||||
"Start angle of the arc")
|
"Start angle of the arc")
|
||||||
obj.addProperty("App::PropertyAngle","LastAngle","Arc",
|
obj.addProperty("App::PropertyAngle","LastAngle","Base",
|
||||||
"End angle of the arc (for a full circle, give it same value as First Angle)")
|
"End angle of the arc (for a full circle, give it same value as First Angle)")
|
||||||
obj.addProperty("App::PropertyDistance","Radius","Base",
|
obj.addProperty("App::PropertyDistance","Radius","Base",
|
||||||
"Radius of the circle")
|
"Radius of the circle")
|
||||||
|
@ -2060,6 +2129,7 @@ class _Wire:
|
||||||
"The start point of this line")
|
"The start point of this line")
|
||||||
obj.addProperty("App::PropertyVector","End","Base",
|
obj.addProperty("App::PropertyVector","End","Base",
|
||||||
"The end point of this line")
|
"The end point of this line")
|
||||||
|
obj.addProperty("App::PropertyDistance","FilletRadius","Base","Radius to use to fillet the corners")
|
||||||
obj.Proxy = self
|
obj.Proxy = self
|
||||||
obj.Closed = False
|
obj.Closed = False
|
||||||
self.Type = "Wire"
|
self.Type = "Wire"
|
||||||
|
@ -2068,7 +2138,7 @@ class _Wire:
|
||||||
self.createGeometry(fp)
|
self.createGeometry(fp)
|
||||||
|
|
||||||
def onChanged(self, fp, prop):
|
def onChanged(self, fp, prop):
|
||||||
if prop in ["Points","Closed","Base","Tool"]:
|
if prop in ["Points","Closed","Base","Tool","FilletRadius"]:
|
||||||
self.createGeometry(fp)
|
self.createGeometry(fp)
|
||||||
if prop == "Points":
|
if prop == "Points":
|
||||||
if fp.Start != fp.Points[0]:
|
if fp.Start != fp.Points[0]:
|
||||||
|
@ -2121,6 +2191,11 @@ class _Wire:
|
||||||
fp.Points.pop()
|
fp.Points.pop()
|
||||||
if fp.Closed and (len(fp.Points) > 2):
|
if fp.Closed and (len(fp.Points) > 2):
|
||||||
shape = Part.makePolygon(fp.Points+[fp.Points[0]])
|
shape = Part.makePolygon(fp.Points+[fp.Points[0]])
|
||||||
|
if "FilletRadius" in fp.PropertiesList:
|
||||||
|
if fp.FilletRadius != 0:
|
||||||
|
w = fcgeo.filletWire(shape,fp.FilletRadius)
|
||||||
|
if w:
|
||||||
|
shape = w
|
||||||
shape = Part.Face(shape)
|
shape = Part.Face(shape)
|
||||||
else:
|
else:
|
||||||
edges = []
|
edges = []
|
||||||
|
@ -2130,6 +2205,11 @@ class _Wire:
|
||||||
edges.append(Part.Line(lp,p).toShape())
|
edges.append(Part.Line(lp,p).toShape())
|
||||||
lp = p
|
lp = p
|
||||||
shape = Part.Wire(edges)
|
shape = Part.Wire(edges)
|
||||||
|
if "FilletRadius" in fp.PropertiesList:
|
||||||
|
if fp.FilletRadius != 0:
|
||||||
|
w = fcgeo.filletWire(shape,fp.FilletRadius)
|
||||||
|
if w:
|
||||||
|
shape = w
|
||||||
fp.Shape = shape
|
fp.Shape = shape
|
||||||
fp.Placement = plm
|
fp.Placement = plm
|
||||||
|
|
||||||
|
@ -2178,6 +2258,7 @@ class _Polygon:
|
||||||
obj.addProperty("App::PropertyInteger","FacesNumber","Base","Number of faces")
|
obj.addProperty("App::PropertyInteger","FacesNumber","Base","Number of faces")
|
||||||
obj.addProperty("App::PropertyDistance","Radius","Base","Radius of the control circle")
|
obj.addProperty("App::PropertyDistance","Radius","Base","Radius of the control circle")
|
||||||
obj.addProperty("App::PropertyEnumeration","DrawMode","Base","How the polygon must be drawn from the control circle")
|
obj.addProperty("App::PropertyEnumeration","DrawMode","Base","How the polygon must be drawn from the control circle")
|
||||||
|
obj.addProperty("App::PropertyDistance","FilletRadius","Base","Radius to use to fillet the corners")
|
||||||
obj.DrawMode = ['inscribed','circumscribed']
|
obj.DrawMode = ['inscribed','circumscribed']
|
||||||
obj.FacesNumber = 3
|
obj.FacesNumber = 3
|
||||||
obj.Radius = 1
|
obj.Radius = 1
|
||||||
|
@ -2193,6 +2274,7 @@ class _Polygon:
|
||||||
|
|
||||||
def createGeometry(self,fp):
|
def createGeometry(self,fp):
|
||||||
import Part
|
import Part
|
||||||
|
from draftlibs import fcgeo
|
||||||
plm = fp.Placement
|
plm = fp.Placement
|
||||||
angle = (math.pi*2)/fp.FacesNumber
|
angle = (math.pi*2)/fp.FacesNumber
|
||||||
if fp.DrawMode == 'inscribed':
|
if fp.DrawMode == 'inscribed':
|
||||||
|
@ -2205,6 +2287,11 @@ class _Polygon:
|
||||||
pts.append(Vector(delta*math.cos(ang),delta*math.sin(ang),0))
|
pts.append(Vector(delta*math.cos(ang),delta*math.sin(ang),0))
|
||||||
pts.append(pts[0])
|
pts.append(pts[0])
|
||||||
shape = Part.makePolygon(pts)
|
shape = Part.makePolygon(pts)
|
||||||
|
if "FilletRadius" in fp.PropertiesList:
|
||||||
|
if fp.FilletRadius != 0:
|
||||||
|
w = fcgeo.filletWire(shape,fp.FilletRadius)
|
||||||
|
if w:
|
||||||
|
shape = w
|
||||||
shape = Part.Face(shape)
|
shape = Part.Face(shape)
|
||||||
fp.Shape = shape
|
fp.Shape = shape
|
||||||
fp.Placement = plm
|
fp.Placement = plm
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -356,6 +356,43 @@ If color mapping is choosed, you must choose a color mapping file containing a t
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Export Style</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Gui::PrefComboBox" name="svg_export_style_combobox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Style of SVG file to write when exporting a Sketch.</string>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="prefEntry" stdset="0">
|
||||||
|
<cstring>svg_export_style</cstring>
|
||||||
|
</property>
|
||||||
|
<property name="prefPath" stdset="0">
|
||||||
|
<cstring>Mod/Draft</cstring>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Translated (for print & display)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Raw (for CAM)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -1196,6 +1196,280 @@ def arcFromSpline(edge):
|
||||||
except:
|
except:
|
||||||
print "couldn't make a circle out of this edge"
|
print "couldn't make a circle out of this edge"
|
||||||
|
|
||||||
|
# Fillet code graciously donated by Jacques-Antoine Gaudin
|
||||||
|
|
||||||
|
def fillet(lEdges,r):
|
||||||
|
''' Take a list of two Edges & a float as argument,
|
||||||
|
Returns a list of sorted edges describing a round corner'''
|
||||||
|
|
||||||
|
def getCurveType(edge,existingCurveType = None):
|
||||||
|
'''Builds or completes a dictionnary containing edges with keys "Arc" and "Line"'''
|
||||||
|
if not existingCurveType :
|
||||||
|
existingCurveType = { 'Line' : [], 'Arc' : [] }
|
||||||
|
if issubclass(type(edge.Curve),Part.Line) :
|
||||||
|
existingCurveType['Line'] += [edge]
|
||||||
|
elif issubclass(type(edge.Curve),Part.Circle) :
|
||||||
|
existingCurveType['Arc'] += [edge]
|
||||||
|
else :
|
||||||
|
raise Exception("Edge's curve must be either Line or Arc")
|
||||||
|
return existingCurveType
|
||||||
|
|
||||||
|
rndEdges = lEdges[0:2]
|
||||||
|
rndEdges = sortEdges(rndEdges)
|
||||||
|
|
||||||
|
if len(rndEdges) < 2 :
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
if r <= 0 :
|
||||||
|
print "fcgeo.fillet : Error : radius is negative."
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
curveType = getCurveType(rndEdges[0])
|
||||||
|
curveType = getCurveType(rndEdges[1],curveType)
|
||||||
|
|
||||||
|
lVertexes = rndEdges[0].Vertexes + [rndEdges[1].Vertexes[-1]]
|
||||||
|
|
||||||
|
if len(curveType['Line']) == 2:
|
||||||
|
|
||||||
|
# Deals with 2-line-edges lists --------------------------------------
|
||||||
|
|
||||||
|
U1 = lVertexes[0].Point.sub(lVertexes[1].Point) ; U1.normalize()
|
||||||
|
U2 = lVertexes[2].Point.sub(lVertexes[1].Point) ; U2.normalize()
|
||||||
|
alpha = U1.getAngle(U2)
|
||||||
|
|
||||||
|
if round(alpha,precision) == 0 or round(alpha - math.pi,precision) == 0: # Edges have same direction
|
||||||
|
print "fcgeo.fillet : Warning : edges have same direction. Did nothing"
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
dToCenter = r / math.sin(alpha/2.)
|
||||||
|
dToTangent = (dToCenter**2-r**2)**(0.5)
|
||||||
|
dirVect = Vector(U1) ; dirVect.scale(dToTangent,dToTangent,dToTangent)
|
||||||
|
arcPt1 = lVertexes[1].Point.add(dirVect)
|
||||||
|
|
||||||
|
dirVect = U2.add(U1) ; dirVect.normalize()
|
||||||
|
dirVect.scale(dToCenter-r,dToCenter-r,dToCenter-r)
|
||||||
|
arcPt2 = lVertexes[1].Point.add(dirVect)
|
||||||
|
|
||||||
|
dirVect = Vector(U2) ; dirVect.scale(dToTangent,dToTangent,dToTangent)
|
||||||
|
arcPt3 = lVertexes[1].Point.add(dirVect)
|
||||||
|
|
||||||
|
if (dToTangent>lEdges[0].Length) or (dToTangent>lEdges[1].Length) :
|
||||||
|
print "fcgeo.fillet : Error : radius value ", r," is too high"
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
rndEdges[1] = Part.Edge(Part.Arc(arcPt1,arcPt2,arcPt3))
|
||||||
|
rndEdges[0] = Part.Edge(Part.Line(lVertexes[0].Point,arcPt1))
|
||||||
|
rndEdges += [Part.Edge(Part.Line(arcPt3,lVertexes[2].Point))]
|
||||||
|
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
elif len(curveType['Arc']) == 1 :
|
||||||
|
|
||||||
|
# Deals with lists containing an arc and a line ----------------------------------
|
||||||
|
|
||||||
|
if lEdges[0] in curveType['Arc'] :
|
||||||
|
lineEnd = lVertexes[2] ; arcEnd = lVertexes[0] ; arcFirst = True
|
||||||
|
else :
|
||||||
|
lineEnd = lVertexes[0] ; arcEnd = lVertexes[2] ; arcFirst = False
|
||||||
|
arcCenter = curveType['Arc'][0].Curve.Center
|
||||||
|
arcRadius = curveType['Arc'][0].Curve.Radius
|
||||||
|
arcAxis = curveType['Arc'][0].Curve.Axis
|
||||||
|
arcLength = curveType['Arc'][0].Length
|
||||||
|
|
||||||
|
U1 = lineEnd.Point.sub(lVertexes[1].Point) ; U1.normalize()
|
||||||
|
toCenter = arcCenter.sub(lVertexes[1].Point)
|
||||||
|
if arcFirst : # make sure the tangent points towards the arc
|
||||||
|
T = arcAxis.cross(toCenter)
|
||||||
|
else :
|
||||||
|
T = toCenter.cross(arcAxis)
|
||||||
|
|
||||||
|
projCenter = toCenter.dot(U1)
|
||||||
|
if round(abs(projCenter),precision) > 0 :
|
||||||
|
normToLine = U1.cross(T).cross(U1)
|
||||||
|
else :
|
||||||
|
normToLine = Vector(toCenter)
|
||||||
|
normToLine.normalize()
|
||||||
|
|
||||||
|
dCenterToLine = toCenter.dot(normToLine) - r
|
||||||
|
|
||||||
|
if round(projCenter,precision) > 0 :
|
||||||
|
newRadius = arcRadius - r
|
||||||
|
elif round(projCenter,precision) < 0 or (round(projCenter,precision) == 0 and U1.dot(T) > 0):
|
||||||
|
newRadius = arcRadius + r
|
||||||
|
else :
|
||||||
|
print "fcgeo.fillet : Warning : edges are already tangent. Did nothing"
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
toNewCent = newRadius**2-dCenterToLine**2
|
||||||
|
if toNewCent > 0 :
|
||||||
|
toNewCent = abs(abs(projCenter) - toNewCent**(0.5))
|
||||||
|
else :
|
||||||
|
print "fcgeo.fillet : Error : radius value ", r," is too high"
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
U1.scale(toNewCent,toNewCent,toNewCent)
|
||||||
|
normToLine.scale(r,r,r)
|
||||||
|
newCent = lVertexes[1].Point.add(U1).add(normToLine)
|
||||||
|
|
||||||
|
arcPt1= lVertexes[1].Point.add(U1)
|
||||||
|
arcPt2= lVertexes[1].Point.sub(newCent); arcPt2.normalize()
|
||||||
|
arcPt2.scale(r,r,r) ; arcPt2 = arcPt2.add(newCent)
|
||||||
|
if newRadius == arcRadius - r :
|
||||||
|
arcPt3= newCent.sub(arcCenter)
|
||||||
|
else :
|
||||||
|
arcPt3= arcCenter.sub(newCent)
|
||||||
|
arcPt3.normalize()
|
||||||
|
arcPt3.scale(r,r,r) ; arcPt3 = arcPt3.add(newCent)
|
||||||
|
arcPt = [arcPt1,arcPt2,arcPt3]
|
||||||
|
|
||||||
|
|
||||||
|
# Warning : In the following I used a trick for calling the right element
|
||||||
|
# in arcPt or V : arcFirst is a boolean so - not arcFirst is -0 or -1
|
||||||
|
# list[-1] is the last element of a list and list[0] the first
|
||||||
|
# this way I don't have to proceed tests to know the position of the arc
|
||||||
|
|
||||||
|
myTrick = not arcFirst
|
||||||
|
|
||||||
|
V = [arcPt3]
|
||||||
|
V += [arcEnd.Point]
|
||||||
|
|
||||||
|
toCenter.scale(-1,-1,-1)
|
||||||
|
|
||||||
|
delLength = arcRadius * V[0].sub(arcCenter).getAngle(toCenter)
|
||||||
|
if delLength > arcLength or toNewCent > curveType['Line'][0].Length:
|
||||||
|
print "fcgeo.fillet : Error : radius value ", r," is too high"
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
arcAsEdge = arcFrom2Pts(V[-arcFirst],V[-myTrick],arcCenter,arcAxis)
|
||||||
|
|
||||||
|
V = [lineEnd.Point,arcPt1]
|
||||||
|
lineAsEdge = Part.Edge(Part.Line(V[-arcFirst],V[myTrick]))
|
||||||
|
|
||||||
|
rndEdges[not arcFirst] = arcAsEdge
|
||||||
|
rndEdges[arcFirst] = lineAsEdge
|
||||||
|
rndEdges[1:1] = [Part.Edge(Part.Arc(arcPt[- arcFirst],arcPt[1],arcPt[- myTrick]))]
|
||||||
|
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
elif len(curveType['Arc']) == 2 :
|
||||||
|
|
||||||
|
# Deals with lists of 2 arc-edges --------------------------------------------
|
||||||
|
|
||||||
|
arcCenter, arcRadius, arcAxis, arcLength, toCenter, T, newRadius = [], [], [], [], [], [], []
|
||||||
|
for i in range(2) :
|
||||||
|
arcCenter += [curveType['Arc'][i].Curve.Center]
|
||||||
|
arcRadius += [curveType['Arc'][i].Curve.Radius]
|
||||||
|
arcAxis += [curveType['Arc'][i].Curve.Axis]
|
||||||
|
arcLength += [curveType['Arc'][i].Length]
|
||||||
|
toCenter += [arcCenter[i].sub(lVertexes[1].Point)]
|
||||||
|
T += [arcAxis[0].cross(toCenter[0])]
|
||||||
|
T += [toCenter[1].cross(arcAxis[1])]
|
||||||
|
CentToCent = toCenter[1].sub(toCenter[0])
|
||||||
|
dCentToCent = CentToCent.Length
|
||||||
|
|
||||||
|
sameDirection = (arcAxis[0].dot(arcAxis[1]) > 0)
|
||||||
|
TcrossT = T[0].cross(T[1])
|
||||||
|
if sameDirection :
|
||||||
|
if round(TcrossT.dot(arcAxis[0]),precision) > 0 :
|
||||||
|
newRadius += [arcRadius[0]+r]
|
||||||
|
newRadius += [arcRadius[1]+r]
|
||||||
|
elif round(TcrossT.dot(arcAxis[0]),precision) < 0 :
|
||||||
|
newRadius += [arcRadius[0]-r]
|
||||||
|
newRadius += [arcRadius[1]-r]
|
||||||
|
elif T[0].dot(T[1]) > 0 :
|
||||||
|
newRadius += [arcRadius[0]+r]
|
||||||
|
newRadius += [arcRadius[1]+r]
|
||||||
|
else :
|
||||||
|
print "fcgeo.fillet : Warning : edges are already tangent. Did nothing"
|
||||||
|
return rndEdges
|
||||||
|
elif not sameDirection :
|
||||||
|
if round(TcrossT.dot(arcAxis[0]),precision) > 0 :
|
||||||
|
newRadius += [arcRadius[0]+r]
|
||||||
|
newRadius += [arcRadius[1]-r]
|
||||||
|
elif round(TcrossT.dot(arcAxis[0]),precision) < 0 :
|
||||||
|
newRadius += [arcRadius[0]-r]
|
||||||
|
newRadius += [arcRadius[1]+r]
|
||||||
|
elif T[0].dot(T[1]) > 0 :
|
||||||
|
if arcRadius[0] > arcRadius[1] :
|
||||||
|
newRadius += [arcRadius[0]-r]
|
||||||
|
newRadius += [arcRadius[1]+r]
|
||||||
|
elif arcRadius[1] > arcRadius[0] :
|
||||||
|
newRadius += [arcRadius[0]+r]
|
||||||
|
newRadius += [arcRadius[1]-r]
|
||||||
|
else :
|
||||||
|
print "fcgeo.fillet : Warning : arcs are coincident. Did nothing"
|
||||||
|
return rndEdges
|
||||||
|
else :
|
||||||
|
print "fcgeo.fillet : Warning : edges are already tangent. Did nothing"
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
if newRadius[0]+newRadius[1] < dCentToCent or \
|
||||||
|
newRadius[0]-newRadius[1] > dCentToCent or \
|
||||||
|
newRadius[1]-newRadius[0] > dCentToCent :
|
||||||
|
print "fcgeo.fillet : Error : radius value ", r," is too high"
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
x = (dCentToCent**2+newRadius[0]**2-newRadius[1]**2)/(2*dCentToCent)
|
||||||
|
y = (newRadius[0]**2-x**2)**(0.5)
|
||||||
|
|
||||||
|
CentToCent.normalize() ; toCenter[0].normalize() ; toCenter[1].normalize()
|
||||||
|
if abs(toCenter[0].dot(toCenter[1])) != 1 :
|
||||||
|
normVect = CentToCent.cross(CentToCent.cross(toCenter[0]))
|
||||||
|
else :
|
||||||
|
normVect = T[0]
|
||||||
|
normVect.normalize()
|
||||||
|
CentToCent.scale(x,x,x) ; normVect.scale(y,y,y)
|
||||||
|
newCent = arcCenter[0].add(CentToCent.add(normVect))
|
||||||
|
CentToNewCent = [newCent.sub(arcCenter[0]),newCent.sub(arcCenter[1])]
|
||||||
|
for i in range(2) :
|
||||||
|
CentToNewCent[i].normalize()
|
||||||
|
if newRadius[i] == arcRadius[i]+r :
|
||||||
|
CentToNewCent[i].scale(-r,-r,-r)
|
||||||
|
else :
|
||||||
|
CentToNewCent[i].scale(r,r,r)
|
||||||
|
toThirdPt = lVertexes[1].Point.sub(newCent) ; toThirdPt.normalize()
|
||||||
|
toThirdPt.scale(r,r,r)
|
||||||
|
arcPt1 = newCent.add(CentToNewCent[0])
|
||||||
|
arcPt2 = newCent.add(toThirdPt)
|
||||||
|
arcPt3 = newCent.add(CentToNewCent[1])
|
||||||
|
arcPt = [arcPt1,arcPt2,arcPt3]
|
||||||
|
|
||||||
|
arcAsEdge = []
|
||||||
|
for i in range(2) :
|
||||||
|
toCenter[i].scale(-1,-1,-1)
|
||||||
|
delLength = arcRadius[i] * arcPt[-i].sub(arcCenter[i]).getAngle(toCenter[i])
|
||||||
|
if delLength > arcLength[i] :
|
||||||
|
print "fcgeo.fillet : Error : radius value ", r," is too high"
|
||||||
|
return rndEdges
|
||||||
|
V = [arcPt[-i],lVertexes[-i].Point]
|
||||||
|
arcAsEdge += [arcFrom2Pts(V[i-1],V[-i],arcCenter[i],arcAxis[i])]
|
||||||
|
|
||||||
|
rndEdges[0] = arcAsEdge[0]
|
||||||
|
rndEdges[1] = arcAsEdge[1]
|
||||||
|
rndEdges[1:1] = [Part.Edge(Part.Arc(arcPt[0],arcPt[1],arcPt[2]))]
|
||||||
|
|
||||||
|
return rndEdges
|
||||||
|
|
||||||
|
def filletWire(aWire,r,makeClosed=True):
|
||||||
|
''' Fillets each angle of a wire with r as radius value'''
|
||||||
|
|
||||||
|
edges = aWire.Edges
|
||||||
|
edges = sortEdges(edges)
|
||||||
|
filEdges = [edges[0]]
|
||||||
|
for i in range(len(edges)-1):
|
||||||
|
result = fillet([filEdges[-1],edges[i+1]],r)
|
||||||
|
if len(result)>2:
|
||||||
|
filEdges[-1:] = result[0:3]
|
||||||
|
else :
|
||||||
|
filEdges[-1:] = result[0:2]
|
||||||
|
if isReallyClosed(aWire) and makeClosed :
|
||||||
|
result = fillet([filEdges[-1],filEdges[0]],r)
|
||||||
|
if len(result)>2:
|
||||||
|
filEdges[-1:] = result[0:2]
|
||||||
|
filEdges[0] = result[2]
|
||||||
|
return Part.Wire(filEdges)
|
||||||
|
|
||||||
|
|
||||||
# circle functions *********************************************************
|
# circle functions *********************************************************
|
||||||
|
|
||||||
def getBoundaryAngles(angle,alist):
|
def getBoundaryAngles(angle,alist):
|
||||||
|
|
|
@ -28,12 +28,15 @@ __url__ = ["http://free-cad.sourceforge.net"]
|
||||||
'''
|
'''
|
||||||
This script imports SVG files in FreeCAD. Currently only reads the following entities:
|
This script imports SVG files in FreeCAD. Currently only reads the following entities:
|
||||||
paths, lines, circular arcs ,rects, circles, ellipses, polygons, polylines.
|
paths, lines, circular arcs ,rects, circles, ellipses, polygons, polylines.
|
||||||
currently unsupported: image, rounded rect(rx,ry), elliptical arcs
|
currently unsupported: use, image
|
||||||
'''
|
'''
|
||||||
#ToDo:
|
#ToDo:
|
||||||
# elliptical arc segments
|
|
||||||
# rounded rects (elliptical arcs)
|
|
||||||
# ignoring CDATA
|
# ignoring CDATA
|
||||||
|
# handle image element (external references and inline base64)
|
||||||
|
# debug Problem with 'Sans' font from Inkscape
|
||||||
|
# debug Problem with fill color
|
||||||
|
# implement inherting fill style from group
|
||||||
|
# handle viewbox and units
|
||||||
|
|
||||||
import xml.sax, string, FreeCAD, os, math, re, Draft
|
import xml.sax, string, FreeCAD, os, math, re, Draft
|
||||||
from draftlibs import fcvec
|
from draftlibs import fcvec
|
||||||
|
@ -48,154 +51,154 @@ except: draftui = None
|
||||||
pythonopen = open
|
pythonopen = open
|
||||||
|
|
||||||
svgcolors = {
|
svgcolors = {
|
||||||
'Pink': [255, 192, 203],
|
'Pink': (255, 192, 203),
|
||||||
'Blue': [0, 0, 255],
|
'Blue': (0, 0, 255),
|
||||||
'Honeydew': [240, 255, 240],
|
'Honeydew': (240, 255, 240),
|
||||||
'Purple': [128, 0, 128],
|
'Purple': (128, 0, 128),
|
||||||
'Fuchsia': [255, 0, 255],
|
'Fuchsia': (255, 0, 255),
|
||||||
'LawnGreen': [124, 252, 0],
|
'LawnGreen': (124, 252, 0),
|
||||||
'Amethyst': [153, 102, 204],
|
'Amethyst': (153, 102, 204),
|
||||||
'Crimson': [220, 20, 60],
|
'Crimson': (220, 20, 60),
|
||||||
'White': [255, 255, 255],
|
'White': (255, 255, 255),
|
||||||
'NavajoWhite': [255, 222, 173],
|
'NavajoWhite': (255, 222, 173),
|
||||||
'Cornsilk': [255, 248, 220],
|
'Cornsilk': (255, 248, 220),
|
||||||
'Bisque': [255, 228, 196],
|
'Bisque': (255, 228, 196),
|
||||||
'PaleGreen': [152, 251, 152],
|
'PaleGreen': (152, 251, 152),
|
||||||
'Brown': [165, 42, 42],
|
'Brown': (165, 42, 42),
|
||||||
'DarkTurquoise': [0, 206, 209],
|
'DarkTurquoise': (0, 206, 209),
|
||||||
'DarkGreen': [0, 100, 0],
|
'DarkGreen': (0, 100, 0),
|
||||||
'MediumOrchid': [186, 85, 211],
|
'MediumOrchid': (186, 85, 211),
|
||||||
'Chocolate': [210, 105, 30],
|
'Chocolate': (210, 105, 30),
|
||||||
'PapayaWhip': [255, 239, 213],
|
'PapayaWhip': (255, 239, 213),
|
||||||
'Olive': [128, 128, 0],
|
'Olive': (128, 128, 0),
|
||||||
'Silver': [192, 192, 192],
|
'Silver': (192, 192, 192),
|
||||||
'PeachPuff': [255, 218, 185],
|
'PeachPuff': (255, 218, 185),
|
||||||
'Plum': [221, 160, 221],
|
'Plum': (221, 160, 221),
|
||||||
'DarkGoldenrod': [184, 134, 11],
|
'DarkGoldenrod': (184, 134, 11),
|
||||||
'SlateGrey': [112, 128, 144],
|
'SlateGrey': (112, 128, 144),
|
||||||
'MintCream': [245, 255, 250],
|
'MintCream': (245, 255, 250),
|
||||||
'CornflowerBlue': [100, 149, 237],
|
'CornflowerBlue': (100, 149, 237),
|
||||||
'Gold': [255, 215, 0],
|
'Gold': (255, 215, 0),
|
||||||
'HotPink': [255, 105, 180],
|
'HotPink': (255, 105, 180),
|
||||||
'DarkBlue': [0, 0, 139],
|
'DarkBlue': (0, 0, 139),
|
||||||
'LimeGreen': [50, 205, 50],
|
'LimeGreen': (50, 205, 50),
|
||||||
'DeepSkyBlue': [0, 191, 255],
|
'DeepSkyBlue': (0, 191, 255),
|
||||||
'DarkKhaki': [189, 183, 107],
|
'DarkKhaki': (189, 183, 107),
|
||||||
'LightGrey': [211, 211, 211],
|
'LightGrey': (211, 211, 211),
|
||||||
'Yellow': [255, 255, 0],
|
'Yellow': (255, 255, 0),
|
||||||
'Gainsboro': [220, 220, 220],
|
'Gainsboro': (220, 220, 220),
|
||||||
'MistyRose': [255, 228, 225],
|
'MistyRose': (255, 228, 225),
|
||||||
'SandyBrown': [244, 164, 96],
|
'SandyBrown': (244, 164, 96),
|
||||||
'DeepPink': [255, 20, 147],
|
'DeepPink': (255, 20, 147),
|
||||||
'Magenta': [255, 0, 255],
|
'Magenta': (255, 0, 255),
|
||||||
'AliceBlue': [240, 248, 255],
|
'AliceBlue': (240, 248, 255),
|
||||||
'DarkCyan': [0, 139, 139],
|
'DarkCyan': (0, 139, 139),
|
||||||
'DarkSlateGrey': [47, 79, 79],
|
'DarkSlateGrey': (47, 79, 79),
|
||||||
'GreenYellow': [173, 255, 47],
|
'GreenYellow': (173, 255, 47),
|
||||||
'DarkOrchid': [153, 50, 204],
|
'DarkOrchid': (153, 50, 204),
|
||||||
'OliveDrab': [107, 142, 35],
|
'OliveDrab': (107, 142, 35),
|
||||||
'Chartreuse': [127, 255, 0],
|
'Chartreuse': (127, 255, 0),
|
||||||
'Peru': [205, 133, 63],
|
'Peru': (205, 133, 63),
|
||||||
'Orange': [255, 165, 0],
|
'Orange': (255, 165, 0),
|
||||||
'Red': [255, 0, 0],
|
'Red': (255, 0, 0),
|
||||||
'Wheat': [245, 222, 179],
|
'Wheat': (245, 222, 179),
|
||||||
'LightCyan': [224, 255, 255],
|
'LightCyan': (224, 255, 255),
|
||||||
'LightSeaGreen': [32, 178, 170],
|
'LightSeaGreen': (32, 178, 170),
|
||||||
'BlueViolet': [138, 43, 226],
|
'BlueViolet': (138, 43, 226),
|
||||||
'LightSlateGrey': [119, 136, 153],
|
'LightSlateGrey': (119, 136, 153),
|
||||||
'Cyan': [0, 255, 255],
|
'Cyan': (0, 255, 255),
|
||||||
'MediumPurple': [147, 112, 219],
|
'MediumPurple': (147, 112, 219),
|
||||||
'MidnightBlue': [25, 25, 112],
|
'MidnightBlue': (25, 25, 112),
|
||||||
'FireBrick': [178, 34, 34],
|
'FireBrick': (178, 34, 34),
|
||||||
'PaleTurquoise': [175, 238, 238],
|
'PaleTurquoise': (175, 238, 238),
|
||||||
'PaleGoldenrod': [238, 232, 170],
|
'PaleGoldenrod': (238, 232, 170),
|
||||||
'Gray': [128, 128, 128],
|
'Gray': (128, 128, 128),
|
||||||
'MediumSeaGreen': [60, 179, 113],
|
'MediumSeaGreen': (60, 179, 113),
|
||||||
'Moccasin': [255, 228, 181],
|
'Moccasin': (255, 228, 181),
|
||||||
'Ivory': [255, 255, 240],
|
'Ivory': (255, 255, 240),
|
||||||
'DarkSlateBlue': [72, 61, 139],
|
'DarkSlateBlue': (72, 61, 139),
|
||||||
'Beige': [245, 245, 220],
|
'Beige': (245, 245, 220),
|
||||||
'Green': [0, 128, 0],
|
'Green': (0, 128, 0),
|
||||||
'SlateBlue': [106, 90, 205],
|
'SlateBlue': (106, 90, 205),
|
||||||
'Teal': [0, 128, 128],
|
'Teal': (0, 128, 128),
|
||||||
'Azure': [240, 255, 255],
|
'Azure': (240, 255, 255),
|
||||||
'LightSteelBlue': [176, 196, 222],
|
'LightSteelBlue': (176, 196, 222),
|
||||||
'DimGrey': [105, 105, 105],
|
'DimGrey': (105, 105, 105),
|
||||||
'Tan': [210, 180, 140],
|
'Tan': (210, 180, 140),
|
||||||
'AntiqueWhite': [250, 235, 215],
|
'AntiqueWhite': (250, 235, 215),
|
||||||
'SkyBlue': [135, 206, 235],
|
'SkyBlue': (135, 206, 235),
|
||||||
'GhostWhite': [248, 248, 255],
|
'GhostWhite': (248, 248, 255),
|
||||||
'MediumTurquoise': [72, 209, 204],
|
'MediumTurquoise': (72, 209, 204),
|
||||||
'FloralWhite': [255, 250, 240],
|
'FloralWhite': (255, 250, 240),
|
||||||
'LavenderBlush': [255, 240, 245],
|
'LavenderBlush': (255, 240, 245),
|
||||||
'SeaGreen': [46, 139, 87],
|
'SeaGreen': (46, 139, 87),
|
||||||
'Lavender': [230, 230, 250],
|
'Lavender': (230, 230, 250),
|
||||||
'BlanchedAlmond': [255, 235, 205],
|
'BlanchedAlmond': (255, 235, 205),
|
||||||
'DarkOliveGreen': [85, 107, 47],
|
'DarkOliveGreen': (85, 107, 47),
|
||||||
'DarkSeaGreen': [143, 188, 143],
|
'DarkSeaGreen': (143, 188, 143),
|
||||||
'SpringGreen': [0, 255, 127],
|
'SpringGreen': (0, 255, 127),
|
||||||
'Navy': [0, 0, 128],
|
'Navy': (0, 0, 128),
|
||||||
'Orchid': [218, 112, 214],
|
'Orchid': (218, 112, 214),
|
||||||
'SaddleBrown': [139, 69, 19],
|
'SaddleBrown': (139, 69, 19),
|
||||||
'IndianRed': [205, 92, 92],
|
'IndianRed': (205, 92, 92),
|
||||||
'Snow': [255, 250, 250],
|
'Snow': (255, 250, 250),
|
||||||
'SteelBlue': [70, 130, 180],
|
'SteelBlue': (70, 130, 180),
|
||||||
'MediumSlateBlue': [123, 104, 238],
|
'MediumSlateBlue': (123, 104, 238),
|
||||||
'Black': [0, 0, 0],
|
'Black': (0, 0, 0),
|
||||||
'LightBlue': [173, 216, 230],
|
'LightBlue': (173, 216, 230),
|
||||||
'Turquoise': [64, 224, 208],
|
'Turquoise': (64, 224, 208),
|
||||||
'MediumVioletRed': [199, 21, 133],
|
'MediumVioletRed': (199, 21, 133),
|
||||||
'DarkViolet': [148, 0, 211],
|
'DarkViolet': (148, 0, 211),
|
||||||
'DarkGray': [169, 169, 169],
|
'DarkGray': (169, 169, 169),
|
||||||
'Salmon': [250, 128, 114],
|
'Salmon': (250, 128, 114),
|
||||||
'DarkMagenta': [139, 0, 139],
|
'DarkMagenta': (139, 0, 139),
|
||||||
'Tomato': [255, 99, 71],
|
'Tomato': (255, 99, 71),
|
||||||
'WhiteSmoke': [245, 245, 245],
|
'WhiteSmoke': (245, 245, 245),
|
||||||
'Goldenrod': [218, 165, 32],
|
'Goldenrod': (218, 165, 32),
|
||||||
'MediumSpringGreen': [0, 250, 154],
|
'MediumSpringGreen': (0, 250, 154),
|
||||||
'DodgerBlue': [30, 144, 255],
|
'DodgerBlue': (30, 144, 255),
|
||||||
'Aqua': [0, 255, 255],
|
'Aqua': (0, 255, 255),
|
||||||
'ForestGreen': [34, 139, 34],
|
'ForestGreen': (34, 139, 34),
|
||||||
'LemonChiffon': [255, 250, 205],
|
'LemonChiffon': (255, 250, 205),
|
||||||
'LightSlateGray': [119, 136, 153],
|
'LightSlateGray': (119, 136, 153),
|
||||||
'SlateGray': [112, 128, 144],
|
'SlateGray': (112, 128, 144),
|
||||||
'LightGray': [211, 211, 211],
|
'LightGray': (211, 211, 211),
|
||||||
'Indigo': [75, 0, 130],
|
'Indigo': (75, 0, 130),
|
||||||
'CadetBlue': [95, 158, 160],
|
'CadetBlue': (95, 158, 160),
|
||||||
'LightYellow': [255, 255, 224],
|
'LightYellow': (255, 255, 224),
|
||||||
'DarkOrange': [255, 140, 0],
|
'DarkOrange': (255, 140, 0),
|
||||||
'PowderBlue': [176, 224, 230],
|
'PowderBlue': (176, 224, 230),
|
||||||
'RoyalBlue': [65, 105, 225],
|
'RoyalBlue': (65, 105, 225),
|
||||||
'Sienna': [160, 82, 45],
|
'Sienna': (160, 82, 45),
|
||||||
'Thistle': [216, 191, 216],
|
'Thistle': (216, 191, 216),
|
||||||
'Lime': [0, 255, 0],
|
'Lime': (0, 255, 0),
|
||||||
'Seashell': [255, 245, 238],
|
'Seashell': (255, 245, 238),
|
||||||
'DarkRed': [139, 0, 0],
|
'DarkRed': (139, 0, 0),
|
||||||
'LightSkyBlue': [135, 206, 250],
|
'LightSkyBlue': (135, 206, 250),
|
||||||
'YellowGreen': [154, 205, 50],
|
'YellowGreen': (154, 205, 50),
|
||||||
'Aquamarine': [127, 255, 212],
|
'Aquamarine': (127, 255, 212),
|
||||||
'LightCoral': [240, 128, 128],
|
'LightCoral': (240, 128, 128),
|
||||||
'DarkSlateGray': [47, 79, 79],
|
'DarkSlateGray': (47, 79, 79),
|
||||||
'Khaki': [240, 230, 140],
|
'Khaki': (240, 230, 140),
|
||||||
'DarkGrey': [169, 169, 169],
|
'DarkGrey': (169, 169, 169),
|
||||||
'BurlyWood': [222, 184, 135],
|
'BurlyWood': (222, 184, 135),
|
||||||
'LightGoldenrodYellow': [250, 250, 210],
|
'LightGoldenrodYellow': (250, 250, 210),
|
||||||
'MediumBlue': [0, 0, 205],
|
'MediumBlue': (0, 0, 205),
|
||||||
'DarkSalmon': [233, 150, 122],
|
'DarkSalmon': (233, 150, 122),
|
||||||
'RosyBrown': [188, 143, 143],
|
'RosyBrown': (188, 143, 143),
|
||||||
'LightSalmon': [255, 160, 122],
|
'LightSalmon': (255, 160, 122),
|
||||||
'PaleVioletRed': [219, 112, 147],
|
'PaleVioletRed': (219, 112, 147),
|
||||||
'Coral': [255, 127, 80],
|
'Coral': (255, 127, 80),
|
||||||
'Violet': [238, 130, 238],
|
'Violet': (238, 130, 238),
|
||||||
'Grey': [128, 128, 128],
|
'Grey': (128, 128, 128),
|
||||||
'LightGreen': [144, 238, 144],
|
'LightGreen': (144, 238, 144),
|
||||||
'Linen': [250, 240, 230],
|
'Linen': (250, 240, 230),
|
||||||
'OrangeRed': [255, 69, 0],
|
'OrangeRed': (255, 69, 0),
|
||||||
'DimGray': [105, 105, 105],
|
'DimGray': (105, 105, 105),
|
||||||
'Maroon': [128, 0, 0],
|
'Maroon': (128, 0, 0),
|
||||||
'LightPink': [255, 182, 193],
|
'LightPink': (255, 182, 193),
|
||||||
'MediumAquamarine': [102, 205, 170],
|
'MediumAquamarine': (102, 205, 170),
|
||||||
'OldLace': [253, 245, 230]
|
'OldLace': (253, 245, 230)
|
||||||
}
|
}
|
||||||
|
|
||||||
def getcolor(color):
|
def getcolor(color):
|
||||||
|
@ -227,6 +230,85 @@ def getsize(width):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return width
|
return width
|
||||||
|
|
||||||
|
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
|
||||||
|
closed if required the 'connectEdgesToWires' function is used'''
|
||||||
|
#ToDo Do not catch all exceptions
|
||||||
|
if not donttry:
|
||||||
|
try:
|
||||||
|
sh = Part.Wire(path)
|
||||||
|
isok = (not checkclosed) or sh.isClosed()
|
||||||
|
except:# BRep_API:command not done
|
||||||
|
isok = False
|
||||||
|
if donttry or not isok:
|
||||||
|
#Code from wmayer forum p15549 to fix the tolerance problem
|
||||||
|
#original tolerance = 0.00001
|
||||||
|
comp=Part.Compound(path)
|
||||||
|
sh = comp.connectEdgesToWires(False,10**(-1*(Draft.precision()-2))).Wires[0]
|
||||||
|
return sh
|
||||||
|
|
||||||
|
def arccenter2end(center,rx,ry,angle1,angledelta,xrotation=0.0):
|
||||||
|
'''calculate start and end vector and flags of an arc given in center parametrization
|
||||||
|
see http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
|
||||||
|
returns (v1,v2,largerc,sweep)'''
|
||||||
|
vr1=Vector(rx*math.cos(angle1),ry*math.sin(angle1),0)
|
||||||
|
vr2=Vector(rx*math.cos(angle1+angledelta),ry*math.sin(angle1+angledelta),0)
|
||||||
|
mxrot=FreeCAD.Matrix()
|
||||||
|
mxrot.rotateZ(xrotation)
|
||||||
|
v1 = mxrot.multiply(vr1).add(center)
|
||||||
|
v2 = mxrot.multiply(vr2).add(center)
|
||||||
|
fa = ((abs(angledelta) / math.pi) % 2) > 1 # <180deg
|
||||||
|
fs = angledelta < 0
|
||||||
|
return v1,v2,fa,fs
|
||||||
|
|
||||||
|
def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False):
|
||||||
|
'''calculate (positive and negative) possible centers for an arc in endpoint parameterization
|
||||||
|
see http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
|
||||||
|
rotation or x-axis has to be specified in radians (CCW)
|
||||||
|
the sweepflag is interpreted as: sweepflag <==> arc is travelled clockwise
|
||||||
|
returns [(vcenter+,angle1+,angledelta+),(...-)]'''
|
||||||
|
#scalefacsign = 1 if (largeflag != sweepflag) else -1
|
||||||
|
rx = float(rx)
|
||||||
|
ry = float(ry)
|
||||||
|
v0 = lastvec.sub(currentvec)
|
||||||
|
v0 = v0.multiply(0.5)
|
||||||
|
m1=FreeCAD.Matrix()
|
||||||
|
m1.rotateZ(-xrotation) #Formular 6.5.1
|
||||||
|
v1=m1.multiply(v0)
|
||||||
|
if correction:
|
||||||
|
eparam = v1.x**2 / rx**2 + v1.y**2 / ry**2
|
||||||
|
if eparam > 1:
|
||||||
|
eproot = math.sqrt(eparam)
|
||||||
|
rx = eproot * rx
|
||||||
|
ry = eproot * ry
|
||||||
|
denom = rx**2 * v1.y**2+ ry**2 * v1.x**2
|
||||||
|
numer = rx**2 * ry**2 -denom
|
||||||
|
results=[]
|
||||||
|
if abs(numer/denom) < 10**(-1*(Draft.precision())):
|
||||||
|
scalefacpos = 0
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
scalefacpos = math.sqrt(numer/denom)
|
||||||
|
except ValueError:
|
||||||
|
print 'sqrt(%f/%f)' % (numer,denom)
|
||||||
|
scalefacpos = 0
|
||||||
|
for scalefacsign in (1,-1):
|
||||||
|
scalefac = scalefacpos * scalefacsign
|
||||||
|
vcx1 = Vector(v1.y*rx/ry,-v1.x*ry/rx,0).multiply(scalefac) # Step2 F.6.5.2
|
||||||
|
m2=FreeCAD.Matrix()
|
||||||
|
m2.rotateZ(xrotation)
|
||||||
|
centeroff = currentvec.add(lastvec)
|
||||||
|
centeroff = fcvec.scale(centeroff,.5)
|
||||||
|
vcenter = m2.multiply(vcx1).add(centeroff) # Step3 F.6.5.3
|
||||||
|
#angle1 = Vector(1,0,0).getAngle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5
|
||||||
|
#angledelta = Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0).getAngle(Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6
|
||||||
|
#we need the right sign for the angle
|
||||||
|
angle1 = fcvec.angle(Vector(1,0,0),Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0)) # F.6.5.5
|
||||||
|
angledelta = fcvec.angle(Vector((v1.x-vcx1.x)/rx,(v1.y-vcx1.y)/ry,0),Vector((-v1.x-vcx1.x)/rx,(-v1.y-vcx1.y)/ry,0)) # F.6.5.6
|
||||||
|
results.append((vcenter,angle1,angledelta))
|
||||||
|
return results,(rx,ry)
|
||||||
|
|
||||||
|
|
||||||
def getrgb(color):
|
def getrgb(color):
|
||||||
"returns a rgb value #000000 from a freecad color"
|
"returns a rgb value #000000 from a freecad color"
|
||||||
r = str(hex(int(color[0]*255)))[2:].zfill(2)
|
r = str(hex(int(color[0]*255)))[2:].zfill(2)
|
||||||
|
@ -364,163 +446,79 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
obj = Draft.makeDimension(p1,p2,p3)
|
obj = Draft.makeDimension(p1,p2,p3)
|
||||||
self.applyTrans(obj)
|
self.applyTrans(obj)
|
||||||
self.format(obj)
|
self.format(obj)
|
||||||
pathdata = []
|
|
||||||
self.lastdim = obj
|
self.lastdim = obj
|
||||||
|
data['d']=[]
|
||||||
pathcommandsre=re.compile('\s*?([mMlLhHvVaAcCqQsStTzZ])\s*?([^mMlLhHvVaAcCqQsStTzZ]*)\s*?',re.DOTALL)
|
pathcommandsre=re.compile('\s*?([mMlLhHvVaAcCqQsStTzZ])\s*?([^mMlLhHvVaAcCqQsStTzZ]*)\s*?',re.DOTALL)
|
||||||
for d,pointsstr in pathcommandsre.findall(' '.join(data['d'])):
|
for d,pointsstr in pathcommandsre.findall(' '.join(data['d'])):
|
||||||
#for d in pathdata:
|
relative = d.islower()
|
||||||
if (d == "M"):
|
pointlist = [float(str1) for str1 in pointsstr.replace(',',' ').split()]
|
||||||
command = "move"
|
if (d == "M" or d == "m"):
|
||||||
relative = False
|
x = pointlist.pop(0)
|
||||||
point = []
|
y = pointlist.pop(0)
|
||||||
elif (d == "m"):
|
|
||||||
command = "move"
|
|
||||||
relative = True
|
|
||||||
point = []
|
|
||||||
elif (d == "L"):
|
|
||||||
command = "line"
|
|
||||||
relative = False
|
|
||||||
point = []
|
|
||||||
elif (d == "l"):
|
|
||||||
command = "line"
|
|
||||||
relative = True
|
|
||||||
point = []
|
|
||||||
elif (d == "H"):
|
|
||||||
command = "horizontal"
|
|
||||||
relative = False
|
|
||||||
point = []
|
|
||||||
elif (d == "h"):
|
|
||||||
command = "horizontal"
|
|
||||||
relative = True
|
|
||||||
point = []
|
|
||||||
elif (d == "V"):
|
|
||||||
command = "vertical"
|
|
||||||
relative = False
|
|
||||||
point = []
|
|
||||||
elif (d == "v"):
|
|
||||||
command = "vertical"
|
|
||||||
relative = True
|
|
||||||
point = []
|
|
||||||
elif (d == "A"):
|
|
||||||
command = "arc"
|
|
||||||
relative = False
|
|
||||||
point = []
|
|
||||||
elif (d == "a"):
|
|
||||||
command = "arc"
|
|
||||||
relative = True
|
|
||||||
point = []
|
|
||||||
elif (d == "Z") or (d == "z"):
|
|
||||||
command = "close"
|
|
||||||
point = []
|
|
||||||
elif (d == "C"):
|
|
||||||
command = "cubic"
|
|
||||||
relative = False
|
|
||||||
smooth = False
|
|
||||||
point = []
|
|
||||||
elif (d == "c"):
|
|
||||||
command = "cubic"
|
|
||||||
relative = True
|
|
||||||
smooth = False
|
|
||||||
point = []
|
|
||||||
elif (d == "Q"):
|
|
||||||
command = "quadratic"
|
|
||||||
relative = False
|
|
||||||
smooth = False
|
|
||||||
point = []
|
|
||||||
elif (d == "q"):
|
|
||||||
command = "quadratic"
|
|
||||||
relative = True
|
|
||||||
smooth = False
|
|
||||||
point = []
|
|
||||||
elif (d == "S"):
|
|
||||||
command = "cubic"
|
|
||||||
relative = False
|
|
||||||
smooth = True
|
|
||||||
point = []
|
|
||||||
elif (d == "s"):
|
|
||||||
command = "cubic"
|
|
||||||
relative = True
|
|
||||||
smooth = True
|
|
||||||
point = []
|
|
||||||
elif (d == "T"):
|
|
||||||
command = "quadratic"
|
|
||||||
relative = False
|
|
||||||
smooth = True
|
|
||||||
point = []
|
|
||||||
elif (d == "t"):
|
|
||||||
command = "quadratic"
|
|
||||||
relative = True
|
|
||||||
smooth = True
|
|
||||||
point = []
|
|
||||||
pointlist = pointsstr.replace(',',' ').split()
|
|
||||||
while pointlist:
|
|
||||||
if pointlist:
|
|
||||||
point.append(float(pointlist.pop(0)))
|
|
||||||
print "command: ",command, ' point: ',point
|
|
||||||
|
|
||||||
if (len(point)==2) and (command=="move"):
|
|
||||||
if path:
|
if path:
|
||||||
sh = Part.Wire(path)
|
#sh = Part.Wire(path)
|
||||||
|
sh = makewire(path)
|
||||||
if self.fill: sh = Part.Face(sh)
|
if self.fill: sh = Part.Face(sh)
|
||||||
sh = self.applyTrans(sh)
|
sh = self.applyTrans(sh)
|
||||||
obj = self.doc.addObject("Part::Feature",pathname)
|
obj = self.doc.addObject("Part::Feature",pathname)
|
||||||
obj.Shape = sh
|
obj.Shape = sh
|
||||||
self.format(obj)
|
self.format(obj)
|
||||||
path = []
|
path = []
|
||||||
if firstvec:
|
#if firstvec:
|
||||||
lastvec = firstvec #Move relative to last move command not last draw command
|
# lastvec = firstvec #Move relative to last move command not last draw command
|
||||||
if relative:
|
if relative:
|
||||||
lastvec = lastvec.add(Vector(point[0],-point[1],0))
|
lastvec = lastvec.add(Vector(x,-y,0))
|
||||||
command="line"
|
|
||||||
else:
|
else:
|
||||||
lastvec = Vector(point[0],-point[1],0)
|
lastvec = Vector(x,-y,0)
|
||||||
firstvec = lastvec
|
firstvec = lastvec
|
||||||
print "move ",lastvec
|
print "move ",lastvec
|
||||||
command = "line"
|
|
||||||
lastpole = None
|
lastpole = None
|
||||||
point = []
|
if (d == "L" or d == "l") or \
|
||||||
elif (len(point)==2) and (command=="line"):
|
((d == 'm' or d == 'M') and pointlist) :
|
||||||
|
for x,y in zip(pointlist[0::2],pointlist[1::2]):
|
||||||
if relative:
|
if relative:
|
||||||
currentvec = lastvec.add(Vector(point[0],-point[1],0))
|
currentvec = lastvec.add(Vector(x,-y,0))
|
||||||
else:
|
else:
|
||||||
currentvec = Vector(point[0],-point[1],0)
|
currentvec = Vector(x,-y,0)
|
||||||
if not fcvec.equals(lastvec,currentvec):
|
if not fcvec.equals(lastvec,currentvec):
|
||||||
seg = Part.Line(lastvec,currentvec).toShape()
|
seg = Part.Line(lastvec,currentvec).toShape()
|
||||||
print "line ",lastvec,currentvec
|
print "line ",lastvec,currentvec
|
||||||
lastvec = currentvec
|
lastvec = currentvec
|
||||||
path.append(seg)
|
path.append(seg)
|
||||||
lastpole = None
|
lastpole = None
|
||||||
point = []
|
elif (d == "H" or d == "h"):
|
||||||
elif (len(point)==1) and (command=="horizontal"):
|
for x in pointlist:
|
||||||
if relative:
|
if relative:
|
||||||
currentvec = lastvec.add(Vector(point[0],0,0))
|
currentvec = lastvec.add(Vector(x,0,0))
|
||||||
else:
|
else:
|
||||||
lasty = path[-1].y
|
lasty = path[-1].y
|
||||||
currentvec = Vector(point[0],lasty,0)
|
currentvec = Vector(x,lasty,0)
|
||||||
seg = Part.Line(lastvec,currentvec).toShape()
|
seg = Part.Line(lastvec,currentvec).toShape()
|
||||||
lastvec = currentvec
|
lastvec = currentvec
|
||||||
lastpole = None
|
lastpole = None
|
||||||
path.append(seg)
|
path.append(seg)
|
||||||
point = []
|
elif (d == "V" or d == "v"):
|
||||||
elif (len(point)==1) and (command=="vertical"):
|
for y in pointlist:
|
||||||
if relative:
|
if relative:
|
||||||
currentvec = lastvec.add(Vector(0,-point[0],0))
|
currentvec = lastvec.add(Vector(0,-y,0))
|
||||||
else:
|
else:
|
||||||
lastx = path[-1].x
|
lastx = path[-1].x
|
||||||
currentvec = Vector(lastx,-point[0],0)
|
currentvec = Vector(lastx,-y,0)
|
||||||
seg = Part.Line(lastvec,currentvec).toShape()
|
seg = Part.Line(lastvec,currentvec).toShape()
|
||||||
lastvec = currentvec
|
lastvec = currentvec
|
||||||
lastpole = None
|
lastpole = None
|
||||||
path.append(seg)
|
path.append(seg)
|
||||||
point = []
|
elif (d == "A" or d == "a"):
|
||||||
elif (len(point)==7) and (command=="arc"):
|
for rx,ry,xrotation, largeflag, sweepflag,x,y in \
|
||||||
|
zip(pointlist[0::7],pointlist[1::7],pointlist[2::7],pointlist[3::7],pointlist[4::7],pointlist[5::7],pointlist[6::7]):
|
||||||
|
|
||||||
#support for large-arc and x-rotation are missing
|
#support for large-arc and x-rotation are missing
|
||||||
rx,ry,xrotation, largeflag, sweepflag = point[0:5]
|
|
||||||
if relative:
|
if relative:
|
||||||
currentvec = lastvec.add(Vector(point[-2],-point[-1],0))
|
currentvec = lastvec.add(Vector(x,-y,0))
|
||||||
else:
|
else:
|
||||||
currentvec = Vector(point[-2],-point[-1],0)
|
currentvec = Vector(x,-y,0)
|
||||||
chord = currentvec.sub(lastvec)
|
chord = currentvec.sub(lastvec)
|
||||||
|
if (not largeflag) and abs(rx-ry) < 10**(-1*Draft.precision()): # small circular arc
|
||||||
# perp = chord.cross(Vector(0,0,-1))
|
# perp = chord.cross(Vector(0,0,-1))
|
||||||
# here is a better way to find the perpendicular
|
# here is a better way to find the perpendicular
|
||||||
if sweepflag == 1:
|
if sweepflag == 1:
|
||||||
|
@ -536,31 +534,71 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
perp = fcvec.scale(perp,s/perp.Length)
|
perp = fcvec.scale(perp,s/perp.Length)
|
||||||
midpoint = lastvec.add(chord.add(perp))
|
midpoint = lastvec.add(chord.add(perp))
|
||||||
seg = Part.Arc(lastvec,midpoint,currentvec).toShape()
|
seg = Part.Arc(lastvec,midpoint,currentvec).toShape()
|
||||||
|
else:# big arc or elliptical arc
|
||||||
|
solution,(rx,ry) = arcend2center(lastvec,currentvec,rx,ry,math.radians(-xrotation),True)
|
||||||
|
negsol = (largeflag != sweepflag)
|
||||||
|
vcenter,angle1,angledelta = solution[negsol]
|
||||||
|
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)
|
||||||
|
e1 = Part.Ellipse(vcenter,rx,ry)
|
||||||
|
if sweepflag:
|
||||||
|
#angledelta=-(-angledelta % (math.pi *2)) # Step4
|
||||||
|
#angledelta=(-angledelta % (math.pi *2)) # Step4
|
||||||
|
angle1 = angle1-angledelta
|
||||||
|
#angle1 = math.pi - angle1
|
||||||
|
|
||||||
|
e1a = Part.Arc(e1,angle1-swapaxis*math.radians(90),\
|
||||||
|
angle1+angledelta-swapaxis*math.radians(90))
|
||||||
|
#e1a = Part.Arc(e1,angle1-0*swapaxis*math.radians(90),angle1+angledelta-0*swapaxis*math.radians(90))
|
||||||
|
if swapaxis or xrotation > 10**(-1*Draft.precision()):
|
||||||
|
m3=FreeCAD.Matrix()
|
||||||
|
m3.move(vcenter)
|
||||||
|
rot90=FreeCAD.Matrix(0,-1,0,0,1,0) #90
|
||||||
|
#swapaxism=FreeCAD.Matrix(0,1,0,0,1,0)
|
||||||
|
if swapaxis:
|
||||||
|
m3=m3.multiply(rot90)
|
||||||
|
m3.rotateZ(math.radians(-xrotation))
|
||||||
|
m3.move(vcenter.multiply(-1))
|
||||||
|
e1a.transform(m3)
|
||||||
|
seg = e1a.toShape()
|
||||||
|
if sweepflag:
|
||||||
|
seg.reverse()
|
||||||
|
#obj = self.doc.addObject("Part::Feature",'DEBUG %s'%pathname) #DEBUG
|
||||||
|
#obj.Shape = seg #DEBUG
|
||||||
|
#seg = Part.Line(lastvec,currentvec).toShape() #DEBUG
|
||||||
lastvec = currentvec
|
lastvec = currentvec
|
||||||
lastpole = None
|
lastpole = None
|
||||||
path.append(seg)
|
path.append(seg)
|
||||||
point = []
|
elif (d == "C" or d == "c") or\
|
||||||
elif (command=="cubic") and (((smooth==False) and (len(point)==6)) or (smooth==True and (len(point)==4))) :
|
(d =="S" or d == "s"):
|
||||||
|
smooth = (d == 'S' or d == 's')
|
||||||
if smooth:
|
if smooth:
|
||||||
if relative:
|
piter = zip(pointlist[2::4],pointlist[3::4],pointlist[0::4],pointlist[1::4],pointlist[2::4],pointlist[3::4])
|
||||||
currentvec = lastvec.add(Vector(point[2],-point[3],0))
|
|
||||||
pole2 = lastvec.add(Vector(point[0],-point[1],0))
|
|
||||||
else:
|
else:
|
||||||
currentvec = Vector(point[2],-point[3],0)
|
piter = zip(pointlist[0::6],pointlist[1::6],pointlist[2::6],pointlist[3::6],pointlist[4::6],pointlist[5::6])
|
||||||
pole2 = Vector(point[0],-point[1],0)
|
for p1x,p1y,p2x,p2y,x,y in piter:
|
||||||
|
if smooth:
|
||||||
if lastpole is not None and lastpole[0]=='cubic':
|
if lastpole is not None and lastpole[0]=='cubic':
|
||||||
pole1 = lastvec.sub(lastpole[1]).add(lastvec)
|
pole1 = lastvec.sub(lastpole[1]).add(lastvec)
|
||||||
else:
|
else:
|
||||||
pole1 = lastvec
|
pole1 = lastvec
|
||||||
else: #not smooth
|
|
||||||
if relative:
|
|
||||||
currentvec = lastvec.add(Vector(point[4],-point[5],0))
|
|
||||||
pole1 = lastvec.add(Vector(point[0],-point[1],0))
|
|
||||||
pole2 = lastvec.add(Vector(point[2],-point[3],0))
|
|
||||||
else:
|
else:
|
||||||
currentvec = Vector(point[4],-point[5],0)
|
if relative:
|
||||||
pole1 = Vector(point[0],-point[1],0)
|
pole1 = lastvec.add(Vector(p1x,-p1y,0))
|
||||||
pole2 = Vector(point[2],-point[3],0)
|
else:
|
||||||
|
pole1 = Vector(p1x,-p1y,0)
|
||||||
|
if relative:
|
||||||
|
currentvec = lastvec.add(Vector(x,-y,0))
|
||||||
|
pole2 = lastvec.add(Vector(p2x,-p2y,0))
|
||||||
|
else:
|
||||||
|
currentvec = Vector(x,-y,0)
|
||||||
|
pole2 = Vector(p2x,-p2y,0)
|
||||||
|
|
||||||
if not fcvec.equals(currentvec,lastvec):
|
if not fcvec.equals(currentvec,lastvec):
|
||||||
mainv = currentvec.sub(lastvec)
|
mainv = currentvec.sub(lastvec)
|
||||||
|
@ -568,8 +606,8 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
pole2v = currentvec.add(pole2)
|
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 \
|
if True and \
|
||||||
pole1.distanceToLine(lastvec,currentvec) < 20**(-1*Draft.precision()) and \
|
pole1.distanceToLine(lastvec,currentvec) < 10**(-1*(2+Draft.precision())) and \
|
||||||
pole2.distanceToLine(lastvec,currentvec) < 20**(-1*Draft.precision()):
|
pole2.distanceToLine(lastvec,currentvec) < 10**(-1*(2+Draft.precision())):
|
||||||
print "straight segment"
|
print "straight segment"
|
||||||
seg = Part.Line(lastvec,currentvec).toShape()
|
seg = Part.Line(lastvec,currentvec).toShape()
|
||||||
else:
|
else:
|
||||||
|
@ -581,54 +619,50 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
lastvec = currentvec
|
lastvec = currentvec
|
||||||
lastpole = ('cubic',pole2)
|
lastpole = ('cubic',pole2)
|
||||||
path.append(seg)
|
path.append(seg)
|
||||||
point = []
|
elif (d == "Q" or d == "q") or\
|
||||||
|
(d =="T" or d == "t"):
|
||||||
elif (command=="quadratic") and (((smooth==False) and (len(point)==4)) or (smooth==True and (len(point)==2))) :
|
smooth = (d == 'T' or d == 't')
|
||||||
if smooth:
|
if smooth:
|
||||||
if relative:
|
piter = zip(pointlist[1::2],pointlist[1::2],pointlist[0::2],pointlist[1::2])
|
||||||
currentvec = lastvec.add(Vector(point[0],-point[1],0))
|
|
||||||
else:
|
else:
|
||||||
currentvec = Vector(point[0],-point[1],0)
|
piter = zip(pointlist[0::4],pointlist[1::4],pointlist[2::4],pointlist[3::4])
|
||||||
|
for px,py,x,y in piter:
|
||||||
|
if smooth:
|
||||||
if lastpole is not None and lastpole[0]=='quadratic':
|
if lastpole is not None and lastpole[0]=='quadratic':
|
||||||
pole1 = lastvec.sub(lastpole[1]).add(lastvec)
|
pole = lastvec.sub(lastpole[1]).add(lastvec)
|
||||||
|
else:
|
||||||
|
pole = lastvec
|
||||||
else:
|
else:
|
||||||
pole1 = lastvec
|
|
||||||
else: #not smooth
|
|
||||||
if relative:
|
if relative:
|
||||||
currentvec = lastvec.add(Vector(point[2],-point[3],0))
|
pole = lastvec.add(Vector(px,-py,0))
|
||||||
pole1 = lastvec.add(Vector(point[0],-point[1],0))
|
|
||||||
else:
|
else:
|
||||||
currentvec = Vector(point[2],-point[3],0)
|
pole = Vector(px,-py,0)
|
||||||
pole1 = Vector(point[0],-point[1],0)
|
if relative:
|
||||||
|
currentvec = lastvec.add(Vector(x,-y,0))
|
||||||
|
else:
|
||||||
|
currentvec = Vector(x,-y,0)
|
||||||
|
|
||||||
if not fcvec.equals(currentvec,lastvec):
|
if not fcvec.equals(currentvec,lastvec):
|
||||||
if True and pole1.distanceToLine(lastvec,currentvec) < 20**(-1*Draft.precision()):
|
if True and \
|
||||||
|
pole.distanceToLine(lastvec,currentvec) < 20**(-1*(2+Draft.precision())):
|
||||||
print "straight segment"
|
print "straight segment"
|
||||||
seg = Part.Line(lastvec,currentvec).toShape()
|
seg = Part.Line(lastvec,currentvec).toShape()
|
||||||
else:
|
else:
|
||||||
print "quadratic bezier segment"
|
print "quadratic bezier segment"
|
||||||
b = Part.BezierCurve()
|
b = Part.BezierCurve()
|
||||||
b.setPoles([lastvec,pole1,currentvec])
|
b.setPoles([lastvec,pole,currentvec])
|
||||||
seg = b.toShape()
|
seg = b.toShape()
|
||||||
print "connect ",lastvec,currentvec
|
print "connect ",lastvec,currentvec
|
||||||
lastvec = currentvec
|
lastvec = currentvec
|
||||||
lastpole = ('quadratic',pole1)
|
lastpole = ('quadratic',pole)
|
||||||
path.append(seg)
|
path.append(seg)
|
||||||
point = []
|
elif (d == "Z") or (d == "z"):
|
||||||
|
|
||||||
#while pointlist or command:
|
|
||||||
else:
|
|
||||||
|
|
||||||
if (command == "close"):
|
|
||||||
if not fcvec.equals(lastvec,firstvec):
|
if not fcvec.equals(lastvec,firstvec):
|
||||||
seg = Part.Line(lastvec,firstvec).toShape()
|
seg = Part.Line(lastvec,firstvec).toShape()
|
||||||
path.append(seg)
|
path.append(seg)
|
||||||
if path: #the path should be closed by now
|
if path: #the path should be closed by now
|
||||||
sh = Part.Wire(path)
|
#sh=makewire(path,True)
|
||||||
if not sh.isClosed:
|
sh=makewire(path,donttry=True)
|
||||||
#Code from wmayer forum p15549 to fix the tolerance problem
|
|
||||||
comp=Part.Compound(path)
|
|
||||||
sh = comp.connectEdgesToWires(False,10**(-1*Draft.precision())).Wires[0] #original tolerance = 0.00001
|
|
||||||
if self.fill: sh = Part.Face(sh)
|
if self.fill: sh = Part.Face(sh)
|
||||||
sh = self.applyTrans(sh)
|
sh = self.applyTrans(sh)
|
||||||
obj = self.doc.addObject("Part::Feature",pathname)
|
obj = self.doc.addObject("Part::Feature",pathname)
|
||||||
|
@ -636,11 +670,12 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
self.format(obj)
|
self.format(obj)
|
||||||
path = []
|
path = []
|
||||||
if firstvec:
|
if firstvec:
|
||||||
lastvec = firstvec #Move relative to last move command not last draw command
|
lastvec = firstvec #Move relative to recent draw command
|
||||||
point = []
|
point = []
|
||||||
command = None
|
command = None
|
||||||
if path:
|
if path:
|
||||||
sh = Part.Wire(path)
|
sh=makewire(path,checkclosed=False)
|
||||||
|
#sh = Part.Wire(path)
|
||||||
if self.fill: sh = Part.Face(sh)
|
if self.fill: sh = Part.Face(sh)
|
||||||
sh = self.applyTrans(sh)
|
sh = self.applyTrans(sh)
|
||||||
obj = self.doc.addObject("Part::Feature",pathname)
|
obj = self.doc.addObject("Part::Feature",pathname)
|
||||||
|
@ -653,9 +688,9 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
if name == "rect":
|
if name == "rect":
|
||||||
if not pathname: pathname = 'Rectangle'
|
if not pathname: pathname = 'Rectangle'
|
||||||
edges = []
|
edges = []
|
||||||
# if ('rx' not in data or data['rx'] < 10**(-1*Draft.precision())) and \
|
if ('rx' not in data or data['rx'] < 10**(-1*Draft.precision())) and \
|
||||||
# ('ry' not in data or data['ry'] < 10**(-1*Draft.precision())): #negative values are invalid
|
('ry' not in data or data['ry'] < 10**(-1*Draft.precision())): #negative values are invalid
|
||||||
if True:
|
# if True:
|
||||||
p1 = Vector(data['x'],-data['y'],0)
|
p1 = Vector(data['x'],-data['y'],0)
|
||||||
p2 = Vector(data['x']+data['width'],-data['y'],0)
|
p2 = Vector(data['x']+data['width'],-data['y'],0)
|
||||||
p3 = Vector(data['x']+data['width'],-data['y']-data['height'],0)
|
p3 = Vector(data['x']+data['width'],-data['y']-data['height'],0)
|
||||||
|
@ -665,6 +700,7 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
edges.append(Part.Line(p3,p4).toShape())
|
edges.append(Part.Line(p3,p4).toShape())
|
||||||
edges.append(Part.Line(p4,p1).toShape())
|
edges.append(Part.Line(p4,p1).toShape())
|
||||||
else: #rounded edges
|
else: #rounded edges
|
||||||
|
#ToTo: check for ry>rx !!!!
|
||||||
rx = data.get('rx')
|
rx = data.get('rx')
|
||||||
ry = data.get('ry') or rx
|
ry = data.get('ry') or rx
|
||||||
rx = rx or ry
|
rx = rx or ry
|
||||||
|
@ -672,8 +708,46 @@ class svgHandler(xml.sax.ContentHandler):
|
||||||
rx = data['width'] / 2.0
|
rx = data['width'] / 2.0
|
||||||
if ry > 2 * data['height']:
|
if ry > 2 * data['height']:
|
||||||
ry = data['height'] / 2.0
|
ry = data['height'] / 2.0
|
||||||
#TBD
|
if rx > ry:
|
||||||
# Part.Ellipse(c,rx,ry).toShape() #needs a proxy object
|
mj = rx
|
||||||
|
mi = ry
|
||||||
|
else:
|
||||||
|
mj = ry
|
||||||
|
mi = rx
|
||||||
|
p1=Vector(data['x']+rx,-data['y']-data['height']+ry,0)
|
||||||
|
e1=Part.Ellipse(p1,mj,mi)
|
||||||
|
p2=Vector(data['x']+data['width']-rx,-data['y']-data['height']+ry,0)
|
||||||
|
e2=Part.Ellipse(p2,mj,mi)
|
||||||
|
p3=Vector(data['x']+data['width']-rx,-data['y']-ry,0)
|
||||||
|
e3=Part.Ellipse(p3,mj,mi)
|
||||||
|
p4=Vector(data['x']+rx,-data['y']-ry,0)
|
||||||
|
e4=Part.Ellipse(p4,mj,mi)
|
||||||
|
if rx > ry:
|
||||||
|
e1a=Part.Arc(e1,math.radians(180),math.radians(270))
|
||||||
|
e2a=Part.Arc(e2,math.radians(270),math.radians(360))
|
||||||
|
e3a=Part.Arc(e3,math.radians(0),math.radians(90))
|
||||||
|
e4a=Part.Arc(e4,math.radians(90),math.radians(180))
|
||||||
|
esh=[e1a.toShape(),e2a.toShape(),e3a.toShape(),e4a.toShape()]
|
||||||
|
else:
|
||||||
|
e1a=Part.Arc(e1,math.radians(90),math.radians(180))
|
||||||
|
e2a=Part.Arc(e2,math.radians(180),math.radians(270))
|
||||||
|
e3a=Part.Arc(e3,math.radians(270),math.radians(360))
|
||||||
|
e4a=Part.Arc(e4,math.radians(0),math.radians(90))
|
||||||
|
rot90=FreeCAD.Matrix(0,-1,0,0,1,0)
|
||||||
|
esh=[]
|
||||||
|
for arc,point in ((e1a,p1),(e2a,p2),(e3a,p3),(e4a,p4)):
|
||||||
|
m1=FreeCAD.Matrix()
|
||||||
|
m1.move(point.multiply(1))
|
||||||
|
m1=m1.multiply(rot90)
|
||||||
|
m1.move(point.multiply(-1))
|
||||||
|
#m1.move(point)
|
||||||
|
arc.transform(m1)
|
||||||
|
esh.append(arc.toShape())
|
||||||
|
for esh1,esh2 in zip(esh[-1:]+esh[:-1],esh):
|
||||||
|
p1,p2 = esh1.Vertexes[-1].Point,esh2.Vertexes[0].Point
|
||||||
|
if not fcvec.equals(p1,p2):
|
||||||
|
edges.append(Part.Line(esh1.Vertexes[-1].Point,esh2.Vertexes[0].Point).toShape()) #straight segments
|
||||||
|
edges.append(esh2) # elliptical segments
|
||||||
sh = Part.Wire(edges)
|
sh = Part.Wire(edges)
|
||||||
if self.fill: sh = Part.Face(sh)
|
if self.fill: sh = Part.Face(sh)
|
||||||
sh = self.applyTrans(sh)
|
sh = self.applyTrans(sh)
|
||||||
|
@ -938,6 +1012,11 @@ def insert(filename,docname):
|
||||||
def export(exportList,filename):
|
def export(exportList,filename):
|
||||||
"called when freecad exports a file"
|
"called when freecad exports a file"
|
||||||
|
|
||||||
|
svg_export_style = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetInt("svg_export_style")
|
||||||
|
if svg_export_style != 0 and svg_export_style != 1:
|
||||||
|
print "unknown svg export style, switching to Translated"
|
||||||
|
svg_export_style = 0
|
||||||
|
|
||||||
# finding sheet size
|
# finding sheet size
|
||||||
minx = 10000
|
minx = 10000
|
||||||
miny = 10000
|
miny = 10000
|
||||||
|
@ -950,7 +1029,13 @@ def export(exportList,filename):
|
||||||
if v.Point.x > maxx: maxx = v.Point.x
|
if v.Point.x > maxx: maxx = v.Point.x
|
||||||
if v.Point.y < miny: miny = v.Point.y
|
if v.Point.y < miny: miny = v.Point.y
|
||||||
if v.Point.y > maxy: maxy = v.Point.y
|
if v.Point.y > maxy: maxy = v.Point.y
|
||||||
|
if svg_export_style == 0:
|
||||||
|
# translated-style exports get a bit of a margin
|
||||||
margin = (maxx-minx)*.01
|
margin = (maxx-minx)*.01
|
||||||
|
else:
|
||||||
|
# raw-style exports get no margin
|
||||||
|
margin = 0
|
||||||
|
|
||||||
minx -= margin
|
minx -= margin
|
||||||
maxx += margin
|
maxx += margin
|
||||||
miny -= margin
|
miny -= margin
|
||||||
|
@ -958,26 +1043,38 @@ def export(exportList,filename):
|
||||||
sizex = maxx-minx
|
sizex = maxx-minx
|
||||||
sizey = maxy-miny
|
sizey = maxy-miny
|
||||||
miny += margin
|
miny += margin
|
||||||
boty = sizey+miny
|
|
||||||
|
|
||||||
# writing header
|
# writing header
|
||||||
|
# we specify the svg width and height in FreeCAD's physical units (mm),
|
||||||
|
# and specify the viewBox so that user units maps one-to-one to mm
|
||||||
svg = pythonopen(filename,'wb')
|
svg = pythonopen(filename,'wb')
|
||||||
svg.write('<?xml version="1.0"?>\n')
|
svg.write('<?xml version="1.0"?>\n')
|
||||||
svg.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"')
|
svg.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"')
|
||||||
svg.write(' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n')
|
svg.write(' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n')
|
||||||
svg.write('<svg')
|
svg.write('<svg')
|
||||||
svg.write(' width="' + str(sizex) + '" height="' + str(sizey) + '"')
|
svg.write(' width="' + str(sizex) + 'mm" height="' + str(sizey) + 'mm"')
|
||||||
|
if svg_export_style == 0:
|
||||||
|
# translated-style exports have the viewbox starting at X=0, Y=0
|
||||||
svg.write(' viewBox="0 0 ' + str(sizex) + ' ' + str(sizey) + '"')
|
svg.write(' viewBox="0 0 ' + str(sizex) + ' ' + str(sizey) + '"')
|
||||||
|
else:
|
||||||
|
# raw-style exports have the viewbox starting at X=0, Y=-height
|
||||||
|
# we need the funny Y here because SVG is upside down, and we
|
||||||
|
# flip the sketch right-way up with a scale later
|
||||||
|
svg.write(' viewBox="0 ' + str(sizey * -1.0) + ' ' + str(sizex) + ' ' + str(sizey) + '"')
|
||||||
svg.write(' xmlns="http://www.w3.org/2000/svg" version="1.1"')
|
svg.write(' xmlns="http://www.w3.org/2000/svg" version="1.1"')
|
||||||
svg.write('>\n')
|
svg.write('>\n')
|
||||||
|
|
||||||
# writing paths
|
# writing paths
|
||||||
for ob in exportList:
|
for ob in exportList:
|
||||||
|
if svg_export_style == 0:
|
||||||
|
# translated-style exports have the entire sketch translated to fit in the X>0, Y>0 quadrant
|
||||||
svg.write('<g transform="translate('+str(-minx)+','+str(-miny+(2*margin))+') scale(1,-1)">\n')
|
svg.write('<g transform="translate('+str(-minx)+','+str(-miny+(2*margin))+') scale(1,-1)">\n')
|
||||||
|
else:
|
||||||
|
# raw-style exports do not translate the sketch
|
||||||
|
svg.write('<g transform="scale(1,-1)">\n')
|
||||||
svg.write(Draft.getSVG(ob))
|
svg.write(Draft.getSVG(ob))
|
||||||
svg.write('</g>\n')
|
svg.write('</g>\n')
|
||||||
|
|
||||||
# closing
|
# closing
|
||||||
svg.write('</svg>')
|
svg.write('</svg>')
|
||||||
svg.close()
|
svg.close()
|
||||||
FreeCAD.Console.PrintMessage("successfully exported "+filename)
|
|
||||||
|
|
|
@ -50,11 +50,7 @@ class VersionControl:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.rev = ""
|
self.rev = ""
|
||||||
self.date = ""
|
self.date = ""
|
||||||
self.range = ""
|
|
||||||
self.url = ""
|
self.url = ""
|
||||||
self.time = ""
|
|
||||||
self.mods = "Src not modified"
|
|
||||||
self.mixed = "Src not mixed"
|
|
||||||
|
|
||||||
def extractInfo(self, srcdir):
|
def extractInfo(self, srcdir):
|
||||||
return False
|
return False
|
||||||
|
@ -67,11 +63,7 @@ class VersionControl:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = string.replace(line,'$WCREV$',self.rev)
|
line = string.replace(line,'$WCREV$',self.rev)
|
||||||
line = string.replace(line,'$WCDATE$',self.date)
|
line = string.replace(line,'$WCDATE$',self.date)
|
||||||
line = string.replace(line,'$WCRANGE$',self.range)
|
|
||||||
line = string.replace(line,'$WCURL$',self.url)
|
line = string.replace(line,'$WCURL$',self.url)
|
||||||
line = string.replace(line,'$WCNOW$',self.time)
|
|
||||||
line = string.replace(line,'$WCMODS?Src modified:Src not modified$',self.mods)
|
|
||||||
line = string.replace(line,'$WCMIXED?Src mixed:Src not mixed$',self.mixed)
|
|
||||||
content.append(line)
|
content.append(line)
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
@ -82,9 +74,7 @@ class UnknownControl(VersionControl):
|
||||||
return False
|
return False
|
||||||
self.rev = "Unknown"
|
self.rev = "Unknown"
|
||||||
self.date = "Unknown"
|
self.date = "Unknown"
|
||||||
self.range = "Unknown"
|
|
||||||
self.url = "Unknown"
|
self.url = "Unknown"
|
||||||
self.time = "Unknown"
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def printInfo(self):
|
def printInfo(self):
|
||||||
|
@ -104,13 +94,10 @@ class DebianChangelog(VersionControl):
|
||||||
r=re.search("bzr(\\d+)",c)
|
r=re.search("bzr(\\d+)",c)
|
||||||
if r != None:
|
if r != None:
|
||||||
self.rev = r.groups()[0] + " (Launchpad)"
|
self.rev = r.groups()[0] + " (Launchpad)"
|
||||||
self.range = self.rev
|
|
||||||
|
|
||||||
t = time.localtime()
|
t = time.localtime()
|
||||||
self.url = "https://code.launchpad.net/~vcs-imports/freecad/trunk"
|
|
||||||
#self.time = time.asctime()
|
|
||||||
self.date = ("%d/%02d/%02d %02d:%02d:%02d") % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
|
self.date = ("%d/%02d/%02d %02d:%02d:%02d") % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
|
||||||
self.time = ("%d/%02d/%02d %02d:%02d:%02d") % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
|
self.url = "https://code.launchpad.net/~vcs-imports/freecad/trunk"
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def printInfo(self):
|
def printInfo(self):
|
||||||
|
@ -121,8 +108,6 @@ class BazaarControl(VersionControl):
|
||||||
info=os.popen("bzr log -l 1 %s" % (srcdir)).read()
|
info=os.popen("bzr log -l 1 %s" % (srcdir)).read()
|
||||||
if len(info) == 0:
|
if len(info) == 0:
|
||||||
return False
|
return False
|
||||||
#Get the current local date
|
|
||||||
self.time = time.strftime("%Y/%m/%d %H:%M:%S")
|
|
||||||
lines=info.split("\n")
|
lines=info.split("\n")
|
||||||
for i in lines:
|
for i in lines:
|
||||||
r = re.match("^revno: (\\d+)$", i)
|
r = re.match("^revno: (\\d+)$", i)
|
||||||
|
@ -151,7 +136,6 @@ class GitControl(VersionControl):
|
||||||
if len(info) == 0:
|
if len(info) == 0:
|
||||||
return False
|
return False
|
||||||
self.rev='%04d (Git)' % (info.count('\n'))
|
self.rev='%04d (Git)' % (info.count('\n'))
|
||||||
self.range='%04d' % (info.count('\n'))
|
|
||||||
# date/time
|
# date/time
|
||||||
info=os.popen("git log -1 --date=iso").read()
|
info=os.popen("git log -1 --date=iso").read()
|
||||||
info=info.split("\n")
|
info=info.split("\n")
|
||||||
|
@ -159,9 +143,7 @@ class GitControl(VersionControl):
|
||||||
r = re.match("^Date:\\W+(\\d+-\\d+-\\d+\\W+\\d+:\\d+:\\d+)", i)
|
r = re.match("^Date:\\W+(\\d+-\\d+-\\d+\\W+\\d+:\\d+:\\d+)", i)
|
||||||
if r != None:
|
if r != None:
|
||||||
self.date = r.groups()[0].replace('-','/')
|
self.date = r.groups()[0].replace('-','/')
|
||||||
self.time = self.date
|
|
||||||
break
|
break
|
||||||
#self.time = time.strftime("%Y/%m/%d %H:%M:%S")
|
|
||||||
self.url = "Unknown"
|
self.url = "Unknown"
|
||||||
info=os.popen("git remote -v").read()
|
info=os.popen("git remote -v").read()
|
||||||
info=info.split("\n")
|
info=info.split("\n")
|
||||||
|
@ -170,11 +152,20 @@ class GitControl(VersionControl):
|
||||||
if r != None:
|
if r != None:
|
||||||
self.url = r.groups()[0]
|
self.url = r.groups()[0]
|
||||||
break
|
break
|
||||||
|
self.hash=os.popen("git log -1 --pretty=format:%H").read()
|
||||||
|
self.branch=os.popen("git branch").read().split('\n')[0][2:]
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def printInfo(self):
|
def printInfo(self):
|
||||||
print "git"
|
print "git"
|
||||||
|
|
||||||
|
def writeVersion(self, lines):
|
||||||
|
content = VersionControl.writeVersion(self, lines)
|
||||||
|
content.append('// Git relevant stuff\n')
|
||||||
|
content.append('#define FCRepositoryHash "%s"\n' % (self.hash))
|
||||||
|
content.append('#define FCRepositoryBranch "%s"\n' % (self.branch))
|
||||||
|
return content
|
||||||
|
|
||||||
class MercurialControl(VersionControl):
|
class MercurialControl(VersionControl):
|
||||||
def extractInfo(self, srcdir):
|
def extractInfo(self, srcdir):
|
||||||
return False
|
return False
|
||||||
|
|
104
src/Tools/makedist.py
Normal file
104
src/Tools/makedist.py
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#! python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# (c) 2006 Werner Mayer LGPL
|
||||||
|
#
|
||||||
|
# Python script to make source tarballs.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys, os, getopt, tarfile, gzip, time, StringIO, platform, shutil
|
||||||
|
|
||||||
|
def main():
|
||||||
|
srcdir="."
|
||||||
|
bindir="."
|
||||||
|
dfsg=False
|
||||||
|
check=False
|
||||||
|
wta=""
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "sb:", ["srcdir=","bindir=","dfsg", "check"])
|
||||||
|
except getopt.GetoptError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
for o, a in opts:
|
||||||
|
if o in ("-s", "--srcdir"):
|
||||||
|
srcdir = a
|
||||||
|
if o in ("-b", "--bindir"):
|
||||||
|
bindir = a
|
||||||
|
if o in ("--dfsg"):
|
||||||
|
dfsg = True
|
||||||
|
wta = "--worktree-attributes"
|
||||||
|
if o in ("--check"):
|
||||||
|
check = True
|
||||||
|
|
||||||
|
if dfsg:
|
||||||
|
gitattr = open("src/.gitattributes","w")
|
||||||
|
gitattr.write("zipios++ export-ignore\n")
|
||||||
|
gitattr.write("Pivy-0.5 export-ignore\n")
|
||||||
|
gitattr.write("Pivy export-ignore\n")
|
||||||
|
gitattr.close()
|
||||||
|
|
||||||
|
# revision number
|
||||||
|
info=os.popen("git rev-list HEAD").read()
|
||||||
|
revision='%04d' % (info.count('\n'))
|
||||||
|
|
||||||
|
PACKAGE_NAME = 'freecad'
|
||||||
|
version = "0.13.%s" % (revision)
|
||||||
|
|
||||||
|
DIRNAME = "%(p)s-%(v)s" % {'p': PACKAGE_NAME, 'v': version}
|
||||||
|
TARNAME = DIRNAME + '.tar'
|
||||||
|
TGZNAME = DIRNAME + '.tar.gz'
|
||||||
|
if dfsg:
|
||||||
|
TGZNAME = DIRNAME + '-dfsg.tar.gz'
|
||||||
|
|
||||||
|
verfile = open("%s/src/Build/Version.h" % (bindir), 'r')
|
||||||
|
verstream = StringIO.StringIO(verfile.read())
|
||||||
|
verfile.close()
|
||||||
|
verinfo = tarfile.TarInfo(DIRNAME + "/src/Build/Version.h")
|
||||||
|
verinfo.mode = 0660
|
||||||
|
verinfo.size = len(verstream.getvalue())
|
||||||
|
verinfo.mtime = time.time()
|
||||||
|
|
||||||
|
print "git archive %s --prefix=%s/ HEAD" % (wta, DIRNAME)
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
os.popen("git archive %s --prefix=%s/ --output=%s HEAD"
|
||||||
|
% (wta, DIRNAME, TARNAME)).read()
|
||||||
|
|
||||||
|
tar = tarfile.TarFile(mode="a", name=TARNAME)
|
||||||
|
tar.addfile(verinfo, verstream)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
out = gzip.open(TGZNAME, "wb")
|
||||||
|
tardata = open(TARNAME, 'rb')
|
||||||
|
out.write(tardata.read())
|
||||||
|
out.close()
|
||||||
|
tardata.close()
|
||||||
|
os.remove(TARNAME)
|
||||||
|
else:
|
||||||
|
tardata = os.popen("git archive %s --prefix=%s/ HEAD"
|
||||||
|
% (wta, DIRNAME)).read()
|
||||||
|
tarstream = StringIO.StringIO(tardata)
|
||||||
|
|
||||||
|
tar = tarfile.TarFile(mode="a", fileobj=tarstream)
|
||||||
|
tar.addfile(verinfo, verstream)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
out = gzip.open(TGZNAME, "wb")
|
||||||
|
out.write(tarstream.getvalue())
|
||||||
|
out.close()
|
||||||
|
|
||||||
|
if dfsg:
|
||||||
|
os.remove("src/.gitattributes")
|
||||||
|
print "Created " + TGZNAME
|
||||||
|
# Unpack and build
|
||||||
|
if check:
|
||||||
|
archive=tarfile.open(mode='r:gz',name=TGZNAME)
|
||||||
|
archive.extractall(bindir)
|
||||||
|
builddir = os.path.join(bindir, DIRNAME)
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.chdir(builddir)
|
||||||
|
os.system("cmake .")
|
||||||
|
os.system("make")
|
||||||
|
os.chdir(cwd)
|
||||||
|
shutil.rmtree(builddir)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user