quadtree.frink

View or download quadtree.frink in plain text format



class Quadtree
{
   var left
   var right
   var top
   var bottom

   var data
   
   // An array of children
   var children
   
   // Construct a new Quadtree node.
   new[l, r, b, t] :=
   {
      left = l
      right = r
      top = t
      bottom = b

      children = undef
      data = undef
   }

   // Creates a child to go at the specified row and column.  Returns the
   // new child.
   createChild[row, column, value] :=
   {
      middle = (left + right) / 2
      if column == 0
      {
         l = left
         r = middle
      } else
      {
         l = middle
         r = right
      }

      middle = (top + bottom) / 2
      if row == 0
      {
         t = top
         b = middle
      } else
      {
         t = middle
         b = bottom
      }

      var child = new Quadtree[l,r,b,t]
      child.data = value

      if children == undef
         children = new array[]
      
      children@(row*2+column) = child    // Attach to tree

      return child
   }

   // Gets the value of the given child.
   getChild[index] :=
   {
      if children == undef
         return undef

      if index >= length[children]
         return undef
      else
         return children@index
   }

   // Gets the value of the given child at the row and column
   getChild[row, column] :=
   {
      getChild[row*2 + column]
   }

   // Deletes all children of the specified node.  The value is the value
   // that should be given to this node.
   deleteChildren[value] :=
   {
      children = undef
      data = value
   }

   // Deletes a single child of the node.  If the deleted node is the last
   // child, then this node takes on the value undef.
   deleteChild[index] :=
   {
      if children == undef
      {
         data = undef
         return
      }

      children@index = undef
      noValue = true
      len = length[children]
      for i = 0 to len-1
         if children@i != undef
            noValue = false

      if (noValue == true)   // Clean up the children array
      {
         data = undef
         children = undef
      }
   }

   // Returns true if this is a leaf node.
   isLeaf[] :=
   {
      if children == undef
         return true

      noValue = true
      len = length[children]
      for i = 0 to len-1
         if children@i != undef
            noValue = false

      return noValue
   }

   // Gets the data for the given node.
   getData[] := data

   // Sets the data for the given node.
   setData[newData] := data = newData

   // Make a Quadtree for the given graph, going to the specified depth.
   class makeQuadtree[l, r, b, t, equation, depth] :=
   {
      var child
      q = new Quadtree[l,r,b,t]
      q.setData["X"]
      q.subdivide[parseToExpression[equation], depth]
      return q
   }

   subdivide[expression, depth] :=
   {
      if (depth > 0 && data)
      {
         hMiddle  = (left + right) / 2
         vMiddle =  (top + bottom) / 2
         
         xs = [new interval[left, hMiddle], new interval[hMiddle, right]]
         ys = [new interval[vMiddle, top], new interval[bottom, vMiddle]]
         index = 0
         solutionFound = false
         for row = 0 to 1
         {
            y = ys@row
            for col = 0 to 1
            {
               index = row*2 + col
               x = xs@col
//               println["$x, $y"]
//             res = eval[equation]
               res = eval[expression]
               val = "X"
               if res or res == undef
               {
                  if res != true
                  {
//                     println[res]
                     val = "!"
                  }
                  v = createChild[row, col, val]
                     
                  solutionFound = true
                  //                  children@index = v
                  data = undef  // Force to be a non-leaf
                  v.subdivide[expression, depth-1]
               }
            }
         }

         if ! solutionFound
            deleteChildren[undef]
      }
   }

   // Plot the graph in text.
   textPlot[rows, cols] :=
   {
      vals = new array[]
      for i = 0 to rows         // One row padding
      {
         vals@i = new array[]
         for j = 0 to cols - 1
            vals@i@j = "."
      }

      xscale = cols / (right-left)
      yscale = rows / (top-bottom)
      privateTextPlot[vals, xscale, yscale, left, bottom]
      for i = rows-1 to 0 step -1
      {
         println[join["",vals@i]]
      }
   }

   // Private text plotter
   privateTextPlot[vals, xscale, yscale, gLeft, gBottom] :=
   {
      for row = 0 to 1
         for col = 0 to 1
         {
            c = getChild[row,col]
            if (c != undef)
            {
               if (c.isLeaf[] and c.data)
               {
                  for y = floor[(c.bottom - gBottom) * yscale] to floor[(c.top-gBottom) * yscale]
                  {
                     rr = vals@y
                     for x = floor[(c.left - gLeft) * xscale] to floor[(c.right-gLeft) * xscale]
                     {
                        rr@x = c.data
                     }
                  }
               } else
               {
                  c.privateTextPlot[vals, xscale, yscale, gLeft, gBottom]
               }
            }
         }
   }
}


n = Quadtree.makeQuadtree[-5, 5, -5, 5,"y PEQ 5 cos[x^2] sin[x]", 6]
//println[n]
n.textPlot[21,76]


View or download quadtree.frink in plain text format


This is a program written in the programming language Frink.
For more information, view the Frink Documentation or see More Sample Frink Programs.

Alan Eliasen was born 17649 days, 5 hours, 36 minutes ago.