Merge branch 'master' of ssh://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad into sanguinariojoe-ship
This commit is contained in:
commit
91599cf603
|
@ -206,7 +206,7 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
|
|||
if( ${OCE_FOUND} )
|
||||
message("-- OpenCASCADE Community Edition has been found.")
|
||||
add_definitions ( -DHAVE_CONFIG_H )
|
||||
set( OCC_LIBRARIES "TKFillet;TKMesh;TKernel;TKG2d;TKG3d;TKMath;TKIGES;TKSTL;TKShHealing;TKXSBase;TKBool;TKBO;TKBRep;TKTopAlgo;TKGeomAlgo;TKGeomBase;TKOffset;TKPrim;TKSTEP;TKSTEPBase;TKSTEPAttr;TKHLR" ) #lib list copied from FreeCAD's FindOpenCasCade.cmake
|
||||
set( OCC_LIBRARIES "TKFeat;TKFillet;TKMesh;TKernel;TKG2d;TKG3d;TKMath;TKIGES;TKSTL;TKShHealing;TKXSBase;TKBool;TKBO;TKBRep;TKTopAlgo;TKGeomAlgo;TKGeomBase;TKOffset;TKPrim;TKSTEP;TKSTEPBase;TKSTEPAttr;TKHLR" ) #lib list copied from FreeCAD's FindOpenCasCade.cmake
|
||||
set( OCC_INCLUDE_DIR ${OCE_INCLUDE_DIRS} )
|
||||
set( OCC_FOUND ${OCE_FOUND} )
|
||||
else() #look for OpenCASCADE
|
||||
|
@ -219,12 +219,6 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
|
|||
ENDIF()
|
||||
endif()
|
||||
|
||||
# -------------------------------- f2c ----------------------------------
|
||||
|
||||
IF(OCC_FOUND)
|
||||
find_package(F2C REQUIRED)
|
||||
ENDIF(OCC_FOUND)
|
||||
|
||||
# -------------------------------- Salome SMESH --------------------------
|
||||
|
||||
# Salome SMESH sources are under src/3rdParty now
|
||||
|
@ -268,7 +262,7 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
|
|||
|
||||
# -------------------------------- ODE ----------------------------------
|
||||
|
||||
find_package(ODE)
|
||||
# find_package(ODE)
|
||||
|
||||
# -------------------------------- Qt --------------------------------
|
||||
|
||||
|
@ -439,7 +433,7 @@ if(FREECAD_MAINTAINERS_BUILD AND NOT WIN32)
|
|||
set(PKG_ARCH amd64)
|
||||
ENDIF( CMAKE_SIZEOF_VOID_P EQUAL 4 )
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "science")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "python, oce | opencascade, libqtgui4, libcoin60, libode1, libsoqt4-20, libxerces-c3.1, libgts-0.7-5, zlib1g, libboost-dev, libeigen2-dev")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "python, oce | opencascade, libqtgui4, libcoin60, libsoqt4-20, libxerces-c3.1, zlib1g, libboost-dev, libeigen2-dev")
|
||||
set(CPACK_PACKAGE_CONTACT "<root@localhost>")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_NAME}-${PACKAGE_VERSION}_${PKG_ARCH}")
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ IF(OCC_LIBRARY)
|
|||
TKSTEPBase
|
||||
TKSTEPAttr
|
||||
TKHLR
|
||||
TKFeat
|
||||
)
|
||||
ENDIF(OCC_LIBRARY)
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ by the authors who actually wrote it.
|
|||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
51 Franklin Street - Fifth Floor
|
||||
Boston, MA 02110-1301, USA.
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
|
2
src/3rdParty/salomesmesh/CMakeLists.txt
vendored
2
src/3rdParty/salomesmesh/CMakeLists.txt
vendored
|
@ -173,7 +173,7 @@ FILE(GLOB StdMeshers_source_files src/StdMeshers/*.cpp src/MEFISTO2/*.cpp src/ME
|
|||
INCLUDE_DIRECTORIES(src/StdMeshers)
|
||||
|
||||
ADD_LIBRARY(StdMeshers SHARED ${StdMeshers_source_files})
|
||||
TARGET_LINK_LIBRARIES(StdMeshers SMESH TKernel TKMath TKAdvTools f2c gfortran)
|
||||
TARGET_LINK_LIBRARIES(StdMeshers SMESH TKernel TKMath TKAdvTools gfortran)
|
||||
SET(StdMeshers_CFLAGS "")
|
||||
IF(WIN32)
|
||||
SET(StdMeshers_CFLAGS "-DSTDMESHERS_EXPORTS -DMEFISTO2D_EXPORTS")
|
||||
|
|
|
@ -1188,13 +1188,13 @@ void Application::processCmdLineFiles(void)
|
|||
Application::_pcSingleton->openDocument(File.filePath().c_str());
|
||||
}
|
||||
else if (File.hasExtension("fcscript")||File.hasExtension("fcmacro")) {
|
||||
Base::Interpreter().runFile(File.filePath().c_str(), false);
|
||||
Base::Interpreter().runFile(File.filePath().c_str(), true);
|
||||
}
|
||||
else if (File.hasExtension("py")) {
|
||||
//FIXME: Does this make any sense? I think we should do the ame as for
|
||||
// fcmacro or fcscript.
|
||||
//Base::Interpreter().loadModule(File.fileNamePure().c_str());
|
||||
Base::Interpreter().runFile(File.filePath().c_str(), false);
|
||||
Base::Interpreter().runFile(File.filePath().c_str(), true);
|
||||
}
|
||||
else {
|
||||
std::vector<std::string> mods = App::GetApplication().getImportModules(Ext.c_str());
|
||||
|
@ -1210,8 +1210,7 @@ void Application::processCmdLineFiles(void)
|
|||
}
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
Base::PyGILStateLocker locker;
|
||||
Base::Interpreter().systemExit();
|
||||
throw; // re-throw to main() function
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Console().Error("Exception while processing file: %s [%s]\n", File.filePath().c_str(), e.what());
|
||||
|
@ -1523,20 +1522,23 @@ void Application::ParseOptions(int ac, char ** av)
|
|||
notify(vm);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
cerr << e.what() << endl << endl << visible << endl;
|
||||
exit(1);
|
||||
std::stringstream str;
|
||||
str << e.what() << endl << endl << visible << endl;
|
||||
throw UnknownProgramOption(str.str());
|
||||
}
|
||||
catch (...) {
|
||||
cerr << "Wrong or unknown option, bailing out!" << endl << endl << visible << endl;
|
||||
exit(1);
|
||||
std::stringstream str;
|
||||
str << "Wrong or unknown option, bailing out!" << endl << endl << visible << endl;
|
||||
throw UnknownProgramOption(str.str());
|
||||
}
|
||||
|
||||
if (vm.count("help")) {
|
||||
cout << mConfig["ExeName"] << endl << endl;
|
||||
cout << "For detailed descripton see http://free-cad.sf.net" << endl<<endl;
|
||||
cout << "Usage: " << mConfig["ExeName"] << " [options] File1 File2 ..." << endl << endl;
|
||||
cout << visible << endl;
|
||||
exit(0);
|
||||
std::stringstream str;
|
||||
str << mConfig["ExeName"] << endl << endl;
|
||||
str << "For detailed descripton see http://free-cad.sf.net" << endl<<endl;
|
||||
str << "Usage: " << mConfig["ExeName"] << " [options] File1 File2 ..." << endl << endl;
|
||||
str << visible << endl;
|
||||
throw Base::ProgramInformation(str.str());
|
||||
}
|
||||
|
||||
if (vm.count("response-file")) {
|
||||
|
@ -1544,9 +1546,10 @@ void Application::ParseOptions(int ac, char ** av)
|
|||
std::ifstream ifs(vm["response-file"].as<string>().c_str());
|
||||
if (!ifs) {
|
||||
Base::Console().Error("Could no open the response file\n");
|
||||
cerr << "Could no open the response file: '"
|
||||
<< vm["response-file"].as<string>() << "'" << endl;
|
||||
exit(1);
|
||||
std::stringstream str;
|
||||
str << "Could no open the response file: '"
|
||||
<< vm["response-file"].as<string>() << "'" << endl;
|
||||
throw Base::UnknownProgramOption(str.str());
|
||||
}
|
||||
// Read the whole file into a string
|
||||
stringstream ss;
|
||||
|
@ -1562,9 +1565,10 @@ void Application::ParseOptions(int ac, char ** av)
|
|||
}
|
||||
|
||||
if (vm.count("version")) {
|
||||
std::cout << mConfig["ExeName"] << " " << mConfig["ExeVersion"]
|
||||
<< " Revision: " << mConfig["BuildRevision"] << std::endl;
|
||||
exit(0);
|
||||
std::stringstream str;
|
||||
str << mConfig["ExeName"] << " " << mConfig["ExeVersion"]
|
||||
<< " Revision: " << mConfig["BuildRevision"] << std::endl;
|
||||
throw Base::ProgramInformation(str.str());
|
||||
}
|
||||
|
||||
if (vm.count("console")) {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <Base/Console.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <iostream>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
using namespace App;
|
||||
|
||||
|
@ -82,10 +83,20 @@ std::string PropertyPythonObject::toString() const
|
|||
std::string repr;
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Module pickle(PyImport_ImportModule("cPickle"),true);
|
||||
Py::Module pickle(PyImport_ImportModule("json"),true);
|
||||
Py::Callable method(pickle.getAttr(std::string("dumps")));
|
||||
Py::Object dump;
|
||||
if (this->object.hasAttr("__getstate__")) {
|
||||
Py::Tuple args(0);
|
||||
Py::Callable state(this->object.getAttr("__getstate__"));
|
||||
dump = state.apply(args);
|
||||
}
|
||||
else if (this->object.hasAttr("__dict__")) {
|
||||
dump = this->object.getAttr("__dict__");
|
||||
}
|
||||
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, this->object);
|
||||
args.setItem(0, dump);
|
||||
Py::Object res = method.apply(args);
|
||||
Py::String str(res);
|
||||
repr = str.as_std_string();
|
||||
|
@ -102,12 +113,21 @@ void PropertyPythonObject::fromString(const std::string& repr)
|
|||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Module pickle(PyImport_ImportModule("cPickle"),true);
|
||||
Py::Module pickle(PyImport_ImportModule("json"),true);
|
||||
Py::Callable method(pickle.getAttr(std::string("loads")));
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::String(repr));
|
||||
Py::Object res = method.apply(args);
|
||||
this->object = res;
|
||||
|
||||
if (this->object.hasAttr("__setstate__")) {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, res);
|
||||
Py::Callable state(this->object.getAttr("__setstate__"));
|
||||
state.apply(args);
|
||||
}
|
||||
else {
|
||||
this->object.setAttr("__dict__", res);
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
|
@ -115,6 +135,32 @@ void PropertyPythonObject::fromString(const std::string& repr)
|
|||
}
|
||||
}
|
||||
|
||||
void PropertyPythonObject::loadPickle(const std::string& str)
|
||||
{
|
||||
// find the custom attributes and restore them
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
std::string buffer = str;
|
||||
boost::regex pickle("S'(\\w+)'.+S'(\\w+)'\\n");
|
||||
boost::match_results<std::string::const_iterator> what;
|
||||
std::string::const_iterator start, end;
|
||||
start = buffer.begin();
|
||||
end = buffer.end();
|
||||
while (boost::regex_search(start, end, what, pickle)) {
|
||||
std::string key = std::string(what[1].first, what[1].second);
|
||||
std::string val = std::string(what[2].first, what[2].second);
|
||||
this->object.setAttr(key, Py::String(val));
|
||||
buffer = std::string(what[2].second, end);
|
||||
start = buffer.begin();
|
||||
end = buffer.end();
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Warning("PropertyPythonObject::loadPickle: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string PropertyPythonObject::encodeValue(const std::string& str) const
|
||||
{
|
||||
std::string tmp;
|
||||
|
@ -210,7 +256,25 @@ void PropertyPythonObject::Save (Base::Writer &writer) const
|
|||
repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size());
|
||||
std::string val = /*encodeValue*/(repr);
|
||||
writer.Stream() << writer.ind() << "<Python value=\"" << val
|
||||
<<"\" encoded=\"yes\"";
|
||||
<< "\" encoded=\"yes\"";
|
||||
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
if (this->object.hasAttr("__module__") && this->object.hasAttr("__class__")) {
|
||||
Py::String mod(this->object.getAttr("__module__"));
|
||||
Py::Object cls(this->object.getAttr("__class__"));
|
||||
if (cls.hasAttr("__name__")) {
|
||||
Py::String name(cls.getAttr("__name__"));
|
||||
writer.Stream() << " module=\"" << (std::string)mod << "\""
|
||||
<< " class=\"" << (std::string)name << "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Warning("PropertyPythonObject::Save: %s\n", e.what());
|
||||
}
|
||||
|
||||
saveObject(writer);
|
||||
writer.Stream() << "/>" << std::endl;
|
||||
//}
|
||||
|
@ -228,6 +292,8 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader)
|
|||
reader.addFile(file.c_str(),this);
|
||||
}
|
||||
else {
|
||||
bool load_json=false;
|
||||
bool load_pickle=false;
|
||||
std::string buffer = reader.getAttribute("value");
|
||||
if (reader.hasAttribute("encoded") &&
|
||||
strcmp(reader.getAttribute("encoded"),"yes") == 0) {
|
||||
|
@ -237,8 +303,39 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader)
|
|||
buffer = decodeValue(buffer);
|
||||
}
|
||||
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
boost::regex pickle("^\\(i(\\w+)\\n(\\w+)\\n");
|
||||
boost::match_results<std::string::const_iterator> what;
|
||||
std::string::const_iterator start, end;
|
||||
start = buffer.begin();
|
||||
end = buffer.end();
|
||||
if (reader.hasAttribute("module") && reader.hasAttribute("class")) {
|
||||
Py::Module mod(PyImport_ImportModule(reader.getAttribute("module")),true);
|
||||
this->object = PyInstance_NewRaw(mod.getAttr(reader.getAttribute("class")).ptr(), 0);
|
||||
load_json = true;
|
||||
}
|
||||
else if (boost::regex_search(start, end, what, pickle)) {
|
||||
std::string nam = std::string(what[1].first, what[1].second);
|
||||
std::string cls = std::string(what[2].first, what[2].second);
|
||||
Py::Module mod(PyImport_ImportModule(nam.c_str()),true);
|
||||
this->object = PyInstance_NewRaw(mod.getAttr(cls).ptr(), 0);
|
||||
load_pickle = true;
|
||||
buffer = std::string(what[2].second, end);
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::Console().Warning("PropertyPythonObject::Restore: %s\n", e.what());
|
||||
}
|
||||
|
||||
aboutToSetValue();
|
||||
this->fromString(buffer);
|
||||
if (load_json)
|
||||
this->fromString(buffer);
|
||||
else if (load_pickle)
|
||||
this->loadPickle(buffer);
|
||||
else
|
||||
Base::Console().Warning("PropertyPythonObject::Restore: unsupported serialisation: %s\n", buffer.c_str());
|
||||
restoreObject(reader);
|
||||
hasSetValue();
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ private:
|
|||
void restoreObject(Base::XMLReader &reader);
|
||||
std::string encodeValue(const std::string& str) const;
|
||||
std::string decodeValue(const std::string& str) const;
|
||||
void loadPickle(const std::string& str);
|
||||
Py::Object object;
|
||||
};
|
||||
|
||||
|
|
|
@ -202,6 +202,40 @@ AbnormalProgramTermination::AbnormalProgramTermination(const AbnormalProgramTerm
|
|||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
UnknownProgramOption::UnknownProgramOption(const char * sMessage)
|
||||
: Exception(sMessage)
|
||||
{
|
||||
}
|
||||
|
||||
UnknownProgramOption::UnknownProgramOption(const std::string& sMessage)
|
||||
: Exception(sMessage)
|
||||
{
|
||||
}
|
||||
|
||||
UnknownProgramOption::UnknownProgramOption(const UnknownProgramOption &inst)
|
||||
: Exception(inst)
|
||||
{
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
ProgramInformation::ProgramInformation(const char * sMessage)
|
||||
: Exception(sMessage)
|
||||
{
|
||||
}
|
||||
|
||||
ProgramInformation::ProgramInformation(const std::string& sMessage)
|
||||
: Exception(sMessage)
|
||||
{
|
||||
}
|
||||
|
||||
ProgramInformation::ProgramInformation(const ProgramInformation &inst)
|
||||
: Exception(inst)
|
||||
{
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
#if defined(__GNUC__) && defined (FC_OS_LINUX)
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
|
|
@ -174,6 +174,38 @@ public:
|
|||
virtual ~AbnormalProgramTermination() throw() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* The UnknownProgramOption can be used to indicate an unknown program option.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
class BaseExport UnknownProgramOption : public Exception
|
||||
{
|
||||
public:
|
||||
/// Construction
|
||||
UnknownProgramOption(const char * sMessage);
|
||||
UnknownProgramOption(const std::string& sMessage);
|
||||
/// Construction
|
||||
UnknownProgramOption(const UnknownProgramOption &inst);
|
||||
/// Destruction
|
||||
virtual ~UnknownProgramOption() throw() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* The ProgramInformation can be used to show information about the program.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
class BaseExport ProgramInformation : public Exception
|
||||
{
|
||||
public:
|
||||
/// Construction
|
||||
ProgramInformation(const char * sMessage);
|
||||
ProgramInformation(const std::string& sMessage);
|
||||
/// Construction
|
||||
ProgramInformation(const ProgramInformation &inst);
|
||||
/// Destruction
|
||||
virtual ~ProgramInformation() throw() {}
|
||||
};
|
||||
|
||||
|
||||
inline void Exception::setMessage(const char * sMessage)
|
||||
{
|
||||
|
|
|
@ -190,7 +190,6 @@ void InterpreterSingleton::runInteractiveString(const char *sCmd)
|
|||
presult = PyRun_String(sCmd, Py_single_input, dict, dict); /* eval direct */
|
||||
if (!presult) {
|
||||
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
|
||||
//systemExit();
|
||||
throw SystemExitException();
|
||||
}
|
||||
/* get latest python exception information */
|
||||
|
|
|
@ -1545,8 +1545,16 @@ void Application::runApplication(void)
|
|||
int argc = App::Application::GetARGC();
|
||||
GUIApplication mainApp(argc, App::Application::GetARGV());
|
||||
// set application icon and window title
|
||||
const std::map<std::string,std::string>& cfg = App::Application::Config();
|
||||
std::map<std::string,std::string>::const_iterator it;
|
||||
it = cfg.find("Application");
|
||||
if (it != cfg.end()) {
|
||||
mainApp.setApplicationName(QString::fromUtf8(it->second.c_str()));
|
||||
}
|
||||
else {
|
||||
mainApp.setApplicationName(QString::fromUtf8(App::GetApplication().getExecutableName()));
|
||||
}
|
||||
mainApp.setWindowIcon(Gui::BitmapFactory().pixmap(App::Application::Config()["AppIcon"].c_str()));
|
||||
mainApp.setApplicationName(QString::fromAscii(App::GetApplication().getExecutableName()));
|
||||
QString plugin;
|
||||
plugin = QString::fromUtf8(App::GetApplication().GetHomePath());
|
||||
plugin += QLatin1String("/plugins");
|
||||
|
@ -1606,8 +1614,6 @@ void Application::runApplication(void)
|
|||
|
||||
QString home = QString::fromUtf8(App::GetApplication().GetHomePath());
|
||||
|
||||
const std::map<std::string,std::string>& cfg = App::Application::Config();
|
||||
std::map<std::string,std::string>::const_iterator it;
|
||||
it = cfg.find("WindowTitle");
|
||||
if (it != cfg.end()) {
|
||||
QString title = QString::fromUtf8(it->second.c_str());
|
||||
|
|
|
@ -292,7 +292,7 @@ StdCmdMergeProjects::StdCmdMergeProjects()
|
|||
|
||||
void StdCmdMergeProjects::activated(int iMsg)
|
||||
{
|
||||
QString exe = QString::fromUtf8(App::GetApplication().getExecutableName());
|
||||
QString exe = qApp->applicationName();
|
||||
QString project = QFileDialog::getOpenFileName(Gui::getMainWindow(),
|
||||
QString::fromUtf8(QT_TR_NOOP("Merge project")), QDir::homePath(),
|
||||
QString::fromUtf8(QT_TR_NOOP("%1 document (*.fcstd)")).arg(exe));
|
||||
|
|
|
@ -193,13 +193,7 @@ Action * StdCmdAbout::createAction(void)
|
|||
{
|
||||
Action *pcAction;
|
||||
|
||||
QString exe;
|
||||
std::map<std::string,std::string>& cfg = App::Application::Config();
|
||||
std::map<std::string,std::string>::iterator it = cfg.find("Application");
|
||||
if (it != cfg.end())
|
||||
exe = QString::fromUtf8(it->second.c_str());
|
||||
else
|
||||
exe = QString::fromUtf8(App::GetApplication().getExecutableName());
|
||||
QString exe = qApp->applicationName();
|
||||
pcAction = new Action(this,getMainWindow());
|
||||
pcAction->setText(QCoreApplication::translate(
|
||||
this->className(), sMenuText, 0,
|
||||
|
@ -235,13 +229,7 @@ void StdCmdAbout::activated(int iMsg)
|
|||
void StdCmdAbout::languageChange()
|
||||
{
|
||||
if (_pcAction) {
|
||||
QString exe;
|
||||
std::map<std::string,std::string>& cfg = App::Application::Config();
|
||||
std::map<std::string,std::string>::iterator it = cfg.find("Application");
|
||||
if (it != cfg.end())
|
||||
exe = QString::fromUtf8(it->second.c_str());
|
||||
else
|
||||
exe = QString::fromUtf8(App::GetApplication().getExecutableName());
|
||||
QString exe = qApp->applicationName();
|
||||
_pcAction->setText(QCoreApplication::translate(
|
||||
this->className(), sMenuText, 0,
|
||||
QCoreApplication::CodecForTr).arg(exe));
|
||||
|
|
|
@ -1,45 +1,62 @@
|
|||
<ui version="4.0" >
|
||||
<author></author>
|
||||
<comment></comment>
|
||||
<exportmacro></exportmacro>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::Dialog::DlgSettingsMacro</class>
|
||||
<widget class="QWidget" name="Gui::Dialog::DlgSettingsMacro" >
|
||||
<property name="geometry" >
|
||||
<widget class="QWidget" name="Gui::Dialog::DlgSettingsMacro">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>384</width>
|
||||
<height>388</height>
|
||||
<width>391</width>
|
||||
<height>407</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<property name="windowTitle">
|
||||
<string>Macro</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QGroupBox" name="GroupBox6" >
|
||||
<property name="title" >
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>General macro settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="PrefCheckBox_LocalEnv">
|
||||
<property name="text">
|
||||
<string>Run macros in local environment</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>LocalEnvironment</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Macro</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="GroupBox6">
|
||||
<property name="title">
|
||||
<string>Macro recording settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="0" >
|
||||
<item row="3" column="0">
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
|
@ -47,56 +64,56 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QGroupBox" name="groupBox4" >
|
||||
<property name="title" >
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox4">
|
||||
<property name="title">
|
||||
<string>Logging Commands</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="PConsoleCheckBox" >
|
||||
<property name="text" >
|
||||
<widget class="Gui::PrefCheckBox" name="PConsoleCheckBox">
|
||||
<property name="text">
|
||||
<string>Show script commands in python console</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ScriptToPyConsole</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0" >
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Macro</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="FileLogCheckBox" >
|
||||
<property name="text" >
|
||||
<widget class="Gui::PrefCheckBox" name="FileLogCheckBox">
|
||||
<property name="text">
|
||||
<string>Log all commands issued by menus to file:</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0" >
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ScriptToFile</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0" >
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Macro</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefFileChooser" name="MacroPath_2" >
|
||||
<property name="fileName" >
|
||||
<widget class="Gui::PrefFileChooser" name="MacroPath_2">
|
||||
<property name="fileName">
|
||||
<string>FullScript.FCScript</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0" >
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ScriptFile</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0" >
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Macro</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -104,46 +121,46 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QGroupBox" name="GroupBox7" >
|
||||
<property name="title" >
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="GroupBox7">
|
||||
<property name="title">
|
||||
<string>Gui commands</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<widget class="Gui::PrefCheckBox" name="PrefCheckBox_RecordGui" >
|
||||
<property name="text" >
|
||||
<item row="0" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="PrefCheckBox_RecordGui">
|
||||
<property name="text">
|
||||
<string>Recording GUI commands</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0" >
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>RecordGui</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0" >
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Macro</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="Gui::PrefCheckBox" name="PrefCheckBox_GuiAsComment" >
|
||||
<property name="text" >
|
||||
<item row="1" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="PrefCheckBox_GuiAsComment">
|
||||
<property name="text">
|
||||
<string>Record as comment</string>
|
||||
</property>
|
||||
<property name="checked" >
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0" >
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>GuiAsComment</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0" >
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Macro</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -151,27 +168,27 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QGroupBox" name="GroupBox8" >
|
||||
<property name="title" >
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="GroupBox8">
|
||||
<property name="title">
|
||||
<string>Macro path</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<widget class="Gui::PrefFileChooser" name="MacroPath" >
|
||||
<property name="mode" >
|
||||
<item row="0" column="0">
|
||||
<widget class="Gui::PrefFileChooser" name="MacroPath">
|
||||
<property name="mode">
|
||||
<enum>Gui::FileChooser::Directory</enum>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0" >
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>MacroPath</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0" >
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Macro</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -184,21 +201,22 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11" />
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
<container>0</container>
|
||||
<pixmap></pixmap>
|
||||
<class>Gui::FileChooser</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/FileDialog.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefFileChooser</class>
|
||||
<extends>Gui::FileChooser</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
<container>0</container>
|
||||
<pixmap></pixmap>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
@ -209,11 +227,11 @@
|
|||
<receiver>PrefCheckBox_GuiAsComment</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
|
|
|
@ -54,6 +54,7 @@ DlgSettingsMacroImp::~DlgSettingsMacroImp()
|
|||
|
||||
void DlgSettingsMacroImp::saveSettings()
|
||||
{
|
||||
PrefCheckBox_LocalEnv->onSave();
|
||||
MacroPath->onSave();
|
||||
PrefCheckBox_RecordGui->onSave();
|
||||
PrefCheckBox_GuiAsComment->onSave();
|
||||
|
@ -64,6 +65,7 @@ void DlgSettingsMacroImp::saveSettings()
|
|||
|
||||
void DlgSettingsMacroImp::loadSettings()
|
||||
{
|
||||
PrefCheckBox_LocalEnv->onRestore();
|
||||
MacroPath->onRestore();
|
||||
PrefCheckBox_RecordGui->onRestore();
|
||||
PrefCheckBox_GuiAsComment->onRestore();
|
||||
|
|
|
@ -504,7 +504,7 @@ bool Document::saveAs(void)
|
|||
{
|
||||
getMainWindow()->statusBar()->showMessage(QObject::tr("Save document under new filename..."));
|
||||
|
||||
QString exe = QString::fromUtf8(App::GetApplication().getExecutableName());
|
||||
QString exe = qApp->applicationName();
|
||||
QString fn = QFileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe),
|
||||
FileDialog::getWorkingDirectory(), QObject::tr("%1 document (*.FCStd)").arg(exe));
|
||||
if (!fn.isEmpty()) {
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* write to the Free Software Foundation, Inc., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#ifndef _PreComp_
|
||||
# include <assert.h>
|
||||
# include <stdio.h>
|
||||
# include <QApplication>
|
||||
# include <QFile>
|
||||
# include <QTextStream>
|
||||
#endif
|
||||
|
@ -71,6 +72,7 @@ void MacroManager::OnChange(Base::Subject<const char*> &rCaller, const char * sR
|
|||
this->recordGui = this->params->GetBool("RecordGui", true);
|
||||
this->guiAsComment = this->params->GetBool("GuiAsComment", true);
|
||||
this->scriptToPyConsole = this->params->GetBool("ScriptToPyConsole", true);
|
||||
this->localEnv = this->params->GetBool("LocalEnvironment", true);
|
||||
}
|
||||
|
||||
void MacroManager::open(MacroType eType,const char *sName)
|
||||
|
@ -228,12 +230,10 @@ void MacroManager::run(MacroType eType,const char *sName)
|
|||
PythonRedirector std_out("stdout",pyout);
|
||||
PythonRedirector std_err("stderr",pyerr);
|
||||
//The given path name is expected to be Utf-8
|
||||
Base::Interpreter().runFile(sName, true);
|
||||
Base::Interpreter().runFile(sName, this->localEnv);
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
Base::PyGILStateLocker lock;
|
||||
PyErr_Clear();
|
||||
Base::Interpreter().systemExit();
|
||||
qApp->quit();
|
||||
}
|
||||
catch (const Base::PyException& e) {
|
||||
Base::Console().Error("%s%s: %s\n",
|
||||
|
|
|
@ -98,6 +98,7 @@ protected:
|
|||
bool recordGui;
|
||||
bool guiAsComment;
|
||||
bool scriptToPyConsole;
|
||||
bool localEnv;
|
||||
PythonConsole* pyConsole; // link to the python console
|
||||
PythonDebugger* pyDebugger;
|
||||
Base::Reference<ParameterGrp> params; // link to the Macro parameter group
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include <Base/Parameter.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/FileInfo.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Persistence.h>
|
||||
#include <Base/Stream.h>
|
||||
#include <Base/Reader.h>
|
||||
|
@ -1152,7 +1153,13 @@ void MainWindow::showMainWindow()
|
|||
void MainWindow::delayedStartup()
|
||||
{
|
||||
// processing all command line files
|
||||
App::Application::processCmdLineFiles();
|
||||
try {
|
||||
App::Application::processCmdLineFiles();
|
||||
}
|
||||
catch (const Base::SystemExitException&) {
|
||||
QApplication::quit();
|
||||
return;
|
||||
}
|
||||
|
||||
const std::map<std::string,std::string>& cfg = App::Application::Config();
|
||||
std::map<std::string,std::string>::const_iterator it = cfg.find("StartHidden");
|
||||
|
@ -1318,10 +1325,7 @@ QPixmap MainWindow::splashImage() const
|
|||
// include application name and version number
|
||||
std::map<std::string,std::string>::const_iterator tc = App::Application::Config().find("SplashInfoColor");
|
||||
if (tc != App::Application::Config().end()) {
|
||||
QString title = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
|
||||
std::map<std::string,std::string>::iterator it = App::Application::Config().find("Application");
|
||||
if (it != App::Application::Config().end())
|
||||
title = QString::fromUtf8(it->second.c_str());
|
||||
QString title = qApp->applicationName();
|
||||
QString major = QString::fromAscii(App::Application::Config()["BuildVersionMajor"].c_str());
|
||||
QString minor = QString::fromAscii(App::Application::Config()["BuildVersionMinor"].c_str());
|
||||
QString version = QString::fromAscii("%1.%2").arg(major).arg(minor);
|
||||
|
|
|
@ -1118,11 +1118,13 @@ SbBool NavigationStyle::processEvent(const SoEvent * const ev)
|
|||
pcPolygon = mouseSelection->getPositions();
|
||||
clipInner = mouseSelection->isInner();
|
||||
delete mouseSelection; mouseSelection = 0;
|
||||
syncWithEvent(ev);
|
||||
return NavigationStyle::processSoEvent(ev);
|
||||
}
|
||||
else if (hd==AbstractMouseSelection::Cancel) {
|
||||
pcPolygon.clear();
|
||||
delete mouseSelection; mouseSelection = 0;
|
||||
syncWithEvent(ev);
|
||||
return NavigationStyle::processSoEvent(ev);
|
||||
}
|
||||
}
|
||||
|
@ -1150,6 +1152,72 @@ SbBool NavigationStyle::processSoEvent(const SoEvent * const ev)
|
|||
return viewer->processSoEventBase(ev);
|
||||
}
|
||||
|
||||
void NavigationStyle::syncWithEvent(const SoEvent * const ev)
|
||||
{
|
||||
// Events when in "ready-to-seek" mode are ignored, except those
|
||||
// which influence the seek mode itself -- these are handled further
|
||||
// up the inheritance hierarchy.
|
||||
if (this->isSeekMode()) { return; }
|
||||
|
||||
const SoType type(ev->getTypeId());
|
||||
|
||||
// Mismatches in state of the modifier keys happens if the user
|
||||
// presses or releases them outside the viewer window.
|
||||
if (this->ctrldown != ev->wasCtrlDown()) {
|
||||
this->ctrldown = ev->wasCtrlDown();
|
||||
}
|
||||
if (this->shiftdown != ev->wasShiftDown()) {
|
||||
this->shiftdown = ev->wasShiftDown();
|
||||
}
|
||||
if (this->altdown != ev->wasAltDown()) {
|
||||
this->altdown = ev->wasAltDown();
|
||||
}
|
||||
|
||||
// Keyboard handling
|
||||
if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
|
||||
const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev;
|
||||
const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
|
||||
switch (event->getKey()) {
|
||||
case SoKeyboardEvent::LEFT_CONTROL:
|
||||
case SoKeyboardEvent::RIGHT_CONTROL:
|
||||
this->ctrldown = press;
|
||||
break;
|
||||
case SoKeyboardEvent::LEFT_SHIFT:
|
||||
case SoKeyboardEvent::RIGHT_SHIFT:
|
||||
this->shiftdown = press;
|
||||
break;
|
||||
case SoKeyboardEvent::LEFT_ALT:
|
||||
case SoKeyboardEvent::RIGHT_ALT:
|
||||
this->altdown = press;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse Button / Spaceball Button handling
|
||||
if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
|
||||
const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
|
||||
const int button = event->getButton();
|
||||
const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
|
||||
|
||||
// SoDebugError::postInfo("processSoEvent", "button = %d", button);
|
||||
switch (button) {
|
||||
case SoMouseButtonEvent::BUTTON1:
|
||||
this->button1down = press;
|
||||
break;
|
||||
case SoMouseButtonEvent::BUTTON2:
|
||||
this->button2down = press;
|
||||
break;
|
||||
case SoMouseButtonEvent::BUTTON3:
|
||||
this->button3down = press;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SbBool NavigationStyle::processMotionEvent(const SoMotion3Event * const ev)
|
||||
{
|
||||
SoCamera * const camera = viewer->getCamera();
|
||||
|
|
|
@ -175,6 +175,7 @@ protected:
|
|||
|
||||
SbBool handleEventInForeground(const SoEvent* const e);
|
||||
virtual SbBool processSoEvent(const SoEvent * const ev);
|
||||
void syncWithEvent(const SoEvent * const ev);
|
||||
virtual void openPopupMenu(const SbVec2s& position);
|
||||
|
||||
void clearLog(void);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QApplication>
|
||||
# include <QClipboard>
|
||||
# include <QDockWidget>
|
||||
# include <QGridLayout>
|
||||
|
@ -700,12 +701,13 @@ void PythonConsole::runSource(const QString& line)
|
|||
catch (const Base::SystemExitException&) {
|
||||
ParameterGrp::handle hPrefGrp = getWindowParameter();
|
||||
bool check = hPrefGrp->GetBool("CheckSystemExit",true);
|
||||
if (!check) Base::Interpreter().systemExit();
|
||||
if (!check) qApp->quit();
|
||||
int ret = QMessageBox::question(this, tr("System exit"), tr("The application is still running.\nDo you want to exit without saving your data?"),
|
||||
QMessageBox::Yes, QMessageBox::No|QMessageBox::Escape|QMessageBox::Default);
|
||||
if (ret == QMessageBox::Yes) {
|
||||
Base::Interpreter().systemExit();
|
||||
} else {
|
||||
qApp->quit();
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,23 +88,31 @@ public:
|
|||
textColor = col;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~SplashObserver()
|
||||
{
|
||||
Base::Console().DetachObserver(this);
|
||||
}
|
||||
|
||||
const char* Name()
|
||||
{
|
||||
return "SplashObserver";
|
||||
}
|
||||
void Warning(const char * s)
|
||||
{
|
||||
#ifdef FC_DEBUG
|
||||
Log(s);
|
||||
#endif
|
||||
}
|
||||
void Message(const char * s)
|
||||
{
|
||||
#ifdef FC_DEBUG
|
||||
Log(s);
|
||||
#endif
|
||||
}
|
||||
void Error (const char * s)
|
||||
{
|
||||
#ifdef FC_DEBUG
|
||||
Log(s);
|
||||
#endif
|
||||
}
|
||||
void Log (const char * s)
|
||||
{
|
||||
|
@ -267,11 +275,9 @@ static QString getPlatform()
|
|||
|
||||
void AboutDialog::setupLabels()
|
||||
{
|
||||
QString exeName = qApp->applicationName();
|
||||
std::map<std::string, std::string>& config = App::Application::Config();
|
||||
QString exeName = QString::fromAscii(config["ExeName"].c_str());
|
||||
std::map<std::string,std::string>::iterator it = config.find("WindowTitle");
|
||||
if (it != config.end())
|
||||
exeName = QString::fromUtf8(it->second.c_str());
|
||||
std::map<std::string,std::string>::iterator it;
|
||||
QString banner = QString::fromUtf8(config["CopyrightInfo"].c_str());
|
||||
banner = banner.left( banner.indexOf(QLatin1Char('\n')) );
|
||||
QString major = QString::fromAscii(config["BuildVersionMajor"].c_str());
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <QApplication>
|
||||
# include <QBuffer>
|
||||
# include <QByteArray>
|
||||
# include <QDateTime>
|
||||
|
@ -97,7 +98,7 @@ void Thumbnail::SaveDocFile (Base::Writer &writer) const
|
|||
// according to specification add some meta-information to the image
|
||||
uint mt = QDateTime::currentDateTime().toTime_t();
|
||||
QString mtime = QString::fromAscii("%1").arg(mt);
|
||||
img.setText(QLatin1String("Software"), QString::fromUtf8(App::GetApplication().getExecutableName()));
|
||||
img.setText(QLatin1String("Software"), qApp->applicationName());
|
||||
img.setText(QLatin1String("Thumb::Mimetype"), QLatin1String("application/x-extension-fcstd"));
|
||||
img.setText(QLatin1String("Thumb::MTime"), mtime);
|
||||
img.setText(QLatin1String("Thumb::URI"), this->uri.toString());
|
||||
|
|
|
@ -311,7 +311,7 @@ void LightManip(SoSeparator * root)
|
|||
in.setBuffer((void *)scenegraph, std::strlen(scenegraph));
|
||||
SoSeparator * _root = SoDB::readAll( &in );
|
||||
root->addChild(_root);
|
||||
if ( root == NULL ) exit( 1 ); // Shouldn't happen.
|
||||
if ( root == NULL ) return; // Shouldn't happen.
|
||||
root->ref();
|
||||
|
||||
const char * pointlightnames[3] = { "RedLight", "GreenLight", "BlueLight" };
|
||||
|
@ -323,7 +323,7 @@ void LightManip(SoSeparator * root)
|
|||
sa.setSearchingAll( FALSE );
|
||||
sa.apply( root );
|
||||
SoPath * path = sa.getPath();
|
||||
if ( path == NULL) exit( 1 ); // Shouldn't happen.
|
||||
if ( path == NULL) return; // Shouldn't happen.
|
||||
|
||||
SoPointLightManip * manip = new SoPointLightManip;
|
||||
manip->replaceNode( path );
|
||||
|
@ -446,7 +446,7 @@ void AnimationTexture(SoSeparator * root)
|
|||
texturetimer->schedule();
|
||||
|
||||
// Scene graph
|
||||
if ( root == NULL ) exit( 1 ); // Shouldn't happen.
|
||||
if ( root == NULL ) return; // Shouldn't happen.
|
||||
root->ref(); // prevent from being deleted because of the still running timer sensor
|
||||
// SoSeparator * root = new SoSeparator;
|
||||
// root->ref();
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
// FreeCAD Base header
|
||||
#include <Base/Console.h>
|
||||
|
@ -89,6 +90,14 @@ int main( int argc, char ** argv )
|
|||
// Inits the Application
|
||||
App::Application::init(argc,argv);
|
||||
}
|
||||
catch (const Base::UnknownProgramOption& e) {
|
||||
std::cerr << e.what();
|
||||
exit(1);
|
||||
}
|
||||
catch (const Base::ProgramInformation& e) {
|
||||
std::cout << e.what();
|
||||
exit(0);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
std::string appName = App::Application::Config()["ExeName"];
|
||||
std::stringstream msg;
|
||||
|
|
|
@ -161,83 +161,6 @@ private:
|
|||
QDomDocument domDocument;
|
||||
};
|
||||
|
||||
class ProgramOptions
|
||||
{
|
||||
public:
|
||||
ProgramOptions()
|
||||
{
|
||||
newcout = new ProgramOptionsStream(out);
|
||||
oldcout = std::cout.rdbuf(newcout);
|
||||
out.reserve(80);
|
||||
newcerr = new ProgramOptionsStream(err);
|
||||
oldcerr = std::cerr.rdbuf(newcerr);
|
||||
err.reserve(80);
|
||||
|
||||
error = true;
|
||||
::atexit(ProgramOptions::failure);
|
||||
}
|
||||
~ProgramOptions()
|
||||
{
|
||||
std::cout.rdbuf(oldcout);
|
||||
delete newcout;
|
||||
std::cerr.rdbuf(oldcerr);
|
||||
delete newcerr;
|
||||
error = false;
|
||||
}
|
||||
static void failure()
|
||||
{
|
||||
if (error) {
|
||||
int argc=0;
|
||||
QApplication app(argc,0);
|
||||
QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
|
||||
if (!err.empty()) {
|
||||
QString msg = QString::fromAscii(err.c_str());
|
||||
QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>");
|
||||
QMessageBox::critical(0, appName, s);
|
||||
}
|
||||
else if (!out.empty()) {
|
||||
QString msg = QString::fromAscii(out.c_str());
|
||||
QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>");
|
||||
QMessageBox::information(0, appName, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
class ProgramOptionsStream : public std::streambuf
|
||||
{
|
||||
public:
|
||||
ProgramOptionsStream(std::string& s) : buf(s)
|
||||
{
|
||||
}
|
||||
int overflow(int c = EOF)
|
||||
{
|
||||
if (c != EOF)
|
||||
buf.push_back((char)c);
|
||||
return c;
|
||||
}
|
||||
int sync()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
std::string& buf;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class ProgramOptionsStream;
|
||||
std::streambuf* oldcout;
|
||||
std::streambuf* newcout;
|
||||
std::streambuf* oldcerr;
|
||||
std::streambuf* newcerr;
|
||||
static std::string out, err;
|
||||
static bool error;
|
||||
};
|
||||
|
||||
bool ProgramOptions::error = false;
|
||||
std::string ProgramOptions::out;
|
||||
std::string ProgramOptions::err;
|
||||
|
||||
#if defined (FC_OS_LINUX) || defined(FC_OS_BSD)
|
||||
QString myDecoderFunc(const QByteArray &localFileName)
|
||||
{
|
||||
|
@ -300,10 +223,25 @@ int main( int argc, char ** argv )
|
|||
App::Application::Config()["RunMode"] = "Gui";
|
||||
|
||||
// Inits the Application
|
||||
ProgramOptions po;
|
||||
App::Application::init(argc,argv);
|
||||
Gui::Application::initApplication();
|
||||
}
|
||||
catch (const Base::UnknownProgramOption& e) {
|
||||
QApplication app(argc,argv);
|
||||
QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
|
||||
QString msg = QString::fromAscii(e.what());
|
||||
QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>");
|
||||
QMessageBox::critical(0, appName, s);
|
||||
exit(1);
|
||||
}
|
||||
catch (const Base::ProgramInformation& e) {
|
||||
QApplication app(argc,argv);
|
||||
QString appName = QString::fromAscii(App::Application::Config()["ExeName"].c_str());
|
||||
QString msg = QString::fromAscii(e.what());
|
||||
QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>");
|
||||
QMessageBox::information(0, appName, s);
|
||||
exit(0);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
// Popup an own dialog box instead of that one of Windows
|
||||
QApplication app(argc,argv);
|
||||
|
|
|
@ -154,31 +154,36 @@ def splitMesh(obj,mark=True):
|
|||
|
||||
def makeFace(wires,method=2,cleanup=False):
|
||||
'''makeFace(wires): makes a face from a list of wires, finding which ones are holes'''
|
||||
|
||||
#print "makeFace: start:", wires
|
||||
import Part
|
||||
|
||||
if not isinstance(wires,list):
|
||||
if len(wires.Vertexes) < 3:
|
||||
raise
|
||||
return Part.Face(wires)
|
||||
elif len(wires) == 1:
|
||||
#import Draft;Draft.printShape(wires[0])
|
||||
if len(wires[0].Vertexes) < 3:
|
||||
raise
|
||||
return Part.Face(wires[0])
|
||||
|
||||
wires = wires[:]
|
||||
|
||||
print "inner wires found"
|
||||
#print "makeFace: inner wires found"
|
||||
ext = None
|
||||
max_length = 0
|
||||
# cleaning up rubbish in wires
|
||||
if cleanup:
|
||||
for i in range(len(wires)):
|
||||
wires[i] = DraftGeomUtils.removeInterVertices(wires[i])
|
||||
print "garbage removed"
|
||||
#print "makeFace: garbage removed"
|
||||
for w in wires:
|
||||
# we assume that the exterior boundary is that one with
|
||||
# the biggest bounding box
|
||||
if w.BoundBox.DiagonalLength > max_length:
|
||||
max_length = w.BoundBox.DiagonalLength
|
||||
ext = w
|
||||
print "exterior wire",ext
|
||||
#print "makeFace: exterior wire",ext
|
||||
wires.remove(ext)
|
||||
|
||||
if method == 1:
|
||||
|
@ -186,23 +191,22 @@ def makeFace(wires,method=2,cleanup=False):
|
|||
# all interior wires mark a hole and must reverse
|
||||
# their orientation, otherwise Part.Face fails
|
||||
for w in wires:
|
||||
print "reversing",w
|
||||
#print "makeFace: reversing",w
|
||||
w.reverse()
|
||||
print "reversed"
|
||||
# make sure that the exterior wires comes as first in the list
|
||||
wires.insert(0, ext)
|
||||
print "done sorting", wires
|
||||
#print "makeFace: done sorting", wires
|
||||
if wires:
|
||||
return Part.Face(wires)
|
||||
else:
|
||||
# method 2: use the cut method
|
||||
mf = Part.Face(ext)
|
||||
print "external face:",mf
|
||||
#print "makeFace: external face:",mf
|
||||
for w in wires:
|
||||
f = Part.Face(w)
|
||||
print "internal face:",f
|
||||
#print "makeFace: internal face:",f
|
||||
mf = mf.cut(f)
|
||||
print "final face:",mf.Faces
|
||||
#print "makeFace: final face:",mf.Faces
|
||||
return mf.Faces[0]
|
||||
|
||||
def meshToShape(obj,mark=True):
|
||||
|
|
|
@ -62,7 +62,8 @@ def addToComponent(compobject,addobject,mod=None):
|
|||
l = getattr(compobject,mod)
|
||||
l.append(addobject)
|
||||
setattr(compobject,mod,l)
|
||||
addobject.ViewObject.hide()
|
||||
if mod != "Objects":
|
||||
addobject.ViewObject.hide()
|
||||
else:
|
||||
for a in attribs[:3]:
|
||||
if hasattr(compobject,a):
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,math,Draft,ArchCommands, DraftVecUtils
|
||||
import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,math,Draft,ArchCommands,DraftVecUtils
|
||||
from FreeCAD import Vector
|
||||
from PyQt4 import QtCore
|
||||
from pivy import coin
|
||||
|
@ -215,7 +215,7 @@ class _ArchDrawingView:
|
|||
import ArchVRM
|
||||
render = ArchVRM.Renderer()
|
||||
render.setWorkingPlane(obj.Source.Placement)
|
||||
render.addObjects(objs)
|
||||
render.addObjects(Draft.getGroupContents(objs,walls=True))
|
||||
render.cut(obj.Source.Shape)
|
||||
svg += render.getViewSVG(linewidth=linewidth)
|
||||
svg += render.getSectionSVG(linewidth=linewidth*2)
|
||||
|
|
|
@ -145,12 +145,14 @@ class Renderer:
|
|||
|
||||
def reorient(self):
|
||||
"reorients the faces on the WP"
|
||||
#print "VRM: start reorient"
|
||||
if not self.faces:
|
||||
return
|
||||
self.faces = [self.projectFace(f) for f in self.faces]
|
||||
if self.sections:
|
||||
self.sections = [self.projectFace(f) for f in self.sections]
|
||||
self.oriented = True
|
||||
#print "VRM: end reorient"
|
||||
|
||||
def removeHidden(self):
|
||||
"removes faces pointing outwards"
|
||||
|
@ -166,17 +168,24 @@ class Renderer:
|
|||
|
||||
def projectFace(self,face):
|
||||
"projects a single face on the WP"
|
||||
#print "VRM: projectFace start: ",len(face[0].Vertexes)," verts, ",len(face[0].Edges)," edges"
|
||||
wires = []
|
||||
if not face[0].Wires:
|
||||
if DEBUG: print "Error: Unable to project face on the WP"
|
||||
return None
|
||||
norm = face[0].normalAt(0,0)
|
||||
for w in face[0].Wires:
|
||||
verts = []
|
||||
edges = DraftGeomUtils.sortEdges(w.Edges)
|
||||
#print len(edges)," edges after sorting"
|
||||
for e in edges:
|
||||
v = e.Vertexes[0].Point
|
||||
#print v
|
||||
v = self.wp.getLocalCoords(v)
|
||||
verts.append(v)
|
||||
verts.append(verts[0])
|
||||
if len(verts) > 2:
|
||||
#print "new wire with ",len(verts)
|
||||
wires.append(Part.makePolygon(verts))
|
||||
try:
|
||||
sh = ArchCommands.makeFace(wires)
|
||||
|
@ -188,6 +197,7 @@ class Renderer:
|
|||
vnorm = self.wp.getLocalCoords(norm)
|
||||
if vnorm.getAngle(sh.normalAt(0,0)) > 1:
|
||||
sh.reverse()
|
||||
#print "VRM: projectFace end: ",len(sh.Vertexes)," verts"
|
||||
return [sh]+face[1:]
|
||||
|
||||
def flattenFace(self,face):
|
||||
|
@ -211,6 +221,7 @@ class Renderer:
|
|||
|
||||
def cut(self,cutplane):
|
||||
"Cuts through the shapes with a given cut plane and builds section faces"
|
||||
if DEBUG: print "\n\n======> Starting cut\n\n"
|
||||
if self.iscut:
|
||||
return
|
||||
if not self.shapes:
|
||||
|
@ -262,12 +273,10 @@ class Renderer:
|
|||
shapes.append([c]+sh[1:])
|
||||
for f in c.Faces:
|
||||
faces.append([f]+sh[1:])
|
||||
sec = sol.section(cutface)
|
||||
if sec.Edges:
|
||||
wires = DraftGeomUtils.findWires(sec.Edges)
|
||||
for w in wires:
|
||||
sec = Part.Face(w)
|
||||
sections.append([sec,fill])
|
||||
print "iscoplanar:",f.Vertexes[0].Point,f.normalAt(0,0),cutface.Vertexes[0].Point,cutface.normalAt(0,0)
|
||||
if DraftGeomUtils.isCoplanar([f,cutface]):
|
||||
print "COPLANAR"
|
||||
sections.append([f,fill])
|
||||
self.shapes = shapes
|
||||
self.faces = faces
|
||||
self.sections = sections
|
||||
|
@ -277,6 +286,7 @@ class Renderer:
|
|||
self.trimmed = False
|
||||
self.sorted = False
|
||||
self.joined = False
|
||||
if DEBUG: print "\n\n======> Finished cut\n\n"
|
||||
|
||||
def isInside(self,vert,face):
|
||||
"Returns True if the vert is inside the face in Z projection"
|
||||
|
@ -319,6 +329,15 @@ class Renderer:
|
|||
def compare(self,face1,face2):
|
||||
"zsorts two faces. Returns 1 if face1 is closer, 2 if face2 is closer, 0 otherwise"
|
||||
|
||||
#print face1,face2
|
||||
|
||||
if not face1:
|
||||
if DEBUG: print "Warning, undefined face!"
|
||||
return 31
|
||||
elif not face2:
|
||||
if DEBUG: print "Warning, undefined face!"
|
||||
return 32
|
||||
|
||||
# theory from
|
||||
# http://www.siggraph.org/education/materials/HyperGraph/scanline/visibility/painter.htm
|
||||
# and practical application http://vrm.ao2.it/ (blender vector renderer)
|
||||
|
@ -456,14 +475,17 @@ class Renderer:
|
|||
|
||||
def sort(self):
|
||||
"projects a shape on the WP"
|
||||
if DEBUG: print "\n\n======> Starting sort\n\n"
|
||||
if len(self.faces) <= 1:
|
||||
return
|
||||
if not self.trimmed:
|
||||
self.removeHidden()
|
||||
if DEBUG: print "Done hidden face removal"
|
||||
if len(self.faces) == 1:
|
||||
return
|
||||
if not self.oriented:
|
||||
self.reorient()
|
||||
if DEBUG: print "Done reorientation"
|
||||
faces = self.faces[:]
|
||||
if DEBUG: print "sorting ",len(self.faces)," faces"
|
||||
sfaces = []
|
||||
|
@ -492,6 +514,7 @@ class Renderer:
|
|||
for f2 in faces[1:]:
|
||||
if DEBUG: print "comparing face",str(self.faces.index(f1))," with face",str(self.faces.index(f2))
|
||||
r = self.compare(f1,f2)
|
||||
print "comparison result:",r
|
||||
if r == 1:
|
||||
faces.remove(f2)
|
||||
sfaces.append(f2)
|
||||
|
@ -506,6 +529,10 @@ class Renderer:
|
|||
sfaces.append(f2)
|
||||
notfoundstack = 0
|
||||
break
|
||||
elif r == 31:
|
||||
faces.remove(f1)
|
||||
elif r == 32:
|
||||
faces.remove(f2)
|
||||
else:
|
||||
# nothing found, move the face to the end of the pile
|
||||
faces.remove(f1)
|
||||
|
@ -518,6 +545,7 @@ class Renderer:
|
|||
if DEBUG: print "done Z sorting. ", len(sfaces), " faces retained, ", len(self.faces)-len(sfaces), " faces lost."
|
||||
self.faces = sfaces
|
||||
self.sorted = True
|
||||
if DEBUG: print "\n\n======> Finished sort\n\n"
|
||||
|
||||
def buildDummy(self):
|
||||
"Builds a dummy object with faces spaced on the Z axis, for visual check"
|
||||
|
@ -544,19 +572,21 @@ class Renderer:
|
|||
|
||||
def getPathData(self,w):
|
||||
"Returns a SVG path data string from a 2D wire"
|
||||
def tostr(val):
|
||||
return str(round(val,DraftVecUtils.precision()))
|
||||
edges = DraftGeomUtils.sortEdges(w.Edges)
|
||||
v = edges[0].Vertexes[0].Point
|
||||
svg = 'M '+ str(v.x) +' '+ str(v.y) + ' '
|
||||
svg = 'M '+ tostr(v.x) +' '+ tostr(v.y) + ' '
|
||||
for e in edges:
|
||||
if isinstance(e.Curve,Part.Line) or isinstance(e.Curve,Part.BSplineCurve):
|
||||
v = e.Vertexes[-1].Point
|
||||
svg += 'L '+ str(v.x) +' '+ str(v.y) + ' '
|
||||
svg += 'L '+ tostr(v.x) +' '+ tostr(v.y) + ' '
|
||||
elif isinstance(e.Curve,Part.Circle):
|
||||
r = e.Curve.Radius
|
||||
v = e.Vertexes[-1].Point
|
||||
svg += 'A '+ str(r) + ' '+ str(r) +' 0 0 1 '+ str(v.x) +' '
|
||||
svg += str(v.y) + ' '
|
||||
svg += 'z '
|
||||
svg += 'A '+ tostr(r) + ' '+ tostr(r) +' 0 0 1 '+ tostr(v.x) +' '
|
||||
svg += tostr(v.y) + ' '
|
||||
svg += 'Z '
|
||||
return svg
|
||||
|
||||
def getViewSVG(self,linewidth=0.01):
|
||||
|
@ -566,44 +596,47 @@ class Renderer:
|
|||
self.sort()
|
||||
svg = ''
|
||||
for f in self.faces:
|
||||
fill = self.getFill(f[1])
|
||||
svg +='<path '
|
||||
svg += 'd="'
|
||||
for w in f[0].Wires:
|
||||
svg += self.getPathData(w)
|
||||
svg += '" '
|
||||
svg += 'stroke="#000000" '
|
||||
svg += 'stroke-width="' + str(linewidth) + '" '
|
||||
svg += 'style="stroke-width:' + str(linewidth) + ';'
|
||||
svg += 'stroke-miterlimit:1;'
|
||||
svg += 'stroke-linejoin:round;'
|
||||
svg += 'stroke-dasharray:none;'
|
||||
svg += 'fill:' + fill + ';'
|
||||
svg += 'fill-rule: evenodd'
|
||||
svg += '"/>\n'
|
||||
if f:
|
||||
fill = self.getFill(f[1])
|
||||
svg +='<path '
|
||||
svg += 'd="'
|
||||
for w in f[0].Wires:
|
||||
svg += self.getPathData(w)
|
||||
svg += '" '
|
||||
svg += 'stroke="#000000" '
|
||||
svg += 'stroke-width="' + str(linewidth) + '" '
|
||||
svg += 'style="stroke-width:' + str(linewidth) + ';'
|
||||
svg += 'stroke-miterlimit:1;'
|
||||
svg += 'stroke-linejoin:round;'
|
||||
svg += 'stroke-dasharray:none;'
|
||||
svg += 'fill:' + fill + ';'
|
||||
svg += 'fill-rule: evenodd'
|
||||
svg += '"/>\n'
|
||||
return svg
|
||||
|
||||
def getSectionSVG(self,linewidth=0.02):
|
||||
"Returns a SVG fragment from cut faces"
|
||||
if DEBUG: print "Printing ", len(self.sections), " cutfaces"
|
||||
if DEBUG: print "Printing ", len(self.sections), " sections"
|
||||
if not self.oriented:
|
||||
self.reorient()
|
||||
svg = ''
|
||||
for f in self.sections:
|
||||
fill = self.getFill(f[1])
|
||||
svg +='<path '
|
||||
svg += 'd="'
|
||||
for w in f[0].Wires:
|
||||
svg += self.getPathData(w)
|
||||
svg += '" '
|
||||
svg += 'stroke="#000000" '
|
||||
svg += 'stroke-width="' + str(linewidth) + '" '
|
||||
svg += 'style="stroke-width:' + str(linewidth) + ';'
|
||||
svg += 'stroke-miterlimit:1;'
|
||||
svg += 'stroke-linejoin:round;'
|
||||
svg += 'stroke-dasharray:none;'
|
||||
svg += 'fill:' + fill + ';'
|
||||
svg += 'fill-rule: evenodd'
|
||||
svg += '"/>\n'
|
||||
if f:
|
||||
fill = self.getFill(f[1])
|
||||
svg +='<path '
|
||||
svg += 'd="'
|
||||
for w in f[0].Wires:
|
||||
#print "wire with ",len(w.Vertexes)," verts"
|
||||
svg += self.getPathData(w)
|
||||
svg += '" '
|
||||
svg += 'stroke="#000000" '
|
||||
svg += 'stroke-width="' + str(linewidth) + '" '
|
||||
svg += 'style="stroke-width:' + str(linewidth) + ';'
|
||||
svg += 'stroke-miterlimit:1;'
|
||||
svg += 'stroke-linejoin:round;'
|
||||
svg += 'stroke-dasharray:none;'
|
||||
svg += 'fill:' + fill + ';'
|
||||
svg += 'fill-rule: evenodd'
|
||||
svg += '"/>\n'
|
||||
return svg
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ How it works / how to extend:
|
|||
'''
|
||||
|
||||
# import FreeCAD modules
|
||||
import FreeCAD, math, sys, os, DraftVecUtils
|
||||
import FreeCAD, math, sys, os, DraftVecUtils, Draft_rc
|
||||
from FreeCAD import Vector
|
||||
from pivy import coin
|
||||
|
||||
|
@ -253,17 +253,43 @@ def shapify(obj):
|
|||
FreeCAD.ActiveDocument.recompute()
|
||||
return newobj
|
||||
|
||||
def getGroupContents(objectslist):
|
||||
def getGroupContents(objectslist,walls=False):
|
||||
'''getGroupContents(objectlist): if any object of the given list
|
||||
is a group, its content is appened to the list, which is returned'''
|
||||
newlist = []
|
||||
for obj in objectslist:
|
||||
if obj.Type == "App::DocumentObjectGroup":
|
||||
if obj.isDerivedFrom("App::DocumentObjectGroup"):
|
||||
newlist.extend(getGroupContents(obj.Group))
|
||||
else:
|
||||
newlist.append(obj)
|
||||
if walls:
|
||||
if getType(obj) == "Wall":
|
||||
for o in obj.OutList:
|
||||
if (getType(o) == "Window") or isClone(o,"Window"):
|
||||
newlist.append(o)
|
||||
return newlist
|
||||
|
||||
def printShape(shape):
|
||||
"""prints detailed information of a shape"""
|
||||
print "solids: ", len(shape.Solids)
|
||||
print "faces: ", len(shape.Faces)
|
||||
print "wires: ", len(shape.Wires)
|
||||
print "edges: ", len(shape.Edges)
|
||||
print "verts: ", len(shape.Vertexes)
|
||||
if shape.Faces:
|
||||
for f in range(len(shape.Faces)):
|
||||
print "face ",f,":"
|
||||
for v in shape.Faces[f].Vertexes:
|
||||
print " ",v.Point
|
||||
elif shape.Wires:
|
||||
for w in range(len(shape.Wires)):
|
||||
print "wire ",w,":"
|
||||
for v in shape.Wires[w].Vertexes:
|
||||
print " ",v.Point
|
||||
else:
|
||||
for v in shape.Vertexes:
|
||||
print " ",v.Point
|
||||
|
||||
def formatObject(target,origin=None):
|
||||
'''
|
||||
formatObject(targetObject,[originObject]): This function applies
|
||||
|
@ -1514,7 +1540,7 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"):
|
|||
ok = False
|
||||
tp = getType(obj)
|
||||
if tp == "BSpline":
|
||||
pass
|
||||
print "makeSketch: BSplines not supported"
|
||||
elif tp == "Circle":
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
nobj.addGeometry(obj.Shape.Edges[0].Curve)
|
||||
|
@ -1560,32 +1586,16 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"):
|
|||
nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,segs[0],StartPoint))
|
||||
ok = True
|
||||
if (not ok) and obj.isDerivedFrom("Part::Feature"):
|
||||
if DraftGeomUtils.hasOnlyWires(obj.Shape):
|
||||
for w in obj.Shape.Wires:
|
||||
for edge in DraftGeomUtils.sortEdges(w.Edges):
|
||||
g = DraftGeomUtils.geom(edge)
|
||||
if g:
|
||||
nobj.addGeometry(g)
|
||||
if autoconstraints:
|
||||
last = nobj.GeometryCount
|
||||
segs = range(last-len(w.Edges),last-1)
|
||||
for seg in segs:
|
||||
nobj.addConstraint(Constraint("Coincident",seg,EndPoint,seg+1,StartPoint))
|
||||
if DraftGeomUtils.isAligned(nobj.Geometry[seg],"x"):
|
||||
nobj.addConstraint(Constraint("Vertical",seg))
|
||||
elif DraftGeomUtils.isAligned(nobj.Geometry[seg],"y"):
|
||||
nobj.addConstraint(Constraint("Horizontal",seg))
|
||||
if w.isClosed:
|
||||
nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,segs[0],StartPoint))
|
||||
else:
|
||||
for edge in obj.Shape.Edges:
|
||||
nobj.addGeometry(DraftGeomUtils.geom(edge))
|
||||
if autoconstraints:
|
||||
last = nobj.GeometryCount - 1
|
||||
if DraftGeomUtils.isAligned(nobj.Geometry[last],"x"):
|
||||
nobj.addConstraint(Constraint("Vertical",last))
|
||||
elif DraftGeomUtils.isAligned(nobj.Geometry[last],"y"):
|
||||
nobj.addConstraint(Constraint("Horizontal",last))
|
||||
if not DraftGeomUtils.isPlanar(obj.Shape):
|
||||
print "Error: The given object is not planar and cannot be converted into a sketch."
|
||||
return None
|
||||
if not addTo:
|
||||
nobj.Placement.Rotation = DraftGeomUtils.calculatePlacement(obj.Shape).Rotation
|
||||
edges = []
|
||||
for e in obj.Shape.Edges:
|
||||
g = (DraftGeomUtils.geom(e,nobj.Placement))
|
||||
if g:
|
||||
nobj.addGeometry(g)
|
||||
ok = True
|
||||
if ok:
|
||||
FreeCAD.ActiveDocument.removeObject(obj.Name)
|
||||
|
@ -1945,7 +1955,7 @@ class _ViewProviderDimension:
|
|||
[p2.x,p2.y,p2.z],
|
||||
[p3.x,p3.y,p3.z],
|
||||
[p4.x,p4.y,p4.z]])
|
||||
self.line.numVertices.setValues([4])
|
||||
self.line.numVertices.setValue(4)
|
||||
else:
|
||||
ts = (len(text)*obj.ViewObject.FontSize)/4
|
||||
rm = ((p3.sub(p2)).Length/2)-ts
|
||||
|
@ -2714,29 +2724,35 @@ class _Array:
|
|||
obj.addProperty("App::PropertyEnumeration","ArrayType","Base",
|
||||
"The type of array to create")
|
||||
obj.addProperty("App::PropertyVector","Axis","Base",
|
||||
"The axis direction for polar arrays")
|
||||
"The axis direction")
|
||||
obj.addProperty("App::PropertyInteger","NumberX","Base",
|
||||
"Number of copies in X direction (ortho arrays)")
|
||||
"Number of copies in X direction")
|
||||
obj.addProperty("App::PropertyInteger","NumberY","Base",
|
||||
"Number of copies in Y direction (ortho arrays)")
|
||||
"Number of copies in Y direction")
|
||||
obj.addProperty("App::PropertyInteger","NumberZ","Base",
|
||||
"Number of copies in Z direction")
|
||||
obj.addProperty("App::PropertyInteger","NumberPolar","Base",
|
||||
"Number of copies (polar arrays)")
|
||||
"Number of copies")
|
||||
obj.addProperty("App::PropertyVector","IntervalX","Base",
|
||||
"Distance and orientation of intervals in X direction (ortho arrays)")
|
||||
"Distance and orientation of intervals in X direction")
|
||||
obj.addProperty("App::PropertyVector","IntervalY","Base",
|
||||
"Distance and orientation of intervals in Y direction (ortho arrays)")
|
||||
"Distance and orientation of intervals in Y direction")
|
||||
obj.addProperty("App::PropertyVector","IntervalZ","Base",
|
||||
"Distance and orientation of intervals in Z direction")
|
||||
obj.addProperty("App::PropertyVector","Center","Base",
|
||||
"Center point (polar arrays)")
|
||||
"Center point")
|
||||
obj.addProperty("App::PropertyAngle","Angle","Base",
|
||||
"Angle to cover with copies (polar arrays)")
|
||||
"Angle to cover with copies")
|
||||
obj.Proxy = self
|
||||
self.Type = "Array"
|
||||
obj.ArrayType = ['ortho','polar']
|
||||
obj.NumberX = 1
|
||||
obj.NumberY = 1
|
||||
obj.NumberZ = 1
|
||||
obj.NumberPolar = 1
|
||||
obj.IntervalX = Vector(1,0,0)
|
||||
obj.IntervalY = Vector(0,1,0)
|
||||
obj.IntervalZ = Vector(0,0,1)
|
||||
obj.Angle = 360
|
||||
obj.Axis = Vector(0,0,1)
|
||||
|
||||
|
@ -2744,7 +2760,32 @@ class _Array:
|
|||
self.createGeometry(obj)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
if prop in ["ArrayType","NumberX","NumberY","NumberPolar","IntervalX","IntervalY","Angle","Center","Axis"]:
|
||||
if prop == "ArrayType":
|
||||
if obj.ViewObject:
|
||||
if obj.ArrayType == "ortho":
|
||||
obj.ViewObject.setEditorMode('Axis',2)
|
||||
obj.ViewObject.setEditorMode('NumberPolar',2)
|
||||
obj.ViewObject.setEditorMode('Center',2)
|
||||
obj.ViewObject.setEditorMode('Angle',2)
|
||||
obj.ViewObject.setEditorMode('NumberX',0)
|
||||
obj.ViewObject.setEditorMode('NumberY',0)
|
||||
obj.ViewObject.setEditorMode('NumberZ',0)
|
||||
obj.ViewObject.setEditorMode('IntervalX',0)
|
||||
obj.ViewObject.setEditorMode('IntervalY',0)
|
||||
obj.ViewObject.setEditorMode('IntervalZ',0)
|
||||
else:
|
||||
obj.ViewObject.setEditorMode('Axis',0)
|
||||
obj.ViewObject.setEditorMode('NumberPolar',0)
|
||||
obj.ViewObject.setEditorMode('Center',0)
|
||||
obj.ViewObject.setEditorMode('Angle',0)
|
||||
obj.ViewObject.setEditorMode('NumberX',2)
|
||||
obj.ViewObject.setEditorMode('NumberY',2)
|
||||
obj.ViewObject.setEditorMode('NumberY',2)
|
||||
obj.ViewObject.setEditorMode('IntervalX',2)
|
||||
obj.ViewObject.setEditorMode('IntervalY',2)
|
||||
obj.ViewObject.setEditorMode('IntervalZ',2)
|
||||
if prop in ["ArrayType","NumberX","NumberY","NumberZ","NumberPolar",
|
||||
"IntervalX","IntervalY","IntervalZ","Angle","Center","Axis"]:
|
||||
self.createGeometry(obj)
|
||||
|
||||
def createGeometry(self,obj):
|
||||
|
@ -2752,14 +2793,15 @@ class _Array:
|
|||
if obj.Base:
|
||||
pl = obj.Placement
|
||||
if obj.ArrayType == "ortho":
|
||||
sh = self.rectArray(obj.Base.Shape,obj.IntervalX,obj.IntervalY,obj.NumberX,obj.NumberY)
|
||||
sh = self.rectArray(obj.Base.Shape,obj.IntervalX,obj.IntervalY,
|
||||
obj.IntervalZ,obj.NumberX,obj.NumberY,obj.NumberZ)
|
||||
else:
|
||||
sh = self.polarArray(obj.Base.Shape,obj.Center,obj.Angle,obj.NumberPolar,obj.Axis)
|
||||
obj.Shape = sh
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
obj.Placement = pl
|
||||
|
||||
def rectArray(self,shape,xvector,yvector,xnum,ynum):
|
||||
def rectArray(self,shape,xvector,yvector,zvector,xnum,ynum,znum):
|
||||
import Part
|
||||
base = [shape.copy()]
|
||||
for xcount in range(xnum):
|
||||
|
@ -2769,12 +2811,19 @@ class _Array:
|
|||
nshape.translate(currentxvector)
|
||||
base.append(nshape)
|
||||
for ycount in range(ynum):
|
||||
currentxvector=FreeCAD.Vector(currentxvector)
|
||||
currentyvector=currentxvector.add(DraftVecUtils.scale(yvector,ycount))
|
||||
currentyvector=FreeCAD.Vector(currentxvector)
|
||||
currentyvector=currentyvector.add(DraftVecUtils.scale(yvector,ycount))
|
||||
if not ycount==0:
|
||||
nshape = shape.copy()
|
||||
nshape.translate(currentyvector)
|
||||
base.append(nshape)
|
||||
for zcount in range(znum):
|
||||
currentzvector=FreeCAD.Vector(currentyvector)
|
||||
currentzvector=currentzvector.add(DraftVecUtils.scale(zvector,zcount))
|
||||
if not zcount==0:
|
||||
nshape = shape.copy()
|
||||
nshape.translate(currentzvector)
|
||||
base.append(nshape)
|
||||
return Part.makeCompound(base)
|
||||
|
||||
def polarArray(self,shape,center,angle,num,axis):
|
||||
|
|
|
@ -355,27 +355,33 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F
|
|||
else :
|
||||
print "fcgeo: Unsupported curve type: (" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")"
|
||||
|
||||
def geom(edge):
|
||||
"returns a Line, ArcOfCircle or Circle geom from the given edge"
|
||||
if isinstance(edge.Curve,Part.Line):
|
||||
return edge.Curve
|
||||
elif isinstance(edge.Curve,Part.Circle):
|
||||
if len(edge.Vertexes) == 1:
|
||||
return Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius)
|
||||
else:
|
||||
ref = edge.Placement.multVec(Vector(1,0,0))
|
||||
ref = ref.sub(edge.Placement.Base) # we only want the orientation
|
||||
v1 = edge.Vertexes[0].Point
|
||||
v2 = edge.Vertexes[-1].Point
|
||||
c = edge.Curve.Center
|
||||
cu = Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius)
|
||||
a1 = -DraftVecUtils.angle(v1.sub(c),ref,edge.Curve.Axis)
|
||||
a2 = -DraftVecUtils.angle(v2.sub(c),ref,edge.Curve.Axis)
|
||||
print "creating sketch arc from ",cu, ", p1=",v1, " (",math.degrees(a1), "d) p2=",v2," (", math.degrees(a2),"d)"
|
||||
p= Part.ArcOfCircle(cu,a1,a2)
|
||||
return p
|
||||
def geom(edge,plac=FreeCAD.Placement()):
|
||||
"returns a Line, ArcOfCircle or Circle geom from the given edge, according to the given placement"
|
||||
if isinstance(edge.Curve,Part.Line):
|
||||
return edge.Curve
|
||||
elif isinstance(edge.Curve,Part.Circle):
|
||||
if len(edge.Vertexes) == 1:
|
||||
return Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius)
|
||||
else:
|
||||
return edge.Curve
|
||||
# reorienting the arc along the correct normal
|
||||
normal = plac.Rotation.multVec(FreeCAD.Vector(0,0,1))
|
||||
v1 = edge.Vertexes[0].Point
|
||||
v2 = edge.Vertexes[-1].Point
|
||||
c = edge.Curve.Center
|
||||
cu = Part.Circle(edge.Curve.Center,normal,edge.Curve.Radius)
|
||||
ref = plac.Rotation.multVec(Vector(1,0,0))
|
||||
a1 = math.pi + DraftVecUtils.angle(v1.sub(c),ref,normal)
|
||||
a2 = DraftVecUtils.angle(v2.sub(c),ref,normal)
|
||||
|
||||
# direction check
|
||||
if a1 > a2:
|
||||
a1,a2 = a2,a1
|
||||
|
||||
#print "creating sketch arc from ",cu, ", p1=",v1, " (",math.degrees(a1), "d) p2=",v2," (", math.degrees(a2),"d)"
|
||||
p= Part.ArcOfCircle(cu,a1,a2)
|
||||
return p
|
||||
else:
|
||||
return edge.Curve
|
||||
|
||||
def mirror (point, edge):
|
||||
"finds mirror point relative to an edge"
|
||||
|
@ -445,98 +451,91 @@ def isLine(bsp):
|
|||
return True
|
||||
|
||||
def sortEdges(lEdges, aVertex=None):
|
||||
"an alternative, more accurate version of Part.__sortEdges__"
|
||||
"an alternative, more accurate version of Part.__sortEdges__"
|
||||
|
||||
#There is no reason to limit this to lines only because every non-closed edge always
|
||||
#has exactly two vertices (wmayer)
|
||||
#for e in lEdges:
|
||||
# if not isinstance(e.Curve,Part.Line):
|
||||
# print "Warning: sortedges cannot treat wired containing curves yet."
|
||||
# return lEdges
|
||||
|
||||
def isSameVertex(V1, V2):
|
||||
''' Test if vertexes have same coordinates with precision 10E(-precision)'''
|
||||
if round(V1.X-V2.X,1)==0 and round(V1.Y-V2.Y,1)==0 and round(V1.Z-V2.Z,1)==0 :
|
||||
return True
|
||||
else :
|
||||
return False
|
||||
|
||||
def lookfor(aVertex, inEdges):
|
||||
''' Look for (aVertex, inEdges) returns count, the position of the instance
|
||||
the position in the instance and the instance of the Edge'''
|
||||
count = 0
|
||||
linstances = [] #lists the instances of aVertex
|
||||
for i in range(len(inEdges)) :
|
||||
for j in range(2) :
|
||||
if isSameVertex(aVertex,inEdges[i].Vertexes[j-1]):
|
||||
instance = inEdges[i]
|
||||
count += 1
|
||||
linstances += [i,j-1,instance]
|
||||
return [count]+linstances
|
||||
|
||||
if (len(lEdges) < 2):
|
||||
if aVertex == None:
|
||||
return lEdges
|
||||
#There is no reason to limit this to lines only because every non-closed edge always
|
||||
#has exactly two vertices (wmayer)
|
||||
#for e in lEdges:
|
||||
# if not isinstance(e.Curve,Part.Line):
|
||||
# print "Warning: sortedges cannot treat wired containing curves yet."
|
||||
# return lEdges
|
||||
|
||||
def lookfor(aVertex, inEdges):
|
||||
''' Look for (aVertex, inEdges) returns count, the position of the instance
|
||||
the position in the instance and the instance of the Edge'''
|
||||
count = 0
|
||||
linstances = [] #lists the instances of aVertex
|
||||
for i in range(len(inEdges)) :
|
||||
for j in range(2) :
|
||||
if aVertex.Point == inEdges[i].Vertexes[j-1].Point:
|
||||
instance = inEdges[i]
|
||||
count += 1
|
||||
linstances += [i,j-1,instance]
|
||||
return [count]+linstances
|
||||
|
||||
if (len(lEdges) < 2):
|
||||
if aVertex == None:
|
||||
return lEdges
|
||||
else:
|
||||
result = lookfor(aVertex,lEdges)
|
||||
if result[0] != 0:
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
return lEdges
|
||||
else:
|
||||
result = lookfor(aVertex,lEdges)
|
||||
if result[0] != 0:
|
||||
if isSameVertex(aVertex,result[3].Vertexes[0]):
|
||||
return lEdges
|
||||
else:
|
||||
if isinstance(result[3].Curve,Part.Line):
|
||||
return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()]
|
||||
elif isinstance(result[3].Curve,Part.Circle):
|
||||
mp = findMidpoint(result[3])
|
||||
return [Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()]
|
||||
elif isinstance(result[3].Curve,Part.BSplineCurve):
|
||||
if isLine(result[3].Curve):
|
||||
return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()]
|
||||
else:
|
||||
return lEdges
|
||||
else:
|
||||
return lEdges
|
||||
|
||||
olEdges = [] # ol stands for ordered list
|
||||
if aVertex == None:
|
||||
for i in range(len(lEdges)*2) :
|
||||
if len(lEdges[i/2].Vertexes) > 1:
|
||||
result = lookfor(lEdges[i/2].Vertexes[i%2],lEdges)
|
||||
if result[0] == 1 : # Have we found an end ?
|
||||
olEdges = sortEdges(lEdges, result[3].Vertexes[result[2]])
|
||||
return olEdges
|
||||
# if the wire is closed there is no end so choose 1st Vertex
|
||||
#print "closed wire, starting from ",lEdges[0].Vertexes[0].Point
|
||||
return sortEdges(lEdges, lEdges[0].Vertexes[0])
|
||||
else :
|
||||
#print "looking ",aVertex.Point
|
||||
result = lookfor(aVertex,lEdges)
|
||||
if result[0] != 0 :
|
||||
del lEdges[result[1]]
|
||||
next = sortEdges(lEdges, result[3].Vertexes[-((-result[2])^1)])
|
||||
#print "result ",result[3].Vertexes[0].Point," ",result[3].Vertexes[1].Point, " compared to ",aVertex.Point
|
||||
if isSameVertex(aVertex,result[3].Vertexes[0]):
|
||||
#print "keeping"
|
||||
olEdges += [result[3]] + next
|
||||
if isinstance(result[3].Curve,Part.Line):
|
||||
return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()]
|
||||
elif isinstance(result[3].Curve,Part.Circle):
|
||||
mp = findMidpoint(result[3])
|
||||
return [Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()]
|
||||
elif isinstance(result[3].Curve,Part.BSplineCurve):
|
||||
if isLine(result[3].Curve):
|
||||
return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()]
|
||||
else:
|
||||
#print "inverting", result[3].Curve
|
||||
if isinstance(result[3].Curve,Part.Line):
|
||||
newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
elif isinstance(result[3].Curve,Part.Circle):
|
||||
mp = findMidpoint(result[3])
|
||||
newedge = Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
elif isinstance(result[3].Curve,Part.BSplineCurve):
|
||||
if isLine(result[3].Curve):
|
||||
newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
else:
|
||||
olEdges += [result[3]] + next
|
||||
else:
|
||||
olEdges += [result[3]] + next
|
||||
return olEdges
|
||||
else :
|
||||
return []
|
||||
return lEdges
|
||||
else:
|
||||
return lEdges
|
||||
|
||||
olEdges = [] # ol stands for ordered list
|
||||
if aVertex == None:
|
||||
for i in range(len(lEdges)*2) :
|
||||
if len(lEdges[i/2].Vertexes) > 1:
|
||||
result = lookfor(lEdges[i/2].Vertexes[i%2],lEdges)
|
||||
if result[0] == 1 : # Have we found an end ?
|
||||
olEdges = sortEdges(lEdges, result[3].Vertexes[result[2]])
|
||||
return olEdges
|
||||
# if the wire is closed there is no end so choose 1st Vertex
|
||||
# print "closed wire, starting from ",lEdges[0].Vertexes[0].Point
|
||||
return sortEdges(lEdges, lEdges[0].Vertexes[0])
|
||||
else :
|
||||
#print "looking ",aVertex.Point
|
||||
result = lookfor(aVertex,lEdges)
|
||||
if result[0] != 0 :
|
||||
del lEdges[result[1]]
|
||||
next = sortEdges(lEdges, result[3].Vertexes[-((-result[2])^1)])
|
||||
#print "result ",result[3].Vertexes[0].Point," ",result[3].Vertexes[1].Point, " compared to ",aVertex.Point
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
#print "keeping"
|
||||
olEdges += [result[3]] + next
|
||||
else:
|
||||
#print "inverting", result[3].Curve
|
||||
if isinstance(result[3].Curve,Part.Line):
|
||||
newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
elif isinstance(result[3].Curve,Part.Circle):
|
||||
mp = findMidpoint(result[3])
|
||||
newedge = Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
elif isinstance(result[3].Curve,Part.BSplineCurve):
|
||||
if isLine(result[3].Curve):
|
||||
newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()
|
||||
olEdges += [newedge] + next
|
||||
else:
|
||||
olEdges += [result[3]] + next
|
||||
else:
|
||||
olEdges += [result[3]] + next
|
||||
return olEdges
|
||||
else :
|
||||
return []
|
||||
|
||||
|
||||
def findWires(edgeslist):
|
||||
|
@ -787,6 +786,31 @@ def getNormal(shape):
|
|||
if n.getAngle(vdir) < 0.78: n = DraftVecUtils.neg(n)
|
||||
return n
|
||||
|
||||
def getRotation(v1,v2=FreeCAD.Vector(0,0,1)):
|
||||
'''Get the rotation Quaternion between 2 vectors'''
|
||||
if (v1.dot(v2) > 0.999999) or (v1.dot(v2) < -0.999999):
|
||||
# vectors are opposite
|
||||
return None
|
||||
axis = v1.cross(v2)
|
||||
axis.normalize()
|
||||
angle = math.degrees(math.sqrt((v1.Length ^ 2) * (v2.Length ^ 2)) + v1.dot(v2))
|
||||
return FreeCAD.Rotation(axis,angle)
|
||||
|
||||
def calculatePlacement(shape):
|
||||
'''calculatePlacement(shape): if the given shape is planar, this function
|
||||
returns a placement located at the center of gravity of the shape, and oriented
|
||||
towards the shape's normal. Otherwise, it returns a null placement.'''
|
||||
if not isPlanar(shape):
|
||||
return FreeCAD.Placement()
|
||||
pos = shape.BoundBox.Center
|
||||
norm = getNormal(shape)
|
||||
pla = FreeCAD.Placement()
|
||||
pla.Base = pos
|
||||
r = getRotation(norm)
|
||||
if r:
|
||||
pla.Rotation = r
|
||||
return pla
|
||||
|
||||
def offsetWire(wire,dvec,bind=False,occ=False):
|
||||
'''
|
||||
offsetWire(wire,vector,[bind]): offsets the given wire along the
|
||||
|
@ -982,11 +1006,13 @@ def isCoplanar(faces):
|
|||
"checks if all faces in the given list are coplanar"
|
||||
if len(faces) < 2:
|
||||
return True
|
||||
base =faces[0].normalAt(.5,.5)
|
||||
base =faces[0].normalAt(0,0)
|
||||
for i in range(1,len(faces)):
|
||||
normal = faces[i].normalAt(.5,.5)
|
||||
if (normal.getAngle(base) > .0001) and (normal.getAngle(base) < 3.1415):
|
||||
return False
|
||||
for v in faces[i].Vertexes:
|
||||
chord = v.Point.sub(faces[0].Vertexes[0].Point)
|
||||
dist = DraftVecUtils.project(chord,base)
|
||||
if round(dist.Length,DraftVecUtils.precision()) > 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def isPlanar(shape):
|
||||
|
|
|
@ -51,8 +51,8 @@ if open.__module__ == '__builtin__':
|
|||
pythonopen = open
|
||||
|
||||
svgcolors = {
|
||||
'Pink': (255, 192, 203),
|
||||
'Blue': (0, 0, 255),
|
||||
'Pink': (255, 192, 203),
|
||||
'Blue': (0, 0, 255),
|
||||
'Honeydew': (240, 255, 240),
|
||||
'Purple': (128, 0, 128),
|
||||
'Fuchsia': (255, 0, 255),
|
||||
|
@ -269,7 +269,7 @@ def makewire(path,checkclosed=False,donttry=False):
|
|||
#ToDo Do not catch all exceptions
|
||||
if not donttry:
|
||||
try:
|
||||
sh = Part.Wire(DraftGeomUtils.sortEdges(path))
|
||||
sh = Part.Wire(DraftGeomUtils.sortEdges(path))
|
||||
#sh = Part.Wire(path)
|
||||
isok = (not checkclosed) or sh.isClosed()
|
||||
except:# BRep_API:command not done
|
||||
|
@ -448,8 +448,7 @@ class svgHandler(xml.sax.ContentHandler):
|
|||
abh = getsize(h,unitmode)
|
||||
sx=abw/vbw
|
||||
sy=abh/vbh
|
||||
preservearstr=data.get('preserveAspectRatio',\
|
||||
'').lower()
|
||||
preservearstr=' '.join(data.get('preserveAspectRatio',[])).lower()
|
||||
uniformscaling = round(sx/sy,5) == 1
|
||||
if uniformscaling:
|
||||
m.scale(Vector(sx,sy,1))
|
||||
|
@ -534,7 +533,8 @@ class svgHandler(xml.sax.ContentHandler):
|
|||
if path:
|
||||
#sh = Part.Wire(path)
|
||||
sh = makewire(path)
|
||||
if self.fill: sh = Part.Face(sh)
|
||||
if self.fill and sh.isClosed():
|
||||
sh = Part.Face(sh)
|
||||
sh = self.applyTrans(sh)
|
||||
obj = self.doc.addObject("Part::Feature",pathname)
|
||||
obj.Shape = sh
|
||||
|
@ -624,7 +624,8 @@ class svgHandler(xml.sax.ContentHandler):
|
|||
if sweepflag:
|
||||
#angledelta=-(-angledelta % (math.pi *2)) # Step4
|
||||
#angledelta=(-angledelta % (math.pi *2)) # Step4
|
||||
angle1 = angle1-angledelta
|
||||
angle1 = angle1+angledelta
|
||||
angledelta = -angledelta
|
||||
#angle1 = math.pi - angle1
|
||||
|
||||
e1a = Part.Arc(e1,angle1-swapaxis*math.radians(90),\
|
||||
|
@ -750,7 +751,8 @@ class svgHandler(xml.sax.ContentHandler):
|
|||
if path:
|
||||
sh=makewire(path,checkclosed=False)
|
||||
#sh = Part.Wire(path)
|
||||
if self.fill: sh = Part.Face(sh)
|
||||
if self.fill and sh.isClosed():
|
||||
sh = Part.Face(sh)
|
||||
sh = self.applyTrans(sh)
|
||||
obj = self.doc.addObject("Part::Feature",pathname)
|
||||
obj.Shape = sh
|
||||
|
@ -828,7 +830,6 @@ class svgHandler(xml.sax.ContentHandler):
|
|||
obj = self.doc.addObject("Part::Feature",pathname)
|
||||
obj.Shape = sh
|
||||
self.format(obj)
|
||||
|
||||
# processing lines
|
||||
|
||||
if name == "line":
|
||||
|
@ -864,7 +865,8 @@ class svgHandler(xml.sax.ContentHandler):
|
|||
path.append(seg)
|
||||
if path:
|
||||
sh = Part.Wire(path)
|
||||
if self.fill: sh = Part.Face(sh)
|
||||
if self.fill and sh.isClosed():
|
||||
sh = Part.Face(sh)
|
||||
sh = self.applyTrans(sh)
|
||||
obj = self.doc.addObject("Part::Feature",pathname)
|
||||
obj.Shape = sh
|
||||
|
|
|
@ -677,5 +677,10 @@
|
|||
<UserDocu>Returns a reparametrized copy of this surface</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="interpolate">
|
||||
<Documentation>
|
||||
<UserDocu>Replaces this B-Spline surface by interpolating a set of points.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
# include <TColStd_Array1OfInteger.hxx>
|
||||
# include <TColgp_Array1OfPnt.hxx>
|
||||
# include <TColgp_Array2OfPnt.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <GeomAPI_PointsToBSplineSurface.hxx>
|
||||
#endif
|
||||
|
||||
#include <Base/GeometryPyCXX.h>
|
||||
|
@ -1242,6 +1244,55 @@ PyObject* BSplineSurfacePy::reparametrize(PyObject * args)
|
|||
}
|
||||
}
|
||||
|
||||
PyObject* BSplineSurfacePy::interpolate(PyObject *args)
|
||||
{
|
||||
PyObject* obj;
|
||||
double tol3d = Precision::Approximation();
|
||||
PyObject* closed = Py_False;
|
||||
PyObject* t1=0; PyObject* t2=0;
|
||||
if (!PyArg_ParseTuple(args, "O!",&(PyList_Type), &obj))
|
||||
return 0;
|
||||
try {
|
||||
Py::List list(obj);
|
||||
Standard_Integer lu = list.size();
|
||||
Py::List col(list.getItem(0));
|
||||
Standard_Integer lv = col.size();
|
||||
TColgp_Array2OfPnt interpolationPoints(1, lu, 1, lv);
|
||||
|
||||
Standard_Integer index1 = 0;
|
||||
Standard_Integer index2 = 0;
|
||||
for (Py::List::iterator it1 = list.begin(); it1 != list.end(); ++it1) {
|
||||
index1++;
|
||||
index2=0;
|
||||
Py::List row(*it1);
|
||||
for (Py::List::iterator it2 = row.begin(); it2 != row.end(); ++it2) {
|
||||
index2++;
|
||||
Py::Vector v(*it2);
|
||||
Base::Vector3d pnt = v.toVector();
|
||||
gp_Pnt newPoint(pnt.x,pnt.y,pnt.z);
|
||||
interpolationPoints.SetValue(index1, index2, newPoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (interpolationPoints.RowLength() < 2 || interpolationPoints.ColLength() < 2) {
|
||||
Standard_Failure::Raise("not enough points given");
|
||||
}
|
||||
|
||||
GeomAPI_PointsToBSplineSurface surInterpolation;
|
||||
surInterpolation.Interpolate (interpolationPoints);
|
||||
Handle_Geom_BSplineSurface sur(surInterpolation.Surface());
|
||||
this->getGeomBSplineSurfacePtr()->setHandle(sur);
|
||||
Py_Return;
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
std::string err = e->GetMessageString();
|
||||
if (err.empty()) err = e->DynamicType()->Name();
|
||||
PyErr_SetString(PyExc_Exception, err.c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Py::Int BSplineSurfacePy::getUDegree(void) const
|
||||
{
|
||||
Handle_Geom_BSplineSurface surf = Handle_Geom_BSplineSurface::DownCast
|
||||
|
|
|
@ -1362,6 +1362,11 @@ GeomBSplineSurface::~GeomBSplineSurface()
|
|||
{
|
||||
}
|
||||
|
||||
void GeomBSplineSurface::setHandle(const Handle_Geom_BSplineSurface& s)
|
||||
{
|
||||
mySurface = Handle_Geom_BSplineSurface::DownCast(s->Copy());
|
||||
}
|
||||
|
||||
const Handle_Geom_Geometry& GeomBSplineSurface::handle() const
|
||||
{
|
||||
return mySurface;
|
||||
|
|
|
@ -448,6 +448,7 @@ public:
|
|||
// Base implementer ----------------------------
|
||||
virtual PyObject *getPyObject(void);
|
||||
|
||||
void setHandle(const Handle_Geom_BSplineSurface&);
|
||||
const Handle_Geom_Geometry& handle() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -726,6 +726,11 @@ void TopoShape::exportBrep(const char *filename) const
|
|||
throw Base::Exception("Writing of BREP failed");
|
||||
}
|
||||
|
||||
void TopoShape::exportBrep(std::ostream& out)
|
||||
{
|
||||
BRepTools::Write(this->_Shape, out);
|
||||
}
|
||||
|
||||
void TopoShape::exportStl(const char *filename) const
|
||||
{
|
||||
StlAPI_Writer writer;
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
void exportIges(const char *FileName) const;
|
||||
void exportStep(const char *FileName) const;
|
||||
void exportBrep(const char *FileName) const;
|
||||
void exportBrep(std::ostream&);
|
||||
void exportStl (const char *FileName) const;
|
||||
void exportFaceSet(double, double, std::ostream&) const;
|
||||
void exportLineSet(std::ostream&) const;
|
||||
|
|
|
@ -88,11 +88,23 @@
|
|||
</Attribute>
|
||||
<Attribute Name="ParameterRange" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns a 4 tuple with the parameter range</UserDocu>
|
||||
<UserDocu>Returns a 2 tuple with the parameter range</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ParameterRange" Type="Tuple"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Curve" ReadOnly="true">
|
||||
<Attribute Name="FirstParameter" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns the start value of the parameter range</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="FirstParameter" Type="Float"/>
|
||||
</Attribute>
|
||||
<Attribute Name="LastParameter" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns the end value of the parameter range</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LastParameter" Type="Float"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Curve" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns the 3D curve of the edge</UserDocu>
|
||||
</Documentation>
|
||||
|
|
|
@ -660,6 +660,22 @@ Py::Tuple TopoShapeEdgePy::getParameterRange(void) const
|
|||
return t;
|
||||
}
|
||||
|
||||
Py::Float TopoShapeEdgePy::getFirstParameter(void) const
|
||||
{
|
||||
const TopoDS_Edge& e = TopoDS::Edge(getTopoShapePtr()->_Shape);
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
double t = adapt.FirstParameter();
|
||||
return Py::Float(t);
|
||||
}
|
||||
|
||||
Py::Float TopoShapeEdgePy::getLastParameter(void) const
|
||||
{
|
||||
const TopoDS_Edge& e = TopoDS::Edge(getTopoShapePtr()->_Shape);
|
||||
BRepAdaptor_Curve adapt(e);
|
||||
double t = adapt.LastParameter();
|
||||
return Py::Float(t);
|
||||
}
|
||||
|
||||
Py::Object TopoShapeEdgePy::getCenterOfMass(void) const
|
||||
{
|
||||
GProp_GProps props;
|
||||
|
|
|
@ -43,6 +43,11 @@ Sub-elements such as vertices, edges or faces are accessible as:
|
|||
<UserDocu>Export the content of this shape to an BREP file. BREP is a CasCade native format.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="exportBrepToString" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Export the content of this shape to a string in BREP format. BREP is a CasCade native format.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="exportStl" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Export the content of this shape to an STL mesh file.</UserDocu>
|
||||
|
@ -53,6 +58,11 @@ Sub-elements such as vertices, edges or faces are accessible as:
|
|||
<UserDocu>Import the content to this shape of a string in BREP format.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="importBrepFromString">
|
||||
<Documentation>
|
||||
<UserDocu>Import the content to this shape from a string in BREP format.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="extrude" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Extrude the shape along a direction.</UserDocu>
|
||||
|
|
|
@ -311,6 +311,32 @@ PyObject* TopoShapePy::exportBrep(PyObject *args)
|
|||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::exportBrepToString(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
// write brep file
|
||||
std::stringstream str;
|
||||
getTopoShapePtr()->exportBrep(str);
|
||||
return Py::new_reference_to(Py::String(str.str()));
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
PyErr_SetString(PyExc_Exception,e.what());
|
||||
return NULL;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PyErr_SetString(PyExc_Exception,e.what());
|
||||
return NULL;
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
PyErr_SetString(PyExc_Exception, e->GetMessageString());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::importBrep(PyObject *args)
|
||||
{
|
||||
PyObject* input;
|
||||
|
@ -335,6 +361,34 @@ PyObject* TopoShapePy::importBrep(PyObject *args)
|
|||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::importBrepFromString(PyObject *args)
|
||||
{
|
||||
char* input;
|
||||
if (!PyArg_ParseTuple(args, "s", &input))
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
// read brep
|
||||
std::stringstream str(input);
|
||||
getTopoShapePtr()->importBrep(str);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
PyErr_SetString(PyExc_Exception,e.what());
|
||||
return NULL;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PyErr_SetString(PyExc_Exception,e.what());
|
||||
return NULL;
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
PyErr_SetString(PyExc_Exception, e->GetMessageString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* TopoShapePy::exportStl(PyObject *args)
|
||||
{
|
||||
char* filename;
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <Gui/Command.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
#include <Gui/SoFCUnifiedSelection.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
|
||||
|
@ -270,6 +271,9 @@ DlgPrimitives::~DlgPrimitives()
|
|||
void DlgPrimitives::pickCallback(void * ud, SoEventCallback * n)
|
||||
{
|
||||
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent*>(n->getEvent());
|
||||
Picker* pick = reinterpret_cast<Picker*>(ud);
|
||||
if (pick->exitCode >= 0)
|
||||
pick->loop.exit(pick->exitCode);
|
||||
|
||||
// Mark all incoming mouse button events as handled, especially, to deactivate the selection node
|
||||
n->setHandled();
|
||||
|
@ -277,16 +281,14 @@ void DlgPrimitives::pickCallback(void * ud, SoEventCallback * n)
|
|||
if (mbe->getState() == SoButtonEvent::DOWN) {
|
||||
const SoPickedPoint * point = n->getPickedPoint();
|
||||
if (point) {
|
||||
Picker* pick = reinterpret_cast<Picker*>(ud);
|
||||
if (pick->pickedPoint(point)) {
|
||||
pick->loop.exit(0);
|
||||
pick->exitCode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2) {
|
||||
if (mbe->getState() == SoButtonEvent::UP) {
|
||||
Picker* pick = reinterpret_cast<Picker*>(ud);
|
||||
pick->loop.exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -305,9 +307,17 @@ void DlgPrimitives::executeCallback(Picker* p)
|
|||
if (!viewer->isEditing()) {
|
||||
viewer->setEditing(true);
|
||||
viewer->setRedirectToSceneGraph(true);
|
||||
SoNode* root = viewer->getSceneGraph();
|
||||
int mode;
|
||||
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) {
|
||||
mode = static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.getValue();
|
||||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(Gui::SoFCUnifiedSelection::OFF);
|
||||
}
|
||||
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, p);
|
||||
this->setDisabled(true);
|
||||
int ret = p->loop.exec();
|
||||
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId()))
|
||||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(mode);
|
||||
this->setEnabled(true);
|
||||
viewer->setEditing(false);
|
||||
viewer->setRedirectToSceneGraph(false);
|
||||
|
@ -587,6 +597,9 @@ Location::~Location()
|
|||
viewer->setEditing(false);
|
||||
viewer->setRedirectToSceneGraph(false);
|
||||
viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback,this);
|
||||
SoNode* root = viewer->getSceneGraph();
|
||||
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId()))
|
||||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(this->mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,6 +618,11 @@ void Location::on_viewPositionButton_clicked()
|
|||
viewer->setEditing(true);
|
||||
viewer->setRedirectToSceneGraph(true);
|
||||
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, this);
|
||||
SoNode* root = viewer->getSceneGraph();
|
||||
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) {
|
||||
this->mode = static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.getValue();
|
||||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(Gui::SoFCUnifiedSelection::OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -617,15 +635,7 @@ void Location::pickCallback(void * ud, SoEventCallback * n)
|
|||
// Mark all incoming mouse button events as handled, especially, to deactivate the selection node
|
||||
n->getAction()->setHandled();
|
||||
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1) {
|
||||
if (mbe->getState() == SoButtonEvent::UP) {
|
||||
n->setHandled();
|
||||
view->setEditing(false);
|
||||
view->setRedirectToSceneGraph(false);
|
||||
Location* dlg = reinterpret_cast<Location*>(ud);
|
||||
dlg->activeView = 0;
|
||||
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback,ud);
|
||||
}
|
||||
else if (mbe->getState() == SoButtonEvent::DOWN) {
|
||||
if (mbe->getState() == SoButtonEvent::DOWN) {
|
||||
const SoPickedPoint * point = n->getPickedPoint();
|
||||
if (point) {
|
||||
SbVec3f pnt = point->getPoint();
|
||||
|
@ -637,6 +647,19 @@ void Location::pickCallback(void * ud, SoEventCallback * n)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2) {
|
||||
if (mbe->getState() == SoButtonEvent::UP) {
|
||||
n->setHandled();
|
||||
view->setEditing(false);
|
||||
view->setRedirectToSceneGraph(false);
|
||||
Location* dlg = reinterpret_cast<Location*>(ud);
|
||||
dlg->activeView = 0;
|
||||
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback,ud);
|
||||
SoNode* root = view->getSceneGraph();
|
||||
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId()))
|
||||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(static_cast<Location*>(ud)->mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString Location::toPlacement() const
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace PartGui {
|
|||
class Picker
|
||||
{
|
||||
public:
|
||||
Picker()
|
||||
Picker() : exitCode(-1)
|
||||
{
|
||||
}
|
||||
virtual ~Picker()
|
||||
|
@ -51,6 +51,7 @@ public:
|
|||
void createPrimitive(QWidget* widget, const QString&, Gui::Document*);
|
||||
QString toPlacement(const gp_Ax2&) const;
|
||||
|
||||
int exitCode;
|
||||
QEventLoop loop;
|
||||
};
|
||||
|
||||
|
@ -88,6 +89,7 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
static void pickCallback(void * ud, SoEventCallback * n);
|
||||
int mode;
|
||||
QPointer<QWidget> activeView;
|
||||
Ui_Location ui;
|
||||
};
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Model refinement</string>
|
||||
<string>Model settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
|
|
|
@ -15,6 +15,7 @@ include_directories(
|
|||
link_directories(${OCC_LIBRARY_DIR})
|
||||
|
||||
set(PartDesign_LIBS
|
||||
${OCC_LIBRARIES}
|
||||
Part
|
||||
FreeCADApp
|
||||
)
|
||||
|
|
|
@ -102,8 +102,6 @@ void CmdRaytracingWriteCamera::activated(int iMsg)
|
|||
SoInput in;
|
||||
in.setBuffer((void*)ppReturn,std::strlen(ppReturn));
|
||||
|
||||
//if (!in.openFile(filename)) { exit(1); }
|
||||
|
||||
SoNode* rootNode;
|
||||
SoDB::read(&in,rootNode);
|
||||
|
||||
|
|
|
@ -731,9 +731,8 @@ public:
|
|||
|
||||
virtual void mouseMove(Base::Vector2D onSketchPos)
|
||||
{
|
||||
setPositionText(onSketchPos);
|
||||
|
||||
if (Mode==STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr1);
|
||||
return;
|
||||
|
@ -750,6 +749,16 @@ public:
|
|||
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - dx, EditCurve[0].fY - dy);
|
||||
}
|
||||
EditCurve[33] = EditCurve[1];
|
||||
|
||||
// Display radius and start angle
|
||||
float radius = (onSketchPos - EditCurve[0]).Length();
|
||||
float angle = atan2f(dy_ , dx_) * 180 / M_PI;
|
||||
|
||||
char buf[40];
|
||||
sprintf( buf, " (R%.1f,%.1f)", radius, angle);
|
||||
std::string text = buf;
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr2);
|
||||
|
@ -767,6 +776,15 @@ public:
|
|||
float dy = rx * sin(angle) + ry * cos(angle);
|
||||
EditCurve[i] = Base::Vector2D(CenterPoint.fX + dx, CenterPoint.fY + dy);
|
||||
}
|
||||
|
||||
// Display radius and end angle
|
||||
float radius = (onSketchPos - EditCurve[0]).Length();
|
||||
|
||||
char buf[40];
|
||||
sprintf( buf, " (R%.1f,%.1f)", radius, arcAngle * 180 / M_PI);
|
||||
std::string text = buf;
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr3);
|
||||
|
@ -950,8 +968,8 @@ public:
|
|||
|
||||
virtual void mouseMove(Base::Vector2D onSketchPos)
|
||||
{
|
||||
setPositionText(onSketchPos);
|
||||
if (Mode==STATUS_SEEK_First) {
|
||||
setPositionText(onSketchPos);
|
||||
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
|
||||
renderSuggestConstraintsCursor(sugConstr1);
|
||||
return;
|
||||
|
@ -968,6 +986,15 @@ public:
|
|||
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
|
||||
}
|
||||
EditCurve[33] = EditCurve[1];
|
||||
|
||||
// Display radius for user
|
||||
float radius = (onSketchPos - EditCurve[0]).Length();
|
||||
|
||||
char buf[40];
|
||||
sprintf( buf, "R%.1f", radius);
|
||||
std::string text = buf;
|
||||
setPositionText(onSketchPos, text);
|
||||
|
||||
sketchgui->drawEdit(EditCurve);
|
||||
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f), CURVE)) {
|
||||
renderSuggestConstraintsCursor(sugConstr2);
|
||||
|
|
|
@ -385,6 +385,12 @@ void DrawSketchHandler::renderSuggestConstraintsCursor(std::vector<AutoConstrain
|
|||
applyCursor(newCursor);
|
||||
}
|
||||
|
||||
void DrawSketchHandler::setPositionText(const Base::Vector2D &Pos, const std::string &text)
|
||||
{
|
||||
sketchgui->setPositionText(Pos, text);
|
||||
}
|
||||
|
||||
|
||||
void DrawSketchHandler::setPositionText(const Base::Vector2D &Pos)
|
||||
{
|
||||
sketchgui->setPositionText(Pos);
|
||||
|
|
|
@ -87,6 +87,7 @@ public:
|
|||
void createAutoConstraints(const std::vector<AutoConstraint> &autoConstrs,
|
||||
int geoId, Sketcher::PointPos pointPos=Sketcher::none);
|
||||
|
||||
void setPositionText(const Base::Vector2D &Pos, const std::string &text);
|
||||
void setPositionText(const Base::Vector2D &Pos);
|
||||
void resetPositionText(void);
|
||||
void renderSuggestConstraintsCursor(std::vector<AutoConstraint> &suggestedConstraints);
|
||||
|
|
|
@ -3026,6 +3026,12 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer)
|
|||
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionRole.setValue(TRUE);
|
||||
}
|
||||
|
||||
void ViewProviderSketch::setPositionText(const Base::Vector2D &Pos, const std::string &text)
|
||||
{
|
||||
edit->textX->string = text.c_str();
|
||||
edit->textPos->translation = SbVec3f(Pos.fX,Pos.fY,zText);
|
||||
}
|
||||
|
||||
void ViewProviderSketch::setPositionText(const Base::Vector2D &Pos)
|
||||
{
|
||||
char buf[40];
|
||||
|
|
|
@ -200,6 +200,7 @@ protected:
|
|||
/// build up the visual of the constraints
|
||||
void rebuildConstraintsVisual(void);
|
||||
|
||||
void setPositionText(const Base::Vector2D &Pos, const std::string &txt);
|
||||
void setPositionText(const Base::Vector2D &Pos);
|
||||
void resetPositionText(void);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user