private List <int[]> FaceEdgePairs() { var allEdgePairs = new List <int[]>(); var edgePairCounts = new Dictionary <int, int>(); var i = 0; do { var numInFace = (Faces[i] == 0) ? 3 : 4; if ((i + numInFace) < Faces.Count()) { i++; for (var v = 0; v < numInFace; v++) { var pair = (new int[] { Faces[i + v], Faces[((v + 1) == numInFace) ? i : i + v + 1] }).OrderBy(n => n).ToArray(); var foundIndex = allEdgePairs.FindIndex(ep => EqualPair(ep, pair)); if (foundIndex >= 0) { edgePairCounts[foundIndex]++; } else { allEdgePairs.Add(pair); edgePairCounts.Add(allEdgePairs.IndexOf(pair), 1); } } } i += numInFace; } while (i < Faces.Count()); var edgePairIndices = edgePairCounts.Where(kvp => kvp.Value == 1).Select(kvp => kvp.Key).ToList(); return(edgePairIndices.Select(pi => allEdgePairs[pi]).ToList()); }
public Structural2DElement[] Explode() { var elements = new List <Structural2DElement>(); var faceCounter = 0; for (var i = 0; i < Faces.Count(); i++) { var vertices = new List <double>(); var colors = new List <int>(); var numVertices = Faces[i++] + 3; for (var j = 0; j < numVertices; j++) { if (Colors != null && Colors.Count() > Faces[i]) { colors.Add(Colors[Faces[i]]); } vertices.AddRange(Vertices.Skip(Faces[i++] * 3).Take(3)); } i--; var element = new Structural2DElement( vertices.ToArray(), (new List <int>() { numVertices - 3 }).Concat(Enumerable.Range(0, numVertices)).ToArray(), colors.Count() == vertices.Count() / 3 ? colors.ToArray() : new int[0], ElementType, PropertyRef, Axis != null && Axis.Count() > faceCounter ? Axis[faceCounter] : null, Offset != null && Offset.Count() > faceCounter ? Offset[faceCounter] : 0, ElementApplicationId != null && ElementApplicationId.Count() > faceCounter ? ElementApplicationId[faceCounter] : Helper.CreateChildApplicationId(i, ApplicationId + "-" + faceCounter.ToString()) ) { GSADummy = GSADummy, GSAMeshSize = GSAMeshSize }; elements.Add(element); faceCounter++; } return(elements.ToArray()); }
/// <summary> /// Converts a hexahedron to a list of tetrahedons /// </summary> /// <returns></returns> public List <Cell> ToTetrahedons(Mesh mesh) { //return object List <Cell> ret = new List <Cell>(); try { LocationTimeValue[] vert = GetVertices(mesh); CreateFaces(mesh); LocationTimeValue loc1 = vert[0]; LocationTimeValue loc2 = vert.OrderByDescending(x => GeographyHelper.EuclideanDistance(x, loc1)).First(); for (int i = 0; i < Faces.Count(); i++) { Faces[i].Vertices.OrderBy(x => GeographyHelper.EuclideanDistance(x, Faces[i].Vertices[0])); Tetrahedron tet = new Tetrahedron(); tet.Vertices = new List <int>() { mesh.Vertices.IndexOf(Faces[i].Vertices[0]), mesh.Vertices.IndexOf(Faces[i].Vertices[1]), mesh.Vertices.IndexOf(Faces[i].Vertices[2]) }; if (Faces[i].Vertices.Contains(loc1)) { tet.Vertices.Add(mesh.Vertices.IndexOf(loc2)); } else { tet.Vertices.Add(mesh.Vertices.IndexOf(loc1)); } tet.CreateFaces(mesh); tet = new Tetrahedron(); tet.Vertices = new List <int>() { mesh.Vertices.IndexOf(Faces[i].Vertices[3]), mesh.Vertices.IndexOf(Faces[i].Vertices[1]), mesh.Vertices.IndexOf(Faces[i].Vertices[2]) }; if (Faces[i].Vertices.Contains(loc1)) { tet.Vertices.Add(mesh.Vertices.IndexOf(loc2)); } else { tet.Vertices.Add(mesh.Vertices.IndexOf(loc1)); } tet.CreateFaces(mesh); ret.Add(tet); } } catch { ret = new List <Cell>(); } return(ret); }
private void _updateFacesList(JArray ja) { ObservableCollection <Face> newColl = new ObservableCollection <Face>(); // Main face computation int mainFaceID = -1; float maxHeadSize = -1; // Copy new faces in existing list if (ja != null) { foreach (var v in ja) { // Parse basic info int id = int.Parse(v["id"].ToString()); string gender = v["gender"].ToString(); string age = v["age"].ToString(); var ageInteger = Int16.Parse(age); string ageRange = ageInteger <= 16 ? "child" : ageInteger <= 30 ? "young adult" : ageInteger <= 45 ? "middle-aged adult" : "old-aged adult"; var x = float.Parse(v["location"]["x"].ToString(), CultureInfo.InvariantCulture); // TODO: normalize? (or on C++ side?) var y = float.Parse(v["location"]["y"].ToString(), CultureInfo.InvariantCulture); var width = float.Parse(v["location"]["width"].ToString(), CultureInfo.InvariantCulture); var height = float.Parse(v["location"]["height"].ToString(), CultureInfo.InvariantCulture); // Intuiface coordinates system: move X&Y coords to represent the center of the head, not the top left corner x += width / 2; y += height / 2; // TODO: estimate distance in cm based on head size and camera focal / calibration step ?? var faceSize = (int)(width * height * 100 * 100); // Current value: % of head area over total image area var mainEmotion = v["mainEmotion"]["emotion"].ToString(); var mainEmotionConfidence = float.Parse(v["mainEmotion"]["confidence"].ToString(), CultureInfo.InvariantCulture); // Parse additional emotions EmotionConfidence emotionConfidence = new EmotionConfidence(); emotionConfidence.Angry = float.Parse(v["emotions"]["anger"].ToString(), CultureInfo.InvariantCulture); emotionConfidence.Happy = float.Parse(v["emotions"]["happy"].ToString(), CultureInfo.InvariantCulture); emotionConfidence.Neutral = float.Parse(v["emotions"]["neutral"].ToString(), CultureInfo.InvariantCulture); emotionConfidence.Sad = float.Parse(v["emotions"]["sad"].ToString(), CultureInfo.InvariantCulture); emotionConfidence.Surprised = float.Parse(v["emotions"]["surprise"].ToString(), CultureInfo.InvariantCulture); // Parse head pose estimation HeadPoseEstimation headPoseEstimation = new HeadPoseEstimation(); headPoseEstimation.Pitch = float.Parse(v["headpose"]["pitch"].ToString(), CultureInfo.InvariantCulture); headPoseEstimation.Yaw = float.Parse(v["headpose"]["yaw"].ToString(), CultureInfo.InvariantCulture); headPoseEstimation.Roll = float.Parse(v["headpose"]["roll"].ToString(), CultureInfo.InvariantCulture); // If face size filtering is active, check is head is bigger than threshold if (faceSize < m_dMinimumFaceSize) { // Don't add face to list continue; } // TODO: use real "distance" and take the min one. if (faceSize > maxHeadSize) { maxHeadSize = faceSize; mainFaceID = id; } newColl.Add(new Face() { Id = id, X = x, Y = y, Width = width, Height = height, FaceSize = faceSize, Gender = gender, Age = age, AgeRange = ageRange, MainEmotion = mainEmotion, MainEmotionConfidence = mainEmotionConfidence, EmotionConfidence = emotionConfidence, HeadPoseEstimation = headPoseEstimation }); } } // Order by ID newColl = new ObservableCollection <Face>(newColl.OrderBy(i => i.Id)); // Compare old (current) list and new list var removed = Faces.Except(newColl); var added = newColl.Except(Faces); if (removed.Count() > 0) { foreach (var face in removed) { // Raise face lost event Console.WriteLine("Face lost: " + face); RaiseFaceLost(face.Id, face.Gender, face.Age, face.DwellTime); m_startTimeMap.Remove(face.Id); } } if (added.Count() > 0) { foreach (var face in added) { // Raise face added event Console.WriteLine("Face added: " + face); RaiseFaceDetected(face.Id, face.Gender, face.Age); m_startTimeMap.Add(face.Id, DateTime.Now); } } // Update elements in current list with new list int newCount = newColl.Count; int oldCount = Faces.Count; if (newCount != oldCount) { // Raise face count changed event Console.WriteLine("Face count changed: " + newCount); RaiseFaceCountChanged(newCount); } // Adjust number of faces in Faces // New users to add if (newCount > oldCount) { for (int i = 0; i < newCount - oldCount; i++) { Faces.Add(new Face()); } } // Users to remove else if (newCount < oldCount) { for (int i = newCount; i < oldCount; i++) { Faces.RemoveAt(newCount); } } // Copy new coll properties in existing faces list. int index = 0; foreach (var item in newColl) { try { Faces[index].Id = item.Id; Faces[index].X = item.X; Faces[index].Y = item.Y; Faces[index].Width = item.Width; Faces[index].Height = item.Height; Faces[index].Gender = item.Gender; Faces[index].Age = item.Age; Faces[index].AgeRange = item.AgeRange; Faces[index].DwellTime = (DateTime.Now - m_startTimeMap[item.Id]).TotalSeconds; Faces[index].FaceSize = item.FaceSize; Faces[index].MainEmotion = item.MainEmotion; Faces[index].MainEmotionConfidence = item.MainEmotionConfidence; // Additional emotions Faces[index].EmotionConfidence = item.EmotionConfidence; // Head pose estimation Faces[index].HeadPoseEstimation = item.HeadPoseEstimation; } catch (Exception ex) { ActivityLog += ex.Message + "\n"; throw; } index++; } // Update face count FaceCount = Faces.Count(); // Copy main face info if (FaceCount > 0) { var item = Faces.FirstOrDefault(i => i.Id == mainFaceID); if (item != null) { MainFace.Id = item.Id; MainFace.X = item.X; MainFace.Y = item.Y; MainFace.Width = item.Width; MainFace.Height = item.Height; MainFace.FaceSize = item.FaceSize; MainFace.Gender = item.Gender; MainFace.Age = item.Age; MainFace.AgeRange = item.AgeRange; MainFace.DwellTime = (DateTime.Now - m_startTimeMap[item.Id]).TotalSeconds; MainFace.MainEmotion = item.MainEmotion; MainFace.MainEmotionConfidence = item.MainEmotionConfidence; // Additional emotions MainFace.EmotionConfidence = item.EmotionConfidence; // Head pose estimation MainFace.HeadPoseEstimation = item.HeadPoseEstimation; // Mark the face detected IsMainFaceDetected = true; } else { IsMainFaceDetected = false; } } else { IsMainFaceDetected = false; } }
public List <int[]> Edges() { var edgeConnectivities = new List <int[]>(); // Get face connectivities and close loop var faceConnnectivities = new List <int[]>(); for (var i = 0; i < Faces.Count(); i++) { var numVertices = Faces[i] + 3; i++; faceConnnectivities.Add(Faces.Skip(i).Take(numVertices).Concat(Faces.Skip(i).Take(1)).ToArray()); i += numVertices - 1; } // Get distinct edges var edges = new List <Tuple <int, int, string, string, double> >(); foreach (var conn in faceConnnectivities) { for (var i = 0; i < conn.Length - 1; i++) { var c1 = string.Join(",", Vertices.Skip(conn[i] * 3).Take(3).Select(x => Math.Round(x, 4).ToString())); var c2 = string.Join(",", Vertices.Skip(conn[i + 1] * 3).Take(3).Select(x => Math.Round(x, 4).ToString())); var length = Math.Pow(Vertices.Skip(conn[i] * 3).Take(1).First() - Vertices.Skip(conn[i + 1] * 3).Take(1).First(), 2) + Math.Pow(Vertices.Skip(conn[i] * 3 + 1).Take(1).First() - Vertices.Skip(conn[i + 1] * 3 + 1).Take(1).First(), 2) + Math.Pow(Vertices.Skip(conn[i] * 3 + 2).Take(1).First() - Vertices.Skip(conn[i + 1] * 3 + 2).Take(1).First(), 2); length = Math.Sqrt(length); if (edges.Any(e => (e.Item3 == c1 && e.Item4 == c2) | (e.Item3 == c2 && e.Item4 == c1))) { edges.RemoveAll(x => (x.Item3 == c1 && x.Item4 == c2) || (x.Item3 == c2 && x.Item4 == c1)); } else { if (conn[i] < conn[i + 1]) { edges.Add(new Tuple <int, int, string, string, double>(conn[i], conn[i + 1], c1, c2, length)); } else { edges.Add(new Tuple <int, int, string, string, double>(conn[i + 1], conn[i], c2, c1, length)); } } } } // Reorder the edges var lengthsOfEdges = new List <double>(); double currentLength = 0; var currentLoop = new List <int>(); var flatCoor = new List <string>(); currentLoop.Add(edges[0].Item1); currentLoop.Add(edges[0].Item2); flatCoor.Add(edges[0].Item3); flatCoor.Add(edges[0].Item4); edges.RemoveAt(0); while (edges.Count > 0) { var commonVertex = flatCoor.Last(); var nextEdge = edges.Where(e => e.Item3 == commonVertex | e.Item4 == commonVertex).ToList(); if (nextEdge.Count > 0) { currentLoop.Add(nextEdge[0].Item3 == commonVertex ? nextEdge[0].Item2 : nextEdge[0].Item1); flatCoor.Add(nextEdge[0].Item3 == commonVertex ? nextEdge[0].Item4 : nextEdge[0].Item3); edges.Remove(nextEdge[0]); currentLength += nextEdge[0].Item5; } else { // Next edge not found. Stop looking for more break; } if (currentLoop[0] == currentLoop.Last()) { currentLoop.RemoveAt(0); edgeConnectivities.Add(currentLoop.ToArray()); lengthsOfEdges.Add(currentLength); currentLength = 0; currentLoop = new List <int>(); faceConnnectivities = new List <int[]>(); if (edges.Count > 0) { currentLoop.Add(edges[0].Item1); currentLoop.Add(edges[0].Item2); flatCoor.Add(edges[0].Item3); flatCoor.Add(edges[0].Item4); edges.RemoveAt(0); } } } // Sort based on length var ordered = lengthsOfEdges .Select((x, i) => new KeyValuePair <double, int>(x, i)) .OrderBy(x => x.Key) .Select(x => x.Value) .Reverse(); var sortedEdgeConnectivities = new List <int[]>(); foreach (var i in ordered) { sortedEdgeConnectivities.Add(edgeConnectivities[i]); } return(sortedEdgeConnectivities); }