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 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 bool IsIllegalIntersection(int externalPoint, int unvisitedPoint, Vector3 curToExtLine) { for (int j = 0; j < triangles.Count; ++j) //For every triangle { if (triangles[j].isInternal == true) //If the triangle is internal we don't need to worry about it, so move onto the next triangle { continue; } for (int k = 0; k < 3; ++k) //For each line in that triangle { GameObject pointA = null; //Get the points at each end of the line GameObject pointB = null; if (k == 0) { pointA = triangles[j].points[0]; pointB = triangles[j].points[1]; } if (k == 1) { pointA = triangles[j].points[1]; pointB = triangles[j].points[2]; } if (k == 2) { pointA = triangles[j].points[2]; pointB = triangles[j].points[0]; } if (pointA.name == externalPoints[externalPoint].name || pointB.name == externalPoints[externalPoint].name) //If the line contains the external point we can ignore it { continue; } Vector2 intersection = MathsFunctions.IntersectionOfTwoLines(curToExtLine, triangles[j].lines[k]); //Get the intersection of the line with the current star to external point line if (MathsFunctions.PointLiesOnLine(externalPoints[externalPoint].transform.position, unvisitedStars[unvisitedPoint].transform.position, intersection)) //If the point lies elsewhere on the line { if (MathsFunctions.PointLiesOnLine(pointA.transform.position, pointB.transform.position, intersection)) { return(true); //This IS an illegal intersection so return that, otherwise keep checking } } } } return(false); }
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 CreateVoronoiCells() //This appears to be fine { MasterScript.triangulation.SimpleTriangulation(); for (int j = 0; j < MasterScript.systemListConstructor.systemList.Count; ++j) //For all systems { VoronoiCellVertices newCell = new VoronoiCellVertices(); //Create new voronoi cell Vector3 voronoiCentre = MasterScript.systemListConstructor.systemList[j].systemObject.transform.position; //Centre of voronoi cell is the current system location for (int i = 0; i < MasterScript.triangulation.triangles.Count; ++i) //For all triangles { if (MasterScript.triangulation.triangles[i].points.Contains(MasterScript.systemListConstructor.systemList[j].systemObject)) //If the triangle has the current system as one of it's vertices { Vector3 systemA = MasterScript.triangulation.triangles[i].points[0].transform.position; //System A equals this system Vector3 systemB = MasterScript.triangulation.triangles[i].points[1].transform.position; //System B is another point in the triangle Vector3 systemC = MasterScript.triangulation.triangles[i].points[2].transform.position; //System C is the final point in the triangle Vector3 lineAB = MathsFunctions.PerpendicularLineEquation(systemA, systemB); //Get the line equations of the line perpendicular to the midpoint between two points Vector3 lineBC = MathsFunctions.PerpendicularLineEquation(systemB, systemC); Vector3 voronoiVertex = MathsFunctions.IntersectionOfTwoLines(lineAB, lineBC); //One of the voronoi vertices is the circumcentre of the triangle float angle = MathsFunctions.RotationOfLine(voronoiVertex, voronoiCentre); //Get the angle of the vertex relative to the centre of the voronoi cell newCell.vertexAngles.Add(angle); //Add the angle to the cells angle list (this is to sort the vertices clockwise) newCell.vertices.Add(voronoiVertex); //Add the vertex to the cells vertex list } } voronoiVertices.Add(newCell); //Add the cell to the list of cells } for (int i = 0; i < voronoiVertices.Count; ++i) //For all voronoi cells { for (int j = voronoiVertices[i].vertexAngles.Count; j > 0; --j) //For all vertices in the cell { bool swapsMade = false; for (int k = 1; k < j; ++k) //While k is less than j (anything above current j value is sorted) { if (voronoiVertices[i].vertexAngles[k] < voronoiVertices[i].vertexAngles[k - 1]) //Sort smallest to largest { float tempAng = voronoiVertices[i].vertexAngles[k]; Vector3 tempPos = voronoiVertices[i].vertices[k]; voronoiVertices[i].vertexAngles[k] = voronoiVertices[i].vertexAngles[k - 1]; voronoiVertices[i].vertices[k] = voronoiVertices[i].vertices[k - 1]; voronoiVertices[i].vertexAngles[k - 1] = tempAng; voronoiVertices[i].vertices[k - 1] = tempPos; swapsMade = true; } } if (swapsMade == false) //If no swaps made, list must have been sorted { break; //So break } } for (int j = 1; j < voronoiVertices[i].vertices.Count; ++j) //For all the vertices { if (voronoiVertices[i].vertices[j] == voronoiVertices[i].vertices[j - 1]) //If there are duplicates { voronoiVertices[i].vertices.RemoveAt(j); //Remove one --j; } } } for (int i = 0; i < voronoiVertices.Count; ++i) //For all cells { GameObject newCell = new GameObject("Voronoi Cell"); //Create new gameobject newCell.AddComponent("MeshRenderer"); //Add meshrenderer to create a mesh newCell.AddComponent("MeshFilter"); //Add meshfilter to apply materials newCell.AddComponent("MeshCollider"); //Add meshcollider (why?) MeshFilter newMesh = (MeshFilter)newCell.GetComponent("MeshFilter"); //Get a reference to the meshfilter List <Vector3> vertices = new List <Vector3>(); //Create new list of vertices for (int j = 0; j < voronoiVertices[i].vertices.Count; ++j) //For all the voronoi cell's vertices { int nextVertex = j + 1; //Get the next vertex if (nextVertex == voronoiVertices[i].vertices.Count) { nextVertex = 0; } int prevVertex = j - 1; //Get the previous vertex if (prevVertex == -1) { prevVertex = voronoiVertices[i].vertices.Count - 1; } Vector3 lineA = voronoiVertices[i].vertices[prevVertex] - voronoiVertices[i].vertices[j]; //Line from vertex to next vertex Vector3 lineB = voronoiVertices[i].vertices[nextVertex] - voronoiVertices[i].vertices[j]; //Line from vertex to previous vertex Vector3 bisector = (lineA.normalized + lineB.normalized) / 2f; //Bisector line float yIntersect = voronoiVertices[i].vertices[j].y - (bisector.y / bisector.x) * voronoiVertices[i].vertices[j].x; //Cintersect = y - mx Vector3 bisectorIntersect = new Vector3(0f, yIntersect, 0f); //Get the y intersect of the bisector float vertAngle = MathsFunctions.AngleBetweenLineSegments(voronoiVertices[i].vertices[j], voronoiVertices[i].vertices[prevVertex], voronoiVertices[i].vertices[nextVertex]) / 2f; //Get the angle between the lines float hypotenuseLength = 0.5f / Mathf.Sin(vertAngle * Mathf.Deg2Rad); //Find the length of the hypotenuse (how far in the new vertex should be Vector3 dir = bisectorIntersect - voronoiVertices[i].vertices[j]; //Find the direction that the new vertex points to from the current vertex dir = bisector.normalized; //Normalise the direction vertices.Add(voronoiVertices[i].vertices[j]); //Add the original vertex to the new vertex list vertices.Add(voronoiVertices[i].vertices[j] + (dir * hypotenuseLength)); //Add this indented vertex to the new vertex list } for (int j = 0; j < vertices.Count; ++j) //For all the vertices { float x = vertices[j].x - MasterScript.systemListConstructor.systemList[i].systemObject.transform.position.x; //Set the x relative to the centre (used to be prevent the vertices being offset from the gameobject centre) float y = vertices[j].y - MasterScript.systemListConstructor.systemList[i].systemObject.transform.position.y; //Do the same for the y Vector3 newPos = new Vector3(x, y, 0f); vertices[j] = newPos; } newMesh.mesh.vertices = vertices.ToArray(); //Add the vertices to the mesh vertex list List <int> tris = new List <int>(); //Create new tris for (int j = 0; j < vertices.Count; ++j) //Create tris from the vertices { int nextVertex = j + 1; int afterNextVertex = j + 2; if (nextVertex == vertices.Count) { nextVertex = 0; afterNextVertex = 1; } if (afterNextVertex == vertices.Count) { afterNextVertex = 0; } if (j % 2 != 0) { tris.Add(afterNextVertex); tris.Add(nextVertex); tris.Add(j); } else { tris.Add(j); tris.Add(nextVertex); tris.Add(afterNextVertex); } } List <Vector2> uvs = new List <Vector2>(); for (int j = 0; j < newMesh.mesh.vertices.Length; ++j) { Vector2 uvCoordinate = new Vector2(newMesh.mesh.vertices[j].x, newMesh.mesh.vertices[j].z); uvs.Add(uvCoordinate); } newMesh.mesh.triangles = tris.ToArray(); newMesh.mesh.uv = uvs.ToArray(); newMesh.mesh.RecalculateNormals(); newMesh.mesh.RecalculateBounds(); newMesh.mesh.Optimize(); newCell.renderer.material = MasterScript.turnInfoScript.emptyMaterial; newCell.renderer.material.shader = Shader.Find("Transparent/Diffuse"); Color newColour = newCell.renderer.material.color; newColour = new Color(newColour.r, newColour.g, newColour.b, 0f); newCell.renderer.material.color = newColour; newCell.AddComponent <SystemRotate>(); newCell.name = "Voronoi Cell" + i.ToString(); newCell.tag = "VoronoiCell"; newCell.transform.position = new Vector3(MasterScript.systemListConstructor.systemList[i].systemObject.transform.position.x, MasterScript.systemListConstructor.systemList[i].systemObject.transform.position.y, 0f); newCell.transform.parent = voronoiCellContainer.transform; //voronoiCells.Add (newCell); } }