Browse Source

codemaid cleanup

Alexander Hendrich 10 years ago
parent
commit
8e289ad778
63 changed files with 2614 additions and 2911 deletions
  1. 3 3
      bbiwarg/App.config
  2. 58 68
      bbiwarg/BBWIWARG.cs
  3. 8 14
      bbiwarg/Images/ConfidenceImage.cs
  4. 11 18
      bbiwarg/Images/DepthImage.cs
  5. 56 56
      bbiwarg/Images/EdgeImage.cs
  6. 33 41
      bbiwarg/Input/InputHandling/FrameData.cs
  7. 73 77
      bbiwarg/Input/InputHandling/InputHandler.cs
  8. 88 96
      bbiwarg/Input/InputProviding/InputProvider.cs
  9. 41 48
      bbiwarg/Input/InputProviding/VideoInputProvider.cs
  10. 5 13
      bbiwarg/Output/DebugOutput/DebugImageCreator.cs
  11. 104 114
      bbiwarg/Output/DebugOutput/DebugWindow.cs
  12. 71 74
      bbiwarg/Output/DebugOutput/TouchEventVisualizer.cs
  13. 89 97
      bbiwarg/Output/GlassesOutput/GlassesWindow.cs
  14. 106 112
      bbiwarg/Output/OutputImage.cs
  15. 206 235
      bbiwarg/Parameters.cs
  16. 6 7
      bbiwarg/Properties/AssemblyInfo.cs
  17. 24 32
      bbiwarg/Recognition/FingerRecognition/Finger.cs
  18. 64 71
      bbiwarg/Recognition/FingerRecognition/FingerDetector.cs
  19. 12 19
      bbiwarg/Recognition/FingerRecognition/FingerSlice.cs
  20. 67 72
      bbiwarg/Recognition/FingerRecognition/FingerSliceTrail.cs
  21. 14 19
      bbiwarg/Recognition/FingerRecognition/FingerTracker.cs
  22. 22 26
      bbiwarg/Recognition/FingerRecognition/TrackedFinger.cs
  23. 32 37
      bbiwarg/Recognition/HandRecognition/Hand.cs
  24. 96 102
      bbiwarg/Recognition/HandRecognition/HandDetector.cs
  25. 13 18
      bbiwarg/Recognition/HandRecognition/HandTracker.cs
  26. 4 8
      bbiwarg/Recognition/HandRecognition/TrackedHand.cs
  27. 18 22
      bbiwarg/Recognition/PalmRecognition/Palm.cs
  28. 77 80
      bbiwarg/Recognition/PalmRecognition/PalmDetector.cs
  29. 14 19
      bbiwarg/Recognition/PalmRecognition/PalmTracker.cs
  30. 29 35
      bbiwarg/Recognition/PalmRecognition/TrackedPalm.cs
  31. 6 15
      bbiwarg/Recognition/TouchRecognition/Touch.cs
  32. 9 13
      bbiwarg/Recognition/TouchRecognition/TouchDetector.cs
  33. 6 12
      bbiwarg/Recognition/TouchRecognition/TouchEvent.cs
  34. 22 30
      bbiwarg/Recognition/TouchRecognition/TouchTracker.cs
  35. 15 21
      bbiwarg/Recognition/TouchRecognition/TrackedTouch.cs
  36. 6 13
      bbiwarg/Recognition/Tracking/Similarity.cs
  37. 2 6
      bbiwarg/Recognition/Tracking/TrackIDPool.cs
  38. 2 8
      bbiwarg/Recognition/Tracking/TrackableObject.cs
  39. 14 20
      bbiwarg/Recognition/Tracking/TrackedObject.cs
  40. 56 57
      bbiwarg/Recognition/Tracking/Tracker.cs
  41. 37 36
      bbiwarg/TUIO/OSC.NET/OSCBundle.cs
  42. 41 36
      bbiwarg/TUIO/OSC.NET/OSCMessage.cs
  43. 76 69
      bbiwarg/TUIO/OSC.NET/OSCPacket.cs
  44. 8 10
      bbiwarg/TUIO/OSC.NET/OSCTransmitter.cs
  45. 75 70
      bbiwarg/TUIO/TUIO/TuioContainer.cs
  46. 6 6
      bbiwarg/TUIO/TUIO/TuioCursor.cs
  47. 49 46
      bbiwarg/TUIO/TUIO/TuioObject.cs
  48. 80 76
      bbiwarg/TUIO/TUIO/TuioPoint.cs
  49. 110 116
      bbiwarg/TUIO/TUIO/TuioServer.cs
  50. 78 72
      bbiwarg/TUIO/TUIO/TuioTime.cs
  51. 45 46
      bbiwarg/TUIO/TuioCommunicator.cs
  52. 26 32
      bbiwarg/Utility/ConvexityDefect.cs
  53. 19 24
      bbiwarg/Utility/CoordinateConverter.cs
  54. 8 16
      bbiwarg/Utility/ImageSize.cs
  55. 41 50
      bbiwarg/Utility/Kalman2DPositionFilter.cs
  56. 27 32
      bbiwarg/Utility/Line2D.cs
  57. 37 40
      bbiwarg/Utility/LineSegment2D.cs
  58. 2 6
      bbiwarg/Utility/Logger.cs
  59. 26 34
      bbiwarg/Utility/Projection2DTo2D.cs
  60. 11 22
      bbiwarg/Utility/Quadrangle.cs
  61. 38 42
      bbiwarg/Utility/Timer.cs
  62. 164 169
      bbiwarg/Utility/Vector2D.cs
  63. 28 33
      bbiwarg/Utility/Vector3D.cs

+ 3 - 3
bbiwarg/App.config

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <configuration>
-    <startup> 
-        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
-    </startup>
+  <startup>
+    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+  </startup>
 </configuration>

+ 58 - 68
bbiwarg/BBWIWARG.cs

@@ -1,100 +1,79 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.Linq;
-using System.Text;
-using System.Net;
-using System.Windows;
-using System.Windows.Forms;
+using bbiwarg.Input.InputHandling;
+using bbiwarg.Input.InputProviding;
 using bbiwarg.Output.DebugOutput;
 using bbiwarg.Output.GlassesOutput;
-using bbiwarg.Input.InputProviding;
-using bbiwarg.Input.InputHandling;
 using bbiwarg.TUIO;
+using System;
+using System.Linq;
+using System.Threading;
+using System.Windows.Forms;
 
 namespace bbiwarg
 {
     /// <summary>
     /// Main class which creates and starts the input, tuio and window objects.
     /// </summary>
-    class BBIWARG
+    internal class BBIWARG
     {
         /// <summary>
-        /// the input provider
-        /// </summary>
-        private InputProvider inputProvider;
-
-        /// <summary>
-        /// the input handler
+        /// the debug window
         /// </summary>
-        private InputHandler inputHandler;
-
+        private DebugWindow debugWindow;
 
         /// <summary>
-        /// true iff the tuio server is enabled
+        /// true iff the debug window is enabled
         /// </summary>
-        private bool tuioEnabled;
+        private bool debugWindowEnabled;
 
         /// <summary>
-        /// the ip address for the tuio server
+        /// the thread the debug window runs in
         /// </summary>
-        private String tuioIP;
+        private Thread debugWindowThread;
 
         /// <summary>
-        /// the port for the tuio server
+        /// the glasses window
         /// </summary>
-        private Int16 tuioPort;
+        private GlassesWindow glassesWindow;
 
         /// <summary>
-        /// the tuio communicator
+        /// true iff the glasses window is enabled
         /// </summary>
-        private TuioCommunicator tuioCommunicator;
-
+        private bool glassesWindowEnabled;
 
         /// <summary>
-        /// true iff the debug window is enabled
+        /// the thread the glasses window runs in
         /// </summary>
-        private bool debugWindowEnabled;
+        private Thread glassesWindowThread;
 
         /// <summary>
-        /// the debug window
+        /// the input handler
         /// </summary>
-        private DebugWindow debugWindow;
+        private InputHandler inputHandler;
 
         /// <summary>
-        /// the thread the debug window runs in
+        /// the input provider
         /// </summary>
-        private Thread debugWindowThread;
-
+        private InputProvider inputProvider;
 
         /// <summary>
-        /// true iff the glasses window is enabled
+        /// the tuio communicator
         /// </summary>
-        private bool glassesWindowEnabled;
+        private TuioCommunicator tuioCommunicator;
 
         /// <summary>
-        /// the thread the glasses window runs in
+        /// true iff the tuio server is enabled
         /// </summary>
-        private Thread glassesWindowThread;
+        private bool tuioEnabled;
 
         /// <summary>
-        /// the glasses window
+        /// the ip address for the tuio server
         /// </summary>
-        private GlassesWindow glassesWindow;
-
+        private String tuioIP;
 
         /// <summary>
-        /// Starts the program.
+        /// the port for the tuio server
         /// </summary>
-        /// <param name="args"></param>
-        static void Main(string[] args)
-        {
-            Console.SetWindowSize(Parameters.ConsoleWidth, Parameters.ConsoleHeight);
-
-            BBIWARG program = new BBIWARG(args);
-            program.run();
-        }
+        private Int16 tuioPort;
 
         /// <summary>
         /// Parses the command line arguments and depending on them creates the input, tuio and window objects.
@@ -129,7 +108,6 @@ namespace bbiwarg
             // glasses output
             if (glassesWindowEnabled)
                 glassesWindowThread = new Thread(new ThreadStart(glassesWindowThreadStart));
-
         }
 
         /// <summary>
@@ -140,6 +118,18 @@ namespace bbiwarg
             inputProvider.start();
         }
 
+        /// <summary>
+        /// Starts the program.
+        /// </summary>
+        /// <param name="args"></param>
+        private static void Main(string[] args)
+        {
+            Console.SetWindowSize(Parameters.ConsoleWidth, Parameters.ConsoleHeight);
+
+            BBIWARG program = new BBIWARG(args);
+            program.run();
+        }
+
         /// <summary>
         /// Creates the input provider.
         /// </summary>
@@ -169,20 +159,6 @@ namespace bbiwarg
             Application.Run(glassesWindow);
         }
 
-        /// <summary>
-        /// Handles the event that the device has started by starting the enabled windows.
-        /// </summary>
-        /// <param name="sender">event sender</param>
-        /// <param name="e">event arguments</param>
-        private void handleDeviceStartedEvent(object sender, EventArgs e)
-        {
-            if (debugWindowEnabled)
-                debugWindowThread.Start();
-
-            if (glassesWindowEnabled)
-                glassesWindowThread.Start();
-        }
-
         /// <summary>
         /// Parses the command line arguments and sets parameters depending on them.
         /// </summary>
@@ -228,5 +204,19 @@ namespace bbiwarg
                 tuioPort = Parameters.TuioDefaultPort;
             }
         }
+
+        /// <summary>
+        /// Handles the event that the device has started by starting the enabled windows.
+        /// </summary>
+        /// <param name="sender">event sender</param>
+        /// <param name="e">event arguments</param>
+        private void handleDeviceStartedEvent(object sender, EventArgs e)
+        {
+            if (debugWindowEnabled)
+                debugWindowThread.Start();
+
+            if (glassesWindowEnabled)
+                glassesWindowThread.Start();
+        }
     }
-}
+}

+ 8 - 14
bbiwarg/Images/ConfidenceImage.cs

@@ -1,13 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Images;
-using bbiwarg.Output;
+using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
-using bbiwarg.Utility;
+using System;
 
 namespace bbiwarg.Images
 {
@@ -16,11 +10,6 @@ namespace bbiwarg.Images
     /// </summary>
     public class ConfidenceImage
     {
-        /// <summary>
-        /// the size of the confidence image
-        /// </summary>
-        public ImageSize Size { get; private set; }
-
         /// <summary>
         /// the confidence image
         /// </summary>
@@ -31,6 +20,11 @@ namespace bbiwarg.Images
         /// </summary>
         public Image<Gray, byte> Mask { get; private set; }
 
+        /// <summary>
+        /// the size of the confidence image
+        /// </summary>
+        public ImageSize Size { get; private set; }
+
         /// <summary>
         /// Constructs a new ConfidenceImage using the specified data and size.
         /// </summary>
@@ -44,4 +38,4 @@ namespace bbiwarg.Images
             Mask = (Image.ThresholdBinary(new Gray(Parameters.ConfidenceImageMinThreshold), new Gray(1))).Convert<Gray, byte>();
         }
     }
-}
+}

+ 11 - 18
bbiwarg/Images/DepthImage.cs

@@ -1,16 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Runtime.InteropServices;
+using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
-using bbiwarg.Output;
-using bbiwarg.Recognition.FingerRecognition;
-using bbiwarg.Recognition.HandRecognition;
-using bbiwarg.Utility;
+using System;
+using System.Drawing;
 
 namespace bbiwarg.Images
 {
@@ -20,14 +12,14 @@ namespace bbiwarg.Images
     public class DepthImage
     {
         /// <summary>
-        /// image size of the deph image
+        /// the processed depth image
         /// </summary>
-        public ImageSize Size { get; private set; }
+        public Image<Gray, byte> Image { get; private set; }
 
         /// <summary>
-        /// the processed depth image
+        /// the maximum depth which is considered important
         /// </summary>
-        public Image<Gray, byte> Image { get; private set; }
+        public Int16 MaxDepth { get; private set; }
 
         /// <summary>
         /// the minimum depth in the raw depth image
@@ -35,9 +27,9 @@ namespace bbiwarg.Images
         public Int16 MinDepth { get; private set; }
 
         /// <summary>
-        /// the maximum depth which is considered important
+        /// image size of the deph image
         /// </summary>
-        public Int16 MaxDepth { get; private set; }
+        public ImageSize Size { get; private set; }
 
         /// <summary>
         /// Construct a DepthImage from the raw depth data, the image size and a confidenceImage.
@@ -119,6 +111,7 @@ namespace bbiwarg.Images
         {
             // min and max values
             double[] min, max;
+
             // min and max locations
             Point[] minLoc, maxLoc;
 
@@ -127,4 +120,4 @@ namespace bbiwarg.Images
             return (Int16)min[0];
         }
     }
-}
+}

+ 56 - 56
bbiwarg/Images/EdgeImage.cs

@@ -11,11 +11,6 @@ namespace bbiwarg.Images
     /// </summary>
     public class EdgeImage
     {
-        /// <summary>
-        /// the size of the edge image
-        /// </summary>
-        public ImageSize Size { get; private set; }
-
         /// <summary>
         /// the edge image
         /// </summary>
@@ -26,6 +21,11 @@ namespace bbiwarg.Images
         /// </summary>
         public Image<Gray, Byte> RoughImage { get; private set; }
 
+        /// <summary>
+        /// the size of the edge image
+        /// </summary>
+        public ImageSize Size { get; private set; }
+
         /// <summary>
         /// Constructs a new EdgeImage from a depth image.
         /// </summary>
@@ -53,55 +53,12 @@ namespace bbiwarg.Images
         }
 
         /// <summary>
-        /// Returns true iff an edge is at a point.
-        /// </summary>
-        /// <param name="point">the point</param>
-        /// <returns>true iff an edge is at point</returns>
-        public bool isEdgeAt(Point point)
-        {
-            return isEdgeAt(point.X, point.Y);
-        }
-
-        /// <summary>
-        /// Returns true iff an edge is at a position.
-        /// </summary>
-        /// <param name="x">x coordinate of the position</param>
-        /// <param name="y">y coordinate of the position</param>
-        /// <returns>true iff an edge is at the position</returns>
-        public bool isEdgeAt(int x, int y)
-        {
-            return (Image.Data[y, x, 0] > 0);
-        }
-
-        /// <summary>
-        /// Returns true iff an edge is at a point in the rough edge image.
-        /// </summary>
-        /// <param name="point">the point</param>
-        /// <returns>true iff an edge is at point in the rough edge image</returns>
-        public bool isRoughEdgeAt(Point point)
-        {
-            return isRoughEdgeAt(point.X, point.Y);
-        }
-
-        /// <summary>
-        /// Returns true iff an edge is at a position in the rough edge image.
-        /// </summary>
-        /// <param name="x">x coordinate of the position</param>
-        /// <param name="y">y coordinate of the position</param>
-        /// <returns>true iff an edge is at the position in the rough edge image</returns>
-        public bool isRoughEdgeAt(int x, int y)
-        {
-            return (RoughImage.Data[y, x, 0] > 0);
-        }
-
-        /// <summary>
-        /// Removes all edges inside the given polygon in both edge images.
+        /// Returns a copy of this edge image.
         /// </summary>
-        /// <param name="polygon">the polygon</param>
-        public void removeEdgesInsidePolygon(Point[] polygon)
+        /// <returns>copy of this edge image</returns>
+        public EdgeImage copy()
         {
-            Image.FillConvexPoly(polygon, new Gray(0));
-            RoughImage.FillConvexPoly(polygon, new Gray(0));
+            return new EdgeImage(Image.Copy(), RoughImage.Copy(), Size);
         }
 
         /// <summary>
@@ -151,12 +108,55 @@ namespace bbiwarg.Images
         }
 
         /// <summary>
-        /// Returns a copy of this edge image.
+        /// Returns true iff an edge is at a point.
         /// </summary>
-        /// <returns>copy of this edge image</returns>
-        public EdgeImage copy()
+        /// <param name="point">the point</param>
+        /// <returns>true iff an edge is at point</returns>
+        public bool isEdgeAt(Point point)
         {
-            return new EdgeImage(Image.Copy(), RoughImage.Copy(), Size);
+            return isEdgeAt(point.X, point.Y);
+        }
+
+        /// <summary>
+        /// Returns true iff an edge is at a position.
+        /// </summary>
+        /// <param name="x">x coordinate of the position</param>
+        /// <param name="y">y coordinate of the position</param>
+        /// <returns>true iff an edge is at the position</returns>
+        public bool isEdgeAt(int x, int y)
+        {
+            return (Image.Data[y, x, 0] > 0);
+        }
+
+        /// <summary>
+        /// Returns true iff an edge is at a point in the rough edge image.
+        /// </summary>
+        /// <param name="point">the point</param>
+        /// <returns>true iff an edge is at point in the rough edge image</returns>
+        public bool isRoughEdgeAt(Point point)
+        {
+            return isRoughEdgeAt(point.X, point.Y);
+        }
+
+        /// <summary>
+        /// Returns true iff an edge is at a position in the rough edge image.
+        /// </summary>
+        /// <param name="x">x coordinate of the position</param>
+        /// <param name="y">y coordinate of the position</param>
+        /// <returns>true iff an edge is at the position in the rough edge image</returns>
+        public bool isRoughEdgeAt(int x, int y)
+        {
+            return (RoughImage.Data[y, x, 0] > 0);
+        }
+
+        /// <summary>
+        /// Removes all edges inside the given polygon in both edge images.
+        /// </summary>
+        /// <param name="polygon">the polygon</param>
+        public void removeEdgesInsidePolygon(Point[] polygon)
+        {
+            Image.FillConvexPoly(polygon, new Gray(0));
+            RoughImage.FillConvexPoly(polygon, new Gray(0));
         }
     }
 }

+ 33 - 41
bbiwarg/Input/InputHandling/FrameData.cs

@@ -1,14 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Images;
+using bbiwarg.Images;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Recognition.PalmRecognition;
 using bbiwarg.Recognition.TouchRecognition;
 using bbiwarg.Utility;
+using System.Collections.Generic;
 
 namespace bbiwarg.Input.InputHandling
 {
@@ -18,82 +14,78 @@ namespace bbiwarg.Input.InputHandling
     public class FrameData
     {
         /// <summary>
-        /// the id of the frame
+        /// the confidence image read in this frame
         /// </summary>
-        public int FrameID { get; set; }
+        public ConfidenceImage ConfidenceImage { get; set; }
 
         /// <summary>
-        /// the size of all the images
+        /// the depth image read in this frame
         /// </summary>
-        public ImageSize ImageSize { get; set; }
+        public DepthImage DepthImage { get; set; }
 
         /// <summary>
-        /// set iff the input source is a movie which is in the first frame again
+        /// a list of fingers detected in this frame
         /// </summary>
-        public bool ResetFlag { get; set; }
+        public List<Finger> DetectedFingers { get; set; }
 
         /// <summary>
-        /// the depth image read in this frame
+        /// a list of hands detected in this frame
         /// </summary>
-        public DepthImage DepthImage { get; set; }
+        public List<Hand> DetectedHands { get; set; }
 
         /// <summary>
-        /// the edge image created in this frame
+        /// a list of plams detected in this frame
         /// </summary>
-        public EdgeImage EdgeImage { get; set; }
+        public List<Palm> DetectedPalms { get; set; }
 
         /// <summary>
-        /// the confidence image read in this frame
+        /// a list of <see cref="Touch"/> objects detected in this frame
         /// </summary>
-        public ConfidenceImage ConfidenceImage { get; set; }
-
+        public List<Touch> DetectedTouches { get; set; }
 
         /// <summary>
-        /// a list of fingers detected in this frame
+        /// the edge image created in this frame
         /// </summary>
-        public List<Finger> DetectedFingers { get; set; }
+        public EdgeImage EdgeImage { get; set; }
 
         /// <summary>
-        /// a list of fingers which are tracked in this frame
+        /// the id of the frame
         /// </summary>
-        public List<Finger> TrackedFingers { get; set; }
-
+        public int FrameID { get; set; }
 
         /// <summary>
-        /// a list of hands detected in this frame
+        /// the size of all the images
         /// </summary>
-        public List<Hand> DetectedHands { get; set; }
+        public ImageSize ImageSize { get; set; }
 
         /// <summary>
-        /// a list of hands which are tracked in this frame
+        /// set iff the input source is a movie which is in the first frame again
         /// </summary>
-        public List<Hand> TrackedHands { get; set; }
-
+        public bool ResetFlag { get; set; }
 
         /// <summary>
-        /// a list of plams detected in this frame
+        /// a list of touch events generated in this frame
         /// </summary>
-        public List<Palm> DetectedPalms { get; set; }
+        public List<TouchEvent> TouchEvents { get; set; }
 
         /// <summary>
-        /// a list of plams which are tracked in this frame
+        /// a list of fingers which are tracked in this frame
         /// </summary>
-        public List<Palm> TrackedPalms { get; set; }
-
+        public List<Finger> TrackedFingers { get; set; }
 
         /// <summary>
-        /// a list of <see cref="Touch"/> objects detected in this frame
+        /// a list of hands which are tracked in this frame
         /// </summary>
-        public List<Touch> DetectedTouches { get; set; }
+        public List<Hand> TrackedHands { get; set; }
 
         /// <summary>
-        /// a list of <see cref="Touch"/> objects which are tracked in this frame
+        /// a list of plams which are tracked in this frame
         /// </summary>
-        public List<Touch> TrackedTouches { get; set; }
+        public List<Palm> TrackedPalms { get; set; }
 
         /// <summary>
-        /// a list of touch events generated in this frame
+        /// a list of <see cref="Touch"/> objects which are tracked in this frame
         /// </summary>
-        public List<TouchEvent> TouchEvents { get; set; }
+        public List<Touch> TrackedTouches { get; set; }
     }
-}
+}

+ 73 - 77
bbiwarg/Input/InputHandling/InputHandler.cs

@@ -16,73 +16,41 @@ namespace bbiwarg.Input.InputHandling
     /// <param name="e">event parameters</param>
     public delegate void NewProcessedFrameEventHandler(object sender, NewProcessedFrameEventArgs e);
 
-    /// <summary>
-    /// Encapsulates the arguments for the event of finishing to process a new frame.
-    /// </summary>
-    public class NewProcessedFrameEventArgs : EventArgs
-    {
-        /// <summary>
-        /// the data of the processed frame
-        /// </summary>
-        public FrameData FrameData { get; private set; }
-
-        /// <summary>
-        /// Creates a new NewProcessedFrameEventArgs with given frame data.
-        /// </summary>
-        /// <param name="frameData">frame data</param>
-        public NewProcessedFrameEventArgs(FrameData frameData)
-        {
-            FrameData = frameData;
-        }
-    }
-
     /// <summary>
     /// Handles new frames by coordinating and delegating the work to the image, detector and tracker classes.
     /// Also provides an event and the data for the tuio server and the graphical output.
     /// </summary>
     public class InputHandler
     {
-        /// <summary>
-        /// the input provider which provides the raw data
-        /// </summary>
-        private InputProvider inputProvider;
-
-        /// <summary>
-        /// set iff the source is a movie which is in the first frame again
-        /// </summary>
-        private bool resetFlag;
-
-
         /// <summary>
         /// the finger detector
         /// </summary>
         private FingerDetector fingerDetector;
 
         /// <summary>
-        /// the hand detector
+        /// the finger tracker
         /// </summary>
-        private HandDetector handDetector;
+        private FingerTracker fingerTracker;
 
         /// <summary>
-        /// the palm detector
+        /// the hand detector
         /// </summary>
-        private PalmDetector palmDetector;
+        private HandDetector handDetector;
 
         /// <summary>
-        /// the touch detector
+        /// the hand tracker
         /// </summary>
-        private TouchDetector touchDetector;
-
+        private HandTracker handTracker;
 
         /// <summary>
-        /// the finger tracker
+        /// the input provider which provides the raw data
         /// </summary>
-        private FingerTracker fingerTracker;
+        private InputProvider inputProvider;
 
         /// <summary>
-        /// the hand tracker
+        /// the palm detector
         /// </summary>
-        private HandTracker handTracker;
+        private PalmDetector palmDetector;
 
         /// <summary>
         /// the palm tracker
@@ -90,15 +58,19 @@ namespace bbiwarg.Input.InputHandling
         private PalmTracker palmTracker;
 
         /// <summary>
-        /// the touch tracker
+        /// set iff the source is a movie which is in the first frame again
         /// </summary>
-        private TouchTracker touchTracker;
+        private bool resetFlag;
 
+        /// <summary>
+        /// the touch detector
+        /// </summary>
+        private TouchDetector touchDetector;
 
         /// <summary>
-        /// the size of all images
+        /// the touch tracker
         /// </summary>
-        public ImageSize ImageSize { get; private set; }
+        private TouchTracker touchTracker;
 
         /// <summary>
         /// converts 2d and 3d coordinates into each other
@@ -110,6 +82,10 @@ namespace bbiwarg.Input.InputHandling
         /// </summary>
         public FrameData FrameData { get; private set; }
 
+        /// <summary>
+        /// the size of all images
+        /// </summary>
+        public ImageSize ImageSize { get; private set; }
 
         /// <summary>
         /// event which occures, when a new frame is finished processing
@@ -131,37 +107,6 @@ namespace bbiwarg.Input.InputHandling
                 videoInputProvider.MovieRestartedEvent += handleMovieRestart;
         }
 
-        /// <summary>
-        /// Initializes all components.
-        /// </summary>
-        private void initialize()
-        {
-            ImageSize = new ImageSize(inputProvider.ImageWidth, inputProvider.ImageHeight);
-            CoordinateConverter = new CoordinateConverter(ImageSize, inputProvider.HFOV, inputProvider.VFOV);
-            resetFlag = false;
-
-            fingerDetector = new FingerDetector(CoordinateConverter);
-            handDetector = new HandDetector();
-            palmDetector = new PalmDetector();
-            touchDetector = new TouchDetector();
-
-            fingerTracker = new FingerTracker(ImageSize);
-            handTracker = new HandTracker(ImageSize);
-            palmTracker = new PalmTracker(ImageSize);
-            touchTracker = new TouchTracker(ImageSize);
-        }
-
-        /// <summary>
-        /// Resets the trackers.
-        /// </summary>
-        public void reset()
-        {
-            touchTracker.reset();
-            handTracker.reset();
-            palmTracker.reset();
-            fingerTracker.reset();
-        }
-
         /// <summary>
         /// Handles a new frame event by processing the new frame using the image, detector and tracker classes.
         /// </summary>
@@ -247,6 +192,17 @@ namespace bbiwarg.Input.InputHandling
                 Timer.outputAll();
         }
 
+        /// <summary>
+        /// Resets the trackers.
+        /// </summary>
+        public void reset()
+        {
+            touchTracker.reset();
+            handTracker.reset();
+            palmTracker.reset();
+            fingerTracker.reset();
+        }
+
         /// <summary>
         /// Handles the event of a restart of the movie.
         /// </summary>
@@ -257,5 +213,45 @@ namespace bbiwarg.Input.InputHandling
             reset();
             resetFlag = true;
         }
+
+        /// <summary>
+        /// Initializes all components.
+        /// </summary>
+        private void initialize()
+        {
+            ImageSize = new ImageSize(inputProvider.ImageWidth, inputProvider.ImageHeight);
+            CoordinateConverter = new CoordinateConverter(ImageSize, inputProvider.FieldOfViewHorizontal, inputProvider.FieldOfViewVertical);
+            resetFlag = false;
+
+            fingerDetector = new FingerDetector(CoordinateConverter);
+            handDetector = new HandDetector();
+            palmDetector = new PalmDetector();
+            touchDetector = new TouchDetector();
+
+            fingerTracker = new FingerTracker(ImageSize);
+            handTracker = new HandTracker(ImageSize);
+            palmTracker = new PalmTracker(ImageSize);
+            touchTracker = new TouchTracker(ImageSize);
+        }
+    }
+
+    /// <summary>
+    /// Encapsulates the arguments for the event of finishing to process a new frame.
+    /// </summary>
+    public class NewProcessedFrameEventArgs : EventArgs
+    {
+        /// <summary>
+        /// the data of the processed frame
+        /// </summary>
+        public FrameData FrameData { get; private set; }
+
+        /// <summary>
+        /// Creates a new NewProcessedFrameEventArgs with given frame data.
+        /// </summary>
+        /// <param name="frameData">frame data</param>
+        public NewProcessedFrameEventArgs(FrameData frameData)
+        {
+            FrameData = frameData;
+        }
     }
 }

+ 88 - 96
bbiwarg/Input/InputProviding/InputProvider.cs

@@ -1,10 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Diagnostics;
-using Iisu;
+using Iisu;
+using System;
 
 namespace bbiwarg.Input.InputProviding
 {
@@ -23,68 +18,34 @@ namespace bbiwarg.Input.InputProviding
     public delegate void NewFrameEventHandler(object sender, NewFrameEventArgs e);
 
     /// <summary>
-    /// Encapsulates the arguments of the event that a new frame is available.
+    /// InputProvider provides the raw depth and confidence data through an event.
     /// </summary>
-    public class NewFrameEventArgs : EventArgs
+    public class InputProvider
     {
         /// <summary>
-        /// the id of the frame
-        /// </summary>
-        public int FrameID { get; private set; }
-
-        /// <summary>
-        /// the with of all images in the frame
-        /// </summary>
-        public int Width { get; private set; }
-
-        /// <summary>
-        /// the height of all images in the frame
-        /// </summary>
-        public int Height { get; private set; }
-
-        /// <summary>
-        /// pointer to the raw depth data for the frame
+        /// data handle for the raw confidence data
         /// </summary>
-        public IntPtr RawDepthData { get; private set; }
+        protected IDataHandle<Iisu.Data.IImageData> confidenceImage;
 
         /// <summary>
-        /// pointer to the raw confidence data for the frame
+        /// data handle for the raw depth data
         /// </summary>
-        public IntPtr RawConfidenceData { get; private set; }
+        protected IDataHandle<Iisu.Data.IImageData> depthImage;
 
         /// <summary>
-        /// Constructs a NewFrameEventArgs.
+        /// iisu device from which the data is read
         /// </summary>
-        /// <param name="frameID">frame id</param>
-        /// <param name="width">width of all images</param>
-        /// <param name="height">height of all images</param>
-        /// <param name="rawDepthData">pointer to raw depth data</param>
-        /// <param name="rawConfidenceData">pointer to raw confidence data</param>
-        public NewFrameEventArgs(int frameID, int width, int height, IntPtr rawDepthData, IntPtr rawConfidenceData)
-        {
-            FrameID = frameID;
-            Width = width;
-            Height = height;
-            RawDepthData = rawDepthData;
-            RawConfidenceData = rawConfidenceData;
-        }
-    }
+        protected IDevice device;
 
-    /// <summary>
-    /// InputProvider provides the raw depth and confidence data through an event.
-    /// </summary>
-    public class InputProvider
-    {
         /// <summary>
-        /// iisu handle 
+        /// parameter handle for the horizontal field of view angle
         /// </summary>
-        protected IHandle handle;
+        protected IParameterHandle<float> fieldOfViewHorizontal;
 
         /// <summary>
-        /// iisu device from which the data is read
+        /// parameter handle for the vertical field of view angle
         /// </summary>
-        protected IDevice device;
-
+        protected IParameterHandle<float> fieldOfViewVertical;
 
         /// <summary>
         /// paramter handle for the frame rate
@@ -92,9 +53,9 @@ namespace bbiwarg.Input.InputProviding
         protected IParameterHandle<float> frameRate;
 
         /// <summary>
-        /// parameter handle for the image width
+        /// iisu handle
         /// </summary>
-        protected IParameterHandle<int> width;
+        protected IHandle handle;
 
         /// <summary>
         /// parameter handle for the image height
@@ -102,29 +63,24 @@ namespace bbiwarg.Input.InputProviding
         protected IParameterHandle<int> height;
 
         /// <summary>
-        /// parameter handle for the horizontal field of view angle
-        /// </summary>
-        protected IParameterHandle<float> hfov;
-
-        /// <summary>
-        /// parameter handle for the vertical field of view angle
+        /// parameter handle for the image width
         /// </summary>
-        protected IParameterHandle<float> vfov;
+        protected IParameterHandle<int> width;
 
         /// <summary>
-        /// data handle for the raw depth data
+        /// the id of the current frame
         /// </summary>
-        protected IDataHandle<Iisu.Data.IImageData> depthImage;
+        public virtual int CurrentFrameID { get { return device.FrameId; } }
 
         /// <summary>
-        /// data handle for the raw confidence data
+        /// the horizontal field of view angle
         /// </summary>
-        protected IDataHandle<Iisu.Data.IImageData> confidenceImage;
+        public float FieldOfViewHorizontal { get { return fieldOfViewHorizontal.Value; } }
 
         /// <summary>
-        /// the width of all images
+        /// the vertical field of view angle
         /// </summary>
-        public int ImageWidth { get { return width.Value; } }
+        public float FieldOfViewVertical { get { return fieldOfViewVertical.Value; } }
 
         /// <summary>
         /// the height of all images
@@ -132,26 +88,15 @@ namespace bbiwarg.Input.InputProviding
         public int ImageHeight { get { return height.Value; } }
 
         /// <summary>
-        /// the horizontal field of view angle
-        /// </summary>
-        public float HFOV { get { return hfov.Value; } }
-
-        /// <summary>
-        /// the vertical field of view angle
+        /// the width of all images
         /// </summary>
-        public float VFOV { get { return vfov.Value; } }
+        public int ImageWidth { get { return width.Value; } }
 
         /// <summary>
         /// true iff the input source provides data
         /// </summary>
         public bool IsActive { get; private set; }
 
-        /// <summary>
-        /// the id of the current frame
-        /// </summary>
-        public virtual int CurrentFrameID { get { return device.FrameId; } }
-
-
         /// <summary>
         /// event that the device started
         /// </summary>
@@ -162,7 +107,6 @@ namespace bbiwarg.Input.InputProviding
         /// </summary>
         public event NewFrameEventHandler NewFrameEvent;
 
-
         /// <summary>
         /// Constructs an InputProvider.
         /// </summary>
@@ -224,6 +168,25 @@ namespace bbiwarg.Input.InputProviding
             return conf;
         }
 
+        /// <summary>
+        /// Gets the next frame from the device.
+        /// </summary>
+        protected virtual void nextFrame()
+        {
+            device.UpdateFrame(true);
+            provideNewFrame();
+            device.ReleaseFrame();
+        }
+
+        /// <summary>
+        /// Triggers the new frame event.
+        /// </summary>
+        protected void provideNewFrame()
+        {
+            if (NewFrameEvent != null)
+                NewFrameEvent(this, new NewFrameEventArgs(CurrentFrameID, ImageWidth, ImageHeight, depthImage.Value.Raw, confidenceImage.Value.Raw));
+        }
+
         /// <summary>
         /// Registers all parameter and data handles.
         /// </summary>
@@ -231,8 +194,8 @@ namespace bbiwarg.Input.InputProviding
         {
             width = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Width");
             height = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Height");
-            hfov = device.RegisterParameterHandle<float>("SOURCE.CAMERA.DEPTH.HFOV");
-            vfov = device.RegisterParameterHandle<float>("SOURCE.CAMERA.DEPTH.VFOV");
+            fieldOfViewHorizontal = device.RegisterParameterHandle<float>("SOURCE.CAMERA.DEPTH.HFOV");
+            fieldOfViewVertical = device.RegisterParameterHandle<float>("SOURCE.CAMERA.DEPTH.VFOV");
             frameRate = device.RegisterParameterHandle<float>("SOURCE.FrameRate");
 
             depthImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.DEPTH.Image");
@@ -247,24 +210,53 @@ namespace bbiwarg.Input.InputProviding
             while (IsActive)
                 nextFrame();
         }
+    }
 
