예제 #1
0
        /// <summary>
        /// 根据给定的一系列有顺序的坐标,逆时针生成轴线左侧的缓冲区边界点
        /// </summary>
        /// <param name="coords">一系列有顺序的坐标</param>
        /// <param name="radius">缓冲区半径</param>
        /// <returns>缓冲区的边界坐标</returns>
        public VertexCollection GetLeftBufferEdgeCoords(VertexCollection coords, double radius)
        {
            VertexCollection polyline = new VertexCollection();
            Vertex           point    = new Vertex();
            //计算时所需变量
            double alpha = 0.0; //向量绕起始点沿顺时针方向旋转到X轴正半轴所扫过的角度
            double delta = 0.0; //前后线段所形成的向量之间的夹角
            double l     = 0.0; //前后线段所形成的向量的叉积
            //辅助变量
            double startRadian = 0.0;
            double endRadian = 0.0;
            double beta = 0.0;
            double x = 0.0, y = 0.0;

            //中间节点
            for (int i = 1; i < coords.Count - 1; i++)
            {
                alpha = GetQuadrantAngle(coords.getVer(i), coords.getVer(i + 1));
                delta = GetIncludedAngle(coords.getVer(i - 1), coords.getVer(i), coords.getVer(i + 1));
                l     = GetVectorProduct(coords.getVer(i - 1), coords.getVer(i), coords.getVer(i + 1));
                if (l > 0)//凸
                {
                    startRadian = alpha + (3 * Math.PI) / 2 - delta;
                    endRadian   = alpha + (3 * Math.PI) / 2;
                    VertexCollection ipc1 = GetBufferCoordsByRadian(coords.getVer(i), startRadian, endRadian, radius);
                    for (int j = 0; j < ipc1.Count; j++)
                    {
                        if (ipc1.getVer(j).X() > 0)
                        {
                        }
                        Alter(ref polyline, ipc1.getVer(j));
                        polyline.addVer(ipc1.getVer(j));
                    }
                }
                else if (l < 0)
                {
                    beta = alpha - (Math.PI - delta) / 2;
                    x    = Math.Round(coords.getVer(i).X() + radius * Math.Cos(beta), 2);
                    y    = Math.Round(coords.getVer(i).Y() + radius * Math.Sin(beta), 2);
                    Vertex ipoint = new Vertex();
                    ipoint.X(x);
                    ipoint.Y(y);
                    if (ipoint.X() > 0)
                    {
                    }
                    Alter(ref polyline, ipoint);
                    polyline.addVer(ipoint);
                }
            }
            return(polyline);
        }
