Exemplo n.º 1
0
        ///*
        // * R*加入距离最近点后的R1范围
        // */
        //static public void getRangeOfROne(double[] longitudeArr1, double[] latitudeArr1,
        //    ref double rOneAfterRejustLongitudeFirst, ref double rOneAfterRejustLatitudeFirst, ref double rOneAfterRejustLongitudeSecond, ref double rOneAfterRejustLatitudeSecond,
        //    ref double rOneLongitudeFirst, ref double rOneLatitudeFirst, ref double rOneLongitudeSecond, ref double rOneLatitudeSecond)
        //{
        //    //R*调整后的R1的范围
        //    rOneAfterRejustLongitudeFirst = UsefulFunction.minInArr(longitudeArr1);
        //    rOneAfterRejustLatitudeFirst = UsefulFunction.minInArr(latitudeArr1);
        //    rOneAfterRejustLongitudeSecond = UsefulFunction.maxInArr(longitudeArr1);
        //    rOneAfterRejustLatitudeSecond = UsefulFunction.maxInArr(latitudeArr1);

        //    if ((rOneLongitudeFirst == rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst == rOneAfterRejustLatitudeFirst)
        //        && (rOneLongitudeSecond == rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond == rOneAfterRejustLatitudeSecond))
        //    {
        //        //划分出R2后R1的范围没有变化
        //        rOneLongitudeFirst = rOneAfterRejustLongitudeFirst;
        //        rOneLatitudeFirst = rOneAfterRejustLatitudeFirst;
        //        rOneLongitudeSecond = rOneAfterRejustLongitudeSecond;
        //        rOneLatitudeSecond = rOneAfterRejustLatitudeSecond;
        //    }
        //    else
        //    {
        //        //Console.WriteLine("R1改变");first和second是原来R1的范围,first1和second1是划分出R2后R1的范围
        //        //我们假设first(1)比second(1)的经纬度都小,并且first(second)的范围肯定包含first1(second1)
        //        //一共会有7种情况
        //        //当(first.x<first1.x)&&(first.y<first1.y)&&(second.x>second1.x)&&(second.y>second1.y)
        //        if ((rOneLongitudeFirst < rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst < rOneAfterRejustLatitudeFirst)
        //            && (rOneLongitudeSecond > rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond > rOneAfterRejustLatitudeSecond))
        //        {
        //            rOneLongitudeFirst = rOneAfterRejustLongitudeFirst;
        //            rOneLatitudeFirst = rOneAfterRejustLatitudeFirst;
        //            rOneLongitudeSecond = rOneAfterRejustLongitudeSecond;
        //            rOneLatitudeSecond = rOneAfterRejustLatitudeSecond;
        //        }
        //        //当(first.x<first1.x)&&(first.y==first1.y)&&(second.x==second1.x)&&(second.y==second1.y)
        //        else if ((rOneLongitudeFirst < rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst == rOneAfterRejustLatitudeFirst)
        //            && (rOneLongitudeSecond == rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond == rOneAfterRejustLatitudeSecond))
        //        {
        //            rOneLongitudeFirst = rOneAfterRejustLongitudeFirst;
        //            //另外三个数据均不会发生改变
        //        }
        //        //当(first.x<first1.x)&&(first.y<first1.y)&&(second.x==second1.x)&&(second.y==second1.y)
        //        else if ((rOneLongitudeFirst < rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst < rOneAfterRejustLatitudeFirst)
        //            && (rOneLongitudeSecond == rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond == rOneAfterRejustLatitudeSecond))
        //        {
        //            rOneLongitudeFirst = rOneAfterRejustLongitudeFirst;
        //            rOneLatitudeFirst = rOneAfterRejustLatitudeFirst;
        //            //另外两个数据均不会发生改变
        //        }
        //        //当(first.x==first1.x)&&(first.y<first1.y)&&(second.x==second1.x)&&(second.y==second1.y)
        //        else if ((rOneLongitudeFirst == rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst < rOneAfterRejustLatitudeFirst)
        //            && (rOneLongitudeSecond == rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond == rOneAfterRejustLatitudeSecond))
        //        {
        //            rOneLatitudeFirst = rOneAfterRejustLatitudeFirst;
        //            //另外三个数据均不会发生改变
        //        }
        //        //当(first.x==first1.x)&&(first.y==first1.y)&&(second.x>second1.x)&&(second.y==second1.y)
        //        else if ((rOneLongitudeFirst == rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst == rOneAfterRejustLatitudeFirst)
        //            && (rOneLongitudeSecond > rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond == rOneAfterRejustLatitudeSecond))
        //        {
        //            rOneLongitudeSecond = rOneAfterRejustLongitudeSecond;
        //            //另外三个数据均不会发生改变
        //        }
        //        //当(first.x==first1.x)&&(first.y==first1.y)&&(second.x>second1.x)&&(second.y>second1.y)
        //        else if ((rOneLongitudeFirst == rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst == rOneAfterRejustLatitudeFirst)
        //            && (rOneLongitudeSecond > rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond > rOneAfterRejustLatitudeSecond))
        //        {
        //            rOneLongitudeSecond = rOneAfterRejustLongitudeSecond;
        //            rOneLatitudeSecond = rOneAfterRejustLatitudeSecond;
        //            //另外两个数据均不会发生改变
        //        }
        //        //当(first.x==first1.x)&&(first.y==first1.y)&&(second.x==second1.x)&&(second.y>second1.y)
        //        else if ((rOneLongitudeFirst == rOneAfterRejustLongitudeFirst) && (rOneLatitudeFirst == rOneAfterRejustLatitudeFirst)
        //            && (rOneLongitudeSecond == rOneAfterRejustLongitudeSecond) && (rOneLatitudeSecond > rOneAfterRejustLatitudeSecond))
        //        {
        //            rOneLatitudeSecond = rOneAfterRejustLatitudeSecond;
        //            //另外三个数据均不会发生改变
        //        }
        //        else
        //        {
        //            Console.Write("出现异常");
        //        }
        //    }
        //}

        /*
         * R*加入距离最近点后的R1范围
         * (R1的范围可能会有8种情况,不管哪一种都不用分别讨论,因为最后其范围都是由其中包含的点所决定)
         */
        static public void getRangeOfROne(double[] longitudeArr1, double[] latitudeArr1,
                                          ref double rOneAfterRejustLongitudeFirst, ref double rOneAfterRejustLatitudeFirst, ref double rOneAfterRejustLongitudeSecond, ref double rOneAfterRejustLatitudeSecond,
                                          ref double rOneLongitudeFirst, ref double rOneLatitudeFirst, ref double rOneLongitudeSecond, ref double rOneLatitudeSecond)
        {
            //R*调整后的R1的范围
            rOneAfterRejustLongitudeFirst  = UsefulFunction.minInArr(longitudeArr1);
            rOneAfterRejustLatitudeFirst   = UsefulFunction.minInArr(latitudeArr1);
            rOneAfterRejustLongitudeSecond = UsefulFunction.maxInArr(longitudeArr1);
            rOneAfterRejustLatitudeSecond  = UsefulFunction.maxInArr(latitudeArr1);

            rOneLongitudeFirst  = rOneAfterRejustLongitudeFirst;
            rOneLatitudeFirst   = rOneAfterRejustLatitudeFirst;
            rOneLongitudeSecond = rOneAfterRejustLongitudeSecond;
            rOneLatitudeSecond  = rOneAfterRejustLatitudeSecond;
        }
Exemplo n.º 2
0
        /*
         * 求在R*外上下两处范围内的点的集合
         * listLongitudeArrClose3(经度):R*外上侧点的集合
         * listLongitudeArrClose4(经度):R*外上侧点的集合
         */
        static public void getLongitudeNewList(double[] latitudeArrClose1, double[] latitudeArrClose2, double[] longitudeArr, double[] latitudeArr,
                                               ref ArrayList listLongitudeArrClose3, ref ArrayList listLongitudeArrClose4)
        {
            //因为latitudeArrClose1、2里存的是纬度,必须要先找到其经度,再使用Except
            for (int i = 0; i < latitudeArrClose1.Length; i++)
            {
                int indexTemp = UsefulFunction.search(latitudeArr, latitudeArr.Length, latitudeArrClose1[i]);
                listLongitudeArrClose3.Add(longitudeArr[indexTemp]);
            }

            for (int i = 0; i < latitudeArrClose2.Length; i++)
            {
                int indexTemp = UsefulFunction.search(latitudeArr, latitudeArr.Length, latitudeArrClose2[i]);
                listLongitudeArrClose4.Add(longitudeArr[indexTemp]);
            }
        }
