public bool IsValidConnection(GameObject thisSystem, GameObject targetSystem) //Returns true if no intersection { Vector3 lineA = MathsFunctions.ABCLineEquation(thisSystem.transform.position, targetSystem.transform.position); //Line equation from current system to target system Vector3 roughCentre = (thisSystem.transform.position + targetSystem.transform.position) / 2f; if (roughCentre.x < 65f && roughCentre.x > 55f) //If the intersection exists in the galactic core, ignore it { if (roughCentre.y < 65f && roughCentre.y > 55f) { return(false); } } for (int i = 0; i < coordinateList.Count; ++i) //For all existing connections { if (coordinateList[i].systemOne == thisSystem && coordinateList[i].systemTwo == targetSystem) //If a connection already exists between the current system and the target system, continue to the next connection { continue; } if (coordinateList[i].systemTwo == thisSystem && coordinateList[i].systemOne == targetSystem) //Continuation of above { continue; } if (coordinateList[i].systemOne == thisSystem || coordinateList[i].systemTwo == thisSystem) //If the connection contains this system it will not make intersections with the temporary connection { continue; } if (coordinateList[i].systemOne == targetSystem || coordinateList[i].systemTwo == targetSystem) //If the connection contains the target system it will not make intersections with the temporary connection { continue; } //if(CheckIfIntersectionCouldOccur(thisSystem, targetSystem, coordinateList[i].systemOne, coordinateList[i].systemTwo) == false) //{ // continue; // Vector3 lineB = MathsFunctions.ABCLineEquation(coordinateList[i].systemOne.transform.position, coordinateList[i].systemTwo.transform.position); //Get the line equation between of the connection Vector2 intersection = MathsFunctions.IntersectionOfTwoLines(lineA, lineB); //Find the intersection of the two lines if (intersection == Vector2.zero) //If the lines are parallel the method returns a zero vector continue to the next connection { continue; } if (MathsFunctions.PointLiesOnLine(thisSystem.transform.position, targetSystem.transform.position, intersection)) //If the intersection lies on the temporary connection { if (MathsFunctions.PointLiesOnLine(coordinateList[i].systemOne.transform.position, coordinateList[i].systemTwo.transform.position, intersection)) //And it lies on the current permanent connection { return(false); //Return true, an intersection does exist } } } return(true); }
public void Update() { if (MasterScript.systemListConstructor.loaded == true && iterator == 0) { //start = true; } if (start == true) { triangles.Clear(); tempTri.Clear(); unvisitedStars.Clear(); externalPoints.Clear(); CacheNearestStars(); //First add all the star systems to a list Triangle newTri = new Triangle(); //Create a new triangle newTri.points.Add(unvisitedStars [0]); //Add the first 3 ordered points from the centre newTri.points.Add(unvisitedStars [1]); newTri.points.Add(unvisitedStars[2]); newTri.lines.Add(MathsFunctions.ABCLineEquation(newTri.points[0].transform.position, newTri.points[1].transform.position)); //Calculate the line equations between the points newTri.lines.Add(MathsFunctions.ABCLineEquation(newTri.points[1].transform.position, newTri.points[2].transform.position)); newTri.lines.Add(MathsFunctions.ABCLineEquation(newTri.points[2].transform.position, newTri.points[0].transform.position)); externalPoints.Add(unvisitedStars [0]); //Add the points to the external points list externalPoints.Add(unvisitedStars [1]); externalPoints.Add(unvisitedStars [2]); triangles.Add(newTri); //Add the triangle to the triangle list unvisitedStars.RemoveRange(0, 3); //Remove the points from the unvisited points list start = false; iterate = true; timer = Time.time; } if (start == false && iterate == true) { if (iterator < unvisitedStars.Count) { LinkPointToTris(iterator); CacheTempTris(iterator); DrawDebugTriangles(); ++iterator; timer = Time.time; } if (iterator == unvisitedStars.Count) { DrawDebugTriangles(); iterate = false; } } }
public bool CheckIsDelaunay(Triangle triOne, Triangle triTwo) { List <GameObject> sharedSides = MasterScript.triangulation.CheckIfSharesSide(triOne, triTwo); //Find if triangles share a side (this actually returns the 2 shared and 2 unshared vertices) if (sharedSides.Count == 4) //If 4 vertices are shared { GameObject sharedPointA = sharedSides[0]; //Assign the shared points GameObject sharedPointB = sharedSides[1]; GameObject unsharedPointA = sharedSides[2]; //Assign the unshared points GameObject unsharedPointB = sharedSides[3]; float angleAlpha = 0f, angleBeta = 0f; //Set some angles to 0 angleAlpha = MathsFunctions.AngleBetweenLineSegments(unsharedPointA.transform.position, sharedPointA.transform.position, sharedPointB.transform.position); //First angle is at one unshared point angleBeta = MathsFunctions.AngleBetweenLineSegments(unsharedPointB.transform.position, sharedPointA.transform.position, sharedPointB.transform.position); //Second angle is at the other unshared point Vector3 sharedPointLine = MathsFunctions.ABCLineEquation(sharedPointA.transform.position, sharedPointB.transform.position); //Get the line between the shared points Vector3 unsharedPointLine = MathsFunctions.ABCLineEquation(unsharedPointA.transform.position, unsharedPointB.transform.position); //Get the line between the unshared points Vector2 intersection = MathsFunctions.IntersectionOfTwoLines(sharedPointLine, unsharedPointLine); //Find the intersection of the two lines if (MathsFunctions.PointLiesOnLine(sharedPointA.transform.position, sharedPointB.transform.position, intersection) == false) //If the intersection does not lie between the shared points then this is a non convex hull { return(true); //So it cannot be flipped, continue to the next triangle } if (angleAlpha + angleBeta > 180f) //If the polygon is convex, and the two angles combine to be greater than 180 degrees, the triangles are non delaunay, so we flip them { int triPosOne = MasterScript.triangulation.triangles.IndexOf(triOne); //Find the position of the two triangles in the triangles list int triPosTwo = MasterScript.triangulation.triangles.IndexOf(triTwo); triOne.points[0] = unsharedPointA; //Reassign the vertices of tri one to make the previously unshared vertices the shared vertices. One of the previously shared vertices is now the unshared vertex. triOne.points[1] = unsharedPointB; triOne.points[2] = sharedPointA; triOne.lines[0] = MathsFunctions.ABCLineEquation(triOne.points[0].transform.position, triOne.points[1].transform.position); //Get the line equations for all the sides triOne.lines[1] = MathsFunctions.ABCLineEquation(triOne.points[1].transform.position, triOne.points[2].transform.position); triOne.lines[2] = MathsFunctions.ABCLineEquation(triOne.points[2].transform.position, triOne.points[0].transform.position); MasterScript.triangulation.triangles[triPosOne] = triOne; //Replace the original triangle with this new, flipped triangle triTwo.points[0] = unsharedPointA; //Do the same for tri two triTwo.points[1] = unsharedPointB; triTwo.points[2] = sharedPointB; triTwo.lines[0] = MathsFunctions.ABCLineEquation(triTwo.points[0].transform.position, triTwo.points[1].transform.position); triTwo.lines[1] = MathsFunctions.ABCLineEquation(triTwo.points[1].transform.position, triTwo.points[2].transform.position); triTwo.lines[2] = MathsFunctions.ABCLineEquation(triTwo.points[2].transform.position, triTwo.points[0].transform.position); MasterScript.triangulation.triangles[triPosTwo] = triTwo; ++flips; //Increase the number of flips that have been made this pass. return(false); //Return false (a flip has been made) } } return(true); //Otherwise continue to the next triangle }
private void CheckForNonDelaunayTriangles() { List <Triangle> numberofnondelaunay = new List <Triangle>(); for (int i = 0; i < triangles.Count; ++i) { for (int j = 0; j < triangles.Count; ++j) { if (i == j) { continue; } List <GameObject> sharedSides = CheckIfSharesSide(triangles[i], triangles[j]); if (sharedSides.Count == 4) { GameObject sharedPointA = sharedSides[0]; GameObject sharedPointB = sharedSides[1]; GameObject unsharedPointA = sharedSides[2]; GameObject unsharedPointB = sharedSides[3]; float angleAlpha = 0f, angleBeta = 0f; angleAlpha = MathsFunctions.AngleBetweenLineSegments(unsharedPointA.transform.position, sharedPointA.transform.position, sharedPointB.transform.position); angleBeta = MathsFunctions.AngleBetweenLineSegments(unsharedPointB.transform.position, sharedPointA.transform.position, sharedPointB.transform.position); Vector3 sharedPointLine = MathsFunctions.ABCLineEquation(sharedPointA.transform.position, sharedPointB.transform.position); Vector3 unsharedPointLine = MathsFunctions.ABCLineEquation(unsharedPointA.transform.position, unsharedPointB.transform.position); Vector2 intersection = MathsFunctions.IntersectionOfTwoLines(sharedPointLine, unsharedPointLine); if (MathsFunctions.PointLiesOnLine(sharedPointA.transform.position, sharedPointB.transform.position, intersection) == false) //Is non-convex { continue; } if (angleBeta + angleAlpha > 180) { numberofnondelaunay.Add(triangles[i]); } } } } Debug.Log(numberofnondelaunay.Count + " | " + triangles.Count); }
public void SimpleTriangulation() //This function controls the triangulation and conversion to delaunay of the stars { CacheNearestStars(); //First add all the star systems to a list Triangle newTri = new Triangle(); //Create a new triangle newTri.points.Add(unvisitedStars [0]); //Add the first 3 ordered points from the centre newTri.points.Add(unvisitedStars [1]); newTri.points.Add(unvisitedStars[2]); newTri.lines.Add(MathsFunctions.ABCLineEquation(newTri.points[0].transform.position, newTri.points[1].transform.position)); //Calculate the line equations between the points newTri.lines.Add(MathsFunctions.ABCLineEquation(newTri.points[1].transform.position, newTri.points[2].transform.position)); newTri.lines.Add(MathsFunctions.ABCLineEquation(newTri.points[2].transform.position, newTri.points[0].transform.position)); externalPoints.Add(unvisitedStars [0]); //Add the points to the external points list externalPoints.Add(unvisitedStars [1]); externalPoints.Add(unvisitedStars [2]); triangles.Add(newTri); //Add the triangle to the triangle list unvisitedStars.RemoveRange(0, 3); //Remove the points from the unvisited points list for (int i = 0; i < unvisitedStars.Count; ++i) //For all unchecked points { LinkPointToTris(i); //Link this unvisited point to all possible external points CacheTempTris(i); //Add all the triangles formed by this linking to the triangle list } bool isDelaunay = false; //Say that the list isn't delaunay while (isDelaunay == false) //While it isn't delaunay { isDelaunay = MasterScript.voronoiGenerator.TriangulationToDelaunay(); //Make it delaunay, if the method returns true, the triangulation is delaunay and the while loop will stop } CheckForNonDelaunayTriangles(); //Debugging method outputs the number of non-delaunay triangles to the log. This has not output any bad values for some time. }
private void LinkPointToTris(int curPoint) //Send the current unvisited star as the seed point SOMETHING WRONG { for (int i = 0; i < externalPoints.Count; ++i) //For all the external points { int nextPoint = i + 1; //Assign the next point if (nextPoint == externalPoints.Count) //If the next point is out of range { nextPoint = 0; //Set it to the first point in the list } Vector3 lineCurToExternal = MathsFunctions.ABCLineEquation(unvisitedStars[curPoint].transform.position, externalPoints[i].transform.position); //Create a line between the external point and the unvisited star if (IsIllegalIntersection(i, curPoint, lineCurToExternal)) //If there is an illegal intersection between the external point-current point line and the external point-unvisited point line { continue; //Move onto the next external point } Vector3 lineCurToNextExternal = MathsFunctions.ABCLineEquation(unvisitedStars[curPoint].transform.position, externalPoints[nextPoint].transform.position); if (IsIllegalIntersection(nextPoint, curPoint, lineCurToNextExternal)) //If there is an illegal intersection between the next point-current point line and the external point-unvisited point line { continue; //Move onto the next external point } bool illegal = false; //Say that the line is not illegal for (int j = 0; j < externalPoints.Count; ++j) //Check through all other external points { if (j == i || j == nextPoint) { continue; } if (MathsFunctions.IsInTriangle(externalPoints[i].transform.position, externalPoints[nextPoint].transform.position, unvisitedStars[curPoint].transform.position, externalPoints[j].transform.position) == true) //If the point lies in any of the triangles { //if(MathsFunctions.PointsAreColinear(externalPoints[i].transform.position, externalPoints[nextPoint].transform.position, externalPoints[j].transform.position) == false) //{ //if(MathsFunctions.PointsAreColinear(externalPoints[i].transform.position, unvisitedStars[curPoint].transform.position, externalPoints[j].transform.position) == false) //{ //if(MathsFunctions.PointsAreColinear(externalPoints[nextPoint].transform.position, unvisitedStars[curPoint].transform.position, externalPoints[j].transform.position) == false) //{ illegal = true; //It is an illegal triangle break; // //} //} //} } } if (illegal) //If it's an illegal triangle { continue; //Skip to the next point } GameObject pointA = externalPoints[i]; //Otherwise assign the points of the triangle GameObject pointB = externalPoints[nextPoint]; GameObject pointC = unvisitedStars[curPoint]; Triangle newTri = new Triangle(); //Create a new triangle object newTri.points.Add(pointA); //Add the points newTri.points.Add(pointB); newTri.points.Add(pointC); newTri.lines.Add(MathsFunctions.ABCLineEquation(pointA.transform.position, pointB.transform.position)); //Calculate the line equations between the points newTri.lines.Add(MathsFunctions.ABCLineEquation(pointB.transform.position, pointC.transform.position)); newTri.lines.Add(MathsFunctions.ABCLineEquation(pointC.transform.position, pointA.transform.position)); tempTri.Add(newTri); //Add the triangle to the temptriangle list } }