Example #1
0
        /// <summary>
        /// Get the vertex at the given position or, if it does not exist, construct a new vertex
        /// </summary>
        /// <param name="vector2"></param>
        /// <returns></returns>
        public Vertex <TVTag, TETag, TFTag> GetOrConstructVertex(Vector2 vector2)
        {
            Contract.Ensures(Contract.Result <Vertex <TVTag, TETag, TFTag> >() != null);
            Contract.Ensures(!Contract.Result <Vertex <TVTag, TETag, TFTag> >().IsDeleted);

            //Select candidate vertices within range (square query)
            var candidates = _vertices.Intersects(new BoundingRectangle(vector2 - new Vector2(VERTEX_EPSILON / 2), vector2 + new Vector2(VERTEX_EPSILON / 2)));

            //Select best candidate (nearest)
            float bestDistance = float.MaxValue;
            Vertex <TVTag, TETag, TFTag> best = null;

            foreach (var candidate in candidates)
            {
                var d = Vector2.DistanceSquared(candidate.Position, vector2);
                if (d < bestDistance && d < VERTEX_EPSILON * VERTEX_EPSILON)
                {
                    bestDistance = d;
                    best         = candidate;
                }
            }

            //If we found a suitable one, return it
            if (best != null)
            {
                return(best);
            }

            //Otherwise create a new vertex and return that
            var v = new Vertex <TVTag, TETag, TFTag>(this, vector2);

            _vertices.Insert(new BoundingRectangle(v.Position, v.Position).Inflate(0.1f), v);
            return(v);
        }
Example #2
0
        public void AssertThat_Intersects_FindsItemInBounds()
        {
            _tree.Insert(new BoundingRectangle(new Vector2(10, 10), new Vector2(20, 20)), "A");
            _tree.Insert(new BoundingRectangle(new Vector2(90, 90), new Vector2(80, 80)), "B");

            var results = _tree.Intersects(new BoundingRectangle(new Vector2(0, 0), new Vector2(20, 20))).ToArray();

            Assert.AreEqual(1, results.Length);
            Assert.AreEqual("A", results.Single());
        }
Example #3
0
        /// <summary>
        /// Find edges close to given position
        /// </summary>
        /// <param name="position"></param>
        /// <param name="radius"></param>
        /// <returns></returns>
        private IEnumerable <Edge> FindEdges(Vector2 position, float radius)
        {
            Contract.Requires(_vertices != null);
            Contract.Ensures(Contract.Result <IEnumerable <Edge> >() != null);

            return(_vertices.Intersects(
                       new BoundingRectangle(
                           new Vector2(position.X - radius, position.Y - radius),
                           new Vector2(position.X + radius, position.Y + radius)
                           )
                       ).SelectMany(v => v.Edges).Distinct());
        }
Example #4
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);
        }
Example #5
0
        /// <summary>
        /// Find edges which itnersect the given bounds
        /// </summary>
        /// <param name="rectangle"></param>
        /// <returns></returns>
        public IEnumerable <HalfEdge <TVTag, TETag, TFTag> > FindEdges(BoundingRectangle rectangle)
        {
            Contract.Ensures(Contract.Result <IEnumerable <HalfEdge <TVTag, TETag, TFTag> > >() != null);
            Contract.Ensures(Contract.ForAll(Contract.Result <IEnumerable <HalfEdge <TVTag, TETag, TFTag> > >(), a => !a.IsDeleted));

            return(_halfEdges.Intersects(rectangle));
        }
Example #6
0
        // Update is called once per frame
        void Update()
        {
            Junction j      = new Junction(1, 0, 1);
            var      foundJ = junctions.Intersects(j.Bound);

            Debug.Log(j.Bound);
            Debug.Log(j.Bound.Contains(new Vector2(1, 1)));

            foreach (var jo in foundJ)
            {
                jo.add(new Road(Vector3.back, Vector3.forward, 1f));
                Debug.Log(jo.RoadsCount);
            }
        }
        private TSelf ConstructFromSlicePart(IReadOnlyList <Vector2> polygon, Quadtree <Side> inputSidesQuad, Ray2?sliceLine, List <KeyValuePair <TSelf, Side> > outInternalSides)
        {
            Contract.Requires(polygon != null);
            Contract.Requires(inputSidesQuad != null);
            Contract.Requires(outInternalSides != null);
            Contract.Ensures(Contract.Result <TSelf>() != null);

            var outputSides   = new List <Side>();
            var internalSides = new List <Side>();

            for (var i = 0; i < polygon.Count; i++)
            {
                var a  = polygon[i];
                var b  = polygon[(i + 1) % polygon.Count];
                var ab = new LineSegment2(a, b).LongLine;

                //Find all sides from the input which overlap this line. Slightly expand the box to handle a perfectly flat line (which would create an empty box and select nothing)
                var candidates = inputSidesQuad
                                 .Intersects(new BoundingRectangle(Vector2.Min(a, b) - new Vector2(0.01f), Vector2.Max(a, b) + new Vector2(0.01f)))
                                 //.Where(c => c.Start == a || c.End == b)
                ;
                //There are three types of edge in the sliced shapes:
                // - unchanged edges. start and end in the same place as an existing side
                // - sliced edges. start or end at the same place as an existing edge and co-linear with it
                // - dividing edge. co-linear with slice line

                var unchanged = candidates.SingleOrDefault(c => c.Start.Equals(a) && c.End.Equals(b));
                if (unchanged != null)
                {
                    //Side completely unchanged, simply copy across the data
                    outputSides.Add(new Side(a, b, unchanged.Sections));
                    continue;
                }

                var slicedStart = candidates.SingleOrDefault(c => c.Start.Equals(a) && new LineSegment2(c.Start, c.End).LongLine.Parallelism(ab) == Parallelism.Collinear && new LineSegment2(c.Start, c.End).DistanceToPoint(b) <= 0.01f);
                if (slicedStart != null)
                {
                    //Side overlapping at start, select the correct sections from OverlapPoint -> 0 (Start)
                    outputSides.Add(new Side(a, b, SelectSections(slicedStart, a, b)));
                    continue;
                }

                var slicedEnd = candidates.SingleOrDefault(c => c.End.Equals(b) && new LineSegment2(c.Start, c.End).LongLine.Parallelism(ab) == Parallelism.Collinear && new LineSegment2(c.Start, c.End).DistanceToPoint(a) <= 0.01f);
                if (slicedEnd != null)
                {
                    //Side overlapping at end, select the correct sections from OverlapPoint -> 1 (End)
                    outputSides.Add(new Side(a, b, SelectSections(slicedEnd, a, b)));
                    continue;
                }

                if (!sliceLine.HasValue)
                {
                    outputSides.Add(new Side(a, b, new TSection[0]));
                }
                else
                {
                    if (sliceLine.Value.Parallelism(ab) == Parallelism.Collinear)
                    {
                        //this is the slice line, need to add a neighbour section
                        //But which section is the neighbour? we can't know yet because not all sections exist yet!
                        //Create a side with a null section, we'll fix this up later
                        var s = new Side(a, b, null);
                        internalSides.Add(s);
                        outputSides.Add(s);
                        continue;
                    }

                    throw new InvalidOperationException("Failed to match up sides when slicing polygon region");
                }
            }

            var region = Construct(outputSides);

            outInternalSides.AddRange(internalSides.Select(a => new KeyValuePair <TSelf, Side>(region, a)));
            return(region);
        }