+    /// <summary>
+    /// Encapsulates the arguments of the event that a new frame is available.
+    /// </summary>
+    public class NewFrameEventArgs : EventArgs
+    {
         /// <summary>
-        /// Gets the next frame from the device.
+        /// the id of the frame
         /// </summary>
-        protected virtual void nextFrame()
-        {
-            device.UpdateFrame(true);
-            provideNewFrame();
-            device.ReleaseFrame();
-        }
+        public int FrameID { get; private set; }
 
         /// <summary>
-        /// Triggers the new frame event.
+        /// the height of all images in the frame
         /// </summary>
-        protected void provideNewFrame()
+        public int Height { get; private set; }
+
+        /// <summary>
+        /// pointer to the raw confidence data for the frame
+        /// </summary>
+        public IntPtr RawConfidenceData { get; private set; }
+
+        /// <summary>
+        /// pointer to the raw depth data for the frame
+        /// </summary>
+        public IntPtr RawDepthData { get; private set; }
+
+        /// <summary>
+        /// the with of all images in the frame
+        /// </summary>
+        public int Width { get; private set; }
+
+        /// <summary>
+        /// Constructs a NewFrameEventArgs.
+        /// </summary>
+        /// <param name="frameID">frame id</param>
+        /// <param name="width">width of all images</param>
+        /// <param name="height">height of all images</param>
+        /// <param name="rawDepthData">pointer to raw depth data</param>
+        /// <param name="rawConfidenceData">pointer to raw confidence data</param>
+        public NewFrameEventArgs(int frameID, int width, int height, IntPtr rawDepthData, IntPtr rawConfidenceData)
         {
-            if (NewFrameEvent != null)
-                NewFrameEvent(this, new NewFrameEventArgs(CurrentFrameID, ImageWidth, ImageHeight, depthImage.Value.Raw, confidenceImage.Value.Raw));
+            FrameID = frameID;
+            Width = width;
+            Height = height;
+            RawDepthData = rawDepthData;
+            RawConfidenceData = rawConfidenceData;
         }
     }
-}
+}

+ 41 - 48
bbiwarg/Input/InputProviding/VideoInputProvider.cs

@@ -1,10 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using Iisu;
+using System;
 using System.Threading;
-using Iisu;
-using bbiwarg.Utility;
 
 namespace bbiwarg.Input.InputProviding
 {
@@ -18,7 +14,7 @@ namespace bbiwarg.Input.InputProviding
     /// <summary>
     /// VideoInputProvider provides the raw depth and confidence data read from a video file.
     /// </summary>
-    class VideoInputProvider : InputProvider
+    internal class VideoInputProvider : InputProvider
     {
         /// <summary>
         /// parameter handle for the current frame of the movie
@@ -35,29 +31,26 @@ namespace bbiwarg.Input.InputProviding
         /// </summary>
         private IParameterHandle<int> playStep;
 
-
         /// <summary>
         /// the id of the current frame
         /// </summary>
         public override int CurrentFrameID { get { return currentMovieFrame.Value; } }
 
-        /// <summary>
-        /// the path to the movie file
-        /// </summary>
-        public String MoviePath { get; private set; }
-
         /// <summary>
         /// true iff the movie is paused
         /// </summary>
         public bool IsPaused { get; private set; }
 
+        /// <summary>
+        /// the path to the movie file
+        /// </summary>
+        public String MoviePath { get; private set; }
 
         /// <summary>
         /// event that the movie has restarted
         /// </summary>
         public event MovieRestartedEventHandler MovieRestartedEvent;
 
-
         /// <summary>
         /// Constructs a VideoInputProvider.
         /// </summary>
@@ -68,27 +61,21 @@ namespace bbiwarg.Input.InputProviding
         }
 
         /// <summary>
-        /// Returns an iisu device configuration, which uses the movie to read the data.
+        /// Jumps to the next movie frame.
         /// </summary>
-        /// <returns>iisu device configuration</returns>
-        protected override IDeviceConfiguration createDeviceConfiguration()
+        public void goToNextFrame()
         {
-            IDeviceConfiguration conf = base.createDeviceConfiguration();
-            conf.MoviePath = MoviePath;
-            return conf;
+            nextFrame();
         }
 
         /// <summary>
-        /// Registers all parameter and data handles.
+        /// Jumps to the previous movie frame.
         /// </summary>
-        protected override void registerHandles()
+        public void goToPreviousFrame()
         {
-            base.registerHandles();
-
-            device.RegisterParameterHandle<int>("SOURCE.MOVIE.PlayMode").Value = 1; // 0=once, 1=loop, 2=pingPong
-            currentMovieFrame = device.RegisterParameterHandle<int>("SOURCE.MOVIE.CurrentFrame");
-            frameCount = device.RegisterParameterHandle<int>("SOURCE.MOVIE.FrameCount");
-            playStep = device.RegisterParameterHandle<int>("SOURCE.MOVIE.PlayStep");
+            playStep.Value = -1;
+            nextFrame();
+            playStep.Value = 1;
         }
 
         /// <summary>
@@ -108,21 +95,38 @@ namespace bbiwarg.Input.InputProviding
         }
 
         /// <summary>
-        /// Jumps to the next movie frame.
+        /// Returns an iisu device configuration, which uses the movie to read the data.
         /// </summary>
-        public void goToNextFrame()
+        /// <returns>iisu device configuration</returns>
+        protected override IDeviceConfiguration createDeviceConfiguration()
         {
-            nextFrame();
+            IDeviceConfiguration conf = base.createDeviceConfiguration();
+            conf.MoviePath = MoviePath;
+            return conf;
         }
 
         /// <summary>
-        /// Jumps to the previous movie frame.
+        /// Gets the next frame from the device and triggers an event if the movie has restarted.
         /// </summary>
-        public void goToPreviousFrame()
+        protected override void nextFrame()
         {
-            playStep.Value = -1;
-            nextFrame();
-            playStep.Value = 1;
+            base.nextFrame();
+
+            if (CurrentFrameID == 0 && MovieRestartedEvent != null)
+                MovieRestartedEvent(this, new EventArgs());
+        }
+
+        /// <summary>
+        /// Registers all parameter and data handles.
+        /// </summary>
+        protected override void registerHandles()
+        {
+            base.registerHandles();
+
+            device.RegisterParameterHandle<int>("SOURCE.MOVIE.PlayMode").Value = 1; // 0=once, 1=loop, 2=pingPong
+            currentMovieFrame = device.RegisterParameterHandle<int>("SOURCE.MOVIE.CurrentFrame");
+            frameCount = device.RegisterParameterHandle<int>("SOURCE.MOVIE.FrameCount");
+            playStep = device.RegisterParameterHandle<int>("SOURCE.MOVIE.PlayStep");
         }
 
         /// <summary>
@@ -138,16 +142,5 @@ namespace bbiwarg.Input.InputProviding
                     Thread.Sleep((int)(1000 / frameRate.Value));
             }
         }
-
-        /// <summary>
-        /// Gets the next frame from the device and triggers an event if the movie has restarted.
-        /// </summary>
-        protected override void nextFrame()
-        {
-            base.nextFrame();
-
-            if (CurrentFrameID == 0 && MovieRestartedEvent != null)
-                MovieRestartedEvent(this, new EventArgs());
-        }
     }
-}
+}

+ 5 - 13
bbiwarg/Output/DebugOutput/DebugImageCreator.cs

@@ -1,30 +1,24 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Drawing;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Input.InputHandling;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Recognition.PalmRecognition;
 using bbiwarg.Recognition.TouchRecognition;
-using Emgu.CV.Structure;
 using Emgu.CV;
+using Emgu.CV.Structure;
+using System.Drawing;
 
 namespace bbiwarg.Output.DebugOutput
 {
     /// <summary>
     /// DebugImageCreator creates all debug images as <see cref="OutputImage"/> objects using the frame data.
     /// </summary>
-    class DebugImageCreator
+    internal class DebugImageCreator
     {
         /// <summary>
         /// visualizes touch events
         /// </summary>
         private TouchEventVisualizer touchEventVisualizer;
 
-
         /// <summary>
         /// the depth image with additional interesting points
         /// </summary>
@@ -50,7 +44,6 @@ namespace bbiwarg.Output.DebugOutput
         /// </summary>
         public OutputImage TouchImage { get; private set; }
 
-
         /// <summary>
         /// Creates a DebugImageCreator.
         /// </summary>
@@ -143,7 +136,6 @@ namespace bbiwarg.Output.DebugOutput
 
             foreach (Hand h in frameData.TrackedHands)
             {
-
                 HandImage.drawImage(h.Mask.ThresholdBinary(new Gray(0), new Gray(255)), Parameters.HandColors[h.TrackID % Parameters.HandNumColors]);
                 HandImage.fillCircle(h.Centroid, 5, Parameters.HandCentroidColor);
                 HandImage.drawText(h.Centroid, h.TrackID.ToString(), Parameters.HandIDColor);
@@ -200,4 +192,4 @@ namespace bbiwarg.Output.DebugOutput
             TouchImage = touchEventVisualizer.getOutputImage(frameData.ImageSize, numRows, numColumns);
         }
     }
-}
+}

+ 104 - 114
bbiwarg/Output/DebugOutput/DebugWindow.cs

@@ -1,17 +1,8 @@
-using System;
-using System.Collections.Generic;
+using bbiwarg.Input.InputHandling;
+using bbiwarg.Input.InputProviding;
+using System;
 using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows.Forms;
-using System.Windows;
-using bbiwarg.Input.InputProviding;
-using bbiwarg.Input.InputHandling;
-using bbiwarg.Utility;
-using Emgu.CV.UI;
 
 namespace bbiwarg.Output.DebugOutput
 {
@@ -21,14 +12,9 @@ namespace bbiwarg.Output.DebugOutput
     public partial class DebugWindow : Form
     {
         /// <summary>
-        /// the input handler
-        /// </summary>
-        private InputHandler inputHandler;
-
-        /// <summary>
-        /// the input provider
+        /// id of the current frame
         /// </summary>
-        private InputProvider inputProvider;
+        private int currentFrameID;
 
         /// <summary>
         /// the debug image creator
@@ -36,20 +22,24 @@ namespace bbiwarg.Output.DebugOutput
         private DebugImageCreator debugImageCreator;
 
         /// <summary>
-        /// timer to periodically update the window
+        /// true iff the window is showing the latest data
         /// </summary>
-        private System.Windows.Forms.Timer timer;
+        private bool guiUpToDate;
 
         /// <summary>
-        /// id of the current frame
+        /// the input handler
         /// </summary>
-        private int currentFrameID;
+        private InputHandler inputHandler;
 
         /// <summary>
-        /// true iff the window is showing the latest data
+        /// the input provider
         /// </summary>
-        private bool guiUpToDate;
+        private InputProvider inputProvider;
 
+        /// <summary>
+        /// timer to periodically update the window
+        /// </summary>
+        private System.Windows.Forms.Timer timer;
 
         /// <summary>
         /// Creates the DebugWindow.
@@ -96,91 +86,75 @@ namespace bbiwarg.Output.DebugOutput
         }
 
         /// <summary>
-        /// Updates the window.
+        /// Jumps to the next movie frame.
         /// </summary>
-        /// <param name="sender">the event sender</param>
-        /// <param name="e">the event arguments</param>
-        private void update(object sender, EventArgs e)
+        private void handleGoToNextFrame()
         {
-            Utility.Timer.start("DebugWindow.update");
-
-            if (!inputProvider.IsActive)
-                Close();
-
-            FrameData frameData = inputHandler.FrameData;
-            if (frameData != null)
-            {
-                lock (frameData)
-                {
-                    if (currentFrameID != frameData.FrameID)
-                    {
-                        currentFrameID = frameData.FrameID;
-                        Utility.Timer.start("DebugWindow.update::updateImages");
-                        updateImages(frameData);
-                        Utility.Timer.stop("DebugWindow.update::updateImages");
-                    }
-                }
-            }
-
-            if (!guiUpToDate)
-            {
-                Utility.Timer.start("DebugWindow.update::updateGUI");
-                updateGUI();
-                Utility.Timer.stop("DebugWindow.update::updateGUI");
-            }
-
-            Utility.Timer.stop("DebugWindow.update");
+            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
+            videoInputProvider.goToNextFrame();
         }
 
         /// <summary>
-        /// Updates the debug images.
+        /// Jumps to the previous movie frame.
         /// </summary>
-        /// <param name="frameData">data for the new frame</param>
-        private void updateImages(FrameData frameData)
+        private void handleGoToPreviousFrame()
         {
-            guiUpToDate = false;
-
-            int numRows = palmGridNumRowsTrackBar.Value;
-            int numColumns = palmGridNumColumnsTrackBar.Value;
-            debugImageCreator.updateImages(frameData, numRows, numColumns);
+            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
+            videoInputProvider.goToPreviousFrame();
         }
 
         /// <summary>
-        /// Updates the gui elements.
+        /// Toggles the paused state of the movie.
         /// </summary>
-        private void updateGUI()
+        private void handlePlayPause()
         {
-            // update image boxes
-            depthImageBox.Image = debugImageCreator.DepthImage;
-            fingerImageBox.Image = debugImageCreator.FingerImage;
-            handImageBox.Image = debugImageCreator.HandImage;
-            palmImageBox.Image = debugImageCreator.PalmImage;
-            touchImageBox.Image = debugImageCreator.TouchImage;
+            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
 
-            // update frame label
-            frameLabel.Text = "Frame: " + currentFrameID;
+            if (videoInputProvider.IsPaused)
+            {
+                videoInputProvider.play();
+                playPauseButton.Text = "Pause";
+                nextFrameButton.Enabled = false;
+                previousFrameButton.Enabled = false;
+            }
+            else
+            {
+                videoInputProvider.pause();
+                playPauseButton.Text = "Play";
+                nextFrameButton.Enabled = true;
+                previousFrameButton.Enabled = true;
+            }
+        }
 
-            guiUpToDate = true;
+        /// <summary>
+        /// Handles the click on the next frame button.
+        /// </summary>
+        /// <param name="sender">event sender</param>
+        /// <param name="e">event arguments</param>
+        private void nextFrameButton_Click(object sender, EventArgs e)
+        {
+            handleGoToNextFrame();
         }
 
         /// <summary>
-        /// Handles the click on the play / pause button.
+        /// Updates the window when the number of rows or columns in the palm grid are changed.
         /// </summary>
         /// <param name="sender">event sender</param>
         /// <param name="e">event arguments</param>
-        private void playPauseButton_Click(object sender, EventArgs e)
+        private void palmGridTrackBar_Scroll(object sender, EventArgs e)
         {
-            handlePlayPause();
+            currentFrameID = -1;
+            update(sender, e);
         }
 
         /// <summary>
-        /// Handles the click on the next frame button.
+        /// Handles the click on the play / pause button.
         /// </summary>
         /// <param name="sender">event sender</param>
         /// <param name="e">event arguments</param>
-        private void nextFrameButton_Click(object sender, EventArgs e)
+        private void playPauseButton_Click(object sender, EventArgs e)
         {
-            handleGoToNextFrame();
+            handlePlayPause();
         }
 
         /// <summary>
@@ -194,55 +168,71 @@ namespace bbiwarg.Output.DebugOutput
         }
 
         /// <summary>
-        /// Toggles the paused state of the movie.
+        /// Updates the window.
         /// </summary>
-        private void handlePlayPause()
+        /// <param name="sender">the event sender</param>
+        /// <param name="e">the event arguments</param>
+        private void update(object sender, EventArgs e)
         {
-            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
+            Utility.Timer.start("DebugWindow.update");
 
-            if (videoInputProvider.IsPaused)
+            if (!inputProvider.IsActive)
+                Close();
+
+            FrameData frameData = inputHandler.FrameData;
+            if (frameData != null)
             {
-                videoInputProvider.play();
-                playPauseButton.Text = "Pause";
-                nextFrameButton.Enabled = false;
-                previousFrameButton.Enabled = false;
+                lock (frameData)
+                {
+                    if (currentFrameID != frameData.FrameID)
+                    {
+                        currentFrameID = frameData.FrameID;
+                        Utility.Timer.start("DebugWindow.update::updateImages");
+                        updateImages(frameData);
+                        Utility.Timer.stop("DebugWindow.update::updateImages");
+                    }
+                }
             }
-            else
+
+            if (!guiUpToDate)
             {
-                videoInputProvider.pause();
-                playPauseButton.Text = "Play";
-                nextFrameButton.Enabled = true;
-                previousFrameButton.Enabled = true;
+                Utility.Timer.start("DebugWindow.update::updateGUI");
+                updateGUI();
+                Utility.Timer.stop("DebugWindow.update::updateGUI");
             }
-        }
 
-        /// <summary>
-        /// Jumps to the next movie frame.
-        /// </summary>
-        private void handleGoToNextFrame()
-        {
-            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
-            videoInputProvider.goToNextFrame();
+            Utility.Timer.stop("DebugWindow.update");
         }
 
         /// <summary>
-        /// Jumps to the previous movie frame.
+        /// Updates the gui elements.
         /// </summary>
-        private void handleGoToPreviousFrame()
+        private void updateGUI()
         {
-            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
-            videoInputProvider.goToPreviousFrame();
+            // update image boxes
+            depthImageBox.Image = debugImageCreator.DepthImage;
+            fingerImageBox.Image = debugImageCreator.FingerImage;
+            handImageBox.Image = debugImageCreator.HandImage;
+            palmImageBox.Image = debugImageCreator.PalmImage;
+            touchImageBox.Image = debugImageCreator.TouchImage;
+
+            // update frame label
+            frameLabel.Text = "Frame: " + currentFrameID;
+
+            guiUpToDate = true;
         }
 
         /// <summary>
-        /// Updates the window when the number of rows or columns in the palm grid are changed.
+        /// Updates the debug images.
         /// </summary>
-        /// <param name="sender">event sender</param>
-        /// <param name="e">event arguments</param>
-        private void palmGridTrackBar_Scroll(object sender, EventArgs e)
+        /// <param name="frameData">data for the new frame</param>
+        private void updateImages(FrameData frameData)
         {
-            currentFrameID = -1;
-            update(sender, e);
+            guiUpToDate = false;
+
+            int numRows = palmGridNumRowsTrackBar.Value;
+            int numColumns = palmGridNumColumnsTrackBar.Value;
+            debugImageCreator.updateImages(frameData, numRows, numColumns);
         }
     }
-}
+}

+ 71 - 74
bbiwarg/Output/DebugOutput/TouchEventVisualizer.cs

@@ -1,36 +1,33 @@
-using System;
+using bbiwarg.Input.InputHandling;
+using bbiwarg.Recognition.TouchRecognition;
+using bbiwarg.Utility;
+using System;
 using System.Collections.Generic;
-using System.Drawing;
 using System.Diagnostics;
+using System.Drawing;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.TouchRecognition;
-using bbiwarg.Utility;
-using bbiwarg.Input.InputHandling;
 
 namespace bbiwarg.Output.DebugOutput
 {
     /// <summary>
     /// Provides an image showing touch events.
     /// </summary>
-    class TouchEventVisualizer
+    internal class TouchEventVisualizer
     {
         /// <summary>
-        /// used to prevent running <see cref="handleNewFrameData"/> and <see cref="getOutputImage"/> simultaneously from different threads
+        /// all touch events starting at the last TouchDown, indexed by a unique id
         /// </summary>
-        private Object sync;
+        private Dictionary<int, List<Vector2D>> activeTouches;
 
         /// <summary>
-        /// used to store the relative time at which the touch events occured
+        /// relative times of last frame updates which are stored for a limited time, indexed by a unique id
         /// </summary>
-        private Stopwatch timer;
-
+        private Dictionary<int, long> lastUpdates;
 
         /// <summary>
-        /// all touch events starting at the last TouchDown, indexed by a unique id
+        /// the next free id, used as a unique id for the dictionaries
         /// </summary>
-        private Dictionary<int, List<Vector2D>> activeTouches;
+        private int nextFreeID;
 
         /// <summary>
         /// old touch events which are stored for a limited time, indexed by a unique id
@@ -38,15 +35,14 @@ namespace bbiwarg.Output.DebugOutput
         private Dictionary<int, List<Vector2D>> oldTouches;
 
         /// <summary>
-        /// relative times of last frame updates which are stored for a limited time, indexed by a unique id
+        /// used to prevent running <see cref="handleNewFrameData"/> and <see cref="getOutputImage"/> simultaneously from different threads
         /// </summary>
-        private Dictionary<int, long> lastUpdates;
+        private Object sync;
 
         /// <summary>
-        /// the next free id, used as a unique id for the dictionaries
+        /// used to store the relative time at which the touch events occured
         /// </summary>
-        private int nextFreeID;
-
+        private Stopwatch timer;
 
         /// <summary>
         /// Creates a TouchEventVisualizer.
@@ -57,59 +53,6 @@ namespace bbiwarg.Output.DebugOutput
             reset();
         }
 
-        /// <summary>
-        /// Resets the touch events and the timer.
-        /// </summary>
-        public void reset()
-        {
-            timer = new Stopwatch();
-            timer.Start();
-
-            nextFreeID = 1;
-            activeTouches = new Dictionary<int, List<Vector2D>>();
-            oldTouches = new Dictionary<int, List<Vector2D>>();
-            lastUpdates = new Dictionary<int, long>();
-
-        }
-
-        /// <summary>
-        /// Handles the event that a new frame is finished processing by updating the touch events.
-        /// </summary>
-        /// <param name="sender">event sender</param>
-        /// <param name="e">event arguments</param>
-        public void handleNewFrameData(object sender, NewProcessedFrameEventArgs e)
-        {
-            FrameData frameData = e.FrameData;
-            lock (frameData) lock (sync)
-                {
-                    if (frameData.ResetFlag)
-                        reset();
-
-                    foreach (TouchEvent te in frameData.TouchEvents)
-                    {
-                        switch (te.Type)
-                        {
-                            case TouchEventType.Down:
-                                activeTouches.Add(te.Touch.TrackID, new List<Vector2D>());
-                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
-                                break;
-                            case TouchEventType.Move:
-                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
-                                break;
-                            case TouchEventType.Up:
-                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
-
-                                oldTouches.Add(nextFreeID, activeTouches[te.Touch.TrackID]);
-                                lastUpdates.Add(nextFreeID, timer.ElapsedMilliseconds);
-
-                                activeTouches.Remove(te.Touch.TrackID);
-                                nextFreeID++;
-                                break;
-                        }
-                    }
-                }
-        }
-
         /// <summary>
         /// Returns an output image showing the touch events.
         /// </summary>
@@ -187,6 +130,60 @@ namespace bbiwarg.Output.DebugOutput
             }
         }
 
+        /// <summary>
+        /// Handles the event that a new frame is finished processing by updating the touch events.
+        /// </summary>
+        /// <param name="sender">event sender</param>
+        /// <param name="e">event arguments</param>
+        public void handleNewFrameData(object sender, NewProcessedFrameEventArgs e)
+        {
+            FrameData frameData = e.FrameData;
+            lock (frameData) lock (sync)
+                {
+                    if (frameData.ResetFlag)
+                        reset();
+
+                    foreach (TouchEvent te in frameData.TouchEvents)
+                    {
+                        switch (te.Type)
+                        {
+                            case TouchEventType.Down:
+                                activeTouches.Add(te.Touch.TrackID, new List<Vector2D>());
+                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
+                                break;
+
+                            case TouchEventType.Move:
+                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
+                                break;
+
+                            case TouchEventType.Up:
+                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
+
+                                oldTouches.Add(nextFreeID, activeTouches[te.Touch.TrackID]);
+                                lastUpdates.Add(nextFreeID, timer.ElapsedMilliseconds);
+
+                                activeTouches.Remove(te.Touch.TrackID);
+                                nextFreeID++;
+                                break;
+                        }
+                    }
+                }
+        }
+
+        /// <summary>
+        /// Resets the touch events and the timer.
+        /// </summary>
+        public void reset()
+        {
+            timer = new Stopwatch();
+            timer.Start();
+
+            nextFreeID = 1;
+            activeTouches = new Dictionary<int, List<Vector2D>>();
+            oldTouches = new Dictionary<int, List<Vector2D>>();
+            lastUpdates = new Dictionary<int, long>();
+        }
+
         /// <summary>
         /// Removes old touch events and update times.
         /// </summary>
@@ -205,4 +202,4 @@ namespace bbiwarg.Output.DebugOutput
             }
         }
     }
-}
+}

+ 89 - 97
bbiwarg/Output/GlassesOutput/GlassesWindow.cs

@@ -1,18 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using bbiwarg.Input.InputHandling;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Input.InputProviding;
-using bbiwarg.Utility;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.PalmRecognition;
-using Emgu.CV.UI;
+using bbiwarg.Utility;
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
 
 namespace bbiwarg.Output.GlassesOutput
 {
@@ -22,19 +16,14 @@ namespace bbiwarg.Output.GlassesOutput
     public partial class GlassesWindow : Form
     {
         /// <summary>
-        /// the input provider
-        /// </summary>
-        private InputProvider inputProvider;
-
-        /// <summary>
-        /// the input handler
+        /// true iff the calibration image has the latest data
         /// </summary>
-        private InputHandler inputHandler;
+        private bool calibrationImageUpToDate;
 
         /// <summary>
-        /// timer to periodically update the window
+        /// position of the current calibration point in the output plane
         /// </summary>
-        private System.Windows.Forms.Timer timer;
+        private Vector2D currentCalibrationPoint;
 
         /// <summary>
         /// id of the current frame
@@ -47,40 +36,44 @@ namespace bbiwarg.Output.GlassesOutput
         private bool guiUpToDate;
 
         /// <summary>
-        /// size of the input images
+        /// the image shown on the glasses
         /// </summary>
-        private ImageSize inputSize;
+        private OutputImage image;
 
         /// <summary>
-        /// size of the image show on the glasses
+        /// the input handler
         /// </summary>
-        private ImageSize outputSize;
+        private InputHandler inputHandler;
 
         /// <summary>
-        /// the image shown on the glasses
+        /// the input provider
         /// </summary>
-        private OutputImage image;
+        private InputProvider inputProvider;
 
         /// <summary>
-        /// projection from the input image plane to a plane which lies in front of the wearer of the glasses (output plane)
+        /// size of the input images
         /// </summary>
-        private Projection2DTo2D projection;
+        private ImageSize inputSize;
 
         /// <summary>
-        /// position of the current calibration point in the output plane
+        /// size of the image show on the glasses
         /// </summary>
-        private Vector2D currentCalibrationPoint;
+        private ImageSize outputSize;
 
         /// <summary>
-        /// true iff the calibration image has the latest data
+        /// projection from the input image plane to a plane which lies in front of the wearer of the glasses (output plane)
         /// </summary>
-        private bool calibrationImageUpToDate;
+        private Projection2DTo2D projection;
 
         /// <summary>
         /// random number generator
         /// </summary>
         private Random rand;
 
+        /// <summary>
+        /// timer to periodically update the window
+        /// </summary>
+        private System.Windows.Forms.Timer timer;
 
         /// <summary>
         /// Creates a GlassesWindow.
@@ -131,6 +124,48 @@ namespace bbiwarg.Output.GlassesOutput
             inputProvider.stop();
         }
 
+        /// <summary>
+        /// Returns a random point in the glasses image.
+        /// </summary>
+        /// <returns></returns>
+        private Vector2D getRandomOutputPoint()
+        {
+            return outputSize.getAbsolutePoint(new Vector2D((float)rand.NextDouble(), (float)rand.NextDouble()));
+        }
+
+        /// <summary>
+        /// Handle key down events by showing the next point or finishing or resetting the calibration.
+        /// </summary>
+        /// <param name="sender">event sender</param>
+        /// <param name="e">event arguments</param>
+        private void GlassesWindow_OnKeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.K)
+            {
+                FrameData frameData = inputHandler.FrameData;
+                if (frameData != null)
+                {
+                    lock (frameData)
+                    {
+                        if (frameData.TrackedFingers.Count == 1)
+                        {
+                            Vector2D pointOutput = currentCalibrationPoint;
+                            Vector2D pointInput = frameData.TrackedFingers[0].TipPoint;
+
+                            projection.addCalibrationPoints(pointInput, pointOutput);
+
+                            currentCalibrationPoint = getRandomOutputPoint();
+                        }
+                    }
+                }
+            }
+            else if (e.KeyCode == Keys.R)
+            {
+                projection.reset();
+                currentCalibrationPoint = getRandomOutputPoint();
+            }
+        }
+
         /// <summary>
         /// Updates the window.
         /// </summary>
@@ -176,37 +211,6 @@ namespace bbiwarg.Output.GlassesOutput
             Utility.Timer.stop("GlassesWindow.update");
         }
 
-        /// <summary>
-        /// Updates the glasses image.
-        /// </summary>
-        /// <param name="frameData">data for the new frame</param>
-        private void updateImage(FrameData frameData)
-        {
-            guiUpToDate = false;
-
-            if (image != null)
-                image.Dispose();
-
-            image = new OutputImage(outputSize);
-            foreach (Palm palm in frameData.TrackedPalms)
-            {
-                Quadrangle quadInput = palm.Quad;
-                Vector2D a = projection.projectPoint(quadInput.TopLeft);
-                Vector2D b = projection.projectPoint(quadInput.TopRight);
-                Vector2D c = projection.projectPoint(quadInput.BottomRight);
-                Vector2D d = projection.projectPoint(quadInput.BottomLeft);
-                Quadrangle quadOutput = new Quadrangle(a, b, c, d);
-                image.drawQuadrangleGrid(quadOutput, Color.Yellow, Color.Orange, 3, 4);
-            }
-
-            foreach (Finger finger in frameData.TrackedFingers)
-            {
-                Vector2D tipProjected = projection.projectPoint(finger.TipPoint);
-                image.fillCircle(tipProjected, 10, Color.Yellow);
-            }
-
-        }
-
         /// <summary>
         /// Updates the calibration image.
         /// </summary>
@@ -233,45 +237,33 @@ namespace bbiwarg.Output.GlassesOutput
         }
 
         /// <summary>
-        /// Handle key down events by showing the next point or finishing or resetting the calibration.
+        /// Updates the glasses image.
         /// </summary>
-        /// <param name="sender">event sender</param>
-        /// <param name="e">event arguments</param>
-        private void GlassesWindow_OnKeyDown(object sender, KeyEventArgs e)
+        /// <param name="frameData">data for the new frame</param>
+        private void updateImage(FrameData frameData)
         {
-            if (e.KeyCode == Keys.K)
-            {
-                FrameData frameData = inputHandler.FrameData;
-                if (frameData != null)
-                {
-                    lock (frameData)
-                    {
-                        if (frameData.TrackedFingers.Count == 1)
-                        {
-                            Vector2D pointOutput = currentCalibrationPoint;
-                            Vector2D pointInput = frameData.TrackedFingers[0].TipPoint;
+            guiUpToDate = false;
 
-                            projection.addCalibrationPoints(pointInput, pointOutput);
+            if (image != null)
+                image.Dispose();
 
-                            currentCalibrationPoint = getRandomOutputPoint();
-                        }
-                    }
-                }
-            }
-            else if (e.KeyCode == Keys.R)
+            image = new OutputImage(outputSize);
+            foreach (Palm palm in frameData.TrackedPalms)
             {
-                projection.reset();
-                currentCalibrationPoint = getRandomOutputPoint();
+                Quadrangle quadInput = palm.Quad;
+                Vector2D a = projection.projectPoint(quadInput.TopLeft);
+                Vector2D b = projection.projectPoint(quadInput.TopRight);
+                Vector2D c = projection.projectPoint(quadInput.BottomRight);
+                Vector2D d = projection.projectPoint(quadInput.BottomLeft);
+                Quadrangle quadOutput = new Quadrangle(a, b, c, d);
+                image.drawQuadrangleGrid(quadOutput, Color.Yellow, Color.Orange, 3, 4);
             }
-        }
 
-        /// <summary>
-        /// Returns a random point in the glasses image.
-        /// </summary>
-        /// <returns></returns>
-        private Vector2D getRandomOutputPoint()
-        {
-            return outputSize.getAbsolutePoint(new Vector2D((float)rand.NextDouble(), (float)rand.NextDouble()));
+            foreach (Finger finger in frameData.TrackedFingers)
+            {
+                Vector2D tipProjected = projection.projectPoint(finger.TipPoint);
+                image.fillCircle(tipProjected, 10, Color.Yellow);
+            }
         }
     }
-}
+}

+ 106 - 112
bbiwarg/Output/OutputImage.cs

@@ -1,20 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Drawing;
-using bbiwarg.Utility;
-
+using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
 
 namespace bbiwarg.Output
 {
     /// <summary>
     /// An <see cref="Image"/> which provides additional drawing functions.
     /// </summary>
-    class OutputImage : Image<Rgb, byte>
+    internal class OutputImage : Image<Rgb, byte>
     {
         /// <summary>
         /// Creates an OutputImage.
@@ -35,30 +31,13 @@ namespace bbiwarg.Output
         {
         }
 
-
-        /// <summary>
-        /// Returns the color at a position.
-        /// </summary>
-        /// <param name="x">x coordinate of the position</param>
-        /// <param name="y">y coordinate of the position</param>
-        /// <returns>color at position (x, y)</returns>
-        public Color getColorAt(int x, int y)
-        {
-            byte red = Data[y, x, 0];
-            byte green = Data[y, x, 1];
-            byte blue = Data[y, x, 2];
-            return Color.FromArgb(red, green, blue);
-        }
-
         /// <summary>
-        /// Draws a line segment.
+        /// Draws a border around the image.
         /// </summary>
-        /// <param name="lineSegment">line segment to draw</param>
-        /// <param name="color">color used to draw the line segment</param>
-        /// <param name="thickness">thickness of the line segment</param>
-        public void drawLineSegment(bbiwarg.Utility.LineSegment2D lineSegment, Color color, int thickness = 1)
+        /// <param name="color">color used to draw the border</param>
+        public void drawBorder(Color color)
         {
-            Draw(new Emgu.CV.Structure.LineSegment2D(lineSegment.P1, lineSegment.P2), new Rgb(color), thickness);
+            drawRectangle(new Rectangle(0, 0, Width, Height), color);
         }
 
         /// <summary>
@@ -73,76 +52,72 @@ namespace bbiwarg.Output
         }
 
         /// <summary>
-        /// Colors a pixel.
-        /// </summary>
-        /// <param name="position">position of the pixel</param>
-        /// <param name="color">new color for pixel</param>
-        public void drawPixel(Point position, Color color)
-        {
-            Data[position.Y, position.X, 0] = color.R;
-            Data[position.Y, position.X, 0] = color.G;
-            Data[position.Y, position.X, 0] = color.B;
-        }
-
-        /// <summary>
-        /// Draws a filled circle.
+        /// Draws a convexity defect.
         /// </summary>
-        /// <param name="position">center of the circle</param>
-        /// <param name="radius">radius of the circle</param>
-        /// <param name="color">color used to draw the circle</param>
-        public void fillCircle(Point position, float radius, Color color)
+        /// <param name="defect">the defect to draw</param>
+        /// <param name="pointColor">color used to draw the points of the defect</param>
+        /// <param name="lineColor">color used to draw the lines of the defect</param>
+        public void drawDefect(ConvexityDefect defect, Color pointColor, Color lineColor)
         {
-            Draw(new CircleF(position, radius), new Rgb(color), 0);
-        }
+            drawLineSegment(new Utility.LineSegment2D(defect.OuterShort, defect.Inner), lineColor);
+            drawLineSegment(new Utility.LineSegment2D(defect.OuterLong, defect.Inner), lineColor);
 
-        /// <summary>
-        /// Draws a filled rectangle.
-        /// </summary>
-        /// <param name="rect">the rectangle</param>
-        /// <param name="color">color used to fill the rectangle</param>
-        public void fillRectangle(Rectangle rect, Color color)
-        {
-            Draw(rect, new Rgb(color), -1);
+            fillCircle(defect.Inner, 2, pointColor);
+            fillCircle(defect.OuterShort, 2, pointColor);
+            fillCircle(defect.OuterLong, 2, pointColor);
         }
 
         /// <summary>
-        /// Draws a unfilled rectangle.
+        /// Draws a grayscale image into channels of the image.
         /// </summary>
-        /// <param name="rect">the rectangle</param>
-        /// <param name="color">color used to raw the rectangle</param>
-        /// <param name="thichness">thickness of the rectangle</param>
-        public void drawRectangle(Rectangle rect, Color color, int thichness = 0)
+        /// <param name="image">the image to draw</param>
+        /// <param name="color">if a color component is != 0 the corresponding image channel is drawn to and image is scaled by (color component value / 255)</param>
+        public void drawImage(Image<Gray, byte> image, Color color)
         {
-            Draw(rect, new Rgb(color), thichness);
+            if (color.R != 0)
+            {
+                if (color.R != byte.MaxValue)
+                    this[0] = this[0].Or(image.Mul((float)color.R / byte.MaxValue));
+                else
+                    this[0] = this[0].Or(image);
+            }
+            if (color.G != 0)
+            {
+                if (color.G != byte.MaxValue)
+                    this[1] = this[1].Or(image.Mul((float)color.G / byte.MaxValue));
+                else
+                    this[1] = this[1].Or(image);
+            }
+            if (color.B != 0)
+            {
+                if (color.B != byte.MaxValue)
+                    this[2] = this[2].Or(image.Mul((float)color.B / byte.MaxValue));
+                else
+                    this[2] = this[2].Or(image);
+            }
         }
 
         /// <summary>
-        /// Draws text.
+        /// Draws a line segment.
         /// </summary>
-        /// <param name="position">top left corner to draw the text at</param>
-        /// <param name="text">the text to draw</param>
-        /// <param name="color">color used to draw the text</param>
-        public void drawText(Point position, String text, Color color)
+        /// <param name="lineSegment">line segment to draw</param>
+        /// <param name="color">color used to draw the line segment</param>
+        /// <param name="thickness">thickness of the line segment</param>
+        public void drawLineSegment(bbiwarg.Utility.LineSegment2D lineSegment, Color color, int thickness = 1)
         {
-            MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 1, 1);
-            Draw(text, ref font, position, new Rgb(color));
+            Draw(new Emgu.CV.Structure.LineSegment2D(lineSegment.P1, lineSegment.P2), new Rgb(color), thickness);
         }
 
         /// <summary>
