 | 级别: 中级 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 语言中的 int、
float 和 boolean 这样的基本类型。
- 在 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 模块不能实例化;它只是一个不同的名称空间下的例程的集合。
- 最常见的文本输出方法有
puts 和 print,前一个方法在输出的末端增加一个换行符,后一个方法则不是。
记住这些规则后,就可以开始尝试编写 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() 方法的操作:它返回一个表示 Object 的 String。图 1 展示了 SketchUp 的
Ruby Console 中显示的这些命令的结果。
图 1. Ruby Console 中的输出
这些命令也许看起来比较简单,但 Ruby 提供了一些独特的特性,这些特性在 Java、C 或 C++ 语言中完全找不到。这些独特的特性包括 iterator 块、并行赋值和像 Range 类这样奇妙的东西。但是说到 SketchUp API,只需对该语言有基本的理解,就可以做很多事情。下一节详细讨论该 API。
SketchUp API
第 1 部分提供了一个示例 SketchUp 脚本,并解释了如何使用 SketchUp 的 load 命令和
SketchUp Bridge 执行它。但是文章中没有解释脚本是如何工作的。该脚本的命令是 SketchUp API 的一部分 — 这正是本节的主题。我首先给出基本的 SketchUp 数据结构(Sketchup
和 Model),然后解释如何创建
Edge 和 Face 对象。然后,我解释两个挤压(extrusion)方法 —
pushpull
和 followme
— 最后描述如何将 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 对象是
Edge 和 Face 对象,这两个对象可作为 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 返回终点。还有
smooth 和 hidden 之类的方法可用于改变直线的外观。
顾名思义,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 类包含两个执行挤压的方法:pushpull
和 followme。特别要记住,SketchUp
没有单独用于 3-D 图形的类。在挤压过程中,SketchUp 创建形成图形的 Edge 和
Face 对象。
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 对象,配置它的显示,并将它与一个形状,例如 Edge 或
Face 对象相关联,从而定义形状的显示。可以用颜色、纹理或同时使用两者来定义 Material 对象的显示。Material 对象越详细,画出的图看上去就越真实,越专业。SketchUp 提供了很多现成的材质。要查看它们在 SketchUp 中是什么样子,可以单击
Window > Materials。
就像模型的 Entities 容器容纳
Entity 对象一样,Materials
容器容纳 Material 对象。要将一个新的
Material 对象添加到设计中,需要调用 Materials 类的 add 方法。该方法接受材质的名称为参数,并返回一个新的 Material 对象。例如,下面的代码访问 Materials 容器,并创建一个名为 RedBrick 的
Material 对象:
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、Plum 或
MintGreen。要查看 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_mat 的
Material 对象的纹理。
rb_mat.texture = "C:/scripts/tex.targa"
|
配置好 Material 对象的颜色或纹理后,将它指定给设计中的一个形状(或多个形状)。这很简单:Drawingelement 类(Entity 的子类,Edge 和 Face 的超类)提供了一个 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 如此成功的秘诀。只需很少的时间,就可以掌握一些基本的类(Edge、Face),通过组合这些类就可以形成 SketchUp 图形。如果投入更多的时间,还可以增加一些高级的功能,例如动画和动态组件。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| 与 SketchUp 交互的 Eclipse 插件 | os-eclipse-sketchup2-example_scripts.zip | 16KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
关于作者  | |  | Matthew Scarpino 是 Eclipse Engineering LLC 的一名项目经理兼 Java 开发人员。他是SWT/JFace in Action的首席作家,并对标准部件工具包(Standard Widget Toolkit,SWT)做过一次较小的但非常重要的贡献。他喜欢爱尔兰民间音乐、马拉松赛跑、William Blake 的诗歌以及图形化编辑框架(Graphical Editing Framework,GEF)。 |
对本文的评价
|  |