Merge branch 'master' of ssh://git.code.sf.net/p/free-cad/code

This commit is contained in:
wmayer 2013-04-26 17:22:10 +02:00
commit adaa3716dd
35 changed files with 2734 additions and 722 deletions

35
README
View File

@ -12,13 +12,20 @@ FreeCAD is based on OpenCasCade, a powerful geometry kernel, features an Open In
The interface is built with Qt. FreeCAD runs exactly the same way on Windows, Mac OSX, BSD and
Linux platforms.
Home page and wiki documentation: http://free-cad.sf.net
Home page: http://www.freecadweb.org
Documentation wiki: http://www.freecadweb.org/wiki
Forum: http://sourceforge.net/apps/phpbb/free-cad/
Bug tracker: http://sourceforge.net/apps/mantisbt/free-cad/
Official git link: git://free-cad.git.sourceforge.net/free-cad/free-cad
Git repository: http://sourceforge.net/p/free-cad/code/ci/master/tree/
Building
========
Installing
==========
Precompiled (installable) packages are usually available to you from several sources and are
described on the FreeCAD download page: http://www.freecadweb.org/wiki/index.php?title=Download
Compiling
=========
Compiling FreeCAD requires to install several heavyweight libraries and their development
files such as OpenCasCADe, Coin and Qt, listed in the pages below. Once this is done,
@ -31,12 +38,26 @@ Note that autotools build system can still be used but will be obsoleted soon.
The pages below contain up-to-date build instructions:
For Linux: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnUnix
For windows: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnWindows
For Mac OSX: http://sourceforge.net/apps/mediawiki/free-cad/index.php?title=CompileOnMac
For Linux: http://www.freecadweb.org/wiki/index.php?title=CompileOnUnix
For windows: http://www.freecadweb.org/wiki/index.php?title=CompileOnWindows
For Mac OSX: http://www.freecadweb.org/wiki/index.php?title=CompileOnMac
In this folder you will also find additional README files, specific for each platform.
Usage
=====
The FreeCAD documentation wiki contains sections for each category of users, and a manual,
which is a compilation of the most useful articles of the wiki:
For users: General FreeCAD usage: http://www.freecadweb.org/wiki/index.php?title=User_hub
For power-users: Python scripting: http://www.freecadweb.org/wiki/index.php?title=Power_users_hub
For developers: C++ FreeCAD development: http://www.freecadweb.org/wiki/index.php?title=Developer_hub
The FreeCAD manual: http://www.freecadweb.org/wiki/index.php?title=Online_Help_Toc

View File

@ -4,5 +4,6 @@ The FreeCAD Document
.. toctree::
:maxdepth: 4
.. automodule:: ActiveDocument
:members:
.. automodule:: DocumentObject

View File

@ -0,0 +1,18 @@
The FreeCAD Document Object
===========================
.. toctree::
:maxdepth: 4
.. automodule:: DocumentObject
.. autoclass:: DocumentObject
:members:
.. method:: __setstate__(value)
allows to save custom attributes of this object as strings, so they can be saved when saving the FreeCAD document
.. method:: __getstate__()
reads values previously saved with __setstate__()

View File

@ -7,14 +7,5 @@ The FreeCAD module
.. automodule:: FreeCAD
:members:
.. autoclass:: Vector
:members:
.. autoclass:: Matrix
:members:
.. autoclass:: Placement
:members:
.. autoclass:: Console
:members:

10
src/Doc/sphinx/Matrix.rst Normal file
View File

@ -0,0 +1,10 @@
The Matrix object
=================
.. toctree::
:maxdepth: 4
.. automodule:: FreeCAD
.. autoclass:: Matrix
:members:

View File

@ -0,0 +1,10 @@
The Placement object
====================
.. toctree::
:maxdepth: 4
.. automodule:: FreeCAD
.. autoclass:: Placement
:members:

10
src/Doc/sphinx/Vector.rst Normal file
View File

@ -0,0 +1,10 @@
The Vector object
=================
.. toctree::
:maxdepth: 4
.. automodule:: FreeCAD
.. autoclass:: Vector
:members:

View File

@ -0,0 +1,10 @@
The View Provider object
========================
.. toctree::
:maxdepth: 4
.. automodule:: DocumentObject
.. autoclass:: ViewProvider
:members:

View File

@ -53,9 +53,13 @@ elif commands.getstatusoutput("locate FreeCAD/lib")[0] == 0:
path = commands.getstatusoutput("locate FreeCAD/lib")[1].split()[0]
sys.path.append(path)
# locate TemplatePyMod
if commands.getstatusoutput("locate TemplatePyMod")[0] == 0:
path = commands.getstatusoutput("locate TemplatePyMod")[1].split()[0]
sys.path.append(path)
import FreeCAD, FreeCADGui
FreeCADGui.showMainWindow() # this is needed for complete import of GUI modules
from FreeCAD import Document
# -- General configuration -----------------------------------------------------

View File

@ -13,7 +13,12 @@ This is the complete python API reference of the FreeCAD appication
FreeCAD.rst
FreeCADGui.rst
Vector.rst
Placement.rst
Matrix.rst
Document.rst
DocumentObject.rst
ViewProvider.rst
Mesh.rst
Part.rst
Sketch.rst

View File

@ -165,6 +165,9 @@ def removeComponents(objectsList,host=None):
s.remove(o)
h.Subtractions = s
o.ViewObject.show()
elif o == s.Base:
s.Base = None
o.ViewObject.show()
elif tp in ["SectionPlane"]:
a = h.Objects
if o in a:
@ -569,7 +572,7 @@ class _CommandRemove:
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Ungrouping")))
if Draft.getType(sel[-1]) in ["Wall","Structure"]:
if (Draft.getType(sel[-1]) in ["Wall","Structure"]) and (len(sel) > 1):
host = sel.pop()
ss = "["
for o in sel:
@ -581,7 +584,7 @@ class _CommandRemove:
FreeCADGui.doCommand("Arch.removeComponents("+ss+",FreeCAD.ActiveDocument."+host.Name+")")
else:
FreeCADGui.doCommand("import Arch")
FreeCADGui.doCommand("Arch.removeComponents("+ss+")")
FreeCADGui.doCommand("Arch.removeComponents(Arch.ActiveDocument."+sel[-1].Name+")")
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@ -25,7 +25,7 @@ __title__="FreeCAD Arch Component"
__author__ = "Yorik van Havre"
__url__ = "http://free-cad.sourceforge.net"
import FreeCAD,FreeCADGui
import FreeCAD,FreeCADGui,Draft
from PyQt4 import QtGui,QtCore
from DraftTools import translate
@ -101,7 +101,8 @@ def removeFromComponent(compobject,subobject):
l = compobject.Subtractions
l.append(subobject)
compobject.Subtractions = l
subobject.ViewObject.hide()
if Draft.getType(subobject) != "Window":
subobject.ViewObject.hide()
class ComponentTaskPanel:
@ -306,7 +307,8 @@ class Component:
if prop in ["Additions","Subtractions"]:
if hasattr(obj,prop):
for o in getattr(obj,prop):
o.ViewObject.hide()
if Draft.getType(o) != "Window":
o.ViewObject.hide()
def processSubShapes(self,obj,base):
"Adds additions and subtractions to a base shape"

View File

@ -78,6 +78,8 @@ class _Floor:
def __init__(self,obj):
obj.addProperty("App::PropertyLength","Height","Base",
str(translate("Arch","The height of this floor")))
obj.addProperty("App::PropertyPlacement","Placement","Base",
str(translate("Arch","The placement of this group")))
self.Type = "Floor"
obj.Proxy = self
self.Object = obj
@ -90,10 +92,18 @@ class _Floor:
self.Type = state
def execute(self,obj):
pass
if hasattr(obj,"Placement"):
self.OldPlacement = obj.Placement.copy()
def onChanged(self,obj,prop):
self.Object = obj
if prop == "Placement":
if hasattr(self,"OldPlacement"):
delta = obj.Placement.Base.sub(self.OldPlacement.Base)
for o in obj.Group:
if hasattr(o,"Placement"):
o.Placement.move(delta)
self.OldPlacement = FreeCAD.Placement(obj.Placement)
def addObject(self,child):
if hasattr(self,"Object"):

View File

@ -68,10 +68,19 @@ class _CommandStructure:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Structure","Creates a structure object from scratch or from a selected object (sketch, wire, face or solid)")}
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure")))
FreeCADGui.doCommand("import Arch")
global QtGui, QtCore
from PyQt4 import QtGui, QtCore
self.Length = 0.5
self.Width = 0.2
self.Height = 1
self.continueCmd = False
sel = FreeCADGui.Selection.getSelection()
if sel:
# direct creation
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure")))
FreeCADGui.doCommand("import Arch")
# if selection contains structs and axes, make a system
st = Draft.getObjectsOfType(sel,"Structure")
ax = Draft.getObjectsOfType(sel,"Axis")
@ -81,10 +90,90 @@ class _CommandStructure:
# else, do normal structs
for obj in sel:
FreeCADGui.doCommand("Arch.makeStructure(FreeCAD.ActiveDocument." + obj.Name + ")")
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
else:
FreeCADGui.doCommand("Arch.makeStructure()")
# interactive mode
import DraftTrackers
self.points = []
self.tracker = DraftTrackers.boxTracker()
self.tracker.on()
FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox())
def getPoint(self,point=None,obj=None):
"this function is called by the snapper when it has a 3D point"
self.tracker.finalize()
if point == None:
return
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure")))
FreeCADGui.doCommand('import Arch')
FreeCADGui.doCommand('s = Arch.makeStructure(length='+str(self.Length)+',width='+str(self.Width)+',height='+str(self.Height)+')')
FreeCADGui.doCommand('s.Placement.Base = '+DraftVecUtils.toString(point))
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if self.continueCmd:
self.Activated()
def taskbox(self):
"sets up a taskbox widget"
w = QtGui.QWidget()
w.setWindowTitle(str(translate("Arch","Structure options")))
lay0 = QtGui.QVBoxLayout(w)
lay1 = QtGui.QHBoxLayout()
lay0.addLayout(lay1)
label1 = QtGui.QLabel(str(translate("Arch","Length")))
lay1.addWidget(label1)
value1 = QtGui.QDoubleSpinBox()
value1.setDecimals(2)
value1.setValue(self.Length)
lay1.addWidget(value1)
lay2 = QtGui.QHBoxLayout()
lay0.addLayout(lay2)
label2 = QtGui.QLabel(str(translate("Arch","Width")))
lay2.addWidget(label2)
value2 = QtGui.QDoubleSpinBox()
value2.setDecimals(2)
value2.setValue(self.Width)
lay2.addWidget(value2)
lay3 = QtGui.QHBoxLayout()
lay0.addLayout(lay3)
label3 = QtGui.QLabel(str(translate("Arch","Height")))
lay3.addWidget(label3)
value3 = QtGui.QDoubleSpinBox()
value3.setDecimals(2)
value3.setValue(self.Height)
lay3.addWidget(value3)
value4 = QtGui.QCheckBox(str(translate("Arch","Continue")))
lay0.addWidget(value4)
QtCore.QObject.connect(value1,QtCore.SIGNAL("valueChanged(double)"),self.setLength)
QtCore.QObject.connect(value2,QtCore.SIGNAL("valueChanged(double)"),self.setWidth)
QtCore.QObject.connect(value3,QtCore.SIGNAL("valueChanged(double)"),self.setHeight)
QtCore.QObject.connect(value4,QtCore.SIGNAL("stateChanged(int)"),self.setContinue)
return w
def update(self,point):
"this function is called by the Snapper when the mouse is moved"
self.tracker.pos(point)
def setWidth(self,d):
self.Width = d
self.tracker.width(d)
def setHeight(self,d):
self.Height = d
self.tracker.height(d)
def setLength(self,d):
self.Length = d
self.tracker.length(d)
def setContinue(self,i):
self.continueCmd = bool(i)
class _Structure(ArchComponent.Component):
"The Structure object"

