GE4 - Furnitures

In this section we will see how to build a class “Furniture” in a GHPython component. This component will able to generate a list of furniture objects.


Basic class Furniture’s structure

Let’s consider the study case of bathrooms and let’s start by observing a wc in plan.

Although a furniture could be parameterized by multiple properties we retain just the most fondamental one for programming 2d planning:

So far so good. These are the properties of our Furniture Class that need to be fed as input data to our new GHPython component:

And here’s the basic skeleton of our class:

import Rhino.Geometry as rg

class Furniture:
    def __init__(self,
                 name,
                 access_area,
                 geo4display=[]):
        self.name = name
        self.plane = rg.Plane.WorldXY
        self.access_area = access_area
        self.geo4display = geo4display


Where, self.plane represents the origin of the furniture and by convinience we used the XY plane.


Furniture class’s methods

To what concerns the methods we are going to implement the following:

Duplicate method

⚠️As in the Roomclass this is a very fundamental method. For more info see the previous chapter.

def Duplicate(self):
    furniture_copy = Furniture(name=self.name,
                                access_area=self.access_area.DuplicateCurve()
                                )
    furniture_copy.plane = rg.Plane(self.plane)
    furniture_copy.geo4display = [g.Duplicate() for g in self.geo4display]
    
    return furniture_copy

Transform method

⚠️ Similarly to the method Duplicate() also Transform() will give you wrong results if you do not go through each geometric property of your class and apply that transformation.

def Transform(self, xform):
    self.plane.Transform(xform)
    self.access_area.Transform(xform)
    for geo in self.geo4display:
        geo.Transform(xform)

__str__() method

This method represent the Python class object as a string.

def __str__(self):
        return self.name


If we try to output( a = furniture) or print (print(furniture)) our object without this method this is what we get:

The output is rather criptic.. In reality this makes sense for python since it shows us where the newly created class object has been allocated in memory. But once we implemented our __str__() method here’s the result:

Not bed right!? This is very useful as a debug tool since you can better read and understand results from your GHPython component.


The final code

If we add everything together and add some docstrings for documentation and clarity here’s the final code

import Rhino.Geometry as rg

class Furniture:
    def __init__(self,
                 name,
                 access_area,
                 geo4display=[]):
        """
            __init__(self, ...) is the constructor definition that you need to call for instantiate a class.
            
            :param name: (str) the name of the furniture
            :param vec_x: (Rhino.Geometry.Vector3d) the vector x
            :param vec_y: (Rhino.Geometry.Vector3d) the vector y
            :param origin: (Rhino.Geometry.Point3d) origin of the furniture
            :param access_area: (Rhino.Geometry.Curve) contour indicating the access area to the furniture
            :param geo4display: (List(Rhino.Geometry.GeometryBase)) the drawings of the object to be displayed
            
            :return: (Furniture) the furniture object
        """
        self.name = name
        self.plane = rg.Plane.WorldXY
        self.access_area = access_area
        self.geo4display = geo4display
    
    def Duplicate(self):
        """
            Copy all the properties inside the class. In C# for Rhino you need to do this for objects other
            than structs (e.g. Point3D, Vectors, etc). All classes need to be copied (e.g. Curve, Line).
            In (iron)python Rhino things are a bit more complicated. In fact you need to copy all objects (even
            structs, e.g. Point, Vector, Box), these types need to be copied with a new constructor. Class objects
            can be duplicated with the traditional .Duplicate() method. The reason why is that EVERYTHING is an OBJECT
            in Python and they are always passed as a REFERENCE.
            
            :return: (Furniture) a new object with duplicated properties (geometries).
        """
        furniture_copy = Furniture(name=self.name,
                                   access_area=self.access_area.DuplicateCurve()
                                   )
        furniture_copy.plane = rg.Plane(self.plane)
        furniture_copy.geo4display = [g.Duplicate() for g in self.geo4display]
        
        return furniture_copy
    
    def Transform(self, xform):
        """
            Transform all the properties (geometries) inside the class.
            
            :param xform: (Rhino.Geometry.Transform)the transformation to be applied
        """
        self.plane.Transform(xform)
        self.access_area.Transform(xform)
        for geo in self.geo4display:
            geo.Transform(xform)

    def __str__(self):
        """
            __str__ is a special method, like __init__ , that is supposed to return a string 
            representation of an object. This method returns the string representation of the 
            object. This method is called when print() or str() function is invoked on an object.

            :return: (str) the string you decided to return when the object is called
        """
        return self.name

if __name__ == "__main__":
    furniture = Furniture(name=i_name,
                          access_area=i_access_area,
                          geo4display=i_geo4display)
    a = furniture


And here’s our little scheme to resume the Furniture class’s structure:


*The extra mile

What would you do if you had to create multiple Furniture classes, let’s say for a bathtub, a chair, a sink, etc.?

Would you copy and paste the GHPython component we just did? What would be the problem with this?

🦊 Be lazy like a fox and take the better out of grasshopper and python. You can use trees and lists like this:

Now we got everything we need to build our next and final class Go to the next tutorial.