コード例 #1
0
        /// <summary>
        /// If we are at edge eid, which as one vertex prev_vid, find 'other' vertex, and other edge connected to that vertex,
        /// and return pair [next_edge, shared_vtx]
        /// Returns [int.MaxValue, shared_vtx] if shared_vtx is not valence=2   (ie stops at boundaries and complex junctions)
        /// </summary>
        public static Index2i NextEdgeAndVtx(int eid, int prev_vid, DGraph2 graph)
        {
            Index2i ev = graph.GetEdgeV(eid);

            if (ev.a == DGraph2.InvalidID)
            {
                return(Index2i.Max);
            }

            int next_vid = (ev.a == prev_vid) ? ev.b : ev.a;

            if (graph.GetVtxEdgeCount(next_vid) != 2)
            {
                return(new Index2i(int.MaxValue, next_vid));
            }

            foreach (int next_eid in graph.VtxEdgesItr(next_vid))
            {
                if (next_eid != eid)
                {
                    return(new Index2i(next_eid, next_vid));
                }
            }
            return(Index2i.Max);
        }
コード例 #2
0
        /// <summary>
        /// walk through graph from fromVtx, in direction of eid, until we hit the next junction vertex
        /// </summary>
        public static List <int> WalkToNextNonRegularVtx(DGraph2 graph, int fromVtx, int eid)
        {
            List <int> path = new List <int>();

            path.Add(fromVtx);
            int  cur_vid   = fromVtx;
            int  cur_eid   = eid;
            bool bContinue = true;

            while (bContinue)
            {
                Index2i next     = DGraph2Util.NextEdgeAndVtx(cur_eid, cur_vid, graph);
                int     next_eid = next.a;
                int     next_vtx = next.b;
                if (next_eid == int.MaxValue)
                {
                    if (graph.IsRegularVertex(next_vtx) == false)
                    {
                        path.Add(next_vtx);
                        bContinue = false;
                    }
                    else
                    {
                        throw new Exception("WalkToNextNonRegularVtx: have no next edge but vtx is regular - how?");
                    }
                }
                else
                {
                    path.Add(next_vtx);
                    cur_vid = next_vtx;
                    cur_eid = next_eid;
                }
            }
            return(path);
        }
コード例 #3
0
        /// <summary>
        /// Find and remove any junction (ie valence>2) vertices of the graph.
        /// At a junction, the pair of best-aligned (ie straightest) edges are left
        /// connected, and all the other edges are disconnected
        ///
        /// [TODO] currently there is no DGraph2.SetEdge(), so the 'other' edges
        /// are deleted and new edges inserted. Hence, edge IDs are not preserved.
        /// </summary>
        public static int DisconnectJunctions(DGraph2 graph)
        {
            var junctions = new List <int>();

            // find all junctions
            foreach (int vid in graph.VertexIndices())
            {
                if (graph.IsJunctionVertex(vid))
                {
                    junctions.Add(vid);
                }
            }


            foreach (int vid in junctions)
            {
                Vector2d v         = graph.GetVertex(vid);
                int[]    nbr_verts = graph.VtxVerticesItr(vid).ToArray();

                // find best-aligned pair of edges connected to vid
                Index2i best_aligned = Index2i.Max; double max_angle = 0;
                for (int i = 0; i < nbr_verts.Length; ++i)
                {
                    for (int j = i + 1; j < nbr_verts.Length; ++j)
                    {
                        double angle = Vector2d.AngleD(
                            (graph.GetVertex(nbr_verts[i]) - v).Normalized,
                            (graph.GetVertex(nbr_verts[j]) - v).Normalized);
                        angle = Math.Abs(angle);
                        if (angle > max_angle)
                        {
                            max_angle    = angle;
                            best_aligned = new Index2i(nbr_verts[i], nbr_verts[j]);
                        }
                    }
                }

                // for nbr verts that are not part of the best_aligned edges,
                // we remove those edges and add a new one connected to a new vertex
                for (int k = 0; k < nbr_verts.Length; ++k)
                {
                    if (nbr_verts[k] == best_aligned.a || nbr_verts[k] == best_aligned.b)
                    {
                        continue;
                    }

                    int eid = graph.FindEdge(vid, nbr_verts[k]);
                    graph.RemoveEdge(eid, true);
                    if (graph.IsVertex(nbr_verts[k]))
                    {
                        var newpos = Vector2d.Lerp(graph.GetVertex(nbr_verts[k]), v, 0.99);
                        int newv   = graph.AppendVertex(newpos);
                        graph.AppendEdge(nbr_verts[k], newv);
                    }
                }
            }

            return(junctions.Count);
        }