View File

@ -335,6 +335,19 @@ class _Wall(ArchComponent.Component):
self.hideSubobjects(obj,prop)
if prop in ["Base","Height","Width","Align","Additions","Subtractions"]:
self.createGeometry(obj)
# propagate movements to children windows
if prop == "Placement":
if obj.Shape:
if not obj.Shape.isNull():
vo = obj.Shape.Placement.Base
vn = obj.Placement.Base
if not DraftVecUtils.equals(vo,vn):
delta = vn.sub(vo)
for o in obj.OutList:
if (Draft.getType(o) == "Window") or Draft.isClone(o,"Window"):
o.Placement.move(delta)
def getDefaultValues(self,obj):
"returns normal,width,height values from this wall"
@ -472,6 +485,10 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent):
def getIcon(self):
import Arch_rc
if hasattr(self,"Object"):
for o in self.Object.OutList:
if Draft.getType(o) == "Wall":
return ":/icons/Arch_Wall_Tree_Assembly.svg"
return ":/icons/Arch_Wall_Tree.svg"
def getDisplayModes(self,vobj):

View File

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

View File

@ -30,6 +30,7 @@
<file>icons/Arch_Check.svg</file>
<file>icons/Arch_SelectNonManifold.svg</file>
<file>icons/Arch_MergeWalls.svg</file>
<file>icons/Arch_Wall_Tree_Assembly.svg</file>
<file>ui/archprefs-base.ui</file>
<file>translations/Arch_af.qm</file>
<file>translations/Arch_de.qm</file>

View File

@ -0,0 +1,415 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2816"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Arch_Wall_Tree.svg">
<defs
id="defs2818">
<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="perspective2824" />
<inkscape:perspective
id="perspective3622"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3622-9"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3653"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3675"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3697"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3720"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3742"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3764"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3785"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3806"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3806-3"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3835"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11"
inkscape:cx="16.107459"
inkscape:cy="33.217385"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:object-nodes="true"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:snap-nodes="false"
inkscape:snap-global="false" />
<metadata
id="metadata2821">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="8.8969326"
height="6.4156804"
x="50.020618"
y="80.818169"
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:1.82064199;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="14.188248"
height="6.3632684"
x="27.991013"
y="38.201286"
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:1.82064199;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="14.188248"
height="6.3632684"
x="43.51255"
y="38.190132"
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:1.77675104;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 33.802565,41.435793 13.512409,4.326796 -7.144868,5.301535 -13.512409,-4.326797 7.144868,-5.301534 z"
id="rect2840-3-5-3-5-0"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 48.584755,46.105614 13.512409,4.326797 -7.144868,5.301534 -13.512409,-4.326797 7.144868,-5.301534 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:1.98266625;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="8.8969326"
height="6.4156804"
x="41.959759"
y="66.366005"
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:1.82064199;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="14.188248"
height="6.3632684"
x="37.004723"
y="30.533503"
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:1.98266625;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="8.8969326"
height="6.4156804"
x="68.427689"
y="96.508865"
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:1.98266625;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="8.8969326"
height="6.4156804"
x="60.71003"
y="82.268806"
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:1.77675104;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 42.386919,36.464382 13.512409,4.326797 -7.144867,5.301534 -13.512409,-4.326797 7.144867,-5.301534 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:1.77675104;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 33.945387,33.819971 6.896146,2.241369 -7.144868,5.301534 -6.896146,-2.241368 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:1.82064199;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="4.8688564"
height="6.3783622"
x="52.702457"
y="30.623219"
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:1.98266625;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="8.8969326"
height="6.4156804"
x="68.274139"
y="88.826065"
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:1.77675104;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 57.336914,41.387566 4.636933,1.45354 -7.144868,5.301534 -4.636934,-1.453539 z"
id="rect2840-3-5-4"
sodipodi:nodetypes="ccccc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 32.557262,11.494551 9.205487,2.784019 -12.158897,8.901351 -9.205487,-2.784019 z"
id="rect2840-3-5-3-1-3"
sodipodi:nodetypes="ccccc" />
<rect
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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-1-5-1"
width="15.060457"
height="8.1599474"
x="53.304558"
y="64.54351"
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:1.98266625;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-1-5-4"
width="15.060457"
height="8.1599474"
x="45.460068"
y="55.047924"
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:1.98266625;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-1"
width="15.060457"
height="8.1599474"
x="36.8633"
y="45.146145"
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:1.98266625;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="8.8969326"
height="6.4156804"
x="49.970425"
y="65.531265"
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:1.82064199;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="14.188248"
height="6.3632684"
x="27.948685"
y="22.957209"
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:1.82064199;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="14.188248"
height="6.3632684"
x="43.470222"
y="22.946053"
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:1.77675104;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 33.762254,26.178803 13.512409,4.326797 -7.144868,5.301535 -13.51241,-4.326797 7.144869,-5.301535 z"
id="rect2840-3-5-3-5-1"
sodipodi:nodetypes="ccccc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#c7c7c7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77675104;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 48.544443,30.848624 13.512409,4.326797 -7.144867,5.301535 -13.512409,-4.326797 7.144867,-5.301535 z"
id="rect2840-3-5-3-1"
sodipodi:nodetypes="ccccc" />
<rect
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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="8.8969326"
height="6.4156804"
x="68.377495"
y="81.22197"
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:1.82064199;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-7"
width="14.188248"
height="6.3632684"
x="12.103945"
y="22.966328"
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:1.77675104;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 18.672257,21.355968 13.512409,4.326797 -7.144868,5.301535 -13.51241,-4.326797 7.144869,-5.301535 z"
id="rect2840-3-5-3-5-1-5"
sodipodi:nodetypes="ccccc" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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-7-5"
width="8.1745195"
height="6.0153747"
x="2.8632176"
y="23.144983"
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:1.77675104;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 10.053518,18.352968 7.603319,2.508615 -7.144868,5.301535 -7.6033201,-2.508615 z"
id="rect2840-3-5-3-5-1-5-1"
sodipodi:nodetypes="ccccc" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82064199;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-1"
width="15.715544"
height="6.7156911"
x="19.251734"
y="30.329483"
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:1.82064199;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-6"
width="15.33372"
height="6.5594053"
x="2.8333008"
y="30.881844"
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:1.82064199;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-3"
width="14.188248"
height="6.3632684"
x="12.569814"
y="38.276264"
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:1.82064199;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-7-5-2"
width="9.1290798"
height="5.8151832"
x="2.6901171"
y="38.834602"
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:1.77675104;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 45.767302,1.6871595 54.972789,4.4711786 42.813892,13.37253 33.608404,10.588511 z"
id="rect2840-3-5-3-1-3-3"
sodipodi:nodetypes="ccccc" />
<rect
style="color:#000000;fill:#7a7a7a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.98266625;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-1-5"
width="15.060457"
height="8.1599474"
x="53.312706"
y="45.140682"
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:1.98266625;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-1-5-7"
width="6.9758401"
height="8.4850521"
x="61.389179"
y="54.704601"
transform="matrix(0.80307096,-0.59588341,0,1,0,0)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -21,10 +21,18 @@
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Arch,Draft
"FreeCAD webgl exporter"
import FreeCAD,Draft,Part,DraftGeomUtils
from DraftTools import translate
if FreeCAD.GuiUp:
import FreeCADGui
else:
FreeCADGui = None
tab = " "
addWireframe = False
if open.__module__ == '__builtin__':
pythonopen = open
@ -32,59 +40,51 @@ if open.__module__ == '__builtin__':
def export(exportList,filename):
"exports the given objects to a .html file"
# get three.min.js
threejspath = Arch.download("https://raw.github.com/mrdoob/three.js/master/build/three.min.js")
threejsfile = pythonopen(threejspath,"r")
threeminjs = threejsfile.read()
threejsfile.close()
html = getHTML(exportList)
outfile = pythonopen(filename,"wb")
outfile.write(html)
outfile.close()
FreeCAD.Console.PrintMessage(str(translate("Arch","successfully written "))+filename)
def getHTML(objectsList):
"returns the complete HTML code of a viewer for the given objects"
# get objects data
objectsData = ''
for obj in exportList:
for obj in objectsList:
objectsData += getObjectData(obj)
# build the final file
template = getTemplate()
template = template.replace("$ThreeMinJs",threeminjs)
template = template.replace("$CameraData",getCameraData())
template = template.replace("$ObjectsData",objectsData)
template = template.replace("$TestData",getTestData())
outfile = pythonopen(filename,"wb")
outfile.write(template)
outfile.close()
FreeCAD.Console.PrintMessage(str(translate("Arch","successfully written "))+filename)
return template
def getCameraData():
"returns the position and direction of the camera as three.js snippet"
# getting camera position
pos = FreeCADGui.ActiveDocument.ActiveView.viewPosition().Base
#result = "camera.position.set( -10,5,15" # test position
result = "camera.position.set( "
result += str(pos.x) + ", "
result += str(pos.y) + ", "
result += str(pos.z)
# getting camera lookat vector
lookat = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
lookat = pos.add(lookat)
result += " );\n"+tab+"camera.lookAt( scene.position );\n"+tab
#result += " );\n"+tab+"camera.lookAt( "
#result += str(lookat.x) + ", "
#result += str(lookat.y) + ", "
#result += str(lookat.z)
#result += " );\n"+tab
result = ""
if FreeCADGui:
# getting camera position
pos = FreeCADGui.ActiveDocument.ActiveView.viewPosition().Base
result += "camera.position.set( "
result += str(pos.x) + ", "
result += str(pos.y) + ", "
result += str(pos.z) + " );\n"
else:
result += "camera.position.set(0,0,1000);\n"
result += tab+"camera.lookAt( scene.position );\n"+tab
# print result
return result
def getObjectData(obj):
"returns the geometry data of an object as three.js snippet"
def getObjectData(obj,wireframeMode="faceloop"):
"""returns the geometry data of an object as three.js snippet. wireframeMode
can be multimaterial, faceloop or None"""
result = ""
wires = []
if obj.isDerivedFrom("Part::Feature"):
fcmesh = obj.Shape.tessellate(0.1)
result = "var geom = new THREE.Geometry();\n"
# adding vertices data
for i in range(len(fcmesh[0])):
v = fcmesh[0][i]
@ -92,33 +92,70 @@ def getObjectData(obj):
result += tab+"console.log(geom.vertices)\n"
for i in range(len(fcmesh[0])):
result += tab+"geom.vertices.push(v"+str(i)+");\n"
# adding facets data
for f in fcmesh[1]:
result += tab+"geom.faces.push( new THREE.Face3"+str(f)+" );\n"
for f in obj.Shape.Faces:
for w in f.Wires:
wo = Part.Wire(DraftGeomUtils.sortEdges(w.Edges))
p = []
for v in wo.Vertexes:
p.append(v.Point)
p.append(wo.Vertexes[0].Point)
wires.append(p)
# adding material
col = obj.ViewObject.ShapeColor
rgb = Draft.getrgb(col,testbw=False)
#rgb = "#888888" # test color
result += tab+"var material = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"
elif obj.isDerivedFrom("Mesh::Feature"):
mesh = obj.Mesh
result = "var geom = new THREE.Geometry();\n"
# adding vertices data
for p in mesh.Points:
v = p.Vector
i = p.Index
result += tab+"var v"+str(i)+" = new THREE.Vector3("+str(v.x)+","+str(v.y)+","+str(v.z)+");\n"
result += tab+"console.log(geom.vertices)\n"
for p in mesh.Points:
result += tab+"geom.vertices.push(v"+str(p.Index)+");\n"
# adding facets data
for f in mesh.Facets:
result += tab+"geom.faces.push( new THREE.Face3"+str(f.PointIndices)+" );\n"
# adding the mesh to the scene
result += tab+"var mesh = new THREE.Mesh( geom, material );\n"
result += tab+"scene.add( mesh );\n"+tab
if result:
# adding a base material
if FreeCADGui:
col = obj.ViewObject.ShapeColor
rgb = Draft.getrgb(col,testbw=False)
else:
rgb = "#888888" # test color
result += tab+"var basematerial = new THREE.MeshBasicMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"
#result += tab+"var basematerial = new THREE.MeshLambertMaterial( { color: 0x"+str(rgb)[1:]+" } );\n"
# print result
return result
if wireframeMode == "faceloop":
# adding the mesh to the scene with a wireframe copy
result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n"
result += tab+"scene.add( mesh );\n"
result += tab+"var linematerial = new THREE.LineBasicMaterial({color: 0x000000,});\n"
for w in wires:
result += tab+"var wire = new THREE.Geometry();\n"
for p in w:
result += tab+"wire.vertices.push(new THREE.Vector3("
result += str(p.x)+", "+str(p.y)+", "+str(p.z)+"));\n"
result += tab+"var line = new THREE.Line(wire, linematerial);\n"
result += tab+"scene.add(line);\n"
def getTestData():
"returns a simple cube as three.js snippet"
elif wireframeMode == "multimaterial":
# adding a wireframe material
result += tab+"var wireframe = new THREE.MeshBasicMaterial( { color: "
result += "0x000000, wireframe: true, transparent: true } );\n"
result += tab+"var material = [ basematerial, wireframe ];\n"
result += tab+"var mesh = new THREE.SceneUtils.createMultiMaterialObject( geom, material );\n"
result += tab+"scene.add( mesh );\n"+tab
#return """var geometry = new THREE.CubeGeometry( .5, .5, .5 );
# var material = new THREE.MeshLambertMaterial( { color: 0xFF0000 } );
# var mesh = new THREE.Mesh( geometry, material );
# scene.add( mesh );"""
else:
# adding the mesh to the scene with simple material
result += tab+"var mesh = new THREE.Mesh( geom, basematerial );\n"
result += tab+"scene.add( mesh );\n"+tab
return ""
return result
def getTemplate():
"returns a html template"
@ -127,35 +164,60 @@ def getTemplate():
<html>
<head>
<title>FreeCAD model</title>
<script>$ThreeMinJs</script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r50/three.min.js"></script>
<script>
var camera, controls, scene, renderer;
window.onload = function() {
var renderer = new THREE.WebGLRenderer();
renderer.setSize( 800, 600 );
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 35, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
renderer = new THREE.WebGLRenderer();
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
35, // Field of view
800 / 600, // Aspect ratio
0.1, // Near plane
10000 // Far plane
camera = new THREE.PerspectiveCamera(
VIEW_ANGLE, // Field of view
ASPECT, // Aspect ratio
NEAR, // Near plane
FAR // Far plane
);
$CameraData // placeholder for the FreeCAD camera
$TestData // placeholder for a test cube
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
$ObjectsData // placeholder for the FreeCAD objects
var light = new THREE.PointLight( 0xFFFF00 );
light.position.set( -10, -10, 10 );
light.position.set( -10000, -10000, 10000 );
scene.add( light );
renderer.render( scene, camera );
animate();
};
function animate(){
requestAnimationFrame( animate );
render();
};
function render(){
controls.update();
renderer.render( scene, camera );
};
</script>
</head>

