internal void UpdateTiles() { lock (this) { var grid = new GridTraversal(_graphViewer.Graph.BoundingBox, _graphViewer.GetBackgroundTileLevel()); Set<Triple> desiredActiveSetOfImages = _desiredActiveSetFunc(); // Set<Triple> setOfNotImageTiles = null; // Console.WriteLine(setOfNotImageTiles); Set<Triple> toRemove = new Set<Triple>(_activeImages.Keys) - desiredActiveSetOfImages; Task.Factory.StartNew(() => { foreach (var visibleTileKey in desiredActiveSetOfImages) CreateAndCacheBitmapIfNeeded(visibleTileKey, grid); }, _cancellationTokenSource.Token, TaskCreationOptions.None, TaskScheduler.Default). ContinueWith(t => { foreach (var visibleTileKey in desiredActiveSetOfImages) DisplayBitmap(visibleTileKey, grid); _graphViewer.GraphCanvas.Dispatcher.Invoke(() => RemoveTiles(toRemove)); _timer.Stop(); // we are done }, TaskContinuationOptions.OnlyOnRanToCompletion); } }
void DrawTilesOnLevel(List<Tuple<int, int>> tileList, GridTraversal grid, RenderTargetBitmap renderBitmap, double w, double h, double scale, int iLevel, List<Tuple<int, int>> nextLevelTileList) { InvalidateNodesForTilesOnLevel(iLevel); foreach (var tile in tileList) { int i = tile.Item1; int j = tile.Item2; var rect = grid.GetTileRect(i, j); bool tileIsAlmostEmpty = DrawImageOfTile(rect, i, j, renderBitmap, (int) w, (int) h, scale, grid); if (tileIsAlmostEmpty) continue; if (iLevel < _lgLayoutSettings.Interactor.GetNumberOfLevels() - 1) AddTileChildren(i, j, nextLevelTileList, grid, iLevel); } }
private void AddOldNodes(int numNodesOnPreviousLevel, GridTraversal grid) { for (int i = 0; i < numNodesOnPreviousLevel; i++) { var ni = SortedLgNodeInfos[i]; var nodeTile = grid.PointToTuple(ni.Center); if (!_nodeTileTable.ContainsKey(nodeTile)) _nodeTileTable[nodeTile] = 0; ni.Processed = true; _nodeTileTable[nodeTile]++; _insertedNodes.Add(ni); } }
/// <summary> /// /// </summary> /// <param name="tileBox"></param> /// <param name="ix"></param> /// <param name="iy"></param> /// <param name="renderBitmap"></param> /// <param name="w"></param> /// <param name="h"></param> /// <param name="scale"></param> /// <param name="grid"></param> /// <returns>true if the tile is small, that is it intersects only a few nodes</returns> public bool DrawImageOfTile(Rectangle tileBox, int ix, int iy, RenderTargetBitmap renderBitmap, int w, int h, double scale, GridTraversal grid) { bool tileIsAlmostEmpty = _lgLayoutSettings.Interactor.NumberOfNodesOfLastLayerIntersectedRectIsLessThanBound(grid.ILevel, tileBox, 60); // test if (tileIsAlmostEmpty) return true; SetTransformOnViewportWithoutRaisingViewChangeEvent(scale, tileBox.Center, new Rectangle(0, 0, w, h)); RenderTile(renderBitmap, w, h); SaveBitmapToFile(ix, iy, renderBitmap, grid); WpfMemoryPressureHelper.ResetTimers(); return false; }
/// <summary> /// generate and load tiles /// </summary> public void GenerateTiles() { var timer = new Timer(); timer.Start(); var renderTransform = _graphCanvas.RenderTransform.Clone(); bool normalFlow = false; try { Debug.Assert(!string.IsNullOrEmpty(TileDirectory)); Clear(); CreateTileDirectoryIfNeededAndRemoveEverythingUnderIt(); MakeAllNodesVisible(); UpdateAllNodeBorders(); RemoveAllVisibleRails(); var fitFactor = GetFitFactor(new Size(800, 800)); var w = GeomGraph.Width * fitFactor; var h = GeomGraph.Height * fitFactor; var renderBitmap = new RenderTargetBitmap((int)w, (int)h, 96, 96, PixelFormats.Pbgra32); var tileList=new List<Tuple<int, int>> {new Tuple<int, int>(0, 0)}; var nextLevelTileList = new List<Tuple<int, int>>(); for (int iLevel = 0; iLevel < _lgLayoutSettings.Interactor.GetNumberOfLevels() - 1 && tileList.Count>0;) { GridTraversal grid = new GridTraversal(GeomGraph.BoundingBox, iLevel); Console.WriteLine("Drawing tiles on level {0} ...", iLevel); DrawTilesOnLevel(tileList, grid, renderBitmap, w, h, fitFactor*Math.Pow(2, iLevel), iLevel, nextLevelTileList); iLevel++; if (iLevel == _lgLayoutSettings.Interactor.GetNumberOfLevels() - 1) break; tileList = SwapTileLists(tileList, ref nextLevelTileList); } Console.WriteLine("Done"); normalFlow = true; } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("did not succeeed to save all tiles"); } finally { // restore the original state foreach ( var node in _drawingGraph.Nodes.Concat(_drawingGraph.RootSubgraph.AllSubgraphsDepthFirstExcludingSelf())) { HideVNode(node); } Clear(); _graphCanvas.RenderTransform = renderTransform; if (normalFlow) InitTiles(); if (ViewChangeEvent != null) ViewChangeEvent(null, null); } timer.Stop(); Console.WriteLine("tiles for {0}", timer.Duration); }
public void RunTest7() { Point p1 = new Point(-497.12352212078628, 1689.84931190121); Point p2 = new Point(198.64235142705752, 2139.4677380013277); Point bl = new Point(-5191.0147700187063, -4395.7850131819132); double gridSize = 553.23948409846571; GridTraversal grid = new GridTraversal(new Rectangle(bl, bl + new Point(gridSize, gridSize)), 20); var tiles = grid.GetTilesIntersectedByLineSeg(p1, p2); #if DEBUG Microsoft.Msagl.GraphViewerGdi.DisplayGeometryGraph.SetShowFunctions(); ShowTiles(tiles, grid, p1, p2); #endif }
Set<Tuple<int, int, int>> GetVisibleTilesSet() { int iLevel = GetBackgroundTileLevel(); GridTraversal grid = new GridTraversal(GeomGraph.BoundingBox, iLevel); var tiles = new Set<Triple>(); var visibleRectangle = GetVisibleRectangleInGraph(); var t1 = grid.PointToTuple(visibleRectangle.LeftBottom); var t2 = grid.PointToTuple(visibleRectangle.RightTop); for (int ix = t1.Item1; ix <= t2.Item1; ix++) for (int iy = t1.Item2; iy <= t2.Item2; iy++) { var t = new Triple(iLevel, ix, iy); TileType tileType; if (!_tileDictionary.TryGetValue(t, out tileType)) continue; if (tileType == TileType.Image) tiles.Insert(t); } return tiles; }
void RemoveLooseSegmentsDecrementTiles(IEnumerable<SymmetricSegment> segs, GridTraversal grid) { foreach (var seg in segs) { RemoveLooseSegmentDecrementTiles(seg, grid); } }
void RemoveLooseSegmentDecrementTiles(SymmetricSegment seg, GridTraversal grid) { var intersectedTiles = GetIntersectedTiles(seg.A, seg.B, grid); foreach (var tile in intersectedTiles) { if (_segmentTileTable.ContainsKey(tile)) _segmentTileTable[tile]--; } }
bool IfCanInsertLooseSegmentUpdateTiles(SymmetricSegment seg, GridTraversal grid) { //test if already inserted if (IsSegmentAlreadyAdded(seg)) return true; var intersectedTiles = GetIntersectedTiles(seg.A, seg.B, grid); bool canInsertSegment = true; foreach (var tile in intersectedTiles) { if (!_segmentTileTable.ContainsKey(tile)) _segmentTileTable[tile] = 0; canInsertSegment &= _segmentTileTable[tile] < MaxAmountRailsPerTile; } if (!canInsertSegment) return false; foreach (var tile in intersectedTiles) { _segmentTileTable[tile]++; } return true; }
bool IfCanInsertLooseSegmentsUpdateTiles(IEnumerable<SymmetricSegment> segs, out Set<SymmetricSegment> insertedSegs, GridTraversal grid) { insertedSegs = new Set<SymmetricSegment>(); foreach (var seg in segs) { if (IfCanInsertLooseSegmentUpdateTiles(seg, grid)) insertedSegs.Insert(seg); else return false; } return true; }
int DrawNodesOnlyOnLevel(int level, int startInd) { int iLevel = (int) Math.Log(level, 2); GridTraversal grid= new GridTraversal(BoundingBox, iLevel); UpdateTilesCountInsertedNodesOnly(level, grid); for (int i = startInd; i < SortedLgNodeInfos.Count; i++) { var ni = SortedLgNodeInfos[i]; var tuple = grid.PointToTuple(ni.Center); if (!_nodeTileTable.ContainsKey(tuple)) _nodeTileTable[tuple] = 0; if (_nodeTileTable[tuple] >= MaxNodesPerTile(level)) { return i; } PerformNodeInsertion(ni, tuple); ni.ZoomLevel = level; } return SortedLgNodeInfos.Count; }
bool TryAddingSegmentsUpdateTiles(IEnumerable<SymmetricSegment> segments, GridTraversal grid, out Set<SymmetricSegment> insertedSegments) { if (!IfCanInsertLooseSegmentsUpdateTiles(segments.ToList(), out insertedSegments, grid)) { // quota broken when inserting node boundary segments RemoveLooseSegmentsDecrementTiles(insertedSegments, grid); return false; } return true; }
private void ShowDebugInsertedSegments(GridTraversal grid, int zoomLevel, LgNodeInfo nodeToAdd, IEnumerable<SymmetricSegment> newToAdd, IEnumerable<SymmetricSegment> allOnNewEdges) { #if DEBUG && !SILVERLIGHT && !SHARPKIT && PREPARE_DEMO var edges = _pathRouter.GetAllEdgesVisibilityEdges(); var ll = new List<DebugCurve>(); foreach (var ni in _insertedNodes) { ll.Add(new DebugCurve(5, "green", ni.BoundaryCurve)); } if (nodeToAdd != null) { var curve = _insertedNodes.Last().BoundaryCurve.Clone(); curve.Translate(nodeToAdd.Center - _insertedNodes.Last().Center); ll.Add(new DebugCurve(5, "red", curve)); } foreach (var e in edges) { ll.Add(new DebugCurve(new LineSegment(e.SourcePoint, e.TargetPoint))); } int n = zoomLevel; int maxNodes = MaxNodesPerTile(zoomLevel); for (int ix = 0; ix < n; ix++) { for (int iy = 0; iy < n; iy++) { var tile = new Tuple<int, int>(ix, iy); var r = grid.GetTileRect(ix, iy); if (_nodeTileTable.ContainsKey(tile) && _nodeTileTable[tile] >= maxNodes) { ll.Add(new DebugCurve(5, "yellow", CurveFactory.CreateRectangle(r))); } else if (_segmentTileTable.ContainsKey(tile) && _segmentTileTable[tile] >= MaxAmountRailsPerTile) { ll.Add(new DebugCurve(5, "orange", CurveFactory.CreateRectangle(r))); } else { ll.Add(new DebugCurve(5, "blue", CurveFactory.CreateRectangle(r))); } } } if (allOnNewEdges != null) { foreach (var seg in allOnNewEdges) { ll.Add(new DebugCurve(5, "yellow", new LineSegment(seg.A, seg.B))); } } if (newToAdd != null) { foreach (var seg in newToAdd) { ll.Add(new DebugCurve(5, "red", new LineSegment(seg.A, seg.B))); } } LayoutAlgorithmSettings.ShowDebugCurves(ll.ToArray()); PrintInsertedNodesLabels(); #endif }
public void RunTest6() { Point bl = new Point(0, 0); Point p1 = new Point(0.5, 1.5); Point p2 = new Point(9.5, 10.1); GridTraversal grid = new GridTraversal(new Rectangle(bl, bl + new Point(20, 15)), 2); var tiles = grid.GetTilesIntersectedByLineSeg(p1, p2); #if DEBUG Microsoft.Msagl.GraphViewerGdi.DisplayGeometryGraph.SetShowFunctions(); ShowTiles(tiles, grid, p1, p2); #endif }
void UpdateTilesCountInsertedNodes(int level, GridTraversal grid) { foreach (var node in _insertedNodes) { var tuple = grid.PointToTuple(node.Center); if (!_nodeTileTable.ContainsKey(tuple)) _nodeTileTable[tuple] = 0; _nodeTileTable[tuple]++; } }
static void ShowTiles(List<Tuple<int, int>> tiles, GridTraversal grid, Point p1, Point p2) { var ll = tiles.Select(t => grid.GetTileRect(t.Item1, t.Item2)).Select(r => new DebugCurve("black", r.Perimeter())).ToList(); ll.Add(new DebugCurve("red", new LineSegment(p1, p2))); LayoutAlgorithmSettings.ShowDebugCurves(ll.ToArray()); }
void UpdateTilesCountInsertedNodesOnly(int level, GridTraversal grid) { _nodeTileTable = new Dictionary<Tuple<int, int>, int>(); UpdateTilesCountInsertedNodes(level, grid); }
IEnumerable<Triple> VectorTiles() { int iLevel = GetBackgroundTileLevel(); GridTraversal grid = new GridTraversal(GeomGraph.BoundingBox, iLevel); var visibleRectangle = GetVisibleRectangleInGraph(); var t1 = grid.PointToTuple(visibleRectangle.LeftBottom); var t2 = grid.PointToTuple(visibleRectangle.RightTop); for (int ix = t1.Item1; ix <= t2.Item1; ix++) for (int iy = t1.Item2; iy <= t2.Item2; iy++) { var t = new Triple(iLevel, ix, iy); TileType tileType; if (!_tileDictionary.TryGetValue(t, out tileType)) continue; if (tileType == TileType.Vector) yield return t; } }
List<Tuple<int, int>> GetIntersectedTiles(Point p1, Point p2, GridTraversal grid) { return grid.GetTilesIntersectedByLineSeg(p1, p2); }
internal string CreateTileFileName(int ix, int iy, GridTraversal grid) { var splitName = grid.SplitTileNameOnDirectories(ix, iy); string fname = TileDirectory; for (int i = splitName.Count - 1; i >= 0; i--) fname=System.IO.Path.Combine(fname, splitName[i]); return fname + ".png"; }
internal int TryInsertingNodesAndRoutes(int numNodesToInsert, Dictionary<SymmetricTuple<LgNodeInfo>, List<Point>> trajectories, List<SymmetricSegment> oldSegments, int zoomLevel, int numNodesOnPreviousLevel, GridTraversal grid, LgPathRouter pathRouter) { MarkAllNodesNotProcessed(); _segmentTileTable = new Dictionary<Tuple<int, int>, int>(); _nodeTileTable = new Dictionary<Tuple<int, int>, int>(); var canAddOldSegments = TryAddingOldSegments(oldSegments, grid); if (!canAddOldSegments) { return 0; } AddOldNodes(numNodesOnPreviousLevel, grid); int i; for (i = numNodesOnPreviousLevel; i < numNodesToInsert; i++) { var ni = SortedLgNodeInfos[i]; var nodeTile = grid.PointToTuple(ni.Center); if (!_nodeTileTable.ContainsKey(nodeTile)) _nodeTileTable[nodeTile] = 0; if (_nodeTileTable[nodeTile] >= MaxNodesPerTile(zoomLevel)) //test MaxAmountNodesPerTile { ShowDebugInsertedSegments(grid, zoomLevel, ni, null, null); break; } Set<VisibilityEdge> edges = GetSegmentsOnPathsToInsertedNeighborsNotOnOldTrajectories(ni, trajectories, pathRouter); Set<SymmetricSegment> segments = new Set<SymmetricSegment>( edges.Select(e => new SymmetricSegment(e.SourcePoint, e.TargetPoint))); var newToAdd = segments.Where(seg => !IsSegmentAlreadyAdded(seg)).ToList(); Set<SymmetricSegment> insertedSegments; bool canInsertPaths = TryAddingSegmentsUpdateTiles(newToAdd, grid, out insertedSegments); if (canInsertPaths) { AddSegmentsToRtree(newToAdd); ni.Processed = true; _nodeTileTable[nodeTile]++; _insertedNodes.Add(ni); continue; } //debug output //AddSegmentsToRtree(newToAdd); //remove // ShowDebugInsertedSegments(grid, zoomLevel, ni, newToAdd, segments); break; } var nextNode = numNodesToInsert < SortedLgNodeInfos.Count ? SortedLgNodeInfos[numNodesToInsert] : null; // ShowDebugInsertedSegments(grid, zoomLevel, nextNode, null, null); return i; }
void SaveBitmapToFile(int ix, int iy, RenderTargetBitmap renderBitmap, GridTraversal grid) { using (FileStream outStream = CreateTileFileStream(grid, ix, iy)) { var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); encoder.Save(outStream); } }
void DisplayBitmap(Triple triple, GridTraversal grid) { _graphViewer.GraphCanvas.Dispatcher.Invoke(() => { lock (_cacheLock) { if (_activeImages.ContainsKey(triple)) return; BitmapImage sourceBitmapImage; if (!_cachedImages.TryGetValue(triple, out sourceBitmapImage)) return; var image = new Image {Source = sourceBitmapImage, Tag = triple}; _activeImages[triple] = image; _graphViewer.GraphCanvas.Children.Add(image); image.Width = grid.TileWidth; image.Height = grid.TileHeight; var center = grid.GetTileCenter(triple.Item2, triple.Item3); Common.PositionFrameworkElement(image, center, 1); } }); }
StreamWriter CreateTileStreamWriter(GridTraversal grid, int ix, int iy) { var splitName = grid.SplitTileNameOnDirectories(ix, iy); string fname = TileDirectory; for (int i = splitName.Count - 1; i >= 0; i--) { fname = System.IO.Path.Combine(fname, splitName[i]); if (i > 0) { if (!Directory.Exists(fname)) Directory.CreateDirectory(fname); } } return new StreamWriter(fname + ".list"); }
void CreateAndCacheBitmapIfNeeded(Triple triple, GridTraversal grid) { if (_activeImages.ContainsKey(triple)) return; if (_cachedImages.ContainsKey(triple)) return; var fname = _graphViewer.CreateTileFileName(triple.Item2, triple.Item3, grid); if (!File.Exists(fname)) return; WpfMemoryPressureHelper.ResetTimers(); BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.CreateOptions = BitmapCreateOptions.PreservePixelFormat; bitmapImage.CacheOption = BitmapCacheOption.None; bitmapImage.UriSource = new Uri(_graphViewer.CreateTileFileName(triple.Item2, triple.Item3, grid)); bitmapImage.UriCachePolicy=new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); bitmapImage.EndInit(); bitmapImage.Freeze(); CacheBitmap(triple, bitmapImage); }
void AddTileChildren(int i, int j, List<Tuple<int, int>> nextLevelTileList, GridTraversal grid,int iLevel) { var tileBox = grid.GetTileRect(i, j); i *= 2; j *= 2; var center = tileBox.Center; var rect = new Rectangle(tileBox.LeftBottom, center); if (!RectIsEmptyAfterLevel(rect, iLevel)) nextLevelTileList.Add(new Tuple<int, int>(i, j)); rect = new Rectangle(tileBox.RightBottom, center); if (!RectIsEmptyAfterLevel(rect, iLevel)) nextLevelTileList.Add(new Tuple<int, int>(i + 1, j)); rect = new Rectangle(tileBox.LeftTop, center); if (!RectIsEmptyAfterLevel(rect, iLevel)) nextLevelTileList.Add(new Tuple<int, int>(i, j + 1)); rect = new Rectangle(tileBox.RightTop, center); if (!RectIsEmptyAfterLevel(rect, iLevel)) nextLevelTileList.Add(new Tuple<int, int>(i + 1, j + 1)); }
private bool TryAddingOldSegments(List<SymmetricSegment> oldSegments, GridTraversal grid) { Set<SymmetricSegment> insertedSegments; bool canInsertOldPaths = TryAddingSegmentsUpdateTiles(oldSegments, grid, out insertedSegments); if (canInsertOldPaths) { AddSegmentsToRtree(oldSegments); return true; } // if couldn't even insert previous level, terminate return false; }