/* * Find all faces that are linked such that the normal from face to face never changes more than angleTolerance. */ public static List <int> FindAllLinkedPlaneFaces(Component component, int faceInt, double angleTolerance) { var valid = new List <int>() { faceInt }; int i = 0; while (i < valid.Count) { foreach (int neighborIndex in component.GetNeighbouringFacesViaEdges(valid[i])) { if (!valid.Contains(neighborIndex) && component.GetFace(valid[i]).normal.AngleTo( component.GetFace(neighborIndex).normal) < angleTolerance) { valid.Add(neighborIndex); } } i++; } return(valid); }
/* * Retrieves the most downward facing face connected to a Vertex. */ public static int FindStartFloorFace(Component component, int lowestVertex) { int currStartFloorFace; try { currStartFloorFace = component.GetVertex(lowestVertex).faceIndices[0]; foreach (int faceIndex in component.GetVertex(lowestVertex).faceIndices) { if (component.GetFace(faceIndex).normal.AngleTo(Vect3.Down) < component.GetFace(currStartFloorFace).normal.AngleTo(Vect3.Down)) { currStartFloorFace = faceIndex; } } } catch (ArgumentOutOfRangeException) { throw new EmptyListException("Vertex exists but has an empty face list."); } return(currStartFloorFace); }
public void DrawStructure(DrawStructure choices, Structure structure, Vect3 structureMiddlePoint) { GameObject structureObject = new GameObject("Structure"); for (int componentIndex = 0; componentIndex < structure.components.Count; componentIndex++) { GameObject componentObject = new GameObject(string.Format("Component {0}", componentIndex)); componentObject.transform.parent = structureObject.transform; Nodegraph_Generator.Component component = structure.components[componentIndex]; // To prepare color List <int> floorFaces = ComponentGraphGenerator.GetFloorFaces(component); LinkedList <int> linkedList = ComponentGraphGenerator.GetShellVertices(component, floorFaces); (LinkedList <int>, LinkedList <int>)sidePair = ComponentGraphGenerator.SplitLinkedList(component, linkedList); if (choices.drawVertices) { GameObject verticesObject = new GameObject(string.Format("Component {0}, Vertices", componentIndex)); verticesObject.transform.parent = componentObject.transform; for (int vertexIndex = 0; vertexIndex < component.vertices.Count; vertexIndex++) { Vertex vertex = component.GetVertex(vertexIndex); Vect3 vertexPosition = Utilities.GetScaledTransletedVect3(vertex.coordinate, structureMiddlePoint, scalingFactor); GameObject vertexObject = Utilities.DrawObject(vertexPrefab, vertexPosition, verticesObject); vertexObject.name = string.Format("Vertex {0}", vertexIndex); if (choices.colorFloor) { if (sidePair.Item1.Contains(vertexIndex)) { Utilities.ColorObject(vertexObject, Color.blue); } else if (sidePair.Item2.Contains(vertexIndex)) { Utilities.ColorObject(vertexObject, Color.red); } } } } if (choices.drawFaces) { var drawnVertexPairs = new List <(int, int)>(); var drawnFaceSides = new List <GameObject>(); GameObject faces = new GameObject(string.Format("Component {0}, Faces", componentIndex)); faces.transform.parent = componentObject.transform; for (int faceIndex = 0; faceIndex < component.faces.Count; faceIndex++) { Face face = component.GetFace(faceIndex); var faceMiddlepoint = new Vect3(); for (int i = 0; i < face.vertexIndices.Length; i++) { int firstVertexIndex = face.vertexIndices[i]; Vertex firstVertex = component.GetVertex(firstVertexIndex); faceMiddlepoint += firstVertex.coordinate; for (int j = i + 1; j < face.vertexIndices.Length; j++) { int secondVertexIndex = face.vertexIndices[j]; if (!(drawnVertexPairs.Contains((firstVertexIndex, secondVertexIndex)) || drawnVertexPairs.Contains((secondVertexIndex, firstVertexIndex)))) { Vertex secondVertex = component.GetVertex(secondVertexIndex); Vect3 startPos = Utilities.GetScaledTransletedVect3(firstVertex.coordinate, structureMiddlePoint, scalingFactor); Vect3 endPos = Utilities.GetScaledTransletedVect3(secondVertex.coordinate, structureMiddlePoint, scalingFactor); GameObject faceSideObject = Utilities.DrawLine(startPos, endPos, faces); faceSideObject.name = string.Format("Faceside to Face {0}", faceIndex); Utilities.ColorObject(faceSideObject, (choices.colorFloor && floorFaces.Contains(faceIndex)) ? Color.green : Color.black); drawnVertexPairs.Add((secondVertexIndex, firstVertexIndex)); drawnFaceSides.Add(faceSideObject); } else { GameObject faceSideObject = drawnFaceSides[drawnVertexPairs.FindIndex(a => (a.Item1 == firstVertexIndex && a.Item2 == secondVertexIndex) || (a.Item1 == secondVertexIndex && a.Item2 == firstVertexIndex))]; if (choices.colorFloor && floorFaces.Contains(faceIndex)) { Utilities.ColorObject(faceSideObject, Color.green); } faceSideObject.name += ", " + faceIndex; } } }
/* * Returns a linked list of the vertices representing the shell of a face list. */ public static LinkedList <int> GetShellVertices(Component component, List <int> floorFaces) { var shellPairs = new List <(int, int)>(); for (int i = 0; i < floorFaces.Count; i++) { Face outerFace = component.GetFace(floorFaces[i]); bool foundPair01 = false; bool foundPair02 = false; bool foundPair12 = false; for (int j = 0; j < floorFaces.Count; j++) { if (i == j) { continue; } Face innerFace = component.GetFace(floorFaces[j]); if (Array.Exists(innerFace.vertexIndices, index => index == outerFace.vertexIndices[0]) && Array.Exists(innerFace.vertexIndices, index => index == outerFace.vertexIndices[1])) { foundPair01 = true; } if (Array.Exists(innerFace.vertexIndices, index => index == outerFace.vertexIndices[0]) && Array.Exists(innerFace.vertexIndices, index => index == outerFace.vertexIndices[2])) { foundPair02 = true; } if (Array.Exists(innerFace.vertexIndices, index => index == outerFace.vertexIndices[1]) && Array.Exists(innerFace.vertexIndices, index => index == outerFace.vertexIndices[2])) { foundPair12 = true; } } if (!foundPair01) { shellPairs.Add((outerFace.vertexIndices[0], outerFace.vertexIndices[1])); } if (!foundPair02) { shellPairs.Add((outerFace.vertexIndices[0], outerFace.vertexIndices[2])); } if (!foundPair12) { shellPairs.Add((outerFace.vertexIndices[1], outerFace.vertexIndices[2])); } } /* Make shellPairs a Linked List */ var linkedList = new LinkedList <int>(); linkedList.AddFirst(shellPairs[0].Item1); linkedList.AddLast(shellPairs[0].Item2); shellPairs.RemoveAt(0); var count = 0; while (shellPairs.Count > 0) { foreach ((int, int)pair in shellPairs) { if (pair.Item1 == linkedList.Last.Value) { if (linkedList.Contains(pair.Item2)) { count++; if (count > 1) { throw new Exception("Shellpair-list is not empty when it should be."); } } else { linkedList.AddLast(pair.Item2); } shellPairs.Remove(pair); break; } else if (pair.Item2 == linkedList.Last.Value) { if (linkedList.Contains(pair.Item1)) { count++; if (count > 1) { throw new Exception("ShellPair-list is not empty when it should be."); } } else { linkedList.AddLast(pair.Item1); } shellPairs.Remove(pair); break; } } } return(linkedList); }