Exemplo n.º 3
0
        /*
         * 注意:选择两点时有个特别重要的问题:就是如果选择的两点就是R1的边界,那么就说明该数据集不能再划分桶了,划分桶失败
         */
        static public int getTwoPoint(double[] longitudeArr, double[] latitudeArr, ref int first, ref int second, ref double minCostNewSum,
                                      ref int involveInRStar, ref double semiPerimeterOne, ref double semiPerimeterTwo)
        {
            //设置备份的经纬度数组
            double[] longitudeArrCopy = new double[longitudeArr.Length];
            longitudeArr.CopyTo(longitudeArrCopy, 0);
            double[] latitudeArrCopy = new double[latitudeArr.Length];
            latitudeArr.CopyTo(latitudeArrCopy, 0);
            //ArrayList list = new ArrayList(longitudeArr);
            //list.Sort();
            //longitudeArr = (double[])list.ToArray(typeof(double));
            //for (int i = 0; i < 34; i++)
            //{
            //    Console.WriteLine(longitudeArr[i]+","+longitudeArrCopy[i]);
            //}
            //Console.WriteLine(longitudeArr[0]);
            //求经度数组longitudeArr中的最大最小值之差
            double x = UsefulFunction.difference(longitudeArr);
            //求纬度数组latitudeArr中的最大最小值之差
            double y = UsefulFunction.difference(latitudeArr);

            //求出R1的半周长
            semiPerimeterOne = x + y;

            //当前R*的半周长
            semiPerimeterTwo = 0;

            //Console.WriteLine(semiPerimeterOne);
            //R1包含的数据集点数
            int countROne = longitudeArr.Length;
            //R1的开销
            double costROne = (double)countROne * semiPerimeterOne;
            //Console.WriteLine(costROne);

            //在分桶R2之前,我们需要计算在数据集中选择一对点对的数目
            //需要用到排列组合
            //其实排列实现了,组合也就实现了,组合C(N,R)=P(N,R)/P(R,R)
            //实现方法P(*,*)为static int permAndComb(int N, int R)
            int countChoose = UsefulFunction.permAndComb(countROne, 2) / UsefulFunction.permAndComb(2, 2);

            //Console.WriteLine(countChoose);

            //对于矩形R2

            //此次分桶成本的数组(因为有很多构成R*的点对,因此产生不同的成本,需存入一个数组)
            double[] costNewSum = new double[countChoose];
            //作为costNewSum数组的下标
            int k = 0;

            //存放构成R*点对的数组
            int[] arrfir = new int[countChoose];
            int[] arrsec = new int[countChoose];

            //选择一对构成R2最小成本的点
            for (int i = 0; i < longitudeArr.Length; i++)
            {
                for (int j = i + 1; j < latitudeArr.Length; j++)
                {
                    //从34个点中任选两个点试图作为构成R2对角线的两个端点(共561种情况)
                    Point pR21 = new Point(longitudeArr[i], latitudeArr[i]);
                    //Console.Write(i);
                    Point pR22 = new Point(longitudeArr[j], latitudeArr[j]);
                    //Console.WriteLine(j);
                    //Console.Write("(" + pR21.showx(pR21) + "," + pR21.showy(pR21) +
                    //    ") (" + pR22.showx(pR22) + "," + pR22.showy(pR22) + ")\t");

                    //计算当前R*的半周长
                    semiPerimeterTwo = pR21.SemiPeri(pR22);
                    //Console.Write(semiPerimeter2 + "\t");

                    //计算这两点构成的R*所包围的点数

                    //介于构成R*两点经度之间的点数countBetweenLongi
                    int countBetweenLongi = 0;
                    //介于构成R*两点之间的点数
                    int countBeRStar = 0;
                    //判断数值有无改变
                    int change = 0;
                    //保存下满足经度范围在经度数组的下标
                    int[] saveIndiceLongi = new int[longitudeArr.Length];
                    for (int i2 = 0; i2 < longitudeArr.Length; i2++)
                    {
                        if (((longitudeArrCopy[i2] > longitudeArr[i]) && (longitudeArrCopy[i2] < longitudeArr[j])) || ((longitudeArrCopy[i2] < longitudeArr[i]) && (longitudeArrCopy[i2] > longitudeArr[j])))
                        {
                            countBetweenLongi++;
                            //判断countBetweenLongi的值是否改变,如果改变了说明出现了介于经度范围之间的点
                            if ((countBetweenLongi - change) > 0)
                            {
                                change = countBetweenLongi;
                                //记录下满足经度范围的数组下标i2
                                saveIndiceLongi[countBetweenLongi] = i2;
                                //计算在满足经度范围内的点中,同时也满足维度范围的点数,这里需要注意经纬度的值并非单调递增递减,所以会有||
                                if (((latitudeArrCopy[saveIndiceLongi[countBetweenLongi]] > latitudeArr[i]) && (latitudeArrCopy[saveIndiceLongi[countBetweenLongi]] < latitudeArr[j])) ||
                                    ((latitudeArrCopy[saveIndiceLongi[countBetweenLongi]] < latitudeArr[i]) && (latitudeArrCopy[saveIndiceLongi[countBetweenLongi]] > latitudeArr[j])))
                                {
                                    countBeRStar++;
                                }
                            }
                        }
                    }
                    //Console.Write(countBeRStar);
                    //构成R*的点数(根据我国省会城市分布特性,构成矩形上不会存在边界上的点,所以直接+2)
                    int countRStar = countBeRStar + 2;
                    //Console.Write(countRStar + "\t");

                    //计算当前R*的成本
                    double costRStar = countRStar * semiPerimeterTwo;
                    //Console.Write(costRStar+",");

                    //计算不包含R*中点时的矩形成本
                    double costDepartRStar = (double)(countROne - countRStar) * semiPerimeterOne;

                    //将每对点产生的成本存入数组
                    costNewSum[k] = costRStar + costDepartRStar;
                    //构成新桶的两点
                    arrfir[k] = i;
                    arrsec[k] = j;
                    k++;//k循环完后的值将==countChoose,也就是561
                }//内层for
            }//外层for
            //计算此次分桶的最小成本及最小成本桶对应的两个点
            ArrayList listCostNewSum = new ArrayList(costNewSum);

            listCostNewSum.Sort();
            //minCostNewSum是分桶R*的最小成本
            minCostNewSum = Convert.ToDouble(listCostNewSum[0]);
            //Console.WriteLine(minCostNewSum);
            for (int i = 0; i < k; i++)
            {
                if (costNewSum[i] == minCostNewSum)
                {
                    first  = arrfir[i];
                    second = arrsec[i];
                    break;
                }
            }
            //构成最小成本分桶R*是两个点first和second
            //此时R*的半周长为这两个点构成矩形的半周长
            Point pFirst  = new Point(longitudeArr[first], latitudeArr[first]);
            Point pSecond = new Point(longitudeArr[second], latitudeArr[second]);

            semiPerimeterTwo = pFirst.SemiPeri(pSecond);
            //Console.WriteLine(semiPerimeter2);

            //计算R*中包含的点数
            //involveInRStar = (int)(Math.Round((longitudeArr.Length * semiPerimeterOne - minCostNewSum) / (semiPerimeterOne - semiPerimeterTwo)));
            //根据公式计算有点问题,因为double精度上有问题,我们根据first和second来计算R*中包含的点数,这样也可以把边界的点算进去
            //构成R*的两点
            //在存储更新经纬度过程中,更新后经纬度数组的下标
            for (int p = 0; p < longitudeArr.Length; p++)
            {
                //先判断两点经度的大小
                if (pFirst.longitudeOneSmaller(pSecond))
                {
                    //如果第一个点的经度值小,在比较两点的维度大小
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //此时就是第一个点的经度和维度都小于第二个点,即(first.x<second.x)&&(first.y<seconde.y)
                        //找出在这个R*范围外的点,分别在左右侧的经度和上下的维度外
                        if ((longitudeArr[p] >= longitudeArr[first]) && (longitudeArr[p] <= longitudeArr[second]) &&
                            (latitudeArr[p] >= latitudeArr[first]) && (latitudeArr[p] <= latitudeArr[second]))
                        {
                            //若在R*范围外,就存入更新的经纬度数组
                            involveInRStar++;
                        }
                    }
                    else
                    {
                        //即(first.x<second.x)&&(first.y>seconde.y)
                        if ((longitudeArr[p] >= longitudeArr[first]) && (longitudeArr[p] <= longitudeArr[second]) &&
                            (latitudeArr[p] <= latitudeArr[first]) && (latitudeArr[p] >= latitudeArr[second]))
                        {
                            //若在R*范围外,就存入更新的经纬度数组
                            involveInRStar++;
                        }
                    }
                }
                else
                {
                    //first.x>seconde.x
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //即(first.x>second.x)&&(first.y<seconde.y)
                        //找出在这个R*范围外的点,分别在左右侧的经度和上下的维度外
                        if ((longitudeArr[p] <= longitudeArr[first]) && (longitudeArr[p] >= longitudeArr[second]) &&
                            (latitudeArr[p] >= latitudeArr[first]) && (latitudeArr[p] <= latitudeArr[second]))
                        {
                            //若在R*范围外,就存入更新的经纬度数组
                            involveInRStar++;
                        }
                    }
                    else
                    {
                        //即(first.x>second.x)&&(first.y>seconde.y)
                        if ((longitudeArr[p] <= longitudeArr[first]) && (longitudeArr[p] >= longitudeArr[second]) &&
                            (latitudeArr[p] <= latitudeArr[first]) && (latitudeArr[p] >= latitudeArr[second]))
                        {
                            //若在R*范围外,就存入更新的经纬度数组
                            involveInRStar++;
                        }
                    }
                }
            }//更新经纬度的for循环

            //Console.WriteLine(involveInRStar);
            return(0);
        }
