# Python: Centroid and Modules part 1

While I have been writing code for the DigiFab project Parallel Pleats, I started to redo my workflow in programming so it would fit better with the functionality of python. Coming from C++ I was not used to the simplicity in separating functions in different files like how python can. With this, and the fact that it never occurred to me that rhino had a built-in centroid module, I decided to attack both problems and write a post on it. If your only interested in the linking of multiple files check out Part 2

My first step was to figure out the math of the centroid from a polygon. While the math is pretty simple, I had a hard time finding the function written in python to easily grab. This made doing the code all that more fun (keeping in mind I had no idea about rhino internally, thanks Mark haha). The math can be broken into three main parts: find the area of the polygon, find the X centroid of the polygon, and find the Y centroid of the polygon.

To tackle the translation from math to python (within a modeling package) we first need to collect our thoughts and figure out what variables we need. First we look at the area function, which is needed to find the centroid.

**i = 0**

**for i in range(our_range)**

**crv_pt_count=rs.CurvePointCount(curve_sel)**

**i = 0**

**for i in range(crv_pt_count – 1):**

**crv_pts=rs.CurvePoints(curve_sel)**

i=0 for i in range(n-1): poly_area_sum=poly_area_sum + ( ( (crv_pts[i][0])*(crv_pts[i+1][1]) ) - ( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) area = ( (.5) * (poly_area_sum) )

To implement this in rhino, we use the built in functions mentioned previously. The entire function looks like this:

def Curve_Area(curve_sel): #Description: Calculates area of a polygon #Parameters: Takes in a curve #Returns: Area of Polygon #Notes: poly_area_sum=0 crv_pt_count=rs.CurvePointCount(curve_sel) n=crv_pt_count crv_pts=rs.CurvePoints(curve_sel) i=0 for i in range(n-1): poly_area_sum=poly_area_sum + ( ( (crv_pts[i][0])*(crv_pts[i+1][1]) ) - ( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) area = ( (.5) * (poly_area_sum) ) return area

Now that we know how to find the proper index and get the variables, we can easily do the centroid function:

#find Centroid sub X i=0 for i in range(n-1): cntrd_x=cntrd_x + ( ( (crv_pts[i][0])+(crv_pts[i+1][0]) )*( ( (crv_pts[i][0])*(crv_pts[i+1][1]) )-( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) ) #find Centroid sub Y, reset i to 0 i=0 for i in range(n-1): cntrd_y=cntrd_y + ( ( (crv_pts[i][1])+(crv_pts[i+1][1]) )*( ( (crv_pts[i][0])*(crv_pts[i+1][1]) )-( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) )

Like the Area function, at the end we need to do a few more manipulations to get the final result:

cent_area_var=( ( 1 / ( 6 *(crv_area) ) ) ) centroid_x = (cent_area_var) * (cntrd_x) centroid_y = (cent_area_var) * (cntrd_y) crv_centroid = [centroid_x,centroid_y,0]

With the beginning variable declarations the entire function looks like this:

def Curve_Centroid(crv_area, curve_sel): #Description: Calculates Centroid of Polygon #Parameters: Takes in the area of curve and the curve #Returns: x,y,z of curve centroid #Notes: cntrd_x=0 cntrd_y=0 crv_pt_count=rs.CurvePointCount(curve_sel) crv_pts=rs.CurvePoints(curve_sel) n=crv_pt_count #find Centroid sub X i=0 for i in range(n-1): cntrd_x=cntrd_x + ( ( (crv_pts[i][0])+(crv_pts[i+1][0]) )*( ( (crv_pts[i][0])*(crv_pts[i+1][1]) )-( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) ) #find Centroid sub Y, reset i to 0 i=0 for i in range(n-1): cntrd_y=cntrd_y + ( ( (crv_pts[i][1])+(crv_pts[i+1][1]) )*( ( (crv_pts[i][0])*(crv_pts[i+1][1]) )-( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) ) #Create centroid coordinate cent_area_var=( ( 1 / ( 6 *(crv_area) ) ) ) centroid_x = (cent_area_var) * (cntrd_x) centroid_y = (cent_area_var) * (cntrd_y) crv_centroid = [centroid_x,centroid_y,0]

So we have these two working functions, although if you observe carefully, we never call either function. So how do we use them? Well, thats part 2. Since the programming I have been doing for our team project involves me testing functions manually but will eventually be automated, I wanted to start creating scripts that are independent. This way I can pass a curve to a function and not worry about how that curve was found, ie. i can manually select the curve and pass it into my function, or I can have a different function get a curve, either way, I never need to touch my centroid.py file again.

#Centroid Module #Notes: x[i] can translate to x being crv_pts[i][0] while y is crv_pts[i][1] import rhinoscriptsyntax as rs def Centroid(curve_sel): #Description: Calculates centroid of polygon #Parameters: Takes in a Curve #Returns: Nothing #Notes: crv_area=Curve_Area(curve_sel) Curve_Centroid(crv_area, curve_sel) def Curve_Area(curve_sel): #Description: Calculates area of a polygon #Parameters: Takes in a curve #Returns: Area of Polygon #Notes: poly_area_sum=0 crv_pt_count=rs.CurvePointCount(curve_sel) n=crv_pt_count crv_pts=rs.CurvePoints(curve_sel) i=0 for i in range(n-1): poly_area_sum=poly_area_sum + ( ( (crv_pts[i][0])*(crv_pts[i+1][1]) ) - ( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) area = ( (.5) * (poly_area_sum) ) return area def Curve_Centroid(crv_area, curve_sel): #Description: Calculates Centroid of Polygon #Parameters: Takes in the area of curve and the curve #Returns: x,y,z of curve centroid #Notes: cntrd_x=0 cntrd_y=0 crv_pt_count=rs.CurvePointCount(curve_sel) crv_pts=rs.CurvePoints(curve_sel) print"Curve point count",crv_pt_count n=crv_pt_count #find Centroid sub X i=0 for i in range(n-1): cntrd_x=cntrd_x + ( ( (crv_pts[i][0])+(crv_pts[i+1][0]) )*( ( (crv_pts[i][0])*(crv_pts[i+1][1]) )-( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) ) #find Centroid sub Y, reset i to 0 i=0 for i in range(n-1): cntrd_y=cntrd_y + ( ( (crv_pts[i][1])+(crv_pts[i+1][1]) )*( ( (crv_pts[i][0])*(crv_pts[i+1][1]) )-( (crv_pts[i+1][0])*(crv_pts[i][1]) ) ) ) #Create centroid coordinate cent_area_var=( ( 1 / ( 6 *(crv_area) ) ) ) centroid_x = (cent_area_var) * (cntrd_x) centroid_y = (cent_area_var) * (cntrd_y) crv_centroid = [centroid_x,centroid_y,0] #Check if Rhino Is same, doesnt matter though, we will trust our math #Rhino gives different answer always but close enough rhino_centroid=rs.CurveAreaCentroid(curve_sel) print(rhino_centroid[0]) print(crv_centroid) #if rhino_centroid[0] != crv_centroid: # print"Centroid does not match with Rhino Internal Centroid" #rs.AddPoint(crv_centroid) #return crv_centroid

Check out the next part discussing separate files: Part 2