コード例 #4
0
        public static void QuickWrite(DGraph2 graph, string sPath, double line_width = 1)
        {
            SVGWriter writer = new SVGWriter();
            Style     style  = SVGWriter.Style.Outline("black", (float)line_width);

            writer.AddGraph(graph, style);
            writer.Write(sPath);
        }
コード例 #5
0
        public Arrangement2d(AxisAlignedBox2d boundsHint)
        {
            Graph = new DGraph2();

            double cellSize = boundsHint.MaxDim / 64;

            PointHash = new PointHashGrid2d <int>(cellSize, -1);
        }
コード例 #6
0
        private static int MergeAppendVertex(DGraph2 graph, Vector2d vertex, double mergeThreshold)
        {
            for (int i = 0; i < graph.VertexCount; i++)
            {
                double d = vertex.Distance(graph.GetVertex(i));
                if (d < mergeThreshold)
                {
                    return(i);
                }
            }

            return(graph.AppendVertex(vertex));
        }
コード例 #7
0
        /// <summary>
        /// compute length of path through graph
        /// </summary>
        public static double PathLength(DGraph2 graph, IList <int> pathVertices)
        {
            double   len = 0;
            int      N = pathVertices.Count;
            Vector2d prev = graph.GetVertex(pathVertices[0]), next = Vector2d.Zero;

            for (int i = 1; i < N; ++i)
            {
                next = graph.GetVertex(pathVertices[i]);
                len += prev.Distance(next);
                prev = next;
            }
            return(len);
        }
コード例 #8
0
 public void AppendGraph(DGraph2 graph, int gid = -1)
 {
     int[] mapV = new int[graph.MaxVertexID];
     foreach (int vid in graph.VertexIndices())
     {
         mapV[vid] = this.AppendVertex(graph.GetVertex(vid));
     }
     foreach (int eid in graph.EdgeIndices())
     {
         Index2i ev      = graph.GetEdgeV(eid);
         int     use_gid = (gid == -1) ? graph.GetEdgeGroup(eid) : gid;
         this.AppendEdge(mapV[ev.a], mapV[ev.b], use_gid);
     }
 }
コード例 #9
0
        private static void MergeAppendPolyline(DGraph2 graph, PolyLine2d polyline, double mergeThreshold, int gid = -1)
        {
            int previousVertexIndex = -1;

            foreach (var vertex in polyline)
            {
                int currentVertexIndex = MergeAppendVertex(graph, vertex, mergeThreshold);
                if (previousVertexIndex != -1)
                {
                    graph.AppendEdge(previousVertexIndex, currentVertexIndex, gid);
                }
                previousVertexIndex = currentVertexIndex;
            }
        }
コード例 #10
0
        /// <summary>
        /// Stitches together any PolyLines in a collection that share endpoints
        /// </summary>
        /// <remarks>
        /// If more than two PolyLine instances share an endpoint, none of the instances will be combined.
        ///
        /// This method is currently implemented using DGraph2.ExtractCurves, so order and orientation of the original
        /// PolyLine instances may not be preserved.
        /// </remarks>
        /// <param name="polylines">The collection of PolyLines to combine</param>
        /// <param name="mergeThreshold">Maximum distance between endpoints that will be considered shared between PolyLines</param>
        /// <returns>Collection of new PolyLine instances</returns>

        public static List <PolyLine2d> CombineConnectedPolyLines(IEnumerable <PolyLine2d> polylines, double mergeThreshold)
        {
            var graph = new DGraph2();

            foreach (var polyline in polylines)
            {
                MergeAppendPolyline(graph, polyline, mergeThreshold);
            }
            var curves = DGraph2Util.ExtractCurves(graph);

            var result = new List <PolyLine2d>();

            result.AddRange(curves.Paths);
            result.AddRange(curves.Loops.ConvertAll(PolyLineToPolygonConverter));
            return(result);
        }