Exemplo n.º 4
0
        static public void getNewDataSet(double[] longitudeArr, double[] latitudeArr, ref ArrayList listLongitudeArr, ref ArrayList listLatitudeArr,
                                         ref double rOneLongitudeFirst, ref double rOneLatitudeFirst, ref double rOneLongitudeSecond, ref double rOneLatitudeSecond,
                                         ref double rTwoLongitudeFirst, ref double rTwoLatitudeFirst, ref double rTwoLongitudeSecond, ref double rTwoLatitudeSecond,
                                         ref ArrayList listCost, ref ArrayList listCostFinal)
        {
            /*
             * ======================================================================================================================================================
             */
            //存放最小成本R*的点对在数组longitudeArr和latitudeArr中的下标
            int first  = 0;
            int second = 0;

            double minCostNewSum = 0;          //minCostNewSum是分桶R*的最小成本

            int involveInRStar = 0;            //计算R*中包含的点数

            double semiPerimeterOne = 0;       //R1的半周长

            double semiPerimeterTwo = 0;       //当前R*的半周长

            ChooseTwoPoint.getTwoPoint(longitudeArr, latitudeArr, ref first, ref second, ref minCostNewSum, ref involveInRStar, ref semiPerimeterOne, ref semiPerimeterTwo);
            //Console.WriteLine(first + "," + second);

            //此时R*的半周长为这两个点构成矩形的半周长
            Point pFirst  = new Point(longitudeArr[first], latitudeArr[first]);
            Point pSecond = new Point(longitudeArr[second], latitudeArr[second]);

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            /*
             * 现在对R*进行调整为R2
             * 首先计算离R*最近的在R*外的点(判断将其加入R*后成本是否会比不加入的小)
             * 注意目前R1中的点(也就是在R*之外的点,有变化)所以longitudeArr和latitudeArr会改变
             */

            //更新后的经纬度数组(R*外的点构成的数组)
            double[] longitudeArr1 = new double[longitudeArr.Length - involveInRStar];
            double[] latitudeArr1  = new double[latitudeArr.Length - involveInRStar];

            PointInROne.getNewArray(longitudeArr, latitudeArr, first, second, ref longitudeArr1, ref latitudeArr1);
            //for (int i = 0; i < (longitudeArr.Length - involveInRStar); i++)
            //{
            //    Console.WriteLine(longitudeArr1[i]);
            //}

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            /*
             * 此时R1的范围可能会因为R*的形成有所变化,但是在R*初次形成时并不是使用R1变化后的范围参与成本计算(这个在调整R*才用到)
             * R*初次形成参与成本运算的是R1受影响变化之前的范围
             * 所以我们先用四个临时变量暂存R1的范围,之后将用于如果调整失败(最近点不能加入R*时)求解当时R1的范围
             */
            //R*形成后的R1的范围(暂存),目前是去除R*中点后剩余数据集中的点构成的矩形
            double rOneTempLongitudeFirst  = UsefulFunction.minInArr(longitudeArr1);
            double rOneTempLatitudeFirst   = UsefulFunction.minInArr(latitudeArr1);
            double rOneTempLongitudeSecond = UsefulFunction.maxInArr(longitudeArr1);
            double rOneTempLatitudeSecond  = UsefulFunction.maxInArr(latitudeArr1);

            //初始R1的范围
            rOneLongitudeFirst  = UsefulFunction.minInArr(longitudeArr);
            rOneLatitudeFirst   = UsefulFunction.minInArr(latitudeArr);
            rOneLongitudeSecond = UsefulFunction.maxInArr(longitudeArr);
            rOneLatitudeSecond  = UsefulFunction.maxInArr(latitudeArr);

            //Console.WriteLine("(" + rOneLongitudeFirst + "," + rOnelatitudeFirst + ")" + " (" + rOneLongitudeSecond + "," + rOneLatitudeSecond + ")");

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //找出在R*外离R*最近的点

            //存放R*上下左右四侧的四个数组,因为R*是个矩形有四条边,找出每边距离最近的点前先找出每边外的所有点
            //需要注意在first.x,first.y,second.x,second.x,second.y范围外,还有四个顶角范围的点
            //所以要进行分别讨论

            //先计算离四边最近的点
            int r = longitudeArr.Length - involveInRStar;//存放R*外R1内的点数
            //因为存放最近距离的个数不确定,所以不能在使用数组,改用ArrayList,之后转化为数组即可
            ArrayList listLongitudeArrClose1 = new ArrayList();
            ArrayList listLongitudeArrClose2 = new ArrayList();
            ArrayList listLatitudeArrClose1  = new ArrayList();
            ArrayList listLatitudeArrClose2  = new ArrayList();

            CloseToRStarEdge.getNewList(longitudeArr, latitudeArr, first, second, involveInRStar, longitudeArr1, latitudeArr1, ref listLongitudeArrClose1, ref listLongitudeArrClose2, ref listLatitudeArrClose1, ref listLatitudeArrClose2);
            //Console.WriteLine();
            //for (int i = 0; i < listLongitudeArrClose2.Count; i++)
            //{
            //    Console.WriteLine(listLongitudeArrClose2[i]);
            //}
            //把集合转化为double型数组
            double[] longitudeArrClose1 = (double[])listLongitudeArrClose1.ToArray(typeof(double));
            double[] longitudeArrClose2 = (double[])listLongitudeArrClose2.ToArray(typeof(double));
            double[] latitudeArrClose1  = (double[])listLatitudeArrClose1.ToArray(typeof(double));
            double[] latitudeArrClose2  = (double[])listLatitudeArrClose2.ToArray(typeof(double));

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //R*外四边距离R*的最近值
            double diffLeft   = 0;          //R*外左侧最近的距离值
            double diffRight  = 0;
            double diffTop    = 0;
            double diffBottom = 0;

            //距离R*四边最近的点的下标,通过longitudeArr1和latitudeArr1数组访问
            int indexRStarLeft   = 0;
            int indexRStarRight  = 0;
            int indexRStarTop    = 0;
            int indexRStarBottom = 0;

            CloseToRStarEdge.getClosest(longitudeArr, latitudeArr, longitudeArr1, latitudeArr1, first, second, r,
                                        listLongitudeArrClose1, listLongitudeArrClose2, listLatitudeArrClose1, listLatitudeArrClose2,
                                        ref diffLeft, ref diffRight, ref diffTop, ref diffBottom, ref indexRStarLeft, ref indexRStarRight, ref indexRStarTop, ref indexRStarBottom);

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            /*算完R*四边外的点到各边的距离后,接下来计算R*四个顶角到R*的距离
             * 但是这个距离并不是单纯的math.sqrt((this.x-x)*(this.x-x)+(this.y-y)*(this.y-y))
             * 仔细观察我们可以发现在包含点数确定的情况下,成本和矩形半周长成正比
             * 因此,对于顶角的点,调整时包含进去的话R*的长宽都会改变,而不是前面的那四种只会改变长和宽之一
             * 所以R*顶角范围的点到R*的距离为=到经度+到纬度
             */
            //找出R*各个顶角范围的点
            ArrayList listLongitudeArrClose3 = new ArrayList();
            ArrayList listLongitudeArrClose4 = new ArrayList();

            CloseToRStarEdge.getLongitudeNewList(latitudeArrClose1, latitudeArrClose2, longitudeArr, latitudeArr, ref listLongitudeArrClose3, ref listLongitudeArrClose4);

            //存放R*外边上下范围外点的经度
            double[] longitudeArrClose3 = (double[])listLongitudeArrClose3.ToArray(typeof(double));
            double[] longitudeArrClose4 = (double[])listLongitudeArrClose4.ToArray(typeof(double));

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //double[] longitudeArrClose5存放R*四个顶角范围的点的经度
            double[] longitudeArrClose5 = longitudeArr1.Except(longitudeArrClose1).Except(longitudeArrClose2).Except(longitudeArrClose3).Except(longitudeArrClose4).ToArray();
            //for (int i = 0; i < longitudeArr1.Length; i++)
            //{
            //    Console.WriteLine(longitudeArr1.Length);
            //    Console.Write(longitudeArr1[i] + " ");
            //}
            //double[] longitudeArrClose5 = new double[longitudeArr1.Length - longitudeArrClose1.Length - longitudeArrClose2.Length - longitudeArrClose3.Length - longitudeArrClose4.Length];
            //ArrayList listLongitudeClose5 = new ArrayList();
            //for (int i = 0; i < longitudeArr1.Length; i++)
            //{
            //    Console.WriteLine(longitudeArr1.Length);
            //    Console.WriteLine(longitudeArr1[i]);
            //}
            //    for (int i = 0; i < longitudeArrClose1.Length; i++)
            //    {
            //        if (longitudeArr1[i] != longitudeArrClose1[i])
            //        {
            //            listLongitudeClose5.Add(longitudeArrClose1[i]);
            //        }
            //    }
            //for (int i = 0; i < longitudeArrClose2.Length; i++)
            //{
            //    if (longitudeArr1[i] != longitudeArrClose2[i])
            //    {
            //        listLongitudeClose5.Add(longitudeArrClose2[i]);
            //    }
            //}
            //for (int i = 0; i < longitudeArrClose3.Length; i++)
            //{
            //    if (longitudeArr1[i] != longitudeArrClose3[i])
            //    {
            //        listLongitudeClose5.Add(longitudeArrClose3[i]);
            //    }
            //}
            //for (int i = 0; i < longitudeArrClose4.Length; i++)
            //{
            //    if (longitudeArr1[i] != longitudeArrClose4[i])
            //    {
            //        listLongitudeClose5.Add(longitudeArrClose4[i]);
            //    }
            //}
            //Console.WriteLine(longitudeArrClose5.Length);
            //Console.WriteLine(listLongitudeClose5.Count);


            //再根据double[] longitudeArrClose5找到存放R*四个顶角范围的点的纬度double[] latitudeArrClose5
            double[] latitudeArrClose5 = new double[longitudeArrClose5.Length];
            for (int i = 0; i < longitudeArrClose5.Length; i++)
            {
                int indexTemp = UsefulFunction.search(longitudeArr, longitudeArr.Length, longitudeArrClose5[i]);
                //if (indexTemp != -1)
                //{
                latitudeArrClose5[i] = latitudeArr[indexTemp];
                //}
            }
            //for (int i = 0; i < latitudeArrClose5.Length; i++)
            //{
            //    Console.WriteLine(latitudeArrClose5[i]);
            //}

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //各顶角的距离R*的最短距离以及确定最短距离的顶角点的获取

            //存储R*外各个顶角范围的点到R*距离的集合
            ArrayList listDiffTopLeft     = new ArrayList();
            ArrayList listDiffTopRight    = new ArrayList();
            ArrayList listDiffBottomLeft  = new ArrayList();
            ArrayList listDiffBottomRight = new ArrayList();

            //R*外右上角最近点的下标,通过longitudeArrClose5和latitudeArrClose5两数组来访问
            int indexRStarTopLeft = 0;

            int[] indexRStarTopLeftArr = new int[longitudeArrClose5.Length];
            int   indexRStarTopRight   = 0;

            int[] indexRStarTopRightArr = new int[longitudeArrClose5.Length];
            int   indexRStarBottomLeft  = 0;

            int[] indexRStarBottomLeftArr = new int[longitudeArrClose5.Length];
            int   indexRStarBottomRight   = 0;

            int[] indexRStarBottomRightArr = new int[longitudeArrClose5.Length];

            CloseToRStarCorner.getDiffNewList(longitudeArr, latitudeArr, first, second, longitudeArrClose5, latitudeArrClose5,
                                              ref indexRStarTopLeftArr, ref indexRStarTopRightArr, ref indexRStarBottomLeftArr, ref indexRStarBottomRightArr,
                                              ref listDiffTopLeft, ref listDiffTopRight, ref listDiffBottomLeft, ref listDiffBottomRight);

            //for (int i = 0; i < listDiffBottomLeft.Count; i++)
            //{
            //    Console.WriteLine(listDiffBottomLeft[i]);
            //}
            double diffTopLeft     = 0;        //R*外左上角点到R*的最小距离
            double diffTopRight    = 0;        //R*外右上角点到R*的最小距离
            double diffBottomLeft  = 0;        //R*外左下角点到R*的最小距离
            double diffBottomRight = 0;        //R*外右下角点到R*的最小距离

            CloseToRStarCorner.getClosest(listDiffTopLeft, listDiffTopRight, listDiffBottomLeft, listDiffBottomRight,
                                          indexRStarTopLeftArr, indexRStarTopRightArr, indexRStarBottomLeftArr, indexRStarBottomRightArr,
                                          ref diffTopLeft, ref diffTopRight, ref diffBottomLeft, ref diffBottomRight,
                                          ref indexRStarTopLeft, ref indexRStarTopRight, ref indexRStarBottomLeft, ref indexRStarBottomRight);

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //现在开始计算成本
            //我们矩形的8个(R*的上、下、左、右、左上、右上、左下、右下)距离中选择出距离最小的来计算成本
            //double[] shortestDistance存放这8个距离的数组
            double[] shortestDistanceArr = new double[8];
            CloseToRStar.closestDiff(diffLeft, diffRight, diffTop, diffBottom, diffTopLeft, diffTopRight, diffBottomLeft, diffBottomRight, ref shortestDistanceArr);
            //for (int i = 0; i < shortestDistanceArr.Length; i++)
            //{
            //    Console.WriteLine(shortestDistanceArr[i]);
            //}
            double shortestDistance = UsefulFunction.minInArr(shortestDistanceArr);//R*外的点到R*的最小距离
            //Console.WriteLine(shortestDistance);

            /*
             * 在计算不包含调整后R*的R1的成本之前,我们需要先判断并计算R1随着R*的调整,其范围有无改变
             * 计算并找到这个最短距离对应的点
             * 找到调整加入的这个点位于R*外8个位置中的哪个位置
             */
            //int indexOfShortestDistanceArr = search(shortestDistanceArr, shortestDistanceArr.Length, shortestDistance);

            //找到经过调整而加入R*的点pJoinInRStar
            Point pJoinInRStar = new Point();

            pJoinInRStar = CloseToRStar.getClosestPoint(shortestDistance, diffLeft, diffRight, diffTop, diffBottom,
                                                        diffTopLeft, diffTopRight, diffBottomLeft, diffBottomRight,
                                                        indexRStarLeft, indexRStarRight, indexRStarTop, indexRStarBottom,
                                                        indexRStarTopLeft, indexRStarTopRight, indexRStarBottomLeft, indexRStarBottomRight,
                                                        longitudeArr1, latitudeArr1, longitudeArrClose5, latitudeArrClose5);

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //找到调整加入到R*中的点后,我们需要计算经过R*调整后,R1的范围有无改变
            //我们先确定调整后的R*的范围


            int rTwoIndexLongitudeFirst  = 0; //存放R*调整后,拥有最小成本R2划分的第一个点的经度下标
            int rTwoIndexLatitudeFirst   = 0; //存放R*调整后,拥有最小成本R2划分的第一个点的纬度下标
            int rTwoIndexLongitudeSecond = 0; //存放R*调整后,拥有最小成本R2划分的第二个点的经度下标
            int rTwoIndexLatitudeSecond  = 0; //存放R*调整后,拥有最小成本R2划分的第二个点的纬度下标

            //double rTwoLongitudeFirst = 0;//存放R*调整后,拥有最小成本R2划分的第一个点的经度
            //double rTwoLatitudeFirst = 0;//存放R*调整后,拥有最小成本R2划分的第一个点的纬度
            //double rTwoLongitudeSecond = 0;//存放R*调整后,拥有最小成本R2划分的第二个点的经度
            //double rTwoLatitudeSecond = 0;//存放R*调整后,拥有最小成本R2划分的第二个点的纬度

            RangeOfR.getRangeOfRStar(shortestDistance, diffLeft, diffRight, diffTop, diffBottom, diffTopLeft, diffTopRight, diffBottomLeft, diffBottomRight, first,
                                     second, indexRStarLeft, indexRStarRight, indexRStarTop, indexRStarBottom, indexRStarTopLeft, indexRStarTopRight, indexRStarBottomLeft, indexRStarBottomRight,
                                     ref rTwoIndexLongitudeFirst, ref rTwoIndexLatitudeFirst, ref rTwoIndexLongitudeSecond, ref rTwoIndexLatitudeSecond, ref rTwoLongitudeFirst,
                                     ref rTwoLatitudeFirst, ref rTwoLongitudeSecond, ref rTwoLatitudeSecond, longitudeArr, latitudeArr, longitudeArr1, latitudeArr1, longitudeArrClose5, latitudeArrClose5);

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //实际上R*经过第一次调整后R*1,还需要判断R1的边界有无发生改变,
            //然后再找离R*1最近的点,计算将其包含进去和不包含进去时的成本,直到包含进去成本变大就停止计算,从而确定下来最终的R2

            //再对R*1(经过第一次调整的R*)进行第二次调整,步骤同上

            /*
             * 以上不再实现
             *
             */


            //我们先计算R1边界有无变化


            /*
             * 这里是计算哪个点加入了R*的算法,但是之前计算过,加入的点为pJoinInRStar,因此它可以直接使用这个点,不必在用下面的算法计算
             */


            ////找出R*第一次调整后R1中的点
            //double receive = findOut(longitudeArr1, latitudeArr1, rTwoLongitudeFirst, rTwoLatitudeFirst, rTwoLongitudeSecond, rTwoLatitudeSecond);
            ////Console.WriteLine(receive);
            ////但是我们并不知道该点是来自longitudeArr1还是来自latitudeArr1
            //int index=0;
            //for (int i = 0; i < longitudeArr1.Length; i++)
            //{
            //    if (receive == longitudeArr1[i])
            //        index = search(longitudeArr1, longitudeArr1.Length, receive);
            //    if (receive == latitudeArr1[i])
            //        index = search(latitudeArr1, latitudeArr1.Length, receive);
            //}
            ////所以经过调整后包含到R*中的点就是
            //Console.WriteLine(longitudeArr1[index] + "," + latitudeArr1[index]);
            //double te = pJoinInRStar.showx(pJoinInRStar);



            //提前保存在最近点未加入R*的R1中的点
            double[] longitudeArrTemp = new double[longitudeArr1.Length];
            longitudeArr1.CopyTo(longitudeArrTemp, 0);
            double[] latitudeArrTemp = new double[latitudeArr1.Length];
            latitudeArr1.CopyTo(latitudeArrTemp, 0);

            //再将此点从longitudeArr1和latitudeArr1中剔除,形成新的数组(R*调整后,在R*外的点的数组)
            int index = 0;

            index         = UsefulFunction.search(longitudeArr1, longitudeArr1.Length, pJoinInRStar.showx(pJoinInRStar));
            longitudeArr1 = UsefulFunction.newArr(longitudeArr1, index);
            latitudeArr1  = UsefulFunction.newArr(latitudeArr1, index);
            //for (int i = 0; i < latitudeArr1.Length; i++)
            //{
            //    Console.WriteLine(latitudeArr1[i]);
            //}
            //R*调整后的R1的范围
            double rOneAfterRejustLongitudeFirst  = 0;
            double rOneAfterRejustLatitudeFirst   = 0;
            double rOneAfterRejustLongitudeSecond = 0;
            double rOneAfterRejustLatitudeSecond  = 0;

            RangeOfR.getRangeOfROne(longitudeArr1, latitudeArr1, ref rOneAfterRejustLongitudeFirst, ref rOneAfterRejustLatitudeFirst, ref rOneAfterRejustLongitudeSecond,
                                    ref rOneAfterRejustLatitudeSecond, ref rOneLongitudeFirst, ref rOneLatitudeFirst, ref rOneLongitudeSecond, ref rOneLatitudeSecond);

            /*
             * 注意:在此桶划分中,调整R*时计算的成本,如果R1的范围因调整受到了影响,在计算成本时,参与运算的R1的半周长应当为调整后改变了的R1的半周长
             * 但是在最初形成R*之时,即使可能因为R*的形成改变了R1的范围,计算成本时参与运算的仍为R1的原始半周长
             */
            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            /*
             * 计算R1和R*的最终范围
             */
            //R*加入一个点后,R1的范围也许也需要调整,所以R1的半周长得重新计算
            semiPerimeterOne = UsefulFunction.semiPeriU(rOneLongitudeFirst, rOneLatitudeFirst, rOneLongitudeSecond, rOneLatitudeSecond);

            double semiPerimeterRejust   = 0; //R*调整后的半周长
            double costRStarRejust       = 0; //调整后的R*划分成本
            double costDepartRStarRejust = 0; //不包含调整后R*的R1的成本
            double minCostNewSumRejust   = 0; //总成本(最小)

            bool flag = true;                 //决定R*是否加入点,以此判断R*的范围

            RangeOfR.getRangeOfFinalR(semiPerimeterTwo, semiPerimeterOne, shortestDistance, minCostNewSum, rOneTempLongitudeFirst, rOneTempLatitudeFirst,
                                      rOneTempLongitudeSecond, rOneTempLatitudeSecond, involveInRStar, first, second, longitudeArr, latitudeArr, ref flag,
                                      ref semiPerimeterRejust, ref costRStarRejust, ref costDepartRStarRejust, ref minCostNewSumRejust, ref rOneLongitudeFirst, ref rOneLatitudeFirst,
                                      ref rOneLongitudeSecond, ref rOneLatitudeSecond, ref rTwoLongitudeFirst, ref rTwoLatitudeFirst, ref rTwoLongitudeSecond, ref rTwoLatitudeSecond,
                                      ref listCost, ref listCostFinal);

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */

            /*
             * R2的范围是(rTwoLongitudeFirst,rTwoLatitudeFirst),(rTwoLongitudeSecond,rTwoLatitudeSecond)
             * R1的范围是(rOneLongitudeFirst,rOneLatitudeFirst),(rOneLongitudeSecond,rOneLatitudeSecond);
             * R*未加入最近点时R1中点存放的数组:longitudeArrTemp,latitudeArrTemp
             * R*加入最近点时R1中点存放的数组:longitudeArr1,latitudeArr1
             * 现在我们需要将这个过程循环,将当前R1中的点(不管是R*中是否加入了点)的数组拷贝给longitudeArr和latitudeArr,以之作为新的数据集
             * 并进一步在新的数据集中(R1)划分出R3,R2因为已经划出就不再考虑而存入文档了
             * 划分出R3后桶R2一样存入文档不再考虑,再将剩余的点作为新的数据集进一步划分,直至循环结束
             */

            if (flag)
            {
                //如果是加入了点的话,那么新的数据集位于数组longitudeArr1和latitudeArr1
                for (int i = 0; i < longitudeArr1.Length; i++)
                {
                    listLongitudeArr.Add(longitudeArr1[i]);
                    listLatitudeArr.Add(latitudeArr1[i]);
                }
            }
            else
            {
                //调整R*没有加入点,新的数据集位于数组longitudeArrTemp和latitudeArrTemp
                for (int i = 0; i < longitudeArrTemp.Length; i++)
                {
                    listLongitudeArr.Add(longitudeArrTemp[i]);
                    listLatitudeArr.Add(latitudeArrTemp[i]);
                }
            }

            /*
             * ======================================================================================================================================================
             */
        }
