Finding Angle of Rotation on Randomly Rotated Shape

Hi there everyone :slight_smile:

So to preface I’m working entirely within RhinoPython and I’m attempting to align custom created randomly rotated shapes. To do this I’m trying to calculate the angle of rotation. One method I’ve been trying to implement involves; calculating the centroid of an object, then finding the point furthest from the centroid and using those two points to calculate the angle. But as of yet I haven’t been able to find a way to access the points of the custom shape (without resorting to RhinoScript to get them).

For testing I’m using the AddRectangle() method to create a shape of random size.

e.g. rs.AddRectangle(plane, size, size * 3) // Size being a random int

I would then add a planar surface to the shape and calculate the surface’s centroid.

But then I hit a snag in attempting to calculate a point to use to calculate the angle of rotation. I’ve done exhaustive research trying to find a function or anything to help me access the attributes of the rectangle or find the point through some other means but I’ve come up dry.

I’m not sure if my logic is incorrect or I’ve overlooked some function that has done exactly what I’m wanting. If anyone would help me get on the right path with this, it would be greatly appreciated! :slight_smile:

Cheers!

Update:

So I’ve gone back and tried it again. This time i’ve created two methods.

The first finds the furthest point of a rectangle (which I understand is all the points because they are equal, the rectangle is just a test shape). Here’s the code:

def findFarPt(shape):

# Gets the array of points from the shape
pointArr = rs.PolylineVertices(shape, 0)
arrLen = len(pointArr)

i = 0

# Holds the largest distance and index of point in array
dist = [0,0]
origin = [0,0,0]

while(i < arrLen):
    # Checks the distance of the current Point2D against the origin point
    # to see if has the greatest distance between the centroid 
    if(dist[0] < rs.Distance(origin, [pointArr[i][0],pointArr[i][1],0])):
        # Assign the new greatest distance
        dist[0] = rs.Distance(origin, [pointArr[i][0],pointArr[i][1],0])
        # Assign the index of the Point2D
        dist[1] = i
    i+=1
print "Farthest Point: (Dist: ", dist[0], ") ", pointArr[dist[1]]

# Returns point with the greatest distance
return pointArr[dist[1]]

The second code block attempts to find the angle of rotation. This is based on two factors: The centroid (When the shape is centred the co-ordinates are [0,0,0]) and the point furthest away from the centroid. Here’s the second block:

def calcRotation(farPt):

# Calculate angle of rotation in Radians
# Rotation = atan(x1 - x2 / y1 - y2)
rotationRad = math.atan((0 - farPt[0]) / (0 - farPt[1]));

# Converting radians into degrees
rad2deg = 180 / math.pi
rotationDeg = rotationRad * rad2deg

# If negative rotation, adjust angle
if(rotationDeg < 0):
    rotationDeg += 180
print "Rotation Rad: ", rotationRad
print "Rotation Deg: ", rotationDeg

return rotationDeg

My problem now is the rotation angle (in degrees) is wrong and when I rotate the rectangle, it doesn’t rotate back to an upright position.

E.g. The desired orientation of the rectangle is:

|||||
|||||
|||||
|||||

Again, thank you guys so much for your time :slight_smile:

I’m not sure I understand - you want to get the vertices of the rectangle without going through rs.PolylineVertices(), rs.CurvePoints() or something similar? You want to do this via RhinoCommon? Or is there something else you would like to do that I didn’t get…

–Mitch

RS should have an areacentroid method, either an all encompassing version or ones that will work on planar surfaces or planar curves solely.

I like the algorithm idea, should work for all sorts of shapes from lines to polysurfaces.

Doh! Thanks so much @Helvetosaur and @Ncik for the reply. I mustn’t have searched very hard since I hadn’t come across rs.PolylineVertices() which should have been immediately apparent to me that’s what I wanted.

Now I’ve run myself into a few more problems. I’ll update my original post.