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

This commit is contained in:
wmayer 2014-04-14 18:15:27 +02:00
commit 384778e2db
8 changed files with 449 additions and 17 deletions

View File

@ -105,8 +105,7 @@ def addComponents(objectsList,host):
a = host.Objects
for o in objectsList:
if not o in a:
if hasattr(o,"Shape"):
a.append(o)
a.append(o)
host.Objects = a
elif host.isDerivedFrom("App::DocumentObjectGroup"):
c = host.Group

View File

@ -34,4 +34,5 @@ if openscadbin:
FreeCAD.addImportType("OpenSCAD Format (*.scad)","importCSG")
FreeCAD.addExportType("OpenSCAD CSG Format (*.csg)","exportCSG")
FreeCAD.addExportType("OpenSCAD Format (*.scad)","exportCSG")
FreeCAD.addExportType("DRAWEXE source (*.draw)","exportDRAWEXE")

View File

@ -183,12 +183,17 @@ class ExpandPlacements:
class ReplaceObject:
def IsActive(self):
return FreeCADGui.Selection.countObjectsOfType('Part::Feature') == 3
nobj = FreeCADGui.Selection.countObjectsOfType('Part::Feature')
if nobj == 3: return True
elif nobj == 2: return tuple((len(obj.InList)) for obj in \
FreeCADGui.Selection.getSelection()) in ((0,1),(1,0))
#else: return False
def Activated(self):
import replaceobj
#objs=[selobj.Object for selobj in FreeCADGui.Selection.getSelectionEx()]
objs=FreeCADGui.Selection.getSelection()
if len(objs)==3:
if len(objs)==3 or \
tuple((len(obj.InList)) for obj in objs) in ((0,1),(1,0)):
replaceobj.replaceobjfromselection(objs)
else:
FreeCAD.Console.PrintError(unicode(translate('OpenSCAD',\

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,7 @@
<file>icons/OpenSCAD_AddOpenSCADElement.svg</file>
<file>icons/OpenSCAD_ColorCodeShape.svg</file>
<file>icons/OpenSCAD_RefineShapeFeature.svg</file>
<file>icons/OpenSCAD_IncreaseToleranceFeature.svg</file>
<file>icons/OpenSCAD_ReplaceObject.svg</file>
<file>icons/OpenSCAD_RemoveSubtree.svg</file>
<file>icons/OpenSCAD_Explode_Group.svg</file>

View File

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg3052"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="OpenSCAD_Tollerance5.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/user/Downloads/cad/mystuff/icons/OpenSCAD_workbench/OpenSCAD_Tollerance5_32px.png"
inkscape:export-xdpi="45"
inkscape:export-ydpi="45">
<defs
id="defs3054">
<linearGradient
id="linearGradient4032">
<stop
style="stop-color:#71b2f8;stop-opacity:1;"
offset="0"
id="stop4034" />
<stop
style="stop-color:#002795;stop-opacity:1;"
offset="1"
id="stop4036" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective3060" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.6244669,-0.05136783,0.04345521,0.9993132,-102.99033,7.7040438)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#4bff54;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#00b800;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3206"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.87904684,0.2250379,-0.41709097,2.0016728,56.73751,-127.99883)" />
<linearGradient
id="linearGradient3199">
<stop
id="stop3201"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3203"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3206">
<stop
id="stop3208"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3210"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4032"
id="radialGradient4030"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.260164,-0.05136783,0.03370995,0.9993132,-43.139781,7.2044077)"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="6.1640625"
inkscape:cx="14.457622"
inkscape:cy="54.967974"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1280"
inkscape:window-height="964"
inkscape:window-x="-2"
inkscape:window-y="-3"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata3057">
<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">
<g
id="g3820"
transform="matrix(0.98080794,0.19497632,-0.19497632,0.98080794,4.8695297,-16.238973)">
<g
id="g3830">
<path
style="fill:none;stroke:#0034ff;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 40.577328,52.677914 59.393065,8.1630479"
id="path3770"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
transform="matrix(0.46742792,-0.21500996,0.22332526,0.48550525,7.5601526,59.921543)"
d="m 73.247149,12.613435 c 0,4.054288 -3.413758,7.340938 -7.624842,7.340938 -4.211084,0 -7.624842,-3.28665 -7.624842,-7.340938 0,-4.0542884 3.413758,-7.3409383 7.624842,-7.3409383 4.211084,0 7.624842,3.2866499 7.624842,7.3409383 z"
sodipodi:ry="7.3409381"
sodipodi:rx="7.6248417"
sodipodi:cy="12.613435"
sodipodi:cx="65.622307"
id="path3023"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
</g>
</g>
<g
id="g3816"
transform="matrix(0.97990083,0.19948528,-0.19948528,0.97990083,-0.45058244,6.8167641)">
<path
style="fill:none;stroke:#0034ff;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 14.009867,52.774823 31.755777,9.1983344"
id="path3021"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3025"
sodipodi:cx="65.622307"
sodipodi:cy="12.613435"
sodipodi:rx="7.6248417"
sodipodi:ry="7.3409381"
d="m 73.247149,12.613435 c 0,4.054288 -3.413758,7.340938 -7.624842,7.340938 -4.211084,0 -7.624842,-3.28665 -7.624842,-7.340938 0,-4.0542884 3.413758,-7.3409383 7.624842,-7.3409383 4.211084,0 7.624842,3.2866499 7.624842,7.3409383 z"
transform="matrix(0.48363026,-0.22246279,0.23799276,0.51739213,-3.2126987,17.62151)" />
</g>
<path
sodipodi:type="arc"
style="fill:none;stroke:#ff0900;stroke-width:5.12306846;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:15.36920538,15.36920538;stroke-dashoffset:0"
id="path3801"
sodipodi:cx="25.551331"
sodipodi:cy="7.1381497"
sodipodi:rx="25.551331"
sodipodi:ry="26.200253"
d="m 51.102661,7.1381497 a 25.551331,26.200253 0 1 1 -51.102661,0 25.551331,26.200253 0 1 1 51.102661,0 z"
transform="matrix(0.96942917,0,0,0.98257024,6.7836602,26.405785)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -0,0 +1,198 @@
#***************************************************************************
#* *
#* Copyright (c) 2014 Sebastian Hoogen <github@sebastianhoogen.de> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* 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 *
#* *
#***************************************************************************
__title__="FreeCAD OpenSCAD Workbench - DRAWEXE exporter"
__author__ = "Sebastian Hoogen <github@sebastianhoogen.de>"
import FreeCAD, Part
if open.__module__ == '__builtin__':
pythonopen = open
def f2s(n):
'''convert to numerical value to string'''
#return str(float(n))
return ('%0.18f' % n).rstrip('0')
def isOpenSCADFeature(ob):
if ob.isDerivedFrom('Part::FeaturePython') and \
hasattr(ob.Proxy,'__module__') and \
ob.Proxy.__module__ == 'OpenSCADFeatures':
return True
def isOpenSCADMultMatrixFeature(ob):
if ob.isDerivedFrom('Part::FeaturePython') and \
hasattr(ob.Proxy,'__module__') and \
ob.Proxy.__module__ == 'OpenSCADFeatures':
import OpenSCADFeatures
return isinstance(ob.Proxy,OpenSCADFeatures.MatrixTransform)
def isDeform(ob):
"""tests whether the object is a Matrix transformation
that does a non-uniform scaling"""
# the [ is important to exclude cases with additional
# rotation or mirroring.
# TBD decompose complex matrix operations
return isOpenSCADMultMatrixFeature(ob) and \
ob.Matrix.analyze().startswith('Scale [')
def process_object(csg,ob,filename):
d1 = {'name':ob.Name}
hasplacement = not ob.Placement.isNull()
if ob.TypeId in ["Part::Cut","Part::Fuse","Part::Common","Part::Section"]:
d1.update({'part':ob.Base.Name,'tool':ob.Tool.Name,\
'command':'b%s' % ob.TypeId[6:].lower()})
process_object(csg,ob.Base,filename)
process_object(csg,ob.Tool,filename)
csg.write("%(command)s %(name)s %(part)s %(tool)s\n"%d1)
elif ob.TypeId == "Part::Sphere" :
d1.update({'radius':f2s(ob.Radius),'angle1':f2s(ob.Angle1),\
'angle2':f2s(ob.Angle2),'angle3':f2s(ob.Angle3)})
csg.write('psphere %(name)s %(radius)s %(angle1)s %(angle2)s '\
'%(angle3)s\n'%d1)
elif ob.TypeId == "Part::Box" :
d1.update({'dx':f2s(ob.Length),'dy':f2s(ob.Width),'dz':f2s(ob.Height)})
csg.write('box %(name)s %(dx)s %(dy)s %(dz)s\n'%d1)
elif ob.TypeId == "Part::Cylinder" :
d1.update({'radius':f2s(ob.Radius),'height':f2s(ob.Height),\
'angle':f2s(ob.Angle)})
csg.write('pcylinder %(name)s %(radius)s %(height)s %(angle)s\n'%d1)
elif ob.TypeId == "Part::Cone" :
d1.update({'radius1':f2s(ob.Radius1),'radius2':f2s(ob.Radius2),\
'height':f2s(ob.Height)})
csg.write('pcone %(name)s %(radius1)s %(radius2)s %(height)s\n'%d1)
elif ob.TypeId == "Part::Torus" :
d1.update({'radius1':f2s(ob.Radius1),'radius2':f2s(ob.Radius2),\
'angle1': f2s(ob.Angle1),'angle2':f2s(ob.Angle2),\
'angle3': f2s(ob.Angle3)})
csg.write('ptorus %(name)s %(radius1)s %(radius2)s %(angle1)s '\
'%(angle2)s %(angle3)s\n' % d1)
elif ob.TypeId == "Part::Mirroring" :
process_object(csg,ob.Source,filename)
csg.write('tcopy %s %s\n'%(ob.Source.Name,d1['name']))
b=ob.Base
d1['dx']=f2s(ob.Base.x)
d1['dy']=f2s(ob.Base.y)
d1['dz']=f2s(ob.Base.z)
d1['x']=f2s(ob.Normal.x)
d1['y']=f2s(ob.Normal.y)
d1['z']=f2s(ob.Normal.z)
csg.write('smirror %(name)s %(x)s %(y)s %(z)s %(dx)s %(dy)s %(dz)s\n' % d1)
elif ob.TypeId in ["Part::MultiCommon", "Part::MultiFuse"]:
if len(ob.Shapes) == 0:
pass
elif len(ob.Shapes) == 1:
process_object(csg,ob.Shapes[0],filename)
csg.write('tcopy %s %s\n'%(ob.Shapes[0].Name,d1['name']))
else:
topname = ob.Name
command = 'b%s' % ob.TypeId[11:].lower()
lst1=ob.Shapes[:]
current=lst1.pop(0)
curname=current.Name
process_object(csg,current,filename)
i=1
while lst1:
if len(lst1) >= 2:
nxtname='to-%s-%03d-t'%(topname,i)
else:
nxtname=topname
nxt=lst1.pop(0)
process_object(csg,nxt,filename)
csg.write("%s %s %s %s\n"%(command,nxtname,curname,nxt.Name))
curname=nxtname
elif ob.TypeId == "Part::Prism" :
import math
polyname = '%s-polyline' % d1['name']
wirename = '%s-polywire' % d1['name']
facename = '%s-polyface' % d1['name']
d1['base']= facename
m=FreeCAD.Matrix()
v=FreeCAD.Vector(ob.Circumradius.Value,0,0)
m.rotateZ(2*math.pi/ob.Polygon)
points=[]
for i in range(ob.Polygon):
points.append(v)
v=m.multiply(v)
points.append(v)
pointstr=' '.join('%s %s %s'%(f2s(v.x),f2s(v.y),f2s(v.z)) \
for v in points)
csg.write('polyline %s %s\n' % (polyname,pointstr))
csg.write('wire %s %s\n' %(wirename,polyname))
csg.write('mkplane %s %s\n' % (facename,polyname))
csg.write('prism %s %s 0 0 %s\n' % (d1['name'],facename,\
f2s(ob.Height.Value)))
elif isDeform(ob): #non-uniform scaling
m=ob.Matrix
process_object(csg,ob.Base,filename)
#csg.write('tcopy %s %s\n'%(ob.Base.Name,d1['name']))
d1['basename']=ob.Base.Name
d1['cx']=f2s(m.A11)
d1['cy']=f2s(m.A22)
d1['cz']=f2s(m.A33)
csg.write('deform %(name)s %(basename)s %(cx)s %(cy)s %(cz)s\n' % d1)
if m.A14 > 1e-8 or m.A24 > 1e-8 or m.A34 > 1e-8:
csg.write("ttranslate %s %s %s %s\n" % \
(ob.Name,f2s(m.A14),f2s(m.A24),f2s(m.A34)))
#elif ob.isDerivedFrom('Part::FeaturePython') and \
# hasattr(ob.Proxy,'__module__'):
# pass
elif ob.isDerivedFrom('Part::Feature') :
if ob.Shape.isNull(): #would crash in exportBrep otherwise
raise ValueError
import os
spath,sname = os.path.split(filename)
sname.replace('.','-')
uname='%s-%s' %(sname,d1['name'])
breppath=os.path.join(spath,'%s.brep'%uname)
csg.write("restore %s.brep\n"%uname)
csg.write("renamevar %s %s\n"%(uname,d1['name']))
if False: # saved with placement
hasplacement = False # saved with placement
ob.Shape.exportBrep(breppath)
if not hasplacement: #doesn't matter
ob.Shape.exportBrep(breppath)
else: #remove placement
sh=ob.Shape.copy()
sh.Placement=FreeCAD.Placement()
sh.exportBrep(breppath)
if hasplacement:
if not ob.Placement.Rotation.isNull():
import math
dx,dy,dz=ob.Placement.Rotation.Axis
an=math.degrees(ob.Placement.Rotation.Angle)
csg.write("trotate %s 0 0 0 %s %s %s %s\n" % \
(ob.Name,f2s(dx),f2s(dy),f2s(dz),f2s(an)))
if ob.Placement.Base.Length > 1e-8:
x,y,z=ob.Placement.Base
csg.write("ttranslate %s %s %s %s\n" % \
(ob.Name,f2s(x),f2s(y),f2s(z)))
def export(exportList,filename):
"called when freecad exports a file"
# process Objects
csg = pythonopen(filename,'w')
csg.write('#generated by FreeCAD\n')
csg.write('pload ALL\n')
for ob in exportList:
process_object(csg,ob,filename)
csg.write('donly %s\n'%' '.join([obj.Name for obj in exportList]))
csg.close()

View File

@ -44,15 +44,31 @@ def replaceobj(parent,oldchild,newchild):
parent.touch()
def replaceobjfromselection(objs):
assert(len(objs)==3)
if objs[2] in objs[0].InList: oldchild, newchild, parent = objs
elif objs[0] in objs[1].InList: parent, oldchild, newchild = objs
elif objs[0] in objs[2].InList: parent, newchild, oldchild = objs
elif objs[1] in objs[0].InList: oldchild, parent, newchild = objs
elif objs[1] in objs[2].InList: newchild, parent, oldchild = objs
elif objs[2] in objs[1].InList: newchild, oldchild, parent = objs
else: assert(False)
# The Parent can be ommited as long as one object is orphaned
if len(objs)==2:
InListLength= tuple((len(obj.InList)) for obj in objs)
if InListLength == (0,1):
newchild,oldchild = objs
parent = oldchild.InList[0]
elif InListLength == (1,0):
oldchild,newchild = objs
parent = oldchild.InList[0]
else:
raise ValueError("Selection ambiguous. Please select oldchild,\
newchild and parent")
elif len(objs)==3:
if objs[2] in objs[0].InList: oldchild, newchild, parent = objs
elif objs[0] in objs[1].InList: parent, oldchild, newchild = objs
elif objs[0] in objs[2].InList: parent, newchild, oldchild = objs
elif objs[1] in objs[0].InList: oldchild, parent, newchild = objs
elif objs[1] in objs[2].InList: newchild, parent, oldchild = objs
elif objs[2] in objs[1].InList: newchild, oldchild, parent = objs
else:
raise ValueError("Cannot determin current parent-child relationship")
else:
raise ValueError("Wrong number of selected objects")
replaceobj(parent,oldchild,newchild)
parent.Document.recompute()
if __name__ == '__main__':
import FreeCAD,FreeCADGui