Exemplo n.º 5
0
        /*
         * 求在R*外四个顶角范围内的点的最近距离及最近点的下标
         * diffTopLeft:R*外左上角最近的距离值             indexRStarTopLeft:R*外左上角最近点的下标(通过longitudeArrClose5和latitudeArrClose5访问)
         * diffTopRight:R*外右上角最近的距离值            indexRStarTopRight:R*外右上角最近点的下标(通过longitudeArrClose5和latitudeArrClose5访问)
         * diffBottomLeft:R*外左下角最近的距离值              indexRStarBottomLeft:R*外左下角最近点的下标(通过longitudeArrClose5和latitudeArrClose5访问)
         * diffBottomRight:R*外右下角最近的距离值           indexRStarBottomRight:R*外右上角最近点的下标(通过longitudeArrClose5和latitudeArrClose5访问)
         */
        static public void getClosest(ArrayList listDiffTopLeft, ArrayList listDiffTopRight, ArrayList listDiffBottomLeft, ArrayList listDiffBottomRight,
                                      int[] indexRStarTopLeftArr, int[] indexRStarTopRightArr, int[] indexRStarBottomLeftArr, int[] indexRStarBottomRightArr,
                                      ref double diffTopLeft, ref double diffTopRight, ref double diffBottomLeft, ref double diffBottomRight,
                                      ref int indexRStarTopLeft, ref int indexRStarTopRight, ref int indexRStarBottomLeft, ref int indexRStarBottomRight)
        {
            //左上角最小距离及最近点下标的计算
            double[] diffTopLeftArr = (double[])listDiffTopLeft.ToArray(typeof(double));
            listDiffTopLeft.Sort();
            if (listDiffTopLeft.Count == 0)
            {
                diffTopLeft = 100;
            }
            else
            {
                diffTopLeft = (double)listDiffTopLeft[0];
            }
            //找到左上角最近点距离左上角的距离在数组diffTopLeftArr中的下标
            int temp0 = UsefulFunction.search(diffTopLeftArr, diffTopLeftArr.Length, diffTopLeft);

            if (temp0 != -1)
            {
                indexRStarTopLeft = indexRStarTopLeftArr[temp0];
            }
            //double longi = longitudeArrClose5[indexRStarTopLeft];


            //右上角最小距离及最近点下标的计算
            double[] diffTopRightArr = (double[])listDiffTopRight.ToArray(typeof(double));
            listDiffTopRight.Sort();
            if (listDiffTopRight.Count == 0)
            {
                diffTopRight = 100;
            }
            else
            {
                diffTopRight = (double)listDiffTopRight[0];
            }
            //Console.WriteLine(diffTopRight);
            //找到右上角最近点距离右上角的距离在数组diffTopRightArr中的下标
            int temp1 = UsefulFunction.search(diffTopRightArr, diffTopRightArr.Length, diffTopRight);

            if (temp1 != -1)
            {
                indexRStarTopRight = indexRStarTopRightArr[temp1];
            }
            //double longi = longitudeArrClose5[indexRStarTopRight];


            //左下角最小距离及最近点下标的计算
            double[] diffBottomLeftArr = (double[])listDiffBottomLeft.ToArray(typeof(double));
            listDiffBottomLeft.Sort();
            if (listDiffBottomLeft.Count == 0)
            {
                diffBottomLeft = 100;
            }
            else
            {
                diffBottomLeft = (double)listDiffBottomLeft[0];
            }
            //找到左下角最近点距离左下角的距离在数组diffTopRightArr中的下标
            int temp2 = UsefulFunction.search(diffBottomLeftArr, diffBottomLeftArr.Length, diffBottomLeft);

            if (temp2 != -1)
            {
                indexRStarBottomLeft = indexRStarBottomLeftArr[temp2];
            }
            //double longi = longitudeArrClose5[indexRStarBottomLeft];


            //右下角最小距离及最近点下标的计算
            double[] diffBottomRightArr = (double[])listDiffBottomRight.ToArray(typeof(double));
            listDiffBottomRight.Sort();
            if (listDiffBottomRight.Count == 0)
            {
                diffBottomRight = 100;
            }
            else
            {
                diffBottomRight = (double)listDiffBottomRight[0];
            }
            //找到左下角最近点距离左下角的距离在数组diffTopRightArr中的下标
            int temp3 = UsefulFunction.search(diffBottomRightArr, diffBottomRightArr.Length, diffBottomRight);

            if (temp3 != -1)
            {
                indexRStarBottomRight = indexRStarBottomRightArr[temp3];
            }
            //double longi = longitudeArrClose5[indexRStarBottomLeft];
        }
