## Tuesday, April 24, 2012

### surface subdivision adjusted by curvature

this script does all we were shown in class+ a little extra something
it caculates the curvatures of the surface and shifts all the points closer to the point with the highest curvature.

import rhinoscriptsyntax as rs
import math

### get the surface, filter =8 ensures that only surfaces can be selected
base =rs.GetObject(message = "please select surface", filter= 8)

### find out the UV domains in order to scale later
uDom= rs.SurfaceDomain(base,0)
vDom= rs.SurfaceDomain(base,1)
uScale = uDom-uDom
vScale = vDom-vDom

### number if subdivisions
uDiv=10
vDiv=10

points = []
curvatures = []
UVs= []

for u in range(uDiv+1):
### we store the data in three matrixes with the same structure
### that way we can use the u and v indexes to find the right elements
uPoints =[]
uCurvatures = []
uUVs=[]
###u/uDiv provides a number between 0 to 1,
###multiplying it by uScale fits it to the surface domain, this works similiarly to the frange, but in  a different way
uP = u/uDiv*uScale
for v in range (vDiv+1):
vP = v/vDiv*vScale
pt = rs.EvaluateSurface(base,uP,vP)
uPoints.append(pt)
curv=rs.SurfaceCurvature(base,(uP,vP))
maxCurv = curv
### max curvature should always be a positive value
if maxCurv<0 : maxCurv=maxCurv*(-1)
uCurvatures.append(maxCurv)
uUVs.append((uP,vP))
### now we have all three matrixs assembeled
points.append(uPoints)
curvatures.append(uCurvatures)
UVs.append(uUVs)

tempMax =0
maxX=0
maxY=0
### this loop finds the indexes of the point with the maximum curvature
for x in range(1,uDiv):
for y in range(1,vDiv):
if curvatures[x][y]>tempMax:
tempMax = curvatures[x][y]
maxX=x
maxY=y

maxPoint= points[maxX][maxY]
### new matrix, again with the same structre, with the distance between all
### points and the point with the maximum curvature
distances =[]
for u in range (uDiv+1):
uDist=rs.Distance(maxPoint, points[u])
distances.append(uDist)

###parameters for the amount of shifting
moveDist = 3
power=.2

### in this loop we first change the UV values of the points (so they will always
### remain on the surface) and then we recalculate the points xyz values
for u in range(1,uDiv):
for v in range(1,vDiv):
if distances[u][v] > 0:
### uDir shows if the point is below or above the center point
### so we can tell which direction to shift the points
uDir = 0
vDir = 0
if maxX < u : uDir=(-1)
if maxX > u : uDir=1
if maxY < v : vDir = (-1)
if maxY >v : vDir = 1
### by using a combination of the moveDist and pow parameters the amount of move can be
### adjusted to fit the size of the surface and the sensitivity to the distance
newU = UVs[u][v]+uDir*(moveDist/math.pow(distances[u][v],power))
newV = UVs[u][v]+vDir*(moveDist/math.pow(distances[u][v],power))
UVs[u][v] = (newU,newV)
points[u][v] = rs.EvaluateSurface(base,newU,newV)

rs.EnableRedraw(False)

for i in range(uDiv):
for j in range(vDiv):