private void GenerateCombinedGraph(bool isGroupLayout)
{
LayoutSubgraphs = new List<GraphLayout.Graph>();
LayoutSubgraphs.Add(new GraphLayout.Graph());
GraphLayout.Graph combinedGraph = LayoutSubgraphs.First();
SubgraphClusters = new List<List<GraphLayout.Node>>();
if (!isGroupLayout)
{
foreach (AnnotationModel group in Annotations)
{
// Treat a group as a graph layout node/vertex
combinedGraph.AddNode(group.GUID, group.Width, group.Height, group.X, group.Y,
group.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
}
}
foreach (NodeModel node in Nodes)
{
if (!isGroupLayout)
{
AnnotationModel group = Annotations.Where(
g => g.SelectedModels.Contains(node)).ToList().FirstOrDefault();
// Do not process nodes within groups
if (group == null)
{
combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
}
}
else
{
// Process all nodes inside the selection
combinedGraph.AddNode(node.GUID, node.Width, node.Height, node.X, node.Y,
node.IsSelected || DynamoSelection.Instance.Selection.Count == 0);
}
}
foreach (ConnectorModel edge in Connectors)
{
if (!isGroupLayout)
{
AnnotationModel startGroup = null, endGroup = null;
startGroup = Annotations.Where(
g => g.SelectedModels.Contains(edge.Start.Owner)).ToList().FirstOrDefault();
endGroup = Annotations.Where(
g => g.SelectedModels.Contains(edge.End.Owner)).ToList().FirstOrDefault();
// Treat a group as a node, but do not process edges within a group
if (startGroup == null || endGroup == null || startGroup != endGroup)
{
combinedGraph.AddEdge(
startGroup == null ? edge.Start.Owner.GUID : startGroup.GUID,
endGroup == null ? edge.End.Owner.GUID : endGroup.GUID,
edge.Start.Center.X, edge.Start.Center.Y, edge.End.Center.X, edge.End.Center.Y);
}
}
else
{
// Edges within a group are also processed
combinedGraph.AddEdge(edge.Start.Owner.GUID, edge.End.Owner.GUID,
edge.Start.Center.X, edge.Start.Center.Y, edge.End.Center.X, edge.End.Center.Y);
}
}
foreach (NoteModel note in Notes)
{
AnnotationModel group = Annotations.Where(
g => g.SelectedModels.Contains(note)).ToList().FirstOrDefault();
GraphLayout.Node nd = null;
if (!isGroupLayout || group == null)
{
// If note is not part of a group, link to the nearest node in the graph
nd = combinedGraph.Nodes.OrderBy(node =>
Math.Pow(node.X + node.Width / 2 - note.X - note.Width / 2, 2) +
Math.Pow(node.Y + node.Height / 2 - note.Y - note.Height / 2, 2)).FirstOrDefault();
}
else
{
// If note is part of a group, link to the nearest node in the group
NodeModel ndm = group.SelectedModels.OfType<NodeModel>().OrderBy(node =>
Math.Pow(node.X + node.Width / 2 - note.X - note.Width / 2, 2) +
Math.Pow(node.Y + node.Height / 2 - note.Y - note.Height / 2, 2)).FirstOrDefault();
// Skip processing the group if there is no node in the group
if (ndm == null) continue;
// If the nearest point is a node model
nd = combinedGraph.FindNode(ndm.GUID);
// If the nearest point is a group model
nd = nd ?? combinedGraph.FindNode(group.GUID);
}
// Otherwise, leave the note unchanged
if (nd != null)
{
nd.LinkNote(note, note.Width, note.Height);
}
}
if (!isGroupLayout)
{
// Add all nodes to one big cluster
List<GraphLayout.Node> bigcluster = new List<GraphLayout.Node>();
bigcluster.AddRange(combinedGraph.Nodes);
SubgraphClusters.Add(bigcluster);
}
else
{
// Each group becomes one cluster
foreach (AnnotationModel group in DynamoSelection.Instance.Selection.OfType<AnnotationModel>())
{
List<GraphLayout.Node> cluster = new List<GraphLayout.Node>();
cluster.AddRange(group.SelectedModels.OfType<NodeModel>().Select(x => combinedGraph.FindNode(x.GUID)));
SubgraphClusters.Add(cluster);
}
}
}