B. Geometry and Class

In this session, you will learn:

  • how to describe geometries in Python

  • what is a class in Python

  • how to use classes in compas and Rhino

Geometry, Data, and Class

Basic geometry types such as Points, Vectors, Lines, and Planes are described with simple lists of values in Python. The number of values in the list corresponds with the number of dimensions of the space the geometry resides in. compas.geometry provides various geometrical classes that can be used interchangeably with native Python types for geometrical calculations. Rhino.Geometry also support geometry classes including points, point clouds, curves, surfaces, poly-surfaces, extrusions, meshes, annotations, and dimensions.

The following tables demonstrate how to describe a geometry using Python, or a class, which you will learn later.

Object

Python

point

point = [0, 0, 0]

vector

vector = [0, 0, 1]

line

line = [0, 0, 0], [1, 0, 0]

plane

plane = [0, 0, 0], [0, 0, 1]

circle

circle = ([0, 0, 0], [0, 0, 1]), 1.0

polyline

polyline = [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 0, 0]

Object

compas.geometry

Rhino.Geometry

point

point = Point(0, 0, 0)

point = Point3d(0, 0, 0)

vector

vector = Vector(0, 0, 1)

vector = Vector3d(0, 0, 1)

line

line = Line(point, point)

line = Line(Point3d, Point3d)

plane

plane = Plane(point, vector)

plane = Plane(Point3d, Vector3d)

circle

circle = Circle(plane, radius)

circle = Circle(plane, radius)

polyline

polyline = Polyline(points)

polyline = Polyline(Point3ds)

1. Python list Point

A point in 3D space has 3 coordinates, usually referred to as [x, y, z]. Coordinate of the point can be retrieved, modified, and updated by accessing the corresponding index of the list. Here we create a point (x=0, y=1, z=1). Now we change y=5.

my_point = [0, 1, 1]  # xyz coordinates of the point
print("y coordinate:", my_point[1])

my_point[1] = 5  # re-assign the y coordinates 5
print("xyz:", my_point)

y coordinate: 1 xyz coordinates: [0, 5, 1]

2. Point class

A class is a template to create a point object, which encapsulates variables and methods. Compared with a point list, a point class can contain not only variables of the point (x, y, z), but also relevant functions, which are called class methods.

Now, we will create our own user-defined Point class. Now it is empty block which is indicated using the pass statement. When we print the pt, we will get a point object: <__main__.Point object at 0x0000021DEBAFB548>.

class Point:
    """ Point class
    """
    pass

pt = Point()  # Instantiate an object of Point
print(pt)  # <__main__.Point object at 0x0000021DEBAFB548>

Currently, our class is still empty. We need to pass some initial values to the class using the __init__ method. Before the parameters x , y, z, there is a self, which refers to the object itself. Then, we need to create new fields also called x , y, z. Notice these are two different variables even though they are both called 'x'. You can view the dotted notation self.x as the attribute of your point object, and the other x is a local variable.

class Point:
    """ Point class
    
    Parameters
    ----------
    x : float
        The X coordinate of the point.
    y : float
        The Y coordinate of the point.
    z : float, optional
        The Z coordinate of the point.
    """
    
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

pt = Point(1,1,0)
print(pt.x, pt.y, pt.z)  # 1, 1, 0

Now let's add another method to Point class to translate the point. It modifies the object attribute self.x, self.y, self.z by adding the translation distance along the corresponding axis.

class Point:
    """ Point class

    Parameters
    ----------
    x : float
        The X coordinate of the point.
    y : float
        The Y coordinate of the point.
    z : float, optional
        The Z coordinate of the point.
    """
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z
    
    def translate(self, vec_x, vec_y, vec_z):
        """Translate this point along a 3d vector

        vec_x : float
            The X coordinate of the translation vector.
        vec_y : float
            The Y coordinate of the translation vector.
        vec_z : float, optional
            The Z coordinate of the translation vector.
        """
        self.x += vec_x
        self.y += vec_y
        self.z += vec_z

pt = Point(1,1,0)
pt.translate(1,1,1) 
print(pt.x, pt.y, pt.z)  # 2 2 1

In COMPAS, a point can be represented by Point class. In a COMPAS Point class, a Point has three parameters, x, y, z, which corresponds to the 3 coordinates. They could be accessed through indexing as well as through x, y, and z attributes.

from compas.geometry import Point

my_point = Point(0, 1, 1)  # create a point object
print(my_point.y)  # attribute y of point
print(my_point[1] == my_point.y)

my_point.y = 5  # reassign the attribute y
print(my_point)

1.0 True Point(0.000, 5.000, 1.000)

COMPAS Point class contains a lot of methods, which we can directly use. For example, the distance between two Point objects by calling Point1.distance_to_point(Point2).

from compas.geometry import Point

my_point = Point(0, 5, 0)
other_point = Point(1, 1, 0)

distance = my_point.distance_to_point(other_point)
print("distance between my_point and other_point is", distance)

In Rhino, a 3D point object could be created by a Point3d class.

Rhino uses IronPython, which is tightly integrated with the . NET Framework. Typical python IDE, such as Visual Studio Code doesn’t know how to work with it. Thus, Rhino.Geometry can only be run in Rhino Python editor.

Open your python editor in Rhino. Type your code then click the green button.

from Rhino.Geometry import Point3d

my_point = Point3d(0, 1, 1)  # create a point object
print(my_point.Y)  # attribute y of point

my_point.Y = 5  # reassign the attribute y
print(my_point)
print(type(my_point))

1.0 0,5,1 <type 'Point3d'>

Geometry Visualization

Geometry classes bind geometry functions as methods. Visualization classes provide mechanisms for displaying the geometry.

1. COMPAS Geometry and Artist

nFor a point object in COMPAS, it geometry class is compas.geometry.Point, and the corresponding visualization class, for example, in plotter, is compas_plotters.artists.PointArtist. The PointArtist object takes care of all the visualization attributes of the point, such as color, size, etc. The artist is always relevant to the graphical software. A point can be drawn in a Plotter with compas_plotters.PointArtist, a pop-up window when it is called in visual studio code. The same point can also be displayed in Rhino with a compas_rhino.PointArtist, which converts the object to Rhino geometry and data.

from compas.geometry import Point
from compas_plotters.artists import PointArtist
from compas_plotters import GeometryPlotter

my_point = Point(1, 1, 0)

pointartist = PointArtist(my_point)

plotter = GeometryPlotter(show_axes=True)
plotter.add(my_point, pointartist)
plotter.show()
from compas.geometry import Point
from compas_rhino.artists import PointArtist

my_point = Point(1, 1, 0)

artist = PointArtist(my_point, layer="Geometry::PointArtist")
artist.draw()

2. RhinoCommon, scriptcontext, rhinoscriptsyntax

What has happened under PointArtist in Rhino? The source code of PointArtist uses scriptcontext module, which creates a “bridge” between the geometry and the active Rhino document. Objects already in the document could be accessed and new ones could be added.

A Rhino Point3d could be directly visualized via the following code.

import scriptcontext
from Rhino.Geometry import Point3d

# create a point
my_point = Point3d(1, 1, 0)

# visualize the point in Rhino
scriptcontext.doc.Objects.AddPoint(my_point)
scriptcontext.doc.Views.Redraw()

rhinoscriptsyntax module contains various pre-written functions written in Python. It uses RhinoCommon. For example, AddPoint could create a point and visualize it.

import rhinoscriptsyntax as rs

# create a point and visualize it in Rhino
rs.AddPoint(1, 1, 0)

Last updated