Beispiel #1
0
 public void AppendGraph(DGraph3 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);
     }
 }
Beispiel #2
0
        public virtual void Generate()
        {
            AxisAlignedBox3d graphBox = Graph.CachedBounds;

            graphBox.Expand(2 * PostRadius);

            double cellSize = (SamplerCellSizeHint == 0) ? (PostRadius / 5) : SamplerCellSizeHint;
            ImplicitFieldSampler3d sampler = new ImplicitFieldSampler3d(graphBox, cellSize);

            ActualCellSize = cellSize;

            // sample segments into graph
            ImplicitLine3d line = new ImplicitLine3d()
            {
                Radius = PostRadius
            };

            foreach (int eid in Graph.EdgeIndices())
            {
                Index2i  ev = Graph.GetEdgeV(eid);
                Vector3d v0 = Graph.GetVertex(ev.a);
                Vector3d v1 = Graph.GetVertex(ev.b);
                double   r  = PostRadius;

                int upper_vid = (v0.y > v1.y) ? ev.a : ev.b;
                if (TipVertices.Contains(upper_vid))
                {
                    r = TipRadius;
                }

                line.Segment = new Segment3d(v0, v1);
                line.Radius  = r;
                sampler.Sample(line, line.Radius / 2);
            }

            foreach (int vid in GroundVertices)
            {
                Vector3d v = Graph.GetVertex(vid);
                sampler.Sample(new ImplicitSphere3d()
                {
                    Origin = v - (PostRadius / 2) * Vector3d.AxisY, Radius = GroundRadius
                });
            }


            ImplicitHalfSpace3d cutPlane = new ImplicitHalfSpace3d()
            {
                Origin = Vector3d.Zero, Normal = Vector3d.AxisY
            };
            ImplicitDifference3d cut = new ImplicitDifference3d()
            {
                A = sampler.ToImplicit(), B = cutPlane
            };

            MarchingCubes mc = new MarchingCubes()
            {
                Implicit = cut, Bounds = graphBox, CubeSize = PostRadius / 3
            };

            mc.Bounds.Min.y  = -2 * mc.CubeSize;
            mc.Bounds.Min.x -= 2 * mc.CubeSize; mc.Bounds.Min.z -= 2 * mc.CubeSize;
            mc.Bounds.Max.x += 2 * mc.CubeSize; mc.Bounds.Max.z += 2 * mc.CubeSize;
            mc.CancelF       = this.Cancelled;
            mc.Generate();

            ResultMesh = mc.Mesh;
        }
Beispiel #3
0
        /// <summary>
        /// Decompose graph into simple polylines and polygons.
        /// </summary>
        public static Curves ExtractCurves(DGraph3 graph)
        {
            Curves c = new Curves();

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

            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;
                }

                DCurve3 path = new DCurve3()
                {
                    Closed = false
                };
                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;

                    DCurve3 path = new DCurve3()
                    {
                        Closed = false
                    };
                    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!
                        }
                    }

                    // we could end up back at our start junction vertex!
                    if (vid == start_vid)
                    {
                        path.RemoveVertex(path.VertexCount - 1);
                        path.Closed = true;
                        c.Loops.Add(path);
                        // need to mark incoming edge as used...but is it valid now?
                        //Util.gDevAssert(eid != int.MaxValue);
                        if (eid != int.MaxValue)
                        {
                            used.Add(eid);
                        }
                    }
                    else
                    {
                        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;

                DCurve3 poly = new DCurve3()
                {
                    Closed = true
                };
                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);
        }
