public static EdgeType[] GetPolygonEdges(int sides, float radius, float radiusRandomness, float randomnessRangeDetail, ILinkedGraphEdgeFactory <EdgeType> factory, System.Object[] factoryParams) { LinkedGraphVertex[] verts = new LinkedGraphVertex[sides]; EdgeType[] edges = new EdgeType[sides]; float noiseOffset = Random.value * 10000f; for (int i = 0; i < sides; i++) { float t = (i / (float)sides); float angle = t * Mathf.PI * 2; Vector2 unitCircle = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); Vector2 position = unitCircle * radius; float noise = Mathf.PerlinNoise(position.x / randomnessRangeDetail + noiseOffset, position.y / randomnessRangeDetail) - 0.5f; Vector2 modPosition = unitCircle * (radius + noise * radiusRandomness); verts[i] = new LinkedGraphVertex(modPosition); } for (int i = 0; i < sides; i++) { int firstVertInd = i; int secondVertInd = (i + 1) % sides; edges[i] = factory.GetEdge(verts[firstVertInd], verts[secondVertInd], factoryParams); } return(edges); }
private static void DebugVert(LinkedGraphVertex vert) { Random.InitState(vert.GetHashCode()); Color vCol = Color.red; float len = 2f; if (vert.connections.Count == 1) { len = 10f; } else if (vert.connections.Count == 2) { vCol = Color.green; } else if (vert.connections.Count == 3) { vCol = Color.yellow; } else if (vert.connections.Count == 4) { vCol = Color.black; } else if (vert.connections.Count == 5) { vCol = Color.white; } else if (vert.connections.Count > 5) { vCol = Color.gray; } Debug.DrawLine(HelperFunctions.projVec2(vert.pt), HelperFunctions.projVec2(vert.pt) + (Vector3.up + new Vector3(Random.Range(-0.3f, 0.3f), 0, 0)) * len, vCol); }
//check to see if an edge in this loop follows the ccw public bool EdgeFollowsWinding(EdgeType edge) { int ind = edges.IndexOf(edge); if (ind == -1) { Debug.Log("Could not calculate if edge follows winding. Not part of loop."); return(false); } //get the vertex on first edge that is shared by the first two edges LinkedGraphVertex lastVertex = edges[0].GetSharedVertex(edges[1]); for (int i = 0; i < edges.Count; i++) { if (i > 0) { lastVertex = edges[i].GetOppositeVertex(lastVertex); } if (i == ind && edges[i].b == lastVertex) { return(true); } } return(false); }
public EdgeLoop(Vector2[] points, ILinkedGraphEdgeFactory <EdgeType> factory, Object[] factoryParams) { LinkedGraphVertex[] verts = new LinkedGraphVertex[points.Length]; for (int i = 0; i < verts.Length; i++) { verts[i] = new LinkedGraphVertex(points[i]); } EdgeType[] newEdges = new EdgeType[points.Length]; for (int i = 0; i < verts.Length; i++) { newEdges[i] = factory.GetEdge(verts[i], verts[(i + 1) % points.Length], factoryParams);//new EdgeLoopEdge(verts[i], verts[(i + 1) % points.Length]); } this.edges = new List <EdgeType>(newEdges); RecalculateBounds(); if (!Verify()) { Debug.LogWarning("Edge loop edges do not form a loop."); } foreach (EdgeType edge in edges) { edge.AddEdgeSplitListener(this); } }
public static EdgeType AddEdge(LinkedGraphVertex aVert, LinkedGraphVertex bVert, ILinkedGraphEdgeFactory <EdgeType> edgeFactory, System.Object[] factoryParams, List <EdgeType> knownEdges) { EdgeType newEdge = edgeFactory.GetEdge(aVert, bVert, factoryParams); if (knownEdges != null) { knownEdges.Add(newEdge); } return(newEdge); }
public LinkedGraphEdge(LinkedGraphVertex a, LinkedGraphVertex b) { this.a = a; this.b = b; segRef = new Segment(); segRef.a = a.pt; segRef.b = b.pt; a.AddConnection(this); b.AddConnection(this); listeners = new List <IEdgeSplitListener>(); }
//given a list of edges, check if the vertex at pt already exists public static LinkedGraphVertex HasVertex(List <EdgeType> inEdges, Vector2 pt) { LinkedGraphVertex matchingVert = null; EnumerateVertices(inEdges, (LinkedGraphVertex vert) => { if ((vert.pt - pt).sqrMagnitude < VERT_MERGE_DIST_SQR) { matchingVert = vert; } }); return(matchingVert); }
public static void SubdivideEdge(EdgeType edge, LinkedGraphVertex midPoint, ILinkedGraphEdgeFactory <EdgeType> edgeFactory, List <EdgeType> knownEdges) { LinkedGraphVertex aVert = edge.a; LinkedGraphVertex bVert = edge.b; EdgeType aEdge = AddEdge(aVert, midPoint, edgeFactory, null, knownEdges); EdgeType bEdge = AddEdge(midPoint, bVert, edgeFactory, null, knownEdges); edge.OnEdgeSplit(aEdge, bEdge); knownEdges.Remove(edge); Detach(edge); }
public CityEdge GetEdge(LinkedGraphVertex a, LinkedGraphVertex b, System.Object[] data) { if (data == null) { return(new CityEdge(a, b, CityEdgeType.Unspecified, 1f)); } else { if (data.Length >= 2 && data[0] is CityEdgeType && data[1] is float) { return(new CityEdge(a, b, (CityEdgeType)data[0], (float)data[1])); } Debug.LogWarning("Bad data for creating CityEdge"); return(new CityEdge(a, b, CityEdgeType.Unspecified, 2f)); } }
public LinkedGraphVertex GetOppositeVertex(LinkedGraphVertex vertex) { if (a != vertex && b != vertex) { Debug.LogWarning("Can't get opposite vertex."); return(null); } else { if (a == vertex) { return(b); } else { return(a); } } }
public void AddConnection(LinkedGraphEdge connection) { int insertIndex = 0; LinkedGraphVertex otherVert = connection.GetOppositeVertex(this); float newAngle = HelperFunctions.AngleBetween(otherVert.pt - pt, Vector2.right) % (Mathf.PI * 2); for (int i = 0; i < connections.Count; i++) { LinkedGraphVertex thisOppositeVert = connections[i].GetOppositeVertex(this); float existingAngle = HelperFunctions.AngleBetween(thisOppositeVert.pt - pt, Vector2.right) % (Mathf.PI * 2); if (newAngle < existingAngle) { insertIndex++; } else { break; } } connections.Insert(insertIndex, connection); }
//given a list of edges that may intersect with the new edge, connect the new edge public static void ConnectNewEdge(Vector2 a, Vector2 b, ILinkedGraphEdgeFactory <EdgeType> edgeFactory, System.Object[] factoryParams, List <EdgeType> knownEdges) { LinkedGraphVertex aVert = HasVertex(knownEdges, a); LinkedGraphVertex bVert = HasVertex(knownEdges, b); if (aVert != null && bVert != null && aVert == bVert || (a - b).sqrMagnitude < VERT_MERGE_DIST_SQR) { return; } if (aVert == null) { aVert = new LinkedGraphVertex(a); } if (bVert == null) { bVert = new LinkedGraphVertex(b); } if (knownEdges == null || knownEdges.Count == 0) { AddEdge(aVert, bVert, edgeFactory, factoryParams, knownEdges); return; } //use for checking intersections Segment testingSegment = Segment.SegmentWithPoints(a, b); Rect testingSegBounds = testingSegment.ExpandedBounds(VERT_MERGE_DIST_SQR); List <LinkedGraphVertex> intersectionVertices = new List <LinkedGraphVertex>(); intersectionVertices.Add(aVert);//these will be sorted later intersectionVertices.Add(bVert); EdgeType[] edgesCopy = new EdgeType[knownEdges.Count]; knownEdges.CopyTo(edgesCopy); //check if new vertices are on another line foreach (EdgeType seg in edgesCopy) { if (!seg.segRef.bounds.Overlaps(testingSegBounds)) { continue; } if (seg.a == aVert || seg.a == bVert || seg.b == aVert || seg.b == bVert) { //do nothing in this case. //this is captured in the base case of finding existing verts } else if (seg.segRef.ContainsPoint(a, VERT_MERGE_DIST_SQR)) { SubdivideEdge(seg, aVert, edgeFactory, knownEdges); } else if (seg.segRef.ContainsPoint(b, VERT_MERGE_DIST_SQR)) { SubdivideEdge(seg, bVert, edgeFactory, knownEdges); } else if (testingSegment.ContainsPoint(seg.a.pt, VERT_MERGE_DIST_SQR)) { intersectionVertices.Add(seg.a); } else if (testingSegment.ContainsPoint(seg.b.pt, VERT_MERGE_DIST_SQR)) { intersectionVertices.Add(seg.b); } else { Vector2 intersectionPoint = Vector2.zero; if (seg.segRef.IntersectionWithSegment(testingSegment, out intersectionPoint)) { LinkedGraphVertex midPtVert = new LinkedGraphVertex(intersectionPoint); SubdivideEdge(seg, midPtVert, edgeFactory, knownEdges); intersectionVertices.Add(midPtVert); } } } Vector2 sortDirection = b - a; intersectionVertices.Sort((first, second) => (first.pt - a).sqrMagnitude.CompareTo( (second.pt - a).sqrMagnitude)); for (int i = 0; i < intersectionVertices.Count - 1; i++) { AddEdge(intersectionVertices[i], intersectionVertices[i + 1], edgeFactory, factoryParams, knownEdges); } }
public static EdgeType AddEdge(LinkedGraphVertex aVert, LinkedGraphVertex bVert, ILinkedGraphEdgeFactory <EdgeType> edgeFactory, List <EdgeType> knownEdges) { return(AddEdge(aVert, bVert, edgeFactory, null, knownEdges)); }
public List <EdgeType> GetLocalLoop(EdgeType startingEdge, bool ccw) { List <EdgeType> foundEdges = new List <EdgeType>(); foundEdges.Add(startingEdge); LinkedGraphVertex firstVertex = startingEdge.a; LinkedGraphVertex lastVertex = startingEdge.b; bool foundLoop = false; int edgesSeen = 0; while (!foundLoop) { EdgeLoopEdge lastEdge = foundEdges[foundEdges.Count - 1]; Vector2 lastEdgeDirection = lastEdge.GetOppositeVertex(lastVertex).pt - lastVertex.pt; float minAngle = float.MaxValue; EdgeType minAngleEdge = null; if (lastVertex.NumConnections() <= 1) { Debug.LogWarning("Reached end of loop while collecting loop."); return(null); } foreach (LinkedGraphEdge connection in lastVertex.GetConnections()) { if (connection == lastEdge) { continue;//ignore the connection if it is this instance. } //all connections must share lastVertex with lastEdge Vector2 thisEdgeDirection = connection.GetOppositeVertex(lastVertex).pt - lastVertex.pt; float angle = HelperFunctions.AngleBetween(thisEdgeDirection, lastEdgeDirection); if (!ccw) { //we want to invert the smallest angle when its cw since angleBetween gets the ccw angle angle = Mathf.PI * 2 - angle; } if (angle < minAngle) { if (connection is EdgeType) { minAngle = angle; minAngleEdge = (EdgeType)connection; } else { Debug.LogWarning("Could not isolate loop because connected edges were not EdgeLoopEdges"); } } edgesSeen++; if (edgesSeen > MAXLOOPSIZE) { Debug.LogWarning("Couldn't close loop. Failing"); DebugLines debug = GameObject.FindObjectOfType <DebugLines>(); foreach (EdgeType edge in foundEdges) { debug.AddEdge(edge, Color.red); } return(null); } } foundEdges.Add(minAngleEdge); lastVertex = minAngleEdge.GetOppositeVertex(lastVertex); if (lastVertex == firstVertex) { foundLoop = true; } } //maintain the loops go ccw paradigm if (!ccw) { foundEdges.Reverse(); } return(foundEdges); }
public CityEdge(LinkedGraphVertex a, LinkedGraphVertex b, CityEdgeType type, float width) : base(a, b) { this.type = type; this.id = getID(); this.width = width; }
public EdgeLoopEdge(LinkedGraphVertex a, LinkedGraphVertex b) : base(a, b) { }
public EdgeLoopEdge GetEdge(LinkedGraphVertex a, LinkedGraphVertex b, System.Object[] data) { return(new EdgeLoopEdge(a, b)); }