@MarcusStrube
Amazing tip, many thanks!
@emilio
Super helpful, thanks!
I see now that reading and writing to the same list might be a bad idea. I gave your example a go and now it works pretty well.
The code still doesn’t return a perfect icosasphere with only equilaterial triangles, but its pretty close, especially for the rougher approximations. I have no idea how hard or easy that will be to achieve, but I’ll give it a try later.
In the meantime, here is the full python script if you feel like giving it a go
It takes an integer value for the level of recursion, and returns an icosasphere subdivided by that number:
import math
import Rhino
#Define function to shift a list in place
def shiftInPlace(l, n):
n = n % len(l)
head =l[:n]
l[:n] = []
l.extend(head)
return l
#Define a function to move points to the unit sphere
#Remove this bit if subdivision is beeing performed on another set of triangles than a icosasphere
def point2unitsphere(Point):
l = math.sqrt(Point[0] * Point[0] + Point[1] * Point[1] + Point[2] * Point[2])
return Rhino.Geometry.Point3d(Point[0]/l, Point[1]/l, Point[2]/l)
#Define function to draw the points of an icosahedron
def icosahedron():
t = ( 1 + math.sqrt(5)) / 2
points = []
polylines = []
for k in reversed(range(-2, 1)):
c = []
for i in reversed(range(-1, 2, 2)):
for j in range(-1, 2, 2):
c.append([j, t * i, 0])
for j in c:
points.append(point2unitsphere(shiftInPlace(j, k)))
polylines.append(Rhino.Geometry.Polyline([points[0], points[11], points[5], points[0]]))
polylines.append(Rhino.Geometry.Polyline([points[0], points[5], points[1], points[0]]))
polylines.append(Rhino.Geometry.Polyline([points[0], points[1], points[7], points[0]]))
polylines.append(Rhino.Geometry.Polyline([points[0], points[7], points[10], points[0]]))
polylines.append(Rhino.Geometry.Polyline([points[0], points[10], points[11], points[0]]))
polylines.append(Rhino.Geometry.Polyline([points[1], points[5], points[9], points[1]]))
polylines.append(Rhino.Geometry.Polyline([points[5], points[11], points[4], points[5]]))
polylines.append(Rhino.Geometry.Polyline([points[11], points[10], points[2], points[11]]))
polylines.append(Rhino.Geometry.Polyline([points[10], points[7], points[6], points[10]]))
polylines.append(Rhino.Geometry.Polyline([points[7], points[1], points[8], points[7]]))
polylines.append(Rhino.Geometry.Polyline([points[3], points[9], points[4], points[3]]))
polylines.append(Rhino.Geometry.Polyline([points[3], points[4], points[2], points[3]]))
polylines.append(Rhino.Geometry.Polyline([points[3], points[2], points[6], points[3]]))
polylines.append(Rhino.Geometry.Polyline([points[3], points[6], points[8], points[3]]))
polylines.append(Rhino.Geometry.Polyline([points[3], points[8], points[9], points[3]]))
polylines.append(Rhino.Geometry.Polyline([points[4], points[9], points[5], points[4]]))
polylines.append(Rhino.Geometry.Polyline([points[2], points[4], points[11], points[2]]))
polylines.append(Rhino.Geometry.Polyline([points[6], points[2], points[10], points[6]]))
polylines.append(Rhino.Geometry.Polyline([points[8], points[6], points[7], points[8]]))
polylines.append(Rhino.Geometry.Polyline([points[9], points[8], points[1], points[9]]))
return polylines
#subdivides a single triangular polyline into 4 smaller
def subdivide_triangle(polylines, recursionLevel):
#Define function to subdive a single closed triangular polyline to 4 smaller ones
def one2four(polyline):
p01 = point2unitsphere((polyline[0] + polyline[1]) / 2)
p12 = point2unitsphere((polyline[1] + polyline[2]) / 2)
p20 = point2unitsphere((polyline[2] + polyline[0]) / 2)
return [
Rhino.Geometry.Polyline([polyline[0], p01, p20, polyline[0]]),
Rhino.Geometry.Polyline([p20, p12, polyline[2], p20]),
Rhino.Geometry.Polyline([p01, polyline[1], p12, p01]),
Rhino.Geometry.Polyline([p01, p12, p20, p01])
]
def dividelist(polylines, recursionLevel):
if recursionLevel < 1: return polylines
result = []
for polyline in polylines:
result.extend(one2four(polyline))
if recursionLevel > 1:
result = dividelist(result, recursionLevel - 1)
return result
polylines = dividelist(polylines, recursionLevel)
return polylines
Icosahedron = icosahedron()
a = subdivide_triangle(Icosahedron, recursionLevel)