コード例 #11
0
        /// <summary>
        /// foreach edge [vid,b] connected to junction vertex vid, remove, add new vertex c,
        /// and then add new edge [b,c]. Optionally move c a bit back along edge from vid.
        /// </summary>
        public static void DisconnectJunction(DGraph2 graph, int vid, double shrinkFactor = 1.0)
        {
            Vector2d v = graph.GetVertex(vid);

            int[] nbr_verts = graph.VtxVerticesItr(vid).ToArray();
            for (int k = 0; k < nbr_verts.Length; ++k)
            {
                int eid = graph.FindEdge(vid, nbr_verts[k]);
                graph.RemoveEdge(eid, true);
                if (graph.IsVertex(nbr_verts[k]))
                {
                    Vector2d newpos = Vector2d.Lerp(graph.GetVertex(nbr_verts[k]), v, shrinkFactor);
                    int      newv   = graph.AppendVertex(newpos);
                    graph.AppendEdge(nbr_verts[k], newv);
                }
            }
        }
コード例 #12
0
        void write_graph(DGraph2 graph, StreamWriter w)
        {
            string style = get_style(graph, ref DefaultDGraphStyle);

            StringBuilder b = new StringBuilder();

            foreach (int eid in graph.EdgeIndices())
            {
                Segment2d seg = graph.GetEdgeSegment(eid);
                b.Append("<line ");
                append_property("x1", seg.P0.x, b, true);
                append_property("y1", seg.P0.y, b, true);
                append_property("x2", seg.P1.x, b, true);
                append_property("y2", seg.P1.y, b, true);
                b.Append(style);
                b.Append(" />");
                b.AppendLine();
            }
            w.WriteLine(b);
        }
コード例 #13
0
        /// <summary>
        /// If vid has two or more neighbours, returns uniform laplacian, otherwise returns vid position
        /// </summary>
        public static Vector2d VertexLaplacian(DGraph2 graph, int vid, out bool isValid)
        {
            Vector2d v        = graph.GetVertex(vid);
            Vector2d centroid = Vector2d.Zero;
            int      n        = 0;

            foreach (int vnbr in graph.VtxVerticesItr(vid))
            {
                centroid += graph.GetVertex(vnbr);
                n++;
            }
            if (n == 2)
            {
                centroid /= n;
                isValid   = true;
                return(centroid - v);
            }
            isValid = false;
            return(v);
        }
コード例 #14
0
 public GraphCells2d(DGraph2 graph)
 {
     Graph = graph;
 }
コード例 #15
0
 public DGraph2Resampler(DGraph2 graph)
 {
     this.Graph = graph;
 }
コード例 #16
0
 public GraphSplitter2d(DGraph2 graph)
 {
     Graph = graph;
 }
コード例 #17
0
 public DGraph2(DGraph2 copy) : base()
 {
     vertices = new DVector <double>();
     AppendGraph(copy);
 }
コード例 #18
0
 public void AddGraph(DGraph2 graph)
 {
     Objects.Add(graph);
     Bounds.Contain(graph.GetBounds());
 }
コード例 #19
0
        public static bool FindRayIntersection(Vector2d o, Vector2d d, out int hit_eid, out double hit_ray_t, DGraph2 graph)
        {
            Line2d   line = new Line2d(o, d);
            Vector2d a = Vector2d.Zero, b = Vector2d.Zero;

            int    near_eid = DGraph2.InvalidID;
            double near_t   = double.MaxValue;

            IntrLine2Segment2 intr = new IntrLine2Segment2(line, new Segment2d(a, b));

            foreach (int eid in graph.VertexIndices())
            {
                graph.GetEdgeV(eid, ref a, ref b);
                intr.Segment = new Segment2d(a, b);
                if (intr.Find() && intr.IsSimpleIntersection && intr.Parameter > 0)
                {
                    if (intr.Parameter < near_t)
                    {
                        near_eid = eid;
                        near_t   = intr.Parameter;
                    }
                }
            }

            hit_eid   = near_eid;
            hit_ray_t = near_t;
            return(hit_ray_t < double.MaxValue);
        }