Exemplo n.º 6
0
        static void Main(string[] args)
        {
            /*
             * ======================================================================================================================================================
             */
            int tuplesCount = GetData.connectSQL();            //首先获取多维数据的数量

            /*
             * 获取数据库中的元组数据并存入数组
             */
            double[] longitudeArr = new double[tuplesCount];
            double[] latitudeArr  = new double[tuplesCount];
            GetData.GetArray(ref longitudeArr, ref latitudeArr);//获取元组
            double peri = 0, cost = 0;

            peri = UsefulFunction.semiPeriU(UsefulFunction.minInArr(longitudeArr), UsefulFunction.minInArr(latitudeArr), UsefulFunction.maxInArr(longitudeArr), UsefulFunction.maxInArr(latitudeArr));
            cost = peri * tuplesCount;
            Console.WriteLine("Tips:The original cost of the buckets is:" + cost);
            //double[] longitudeArr = new double[34] { 116.28, 121.29, 117.11, 106.32, 126.41, 125.19, 123.24, 111.48, 114.28, 112.34, 117, 113.42, 108.54, 103.49, 106.16, 101.45, 87.36, 117.18, 118.50, 120.09, 113, 115.52, 114.21, 104.05, 106.42, 119.18, 121.31, 113.15, 110.20, 108.20, 102.41, 91.10, 114.10, 113.5 };
            //double[] latitudeArr = new double[34] { 39.54, 31.14, 39.09, 29.32, 45.45, 43.52, 41.50, 40.49, 38.02, 37.52, 36.38, 34.48, 34.16, 36.03, 38.20, 36.38, 43.48, 31.51, 32.02, 30.14, 28.11, 28.41, 30.37, 30.39, 26.35, 26.05, 25.03, 23.08, 20.02, 22.48, 25, 29.40, 22.18, 22.2 };
            //Console.WriteLine(longitudeArr.Length);
            //for (int i = 0; i < longitudeArr.Length; i++)
            //{
            //    Console.WriteLine(longitudeArr[i]);
            //}
            //初始R1的范围
            double rOneLongitudeFirst         = 0;
            double rOneLatitudeFirst          = 0;
            double rOneLongitudeSecond        = 0;
            double rOneLatitudeSecond         = 0;

            double rTwoLongitudeFirst         = 0;//R2的范围
            double rTwoLatitudeFirst          = 0;
            double rTwoLongitudeSecond        = 0;
            double rTwoLatitudeSecond         = 0;

            /*
             * ======================================================================================================================================================
             */
            /*
             * 我们需要把每次生成的R1和R*的范围存入以下集合中
             */
            ArrayList listROneLongitudeFirst  = new ArrayList();
            ArrayList listROneLatitudeFirst   = new ArrayList();
            ArrayList listROneLongitudeSecond = new ArrayList();
            ArrayList listROneLatitudeSecond  = new ArrayList();

            ArrayList listRTwoLongitudeFirst  = new ArrayList();
            ArrayList listRTwoLatitudeFirst   = new ArrayList();
            ArrayList listRTwoLongitudeSecond = new ArrayList();
            ArrayList listRTwoLatitudeSecond  = new ArrayList();

            string str                        = string.Empty;
            int    bucketNum                  = 0;

            Console.Write("Please input the number of bucket's label that you want to create:");
            //bucketNum = Console.Read() - 48;
            str       = Console.ReadLine();
            bucketNum = Convert.ToInt32(str);
            ArrayList listCost      = new ArrayList();
            ArrayList listCostFinal = new ArrayList();

            Console.WriteLine("_______________________________________________________________________________");
            Console.WriteLine("\tRejust Or Not\t\t The cost of R1 and R*\t The cost of R*");
            for (int i = 0; i < bucketNum - 1; i++)//划分一次(最终加上R1有两个桶)
            {
                //用于在划分迭代计算时,存放新的数据集的集合
                ArrayList listLongitudeArr = new ArrayList();
                ArrayList listLatitudeArr  = new ArrayList();

                /*
                 * 如果R1中的数据集少于4个,就不能再分桶了
                 * 如果只有一个点,显然已经不是一个平面
                 * 如果还有两个分桶会是一样的
                 * 如果有三个,分桶后R1中只剩一个点,不能确定一个平面
                 */
                if (longitudeArr.Length < 4)
                {
                    break;
                }
                NewDataSet.getNewDataSet(longitudeArr, latitudeArr, ref listLongitudeArr, ref listLatitudeArr, ref rOneLongitudeFirst, ref rOneLatitudeFirst,
                                         ref rOneLongitudeSecond, ref rOneLatitudeSecond, ref rTwoLongitudeFirst, ref rTwoLatitudeFirst, ref rTwoLongitudeSecond, ref rTwoLatitudeSecond,
                                         ref listCost, ref listCostFinal);
                longitudeArr = (double[])listLongitudeArr.ToArray(typeof(double));
                latitudeArr  = (double[])listLatitudeArr.ToArray(typeof(double));
                //注意添加到集合中的范围,集合中的第一项(下标从0开始)是R2的范围,集合中的最后一项(下标:list.Count-1)是R1的范围,中间的依次为R3,R4,R5...

                /*
                 * 在加入集合前我们需要判断新划分出来的桶会不会是一个点
                 * 如果是一个点,说明R1中的数据集不可以再进行划分了,因此需要立即终止该循环
                 * 否则继续划分
                 */
                //if ((rTwoLongitudeFirst == rTwoLongitudeSecond) && (rTwoLatitudeFirst == rTwoLatitudeSecond))
                //    break;
                ///*
                // * 除了划分出去的点外还要检查R1是不是也是一个点
                // */
                //if ((rOneLongitudeFirst == rOneLongitudeSecond) && (rOneLatitudeFirst == rOneLatitudeSecond))
                //    break;

                /*
                 * 在将矩形的范围存入集合中时,为了保持范围的一致性,按照参考文献的标准我们设计如下:
                 * first.x<second.x     first.y>second.y
                 */
                if (rOneLongitudeFirst > rOneLongitudeSecond)
                {
                    UsefulFunction.swap(ref rOneLongitudeFirst, ref rOneLongitudeSecond);
                }
                if (rTwoLongitudeFirst > rTwoLongitudeSecond)
                {
                    UsefulFunction.swap(ref rTwoLongitudeFirst, ref rTwoLongitudeSecond);
                }
                if (rOneLatitudeSecond > rOneLatitudeFirst)
                {
                    UsefulFunction.swap(ref rOneLatitudeSecond, ref rOneLatitudeFirst);
                }
                if (rTwoLatitudeSecond > rTwoLatitudeFirst)
                {
                    UsefulFunction.swap(ref rTwoLatitudeSecond, ref rTwoLatitudeFirst);
                }


                listROneLongitudeFirst.Add(rOneLongitudeFirst);
                listROneLatitudeFirst.Add(rOneLatitudeFirst);
                listROneLongitudeSecond.Add(rOneLongitudeSecond);
                listROneLatitudeSecond.Add(rOneLatitudeSecond);

                listRTwoLongitudeFirst.Add(rTwoLongitudeFirst);
                listRTwoLatitudeFirst.Add(rTwoLatitudeFirst);
                listRTwoLongitudeSecond.Add(rTwoLongitudeSecond);
                listRTwoLatitudeSecond.Add(rTwoLatitudeSecond);
            }
            Console.WriteLine("_______________________________________________________________________________");
            //for (int i = 0; i < listCostFinal.Count; i++)
            //{
            //    Console.WriteLine(listCostFinal[i]);
            //}
            int realLabelNum = 0;//真实生成的桶标签数

            realLabelNum = listROneLongitudeFirst.Count + 1;
            if (bucketNum > 1)
            {
                double[] costArr = (double[])listCost.ToArray(typeof(double));
                double[] costFinalArr = (double[])listCostFinal.ToArray(typeof(double));
                double   costPartOne = 0, costPartTwo = 0, realCost = 0;
                for (int i = 1; i < realLabelNum; i++)
                {
                    costPartOne = costFinalArr[i - 1];
                    if (i == 1)//如果是第一次划分,只需要R1和R*的总成本
                    {
                        costPartTwo = 0;
                    }
                    else
                    {
                        costPartTwo += costArr[i - 2];
                    }
                    realCost = costPartOne + costPartTwo;
                    Console.WriteLine("The " + i + "th bucketization cost:" + realCost);
                }
                //int icost = 0;
                //for (icost = 0; icost < listCost.Count; icost++)
                //{
                //    if (listCost.Count - 1 == icost)//不加最后一项
                //        break;
                //    realCost += costArr[icost];
                //}
                //realCost += costFinalArr[listCostFinal.Count - 1];
                //int itemp = icost + 1;
                //Console.WriteLine("The " + itemp + "th bucketization cost:" + realCost);
                Console.WriteLine("_______________________________________________________________________________");
                Console.WriteLine("Tips:The real number of the bucket's label is:" + realLabelNum);    //真实生成的桶标签数
                Console.WriteLine("Tips:The real cost of the bucketization algorithm is:" + realCost); //真实生成的桶标签数
            }
            else if (bucketNum == 1)
            {
                Console.WriteLine("The bucketization cost:" + cost);
                realLabelNum = listROneLongitudeFirst.Count + 1;
                Console.WriteLine("_______________________________________________________________________________");
                Console.WriteLine("Tips:The real number of the bucket's label is:" + realLabelNum); //真实生成的桶标签数
                Console.WriteLine("Tips:The real cost of the bucketization algorithm is:" + cost);  //真实生成的桶标签数
            }
            else
            {
                Console.WriteLine("输入数据非法!");
            }

            /*
             * ======================================================================================================================================================
             */
            /*
             * 以下是存放R2,R3,R4,...R1范围的数组
             * rOne的数组中存放的是:R1,R1,R1......R1的范围,其中最后一个R1就是最终的R1范围
             * rTwo的数组中存放的是:R2,R3,R4.....的范围
             */
            double[] rOneLongitudeFirstArr  = (double[])listROneLongitudeFirst.ToArray(typeof(double));
            double[] rOneLatitudeFirstArr   = (double[])listROneLatitudeFirst.ToArray(typeof(double));
            double[] rOneLongitudeSecondArr = (double[])listROneLongitudeSecond.ToArray(typeof(double));
            double[] rOneLatitudeSecondArr  = (double[])listROneLatitudeSecond.ToArray(typeof(double));

            double[] rTwoLongitudeFirstArr  = (double[])listRTwoLongitudeFirst.ToArray(typeof(double));
            double[] rTwoLatitudeFirstArr   = (double[])listRTwoLatitudeFirst.ToArray(typeof(double));
            double[] rTwoLongitudeSecondArr = (double[])listRTwoLongitudeSecond.ToArray(typeof(double));
            double[] rTwoLatitudeSecondArr  = (double[])listRTwoLatitudeSecond.ToArray(typeof(double));

            /*
             * ======================================================================================================================================================
             */

            /*
             * ======================================================================================================================================================
             */
            //将桶划分的结果写入本地的文件中,用于今后用户查询的读取进行桶标签的匹配

            string path = "D:\\BukectInfo3.txt";

            if (!File.Exists(path))
            {
                File.Create(path);
            }
            FileInfo finfo = new FileInfo(path);

            if (finfo.Exists)
            {
                finfo.Delete();
            }
            using (FileStream fs = finfo.OpenWrite())
            {
                //根据上面创建的文件流创建写文件流
                StreamWriter sw = new StreamWriter(fs);
                //设置写数据流的起始位置为文件流的末尾
                sw.BaseStream.Seek(0, SeekOrigin.End);
                if (realLabelNum == 1)
                {
                    //如果只有一个桶标签,说明只生成一个桶,就是原来的数据集
                    ArrayList list = new ArrayList();
                    list.Add(UsefulFunction.minInArr(longitudeArr));
                    list.Add(UsefulFunction.maxInArr(latitudeArr));
                    list.Add(UsefulFunction.maxInArr(longitudeArr));
                    list.Add(UsefulFunction.minInArr(latitudeArr));
                    double[] ff = (double[])list.ToArray(typeof(double));
                    foreach (double f in ff)
                    {
                        sw.Write("{0} ", f);
                    }
                    sw.Write("A\r\n");
                }
                else
                {
                    ArrayList list0 = new ArrayList();
                    list0.Add(rOneLongitudeFirstArr[rOneLongitudeFirstArr.Length - 1]);
                    list0.Add(rOneLatitudeFirstArr[rOneLatitudeFirstArr.Length - 1]);
                    list0.Add(rOneLongitudeSecondArr[rOneLongitudeSecondArr.Length - 1]);
                    list0.Add(rOneLatitudeSecondArr[rOneLatitudeSecondArr.Length - 1]);
                    double[] dd = (double[])list0.ToArray(typeof(double));
                    foreach (double d in dd)
                    {
                        sw.Write("{0} ", d);
                    }
                    sw.Write("A");
                    //windows下是用\r\n实现回车换行
                    sw.Write("\r\n");
                    //string s1 = "101.45 25 123.24 41.5 B";
                    //string s1 = rTwoLongitudeFirst.ToString() + " " + rTwoLatitudeFirst.ToString() + " "
                    //    + rTwoLongitudeSecond.ToString() + " " + rTwoLatitudeSecond.ToString() + " " + "B";
                    //sw.WriteLine(s1);

                    /*
                     * 因为给定的划分桶标签数量可能会大于真实生成的桶标签数(因为在数据集过小时,划分出来的桶会不是矩形而是一个点,这样的桶将会被舍弃,并终止当前的桶划分循环)
                     * 因此在写入桶范围,循环应该由真实生成的桶标签数决定,不能将bucketNum作为循环的判断条件
                     */
                    //for (int i = 0; i < bucketNum - 1; i++)
                    for (int i = 0; i < rOneLongitudeFirstArr.Length; i++)
                    {
                        ArrayList list1 = new ArrayList();
                        list1.Add(rTwoLongitudeFirstArr[i]);
                        list1.Add(rTwoLatitudeFirstArr[i]);
                        list1.Add(rTwoLongitudeSecondArr[i]);
                        list1.Add(rTwoLatitudeSecondArr[i]);
                        double[] ee = (double[])list1.ToArray(typeof(double));
                        foreach (double e in ee)
                        {
                            sw.Write("{0} ", e);
                        }
                        char c    = 'B';
                        int  asii = Convert.ToInt32(c) + i;
                        c = Convert.ToChar(asii);
                        sw.Write(c + "\r\n");
                    }
                }

                //清空缓冲区内容,并把缓冲区内容写入基础流
                sw.Flush();
                //关闭写数据流
                sw.Close();
                fs.Close();
            }
        } //Main
