/// <summary>
 /// Конструктор
 /// </summary>
 public TRtree()
 {
     FNodeArr                = new TRNode[1];
     FNodeArr[0]             = new TRNode();
     FRoot                   = 0;
     FNodeArr[FRoot].FisLeaf = true;
 }
Esempio n. 2
0
        /// <summary>
        /// Копирование
        /// </summary>
        /// <param name="node"></param>
        public void copy(TRNode node)// метод копирования узла
        {
            FObject = new MyLib.Point[node.FObject.Length];
            if (FObject.Length > 0)
            {
                for (int i = 0; i < node.FObject.Length; i++)
                {
                    FObject[i]         = new MyLib.Point(node.FObject[i].x, node.FObject[i].y, node.FObject[i].idx);
                    FObject[i].cluster = node.FObject[i].cluster;
                }
                FisLeaf = true;
            }
            else
            {
                FChildren = new int[node.FChildren.Length];
                for (int i = 0; i < node.FChildren.Length; i++)
                {
                    FChildren[i] = node.FChildren[i];
                }
                FisLeaf = false;
            }


            fmbr = new TMBR(node.fmbr.Left, node.fmbr.Right);

            FParent = node.FParent;
            FLevel  = node.FLevel;
        }
Esempio n. 3
0
 /// <summary>
 /// Конструктор копирования
 /// </summary>
 /// <param name="node"></param>
 public TRNode(TRNode node)
 {
     FParent = -10;
     copy(node);
 }
        private TAxis chooseSplitAxis(int nodeFather, int nodeChild)
        {
            //Console.WriteLine("chooseSplitAxis work");
            int[]  arr_node;
            int    i, j, k, idx;
            TRNode node_1, node_2;
            double perimetr, perimetr_min;
            TAxis  result = new TAxis();

            arr_node = new int[MAX_M + 1];

            for (i = 0; i < FNodeArr[nodeFather].FChildren.Length; i++)
            {
                arr_node[i] = FNodeArr[nodeFather].FChildren[i];
            }

            arr_node[arr_node.Length - 1] = nodeChild;

            perimetr_min = double.MaxValue;

            node_1 = new TRNode();
            node_2 = new TRNode();

            for (i = 0; i <= 1; i++)
            {
                perimetr = 0;
                for (j = 0; j <= 1; j++)
                {
                    node_1.clearChildren();
                    node_2.clearChildren();

                    QuickSort(arr_node, 0, arr_node.Length - 1, (TAxis)i, (TBound)j);

                    for (k = 1; k <= MAX_M - MIN_M * 2 + 2; k++)
                    {
                        idx = 0;

                        while (idx < ((MIN_M - 1) + k))
                        {
                            node_1.setChild(idx, arr_node[idx]);
                            idx++;
                        }

                        for (; idx < arr_node.Length; idx++)
                        {
                            node_2.setChild(idx - ((MIN_M - 1) + k), arr_node[idx]);
                        }

                        updateMBR(node_1);
                        updateMBR(node_2);

                        perimetr = perimetr + node_1.margin() + node_2.margin();
                    }
                }

                if (perimetr <= perimetr_min)
                {
                    result       = (TAxis)i;
                    perimetr_min = perimetr;
                }

                perimetr = 0;
            }

            node_1   = null;
            node_2   = null;
            arr_node = new int[0];
            return(result);
        }
        /// <summary>
        /// TAXis
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="node_id"></param>
        /// <returns></returns>
        #region
        private TAxis chooseSplitAxis(MyLib.Point obj, int node_id)
        {
            //Console.WriteLine("chooseSplitAxis1 work");
            MyLib.Point[] arr_obj;
            int           i, j, k, idx;
            TRNode        node_1, node_2;
            double        perimetr_min, perimetr;
            TAxis         result = new TAxis();

            arr_obj = new MyLib.Point[MAX_M + 1];

            if (!FNodeArr[node_id].isLeaf)
            {
                return(0);
            }

            for (i = 0; i < FNodeArr[node_id].FObject.Length; i++)
            {
                arr_obj[i] = FNodeArr[node_id].FObject[i];
            }

            arr_obj[arr_obj.Length - 1] = obj;

            node_1 = new TRNode();
            node_2 = new TRNode();

            perimetr_min = double.MaxValue;

            for (i = 0; i <= 1; i++)
            {
                perimetr = 0;

                for (j = 0; j <= 1; j++)
                {
                    node_1.clearObjects();
                    node_2.clearObjects();

                    QuickSort(arr_obj, 0, arr_obj.Length - 1, (TAxis)i);

                    for (k = 1; k <= MAX_M - MIN_M * 2 + 2; k++) // высчитваем периметры
                    {
                        idx = 0;

                        while (idx < ((MIN_M - 1) + k))
                        {
                            node_1.setObject(idx, arr_obj[idx]);
                            idx++;
                        }

                        for (; idx < arr_obj.Length; idx++)
                        {
                            node_2.setObject(idx - ((MIN_M - 1) + k), arr_obj[idx]);
                        }

                        updateMBR(node_1);
                        updateMBR(node_2);

                        perimetr = perimetr + ((node_1.mbr.Right.X - node_1.mbr.Left.X) * 2 + (node_2.mbr.Left.Y - node_2.mbr.Right.Y) * 2);
                    }
                }

                if (perimetr <= perimetr_min)
                {
                    result       = (TAxis)i;
                    perimetr_min = perimetr;
                }
            }
            return(result);
        }
        /// <summary>
        /// обновляет MBR узла
        /// </summary>
        /// <param name="node"></param>
        #region
        public void updateMBR(TRNode node)
        {
            //Console.WriteLine("updateMBR1 work");
            int  i, idx;
            bool changed = false;

            node.fmbr.Left.X  = double.MaxValue;
            node.fmbr.Left.Y  = double.MinValue;
            node.fmbr.Right.X = double.MinValue;
            node.fmbr.Right.Y = double.MaxValue;

            if (node.getIsLeaf())
            {
                for (i = 0; i < node.FObject.Length; i++)
                {
                    if (node.FObject[i].x < node.fmbr.Left.X)
                    {
                        node.fmbr.Left.X = node.FObject[i].x;
                        changed          = true;
                    }
                    if (node.FObject[i].y > node.fmbr.Left.Y)
                    {
                        node.fmbr.Left.Y = node.FObject[i].y;
                        changed          = true;
                    }
                    if (node.FObject[i].x > node.fmbr.Right.X)
                    {
                        node.fmbr.Right.X = node.FObject[i].x;
                        changed           = true;
                    }
                    if (node.FObject[i].y < node.fmbr.Right.Y)
                    {
                        node.fmbr.Right.Y = node.FObject[i].y;
                        changed           = true;
                    }
                }
            }
            else
            {
                for (i = 0; i < node.FChildren.Length; i++)
                {
                    idx = node.FChildren[i];
                    if (FNodeArr[idx].fmbr.Left.X < node.fmbr.Left.X)
                    {
                        node.fmbr.Left.X = FNodeArr[idx].fmbr.Left.X;
                        changed          = true;
                    }
                    if (FNodeArr[idx].fmbr.Left.Y > node.fmbr.Left.Y)
                    {
                        node.fmbr.Left.Y = FNodeArr[idx].fmbr.Left.Y;
                        changed          = true;
                    }
                    if (FNodeArr[idx].fmbr.Right.X > node.fmbr.Right.X)
                    {
                        node.fmbr.Right.X = FNodeArr[idx].fmbr.Right.X;
                        changed           = true;
                    }
                    if (FNodeArr[idx].fmbr.Right.Y < node.fmbr.Right.Y)
                    {
                        node.fmbr.Right.Y = FNodeArr[idx].fmbr.Right.Y;
                        changed           = true;
                    }
                }
            }
            if (changed)
            {
                if (node.Parent >= 0)
                {
                    updateMBR(node.Parent);
                }
            }
        }
        /// <summary>
        /// разделяет узел на 2 в соответствии с алгоритмами R*-tree splited_Node_Id = ссылка на узел для разделения, inserted_Node_Id = узел для вставки
        /// </summary>
        /// <param name="splited_Node_Id"></param>
        /// <param name="inserted_Node_Id"></param>
        #region
        private void splitNodeRStar(int splited_Node_Id, int inserted_Node_Id)
        {
            //Console.WriteLine("splitNodeRSter2 work");
            TAxis  axe;
            int    parent_id, new_child_id;
            TRNode node_1, node_2, node_1_min, node_2_min;
            int    i, j, k;

            int[]  arr_node;
            double area_min, Area;

            if (FNodeArr[splited_Node_Id].isLeaf)
            {
                return;
            }

            if (isRoot(splited_Node_Id))
            {
                parent_id = newNode();
                FNodeArr[FRoot].Parent = parent_id;
                FNodeArr[parent_id].setChild(0, FRoot);
                FNodeArr[parent_id].Level = FNodeArr[FNodeArr[parent_id].getChild(0)].Level + 1;
                FRoot = parent_id;
                FNodeArr[parent_id].FisLeaf = false;
                FHeight = FHeight + 1;
            }
            else
            {
                parent_id = newNode();
                FNodeArr[parent_id].Parent = FNodeArr[splited_Node_Id].Parent;
                FNodeArr[FNodeArr[parent_id].Parent].setChild(FNodeArr[FNodeArr[parent_id].Parent].FChildren.Length, parent_id);
                FNodeArr[splited_Node_Id].Parent = parent_id;
                FNodeArr[parent_id].setChild(0, splited_Node_Id);
                //parent_id = FNodeArr[splited_Node_Id].Parent;
            }

            arr_node = new int[MAX_M + 1];
            for (i = 0; i < arr_node.Length - 1; i++)
            {
                arr_node[i] = FNodeArr[splited_Node_Id].getChild(i);
            }

            arr_node[arr_node.Length - 1] = inserted_Node_Id;

            node_1_min = new TRNode();
            node_2_min = new TRNode();

            node_1 = new TRNode();
            node_2 = new TRNode();

            axe = chooseSplitAxis(splited_Node_Id, inserted_Node_Id);

            area_min = double.MaxValue;

            for (i = 0; i <= 1; i++)
            {
                QuickSort(arr_node, 0, arr_node.Length - 1, axe, (TBound)i);

                for (k = MIN_M - 1; k <= MAX_M - MIN_M; k++)
                {
                    node_1.clearChildren();
                    node_2.clearChildren();

                    j = 0;

                    while (j <= k)
                    {
                        node_1.setChild(j, arr_node[j]);
                        j++;
                    }

                    for (j = k; j < arr_node.Length - 1; j++)
                    {
                        node_2.setChild(j - k, arr_node[j + 1]);
                    }

                    updateMBR(node_1);
                    updateMBR(node_2);

                    Area = node_1.Area() + node_2.Area();
                    if (Area < area_min)
                    {
                        node_1_min.copy(node_1);
                        node_2_min.copy(node_2);
                        area_min = Area;
                    }
                }
            }

            node_1_min.Level = FNodeArr[splited_Node_Id].Level;
            node_2_min.Level = FNodeArr[splited_Node_Id].Level;

            FNodeArr[splited_Node_Id].copy(node_1_min);
            FNodeArr[splited_Node_Id].Parent = parent_id;

            new_child_id = newNode();
            FNodeArr[new_child_id].copy(node_2_min);
            FNodeArr[new_child_id].Parent = parent_id;

            node_1     = null;
            node_2     = null;
            node_1_min = null;
            node_2_min = null;



            for (i = 0; i < FNodeArr[new_child_id].FChildren.Length; i++)
            {
                FNodeArr[FNodeArr[new_child_id].getChild(i)].Parent = new_child_id;
            }

            if (FNodeArr[parent_id].FChildren.Length < MAX_M)
            {
                FNodeArr[parent_id].setChild(FNodeArr[parent_id].FChildren.Length, new_child_id);
                FNodeArr[parent_id].FisLeaf = false;
                updateMBR(parent_id);
            }
            else
            {
                splitNodeRStar(parent_id, new_child_id);
            }
        }
        /// <summary>
        /// разделяет узел на 2 в соответствии с алгоритмами R*-tree (node_id = ссылка на узел для разделения obj = обьект для вставки)
        /// </summary>
        #region
        private void splitNodeRStar(int node_id, MyLib.Point obj)
        {
            //Console.WriteLine("splitNodeRStar work1 " + FHeight);
            TAxis  axe;
            int    parent_id, new_child_id;
            TRNode node_1, node_2, node_1_min, node_2_min;
            int    i, j, k;

            MyLib.Point[] arr_obj;
            double        area_min, Area;

            if (!FNodeArr[node_id].isLeaf)
            {
                return;
            }

            if (isRoot(node_id))
            {
                //Console.WriteLine("it works");
                parent_id = newNode();
                FNodeArr[FRoot].Parent = parent_id;
                FNodeArr[parent_id].setChild(0, FRoot);
                FNodeArr[parent_id].Level = FNodeArr[FNodeArr[parent_id].getChild(0)].Level + 1;
                FRoot = parent_id;
                FHeight++;
            }
            else
            {
                parent_id = newNode();
                FNodeArr[parent_id].Parent = FNodeArr[node_id].Parent;
                FNodeArr[FNodeArr[parent_id].Parent].setChild(FNodeArr[FNodeArr[parent_id].Parent].FChildren.Length, parent_id);
                FNodeArr[node_id].Parent = parent_id;
                FNodeArr[parent_id].setChild(0, node_id);

                /*
                 * parent_id = FNodeArr[node_id].Parent;
                 * Console.WriteLine("f**k); " + parent_id);
                 * FNodeArr[FNodeArr[node_id].Parent].FisLeaf = false;
                 */
            }


            arr_obj = new MyLib.Point[MAX_M + 1];

            for (i = 0; i < arr_obj.Length - 1; i++)
            {
                arr_obj[i] = FNodeArr[node_id].getObject(i);
            }

            arr_obj[arr_obj.Length - 1] = obj;

            node_1_min = new TRNode();
            node_2_min = new TRNode();
            node_1     = new TRNode();
            node_2     = new TRNode();

            axe = chooseSplitAxis(obj, node_id);

            area_min = double.MaxValue;


            for (i = 0; i <= 1; i++)
            {
                QuickSort(arr_obj, 0, arr_obj.Length - 1, axe);

                for (k = MIN_M - 1; k <= MAX_M - MIN_M; k++)
                {
                    node_1.clearObjects();
                    node_2.clearObjects();

                    j = 0;

                    while (j <= k)
                    {
                        node_1.setObject(j, arr_obj[j]);
                        j++;
                    }

                    for (j = k; j < arr_obj.Length - 1; j++)
                    {
                        node_2.setObject(j - k, arr_obj[j + 1]);
                    }


                    updateMBR(node_1);
                    updateMBR(node_2);

                    Area = node_1.Area() + node_2.Area();
                    if (Area < area_min)
                    {
                        node_1_min.copy(node_1);
                        node_2_min.copy(node_2);
                        area_min = Area;
                    }
                }
            }

            node_1_min.Level = 0;
            node_2_min.Level = 0;

            FNodeArr[node_id].copy(node_1_min);
            FNodeArr[node_id].Parent = parent_id;

            updateMBR(node_id);

            new_child_id = newNode();
            FNodeArr[new_child_id].copy(node_2_min);
            FNodeArr[new_child_id].Parent = parent_id;
            updateMBR(new_child_id);

            if (FNodeArr[parent_id].FChildren.Length < MAX_M)
            {
                FNodeArr[parent_id].setChild(FNodeArr[parent_id].FChildren.Length, new_child_id);
                updateMBR(parent_id);
                FNodeArr[parent_id].FisLeaf = false;
            }
            else
            {
                splitNodeRStar(parent_id, new_child_id);
            }
        }