“””
##########################################################
script written by Luis Felipe Paris & Ezio Blasetti
script version Nov. 20, 2012
#########################################################
“””
import rhinoscriptsyntax as rs
import random
class machine():
def __init__(self,PTA,CRVS,DIST):
####MAX DIST####
self.maxDist = DIST
####CLOSEST POINT###
minDist = 5000000000000000000 #large number
for crv in CRVS:
if crv is not None:
t = rs.CurveClosestPoint(crv, PTA)
clPt = rs.EvaluateCurve(crv,t)
dist = rs.Distance(PTA, clPt) #distance to closest point on each curve
if dist < minDist: #if distance is smaller than last one
minDist = dist #set minDist to this one
clPt = clPt #set closest pt to this one
####POINT B####
vec = rs.VectorCreate(PTA,clPt)#vector to closest point
vec = rs.VectorUnitize(vec)
zVec = rs.VectorCreate([0,0,1],[0,0,0])#Unit Z Vector \\NOT NECESSARY FOR 3D
trans = rs.VectorRotate(vec,90,zVec)
PTB = rs.CopyObject(PTA,trans) #end point for line
####################
self.ptsA = [rs.PointCoordinates(PTA)] #list of points a
self.idsA = [PTA] #list of ids a
self.ptsB = [rs.PointCoordinates(PTB)] #list of points b
self.idsB = [PTB] #list of ids b
self.vecs = [vec] #list of direction vectors
self.trailPts = [PTA] #list of trail points
self.trails = []
self.boundsCount = [] #empty list for number of times is far from start point
####################
def reflection(self,CRV,POS1,POS2,ID,SCALE):
scaleR = SCALE*2
scaleP = 2000000
#create intersection for point a
t = rs.CurveClosestPoint(CRV,POS1)
inx = rs.EvaluateCurve(CRV, t)
inxL = rs.AddLine(POS1, inx)#line to intersect
mirrorIntersections = rs.CurveCurveIntersection(inxL, CRV)#list of intersection results
rs.DeleteObject(inxL) #delete line
for mirrorInt in mirrorIntersections:
inxP = mirrorInt[3] #intersection point
inxT = mirrorInt[7] #parameter in CRV
delList = []
tan = rs.CurveTangent(CRV,inxT)#tangent vector
tan = rs.VectorAdd(tan, inxP)#tangent at curve
tan = rs.AddPoint(tan)#TANGENT ADD
delList.append(tan)#Delete List Add
zVec = rs.VectorCreate([0,0,1],[0,0,0])#Unit Z Vector \\NOT NECESSARY FOR 3D
nor = rs.RotateObject(tan,inxP,90,zVec,copy=True)#rotate 90 degrees to get normal
pt = rs.MirrorObject(ID,inxP,nor,copy=True)#mirror self using normal as plane info
delList.append(nor)#Delete List Add
delList.append(pt)#Delete List Add
refl = rs.AddLine(inxP, pt)#line to intersect
refl = rs.ScaleObject(refl,inxP,[scaleR,scaleR,scaleR])#scale
delList.append(refl)#Delete List Add
plane = rs.AddLine(POS1, POS2) #plane at direction of movement
midPt = rs.VectorAdd(POS1, POS2)#midPoint of plane //add and divide
midPt = rs.VectorDivide(midPt, 2)
plane = rs.ScaleObject(plane,midPt,[scaleP,scaleP,scaleP])#scale plane to ensure intersection
delList.append(plane)#Delete List Add
reflIntersections = rs.CurveCurveIntersection(refl,plane)#list of intersection results
if type(reflIntersections) == type([]):
reflInt = rs.AddPoint(reflIntersections[0][3])#resulting reflection
else: reflInt = rs.CurveEndPoint(refl)
rs.DeleteObjects(delList)
return reflInt
def test(self,CRVS,TRAILS,FCT,MAX,INDEX,TRAILINDEX,RECU,INT):
####PTS 0####
ptA0 = self.ptsA[-1] #assign point a info (last item on list)
idA0 = self.idsA[-1]
ptB0 = self.ptsB[-1] #assign point b info (last item on list)
idB0 = self.idsB[-1]
####SEPARATION####
if RECU > 0:
SEPM = self.separationMirror(CRVS,INDEX,RanOfVis)#find closest Point
if SEPM is None: SEPM = [0,0,0]
SEPS = self.separationSelf(CRVS,INDEX)#find closest Point
if SEPS is None: SEPS = [0,0,0]
####COHESION####
if RECU > 0:
COH = self.cohesion(TRAILS,TRAILINDEX,RanOfVis)
if COH is None: COH = [0,0,0]
if INT < div:
COH = rs.VectorReverse(COH)
####PTS 1####
CRV = self.findClosestCurve(CRVS,INDEX,RECU)#find closest Curve
mirrorVec = self.vecToRefl(idA0, CRV)#vector to point of reflection in mirror
scale = rs.VectorLength(mirrorVec)
ptA1 = self.reflection(CRV, ptA0, ptB0, idA0, scale)#reflection point of point a
ptB1 = self.reflection(CRV, ptB0, ptA0, idB0, scale) #reflection point of point b
adjust = 1.00 #adjust for scaling (in case of no intersection)
if rs.IsPoint(ptA1): ptA1=ptA1
else:
ptA1=rs.AddPoint(ptA1)
adjust = adjust-0.25
if rs.IsPoint(ptB1): ptB1=ptB1
else:
ptB1=rs.AddPoint(ptB1)
adjust = adjust-0.25
####DISTANCE TESTS####
dInc = rs.Distance(ptA0,ptB0) #distance point a to point b
dRefl = rs.Distance(ptA1,ptB1)*adjust #distance in reflected points
Test1 = rs.Distance(ptB0,ptA1) #test to check for inversion
Test2 = rs.Distance(ptA0,ptA1) #test to check for inversion
dStart = rs.Distance(self.ptsA[0],ptA0) #distance from start point
rs.DeleteObject(ptA1) #delete reflected points
rs.DeleteObject(ptB1) #delete reflected points
ratio = dRefl/dInc #ratio of distortion
ratio = 0.00000001 + ratio*FCT #scaling
if ratio > MAX*FCT: ratio = MAX*FCT
####TRANSLATION####
trans = rs.VectorCreate(ptB0, ptA0)#translation vector
if unitizeCurrent == True: ##
trans = rs.VectorUnitize(trans)
if scaleCurrent == True: ##
trans = rs.VectorScale(trans,ratio)
vec = self.vecs[-1] #direction vector from previous translation
if unitizePrevious == True: ##
vec = rs.VectorUnitize(vec)
trans = rs.VectorAdd(vec,trans)
if unitizeResult == True: ##
trans = rs.VectorUnitize(trans)
####DISTORTION STATES####
#if dInc == dRefl: print “true reflection”
if dInc < dRefl:
#print “augmented reflection”
trans = rs.VectorSubtract(trans, rs.VectorScale(rs.VectorUnitize(mirrorVec), ratio))
if dInc > dRefl:
#print “reduced reflection”
trans = rs.VectorAdd(trans, rs.VectorScale(rs.VectorUnitize(mirrorVec), ratio))
if rs.VectorLength(trans) > maxMove:
trans = rs.VectorUnitize(trans)
trans = rs.VectorScale(trans, maxMove)
if Test1>Test2:
#print “inversion”
trans = rs.VectorReverse(trans)
if dStart >= self.maxDist:
#trans = -1*trans
self.boundsCount.append(1)
####SUM VECTORS####
if RECU > 0:
mag = rs.VectorLength(trans)
if rs.VectorLength(SEPM) > mag:
SEPM = rs.VectorUnitize(SEPM)
SEPM = rs.VectorScale(SEPM,mag)
if rs.VectorLength(SEPS) > mag:
SEPS = rs.VectorUnitize(SEPS)
SEPS = rs.VectorScale(SEPS,mag)
if rs.VectorLength(COH) > mag:
COH = rs.VectorUnitize(COH)
COH = rs.VectorScale(COH,mag)
trans = rs.VectorAdd(SEPM, trans)
trans = rs.VectorAdd(SEPS, trans)
trans = rs.VectorAdd(COH, trans)
trans = rs.VectorUnitize(trans)
trans = rs.VectorScale(trans, mag)
###################
self.vecs.append(trans)
newPtA = rs.VectorAdd(ptA0, trans)
self.ptsA.append(newPtA)
tp = rs.AddPoint(newPtA)
self.idsA.append(tp)
newPtB = rs.VectorAdd(ptB0, trans)
self.ptsB.append(newPtB)
self.idsB.append(rs.AddPoint(newPtB))
self.trailPts.append(tp)
###################
def makeTrails(self,INDEX,RECU):
if len(self.trailPts)>2:
myTrailID = rs.AddInterpCurve(self.trailPts) #Control Pts Curve Trajectory
self.trails.append(myTrailID)
return myTrailID
def vecToRefl(self, PT1, CRV):
t = rs.CurveClosestPoint(CRV, PT1)
clPt = rs.EvaluateCurve(CRV,t)
vec = rs.VectorCreate(clPt, PT1)
return vec
def findClosestCurve(self, CRVS, INDEX, RECU):
mycoord = self.ptsA[-1] #position at last item of ptsA list
minDist = 5000000000000000000 #large number
for crv in CRVS:
if crv is not None:
if RECU > 0 and crv is not CRVS[INDEX]:
t = rs.CurveClosestPoint(crv, mycoord)
clPt = rs.EvaluateCurve(crv,t)
dist = rs.Distance(mycoord, clPt) #distance to closest point on each curve
if dist < minDist: #if distance is smaller than last one
minDist = dist #set minDist to this one
closestCurve = crv #set closest crv to this one
t = rs.CurveClosestPoint(crv, mycoord)
clPt = rs.EvaluateCurve(crv,t)
dist = rs.Distance(mycoord, clPt) #distance to closest point on each curve
if dist < minDist: #if distance is smaller than last one
minDist = dist #set minDist to this one
closestCurve = crv #set closest crv to this one
return closestCurve
def separationMirror(self,CRVS, INDEX, RANGE):
closestPt = 0
mycoord = self.idsA[-1] #position at last item of ptsA list
minDist = RANGE
for crv in CRVS:
if crv is not None:
if crv is not CRVS[INDEX]:
t = rs.CurveClosestPoint(crv, mycoord)
clPt = rs.EvaluateCurve(crv,t)
dist = rs.Distance(mycoord, clPt) #distance to closest point on each curve
if dist < minDist: #if distance is smaller than last one
minDist = dist #set minDist to this one
closestPt = clPt #set closest point to this one
if closestPt != 0:
vec = rs.VectorCreate(mycoord, closestPt)
vec = rs.VectorScale(vec, sepMFct)
return vec
else: return None
def separationSelf(self,CRVS, INDEX):
mycoord = self.idsA[-1] #position at last item of ptsA list
minDist = 5000000000000000000 #large number
for pt in self.idsA:
if pt is not mycoord:
dist = rs.Distance(mycoord, pt)#distance to each previous point
if dist < minDist: #if distance is smaller than last one
minDist = dist #set minDist to this one
closestPt = pt #set closest point to this one
vec = rs.VectorCreate(mycoord, closestPt)
vec = rs.VectorScale(vec, sepSFct)
return vec
def cohesion(self,TRAILS,TRAILINDEX,RANGE):
closestPt = 0
mycoord = self.ptsA[-1] #position at last item of ptsA list
minDist = RANGE #large number
for crv in TRAILS:
if crv is not TRAILS[TRAILINDEX]:
t = rs.CurveClosestPoint(crv, mycoord)
clPt = rs.EvaluateCurve(crv,t)
dist = rs.Distance(mycoord, clPt) #distance to closest point on each curve
if dist < minDist: #if distance is smaller than last one
minDist = dist #set minDist to this one
closestPt = clPt #set closest point to this one
if closestPt != 0:
vec = rs.VectorCreate(closestPt, mycoord)
vec = rs.VectorScale(vec, cohFct)
return vec
else: return None
def delete(self):
self.idsA.pop(0)
self.trails.pop()
rs.DeleteObjects(self.idsA)
rs.DeleteObjects(self.idsB)
rs.DeleteObjects(self.trails)
def Main():
rs.EnableRedraw(drawOn)
baseListLen = len(reflcrvs)
####TRAILS####
trails = []
####MACHINE CREATION####
myMachines = []
for i in range(len(startPos)):
myMachines.append(machine(startPos[i],reflcrvs, dist))
####RUN TEST####
count = 0
interval = 0
for i in range(int(recurrence)):
j = 0
for m in myMachines:
#print j
if len(m.boundsCount) > limit: break
k = baseListLen+j
m.test(reflcrvs,trails,amplitude,max,k,j,i,interval)
trajectory = m.makeTrails(i,int(recurrence))#append resulting trajectory
if i == 0:
reflcrvs.append(trajectory)#append resulting trajectory
trails.append(trajectory)
reflcrvs[k] = trajectory
trails[j] = trajectory
j = j + 1
interval = count % divisor
count = count +1
################
for m in myMachines:
m.delete()
################
#################################################################################
drawOn = False
startPos = rs.GetObjects(“Select Machine Locations”, rs.filter.point, preselect=True) #Initial Position
reflcrvs = rs.GetObjects(“Select Reflective Curves”, rs.filter.curve) #Mirrors
####AMPLITUDE####
amplitude = 24 #Amplitude Scale
max = 10.0 #Max Amplitude
####BOUNDS####
limit = 500 #limit to kill
dist = 10000.0 #distance to kill
####SCALING FROM REFLECTION####
scaleCurrent = True
unitizeCurrent = False
unitizePrevious = True
unitizeResult = True
####SEPARATION & COHESION####
cohFct = 0.1
sepSFct = 0.3
sepMFct = 0.7
####GLOBALS######################################################################
recurrence = 2000
maxMove = 10.0
RanOfVis = 100.0
divisor = RanOfVis/maxMove*10
div = divisor/5
#################################################################################
Main()
“””
##########################################################
script written by Luis Felipe Paris & Ezio Blasetti
script version Nov. 12, 2012
#########################################################
“””
import rhinoscriptsyntax as rs
import math
import random
fx = 1.50 #Global Variable for Scaling
def vertOffset(paths,spacing,max,fct,fct2,fct3,recu,per):
for path in paths: #loop through paths
pLen = rs.CurveLength(path) #length of path
nPoints = int(pLen/spacing) #divide by distance
crvs = [] #empty curves list
crvLns = [] #empty length list
crvs.append(path) #add path to curves list
crvLns.append(rs.CurveLength(path)) #add length to length list
for j in range(recu): #loop for a given number of curves to produce
crv = crvs[j] #get curve
initcrv = crvs[0] #original curve
crvLen = crvLns[j] #get curve length
pts = [] #empty points list
curvRadiiList = curvPercentage(crv,nPoints) #get curve curvatures radii list
for i in range(nPoints): #loop through points in curve
domain = rs.CurveDomain(crv) #get curve domain
t = domain[0] + i*(domain[1]-domain[0])/nPoints #scale parameter to evaluate to domain
##4 PARAMETERS: VEC, NORMAL, RADIUS, PERCENTAGE
vec = rs.CurveCurvature(crv,t)[4]#curvature vector
vec = rs.VectorScale(vec,1/fx)
tan = rs.CurveTangent(crv, t)
normal = rs.VectorRotate(tan, 90, [0,0,1])#normal vector
curvRad = rs.CurveCurvature(crv, t)[3]#curvature radius
index = curvRadiiList.index(curvRad)+1
curvRad = curvRad/fx
curvPer = index/len(curvRadiiList)#curvature percentage
##### FISHNET #####
if curvPer >= per: #slider test
##SCALING
vec = rs.VectorScale(vec, max/2)
l = rs.VectorLength(vec)
#for Height
if l > max:
vec = rs.VectorUnitize(vec)
vec = rs.VectorScale(vec, max)
l = rs.VectorLength(vec)
#for CurvatureVector
if l > fct2:
vec = rs.VectorUnitize(vec)
vec = rs.VectorScale(vec, fct2)
##GLOBAL NORMAL FROM ORIGINAL CURVE
initdomain = rs.CurveDomain(initcrv)
initT = initdomain[0] + i*(initdomain[1]-initdomain[0])/nPoints
globalNormal = rs.VectorRotate(rs.CurveTangent(initcrv, initT), 90, [0,0,1]) #normal at initcrv
##CURVATURE RADIUS AT PREVIOUS & NEXT T
t0Rad = 0
t2Rad = 0
if i > nPoints-1 and i < 0:
t0 = domain[0] + (i-1)*(domain[1]-domain[0])/nPoints
t0Rad = rs.CurveCurvature(crv, t)[3]#curvature radius at t0
t2 = domain[0] + (i+1)*(domain[1]-domain[0])/nPoints
t2Rad = rs.CurveCurvature(crv, t)[3]#curvature radius at t2
if curvRad – t2Rad > curvRad – t0Rad:
globalNormal2 = rs.VectorAdd(globalNormal,rs.VectorReverse([normal[0],normal[1],globalNormal[2]]))
globalNormal2 = rs.VectorUnitize(globalNormal2)
if globalNormal2:
globalNormal2 = rs.VectorScale(globalNormal2, fct)
globalNormal = globalNormal2
globalNormal = rs.VectorScale(globalNormal, fct*max*math.sqrt(j*i/nPoints)) #global normal scaling
globalNormal = rs.VectorScale(globalNormal, curvPer+0.01)
temp = rs.EvaluateCurve(crv,t)
temp = rs.VectorAdd(temp,vec)
temp = rs.VectorAdd(globalNormal, temp)
pts.append([temp[0],temp[1],temp[2]+l])
##### CURVATURE JITTER #####
else:
curvRad = curvRad*fct3
normal = rs.VectorUnitize(normal)
normal = rs.VectorScale(normal, curvRad)
if rs.VectorLength(normal) > fct3:
normal = rs.VectorUnitize(normal)
normal = rs.VectorScale(normal, fct3)
if rs.VectorLength(normal) < -1*fct3:
normal = rs.VectorUnitize(normal)
normal = rs.VectorScale(normal, -1*fct3)
h = spacing*(1-curvPer)/max
if h < 0: h = 0
pt = rs.EvaluateCurve(crv, t)
pt = rs.VectorAdd(pt, normal)
pts.append([pt[0],pt[1],pt[2]+h])
result = rs.AddInterpCurve(pts)
crvLns.append(rs.CurveLength(result))
crvs.append(result)
“””
####MESHING####
vtxs = []
fvtxs = []
colvtxs = []
nPoints = 2000
for i in range(len(crvs)-1):
for j in range(nPoints):
t = domain[0] + j*(domain[1]-domain[0])/nPoints
temp1 = rs.EvaluateCurve(crvs[i],t)
temp2 = rs.EvaluateCurve(crvs[i+1],t)
vtxs.append(temp1)
vtxs.append(temp2)
ran = 40
start = 5
h1 = ((((i+1)/recu)+((j+1)/nPoints))/2*ran)+start
h2 = ((((i+2)/recu)+((j+1)/nPoints))/2*ran)+start
c1 = rs.ColorHLSToRGB([h1,127,255])
c2 = rs.ColorHLSToRGB([h2,127,255])
colvtxs.append(c1)
colvtxs.append(c2)
if j>0:
e = len(vtxs)
fvtxs.append([e-4,e-2,e-1,e-3])
rs.AddMesh(vtxs,fvtxs,vertex_colors=colvtxs)
“””
def curvPercentage(crv,nPoints):
lList = []
domain = rs.CurveDomain(crv)
for i in range(nPoints):
t = domain[0] + i*(domain[1]-domain[0])/nPoints
r = rs.CurveCurvature(crv, t)[3] #radius
lList.append(r)
lList.sort()
return lList
def Main():
paths = rs.GetObjects(“Select Curves”, rs.filter.curve, preselect=True)
“””
##relation should be length of curve/10^2 for scaling and of curve/10^5 for factors##
i.e. len:1000mm & 7 Peaks
fx=1
divLen = 5
yOffset = 12
factor1 = 0.01
factor2 = 0.08(5)
“””
####TUNING SCALE####
divLen = 2/fx #a point every __ units(i.e. mm)
yOffset = 5/fx #vertical height offset
####CONTROL####
factor1 = 0.04/fx #factor for: FISHNET: GlobalNormal (Overhang)
factor2 = 1/fx #factor for: FISHNET: Curvature Vector (Jitter)
factor3 = 0.05/fx #factor 2 for: JITTER: Normal (Loops); Usually good when == factor1*5
####NUMBER####
recurrence = 5 #number of curves
####SLIDER####
percentage = 0.6 #split percentage point between FISHNET(-0.0001) to JITTER(1.0001)
vertOffset(paths,divLen,yOffset,factor1,factor2,factor3,recurrence,percentage)
Main()