anchor.diff:      ASet.custom (fun self ->
           let proj = gridProj.GetValue self
           let view = gridCam.GetValue self
  -        let set = data.Rasterize(CameraView.viewTrafo view, proj, 0.01)
  -
  -        let add = set |> Seq.filter (self.Content.Contains >> not) |> Seq.map Add |> Seq.toArray
  -        let rem = self.Content |> Seq.filter (set.Contains >> not) |> Seq.map Rem |> Seq.toArray
  -
  -        printfn "+%d / -%d" add.Length rem.Length
  +        let set = data.Rasterize(CameraView.viewTrafo view, proj, 0.005)
  +
  +        let viewProj = CameraView.viewTrafo view * Frustum.projTrafo proj
  +
  +        let add = set |> Seq.filter (self.Content.Contains >> not) |> Seq.map Add
  +        let rem = self.Content |> Seq.filter (set.Contains >> not) |> Seq.map Rem
   
           Seq.append add rem |> Seq.toList
       )
   
  -let boxes = nodes |> ASet.map (fun n -> Helpers.wireBox (Helpers.randomColor()) n.bounds)
  +let boxes = nodes |> ASet.map (fun n -> Helpers.box (Helpers.randomColor()) n.bounds)
   
   let attributeTypes =
       Map.ofList [
  
positive.code: // ===================================================================================
  // example usage
  // ===================================================================================
  let data = DummyDataProvider(GridCell(V3l.OOO, 4)) :> IDataProvider<_>
  
  [<AutoOpen>]
  module Camera =
  
negative.code:             let result = HashSet<Node<'a>>()
  
              x.Traverse(fun node ->
  //                let viewBox = 
  //                    node.bounds.ComputeCorners()
  //                        |> Array.map (fun p -> viewProj.Forward.TransformPosProj p)
  //                        |> Box3d
  //                
  
                  if node.bounds.IntersectsFrustum viewProj.Forward then
                      if node.inner then
                          let bounds = node.bounds
  
  //                        let nearPlanePoints =
  //                            bounds.ComputeCorners()
  //                                |> Array.map viewProj.Forward.TransformPosProj
  //                                |> Array.map Vec.xy
  //
  //                        let nearPlanePolygon =
  //                            Polygon2d(nearPlanePoints)
  //                                .ComputeConvexHullIndexPolygon()
  //                                .ToPolygon2d()
  //                                .ConvexClipped(Box2d(-V2d.II, V2d.II))
  
                          let depthRange =
                              bounds.ComputeCorners()
                                  |> Array.map view.Forward.TransformPos
                                  |> Array.map (fun v -> -v.Z)
                                  |> Range1d
  
  //                        let depthRange =
  //                            nearPlanePolygon.Points
  //                                |> Seq.choose (fun v -> 
  //                                    let p = viewProj.Backward.TransformPosProj(V3d(v, 0.0))
  //                                    let r = Ray3d(camLocation, Vec.normalize (p - camLocation))
  //                                    match bounds.Intersects(r) with
  //                                        | (true, t) -> 
  //                                            let vp = view.Forward.TransformPos (r.GetPointOnRay t)
  //                                            Some -vp.Z
  //                                        | _ -> None
  //                                   )
  //                                |> Seq.map (clamp frustum.near frustum.far)
  //                                |> Range1d
  
                          if depthRange.Max < frustum.near || depthRange.Min > frustum.far then
                              false
                          else
                              let projAvgDistance =
                                  abs (node.granularity / depthRange.Min)
  
                              if projAvgDistance > wantedNearPlaneDistance then
                                  true
                              else
                                  if not (result.Add node) then
                                      failwith "duplicate box"
                                  false
                      else
                          if not (result.Add node) then
                              failwith "duplicate box"
                          false
                  else
                      false
  