Exemplo n.º 7
0
        /*
         * 求在R*外上下左右四处范围内的点的最近距离及最近点的下标
         * diffLeft:R*外左侧最近的距离值             indexRStarLeft:R*外左侧最近点的下标(通过longitudeArr1和latitudeArr1访问)
         * diffRight:R*外右侧最近的距离值            indexRStarRight:R*外右侧最近点的下标(通过longitudeArr1和latitudeArr1访问)
         * diffTop:R*外上侧最近的距离值              indexRStarTop:R*外上侧最近点的下标(通过longitudeArr1和latitudeArr1访问)
         * diffBottom:R*外下侧最近的距离值           indexRStarBottom:R*外下侧最近点的下标(通过longitudeArr1和latitudeArr1访问)
         */
        static public void getClosest(double[] longitudeArr, double[] latitudeArr, double[] longitudeArr1, double[] latitudeArr1, int first, int second, int r,
                                      ArrayList listLongitudeArrClose1, ArrayList listLongitudeArrClose2, ArrayList listLatitudeArrClose1, ArrayList listLatitudeArrClose2,
                                      ref double diffLeft, ref double diffRight, ref double diffTop, ref double diffBottom,
                                      ref int indexRStarLeft, ref int indexRStarRight, ref int indexRStarTop, ref int indexRStarBottom)
        {
            Point pFirst  = new Point(longitudeArr[first], latitudeArr[first]);
            Point pSecond = new Point(longitudeArr[second], latitudeArr[second]);

            //我们先看R*左边最近的点
            listLongitudeArrClose1.Sort();
            //for (int i = 0; i < longitudeArrClose1.Count; i++)
            //{
            //    Console.WriteLine(longitudeArrClose1[i]);
            //}
            if (listLongitudeArrClose1.Count == 0)
            {
                diffLeft = 100;
            }
            else
            {
                double maxRStarLeft = (double)listLongitudeArrClose1[listLongitudeArrClose1.Count - 1]; //左边离R*最近点就是选择经度最大的
                indexRStarLeft = UsefulFunction.search(longitudeArr1, r, maxRStarLeft);                 //r是R*外R1内的点数
                //Console.Write(indexRStarLeft);
                Point pLeft = new Point(longitudeArr1[indexRStarLeft], latitudeArr1[indexRStarLeft]);
                //Console.WriteLine(pLeft.showx(pLeft) + "," + pLeft.showy(pLeft));
                //计算diffLeft
                //先判断两点经度的大小,需要确定左边那根经度是点一确定的还是点二
                if (pFirst.longitudeOneSmaller(pSecond))
                {
                    //如果第一个点的经度值小,在比较两点的维度大小
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //此时就是第一个点的经度和维度都小于第二个点,即(first.x<second.x)&&(first.y<seconde.y)
                        //R*左边的线由点一的经度确定
                        diffLeft = longitudeArr[first] - pLeft.showx(pLeft);
                    }
                    else
                    {
                        //即(first.x<second.x)&&(first.y>seconde.y)
                        //R*左边的线由点一的经度确定
                        diffLeft = longitudeArr[first] - pLeft.showx(pLeft);
                    }
                }
                else
                {
                    //first.x>seconde.x
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //即(first.x>second.x)&&(first.y<seconde.y)
                        //R*左边的线由点二的经度决定
                        diffLeft = longitudeArr[second] - pLeft.showx(pLeft);
                    }
                    else
                    {
                        //即(first.x>second.x)&&(first.y>seconde.y)
                        //R*左边的线由点二的经度决定
                        diffLeft = longitudeArr[second] - pLeft.showx(pLeft);
                    }
                }
            }
            //Console.WriteLine(diffLeft);

            //Console.WriteLine("右");
            ////我们先看R*右边最近的点
            listLongitudeArrClose2.Sort();
            //for (int i = 0; i < longitudeArrClose2.Count; i++)
            //{
            //    Console.WriteLine(longitudeArrClose2[i]);
            //}

            if (listLongitudeArrClose2.Count == 0)
            {
                diffRight = 100;
            }
            else
            {
                double minRStarRight = (double)listLongitudeArrClose2[0];//右边就是选择经度最小的
                indexRStarRight = UsefulFunction.search(longitudeArr1, r, minRStarRight);
                //Console.Write(indexRStarRight);
                Point pRight = new Point(longitudeArr1[indexRStarRight], latitudeArr1[indexRStarRight]);
                //Console.WriteLine(pLeft.showx(pRight) + "," + pLeft.showy(pRight));
                //计算diffRight
                //先判断两点经度的大小,需要确定右边那根经度是点一确定的还是点二
                if (pFirst.longitudeOneSmaller(pSecond))
                {
                    //如果第一个点的经度值小,在比较两点的维度大小
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //此时就是第一个点的经度和维度都小于第二个点,即(first.x<second.x)&&(first.y<seconde.y)
                        //R*右边的线由点二的经度确定
                        diffRight = pRight.showx(pRight) - longitudeArr[second];
                    }
                    else
                    {
                        //即(first.x<second.x)&&(first.y>seconde.y)
                        //R*右边的线由点二的经度确定
                        diffRight = pRight.showx(pRight) - longitudeArr[second];
                    }
                }
                else
                {
                    //first.x>seconde.x
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //即(first.x>second.x)&&(first.y<seconde.y)
                        //R*右边的线由点一的经度决定
                        diffRight = pRight.showx(pRight) - longitudeArr[first];
                    }
                    else
                    {
                        //即(first.x>second.x)&&(first.y>seconde.y)
                        //R*右边的线由点一的经度决定
                        diffRight = pRight.showx(pRight) - longitudeArr[first];
                    }
                }
            }
            //Console.WriteLine(diffRight);



            //Console.WriteLine("上");
            ////我们先看R*上边最近的点
            listLatitudeArrClose1.Sort();
            //for (int i = 0; i < listLatitudeArrClose1.Count; i++)
            //{
            //    Console.WriteLine(listLatitudeArrClose1[i]);
            //}
            if (listLatitudeArrClose1.Count == 0)
            {
                diffTop = 100;
            }
            else
            {
                double minRStarTop = (double)listLatitudeArrClose1[0];//上边就是选择维度最小的
                indexRStarTop = UsefulFunction.search(latitudeArr1, r, minRStarTop);
                //Console.Write(indexRStarTop);
                Point pTop = new Point(longitudeArr1[indexRStarTop], latitudeArr1[indexRStarTop]);
                //Console.WriteLine(pTop.showx(pTop) + "," + pTop.showy(pTop));
                //计算diffTop
                //先判断两点经度的大小,需要确定上边那根纬度是点一确定的还是点二
                if (pFirst.longitudeOneSmaller(pSecond))
                {
                    //如果第一个点的经度值小,在比较两点的维度大小
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //此时就是第一个点的经度和维度都小于第二个点,即(first.x<second.x)&&(first.y<seconde.y)
                        //R*上边的线由点二的纬度确定
                        diffTop = pTop.showy(pTop) - latitudeArr[second];
                    }
                    else
                    {
                        //即(first.x<second.x)&&(first.y>seconde.y)
                        //R*上边的线由点一的纬度确定
                        diffTop = pTop.showy(pTop) - latitudeArr[first];
                    }
                }
                else
                {
                    //first.x>seconde.x
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //即(first.x>second.x)&&(first.y<seconde.y)
                        //R*上边的线由点二的纬度决定
                        diffTop = pTop.showy(pTop) - latitudeArr[second];
                    }
                    else
                    {
                        //即(first.x>second.x)&&(first.y>seconde.y)
                        //R*上边的线由点一的纬度决定
                        diffTop = pTop.showy(pTop) - latitudeArr[first];
                    }
                }
            }
            //Console.WriteLine(diffTop);

            //Console.WriteLine("下");
            ////我们先看R*下边最近的点
            listLatitudeArrClose2.Sort();
            //for (int i = 0; i < latitudeArrClose2.Count; i++)
            //{
            //    Console.WriteLine(latitudeArrClose2[i]);
            //}
            if (listLatitudeArrClose2.Count == 0)
            {
                diffBottom = 100;
            }
            else
            {
                double maxRStarBottom = (double)listLatitudeArrClose2[listLatitudeArrClose2.Count - 1];//下边就是选择维度最大的
                indexRStarBottom = UsefulFunction.search(latitudeArr1, r, maxRStarBottom);
                //Console.Write(indexRStarBottom);
                Point pBottom = new Point(longitudeArr1[indexRStarBottom], latitudeArr1[indexRStarBottom]);
                //Console.WriteLine(pBottom.showx(pBottom) + "," + pBottom.showy(pBottom));
                //计算diffBottom
                //先判断两点经度的大小,需要确定下边那根纬度是点一确定的还是点二
                if (pFirst.longitudeOneSmaller(pSecond))
                {
                    //如果第一个点的经度值小,在比较两点的维度大小
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //此时就是第一个点的经度和维度都小于第二个点,即(first.x<second.x)&&(first.y<seconde.y)
                        //R*下边的线由点一的纬度确定
                        diffBottom = latitudeArr[first] - pBottom.showy(pBottom);
                    }
                    else
                    {
                        //即(first.x<second.x)&&(first.y>seconde.y)
                        //R*下边的线由点二的纬度确定
                        diffBottom = latitudeArr[second] - pBottom.showy(pBottom);
                    }
                }
                else
                {
                    //first.x>seconde.x
                    if (pFirst.latitudeOneSmaller(pSecond))
                    {
                        //即(first.x>second.x)&&(first.y<seconde.y)
                        //R*下边的线由点一的纬度决定
                        diffBottom = latitudeArr[first] - pBottom.showy(pBottom);
                    }
                    else
                    {
                        //即(first.x>second.x)&&(first.y>seconde.y)
                        //R*下边的线由点二的纬度决定
                        diffBottom = latitudeArr[second] - pBottom.showy(pBottom);
                    }
                }
            }
            //Console.WriteLine(diffBottom);
        }