Introduction: Project3_LED_shade

About: PhD student at University of California, Santa Barbara, in the Expressive Computation Lab (

This project aimed to create a 3d lamp shade. I used a 5 mm LED as my lamp. I began by adding attraction and repulsion points to the starter code provided by Jennifer Jacobs. I printed a version of this alteration. Then I wanted to have a modular lamp stand that would resemble a virus or a spider. I coded the shape in Python and printed the result. I finished by combining both designs together.

Step 1: Making the Lamp Fitting

The first step consisted in making a fitting for my LED and printing it to make sure that it works. The LED has a diameter of 5 mm and an indent of 5.9 mm diameter. So I started by printing a fitting of exactly 5 mm diameter, but the circular shape made by the Ender Pro 3 was not perfect and I couldn't fit the LED inside. So I reprinted a fitting of 6 mm diameter. The LED could fit without passing through it. I kept that measurement for the following designs.

Step 2: Lampeshade With Distortion

This first designing iterates from Jennifer Jacobs' parametric surface code. I added two vectors to the paramsurf function to calculate the combined effect of attractors and repulsers on each point of the surface in relation to distance.

def paramsurf(u, v):

r =(10+0.5*math.cos(10*u))

x = math.cos(u) * math.cos(v)*r y = math.sin(u) * math.cos(v)*r z = math.sin(v)*r p = rs.CreateVector(x,y,z) p2 = rs.CreateVector(x,y,z) for i in range(0, len(at)): pat = rs.CreateVector(at[i].X,at[i].Y,at[i].Z) dist = (pat-p).Length p2 += pat/math.sqrt(dist)*atq for j in range(0, len(rep)): pat = rs.CreateVector(rep[j].X,rep[j].Y,rep[j].Z) dist= (pat-p).Length p2 -= pat/math.sqrt(dist)*atq return geom.Point3d(p2[0], p2[1], z)

I printed my design with a translucent filament, which allows to see the brightness of the LED through the material.

Step 3: Spider LED Support in Grasshopper

This following design aimed to create a LED stand/shade that would be modular and that would look like an hybrid between a spider and a virus.

The first function creates am ellipse shape out of points in Rhino.

import rhinoscriptsyntax as rs
import Rhino.Geometry as geom import Rhino.Geometry.BezierCurve as be import Rhino.Collections as rc import Rhino import math import random offset = 30

def baseCircle(rr): pts = [] cs = [] nb = 11 theta = 2*math.pi/nb t = theta for i in range (0,nb): r = rr*math.sqrt(1/(1*math.pow(math.cos(t),2) + 2*math.pow(math.sin(t),2))) x = r*math.cos(t) y = r*math.sin(t) z = 0 p = geom.Point3d(x-offset,y,z) t += theta pts.append(p) return pts

Then I made a second function that creates an inner circle following the same angle of the previous points and located higher along the Z-axis.

def topCircle(tp): pts2 = [] cs = [] nb = 11 theta = 2*math.pi/nb t = theta for i in range (0,nb): r = 70*math.sqrt(1/(1*math.pow(math.cos(t),2) + 2*math.pow(math.sin(t),2))) x = r*math.cos(t) y = r*math.sin(t) z = 0 theta2 = math.atan(y/(x-offset)) if((x-offset) < 0): theta2+=math.pi x2 = 20*math.cos(theta2) y2 = 20*math.sin(theta2) p2 = geom.Point3d(x2,y2,tp.Z) t += theta pts2.append(p2) return pts2

The third function produces curves between the two previous series of points.

def addCurves(pts, pts2):
cs = [] for i in range(0, len(pts)): points = rc.Point3dList(5) points.Add(pts2[i].X, pts2[i].Y, pts2[i].Z) points.Add(1.5*pts[i].X/2, 1.5*pts[i].Y/2, pts2[i].Z) points.Add(pts[i].X, pts[i].Y, pts2[i].Z) points.Add(pts[i].X, pts[i].Y, pts[i].Z)

nc = geom.NurbsCurve.Create(False, 3, points) cs.append(nc) return cs

And the last required function simply creates straight lines between two series of points.

def straightLine(pts, pts2):
cs = [] for i in range(0, len(pts)): c = [] c.append(pts[i]) c.append(pts2[i]) curve = rs.AddCurve(c) cs.append(curve) return cs

The last step is to combine these function to create the ellipse shape for the bottom of the legs (1), the two higher circles at the center of the piece that constitute the base of the legs that connect to the central piece (2, 3), the two series of curves that go from each central circle to the outer ellipse of points (4, 5), the straight lines that go from one inner circle to the other to create the thickness of the legs (6) and the loft surfaces between 4 and 5 (7).

pts = baseCircle(70) pts1 = baseCircle(70.5) pts2 = topCircle(top) pts3 = topCircle(ttop) curves = addCurves(pts,pts2) curves2 = addCurves(pts1,pts3) lofts = [] for i in range (0, len(curves)): loft = rs.AddLoftSrf([curves[i],curves2[i]]) lofts.append(loft[0]) curves3 = straightLine(pts2,pts3) a = pts + pts1 b = pts2 + pts3 c = curves d = lofts

From there the only step left is to use the OffsetSurface component in grasshopper after the loft surfaces (d output). Et voilà for the legs!

I then made a circular central piece with a hole in its center to welcome the LED and I used a Difference boolean operation on each leg to create an opening at the base so that the leg could connect to the piece.

Step 4: Printing and Assembling the Virus/spider Lamp Stand

I printed the pieces flat on the Ender Pro 3 bed, which worked pretty well :)

Because the design is modular, I could actually play with it once printed. I ended up enjoying when some of the legs were pointing upward rather than downward. I printed enough legs so they didn't have to be all supporting the circular center.

Step 5: Documentation of the Virus/spider Lamp Stand

I explored how the virus/spider lamp stand looks like in different settings. The red LED seems definitely more venomous than the white one.

Step 6: Combining Both Designs

My final investigation was to combine both designs. The good thing in using the LED dimensions as the basic unit is that the prints fitted in one another. If this assignment was a Pokemon, this stage would be the last evolution: a carnivorous flower.