基于C#+ArcGIS Engine绘制三维钻孔模型

1、绘制原理

主要使用ArcGIS Engine中提供画圆的方法,以钻孔的中心为圆点绘制圆,然后使用IConstructMultiPatch接口中的ConstructExtrudeFromTo方法实现圆的拉伸,最后对每个深度的品位进行渲染。其生成的钻孔模型如下图所示:

生成带钻孔名的钻孔模型

2、解析数据

对.csv格式的钻孔数据进行解析,其数据格式如下图所示,直接上代码。

钻孔数据格式

 OpenFileDialog openDlg = new OpenFileDialog();

                openDlg.Filter = "钻孔Excel文件|*.csv";
                openDlg.Title = "打开钻孔数据";
                string path = null;
                if (openDlg.ShowDialog() == DialogResult.OK)
                {
                    path = openDlg.FileName;

                }
                DataTable dt = null;
              
                if (File.Exists(path))
                {
                    // 如果文件存在
                    dt = new DataTable();
                    FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);

                    StreamReader sr = new StreamReader(fs, Encoding.Default);

                    string head = sr.ReadLine();
                    string[] headNames = head.Split(',');
                    for (int i = 0; i < headNames.Length; i++)
                    {
                        dt.Columns.Add(headNames[i], typeof(string));
                    }
                    while (!sr.EndOfStream)
                    {
                        //循环读取文件
                        string lineStr = sr.ReadLine();
                        if (lineStr == null || lineStr.Length == 0)
                            continue;
                        string[] values = lineStr.Split(',');
                        //添加行数据
                        DataRow dr = dt.NewRow();
                        for (int i = 0; i < values.Length; i++)
                        {
                            dr[i] = values[i];
                        }
                        dt.Rows.Add(dr);

                    }
                    fs.Close();
                    sr.Close();

                }

                int a = dt.Columns.Count;
                int b = dt.Rows.Count;
                string str = dt.Rows[0][0].ToString();

                
                double maxpw = double.MinValue;
                double minpw = double.MaxValue;
                for (int i = 0; i < b; i++)
                {
                    string pinwei = dt.Rows[i][3].ToString();
                    double PW = Convert.ToDouble(pinwei);
                    if (PW > maxpw) maxpw = PW;
                    else if (PW < minpw) minpw = PW;
                }

                //生成系数
                double A = 120;
                double distmm = (maxpw - minpw) / 2;
                double f = Math.PI / distmm;

3、绘制圆以及对圆进行拉伸成圆柱的方法

  /// <summary>
        /// 绘制钻孔方法
        /// </summary>
        /// <param name="point">坐标点</param>
        /// <param name="radius">半径</param>
        /// <param name="multiPatchGraphicsContainer3D"></param>
        /// <param name="FromZ"></param>
        /// <param name="ToZ"></param>
        /// <param name="i"></param>
        /// <param name="j"></param>
        /// <param name="h"></param>
        public void DrawZK(IPoint point, double radius, IGraphicsContainer3D multiPatchGraphicsContainer3D, double FromZ, double ToZ,int i, int j,int h)
        {

            IConstructCircularArc pConstructCircularArc = new CircularArcClass();
            pConstructCircularArc.ConstructCircle(point, radius, false);
            ICircularArc pArc = pConstructCircularArc as ICircularArc;
            ISegment pSegment1 = pArc as ISegment;
            ISegmentCollection pSegCollection = new RingClass();
            object o = Type.Missing;
            pSegCollection.AddSegment(pSegment1, ref o, ref o);
            IRing pRing = pSegCollection as IRing;
            pRing.Close();
            IGeometryCollection pGeometryColl = new PolygonClass();
            pGeometryColl.AddGeometry(pRing, ref o, ref o);

            IGeometry polygonGeometry = pGeometryColl as IGeometry;
            ITopologicalOperator topologicalOperator = polygonGeometry as ITopologicalOperator;
            topologicalOperator.Simplify();
            IConstructMultiPatch constructMultiPatch = new MultiPatchClass();
            constructMultiPatch.ConstructExtrudeFromTo(FromZ, ToZ, polygonGeometry);
            //return constructMultiPatch as IGeometry;




            IGeometry geo = constructMultiPatch as IGeometry;

            IElement element = ConstructMultiPatchElement(geo, i, j, h);
            //multiPatchGraphicsContainer3D.DeleteAllElements();
            
            multiPatchGraphicsContainer3D.AddElement(element);
           
         

        
        }

4、为绘制的钻孔显示各自的名称

