/// <summary> /// Конструктор /// </summary> public TRtree() { FNodeArr = new TRNode[1]; FNodeArr[0] = new TRNode(); FRoot = 0; FNodeArr[FRoot].FisLeaf = true; }
/// <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; }
/// <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); } }