Merge branch 'master' of git://free-cad.git.sourceforge.net/gitroot/free-cad/free-cad

This commit is contained in:
jrheinlaender 2012-10-26 14:18:05 +04:30
commit 1ce464dd27
18 changed files with 2513 additions and 961 deletions

View File

@ -8,7 +8,6 @@ SET(OpenSCAD_SRCS
OpenSCADCommands.py
exportCSG.py
importCSG.py
prototype.py
tokrules.py
colorcodeshapes.py
expandplacements.py

View File

@ -24,3 +24,11 @@
#* *
#* Juergen Riegel 2002 *
#***************************************************************************/
import FreeCAD,os
FreeCAD.addImportType("OpenSCAD CSG Format (*.csg)","importCSG")
param = FreeCAD.ParamGet(\
"User parameter:BaseApp/Preferences/Mod/OpenSCAD")
openscadfilename = param.GetString('openscadexecutable')
openscadbin = openscadfilename and os.path.isfile(openscadfilename)
if openscadbin:
FreeCAD.addImportType("OpenSCAD Format (*.scad)","importCSG")

View File

@ -94,19 +94,26 @@ static char * openscadlogo_xpm[] = {
ToolTip = "OpenSCAD workbench"
def Initialize(self):
import OpenSCAD_rc,OpenSCADCommands
commands=["ColorCodeShape",'RefineShapeFeature','ReplaceObject',"Edgestofaces",'ExpandPlacements','RemoveSubtree']
commands=['ReplaceObject','RemoveSubtree','RefineShapeFeature',"Edgestofaces",'ExpandPlacements']
toolbarcommands=['ReplaceObject','RemoveSubtree','RefineShapeFeature']
import PartGui
parttoolbarcommands = ['Part_CheckGeometry',"Part_Primitives",\
"Part_Builder",'Part_Cut','Part_Fuse','Part_Common',\
'Part_Extrude',"Part_Revolve"]
import FreeCAD
param = FreeCAD.ParamGet(\
"User parameter:BaseApp/Preferences/Mod/OpenSCAD")
openscadfilename = param.GetString('openscadexecutable')
if openscadfilename:
commands.extend(['AddOpenSCADElement'])
self.appendToolbar("OpenSCADTools",["ColorCodeShape",'RefineShapeFeature','ReplaceObject','RemoveSubtree'])
toolbarcommands.extend(['AddOpenSCADElement'])
self.appendToolbar("OpenSCADTools",toolbarcommands)
self.appendMenu('OpenSCAD',commands)
self.appendToolbar('OpenSCAD Part tools',parttoolbarcommands)
#self.appendMenu('OpenSCAD',["AddOpenSCADElement"])
###self.appendCommandbar("&Generic Tools",["ColorCodeShape"])
FreeCADGui.addIconPath(":/icons")
#FreeCADGui.addLanguagePath(":/translations")
FreeCADGui.addLanguagePath(":/translations")
FreeCADGui.addPreferencePage(":/ui/openscadprefs-base.ui","OpenSCAD")
def GetClassName(self):
#return "OpenSCADGui::Workbench"
@ -114,16 +121,5 @@ static char * openscadlogo_xpm[] = {
Gui.addWorkbench(OpenSCADWorkbench())
App.addImportType("OpenSCAD CSG Format (*.csg)","importCSG")
App.addExportType("OpenSCAD CSG Format (*.csg)","exportCSG")
App.addExportType("OpenSCAD Format (*.scad)","exportCSG")
import os
openscadbin = openscadfilename and os.path.isfile(openscadfilename)
if openscadbin:
App.addImportType("OpenSCAD Format (*.scad)","importCSG")
if param.GetBool('debugRegisterPrototype'):
App.addImportType("OpenSCAD CSG prototype (*.csg)","prototype") #prototype
if openscadbin:
App.addImportType("OpenSCAD prototype (*.scad)","prototype") #prototype

View File

@ -11,7 +11,6 @@ data_DATA = \
OpenSCADCommands.py \
exportCSG.py \
importCSG.py \
prototype.py \
tokrules.py \
colorcodeshapes.py \
expandplacements.py \

View File

@ -1,6 +1,13 @@
import FreeCAD,FreeCADGui
from PyQt4 import QtGui, QtCore
def translate(context,text):
"convenience function for Qt translator"
return QtGui.QApplication.translate(context, text, None, \
QtGui.QApplication.UnicodeUTF8)
def utf8(unio):
return unicode(unio).encode('UTF8')
class ColorCodeShape:
"Change the Color of selected or all Shapes based on their validity"
def Activated(self):
@ -13,9 +20,16 @@ class ColorCodeShape:
objs=FreeCAD.ActiveDocument.Objects
colorcodeshapes.colorcodeshapes(objs)
def GetResources(self):
return {'Pixmap' : 'OpenSCAD_ColorCodeShape', 'MenuText': 'Color Shapes', 'ToolTip': 'Color Shapes by validity and type'}
return {'Pixmap' : 'OpenSCAD_ColorCodeShape', 'MenuText': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ColorCodeShape',\
'Color Shapes'), 'ToolTip': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ColorCodeShape',\
'Color Shapes by validity and type')}
class Edgestofaces:
def IsActive(self):
return bool(FreeCADGui.Selection.getSelectionEx())
def Activated(self):
from OpenSCAD2Dgeom import edgestofaces,Overlappingfaces
selection=FreeCADGui.Selection.getSelectionEx()
@ -28,9 +42,15 @@ class Edgestofaces:
FreeCAD.ActiveDocument.recompute()
def GetResources(self):
return {'Pixmap' : 'python', 'MenuText': 'EdgesToFaces', 'ToolTip': 'Convert Edges to Faces'}
return {'Pixmap' : 'python', 'MenuText': QtCore.QT_TRANSLATE_NOOP(\
'OpenSCAD_Edgestofaces','Convert Edges To Faces'),
'ToolTip': QtCore.QT_TRANSLATE_NOOP('OpenSCAD',\
'Convert Edges to Faces')}
class RefineShapeFeature:
def IsActive(self):
return bool(FreeCADGui.Selection.getSelectionEx())
def Activated(self):
import Part,OpenSCADFeatures
selection=FreeCADGui.Selection.getSelectionEx()
@ -44,22 +64,33 @@ class RefineShapeFeature:
FreeCAD.ActiveDocument.recompute()
def GetResources(self):
return {'Pixmap' : 'OpenSCAD_RefineShapeFeature', 'MenuText': \
'Refine Shape Feature', 'ToolTip': 'Create Refine Shape Feature'}
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RefineShapeFeature',\
'Refine Shape Feature'), 'ToolTip': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RefineShapeFeature',\
'Create Refine Shape Feature')}
class ExpandPlacements:
'''This should aid interactive repair in the future
but currently it breaks extrusions, as axis, base and so on have to be
recalculated'''
def IsActive(self):
return bool(FreeCADGui.Selection.getSelectionEx())
def Activated(self):
import expandplacements
selobj=FreeCADGui.Selection.getSelectionEx()[0]
expandplacements.expandplacements(selobj.Object,FreeCAD.Placement())
for selobj in FreeCADGui.Selection.getSelectionEx():
expandplacements.expandplacements(selobj.Object,FreeCAD.Placement())
FreeCAD.ActiveDocument.recompute()
def GetResources(self):
return {'Pixmap' : 'python', 'MenuText': 'Expand Placements', 'ToolTip': 'Expand all placements downwards the FeatureTree'}
return {'Pixmap' : 'python', 'MenuText': QtCore.QT_TRANSLATE_NOOP(\
'OpenSCAD_ExpandPlacements','Expand Placements'), 'ToolTip': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExpandPlacements',\
'Expand all placements downwards the FeatureTree')}
class ReplaceObject:
def IsActive(self):
return len(FreeCADGui.Selection.getSelection()) == 3
def Activated(self):
import replaceobj
#objs=[selobj.Object for selobj in FreeCADGui.Selection.getSelectionEx()]
@ -67,14 +98,19 @@ class ReplaceObject:
if len(objs)==3:
replaceobj.replaceobjfromselection(objs)
else:
FreeCAD.Console.PrintError('please select 3 objects first')
FreeCAD.Console.PrintError(unicode(translate('OpenSCAD',\
'Please select 3 objects first'))+u'\n')
def GetResources(self):
return {'Pixmap' : 'OpenSCAD_ReplaceObject', 'MenuText': \
'Replace Object', 'ToolTip': \
'Replace an object in the Feature Tree select old, new and parent object'}
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ReplaceObject',\
'Replace Object'), 'ToolTip': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ReplaceObject',\
'Replace an object in the Feature Tree. Please select old, new and parent object')}
class RemoveSubtree:
def IsActive(self):
return bool(FreeCADGui.Selection.getSelectionEx())
def Activated(self):
def addsubobjs(obj,toremoveset):
toremove.add(obj)
@ -98,16 +134,18 @@ class RemoveSubtree:
obj.Document.removeObject(obj.Name)
def GetResources(self):
return {'Pixmap' : 'OpenSCAD_RemoveSubtree', 'MenuText': \
'Remove Objects and thier Children', 'ToolTip': \
'Removes the selected Objects and all Children that are not referenced from other objects'}
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RemoveSubtree',\
'Remove Objects and their Children'), 'ToolTip': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RemoveSubtree',\
'Removes the selected objects and all children that are not referenced from other objects')}
class AddSCADWidget(QtGui.QWidget):
def __init__(self,*args):
QtGui.QWidget.__init__(self,*args)
self.textEdit=QtGui.QTextEdit()
self.buttonadd = QtGui.QPushButton(u'Add')
self.buttonclear = QtGui.QPushButton(u'Clear')
self.checkboxmesh = QtGui.QCheckBox(u'as Mesh')
self.buttonadd = QtGui.QPushButton(translate('OpenSCAD',u'Add'))
self.buttonclear = QtGui.QPushButton(translate('OpenSCAD',u'Clear'))
self.checkboxmesh = QtGui.QCheckBox(translate('OpenSCAD',u'as Mesh'))
layouth=QtGui.QHBoxLayout()
layouth.addWidget(self.buttonadd)
layouth.addWidget(self.buttonclear)
@ -116,10 +154,16 @@ class AddSCADWidget(QtGui.QWidget):
layout.addWidget(self.checkboxmesh)
layout.addWidget(self.textEdit)
self.setLayout(layout)
self.setWindowTitle(u'Add OpenSCAD Element')
self.setWindowTitle(translate('OpenSCAD',u'Add OpenSCAD Element'))
self.textEdit.setText(u'cube();')
self.buttonclear.clicked.connect(self.textEdit.clear)
def retranslateUi(self, widget=None):
self.buttonadd.setText(translate('OpenSCAD',u'Add'))
self.buttonclear.setText(translate('OpenSCAD',u'Clear'))
self.checkboxmesh.setText(translate('OpenSCAD',u'as Mesh'))
self.setWindowTitle(translate('OpenSCAD',u'Add OpenSCAD Element'))
class AddSCADTask:
def __init__(self):
self.form = AddSCADWidget()
@ -152,16 +196,18 @@ class AddSCADTask:
importCSG.insert(tmpfilename,doc.Name)
os.unlink(tmpfilename)
else:
FreeCAD.Console.PrintError('Running OpenSCAD failed\n')
FreeCAD.Console.PrintError(unicode(translate('OpenSCAD','Running OpenSCAD failed'))+u'\n')
class AddOpenSCADElement:
def Activated(self):
panel = AddSCADTask()
FreeCADGui.Control.showDialog(panel)
def GetResources(self):
return {'Pixmap' : 'python', 'MenuText': \
'Add OpenSCAD Element...', 'ToolTip': \
'Add an OpenSCAD Element by entering OpenSCAD Code and executing the OpenSCAD binary'}
return {'Pixmap' : 'OpenSCAD_AddOpenSCADElement', 'MenuText': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_AddOpenSCADElement',\
'Add OpenSCAD Element...'), 'ToolTip': \
QtCore.QT_TRANSLATE_NOOP('OpenSCAD_AddOpenSCADElement',\
'Add an OpenSCAD element by entering OpenSCAD code and executing the OpenSCAD binary')}
FreeCADGui.addCommand('ColorCodeShape',ColorCodeShape())

View File

@ -431,3 +431,35 @@ class OffsetShape:
def createGeometry(self,fp):
if fp.Base and fp.Offset:
fp.Shape=fp.Base.Shape.makeOffsetShape(self.Offset,1e-6)
def makeSurfaceVolume(filename):
import FreeCAD,Part
f1=open(filename)
coords=[]
miny=1
for line in f1.readlines():
sline=line.strip()
if sline and not sline.startswith('#'):
ycoord=len(coords)
lcoords=[]
for xcoord, num in enumerate(sline.split()):
fnum=float(num)
lcoords.append(FreeCAD.Vector(float(xcoord),float(ycoord),fnum))
miny=min(fnum,miny)
coords.append(lcoords)
s=Part.BSplineSurface()
s.interpolate(coords)
plane=Part.makePlane(len(coords[0])-1,len(coords)-1,FreeCAD.Vector(0,0,miny-1))
l1=Part.makeLine(plane.Vertexes[0].Point,s.value(0,0))
l2=Part.makeLine(plane.Vertexes[1].Point,s.value(1,0))
l3=Part.makeLine(plane.Vertexes[2].Point,s.value(0,1))
l4=Part.makeLine(plane.Vertexes[3].Point,s.value(1,1))
f0=plane.Faces[0]
f0.reverse()
f1=Part.Face(Part.Wire([plane.Edges[0],l1.Edges[0],s.vIso(0).toShape(),l2.Edges[0]]))
f2=Part.Face(Part.Wire([plane.Edges[1],l3.Edges[0],s.uIso(0).toShape(),l1.Edges[0]]))
f3=Part.Face(Part.Wire([plane.Edges[2],l4.Edges[0],s.vIso(1).toShape(),l3.Edges[0]]))
f4=Part.Face(Part.Wire([plane.Edges[3],l2.Edges[0],s.uIso(1).toShape(),l4.Edges[0]]))
f5=s.toShape().Faces[0]
solid=Part.Solid(Part.Shell([f0,f1,f2,f3,f4,f5]))
return solid,(len(coords[0])-1)/2.0,(len(choords)-1)/2.0

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
<RCC>
<qresource>
<file>icons/preferences-openscad.svg</file>
<file>icons/OpenSCAD_AddOpenSCADElement.svg</file>
<file>icons/OpenSCAD_ColorCodeShape.svg</file>
<file>icons/OpenSCAD_RefineShapeFeature.svg</file>
<file>icons/OpenSCAD_ReplaceObject.svg</file>

View File

@ -0,0 +1,305 @@
<?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="svg2784"
sodipodi:version="0.32"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Part_Sphere.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2786">
<linearGradient
id="linearGradient3808">
<stop
style="stop-color:#e4ea00;stop-opacity:1;"
offset="0"
id="stop3810" />
<stop
style="stop-color:#f2db00;stop-opacity:1;"
offset="1"
id="stop3812" />
</linearGradient>
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
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" />
<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="perspective2792" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-7"
id="radialGradient3692-1"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(2.5454545,3.8181818)" />
<linearGradient
id="linearGradient3377-7">
<stop
id="stop3379-4"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381-0"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.467436"
fy="28.869568"
fx="45.883327"
cy="28.869568"
cx="45.883327"
gradientUnits="userSpaceOnUse"
id="radialGradient3777"
xlink:href="#linearGradient3377-7"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-7"
id="radialGradient3798"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(2.1818181,3.8181818)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-7"
id="radialGradient3802"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.65611777,-0.75465852,0.75465852,-0.65611777,22.507051,71.547083)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-7"
id="radialGradient3806"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.69506957,-0.71894249,0.71894249,0.69506957,15.179872,55.595203)"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-2"
id="radialGradient3692-8"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3377-2">
<stop
id="stop3379-45"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381-5"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.467436"
fy="28.869568"
fx="45.883327"
cy="28.869568"
cx="45.883327"
gradientUnits="userSpaceOnUse"
id="radialGradient3777-1"
xlink:href="#linearGradient3377-2"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377-27"
id="radialGradient3692-5"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0.10223447,0.35782063)" />
<linearGradient
id="linearGradient3377-27">
<stop
id="stop3379-6"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381-1"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
r="19.467436"
fy="28.869568"
fx="45.883327"
cy="28.869568"
cx="45.883327"
gradientUnits="userSpaceOnUse"
id="radialGradient3777-4"
xlink:href="#linearGradient3377-27"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.61133982"
inkscape:cx="27.363636"
inkscape:cy="29.954517"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="719"
inkscape:window-height="670"
inkscape:window-x="89"
inkscape:window-y="125"
inkscape:window-maximized="0" />
<metadata
id="metadata2789">
<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="g3564"
transform="translate(-0.8153068,-67.540042)">
<path
transform="matrix(1.2482835,0,0,0.4121139,-28.969888,102.91872)"
d="m 71.785715,34.571426 c 0,10.256717 -8.314712,18.571429 -18.571428,18.571429 -10.256717,0 -18.571428,-8.314712 -18.571428,-18.571429 0,-10.256716 8.314711,-18.571428 18.571428,-18.571428 10.256716,0 18.571428,8.314712 18.571428,18.571428 z"
sodipodi:ry="18.571428"
sodipodi:rx="18.571428"
sodipodi:cy="34.571426"
sodipodi:cx="53.214287"
id="path3694"
style="opacity:0.66523605;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc" />
<path
transform="matrix(1.2276699,0,0,1.2276699,-36.802054,58.263192)"
d="m 71.785715,34.571426 c 0,10.256717 -8.314712,18.571429 -18.571428,18.571429 -10.256717,0 -18.571428,-8.314712 -18.571428,-18.571429 0,-10.256716 8.314711,-18.571428 18.571428,-18.571428 10.256716,0 18.571428,8.314712 18.571428,18.571428 z"
sodipodi:ry="18.571428"
sodipodi:rx="18.571428"
sodipodi:cy="34.571426"
sodipodi:cx="53.214287"
id="path3696"
style="opacity:1;fill:url(#radialGradient3692);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:1.79201269;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc" />
</g>
<path
style="color:#000000;fill:url(#radialGradient3798);fill-opacity:1.0;fill-rule:evenodd;stroke:#7b5600;stroke-width:1.79201269000000000;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 27.823864,10.71875 c -5.824094,0 -10.5625,1.834403 -10.5625,4.09375 0,2.259347 4.738406,4.09375 10.5625,4.09375 5.824094,0 10.53125,-1.834403 10.53125,-4.09375 0,-2.259347 -4.707156,-4.09375 -10.53125,-4.09375 z"
id="path3758"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path3800"
d="m 10.890422,47.668509 c 3.821292,4.395202 8.314592,6.767496 10.019627,5.285098 1.705036,-1.482398 -0.01957,-6.26186 -3.84086,-10.657062 -3.821292,-4.395203 -8.2940882,-6.743914 -9.9991242,-5.261516 -1.705035,1.482398 -9.34e-4,6.238278 3.8203572,10.63348 z"
style="color:#000000;fill:url(#radialGradient3802);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:1.79201269;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" />
<path
style="color:#000000;fill:url(#radialGradient3806);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:1.79201269;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 37.963989,41.956422 c -4.04815,4.187189 -6.022841,8.868868 -4.398501,10.439271 1.624341,1.570404 6.236692,-0.561201 10.284843,-4.748388 4.048151,-4.187189 6.001122,-8.846401 4.376781,-10.416805 -1.624341,-1.570403 -6.214972,0.538734 -10.263123,4.725922 z"
id="path3804"
inkscape:connector-curvature="0" />
<path
style="color:#000000;fill:url(#radialGradient3692-8);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:1.79201269;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 20.539027,17.238445 c 1.314216,-1.574289 4.22041,-2.585994 7.853076,-0.914907 4.090657,-1.80613 6.034549,-0.36085 6.813284,0.886441"
id="path3816"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="color:#000000;fill:url(#radialGradient3692-5);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:1.79201269;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 28.284052,15.994185 0,3.090909"
id="path3838"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path3858"
d="m 20.438026,48.752608 c -2.049875,0.05964 -4.733867,-1.445586 -5.890816,-5.273153 -4.063964,-1.865413 -4.270484,-4.278896 -3.852854,-5.688771"
style="color:#000000;fill:none;stroke:#7b5600;stroke-width:1.79201269;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" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3860"
d="m 14.37225,43.778682 2.314182,-2.048969"
style="color:#000000;fill:none;stroke:#7b5600;stroke-width:1.79201269;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" />
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path3866"
d="m 45.902939,37.43545 c 0.0408,2.050338 -1.489017,4.720387 -5.327051,5.842121 -1.902672,4.046656 -4.31795,4.230993 -5.723929,3.800429"
style="color:#000000;fill:none;stroke:#7b5600;stroke-width:1.79201269;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"
inkscape:transform-center-y="-0.61340679" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3868"
d="M 40.873495,43.455274 38.845873,41.122365"
style="color:#000000;fill:none;stroke:#7b5600;stroke-width:1.79201269;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"
inkscape:transform-center-x="0.51816164"
inkscape:transform-center-y="-0.66146961" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,290 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="1.1">
<context>
<name>Gui::Dialog::DlgSettingsOpenSCAD</name>
<message>
<location filename="openscadprefs-base.ui" line="14"/>
<source>General settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="26"/>
<source>General OpenSCAD Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="34"/>
<source>OpenSCAD executable</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="47"/>
<source>The path to the OpenSCAD executeable</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="65"/>
<source>OpenSCAD import</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="73"/>
<source>If this is checked, Features will claim thier children in the tree view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="76"/>
<source>Use ViewProvider in Tree View</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="93"/>
<source>If this is checked, Multmatrix Object will be Parametric</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="96"/>
<source>Use Multmatrix Feature</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="136"/>
<source>The maximum number of faces of a polygon, prism or frustum. If fn is greater than this value the object is considered to be a circular. Set to 0 for no limit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="116"/>
<source>Maximum number of faces for polygons (fn)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="159"/>
<source>Debug: Register filetype to prototype importer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="180"/>
<source>OpenSCAD export</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="188"/>
<source>maximum fragment size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="218"/>
<source>minimum angle for a fragment</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="211"/>
<source>angular (fa)</source>
<translation type="unfinished"></translation>
</message>
<message encoding="UTF-8">
<location filename="openscadprefs-base.ui" line="221"/>
<source>°</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="275"/>
<source>minimum size of a fragment</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="253"/>
<source>size (fs)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="281"/>
<source>mm</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="307"/>
<source>convexity</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="344"/>
<source>Mesh fallback</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="364"/>
<source>Maxium Length</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="367"/>
<source>MaxLength</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="374"/>
<source>Maximum Length</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="406"/>
<source>Maximum Area</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="399"/>
<source>maxArea</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="450"/>
<source>Local Length</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="453"/>
<source>localLen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="482"/>
<source>Deflection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="485"/>
<source>deflection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="openscadprefs-base.ui" line="492"/>
<source>Triangulation settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD</name>
<message>
<location filename="OpenSCADCommands.py" line="44"/>
<source>Convert Edges to Faces</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="90"/>
<source>Please select 3 objects first</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="importCSG.py" line="330"/>
<source>Unsupported Function</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="importCSG.py" line="330"/>
<source>Press OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="importCSG.py" line="940"/>
<source>Projection Not yet Coded waiting for Peter Li</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="importCSG.py" line="940"/>
<source> Press OK</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="186"/>
<source>Running OpenSCAD failed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD_AddOpenSCADElement</name>
<message>
<location filename="OpenSCADCommands.py" line="194"/>
<source>Add OpenSCAD Element...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="196"/>
<source>Add an OpenSCAD element by entering OpenSCAD code and executing the OpenSCAD binary</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD_ColorCodeShape</name>
<message>
<location filename="OpenSCADCommands.py" line="24"/>
<source>Color Shapes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="26"/>
<source>Color Shapes by validity and type</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD_Edgestofaces</name>
<message>
<location filename="OpenSCADCommands.py" line="42"/>
<source>Convert Edges To Faces</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD_ExpandPlacements</name>
<message>
<location filename="OpenSCADCommands.py" line="77"/>
<source>Expand Placements</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="79"/>
<source>Expand all placements downwards the FeatureTree</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD_RefineShapeFeature</name>
<message>
<location filename="OpenSCADCommands.py" line="61"/>
<source>Refine Shape Feature</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="63"/>
<source>Create Refine Shape Feature</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD_RemoveSubtree</name>
<message>
<location filename="OpenSCADCommands.py" line="124"/>
<source>Remove Objects and their Children</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="126"/>
<source>Removes the selected objects and all children that are not referenced from other objects</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OpenSCAD_ReplaceObject</name>
<message>
<location filename="OpenSCADCommands.py" line="94"/>
<source>Replace Object</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="OpenSCADCommands.py" line="96"/>
<source>Replace an object in the Feature Tree. Please select old, new and parent object</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -148,26 +148,6 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="Gui::PrefCheckBox" name="gui::prefcheckboxmultmatrixfeature">
<property name="toolTip">
<string>Debug: Register filetype to prototype importer</string>
</property>
<property name="text">
<string>Debug: Register filetype to prototype importer</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>debugRegisterPrototype</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/OpenSCAD</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3"/>
</item>

