一段用C#编写的程序,可以自动生成点和Tin,想学习的可以下载看下
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace TIN
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.PictureBox picTIN;
private System.Windows.Forms.Button btnDots;
private System.Windows.Forms.Button btnTIN;
private System.Windows.Forms.TextBox txtNum;
private System.Windows.Forms.Label lblNum;
private Point[] arrDots;
private ArrayList arrEdges=new ArrayList();
private ArrayList arrTris=new ArrayList();
private System.Windows.Forms.Button button1;
private bool doshow;
public class Edge
{
public int Start;//边的起点
public int End;//边的终点
public int LeftTri=-1;//左三角形索引
public int RightTri=-1;//右三角形索引
}
public class Tri
{
public int NodeA;
public int NodeB;
public int NodeC;
public int AdjTriA=-1;
public int AdjTriB=-1;
public int AdjTriC=-1;
}
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.picTIN = new System.Windows.Forms.PictureBox();
this.btnDots = new System.Windows.Forms.Button();
this.btnTIN = new System.Windows.Forms.Button();
this.txtNum = new System.Windows.Forms.TextBox();
this.lblNum = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// picTIN
//
this.picTIN.BackColor = System.Drawing.SystemColors.ControlLightLight;
this.picTIN.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.picTIN.Location = new System.Drawing.Point(8, 8);
this.picTIN.Name = "picTIN";
this.picTIN.Size = new System.Drawing.Size(500, 500);
this.picTIN.TabIndex = 0;
this.picTIN.TabStop = false;
//
// btnDots
//
this.btnDots.Location = new System.Drawing.Point(520, 80);
this.btnDots.Name = "btnDots";
this.btnDots.Size = new System.Drawing.Size(88, 32);
this.btnDots.TabIndex = 1;
this.btnDots.Text = "生成随机点";
this.btnDots.Click += new System.EventHandler(this.btnDots_Click);
//
// btnTIN
//
this.btnTIN.Enabled = false;
this.btnTIN.Location = new System.Drawing.Point(520, 136);
this.btnTIN.Name = "btnTIN";
this.btnTIN.Size = new System.Drawing.Size(88, 32);
this.btnTIN.TabIndex = 2;
this.btnTIN.Text = "生成TIN";
this.btnTIN.Click += new System.EventHandler(this.btnTIN_Click);
//
// txtNum
//
this.txtNum.Location = new System.Drawing.Point(520, 48);
this.txtNum.Name = "txtNum";
this.txtNum.Size = new System.Drawing.Size(80, 21);
this.txtNum.TabIndex = 3;
this.txtNum.Text = "10";
this.txtNum.TextChanged += new System.EventHandler(this.txtNum_TextChanged);
//
// lblNum
//
this.lblNum.Location = new System.Drawing.Point(520, 32);
this.lblNum.Name = "lblNum";
this.lblNum.Size = new System.Drawing.Size(80, 16);
this.lblNum.TabIndex = 4;
this.lblNum.Text = "随机点数目:";
//
// button1
//
this.button1.Enabled = false;
this.button1.Location = new System.Drawing.Point(520, 200);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(88, 32);
this.button1.TabIndex = 5;
this.button1.Text = "演示生成过程";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(624, 518);
this.Controls.Add(this.button1);
this.Controls.Add(this.lblNum);
this.Controls.Add(this.txtNum);
this.Controls.Add(this.btnTIN);
this.Controls.Add(this.btnDots);
this.Controls.Add(this.picTIN);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Name = "Form1";
this.Text = "TIN自动生成演示程序";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void btnDots_Click(object sender, System.EventArgs e)
{
//生成指定数目的随机点,并显示在picTIN里
GeneDots();
}
private void GeneDots()
{
int num=Convert.ToInt32(txtNum.Text);
if(num<3)
MessageBox.Show("点数太少,请输入一个大于3的值");
else if(num>1000)
MessageBox.Show("本程序只用于演示,请勿输入大数以免浪费时间。建议输入1000以内的数");
else
{
arrDots=new Point[num];
Random rdm=new Random();
for(int i=0;i<num;i++)
{
arrDots[i].X=rdm.Next(0,500);
arrDots[i].Y=rdm.Next(0,500);
}
this.picTIN.Paint-=new PaintEventHandler(picTIN_DrawTIN);
this.picTIN.Paint+=new PaintEventHandler(picTIN_DrawDots);
this.picTIN.Refresh();
this.btnTIN.Enabled=true;
this.button1.Enabled=true;
}
}
private void btnTIN_Click(object sender, System.EventArgs e)
{
//this.btnTIN.Enabled=false;
//生成并绘制TIN
doshow=false;
GeneTIN();
}
private void picTIN_DrawDots(object sender, PaintEventArgs e)
{
int num=arrDots.Length;
for(int i=0;i<num;i++)
{
e.Graphics.DrawRectangle(Pens.Red,arrDots[i].X,arrDots[i].Y,1,1);
}
}
private void txtNum_TextChanged(object sender, System.EventArgs e)
{
string txt=txtNum.Text;
int i=txt.Length;
if( i < 1)
return;
for(int m = 0; m < i; m ++)
{
string str = txt.Substring(m, 1);
if( !Char.IsNumber( Convert.ToChar(str) ))
{
txtNum.Text = txtNum.Text.Replace(str, ""); //将非数字文本过滤掉
txtNum.SelectionStart = txtNum.Text.Length;//将光标定位到最后一位
}
}
}
private void picTIN_DrawTIN(object sender, PaintEventArgs e)
{
for(int i=0;i<arrEdges.Count;i++)
{
Edge eg=(Edge)arrEdges[i];
Point pt1,pt2;
pt1=arrDots[eg.Start];
pt2=arrDots[eg.End];
e.Graphics.DrawLine(Pens.Black,pt1,pt2);
}
}
private void GeneTIN()
{
arrEdges.Clear();
arrTris.Clear();
int i,idxStart=0,endTemp,ptindex;
bool isExist;
double angMax,angMin,angTemp,angRcdMax,angRcdTmp,lenMin,lenCur,lenTmp1,lenTmp2;
Edge edge=new Edge();
this.picTIN.Paint-=new PaintEventHandler(picTIN_DrawTIN);
this.picTIN.Paint+=new PaintEventHandler(picTIN_DrawTIN);
//找到边界---(删除不需要的点,从X最小的地方开始找,直至回到起始点)
Point dirCur=new Point();
Point dirTmp1=new Point();
Point dirTmp2=new Point();
Point ptStart=new Point();
for(i=1;i<arrDots.Length;i++)
{
if(arrDots[i].X<arrDots[idxStart].X)
{
idxStart=i;
}
}
endTemp=idxStart-1;
ptStart.X=arrDots[idxStart].X;
ptStart.Y=arrDots[idxStart].Y;
edge.Start=idxStart;
angMin=Math.PI;
dirCur.X=0;
dirCur.Y=500;
while(endTemp!=idxStart)
{
lenCur=Math.Sqrt(dirCur.X*dirCur.X+dirCur.Y*dirCur.Y);
lenMin=1000;
for(i=0;i<arrDots.Length;i++)//找边界
{
if(i!=edge.Start)
{
dirTmp1.X=arrDots[i].X-ptStart.X;
dirTmp1.Y=arrDots[i].Y-ptStart.Y;
lenTmp1=Math.Sqrt(dirTmp1.X*dirTmp1.X+dirTmp1.Y*dirTmp1.Y);
angTemp=Math.Acos((dirCur.X*dirTmp1.X+dirCur.Y*dirTmp1.Y)/(lenTmp1*lenCur));
if(angTemp<angMin)
{
angMin=angTemp;
edge.End=i;
lenMin=lenTmp1;
}
else if(angTemp==angMin && lenTmp1<lenMin)
{
edge.End=i;
lenMin=lenTmp1;
}
}
}
arrEdges.Add(edge);
if(doshow==true)
{
System.Threading.Thread.Sleep(500);
this.picTIN.Refresh();
}
endTemp=edge.End;
edge=new Edge();
angMin=Math.PI;
dirCur.X=arrDots[endTemp].X-ptStart.X;
dirCur.Y=arrDots[endTemp].Y-ptStart.Y;
ptStart=arrDots[endTemp];
edge.Start=endTemp;
}
if(doshow==true)
{
System.Threading.Thread.Sleep(500);
this.picTIN.Refresh();
}
//以下为自动生成TIN
//从第一条边开始,按照先左后右的顺序寻找,找到则加入三角形数组和边数组,没有则继续下一边,直到边到达最后
//注意边可能有两种顺序存储。
for(i=0;i<arrEdges.Count;i++)
{
//取出一条边
edge=new Edge();
edge=(Edge)arrEdges[i];
//先左后右计算扩展点-判断三角形是否存在过(若本边的左三角已存在,则计算右三角)??
if(edge.LeftTri==-1)
{
ptindex=-1;//选中的点的index
dirCur.X=arrDots[edge.End].X-arrDots[edge.Start].X;
dirCur.Y=arrDots[edge.End].Y-arrDots[edge.Start].Y;
angRcdMax=0;//与该边夹角最大值
angMax=0;//最大圆内接角
for(int j=0;j<arrDots.Length;j++)
{
if(j!=edge.Start && j!=edge.End)//排除边的端点
{
dirTmp1.X=arrDots[j].X-arrDots[edge.Start].X;
dirTmp1.Y=arrDots[j].Y-arrDots[edge.Start].Y;
if(dirCur.X*dirTmp1.Y-dirCur.Y*dirTmp1.X<0)//如果该点在左边,则计算
{
//找角度最大的
lenCur=Math.Sqrt(dirCur.X*dirCur.X+dirCur.Y*dirCur.Y);//当前向量长度
lenTmp1=Math.Sqrt(dirTmp1.X*dirTmp1.X+dirTmp1.Y*dirTmp1.Y);
dirTmp2.X=arrDots[j].X-arrDots[edge.End].X;
dirTmp2.Y=arrDots[j].Y-arrDots[edge.End].Y;
lenTmp2=Math.Sqrt(dirTmp2.X*dirTmp2.X+dirTmp2.Y*dirTmp2.Y);
angRcdTmp=Math.Acos((dirCur.X*dirTmp1.X+dirCur.Y*dirTmp1.Y)/(lenTmp1*lenCur));
angTemp=Math.Acos((dirTmp2.X*dirTmp1.X+dirTmp2.Y*dirTmp1.Y)/(lenTmp1*lenTmp2));
if(angTemp>angMax)
{
angMax=angTemp;
angRcdMax=angRcdTmp;
ptindex=j;
}
else if(angTemp==angMax && angRcdMax<angRcdTmp)//相等取最左
{
angRcdMax=angRcdTmp;
ptindex=j;
}
}
}
}
if(ptindex!=-1)//选择有点
{
//记录三角形
Tri tri=new Tri();
tri.NodeA=edge.Start;
tri.NodeB=edge.End;
tri.NodeC=ptindex;
edge.LeftTri=arrTris.Count;
isExist=false;
//记录边1-需要检索是否存在过这条边-由于每条边都先有左三角形,如有三角形加入,必定为右三角形
for(int k=0;k<arrEdges.Count;k++)
{
Edge e=(Edge)arrEdges[k];
if(e.Start==edge.Start && e.End==ptindex)//如果存在过这条边,则记录其右三角形
{
e.RightTri=arrTris.Count;
tri.AdjTriB=e.LeftTri;
isExist=true;
break;
}
else if(e.Start==ptindex && e.End==edge.Start)
{
e.LeftTri=arrTris.Count;
tri.AdjTriB=e.RightTri;
isExist=true;
break;
}
}
if(isExist==false)//如果不存在这条边,则新建一条边
{
Edge edgeadd=new Edge();
edgeadd.Start=ptindex;
edgeadd.End=edge.Start;
edgeadd.LeftTri=arrTris.Count;
arrEdges.Add(edgeadd);
if(doshow==true)
{
System.Threading.Thread.Sleep(500);
this.picTIN.Refresh();
}
}
isExist=false;
//记录边2
for(int k=0;k<arrEdges.Count;k++)
{
Edge e=(Edge)arrEdges[k];
if(e.Start==ptindex && e.End==edge.End)//如果存在过这条边,则记录其右三角形
{
e.RightTri=arrTris.Count;
tri.AdjTriA=e.LeftTri;
isExist=true;
break;
}
else if(e.Start==edge.End && e.End==ptindex)
{
e.LeftTri=arrTris.Count;
tri.AdjTriA=e.RightTri;
isExist=true;
break;
}
}
if(isExist==false)//如果不存在这条边,则新建一条边
{
Edge edgeadd=new Edge();
edgeadd.Start=edge.End;
edgeadd.End=ptindex;
edgeadd.LeftTri=arrTris.Count;
arrEdges.Add(edgeadd);
if(doshow==true)
{
System.Threading.Thread.Sleep(500);
this.picTIN.Refresh();
}
}
tri.AdjTriC=edge.RightTri;//如果edge的右三角形不存在,由if进来可见左三角也不存在,这只能是边界,从而tri.AdjTriC=-1合理
arrTris.Add(tri);//add the tri to the arraylist
}
}
else if(edge.RightTri==-1)//由于最开始的那部分都是边界,只有一个三角形;以后的边都已存在一个三角形,也仅剩余一个,故可以else if
{
//仅在右边找
ptindex=-1;//选中的点的index
dirCur.X=arrDots[edge.End].X-arrDots[edge.Start].X;
dirCur.Y=arrDots[edge.End].Y-arrDots[edge.Start].Y;
angMax=0;//最大角度
angRcdMax=0;//与该边夹角最大值
for(int j=0;j<arrDots.Length;j++)
{
if(j!=edge.Start && j!=edge.End)//排除边的端点
{
lenCur=Math.Sqrt(dirCur.X*dirCur.X+dirCur.Y*dirCur.Y);//当前向量长度
dirTmp1.X=arrDots[j].X-arrDots[edge.Start].X;
dirTmp1.Y=arrDots[j].Y-arrDots[edge.Start].Y;
if(dirCur.X*dirTmp1.Y-dirCur.Y*dirTmp1.X>0)//如果该点在右边,则计算
{
//找角度最大的
lenTmp1=Math.Sqrt(dirTmp1.X*dirTmp1.X+dirTmp1.Y*dirTmp1.Y);
dirTmp2.X=arrDots[j].X-arrDots[edge.End].X;
dirTmp2.Y=arrDots[j].Y-arrDots[edge.End].Y;
lenTmp2=Math.Sqrt(dirTmp2.X*dirTmp2.X+dirTmp2.Y*dirTmp2.Y);
angRcdTmp=Math.Acos((dirCur.X*dirTmp1.X+dirCur.Y*dirTmp1.Y)/(lenTmp1*lenCur));
angTemp=Math.Acos((dirTmp2.X*dirTmp1.X+dirTmp2.Y*dirTmp1.Y)/(lenTmp1*lenTmp2));
if(angTemp>angMax)
{
angMax=angTemp;
angRcdMax=angRcdTmp;
ptindex=j;
}
else if(angTemp==angMax && angRcdTmp>angRcdTmp)//相等取最左
{
angRcdTmp=angRcdTmp;
ptindex=j;
}
}
}
}
if(ptindex!=-1)//选择有点
{
//记录三角形
//记录三角形
Tri tri=new Tri();
tri.NodeA=edge.Start;
tri.NodeB=edge.End;
tri.NodeC=ptindex;
edge.RightTri=arrTris.Count;
isExist=false;
//记录边1-需要检索是否存在过这条边-由于每条边都先有左三角形,如有三角形加入,必定为右三角形
for(int k=0;k<arrEdges.Count;k++)
{
Edge e=(Edge)arrEdges[k];
if(e.Start==ptindex && e.End==edge.Start)//如果存在过这条边,则记录其右三角形
{
e.RightTri=arrTris.Count;
tri.AdjTriB=e.LeftTri;
isExist=true;
break;
}
else if(e.Start==edge.Start && e.End==ptindex)
{
e.LeftTri=arrTris.Count;
tri.AdjTriB=e.RightTri;
isExist=true;
break;
}
}
if(isExist==false)//如果不存在这条边,则新建一条边
{
Edge edgeadd=new Edge();
edgeadd.Start=edge.Start;
edgeadd.End=ptindex;
edgeadd.LeftTri=arrTris.Count;
arrEdges.Add(edgeadd);
if(doshow==true)
{
System.Threading.Thread.Sleep(500);
this.picTIN.Refresh();
}
}
isExist=false;
//记录边2
for(int k=0;k<arrEdges.Count;k++)
{
Edge e=(Edge)arrEdges[k];
if(e.Start==edge.End && e.End==ptindex)//如果存在过这条边,则记录其右三角形
{
e.RightTri=arrTris.Count;
tri.AdjTriA=e.LeftTri;
isExist=true;
break;
}
else if(e.Start==ptindex && e.End==edge.End)
{
e.LeftTri=arrTris.Count;
tri.AdjTriA=e.RightTri;
isExist=true;
break;
}
}
if(isExist==false)//如果不存在这条边,则新建一条边
{
Edge edgeadd=new Edge();
edgeadd.Start=ptindex;
edgeadd.End=edge.End;
edgeadd.LeftTri=arrTris.Count;
arrEdges.Add(edgeadd);
if(doshow==true)
{
System.Threading.Thread.Sleep(500);
this.picTIN.Refresh();
}
}
tri.AdjTriC=edge.LeftTri;//如果edge的左三角形不存在,由if进来可见右三角也不存在,这只能是边界,从而tri.AdjTriC=-1合理
arrTris.Add(tri);//add the tri to the arraylist
}
}
}
this.picTIN.Refresh();
}
private void button1_Click(object sender, System.EventArgs e)
{
doshow=true;
GeneTIN();
}
}
}
来自:http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid=36377&extra=page%3D6%26amp%3Bfilter%3Dtype%26amp%3Btypeid%3D6