private void Animate(Data[] d) {
   if (frames == 0) stopwatch.Start();
   frames++;
   ShowStats();
  
   Vector3D unitY = new Vector3D(0.0, 1.0, 0.0);
   for (var index = 0; index < NumBoids; index++) {
     Data data = d[index];
     Transform3DGroup group = new Transform3DGroup();
     Vector3D velocity = data.velocity;
     velocity.Normalize();
     BoidModels[index].Transform = null;
     double theta = Math.Acos(Vector3D.DotProduct(velocity, unitY) / (velocity.Length * unitY.Length)) * (180.0/Math.PI);
     double len = data.velocity.Length;
     ScaleTransform3D s = new ScaleTransform3D(2.0, 2.0, 2.0);
     Vector3D vectord3 = new Vector3D(0.0, 1.0, 0.0);
     AxisAngleRotation3D rotation = new AxisAngleRotation3D(Vector3D.CrossProduct(vectord3, velocity), theta);
     RotateTransform3D rt = new RotateTransform3D(rotation);
     TranslateTransform3D tt = new TranslateTransform3D(data.position - data.velocity);
     group.Children.Add(s);
     group.Children.Add(rt);
     group.Children.Add(tt);
     BoidModels[index].Transform = group;
   }
   var delay = (int)this.FPS.Value; 
   //if (delay > 0) 
       System.Threading.Thread.Sleep(delay);
 }
 public void ProcessBoid(Data boid) {
   Vector3D vectord = boid.position - position;
   double num = Math.Acos(Vector3D.DotProduct(velocity, boid.position - position) / (velocity.Length * vectord.Length)) * (180.0/Math.PI);
   vectord = boid.position - position;
   if ((vectord.Length < MinDistance) & (num < 135.0)) {
     Nearby = Nearby + 1;
     Cohesion += boid.position;
     vectord = boid.position - position;
     if (vectord.Length < 10.0) {
       Separation -= boid.position - position;
     }
     Alignment += boid.velocity;
   }
 }
    public void InitJoin() {


      var join = (MainWindow.SCALABLE) ? 
          Join.Create<Join.Scalable>(4 + NumBoids + NumBoids)
        : Join.Create<Join.LockBased>(4 + NumBoids + NumBoids);
    
      join.Initialize(out Boids, NumBoids);
      join.Initialize(out Tick);
      join.Initialize(out Running);
      join.Initialize(out NotRunning);
      join.Initialize(out PauseResume);
      join.Initialize(out Sync, NumBoids);
      for (int i = 0; i < NumBoids; i++)
      {   // dummy channels to add contention
          join.When(Sync[i]).Do(() => { ;});
      }
      // rendezvous pattern
      join.When(Tick).And(Running).And(Boids).Do(data => { Running(); return data; });
      
      join.When(PauseResume).And(Running).Do(() => NotRunning());
      join.When(PauseResume).And(NotRunning).Do(() => { ResetStats(); Running(); });
      Running();

     
      var d = new Data[NumBoids];
    }