View File

@ -13,6 +13,7 @@ SET(Draft_SRCS
importDXF.py
importOCA.py
importSVG.py
importDWG.py
importAirfoilDAT.py
macros.py
Draft_rc.py

View File

@ -101,7 +101,7 @@ def getParamType(param):
"modalt"]:
return "int"
elif param in ["constructiongroupname","textfont","patternFile","template","maxSnapEdges",
"snapModes"]:
"snapModes","FontFile"]:
return "string"
elif param in ["textheight","tolerance","gridSpacing"]:
return "float"
@ -143,6 +143,11 @@ def tolerance():
"tolerance(): returns the tolerance value from Draft user settings"
return getParam("tolerance")
def epsilon():
''' epsilon(): returns a small number based on Draft.tolerance() for use in
floating point comparisons. Use with caution. '''
return (1.0/(10.0**tolerance()))
def getRealName(name):
"getRealName(string): strips the trailing numbers from a string name"
for i in range(1,len(name)):
@ -803,17 +808,24 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None):
select(obj)
return obj
def makeEllipse(majradius,minradius,placement=None):
'''makeEllipse(majradius,minradius,[placement]): makes
def makeEllipse(majradius,minradius,placement=None,face=True,support=None):
'''makeEllipse(majradius,minradius,[placement],[face],[support]): makes
an ellipse with the given major and minor radius, and optionally
a placement.'''
import Part
e = Part.Ellipse(FreeCAD.Vector(0,0,0),majradius,minradius)
newobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Ellipse")
newobj.Shape = e.toShape()
if placement: newobj.Placement = placement
FreeCAD.ActiveDocument.recompute()
return newobj
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","Ellipse")
_Ellipse(obj)
obj.MajorRadius = majradius
obj.MinorRadius = minradius
obj.Support = support
if placement:
obj.Placement = placement
if gui:
_ViewProviderDraft(obj.ViewObject)
if not face:
obj.ViewObject.DisplayMode = "Wireframe"
formatObject(obj)
select(obj)
return obj
def extrude(obj,vector):
'''makeExtrusion(object,vector): extrudes the given object
@ -1682,6 +1694,34 @@ def makePoint(X=0, Y=0, Z=0,color=None,name = "Point", point_size= 5):
FreeCAD.ActiveDocument.recompute()
return obj
def makeShapeString(String,FontFile,Size = 100,Tracking = 0):
'''ShapeString(Text,FontFile,Height,Track): Turns a text string
into a Compound Shape'''
# temporary code
import platform
if not (platform.system() == 'Linux'):
# if (platform.system() == 'Linux'):
FreeCAD.Console.PrintWarning("Sorry, ShapeString is not yet implemented for your platform.\n")
return (None)
# temporary code
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython","ShapeString")
_ShapeString(obj)
obj.String = String
obj.FontFile = FontFile
obj.Size = Size
obj.Tracking = Tracking
if gui:
_ViewProviderDraft(obj.ViewObject)
formatObject(obj)
obrep = obj.ViewObject
if "PointSize" in obrep.PropertiesList: obrep.PointSize = 1 # hide the segment end points
select(obj)
FreeCAD.ActiveDocument.recompute()
return obj
def clone(obj,delta=None):
'''clone(obj,[delta]): makes a clone of the given object(s). The clone is an exact,
linked copy of the given object. If the original object changes, the final object
@ -3001,6 +3041,36 @@ class _Circle(_DraftObject):
fp.Shape = shape
fp.Placement = plm
class _Ellipse(_DraftObject):
"The Circle object"
def __init__(self, obj):
_DraftObject.__init__(self,obj,"Ellipse")
obj.addProperty("App::PropertyDistance","MinorRadius","Base",
"The minor radius of the ellipse")
obj.addProperty("App::PropertyDistance","MajorRadius","Base",
"The major radius of the ellipse")
def execute(self, fp):
self.createGeometry(fp)
def onChanged(self, fp, prop):
if prop in ["MinorRadius","MajorRadius"]:
self.createGeometry(fp)
def createGeometry(self,fp):
import Part
plm = fp.Placement
if fp.MajorRadius < fp.MinorRadius:
msg(translate("Error: Major radius is smaller than the minor radius"))
return
if fp.MajorRadius and fp.MinorRadius:
shape = Part.Ellipse(Vector(0,0,0),fp.MajorRadius,fp.MinorRadius).toShape()
shape = Part.Wire(shape)
shape = Part.Face(shape)
fp.Shape = shape
fp.Placement = plm
class _Wire(_DraftObject):
"The Wire object"
@ -3371,45 +3441,9 @@ class _Shape2DView(_DraftObject):
if prop in ["Projection","Base","ProjectionMode","FaceNumbers"]:
self.createGeometry(obj)
def clean(self,shape):
"returns a valid compound of edges, by recreating them"
# this is because the projection algorithm somehow creates wrong shapes.
# they dispay fine, but on loading the file the shape is invalid
import Part,DraftGeomUtils
oldedges = shape.Edges
newedges = []
for e in oldedges:
try:
if DraftGeomUtils.geomType(e) == "Line":
newedges.append(e.Curve.toShape())
elif DraftGeomUtils.geomType(e) == "Circle":
if len(e.Vertexes) > 1:
mp = DraftGeomUtils.findMidpoint(e)
a = Part.Arc(e.Vertexes[0].Point,mp,e.Vertexes[-1].Point).toShape()
newedges.append(a)
else:
newedges.append(e.Curve.toShape())
elif DraftGeomUtils.geomType(e) == "Ellipse":
if len(e.Vertexes) > 1:
a = Part.Arc(e.Curve,e.FirstParameter,e.LastParameter).toShape()
newedges.append(a)
else:
newedges.append(e.Curve.toShape())
elif DraftGeomUtils.geomType(e) == "BSplineCurve":
if DraftGeomUtils.isLine(e.Curve):
l = Part.Line(e.Vertexes[0].Point,e.Vertexes[-1].Point).toShape()
newedges.append(l)
else:
newedges.append(e.Curve.toShape())
else:
newedges.append(e)
except:
print "Debug: error cleaning edge ",e
return Part.makeCompound(newedges)
def getProjected(self,obj,shape,direction):
"returns projected edges from a shape and a direction"
import Part,Drawing
import Part,Drawing,DraftGeomUtils
edges = []
groups = Drawing.projectEx(shape,direction)
for g in groups[0:5]:
@ -3420,7 +3454,7 @@ class _Shape2DView(_DraftObject):
for g in groups[5:]:
edges.append(g)
#return Part.makeCompound(edges)
return self.clean(Part.makeCompound(edges))
return DraftGeomUtils.cleanProjection(Part.makeCompound(edges))
def createGeometry(self,obj):
import DraftGeomUtils
@ -3694,6 +3728,91 @@ class _ViewProviderClone(_ViewProviderDraftAlt):
def getIcon(self):
return ":/icons/Draft_Clone.svg"
class _ShapeString(_DraftObject):
"The ShapeString object"
def __init__(self, obj):
_DraftObject.__init__(self,obj,"ShapeString")
obj.addProperty("App::PropertyString","String","Base","Text string")
obj.addProperty("App::PropertyString","FontFile","Base","Font file name")
obj.addProperty("App::PropertyFloat","Size","Base","Height of text")
obj.addProperty("App::PropertyInteger","Tracking","Base",
"Inter-character spacing")
def execute(self, fp):
self.createGeometry(fp)
def onChanged(self, fp, prop):
pass
def createGeometry(self,fp):
import Part
# import OpenSCAD2Dgeom
import os
if fp.String and fp.FontFile:
if fp.Placement:
plm = fp.Placement
# TODO: os.path.splitunc() for Win/Samba net files?
head, tail = os.path.splitdrive(fp.FontFile) # os.path.splitdrive() for Win
head, tail = os.path.split(tail)
head = head + '/' # os.split drops last '/' from head
CharList = Part.makeWireString(fp.String,
head,
tail,
fp.Size,
fp.Tracking)
SSChars = []
for char in CharList:
CharFaces = []
for CWire in char:
f = Part.Face(CWire)
if f:
CharFaces.append(f)
# whitespace (ex: ' ') has no faces. This breaks OpenSCAD2Dgeom...
if CharFaces:
# s = OpenSCAD2Dgeom.Overlappingfaces(CharFaces).makeshape()
s = self.makeGlyph(CharFaces)
SSChars.append(s)
shape = Part.Compound(SSChars)
fp.Shape = shape
if plm:
fp.Placement = plm
def makeGlyph(self, facelist):
''' turn list of simple contour faces into a compound shape representing a glyph '''
''' remove cuts, fuse overlapping contours, retain islands '''
import Part
if len(facelist) == 1:
return(facelist[0])
sortedfaces = sorted(facelist,key=(lambda shape: shape.Area),reverse=True)
biggest = sortedfaces[0]
result = biggest
islands =[]
for face in sortedfaces[1:]:
bcfA = biggest.common(face).Area
fA = face.Area
difA = abs(bcfA - fA)
eps = epsilon()
# if biggest.common(face).Area == face.Area:
if difA <= eps: # close enough to zero
# biggest completely overlaps current face ==> cut
result = result.cut(face)
# elif biggest.common(face).Area == 0:
elif bcfA <= eps:
# island
islands.append(face)
else:
# partial overlap - (font designer error?)
result = result.fuse(face)
glyphfaces = [result]
glyphfaces.extend(islands)
ret = Part.Compound(glyphfaces) # should we fuse these instead of making compound?
return ret
#----End of Python Features Definitions----#
if gui:
if not hasattr(FreeCADGui,"Snapper"):
import DraftSnap

View File

@ -195,30 +195,13 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F
returns a list containing the intersection point(s) of 2 edges.
You can also feed 4 points instead of edge1 and edge2'''
pt1 = None
if isinstance(edge1,FreeCAD.Vector) and isinstance(edge2,FreeCAD.Vector):
# we got points directly
pt1 = edge1
pt2 = edge2
pt3 = infinite1
pt4 = infinite2
infinite1 = ex1
infinite2 = ex2
elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line") :
# we have 2 straight lines
pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point,
edge1.Vertexes[1].Point,
edge2.Vertexes[0].Point,
edge2.Vertexes[1].Point]
def getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2):
if pt1:
# first check if we don't already have coincident endpoints
if (pt1 in [pt3,pt4]):
return [pt1]
elif (pt2 in [pt3,pt4]):
return [pt2]
# first check if we don't already have coincident endpoints
if (pt1 in [pt3,pt4]):
return [pt1]
elif (pt2 in [pt3,pt4]):
return [pt2]
norm1 = pt2.sub(pt1).cross(pt3.sub(pt1))
norm2 = pt2.sub(pt4).cross(pt3.sub(pt4))
if not DraftVecUtils.isNull(norm1):
@ -251,6 +234,26 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F
else :
return [] # Lines aren't on same plane
pt1 = None
if isinstance(edge1,FreeCAD.Vector) and isinstance(edge2,FreeCAD.Vector):
# we got points directly
pt1 = edge1
pt2 = edge2
pt3 = infinite1
pt4 = infinite2
infinite1 = ex1
infinite2 = ex2
return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2)
elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line") :
# we have 2 straight lines
pt1, pt2, pt3, pt4 = [edge1.Vertexes[0].Point,
edge1.Vertexes[1].Point,
edge2.Vertexes[0].Point,
edge2.Vertexes[1].Point]
return getLineIntersections(pt1,pt2,pt3,pt4,infinite1,infinite2)
elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Line") \
or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle") :
@ -1668,6 +1671,71 @@ def filletWire(aWire,r,chamfer=False):
filEdges[0] = result[2]
return Part.Wire(filEdges)
def getCircleFromSpline(edge):
"returns a circle-based edge from a bspline-based edge"
if geomType(edge) != "BSplineCurve":
return None
if len(edge.Vertexes) != 1:
return None
# get 2 points
p1 = edge.Curve.value(0)
p2 = edge.Curve.value(math.pi/2)
# get 2 tangents
t1 = edge.Curve.tangent(0)[0]
t2 = edge.Curve.tangent(math.pi/2)[0]
# get normal
n = p1.cross(p2)
if DraftVecUtils.isNull(n):
return None
# get rays
r1 = DraftVecUtils.rotate(t1,math.pi/2,n)
r2 = DraftVecUtils.rotate(t2,math.pi/2,n)
# get center (intersection of rays)
i = findIntersection(p1,p1.add(r1),p2,p2.add(r2),True,True)
if not i:
return None
c = i[0]
r = (p1.sub(c)).Length
circle = Part.makeCircle(r,c,n)
#print circle.Curve
return circle
def cleanProjection(shape):
"returns a valid compound of edges, by recreating them"
# this is because the projection algorithm somehow creates wrong shapes.
# they dispay fine, but on loading the file the shape is invalid
oldedges = shape.Edges
newedges = []
for e in oldedges:
try:
if geomType(e) == "Line":
newedges.append(e.Curve.toShape())
elif geomType(e) == "Circle":
if len(e.Vertexes) > 1:
mp = findMidpoint(e)
a = Part.Arc(e.Vertexes[0].Point,mp,e.Vertexes[-1].Point).toShape()
newedges.append(a)
else:
newedges.append(e.Curve.toShape())
elif geomType(e) == "Ellipse":
if len(e.Vertexes) > 1:
a = Part.Arc(e.Curve,e.FirstParameter,e.LastParameter).toShape()
newedges.append(a)
else:
newedges.append(e.Curve.toShape())
elif geomType(e) == "BSplineCurve":
if isLine(e.Curve):
l = Part.Line(e.Vertexes[0].Point,e.Vertexes[-1].Point).toShape()
newedges.append(l)
else:
newedges.append(e.Curve.toShape())
else:
newedges.append(e)
except:
print "Debug: error cleaning edge ",e
return Part.makeCompound(newedges)
# circle functions *********************************************************
def getBoundaryAngles(angle,alist):

