Ejemplo n.º 1
0
        private void AppendNewHead <T>(Dimension <T> dimension, SpacePoint <T> sp, float position)
        {
            var newHead = new DimensionPoint <T>(dimension)
            {
                Position = position
            };

            newHead.AddPoint(sp);
            newHead.HeadLink = new DimensionLink <T>(0, newHead);

            var oldHead = dimension.HeadDimPoint;

            dimension.HeadDimPoint = newHead;
            newHead.HeadLink.AssignNext(oldHead.HeadLink);

            var upper = oldHead.HeadLink.Upper;

            newHead.HeadLink.AssignUpper(upper);
            oldHead.HeadLink.Upper = null;
            newHead.TailLink       = oldHead.TailLink.Level == 0 ? newHead.HeadLink : oldHead.TailLink;
            oldHead.TailLink       = oldHead.HeadLink;

            _spaceManager.TryAddLevel(dimension);
            var toExtendUp = dimension.HeadDimPoint.HeadLink.NextUntil((n, i) => i == 1);

            while (_spaceManager.TryExtendUp(toExtendUp, out toExtendUp))
            {
                _spaceManager.TryAddLevel(dimension);
            }
        }
Ejemplo n.º 2
0
        private static bool RemoveDimensionPoint <T>(DimensionPoint <T> dPoint)
        {
            var dimension = dPoint.Dimension;

            if (dimension == null || dimension.HeadDimPoint == null)
            {
                throw new InvalidOperationException("Invalid tree: point was requested to be removed but the tree is already empty");
            }
            if (dimension.Count == 1)
            {
                if (dimension.HeadDimPoint == dPoint)
                {
                    dimension.Count        = 0;
                    dimension.HeadDimPoint = dimension.TailDimPoint = null;
                    return(true);
                }
                throw new InvalidOperationException("Invalid tree: point requested to be removed does not seem to belong to the tree");
            }
            if (dimension.HeadDimPoint == dPoint)
            {
                RemoveHead(dPoint.Dimension);
            }
            else if (dimension.TailDimPoint == dPoint)
            {
                RemoveTail(dPoint.Dimension);
            }
            else
            {
                RemoveMiddlePoint(dPoint);
            }
            dimension.Count--;
            return(true);
        }
Ejemplo n.º 3
0
        private static void RemoveMiddlePoint <T>(DimensionPoint <T> dPoint)
        {
            var link = dPoint.HeadLink;

            RemoveOrMoveColumn(dPoint);

            var prev = link.Prev;
            var next = link.Next;

            prev.AssignNext(next);
            TryRemoveLevelInternal(dPoint.Dimension);
        }
Ejemplo n.º 4
0
        private static IEnumerable <SpacePoint <T> > EnumerateSpacePoints <T>(
            DimensionPoint <T> curr, HashSet <SpacePoint <T> > spacePoints,
            HashSet <DimensionPoint <T> > tempDimPoints, float within,
            IDimensionSelector dimSelector, params float[] dimensionPositions)
        {
            if (curr == null)
            {
                yield break;
            }
            tempDimPoints.Add(curr);

            foreach (var sp in curr.SpaPoints)
            {
                if (!spacePoints.Contains(sp))
                {
                    var dist = sp.DistanceTo(dimensionPositions, dimSelector);
                    if (dist <= within)
                    {
                        spacePoints.Add(sp);
                        yield return(sp);
                    }
                }
            }
        }
