Example #1
0
 public void LoadSigma(SigmaGraphModel graph)
 {
     nodes = graph.Nodes?.Select(n => new V8NodeModel()
     {
         id = n.Id, x = n.X, y = n.Y, size = n.Size
     }).ToArray() ?? new V8NodeModel[0];
     edges = graph.Edges?.Select(e => new V8EdgeModel()
     {
         id = e.Id, source = e.Source, target = e.Target
     }).ToArray() ?? new V8EdgeModel[0];
 }
Example #2
0
        /// <summary>
        /// Assumes layout has been already applied
        /// Note: method mutates graph and graphLayout
        /// </summary>
        public void ImproveAppliedLayout(SigmaGraphModel graph, GraphLayout graphLayout, LayoutSettings layoutSettings, TimeSpan duration)
        {
            using (var engine = new V8ScriptEngine())
            {
                try
                {
                    var v8Graph = new V8GraphModel();
                    v8Graph.LoadSigma(graph);
                    engine.AddHostObject("log", _log);

                    engine.Execute("var graph = " + JsonConvention.SerializeObject(v8Graph) + ";");
                    engine.Execute("var settings = " + JsonConvention.SerializeObject(layoutSettings) + ";");
                    engine.Execute("var duration = " + JsonConvention.SerializeObject(duration.TotalMilliseconds) + ";");

                    var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;

                    var forceAtlas2   = engine.Compile(File.ReadAllText($@"{baseDirectory}\App\Graph\Layout\ForceAtlas2.js"));
                    var serviceScript = engine.Compile(File.ReadAllText($@"{baseDirectory}\App\Graph\Layout\GraphLayoutService.js"));
                    engine.Execute(forceAtlas2);
                    engine.Execute(serviceScript);

                    var nodesJson = engine.Evaluate("JSON.stringify(nodes)").ToString();
                    var nodes     = JsonConvention.DeserializeObject <V8NodeModel[]>(nodesJson);
                    for (int i = 0; i < nodes.Length; i++)
                    {
                        var node = graph.Nodes[i];
                        node.X = nodes[i].x;
                        node.Y = nodes[i].y;

                        var id = node.Entity;
                        if (id.HasValue)
                        {
                            graphLayout[id.Value] = new GraphLayout.Coords()
                            {
                                X = nodes[i].x,
                                Y = nodes[i].y
                            };
                        }
                    }
                }
                catch (ScriptEngineException e)
                {
                    _log.Error("V8 exception: " + e.ErrorDetails);
                    throw;
                }
            }
        }
Example #3
0
        private bool ApplyLayout(SigmaGraphModel graph, GraphLayout graphLayout)
        {
            var allNodesCovered = true;
            var rnd             = new Random();

            foreach (var node in graph.Nodes)
            {
                GraphLayout.Coords coords;

                // should we interpolate vertex position for group by clause
                if (node.Props != null && node.Props.ContainsKey("members") &&
                    graph.Data != null && graph.Data.ContainsKey("grouped_vertices"))
                {
                    if (InterpolateCoords(
                            node.Props["members"] as HashSet <int>,
                            graph.Data["grouped_vertices"] as List <PropertyVertexModel>,
                            graphLayout, rnd, out coords))
                    {
                        node.X = coords.X;
                        node.Y = coords.Y;
                    }
                    else
                    {
                        node.X          = rnd.NextDouble();
                        node.Y          = rnd.NextDouble();
                        allNodesCovered = false;
                    }
                }
                // no interpolation but layout available
                else if (node.Entity.HasValue && graphLayout != null && graphLayout.TryGetValue(node.Entity.Value, out coords))
                {
                    node.X = coords.X;
                    node.Y = coords.Y;
                }
                else
                {
                    node.X          = rnd.NextDouble();
                    node.Y          = rnd.NextDouble();
                    allNodesCovered = false;
                }
            }
            return(allNodesCovered);
        }
Example #4
0
        /// <summary>
        /// 1) jeśli nie layoutu ma to utwórz nowy layout, synchronicznie odpal layout i dodaj do bazy
        /// 2) jeśli jest już layout to go wczytaj
        ///    2a) jeśli któryś z węzłow nie ma współżędnych to synchronicznie odpal layout ale na krótkie 0.5 sekundy
        ///    2b) zakolejkuj kolejny krok rozłożenia z niskim priorytetem
        /// </summary>
        public async Task LayoutGraph(SigmaGraphModel graph, LayoutTask layoutTask, TimeSpan?duration)
        {
            if (Guid.Empty.Equals(layoutTask.Query.NetworkId))
            {
                throw new ArgumentNullException(nameof(layoutTask.Query.NetworkId));
            }
            if (graph.Nodes == null)
            {
                return;
            }

            var networkId = layoutTask.Query.NetworkId;
            var layout    = await _repository.Db.Layouts.SingleOrDefaultAsync(l => l.NetworkId == networkId && l.Key == layoutTask.Query.LayoutKey);

            // Ad 1
            if (layout == null)
            {
                lock (LayoutLock)
                {
                    // prevent entering here from many threads
                    layout = _repository.Db.Layouts.SingleOrDefault(
                        l => l.NetworkId == networkId && l.Key == layoutTask.Query.LayoutKey);
                    if (layout == null)
                    {
                        layout = new Entities.Layout()
                        {
                            Id        = Guid.NewGuid(),
                            NetworkId = networkId,
                            Key       = layoutTask.Query.LayoutKey
                        };
                        _repository.Db.Layouts.Add(layout);
                        _repository.Db.SaveChanges();
                    }
                }
                ApplyLayout(graph, null);

                var graphLayout = new GraphLayout();
                ImproveAppliedLayout(graph, graphLayout, layoutTask.Settings,
                                     duration ?? _firstTimeLayoutDuration);

                // save layout
                layout.GraphLayout = graphLayout;
                _repository.Db.SaveChanges();
            }
            else
            // Ad 2
            {
                var graphLayout = layout.GraphLayout;
                if (!ApplyLayout(graph, graphLayout))
                {
                    // ad 2a
                    ImproveAppliedLayout(graph, graphLayout, layoutTask.Settings, duration ?? _missingNodesImproveLayoutDuration);
                    layout.GraphLayout = graphLayout;
                    await _repository.Db.SaveChangesAsync();
                }
                else
                {
                    // ad 2b
                    if (Background == null)
                    {
                        ImproveAppliedLayout(graph, graphLayout, layoutTask.Settings, duration ?? _missingNodesImproveLayoutDuration);
                        layout.GraphLayout = graphLayout;
                        await _repository.Db.SaveChangesAsync();
                    }
                    else
                    {
                        _log.Debug("Scheduling background layout");

                        if (layoutTask.ModifyLayout)
                        {
                            Background.Execute(new ImproveLayoutCommand()
                            {
                                Task     = layoutTask,
                                Duration = duration ?? _improveLayoutInBackgroundDuration
                            }, new BackgroundPrincipal(Auth.UserName));
                        }
                    }
                }
            }
        }