Merge branch 'master' of git://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad
@@ -14,6 +14,8 @@ IF (WIN32)
|
||||
FIND_PATH(OCC_INCLUDE_DIR Standard_Version.hxx
|
||||
/usr/include/opencascade
|
||||
/usr/local/include/opencascade
|
||||
/opt/opencascade/include
|
||||
/opt/opencascade/inc
|
||||
)
|
||||
|
||||
FIND_LIBRARY(OCC_LIBRARY TKernel
|
||||
|
||||
@@ -91,6 +91,8 @@
|
||||
#include "VRMLObject.h"
|
||||
#include "Annotation.h"
|
||||
#include "MeasureDistance.h"
|
||||
#include "Placement.h"
|
||||
#include "Plane.h"
|
||||
|
||||
// If you stumble here, run the target "BuildExtractRevision" on Windows systems
|
||||
// or the Python script "SubWCRev.py" on Linux based systems which builds
|
||||
@@ -1042,6 +1044,8 @@ void Application::initTypes(void)
|
||||
App ::Annotation ::init();
|
||||
App ::AnnotationLabel ::init();
|
||||
App ::MeasureDistance ::init();
|
||||
App ::Placement ::init();
|
||||
App ::Plane ::init();
|
||||
}
|
||||
|
||||
void Application::initConfig(int argc, char ** argv)
|
||||
@@ -1204,10 +1208,12 @@ void Application::processCmdLineFiles(void)
|
||||
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(), true);
|
||||
try{
|
||||
Base::Interpreter().loadModule(File.fileNamePure().c_str());
|
||||
}catch(PyException){
|
||||
// if module load not work, just try run the script (run in __main__)
|
||||
Base::Interpreter().runFile(File.filePath().c_str(),true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::vector<std::string> mods = App::GetApplication().getImportModules(Ext.c_str());
|
||||
|
||||
@@ -77,6 +77,7 @@ SET(Document_CPP_SRCS
|
||||
InventorObject.cpp
|
||||
MeasureDistance.cpp
|
||||
Placement.cpp
|
||||
Plane.cpp
|
||||
Transactions.cpp
|
||||
VRMLObject.cpp
|
||||
)
|
||||
@@ -95,6 +96,7 @@ SET(Document_HPP_SRCS
|
||||
InventorObject.h
|
||||
MeasureDistance.h
|
||||
Placement.h
|
||||
Plane.h
|
||||
Transactions.h
|
||||
VRMLObject.h
|
||||
)
|
||||
|
||||
@@ -143,6 +143,8 @@ struct DocumentP
|
||||
int iUndoMode;
|
||||
unsigned int UndoMemSize;
|
||||
unsigned int UndoMaxStackSize;
|
||||
DependencyList DepList;
|
||||
std::map<DocumentObject*,Vertex> VertexObjectList;
|
||||
|
||||
DocumentP() {
|
||||
activeObject = 0;
|
||||
@@ -530,13 +532,20 @@ Document::Document(void)
|
||||
ADD_PROPERTY_TYPE(LastModifiedDate,("Unknown"),0,Prop_ReadOnly,"Date of last modification");
|
||||
ADD_PROPERTY_TYPE(Company,(""),0,Prop_None,"Additional tag to save the the name of the company");
|
||||
ADD_PROPERTY_TYPE(Comment,(""),0,Prop_None,"Additional tag to save a comment");
|
||||
ADD_PROPERTY_TYPE(Meta,(),0,Prop_None,"Map with additional meta information");
|
||||
ADD_PROPERTY_TYPE(Material,(),0,Prop_None,"Map with material properties");
|
||||
// create the uuid for the document
|
||||
Base::Uuid id;
|
||||
ADD_PROPERTY_TYPE(Id,(id.UuidStr),0,Prop_None,"UUID of the document");
|
||||
ADD_PROPERTY_TYPE(Id,(""),0,Prop_None,"ID of the document");
|
||||
ADD_PROPERTY_TYPE(Uid,(id),0,Prop_None,"UUID of the document");
|
||||
|
||||
// license stuff
|
||||
ADD_PROPERTY_TYPE(License,("CC-BY 3.0"),0,Prop_None,"License string of the Item");
|
||||
ADD_PROPERTY_TYPE(LicenseURL,("http://creativecommons.org/licenses/by/3.0/"),0,Prop_None,"URL to the license text/contract");
|
||||
|
||||
// create transient directory
|
||||
std::string basePath = Base::FileInfo::getTempPath() + GetApplication().getExecutableName();
|
||||
Base::FileInfo TransDir(basePath + "_Doc_" + id.UuidStr);
|
||||
Base::FileInfo TransDir(basePath + "_Doc_" + id.getValue());
|
||||
if (!TransDir.exists())
|
||||
TransDir.createDirectory();
|
||||
ADD_PROPERTY_TYPE(TransientDir,(TransDir.filePath().c_str()),0,Prop_Transient,
|
||||
@@ -629,7 +638,7 @@ void Document::Restore(Base::XMLReader &reader)
|
||||
|
||||
// create new transient directory
|
||||
std::string basePath = Base::FileInfo::getTempPath() + GetApplication().getExecutableName();
|
||||
Base::FileInfo TransDirNew(basePath + "_Doc_" + Id.getValue());
|
||||
Base::FileInfo TransDirNew(basePath + "_Doc_" + Uid.getValueStr());
|
||||
if(!TransDirNew.exists())
|
||||
TransDirNew.createDirectory();
|
||||
TransientDir.setValue(TransDirNew.filePath());
|
||||
@@ -859,7 +868,7 @@ bool Document::save (void)
|
||||
// make a tmp. file where to save the project data first and then rename to
|
||||
// the actual file name. This may be useful if overwriting an existing file
|
||||
// fails so that the data of the work up to now isn't lost.
|
||||
std::string uuid = Base::Uuid::CreateUuid();
|
||||
std::string uuid = Base::Uuid::createUuid();
|
||||
std::string fn = FileName.getValue();
|
||||
fn += "."; fn += uuid;
|
||||
Base::FileInfo tmp(fn);
|
||||
@@ -1081,6 +1090,24 @@ std::vector<App::DocumentObject*> Document::getInList(const DocumentObject* me)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Document::_rebuildDependencyList(void){
|
||||
|
||||
// Filling up the adjacency List
|
||||
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It)
|
||||
// add the object as Vertex and remember the index
|
||||
d->VertexObjectList[It->second] = add_vertex(d->DepList);
|
||||
// add the edges
|
||||
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
|
||||
std::vector<DocumentObject*> OutList = It->second->getOutList();
|
||||
for (std::vector<DocumentObject*>::const_iterator It2=OutList.begin();It2!=OutList.end();++It2)
|
||||
if (*It2)
|
||||
add_edge(d->VertexObjectList[It->second],d->VertexObjectList[*It2],d->DepList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Document::recompute()
|
||||
{
|
||||
// delete recompute log
|
||||
@@ -1088,27 +1115,30 @@ void Document::recompute()
|
||||
delete *it;
|
||||
_RecomputeLog.clear();
|
||||
|
||||
DependencyList DepList;
|
||||
std::map<DocumentObject*,Vertex> VertexObjectList;
|
||||
// updates the depency graph
|
||||
_rebuildDependencyList();
|
||||
|
||||
// Filling up the adjacency List
|
||||
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It)
|
||||
// add the object as Vertex and remember the index
|
||||
VertexObjectList[It->second] = add_vertex(DepList);
|
||||
// add the edges
|
||||
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
|
||||
std::vector<DocumentObject*> OutList = It->second->getOutList();
|
||||
for (std::vector<DocumentObject*>::const_iterator It2=OutList.begin();It2!=OutList.end();++It2)
|
||||
if (*It2)
|
||||
add_edge(VertexObjectList[It->second],VertexObjectList[*It2],DepList);
|
||||
}
|
||||
//DependencyList DepList;
|
||||
//std::map<DocumentObject*,Vertex> VertexObjectList;
|
||||
|
||||
//// Filling up the adjacency List
|
||||
//for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It)
|
||||
// // add the object as Vertex and remember the index
|
||||
// VertexObjectList[It->second] = add_vertex(DepList);
|
||||
//// add the edges
|
||||
//for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
|
||||
// std::vector<DocumentObject*> OutList = It->second->getOutList();
|
||||
// for (std::vector<DocumentObject*>::const_iterator It2=OutList.begin();It2!=OutList.end();++It2)
|
||||
// if (*It2)
|
||||
// add_edge(VertexObjectList[It->second],VertexObjectList[*It2],DepList);
|
||||
//}
|
||||
|
||||
std::list<Vertex> make_order;
|
||||
DependencyList::out_edge_iterator j, jend;
|
||||
|
||||
try {
|
||||
// this sort gives the execute
|
||||
boost::topological_sort(DepList, std::front_inserter(make_order));
|
||||
boost::topological_sort(d->DepList, std::front_inserter(make_order));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Document::recompute: " << e.what() << std::endl;
|
||||
@@ -1116,7 +1146,7 @@ void Document::recompute()
|
||||
}
|
||||
|
||||
// caching vertex to DocObject
|
||||
for (std::map<DocumentObject*,Vertex>::const_iterator It1= VertexObjectList.begin();It1 != VertexObjectList.end(); ++It1)
|
||||
for (std::map<DocumentObject*,Vertex>::const_iterator It1= d->VertexObjectList.begin();It1 != d->VertexObjectList.end(); ++It1)
|
||||
d->vertexMap[It1->second] = It1->first;
|
||||
|
||||
#ifdef FC_LOGFEATUREUPDATE
|
||||
@@ -1136,8 +1166,8 @@ void Document::recompute()
|
||||
NeedUpdate = true;
|
||||
else {// if (Cur->mustExecute() == -1)
|
||||
// update if one of the dependencies is touched
|
||||
for (boost::tie(j, jend) = out_edges(*i, DepList); j != jend; ++j) {
|
||||
DocumentObject* Test = d->vertexMap[target(*j, DepList)];
|
||||
for (boost::tie(j, jend) = out_edges(*i, d->DepList); j != jend; ++j) {
|
||||
DocumentObject* Test = d->vertexMap[target(*j, d->DepList)];
|
||||
if (!Test) continue;
|
||||
#ifdef FC_LOGFEATUREUPDATE
|
||||
std::clog << Test->getNameInDocument() << ", " ;
|
||||
|
||||
@@ -71,11 +71,29 @@ public:
|
||||
/// creators name (utf-8)
|
||||
PropertyString CreatedBy;
|
||||
PropertyString CreationDate;
|
||||
/// user last modified the document
|
||||
PropertyString LastModifiedBy;
|
||||
PropertyString LastModifiedDate;
|
||||
/// company name UTF8(optional)
|
||||
PropertyString Company;
|
||||
/// long comment or description (UTF8 with line breaks)
|
||||
PropertyString Comment;
|
||||
/// Id e.g. Part number
|
||||
PropertyString Id;
|
||||
/// unique identifier of the document
|
||||
PropertyUUID Uid;
|
||||
/** License string
|
||||
* Holds the short license string for the Item, e.g. CC-BY
|
||||
* for the Creative Commons license suit.
|
||||
*/
|
||||
App::PropertyString License;
|
||||
/// License descripton/contract URL
|
||||
App::PropertyString LicenseURL;
|
||||
/// Meta descriptons
|
||||
App::PropertyMap Meta;
|
||||
/// Meta descriptons
|
||||
App::PropertyMap Material;
|
||||
/// read-only name of the temp dir created wen the document is opened
|
||||
PropertyString TransientDir;
|
||||
//@}
|
||||
|
||||
@@ -283,6 +301,8 @@ protected:
|
||||
/// helper which Recompute only this feature
|
||||
bool _recomputeFeature(DocumentObject* Feat);
|
||||
void _clearRedos();
|
||||
/// refresh the internal dependency graph
|
||||
void _rebuildDependencyList(void);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</Attribute>
|
||||
<Attribute Name="InList" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>A list of all objects which link tobthis object.</UserDocu>
|
||||
<UserDocu>A list of all objects which link to this object.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="InList" Type="List"/>
|
||||
</Attribute>
|
||||
|
||||
@@ -40,7 +40,6 @@ PROPERTY_SOURCE(App::GeoFeature, App::DocumentObject)
|
||||
|
||||
GeoFeature::GeoFeature(void)
|
||||
{
|
||||
ADD_PROPERTY(Pos,(0));
|
||||
ADD_PROPERTY(Placement,(Base::Placement()));
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ class AppExport GeoFeature : public App::DocumentObject
|
||||
PROPERTY_HEADER(App::GeoFeature);
|
||||
|
||||
public:
|
||||
PropertyPlacementLink Pos;
|
||||
PropertyPlacement Placement;
|
||||
|
||||
/// Constructor
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
using namespace App;
|
||||
|
||||
|
||||
PROPERTY_SOURCE_ABSTRACT(App::Placement, App::DocumentObject)
|
||||
PROPERTY_SOURCE(App::Placement, App::DocumentObject)
|
||||
|
||||
|
||||
//===========================================================================
|
||||
@@ -43,7 +43,6 @@ PROPERTY_SOURCE_ABSTRACT(App::Placement, App::DocumentObject)
|
||||
Placement::Placement(void)
|
||||
{
|
||||
|
||||
ADD_PROPERTY(Pos,(Base::Placement()));
|
||||
}
|
||||
|
||||
Placement::~Placement(void)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include <Base/Placement.h>
|
||||
|
||||
#include "DocumentObject.h"
|
||||
#include "GeoFeature.h"
|
||||
#include "PropertyGeo.h"
|
||||
|
||||
|
||||
@@ -48,18 +48,21 @@ namespace App
|
||||
/** Placement Object
|
||||
* Handles the repositioning of data. Also can do grouping
|
||||
*/
|
||||
class AppExport Placement: public App::DocumentObject
|
||||
class AppExport Placement: public App::GeoFeature
|
||||
{
|
||||
PROPERTY_HEADER(App::Placement);
|
||||
|
||||
public:
|
||||
|
||||
PropertyPlacement Pos;
|
||||
|
||||
|
||||
/// Constructor
|
||||
Placement(void);
|
||||
virtual ~Placement();
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "Gui::ViewProviderPlacement";
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) Jürgen Riegel ([email protected]) 2012 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
|
||||
#include "Plane.h"
|
||||
|
||||
using namespace App;
|
||||
|
||||
|
||||
PROPERTY_SOURCE(App::Plane, App::GeoFeature)
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// Feature
|
||||
//===========================================================================
|
||||
|
||||
Plane::Plane(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Plane::~Plane(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) Jürgen Riegel ([email protected]) 2012 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef _AppPlane_h_
|
||||
#define _AppPlane_h_
|
||||
|
||||
|
||||
#include "GeoFeature.h"
|
||||
#include "PropertyGeo.h"
|
||||
|
||||
|
||||
|
||||
namespace App
|
||||
{
|
||||
|
||||
|
||||
/** Plane Object
|
||||
* Used to define planar support for all kind of operations in the document space
|
||||
*/
|
||||
class AppExport Plane: public App::GeoFeature
|
||||
{
|
||||
PROPERTY_HEADER(App::Plane);
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
Plane(void);
|
||||
virtual ~Plane();
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "Gui::ViewProviderPlane";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} //namespace App
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -254,12 +254,17 @@ void PropertyLinkSub::setPyObject(PyObject *value)
|
||||
|
||||
setValue(pcObj->getDocumentObjectPtr(),vals);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type of first element in tuple must be 'DocumentObject', not ");
|
||||
error += tup[0].ptr()->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
}
|
||||
else if(Py_None == value) {
|
||||
setValue(0);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be 'DocumentObject', 'NoneType' of ('DocumentObject',['String',]) not ");
|
||||
std::string error = std::string("type must be 'DocumentObject', 'NoneType' or ('DocumentObject',['String',]) not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
|
||||
@@ -1127,6 +1127,110 @@ unsigned int PropertyString::getMemSize (void) const
|
||||
return static_cast<unsigned int>(_cValue.size());
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
// PropertyUUID
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
TYPESYSTEM_SOURCE(App::PropertyUUID , App::Property);
|
||||
|
||||
PropertyUUID::PropertyUUID()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PropertyUUID::~PropertyUUID()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PropertyUUID::setValue(const Base::Uuid &id)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_uuid = id;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
void PropertyUUID::setValue(const char* sString)
|
||||
{
|
||||
if (sString) {
|
||||
aboutToSetValue();
|
||||
_uuid.setValue(sString);
|
||||
hasSetValue();
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyUUID::setValue(const std::string &sString)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_uuid.setValue(sString);
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
const std::string& PropertyUUID::getValueStr(void) const
|
||||
{
|
||||
return _uuid.getValue();
|
||||
}
|
||||
|
||||
const Base::Uuid& PropertyUUID::getValue(void) const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
PyObject *PropertyUUID::getPyObject(void)
|
||||
{
|
||||
PyObject *p = PyString_FromString(_uuid.getValue().c_str());
|
||||
return p;
|
||||
}
|
||||
|
||||
void PropertyUUID::setPyObject(PyObject *value)
|
||||
{
|
||||
std::string string;
|
||||
if (PyString_Check(value)) {
|
||||
string = PyString_AsString(value);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be a str, not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
|
||||
// assign the string
|
||||
setValue(string);
|
||||
}
|
||||
|
||||
void PropertyUUID::Save (Base::Writer &writer) const
|
||||
{
|
||||
writer.Stream() << writer.ind() << "<Uuid value=\"" << _uuid.getValue() <<"\"/>" << std::endl;
|
||||
}
|
||||
|
||||
void PropertyUUID::Restore(Base::XMLReader &reader)
|
||||
{
|
||||
// read my Element
|
||||
reader.readElement("Uuid");
|
||||
// get the value of my Attribute
|
||||
setValue(reader.getAttribute("value"));
|
||||
}
|
||||
|
||||
Property *PropertyUUID::Copy(void) const
|
||||
{
|
||||
PropertyUUID *p= new PropertyUUID();
|
||||
p->_uuid = _uuid;
|
||||
return p;
|
||||
}
|
||||
|
||||
void PropertyUUID::Paste(const Property &from)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_uuid = dynamic_cast<const PropertyUUID&>(from)._uuid;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
unsigned int PropertyUUID::getMemSize (void) const
|
||||
{
|
||||
return static_cast<unsigned int>(sizeof(_uuid));
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// PropertyFont
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
@@ -1300,6 +1404,183 @@ void PropertyStringList::Paste(const Property &from)
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// PropertyMap
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
TYPESYSTEM_SOURCE(App::PropertyMap , App::Property);
|
||||
|
||||
PropertyMap::PropertyMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PropertyMap::~PropertyMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// Base class implementer
|
||||
|
||||
|
||||
int PropertyMap::getSize(void) const
|
||||
{
|
||||
return static_cast<int>(_lValueList.size());
|
||||
}
|
||||
|
||||
void PropertyMap::setValue(const std::string& key,const std::string& value)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_lValueList[key] = value;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
void PropertyMap::setValues(const std::map<std::string,std::string>& map)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_lValueList=map;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::string& PropertyMap::operator[] (const std::string& key) const
|
||||
{
|
||||
static std::string empty;
|
||||
std::map<std::string,std::string>::const_iterator it = _lValueList.find(key);
|
||||
if(it!=_lValueList.end())
|
||||
return it->second;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
PyObject *PropertyMap::getPyObject(void)
|
||||
{
|
||||
PyObject* dict = PyDict_New();
|
||||
|
||||
for (std::map<std::string,std::string>::const_iterator it = _lValueList.begin();it!= _lValueList.end(); ++it) {
|
||||
PyObject* item = PyUnicode_DecodeUTF8(it->second.c_str(), it->second.size(), 0);
|
||||
if (!item) {
|
||||
Py_DECREF(dict);
|
||||
throw Base::Exception("UTF8 conversion failure at PropertyMap::getPyObject()");
|
||||
}
|
||||
PyDict_SetItemString(dict,it->first.c_str(),item);
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
void PropertyMap::setPyObject(PyObject *value)
|
||||
{
|
||||
if (PyDict_Check(value)) {
|
||||
|
||||
std::map<std::string,std::string> values;
|
||||
// get key and item list
|
||||
PyObject* keyList = PyDict_Keys(value);
|
||||
|
||||
PyObject* itemList = PyDict_Values(value);
|
||||
Py_ssize_t nSize = PyList_Size(keyList);
|
||||
|
||||
for (Py_ssize_t i=0; i<nSize;++i) {
|
||||
|
||||
// check on the key:
|
||||
std::string keyStr;
|
||||
PyObject* key = PyList_GetItem(keyList, i);
|
||||
if (PyString_Check(key)) {
|
||||
keyStr = PyString_AsString(key);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type of the key need to be a string, not");
|
||||
error += key->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
|
||||
// check on the item:
|
||||
PyObject* item = PyList_GetItem(itemList, i);
|
||||
if (PyUnicode_Check(item)) {
|
||||
PyObject* unicode = PyUnicode_AsUTF8String(item);
|
||||
values[keyStr] = PyString_AsString(unicode);
|
||||
Py_DECREF(unicode);
|
||||
}
|
||||
else if (PyString_Check(item)) {
|
||||
values[keyStr] = PyString_AsString(item);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type in list must be string or unicode, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
setValues(values);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be a dict object");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int PropertyMap::getMemSize (void) const
|
||||
{
|
||||
size_t size=0;
|
||||
for (std::map<std::string,std::string>::const_iterator it = _lValueList.begin();it!= _lValueList.end(); ++it) {
|
||||
size += it->second.size();
|
||||
size += it->first.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void PropertyMap::Save (Base::Writer &writer) const
|
||||
{
|
||||
writer.Stream() << writer.ind() << "<Map count=\"" << getSize() <<"\">" << endl;
|
||||
writer.incInd();
|
||||
for (std::map<std::string,std::string>::const_iterator it = _lValueList.begin();it!= _lValueList.end(); ++it)
|
||||
writer.Stream() << writer.ind() << "<Item key=\"" << it->first <<"\" value=\"" << encodeAttribute(it->second) <<"\"/>" << endl;
|
||||
|
||||
writer.decInd();
|
||||
writer.Stream() << writer.ind() << "</Map>" << endl ;
|
||||
}
|
||||
|
||||
void PropertyMap::Restore(Base::XMLReader &reader)
|
||||
{
|
||||
// read my Element
|
||||
reader.readElement("Map");
|
||||
// get the value of my Attribute
|
||||
int count = reader.getAttributeAsInteger("count");
|
||||
|
||||
std::map<std::string,std::string> values;
|
||||
for(int i = 0; i < count; i++) {
|
||||
reader.readElement("Item");
|
||||
values[reader.getAttribute("key")] = reader.getAttribute("value");
|
||||
}
|
||||
|
||||
reader.readEndElement("Map");
|
||||
|
||||
// assignment
|
||||
setValues(values);
|
||||
}
|
||||
|
||||
Property *PropertyMap::Copy(void) const
|
||||
{
|
||||
PropertyMap *p= new PropertyMap();
|
||||
p->_lValueList = _lValueList;
|
||||
return p;
|
||||
}
|
||||
|
||||
void PropertyMap::Paste(const Property &from)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_lValueList = dynamic_cast<const PropertyMap&>(from)._lValueList;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
// PropertyBool
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <vector>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <Base/Uuid.h>
|
||||
#include "Property.h"
|
||||
#include "Material.h"
|
||||
|
||||
@@ -297,6 +298,61 @@ private:
|
||||
std::vector<long> _lValueList;
|
||||
};
|
||||
|
||||
/** implements a key/value list as property
|
||||
* The key ought to be ASCII the Value should be treated as UTF8 to be save.
|
||||
*/
|
||||
class AppExport PropertyMap: public Property
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor.
|
||||
* A more elaborate description of the constructor.
|
||||
*/
|
||||
PropertyMap();
|
||||
|
||||
/**
|
||||
* A destructor.
|
||||
* A more elaborate description of the destructor.
|
||||
*/
|
||||
~PropertyMap();
|
||||
|
||||
virtual int getSize(void) const;
|
||||
|
||||
/** Sets the property
|
||||
*/
|
||||
void setValue(void){};
|
||||
void setValue(const std::string& key,const std::string& value);
|
||||
void setValues(const std::map<std::string,std::string>&);
|
||||
|
||||
/// index operator
|
||||
const std::string& operator[] (const std::string& key) const ;
|
||||
|
||||
void set1Value (const std::string& key, const std::string& value){_lValueList.operator[] (key) = value;}
|
||||
|
||||
const std::map<std::string,std::string> &getValues(void) const{return _lValueList;}
|
||||
|
||||
//virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyStringListItem"; }
|
||||
|
||||
virtual PyObject *getPyObject(void);
|
||||
virtual void setPyObject(PyObject *);
|
||||
|
||||
virtual void Save (Base::Writer &writer) const;
|
||||
virtual void Restore(Base::XMLReader &reader);
|
||||
|
||||
virtual Property *Copy(void) const;
|
||||
virtual void Paste(const Property &from);
|
||||
|
||||
virtual unsigned int getMemSize (void) const;
|
||||
|
||||
|
||||
private:
|
||||
std::map<std::string,std::string> _lValueList;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Float properties
|
||||
* This is the father of all properties handling floats.
|
||||
@@ -489,6 +545,50 @@ private:
|
||||
std::string _cValue;
|
||||
};
|
||||
|
||||
/** UUID properties
|
||||
* This property handles unique identifieers
|
||||
*/
|
||||
class AppExport PropertyUUID: public Property
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A constructor.
|
||||
* A more elaborate description of the constructor.
|
||||
*/
|
||||
PropertyUUID(void);
|
||||
|
||||
/**
|
||||
* A destructor.
|
||||
* A more elaborate description of the destructor.
|
||||
*/
|
||||
virtual ~PropertyUUID();
|
||||
|
||||
|
||||
void setValue(const Base::Uuid &);
|
||||
void setValue(const char* sString);
|
||||
void setValue(const std::string &sString);
|
||||
const std::string& getValueStr(void) const;
|
||||
const Base::Uuid& getValue(void) const;
|
||||
|
||||
//virtual const char* getEditorName(void) const { return "Gui::PropertyEditor::PropertyStringItem"; }
|
||||
virtual PyObject *getPyObject(void);
|
||||
virtual void setPyObject(PyObject *);
|
||||
|
||||
virtual void Save (Base::Writer &writer) const;
|
||||
virtual void Restore(Base::XMLReader &reader);
|
||||
|
||||
virtual Property *Copy(void) const;
|
||||
virtual void Paste(const Property &from);
|
||||
virtual unsigned int getMemSize (void) const;
|
||||
|
||||
private:
|
||||
Base::Uuid _uuid;
|
||||
};
|
||||
|
||||
|
||||
/** Property handling with font names.
|
||||
*/
|
||||
class AppExport PropertyFont : public PropertyString
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
bool operator > (const TimeInfo &time) const;
|
||||
|
||||
static const char* currentDateTimeString();
|
||||
static std::string diffTime(const TimeInfo &timeStart,const TimeInfo &timeEnd );
|
||||
static std::string diffTime(const TimeInfo &timeStart,const TimeInfo &timeEnd = TimeInfo());
|
||||
static float diffTimeF(const TimeInfo &timeStart,const TimeInfo &timeEnd );
|
||||
bool isNull() const;
|
||||
static TimeInfo null();
|
||||
|
||||
@@ -24,17 +24,14 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# ifdef FC_OS_WIN32
|
||||
# include <Rpc.h>
|
||||
# else
|
||||
# include <QUuid>
|
||||
# endif
|
||||
# include <QUuid>
|
||||
#endif
|
||||
|
||||
/// Here the FreeCAD includes sorted by Base,App,Gui......
|
||||
#include "Uuid.h"
|
||||
#include "Exception.h"
|
||||
#include "Interpreter.h"
|
||||
#include <stdexcept>
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
|
||||
@@ -50,7 +47,7 @@ using namespace Base;
|
||||
*/
|
||||
Uuid::Uuid()
|
||||
{
|
||||
UuidStr = CreateUuid();
|
||||
_uuid = createUuid();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,46 +62,36 @@ Uuid::~Uuid()
|
||||
//**************************************************************************
|
||||
// Get the UUID
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
std::string Uuid::CreateUuid(void)
|
||||
std::string Uuid::createUuid(void)
|
||||
{
|
||||
#ifdef FC_OS_WIN32
|
||||
RPC_STATUS rstat;
|
||||
UUID uuid;
|
||||
unsigned char *uuidStr;
|
||||
|
||||
rstat = UuidCreate(&uuid);
|
||||
if (rstat != RPC_S_OK) throw Base::Exception("Cannot convert a unique Windows UUID to a string");
|
||||
|
||||
rstat = UuidToString(&uuid, &uuidStr);
|
||||
if (rstat != RPC_S_OK) throw Base::Exception("Cannot convert a unique Windows UUID to a string");
|
||||
|
||||
std::string Uuid((char *)uuidStr);
|
||||
|
||||
/* convert it from rcp memory to our own */
|
||||
//container = nssUTF8_Duplicate(uuidStr, NULL);
|
||||
RpcStringFree(&uuidStr);
|
||||
#elif 1
|
||||
std::string Uuid;
|
||||
QString uuid = QUuid::createUuid().toString();
|
||||
uuid = uuid.mid(1);
|
||||
uuid.chop(1);
|
||||
Uuid = (const char*)uuid.toAscii();
|
||||
#else
|
||||
// use Python's implemententation
|
||||
std::string Uuid;
|
||||
PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Module module(PyImport_ImportModule("uuid"),true);
|
||||
Py::Callable method(module.getAttr("uuid4"));
|
||||
Py::Tuple arg;
|
||||
Py::Object guid = method.apply(arg);
|
||||
Uuid = guid.as_string();
|
||||
}
|
||||
catch (Py::Exception& e) {
|
||||
e.clear();
|
||||
throw Base::Exception("Creation of UUID failed");
|
||||
}
|
||||
#endif
|
||||
return Uuid;
|
||||
}
|
||||
|
||||
void Uuid::setValue(const char* sString)
|
||||
{
|
||||
if (sString) {
|
||||
QUuid uuid(QString::fromAscii(sString));
|
||||
if (uuid.isNull())
|
||||
throw std::runtime_error("invalid uuid");
|
||||
// remove curly braces
|
||||
QString id = uuid.toString();
|
||||
id = id.mid(1);
|
||||
id.chop(1);
|
||||
_uuid = (const char*)id.toAscii();
|
||||
}
|
||||
}
|
||||
|
||||
void Uuid::setValue(const std::string &sString)
|
||||
{
|
||||
setValue(sString.c_str());
|
||||
}
|
||||
|
||||
const std::string& Uuid::getValue(void) const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
namespace Base
|
||||
{
|
||||
|
||||
|
||||
/** Creates a Uuid
|
||||
* \author Jürgen Riegel
|
||||
*/
|
||||
@@ -43,10 +42,13 @@ public:
|
||||
/// Destruction
|
||||
virtual ~Uuid();
|
||||
|
||||
/// Uuid
|
||||
std::string UuidStr;
|
||||
void setValue(const char* sString);
|
||||
void setValue(const std::string &sString);
|
||||
const std::string& getValue(void) const;
|
||||
static std::string createUuid(void);
|
||||
|
||||
static std::string CreateUuid(void);
|
||||
private:
|
||||
std::string _uuid;
|
||||
};
|
||||
|
||||
} //namespace Base
|
||||
|
||||
@@ -93,6 +93,8 @@
|
||||
#include "ViewProviderVRMLObject.h"
|
||||
#include "ViewProviderAnnotation.h"
|
||||
#include "ViewProviderMeasureDistance.h"
|
||||
#include "ViewProviderPlacement.h"
|
||||
#include "ViewProviderPlane.h"
|
||||
|
||||
#include "Language/Translator.h"
|
||||
#include "TaskView/TaskDialogPython.h"
|
||||
@@ -1443,6 +1445,8 @@ void Application::initTypes(void)
|
||||
Gui::ViewProviderMeasureDistance ::init();
|
||||
Gui::ViewProviderPythonFeature ::init();
|
||||
Gui::ViewProviderPythonGeometry ::init();
|
||||
Gui::ViewProviderPlacement ::init();
|
||||
Gui::ViewProviderPlane ::init();
|
||||
|
||||
// Workbench
|
||||
Gui::Workbench ::init();
|
||||
@@ -1690,6 +1694,9 @@ void Application::runApplication(void)
|
||||
SetASCII("AutoloadModule", start.c_str());
|
||||
}
|
||||
|
||||
// Call this before showing the main window because otherwise:
|
||||
// 1. it shows a white window for a few seconds which doesn't look nice
|
||||
// 2. the layout of the toolbars is completely broken
|
||||
app.activateWorkbench(start.c_str());
|
||||
|
||||
// show the main window
|
||||
@@ -1706,6 +1713,7 @@ void Application::runApplication(void)
|
||||
SoQt::setFatalErrorHandler( messageHandlerSoQt, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
Instance->d->startingUp = false;
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -497,7 +497,17 @@ PyObject* Application::sActivateWorkbenchHandler(PyObject * /*self*/, PyObject *
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Instance->activateWorkbench(psKey);
|
||||
try {
|
||||
Instance->activateWorkbench(psKey);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
PyErr_SetString(PyExc_Exception, e.what());
|
||||
return 0;
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_Exception, "Unknown C++ exception raised in activateWorkbench");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
@@ -164,6 +164,7 @@ set(Gui_MOC_HDRS
|
||||
Transform.h
|
||||
Tree.h
|
||||
TreeView.h
|
||||
ProjectView.h
|
||||
View3DInventor.h
|
||||
WidgetFactory.h
|
||||
Widgets.h
|
||||
@@ -424,6 +425,7 @@ SET(Dock_Windows_CPP_SRCS
|
||||
ToolBox.cpp
|
||||
Tree.cpp
|
||||
TreeView.cpp
|
||||
ProjectView.cpp
|
||||
)
|
||||
SET(Dock_Windows_HPP_SRCS
|
||||
CombiView.h
|
||||
@@ -436,6 +438,7 @@ SET(Dock_Windows_HPP_SRCS
|
||||
ToolBox.h
|
||||
Tree.h
|
||||
TreeView.h
|
||||
ProjectView.h
|
||||
)
|
||||
SET(Dock_Windows_SRCS
|
||||
${Dock_Windows_CPP_SRCS}
|
||||
@@ -617,6 +620,8 @@ SET(Viewprovider_CPP_SRCS
|
||||
ViewProviderPythonFeature.cpp
|
||||
ViewProviderVRMLObject.cpp
|
||||
ViewProviderBuilder.cpp
|
||||
ViewProviderPlacement.cpp
|
||||
ViewProviderPlane.cpp
|
||||
)
|
||||
SET(Viewprovider_SRCS
|
||||
${Viewprovider_CPP_SRCS}
|
||||
@@ -632,12 +637,15 @@ SET(Viewprovider_SRCS
|
||||
ViewProviderPythonFeature.h
|
||||
ViewProviderVRMLObject.h
|
||||
ViewProviderBuilder.h
|
||||
ViewProviderPlacement.h
|
||||
ViewProviderPlane.h
|
||||
)
|
||||
SOURCE_GROUP("View3D\\Viewprovider" FILES ${Viewprovider_SRCS})
|
||||
|
||||
# The Inventor sources
|
||||
SET(Inventor_CPP_SRCS
|
||||
Inventor/SoDrawingGrid.cpp
|
||||
Inventor/SoAutoZoomTranslation.cpp
|
||||
SoFCBackgroundGradient.cpp
|
||||
SoFCBoundingBox.cpp
|
||||
SoFCColorBar.cpp
|
||||
@@ -658,6 +666,7 @@ SET(Inventor_CPP_SRCS
|
||||
SET(Inventor_SRCS
|
||||
${Inventor_CPP_SRCS}
|
||||
Inventor/SoDrawingGrid.h
|
||||
Inventor/SoAutoZoomTranslation.h
|
||||
SoFCBackgroundGradient.h
|
||||
SoFCBoundingBox.h
|
||||
SoFCColorBar.h
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "BitmapFactory.h"
|
||||
#include "iisTaskPanel/include/iisTaskPanel"
|
||||
#include "PropertyView.h"
|
||||
#include "ProjectView.h"
|
||||
#include "Application.h"
|
||||
#include "Document.h"
|
||||
#include "Tree.h"
|
||||
@@ -71,12 +72,15 @@ CombiView::CombiView(Gui::Document* pcDocument, QWidget *parent)
|
||||
// property view
|
||||
prop = new PropertyView(this);
|
||||
splitter->addWidget(prop);
|
||||
|
||||
tabs->addTab(splitter,trUtf8("Project"));
|
||||
tabs->addTab(splitter,trUtf8("Model"));
|
||||
|
||||
// task panel
|
||||
taskPanel = new Gui::TaskView::TaskView(this);
|
||||
tabs->addTab(taskPanel, trUtf8("Tasks"));
|
||||
|
||||
// task panel
|
||||
projectView = new Gui::ProjectWidget(this);
|
||||
tabs->addTab(projectView, trUtf8("Project"));
|
||||
}
|
||||
|
||||
CombiView::~CombiView()
|
||||
@@ -119,8 +123,9 @@ void CombiView::showTaskView()
|
||||
void CombiView::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
tabs->setTabText(0, trUtf8("Project"));
|
||||
tabs->setTabText(0, trUtf8("Model"));
|
||||
tabs->setTabText(1, trUtf8("Tasks"));
|
||||
tabs->setTabText(2, trUtf8("Project"));
|
||||
}
|
||||
|
||||
DockWindow::changeEvent(e);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace App {
|
||||
namespace Gui {
|
||||
class TreeWidget;
|
||||
class PropertyView;
|
||||
|
||||
class ProjectWidget;
|
||||
namespace PropertyEditor {
|
||||
class EditableListView;
|
||||
class EditableItem;
|
||||
@@ -98,6 +98,7 @@ private:
|
||||
Gui::PropertyView * prop;
|
||||
QTreeView * tree;
|
||||
Gui::TaskView::TaskView * taskPanel;
|
||||
Gui::ProjectWidget * projectView;
|
||||
};
|
||||
|
||||
} // namespace DockWnd
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#include "Control.h"
|
||||
#include "View3DInventor.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "WorkbenchManager.h"
|
||||
#include "Workbench.h"
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
@@ -119,6 +121,9 @@ using namespace Gui::DockWnd;
|
||||
* @see Gui::Command, Gui::CommandManager
|
||||
*/
|
||||
|
||||
// list of modules already loaded by a command (not issue again for macro cleanness)
|
||||
std::set<std::string> alreadyLoadedModule;
|
||||
|
||||
CommandBase::CommandBase( const char* sMenu, const char* sToolTip, const char* sWhat,
|
||||
const char* sStatus, const char* sPixmap, const char* sAcc)
|
||||
: sMenuText(sMenu), sToolTipText(sToolTip), sWhatsThis(sWhat?sWhat:sToolTip),
|
||||
@@ -443,6 +448,35 @@ void Command::runCommand(DoCmd_Type eType,const char* sCmd)
|
||||
Base::Interpreter().runString(sCmd);
|
||||
}
|
||||
|
||||
void Command::addModule(DoCmd_Type eType,const char* sModuleName)
|
||||
{
|
||||
if(alreadyLoadedModule.find(sModuleName) == alreadyLoadedModule.end()) {
|
||||
std::string sCmd("import ");
|
||||
sCmd += sModuleName;
|
||||
if (eType == Gui)
|
||||
Gui::Application::Instance->macroManager()->addLine(MacroManager::Gui,sCmd.c_str());
|
||||
else
|
||||
Gui::Application::Instance->macroManager()->addLine(MacroManager::App,sCmd.c_str());
|
||||
Base::Interpreter().runString(sCmd.c_str());
|
||||
alreadyLoadedModule.insert(sModuleName);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Command::assureWorkbench(const char * sName)
|
||||
{
|
||||
// check if the WB is already open?
|
||||
std::string actName = WorkbenchManager::instance()->active()->name();
|
||||
// if yes, do nothing
|
||||
if(actName == sName)
|
||||
return actName;
|
||||
|
||||
// else - switch to new WB
|
||||
doCommand(Gui,"Gui.activateWorkbench('%s')",sName);
|
||||
|
||||
return actName;
|
||||
|
||||
}
|
||||
|
||||
void Command::copyVisual(const char* to, const char* attr, const char* from)
|
||||
{
|
||||
doCommand(Gui,"Gui.ActiveDocument.%s.%s=Gui.ActiveDocument.%s.%s", to, attr, from, attr);
|
||||
|
||||
@@ -237,6 +237,11 @@ public:
|
||||
/// Run a App level Action
|
||||
static void doCommand(DoCmd_Type eType,const char* sCmd,...);
|
||||
static void runCommand(DoCmd_Type eType,const char* sCmd);
|
||||
/// import an external (or own) module only once
|
||||
static void addModule(DoCmd_Type eType,const char* sModuleName);
|
||||
/// assures the switch to a certain workbench, if already in the workbench, does nothing.
|
||||
static std::string assureWorkbench(const char * sName);
|
||||
|
||||
static void copyVisual(const char* to, const char* attr, const char* from);
|
||||
static void copyVisual(const char* to, const char* attr_to, const char* from, const char* attr_from);
|
||||
/// Get Python tuple from object and sub-elements
|
||||
|
||||
@@ -81,6 +81,16 @@ void ControlSingleton::showTaskView()
|
||||
_taskPanel->raise();
|
||||
}
|
||||
|
||||
void ControlSingleton::showModelView()
|
||||
{
|
||||
Gui::DockWnd::CombiView* pcCombiView = qobject_cast<Gui::DockWnd::CombiView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
if (pcCombiView)
|
||||
pcCombiView->showTreeView();
|
||||
else if (_taskPanel)
|
||||
_taskPanel->raise();
|
||||
}
|
||||
|
||||
void ControlSingleton::showDialog(Gui::TaskView::TaskDialog *dlg)
|
||||
{
|
||||
// only one dialog at a time
|
||||
|
||||
@@ -64,12 +64,15 @@ public:
|
||||
/// This method start an Task dialog in the TaskView
|
||||
void showDialog(Gui::TaskView::TaskDialog *dlg);
|
||||
Gui::TaskView::TaskDialog* activeDialog() const;
|
||||
//void closeDialog();
|
||||
//@}
|
||||
|
||||
/** @name task view handling
|
||||
*/
|
||||
//@{
|
||||
Gui::TaskView::TaskView* taskPanel() const;
|
||||
/// reisin the model view
|
||||
void showModelView();
|
||||
//@}
|
||||
|
||||
bool isAllowedAlterDocument(void) const;
|
||||
@@ -78,6 +81,7 @@ public:
|
||||
|
||||
public Q_SLOTS:
|
||||
void closeDialog();
|
||||
/// reises the task view pane
|
||||
void showTaskView();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
# include <qstatusbar.h>
|
||||
# include <boost/signals.hpp>
|
||||
# include <boost/bind.hpp>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
@@ -188,6 +189,10 @@ bool Document::setEdit(Gui::ViewProvider* p, int ModNum)
|
||||
{
|
||||
if (d->_pcInEdit)
|
||||
resetEdit();
|
||||
// is it really a ViewProvider of this document?
|
||||
if (d->_ViewProviderMap.find(dynamic_cast<ViewProviderDocumentObject*>(p)->getObject()) == d->_ViewProviderMap.end())
|
||||
return false;
|
||||
|
||||
View3DInventor *activeView = dynamic_cast<View3DInventor *>(getActiveView());
|
||||
if (activeView && activeView->getViewer()->setEditingViewProvider(p,ModNum)) {
|
||||
d->_pcInEdit = p;
|
||||
@@ -388,6 +393,7 @@ void Document::slotNewObject(const App::DocumentObject& Obj)
|
||||
Base::Console().Error("App::Document::_RecomputeFeature(): Unknown exception in Feature \"%s\" thrown\n",Obj.getNameInDocument());
|
||||
}
|
||||
#endif
|
||||
|
||||
std::list<Gui::BaseView*>::iterator vIt;
|
||||
// cycling to all views of the document
|
||||
for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) {
|
||||
@@ -450,6 +456,36 @@ void Document::slotChangedObject(const App::DocumentObject& Obj, const App::Prop
|
||||
Base::Console().Error("Cannot update representation for '%s'.\n", Obj.getNameInDocument());
|
||||
}
|
||||
|
||||
// check for children
|
||||
if(viewProvider->getChildRoot()) {
|
||||
std::vector<App::DocumentObject*> children = viewProvider->claimChildren3D();
|
||||
SoGroup* childGroup = viewProvider->getChildRoot();
|
||||
|
||||
// size not the same -> build up the list new
|
||||
if(childGroup->getNumChildren() != children.size()){
|
||||
|
||||
childGroup->removeAllChildren();
|
||||
|
||||
for(std::vector<App::DocumentObject*>::iterator it=children.begin();it!=children.end();++it){
|
||||
ViewProvider* ChildViewProvider = getViewProvider(*it);
|
||||
if(ChildViewProvider) {
|
||||
SoSeparator* childRootNode = ChildViewProvider->getRoot();
|
||||
childGroup->addChild(childRootNode);
|
||||
|
||||
// cycling to all views of the document to remove the viewprovider from the viewer itself
|
||||
for (std::list<Gui::BaseView*>::iterator vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) {
|
||||
View3DInventor *activeView = dynamic_cast<View3DInventor *>(*vIt);
|
||||
if (activeView && viewProvider) {
|
||||
if (d->_pcInEdit == ChildViewProvider)
|
||||
resetEdit();
|
||||
activeView->getViewer()->removeViewProvider(ChildViewProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
|
||||
signalChangedObject(static_cast<ViewProviderDocumentObject&>(*viewProvider), Prop);
|
||||
}
|
||||
@@ -489,6 +525,26 @@ bool Document::isModified() const
|
||||
return d->_isModified;
|
||||
}
|
||||
|
||||
|
||||
ViewProvider* Document::getViewProviderByPathFromTail(SoPath * path) const
|
||||
{
|
||||
// Make sure I'm the lowest LocHL in the pick path!
|
||||
for (int i = 0; i < path->getLength(); i++) {
|
||||
SoNode *node = path->getNodeFromTail(i);
|
||||
if (node->isOfType(SoSeparator::getClassTypeId())) {
|
||||
std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator it = d->_ViewProviderMap.begin();
|
||||
for(;it!= d->_ViewProviderMap.end();++it)
|
||||
if (node == it->second->getRoot())
|
||||
return it->second;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
App::Document* Document::getDocument(void) const
|
||||
{
|
||||
return d->_pcDocument;
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
#include <Base/Persistence.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
#include "Tree.h"
|
||||
|
||||
class SoPath;
|
||||
|
||||
namespace Base
|
||||
{
|
||||
class Matrix4D;
|
||||
@@ -79,10 +83,10 @@ public:
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&)> signalNewObject;
|
||||
/// signal on deleted Object
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&)> signalDeletedObject;
|
||||
/// signal on changed Object, the 2nd argument is the changed property
|
||||
/// of the referenced document object, not of the view provider
|
||||
/** signal on changed Object, the 2nd argument is the changed property
|
||||
of the referenced document object, not of the view provider */
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&,
|
||||
const App::Property&)> signalChangedObject;
|
||||
const App::Property&)> signalChangedObject;
|
||||
/// signal on renamed Object
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&)> signalRenamedObject;
|
||||
/// signal on activated Object
|
||||
@@ -91,6 +95,14 @@ public:
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&)> signalInEdit;
|
||||
/// signal on leaving edit mode
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&)> signalResetEdit;
|
||||
/// signal on changed Object, the 2nd argument is the highlite mode to use
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&,
|
||||
const Gui::HighlightMode&,
|
||||
bool)> signalHighlightObject;
|
||||
/// signal on changed Object, the 2nd argument is the highlite mode to use
|
||||
mutable boost::signal<void (const Gui::ViewProviderDocumentObject&,
|
||||
const Gui::TreeItemMode&)> signalExpandObject;
|
||||
|
||||
//@}
|
||||
|
||||
/** @name I/O of the document */
|
||||
@@ -134,7 +146,9 @@ public:
|
||||
/// Attach a view (get called by the MDIView constructor)
|
||||
void attachView(Gui::BaseView* pcView, bool bPassiv=false);
|
||||
/// Detach a view (get called by the MDIView destructor)
|
||||
void detachView(Gui::BaseView* pcView, bool bPassiv=false);
|
||||
void detachView(Gui::BaseView* pcView, bool bPassiv=false);
|
||||
/// helper for selection
|
||||
ViewProvider* getViewProviderByPathFromTail(SoPath * path) const;
|
||||
/// call update on all attached views
|
||||
void onUpdate(void);
|
||||
/// call relabel to all attached views
|
||||
|
||||
@@ -68,38 +68,43 @@
|
||||
<UserDocu>deprecated -- use ActiveView</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="mdiViewsOfType" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return a list if mdi views of a given type</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="sendMsgToViews">
|
||||
<Documentation>
|
||||
<UserDocu>Send a message to all views of the document</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="mergeProject">
|
||||
<Documentation>
|
||||
<UserDocu>Merges this document with another project file</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="ActiveObject" ReadOnly="false">
|
||||
<Methode Name="mdiViewsOfType" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return a list if mdi views of a given type</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="sendMsgToViews">
|
||||
<Documentation>
|
||||
<UserDocu>Send a message to all views of the document</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="mergeProject">
|
||||
<Documentation>
|
||||
<UserDocu>Merges this document with another project file</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="toggleTreeItem">
|
||||
<Documentation>
|
||||
<UserDocu>toggleTreeItem(DocObject,int=0) - change TreeItem of a document object 0:Toggle,1:Collaps,2:Expand</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="ActiveObject" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>The active object of the document</UserDocu>
|
||||
<UserDocu>The active object of the document</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ActiveObject" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="ActiveView" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>The active view of the document</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ActiveView" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Document" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The related App document to this Gui document</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Document" Type="Object" />
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
<Attribute Name="ActiveView" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>The active view of the document</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ActiveView" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Document" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The related App document to this Gui document</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Document" Type="Object" />
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
// inclusion of the generated files (generated out of DocumentPy.xml)
|
||||
#include "DocumentPy.h"
|
||||
#include "DocumentPy.cpp"
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include "Tree.h"
|
||||
#include "ViewProviderDocumentObject.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
@@ -251,6 +255,30 @@ PyObject* DocumentPy::mergeProject(PyObject *args)
|
||||
} PY_CATCH;
|
||||
}
|
||||
|
||||
PyObject* DocumentPy::toggleTreeItem(PyObject *args)
|
||||
{
|
||||
PyObject *object=0;
|
||||
int mod = 0;
|
||||
if (PyArg_ParseTuple(args,"O!|i",&(App::DocumentObjectPy::Type), &object,&mod)) {
|
||||
App::DocumentObject* Object = static_cast<App::DocumentObjectPy*>(object)->getDocumentObjectPtr();
|
||||
// Should be set!
|
||||
assert(Object);
|
||||
|
||||
// get the gui document of the Assembly Item
|
||||
//ActiveAppDoc = Item->getDocument();
|
||||
//ActiveGuiDoc = Gui::Application::Instance->getDocument(getDocumentPtr());
|
||||
Gui::ViewProviderDocumentObject* ActiveVp = dynamic_cast<Gui::ViewProviderDocumentObject*> (getDocumentPtr()->getViewProvider(Object)) ;
|
||||
switch(mod) {
|
||||
case 0: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Toggle); break;
|
||||
case 1: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Collaps); break;
|
||||
case 2: getDocumentPtr()->signalExpandObject(*ActiveVp,Gui::Expand); break;
|
||||
}
|
||||
}
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
|
||||
Py::Object DocumentPy::getActiveObject(void) const
|
||||
{
|
||||
App::DocumentObject *object = getDocumentPtr()->getDocument()->getActiveObject();
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c)2011 Luke Parry *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <Inventor/actions/SoGLRenderAction.h>
|
||||
# include <Inventor/misc/SoState.h>
|
||||
# include <math.h>
|
||||
# include <cfloat>
|
||||
#endif
|
||||
|
||||
#include <Inventor/actions/SoGetMatrixAction.h>
|
||||
#include <Inventor/actions/SoGLRenderAction.h>
|
||||
#include <Inventor/elements/SoModelMatrixElement.h>
|
||||
#include <Inventor/elements/SoProjectionMatrixElement.h>
|
||||
#include <Inventor/elements/SoViewingMatrixElement.h>
|
||||
#include <Inventor/elements/SoViewVolumeElement.h>
|
||||
#include <Inventor/elements/SoViewportRegionElement.h>
|
||||
#include <Inventor/nodes/SoCamera.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
|
||||
|
||||
#include "SoAutoZoomTranslation.h"
|
||||
|
||||
// *************************************************************************
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
// ------------------------------------------------------
|
||||
|
||||
SO_NODE_SOURCE(SoAutoZoomTranslation);
|
||||
|
||||
void SoAutoZoomTranslation::initClass()
|
||||
{
|
||||
SO_NODE_INIT_CLASS(SoAutoZoomTranslation, SoTransformation, "AutoZoom");
|
||||
}
|
||||
|
||||
float SoAutoZoomTranslation::getScaleFactor()
|
||||
{
|
||||
// Dividing by 5 seems to work well
|
||||
|
||||
Gui::MDIView *mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
if (mdi && mdi->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
|
||||
Gui::View3DInventorViewer *viewer = static_cast<Gui::View3DInventor *>(mdi)->getViewer();
|
||||
float fScale = viewer->getCamera()->getViewVolume(viewer->getCamera()->aspectRatio.getValue()).getWorldToScreenScale(SbVec3f(0.f, 0.f, 0.f), 0.1f) / 5;
|
||||
if (fScale != this->scale) this->touch();
|
||||
this->scale = fScale;
|
||||
return this->scale;
|
||||
} else {
|
||||
return this->scale;
|
||||
}
|
||||
}
|
||||
|
||||
SoAutoZoomTranslation::SoAutoZoomTranslation()
|
||||
{
|
||||
SO_NODE_CONSTRUCTOR(SoAutoZoomTranslation);
|
||||
//SO_NODE_ADD_FIELD(abPos, (SbVec3f(0.f,0.f,0.f)));
|
||||
//this->scale = -1;
|
||||
}
|
||||
|
||||
void SoAutoZoomTranslation::GLRender(SoGLRenderAction * action)
|
||||
{
|
||||
//Base::Console().Log("Draw\n");
|
||||
SoAutoZoomTranslation::doAction((SoAction *)action);
|
||||
inherited::GLRender(action);
|
||||
}
|
||||
|
||||
// Doc in superclass.
|
||||
void SoAutoZoomTranslation::doAction(SoAction * action)
|
||||
{
|
||||
float sf = this->getScaleFactor();
|
||||
SoModelMatrixElement::scaleBy(action->getState(), this,
|
||||
SbVec3f(sf,sf,sf));
|
||||
//Base::Console().Log("Scale: %f\n",sf);
|
||||
}
|
||||
|
||||
// set the auto scale factor.
|
||||
//void SoAutoZoomTranslation::setAutoScale(void)
|
||||
//{
|
||||
// float sf = this->getScaleFactor();
|
||||
// //this->enableNotify ( false );
|
||||
// scaleFactor.setValue(SbVec3f(sf,sf,sf));
|
||||
// //this->enableNotify ( true );
|
||||
// //scaleFactor.setDirty (true);
|
||||
//
|
||||
//}
|
||||
|
||||
void SoAutoZoomTranslation::getMatrix(SoGetMatrixAction * action)
|
||||
{
|
||||
//Base::Console().Log("Matrix\n");
|
||||
float sf = this->getScaleFactor();
|
||||
|
||||
SbVec3f scalevec = SbVec3f(sf,sf,sf);
|
||||
SbMatrix m;
|
||||
|
||||
m.setScale(scalevec);
|
||||
action->getMatrix().multLeft(m);
|
||||
|
||||
m.setScale(SbVec3f(1.0f / scalevec[0], 1.0f / scalevec[1], 1.0f / scalevec[2]));
|
||||
action->getInverse().multRight(m);
|
||||
|
||||
}
|
||||
|
||||
void SoAutoZoomTranslation::callback(SoCallbackAction * action)
|
||||
{
|
||||
// Base::Console().Log("callback\n");
|
||||
SoAutoZoomTranslation::doAction((SoAction*)action);
|
||||
}
|
||||
|
||||
void SoAutoZoomTranslation::getBoundingBox(SoGetBoundingBoxAction * action)
|
||||
{
|
||||
//Base::Console().Log("getBoundingBox\n");
|
||||
SoAutoZoomTranslation::doAction((SoAction*)action);
|
||||
}
|
||||
|
||||
void SoAutoZoomTranslation::pick(SoPickAction * action)
|
||||
{
|
||||
//Base::Console().Log("pick\n");
|
||||
SoAutoZoomTranslation::doAction((SoAction*)action);
|
||||
}
|
||||
|
||||
// Doc in superclass.
|
||||
void SoAutoZoomTranslation::getPrimitiveCount(SoGetPrimitiveCountAction * action)
|
||||
{
|
||||
//Base::Console().Log("getPrimitiveCount\n");
|
||||
SoAutoZoomTranslation::doAction((SoAction*)action);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/***************************************************************************
|
||||
* (c) 2011 Luke Parry *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GUI_SOAUTOZOOMTRANSLATION_H
|
||||
#define GUI_SOAUTOZOOMTRANSLATION_H
|
||||
|
||||
#include <Inventor/nodes/SoTranslation.h>
|
||||
#include <Inventor/nodes/SoSubNode.h>
|
||||
#include <Inventor/nodes/SoTransformation.h>
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class GuiExport SoAutoZoomTranslation : public SoTransformation {
|
||||
typedef SoTransformation inherited;
|
||||
|
||||
SO_NODE_HEADER(SoAutoZoomTranslation);
|
||||
|
||||
public:
|
||||
static void initClass();
|
||||
SoAutoZoomTranslation();
|
||||
//SoSFVec3f abPos;
|
||||
float getScaleFactor();
|
||||
|
||||
protected:
|
||||
virtual ~SoAutoZoomTranslation() {};
|
||||
virtual void doAction(SoAction * action);
|
||||
virtual void getPrimitiveCount(SoGetPrimitiveCountAction * action);
|
||||
virtual void getMatrix(SoGetMatrixAction * action);
|
||||
virtual void GLRender(SoGLRenderAction *action);
|
||||
virtual void getBoundingBox(SoGetBoundingBoxAction * action);
|
||||
virtual void callback(SoCallbackAction * action);
|
||||
virtual void pick(SoPickAction * action);
|
||||
|
||||
private:
|
||||
float scale;
|
||||
//void setAutoScale(void);
|
||||
};
|
||||
|
||||
}
|
||||
#endif // GUI_SOAUTOZOOMTRANSLATION_H
|
||||
@@ -0,0 +1,75 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2012 Jürgen Riegel <[email protected]> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <boost/signals.hpp>
|
||||
# include <boost/bind.hpp>
|
||||
# include <QAction>
|
||||
# include <QActionGroup>
|
||||
# include <QApplication>
|
||||
# include <qcursor.h>
|
||||
# include <qlayout.h>
|
||||
# include <qstatusbar.h>
|
||||
# include <QContextMenuEvent>
|
||||
# include <QMenu>
|
||||
# include <QPixmap>
|
||||
# include <QTimer>
|
||||
#endif
|
||||
|
||||
#include <QDirModel>
|
||||
#include <Base/Console.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
#include "ProjectView.h"
|
||||
#include "Document.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "ViewProviderDocumentObject.h"
|
||||
#include "MenuManager.h"
|
||||
#include "Application.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
|
||||
|
||||
/* TRANSLATOR Gui::ProjectWidget */
|
||||
ProjectWidget::ProjectWidget(QWidget* parent)
|
||||
: QTreeView(parent)
|
||||
{
|
||||
fileModel = new QDirModel(this);
|
||||
fileModel->setSorting(QDir::DirsFirst | QDir::Type);
|
||||
setModel(fileModel);
|
||||
}
|
||||
|
||||
ProjectWidget::~ProjectWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "moc_ProjectView.cpp"
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2012 Jürgen Riegel <[email protected]> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_ProjectView_H
|
||||
#define GUI_ProjectView_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/Application.h>
|
||||
|
||||
#include <Gui/DockWindow.h>
|
||||
#include <Gui/Selection.h>
|
||||
class QDirModel;
|
||||
|
||||
namespace Gui {
|
||||
|
||||
|
||||
/** Tree view that allows drag & drop of document objects.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
class ProjectWidget : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ProjectWidget(QWidget* parent=0);
|
||||
~ProjectWidget();
|
||||
|
||||
private:
|
||||
QDirModel *fileModel;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // GUI_ProjectView_H
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
std::vector<std::vector<SelectionObject> > Result;
|
||||
|
||||
/// true if a valid filter is set
|
||||
bool isValid(void) const {return Ast;}
|
||||
bool isValid(void) const {return (bool) Ast;}
|
||||
|
||||
protected:
|
||||
std::string Filter;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "SoTextLabel.h"
|
||||
#include "SoNavigationDragger.h"
|
||||
#include "Inventor/SoDrawingGrid.h"
|
||||
#include "Inventor/SoAutoZoomTranslation.h"
|
||||
|
||||
#include "propertyeditor/PropertyItem.h"
|
||||
#include "NavigationStyle.h"
|
||||
@@ -97,6 +98,7 @@ void Gui::SoFCDB::init()
|
||||
SoAxisCrossKit ::initClass();
|
||||
SoRegPoint ::initClass();
|
||||
SoDrawingGrid ::initClass();
|
||||
SoAutoZoomTranslation ::initClass();
|
||||
|
||||
PropertyItem ::init();
|
||||
PropertySeparatorItem ::init();
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include <Base/Console.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
|
||||
#include "SoFCUnifiedSelection.h"
|
||||
@@ -288,7 +289,7 @@ void SoFCUnifiedSelection::doAction(SoAction *action)
|
||||
}
|
||||
else if (selaction->SelChange.Type == SelectionChanges::ClrSelection ||
|
||||
selaction->SelChange.Type == SelectionChanges::SetSelection) {
|
||||
std::vector<ViewProvider*> vps = this->viewer->getViewProvidersOfType
|
||||
std::vector<ViewProvider*> vps = this->pcDocument->getViewProvidersOfType
|
||||
(ViewProviderDocumentObject::getClassTypeId());
|
||||
for (std::vector<ViewProvider*>::iterator it = vps.begin(); it != vps.end(); ++it) {
|
||||
ViewProviderDocumentObject* vpd = static_cast<ViewProviderDocumentObject*>(*it);
|
||||
@@ -350,7 +351,7 @@ SoFCUnifiedSelection::handleEvent(SoHandleEventAction * action)
|
||||
ViewProvider *vp = 0;
|
||||
ViewProviderDocumentObject* vpd = 0;
|
||||
if (pPath && pPath->containsPath(action->getCurPath()))
|
||||
vp = viewer->getViewProviderByPathFromTail(pPath);
|
||||
vp = pcDocument->getViewProviderByPathFromTail(pPath);
|
||||
if (vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
|
||||
vpd = static_cast<ViewProviderDocumentObject*>(vp);
|
||||
|
||||
@@ -423,7 +424,7 @@ SoFCUnifiedSelection::handleEvent(SoHandleEventAction * action)
|
||||
ViewProvider *vp = 0;
|
||||
ViewProviderDocumentObject* vpd = 0;
|
||||
if (pPath && pPath->containsPath(action->getCurPath()))
|
||||
vp = viewer->getViewProviderByPathFromTail(pPath);
|
||||
vp = pcDocument->getViewProviderByPathFromTail(pPath);
|
||||
if (vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
|
||||
vpd = static_cast<ViewProviderDocumentObject*>(vp);
|
||||
if (vpd && vpd->useNewSelectionModel() && vpd->isSelectable()) {
|
||||
|
||||
@@ -48,6 +48,7 @@ class SoDetail;
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class Document;
|
||||
|
||||
/** Unified Selection node
|
||||
* This is the new selection node for the 3D Viewer which will
|
||||
@@ -95,6 +96,7 @@ protected:
|
||||
//virtual SbBool readInstance(SoInput * in, unsigned short flags);
|
||||
|
||||
View3DInventorViewer *viewer;
|
||||
Gui::Document *pcDocument;
|
||||
private:
|
||||
//static void turnoffcurrent(SoAction * action);
|
||||
//void setOverride(SoGLRenderAction * action);
|
||||
|
||||
@@ -573,6 +573,7 @@ void TreeWidget::slotActiveDocument(const Gui::Document& Doc)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TreeWidget::onTestStatus(void)
|
||||
{
|
||||
if (isVisible()) {
|
||||
@@ -758,6 +759,8 @@ DocumentItem::DocumentItem(const Gui::Document* doc, QTreeWidgetItem * parent)
|
||||
doc->signalActivatedObject.connect(boost::bind(&DocumentItem::slotActiveObject, this, _1));
|
||||
doc->signalInEdit.connect(boost::bind(&DocumentItem::slotInEdit, this, _1));
|
||||
doc->signalResetEdit.connect(boost::bind(&DocumentItem::slotResetEdit, this, _1));
|
||||
doc->signalHighlightObject.connect(boost::bind(&DocumentItem::slotHighlightObject, this, _1,_2,_3));
|
||||
doc->signalExpandObject.connect(boost::bind(&DocumentItem::slotExpandObject, this, _1,_2));
|
||||
|
||||
setFlags(Qt::ItemIsEnabled/*|Qt::ItemIsEditable*/);
|
||||
}
|
||||
@@ -826,7 +829,6 @@ void DocumentItem::slotChangeObject(const Gui::ViewProviderDocumentObject& view)
|
||||
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(objectName);
|
||||
if (it != ObjectMap.end()) {
|
||||
// use new grouping style
|
||||
# if 1
|
||||
std::set<QTreeWidgetItem*> children;
|
||||
std::vector<App::DocumentObject*> group = view.claimChildren();
|
||||
for (std::vector<App::DocumentObject*>::iterator jt = group.begin(); jt != group.end(); ++jt) {
|
||||
@@ -866,49 +868,8 @@ void DocumentItem::slotChangeObject(const Gui::ViewProviderDocumentObject& view)
|
||||
this->addChild(child);
|
||||
}
|
||||
}
|
||||
//this->treeWidget()->expandItem(it->second);
|
||||
// old grouping style here
|
||||
# else
|
||||
this->treeWidget()->expandItem(it->second);
|
||||
|
||||
// is the object a group?
|
||||
if (obj->getTypeId().isDerivedFrom(App::DocumentObjectGroup::getClassTypeId())) {
|
||||
std::set<QTreeWidgetItem*> children;
|
||||
std::vector<App::DocumentObject*> group = static_cast<App::DocumentObjectGroup*>(obj)->Group.getValues();
|
||||
for (std::vector<App::DocumentObject*>::iterator jt = group.begin(); jt != group.end(); ++jt) {
|
||||
const char* internalName = (*jt)->getNameInDocument();
|
||||
if (internalName) {
|
||||
std::map<std::string, DocumentObjectItem*>::iterator kt = ObjectMap.find(internalName);
|
||||
if (kt != ObjectMap.end()) {
|
||||
children.insert(kt->second);
|
||||
QTreeWidgetItem* parent = kt->second->parent();
|
||||
if (parent && parent != it->second) {
|
||||
int index = parent->indexOfChild(kt->second);
|
||||
parent->takeChild(index);
|
||||
it->second->addChild(kt->second);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("DocumentItem::slotChangedObject: Cannot reparent unknown object.\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("DocumentItem::slotChangedObject: Group references unknown object.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// move all children which are not part of the group anymore to this item
|
||||
int count = it->second->childCount();
|
||||
for (int i=0; i < count; i++) {
|
||||
QTreeWidgetItem* child = it->second->child(i);
|
||||
if (children.find(child) == children.end()) {
|
||||
it->second->takeChild(i);
|
||||
this->addChild(child);
|
||||
}
|
||||
}
|
||||
this->treeWidget()->expandItem(it->second);
|
||||
}
|
||||
// end of grouping style switch
|
||||
# endif
|
||||
// set the text label
|
||||
std::string displayName = obj->Label.getValue();
|
||||
it->second->setText(0, QString::fromUtf8(displayName.c_str()));
|
||||
@@ -948,11 +909,84 @@ void DocumentItem::slotActiveObject(const Gui::ViewProviderDocumentObject& obj)
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentItem::slotHighlightObject (const Gui::ViewProviderDocumentObject& obj,const Gui::HighlightMode& high,bool set)
|
||||
{
|
||||
|
||||
std::string objectName = obj.getObject()->getNameInDocument();
|
||||
std::map<std::string, DocumentObjectItem*>::iterator jt = ObjectMap.find(objectName);
|
||||
if (jt == ObjectMap.end())
|
||||
return; // signal is emitted before the item gets created
|
||||
|
||||
QFont f = jt->second->font(0);
|
||||
switch (high) {
|
||||
case Gui::Bold: f.setBold(set); break;
|
||||
case Gui::Italic: f.setItalic(set); break;
|
||||
case Gui::Underlined: f.setUnderline(set); break;
|
||||
case Gui::Overlined: f.setOverline(set); break;
|
||||
case Gui::Blue:
|
||||
if(set)
|
||||
jt->second->setBackgroundColor(0,QColor(200,200,255));
|
||||
else
|
||||
jt->second->setData(0, Qt::BackgroundColorRole,QVariant());
|
||||
break;
|
||||
default:
|
||||
// not defined enum
|
||||
assert(0);
|
||||
}
|
||||
jt->second->setFont(0,f);
|
||||
|
||||
}
|
||||
|
||||
void DocumentItem::slotExpandObject (const Gui::ViewProviderDocumentObject& obj,const Gui::TreeItemMode& mode)
|
||||
{
|
||||
|
||||
std::string objectName = obj.getObject()->getNameInDocument();
|
||||
std::map<std::string, DocumentObjectItem*>::iterator jt = ObjectMap.find(objectName);
|
||||
if (jt == ObjectMap.end())
|
||||
return; // signal is emitted before the item gets created
|
||||
|
||||
switch (mode) {
|
||||
case Gui::Expand:
|
||||
jt->second->setExpanded(true);
|
||||
break;
|
||||
case Gui::Collaps:
|
||||
jt->second->setExpanded(false);
|
||||
break;
|
||||
case Gui::Toggle:
|
||||
if(jt->second->isExpanded())
|
||||
jt->second->setExpanded(false);
|
||||
else
|
||||
jt->second->setExpanded(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
// not defined enum
|
||||
assert(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const Gui::Document* DocumentItem::document() const
|
||||
{
|
||||
return this->pDocument;
|
||||
}
|
||||
|
||||
//void DocumentItem::markItem(const App::DocumentObject* Obj,bool mark)
|
||||
//{
|
||||
// // never call without Object!
|
||||
// assert(Obj);
|
||||
//
|
||||
//
|
||||
// std::map<std::string,DocumentObjectItem*>::iterator pos;
|
||||
// pos = ObjectMap.find(Obj->getNameInDocument());
|
||||
// if (pos != ObjectMap.end()) {
|
||||
// QFont f = pos->second->font(0);
|
||||
// f.setUnderline(mark);
|
||||
// pos->second->setFont(0,f);
|
||||
// }
|
||||
//}
|
||||
|
||||
void DocumentItem::testStatus(void)
|
||||
{
|
||||
for (std::map<std::string,DocumentObjectItem*>::iterator pos = ObjectMap.begin();pos!=ObjectMap.end();++pos) {
|
||||
|
||||
@@ -32,12 +32,28 @@
|
||||
#include <Gui/DockWindow.h>
|
||||
#include <Gui/Selection.h>
|
||||
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class ViewProviderDocumentObject;
|
||||
class DocumentObjectItem;
|
||||
class DocumentItem;
|
||||
|
||||
/// highlight modes for the tree items
|
||||
enum HighlightMode { Underlined,
|
||||
Italic ,
|
||||
Overlined ,
|
||||
Bold ,
|
||||
Blue
|
||||
};
|
||||
|
||||
/// highlight modes for the tree items
|
||||
enum TreeItemMode { Expand,
|
||||
Collaps,
|
||||
Toggle
|
||||
};
|
||||
|
||||
|
||||
/** Tree view that allows drag & drop of document objects.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
@@ -55,6 +71,8 @@ public:
|
||||
static const int DocumentType;
|
||||
static const int ObjectType;
|
||||
|
||||
void markItem(const App::DocumentObject* Obj,bool mark);
|
||||
|
||||
protected:
|
||||
/// Observer message from the Selection
|
||||
void onSelectionChanged(const SelectionChanges& msg);
|
||||
@@ -130,12 +148,14 @@ protected:
|
||||
/** Removes a view provider from the document item.
|
||||
* If this view provider is not added nothing happens.
|
||||
*/
|
||||
void slotDeleteObject(const Gui::ViewProviderDocumentObject&);
|
||||
void slotChangeObject(const Gui::ViewProviderDocumentObject&);
|
||||
void slotRenameObject(const Gui::ViewProviderDocumentObject&);
|
||||
void slotActiveObject(const Gui::ViewProviderDocumentObject&);
|
||||
void slotInEdit (const Gui::ViewProviderDocumentObject&);
|
||||
void slotResetEdit (const Gui::ViewProviderDocumentObject&);
|
||||
void slotDeleteObject (const Gui::ViewProviderDocumentObject&);
|
||||
void slotChangeObject (const Gui::ViewProviderDocumentObject&);
|
||||
void slotRenameObject (const Gui::ViewProviderDocumentObject&);
|
||||
void slotActiveObject (const Gui::ViewProviderDocumentObject&);
|
||||
void slotInEdit (const Gui::ViewProviderDocumentObject&);
|
||||
void slotResetEdit (const Gui::ViewProviderDocumentObject&);
|
||||
void slotHighlightObject (const Gui::ViewProviderDocumentObject&,const Gui::HighlightMode&,bool);
|
||||
void slotExpandObject (const Gui::ViewProviderDocumentObject&,const Gui::TreeItemMode&);
|
||||
|
||||
private:
|
||||
const Gui::Document* pDocument;
|
||||
|
||||
@@ -113,6 +113,7 @@ View3DInventor::View3DInventor(Gui::Document* pcDocument, QWidget* parent, Qt::W
|
||||
// create the inventor widget and set the defaults
|
||||
#if !defined (NO_USE_QT_MDI_AREA)
|
||||
_viewer = new View3DInventorViewer(0);
|
||||
_viewer->setDocument(this->_pcDocument);
|
||||
stack->addWidget(_viewer->getWidget());
|
||||
setCentralWidget(stack);
|
||||
#else
|
||||
|
||||
@@ -215,7 +215,7 @@ View3DInventorViewer::View3DInventorViewer (QWidget *parent, const char *name,
|
||||
// NOTE: For every mouse click event the SoFCUnifiedSelection searches for the picked
|
||||
// point which causes a certain slow-down because for all objects the primitives
|
||||
// must be created. Using an SoSeparator avoids this drawback.
|
||||
Gui::SoFCUnifiedSelection* selectionRoot = new Gui::SoFCUnifiedSelection();
|
||||
selectionRoot = new Gui::SoFCUnifiedSelection();
|
||||
selectionRoot->applySettings();
|
||||
selectionRoot->viewer = this;
|
||||
#endif
|
||||
@@ -292,6 +292,12 @@ View3DInventorViewer::~View3DInventorViewer()
|
||||
Gui::Selection().Detach(this);
|
||||
}
|
||||
|
||||
void View3DInventorViewer::setDocument(Gui::Document *pcDocument)
|
||||
{
|
||||
// write the document the viewer belongs to to the selection node
|
||||
selectionRoot->pcDocument = pcDocument;
|
||||
}
|
||||
|
||||
void View3DInventorViewer::initialize()
|
||||
{
|
||||
navigation = new CADNavigationStyle();
|
||||
@@ -355,10 +361,9 @@ void View3DInventorViewer::removeViewProvider(ViewProvider* pcProvider)
|
||||
|
||||
}
|
||||
|
||||
|
||||
SbBool View3DInventorViewer::setEditingViewProvider(Gui::ViewProvider* p, int ModNum)
|
||||
{
|
||||
if (_ViewProviderSet.find(p) == _ViewProviderSet.end())
|
||||
return false;
|
||||
if (this->editViewProvider)
|
||||
return false; // only one view provider is editable at a time
|
||||
bool ok = p->startEditing(ModNum);
|
||||
|
||||
@@ -52,6 +52,8 @@ class ViewProvider;
|
||||
class SoFCBackgroundGradient;
|
||||
class NavigationStyle;
|
||||
class SoFCUnifiedSelection;
|
||||
class Document;
|
||||
class SoFCUnifiedSelection;
|
||||
|
||||
/** The Inventor viewer
|
||||
*
|
||||
@@ -266,6 +268,8 @@ public:
|
||||
void setNavigationType(Base::Type);
|
||||
NavigationStyle* navigationStyle() const;
|
||||
|
||||
void setDocument(Gui::Document *pcDocument);
|
||||
|
||||
protected:
|
||||
virtual void actualRedraw(void);
|
||||
virtual void setSeekMode(SbBool enable);
|
||||
@@ -301,6 +305,7 @@ private:
|
||||
SoSeparator * pcViewProviderRoot;
|
||||
SoEventCallback* pEventCallback;
|
||||
NavigationStyle* navigation;
|
||||
SoFCUnifiedSelection* selectionRoot;
|
||||
|
||||
void initialize();
|
||||
SbBool axiscrossEnabled;
|
||||
|
||||
@@ -139,6 +139,12 @@ void ViewProvider::setUpdatesEnabled (bool enable)
|
||||
_updateData = enable;
|
||||
}
|
||||
|
||||
void highlight(const HighlightMode& high)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ViewProvider::eventCallback(void * ud, SoEventCallback * node)
|
||||
{
|
||||
const SoEvent * ev = node->getEvent();
|
||||
|
||||
@@ -54,9 +54,12 @@ namespace App {
|
||||
class Color;
|
||||
}
|
||||
|
||||
class SoGroup;
|
||||
|
||||
#include <App/PropertyContainer.h>
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
|
||||
namespace Gui {
|
||||
namespace TaskView {
|
||||
class TaskContent;
|
||||
@@ -66,6 +69,7 @@ class ViewProviderPy;
|
||||
class ObjectItem;
|
||||
|
||||
|
||||
|
||||
/** General interface for all visual stuff in FreeCAD
|
||||
* This class is used to generate and handle all around
|
||||
* visualizing and presenting objects from the FreeCAD
|
||||
@@ -90,8 +94,18 @@ public:
|
||||
SoSeparator* getAnnotation(void);
|
||||
// returns the root node of the Provider (3D)
|
||||
virtual SoSeparator* getFrontRoot(void) const {return 0;}
|
||||
// returns the root node where the children gets collected(3D)
|
||||
virtual SoGroup* getChildRoot(void) const {return 0;}
|
||||
// returns the root node of the Provider (3D)
|
||||
virtual SoSeparator* getBackRoot(void) const {return 0;}
|
||||
/** deliver the children belonging to this object
|
||||
* this method is used to deliver the objects to
|
||||
* the 3DView which should be grouped under its
|
||||
* scene graph. This affects the visibility and the 3D
|
||||
* position of the object.
|
||||
*/
|
||||
virtual std::vector<App::DocumentObject*> claimChildren3D(void) const
|
||||
{ return std::vector<App::DocumentObject*>(); }
|
||||
|
||||
/** @name Selection handling
|
||||
* This group of methodes do the selection handling.
|
||||
@@ -179,6 +193,7 @@ public:
|
||||
bool isVisible() const;
|
||||
//@}
|
||||
|
||||
|
||||
/** @name Edit methods
|
||||
* if the Viewprovider goes in edit mode
|
||||
* you can handle most of the events in the viewer by yourself
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2012 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <sstream>
|
||||
# include <QApplication>
|
||||
# include <Inventor/SoPickedPoint.h>
|
||||
# include <Inventor/events/SoMouseButtonEvent.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
# include <Inventor/nodes/SoBaseColor.h>
|
||||
# include <Inventor/nodes/SoFontStyle.h>
|
||||
# include <Inventor/nodes/SoPickStyle.h>
|
||||
# include <Inventor/nodes/SoText2.h>
|
||||
# include <Inventor/nodes/SoTranslation.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoIndexedLineSet.h>
|
||||
# include <Inventor/nodes/SoMarkerSet.h>
|
||||
# include <Inventor/nodes/SoDrawStyle.h>
|
||||
#endif
|
||||
|
||||
#include <Inventor/nodes/SoMaterial.h>
|
||||
#include <Inventor/nodes/SoAnnotation.h>
|
||||
#include <Inventor/details/SoLineDetail.h>
|
||||
#include "ViewProviderPlacement.h"
|
||||
#include "SoFCSelection.h"
|
||||
#include "Application.h"
|
||||
#include "Document.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "Inventor/SoAutoZoomTranslation.h"
|
||||
#include "SoAxisCrossKit.h"
|
||||
//#include <SoDepthBuffer.h>
|
||||
|
||||
#include <App/PropertyGeo.h>
|
||||
#include <App/PropertyStandard.h>
|
||||
#include <App/MeasureDistance.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
PROPERTY_SOURCE(Gui::ViewProviderPlacement, Gui::ViewProviderGeometryObject)
|
||||
|
||||
|
||||
ViewProviderPlacement::ViewProviderPlacement()
|
||||
{
|
||||
|
||||
pMat = new SoMaterial();
|
||||
pMat->ref();
|
||||
|
||||
const float dist = 2;
|
||||
const float size = 6;
|
||||
const float pSize = 4;
|
||||
|
||||
static const SbVec3f verts[13] =
|
||||
{
|
||||
SbVec3f(0,0,0), SbVec3f(size,0,0),
|
||||
SbVec3f(0,size,0), SbVec3f(0,0,size),
|
||||
SbVec3f(dist,dist,0), SbVec3f(dist,pSize,0), SbVec3f(pSize,dist,0), // XY Plane
|
||||
SbVec3f(dist,0,dist), SbVec3f(dist,0,pSize), SbVec3f(pSize,0,dist), // XY Plane
|
||||
SbVec3f(0,dist,dist), SbVec3f(0,pSize,dist), SbVec3f(0,dist,pSize) // XY Plane
|
||||
};
|
||||
|
||||
// indexes used to create the edges
|
||||
static const int32_t lines[21] =
|
||||
{
|
||||
0,1,-1,
|
||||
0,2,-1,
|
||||
0,3,-1,
|
||||
5,4,6,-1,
|
||||
8,7,9,-1,
|
||||
11,10,12,-1
|
||||
};
|
||||
|
||||
pMat->diffuseColor.setNum(6);
|
||||
pMat->diffuseColor.set1Value(0, SbColor(1.0f, 0.2f, 0.2f));
|
||||
pMat->diffuseColor.set1Value(1, SbColor(0.2f, 1.0f, 0.2f));
|
||||
pMat->diffuseColor.set1Value(2, SbColor(0.2f, 0.2f, 1.0f));
|
||||
|
||||
pMat->diffuseColor.set1Value(3, SbColor(1.0f, 1.0f, 0.8f));
|
||||
pMat->diffuseColor.set1Value(4, SbColor(1.0f, 0.8f, 1.0f));
|
||||
pMat->diffuseColor.set1Value(5, SbColor(0.8f, 1.0f, 1.0f));
|
||||
|
||||
pCoords = new SoCoordinate3();
|
||||
pCoords->ref();
|
||||
pCoords->point.setNum(13);
|
||||
pCoords->point.setValues(0, 13, verts);
|
||||
|
||||
pLines = new SoIndexedLineSet();
|
||||
pLines->ref();
|
||||
pLines->coordIndex.setNum(21);
|
||||
pLines->coordIndex.setValues(0, 21, lines);
|
||||
sPixmap = "view-measurement";
|
||||
}
|
||||
|
||||
ViewProviderPlacement::~ViewProviderPlacement()
|
||||
{
|
||||
pCoords->unref();
|
||||
pLines->unref();
|
||||
pMat->unref();
|
||||
}
|
||||
|
||||
void ViewProviderPlacement::onChanged(const App::Property* prop)
|
||||
{
|
||||
ViewProviderGeometryObject::onChanged(prop);
|
||||
}
|
||||
|
||||
std::vector<std::string> ViewProviderPlacement::getDisplayModes(void) const
|
||||
{
|
||||
// add modes
|
||||
std::vector<std::string> StrList;
|
||||
StrList.push_back("Base");
|
||||
return StrList;
|
||||
}
|
||||
|
||||
void ViewProviderPlacement::setDisplayMode(const char* ModeName)
|
||||
{
|
||||
if (strcmp(ModeName, "Base") == 0)
|
||||
setDisplayMaskMode("Base");
|
||||
ViewProviderGeometryObject::setDisplayMode(ModeName);
|
||||
}
|
||||
|
||||
void ViewProviderPlacement::attach(App::DocumentObject* pcObject)
|
||||
{
|
||||
ViewProviderGeometryObject::attach(pcObject);
|
||||
|
||||
SoAnnotation *lineSep = new SoAnnotation();
|
||||
|
||||
|
||||
SoAutoZoomTranslation *zoom = new SoAutoZoomTranslation;
|
||||
|
||||
SoDrawStyle* style = new SoDrawStyle();
|
||||
style->lineWidth = 2.0f;
|
||||
|
||||
SoMaterialBinding* matBinding = new SoMaterialBinding;
|
||||
matBinding->value = SoMaterialBinding::PER_FACE;
|
||||
|
||||
lineSep->addChild(zoom);
|
||||
lineSep->addChild(style);
|
||||
lineSep->addChild(matBinding);
|
||||
lineSep->addChild(pMat);
|
||||
lineSep->addChild(pCoords);
|
||||
lineSep->addChild(pLines);
|
||||
|
||||
addDisplayMaskMode(lineSep, "Base");
|
||||
}
|
||||
|
||||
void ViewProviderPlacement::updateData(const App::Property* prop)
|
||||
{
|
||||
ViewProviderGeometryObject::updateData(prop);
|
||||
}
|
||||
|
||||
std::string ViewProviderPlacement::getElement(const SoDetail* detail) const
|
||||
{
|
||||
if (detail) {
|
||||
if (detail->getTypeId() == SoLineDetail::getClassTypeId()) {
|
||||
const SoLineDetail* line_detail = static_cast<const SoLineDetail*>(detail);
|
||||
int edge = line_detail->getLineIndex();
|
||||
switch (edge)
|
||||
{
|
||||
case 0: return std::string("X-Axis");
|
||||
case 1: return std::string("Y-Axis");
|
||||
case 2: return std::string("Z-Axis");
|
||||
case 3: return std::string("XY-Plane");
|
||||
case 4: return std::string("XZ-Plane");
|
||||
case 5: return std::string("YZ-Plane");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
SoDetail* ViewProviderPlacement::getDetail(const char* subelement) const
|
||||
{
|
||||
SoLineDetail* detail = 0;
|
||||
std::string subelem(subelement);
|
||||
int edge = -1;
|
||||
|
||||
if(subelem == "X-Axis") edge = 0;
|
||||
else if(subelem == "Y-Axis") edge = 1;
|
||||
else if(subelem == "Z-Axis") edge = 2;
|
||||
else if(subelem == "XY-Plane") edge = 3;
|
||||
else if(subelem == "XZ-Plane") edge = 4;
|
||||
else if(subelem == "YZ-Plane") edge = 5;
|
||||
|
||||
if(edge >= 0) {
|
||||
detail = new SoLineDetail();
|
||||
detail->setPartIndex(edge);
|
||||
}
|
||||
|
||||
|
||||
return detail;
|
||||
}
|
||||
|
||||
bool ViewProviderPlacement::isSelectable(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2012 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_ViewProviderPlacement_H
|
||||
#define GUI_ViewProviderPlacement_H
|
||||
|
||||
#include "ViewProviderGeometryObject.h"
|
||||
#include <QObject>
|
||||
|
||||
class SoFontStyle;
|
||||
class SoText2;
|
||||
class SoBaseColor;
|
||||
class SoTranslation;
|
||||
class SoCoordinate3;
|
||||
class SoIndexedLineSet;
|
||||
class SoEventCallback;
|
||||
class SoMaterial;
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
|
||||
class GuiExport ViewProviderPlacement : public ViewProviderGeometryObject
|
||||
{
|
||||
PROPERTY_HEADER(Gui::ViewProviderPlacement);
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
ViewProviderPlacement(void);
|
||||
virtual ~ViewProviderPlacement();
|
||||
|
||||
void attach(App::DocumentObject *);
|
||||
void updateData(const App::Property*);
|
||||
std::vector<std::string> getDisplayModes(void) const;
|
||||
void setDisplayMode(const char* ModeName);
|
||||
|
||||
/// indicates if the ViewProvider use the new Selection model
|
||||
virtual bool useNewSelectionModel(void) const {return true;}
|
||||
/// indicates if the ViewProvider can be selected
|
||||
virtual bool isSelectable(void) const ;
|
||||
/// return a hit element to the selection path or 0
|
||||
virtual std::string getElement(const SoDetail *) const;
|
||||
virtual SoDetail* getDetail(const char*) const;
|
||||
|
||||
protected:
|
||||
void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
SoCoordinate3 * pCoords;
|
||||
SoMaterial * pMat;
|
||||
SoIndexedLineSet * pLines;
|
||||
};
|
||||
|
||||
} //namespace Gui
|
||||
|
||||
|
||||
#endif // GUI_ViewProviderPlacement_H
|
||||
@@ -0,0 +1,195 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2012 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <sstream>
|
||||
# include <QApplication>
|
||||
# include <Inventor/SoPickedPoint.h>
|
||||
# include <Inventor/events/SoMouseButtonEvent.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
# include <Inventor/nodes/SoBaseColor.h>
|
||||
# include <Inventor/nodes/SoFontStyle.h>
|
||||
# include <Inventor/nodes/SoPickStyle.h>
|
||||
# include <Inventor/nodes/SoText2.h>
|
||||
# include <Inventor/nodes/SoTranslation.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoIndexedLineSet.h>
|
||||
# include <Inventor/nodes/SoMarkerSet.h>
|
||||
# include <Inventor/nodes/SoDrawStyle.h>
|
||||
#endif
|
||||
|
||||
#include <Inventor/nodes/SoMaterial.h>
|
||||
#include <Inventor/nodes/SoAnnotation.h>
|
||||
#include <Inventor/details/SoLineDetail.h>
|
||||
#include "ViewProviderPlane.h"
|
||||
#include "SoFCSelection.h"
|
||||
#include "Application.h"
|
||||
#include "Document.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "Inventor/SoAutoZoomTranslation.h"
|
||||
#include "SoAxisCrossKit.h"
|
||||
//#include <SoDepthBuffer.h>
|
||||
|
||||
#include <App/PropertyGeo.h>
|
||||
#include <App/PropertyStandard.h>
|
||||
#include <App/MeasureDistance.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
PROPERTY_SOURCE(Gui::ViewProviderPlane, Gui::ViewProviderGeometryObject)
|
||||
|
||||
|
||||
ViewProviderPlane::ViewProviderPlane()
|
||||
{
|
||||
|
||||
pMat = new SoMaterial();
|
||||
pMat->ref();
|
||||
|
||||
const float size = 2;
|
||||
|
||||
static const SbVec3f verts[4] =
|
||||
{
|
||||
SbVec3f(size,size,0), SbVec3f(size,-size,0),
|
||||
SbVec3f(-size,-size,0), SbVec3f(-size,size,0),
|
||||
};
|
||||
|
||||
// indexes used to create the edges
|
||||
static const int32_t lines[6] =
|
||||
{
|
||||
0,1,2,3,0,-1
|
||||
};
|
||||
|
||||
pMat->diffuseColor.setNum(1);
|
||||
pMat->diffuseColor.set1Value(0, SbColor(1.0f, 1.0f, 1.0f));
|
||||
|
||||
pCoords = new SoCoordinate3();
|
||||
pCoords->ref();
|
||||
pCoords->point.setNum(4);
|
||||
pCoords->point.setValues(0, 4, verts);
|
||||
|
||||
pLines = new SoIndexedLineSet();
|
||||
pLines->ref();
|
||||
pLines->coordIndex.setNum(6);
|
||||
pLines->coordIndex.setValues(0, 6, lines);
|
||||
sPixmap = "view-measurement";
|
||||
}
|
||||
|
||||
ViewProviderPlane::~ViewProviderPlane()
|
||||
{
|
||||
pCoords->unref();
|
||||
pLines->unref();
|
||||
pMat->unref();
|
||||
}
|
||||
|
||||
void ViewProviderPlane::onChanged(const App::Property* prop)
|
||||
{
|
||||
ViewProviderGeometryObject::onChanged(prop);
|
||||
}
|
||||
|
||||
std::vector<std::string> ViewProviderPlane::getDisplayModes(void) const
|
||||
{
|
||||
// add modes
|
||||
std::vector<std::string> StrList;
|
||||
StrList.push_back("Base");
|
||||
return StrList;
|
||||
}
|
||||
|
||||
void ViewProviderPlane::setDisplayMode(const char* ModeName)
|
||||
{
|
||||
if (strcmp(ModeName, "Base") == 0)
|
||||
setDisplayMaskMode("Base");
|
||||
ViewProviderGeometryObject::setDisplayMode(ModeName);
|
||||
}
|
||||
|
||||
void ViewProviderPlane::attach(App::DocumentObject* pcObject)
|
||||
{
|
||||
ViewProviderGeometryObject::attach(pcObject);
|
||||
|
||||
SoAnnotation *lineSep = new SoAnnotation();
|
||||
|
||||
|
||||
SoAutoZoomTranslation *zoom = new SoAutoZoomTranslation;
|
||||
|
||||
SoDrawStyle* style = new SoDrawStyle();
|
||||
style->lineWidth = 1.0f;
|
||||
|
||||
SoMaterialBinding* matBinding = new SoMaterialBinding;
|
||||
matBinding->value = SoMaterialBinding::PER_FACE;
|
||||
|
||||
lineSep->addChild(zoom);
|
||||
lineSep->addChild(style);
|
||||
lineSep->addChild(matBinding);
|
||||
lineSep->addChild(pMat);
|
||||
lineSep->addChild(pCoords);
|
||||
lineSep->addChild(pLines);
|
||||
|
||||
addDisplayMaskMode(lineSep, "Base");
|
||||
}
|
||||
|
||||
void ViewProviderPlane::updateData(const App::Property* prop)
|
||||
{
|
||||
ViewProviderGeometryObject::updateData(prop);
|
||||
}
|
||||
|
||||
std::string ViewProviderPlane::getElement(const SoDetail* detail) const
|
||||
{
|
||||
if (detail) {
|
||||
if (detail->getTypeId() == SoLineDetail::getClassTypeId()) {
|
||||
const SoLineDetail* line_detail = static_cast<const SoLineDetail*>(detail);
|
||||
int edge = line_detail->getLineIndex();
|
||||
if (edge == 0)
|
||||
{
|
||||
return std::string("Main");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
SoDetail* ViewProviderPlane::getDetail(const char* subelement) const
|
||||
{
|
||||
SoLineDetail* detail = 0;
|
||||
std::string subelem(subelement);
|
||||
int edge = -1;
|
||||
|
||||
if(subelem == "Main") edge = 0;
|
||||
|
||||
if(edge >= 0) {
|
||||
detail = new SoLineDetail();
|
||||
detail->setPartIndex(edge);
|
||||
}
|
||||
|
||||
return detail;
|
||||
}
|
||||
|
||||
bool ViewProviderPlane::isSelectable(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2012 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_ViewProviderPlane_H
|
||||
#define GUI_ViewProviderPlane_H
|
||||
|
||||
#include "ViewProviderGeometryObject.h"
|
||||
#include <QObject>
|
||||
|
||||
class SoFontStyle;
|
||||
class SoText2;
|
||||
class SoBaseColor;
|
||||
class SoTranslation;
|
||||
class SoCoordinate3;
|
||||
class SoIndexedLineSet;
|
||||
class SoEventCallback;
|
||||
class SoMaterial;
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
|
||||
class GuiExport ViewProviderPlane : public ViewProviderGeometryObject
|
||||
{
|
||||
PROPERTY_HEADER(Gui::ViewProviderPlane);
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
ViewProviderPlane(void);
|
||||
virtual ~ViewProviderPlane();
|
||||
|
||||
void attach(App::DocumentObject *);
|
||||
void updateData(const App::Property*);
|
||||
std::vector<std::string> getDisplayModes(void) const;
|
||||
void setDisplayMode(const char* ModeName);
|
||||
|
||||
/// indicates if the ViewProvider use the new Selection model
|
||||
virtual bool useNewSelectionModel(void) const {return true;}
|
||||
/// indicates if the ViewProvider can be selected
|
||||
virtual bool isSelectable(void) const ;
|
||||
/// return a hit element to the selection path or 0
|
||||
virtual std::string getElement(const SoDetail *) const;
|
||||
virtual SoDetail* getDetail(const char*) const;
|
||||
|
||||
protected:
|
||||
void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
SoCoordinate3 * pCoords;
|
||||
SoMaterial * pMat;
|
||||
SoIndexedLineSet * pLines;
|
||||
};
|
||||
|
||||
} //namespace Gui
|
||||
|
||||
|
||||
#endif // GUI_ViewProviderPlane_H
|
||||
@@ -46,7 +46,6 @@
|
||||
|
||||
// FreeCAD Base header
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Uuid.h>
|
||||
#include <App/Application.h>
|
||||
|
||||
|
||||
@@ -127,8 +126,6 @@ extern "C"
|
||||
strncpy(argv[0], info.dli_fname,PATH_MAX);
|
||||
argv[0][PATH_MAX-1] = '\0'; // ensure null termination
|
||||
// this is a workaround to avoid a crash in libuuid.so
|
||||
Base::Uuid uuid;
|
||||
uuid.UuidStr="";
|
||||
#elif defined(FC_OS_MACOSX)
|
||||
uint32_t sz = 0;
|
||||
char *buf;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
#### WARNING: CELL OBJECT IS OBSOLETED
|
||||
|
||||
import FreeCAD,FreeCADGui,Draft,ArchComponent,ArchCommands
|
||||
from FreeCAD import Vector
|
||||
from PyQt4 import QtCore
|
||||
|
||||
@@ -78,7 +78,7 @@ def addComponents(objectsList,host):
|
||||
if not o in c:
|
||||
c.append(o)
|
||||
host.Group = c
|
||||
elif tp in ["Wall","Structure"]:
|
||||
elif tp in ["Wall","Structure","Window","Roof"]:
|
||||
a = host.Additions
|
||||
if hasattr(host,"Axes"):
|
||||
x = host.Axes
|
||||
|
||||
@@ -37,7 +37,7 @@ def addToComponent(compobject,addobject,mod=None):
|
||||
to override the default.'''
|
||||
import Draft
|
||||
if compobject == addobject: return
|
||||
# first check is already there
|
||||
# first check zis already there
|
||||
found = False
|
||||
attribs = ["Additions","Objects","Components","Subtractions","Base"]
|
||||
for a in attribs:
|
||||
@@ -266,13 +266,120 @@ class Component:
|
||||
self.Type = "Component"
|
||||
self.Subvolume = None
|
||||
|
||||
|
||||
def __getstate__(self):
|
||||
return self.Type
|
||||
|
||||
|
||||
def __setstate__(self,state):
|
||||
if state:
|
||||
self.Type = state
|
||||
|
||||
|
||||
|
||||
def getSubVolume(self,base,width,plac=None):
|
||||
"returns a subvolume from a base object"
|
||||
import Part,DraftVecUtils
|
||||
|
||||
# finding biggest wire in the base shape
|
||||
max_length = 0
|
||||
f = None
|
||||
for w in base.Shape.Wires:
|
||||
if w.BoundBox.DiagonalLength > max_length:
|
||||
max_length = w.BoundBox.DiagonalLength
|
||||
f = w
|
||||
if f:
|
||||
f = Part.Face(f)
|
||||
n = f.normalAt(0,0)
|
||||
v1 = DraftVecUtils.scaleTo(n,width*1.1) # we extrude a little more to avoid face-on-face
|
||||
f.translate(v1)
|
||||
v2 = DraftVecUtils.neg(v1)
|
||||
v2 = DraftVecUtils.scale(v1,-2)
|
||||
f = f.extrude(v2)
|
||||
if plac:
|
||||
f.Placement = plac
|
||||
return f
|
||||
return None
|
||||
|
||||
|
||||
def hideSubobjects(self,obj,prop):
|
||||
"Hides subobjects when a subobject lists change"
|
||||
if prop in ["Additions","Subtractions"]:
|
||||
if hasattr(obj,prop):
|
||||
for o in getattr(obj,prop):
|
||||
o.ViewObject.hide()
|
||||
|
||||
def processSubShapes(self,obj,base):
|
||||
"Adds additions and subtractions to a base shape"
|
||||
import Draft
|
||||
|
||||
# treat additions
|
||||
for o in obj.Additions:
|
||||
|
||||
if base:
|
||||
if base.isNull():
|
||||
base = None
|
||||
|
||||
if (Draft.getType(o) == "Window") or (Draft.isClone(o,"Window")):
|
||||
if base:
|
||||
# windows can be additions or subtractions, treated the same way
|
||||
if hasattr(self,"Width"):
|
||||
width = self.Width
|
||||
else:
|
||||
b = base.BoundBox
|
||||
width = max(b.XLength,b.YLength,b.ZLength)
|
||||
if Draft.isClone(o,"Window"):
|
||||
window = o.Objects[0]
|
||||
else:
|
||||
window = o
|
||||
if window.Base and width:
|
||||
f = self.getSubVolume(window.Base,width)
|
||||
if f:
|
||||
if base.Solids and f.Solids:
|
||||
base = base.cut(f)
|
||||
|
||||
elif o.isDerivedFrom("Part::Feature"):
|
||||
if o.Shape:
|
||||
if not o.Shape.isNull():
|
||||
if o.Shape.Solids:
|
||||
if base:
|
||||
if base.Solids:
|
||||
base = base.fuse(o.Shape)
|
||||
else:
|
||||
base = o.Shape
|
||||
|
||||
# treat subtractions
|
||||
for o in obj.Subtractions:
|
||||
|
||||
if base:
|
||||
if base.isNull():
|
||||
base = None
|
||||
|
||||
if base:
|
||||
if (Draft.getType(o) == "Window") or (Draft.isClone(o,"Window")):
|
||||
# windows can be additions or subtractions, treated the same way
|
||||
if hasattr(self,"Width"):
|
||||
width = self.Width
|
||||
else:
|
||||
b = base.BoundBox
|
||||
width = max(b.XLength,b.YLength,b.ZLength)
|
||||
if Draft.isClone(o,"Window"):
|
||||
window = o.Objects[0]
|
||||
else:
|
||||
window = o
|
||||
if window.Base and width:
|
||||
f = self.getSubVolume(window.Base,width)
|
||||
if f:
|
||||
if base.Solids and f.Solids:
|
||||
base = base.cut(f)
|
||||
|
||||
elif o.isDerivedFrom("Part::Feature"):
|
||||
if o.Shape:
|
||||
if not o.Shape.isNull():
|
||||
if o.Shape.Solids and base.Solids:
|
||||
base = base.cut(o.Shape)
|
||||
return base
|
||||
|
||||
|
||||
class ViewProviderComponent:
|
||||
"A default View Provider for Component objects"
|
||||
def __init__(self,vobj):
|
||||
|
||||
@@ -30,7 +30,7 @@ __title__="FreeCAD Roof"
|
||||
__author__ = "Yorik van Havre"
|
||||
__url__ = "http://free-cad.sourceforge.net"
|
||||
|
||||
def makeRoof(baseobj,facenr=1,angle=45,name=str(translate("Arch","Roof"))):
|
||||
def makeRoof(baseobj=None,facenr=1,angle=45,name=str(translate("Arch","Roof"))):
|
||||
'''makeRoof(baseobj,[facenr],[angle],[name]) : Makes a roof based on a
|
||||
face from an existing object. You can provide the number of the face
|
||||
to build the roof on (default = 1), the angle (default=45) and a name (default
|
||||
@@ -38,7 +38,8 @@ def makeRoof(baseobj,facenr=1,angle=45,name=str(translate("Arch","Roof"))):
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
|
||||
_Roof(obj)
|
||||
_ViewProviderRoof(obj.ViewObject)
|
||||
obj.Base = baseobj
|
||||
if baseobj:
|
||||
obj.Base = baseobj
|
||||
obj.Face = facenr
|
||||
obj.Angle = angle
|
||||
return obj
|
||||
@@ -92,12 +93,13 @@ class _Roof(ArchComponent.Component):
|
||||
str(translate("Arch","The angle of this roof")))
|
||||
obj.addProperty("App::PropertyInteger","Face","Base",
|
||||
str(translate("Arch","The face number of the base object used to build this roof")))
|
||||
self.Type = "Structure"
|
||||
self.Type = "Roof"
|
||||
|
||||
def execute(self,obj):
|
||||
self.createGeometry(obj)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
self.hideSubobjects(obj,prop)
|
||||
if prop in ["Base","Face","Angle","Additions","Subtractions"]:
|
||||
self.createGeometry(obj)
|
||||
|
||||
@@ -105,6 +107,7 @@ class _Roof(ArchComponent.Component):
|
||||
import Part, math, DraftGeomUtils
|
||||
pl = obj.Placement
|
||||
|
||||
base = None
|
||||
if obj.Base and obj.Angle:
|
||||
w = None
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
@@ -133,14 +136,18 @@ class _Roof(ArchComponent.Component):
|
||||
dv.normalize()
|
||||
dv.scale(d,d,d)
|
||||
shps.append(f.extrude(dv))
|
||||
c = shps.pop()
|
||||
base = shps.pop()
|
||||
for s in shps:
|
||||
c = c.common(s)
|
||||
c = c.removeSplitter()
|
||||
if not c.isNull():
|
||||
obj.Shape = c
|
||||
base = base.common(s)
|
||||
base = base.removeSplitter()
|
||||
if not base.isNull():
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
obj.Placement = pl
|
||||
base.Placement = pl
|
||||
|
||||
base = self.processSubShapes(obj,base)
|
||||
if base:
|
||||
if not base.isNull():
|
||||
obj.Shape = base
|
||||
|
||||
class _ViewProviderRoof(ArchComponent.ViewProviderComponent):
|
||||
"A View Provider for the Roof object"
|
||||
|
||||
@@ -80,6 +80,8 @@ class _Site(ArchFloor._Floor):
|
||||
"The Site object"
|
||||
def __init__(self,obj):
|
||||
ArchFloor._Floor.__init__(self,obj)
|
||||
obj.addProperty("App::PropertyLink","Terrain","Base",
|
||||
str(translate("Arch","The terrain of this site")))
|
||||
self.Type = "Site"
|
||||
obj.setEditorMode('Height',2)
|
||||
|
||||
@@ -91,6 +93,9 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor):
|
||||
def getIcon(self):
|
||||
import Arch_rc
|
||||
return ":/icons/Arch_Site_Tree.svg"
|
||||
|
||||
def claimChildren(self):
|
||||
return self.Object.Group+[self.Object.Terrain]
|
||||
|
||||
|
||||
FreeCADGui.addCommand('Arch_Site',_CommandSite())
|
||||
|
||||
@@ -108,6 +108,7 @@ class _Structure(ArchComponent.Component):
|
||||
self.createGeometry(obj)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
self.hideSubobjects(obj,prop)
|
||||
if prop in ["Base","Length","Width","Height","Normal","Additions","Subtractions","Axes"]:
|
||||
self.createGeometry(obj)
|
||||
|
||||
@@ -189,20 +190,9 @@ class _Structure(ArchComponent.Component):
|
||||
base = Part.Face(base)
|
||||
base = base.extrude(normal)
|
||||
|
||||
base = self.processSubShapes(obj,base)
|
||||
|
||||
if base:
|
||||
# applying adds and subs
|
||||
if not base.isNull():
|
||||
for app in obj.Additions:
|
||||
if hasattr(app,"Shape"):
|
||||
if not app.Shape.isNull():
|
||||
base = base.fuse(app.Shape)
|
||||
app.ViewObject.hide() # to be removed
|
||||
for hole in obj.Subtractions:
|
||||
if hasattr(hole,"Shape"):
|
||||
if not hole.Shape.isNull():
|
||||
base = base.cut(hole.Shape)
|
||||
hole.ViewObject.hide() # to be removed
|
||||
|
||||
# applying axes
|
||||
pts = self.getAxisPoints(obj)
|
||||
apl = self.getAxisPlacement(obj)
|
||||
@@ -220,6 +210,7 @@ class _Structure(ArchComponent.Component):
|
||||
obj.Shape = Part.makeCompound(fsh)
|
||||
|
||||
# finalizing
|
||||
|
||||
else:
|
||||
if base:
|
||||
if not base.isNull():
|
||||
|
||||
@@ -110,7 +110,8 @@ class _CommandWall:
|
||||
self.Height = 1
|
||||
self.Align = "Center"
|
||||
self.continueCmd = False
|
||||
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
self.JOIN_WALLS = p.GetBool("joinWallSketches")
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
done = False
|
||||
self.existing = []
|
||||
@@ -145,7 +146,6 @@ class _CommandWall:
|
||||
FreeCADGui.Snapper.getPoint(last=self.points[0],callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox())
|
||||
elif len(self.points) == 2:
|
||||
import Part
|
||||
add = False
|
||||
l = Part.Line(self.points[0],self.points[1])
|
||||
self.tracker.finalize()
|
||||
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Wall")))
|
||||
@@ -153,19 +153,25 @@ class _CommandWall:
|
||||
FreeCADGui.doCommand('import Part')
|
||||
FreeCADGui.doCommand('trace=Part.Line(FreeCAD.'+str(l.StartPoint)+',FreeCAD.'+str(l.EndPoint)+')')
|
||||
if not self.existing:
|
||||
# no existing wall snapped, just add a default wall
|
||||
self.addDefault(l)
|
||||
else:
|
||||
w = joinWalls(self.existing)
|
||||
if w:
|
||||
if areSameWallTypes([w,self]):
|
||||
FreeCADGui.doCommand('FreeCAD.ActiveDocument.'+w.Name+'.Base.addGeometry(trace)')
|
||||
if self.JOIN_WALLS:
|
||||
# join existing subwalls first if possible, then add the new one
|
||||
w = joinWalls(self.existing)
|
||||
if w:
|
||||
if areSameWallTypes([w,self]):
|
||||
FreeCADGui.doCommand('FreeCAD.ActiveDocument.'+w.Name+'.Base.addGeometry(trace)')
|
||||
else:
|
||||
# if not possible, add new wall as addition to the existing one
|
||||
self.addDefault(l)
|
||||
FreeCADGui.doCommand('Arch.addComponents(FreeCAD.ActiveDocument.'+FreeCAD.ActiveDocument.Objects[-1].Name+',FreeCAD.ActiveDocument.'+w.Name+')')
|
||||
else:
|
||||
self.addDefault(l)
|
||||
add = True
|
||||
else:
|
||||
# add new wall as addition to the first existing one
|
||||
self.addDefault(l)
|
||||
if add:
|
||||
FreeCADGui.doCommand('Arch.addComponents(FreeCAD.ActiveDocument.'+FreeCAD.ActiveDocument.Objects[-1].Name+',FreeCAD.ActiveDocument.'+w.Name+')')
|
||||
FreeCADGui.doCommand('Arch.addComponents(FreeCAD.ActiveDocument.'+FreeCAD.ActiveDocument.Objects[-1].Name+',FreeCAD.ActiveDocument.'+self.existing[0].Name+')')
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
if self.continueCmd:
|
||||
@@ -267,31 +273,10 @@ class _Wall(ArchComponent.Component):
|
||||
self.createGeometry(obj)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
self.hideSubobjects(obj,prop)
|
||||
if prop in ["Base","Height","Width","Align","Additions","Subtractions"]:
|
||||
self.createGeometry(obj)
|
||||
|
||||
def getSubVolume(self,base,width,plac=None):
|
||||
"returns a subvolume from a base object"
|
||||
import Part
|
||||
max_length = 0
|
||||
f = None
|
||||
for w in base.Shape.Wires:
|
||||
if w.BoundBox.DiagonalLength > max_length:
|
||||
max_length = w.BoundBox.DiagonalLength
|
||||
f = w
|
||||
if f:
|
||||
f = Part.Face(f)
|
||||
n = f.normalAt(0,0)
|
||||
v1 = DraftVecUtils.scaleTo(n,width)
|
||||
f.translate(v1)
|
||||
v2 = DraftVecUtils.neg(v1)
|
||||
v2 = DraftVecUtils.scale(v1,-2)
|
||||
f = f.extrude(v2)
|
||||
if plac:
|
||||
f.Placement = plac
|
||||
return f
|
||||
return None
|
||||
|
||||
def createGeometry(self,obj):
|
||||
"builds the wall shape"
|
||||
|
||||
@@ -361,11 +346,11 @@ class _Wall(ArchComponent.Component):
|
||||
base = obj.Base.Shape.copy()
|
||||
if base.Solids:
|
||||
pass
|
||||
elif base.Faces and (not obj.ForceWire):
|
||||
elif (len(base.Faces) == 1) and (not obj.ForceWire):
|
||||
if height:
|
||||
norm = normal.multiply(height)
|
||||
base = base.extrude(norm)
|
||||
elif base.Wires:
|
||||
elif len(base.Wires) == 1:
|
||||
temp = None
|
||||
for wire in obj.Base.Shape.Wires:
|
||||
sh = getbase(wire)
|
||||
@@ -376,9 +361,10 @@ class _Wall(ArchComponent.Component):
|
||||
base = temp
|
||||
elif base.Edges:
|
||||
wire = Part.Wire(base.Edges)
|
||||
sh = getbase(wire)
|
||||
if sh:
|
||||
base = sh
|
||||
if wire:
|
||||
sh = getbase(wire)
|
||||
if sh:
|
||||
base = sh
|
||||
else:
|
||||
base = None
|
||||
FreeCAD.Console.PrintError(str(translate("Arch","Error: Invalid base object")))
|
||||
@@ -392,44 +378,10 @@ class _Wall(ArchComponent.Component):
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning(str(translate("Arch","This mesh is an invalid solid")))
|
||||
obj.Base.ViewObject.show()
|
||||
|
||||
|
||||
base = self.processSubShapes(obj,base)
|
||||
|
||||
if base:
|
||||
|
||||
for app in obj.Additions:
|
||||
if Draft.getType(app) == "Window":
|
||||
# window
|
||||
if app.Base and obj.Width:
|
||||
f = self.getSubVolume(app.Base,width)
|
||||
if f:
|
||||
base = base.cut(f)
|
||||
elif Draft.isClone(app,"Window"):
|
||||
if app.Objects[0].Base and width:
|
||||
f = self.getSubVolume(app.Objects[0].Base,width,app.Placement)
|
||||
if f:
|
||||
base = base.cut(f)
|
||||
elif app.isDerivedFrom("Part::Feature"):
|
||||
if app.Shape:
|
||||
if not app.Shape.isNull():
|
||||
base = base.fuse(app.Shape)
|
||||
app.ViewObject.hide() #to be removed
|
||||
for hole in obj.Subtractions:
|
||||
if Draft.getType(hole) == "Window":
|
||||
# window
|
||||
if hole.Base and obj.Width:
|
||||
f = self.getSubVolume(hole.Base,width)
|
||||
if f:
|
||||
base = base.cut(f)
|
||||
elif Draft.isClone(hole,"Window"):
|
||||
if hole.Objects[0].Base and width:
|
||||
f = self.getSubVolume(hole.Objects[0].Base,width,hole.Placement)
|
||||
if f:
|
||||
base = base.cut(f)
|
||||
elif hole.isDerivedFrom("Part::Feature"):
|
||||
if hole.Shape:
|
||||
if not hole.Shape.isNull():
|
||||
base = base.cut(hole.Shape)
|
||||
hole.ViewObject.hide() # to be removed
|
||||
|
||||
if not base.isNull():
|
||||
if base.isValid() and base.Solids:
|
||||
if base.Volume < 0:
|
||||
|
||||
@@ -120,12 +120,14 @@ class _Window(ArchComponent.Component):
|
||||
self.createGeometry(obj)
|
||||
|
||||
def onChanged(self,obj,prop):
|
||||
self.hideSubobjects(obj,prop)
|
||||
if prop in ["Base","WindowParts"]:
|
||||
self.createGeometry(obj)
|
||||
|
||||
def createGeometry(self,obj):
|
||||
import Part, DraftGeomUtils
|
||||
pl = obj.Placement
|
||||
base = None
|
||||
if obj.Base:
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
if hasattr(obj,"WindowParts"):
|
||||
@@ -163,9 +165,14 @@ class _Window(ArchComponent.Component):
|
||||
shape.translate(zov)
|
||||
shapes.append(shape)
|
||||
if shapes:
|
||||
obj.Shape = Part.makeCompound(shapes)
|
||||
base = Part.makeCompound(shapes)
|
||||
if not DraftGeomUtils.isNull(pl):
|
||||
obj.Placement = pl
|
||||
base.Placement = pl
|
||||
|
||||
base = self.processSubShapes(obj,base)
|
||||
if base:
|
||||
if not base.isNull():
|
||||
obj.Shape = base
|
||||
|
||||
class _ViewProviderWindow(ArchComponent.ViewProviderComponent):
|
||||
"A View Provider for the Window object"
|
||||
|
||||
@@ -26,33 +26,41 @@ class ArchWorkbench(Workbench):
|
||||
Icon = """
|
||||
/* XPM */
|
||||
static char * arch_xpm[] = {
|
||||
"16 16 9 1",
|
||||
"16 16 17 1",
|
||||
" c None",
|
||||
". c #543016",
|
||||
"+ c #6D2F08",
|
||||
"@ c #954109",
|
||||
"# c #874C24",
|
||||
"$ c #AE6331",
|
||||
"% c #C86423",
|
||||
"& c #FD7C26",
|
||||
"* c #F5924F",
|
||||
". c #373936",
|
||||
"+ c #464845",
|
||||
"@ c #545553",
|
||||
"# c #626461",
|
||||
"$ c #6B6D6A",
|
||||
"% c #727471",
|
||||
"& c #7E807D",
|
||||
"* c #8A8C89",
|
||||
"= c #949693",
|
||||
"- c #A1A3A0",
|
||||
"; c #ADAFAC",
|
||||
"> c #BEC1BD",
|
||||
", c #C9CBC8",
|
||||
"' c #D9DCD8",
|
||||
") c #E4E6E3",
|
||||
"! c #FDFFFC",
|
||||
" ",
|
||||
" ",
|
||||
" # ",
|
||||
" ***$# ",
|
||||
" .*******. ",
|
||||
" *##$****#+ ",
|
||||
" #**%&&##$#@@ ",
|
||||
".$**%&&&&+@@+ ",
|
||||
"@&@#$$%&&@@+.. ",
|
||||
"@&&&%#.#$#+..#$.",
|
||||
" %&&&&+%#.$**$@+",
|
||||
" @%&+&&&$##@@+",
|
||||
" @.&&&&&@@@ ",
|
||||
" @%&&@@ ",
|
||||
" @+ ",
|
||||
" "};
|
||||
"""
|
||||
" & ",
|
||||
" >)'-% ",
|
||||
" #,))))),@ ",
|
||||
" >%*-))))*# ",
|
||||
" $')>!)**>%*% ",
|
||||
"@=')>!!!!$==# ",
|
||||
"=!=**;'!!&=$++ ",
|
||||
"=!!!)*@&-%#@#&-.",
|
||||
" ,!!!!#>&#=,'=%@",
|
||||
" ;)!#!!!-*$&=@",
|
||||
" *@!!!!!$=* ",
|
||||
" =>!!$& ",
|
||||
" -+ ",
|
||||
" "};"""
|
||||
|
||||
MenuText = "Arch"
|
||||
ToolTip = "Architecture workbench"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
height="64px"
|
||||
id="svg2816"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="Arch_Wall.svg">
|
||||
<defs
|
||||
id="defs2818">
|
||||
@@ -172,9 +172,9 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.9445436"
|
||||
inkscape:cx="61.084031"
|
||||
inkscape:cy="29.484142"
|
||||
inkscape:zoom="5.4999999"
|
||||
inkscape:cx="12.067807"
|
||||
inkscape:cy="34.07063"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
@@ -186,11 +186,13 @@
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="758"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1057"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="19"
|
||||
inkscape:window-maximized="0" />
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-global="false" />
|
||||
<metadata
|
||||
id="metadata2821">
|
||||
<rdf:RDF>
|
||||
@@ -208,72 +210,158 @@
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.11589425;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-8"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
x="32.997906"
|
||||
y="59.61282"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="31.222485"
|
||||
y="61.948494"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287753;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.02470295;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
x="2.3111296"
|
||||
y="28.888771"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="2.3714659"
|
||||
y="35.403149"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287753;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.02470295;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-9"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
x="28.963516"
|
||||
y="28.866888"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="28.579195"
|
||||
y="35.384312"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 14.241527,19.294108 37.07818,27.781829 25.002993,38.181657 2.1663398,29.693936 14.241527,19.294108 z"
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 14.322436,27.174833 37.137803,34.480522 25.073871,43.432031 2.2585043,36.126342 14.322436,27.174833 z"
|
||||
id="rect2840-3-5-3-5"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.02470295;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-6-8"
|
||||
width="12.321729"
|
||||
height="10.849375"
|
||||
x="2.5293117"
|
||||
y="22.506136"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 39.224174,28.454727 62.060827,36.942448 49.98564,47.342276 27.148987,38.854555 39.224174,28.454727 z"
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 39.281797,35.05971 62.097164,42.365399 50.033232,51.316908 27.217865,44.011219 39.281797,35.05971 z"
|
||||
id="rect2840-3-5-3"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#000000;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.60305344"
|
||||
d="m 39.510988,41.014833 13.307194,-1.651197 4.898989,-4.035599 -20.638992,-7.649023 -8.324649,7.169655 10.757458,6.166164 z"
|
||||
id="path3849"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287752999999993;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.11589425;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-5-6"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="17.611925"
|
||||
y="37.546371"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.02470295;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
x="17.78878"
|
||||
y="13.847153"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="17.590893"
|
||||
y="22.456282"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.11589425;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
x="65.968956"
|
||||
y="90.392708"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="62.302372"
|
||||
y="88.441856"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727000000005;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.11589425;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
x="52.144951"
|
||||
y="62.458496"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="49.27129"
|
||||
y="64.397865"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 28.74952,9.541872 51.586172,18.029593 39.510985,28.429421 16.674332,19.9417 28.74952,9.541872 z"
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 28.816906,18.78073 51.632272,26.086419 39.568341,35.037928 16.752974,27.732239 28.816906,18.78073 z"
|
||||
id="rect2840-3-5"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 14.563589,14.315707 26.20756,18.100203 14.143628,27.051712 2.4996565,23.267217 z"
|
||||
id="rect2840-3-5-4-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.02470295;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-6"
|
||||
width="8.2209435"
|
||||
height="10.769706"
|
||||
x="44.096127"
|
||||
y="22.607765"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.11589425;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-5"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="62.043102"
|
||||
y="75.469635"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 54.0596,27.093403 7.829347,2.454267 -12.063932,8.951509 -7.829348,-2.454266 z"
|
||||
id="rect2840-3-5-4"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.11589425;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-8-7"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="31.137732"
|
||||
y="36.13694"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.02470295;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-2"
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="2.2999978"
|
||||
y="9.6638966"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffaf00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.02470295;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-9-2"
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="28.507727"
|
||||
y="9.6450615"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 14.254372,1.4137861 37.069739,8.7194752 25.005807,17.670984 2.1904396,10.365295 14.254372,1.4137861 z"
|
||||
id="rect2840-3-5-3-5-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#ffdd27;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 39.213732,9.2986629 62.029099,16.604352 49.965168,25.555861 27.149801,18.250172 39.213732,9.2986629 z"
|
||||
id="rect2840-3-5-3-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#aa7200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.11589425;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-04"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="62.217617"
|
||||
y="62.630302"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 18 KiB |
@@ -117,8 +117,8 @@
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5000001"
|
||||
inkscape:cx="45.025641"
|
||||
inkscape:cy="27.819016"
|
||||
inkscape:cx="16.555064"
|
||||
inkscape:cy="36.41599"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
@@ -130,11 +130,11 @@
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="758"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1057"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="19"
|
||||
inkscape:window-maximized="0" />
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata2821">
|
||||
<rdf:RDF>
|
||||
@@ -152,72 +152,158 @@
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="color:#000000;fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.44642201;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-8"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
x="32.997906"
|
||||
y="59.61282"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.34768275;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-8-5"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="31.222485"
|
||||
y="61.948494"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.09863277999999998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
x="2.3111296"
|
||||
y="28.888771"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.07410886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-7"
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="2.3714659"
|
||||
y="35.403145"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.09863277999999998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-9"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
x="28.963516"
|
||||
y="28.866888"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.07410886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-9-6"
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="28.579195"
|
||||
y="35.384308"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 14.241527,19.294108 37.07818,27.781829 25.002993,38.181657 2.1663398,29.693936 14.241527,19.294108 z"
|
||||
id="rect2840-3-5-3-5"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 14.322436,27.174833 37.137803,34.480522 25.073871,43.432031 2.2585043,36.126342 14.322436,27.174833 z"
|
||||
id="rect2840-3-5-3-5-0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.07410886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-6-8"
|
||||
width="12.321729"
|
||||
height="10.849375"
|
||||
x="2.5293117"
|
||||
y="22.506136"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 39.281797,35.05971 62.097164,42.365399 50.033232,51.316908 27.217865,44.011219 39.281797,35.05971 z"
|
||||
id="rect2840-3-5-3-0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.34768275;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-5-6"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="17.611925"
|
||||
y="37.546371"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.07410886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-2"
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="17.590893"
|
||||
y="22.456282"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.34768275;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-5"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="62.302372"
|
||||
y="88.441849"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.34768275;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-7"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="49.27129"
|
||||
y="64.397865"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 28.816906,18.78073 51.632272,26.086419 39.568341,35.037928 16.752974,27.732239 28.816906,18.78073 z"
|
||||
id="rect2840-3-5-2"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 14.563589,14.315707 26.20756,18.100203 14.143628,27.051712 2.4996565,23.267217 z"
|
||||
id="rect2840-3-5-4-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.07410886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-6"
|
||||
width="8.2209435"
|
||||
height="10.769706"
|
||||
x="44.096127"
|
||||
y="22.607765"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.34768275;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-5"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="62.043102"
|
||||
y="75.469627"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 54.0596,27.093403 7.829347,2.454267 -12.063932,8.951509 -7.829348,-2.454266 z"
|
||||
id="rect2840-3-5-4"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.34768275;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-8-7"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="31.137732"
|
||||
y="36.13694"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.07410886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-2"
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="2.2999978"
|
||||
y="9.6638966"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.07410886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-9-2"
|
||||
width="23.956503"
|
||||
height="10.744221"
|
||||
x="28.507727"
|
||||
y="9.6450615"
|
||||
transform="matrix(0.95236631,0.3049564,0,1,0,0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 14.254372,1.413786 37.069739,8.7194751 25.005807,17.670984 2.1904396,10.365295 14.254372,1.413786 z"
|
||||
id="rect2840-3-5-3-5-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 39.224174,28.454727 62.060827,36.942448 49.98564,47.342276 27.148987,38.854555 39.224174,28.454727 z"
|
||||
id="rect2840-3-5-3"
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 39.213732,9.2986628 62.029099,16.604352 49.965168,25.555861 27.149801,18.250172 39.213732,9.2986628 z"
|
||||
id="rect2840-3-5-3-1"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#000000;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.60305344000000005;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 39.510988,41.014833 13.307194,-1.651197 4.898989,-4.035599 -20.638992,-7.649023 -8.324649,7.169655 10.757458,6.166164 z"
|
||||
id="path3849"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.09863277999999998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-3"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
x="17.78878"
|
||||
y="13.847153"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.44642201000000004;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-3-4"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
x="65.968956"
|
||||
y="90.392708"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.44642201000000004;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-3-4-0"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
x="52.144951"
|
||||
y="62.458496"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 28.74952,9.541872 51.586172,18.029593 39.510985,28.429421 16.674332,19.9417 28.74952,9.541872 z"
|
||||
id="rect2840-3-5"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.34768275;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-04"
|
||||
width="15.022249"
|
||||
height="10.832717"
|
||||
x="62.217617"
|
||||
y="62.630302"
|
||||
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 16 KiB |
@@ -13,8 +13,8 @@
|
||||
height="64px"
|
||||
id="svg2816"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="New document 2">
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="preferences-arch.svg">
|
||||
<defs
|
||||
id="defs2818">
|
||||
<inkscape:perspective
|
||||
@@ -116,9 +116,9 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="33.685487"
|
||||
inkscape:cy="28.119326"
|
||||
inkscape:zoom="2.75"
|
||||
inkscape:cx="29.770815"
|
||||
inkscape:cy="15.617924"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
@@ -130,11 +130,11 @@
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="758"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1057"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="19"
|
||||
inkscape:window-maximized="0" />
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata2821">
|
||||
<rdf:RDF>
|
||||
@@ -143,7 +143,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -152,7 +152,7 @@
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<rect
|
||||
style="color:#000000;fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880729;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="color:#000000;fill:#969696;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect2840-3-4-0-8"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
@@ -160,7 +160,7 @@
|
||||
y="59.61282"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ff7f2a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287753;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287753;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
@@ -168,7 +168,7 @@
|
||||
y="28.888771"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ff7f2a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287753;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287753;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-9"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
@@ -176,12 +176,12 @@
|
||||
y="28.866888"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#ff9955;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 14.241527,19.294108 37.07818,27.781829 25.002993,38.181657 2.1663398,29.693936 14.241527,19.294108 z"
|
||||
id="rect2840-3-5-3-5"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:#ff9955;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 39.224174,28.454727 62.060827,36.942448 49.98564,47.342276 27.148987,38.854555 39.224174,28.454727 z"
|
||||
id="rect2840-3-5-3"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
@@ -191,7 +191,7 @@
|
||||
id="path3849"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#ff7f2a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287753;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.03287752999999993;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-3"
|
||||
width="24.362967"
|
||||
height="12.482594"
|
||||
@@ -199,7 +199,7 @@
|
||||
y="13.847153"
|
||||
transform="matrix(0.93735109,0.34838619,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727000000005;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#969696;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-3-4"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
@@ -207,7 +207,7 @@
|
||||
y="90.392708"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
<rect
|
||||
style="color:#000000;fill:#aa4400;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#969696;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.14880727000000005;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dashoffset:0"
|
||||
id="rect2840-3-4-0"
|
||||
width="15.936329"
|
||||
height="12.585408"
|
||||
@@ -215,7 +215,7 @@
|
||||
y="62.458496"
|
||||
transform="matrix(0.7577145,-0.65258619,0,1,0,0)" />
|
||||
<path
|
||||
style="color:#000000;fill:#ff9955;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
style="color:#000000;fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994000000003;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 28.74952,9.541872 51.586172,18.029593 39.510985,28.429421 16.674332,19.9417 28.74952,9.541872 z"
|
||||
id="rect2840-3-5"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -155,6 +155,26 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_8">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, when 2 similar walls are being connected, their underlying sketches will be joined into one, and the two walls will become one</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Join walls base sketches when possible</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>joinWallSketches</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -164,18 +184,38 @@
|
||||
<string>IFC import</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_5">
|
||||
<property name="toolTip">
|
||||
<string>Check this to display debug messages while importing IFC files</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show debug messages</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ifcDebug</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, the IFCOpenShell importer will be used, allowing to import more IFC types</string>
|
||||
<string>If this is checked, IFC files will always be imported with the internal python parser, even if IfcOpenShell is installed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use IFCOpenShell if available</string>
|
||||
<string>Force python parser</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>useIfcOpenShell</cstring>
|
||||
<cstring>forceIfcPythonParser</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
@@ -221,6 +261,76 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_6">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, openings will be imported as subtractions, otherwise wall shapes will already have their openings subtracted</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Separate openings</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ifcSeparateOpenings</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_7">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, object names will be prefixed with the IFC ID number</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Prefix names with ID number</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ifcPrefixNumbers</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Exclude list: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefLineEdit" name="gui::preflineedit">
|
||||
<property name="toolTip">
|
||||
<string>A comma-separated list of Ifc entities to exclude from import</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>IfcSpace,IfcBuildingElementProxy,IfcFlowTerminal</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ifcSkip</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -326,6 +436,11 @@
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefDoubleSpinBox</class>
|
||||
<extends>QDoubleSpinBox</extends>
|
||||
|
||||
@@ -29,9 +29,8 @@ __author__ = "Yorik van Havre"
|
||||
__url__ = "http://free-cad.sourceforge.net"
|
||||
|
||||
# config
|
||||
DEBUG = True
|
||||
subtractiveTypes = ["IfcOpeningElement"] # elements that must be subtracted from their parents
|
||||
SCHEMA = "http://www.steptools.com/support/stdev_docs/express/ifc2x3/ifc2x3_tc1.exp"
|
||||
SKIP = ["IfcOpeningElement","IfcSpace"]
|
||||
# end config
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
@@ -43,14 +42,7 @@ def open(filename):
|
||||
doc = FreeCAD.newDocument(docname)
|
||||
doc.Label = decode(docname)
|
||||
FreeCAD.ActiveDocument = doc
|
||||
global createIfcGroups, useIfcOpenShell, importIfcFurniture
|
||||
createIfcGroups = useIfcOpenShell = importIfcFurniture = False
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
useIfcOpenShell = p.GetBool("useIfcOpenShell")
|
||||
createIfcGroups = p.GetBool("createIfcGroups")
|
||||
importIfcFurniture = p.GetBool("importIfcFurniture")
|
||||
if not importIfcFurniture:
|
||||
SKIP.append("IfcFurnishingElement")
|
||||
getConfig()
|
||||
read(filename)
|
||||
return doc
|
||||
|
||||
@@ -61,40 +53,31 @@ def insert(filename,docname):
|
||||
except:
|
||||
doc = FreeCAD.newDocument(docname)
|
||||
FreeCAD.ActiveDocument = doc
|
||||
global createIfcGroups, useIfcOpenShell, importIfcFurniture
|
||||
createIfcGroups = useIfcOpenShell = importIfcFurniture = False
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
useIfcOpenShell = p.GetBool("useIfcOpenShell")
|
||||
createIfcGroups = p.GetBool("createIfcGroups")
|
||||
importIfcFurniture = p.GetBool("importIfcFurniture")
|
||||
if not importIfcFurniture:
|
||||
SKIP.append("IfcFurnishingElement")
|
||||
getConfig()
|
||||
read(filename)
|
||||
return doc
|
||||
|
||||
def decode(name):
|
||||
"decodes encoded strings"
|
||||
try:
|
||||
decodedName = (name.decode("utf8"))
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
decodedName = (name.decode("latin1"))
|
||||
except UnicodeDecodeError:
|
||||
FreeCAD.Console.PrintError(str(translate("Arch", "Error: Couldn't determine character encoding\n")))
|
||||
decodedName = name
|
||||
return decodedName
|
||||
|
||||
def getSchema():
|
||||
"retrieves the express schema"
|
||||
p = None
|
||||
p = os.path.join(FreeCAD.ConfigGet("UserAppData"),SCHEMA.split('/')[-1])
|
||||
if os.path.exists(p):
|
||||
return p
|
||||
import ArchCommands
|
||||
p = ArchCommands.download(SCHEMA)
|
||||
if p:
|
||||
return p
|
||||
return None
|
||||
|
||||
def getConfig():
|
||||
"Gets Arch IFC import preferences"
|
||||
global CREATE_IFC_GROUPS, IMPORT_IFC_FURNITURE, DEBUG, SKIP, PREFIX_NUMBERS, FORCE_PYTHON_PARSER, SEPARATE_OPENINGS
|
||||
CREATE_IFC_GROUPS = False
|
||||
IMPORT_IFC_FURNITURE = False
|
||||
DEBUG = False
|
||||
SKIP = ["IfcSpace","IfcBuildingElementProxy","IfcFlowTerminal"]
|
||||
PREFIX_NUMBERS = False
|
||||
FORCE_PYTHON_PARSER = False
|
||||
SEPARATE_OPENINGS = False
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
CREATE_IFC_GROUPS = p.GetBool("createIfcGroups")
|
||||
IMPORT_IFC_FURNITURE = p.GetBool("importIfcFurniture")
|
||||
FORCE_PYTHON_PARSER = p.GetBool("forceIfcPythonParser")
|
||||
DEBUG = p.GetBool("ifcDebug")
|
||||
SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings")
|
||||
PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers")
|
||||
skiplist = p.GetString("ifcSkip")
|
||||
if skiplist:
|
||||
SKIP = skiplist.split(",")
|
||||
|
||||
|
||||
def getIfcOpenShell():
|
||||
"locates and imports ifcopenshell"
|
||||
@@ -112,194 +95,226 @@ def read(filename):
|
||||
|
||||
# parsing the IFC file
|
||||
t1 = time.time()
|
||||
schema=getSchema()
|
||||
if schema:
|
||||
if DEBUG: global ifc
|
||||
if DEBUG: print "opening",filename,"..."
|
||||
ifc = ifcReader.IfcDocument(filename,schema=schema,debug=DEBUG)
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning(str(translate("Arch","IFC Schema not found, IFC import disabled.\n")))
|
||||
return None
|
||||
t2 = time.time()
|
||||
if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1))
|
||||
num_lines = sum(1 for line in pyopen(filename))
|
||||
|
||||
if useIfcOpenShell and getIfcOpenShell():
|
||||
if getIfcOpenShell() and not FORCE_PYTHON_PARSER:
|
||||
# use the IfcOpenShell parser
|
||||
|
||||
# preparing IfcOpenShell
|
||||
if DEBUG: global ifcObjects,ifcParents
|
||||
ifcObjects = {} # a table to relate ifc id with freecad object
|
||||
ifcParents = {} # a table to relate ifc id with parent id
|
||||
if not IMPORT_IFC_FURNITURE:
|
||||
SKIP.append("IfcFurnishingElement")
|
||||
if hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS") and SEPARATE_OPENINGS:
|
||||
IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS,True)
|
||||
else:
|
||||
SKIP.append("IfcOpeningElement")
|
||||
useShapes = False
|
||||
if hasattr(IfcImport,"USE_BREP_DATA"):
|
||||
IfcImport.Settings(IfcImport.USE_BREP_DATA,True)
|
||||
useShapes = True
|
||||
else:
|
||||
if DEBUG: print "Warning: IfcOpenShell version very old, unable to handle Brep data"
|
||||
|
||||
# processing geometry
|
||||
if IfcImport.Init(filename):
|
||||
while True:
|
||||
|
||||
obj = IfcImport.Get()
|
||||
if DEBUG: print "parsing ",obj.id,": ",obj.name," of type ",obj.type
|
||||
if DEBUG: print "["+str(int((float(obj.id)/num_lines)*100))+"%] parsing ",obj.id,": ",obj.name," of type ",obj.type
|
||||
meshdata = []
|
||||
|
||||
# retrieving name
|
||||
n = obj.name
|
||||
if not n:
|
||||
n = "Unnamed"
|
||||
|
||||
# build shape
|
||||
shape = None
|
||||
if useShapes:
|
||||
shape = getShape(obj)
|
||||
|
||||
n = getName(obj)
|
||||
|
||||
# skip types
|
||||
if obj.type in SKIP:
|
||||
pass
|
||||
|
||||
# walls
|
||||
elif obj.type == "IfcWallStandardCase":
|
||||
makeWall(ifc.Entities[obj.id],shape)
|
||||
|
||||
# windows
|
||||
elif obj.type in ["IfcWindow","IfcDoor"]:
|
||||
makeWindow(ifc.Entities[obj.id],shape)
|
||||
|
||||
# structs
|
||||
elif obj.type in ["IfcBeam","IfcColumn","IfcSlab"]:
|
||||
makeStructure(ifc.Entities[obj.id],shape)
|
||||
|
||||
# furniture
|
||||
elif obj.type == "IfcFurnishingElement":
|
||||
nobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Furniture")
|
||||
nobj.Shape = shape
|
||||
|
||||
elif shape:
|
||||
# treat as dumb parts
|
||||
nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n)
|
||||
nobj.Shape = shape
|
||||
if DEBUG: print "skipping because type is in skip list"
|
||||
nobj = None
|
||||
|
||||
else:
|
||||
# treat as meshes
|
||||
me,pl = getMesh(obj)
|
||||
nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n)
|
||||
nobj.Mesh = me
|
||||
nobj.Placement = pl
|
||||
# build shape
|
||||
shape = None
|
||||
if useShapes:
|
||||
shape = getShape(obj)
|
||||
|
||||
# walls
|
||||
if obj.type in ["IfcWallStandardCase","IfcWall"]:
|
||||
nobj = makeWall(obj.id,shape,n)
|
||||
|
||||
# windows
|
||||
elif obj.type in ["IfcWindow","IfcDoor"]:
|
||||
nobj = makeWindow(obj.id,shape,n)
|
||||
|
||||
# structs
|
||||
elif obj.type in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]:
|
||||
nobj = makeStructure(obj.id,shape,n)
|
||||
|
||||
# roofs
|
||||
elif obj.type in ["IfcRoof"]:
|
||||
nobj = makeRoof(obj.id,shape,n)
|
||||
|
||||
# furniture
|
||||
elif obj.type in ["IfcFurnishingElement"]:
|
||||
nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n)
|
||||
nobj.Shape = shape
|
||||
|
||||
# sites
|
||||
elif obj.type in ["IfcSite"]:
|
||||
nobj = makeSite(obj.id,shape,n)
|
||||
|
||||
elif shape:
|
||||
# treat as dumb parts
|
||||
#if DEBUG: print "Fixme: Shape-containing object not handled: ",obj.id, " ", obj.type
|
||||
nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n)
|
||||
nobj.Shape = shape
|
||||
|
||||
else:
|
||||
# treat as meshes
|
||||
if DEBUG: print "Warning: Object without shape: ",obj.id, " ", obj.type
|
||||
me,pl = getMesh(obj)
|
||||
nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n)
|
||||
nobj.Mesh = me
|
||||
nobj.Placement = pl
|
||||
|
||||
# registering object number and parent
|
||||
if obj.parent_id > 0:
|
||||
ifcParents[obj.id] = [obj.parent_id,not (obj.type in subtractiveTypes)]
|
||||
ifcObjects[obj.id] = nobj
|
||||
|
||||
if not IfcImport.Next():
|
||||
break
|
||||
|
||||
# processing non-geometry and relationships
|
||||
parents_temp = dict(ifcParents)
|
||||
import ArchCommands
|
||||
|
||||
while parents_temp:
|
||||
id, c = parents_temp.popitem()
|
||||
parent_id = c[0]
|
||||
additive = c[1]
|
||||
|
||||
if (id <= 0) or (parent_id <= 0):
|
||||
# root dummy object
|
||||
parent = None
|
||||
|
||||
elif parent_id in ifcObjects:
|
||||
parent = ifcObjects[parent_id]
|
||||
# check if parent is a subtraction, if yes parent to grandparent
|
||||
if parent_id in ifcParents:
|
||||
if ifcParents[parent_id][1] == False:
|
||||
grandparent_id = ifcParents[parent_id][0]
|
||||
if grandparent_id in ifcObjects:
|
||||
parent = ifcObjects[grandparent_id]
|
||||
else:
|
||||
# creating parent if needed
|
||||
parent_ifcobj = IfcImport.GetObject(parent_id)
|
||||
if DEBUG: print "["+str(int((float(parent_ifcobj.id)/num_lines)*100))+"%] parsing ",parent_ifcobj.id,": ",parent_ifcobj.name," of type ",parent_ifcobj.type
|
||||
n = getName(parent_ifcobj)
|
||||
if parent_ifcobj.id <= 0:
|
||||
parent = None
|
||||
elif parent_ifcobj.type == "IfcBuildingStorey":
|
||||
parent = Arch.makeFloor(name=n)
|
||||
elif parent_ifcobj.type == "IfcBuilding":
|
||||
parent = Arch.makeBuilding(name=n)
|
||||
elif parent_ifcobj.type == "IfcSite":
|
||||
parent = Arch.makeSite(name=n)
|
||||
elif parent_ifcobj.type == "IfcWindow":
|
||||
parent = Arch.makeWindow(name=n)
|
||||
else:
|
||||
if DEBUG: print "Fixme: skipping unhandled parent: ", parent_ifcobj.id, " ", parent_ifcobj.type
|
||||
parent = None
|
||||
# registering object number and parent
|
||||
if parent_ifcobj.parent_id > 0:
|
||||
ifcParents[parent_ifcobj.id] = [parent_ifcobj.parent_id,True]
|
||||
parents_temp[parent_ifcobj.id] = [parent_ifcobj.parent_id,True]
|
||||
if parent and (not parent_ifcobj.id in ifcObjects):
|
||||
ifcObjects[parent_ifcobj.id] = parent
|
||||
|
||||
# attributing parent
|
||||
if parent and (id in ifcObjects):
|
||||
if ifcObjects[id]:
|
||||
if additive:
|
||||
ArchCommands.addComponents(ifcObjects[id],parent)
|
||||
else:
|
||||
ArchCommands.removeComponents(ifcObjects[id],parent)
|
||||
|
||||
IfcImport.CleanUp()
|
||||
|
||||
else:
|
||||
# use only the internal python parser
|
||||
|
||||
FreeCAD.Console.PrintWarning(str(translate("Arch","IfcOpenShell not found, falling back on internal parser.\n")))
|
||||
schema=getSchema()
|
||||
if schema:
|
||||
if DEBUG: global ifc
|
||||
if DEBUG: print "opening",filename,"..."
|
||||
ifc = ifcReader.IfcDocument(filename,schema=schema,debug=DEBUG)
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning(str(translate("Arch","IFC Schema not found, IFC import disabled.\n")))
|
||||
return None
|
||||
t2 = time.time()
|
||||
if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1))
|
||||
|
||||
# getting walls
|
||||
for w in ifc.getEnt("IfcWallStandardCase"):
|
||||
makeWall(w)
|
||||
nobj = makeWall(w)
|
||||
|
||||
# getting windows and doors
|
||||
for w in (ifc.getEnt("IfcWindow") + ifc.getEnt("IfcDoor")):
|
||||
makeWindow(w)
|
||||
nobj = makeWindow(w)
|
||||
|
||||
# getting structs
|
||||
for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn")):
|
||||
makeStructure(w)
|
||||
for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn") \
|
||||
+ ifc.getEnt("IfcFooting")):
|
||||
nobj = makeStructure(w)
|
||||
|
||||
# getting floors
|
||||
for f in ifc.getEnt("IfcBuildingStorey"):
|
||||
group(f,ifc,"Floor")
|
||||
|
||||
order(ifc)
|
||||
# getting buildings
|
||||
for b in ifc.getEnt("IfcBuilding"):
|
||||
group(b,ifc,"Building")
|
||||
|
||||
# getting sites
|
||||
for s in ifc.getEnt("IfcSite"):
|
||||
group(s,ifc,"Site")
|
||||
|
||||
if DEBUG: print "done parsing. Recomputing..."
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
t3 = time.time()
|
||||
if DEBUG: print "done processing",ifc,"in %s s" % ((t3-t1))
|
||||
if DEBUG: print "done processing IFC file in %s s" % ((t3-t1))
|
||||
|
||||
return None
|
||||
|
||||
def order(ifc):
|
||||
"orders the already generated elements by building and by floor"
|
||||
|
||||
# getting floors
|
||||
for f in ifc.getEnt("IfcBuildingStorey"):
|
||||
group(f,"Floor")
|
||||
# getting buildings
|
||||
for b in ifc.getEnt("IfcBuilding"):
|
||||
group(b,"Building")
|
||||
# getting sites
|
||||
for s in ifc.getEnt("IfcSite"):
|
||||
group(s,"Site")
|
||||
def getName(ifcobj):
|
||||
"Get a clean name from an ifc object"
|
||||
n = ifcobj.name
|
||||
if not n:
|
||||
n = ifcobj.type
|
||||
if PREFIX_NUMBERS:
|
||||
n = "ID"+str(ifcobj.id)+" "+n
|
||||
#for c in ",.!?;:":
|
||||
# n = n.replace(c,"_")
|
||||
return n
|
||||
|
||||
def group(entity,mode=None):
|
||||
"gathers the children of the given entity"
|
||||
|
||||
try:
|
||||
if DEBUG: print "=====> making group",entity.id
|
||||
placement = None
|
||||
placement = getPlacement(entity.ObjectPlacement)
|
||||
if DEBUG: print "got cell placement",entity.id,":",placement
|
||||
subelements = ifc.find("IFCRELCONTAINEDINSPATIALSTRUCTURE","RelatingStructure",entity)
|
||||
subelements.extend(ifc.find("IFCRELAGGREGATES","RelatingObject",entity))
|
||||
elts = []
|
||||
for s in subelements:
|
||||
if hasattr(s,"RelatedElements"):
|
||||
s = s.RelatedElements
|
||||
if not isinstance(s,list): s = [s]
|
||||
elts.extend(s)
|
||||
elif hasattr(s,"RelatedObjects"):
|
||||
s = s.RelatedObjects
|
||||
if not isinstance(s,list): s = [s]
|
||||
elts.extend(s)
|
||||
elif hasattr(s,"RelatedObject"):
|
||||
s = s.RelatedObject
|
||||
if not isinstance(s,list): s = [s]
|
||||
elts.extend(s)
|
||||
print "found dependent elements: ",elts
|
||||
|
||||
groups = [['Wall','IfcWallStandardCase',[]],
|
||||
['Window','IfcWindow',[]],
|
||||
['Door','IfcDoor',[]],
|
||||
['Slab','IfcSlab',[]],
|
||||
['Beam','IfcBeam',[]],
|
||||
['Column','IfcColumn',[]],
|
||||
['Floor','IfcBuildingStorey',[]],
|
||||
['Building','IfcBuilding',[]],
|
||||
['Furniture','IfcFurnishingElement',[]]]
|
||||
|
||||
for e in elts:
|
||||
for g in groups:
|
||||
if e.type.upper() == g[1].upper():
|
||||
o = FreeCAD.ActiveDocument.getObject(g[0] + str(e.id))
|
||||
if o:
|
||||
g[2].append(o)
|
||||
print "groups:",groups
|
||||
|
||||
comps = []
|
||||
if createIfcGroups:
|
||||
if DEBUG: print "creating subgroups"
|
||||
for g in groups:
|
||||
if g[2]:
|
||||
if g[0] in ['Building','Floor']:
|
||||
comps.extend(g[2])
|
||||
else:
|
||||
fcg = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup",g[0]+"s")
|
||||
for o in g[2]:
|
||||
fcg.addObject(o)
|
||||
comps.append(fcg)
|
||||
else:
|
||||
for g in groups:
|
||||
comps.extend(g[2])
|
||||
|
||||
name = mode + str(entity.id)
|
||||
if mode == "Site":
|
||||
cell = Arch.makeSite(comps,name=name)
|
||||
elif mode == "Floor":
|
||||
cell = Arch.makeFloor(comps,name=name)
|
||||
elif mode == "Building":
|
||||
cell = Arch.makeBuilding(comps,name=name)
|
||||
except:
|
||||
if DEBUG: print "error: skipping group ",entity.id
|
||||
|
||||
def makeWall(entity,shape=None):
|
||||
def makeWall(entity,shape=None,name="Wall"):
|
||||
"makes a wall in the freecad document"
|
||||
try:
|
||||
if DEBUG: print "=====> making wall",entity.id
|
||||
if shape:
|
||||
sh = FreeCAD.ActiveDocument.addObject("Part::Feature","WallBody")
|
||||
sh.Shape = shape
|
||||
wall = Arch.makeWall(sh,name="Wall"+str(entity.id))
|
||||
if DEBUG: print "made wall object ",entity.id,":",wall
|
||||
return
|
||||
# use ifcopenshell
|
||||
body = FreeCAD.ActiveDocument.addObject("Part::Feature","WallBody")
|
||||
body.Shape = shape
|
||||
wall = Arch.makeWall(body,name=name)
|
||||
wall.Label = name
|
||||
if DEBUG: print "made wall object ",entity,":",wall
|
||||
return wall
|
||||
|
||||
# use internal parser
|
||||
if DEBUG: print "=====> making wall",entity.id
|
||||
placement = wall = wire = body = width = height = None
|
||||
placement = getPlacement(entity.ObjectPlacement)
|
||||
if DEBUG: print "got wall placement",entity.id,":",placement
|
||||
@@ -324,19 +339,27 @@ def makeWall(entity,shape=None):
|
||||
wall.Normal = norm
|
||||
if wall:
|
||||
if DEBUG: print "made wall object ",entity.id,":",wall
|
||||
return wall
|
||||
if DEBUG: print "error: skipping wall",entity.id
|
||||
return None
|
||||
except:
|
||||
if DEBUG: print "error: skipping wall",entity.id
|
||||
return None
|
||||
|
||||
def makeWindow(entity,shape=None):
|
||||
|
||||
def makeWindow(entity,shape=None,name="Window"):
|
||||
"makes a window in the freecad document"
|
||||
try:
|
||||
typ = "Window" if entity.type == "IFCWINDOW" else "Door"
|
||||
if DEBUG: print "=====> making window",entity.id
|
||||
if shape:
|
||||
window = Arch.makeWindow(name=typ+str(entity.id))
|
||||
# use ifcopenshell
|
||||
window = Arch.makeWindow(name=name)
|
||||
window.Shape = shape
|
||||
if DEBUG: print "made window object ",entity.id,":",window
|
||||
return
|
||||
window.Label = name
|
||||
if DEBUG: print "made window object ",entity,":",window
|
||||
return window
|
||||
|
||||
# use internal parser
|
||||
if DEBUG: print "=====> making window",entity.id
|
||||
placement = window = wire = body = width = height = None
|
||||
placement = getPlacement(entity.ObjectPlacement)
|
||||
if DEBUG: print "got window placement",entity.id,":",placement
|
||||
@@ -347,29 +370,31 @@ def makeWindow(entity,shape=None):
|
||||
for b in r.Items:
|
||||
if b.type == "IFCEXTRUDEDAREASOLID":
|
||||
wire = getWire(b.SweptArea,placement)
|
||||
window = Arch.makeWindow(wire,width=b.Depth,name=typ+str(entity.id))
|
||||
window = Arch.makeWindow(wire,width=b.Depth,name=objtype+str(entity.id))
|
||||
if window:
|
||||
if DEBUG: print "made window object ",entity.id,":",window
|
||||
return window
|
||||
if DEBUG: print "error: skipping window",entity.id
|
||||
return None
|
||||
except:
|
||||
if DEBUG: print "error: skipping window",entity.id
|
||||
return None
|
||||
|
||||
def makeStructure(entity,shape=None):
|
||||
|
||||
def makeStructure(entity,shape=None,name="Structure"):
|
||||
"makes a structure in the freecad document"
|
||||
try:
|
||||
if entity.type == "IFCSLAB":
|
||||
typ = "Slab"
|
||||
elif entity.type == "IFCBEAM":
|
||||
typ = "Beam"
|
||||
else:
|
||||
typ = "Column"
|
||||
|
||||
if DEBUG: print "=====> making struct",entity.id
|
||||
if shape:
|
||||
# use ifcopenshell
|
||||
sh = FreeCAD.ActiveDocument.addObject("Part::Feature","StructureBody")
|
||||
sh.Shape = shape
|
||||
structure = Arch.makeStructure(sh,name=typ+str(entity.id))
|
||||
if DEBUG: print "made structure object ",entity.id,":",structure
|
||||
return
|
||||
structure = Arch.makeStructure(sh,name=name)
|
||||
structure.Label = name
|
||||
if DEBUG: print "made structure object ",entity,":",structure
|
||||
return structure
|
||||
|
||||
# use internal parser
|
||||
if DEBUG: print "=====> making struct",entity.id
|
||||
placement = structure = wire = body = width = height = None
|
||||
placement = getPlacement(entity.ObjectPlacement)
|
||||
if DEBUG: print "got window placement",entity.id,":",placement
|
||||
@@ -380,13 +405,46 @@ def makeStructure(entity,shape=None):
|
||||
for b in r.Items:
|
||||
if b.type == "IFCEXTRUDEDAREASOLID":
|
||||
wire = getWire(b.SweptArea,placement)
|
||||
structure = Arch.makeStructure(wire,height=b.Depth,name=typ+str(entity.id))
|
||||
structure = Arch.makeStructure(wire,height=b.Depth,name=objtype+str(entity.id))
|
||||
if structure:
|
||||
if DEBUG: print "made structure object ",entity.id,":",structure
|
||||
return structure
|
||||
if DEBUG: print "error: skipping structure",entity.id
|
||||
return None
|
||||
except:
|
||||
if DEBUG: print "error: skipping structure",entity.id
|
||||
return None
|
||||
|
||||
|
||||
def makeSite(entity,shape=None,name="Site"):
|
||||
"makes a site in the freecad document"
|
||||
try:
|
||||
if shape:
|
||||
# use ifcopenshell
|
||||
site = Arch.makeSite(name=name)
|
||||
site.Label = name
|
||||
body = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
|
||||
body.Shape = shape
|
||||
site.Terrain = body
|
||||
if DEBUG: print "made site object ",entity,":",site
|
||||
return site
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def makeRoof(entity,shape=None,name="Roof"):
|
||||
"makes a roof in the freecad document"
|
||||
try:
|
||||
if shape:
|
||||
# use ifcopenshell
|
||||
roof = Arch.makeRoof(name=name)
|
||||
roof.Label = name
|
||||
roof.Shape = shape
|
||||
if DEBUG: print "made roof object ",entity,":",roof
|
||||
return roof
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
# geometry helpers ###################################################################
|
||||
|
||||
def getMesh(obj):
|
||||
@@ -412,20 +470,133 @@ def getMesh(obj):
|
||||
|
||||
def getShape(obj):
|
||||
"gets a shape from an IfcOpenShell object"
|
||||
import StringIO
|
||||
import StringIO,Part
|
||||
sh=Part.Shape()
|
||||
sh.importBrep(StringIO.StringIO(obj.mesh.brep_data))
|
||||
if not sh.Solids:
|
||||
# try to extract a solid shape
|
||||
if sh.Faces:
|
||||
try:
|
||||
if DEBUG: print "Malformed solid. Attempting to fix..."
|
||||
shell = Part.makeShell(sh.Faces)
|
||||
if shell:
|
||||
solid = Part.makeSolid(shell)
|
||||
if solid:
|
||||
sh = solid
|
||||
except:
|
||||
if DEBUG: print "failed to retrieve solid from object ",obj.id
|
||||
else:
|
||||
if DEBUG: print "object ", obj.id, " doesn't contain any face"
|
||||
m = obj.matrix
|
||||
mat = FreeCAD.Matrix(m[0], m[3], m[6], m[9],
|
||||
m[1], m[4], m[7], m[10],
|
||||
m[2], m[5], m[8], m[11],
|
||||
0, 0, 0, 1)
|
||||
sh.Placement = FreeCAD.Placement(mat)
|
||||
if DEBUG: print "getting Shape from ",obj
|
||||
# if DEBUG: print "getting Shape from ",obj
|
||||
return sh
|
||||
|
||||
# below is only used by the internal parser #########################################
|
||||
|
||||
def decode(name):
|
||||
"decodes encoded strings"
|
||||
try:
|
||||
decodedName = (name.decode("utf8"))
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
decodedName = (name.decode("latin1"))
|
||||
except UnicodeDecodeError:
|
||||
FreeCAD.Console.PrintError(str(translate("Arch", "Error: Couldn't determine character encoding\n")))
|
||||
decodedName = name
|
||||
return decodedName
|
||||
|
||||
def getSchema():
|
||||
"retrieves the express schema"
|
||||
p = None
|
||||
p = os.path.join(FreeCAD.ConfigGet("UserAppData"),SCHEMA.split('/')[-1])
|
||||
if os.path.exists(p):
|
||||
return p
|
||||
import ArchCommands
|
||||
p = ArchCommands.download(SCHEMA)
|
||||
if p:
|
||||
return p
|
||||
return None
|
||||
|
||||
def group(entity,ifc,mode=None):
|
||||
"gathers the children of the given entity"
|
||||
# only used by internal parser
|
||||
|
||||
try:
|
||||
if DEBUG: print "=====> making group",entity.id
|
||||
placement = None
|
||||
placement = getPlacement(entity.ObjectPlacement)
|
||||
if DEBUG: print "got cell placement",entity.id,":",placement
|
||||
subelements = ifc.find("IFCRELCONTAINEDINSPATIALSTRUCTURE","RelatingStructure",entity)
|
||||
subelements.extend(ifc.find("IFCRELAGGREGATES","RelatingObject",entity))
|
||||
elts = []
|
||||
for s in subelements:
|
||||
if hasattr(s,"RelatedElements"):
|
||||
s = s.RelatedElements
|
||||
if not isinstance(s,list): s = [s]
|
||||
elts.extend(s)
|
||||
elif hasattr(s,"RelatedObjects"):
|
||||
s = s.RelatedObjects
|
||||
if not isinstance(s,list): s = [s]
|
||||
elts.extend(s)
|
||||
elif hasattr(s,"RelatedObject"):
|
||||
s = s.RelatedObject
|
||||
if not isinstance(s,list): s = [s]
|
||||
elts.extend(s)
|
||||
print "found dependent elements: ",elts
|
||||
|
||||
groups = [['Wall',['IfcWallStandardCase'],[]],
|
||||
['Window',['IfcWindow','IfcDoor'],[]],
|
||||
['Structure',['IfcSlab','IfcFooting','IfcBeam','IfcColumn'],[]],
|
||||
['Floor',['IfcBuildingStorey'],[]],
|
||||
['Building',['IfcBuilding'],[]],
|
||||
['Furniture',['IfcFurnishingElement'],[]]]
|
||||
|
||||
for e in elts:
|
||||
for g in groups:
|
||||
for t in g[1]:
|
||||
if e.type.upper() == t.upper():
|
||||
if hasattr(FreeCAD.ActiveDocument,g[0]+str(e.id)):
|
||||
g[2].append(FreeCAD.ActiveDocument.getObject(g[0]+str(e.id)))
|
||||
print "groups:",groups
|
||||
|
||||
comps = []
|
||||
if CREATE_IFC_GROUPS:
|
||||
if DEBUG: print "creating subgroups"
|
||||
for g in groups:
|
||||
if g[2]:
|
||||
if g[0] in ['Building','Floor']:
|
||||
comps.extend(g[2])
|
||||
else:
|
||||
fcg = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup",g[0]+"s")
|
||||
for o in g[2]:
|
||||
fcg.addObject(o)
|
||||
comps.append(fcg)
|
||||
else:
|
||||
for g in groups:
|
||||
comps.extend(g[2])
|
||||
|
||||
label = entity.Name
|
||||
name = mode + str(entity.id)
|
||||
cell = None
|
||||
if mode == "Site":
|
||||
cell = Arch.makeSite(comps,name=name)
|
||||
elif mode == "Floor":
|
||||
cell = Arch.makeFloor(comps,name=name)
|
||||
elif mode == "Building":
|
||||
cell = Arch.makeBuilding(comps,name=name)
|
||||
if label and cell:
|
||||
cell.Label = label
|
||||
except:
|
||||
if DEBUG: print "error: skipping group ",entity.id
|
||||
|
||||
def getWire(entity,placement=None):
|
||||
"returns a wire (created in the freecad document) from the given entity"
|
||||
# only used by internal parser
|
||||
if DEBUG: print "making Wire from :",entity
|
||||
if not entity: return None
|
||||
if entity.type == "IFCPOLYLINE":
|
||||
@@ -441,6 +612,7 @@ def getWire(entity,placement=None):
|
||||
|
||||
def getPlacement(entity):
|
||||
"returns a placement from the given entity"
|
||||
# only used by internal parser
|
||||
if DEBUG: print "getting placement ",entity
|
||||
if not entity: return None
|
||||
pl = None
|
||||
@@ -468,6 +640,7 @@ def getPlacement(entity):
|
||||
|
||||
def getVector(entity):
|
||||
"returns a vector from the given entity"
|
||||
# only used by internal parser
|
||||
if DEBUG: print "getting point from",entity
|
||||
if entity.type == "IFCDIRECTION":
|
||||
if len(entity.DirectionRatios) == 3:
|
||||
|
||||
@@ -1200,10 +1200,11 @@ def offset(obj,delta,copy=False,bind=False,sym=False,occ=False):
|
||||
select(obj)
|
||||
return newobj
|
||||
|
||||
def draftify(objectslist,makeblock=False):
|
||||
'''draftify(objectslist,[makeblock]): turns each object of the given list
|
||||
def draftify(objectslist,makeblock=False,delete=True):
|
||||
'''draftify(objectslist,[makeblock],[delete]): turns each object of the given list
|
||||
(objectslist can also be a single object) into a Draft parametric
|
||||
wire. If makeblock is True, multiple objects will be grouped in a block'''
|
||||
wire. If makeblock is True, multiple objects will be grouped in a block.
|
||||
If delete = False, old objects are not deleted'''
|
||||
import DraftGeomUtils, Part
|
||||
|
||||
if not isinstance(objectslist,list):
|
||||
@@ -1226,7 +1227,8 @@ def draftify(objectslist,makeblock=False):
|
||||
nobj.ViewObject.DisplayMode = "Wireframe"
|
||||
newobjlist.append(nobj)
|
||||
formatObject(nobj,obj)
|
||||
FreeCAD.ActiveDocument.removeObject(obj.Name)
|
||||
if delete:
|
||||
FreeCAD.ActiveDocument.removeObject(obj.Name)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
if makeblock:
|
||||
return makeBlock(newobjlist)
|
||||
@@ -1731,8 +1733,521 @@ def heal(objlist=None,delete=True,reparent=True):
|
||||
if dellist and delete:
|
||||
for n in dellist:
|
||||
FreeCAD.ActiveDocument.removeObject(n)
|
||||
|
||||
def upgrade(objects,delete=False,force=None):
|
||||
"""upgrade(objects,delete=False,force=None): Upgrades the given object(s) (can be
|
||||
an object or a list of objects). If delete is True, old objects are deleted.
|
||||
The force attribute can be used to
|
||||
force a certain way of upgrading. It can be: makeCompound, closeGroupWires,
|
||||
makeSolid, closeWire, turnToParts, makeFusion, makeShell, makeFaces, draftify,
|
||||
joinFaces, makeSketchFace, makeWires
|
||||
Returns a dictionnary containing two lists, a list of new objects and a list
|
||||
of objects to be deleted"""
|
||||
|
||||
import Part, DraftGeomUtils
|
||||
from DraftTools import msg,translate
|
||||
|
||||
if not isinstance(objects,list):
|
||||
objects = [objects]
|
||||
|
||||
global deleteList, newList
|
||||
deleteList = []
|
||||
addList = []
|
||||
|
||||
# definitions of actions to perform
|
||||
|
||||
def makeCompound(objectslist):
|
||||
"""returns a compound object made from the given objects"""
|
||||
newobj = makeBlock(objectslist)
|
||||
addList.append(newobj)
|
||||
return newobj
|
||||
|
||||
def closeGroupWires(groupslist):
|
||||
"""closes every open wire in the given groups"""
|
||||
result = False
|
||||
for grp in groupslist:
|
||||
for obj in grp.Group:
|
||||
newobj = closeWire(obj)
|
||||
# add new objects to their respective groups
|
||||
if newobj:
|
||||
result = True
|
||||
grp.addObject(newobj)
|
||||
return result
|
||||
|
||||
def makeSolid(obj):
|
||||
"""turns an object into a solid, if possible"""
|
||||
if obj.Shape.Solids:
|
||||
return None
|
||||
sol = None
|
||||
try:
|
||||
sol = Part.makeSolid(obj.Shape)
|
||||
except:
|
||||
return None
|
||||
else:
|
||||
if sol:
|
||||
if sol.isClosed():
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Solid")
|
||||
newobj.Shape = sol
|
||||
addList.append(newobj)
|
||||
deleteList.append(obj)
|
||||
return newob
|
||||
|
||||
def closeWire(obj):
|
||||
"""closes a wire object, if possible"""
|
||||
if obj.Shape.Faces:
|
||||
return None
|
||||
if len(obj.Shape.Wires) != 1:
|
||||
return None
|
||||
if len(obj.Shape.Edges) == 1:
|
||||
return None
|
||||
if getType(obj) == "Wire":
|
||||
obj.Closed = True
|
||||
return True
|
||||
else:
|
||||
w = obj.Shape.Wires[0]
|
||||
if not w.isClosed():
|
||||
edges = w.Edges
|
||||
p0 = w.Vertexes[0].Point
|
||||
p1 = w.Vertexes[-1].Point
|
||||
if p0 == p1:
|
||||
# sometimes an open wire can have its start and end points identical (OCC bug)
|
||||
# in that case, although it is not closed, face works...
|
||||
f = Part.Face(w)
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Face")
|
||||
newobj.Shape = f
|
||||
else:
|
||||
edges.append(Part.Line(p1,p0).toShape())
|
||||
w = Part.Wire(DraftGeomUtils.sortEdges(edges))
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Wire")
|
||||
newobj.Shape = w
|
||||
addList.append(newobj)
|
||||
deleteList.append(obj)
|
||||
return newobj
|
||||
else:
|
||||
return None
|
||||
|
||||
def turnToParts(meshes):
|
||||
"""turn given meshes to parts"""
|
||||
result = False
|
||||
import Arch
|
||||
for mesh in meshes:
|
||||
sh = Arch.getShapeFromMesh(mesh.Mesh)
|
||||
if sh:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Shell")
|
||||
newobj.Shape = sh
|
||||
addList.append(newobj)
|
||||
deleteList.append(mesh)
|
||||
result = True
|
||||
return result
|
||||
|
||||
def makeFusion(obj1,obj2):
|
||||
"""makes a Draft or Part fusion between 2 given objects"""
|
||||
newobj = fuse(obj1,obj2)
|
||||
if newobj:
|
||||
addList.append(newobj)
|
||||
return newobj
|
||||
return None
|
||||
|
||||
def makeShell(objectslist):
|
||||
"""makes a shell with the given objects"""
|
||||
faces = []
|
||||
for obj in objectslist:
|
||||
faces.append(obj.Shape.Faces)
|
||||
sh = Part.makeShell(faces)
|
||||
if sh:
|
||||
if sh.Faces:
|
||||
newob = FreeCAD.ActiveDocument.addObject("Part::Feature","Shell")
|
||||
newob.Shape = sh
|
||||
addList.append(newobj)
|
||||
deleteList.extend(objectslist)
|
||||
return newobj
|
||||
return None
|
||||
|
||||
def joinFaces(objectslist):
|
||||
"""makes one big face from selected objects, if possible"""
|
||||
faces = []
|
||||
for obj in objectslist:
|
||||
faces.append(obj.Shape.Faces)
|
||||
u = faces.pop(0)
|
||||
for f in faces:
|
||||
u = u.fuse(f)
|
||||
if DraftGeomUtils.isCoplanar(faces):
|
||||
u = DraftGeomUtils.concatenate(u)
|
||||
if not DraftGeomUtils.hasCurves(u):
|
||||
# several coplanar and non-curved faces: they can becoem a Draft wire
|
||||
newobj = makeWire(u.Wires[0],closed=True,face=True)
|
||||
else:
|
||||
# if not possible, we do a non-parametric union
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Union")
|
||||
newobj.Shape = u
|
||||
addList.append(newobj)
|
||||
deleteList.extend(objectslist)
|
||||
return newobj
|
||||
return None
|
||||
|
||||
def makeSketchFace(obj):
|
||||
"""Makes a Draft face out of a sketch"""
|
||||
newobj = makeWire(obj.Shape,closed=True)
|
||||
if newobj:
|
||||
newobj.Base = obj
|
||||
obj.ViewObject.Visibility = False
|
||||
addList.append(newobj)
|
||||
return newobj
|
||||
return None
|
||||
|
||||
def makeFaces(objectslist):
|
||||
"""make a face from every closed wire in the list"""
|
||||
result = False
|
||||
for o in objectslist:
|
||||
for w in o.Shape.Wires:
|
||||
if w.isClosed() and DraftGeomUtils.isPlanar(w):
|
||||
f = Part.Face(w)
|
||||
if f:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Face")
|
||||
newobj.Shape = f
|
||||
addList.append(newobj)
|
||||
result = True
|
||||
if not o in deleteList:
|
||||
deleteList.append(o)
|
||||
return result
|
||||
|
||||
def makeWires(objectslist):
|
||||
"""joins edges in the given objects list into wires"""
|
||||
edges = []
|
||||
for o in objectslist:
|
||||
for e in o.Shape.Edges:
|
||||
edges.append(e)
|
||||
try:
|
||||
nedges = DraftGeomUtils.sortEdges(edges[:])
|
||||
# for e in nedges: print "debug: ",e.Curve,e.Vertexes[0].Point,e.Vertexes[-1].Point
|
||||
w = Part.Wire(nedges)
|
||||
except:
|
||||
return None
|
||||
else:
|
||||
if len(w.Edges) == len(edges):
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Wire")
|
||||
newobj.Shape = w
|
||||
addList.append(newobj)
|
||||
deleteList.extend(objectslist)
|
||||
return True
|
||||
return None
|
||||
|
||||
# analyzing what we have in our selection
|
||||
|
||||
edges = []
|
||||
wires = []
|
||||
openwires = []
|
||||
faces = []
|
||||
groups = []
|
||||
parts = []
|
||||
curves = []
|
||||
facewires = []
|
||||
loneedges = []
|
||||
meshes = []
|
||||
for ob in objects:
|
||||
if ob.Type == "App::DocumentObjectGroup":
|
||||
groups.append(ob)
|
||||
elif ob.isDerivedFrom("Part::Feature"):
|
||||
parts.append(ob)
|
||||
faces.extend(ob.Shape.Faces)
|
||||
wires.extend(ob.Shape.Wires)
|
||||
edges.extend(ob.Shape.Edges)
|
||||
for f in ob.Shape.Faces:
|
||||
facewires.extend(f.Wires)
|
||||
wirededges = []
|
||||
for w in ob.Shape.Wires:
|
||||
if len(w.Edges) > 1:
|
||||
for e in w.Edges:
|
||||
wirededges.append(e.hashCode())
|
||||
if not w.isClosed():
|
||||
openwires.append(w)
|
||||
for e in ob.Shape.Edges:
|
||||
if not isinstance(e.Curve,Part.Line):
|
||||
curves.append(e)
|
||||
if not e.hashCode() in wirededges:
|
||||
loneedges.append(e)
|
||||
elif ob.isDerivedFrom("Mesh::Feature"):
|
||||
meshes.append(ob)
|
||||
objects = parts
|
||||
|
||||
#print "objects:",objects," edges:",edges," wires:",wires," openwires:",openwires," faces:",faces
|
||||
#print "groups:",groups," curves:",curves," facewires:",facewires, "loneedges:", loneedges
|
||||
|
||||
if force:
|
||||
if force in ["makeCompound","closeGroupWires","makeSolid","closeWire","turnToParts","makeFusion",
|
||||
"makeShell","makeFaces","draftify","joinFaces","makeSketchFace","makeWires"]:
|
||||
result = eval(force)(objects)
|
||||
else:
|
||||
msg(translate("Upgrade: Unknow force method:")+" "+force)
|
||||
result = None
|
||||
|
||||
else:
|
||||
|
||||
# applying transformations automatically
|
||||
|
||||
result = None
|
||||
|
||||
# if we have a group: turn each closed wire inside into a face
|
||||
if groups:
|
||||
result = closeGroupWires(groups)
|
||||
if result: msg(translate("draft", "Found groups: closing each open object inside\n"))
|
||||
|
||||
# if we have meshes, we try to turn them into shapes
|
||||
elif meshes:
|
||||
result = turnToParts(meshes)
|
||||
if result: msg(translate("draft", "Found mesh(es): turning into Part shapes\n"))
|
||||
|
||||
# we have only faces here, no lone edges
|
||||
elif faces and (len(wires) + len(openwires) == len(facewires)):
|
||||
|
||||
# we have one shell: we try to make a solid
|
||||
if (len(objects) == 1) and (len(faces) > 3):
|
||||
result = makeSolid(objects[0])
|
||||
if result: msg(translate("draft", "Found 1 solidificable object: solidifying it\n"))
|
||||
|
||||
# we have exactly 2 objects: we fuse them
|
||||
elif (len(objects) == 2) and (not curves):
|
||||
result = makeFusion(objects[0],objects[1])
|
||||
if result: msg(translate("draft", "Found 2 objects: fusing them\n"))
|
||||
|
||||
# we have many separate faces: we try to make a shell
|
||||
elif (len(objects) > 2) and (len(faces) > 1) and (not loneedges):
|
||||
result = makeShell(objects)
|
||||
if result: msg(translate("draft", "Found several objects: making a shell\n"))
|
||||
|
||||
# we have faces: we try to join them if they are coplanar
|
||||
elif len(faces) > 1:
|
||||
result = joinFaces(objects)
|
||||
if result: msg(translate("draft", "Found several coplanar objects or faces: making one face\n"))
|
||||
|
||||
# only one object: if not parametric, we "draftify" it
|
||||
elif len(objects) == 1 and (not objects[0].isDerivedFrom("Part::Part2DObjectPython")):
|
||||
result = draftify(objects[0])
|
||||
if result: msg(translate("draft", "Found 1 non-parametric objects: draftifying it\n"))
|
||||
|
||||
# we have only closed wires, no faces
|
||||
elif wires and (not faces) and (not openwires):
|
||||
|
||||
# we have a sketch: Extract a face
|
||||
if (len(objects) == 1) and objects[0].isDerivedFrom("Sketcher::SketchObject") and (not curves):
|
||||
result = makeSketchFace(objects[0])
|
||||
if result: msg(translate("draft", "Found 1 closed sketch object: making a face from it\n"))
|
||||
|
||||
# only closed wires
|
||||
else:
|
||||
result = makeFaces(objects)
|
||||
if result: msg(translate("draft", "Found closed wires: making faces\n"))
|
||||
|
||||
# special case, we have only one open wire. We close it, unless it has only 1 edge!"
|
||||
elif (len(openwires) == 1) and (not faces) and (not loneedges):
|
||||
result = closeWire(objects[0])
|
||||
if result: msg(translate("draft", "Found 1 open wire: closing it\n"))
|
||||
|
||||
# only open wires and edges: we try to join their edges
|
||||
elif openwires and (not wires) and (not faces):
|
||||
result = makeWires(objects)
|
||||
if result: msg(translate("draft", "Found several open wires: joining them\n"))
|
||||
|
||||
# only loneedges: we try to join them
|
||||
elif loneedges and (not facewires):
|
||||
result = makeWires(objects)
|
||||
if result: msg(translate("draft", "Found several edges: wiring them\n"))
|
||||
|
||||
# all other cases, if more than 1 object, make a compound
|
||||
elif (len(objects) > 1):
|
||||
result = makeCompound(objects)
|
||||
if result: msg(translate("draft", "Found several non-treatable objects: making compound\n"))
|
||||
|
||||
# no result has been obtained
|
||||
if not result:
|
||||
msg(translate("draft", "Unable to upgrade these objects\n"))
|
||||
|
||||
if delete:
|
||||
names = []
|
||||
for o in deleteList:
|
||||
names.append(o.Name)
|
||||
deleteList = []
|
||||
for n in names:
|
||||
FreeCAD.ActiveDocument.removeObject(n)
|
||||
|
||||
return [addList,deleteList]
|
||||
|
||||
def downgrade(objects,delete=False,force=None):
|
||||
"""downgrade(objects,delete=False,force=None): Downgrades the given object(s) (can be
|
||||
an object or a list of objects). If delete is True, old objects are deleted.
|
||||
The force attribute can be used to
|
||||
force a certain way of downgrading. It can be: explode, shapify, subtr,
|
||||
splitFaces, cut2, getWire, splitWires.
|
||||
Returns a dictionnary containing two lists, a list of new objects and a list
|
||||
of objects to be deleted"""
|
||||
|
||||
import Part, DraftGeomUtils
|
||||
from DraftTools import msg,translate
|
||||
|
||||
if not isinstance(objects,list):
|
||||
objects = [objects]
|
||||
|
||||
global deleteList, newList
|
||||
deleteList = []
|
||||
addList = []
|
||||
|
||||
# actions definitions
|
||||
|
||||
def explode(obj):
|
||||
"""explodes a Draft block"""
|
||||
pl = obj.Placement
|
||||
newobj = []
|
||||
for o in obj.Components:
|
||||
o.ViewObject.Visibility = True
|
||||
o.Placement = o.Placement.multiply(pl)
|
||||
if newobj:
|
||||
deleteList(obj)
|
||||
return newobj
|
||||
return None
|
||||
|
||||
def cut2(objects):
|
||||
"""cuts first object from the last one"""
|
||||
newobj = cut(objects[0],objects[1])
|
||||
if newobj:
|
||||
addList.append(newobj)
|
||||
return newobj
|
||||
return None
|
||||
|
||||
def splitFaces(objects):
|
||||
"""split faces contained in objects into new objects"""
|
||||
result = False
|
||||
for o in objects:
|
||||
if o.Shape.Faces:
|
||||
for f in o.Shape.Faces:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Face")
|
||||
newobj.Shape = f
|
||||
addList.append(newobj)
|
||||
result = True
|
||||
deleteList.append(o)
|
||||
return result
|
||||
|
||||
def subtr(objects):
|
||||
"""subtracts objects from the first one"""
|
||||
faces = []
|
||||
for o in objects:
|
||||
if o.Shape.Faces:
|
||||
faces.append(o.Shape.Faces)
|
||||
deleteList.append(o)
|
||||
u = faces.pop(0)
|
||||
for f in faces:
|
||||
u = u.cut(f)
|
||||
if not u.isNull():
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Subtraction")
|
||||
newobj.Shape = u
|
||||
addList.append(newobj)
|
||||
return newobj
|
||||
return None
|
||||
|
||||
def getWire(obj):
|
||||
"""gets the wire from a face object"""
|
||||
result = False
|
||||
for w in obj.Shape.Faces[0].Wires:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Wire")
|
||||
newobj.Shape = w
|
||||
addList.append(newobj)
|
||||
result = True
|
||||
deleteList.append(obj)
|
||||
return result
|
||||
|
||||
def splitWires(objects):
|
||||
"""splits the wires contained in objects into edges"""
|
||||
result = False
|
||||
for o in objects:
|
||||
if o.Shape.Edges:
|
||||
for e in o.Shape.Edges:
|
||||
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Edge")
|
||||
newobj.Shape = e
|
||||
addList.append(newobj)
|
||||
deleteList.append(o)
|
||||
result = True
|
||||
return result
|
||||
|
||||
# analyzing objects
|
||||
|
||||
faces = []
|
||||
edges = []
|
||||
onlyedges = True
|
||||
parts = []
|
||||
|
||||
for o in objects:
|
||||
if o.isDerivedFrom("Part::Feature"):
|
||||
for f in o.Shape.Faces:
|
||||
faces.append(f)
|
||||
for e in o.Shape.Edges:
|
||||
edges.append(e)
|
||||
if o.Shape.ShapeType != "Edge":
|
||||
onlyedges = False
|
||||
parts.append(o)
|
||||
objects = parts
|
||||
|
||||
if force:
|
||||
if force in ["explode","shapify","subtr","splitFaces","cut2","getWire","splitWires"]:
|
||||
result = eval(force)(objects)
|
||||
else:
|
||||
msg(translate("Upgrade: Unknow force method:")+" "+force)
|
||||
result = None
|
||||
|
||||
else:
|
||||
|
||||
# applying transformation automatically
|
||||
|
||||
# we have a block, we explode it
|
||||
if (len(objects) == 1) and (getType(objects[0]) == "Block"):
|
||||
result = explode(objects[0])
|
||||
if result: msg(translate("draft", "Found 1 block: exploding it\n"))
|
||||
|
||||
# special case, we have one parametric object: we "de-parametrize" it
|
||||
elif (len(objects) == 1) and (objects[0].isDerivedFrom("Part::Feature")) and ("Base" in objects[0].PropertiesList):
|
||||
result = shapify(objects[0])
|
||||
if result: msg(translate("draft", "Found 1 parametric object: breaking its dependencies\n"))
|
||||
|
||||
# we have only 2 objects: cut 2nd from 1st
|
||||
elif len(objects) == 2:
|
||||
result = cut2(objects)
|
||||
if result: msg(translate("draft", "Found 2 objects: subtracting them\n"))
|
||||
|
||||
elif (len(faces) > 1):
|
||||
|
||||
# one object with several faces: split it
|
||||
if len(objects) == 1:
|
||||
result = splitFaces(objects)
|
||||
if result: msg(translate("draft", "Found several faces: splitting them\n"))
|
||||
|
||||
# several objects: remove all the faces from the first one
|
||||
else:
|
||||
result = subtr(objects)
|
||||
if result: msg(translate("draft", "Found several objects: subtracting them from the first one\n"))
|
||||
|
||||
# only one face: we extract its wires
|
||||
elif (len(faces) > 0):
|
||||
result = getWire(objects[0])
|
||||
if result: msg(translate("draft", "Found 1 face: extracting its wires\n"))
|
||||
|
||||
# no faces: split wire into single edges
|
||||
elif not onlyedges:
|
||||
result = splitWires(objects)
|
||||
if result: msg(translate("draft", "Found only wires: extracting their edges\n"))
|
||||
|
||||
# no result has been obtained
|
||||
if not result:
|
||||
msg(translate("draft", "No more downgrade possible\n"))
|
||||
|
||||
if delete:
|
||||
names = []
|
||||
for o in deleteList:
|
||||
names.append(o.Name)
|
||||
deleteList = []
|
||||
for n in names:
|
||||
FreeCAD.ActiveDocument.removeObject(n)
|
||||
|
||||
return [addList,deleteList]
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Python Features definitions
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
@@ -2127,17 +2127,9 @@ class Offset(Modifier):
|
||||
'Draft.offset(FreeCAD.ActiveDocument.'+self.sel.Name+','+d+',copy='+str(copymode)+',occ='+str(occmode)+')'])
|
||||
self.finish()
|
||||
|
||||
|
||||
|
||||
class Upgrade(Modifier):
|
||||
'''The Draft_Upgrade FreeCAD command definition.
|
||||
This class upgrades selected objects in different ways,
|
||||
following this list (in order):
|
||||
- if there are more than one faces, the faces are merged (union)
|
||||
- if there is only one face, nothing is done
|
||||
- if there are closed wires, they are transformed in a face
|
||||
- otherwise join all edges into a wire (closed if applicable)
|
||||
- if nothing of the above is possible, a Compound is created
|
||||
'''
|
||||
'''The Draft_Upgrade FreeCAD command definition.'''
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Draft_Upgrade',
|
||||
@@ -2154,268 +2146,19 @@ class Upgrade(Modifier):
|
||||
self.call = self.view.addEventCallback("SoEvent",selectObject)
|
||||
else:
|
||||
self.proceed()
|
||||
|
||||
def compound(self):
|
||||
# shapeslist = []
|
||||
# for ob in self.sel: shapeslist.append(ob.Shape)
|
||||
# newob = self.doc.addObject("Part::Feature","Compound")
|
||||
# newob.Shape = Part.makeCompound(shapeslist)
|
||||
newob = Draft.makeBlock(self.sel)
|
||||
self.nodelete = True
|
||||
return newob
|
||||
|
||||
|
||||
def proceed(self):
|
||||
if self.call: self.view.removeEventCallback("SoEvent",self.call)
|
||||
self.sel = Draft.getSelection()
|
||||
newob = None
|
||||
self.nodelete = False
|
||||
edges = []
|
||||
wires = []
|
||||
openwires = []
|
||||
faces = []
|
||||
groups = []
|
||||
curves = []
|
||||
facewires = []
|
||||
loneedges = 0
|
||||
|
||||
# determining what we have in our selection
|
||||
for ob in self.sel:
|
||||
if ob.Type == "App::DocumentObjectGroup":
|
||||
groups.append(ob)
|
||||
else:
|
||||
if ob.Shape.ShapeType == 'Edge': openwires.append(ob.Shape)
|
||||
for f in ob.Shape.Faces:
|
||||
faces.append(f)
|
||||
facewires.extend(f.Wires)
|
||||
wedges = 0
|
||||
for w in ob.Shape.Wires:
|
||||
wedges += len(w.Edges)
|
||||
if w.isClosed():
|
||||
wires.append(w)
|
||||
else:
|
||||
openwires.append(w)
|
||||
if wedges < len(ob.Shape.Edges):
|
||||
loneedges += (len(ob.Shape.Edges)-wedges)
|
||||
for e in ob.Shape.Edges:
|
||||
if not isinstance(e.Curve,Part.Line):
|
||||
curves.append(e)
|
||||
lastob = ob
|
||||
# print "objects:",self.sel," edges:",edges," wires:",wires," openwires:",openwires," faces:",faces
|
||||
# print "groups:",groups," curves:",curves," facewires:",facewires
|
||||
|
||||
# applying transformation
|
||||
self.doc.openTransaction("Upgrade")
|
||||
|
||||
if groups:
|
||||
# if we have a group: turn each closed wire inside into a face
|
||||
msg(translate("draft", "Found groups: closing each open object inside\n"))
|
||||
for grp in groups:
|
||||
for ob in grp.Group:
|
||||
if not ob.Shape.Faces:
|
||||
for w in ob.Shape.Wires:
|
||||
newob = Draft.makeWire(w,closed=w.isClosed())
|
||||
self.sel.append(ob)
|
||||
grp.addObject(newob)
|
||||
|
||||
elif faces and (len(wires)+len(openwires)==len(facewires)):
|
||||
# we have only faces here, no lone edges
|
||||
|
||||
if (len(self.sel) == 1) and (len(faces) > 1):
|
||||
# we have a shell: we try to make a solid
|
||||
sol = Part.makeSolid(self.sel[0].Shape)
|
||||
if sol.isClosed():
|
||||
msg(translate("draft", "Found 1 solidificable object: solidifying it\n"))
|
||||
newob = self.doc.addObject("Part::Feature","Solid")
|
||||
newob.Shape = sol
|
||||
Draft.formatObject(newob,lastob)
|
||||
|
||||
elif (len(self.sel) == 2) and (not curves):
|
||||
# we have exactly 2 objects: we fuse them
|
||||
msg(translate("draft", "Found 2 objects: fusing them\n"))
|
||||
newob = Draft.fuse(self.sel[0],self.sel[1])
|
||||
self.nodelete = True
|
||||
|
||||
elif (len(self.sel) > 2) and (len(faces) > 6):
|
||||
# we have many separate faces: we try to make a shell
|
||||
sh = Part.makeShell(faces)
|
||||
newob = self.doc.addObject("Part::Feature","Shell")
|
||||
newob.Shape = sh
|
||||
Draft.formatObject(newob,lastob)
|
||||
|
||||
elif (len(self.sel) > 2) or (len(faces) > 1):
|
||||
# more than 2 objects or faces: we try the draft way: make one face out of them
|
||||
u = faces.pop(0)
|
||||
for f in faces:
|
||||
u = u.fuse(f)
|
||||
if DraftGeomUtils.isCoplanar(faces):
|
||||
if self.sel[0].ViewObject.DisplayMode == "Wireframe":
|
||||
f = False
|
||||
else:
|
||||
f = True
|
||||
u = DraftGeomUtils.concatenate(u)
|
||||
if not curves:
|
||||
# several coplanar and non-curved faces: they can becoem a Draft wire
|
||||
msg(translate("draft", "Found several objects or faces: making a parametric face\n"))
|
||||
newob = Draft.makeWire(u.Wires[0],closed=True,face=f)
|
||||
Draft.formatObject(newob,lastob)
|
||||
else:
|
||||
# if not possible, we do a non-parametric union
|
||||
msg(translate("draft", "Found objects containing curves: fusing them\n"))
|
||||
newob = self.doc.addObject("Part::Feature","Union")
|
||||
newob.Shape = u
|
||||
Draft.formatObject(newob,lastob)
|
||||
else:
|
||||
# if not possible, we do a non-parametric union
|
||||
msg(translate("draft", "Found several objects: fusing them\n"))
|
||||
# if we have a solid, make sure we really return a solid
|
||||
if (len(u.Faces) > 1) and u.isClosed():
|
||||
u = Part.makeSolid(u)
|
||||
newob = self.doc.addObject("Part::Feature","Union")
|
||||
newob.Shape = u
|
||||
Draft.formatObject(newob,lastob)
|
||||
elif len(self.sel) == 1:
|
||||
# only one object: if not parametric, we "draftify" it
|
||||
self.nodelete = True
|
||||
if (not curves) and (Draft.getType(self.sel[0]) == "Part"):
|
||||
msg(translate("draft", "Found 1 non-parametric objects: draftifying it\n"))
|
||||
Draft.draftify(self.sel[0])
|
||||
else:
|
||||
msg(translate("draft", "No upgrade available for this object\n"))
|
||||
self.doc.abortTransaction()
|
||||
return
|
||||
else:
|
||||
msg(translate("draft", "Couldn't upgrade these objects\n"))
|
||||
self.doc.abortTransaction()
|
||||
return
|
||||
|
||||
elif wires and (not faces) and (not openwires):
|
||||
# we have only wires, no faces
|
||||
|
||||
if (len(self.sel) == 1) and self.sel[0].isDerivedFrom("Sketcher::SketchObject") and (not curves):
|
||||
# we have a sketch
|
||||
msg(translate("draft", "Found 1 closed sketch object: making a face from it\n"))
|
||||
newob = Draft.makeWire(self.sel[0].Shape,closed=True)
|
||||
newob.Base = self.sel[0]
|
||||
self.sel[0].ViewObject.Visibility = False
|
||||
self.nodelete = True
|
||||
|
||||
else:
|
||||
# only closed wires
|
||||
for w in wires:
|
||||
if DraftGeomUtils.isPlanar(w):
|
||||
f = Part.Face(w)
|
||||
faces.append(f)
|
||||
else:
|
||||
msg(translate("draft", "One wire is not planar, upgrade not done\n"))
|
||||
self.nodelete = True
|
||||
for f in faces:
|
||||
# if there are curved segments, we do a non-parametric face
|
||||
msg(translate("draft", "Found a closed wire: making a face\n"))
|
||||
newob = self.doc.addObject("Part::Feature","Face")
|
||||
newob.Shape = f
|
||||
Draft.formatObject(newob,lastob)
|
||||
newob.ViewObject.DisplayMode = "Flat Lines"
|
||||
|
||||
elif (len(openwires) == 1) and (not faces) and (not wires) and (not loneedges):
|
||||
# special case, we have only one open wire. We close it, unless it has only 1 edge!"
|
||||
p0 = openwires[0].Vertexes[0].Point
|
||||
p1 = openwires[0].Vertexes[-1].Point
|
||||
if p0 == p1:
|
||||
# sometimes an open wire can have its start and end points identical (OCC bug)
|
||||
# in that case, although it is not closed, face works...
|
||||
f = Part.Face(openwires[0])
|
||||
msg(translate("draft", "Found a closed wire: making a face\n"))
|
||||
newob = self.doc.addObject("Part::Feature","Face")
|
||||
newob.Shape = f
|
||||
Draft.formatObject(newob,lastob)
|
||||
newob.ViewObject.DisplayMode = "Flat Lines"
|
||||
else:
|
||||
edges = openwires[0].Edges
|
||||
if len(edges) > 1:
|
||||
edges.append(Part.Line(p1,p0).toShape())
|
||||
w = Part.Wire(DraftGeomUtils.sortEdges(edges))
|
||||
if len(edges) == 1:
|
||||
if len(w.Vertexes) == 2:
|
||||
msg(translate("draft", "Found 1 open edge: making a line\n"))
|
||||
newob = Draft.makeWire(w,closed=False)
|
||||
elif len(w.Vertexes) == 1:
|
||||
msg(translate("draft", "Found 1 circular edge: making a circle\n"))
|
||||
c = w.Edges[0].Curve.Center
|
||||
r = w.Edges[0].Curve.Radius
|
||||
p = FreeCAD.Placement()
|
||||
p.move(c)
|
||||
newob = Draft.makeCircle(r,p)
|
||||
else:
|
||||
msg(translate("draft", "Found 1 open wire: closing it\n"))
|
||||
if not curves:
|
||||
newob = Draft.makeWire(w,closed=True)
|
||||
else:
|
||||
# if not possible, we do a non-parametric union
|
||||
newob = self.doc.addObject("Part::Feature","Wire")
|
||||
newob.Shape = w
|
||||
Draft.formatObject(newob,lastob)
|
||||
if self.call:
|
||||
self.view.removeEventCallback("SoEvent",self.call)
|
||||
if Draft.getSelection():
|
||||
self.commit(translate("draft","Upgrade"),
|
||||
['import Draft',
|
||||
'Draft.upgrade(FreeCADGui.Selection.getSelection(),delete=True)'])
|
||||
self.finish()
|
||||
|
||||
elif openwires and (not wires) and (not faces):
|
||||
# only open wires and edges: we try to join their edges
|
||||
for ob in self.sel:
|
||||
for e in ob.Shape.Edges:
|
||||
edges.append(e)
|
||||
newob = None
|
||||
nedges = DraftGeomUtils.sortEdges(edges[:])
|
||||
#for e in nedges: print "debug: ",e.Curve,e.Vertexes[0].Point,e.Vertexes[-1].Point
|
||||
try:
|
||||
w = Part.Wire(nedges)
|
||||
except:
|
||||
msg(translate("draft", "Error: unable to join edges\n"))
|
||||
else:
|
||||
if len(w.Edges) == len(edges):
|
||||
msg(translate("draft", "Found several edges: wiring them\n"))
|
||||
newob = self.doc.addObject("Part::Feature","Wire")
|
||||
newob.Shape = w
|
||||
Draft.formatObject(newob,lastob)
|
||||
if not newob:
|
||||
if (len(self.sel) == 1) and (lastob.Shape.ShapeType == "Compound"):
|
||||
# the selected object is already a compound
|
||||
msg(translate("draft", "Unable to upgrade more\n"))
|
||||
self.nodelete = True
|
||||
else:
|
||||
# all other cases
|
||||
#print "no new object found"
|
||||
msg(translate("draft", "Found several non-connected edges: making compound\n"))
|
||||
newob = self.compound()
|
||||
Draft.formatObject(newob,lastob)
|
||||
else:
|
||||
if (len(self.sel) == 1) and (lastob.Shape.ShapeType == "Compound"):
|
||||
# the selected object is already a compound
|
||||
msg(translate("draft", "Unable to upgrade more\n"))
|
||||
self.nodelete = True
|
||||
else:
|
||||
# all other cases
|
||||
msg(translate("draft", "Found several non-treatable objects: making compound\n"))
|
||||
newob = self.compound()
|
||||
Draft.formatObject(newob,lastob)
|
||||
|
||||
if not self.nodelete:
|
||||
# deleting original objects, if needed
|
||||
for ob in self.sel:
|
||||
if not ob.Type == "App::DocumentObjectGroup":
|
||||
self.doc.removeObject(ob.Name)
|
||||
|
||||
self.doc.commitTransaction()
|
||||
if newob: Draft.select(newob)
|
||||
Modifier.finish(self)
|
||||
|
||||
|
||||
class Downgrade(Modifier):
|
||||
'''
|
||||
The Draft_Downgrade FreeCAD command definition.
|
||||
This class downgrades selected objects in different ways,
|
||||
following this list (in order):
|
||||
- if there are more than one faces, the subsequent
|
||||
faces are subtracted from the first one
|
||||
- if there is only one face, it gets converted to a wire
|
||||
- otherwise wires are exploded into single edges
|
||||
'''
|
||||
'''The Draft_Downgrade FreeCAD command definition.'''
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Draft_Downgrade',
|
||||
@@ -2434,95 +2177,13 @@ class Downgrade(Modifier):
|
||||
self.proceed()
|
||||
|
||||
def proceed(self):
|
||||
self.sel = Draft.getSelection()
|
||||
edges = []
|
||||
faces = []
|
||||
|
||||
# scanning objects
|
||||
for ob in self.sel:
|
||||
for f in ob.Shape.Faces:
|
||||
faces.append(f)
|
||||
for ob in self.sel:
|
||||
for e in ob.Shape.Edges:
|
||||
edges.append(e)
|
||||
lastob = ob
|
||||
|
||||
# applying transformation
|
||||
self.doc.openTransaction("Downgrade")
|
||||
|
||||
if (len(self.sel) == 1) and (Draft.getType(self.sel[0]) == "Block"):
|
||||
# we have a block, we explode it
|
||||
pl = self.sel[0].Placement
|
||||
newob = []
|
||||
for ob in self.sel[0].Components:
|
||||
ob.ViewObject.Visibility = True
|
||||
ob.Placement = ob.Placement.multiply(pl)
|
||||
newob.append(ob)
|
||||
self.doc.removeObject(self.sel[0].Name)
|
||||
|
||||
elif (len(self.sel) == 1) and (self.sel[0].isDerivedFrom("Part::Feature")) and ("Base" in self.sel[0].PropertiesList):
|
||||
# special case, we have one parametric object: we "de-parametrize" it
|
||||
msg(translate("draft", "Found 1 parametric object: breaking its dependencies\n"))
|
||||
newob = Draft.shapify(self.sel[0])
|
||||
|
||||
elif len(self.sel) == 2:
|
||||
# we have only 2 objects: cut 2nd from 1st
|
||||
msg(translate("draft", "Found 2 objects: subtracting them\n"))
|
||||
newob = Draft.cut(self.sel[0],self.sel[1])
|
||||
|
||||
elif (len(faces) > 1):
|
||||
|
||||
if len(self.sel) == 1:
|
||||
# one object with several faces: split it
|
||||
for f in faces:
|
||||
msg(translate("draft", "Found several faces: splitting them\n"))
|
||||
newob = self.doc.addObject("Part::Feature","Face")
|
||||
newob.Shape = f
|
||||
Draft.formatObject(newob,self.sel[0])
|
||||
self.doc.removeObject(ob.Name)
|
||||
|
||||
else:
|
||||
# several objects: remove all the faces from the first one
|
||||
msg(translate("draft", "Found several objects: subtracting them from the first one\n"))
|
||||
u = faces.pop(0)
|
||||
for f in faces:
|
||||
u = u.cut(f)
|
||||
newob = self.doc.addObject("Part::Feature","Subtraction")
|
||||
newob.Shape = u
|
||||
for ob in self.sel:
|
||||
Draft.formatObject(newob,ob)
|
||||
self.doc.removeObject(ob.Name)
|
||||
|
||||
elif (len(faces) > 0):
|
||||
# only one face: we extract its wires
|
||||
msg(translate("draft", "Found 1 face: extracting its wires\n"))
|
||||
for w in faces[0].Wires:
|
||||
newob = self.doc.addObject("Part::Feature","Wire")
|
||||
newob.Shape = w
|
||||
Draft.formatObject(newob,lastob)
|
||||
for ob in self.sel:
|
||||
self.doc.removeObject(ob.Name)
|
||||
|
||||
else:
|
||||
# no faces: split wire into single edges
|
||||
onlyedges = True
|
||||
for ob in self.sel:
|
||||
if ob.Shape.ShapeType != "Edge":
|
||||
onlyedges = False
|
||||
if onlyedges:
|
||||
msg(translate("draft", "No more downgrade possible\n"))
|
||||
self.doc.abortTransaction()
|
||||
return
|
||||
msg(translate("draft", "Found only wires: extracting their edges\n"))
|
||||
for ob in self.sel:
|
||||
for e in edges:
|
||||
newob = self.doc.addObject("Part::Feature","Edge")
|
||||
newob.Shape = e
|
||||
Draft.formatObject(newob,ob)
|
||||
self.doc.removeObject(ob.Name)
|
||||
self.doc.commitTransaction()
|
||||
Draft.select(newob)
|
||||
Modifier.finish(self)
|
||||
if self.call:
|
||||
self.view.removeEventCallback("SoEvent",self.call)
|
||||
if Draft.getSelection():
|
||||
self.commit(translate("draft","Downgrade"),
|
||||
['import Draft',
|
||||
'Draft.downgrade(FreeCADGui.Selection.getSelection(),delete=True)'])
|
||||
self.finish()
|
||||
|
||||
|
||||
class Trimex(Modifier):
|
||||
|
||||
@@ -29,121 +29,41 @@ class DraftWorkbench (Workbench):
|
||||
Icon = """
|
||||
/* XPM */
|
||||
static char * draft_xpm[] = {
|
||||
"14 16 96 2",
|
||||
" c None",
|
||||
". c #584605",
|
||||
"+ c #513E03",
|
||||
"@ c #E6B50D",
|
||||
"# c #C29F0E",
|
||||
"$ c #6E5004",
|
||||
"% c #F7BD0B",
|
||||
"& c #8F7008",
|
||||
"* c #F3C711",
|
||||
"= c #B1950F",
|
||||
"- c #785402",
|
||||
"; c #946C05",
|
||||
"> c #FABF0B",
|
||||
", c #F7C20E",
|
||||
"' c #8D740A",
|
||||
") c #F8D115",
|
||||
"! c #9F8A0F",
|
||||
"~ c #593D00",
|
||||
"{ c #FEB304",
|
||||
"] c #F3B208",
|
||||
"^ c #987407",
|
||||
"/ c #FDC70E",
|
||||
"( c #EFC311",
|
||||
"_ c #8F790C",
|
||||
": c #FBDA18",
|
||||
"< c #8B7C0F",
|
||||
"[ c #B88203",
|
||||
"} c #FEBA08",
|
||||
"| c #E7B00A",
|
||||
"1 c #A17E09",
|
||||
"2 c #FCCE12",
|
||||
"3 c #E6C213",
|
||||
"4 c #96830E",
|
||||
"5 c #FBE11C",
|
||||
"6 c #786F0F",
|
||||
"7 c #CA9406",
|
||||
"8 c #FDC10B",
|
||||
"9 c #D8AA0C",
|
||||
"0 c #AE8E0C",
|
||||
"a c #FCD415",
|
||||
"b c #DBBF15",
|
||||
"c c #A09012",
|
||||
"d c #F9E61F",
|
||||
"e c #69650E",
|
||||
"f c #4B3702",
|
||||
"g c #DAA609",
|
||||
"h c #CAA50E",
|
||||
"i c #BB9D10",
|
||||
"j c #FCDB18",
|
||||
"k c #CEB817",
|
||||
"l c #AB9E15",
|
||||
"m c #F2E821",
|
||||
"n c #5E5C0E",
|
||||
"o c #503D03",
|
||||
"p c #E8B60D",
|
||||
"q c #CAAF13",
|
||||
"r c #C1B218",
|
||||
"s c #B6AE19",
|
||||
"t c #EAE625",
|
||||
"u c #575723",
|
||||
"v c #594605",
|
||||
"w c #F1C511",
|
||||
"x c #AB9510",
|
||||
"y c #D7C018",
|
||||
"z c #FBE81F",
|
||||
"A c #B3AC18",
|
||||
"B c #BCB81D",
|
||||
"C c #7F8051",
|
||||
"D c #645207",
|
||||
"E c #9D8C11",
|
||||
"F c #E4D31C",
|
||||
"G c #BEB62F",
|
||||
"H c #6C6A3F",
|
||||
"I c #E1E1E1",
|
||||
"J c #73610A",
|
||||
"K c #7C720F",
|
||||
"L c #A1A084",
|
||||
"M c #FFFFFF",
|
||||
"N c #565656",
|
||||
"O c #887921",
|
||||
"P c #988F44",
|
||||
"Q c #BFBEB7",
|
||||
"R c #EEEEEC",
|
||||
"S c #C0C0C0",
|
||||
"T c #323232",
|
||||
"U c #4D4B39",
|
||||
"V c #C7C7C7",
|
||||
"W c #FBFBFB",
|
||||
"X c #BFBFBF",
|
||||
"Y c #141414",
|
||||
"Z c #222222",
|
||||
"` c #303030",
|
||||
" . c #313131",
|
||||
".. c #282828",
|
||||
"+. c #121212",
|
||||
"@. c #000000",
|
||||
" . ",
|
||||
" + @ # ",
|
||||
" $ % & * = ",
|
||||
" - ; > , ' ) ! ",
|
||||
"~ { ] ^ / ( _ : < ",
|
||||
" [ } | 1 2 3 4 5 6 ",
|
||||
" 7 8 9 0 a b c d e ",
|
||||
" f g / h i j k l m n ",
|
||||
" o p 2 i q 5 r s t u ",
|
||||
" v w a x y z A B C ",
|
||||
" D ) j E F G H I ",
|
||||
" J : 5 K L M M N ",
|
||||
" O P Q R M S T ",
|
||||
" U V W X Y Z ",
|
||||
" ` ...+.",
|
||||
" @.@.@.@.@.@.@.@. "};
|
||||
"""
|
||||
|
||||
"16 16 17 1",
|
||||
" c None",
|
||||
". c #5F4A1C",
|
||||
"+ c #5A4E36",
|
||||
"@ c #8A4D00",
|
||||
"# c #835A04",
|
||||
"$ c #7E711F",
|
||||
"% c #847954",
|
||||
"& c #C27400",
|
||||
"* c #817D74",
|
||||
"= c #E79300",
|
||||
"- c #BFAB0C",
|
||||
"; c #ADA791",
|
||||
"> c #B3AE87",
|
||||
", c #B0B2AE",
|
||||
"' c #ECD200",
|
||||
") c #D6D8D5",
|
||||
"! c #FCFEFA",
|
||||
" ,!!)!!!!!!!!!",
|
||||
" ,!!>;!!!!!!!!",
|
||||
" ,!!>-,!!!!!!!",
|
||||
" ,!!>'$)!!!!!!",
|
||||
" ,!!>-'%!!!!!!",
|
||||
" ,!!>-$-;!!!!!",
|
||||
" ,!!>-*-$)!!!!",
|
||||
" @&+!!>-*;-%!!!!",
|
||||
"@&=+)!;'-''-*!!!",
|
||||
".@@.;;%%....+;;!",
|
||||
".&&===========$,",
|
||||
".&&=====&&####.,",
|
||||
".&&.++***,,)))!!",
|
||||
"#==+)!!!!!!!!!!!",
|
||||
" ##+)!!!!!!!!!!!",
|
||||
" *,,,,,,,,,,,,"};"""
|
||||
|
||||
MenuText = "Draft"
|
||||
ToolTip = "The Draft module is used for basic 2D CAD Drafting"
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
@@ -11,25 +13,54 @@
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg5821"
|
||||
id="svg2980"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docname="preferences-Draft.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="Draft_Workbench_Idea2.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1"
|
||||
inkscape:export-filename="/home/yorik/Draft_Workbench_Idea16.png"
|
||||
inkscape:export-xdpi="22.5"
|
||||
inkscape:export-ydpi="22.5">
|
||||
<defs
|
||||
id="defs5823">
|
||||
id="defs2982">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6349">
|
||||
id="linearGradient3855">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
style="stop-color:#d07200;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6351" />
|
||||
id="stop3857" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
style="stop-color:#fcb200;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop6353" />
|
||||
id="stop3859" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3786"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#a0eb07;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3788" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3864">
|
||||
<stop
|
||||
id="stop3866"
|
||||
offset="0"
|
||||
style="stop-color:#71b2f8;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3868"
|
||||
offset="1"
|
||||
style="stop-color:#002795;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2988" />
|
||||
<linearGradient
|
||||
id="linearGradient3377">
|
||||
<stop
|
||||
@@ -43,31 +74,85 @@
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3377"
|
||||
id="linearGradient3383"
|
||||
x1="901.1875"
|
||||
y1="1190.875"
|
||||
x2="1267.9062"
|
||||
y2="1190.875"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective5829" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient3855"
|
||||
id="linearGradient3861"
|
||||
x1="3.9825215"
|
||||
y1="31.552309"
|
||||
x2="60.769054"
|
||||
y2="51.094166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.95198975,0,0,0.91651928,0.07298588,1.7291139)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6349"
|
||||
id="radialGradient6355"
|
||||
cx="1103.6399"
|
||||
cy="1424.4465"
|
||||
fx="1103.6399"
|
||||
fy="1424.4465"
|
||||
r="194.40614"
|
||||
gradientTransform="matrix(1.4307499,-1.3605156e-7,1.202713e-8,0.1264801,-475.3928,1244.2826)"
|
||||
xlink:href="#linearGradient3855"
|
||||
id="linearGradient3863"
|
||||
x1="3.9825215"
|
||||
y1="31.552309"
|
||||
x2="23.852976"
|
||||
y2="45.686504"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.95198975,0,0,0.91651928,0.07298588,1.7291139)" />
|
||||
<linearGradient
|
||||
gradientTransform="translate(63.406413,58.258077)"
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3855-2"
|
||||
id="linearGradient3861-4"
|
||||
x1="3.9825215"
|
||||
y1="31.552309"
|
||||
x2="60.769054"
|
||||
y2="51.094166"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient3855-2">
|
||||
<stop
|
||||
style="stop-color:#d07200;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3857-1" />
|
||||
<stop
|
||||
style="stop-color:#fcb200;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3859-6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3855-2"
|
||||
id="linearGradient3863-2"
|
||||
x1="3.9825215"
|
||||
y1="31.552309"
|
||||
x2="23.852976"
|
||||
y2="45.686504"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient3880">
|
||||
<stop
|
||||
style="stop-color:#d07200;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3882" />
|
||||
<stop
|
||||
style="stop-color:#fcb200;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3884" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="translate(63.406413,58.258077)"
|
||||
y2="45.686504"
|
||||
x2="23.852976"
|
||||
y1="31.552309"
|
||||
x1="3.9825215"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3889"
|
||||
xlink:href="#linearGradient3855-2"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3855-2"
|
||||
id="linearGradient3921"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(63.406413,58.258077)"
|
||||
x1="3.9825215"
|
||||
y1="31.552309"
|
||||
x2="23.852976"
|
||||
y2="45.686504" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
@@ -76,25 +161,30 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="13.770759"
|
||||
inkscape:cy="33.3857"
|
||||
inkscape:current-layer="g3360"
|
||||
inkscape:zoom="3.8890873"
|
||||
inkscape:cx="40.657951"
|
||||
inkscape:cy="30.318818"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1278"
|
||||
inkscape:window-height="723"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1057"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="19" />
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="true" />
|
||||
<metadata
|
||||
id="metadata5826">
|
||||
id="metadata2985">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -102,56 +192,44 @@
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g3360"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
|
||||
inkscape:export-xdpi="3.2478156"
|
||||
inkscape:export-ydpi="3.2478156"
|
||||
transform="matrix(0.1367863,0,0,0.1367863,-119.15519,-134.86962)">
|
||||
<path
|
||||
inkscape:export-ydpi="6.2926431"
|
||||
inkscape:export-xdpi="6.2926431"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path3385"
|
||||
d="M 1242.2722,1225.5972 L 1267.0061,1252.4449 L 1293.1685,1414.2927 L 1139.29,1378.3753 L 1103.2685,1339.6008"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#333333;stroke-width:10.00100156000000062;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:export-ydpi="6.2926431"
|
||||
inkscape:export-xdpi="6.2926431"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
|
||||
id="rect2390"
|
||||
d="M 1038.5,1003.9062 L 906.1875,1125.9375 L 1138.5312,1377.8438 C 1136.5381,1373.6971 1135.4375,1369.1125 1135.4375,1364.2812 C 1135.4374,1345.8803 1151.5176,1330.9688 1171.3125,1330.9688 C 1176.6723,1330.9688 1181.7449,1332.0701 1186.3125,1334.0312 L 1188.4688,1332.0312 C 1187.8006,1329.4882 1187.4375,1326.8233 1187.4375,1324.0938 C 1187.4375,1305.6928 1203.4863,1290.75 1223.2812,1290.75 C 1226.3231,1290.75 1229.2726,1291.1148 1232.0938,1291.7812 L 1239.5938,1284.875 C 1239.1763,1282.8514 1238.9375,1280.7597 1238.9375,1278.625 C 1238.9375,1264.1088 1248.9625,1251.784 1262.9062,1247.2188 L 1038.5,1003.9062 z"
|
||||
style="opacity:1;fill:url(#linearGradient3383);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:10.00100156000000062;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:export-ydpi="6.2926431"
|
||||
inkscape:export-xdpi="6.2926431"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
|
||||
id="path3373"
|
||||
d="M 1236.4267,1288.7379 L 1005.1018,1040.2404"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#7b5600;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:export-ydpi="6.2926431"
|
||||
inkscape:export-xdpi="6.2926431"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
|
||||
id="path3375"
|
||||
d="M 1185.9191,1331.1643 L 958.63474,1081.6566"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#7b5600;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:export-ydpi="6.2926431"
|
||||
inkscape:export-xdpi="6.2926431"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
|
||||
id="path3387"
|
||||
d="M 1279.8632,1334.1947 L 1216.2236,1393.7937 L 1296.0257,1413.9968 L 1279.8632,1334.1947 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:export-ydpi="6.2926431"
|
||||
inkscape:export-xdpi="6.2926431"
|
||||
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/draft.png"
|
||||
id="path3389"
|
||||
d="M 1298.046,1418.0374 C 1232.5494,1435.5504 1193.8334,1438.6328 1148.5434,1442.2811 C 1078.4638,1447.9264 1026.2959,1454.1271 914.18803,1442.2811 C 890.51576,1439.7798 958.08047,1399.9848 981.86825,1400.8648 C 1035.4438,1402.8469 1102.1666,1397.8186 1153.5942,1400.8648 C 1197.1585,1403.4452 1234.647,1414.2829 1298.046,1418.0374 z"
|
||||
style="fill:url(#radialGradient6355);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cssssc" />
|
||||
</g>
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect3924"
|
||||
width="50.65456"
|
||||
height="62.482525"
|
||||
x="12.856487"
|
||||
y="0.48895457" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 12.856487,0.48895457 0,62.48252643"
|
||||
id="path3926"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="opacity:0.63876654;fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 30.471844,5.6253174 0.535494,33.0519766 22.609757,0 L 30.471844,5.6253174 z M 34.964045,20.375549 44.75169,33.69372 35.321041,33.92285 34.964045,20.375549 z m -24.573235,9.451605 -4.8491983,3.207818 0.2974968,23.829501 4.5517015,4.095696 6.098684,-0.200488 0.08925,-9.566171 44.59477,-2.921405 1.636233,-7.246231 -46.141754,-0.343694 0.118999,-10.855026 -6.396181,0 z"
|
||||
id="path3010-7"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3863);fill-opacity:1;stroke:#000000;stroke-width:1.16431034;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 6.7484353,28.04146 1.8898368,31.242417 2.1934992,55.07178 6.7484353,59.161894 12.821683,58.984063 13.125346,28.04146 z"
|
||||
id="path3010"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3861);fill-opacity:1;stroke:#000000;stroke-width:1.16431034;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 59.162002,39.234097 -1.641628,7.255521 -54.2816054,3.546854 0,-11.205391 z"
|
||||
id="path3012"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#ffe400;fill-opacity:1;stroke:#000000;stroke-width:1.16431034;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 26.808896,3.8396874 0.555024,33.0451956 22.60454,0 L 26.808896,3.8396874 z m 4.490635,14.7446996 9.788573,13.322381 -9.435378,0.237054 -0.353195,-13.559435 z"
|
||||
id="path3782"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 12.856487,62.971481 50.65456,0"
|
||||
id="path3928"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 8.1 KiB |
@@ -116,6 +116,29 @@ static PyObject * open(PyObject *self, PyObject *args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
show(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *pcObj;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(FemMeshPy::Type), &pcObj)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
PY_TRY {
|
||||
App::Document *pcDoc = App::GetApplication().getActiveDocument();
|
||||
if (!pcDoc)
|
||||
pcDoc = App::GetApplication().newDocument();
|
||||
|
||||
FemMeshPy* pShape = static_cast<FemMeshPy*>(pcObj);
|
||||
Fem::FemMeshObject *pcFeature = (Fem::FemMeshObject *)pcDoc->addObject("Fem::FemMeshObject", "Mesh");
|
||||
// copy the data
|
||||
//TopoShape* shape = new MeshObject(*pShape->getTopoShapeObjectPtr());
|
||||
pcFeature->FemMesh.setValue(*(pShape->getFemMeshPtr()));
|
||||
pcDoc->recompute();
|
||||
} PY_CATCH;
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
|
||||
static PyObject * SMESH_PCA(PyObject *self, PyObject *args)
|
||||
{
|
||||
@@ -1079,10 +1102,15 @@ struct PyMethodDef Fem_methods[] = {
|
||||
{"insert" ,importer, METH_VARARGS, inst_doc},
|
||||
{"export" ,exporter, METH_VARARGS, export_doc},
|
||||
{"read" ,read, Py_NEWARGS, "Read a mesh from a file and returns a Mesh object."},
|
||||
{"calcMeshVolume", calcMeshVolume, Py_NEWARGS, "Calculate Mesh Volume for C3D10"},
|
||||
{"getBoundary_Conditions" , getBoundary_Conditions, Py_NEWARGS, "Get Boundary Conditions for Residual Stress Calculation"},
|
||||
{"SMESH_PCA" , SMESH_PCA, Py_NEWARGS, "Get a Matrix4D related to the PCA of a Mesh Object"},
|
||||
{"import_NASTRAN",import_NASTRAN, Py_NEWARGS, "Test"},
|
||||
{"show" ,show ,METH_VARARGS,
|
||||
"show(shape) -- Add the shape to the active document or create one if no document exists."},
|
||||
{"calcMeshVolume", calcMeshVolume, Py_NEWARGS,
|
||||
"Calculate Mesh Volume for C3D10"},
|
||||
{"getBoundary_Conditions" , getBoundary_Conditions, Py_NEWARGS,
|
||||
"Get Boundary Conditions for Residual Stress Calculation"},
|
||||
{"SMESH_PCA" , SMESH_PCA, Py_NEWARGS,
|
||||
"Get a Matrix4D related to the PCA of a Mesh Object"},
|
||||
{"import_NASTRAN",import_NASTRAN, Py_NEWARGS, "Import Nastran files, for tests only. Use read() or insert()"},
|
||||
{"minBoundingBox",minBoundingBox,Py_NEWARGS,"Minimize the Bounding Box and reorient the mesh to the 1st Quadrant"},
|
||||
{"checkBB",checkBB,Py_NEWARGS,"Check if the nodal z-values are still in the prescribed range"},
|
||||
{NULL, NULL} /* sentinel */
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include <Base/Stream.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/FileInfo.h>
|
||||
#include <Base/TimeInfo.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include <Mod/Mesh/App/Core/MeshKernel.h>
|
||||
#include <Mod/Mesh/App/Core/Evaluation.h>
|
||||
@@ -374,6 +376,9 @@ void FemMesh::compute()
|
||||
|
||||
void FemMesh::readNastran(const std::string &Filename)
|
||||
{
|
||||
Base::TimeInfo Start;
|
||||
Base::Console().Log("Start: FemMesh::readNastran() =================================\n");
|
||||
|
||||
std::ifstream inputfile;
|
||||
inputfile.open(Filename.c_str());
|
||||
inputfile.seekg(std::ifstream::beg);
|
||||
@@ -480,6 +485,8 @@ void FemMesh::readNastran(const std::string &Filename)
|
||||
while (inputfile.good());
|
||||
inputfile.close();
|
||||
|
||||
Base::Console().Log(" %f: File read, start building mesh\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
|
||||
//Now fill the SMESH datastructure
|
||||
std::vector<Base::Vector3d>::const_iterator anodeiterator;
|
||||
SMESHDS_Mesh* meshds = this->myMesh->GetMeshDS();
|
||||
@@ -495,21 +502,37 @@ void FemMesh::readNastran(const std::string &Filename)
|
||||
{
|
||||
//Die Reihenfolge wie hier die Elemente hinzugefügt werden ist sehr wichtig.
|
||||
//Ansonsten ist eine konsistente Datenstruktur nicht möglich
|
||||
//meshds->AddVolumeWithID
|
||||
//(
|
||||
// meshds->FindNode(all_elements[i][0]),
|
||||
// meshds->FindNode(all_elements[i][2]),
|
||||
// meshds->FindNode(all_elements[i][1]),
|
||||
// meshds->FindNode(all_elements[i][3]),
|
||||
// meshds->FindNode(all_elements[i][6]),
|
||||
// meshds->FindNode(all_elements[i][5]),
|
||||
// meshds->FindNode(all_elements[i][4]),
|
||||
// meshds->FindNode(all_elements[i][9]),
|
||||
// meshds->FindNode(all_elements[i][7]),
|
||||
// meshds->FindNode(all_elements[i][8]),
|
||||
// element_id[i]
|
||||
//);
|
||||
meshds->AddVolumeWithID
|
||||
(
|
||||
meshds->FindNode(all_elements[i][1]),
|
||||
meshds->FindNode(all_elements[i][0]),
|
||||
meshds->FindNode(all_elements[i][2]),
|
||||
meshds->FindNode(all_elements[i][1]),
|
||||
meshds->FindNode(all_elements[i][3]),
|
||||
meshds->FindNode(all_elements[i][4]),
|
||||
meshds->FindNode(all_elements[i][6]),
|
||||
meshds->FindNode(all_elements[i][5]),
|
||||
meshds->FindNode(all_elements[i][4]),
|
||||
meshds->FindNode(all_elements[i][9]),
|
||||
meshds->FindNode(all_elements[i][7]),
|
||||
meshds->FindNode(all_elements[i][8]),
|
||||
meshds->FindNode(all_elements[i][7]),
|
||||
meshds->FindNode(all_elements[i][9]),
|
||||
element_id[i]
|
||||
);
|
||||
}
|
||||
Base::Console().Log(" %f: Done \n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -591,16 +614,27 @@ void FemMesh::writeABAQUS(const std::string &Filename, Base::Placement* placemen
|
||||
//I absolute dont understand the scheme behind it but somehow its working like this
|
||||
apair.first = aVol->GetID();
|
||||
apair.second.clear();
|
||||
apair.second.push_back(aVol->GetNode(0)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(2)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(0)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(2)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(1)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(3)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(6)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(5)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(4)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(8)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(9)->GetID());
|
||||
//apair.second.push_back(aVol->GetNode(7)->GetID());
|
||||
|
||||
apair.second.push_back(aVol->GetNode(1)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(2)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(2)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(3)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(4)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(6)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(5)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(4)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(8)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(9)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(7)->GetID());
|
||||
apair.second.push_back(aVol->GetNode(9)->GetID());
|
||||
temp_map.insert(apair);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "FemMeshPy.cpp"
|
||||
#include "HypothesisPy.h"
|
||||
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
@@ -193,27 +192,67 @@ PyObject* FemMeshPy::addEdge(PyObject *args)
|
||||
|
||||
PyObject* FemMeshPy::addFace(PyObject *args)
|
||||
{
|
||||
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
|
||||
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
|
||||
|
||||
int n1,n2,n3;
|
||||
if (!PyArg_ParseTuple(args, "iii",&n1,&n2,&n3))
|
||||
return 0;
|
||||
if (PyArg_ParseTuple(args, "iii",&n1,&n2,&n3))
|
||||
{
|
||||
// old form, debrekadet
|
||||
try {
|
||||
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
|
||||
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
|
||||
const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
|
||||
if (!node1 || !node2 || !node3)
|
||||
throw std::runtime_error("Failed to get node of the given indices");
|
||||
SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3);
|
||||
if (!face)
|
||||
throw std::runtime_error("Failed to add face");
|
||||
return Py::new_reference_to(Py::Int(face->GetID()));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PyErr_SetString(PyExc_Exception, e.what());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
|
||||
PyObject *obj;
|
||||
int ElementId=-1;
|
||||
float min_eps = 1.0e-2f;
|
||||
if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId))
|
||||
{
|
||||
Py::List list(obj);
|
||||
std::vector<const SMDS_MeshNode*> Nodes;
|
||||
for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
Py::Int NoNr(*it);
|
||||
const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
|
||||
if (!node)
|
||||
throw std::runtime_error("Failed to get node of the given indices");
|
||||
Nodes.push_back(node);
|
||||
}
|
||||
|
||||
SMDS_MeshFace* face=0;
|
||||
switch(Nodes.size()){
|
||||
case 3:
|
||||
face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2]);
|
||||
if (!face)
|
||||
throw std::runtime_error("Failed to add triangular face");
|
||||
break;
|
||||
|
||||
default: throw std::runtime_error("Unknown node count, [3|4|6|8] are allowed"); //unknown face type
|
||||
}
|
||||
|
||||
try {
|
||||
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
|
||||
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
|
||||
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
|
||||
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
|
||||
const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
|
||||
if (!node1 || !node2 || !node3)
|
||||
throw std::runtime_error("Failed to get node of the given indices");
|
||||
SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3);
|
||||
if (!face)
|
||||
throw std::runtime_error("Failed to add face");
|
||||
return Py::new_reference_to(Py::Int(face->GetID()));
|
||||
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PyErr_SetString(PyExc_Exception, e.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Line constructor accepts:\n"
|
||||
"-- empty parameter list\n"
|
||||
"-- Line\n"
|
||||
"-- Point, Point");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
PyObject* FemMeshPy::addQuad(PyObject *args)
|
||||
@@ -244,28 +283,77 @@ PyObject* FemMeshPy::addQuad(PyObject *args)
|
||||
|
||||
PyObject* FemMeshPy::addVolume(PyObject *args)
|
||||
{
|
||||
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
|
||||
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
|
||||
|
||||
int n1,n2,n3,n4;
|
||||
if (!PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4))
|
||||
return 0;
|
||||
if (PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4))
|
||||
{
|
||||
try {
|
||||
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
|
||||
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
|
||||
const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
|
||||
const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
|
||||
if (!node1 || !node2 || !node3 || !node4)
|
||||
throw std::runtime_error("Failed to get node of the given indices");
|
||||
SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4);
|
||||
if (!vol)
|
||||
throw std::runtime_error("Failed to add volume");
|
||||
return Py::new_reference_to(Py::Int(vol->GetID()));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PyErr_SetString(PyExc_Exception, e.what());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
|
||||
PyObject *obj;
|
||||
int ElementId=-1;
|
||||
float min_eps = 1.0e-2f;
|
||||
if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId))
|
||||
{
|
||||
Py::List list(obj);
|
||||
std::vector<const SMDS_MeshNode*> Nodes;
|
||||
for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
Py::Int NoNr(*it);
|
||||
const SMDS_MeshNode* node = meshDS->FindNode(NoNr);
|
||||
if (!node)
|
||||
throw std::runtime_error("Failed to get node of the given indices");
|
||||
Nodes.push_back(node);
|
||||
}
|
||||
|
||||
SMDS_MeshVolume* vol=0;
|
||||
switch(Nodes.size()){
|
||||
case 4:
|
||||
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3]);
|
||||
if (!vol)
|
||||
throw std::runtime_error("Failed to add Tet4 volume");
|
||||
break;
|
||||
case 8:
|
||||
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]);
|
||||
if (!vol)
|
||||
throw std::runtime_error("Failed to add Tet10 volume");
|
||||
break;
|
||||
case 10:
|
||||
vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9]);
|
||||
if (!vol)
|
||||
throw std::runtime_error("Failed to add Tet10 volume");
|
||||
break;
|
||||
|
||||
default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type
|
||||
}
|
||||
|
||||
try {
|
||||
SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh();
|
||||
SMESHDS_Mesh* meshDS = mesh->GetMeshDS();
|
||||
const SMDS_MeshNode* node1 = meshDS->FindNode(n1);
|
||||
const SMDS_MeshNode* node2 = meshDS->FindNode(n2);
|
||||
const SMDS_MeshNode* node3 = meshDS->FindNode(n3);
|
||||
const SMDS_MeshNode* node4 = meshDS->FindNode(n4);
|
||||
if (!node1 || !node2 || !node3 || !node4)
|
||||
throw std::runtime_error("Failed to get node of the given indices");
|
||||
SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4);
|
||||
if (!vol)
|
||||
throw std::runtime_error("Failed to add volume");
|
||||
return Py::new_reference_to(Py::Int(vol->GetID()));
|
||||
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
PyErr_SetString(PyExc_Exception, e.what());
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Line constructor accepts:\n"
|
||||
"-- empty parameter list\n"
|
||||
"-- Line\n"
|
||||
"-- Point, Point");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
PyObject* FemMeshPy::copy(PyObject *args)
|
||||
|
||||
@@ -53,13 +53,105 @@
|
||||
#include <Base/FileInfo.h>
|
||||
#include <Base/Stream.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/TimeInfo.h>
|
||||
#include <Base/BoundBox.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <SMESH_Mesh.hxx>
|
||||
#include <SMESHDS_Mesh.hxx>
|
||||
#include <SMDSAbs_ElementType.hxx>
|
||||
|
||||
using namespace FemGui;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct FemFace
|
||||
{
|
||||
const SMDS_MeshNode *Nodes[8];
|
||||
unsigned long ElementNumber;
|
||||
const SMDS_MeshElement* Element;
|
||||
unsigned short Size;
|
||||
unsigned short FaceNo;
|
||||
bool hide;
|
||||
Base::Vector3d getFirstNodePoint(void) {
|
||||
return Base::Vector3d(Nodes[0]->X(),Nodes[0]->Y(),Nodes[0]->Z());
|
||||
}
|
||||
|
||||
Base::Vector3d set(short size,const SMDS_MeshElement* element,unsigned short id, short faceNo, const SMDS_MeshNode* n1,const SMDS_MeshNode* n2,const SMDS_MeshNode* n3,const SMDS_MeshNode* n4=0,const SMDS_MeshNode* n5=0,const SMDS_MeshNode* n6=0,const SMDS_MeshNode* n7=0,const SMDS_MeshNode* n8=0);
|
||||
|
||||
bool isSameFace (FemFace &face);
|
||||
};
|
||||
|
||||
Base::Vector3d FemFace::set(short size,const SMDS_MeshElement* element,unsigned short id,short faceNo, const SMDS_MeshNode* n1,const SMDS_MeshNode* n2,const SMDS_MeshNode* n3,const SMDS_MeshNode* n4,const SMDS_MeshNode* n5,const SMDS_MeshNode* n6,const SMDS_MeshNode* n7,const SMDS_MeshNode* n8)
|
||||
{
|
||||
Nodes[0] = n1;
|
||||
Nodes[1] = n2;
|
||||
Nodes[2] = n3;
|
||||
Nodes[3] = n4;
|
||||
Nodes[4] = n5;
|
||||
Nodes[5] = n6;
|
||||
Nodes[6] = n7;
|
||||
Nodes[7] = n8;
|
||||
|
||||
Element = element;
|
||||
ElementNumber = id;
|
||||
Size = size;
|
||||
FaceNo = faceNo;
|
||||
hide = false;
|
||||
|
||||
// sorting the nodes for later easier comparison (bubble sort)
|
||||
int i, j, flag = 1; // set flag to 1 to start first pass
|
||||
const SMDS_MeshNode* temp; // holding variable
|
||||
|
||||
for(i = 1; (i <= size) && flag; i++)
|
||||
{
|
||||
flag = 0;
|
||||
for (j=0; j < (size -1); j++)
|
||||
{
|
||||
if (Nodes[j+1] > Nodes[j]) // ascending order simply changes to <
|
||||
{
|
||||
temp = Nodes[j]; // swap elements
|
||||
Nodes[j] = Nodes[j+1];
|
||||
Nodes[j+1] = temp;
|
||||
flag = 1; // indicates that a swap occurred.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Base::Vector3d(Nodes[0]->X(),Nodes[0]->Y(),Nodes[0]->Z());
|
||||
};
|
||||
|
||||
class FemFaceGridItem :public std::vector<FemFace*>{
|
||||
public:
|
||||
//FemFaceGridItem(void){reserve(200);}
|
||||
};
|
||||
|
||||
bool FemFace::isSameFace (FemFace &face)
|
||||
{
|
||||
// the same element can not have the same face
|
||||
if(face.ElementNumber == ElementNumber)
|
||||
return false;
|
||||
assert(face.Size == Size);
|
||||
// if the same face size just compare if the sorted nodes are the same
|
||||
if( Nodes[0] == face.Nodes[0] &&
|
||||
Nodes[1] == face.Nodes[1] &&
|
||||
Nodes[2] == face.Nodes[2] &&
|
||||
Nodes[3] == face.Nodes[3] &&
|
||||
Nodes[4] == face.Nodes[4] &&
|
||||
Nodes[5] == face.Nodes[5] &&
|
||||
Nodes[6] == face.Nodes[6] &&
|
||||
Nodes[7] == face.Nodes[7] ){
|
||||
hide = true;
|
||||
face.hide = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
PROPERTY_SOURCE(FemGui::ViewProviderFemMesh, Gui::ViewProviderGeometryObject)
|
||||
|
||||
App::PropertyFloatConstraint::Constraints ViewProviderFemMesh::floatRange = {1.0f,64.0f,1.0f};
|
||||
@@ -77,18 +169,20 @@ ViewProviderFemMesh::ViewProviderFemMesh()
|
||||
ADD_PROPERTY(PointColor,(mat.diffuseColor));
|
||||
ADD_PROPERTY(PointSize,(2.0f));
|
||||
PointSize.setConstraints(&floatRange);
|
||||
ADD_PROPERTY(LineWidth,(1.0f));
|
||||
ADD_PROPERTY(LineWidth,(4.0f));
|
||||
LineWidth.setConstraints(&floatRange);
|
||||
|
||||
ADD_PROPERTY(BackfaceCulling,(true));
|
||||
ADD_PROPERTY(ShowInner, (false));
|
||||
|
||||
pcDrawStyle = new SoDrawStyle();
|
||||
pcDrawStyle->ref();
|
||||
pcDrawStyle->style = SoDrawStyle::LINES;
|
||||
pcDrawStyle->lineWidth = LineWidth.getValue();
|
||||
|
||||
pShapeHints = new SoShapeHints;
|
||||
pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
|
||||
pShapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
|
||||
pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
|
||||
pShapeHints->shapeType = SoShapeHints::SOLID;
|
||||
pShapeHints->vertexOrdering = SoShapeHints::CLOCKWISE;
|
||||
pShapeHints->ref();
|
||||
|
||||
pcMatBinding = new SoMaterialBinding;
|
||||
@@ -148,16 +242,6 @@ void ViewProviderFemMesh::attach(App::DocumentObject *pcObj)
|
||||
pcWireRoot->addChild(pcHighlight);
|
||||
addDisplayMaskMode(pcWireRoot, "Wireframe");
|
||||
|
||||
// flat+line
|
||||
SoPolygonOffset* offset = new SoPolygonOffset();
|
||||
offset->styles = SoPolygonOffset::LINES;
|
||||
offset->factor = -2.0f;
|
||||
offset->units = 1.0f;
|
||||
SoGroup* pcFlatWireRoot = new SoSeparator();
|
||||
pcFlatWireRoot->addChild(pcFlatRoot);
|
||||
pcFlatWireRoot->addChild(offset);
|
||||
pcFlatWireRoot->addChild(pcWireRoot);
|
||||
addDisplayMaskMode(pcFlatWireRoot, "Flat Lines");
|
||||
|
||||
// Points
|
||||
SoGroup* pcPointsRoot = new SoSeparator();
|
||||
@@ -168,6 +252,17 @@ void ViewProviderFemMesh::attach(App::DocumentObject *pcObj)
|
||||
pcPointsRoot->addChild(pointset);
|
||||
addDisplayMaskMode(pcPointsRoot, "Points");
|
||||
|
||||
// flat+line
|
||||
//SoPolygonOffset* offset = new SoPolygonOffset();
|
||||
//offset->styles = SoPolygonOffset::LINES;
|
||||
//offset->factor = -2.0f;
|
||||
//offset->units = 1.0f;
|
||||
SoGroup* pcFlatWireRoot = new SoSeparator();
|
||||
pcFlatWireRoot->addChild(pcFlatRoot);
|
||||
//pcFlatWireRoot->addChild(offset);
|
||||
pcFlatWireRoot->addChild(pcPointsRoot);
|
||||
addDisplayMaskMode(pcFlatWireRoot, "Flat Lines");
|
||||
|
||||
pcHighlight->addChild(pcCoords);
|
||||
pcHighlight->addChild(pcFaces);
|
||||
}
|
||||
@@ -200,7 +295,7 @@ void ViewProviderFemMesh::updateData(const App::Property* prop)
|
||||
{
|
||||
if (prop->isDerivedFrom(Fem::PropertyFemMesh::getClassTypeId())) {
|
||||
ViewProviderFEMMeshBuilder builder;
|
||||
builder.createMesh(prop, pcCoords, pcFaces);
|
||||
builder.createMesh(prop, pcCoords, pcFaces,ShowInner.getValue());
|
||||
}
|
||||
Gui::ViewProviderGeometryObject::updateData(prop);
|
||||
}
|
||||
@@ -216,6 +311,20 @@ void ViewProviderFemMesh::onChanged(const App::Property* prop)
|
||||
if (c != PointMaterial.getValue().diffuseColor)
|
||||
PointMaterial.setDiffuseColor(c);
|
||||
}
|
||||
else if (prop == &BackfaceCulling) {
|
||||
if(BackfaceCulling.getValue()){
|
||||
pShapeHints->shapeType = SoShapeHints::SOLID;
|
||||
//pShapeHints->vertexOrdering = SoShapeHints::CLOCKWISE;
|
||||
}else{
|
||||
pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
|
||||
//pShapeHints->vertexOrdering = SoShapeHints::CLOCKWISE;
|
||||
}
|
||||
}
|
||||
else if (prop == &ShowInner) {
|
||||
// recalc mesh with new settings
|
||||
ViewProviderFEMMeshBuilder builder;
|
||||
builder.createMesh(&(dynamic_cast<Fem::FemMeshObject*>(this->pcObject)->FemMesh), pcCoords, pcFaces,ShowInner.getValue());
|
||||
}
|
||||
else if (prop == &PointMaterial) {
|
||||
const App::Material& Mat = PointMaterial.getValue();
|
||||
if (PointColor.getValue() != Mat.diffuseColor)
|
||||
@@ -258,23 +367,425 @@ void ViewProviderFEMMeshBuilder::buildNodes(const App::Property* prop, std::vect
|
||||
if (pcPointsCoord && pcFaces)
|
||||
createMesh(prop, pcPointsCoord, pcFaces);
|
||||
}
|
||||
#if 1 // new visual
|
||||
|
||||
void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces,bool ShowInner) const
|
||||
{
|
||||
|
||||
const Fem::PropertyFemMesh* mesh = static_cast<const Fem::PropertyFemMesh*>(prop);
|
||||
|
||||
SMESHDS_Mesh* data = const_cast<SMESH_Mesh*>(mesh->getValue().getSMesh())->GetMeshDS();
|
||||
|
||||
int numFaces = data->NbFaces();
|
||||
int numNodes = data->NbNodes();
|
||||
int numEdges = data->NbEdges();
|
||||
|
||||
if(numFaces+numNodes+numEdges == 0) return;
|
||||
Base::TimeInfo Start;
|
||||
Base::Console().Log("Start: ViewProviderFEMMeshBuilder::createMesh() =================================\n");
|
||||
|
||||
const SMDS_MeshInfo& info = data->GetMeshInfo();
|
||||
int numNode = info.NbNodes();
|
||||
int numTria = info.NbTriangles();
|
||||
int numQuad = info.NbQuadrangles();
|
||||
int numPoly = info.NbPolygons();
|
||||
int numVolu = info.NbVolumes();
|
||||
int numTetr = info.NbTetras();
|
||||
int numHexa = info.NbHexas();
|
||||
int numPyrd = info.NbPyramids();
|
||||
int numPris = info.NbPrisms();
|
||||
int numHedr = info.NbPolyhedrons();
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<FemFace> facesHelper(numTria+numQuad+numPoly+numTetr*4+numHexa*6+numPyrd*5+numPris*6);
|
||||
Base::Console().Log(" %f: Start build up %i face helper\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()),facesHelper.size());
|
||||
SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator();
|
||||
Base::BoundBox3d BndBox;
|
||||
|
||||
for (int i=0;aVolIter->more();) {
|
||||
const SMDS_MeshVolume* aVol = aVolIter->next();
|
||||
|
||||
int num = aVol->NbNodes();
|
||||
|
||||
switch(num){
|
||||
// tet 4 element
|
||||
case 4:
|
||||
// face 1
|
||||
BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),1,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(2)));
|
||||
// face 2
|
||||
BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),2,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(1)));
|
||||
// face 3
|
||||
BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),3,aVol->GetNode(1),aVol->GetNode(3),aVol->GetNode(2)));
|
||||
// face 4
|
||||
BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),4,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(0)));
|
||||
break;
|
||||
//unknown case
|
||||
case 8:
|
||||
// face 1
|
||||
BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),1,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(2),aVol->GetNode(3)));
|
||||
// face 2
|
||||
BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),2,aVol->GetNode(4),aVol->GetNode(5),aVol->GetNode(6),aVol->GetNode(7)));
|
||||
// face 3
|
||||
BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),3,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(4),aVol->GetNode(5)));
|
||||
// face 4
|
||||
BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),4,aVol->GetNode(1),aVol->GetNode(2),aVol->GetNode(5),aVol->GetNode(6)));
|
||||
// face 5
|
||||
BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),5,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(6),aVol->GetNode(7)));
|
||||
// face 6
|
||||
BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),6,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(4),aVol->GetNode(7)));
|
||||
break;
|
||||
//unknown case
|
||||
case 10:
|
||||
// face 1
|
||||
BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),1,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(2),aVol->GetNode(4),aVol->GetNode(5),aVol->GetNode(6)));
|
||||
// face 2
|
||||
BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),2,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(1),aVol->GetNode(7),aVol->GetNode(8),aVol->GetNode(4)));
|
||||
// face 3
|
||||
BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),3,aVol->GetNode(1),aVol->GetNode(3),aVol->GetNode(2),aVol->GetNode(8),aVol->GetNode(9),aVol->GetNode(5)));
|
||||
// face 4
|
||||
BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),4,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(0),aVol->GetNode(9),aVol->GetNode(7),aVol->GetNode(6)));
|
||||
break;
|
||||
//unknown case
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
int FaceSize = facesHelper.size();
|
||||
|
||||
|
||||
if( FaceSize < 5000){
|
||||
Base::Console().Log(" %f: Start eliminate internal faces SIMPLE\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
|
||||
// search for double (inside) faces and hide them
|
||||
if(!ShowInner){
|
||||
for(int l=0; l< FaceSize;l++){
|
||||
if(! facesHelper[l].hide){
|
||||
for(int i=l+1; i<FaceSize; i++){
|
||||
if(facesHelper[l].isSameFace(facesHelper[i]) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
Base::Console().Log(" %f: Start eliminate internal faces GRID\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
BndBox.Enlarge(BndBox.CalcDiagonalLength()/10000.0);
|
||||
// calculate grid properties
|
||||
double edge = pow(FaceSize,1.0/3.0);
|
||||
double edgeL = BndBox.LengthX() + BndBox.LengthY() + BndBox.LengthZ();
|
||||
double gridFactor = 50.0;
|
||||
double size = ((3*edge) / edgeL)*gridFactor;
|
||||
|
||||
unsigned int NbrX = unsigned int(BndBox.LengthX()/size)+1 ;
|
||||
unsigned int NbrY = unsigned int(BndBox.LengthY()/size)+1;
|
||||
unsigned int NbrZ = unsigned int(BndBox.LengthZ()/size)+1;
|
||||
Base::Console().Log(" Size:F:%f, X:%i ,Y:%i ,Z:%i\n",gridFactor,NbrX,NbrY,NbrZ);
|
||||
|
||||
double Xmin = BndBox.MinX;
|
||||
double Ymin = BndBox.MinY;
|
||||
double Zmin = BndBox.MinZ;
|
||||
double Xln = BndBox.LengthX() / NbrX;
|
||||
double Yln = BndBox.LengthY() / NbrY;
|
||||
double Zln = BndBox.LengthZ() / NbrZ;
|
||||
|
||||
std::vector<FemFaceGridItem> Grid(NbrX*NbrY*NbrZ);
|
||||
|
||||
|
||||
unsigned int iX = 0;
|
||||
unsigned int iY = 0;
|
||||
unsigned int iZ = 0;
|
||||
|
||||
for(int l=0; l< FaceSize;l++){
|
||||
Base::Vector3d point(facesHelper[l].getFirstNodePoint());
|
||||
double x = (point.x - Xmin) / Xln;
|
||||
double y = (point.y - Ymin) / Yln;
|
||||
double z = (point.z - Zmin) / Zln;
|
||||
|
||||
iX = x;
|
||||
iY = y;
|
||||
iZ = z;
|
||||
|
||||
if(iX >= NbrX || iY >= NbrY || iZ >= NbrZ)
|
||||
Base::Console().Log(" Outof range!\n");
|
||||
|
||||
Grid[iX + iY*NbrX + iZ*NbrX*NbrY].push_back(&facesHelper[l]);
|
||||
}
|
||||
|
||||
unsigned int max =0, avg = 0;
|
||||
for(std::vector<FemFaceGridItem>::iterator it=Grid.begin();it!=Grid.end();++it){
|
||||
for(unsigned int l=0; l< it->size();l++){
|
||||
if(! it->operator[](l)->hide){
|
||||
for(unsigned int i=l+1; i<it->size(); i++){
|
||||
if(it->operator[](l)->isSameFace(*(it->operator[](i))) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(it->size() > max)max=it->size();
|
||||
avg += it->size();
|
||||
}
|
||||
avg = avg/Grid.size();
|
||||
|
||||
Base::Console().Log(" VoxelSize: Max:%i ,Average:%i\n",max,avg);
|
||||
|
||||
} //if( FaceSize < 1000)
|
||||
|
||||
|
||||
Base::Console().Log(" %f: Start build up node map\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
|
||||
// sort out double nodes and build up index map
|
||||
std::map<const SMDS_MeshNode*, int> mapNodeIndex;
|
||||
for(int l=0; l< FaceSize;l++){
|
||||
if(!facesHelper[l].hide)
|
||||
for(int i=0; i<8;i++)
|
||||
if(facesHelper[l].Nodes[i])
|
||||
mapNodeIndex[facesHelper[l].Nodes[i]]=0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
Base::Console().Log(" %f: Start set point vector\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
|
||||
// set the point coordinates
|
||||
coords->point.setNum(mapNodeIndex.size());
|
||||
std::map<const SMDS_MeshNode*, int>::iterator it= mapNodeIndex.begin();
|
||||
SbVec3f* verts = coords->point.startEditing();
|
||||
for (int i=0;it != mapNodeIndex.end() ;++it,i++) {
|
||||
verts[i].setValue((float)it->first->X(),(float)it->first->Y(),(float)it->first->Z());
|
||||
it->second = i;
|
||||
}
|
||||
coords->point.finishEditing();
|
||||
|
||||
|
||||
|
||||
// count triangle size
|
||||
int triangleCount=0;
|
||||
for(int l=0; l< FaceSize;l++)
|
||||
if(! facesHelper[l].hide)
|
||||
switch(facesHelper[l].Size){
|
||||
case 3:triangleCount++ ;break;
|
||||
case 4:triangleCount+=2 ;break;
|
||||
case 6:triangleCount+=4 ;break;
|
||||
default: assert(0);
|
||||
}
|
||||
|
||||
Base::Console().Log(" %f: Start build up triangle vector\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
// set the triangle face indices
|
||||
faces->coordIndex.setNum(4*triangleCount);
|
||||
int index=0;
|
||||
int32_t* indices = faces->coordIndex.startEditing();
|
||||
// iterate all element faces, allways assure CLOCKWISE triangle ordering to allow backface culling
|
||||
for(int l=0; l< FaceSize;l++){
|
||||
if(! facesHelper[l].hide){
|
||||
switch( facesHelper[l].Element->NbNodes()){
|
||||
case 4: // Tet 4
|
||||
switch(facesHelper[l].FaceNo){
|
||||
case 1: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 2: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 3: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 4: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
default: assert(0);
|
||||
|
||||
}
|
||||
break;
|
||||
case 8: // Hex 8
|
||||
switch(facesHelper[l].FaceNo){
|
||||
case 1: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 2: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 3: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 4: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 5: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 6: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
}
|
||||
break;
|
||||
case 10: // Tet 10
|
||||
switch(facesHelper[l].FaceNo){
|
||||
case 1: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 2: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 3: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
case 4: {
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
|
||||
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
|
||||
indices[index++] = SO_END_FACE_INDEX;
|
||||
break; }
|
||||
default: assert(0);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:assert(0); // not implemented node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
faces->coordIndex.finishEditing();
|
||||
Base::Console().Log(" %f: Finish =========================================================\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()));
|
||||
|
||||
|
||||
}
|
||||
#else // old version of createMesh()
|
||||
void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces) const
|
||||
{
|
||||
const Fem::PropertyFemMesh* mesh = static_cast<const Fem::PropertyFemMesh*>(prop);
|
||||
|
||||
SMESHDS_Mesh* data = const_cast<SMESH_Mesh*>(mesh->getValue().getSMesh())->GetMeshDS();
|
||||
const SMDS_MeshInfo& info = data->GetMeshInfo();
|
||||
|
||||
int numFaces = data->NbFaces();
|
||||
int numNodes = data->NbNodes ();
|
||||
int numEdges = data->NbEdges ();
|
||||
|
||||
const SMDS_MeshInfo& info = data->GetMeshInfo();
|
||||
int numNode = info.NbNodes();
|
||||
int numTria = info.NbTriangles();
|
||||
int numQuad = info.NbQuadrangles();
|
||||
//int numPoly = info.NbPolygons();
|
||||
//int numVolu = info.NbVolumes();
|
||||
int numPoly = info.NbPolygons();
|
||||
int numVolu = info.NbVolumes();
|
||||
int numTetr = info.NbTetras();
|
||||
//int numHexa = info.NbHexas();
|
||||
//int numPyrd = info.NbPyramids();
|
||||
//int numPris = info.NbPrisms();
|
||||
//int numHedr = info.NbPolyhedrons();
|
||||
int numHexa = info.NbHexas();
|
||||
int numPyrd = info.NbPyramids();
|
||||
int numPris = info.NbPrisms();
|
||||
int numHedr = info.NbPolyhedrons();
|
||||
|
||||
int index=0;
|
||||
std::map<const SMDS_MeshNode*, int> mapNodeIndex;
|
||||
@@ -295,6 +806,7 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
|
||||
index=0;
|
||||
faces->coordIndex.setNum(4*numTria + 5*numQuad + 16*numTetr);
|
||||
int32_t* indices = faces->coordIndex.startEditing();
|
||||
// iterate all faces
|
||||
SMDS_FaceIteratorPtr aFaceIter = data->facesIterator();
|
||||
for (;aFaceIter->more();) {
|
||||
const SMDS_MeshFace* aFace = aFaceIter->next();
|
||||
@@ -336,3 +848,4 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
|
||||
}
|
||||
faces->coordIndex.finishEditing();
|
||||
}
|
||||
#endif
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
ViewProviderFEMMeshBuilder(){}
|
||||
~ViewProviderFEMMeshBuilder(){}
|
||||
virtual void buildNodes(const App::Property*, std::vector<SoNode*>&) const;
|
||||
void createMesh(const App::Property*, SoCoordinate3*, SoIndexedFaceSet*) const;
|
||||
void createMesh(const App::Property*, SoCoordinate3*, SoIndexedFaceSet*,bool ShowInner=false) const;
|
||||
};
|
||||
|
||||
class FemGuiExport ViewProviderFemMesh : public Gui::ViewProviderGeometryObject
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
App::PropertyFloatConstraint PointSize;
|
||||
App::PropertyFloatConstraint LineWidth;
|
||||
App::PropertyMaterial PointMaterial;
|
||||
App::PropertyBool BackfaceCulling;
|
||||
App::PropertyBool ShowInner;
|
||||
|
||||
void attach(App::DocumentObject *pcObject);
|
||||
void setDisplayMode(const char* ModeName);
|
||||
|
||||
@@ -1538,7 +1538,6 @@ bool MeshAlgorithm::ConnectLines (std::list<std::pair<Base::Vector3f, Base::Vect
|
||||
rclLines.erase(pFront);
|
||||
}
|
||||
|
||||
|
||||
if (pEnd != rclLines.end())
|
||||
{
|
||||
if (bEndFirst == true)
|
||||
|
||||
@@ -416,7 +416,7 @@ float QuadraticFit::Fit()
|
||||
if (CountPoints() > 0) {
|
||||
std::vector< Wm4::Vector3<double> > cPts;
|
||||
GetMgcVectorArray( cPts );
|
||||
fResult = Wm4::QuadraticFit3<double>( CountPoints(), &(cPts[0]), _fCoeff );
|
||||
fResult = (float) Wm4::QuadraticFit3<double>( CountPoints(), &(cPts[0]), _fCoeff );
|
||||
_fLastResult = fResult;
|
||||
|
||||
_bIsFitted = true;
|
||||
@@ -520,7 +520,7 @@ float SurfaceFit::Fit()
|
||||
float fResult = FLOAT_MAX;
|
||||
|
||||
if (CountPoints() > 0) {
|
||||
fResult = PolynomFit();
|
||||
fResult = (float) PolynomFit();
|
||||
_fLastResult = fResult;
|
||||
|
||||
_bIsFitted = true;
|
||||
@@ -684,7 +684,7 @@ double SurfaceFit::Value(double x, double y) const
|
||||
float z = 0.0f;
|
||||
if (_bIsFitted) {
|
||||
FunctionContainer clFuncCont(_fCoeff);
|
||||
z = clFuncCont.F(x, y, 0.0f);
|
||||
z = (float) clFuncCont.F(x, y, 0.0f);
|
||||
}
|
||||
|
||||
return z;
|
||||
|
||||
@@ -413,7 +413,7 @@ public:
|
||||
Base::Vector3f GetGradient( double x, double y, double z ) const
|
||||
{
|
||||
Wm4::Vector3<double> grad = pImplSurf->GetGradient( Wm4::Vector3<double>(x, y, z) );
|
||||
return Base::Vector3f( grad.X(), grad.Y(), grad.Z() );
|
||||
return Base::Vector3f( (float)grad.X(), (float)grad.Y(), (float)grad.Z() );
|
||||
}
|
||||
|
||||
Base::Matrix4D GetHessian( double x, double y, double z ) const
|
||||
|
||||
@@ -701,7 +701,7 @@ bool MeshFixDeformedFacets::Fixup()
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool MeshEvalFoldsOnSurface::Evaluate()
|
||||
bool MeshEvalDentsOnSurface::Evaluate()
|
||||
{
|
||||
this->indices.clear();
|
||||
MeshRefPointToFacets clPt2Facets(_rclMesh);
|
||||
@@ -749,14 +749,25 @@ bool MeshEvalFoldsOnSurface::Evaluate()
|
||||
return this->indices.empty();
|
||||
}
|
||||
|
||||
std::vector<unsigned long> MeshEvalFoldsOnSurface::GetIndices() const
|
||||
std::vector<unsigned long> MeshEvalDentsOnSurface::GetIndices() const
|
||||
{
|
||||
return this->indices;
|
||||
}
|
||||
|
||||
bool MeshFixFoldsOnSurface::Fixup()
|
||||
/*
|
||||
Forbidden is:
|
||||
+ two facets share a common point but not a common edge
|
||||
|
||||
Repair:
|
||||
+ store the point indices which can be projected on a face
|
||||
+ store the face indices on which a point can be projected
|
||||
+ remove faces with an edge length smaller than a certain threshold (e.g. 0.01) from the stored triangles or that reference one of the stored points
|
||||
+ for this edge merge the two points
|
||||
+ if a point of a face can be projected onto another face and they have a common point then split the second face if the distance is under a certain threshold
|
||||
*/
|
||||
bool MeshFixDentsOnSurface::Fixup()
|
||||
{
|
||||
MeshEvalFoldsOnSurface eval(_rclMesh);
|
||||
MeshEvalDentsOnSurface eval(_rclMesh);
|
||||
if (!eval.Evaluate()) {
|
||||
std::vector<unsigned long> inds = eval.GetIndices();
|
||||
_rclMesh.DeleteFacets(inds);
|
||||
@@ -767,6 +778,44 @@ bool MeshFixFoldsOnSurface::Fixup()
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool MeshEvalFoldsOnSurface::Evaluate()
|
||||
{
|
||||
this->indices.clear();
|
||||
const MeshFacetArray& rFAry = _rclMesh.GetFacets();
|
||||
unsigned long ct=0;
|
||||
for (MeshFacetArray::const_iterator it = rFAry.begin(); it != rFAry.end(); ++it, ct++) {
|
||||
for (int i=0; i<3; i++) {
|
||||
unsigned long n1 = it->_aulNeighbours[i];
|
||||
unsigned long n2 = it->_aulNeighbours[(i+1)%3];
|
||||
Base::Vector3f v1 =_rclMesh.GetFacet(*it).GetNormal();
|
||||
if (n1 != ULONG_MAX && n2 != ULONG_MAX) {
|
||||
Base::Vector3f v2 = _rclMesh.GetFacet(n1).GetNormal();
|
||||
Base::Vector3f v3 = _rclMesh.GetFacet(n2).GetNormal();
|
||||
if (v2 * v3 > 0.0f) {
|
||||
if (v1 * v2 < -0.1f && v1 * v3 < -0.1f) {
|
||||
indices.push_back(n1);
|
||||
indices.push_back(n2);
|
||||
indices.push_back(ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
std::sort(this->indices.begin(), this->indices.end());
|
||||
this->indices.erase(std::unique(this->indices.begin(),
|
||||
this->indices.end()), this->indices.end());
|
||||
return this->indices.empty();
|
||||
}
|
||||
|
||||
std::vector<unsigned long> MeshEvalFoldsOnSurface::GetIndices() const
|
||||
{
|
||||
return this->indices;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool MeshEvalFoldsOnBoundary::Evaluate()
|
||||
{
|
||||
// remove all boundary facets with two open edges and where
|
||||
|
||||
@@ -380,6 +380,37 @@ private:
|
||||
float fMaxAngle;
|
||||
};
|
||||
|
||||
/**
|
||||
* If an adjacent point (A) of a point (P) can be projected onto a triangle shared
|
||||
* by (P) but not by (A) then we have a local dent. The topology is not affected.
|
||||
*/
|
||||
class MeshExport MeshEvalDentsOnSurface : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
MeshEvalDentsOnSurface (const MeshKernel &rclM) : MeshEvaluation( rclM ) { }
|
||||
~MeshEvalDentsOnSurface() {}
|
||||
|
||||
bool Evaluate();
|
||||
std::vector<unsigned long> GetIndices() const;
|
||||
|
||||
private:
|
||||
std::vector<unsigned long> indices;
|
||||
};
|
||||
|
||||
class MeshExport MeshFixDentsOnSurface : public MeshValidation
|
||||
{
|
||||
public:
|
||||
MeshFixDentsOnSurface (MeshKernel &rclM) : MeshValidation( rclM ) { }
|
||||
~MeshFixDentsOnSurface() {}
|
||||
|
||||
bool Fixup();
|
||||
};
|
||||
|
||||
/**
|
||||
* If the angle between the adjacent triangles of a triangle is lower then 90 deg
|
||||
* but the angles between both of these adjacent triangles is higher than 90 deg
|
||||
* we have a fold. The topology is not affected but the geometry is broken.
|
||||
*/
|
||||
class MeshExport MeshEvalFoldsOnSurface : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
@@ -393,15 +424,12 @@ private:
|
||||
std::vector<unsigned long> indices;
|
||||
};
|
||||
|
||||
class MeshExport MeshFixFoldsOnSurface : public MeshValidation
|
||||
{
|
||||
public:
|
||||
MeshFixFoldsOnSurface (MeshKernel &rclM) : MeshValidation( rclM ) { }
|
||||
~MeshFixFoldsOnSurface() {}
|
||||
|
||||
bool Fixup();
|
||||
};
|
||||
|
||||
/**
|
||||
* Considers a boundary triangle with two open edges and an angle higher than
|
||||
* 60 deg with its adjacent triangle as a boundary fold.
|
||||
* The topology is not affected there but such triangles can lead to problems
|
||||
* on some hole-filling algorithms.
|
||||
*/
|
||||
class MeshExport MeshEvalFoldsOnBoundary : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
@@ -424,6 +452,10 @@ public:
|
||||
bool Fixup();
|
||||
};
|
||||
|
||||
/**
|
||||
* Considers two adjacent triangles with an angle higher than 120 deg of their
|
||||
* normals as a fold-over. The topology is not affected there.
|
||||
*/
|
||||
class MeshExport MeshEvalFoldOversOnSurface : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -411,27 +411,26 @@ unsigned long MeshEvalTopology::CountManifolds() const
|
||||
|
||||
bool MeshFixTopology::Fixup ()
|
||||
{
|
||||
std::vector<unsigned long> indices;
|
||||
#if 0
|
||||
MeshEvalTopology eval(_rclMesh);
|
||||
if (!eval.Evaluate()) {
|
||||
eval.GetFacetManifolds(indices);
|
||||
eval.GetFacetManifolds(deletedFaces);
|
||||
|
||||
// remove duplicates
|
||||
std::sort(indices.begin(), indices.end());
|
||||
indices.erase(std::unique(indices.begin(), indices.end()), indices.end());
|
||||
std::sort(deletedFaces.begin(), deletedFaces.end());
|
||||
deletedFaces.erase(std::unique(deletedFaces.begin(), deletedFaces.end()), deletedFaces.end());
|
||||
|
||||
_rclMesh.DeleteFacets(indices);
|
||||
_rclMesh.DeleteFacets(deletedFaces);
|
||||
}
|
||||
#else
|
||||
const MeshFacetArray& rFaces = _rclMesh.GetFacets();
|
||||
indices.reserve(3 * nonManifoldList.size()); // allocate some memory
|
||||
deletedFaces.reserve(3 * nonManifoldList.size()); // allocate some memory
|
||||
std::list<std::vector<unsigned long> >::const_iterator it;
|
||||
for (it = nonManifoldList.begin(); it != nonManifoldList.end(); ++it) {
|
||||
std::vector<unsigned long> non_mf;
|
||||
non_mf.reserve(it->size());
|
||||
for (std::vector<unsigned long>::const_iterator jt = it->begin(); jt != it->end(); ++jt) {
|
||||
// fscet is only connected with one edge and there causes a non-manifold
|
||||
// facet is only connected with one edge and there causes a non-manifold
|
||||
unsigned short numOpenEdges = rFaces[*jt].CountOpenEdges();
|
||||
if (numOpenEdges == 2)
|
||||
non_mf.push_back(*jt);
|
||||
@@ -441,17 +440,17 @@ bool MeshFixTopology::Fixup ()
|
||||
|
||||
// are we able to repair the non-manifold edge by not removing all facets?
|
||||
if (it->size() - non_mf.size() == 2)
|
||||
indices.insert(indices.end(), non_mf.begin(), non_mf.end());
|
||||
deletedFaces.insert(deletedFaces.end(), non_mf.begin(), non_mf.end());
|
||||
else
|
||||
indices.insert(indices.end(), it->begin(), it->end());
|
||||
deletedFaces.insert(deletedFaces.end(), it->begin(), it->end());
|
||||
}
|
||||
|
||||
if (!indices.empty()) {
|
||||
if (!deletedFaces.empty()) {
|
||||
// remove duplicates
|
||||
std::sort(indices.begin(), indices.end());
|
||||
indices.erase(std::unique(indices.begin(), indices.end()), indices.end());
|
||||
std::sort(deletedFaces.begin(), deletedFaces.end());
|
||||
deletedFaces.erase(std::unique(deletedFaces.begin(), deletedFaces.end()), deletedFaces.end());
|
||||
|
||||
_rclMesh.DeleteFacets(indices);
|
||||
_rclMesh.DeleteFacets(deletedFaces);
|
||||
_rclMesh.RebuildNeighbours();
|
||||
}
|
||||
#endif
|
||||
@@ -461,6 +460,53 @@ bool MeshFixTopology::Fixup ()
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
bool MeshEvalPointManifolds::Evaluate ()
|
||||
{
|
||||
this->nonManifoldPoints.clear();
|
||||
this->facetsOfNonManifoldPoints.clear();
|
||||
|
||||
MeshCore::MeshRefPointToPoints vv_it(_rclMesh);
|
||||
MeshCore::MeshRefPointToFacets vf_it(_rclMesh);
|
||||
|
||||
unsigned long ctPoints = _rclMesh.CountPoints();
|
||||
for (unsigned long index=0; index < ctPoints; index++) {
|
||||
// get the local neighbourhood of the point
|
||||
const std::set<unsigned long>& nf = vf_it[index];
|
||||
const std::set<unsigned long>& np = vv_it[index];
|
||||
|
||||
std::set<unsigned long>::size_type sp, sf;
|
||||
sp = np.size();
|
||||
sf = nf.size();
|
||||
// for an inner point the number of adjacent points is equal to the number of shared faces
|
||||
// for a boundary point the number of adjacent points is higher by one than the number of shared faces
|
||||
// for a non-manifold point the number of adjacent points is higher by more than one than the number of shared faces
|
||||
if (sp > sf + 1) {
|
||||
nonManifoldPoints.push_back(index);
|
||||
std::vector<unsigned long> faces;
|
||||
faces.insert(faces.end(), nf.begin(), nf.end());
|
||||
this->facetsOfNonManifoldPoints.push_back(faces);
|
||||
}
|
||||
}
|
||||
|
||||
return this->nonManifoldPoints.empty();
|
||||
}
|
||||
|
||||
void MeshEvalPointManifolds::GetFacetIndices (std::vector<unsigned long> &facets) const
|
||||
{
|
||||
std::list<std::vector<unsigned long> >::const_iterator it;
|
||||
for (it = facetsOfNonManifoldPoints.begin(); it != facetsOfNonManifoldPoints.end(); ++it) {
|
||||
facets.insert(facets.end(), it->begin(), it->end());
|
||||
}
|
||||
|
||||
if (!facets.empty()) {
|
||||
// remove duplicates
|
||||
std::sort(facets.begin(), facets.end());
|
||||
facets.erase(std::unique(facets.begin(), facets.end()), facets.end());
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
bool MeshEvalSingleFacet::Evaluate ()
|
||||
{
|
||||
// get all non-manifolds
|
||||
|
||||
@@ -214,12 +214,40 @@ public:
|
||||
virtual ~MeshFixTopology () {}
|
||||
bool Fixup();
|
||||
|
||||
const std::vector<unsigned long>& GetDeletedFaces() const { return deletedFaces; }
|
||||
|
||||
protected:
|
||||
std::vector<unsigned long> deletedFaces;
|
||||
const std::list<std::vector<unsigned long> >& nonManifoldList;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
/**
|
||||
* The MeshEvalPointManifolds class checks for non-manifold points.
|
||||
* A point is considered non-manifold if two sets of triangles share
|
||||
* the point but are not topologically connected over a common edge.
|
||||
* Such mesh defects can lead to some very ugly folds on the surface.
|
||||
*/
|
||||
class MeshExport MeshEvalPointManifolds : public MeshEvaluation
|
||||
{
|
||||
public:
|
||||
MeshEvalPointManifolds (const MeshKernel &rclB) : MeshEvaluation(rclB) {}
|
||||
virtual ~MeshEvalPointManifolds () {}
|
||||
virtual bool Evaluate ();
|
||||
|
||||
void GetFacetIndices (std::vector<unsigned long> &facets) const;
|
||||
const std::list<std::vector<unsigned long> >& GetFacetIndices () const { return facetsOfNonManifoldPoints; }
|
||||
const std::vector<unsigned long>& GetIndices() const { return nonManifoldPoints; }
|
||||
unsigned long CountManifolds() const { return nonManifoldPoints.size(); }
|
||||
|
||||
protected:
|
||||
std::vector<unsigned long> nonManifoldPoints;
|
||||
std::list<std::vector<unsigned long> > facetsOfNonManifoldPoints;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------
|
||||
|
||||
/**
|
||||
* The MeshEvalSingleFacet class checks a special case of non-manifold edges as follows.
|
||||
* If an edge is shared by more than two facets and if all further facets causing this non-
|
||||
|
||||
@@ -50,16 +50,16 @@ void AbstractSmoothing::initialize(Component comp, Continuity cont)
|
||||
this->continuity = cont;
|
||||
}
|
||||
|
||||
MeshSmoothing::MeshSmoothing(MeshKernel& m)
|
||||
PlaneFitSmoothing::PlaneFitSmoothing(MeshKernel& m)
|
||||
: AbstractSmoothing(m)
|
||||
{
|
||||
}
|
||||
|
||||
MeshSmoothing::~MeshSmoothing()
|
||||
PlaneFitSmoothing::~PlaneFitSmoothing()
|
||||
{
|
||||
}
|
||||
|
||||
void MeshSmoothing::Smooth(unsigned int iterations)
|
||||
void PlaneFitSmoothing::Smooth(unsigned int iterations)
|
||||
{
|
||||
MeshCore::MeshPoint center;
|
||||
MeshCore::MeshPointArray PointArray = kernel.GetPoints();
|
||||
@@ -112,6 +112,60 @@ void MeshSmoothing::Smooth(unsigned int iterations)
|
||||
}
|
||||
}
|
||||
|
||||
void PlaneFitSmoothing::SmoothPoints(unsigned int iterations, const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
MeshCore::MeshPoint center;
|
||||
MeshCore::MeshPointArray PointArray = kernel.GetPoints();
|
||||
|
||||
MeshCore::MeshPointIterator v_it(kernel);
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
MeshCore::MeshPointArray::_TConstIterator v_beg = kernel.GetPoints().begin();
|
||||
|
||||
for (unsigned int i=0; i<iterations; i++) {
|
||||
Base::Vector3f N, L;
|
||||
for (std::vector<unsigned long>::const_iterator it = point_indices.begin(); it != point_indices.end(); ++it) {
|
||||
v_it.Set(*it);
|
||||
MeshCore::PlaneFit pf;
|
||||
pf.AddPoint(*v_it);
|
||||
center = *v_it;
|
||||
const std::set<unsigned long>& cv = vv_it[v_it.Position()];
|
||||
if (cv.size() < 3)
|
||||
continue;
|
||||
|
||||
std::set<unsigned long>::const_iterator cv_it;
|
||||
for (cv_it = cv.begin(); cv_it !=cv.end(); ++cv_it) {
|
||||
pf.AddPoint(v_beg[*cv_it]);
|
||||
center += v_beg[*cv_it];
|
||||
}
|
||||
|
||||
float scale = 1.0f/((float)cv.size()+1.0f);
|
||||
center.Scale(scale,scale,scale);
|
||||
|
||||
// get the mean plane of the current vertex with the surrounding vertices
|
||||
pf.Fit();
|
||||
N = pf.GetNormal();
|
||||
N.Normalize();
|
||||
|
||||
// look in which direction we should move the vertex
|
||||
L.Set(v_it->x - center.x, v_it->y - center.y, v_it->z - center.z);
|
||||
if (N*L < 0.0)
|
||||
N.Scale(-1.0, -1.0, -1.0);
|
||||
|
||||
// maximum value to move is distance to mean plane
|
||||
float d = std::min<float>((float)fabs(this->tolerance),(float)fabs(N*L));
|
||||
N.Scale(d,d,d);
|
||||
|
||||
PointArray[v_it.Position()].Set(v_it->x - N.x, v_it->y - N.y, v_it->z - N.z);
|
||||
}
|
||||
|
||||
// assign values without affecting iterators
|
||||
unsigned long count = kernel.CountPoints();
|
||||
for (unsigned long idx = 0; idx < count; idx++) {
|
||||
kernel.SetPoint(idx, PointArray[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaplaceSmoothing::LaplaceSmoothing(MeshKernel& m)
|
||||
: AbstractSmoothing(m), lambda(0.6307)
|
||||
{
|
||||
@@ -157,6 +211,41 @@ void LaplaceSmoothing::Umbrella(const MeshRefPointToPoints& vv_it,
|
||||
}
|
||||
}
|
||||
|
||||
void LaplaceSmoothing::Umbrella(const MeshRefPointToPoints& vv_it,
|
||||
const MeshRefPointToFacets& vf_it, double stepsize,
|
||||
const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
const MeshCore::MeshPointArray& points = kernel.GetPoints();
|
||||
MeshCore::MeshPointArray::_TConstIterator v_beg = points.begin();
|
||||
|
||||
for (std::vector<unsigned long>::const_iterator pos = point_indices.begin(); pos != point_indices.end(); ++pos) {
|
||||
const std::set<unsigned long>& cv = vv_it[*pos];
|
||||
if (cv.size() < 3)
|
||||
continue;
|
||||
if (cv.size() != vf_it[*pos].size()) {
|
||||
// do nothing for border points
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int n_count = cv.size();
|
||||
double w;
|
||||
w=1.0/double(n_count);
|
||||
|
||||
double delx=0.0,dely=0.0,delz=0.0;
|
||||
std::set<unsigned long>::const_iterator cv_it;
|
||||
for (cv_it = cv.begin(); cv_it !=cv.end(); ++cv_it) {
|
||||
delx += w*((v_beg[*cv_it]).x-(v_beg[*pos]).x);
|
||||
dely += w*((v_beg[*cv_it]).y-(v_beg[*pos]).y);
|
||||
delz += w*((v_beg[*cv_it]).z-(v_beg[*pos]).z);
|
||||
}
|
||||
|
||||
float x = (float)((v_beg[*pos]).x+stepsize*delx);
|
||||
float y = (float)((v_beg[*pos]).y+stepsize*dely);
|
||||
float z = (float)((v_beg[*pos]).z+stepsize*delz);
|
||||
kernel.SetPoint(*pos,x,y,z);
|
||||
}
|
||||
}
|
||||
|
||||
void LaplaceSmoothing::Smooth(unsigned int iterations)
|
||||
{
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
@@ -167,6 +256,16 @@ void LaplaceSmoothing::Smooth(unsigned int iterations)
|
||||
}
|
||||
}
|
||||
|
||||
void LaplaceSmoothing::SmoothPoints(unsigned int iterations, const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
MeshCore::MeshRefPointToFacets vf_it(kernel);
|
||||
|
||||
for (unsigned int i=0; i<iterations; i++) {
|
||||
Umbrella(vv_it, vf_it, lambda, point_indices);
|
||||
}
|
||||
}
|
||||
|
||||
TaubinSmoothing::TaubinSmoothing(MeshKernel& m)
|
||||
: LaplaceSmoothing(m), micro(0.0424)
|
||||
{
|
||||
@@ -189,3 +288,17 @@ void TaubinSmoothing::Smooth(unsigned int iterations)
|
||||
Umbrella(vv_it, vf_it, -(lambda+micro));
|
||||
}
|
||||
}
|
||||
|
||||
void TaubinSmoothing::SmoothPoints(unsigned int iterations, const std::vector<unsigned long>& point_indices)
|
||||
{
|
||||
MeshCore::MeshPointArray::_TConstIterator v_it;
|
||||
MeshCore::MeshRefPointToPoints vv_it(kernel);
|
||||
MeshCore::MeshRefPointToFacets vf_it(kernel);
|
||||
|
||||
// Theoretically Taubin does not shrink the surface
|
||||
iterations = (iterations+1)/2; // two steps per iteration
|
||||
for (unsigned int i=0; i<iterations; i++) {
|
||||
Umbrella(vv_it, vf_it, lambda, point_indices);
|
||||
Umbrella(vv_it, vf_it, -(lambda+micro), point_indices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#ifndef MESH_SMOOTHING_H
|
||||
#define MESH_SMOOTHING_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace MeshCore
|
||||
{
|
||||
class MeshKernel;
|
||||
@@ -52,6 +54,7 @@ public:
|
||||
|
||||
/** Smooth the triangle mesh. */
|
||||
virtual void Smooth(unsigned int) = 0;
|
||||
virtual void SmoothPoints(unsigned int, const std::vector<unsigned long>&) = 0;
|
||||
|
||||
protected:
|
||||
MeshKernel& kernel;
|
||||
@@ -61,12 +64,13 @@ protected:
|
||||
Continuity continuity;
|
||||
};
|
||||
|
||||
class MeshExport MeshSmoothing : public AbstractSmoothing
|
||||
class MeshExport PlaneFitSmoothing : public AbstractSmoothing
|
||||
{
|
||||
public:
|
||||
MeshSmoothing(MeshKernel&);
|
||||
virtual ~MeshSmoothing();
|
||||
PlaneFitSmoothing(MeshKernel&);
|
||||
virtual ~PlaneFitSmoothing();
|
||||
void Smooth(unsigned int);
|
||||
void SmoothPoints(unsigned int, const std::vector<unsigned long>&);
|
||||
};
|
||||
|
||||
class MeshExport LaplaceSmoothing : public AbstractSmoothing
|
||||
@@ -75,11 +79,15 @@ public:
|
||||
LaplaceSmoothing(MeshKernel&);
|
||||
virtual ~LaplaceSmoothing();
|
||||
void Smooth(unsigned int);
|
||||
void SmoothPoints(unsigned int, const std::vector<unsigned long>&);
|
||||
void SetLambda(double l) { lambda = l;}
|
||||
|
||||
protected:
|
||||
void Umbrella(const MeshRefPointToPoints&,
|
||||
const MeshRefPointToFacets&, double);
|
||||
void Umbrella(const MeshRefPointToPoints&,
|
||||
const MeshRefPointToFacets&, double,
|
||||
const std::vector<unsigned long>&);
|
||||
|
||||
protected:
|
||||
double lambda;
|
||||
@@ -91,6 +99,7 @@ public:
|
||||
TaubinSmoothing(MeshKernel&);
|
||||
virtual ~TaubinSmoothing();
|
||||
void Smooth(unsigned int);
|
||||
void SmoothPoints(unsigned int, const std::vector<unsigned long>&);
|
||||
void SetMicro(double m) { micro = m;}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1108,15 +1108,18 @@ bool MeshObject::hasNonManifolds() const
|
||||
|
||||
void MeshObject::removeNonManifolds()
|
||||
{
|
||||
unsigned long count = _kernel.CountFacets();
|
||||
MeshCore::MeshEvalTopology cMeshEval(_kernel);
|
||||
if (!cMeshEval.Evaluate()) {
|
||||
MeshCore::MeshFixTopology cMeshFix(_kernel, cMeshEval.GetFacets());
|
||||
cMeshFix.Fixup();
|
||||
MeshCore::MeshEvalTopology f_eval(_kernel);
|
||||
if (!f_eval.Evaluate()) {
|
||||
MeshCore::MeshFixTopology f_fix(_kernel, f_eval.GetFacets());
|
||||
f_fix.Fixup();
|
||||
deletedFacets(f_fix.GetDeletedFaces());
|
||||
}
|
||||
MeshCore::MeshEvalPointManifolds p_eval(_kernel);
|
||||
if (!p_eval.Evaluate()) {
|
||||
std::vector<unsigned long> faces;
|
||||
p_eval.GetFacetIndices(faces);
|
||||
deleteFacets(faces);
|
||||
}
|
||||
|
||||
if (_kernel.CountFacets() < count)
|
||||
this->_segments.clear();
|
||||
}
|
||||
|
||||
bool MeshObject::hasSelfIntersections() const
|
||||
|
||||
@@ -124,6 +124,7 @@ void MeshGuiExport initMeshGui()
|
||||
MeshGui::ViewProviderMeshDefects ::init();
|
||||
MeshGui::ViewProviderMeshOrientation ::init();
|
||||
MeshGui::ViewProviderMeshNonManifolds ::init();
|
||||
MeshGui::ViewProviderMeshNonManifoldPoints ::init();
|
||||
MeshGui::ViewProviderMeshDuplicatedFaces ::init();
|
||||
MeshGui::ViewProviderMeshDuplicatedPoints ::init();
|
||||
MeshGui::ViewProviderMeshDegenerations ::init();
|
||||
|
||||
@@ -478,29 +478,37 @@ void DlgEvaluateMeshImp::on_analyzeNonmanifoldsButton_clicked()
|
||||
qApp->setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
const MeshKernel& rMesh = d->meshFeature->Mesh.getValue().getKernel();
|
||||
MeshEvalTopology eval(rMesh);
|
||||
MeshEvalTopology f_eval(rMesh);
|
||||
MeshEvalPointManifolds p_eval(rMesh);
|
||||
bool ok1 = f_eval.Evaluate();
|
||||
bool ok2 = p_eval.Evaluate();
|
||||
|
||||
if (eval.Evaluate()) {
|
||||
if (ok1 && ok2) {
|
||||
checkNonmanifoldsButton->setText(tr("No non-manifolds"));
|
||||
checkNonmanifoldsButton->setChecked(false);
|
||||
repairNonmanifoldsButton->setEnabled(false);
|
||||
removeViewProvider("MeshGui::ViewProviderMeshNonManifolds");
|
||||
}
|
||||
else {
|
||||
checkNonmanifoldsButton->setText(tr("%1 non-manifolds").arg(eval.CountManifolds()));
|
||||
checkNonmanifoldsButton->setText(tr("%1 non-manifolds").arg(f_eval.CountManifolds()+p_eval.CountManifolds()));
|
||||
checkNonmanifoldsButton->setChecked(true);
|
||||
repairNonmanifoldsButton->setEnabled(true);
|
||||
repairAllTogether->setEnabled(true);
|
||||
const std::vector<std::pair<unsigned long, unsigned long> >& inds = eval.GetIndices();
|
||||
std::vector<unsigned long> indices;
|
||||
indices.reserve(2*inds.size());
|
||||
std::vector<std::pair<unsigned long, unsigned long> >::const_iterator it;
|
||||
for (it = inds.begin(); it != inds.end(); ++it) {
|
||||
indices.push_back(it->first);
|
||||
indices.push_back(it->second);
|
||||
}
|
||||
if (!ok1) {
|
||||
const std::vector<std::pair<unsigned long, unsigned long> >& inds = f_eval.GetIndices();
|
||||
std::vector<unsigned long> indices;
|
||||
indices.reserve(2*inds.size());
|
||||
std::vector<std::pair<unsigned long, unsigned long> >::const_iterator it;
|
||||
for (it = inds.begin(); it != inds.end(); ++it) {
|
||||
indices.push_back(it->first);
|
||||
indices.push_back(it->second);
|
||||
}
|
||||
|
||||
addViewProvider("MeshGui::ViewProviderMeshNonManifolds", indices);
|
||||
addViewProvider("MeshGui::ViewProviderMeshNonManifolds", indices);
|
||||
}
|
||||
if (!ok2) {
|
||||
addViewProvider("MeshGui::ViewProviderMeshNonManifoldPoints", p_eval.GetIndices());
|
||||
}
|
||||
}
|
||||
|
||||
qApp->restoreOverrideCursor();
|
||||
@@ -1124,9 +1132,9 @@ void DlgEvaluateMeshImp::on_repairAllTogether_clicked()
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR MeshGui::DockEvaluateMeshImp */
|
||||
|
||||
/* TRANSLATOR MeshGui::DockEvaluateMeshImp */
|
||||
|
||||
#if 0 // needed for Qt's lupdate utility
|
||||
qApp->translate("QDockWidget", "Evaluate & Repair Mesh");
|
||||
#endif
|
||||
|
||||
@@ -59,6 +59,7 @@ using namespace MeshGui;
|
||||
PROPERTY_SOURCE_ABSTRACT(MeshGui::ViewProviderMeshDefects, Gui::ViewProviderDocumentObject)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshOrientation, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshNonManifolds, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshNonManifoldPoints, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshDuplicatedFaces, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshDuplicatedPoints, MeshGui::ViewProviderMeshDefects)
|
||||
PROPERTY_SOURCE(MeshGui::ViewProviderMeshDegenerations, MeshGui::ViewProviderMeshDefects)
|
||||
@@ -234,6 +235,63 @@ void ViewProviderMeshNonManifolds::showDefects(const std::vector<unsigned long>&
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
ViewProviderMeshNonManifoldPoints::ViewProviderMeshNonManifoldPoints()
|
||||
{
|
||||
pcPoints = new SoPointSet;
|
||||
pcPoints->ref();
|
||||
}
|
||||
|
||||
ViewProviderMeshNonManifoldPoints::~ViewProviderMeshNonManifoldPoints()
|
||||
{
|
||||
pcPoints->unref();
|
||||
}
|
||||
|
||||
void ViewProviderMeshNonManifoldPoints::attach(App::DocumentObject* pcFeat)
|
||||
{
|
||||
ViewProviderDocumentObject::attach( pcFeat );
|
||||
|
||||
SoGroup* pcPointRoot = new SoGroup();
|
||||
pcDrawStyle->pointSize = 3;
|
||||
pcPointRoot->addChild(pcDrawStyle);
|
||||
|
||||
// Draw points
|
||||
SoSeparator* pointsep = new SoSeparator;
|
||||
SoBaseColor * basecol = new SoBaseColor;
|
||||
basecol->rgb.setValue( 1.0f, 0.5f, 0.0f );
|
||||
pointsep->addChild(basecol);
|
||||
pointsep->addChild(pcCoords);
|
||||
pointsep->addChild(pcPoints);
|
||||
pcPointRoot->addChild(pointsep);
|
||||
|
||||
// Draw markers
|
||||
SoBaseColor * markcol = new SoBaseColor;
|
||||
markcol->rgb.setValue( 1.0f, 1.0f, 0.0f );
|
||||
SoMarkerSet* marker = new SoMarkerSet;
|
||||
marker->markerIndex=SoMarkerSet::PLUS_7_7;
|
||||
pointsep->addChild(markcol);
|
||||
pointsep->addChild(marker);
|
||||
|
||||
addDisplayMaskMode(pcPointRoot, "Point");
|
||||
}
|
||||
|
||||
void ViewProviderMeshNonManifoldPoints::showDefects(const std::vector<unsigned long>& inds)
|
||||
{
|
||||
Mesh::Feature* f = dynamic_cast<Mesh::Feature*>(pcObject);
|
||||
const MeshCore::MeshKernel & rMesh = f->Mesh.getValue().getKernel();
|
||||
pcCoords->point.deleteValues(0);
|
||||
pcCoords->point.setNum(inds.size());
|
||||
MeshCore::MeshPointIterator cP(rMesh);
|
||||
unsigned long i = 0;
|
||||
for ( std::vector<unsigned long>::const_iterator it = inds.begin(); it != inds.end(); ++it ) {
|
||||
cP.Set(*it);
|
||||
pcCoords->point.set1Value(i++,cP->x,cP->y,cP->z);
|
||||
}
|
||||
|
||||
setDisplayMaskMode("Point");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
ViewProviderMeshDuplicatedFaces::ViewProviderMeshDuplicatedFaces()
|
||||
{
|
||||
pcFaces = new SoFaceSet;
|
||||
|
||||
@@ -96,6 +96,24 @@ protected:
|
||||
SoLineSet* pcLines;
|
||||
};
|
||||
|
||||
/** The ViewProviderMeshNonManifoldPoints class displays non-manifold vertexes in red.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
class MeshGuiExport ViewProviderMeshNonManifoldPoints : public ViewProviderMeshDefects
|
||||
{
|
||||
PROPERTY_HEADER(MeshGui::ViewProviderMeshNonManifoldPoints);
|
||||
|
||||
public:
|
||||
ViewProviderMeshNonManifoldPoints();
|
||||
virtual ~ViewProviderMeshNonManifoldPoints();
|
||||
|
||||
void attach(App::DocumentObject* pcFeature);
|
||||
void showDefects(const std::vector<unsigned long>&);
|
||||
|
||||
protected:
|
||||
SoPointSet* pcPoints;
|
||||
};
|
||||
|
||||
/** The ViewProviderMeshDuplicatedFaces class displays duplicated faces in red.
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
|
||||
@@ -162,30 +162,10 @@ void Part2DObject::positionBySupport(void)
|
||||
gp_Trsf Trf;
|
||||
Trf.SetTransformation(SketchPos);
|
||||
Trf.Invert();
|
||||
Trf.SetScaleFactor(Standard_Real(1.0));
|
||||
|
||||
Base::Matrix4D mtrx;
|
||||
|
||||
gp_Mat m = Trf._CSFDB_Getgp_Trsfmatrix();
|
||||
gp_XYZ p = Trf._CSFDB_Getgp_Trsfloc();
|
||||
Standard_Real scale = 1.0;
|
||||
|
||||
// set Rotation matrix
|
||||
mtrx[0][0] = scale * m._CSFDB_Getgp_Matmatrix(0,0);
|
||||
mtrx[0][1] = scale * m._CSFDB_Getgp_Matmatrix(0,1);
|
||||
mtrx[0][2] = scale * m._CSFDB_Getgp_Matmatrix(0,2);
|
||||
|
||||
mtrx[1][0] = scale * m._CSFDB_Getgp_Matmatrix(1,0);
|
||||
mtrx[1][1] = scale * m._CSFDB_Getgp_Matmatrix(1,1);
|
||||
mtrx[1][2] = scale * m._CSFDB_Getgp_Matmatrix(1,2);
|
||||
|
||||
mtrx[2][0] = scale * m._CSFDB_Getgp_Matmatrix(2,0);
|
||||
mtrx[2][1] = scale * m._CSFDB_Getgp_Matmatrix(2,1);
|
||||
mtrx[2][2] = scale * m._CSFDB_Getgp_Matmatrix(2,2);
|
||||
|
||||
// set pos vector
|
||||
mtrx[0][3] = p._CSFDB_Getgp_XYZx();
|
||||
mtrx[1][3] = p._CSFDB_Getgp_XYZy();
|
||||
mtrx[2][3] = p._CSFDB_Getgp_XYZz();
|
||||
TopoShape::convertToMatrix(Trf,mtrx);
|
||||
|
||||
// check the angle against the Z Axis
|
||||
//Standard_Real a = Normal.Angle(gp_Ax1(gp_Pnt(0,0,0),gp_Dir(0,0,1)));
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
# include <gp_Trsf.hxx>
|
||||
# include <gp_Ax1.hxx>
|
||||
# include <BRepBuilderAPI_MakeShape.hxx>
|
||||
# include <BRepAlgoAPI_Fuse.hxx>
|
||||
# include <BRepAlgoAPI_Common.hxx>
|
||||
# include <TopTools_ListIteratorOfListOfShape.hxx>
|
||||
# include <TopExp.hxx>
|
||||
@@ -336,33 +337,50 @@ std::vector<Part::cutFaces> Part::findAllFacesCutBy(
|
||||
return result;
|
||||
}
|
||||
|
||||
const bool Part::checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second, const bool quick) {
|
||||
const bool Part::checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second,
|
||||
const bool quick, const bool touch_is_intersection) {
|
||||
Bnd_Box first_bb, second_bb;
|
||||
BRepBndLib::Add(first, first_bb);
|
||||
first_bb.SetGap(0);
|
||||
BRepBndLib::Add(second, second_bb);
|
||||
second_bb.SetGap(0);
|
||||
|
||||
// Note: Both tests fail if the objects are touching one another at zero distance!
|
||||
// Note: This test fails if the objects are touching one another at zero distance
|
||||
if (first_bb.IsOut(second_bb))
|
||||
return false; // no intersection
|
||||
//if (first_bb.Distance(second_bb) > Precision::Confusion())
|
||||
// return false;
|
||||
if (quick)
|
||||
return true; // assumed intersection
|
||||
|
||||
// Try harder
|
||||
BRepAlgoAPI_Common mkCommon(first, second);
|
||||
// FIXME: Error in boolean operation, return true by default
|
||||
if (!mkCommon.IsDone())
|
||||
return true;
|
||||
if (mkCommon.Shape().IsNull())
|
||||
return true;
|
||||
if (touch_is_intersection) {
|
||||
// If both shapes fuse to a single solid, then they intersect
|
||||
BRepAlgoAPI_Fuse mkFuse(first, second);
|
||||
if (!mkFuse.IsDone())
|
||||
return false;
|
||||
if (mkFuse.Shape().IsNull())
|
||||
return false;
|
||||
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(mkCommon.Shape(),TopAbs_SOLID);
|
||||
if (xp.More())
|
||||
return true;
|
||||
// Did we get one or two solids?
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(mkFuse.Shape(),TopAbs_SOLID);
|
||||
if (xp.More()) {
|
||||
// At least one solid
|
||||
xp.Next();
|
||||
return (xp.More() == Standard_False);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// If both shapes have common material, then they intersect
|
||||
BRepAlgoAPI_Common mkCommon(first, second);
|
||||
if (!mkCommon.IsDone())
|
||||
return false;
|
||||
if (mkCommon.Shape().IsNull())
|
||||
return false;
|
||||
|
||||
return false;
|
||||
// Did we get a solid?
|
||||
TopExp_Explorer xp;
|
||||
xp.Init(mkCommon.Shape(),TopAbs_SOLID);
|
||||
return (xp.More() == Standard_True);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,10 +141,18 @@ std::vector<cutFaces> findAllFacesCutBy(const TopoDS_Shape& shape,
|
||||
* 1. Bounding box check only - quick but inaccurate
|
||||
* 2. Bounding box check plus (if necessary) boolean operation - costly but accurate
|
||||
* Return true if the shapes intersect, false if they don't
|
||||
* The flag touch_is_intersection decides whether shapes touching at distance zero are regarded
|
||||
* as intersecting or not
|
||||
* 1. If set to true, a true check result means that a boolean fuse operation between the two shapes
|
||||
* will return a single solid
|
||||
* 2. If set to false, a true check result means that a boolean common operation will return a
|
||||
* valid solid
|
||||
* If there is any error in the boolean operations, the check always returns false
|
||||
*/
|
||||
PartExport
|
||||
const bool checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second, const bool quick = true);
|
||||
|
||||
const bool checkIntersection(const TopoDS_Shape& first, const TopoDS_Shape& second,
|
||||
const bool quick, const bool touch_is_intersection);
|
||||
|
||||
} //namespace Part
|
||||
|
||||
|
||||
|
||||
@@ -259,12 +259,16 @@ App::DocumentObjectExecReturn *Sweep::execute(void)
|
||||
path = mkWire.Wire();
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
if (shape._Shape.ShapeType() == TopAbs_EDGE)
|
||||
if (shape._Shape.ShapeType() == TopAbs_EDGE) {
|
||||
path = shape._Shape;
|
||||
else if (shape._Shape.ShapeType() == TopAbs_WIRE)
|
||||
path = shape._Shape;
|
||||
else
|
||||
}
|
||||
else if (shape._Shape.ShapeType() == TopAbs_WIRE) {
|
||||
BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape._Shape));
|
||||
path = mkWire.Wire();
|
||||
}
|
||||
else {
|
||||
return new App::DocumentObjectExecReturn("Spine is neither an edge nor a wire.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +195,30 @@ int TopoShapeFacePy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
|
||||
if (!wires.empty()) {
|
||||
BRepBuilderAPI_MakeFace mkFace(wires.front());
|
||||
if (!mkFace.IsDone()) {
|
||||
switch (mkFace.Error()) {
|
||||
case BRepBuilderAPI_NoFace:
|
||||
Standard_Failure::Raise("No face");
|
||||
break;
|
||||
case BRepBuilderAPI_NotPlanar:
|
||||
Standard_Failure::Raise("Not planar");
|
||||
break;
|
||||
case BRepBuilderAPI_CurveProjectionFailed:
|
||||
Standard_Failure::Raise("Curve projection failed");
|
||||
break;
|
||||
case BRepBuilderAPI_ParametersOutOfRange:
|
||||
Standard_Failure::Raise("Parameters out of range");
|
||||
break;
|
||||
#if OCC_HEX_VERSION < 0x060500
|
||||
case BRepBuilderAPI_SurfaceNotC2:
|
||||
Standard_Failure::Raise("Surface not C2");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
Standard_Failure::Raise("Unknown failure");
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (std::vector<TopoDS_Wire>::iterator it = wires.begin()+1; it != wires.end(); ++it)
|
||||
mkFace.Add(*it);
|
||||
getTopoShapePtr()->_Shape = mkFace.Face();
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
# include <BRepAlgoAPI_Cut.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <gp_Lin.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
# include <BRepGProp.hxx>
|
||||
#endif
|
||||
|
||||
#include <Base/Axis.h>
|
||||
@@ -83,49 +85,17 @@ App::DocumentObjectExecReturn *Groove::execute(void)
|
||||
if (Reversed.getValue() && !Midplane.getValue())
|
||||
angle *= (-1.0);
|
||||
|
||||
Part::Part2DObject* sketch = 0;
|
||||
std::vector<TopoDS_Wire> wires;
|
||||
TopoDS_Shape support;
|
||||
try {
|
||||
sketch = getVerifiedSketch();
|
||||
wires = getSketchWires();
|
||||
support = getSupportShape();
|
||||
} catch (const Base::Exception& e) {
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
}
|
||||
|
||||
// get the Sketch plane
|
||||
Base::Placement SketchPlm = sketch->Placement.getValue();
|
||||
|
||||
// get reference axis
|
||||
App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue();
|
||||
const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues();
|
||||
if (pcReferenceAxis && pcReferenceAxis == sketch) {
|
||||
bool hasValidAxis=false;
|
||||
Base::Axis axis;
|
||||
if (subReferenceAxis[0] == "V_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::V_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0] == "H_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::H_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") {
|
||||
int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str());
|
||||
if (AxId >= 0 && AxId < sketch->getAxisCount()) {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(AxId);
|
||||
}
|
||||
}
|
||||
if (hasValidAxis) {
|
||||
axis *= SketchPlm;
|
||||
Base::Vector3d base=axis.getBase();
|
||||
Base::Vector3d dir=axis.getDirection();
|
||||
Base.setValue(base.x,base.y,base.z);
|
||||
Axis.setValue(dir.x,dir.y,dir.z);
|
||||
}
|
||||
}
|
||||
// update Axis from ReferenceAxis
|
||||
updateAxis();
|
||||
|
||||
// get revolve axis
|
||||
Base::Vector3f b = Base.getValue();
|
||||
@@ -196,4 +166,77 @@ App::DocumentObjectExecReturn *Groove::execute(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool Groove::suggestReversed(void)
|
||||
{
|
||||
try {
|
||||
updateAxis();
|
||||
|
||||
Part::Part2DObject* sketch = getVerifiedSketch();
|
||||
std::vector<TopoDS_Wire> wires = getSketchWires();
|
||||
TopoDS_Shape sketchshape = makeFace(wires);
|
||||
|
||||
Base::Vector3f b = Base.getValue();
|
||||
Base::Vector3f v = Axis.getValue();
|
||||
|
||||
// get centre of gravity of the sketch face
|
||||
GProp_GProps props;
|
||||
BRepGProp::SurfaceProperties(sketchshape, props);
|
||||
gp_Pnt cog = props.CentreOfMass();
|
||||
Base::Vector3f p_cog(cog.X(), cog.Y(), cog.Z());
|
||||
// get direction to cog from its projection on the revolve axis
|
||||
Base::Vector3f perp_dir = p_cog - p_cog.Perpendicular(b, v);
|
||||
// get cross product of projection direction with revolve axis direction
|
||||
Base::Vector3f cross = v % perp_dir;
|
||||
// get sketch vector pointing away from support material
|
||||
Base::Placement SketchPos = sketch->Placement.getValue();
|
||||
Base::Rotation SketchOrientation = SketchPos.getRotation();
|
||||
Base::Vector3d SketchNormal(0,0,1);
|
||||
SketchOrientation.multVec(SketchNormal,SketchNormal);
|
||||
// simply convert double to float
|
||||
Base::Vector3f norm(SketchNormal.x, SketchNormal.y, SketchNormal.z);
|
||||
|
||||
// return true if the angle between norm and cross is acute
|
||||
return norm * cross > 0.f;
|
||||
}
|
||||
catch (...) {
|
||||
return Reversed.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
void Groove::updateAxis(void)
|
||||
{
|
||||
Part::Part2DObject* sketch = getVerifiedSketch();
|
||||
Base::Placement SketchPlm = sketch->Placement.getValue();
|
||||
|
||||
// get reference axis
|
||||
App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue();
|
||||
const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues();
|
||||
if (pcReferenceAxis && pcReferenceAxis == sketch) {
|
||||
bool hasValidAxis=false;
|
||||
Base::Axis axis;
|
||||
if (subReferenceAxis[0] == "V_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::V_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0] == "H_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::H_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") {
|
||||
int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str());
|
||||
if (AxId >= 0 && AxId < sketch->getAxisCount()) {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(AxId);
|
||||
}
|
||||
}
|
||||
if (hasValidAxis) {
|
||||
axis *= SketchPlm;
|
||||
Base::Vector3d base=axis.getBase();
|
||||
Base::Vector3d dir=axis.getDirection();
|
||||
Base.setValue(base.x,base.y,base.z);
|
||||
Axis.setValue(dir.x,dir.y,dir.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,6 +62,12 @@ public:
|
||||
return "PartDesignGui::ViewProviderGroove";
|
||||
}
|
||||
//@}
|
||||
|
||||
/// suggests a value for Reversed flag so that material is always removed from the support
|
||||
bool suggestReversed(void);
|
||||
protected:
|
||||
/// updates Axis from ReferenceAxis
|
||||
void updateAxis(void);
|
||||
};
|
||||
|
||||
} //namespace PartDesign
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
# include <BRepAlgoAPI_Fuse.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <gp_Lin.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
# include <BRepGProp.hxx>
|
||||
#endif
|
||||
|
||||
#include <Base/Axis.h>
|
||||
@@ -41,7 +43,6 @@
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#include "FeatureRevolution.h"
|
||||
#include <Base/Console.h>
|
||||
|
||||
|
||||
using namespace PartDesign;
|
||||
@@ -75,19 +76,17 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||
// Validate parameters
|
||||
double angle = Angle.getValue();
|
||||
if (angle < Precision::Confusion())
|
||||
return new App::DocumentObjectExecReturn("Angle of groove too small");
|
||||
return new App::DocumentObjectExecReturn("Angle of revolution too small");
|
||||
if (angle > 360.0)
|
||||
return new App::DocumentObjectExecReturn("Angle of groove too large");
|
||||
return new App::DocumentObjectExecReturn("Angle of revolution too large");
|
||||
|
||||
angle = Base::toRadians<double>(angle);
|
||||
// Reverse angle if selected
|
||||
if (Reversed.getValue() && !Midplane.getValue())
|
||||
angle *= (-1.0);
|
||||
|
||||
Part::Part2DObject* sketch = 0;
|
||||
std::vector<TopoDS_Wire> wires;
|
||||
try {
|
||||
sketch = getVerifiedSketch();
|
||||
wires = getSketchWires();
|
||||
} catch (const Base::Exception& e) {
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
@@ -101,41 +100,8 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||
support = TopoDS_Shape();
|
||||
}
|
||||
|
||||
// get the Sketch plane
|
||||
Base::Placement SketchPlm = sketch->Placement.getValue();
|
||||
|
||||
// get reference axis
|
||||
App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue();
|
||||
const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues();
|
||||
bool hasValidAxis=false;
|
||||
if (pcReferenceAxis && pcReferenceAxis == sketch) {
|
||||
Base::Axis axis;
|
||||
if (subReferenceAxis[0] == "V_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::V_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0] == "H_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::H_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") {
|
||||
int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str());
|
||||
if (AxId >= 0 && AxId < sketch->getAxisCount()) {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(AxId);
|
||||
}
|
||||
}
|
||||
if (hasValidAxis) {
|
||||
axis *= SketchPlm;
|
||||
Base::Vector3d base=axis.getBase();
|
||||
Base::Vector3d dir=axis.getDirection();
|
||||
Base.setValue(base.x,base.y,base.z);
|
||||
Axis.setValue(dir.x,dir.y,dir.z);
|
||||
}
|
||||
}
|
||||
if (!hasValidAxis) {
|
||||
return new App::DocumentObjectExecReturn("No valid reference axis defined");
|
||||
}
|
||||
// update Axis from ReferenceAxis
|
||||
updateAxis();
|
||||
|
||||
// get revolve axis
|
||||
Base::Vector3f b = Base.getValue();
|
||||
@@ -204,5 +170,78 @@ App::DocumentObjectExecReturn *Revolution::execute(void)
|
||||
return new App::DocumentObjectExecReturn(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool Revolution::suggestReversed(void)
|
||||
{
|
||||
try {
|
||||
updateAxis();
|
||||
|
||||
Part::Part2DObject* sketch = getVerifiedSketch();
|
||||
std::vector<TopoDS_Wire> wires = getSketchWires();
|
||||
TopoDS_Shape sketchshape = makeFace(wires);
|
||||
|
||||
Base::Vector3f b = Base.getValue();
|
||||
Base::Vector3f v = Axis.getValue();
|
||||
|
||||
// get centre of gravity of the sketch face
|
||||
GProp_GProps props;
|
||||
BRepGProp::SurfaceProperties(sketchshape, props);
|
||||
gp_Pnt cog = props.CentreOfMass();
|
||||
Base::Vector3f p_cog(cog.X(), cog.Y(), cog.Z());
|
||||
// get direction to cog from its projection on the revolve axis
|
||||
Base::Vector3f perp_dir = p_cog - p_cog.Perpendicular(b, v);
|
||||
// get cross product of projection direction with revolve axis direction
|
||||
Base::Vector3f cross = v % perp_dir;
|
||||
// get sketch vector pointing away from support material
|
||||
Base::Placement SketchPos = sketch->Placement.getValue();
|
||||
Base::Rotation SketchOrientation = SketchPos.getRotation();
|
||||
Base::Vector3d SketchNormal(0,0,1);
|
||||
SketchOrientation.multVec(SketchNormal,SketchNormal);
|
||||
// simply convert double to float
|
||||
Base::Vector3f norm(SketchNormal.x, SketchNormal.y, SketchNormal.z);
|
||||
|
||||
// return true if the angle between norm and cross is obtuse
|
||||
return norm * cross < 0.f;
|
||||
}
|
||||
catch (...) {
|
||||
return Reversed.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
void Revolution::updateAxis(void)
|
||||
{
|
||||
Part::Part2DObject* sketch = getVerifiedSketch();
|
||||
Base::Placement SketchPlm = sketch->Placement.getValue();
|
||||
|
||||
// get reference axis
|
||||
App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue();
|
||||
const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues();
|
||||
if (pcReferenceAxis && pcReferenceAxis == sketch) {
|
||||
bool hasValidAxis=false;
|
||||
Base::Axis axis;
|
||||
if (subReferenceAxis[0] == "V_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::V_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0] == "H_Axis") {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(Part::Part2DObject::H_Axis);
|
||||
}
|
||||
else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") {
|
||||
int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str());
|
||||
if (AxId >= 0 && AxId < sketch->getAxisCount()) {
|
||||
hasValidAxis = true;
|
||||
axis = sketch->getAxis(AxId);
|
||||
}
|
||||
}
|
||||
if (hasValidAxis) {
|
||||
axis *= SketchPlm;
|
||||
Base::Vector3d base=axis.getBase();
|
||||
Base::Vector3d dir=axis.getDirection();
|
||||
Base.setValue(base.x,base.y,base.z);
|
||||
Axis.setValue(dir.x,dir.y,dir.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,6 +62,12 @@ public:
|
||||
return "PartDesignGui::ViewProviderRevolution";
|
||||
}
|
||||
//@}
|
||||
|
||||
/// suggests a value for Reversed flag so that material is always added to the support
|
||||
bool suggestReversed(void);
|
||||
protected:
|
||||
/// updates Axis from ReferenceAxis
|
||||
void updateAxis(void);
|
||||
};
|
||||
|
||||
} //namespace PartDesign
|
||||
|
||||
@@ -197,6 +197,8 @@ const TopoDS_Face SketchBased::getSupportFace() const {
|
||||
|
||||
Part::Feature* SketchBased::getSupport() const {
|
||||
// get the support of the Sketch if any
|
||||
if (!Sketch.getValue())
|
||||
return 0;
|
||||
App::DocumentObject* SupportLink = static_cast<Part::Part2DObject*>(Sketch.getValue())->Support.getValue();
|
||||
Part::Feature* SupportObject = NULL;
|
||||
if (SupportLink && SupportLink->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
|
||||
|
||||