Example #1
0
        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);
    }