【速度测试】三种表面创建方法的速度对比

Apiglio

共 4265字,需浏览 9分钟

 · 2022-06-26

在 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×150gen_xy_surface_builder(150){|x,y|x+y}# 使用 PolygonMesh 生成平面 z = exp(-x^2-y^2) 格网大小50×50gen_xy_surface_mesh(50){|x,y|Math.exp(-x**2-y**2)}# 使用常规方法生成平面 z = sin x + cos y 格网大小20×20gen_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

浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报