-        /// Draws a convexity defect.
+        /// Colors a pixel.
         /// </summary>
-        /// <param name="defect">the defect to draw</param>
-        /// <param name="pointColor">color used to draw the points of the defect</param>
-        /// <param name="lineColor">color used to draw the lines of the defect</param>
-        public void drawDefect(ConvexityDefect defect, Color pointColor, Color lineColor)
+        /// <param name="position">position of the pixel</param>
+        /// <param name="color">new color for pixel</param>
+        public void drawPixel(Point position, Color color)
         {
-            drawLineSegment(new Utility.LineSegment2D(defect.OuterShort, defect.Inner), lineColor);
-            drawLineSegment(new Utility.LineSegment2D(defect.OuterLong, defect.Inner), lineColor);
-
-            fillCircle(defect.Inner, 2, pointColor);
-            fillCircle(defect.OuterShort, 2, pointColor);
-            fillCircle(defect.OuterLong, 2, pointColor);
-
+            Data[position.Y, position.X, 0] = color.R;
+            Data[position.Y, position.X, 0] = color.G;
+            Data[position.Y, position.X, 0] = color.B;
         }
 
         /// <summary>
@@ -182,12 +157,26 @@ namespace bbiwarg.Output
         }
 
         /// <summary>
-        /// Draws a border around the image.
+        /// Draws a unfilled rectangle.
         /// </summary>
-        /// <param name="color">color used to draw the border</param>
-        public void drawBorder(Color color)
+        /// <param name="rect">the rectangle</param>
+        /// <param name="color">color used to raw the rectangle</param>
+        /// <param name="thichness">thickness of the rectangle</param>
+        public void drawRectangle(Rectangle rect, Color color, int thichness = 0)
         {
-            drawRectangle(new Rectangle(0, 0, Width, Height), color);
+            Draw(rect, new Rgb(color), thichness);
+        }
+
+        /// <summary>
+        /// Draws text.
+        /// </summary>
+        /// <param name="position">top left corner to draw the text at</param>
+        /// <param name="text">the text to draw</param>
+        /// <param name="color">color used to draw the text</param>
+        public void drawText(Point position, String text, Color color)
+        {
+            MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 1, 1);
+            Draw(text, ref font, position, new Rgb(color));
         }
 
         /// <summary>
@@ -212,33 +201,38 @@ namespace bbiwarg.Output
         }
 
         /// <summary>
-        /// Draws a grayscale image into channels of the image.  
+        /// Draws a filled circle.
         /// </summary>
-        /// <param name="image">the image to draw</param>
-        /// <param name="color">if a color component is != 0 the corresponding image channel is drawn to and image is scaled by (color component value / 255)</param>
-        public void drawImage(Image<Gray, byte> image, Color color)
+        /// <param name="position">center of the circle</param>
+        /// <param name="radius">radius of the circle</param>
+        /// <param name="color">color used to draw the circle</param>
+        public void fillCircle(Point position, float radius, Color color)
         {
-            if (color.R != 0)
-            {
-                if (color.R != byte.MaxValue)
-                    this[0] = this[0].Or(image.Mul((float)color.R / byte.MaxValue));
-                else
-                    this[0] = this[0].Or(image);
-            }
-            if (color.G != 0)
-            {
-                if (color.G != byte.MaxValue)
-                    this[1] = this[1].Or(image.Mul((float)color.G / byte.MaxValue));
-                else
-                    this[1] = this[1].Or(image);
-            }
-            if (color.B != 0)
-            {
-                if (color.B != byte.MaxValue)
-                    this[2] = this[2].Or(image.Mul((float)color.B / byte.MaxValue));
-                else
-                    this[2] = this[2].Or(image);
-            }
+            Draw(new CircleF(position, radius), new Rgb(color), 0);
+        }
+
+        /// <summary>
+        /// Draws a filled rectangle.
+        /// </summary>
+        /// <param name="rect">the rectangle</param>
+        /// <param name="color">color used to fill the rectangle</param>
+        public void fillRectangle(Rectangle rect, Color color)
+        {
+            Draw(rect, new Rgb(color), -1);
+        }
+
+        /// <summary>
+        /// Returns the color at a position.
+        /// </summary>
+        /// <param name="x">x coordinate of the position</param>
+        /// <param name="y">y coordinate of the position</param>
+        /// <returns>color at position (x, y)</returns>
+        public Color getColorAt(int x, int y)
+        {
+            byte red = Data[y, x, 0];
+            byte green = Data[y, x, 1];
+            byte blue = Data[y, x, 2];
+            return Color.FromArgb(red, green, blue);
         }
     }
-}
+}

+ 206 - 235
bbiwarg/Parameters.cs

@@ -1,12 +1,6 @@
-using System;
-using System.Collections.Generic;
+using bbiwarg.Utility;
+using System;
 using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Net;
-
-using bbiwarg.Utility;
 
 namespace bbiwarg
 {
@@ -22,52 +16,49 @@ namespace bbiwarg
     /// <summary>
     /// Defines all parameters used in the whole program.
     /// </summary>
-    static class Parameters
+    internal static class Parameters
     {
         #region console
 
-        /// <summary>
-        /// with of the console in monospace characters
-        /// </summary>
-        public static readonly int ConsoleWidth = 90;
-
         /// <summary>
         /// height of the console in monospace characters
         /// </summary>
         public static readonly int ConsoleHeight = 30;
 
-        #endregion
+        /// <summary>
+        /// with of the console in monospace characters
+        /// </summary>
+        public static readonly int ConsoleWidth = 90;
 
+        #endregion console
 
         #region input
 
-        /// <summary>
-        /// the input source type
-        /// </summary>
-        public static readonly InputType InputSource = InputType.Movie;
-
         /// <summary>
         /// path to the movie file used as input source
         /// </summary>
         public static readonly String InputMoviePath = "..\\..\\videos\\touch\\4.skv";
 
-        #endregion
+        /// <summary>
+        /// the input source type
+        /// </summary>
+        public static readonly InputType InputSource = InputType.Movie;
 
+        #endregion input
 
         #region Logger
 
-        /// <summary>
-        /// true iff the timer output should be shown
-        /// </summary>
-        public static readonly bool LoggerTimerOutputEnabled = true;
-
         /// <summary>
         /// bitfield which specifies which subjects should be logged
         /// </summary>
         public static readonly LogSubject LoggerEnabledSubjects = LogSubject.None;
 
-        #endregion
+        /// <summary>
+        /// true iff the timer output should be shown
+        /// </summary>
+        public static readonly bool LoggerTimerOutputEnabled = true;
 
+        #endregion Logger
 
         #region DebugWindow
 
@@ -76,18 +67,17 @@ namespace bbiwarg
         /// </summary>
         public static readonly bool DebugWindowEnabled = true;
 
-        /// <summary>
-        /// the update interval for the debug window
-        /// </summary>
-        public static readonly int DebugWindowUpdateIntervall = 1000 / 30; // 30fps
-
         /// <summary>
         /// the title of the debug window
         /// </summary>
         public static readonly String DebugWindowTitle = "BBIWARG - DebugOutput";
 
-        #endregion
+        /// <summary>
+        /// the update interval for the debug window
+        /// </summary>
+        public static readonly int DebugWindowUpdateIntervall = 1000 / 30; // 30fps
 
+        #endregion DebugWindow
 
         #region GlassesWindow
 
@@ -97,9 +87,9 @@ namespace bbiwarg
         public static readonly bool GlassesWindowEnabled = false;
 
         /// <summary>
-        /// the update interval for the glasses window
+        /// number of calibration points
         /// </summary>
-        public static readonly int GlassesWindowUpdateInterval = 1000 / 30; // 30fps
+        public static readonly int GlassesWindowNumCalibrationPoints = 20;
 
         /// <summary>
         /// the titel of the debug window
@@ -107,20 +97,14 @@ namespace bbiwarg
         public static readonly String GlassesWindowTitle = "BBIWARG - GlassesOutput";
 
         /// <summary>
-        /// number of calibration points
+        /// the update interval for the glasses window
         /// </summary>
-        public static readonly int GlassesWindowNumCalibrationPoints = 20;
-
-        #endregion
+        public static readonly int GlassesWindowUpdateInterval = 1000 / 30; // 30fps
 
+        #endregion GlassesWindow
 
         #region tuio
 
-        /// <summary>
-        /// true iff the tuio server is enabled
-        /// </summary>
-        public static readonly bool TuioEnabledByDefault = true;
-
         /// <summary>
         /// the default ip address of the tuio server
         /// </summary>
@@ -131,8 +115,12 @@ namespace bbiwarg
         /// </summary>
         public static readonly Int16 TuioDefaultPort = 3333;
 
-        #endregion
+        /// <summary>
+        /// true iff the tuio server is enabled
+        /// </summary>
+        public static readonly bool TuioEnabledByDefault = true;
 
+        #endregion tuio
 
         #region ConfidenceImage
 
@@ -141,48 +129,47 @@ namespace bbiwarg
         /// </summary>
         public static readonly int ConfidenceImageMinThreshold = 500;
 
-        #endregion
-
+        #endregion ConfidenceImage
 
         #region DepthImage
 
         /// <summary>
-        /// the size of the median filter used to filter the depth image
+        /// the depth range which is considered important (in mm)
         /// </summary>
-        public static readonly int DepthImageMedianSize = 5;
+        public static readonly int DepthImageDepthRange = 200;
 
         /// <summary>
-        /// the depth range which is considered important (in mm)
+        /// the size of the median filter used to filter the depth image
         /// </summary>
-        public static readonly int DepthImageDepthRange = 200; // <255
+        public static readonly int DepthImageMedianSize = 5;
 
-        #endregion
+        // <255
 
+        #endregion DepthImage
 
         #region EdgeImage
 
         /// <summary>
-        /// start threshold for the canny edge detector used to detect edges in the depth image
+        /// linking threshold for the canny edge detector used to detect edges in the depth image
         /// </summary>
-        public static readonly int EdgeImageCannyStartThreshold = 80;
+        public static readonly int EdgeImageCannyLinkingThreshold = 60;
 
         /// <summary>
-        /// linking threshold for the canny edge detector used to detect edges in the depth image 
+        /// filter size for the canny edge detector used to detect edges in the depth image
         /// </summary>
-        public static readonly int EdgeImageCannyLinkingThreshold = 60;
+        public static readonly int EdgeImageCannySize = 3;
 
         /// <summary>
-        /// filter size for the canny edge detector used to detect edges in the depth image  
+        /// start threshold for the canny edge detector used to detect edges in the depth image
         /// </summary>
-        public static readonly int EdgeImageCannySize = 3;
+        public static readonly int EdgeImageCannyStartThreshold = 80;
 
         /// <summary>
         /// number of dilation iterations to generate the rough edge image from the edge image
         /// </summary>
         public static readonly int EdgeImageRoughNumDilationIterations = 1;
 
-        #endregion
-
+        #endregion EdgeImage
 
         #region general tracking
 
@@ -191,11 +178,20 @@ namespace bbiwarg
         /// </summary>
         public static readonly float TrackerMaxRelativeMove = 0.25f;
 
-        #endregion
-
+        #endregion general tracking
 
         #region finger detection
 
+        /// <summary>
+        /// the contour margin around the finger
+        /// </summary>
+        public static readonly int FingerContourMargin = 4;
+
+        /// <summary>
+        /// the maximum depth difference between the finger and a point beside the finger
+        /// </summary>
+        public static readonly int FingerMaxCrippleDifference = 20;
+
         /// <summary>
         /// the number of missed slices until the trail expansion stops
         /// </summary>
@@ -207,9 +203,9 @@ namespace bbiwarg
         public static readonly int FingerMaxSliceLengthDifferencePerStep = 5;
 
         /// <summary>
-        /// the minimum number of slices a finger must have
+        /// maximum finger slice length (in pixels)
         /// </summary>
-        public static readonly int FingerMinNumSlices = 20;
+        public static readonly int FingerMaxWidth2D = 30;
 
         /// <summary>
         /// maximum finger slice length (in mm)
@@ -217,24 +213,21 @@ namespace bbiwarg
         public static readonly float FingerMaxWidth3D = 35f;
 
         /// <summary>
-        /// maximum finger slice length (in pixels)
+        /// the minimum number of slices a finger must have
         /// </summary>
-        public static readonly int FingerMaxWidth2D = 30; // TODO remove and replace with 3Dwidth
+        public static readonly int FingerMinNumSlices = 20;
+
+        // TODO remove and replace with 3Dwidth
 
         /// <summary>
         /// minimum finger slice length (in pixels)
         /// </summary>
         public static readonly int FingerMinWidth2D = 2;
 
-        /// <summary>
-        /// the number of slices that are removed when the finger expansion starts in opposite direction (because inital slices don't have the correct direction)
-        /// </summary>
-        public static readonly int FingerRemoveNumSlicesForCorrection = 10;
-
         /// <summary>
         /// the number of slices used to calculate the start and end directions
         /// </summary>
-        public static readonly int FingerNumSlicesForRelativeDirection = FingerRemoveNumSlicesForCorrection;
+        public static readonly int FingerNumSlicesForRelativeDirection = 5;
 
         /// <summary>
         /// the distance of a point to be considered beside the finger (in pixels)
@@ -242,30 +235,14 @@ namespace bbiwarg
         public static readonly int FingerOutMargin = 6;
 
         /// <summary>
-        /// the maximum depth difference between the finger and a point beside the finger
-        /// </summary>
-        public static readonly int FingerMaxCrippleDifference = 20;
-
-        /// <summary>
-        /// the contour margin around the finger
+        /// the number of slices that are removed when the finger expansion starts in opposite direction (because inital slices don't have the correct direction)
         /// </summary>
-        public static readonly int FingerContourMargin = 4;
-
-        #endregion
+        public static readonly int FingerRemoveNumSlicesForCorrection = 10;
 
+        #endregion finger detection
 
         #region finger tracking
 
-        /// <summary>
-        /// number of frames a finger needs to be detected before it is tracked
-        /// </summary>
-        public static readonly int FingerTrackerNumFramesDetectedUntilTracked = 5;
-
-        /// <summary>
-        /// number of frames a finger needs to be lost before it is deleted
-        /// </summary>
-        public static readonly int FingerTrackerNumFramesLostUntilDeleted = 10;
-
         /// <summary>
         /// xx entry for the measurement noise covariance matrix for the kalman filter used to smooth the finger hand and tip points
         /// </summary>
@@ -282,9 +259,9 @@ namespace bbiwarg
         public static readonly float FingermYY = 0.000005f;
 
         /// <summary>
-        /// number of finger slice directions used to compute the mean finger direction
+        /// if the hand point of a finger moves this relative amount it will have a similarity of 0 to itself at the previous position
         /// </summary>
-        public static readonly int FingerTrackerNumDirectionsForMeanDirection = 10;
+        public static readonly float FingerTrackerMaxHandPointRelativeMove = TrackerMaxRelativeMove;
 
         /// <summary>
         /// if the tip point of a finger moves this relative amount it will have a similarity of 0 to itself at the previous position
@@ -292,19 +269,33 @@ namespace bbiwarg
         public static readonly float FingerTrackerMaxTipPointRelativeMove = TrackerMaxRelativeMove;
 
         /// <summary>
-        /// if the hand point of a finger moves this relative amount it will have a similarity of 0 to itself at the previous position
+        /// number of finger slice directions used to compute the mean finger direction
         /// </summary>
-        public static readonly float FingerTrackerMaxHandPointRelativeMove = TrackerMaxRelativeMove;
+        public static readonly int FingerTrackerNumDirectionsForMeanDirection = 10;
 
-        #endregion
+        /// <summary>
+        /// number of frames a finger needs to be detected before it is tracked
+        /// </summary>
+        public static readonly int FingerTrackerNumFramesDetectedUntilTracked = 5;
 
+        /// <summary>
+        /// number of frames a finger needs to be lost before it is deleted
+        /// </summary>
+        public static readonly int FingerTrackerNumFramesLostUntilDeleted = 10;
+
+        #endregion finger tracking
 
         #region hand detection
 
         /// <summary>
-        /// number of colors used to draw hands
+        /// maximum depth difference below which two sections of a hand which are seperated by a finger are considered to belong to the same hand
         /// </summary>
-        public static readonly int HandNumColors = 3;
+        public static readonly int HandExtendMaxDifference = 40;
+
+        /// <summary>
+        /// maximum size of a hand extension mask relative to the whole image
+        /// </summary>
+        public static readonly float HandExtensionMaxRelativeSize = 0.5f * HandMaxSize;
 
         /// <summary>
         /// maximum downwards depth difference between a pixel and a neighboring pixel belonging to the same hand
@@ -327,14 +318,9 @@ namespace bbiwarg
         public static readonly float HandMinSize = 0.01f;
 
         /// <summary>
-        /// maximum size of a hand extension mask relative to the whole image
-        /// </summary>
-        public static readonly float HandExtensionMaxRelativeSize = 0.5f * HandMaxSize;
-
-        /// <summary>
-        /// maximum depth difference below which two sections of a hand which are seperated by a finger are considered to belong to the same hand
+        /// number of colors used to draw hands
         /// </summary>
-        public static readonly int HandExtendMaxDifference = 40;
+        public static readonly int HandNumColors = 3;
 
         /// <summary>
         /// the maximum distance of the thumb tip point to the outer short point of a convexity defect for possible thumb defects
@@ -342,9 +328,10 @@ namespace bbiwarg
         public static readonly float HandThumbDefectMaxDistanceToThumb = Parameters.FingerMaxWidth2D;
 
         /// <summary>
-        /// the minumum ratio of the thumb length to the length from the depth point to the outer short point of a convexity defect for possible thumb defects
+        /// the maximum ratio of the length from the depth point to the outer short point to
+        /// the length from the depth point to the outer long point of a convexity defect for possible thumb defects
         /// </summary>
-        public static readonly float HandThumbDefectMinThumbShortLengthRatio = 0.75f;
+        public static readonly float HandThumbDefectMaxShortLongLengthRatio = 0.7f;
 
         /// <summary>
         /// the maximum ratio of the thumb length to the length from the depth point to the outer short point of a convexity defect for possible thumb defects
@@ -352,90 +339,87 @@ namespace bbiwarg
         public static readonly float HandThumbDefectMaxThumbShortLengthRatio = 1.1f;
 
         /// <summary>
-        /// the minimum ratio of the length from the depth point to the outer short point to 
+        /// the minimum ratio of the length from the depth point to the outer short point to
         /// the length from the depth point to the outer long point of a convexity defect for possible thumb defects
         /// </summary>
         public static readonly float HandThumbDefectMinShortLongLengthRatio = 0.3f;
+
         /// <summary>
-        /// the maximum ratio of the length from the depth point to the outer short point to 
-        /// the length from the depth point to the outer long point of a convexity defect for possible thumb defects
+        /// the minumum ratio of the thumb length to the length from the depth point to the outer short point of a convexity defect for possible thumb defects
         /// </summary>
-        public static readonly float HandThumbDefectMaxShortLongLengthRatio = 0.7f;
-
-        #endregion
+        public static readonly float HandThumbDefectMinThumbShortLengthRatio = 0.75f;
 
+        #endregion hand detection
 
         #region hand tracker
 
         /// <summary>
-        /// number of frames a hand needs to be detected before it is tracked
+        /// xx entry for the measurement noise covariance matrix for the kalman filter used to smooth the hand centroid
         /// </summary>
-        public static readonly int HandTrackerNumFramesDetectedUntilTracked = 5;
+        public static readonly float HandmXX = 0.0005f;
 
         /// <summary>
-        /// number of frames a hand needs to be lost before it is deleted
+        /// xy and yx entry for the measurement noise covariance matrix for the kalman filter used to smooth the hand centroid
         /// </summary>
-        public static readonly int HandTrackerNumFramesLostUntilDeleted = 5;
+        public static readonly float HandmXY = 0.0f;
 
         /// <summary>
-        /// if the centroid of a hand moves this relative amount it will have a similarity of 0 to itself at the previous position
+        /// yy entry for the measurement noise covariance matrix for the kalman filter used to smooth the hand centroid
         /// </summary>
-        public static readonly float HandTrackerMaxCentroidRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float HandmYY = 0.0005f;
 
         /// <summary>
-        /// xx entry for the measurement noise covariance matrix for the kalman filter used to smooth the hand centroid
+        /// if the centroid of a hand moves this relative amount it will have a similarity of 0 to itself at the previous position
         /// </summary>
-        public static readonly float HandmXX = 0.0005f;
+        public static readonly float HandTrackerMaxCentroidRelativeMove = TrackerMaxRelativeMove;
 
         /// <summary>
-        /// xy and yx entry for the measurement noise covariance matrix for the kalman filter used to smooth the hand centroid
+        /// number of frames a hand needs to be detected before it is tracked
         /// </summary>
-        public static readonly float HandmXY = 0.0f;
+        public static readonly int HandTrackerNumFramesDetectedUntilTracked = 5;
 
         /// <summary>
-        /// yy entry for the measurement noise covariance matrix for the kalman filter used to smooth the hand centroid
+        /// number of frames a hand needs to be lost before it is deleted
         /// </summary>
-        public static readonly float HandmYY = 0.0005f;
-
-        #endregion
+        public static readonly int HandTrackerNumFramesLostUntilDeleted = 5;
 
+        #endregion hand tracker
 
         #region palm detection
 
-        /// <summary>
-        /// number of positions along the forefinger used as starting points to detect the palm width
-        /// </summary>
-        public static readonly int PalmNumPositionsForPalmWidth = 5;
-
         /// <summary>
         /// relative tolerance which specifies when a point is considered to be in the palm grid
         /// </summary>
         public static readonly float PalmInsideTolerance = 0.1f;
 
-        #endregion
+        /// <summary>
+        /// number of positions along the forefinger used as starting points to detect the palm width
+        /// </summary>
+        public static readonly int PalmNumPositionsForPalmWidth = 5;
 
+        #endregion palm detection
 
         #region palm tracker
 
         /// <summary>
-        /// number of frames a palm needs to be detected before it is tracked
+        /// xx entry for the measurement noise covariance matrix for the kalman filter used to smooth the palm grid points
         /// </summary>
-        public static readonly int PalmTrackerNumFramesDetectedUntilTracked = 5;
+        public static readonly float PalmmXX = 0.00005f;
 
         /// <summary>
-        /// number of frames a palm needs to be lost before it is deleted
+        /// xy and yx entry for the measurement noise covariance matrix for the kalman filter used to smooth the palm grid points
         /// </summary>
-        public static readonly int PalmTrackerNumFramesLostUntilDeleted = 5;
+        public static readonly float PalmmXY = 0.0f;
 
         /// <summary>
-        /// if the upper wrist point of the palm grid moves this relative amount it will have a similarity of 0 to itself at the previous position
+        /// yy entry for the measurement noise covariance matrix for the kalman filter used to smooth the palm grid points
         /// </summary>
-        public static readonly float PalmTrackerMaxWristUpperRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float PalmmYY = 0.00005f;
 
         /// <summary>
-        /// if the lower wrist point of the palm grid moves this relative amount it will have a similarity of 0 to itself at the previous position
+        /// if the lower finger point of the palm grid moves this relative amount it will have a similarity of 0 to itself at the previous position
         /// </summary>
-        public static readonly float PalmTrackerMaxWristLowerRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float PalmTrackerMaxFingersLowerRelativeMove = TrackerMaxRelativeMove;
 
         /// <summary>
         /// if the upper finger point of the palm grid moves this relative amount it will have a similarity of 0 to itself at the previous position
@@ -443,50 +427,43 @@ namespace bbiwarg
         public static readonly float PalmTrackerMaxFingersUpperRelativeMove = TrackerMaxRelativeMove;
 
         /// <summary>
-        /// if the lower finger point of the palm grid moves this relative amount it will have a similarity of 0 to itself at the previous position
+        /// if the lower wrist point of the palm grid moves this relative amount it will have a similarity of 0 to itself at the previous position
         /// </summary>
-        public static readonly float PalmTrackerMaxFingersLowerRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float PalmTrackerMaxWristLowerRelativeMove = TrackerMaxRelativeMove;
 
         /// <summary>
-        /// xx entry for the measurement noise covariance matrix for the kalman filter used to smooth the palm grid points
+        /// if the upper wrist point of the palm grid moves this relative amount it will have a similarity of 0 to itself at the previous position
         /// </summary>
-        public static readonly float PalmmXX = 0.00005f;
+        public static readonly float PalmTrackerMaxWristUpperRelativeMove = TrackerMaxRelativeMove;
 
         /// <summary>
-        /// xy and yx entry for the measurement noise covariance matrix for the kalman filter used to smooth the palm grid points
+        /// number of frames a palm needs to be detected before it is tracked
         /// </summary>
-        public static readonly float PalmmXY = 0.0f;
+        public static readonly int PalmTrackerNumFramesDetectedUntilTracked = 5;
 
         /// <summary>
-        /// yy entry for the measurement noise covariance matrix for the kalman filter used to smooth the palm grid points
+        /// number of frames a palm needs to be lost before it is deleted
         /// </summary>
-        public static readonly float PalmmYY = 0.00005f;
-
-        #endregion
+        public static readonly int PalmTrackerNumFramesLostUntilDeleted = 5;
 
+        #endregion palm tracker
 
         #region palm grid
 
-        /// <summary>
-        /// default number of palm grid rows
-        /// </summary>
-        public static readonly int PalmGridDefaultNumRows = 3;
-
         /// <summary>
         /// default number of palm grid columns
         /// </summary>
         public static readonly int PalmGridDefaultNumColumns = 4;
 
-        #endregion
+        /// <summary>
+        /// default number of palm grid rows
+        /// </summary>
+        public static readonly int PalmGridDefaultNumRows = 3;
 
+        #endregion palm grid
 
         #region touch detection
 
-        /// <summary>
-        /// the threshold number of pixels affected by the flood fill (in percentage) to be considered as a touch
-        /// </summary>
-        public static readonly float TouchMinTouchValue = 0.3f;
-
         /// <summary>
         /// the size of the quadrant around the touch positions that is used to determine the touch value
         /// </summary>
@@ -502,6 +479,11 @@ namespace bbiwarg
         /// </summary>
         public static readonly int TouchFloodfillUpDiff = 3;
 
+        /// <summary>
+        /// the threshold number of pixels affected by the flood fill (in percentage) to be considered as a touch
+        /// </summary>
+        public static readonly float TouchMinTouchValue = 0.3f;
+
         /// <summary>
         /// the position adjustment for the start point of the flood fill operation
         /// </summary>
@@ -512,26 +494,10 @@ namespace bbiwarg
         /// </summary>
         public static readonly int TouchTipOutsideFactor = 7;
 
-        #endregion
-
+        #endregion touch detection
 
         #region touch tracking
 
-        /// <summary>
-        /// number of frames an object needs to be detected before it is tracked
-        /// </summary>
-        public static readonly int TouchTrackerNumFramesDetectedUntilTracked = 1;
-
-        /// <summary>
-        /// number of frames an object needs to be lost before it is deleted
-        /// </summary>
-        public static readonly int TouchTrackerNumFramesLostUntilDeleted = 5;
-
-        /// <summary>
-        /// if the absolute position of a tracked touch event moves this relative amount it will have a similarity of 0 to itself at the previous position
-        /// </summary>
-        public static readonly float TouchTrackerMaxAbsolutePositionRelativeMove = TrackerMaxRelativeMove;
-
         /// <summary>
         /// xx entry for the measurement noise covariance matrix for the kalman filter used to smooth touch events
         /// </summary>
@@ -552,8 +518,22 @@ namespace bbiwarg
         /// </summary>
         public static readonly float TouchProcessNoise = 3.0e-4f;
 
-        #endregion
+        /// <summary>
+        /// if the absolute position of a tracked touch event moves this relative amount it will have a similarity of 0 to itself at the previous position
+        /// </summary>
+        public static readonly float TouchTrackerMaxAbsolutePositionRelativeMove = TrackerMaxRelativeMove;
+
+        /// <summary>
+        /// number of frames an object needs to be detected before it is tracked
+        /// </summary>
+        public static readonly int TouchTrackerNumFramesDetectedUntilTracked = 1;
+
+        /// <summary>
+        /// number of frames an object needs to be lost before it is deleted
+        /// </summary>
+        public static readonly int TouchTrackerNumFramesLostUntilDeleted = 5;
 
+        #endregion touch tracking
 
         #region TouchEventVisualizer
 
@@ -562,8 +542,7 @@ namespace bbiwarg
         /// </summary>
         public static readonly int TouchEventVisualizerFadeOutTime = 1500;
 
-        #endregion
-
+        #endregion TouchEventVisualizer
 
         #region homographyExport
 
@@ -572,8 +551,7 @@ namespace bbiwarg
         /// </summary>
         public static readonly String HomographyFileName = "homography.txt";
 
-        #endregion
-
+        #endregion homographyExport
 
         #region colors
 
@@ -589,8 +567,7 @@ namespace bbiwarg
         /// </summary>
         public static readonly Color ColorTracked = Color.Yellow;
 
-        #endregion
-
+        #endregion general
 
         #region images
 
@@ -609,15 +586,14 @@ namespace bbiwarg
         /// </summary>
         public static readonly Color OutputImageBorderColor = Color.White;
 
-        #endregion
-
+        #endregion images
 
         #region finger
 
         /// <summary>
-        /// color used to draw the finger slices
+        /// color used to draw the finger contour
         /// </summary>
-        public static readonly Color FingerSliceColor = Color.Magenta;
+        public static readonly Color FingerContourColor = Color.Red;
 
         /// <summary>
         /// color used to draw the detected fingers
@@ -625,32 +601,31 @@ namespace bbiwarg
         public static readonly Color FingerDetectedColor = ColorDetected;
 
         /// <summary>
-        /// color used to draw the tracked fingers
+        /// color used to draw the finger hand point
         /// </summary>
-        public static readonly Color FingerTrackedColor = ColorTracked;
+        public static readonly Color FingerHandColor = Color.Yellow;
 
         /// <summary>
-        /// color used to draw the finger tip point
+        /// color used to draw the text for the finger id
         /// </summary>
-        public static readonly Color FingerTipColor = Color.Blue;
+        public static readonly Color FingerIDColor = Color.White;
 
         /// <summary>
-        /// color used to draw the finger hand point
+        /// color used to draw the finger slices
         /// </summary>
-        public static readonly Color FingerHandColor = Color.Yellow;
+        public static readonly Color FingerSliceColor = Color.Magenta;
 
         /// <summary>
-        /// color used to draw the finger contour
+        /// color used to draw the finger tip point
         /// </summary>
-        public static readonly Color FingerContourColor = Color.Red;
+        public static readonly Color FingerTipColor = Color.Blue;
 
         /// <summary>
-        /// color used to draw the text for the finger id
+        /// color used to draw the tracked fingers
         /// </summary>
-        public static readonly Color FingerIDColor = Color.White;
-
-        #endregion
+        public static readonly Color FingerTrackedColor = ColorTracked;
 
+        #endregion finger
 
         #region touch
 
@@ -664,20 +639,14 @@ namespace bbiwarg
         /// </summary>
         public static readonly Color TouchEventTrackedColor = ColorTracked;
 
-        #endregion
-
+        #endregion touch
 
         #region TouchEventVisualizer
 
         /// <summary>
-        /// color used to draw the lines between touch events in the touch event visualizer
-        /// </summary>
-        public static readonly Color TouchEventVisualizerLineColor = Color.Yellow;
-
-        /// <summary>
-        /// color used to draw the touch event points in the touch event visualizer
+        /// color used to highlight the active block in the touch event visualizer
         /// </summary>
-        public static readonly Color TouchEventVisualizerPointColor = Color.Red;
+        public static readonly Color TouchEventVisualizerActiveBlockColor = Color.DarkSlateGray;
 
         /// <summary>
         /// color used to draw the grid in the touch event visualizer
@@ -685,62 +654,64 @@ namespace bbiwarg
         public static readonly Color TouchEventVisualizerGridColor = Color.White;
 
         /// <summary>
-        /// color used to draw the text in the touch event visualizer
+        /// color used to draw the lines between touch events in the touch event visualizer
         /// </summary>
-        public static readonly Color TouchEventVisualizerTextColor = Color.White;
+        public static readonly Color TouchEventVisualizerLineColor = Color.Yellow;
 
         /// <summary>
-        /// color used to highlight the active block in the touch event visualizer
+        /// color used to draw the touch event points in the touch event visualizer
         /// </summary>
-        public static readonly Color TouchEventVisualizerActiveBlockColor = Color.DarkSlateGray;
+        public static readonly Color TouchEventVisualizerPointColor = Color.Red;
 
-        #endregion
+        /// <summary>
+        /// color used to draw the text in the touch event visualizer
+        /// </summary>
+        public static readonly Color TouchEventVisualizerTextColor = Color.White;
 
+        #endregion TouchEventVisualizer
 
         #region palm
 
-        /// <summary>
-        /// color used to draw the plam quadrangle
-        /// </summary>
-        public static readonly Color PalmQuadColor = Color.Blue;
-
         /// <summary>
         /// color used to draw the palm grid in the palm
         /// </summary>
         public static readonly Color PalmGridColor = Color.CornflowerBlue;
 
-        #endregion
+        /// <summary>
+        /// color used to draw the plam quadrangle
+        /// </summary>
+        public static readonly Color PalmQuadColor = Color.Blue;
 
+        #endregion palm
 
         #region hand
 
-        /// <summary>
-        /// colors used to draw the hands (ith element is a color which specifies the color channels used to draw the ith hand)
-        /// </summary>
-        public static readonly Color[] HandColors = new Color[3] { Color.Red, Color.Blue, Color.Green };
-
         /// <summary>
         /// color used to draw the hand centroid
         /// </summary>
         public static readonly Color HandCentroidColor = Color.Yellow;
 
         /// <summary>
-        /// color used to draw the hand id text
+        /// colors used to draw the hands (ith element is a color which specifies the color channels used to draw the ith hand)
         /// </summary>
-        public static readonly Color HandIDColor = Color.White;
+        public static readonly Color[] HandColors = new Color[3] { Color.Red, Color.Blue, Color.Green };
 
         /// <summary>
-        /// color used to draw the points of the thumb defects
+        /// color used to draw the hand id text
         /// </summary>
-        public static readonly Color HandThumbDefectPointColor = Color.Lime;
+        public static readonly Color HandIDColor = Color.White;
 
         /// <summary>
         /// color used to draw the lines of the thumb defects
         /// </summary>
         public static readonly Color HandThumbDefectLineColor = Color.CornflowerBlue;
 
-        #endregion
+        /// <summary>
+        /// color used to draw the points of the thumb defects
+        /// </summary>
+        public static readonly Color HandThumbDefectPointColor = Color.Lime;
 
+        #endregion hand
 
         #region calibration
 
@@ -749,8 +720,8 @@ namespace bbiwarg
         /// </summary>
         public static readonly Color CalibrationPointColor = Color.Yellow;
 
-        #endregion
+        #endregion calibration
 
-        #endregion
+        #endregion colors
     }
-}
+}

+ 6 - 7
bbiwarg/Properties/AssemblyInfo.cs

@@ -1,8 +1,7 @@
 using System.Reflection;
-using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
-// General Information about an assembly is controlled through the following 
+// General Information about an assembly is controlled through the following
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 [assembly: AssemblyTitle("bbiwarg")]
@@ -14,8 +13,8 @@ using System.Runtime.InteropServices;
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
 // COM, set the ComVisible attribute to true on that type.
 [assembly: ComVisible(false)]
 
@@ -25,12 +24,12 @@ using System.Runtime.InteropServices;
 // Version information for an assembly consists of the following four values:
 //
 //      Major Version
-//      Minor Version 
+//      Minor Version
 //      Build Number
 //      Revision
 //
-// You can specify all the values or you can default the Build and Revision Numbers 
+// You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 24 - 32
bbiwarg/Recognition/FingerRecognition/Finger.cs

@@ -1,16 +1,9 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Images;
-using bbiwarg.Utility;
-using bbiwarg.Output;
-using bbiwarg.Recognition.HandRecognition;
+using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Recognition.TouchRecognition;
 using bbiwarg.Recognition.Tracking;
+using bbiwarg.Utility;
 using Emgu.CV;
