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:
- name: right?
- access area (in purple): a bounding box indicating the area around the furniture occupied by the user for accessing or employing the furniture. It also indicates the overhaul encumbrance of the furniture.
- symbol: each symbol corresponds to a different furniture and it helps us recognizing them visually on the plan.
- origin: or anchor plane. It adds to the furniture a reference system.
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(self)
: we already know it from theRoom
method;Transform(self, xform)
: to apply transformation to our object;__str__(self)
: as a bonus, this will help us printing the object in, e.g. gh panels.
Duplicate method
⚠️As in the Room
class 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.