Beispiel #1
0
            /// <summary>
            /// Adds objects, which bounding rectangles intersect
            /// specified rectangle, to the list.
            /// </summary>
            /// <param name="box">A bounding rectangle defining queryable area</param>
            /// <param name="objects">A list for adding objects</param>
            internal void QueryObjectsInRectangle <T>(BoundingRectangle box, IList <T> objects)
                where T : IIndexable
            {
                // возможно ячейка узла лежит внутри запрашиваемой области,
                // в этом случае мы должны добавить все объекты дочерних узлов
                // без выполнения проверок на пересечения
                if (box.ContainsRectangle(BoundingBox))
                {
                    addAllObjectsRecursively(objects);
                    return;
                }

                // предпринимаем действия по добавлению объектов в список только
                // в том случае, если ограничивающие прямоугольники пересеклись
                if (box.Intersects(BoundingBox))
                {
                    foreach (T obj in _objects)
                    {
                        if (box.Intersects(obj.BoundingRectangle))
                        {
                            objects.Add(obj);
                        }
                    }

                    if (_child0 != null && _child1 != null)
                    {
                        _child0.QueryObjectsInRectangle(box, objects);
                        _child1.QueryObjectsInRectangle(box, objects);
                    }
                }
            }
Beispiel #2
0
 public void AddPolygonObstaclesLayer(FeatureLayer layer)
 {
     foreach (var polygonFeature in layer.Polygons)
     {
         var bounds = polygonFeature.BoundingRectangle;
         if (BoundingRectangle.ContainsRectangle(bounds))
         {
             _obstacles.Add(polygonFeature.Polygon);
             RegisterObstacle(polygonFeature.Polygon);
         }
     }
 }
Beispiel #3
0
            internal void Insert(IIndexable obj, int branchDepth)
            {
                if (!_fullRectangle.ContainsRectangle(obj.BoundingRectangle))
                {
                    throw new ArgumentException("Bounding rectangle of the indexed object exceeds the node bounding rectangle", "obj");
                }

                // возможно глубина текущей ветки
                // уже больше глубины индекса
                if (branchDepth > _owner.Depth)
                {
                    _owner._depth++;
                }

                if (HasChildren)
                {
                    if (!canAddingToChildCell(obj.BoundingRectangle))
                    {
                        forceInsert(obj);
                    }
                    else
                    {
                        insertIntoChild(obj, branchDepth);
                    }
                }
                else
                {
                    if (_owner._minObjectCount < _objects.Count)
                    {
                        forceInsert(obj);
                    }
                    else
                    {
                        forceInsert(obj);

                        // ячейку можно разбивать, если ее площадь превосходит
                        // порог площади ячейки и текущая глубина ветви меньше предельной
                        if (_owner.BoxSquareThreshold < _fullRectangle.Width * _fullRectangle.Height &&
                            _owner.MaxDepth > branchDepth)
                        {
                            splitAndRebuild(branchDepth);
                        }
                    }
                }
            }