View File

@ -313,6 +313,27 @@ class DraftToolBar:
self.zValue.setText("0.00")
self.textValue = self._lineedit("textValue", self.layout)
# shapestring
self.labelSSize = self._label("labelSize", self.layout)
self.SSizeValue = self._lineedit("SSizeValue", self.layout, width=60)
self.SSizeValue.setText("200.0")
self.labelSTrack = self._label("labelTracking", self.layout)
self.STrackValue = self._lineedit("STrackValue", self.layout, width=60)
self.STrackValue.setText("0")
self.labelSString = self._label("labelString", self.layout)
self.SStringValue = self._lineedit("SStringValue", self.layout)
self.SStringValue.setText("")
self.labelFFile = self._label("labelFFile", self.layout)
self.FFileValue = self._lineedit("FFileValue", self.layout)
defFile = Draft.getParam("FontFile")
if defFile:
self.FFileValue.setText(defFile)
else:
self.FFileValue.setText("")
self.chooserButton = self._pushbutton("chooserButton", self.layout, width=26)
self.chooserButton.setText("...")
# options
self.numFaces = self._spinbox("numFaces", self.layout, 3)
@ -386,6 +407,19 @@ class DraftToolBar:
QtCore.QObject.connect(self.radiusValue,QtCore.SIGNAL("escaped()"),self.escape)
QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("resized()"),self.relocate)
QtCore.QObject.connect(self.baseWidget,QtCore.SIGNAL("retranslate()"),self.retranslateUi)
QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("returnPressed()"),self.validateSNumeric)
QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("escaped()"),self.escape)
QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("returnPressed()"),self.validateSNumeric)
QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("escaped()"),self.escape)
QtCore.QObject.connect(self.SStringValue,QtCore.SIGNAL("returnPressed()"),self.validateSString)
QtCore.QObject.connect(self.SStringValue,QtCore.SIGNAL("escaped()"),self.escape)
QtCore.QObject.connect(self.chooserButton,QtCore.SIGNAL("pressed()"),self.pickFile)
QtCore.QObject.connect(self.FFileValue,QtCore.SIGNAL("returnPressed()"),self.validateFile)
QtCore.QObject.connect(self.FFileValue,QtCore.SIGNAL("escaped()"),self.escape)
# if Ui changed to have Size & Track visible at same time, use this
# QtCore.QObject.connect(self.SSizeValue,QtCore.SIGNAL("returnPressed()"),self.checkSSize)
# QtCore.QObject.connect(self.STrackValue,QtCore.SIGNAL("returnPressed()"),self.checkSTrack)
def setupTray(self):
"sets draft tray buttons up"
@ -478,6 +512,15 @@ class DraftToolBar:
self.resetPlaneButton.setToolTip(translate("draft", "Do not project points to a drawing plane"))
self.isCopy.setText(translate("draft", "&Copy"))
self.isCopy.setToolTip(translate("draft", "If checked, objects will be copied instead of moved (C)"))
self.SStringValue.setToolTip(translate("draft", "Text string to draw"))
self.labelSString.setText(translate("draft", "String"))
self.SSizeValue.setToolTip(translate("draft", "Height of text"))
self.labelSSize.setText(translate("draft", "Height"))
self.STrackValue.setToolTip(translate("draft", "Intercharacter spacing"))
self.labelSTrack.setText(translate("draft", "Tracking"))
self.labelFFile.setText(translate("draft", "Pick a font file"))
self.chooserButton.setToolTip(translate("draft", "Open a FileChooser for font file"))
if (not self.taskmode) or self.tray:
self.wplabel.setToolTip(translate("draft", "Set/unset a working plane"))
self.colorButton.setToolTip(translate("draft", "Line Color"))
@ -528,6 +571,15 @@ class DraftToolBar:
self.offsetLabel.show()
self.offsetValue.show()
def hideXYZ(self):
''' turn off all the point entry widgets '''
self.labelx.hide()
self.labely.hide()
self.labelz.hide()
self.xValue.hide()
self.yValue.hide()
self.zValue.hide()
def lineUi(self,title=None):
if title:
self.pointUi(title,icon="Draft_Line")
@ -606,12 +658,7 @@ class DraftToolBar:
else:
self.setTitle(translate("draft", "None"))
self.labelx.setText(translate("draft", "X"))
self.labelx.hide()
self.labely.hide()
self.labelz.hide()
self.xValue.hide()
self.yValue.hide()
self.zValue.hide()
self.hideXYZ()
self.numFaces.hide()
self.isRelative.hide()
self.hasFill.hide()
@ -634,6 +681,15 @@ class DraftToolBar:
self.textValue.hide()
self.continueCmd.hide()
self.occOffset.hide()
self.labelSString.hide()
self.SStringValue.hide()
self.labelSSize.hide()
self.SSizeValue.hide()
self.labelSTrack.hide()
self.STrackValue.hide()
self.labelFFile.hide()
self.FFileValue.hide()
self.chooserButton.hide()
def trimUi(self,title=translate("draft","Trim")):
self.taskUi(title)
@ -643,23 +699,13 @@ class DraftToolBar:
self.radiusValue.selectAll()
def radiusUi(self):
self.labelx.hide()
self.labely.hide()
self.labelz.hide()
self.xValue.hide()
self.yValue.hide()
self.zValue.hide()
self.hideXYZ()
self.labelRadius.setText(translate("draft", "Radius"))
self.labelRadius.show()
self.radiusValue.show()
def textUi(self):
self.labelx.hide()
self.labely.hide()
self.labelz.hide()
self.xValue.hide()
self.yValue.hide()
self.zValue.hide()
self.hideXYZ()
self.textValue.show()
self.textValue.setText('')
self.textValue.setFocus()
@ -667,6 +713,43 @@ class DraftToolBar:
self.textline=0
self.continueCmd.show()
def SSUi(self):
''' set up ui for ShapeString text entry '''
self.hideXYZ()
self.labelSString.show()
self.SStringValue.show()
self.SStringValue.setText('')
self.SStringValue.setFocus()
self.continueCmd.hide()
def SSizeUi(self):
''' set up ui for ShapeString size entry '''
self.labelSString.hide()
self.SStringValue.hide()
self.continueCmd.hide()
self.labelSSize.show()
self.SSizeValue.setText('200.0')
self.SSizeValue.show()
self.SSizeValue.setFocus()
def STrackUi(self):
''' set up ui for ShapeString tracking entry '''
self.labelSSize.hide()
self.SSizeValue.hide()
self.labelSTrack.show()
self.STrackValue.setText('0')
self.STrackValue.show()
self.STrackValue.setFocus()
def SFileUi(self):
''' set up UI for ShapeString font file selection '''
self.labelSTrack.hide()
self.STrackValue.hide()
self.labelFFile.show()
self.FFileValue.show()
self.chooserButton.show()
self.FFileValue.setFocus()
def switchUi(self,store=True):
if store:
self.state = []
@ -676,12 +759,7 @@ class DraftToolBar:
self.state.append(self.xValue.isVisible())
self.state.append(self.yValue.isVisible())
self.state.append(self.zValue.isVisible())
self.labelx.hide()
self.labely.hide()
self.labelz.hide()
self.xValue.hide()
self.yValue.hide()
self.zValue.hide()
self.hideXYZ()
else:
if self.state:
if self.state[0]:self.labelx.show()
@ -707,12 +785,7 @@ class DraftToolBar:
def editUi(self):
self.taskUi(translate("draft", "Edit"))
self.labelx.hide()
self.labely.hide()
self.labelz.hide()
self.xValue.hide()
self.yValue.hide()
self.zValue.hide()
self.hideXYZ()
self.numFaces.hide()
self.isRelative.hide()
self.hasFill.hide()
@ -902,6 +975,74 @@ class DraftToolBar:
numz = last.z + v.z
self.sourceCmd.numericInput(numx,numy,numz)
def validateSNumeric(self):
''' send valid numeric parameters to ShapeString '''
if self.sourceCmd:
if (self.labelSSize.isVisible()):
try:
SSize=float(self.SSizeValue.text())
except ValueError:
FreeCAD.Console.PrintMessage(translate("draft", "Invalid Size value. Using 200.0."))
self.sourceCmd.numericSSize(unicode("200.0"))
else:
self.sourceCmd.numericSSize(unicode(SSize))
elif (self.labelSTrack.isVisible()):
try:
track=int(self.STrackValue.text())
except ValueError:
FreeCAD.Console.PrintMessage(translate("draft", "Invalid Tracking value. Using 0."))
self.sourceCmd.numericSTrack(unicode("0"))
else:
self.sourceCmd.numericSTrack(unicode(track))
def validateSString(self):
''' send a valid text string to ShapeString as unicode '''
if self.sourceCmd:
if (self.labelSString.isVisible()):
if self.SStringValue.text():
# print "debug: D_G DraftToolBar.validateSString type(SStringValue.text): " str(type(self.SStringValue.text))
self.sourceCmd.validSString(str(self.SStringValue.text().toUtf8())) # QString to QByteArray to PyString
else:
FreeCAD.Console.PrintMessage(translate("draft", "Please enter a text string."))
def pickFile(self):
''' invoke a font file chooser dialog and send result to ShapeString to'''
if self.sourceCmd:
if (self.chooserButton.isVisible()):
try:
dialogCaption = translate("draft", "Select a Font file")
dialogDir = os.path.dirname(Draft.getParam("FontFile"))
if not dialogDir:
dialogDir = os.getcwd() # reasonable default?
dialogFilter = "Fonts (*.ttf *.pfb *.otf);;All files (*.*)"
fname = QtGui.QFileDialog.getOpenFileName(self.baseWidget,
dialogCaption,
dialogDir,
dialogFilter)
fname = str(fname.toUtf8()) # QString to PyString
# print "debug: D_G DraftToolBar.pickFile type(fname): " str(type(fname))
except Exception as e:
FreeCAD.Console.PrintMessage("DraftGui.pickFile: unable to select a font file.")
print type(e)
print e.args
else:
if fname:
self.sourceCmd.validFFile(fname)
else:
FreeCAD.Console.PrintMessage("DraftGui.pickFile: no file selected.") # can this happen?
def validateFile(self):
''' check and send font file parameter to ShapeString as unicode'''
if self.sourceCmd:
if (self.labelFFile.isVisible()):
if self.FFileValue.text():
self.sourceCmd.validFFile(str(self.FFileValue.text().toUtf8())) #QString to PyString
else:
FreeCAD.Console.PrintMessage(translate("draft", "Please enter a font file."))
def finish(self):
"finish button action"
if self.sourceCmd:
@ -1222,7 +1363,8 @@ class DraftToolBar:
self.commands = ["Draft_Line","Draft_Wire",
"Draft_Rectangle","Draft_Arc",
"Draft_Circle","Draft_BSpline",
"Draft_Text","Draft_Dimension"]
"Draft_Text","Draft_Dimension",
"Draft_ShapeString"]
self.title = "Create objects"
def shouldShow(self):
return (FreeCAD.ActiveDocument != None) and (not FreeCADGui.Selection.getSelection())