예제 #2
0
        /// <summary>
        /// 判断新加入的点会不会是边界产生自相交,是则进行修改
        /// </summary>
        /// <param name="ipc"></param>
        /// <param name="point"></param>
        /// <returns></returns>
        public bool Alter(ref VertexCollection ipc, Vertex point)
        {
            int count = ipc.Count;

            if (count >= 3)
            {
                bool flag  = false;
                int  index = count - 1;
                for (int i = index - 1; i >= 1; i--)
                {
                    if (InsectionJudge(ipc.getVer(index), point, ipc.getVer(i), ipc.getVer(i - 1)))
                    {
                        flag  = true;
                        index = i;
                        break;
                    }
                }
                if (flag)
                {
                    Vertex insectp = Inter(ipc.getVer(count - 1), point, ipc.getVer(index), ipc.getVer(index - 1));
                    ipc.removeVers(index, count - index);
                    ipc.addVer(insectp);
                }
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// 执行线要素的反转
        /// </summary>
        /// <param name="ipc"></param>
        /// <returns></returns>
        public VertexCollection Reverse(VertexCollection ipc)
        {
            VertexCollection ipc0 = new VertexCollection();

            for (int i = ipc.Count - 1; i >= 0; i--)
            {
                ipc0.addVer(ipc.getVer(i));
            }
            return(ipc0);
        }
예제 #4
0
        /// <summary>
        /// 生成穹窿模型侧面
        /// </summary>
        /// <param name="fornix"></param>
        /// <param name="preFornix"></param>
        private static void createSide(Fornix fornix, Fornix preFornix, double FornixDip)
        {
            VertexCollection vcDown = new VertexCollection();//底面顶点集合
            Vertex           vertexUp, vertexDown;
            double           dip = FornixDip;

            //根据产状生成底面顶点
            for (int i = 1; i < fornix.outSide.countUpVers() - 1; ++i)
            {
                vertexUp = fornix.outSide.getUpver(i);
                vertexUp.calOccuurence(fornix.outSide.getUpver(i - 1), fornix.outSide.getUpver(i + 1), dip);
                vertexDown = new Vertex();
                vertexDown.createDownVer(vertexUp);
                vertexDown.ID = _verNum++;
                vcDown.addVer(vertexDown);
            }

            vertexUp = fornix.outSide.getUpver(fornix.outSide.countUpVers() - 1);
            vertexUp.calOccuurence(fornix.outSide.getUpver(fornix.outSide.countUpVers() - 2), fornix.outSide.getUpver(0), dip);
            vertexDown = new Vertex();
            vertexDown.createDownVer(vertexUp);
            vertexDown.ID = _verNum++;
            vcDown.addVer(vertexDown);

            vertexUp = fornix.outSide.getUpver(0);
            vertexUp.calOccuurence(fornix.outSide.getUpver(fornix.outSide.countUpVers() - 1), fornix.outSide.getUpver(1), dip);
            vertexDown = new Vertex();
            vertexDown.createDownVer(vertexUp);
            vertexDown.ID = _verNum++;
            vcDown.addVer(vertexDown);

            //生成地层外侧面
            fornix.createOutSideLowvers(vcDown);
            _verNum -= fornix.createOutSide();

            //生成前一地层的内侧面
            if (preFornix != null)
            {
                preFornix.createInSide(fornix);
            }
        }
예제 #5
0
        /// <summary>
        /// 获取指定弧度范围之间的缓冲区圆弧拟合边界点
        /// </summary>
        /// <param name="center">指定拟合圆弧的原点</param>
        /// <param name="startRadian">开始弧度</param>
        /// <param name="endRadian">结束弧度</param>
        /// <param name="radius">缓冲区半径</param>
        /// <returns>缓冲区的边界坐标</returns>
        private VertexCollection GetBufferCoordsByRadian(Vertex center, double startRadian, double endRadian, double radius)
        {
            VertexCollection points = new VertexCollection();
            double           gamma = Math.PI / 100;
            double           x = 0.0, y = 0.0;

            for (double phi = startRadian; phi <= endRadian + 0.000000000000001; phi += gamma)
            {
                Vertex point = new Vertex();
                x = Math.Round(center.X() + radius * Math.Cos(phi), 2);
                y = Math.Round(center.Y() + radius * Math.Sin(phi), 2);
                point.X(x);
                point.Y(y);
                points.addVer(point);
            }
            return(points);
        }
예제 #6
0
파일: Delaunay.cs 프로젝트: CowSaltfish/NNU
        /// <summary>
        /// 由多边形顶点生成三角网
        /// </summary>
        /// <param name="tris"></param>
        /// <param name="vc"></param>
        /// <param name="rectangle"></param>
        /// <param name="cavity"></param>
        /// <param name="edges"></param>
        private static VertexCollection insertVC2Tris(ref SortedList <string, Triangle> tris, VertexCollection vc, Vertex[] rectangle, SortedList <string, Triangle> cavity, List <Edge> edges)
        {
            if (null == vc)
            {
                return(null);
            }
            Triangle         tri;
            int              i = 0, j;
            VertexCollection vcInner = new VertexCollection();

            if (0 == tris.Count)
            {
                //第一个点连接矩形顶点
                Vertex     ver0           = vc.getVer(0);
                Triangle[] triOfRectangle = new Triangle[4];
                triOfRectangle[0] = new Triangle();
                triOfRectangle[1] = new Triangle();
                triOfRectangle[2] = new Triangle();
                triOfRectangle[3] = new Triangle();
                triOfRectangle[0].addPoint(ver0);
                triOfRectangle[0].addPoint(rectangle[1]);
                triOfRectangle[0].addPoint(rectangle[0]);
                tris.Add(triOfRectangle[0].name, triOfRectangle[0]);
                triOfRectangle[1].addPoint(ver0);
                triOfRectangle[1].addPoint(rectangle[3]);
                triOfRectangle[1].addPoint(rectangle[1]);
                tris.Add(triOfRectangle[1].name, triOfRectangle[1]);
                triOfRectangle[2].addPoint(ver0);
                triOfRectangle[2].addPoint(rectangle[2]);
                triOfRectangle[2].addPoint(rectangle[3]);
                tris.Add(triOfRectangle[2].name, triOfRectangle[2]);
                triOfRectangle[3].addPoint(ver0);
                triOfRectangle[3].addPoint(rectangle[0]);
                triOfRectangle[3].addPoint(rectangle[2]);
                tris.Add(triOfRectangle[3].name, triOfRectangle[3]);
                ++i;
            }
            //将地层顶点插入三角网中
            for (; i < vc.Count; ++i)
            {
                Vertex verInserted = vc.getVer(i);
                if (!verInserted.innerPoint)
                {
                    for (j = 0; j < tris.Count; ++j)
                    {
                        tri = tris.Values[j];
                        Vertex circumcenter = tri.calCircumCenter();
                        //点在三角形外接圆中
                        if (verInserted.calDistance(circumcenter) <= tri.points.getVer(0).calDistance(circumcenter))
                        {
                            //广度遍历得到空腔
                            findCavity(verInserted, tri, tris, cavity, edges);
                            //由空腔生成新三角形
                            createTriByCavity(verInserted, ref tris, cavity, edges);
                            break;
                        }
                    }
                }
                else
                {
                    for (j = 0; j < tris.Count; ++j)
                    {
                        tri = tris.Values[j];
                        //判断点在三角形中
                        if (verInserted.inside(tri))
                        {
                            verInserted.ID = ++idxInnerPoint;
                            vcInner.addVer(verInserted);
                            //广度遍历得到空腔
                            findCavity(verInserted, tri, tris, cavity, edges);
                            //由空腔生成新三角形
                            createTriByCavity(verInserted, ref tris, cavity, edges);
                            break;
                        }
                    }
                }
            }
            //插入内部点后调整三角面法向
            if (0 != vc.Count && vc.getVer(0).innerPoint)
            {
                for (i = 0; i < tris.Count; ++i)
                {
                    tri = tris.Values[i];
                    if (tri.calVector() < 0.0)
                    {
                        tri.reverse();
                    }
                }
            }
            return(vcInner);
        }
예제 #7
0
        /// <summary>
        /// 由带值点要素生成穹窿模型
        /// </summary>
        private static void createFornixModelByPoint()
        {
            string path    = @"E:\Users\LiuXianyu\Documents\ExperimentData\myProject\FornixModelingGDAL\Data\LingYanShan\Export\fornix1.obj";
            string imgpath = @"E:\Users\LiuXianyu\Documents\ExperimentData\myProject\FornixModelingGDAL\Data\LingYanShan\lingyan.img";

            _RasterPoints = DEMServer.getVersFromDEM(imgpath);

            //_RasterPoints = new VertexCollection();
            //Vertex tempVer = new Vertex();
            //tempVer.X(139741.0);
            //tempVer.Y(175806.0);
            //tempVer.Z(300.0);
            //tempVer.innerPoint = true;
            //_RasterPoints.addVer(tempVer);

            Fornix preFornix = null;

            ReadShp(@"E:\Users\LiuXianyu\Documents\ExperimentData\myProject\FornixModelingGDAL\Data\LingYanShan\codedata\vertex1\lyspv1.shp");
            ReadShp(@"E:\Users\LiuXianyu\Documents\ExperimentData\myProject\FornixModelingGDAL\Data\LingYanShan\codedata\vertex1\lyspv2.shp");
            ReadShp(@"E:\Users\LiuXianyu\Documents\ExperimentData\myProject\FornixModelingGDAL\Data\LingYanShan\codedata\vertex1\lyspv3.shp");

            foreach (Layer PointLayer in layers)
            {
                //读入一个地层
                Fornix           fornix = new Fornix(PointLayer.GetName());
                VertexCollection vcUp   = new VertexCollection();
                fornix.dip = PointLayer.GetFeature(0).GetFieldAsDouble("dip");
                for (int i = 0; i < (int)PointLayer.GetFeatureCount(0); ++i)
                {
                    Vertex vertex = new Vertex();
                    vertex.ID = _verNum++;
                    vertex.X(PointLayer.GetFeature(i).GetFieldAsDouble("POINT_X"));
                    vertex.Y(PointLayer.GetFeature(i).GetFieldAsDouble("POINT_Y"));
                    //vertex.Z(PointLayer.GetFeature(i).GetFieldAsDouble("RASTERVALU"));
                    vertex.Z(DEMServer.GetElevation(vertex.X(), vertex.Y()));
                    vcUp.addVer(vertex);
                }
                if (vcUp.Count < 3)
                {
                    MessageBox.Show("地层产状点不足!");
                }
                //生成侧面上顶点
                fornix.createOutSideUpvers(vcUp);
                //侧面生成
                createSide(fornix, preFornix, fornix.dip);

                //将顶面边界点产状信息插回shp中
                //SetShp(PointLayer, fornix);

                //组合
                _fornixs.Add(fornix);
                preFornix = fornix;
            }
            foreach (Fornix fornix in _fornixs)
            {
                //基于相邻顶边,生成顶面
                fornix.createUpFace(_RasterPoints);
                //基于相邻底边,生成底面
                fornix.createDownFace();
            }
            //打印obj
            ObjWriter.writeFornixObj(_fornixs, path, _verNum);
        }
예제 #8
0
        public static VertexCollection getVersFromDEM(string imgpath)
        {
            VertexCollection vc = new VertexCollection();

            //栅格范围:left,top,right,bottom
            //double dProjX = 138542.596197;
            //double dProjY = 177431.143484;
            //double dProjX1 = 141246.33321;
            //double dProjY1 = 173721.13817;
            _ds       = Gdal.Open(imgpath, Access.GA_ReadOnly);
            srcWidth  = _ds.RasterXSize;
            srcHeight = _ds.RasterYSize;
            int bandCount = _ds.RasterCount;

            int[] bandArray = new int[bandCount];
            for (int i = 0; i < bandCount; i++)
            {
                bandArray[i] = i + 1;
            }
            double[] dataArray = new double[srcWidth * srcHeight * bandCount];
            double[] dataArray1 = new double[srcWidth * srcHeight * bandCount];
            double   x, y;

            _ds.ReadRaster(0, 0, srcWidth, srcHeight, dataArray, srcWidth, srcHeight, bandCount, bandArray, 0, 0, 0);
            RasterWriter.writeFornixObj(dataArray, srcWidth, srcHeight, @"E:\Users\LiuXianyu\Documents\ExperimentData\myProject\FornixModelingGDAL\Data\LingYanShan\Export\Raster.txt");
            //获取坐标变换系数
            //0左上角x坐标
            //1东西方向分辨率
            //2旋转角度, 0表示图像 "北方朝上"
            //3左上角y坐标
            //4旋转角度, 0表示图像 "北方朝上"
            //5南北方向分辨率
            _ds.GetGeoTransform(_adfGeoTransform);
            Band band = _ds.GetRasterBand(1);

            band.ComputeRasterMinMax(lim, 0);

            //VIP法筛选DEM点
            //getInnerPointsByVIP(dataArray, dataArray1);

            //固定步长法筛选DEM点
            getInnerPointsByStep(dataArray, dataArray1);

            //根据矩阵数据生成点集
            for (int i = 0; i < srcWidth; ++i)
            {
                for (int j = 0; j < srcHeight; ++j)
                {
                    if (-1.0 != dataArray1[i * srcWidth + j])
                    {
                        Vertex ver = new Vertex();
                        getCoordinateFromMatrix(dataArray1, i, j, out x, out y);
                        ver.X(x);
                        ver.Y(y);
                        //ver.Z(dataArray1[i * srcWidth + j]);
                        ver.Z(GetElevation(x, y));
                        ver.innerPoint = true;
                        vc.addVer(ver);
                    }
                }
            }
            return(vc);
        }
예제 #9
0
        /// <summary>
        /// 通过检查侧边底边线段有无相交(形成意外圈),来消除相交三角面,转而用其最外交点为顶点,生成新的三角面代替
        /// </summary>
        private int removeInsectedFace()
        {
            int              removeLowVersNum = 0; //移去侧面底边顶点个数
            int              i, j, k = 0, idxEdge; //当前线段与其后第idxEdge个线段最后相交
            Triangle         insertedTri;
            Edge             curEdge, testEdge, crossEdge = null;
            Vertex           insertedVer;
            VertexCollection vcDown1 = new VertexCollection();

            for (i = 0; i < this.outSide.edges.Count; ++i)
            {
                curEdge = this.outSide.edges[i];
                idxEdge = 0;
                for (j = i + 2; (i > 0 && j < this.outSide.edges.Count) || (i == 0 && j < this.outSide.edges.Count - 1); ++j)//一个线段的下两个线段才可能与其“相交”,所以从i+2开始
                {
                    testEdge = this.outSide.edges[j];
                    if (curEdge.InsectionJudge(testEdge))
                    {
                        crossEdge = testEdge;
                        idxEdge   = j - i;
                    }
                }
                if (0 == idxEdge)
                {
                    continue;
                }
                if (idxEdge > this.outSide.edges.Count / 2)
                {
                    MessageBox.Show("底边起始点可能处于‘意外圈’中!");//TODO:这种情况还没解决
                }
                removeLowVersNum += (idxEdge - 1);
                //两个线段交点
                insertedVer = curEdge.getCrossPoint(crossEdge);
                //删除意外圈原有三角面,并插入意外圈所有新上三角面
                for (j = i; j <= i + idxEdge; ++j)
                {
                    this.outSide.tris.Remove(this.outSide.edges[j].adjTriName[0]);
                    this.outSide.tris.Remove(this.outSide.edges[j].adjTriName[1]);
                    insertedTri = new Triangle();
                    insertedTri.addPoint(this.outSide.upvers.getVer(j));
                    insertedTri.addPoint(this.outSide.upvers.getVer((j + 1 == this.outSide.edges.Count) ? 0 : j + 1));
                    insertedTri.addPoint(insertedVer);
                    this.outSide.tris.Add(insertedTri.name, insertedTri);
                }
                //插入“意外圈”前端新下三角面
                insertedTri = new Triangle();
                insertedTri.addPoint(this.outSide.upvers.getVer(i));
                insertedTri.addPoint(insertedVer);
                insertedTri.addPoint(this.outSide.lowvers.getVer(i));
                this.outSide.tris.Add(insertedTri.name, insertedTri);
                //插入“意外圈”后端新下三角面
                insertedTri = new Triangle();
                insertedTri.addPoint(this.outSide.upvers.getVer((i + idxEdge + 1 == this.outSide.edges.Count) ? 0 : i + idxEdge + 1));
                insertedTri.addPoint(this.outSide.lowvers.getVer((i + idxEdge + 1 == this.outSide.edges.Count) ? 0 : i + idxEdge + 1));
                insertedTri.addPoint(insertedVer);
                this.outSide.tris.Add(insertedTri.name, insertedTri);
                //当前顶点后的所有顶点ID前移
                for (; j < this.outSide.lowvers.Count; ++j)
                {
                    this.outSide.lowvers.getVer(j).ID -= (idxEdge - 1);
                }
                //往新底面顶点集合中插入已确定的顶点
                for (j = k; j <= i; ++j)
                {
                    vcDown1.addVer(this.outSide.lowvers.getVer(j));
                }
                vcDown1.addVer(insertedVer);
                k = i + idxEdge + 1;
                //向后推进到与当前侧面底边线段无交点的第一个线段
                i += idxEdge;
            }
            //插入剩余的顶点
            for (j = k; j < i; ++j)
            {
                vcDown1.addVer(this.outSide.lowvers.getVer(j));
            }
            this.outSide.lowvers.clear();
            this.outSide.lowvers.addVerCollection(vcDown1);
            return(removeLowVersNum);
        }