3-D modeling with SketchUp and Eclipse, Part 2: Coding with the SketchUp scripting language

Scripts allow you to add automation, animation, and geometric computation to your SketchUp designs. With the right code, SketchUp can become a rendering tool like Maya or a mechanical design tool like AutoCAD. This article, the second in a two-part "3-D modeling with SketchUp and Eclipse" series, describes a number of the basic classes used in SketchUp scripts and provides examples of their usage. With these classes, you can construct any 3-D figure composed of line segments and faces. Then you can configure the appearance of each face with colors and images.

Share:

Matthew Scarpino, Java Developer, Eclipse Engineering, LLC

Matthew Scarpino is a project manager and Java developer at Eclipse Engineering LLC. He is the lead author of SWT/JFace in Action and made a minor but important contribution to the Standard Widget Toolkit (SWT). He enjoys Irish folk music, marathon running, the poetry of William Blake, and the Graphical Editing Framework (GEF).


developerWorks Contributing author
        level

12 May 2009

Also available in Russian Japanese

Part 1 shows how to set up the Eclipse environment to create, edit, and execute SketchUp scripts. It provided an example script, but left an important question unanswered: How does the code inside the scripts work? The goal of this article is to answer this question by discussing the SketchUp API. The SketchUp API contains classes whose methods draw and modify aspects of a SketchUp design, including lines, surfaces, colors, and images. This article can't cover the entire API, so I focus on the basic classes needed to construct SketchUp shapes. But first, because the SketchUp API is based on Ruby, I provide an overview of what the Ruby language is and how it works.

Frequently used acronyms

  • API: Application programming interface
  • DHTML: Dynamic Hypertext Markup Language
  • UI: User interface

Ruby for Java programmers: A brief introduction

Given the popularity of the Java™ programming language and the mention of Eclipse in the title, I assume you're familiar with the Java programming language. Ruby isn't nearly as popular, so I briefly explain some of the similarities and differences between the two. In this way, I hope to make you sufficiently comfortable with the language to dip your toes in and write some elementary commands.

