//-------------------------------------------------------------------------------------------------- static void _CreateFaces(List <ObjectDescription> objectDescList, List <Pnt> vertices) { // Create Faces foreach (var objectDesc in objectDescList) { // Extract used vertices var usedVertices = new List <Pnt>(); var indexMap = new Dictionary <int, int>(); for (int index = 0; index < objectDesc.Indices.Count; index++) { int newIndex; int oldIndex = objectDesc.Indices[index]; if (!indexMap.TryGetValue(oldIndex, out newIndex)) { newIndex = usedVertices.Count; usedVertices.Add(vertices[oldIndex]); indexMap.Add(oldIndex, newIndex); } objectDesc.Indices[index] = newIndex; } // Create shape objectDesc.Face = TriangulationHelper.CreateFaceFromTriangulation(new TriangulationData(objectDesc.Indices.ToArray(), usedVertices.ToArray(), null)); } }
private void BuildMesh() { int[] indices = TriangulationHelper.Triangulate2D(_polygonCollider2D.points); Vector3[] vertices = new Vector3[_polygonCollider2D.points.Length]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = _polygonCollider2D.points[i] + _polygonCollider2D.offset; } if (_meshFilter.sharedMesh == null) { _meshFilter.sharedMesh = new Mesh(); } if (_meshFilter.sharedMesh.vertices != vertices) { _meshFilter.sharedMesh.vertices = vertices; _meshFilter.sharedMesh.triangles = indices; _meshFilter.sharedMesh.RecalculateNormals(); _meshFilter.sharedMesh.RecalculateBounds(); _meshRenderer.sortingOrder = _orderInLayer; _meshFilter.sharedMesh.name = "geometry"; _meshFilter.sharedMesh.hideFlags = HideFlags.HideAndDontSave; } }
private void OnDrawGizmos() { PolygonCollider2D polygonCollider2D = this.gameObject.GetComponent <PolygonCollider2D>(); int[] indices = TriangulationHelper.Triangulate2D(polygonCollider2D.points); Vector3[] vertices = new Vector3[polygonCollider2D.points.Length]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = polygonCollider2D.points[i] + polygonCollider2D.offset; } MeshFilter meshFilter = this.gameObject.GetComponent <MeshFilter>(); MeshRenderer meshRenderer = this.gameObject.GetComponent <MeshRenderer>(); if (meshFilter.sharedMesh == null || meshFilter.sharedMesh.vertices.Length != vertices.Length) { meshFilter.sharedMesh = new Mesh(); } meshFilter.sharedMesh.vertices = vertices; meshFilter.sharedMesh.triangles = indices; meshFilter.sharedMesh.RecalculateNormals(); meshFilter.sharedMesh.RecalculateBounds(); meshRenderer.sortingOrder = _orderInLayer; meshFilter.sharedMesh.name = "geometry"; meshFilter.sharedMesh.hideFlags = HideFlags.HideAndDontSave; }
//-------------------------------------------------------------------------------------------------- bool IBodyImporter.DoImport(string fileName, out IEnumerable <Body> bodies) { bodies = null; try { using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { IStlReader reader; // Binary or Ascii? var tempBuffer = new byte[80]; fs.Read(tempBuffer, 0, 80); var header = Encoding.ASCII.GetString(tempBuffer).TrimStart(' '); if (header.StartsWith("solid", StringComparison.InvariantCultureIgnoreCase)) { reader = new StlAsciiReader(); } else { reader = new StlBinaryReader(); } var predictedTriangleCount = reader.Init(fs); // Read facets var vertices = new List <Pnt>(predictedTriangleCount * 3); while (reader.MoveNext()) { vertices.Add(reader.CurrentVertices[0]); vertices.Add(reader.CurrentVertices[1]); vertices.Add(reader.CurrentVertices[2]); } // Create Shape var face = TriangulationHelper.CreateFaceFromTriangulation(new TriangulationData(null, vertices.ToArray())); var body = Body.Create(Mesh.Create(face)); body.Name = Path.GetFileNameWithoutExtension(fileName); bodies = new[] { body }; // Cleanup fs.Close(); } return(true); } catch (Exception e) { Messages.Exception($"Exception occured while importing {fileName}.", e); return(false); } }
private static void AddVertexToTriangulation(int vertexId, List <SortedVertex> vertices, HullEdgesList convexHull, TriangulationGraph graph) { FixTriangulationIteratively(vertexId, vertices, convexHull, HullEdge.IterationDirections.Right, (v1, v2) => TriangulationHelper.CrossProduct(v1, v2) > -DelaunayTriangulationValidator.Eps, (left, right, outer) => FixTriangulation(left, right, outer, vertices, graph)); var hullVertex = FixTriangulationIteratively(vertexId, vertices, convexHull, HullEdge.IterationDirections.Left, (v1, v2) => TriangulationHelper.CrossProduct(v1, v2) < DelaunayTriangulationValidator.Eps, (left, right, outer) => FixTriangulation(right, left, outer, vertices, graph)); convexHull[convexHull[vertexId].Right].Set(HullEdge.IterationDirections.Left, vertexId); convexHull[hullVertex].Set(HullEdge.IterationDirections.Right, vertexId); }
/// <summary> /// Returns a trajectory created from input file /// </summary> public virtual IEnumerable <IPoint> GetTrajectory(string inputFilePath) { var inputData = LoadInputData(inputFilePath) as InputData; var trajectoryPoints = new List <IPoint>(); var timesCollection = inputData.PropagationTime; OutputData = new List <string>(); foreach (var time in timesCollection) { var position = TriangulationHelper.GetPosition(inputData.Receivers, time, PublicFields.Error) as TwoDimensialPoint; if (position != null) { (OutputData as List <string>).Add($"{position.XPosition.ToString("0.00000000", CultureInfo.InvariantCulture)}{PublicFields.PositionSeparator}{position.YPosition.ToString("0.00000000", CultureInfo.InvariantCulture)}"); trajectoryPoints.Add(position); } } return(trajectoryPoints); }
private static void FixTriangulation(int left, int right, int outer, IReadOnlyList <SortedVertex> vertices, TriangulationGraph graph) { var recursionStack = new Edge[vertices.Count]; recursionStack[0] = new Edge(left, right); var stackSize = 1; while (stackSize > 0) { left = recursionStack[stackSize - 1].Vertex1; right = recursionStack[stackSize - 1].Vertex2; --stackSize; var inner = graph[new Edge(Mathf.Min(left, right), Mathf.Max(left, right))].Min(); if (DelaunayTriangulationValidator.Validate(left, right, outer, inner, vertices)) { graph[new Edge(right, outer)].Insert(left); graph[new Edge(left, outer)].Insert(right); if (right < left) { TriangulationHelper.Swap(ref left, ref right); } graph[new Edge(left, right)].Insert(outer); continue; } graph[new Edge(right, outer)].Replace(left, inner); graph[new Edge(left, outer)].Replace(right, inner); graph[new Edge(Mathf.Min(inner, left), Mathf.Max(inner, left))].Replace(right, outer); graph[new Edge(Mathf.Min(inner, right), Mathf.Max(inner, right))].Replace(left, outer); graph.Remove(new Edge(Mathf.Min(left, right), Mathf.Max(left, right))); recursionStack[stackSize++] = new Edge(left, inner); recursionStack[stackSize++] = new Edge(inner, right); } }
private void UpdateMesh(bool initialize = false) { if (!initialize) { if (!_meshRenderer.isVisible) { return; } if (_settleScale <= 0) { return; } } Vector2[] pathPoints = GetPathPoints(); _polygonCollider2D.points = pathPoints; int[] indices = TriangulationHelper.Triangulate2D(pathPoints); Vector3[] vertices = new Vector3[pathPoints.Length]; int vertexCount = vertices.Length; for (int i = 0; i < vertexCount; i++) { vertices[i] = pathPoints[i]; } Mesh mesh = _meshFilter.sharedMesh; // Update mesh if (mesh.vertexCount == 0 || mesh.vertexCount == vertexCount) { mesh.vertices = vertices; mesh.triangles = indices; mesh.RecalculateNormals(); mesh.RecalculateBounds(); } }
public static bool Export(IEnumerable <Body> bodies, string fileName, bool binaryFormat) { var sumTriangleCount = 0; var triangulations = new List <TriangulationData>(); foreach (var body in bodies) { var shape = body.Shape.GetTransformedBRep(); if (shape == null) { continue; } var triangulation = TriangulationHelper.GetTriangulation(shape, false); if (triangulation.TriangleCount == 0) { continue; } triangulations.Add(triangulation); sumTriangleCount += triangulation.TriangleCount; } if (sumTriangleCount == 0) { return(false); } IStlWriter writer; if (binaryFormat) { writer = new StlBinaryWriter(); } else { writer = new StlAsciiWriter(); } writer.Init("Written by Macad3D STL-Export", sumTriangleCount); foreach (var triangulation in triangulations) { var index = 0; for (int triangle = 0; triangle < triangulation.TriangleCount; triangle++) { // Get vertices var vertex1 = triangulation.Vertices[triangulation.Indices[index]]; var vertex2 = triangulation.Vertices[triangulation.Indices[index + 1]]; var vertex3 = triangulation.Vertices[triangulation.Indices[index + 2]]; index += 3; // Calculate normal of facet var vec1 = new Vec(vertex1, vertex2); var vec2 = new Vec(vertex1, vertex3); var normal = vec1.Crossed(vec2); if (normal.SquareMagnitude() > gp.Resolution) { normal.Normalize(); } else { normal = default; } // Write out facet writer.AddFacet(normal, vertex1, vertex2, vertex3); } } return(writer.WriteToFile(fileName)); }
public static bool Export(string fileName, IEnumerable <Body> bodies, bool smoothEdges) { ObjAsciiWriter writer = new ObjAsciiWriter(); writer.Init("Written by Macad3D OBJ-Export"); var indexOffset = 1; // OBJ list index starts with 1 var vertexMap = new Dictionary <Pnt, int>(); // Written vertex to resulting index var indexList = new List <int>(); foreach (var body in bodies) { var shape = body.Shape.GetTransformedBRep(); if (shape == null) { continue; } var triangulation = TriangulationHelper.GetTriangulation(shape, false); if (triangulation.TriangleCount == 0) { continue; } writer.AddObject(body.Name); if (smoothEdges) // Export smooth edges { for (var vtxIndex = 0; vtxIndex < triangulation.Vertices.Length; vtxIndex++) { var vertex = triangulation.Vertices[vtxIndex]; int newIndex; if (!vertexMap.TryGetValue(vertex, out newIndex)) { writer.AddVertex(vertex); newIndex = vertexMap.Count + indexOffset; vertexMap.Add(vertex, newIndex); } indexList.Add(newIndex); } for (int i = 0; i < triangulation.Indices.Length; i += 3) { writer.AddFace(indexList[triangulation.Indices[i]], indexList[triangulation.Indices[i + 1]], indexList[triangulation.Indices[i + 2]]); } } else // Export face by face { foreach (var vertex in triangulation.Vertices) { writer.AddVertex(vertex); } for (int i = 0; i < triangulation.Indices.Length; i += 3) { writer.AddFace(triangulation.Indices[i] + indexOffset, triangulation.Indices[i + 1] + indexOffset, triangulation.Indices[i + 2] + indexOffset); } } indexOffset += smoothEdges ? vertexMap.Count : triangulation.Vertices.Length; vertexMap.Clear(); // Don't share vertices between objects indexList.Clear(); } return(writer.WriteToFile(fileName)); }
//-------------------------------------------------------------------------------------------------- bool IBodyImporter.DoImport(string fileName, out IEnumerable <Body> bodies) { bodies = null; try { using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { var vertices = new List <Pnt>(); var currentObject = ObjectDescription.Create(); var objectDescList = new List <ObjectDescription>(); var reader = new ObjAsciiReader(fs); // Read string cmd; while (reader.MoveNext(out cmd)) { switch (cmd) { case "o": case "g": if (currentObject.Indices.Count != 0) { objectDescList.Add(currentObject); } currentObject = ObjectDescription.Create(); reader.GetObjectOrGroup(out currentObject.Name); break; case "v": if (!reader.GetVertex(out var vertex)) { return(false); } vertices.Add(vertex); break; case "f": case "fo": if (!reader.GetFace(out var indices)) { continue; } // Negative indices must be correctly re-assigned // -1 => vertices.Count // -2 => vertices.Count-1 for (int i = 0; i < indices.Length; i++) { if (indices[i] < 0) { indices[i] = vertices.Count + (indices[i] + 1); } } if (indices.Length == 3) { currentObject.Indices.AddRange(indices.Take(3).Select(index => index - 1)); // Correct lower bound (from 1 to 0) } else { var triangulator = new EarClippingTriangulator(); var result = triangulator.DoTriangulation(vertices, indices.Select(index => index - 1)); // Correct lower bound (from 1 to 0) if (result != null) { currentObject.Indices.AddRange(result); } } break; } } if (currentObject.Indices.Count != 0) { objectDescList.Add(currentObject); } // Create Faces foreach (var objectDesc in objectDescList) { // Extract used vertices var usedVertices = new List <Pnt>(); var indexMap = new Dictionary <int, int>(); for (int index = 0; index < objectDesc.Indices.Count; index++) { int newIndex; int oldIndex = objectDesc.Indices[index]; if (!indexMap.TryGetValue(oldIndex, out newIndex)) { newIndex = usedVertices.Count; usedVertices.Add(vertices[oldIndex]); indexMap.Add(oldIndex, newIndex); } objectDesc.Indices[index] = newIndex; } // Create shape objectDesc.Face = TriangulationHelper.CreateFaceFromTriangulation(new TriangulationData(objectDesc.Indices.ToArray(), usedVertices.ToArray())); } // Create bodies var bodyList = new List <Body>(); string bodyName = Path.GetFileNameWithoutExtension(fileName); if (Settings.ImportSingleBody) { var compound = new TopoDS_Compound(); var builder = new BRep_Builder(); builder.MakeCompound(compound); foreach (var objectDesc in objectDescList) { builder.Add(compound, objectDesc.Face); } var body = Body.Create(Mesh.Create(compound)); body.Name = bodyName; bodyList.Add(body); } else { int index = 1; foreach (var objectDesc in objectDescList) { var body = Body.Create(Mesh.Create(objectDesc.Face)); if (!objectDesc.Name.IsNullOrWhiteSpace()) { body.Name = objectDesc.Name; } else { body.Name = $"{bodyName}_{index++}"; } bodyList.Add(body); } } bodies = bodyList; // Cleanup fs.Close(); } return(true); } catch (Exception e) { Messages.Exception($"Exception occured while importing {fileName}.", e); return(false); } }
/// <summary> /// ctor /// </summary> public TwoDimensialTracker() { TriangulationHelper = new TriangulationHelper(); }