/// <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); }
/// <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); }
/// <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); }
/// <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); } }
/// <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); }
/// <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); }
/// <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); }
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); }
/// <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); }