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