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); }
/// <summary> /// insert edge [a,b] into the arrangement, splitting existing edges as necessary /// </summary> protected bool insert_segment(ref Vector2d a, ref Vector2d b, int gid = -1, double tol = 0) { // handle degenerate edges int a_idx = find_existing_vertex(a); int b_idx = find_existing_vertex(b); if (a_idx == b_idx && a_idx >= 0) { return(false); } // ok find all intersections List <Intersection> hits = new List <Intersection>(); find_intersecting_edges(ref a, ref b, hits, tol); int N = hits.Count; // we are going to construct a list of <t,vertex_id> values along segment AB List <SegmentPoint> points = new List <SegmentPoint>(); Segment2d segAB = new Segment2d(a, b); // insert intersections into existing segments for (int i = 0; i < N; ++i) { Intersection intr = hits[i]; int eid = intr.eid; double t0 = intr.intr.Parameter0, t1 = intr.intr.Parameter1; // insert first point at t0 int new_eid = -1; if (intr.intr.Type == IntersectionType.Point || intr.intr.Type == IntersectionType.Segment) { Index2i new_info = split_segment_at_t(eid, t0, VertexSnapTol); new_eid = new_info.b; Vector2d v = Graph.GetVertex(new_info.a); points.Add(new SegmentPoint() { t = segAB.Project(v), vid = new_info.a }); } // if intersection was on-segment, then we have a second point at t1 if (intr.intr.Type == IntersectionType.Segment) { if (new_eid == -1) { // did not actually split edge for t0, so we can still use eid Index2i new_info = split_segment_at_t(eid, t1, VertexSnapTol); Vector2d v = Graph.GetVertex(new_info.a); points.Add(new SegmentPoint() { t = segAB.Project(v), vid = new_info.a }); } else { // find t1 was in eid, rebuild in new_eid Segment2d new_seg = Graph.GetEdgeSegment(new_eid); Vector2d p1 = intr.intr.Segment1.PointAt(t1); double new_t1 = new_seg.Project(p1); Util.gDevAssert(new_t1 <= Math.Abs(new_seg.Extent)); Index2i new_info = split_segment_at_t(new_eid, new_t1, VertexSnapTol); Vector2d v = Graph.GetVertex(new_info.a); points.Add(new SegmentPoint() { t = segAB.Project(v), vid = new_info.a }); } } } // find or create start and end points if (a_idx == -1) { a_idx = find_existing_vertex(a); } if (a_idx == -1) { a_idx = Graph.AppendVertex(a); PointHash.InsertPointUnsafe(a_idx, a); } if (b_idx == -1) { b_idx = find_existing_vertex(b); } if (b_idx == -1) { b_idx = Graph.AppendVertex(b); PointHash.InsertPointUnsafe(b_idx, b); } // add start/end to points list. These may be duplicates but we will sort that out after points.Add(new SegmentPoint() { t = segAB.Project(a), vid = a_idx }); points.Add(new SegmentPoint() { t = segAB.Project(b), vid = b_idx }); // sort by t points.Sort((pa, pb) => { return((pa.t < pb.t) ? -1 : ((pa.t > pb.t) ? 1 : 0)); }); // connect sequential points, as long as they aren't the same point, // and the segment doesn't already exist for (int k = 0; k < points.Count - 1; ++k) { int v0 = points[k].vid; int v1 = points[k + 1].vid; if (v0 == v1) { continue; } if (Math.Abs(points[k].t - points[k + 1].t) < MathUtil.Epsilonf) { System.Console.WriteLine("insert_segment: different points with same t??"); } if (Graph.FindEdge(v0, v1) == DGraph2.InvalidID) { Graph.AppendEdge(v0, v1, gid); } } return(true); }