BRL-CAD’s Python Procedural Geometry

Jaipal Singh
6 min readAug 14, 2018

Google Summer of Code : 2018

What is BRL-CAD?

BRL-CAD is a powerful open source cross-platform solid modeling system that includes interactive geometry editing, high-performance ray-tracing for rendering and geometric analysis, a system performance analysis benchmark suite, geometry libraries for application developers, and more than 30 years of active development.

What is Procedural Geometry?

Procedural geometry is geometry modeled in code

It is a method of geometry generation that automates creation of complex shapes using various rules, algorithms and procedures. One of the finest examples of Procedural Geometry is the Sierpinski Triangle.

Why Procedural Geometry

This is best explained using an example. BRL-CAD is capable of creating extremely complex objects using just a few basic primitives (basic geometrical shapes in BRL-CAD are referred to as primitives). For this example, let’s talk about one of my favorite examples, the mighty tank!

Tank Created Using BRL-CAD

Focus on the continuous track (caterpillar track) in this tank. You can see there are 7 wheels surrounded by a track plate. Now let’s say you were given this tank sans the wheels and asked to put the wheels in place. The classical way would be to figure out the 3-D co-ordinates for one of the wheels and then infer the co-ordinates for the other wheels (given that they’re equidistant from one another). This would involve :-

  1. Find co-ordinates for the first wheel
  2. Calculating the co-ordinates for each of the wheels
  3. Manually create each wheel by passing specific co-ordinates.

Now, let’s think about this problem as programmers, you don’t want to put in so much effort if your laptop with a ton of stickers can do it for you. So, what would be an alternate (and better) way to do this?

  1. Find co-ordinates for the first wheel
  2. Create a procedure (function) that calculates co-ordinates for each wheel and draws the wheel
  3. Loop over your procedure to create all wheels

The procedural approach is not only easier but it also saves you time and can be done with only a few lines of code.

“Make it work, make it right, make it fast.” — Kent Beck

Procedural Geometry in BRL-CAD

Procedural geometry of sorts has existed in BRL-CAD for a while now. This is an example shell script that uses BRL-CAD tools to procedurally create and render the SGI Cube. The script sets up functions (procedures)that create spheres (SPHs) and cylinders (RCCs) going back and forth in various directions, creating the corresponding geometry for each of those directions. The issue with this approach is that, it depends on interacting with BRL-CAD’s geometry editor GUI, mged.

Python Procedural Geometry

Approach 1 : Ctypesgen

Python BRL-CAD came into existence in 2014. The project focusses on wrapping BRL-CAD’s primitives in python using ctypesgen. These bindings parse the header files of the primitives from the installed version of BRL-CAD and uses them to construct a standard library of abstractions around the bindings. . A minor drawback with this approach is that, the bindings might need to be updates to accommodate changes brought to the C code.

Approach 2 : Tcl Scripts

As a solution to shortcomings of the ctypesgen approach, a new approach for procedural geometry was developed. We now express procedural geometry as pythonic scripts that generate .tcl scripts which are then fed into MGED to create the required complex geometry. Here, the python script for creating a particular shape would have multiple functions creating different primitives and one main caller that would put it all together.

This approach though, is still plagued with the major shortcoming of the pre-existing procedural geometry architecture in BRL-CAD, viz. it involves interaction with the geometry editor, mged. To avoid this, we resort to solving the problem of procedural geometry using the ctypesgen approach.

Python Procedural Geometry : Ctypesgen

Setting Up Python BRL-CAD

In this post, I’ll be sharing some insights and examples into creating procedural geometry using the ctypesgen approach. A second part of this post (coming soon) will be dedicated to working with the tcl approach.

What you’re going to need :

Now, it’s time to setup Python BRL-CAD (PB from now on). This is what you’ll have to do :

  1. In your terminal :
    git clone :https://github.com/Killthebug/python-brlcad/
  2. cd python-brlcad
  3. export BRLCAD_PATH="YOUR_BRLCAD_INSTALLATION"
  4. python setup.py install

You might have to use sudo while setting up depending on your system. You will also see a lot of errors, but they shouldn’t be an issue unless they stop the installation half-way. In just a couple of seconds, you’re all ready!

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Creating Your First Primitive

Great! Let’s now go ahead and create our first primitive. For this example, let’s work on creating a sphere!

So go ahead and create a python file, let’s call ours sphere.py.

I. The very first step is to import the libraries and modules that you might require.

from brlcad.vmath import Transform
from brlcad.geometry import Database
from brlcad import primitives

II. The next step is to open a database that you want to save your geometry into. Geometry files in BRL-CAD follow a .g file extension.

db = Database("geometry.g", "Test BRL-CAD DB file")

III. And just like that, we’re halfway there! Now, let’s go ahead and create a sphere and save it into our database. Primitives created are given a unique name, which is passed as the first argument in all our primitive functions. You should also make a note that primitive names end with a .s extension in BRL-CAD.

db.sphere("sph1.s",center=(0.5, 5, 8), radius=0.75

IV. Save your script and execute it. This should now create a new database file called as geometry.g. The sphere can be viewed by opening the database file using mged. You can do this by : mged geometry.g

You’ll then see something like this :

Basic Primitive Drawn

V. We’re almost there. What we’re lacking is some good color for the primitive. Let’s do this by creating a region and assigning it some material properties.

db.region(
'sph.r',
region_id = 16,
tree = 'sph1.s',
shader="plastic {di .9 sp .4}",
rgb_color=(66,102,0)
)

VI. Save the file and open the database file with mged. Go ahead, draw the region that you just created and raytrace it. If everything goes as planned, you’ll see something like this :

Primitive Region RayTraced

Voila! You’ve done it. You’ve create your first every geometry object using PB!

From here on, it’s all up-to how creative you wish to get with this. You can create procedures (functions) with various shapes and maybe also try and create the tank we saw earlier using procedural geometry.

The project is currently maintained and updated at : https://github.com/kanzure/python-brlcad. Pull requests, issues and new ideas to improve the project are extremely welcome!

Tutorials on how to work with the different primitives can be found at: http://bit.ly/pyBRLCADTutorial

P.S. The scene showcased at the top of the blog was created purely using python BRL-CAD, you can find the source for it at : http://bit.ly/pyBRLCADScene

--

--