+using System.Drawing;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
@@ -20,29 +13,29 @@ namespace bbiwarg.Recognition.FingerRecognition
     public class Finger : TrackableObject
     {
         /// <summary>
-        /// the position of the finger tip
+        /// the direction of the finger (end to start)
         /// </summary>
-        public Vector2D TipPoint { get { return SliceTrail.StartSlice.Mid; } }
+        public Vector2D Direction { get { return SliceTrail.FittedDirection; } }
 
         /// <summary>
-        /// the position of the finger end (hand)
+        /// the hand the finger belongs to
         /// </summary>
-        public Vector2D HandPoint { get { return SliceTrail.EndSlice.Mid; } }
+        public Hand Hand { get; set; }
 
         /// <summary>
-        /// a position in the middle of the finger
+        /// the position of the finger end (hand)
         /// </summary>
-        public Vector2D MidPoint { get { return SliceTrail.MidSlice.Mid; } }
+        public Vector2D HandPoint { get { return SliceTrail.EndSlice.Mid; } }
 
         /// <summary>
-        /// the direction of the finger (end to start)
+        /// the line segment from start to end
         /// </summary>
-        public Vector2D Direction { get { return SliceTrail.FittedDirection; } }
+        public LineSegment2D LineSegment { get { return SliceTrail.LineSegment; } }
 
         /// <summary>
-        /// the line segment from start to end
+        /// a position in the middle of the finger
         /// </summary>
-        public LineSegment2D LineSegment { get { return SliceTrail.LineSegment; } }
+        public Vector2D MidPoint { get { return SliceTrail.MidSlice.Mid; } }
 
         /// <summary>
         /// the finger slices
@@ -50,16 +43,15 @@ namespace bbiwarg.Recognition.FingerRecognition
         public FingerSliceTrail SliceTrail { get; private set; }
 
         /// <summary>
-        /// the hand the finger belongs to
+        /// the position of the finger tip
         /// </summary>
-        public Hand Hand { get; set; }
+        public Vector2D TipPoint { get { return SliceTrail.StartSlice.Mid; } }
 
         /// <summary>
         /// the touch of the current finger
         /// </summary>
         public Touch Touch { get; set; }
 
-
         /// <summary>
         /// Initializes a new instance of the Finger class.
         /// </summary>
@@ -70,14 +62,6 @@ namespace bbiwarg.Recognition.FingerRecognition
             SliceTrail = sliceTrail;
         }
 
-        /// <summary>
-        /// Reverses the finger (start<->end)
-        /// </summary>
-        public void reverse()
-        {
-            SliceTrail.reverse();
-        }
-
         /// <summary>
         /// Gets a contour of the finger
         /// </summary>
@@ -87,5 +71,13 @@ namespace bbiwarg.Recognition.FingerRecognition
         {
             return SliceTrail.getContour(margin);
         }
+
+        /// <summary>
+        /// Reverses the finger (start<->end)
+        /// </summary>
+        public void reverse()
+        {
+            SliceTrail.reverse();
+        }
     }
-}
+}

+ 64 - 71
bbiwarg/Recognition/FingerRecognition/FingerDetector.cs

@@ -1,22 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Images;
+using bbiwarg.Images;
 using bbiwarg.Input.InputHandling;
 using bbiwarg.Utility;
-using Emgu.CV.Structure;
-using Emgu.CV;
+using System;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
     /// <summary>
     /// Detects fingers in the given depth and edge images. The finger detection searches for edges in the edge image and tries to find an initial finger slice. For each found finger slice, the finger detector tries to move along the finger direction to extend the finger slice trail. If the trail reaches its end, the finger detector removes the first few slices and starts the trail expansion in opposite direction. If the complete slice trail is long enough, the finger slices are sorted into correct order and the edges around the finger are removed to increase performance for the next finger detection.
     /// </summary>
-    class FingerDetector
+    internal class FingerDetector
     {
         /// <summary>
         /// the coordinateConverter (used to calculate finger width (in milimeters))
@@ -29,14 +22,14 @@ namespace bbiwarg.Recognition.FingerRecognition
         private DepthImage depthImage;
 
         /// <summary>
-        /// the current edge image in its original form
+        /// the current edge image in its adapted form (edges around detected fingers will be removed)
         /// </summary>
-        private EdgeImage edgeImageOriginal;
+        private EdgeImage edgeImageAdapted;
 
         /// <summary>
-        /// the current edge image in its adapted form (edges around detected fingers will be removed)
+        /// the current edge image in its original form
         /// </summary>
-        private EdgeImage edgeImageAdapted;
+        private EdgeImage edgeImageOriginal;
 
         /// <summary>
         /// the detected fingers
@@ -99,52 +92,23 @@ namespace bbiwarg.Recognition.FingerRecognition
         }
 
         /// <summary>
-        /// Gets the edge direction of the given edge point. The edge direction is either horizontal, vertical, diagonal (both) or null.
-        /// </summary>
-        /// <param name="edgePoint">the edge point</param>
-        /// <returns>the edge directon at the given point</returns>
-        private Vector2D getEdgeDirection(Vector2D edgePoint)
-        {
-            int x = edgePoint.IntX;
-            int y = edgePoint.IntY;
-
-            if (edgeImageAdapted.isEdgeAt(x, y - 1) && edgeImageAdapted.isEdgeAt(x, y + 1)) return new Vector2D(0, 1);
-            else if (edgeImageAdapted.isEdgeAt(x - 1, y) && edgeImageAdapted.isEdgeAt(x + 1, y)) return new Vector2D(1, 0);
-            else if (edgeImageAdapted.isEdgeAt(x - 1, y - 1) && edgeImageAdapted.isEdgeAt(x + 1, y + 1)) return new Vector2D(1, 1).normalize();
-            else if (edgeImageAdapted.isEdgeAt(x + 1, y - 1) && edgeImageAdapted.isEdgeAt(x - 1, y + 1)) return new Vector2D(1, -1).normalize();
-            else return null;
-        }
-
-        /// <summary>
-        /// Creates a new FingerSliceTrail and expands it along its direction.
+        /// Sorts the finger slices in correct order an checks if the finger is a valid finger (<see cref="isCrippleFinger(Finger)"/>). If it is valid the finger is added to the list of detected fingers. Afterwards the edges around the finger are removed to surpress a new finger search for the same finger.
         /// </summary>
-        /// <param name="startSlice">the initial finger slice</param>
-        /// <param name="startDirection">the initial finger direction</param>
-        /// <returns>the found FingerSliceTrail or null</returns>
-        private FingerSliceTrail findFingerSliceTrail(FingerSlice startSlice, Vector2D startDirection)
+        /// <param name="trail">the slice trail of the possible finger</param>
+        private void createFingerFromTrail(FingerSliceTrail trail)
         {
-            FingerSliceTrail trail = new FingerSliceTrail(startSlice);
+            //bring finger in correct direction Tip->Hand
+            trail = orderTrailTipToHand(trail);
 
-            Vector2D direction = startDirection;
-            Vector2D position = startSlice.Mid + direction;
+            //create finger
+            Finger finger = new Finger(trail);
 
-            if (position.isInBound(depthImage.Size))
-            {
-                FingerSlice nextSlice = findFingerSliceFromMid(position, direction);
-                if (nextSlice != null)
-                {
-                    trail.addSlice(nextSlice);
-                    trail = expandTrail(trail);
+            //add finger
+            if (!isCrippleFinger(finger))
+                fingers.Add(finger);
 
-                    if (trail.NumSlices > Parameters.FingerMinNumSlices / 2)
-                    {
-                        trail.removeFirstSlices(Parameters.FingerRemoveNumSlicesForCorrection);
-                        trail = expandTrail(trail, true);
-                        return trail;
-                    }
-                }
-            }
-            return null;
+            //remove edges around detected finger to improve performance
+            edgeImageAdapted.removeEdgesInsidePolygon(finger.getContour(Parameters.FingerContourMargin).ToArray());
         }
 
         /// <summary>
@@ -250,6 +214,38 @@ namespace bbiwarg.Recognition.FingerRecognition
             return slice;
         }
 
+        /// <summary>
+        /// Creates a new FingerSliceTrail and expands it along its direction.
+        /// </summary>
+        /// <param name="startSlice">the initial finger slice</param>
+        /// <param name="startDirection">the initial finger direction</param>
+        /// <returns>the found FingerSliceTrail or null</returns>
+        private FingerSliceTrail findFingerSliceTrail(FingerSlice startSlice, Vector2D startDirection)
+        {
+            FingerSliceTrail trail = new FingerSliceTrail(startSlice);
+
+            Vector2D direction = startDirection;
+            Vector2D position = startSlice.Mid + direction;
+
+            if (position.isInBound(depthImage.Size))
+            {
+                FingerSlice nextSlice = findFingerSliceFromMid(position, direction);
+                if (nextSlice != null)
+                {
+                    trail.addSlice(nextSlice);
+                    trail = expandTrail(trail);
+
+                    if (trail.NumSlices > Parameters.FingerMinNumSlices / 2)
+                    {
+                        trail.removeFirstSlices(Parameters.FingerRemoveNumSlicesForCorrection);
+                        trail = expandTrail(trail, true);
+                        return trail;
+                    }
+                }
+            }
+            return null;
+        }
+
         /// <summary>
         /// Checks if a possible finger slice is located on a finger. To pass this test, the depth value at the mid has to be lower than on the outside (start and end).
         /// </summary>
@@ -264,23 +260,20 @@ namespace bbiwarg.Recognition.FingerRecognition
         }
 
         /// <summary>
-        /// Sorts the finger slices in correct order an checks if the finger is a valid finger (<see cref="isCrippleFinger(Finger)"/>). If it is valid the finger is added to the list of detected fingers. Afterwards the edges around the finger are removed to surpress a new finger search for the same finger.
+        /// Gets the edge direction of the given edge point. The edge direction is either horizontal, vertical, diagonal (both) or null.
         /// </summary>
-        /// <param name="trail">the slice trail of the possible finger</param>
-        private void createFingerFromTrail(FingerSliceTrail trail)
+        /// <param name="edgePoint">the edge point</param>
+        /// <returns>the edge directon at the given point</returns>
+        private Vector2D getEdgeDirection(Vector2D edgePoint)
         {
-            //bring finger in correct direction Tip->Hand
-            trail = orderTrailTipToHand(trail);
-
-            //create finger
-            Finger finger = new Finger(trail);
-
-            //add finger
-            if (!isCrippleFinger(finger))
-                fingers.Add(finger);
+            int x = edgePoint.IntX;
+            int y = edgePoint.IntY;
 
-            //remove edges around detected finger to improve performance
-            edgeImageAdapted.removeEdgesInsidePolygon(finger.getContour(Parameters.FingerContourMargin).ToArray());
+            if (edgeImageAdapted.isEdgeAt(x, y - 1) && edgeImageAdapted.isEdgeAt(x, y + 1)) return new Vector2D(0, 1);
+            else if (edgeImageAdapted.isEdgeAt(x - 1, y) && edgeImageAdapted.isEdgeAt(x + 1, y)) return new Vector2D(1, 0);
+            else if (edgeImageAdapted.isEdgeAt(x - 1, y - 1) && edgeImageAdapted.isEdgeAt(x + 1, y + 1)) return new Vector2D(1, 1).normalize();
+            else if (edgeImageAdapted.isEdgeAt(x + 1, y - 1) && edgeImageAdapted.isEdgeAt(x - 1, y + 1)) return new Vector2D(1, -1).normalize();
+            else return null;
         }
 
         /// <summary>
@@ -318,4 +311,4 @@ namespace bbiwarg.Recognition.FingerRecognition
             return trail;
         }
     }
-}
+}

+ 12 - 19
bbiwarg/Recognition/FingerRecognition/FingerSlice.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Utility;
+using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
@@ -13,19 +8,19 @@ namespace bbiwarg.Recognition.FingerRecognition
     public class FingerSlice
     {
         /// <summary>
-        /// the point in the middle of the slice
+        /// the direction of the slice
         /// </summary>
-        public Vector2D Mid { get; private set; }
+        public Vector2D Direction { get { return LineSegment.Direction; } }
 
         /// <summary>
-        /// the start point of the slice
+        /// the end point of the slice
         /// </summary>
-        public Vector2D Start { get; private set; }
+        public Vector2D End { get; private set; }
 
         /// <summary>
-        /// the end point of the slice
+        /// the length of the slice (in pixels)
         /// </summary>
-        public Vector2D End { get; private set; }
+        public float Length { get { return LineSegment.Length; } }
 
         /// <summary>
         /// the line segment connecting start and end
@@ -33,15 +28,14 @@ namespace bbiwarg.Recognition.FingerRecognition
         public LineSegment2D LineSegment { get; private set; }
 
         /// <summary>
-        /// the direction of the slice
+        /// the point in the middle of the slice
         /// </summary>
-        public Vector2D Direction { get { return LineSegment.Direction; } }
+        public Vector2D Mid { get; private set; }
 
         /// <summary>
-        /// the length of the slice (in pixels)
+        /// the start point of the slice
         /// </summary>
-        public float Length { get { return LineSegment.Length; } }
-
+        public Vector2D Start { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the FingerSlice class.
@@ -55,6 +49,5 @@ namespace bbiwarg.Recognition.FingerRecognition
             Mid = (start + end) / 2;
             LineSegment = new LineSegment2D(Start, End);
         }
-
     }
-}
+}

+ 67 - 72
bbiwarg/Recognition/FingerRecognition/FingerSliceTrail.cs

@@ -1,11 +1,8 @@
-using System;
+using bbiwarg.Utility;
+using Emgu.CV;
+using System;
 using System.Collections.Generic;
 using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Utility;
-using Emgu.CV;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
@@ -14,52 +11,45 @@ namespace bbiwarg.Recognition.FingerRecognition
     /// </summary>
     public class FingerSliceTrail
     {
-        /// <summary>
-        /// the line segment connection the first slice's mid to the last slice's mid
-        /// </summary>
-        private LineSegment2D lineSegment;
-
         /// <summary>
         /// the fitted direction through all slice's mid points [end to start]
         /// </summary>
         private Vector2D fittedDirection;
 
         /// <summary>
-        /// indicates wether the variable lineSegment is up to date (outdates if new start or end slices are added)
+        /// indicates weter the variable fittedDirection is up to date (outdates if new slices are added)
         /// </summary>
-        private bool lineSegmentUpToDate;
+        private bool fittedDirectionUpToDate;
 
         /// <summary>
-        /// indicates weter the variable fittedDirection is up to date (outdates if new slices are added)
+        /// the line segment connection the first slice's mid to the last slice's mid
         /// </summary>
-        private bool fittedDirectionUpToDate;
+        private LineSegment2D lineSegment;
 
         /// <summary>
-        /// the finger slices
+        /// indicates wether the variable lineSegment is up to date (outdates if new start or end slices are added)
         /// </summary>
-        public List<FingerSlice> Slices { get; private set; }
+        private bool lineSegmentUpToDate;
 
         /// <summary>
-        /// the first slice
+        /// the last slice
         /// </summary>
-        public FingerSlice StartSlice { get { return Slices[0]; } }
+        public FingerSlice EndSlice { get { return Slices[Slices.Count - 1]; } }
 
         /// <summary>
-        /// the middle slice
+        /// the fitted direction through all slice's mid points [end to start]
         /// </summary>
-        public FingerSlice MidSlice { get { return Slices[NumSlices / 2]; } }
+        public Vector2D FittedDirection { get { if (!fittedDirectionUpToDate) updateFittedDirection(); return fittedDirection; } }
 
         /// <summary>
-        /// the last slice
+        /// the line segment connecting the start slice's mid to the end slice's mid
         /// </summary>
-        public FingerSlice EndSlice { get { return Slices[Slices.Count - 1]; } }
+        public LineSegment2D LineSegment { get { if (!lineSegmentUpToDate) updateLineSegment(); return lineSegment; } }
 
         /// <summary>
-        /// The slice at the given index.
+        /// the middle slice
         /// </summary>
-        /// <param name="index">the index</param>
-        /// <returns>the slice at the given index</returns>
-        public FingerSlice this[int index] { get { return Slices[index]; } }
+        public FingerSlice MidSlice { get { return Slices[NumSlices / 2]; } }
 
         /// <summary>
         /// the number of slices
@@ -67,15 +57,14 @@ namespace bbiwarg.Recognition.FingerRecognition
         public int NumSlices { get { return Slices.Count; } }
 
         /// <summary>
-        /// the line segment connecting the start slice's mid to the end slice's mid
+        /// the finger slices
         /// </summary>
-        public LineSegment2D LineSegment { get { if (!lineSegmentUpToDate) updateLineSegment(); return lineSegment; } }
+        public List<FingerSlice> Slices { get; private set; }
 
         /// <summary>
-        /// the fitted direction through all slice's mid points [end to start]
+        /// the first slice
         /// </summary>
-        public Vector2D FittedDirection { get { if (!fittedDirectionUpToDate) updateFittedDirection(); return fittedDirection; } }
-
+        public FingerSlice StartSlice { get { return Slices[0]; } }
 
         /// <summary>
         /// Initializes a new instance of the FingerSliceTrail class.
@@ -89,6 +78,13 @@ namespace bbiwarg.Recognition.FingerRecognition
             fittedDirectionUpToDate = false;
         }
 
+        /// <summary>
+        /// The slice at the given index.
+        /// </summary>
+        /// <param name="index">the index</param>
+        /// <returns>the slice at the given index</returns>
+        public FingerSlice this[int index] { get { return Slices[index]; } }
+
         /// <summary>
         /// Adds a slice to the end of the slice trail and outdates the lineSegment and fittedDirection.
         /// </summary>
@@ -101,13 +97,28 @@ namespace bbiwarg.Recognition.FingerRecognition
         }
 
         /// <summary>
-        /// Calculates the direction of the first few slices
+        /// Gets the contour of the finger with a given margin
         /// </summary>
-        /// <returns>the start direction (pointing direction)</returns>
-        public Vector2D getStartDirection()
+        /// <param name="margin">the margin around the finger (in pixels)</param>
+        /// <returns>the contour of the finger</returns>
+        public Contour<Point> getContour(float margin)
         {
-            int innerStartIndex = Math.Min(NumSlices - 1, Parameters.FingerNumSlicesForRelativeDirection);
-            return (StartSlice.Mid - Slices[innerStartIndex].Mid).normalize();
+            List<Point> pointsA = new List<Point>();
+            List<Point> pointsB = new List<Point>();
+
+            foreach (FingerSlice slice in Slices)
+            {
+                Vector2D direction = slice.Direction;
+                pointsA.Add(slice.Start + margin * direction.getInverse());
+                pointsB.Add(slice.End + margin * direction);
+            }
+
+            pointsA.Reverse();
+            pointsA.AddRange(pointsB);
+
+            Contour<Point> contour = new Contour<Point>(new MemStorage());
+            contour.PushMulti(pointsA.ToArray(), Emgu.CV.CvEnum.BACK_OR_FRONT.FRONT);
+            return contour;
         }
 
         /// <summary>
@@ -120,6 +131,16 @@ namespace bbiwarg.Recognition.FingerRecognition
             return (EndSlice.Mid - Slices[innerEndIndex].Mid).normalize();
         }
 
+        /// <summary>
+        /// Calculates the direction of the first few slices
+        /// </summary>
+        /// <returns>the start direction (pointing direction)</returns>
+        public Vector2D getStartDirection()
+        {
+            int innerStartIndex = Math.Min(NumSlices - 1, Parameters.FingerNumSlicesForRelativeDirection);
+            return (StartSlice.Mid - Slices[innerStartIndex].Mid).normalize();
+        }
+
         /// <summary>
         /// Removes the first few slices.
         /// </summary>
@@ -145,40 +166,6 @@ namespace bbiwarg.Recognition.FingerRecognition
                 fittedDirection = fittedDirection.getInverse();
         }
 
-        /// <summary>
-        /// Gets the contour of the finger with a given margin
-        /// </summary>
-        /// <param name="margin">the margin around the finger (in pixels)</param>
-        /// <returns>the contour of the finger</returns>
-        public Contour<Point> getContour(float margin)
-        {
-            List<Point> pointsA = new List<Point>();
-            List<Point> pointsB = new List<Point>();
-
-            foreach (FingerSlice slice in Slices)
-            {
-                Vector2D direction = slice.Direction;
-                pointsA.Add(slice.Start + margin * direction.getInverse());
-                pointsB.Add(slice.End + margin * direction);
-            }
-
-            pointsA.Reverse();
-            pointsA.AddRange(pointsB);
-
-            Contour<Point> contour = new Contour<Point>(new MemStorage());
-            contour.PushMulti(pointsA.ToArray(), Emgu.CV.CvEnum.BACK_OR_FRONT.FRONT);
-            return contour;
-        }
-
-        /// <summary>
-        /// updtes the line segment (new line segment from end to start)
-        /// </summary>
-        private void updateLineSegment()
-        {
-            lineSegment = new LineSegment2D(EndSlice.Mid, StartSlice.Mid);
-            lineSegmentUpToDate = true;
-        }
-
         /// <summary>
         /// updates the fitted direction (line fitting through all slices mid points)
         /// </summary>
@@ -198,5 +185,13 @@ namespace bbiwarg.Recognition.FingerRecognition
             fittedDirectionUpToDate = true;
         }
 
+        /// <summary>
+        /// updtes the line segment (new line segment from end to start)
+        /// </summary>
+        private void updateLineSegment()
+        {
+            lineSegment = new LineSegment2D(EndSlice.Mid, StartSlice.Mid);
+            lineSegmentUpToDate = true;
+        }
     }
-}
+}

+ 14 - 19
bbiwarg/Recognition/FingerRecognition/FingerTracker.cs

@@ -1,18 +1,13 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
-using bbiwarg.Input.InputHandling;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
     /// <summary>
     /// Keeps track of fingers over a period of time.
     /// </summary>
-    class FingerTracker : Tracker<Finger, TrackedFinger>
+    internal class FingerTracker : Tracker<Finger, TrackedFinger>
     {
         /// <summary>
         /// Initializes a new instance of the FingerTracker class.
@@ -24,17 +19,7 @@ namespace bbiwarg.Recognition.FingerRecognition
         }
 
         /// <summary>
-        /// Updates the TrackedFingers with the detected fingers in the current frame and stores the tracked fingers.
-        /// </summary>
-        /// <param name="frameData">the current frame</param>
-        public void trackFingers(FrameData frameData)
-        {
-            trackObjects(frameData.DetectedFingers);
-            frameData.TrackedFingers = getCurrentObjectsWithState(TrackingState.Tracked);
-        }
-
-        /// <summary>
-        /// Calculates the similarity [0-1] of a tracked Finger and a detected finger 
+        /// Calculates the similarity [0-1] of a tracked Finger and a detected finger
         /// </summary>
         /// <param name="trackedFinger">the tracked finger</param>
         /// <param name="detectedFinger">the detected finger</param>
@@ -59,6 +44,16 @@ namespace bbiwarg.Recognition.FingerRecognition
             return tipPointSimilarity * handPointSimilarity;
         }
 
+        /// <summary>
+        /// Updates the TrackedFingers with the detected fingers in the current frame and stores the tracked fingers.
+        /// </summary>
+        /// <param name="frameData">the current frame</param>
+        public void trackFingers(FrameData frameData)
+        {
+            trackObjects(frameData.DetectedFingers);
+            frameData.TrackedFingers = getCurrentObjectsWithState(TrackingState.Tracked);
+        }
+
         /// <summary>
         /// Creates a TrackedFinger.
         /// </summary>
@@ -69,4 +64,4 @@ namespace bbiwarg.Recognition.FingerRecognition
             return new TrackedFinger(idPool.getNextUnusedID(), detectedObject, Parameters.FingerTrackerNumFramesDetectedUntilTracked, Parameters.FingerTrackerNumFramesLostUntilDeleted);
         }
     }
-}
+}

+ 22 - 26
bbiwarg/Recognition/FingerRecognition/TrackedFinger.cs

@@ -1,23 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.Tracking;
+using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
+using System;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
     /// <summary>
     /// Represents a finger that is tracked for several frames.
     /// </summary>
-    class TrackedFinger : TrackedObject<Finger>
+    internal class TrackedFinger : TrackedObject<Finger>
     {
-        /// <summary>
-        /// the kalman filter for the tip point prediction
-        /// </summary>
-        private Kalman2DPositionFilter tipPointKalman;
-
         /// <summary>
         /// the kalman filter for the hand point prediction
         /// </summary>
@@ -29,9 +21,9 @@ namespace bbiwarg.Recognition.FingerRecognition
         private List<Vector2D> lastRawDirections;
 
         /// <summary>
-        /// predicted position of the tip point
+        /// the kalman filter for the tip point prediction
         /// </summary>
-        public Vector2D TipPointPrediction { get { return tipPointKalman.getPrediction(); } }
+        private Kalman2DPositionFilter tipPointKalman;
 
         /// <summary>
         /// predicted position of the hand point
@@ -43,6 +35,10 @@ namespace bbiwarg.Recognition.FingerRecognition
         /// </summary>
         public Vector2D MeanDirection { get { return Vector2D.mean(lastRawDirections); } }
 
+        /// <summary>
+        /// predicted position of the tip point
+        /// </summary>
+        public Vector2D TipPointPrediction { get { return tipPointKalman.getPrediction(); } }
 
         /// <summary>
         /// Initializes a new instance of the TrackedFinger class.
@@ -63,6 +59,17 @@ namespace bbiwarg.Recognition.FingerRecognition
             logStateChange();
         }
 
+        /// <summary>
+        /// Indicates wether a newly detected finger should be reverse (direction differs from average direction of previous fingers).
+        /// </summary>
+        /// <param name="detectedFinger">the detected finger</param>
+        /// <returns>wether the fingers direction matches to the direction of the previous fingers</returns>
+        public bool shouldFingerBeReversed(Finger detectedFinger)
+        {
+            Vector2D meanDirection = Vector2D.mean(lastRawDirections);
+            return meanDirection.isInOppositeDirection(detectedFinger.Direction);
+        }
+
         /// <summary>
         /// Updates the tracked finger with the given finger, logs the state change, corrects the finger's direction if needed and updates the position predictions (kalman filters).
         /// </summary>
@@ -88,17 +95,6 @@ namespace bbiwarg.Recognition.FingerRecognition
             }
         }
 
-        /// <summary>
-        /// Indicates wether a newly detected finger should be reverse (direction differs from average direction of previous fingers).
-        /// </summary>
-        /// <param name="detectedFinger">the detected finger</param>
-        /// <returns>wether the fingers direction matches to the direction of the previous fingers</returns>
-        public bool shouldFingerBeReversed(Finger detectedFinger)
-        {
-            Vector2D meanDirection = Vector2D.mean(lastRawDirections);
-            return meanDirection.isInOppositeDirection(detectedFinger.Direction);
-        }
-
         /// <summary>
         /// logs the state change
         /// </summary>
@@ -108,4 +104,4 @@ namespace bbiwarg.Recognition.FingerRecognition
             Logger.log(String.Format("Finger #{0} {1}", this.ID, stateAsString), LogSubject.FingerTracker);
         }
     }
-}
+}

+ 32 - 37
bbiwarg/Recognition/HandRecognition/Hand.cs

@@ -1,15 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using bbiwarg.Recognition.FingerRecognition;
+using bbiwarg.Recognition.PalmRecognition;
+using bbiwarg.Recognition.Tracking;
+using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
-using bbiwarg.Recognition.FingerRecognition;
-using bbiwarg.Utility;
-using bbiwarg.Recognition.Tracking;
-using bbiwarg.Recognition.PalmRecognition;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
@@ -24,14 +19,14 @@ namespace bbiwarg.Recognition.HandRecognition
         public Vector2D Centroid { get; private set; }
 
         /// <summary>
-        /// a mask of the hand (0=outside, 1=in hand)
+        /// the fingers belonging to the hand
         /// </summary>
-        public Image<Gray, byte> Mask { get; private set; }
+        public List<Finger> Fingers { get; private set; }
 
         /// <summary>
-        /// the fingers belonging to the hand
+        /// a mask of the hand (0=outside, 1=in hand)
         /// </summary>
-        public List<Finger> Fingers { get; private set; }
+        public Image<Gray, byte> Mask { get; private set; }
 
         /// <summary>
         /// the palm belonging to the hand
@@ -52,28 +47,6 @@ namespace bbiwarg.Recognition.HandRecognition
                 finger.Hand = this;
         }
 
-        /// <summary>
-        /// Checks wether a given point is inside the hand.
-        /// </summary>
-        /// <param name="point">the point</param>
-        /// <returns>wether the point is inside the hand</returns>
-        public bool isInside(Vector2D point)
-        {
-            return (Mask.Data[point.IntY, point.IntX, 0] != 0);
-        }
-
-        /// <summary>
-        /// Merges another Hand to this hand by extending the mask and adding the fingers.
-        /// </summary>
-        /// <param name="mergeHand">the other hand</param>
-        public void mergeWith(Hand mergeHand)
-        {
-            extendMask(mergeHand.Mask);
-            Fingers.AddRange(mergeHand.Fingers);
-            foreach (Finger finger in mergeHand.Fingers)
-                finger.Hand = this;
-        }
-
         /// <summary>
         /// Extends the mask.
         /// </summary>
@@ -123,5 +96,27 @@ namespace bbiwarg.Recognition.HandRecognition
             MCvPoint2D64f gravityCenter = Mask.GetMoments(true).GravityCenter;
             Centroid = new Vector2D((float)gravityCenter.x, (float)gravityCenter.y);
         }
+
+        /// <summary>
+        /// Checks wether a given point is inside the hand.
+        /// </summary>
+        /// <param name="point">the point</param>
+        /// <returns>wether the point is inside the hand</returns>
+        public bool isInside(Vector2D point)
+        {
+            return (Mask.Data[point.IntY, point.IntX, 0] != 0);
+        }
+
+        /// <summary>
+        /// Merges another Hand to this hand by extending the mask and adding the fingers.
+        /// </summary>
+        /// <param name="mergeHand">the other hand</param>
+        public void mergeWith(Hand mergeHand)
+        {
+            extendMask(mergeHand.Mask);
+            Fingers.AddRange(mergeHand.Fingers);
+            foreach (Finger finger in mergeHand.Fingers)
+                finger.Hand = this;
+        }
     }
-}
+}

+ 96 - 102
bbiwarg/Recognition/HandRecognition/HandDetector.cs

@@ -1,25 +1,19 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Images;
+using bbiwarg.Images;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.FingerRecognition;
-using bbiwarg.Output;
 using bbiwarg.Utility;
-using bbiwarg.Input.InputHandling;
 using Emgu.CV;
 using Emgu.CV.Structure;
-
-
+using System;
+using System.Collections.Generic;
+using System.Drawing;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
     /// <summary>
     /// Finds Hands by iterating over all fingers and flooding them. Each filled region is considered to be one hand and each finger belongs to one hand. To improve the hand contours, the hand mask are filled with the defects caused by overlapping fingers.
     /// </summary>
-    class HandDetector
+    internal class HandDetector
     {
         /// <summary>
         /// the depth image of the current frame
@@ -27,24 +21,24 @@ namespace bbiwarg.Recognition.HandRecognition
         private DepthImage depthImage;
 
         /// <summary>
-        /// the modified depth image of the current frame (hand flooding changes depth image)
+        /// the fingers in the current frame
         /// </summary>
-        private Image<Gray, byte> modifiedHandDepthImage;
+        private List<Finger> fingers;
 
         /// <summary>
-        /// the fingers in the current frame
+        /// the hands in the current frame
         /// </summary>
-        private List<Finger> fingers;
+        private List<Hand> hands;
 
         /// <summary>
-        /// a mapping of hands and list of fingers, that don't belong to that specific hand
+        /// the modified depth image of the current frame (hand flooding changes depth image)
         /// </summary>
-        private Dictionary<Hand, List<Finger>> otherHandsFingers;
+        private Image<Gray, byte> modifiedHandDepthImage;
 
         /// <summary>
-        /// the hands in the current frame
+        /// a mapping of hands and list of fingers, that don't belong to that specific hand
         /// </summary>
-        private List<Hand> hands;
+        private Dictionary<Hand, List<Finger>> otherHandsFingers;
 
         /// <summary>
         /// Detects Hands in the current frame and stores found hands in frameData.detectedHands
@@ -78,72 +72,6 @@ namespace bbiwarg.Recognition.HandRecognition
             }
         }
 
-        /// <summary>
-        /// Finds hands by flood filling from each finger (mask). All unassigned fingers that lie within the hand are assigned to the hand, all other fingers are mapped as fingers that don't belong to that specific hand.
-        /// </summary>
-        private void findHands()
-        {
-            hands = new List<Hand>();
-            otherHandsFingers = new Dictionary<Hand, List<Finger>>();
-            List<Finger> assignedFingers = new List<Finger>();
-
-            foreach (Finger finger in fingers)
-            {
-                if (!assignedFingers.Contains(finger))
-                {
-                    Image<Gray, byte> handMask = getHandMask(finger.HandPoint);
-
-                    int numPixels = handMask.CountNonzero()[0];
-                    if (numPixels > Parameters.HandMaxSize * depthImage.Size.NumPixels)
-                    {
-                        assignedFingers.Add(finger);
-                        break;
-                    }
-
-                    List<Finger> fingersOnHand = new List<Finger>();
-                    List<Finger> fingersOnOtherHand = new List<Finger>();
-
-                    foreach (Finger f in fingers)
-                    {
-                        if (!assignedFingers.Contains(f) && handMask.Data[f.HandPoint.IntY, f.HandPoint.IntX, 0] != 0)
-                        {
-                            fingersOnHand.Add(f);
-                            assignedFingers.Add(f);
-                        }
-                        else
-                            fingersOnOtherHand.Add(f);
-                    }
-
-                    Hand hand = new Hand(handMask, fingersOnHand);
-                    otherHandsFingers.Add(hand, fingersOnOtherHand);
-                    hands.Add(hand);
-                }
-            }
-        }
-
-        /// <summary>
-        /// Flood fills from a given point and returns the filled area as mask.
-        /// </summary>
-        /// <param name="p">flood fill starting point</param>
-        /// <returns>the filled area as mask</returns>
-        private Image<Gray, byte> getHandMask(Vector2D p)
-        {
-            Image<Gray, byte> mask = new Image<Gray, byte>(depthImage.Size.Width + 2, depthImage.Size.Height + 2);
-            MCvConnectedComp comp = new MCvConnectedComp();
-            CvInvoke.cvFloodFill(modifiedHandDepthImage, p, new MCvScalar(255), new MCvScalar(Parameters.HandFloodFillDownDiff),
-                new MCvScalar(Parameters.HandFloodFillUpDiff), out comp, Emgu.CV.CvEnum.CONNECTIVITY.FOUR_CONNECTED, Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask);
-            return mask.Copy(new Rectangle(1, 1, depthImage.Size.Width, depthImage.Size.Height));
-        }
-
-        /// <summary>
-        /// Fixes overlapping fingers by merging two hands if they are seperated by a finger and/or fills holes caused by overlapping fingers.
-        /// </summary>
-        private void fixOverlappingFingers()
-        {
-            extendOrMergeThroughOverlappingFingers();
-            fillOverlappingFingers();
-        }
-
         /// <summary>
         /// Merges two hands if they are seperatd by an overlapping finger or extends the hand mask through an overlapping finger.
         /// </summary>
@@ -209,21 +137,6 @@ namespace bbiwarg.Recognition.HandRecognition
                 hands.Remove(mergedHand);
         }
 
-        /// <summary>
-        /// Merges two hands together and updates the list of other hands fingers.
-        /// </summary>
-        /// <param name="hand">the first hand (other hand will be merged to this one)</param>
-        /// <param name="mergeHand">the second hand (this hand will be dropped afterwards)</param>
-        private void mergeToHand(Hand hand, Hand mergeHand)
-        {
-            hand.mergeWith(mergeHand);
-
-            foreach (Finger finger in mergeHand.Fingers)
-                otherHandsFingers[hand].Remove(finger);
-
-            otherHandsFingers.Remove(mergeHand);
-        }
-
         /// <summary>
         /// Extends the hand mask of a given hand by flood filling starting from the given point.
         /// </summary>
@@ -257,5 +170,86 @@ namespace bbiwarg.Recognition.HandRecognition
             foreach (Hand hand in hands)
                 hand.findCentroid();
         }
