using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Microsoft.Msagl.Core.DataStructures; using Microsoft.Msagl.Core.Geometry; using Microsoft.Msagl.Core.Geometry.Curves; using Microsoft.Msagl.Core.Layout; using Microsoft.Msagl.Layout.OverlapRemovalFixedSegments; using Microsoft.Msagl.Routing; using Microsoft.Msagl.Routing.Visibility; using SymmetricSegment = Microsoft.Msagl.Core.DataStructures.SymmetricTuple; namespace Microsoft.Msagl.Layout.LargeGraphLayout { internal class LgSkeletonLevel { //internal RTree RailTree = new RTree(); //internal Dictionary RailDictionary = // new Dictionary(); readonly RTree _visGraphVertices = new RTree(); internal int ZoomLevel; //VisibilityGraph VisGraph = new VisibilityGraph(); internal LgPathRouter PathRouter = new LgPathRouter(); readonly Dictionary, List> _edgeTrajectories = new Dictionary, List>(); internal Dictionary, List> EdgeTrajectories { get { return _edgeTrajectories; } } internal void AddGraphEdgesFromCentersToPointsOnBorders(IEnumerable nodeInfos) { foreach (var nodeInfo in nodeInfos) PathRouter.AddVisGraphEdgesFromNodeCenterToNodeBorder(nodeInfo); } internal void Clear() { _visGraphVertices.Clear(); PathRouter = new LgPathRouter(); } internal void SetTrajectoryAndAddEdgesToUsed(LgNodeInfo s, LgNodeInfo t, List path) { var t1 = new SymmetricTuple(s, t); if (_edgeTrajectories.ContainsKey(t1)) return; _edgeTrajectories[t1] = path; PathRouter.MarkEdgesUsedAlongPath(path); } internal bool HasSavedTrajectory(LgNodeInfo s, LgNodeInfo t) { var t1 = new SymmetricTuple(s, t); return EdgeTrajectories.ContainsKey(t1); } internal List GetTrajectory(LgNodeInfo s, LgNodeInfo t) { List path; var tuple = new SymmetricTuple(s, t); EdgeTrajectories.TryGetValue(tuple, out path); return path; } internal void ClearSavedTrajectoriesAndUsedEdges() { _edgeTrajectories.Clear(); PathRouter.ClearUsedEdges(); } internal Set GetPointsOnSavedTrajectories() { var points = new Set(); foreach (var edgeTrajectory in _edgeTrajectories.Values) { points.InsertRange(edgeTrajectory); } return points; } internal void RemoveUnusedGraphEdgesAndNodes() { List unusedEdges = GetUnusedGraphEdges(); PathRouter.RemoveVisibilityEdges(unusedEdges); } internal List GetUnusedGraphEdges() { return PathRouter.GetAllEdgesVisibilityEdges().Where(e => !PathRouter.IsEdgeUsed(e)).ToList(); } IEnumerable SymSegsOfPointList(List ps) { for (int i = 0; i < ps.Count - 1; i++) yield return new SymmetricSegment(ps[i], ps[i + 1]); } internal bool RoutesAreConsistent() { var usedEdges=new Set(PathRouter.UsedEdges()); var routesDump = new Set(_edgeTrajectories.Select(p => p.Value).SelectMany(SymSegsOfPointList)); var visEdgeDump = new Set( PathRouter.VisGraph.Edges.Select(e => new SymmetricSegment(e.SourcePoint, e.TargetPoint))); // #if DEBUG && !SHARPKIT // foreach (var s in routesDump - visEdgeDump) // Console.WriteLine("{0} is in routes but no in vis graph", s); // foreach (var s in visEdgeDump - routesDump) // Console.WriteLine("{0} is in visgraph but no in routes", s); // var routesOutOfVisGraph = routesDump - visEdgeDump; // if (routesOutOfVisGraph.Count > 0) { // SplineRouter.ShowVisGraph(PathRouter.VisGraph, null,null, Ttt(routesOutOfVisGraph)); // } // foreach (var s in usedEdges - routesDump) // Console.WriteLine("{0} is in usedEdges but not in routes", s); // // foreach (var s in routesDump - usedEdges) // Console.WriteLine("{0} is in routes but not in usedEdges", s); // // #endif return routesDump == visEdgeDump && usedEdges==routesDump; } #if DEBUG IEnumerable Ttt(Set routesOutOfVisGraph) { foreach (var symmetricTuple in routesOutOfVisGraph) { yield return new LineSegment(symmetricTuple.A,symmetricTuple.B); } } #endif internal void RemoveSomeEdgeTrajectories(List> removeList) { foreach (var symmetricTuple in removeList) RemoveEdgeTrajectory(symmetricTuple); RemoveUnusedGraphEdgesAndNodes(); } void RemoveEdgeTrajectory(SymmetricTuple symmetricTuple) { List trajectory; if (_edgeTrajectories.TryGetValue(symmetricTuple, out trajectory)) { for (int i = 0; i < trajectory.Count - 1; i++) { DiminishUsed(trajectory[i], trajectory[i + 1]); } _edgeTrajectories.Remove(symmetricTuple); } } void DiminishUsed(Point a, Point b) { PathRouter.DiminishUsed(a, b); } public void MarkEdgesAlongPathAsEdgesOnOldTrajectories(List trajectory) { PathRouter.MarkEdgesAlongPathAsEdgesOnOldTrajectories(trajectory); } } }