IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Open source  >

用 SketchUp 和 Eclipse 进行 3-D 建模,第 2 部分: 用 SketchUp 脚本编制语言编写代码

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

样例代码

英文原文

英文原文


级别: 中级

Matthew Scarpino, Java 开发人员, Eclipse Engineering, LLC

2009 年 6 月 11 日

通过脚本可以为 SketchUp 设计增加自动化、动画和几何计算。如果可以编写适当的代码,SketchUp 可以成为像 Maya 这样的呈现工具或者像 AutoCAD 这样的机械设计工具。本文是一个分两部分的 “用 SketchUp 和 Eclipse 进行 3D 建模” 系列的第 2 部分,文中描述 SketchUp 脚本中使用的众多基本类,并提供一些例子来展示这些类的用法。通过这些类,可以使用线段和面构造任意的 3D 图形。然后,可以用颜色和图像配置每个面的外观。

第 1 部分 展示如何设置 Eclipse 环境,以便创建、编辑和执行 SketchUp 脚本。这个部分提供了一个示例脚本,但是留下一个重要的问题没有回答:脚本中的代码是如何工作的?本文的目的是通过讨论 SketchUp API 来回答这个问题。SketchUp API 包含一些类,这些类的方法可以绘制和修改 SketchUp 设计的一些方面,包括直线、面、颜色和图像。本文无法涵盖整个 API,所以我重点关注构造 SketchUp 形状所需的基本的类。但是,由于 SketchUp API 是基于 Ruby 的,因此,我将首先概述什么是 Ruby 语言以及它是如何工作的。

经常使用的缩写词
  • API:应用程序编程接口(application programming interface)
  • DHTML:动态超文本标记语言(Dynamic Hypertext Markup Language)
  • UI:用户界面(user interface)

面向 Java 程序员的 Ruby 简介

考虑到 Java™ 编程语言的流行度,加上本文提到了 Eclipse,我假设您熟悉 Java 编程语言。而 Ruby 则没有那么流行,因此我简要地解释一下两者之间的相似点和不同点。希望这种方式能让您对该语言有足够的了解,并试着编写一些基本的命令。