+
+        /// <summary>
+        /// Finds hands by flood filling from each finger (mask). All unassigned fingers that lie within the hand are assigned to the hand, all other fingers are mapped as fingers that don't belong to that specific hand.
+        /// </summary>
+        private void findHands()
+        {
+            hands = new List<Hand>();
+            otherHandsFingers = new Dictionary<Hand, List<Finger>>();
+            List<Finger> assignedFingers = new List<Finger>();
+
+            foreach (Finger finger in fingers)
+            {
+                if (!assignedFingers.Contains(finger))
+                {
+                    Image<Gray, byte> handMask = getHandMask(finger.HandPoint);
+
+                    int numPixels = handMask.CountNonzero()[0];
+                    if (numPixels > Parameters.HandMaxSize * depthImage.Size.NumPixels)
+                    {
+                        assignedFingers.Add(finger);
+                        break;
+                    }
+
+                    List<Finger> fingersOnHand = new List<Finger>();
+                    List<Finger> fingersOnOtherHand = new List<Finger>();
+
+                    foreach (Finger f in fingers)
+                    {
+                        if (!assignedFingers.Contains(f) && handMask.Data[f.HandPoint.IntY, f.HandPoint.IntX, 0] != 0)
+                        {
+                            fingersOnHand.Add(f);
+                            assignedFingers.Add(f);
+                        }
+                        else
+                            fingersOnOtherHand.Add(f);
+                    }
+
+                    Hand hand = new Hand(handMask, fingersOnHand);
+                    otherHandsFingers.Add(hand, fingersOnOtherHand);
+                    hands.Add(hand);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Fixes overlapping fingers by merging two hands if they are seperated by a finger and/or fills holes caused by overlapping fingers.
+        /// </summary>
+        private void fixOverlappingFingers()
+        {
+            extendOrMergeThroughOverlappingFingers();
+            fillOverlappingFingers();
+        }
+
+        /// <summary>
+        /// Flood fills from a given point and returns the filled area as mask.
+        /// </summary>
+        /// <param name="p">flood fill starting point</param>
+        /// <returns>the filled area as mask</returns>
+        private Image<Gray, byte> getHandMask(Vector2D p)
+        {
+            Image<Gray, byte> mask = new Image<Gray, byte>(depthImage.Size.Width + 2, depthImage.Size.Height + 2);
+            MCvConnectedComp comp = new MCvConnectedComp();
+            CvInvoke.cvFloodFill(modifiedHandDepthImage, p, new MCvScalar(255), new MCvScalar(Parameters.HandFloodFillDownDiff),
+                new MCvScalar(Parameters.HandFloodFillUpDiff), out comp, Emgu.CV.CvEnum.CONNECTIVITY.FOUR_CONNECTED, Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask);
+            return mask.Copy(new Rectangle(1, 1, depthImage.Size.Width, depthImage.Size.Height));
+        }
+
+        /// <summary>
+        /// Merges two hands together and updates the list of other hands fingers.
+        /// </summary>
+        /// <param name="hand">the first hand (other hand will be merged to this one)</param>
+        /// <param name="mergeHand">the second hand (this hand will be dropped afterwards)</param>
+        private void mergeToHand(Hand hand, Hand mergeHand)
+        {
+            hand.mergeWith(mergeHand);
+
+            foreach (Finger finger in mergeHand.Fingers)
+                otherHandsFingers[hand].Remove(finger);
+
+            otherHandsFingers.Remove(mergeHand);
+        }
     }
-}
+}

+ 13 - 18
bbiwarg/Recognition/HandRecognition/HandTracker.cs

@@ -1,10 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.Tracking;
-using bbiwarg.Input.InputHandling;
 using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.HandRecognition
@@ -12,7 +7,7 @@ namespace bbiwarg.Recognition.HandRecognition
     /// <summary>
     /// Keeps track of hands over a period of time.
     /// </summary>
-    class HandTracker : Tracker<Hand, TrackedHand>
+    internal class HandTracker : Tracker<Hand, TrackedHand>
     {
         /// <summary>
         /// Initializes a new instance of the HandTracker class.
@@ -23,16 +18,6 @@ namespace bbiwarg.Recognition.HandRecognition
         {
         }
 
-        /// <summary>
-        /// Updates the TrackedHands with the detected hands in the current frame and stores the results in frameData.trackedFingers.
-        /// </summary>
-        /// <param name="frameData">the current frame</param>
-        public void trackHands(FrameData frameData)
-        {
-            trackObjects(frameData.DetectedHands);
-            frameData.TrackedHands = getCurrentObjectsWithState(TrackingState.Tracked);
-        }
-
         /// <summary>
         /// Calculates the similarity [0-1] of a tracked Hand and a detected Hand.
         /// </summary>
@@ -44,6 +29,16 @@ namespace bbiwarg.Recognition.HandRecognition
             return getPositionSimilarity(trackedHand.CentroidPrediction, detectedHand.Centroid, Parameters.HandTrackerMaxCentroidRelativeMove);
         }
 
+        /// <summary>
+        /// Updates the TrackedHands with the detected hands in the current frame and stores the results in frameData.trackedFingers.
+        /// </summary>
+        /// <param name="frameData">the current frame</param>
+        public void trackHands(FrameData frameData)
+        {
+            trackObjects(frameData.DetectedHands);
+            frameData.TrackedHands = getCurrentObjectsWithState(TrackingState.Tracked);
+        }
+
         /// <summary>
         /// Creates a TrackedHand.
         /// </summary>
@@ -54,4 +49,4 @@ namespace bbiwarg.Recognition.HandRecognition
             return new TrackedHand(idPool.getNextUnusedID(), detectedObject, Parameters.HandTrackerNumFramesDetectedUntilTracked, Parameters.HandTrackerNumFramesLostUntilDeleted);
         }
     }
-}
+}

+ 4 - 8
bbiwarg/Recognition/HandRecognition/TrackedHand.cs

@@ -1,17 +1,13 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.Tracking;
+using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
+using System;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
     /// <summary>
     /// Represents a hand that is tracked for several frames
     /// </summary>
-    class TrackedHand : TrackedObject<Hand>
+    internal class TrackedHand : TrackedObject<Hand>
     {
         /// <summary>
         /// the kalman filter for the centroid prediction
@@ -63,4 +59,4 @@ namespace bbiwarg.Recognition.HandRecognition
             Logger.log(String.Format("Hand #{0} {1}", this.ID, stateAsString), LogSubject.HandTracker);
         }
     }
-}
+}

+ 18 - 22
bbiwarg/Recognition/PalmRecognition/Palm.cs

@@ -1,11 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Utility;
-using bbiwarg.Recognition.HandRecognition;
+using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Recognition.Tracking;
+using bbiwarg.Utility;
+using System;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
@@ -25,34 +21,34 @@ namespace bbiwarg.Recognition.PalmRecognition
     public class Palm : TrackableObject
     {
         /// <summary>
-        /// the hand belonging to this palm
+        /// the position of the fingers lower (bottom right for left hand, bottom left for right hand)
         /// </summary>
-        public Hand Hand { get; private set; }
+        public Vector2D FingersLower { get; private set; }
 
         /// <summary>
-        /// the thumb's convexity defect
+        /// the position of the upper fingers (top right for left hand, top left for left hannd)
         /// </summary>
-        public ConvexityDefect ThumbDefect { get; private set; }
+        public Vector2D FingersUpper { get; private set; }
 
         /// <summary>
-        /// the handedness
+        /// the hand belonging to this palm
         /// </summary>
-        public HandSide HandSide { get; private set; }
+        public Hand Hand { get; private set; }
 
         /// <summary>
-        /// the position of the upper wrist (top left corner for left hand, top right for right hand)
+        /// the handedness
         /// </summary>
-        public Vector2D WristUpper { get; private set; }
+        public HandSide HandSide { get; private set; }
 
         /// <summary>
-        /// the position of the upper fingers (top right for left hand, top left for left hannd)
+        /// the quadrangle of the four palm points
         /// </summary>
-        public Vector2D FingersUpper { get; private set; }
+        public Quadrangle Quad { get; private set; }
 
         /// <summary>
-        /// the position of the fingers lower (bottom right for left hand, bottom left for right hand)
+        /// the thumb's convexity defect
         /// </summary>
-        public Vector2D FingersLower { get; private set; }
+        public ConvexityDefect ThumbDefect { get; private set; }
 
         /// <summary>
         /// the position of the wrist lower (bottom left for left hand, bottom right for right hand)
@@ -60,9 +56,9 @@ namespace bbiwarg.Recognition.PalmRecognition
         public Vector2D WristLower { get; private set; }
 
         /// <summary>
-        /// the quadrangle of the four palm points
+        /// the position of the upper wrist (top left corner for left hand, top right for right hand)
         /// </summary>
-        public Quadrangle Quad { get; private set; }
+        public Vector2D WristUpper { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the Palm class.
@@ -124,4 +120,4 @@ namespace bbiwarg.Recognition.PalmRecognition
                 Quad = new Quadrangle(FingersUpper, WristUpper, WristLower, FingersLower);
         }
     }
-}
+}

+ 77 - 80
bbiwarg/Recognition/PalmRecognition/PalmDetector.cs

@@ -1,23 +1,20 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Images;
-using bbiwarg.Utility;
+using bbiwarg.Images;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.HandRecognition;
-using bbiwarg.Input.InputHandling;
+using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
     /// <summary>
     /// Detects palms by iterating over each hand, if the hand has exactly one finger (possible thumb) it calculates its convexity defects and checks if there is a convexity defect that matches the requirements for a thumb defect. If a thumb defect is found, the four palm points are generated and a new palm is created.
     /// </summary>
-    class PalmDetector
+    internal class PalmDetector
     {
         /// <summary>
         /// the depth image of the current frame
@@ -48,64 +45,6 @@ namespace bbiwarg.Recognition.PalmRecognition
             frameData.DetectedPalms = palms;
         }
 
-        /// <summary>
-        /// Find Palms by checking each hand with only one finger, if that finger is a thumb.
-        /// </summary>
-        private void findPalms()
-        {
-            palms = new List<Palm>();
-            foreach (Hand hand in hands)
-            {
-                if (hand.Fingers.Count == 1)
-                {
-                    List<ConvexityDefect> convexityDefects = findConvexityDefects(hand);
-                    ConvexityDefect thumbDefect = findThumbDefect(hand.Fingers[0], convexityDefects);
-                    if (thumbDefect != null)
-                    {
-                        Palm palm = createPalm(hand, thumbDefect);
-                        palms.Add(palm);
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the convexity Defects from a hand mask.
-        /// </summary>
-        /// <param name="hand">the hand</param>
-        /// <returns>the conveixty defects</returns>
-        private List<ConvexityDefect> findConvexityDefects(Hand hand)
-        {
-            List<ConvexityDefect> convexityDefects;
-            using (MemStorage ms = new MemStorage())
-            {
-                Contour<Point> contour = hand.Mask.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL);
-                List<MCvConvexityDefect> mcvConvexityDefects = new List<MCvConvexityDefect>(contour.GetConvexityDefacts(ms, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE));
-
-                convexityDefects = new List<ConvexityDefect>();
-                foreach (MCvConvexityDefect defect in mcvConvexityDefects)
-                    convexityDefects.Add(new ConvexityDefect(defect));
-            }
-            return convexityDefects;
-        }
-
-        /// <summary>
-        /// Checks all convexity defects sorted by length if they match the thumb defect requirements and returns the first match or null if none match.
-        /// </summary>
-        /// <param name="thumb">the possible thumb</param>
-        /// <param name="convexityDefects">the convexity defects</param>
-        /// <returns></returns>
-        private ConvexityDefect findThumbDefect(Finger thumb, List<ConvexityDefect> convexityDefects)
-        {
-            convexityDefects.Sort((cd1, cd2) => (cd2.Depth.CompareTo(cd1.Depth)));
-            foreach (ConvexityDefect defect in convexityDefects)
-            {
-                if (defect.isPossibleThumbDefect(thumb))
-                    return defect;
-            }
-            return null;
-        }
-
         /// <summary>
         /// Finds the four palm points and creates a new palm
         /// </summary>
@@ -141,22 +80,23 @@ namespace bbiwarg.Recognition.PalmRecognition
         }
 
         /// <summary>
-        /// Finds the upper wrist end by walking from the defect.Inner towards the wrist direction, until it reaches the hand boundaries.
+        /// Gets the convexity Defects from a hand mask.
         /// </summary>
         /// <param name="hand">the hand</param>
-        /// <param name="thumbDefect">the convexity defect of the thumb</param>
-        /// <returns>the position of the upper wrist end</returns>
-        private Vector2D findWristUpper(Hand hand, ConvexityDefect thumbDefect)
+        /// <returns>the conveixty defects</returns>
+        private List<ConvexityDefect> findConvexityDefects(Hand hand)
         {
-            Vector2D wristDirection = thumbDefect.VectorLong.getInverse().normalize();
-            Vector2D wristUpper = thumbDefect.Inner;
-            Vector2D wristUpperNext = wristUpper + 5 * wristDirection;
-            while (wristUpperNext.isInBound(depthImage.Size) && hand.isInside(wristUpperNext))
+            List<ConvexityDefect> convexityDefects;
+            using (MemStorage ms = new MemStorage())
             {
-                wristUpper = wristUpperNext;
-                wristUpperNext += wristDirection;
+                Contour<Point> contour = hand.Mask.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL);
+                List<MCvConvexityDefect> mcvConvexityDefects = new List<MCvConvexityDefect>(contour.GetConvexityDefacts(ms, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE));
+
+                convexityDefects = new List<ConvexityDefect>();
+                foreach (MCvConvexityDefect defect in mcvConvexityDefects)
+                    convexityDefects.Add(new ConvexityDefect(defect));
             }
-            return wristUpper;
+            return convexityDefects;
         }
 
         /// <summary>
@@ -189,6 +129,27 @@ namespace bbiwarg.Recognition.PalmRecognition
             return fingersUpper;
         }
 
+        /// <summary>
+        /// Find Palms by checking each hand with only one finger, if that finger is a thumb.
+        /// </summary>
+        private void findPalms()
+        {
+            palms = new List<Palm>();
+            foreach (Hand hand in hands)
+            {
+                if (hand.Fingers.Count == 1)
+                {
+                    List<ConvexityDefect> convexityDefects = findConvexityDefects(hand);
+                    ConvexityDefect thumbDefect = findThumbDefect(hand.Fingers[0], convexityDefects);
+                    if (thumbDefect != null)
+                    {
+                        Palm palm = createPalm(hand, thumbDefect);
+                        palms.Add(palm);
+                    }
+                }
+            }
+        }
+
         /// <summary>
         /// Gets the palm width by checking for the maximum orthogonal length withing the hand along multiple positions on the index finger (defect.inner<->defect.outerLong)
         /// </summary>
@@ -217,5 +178,41 @@ namespace bbiwarg.Recognition.PalmRecognition
             }
             return maxWidth;
         }
+
+        /// <summary>
+        /// Checks all convexity defects sorted by length if they match the thumb defect requirements and returns the first match or null if none match.
+        /// </summary>
+        /// <param name="thumb">the possible thumb</param>
+        /// <param name="convexityDefects">the convexity defects</param>
+        /// <returns></returns>
+        private ConvexityDefect findThumbDefect(Finger thumb, List<ConvexityDefect> convexityDefects)
+        {
+            convexityDefects.Sort((cd1, cd2) => (cd2.Depth.CompareTo(cd1.Depth)));
+            foreach (ConvexityDefect defect in convexityDefects)
+            {
+                if (defect.isPossibleThumbDefect(thumb))
+                    return defect;
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// Finds the upper wrist end by walking from the defect.Inner towards the wrist direction, until it reaches the hand boundaries.
+        /// </summary>
+        /// <param name="hand">the hand</param>
+        /// <param name="thumbDefect">the convexity defect of the thumb</param>
+        /// <returns>the position of the upper wrist end</returns>
+        private Vector2D findWristUpper(Hand hand, ConvexityDefect thumbDefect)
+        {
+            Vector2D wristDirection = thumbDefect.VectorLong.getInverse().normalize();
+            Vector2D wristUpper = thumbDefect.Inner;
+            Vector2D wristUpperNext = wristUpper + 5 * wristDirection;
+            while (wristUpperNext.isInBound(depthImage.Size) && hand.isInside(wristUpperNext))
+            {
+                wristUpper = wristUpperNext;
+                wristUpperNext += wristDirection;
+            }
+            return wristUpper;
+        }
     }
-}
+}

+ 14 - 19
bbiwarg/Recognition/PalmRecognition/PalmTracker.cs

@@ -1,20 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.Tracking;
-using bbiwarg.Input.InputHandling;
 using bbiwarg.Utility;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
     /// <summary>
     /// Keeps track of palms over a period of time.
     /// </summary>
-    class PalmTracker : Tracker<Palm, TrackedPalm>
+    internal class PalmTracker : Tracker<Palm, TrackedPalm>
     {
-
         /// <summary>
         /// Initializes a new instance of the PalmTracker class.
         /// </summary>
@@ -24,16 +19,6 @@ namespace bbiwarg.Recognition.PalmRecognition
         {
         }
 
-        /// <summary>
-        /// Updates the tracked palms with the detected palms in the current frame and stores the (optimized) results in frameData.trackedPalms
-        /// </summary>
-        /// <param name="frameData"></param>
-        public void trackPalms(FrameData frameData)
-        {
-            trackObjects(frameData.DetectedPalms);
-            frameData.TrackedPalms = getOptimizedPalms();
-        }
-
         /// <summary>
         /// Calculates the similarity [0-1] of a tracked palm and a detected palm
         /// </summary>
@@ -51,6 +36,16 @@ namespace bbiwarg.Recognition.PalmRecognition
             return handSimilarity * wristUpperSimilarity * wristLowerSimilarity * fingersUpperSimilarity * fingersLowerSimilarity;
         }
 
+        /// <summary>
+        /// Updates the tracked palms with the detected palms in the current frame and stores the (optimized) results in frameData.trackedPalms
+        /// </summary>
+        /// <param name="frameData"></param>
+        public void trackPalms(FrameData frameData)
+        {
+            trackObjects(frameData.DetectedPalms);
+            frameData.TrackedPalms = getOptimizedPalms();
+        }
+
         /// <summary>
         /// Creates a TrackedPalm
         /// </summary>
@@ -76,4 +71,4 @@ namespace bbiwarg.Recognition.PalmRecognition
             return optimizedPalms;
         }
     }
-}
+}

+ 29 - 35
bbiwarg/Recognition/PalmRecognition/TrackedPalm.cs

@@ -1,28 +1,18 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.Tracking;
-using bbiwarg.Recognition.HandRecognition;
+using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
+using System;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
     /// <summary>
     /// Represents a palm that ist tracked for several frames.
     /// </summary>
-    class TrackedPalm : TrackedObject<Palm>
+    internal class TrackedPalm : TrackedObject<Palm>
     {
         /// <summary>
-        /// the kalman filter for the wrist upper prediction
-        /// </summary>
-        private Kalman2DPositionFilter wristUpperKalman;
-
-        /// <summary>
-        /// the kalman filter for the wrist lower prediction
+        /// the kalman filter for the fingers lower prediction
         /// </summary>
-        private Kalman2DPositionFilter wristLowerKalman;
+        private Kalman2DPositionFilter fingersLowerKalman;
 
         /// <summary>
         /// the kalman filter for the fingers upper prediction
@@ -30,19 +20,19 @@ namespace bbiwarg.Recognition.PalmRecognition
         private Kalman2DPositionFilter fingersUpperKalman;
 
         /// <summary>
-        /// the kalman filter for the fingers lower prediction
+        /// the kalman filter for the wrist lower prediction
         /// </summary>
-        private Kalman2DPositionFilter fingersLowerKalman;
+        private Kalman2DPositionFilter wristLowerKalman;
 
         /// <summary>
-        /// the predicted position of the wrist upper
+        /// the kalman filter for the wrist upper prediction
         /// </summary>
-        public Vector2D WristUpperPrediction { get { return wristUpperKalman.getPrediction(); } }
+        private Kalman2DPositionFilter wristUpperKalman;
 
         /// <summary>
-        /// the predicted position of the wrist lower
+        /// the predicted position of the fingers lower
         /// </summary>
-        public Vector2D WristLowerPrediction { get { return wristLowerKalman.getPrediction(); } }
+        public Vector2D FingersLowerPrediction { get { return fingersLowerKalman.getPrediction(); } }
 
         /// <summary>
         /// the predicted position of the fingers upper
@@ -50,14 +40,19 @@ namespace bbiwarg.Recognition.PalmRecognition
         public Vector2D FingersUpperPrediction { get { return fingersUpperKalman.getPrediction(); } }
 
         /// <summary>
-        /// the predicted position of the fingers lower
+        /// the optimized palm (using predicted palm points)
         /// </summary>
-        public Vector2D FingersLowerPrediction { get { return fingersLowerKalman.getPrediction(); } }
+        public Palm OptimizedPalm { get; private set; }
 
         /// <summary>
-        /// the optimized palm (using predicted palm points)
+        /// the predicted position of the wrist lower
         /// </summary>
-        public Palm OptimizedPalm { get; private set; }
+        public Vector2D WristLowerPrediction { get { return wristLowerKalman.getPrediction(); } }
+
+        /// <summary>
+        /// the predicted position of the wrist upper
+        /// </summary>
+        public Vector2D WristUpperPrediction { get { return wristUpperKalman.getPrediction(); } }
 
         /// <summary>
         /// Initializes a new instance of the TrackedPalm class.
@@ -104,15 +99,6 @@ namespace bbiwarg.Recognition.PalmRecognition
             }
         }
 
-        /// <summary>
-        /// Updates the optimized palm by creating a new palm with the predicted palm points
-        /// </summary>
-        /// <param name="detectedPalm"></param>
-        private void updateOptimizedPalm(Palm detectedPalm)
-        {
-            OptimizedPalm = new Palm(detectedPalm.Hand, detectedPalm.ThumbDefect, detectedPalm.HandSide, WristUpperPrediction, FingersUpperPrediction, FingersLowerPrediction, WristLowerPrediction);
-        }
-
         /// <summary>
         /// logs the state change
         /// </summary>
@@ -122,5 +108,13 @@ namespace bbiwarg.Recognition.PalmRecognition
             Logger.log(String.Format("Palm #{0} {1}", this.ID, stateAsString), LogSubject.PalmTracker);
         }
 
+        /// <summary>
+        /// Updates the optimized palm by creating a new palm with the predicted palm points
+        /// </summary>
+        /// <param name="detectedPalm"></param>
+        private void updateOptimizedPalm(Palm detectedPalm)
+        {
+            OptimizedPalm = new Palm(detectedPalm.Hand, detectedPalm.ThumbDefect, detectedPalm.HandSide, WristUpperPrediction, FingersUpperPrediction, FingersLowerPrediction, WristLowerPrediction);
+        }
     }
-}
+}

+ 6 - 15
bbiwarg/Recognition/TouchRecognition/Touch.cs

@@ -1,14 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.FingerRecognition;
+using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.PalmRecognition;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
-using Emgu.CV;
-using Emgu.CV.Structure;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
@@ -22,11 +15,6 @@ namespace bbiwarg.Recognition.TouchRecognition
         /// </summary>
         public Vector2D AbsolutePosition { get; private set; }
 
-        /// <summary>
-        /// the relative position of the touch within the palm quad
-        /// </summary>
-        public Vector2D RelativePosition { get; private set; }
-
         /// <summary>
         /// the touching finger
         /// </summary>
@@ -37,6 +25,10 @@ namespace bbiwarg.Recognition.TouchRecognition
         /// </summary>
         public Palm Palm { get; private set; }
 
+        /// <summary>
+        /// the relative position of the touch within the palm quad
+        /// </summary>
+        public Vector2D RelativePosition { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the Touch class.
@@ -53,6 +45,5 @@ namespace bbiwarg.Recognition.TouchRecognition
 
             finger.Touch = this;
         }
-
     }
-}
+}

+ 9 - 13
bbiwarg/Recognition/TouchRecognition/TouchDetector.cs

@@ -1,24 +1,20 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Emgu.CV;
-using Emgu.CV.Structure;
-using bbiwarg.Images;
+using bbiwarg.Images;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.PalmRecognition;
 using bbiwarg.Utility;
-using bbiwarg.Output;
-using bbiwarg.Input.InputHandling;
+using Emgu.CV;
+using Emgu.CV.Structure;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
     /// <summary>
     /// Detects touches by flood filling around a small area around each finger tip and counting the number of affected pixels. If the finger is touching or slightly hovering above something, the flood fill spreads into the touched object and the number of affected pixels is higher.
     /// </summary>
-    class TouchDetector
+    internal class TouchDetector
     {
         /// <summary>
         /// the depth image of the current frame
@@ -121,4 +117,4 @@ namespace bbiwarg.Recognition.TouchRecognition
             return touchMask.Copy(cropRect);
         }
     }
-}
+}

+ 6 - 12
bbiwarg/Recognition/TouchRecognition/TouchEvent.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bbiwarg.Recognition.TouchRecognition
+namespace bbiwarg.Recognition.TouchRecognition
 {
     /// <summary>
     /// The type of the touch event.
@@ -22,14 +16,14 @@ namespace bbiwarg.Recognition.TouchRecognition
     public class TouchEvent
     {
         /// <summary>
-        /// the type of the touch event
+        /// the touch of the touch event
         /// </summary>
-        public TouchEventType Type { get; private set; }
+        public Touch Touch { get; private set; }
 
         /// <summary>
-        /// the touch of the touch event
+        /// the type of the touch event
         /// </summary>
-        public Touch Touch { get; private set; }
+        public TouchEventType Type { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the TouchEvent class.
@@ -42,4 +36,4 @@ namespace bbiwarg.Recognition.TouchRecognition
             Touch = touch;
         }
     }
-}
+}

+ 22 - 30
bbiwarg/Recognition/TouchRecognition/TouchTracker.cs

@@ -1,21 +1,14 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Images;
-using bbiwarg.Output;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
-using bbiwarg.Input.InputHandling;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
     /// <summary>
     /// Keeps track of touches over a period of time and generates touch events
     /// </summary>
-    class TouchTracker : Tracker<Touch, TrackedTouch>
+    internal class TouchTracker : Tracker<Touch, TrackedTouch>
     {
         /// <summary>
         /// the touch events in the current frame
@@ -32,17 +25,6 @@ namespace bbiwarg.Recognition.TouchRecognition
             touchEvents = new List<TouchEvent>();
         }
 
-        /// <summary>
-        /// Updates the tracked touches, and stores the (optimized) touches in frameData.trackedTouches and the touch events in frameData.touchEvents.
-        /// </summary>
-        /// <param name="frameData"></param>
-        public void trackTouches(FrameData frameData)
-        {
-            trackObjects(frameData.DetectedTouches);
-            frameData.TrackedTouches = getOptimizedTouches();
-            frameData.TouchEvents = flushTouchEvents();
-        }
-
         /// <summary>
         /// Calculates the similarity [0-1] of a tracked touch and a detected touch.
         /// </summary>
@@ -54,6 +36,24 @@ namespace bbiwarg.Recognition.TouchRecognition
             return (trackedTouch.FingerID == detectedTouch.Finger.TrackID) ? 1 : 0;
         }
 
+        public List<TouchEvent> flushTouchEvents()
+        {
+            List<TouchEvent> flushedTouchEvents = touchEvents;
+            touchEvents = new List<TouchEvent>();
+            return flushedTouchEvents;
+        }
+
+        /// <summary>
+        /// Updates the tracked touches, and stores the (optimized) touches in frameData.trackedTouches and the touch events in frameData.touchEvents.
+        /// </summary>
+        /// <param name="frameData"></param>
+        public void trackTouches(FrameData frameData)
+        {
+            trackObjects(frameData.DetectedTouches);
+            frameData.TrackedTouches = getOptimizedTouches();
+            frameData.TouchEvents = flushTouchEvents();
+        }
+
         /// <summary>
         /// Creates a new TrackedTouch
         /// </summary>
@@ -85,13 +85,5 @@ namespace bbiwarg.Recognition.TouchRecognition
         {
             touchEvents.Add(e);
         }
-
-        public List<TouchEvent> flushTouchEvents()
-        {
-            List<TouchEvent> flushedTouchEvents = touchEvents;
-            touchEvents = new List<TouchEvent>();
-            return flushedTouchEvents;
-        }
-
     }
-}
+}

+ 15 - 21
bbiwarg/Recognition/TouchRecognition/TrackedTouch.cs

@@ -1,10 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.Tracking;
+using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
+using System;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
@@ -31,9 +27,9 @@ namespace bbiwarg.Recognition.TouchRecognition
         public Vector2D AbsolutePositionPrediction { get { return absolutePositionKalman.getPrediction(); } }
 
         /// <summary>
-        /// the optimized touch (using the predicted absolute position)
+        /// the track ID of the touching finger
         /// </summary>
-        public Touch OptimizedTouch { get; private set; }
+        public int FingerID { get; private set; }
 
         /// <summary>
         /// indicates if the touch is currently active
@@ -41,9 +37,9 @@ namespace bbiwarg.Recognition.TouchRecognition
         public bool IsTouchActive { get; private set; }
 
         /// <summary>
-        /// the track ID of the touching finger
+        /// the optimized touch (using the predicted absolute position)
         /// </summary>
-        public int FingerID { get; private set; }
+        public Touch OptimizedTouch { get; private set; }
 
         /// <summary>
         /// the event which is fired, if a touchEvent occurs
@@ -96,16 +92,6 @@ namespace bbiwarg.Recognition.TouchRecognition
             }
             else if (IsTouchActive && CurrentState == TrackingState.Deleted)
                 TriggerTouchUp();
-
-        }
-
-        /// <summary>
-        /// Updates the optimized touch using the absolute position prediction
-        /// </summary>
-        /// <param name="detectedTouch">the detected touch</param>
-        private void updateOptimizedTouch(Touch detectedTouch)
-        {
-            OptimizedTouch = new Touch(AbsolutePositionPrediction, detectedTouch.Finger, detectedTouch.Palm);
         }
 
         /// <summary>
@@ -152,5 +138,13 @@ namespace bbiwarg.Recognition.TouchRecognition
             }
         }
 
+        /// <summary>
+        /// Updates the optimized touch using the absolute position prediction
+        /// </summary>
+        /// <param name="detectedTouch">the detected touch</param>
+        private void updateOptimizedTouch(Touch detectedTouch)
+        {
+            OptimizedTouch = new Touch(AbsolutePositionPrediction, detectedTouch.Finger, detectedTouch.Palm);
+        }
     }
-}
+}

+ 6 - 13
bbiwarg/Recognition/Tracking/Similarity.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bbiwarg.Recognition.Tracking
+namespace bbiwarg.Recognition.Tracking
 {
     /// <summary>
     /// Encapsulates the similarity between a TrackedObject and a TrackableObject.
@@ -16,21 +10,20 @@ namespace bbiwarg.Recognition.Tracking
         where TrackedT : TrackedObject<T>
     {
         /// <summary>
-        /// the tracked object
+        /// the detected object
         /// </summary>
-        public TrackedT TrackedObject { get; private set; }
+        public T DetectedObject { get; private set; }
 
         /// <summary>
-        /// the detected object
+        /// the tracked object
         /// </summary>
-        public T DetectedObject { get; private set; }
+        public TrackedT TrackedObject { get; private set; }
 
         /// <summary>
         /// the similarity value [0-1]
         /// </summary>
         public float Value { get; private set; }
 
-
         /// <summary>
         /// Initializes a new instance of the Similarity class.
         /// </summary>
@@ -44,4 +37,4 @@ namespace bbiwarg.Recognition.Tracking
             Value = value;
         }
     }
-}
+}

+ 2 - 6
bbiwarg/Recognition/Tracking/TrackIDPool.cs

@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.Tracking
 {
@@ -46,4 +42,4 @@ namespace bbiwarg.Recognition.Tracking
             usedIDs.Remove(id);
         }
     }
-}
+}

+ 2 - 8
bbiwarg/Recognition/Tracking/TrackableObject.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bbiwarg.Recognition.Tracking
+namespace bbiwarg.Recognition.Tracking
 {
     /// <summary>
     /// A object that can be identified via a unique ID.
@@ -25,4 +19,4 @@ namespace bbiwarg.Recognition.Tracking
             TrackID = id;
         }
     }
-}
+}

+ 14 - 20
bbiwarg/Recognition/Tracking/TrackedObject.cs

@@ -1,11 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Utility;
-
-namespace bbiwarg.Recognition.Tracking
+namespace bbiwarg.Recognition.Tracking
 {
     /// <summary>
     /// The possible tracking state values
@@ -40,36 +33,35 @@ namespace bbiwarg.Recognition.Tracking
         /// </summary>
         private bool wasTrackedBefore;
 
-        /// <summary>
-        /// the objects track id
-        /// </summary>
-        public int ID { get; private set; }
-
         /// <summary>
         /// a reference to the current TrackableObject
         /// </summary>
         public T CurrentObject { get; private set; }
 
         /// <summary>
-        /// a reference to the last TrackableObject
+        /// the current tracking state
         /// </summary>
-        public T LastObject { get; private set; }
+        public TrackingState CurrentState { get; private set; }
 
         /// <summary>
-        /// the current tracking state
+        /// the objects track id
         /// </summary>
-        public TrackingState CurrentState { get; private set; }
+        public int ID { get; private set; }
 
         /// <summary>
-        /// the previous tracking state
+        /// a reference to the last TrackableObject
         /// </summary>
-        public TrackingState PreviousState { get; private set; }
+        public T LastObject { get; private set; }
 
         /// <summary>
         /// the number of consecutive frames in the current state
         /// </summary>
         public int NumFramesInCurrentState { get; private set; }
 
+        /// <summary>
+        /// the previous tracking state
+        /// </summary>
+        public TrackingState PreviousState { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the TrackedObject class.
@@ -138,9 +130,11 @@ namespace bbiwarg.Recognition.Tracking
                         else
                             newState = TrackingState.Detected;
                         break;
+
                     case TrackingState.Tracked:
                         newState = TrackingState.Tracked;
                         break;
+
                     case TrackingState.Detected:
                         if (NumFramesInCurrentState >= numFramesDetectedUntilTracked)
                             newState = TrackingState.Tracked;
@@ -157,4 +151,4 @@ namespace bbiwarg.Recognition.Tracking
             return newState;
         }
     }
-}
+}

+ 56 - 57
bbiwarg/Recognition/Tracking/Tracker.cs

@@ -1,6 +1,6 @@
-using System.Collections.Generic;
+using bbiwarg.Utility;
 using System;
-using bbiwarg.Utility;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.Tracking
 {
@@ -14,14 +14,9 @@ namespace bbiwarg.Recognition.Tracking
         where TrackedT : TrackedObject<T>
     {
         /// <summary>
-        /// the size of the input image (used to calculate position similarities)
-        /// </summary>
-        private ImageSize imageSize;
-
-        /// <summary>
-        /// list of similarities between trackableObjects and trackedObjects
+        /// the trackedObjects
         /// </summary>
-        private List<Similarity<T, TrackedT>> similarities;
+        public List<TrackedT> TrackedObjects;
 
         /// <summary>
         /// the unique ID generator
@@ -29,10 +24,14 @@ namespace bbiwarg.Recognition.Tracking
         protected TrackIDPool idPool;
 
         /// <summary>
-        /// the trackedObjects
+        /// the size of the input image (used to calculate position similarities)
         /// </summary>
-        public List<TrackedT> TrackedObjects;
+        private ImageSize imageSize;
 
+        /// <summary>
+        /// list of similarities between trackableObjects and trackedObjects
+        /// </summary>
+        private List<Similarity<T, TrackedT>> similarities;
 
         /// <summary>
         /// Initializes a new instance of the Tracker class.
@@ -44,6 +43,14 @@ namespace bbiwarg.Recognition.Tracking
             reset();
         }
 
+        /// <summary>
+        /// Calculates the similarity [0-1] between a TrackedObject and a TrackableObject.
+        /// </summary>
+        /// <param name="trackedObject">the tracked object</param>
+        /// <param name="detectedObject">the detected trackable object</param>
+        /// <returns>the smiliarity [0-1]</returns>
+        public abstract float calculateSimilarity(TrackedT trackedObject, T detectedObject);
+
         /// <summary>
         /// Resets the idPool and the trackedObjects.
         /// </summary>
@@ -53,6 +60,44 @@ namespace bbiwarg.Recognition.Tracking
             TrackedObjects = new List<TrackedT>();
         }
 
+        /// <summary>
+        /// Creates a new TrackedObject with the given TrackableObject as initial object.
+        /// </summary>
+        /// <param name="detectedObject">the initial trackableObject</param>
+        /// <returns>the TrackedObject</returns>
+        protected abstract TrackedT createTrackedObject(T detectedObject);
+
+        /// <summary>
+        /// Gets a list of TrackableObjects from all TrackedObjects with the given state.
+        /// </summary>
+        /// <param name="state">the desired tracking state</param>
+        /// <returns>the list of trackableObjects with the given state</returns>
+        protected List<T> getCurrentObjectsWithState(TrackingState state)
+        {
+            List<T> objects = new List<T>();
+            foreach (TrackedT trackedObject in TrackedObjects)
+            {
+                if (trackedObject.CurrentState == state)
+                    objects.Add(trackedObject.CurrentObject);
+            }
+            return objects;
+        }
+
+        /// <summary>
+        /// Calculates a similarity [0-1] between two positions with the given maximum relative distance.
+        /// </summary>
+        /// <param name="p1">the first position</param>
+        /// <param name="p2">the second position</param>
+        /// <param name="maxRelativeDistance">the maximum distance [0-1] relative to the image size (maxAbsoluteDistance = maxRelativeDistance*imageSize.DiagonalLenght)</param>
+        /// <returns>the calculated similarity between the two positions</returns>
+        protected float getPositionSimilarity(Vector2D p1, Vector2D p2, float maxRelativeDistance)
+        {
+            float distance = p1.getDistanceTo(p2);
+            float maxDistance = maxRelativeDistance * imageSize.DiagonalLength;
+            float similarity = Math.Max(1 - distance / maxDistance, 0);
+            return similarity;
+        }
+
         /// <summary>
         /// adds new TrackedObjects or updates and removes TrackedObjects with the new trackableObjects
         /// </summary>
@@ -133,14 +178,6 @@ namespace bbiwarg.Recognition.Tracking
             similarities.Sort((s1, s2) => s2.Value.CompareTo(s1.Value));
         }
 