View File

@ -104,13 +104,14 @@ class Snapper:
'ortho':':/icons/Snap_Ortho.svg',
'intersection':':/icons/Snap_Intersection.svg'}
def snap(self,screenpos,lastpoint=None,active=True,constrain=False):
"""snap(screenpos,lastpoint=None,active=True,constrain=False): returns a snapped
def snap(self,screenpos,lastpoint=None,active=True,constrain=False,noTracker=False):
"""snap(screenpos,lastpoint=None,active=True,constrain=False,noTracker=False): returns a snapped
point from the given (x,y) screenpos (the position of the mouse cursor), active is to
activate active point snapping or not (passive), lastpoint is an optional
other point used to draw an imaginary segment and get additional snap locations. Constrain can
be True to constrain the point against the closest working plane axis.
Screenpos can be a list, a tuple or a coin.SbVec2s object."""
Screenpos can be a list, a tuple or a coin.SbVec2s object. If noTracker is True,
the tracking line is not displayed."""
global Part, DraftGeomUtils
import Part, DraftGeomUtils
@ -196,7 +197,7 @@ class Snapper:
if active:
point = self.snapToGrid(point)
fp = cstr(point)
if self.trackLine and lastpoint:
if self.trackLine and lastpoint and (not noTracker):
self.trackLine.p2(fp)
self.trackLine.on()
return fp

