f = rd.getFileList(mulu);
+
+
+ double[] q = {6000, 5100};
+// double[] q = {10208, 76204};
+ com.secure.rtree.Point query = new com.secure.rtree.Point(q);
+
+ for(String fn:f){
+ for (int ca = 3; ca<4;ca=ca+2){
+ testBBS.excute(mulu+"\\"+fn,ca,query);
+ }
+ }
+ }
+
+
+}
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/oneVoronoi/PointIntersect.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/oneVoronoi/PointIntersect.java
new file mode 100644
index 00000000..2022c74b
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/oneVoronoi/PointIntersect.java
@@ -0,0 +1,81 @@
+package com.secure.oneVoronoi;
+
+public class PointIntersect {
+
+ public static class Point{
+ private double x;
+ private double y;
+
+ public Point(double x,double y){
+ this.x=x;
+ this.y=y;
+ }
+
+ public double getX() {
+ return x;
+ }
+
+ public void setX(double x) {
+ this.x = x;
+ }
+
+ public double getY() {
+ return y;
+ }
+
+ public void setY(double y) {
+ this.y = y;
+ }
+
+ @Override
+ public String toString() {
+ return "X="+this.x+"Y="+this.y;
+ }
+ }
+
+ /**
+ * 获取两条直线相交的点
+ */
+ public static Point getIntersectPoint(Point p1, Point p2, Point p3, Point p4){
+
+ double A1=p1.getY()-p2.getY();
+ double B1=p2.getX()-p1.getX();
+ double C1=A1*p1.getX()+B1*p1.getY();
+
+ double A2=p3.getY()-p4.getY();
+ double B2=p4.getX()-p3.getX();
+ double C2=A2*p3.getX()+B2*p3.getY();
+
+ double det_k=A1*B2-A2*B1;
+
+ if(Math.abs(det_k)<0.00001){
+ return null;
+ }
+
+ double a=B2/det_k;
+ double b=-1*B1/det_k;
+ double c=-1*A2/det_k;
+ double d=A1/det_k;
+
+ double x=a*C1+b*C2;
+ double y=c*C1+d*C2;
+
+ return new Point(x,y);
+ }
+
+ public static void main(String[] args) {
+ Point p1=new Point(1,1);
+ Point p2=new Point(5,5);
+ Point p3=new Point(2,1);
+ Point p4=new Point(2,5);
+
+ Point point=getIntersectPoint(p1,p2,p3,p4);
+
+ if(point==null){
+ System.out.print("未相交");
+ }else{
+ System.out.print("相交于:"+point.toString());
+ }
+ }
+}
+
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Constants.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Constants.java
new file mode 100644
index 00000000..8afb4686
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Constants.java
@@ -0,0 +1,28 @@
+package com.secure.rtree;
+
+import com.secure.ssvrtree.SSVRTNode;
+import com.secure.svrtree.SVRTNode;
+import com.secure.vsptree.VSPRTNode;
+import com.secure.vtree.VRTNode;
+
+public class Constants
+{
+ public static final int MAX_NUMBER_OF_ENTRIES_IN_NODE = 20;//结点中的最大条目数
+ public static final int MIN_NUMBER_OF_ENTRIES_IN_NODE = 8;//结点中的最小条目数
+
+ public static final int RTDataNode_Dimension = 2;
+
+ /** Available RTree variants. */
+ public static final int RTREE_LINEAR = 0;
+ public static final int RTREE_QUADRATIC = 1;
+ public static final int RTREE_EXPONENTIAL = 2;
+ public static final int RSTAR = 3;
+
+ public static final int NIL = -1;
+ public static final RTNode NULL = null;
+
+ public static final SVRTNode SNULL = null;
+ public static final VRTNode VNULL = null;
+ public static final VSPRTNode VSPNULL = null;
+ public static final SSVRTNode SPNULL = null;
+}
\ No newline at end of file
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Point.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Point.java
new file mode 100644
index 00000000..b015625f
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Point.java
@@ -0,0 +1,179 @@
+package com.secure.rtree;
+
+import java.io.Serializable;
+
+/**
+ * @ClassName Point
+ * @Description n维空间中的点,所有的维度被存储在一个float数组中
+ */
+public class Point implements Cloneable, Serializable
+{
+ private double[] data;
+ private double[] location;
+
+ //距离
+ private double dist=-1;
+
+ public double getDist() {
+ return dist;
+ }
+
+ public void setDist(double dist) {
+ this.dist = dist;
+ }
+
+ public Point(double[] data)
+ {
+ if(data == null)
+ {
+ throw new IllegalArgumentException("Coordinates cannot be null.");
+ }
+ if(data.length < 2)
+ {
+ throw new IllegalArgumentException("Point dimension should be greater than 1.");
+ }
+
+ this.data = new double[data.length];
+ System.arraycopy(data, 0, this.data, 0, data.length);
+ }
+
+ public Point(double[] data, double[] location) {
+ this.data = data;
+ this.location = location;
+ }
+
+ public Point(int[] data)
+ {
+ if(data == null)
+ {
+ throw new IllegalArgumentException("Coordinates cannot be null.");
+ }
+ if(data.length < 2)
+ {
+ throw new IllegalArgumentException("Point dimension should be greater than 1.");
+ }
+
+ this.data = new double[data.length];
+ for(int i = 0 ; i < data.length ; i ++)
+ {
+ this.data[i] = data[i];
+ }
+ }
+
+ @Override
+ protected Object clone()
+ {
+ double[] copy_data = new double[data.length];
+ if (location!=null){
+ double[] copy_location = new double[2];
+ System.arraycopy(location, 0, copy_location, 0, 2);
+ System.arraycopy(data, 0, copy_data, 0, data.length);
+ return new Point(copy_data,copy_location);
+ }else{
+ System.arraycopy(data, 0, copy_data, 0, data.length);
+ return new Point(copy_data);
+ }
+
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuffer sBuffer = new StringBuffer("(");
+
+ if (location!=null){
+ sBuffer.append(location[0]).append(",");
+ sBuffer.append(location[1]).append(",");
+ }
+
+ for(int i = 0 ; i < data.length - 1 ; i ++)
+ {
+ sBuffer.append(data[i]).append(",");
+ }
+
+ sBuffer.append(data[data.length - 1]).append(")");
+
+ return sBuffer.toString();
+ }
+
+ public void setData(double[] data) {
+ this.data = data;
+ }
+
+ public double[] getLocation() {
+ return location;
+ }
+
+ public void setLocation(double[] location) {
+ this.location = location;
+ }
+ public void setLocation(double x,double y) {
+ this.location = new double[2];
+ this.location[0] = x;
+ this.location[1] = y;
+ }
+
+ public static void main(String[] args)
+ {
+ double[] test = {1.2f,2f,34f};
+ Point point1 = new Point(test);
+ System.out.println(point1);
+
+ int[] test2 = {1,2,3,4};
+ point1 = new Point(test2);
+ System.out.println(point1);
+ }
+
+ /**
+ * @return 返回Point的维度
+ */
+ public int getDimension()
+ {
+ return data.length;
+ }
+
+ public double[] getData() {
+ return data;
+ }
+
+ /**
+ * @param index
+ * @return 返回Point坐标第i位的double值
+ */
+ public double getFloatCoordinate(int index)
+ {
+ return data[index];
+ }
+
+ /**
+ * @param index
+ * @return 返回Point坐标第i位的int值
+ */
+ public int getIntCoordinate(int index)
+ {
+ return (int) data[index];
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if(obj instanceof Point)
+ {
+ Point point = (Point) obj;
+
+ if(point.getDimension() != getDimension())
+ throw new IllegalArgumentException("Points must be of equal dimensions to be compared.");
+
+ for(int i = 0; i < getDimension(); i ++)
+ {
+ if(getFloatCoordinate(i) != point.getFloatCoordinate(i))
+ return false;
+ }
+ }
+
+ if(! (obj instanceof Point))
+ return false;
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTDataNode.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTDataNode.java
new file mode 100644
index 00000000..390aa952
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTDataNode.java
@@ -0,0 +1,180 @@
+package com.secure.rtree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName RTDataNode
+ * @Description
+ */
+public class RTDataNode extends RTNode
+{
+
+ public RTDataNode(RTree rTree, RTNode parent)
+ {
+ super(rTree, parent, 0);
+ }
+
+ /**
+ * 在叶节点中插入Rectangle,插入后如果其父节点不为空则需要向上调整树直到根节点;
+ * 若插入Rectangle之后超过结点容量则需要分裂结点
+ * @param rectangle
+ * @return
+ */
+ public boolean insert(Rectangle rectangle)
+ {
+ if(usedSpace < rtree.getNodeCapacity())
+ {
+ datas[usedSpace ++] = rectangle;
+ RTDirNode parent = (RTDirNode) getParent();
+
+ if(parent != null)
+ parent.adjustTree(this, null);
+ return true;
+
+ }else{//超过结点容量
+ RTDataNode[] splitNodes = splitLeaf(rectangle);
+ RTDataNode l = splitNodes[0];
+ RTDataNode ll = splitNodes[1];
+
+ if(isRoot())
+ {
+ //根节点已满,需要分裂。创建新的根节点
+ RTDirNode rDirNode = new RTDirNode(rtree, Constants.NULL, level + 1);
+ rtree.setRoot(rDirNode);
+ rDirNode.addData(l.getNodeRectangle());
+ rDirNode.addData(ll.getNodeRectangle());
+
+ ll.parent = rDirNode;
+ l.parent = rDirNode;
+
+ rDirNode.children.add(l);
+ rDirNode.children.add(ll);
+
+ }else{//不是根节点
+ RTDirNode parentNode = (RTDirNode) getParent();
+ parentNode.adjustTree(l, ll);
+ }
+
+
+ }
+ return true;
+ }
+
+ /**
+ * 插入Rectangle之后超过容量需要分裂
+ * @param rectangle
+ * @return
+ */
+ public RTDataNode[] splitLeaf(Rectangle rectangle)
+ {
+ int[][] group = null;
+
+ switch(rtree.getTreeType())
+ {
+ case Constants.RTREE_LINEAR:
+ break;
+ case Constants.RTREE_QUADRATIC:
+ group = quadraticSplit(rectangle);
+ break;
+ case Constants.RTREE_EXPONENTIAL:
+ break;
+ case Constants.RSTAR:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid tree type.");
+ }
+
+ RTDataNode l = new RTDataNode(rtree, parent);
+ RTDataNode ll = new RTDataNode(rtree, parent);
+
+ int[] group1 = group[0];
+ int[] group2 = group[1];
+
+ for(int i = 0; i < group1.length; i ++)
+ {
+ l.addData(datas[group1[i]]);
+ }
+
+ for(int i = 0; i < group2.length; i ++)
+ {
+ ll.addData(datas[group2[i]]);
+ }
+ return new RTDataNode[]{l, ll};
+ }
+
+
+ @Override
+ public RTDataNode chooseLeaf(Rectangle rectangle)
+ {
+ insertIndex = usedSpace;//记录插入路径的索引
+ return this;
+ }
+
+ /**
+ * 从叶节点中删除此条目rectangle
+ * 先删除此rectangle,再调用condenseTree()返回删除结点的集合,把其中的叶子结点中的每个条目重新插入;
+ * 非叶子结点就从此结点开始遍历所有结点,然后把所有的叶子结点中的所有条目全部重新插入
+ * @param rectangle
+ * @return
+ */
+ protected int delete(Rectangle rectangle)
+ {
+ for(int i = 0; i < usedSpace; i ++)
+ {
+ if(datas[i].equals(rectangle))
+ {
+ deleteData(i);
+ List deleteEntriesList = new ArrayList();
+ condenseTree(deleteEntriesList);
+
+ //重新插入删除结点中剩余的条目
+ for(int j = 0; j < deleteEntriesList.size(); j ++)
+ {
+ RTNode node = deleteEntriesList.get(j);
+ if(node.isLeaf())//叶子结点,直接把其上的数据重新插入
+ {
+ for(int k = 0; k < node.usedSpace; k ++)
+ {
+ rtree.insert(node.datas[k]);
+ }
+ }else{//非叶子结点,需要先后序遍历出其上的所有结点
+ List traverseNodes = rtree.traversePostOrder(node);
+
+ //把其中的叶子结点中的条目重新插入
+ for(int index = 0; index < traverseNodes.size(); index ++)
+ {
+ RTNode traverseNode = traverseNodes.get(index);
+ if(traverseNode.isLeaf())
+ {
+ for(int t = 0; t < traverseNode.usedSpace; t ++)
+ {
+ rtree.insert(traverseNode.datas[t]);
+ }
+ }
+ }
+
+ }
+ }
+
+ return deleteIndex;
+ }//end if
+ }//end for
+ return -1;
+ }
+
+ @Override
+ protected RTDataNode findLeaf(Rectangle rectangle)
+ {
+ for(int i = 0; i < usedSpace; i ++)
+ {
+ if(datas[i].enclosure(rectangle))
+ {
+ deleteIndex = i;//记录搜索路径
+ return this;
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTDirNode.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTDirNode.java
new file mode 100644
index 00000000..023d1926
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTDirNode.java
@@ -0,0 +1,281 @@
+package com.secure.rtree;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName RTDirNode
+ * @Description 非叶节点
+ */
+public class RTDirNode extends RTNode implements Serializable
+{
+ /**
+ * 孩子结点
+ */
+ protected List children;
+
+ public RTDirNode() {
+ }
+
+ public RTDirNode(RTree rtree, RTNode parent, int level)
+ {
+ super(rtree, parent, level);
+ children = new ArrayList();
+ }
+
+ /**
+ * @param index
+ * @return 对应索引下的孩子结点
+ */
+ public RTNode getChild(int index)
+ {
+ return children.get(index);
+ }
+
+ public List getChildren(){ return children; }
+
+ @Override
+ public RTDataNode chooseLeaf(Rectangle rectangle)
+ {
+ int index;
+
+ switch (rtree.getTreeType())
+ {
+ case Constants.RTREE_LINEAR:
+
+ case Constants.RTREE_QUADRATIC:
+
+ case Constants.RTREE_EXPONENTIAL:
+ index = findLeastEnlargement(rectangle);
+ break;
+ case Constants.RSTAR:
+ if(level == 1)//即此结点指向叶节点
+ {
+ index = findLeastOverlap(rectangle);
+ }else{
+ index = findLeastEnlargement(rectangle);
+ }
+ break;
+
+ default:
+ throw new IllegalStateException("Invalid tree type.");
+ }
+
+ insertIndex = index;//记录插入路径的索引
+
+ return getChild(index).chooseLeaf(rectangle);
+ }
+
+ /**
+ * @param rectangle
+ * @return 返回最小重叠面积的结点的索引,如果重叠面积相等则选择加入此Rectangle后面积增量更小的,如果面积增量还相等则选择自身面积更小的
+ */
+ private int findLeastOverlap(Rectangle rectangle)
+ {
+ float overlap = Float.POSITIVE_INFINITY;
+ int sel = -1;
+
+ for(int i = 0; i < usedSpace; i ++)
+ {
+ RTNode node = getChild(i);
+ float ol = 0;
+
+ for(int j = 0; j < node.datas.length; j ++)
+ {
+ ol += rectangle.intersectingArea(node.datas[j]);
+ }
+ if(ol < overlap)
+ {
+ overlap = ol;//记录重叠面积最小的
+ sel = i;//记录第几个孩子的索引
+ }else if(ol == overlap)//如果重叠面积相等则选择加入此Rectangle后面积增量更小的,如果面积增量还相等则选择自身面积更小的
+ {
+ double area1 = datas[i].getUnionRectangle(rectangle).getArea() - datas[i].getArea();
+ double area2 = datas[sel].getUnionRectangle(rectangle).getArea() - datas[sel].getArea();
+
+ if(area1 == area2)
+ {
+ sel = (datas[sel].getArea() <= datas[i].getArea()) ? sel : i;
+ }else{
+ sel = (area1 < area2) ? i : sel;
+ }
+ }
+ }
+ return sel;
+ }
+
+ /**
+ * @param rectangle
+ * @return 面积增量最小的结点的索引,如果面积增量相等则选择自身面积更小的
+ */
+ private int findLeastEnlargement(Rectangle rectangle)
+ {
+ double area = Double.POSITIVE_INFINITY;
+ int sel = -1;
+
+ for(int i = 0; i < usedSpace; i ++)
+ {
+ double enlargement = datas[i].getUnionRectangle(rectangle).getArea() - datas[i].getArea();
+ if(enlargement < area)
+ {
+ area = enlargement;
+ sel = i;
+ }else if(enlargement == area)
+ {
+ sel = (datas[sel].getArea() < datas[i].getArea()) ? sel : i;
+ }
+ }
+
+ return sel;
+ }
+
+ /**
+ * 插入新的Rectangle后从插入的叶节点开始向上调整RTree,直到根节点
+ * @param node1 引起需要调整的孩子结点
+ * @param node2 分裂的结点,若未分裂则为null
+ */
+ public void adjustTree(RTNode node1, RTNode node2)
+ {
+ //先要找到指向原来旧的结点(即未添加Rectangle之前)的条目的索引
+ datas[insertIndex] = node1.getNodeRectangle();//先用node1覆盖原来的结点
+ children.set(insertIndex, node1);//替换旧的结点
+
+ if(node2 != null)
+ {
+ insert(node2);//插入新的结点
+
+ }else if(! isRoot())//还没到达根节点
+ {
+ RTDirNode parent = (RTDirNode) getParent();
+ parent.adjustTree(this, null);//向上调整直到根节点
+ }
+ }
+
+ /**
+ * @param node
+ * @return 如果结点需要分裂则返回true
+ */
+ protected boolean insert(RTNode node)
+ {
+ if(usedSpace < rtree.getNodeCapacity())
+ {
+ datas[usedSpace ++] = node.getNodeRectangle();
+ children.add(node);//新加的
+ node.parent = this;//新加的
+ RTDirNode parent = (RTDirNode) getParent();
+ if(parent != null)
+ {
+ parent.adjustTree(this, null);
+ }
+ return false;
+ }else{//非叶子结点需要分裂
+ RTDirNode[] a = splitIndex(node);
+ RTDirNode n = a[0];
+ RTDirNode nn = a[1];
+
+ if(isRoot())
+ {
+ //新建根节点,层数加1
+ RTDirNode newRoot = new RTDirNode(rtree, Constants.NULL, level + 1);
+
+ //还需要把原来结点的孩子添加到两个分裂的结点n和nn中,此时n和nn的孩子结点还为空
+// for(int i = 0; i < n.usedSpace; i ++)
+// {
+// n.children.add(this.children.get(index));
+// }
+//
+// for(int i = 0; i < nn.usedSpace; i ++)
+// {
+// nn.children.add(this.children.get(index));
+// }
+
+ //把两个分裂的结点n和nn添加到根节点
+ newRoot.addData(n.getNodeRectangle());
+ newRoot.addData(nn.getNodeRectangle());
+
+ newRoot.children.add(n);
+ newRoot.children.add(nn);
+
+ //设置两个分裂的结点n和nn的父节点
+ n.parent = newRoot;
+ nn.parent = newRoot;
+
+ //最后设置rtree的根节点
+ rtree.setRoot(newRoot);//新加的
+ }else {
+ RTDirNode p = (RTDirNode) getParent();
+ p.adjustTree(n, nn);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 非叶子结点的分裂
+ *
+ * @param node
+ * @return
+ */
+ private RTDirNode[] splitIndex(RTNode node)
+ {
+ int[][] group = null;
+
+ switch (rtree.getTreeType())
+ {
+ case Constants.RTREE_LINEAR:
+ break;
+ case Constants.RTREE_QUADRATIC:
+ group = quadraticSplit(node.getNodeRectangle());
+ children.add(node);//新加的
+ node.parent = this;//新加的
+ break;
+ case Constants.RTREE_EXPONENTIAL:
+ break;
+ case Constants.RSTAR:
+ break;
+ default:
+ throw new IllegalStateException("Invalid tree type.");
+ }
+
+ RTDirNode index1 = new RTDirNode(rtree, parent, level);
+ RTDirNode index2 = new RTDirNode(rtree, parent, level);
+
+ int[] group1 = group[0];
+ int[] group2 = group[1];
+
+ for(int i = 0; i < group1.length; i ++)
+ {
+ //为index1添加数据和孩子
+ index1.addData(datas[group1[i]]);
+ index1.children.add(this.children.get(group1[i]));//新加的
+ //让index1成为其父节点
+ this.children.get(group1[i]).parent = index1;//新加的
+ }
+ for(int i = 0; i < group2.length; i ++)
+ {
+ index2.addData(datas[group2[i]]);
+ index2.children.add(this.children.get(group2[i]));//新加的
+ this.children.get(group2[i]).parent = index2;//新加的
+ }
+
+ return new RTDirNode[]{index1,index2};
+ }
+
+ @Override
+ protected RTDataNode findLeaf(Rectangle rectangle)
+ {
+ for(int i = 0; i < usedSpace; i ++)
+ {
+ if(datas[i].enclosure(rectangle))
+ {
+ deleteIndex = i;//记录搜索路径
+ RTDataNode leaf = children.get(i).findLeaf(rectangle);
+ if(leaf != null)
+ return leaf;
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTNode.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTNode.java
new file mode 100644
index 00000000..abaf0d6e
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTNode.java
@@ -0,0 +1,431 @@
+package com.secure.rtree;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+//import com.njupt.spatial.INode;
+
+/**
+ * @ClassName RTNode
+ * @Description
+ */
+public abstract class RTNode implements Serializable
+{
+ /**
+ * 结点所在的树
+ */
+ protected RTree rtree;
+
+ /**
+ * 结点所在的层
+ */
+ protected int level;
+
+ /**
+ * 相当于条目
+ */
+ protected Rectangle[] datas;
+
+// /**
+// * 结点的容量
+// */
+// protected int capacity;
+
+ /**
+ * 父节点
+ */
+ protected RTNode parent;
+
+ /**
+ * 结点已用的空间
+ */
+ protected int usedSpace;
+
+ /**
+ * 记录插入的搜索路径索引
+ */
+ protected int insertIndex;
+
+ /**
+ * 记录删除的查找路径索引
+ */
+ protected int deleteIndex;
+
+ public RTNode() {
+ }
+
+ public RTNode(RTree rtree, RTNode parent, int level)
+ {
+ this.rtree = rtree;
+ this.parent = parent;
+ this.level = level;
+// this.capacity = capacity;
+ datas = new Rectangle[rtree.getNodeCapacity() + 1];//多出的一个用于结点分裂
+ usedSpace = 0;
+ }
+
+ /**
+ * @return 返回父节点
+ */
+ public RTNode getParent()
+ {
+ return parent;
+ }
+
+ public int getLevel() {
+ return level;
+ }
+
+ public Rectangle[] getDatas() {
+ return datas;
+ }
+
+ public int getUsedSpace() {
+ return usedSpace;
+ }
+ // /**
+// * @return 结点容量
+// */
+// public int getNodeCapacity()
+// {
+// return capacity;
+// }
+
+ /**
+ * 向结点中添加Rectangle,即添加条目
+ * @param rectangle
+ */
+ protected void addData(Rectangle rectangle)
+ {
+ if(usedSpace == rtree.getNodeCapacity())
+ {
+ throw new IllegalArgumentException("Node is full.");
+ }
+ datas[usedSpace ++] = rectangle;
+ }
+
+ /**
+ * 删除结点中的第i个条目
+ * @param i
+ */
+ protected void deleteData(int i)
+ {
+ if(datas[i + 1] != null)
+ {
+ System.arraycopy(datas, i + 1, datas, i, usedSpace - i -1);
+ datas[usedSpace - 1] = null;
+ }
+ else
+ datas[i] = null;
+ usedSpace --;
+ }
+
+ /**
+ * 叶节点L中刚刚删除了一个条目,如果这个结点的条目数太少下溢,则删除该结点,同时将该结点中剩余的条目重定位到其他结点中。
+ * 如果有必要,要逐级向上进行这种删除,调整向上传递的路径上的所有外包矩形,使其尽可能小,直到根节点。
+ * @param list 存储删除结点中剩余条目
+ */
+ protected void condenseTree(List list)
+ {
+ if(isRoot())
+ {
+ //根节点只有一个条目了,即只有左孩子或者右孩子
+ if(! isLeaf() && usedSpace == 1)
+ {
+ RTDirNode root = (RTDirNode) this;
+
+ RTNode child = root.getChild(0);
+ root.children.remove(this);//gc
+ child.parent = null;
+// if(child.level > 0)
+// child.level --;
+ rtree.setRoot(child);
+
+// //所有结点的level减1,即树降低一层
+// List nodes = rtree.traversePostOrder(child);
+// for(int i = 0; i < nodes.size(); i ++)
+// {
+// nodes.get(i).level -= 1;
+// }
+
+ }
+ }else{
+ RTNode parent = getParent();
+
+ int min = Math.round(rtree.getNodeCapacity() * rtree.getFillFactor());
+ if(usedSpace < min)
+ {
+ parent.deleteData(parent.deleteIndex);//其父节点中删除此条目
+ ((RTDirNode)parent).children.remove(this);
+ this.parent = null;
+ list.add(this);//之前已经把数据删除了
+ }else{
+ parent.datas[parent.deleteIndex] = getNodeRectangle();
+ }
+ parent.condenseTree(list);
+ }
+ }
+
+ /**
+ * 分裂结点的平方算法
+ * 1、为两个组选择第一个条目--调用算法pickSeeds()来为两个组选择第一个元素,分别把选中的两个条目分配到两个组当中。
+ * 2、检查是否已经分配完毕,如果一个组中的条目太少,为避免下溢,将剩余的所有条目全部分配到这个组中,算法终止
+ * 3、调用pickNext来选择下一个进行分配的条目--计算把每个条目加入每个组之后面积的增量,选择两个组面积增量差最大的条目索引,
+ * 如果面积增量相等则选择面积较小的组,若面积也相等则选择条目数更少的组
+ * @param rectangle 导致分裂的溢出Rectangle
+ * @return 两个组中的条目的索引
+ */
+ protected int[][] quadraticSplit(Rectangle rectangle)
+ {
+ if(rectangle == null)
+ {
+ throw new IllegalArgumentException("Rectangle cannot be null.");
+ }
+
+ datas[usedSpace] = rectangle; //先添加进去
+// if(this instanceof RTDirNode)
+// {
+// (RTDirNode)(this).children.add()
+// }
+ int total = usedSpace + 1; //结点总数
+
+ //标记访问的条目
+ int[] mask = new int[total];
+ for(int i = 0; i < total; i ++)
+ {
+ mask[i] = 1;
+ }
+
+ //每个组只是有total/2个条目
+ int c = total/2 + 1;
+ //每个结点最小条目个数
+ int nodeCapacity = rtree.getNodeCapacity();
+ int minNodeSize = Math.round( nodeCapacity* rtree.getFillFactor());
+ //至少有两个
+ if(minNodeSize < 2)
+ minNodeSize = 2;
+
+ //记录没有被检查的条目的个数
+ int rem = total;
+
+ int[] group1 = new int[c];//记录分配的条目的索引
+ int[] group2 = new int[c];//记录分配的条目的索引
+ //跟踪被插入每个组的条目的索引
+ int i1 = 0, i2 = 0;
+
+ int[] seed = pickSeeds();
+ group1[i1 ++] = seed[0];
+ group2[i2 ++] = seed[1];
+ rem -=2;
+ mask[group1[0]] = -1;
+ mask[group2[0]] = -1;
+
+ while(rem > 0)
+ {
+ //将剩余的所有条目全部分配到group1组中,算法终止
+ if(minNodeSize - i1 == rem)
+ {
+ for(int i = 0; i < total; i ++)//总共rem个
+ {
+ if(mask[i] != -1)//还没有被分配
+ {
+ group1[i1 ++] = i;
+ mask[i] = -1;
+ rem --;
+ }
+ }
+ //将剩余的所有条目全部分配到group2组中,算法终止
+ }else if(minNodeSize - i2 == rem)
+ {
+ for(int i = 0; i < total; i ++)//总共rem个
+ {
+ if(mask[i] != -1)//还没有被分配
+ {
+ group2[i2 ++] = i;
+ mask[i] = -1;
+ rem --;
+ }
+ }
+ }else
+ {
+ //求group1中所有条目的最小外包矩形
+ Rectangle mbr1 = (Rectangle) datas[group1[0]].clone();
+ for(int i = 1; i < i1; i ++)
+ {
+ mbr1 = mbr1.getUnionRectangle(datas[group1[i]]);
+ }
+ //求group2中所有条目的外包矩形
+ Rectangle mbr2 = (Rectangle) datas[group2[0]].clone();
+ for(int i = 1; i < i2; i ++)
+ {
+ mbr2 = mbr2.getUnionRectangle(datas[group2[i]]);
+ }
+
+ //找出下一个进行分配的条目
+ double dif = Double.NEGATIVE_INFINITY;
+ double areaDiff1 = 0, areaDiff2 = 0;
+ int sel = -1;
+ for(int i = 0; i < total; i ++)
+ {
+ if(mask[i] != -1)//还没有被分配的条目
+ {
+ //计算把每个条目加入每个组之后面积的增量,选择两个组面积增量差最大的条目索引
+ Rectangle a = mbr1.getUnionRectangle(datas[i]);
+ areaDiff1 = a.getArea() - mbr1.getArea();
+
+ Rectangle b = mbr2.getUnionRectangle(datas[i]);
+ areaDiff2 = b.getArea() - mbr2.getArea();
+
+ if(Math.abs(areaDiff1 - areaDiff2) > dif)
+ {
+ dif = Math.abs(areaDiff1 - areaDiff2);
+ sel = i;
+ }
+ }
+ }
+
+ if(areaDiff1 < areaDiff2)//先比较面积增量
+ {
+ group1[i1 ++] = sel;
+ }else if(areaDiff1 > areaDiff2)
+ {
+ group2[i2 ++] = sel;
+ }else if(mbr1.getArea() < mbr2.getArea())//再比较自身面积
+ {
+ group1[i1 ++] = sel;
+ }else if(mbr1.getArea() > mbr2.getArea())
+ {
+ group2[i2 ++] = sel;
+ }else if(i1 < i2)//最后比较条目个数
+ {
+ group1[i1 ++] = sel;
+ }else if(i1 > i2)
+ {
+ group2[i2 ++] = sel;
+ }else {
+ group1[i1 ++] = sel;
+ }
+ mask[sel] = -1;
+ rem --;
+
+ }
+ }//end while
+
+
+ int[][] ret = new int[2][];
+ ret[0] = new int[i1];
+ ret[1] = new int[i2];
+
+ for(int i = 0; i < i1; i ++)
+ {
+ ret[0][i] = group1[i];
+ }
+ for(int i = 0; i < i2; i ++)
+ {
+ ret[1][i] = group2[i];
+ }
+ return ret;
+ }
+
+
+ /**
+ * 1、对每一对条目E1和E2,计算包围它们的Rectangle J,计算d = area(J) - area(E1) - area(E2);
+ * 2、Choose the pair with the largest d
+ * @return 返回两个条目如果放在一起会有最多的冗余空间的条目索引
+ */
+ protected int[] pickSeeds()
+ {
+ double inefficiency = Double.NEGATIVE_INFINITY;
+ int i1 = 0, i2 = 0;
+
+ //
+ for(int i = 0; i < usedSpace; i ++)
+ {
+ for(int j = i + 1; j <= usedSpace; j ++)//注意此处的j值
+ {
+ Rectangle rectangle = datas[i].getUnionRectangle(datas[j]);
+ double d = rectangle.getArea() - datas[i].getArea() - datas[j].getArea();
+
+ if(d > inefficiency)
+ {
+ inefficiency = d;
+ i1 = i;
+ i2 = j;
+ }
+ }
+ }
+ return new int[]{i1, i2};
+ }
+
+ /**
+ * @return 返回包含结点中所有条目的最小Rectangle
+ */
+ public Rectangle getNodeRectangle()
+ {
+ if(usedSpace > 0)
+ {
+ Rectangle[] rectangles = new Rectangle[usedSpace];
+ System.arraycopy(datas, 0, rectangles, 0, usedSpace);
+ return Rectangle.getUnionRectangle(rectangles);
+ }else {
+ return new Rectangle(new Point(new double[]{0,0}), new Point(new double[]{0,0}));
+ }
+ }
+
+ /**
+ * @return 是否根节点
+ */
+ public boolean isRoot()
+ {
+ return (parent == Constants.NULL);
+ }
+
+ /**
+ * @return 是否非叶子结点
+ */
+ public boolean isIndex()
+ {
+ return (level != 0);
+ }
+
+ /**
+ * @return 是否叶子结点
+ */
+ public boolean isLeaf()
+ {
+ return (level == 0);
+ }
+
+
+ /**
+ * 步骤CL1:初始化——记R树的根节点为N。
+ * 步骤CL2:检查叶节点——如果N是个叶节点,返回N
+ * 步骤CL3:选择子树——如果N不是叶节点,则从N中所有的条目中选出一个最佳的条目F,
+ * 选择的标准是:如果E加入F后,F的外廓矩形FI扩张最小,则F就是最佳的条目。如果有两个
+ * 条目在加入E后外廓矩形的扩张程度相等,则在这两者中选择外廓矩形较小的那个。
+ * 步骤CL4:向下寻找直至达到叶节点——记Fp指向的孩子节点为N,然后返回步骤CL2循环运算,
+ * 直至查找到叶节点。
+ * @param rectangle
+ * @return RTDataNode
+ */
+ protected abstract RTDataNode chooseLeaf(Rectangle rectangle);
+
+ /**
+ * R树的根节点为T,查找包含rectangle的叶子结点
+ * 1、如果T不是叶子结点,则逐个查找T中的每个条目是否包围rectangle,若包围则递归调用findLeaf()
+ * 2、如果T是一个叶子结点,则逐个检查T中的每个条目能否匹配rectangle
+ * @param rectangle
+ * @return 返回包含rectangle的叶节点
+ */
+ protected abstract RTDataNode findLeaf(Rectangle rectangle);
+
+ public List getObjects() {
+ List d = new ArrayList<>();
+ Rectangle[] datas = getDatas();
+ for (Rectangle sRectangle:datas)
+ d.add(sRectangle);
+
+ return d;
+ }
+
+}
\ No newline at end of file
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTree.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTree.java
new file mode 100644
index 00000000..dbefb147
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RTree.java
@@ -0,0 +1,497 @@
+package com.secure.rtree;
+
+import com.secure.alg.BVLSQ;
+import com.secure.svrtree.SVRTree;
+import org.apache.commons.collections.CollectionUtils;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * @ClassName RTree
+ * @Description
+ */
+public class RTree implements Serializable
+{
+ /**
+ * 根节点
+ */
+ private RTNode root;
+
+ /**
+ * 树类型
+ */
+ private int tree_type;
+
+ /**
+ * 结点容量
+ */
+ private int nodeCapacity = -1;
+
+ /**
+ * 结点填充因子
+ */
+ private float fillFactor = -1;
+
+ private int dimension ;
+
+ public RTree(int capacity, float fillFactor, int type, int dimension)
+ {
+ this.fillFactor = fillFactor;
+ tree_type = type;
+ nodeCapacity = capacity;
+ this.dimension = dimension;
+ root = new RTDataNode(this, Constants.NULL);
+ }
+
+ /**
+ * @return RTree的维度
+ */
+ public int getDimension()
+ {
+ return dimension;
+ }
+
+ public void setRoot(RTNode root)
+ {
+ this.root = root;
+ }
+
+ public float getFillFactor()
+ {
+ return fillFactor;
+ }
+
+ /**
+ * @return 返回结点容量
+ */
+ public int getNodeCapacity()
+ {
+ return nodeCapacity;
+ }
+
+ /**
+ * @return 返回树的类型
+ */
+ public int getTreeType()
+ {
+ return tree_type;
+ }
+
+ public RTNode getRoot() {
+ return root;
+ }
+
+ public int getTree_type() {
+ return tree_type;
+ }
+
+ public void setTree_type(int tree_type) {
+ this.tree_type = tree_type;
+ }
+
+ public void setNodeCapacity(int nodeCapacity) {
+ this.nodeCapacity = nodeCapacity;
+ }
+
+ public void setFillFactor(float fillFactor) {
+ this.fillFactor = fillFactor;
+ }
+
+ public void setDimension(int dimension) {
+ this.dimension = dimension;
+ }
+
+ /**
+ * 向Rtree中插入Rectangle
+ * 1、先找到合适的叶节点
+ * 2、再向此叶节点中插入
+ * @param rectangle
+ */
+ public boolean insert(Rectangle rectangle)
+ {
+ if(rectangle == null)
+ throw new IllegalArgumentException("Rectangle cannot be null.");
+
+ if(rectangle.getHigh().getDimension() != getDimension())
+ {
+ throw new IllegalArgumentException("Rectangle dimension different than RTree dimension.");
+ }
+
+ RTDataNode leaf = root.chooseLeaf(rectangle);
+
+ return leaf.insert(rectangle);
+ }
+
+ /**
+ * 从R树中删除Rectangle
+ * 1、寻找包含记录的结点--调用算法findLeaf()来定位包含此记录的叶子结点L,如果没有找到则算法终止。
+ * 2、删除记录--将找到的叶子结点L中的此记录删除
+ * 3、调用算法condenseTree
+ * @param rectangle
+ * @return
+ */
+ public int delete(Rectangle rectangle)
+ {
+ if(rectangle == null)
+ {
+ throw new IllegalArgumentException("Rectangle cannot be null.");
+ }
+
+ if(rectangle.getHigh().getDimension() != getDimension())
+ {
+ throw new IllegalArgumentException("Rectangle dimension different than RTree dimension.");
+ }
+
+ RTDataNode leaf = root.findLeaf(rectangle);
+
+ if(leaf != null)
+ {
+ return leaf.delete(rectangle);
+ }
+
+ return -1;
+ }
+
+ /**
+ * 从给定的结点root开始遍历所有的结点
+ * @param
+ * @return 所有遍历的结点集合
+ */
+ public List traversePostOrder(RTNode root)
+ {
+ if(root == null)
+ throw new IllegalArgumentException("Node cannot be null.");
+
+ List list = new ArrayList();
+ list.add(root);
+
+ if(! root.isLeaf())
+ {
+ for(int i = 0; i < root.usedSpace; i ++)
+ {
+ List a = traversePostOrder(((RTDirNode)root).getChild(i));
+ for(int j = 0; j < a.size(); j ++)
+ {
+ list.add(a.get(j));
+ }
+ }
+ }
+
+ return list;
+ }
+
+ public static RTree createRTree(double[] data, int capacity, int dim) {
+ RTree tree = new RTree(capacity, 0.4f, Constants.RTREE_QUADRATIC, dim);
+
+ for (int i = 0; i < data.length; ) {
+ double[] dt = new double[dim];
+ double[] sp = new double[2];
+
+ for (int j = 0; j < dim + 2; j++) {
+ if (j < 2) {
+ sp[j] = data[i++];
+ } else {
+ dt[j - 2] = data[i++];
+ }
+ }
+
+ Point p1 = new Point(dt, sp);
+ final Rectangle rectangle = new Rectangle(p1, p1);
+ tree.insert(rectangle);
+ }
+ //补充location
+ List list = tree.traversePostOrder(tree.getRoot());
+ int highLevel = tree.getRoot().getLevel();
+ List> listWithLevel = new ArrayList<>();
+ for (int h = 0; h < highLevel + 1; h++) {
+ listWithLevel.add(new ArrayList());
+ }
+
+ for (RTNode node : list) {
+ for (int h = 0; h < highLevel + 1; h++) {
+ if (node.getLevel() == h)
+ listWithLevel.get(h).add(node);
+ }
+ }
+ for (int L = 1; L < highLevel + 1; L++) {
+ for (int i = 0; i < listWithLevel.get(L).size(); i++) {
+ RTDirNode parent_node = (RTDirNode) listWithLevel.get(L).get(i);
+ List children_node = parent_node.getChildren();
+ Rectangle[] children_rect = parent_node.getDatas();
+ for (int j = 0; j < children_node.size(); j++) {
+ Rectangle[] set = children_node.get(j).getDatas();
+ double low_x = Double.MAX_VALUE;
+ double low_y = Double.MAX_VALUE;
+ double high_x = Double.MIN_VALUE;
+ double high_y = Double.MIN_VALUE;
+ for (int n = 0; n < set.length; n++) {
+ if (set[n] != null) {
+ if (set[n].getLow().getLocation()[0] < low_x)
+ low_x = set[n].getLow().getLocation()[0];
+ if (set[n].getLow().getLocation()[1] < low_y)
+ low_y = set[n].getLow().getLocation()[1];
+
+ if (set[n].getHigh().getLocation()[0] > high_x)
+ high_x = set[n].getHigh().getLocation()[0];
+ if (set[n].getHigh().getLocation()[1] > high_y)
+ high_y = set[n].getHigh().getLocation()[1];
+ }
+ }
+ children_rect[j].getLowWithoutClone().setLocation(low_x, low_y);
+ children_rect[j].getHigh().setLocation(high_x, high_y);
+ }
+ }
+ }
+ return tree;
+ }
+ public static void main(String[] args) throws Exception
+ {
+ RTree tree = new RTree(3, 0.4f, Constants.RTREE_QUADRATIC, 2);
+
+// float[] f = {10, 20, 40, 70, //1
+// 30, 10, 70, 15,
+// 100, 70, 110, 80, //3
+// 0, 50, 30, 55,
+// 13, 21, 54, 78, //5
+// 3, 8, 23, 34,
+// 200, 29, 202, 50,
+// 34, 1, 35, 1, //8
+// 201, 200, 234, 203,
+// 56, 69, 58, 70, //10
+// 2, 67, 270, 102,
+// 1, 10, 310, 20, //12
+// 23, 12, 345, 120,
+// 5, 34, 100, 340,
+// 19,100,450,560, //15
+// 12,340,560,450,
+// 34,45,190,590,
+// 24,47,770,450, //18
+//
+// 91,99,390,980,
+// 89,10,99,100, //20
+// 10,29,400,990,
+// 110,220,220,330,
+// 123,24,234,999 //23
+// };
+
+// float[] f = {1,9,2,10,
+// 4,8,6,7,
+// 9,10,7,5,
+// 5,6,4,3,
+// 3,2,9,1,
+// 10,4,6,2,
+// 8,3,8,4
+// };
+ //插入结点
+// for(int i = 0; i < f.length;)
+// {
+// Point p1 = new Point(new double[]{f[i++],f[i++]});
+// final Rectangle rectangle = new Rectangle(p1, p1);
+// tree.insert(rectangle);
+//
+// Rectangle[] rectangles = tree.root.datas;
+// System.out.println(tree.root.level);
+// for(int j = 0; j < rectangles.length; j ++)
+// System.out.println(rectangles[j]);
+// }
+ String path = "D:\\idea\\SVLSQ\\data_test\\test_2_12.txt";
+ double[] f = new double[0];
+ String filename = path.substring(0,path.lastIndexOf("."));
+ String[] split = filename.split("\\\\");
+ String [] p =split[split.length-1].split("_");
+ String typeName = p[0];
+ Integer num = Integer.valueOf(p[p.length - 1]);
+ Integer dim = Integer.valueOf(p[p.length - 2]);
+
+ try {
+ f = BVLSQ.readFile(path);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ for(int i = 0; i < f.length;)
+ {
+ double[] dt = new double[dim];
+ double[] sp = new double[2];
+
+ for (int j =0;j>>>>>>>>>>>>>>>遍历R-Tree>>>>>>>>>>>>>>>>>>>>>>");
+ Queue queue = new LinkedList<>();
+
+ queue.offer(tree.root);
+
+ while (!queue.isEmpty()) {
+ RTNode node = queue.poll();
+ Rectangle[] rectangles = node.datas;
+ System.out.println(node.level);
+ for (int j = 0; j < rectangles.length; j++)
+ System.out.println(rectangles[j]);
+ if(node.getClass().equals(RTDirNode.class)) {
+ RTDirNode dirNode = (RTDirNode) node;
+ List children = dirNode.getChildren();
+ queue.addAll(children);
+ }
+ }
+
+ System.out.println(">>>>>>>>>>>>>>>>遍历R-Tree2>>>>>>>>>>>>>>>>>>>>>>");
+ List list = tree.traversePostOrder(tree.root);
+
+
+// List newList = new ArrayList<>();
+// CollectionUtils.addAll(newList, new Object[list.size()]);
+// Collections.copy(newList, list);
+
+ int highLevel = tree.root.getLevel();
+ List> listWithLevel = new ArrayList<>();
+ for (int h = 0; h ());
+ }
+
+ for (RTNode node:list){
+ for (int h = 0; h children_node = parent_node.getChildren();
+ Rectangle[] children_rect = parent_node.getDatas();
+ for (int j =0;jhigh_x)
+ high_x=set[n].getHigh().getLocation()[0];
+ if (set[n].getHigh().getLocation()[1]>high_y)
+ high_y=set[n].getHigh().getLocation()[1];
+ }
+ }
+ children_rect[j].getLowWithoutClone().setLocation(low_x,low_y);
+ children_rect[j].getHigh().setLocation(high_x,high_y);
+ }
+ }
+ }
+ //打印结点
+ for (RTNode node:list){
+ System.out.println(node.getLevel());
+
+ Rectangle[] datas = node.getDatas();
+ for(Rectangle data:datas){
+ if (data!=null){
+ System.out.println(data.toString());
+ }
+ }
+ }
+
+ System.out.println("---------------------------------");
+// System.out.println("Insert finished.");
+//
+// //删除结点
+// System.out.println("---------------------------------");
+// System.out.println("Begin delete.");
+//
+// for(int i = 0; i < f.length;)
+// {
+// Point p1 = new Point(new float[]{f[i++],f[i++]});
+// Point p2 = new Point(new float[]{f[i++],f[i++]});
+// final Rectangle rectangle = new Rectangle(p1, p2);
+// tree.delete(rectangle);
+//
+// Rectangle[] rectangles = tree.root.datas;
+// System.out.println(tree.root.level);
+// for(int j = 0; j < rectangles.length; j ++)
+// System.out.println(rectangles[j]);
+// }
+//
+// System.out.println("---------------------------------");
+// System.out.println("Delete finished.");
+//
+//
+// Rectangle[] rectangles = tree.root.datas;
+// for(int i = 0; i < rectangles.length; i ++)
+// System.out.println(rectangles[i]);
+
+
+// System.out.println("---------------------------------");
+// RTree tree = new RTree(5, 0.4f, Constants.RTREE_QUADRATIC,2);
+// BufferedReader reader = new BufferedReader(new FileReader(new File("d:\\LB.txt")));
+// String line ;
+// while((line = reader.readLine()) != null)
+// {
+// String[] splits = line.split(" ");
+// float lx = Float.parseFloat(splits[1]);
+// float ly = Float.parseFloat(splits[2]);
+// float hx = Float.parseFloat(splits[3]);
+// float hy = Float.parseFloat(splits[4]);
+//
+// Point p1 = new Point(new float[]{lx,ly});
+// Point p2 = new Point(new float[]{hx,hy});
+//
+// final Rectangle rectangle = new Rectangle(p1, p2);
+// tree.insert(rectangle);
+//
+// Rectangle[] rectangles = tree.root.datas;
+// System.out.println(tree.root.level);
+// for(int j = 0; j < rectangles.length; j ++)
+// System.out.println(rectangles[j]);
+// }
+//
+//
+// //删除结点
+// System.out.println("---------------------------------");
+// System.out.println("Begin delete.");
+//
+// reader = new BufferedReader(new FileReader(new File("d:\\LB.txt")));
+// while((line = reader.readLine()) != null)
+// {
+// String[] splits = line.split(" ");
+// float lx = Float.parseFloat(splits[1]);
+// float ly = Float.parseFloat(splits[2]);
+// float hx = Float.parseFloat(splits[3]);
+// float hy = Float.parseFloat(splits[4]);
+//
+// Point p1 = new Point(new float[]{lx,ly});
+// Point p2 = new Point(new float[]{hx,hy});
+//
+// final Rectangle rectangle = new Rectangle(p1, p2);
+// tree.delete(rectangle);
+//
+// Rectangle[] rectangles = tree.root.datas;
+// System.out.println(tree.root.level);
+// for(int j = 0; j < rectangles.length; j ++)
+// System.out.println(rectangles[j]);
+// }
+//
+// System.out.println("---------------------------------");
+// System.out.println("Delete finished.");
+
+ }
+
+}
\ No newline at end of file
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RectAndNode.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RectAndNode.java
new file mode 100644
index 00000000..bdfe1ffb
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/RectAndNode.java
@@ -0,0 +1,32 @@
+package com.secure.rtree;
+
+import java.util.Stack;
+
+public class RectAndNode {
+ private Stack rect;
+ private Stack node;
+
+ public RectAndNode() {
+ }
+
+ public RectAndNode(Stack rect, Stack node) {
+ this.rect = rect;
+ this.node = node;
+ }
+
+ public Stack getRect() {
+ return rect;
+ }
+
+ public void setRect(Stack rect) {
+ this.rect = rect;
+ }
+
+ public Stack getNode() {
+ return node;
+ }
+
+ public void setNode(Stack node) {
+ this.node = node;
+ }
+}
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Rectangle.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Rectangle.java
new file mode 100644
index 00000000..7fc84adf
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/rtree/Rectangle.java
@@ -0,0 +1,423 @@
+package com.secure.rtree;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 外包矩形
+ * @ClassName Rectangle
+ * @Description
+ */
+public class Rectangle implements Cloneable, Serializable
+{
+ private Point low;
+ private Point high;
+ private List cell;
+ private List> scope;
+
+ //补
+ private double dis=-1;
+
+ public double getDis() {
+ return dis;
+ }
+
+ public void setDis(double dis) {
+ this.dis = dis;
+ }
+
+ public List getCell() {
+ return cell;
+ }
+
+ public void setCell(List cell) {
+ this.cell = cell;
+ }
+
+ public List> getScope() {
+ return scope;
+ }
+
+ public void setScope(List> scope) {
+ this.scope = scope;
+ }
+
+ public Rectangle(List cell, List> scope){
+ this.cell =cell;
+ this.scope = scope;
+
+ //矩形四个点
+ ArrayList p1 = new ArrayList<>();
+ ArrayList p2 = new ArrayList<>();
+ ArrayList p3 = new ArrayList<>();
+ ArrayList p4 = new ArrayList<>();
+
+ double x = scope.get(0).get(0);
+ if (x<0){
+ p1.add(new BigInteger("0"));
+ p2.add(new BigInteger("0"));
+ p3.add(new BigInteger("0"));
+ p4.add(new BigInteger("0"));
+ }else{
+ p1.add(new BigDecimal(Math.floor(scope.get(0).get(0))).toBigIntegerExact());
+ p2.add(new BigDecimal(Math.floor(scope.get(0).get(0))).toBigIntegerExact());
+ p3.add(new BigDecimal(Math.floor(scope.get(0).get(0))).toBigIntegerExact());
+ p4.add(new BigDecimal(Math.floor(scope.get(0).get(0))).toBigIntegerExact());
+ }
+
+ p1.add(new BigDecimal(Math.floor(scope.get(0).get(1))).toBigIntegerExact());
+ p2.add(new BigDecimal(Math.floor(scope.get(0).get(1))).toBigIntegerExact());
+ p3.add(new BigDecimal(Math.floor(scope.get(0).get(1))).toBigIntegerExact());
+ p4.add(new BigDecimal(Math.floor(scope.get(0).get(1))).toBigIntegerExact());
+
+ for (int i = 0; i < scope.size(); i++){
+ ArrayList point = scope.get(i);
+ BigInteger d1 = new BigDecimal(Math.floor(point.get(0))).toBigIntegerExact();
+ BigInteger d2 = new BigDecimal(Math.floor(point.get(1))).toBigIntegerExact();
+
+ if (d1.compareTo(new BigInteger("0"))<0){
+ p1.set(0,new BigInteger("0"));
+ p4.set(0,new BigInteger("0"));
+ }else{
+ if (d1.compareTo(p1.get(0))<0){
+ p1.set(0,d1);
+ p4.set(0,d1);
+ }
+ }
+
+
+ if (d1.compareTo(p2.get(0))>0){
+ p2.set(0,d1);
+ p3.set(0,d1);
+ }
+
+ if (d2.compareTo(p1.get(1))>0){
+ p1.set(1,d2);
+ p2.set(1,d2);
+ }
+ if (d2.compareTo(p3.get(1))<0){
+ p3.set(1,d2);
+ p4.set(1,d2);
+ }
+ }
+
+ double[] lowAray = {p4.get(0).doubleValue(),p4.get(1).doubleValue()};
+ this.low = new Point(lowAray);
+
+ double[] highAray = {p2.get(0).doubleValue(),p2.get(1).doubleValue()};
+ this.high = new Point(highAray);
+ }
+
+ public Rectangle(Point p1, Point p2)
+ {
+ if(p1 == null || p2 == null)
+ {
+ throw new IllegalArgumentException("Points cannot be null.");
+ }
+ if(p1.getDimension() != p2.getDimension())
+ {
+ throw new IllegalArgumentException("Points must be of same dimension.");
+ }
+ //先左下角后右上角
+ for(int i = 0; i < p1.getDimension(); i ++)
+ {
+ if(p1.getFloatCoordinate(i) > p2.getFloatCoordinate(i))
+ {
+// throw new IllegalArgumentException("坐标点为先左下角后右上角");
+ //交换p1和p2
+ Point tmp = (Point) p1.clone();
+ p1 = (Point) p2.clone();
+ p2 = tmp;
+ }
+ }
+ low = (Point) p1.clone();
+ high = (Point) p2.clone();
+ }
+
+ /**
+ * 返回Rectangle左下角的Point
+ * @return Point
+ */
+ public Point getLow()
+ {
+ return (Point) low.clone();
+ }
+
+ public Point getLowWithoutClone()
+ {
+ return low;
+ }
+
+ /**
+ * 返回Rectangle右上角的Point
+ * @return Point
+ */
+ public Point getHigh()
+ {
+ return high;
+ }
+
+ /**
+ * @param rectangle
+ * @return 包围两个Rectangle的最小Rectangle
+ */
+ public Rectangle getUnionRectangle(Rectangle rectangle)
+ {
+ if(rectangle == null)
+ throw new IllegalArgumentException("Rectangle cannot be null.");
+
+ if(rectangle.getDimension() != getDimension())
+ {
+ throw new IllegalArgumentException("Rectangle must be of same dimension.");
+ }
+
+ double[] min = new double[getDimension()];
+ double[] max = new double[getDimension()];
+
+ for(int i = 0; i < getDimension(); i ++)
+ {
+ min[i] = Math.min(low.getFloatCoordinate(i), rectangle.low.getFloatCoordinate(i));
+ max[i] = Math.max(high.getFloatCoordinate(i), rectangle.high.getFloatCoordinate(i));
+ }
+
+ return new Rectangle(new Point(min), new Point(max));
+ }
+
+ /**
+ * @return 返回Rectangle的面积
+ */
+ public double getArea()
+ {
+ double area = 1;
+ for(int i = 0; i < getDimension(); i ++)
+ {
+ area *= high.getFloatCoordinate(i) - low.getFloatCoordinate(i);
+ }
+
+ return area;
+ }
+
+ /**
+ * @param rectangles
+ * @return 包围一系列Rectangle的最小Rectangle
+ */
+ public static Rectangle getUnionRectangle(Rectangle[] rectangles)
+ {
+ if(rectangles == null || rectangles.length == 0)
+ throw new IllegalArgumentException("Rectangle array is empty.");
+
+ Rectangle r0 = (Rectangle) rectangles[0].clone();
+ for(int i = 1; i < rectangles.length; i ++)
+ {
+ r0 = r0.getUnionRectangle(rectangles[i]);
+ }
+
+ return r0;
+ }
+
+ @Override
+ protected Object clone()
+ {
+ Point p1 = (Point) low.clone();
+ Point p2 = (Point) high.clone();
+ return new Rectangle(p1, p2);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Rectangle Low:" + low + " High:" + high;
+ }
+
+ public static void main(String[] args)
+ {
+ double[] f1 = {1.3f,2.4f};
+ double[] f2 = {3.4f,4.5f};
+ Point p1 = new Point(f1);
+ Point p2 = new Point(f2);
+ Rectangle rectangle = new Rectangle(p1, p2);
+ System.out.println(rectangle);
+// Point point = rectangle.getHigh();
+// point = p1;
+// System.out.println(rectangle);
+
+ double[] f_1 = {0f,0f};
+ double[] f_2 = {-2f,2f};
+ double[] f_3 = {3f,3f};
+ double[] f_4 = {2.5f,2.5f};
+ double[] f_5 = {1.5f,1.5f};
+ p1 = new Point(f_1);
+ p2 = new Point(f_2);
+ Point p3 = new Point(f_3);
+ Point p4 = new Point(f_4);
+ Point p5 = new Point(f_5);
+ Rectangle re1 = new Rectangle(p1, p2);
+ Rectangle re2 = new Rectangle(p2, p3);
+ Rectangle re3 = new Rectangle(p4, p3);
+// Rectangle re4 = new Rectangle(p3, p4);
+ Rectangle re5 = new Rectangle(p5, p4);
+ System.out.println(re1.isIntersection(re2));
+ System.out.println(re1.isIntersection(re3));
+ System.out.println(re1.intersectingArea(re2));
+ System.out.println(re1.intersectingArea(re5));
+
+ /**
+ * 测试新的构造函数
+ */
+ List c = new ArrayList<>();
+ c.add(new BigInteger("2"));
+ c.add(new BigInteger("2"));
+ c.add(new BigInteger("2"));
+ c.add(new BigInteger("2"));
+
+
+ ArrayList a1 = new ArrayList<>();
+ a1.add(7.0);
+ a1.add(5.0);
+ a1.add(6.0);
+ a1.add(7.0);
+
+ ArrayList a2 = new ArrayList<>();
+ a2.add(-1.0);
+ a2.add(9.0);
+ a2.add(6.0);
+ a2.add(7.0);
+
+ ArrayList a3 = new ArrayList<>();
+ a3.add(1.0);
+ a3.add(1.0);
+ a3.add(6.0);
+ a3.add(7.0);
+
+ ArrayList a4 = new ArrayList<>();
+ a4.add(5.0);
+ a4.add(5.0);
+ a4.add(6.0);
+ a4.add(7.0);
+
+
+ List> list = new ArrayList<>();
+ list.add(a1);
+ list.add(a2);
+ list.add(a3);
+// list.add(a4);
+ Rectangle rect2 = new Rectangle(c,list);
+ System.out.println(rect2);
+ }
+
+ /**
+ * 两个Rectangle相交的面积
+ * @param rectangle Rectangle
+ * @return double
+ */
+ public double intersectingArea(Rectangle rectangle)
+ {
+ if(! isIntersection(rectangle))
+ {
+ return 0;
+ }
+
+ double ret = 1;
+ for(int i = 0; i < rectangle.getDimension(); i ++)
+ {
+ double l1 = this.low.getFloatCoordinate(i);
+ double h1 = this.high.getFloatCoordinate(i);
+ double l2 = rectangle.low.getFloatCoordinate(i);
+ double h2 = rectangle.high.getFloatCoordinate(i);
+
+ //rectangle1在rectangle2的左边
+ if(l1 <= l2 && h1 <= h2)
+ {
+ ret *= (h1 - l1) - (l2 - l1);
+ }else if(l1 >= l2 && h1 >= h2)
+ //rectangle1在rectangle2的右边
+ {
+ ret *= (h2 - l2) - (l1 - l2);
+ }else if(l1 >= l2 && h1 <= h2)
+ //rectangle1在rectangle2里面
+ {
+ ret *= h1 - l1;
+ }else if(l1 <= l2 && h1 >= h2)
+ //rectangle1包含rectangle2
+ {
+ ret *= h2 - l2;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * @param rectangle
+ * @return 判断两个Rectangle是否相交
+ */
+ public boolean isIntersection(Rectangle rectangle)
+ {
+ if(rectangle == null)
+ throw new IllegalArgumentException("Rectangle cannot be null.");
+
+ if(rectangle.getDimension() != getDimension())
+ {
+ throw new IllegalArgumentException("Rectangle cannot be null.");
+ }
+
+
+ for(int i = 0; i < getDimension(); i ++)
+ {
+ if(low.getFloatCoordinate(i) > rectangle.high.getFloatCoordinate(i) ||
+ high.getFloatCoordinate(i) < rectangle.low.getFloatCoordinate(i))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return 返回Rectangle的维度
+ */
+ private int getDimension()
+ {
+ return low.getDimension();
+ }
+
+ /**
+ * 判断rectangle是否被包围
+ * @param rectangle
+ * @return
+ */
+ public boolean enclosure(Rectangle rectangle)
+ {
+ if(rectangle == null)
+ throw new IllegalArgumentException("Rectangle cannot be null.");
+
+ if(rectangle.getDimension() != getDimension())
+ throw new IllegalArgumentException("Rectangle dimension is different from current dimension.");
+
+ for(int i = 0; i < getDimension(); i ++)
+ {
+ if(rectangle.low.getFloatCoordinate(i) < low.getFloatCoordinate(i) ||
+ rectangle.high.getFloatCoordinate(i) > high.getFloatCoordinate(i))
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if(obj instanceof Rectangle)
+ {
+ Rectangle rectangle = (Rectangle) obj;
+ if(low.equals(rectangle.getLow()) && high.equals(rectangle.getHigh()))
+ return true;
+ }
+ return false;
+ }
+
+
+}
\ No newline at end of file
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/scope/CellAndScope.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/scope/CellAndScope.java
new file mode 100644
index 00000000..81a9df69
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/scope/CellAndScope.java
@@ -0,0 +1,34 @@
+package com.secure.scope;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CellAndScope {
+ private List cell;
+ private List> Scope;
+
+ public CellAndScope() {
+ }
+
+ public CellAndScope(List cell, List> scope) {
+ this.cell = cell;
+ Scope = scope;
+ }
+
+ public List getCell() {
+ return cell;
+ }
+
+ public void setCell(List cell) {
+ this.cell = cell;
+ }
+
+ public List> getScope() {
+ return Scope;
+ }
+
+ public void setScope(List> scope) {
+ Scope = scope;
+ }
+}
diff --git a/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/scope/ScopeRectangle.java b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/scope/ScopeRectangle.java
new file mode 100644
index 00000000..1a55c72b
--- /dev/null
+++ b/Database_SemiTest/R-tree-demol2-Verifiable/src/com/secure/scope/ScopeRectangle.java
@@ -0,0 +1,178 @@
+package com.secure.scope;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ScopeRectangle {
+ private List cell;
+ private List> scope;
+
+
+ public Map>,List> genernateRectangle(Map,List>> scopeWithCell){
+
+ Map>,List> rectMaP
+ = new HashMap<>();
+
+ for (Map.Entry entry:scopeWithCell.entrySet()) {
+
+ List> rect = new ArrayList>();
+
+ List> pointList = (List>) entry.getValue();
+ List key = (List) entry.getKey();
+
+ //矩形四个点
+ ArrayList p1 = new ArrayList<>();
+ ArrayList p2 = new ArrayList<>();
+ ArrayList