//List<VoronoiCell2> public static List <VoronoiCell2> UnNormalize(List <VoronoiCell2> data, AABB2 aabb, float dMax) { List <VoronoiCell2> unNormalizedData = new List <VoronoiCell2>(); foreach (VoronoiCell2 cell in data) { MyVector2 sitePosUnNormalized = HelpMethods.UnNormalize(cell.sitePos, aabb, dMax); VoronoiCell2 cellUnNormalized = new VoronoiCell2(sitePosUnNormalized); foreach (VoronoiEdge2 e in cell.edges) { MyVector2 p1UnNormalized = HelpMethods.UnNormalize(e.p1, aabb, dMax); MyVector2 p2UnNormalized = HelpMethods.UnNormalize(e.p2, aabb, dMax); VoronoiEdge2 eUnNormalized = new VoronoiEdge2(p1UnNormalized, p2UnNormalized, sitePosUnNormalized); cellUnNormalized.edges.Add(eUnNormalized); } unNormalizedData.Add(cellUnNormalized); } return(unNormalizedData); }
// // Algorithms that test if we can form a convex hull // private static bool CanFormConvexHull(List <MyVector2> points) { //First test of we can form a convex hull //If fewer points, then we cant create a convex hull if (points.Count < 3) { Debug.Log("Too few points co calculate a convex hull"); return(false); } //Find the bounding box of the points //If the spread is close to 0, then they are all at the same position, and we cant create a hull AABB box = HelpMethods.GetAABB(points); if (Mathf.Abs(box.maxX - box.minX) < MathUtility.EPSILON || Mathf.Abs(box.maxY - box.minY) < MathUtility.EPSILON) { Debug.Log("The points cant form a convex hull"); return(false); } return(true); }
//For debugging private static void DisplayPoints(HashSet <MyVector2> points, AABB2 normalizingbox, float dMax) { foreach (MyVector2 p in points) { MyVector2 pUnNormalize = HelpMethods.UnNormalize(p, normalizingbox, dMax); Debug.DrawLine(pUnNormalize.ToVector3(), Vector3.zero, Color.blue, 3f); } }
//HalfEdgeData2 public static HalfEdgeData2 UnNormalize(HalfEdgeData2 data, AABB2 aabb, float dMax) { foreach (HalfEdgeVertex2 v in data.vertices) { MyVector2 vUnNormalized = HelpMethods.UnNormalize(v.position, aabb, dMax); v.position = vUnNormalized; } return(data); }
//HashSet<Triangle2> public static HashSet <Triangle2> UnNormalize(HashSet <Triangle2> normalized, AABB2 aabb, float dMax) { HashSet <Triangle2> unNormalized = new HashSet <Triangle2>(); foreach (Triangle2 t in normalized) { MyVector2 p1 = HelpMethods.UnNormalize(t.p1, aabb, dMax); MyVector2 p2 = HelpMethods.UnNormalize(t.p2, aabb, dMax); MyVector2 p3 = HelpMethods.UnNormalize(t.p3, aabb, dMax); Triangle2 tUnNormalized = new Triangle2(p1, p2, p3); unNormalized.Add(tUnNormalized); } return(unNormalized); }
//Calculate the angle between the vectors if we are going from p1-p2-p3 //Return +180 if "small" or -180 if "large" //public static float CalculateAngleBetweenVectors(MyVector2 p1, MyVector2 p2, MyVector2 p3) //{ // MyVector2 from = p1 - p2; // MyVector2 to = p3 - p2; // float angle = Vector2.SignedAngle(from, to); // return angle; //} //Create a supertriangle that contains all other points //According to the book "Geometric tools for computer graphics" a reasonably sized triangle //is one that contains a circle that contains the axis-aligned bounding rectangle of the points //Is currently not used anywhere because our points are normalized to the range 0-1 //and then we can make a supertriangle by just setting its size to 100 public static Triangle2 GenerateSupertriangle(HashSet <MyVector2> points) { //Step 1. Create a AABB around the points AABB aabb = HelpMethods.GetAABB(new List <MyVector2>(points)); MyVector2 TL = new MyVector2(aabb.minX, aabb.maxY); MyVector2 TR = new MyVector2(aabb.maxX, aabb.maxY); MyVector2 BR = new MyVector2(aabb.maxX, aabb.minY); //Step2. Find the inscribed circle - the smallest circle that surrounds the AABB MyVector2 circleCenter = (TL + BR) * 0.5f; float circleRadius = MyVector2.Magnitude(circleCenter - TR); //Step 3. Create the smallest triangle that surrounds the circle //All edges of this triangle have the same length float halfSideLenghth = circleRadius / Mathf.Tan(30f * Mathf.Deg2Rad); //The center position of the bottom-edge MyVector2 t_B = new MyVector2(circleCenter.x, circleCenter.y - circleRadius); MyVector2 t_BL = new MyVector2(t_B.x - halfSideLenghth, t_B.y); MyVector2 t_BR = new MyVector2(t_B.x + halfSideLenghth, t_B.y); //The height from the bottom edge to the top vertex float triangleHeight = halfSideLenghth * Mathf.Tan(60f * Mathf.Deg2Rad); MyVector2 t_T = new MyVector2(circleCenter.x, t_B.y + triangleHeight); //The final triangle Triangle2 superTriangle = new Triangle2(t_BR, t_BL, t_T); return(superTriangle); }
// // Triangle to half-edge // public static HalfEdgeData2 Triangle2ToHalfEdge2(HashSet <Triangle2> triangles, HalfEdgeData2 data) { //Make sure the triangles have the same orientation, which is clockwise triangles = HelpMethods.OrientTrianglesClockwise(triangles); //Fill the data structure foreach (Triangle2 t in triangles) { HalfEdgeVertex2 v1 = new HalfEdgeVertex2(t.p1); HalfEdgeVertex2 v2 = new HalfEdgeVertex2(t.p2); HalfEdgeVertex2 v3 = new HalfEdgeVertex2(t.p3); //The vertices the edge points to HalfEdge2 he1 = new HalfEdge2(v1); HalfEdge2 he2 = new HalfEdge2(v2); HalfEdge2 he3 = new HalfEdge2(v3); he1.nextEdge = he2; he2.nextEdge = he3; he3.nextEdge = he1; he1.prevEdge = he3; he2.prevEdge = he1; he3.prevEdge = he2; //The vertex needs to know of an edge going from it v1.edge = he2; v2.edge = he3; v3.edge = he1; //The face the half-edge is connected to HalfEdgeFace2 face = new HalfEdgeFace2(he1); //Each edge needs to know of the face connected to this edge he1.face = face; he2.face = face; he3.face = face; //Add everything to the lists data.edges.Add(he1); data.edges.Add(he2); data.edges.Add(he3); data.faces.Add(face); data.vertices.Add(v1); data.vertices.Add(v2); data.vertices.Add(v3); } //Step 4. Find the half-edges going in the opposite direction of each edge we have //Is there a faster way to do this because this is the bottleneck? foreach (HalfEdge2 e in data.edges) { HalfEdgeVertex2 goingToVertex = e.v; HalfEdgeVertex2 goingFromVertex = e.prevEdge.v; foreach (HalfEdge2 eOther in data.edges) { //Dont compare with itself if (e == eOther) { continue; } //Is this edge going between the vertices in the opposite direction if (goingFromVertex.position.Equals(eOther.v.position) && goingToVertex.position.Equals(eOther.prevEdge.v.position)) { e.oppositeEdge = eOther; break; } } } return(data); }