Files
Triangle.NET/Triangle.NET/TestApp/FormMain.cs
T
SND\wo80_cp d76842d2f6 Fix Quadtree;
Added topology explorer to test app;

git-svn-id: https://triangle.svn.codeplex.com/svn@74355 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
2014-01-14 21:16:08 +00:00

754 lines
21 KiB
C#

using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using MeshExplorer.Controls;
using MeshExplorer.IO;
using MeshRenderer.Core;
using TriangleNet;
using TriangleNet.Geometry;
using TriangleNet.Tools;
namespace MeshExplorer
{
public partial class FormMain : Form
{
Settings settings;
InputGeometry input;
Mesh mesh;
FormLog frmLog;
FormGenerator frmGenerator;
RenderManager renderManager;
RenderData renderData;
public FormMain()
{
InitializeComponent();
ToolStripManager.Renderer = new DarkToolStripRenderer();
}
private void Form1_Load(object sender, EventArgs e)
{
oldClientSize = this.ClientSize;
settings = new Settings();
renderManager = new RenderManager();
renderManager.CreateDefaultControl();
/*
if (!renderManager.CreateControl("MeshRenderer.SharpGL2.dll", new string[] { "SharpGL.dll" }))
{
renderManager.CreateDefaultControl();
if (frmLog == null)
{
frmLog = new FormLog();
}
frmLog.AddItem("Failed to initialize OpenGL.", true);
}
*/
var control = renderManager.RenderControl;
if (control != null)
{
this.splitContainer1.Panel2.Controls.Add(control);
// Initialize control
control.BackColor = Color.Black;
control.Dock = DockStyle.Fill;
control.Font = new Font("Consolas", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
control.Location = new System.Drawing.Point(0, 0);
control.Name = "renderControl1";
control.Size = new Size(703, 612);
control.TabIndex = 0;
control.Text = "meshRenderer1";
renderManager.Initialize();
}
else
{
DarkMessageBox.Show("Ooops ...", "Failed to initialize renderer.");
}
renderData = new RenderData();
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.F3:
OpenWithDialog();
break;
case Keys.F4:
Save();
break;
case Keys.F5:
Reload();
break;
case Keys.F8:
TriangulateOrRefine();
break;
case Keys.F9:
Smooth();
break;
case Keys.F12:
ShowLog();
break;
}
}
void frmGenerator_InputGenerated(object sender, EventArgs e)
{
this.input = sender as InputGeometry;
if (input != null)
{
settings.CurrentFile = "tmp-" + DateTime.Now.ToString("HH-mm-ss");
HandleNewInput();
}
}
private void btnMesh_Click(object sender, EventArgs e)
{
TriangulateOrRefine();
}
private void btnSmooth_Click(object sender, EventArgs e)
{
Smooth();
}
#region Drag and drop
private void frmDragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
Open(args[0]);
}
}
private void frmDragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
if (args.Length > 1)
{
e.Effect = DragDropEffects.None;
return;
}
string file = args[0].ToLower();
// Check if file extension is known
if (FileProcessor.CanHandleFile(file))
{
e.Effect = DragDropEffects.Copy;
}
}
else
{
e.Effect = DragDropEffects.None;
}
}
#endregion
protected override void OnMouseWheel(MouseEventArgs e)
{
var container = this.splitContainer1.Panel2.ClientRectangle;
System.Drawing.Point pt = e.Location;
pt.Offset(-splitContainer1.SplitterDistance, 0);
if (container.Contains(pt))
{
renderManager.Zoom(((float)pt.X) / container.Width,
((float)pt.Y) / container.Height, e.Delta);
}
base.OnMouseWheel(e);
}
#region Resize event handler
bool isResizing = false;
Size oldClientSize;
private void ResizeHandler(object sender, EventArgs e)
{
// Handle window minimize and maximize
if (!isResizing)
{
renderManager.HandleResize();
}
}
private void ResizeEndHandler(object sender, EventArgs e)
{
isResizing = false;
if (this.ClientSize != this.oldClientSize)
{
this.oldClientSize = this.ClientSize;
renderManager.HandleResize();
}
}
private void ResizeBeginHandler(object sender, EventArgs e)
{
isResizing = true;
}
#endregion
#region State changes
private void LockOnException()
{
btnMesh.Enabled = false;
btnSmooth.Enabled = false;
//menuFileSave.Enabled = false;
//menuFileExport.Enabled = false;
menuViewVoronoi.Enabled = false;
menuToolsCheck.Enabled = false;
menuToolsRcm.Enabled = false;
settings.ExceptionThrown = true;
}
private void HandleNewInput()
{
// Reset mesh
mesh = null;
// Reset state
settings.RefineMode = false;
settings.ExceptionThrown = false;
// Reset buttons
btnMesh.Enabled = true;
btnMesh.Text = "Triangulate";
btnSmooth.Enabled = false;
// Update Statistic view
statisticView.HandleNewInput(input);
// Clear voronoi
menuViewVoronoi.Checked = false;
// Disable menu items
menuFileSave.Enabled = false;
menuFileExport.Enabled = false;
menuViewVoronoi.Enabled = false;
menuToolsCheck.Enabled = false;
menuToolsRcm.Enabled = false;
// Render input
renderData.SetInputGeometry(input);
renderManager.SetData(renderData);
// Update window caption
this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
}
private void HandleMeshImport()
{
// Render mesh
renderData.SetMesh(mesh);
renderManager.SetData(renderData);
//renderManager.Initialize();
// Update window caption
this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
// Update Statistic view
statisticView.HandleMeshImport(input, mesh);
// Set refine mode
btnMesh.Enabled = true;
btnMesh.Text = "Refine";
settings.RefineMode = true;
HandleMeshChange();
}
private void HandleMeshUpdate()
{
// Render mesh
renderData.SetMesh(mesh);
renderManager.SetData(renderData);
// Update Statistic view
statisticView.HandleMeshUpdate(mesh);
HandleMeshChange();
}
private void HandleMeshChange()
{
// Update Statistic view
statisticView.HandleMeshChange(mesh);
// TODO: Should the Voronoi diagram automatically update?
menuViewVoronoi.Checked = false;
// Enable menu items
menuFileSave.Enabled = true;
menuFileExport.Enabled = true;
menuViewVoronoi.Enabled = true;
menuToolsCheck.Enabled = true;
menuToolsRcm.Enabled = true;
}
#endregion
#region Commands
private void OpenWithDialog()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = settings.OfdFilter;
ofd.FilterIndex = settings.OfdFilterIndex;
ofd.InitialDirectory = settings.OfdDirectory;
ofd.FileName = "";
if (ofd.ShowDialog() == DialogResult.OK)
{
if (Open(ofd.FileName))
{
// Update folder settings
settings.OfdFilterIndex = ofd.FilterIndex;
settings.OfdDirectory = Path.GetDirectoryName(ofd.FileName);
}
}
}
private bool Open(string filename)
{
if (FileProcessor.ContainsMeshData(filename))
{
if (DarkMessageBox.Show("Import mesh", Settings.ImportString,
"Do you want to import the mesh?", MessageBoxButtons.YesNo) == DialogResult.OK)
{
input = null;
mesh = FileProcessor.Import(filename);
if (mesh != null)
{
statisticView.UpdateStatistic(mesh);
// Update settings
settings.CurrentFile = Path.GetFileName(filename);
HandleMeshImport();
btnSmooth.Enabled = true; // TODO: Remove
}
// else Message
return true;
}
}
input = FileProcessor.Read(filename);
if (input != null)
{
// Update settings
settings.CurrentFile = Path.GetFileName(filename);
HandleNewInput();
}
// else Message
return true;
}
private void Save()
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = settings.SfdFilter;
sfd.FilterIndex = settings.SfdFilterIndex;
sfd.InitialDirectory = settings.SfdDirectory;
sfd.FileName = "";
if (sfd.ShowDialog() == DialogResult.OK)
{
FileProcessor.Save(sfd.FileName, mesh);
}
}
private void Reload()
{
if (input != null)
{
mesh = null;
settings.RefineMode = false;
settings.ExceptionThrown = false;
HandleNewInput();
}
}
private void TriangulateOrRefine()
{
if ((input == null && !settings.RefineMode) || settings.ExceptionThrown)
{
return;
}
if (settings.RefineMode == false)
{
Triangulate();
if (meshControlView.ParamQualityChecked)
{
btnMesh.Text = "Refine";
btnSmooth.Enabled = mesh.IsPolygon;
}
}
else if (meshControlView.ParamQualityChecked)
{
Refine();
}
}
private void Triangulate()
{
if (input == null) return;
//Stopwatch sw = new Stopwatch();
mesh = new Mesh();
if (meshControlView.ParamConformDelChecked)
{
mesh.Behavior.ConformingDelaunay = true;
}
if (meshControlView.ParamSweeplineChecked)
{
mesh.Behavior.Algorithm = TriangulationAlgorithm.SweepLine;
}
if (meshControlView.ParamQualityChecked)
{
mesh.Behavior.Quality = true;
mesh.Behavior.MinAngle = meshControlView.ParamMinAngleValue;
double maxAngle = meshControlView.ParamMaxAngleValue;
if (maxAngle < 180)
{
mesh.Behavior.MaxAngle = maxAngle;
}
// Ignore area constraints on initial triangulation.
//double area = slMaxArea.Value * 0.01;
//if (area > 0 && area < 1)
//{
// var size = input.Bounds;
// double min = Math.Min(size.Width, size.Height);
// mesh.Behavior.MaxArea, area * min);
//}
}
if (meshControlView.ParamConvexChecked)
{
mesh.Behavior.Convex = true;
}
try
{
//sw.Start();
mesh.Triangulate(input);
//sw.Stop();
statisticView.UpdateStatistic(mesh);
HandleMeshUpdate();
if (meshControlView.ParamQualityChecked)
{
settings.RefineMode = true;
}
}
catch (Exception ex)
{
LockOnException();
DarkMessageBox.Show("Exception - Triangulate", ex.Message, MessageBoxButtons.OK);
}
UpdateLog();
}
private void Refine()
{
if (mesh == null) return;
Stopwatch sw = new Stopwatch();
double area = meshControlView.ParamMaxAreaValue;
if (area > 0 && area < 1)
{
mesh.Behavior.MaxArea = area * statisticView.Statistic.LargestArea;
}
mesh.Behavior.MinAngle = meshControlView.ParamMinAngleValue;
double maxAngle = meshControlView.ParamMaxAngleValue;
if (maxAngle < 180)
{
mesh.Behavior.MaxAngle = maxAngle;
}
try
{
sw.Start();
mesh.Refine();
sw.Stop();
statisticView.UpdateStatistic(mesh);
HandleMeshUpdate();
}
catch (Exception ex)
{
LockOnException();
DarkMessageBox.Show("Exception - Refine", ex.Message, MessageBoxButtons.OK);
}
UpdateLog();
}
private void Renumber()
{
if (mesh == null || settings.ExceptionThrown) return;
bool tmp = Behavior.Verbose;
Behavior.Verbose = true;
mesh.Renumber(NodeNumbering.CuthillMcKee);
ShowLog();
Behavior.Verbose = tmp;
}
private void Smooth()
{
if (mesh == null || settings.ExceptionThrown) return;
if (!mesh.IsPolygon)
{
return;
}
Stopwatch sw = new Stopwatch();
try
{
sw.Start();
mesh.Smooth();
sw.Stop();
statisticView.UpdateStatistic(mesh);
HandleMeshUpdate();
}
catch (Exception ex)
{
LockOnException();
DarkMessageBox.Show("Exception - Smooth", ex.Message, MessageBoxButtons.OK);
}
UpdateLog();
}
private void ShowLog()
{
if (frmLog == null)
{
frmLog = new FormLog();
}
UpdateLog();
if (!frmLog.Visible)
{
frmLog.Show(this);
}
}
private void UpdateLog()
{
if (frmLog != null)
{
frmLog.UpdateItems();
}
}
#endregion
#region Menu Handler
private void menuFileOpen_Click(object sender, EventArgs e)
{
OpenWithDialog();
}
private void menuFileSave_Click(object sender, EventArgs ev)
{
if (mesh != null)
{
Save();
}
}
private void menuFileExport_Click(object sender, EventArgs e)
{
if (mesh != null)
{
FormExport export = new FormExport();
string file = settings.OfdDirectory;
if (!file.EndsWith("\\"))
{
file += "\\";
}
file += settings.CurrentFile;
export.ImageName = Path.ChangeExtension(file, ".png");
if (export.ShowDialog() == DialogResult.OK)
{
int format = export.ImageFormat;
int size = export.ImageSize;
if (format == 1)
{
EpsImage eps = new EpsImage();
eps.Export(this.mesh, export.ImageName, size);
}
else if (format == 2)
{
SvgImage svg = new SvgImage();
svg.Export(this.mesh, export.ImageName, size);
}
else
{
RasterImage img = new RasterImage();
img.ColorScheme = ColorManager.LightScheme();
img.Export(this.mesh, export.ImageName, size);
}
}
}
}
private void menuFileQuit_Click(object sender, EventArgs e)
{
this.Close();
}
private void menuViewVoronoi_Click(object sender, EventArgs e)
{
if (mesh == null)
{
return;
}
if (menuViewVoronoi.Checked)
{
renderManager.ShowVoronoi = false;
menuViewVoronoi.Checked = false;
return;
}
IVoronoi voronoi;
if (mesh.IsPolygon)
{
voronoi = new BoundedVoronoi(mesh);
}
else
{
voronoi = new Voronoi(mesh);
}
renderData.SetVoronoi(voronoi);
renderManager.SetData(renderData);
menuViewVoronoi.Checked = true;
}
private void menuViewLog_Click(object sender, EventArgs e)
{
ShowLog();
}
private void menuToolsGenerator_Click(object sender, EventArgs e)
{
if (frmGenerator == null || frmGenerator.IsDisposed)
{
frmGenerator = new FormGenerator();
frmGenerator.InputGenerated += new EventHandler(frmGenerator_InputGenerated);
}
if (!frmGenerator.Visible)
{
frmGenerator.Show();
}
else
{
frmGenerator.Activate();
}
}
private void menuToolsCheck_Click(object sender, EventArgs e)
{
if (mesh != null)
{
bool isConsistent, isDelaunay;
Behavior.Verbose = true;
mesh.Check(out isConsistent, out isDelaunay);
Behavior.Verbose = false;
ShowLog();
}
}
private void menuToolsTopology_Click(object sender, EventArgs e)
{
(new FormTopology()).ShowDialog(this);
}
private void menuToolsRcm_Click(object sender, EventArgs e)
{
Renumber();
}
#endregion
}
}