コード例 #20
0
        /// <summary>
        /// Decompose graph into simple polylines and polygons.
        /// </summary>
        public static Curves ExtractCurves(DGraph2 graph)
        {
            Curves c = new Curves();

            c.Loops = new List <Polygon2d>();
            c.Paths = new List <PolyLine2d>();

            HashSet <int> used = new HashSet <int>();

            // find boundary and junction vertices
            HashSet <int> boundaries = new HashSet <int>();
            HashSet <int> junctions  = new HashSet <int>();

            foreach (int vid in graph.VertexIndices())
            {
                if (graph.IsBoundaryVertex(vid))
                {
                    boundaries.Add(vid);
                }
                if (graph.IsJunctionVertex(vid))
                {
                    junctions.Add(vid);
                }
            }

            // walk paths from boundary vertices
            foreach (int start_vid in boundaries)
            {
                int vid = start_vid;
                int eid = graph.GetVtxEdges(vid)[0];
                if (used.Contains(eid))
                {
                    continue;
                }

                PolyLine2d path = new PolyLine2d();
                path.AppendVertex(graph.GetVertex(vid));
                while (true)
                {
                    used.Add(eid);
                    Index2i next = NextEdgeAndVtx(eid, vid, graph);
                    eid = next.a;
                    vid = next.b;
                    path.AppendVertex(graph.GetVertex(vid));
                    if (boundaries.Contains(vid) || junctions.Contains(vid))
                    {
                        break;  // done!
                    }
                }
                c.Paths.Add(path);
            }

            // ok we should be done w/ boundary verts now...
            boundaries.Clear();


            foreach (int start_vid in junctions)
            {
                foreach (int outgoing_eid in graph.VtxEdgesItr(start_vid))
                {
                    if (used.Contains(outgoing_eid))
                    {
                        continue;
                    }
                    int vid = start_vid;
                    int eid = outgoing_eid;

                    PolyLine2d path = new PolyLine2d();
                    path.AppendVertex(graph.GetVertex(vid));
                    while (true)
                    {
                        used.Add(eid);
                        Index2i next = NextEdgeAndVtx(eid, vid, graph);
                        eid = next.a;
                        vid = next.b;
                        path.AppendVertex(graph.GetVertex(vid));
                        if (eid == int.MaxValue || junctions.Contains(vid))
                        {
                            break;  // done!
                        }
                    }
                    c.Paths.Add(path);
                }
            }


            // all that should be left are continuous loops...
            foreach (int start_eid in graph.EdgeIndices())
            {
                if (used.Contains(start_eid))
                {
                    continue;
                }

                int     eid = start_eid;
                Index2i ev  = graph.GetEdgeV(eid);
                int     vid = ev.a;

                Polygon2d poly = new Polygon2d();
                poly.AppendVertex(graph.GetVertex(vid));
                while (true)
                {
                    used.Add(eid);
                    Index2i next = NextEdgeAndVtx(eid, vid, graph);
                    eid = next.a;
                    vid = next.b;
                    poly.AppendVertex(graph.GetVertex(vid));
                    if (eid == int.MaxValue || junctions.Contains(vid))
                    {
                        throw new Exception("how did this happen??");
                    }
                    if (used.Contains(eid))
                    {
                        break;
                    }
                }
                poly.RemoveVertex(poly.VertexCount - 1);
                c.Loops.Add(poly);
            }


            return(c);
        }
コード例 #21
0
 public void AddGraph(DGraph2 graph, Style style)
 {
     Objects.Add(graph);
     Styles[graph] = style;
     Bounds.Contain(graph.GetBounds());
 }
コード例 #22
0
 public void AddGraph(DGraph2 graph)
 {
     CurrentLayer.Objects.Add(graph);
     Bounds.Contain(graph.GetBounds());
 }