/* * Returns the mean velocity vector for the gesture in world space. */ private Point_3D mean_velocity_3D(ref List <Point_3D> gesture3d) { Point_3D v = new Point_3D(); v.time = 0; v.x = 0; v.y = 0; v.z = 0; for (int i = 0; i < gesture3d.Count - 1; i++) { float dx = gesture3d[i + 1].x - gesture3d[i].x; float dy = gesture3d[i + 1].y - gesture3d[i].y; float dz = gesture3d[i + 1].z - gesture3d[i].z; float dt = gesture3d[i + 1].time - gesture3d[i].time; v.x += dx / dt; v.y += dy / dt; v.z += dz / dt; } v.x /= (gesture3d.Count - 1); v.y /= (gesture3d.Count - 1); v.z /= (gesture3d.Count - 1); return(v); }
public void VaryingOrderingOfJson() { Point_3D point = Serializer.Deserialize <Point_3D>(@"{""X"":1,""Y"":2,""Z"":3}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = Serializer.Deserialize <Point_3D>(@"{""X"":1,""Z"":3,""Y"":2}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = Serializer.Deserialize <Point_3D>(@"{""Y"":2,""Z"":3,""X"":1}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = Serializer.Deserialize <Point_3D>(@"{""Y"":2,""X"":1,""Z"":3}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = Serializer.Deserialize <Point_3D>(@"{""Z"":3,""Y"":2,""X"":1}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = Serializer.Deserialize <Point_3D>(@"{""Z"":3,""X"":1,""Y"":2}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); }
public async Task NoConstructorHandlingWhenObjectHasConverter() { // Baseline without converter string serialized = JsonSerializer.Serialize(new Point_3D(10, 6)); Point_3D point = await Serializer.DeserializeWrapper <Point_3D>(serialized); Assert.Equal(10, point.X); Assert.Equal(6, point.Y); Assert.Equal(50, point.Z); serialized = JsonSerializer.Serialize(new[] { new Point_3D(10, 6) }); point = (await Serializer.DeserializeWrapper <Point_3D[]>(serialized))[0]; Assert.Equal(10, point.X); Assert.Equal(6, point.Y); Assert.Equal(50, point.Z); serialized = JsonSerializer.Serialize(new WrapperForPoint_3D { Point_3D = new Point_3D(10, 6) }); point = (await Serializer.DeserializeWrapper <WrapperForPoint_3D>(serialized)).Point_3D; Assert.Equal(10, point.X); Assert.Equal(6, point.Y); Assert.Equal(50, point.Z); // Converters for objects with parameterized ctors are honored var options = new JsonSerializerOptions(); options.Converters.Add(new ConverterForPoint3D()); serialized = JsonSerializer.Serialize(new Point_3D(10, 6)); point = await Serializer.DeserializeWrapper <Point_3D>(serialized, options); Assert.Equal(4, point.X); Assert.Equal(4, point.Y); Assert.Equal(4, point.Z); serialized = JsonSerializer.Serialize(new[] { new Point_3D(10, 6) }); point = (await Serializer.DeserializeWrapper <Point_3D[]>(serialized, options))[0]; Assert.Equal(4, point.X); Assert.Equal(4, point.Y); Assert.Equal(4, point.Z); serialized = JsonSerializer.Serialize(new WrapperForPoint_3D { Point_3D = new Point_3D(10, 6) }); point = (await Serializer.DeserializeWrapper <WrapperForPoint_3D>(serialized, options)).Point_3D; Assert.Equal(4, point.X); Assert.Equal(4, point.Y); Assert.Equal(4, point.Z); }
public void AsProperty_Of_ObjectWithParameterizedCtor() { ClassWrapperForPoint_3D obj = Serializer.Deserialize <ClassWrapperForPoint_3D>(@"{""Point3D"":{""Y"":2,""Z"":3,""X"":1}}"); Point_3D point = obj.Point3D; Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); }
public async Task AsProperty_Of_ObjectWithParameterlessCtor() { WrapperForPoint_3D obj = await Serializer.DeserializeWrapper <WrapperForPoint_3D>(@"{""Point_3D"":{""Y"":2,""Z"":3,""X"":1}}"); Point_3D point = obj.Point_3D; Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); }
public async Task VaryingOrderingOfJson() { Point_3D point = await Serializer.DeserializeWrapper <Point_3D>(@"{""X"":1,""Y"":2,""Z"":3}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = await Serializer.DeserializeWrapper <Point_3D>(@"{""X"":1,""Z"":3,""Y"":2}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = await Serializer.DeserializeWrapper <Point_3D>(@"{""Y"":2,""Z"":3,""X"":1}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = await Serializer.DeserializeWrapper <Point_3D>(@"{""Y"":2,""X"":1,""Z"":3}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = await Serializer.DeserializeWrapper <Point_3D>(@"{""Z"":3,""Y"":2,""X"":1}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); point = await Serializer.DeserializeWrapper <Point_3D>(@"{""Z"":3,""X"":1,""Y"":2}"); Assert.Equal(1, point.X); Assert.Equal(2, point.Y); Assert.Equal(3, point.Z); }
public async Task UseDefaultValues_When_NoJsonMatch() { // Using CLR value when `ParameterInfo.DefaultValue` is not set. Point_2D point = await Serializer.DeserializeWrapper <Point_2D>(@"{""x"":1,""y"":2}"); Assert.Equal(0, point.X); Assert.Equal(0, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""y"":2,""x"":1}"); Assert.Equal(0, point.X); Assert.Equal(0, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""x"":1,""Y"":2}"); Assert.Equal(0, point.X); Assert.Equal(2, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""y"":2,""X"":1}"); Assert.Equal(1, point.X); Assert.Equal(0, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""X"":1}"); Assert.Equal(1, point.X); Assert.Equal(0, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""Y"":2}"); Assert.Equal(0, point.X); Assert.Equal(2, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""X"":1}"); Assert.Equal(1, point.X); Assert.Equal(0, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""Y"":2}"); Assert.Equal(0, point.X); Assert.Equal(2, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{}"); Assert.Equal(0, point.X); Assert.Equal(0, point.Y); point = await Serializer.DeserializeWrapper <Point_2D>(@"{""a"":1,""b"":2}"); Assert.Equal(0, point.X); Assert.Equal(0, point.Y); // Using `ParameterInfo.DefaultValue` when set; using CLR value as fallback. Point_3D point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""X"":1}"); Assert.Equal(1, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(50, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""y"":2}"); Assert.Equal(0, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(50, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""Z"":3}"); Assert.Equal(0, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(3, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""X"":1}"); Assert.Equal(1, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(50, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""Y"":2}"); Assert.Equal(0, point3d.X); Assert.Equal(2, point3d.Y); Assert.Equal(50, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""Z"":3}"); Assert.Equal(0, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(3, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""x"":1,""Y"":2}"); Assert.Equal(0, point3d.X); Assert.Equal(2, point3d.Y); Assert.Equal(50, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""Z"":3,""y"":2}"); Assert.Equal(0, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(3, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""x"":1,""Z"":3}"); Assert.Equal(0, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(3, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{}"); Assert.Equal(0, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(50, point3d.Z); point3d = await Serializer.DeserializeWrapper <Point_3D>(@"{""a"":1,""b"":2}"); Assert.Equal(0, point3d.X); Assert.Equal(0, point3d.Y); Assert.Equal(50, point3d.Z); }
/* * returns the norm of a 3D vector. */ private float vec3_norm(Point_3D vec) { return((float)Math.Sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z)); }
public Gesture_Meta recognize_gesture(List <Point_2D> gesture, List <Point_3D> gesture3D) { if (gesture.Count <= 2 * LP_KERNEL_SIZE) { var gm = new Gesture_Meta(); gm.type = Gesture.unknown; return(gm); } Bounds bounds = calculate_bounds(ref gesture, 0, gesture.Count); List <float> angles = new List <float>(); if (LP_ENABLE) { gesture = gaussian_average_lowpass(gesture, LP_KERNEL_SIZE, LP_SIGMA); } float angle_sum = calculate_angles(ref gesture, ref angles, bounds); Point_2D avg_vel_vec2 = mean_velocity_2D(ref gesture); Point_3D avg_vel_vec3 = mean_velocity_3D(ref gesture3D); float gesture_width = bounds.max_x - bounds.min_x; float gesture_height = bounds.max_y - bounds.min_y; float gesture_depth = bounds.max_z - bounds.min_z; Point_2D start = gesture[0]; Point_2D end = gesture[gesture.Count - 1]; Gesture_Meta ret = new Gesture_Meta(); ret.type = Gesture.unknown; ret.avg_vel_vector = avg_vel_vec3; ret.angle_sum = angle_sum; ret.bounds = bounds; List <Point_2D> sparse_gesture = sparsify(ref gesture); float[] global_angles = vector_list_angles(ref sparse_gesture); // ************************ Classify gesture ************************** float vel_vec_norm = vec2_norm(avg_vel_vec2, false); float x_pos_dev = angle(avg_vel_vec2, new Point_2D(0, 1, 0, 0), false); float y_pos_dev = angle(avg_vel_vec2, new Point_2D(0, 0, 1, 0), false); float z_pos_dev = angle(avg_vel_vec2, new Point_2D(0, 0, 0, 1), false); float x_neg_dev = angle(avg_vel_vec2, new Point_2D(0, -1, 0, 0), false); float y_neg_dev = angle(avg_vel_vec2, new Point_2D(0, 0, -1, 0), false); float z_neg_dev = angle(avg_vel_vec2, new Point_2D(0, 0, 0, -1), false); bool x_pos = x_pos_dev < x_neg_dev; bool y_pos = y_pos_dev < y_neg_dev; bool z_pos = z_pos_dev < z_neg_dev; bool z_gesture = gesture_depth > gesture_height && gesture_depth > gesture_width; // likely a gesture with depth if (vel_vec_norm > VEL_VEC_NORM_THRESH && z_gesture || gesture_depth > Z_DEPTH_THRESH) { if (z_pos_dev < ANGLE_DEVIATION_THRESH && Math.Abs(avg_vel_vec2.z) > 0.2) { ret.type = Gesture.push; } else if (z_neg_dev < ANGLE_DEVIATION_THRESH && Math.Abs(avg_vel_vec2.z) > 0.2) { ret.type = Gesture.pull; } } // likely a gesture of one or more line segments if (ret.type == Gesture.unknown) { List <LinearSegment> segments = find_linear_segments(global_angles, sparse_gesture, bounds); Console.WriteLine(segments.Count); Gesture[] candidate_gestures; gesture_len_map.TryGetValue(segments.Count, out candidate_gestures); if (candidate_gestures != null) { foreach (Gesture g in candidate_gestures) { if (matches_linear_segments(segments, g, sparse_gesture, alt_start_allowed_map[g])) { ret.type = g; break; } } } } // likely a circle if (ret.type == Gesture.unknown) { // likely a circle float min_angle = (float)((2 - ANGLE_SUM_THRESH) * Math.PI); float max_angle = (float)((2 + ANGLE_SUM_THRESH) * Math.PI); if (angle_sum > min_angle && angle_sum < max_angle) { ret.type = Gesture.circle_ccw; } else if (angle_sum < -min_angle && angle_sum > -max_angle) { ret.type = Gesture.circle_cw; } else if (angle_sum > 6 * Math.PI) { ret.type = Gesture.spiral_ccw; } } return(ret); }