//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); }
// // Are two Axis-aligned-bounding-box (boxes are here rectangles) intersecting? // //2d public static bool AABB_AABB(AABB2 r1, AABB2 r2) { //If the min of one box in one dimension is greater than the max of another box then the boxes are not intersecting //They have to intersect in 2 dimensions. We have to test if box 1 is to the left or box 2 and vice versa bool isIntersecting = true; //X axis ///r1_minX - the smallest x-coordinate of all corners belonging to rectangle 1 if (r1.min.x > r2.max.x) { isIntersecting = false; } else if (r2.min.x > r1.max.x) { isIntersecting = false; } //Y axis else if (r1.min.y > r2.max.y) { isIntersecting = false; } else if (r2.min.y > r1.max.y) { isIntersecting = false; } return(isIntersecting); }
// // 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 AABB2 box = new AABB2(points); if (Mathf.Abs(box.max.x - box.min.x) < MathUtility.EPSILON || Mathf.Abs(box.max.y - box.min.y) < MathUtility.EPSILON) { Debug.Log("The points cant form a convex hull"); return(false); } return(true); }
// // Are two Axis-aligned-bounding-box (boxes are here rectangles) intersecting? // //r1_minX - the smallest x-coordinate of all corners belonging to rectangle 1 public static bool AABB_AABB_2D(AABB2 r1, AABB2 r2) { //If the min of one box in one dimension is greater than the max of another box then the boxes are not intersecting //They have to intersect in 2 dimensions. We have to test if box 1 is to the left or box 2 and vice versa bool isIntersecting = true; //X axis if (r1.minX > r2.maxX) { isIntersecting = false; } else if (r2.minX > r1.maxX) { isIntersecting = false; } //Y axis else if (r1.minY > r2.maxY) { isIntersecting = false; } else if (r2.minY > r1.maxY) { isIntersecting = false; } return(isIntersecting); }
// // Algorithms that test if we can form a convex hull // private static bool CanFormConvexHull_2d(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 AABB2 rectangle = new AABB2(points); if (!rectangle.IsRectangleARectangle()) { Debug.Log("The points cant form a convex hull"); return(false); } return(true); }
//Normalize stuff //MyVector2 public static MyVector2 Normalize(MyVector2 point, AABB2 boundingBox, float dMax) { float x = (point.x - boundingBox.minX) / dMax; float y = (point.y - boundingBox.minY) / dMax; MyVector2 pNormalized = new MyVector2(x, y); return(pNormalized); }
//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); } }
//UnNormalize different stuff //MyVector2 public static MyVector2 UnNormalize(MyVector2 point, AABB2 boundingBox, float dMax) { float x = (point.x * dMax) + boundingBox.minX; float y = (point.y * dMax) + boundingBox.minY; MyVector2 pUnNormalized = new MyVector2(x, y); return(pUnNormalized); }
//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<MyVector2> public static HashSet <MyVector2> Normalize(HashSet <MyVector2> points, AABB2 boundingBox, float dMax) { HashSet <MyVector2> normalizedPoints = new HashSet <MyVector2>(); foreach (MyVector2 p in points) { normalizedPoints.Add(Normalize(p, boundingBox, dMax)); } return(normalizedPoints); }
//List<MyVector2> public static List <MyVector2> UnNormalize(List <MyVector2> normalized, AABB2 aabb, float dMax) { List <MyVector2> unNormalized = new List <MyVector2>(); foreach (MyVector2 p in normalized) { MyVector2 pUnNormalized = UnNormalize(p, aabb, dMax); unNormalized.Add(pUnNormalized); } 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 AABB2 aabb = new AABB2(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); }
// // Are two triangles intersecting in 2d space // public static bool TriangleTriangle2D(Triangle2 t1, Triangle2 t2, bool do_AABB_test) { bool isIntersecting = false; //Step 0. AABB intersection which may speed up the algorithm if the triangles are far apart if (do_AABB_test) { //Rectangle that covers t1 AABB2 r1 = new AABB2(t1.MinX(), t1.MaxX(), t1.MinY(), t1.MaxY()); //Rectangle that covers t2 AABB2 r2 = new AABB2(t2.MinX(), t2.MaxX(), t2.MinY(), t2.MaxY()); if (!AABB_AABB_2D(r1, r2)) { return(false); } } //Step 1. Line-line instersection //Line 1 of t1 against all lines of t2 if ( LineLine(t1.p1, t1.p2, t2.p1, t2.p2, true) || LineLine(t1.p1, t1.p2, t2.p2, t2.p3, true) || LineLine(t1.p1, t1.p2, t2.p3, t2.p1, true) ) { isIntersecting = true; } //Line 2 of t1 against all lines of t2 else if ( LineLine(t1.p2, t1.p3, t2.p1, t2.p2, true) || LineLine(t1.p2, t1.p3, t2.p2, t2.p3, true) || LineLine(t1.p2, t1.p3, t2.p3, t2.p1, true) ) { isIntersecting = true; } //Line 3 of t1 against all lines of t2 else if ( LineLine(t1.p3, t1.p1, t2.p1, t2.p2, true) || LineLine(t1.p3, t1.p1, t2.p2, t2.p3, true) || LineLine(t1.p3, t1.p1, t2.p3, t2.p1, true) ) { isIntersecting = true; } //Now we can return if we are intersecting so we dont need to spend time testing something else if (isIntersecting) { return(isIntersecting); } //Step 2. Point-in-triangle intersection //We only need to test one corner from each triangle //If this point is not in the triangle, then the other points can't be in the triangle, because if this point is outside //and another point is inside, then the line between them would have been covered by step 1: line-line intersections test if (PointTriangle(t2, t1.p1, true) || PointTriangle(t1, t2.p1, true)) { isIntersecting = true; } return(isIntersecting); }
//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); }
// // Normalize points to the range (0 -> 1) // //From "A fast algorithm for constructing Delaunay triangulations in the plane" by Sloan //boundingBox is the rectangle that covers all original points before normalization public static float CalculateDMax(AABB2 boundingBox) { float dMax = Mathf.Max(boundingBox.maxX - boundingBox.minX, boundingBox.maxY - boundingBox.minY); return(dMax); }
//From "A fast algorithm for constructing Delaunay triangulations in the plane" by Sloan //boundingBox is the rectangle that covers all original points before normalization public float CalculateDMax(AABB2 boundingBox) { float dMax = Mathf.Max(boundingBox.max.x - boundingBox.min.x, boundingBox.max.y - boundingBox.min.y); return(dMax); }
public Normalizer2(List <MyVector2> points) { this.boundingBox = new AABB2(points); this.dMax = CalculateDMax(this.boundingBox); }