public async Task <string> AddGroup(GroupVertex Group, string User) { try { Group.id = Guid.NewGuid().ToString(); Group.Name = Group.Name ?? ""; Group.BackgroundPhotoUrl = Group.BackgroundPhotoUrl ?? ""; Group.Description = Group.Description ?? ""; Group.Admins.Add(User); await client.Add(Group).SubmitAsync(); return(Group.id); } catch (Exception e) { throw (e); } }
public GroupVertex(GroupVertex other) : this(other.groupInfo, other.areaPerVertex) { // Position and location may not exist... Position = new double[] { other.Position[0], other.Position[1] }; Location = new PointF(other.Location.X, other.Location.Y); }
//************************************************************************* // Method: createGroupVertexProximityGraph() // /// <summary> /// Creates the proximity graph (delaunay triangulation) of the node /// positions in the group graph. /// </summary> /// <param name="graph"> /// The group graph to create a proximity graph from. /// </param> /// /// <returns> /// The proximity graph. /// </returns> //************************************************************************* private static Graph createGroupVertexProximityGraph(IGraph graph) { Graph groupProximityGraph = new Graph(GraphDirectedness.Undirected); List<GroupVertex> groupProximityGraphVertices = new List<GroupVertex>(); foreach (GroupVertex groupVertex in graph.Vertices) { // Update group collapsed location with the result of the initial layout //groupVertex.updateGroupInfoLocationAndRectangleFromLocation(areaPerVertex); groupVertex.updatePositionFromLocation(); } foreach (GroupVertex groupVertex in graph.Vertices) { GroupVertex newGroupVertex = new GroupVertex(groupVertex); groupProximityGraphVertices.Add(newGroupVertex); groupProximityGraph.Vertices.Add(newGroupVertex); } // If we have a degenerate case do nothing if (graph.Vertices.Count == 0) { // Do nothing } // If we have fewer group vertices/points than the delaunay triangulation code can handle (0-3) do it manually else if (groupProximityGraphVertices.Count <= 3) { // Connect all the vertices in a clique for (Int32 i = 0; i < groupProximityGraphVertices.Count; i++) { IVertex groupVertex1 = groupProximityGraphVertices.ElementAt(i); for (Int32 j = i + 1; j < groupProximityGraphVertices.Count; j++) { IVertex groupVertex2 = groupProximityGraphVertices.ElementAt(j); groupProximityGraph.Edges.Add(new Edge(groupVertex1, groupVertex2, false)); } } } else { // Use the node positions stored in GroupVertex.Position for the delaunay triangulation // Ensure the position has been set ahead of time (e.g., using groupVertex.updatePositionFromLocation()) ITriangulation<GroupVertex, DefaultTriangulationCell<GroupVertex>> delaunayTriangulation = Triangulation.CreateDelaunay<GroupVertex>(groupProximityGraphVertices); // Each delaunay triangulation cell is a triangle with our group vertices as its vertices // Add edges to the proximity graph from the triangle edges foreach (DefaultTriangulationCell<GroupVertex> cell in delaunayTriangulation.Cells) { Debug.Assert(cell.Vertices.Count() == 3); // Add edges for the three triangle faces groupProximityGraph.Edges.Add(new Edge(cell.Vertices[0], cell.Vertices[1], false)); groupProximityGraph.Edges.Add(new Edge(cell.Vertices[0], cell.Vertices[2], false)); groupProximityGraph.Edges.Add(new Edge(cell.Vertices[1], cell.Vertices[2], false)); } // Two triangles can share an edge, so remove one of them groupProximityGraph.Edges.RemoveDuplicates(); //// Update group vertex location with the positions from the delaunay triangulation //foreach (GroupVertex groupVertex in groupProximityGraph.Vertices) //{ // groupVertex.updateLocationFromPosition(); //} } return groupProximityGraph; }
LayOutGraphUsingForceDirectedGroups ( IGraph oGraph, List<GroupInfo> oGroupsToLayout, LayoutContext oAdjustedLayoutContext, BackgroundWorker oBackgroundWorker ) { Debug.Assert(oGraph != null); Debug.Assert(oAdjustedLayoutContext != null); ///////////////////////////////////////////////////// // Get the initial position for the group vertices // ///////////////////////////////////////////////////// // Determine how much of the screen to use for groups Single areaPerVertex = (Single)GroupRectangleCalculator.GetAreaPerVertex(oAdjustedLayoutContext.GraphRectangle, oGroupsToLayout); areaPerVertex /= 2f; // Customise this value if necessary to have more whitespace between groups -- expose as a user control? // Create a graph for the groups Graph groupInitialGraph = new Graph(GraphDirectedness.Undirected); // Convert GroupInfos into vertices that can be laid out //IEnumerable<GroupVertex> groupInitialGraphVertices = groupsToLayOut.Select<GroupInfo, GroupVertex>(g => new GroupVertex(g, groupInitialGraph)); List<GroupVertex> groupInitialGraphVertices = new List<GroupVertex>(); foreach (GroupInfo groupInfo in oGroupsToLayout) { GroupVertex groupVertex = new GroupVertex(groupInfo, areaPerVertex); groupInitialGraphVertices.Add(groupVertex); groupInitialGraph.Vertices.Add(groupVertex); } Int32 iGroups = oGroupsToLayout.Count; // Add edges between groups IVertexCollection oVertices = groupInitialGraph.Vertices; IEdgeCollection oEdges = groupInitialGraph.Edges; IList<IntergroupEdgeInfo> intergroupEdgeInfos = new IntergroupEdgeCalculator().CalculateGraphMetrics(oGraph, oGroupsToLayout, false); foreach (IntergroupEdgeInfo interGroupEdgeInfo in intergroupEdgeInfos) { IVertex groupVertex1 = oVertices.ElementAt<IVertex>(interGroupEdgeInfo.Group1Index); IVertex groupVertex2 = oVertices.ElementAt<IVertex>(interGroupEdgeInfo.Group2Index); if (groupVertex1 != groupVertex2) { oEdges.Add(groupVertex1, groupVertex2, false); } } // Use Harel-Koren to compute initial group positions, stored in groupVertex.Location ILayout oLayout = new HarelKorenFastMultiscaleLayout(); oLayout.LayOutGraph(groupInitialGraph, oAdjustedLayoutContext); foreach (GroupVertex groupVertex in groupInitialGraph.Vertices) { // If we have too few groups, automatically push them into the AdjustedLayoutContext if (groupInitialGraph.Vertices.Count <= 3) { groupVertex.updateGroupInfoRectangleFromLocation(); groupVertex.groupInfo.Rectangle = GraphicsUtil.RectangleFToRectangle(GraphicsUtil.MoveRectangleWithinBounds(groupVertex.groupInfo.Rectangle, oAdjustedLayoutContext.GraphRectangle, false), 1); RectangleF r = groupVertex.groupInfo.Rectangle; groupVertex.Location = new PointF(r.X + r.Width / 2, r.Y + r.Height / 2); } // Update the meta-node locations groupVertex.updateGroupInfoLocationFromLocation(); } ///////////////////////// // Remove node overlap // ///////////////////////// // while ( overlaps exist along proximity graph edges ) // { // Create proximity graph (delaunay triangulation) // Minimize proxmity graph overlap stress function // } // // while ( any overlaps exist ) // { // Create proximity graph (delaunay triangulation) // Find overlaps (scan-line alg) // Augment proximity graph with edges for overlaps // Minimize proxmity graph overlap stress function // } Boolean initialOverlapInProximityGraph; Int32 iteration = 0; Graph lastGraphAfterFirstPhase = groupInitialGraph; do { Graph groupProximityGraph = createGroupVertexProximityGraph(lastGraphAfterFirstPhase); lastGraphAfterFirstPhase = groupProximityGraph; initialOverlapInProximityGraph = proximityGraphStressMajorization(groupProximityGraph, 1000); iteration++; } while (initialOverlapInProximityGraph == true); /////////////////////////////////////////////////////////////////// // Transform the layout to get the boxes within the LayoutContext// /////////////////////////////////////////////////////////////////// Rectangle boundingRectangle = oAdjustedLayoutContext.GraphRectangle; Int32 overallLeftOffset = Int32.MinValue; Int32 overallTopOffset = Int32.MinValue; Int32 overallRightOffset = Int32.MinValue; Int32 overallBottomOffset = Int32.MinValue; foreach (GroupInfo groupInfo in oGroupsToLayout) { Rectangle groupRectangle = groupInfo.Rectangle; Int32 rectangleLeftOffset = boundingRectangle.Left - groupRectangle.Left; if (rectangleLeftOffset > overallLeftOffset) { overallLeftOffset = rectangleLeftOffset; } Int32 rectangleTopOffset = boundingRectangle.Top - groupRectangle.Top; if (rectangleTopOffset > overallTopOffset) { overallTopOffset = rectangleTopOffset; } Int32 rectangleRightOffset = groupRectangle.Right - boundingRectangle.Right; if (rectangleRightOffset > overallRightOffset) { overallRightOffset = rectangleRightOffset; } Int32 rectangleBottomOffset = groupRectangle.Bottom - boundingRectangle.Bottom; if (rectangleBottomOffset > overallBottomOffset) { overallBottomOffset = rectangleBottomOffset; } } Rectangle newBoundingRectangle = new Rectangle( boundingRectangle.X - overallLeftOffset, boundingRectangle.Y - overallTopOffset, boundingRectangle.Width + overallLeftOffset + overallRightOffset, boundingRectangle.Height + overallTopOffset + overallBottomOffset); // Perform metadata-related tasks. GroupMetadataManager.OnLayoutUsingGroupsEnd(lastGraphAfterFirstPhase, oGroupsToLayout, this.GroupRectanglePenWidth, this.IntergroupEdgeStyle); lastGraphAfterFirstPhase.SetValue(ReservedMetadataKeys.GroupLayoutDrawingInfo, new GroupLayoutDrawingInfo(oGroupsToLayout, this.GroupRectanglePenWidth, null)); //TransformLayout(oGraph, new LayoutContext(newBoundingRectangle), oAdjustedLayoutContext); TransformLayout(lastGraphAfterFirstPhase, new LayoutContext(newBoundingRectangle), oAdjustedLayoutContext); /////////////////////////////////// // Finish with individual groups // /////////////////////////////////// for (Int32 i = 0; i < iGroups; i++) { GroupInfo oGroupInfo = oGroupsToLayout[i]; Rectangle oGroupRectangle = oGroupInfo.Rectangle; oGroupRectangle.Inflate(-m_iMargin, -m_iMargin); // Do not use Rectangle.IsEmpty() here. It returns true only if // the rectangle is at the origin and has zero width and height. if (oGroupRectangle.Width > 0 && oGroupRectangle.Height > 0) { ICollection<IVertex> oVerticesInGroup = oGroupInfo.Vertices; if ( !GetLayoutToUseForGroup(oGraph, oVerticesInGroup). LayOutGraphCore(oGraph, oVerticesInGroup, new LayoutContext(oGroupRectangle), oBackgroundWorker) ) { // LayOutGraphAsyncCancel() was called. return (false); } } else { oGroupRectangle = oGroupInfo.Rectangle; PointF oVertexLocation; if (oGroupRectangle.Width > 0 && oGroupRectangle.Height > 0) { // Put the group's vertices at the rectangle's center. oVertexLocation = new PointF( oGroupRectangle.Left + oGroupRectangle.Width / 2, oGroupRectangle.Top + oGroupRectangle.Height / 2 ); } else { // Put the group's vertices at the rectangle's upper-left // corner. oVertexLocation = new PointF( oGroupRectangle.X, oGroupRectangle.Y ); } foreach (IVertex oVertex in oGroupInfo.Vertices) { oVertex.Location = oVertexLocation; } } } // Perform metadata-related tasks. GroupMetadataManager.OnLayoutUsingGroupsEnd(oGraph, oGroupsToLayout, this.GroupRectanglePenWidth, this.IntergroupEdgeStyle); return (true); }