public static IEnumerable <LineSegment2> AsLineSegments(this IEnumerable <Vector2> points) { foreach (var pair in points.AsPairs()) { yield return(LineSegment2.FromOriginAndDestination(pair.Item1, pair.Item2)); } }
public Intersection(LineSegment2 line1, LineSegment2 line2) : this() { Line1 = line1; Line2 = line2; var p = line1.End1; var q = line2.End1; var r = line1.ToVector2(); var s = line2.ToVector2(); var denom = r.Cross(s); if (denom == 0) { // The lines are parallel and there's no intersection HasIntersection = false; Distance1 = double.NaN; Distance2 = double.NaN; return; } var t = (q - p).Cross(s)/denom; var u = (q - p).Cross(r)/denom; Point = p + r*t; Distance1 = t; Distance2 = u; HasIntersection = true; }
public void AssertThat_IntersectionWithSegment_IntersectsDiagonalSegment() { var r = new BoundingRectangle(new Vector2(0, 0), new Vector2(10, 10)); var l = new LineSegment2(new Vector2(-10, -10), new Vector2(20, 20)); Assert.IsTrue(r.Intersects(l).HasValue); }
private static IEnumerable <Point2> GetPoints(LineSegment2 entity, float elementSize, bool revert) { var numElements = (int)Math.Ceiling(entity.Length / elementSize); var points = new Point2[numElements]; var start = entity.Vertex1; var end = entity.Vertex2; if (revert) { for (var i = numElements; i > 0; i--) { points[numElements - i] = new Point2(start.X + i * (end.X - start.X) / numElements, start.Y + i * (end.Y - start.Y) / numElements); } } else { for (var i = 0; i < numElements; i++) { points[i] = new Point2(start.X + i * (end.X - start.X) / numElements, start.Y + i * (end.Y - start.Y) / numElements); } } return(points); }
public void TestEquality(string lineAStr, string lineBStr) { var lineA = LineSegment2.Parse(lineAStr); var lineB = LineSegment2.Parse(lineBStr); Assert.AreEqual(lineA, lineB); }
public List <OSMWay> GetWaysIntersectingLine(LatitudeLongitude point1, LatitudeLongitude point2) { List <OSMWay> output = new List <OSMWay>(); try { foreach (OSMWay way in Ways) { if (way.BoundingBox.IntersectsLine(point1, point2)) { for (int i = 0; i < way.NodeReferences.Count - 1; i++) { OSMNode thisNode, thatNode; if (!NodesById.TryGetValue(way.NodeReferences[i], out thisNode) || !NodesById.TryGetValue(way.NodeReferences[i + 1], out thatNode)) { continue; } Point2 intersectionPoint = LineSegment2.Intersection(point1, point2, thisNode.Location, thatNode.Location); if (intersectionPoint != null) { output.Add(way); } } } } return(output); } catch (Exception ex) { LogHelper.LogException(ex, "Error getting intersecting ways", true); } return(output); }
private static HalfEdge <TVertexTag, THalfEdgeTag, TFaceTag> FindHalfEdge <TVertexTag, THalfEdgeTag, TFaceTag>(Face <TVertexTag, THalfEdgeTag, TFaceTag> face, Vector2 point) { Contract.Requires(face != null); Contract.Ensures(Contract.Result <HalfEdge <TVertexTag, THalfEdgeTag, TFaceTag> >() != null); Contract.Ensures(!Contract.Result <HalfEdge <TVertexTag, THalfEdgeTag, TFaceTag> >().IsDeleted); HalfEdge <TVertexTag, THalfEdgeTag, TFaceTag> winner = null; var score = float.MaxValue; foreach (var halfEdge in face.Edges) { var closest = new LineSegment2(halfEdge.EndVertex.Position, halfEdge.Pair.EndVertex.Position).ClosestPoint(point); var d = Vector2.DistanceSquared(closest, point); if (d < score) { winner = halfEdge; score = d; } } if (score > 0.05f) { throw new InvalidOperationException("Closest edge is too far"); } return(winner); }
protected BuildingSideInfo[] GetNeighbourInfo(Prism bounds) { Contract.Ensures(Contract.Result <BuildingSideInfo[]>() != null); Contract.Ensures(Contract.Result <BuildingSideInfo[]>().Length == bounds.Footprint.Count); var sides = new BuildingSideInfo[bounds.Footprint.Count]; for (var i = 0; i < bounds.Footprint.Count; i++) { //Start and end point of this segment var a = bounds.Footprint[i]; var b = bounds.Footprint[(i + 1) % bounds.Footprint.Count]; var seg = new LineSegment2(a, b).Transform(WorldTransformation); var line = seg.Line; //Neighbours which are for this segment var ns = from n in (Neighbours ?? new NeighbourInfo[0]) where (n.Segment.Line.Parallelism(line) == Parallelism.Collinear) let result = ExtractDataFromUnknownNode(n.Neighbour) select new BuildingSideInfo.NeighbourInfo(n.Start, n.End, result.Key, result.Value); //Save the results sides[i] = new BuildingSideInfo(a, b, ns.ToArray()); } return(sides); }
public Intersection(LineSegment2 line1, LineSegment2 line2) : this() { Line1 = line1; Line2 = line2; var p = line1.End1; var q = line2.End1; var r = line1.ToVector2(); var s = line2.ToVector2(); var denom = r.Cross(s); if (denom == 0) { // The lines are parallel and there's no intersection HasIntersection = false; Distance1 = double.NaN; Distance2 = double.NaN; return; } var t = (q - p).Cross(s) / denom; var u = (q - p).Cross(r) / denom; Point = p + r * t; Distance1 = t; Distance2 = u; HasIntersection = true; }
[TestCase("(10,10) (10,100)", "(0,303) (0,500)", true)] // Two vert lines public void IsParallelTo(string line1Str, string line2Str, bool expected) { var line1 = LineSegment2.Parse(line1Str); var line2 = LineSegment2.Parse(line2Str); Assert.AreEqual(expected, line1.IsParallelTo(line2)); }
private IEnumerable <NeighbourInfo> CalculateNeighbours(KeyValuePair <Parcel, ISubdivisionContext> subject, NeighbourSet <ISubdivisionContext> nodes) { foreach (var edge in subject.Key.Edges) { var query = new LineSegment2(edge.Start, edge.End); var neighbours = nodes.Neighbours(query, MathHelper.ToRadians(5), 1); foreach (var neighbour in neighbours) { //Do not add self as a neighbour! if (neighbour.Value.Equals(subject.Value)) { continue; } yield return(new NeighbourInfo( neighbour.Value, neighbour.Segment.Transform(WorldTransformation), neighbour.SegmentOverlapStart, neighbour.SegmentOverlapEnd, query.Transform(WorldTransformation), neighbour.QueryOverlapStart, neighbour.QueryOverlapEnd )); } } }
private Edge FindIntersectingEdge(Vector2 a, Vector2 b, out Vector2 intersectPosition) { var min = new Vector2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); var max = new Vector2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); //Select the all intersections (by checking all edges in octree result) var segment = new LineSegment2(a, b); var best = (from candidate in _edges.Intersects(new BoundingRectangle(min, max)) let intersectionMaybe = new LineSegment2(candidate.A.Position, candidate.B.Position).Intersects(segment) where intersectionMaybe.HasValue let intersection = intersectionMaybe.Value select new KeyValuePair <LinesIntersection2, Edge>(intersection, candidate)); intersectPosition = Vector2.Zero; Edge bestEdge = null; var bestScore = float.MaxValue; foreach (var keyValuePair in best) { if (keyValuePair.Key.DistanceAlongB < bestScore) { intersectPosition = keyValuePair.Key.Position; bestEdge = keyValuePair.Value; bestScore = keyValuePair.Key.DistanceAlongB; } } return(bestEdge); }
public static VisualLine Create(LineSegment2 line, Pen pen = null) { return(new VisualLine(line) { Pen = pen }); }
public void GetHashCode_SameForEqual() { var a = new LineSegment2(new Vector2(1, 2), new Vector2(3, 4)); var b = new LineSegment2(new Vector2(1, 2), new Vector2(3, 4)); Assert.AreEqual(a.GetHashCode(), b.GetHashCode()); }
public void NotEquals_TrueForNotEqual() { var a = new LineSegment2(new Vector2(1, 2), new Vector2(3, 4)); var b = new LineSegment2(new Vector2(6, 2), new Vector2(3, 4)); Assert.IsTrue(a != b); }
public void NotEquals_FalseForEqual() { var a = new LineSegment2(new Vector2(1, 2), new Vector2(3, 4)); var b = a; Assert.IsFalse(a != b); }
private KeyValuePair <HalfEdge, LinesIntersection2>?FindFirstIntersection(Seed seed, float length) { Contract.Requires(seed != null); Contract.Ensures(!Contract.Result <KeyValuePair <HalfEdge, LinesIntersection2>?>().HasValue || Contract.Result <KeyValuePair <HalfEdge, LinesIntersection2>?>().Value.Key != null); //Create the bounds of this new line (inflated slightly, just in case it's perfectly axis aligned) var a = seed.Origin.Position; var b = seed.Origin.Position + seed.Direction * length; var bounds = new BoundingRectangle(Vector2.Min(a, b), Vector2.Max(a, b)).Inflate(0.2f); var segment = new LineSegment2(a, b); //Find all edges which intersect this bounds, then test them one by one for intersection var results = _mesh .FindEdges(bounds) .Select(e => new KeyValuePair <HalfEdge, LinesIntersection2?>(e, e.Segment.Intersects(segment))) .Where(i => i.Value.HasValue) .Select(i => new KeyValuePair <HalfEdge, LinesIntersection2>(i.Key, i.Value.Value)); //Find the first intersection from all the results KeyValuePair <HalfEdge, LinesIntersection2>?result = null; foreach (var candidate in results) { if (result == null || candidate.Value.DistanceAlongB < result.Value.Value.DistanceAlongB) { result = candidate; } } return(result); }
public void Slope(string sp, string ep, double expected) { var spv = Vector2.Parse(sp); var epv = Vector2.Parse(ep); var l1 = new LineSegment2(spv, epv); Assert.AreEqual(expected, l1.Slope); }
public void IsVertical(string sp, string ep, bool expected) { var spv = Vector2.Parse(sp); var epv = Vector2.Parse(ep); var l1 = new LineSegment2(spv, epv); Assert.AreEqual(expected, l1.IsVertical); }
public static PostgisLineString ToPGis(LineSegment2 <double> geom) { if (geom != null) { return(new PostgisLineString(new Coordinate2D[] { new Coordinate2D(geom.Start.X, geom.Start.Y), new Coordinate2D(geom.End.X, geom.End.Y) })); } return(null); }
internal void AddSegment(LineSegment2 <T> segment) { if (segment == null) { return; } this.lineSegments.Add(segment, this.masterNodes); }
public void TesthasOverlap(string line1Str, string line2Str, bool expectedOverlap) { var line1 = LineSegment2.Parse(line1Str); var line2 = LineSegment2.Parse(line2Str); var hasOverlap = line1.HasOverlap(line2); Assert.AreEqual(expectedOverlap, hasOverlap); }
[TestCase("(6,56497115745559, -13,4350288425444), (20, -1,77635683940025E-15)", "(0, 0), (20, 0)", false)] // // A line touches another - no proper intersection public void TestProperIntersection(string line1Str, string line2Str, bool expectedProperIntersection) { var line1 = LineSegment2.Parse(line1Str); var line2 = LineSegment2.Parse(line2Str); var properIntersection = line1.IsIntersectionProper(line2); Assert.AreEqual(expectedProperIntersection, properIntersection); }
private KeyValuePair <HalfEdge, float>?FindFirstParallelEdge(Seed seed, float length, float distance, float parallelThreshold) { Contract.Requires(seed != null); var start = seed.Origin.Position; var end = seed.Origin.Position + seed.Direction * length; var segment = new LineSegment2(start, end); //Calculate the expanded bounds to query. This is as wide as the parallel check distance var p = seed.Direction.Perpendicular() * distance / 2; var a = start + p; var b = start - p; var c = end + p; var d = end - p; var queryBounds = new BoundingRectangle( Vector2.Min(Vector2.Min(a, b), Vector2.Min(c, d)), Vector2.Max(Vector2.Max(a, b), Vector2.Max(c, d)) ); //now get all lines which intersect this bounds and check them for parallelism var candidates = _mesh.FindEdges(queryBounds); KeyValuePair <HalfEdge, float>?firstParallel = null; foreach (var candidate in candidates) { var dirCandidate = candidate.Segment.Line.Direction; var dir = segment.Line.Direction; //Dot product directions of lines to check parallelism (compare with threshold) var dot = Math.Abs(Vector2.Dot(dir, dirCandidate)); if (dot > parallelThreshold) { //Our query bounds were larger than the actual area we wanted to query (because we're limited to axis aligned bounds) //Check that this line enters the smaller OABB area //We'll do this check by checking if the line segment intersects any of the four OABB segments (AB, BC, CD, DA) if (new LineSegment2(a, b).Intersects(candidate.Segment).HasValue || new LineSegment2(b, c).Intersects(candidate.Segment).HasValue || new LineSegment2(c, d).Intersects(candidate.Segment).HasValue || new LineSegment2(d, a).Intersects(candidate.Segment).HasValue) { //check how far along this segment the parallelism starts var startDist = segment.ClosestPointDistanceAlongSegment(candidate.StartVertex.Position); var endDist = segment.ClosestPointDistanceAlongSegment(candidate.EndVertex.Position); var minDist = Math.Min(startDist, endDist); if (firstParallel == null || minDist < firstParallel.Value.Value) { firstParallel = new KeyValuePair <HalfEdge, float>(candidate, minDist); } } } } return(firstParallel); }
public void Lenght(string sp, string ep, double expected) { var spv = Vector2.Parse(sp); var epv = Vector2.Parse(ep); var l1 = new LineSegment2(spv, epv); Assert.AreEqual(l1.Length, expected); }
[TestCase("(10, 20),(60, 70)", "(35,30),(45,40)")] // two parallel but nonaxial non overlapping lines public void TestNoOverlap(string line1Str, string line2Str) { var line1 = LineSegment2.Parse(line1Str); var line2 = LineSegment2.Parse(line2Str); var overlap = line1.HasOverlap(line2); Assert.AreEqual(false, overlap); }
public void TestLineCollisions(string line1Str, string line2Str, bool expectedCollision) { var line1 = LineSegment2.Parse(line1Str); var line2 = LineSegment2.Parse(line2Str); var collides = line1.HasCollision(line2); Assert.AreEqual(expectedCollision, collides); }
public LineSegment2 Reflect(LineSegment2 segment) { if (!this.valid) { return(segment); } return(new LineSegment2(Reflect(segment.A), Reflect(segment.B))); }
public void Equals_FalseForNotEqual() { var a = new LineSegment2(new Vector2(1, 2), new Vector2(3, 4)); var b = new LineSegment2(new Vector2(5, 6), new Vector2(7, 8)); Assert.IsFalse(a.Equals(b)); Assert.IsFalse(a.Equals((object)b)); Assert.IsFalse(a == b); }
public NeighbourResult(LineSegment2 segment, float segmentOverlapStart, float segmentOverlapEnd, T value, float queryOverlapStart, float queryOverlapEnd) { Segment = segment; SegmentOverlapStart = segmentOverlapStart; SegmentOverlapEnd = segmentOverlapEnd; Value = value; QueryOverlapStart = queryOverlapStart; QueryOverlapEnd = queryOverlapEnd; }
public Angle MaximalAngleWith(LineSegment2 line) { if (!this.valid) { return(Angle.ZERO); } return(this.direction.MaximalAngleWithAxis(line.VectorAB)); }
/// <summary> /// Get 2 rays from 3 points. The Rays interception Point is the Middlepoint of the Arc /// </summary> /// <param name="startPoint"></param> /// <param name="interPoint"></param> /// <param name="endPoint"></param> /// <returns></returns> private static Ray[] RaysFromDescriptorPoints(Vector2 startPoint, Vector2 interPoint, Vector2 endPoint, Direction direction) { Ray[] rays = new Ray[2]; Vector2 vRay1 = new Vector2(startPoint, interPoint).GetOrthogonalVector(direction); //Direction doesn't matter !? Vector2 vRay2 = new Vector2(interPoint, endPoint).GetOrthogonalVector(direction); //Direction doesn't matter !? var ray1StartPoint = new LineSegment2(startPoint, interPoint).MiddlePoint; var ray2StartPoint = new LineSegment2(interPoint, endPoint).MiddlePoint; rays[0] = new Ray(vRay1, ray1StartPoint); rays[1] = new Ray(vRay2, ray2StartPoint); return rays; }
/// <summary> /// Returns the angle formed between this <see cref="LineSegment2"/> and the supplied <paramref name="lineSegment"/>. /// </summary> /// <param name="lineSegment"></param> /// <returns></returns> public double AngleTo(LineSegment2 lineSegment) { return ToVector2().Angle - lineSegment.ToVector2().Angle; }