public void OneHundredSidedPolygon() { var polygonPerimeter = new PolygonPerimeter(); var answer = polygonPerimeter.Perimeter(100, 1.0); Assert.AreEqual(6.282, answer); }
public void Test() { var polygonPerimeter = new PolygonPerimeter(); var answer = polygonPerimeter.Perimeter(5, 3.7); Assert.AreEqual(21.748, answer); }
public static unsafe NativeHull CreateFromMesh(Mesh mesh) { var faces = new List <DetailedFaceDef>(); var verts = mesh.vertices.Select(RoundVertex).ToArray(); var uniqueVerts = verts.Distinct().ToList(); var indices = mesh.triangles; // Create faces from Triangles and collapse multiple vertices with same position into shared vertices. for (int i = 0; i < mesh.triangles.Length; i = i + 3) { var idx1 = i; var idx2 = i + 1; var idx3 = i + 2; Vector3 p1 = verts[indices[idx1]]; Vector3 p2 = verts[indices[idx2]]; Vector3 p3 = verts[indices[idx3]]; var normal = math.normalize(math.cross(p3 - p2, p1 - p2)); // Round normal so that faces with only slight variances can be grouped properly together. var roundedNormal = RoundVertex(normal); faces.Add(new DetailedFaceDef { Center = ((p1 + p2 + p3) / 3), Normal = roundedNormal, Verts = new List <float3> { p1, p2, p3 }, Indices = new List <int> { uniqueVerts.IndexOf(p1), uniqueVerts.IndexOf(p2), uniqueVerts.IndexOf(p3) } }); } var faceDefs = new List <NativeFaceDef>(); var orphanIndices = new HashSet <int>(); // Merge all faces with the same normal and shared vertex var mergedFaces = GroupBySharedVertex(GroupByNormal(faces)); foreach (var faceGroup in mergedFaces) { var indicesFromMergedFaces = faceGroup.SelectMany(face => face.Indices).ToArray(); // Collapse points inside the new combined face by using only the border vertices. var border = PolygonPerimeter.CalculatePerimeter(indicesFromMergedFaces, ref uniqueVerts); var borderIndices = border.Select(b => b.EndIndex).ToArray(); foreach (var idx in indicesFromMergedFaces.Except(borderIndices)) { orphanIndices.Add(idx); } var v = stackalloc int[borderIndices.Length]; int max = 0; for (int i = 0; i < borderIndices.Length; i++) { var idx = borderIndices[i]; if (idx > max) { max = idx; } v[i] = idx; } faceDefs.Add(new NativeFaceDef { HighestIndex = max, VertexCount = borderIndices.Length, Vertices = v, }); } // Remove vertices with no edges connected to them and fix all impacted face vertex references. foreach (var orphanIdx in orphanIndices.OrderByDescending(i => i)) { uniqueVerts.RemoveAt(orphanIdx); foreach (var face in faceDefs.Where(f => f.HighestIndex >= orphanIdx)) { for (int i = 0; i < face.VertexCount; i++) { var faceVertIdx = face.Vertices[i]; if (faceVertIdx >= orphanIdx) { face.Vertices[i] = --faceVertIdx; } } } } var result = new NativeHull(); using (var faceNative = new NativeArray <NativeFaceDef>(faceDefs.ToArray(), Allocator.Temp)) using (var vertsNative = new NativeArray <float3>(uniqueVerts.ToArray(), Allocator.Temp)) { NativeHullDef hullDef; hullDef.VertexCount = vertsNative.Length; hullDef.VerticesNative = vertsNative; hullDef.FaceCount = faceNative.Length; hullDef.FacesNative = faceNative; SetFromFaces(ref result, hullDef); } result.IsCreated = true; HullValidation.ValidateHull(result); return(result); }