The breakdown:

  • Like the Java language, Ruby is object-oriented. In fact, everything in Ruby is a subclass of Object. There are no primitives like the Java language's int, float, and boolean.
  • You don't have to declare variable types in Ruby, so you can set x equal to 5 in one command and x equal to "Hello world!" in the next.
  • Ruby methods are invoked with the same dot-notation as in Java programming, but parentheses (()) and semicolons (;) are optional. Every Ruby class has a constructor method called new.
  • Ruby String objects can be surrounded by double quotation marks (") or single quotation marks ('); the difference is that the interpreter recognizes escape sequences (\n, \t, etc.) inside double-quoted String objects. Ruby accepts single-character String objects, but doesn't have a separate data structure for char objects.
  • Single-line comments start with the pound sign (#). Multi-line comments are delimited by =begin and =end.
  • Ruby classes serve the same roles as Java classes, but in addition to classes, Ruby supports modules. A Ruby module is like a Java class that contains only static methods. You can't instantiate a Ruby module; it's just a collection of routines under a distinct namespace.
  • The most common text output methods are puts, which adds a newline to the end of the output, and print, which does not.

With these rules in mind, you're ready to start experimenting with Ruby code. In SketchUp, click Window > Ruby Console. Then try any or all of the following commands:

  • 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

In the last command, the to_s method of Ruby's Object class performs the same operation as the toString() method in Java's Object class: It returns a String that represents the Object. Figure 1 shows the results of these commands displayed in SketchUp's Ruby Console.

Figure 1. Output in the Ruby Console
Console output

These commands may seem simple, but Ruby provides features that aren't anything like what you'll see in the Java, C, or C++ languages. Such unique features include iterator blocks, parallel assignment, and oddities like the Range class. But when it comes to the SketchUp API, you can go very far with just a basic understanding of the language. The next section discusses the API in detail.


The SketchUp API

Part 1 provides an example SketchUp script and explains how to execute it using SketchUp's load command and the SketchUp Bridge. But the article doesn't explain how the script works. The script's commands are part of the SketchUp API — the subject of this section. I present the fundamental SketchUp data structures first (Sketchup and Model), then explain how to create Edge and Face objects. After that, I explain the two extrusion methods —pushpull and followme— and conclude with a description of how SketchUp materials are applied to objects.

The fundamental data structures

A Ruby module is a collection of methods; the SketchUp module is the most important module in the SketchUp API. Its methods provide information related to the entire SketchUp installation, and five of them are listed here:

  • os_language— Returns the operating system on which SketchUp is running
  • locale— Returns the language code for the current locale
  • find_support_files— Returns the path of files within the top-level SketchUp directory
  • version_number— Returns the version of SketchUp
  • active_model— Returns the Model object representing the current design

Like a static method in the Java language, you invoke a Ruby module's method by following the module name with a dot and the name of the method. For example, to find the version of the SketchUp application, you could enter the following command in the Ruby Console: Sketchup.version_number.

Of all the methods in the SketchUp module, active_model is the most important. It returns the Model object that contains all the information in the current SketchUp design. Each design has a single Model object, and each Model object embodies a single design. By "all the information," I mean that the Model object stores the positions of every vertex, the color of every shape, the styles available for the design, and much more. The Model stores its information in a series of container objects, which include the following components:

  • Entities— All the shapes in the current design
  • Materials— Colors and textures
  • Layers— The design's graphic layers
  • Styles— The appearance settings for the design

Generally speaking, the goal of a SketchUp script is to modify the data in these container objects. To do this, call the corresponding method in the Model class. These methods are easy to remember: The layers method returns the Layers object, the styles method returns the Styles object, the entities method returns the Entities object, etc. For example, the following code retrieves the Entities container of the current Model object:

model = Sketchup.active_model
ents = model.entities

You can combine these into a single command:

ents = Sketchup.active_model.entities

This is an important command to know, as all of the example scripts in this article begin with this line. You can download the example scripts. Next, I explain why it's so important to be able to access the Entities container of a Model object.

SketchUp entities: Edges and Faces

As you might expect, the Entities container contains Entity objects. Put simply, an Entity object represents any shape that can be seen, moved, or modified within the SketchUp design window. The Entity class is the superclass of many of SketchUp's classes, as shown in Figure 2, which shows most of the Entity subclasses.

Figure 2. Entity class hierarchy
Entity class hierarchy

The most important Entity objects are the Edge and Face objects, which serve as the building blocks of every shape in a SketchUp design. An Edge is a line segment, and you add Edge objects to a design through the add_line method of the Entities class. This method accepts two three-element arrays that represent the Edge object's starting and ending points. For example, to create a line segment from [0, 0, 0] to [5, 5, 5], you could use code like the following:

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

When the second command executes, SketchUp automatically draws the line corresponding to the Edge object in its design window. You can read and modify the line's properties by calling methods of the Edge class. For example, the length method returns the line's length, start returns its starting point, and end returns its ending point. There are also methods like smooth and hidden that change the line's appearance.

As its name implies, a Face object represents a 2-D surface. The add_face method of the Entities class both draws the surface in the design window and returns a Face object. This method accepts a set of points or Edge objects. For example, the following code creates two Face objects — one in the x-y plane and one in the y-z plane. Both Face objects have four vertices, but you can create a Face with any number of points.

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]

The methods of the Face class access the properties of the corresponding shape. The area method returns the surface area, the edges method returns the array of Edge objects that form the face, and the normal method returns the surface's normal vector, which identifies the direction perpendicular to the surface. For example, face1.normal returns [0, 0, 1] because the +z direction is perpendicular to the x-y plane. Of course, the [0, 0, -1] vector is also perpendicular, and you can flip the Face object's normal vector by calling the reverse! method.

Extruding 3-D figures

The process of forming a 3-D figure from a 2-D surface is called extrusion. The Face class contains two methods that perform extrusion: pushpull and followme. It's important to note that SketchUp doesn't have a separate class for 3-D figures. Instead, during the extrusion process, SketchUp creates the Edge and Face objects that form the figure.

The pushpull method is the easier of the two methods to use, and it performs the same operation as SketchUp's pushpull tool. That is, it creates a 3-D figure by extruding in the direction of the Face object's normal vector. Its only required argument is a numerical distance that identifies how far the extrusion should be performed. This value can be negative to extrude in the direction opposite the Face object's normal vector. For example, the previous article formed a box by creating a square Face object and calling the pushpull method with an argument of -9.

The second extrusion method is followme, which serves the same purpose as SketchUp's followme tool. Although pushpull only extrudes in a single direction, followme extrudes in whatever direction you like. For example, if you create a circular Face object, you can form a cylinder by extruding along the circle's axis. But you can also create a torus or sphere by extruding along a circular path. To set the extrusion path, you need to define an Edge object or an array of Edge objects. This usage is shown in Listing 1, which creates a triangular face and extrudes it along a rectangular path (also see Download).

Listing 1. Extruding with the followme method
# 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

The add_edges method creates an array of Edge objects from a sequence of points. Figure 3a shows the triangular Face object and a rectangular path. Figure 3b shows the result of the last command of the script (triangle.followme path), which extrudes the triangle along the path.

Figure 3. SketchUp extrusion
Extruding a triangle along a rectangular path

Note that the path must be a closed loop — that is, the first point of the first Edge object in the path must have the same location as the last point of the last Edge object.

SketchUp materials

Now that you know how to build shapes in code, you need to know how to define the appearance of those shapes. You do this by creating a Material object, configuring its appearance, and associating it with a shape such as an Edge or Face object. You can define a Material object's appearance by a color, a texture, or both. The more detailed the Material object, the more realistic and professional the drawing will look. SketchUp provides a number of existing materials. To see what they look like in SketchUp, click Window > Materials.

Just as the model's Entities container holds Entity objects, and the Materials container holds Material objects. To add a new Material object to your design, you need to invoke the add method of the Materials class. This method accepts a name for the material and returns a new Material object. For example, the following code accesses the Materials container and creates a Material object named RedBrick:

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

After you've created a Material object, you can access and configure its properties with methods in the Material class, which include the following:

  • color— Sets the color of the Material object
  • texture— Identifies the texture of the Material object
  • materialType— Returns a number that identifies whether the Material object has a color (0), a texture (1), or both (2)
  • display_name— Returns the name of the Material object

SketchUp provides a specific Color object, but it's easier to substitute a simple RGB array like [64, 128, 255]. Here, the first element identifies the intensity of red in the color, the second identifies the intensity of green, and the third identifies the intensity of blue. You can also substitute the name of a color, such as Red, Plum, or MintGreen. To see the full list of X11 color names, type Sketchup::Color.names in the Ruby Console. For example, to color rb_mat red, you could enter either of the following commands:

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

In 3-D graphics parlance, a texture is an image applied to a design area like wallpaper pattern: The image is repeated or cut as needed to cover the surface. SketchUp provides a specific Texture object, but it's easier to substitute the image file name. SketchUp can create textures from JPG, PNG, PSD, TIF, TGA, and BMP files, and the following command shows how the image in C:/scripts/tex.targa is made the texture of a Material object called rb_mat.

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

After you've configured a Material object's color or texture, assign it to a shape (or multiple shapes) in the design. Doing so is simple: The Drawingelement class (subclass of Entity, superclass of Edge and Face) provides a method called material that accepts a Material object and applies the Material object's color or texture to the element. This is shown in Listing 2, which creates a Material object with a texture (C:/scripts/brick.jpg) and a color (DodgerBlue). The path of the image file is defined in the first line; the script won't work unless the path is identified correctly.

Listing 2. Creating and applying a material
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

Note that the color of brick_mat is defined after its texture to change the color of the texture before it's applied to the surface. Though the brick.jpg image is primarily red, the final texture is blue, because the Material object's color is defined afterward. Figure 4 shows what the blue color looks like.

Figure 4. Material applied to a face
Material applied to a face

More to learn

I'd feel guilty if I let you think that all SketchUp scripts had to offer was Edge objects, Face objects, and Material objects. SketchUp provides many more fascinating capabilities that go far beyond making pretty shapes. They include:

  • Animation— Define how a SketchUp design moves over time
  • Component— Create modular design pieces that can be stored in files and instantiated within designs
  • PolygonMesh— Create or import sophisticated shapes and apply complex textures
  • WebDialog— Interact with the Internet through a specialized DHTML window
  • Tool/Menu/Page— Add capabilities to SketchUp by augmenting the UI

And of course, one of SketchUp's strengths is the ability to interact with Google Earth and create geography-specific structures.


Conclusion

By creating and executing SketchUp scripts, you can automate the design process and potentially save yourself a great deal of time. In addition, you can code geometric algorithms that draw shapes like splines, nonuniform rational B-splines (NURBs), and parametric curves. Thankfully, the SketchUp API keeps to the same simple-but-powerful mindset that has made Google so successful. In just a small amount of time, you can master the basic classes (Edge, Face) that combine to form SketchUp figures. And as you invest further time, you can add advanced capabilities like animation and dynamic components.


Download

DescriptionNameSize
Eclipse plug-in that interfaces with SketchUpos-eclipse-sketchup2-example_scripts.zip16KB

Resources

Learn

Get products and technologies

Discuss

  • The Eclipse Platform newsgroups should be your first stop to discuss questions regarding Eclipse. (Selecting this will launch your default Usenet news reader application and open eclipse.platform.)
  • The Eclipse newsgroups has many resources for people interested in using and extending Eclipse.
  • Participate in developerWorks blogs and get involved in the developerWorks community.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Open source on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source
ArticleID=387473
ArticleTitle=3-D modeling with SketchUp and Eclipse, Part 2: Coding with the SketchUp scripting language
publish-date=05122009