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