–SolidPython 学习笔记1
参考Parkinbotshortcuts.scad做了部分修改使得代码更为简洁易读
以下是对solidpython的readme的学习笔记(其中的部分code进行了简化):
–好像作者是在这个链接中得到启发,下面是个例子:
from solid import *
d = difference()(
Cu(10),
Sp(15)
)
print(scad_render(d))
这个改变似乎没啥意思呀,继续往下看:
from solid import *
from solid.utils import *
import viewscad
import os
import sys
r = viewscad.Renderer()
SEGMENTS = 60
d = Cu(5) + Tx(5)(Sp(5)) - Cy(2,6)
r.render(d)
这是OpenSCAD代码:
difference(){ union(){ cube(5); translate( [5, 0,0]){ sphere(5); } } cylinder(r=2, h=6); }
比原来的编码简单易读,好聪明的方法!
当然了,还可以应用Python实现更多的可能:
> 内置字典类型
> 可变,可切片的列表和字符串类型
> 递归
> 外部库(图像!3D几何!网页抓取!...)
直接pip:
pip install solidpython
下载(或者直接克隆)并解压,并在解压目录内安装:
python setup.py install
Ci= circle #圆
Sq= square #方
Sp= sphere #(radius | d=diameter) 球
Cu= cube #(size, center) or cube([width,depth,height], center) 立方
Cy= cylinder #(h,r|d,center) or cylinder(h,r1|d1,r2|d2,center) 锥柱
Mi= mirror #镜像
Of = offset # 偏移
C= color #色
Le= linear_extrude #(height,center,convexity,twist,slices,scale) 线拖
Re= rotate_extrude #(angle,convexity) 旋拖
dxf_Le= dxf_linear_extrude #dxf拖
Pr= projection #(cut) 投影
Sf= surface #(file = “….dat”,center,convexity)
deb= debug ##
bac= background # !
roo= root # %
dis= disable # *
# 旋转和移动
def Tx(x):
return translate([x,0,0])def Ty(y):
return translate([0,y,0])def Tz(z):
return translate([0,0,z])def Rx(x=90):
return rotate([x,0,0])def Ry(y=90):
return rotate([0,y,0])def Rz(z=90):
return rotate([0,0,z])
from solid import *
from solid.utils import * # Not required, but the utils module is useful--非必须但是很有用
import os
import sys
use("/path/to/scadfile.scad")
include("/path/to/scadfile.scad")
use(r"C:\Program Files\OpenSCAD\libraries\shortcuts.scad")# 为啥出错呀?
use (r"C:\Users\Administrator\Documents\3dguide\testd.scad")这个就行!!!
d = Cu(10) - Sp(15)
scad_render_to_file(d,r"C:\Users\Administrator\Documents\3dguide\testd.scad")
scad_render(py_scad_obj) 返回OpenScad代码
scad_render_to_file(py_scad_obj, filepath) 另存为.scad文件
d = Cu(10) - Sp(15)
scad_render_to_file(d,r"C:\Users\Administrator\Documents\3dguide\testd.scad")
这个命令还可以在OpenSCAD IDE中加载并预览编辑的图像(需要设置)
还可以调用openscad的命令行格式可以直接导出为stl文件
可以用如下代码打开例子的目录:
import os, solid; print(os.path.dirname(solid.__file__) + '\examples')#例子在这里
原链接:here
solid/examples/solidpython_template.py
这是模板文件
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division#1.在python2 中导入未来的支持的语言特征中division(精确除法),即from __future__ import division ,当我们在程序中没有导入该特征时,"/"操作符执行的只能是整除,也就是取整数,只有当我们导入division(精确算法)以后,"/"执行的才是精确算法。2.但是在python3中已经支持了精确算法,所以无需再导入division(精确算法):
import os
import sys
# Assumes SolidPython is in site-packages or elsewhwere in sys.path
from solid import *
from solid.utils import *
SEGMENTS = 48
def assembly():
# Your code here!在这里输入代码?这是个assembly函数还不懂啥意思以后在研究吧
a = union()
return a
if __name__ == '__main__':
a = assembly()
scad_render_to_file(a, file_header='$fn = %s;' % SEGMENTS, include_orig_code=True)
c = Cy(r=10, h=5) + Cy(r=2, h=30)
r.render(c)
c = Cy(r=10, h=5)
c -= Cy(r=2, h=30)
r.render(c)
outer = Cy(5, 30)
inner = Cy(3,35)
pipe_a = outer - hole()(inner)
r.render(pipe_a)
这里提到了一个 part() 函数,以利于组装以后再看吧
See solid/examples/animation_example.py 动画模块。。。以后再看吧
solid/utils.py.
比如:
Directions: (up, down, left, right, forward, back) for arranging things:–作者自定义的方向函数,我做了了一些修改:
b = Tx(5)(Cu(5))
r.render(b)
outer = Cy(5, 30)
inner = Cy(3,35)
pipe_a = outer - hole()(inner)
r.render(pipe_a)
这里solid/examples/hole_example.py有一个示范文件,分段分析一下。。。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
import os
import sys
# Assumes SolidPython is in site-packages or elsewhwere in sys.path
from solid import *
from solid.utils import *
SEGMENTS = 120#相当于fn
def pipe_intersection_hole():
pipe_od = 12
pipe_id = 10
seg_length = 30
outer = Cy(r=pipe_od, h=seg_length, center=True)
inner = Cy(r=pipe_id, h=seg_length + 2, center=True)
# By declaring that the internal void of pipe_a should
# explicitly remain empty, the combination of both pipes
# is empty all the way through.
# -通过hole()声明负空间,这个管子的内部总是空的,即使将两个
# -交叉合并
# Any OpenSCAD / SolidPython object can be declared a hole(),
# and after that will always be empty
pipe_a = outer + hole()(inner)
# Note that "pipe_a = outer - hole()(inner)" would work identically;
# inner will always be subtracted now that it's a hole
pipe_b = Ry()(pipe_a)
return pipe_a + pipe_b
r.render(pipe_intersection_hole())
def pipe_intersection_no_hole():
pipe_od = 12
pipe_id = 10
seg_length = 30
outer = Cy(r=pipe_od, h=seg_length, center=True)
inner = Cy(r=pipe_id, h=seg_length + 2, center=True)
pipe_a = outer - inner
pipe_b = rotate(a=90, v=FORWARD_VEC)(pipe_a)
# pipe_a and pipe_b are both hollow, but because
# their central voids aren't explicitly holes,
# the union of both pipes has unwanted internal walls
# 没有用hole()就是这个结果
return pipe_a + pipe_b
r.render(pipe_intersection_no_hole())
- 当我们需要在hole()所形成的负空间里插入一个物体时,我们需要用到另一个函数part(),以消除负空间,看看下面这个例子:
def multipart_hole():
# It's good to be able to keep holes empty, but often we want to put
# things (bolts, etc.) in them. The way to do this is to declare the
# object containing the hole a "part". Then, the hole will remain
# empty no matter what you add to the 'part'. But if you put an object
# that is NOT part of the 'part' into the hole, it will still appear.
# On the left (not_part), here's what happens if we try to put an object
# into an explicit hole: the object gets erased by the hole.
# On the Tx (is_part), we mark the Cu-with-hole as a "part",
# and then insert the same 'bolt' Cy into it. The entire
# bolt rematins.
b = Cu(10, center=True)
c = Cy(r=2, h=12, center=True)
# A Cu with an explicit hole
not_part = b - hole()(c)
# Mark this Cu-with-hole as a separate part from the Cy
is_part = part()(not_part.copy())
# This fits in the holes
bolt = Cy(r=1.5, h=14, center=True) + Tz(8)(Cy(r=2.5, h=2.5, center=True))
# The section of the bolt inside not_part disappears. The section
# of the bolt inside is_part is still there.
a = not_part + bolt + Tx(45)(is_part + bolt)
return a
if __name__ == '__main__':
out_dir = sys.argv[1] if len(sys.argv) > 1 else os.curdir
file_out = os.path.join(out_dir, 'hole_example.scad')
# On the left, pipes with no explicit holes, which can give
# unexpected walls where we don't want them.
# On the Tx, we use the hole() function to fix the problem
a = pipe_intersection_no_hole() + Tx(45)(pipe_intersection_hole())
# Below is an example of how to put objects into holes and have them
# still appear
b = up(40)(multipart_hole())
a += b
# print("%(__file__)s: SCAD file written to: \n%(file_out)s" % vars())
# scad_render_to_file(a, file_out, file_header='$fn = %s;' % SEGMENTS, include_orig_code=True)
r.render(multipart_hole())
b = Cu(10, center=True)
c = Cy(r=2, h=12, center=True)
# A Cu with an explicit hole
not_part = b - hole()(c)
# Mark this Cu-with-hole as a separate part from the Cy
is_part = part()(not_part.copy())
# This fits in the holes
bolt = Cy(r=1.5, h=14, center=True) + Tz(8)(Cy(r=2.5, h=2.5, center=True))
# The section of the bolt inside not_part disappears. The section
# of the bolt inside is_part is still there.
a = not_part + bolt + Tx(45)(is_part + bolt)
r.render(a)
def Sec1(rad = 10, start_degrees = 15, end_degrees = 165, thick = 5, segments= 60):
# Note: the circle that this arc is drawn from gets segments,
# not the arc itself. That means a quarter-circle arc will
# have segments/4 segments.
# 加上了厚度thick
bottom_half_square = Ty(-rad)(Sq([3 * rad, 2 * rad], center=True))
top_half_square = Ty(rad)(Sq([3 * rad, 2 * rad], center=True))
start_shape = Ci(rad, segments=segments)
if abs((end_degrees - start_degrees) % 360) <= 180:
end_angle = end_degrees - 180
ret = start_shape
ret -= Rz(start_degrees)(bottom_half_square.copy())
ret -= Rz(end_angle)(bottom_half_square.copy())
else:
ret = start_shape
ret *= Rz(start_degrees)(top_half_square.copy()) + Rz(end_degrees)(bottom_half_square.copy())
return Le(thick)(ret)
d = Sec1()
r.render(d)
未完待续。。。