Ejemplo n.º 5
0
        bool ISpaceManager.TryFindDimensionPoint <T>(Dimension <T> dimension, float position, out DimensionPoint <T> left, out DimensionPoint <T> right)
        {
            if (dimension.HeadDimPoint == null)
            {
                left  = null;
                right = null;
                return(false);
            }

            var candidateLeft  = dimension.HeadDimPoint.TailLink;
            var candidateRight = dimension.TailDimPoint.TailLink;
            var leftLimit      = candidateLeft.DimPoint.Position;
            var rightLimit     = candidateRight.DimPoint.Position;

            if (position > (leftLimit - dimension.Epsillon) && position < (rightLimit + dimension.Epsillon))
            {
                while (true)
                {
                    while (candidateLeft.Next != null && candidateLeft.Next != candidateRight)
                    {
                        if ((candidateLeft.Next.DimPoint.Position - dimension.Epsillon) < position)
                        {
                            candidateLeft = candidateLeft.Next;
                        }
                        else
                        {
                            candidateRight = candidateLeft.Next;
                            break;
                        }
                    }

                    if (candidateLeft.Level > 0)
                    {
                        candidateLeft  = candidateLeft.Lower;
                        candidateRight = candidateRight.Lower;
                        continue;
                    }


                    if (dimension.Eq(position, candidateLeft.DimPoint.Position))
                    {
                        left = right = candidateLeft.DimPoint;
                        return(true);
                    }
                    if (dimension.Eq(position, candidateRight.DimPoint.Position))
                    {
                        left = right = candidateRight.DimPoint;
                        return(true);
                    }
                    break;
                }
                left  = candidateLeft.DimPoint;
                right = candidateRight.DimPoint;
                return(false);
            }
            else if (position < leftLimit)
            {
                left  = null;
                right = candidateLeft.DimPoint;
                return(false);
            }
            else if (position > rightLimit)
            {
                left  = candidateRight.DimPoint;
                right = null;
                return(false);
            }


            left  = null;
            right = null;
            return(false);
        }
Ejemplo n.º 6
0
        bool ISpaceManager.AddPoint <T>(Dimension <T> dimension, SpacePoint <T> sp, float position)
        {
            if (dimension == null || sp == null)
            {
                return(false);
            }

            MustBe.Null(sp.Dimensions[dimension.Index], () => "space point already has assigned the dimension with index=" + dimension.Index);

            if (dimension.HeadDimPoint == null)
            {
                var dp = new DimensionPoint <T>(dimension)
                {
                    Position = position
                };
                dp.HeadLink = dp.TailLink = new DimensionLink <T>(0, dp);
                dp.AddPoint(sp);
                dimension.HeadDimPoint = dimension.TailDimPoint = dp;
                dimension.Count        = 1;
                return(true);
            }

            // try to find existing dimension point
            DimensionPoint <T> left;
            DimensionPoint <T> right;

            if (_spaceManager.TryFindDimensionPoint(dimension, position, out left, out right))
            {
                // if found add the space point to it
                return(left.AddPoint(sp));
            }
            // new head
            if (left == null)
            {
                AppendNewHead(dimension, sp, position);
                dimension.Count++;
                return(true);
            }
            // new tail
            if (right == null)
            {
                AppendNewTail(dimension, sp, position);
                dimension.Count++;
                return(true);
            }

            // new in between
            var newPoint = new DimensionPoint <T>(dimension)
            {
                Position = position
            };

            newPoint.AddPoint(sp);
            var newLink = new DimensionLink <T>(0, newPoint);

            newPoint.HeadLink = newLink;
            newPoint.TailLink = newLink;

            left.HeadLink.AssignNext(newLink);
            newLink.AssignNext(right.HeadLink);

            // for fast movers do not normalize the tree
            if (!sp.IsFastMover)
            {
                _spaceManager.TryAddLevel(dimension);
                var toExtendUp = newLink.GetSiblingExtensionCandidate();
                while (_spaceManager.TryExtendUp(toExtendUp, out toExtendUp))
                {
                    _spaceManager.TryAddLevel(dimension);
                }
            }
            dimension.Count++;
            return(true);
        }