分析:

  • 和 Java 语言一样,Ruby 是面向对象的。实际上,Ruby 中的所有 内容都是 Object 的子类。Ruby 不具备 Java 语言中的 intfloatboolean 这样的基本类型。
  • 在 Ruby 中不必声明变量类型,所以可以在一个命令中将 x 设为等于 5,而在下一个命令中又可以将 x 设为等于 “Hello world!”。
  • 和 Java 编程一样,Ruby 方法也是通过点标记法调用的,但是括号(())和分号(;)是可选的。每个 Ruby 类有一个名为 new 的构造函数方法。
  • Ruby String 对象可以用双引号(")括起来,也可以用单引号(')括起来;不同之处是,解释器可以识别双引号括起的 String 对象中的转义序列(\n\t 等)。Ruby 接受单字符 String 对象,但是没有单独用于 char 对象的数据结构。
  • 单行注释以 # 开头。多行注释由 =begin=end 分隔。
  • Ruby 类与 Java 类的作用类似,但是除了类以外,Ruby 还支持 模块。Ruby 模块就像只包含静态方法的 Java 类。Ruby 模块不能实例化;它只是一个不同的名称空间下的例程的集合。
  • 最常见的文本输出方法有 putsprint,前一个方法在输出的末端增加一个换行符,后一个方法则不是。

记住这些规则后,就可以开始尝试编写 Ruby 代码。在 SketchUp 中,单击 Window > Ruby Console。然后尝试以下任何一个命令或所有的命令:

  • 2 * (5 + 5) / 4 * 1.0
  • 6.class
  • print 'Hello world'; puts '!'
  • m = Time.new; m.month
  • x = [4, true, 'hi there!']
  • puts x[2].to_s + " is a " + x[2].class.to_s

在最后一个命令中,Ruby 的 Object 类的 to_s 方法执行类似 Java 的 Object 类的 toString() 方法的操作:它返回一个表示 ObjectString。图 1 展示了 SketchUp 的 Ruby Console 中显示的这些命令的结果。


图 1. Ruby Console 中的输出
控制台输出

这些命令也许看起来比较简单,但 Ruby 提供了一些独特的特性,这些特性在 Java、CC++ 语言中完全找不到。这些独特的特性包括 iterator 块、并行赋值和像 Range 类这样奇妙的东西。但是说到 SketchUp API,只需对该语言有基本的理解,就可以做很多事情。下一节详细讨论该 API。





回页首


SketchUp API

第 1 部分提供了一个示例 SketchUp 脚本,并解释了如何使用 SketchUp 的 load 命令和 SketchUp Bridge 执行它。但是文章中没有解释脚本是如何工作的。该脚本的命令是 SketchUp API 的一部分 — 这正是本节的主题。我首先给出基本的 SketchUp 数据结构(SketchupModel),然后解释如何创建 EdgeFace 对象。然后,我解释两个挤压(extrusion)方法 — pushpullfollowme — 最后描述如何将 SketchUp 材质(material)内容应用到对象。

基本数据结构

Ruby 模块是方法的集合;SketchUp 模块是 SketchUp API 中最重要的模块。它的方法提供与整个 SketchUp 安装相关的信息,下面列出其中 5 个方法:

  • os_language — 返回运行 SketchUp 的操作系统
  • locale — 返回当前位置的语言代码
  • find_support_files — 返回顶级 SketchUp 目录中文件的路径
  • version_number — 返回 SketchUp 的版本
  • active_model — 返回表示当前设计的 Model 对象

与 Java 语言中任何静态方法一样,Ruby 模块方法的调用方式是在模块名后加一个点再加方法名。例如,为了发现 SketchUp 应用程序的版本,可以在 Ruby Console 中输入以下命令:Sketchup.version_number

在 SketchUp 模块中的所有方法当中,active_model 是最重要的。它返回 Model 对象,其中包含当前 SketchUp 设计中的所有信息。每个设计只有一个 Model 对象,每个 Model 对象只包含一个设计。这里的 “所有信息” 是指 Model 对象存储每个顶点的位置、每个形状的颜色、可用于设计的风格等。Model 将信息存储在一系列的容器对象(container object) 中,包括:

  • Entities — 当前设计中的所有形状
  • Materials — 颜色和纹理(texture)
  • Layers — 设计的图层
  • Styles — 设计的显示设置

一般而言,SketchUp 脚本的目的是修改这些容器对象中的数据。为此,可调用 Model 类中相应的方法。这些方法非常容易记住:layers 方法返回 Layers 对象,styles 方法返回 Styles 对象,entities 方法返回 Entities 对象,依此类推。例如,下面的代码获取当前 Model 对象的 Entities 容器:

model = Sketchup.active_model
ents = model.entities

可以将这些代码合并到一个命令中:

ents = Sketchup.active_model.entities

这是必须知道的一个重要命令,因为本文中的所有示例脚本都以这一行开头。您可以 下载 这些示例脚本。接下来,我将解释为什么能够访问 Model 对象的 Entities 容器是如此重要。

SketchUp 实体:Edges 和 Faces

如您所料,Entities 容器包含 Entity 对象。简言之,一个 Entity 对象表示 SketchUp 设计窗口中任何可以看见、移动或修改的形状。Entity 类是 SketchUp 中很多类的超类,如图 2 所示,该图显示了大部分 Entity 子类。


图 2. Entity 类的层次结构
Entity 类的层次结构

最重要的 Entity 对象是 EdgeFace 对象,这两个对象可作为 SketchUp 设计中的任何形状的构建块。Edge 是一条线段,可以通过 Entities 类的 add_line 方法将 Edge 对象添加到设计中。该方法接受两个各有 3 个元素的数组,这两个数组分别表示 Edge 对象的起点和终点。例如,要创建一条从 [0, 0, 0] 到 [5, 5, 5] 的线段,可以使用下面这样的代码:

ents = Sketchup.active_model.entities
edge = ents.add_line [0,0,0], [5, 5, 5]

当第二条命令执行时,SketchUp 自动在设计窗口中画出与 Edge 对象对应的直线。可以通过调用 Edge 类的方法查看和修改直线的属性。例如,length 方法返回直线的长度,start 返回起始点,end 返回终点。还有 smoothhidden 之类的方法可用于改变直线的外观。

顾名思义,Face 对象表示一个 2-D 平面。Entities 类的 add_face 方法在设计窗口中画出该平面,并返回一个 Face 对象。该方法接受一组点或 Edge 对象为参数。例如,下面的代码创建两个 Face 对象 — 一个在 x-y 平面上,另一个在 y-z 平面上。这两个 Face 对象都有 4 个顶点,但实际上可以创建有任意个点的 Face

ents = Sketchup.active_model.entities
# Create a face from points
face1 = ents.add_face [0,0,0], [3,0,0], [3,3,0], [0,3,0]
# Create a face from edges
edge1 = ents.add_line [0,0,0], [0,3,0]
edge2 = ents.add_line [0,3,0], [0,3,3]
edge3 = ents.add_line [0,3,3], [0,0,3]
edge4 = ents.add_line [0,0,3], [0,0,0]
face2 = ents.add_face [edge1, edge2, edge3, edge4]

Face 类的方法访问相应形状的属性。area 方法 返回表面面积,edges 方法返回形成平面的 Edge 对象的数组,normal 方法返回平面的法向量,法向量确定与平面垂直的方向。例如,face1.normal 返回 [0, 0, 1],因为 +z 方向垂直于 x-y 平面。当然,[0, 0, -1] 向量也是垂直的,可以通过调用 reverse! 方法翻转 Face 对象的法向量。

挤压 3-D 图形

从 2-D 平面形成 3-D 图形的过程称作挤压Face 类包含两个执行挤压的方法:pushpullfollowme。特别要记住,SketchUp 没有单独用于 3-D 图形的类。在挤压过程中,SketchUp 创建形成图形的 EdgeFace 对象。

pushpull 方法是两个方法中较容易使用的一个,它执行与 SketchUp 的 pushpull 工具相同的操作。也就是说,它在 Face 对象的法向量方向上进行挤压,创建一个 3-D 图形。该方法惟一需要的参数是一个数值距离,表明挤压应该执行多远。这个值可以为负,从而在 Face 对象的法向量的反方向上挤压。例如,前一篇文章通过创建一个正方形 Face 对象,并使用参数 -9 调用 pushpull 方法,形成了一个盒状立体图形。

第二个挤压方法是 followme,该方法与 SketchUp 的 followme 工具的作用是一样的。pushpull 只在一个方向上挤压,而 followme 则可以在任意方向上挤压。例如,如果创建一个圆形 Face 对象,那么可以沿着圆的轴线进行挤压,最后将形成一个圆柱体。但是还可以沿着圆形路径挤压来创建圆环体或球形。要设置挤压路径,需要定义一个 Edge 对象或一个 Edge 对象数组。清单 1 显示了该方法的用法,其中的代码创建一个三角形平面,并沿着一个矩形路径挤压它(请查看 下载)。


清单 1. 使用 followme 方法进行挤压
				
# Access the Entities object
model = Sketchup.active_model
ents = model.entities

# Create a triangular face
triangle = ents.add_face [1, 0, 0], [0, 1, 0], [0, -1, 0]

# Create the extrusion path
path = ents.add_edges [0, 0, 0], [0, 0, 10], [0, -10, 10], 
   [0, -10, 0], [0, 0, 0]

# Extrude the triangle along the rectangular path
triangle.followme path

add_edges 方法根据一系列的点创建一个 Edge 对象数组。图 3a 显示三角形 Face 对象和一个矩形路径。图 3b 显示该脚本最后一条命令(triangle.followme path)的结果,该命令沿着路径挤压三角形。


图 3. SketchUp 挤压
沿着矩形路径挤压三角形

注意,路径必须是一个闭环 — 也就是说,路径中第一个 Edge 对象的第一个点必须与最后一个 Edge 对象的最后一个点的位置相同。

SketchUp 材质

至此,您已经知道如何用代码构建形状,接下来还需要知道如何定义这些形状的显示。可以通过创建一个 Material 对象,配置它的显示,并将它与一个形状,例如 EdgeFace 对象相关联,从而定义形状的显示。可以用颜色、纹理或同时使用两者来定义 Material 对象的显示。Material 对象越详细,画出的图看上去就越真实,越专业。SketchUp 提供了很多现成的材质。要查看它们在 SketchUp 中是什么样子,可以单击 Window > Materials

就像模型的 Entities 容器容纳 Entity 对象一样,Materials 容器容纳 Material 对象。要将一个新的 Material 对象添加到设计中,需要调用 Materials 类的 add 方法。该方法接受材质的名称为参数,并返回一个新的 Material 对象。例如,下面的代码访问 Materials 容器,并创建一个名为 RedBrickMaterial 对象:

mats = Sketchup.active_model.materials
rb_mat = mats.add "RedBrick"

创建好 Material 对象后,就可以用 Material 类中的方法访问和配置它的属性,这些方法包括:

  • color — 设置 Material 对象的颜色
  • texture — 识别 Material 对象的纹理
  • materialType — 返回一个数字,表明 Material 对象是否具有颜色(0)或纹理(1),还是两者都有(2
  • display_name — 返回 Material 对象的名称

SketchUp 提供了一个 Color 对象,但是更容易的方法是使用一个简单的 RGB 数组替代,例如 [64, 128, 255]。其中第一个元素表示颜色中红色的亮度,第二个元素表示绿色的亮度,第三个元素表示蓝色的亮度。还可以使用颜色的名称,例如 Red、PlumMintGreen。要查看 X11 颜色名称的完整列表,可在 Ruby Console 中输入 Sketchup::Color.names。例如,要将 rb_mat 的颜色设为红色,可输入以下任意一条命令:

rb_mat.color = [255, 0, 0]
rb_mat.color = "Red"

在 3-D 图形用语中,纹理 是指像墙纸模式一样应用到某个设计区域的图像:该图像可以重复,也可以根据需要裁剪,以覆盖平面。SketchUp 提供了 Texture 对象,但更容易的方法是使用图像文件名替代。SketchUp 可以从 JPG、PNG、PSD、TIF、TGA 和 BMP 文件创建纹理,下面的命令展示如何将 C:/scripts/tex.targa 中的图像设为一个名为 rb_matMaterial 对象的纹理。

rb_mat.texture = "C:/scripts/tex.targa"

配置好 Material 对象的颜色或纹理后,将它指定给设计中的一个形状(或多个形状)。这很简单:Drawingelement 类(Entity 的子类,EdgeFace 的超类)提供了一个 material 方法,该方法接受一个 Material 对象为参数,并将该 Material 对象的颜色或纹理应用到元素。清单 2 中显示了具体的代码,该代码创建一个具有纹理(C:/scripts/brick.jpg)和颜色(DodgerBlue)的 Material 对象。第一行定义图像文件的路径;路径必须正确指定,否则脚本不会正常运行。


清单 2. 创建和应用材质
				
image_file_path = "C:/scripts/brick.jpg"

# Create the new material
mats = Sketchup.active_model.materials
brick_mat = mats.add "red_brick"

# Assign the color and texture
brick_mat.texture = image_file_path
brick_mat.color = "DodgerBlue"

# Draw a Face and set its material
ents = Sketchup.active_model.entities
face = ents.add_face [10, -10, 0], [10, 10, 0], 
   [-10, 10, 0], [-10, -10, 0]
face.reverse!
face.material = brick_mat

注意,brick_mat 的颜色是在纹理之后 定义的,以便在应用到平面之前改变纹理的颜色。虽然 brick.jpg 图像主要是红色,但最终的纹理是蓝色,因为后面定义了 Material 对象的颜色。图 4 显示这种蓝色看上去是什么样子。


图 4. 应用到一个平面的材质
应用到一个平面的材质





回页首


了解更多

如果我让您认为 SketchUp 脚本中只有 Edge 对象、Face 对象和 Material 对象,那么我会感到愧疚。实际上,SketchUp 提供了大量精彩功能,远远不止画出漂亮的形状那么简单。它们包括:

  • Animation — 定义 SketchUp 设计如何随着时间而移动
  • Component — 创建模块化设计块,这种设计块可存储在文件中,并在设计中实例化
  • PolygonMesh — 创建或导入高级的形状,并应用复杂的纹理
  • WebDialog — 通过专门的 DHTML 窗口与 Internet 交互
  • Tool/Menu/Page — 通过扩大 UI 增加 SketchUp 的功能

当然,SketchUp 的一个优点是可以与 Google Earth 交互,并创建特定于地形的结构。





回页首


结束语

通过创建和执行 SketchUp 脚本,可以自动化设计过程,节省大量的时间。此外,还可以编写绘制样条曲线(spline)、非均匀有理 B 样条曲线(nonuniform rational B-spline,NURB)和参数曲线(parametric curve)等形状的几何算法。幸运的是,SketchUp API 仍保持简单而强大的思想,这正是 Google 如此成功的秘诀。只需很少的时间,就可以掌握一些基本的类(EdgeFace),通过组合这些类就可以形成 SketchUp 图形。如果投入更多的时间,还可以增加一些高级的功能,例如动画和动态组件。






回页首


下载

描述名字大小下载方法
与 SketchUp 交互的 Eclipse 插件os-eclipse-sketchup2-example_scripts.zip16KBHTTP
关于下载方法的信息


参考资料

学习

获得产品和技术

讨论
  • Eclipse Platform 新闻组 是讨论关于 Eclipse 的问题的第一站(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.platform)。

  • Eclipse 新闻组 中有很多参考资料适用于对使用和扩展 Eclipse 感兴趣的人员。

  • 参与 developerWorks blogs 并加入 developerWorks 社区。



关于作者

Matthew Scarpino 是 Eclipse Engineering LLC 的一名项目经理兼 Java 开发人员。他是SWT/JFace in Action的首席作家,并对标准部件工具包(Standard Widget Toolkit,SWT)做过一次较小的但非常重要的贡献。他喜欢爱尔兰民间音乐、马拉松赛跑、William Blake 的诗歌以及图形化编辑框架(Graphical Editing Framework,GEF)。




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

建议?







回页首


Java 和所有基于 Java 的商标和徽标是 Sun Microsystems 公司在美国和/或其他国家的商标。 IBM、DB2、Lotus、Rational、Tivoli 和 WebSphere 是 IBM 公司在美国和/或其他国家的商标。 其他公司、产品或服务的名称可能是其他公司的商标或服务标志。

IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款