显示钻孔名称的代码如下:

   /// <summary>
        /// 绘制文本
        /// </summary>
        /// <param name="pt">文字坐标</param>
        /// <param name="text">绘制的文字</param>
        /// <param name="Fsize">大小</param>
        /// <param name="r"></param>
        /// <param name="g"></param>
        /// <param name="b"></param>
        public  void DrawText(IPoint pt, string text, double Fsize, int r, int g, int b)
        {
            IPoint point = new PointClass();
         
            point = pt;
            point.Z = shengdu+0.5;
            
            IText3DElement Ptext3DElement = new Text3DElementClass();
            Ptext3DElement.AnchorPoint = point;
            Ptext3DElement.Text = text;       
            Ptext3DElement.BoldFont = false;      
            Ptext3DElement.Alignment = esriT3DAlignment.esriT3DAlignHorizontal;      
            Ptext3DElement.AxisRotation = esriT3DRotationAxis.esriT3DRotateAxisZ;
            Ptext3DElement.ZAxisScale = 1;
            Ptext3DElement.Justification = esriT3DJustification.esriT3DJustifyCenter;
            Ptext3DElement.Height = Fsize;
            Ptext3DElement.Depth = Fsize / 4;
            Ptext3DElement.OrientationPlane = esriT3DOrientationPlane.esriT3DPlaneXZ;
            IRgbColor Fcolor = new RgbColorClass();
            Fcolor.Red = r;
            Fcolor.Green = g;
            Fcolor.Blue = b;
            //IElement ep = Ptext3DElement as IElement;
            //ep.Geometry = pt;
            IFillSymbol pFillSymbol = new SimpleFillSymbol();
            pFillSymbol.Color = Fcolor;
            IFillShapeElement pFillShapeElement = Ptext3DElement as IFillShapeElement;
            pFillShapeElement.Symbol = pFillSymbol;


            multiPatchGraphicsContainer3D.AddElement(Ptext3DElement as IElement);
            Ptext3DElement.Update();
        
        }

5、调用以上的方法生成圆柱

这里需要注意的是需要对钻孔的深度进行排序处理,不然后期的生成的钻孔渲染会出现很大的问题。至此,就可以生成上图的钻孔模型。

 //生成系数
                double A = 120;
                double distmm = (maxpw - minpw) / 2;
                double f = Math.PI / distmm;


                for (int i = 0; i < b; i++)
                {
                    string s = dt.Rows[i][0].ToString();
                    string t = dt.Rows[i][1].ToString();
                    string Depth = dt.Rows[i][2].ToString();
                    double depth = Convert.ToDouble(Depth);
                    string pinwei = dt.Rows[i][3].ToString();
                    string name = dt.Rows[i][4].ToString();
                    double PW = Convert.ToDouble(pinwei);
                    double S = Convert.ToDouble(s);
                    double T = Convert.ToDouble(t);
                    point.X = S;
                    point.Y = T;


                    //if (PW > 5)
                    //{
                    //    PW *= 10;
                    //}
                    //else {
                    //    PW *= 100;
                    //}
                    int tcolor = (Convert.ToInt32(A * Math.Sin(f * (PW - distmm)) + 120));
                    int bcolor = tcolor < 0 ? 0 : tcolor;

                    // 测试深度的选取
                    double nearepth = depth;

                    for (int j = 0; j < b; j++)
                    {
                        if (dt.Rows[j][4].ToString() == name)
                        {
                            double tempdepth = Convert.ToDouble(dt.Rows[j][2].ToString());
                            
                            if (j == i)
                            {
                                continue;
                            }
                            else
                            {
                                if (tempdepth < depth)
                                {
                                    if ((depth - tempdepth) < nearepth)
                                    {
                                        nearepth = depth - tempdepth;
                                    }
                                }
                            }
                        }
                    }

                    for (int k = 0; k < b; k++)
                    {
                        if (dt.Rows[k][4].ToString() == name)
                        {
                            double tao = Convert.ToDouble(dt.Rows[k][2].ToString());
                            shengdu = tao;
                        }
                    }


                    string x = textBox1.Text;
                    double X = Convert.ToDouble(x);
                    DrawZK(point, X, multiPatchGraphicsContainer3D, depth - nearepth, depth,//max--min
                        160,
                        bcolor % 250,
                        30);
                    // point.Z = depth;
                    //shengdu = depth;
                   // ThreadStart childfref = new ThreadStart(delegate() { DrawText(point, name, 1.2, 255, 0, 0); });
                    //Thread childThread=new Thread(delegate() { DrawText(point, name, 1.2, 255, 0, 0); });
                    //childThread.Start();
                   DrawText(point, name, 1.2, 255, 0, 0);

                }
            }
发布了6 篇原创文章 · 获赞 8 · 访问量 779

猜你喜欢

转载自blog.csdn.net/sinat_39271486/article/details/103529661