This project is read-only.

All vertices stacked on top of each other when dynamically adding

Nov 30, 2009 at 8:52 PM

Hi guys,

if you allow me one question regarding dynamically adding vertices (and connected edges).
My problem is that the newly created vertices are all stacked on top of each other (even though the edges are connected correctly to their assigned vertices - which only becomes visible when manually dragging the vertices a bit apart).

I've included a bit of code - hopefully my problem is more abstract and I am simply doing a typical noobish thinking-mistake in the architecture though :-)
I am basically creating an empty graph from my ViewModel and at the same time starting various background-workers which load rdf-data from different sources.
The background workers fill a singleton (thread-safe) collection object (EntityCache). When the workers finish the workerCompleted method in the main UI thread triggers a refreshGraph(..)  which adds newly added model objects as new vertices to the graph:


private
void refreshGraph (object sender, NotifyCollectionChangedEventArgs eventArgs) { // handle added items if (eventArgs.Action == NotifyCollectionChangedAction.Add) { foreach (EntityViewModel newEntityViewModel in eventArgs.NewItems) { this.addEntityViewModelToGraph(newEntityViewModel); } } // request relayout from the view this.OnEventRequestRelayoutGraph(new EventArgs()); } /// <summary> /// Adds an entity to the graph. /// </summary> /// <param name="entity">The entity.</param> private void addEntityViewModelToGraph(EntityViewModel entityViewModel) { if (entityViewModel != null) { //// create a new EntityViewModel from this entity (or get from cache) entityViewModel = this.getCachedEntityViewModel(entityViewModel); this._graphToVisualize.AddVertex(entityViewModel); // now check if there are references in object-properties we can add too Dictionary<string, object> properties = entityViewModel.entity.GetAllProperties(); foreach (KeyValuePair<string, object> kvpProperty in properties) { // check if it is an object property Property propertyType = entityViewModel.entity.GetPropertyType(kvpProperty.Key); if (entityViewModel.entity.GetPropertyType(kvpProperty.Key).IsObjectProperty()) { // if the object property is a list of entities add all if (kvpProperty.Value.GetType() == typeof(List<IEntity>)) { foreach (IEntity connectedEntity in (IList<IEntity>)kvpProperty.Value) { // create a new EntityViewModel from this entity (or get cached) EntityViewModel connectedEntityViewModel = this.getCachedEntityViewModel(connectedEntity); Edge<EntityViewModel> e2 = new Edge<EntityViewModel>(entityViewModel, connectedEntityViewModel); this._graphToVisualize.AddVerticesAndEdge(e2); } } } } // raise property changed to View RaisePropertyChanged("GraphToVisualize"); } }

When the vertices ended up all stucked up I tried to manually force a relayout of the graphControl in the view by raising an event from viewModel to view.
(As you can see in the first method (last statement)).
This unfortunately led to the following exception in FSAAlgorithms.cs:HorizontalImproved()


System.ArgumentOutOfRangeException was unhandled Message="Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index" Source="mscorlib" ParamName="index" StackTrace: at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) at System.ThrowHelper.ThrowArgumentOutOfRangeException() at System.Collections.Generic.List`1.get_Item(Int32 index) at GraphSharp.Algorithms.OverlapRemoval.FSAAlgorithm`2.HorizontalImproved() in D:\ConSenseCode\ConSense\_foreignSvn\GraphSharp\Graph#\Algorithms\OverlapRemoval\FSAAlgorithm.cs:line 164 at GraphSharp.Algorithms.OverlapRemoval.FSAAlgorithm`2.RemoveOverlap() in D:\ConSenseCode\ConSense\_foreignSvn\GraphSharp\Graph#\Algorithms\OverlapRemoval\FSAAlgorithm.cs:line 35 at GraphSharp.Algorithms.OverlapRemoval.OverlapRemovalAlgorithmBase`2.InternalCompute() in D:\ConSenseCode\ConSense\_foreignSvn\GraphSharp\Graph#\Algorithms\OverlapRemoval\OverlapRemovalAlgorithmBase.cs:line 48 at GraphSharp.Algorithms.AlgorithmBase.Compute() in D:\ConSenseCode\ConSense\_foreignSvn\GraphSharp\Graph#\Algorithms\AlgorithmBase.cs:line 36 [.. left the rest of the stacktrace out]

Really at a loss at what to do here.
I could imagine the two problems are a bit unrelated with the second being due to some threading problem in my architecture, but the first?
Why isnt the graph just laying out the newly added vertices correctly - I mean obviously updating the ViewModel gets noticed by the graphControl, as there ARE vertices shown in the first place.

 

Cheers and thank you a bunch for any input on this,
Hinnerk

Nov 30, 2009 at 9:05 PM

Hmmm - writing the above got me thinking about the Exception in FSAAlgorithm.cs (as I am actually using LinLog and not FSA).
Tturns out if I switch to FSA no exception is thrown (but the vertices still stay stacked up - even though calling Relayout() ).

Additionally calling RecalculateEdgeRouting() on the graphControl (in place of ReLayout()) throws an 

ArgumentOutOfRangeException 

as well - in this case both with LinLog and FSA.

Dec 1, 2009 at 6:47 PM
Edited Dec 1, 2009 at 7:44 PM

Alright, so changing the layoutAlgorithmType to EfficientSugiyama leads to the expected behavior.

Is it a design mistake on my side, or are Circular, ISOM, EfficientSugiyama and Tree the only mutable layouts?
I didnt even consider that at first as e.g. FSA also seems to register for change events to the itemSource.
Maybe you could give me some rough estimation on the required effort and a starting point to implement this in a different layout as well?

Thanks,
Hinnerk

 

 

Dec 14, 2009 at 1:20 AM

Thanks Hinnerk,

I was stumped on the same problem using Tree instead of EfficientSugiyama!

Andrew.