public double DistanceSquared(Vector2D p, out int iNearSeg, out double fNearSegT) { iNearSeg = -1; fNearSegT = double.MaxValue; double dist = double.MaxValue; int N = vertices.Count; for (int vi = 0; vi < N; ++vi) { Segment2d seg = new Segment2d(vertices[vi], vertices[(vi + 1) % N]); double t = (p - seg.Center).Dot(seg.Direction); double d = double.MaxValue; if (t >= seg.Extent) { d = seg.P1.DistanceSquared(p); } else if (t <= -seg.Extent) { d = seg.P0.DistanceSquared(p); } else { d = (seg.PointAt(t) - p).LengthSquared; } if (d < dist) { dist = d; iNearSeg = vi; fNearSegT = t; } } return(dist); }
public static Segment2d Project(this Segment2d _host, Segment2d _seg) { //project each end point double t0 = _host.Project(_seg.P0); double t1 = _host.Project(_seg.P1); t0 = MathUtil.Clamp(t0, -1.0 * _host.Extent, _host.Extent); t1 = MathUtil.Clamp(t1, -1.0 * _host.Extent, _host.Extent); if (t0.IsAlmostEqualByDifference(t1)) { return(new Segment2d(Vector2d.Zero, Vector2d.Zero)); } var p0 = _host.PointAt(t0); var p1 = _host.PointAt(t1); return(new Segment2d(p0, p1)); }
// yikes not robust at all!! protected List <Segment2d> compute_polygon_ray_spans(GeneralPolygon2d poly, Segment2d ray, Vector2d axis_origin, Vector2d axis, double axisT, SegmentSet2d segments) { List <double> hits = new List <double>(); // todo reusable buffer segments.FindAllIntersections(ray, hits, null, null, false); hits.Sort(); bool clean = true; for (int i = 0; i < hits.Count - 1 && clean; ++i) { if (hits[i + 1] - hits[i] < MathUtil.Epsilonf) { clean = false; } } if (!clean) { hits = extract_valid_segments(poly, ray, hits); } if (hits.Count % 2 != 0) { throw new Exception("DenseLineFill.ComputeAllSpans: have not handled hard cases..."); } List <Segment2d> spans = new List <Segment2d>(); for (int i = 0; i < hits.Count / 2; ++i) { Vector2d p0 = ray.PointAt(hits[2 * i]); Vector2d p1 = ray.PointAt(hits[2 * i + 1]); spans.Add(new Segment2d(p0, p1)); } return(spans); }
/// <summary> /// hits is a sorted list of t-values along ray. This function /// tries to pull out the valid pairs, ie where the segment between the /// pair is inside poly. /// /// numerical problems: /// - no guarantee that all intersection t's are in hits list /// (although we are being conservative in SegmentSet2d, testing extent+eps) /// - poly.Contains() could return false for points very near to border /// (in unfortunate case this means we discard valid segments. in /// pathological case it means we produce invalid ones) /// </summary> List <double> extract_valid_segments(GeneralPolygon2d poly, Segment2d ray, List <double> hits) { double eps = MathUtil.Epsilonf; List <double> result = new List <double>(); int i = 0; int j = i + 1; while (j < hits.Count) { // find next non-dupe while (j < hits.Count && hits[j] - hits[i] < eps) { j++; } if (j == hits.Count) { continue; } // ok check if midpoint is inside or outside double mid_t = (hits[i] + hits[j]) * 0.5; Vector2d mid = ray.PointAt(mid_t); // not robust...eek bool isInside = poly.Contains(mid); if (isInside) { // ok we add this segment, and then we start looking at next point (?) result.Add(hits[i]); result.Add(hits[j]); i = j + 1; j = i + 1; } else { // ok we were not inside, so start search at j i = j; j++; } } return(result); }
public Vector2D PointAt(int iSegment, double fSegT) { Segment2d seg = new Segment2d(vertices[iSegment], vertices[(iSegment + 1) % vertices.Count]); return(seg.PointAt(fSegT)); }