【速度测试】三种表面创建方法的速度对比
在 SketchUp 最新的 2022 版本中,新增了一个 EntitiesBuilder 类,官方文档中将其描述为与 PolygonMesh 类相似的结构,用于创建复杂的表面网络。
Note: Like Geom:: PolygonMesh there is minimal validation checks made on the input to the creation of the geometry. Vertices are de-duplicated and edges sharing the same vertices will be de-duplicated ... It leaves a higher responsibility on the API user to produce valid geometry. https://ruby.sketchup.com/Sketchup/EntitiesBuilder.html
那么这两个类在创建表面时能提升多少效率?以下通过三段实现方式相同的代码来测试三者的创建速度。
这三段代码的作用是在xy平面内靠近原点的正方形内根据给定的表达式创建三维表面。只需要提供 z=f( x, y) 的函数表达式,就可以在 SketchUp 中创建相应的曲面:
测试结果显示,创建一个51×51的网格使用常规方法需要 1.7365 秒的时间。生成包含相应点坐标和平面信息的 PolygonMesh 对象后再创建平面的方法耗时 0.1967 秒,比常规方法的效率相比有显著的提高。而在 EntitiesBuilder 的编辑模式下,相同表面的创建仅需要 0.0468 秒,相比 PolygonMesh 在效率上也仍然有很大的提升。
通过测试函数生成的曲面
不同形状与精细度的曲面生成速度测试结果
(其中L50表示50×50的格网,L100表示100×100的格网)
代码如下:
#常规的方法
def gen_xy_surface_rough(pixelcount=10,&block)
block=proc{|x,y|0} if block.nil?
step=2.0/pixelcount.to_f
pts=[]
Sketchup.active_model.start_operation("Apiglio: Surface R")
t0=Time.now().to_f
begin
0.upto(pixelcount) do |i|
pts.push([])
0.upto(pixelcount) do |j|
x=i*step-1
y=j*step-1
pts[-1].push([x,y,block.call(x,y)])
end
end
0.upto(pixelcount-1) do |i|
0.upto(pixelcount-1) do |j|
Sketchup.active_model.entities.add_face(pts[i][j],pts[i+1][j],pts[i][j+1])
Sketchup.active_model.entities.add_face(pts[i+1][j+1],pts[i][j+1],pts[i+1][j])
end
end
rescue
Sketchup.active_model.abort_operation()
return RuntimeError.new("生成表面出错。")
end
t1=Time.now().to_f
Sketchup.active_model.commit_operation()
puts("用时#{t1-t0}秒。")
end
#使用PolygonMesh的方法
def gen_xy_surface_mesh(pixelcount=10,&block)
block=proc{|x,y|0} if block.nil?
step=2.0/pixelcount.to_f
pts=[]
i=-1.0
Sketchup.active_model.start_operation("Apiglio: Surface M")
mesh=Geom::PolygonMesh.new
t0=Time.now().to_f
begin
0.upto(pixelcount) do |i|
pts.push([])
0.upto(pixelcount) do |j|
x=i*step-1
y=j*step-1
pts[-1].push(mesh.add_point([x,y,block.call(x,y)]))
end
end
0.upto(pixelcount-1) do |i|
0.upto(pixelcount-1) do |j|
mesh.add_polygon(pts[i][j],pts[i+1][j],pts[i][j+1])
mesh.add_polygon(pts[i+1][j+1],pts[i][j+1],pts[i+1][j])
end
end
Sketchup.active_model.entities.add_faces_from_mesh(mesh)
rescue
Sketchup.active_model.abort_operation()
return RuntimeError.new("生成表面出错。")
end
t1=Time.now().to_f
Sketchup.active_model.commit_operation()
puts("用时#{t1-t0}秒。")
end
#使用EntitiesBuilder的方法
def gen_xy_surface_builder(pixelcount=10,&block)
block=proc{|x,y|0} if block.nil?
step=2.0/pixelcount.to_f
pts=[]
Sketchup.active_model.start_operation("Apiglio: Surface B")
t0=Time.now().to_f
begin
0.upto(pixelcount) do |i|
pts.push([])
0.upto(pixelcount) do |j|
x=i*step-1
y=j*step-1
pts[-1].push([x,y,block.call(x,y)])
end
end
Sketchup.active_model.entities.build{|builder|
0.upto(pixelcount-1) do |i|
0.upto(pixelcount-1) do |j|
builder.add_face(pts[i][j],pts[i+1][j],pts[i][j+1])
builder.add_face(pts[i+1][j+1],pts[i][j+1],pts[i+1][j])
end
end
}
rescue
Sketchup.active_model.abort_operation()
return RuntimeError.new("生成表面出错。")
end
t1=Time.now().to_f
Sketchup.active_model.commit_operation()
puts("用时#{t1-t0}秒。")
end
三个测试函数的使用方法如下:
# 使用 EntitiesBuilder 生成平面 z = x + y 格网大小150×150
gen_xy_surface_builder(150){|x,y|x+y}
# 使用 PolygonMesh 生成平面 z = exp(-x^2-y^2) 格网大小50×50
gen_xy_surface_mesh(50){|x,y|Math.exp(-x**2-y**2)}
# 使用常规方法生成平面 z = sin x + cos y 格网大小20×20
gen_xy_surface_rough(20){|x,y|Math.sin(x)+Math.cos(y)}
(完)
从SU-2022-01期开始,本人的 SketchUp Ruby “小功能与灵感” 的文章中涉及的功能会在 GitHub 中相应更新。这样一来,如果日后发现存在bug需要修正或者是想追加相关的功能,都有极大的便利。
这个代码仓库同样也包含大部分之前文章的代码,可以访问以下网址查看,也欢迎大家共同提交修改:
https://github.com/Apiglio/SketchupScriptTool
本期代码在 Plot.rb 文件中。
本文编号:SU-2022-03
评论