-        /// <summary>
-        /// Calculates the similarity [0-1] between a TrackedObject and a TrackableObject.
-        /// </summary>
-        /// <param name="trackedObject">the tracked object</param>
-        /// <param name="detectedObject">the detected trackable object</param>
-        /// <returns>the smiliarity [0-1]</returns>
-        public abstract float calculateSimilarity(TrackedT trackedObject, T detectedObject);
-
         /// <summary>
         /// Removes all similarities with the trackedObject or the same trackableObject as the given similarity.
         /// </summary>
@@ -170,43 +207,5 @@ namespace bbiwarg.Recognition.Tracking
                 }
             }
         }
-
-        /// <summary>
-        /// Gets a list of TrackableObjects from all TrackedObjects with the given state.
-        /// </summary>
-        /// <param name="state">the desired tracking state</param>
-        /// <returns>the list of trackableObjects with the given state</returns>
-        protected List<T> getCurrentObjectsWithState(TrackingState state)
-        {
-            List<T> objects = new List<T>();
-            foreach (TrackedT trackedObject in TrackedObjects)
-            {
-                if (trackedObject.CurrentState == state)
-                    objects.Add(trackedObject.CurrentObject);
-            }
-            return objects;
-        }
-
-        /// <summary>
-        /// Creates a new TrackedObject with the given TrackableObject as initial object.
-        /// </summary>
-        /// <param name="detectedObject">the initial trackableObject</param>
-        /// <returns>the TrackedObject</returns>
-        protected abstract TrackedT createTrackedObject(T detectedObject);
-
-        /// <summary>
-        /// Calculates a similarity [0-1] between two positions with the given maximum relative distance.
-        /// </summary>
-        /// <param name="p1">the first position</param>
-        /// <param name="p2">the second position</param>
-        /// <param name="maxRelativeDistance">the maximum distance [0-1] relative to the image size (maxAbsoluteDistance = maxRelativeDistance*imageSize.DiagonalLenght)</param>
-        /// <returns>the calculated similarity between the two positions</returns>
-        protected float getPositionSimilarity(Vector2D p1, Vector2D p2, float maxRelativeDistance)
-        {
-            float distance = p1.getDistanceTo(p2);
-            float maxDistance = maxRelativeDistance * imageSize.DiagonalLength;
-            float similarity = Math.Max(1 - distance / maxDistance, 0);
-            return similarity;
-        }
     }
 }

+ 37 - 36
bbiwarg/TUIO/OSC.NET/OSCBundle.cs

@@ -1,4 +1,3 @@
-using System;
 using System.Collections;
 
 namespace OSC.NET
@@ -23,35 +22,10 @@ namespace OSC.NET
             this.timestamp = 0;
         }
 
-        override protected void pack()
-        {
-            ArrayList data = new ArrayList();
-
-            addBytes(data, packString(this.Address));
-            padNull(data);
-            addBytes(data, packLong(0)); // TODO
-
-            foreach (object value in this.Values)
-            {
-                if (value is OSCPacket)
-                {
-                    byte[] bs = ((OSCPacket)value).BinaryData;
-                    addBytes(data, packInt(bs.Length));
-                    addBytes(data, bs);
-                }
-                else
-                {
-                    // TODO
-                }
-            }
-
-            this.binaryData = (byte[])data.ToArray(typeof(byte));
-        }
-
         public static new OSCBundle Unpack(byte[] bytes, ref int start, int end)
         {
-
             string address = unpackString(bytes, ref start);
+
             //Console.WriteLine("bundle: " + address);
             if (!address.Equals(BUNDLE)) return null; // TODO
 
@@ -62,19 +36,14 @@ namespace OSC.NET
             {
                 int length = unpackInt(bytes, ref start);
                 int sub_end = start + length;
+
                 //Console.WriteLine(bytes.Length +" "+ start+" "+length+" "+sub_end);
                 bundle.Append(OSCPacket.Unpack(bytes, ref start, sub_end));
-
             }
 
             return bundle;
         }
 
-        public long getTimeStamp()
-        {
-            return timestamp;
-        }
-
         override public void Append(object value)
         {
             if (value is OSCPacket)
@@ -87,7 +56,39 @@ namespace OSC.NET
             }
         }
 
-        override public bool IsBundle() { return true; }
-    }
-}
+        public long getTimeStamp()
+        {
+            return timestamp;
+        }
 
+        override public bool IsBundle()
+        {
+            return true;
+        }
+
+        override protected void pack()
+        {
+            ArrayList data = new ArrayList();
+
+            addBytes(data, packString(this.Address));
+            padNull(data);
+            addBytes(data, packLong(0)); // TODO
+
+            foreach (object value in this.Values)
+            {
+                if (value is OSCPacket)
+                {
+                    byte[] bs = ((OSCPacket)value).BinaryData;
+                    addBytes(data, packInt(bs.Length));
+                    addBytes(data, bs);
+                }
+                else
+                {
+                    // TODO
+                }
+            }
+
+            this.binaryData = (byte[])data.ToArray(typeof(byte));
+        }
+    }
+}

+ 41 - 36
bbiwarg/TUIO/OSC.NET/OSCMessage.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections;
-using System.Text;
 
 namespace OSC.NET
 {
@@ -9,20 +8,24 @@ namespace OSC.NET
     /// </summary>
     public class OSCMessage : OSCPacket
     {
-        protected const char INTEGER = 'i';
+        protected const char DOUBLE = 'd';
         protected const char FLOAT = 'f';
+        protected const char INTEGER = 'i';
         protected const char LONG = 'h';
-        protected const char DOUBLE = 'd';
         protected const char STRING = 's';
         protected const char SYMBOL = 'S';
+
         //protected const char BLOB	  = 'b';
         //protected const char ALL     = '*';
 
+        protected string typeTag;
+
         public OSCMessage(string address)
         {
             this.typeTag = ",";
             this.Address = address;
         }
+
         public OSCMessage(string address, object value)
         {
             this.typeTag = ",";
@@ -30,43 +33,15 @@ namespace OSC.NET
             Append(value);
         }
 
-        override protected void pack()
-        {
-            ArrayList data = new ArrayList();
-
-            addBytes(data, packString(this.address));
-            padNull(data);
-            addBytes(data, packString(this.typeTag));
-            padNull(data);
-
-            foreach (object value in this.Values)
-            {
-                if (value is int) addBytes(data, packInt((int)value));
-                else if (value is long) addBytes(data, packLong((long)value));
-                else if (value is float) addBytes(data, packFloat((float)value));
-                else if (value is double) addBytes(data, packDouble((double)value));
-                else if (value is string)
-                {
-                    addBytes(data, packString((string)value));
-                    padNull(data);
-                }
-                else
-                {
-                    // TODO
-                }
-            }
-
-            this.binaryData = (byte[])data.ToArray(typeof(byte));
-        }
-
-
         public static OSCMessage Unpack(byte[] bytes, ref int start)
         {
             string address = unpackString(bytes, ref start);
+
             //Console.WriteLine("address: " + address);
             OSCMessage msg = new OSCMessage(address);
 
             char[] tags = unpackString(bytes, ref start).ToCharArray();
+
             //Console.WriteLine("tags: " + new string(tags));
             foreach (char tag in tags)
             {
@@ -112,13 +87,43 @@ namespace OSC.NET
             values.Add(value);
         }
 
-        protected string typeTag;
+        override public bool IsBundle()
+        {
+            return false;
+        }
+
         protected void AppendTag(char type)
         {
             typeTag += type;
         }
 
+        override protected void pack()
+        {
+            ArrayList data = new ArrayList();
+
+            addBytes(data, packString(this.address));
+            padNull(data);
+            addBytes(data, packString(this.typeTag));
+            padNull(data);
 
-        override public bool IsBundle() { return false; }
+            foreach (object value in this.Values)
+            {
+                if (value is int) addBytes(data, packInt((int)value));
+                else if (value is long) addBytes(data, packLong((long)value));
+                else if (value is float) addBytes(data, packFloat((float)value));
+                else if (value is double) addBytes(data, packDouble((double)value));
+                else if (value is string)
+                {
+                    addBytes(data, packString((string)value));
+                    padNull(data);
+                }
+                else
+                {
+                    // TODO
+                }
+            }
+
+            this.binaryData = (byte[])data.ToArray(typeof(byte));
+        }
     }
-}
+}

+ 76 - 69
bbiwarg/TUIO/OSC.NET/OSCPacket.cs

@@ -9,61 +9,90 @@ namespace OSC.NET
     /// </summary>
     abstract public class OSCPacket
     {
-        public OSCPacket()
-        {
-            this.values = new ArrayList();
-        }
+        protected string address;
 
-        protected static void addBytes(ArrayList data, byte[] bytes)
+        protected byte[] binaryData;
+
+        protected ArrayList values;
+
+        public string Address
         {
-            foreach (byte b in bytes)
+            get
             {
-                data.Add(b);
+                return address;
+            }
+            set
+            {
+                // TODO: validate
+                address = value;
             }
         }
 
-        protected static void padNull(ArrayList data)
+        public byte[] BinaryData
         {
-            byte zero = 0;
-            int pad = 4 - (data.Count % 4);
-            for (int i = 0; i < pad; i++)
+            get
             {
-                data.Add(zero);
+                pack();
+                return binaryData;
             }
         }
 
-        protected static byte[] swapEndian(byte[] data)
+        public ArrayList Values
         {
-            byte[] swapped = new byte[data.Length];
-            for (int i = data.Length - 1, j = 0; i >= 0; i--, j++)
+            get { return (ArrayList)values.Clone(); }
+        }
+
+        public OSCPacket()
+        {
+            this.values = new ArrayList();
+        }
+
+        public static OSCPacket Unpack(byte[] bytes)
+        {
+            int start = 0;
+            return Unpack(bytes, ref start, bytes.Length);
+        }
+
+        public static OSCPacket Unpack(byte[] bytes, ref int start, int end)
+        {
+            if (bytes[start] == '#') return OSCBundle.Unpack(bytes, ref start, end);
+            else return OSCMessage.Unpack(bytes, ref start);
+        }
+
+        abstract public void Append(object value);
+
+        abstract public bool IsBundle();
+
+        protected static void addBytes(ArrayList data, byte[] bytes)
+        {
+            foreach (byte b in bytes)
             {
-                swapped[j] = data[i];
+                data.Add(b);
             }
-            return swapped;
         }
 
-        protected static byte[] packInt(int value)
+        protected static byte[] packDouble(double value)
         {
             byte[] data = BitConverter.GetBytes(value);
             if (BitConverter.IsLittleEndian) data = swapEndian(data);
             return data;
         }
 
-        protected static byte[] packLong(long value)
+        protected static byte[] packFloat(float value)
         {
             byte[] data = BitConverter.GetBytes(value);
             if (BitConverter.IsLittleEndian) data = swapEndian(data);
             return data;
         }
 
-        protected static byte[] packFloat(float value)
+        protected static byte[] packInt(int value)
         {
             byte[] data = BitConverter.GetBytes(value);
             if (BitConverter.IsLittleEndian) data = swapEndian(data);
             return data;
         }
 
-        protected static byte[] packDouble(double value)
+        protected static byte[] packLong(long value)
         {
             byte[] data = BitConverter.GetBytes(value);
             if (BitConverter.IsLittleEndian) data = swapEndian(data);
@@ -75,31 +104,32 @@ namespace OSC.NET
             return System.Text.Encoding.ASCII.GetBytes(value);
         }
 
-        abstract protected void pack();
-        protected byte[] binaryData;
-        public byte[] BinaryData
+        protected static void padNull(ArrayList data)
         {
-            get
+            byte zero = 0;
+            int pad = 4 - (data.Count % 4);
+            for (int i = 0; i < pad; i++)
             {
-                pack();
-                return binaryData;
+                data.Add(zero);
             }
         }
 
-        protected static int unpackInt(byte[] bytes, ref int start)
+        protected static byte[] swapEndian(byte[] data)
         {
-            byte[] data = new byte[4];
-            for (int i = 0; i < 4; i++, start++) data[i] = bytes[start];
-            if (BitConverter.IsLittleEndian) data = swapEndian(data);
-            return BitConverter.ToInt32(data, 0);
+            byte[] swapped = new byte[data.Length];
+            for (int i = data.Length - 1, j = 0; i >= 0; i--, j++)
+            {
+                swapped[j] = data[i];
+            }
+            return swapped;
         }
 
-        protected static long unpackLong(byte[] bytes, ref int start)
+        protected static double unpackDouble(byte[] bytes, ref int start)
         {
             byte[] data = new byte[8];
             for (int i = 0; i < 8; i++, start++) data[i] = bytes[start];
             if (BitConverter.IsLittleEndian) data = swapEndian(data);
-            return BitConverter.ToInt64(data, 0);
+            return BitConverter.ToDouble(data, 0);
         }
 
         protected static float unpackFloat(byte[] bytes, ref int start)
@@ -110,12 +140,20 @@ namespace OSC.NET
             return BitConverter.ToSingle(data, 0);
         }
 
-        protected static double unpackDouble(byte[] bytes, ref int start)
+        protected static int unpackInt(byte[] bytes, ref int start)
+        {
+            byte[] data = new byte[4];
+            for (int i = 0; i < 4; i++, start++) data[i] = bytes[start];
+            if (BitConverter.IsLittleEndian) data = swapEndian(data);
+            return BitConverter.ToInt32(data, 0);
+        }
+
+        protected static long unpackLong(byte[] bytes, ref int start)
         {
             byte[] data = new byte[8];
             for (int i = 0; i < 8; i++, start++) data[i] = bytes[start];
             if (BitConverter.IsLittleEndian) data = swapEndian(data);
-            return BitConverter.ToDouble(data, 0);
+            return BitConverter.ToInt64(data, 0);
         }
 
         protected static string unpackString(byte[] bytes, ref int start)
@@ -128,37 +166,6 @@ namespace OSC.NET
             return s;
         }
 
-        public static OSCPacket Unpack(byte[] bytes)
-        {
-            int start = 0;
-            return Unpack(bytes, ref start, bytes.Length);
-        }
-
-        public static OSCPacket Unpack(byte[] bytes, ref int start, int end)
-        {
-            if (bytes[start] == '#') return OSCBundle.Unpack(bytes, ref start, end);
-            else return OSCMessage.Unpack(bytes, ref start);
-        }
-
-
-        protected string address;
-        public string Address
-        {
-            get { return address; }
-            set
-            {
-                // TODO: validate
-                address = value;
-            }
-        }
-
-        protected ArrayList values;
-        public ArrayList Values
-        {
-            get { return (ArrayList)values.Clone(); }
-        }
-        abstract public void Append(object value);
-
-        abstract public bool IsBundle();
+        abstract protected void pack();
     }
-}
+}

+ 8 - 10
bbiwarg/TUIO/OSC.NET/OSCTransmitter.cs

@@ -1,5 +1,4 @@
 using System;
-using System.Net;
 using System.Net.Sockets;
 
 namespace OSC.NET
@@ -9,9 +8,9 @@ namespace OSC.NET
     /// </summary>
     public class OSCTransmitter
     {
-        protected UdpClient udpClient;
         protected string remoteHost;
         protected int remotePort;
+        protected UdpClient udpClient;
 
         public OSCTransmitter(string remoteHost, int remotePort)
         {
@@ -20,18 +19,18 @@ namespace OSC.NET
             Connect();
         }
 
-        public void Connect()
-        {
-            if (this.udpClient != null) Close();
-            this.udpClient = new UdpClient(this.remoteHost, this.remotePort);
-        }
-
         public void Close()
         {
             this.udpClient.Close();
             this.udpClient = null;
         }
 
+        public void Connect()
+        {
+            if (this.udpClient != null) Close();
+            this.udpClient = new UdpClient(this.remoteHost, this.remotePort);
+        }
+
         public int Send(OSCPacket packet)
         {
             int byteNum = 0;
@@ -48,6 +47,5 @@ namespace OSC.NET
 
             return byteNum;
         }
-
     }
-}
+}

+ 75 - 70
bbiwarg/TUIO/TUIO/TuioContainer.cs

