public void TestUnrelated() { // Super strict... double ang_tol = System.Double.Epsilon; double dist_tol = System.Double.Epsilon; Dictionary <int, bool> seen = new Dictionary <int, bool>(); ISegIdx spidx = GetIndex(dist_tol, ang_tol); LineSegOverlay <NumLineSeg> overlay = new LineSegOverlay <NumLineSeg>(spidx, ang_tol, dist_tol); int idx = 0; foreach (LineSeg l in Take(TestCount, LineSegs)) { overlay.Insert(new NumLineSeg(l, idx++)); } foreach (Pair <LineSeg, IEnumerable <NumLineSeg> > res in overlay.Segments) { bool here = false; foreach (NumLineSeg r in res.Second) { Assert.IsFalse(seen.ContainsKey(r.Idx)); Assert.IsFalse(here); seen[r.Idx] = true; here = true; } } for (int i = 0; i < TestCount; i++) { Assert.IsTrue(seen[i]); } DumpIndex(spidx); }
void OverlayFn(LineSeg a, LineSeg b, double ang_tol, double disttol, out LineSeg before, out bool a_before, out LineSeg overlap, out LineSeg after, out bool a_after) { before = null; a_before = false; overlap = null; after = null; a_after = false; OverlayObj aobj = new OverlayObj(a, true); OverlayObj bobj = new OverlayObj(b, false); double dtol = Math.Sqrt(disttol); LineSegOverlay <OverlayObj> overlay = new LineSegOverlay <OverlayObj>(GetIndex(dtol, ang_tol), ang_tol, dtol); overlay.Insert(aobj); overlay.Insert(bobj); List <Pair <LineSeg, OverlayObj> > nonoverlaps = new List <Pair <LineSeg, OverlayObj> >(); bool have_overlay = false; foreach (Pair <LineSeg, IEnumerable <OverlayObj> > r in overlay.Segments) { int count = 0; bool fsta = false; OverlayObj o = null; foreach (OverlayObj os in r.Second) { o = os; if (count > 0 && os.FromA != fsta) // An overlay. { overlap = r.First; have_overlay = true; } else if (count == 0) { fsta = os.FromA; } count++; } if (count == 1) { nonoverlaps.Add(new Pair <LineSeg, OverlayObj>(r.First, o)); } } if (have_overlay) { foreach (Pair <LineSeg, OverlayObj> ls in nonoverlaps) { double start_tval, end_tval; ls.First.PointDistanceSq(overlap.Start, out start_tval); ls.First.PointDistanceSq(overlap.End, out end_tval); bool dir = (start_tval - disttol <= 0.0); if (dir) { after = ls.First; a_after = ls.Second.FromA; } else { before = ls.First; a_before = ls.Second.FromA; } } } else { overlap = null; before = null; after = null; } }
public void TestBeforeAndAfter() { int count = TestCount; double ang_tol = 0.0001; double dist_tol = 0.000001; Dictionary <int, int> seen = new Dictionary <int, int>(); ISegIdx spidx = GetIndex(dist_tol, ang_tol); LineSegOverlay <NumLineSeg> overlay = new LineSegOverlay <NumLineSeg>(spidx, ang_tol, dist_tol); int idx = 0; LineSeg[] lines = new LineSeg[count]; foreach (LineSeg ll in Take(count, LineSegs)) { LineSeg l = ll; if (idx == 0) { l = LineSeg.FromEndpoints(new Vector(0, 0), new Vector(0, 1)); } lines[idx] = l; idx++; } for (int i = 0; i < lines.Length; i++) { double ta = -0.75; double tb = 0.25; ta = 0.75; tb = 1.75; // The 'before' half: LineSeg bl = LineSeg.FromEndpoints(lines[i].Start + (ta * lines[i].Dir), lines[i].Start + (tb * lines[i].Dir)); // the 'after' half: ta = -0.75; tb = 0.25; LineSeg al = LineSeg.FromEndpoints(lines[i].Start + (ta * lines[i].Dir), lines[i].Start + (tb * lines[i].Dir)); NumLineSeg a = new NumLineSeg(al, count + i); NumLineSeg b = new NumLineSeg(bl, 2 * count + i); NumLineSeg c = new NumLineSeg(lines[i], i); switch (Int(6)) { case 0: overlay.Insert(a); overlay.Insert(b); overlay.Insert(c); break; case 5: overlay.Insert(a); overlay.Insert(c); overlay.Insert(b); break; case 1: overlay.Insert(b); overlay.Insert(a); overlay.Insert(c); break; case 4: overlay.Insert(b); overlay.Insert(c); overlay.Insert(a); break; case 2: overlay.Insert(c); overlay.Insert(b); overlay.Insert(a); break; case 3: overlay.Insert(c); overlay.Insert(a); overlay.Insert(b); break; } } DumpIndex(spidx); int rcount = 0; foreach (Pair <LineSeg, IEnumerable <NumLineSeg> > res in overlay.Segments) { // Console.Error.WriteLine("Res-----"); foreach (NumLineSeg r in res.Second) { // Console.Error.WriteLine(" Portion: " + r.Idx); if (!seen.ContainsKey(r.Idx)) { seen[r.Idx] = 0; } seen[r.Idx]++; } rcount++; } Assert.AreEqual(5 * count, rcount); for (int i = 0; i < 3 * count; i++) { if (i < count) { Assert.AreEqual(3, seen[i]); } if (i > count) { Assert.AreEqual(2, seen[i]); } } }
public void Run(IFeatureClass inp, IFeatureClass outp, ProgressCallback progress) { IFeatureCursor all_inp = inp.Search(null, true); LineSegOverlay <ArcSegInf> op = new LineSegOverlay <ArcSegInf>(new PMQTree(4, 8), m_atol, m_dtol); double inp_count = inp.FeatureCount(null); int steps = (int)Math.Ceiling((double)inp_count / 20.0); int inp_progress = 0; IFeature infeat = all_inp.NextFeature(); while (infeat != null) { int fid = infeat.OID; IGeometryCollection c = infeat.Shape as IGeometryCollection; for (int shell_num = 0; shell_num < c.GeometryCount; shell_num++) { IPointCollection ps = c.get_Geometry(shell_num) as IPointCollection; IPoint last = null; for (int seg_num = 0; seg_num < ps.PointCount; seg_num++) { IPoint cur = ps.get_Point(seg_num); if (last != null) { LineSeg seg = LineSeg.FromEndpoints(new Vector(last.X, last.Y), new Vector(cur.X, cur.Y)); op.Insert(new ArcSegInf(seg, fid, shell_num, seg_num)); m_seensegs++; } last = cur; } } inp_progress++; if (inp_progress % steps == 0) { progress(0.5 * (inp_progress / inp_count)); } infeat = all_inp.NextFeature(); } int lfid = outp.FindField("left_fid"); int rfid = outp.FindField("right_fid"); // Reassemble line strings SegmentAssembler sa = new SegmentAssembler(); foreach (Pair <LineSeg, IEnumerable <ArcSegInf> > r in op.Segments) { int overlap_count = 0; foreach (Pair <ArcSegInf, ArcSegInf> v in Pair <ArcSegInf, ArcSegInf> .Pairs(r.Second)) { OverlapSegment o = new OverlapSegment(r.First, v.First, v.Second); if (v.First.SrcFid < v.Second.SrcFid) { sa.AddSegment(o); } overlap_count++; } if (overlap_count == 0) { // TODO: add exterior boundaries? ArcSegInf seen = null; foreach (ArcSegInf seg in r.Second) { seen = seg; } sa.AddSegment(new OverlapSegment(r.First, seen, null)); } } double outp_count = sa.OverlapCount; int outp_progress = 0; int outp_steps = (int)Math.Ceiling((double)outp_count / 20.0); IFeatureBuffer outfeat = outp.CreateFeatureBuffer(); IFeatureCursor outcursor = outp.Insert(true); foreach (Pair <Pair <int, int>, Pair <int, int> > ss in sa.SegsAndShells) { int rhs_fid = ss.First.First; int rhs_shellid = ss.First.Second; int lhs_fid = ss.Second.First; int lhs_shellid = ss.Second.Second; foreach (Pair <Pair <int, int>, List <LineSeg> > linestring in sa.GetStrings(ss)) { IPolyline line = assemblePolyLine(linestring.Second); outfeat.set_Value(lfid, lhs_fid); outfeat.set_Value(rfid, rhs_fid); outfeat.Shape = line; outcursor.InsertFeature(outfeat); // Same boundary but swapped! outfeat.set_Value(lfid, rhs_fid); outfeat.set_Value(rfid, lhs_fid); outfeat.Shape = line; outcursor.InsertFeature(outfeat); } // progress outp_progress++; if (outp_progress % outp_steps == 0) { progress(0.5 + (0.5 * outp_progress / outp_count)); } } outcursor.Flush(); System.Runtime.InteropServices.Marshal.ReleaseComObject(outcursor); }