Beispiel #4
0
            /// <summary>
            /// Builds an index for the specified objects.
            /// </summary>
            internal void BuildUnbalanced <T>(List <T> objects, int currentDepth)
                where T : IIndexable
            {
                if (currentDepth > _parent.Depth)
                {
                    _parent._depth = currentDepth;
                }

                // Возможно мы достигли:
                // 1. максимально допустимой глубины индекса
                // 2. порогового значения площади ячейки узла
                // или кол-во объектов переданных для индексирования
                // не превысило минимального.
                // При этом создавать дочерние узлы уже нельзя
                if (_parent.Depth >= _parent.MaxDepth ||
                    _parent._boxSquareThreshold > _boundingBox.Width * _boundingBox.Height ||
                    _parent.MinObjectCount >= objects.Count)
                {
                    foreach (T obj in objects)
                    {
                        _objects.Add(obj);
                    }

                    objects.Clear();
                    return;
                }

                List <IIndexable> objects0 = new List <IIndexable>();
                List <IIndexable> objects1 = new List <IIndexable>();

                double minCost = double.MaxValue;

                BoundingRectangle box0, box1;
                BoundingRectangle minCostBox0 = _parent._indexedSpace,
                                  minCostBox1 = _parent._indexedSpace;

                #region Вычисление разбиения с минимальной стоимостью: стоимость = кол-во объекты * площадь

                for (int i = 1; i < KDTree.DividingGridRowCount; i++)
                {
                    double x = _boundingBox.MinX + _boundingBox.Width / KDTree.DividingGridRowCount * i;
                    splitX(_boundingBox, x, out box0, out box1);

                    double cost = getSplitCostVertical(objects, box0, box1);

                    if (cost < minCost)
                    {
                        minCost     = cost;
                        minCostBox0 = box0;
                        minCostBox1 = box1;
                    }

                    double y = _boundingBox.MinY + _boundingBox.Height / KDTree.DividingGridRowCount * i;

                    splitY(_boundingBox, y, out box0, out box1);

                    cost = getSplitCostHorizontal(objects, ref box0, ref box1);

                    if (cost < minCost)
                    {
                        minCost     = cost;
                        minCostBox0 = box0;
                        minCostBox1 = box1;
                    }
                }

                #endregion

                // разбиваем исходный список на 3 множества:
                // objects0 - объекты индексируемые в дочернем узле _child0
                // objects1 - объекты индексируемые в дочернем узле _child1
                // _objects - объекты этого узла
                foreach (T obj in objects)
                {
                    if (minCostBox0.ContainsRectangle(obj.BoundingRectangle))
                    {
                        objects0.Add(obj);
                    }
                    else
                    {
                        if (minCostBox1.ContainsRectangle(obj.BoundingRectangle))
                        {
                            objects1.Add(obj);
                        }
                        else
                        {
                            _objects.Add(obj);
                        }
                    }
                }

                objects.Clear();

                if (objects0.Count > 0 || objects1.Count > 0)
                {
                    _child0 = new KDTreeNode(minCostBox0, _parent);
                    _child1 = new KDTreeNode(minCostBox1, _parent);
                    _child0.BuildUnbalanced(objects0, currentDepth + 1);
                    _child1.BuildUnbalanced(objects1, currentDepth + 1);
                }
            }
Beispiel #5
0
            internal void QueryObjectsInRectangle <T>(BoundingRectangle box, IList <T> objects)
                where T : IIndexable
            {
                // если прямоугольник ячейки не пересекается
                // с запрашиваемым прямоугольником - считать нечего
                if (!box.Intersects(_fullRectangle))
                {
                    return;
                }

                // если прямоугольник ячейки целиком содержится в
                // запрашиваемом прямоугольнике - добавляем все объекты рекурсивно
                if (box.ContainsRectangle(this._fullRectangle))
                {
                    addAllObjectsRecursively(objects);
                    return;
                }

                // если прямоугольник объектов ячейки целиком содержится в
                // запрашиваемом прямоугольнике - добавляем все объекты этой ячейки
                if (_geometriesRectangle != null && box.ContainsRectangle(_geometriesRectangle))
                {
                    foreach (IIndexable obj in _objects)
                    {
                        objects.Add((T)obj);
                    }
                }
                else
                {
                    // иначе выполняем проверки на пересечение
                    // прямоугольников для каждого объекта
                    foreach (IIndexable obj in _objects)
                    {
                        if (box.Intersects(obj.BoundingRectangle))
                        {
                            objects.Add((T)obj);
                        }
                    }
                }

                // если дочерние узлы отсутствуют,
                // дальше считать нечего
                if (!HasChildren)
                {
                    return;
                }

                // разбираемся с детьми
                if (_leftUpChild != null)
                {
                    _leftUpChild.QueryObjectsInRectangle(box, objects);
                }

                if (_rightUpChild != null)
                {
                    _rightUpChild.QueryObjectsInRectangle(box, objects);
                }

                if (_rightDownChild != null)
                {
                    _rightDownChild.QueryObjectsInRectangle(box, objects);
                }

                if (_leftDownChild != null)
                {
                    _leftDownChild.QueryObjectsInRectangle(box, objects);
                }
            }