Commit 9f83935e authored by Alexander Krause's avatar Alexander Krause

Refactoring

parent aa6ceaf7
......@@ -37,17 +37,17 @@ namespace ExplorVizGestureControl.General
#region Function
/*
* The startTimer function can start a new timer run, but also restart a currently running one.
* The StartTimer function can start a new timer run, but also restart a currently running one.
* In this case, busy is set to true.
*/
public void startTimer()
public void StartTimer()
{
busy = true;
timer.Stop();
timer.Start();
}
public void stopTimer()
public void StopTimer()
{
busy = false;
timer.Stop();
......@@ -62,11 +62,11 @@ namespace ExplorVizGestureControl.General
//Console.WriteLine("elapsed" + DateTime.Now.ToString());
}
public void changeTimerCycle(double timeSpan)
public void ChangeTimerCycle(double timeSpan)
{
timer.Stop();
timer.Interval = timeSpan;
startTimer();
StartTimer();
}
#endregion
......
......@@ -24,11 +24,11 @@ namespace ExplorVizGestureControl.General
// Not passed by reference as design choice. You may use filteredJoints'
// unaltered data
public Vector3D[] accumulateJoints(CameraSpacePoint[] filteredJoints)
public Vector3D[] AccumulateJoints(CameraSpacePoint[] filteredJoints)
{
this.filteredJoints = filteredJoints;
accumulateRightShoulder();
AccumulateRightShoulder();
// add new methods based on the above for
// further joint accumulation
......@@ -36,7 +36,7 @@ namespace ExplorVizGestureControl.General
}
#region Accumulations
private void accumulateRightShoulder()
private void AccumulateRightShoulder()
{
int shoulderRightIndex = (int)JointType.ShoulderRight;
Vector3D shoulderRight = new Vector3D(filteredJoints[shoulderRightIndex].X, filteredJoints[shoulderRightIndex].Y, filteredJoints[shoulderRightIndex].Z);
......
......@@ -17,37 +17,29 @@ namespace ExplorVizGestureControl.Gestures
{
public class ContinuousGestureDetector
{
#region Variables
private struct MOUSE_EVENTS
{
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
public const int MOUSEEVENTF_LEFTUP = 0x04;
public const int MOUSEEVENTF_RIGHTDOWN = 0x08;
public const int MOUSEEVENTF_RIGHTUP = 0x10;
public const int MOUSEEVENTF_WHEEL = 0x0800;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
private const int MOUSEEVENTF_WHEEL = 0x0800;
private GestureTimer zoomDelayTimer;
private GestureTimer zoomActivationTimer;
private GestureTimer rotationActivationTimer;
#region Variables
internal static GestureTimer delayTimer;
private GestureTimer[] timers;
private Boolean rotationActive = false;
private Boolean gripActive = false;
private Boolean zoomingActive = false;
private Boolean rotAnchorSet = false;
private int[] flags;
private float[] anchors;
private Dictionary<string, double> dynamicValues = new Dictionary<string, double>();
private float selectionAnchorLength;
private float rotationAnchorLength;
private float rotationAnchorY;
private float zoomAnchorZ;
private int selectionStatus = 0;
private int zoomStatus = 0;
private int zoomFrameCounter = 0;
#endregion
#region Constructor
......@@ -61,11 +53,23 @@ namespace ExplorVizGestureControl.Gestures
dynamicValues.Add("rotationVelocityY", 1000);
dynamicValues.Add("rotationYActivation", 0.04);
zoomDelayTimer = new GestureTimer(700);
int arrayLength = 7;
flags = new int[arrayLength];
Array.Clear(flags, 0, arrayLength);
arrayLength = 4;
anchors = new float[arrayLength];
Array.Clear(anchors, 0, arrayLength);
delayTimer = new GestureTimer(2000);
rotationActivationTimer = new GestureTimer(500);
zoomActivationTimer = new GestureTimer(500);
timers = new GestureTimer[3];
timers[0] = new GestureTimer(2000);
timers[1] = new GestureTimer(500);
timers[2] = new GestureTimer(500);
}
#endregion
......@@ -76,7 +80,7 @@ namespace ExplorVizGestureControl.Gestures
Zoom();
Rotation();
if (IntersectWithPhIZ() || gripActive) GripAndSelection();
if (IntersectWithPhIZ() || flags[1] == 1) GripAndSelection();
}
private bool IntersectWithPhIZ()
......@@ -90,7 +94,7 @@ namespace ExplorVizGestureControl.Gestures
(GestureDatabase.Joints[(int)JointType.HandRight].Y <= maxY && GestureDatabase.Joints[(int)JointType.HandRight].Y >= minY) ? true : false;
}
public void updateDynamicValues(string key, double value)
public void UpdateDynamicValues(string key, double value)
{
dynamicValues[key] = value;
}
......@@ -99,24 +103,30 @@ namespace ExplorVizGestureControl.Gestures
#region Gestures
private void Rotation()
{
if (gripActive || zoomingActive) return;
{
if (flags[2] == 1 || flags[2] == 1) return;
int rotationActive = 0;
int rotAnchorSet = 3;
int rotationAnchorLength = 1;
int rotationAnchorY = 2;
if (GestureDatabase.LeftHandClosed())
{
if (!rotationActivationTimer.busy && !rotAnchorSet)
if (!timers[1].busy && flags[rotAnchorSet] == 0)
{
rotationActivationTimer.startTimer();
timers[1].StartTimer();
}
if (!rotAnchorSet)
if (flags[rotAnchorSet] == 0)
{
if (GestureDatabase.HandsAboveSpineBase("left") &&
GestureDatabase.Joints[(int)JointType.HandLeft].X <= GestureDatabase.Joints[(int)JointType.ShoulderLeft].X - 0.07f)
{
rotationAnchorY = Math.Abs(GestureDatabase.Joints[(int)JointType.HandLeft].Y);
rotationAnchorLength = GestureDatabase.CalculateVectorLength(GestureDatabase.Joints[(int)JointType.HandLeft]);
rotAnchorSet = true;
anchors[rotationAnchorY] = Math.Abs(GestureDatabase.Joints[(int)JointType.HandLeft].Y);
anchors[rotationAnchorLength] = GestureDatabase.CalculateVectorLength(GestureDatabase.Joints[(int)JointType.HandLeft]);
flags[rotAnchorSet] = 1;
}
else return;
}
......@@ -124,29 +134,29 @@ namespace ExplorVizGestureControl.Gestures
float vLength = GestureDatabase.CalculateVectorLength(GestureDatabase.Joints[(int)JointType.HandLeft]);
// Check for intentional / non-intentional rotation
if (!rotationActivationTimer.busy && !rotationActive)
if (!timers[1].busy && flags[rotationActive] == 0)
{
if (Math.Abs(rotationAnchorLength - vLength) < 0.015f)
{
mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
rotationActive = true;
if (Math.Abs(anchors[rotationAnchorLength] - vLength) < 0.015f)
{
mouse_event(MOUSE_EVENTS.MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
flags[rotationActive] = 1;
}
else
{
rotAnchorSet = false;
flags[rotAnchorSet] = 0;
return;
}
}
if (rotationActive)
{
if (flags[rotationActive] == 1)
{
float distanceXHands = GestureDatabase.Joints[(int)JointType.HandLeft].X - GestureDatabase.PreviousFrameJoints[(int)JointType.HandLeft].X;
float distanceYHands = GestureDatabase.Joints[(int)JointType.HandLeft].Y - GestureDatabase.PreviousFrameJoints[(int)JointType.HandLeft].Y;
int yDetection = 0;
float currentlyHandLeftY = Math.Abs(GestureDatabase.Joints[(int)JointType.HandLeft].Y);
if (Math.Abs(currentlyHandLeftY - rotationAnchorY) > (float)dynamicValues["rotationYActivation"]) yDetection = (int)dynamicValues["rotationVelocityY"];
if (Math.Abs(currentlyHandLeftY - anchors[rotationAnchorY]) > (float)dynamicValues["rotationYActivation"]) yDetection = (int)dynamicValues["rotationVelocityY"];
int moveX = (int)(distanceXHands * dynamicValues["rotationVelocityX"]);
int moveY = (int)(distanceYHands * yDetection);
......@@ -155,110 +165,120 @@ namespace ExplorVizGestureControl.Gestures
}
else return;
}
else if (rotationActive)
else if (flags[rotationActive] == 1)
{
rotationActivationTimer.startTimer();
rotationActive = false;
rotAnchorSet = false;
mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
timers[1].StartTimer();
flags[rotationActive] = 0;
flags[rotAnchorSet] = 0;
mouse_event(MOUSE_EVENTS.MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
}
}
private void Zoom()
{
if (rotationActive || gripActive || zoomDelayTimer.busy) return;
{
if (flags[0] == 1 || flags[1] == 1 || timers[0].busy) return;
int zoomingActive = 2;
int zoomStatus = 5;
int zoomFrameCounter = 6;
int zoomAnchorZ = 3;
if (GestureDatabase.ZoomRecognized())
{
zoomFrameCounter = ++zoomFrameCounter % (int)dynamicValues["zoomAccelerationFactor"];
flags[zoomFrameCounter] = ++flags[zoomFrameCounter] % (int)dynamicValues["zoomAccelerationFactor"];
// process after every n-th frame (standard: 5th)
if (zoomFrameCounter != 0) return;
if (flags[zoomFrameCounter] != 0) return;
if (zoomStatus == 0)
{
zoomStatus = 1;
zoomActivationTimer.startTimer();
zoomAnchorZ = GestureDatabase.Joints[(int)JointType.HandRight].Z;
if (flags[zoomStatus] == 0)
{
flags[zoomStatus] = 1;
timers[2].StartTimer();
anchors[zoomAnchorZ] = GestureDatabase.Joints[(int)JointType.HandRight].Z;
}
float currentZ = GestureDatabase.Joints[(int)JointType.HandRight].Z;
if (zoomingActive || (!zoomActivationTimer.busy && (currentZ < zoomAnchorZ + 0.015f) &&
(currentZ < zoomAnchorZ + 0.015f)))
if (zoomingActive == 1 || (!timers[2].busy && (currentZ < anchors[zoomAnchorZ] + 0.015f) &&
(currentZ < anchors[zoomAnchorZ] + 0.015f)))
{
zoomingActive = true;
zoomingActive = 1;
float distance = GestureDatabase.Joints[(int)JointType.HandRight].Z -
GestureDatabase.PreviousFrameJoints[(int)JointType.HandRight].Z;
if (distance >= 0f && GestureDatabase.BothHandsClosed())
{
zoomStatus = 2;
flags[zoomStatus] = 2;
}
else if (distance < 0f && GestureDatabase.BothHandsClosed()) { return; }
if (distance < 0 && GestureDatabase.BothHandsOpen())
{
if (zoomStatus == 2)
if (flags[zoomStatus] == 2)
{
zoomStatus = 3;
zoomDelayTimer.startTimer();
flags[zoomStatus] = 3;
timers[0].StartTimer();
return;
}
zoomStatus = 3;
flags[zoomStatus] = 3;
}
else if (distance >= 0 && GestureDatabase.BothHandsOpen()) { return; }
// For small changes between frames, we need a high multiplicator,
// because of the cast.
int scrollValue = (int)(distance * 20000);
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, scrollValue, 0);
mouse_event(MOUSE_EVENTS.MOUSEEVENTF_WHEEL, 0, 0, scrollValue, 0);
}
}
else
{
zoomingActive = false;
zoomStatus = 0;
zoomDelayTimer.startTimer();
flags[zoomingActive] = 0;
flags[zoomStatus] = 0;
timers[0].StartTimer();
}
}
private void GripAndSelection()
{
if (rotationActive || zoomingActive) return;
if (flags[0] == 1 || flags[2] == 1) return;
int gripActive = 1;
int selectionStatus = 4;
int selectionAnchorLength = 0;
if (!GestureDatabase.RightHandClosed() && selectionStatus == 1)
if (!GestureDatabase.RightHandClosed() && flags[selectionStatus] == 1)
{
selectionStatus = 2;
flags[selectionStatus] = 2;
}
if (!GestureDatabase.RightHandClosed() && selectionStatus == 2 && !gripActive)
if (!GestureDatabase.RightHandClosed() && flags[selectionStatus] == 2 && flags[gripActive] == 0)
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
selectionStatus = 0;
mouse_event(MOUSE_EVENTS.MOUSEEVENTF_LEFTDOWN | MOUSE_EVENTS.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
flags[selectionStatus] = 0;
}
if (GestureDatabase.RightHandClosed())
{
if (selectionStatus == 0)
if (flags[selectionStatus] == 0)
{
selectionAnchorLength = GestureDatabase.CalculateVectorLength(GestureDatabase.Joints[(int)JointType.HandRight]);
selectionStatus = 1;
anchors[selectionAnchorLength] = GestureDatabase.CalculateVectorLength(GestureDatabase.Joints[(int)JointType.HandRight]);
flags[selectionStatus] = 1;
}
float vLength = GestureDatabase.CalculateVectorLength(GestureDatabase.Joints[(int)JointType.HandRight]);
// Check for intentional / non-intentional rotation
if (!gripActive)
if (flags[gripActive] == 0)
{
// If hand position changed at least 1.5 cm (vector length!), activate dragging
if (Math.Abs(selectionAnchorLength - vLength) > 0.015f)
if (Math.Abs(anchors[selectionAnchorLength] - vLength) > 0.015f)
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
gripActive = true;
mouse_event(MOUSE_EVENTS.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
flags[gripActive] = 1;
}
else
{
......@@ -267,7 +287,7 @@ namespace ExplorVizGestureControl.Gestures
}
// Else handle grip processing
if (gripActive)
if (flags[gripActive] == 1)
{
double distanceX = GestureDatabase.Joints[(int)JointType.HandRight].X -
GestureDatabase.PreviousFrameJoints[(int)JointType.HandRight].X;
......@@ -281,11 +301,11 @@ namespace ExplorVizGestureControl.Gestures
}
else return;
}
else if (gripActive)
else if (flags[gripActive] == 1)
{
selectionStatus = 0;
gripActive = false;
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
flags[selectionStatus] = 0;
flags[gripActive] = 0;
mouse_event(MOUSE_EVENTS.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
}
......
......@@ -20,15 +20,21 @@ namespace ExplorVizGestureControl.Gestures
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private struct KEYBOARD_EVENTS
{
public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
public const int UP = 0x26;
}
#region Variables
private GestureTimer timerForNextGesture;
public Boolean detectContinousGestures = false;
private Boolean detectContinuousGestures = false;
private GestureTimer contDetStartReset;
private const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
private const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
private const int UP = 0x26;
#endregion
#region Initialization
......@@ -40,7 +46,7 @@ namespace ExplorVizGestureControl.Gestures
#endregion
#region Gesture recognition
public void gestureRecognition()
public void GestureRecognition()
{
foreach (KeyValuePair<string, Func<bool>> entry in GestureDatabase.GestureDictionary)
{
......@@ -48,19 +54,19 @@ namespace ExplorVizGestureControl.Gestures
if (entry.Value.Invoke() && !this.timerForNextGesture.busy)
{
// start a gesture timer for mistake avoidance
timerForNextGesture.startTimer();
timerForNextGesture.StartTimer();
switch (entry.Key)
{
case "Start_Reset":
if (contDetStartReset.busy) return;
contDetStartReset.startTimer();
contDetStartReset.StartTimer();
keybd_event(UP, 0, KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(UP, 0, KEYEVENTF_KEYUP, 0);
keybd_event(KEYBOARD_EVENTS.UP, 0, KEYBOARD_EVENTS.KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(KEYBOARD_EVENTS.UP, 0, KEYBOARD_EVENTS.KEYEVENTF_KEYUP, 0);
ContinuousGestureDetector.delayTimer.startTimer();
detectContinousGestures = true;
ContinuousGestureDetector.delayTimer.StartTimer();
detectContinuousGestures = true;
break;
case "PreviousTab":
break;
......@@ -74,5 +80,13 @@ namespace ExplorVizGestureControl.Gestures
}
#endregion
public bool DetectContinuousGestures
{
get
{
return this.detectContinuousGestures;
}
}
}
}
......@@ -66,7 +66,7 @@ namespace ExplorVizGestureControl.Gestures
#region Update Database
public static void refreshJoints(CameraSpacePoint[] filteredJoints, Vector3D[] accumulatedJoint, HandState right, HandState left)
public static void RefreshJoints(CameraSpacePoint[] filteredJoints, Vector3D[] accumulatedJoint, HandState right, HandState left)
{
int flagIndex = 0;
......
......@@ -126,16 +126,16 @@ namespace ExplorVizGestureControl
{
filter.UpdateFilter(body);
CameraSpacePoint[] filteredJoints = filter.GetFilteredJoints();
Vector3D[] accumulatedJoints = jointAccumulator.accumulateJoints(filteredJoints);
GestureDatabase.refreshJoints(filteredJoints, accumulatedJoints, body.HandRightState, body.HandLeftState);
discreteGestureDetector.gestureRecognition();
Vector3D[] accumulatedJoints = jointAccumulator.AccumulateJoints(filteredJoints);
GestureDatabase.RefreshJoints(filteredJoints, accumulatedJoints, body.HandRightState, body.HandLeftState);
discreteGestureDetector.GestureRecognition();
if (drawBody)
{
bodyStream.DrawBodies();
cleanBitmap = false;
}
if (discreteGestureDetector.detectContinousGestures)
if (discreteGestureDetector.DetectContinuousGestures)
continuousGestureDetector.DetectContinousGestures();
}
}
......@@ -238,7 +238,7 @@ namespace ExplorVizGestureControl
if (e.Key == Key.Return)
{
TextBox textBox = sender as TextBox;
continuousGestureDetector.updateDynamicValues(textBox.Name, Convert.ToDouble(textBox.Text));
continuousGestureDetector.UpdateDynamicValues(textBox.Name, Convert.ToDouble(textBox.Text));
}
}
......
......@@ -17,24 +17,32 @@ namespace ExplorVizGestureControl.StreamsAndDrawing
public class BodyDrawing
{
private class DrawingParameters
{
public readonly double jointThickness = 3;
public readonly Brush trackedJointBrush = new SolidColorBrush(Color.FromArgb(255, 68, 192, 68));
public readonly List<Pen> bodyColors = new List<Pen>();
}
#region Variables
private const double HandSize = 20;
private const double JointThickness = 3;
private const double ClipBoundsThickness = 10;
private const float InferredZPositionClamp = 0.1f;
private readonly Brush handClosedBrush = new SolidColorBrush(Color.FromArgb(128, 255, 0, 0));
private readonly Brush handOpenBrush = new SolidColorBrush(Color.FromArgb(128, 0, 255, 0));
private readonly Brush handLassoBrush = new SolidColorBrush(Color.FromArgb(128, 0, 0, 255));
private readonly Brush trackedJointBrush = new SolidColorBrush(Color.FromArgb(255, 68, 192, 68));
private readonly Brush inferredJointBrush = Brushes.Yellow;
private readonly Pen inferredBonePen = new Pen(Brushes.Gray, 1);
private DrawingGroup drawingGroup;
private DrawingImage jointsSource;
private CoordinateMapper coordinateMapper = null;
private const float InferredZPositionClamp = 0.1f;
private List<Tuple<JointType, JointType>> bones;
private int displayWidth = 480;
private int displayHeight = 270;
private List<Pen> bodyColors;
private DrawingParameters dParameters;
private Dictionary<JointType, Point> jointPoints;
private Dictionary<JointType, Joint> joints;
#endregion
#region Constructor
......@@ -84,15 +92,15 @@ namespace ExplorVizGestureControl.StreamsAndDrawing
this.bones.Add(new Tuple<JointType, JointType>(JointType.KneeLeft, JointType.AnkleLeft));
this.bones.Add(new Tuple<JointType, JointType>(JointType.AnkleLeft, JointType.FootLeft));
// populate body colors, one for each BodyIndex
this.bodyColors = new List<Pen>();
this.dParameters = new DrawingParameters();
this.bodyColors.Add(new Pen(Brushes.Red, 6));
this.bodyColors.Add(new Pen(Brushes.Orange, 6));
this.bodyColors.Add(new Pen(Brushes.Green, 6));
this.bodyColors.Add(new Pen(Brushes.Blue, 6));
this.bodyColors.Add(new Pen(Brushes.Indigo, 6));
this.bodyColors.Add(new Pen(Brushes.Violet, 6));
// populate body colors, one for each BodyIndex