View File

@ -1,5 +0,0 @@
Makefiles (get the python files included)
Copyright notices (Ply is BSD, everything Keith did is GPL, most of the stuff from freecad is LGPL)
Make filenames unique, e.g. prepepend module name
Add a gui command for the Refine Shape feature.
Add a gui command for subtractfaces2.

View File

@ -32,6 +32,14 @@ __author__ = "Keith Sloan <keith@sloan-home.co.uk>"
__url__ = ["http://www.sloan-home.co.uk/ImportCSG"]
import FreeCAD, os, sys
if FreeCAD.GuiUp:
import FreeCADGui
gui = True
else:
print "FreeCAD Gui not present."
gui = False
import ply.lex as lex
import ply.yacc as yacc
import Part
@ -51,6 +59,10 @@ from tokrules import tokens
#Globals
dxfcache = {}
def translate(context,text):
"convenience function for Qt translator"
return QtGui.QApplication.translate(context, text, None, \
QtGui.QApplication.UnicodeUTF8)
def open(filename):
"called when freecad opens a file."
@ -101,7 +113,6 @@ def processcsg(filename):
# Build the parser
print 'Load Parser'
# No debug out otherwise Linux has protection exception
#parser = yacc.yacc(debug=0)
parser = yacc.yacc(debug=0)
print 'Parser Loaded'
# Give the lexer some input
@ -117,13 +128,13 @@ def processcsg(filename):
print result
FreeCAD.Console.PrintMessage('End processing CSG file')
doc.recompute()
#import colorcodeshapes
#colorcodeshapes.colorcodeshapes(doc.Objects)
def p_block_list_(p):
'''
block_list : statement
| block_list statement
block_list : statement
| block_list statement
| statementwithmod
| block_list statementwithmod
'''
print "Block List"
print p[1]
@ -133,11 +144,20 @@ def p_block_list_(p):
else :
p[0] = p[1]
print "End Block List"
def p_render_action(p):
'render_action : render LPAREN keywordargument_list RPAREN OBRACE block_list EBRACE'
print "Render (ignored)"
p[0] = p[6]
def p_group_action1(p):
'group_action1 : group LPAREN RPAREN OBRACE block_list EBRACE'
print "Group"
p[0] = p[5]
# Test if need for implicit fuse
if (len(p[5]) > 1) :
p[0] = [fuse(p[5],"Group")]
else :
p[0] = p[5]
def p_group_action2(p) :
'group_action2 : group LPAREN RPAREN SEMICOL'
@ -166,10 +186,31 @@ def p_statement(p):
| group_action1
| group_action2
| color_action
| render_action
| not_supported
'''
p[0] = p[1]
def p_anymodifier(p):
'''anymodifier : MODIFIERBACK
| MODIFIERDEBUG
| MODIFIERROOT
| MODIFIERDISABLE
'''
#just return the plain modifier for now
#has to be changed when the modifiers are inplemented
#please note that disabled objects usualy are stript of the CSG ouput during compilation
p[0] = p[1]
def p_statementwithmod(p):
'''statementwithmod : anymodifier statement'''
#ignore the modifiers but add them to the label
modifier = p[1]
obj = p[2]
if hasattr(obj,'Label'):
obj.Label = modifier + obj.Label
p[0] = obj
def p_part(p):
'''
part : sphere_action
@ -276,7 +317,6 @@ def p_operation(p):
| union_action
| rotate_extrude_action
| linear_extrude_with_twist
| linear_extrude_action2
| rotate_extrude_file
| import_file1
| projection_action
@ -285,22 +325,40 @@ def p_operation(p):
def p_not_supported(p):
'''
not_supported : hull
| minkowski
not_supported : hull LPAREN RPAREN OBRACE block_list EBRACE
| minkowski LPAREN keywordargument_list RPAREN OBRACE block_list EBRACE
| glide LPAREN RPAREN OBRACE block_list EBRACE
'''
from PyQt4 import QtGui
QtGui.QMessageBox.critical(None, "Unsupported Function : "+p[1], "Press OK")
if gui:
from PyQt4 import QtGui
QtGui.QMessageBox.critical(None, unicode(translate('OpenSCAD',"Unsupported Function"))+" : "+p[1],unicode(translate('OpenSCAD',"Press OK")))
def p_size_vector(p):
'size_vector : OSQUARE NUMBER COMMA NUMBER COMMA NUMBER ESQUARE'
print "size vector"
p[0] = [p[2],p[4],p[6]]
def p_assign(p):
'assign : ID EQ NUMBER'
print "Assignment"
print p[1] + ' : ' + p[3]
p[0] = p[3]
def p_keywordargument(p):
'''keywordargument : ID EQ boolean
| ID EQ NUMBER
| ID EQ size_vector
| ID EQ vector
| ID EQ 2d_point
| ID EQ stripped_string
'''
p[0] = (p[1],p[3])
print p[0]
def p_keywordargument_list(p):
'''
keywordargument_list : keywordargument
| keywordargument_list COMMA keywordargument
'''
if len(p) == 2:
p[0] = {p[1][0] : p[1][1]}
else:
p[1][p[3][0]] = p[3][1]
p[0]=p[1]
def p_color_action(p):
'color_action : color LPAREN vector RPAREN OBRACE block_list EBRACE'
@ -308,34 +366,39 @@ def p_color_action(p):
print "Color"
color = tuple([float(f) for f in p[3][:3]]) #RGB
transp = 100 - int(math.floor(100*float(p[3][3]))) #Alpha
for obj in p[6]:
obj.ViewObject.ShapeColor =color
obj.ViewObject.Transparency = transp
if gui:
for obj in p[6]:
obj.ViewObject.ShapeColor =color
obj.ViewObject.Transparency = transp
p[0] = p[6]
# Error rule for syntax errors
def p_error(p):
print "Syntax error in input!"
print p
def fuse(list,name):
def fuse(lst,name):
global doc
print "Fuse"
print list
print lst
if len(lst) == 1:
return lst[0]
# Is this Multi Fuse
if ( len(list) > 2):
elif len(lst) > 2:
print "Multi Fuse"
myfuse = doc.addObject('Part::MultiFuse',name)
myfuse.Shapes = list
for subobj in myfuse.Shapes:
subobj.ViewObject.hide()
else :
myfuse.Shapes = lst
if gui:
for subobj in myfuse.Shapes:
subobj.ViewObject.hide()
else:
print "Single Fuse"
myfuse = doc.addObject('Part::Fuse',name)
myfuse.Base = list[0]
myfuse.Tool = list[1]
myfuse.Base.ViewObject.hide()
myfuse.Tool.ViewObject.hide()
myfuse.Base = lst[0]
myfuse.Tool = lst[1]
if gui:
myfuse.Base.ViewObject.hide()
myfuse.Tool.ViewObject.hide()
return(myfuse)
def p_union_action(p):
@ -352,40 +415,45 @@ def p_difference_action(p):
print "difference"
print len(p[5])
print p[5]
mycut = doc.addObject('Part::Cut',p[1])
# Cut using Fuse
mycut.Base = p[5][0]
# Can only Cut two objects do we need to fuse extras
if (len(p[5]) > 2 ):
print "Need to Fuse Extra First"
mycut.Tool = fuse(p[5][1:],'union')
else :
mycut.Tool = p[5][1]
mycut.Base.ViewObject.hide()
mycut.Tool.ViewObject.hide()
print "Push Resulting Cut"
p[0] = [mycut]
if (len(p[5]) == 1 ): #single object
p[0] = p[5]
else:
# Cut using Fuse
# Can only Cut two objects do we need to fuse extras
if (len(p[5]) > 2 ):
print "Need to Fuse Extra First"
mycut.Tool = fuse(p[5][1:],'union')
else :
mycut.Tool = p[5][1]
if gui:
mycut.Base.ViewObject.hide()
mycut.Tool.ViewObject.hide()
print "Push Resulting Cut"
p[0] = [mycut]
print "End Cut"
def p_intersection_action(p):
'intersection_action : intersection LPAREN RPAREN OBRACE block_list EBRACE'
print "intersection"
# Is this Multi Common
if (len(p[5]) > 2):
if (len(p[5]) > 2):
print "Multi Common"
mycommon = doc.addObject('Part::MultiCommon',p[1])
mycommon.Shapes = p[5]
for subobj in mycommon.Shapes:
subobj.ViewObject.hide()
if gui:
for subobj in mycommon.Shapes:
subobj.ViewObject.hide()
else :
print "Single Common"
mycommon = doc.addObject('Part::Common',p[1])
mycommon.Base = p[5][0]
mycommon.Tool = p[5][1]
mycommon.Base.ViewObject.hide()
mycommon.Tool.ViewObject.hide()
if gui:
mycommon.Base.ViewObject.hide()
mycommon.Tool.ViewObject.hide()
p[0] = [mycommon]
print "End Intersection"
@ -397,34 +465,35 @@ def process_rotate_extrude(obj):
myrev.Base = (0.00,0.00,0.00)
myrev.Angle = 360.00
myrev.Placement=FreeCAD.Placement(FreeCAD.Vector(),FreeCAD.Rotation(0,0,90))
obj.ViewObject.hide()
if gui:
obj.ViewObject.hide()
newobj=doc.addObject("Part::FeaturePython",'RefineRotateExtrude')
RefineShape(newobj,myrev)
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
if gui:
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
myrev.ViewObject.hide()
return(newobj)
def p_rotate_extrude_action(p):
'rotate_extrude_action : rotate_extrude LPAREN assign COMMA assign COMMA assign COMMA assign RPAREN OBRACE block_list EBRACE'
'rotate_extrude_action : rotate_extrude LPAREN keywordargument_list RPAREN OBRACE block_list EBRACE'
print "Rotate Extrude"
if (len(p[12]) > 1) :
part = fuse(p[12],"Rotate Extrude Union")
if (len(p[6]) > 1) :
part = fuse(p[6],"Rotate Extrude Union")
else :
part = p[12][0]
part = p[6][0]
p[0] = [process_rotate_extrude(part)]
print "End Rotate Extrude"
def p_rotate_extrude_file(p):
'rotate_extrude_file : rotate_extrude LPAREN file EQ stripped_string COMMA layer EQ stripped_string COMMA origin EQ 2d_point COMMA assign \
COMMA assign COMMA assign COMMA assign COMMA assign RPAREN SEMICOL'
'rotate_extrude_file : rotate_extrude LPAREN keywordargument_list RPAREN SEMICOL'
print "Rotate Extrude File"
filen,ext =p[5] .rsplit('.',1)
obj = process_import_file(filen,ext,p[9])
filen,ext =p[3]['file'] .rsplit('.',1)
obj = process_import_file(filen,ext,p[3]['layer'])
p[0] = [process_rotate_extrude(obj)]
print "End Rotate Extrude File"
@ -437,71 +506,57 @@ def process_linear_extrude(obj,h) :
mylinear.Solid = True
except:
a = 1 # Any old null statement
obj.ViewObject.hide()
if gui:
obj.ViewObject.hide()
newobj=doc.addObject("Part::FeaturePython",'RefineLinearExtrude')
RefineShape(newobj,mylinear)
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
mylinear.ViewObject.hide()
if gui:
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
mylinear.ViewObject.hide()
return(newobj)
def process_linear_extrude_with_twist(base,height,twist) :
newobj=doc.addObject("Part::FeaturePython",'twist_extrude')
Twist(newobj,base,height,-twist) #base is an FreeCAD Object, heigth and twist are floats
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
if gui:
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
#import ViewProviderTree from OpenSCADFeatures
#ViewProviderTree(obj.ViewObject)
return(newobj)
def p_linear_extrude_with_twist(p):
'linear_extrude_with_twist : linear_extrude LPAREN assign COMMA center EQ boolean COMMA assign COMMA assign COMMA assign COMMA \
assign COMMA assign COMMA assign RPAREN OBRACE block_list EBRACE'
'linear_extrude_with_twist : linear_extrude LPAREN keywordargument_list RPAREN OBRACE block_list EBRACE'
print "Linear Extrude With Twist"
h = float(p[3])
print "Twist : "+p[11]
t = float(p[11])
s = int(p[13])
if (len(p[22]) > 1) :
obj = fuse(p[22],"Linear Extrude Union")
h = float(p[3]['height'])
print "Twist : ",p[3]
t = float(p[3]['twist'])
if (len(p[6]) > 1) :
obj = fuse(p[6],"Linear Extrude Union")
else :
obj = p[22][0]
obj = p[6][0]
if t:
p[0] = [process_linear_extrude_with_twist(obj,h,t)]
else:
p[0] = [process_linear_extrude(obj,h)]
if p[7]=='true' :
if p[3]['center']=='true' :
center(obj,0,0,h)
print "End Linear Extrude with twist"
def p_linear_extrude_action2(p):
'linear_extrude_action2 : linear_extrude LPAREN assign COMMA center EQ boolean COMMA assign COMMA assign COMMA assign COMMA \
assign RPAREN OBRACE block_list EBRACE'
print "Linear Extrude 2"
h = float(p[3])
if (len(p[18]) > 1) :
obj = fuse(p[18],"Linear Extrude Union")
else :
obj = p[18][0]
p[0] = [process_linear_extrude(obj,h)]
if p[7]=='true' :
center(obj,0,0,h)
print "End Linear Extrude 2"
def p_import_file1(p):
'import_file1 : import LPAREN file EQ stripped_string COMMA layer EQ stripped_string COMMA origin EQ 2d_point COMMA assign COMMA assign COMMA \
assign COMMA assign COMMA assign RPAREN SEMICOL'
'import_file1 : import LPAREN keywordargument_list RPAREN SEMICOL'
print "Import File"
filen,ext =p[5] .rsplit('.',1)
p[0] = [process_import_file(filen,ext,p[9])]
filen,ext =p[3]['file'].rsplit('.',1)
p[0] = [process_import_file(filen,ext,p[3]['layer'])]
print "End Import File"
def process_import_file(fname,ext,layer):
@ -522,7 +577,8 @@ def process_mesh_file(fname,ext):
if not mesh1:
Mesh.insert(filename)
mesh1=doc.getObject(fname)
mesh1.ViewObject.hide()
if gui:
mesh1.ViewObject.hide()
sh=Part.Shape()
sh.makeShapeFromMesh(mesh1.Mesh.Topology,0.1)
solid = Part.Solid(sh)
@ -566,9 +622,10 @@ def processDXF(fname,layer):
layers = importDXF.processdxf(doc,filename) or importDXF.layers
dxfcache[id(doc)] = layers[:]
for l in layers:
for o in l.Group:
o.ViewObject.hide()
l.ViewObject.hide()
if gui:
for o in l.Group:
o.ViewObject.hide()
l.ViewObject.hide()
groupobj=[go for go in layers if (not layer) or go.Label == layer]
edges=[]
if not groupobj:
@ -628,13 +685,14 @@ def p_multmatrix_action(p):
from OpenSCADFeatures import MatrixTransform
new_part=doc.addObject("Part::FeaturePython",'Matrix Deformation')
MatrixTransform(new_part,transform_matrix,part)
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(new_part.ViewObject)
else:
new_part.ViewObject.Proxy = 0
part.ViewObject.hide()
if gui:
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(new_part.ViewObject)
else:
new_part.ViewObject.Proxy = 0
part.ViewObject.hide()
else :
print "Transform Geometry"
# Need to recompute to stop transformGeometry causing a crash
@ -642,13 +700,15 @@ def p_multmatrix_action(p):
new_part = doc.addObject("Part::Feature","Matrix Deformation")
# new_part.Shape = part.Base.Shape.transformGeometry(transform_matrix)
new_part.Shape = part.Shape.transformGeometry(transform_matrix)
part.ViewObject.hide()
if gui:
part.ViewObject.hide()
if False :
# Does not fix problemfile or beltTighener although later is closer
newobj=doc.addObject("Part::FeaturePython",'RefineMultMatrix')
RefineShape(newobj,new_part)
newobj.ViewObject.Proxy = 0
new_part.ViewObject.hide()
if gui:
newobj.ViewObject.Proxy = 0
new_part.ViewObject.hide()
p[0] = [newobj]
else :
p[0] = [new_part]
@ -670,9 +730,9 @@ def center(obj,x,y,z):
FreeCAD.Rotation(0,0,0,1))
def p_sphere_action(p):
'sphere_action : sphere LPAREN assign COMMA assign COMMA assign COMMA assign RPAREN SEMICOL'
print "Sphere : "+p[9]
r = float(p[9])
'sphere_action : sphere LPAREN keywordargument_list RPAREN SEMICOL'
print "Sphere : ",p[3]
r = float(p[3]['r'])
mysphere = doc.addObject("Part::Sphere",p[1])
mysphere.Radius = r
print "Push Sphere"
@ -696,19 +756,20 @@ def myPolygon(n,r1):
return(polygon)
def p_cylinder_action(p):
'cylinder_action : cylinder LPAREN assign COMMA assign COMMA assign COMMA assign COMMA assign COMMA assign COMMA center EQ boolean RPAREN SEMICOL'
'cylinder_action : cylinder LPAREN keywordargument_list RPAREN SEMICOL'
print "Cylinder"
h = float(p[9])
r1 = float(p[11])
r2 = float(p[13])
print p[9] + ' : ' + p[11] + ' : ' + p[13]
if ( r1 == r2 ):
tocenter = p[3]['center']
h = float(p[3]['h'])
r1 = float(p[3]['r1'])
r2 = float(p[3]['r2'])
n = int(p[3]['$fn'])
print p[3]
if ( r1 == r2 ):
print "Make Cylinder"
n = int(p[3])
fnmax = FreeCAD.ParamGet(\
"User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetInt('useMaxFN')
if n < 3 or fnmax != 0 and n > fnmax:
if n < 3 or fnmax != 0 and n >= fnmax:
mycyl=doc.addObject("Part::Cylinder",p[1])
mycyl.Height = h
mycyl.Radius = r1
@ -728,76 +789,76 @@ def p_cylinder_action(p):
else :
pass
mycyl.Base.ViewObject.hide()
if gui:
mycyl.Base.ViewObject.hide()
# mycyl.Solid = True
else:
print "Make Cone"
mycyl=doc.addObject("Part::Cone",p[1])
mycyl.Height = h
mycyl.Radius1 = r1
mycyl.Radius2 = r2
print "Center = "+str(p[17])
if p[17]=='true' :
center(mycyl,0,0,h)
print "Center = ",center
if tocenter=='true' :
center(mycyl,0,0,h)
if False :
# Does not fix problemfile or beltTighener although later is closer
newobj=doc.addObject("Part::FeaturePython",'RefineCylinder')
RefineShape(newobj,mycyl)
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
mycyl.ViewObject.hide()
if gui:
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetBool('useViewProviderTree'):
from OpenSCADFeatures import ViewProviderTree
ViewProviderTree(newobj.ViewObject)
else:
newobj.ViewObject.Proxy = 0
mycyl.ViewObject.hide()
p[0] = [newobj]
else :
p[0] = [mycyl]
print "End Cylinder"
def p_cube_action(p):
'cube_action : cube LPAREN size EQ size_vector COMMA center EQ boolean RPAREN SEMICOL'
'cube_action : cube LPAREN keywordargument_list RPAREN SEMICOL'
global doc
l = float(p[5][0])
w = float(p[5][1])
h = float(p[5][2])
print "cube : "+p[5][0] + ' : ' + p[5][1] +' : '+ p[5][2]
l,w,h = [float(str1) for str1 in p[3]['size']]
print "cube : ",p[3]
mycube=doc.addObject('Part::Box',p[1])
mycube.Length=l
mycube.Width=w
mycube.Height=h
print "Center = "+str(p[9])
if p[9]=='true' :
center(mycube,l,w,h);
if p[3]['center']=='true' :
center(mycube,l,w,h);
p[0] = [mycube]
print "End Cube"
def p_circle_action(p) :
'circle_action : circle LPAREN assign COMMA assign COMMA assign COMMA assign RPAREN SEMICOL'
print "Circle : "+str(p[9])
r = float(p[9])
n = int(p[3])
'circle_action : circle LPAREN keywordargument_list RPAREN SEMICOL'
print "Circle : "+str(p[3])
r = float(p[3]['r'])
n = int(p[3]['$fn'])
fnmax = FreeCAD.ParamGet(\
"User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
GetInt('useMaxFN')
GetInt('useMaxFN',50)
# Alter Max polygon to control if polygons are circles or polygons
# in the modules preferences
import Draft
if n == 0 or fnmax != 0 and n > fnmax:
if n == 0 or fnmax != 0 and n >= fnmax:
mycircle = Draft.makeCircle(r)
#mycircle = doc.addObject('Part::Circle',p[1])
#mycircle.Radius = r
else :
mycircle = Draft.makePolygon(n,r)
print "Push Circle"
print "Push Circle"
p[0] = [mycircle]
def p_square_action(p) :
'square_action : square LPAREN size EQ 2d_point COMMA center EQ boolean RPAREN SEMICOL'
'square_action : square LPAREN keywordargument_list RPAREN SEMICOL'
print "Square"
x = float(p[5][0])
y = float(p[5][1])
size = p[3]['size']
x = float(size[0])
y = float(size[1])
mysquare = doc.addObject('Part::Plane',p[1])
mysquare.Length=x
mysquare.Width=y
@ -815,7 +876,7 @@ def convert_points_list_to_vector(l):
def p_polygon_action_nopath(p) :
'polygon_action_nopath : polygon LPAREN points EQ OSQUARE points_list_2d ESQUARE COMMA paths EQ undef COMMA assign RPAREN SEMICOL'
'polygon_action_nopath : polygon LPAREN points EQ OSQUARE points_list_2d ESQUARE COMMA paths EQ undef COMMA keywordargument_list RPAREN SEMICOL'
print "Polygon"
print p[6]
v = convert_points_list_to_vector(p[6])
@ -826,10 +887,10 @@ def p_polygon_action_nopath(p) :
parts = Part.makePolygon(v)
print "update object"
mypolygon.Shape = Part.Face(parts)
p[0] = [mypolygon]
p[0] = [mypolygon]
def p_polygon_action_plus_path(p) :
'polygon_action_plus_path : polygon LPAREN points EQ OSQUARE points_list_2d ESQUARE COMMA paths EQ OSQUARE path_set ESQUARE COMMA assign RPAREN SEMICOL'
'polygon_action_plus_path : polygon LPAREN points EQ OSQUARE points_list_2d ESQUARE COMMA paths EQ OSQUARE path_set ESQUARE COMMA keywordargument_list RPAREN SEMICOL'
print "Polygon with Path"
print p[6]
v = convert_points_list_to_vector(p[6])
@ -858,7 +919,7 @@ def make_face(v1,v2,v3):
return face
def p_polyhedron_action(p) :
'polyhedron_action : polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA triangles EQ OSQUARE points_list_3d ESQUARE COMMA assign RPAREN SEMICOL'
'polyhedron_action : polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA triangles EQ OSQUARE points_list_3d ESQUARE COMMA keywordargument_list RPAREN SEMICOL'
print "Polyhedron Points"
v = []
for i in p[6] :
@ -875,11 +936,12 @@ def p_polyhedron_action(p) :
faces_list.append(f)
shell=Part.makeShell(faces_list)
mypolyhed.Shape=Part.Solid(shell)
p[0] = [mypolyhed]
p[0] = [mypolyhed]
def p_projection_action(p) :
'projection_action : projection LPAREN cut EQ boolean COMMA assign RPAREN OBRACE block_list EBRACE'
'projection_action : projection LPAREN keywordargument_list RPAREN OBRACE block_list EBRACE'
print 'Projection'
from PyQt4 import QtGui
QtGui.QMessageBox.critical(None, "Projection Not yet Coded waiting for Peter Li"," Press OK")
if gui:
from PyQt4 import QtGui
QtGui.QMessageBox.critical(None, unicode(translate('OpenSCAD',"Projection Not yet Coded waiting for Peter Li")),unicode(translate('OpenSCAD'," Press OK")))

View File

@ -49,10 +49,13 @@ Version History
0.05c - Fix for polygon with path - Changes to Polygon and polyhdron - parse projection
0.05d - Fix for implicit fuse for groups
global max_polygon parameter to control cylinder or prism
There appear to be problems with some files and these maybe as a result of bugs in FreeCAD that corrupt
the model. If you find problem files please email them to keith@sloan-home.co.uk
Thanks to shoogen and Peter Li for their advice, support and expertise.
Keith Sloan
keith@sloan-home.co.uk
keith@sloan-home.co.uk

View File

@ -409,6 +409,8 @@ class Node:
raise(NotImplementedError)
if obj: #handle origin and scale
if scale is not None and scale !=1:
if origin is not None and any([c != 0 for c in origin]):
raise(NotImplementedError)# order of transformations unkown
child = obj
m1=FreeCAD.Matrix()
m1.scale(scale,scale,scale)
@ -416,7 +418,7 @@ class Node:
MatrixTransform(obj,m1,child) #This object is not mutable from the GUI
ViewProviderTree(obj.ViewObject)
elif origin is not None and any([c != 0 for c in origin]):
placement=FreeCAD.Placement(FreeCAD.Vector(*origin),FreeCAD.Rotation())
placement=FreeCAD.Placement(FreeCAD.Vector(*[-c for c in origin]),FreeCAD.Rotation())
obj.Placement=placement.multiply(obj.Placement)
else:
FreeCAD.Console.ErrorMessage('Import of %s failed\n' % (filename))
@ -476,12 +478,17 @@ class Node:
else:
raise(NotImplementedError)
elif namel == 'surface':
import os
scadstr = 'surface(file = "%s", center = %s );' % \
(self.arguments['file'], 'true' if self.arguments['center'] else 'false')
docname=os.path.split(self.arguments['file'])[1]
objname,extension = docname.split('.',1)
obj = openscadmesh(doc,scadstr,objname)
obj = doc.addObject("Part::Feature",namel) #include filename?
obj.Shape,xoff,yoff=makeSurfaceVolume(self.arguments['file'])
if self.arguments['center']:
center(obj,xoff,yoff,0.0)
return obj
#import os
#scadstr = 'surface(file = "%s", center = %s );' % \
# (self.arguments['file'], 'true' if self.arguments['center'] else 'false')
#docname=os.path.split(self.arguments['file'])[1]
#objname,extension = docname.split('.',1)
#obj = openscadmesh(doc,scadstr,objname)
elif namel in ['glide','hull']:
raise(NotImplementedError)

View File

@ -31,14 +31,12 @@ reserved = (
'sphere',
'cylinder',
'cube',
'size',
'multmatrix',
'intersection',
'difference',
'union',
'rotate_extrude',
'linear_extrude',
'center',
'true',
'false',
'circle',
@ -59,9 +57,6 @@ reserved = (
'import_stl',
'import_dxf',
'import',
'origin',
'layer',
'file',
'color',
'cut',
)
@ -81,7 +76,11 @@ tokens = reserved + (
'EQ',
'STRING',
'ID',
'DOT'
'DOT',
'MODIFIERBACK',
'MODIFIERDEBUG',
'MODIFIERROOT',
'MODIFIERDISABLE'
)
# Regular expression rules for simple tokens
@ -99,6 +98,10 @@ t_EQ = r'='
t_DOT = r'\.'
t_STRING = r'"[^"]*"'
#t_STRING = r'["]+[a-zA-Z.]+["]+'
t_MODIFIERBACK = r'%'
t_MODIFIERDEBUG = r'\#'
t_MODIFIERROOT = r'!'
t_MODIFIERDISABLE = r'\*'
# Deal with Reserved words
reserved_map = { }
for r in reserved:

View File

@ -53,6 +53,7 @@ DirFilter = ["^Attic$",
"src/Mod/TemplatePyMod",
"src/Mod/Draft",
"src/Mod/Arch",
"src/Mod/OpenSCAD",
"src/Mod/Start"]
# folders that need a special pylupdate command
@ -60,6 +61,8 @@ PyCommands = [["src/Mod/Draft",
"pylupdate *.py draftlibs/*.py Resources/ui/*.ui -ts Resources/translations/Draft.ts"],
["src/Mod/Arch",
"pylupdate *.py Resources/ui/*.ui -ts Resources/translations/Arch.ts"],
["src/Mod/OpenSCAD",
"pylupdate *.py Resources/ui/*.ui -ts Resources/translations/OpenSCAD.ts"],
["src/Mod/Start",
"pylupdate StartPage/*.py -ts Gui/Resources/translations/StartPage.ts"]]

View File

@ -35,7 +35,6 @@
<File Id="OpenSCADCommandspy" Name="OpenSCADCommands.py" DiskId="1" />
<File Id="OpenSCADFeaturespy" Name="OpenSCADFeatures.py" DiskId="1" />
<File Id="OpenSCADUtilspy" Name="OpenSCADUtils.py" DiskId="1" />
<File Id="prototypepy" Name="prototype.py" DiskId="1" />
<File Id="replaceobjpy" Name="replaceobj.py" DiskId="1" />
<File Id="tokrulespy" Name="tokrules.py" DiskId="1" />
</Component>