主界面
视频演示1
视频演示2
程序框架
部分代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Geometric2.RasterizationClasses;
using OpenTK.Graphics.OpenGL4;
using Geometric2.MatrixHelpers;
using Geometric2.ModelGeneration;
using System.Numerics;
using OpenTK;
using Geometric2.Helpers;
using System.Diagnostics;
using System.Threading;
using System.Drawing;
using Geometric2.Global;
using System.Xml;
using System.Linq;
using Geometric2.Models;
namespace Geometric2
{
public partial class Form1 : Form
{
Thread progressthread;
Thread glthread;
public Form1()
{
InitializeComponent();
InitSolution();
glthread = new Thread(() =>
{
while (true)
{
glControl1.Invalidate();//gl更新
Thread.Sleep(16);
}
});
glthread.Start();//更新GL线程
FormClosing += new FormClosingEventHandler(Form1_Closing);
coursor = new Coursor();//鼠标
millModel = new MillModel(dataModel.Width, dataModel.Height, dataModel.Altitude, dataModel.Divisions_X, dataModel.Divisions_Y, simulationTick, percentCompleted, nonCuttingPart);//铣削元素
coursor.CoursorMode = CoursorMode.Auto;//鼠标自动模式
transformCenterLines.selectedElements = SelectedElements;//变换的中心线:选中元素
this.glControl1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseWheel);//鼠标滚轮事件处理函数
}
//关闭窗口时关闭线程
private void Form1_Closing(object sender,EventArgs e)
{
progressthread.Abort();
glthread.Abort();
//if (this.progressthread.ThreadState== System.Threading.ThreadState.Running)
//{
// progressthread.Abort();
//}
Application.Exit();
}
//窗体加载
private void Form1_Load(object sender, EventArgs e)
{ //开启进度条线程
progressthread = new Thread(() =>
{
while (true)
{
this.Invoke((MethodInvoker)delegate {
progressBar.Value = percentCompleted[0];//更新进度条
if (nonCuttingPart[0] != 0)//无铣削零件
{
errorLabel.Text = "ERROR: MILLING WITH A NON-CUTTING PART";
nonCuttingPart[0] = 0;
}
});
if (percentCompleted[0] == 100)//完成后,重置
{
percentCompleted[0] = 0;
}
Thread.Sleep(50);
}
});
progressthread.Start();//开启进度条更新线程
// UI 初始化
cameraLightCheckBox.Checked = true;
radiousTextBox.Text = "5.0";
drillHeightTextBox.Text = "50";
normalRadioButton.Checked = true;
drillButton.Enabled = false;
}
private List<Vector3> drillPositions;//铣削路径点
private Shader _shader;//路径线着色器
private Shader _millshader;//铣削着色器
private Camera _camera;//相机
private Coursor coursor;//鼠标渲染
private MillModel millModel;//铣削模型
public InitializeDataModel dataModel;//初始数据模型
private bool cameraLight = true;//相机灯光
DrillType drillType = DrillType.Normal;//铣削模拟速度类型:正常
CutterType cutterType = CutterType.Spherical;//球头铣刀
int radious = 50;//半径
int drillHeight = 50;//铣刀高度
int[] simulationTick = new int[] { 0 };//仿真快慢
int[] percentCompleted = new int[] { 0 };//仿真百分比
int[] nonCuttingPart = new int[] { 0 };//无铣削零件
private XyzLines xyzLines = new XyzLines();X Y Z轴 无限长直线
private DrillingLines drillingLines;//铣削路径
private List<Element> Elements = new List<Element>();//元素集合:铣削路径 集合
private List<Element> SelectedElements = new List<Element>();//选中元素
DrawingStatus drawingStatus = DrawingStatus.No;//绘制状态
private TransformCenterLines transformCenterLines = new TransformCenterLines();//变换的中心线
int prev_xPosMouse = -1, prev_yPosMouse = -1;//上一鼠标位置
int torusNumber;//环数
//加载路径文件
private void loadToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.Title = "Select Paths File";
openFileDialog.RestoreDirectory = true;
string fileName = "";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
fileName = openFileDialog.FileName;
List<string> file = new List<string>();//行列表
drillPositions = new List<Vector3>();
foreach (string line in System.IO.File.ReadLines(fileName))
{
file.Add(line);
}
foreach (var line in file)//遍历行,并解析。得到铣削路径坐标
{
string afterX = line.Split('X')[1];
string X = afterX.Split('Y')[0];
string afterY = afterX.Split('Y')[1];
string Y = afterY.Split('Z')[0];
string Z = afterY.Split('Z')[1];
float _x, _y, _z;
if (float.TryParse(X, out _x) && float.TryParse(Y, out _y) && float.TryParse(Z, out _z))
{
drillPositions.Add(new Vector3(_x, _z, -_y));//x,y,z路径点。
if(_z < 0)
{
MessageBox.Show("GIONG TO DRILL UNDER SURFACE");
}
}
}
drillingLines = new DrillingLines(drillPositions);//铣削路径
Element elToRemove = null;//铣削路径线,找到后删除
foreach(var el in Elements)
{
if(el is DrillingLines)
{
elToRemove = el;//找到铣削路径线
}
}
if(elToRemove != null)//存在铣削路径线
{
Elements.Remove(elToRemove);//移除路径元素
drillingLineCheckBox.Checked = false;//不显示路径线条
}
string fileExt = fileName.Split('.').LastOrDefault();//文件后缀
if(fileExt.Length == 3)// kxx xx:为铣刀尺寸代号
{
char drill = fileExt[0];
if(drill == 'k')
{
cutterType = CutterType.Spherical;// 后缀含k,球头铣刀
}
else
{
cutterType = CutterType.Flat;//端铣刀
}
string size = fileExt[1].ToString() + fileExt[2].ToString();
int r;
if (int.TryParse(size, out r))//铣刀尺寸代号
{
radious = r * 10;//半径x10
}
else
{
radious = 50;//默认半径50
}
}
else
{
cutterType = CutterType.Spherical;//默认球头铣刀
radious = 50;//默认直径50
}
if(cutterType == CutterType.Spherical)
{
sphericalRadioButton.Checked = true;//勾选球头铣刀复选框
}
else
{
flatRadioButton.Checked = true;//勾选端铣刀复选框
}
radiousTextBox.Text = (radious / 10.0f).ToString();//显示半径代号
drillButton.Enabled = true;//铣削按钮可用
Elements.Add(drillingLines);//将新加载的铣削路径添加到 元素集合
drillingLines.CreateGlElement(_shader);//创建铣削路径线GL元素:着色器— _shader
}
}
//新建解决方案:设置基板尺寸
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
InitSolution();
}
//勾选绘制铣削路径线
private void drillingLineCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (drillingLines != null)
{
drillingLines.DrawPolyline = drillingLineCheckBox.Checked;
}
}
//相机光照
private void cameraLightCheckBox_CheckedChanged(object sender, EventArgs e)
{
cameraLight = cameraLightCheckBox.Checked;
}
//半径 文本框设置
private void radiousTextBox_TextChanged(object sender, EventArgs e)
{
float r;
if (float.TryParse(radiousTextBox.Text, out r))
{
radious = (int)(r * 10);//半径是设置值的10倍
if (radiousTextBox.Text.Contains(".") && radiousTextBox.Text.Split('.').LastOrDefault().Length > 1 || radiousTextBox.Text.Split('.').Length > 2)
{
radiousTextBox.Text = (radious / 10.0f).ToString();
}
}
else
{
radiousTextBox.Text = (radious / 10.0f).ToString();//解析文本框失败:重置为初始 50/10=5
}
}
//铣削仿真
private void drillButton_Click(object sender, EventArgs e)
{
millModel.DrillAll(drillingLines.drillPoints, cutterType, drillType, radious, drillHeight);
}
//正常速度仿真
private void normalRadioButton_CheckedChanged(object sender, EventArgs e)
{
drillType = DrillType.Normal;
}
//快速仿真
private void quickRadioButton_CheckedChanged(object sender, EventArgs e)
{
drillType = DrillType.Fast;
}
//并行线程仿真
private void parallelRadioButton_CheckedChanged(object sender, EventArgs e)
{
drillType = DrillType.Parallel;
}
//球头铣刀类型
private void sphericalRadioButton_CheckedChanged(object sender, EventArgs e)
{
cutterType = CutterType.Spherical;
}
//端铣刀
private void flatRadioButton_CheckedChanged(object sender, EventArgs e)
{
cutterType = CutterType.Flat;
}
//清空
private void clearToolStripMenuItem_Click(object sender, EventArgs e)
{
if(millModel != null && millModel.topLayer != null)//
{
for(int i=0;i<dataModel.Width;i++)
{
for(int j=0;j<dataModel.Height;j++)
{
millModel.topLayer[i, j] = dataModel.Altitude;// 重置[i,j]坐标处顶层高度
}
}
}
}
private void progressBar_Click(object sender, EventArgs e)
{
}
//修改仿真步长
private void simulationTickTrackBar_Scroll(object sender, EventArgs e)
{
simulationTick[0] = simulationTickTrackBar.Value;
}
//修改铣刀高度
private void drillHeightTextBox_TextChanged(object sender, EventArgs e)
{
float drillH;
if (float.TryParse(drillHeightTextBox.Text, out drillH))
{
drillHeight = (int)(drillH * 10);
if (drillHeightTextBox.Text.Contains(".") && drillHeightTextBox.Text.Split('.').LastOrDefault().Length > 1 || drillHeightTextBox.Text.Split('.').Length > 2)
{
drillHeightTextBox.Text = (drillHeight / 10.0f).ToString();
}
}
else
{
drillHeightTextBox.Text = (drillHeight / 10.0f).ToString();
}
}
//初始化解决方案:设置基板尺寸
private void InitSolution()
{
dataModel = new InitializeDataModel();//初始化数据模型
InitializeData initializeData = new InitializeData(dataModel);//实例化初始化数据对话框
initializeData.ShowDialog();//显示对话框
if(dataModel.Width == -1)//宽度需非-1
{
Environment.Exit(Environment.ExitCode);
}
else//显示修改后的数据
{
widthLabelValue.Text = (dataModel.Width / 10.0f).ToString() + " mm";
heightLabelValue.Text = (dataModel.Height / 10.0f).ToString() + " mm";
altitudeLabelValue.Text = (dataModel.Altitude * 10.0f).ToString() + " mm";
divisionsXLabelValue.Text = (dataModel.Divisions_X).ToString();
divisionsYLabelValue.Text = (dataModel.Divisions_Y).ToString();
}
}
}
}
The End