View File

@ -121,14 +121,15 @@ def selectObject(arg):
FreeCAD.activeDraftCommand.component=snapped['Component']
FreeCAD.activeDraftCommand.proceed()
def getPoint(target,args,mobile=False,sym=False,workingplane=True):
def getPoint(target,args,mobile=False,sym=False,workingplane=True,noTracker=False):
'''
Function used by the Draft Tools.
returns a constrained 3d point and its original point.
if mobile=True, the constraining occurs from the location of
mouse cursor when Shift is pressed, otherwise from last entered
point. If sym=True, x and y values stay always equal. If workingplane=False,
the point wont be projected on the Working Plane.
the point wont be projected on the Working Plane. if noTracker is True, the
tracking line will not be displayed
'''
ui = FreeCADGui.draftToolBar
@ -141,7 +142,7 @@ def getPoint(target,args,mobile=False,sym=False,workingplane=True):
last = None
amod = hasMod(args,MODSNAP)
cmod = hasMod(args,MODCONSTRAIN)
point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod)
point = FreeCADGui.Snapper.snap(args["Position"],lastpoint=last,active=amod,constrain=cmod,noTracker=noTracker)
info = FreeCADGui.Snapper.snapInfo
ctrlPoint = Vector(point)
mask = FreeCADGui.Snapper.affinity
@ -606,7 +607,7 @@ class BSpline(Line):
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
self.point,ctrlPoint,info = getPoint(self,arg)
self.point,ctrlPoint,info = getPoint(self,arg,noTracker=True)
self.bsplinetrack.update(self.node + [self.point])
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
@ -813,7 +814,7 @@ class Rectangle(Creator):
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True)
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True)
self.rect.update(self.point)
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
@ -1394,7 +1395,7 @@ class Ellipse(Creator):
'pl = FreeCAD.Placement()',
'pl.Rotation.Q='+rot,
'pl.Base = '+DraftVecUtils.toString(center),
'Draft.makeEllipse('+str(r1)+','+str(r2)+',placement=pl)'])
'Draft.makeEllipse('+str(r1)+','+str(r2)+',placement=pl,face='+fil+',support='+sup+')'])
except:
print "Draft: Error: Unable to create object."
self.finish(cont=True)
@ -1405,7 +1406,7 @@ class Ellipse(Creator):
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True)
self.point,ctrlPoint,info = getPoint(self,arg,mobile=True,noTracker=True)
self.rect.update(self.point)
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
@ -1616,8 +1617,9 @@ class Dimension(Creator):
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
import DraftGeomUtils
shift = hasMod(arg,MODCONSTRAIN)
self.point,ctrlPoint,self.info = getPoint(self,arg)
self.point,ctrlPoint,self.info = getPoint(self,arg,noTracker=(len(self.node)>0))
if self.arcmode or self.point2:
setMod(arg,MODCONSTRAIN,False)
if hasMod(arg,MODALT) and (len(self.node)<3):
@ -1696,6 +1698,7 @@ class Dimension(Creator):
self.dimtrack.update(self.node+[self.point]+[self.cont])
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
import DraftGeomUtils
if self.point:
if (not self.node) and (not self.support):
self.support = getSupport(arg)
@ -1721,7 +1724,6 @@ class Dimension(Creator):
self.node = [v1,v2]
self.link = [ob,i1,i2]
self.edges.append(ed)
import DraftGeomUtils
if DraftGeomUtils.geomType(ed) == "Circle":
# snapped edge is an arc
self.arcmode = "diameter"
@ -1736,6 +1738,7 @@ class Dimension(Creator):
self.node[3],
True,True)
if c:
print "centers:",c
self.center = c[0]
self.arctrack.setCenter(self.center)
self.arctrack.on()
@ -1786,6 +1789,118 @@ class Dimension(Creator):
self.createObject()
if not self.cont: self.finish()
class ShapeString(Creator):
"This class creates a shapestring feature."
def GetResources(self):
return {'Pixmap' : 'Draft_ShapeString',
'Accel' : "S, S",
'MenuShapeString': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "ShapeString"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Draft_ShapeString", "Creates text string in shapes.")}
def Activated(self):
name = str(translate("draft","ShapeString"))
Creator.Activated(self,name)
if self.ui:
self.ui.sourceCmd = self
self.dialog = None
self.text = ''
self.ui.sourceCmd = self
self.ui.pointUi(name)
self.call = self.view.addEventCallback("SoEvent",self.action)
self.ui.xValue.setFocus()
self.ui.xValue.selectAll()
msg(translate("draft", "Pick ShapeString location point:\n"))
FreeCADGui.draftToolBar.show()
def createObject(self):
"creates object in the current doc"
# print "debug: D_T ShapeString.createObject type(self.SString): " str(type(self.SString))
# temporary code
import platform
if not (platform.system() == 'Linux'):
# if (platform.system() == 'Linux'):
FreeCAD.Console.PrintWarning("Sorry, ShapeString is not yet fully implemented for your platform.\n")
self.finish()
return
# temporary code
dquote = '"'
String = dquote + self.SString + dquote
Size = str(self.SSSize) # numbers are ascii so this should always work
Tracking = str(self.SSTrack) # numbers are ascii so this should always work
FFile = dquote + self.FFile + dquote
# print "debug: D_T ShapeString.createObject type(String): " str(type(String))
# print "debug: D_T ShapeString.createObject type(FFile): " str(type(FFile))
try:
qr,sup,points,fil = self.getStrings()
self.commit(translate("draft","Create ShapeString"),
['import Draft',
'ss=Draft.makeShapeString(String='+String+',FontFile='+FFile+',Size='+Size+',Tracking='+Tracking+')',
'plm=FreeCAD.Placement()',
'plm.Base='+DraftVecUtils.toString(self.point),
'plm.Rotation.Q='+qr,
'ss.Placement=plm',
'ss.Support='+sup])
except Exception as e:
msg("Draft_ShapeString: error delaying commit", "error")
print type(e)
print e.args
self.finish()
def action(self,arg):
"scene event handler"
if arg["Type"] == "SoKeyboardEvent":
if arg["Key"] == "ESCAPE":
self.finish()
elif arg["Type"] == "SoLocation2Event": #mouse movement detection
self.point,ctrlPoint,info = getPoint(self,arg)
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
if self.point:
self.node.append(self.point)
self.ui.SSUi()
def numericInput(self,numx,numy,numz):
'''this function gets called by the toolbar when valid
x, y, and z have been entered there'''
self.point = Vector(numx,numy,numz)
self.node.append(self.point)
self.ui.SSUi() #move on to next step in parameter entry
def numericSSize(self,ssize):
'''this function is called by the toolbar when valid size parameter
has been entered. '''
self.SSSize = ssize
self.ui.STrackUi()
def numericSTrack(self,strack):
'''this function is called by the toolbar when valid size parameter
has been entered. ?'''
self.SSTrack = strack
self.ui.SFileUi()
def validSString(self,sstring):
'''this function is called by the toolbar when a ?valid? string parameter
has been entered. '''
self.SString = sstring
self.ui.SSizeUi()
def validFFile(self,FFile):
'''this function is called by the toolbar when a ?valid? font file parameter
has been entered. '''
self.FFile = FFile
# last step in ShapeString parm capture, create object
self.createObject()
def finish(self, finishbool=False):
"terminates the operation"
Creator.finish(self)
if self.ui:
# del self.dialog # what does this do??
if self.ui.continueMode:
self.Activated()
#---------------------------------------------------------------------------
# Modifier functions
@ -1821,7 +1936,14 @@ class Move(Modifier):
def proceed(self):
if self.call: self.view.removeEventCallback("SoEvent",self.call)
self.sel = Draft.getSelection()
self.sel = Draft.getGroupContents(self.sel)
# testing for special case: only Arch groups in selection
onlyarchgroups = True
for o in self.sel:
if not(Draft.getType(o) in ["Floor","Building","Site"]):
onlyarchgroups = False
if not onlyarchgroups:
# arch groups can be moved, no need to add their children
self.sel = Draft.getGroupContents(self.sel)
self.ui.pointUi(self.name)
self.ui.modUi()
self.ui.xValue.setFocus()
@ -2972,7 +3094,8 @@ class Edit(Modifier):
Modifier.finish(self)
plane.restore()
self.running = False
FreeCADGui.ActiveDocument.resetEdit()
# following line causes crash
# FreeCADGui.ActiveDocument.resetEdit()
def action(self,arg):
"scene event handler"
@ -3584,6 +3707,7 @@ FreeCADGui.addCommand('Draft_Polygon',Polygon())
FreeCADGui.addCommand('Draft_BSpline',BSpline())
FreeCADGui.addCommand('Draft_Point',Point())
FreeCADGui.addCommand('Draft_Ellipse',Ellipse())
FreeCADGui.addCommand('Draft_ShapeString',ShapeString())
# modification commands
FreeCADGui.addCommand('Draft_Move',Move())

File diff suppressed because it is too large Load Diff

View File

@ -104,7 +104,8 @@ class DraftWorkbench (Workbench):
pass
self.cmdList = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse",
"Draft_Polygon","Draft_Rectangle", "Draft_Text",
"Draft_Dimension", "Draft_BSpline","Draft_Point"]
"Draft_Dimension", "Draft_BSpline","Draft_Point",
"Draft_ShapeString"]
self.modList = ["Draft_Move","Draft_Rotate","Draft_Offset",
"Draft_Trimex", "Draft_Upgrade", "Draft_Downgrade", "Draft_Scale",
"Draft_Drawing","Draft_Edit","Draft_WireToBSpline","Draft_AddPoint",
@ -161,3 +162,12 @@ App.addExportType("Autodesk DXF (*.dxf)","importDXF")
App.addExportType("Flattened SVG (*.svg)","importSVG")
App.addExportType("Open CAD Format (*.oca)","importOCA")
# DWG support
import importDWG
if importDWG.getTeighaConverter():
App.addImportType("Autodesk DWG (*.dwg)","importDWG")
App.addExportType("Autodesk DWG (*.dwg)","importDWG")
else:
from DraftTools import translate
FreeCAD.Console.PrintMessage(str(translate("draft","Teigha File Converter not found, DWG support will be disabled.\n")))

View File

@ -55,6 +55,7 @@
<file>icons/Draft_Clone.svg</file>
<file>icons/Draft_Heal.svg</file>
<file>icons/Draft_Ellipse.svg</file>
<file>icons/Draft_ShapeString.svg</file>
<file>patterns/concrete.svg</file>
<file>patterns/cross.svg</file>
<file>patterns/line.svg</file>

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg4594"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Draft_ShapeString.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs4596">
<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="perspective4602" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568542"
inkscape:cx="16.724718"
inkscape:cy="24.831907"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1366"
inkscape:window-height="695"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata4599">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="15.684914"
y="19.773684"
id="text3097"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3099"
x="15.684914"
y="19.773684" /></text>
<g
id="g4061">
<text
transform="scale(1.2630773,0.79171719)"
sodipodi:linespacing="125%"
id="text3892"
y="69.508385"
x="5.465425"
style="font-size:77.39546203999999818px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;opacity:0.62711863999999995;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.191;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Times New Roman;-inkscape-font-specification:'Times New Roman, Italic'"
xml:space="preserve"><tspan
style="stroke-width:3.191;stroke-miterlimit:4;stroke-dasharray:none"
y="69.508385"
x="5.465425"
id="tspan3894"
sodipodi:role="line">S</tspan><tspan
style="stroke-width:3.191;stroke-miterlimit:4;stroke-dasharray:none"
id="tspan3896"
y="166.25272"
x="5.465425"
sodipodi:role="line" /></text>
<text
inkscape:transform-center-y="17.646795"
inkscape:transform-center-x="1.9859923"
transform="scale(1.258685,0.79447996)"
sodipodi:linespacing="125%"
id="text3103"
y="65.225639"
x="2.1774669"
style="font-size:80.06713104px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffda04;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.57333159;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Times New Roman;-inkscape-font-specification:'Times New Roman, Italic'"
xml:space="preserve"><tspan
style="stroke-width:1.57333159"
y="65.225639"
x="2.1774669"
id="tspan3105"
sodipodi:role="line">S</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>590</width>
<height>632</height>
<width>718</width>
<height>808</height>
</rect>
</property>
<property name="windowTitle">
@ -1199,6 +1199,49 @@ such as &quot;Arial:Bold&quot;</string>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_23">
<item>
<widget class="QLabel" name="label_24">
<property name="text">
<string>Default ShapeString Font File</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Gui::PrefFileChooser" name="gui::preffilechooser">
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Select a font file</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>FontFile</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>

View File

@ -280,6 +280,26 @@ If color mapping is choosed, you must choose a color mapping file containing a t
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="Gui::PrefCheckBox" name="gui::prefcheckbox_12">
<property name="toolTip">
<string>If this is checked, the exported objects will be projected to reflect the current view direction</string>
</property>
<property name="text">
<string>Project exported objects along current view direction</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>dxfproject</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>

View File

@ -0,0 +1,94 @@
# -*- coding: utf8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2009 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (GPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
"FreeCAD Draft Workbench - DWG importer/exporter"
if open.__module__ == '__builtin__':
pythonopen = open # to distinguish python built-in open function from the one declared here
def open(filename):
"called when freecad opens a file."
dxf = convertToDxf(filename)
import importDXF
doc = importDXF.open(dxf)
return doc
def insert(filename,docname):
"called when freecad imports a file"
dxf = convertToDxf(filemname)
import importDXF
doc = importDXF.insert(dxf,docname)
return doc
def export(objectslist,filename):
"called when freecad exports a file"
import importDXF,os,tempfile
outdir = tempfile.mkdtemp()
dxf = outdir + os.sep + os.path.splitext(os.path.basename(filename))[0] + ".dxf"
importDXF.export(objectslist,dxf)
convertToDwg(dxf,filename)
return filename
def getTeighaConverter():
"finds the Teigha Converter executable"
import os,platform
teigha = None
if platform.system() == "Linux":
teigha = "/usr/bin/TeighaFileConverter"
elif platform.system() == "Windows":
odadir = "C:\Program Files\ODA"
if os.path.exists(odadir):
subdirs = os.walk(odadir).next()[1]
for sub in subdirs:
t = odadir + os.sep + sub + os.sep + "TeighaFileConverter.exe"
if os.path.exists(t):
teigha = t
if teigha:
if os.path.exists(teigha):
return teigha
return None
def convertToDxf(dwgfilename):
"converts a DWG file to DXF"
import os,tempfile
teigha = getTeighaConverter()
indir = os.path.dirname(dwgfilename)
outdir = tempfile.mkdtemp()
basename = os.path.basename(dwgfilename)
cmdline = teigha + ' "' + indir + '" "' + outdir + '" "ACAD2010" "DXF" "0" "1" "' + basename + '"'
print "converting " + cmdline
os.system(cmdline)
return outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
def convertToDwg(dxffilename,dwgfilename):
"converts a DXF file to DWG"
import os
teigha = getTeighaConverter()
indir = os.path.dirname(dxffilename)
outdir = os.path.dirname(dwgfilename)
basename = os.path.basename(dxffilename)
cmdline = teigha + ' "' + indir + '" "' + outdir + '" "ACAD2010" "DWG" "0" "1" "' + basename + '"'
print "converting " + cmdline
os.system(cmdline)
return dwgfilename

View File

@ -1190,18 +1190,31 @@ def insert(filename,docname):
# EXPORT ########################################################################
def projectShape(shape,direction):
import Drawing
edges = []
try:
groups = Drawing.projectEx(shape,direction)
except:
print "unable to project shape"
return shape
else:
for g in groups[0:5]:
if g:
edges.append(g)
return DraftGeomUtils.cleanProjection(Part.makeCompound(edges))
def getArcData(edge):
"returns center, radius, start and end angles of a circle-based edge"
ce = edge.Curve.Center
radius = edge.Curve.Radius
if len(edge.Vertexes) == 1:
# closed circle
return ce, radius, 0, 0
return DraftVecUtils.tup(ce), radius, 0, 0
else:
# find direction of arc
tang1 = edge.Curve.tangent(edge.ParameterRange[0])
tang2 = edge.Curve.tangent(edge.ParameterRange[1])
# method 1 - find direction of arc from tangents - not reliable
#tang1 = edge.Curve.tangent(edge.ParameterRange[0])
#tang2 = edge.Curve.tangent(edge.ParameterRange[1])
# following code doesn't seem to give right result?
# cross1 = Vector.cross(Vector(tang1[0][0],tang1[0][1],tang1[0][2]),Vector(tang2[0][0],tang2[0][1],tang2[0][2]))
# if cross1[2] > 0: # >0 ccw <0 cw
@ -1211,15 +1224,31 @@ def getArcData(edge):
# ve1 = edge.Vertexes[-1].Point
# ve2 = edge.Vertexes[0].Point
# check the midpoint seems more reliable
# method 3 - recreate an arc and check if the length is the same
ve1 = edge.Vertexes[0].Point
ve2 = edge.Vertexes[-1].Point
ang1 = -math.degrees(DraftVecUtils.angle(ve1.sub(ce)))
ang2 = -math.degrees(DraftVecUtils.angle(ve2.sub(ce)))
ve3 = DraftGeomUtils.findMidpoint(edge)
ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce)))
if (ang3 < ang1) and (ang2 < ang3):
a1 = -DraftVecUtils.angle(ve1.sub(ce))
a2 = -DraftVecUtils.angle(ve2.sub(ce))
pseudoarc = Part.ArcOfCircle(edge.Curve,a1,a2).toShape()
if round(pseudoarc.Length,Draft.precision()) != round(edge.Length,Draft.precision()):
ang1, ang2 = ang2, ang1
# method 2 - check the midpoint - not reliable either
#ve3 = DraftGeomUtils.findMidpoint(edge)
#ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce)))
#print "edge ",edge.hashCode()," data ",ang1, " , ",ang2," , ", ang3
#if (ang3 < ang1) and (ang2 < ang3):
# print "inverting, case1"
# ang1, ang2 = ang2, ang1
#elif (ang3 > ang1) and (ang3 > ang2):
# print "inverting, case2"
# ang1, ang2 = ang2, ang1
#elif (ang3 < ang1) and (ang3 < ang2):
# print "inverting, case3"
# ang1, ang2 = ang2, ang1
return DraftVecUtils.tup(ce), radius, ang1, ang2
def getSplineSegs(edge):
@ -1246,6 +1275,7 @@ def getWire(wire,nospline=False):
"returns an array of dxf-ready points and bulges from a wire"
edges = DraftGeomUtils.sortEdges(wire.Edges)
points = []
# print "processing wire ",wire.Edges
for edge in edges:
v1 = edge.Vertexes[0].Point
if len(edge.Vertexes) < 2:
@ -1256,7 +1286,8 @@ def getWire(wire,nospline=False):
c = edge.Curve.Center
angle = abs(DraftVecUtils.angle(v1.sub(c),v2.sub(c)))
if DraftGeomUtils.isWideAngle(edge):
angle = math.pi*2 - angle
if angle < math.pi:
angle = math.pi*2 - angle
# if (DraftVecUtils.angle(v2.sub(c)) < DraftVecUtils.angle(v1.sub(c))):
# angle = -angle
# polyline bulge -> negative makes the arc go clockwise
@ -1293,16 +1324,16 @@ def getWire(wire,nospline=False):
# print "wire verts: ",points
return points
def getBlock(obj):
def getBlock(sh,obj):
"returns a dxf block with the contents of the object"
block = dxfLibrary.Block(name=obj.Name,layer=getGroup(obj,exportList))
writeShape(obj,block)
writeShape(sh,obj,block)
return block
def writeShape(ob,dxfobject,nospline=False):
def writeShape(sh,ob,dxfobject,nospline=False):
"writes the object's shape contents in the given dxf object"
processededges = []
for wire in ob.Shape.Wires: # polylines
for wire in sh.Wires: # polylines
for e in wire.Edges:
processededges.append(e.hashCode())
if (len(wire.Edges) == 1) and (DraftGeomUtils.geomType(wire.Edges[0]) == "Circle"):
@ -1319,22 +1350,32 @@ def writeShape(ob,dxfobject,nospline=False):
dxfobject.append(dxfLibrary.PolyLine(getWire(wire,nospline), [0.0,0.0,0.0],
int(DraftGeomUtils.isReallyClosed(wire)), color=getACI(ob),
layer=getGroup(ob,exportList)))
if len(processededges) < len(ob.Shape.Edges): # lone edges
if len(processededges) < len(sh.Edges): # lone edges
loneedges = []
for e in ob.Shape.Edges:
for e in sh.Edges:
if not(e.hashCode() in processededges): loneedges.append(e)
# print "lone edges ",loneedges
for edge in loneedges:
if (DraftGeomUtils.geomType(edge) == "BSplineCurve") and ((not nospline) or (len(edge.Vertexes) == 1)): # splines
points = []
spline = getSplineSegs(edge)
for p in spline:
points.append((p.x,p.y,p.z,None,None,0.0))
dxfobject.append(dxfLibrary.PolyLine(points, [0.0,0.0,0.0],
0, color=getACI(ob),
layer=getGroup(ob,exportList)))
if (len(edge.Vertexes) == 1) and (edge.Curve.isClosed()):
# special case: 1-vert closed spline, approximate as a circle
c = DraftGeomUtils.getCircleFromSpline(edge)
if c:
dxfobject.append(dxfLibrary.Circle(DraftVecUtils.tup(c.Curve.Center), c.Curve.Radius,
color=getACI(ob),
layer=getGroup(ob,exportList)))
else:
points = []
spline = getSplineSegs(edge)
for p in spline:
points.append((p.x,p.y,p.z,None,None,0.0))
dxfobject.append(dxfLibrary.PolyLine(points, [0.0,0.0,0.0],
0, color=getACI(ob),
layer=getGroup(ob,exportList)))
elif DraftGeomUtils.geomType(edge) == "Circle": # curves
center, radius, ang1, ang2 = getArcData(edge)
if not isinstance(center,tuple):
center = DraftVecUtils.tup(center)
if len(edge.Vertexes) == 1: # circles
dxfobject.append(dxfLibrary.Circle(center, radius,
color=getACI(ob),
@ -1389,27 +1430,37 @@ def export(objectslist,filename,nospline=False):
for ob in exportList:
print "processing ",ob.Name
if ob.isDerivedFrom("Part::Feature"):
if not ob.Shape.isNull():
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"):
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"):
sh = None
if not ob.Shape.isNull():
writeMesh(ob,dxf)
elif FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfproject"):
direction = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
sh = projectShape(ob.Shape,direction)
else:
if ob.Shape.Volume > 0:
sh = projectShape(ob.Shape,Vector(0,0,1))
else:
if ob.Shape.ShapeType == 'Compound':
if (len(ob.Shape.Wires) == 1):
sh = ob.Shape
if sh:
if not sh.isNull():
if sh.ShapeType == 'Compound':
if (len(sh.Wires) == 1):
# only one wire in this compound, no lone edge -> polyline
if (len(ob.Shape.Wires[0].Edges) == len(ob.Shape.Edges)):
writeShape(ob,dxf,nospline)
if (len(sh.Wires[0].Edges) == len(sh.Edges)):
writeShape(sh,ob,dxf,nospline)
else:
# 1 wire + lone edges -> block
block = getBlock(ob)
block = getBlock(sh,ob)
dxf.blocks.append(block)
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
else:
# all other cases: block
block = getBlock(ob)
block = getBlock(sh,ob)
dxf.blocks.append(block)
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
else:
writeShape(ob,dxf,nospline)
writeShape(sh,ob,dxf,nospline)
elif Draft.getType(ob) == "Annotation":
# texts

View File

@ -2,9 +2,20 @@
# (c) 2011 Werner Mayer LGPL
class DocumentObject(object):
"""The Document object is the base class for all FreeCAD objects.
Example of use:
import FreeCAD
doc=FreeCAD.newDocument()
myobj = doc.addObject("Mesh::FeaturePython","MyName")
myobj.addProperty("App::PropertyLinkList","Layers","Base", "Layers")"""
def __init__(self):
self.__object__=None
def execute(self):
"this method is executed on object creation and whenever the document is recomputed"
raise Exception("Not yet implemented")
#def onChanged(self,prop):
# return None
@ -14,67 +25,98 @@ class DocumentObject(object):
# else:
# return object.__getattribute__(self,attr)
def addProperty(self,type,name='',group='',doc='',attr=0,readonly=False,hidden=False):
"adds a new property to this object"
self.__object__.addProperty(type,name,group,doc,attr,readonly,hidden)
def supportedProperties(self):
"lists the property types supported by this object"
return self.__object__.supportedProperties()
def isDerivedFrom(self, obj):
"""returns True if this object is derived from the given C++ class, for
example Part::Feature"""
return self.__object__.isDerivedFrom(obj)
def getAllDerivedFrom(self):
"returns all parent C++ classes of this object"
return self.__object__.getAllDerivedFrom()
def getProperty(self,attr):
"returns the value of a given property"
return self.__object__.getPropertyByName(attr)
def getTypeOfProperty(self,attr):
"returns the type of a given property"
return self.__object__.getTypeOfProperty(attr)
def getGroupOfProperty(self,attr):
"returns the group of a given property"
return self.__object__.getGroupOfProperty(attr)
def getDocumentationOfProperty(self,attr):
"returns the documentation string of a given property"
return self.__object__.getDocumentationOfProperty(attr)
def touch(self):
"marks this object to be recomputed"
return self.__object__.touch()
def purgeTouched(self):
"removes the to-be-recomputed flag of this object"
return self.__object__.purgeTouched()
def __setstate__(self,value):
"""allows to save custom attributes of this object as strings, so
they can be saved when saving the FreeCAD document"""
return None
def __getstate__(self):
"""reads values previously saved with __setstate__()"""
return None
@property
def PropertiesList(self):
"lists the current properties of this object"
return self.__object__.PropertiesList
@property
def Type(self):
"shows the C++ class of this object"
return self.__object__.Type
@property
def Module(self):
"gives the module this object is defined in"
return self.__object__.Module
@property
def Content(self):
"""shows the contents of the properties of this object as an xml string.
This is the content that is saved when the file is saved by FreeCAD"""
return self.__object__.Content
@property
def MemSize(self):
"shows the amount of memory this object uses"
return self.__object__.MemSize
@property
def Name(self):
"the name ofthis object, unique in the FreeCAD document"
return self.__object__.Name
@property
def Document(self):
"the document this object is part of"
return self.__object__.Document
@property
def State(self):
"shows if this object is valid (presents no errors)"
return self.__object__.State
@property
def ViewObject(self):
return self.__object__.ViewObject
@ViewObject.setter
def ViewObject(self,value):
"""returns or sets the ViewObject associated with this object. Returns
None if FreeCAD is running in console mode"""
self.__object__.ViewObject=value
@property
def InList(self):
"lists the parents of this object"
return self.__object__.InList
@property
def OutList(self):
"lists the children of this object"
return self.__object__.OutList
class ViewProvider(object):
"""The ViewProvider is the counterpart of the DocumentObject in
the GUI space. It is only present when FreeCAD runs in GUI mode.
It contains all that is needed to represent the DocumentObject in
the 3D view and the FreeCAD interface"""
def __init__(self):
self.__vobject__=None
#def getIcon(self):
@ -92,6 +134,7 @@ class ViewProvider(object):
#def onChanged(self, prop):
# return None
def addDisplayMode(self,node,mode):
"adds a coin node as a display mode to this object"
self.__vobject__.addDisplayMode(node,mode)
#def getDefaultDisplayMode(self):
# return ""
@ -100,65 +143,93 @@ class ViewProvider(object):
#def setDisplayMode(self,mode):
# return mode
def addProperty(self,type,name='',group='',doc='',attr=0,readonly=False,hidden=False):
"adds a new property to this object"
self.__vobject__.addProperty(type,name,group,doc,attr,readonly,hidden)
def update(self):
"this method is executed whenever any of the properties of this ViewProvider changes"
self.__vobject__.update()
def show(self):
"switches this object to visible"
self.__vobject__.show()
def hide(self):
"switches this object to invisible"
self.__vobject__.hide()
def isVisible(self):
"shows wether this object is visible or invisible"
return self.__vobject__.isVisible()
def toString(self):
"returns a string representation of the coin node of this object"
return self.__vobject__.toString()
def startEditing(self,mode=0):
"sets this object in edit mode"
return self.__vobject__.startEditing(mode)
def finishEditing(self):
"leaves edit mode for this object"
self.__vobject__.finishEditing()
def isEditing(self):
"shows wether this object is in edit mode"
self.__vobject__.isEditing()
def setTransformation(self,trsf):
"defines a transformation for this object"
return self.__vobject__.setTransformation(trsf)
def supportedProperties(self):
"lists the property types this ViewProvider supports"
return self.__vobject__.supportedProperties()
def isDerivedFrom(self, obj):
"""returns True if this object is derived from the given C++ class, for
example Part::Feature"""
return self.__vobject__.isDerivedFrom(obj)
def getAllDerivedFrom(self):
"returns all parent C++ classes of this object"
return self.__vobject__.getAllDerivedFrom()
def getProperty(self,attr):
"returns the value of a given property"
return self.__vobject__.getPropertyByName(attr)
def getTypeOfProperty(self,attr):
"returns the type of a given property"
return self.__vobject__.getTypeOfProperty(attr)
def getGroupOfProperty(self,attr):
"returns the group of a given property"
return self.__vobject__.getGroupOfProperty(attr)
def getDocumentationOfProperty(self,attr):
"returns the documentation string of a given property"
return self.__vobject__.getDocumentationOfProperty(attr)
@property
def Annotation(self):
"returns the Annotation coin node of this object"
return self.__vobject__.Annotation
@property
def RootNode(self):
"returns the Root coin node of this object"
return self.__vobject__.RootNode
@property
def DisplayModes(self):
"lists the display modes of this object"
return self.__vobject__.listDisplayModes()
@property
def PropertiesList(self):
"lists the current properties of this object"
return self.__vobject__.PropertiesList
@property
def Type(self):
"shows the C++ class of this object"
return self.__vobject__.Type
@property
def Module(self):
"gives the module this object is defined in"
return self.__vobject__.Module
@property
def Content(self):
"""shows the contents of the properties of this object as an xml string.
This is the content that is saved when the file is saved by FreeCAD"""
return self.__vobject__.Content
@property
def MemSize(self):
"shows the amount of memory this object uses"
return self.__vobject__.MemSize
@property
def Object(self):
"returns the DocumentObject this ViewProvider is associated to"
return self.__vobject__.Object

View File

@ -40,6 +40,7 @@
<File Id="DraftRcPy" Name="Draft_rc.py" DiskId="1" />
<File Id="DraftVecUtilsPy" Name="DraftVecUtils.py" DiskId="1" />
<File Id="DraftGeomUtilsPy" Name="DraftGeomUtils.py" DiskId="1" />
<File Id="importDWGPy" Name="importDWG.py" DiskId="1" />
</Component>
<Directory Id="ModDraftLib" Name="draftlibs" FileSource="../../Mod/Draft/draftlibs">
<Component Id="CompModDraftLib" Guid="d19c08b0-0747-11de-8c30-0800200c9a66" Win64='$(var.Win_64)' KeyPath="yes">