Ejemplo n.º 7
0
        private static bool RemoveOrMoveColumn <T>(DimensionPoint <T> dPoint)
        {
            if (dPoint == null || dPoint.HeadLink == null)
            {
                return(false);
            }
            var dimension = dPoint.Dimension;

            if (dimension.HeadDimPoint == dPoint || dimension.TailDimPoint == dPoint)
            {
                return(false);
            }
            var head = dPoint.HeadLink;
            var tail = dPoint.TailLink;


            // try move right to direct neighbour that has only 1 level
            if (HasBottomLevelNeighbourToTheRight(head))
            {
                var destination = head.Next;

                destination.AssignUpper(head.Upper);
                destination.DimPoint.TailLink = tail;

                head.AssignUpper(null);
                head.DimPoint.TailLink = head.DimPoint.HeadLink;
            }
            // try move left to direct neighbour that has only 1 level
            else if (HasBottomLevelNeighbourToTheLeft(head))
            {
                var destination = head.Prev;

                destination.AssignUpper(head.Upper);
                destination.DimPoint.TailLink = tail;

                head.AssignUpper(null);
                head.DimPoint.TailLink = head.DimPoint.HeadLink;
            }
            // try move the tip right to current level neighbour
            else if (HasTopLevelNeighbourToTheRight(tail))
            {
                var toDelete = tail.Lower.DimPoint;
                var target   = tail.Next.Lower.Prev.Prev;
                tail.Lower.AssignUpper(null);
                target.AssignUpper(tail);
                target.DimPoint.TailLink = tail;

                DeleteColumn(toDelete.HeadLink);
            }
            // try move the tip left to current level neighbour
            else if (HasTopLevelNeighbourToTheLeft(tail))
            {
                var toDelete = tail.Lower.DimPoint;
                var target   = tail.Prev.Lower.Next.Next;
                tail.Lower.AssignUpper(null);
                target.AssignUpper(tail);
                target.DimPoint.TailLink = tail;

                DeleteColumn(toDelete.HeadLink);
            }
            // delete the column
            else
            {
                DeleteColumn(head);
            }

            return(true);
        }
Ejemplo n.º 8
0
        private bool PopulateDimension <T>(Dimension <T> dimension, List <SpacePointSource <T> > points)
        {
            if (points.Count == 0)
            {
                return(false);
            }

            points.Sort(new SpacePointComparer <T>(dimension.Index));
            //points.Sort((a, b) => a.InitialPositions[dimension.Index].CompareTo(b.InitialPositions[dimension.Index]));

            DimensionPoint <T> head = null;
            DimensionPoint <T> curr = null;
            DimensionPoint <T> prev = null;

            for (var i = 0; i < points.Count; ++i)
            {
                var sp = points[i];
                if (sp == null)
                {
                    continue;
                }
                var position = sp.InitialPositions[dimension.Index];
                if (prev != null)
                {
                    if (dimension.Eq(prev.Position, position))
                    {
                        prev.AddPoint(sp);
                        continue;
                    }
                }
                curr = new DimensionPoint <T>(dimension)
                {
                    Position = position
                };
                curr.HeadLink = new DimensionLink <T>(0, curr);
                curr.TailLink = curr.HeadLink;
                curr.AddPoint(sp);

                if (prev != null)
                {
                    prev.HeadLink.AssignNext(curr.HeadLink);
                }
                else
                {
                    head = curr;
                }
                prev = curr;
            }

            dimension.HeadDimPoint = head;
            dimension.TailDimPoint = curr;
            dimension.Count       += points.Count;

            // ReSharper disable PossibleNullReferenceException
            DimensionLink <T> link = dimension.HeadDimPoint.HeadLink;

            // ReSharper restore PossibleNullReferenceException

            // if this is the top level
            if (link.Next == null || link.Next.Next == null)
            {
                return(true);
            }

            DimensionLink <T> prevUpper  = null;
            DimensionLink <T> firstUpper = null;

            while (link != null)
            {
                var upper = new DimensionLink <T>((byte)(link.Level + 1));
                if (firstUpper == null)
                {
                    firstUpper = upper;
                }
                link.AssignUpper(upper);
                link.DimPoint.TailLink = upper;
                if (prevUpper != null)
                {
                    prevUpper.AssignNext(upper);
                }
                // if this is the end
                if (link.Next == null)
                {
                    link       = firstUpper;
                    firstUpper = null;
                    prevUpper  = null;
                    // if this is the top level
                    if (link.Next == null || link.Next.Next == null)
                    {
                        return(true);
                    }
                    continue;
                }
                link = link.Next.Next;
                // the next is the end and it is two links away
                if (link.Next != null && link.Next.Next == null)
                {
                    link = link.Next;
                }
                prevUpper = upper;
            }
            return(true);
        }