@@ -24,23 +24,31 @@ using System.Collections.Generic;
 
 namespace TUIO
 {
-
     /**
      * The abstract TuioContainer class defines common attributes that apply to both subclasses {@link TuioObject} and {@link TuioCursor}.
      *
      * @author Martin Kaltenbrunner
      * @version 1.4
      */
+
     public abstract class TuioContainer : TuioPoint
     {
-
         /**
          * The unique session ID number that is assigned to each TUIO object or cursor.
          */
+        public const int TUIO_ACCELERATING = 1;
+        public const int TUIO_ADDED = 0;
+        public const int TUIO_DECELERATING = 2;
+        public const int TUIO_REMOVED = 4;
+        public const int TUIO_STOPPED = 3;
+        protected float motion_accel;
+        protected float motion_speed;
+        protected List<TuioPoint> path;
         protected long session_id;
         /**
          * The X-axis velocity value.
          */
+        protected int state;
         protected float x_speed;
         /**
          * The Y-axis velocity value.
@@ -49,40 +57,30 @@ namespace TUIO
         /**
          * The motion speed value.
          */
-        protected float motion_speed;
         /**
          * The motion acceleration value.
          */
-        protected float motion_accel;
         /**
          * A Vector of TuioPoints containing all the previous positions of the TUIO component.
          */
-        protected List<TuioPoint> path;
         /**
          * Defines the ADDED state.
          */
-        public const int TUIO_ADDED = 0;
         /**
          * Defines the ACCELERATING state.
          */
-        public const int TUIO_ACCELERATING = 1;
         /**
          * Defines the DECELERATING state.
          */
-        public const int TUIO_DECELERATING = 2;
         /**
          * Defines the STOPPED state.
          */
-        public const int TUIO_STOPPED = 3;
         /**
          * Defines the REMOVED state.
          */
-        public const int TUIO_REMOVED = 4;
         /**
          * Reflects the current state of the TuioComponent
          */
-        protected int state;
-
         /**
          * This constructor takes a TuioTime argument and assigns it along with the provided
          * Session ID, X and Y coordinate to the newly created TuioContainer.
@@ -92,6 +90,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public TuioContainer(TuioTime ttime, long si, float xp, float yp)
             : base(ttime, xp, yp)
         {
@@ -114,6 +113,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public TuioContainer(long si, float xp, float yp)
             : base(xp, yp)
         {
@@ -133,6 +133,7 @@ namespace TUIO
          *
          * @param	tcon	the TuioContainer to assign
          */
+
         public TuioContainer(TuioContainer tcon)
             : base(tcon)
         {
@@ -155,6 +156,64 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
+        public float getMotionAccel()
+        {
+            return motion_accel;
+        }
+
+        public float getMotionSpeed()
+        {
+            return motion_speed;
+        }
+
+        public List<TuioPoint> getPath()
+        {
+            return path;
+        }
+
+        public TuioPoint getPosition()
+        {
+            return new TuioPoint(xpos, ypos);
+        }
+
+        public long getSessionID()
+        {
+            return session_id;
+        }
+
+        public int getTuioState()
+        {
+            return state;
+        }
+
+        public float getXSpeed()
+        {
+            return x_speed;
+        }
+
+        public float getYSpeed()
+        {
+            return y_speed;
+        }
+
+        public bool isMoving()
+        {
+            if ((state == TUIO_ACCELERATING) || (state == TUIO_DECELERATING)) return true;
+            else return false;
+        }
+
+        public void remove(TuioTime ttime)
+        {
+            currentTime = ttime;
+            state = TUIO_REMOVED;
+        }
+
+        public void stop(TuioTime ttime)
+        {
+            update(ttime, this.xpos, this.ypos);
+        }
+
         public new void update(TuioTime ttime, float xp, float yp)
         {
             TuioPoint lastPoint = path[path.Count - 1];
@@ -182,11 +241,6 @@ namespace TUIO
          * This method is used to calculate the speed and acceleration values of
          * TuioContainers with unchanged positions.
          */
-        public void stop(TuioTime ttime)
-        {
-            update(ttime, this.xpos, this.ypos);
-        }
-
         /**
          * Takes a TuioTime argument and assigns it along with the provided
          * X and Y coordinate, X and Y velocity and acceleration
@@ -199,6 +253,7 @@ namespace TUIO
          * @param	ys	the Y velocity to assign
          * @param	ma	the acceleration to assign
          */
+
         public void update(TuioTime ttime, float xp, float yp, float xs, float ys, float ma)
         {
             base.update(ttime, xp, yp);
@@ -222,6 +277,7 @@ namespace TUIO
          * @param	ys	the Y velocity to assign
          * @param	ma	the acceleration to assign
          */
+
         public void update(float xp, float yp, float xs, float ys, float ma)
         {
             base.update(xp, yp);
@@ -243,6 +299,7 @@ namespace TUIO
          *
          * @param	tcon	the TuioContainer to assign
          */
+
         public void update(TuioContainer tcon)
         {
             base.update(tcon.getX(), tcon.getY());
@@ -263,93 +320,41 @@ namespace TUIO
          *
          * @param	ttime	the TuioTime to assign
          */
-        public void remove(TuioTime ttime)
-        {
-            currentTime = ttime;
-            state = TUIO_REMOVED;
-        }
-
         /**
          * Returns the Session ID of this TuioContainer.
          * @return	the Session ID of this TuioContainer
          */
-        public long getSessionID()
-        {
-            return session_id;
-        }
-
         /**
          * Returns the X velocity of this TuioContainer.
          * @return	the X velocity of this TuioContainer
          */
-        public float getXSpeed()
-        {
-            return x_speed;
-        }
-
         /**
          * Returns the Y velocity of this TuioContainer.
          * @return	the Y velocity of this TuioContainer
          */
-        public float getYSpeed()
-        {
-            return y_speed;
-        }
-
         /**
          * Returns the position of this TuioContainer.
          * @return	the position of this TuioContainer
          */
-        public TuioPoint getPosition()
-        {
-            return new TuioPoint(xpos, ypos);
-        }
-
         /**
          * Returns the path of this TuioContainer.
          * @return	the path of this TuioContainer
          */
-        public List<TuioPoint> getPath()
-        {
-            return path;
-        }
-
         /**
          * Returns the motion speed of this TuioContainer.
          * @return	the motion speed of this TuioContainer
          */
-        public float getMotionSpeed()
-        {
-            return motion_speed;
-        }
-
         /**
          * Returns the motion acceleration of this TuioContainer.
          * @return	the motion acceleration of this TuioContainer
          */
-        public float getMotionAccel()
-        {
-            return motion_accel;
-        }
-
         /**
          * Returns the TUIO state of this TuioContainer.
          * @return	the TUIO state of this TuioContainer
          */
-        public int getTuioState()
-        {
-            return state;
-        }
-
         /**
          * Returns true of this TuioContainer is moving.
          * @return	true of this TuioContainer is moving
          */
-        public bool isMoving()
-        {
-            if ((state == TUIO_ACCELERATING) || (state == TUIO_DECELERATING)) return true;
-            else return false;
-        }
-
     }
-}
+}

+ 6 - 6
bbiwarg/TUIO/TUIO/TuioCursor.cs

@@ -19,20 +19,17 @@
 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
 
-using System;
-
 namespace TUIO
 {
-
     /**
      * The TuioCursor class encapsulates /tuio/2Dcur TUIO cursors.
      *
      * @author Martin Kaltenbrunner
      * @version 1.4
      */
+
     public class TuioCursor : TuioContainer
     {
-
         /**
          * The individual cursor ID number that is assigned to each TuioCursor.
          */
@@ -48,6 +45,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public TuioCursor(TuioTime ttime, long si, int ci, float xp, float yp)
             : base(ttime, si, xp, yp)
         {
@@ -63,6 +61,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public TuioCursor(long si, int ci, float xp, float yp)
             : base(si, xp, yp)
         {
@@ -75,6 +74,7 @@ namespace TUIO
          *
          * @param	tcur	the TuioCursor to assign
          */
+
         public TuioCursor(TuioCursor tcur)
             : base(tcur)
         {
@@ -85,10 +85,10 @@ namespace TUIO
          * Returns the Cursor ID of this TuioCursor.
          * @return	the Cursor ID of this TuioCursor
          */
+
         public int getCursorID()
         {
             return cursor_id;
         }
-
     }
-}
+}

+ 49 - 46
bbiwarg/TUIO/TUIO/TuioObject.cs

@@ -20,41 +20,38 @@
 */
 
 using System;
-using System.Collections.Generic;
 
 namespace TUIO
 {
-
     /**
      * The TuioObject class encapsulates /tuio/2Dobj TUIO objects.
      *
      * @author Martin Kaltenbrunner
      * @version 1.4
      */
+
     public class TuioObject : TuioContainer
     {
-
         /**
          * The individual symbol ID number that is assigned to each TuioObject.
          */
+        public static readonly int TUIO_ROTATING = 5;
+        protected float angle;
+        protected float rotation_accel;
+        protected float rotation_speed;
         protected int symbol_id;
         /**
          * The rotation angle value.
          */
-        protected float angle;
         /**
          * The rotation speed value.
          */
-        protected float rotation_speed;
         /**
          * The rotation acceleration value.
          */
-        protected float rotation_accel;
         /**
          * Defines the ROTATING state.
          */
-        public static readonly int TUIO_ROTATING = 5;
-
         /**
          * This constructor takes a TuioTime argument and assigns it along with the provided
          * Session ID, Symbol ID, X and Y coordinate and angle to the newly created TuioObject.
@@ -66,6 +63,7 @@ namespace TUIO
          * @param	yp	the Y coordinate to assign
          * @param	a	the angle to assign
          */
+
         public TuioObject(TuioTime ttime, long si, int sym, float xp, float yp, float a)
             : base(ttime, si, xp, yp)
         {
@@ -85,6 +83,7 @@ namespace TUIO
          * @param	yp	the Y coordinate to assign
          * @param	a	the angle to assign
          */
+
         public TuioObject(long si, int sym, float xp, float yp, float a)
             : base(si, xp, yp)
         {
@@ -100,6 +99,7 @@ namespace TUIO
          *
          * @param	tobj	the TuioObject to assign
          */
+
         public TuioObject(TuioObject tobj)
             : base(tobj)
         {
@@ -124,6 +124,43 @@ namespace TUIO
          * @param	ma	the motion acceleration to assign
          * @param	ra	the rotation acceleration to assign
          */
+
+        public float getAngle()
+        {
+            return angle;
+        }
+
+        public float getAngleDegrees()
+        {
+            return angle / (float)Math.PI * 180.0f;
+        }
+
+        public float getRotationAccel()
+        {
+            return rotation_accel;
+        }
+
+        public float getRotationSpeed()
+        {
+            return rotation_speed;
+        }
+
+        public int getSymbolID()
+        {
+            return symbol_id;
+        }
+
+        public new bool isMoving()
+        {
+            if ((state == TUIO_ACCELERATING) || (state == TUIO_DECELERATING) || (state == TUIO_ROTATING)) return true;
+            else return false;
+        }
+
+        public new void stop(TuioTime ttime)
+        {
+            update(ttime, this.xpos, this.ypos, this.angle);
+        }
+
         public void update(TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra)
         {
             base.update(ttime, xp, yp, xs, ys, ma);
@@ -147,6 +184,7 @@ namespace TUIO
          * @param	ma	the motion acceleration to assign
          * @param	ra	the rotation acceleration to assign
          */
+
         public void update(float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra)
         {
             base.update(xp, yp, xs, ys, ma);
@@ -166,6 +204,7 @@ namespace TUIO
          * @param	yp	the Y coordinate to assign
          * @param	a	the angle coordinate to assign
          */
+
         public void update(TuioTime ttime, float xp, float yp, float a)
         {
             TuioPoint lastPoint = path[path.Count - 1];
@@ -193,6 +232,7 @@ namespace TUIO
          *
          * @param	tobj	the TuioContainer to assign
          */
+
         public void update(TuioObject tobj)
         {
             base.update(tobj);
@@ -206,66 +246,29 @@ namespace TUIO
          * This method is used to calculate the speed and acceleration values of a
          * TuioObject with unchanged position and angle.
          */
-        public new void stop(TuioTime ttime)
-        {
-            update(ttime, this.xpos, this.ypos, this.angle);
-        }
-
         /**
          * Returns the symbol ID of this TuioObject.
          * @return	the symbol ID of this TuioObject
          */
-        public int getSymbolID()
-        {
-            return symbol_id;
-        }
-
         /**
          * Returns the rotation angle of this TuioObject.
          * @return	the rotation angle of this TuioObject
          */
-        public float getAngle()
-        {
-            return angle;
-        }
-
         /**
          * Returns the rotation angle in degrees of this TuioObject.
          * @return	the rotation angle in degrees of this TuioObject
          */
-        public float getAngleDegrees()
-        {
-            return angle / (float)Math.PI * 180.0f;
-        }
-
         /**
          * Returns the rotation speed of this TuioObject.
          * @return	the rotation speed of this TuioObject
          */
-        public float getRotationSpeed()
-        {
-            return rotation_speed;
-        }
-
         /**
          * Returns the rotation acceleration of this TuioObject.
          * @return	the rotation acceleration of this TuioObject
          */
-        public float getRotationAccel()
-        {
-            return rotation_accel;
-        }
-
         /**
          * Returns true of this TuioObject is moving.
          * @return	true of this TuioObject is moving
          */
-        public new bool isMoving()
-        {
-            if ((state == TUIO_ACCELERATING) || (state == TUIO_DECELERATING) || (state == TUIO_ROTATING)) return true;
-            else return false;
-        }
-
     }
-
-}
+}

+ 80 - 76
bbiwarg/TUIO/TUIO/TuioPoint.cs

@@ -23,7 +23,6 @@ using System;
 
 namespace TUIO
 {
-
     /**
      * The TuioPoint class on the one hand is a simple container and utility class to handle TUIO positions in general,
      * on the other hand the TuioPoint is the base class for the TuioCursor and TuioObject classes.
@@ -31,12 +30,14 @@ namespace TUIO
      * @author Martin Kaltenbrunner
      * @version 1.4
      */
+
     public class TuioPoint
     {
-
         /**
          * X coordinate, representated as a floating point value in a range of 0..1
          */
+        protected TuioTime currentTime;
+        protected TuioTime startTime;
         protected float xpos;
         /**
          * Y coordinate, representated as a floating point value in a range of 0..1
@@ -45,16 +46,14 @@ namespace TUIO
         /**
          * The time stamp of the last update represented as TuioTime (time since session start)
          */
-        protected TuioTime currentTime;
         /**
          * The creation time of this TuioPoint represented as TuioTime (time since session start)
          */
-        protected TuioTime startTime;
-
         /**
          * The default constructor takes no arguments and sets
          * its coordinate attributes to zero and its time stamp to the current session time.
          */
+
         public TuioPoint()
         {
             xpos = 0.0f;
@@ -70,6 +69,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public TuioPoint(float xp, float yp)
         {
             xpos = xp;
@@ -84,6 +84,7 @@ namespace TUIO
          *
          * @param	tpoint	the TuioPoint to assign
          */
+
         public TuioPoint(TuioPoint tpoint)
         {
             xpos = tpoint.getX();
@@ -100,6 +101,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public TuioPoint(TuioTime ttime, float xp, float yp)
         {
             xpos = xp;
@@ -114,6 +116,76 @@ namespace TUIO
          *
          * @param	tpoint	the TuioPoint to assign
          */
+
+        public float getAngle(float xp, float yp)
+        {
+            float side = xp - xpos;
+            float height = yp - ypos;
+            float distance = getDistance(xp, yp);
+
+            float angle = (float)(Math.Asin(side / distance) + Math.PI / 2);
+            if (height < 0) angle = 2.0f * (float)Math.PI - angle;
+
+            return angle;
+        }
+
+        public float getAngle(TuioPoint tpoint)
+        {
+            return getAngle(tpoint.getX(), tpoint.getY());
+        }
+
+        public float getAngleDegrees(float xp, float yp)
+        {
+            return (getAngle(xp, yp) / (float)Math.PI) * 180.0f;
+        }
+
+        public float getAngleDegrees(TuioPoint tpoint)
+        {
+            return (getAngle(tpoint) / (float)Math.PI) * 180.0f;
+        }
+
+        public float getDistance(float x, float y)
+        {
+            float dx = xpos - x;
+            float dy = ypos - y;
+            return (float)Math.Sqrt(dx * dx + dy * dy);
+        }
+
+        public float getDistance(TuioPoint tpoint)
+        {
+            return getDistance(tpoint.getX(), tpoint.getY());
+        }
+
+        public int getScreenX(int width)
+        {
+            return (int)Math.Round(xpos * width);
+        }
+
+        public int getScreenY(int height)
+        {
+            return (int)Math.Round(ypos * height);
+        }
+
+        public TuioTime getStartTime()
+        {
+            return new TuioTime(startTime);
+        }
+
+        public TuioTime getTuioTime()
+        {
+            return new TuioTime(currentTime);
+        }
+
+        public float getX()
+        {
+            return xpos;
+        }
+
+        public float getY()
+        {
+            return ypos;
+        }
+
         public void update(TuioPoint tpoint)
         {
             xpos = tpoint.getX();
@@ -127,6 +199,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public void update(float xp, float yp)
         {
             xpos = xp;
@@ -141,6 +214,7 @@ namespace TUIO
          * @param	xp	the X coordinate to assign
          * @param	yp	the Y coordinate to assign
          */
+
         public void update(TuioTime ttime, float xp, float yp)
         {
             xpos = xp;
@@ -152,20 +226,10 @@ namespace TUIO
          * Returns the X coordinate of this TuioPoint.
          * @return	the X coordinate of this TuioPoint
          */
-        public float getX()
-        {
-            return xpos;
-        }
-
         /**
          * Returns the Y coordinate of this TuioPoint.
          * @return	the Y coordinate of this TuioPoint
          */
-        public float getY()
-        {
-            return ypos;
-        }
-
         /**
          * Returns the distance to the provided coordinates
          *
@@ -173,24 +237,12 @@ namespace TUIO
          * @param	yp	the Y coordinate of the distant point
          * @return	the distance to the provided coordinates
          */
-        public float getDistance(float x, float y)
-        {
-            float dx = xpos - x;
-            float dy = ypos - y;
-            return (float)Math.Sqrt(dx * dx + dy * dy);
-        }
-
         /**
          * Returns the distance to the provided TuioPoint
          *
          * @param	tpoint	the distant TuioPoint
          * @return	the distance to the provided TuioPoint
          */
-        public float getDistance(TuioPoint tpoint)
-        {
-            return getDistance(tpoint.getX(), tpoint.getY());
-        }
-
         /**
          * Returns the angle to the provided coordinates
          *
@@ -198,30 +250,12 @@ namespace TUIO
          * @param	yp	the Y coordinate of the distant point
          * @return	the angle to the provided coordinates
          */
-        public float getAngle(float xp, float yp)
-        {
-
-            float side = xp - xpos;
-            float height = yp - ypos;
-            float distance = getDistance(xp, yp);
-
-            float angle = (float)(Math.Asin(side / distance) + Math.PI / 2);
-            if (height < 0) angle = 2.0f * (float)Math.PI - angle;
-
-            return angle;
-        }
-
         /**
          * Returns the angle to the provided TuioPoint
          *
          * @param	tpoint	the distant TuioPoint
          * @return	the angle to the provided TuioPoint
          */
-        public float getAngle(TuioPoint tpoint)
-        {
-            return getAngle(tpoint.getX(), tpoint.getY());
-        }
-
         /**
          * Returns the angle in degrees to the provided coordinates
          *
@@ -229,63 +263,33 @@ namespace TUIO
          * @param	yp	the Y coordinate of the distant point
          * @return	the angle in degrees to the provided TuioPoint
          */
-        public float getAngleDegrees(float xp, float yp)
-        {
-            return (getAngle(xp, yp) / (float)Math.PI) * 180.0f;
-        }
-
         /**
          * Returns the angle in degrees to the provided TuioPoint
          *
          * @param	tpoint	the distant TuioPoint
          * @return	the angle in degrees to the provided TuioPoint
          */
-        public float getAngleDegrees(TuioPoint tpoint)
-        {
-            return (getAngle(tpoint) / (float)Math.PI) * 180.0f;
-        }
-
         /**
          * Returns the X coordinate in pixels relative to the provided screen width.
          *
          * @param	width	the screen width
          * @return	the X coordinate of this TuioPoint in pixels relative to the provided screen width
          */
-        public int getScreenX(int width)
-        {
-            return (int)Math.Round(xpos * width);
-        }
-
         /**
          * Returns the Y coordinate in pixels relative to the provided screen height.
          *
          * @param	height	the screen height
          * @return	the Y coordinate of this TuioPoint in pixels relative to the provided screen height
          */
-        public int getScreenY(int height)
-        {
-            return (int)Math.Round(ypos * height);
-        }
-
         /**
          * Returns the time stamp of this TuioPoint as TuioTime.
          *
          * @return	the time stamp of this TuioPoint as TuioTime
          */
-        public TuioTime getTuioTime()
-        {
-            return new TuioTime(currentTime);
-        }
-
         /**
          * Returns the start time of this TuioPoint as TuioTime.
          *
          * @return	the start time of this TuioPoint as TuioTime
          */
-        public TuioTime getStartTime()
-        {
-            return new TuioTime(startTime);
-        }
-
     }
-}
+}

+ 110 - 116
bbiwarg/TUIO/TUIO/TuioServer.cs

@@ -1,37 +1,42 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-//using Ventuz.OSC;
+//using Ventuz.OSC;
 using OSC.NET;
-//using System.Runtime.InteropServices;
+using System;
+using System.Collections.Generic;
 
-using bbiwarg.Utility;
+//using System.Runtime.InteropServices;
 
 namespace TUIO
 {
     /// <summary>
     /// Tuio server class to send tuio cursors and objects to tuio clients.
     /// </summary>
-    class TuioServer
+    internal class TuioServer
     {
         /// <summary>
         /// the maximum packet size
         /// </summary>
-        const int MAX_PACKET_SIZE = 65535 - 8;
+        private const int MAX_PACKET_SIZE = 65535 - 8;
 
+        /// <summary>
+        /// current tuio time
+        /// </summary>
+        private TuioTime currentFrameTime;
 
         /// <summary>
-        /// transmitter to send packages over udp
+        /// list of generated cursors
         /// </summary>
-        private OSCTransmitter transmitter = null;
+        private List<TuioCursor> cursorList;
 
         /// <summary>
         /// server ip address
         /// </summary>
         private String host = "127.0.0.1";
 
+        /// <summary>
+        /// list of all generated objects
+        /// </summary>
+        private List<TuioObject> objectList;
+
         /// <summary>
         /// server port
         /// </summary>
@@ -43,37 +48,27 @@ namespace TUIO
         private long sessionID = 0;
 
         /// <summary>
-        /// current tuio time
-        /// </summary>
-        private TuioTime currentFrameTime;
-
-
-        /// <summary>
-        /// list of generated cursors
+        /// transmitter to send packages over udp
         /// </summary>
-        private List<TuioCursor> cursorList;
+        private OSCTransmitter transmitter = null;
 
         /// <summary>
         /// list of cursors updated in the current frame
         /// </summary>
         private List<TuioCursor> updatedCursorList;
 
-
-        /// <summary>
-        /// list of all generated objects
-        /// </summary>
-        private List<TuioObject> objectList;
-
         /// <summary>
         /// list of objects updated in the current frame
         /// </summary>
         private List<TuioObject> updatedObjectList;
 
-
         /// <summary>
         /// Creates a tuio server with default ip and port.
         /// </summary>
-        public TuioServer() { init(); }
+        public TuioServer()
+        {
+            init();
+        }
 
         /// <summary>
         /// Creates a tuio server with default ip.
@@ -97,25 +92,6 @@ namespace TUIO
             init();
         }
 
-        /// <summary>
-        /// Initializes the server, cursors and objects.
-        /// </summary>
-        private void init()
-        {
-            TuioTime.initSession();
-            cursorList = new List<TuioCursor>();
-            objectList = new List<TuioObject>();
-            transmitter = new OSCTransmitter(host, port);
-        }
-
-        /// <summary>
-        /// Closes the transmission.
-        /// </summary>
-        public void close()
-        {
-            transmitter.Close();
-        }
-
         /// <summary>
         /// Adds and returns a tuio cursor.
         /// </summary>
@@ -132,28 +108,6 @@ namespace TUIO
             return tcur;
         }
 
-        /// <summary>
-        /// Updates a tui cursor.
-        /// </summary>
-        /// <param name="tcur">the cursor to update</param>
-        /// <param name="xp">new x position</param>
-        /// <param name="yp">new y position</param>
-        public void updateTuioCursor(TuioCursor tcur, float xp, float yp)
-        {
-            tcur.update(currentFrameTime, xp, yp);
-            if (!updatedCursorList.Contains(tcur))
-                updatedCursorList.Add(tcur);
-        }
-
-        /// <summary>
-        /// Removes a tuio cursor.
-        /// </summary>
-        /// <param name="tcur">the cursor to remove</param>
-        public void removeTuioCursor(TuioCursor tcur)
-        {
-            cursorList.Remove(tcur);
-        }
-
         /// <summary>
         /// Adds and returns tuio object.
         /// </summary>
@@ -172,25 +126,19 @@ namespace TUIO
         }
 
         /// <summary>
-        /// Updates a tuio object.
+        /// Closes the transmission.
         /// </summary>
-        /// <param name="tobj">the object to update</param>
-        /// <param name="xp">new x position</param>
-        /// <param name="yp">new y position</param>
-        public void updateTuioObject(TuioObject tobj, float xp, float yp)
+        public void close()
         {
-            tobj.update(currentFrameTime, xp, yp);
-            if (!updatedObjectList.Contains(tobj))
-                updatedObjectList.Add(tobj);
+            transmitter.Close();
         }
 
         /// <summary>
-        /// Removes a tuio object.
+        /// Sends cursors and objects which were updated in the current frame.
         /// </summary>
-        /// <param name="tobj">the object to remove</param>
-        public void removeTuioObject(TuioObject tobj)
+        public void commitFrame()
         {
-            objectList.Remove(tobj);
+            sendMessage(updatedCursorList, updatedObjectList);
         }
 
         /// <summary>
@@ -204,11 +152,21 @@ namespace TUIO
         }
 
         /// <summary>
-        /// Sends cursors and objects which were updated in the current frame.
+        /// Removes a tuio cursor.
         /// </summary>
-        public void commitFrame()
+        /// <param name="tcur">the cursor to remove</param>
+        public void removeTuioCursor(TuioCursor tcur)
         {
-            sendMessage(updatedCursorList, updatedObjectList);
+            cursorList.Remove(tcur);
+        }
+
+        /// <summary>
+        /// Removes a tuio object.
+        /// </summary>
+        /// <param name="tobj">the object to remove</param>
+        public void removeTuioObject(TuioObject tobj)
+        {
+            objectList.Remove(tobj);
         }
 
         /// <summary>
@@ -219,6 +177,73 @@ namespace TUIO
             sendMessage(cursorList, objectList);
         }
 
+        /// <summary>
+        /// Updates a tui cursor.
+        /// </summary>
+        /// <param name="tcur">the cursor to update</param>
+        /// <param name="xp">new x position</param>
+        /// <param name="yp">new y position</param>
+        public void updateTuioCursor(TuioCursor tcur, float xp, float yp)
+        {
+            tcur.update(currentFrameTime, xp, yp);
+            if (!updatedCursorList.Contains(tcur))
+                updatedCursorList.Add(tcur);
+        }
+
+        /// <summary>
+        /// Updates a tuio object.
+        /// </summary>
+        /// <param name="tobj">the object to update</param>
+        /// <param name="xp">new x position</param>
+        /// <param name="yp">new y position</param>
+        public void updateTuioObject(TuioObject tobj, float xp, float yp)
+        {
+            tobj.update(currentFrameTime, xp, yp);
+            if (!updatedObjectList.Contains(tobj))
+                updatedObjectList.Add(tobj);
+        }
+
+        /// <summary>
+        /// Adds a tuio cursor alive message to a packet.
+        /// </summary>
+        /// <param name="packet">packet to add the message to</param>
+        private void addAliveCursorMessagesToBundle(OSCBundle packet)
+        {
+            OSCMessage mssg = new OSCMessage("/tuio/2Dcur");
+            mssg.Append("alive");
+            for (int i = 0; i < cursorList.Count; i++)
+            {
+                mssg.Append((Int32)cursorList[i].getSessionID());
+            }
+            packet.Append(mssg);
+        }
+
+        /// <summary>
+        /// Adds a tuio object alive message to a packet.
+        /// </summary>
+        /// <param name="packet">packet to add the message to</param>
+        private void addAliveObjectMessagesToBundle(OSCBundle packet)
+        {
+            OSCMessage mssg = new OSCMessage("/tuio/2Dobj");
+            mssg.Append("alive");
+            for (int i = 0; i < objectList.Count; i++)
+            {
+                mssg.Append((Int32)objectList[i].getSessionID());
+            }
+            packet.Append(mssg);
+        }
+
+        /// <summary>
+        /// Initializes the server, cursors and objects.
+        /// </summary>
+        private void init()
+        {
+            TuioTime.initSession();
+            cursorList = new List<TuioCursor>();
+            objectList = new List<TuioObject>();
+            transmitter = new OSCTransmitter(host, port);
+        }
+
         /// <summary>
         /// Sends cursors and objects.
         /// </summary>
@@ -279,38 +304,7 @@ namespace TUIO
             currentMessage.Append(-1); //sequence_id; actually -1 stands for redundant bundle
             packet.Append(currentMessage);
 
-
             transmitter.Send(packet);
         }
-
-        /// <summary>
-        /// Adds a tuio cursor alive message to a packet.
-        /// </summary>
-        /// <param name="packet">packet to add the message to</param>
-        private void addAliveCursorMessagesToBundle(OSCBundle packet)
-        {
-            OSCMessage mssg = new OSCMessage("/tuio/2Dcur");
-            mssg.Append("alive");
-            for (int i = 0; i < cursorList.Count; i++)
-            {
-                mssg.Append((Int32)cursorList[i].getSessionID());
-            }
-            packet.Append(mssg);
-        }
-
-        /// <summary>
-        /// Adds a tuio object alive message to a packet.
-        /// </summary>
-        /// <param name="packet">packet to add the message to</param>
-        private void addAliveObjectMessagesToBundle(OSCBundle packet)
-        {
-            OSCMessage mssg = new OSCMessage("/tuio/2Dobj");
-            mssg.Append("alive");
-            for (int i = 0; i < objectList.Count; i++)
-            {
-                mssg.Append((Int32)objectList[i].getSessionID());
-            }
-            packet.Append(mssg);
-        }
     }
-}
+}

+ 78 - 72
bbiwarg/TUIO/TUIO/TuioTime.cs

@@ -23,7 +23,6 @@ using System;
 
 namespace TUIO
 {
-
     /**
      * The TuioTime class is a simple structure that is used to reprent the time that has elapsed since the session start.
      * The time is internally represented as seconds and fractions of microseconds which should be more than sufficient for gesture related timing requirements.
@@ -34,30 +33,30 @@ namespace TUIO
      * @author Martin Kaltenbrunner
      * @version 1.4
      */
+
     public class TuioTime
     {
-
         /**
          * the time since session start in seconds
          */
+        private static long start_micro_seconds = 0;
+        private static long start_seconds = 0;
+        private long micro_seconds = 0;
         private long seconds = 0;
         /**
          * time fraction in microseconds
          */
-        private long micro_seconds = 0;
         /**
          * the session start time in seconds
          */
-        private static long start_seconds = 0;
         /**
          * start time fraction in microseconds
          */
-        private static long start_micro_seconds = 0;
-
         /**
          * The default constructor takes no arguments and sets
          * the Seconds and Microseconds attributes of the newly created TuioTime both to zero.
          */
+
         public TuioTime()
         {
             this.seconds = 0;
@@ -70,6 +69,7 @@ namespace TUIO
          *
          * @param msec the total time in Millseconds
          */
+
         public TuioTime(long msec)
         {
             this.seconds = msec / 1000;
@@ -83,6 +83,7 @@ namespace TUIO
          * @param sec the total time in seconds
          * @param usec	the microseconds time component
          */
+
         public TuioTime(long sec, long usec)
         {
             this.seconds = sec;
@@ -95,6 +96,7 @@ namespace TUIO
          *
          * @param ttime the TuioTime used to copy
          */
+
         public TuioTime(TuioTime ttime)
         {
             this.seconds = ttime.getSeconds();
@@ -108,6 +110,58 @@ namespace TUIO
          * @param us	the total time to add in Microseconds
          * @return the sum of this TuioTime with the provided argument in microseconds
         */
+
+        public static TuioTime getSessionTime()
+        {
+            return getSystemTime() - getStartTime();
+        }
+
+        public static TuioTime getStartTime()
+        {
+            return new TuioTime(start_seconds, start_micro_seconds);
+        }
+
+        public static TuioTime getSystemTime()
+        {
+            long usec = DateTime.Now.Ticks / 10;
+            return new TuioTime(usec / 1000000, usec % 1000000);
+        }
+
+        public static void initSession()
+        {
+            TuioTime startTime = getSystemTime();
+            start_seconds = startTime.getSeconds();
+            start_micro_seconds = startTime.getMicroseconds();
+        }
+
+        public static TuioTime operator -(TuioTime btime, long us)
+        {
+            long sec = btime.getSeconds() - us / 1000000;
+            long usec = btime.getMicroseconds() - us % 1000000;
+
+            if (usec < 0)
+            {
+                usec += 1000000;
+                sec--;
+            }
+
+            return new TuioTime(sec, usec);
+        }
+
+        public static TuioTime operator -(TuioTime btime, TuioTime ttime)
+        {
+            long sec = btime.getSeconds() - ttime.getSeconds();
+            long usec = btime.getMicroseconds() - ttime.getMicroseconds();
+
+            if (usec < 0)
+            {
+                usec += 1000000;
+                sec--;
+            }
+
+            return new TuioTime(sec, usec);
+        }
+
         public static TuioTime operator +(TuioTime atime, long us)
         {
             long sec = atime.getSeconds() + us / 1000000;
@@ -122,6 +176,7 @@ namespace TUIO
          * @param ttime	the TuioTime to add
          * @return the sum of this TuioTime with the provided TuioTime argument
          */
+
         public static TuioTime operator +(TuioTime btime, TuioTime ttime)
         {
             long sec = btime.getSeconds() + ttime.getSeconds();
@@ -138,20 +193,6 @@ namespace TUIO
          * @param us	the total time to subtract in Microseconds
          * @return the subtraction result of this TuioTime minus the provided time in Microseconds
          */
-        public static TuioTime operator -(TuioTime btime, long us)
-        {
-            long sec = btime.getSeconds() - us / 1000000;
-            long usec = btime.getMicroseconds() - us % 1000000;
-
-            if (usec < 0)
-            {
-                usec += 1000000;
-                sec--;
-            }
-
-            return new TuioTime(sec, usec);
-        }
-
         /**
          * Subtracts the provided TuioTime from the private Seconds and Microseconds attributes.
          *
@@ -159,26 +200,13 @@ namespace TUIO
          * @param ttime	the TuioTime to subtract
          * @return the subtraction result of this TuioTime minus the provided TuioTime
          */
-        public static TuioTime operator -(TuioTime btime, TuioTime ttime)
-        {
-            long sec = btime.getSeconds() - ttime.getSeconds();
-            long usec = btime.getMicroseconds() - ttime.getMicroseconds();
-
-            if (usec < 0)
-            {
-                usec += 1000000;
-                sec--;
-            }
-
-            return new TuioTime(sec, usec);
-        }
-
         /**
          * Takes a TuioTime argument and compares the provided TuioTime to the private Seconds and Microseconds attributes.
          *
          * @param ttime	the TuioTime to compare
          * @return true if the two TuioTime have equal Seconds and Microseconds attributes
          */
+
         public bool Equals(TuioTime ttime)
         {
             if ((seconds == ttime.getSeconds()) && (micro_seconds == ttime.getMicroseconds())) return true;
@@ -188,6 +216,22 @@ namespace TUIO
         /**
          * Resets the seconds and micro_seconds attributes to zero.
          */
+
+        public long getMicroseconds()
+        {
+            return micro_seconds;
+        }
+
+        public long getSeconds()
+        {
+            return seconds;
+        }
+
+        public long getTotalMilliseconds()
+        {
+            return seconds * 1000 + micro_seconds / 1000;
+        }
+
         public void reset()
         {
             seconds = 0;
@@ -198,67 +242,29 @@ namespace TUIO
          * Returns the TuioTime Seconds component.
          * @return the TuioTime Seconds component
          */
-        public long getSeconds()
-        {
-            return seconds;
-        }
-
         /**
          * Returns the TuioTime Microseconds component.
          * @return the TuioTime Microseconds component
          */
-        public long getMicroseconds()
-        {
-            return micro_seconds;
-        }
-
         /**
          * Returns the total TuioTime in Milliseconds.
          * @return the total TuioTime in Milliseconds
          */
-        public long getTotalMilliseconds()
-        {
-            return seconds * 1000 + micro_seconds / 1000;
-        }
-
         /**
          * This static method globally resets the TUIO session time.
          */
-        public static void initSession()
-        {
-            TuioTime startTime = getSystemTime();
-            start_seconds = startTime.getSeconds();
-            start_micro_seconds = startTime.getMicroseconds();
-        }
-
         /**
          * Returns the present TuioTime representing the time since session start.
          * @return the present TuioTime representing the time since session start
          */
-        public static TuioTime getSessionTime()
-        {
-            return getSystemTime() - getStartTime();
-        }
-
         /**
          * Returns the absolut TuioTime representing the session start.
          * @return the absolut TuioTime representing the session start
          */
-        public static TuioTime getStartTime()
-        {
-            return new TuioTime(start_seconds, start_micro_seconds);
-        }
-
         /**
          * Returns the absolut TuioTime representing the current system time.
          * @return the absolut TuioTime representing the current system time
          */
-        public static TuioTime getSystemTime()
-        {
-            long usec = DateTime.Now.Ticks / 10;
-            return new TuioTime(usec / 1000000, usec % 1000000);
-        }
-
 
         public override String ToString()
         {

+ 45 - 46
bbiwarg/TUIO/TuioCommunicator.cs

@@ -1,14 +1,12 @@
-using System;
+using bbiwarg.Input.InputHandling;
+using bbiwarg.Recognition.PalmRecognition;
+using bbiwarg.Recognition.TouchRecognition;
+using bbiwarg.Utility;
+using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Net;
 using System.Net.Sockets;
-using bbiwarg.Recognition.TouchRecognition;
-using bbiwarg.Recognition.PalmRecognition;
-using bbiwarg.Utility;
-using bbiwarg.Input.InputHandling;
 using TUIO;
 
 namespace bbiwarg.TUIO
@@ -16,7 +14,7 @@ namespace bbiwarg.TUIO
     /// <summary>
     /// TuioCommunicator sends generated touch events and palm grid coordinates to tuio clients using a <see cref="TuioServer"/>.
     /// </summary>
-    class TuioCommunicator
+    internal class TuioCommunicator
     {
         /// <summary>
         /// the tuio server
@@ -33,7 +31,6 @@ namespace bbiwarg.TUIO
         /// </summary>
         private Dictionary<int, List<TuioObject>> tobjects;
 
-
         /// <summary>
         /// Constructs a TuioCommunicator.
         /// </summary>
@@ -46,6 +43,42 @@ namespace bbiwarg.TUIO
             tobjects = new Dictionary<int, List<TuioObject>>();
         }
 
+        /// <summary>
+        /// Tries to parse an ip address string.
+        /// </summary>
+        /// <param name="ipIn">the ip address string to parse</param>
+        /// <param name="ipOut">out parameter for the ip address in *.*.*.* format if ipIn is valid and null otherwise</param>
+        /// <returns>true iff ipIn is a valid ip address</returns>
+        public static bool tryParseIPAddress(String ipIn, out String ipOut)
+        {
+            IPAddress ipAddress;
+            bool result = (IPAddress.TryParse(ipIn, out ipAddress) && ipAddress.AddressFamily == AddressFamily.InterNetwork);
+            if (result)
+                ipOut = ipAddress.ToString();
+            else
+                ipOut = null;
+            return result;
+        }
+
+        /// <summary>
+        /// Tries to parse a port string.
+        /// </summary>
+        /// <param name="portIn">the port string to parse</param>
+        /// <param name="portOut">out parameter for the port as an Int16 if portIn is valid and undefined otherwise</param>
+        /// <returns>true iff portIn is a valid port</returns>
+        public static bool tryParsePort(String portIn, out Int16 portOut)
+        {
+            return Int16.TryParse(portIn, out portOut);
+        }
+
+        /// <summary>
+        /// Closes the server.
+        /// </summary>
+        public void close()
+        {
+            server.close();
+        }
+
         /// <summary>
         /// Handles the event that a new frame is finished processing by updating the cursors and objects and sending them.
         /// </summary>
@@ -68,9 +101,11 @@ namespace bbiwarg.TUIO
                             TuioCursor tcur = server.addTuioCursor(te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
                             tcursors.Add(te.Touch.TrackID, tcur);
                             break;
+
                         case TouchEventType.Move:
                             server.updateTuioCursor(tcursors[te.Touch.TrackID], te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
                             break;
+
                         case TouchEventType.Up:
                             server.removeTuioCursor(tcursors[te.Touch.TrackID]);
                             tcursors.Remove(te.Touch.TrackID);
@@ -118,14 +153,6 @@ namespace bbiwarg.TUIO
             server.commitFrame();
         }
 
-        /// <summary>
-        /// Closes the server.
-        /// </summary>
-        public void close()
-        {
-            server.close();
-        }
-
         /// <summary>
         /// Resets the server by removing all cursors and objects.
         /// </summary>
@@ -142,33 +169,5 @@ namespace bbiwarg.TUIO
 
             tobjects.Clear();
         }
-
-        /// <summary>
-        /// Tries to parse an ip address string.
-        /// </summary>
-        /// <param name="ipIn">the ip address string to parse</param>
-        /// <param name="ipOut">out parameter for the ip address in *.*.*.* format if ipIn is valid and null otherwise</param>
-        /// <returns>true iff ipIn is a valid ip address</returns>
-        public static bool tryParseIPAddress(String ipIn, out String ipOut)
-        {
-            IPAddress ipAddress;
-            bool result = (IPAddress.TryParse(ipIn, out ipAddress) && ipAddress.AddressFamily == AddressFamily.InterNetwork);
-            if (result)
-                ipOut = ipAddress.ToString();
-            else
-                ipOut = null;
-            return result;
-        }
-
-        /// <summary>
-        /// Tries to parse a port string.
-        /// </summary>
-        /// <param name="portIn">the port string to parse</param>
-        /// <param name="portOut">out parameter for the port as an Int16 if portIn is valid and undefined otherwise</param>
-        /// <returns>true iff portIn is a valid port</returns>
-        public static bool tryParsePort(String portIn, out Int16 portOut)
-        {
-            return Int16.TryParse(portIn, out portOut);
-        }
     }
-}
+}

+ 26 - 32
bbiwarg/Utility/ConvexityDefect.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.FingerRecognition;
+using bbiwarg.Recognition.FingerRecognition;
 using Emgu.CV.Structure;
 
 namespace bbiwarg.Utility
@@ -14,14 +9,9 @@ namespace bbiwarg.Utility
     public class ConvexityDefect
     {
         /// <summary>
-        /// the point of start and end point which is nearer to the depth point
-        /// </summary>
-        public Vector2D OuterShort { get; private set; }
-
-        /// <summary>
-        /// the point of start and end point which is farther away from the depth point
+        /// distance from OuterLineSegment to Inner
         /// </summary>
-        public Vector2D OuterLong { get; private set; }
+        public float Depth { get; private set; }
 
         /// <summary>
         /// the depth point
@@ -29,25 +19,29 @@ namespace bbiwarg.Utility
         public Vector2D Inner { get; private set; }
 
         /// <summary>
-        /// vector from Inner to OuterShort
+        /// line segment from start to end point
         /// </summary>
-        public Vector2D VectorShort { get; private set; }
+        public LineSegment2D OuterLineSegment { get; private set; }
 
         /// <summary>
-        /// vector from Inner to OuterLong
+        /// the point of start and end point which is farther away from the depth point
         /// </summary>
-        public Vector2D VectorLong { get; private set; }
+        public Vector2D OuterLong { get; private set; }
 
         /// <summary>
-        /// line segment from start to end point
+        /// the point of start and end point which is nearer to the depth point
         /// </summary>
-        public LineSegment2D OuterLineSegment { get; private set; }
+        public Vector2D OuterShort { get; private set; }
 
         /// <summary>
-        /// distance from OuterLineSegment to Inner
+        /// vector from Inner to OuterLong
         /// </summary>
-        public float Depth { get; private set; }
+        public Vector2D VectorLong { get; private set; }
 
+        /// <summary>
+        /// vector from Inner to OuterShort
+        /// </summary>
+        public Vector2D VectorShort { get; private set; }
 
         /// <summary>
         /// Constructs a ConvexityDefect.
@@ -76,6 +70,16 @@ namespace bbiwarg.Utility
             Depth = OuterLineSegment.getDistanceTo(Inner);
         }
 
+        /// <summary>
+        /// Tests if this defect is caused by a finger.
+        /// </summary>
+        /// <param name="finger">the finger maybe causing the defect</param>
+        /// <returns>true iff this defect is caused by finger</returns>
+        public bool isCausedByFinger(Finger finger)
+        {
+            return (OuterLineSegment.intersectsWith(finger.LineSegment));
+        }
+
         /// <summary>
         /// Tests if this defect could be the defect near the thumb.
         /// </summary>
@@ -93,15 +97,5 @@ namespace bbiwarg.Utility
                     thumbShortLengthRatio <= Parameters.HandThumbDefectMaxThumbShortLengthRatio && thumbShortLengthRatio >= Parameters.HandThumbDefectMinThumbShortLengthRatio &&
                     shortLongLengthRatio <= Parameters.HandThumbDefectMaxShortLongLengthRatio && shortLongLengthRatio >= Parameters.HandThumbDefectMinShortLongLengthRatio);
         }
-
-        /// <summary>
-        /// Tests if this defect is caused by a finger.
-        /// </summary>
-        /// <param name="finger">the finger maybe causing the defect</param>
-        /// <returns>true iff this defect is caused by finger</returns>
-        public bool isCausedByFinger(Finger finger)
-        {
-            return (OuterLineSegment.intersectsWith(finger.LineSegment));
-        }
     }
-}
+}

+ 19 - 24
bbiwarg/Utility/CoordinateConverter.cs

@@ -1,8 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace bbiwarg.Utility
 {
@@ -11,31 +7,30 @@ namespace bbiwarg.Utility
     /// </summary>
     public class CoordinateConverter
     {
-        /// <summary>
-        /// size of the image the coordinates are from
-        /// </summary>
-        private ImageSize imageSize;
-
         /// <summary>
         /// the horizontal field of view angle
         /// </summary>
-        private float hfov;
+        private float fieldOfViewHorizontal;
 
         /// <summary>
         /// the vertical field of view angle
         /// </summary>
-        private float vfov;
+        private float fieldOfViewVertical;
 
         /// <summary>
-        /// tangens of hfov / 2
+        /// size of the image the coordinates are from
         /// </summary>
-        private float hRatio;
+        private ImageSize imageSize;
 
         /// <summary>
-        /// tanges of vfov / 2
+        /// tangens of fieldOfViewHorizontal / 2
         /// </summary>
-        private float vRatio;
+        private float relativeRatioHorizontal;
 
+        /// <summary>
+        /// tanges of fieldOfViewVertical / 2
+        /// </summary>
+        private float relativeRatioVertical;
 
         /// <summary>
         /// Constructs a CoordinateConverter.
@@ -46,11 +41,11 @@ namespace bbiwarg.Utility
         public CoordinateConverter(ImageSize imageSize, float hfov, float vfov)
         {
             this.imageSize = imageSize;
-            this.hfov = hfov;
-            this.vfov = vfov;
+            this.fieldOfViewHorizontal = hfov;
+            this.fieldOfViewVertical = vfov;
 
-            hRatio = (float)Math.Tan(hfov / 2);
-            vRatio = (float)Math.Tan(vfov / 2);
+            relativeRatioHorizontal = (float)Math.Tan(hfov / 2);
+            relativeRatioVertical = (float)Math.Tan(vfov / 2);
         }
 
         /// <summary>
@@ -76,8 +71,8 @@ namespace bbiwarg.Utility
             float deltaX = 2 * ((x / imageSize.Width) - 0.5f);
             float deltaY = -2 * ((y / imageSize.Height) - 0.5f);
 
-            float tanX = deltaX * hRatio;
-            float tanY = deltaY * vRatio;
+            float tanX = deltaX * relativeRatioHorizontal;
+            float tanY = deltaY * relativeRatioVertical;
 
             float a = depth * depth;
             float b = (float)(Math.Pow(tanX, 2) + Math.Pow(tanY, 2));
@@ -97,12 +92,12 @@ namespace bbiwarg.Utility
         /// <returns>2d length of the linesegment</returns>
         public float convertLength3Dto2D(float length, float depth)
         {
-            float fullLengthX = (float)(2 * Math.Cos(hfov / 2) * depth);
-            float fullLengthY = (float)(2 * Math.Cos(vfov / 2) * depth);
+            float fullLengthX = (float)(2 * Math.Cos(fieldOfViewHorizontal / 2) * depth);
+            float fullLengthY = (float)(2 * Math.Cos(fieldOfViewVertical / 2) * depth);
             float fullLengthDiagonal = (float)Math.Sqrt(Math.Pow(fullLengthX, 2) + Math.Pow(fullLengthY, 2));
 
             float ratio = length / fullLengthDiagonal;
             return ratio * imageSize.DiagonalLength;
         }
     }
-}
+}

+ 8 - 16
bbiwarg/Utility/ImageSize.cs

@@ -1,11 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Drawing;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bbiwarg.Utility
+namespace bbiwarg.Utility
 {
     /// <summary>
     /// Manages the size of a image.
@@ -13,9 +6,9 @@ namespace bbiwarg.Utility
     public class ImageSize
     {
         /// <summary>
-        /// image width
+        /// the length of the longer image diagonal
         /// </summary>
-        public int Width { get; private set; }
+        public float DiagonalLength { get { return MaxPixel.Length; } }
 
         /// <summary>
         /// image height
@@ -27,16 +20,15 @@ namespace bbiwarg.Utility
         /// </summary>
         public Vector2D MaxPixel { get; private set; }
 
-        /// <summary>
-        /// the length of the longer image diagonal
-        /// </summary>
-        public float DiagonalLength { get { return MaxPixel.Length; } }
-
         /// <summary>
         /// number of pixels in the image
         /// </summary>
         public int NumPixels { get { return Width * Height; } }
 
+        /// <summary>
+        /// image width
+        /// </summary>
+        public int Width { get; private set; }
 
         /// <summary>
         /// Constructs a ImageSize.
@@ -70,4 +62,4 @@ namespace bbiwarg.Utility
             return new Vector2D(absolutePoint.X / Width, absolutePoint.Y / Height);
         }
     }
-}
+}

+ 41 - 50
bbiwarg/Utility/Kalman2DPositionFilter.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using Emgu.CV;
+using Emgu.CV;
 using Emgu.CV.Structure;
 
 namespace bbiwarg.Utility
@@ -12,8 +6,13 @@ namespace bbiwarg.Utility
     /// <summary>
     /// Filter used to smooth a series of 2d positions.
     /// </summary>
-    class Kalman2DPositionFilter
+    internal class Kalman2DPositionFilter
     {
+        /// <summary>
+        /// number of measurements per second
+        /// </summary>
+        private float fps;
+
         /// <summary>
         /// the emgu kalman filter
         /// </summary>
@@ -31,7 +30,7 @@ namespace bbiwarg.Utility
 
         /// <summary>
         /// yy entry for the measurement noise covariance matrix
-        /// </summary> 
+        /// </summary>
         private float mYY;
 
         /// <summary>
@@ -39,19 +38,11 @@ namespace bbiwarg.Utility
         /// </summary>
         private float processNoiseFactor;
 
-
-        /// <summary>
-        /// number of measurements per second
-        /// </summary>
-        private float fps;
-
-
         /// <summary>
         /// true iff the kalman filter is initialized
         /// </summary>
         public bool Initialized { get; private set; }
 
-
         // state: x, y, v_x, v_y
         //   x: current x position
         //   y: current y position
@@ -77,6 +68,35 @@ namespace bbiwarg.Utility
             reset();
         }
 
+        /// <summary>
+        /// Computes a smoothed position for a measurement and updates the filter.
+        /// </summary>
+        /// <param name="rawPosition">the measurement</param>
+        /// <returns>the smoothed position</returns>
+        public Vector2D getCorrectedPosition(Vector2D rawPosition)
+        {
+            Matrix<float> rawPositionMatrix = new Matrix<float>(new float[,]
+            { {rawPosition.X},
+              {rawPosition.Y}});
+
+            // prediction according to model
+            kalman.Predict();
+
+            // corrected point
+            Matrix<float> estimate = kalman.Correct(rawPositionMatrix);
+            return new Vector2D(estimate[0, 0], estimate[1, 0]);
+        }
+
+        /// <summary>
+        /// Computes a prediction for the next position based on the previous positions.
+        /// </summary>
+        /// <returns>prediction for the next position</returns>
+        public Vector2D getPrediction()
+        {
+            Matrix<float> predicton = kalman.Predict();
+            return new Vector2D(predicton[0, 0], predicton[1, 0]);
+        }
+
         /// <summary>
         /// Resets the kalman filter.
         /// </summary>
@@ -88,9 +108,9 @@ namespace bbiwarg.Utility
             // time step (s)
             float t = 1 / fps;
 
-            // transition matrix 
-            Matrix<float> transitionMatrix = new Matrix<float>(new float[,] 
-            { {1.0f, 0.0f},  
+            // transition matrix
+            Matrix<float> transitionMatrix = new Matrix<float>(new float[,]
+            { {1.0f, 0.0f},
               {0.0f, 1.0f}});
             kalman.TransitionMatrix = transitionMatrix;
 
@@ -135,34 +155,5 @@ namespace bbiwarg.Utility
 
             Initialized = true;
         }
-
-        /// <summary>
-        /// Computes a prediction for the next position based on the previous positions.
-        /// </summary>
-        /// <returns>prediction for the next position</returns>
-        public Vector2D getPrediction()
-        {
-            Matrix<float> predicton = kalman.Predict();
-            return new Vector2D(predicton[0, 0], predicton[1, 0]);
-        }
-
-        /// <summary>
-        /// Computes a smoothed position for a measurement and updates the filter.
-        /// </summary>
-        /// <param name="rawPosition">the measurement</param>
-        /// <returns>the smoothed position</returns>
-        public Vector2D getCorrectedPosition(Vector2D rawPosition)
-        {
-            Matrix<float> rawPositionMatrix = new Matrix<float>(new float[,] 
-            { {rawPosition.X},
-              {rawPosition.Y}});
-
-            // prediction according to model
-            kalman.Predict();
-
-            // corrected point
-            Matrix<float> estimate = kalman.Correct(rawPositionMatrix);
-            return new Vector2D(estimate[0, 0], estimate[1, 0]);
-        }
     }
-}
+}

+ 27 - 32
bbiwarg/Utility/Line2D.cs

@@ -1,8 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace bbiwarg.Utility
 {
@@ -22,14 +18,14 @@ namespace bbiwarg.Utility
     public class Line2D
     {
         /// <summary>
-        /// one point on the line
+        /// direction vector of the line
         /// </summary>
-        public Vector2D PointOnLine { get; private set; }
+        public Vector2D Direction { get; private set; }
 
         /// <summary>
-        /// direction vector of the line
+        /// one point on the line
         /// </summary>
-        public Vector2D Direction { get; private set; }
+        public Vector2D PointOnLine { get; private set; }
 
         /// <summary>
         /// Standard constructor which sets the essential attributes.
@@ -53,6 +49,28 @@ namespace bbiwarg.Utility
             return Math.Min(angle, 180 - angle);
         }
 
+        /// <summary>
+        /// Computes the intersection of two lines, iff the lines do not intersect it returns null.
+        /// </summary>
+        /// <param name="line">the second line</param>
+        /// <returns>the intersection or null iff the lines do not intersect</returns>
+        public Vector2D getIntersection(Line2D line)
+        {
+            Vector2D p = PointOnLine;
+            Vector2D r = Direction;
+            Vector2D q = line.PointOnLine;
+            Vector2D s = line.Direction;
+
+            float r_cross_s = r.crossProduct(s);
+            float q_p_cross_s = (q - p).crossProduct(s);
+
+            if (r_cross_s == 0.0)
+                return null;
+
+            float t = q_p_cross_s / r_cross_s;
+            return p + t * r;
+        }
+
         /// <summary>
         /// Calculates whether a point is above, below or on this line.
         /// </summary>
@@ -88,28 +106,5 @@ namespace bbiwarg.Utility
 
             return new Vector2D(newX, newY);
         }
-
-        /// <summary>
-        /// Computes the intersection of two lines, iff the lines do not intersect it returns null.
-        /// </summary>
-        /// <param name="line">the second line</param>
-        /// <returns>the intersection or null iff the lines do not intersect</returns>
-        public Vector2D getIntersection(Line2D line)
-        {
-            Vector2D p = PointOnLine;
-            Vector2D r = Direction;
-            Vector2D q = line.PointOnLine;
-            Vector2D s = line.Direction;
-
-            float r_cross_s = r.crossProduct(s);
-            float q_p_cross_s = (q - p).crossProduct(s);
-
-            if (r_cross_s == 0.0)
-                return null;
-
-            float t = q_p_cross_s / r_cross_s;
-            return p + t * r;
-        }
-
     }
-}
+}

+ 37 - 40
bbiwarg/Utility/LineSegment2D.cs

@@ -1,40 +1,36 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace bbiwarg.Utility
 {
     /// <summary>
-    /// Class to represent a segment of a line, a line between two points. 
+    /// Class to represent a segment of a line, a line between two points.
     /// </summary>
     public class LineSegment2D
     {
         /// <summary>
-        /// first point of the lineSegment
+        /// direction vector of the line which contains the lineSegment
         /// </summary>
-        public Vector2D P1 { get; private set; }
+        public Vector2D Direction { get { return Line.Direction; } }
 
         /// <summary>
-        /// second point of the lineSegment
+        /// length of the LineSegment
         /// </summary>
-        public Vector2D P2 { get; private set; }
+        public float Length { get; private set; }
 
         /// <summary>
-        /// direction vector of the line which contains the lineSegment
+        /// line which contains the lineSegment
         /// </summary>
-        public Vector2D Direction { get { return Line.Direction; } }
+        public Line2D Line { get; private set; }
 
         /// <summary>
-        /// line which contains the lineSegment
+        /// first point of the lineSegment
         /// </summary>
-        public Line2D Line { get; private set; }
+        public Vector2D P1 { get; private set; }
 
         /// <summary>
-        /// length of the LineSegment
+        /// second point of the lineSegment
         /// </summary>
-        public float Length { get; private set; }
+        public Vector2D P2 { get; private set; }
 
         /// <summary>
         /// Standard contructor which sets the essential attributes.
@@ -52,14 +48,27 @@ namespace bbiwarg.Utility
         }
 
         /// <summary>
-        /// Computes the intersection of two LineSegments, iff they do not intersect returns null.
+        /// Computes the shortest distance of a point to the LineSegment.
         /// </summary>
-        /// <param name="ls">second LineSegment</param>
-        /// <returns>Intersection iff its defined, else null</returns>
-        public bool intersectsWith(LineSegment2D ls)
+        /// <param name="point">the point for distance calculation</param>
+        /// <returns>the distance</returns>
+        public float getDistanceTo(Vector2D point)
         {
-            Vector2D intersection = Line.getIntersection(ls.Line);
-            return (intersection != null && intersection.isInBox(P1, P2) && intersection.isInBox(ls.P1, ls.P2));
+            // http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
+            float l2 = (P1 - P2).dotProduct(P1 - P2);  // i.e. |w-v|^2 -  avoid a sqrt
+            if (l2 == 0.0)
+                return point.getDistanceTo(P1);   // v == w case
+
+            // Consider the line extending the segment, parameterized as v + t (w - v).
+            // We find projection of point p onto the line.
+            // It falls where t = [(p-v) . (w-v)] / |w-v|^2
+            float t = (point - P1).dotProduct(P2 - P1) / l2;
+            if (t < 0.0)
+                return point.getDistanceTo(P1);       // Beyond the 'v' end of the segment
+            else if (t > 1.0)
+                return point.getDistanceTo(P2);  // Beyond the 'w' end of the segment
+            Vector2D projection = P1 + t * (P2 - P1);  // Projection falls on the segment
+            return point.getDistanceTo(projection);
         }
 
         /// <summary>
@@ -99,26 +108,14 @@ namespace bbiwarg.Utility
         }
 
         /// <summary>
-        /// Computes the shortest distance of a point to the LineSegment.
+        /// Computes the intersection of two LineSegments, iff they do not intersect returns null.
         /// </summary>
-        /// <param name="point">the point for distance calculation</param>
-        /// <returns>the distance</returns>
-        public float getDistanceTo(Vector2D point)
+        /// <param name="ls">second LineSegment</param>
+        /// <returns>Intersection iff its defined, else null</returns>
+        public bool intersectsWith(LineSegment2D ls)
         {
-            // http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
-            float l2 = (P1 - P2).dotProduct(P1 - P2);  // i.e. |w-v|^2 -  avoid a sqrt
-            if (l2 == 0.0)
-                return point.getDistanceTo(P1);   // v == w case
-            // Consider the line extending the segment, parameterized as v + t (w - v).
-            // We find projection of point p onto the line. 
-            // It falls where t = [(p-v) . (w-v)] / |w-v|^2
-            float t = (point - P1).dotProduct(P2 - P1) / l2;
-            if (t < 0.0)
-                return point.getDistanceTo(P1);       // Beyond the 'v' end of the segment
-            else if (t > 1.0)
-                return point.getDistanceTo(P2);  // Beyond the 'w' end of the segment
-            Vector2D projection = P1 + t * (P2 - P1);  // Projection falls on the segment
-            return point.getDistanceTo(projection);
+            Vector2D intersection = Line.getIntersection(ls.Line);
+            return (intersection != null && intersection.isInBox(P1, P2) && intersection.isInBox(ls.P1, ls.P2));
         }
 
         public override string ToString()
@@ -126,4 +123,4 @@ namespace bbiwarg.Utility
             return (int)P1.X + "|" + (int)P1.Y + " --- " + (int)P2.X + "|" + (int)P2.Y;
         }
     }
-}
+}

+ 2 - 6
bbiwarg/Utility/Logger.cs

@@ -1,8 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace bbiwarg.Utility
 {
@@ -28,7 +24,7 @@ namespace bbiwarg.Utility
     /// <summary>
     /// Logs messages.
     /// </summary>
-    static class Logger
+    internal static class Logger
     {
         /// <summary>
         /// the current frame
@@ -46,4 +42,4 @@ namespace bbiwarg.Utility
                 Console.WriteLine("Frame: " + CurrentFrame + "\t" + message);
         }
     }
-}
+}

