private static void SetPreferredSide(PreferredPlacementDescriptor newDescriptor, PreferredPlacementDescriptor oldDescriptor, ILabelModel model) { if (model is EdgeSegmentLabelModel) { var rotatedModel = model as EdgeSegmentLabelModel; var onEdge = (rotatedModel.SideOfEdge & EdgeSides.OnEdge) == EdgeSides.OnEdge; newDescriptor.SideOfEdge = onEdge ? LabelPlacements.OnEdge : LabelPlacements.RightOfEdge | LabelPlacements.LeftOfEdge; newDescriptor.DistanceToEdge = rotatedModel.Distance; } }
private static void AddEdgeLabelPlacementDescriptors(LayoutGraphAdapter adapter) { var atSourceDescriptor = new PreferredPlacementDescriptor { PlaceAlongEdge = LabelPlacements.AtSourcePort, SideOfEdge = LabelPlacements.LeftOfEdge | LabelPlacements.RightOfEdge, }; adapter.AddDataProvider(LayoutGraphAdapter.EdgeLabelLayoutPreferredPlacementDescriptorDpKey, Mappers.FromDelegate((ILabel label) => { var edgeType = ((BpmnEdgeStyle)((IEdge)label.Owner).Style).Type; if (edgeType == EdgeType.SequenceFlow || edgeType == EdgeType.DefaultFlow || edgeType == EdgeType.ConditionalFlow) { // labels on sequence, default and conditional flow edges should be placed at the source side. return(atSourceDescriptor); } return(null); })); }
/// <summary> /// Creates a new <see cref="PreferredPlacementDescriptor"/> that matches the given settings. /// </summary> public PreferredPlacementDescriptor CreatePreferredPlacementDescriptor( EnumLabelPlacementAlongEdge placeAlongEdge, EnumLabelPlacementSideOfEdge sideOfEdge, EnumLabelPlacementOrientation orientation, double distanceToEdge) { var descriptor = new PreferredPlacementDescriptor(); switch (sideOfEdge) { case EnumLabelPlacementSideOfEdge.Anywhere: descriptor.SideOfEdge = LabelPlacements.Anywhere; break; case EnumLabelPlacementSideOfEdge.OnEdge: descriptor.SideOfEdge = LabelPlacements.OnEdge; break; case EnumLabelPlacementSideOfEdge.Left: descriptor.SideOfEdge = LabelPlacements.LeftOfEdge; break; case EnumLabelPlacementSideOfEdge.Right: descriptor.SideOfEdge = LabelPlacements.RightOfEdge; break; case EnumLabelPlacementSideOfEdge.LeftOrRight: descriptor.SideOfEdge = LabelPlacements.LeftOfEdge | LabelPlacements.RightOfEdge; break; } switch (placeAlongEdge) { case EnumLabelPlacementAlongEdge.Anywhere: descriptor.PlaceAlongEdge = LabelPlacements.Anywhere; break; case EnumLabelPlacementAlongEdge.AtSourcePort: descriptor.PlaceAlongEdge = LabelPlacements.AtSourcePort; break; case EnumLabelPlacementAlongEdge.AtTargetPort: descriptor.PlaceAlongEdge = LabelPlacements.AtTargetPort; break; case EnumLabelPlacementAlongEdge.AtSource: descriptor.PlaceAlongEdge = LabelPlacements.AtSource; break; case EnumLabelPlacementAlongEdge.AtTarget: descriptor.PlaceAlongEdge = LabelPlacements.AtTarget; break; case EnumLabelPlacementAlongEdge.Centered: descriptor.PlaceAlongEdge = LabelPlacements.AtCenter; break; } switch (orientation) { case EnumLabelPlacementOrientation.Parallel: descriptor.Angle = 0.0d; descriptor.AngleReference = LabelAngleReferences.RelativeToEdgeFlow; break; case EnumLabelPlacementOrientation.Orthogonal: descriptor.Angle = Math.PI / 2; descriptor.AngleReference = LabelAngleReferences.RelativeToEdgeFlow; break; case EnumLabelPlacementOrientation.Horizontal: descriptor.Angle = 0.0d; descriptor.AngleReference = LabelAngleReferences.Absolute; break; case EnumLabelPlacementOrientation.Vertical: descriptor.Angle = Math.PI / 2; descriptor.AngleReference = LabelAngleReferences.Absolute; break; } descriptor.DistanceToEdge = distanceToEdge; return(descriptor); }
private void UpdateLabelValues(IEnumerable <ILabel> labels) { if (descriptorMapper == null) { return; } var handler = Handler; foreach (var edgeLabel in labels) { if (edgeLabel.Owner is INode || edgeLabel.Owner is IPort) { // this demo shouldn't have node or port labels but we make sure that nothing goes wrong continue; } var prototype = descriptorMapper[edgeLabel]; var descriptor = new PreferredPlacementDescriptor(prototype); var item = handler.GetItemByName(LabelText); if (item.Value != OptionItem.VALUE_UNDEFINED) { graphControl.Graph.SetLabelText(edgeLabel, (string)item.Value); } item = handler.GetItemByName(PlacementAlongEdge); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.PlaceAlongEdge = (LabelPlacements)item.Value; } item = handler.GetItemByName(PlacementSideOfEdge); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.SideOfEdge = (LabelPlacements)item.Value; } item = handler.GetItemByName(PlacementSideReference); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.SideReference = (LabelSideReferences)item.Value; } item = handler.GetItemByName(Angle); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.Angle = Geom.ToRadians((double)item.Value); } item = handler.GetItemByName(AngleReference); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.AngleReference = (LabelAngleReferences)item.Value; } item = handler.GetItemByName(AngleRotation); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.AngleRotationOnRightSide = (LabelAngleOnRightSideRotations)item.Value; } item = handler.GetItemByName(AngleAdd180Degree); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.AngleOffsetOnRightSide = GetLabelAngleOnRightSideOffset((bool)item.Value); } item = handler.GetItemByName(PlacementDistance); if (item.Value != OptionItem.VALUE_UNDEFINED) { descriptor.DistanceToEdge = (double)item.Value; } if (!descriptor.Equals(prototype)) { descriptorMapper[edgeLabel] = descriptor; } } }
public static void Main() { DefaultLayoutGraph graph = new DefaultLayoutGraph(); //construct graph. assign sizes to nodes Node v1 = graph.CreateNode(); graph.SetSize(v1, 30, 30); Node v2 = graph.CreateNode(); graph.SetSize(v2, 30, 30); Node v3 = graph.CreateNode(); graph.SetSize(v3, 30, 30); // add a label to one node var nodeLabelLayoutModel = new DiscreteNodeLabelLayoutModel(DiscreteNodeLabelPositions.InternalMask, 4); var labelLayoutFactory = LayoutGraphUtilities.GetLabelFactory(graph); labelLayoutFactory.AddLabelLayout(v1, labelLayoutFactory.CreateLabelLayout(v1, new YOrientedRectangle(0, 0, 80, 20), nodeLabelLayoutModel)); Edge e1 = graph.CreateEdge(v1, v2); Edge e2 = graph.CreateEdge(v1, v3); // add a label to an edge var edgeLabelLayoutModel = new SliderEdgeLabelLayoutModel(SliderMode.Side); labelLayoutFactory.AddLabelLayout(e1, labelLayoutFactory.CreateLabelLayout(e1, new YOrientedRectangle(0, 0, 80, 20), edgeLabelLayoutModel, PreferredPlacementDescriptor.NewSharedInstance(LabelPlacements.LeftOfEdge))); //optionally setup some port constraints for HierarchicLayout IEdgeMap spc = graph.CreateEdgeMap(); IEdgeMap tpc = graph.CreateEdgeMap(); //e1 shall leave and enter the node on the right side spc.Set(e1, PortConstraint.Create(PortSide.East, false)); //additionally set a strong port constraint on the target side. tpc.Set(e1, PortConstraint.Create(PortSide.East, true)); //ports with strong port constraints will not be reset by the //layout algorithm. So we specify the target port right now to connect //to the upper left corner of the node graph.SetTargetPointRel(e1, new YPoint(15, -15)); //e2 shall leave and enter the node on the top side spc.Set(e2, PortConstraint.Create(PortSide.North, false)); tpc.Set(e2, PortConstraint.Create(PortSide.North, false)); graph.AddDataProvider(PortConstraintKeys.SourcePortConstraintDpKey, spc); graph.AddDataProvider(PortConstraintKeys.TargetPortConstraintDpKey, tpc); HierarchicLayout layout = new HierarchicLayout(); layout.IntegratedEdgeLabeling = true; layout.ConsiderNodeLabels = true; layout.LayoutMode = LayoutMode.FromScratch; new BufferedLayout(layout).ApplyLayout(graph); Console.WriteLine("\n\nGRAPH LAID OUT HIERARCHICALLY FROM SCRATCH"); Console.WriteLine("v1 center position = " + graph.GetCenter(v1)); Console.WriteLine("v2 center position = " + graph.GetCenter(v2)); Console.WriteLine("v3 center position = " + graph.GetCenter(v3)); Console.WriteLine("e1 path = " + graph.GetPath(e1)); Console.WriteLine("e2 path = " + graph.GetPath(e2)); //display the graph in a simple viewer GraphViewer gv = new GraphViewer(); gv.AddLayoutGraph(new CopiedLayoutGraph(graph), "Before Addition"); // now add a node and two edges incrementally... Node v4 = graph.CreateNode(); graph.SetSize(v4, 30, 30); Edge e4 = graph.CreateEdge(v4, v2); Edge e3 = graph.CreateEdge(v1, v4); //mark elements as newly added so that the layout algorithm can place //them nicely. IIncrementalHintsFactory ihf = layout.CreateIncrementalHintsFactory(); IDataMap map = Maps.CreateHashedDataMap(); map.Set(v4, ihf.CreateLayerIncrementallyHint(v4)); map.Set(e3, ihf.CreateSequenceIncrementallyHint(e3)); map.Set(e4, ihf.CreateSequenceIncrementallyHint(e4)); graph.AddDataProvider(HierarchicLayout.IncrementalHintsDpKey, map); layout.LayoutMode = LayoutMode.Incremental; new BufferedLayout(layout).ApplyLayout(graph); Console.WriteLine("\n\nGRAPH AFTER ELEMENTS HAVE BEEN ADDED INCREMENTALLY"); Console.WriteLine("v1 center position = " + graph.GetCenter(v1)); Console.WriteLine("v2 center position = " + graph.GetCenter(v2)); Console.WriteLine("v3 center position = " + graph.GetCenter(v3)); Console.WriteLine("v4 center position = " + graph.GetCenter(v4)); Console.WriteLine("e1 path = " + graph.GetPath(e1)); Console.WriteLine("e2 path = " + graph.GetPath(e2)); Console.WriteLine("e3 path = " + graph.GetPath(e3)); Console.WriteLine("e4 path = " + graph.GetPath(e4)); //clean up data maps graph.RemoveDataProvider(HierarchicLayout.IncrementalHintsDpKey); //display the graph in a simple viewer gv.AddLayoutGraph(new CopiedLayoutGraph(graph), "After Addition"); Application.Run(gv); }
/// <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(); }
public static void Main() { DefaultLayoutGraph graph = new DefaultLayoutGraph(); //construct graph. assign sizes to nodes Node v1 = graph.CreateNode(); graph.SetSize(v1, 30, 30); Node v2 = graph.CreateNode(); graph.SetSize(v2, 30, 30); Node v3 = graph.CreateNode(); graph.SetSize(v3, 30, 30); Edge e1 = graph.CreateEdge(v1, v2); Edge e2 = graph.CreateEdge(v2, v3); Edge e3 = graph.CreateEdge(v1, v3); //optionally setup some port constraints for HierarchicLayout IEdgeMap spc = graph.CreateEdgeMap(); IEdgeMap tpc = graph.CreateEdgeMap(); //e1 shall leave and enter the node on the right side spc.Set(e1, PortConstraint.Create(PortSide.East)); //additionally set a strong port constraint on the target side. tpc.Set(e1, PortConstraint.Create(PortSide.East, true)); //ports with strong port constraints will not be reset by the //layout algorithm. So we specify the target port right now to connect //to the upper left corner of the node graph.SetTargetPointRel(e1, new YPoint(15, -15)); //e2 shall leave and enter the node on the top side spc.Set(e2, PortConstraint.Create(PortSide.North)); tpc.Set(e2, PortConstraint.Create(PortSide.North)); //e3 uses no port constraints, i.e. layout will choose best side graph.AddDataProvider(PortConstraintKeys.SourcePortConstraintDpKey, spc); graph.AddDataProvider(PortConstraintKeys.TargetPortConstraintDpKey, tpc); //setup two edge labels for edge e1. The size of the edge labels will be set to //80x20. Usually the size of the labels will be determined by //calculaing the bounding box of a piece text that is displayed //with a specific font. var labelFactory = LayoutGraphUtilities.GetLabelFactory(graph); graph.SetLabelLayout(e1, new[] { CreateEdgeLabelLayout(labelFactory, e1, new SliderEdgeLabelLayoutModel(SliderMode.Center), PreferredPlacementDescriptor.NewSharedInstance(LabelPlacements.AtCenter)), CreateEdgeLabelLayout(labelFactory, e1, new SliderEdgeLabelLayoutModel(SliderMode.Side), PreferredPlacementDescriptor.NewSharedInstance(LabelPlacements.LeftOfEdge)) }); var layout = new HierarchicLayout(); layout.LabelingEnabled = true; layout.Labeling = new GenericLabeling(); new BufferedLayout(layout).ApplyLayout(graph); Console.WriteLine("\n\nGRAPH LAID OUT USING GENERIC EDGE LABELING"); Console.WriteLine("v1 center position = " + graph.GetCenter(v1)); Console.WriteLine("v2 center position = " + graph.GetCenter(v2)); Console.WriteLine("v3 center position = " + graph.GetCenter(v3)); Console.WriteLine("e1 path = " + graph.GetPath(e1)); Console.WriteLine("e2 path = " + graph.GetPath(e2)); Console.WriteLine("e3 path = " + graph.GetPath(e3)); Console.WriteLine("ell1 upper left location = " + GetEdgeLabelLocation(graph, e1, CreateEdgeLabelLayout(labelFactory, e1, new SliderEdgeLabelLayoutModel(SliderMode.Center), PreferredPlacementDescriptor.NewSharedInstance(LabelPlacements.AtCenter)))); Console.WriteLine("ell2 upper left location = " + GetEdgeLabelLocation(graph, e1, graph.GetLabelLayout(e1)[1])); GraphViewer gv = new GraphViewer(); gv.AddLayoutGraph(new CopiedLayoutGraph(graph), "Layout with Generic Labeling"); var freeModel = new FreeEdgeLabelLayoutModel(); graph.SetLabelLayout(e1, new[] { CreateEdgeLabelLayout(labelFactory, e1, freeModel, PreferredPlacementDescriptor.NewSharedInstance(LabelPlacements.AtCenter)), CreateEdgeLabelLayout(labelFactory, e1, freeModel, PreferredPlacementDescriptor.NewSharedInstance(LabelPlacements.LeftOfEdge)) }); layout.LabelingEnabled = true; layout.Labeling = new LabelLayoutTranslator(); new BufferedLayout(layout).ApplyLayout(graph); Console.WriteLine("\n\nGRAPH LAID OUT USING HIERACHIC LAYOUT SPECIFIC EDGE LABELING"); Console.WriteLine("v1 center position = " + graph.GetCenter(v1)); Console.WriteLine("v2 center position = " + graph.GetCenter(v2)); Console.WriteLine("v3 center position = " + graph.GetCenter(v3)); Console.WriteLine("e1 path = " + graph.GetPath(e1)); Console.WriteLine("e2 path = " + graph.GetPath(e2)); Console.WriteLine("e3 path = " + graph.GetPath(e3)); Console.WriteLine("ell1 upper left location = " + GetEdgeLabelLocation(graph, e1, CreateEdgeLabelLayout(labelFactory, e1, new SliderEdgeLabelLayoutModel(SliderMode.Center), PreferredPlacementDescriptor.NewSharedInstance(LabelPlacements.AtCenter)))); Console.WriteLine("ell2 upper left location = " + GetEdgeLabelLocation(graph, e1, graph.GetLabelLayout(e1)[1])); //display the result in a simple viewer gv.AddLayoutGraph(graph, "Layout with Integrated Labeling"); var application = new System.Windows.Application(); application.Run(gv); }
private static IEdgeLabelLayout CreateEdgeLabelLayout(ILabelLayoutFactory labelFactory, Edge edge, IEdgeLabelLayoutModel edgeLabelModel, PreferredPlacementDescriptor preferredPlacementDescriptor) { var label = labelFactory.CreateLabelLayout(edge, new YOrientedRectangle(0, 0, 80, 20), edgeLabelModel, preferredPlacementDescriptor); label.ModelParameter = edgeLabelModel.DefaultParameter; return(label); }