Пример #1
0
 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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        public void TestEquality(string lineAStr, string lineBStr)
        {
            var lineA = LineSegment2.Parse(lineAStr);
            var lineB = LineSegment2.Parse(lineBStr);

            Assert.AreEqual(lineA, lineB);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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;
        }
Пример #10
0
        [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));
        }
Пример #11
0
        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
                                     ));
                }
            }
        }
Пример #12
0
        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);
        }
Пример #13
0
 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);
        }
Пример #17
0
        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);
        }
Пример #18
0
        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);
        }
Пример #19
0
        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);
        }
Пример #20
0
 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);
 }
Пример #21
0
 internal void AddSegment(LineSegment2 <T> segment)
 {
     if (segment == null)
     {
         return;
     }
     this.lineSegments.Add(segment, this.masterNodes);
 }
Пример #22
0
        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);
        }
Пример #23
0
        [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);
        }
Пример #24
0
        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);
        }
Пример #25
0
        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);
        }
Пример #26
0
        [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);
        }
Пример #27
0
        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);
        }
Пример #28
0
        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);
        }
Пример #30
0
 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;
 }
Пример #31
0
        public Angle MaximalAngleWith(LineSegment2 line)
        {
            if (!this.valid)
            {
                return(Angle.ZERO);
            }

            return(this.direction.MaximalAngleWithAxis(line.VectorAB));
        }
Пример #32
0
        /// <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;
 }