﻿import math
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.DB import *

doc = __revit__.ActiveUIDocument.Document

t = Transaction(doc,'undo')

t.Start()

#This script creates a 3D Supershape using lofted segments.
#Copyright (c) 2011, Nathan Miller, The Proving Ground
#The Proving Ground,  http://nmillerarch.blogspot.com

#3D supershape parameters
m = 15.97
a = 0.0486
b = 5.36
n1 = .2624
n2 = -.29
n3 = 1.5

ustep = 50
vstep = 50

piA = math.pi *.5
piB = math.pi *.5

#Because curves will eventually become absorbed into the loft form, it is important to create two sets of the same curve.
#This method is a workaround for being unable to connect all curves into one single lofted shape.

#Create ReferenceArrayArrays
refarar1 = ReferenceArrayArray()
refarar2 = ReferenceArrayArray()

#The math part...
theta = -piA
while (theta <= piA):
	phi = -piB/2
	r1 = 1/(((abs(math.cos(m*theta/4)/a))**n2+(abs(math.sin(m*theta/4)/b))**n3)**n1)
	refptsarr = ReferencePointArray()
	while (phi <= piB/2):
		r2 = 1/(((abs(math.cos(m*phi/4)/a))**n2+(abs(math.sin(m*phi/4)/b))**n3)**n1)
		x = r1 * math.cos(theta) * r2 * math.cos(phi)
		y = r1 * math.sin(theta) * r2 * math.cos(phi)
		z = r2 * math.sin(phi)
		myXYZ = XYZ(x,y,z)
		refptsarr.Append(doc.FamilyCreate.NewReferencePoint(myXYZ))
		
		#Increment phi
		phi = phi + (piB/2 / (vstep/2))
	#Increment theta
	theta = theta + (piA / (ustep/2))
	
	
	#Comment out everything below to quickly test the point cloud shapes
	#Surface geometry takes a long time to generate.... needs to be faster!
	
	#create the curves
	crv1 = doc.FamilyCreate.NewCurveByPoints(refptsarr)
	crv2 = doc.FamilyCreate.NewCurveByPoints(refptsarr)
	
	#create reference arrays
	refar1 = ReferenceArray()
	refar2 = ReferenceArray()
	
	#Append curve refences to the reference arrays
	refar1.Append(crv1.GeometryCurve.Reference)
	refar2.Append(crv2.GeometryCurve.Reference)
	
	#Append ReferenceArrays to ReferenceArrayArrays
	refarar1.Append(refar1)
	refarar2.Append(refar2)
	
#Get the number of curves stored in the ReferenceArAr.
refsize = refarar1.Size

#Loft pairs of curves together for a segmented surface.
for i in range(0,refsize-1):
	loftar = ReferenceArrayArray()
	loftar.Append(refarar1[i])
	loftar.Append(refarar2[i+1])
	
	doc.FamilyCreate.NewLoftForm(True, loftar)
	
t.Commit()

__window__.Close()