+ 26 - 34
bbiwarg/Utility/Projection2DTo2D.cs

@@ -1,29 +1,16 @@
-using System;
+using Emgu.CV;
+using System;
 using System.Collections.Generic;
-using System.Linq;
 using System.Drawing;
 using System.Text;
-using System.Threading.Tasks;
-using Emgu.CV;
-using Emgu.CV.Structure;
 
 namespace bbiwarg.Utility
 {
     /// <summary>
     /// Computes and stores a homography matrix and provides functions to export it and project points.
     /// </summary>
-    class Projection2DTo2D
+    internal class Projection2DTo2D
     {
-        /// <summary>
-        /// size of the image the original points are in
-        /// </summary>
-        private ImageSize sizeA;
-
-        /// <summary>
-        /// size of the image the projected points are in
-        /// </summary>
-        private ImageSize sizeB;
-
         /// <summary>
         /// calibration points in the first image (match points in calibrationPointsB)
         /// </summary>
@@ -34,23 +21,31 @@ namespace bbiwarg.Utility
         /// </summary>
         private List<PointF> calibrationPointsB;
 
+        /// <summary>
+        /// homography matrix used to compute the projected points
+        /// </summary>
+        private HomographyMatrix homography;
+
         /// <summary>
         /// number of points used for the calibration
         /// </summary>
         private int numPointsForCalibration;
 
         /// <summary>
-        /// homography matrix used to compute the projected points
+        /// size of the image the original points are in
         /// </summary>
-        private HomographyMatrix homography;
+        private ImageSize sizeA;
 
+        /// <summary>
+        /// size of the image the projected points are in
+        /// </summary>
+        private ImageSize sizeB;
 
         /// <summary>
         /// true iff the calibration is finished
         /// </summary>
         public bool IsCalibrated { get; private set; }
 
-
         /// <summary>
         /// Constructs a Projection2DTo2D.
         /// </summary>
@@ -66,17 +61,6 @@ namespace bbiwarg.Utility
             reset();
         }
 
-        /// <summary>
-        /// Resets the calibration.
-        /// </summary>
-        public void reset()
-        {
-            homography = null;
-            IsCalibrated = false;
-            calibrationPointsA = new List<PointF>();
-            calibrationPointsB = new List<PointF>();
-        }
-
         /// <summary>
         /// Adds a pair of calibration points.
         /// </summary>
@@ -103,6 +87,17 @@ namespace bbiwarg.Utility
             return sizeB.getAbsolutePoint(new Vector2D(pointfsB[0]));
         }
 
+        /// <summary>
+        /// Resets the calibration.
+        /// </summary>
+        public void reset()
+        {
+            homography = null;
+            IsCalibrated = false;
+            calibrationPointsA = new List<PointF>();
+            calibrationPointsB = new List<PointF>();
+        }
+
         /// <summary>
         /// Computes the homography from the lists of calibration points.
         /// </summary>
@@ -137,7 +132,4 @@ namespace bbiwarg.Utility
             System.IO.File.WriteAllLines(Parameters.HomographyFileName, fileData);
         }
     }
-}
-
-
-
+}

+ 11 - 22
bbiwarg/Utility/Quadrangle.cs

@@ -1,15 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using System.Drawing;
-
-using bbiwarg.Recognition.HandRecognition;
-
-using Emgu.CV;
-using Emgu.CV.Structure;
 
 namespace bbiwarg.Utility
 {
@@ -19,29 +8,29 @@ namespace bbiwarg.Utility
     public class Quadrangle
     {
         /// <summary>
-        /// point in the top left corner
+        /// point in the bottom left corner
         /// </summary>
-        public Vector2D TopLeft { get; private set; }
+        public Vector2D BottomLeft { get; private set; }
 
         /// <summary>
-        /// point in the top right corner 
+        /// point in the bottom right corner
         /// </summary>
-        public Vector2D TopRight { get; private set; }
+        public Vector2D BottomRight { get; private set; }
 
         /// <summary>
-        /// point in the bottom right corner
+        /// all 4 points of the quadrangle in clockwise order, begining at the top left corner
         /// </summary>
-        public Vector2D BottomRight { get; private set; }
+        public Vector2D[] Corners { get { return new Vector2D[4] { TopLeft, TopRight, BottomRight, BottomLeft }; } }
 
         /// <summary>
-        /// point in the bottom left corner
+        /// point in the top left corner
         /// </summary>
-        public Vector2D BottomLeft { get; private set; }
+        public Vector2D TopLeft { get; private set; }
 
         /// <summary>
-        /// all 4 points of the quadrangle in clockwise order, begining at the top left corner
+        /// point in the top right corner
         /// </summary>
-        public Vector2D[] Corners { get { return new Vector2D[4] { TopLeft, TopRight, BottomRight, BottomLeft }; } }
+        public Vector2D TopRight { get; private set; }
 
         /// <summary>
         /// Standard constructor of quadrangle, which sets the 4 points.
@@ -104,4 +93,4 @@ namespace bbiwarg.Utility
             return (relativePos.X >= min && relativePos.X <= max) && (relativePos.Y >= min && relativePos.Y <= max);
         }
     }
-}
+}

+ 38 - 42
bbiwarg/Utility/Timer.cs

@@ -1,31 +1,29 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Linq;
 using System.Text;
-using System.Threading;
 
 namespace bbiwarg.Utility
 {
     /// <summary>
     /// Stores and prints timing information for different code sections.
     /// </summary>
-    static class Timer
+    internal static class Timer
     {
         /// <summary>
-        /// used to prevent running <see cref="start"/>, <see cref="stop"/> and <see cref="outputAll"/> simultaneously from different threads
+        /// dictionary of current runtimes indexed by name of the code section
         /// </summary>
-        private static Object sync = new object();
+        private static Dictionary<String, double> currentTimes = new Dictionary<string, double>();
 
         /// <summary>
-        /// dictionary of stopwatches indexed by name of the code section
+        /// the maximum length for the name of a code section
         /// </summary>
-        private static Dictionary<String, Stopwatch> stopwatches = new Dictionary<string, Stopwatch>();
+        private static int maxNameLength = 1;
 
         /// <summary>
-        /// dictionary of current runtimes indexed by name of the code section
+        /// dictionary of maximum runtimes indexed by name of the code section
         /// </summary>
-        private static Dictionary<String, double> currentTimes = new Dictionary<string, double>();
+        private static Dictionary<String, double> maxTimes = new Dictionary<string, double>();
 
         /// <summary>
         /// dictionary of minimum runtimes indexed by name of the code section
@@ -33,9 +31,14 @@ namespace bbiwarg.Utility
         private static Dictionary<String, double> minTimes = new Dictionary<string, double>();
 
         /// <summary>
-        /// dictionary of maximum runtimes indexed by name of the code section
+        /// dictionary of the number of times the time was measured indexed by name of the code section
         /// </summary>
-        private static Dictionary<String, double> maxTimes = new Dictionary<string, double>();
+        private static Dictionary<String, int> numTimes = new Dictionary<string, int>();
+
+        /// <summary>
+        /// dictionary of stopwatches indexed by name of the code section
+        /// </summary>
+        private static Dictionary<String, Stopwatch> stopwatches = new Dictionary<string, Stopwatch>();
 
         /// <summary>
         /// dictionary of the sum of runtimes indexed by name of the code section
@@ -43,15 +46,34 @@ namespace bbiwarg.Utility
         private static Dictionary<String, double> sumTimes = new Dictionary<string, double>();
 
         /// <summary>
-        /// dictionary of the number of times the time was measured indexed by name of the code section
+        /// used to prevent running <see cref="start"/>, <see cref="stop"/> and <see cref="outputAll"/> simultaneously from different threads
         /// </summary>
-        private static Dictionary<String, int> numTimes = new Dictionary<string, int>();
+        private static Object sync = new object();
 
         /// <summary>
-        /// the maximum length for the name of a code section
+        /// Prints all collected timing information.
         /// </summary>
-        private static int maxNameLength = 1;
+        public static void outputAll()
+        {
+            lock (sync)
+            {
+                StringBuilder divider = new StringBuilder();
+                divider.Append("├-");
+                divider.Append(new String('-', maxNameLength));
+                divider.Append("-┼-------┼-------┤");
+
+                Console.Clear();
+                Console.WriteLine(String.Format("| {0,-" + maxNameLength + "} | {1,-5} | {2,-5} |", "NAME", "AVG.", "CUR."));
+                Console.WriteLine(divider.ToString());
+                foreach (String name in stopwatches.Keys)
+                {
+                    double average = sumTimes[name] / Math.Max(numTimes[name], 1);
+                    double current = currentTimes[name];
 
+                    Console.WriteLine(String.Format("| {0,-" + maxNameLength + "} | {1:00.00} | {2:00.00} |", name, average, current));
+                }
+            }
+        }
 
         /// <summary>
         /// Starts a timer for the given name and initializes the dictionaries when called for the first time with this name.
@@ -92,31 +114,5 @@ namespace bbiwarg.Utility
                 currentTimes[name] = time;
             }
         }
-
-        /// <summary>
-        /// Prints all collected timing information.
-        /// </summary>
-        public static void outputAll()
-        {
-            lock (sync)
-            {
-                StringBuilder divider = new StringBuilder();
-                divider.Append("├-");
-                divider.Append(new String('-', maxNameLength));
-                divider.Append("-┼-------┼-------┤");
-
-                Console.Clear();
-                Console.WriteLine(String.Format("| {0,-" + maxNameLength + "} | {1,-5} | {2,-5} |", "NAME", "AVG.", "CUR."));
-                Console.WriteLine(divider.ToString());
-                foreach (String name in stopwatches.Keys)
-                {
-                    double average = sumTimes[name] / Math.Max(numTimes[name], 1);
-                    double current = currentTimes[name];
-
-                    Console.WriteLine(String.Format("| {0,-" + maxNameLength + "} | {1:00.00} | {2:00.00} |", name, average, current));
-                }
-            }
-        }
-
     }
-}
+}

+ 164 - 169
bbiwarg/Utility/Vector2D.cs

@@ -1,18 +1,14 @@
 using System;
 using System.Collections.Generic;
 using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace bbiwarg.Utility
 {
     /// <summary>
-    /// Class with represents a vector or a point in 2 dimensional space.  
+    /// Class with represents a vector or a point in 2 dimensional space.
     /// </summary>
     public class Vector2D
     {
-
         /// <summary>
         /// length of the vector, is initialized with -1 and will only be calculated if needed and only once
         /// </summary>
@@ -23,16 +19,6 @@ namespace bbiwarg.Utility
         /// </summary>
         public static Vector2D Zero { get { return new Vector2D(0, 0); } }
 
-        /// <summary>
-        /// X (first) component
-        /// </summary>
-        public float X { get; private set; }
-
-        /// <summary>
-        /// Y (second) component
-        /// </summary>
-        public float Y { get; private set; }
-
         /// <summary>
         /// X component as integer
         /// </summary>
@@ -48,6 +34,16 @@ namespace bbiwarg.Utility
         /// </summary>
         public float Length { get { if (length == -1) length = (float)Math.Sqrt(X * X + Y * Y); return length; } }
 
+        /// <summary>
+        /// X (first) component
+        /// </summary>
+        public float X { get; private set; }
+
+        /// <summary>
+        /// Y (second) component
+        /// </summary>
+        public float Y { get; private set; }
+
         /// <summary>
         /// Standard constructor which sets the components.
         /// </summary>
@@ -80,151 +76,143 @@ namespace bbiwarg.Utility
         }
 
         /// <summary>
-        /// Computes the euclidean distance between the point this vector describes and another point described by a Vector.
+        /// Casts a Vector2D to Point.
         /// </summary>
-        /// <param name="point">a Point</param>
-        /// <returns>euclidean distance</returns>
-        public float getDistanceTo(Vector2D point)
+        /// <param name="vec">a vector</param>
+        /// <returns>a Point</returns>
+        public static implicit operator Point(Vector2D vec)
         {
-            return (this - point).Length;
+            return new Point(vec.IntX, vec.IntY);
         }
 
         /// <summary>
-        /// Computes the angle between this vector and another vector in radians.
+        /// Casts a Vector2D to PointF.
         /// </summary>
-        /// <param name="vector">a vector</param>
-        /// <returns>angle in radians</returns>
-        public float getAngleBetween(Vector2D vector)
+        /// <param name="vec">a vector</param>
+        /// <returns>a PointF</returns>
+        public static implicit operator PointF(Vector2D vec)
         {
-            return (float)Math.Acos(dotProduct(vector) / (Length * vector.Length));
+            return new PointF(vec.X, vec.Y);
         }
 
         /// <summary>
-        /// Computes whether this vector and another vector point in opposite directions, meaning the smallest angle is between 90° and 180°.
+        /// Computes the mean of two vectors.
         /// </summary>
-        /// <param name="vector">a vector</param>
-        /// <returns>true iff the vectors point in opposite directions</returns>
-        public bool isInOppositeDirection(Vector2D vector)
+        /// <param name="vectors">second vector</param>
+        /// <returns>the mean vector</returns>
+        public static Vector2D mean(List<Vector2D> vectors)
         {
-            return (getAngleBetween(vector) > Math.PI / 2);
+            Vector2D sumVector = Vector2D.sum(vectors);
+            return sumVector / vectors.Count;
         }
 
         /// <summary>
-        /// Computes the dot product of this vector and another vector.
+        /// Subtracts two vectors (component-by-component).
         /// </summary>
-        /// <param name="vector">the other vector</param>
-        /// <returns>the dot product</returns>
-        public float dotProduct(Vector2D vector)
+        /// <param name="vector1">the minuend</param>
+        /// <param name="vector2">the subtrahend</param>
+        /// <returns>the difference of the two vectors</returns>
+        public static Vector2D operator -(Vector2D vector1, Vector2D vector2)
         {
-            return X * vector.X + Y * vector.Y;
+            return new Vector2D(vector1.X - vector2.X, vector1.Y - vector2.Y);
         }
 
         /// <summary>
-        /// Computes the cross product (determinant) of this vector and another vector.
+        /// Multiplies this vector component-by-component with a scalar value.
         /// </summary>
-        /// <param name="v">the other vector</param>
-        /// <returns>cross product of this and v</returns>
-        public float crossProduct(Vector2D v)
+        /// <param name="scalar">multiplier</param>
+        /// <param name="vector">multiplicant</param>
+        /// <returns>multiplied vector (product)</returns>
+        public static Vector2D operator *(float scalar, Vector2D vector)
         {
-            return X * v.Y - Y * v.X;
+            return new Vector2D(scalar * vector.X, scalar * vector.Y);
         }
 
         /// <summary>
-        /// Multiplies this vector component-by-component with another vector.
+        /// Multiplies this vector component-by-component with a scalar value.
         /// </summary>
-        /// <param name="v">the other vector</param>
-        /// <returns>the component-by-component multiplied vector</returns>
-        public Vector2D scale(Vector2D v)
+        /// <param name="vector">multiplicant</param>
+        /// <param name="scalar">multiplier</param>
+        /// <returns>multiplied vector (product)</returns>
+        public static Vector2D operator *(Vector2D vector, float scalar)
         {
-            return new Vector2D(X * v.X, Y * v.Y);
+            return new Vector2D(scalar * vector.X, scalar * vector.Y);
         }
 
         /// <summary>
-        /// Determines whether this point (vector) is inside a given box or not.
+        /// Divides this vector with a scalar value.
         /// </summary>
-        /// <param name="corner1">first corner of the box</param>
-        /// <param name="corner2">second corner of the box</param>
-        /// <returns>true iff point is inside the box</returns>
-        public bool isInBox(Vector2D corner1, Vector2D corner2)
+        /// <param name="vector">this vector</param>
+        /// <param name="scalar">the value</param>
+        /// <returns>the divided vector</returns>
+        public static Vector2D operator /(Vector2D vector, float scalar)
         {
-            float minX = Math.Min(corner1.X, corner2.X);
-            float maxX = Math.Max(corner1.X, corner2.X);
-            float minY = Math.Min(corner1.Y, corner2.Y);
-            float maxY = Math.Max(corner1.Y, corner2.Y);
-            return (minX <= X && X <= maxX && minY <= Y && Y <= maxY);
+            return new Vector2D(vector.X / scalar, vector.Y / scalar);
         }
 
         /// <summary>
-        /// Determines whether a this point is inside the boundaries of a given image or not. 
+        /// Divides on vector with another vector component-by-component.
         /// </summary>
-        /// <param name="imageSize">a imageSize object</param>
-        /// <returns>true iff point is inside the image boundaries</returns>
-        public bool isInBound(ImageSize imageSize)
+        /// <param name="vector1">the dividend</param>
+        /// <param name="vector2">the divisor</param>
+        /// <returns>the component divided vector</returns>
+        public static Vector2D operator /(Vector2D vector1, Vector2D vector2)
         {
-            return isInBound(Vector2D.Zero, imageSize.MaxPixel);
+            return new Vector2D(vector1.X / vector2.X, vector1.Y / vector2.Y);
         }
 
         /// <summary>
-        /// Determines whether a point is inside a box. iff bottomRight is higher or more left than topLeft the result is false.
+        /// Adds two vectors (component-by-component).
         /// </summary>
-        /// <param name="topLeft">top left corner of the box</param>
-        /// <param name="bottomRight">bottom right corner of the box</param>
-        /// <returns>true iff point is in box</returns>
-        public bool isInBound(Vector2D topLeft, Vector2D bottomRight)
+        /// <param name="vector1">first addend</param>
+        /// <param name="vector2">second addend</param>
+        /// <returns>sum of the vectors</returns>
+        public static Vector2D operator +(Vector2D vector1, Vector2D vector2)
         {
-            return (X >= topLeft.X && X <= bottomRight.X && Y >= topLeft.Y && Y <= bottomRight.Y);
+            return new Vector2D(vector1.X + vector2.X, vector1.Y + vector2.Y);
         }
 
         /// <summary>
-        /// Moves this vector along the direction vector factor times inside the imageSize, this point won't leave the image.
+        /// Sums a list of vectors (component-by-component).
         /// </summary>
-        /// <param name="imageSize">the imagesize</param>
-        /// <param name="direction">the move direction</param>
-        /// <param name="factor">the move factor</param>
-        /// <returns>a point inside the image</returns>
-        public Vector2D moveWithinBound(ImageSize imageSize, Vector2D direction, float factor)
+        /// <param name="vectors">a list of vectors</param>
+        /// <returns>vector of sumed components</returns>
+        public static Vector2D sum(List<Vector2D> vectors)
         {
-            Vector2D newPosition = this + factor * direction;
-            if (!newPosition.isInBound(imageSize))
-            {
-                Vector2D inverseDirection = direction.getInverse().normalize();
-                while (!newPosition.isInBound(imageSize))
-                {
-                    newPosition += inverseDirection;
-                }
-            }
-            return newPosition;
+            Vector2D sumVector = new Vector2D(0, 0);
+            foreach (Vector2D vector in vectors)
+                sumVector += vector;
+
+            return sumVector;
         }
 
         /// <summary>
-        /// Normalizes this vector with the euclidean norm (2. norm).
+        /// Copies this vector (clone).
         /// </summary>
-        /// <returns>normalized vector</returns>
-        public Vector2D normalize()
+        /// <returns>this vector as new vector</returns>
+        public Vector2D copy()
         {
-            return new Vector2D(X / Length, Y / Length);
+            return new Vector2D(X, Y);
         }
 
         /// <summary>
-        /// Computes a orthogonal vector of this vector, if side is true the X component will be switched, else the Y component.
+        /// Computes the cross product (determinant) of this vector and another vector.
         /// </summary>
-        /// <param name="side">which vector</param>
-        /// <returns>a orthogonal vector</returns>
-        public Vector2D getOrthogonal(bool side = true)
+        /// <param name="v">the other vector</param>
+        /// <returns>cross product of this and v</returns>
+        public float crossProduct(Vector2D v)
         {
-            if (side)
-                return new Vector2D(Y, -X);
-            else
-                return new Vector2D(-Y, X);
+            return X * v.Y - Y * v.X;
         }
 
         /// <summary>
-        /// Computes the inverse vector of this vector.
+        /// Computes the dot product of this vector and another vector.
         /// </summary>
-        /// <returns>inverse vector</returns>
-        public Vector2D getInverse()
+        /// <param name="vector">the other vector</param>
+        /// <returns>the dot product</returns>
+        public float dotProduct(Vector2D vector)
         {
-            return new Vector2D(-X, -Y);
+            return X * vector.X + Y * vector.Y;
         }
 
         /// <summary>
@@ -237,133 +225,140 @@ namespace bbiwarg.Utility
         }
 
         /// <summary>
-        /// Copies this vector (clone).
+        /// Computes the angle between this vector and another vector in radians.
         /// </summary>
-        /// <returns>this vector as new vector</returns>
-        public Vector2D copy()
+        /// <param name="vector">a vector</param>
+        /// <returns>angle in radians</returns>
+        public float getAngleBetween(Vector2D vector)
         {
-            return new Vector2D(X, Y);
+            return (float)Math.Acos(dotProduct(vector) / (Length * vector.Length));
         }
 
         /// <summary>
-        /// Creates a description of this vector.
+        /// Computes the euclidean distance between the point this vector describes and another point described by a Vector.
         /// </summary>
-        /// <returns>a string describing this vector</returns>
-        public override string ToString()
+        /// <param name="point">a Point</param>
+        /// <returns>euclidean distance</returns>
+        public float getDistanceTo(Vector2D point)
         {
-            return "(" + X + "|" + Y + ")";
+            return (this - point).Length;
         }
 
         /// <summary>
-        /// Multiplies this vector component-by-component with a scalar value.
+        /// Computes the inverse vector of this vector.
         /// </summary>
-        /// <param name="scalar">multiplier</param>
-        /// <param name="vector">multiplicant</param>
-        /// <returns>multiplied vector (product)</returns>
-        public static Vector2D operator *(float scalar, Vector2D vector)
+        /// <returns>inverse vector</returns>
+        public Vector2D getInverse()
         {
-            return new Vector2D(scalar * vector.X, scalar * vector.Y);
+            return new Vector2D(-X, -Y);
         }
 
         /// <summary>
-        /// Multiplies this vector component-by-component with a scalar value.
+        /// Computes a orthogonal vector of this vector, if side is true the X component will be switched, else the Y component.
         /// </summary>
-        /// <param name="vector">multiplicant</param>
-        /// <param name="scalar">multiplier</param>
-        /// <returns>multiplied vector (product)</returns>
-        public static Vector2D operator *(Vector2D vector, float scalar)
+        /// <param name="side">which vector</param>
+        /// <returns>a orthogonal vector</returns>
+        public Vector2D getOrthogonal(bool side = true)
         {
-            return new Vector2D(scalar * vector.X, scalar * vector.Y);
+            if (side)
+                return new Vector2D(Y, -X);
+            else
+                return new Vector2D(-Y, X);
         }
 
         /// <summary>
-        /// Divides this vector with a scalar value.
+        /// Determines whether a this point is inside the boundaries of a given image or not.
         /// </summary>
-        /// <param name="vector">this vector</param>
-        /// <param name="scalar">the value</param>
-        /// <returns>the divided vector</returns>
-        public static Vector2D operator /(Vector2D vector, float scalar)
+        /// <param name="imageSize">a imageSize object</param>
+        /// <returns>true iff point is inside the image boundaries</returns>
+        public bool isInBound(ImageSize imageSize)
         {
-            return new Vector2D(vector.X / scalar, vector.Y / scalar);
+            return isInBound(Vector2D.Zero, imageSize.MaxPixel);
         }
 
         /// <summary>
-        /// Divides on vector with another vector component-by-component.
+        /// Determines whether a point is inside a box. iff bottomRight is higher or more left than topLeft the result is false.
         /// </summary>
-        /// <param name="vector1">the dividend</param>
-        /// <param name="vector2">the divisor</param>
-        /// <returns>the component divided vector</returns>
-        public static Vector2D operator /(Vector2D vector1, Vector2D vector2)
+        /// <param name="topLeft">top left corner of the box</param>
+        /// <param name="bottomRight">bottom right corner of the box</param>
+        /// <returns>true iff point is in box</returns>
+        public bool isInBound(Vector2D topLeft, Vector2D bottomRight)
         {
-            return new Vector2D(vector1.X / vector2.X, vector1.Y / vector2.Y);
+            return (X >= topLeft.X && X <= bottomRight.X && Y >= topLeft.Y && Y <= bottomRight.Y);
         }
 
         /// <summary>
-        /// Adds two vectors (component-by-component).
+        /// Determines whether this point (vector) is inside a given box or not.
         /// </summary>
-        /// <param name="vector1">first addend</param>
-        /// <param name="vector2">second addend</param>
-        /// <returns>sum of the vectors</returns>
-        public static Vector2D operator +(Vector2D vector1, Vector2D vector2)
+        /// <param name="corner1">first corner of the box</param>
+        /// <param name="corner2">second corner of the box</param>
+        /// <returns>true iff point is inside the box</returns>
+        public bool isInBox(Vector2D corner1, Vector2D corner2)
         {
-            return new Vector2D(vector1.X + vector2.X, vector1.Y + vector2.Y);
+            float minX = Math.Min(corner1.X, corner2.X);
+            float maxX = Math.Max(corner1.X, corner2.X);
+            float minY = Math.Min(corner1.Y, corner2.Y);
+            float maxY = Math.Max(corner1.Y, corner2.Y);
+            return (minX <= X && X <= maxX && minY <= Y && Y <= maxY);
         }
 
         /// <summary>
-        /// Subtracts two vectors (component-by-component).
+        /// Computes whether this vector and another vector point in opposite directions, meaning the smallest angle is between 90° and 180°.
         /// </summary>
-        /// <param name="vector1">the minuend</param>
-        /// <param name="vector2">the subtrahend</param>
-        /// <returns>the difference of the two vectors</returns>
-        public static Vector2D operator -(Vector2D vector1, Vector2D vector2)
+        /// <param name="vector">a vector</param>
+        /// <returns>true iff the vectors point in opposite directions</returns>
+        public bool isInOppositeDirection(Vector2D vector)
         {
-            return new Vector2D(vector1.X - vector2.X, vector1.Y - vector2.Y);
+            return (getAngleBetween(vector) > Math.PI / 2);
         }
 
         /// <summary>
-        /// Computes the mean of two vectors.
+        /// Moves this vector along the direction vector factor times inside the imageSize, this point won't leave the image.
         /// </summary>
-        /// <param name="vectors">second vector</param>
-        /// <returns>the mean vector</returns>
-        public static Vector2D mean(List<Vector2D> vectors)
+        /// <param name="imageSize">the imagesize</param>
+        /// <param name="direction">the move direction</param>
+        /// <param name="factor">the move factor</param>
+        /// <returns>a point inside the image</returns>
+        public Vector2D moveWithinBound(ImageSize imageSize, Vector2D direction, float factor)
         {
-            Vector2D sumVector = Vector2D.sum(vectors);
-            return sumVector / vectors.Count;
+            Vector2D newPosition = this + factor * direction;
+            if (!newPosition.isInBound(imageSize))
+            {
+                Vector2D inverseDirection = direction.getInverse().normalize();
+                while (!newPosition.isInBound(imageSize))
+                {
+                    newPosition += inverseDirection;
+                }
+            }
+            return newPosition;
         }
 
         /// <summary>
-        /// Sums a list of vectors (component-by-component).
+        /// Normalizes this vector with the euclidean norm (2. norm).
         /// </summary>
-        /// <param name="vectors">a list of vectors</param>
-        /// <returns>vector of sumed components</returns>
-        public static Vector2D sum(List<Vector2D> vectors)
+        /// <returns>normalized vector</returns>
+        public Vector2D normalize()
         {
-            Vector2D sumVector = new Vector2D(0, 0);
-            foreach (Vector2D vector in vectors)
-                sumVector += vector;
-
-            return sumVector;
+            return new Vector2D(X / Length, Y / Length);
         }
 
         /// <summary>
-        /// Casts a Vector2D to PointF.
+        /// Multiplies this vector component-by-component with another vector.
         /// </summary>
-        /// <param name="vec">a vector</param>
-        /// <returns>a PointF</returns>
-        public static implicit operator PointF(Vector2D vec)
+        /// <param name="v">the other vector</param>
+        /// <returns>the component-by-component multiplied vector</returns>
+        public Vector2D scale(Vector2D v)
         {
-            return new PointF(vec.X, vec.Y);
+            return new Vector2D(X * v.X, Y * v.Y);
         }
 
         /// <summary>
-        /// Casts a Vector2D to Point.
+        /// Creates a description of this vector.
         /// </summary>
-        /// <param name="vec">a vector</param>
-        /// <returns>a Point</returns>
-        public static implicit operator Point(Vector2D vec)
+        /// <returns>a string describing this vector</returns>
+        public override string ToString()
         {
-            return new Point(vec.IntX, vec.IntY);
+            return "(" + X + "|" + Y + ")";
         }
-
     }
-}
+}

+ 28 - 33
bbiwarg/Utility/Vector3D.cs

@@ -1,50 +1,46 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace bbiwarg.Utility
 {
     /// <summary>
-    /// Class with represents a vector or a point in 3 dimensional space.  
+    /// Class with represents a vector or a point in 3 dimensional space.
     /// </summary>
     public class Vector3D
     {
         /// <summary>
-        /// X (first) component
+        /// X component as integer
         /// </summary>
-        public float X { get; private set; }
+        public int IntX { get { return (int)X; } }
 
         /// <summary>
-        /// Y (second) component
+        /// Y component as Integer
         /// </summary>
-        public float Y { get; private set; }
+        public int IntY { get { return (int)Y; } }
 
         /// <summary>
-        /// Z (third) component
+        /// Z component as Integer
         /// </summary>
-        public float Z { get; private set; }
+        public int IntZ { get { return (int)Z; } }
 
         /// <summary>
-        /// X component as integer
+        /// length of the vector, computed with euclidean distance (2.Norm)
         /// </summary>
-        public int IntX { get { return (int)X; } }
+        public float Length { get { return (float)Math.Sqrt(X * X + Y * Y + Z * Z); } }
 
         /// <summary>
-        /// Y component as Integer
+        /// X (first) component
         /// </summary>
-        public int IntY { get { return (int)Y; } }
+        public float X { get; private set; }
 
         /// <summary>
-        /// Z component as Integer
+        /// Y (second) component
         /// </summary>
-        public int IntZ { get { return (int)Z; } }
+        public float Y { get; private set; }
 
         /// <summary>
-        /// length of the vector, computed with euclidean distance (2.Norm)
+        /// Z (third) component
         /// </summary>
-        public float Length { get { return (float)Math.Sqrt(X * X + Y * Y + Z * Z); } }
+        public float Z { get; private set; }
 
         /// <summary>
         /// Standard constructor which sets the 3 components.
@@ -60,14 +56,14 @@ namespace bbiwarg.Utility
         }
 
         /// <summary>
-        /// Computes the distance from the point this vector describes to another 3D point (vector).
-        /// The distance is the euclidean distance (2. Norm).
+        /// Subtracts two vectors (component-by-component).
         /// </summary>
-        /// <param name="point">the other point</param>
-        /// <returns>euclidean distance between this and point</returns>
-        public float getDistanceTo(Vector3D point)
+        /// <param name="v1">the minuend</param>
+        /// <param name="v2">the subtrahend</param>
+        /// <returns>the difference of the two vectors</returns>
+        public static Vector3D operator -(Vector3D v1, Vector3D v2)
         {
-            return (this - point).Length;
+            return new Vector3D(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
         }
 
         /// <summary>
@@ -126,15 +122,14 @@ namespace bbiwarg.Utility
         }
 
         /// <summary>
-        /// Subtracts two vectors (component-by-component).
+        /// Computes the distance from the point this vector describes to another 3D point (vector).
+        /// The distance is the euclidean distance (2. Norm).
         /// </summary>
-        /// <param name="v1">the minuend</param>
-        /// <param name="v2">the subtrahend</param>
-        /// <returns>the difference of the two vectors</returns>
-        public static Vector3D operator -(Vector3D v1, Vector3D v2)
+        /// <param name="point">the other point</param>
+        /// <returns>euclidean distance between this and point</returns>
+        public float getDistanceTo(Vector3D point)
         {
-            return new Vector3D(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
+            return (this - point).Length;
         }
-
     }
-}
+}