Beispiel #4
0
        /// <summary>
        /// Decompose graph into simple polylines and polygons.
        /// </summary>
        public static Curves ExtractCurves(DGraph3 graph,
                                           bool bWantLoopIndices = false,
                                           Func <int, bool> CurveOrientationF = null)
        {
            var c = new Curves();

            c.Loops = new List <DCurve3>();
            c.Paths = new List <DCurve3>();
            if (bWantLoopIndices)
            {
                c.LoopEdges = new List <List <int> >();
                c.PathEdges = new List <List <int> >();
            }

            var used = new HashSet <int>();

            // find boundary and junction vertices
            var boundaries = new HashSet <int>();
            var 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;
                }

                bool reverse = (CurveOrientationF != null) ? CurveOrientationF(eid) : false;

                var path = new DCurve3()
                {
                    Closed = false
                };
                List <int> pathE = (bWantLoopIndices) ? new List <int>() : null;
                path.AppendVertex(graph.GetVertex(vid));
                if (pathE != null)
                {
                    pathE.Add(eid);
                }

                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!
                    }

                    if (pathE != null)
                    {
                        pathE.Add(eid);
                    }
                }
                if (reverse)
                {
                    path.Reverse();
                }

                c.Paths.Add(path);

                if (pathE != null)
                {
                    Util.gDevAssert(pathE.Count == path.VertexCount - 1);
                    if (reverse)
                    {
                        pathE.Reverse();
                    }

                    c.PathEdges.Add(pathE);
                }
            }

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


            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;

                    bool reverse = (CurveOrientationF != null) ? CurveOrientationF(eid) : false;

                    var path = new DCurve3()
                    {
                        Closed = false
                    };
                    List <int> pathE = (bWantLoopIndices) ? new List <int>() : null;
                    path.AppendVertex(graph.GetVertex(vid));
                    if (pathE != null)
                    {
                        pathE.Add(eid);
                    }

                    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!
                        }

                        if (pathE != null)
                        {
                            pathE.Add(eid);
                        }
                    }

                    // we could end up back at our start junction vertex!
                    if (vid == start_vid)
                    {
                        path.RemoveVertex(path.VertexCount - 1);
                        path.Closed = true;
                        if (reverse)
                        {
                            path.Reverse();
                        }

                        c.Loops.Add(path);

                        if (pathE != null)
                        {
                            Util.gDevAssert(pathE.Count == path.VertexCount);
                            if (reverse)
                            {
                                pathE.Reverse();
                            }

                            c.LoopEdges.Add(pathE);
                        }

                        // need to mark incoming edge as used...but is it valid now?
                        //Util.gDevAssert(eid != int.MaxValue);
                        if (eid != int.MaxValue)
                        {
                            used.Add(eid);
                        }
                    }
                    else
                    {
                        if (reverse)
                        {
                            path.Reverse();
                        }

                        c.Paths.Add(path);

                        if (pathE != null)
                        {
                            Util.gDevAssert(pathE.Count == path.VertexCount - 1);
                            if (reverse)
                            {
                                pathE.Reverse();
                            }

                            c.PathEdges.Add(pathE);
                        }
                    }
                }
            }
            c.JunctionV = junctions;


            // 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;

                bool reverse = (CurveOrientationF != null) ? CurveOrientationF(eid) : false;

                var poly = new DCurve3()
                {
                    Closed = true
                };
                List <int> polyE = (bWantLoopIndices) ? new List <int>() : null;
                poly.AppendVertex(graph.GetVertex(vid));
                if (polyE != null)
                {
                    polyE.Add(eid);
                }

                while (true)
                {
                    used.Add(eid);
                    Index2i next = NextEdgeAndVtx(eid, vid, graph);
                    eid = next.a;
                    vid = next.b;
                    poly.AppendVertex(graph.GetVertex(vid));
                    if (polyE != null)
                    {
                        polyE.Add(eid);
                    }

                    if (eid == int.MaxValue || junctions.Contains(vid))
                    {
                        throw new Exception("how did this happen??");
                    }

                    if (used.Contains(eid))
                    {
                        break;
                    }
                }
                poly.RemoveVertex(poly.VertexCount - 1);
                if (reverse)
                {
                    poly.Reverse();
                }

                c.Loops.Add(poly);

                if (polyE != null)
                {
                    polyE.RemoveAt(polyE.Count - 1);
                    Util.gDevAssert(polyE.Count == poly.VertexCount);
                    if (reverse)
                    {
                        polyE.Reverse();
                    }

                    c.LoopEdges.Add(polyE);
                }
            }

            return(c);
        }