static bool SpawnBuilding(Vector2 center, float direction, Quadtree quadtree, out Allotment allotment, List <Allotment> allotments) { allotment = new Allotment(default(Vector2), 0, UnityEngine.Random.Range(Config.allotmentMinHalfDiagonal, Config.allotmentMaxHalfDiagonal), UnityEngine.Random.Range(Config.allotmentMinAspect, Config.allotmentMaxAspect)); allotment.UpdateCenterAndDirection(center, direction); bool allow = false; for (int j = 0; j < Config.allotmentPlacementLoopLimit; j++) { int c = 0; Vector2 offset; var colliders = quadtree.Retrieve(allotment.GetCollider().GetAABB()); for (int k = 0; k < colliders.Count && (c == 0 || j < Config.allotmentPlacementLoopLimit - 1); k++) { if (allotment.GetCollider().Collide(((ICollidable)colliders[k].reference).GetCollider(), out offset)) { c++; allotment.Center = (allotment.Center + offset); } } for (int k = 0; k < allotments.Count && (c == 0 || j < Config.allotmentPlacementLoopLimit - 1); k++) { if (allotment.GetCollider().Collide(allotments[k].GetCollider(), out offset)) { c++; allotment.Center = (allotment.Center + offset); } } if (c == 0) { allow = true; break; } } return(allow); }
static bool LocalConstraints(Segment segment, List <Segment> segments, Quadtree quadtree, DebugData debugData) { int priority = 0; Func <bool> action = null; float t0 = -1; var matches = quadtree.Retrieve(segment); for (int i = 0, j = 0, k = matches.Count - 1; j <= k; i = j += 1) { Segment other = (Segment)matches[i].reference; if (segment == other) { continue; } // intersection check if (priority <= 4) { Vector2 intersection; float t1; if (segment.Intersect(other, out intersection, out t1)) { if (t0 == -1 || t1 < t0) { t0 = t1; priority = 4; action = () => { float dirDiff = Mathf.Abs(other.Direction - segment.Direction) % 180.0f; float minDirectionDiff = Mathf.Min(dirDiff, Mathf.Abs(dirDiff - 180.0f)); if (minDirectionDiff < Config.minIntersectionDeviation) { return(false); } IntersectSegments(intersection, other, segment, segments, quadtree); if (debugData != null) { debugData.intersections.Add(intersection); } return(true); }; } } } // snap to crossing within radius check if (priority <= 3) { if ((segment.End - other.End).magnitude <= Config.snapDistance) { priority = 3; action = () => { List <Segment> links; segment.End = other.End; segment.Severed = true; foreach (var destination in segment.Destinations) { int index = destination.Sources.IndexOf(other); if (index != -1) { continue; } destination.Sources.Add(other); } links = other.StartIsBackwards() ? other.Forwards : other.Branches; if (links.Any((Segment link) => { return(((link.Start == segment.End) && (link.End == segment.Start)) || ((link.Start == segment.Start) && (link.End == segment.End))); })) { return(false); } links.ForEach((Segment link) => { link.LinksForEndContaining(other).Add(segment); segment.Forwards.Add(link); }); links.Add(segment); segment.Forwards.Add(other); if (debugData != null) { debugData.snaps.Add(other.End); } return(true); }; } } // intersection within radius check if (priority <= 2) { var e0 = (segment.End - other.Start); var e1 = (other.End - other.Start); Vector2 proj = Vector3.Project(e0, e1); Vector2 pointOnLine = (other.Start + proj); float distance2 = Vector2.SqrMagnitude(segment.End - pointOnLine); float lineProj2 = Mathf.Sign(Vector3.Dot(e0, e1)) * Vector2.SqrMagnitude(proj); float length2 = Vector2.SqrMagnitude(e1); if (distance2 < Config.snapDistance * Config.snapDistance && lineProj2 >= 0 && lineProj2 <= length2) { Vector2 point; point = pointOnLine; priority = 2; action = () => { float dirDiff = Math.Abs(other.Direction - segment.Direction) % 180.0f; float minDirDiff = Math.Min(dirDiff, Math.Abs(dirDiff - 180.0f)); if (minDirDiff < Config.minIntersectionDeviation) { return(false); } IntersectSegments(point, other, segment, segments, quadtree); if (debugData != null) { debugData.intersectionsRadius.Add(point); } return(true); }; } } } if (action != null) { return(action()); } return(true); }