/// <summary> /// Initializes the graph instance setting default styles /// and creating a small sample graph. /// </summary> protected virtual void InitializeGraph() { IGraph graph = Graph; // load a sample graph new GraphMLIOHandler().Read(graph, "Resources/sample.graphml"); // set some defaults graph.NodeDefaults.Style = Enumerable.First(graph.Nodes).Style; graph.NodeDefaults.ShareStyleInstance = true; // we start with a simple run of OrganicLayout to get a good starting result // the algorithm is optimized to "unfold" graphs quicker than // interactive organic, so we use this result as a starting solution var initialLayout = new OrganicLayout { MinimumNodeDistance = 50 }; graph.ApplyLayout(initialLayout); // center the initial graph GraphControl.FitGraphBounds(); movedNodes = new List <INode>(); // we wrap the PositionHandler for nodes so that we always have the collection of nodes // that are currently being moved available in "movedNodes". // this way we do not need to know how the node is moved and do not have to guess // what elements are currently being moved based upon selection, etc. graph.GetDecorator().NodeDecorator.PositionHandlerDecorator.SetImplementationWrapper( (item, implementation) => new CollectingPositionHandlerWrapper(item, movedNodes, implementation)); // create a copy of the graph for the layout algorithm LayoutGraphAdapter adapter = new LayoutGraphAdapter(graphControl.Graph); copiedLayoutGraph = adapter.CreateCopiedLayoutGraph(); // create and start the layout algorithm layout = StartLayout(); WakeUp(); // register a listener so that structure updates are handled automatically graph.NodeCreated += delegate(object source, ItemEventArgs <INode> args) { if (layout != null) { var center = args.Item.Layout.GetCenter(); layout.SyncStructure(true); //we nail down all newly created nodes var copiedNode = copiedLayoutGraph.GetCopiedNode(args.Item); layout.SetCenter(copiedNode, center.X, center.Y); layout.SetInertia(copiedNode, 1); layout.SetStress(copiedNode, 0); layout.WakeUp(); } }; graph.NodeRemoved += OnStructureChanged; graph.EdgeCreated += OnStructureChanged; graph.EdgeRemoved += OnStructureChanged; }
static PartialLayoutForm() { SubGraphLayouts[LayoutIncremental] = new HierarchicLayout(); SubGraphLayouts[LayoutOrganic] = new OrganicLayout(); SubGraphLayouts[LayoutOrthogonal] = new OrthogonalLayout(); SubGraphLayouts[LayoutCircular] = new CircularLayout(); SubGraphLayouts[LayoutUnchanged] = null; }
private void CreateOrganic() { if (organic == null) { organic = new OrganicLayout(); organic.PrependStage(new PortCalculator()); } }
/// <summary> /// Gets the layout algorithm selected by the user. /// </summary> /// <returns></returns> private ILayoutAlgorithm GetLayoutAlgorithm() { var graph = graphControl.Graph; var item = layoutChooserBox.SelectedItem as ComboBoxItem; var layoutName = item != null ? item.Tag as String: null; ILayoutAlgorithm layout = new HierarchicLayout(); if (layoutName != null) { if (layoutName == "hierarchic") { layout = new HierarchicLayout(); } else if (layoutName == "organic") { layout = new OrganicLayout { PreferredEdgeLength = 1.5 * Math.Max(graph.NodeDefaults.Size.Width, graph.NodeDefaults.Size.Height) }; } else if (layoutName == "orthogonal") { layout = new OrthogonalLayout(); } else if (layoutName == "circular") { layout = new CircularLayout(); } else if (layoutName == "tree") { layout = new TreeReductionStage(new TreeLayout()) { NonTreeEdgeRouter = new OrganicEdgeRouter() }; } else if (layoutName == "balloon") { layout = new TreeReductionStage(new BalloonLayout()) { NonTreeEdgeRouter = new OrganicEdgeRouter() }; } else if (layoutName == "radial") { layout = new RadialLayout(); } else if (layoutName == "router-polyline") { layout = new EdgeRouter(); } else if (layoutName == "router-organic") { layout = new OrganicEdgeRouter { EdgeNodeOverlapAllowed = false }; } } return(layout); }
/// <summary> /// Gets the layout algorithm selected by the user. /// </summary> /// <returns></returns> private ILayoutAlgorithm GetLayoutAlgorithm() { var graph = graphControl.Graph; var layoutName = layoutBox.SelectedItem as string; ILayoutAlgorithm layout = new HierarchicLayout(); if (layoutName != null) { if (layoutName == "Layout: Hierarchic") { layout = new HierarchicLayout(); } else if (layoutName == "Layout: Organic") { layout = new OrganicLayout { PreferredEdgeLength = 1.5 * Math.Max(graph.NodeDefaults.Size.Width, graph.NodeDefaults.Size.Height) }; } else if (layoutName == "Layout: Orthogonal") { layout = new OrthogonalLayout(); } else if (layoutName == "Layout: Circular") { layout = new CircularLayout(); } else if (layoutName == "Layout: Tree") { layout = new TreeReductionStage(new TreeLayout()) { NonTreeEdgeRouter = new OrganicEdgeRouter() }; } else if (layoutName == "Layout: Balloon") { layout = new TreeReductionStage(new BalloonLayout()) { NonTreeEdgeRouter = new OrganicEdgeRouter() }; } else if (layoutName == "Layout: Radial") { layout = new RadialLayout(); } else if (layoutName == "Routing: Polyline") { layout = new EdgeRouter(); } else if (layoutName == "Routing: Organic") { layout = new OrganicEdgeRouter { EdgeNodeOverlapAllowed = false }; } } return(layout); }
/// <summary> /// Populates the layout combo box. /// </summary> private void PopulateLayoutComboBox() { layouts["Hierarchic Layout"] = new HierarchicLayout(); layouts["Organic Layout"] = new OrganicLayout { MinimumNodeDistance = 40 }; layouts["Orthogonal Layout"] = new OrthogonalLayout(); layoutComboBox.Items.AddRange(layouts.Keys.ToArray()); }
///<inheritdoc/> protected override void ConfigureLayout() { OptionGroup layoutGroup = Handler.GetGroupByName(GENERAL); var partialLayout = new PartialLayout { MinimumNodeDistance = (int)layoutGroup[MIN_NODE_DIST].Value, ConsiderNodeAlignment = (bool)layoutGroup[CONSIDER_SNAPLINES].Value, SubgraphPlacement = subgraphPlacementStrategies[ (string)layoutGroup[SUBGRAPH_POSITION_STRATEGY].Value] }; string componentAssignmentStr = (string)layoutGroup[MODE_COMPONENT_ASSIGNMENT].Value; partialLayout.ComponentAssignmentStrategy = componentAssignment[componentAssignmentStr]; partialLayout.LayoutOrientation = layoutOrientation[(string)layoutGroup[ORIENTATION_MAIN_GRAPH].Value]; partialLayout.EdgeRoutingStrategy = routingStrategies[(string)layoutGroup[ROUTING_TO_SUBGRAPH].Value]; ILayoutAlgorithm subgraphLayout = null; if (componentAssignmentStr != MODE_COMPONENT_SINGLE) { var subGraphLayoutStr = (string)layoutGroup[SUBGRAPH_LAYOUT].Value; switch (subGraphLayoutStr) { case SUBGRAPH_LAYOUT_IHL: subgraphLayout = new HierarchicLayout(); break; case SUBGRAPH_LAYOUT_ORGANIC: subgraphLayout = new OrganicLayout(); break; case SUBGRAPH_LAYOUT_CIRCULAR: subgraphLayout = new CircularLayout(); break; case SUBGRAPH_LAYOUT_ORTHOGONAL: subgraphLayout = new OrthogonalLayout(); break; default: break; } } partialLayout.CoreLayout = subgraphLayout; LayoutAlgorithm = partialLayout; }
private OrganicLayout CreateLayout() { OrganicLayout organicLayout = new OrganicLayout { PreferredEdgeLength = 100, MinimumNodeDistance = 30, Deterministic = true }; return(organicLayout); }
/// <summary> /// Creates the core layouts and populates the layouts box /// </summary> private void InitializeCoreLayouts() { coreLayouts = new Dictionary <string, ILayoutAlgorithm>(); coreLayouts["Hierarchic"] = new HierarchicLayout { ConsiderNodeLabels = true, IntegratedEdgeLabeling = true, OrthogonalRouting = true }; coreLayouts["Circular"] = new CircularLayout(); coreLayouts["Compact Orthogonal"] = new CompactOrthogonalLayout(); coreLayouts["Organic"] = new OrganicLayout { MinimumNodeDistance = 10, Deterministic = true }; coreLayouts["Orthogonal"] = new OrthogonalLayout(); coreLayoutComboBox.ItemsSource = coreLayouts.Keys; coreLayoutComboBox.SelectedIndex = 0; }
private void SetupLayouts() { // create TreeLayout var treeLayout = new TreeLayout { LayoutOrientation = LayoutOrientation.LeftToRight }; treeLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(treeLayout); layoutMapper["Tree"] = treeLayout; layoutComboBox.Items.Add("Tree"); // create BalloonLayout var balloonLayout = new BalloonLayout { FromSketchMode = true, CompactnessFactor = 1.0, AllowOverlaps = true }; balloonLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(balloonLayout); layoutMapper["Balloon"] = balloonLayout; layoutComboBox.Items.Add("Balloon"); // create OrganicLayout var organicLayout = new OrganicLayout { MinimumNodeDistance = 40, Deterministic = true }; organicLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(organicLayout); layoutMapper["Organic"] = organicLayout; layoutComboBox.Items.Add("Organic"); // create OrthogonalLayout var orthogonalLayout = new OrthogonalLayout(); orthogonalLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(orthogonalLayout); layoutMapper["Orthogonal"] = orthogonalLayout; layoutComboBox.Items.Add("Orthogonal"); // set it as initial value currentLayout = treeLayout; layoutComboBox.SelectedIndex = 0; }
/// <summary> /// Runs an organic layout with edge labeling. /// </summary> private void RunLayout() { var genericLabeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, ReduceAmbiguity = true }; var layout = new OrganicLayout { MinimumNodeDistance = 60, NodeEdgeOverlapAvoided = true, LabelingEnabled = true, Labeling = genericLabeling }; graphControl.MorphLayout(layout, TimeSpan.FromSeconds(1)); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new OrganicLayout(); layout.PreferredEdgeLength = PreferredEdgeLengthItem; layout.ConsiderNodeLabels = ConsiderNodeLabelsItem; layout.NodeOverlapsAllowed = AllowNodeOverlapsItem; layout.MinimumNodeDistance = MinimumNodeDistanceItem; layout.Scope = ScopeItem; layout.CompactnessFactor = CompactnessItem; layout.ConsiderNodeSizes = true; layout.ClusterNodes = UseAutoClusteringItem; layout.ClusteringQuality = AutoClusteringQualityItem; layout.NodeEdgeOverlapAvoided = AvoidNodeEdgeOverlapsItem; layout.Deterministic = ActivateDeterministicModeItem; layout.MaximumDuration = 1000 * MaximumDurationItem; layout.QualityTimeRatio = QualityTimeRatioItem; if (EdgeLabelingItem) { var genericLabeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, ReduceAmbiguity = ReduceAmbiguityItem }; layout.LabelingEnabled = true; layout.Labeling = genericLabeling; } ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; ConfigureOutputRestrictions(graphControl, layout); layout.ChainSubstructureStyle = ChainSubstructureStyleItem; layout.CycleSubstructureStyle = CycleSubstructureStyleItem; layout.StarSubstructureStyle = StarSubstructureStyleItem; layout.ParallelSubstructureStyle = ParallelSubstructureStyleItem; if (UseEdgeGroupingItem) { graphControl.Graph.MapperRegistry.CreateConstantMapper <IEdge, object>(PortConstraintKeys.SourceGroupIdDpKey, "Group"); graphControl.Graph.MapperRegistry.CreateConstantMapper <IEdge, object>(PortConstraintKeys.TargetGroupIdDpKey, "Group"); } AddPreferredPlacementDescriptor(graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem); return(layout); }
/// <summary> /// Setup default values for various configuration parameters. /// </summary> public OrganicLayoutConfig() { var layout = new OrganicLayout(); ScopeItem = Scope.All; PreferredEdgeLengthItem = layout.PreferredEdgeLength; AllowNodeOverlapsItem = layout.NodeOverlapsAllowed; MinimumNodeDistanceItem = 10; AvoidNodeEdgeOverlapsItem = layout.NodeEdgeOverlapAvoided; CompactnessItem = layout.CompactnessFactor; ClusteringPolicyItem = layout.ClusteringPolicy; ClusteringQualityItem = layout.ClusteringQuality; RestrictOutputItem = EnumOutputRestrictions.None; RectCageUseViewItem = true; CageXItem = 0; CageYItem = 0; CageWidthItem = 1000; CageHeightItem = 1000; ArCageUseViewItem = true; CageRatioItem = 1; GroupLayoutPolicyItem = EnumGroupLayoutPolicy.LayoutGroups; QualityTimeRatioItem = layout.QualityTimeRatio; MaximumDurationItem = (int)(layout.MaximumDuration / 1000); ActivateDeterministicModeItem = layout.Deterministic; CycleSubstructureStyleItem = CycleSubstructureStyle.None; CycleSubstructureSizeItem = layout.CycleSubstructureSize; ChainSubstructureStyleItem = ChainSubstructureStyle.None; ChainSubstructureSizeItem = layout.ChainSubstructureSize; StarSubstructureStyleItem = StarSubstructureStyle.None; StarSubstructureSizeItem = layout.StarSubstructureSize; ParallelSubstructureStyleItem = ParallelSubstructureStyle.None; ParallelSubstructureSizeItem = layout.ParallelSubstructureSize; ConsiderNodeLabelsItem = layout.ConsiderNodeLabels; EdgeLabelingItem = false; LabelPlacementAlongEdgeItem = EnumLabelPlacementAlongEdge.Centered; LabelPlacementSideOfEdgeItem = EnumLabelPlacementSideOfEdge.OnEdge; LabelPlacementOrientationItem = EnumLabelPlacementOrientation.Horizontal; LabelPlacementDistanceItem = 10; }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new OrganicLayout(); layout.PreferredEdgeLength = PreferredEdgeLengthItem; layout.ConsiderNodeLabels = ConsiderNodeLabelsItem; layout.NodeOverlapsAllowed = AllowNodeOverlapsItem; layout.MinimumNodeDistance = MinimumNodeDistanceItem; layout.Scope = ScopeItem; layout.CompactnessFactor = CompactnessItem; layout.ConsiderNodeSizes = true; layout.ClusteringPolicy = ClusteringPolicyItem; layout.ClusteringQuality = ClusteringQualityItem; layout.NodeEdgeOverlapAvoided = AvoidNodeEdgeOverlapsItem; layout.Deterministic = ActivateDeterministicModeItem; layout.MaximumDuration = 1000 * MaximumDurationItem; layout.QualityTimeRatio = QualityTimeRatioItem; if (EdgeLabelingItem) { var genericLabeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, ReduceAmbiguity = ReduceAmbiguityItem }; layout.LabelingEnabled = true; layout.Labeling = genericLabeling; } ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; ConfigureOutputRestrictions(graphControl, layout); layout.ChainSubstructureStyle = ChainSubstructureStyleItem; layout.CycleSubstructureSize = CycleSubstructureSizeItem; layout.CycleSubstructureStyle = CycleSubstructureStyleItem; layout.ChainSubstructureSize = ChainSubstructureSizeItem; layout.StarSubstructureStyle = StarSubstructureStyleItem; layout.StarSubstructureSize = StarSubstructureSizeItem; layout.ParallelSubstructureStyle = ParallelSubstructureStyleItem; layout.ParallelSubstructureSize = ParallelSubstructureSizeItem; return(layout); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new PartialLayout(); layout.ConsiderNodeAlignment = AlignNodesItem; layout.MinimumNodeDistance = MinimumNodeDistanceItem; layout.SubgraphPlacement = SubgraphPlacementItem; layout.ComponentAssignmentStrategy = ComponentAssignmentStrategyItem; layout.LayoutOrientation = OrientationItem; layout.EdgeRoutingStrategy = RoutingToSubgraphItem; layout.AllowMovingFixedElements = MoveFixedElementsItem; ILayoutAlgorithm subgraphLayout = null; if (ComponentAssignmentStrategyItem != ComponentAssignmentStrategy.Single) { switch (SubgraphLayoutItem) { case EnumSubgraphLayouts.Hierarchic: subgraphLayout = new HierarchicLayout(); break; case EnumSubgraphLayouts.Organic: subgraphLayout = new OrganicLayout(); break; case EnumSubgraphLayouts.Circular: subgraphLayout = new CircularLayout(); break; case EnumSubgraphLayouts.Orthogonal: subgraphLayout = new OrthogonalLayout(); break; } } layout.CoreLayout = subgraphLayout; return(layout); }
private void SetupLayouts() { //using hierarchical layout style HierarchicLayout hierarchicLayout = new HierarchicLayout(); hierarchicLayout.EdgeLayoutDescriptor.RoutingStyle = new yWorks.Layout.Hierarchic.RoutingStyle( yWorks.Layout.Hierarchic.EdgeRoutingStyle.Orthogonal); CurrentLayout = hierarchicLayout; layouts.Add("Hierarchic", hierarchicLayout); //using organic layout style OrganicLayout organic = new OrganicLayout { QualityTimeRatio = 1.0, NodeOverlapsAllowed = false, NodeEdgeOverlapAvoided = true, MinimumNodeDistance = 10, PreferredEdgeLength = 50, }; layouts.Add("Organic", organic); //using orthogonal layout style OrthogonalLayout orthogonal = new OrthogonalLayout { GridSpacing = 15, OptimizePerceivedBends = true }; layouts.Add("Orthogonal", orthogonal); //using circular layout style CircularLayout circular = new CircularLayout(); circular.BalloonLayout.MinimumEdgeLength = 50; circular.BalloonLayout.CompactnessFactor = 0.1; layouts.Add("Circular", circular); // a tree layout algorithm TreeLayout treeLayout = new TreeLayout { ConsiderNodeLabels = true }; treeLayout.AppendStage(new TreeReductionStage() { NonTreeEdgeRouter = new OrganicEdgeRouter(), NonTreeEdgeSelectionKey = OrganicEdgeRouter.AffectedEdgesDpKey, }); layouts.Add("Tree", treeLayout); //using Polyline Router var polylineRouter = new EdgeRouter { Grid = new Grid(0, 0, 10), PolylineRouting = true, Rerouting = true }; polylineRouter.DefaultEdgeLayoutDescriptor.PenaltySettings.BendPenalty = 3; polylineRouter.DefaultEdgeLayoutDescriptor.PenaltySettings.EdgeCrossingPenalty = 5; layouts.Add("Polyline Edge Router", polylineRouter); }
private void ConfigureOutputRestrictions(GraphControl graphControl, OrganicLayout layout) { var viewInfoIsAvailable = false; var visibleRect = GetVisibleRectangle(graphControl); double x = 0, y = 0, w = 0, h = 0; if (visibleRect != null) { viewInfoIsAvailable = true; x = visibleRect[0]; y = visibleRect[1]; w = visibleRect[2]; h = visibleRect[3]; } switch (RestrictOutputItem) { case EnumOutputRestrictions.None: layout.ComponentLayoutEnabled = true; layout.OutputRestriction = OutputRestriction.None; break; case EnumOutputRestrictions.OutputCage: if (!viewInfoIsAvailable || !RectCageUseViewItem) { x = CageXItem; y = CageYItem; w = CageWidthItem; h = CageHeightItem; } layout.OutputRestriction = OutputRestriction.CreateRectangularCageRestriction(x, y, w, h); layout.ComponentLayoutEnabled = false; break; case EnumOutputRestrictions.OutputAr: double ratio; if (viewInfoIsAvailable && ArCageUseViewItem) { ratio = w / h; } else { ratio = CageRatioItem; } layout.OutputRestriction = OutputRestriction.CreateAspectRatioRestriction(ratio); layout.ComponentLayoutEnabled = true; ((ComponentLayout)layout.ComponentLayout).PreferredSize = new YDimension(ratio * 100, 100); break; case EnumOutputRestrictions.OutputEllipticalCage: if (!viewInfoIsAvailable || !RectCageUseViewItem) { x = CageXItem; y = CageYItem; w = CageWidthItem; h = CageHeightItem; } layout.OutputRestriction = OutputRestriction.CreateEllipticalCageRestriction(x, y, w, h); layout.ComponentLayoutEnabled = false; break; } }
protected override LayoutData CreateConfiguredLayoutData(GraphControl graphControl, ILayoutAlgorithm layout) { var layoutData = new HierarchicLayoutData(); var incrementalLayout = SelectedElementsIncrementallyItem; var selection = graphControl.Selection; var selectedElements = selection.SelectedEdges.Any() || selection.SelectedNodes.Any(); if (incrementalLayout && selectedElements) { // configure the mode var ihf = ((HierarchicLayout)layout).CreateIncrementalHintsFactory(); layoutData.IncrementalHints.Delegate = item => { // Return the correct hint type for each model item that appears in one of these sets if (item is INode && selection.IsSelected(item)) { return(ihf.CreateLayerIncrementallyHint(item)); } if (item is IEdge && selection.IsSelected(item)) { return(ihf.CreateSequenceIncrementallyHint(item)); } return(null); }; } if (RankingPolicyItem == LayeringStrategy.Bfs) { layoutData.BfsLayererCoreNodes.Delegate = selection.IsSelected; } if (GridEnabledItem) { var nld = ((HierarchicLayout)layout).NodeLayoutDescriptor; layoutData.NodeLayoutDescriptors.Delegate = node => { var descriptor = new NodeLayoutDescriptor(); descriptor.LayerAlignment = nld.LayerAlignment; descriptor.MinimumDistance = nld.MinimumDistance; descriptor.MinimumLayerHeight = nld.MinimumLayerHeight; descriptor.NodeLabelMode = nld.NodeLabelMode; // anchor nodes on grid according to their alignment within the layer descriptor.GridReference = new YPoint(0.0, (nld.LayerAlignment - 0.5) * node.Layout.Height); descriptor.PortAssignment = this.GridPortAssignmentItem; return(descriptor); }; } if (EdgeDirectednessItem) { layoutData.EdgeDirectedness.Delegate = edge => { if (edge.Style is IArrowOwner && !Equals(((IArrowOwner)edge.Style).TargetArrow, Arrows.None)) { return(1); } return(0); }; } if (EdgeThicknessItem) { layoutData.EdgeThickness.Delegate = edge => { var style = edge.Style as PolylineEdgeStyle; if (style != null) { return(style.Pen.Thickness); } return(1); }; } if (SubComponentsItem) { // layout all siblings with label 'TL' separately with tree layout var treeLayout = new TreeLayout { DefaultNodePlacer = new LeftRightNodePlacer() }; foreach (var listOfNodes in FindSubComponents(graphControl.Graph, "TL")) { layoutData.SubComponents.Add(treeLayout).Items = listOfNodes; } // layout all siblings with label 'HL' separately with hierarchical layout var hierarchicLayout = new HierarchicLayout { LayoutOrientation = LayoutOrientation.LeftToRight }; foreach (var listOfNodes in FindSubComponents(graphControl.Graph, "HL")) { layoutData.SubComponents.Add(hierarchicLayout).Items = listOfNodes; } // layout all siblings with label 'OL' separately with organic layout var organicLayout = new OrganicLayout { PreferredEdgeLength = 100, Deterministic = true }; foreach (var listOfNodes in FindSubComponents(graphControl.Graph, "OL")) { layoutData.SubComponents.Add(organicLayout).Items = listOfNodes; } } if (HighlightCriticalPath) { // highlight the longest path in the graph as critical path // since the longest path algorithm only works for acyclic graphs, // feedback edges and self loops have to be excluded here var feedbackEdgeSetResult = new FeedbackEdgeSet().Run(graphControl.Graph); var longestPath = new LongestPath { SubgraphEdges = { Excludes = { Delegate = edge => feedbackEdgeSetResult.FeedbackEdgeSet.Contains(edge) || edge.IsSelfloop() } } }.Run(graphControl.Graph); if (longestPath.Edges.Any()) { layoutData.CriticalEdgePriorities.Delegate = edge => { if (longestPath.Edges.Contains(edge)) { return(10); } return(1); }; } } if (AutomaticBusRouting) { var allBusNodes = new HashSet <INode>(); foreach (var node in graphControl.Graph.Nodes) { if (!graphControl.Graph.IsGroupNode(node) && !allBusNodes.Contains(node)) { // search for good opportunities for bus structures rooted at this node if (graphControl.Graph.InDegree(node) >= 4) { var busDescriptor = new BusDescriptor(); var busEdges = GetBusEdges(graphControl.Graph, node, allBusNodes, graphControl.Graph.InEdgesAt(node)); if (busEdges.Any()) { layoutData.Buses.Add(busDescriptor).Items = busEdges; } } if (graphControl.Graph.OutDegree(node) >= 4) { var busDescriptor = new BusDescriptor(); var busEdges = GetBusEdges(graphControl.Graph, node, allBusNodes, graphControl.Graph.OutEdgesAt(node)); if (busEdges.Any()) { layoutData.Buses.Add(busDescriptor).Items = busEdges; } } } } } return(layoutData.CombineWith( CreateLabelingLayoutData( graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem ) )); }
/// <summary> /// Run a layout and an analysis algorithm if wanted. /// </summary> /// <param name="incremental">Whether to run in incremental mode, i.e. only moving new items.</param> /// <param name="clearUndo">Whether to clear the undo queue after the layout.</param> /// <param name="runAlgorithm">Whether to apply the <see cref="CurrentConfig">current analysis algorithm</see>, too.</param> /// <returns></returns> private async Task RunLayout(bool incremental, bool clearUndo, bool runAlgorithm) { // the actual organic layout var layout = new OrganicLayout { Deterministic = true, ConsiderNodeSizes = true, Scope = incremental ? Scope.MainlySubset : Scope.All, LabelingEnabled = false, PreferredEdgeLength = 100, MinimumNodeDistance = 10 }; ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.None | ComponentArrangementStyles.ModifierNoOverlap; OrganicLayoutData layoutData = null; if (incremental && incrementalNodesMapper != null) { layoutData = new OrganicLayoutData(); layoutData.AffectedNodes.Mapper = incrementalNodesMapper; } inLayout = true; SetUiDisabled(true); // run the layout in an asynchronous, animated fashion await graphControl.MorphLayout(layout, TimeSpan.FromSeconds(0.5), layoutData); // run algorithm if (runAlgorithm) { // apply graph algorithms after layout ApplyAlgorithm(); var algorithm = algorithmComboBox.SelectedItem as Algorithm; if (algorithm != null && algorithm.DisplayName.EndsWith("Centrality")) { // since centrality changes the node sizes, node overlaps need to be removed await graphControl.MorphLayout(new OrganicRemoveOverlapsStage(), TimeSpan.FromSeconds(0.2)); } } // labeling: place labels after the layout and the analysis (which might have generated or changed labels) var labeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, Deterministic = true }; var labelingData = new LabelingData { EdgeLabelPreferredPlacement = { Delegate = label => { var preferredPlacementDescriptor = new PreferredPlacementDescriptor(); if ("Centrality".Equals(label.Tag)) { preferredPlacementDescriptor.SideOfEdge = LabelPlacements.OnEdge; } else { preferredPlacementDescriptor.SideOfEdge = LabelPlacements.RightOfEdge | LabelPlacements.LeftOfEdge; preferredPlacementDescriptor.DistanceToEdge = 5; } preferredPlacementDescriptor.Freeze(); return(preferredPlacementDescriptor); } } }; await graphControl.MorphLayout(labeling, TimeSpan.FromSeconds(0.2), labelingData); // cleanup if (clearUndo) { graphControl.Graph.GetUndoEngine().Clear(); } // clean up data provider incrementalNodesMapper.Clear(); // enable the UI's buttons ReleaseLocks(); SetUiDisabled(false); UpdateUiState(); }
protected override LayoutData CreateConfiguredLayoutData(GraphControl graphControl, ILayoutAlgorithm layout) { var layoutData = new HierarchicLayoutData(); var incrementalLayout = SelectedElementsIncrementallyItem; var selection = graphControl.Selection; var selectedElements = selection.SelectedEdges.Any() || selection.SelectedNodes.Any(); if (incrementalLayout && selectedElements) { // configure the mode var ihf = ((HierarchicLayout)layout).CreateIncrementalHintsFactory(); layoutData.IncrementalHints.Delegate = item => { // Return the correct hint type for each model item that appears in one of these sets if (item is INode && selection.IsSelected(item)) { return(ihf.CreateLayerIncrementallyHint(item)); } if (item is IEdge && selection.IsSelected(item)) { return(ihf.CreateSequenceIncrementallyHint(item)); } return(null); }; } if (RankingPolicyItem == LayeringStrategy.Bfs) { layoutData.BfsLayererCoreNodes.Delegate = selection.IsSelected; } if (GridEnabledItem) { var nld = ((HierarchicLayout)layout).NodeLayoutDescriptor; layoutData.NodeLayoutDescriptors.Delegate = node => { var descriptor = new NodeLayoutDescriptor(); descriptor.LayerAlignment = nld.LayerAlignment; descriptor.MinimumDistance = nld.MinimumDistance; descriptor.MinimumLayerHeight = nld.MinimumLayerHeight; descriptor.NodeLabelMode = nld.NodeLabelMode; // anchor nodes on grid according to their alignment within the layer descriptor.GridReference = new YPoint(0.0, (nld.LayerAlignment - 0.5) * node.Layout.Height); descriptor.PortAssignment = this.GridPortAssignmentItem; return(descriptor); }; } if (EdgeDirectednessItem) { layoutData.EdgeDirectedness.Delegate = edge => { if (edge.Style is IArrowOwner && !Equals(((IArrowOwner)edge.Style).TargetArrow, Arrows.None)) { return(1); } return(0); }; } if (EdgeThicknessItem) { layoutData.EdgeThickness.Delegate = edge => { var style = edge.Style as PolylineEdgeStyle; if (style != null) { return(style.Pen.Width); } return(1); }; } if (SubComponentsItem) { var treeLayout = new TreeLayout { DefaultNodePlacer = new LeftRightNodePlacer() }; layoutData.SubComponents.Add(treeLayout).Delegate = node => node.Labels.Any() && node.Labels.First().Text == "TL"; var hierarchicLayout = new HierarchicLayout { LayoutOrientation = LayoutOrientation.LeftToRight }; layoutData.SubComponents.Add(hierarchicLayout).Delegate = node => node.Labels.Any() && node.Labels.First().Text == "HL"; var organicLayout = new OrganicLayout { PreferredEdgeLength = 100, Deterministic = true }; layoutData.SubComponents.Add(organicLayout).Delegate = node => node.Labels.Any() && node.Labels.First().Text == "OL"; } if (BusesItem) { // Group edges ending at a node with the label "Bus" into a bus layoutData.Buses.Add(new BusDescriptor()).Delegate = edge => edge.GetTargetNode().Labels.Count > 0 && edge.GetTargetNode().Labels[0].Text == "Bus"; } return(layoutData); }
/// <summary> /// Lays out the graph with nodes that are laid out incrementally. /// </summary> /// <param name="incrementalNodes">Nodes that should be inserted into the graph incrementally.</param> private async Task ApplyLayout(HashSet <INode> incrementalNodes) { toolStrip.Enabled = false; // We'll use an OrganicLayout with OrganicEdgeRouter to get a pleasing image for most databases var layout = new OrganicLayout { NodeEdgeOverlapAvoided = true, NodeOverlapsAllowed = false, PreferredEdgeLength = 180, MinimumNodeDistance = 80, StarSubstructureStyle = StarSubstructureStyle.Radial, StarSubstructureSize = 3, ConsiderNodeSizes = true, CycleSubstructureStyle = CycleSubstructureStyle.Circular, StarSubstructureTypeSeparation = false, LabelingEnabled = true, ParallelEdgeRouterEnabled = true, Scope = incrementalNodes.Count > 0 ? Scope.MainlySubset : Scope.All }; layout.PrependStage(new OrganicEdgeRouter() { ConsiderExistingBends = false, KeepExistingBends = false, EdgeNodeOverlapAllowed = false, RouteAllEdges = false, MinimumDistance = 10 }); // GenericLabeling ensures that labels don't overlap layout.PrependStage(new GenericLabeling { RemoveNodeOverlaps = true }); // CurveFittingLayoutStage adds Bezier control points so we can use BezierEdgeStyle to render the edges layout.PrependStage(new CurveFittingLayoutStage()); var layoutData = new CompositeLayoutData( new OrganicLayoutData { NodeTypes = { Delegate = node => ((INeo4jNode)node.Tag).Labels[0] }, AffectedNodes = { Source = incrementalNodes }, }, new LabelingData { EdgeLabelPreferredPlacement = { Constant = new PreferredPlacementDescriptor { AngleReference = LabelAngleReferences.RelativeToEdgeFlow, PlaceAlongEdge = LabelPlacements.AtSource, SideOfEdge = LabelPlacements.RightOfEdge | LabelPlacements.LeftOfEdge } } } ); await graphControl.MorphLayout(layout, TimeSpan.FromMilliseconds(700), layoutData); toolStrip.Enabled = true; }
public BusinessModelAdapterWindow() { InitializeComponent(); // create a sample list of customers // create the template Customer dummyCustomer = new Customer("Enter A Name", 0); customers = new ObservableCollection <Customer>(); this.Resources.Add("DummyCustomer", dummyCustomer); Customer customer1 = new Customer("Mr. Tester", 42); Customer customer2 = new Customer("Mrs. Tester", 43); Customer customer3 = new Customer("Baby Tester", 2); Customer customer4 = new Customer("Aunt Tester", 34); this.customers.Add(customer1); this.customers.Add(customer2); this.customers.Add(customer3); this.customers.Add(customer4); // add some relationships between customers customer2.RelatedCustomers.Add(customer3); customer2.RelatedCustomers.Add(customer4); customer1.RelatedCustomers.Add(customer2); customer2.RelatedCustomers.Add(customer1); // publish the list so that the listview can pick it up this.Resources.Add("Customers", this.customers); // configure the GraphControl GraphEditorInputMode editorInputMode = new GraphEditorInputMode(); // configure some structural edits editorInputMode.CreateBendInputMode.Enabled = false; editorInputMode.ShowHandleItems = GraphItemTypes.Edge; editorInputMode.DeletableItems = GraphItemTypes.None; editorInputMode.CreateEdgeInputMode.Enabled = true; editorInputMode.CreateEdgeInputMode.EdgeCreator = EdgeCreator; // register custom code for the creation of new entities editorInputMode.NodeCreator = NodeCreator; // set the mode graphControl.InputMode = editorInputMode; // define the default edge style ArcEdgeStyle style = new ArcEdgeStyle { Pen = new Pen(Brushes.Black, 2), Height = 30, TargetArrow = Arrows.Default, ProvideHeightHandle = false }; Graph.EdgeDefaults.Style = style; // fetch the node style from the xaml templates customerNodeStyle = new NodeControlNodeStyle("CustomerNodeStyle") { OutlineShape = new System.Windows.Shapes.Rectangle { RadiusX = 3, RadiusY = 3 } }; // now create the graph from the bindinglist CreateGraph(this.customers); // register for change notification ((INotifyCollectionChanged)customers).CollectionChanged += customers_CollectionChanged; layout = CreateLayout(); }
public static void Main() { DefaultLayoutGraph graph = new DefaultLayoutGraph(); //construct graph and assign sizes to its nodes Node[] nodes = new Node[16]; for (int i = 0; i < 16; i++) { nodes[i] = graph.CreateNode(); graph.SetSize(nodes[i], 30, 30); } graph.CreateEdge(nodes[0], nodes[1]); graph.CreateEdge(nodes[0], nodes[2]); graph.CreateEdge(nodes[0], nodes[3]); graph.CreateEdge(nodes[0], nodes[14]); graph.CreateEdge(nodes[2], nodes[4]); graph.CreateEdge(nodes[3], nodes[5]); graph.CreateEdge(nodes[3], nodes[6]); graph.CreateEdge(nodes[3], nodes[9]); graph.CreateEdge(nodes[4], nodes[7]); graph.CreateEdge(nodes[4], nodes[8]); graph.CreateEdge(nodes[5], nodes[9]); graph.CreateEdge(nodes[6], nodes[10]); graph.CreateEdge(nodes[7], nodes[11]); graph.CreateEdge(nodes[8], nodes[12]); graph.CreateEdge(nodes[8], nodes[15]); graph.CreateEdge(nodes[9], nodes[13]); graph.CreateEdge(nodes[10], nodes[13]); graph.CreateEdge(nodes[10], nodes[14]); graph.CreateEdge(nodes[12], nodes[15]); GraphViewer gv = new GraphViewer(); //using organic layout style OrganicLayout organic = new OrganicLayout(); organic.QualityTimeRatio = 1.0; organic.NodeOverlapsAllowed = false; organic.MinimumNodeDistance = 10; organic.PreferredEdgeLength = 40; new BufferedLayout(organic).ApplyLayout(graph); LayoutGraphUtilities.ClipEdgesOnBounds(graph); gv.AddLayoutGraph(new CopiedLayoutGraph(graph), "Organic Layout Style"); //using orthogonal edge router (node positions stay fixed) EdgeRouter router = new EdgeRouter(); new BufferedLayout(router).ApplyLayout(graph); gv.AddLayoutGraph(new CopiedLayoutGraph(graph), "Polyline Edge Router"); //using orthogonal layout style OrthogonalLayout orthogonal = new OrthogonalLayout(); orthogonal.GridSpacing = 15; orthogonal.OptimizePerceivedBends = true; new BufferedLayout(orthogonal).ApplyLayout(graph); gv.AddLayoutGraph(new CopiedLayoutGraph(graph), "Orthogonal Layout Style"); //using circular layout style CircularLayout circular = new CircularLayout(); circular.BalloonLayout.MinimumEdgeLength = 20; circular.BalloonLayout.CompactnessFactor = 0.1; new BufferedLayout(circular).ApplyLayout(graph); LayoutGraphUtilities.ClipEdgesOnBounds(graph); gv.AddLayoutGraph(new CopiedLayoutGraph(graph), "Circular Layout Style"); //using hierarchical layout style var hierarchic = new HierarchicLayout(); new BufferedLayout(hierarchic).ApplyLayout(graph); gv.AddLayoutGraph(graph, "Hierarchical Layout Style"); var application = new System.Windows.Application(); application.Run(gv); }