public LinkModel AddLink(Faction faction, KeyInventoryModel inventory, PortalModel source, PortalModel target) { string message; if (IsLinkableSource(faction, source, out message) && IsLinkableTarget(faction, inventory, source, target, out message)) { LinkModel newLink = new LinkModel(source, target); links.Add(newLink); source.NumberOfLinks++; target.NumberOfLinks++; return(newLink); } else { throw new Exception(message); } }
public bool IsLinkableTarget(Faction faction, KeyInventoryModel inventory, PortalModel source, PortalModel target, out string message) { if (source == target) { message = string.Format("Source portal {0} is also the target portal.", source); return(false); } if (target.Faction != faction) { message = string.Format("Target portal {0} is an enemy portal.", target); return(false); } if (!inventory.HasKey(target)) { message = string.Format("No key for target portal {0}.", target); return(false); } if (links.Any(link => link.Overlaps(target))) { message = string.Format("Target portal {0} is overlapped by a link.", target); return(false); } LinkModel newLink = new LinkModel(source, target); if (links.Any(link => link.EqualsIgnoreDirection(newLink))) { message = string.Format("Link already exists between portal {0} and {1}.", source, target); return(false); } if (links.Any(link => link.Intersects(newLink))) { message = "Link crosses an existing link."; return(false); } message = ""; return(true); }
public IEnumerable <CFModel> AddCFs(LinkModel newLink) { var connectingLinks = links.Where(link => link != newLink && link.IsConnecting(newLink)); var connectingLinkCombinations = connectingLinks.SelectMany(link1 => connectingLinks.Where(l => l != link1).Select(link2 => new LinkModel[] { link1, link2 }) ).ToList(); var triangleLinkCombinations = connectingLinkCombinations.Where(lc => lc[0].IsConnecting(newLink.Source) && lc[1].IsConnecting(newLink.Target) && lc[0].OtherEnd(newLink.Source) == lc[1].OtherEnd(newLink.Target)); var candidateCFs = triangleLinkCombinations.Select(lc => new CFModel(newLink, lc[0], lc[1])).ToList(); // TODO: Should exclude smaller overlapping CFs? cfs.AddRange(candidateCFs); return(candidateCFs); }
public bool Intersects(LinkModel other) { if (IsConnecting(other)) { // connection is ok return(false); } var a1 = Source.Position; var a2 = Target.Position; var b1 = other.Source.Position; var b2 = other.Target.Position; var a12 = a2 - a1; var b12 = b2 - b1; var p = Vector3.Cross(a12, b1 - a1).z *Vector3.Cross(a12, b2 - a1).z; var q = Vector3.Cross(b12, a1 - b1).z *Vector3.Cross(b12, a2 - b1).z; if (p == 0 && q == 0) { // straight var b1r = Vector2.Dot(a12, b1 - a1) / a12.sqrMagnitude; var b2r = Vector2.Dot(a12, b2 - a1) / a12.sqrMagnitude; return((!Util.InRange(b1r, 0, 1) && Util.InRange(b2r, 0, 1)) || (!Util.InRange(b2r, 0, 1) && Util.InRange(b1r, 0, 1))); } else if (p <= 0 && q <= 0) { // cross, inclusive return(true); } else { // OK return(false); } }
public bool Contains(LinkModel link) { return(Links.Contains(link)); }
public bool EqualsIgnoreDirection(LinkModel other) { return((Source == other.Source && Target == other.Target) || (Source == other.Target && Target == other.Source)); }
public bool IsConnecting(LinkModel other) { return(IsConnecting(other.Source) || IsConnecting(other.Target)); }