   run: ->
     @running = true
     @go()
+  tp: ( x, y, minDistance, distance ) ->
+    p = @trigPool.pop() || new TrigPair()
+    p.init( x, y, minDistance, distance )
+    p
   # calculate and store the geometric relationship between two things
   trig: ( t, o ) ->
     base = o.x - t.x
     height = o.y - t.y
-    tp = new TrigPair(base, height, @minDistance)
-    t.others[o.id] = tp
-    o.others[t.id] = tp.opposite()
+    ti = t.id
+    oi = o.id
+    t1 = t.others[oi]
+    t2 = o.others[ti]
+    @trigPool.push t1 if t1?
+    @trigPool.push t2 if t2? && !t2.tooFar
+    tp = @tp(base, height, @minDistance)
+    t.others[oi] = tp
+    o.others[ti] = tp.opposite(@)
   # finds the things within a particular distance of a reference thing and within a certain
   # wedge around the direction of the things movement
   # if the thing has a visual angle of 1, or the thing is motionless, all things within the distance are returned

  vector: (magnitude) ->
    [ @width * magnitude, @height * magnitude ]
  # generates the counterpart of @ TrigPair after a 180 degree rotation
  opposite: ->
    return @ if @tooFar
    op = new TrigPair( -@sine, -@cosine, null, @distance )
    op.width = -@width
    op.height = -@height
    op

    @height = @canvas.height
    @maxDim = Math.max @width, @height
    @things = []
    @trigPool = []
    @dotCache = {}
    @idBase = 0
    @tick   = 0
