From 54f5c94eba7c12465642308089ddf339ad765873 Mon Sep 17 00:00:00 2001 From: "SND\\wo80_cp" Date: Mon, 11 Jun 2012 16:52:41 +0000 Subject: [PATCH] Mesh file format and I/O tweaks git-svn-id: https://triangle.svn.codeplex.com/svn@67986 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5 --- .../TestApp/Controls/RendererControl.cs | 20 +- Triangle.NET/TestApp/DarkMessageBox.cs | 91 +-- Triangle.NET/TestApp/Examples.cs | 2 +- Triangle.NET/TestApp/FormMain.Designer.cs | 384 ++++++------ Triangle.NET/TestApp/FormMain.cs | 121 ++-- Triangle.NET/TestApp/IO/FileProcessor.cs | 56 +- Triangle.NET/TestApp/IO/Formats/DatFile.cs | 23 +- Triangle.NET/TestApp/IO/Formats/JsonFile.cs | 550 +++++++++++++++--- .../TestApp/IO/Formats/TriangleFile.cs | 109 +--- .../IO/{IMeshFormat.cs => IMeshFile.cs} | 15 +- Triangle.NET/TestApp/Mesh Explorer.csproj | 2 +- Triangle.NET/TestApp/Rendering/RenderData.cs | 12 + Triangle.NET/TestApp/Settings.cs | 16 +- Triangle.NET/Triangle/IO/DataReader.cs | 10 +- Triangle.NET/Triangle/IO/FileReader.cs | 107 ++-- Triangle.NET/Triangle/IO/FileWriter.cs | 8 +- Triangle.NET/Triangle/IO/IGeometryFormat.cs | 27 + Triangle.NET/Triangle/IO/IMeshFormat.cs | 34 ++ Triangle.NET/Triangle/IO/TriangleFormat.cs | 67 +++ Triangle.NET/Triangle/Mesh.cs | 30 +- Triangle.NET/Triangle/Quality.cs | 4 +- Triangle.NET/Triangle/Triangle.csproj | 3 + 22 files changed, 1148 insertions(+), 543 deletions(-) rename Triangle.NET/TestApp/IO/{IMeshFormat.cs => IMeshFile.cs} (50%) create mode 100644 Triangle.NET/Triangle/IO/IGeometryFormat.cs create mode 100644 Triangle.NET/Triangle/IO/IMeshFormat.cs create mode 100644 Triangle.NET/Triangle/IO/TriangleFormat.cs diff --git a/Triangle.NET/TestApp/Controls/RendererControl.cs b/Triangle.NET/TestApp/Controls/RendererControl.cs index 79d20bc..955b9a9 100644 --- a/Triangle.NET/TestApp/Controls/RendererControl.cs +++ b/Triangle.NET/TestApp/Controls/RendererControl.cs @@ -111,20 +111,34 @@ namespace MeshExplorer.Controls this.Render(); } - public void SetData(Mesh mesh) + public void SetData(Mesh mesh, bool initZoom) { data.SetData(mesh); - meshRenderer = new MeshRenderer(data); + if (initZoom) + { + // Reset the zoom on new data + zoom.Initialize(this.ClientRectangle, data.Bounds); + } + meshRenderer = new MeshRenderer(data); voronoiRenderer = new VoronoiRenderer(mesh); - voronoiRenderer.Update(); + + if (showVoronoi) + { + voronoiRenderer.Update(); + } initialized = true; this.Render(); } + public void SetData(Mesh mesh) + { + SetData(mesh, false); + } + public void Zoom(PointF location, int delta) { if (!initialized) return; diff --git a/Triangle.NET/TestApp/DarkMessageBox.cs b/Triangle.NET/TestApp/DarkMessageBox.cs index 4fc2a22..517791c 100644 --- a/Triangle.NET/TestApp/DarkMessageBox.cs +++ b/Triangle.NET/TestApp/DarkMessageBox.cs @@ -39,31 +39,31 @@ namespace MeshExplorer /// private void InitializeComponent() { - this.btnClose = new MeshExplorer.Controls.DarkButton(); - this.btnShowLog = new MeshExplorer.Controls.DarkButton(); + this.btnCancel = new MeshExplorer.Controls.DarkButton(); + this.btnOk = new MeshExplorer.Controls.DarkButton(); this.lbMessage = new System.Windows.Forms.Label(); this.lbInfo = new System.Windows.Forms.Label(); this.SuspendLayout(); // - // btnClose + // btnCancel // - this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.btnClose.Location = new System.Drawing.Point(336, 87); - this.btnClose.Name = "btnClose"; - this.btnClose.Size = new System.Drawing.Size(92, 23); - this.btnClose.TabIndex = 0; - this.btnClose.Text = "Close"; - this.btnClose.UseVisualStyleBackColor = true; + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(336, 87); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(92, 23); + this.btnCancel.TabIndex = 0; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; // - // btnShowLog + // btnOk // - this.btnShowLog.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btnShowLog.Location = new System.Drawing.Point(234, 87); - this.btnShowLog.Name = "btnShowLog"; - this.btnShowLog.Size = new System.Drawing.Size(92, 23); - this.btnShowLog.TabIndex = 1; - this.btnShowLog.Text = "Show Log"; - this.btnShowLog.UseVisualStyleBackColor = true; + this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnOk.Location = new System.Drawing.Point(234, 87); + this.btnOk.Name = "btnOk"; + this.btnOk.Size = new System.Drawing.Size(92, 23); + this.btnOk.TabIndex = 1; + this.btnOk.Text = "Ok"; + this.btnOk.UseVisualStyleBackColor = true; // // lbMessage // @@ -94,8 +94,8 @@ namespace MeshExplorer this.ClientSize = new System.Drawing.Size(436, 118); this.Controls.Add(this.lbInfo); this.Controls.Add(this.lbMessage); - this.Controls.Add(this.btnShowLog); - this.Controls.Add(this.btnClose); + this.Controls.Add(this.btnOk); + this.Controls.Add(this.btnCancel); this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; @@ -111,10 +111,10 @@ namespace MeshExplorer #endregion - private Controls.DarkButton btnClose; + private Controls.DarkButton btnCancel; private Label lbMessage; private Label lbInfo; - private Controls.DarkButton btnShowLog; + private Controls.DarkButton btnOk; #endregion @@ -133,32 +133,53 @@ namespace MeshExplorer e.Graphics.FillRectangle(Brushes.DimGray, rect); } - public static DialogResult Show(string title, string message, string info, bool log) + public static DialogResult Show(string title, string message, string info, MessageBoxButtons buttons) { - DarkMessageBox m = new DarkMessageBox(); + DarkMessageBox dialog = new DarkMessageBox(); - if (!log) - { - m.btnShowLog.Enabled = false; - m.btnShowLog.Visible = false; - } + SetButtonsText(dialog, buttons); - m.Text = title; + dialog.Text = title; - m.lbInfo.Text = info; - m.lbMessage.Text = message; + dialog.lbInfo.Text = info; + dialog.lbMessage.Text = message; - return m.ShowDialog(); + return dialog.ShowDialog(); } public static DialogResult Show(string title, string message, string info) { - return Show(title, message, info, false); + return Show(title, message, info, MessageBoxButtons.OKCancel); + } + + public static DialogResult Show(string title, string message, MessageBoxButtons buttons) + { + return Show(title, message, "", buttons); } public static DialogResult Show(string title, string message) { - return Show(title, message, "", false); + return Show(title, message, "", MessageBoxButtons.OKCancel); + } + + private static void SetButtonsText(DarkMessageBox dialog, MessageBoxButtons buttons) + { + if (buttons == MessageBoxButtons.OKCancel) + { + dialog.btnOk.Text = "OK"; + dialog.btnCancel.Text = "Cancel"; + } + else if (buttons == MessageBoxButtons.YesNo) + { + dialog.btnOk.Text = "Yes"; + dialog.btnCancel.Text = "No"; + } + else + { + dialog.btnCancel.Text = "Close"; + dialog.btnOk.Visible = false; + dialog.btnOk.Enabled = false; + } } } } diff --git a/Triangle.NET/TestApp/Examples.cs b/Triangle.NET/TestApp/Examples.cs index 25de7a0..e2802b4 100644 --- a/Triangle.NET/TestApp/Examples.cs +++ b/Triangle.NET/TestApp/Examples.cs @@ -42,7 +42,7 @@ namespace MeshExplorer // Read face polygon file and gernerate the delaunay triangulation // of the PSLG. We reuse the mesh instance here. - InputGeometry data = FileReader.ReadFile(pathToData + "face.poly"); + InputGeometry data = FileReader.Read(pathToData + "face.poly"); mesh.Triangulate(data); imageWriter.WritePng(mesh, "face.png", 200); diff --git a/Triangle.NET/TestApp/FormMain.Designer.cs b/Triangle.NET/TestApp/FormMain.Designer.cs index 43b0b6e..a73a36f 100644 --- a/Triangle.NET/TestApp/FormMain.Designer.cs +++ b/Triangle.NET/TestApp/FormMain.Designer.cs @@ -29,31 +29,31 @@ private void InitializeComponent() { this.splitContainer1 = new System.Windows.Forms.SplitContainer(); - this.btnSmooth = new MeshExplorer.Controls.DarkButton(); - this.btnMesh = new MeshExplorer.Controls.DarkButton(); this.flatTabControl1 = new MeshExplorer.Controls.DarkTabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); - this.label20 = new System.Windows.Forms.Label(); + this.btnSmooth = new MeshExplorer.Controls.DarkButton(); this.lbMaxArea = new System.Windows.Forms.Label(); + this.btnMesh = new MeshExplorer.Controls.DarkButton(); this.label6 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); this.lbMinAngle = new System.Windows.Forms.Label(); - this.label3 = new System.Windows.Forms.Label(); this.label9 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.lbNumSeg = new System.Windows.Forms.Label(); this.label8 = new System.Windows.Forms.Label(); - this.lbNumSeg2 = new System.Windows.Forms.Label(); this.label5 = new System.Windows.Forms.Label(); - this.lbNumTri = new System.Windows.Forms.Label(); this.slMaxArea = new MeshExplorer.Controls.DarkSlider(); - this.lbNumTri2 = new System.Windows.Forms.Label(); this.slMinAngle = new MeshExplorer.Controls.DarkSlider(); - this.lbNumVert = new System.Windows.Forms.Label(); this.cbConvex = new MeshExplorer.Controls.DarkCheckBox(); - this.lbNumVert2 = new System.Windows.Forms.Label(); this.cbQuality = new MeshExplorer.Controls.DarkCheckBox(); this.tabPage2 = new System.Windows.Forms.TabPage(); + this.label20 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.lbNumSeg = new System.Windows.Forms.Label(); + this.lbNumSeg2 = new System.Windows.Forms.Label(); + this.lbNumTri = new System.Windows.Forms.Label(); + this.lbNumTri2 = new System.Windows.Forms.Label(); + this.lbNumVert = new System.Windows.Forms.Label(); + this.lbNumVert2 = new System.Windows.Forms.Label(); this.label32 = new System.Windows.Forms.Label(); this.label13 = new System.Windows.Forms.Label(); this.label31 = new System.Windows.Forms.Label(); @@ -124,8 +124,6 @@ // splitContainer1.Panel1 // this.splitContainer1.Panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76))))); - this.splitContainer1.Panel1.Controls.Add(this.btnSmooth); - this.splitContainer1.Panel1.Controls.Add(this.btnMesh); this.splitContainer1.Panel1.Controls.Add(this.flatTabControl1); this.splitContainer1.Panel1.Controls.Add(this.menuStrip1); // @@ -138,80 +136,50 @@ this.splitContainer1.SplitterWidth = 1; this.splitContainer1.TabIndex = 0; // - // btnSmooth - // - this.btnSmooth.Enabled = false; - this.btnSmooth.Location = new System.Drawing.Point(149, 39); - this.btnSmooth.Name = "btnSmooth"; - this.btnSmooth.Size = new System.Drawing.Size(126, 23); - this.btnSmooth.TabIndex = 12; - this.btnSmooth.Text = "Smooth"; - this.btnSmooth.UseVisualStyleBackColor = true; - this.btnSmooth.Click += new System.EventHandler(this.btnSmooth_Click); - // - // btnMesh - // - this.btnMesh.Enabled = false; - this.btnMesh.Location = new System.Drawing.Point(3, 39); - this.btnMesh.Name = "btnMesh"; - this.btnMesh.Size = new System.Drawing.Size(126, 23); - this.btnMesh.TabIndex = 12; - this.btnMesh.Text = "Triangulate"; - this.btnMesh.UseVisualStyleBackColor = true; - this.btnMesh.Click += new System.EventHandler(this.btnMesh_Click); - // // flatTabControl1 // this.flatTabControl1.Alignment = System.Windows.Forms.TabAlignment.Bottom; this.flatTabControl1.Controls.Add(this.tabPage1); this.flatTabControl1.Controls.Add(this.tabPage2); this.flatTabControl1.Controls.Add(this.tabPage3); - this.flatTabControl1.Location = new System.Drawing.Point(0, 83); + this.flatTabControl1.Location = new System.Drawing.Point(0, 27); this.flatTabControl1.Name = "flatTabControl1"; this.flatTabControl1.SelectedIndex = 0; - this.flatTabControl1.Size = new System.Drawing.Size(280, 528); + this.flatTabControl1.Size = new System.Drawing.Size(280, 584); this.flatTabControl1.TabIndex = 1; // // tabPage1 // this.tabPage1.BackColor = System.Drawing.Color.DimGray; - this.tabPage1.Controls.Add(this.label20); + this.tabPage1.Controls.Add(this.btnSmooth); this.tabPage1.Controls.Add(this.lbMaxArea); + this.tabPage1.Controls.Add(this.btnMesh); this.tabPage1.Controls.Add(this.label6); - this.tabPage1.Controls.Add(this.label4); this.tabPage1.Controls.Add(this.lbMinAngle); - this.tabPage1.Controls.Add(this.label3); this.tabPage1.Controls.Add(this.label9); - this.tabPage1.Controls.Add(this.label2); - this.tabPage1.Controls.Add(this.lbNumSeg); this.tabPage1.Controls.Add(this.label8); - this.tabPage1.Controls.Add(this.lbNumSeg2); this.tabPage1.Controls.Add(this.label5); - this.tabPage1.Controls.Add(this.lbNumTri); this.tabPage1.Controls.Add(this.slMaxArea); - this.tabPage1.Controls.Add(this.lbNumTri2); this.tabPage1.Controls.Add(this.slMinAngle); - this.tabPage1.Controls.Add(this.lbNumVert); this.tabPage1.Controls.Add(this.cbConvex); - this.tabPage1.Controls.Add(this.lbNumVert2); this.tabPage1.Controls.Add(this.cbQuality); this.tabPage1.ForeColor = System.Drawing.Color.DarkGray; this.tabPage1.Location = new System.Drawing.Point(4, 4); this.tabPage1.Name = "tabPage1"; - this.tabPage1.Size = new System.Drawing.Size(272, 499); + this.tabPage1.Size = new System.Drawing.Size(272, 555); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "Mesh Control"; // - // label20 + // btnSmooth // - this.label20.AutoSize = true; - this.label20.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label20.ForeColor = System.Drawing.Color.White; - this.label20.Location = new System.Drawing.Point(8, 12); - this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(89, 13); - this.label20.TabIndex = 15; - this.label20.Text = "Mesh Elements:"; + this.btnSmooth.Enabled = false; + this.btnSmooth.Location = new System.Drawing.Point(144, 16); + this.btnSmooth.Name = "btnSmooth"; + this.btnSmooth.Size = new System.Drawing.Size(115, 23); + this.btnSmooth.TabIndex = 12; + this.btnSmooth.Text = "Smooth"; + this.btnSmooth.UseVisualStyleBackColor = true; + this.btnSmooth.Click += new System.EventHandler(this.btnSmooth_Click); // // lbMaxArea // @@ -223,26 +191,27 @@ this.lbMaxArea.TabIndex = 14; this.lbMaxArea.Text = "0"; // + // btnMesh + // + this.btnMesh.Enabled = false; + this.btnMesh.Location = new System.Drawing.Point(11, 16); + this.btnMesh.Name = "btnMesh"; + this.btnMesh.Size = new System.Drawing.Size(115, 23); + this.btnMesh.TabIndex = 12; + this.btnMesh.Text = "Triangulate"; + this.btnMesh.UseVisualStyleBackColor = true; + this.btnMesh.Click += new System.EventHandler(this.btnMesh_Click); + // // label6 // this.label6.AutoSize = true; this.label6.ForeColor = System.Drawing.Color.White; - this.label6.Location = new System.Drawing.Point(8, 191); + this.label6.Location = new System.Drawing.Point(8, 126); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(81, 13); this.label6.TabIndex = 14; this.label6.Text = "Maximum area"; // - // label4 - // - this.label4.AutoSize = true; - this.label4.ForeColor = System.Drawing.Color.DarkGray; - this.label4.Location = new System.Drawing.Point(8, 59); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(60, 13); - this.label4.TabIndex = 7; - this.label4.Text = "Segments:"; - // // lbMinAngle // this.lbMinAngle.AutoSize = true; @@ -253,92 +222,42 @@ this.lbMinAngle.TabIndex = 14; this.lbMinAngle.Text = "20"; // - // label3 - // - this.label3.AutoSize = true; - this.label3.ForeColor = System.Drawing.Color.DarkGray; - this.label3.Location = new System.Drawing.Point(8, 80); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(56, 13); - this.label3.TabIndex = 9; - this.label3.Text = "Triangles:"; - // // label9 // this.label9.BackColor = System.Drawing.Color.DimGray; this.label9.ForeColor = System.Drawing.Color.DarkGray; - this.label9.Location = new System.Drawing.Point(8, 296); + this.label9.Location = new System.Drawing.Point(8, 231); this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(258, 33); this.label9.TabIndex = 14; this.label9.Text = "Use the convex mesh option, if the convex hull should be included in the output."; // - // label2 - // - this.label2.AutoSize = true; - this.label2.ForeColor = System.Drawing.Color.DarkGray; - this.label2.Location = new System.Drawing.Point(8, 39); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(50, 13); - this.label2.TabIndex = 11; - this.label2.Text = "Vertices:"; - // - // lbNumSeg - // - this.lbNumSeg.ForeColor = System.Drawing.Color.White; - this.lbNumSeg.Location = new System.Drawing.Point(92, 59); - this.lbNumSeg.Name = "lbNumSeg"; - this.lbNumSeg.Size = new System.Drawing.Size(70, 13); - this.lbNumSeg.TabIndex = 3; - this.lbNumSeg.Text = "-"; - this.lbNumSeg.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // // label8 // this.label8.BackColor = System.Drawing.Color.DimGray; this.label8.ForeColor = System.Drawing.Color.DarkGray; - this.label8.Location = new System.Drawing.Point(8, 215); + this.label8.Location = new System.Drawing.Point(8, 150); this.label8.Name = "label8"; this.label8.Size = new System.Drawing.Size(258, 33); this.label8.TabIndex = 14; this.label8.Text = "Hint: maximum area values of 0 or 1 will be irgnored (no area constraints are set" + ")."; - // - // lbNumSeg2 - // - this.lbNumSeg2.ForeColor = System.Drawing.Color.DarkGray; - this.lbNumSeg2.Location = new System.Drawing.Point(182, 59); - this.lbNumSeg2.Name = "lbNumSeg2"; - this.lbNumSeg2.Size = new System.Drawing.Size(70, 13); - this.lbNumSeg2.TabIndex = 3; - this.lbNumSeg2.Text = "-"; - this.lbNumSeg2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // label5 // this.label5.AutoSize = true; this.label5.ForeColor = System.Drawing.Color.White; - this.label5.Location = new System.Drawing.Point(8, 169); + this.label5.Location = new System.Drawing.Point(8, 104); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(87, 13); this.label5.TabIndex = 14; this.label5.Text = "Minimum angle"; // - // lbNumTri - // - this.lbNumTri.ForeColor = System.Drawing.Color.White; - this.lbNumTri.Location = new System.Drawing.Point(92, 80); - this.lbNumTri.Name = "lbNumTri"; - this.lbNumTri.Size = new System.Drawing.Size(70, 13); - this.lbNumTri.TabIndex = 2; - this.lbNumTri.Text = "-"; - this.lbNumTri.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // // slMaxArea // this.slMaxArea.BackColor = System.Drawing.Color.Transparent; this.slMaxArea.CriticalPercent = ((uint)(0u)); - this.slMaxArea.Location = new System.Drawing.Point(102, 188); + this.slMaxArea.Location = new System.Drawing.Point(102, 123); this.slMaxArea.Maximum = 100; this.slMaxArea.Minimum = 0; this.slMaxArea.Name = "slMaxArea"; @@ -348,21 +267,11 @@ this.slMaxArea.Value = 0; this.slMaxArea.ValueChanging += new System.EventHandler(this.slMaxArea_ValueChanging); // - // lbNumTri2 - // - this.lbNumTri2.ForeColor = System.Drawing.Color.DarkGray; - this.lbNumTri2.Location = new System.Drawing.Point(182, 80); - this.lbNumTri2.Name = "lbNumTri2"; - this.lbNumTri2.Size = new System.Drawing.Size(70, 13); - this.lbNumTri2.TabIndex = 2; - this.lbNumTri2.Text = "-"; - this.lbNumTri2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // // slMinAngle // this.slMinAngle.BackColor = System.Drawing.Color.Transparent; this.slMinAngle.CriticalPercent = ((uint)(89u)); - this.slMinAngle.Location = new System.Drawing.Point(102, 166); + this.slMinAngle.Location = new System.Drawing.Point(102, 101); this.slMinAngle.Maximum = 100; this.slMinAngle.Minimum = 0; this.slMinAngle.Name = "slMinAngle"; @@ -372,42 +281,22 @@ this.slMinAngle.Value = 50; this.slMinAngle.ValueChanging += new System.EventHandler(this.slMinAngle_ValueChanging); // - // lbNumVert - // - this.lbNumVert.ForeColor = System.Drawing.Color.White; - this.lbNumVert.Location = new System.Drawing.Point(92, 39); - this.lbNumVert.Name = "lbNumVert"; - this.lbNumVert.Size = new System.Drawing.Size(70, 13); - this.lbNumVert.TabIndex = 4; - this.lbNumVert.Text = "-"; - this.lbNumVert.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // // cbConvex // this.cbConvex.BackColor = System.Drawing.Color.DimGray; this.cbConvex.Checked = false; - this.cbConvex.Location = new System.Drawing.Point(11, 276); + this.cbConvex.Location = new System.Drawing.Point(11, 211); this.cbConvex.Name = "cbConvex"; this.cbConvex.Size = new System.Drawing.Size(115, 17); this.cbConvex.TabIndex = 0; this.cbConvex.Text = "Convex mesh"; this.cbConvex.UseVisualStyleBackColor = false; // - // lbNumVert2 - // - this.lbNumVert2.ForeColor = System.Drawing.Color.DarkGray; - this.lbNumVert2.Location = new System.Drawing.Point(182, 39); - this.lbNumVert2.Name = "lbNumVert2"; - this.lbNumVert2.Size = new System.Drawing.Size(70, 13); - this.lbNumVert2.TabIndex = 4; - this.lbNumVert2.Text = "-"; - this.lbNumVert2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // // cbQuality // this.cbQuality.BackColor = System.Drawing.Color.DimGray; this.cbQuality.Checked = false; - this.cbQuality.Location = new System.Drawing.Point(11, 143); + this.cbQuality.Location = new System.Drawing.Point(11, 78); this.cbQuality.Name = "cbQuality"; this.cbQuality.Size = new System.Drawing.Size(115, 17); this.cbQuality.TabIndex = 0; @@ -417,6 +306,16 @@ // tabPage2 // this.tabPage2.BackColor = System.Drawing.Color.DimGray; + this.tabPage2.Controls.Add(this.label20); + this.tabPage2.Controls.Add(this.label4); + this.tabPage2.Controls.Add(this.label3); + this.tabPage2.Controls.Add(this.label2); + this.tabPage2.Controls.Add(this.lbNumSeg); + this.tabPage2.Controls.Add(this.lbNumSeg2); + this.tabPage2.Controls.Add(this.lbNumTri); + this.tabPage2.Controls.Add(this.lbNumTri2); + this.tabPage2.Controls.Add(this.lbNumVert); + this.tabPage2.Controls.Add(this.lbNumVert2); this.tabPage2.Controls.Add(this.label32); this.tabPage2.Controls.Add(this.label13); this.tabPage2.Controls.Add(this.label31); @@ -444,15 +343,116 @@ this.tabPage2.Location = new System.Drawing.Point(4, 4); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(272, 499); + this.tabPage2.Size = new System.Drawing.Size(272, 555); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Statistic"; // + // label20 + // + this.label20.AutoSize = true; + this.label20.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label20.ForeColor = System.Drawing.Color.White; + this.label20.Location = new System.Drawing.Point(8, 13); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(39, 13); + this.label20.TabIndex = 26; + this.label20.Text = "Mesh:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.ForeColor = System.Drawing.Color.DarkGray; + this.label4.Location = new System.Drawing.Point(8, 53); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(60, 13); + this.label4.TabIndex = 23; + this.label4.Text = "Segments:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.DarkGray; + this.label3.Location = new System.Drawing.Point(8, 72); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(56, 13); + this.label3.TabIndex = 24; + this.label3.Text = "Triangles:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.ForeColor = System.Drawing.Color.DarkGray; + this.label2.Location = new System.Drawing.Point(8, 34); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(50, 13); + this.label2.TabIndex = 25; + this.label2.Text = "Vertices:"; + // + // lbNumSeg + // + this.lbNumSeg.ForeColor = System.Drawing.Color.White; + this.lbNumSeg.Location = new System.Drawing.Point(98, 53); + this.lbNumSeg.Name = "lbNumSeg"; + this.lbNumSeg.Size = new System.Drawing.Size(70, 13); + this.lbNumSeg.TabIndex = 20; + this.lbNumSeg.Text = "-"; + this.lbNumSeg.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // lbNumSeg2 + // + this.lbNumSeg2.ForeColor = System.Drawing.Color.DarkGray; + this.lbNumSeg2.Location = new System.Drawing.Point(188, 53); + this.lbNumSeg2.Name = "lbNumSeg2"; + this.lbNumSeg2.Size = new System.Drawing.Size(70, 13); + this.lbNumSeg2.TabIndex = 19; + this.lbNumSeg2.Text = "-"; + this.lbNumSeg2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // lbNumTri + // + this.lbNumTri.ForeColor = System.Drawing.Color.White; + this.lbNumTri.Location = new System.Drawing.Point(98, 72); + this.lbNumTri.Name = "lbNumTri"; + this.lbNumTri.Size = new System.Drawing.Size(70, 13); + this.lbNumTri.TabIndex = 17; + this.lbNumTri.Text = "-"; + this.lbNumTri.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // lbNumTri2 + // + this.lbNumTri2.ForeColor = System.Drawing.Color.DarkGray; + this.lbNumTri2.Location = new System.Drawing.Point(188, 72); + this.lbNumTri2.Name = "lbNumTri2"; + this.lbNumTri2.Size = new System.Drawing.Size(70, 13); + this.lbNumTri2.TabIndex = 18; + this.lbNumTri2.Text = "-"; + this.lbNumTri2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // lbNumVert + // + this.lbNumVert.ForeColor = System.Drawing.Color.White; + this.lbNumVert.Location = new System.Drawing.Point(98, 34); + this.lbNumVert.Name = "lbNumVert"; + this.lbNumVert.Size = new System.Drawing.Size(70, 13); + this.lbNumVert.TabIndex = 21; + this.lbNumVert.Text = "-"; + this.lbNumVert.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // lbNumVert2 + // + this.lbNumVert2.ForeColor = System.Drawing.Color.DarkGray; + this.lbNumVert2.Location = new System.Drawing.Point(188, 34); + this.lbNumVert2.Name = "lbNumVert2"; + this.lbNumVert2.Size = new System.Drawing.Size(70, 13); + this.lbNumVert2.TabIndex = 22; + this.lbNumVert2.Text = "-"; + this.lbNumVert2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // // label32 // this.label32.AutoSize = true; this.label32.ForeColor = System.Drawing.Color.DarkGray; - this.label32.Location = new System.Drawing.Point(204, 156); + this.label32.Location = new System.Drawing.Point(210, 209); this.label32.Name = "label32"; this.label32.Size = new System.Drawing.Size(48, 13); this.label32.TabIndex = 11; @@ -462,7 +462,7 @@ // this.label13.AutoSize = true; this.label13.ForeColor = System.Drawing.Color.DarkGray; - this.label13.Location = new System.Drawing.Point(196, 12); + this.label13.Location = new System.Drawing.Point(202, 110); this.label13.Name = "label13"; this.label13.Size = new System.Drawing.Size(56, 13); this.label13.TabIndex = 11; @@ -472,7 +472,7 @@ // this.label31.AutoSize = true; this.label31.ForeColor = System.Drawing.Color.DarkGray; - this.label31.Location = new System.Drawing.Point(106, 156); + this.label31.Location = new System.Drawing.Point(112, 209); this.label31.Name = "label31"; this.label31.Size = new System.Drawing.Size(55, 13); this.label31.TabIndex = 12; @@ -482,7 +482,7 @@ // this.label12.AutoSize = true; this.label12.ForeColor = System.Drawing.Color.DarkGray; - this.label12.Location = new System.Drawing.Point(106, 12); + this.label12.Location = new System.Drawing.Point(113, 110); this.label12.Name = "label12"; this.label12.Size = new System.Drawing.Size(55, 13); this.label12.TabIndex = 12; @@ -492,7 +492,7 @@ // this.label16.AutoSize = true; this.label16.ForeColor = System.Drawing.Color.DarkGray; - this.label16.Location = new System.Drawing.Point(8, 80); + this.label16.Location = new System.Drawing.Point(8, 169); this.label16.Name = "label16"; this.label16.Size = new System.Drawing.Size(40, 13); this.label16.TabIndex = 9; @@ -502,7 +502,7 @@ // this.label29.AutoSize = true; this.label29.ForeColor = System.Drawing.Color.DarkGray; - this.label29.Location = new System.Drawing.Point(9, 203); + this.label29.Location = new System.Drawing.Point(8, 249); this.label29.Name = "label29"; this.label29.Size = new System.Drawing.Size(71, 13); this.label29.TabIndex = 15; @@ -512,7 +512,7 @@ // this.label14.AutoSize = true; this.label14.ForeColor = System.Drawing.Color.DarkGray; - this.label14.Location = new System.Drawing.Point(9, 59); + this.label14.Location = new System.Drawing.Point(8, 150); this.label14.Name = "label14"; this.label14.Size = new System.Drawing.Size(73, 13); this.label14.TabIndex = 15; @@ -521,7 +521,7 @@ // lbAngleMax // this.lbAngleMax.ForeColor = System.Drawing.Color.White; - this.lbAngleMax.Location = new System.Drawing.Point(176, 80); + this.lbAngleMax.Location = new System.Drawing.Point(182, 169); this.lbAngleMax.Name = "lbAngleMax"; this.lbAngleMax.Size = new System.Drawing.Size(76, 13); this.lbAngleMax.TabIndex = 16; @@ -531,7 +531,7 @@ // lbQualAspectAve // this.lbQualAspectAve.ForeColor = System.Drawing.Color.White; - this.lbQualAspectAve.Location = new System.Drawing.Point(176, 203); + this.lbQualAspectAve.Location = new System.Drawing.Point(182, 249); this.lbQualAspectAve.Name = "lbQualAspectAve"; this.lbQualAspectAve.Size = new System.Drawing.Size(76, 13); this.lbQualAspectAve.TabIndex = 14; @@ -541,7 +541,7 @@ // lbEdgeMax // this.lbEdgeMax.ForeColor = System.Drawing.Color.White; - this.lbEdgeMax.Location = new System.Drawing.Point(176, 59); + this.lbEdgeMax.Location = new System.Drawing.Point(182, 150); this.lbEdgeMax.Name = "lbEdgeMax"; this.lbEdgeMax.Size = new System.Drawing.Size(76, 13); this.lbEdgeMax.TabIndex = 14; @@ -551,7 +551,7 @@ // lbQualAlphaAve // this.lbQualAlphaAve.ForeColor = System.Drawing.Color.White; - this.lbQualAlphaAve.Location = new System.Drawing.Point(176, 183); + this.lbQualAlphaAve.Location = new System.Drawing.Point(182, 230); this.lbQualAlphaAve.Name = "lbQualAlphaAve"; this.lbQualAlphaAve.Size = new System.Drawing.Size(76, 13); this.lbQualAlphaAve.TabIndex = 3; @@ -561,7 +561,7 @@ // lbAreaMax // this.lbAreaMax.ForeColor = System.Drawing.Color.White; - this.lbAreaMax.Location = new System.Drawing.Point(176, 39); + this.lbAreaMax.Location = new System.Drawing.Point(182, 131); this.lbAreaMax.Name = "lbAreaMax"; this.lbAreaMax.Size = new System.Drawing.Size(76, 13); this.lbAreaMax.TabIndex = 3; @@ -571,7 +571,7 @@ // lbAngleMin // this.lbAngleMin.ForeColor = System.Drawing.Color.White; - this.lbAngleMin.Location = new System.Drawing.Point(94, 80); + this.lbAngleMin.Location = new System.Drawing.Point(100, 169); this.lbAngleMin.Name = "lbAngleMin"; this.lbAngleMin.Size = new System.Drawing.Size(68, 13); this.lbAngleMin.TabIndex = 4; @@ -581,7 +581,7 @@ // lbQualAspectMin // this.lbQualAspectMin.ForeColor = System.Drawing.Color.White; - this.lbQualAspectMin.Location = new System.Drawing.Point(94, 203); + this.lbQualAspectMin.Location = new System.Drawing.Point(100, 249); this.lbQualAspectMin.Name = "lbQualAspectMin"; this.lbQualAspectMin.Size = new System.Drawing.Size(68, 13); this.lbQualAspectMin.TabIndex = 2; @@ -591,7 +591,7 @@ // lbEdgeMin // this.lbEdgeMin.ForeColor = System.Drawing.Color.White; - this.lbEdgeMin.Location = new System.Drawing.Point(94, 59); + this.lbEdgeMin.Location = new System.Drawing.Point(100, 150); this.lbEdgeMin.Name = "lbEdgeMin"; this.lbEdgeMin.Size = new System.Drawing.Size(68, 13); this.lbEdgeMin.TabIndex = 2; @@ -601,7 +601,7 @@ // lbQualAlphaMin // this.lbQualAlphaMin.ForeColor = System.Drawing.Color.White; - this.lbQualAlphaMin.Location = new System.Drawing.Point(94, 183); + this.lbQualAlphaMin.Location = new System.Drawing.Point(100, 230); this.lbQualAlphaMin.Name = "lbQualAlphaMin"; this.lbQualAlphaMin.Size = new System.Drawing.Size(68, 13); this.lbQualAlphaMin.TabIndex = 7; @@ -611,7 +611,7 @@ // lbAreaMin // this.lbAreaMin.ForeColor = System.Drawing.Color.White; - this.lbAreaMin.Location = new System.Drawing.Point(94, 39); + this.lbAreaMin.Location = new System.Drawing.Point(100, 131); this.lbAreaMin.Name = "lbAreaMin"; this.lbAreaMin.Size = new System.Drawing.Size(68, 13); this.lbAreaMin.TabIndex = 7; @@ -622,7 +622,7 @@ // this.label22.AutoSize = true; this.label22.ForeColor = System.Drawing.Color.DarkGray; - this.label22.Location = new System.Drawing.Point(9, 183); + this.label22.Location = new System.Drawing.Point(8, 230); this.label22.Name = "label22"; this.label22.Size = new System.Drawing.Size(65, 13); this.label22.TabIndex = 8; @@ -632,7 +632,7 @@ // this.label10.AutoSize = true; this.label10.ForeColor = System.Drawing.Color.DarkGray; - this.label10.Location = new System.Drawing.Point(9, 39); + this.label10.Location = new System.Drawing.Point(8, 131); this.label10.Name = "label10"; this.label10.Size = new System.Drawing.Size(76, 13); this.label10.TabIndex = 8; @@ -643,7 +643,7 @@ this.label17.AutoSize = true; this.label17.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.label17.ForeColor = System.Drawing.Color.White; - this.label17.Location = new System.Drawing.Point(8, 280); + this.label17.Location = new System.Drawing.Point(8, 336); this.label17.Name = "label17"; this.label17.Size = new System.Drawing.Size(97, 13); this.label17.TabIndex = 5; @@ -654,7 +654,7 @@ this.label21.AutoSize = true; this.label21.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.label21.ForeColor = System.Drawing.Color.White; - this.label21.Location = new System.Drawing.Point(8, 156); + this.label21.Location = new System.Drawing.Point(8, 209); this.label21.Name = "label21"; this.label21.Size = new System.Drawing.Size(47, 13); this.label21.TabIndex = 6; @@ -665,7 +665,7 @@ this.label11.AutoSize = true; this.label11.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.label11.ForeColor = System.Drawing.Color.White; - this.label11.Location = new System.Drawing.Point(8, 12); + this.label11.Location = new System.Drawing.Point(8, 110); this.label11.Name = "label11"; this.label11.Size = new System.Drawing.Size(50, 13); this.label11.TabIndex = 6; @@ -675,7 +675,7 @@ // this.angleHistogram1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76))))); this.angleHistogram1.Font = new System.Drawing.Font("Segoe UI", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.angleHistogram1.Location = new System.Drawing.Point(6, 298); + this.angleHistogram1.Location = new System.Drawing.Point(6, 354); this.angleHistogram1.Name = "angleHistogram1"; this.angleHistogram1.Size = new System.Drawing.Size(260, 195); this.angleHistogram1.TabIndex = 0; @@ -694,7 +694,7 @@ this.tabPage3.Location = new System.Drawing.Point(4, 4); this.tabPage3.Name = "tabPage3"; this.tabPage3.Padding = new System.Windows.Forms.Padding(3); - this.tabPage3.Size = new System.Drawing.Size(272, 499); + this.tabPage3.Size = new System.Drawing.Size(272, 555); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "About"; // @@ -740,7 +740,7 @@ this.label19.Name = "label19"; this.label19.Size = new System.Drawing.Size(134, 40); this.label19.TabIndex = 0; - this.label19.Text = "Beta 2 (2012-06-09)\r\nChristian Woltering\r\nMIT"; + this.label19.Text = "Beta 2 (2012-06-11)\r\nChristian Woltering\r\nMIT"; // // label18 // @@ -955,15 +955,6 @@ private Controls.DarkTabControl flatTabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label lbNumSeg2; - private System.Windows.Forms.Label lbNumTri2; - private System.Windows.Forms.Label lbNumVert2; - private System.Windows.Forms.Label lbNumSeg; - private System.Windows.Forms.Label lbNumTri; - private System.Windows.Forms.Label lbNumVert; private Controls.DarkButton btnSmooth; private Controls.DarkButton btnMesh; private Controls.DarkCheckBox cbQuality; @@ -1009,7 +1000,6 @@ private System.Windows.Forms.Label lbCodeplex; private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; private System.Windows.Forms.ToolStripMenuItem menuFileExport; - private System.Windows.Forms.Label label20; private System.Windows.Forms.Label label32; private System.Windows.Forms.Label label31; private System.Windows.Forms.Label label29; @@ -1019,6 +1009,16 @@ private System.Windows.Forms.Label lbQualAlphaMin; private System.Windows.Forms.Label label22; private System.Windows.Forms.Label label21; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label lbNumSeg; + private System.Windows.Forms.Label lbNumSeg2; + private System.Windows.Forms.Label lbNumTri; + private System.Windows.Forms.Label lbNumTri2; + private System.Windows.Forms.Label lbNumVert; + private System.Windows.Forms.Label lbNumVert2; } } diff --git a/Triangle.NET/TestApp/FormMain.cs b/Triangle.NET/TestApp/FormMain.cs index 8662a39..74d796a 100644 --- a/Triangle.NET/TestApp/FormMain.cs +++ b/Triangle.NET/TestApp/FormMain.cs @@ -39,32 +39,6 @@ namespace MeshExplorer renderControl1.Initialize(); stats = new Statistic(); - - //BatchTest(); - } - - void BatchTest() - { - try - { - //Mesh m = new Mesh(); - //m.SetOption(Options.MinAngle, 20); - - - for (int j = 0; j < 10; j++) - { - for (int i = 20; i > 0; i--) - { - //var geom = PolygonGenerator.CreateRandomPoints(10 * i, 100, 100); - - //m.Triangulate(geom); - } - } - } - catch (Exception e) - { - MessageBox.Show("BLUB\n" + e.Message); - } } private void Form1_KeyUp(object sender, KeyEventArgs e) @@ -263,6 +237,55 @@ namespace MeshExplorer lbQualAspectAve.Text = Util.DoubleToString(quality.Q_Average); } + private void HandleMeshImport() + { + // Render mesh + renderControl1.SetData(mesh, true); + + // Previous mesh stats + lbNumVert2.Text = "-"; + lbNumTri2.Text = "-"; + lbNumSeg2.Text = "-"; + + // New mesh stats + lbNumVert.Text = stats.Vertices.ToString(); + lbNumSeg.Text = stats.ConstrainedEdges.ToString(); + lbNumTri.Text = stats.Triangles.ToString(); + + // Update statistics tab + angleHistogram1.SetData(stats.MinAngleHistogram, stats.MaxAngleHistogram); + + lbAreaMin.Text = Util.DoubleToString(stats.SmallestArea); + lbAreaMax.Text = Util.DoubleToString(stats.LargestArea); + lbEdgeMin.Text = Util.DoubleToString(stats.ShortestEdge); + lbEdgeMax.Text = Util.DoubleToString(stats.LongestEdge); + lbAngleMin.Text = Util.AngleToString(stats.SmallestAngle); + lbAngleMax.Text = Util.AngleToString(stats.LargestAngle); + + // Enable menu items + viewMenuVoronoi.Enabled = true; + + // Set refine mode + btnMesh.Enabled = true; + btnMesh.Text = "Refine"; + + settings.RefineMode = true; + + // Update quality + if (quality == null) + { + quality = new QualityMeasure(); + } + + quality.Update(this.mesh); + + lbQualAlphaMin.Text = Util.DoubleToString(quality.AlphaMinimum); + lbQualAlphaAve.Text = Util.DoubleToString(quality.AlphaAverage); + + lbQualAspectMin.Text = Util.DoubleToString(quality.Q_Minimum); + lbQualAspectAve.Text = Util.DoubleToString(quality.Q_Average); + } + #endregion #region Commands @@ -278,16 +301,39 @@ namespace MeshExplorer if (ofd.ShowDialog() == DialogResult.OK) { - input = FileProcessor.Open(ofd.FileName); - - if (input != null) + if (FileProcessor.ContainsMeshData(ofd.FileName)) { - // Update settings - settings.CurrentFile = Path.GetFileName(ofd.FileName); + if (DarkMessageBox.Show("Import mesh", Settings.ImportString, + "Do you want to import the mesh?", MessageBoxButtons.YesNo) == DialogResult.OK) + { + input = null; + mesh = FileProcessor.Import(ofd.FileName); - HandleNewInput(); + if (mesh != null) + { + stats.Update(mesh, 10); + + // Update settings + settings.CurrentFile = Path.GetFileName(ofd.FileName); + + HandleMeshImport(); + } + // else Message + } + } + else + { + input = FileProcessor.Read(ofd.FileName); + + if (input != null) + { + // Update settings + settings.CurrentFile = Path.GetFileName(ofd.FileName); + + HandleNewInput(); + } + // else Message } - // else Message // Update folder settings settings.OfdFilterIndex = ofd.FilterIndex; @@ -306,6 +352,8 @@ namespace MeshExplorer if (sfd.ShowDialog() == DialogResult.OK) { + mesh.Renumber(); + FileProcessor.Save(sfd.FileName, mesh); } } @@ -324,7 +372,10 @@ namespace MeshExplorer private void TriangulateOrRefine() { - if (input == null || settings.ExceptionThrown) return; + if ((input == null && !settings.RefineMode) || settings.ExceptionThrown) + { + return; + } if (settings.RefineMode == false) { @@ -336,7 +387,7 @@ namespace MeshExplorer btnSmooth.Enabled = true; } } - else + else if (cbQuality.Checked) { Refine(); } diff --git a/Triangle.NET/TestApp/IO/FileProcessor.cs b/Triangle.NET/TestApp/IO/FileProcessor.cs index 348378c..0f1d3c1 100644 --- a/Triangle.NET/TestApp/IO/FileProcessor.cs +++ b/Triangle.NET/TestApp/IO/FileProcessor.cs @@ -19,31 +19,41 @@ namespace MeshExplorer.IO /// public static class FileProcessor { - static Dictionary container = new Dictionary(); + static Dictionary container = new Dictionary(); - public static InputGeometry Open(string path) + public static bool ContainsMeshData(string path) { - string ext = Path.GetExtension(path); + IMeshFile provider = GetProviderInstance(path); - IMeshFormat provider; + return provider.ContainsMeshData(path); + } - if (container.ContainsKey(ext)) - { - provider = container[ext]; - } - else - { - provider = CreateInstance(ext); - } + public static InputGeometry Read(string path) + { + IMeshFile provider = GetProviderInstance(path); return provider.Read(path); } - public static void Save(string path, Mesh data) + public static Mesh Import(string path) + { + IMeshFile provider = GetProviderInstance(path); + + return provider.Import(path); + } + + public static void Save(string path, Mesh mesh) + { + IMeshFile provider = GetProviderInstance(path); + + provider.Write(mesh, path); + } + + private static IMeshFile GetProviderInstance(string path) { string ext = Path.GetExtension(path); - IMeshFormat provider; + IMeshFile provider; if (container.ContainsKey(ext)) { @@ -51,19 +61,19 @@ namespace MeshExplorer.IO } else { - provider = CreateInstance(ext); + provider = CreateProviderInstance(ext); } - provider.Write(path, data); + return provider; } - private static IMeshFormat CreateInstance(string ext) + private static IMeshFile CreateProviderInstance(string ext) { // TODO: automate by using IMeshFormat's Extensions property. - IMeshFormat provider = null; + IMeshFile provider = null; - if (ext == ".node" || ext == ".poly") + if (ext == ".node" || ext == ".poly" || ext == ".ele") { provider = new TriangleFile(); } @@ -75,14 +85,6 @@ namespace MeshExplorer.IO { provider = new DatFile(); } - else if (ext == ".mphtxt") - { - //provider = new COMSOL(); - } - else if (ext == ".vtk") - { - //provider = new VtkFile(); - } if (provider == null) { diff --git a/Triangle.NET/TestApp/IO/Formats/DatFile.cs b/Triangle.NET/TestApp/IO/Formats/DatFile.cs index 813686e..bd51e20 100644 --- a/Triangle.NET/TestApp/IO/Formats/DatFile.cs +++ b/Triangle.NET/TestApp/IO/Formats/DatFile.cs @@ -9,16 +9,17 @@ namespace MeshExplorer.IO.Formats using System; using System.Collections.Generic; using System.Linq; - using System.IO; using System.Text; - using TriangleNet; - using TriangleNet.Geometry; using TriangleNet.IO; + using System.IO; + using MeshExplorer.Rendering; + using TriangleNet.Geometry; + using TriangleNet; /// /// TODO: Update summary. /// - public class DatFile : MeshExplorer.IO.IMeshFormat + public class DatFile : IMeshFile { /// /// Gets the supported file extensions. @@ -28,6 +29,11 @@ namespace MeshExplorer.IO.Formats get { return new string[] { ".dat" }; } } + public bool ContainsMeshData(string filename) + { + return false; + } + public InputGeometry Read(string filename) { InputGeometry data = new InputGeometry(); @@ -44,7 +50,7 @@ namespace MeshExplorer.IO.Formats if (split.Length == 2) { data.AddPoint( - double.Parse(split[0], Util.Nfi), + double.Parse(split[0], Util.Nfi), double.Parse(split[1], Util.Nfi)); } } @@ -61,7 +67,12 @@ namespace MeshExplorer.IO.Formats return data; } - public void Write(string filename, Mesh data) + public Mesh Import(string filename) + { + throw new NotImplementedException(); + } + + public void Write(Mesh mesh, string filename) { throw new NotImplementedException(); } diff --git a/Triangle.NET/TestApp/IO/Formats/JsonFile.cs b/Triangle.NET/TestApp/IO/Formats/JsonFile.cs index d3ad046..0f6d60a 100644 --- a/Triangle.NET/TestApp/IO/Formats/JsonFile.cs +++ b/Triangle.NET/TestApp/IO/Formats/JsonFile.cs @@ -15,12 +15,41 @@ namespace MeshExplorer.IO.Formats using MeshExplorer.Rendering; using TriangleNet.Geometry; using TriangleNet; + using System.Collections; /// - /// TODO: Update summary. + /// Read and write JSON files. /// - public class JsonFile : MeshExplorer.IO.IMeshFormat + /// + /// The JSON format: + /// { + /// "config": { + /// "ver": 1, + /// "type": "mesh" | "poly" | "points", + /// "dim": 2 + /// }, + /// "points": { + /// "data": [ p0.x, p0.y ... pn.x, pn.y ], + /// "markers": [ ... ], + /// "attributes": [ ... ] + /// }, + /// "segments": { + /// "data": [ s0(1), s0(2) ... sn(1), sn(2) ], + /// "markers": [ ... ] + /// }, + /// "holes": [ h0.x, h0.y ... hn.x, hn.y ], + /// "triangles": { + /// "data": [ t0(1), t0(2), t0(3) ... tn(1), tn(2), tn(3) ], + /// "neighbors": [ t0.n1, t0.n2, t0.n3 ... tn.n1, tn.n2, tn.n3 ], + /// "attributes": [ ... ] + /// } + /// } + /// + public class JsonFile : IMeshFile { + string file; + Dictionary json; + /// /// Gets the supported file extensions. /// @@ -29,6 +58,95 @@ namespace MeshExplorer.IO.Formats get { return new string[] { ".json" }; } } + public bool ContainsMeshData(string filename) + { + ParseJson(filename); + + if (this.json.ContainsKey("config")) + { + var config = this.json["config"] as Dictionary; + + if (config != null && config.ContainsKey("type")) + { + return config["type"].ToString() == "mesh"; + } + } + + return false; + } + + public Mesh Import(string filename) + { + InputGeometry geometry = this.Read(filename); + + List triangles = null; + + if (this.json.ContainsKey("triangles")) + { + var tri = this.json["triangles"] as Dictionary; + + if (tri != null) + { + triangles = ReadTriangles(tri, geometry.Count); + } + } + + Mesh mesh = new Mesh(); + mesh.Load(geometry, triangles); + + return mesh; + } + + public void Write(Mesh mesh, string filename) + { + using (StreamWriter writer = new StreamWriter(filename)) + { + int nv = mesh.NumberOfVertices; + int ns = mesh.NumberOfSegments; + int nh = mesh.Holes.Count; + int ne = mesh.NumberOfTriangles; + + writer.Write("{"); + + // Config header + writer.Write("\"config\":{"); + writer.Write("\"ver\":1,"); + writer.Write("\"type\":\"{0}\",", ne > 0 ? "mesh" : (ns > 0 ? "poly" : "points")); + writer.Write("\"dim\":2"); + writer.Write("}"); + + // Write the coordinates + if (nv > 0) + { + writer.Write(","); + WritePoints(mesh, writer, nv); + } + + // Write the segments + if (ns > 0) + { + writer.Write(","); + WriteSegments(mesh, writer, ns); + } + + // Write the holes + if (nh > 0) + { + writer.Write(","); + WriteHoles(mesh, writer, nh); + } + + // Write the elements + if (ne > 0) + { + writer.Write(","); + WriteTriangles(mesh, writer, ne); + } + + writer.Write("}"); + } + } + /// /// /// @@ -36,99 +154,365 @@ namespace MeshExplorer.IO.Formats /// public InputGeometry Read(string filename) { - string json = File.ReadAllText(filename); - - JsonParser parser = new JsonParser("json"); - object rawData = parser.Decode(); + ParseJson(filename); InputGeometry data = new InputGeometry(); - List triangles = new List(); + if (json == null) + { + // TODO: Exception? + return data; + } + + if (json.ContainsKey("config")) + { + + } + + int count = 0; + + if (json.ContainsKey("points")) + { + var points = json["points"] as Dictionary; + + if (points != null) + { + ReadPoints(data, points, ref count); + } + else + { + // TODO: Exception? + return data; + } + } + + if (json.ContainsKey("segments")) + { + var segments = json["segments"] as Dictionary; + + if (segments != null) + { + ReadSegments(data, segments, count); + } + } + + if (json.ContainsKey("holes")) + { + var holes = json["holes"] as ArrayList; + + if (holes != null) + { + ReadHoles(data, holes); + } + } return data; } - public void Write(string filename, Mesh data) + private void ParseJson(string filename) { - using (StreamWriter writer = new StreamWriter(filename)) + if (this.json == null || this.file != filename) { - int nv = data.NumberOfVertices; - int ns = data.NumberOfSegments; - int ne = data.NumberOfTriangles; - int nn = data.NumberOfTriangles; - int i = 0; + this.file = filename; - string sep = String.Empty; + string content = File.ReadAllText(filename); - // Header - writer.Write("{{\"format\":\"{0}\",\"dim\":2", ne > 0 ? "mesh" : (ns > 0 ? "poly" : "nodes")); - - // Write the coordinates - writer.Write(",\"points\":["); - foreach (var item in data.Vertices) - { - sep = (i == nv - 1) ? String.Empty : ", "; - - writer.Write("{0},{1}{2}", - item.X.ToString(Util.Nfi), - item.Y.ToString(Util.Nfi), sep); - - i++; - } - writer.Write("]"); - - // Write the segments - if (ns > 0) - { - writer.Write(",\"segments\":["); - foreach (var item in data.Segments) - { - sep = (i == ns - 1) ? String.Empty : ", "; - - writer.Write("{0},{1}{2}", - item.P0, item.P1, sep); - - i++; - } - - writer.Write("]"); - } - - // Write the elements - if (ne > 0) - { - writer.Write(",\"triangles\":["); - foreach (var item in data.Triangles) - { - sep = (i == ne - 1) ? String.Empty : ", "; - - writer.Write("{0},{1},{2}{3}", - item.P0, item.P1, item.P2, sep); - - i++; - } - writer.Write("]"); - } - - // Write neighbors - if (nn > 0) - { - writer.Write(",\"neighbors\":["); - //for (int i = 0; i < nn; i++) - //{ - // sep = (i == nn - 1) ? String.Empty : ", "; - - // writer.Write("{0},{1},{2}{3}", - // data.Neighbors[i][0], - // data.Neighbors[i][1], - // data.Neighbors[i][2], sep); - - //} - writer.Write("]"); - } - - writer.Write("}"); + JsonParser parser = new JsonParser(content); + this.json = parser.Decode() as Dictionary; } } + + #region Read helpers + + private void ReadPoints(InputGeometry geometry, Dictionary points, ref int count) + { + ArrayList data = points["data"] as ArrayList; + + ArrayList markers = null; + ArrayList attributes = null; + + if (points.ContainsKey("markers")) + { + markers = points["markers"] as ArrayList; + } + + if (points.ContainsKey("attributes")) + { + attributes = points["attributes"] as ArrayList; + } + + if (data != null) + { + int mark, n = data.Count; + + if (n % 2 != 0) + { + throw new Exception("JSON format error (points)."); + } + + // Number of points + count = n / 2; + + for (int i = 0; i < n; i += 2) + { + mark = 0; + + if (markers != null && markers.Count == count) + { + mark = int.Parse(markers[i / 2].ToString()); + } + + geometry.AddPoint( + double.Parse(data[i].ToString(), Util.Nfi), + double.Parse(data[i + 1].ToString(), Util.Nfi), + mark + ); + } + } + } + + private void ReadSegments(InputGeometry geometry, Dictionary segments, int count) + { + ArrayList data = segments["data"] as ArrayList; + + ArrayList markers = null; + + if (segments.ContainsKey("markers")) + { + markers = segments["markers"] as ArrayList; + } + + if (data != null) + { + int mark, n = data.Count; + + if (n % 2 != 0) + { + throw new Exception("JSON format error (segments)."); + } + + int p0, p1; + + for (int i = 0; i < n; i += 2) + { + mark = 0; + + if (markers != null && markers.Count == n) + { + mark = int.Parse(markers[i / 2].ToString()); + } + + p0 = int.Parse(data[i].ToString()); + p1 = int.Parse(data[i + 1].ToString()); + + if (p0 < 0 || p0 >= count || p1 < 0 || p1 >= count) + { + throw new Exception("JSON format error (segment index)."); + } + + geometry.AddSegment(p0, p1, mark); + } + } + } + + private void ReadHoles(InputGeometry geometry, ArrayList holes) + { + int n = holes.Count; + + if (n % 2 != 0) + { + throw new Exception("JSON format error (holes)."); + } + + for (int i = 0; i < n; i += 2) + { + geometry.AddHole( + double.Parse(holes[i].ToString(), Util.Nfi), + double.Parse(holes[i + 1].ToString(), Util.Nfi) + ); + } + } + + private List ReadTriangles(Dictionary triangles, int points) + { + ArrayList data = triangles["data"] as ArrayList; + + ArrayList neighbors = null; + ArrayList attributes = null; + + if (triangles.ContainsKey("neighbors")) + { + neighbors = triangles["neighbors"] as ArrayList; + } + + if (triangles.ContainsKey("attributes")) + { + attributes = triangles["attributes"] as ArrayList; + } + + List output = null; + + if (data != null) + { + int n = data.Count; + + if (n % 3 != 0) + { + throw new Exception("JSON format error (triangles)."); + } + + output = new List(n / 3); + + int p0, p1, p2, n0, n1, n2; + + for (int i = 0; i < n; i += 3) + { + p0 = int.Parse(data[i].ToString()); + p1 = int.Parse(data[i + 1].ToString()); + p2 = int.Parse(data[i + 2].ToString()); + + n0 = n1 = n2 = -1; + + if (p0 < 0 || p0 >= points || p1 < 0 || p1 >= points || p2 < 0 || p2 >= points) + { + throw new Exception("JSON format error (triangle index)."); + } + + if (neighbors.Count == n) + { + n0 = int.Parse(neighbors[i].ToString()); + n1 = int.Parse(neighbors[i + 1].ToString()); + n2 = int.Parse(neighbors[i + 2].ToString()); + } + + // TODO: Set neighbors + output.Add(new InputTriangle(p0, p1, p2)); + } + } + + return output; + } + + #endregion + + #region Write helpers + + private void WritePoints(Mesh data, StreamWriter writer, int nv) + { + int i = 0; + + StringBuilder markers = new StringBuilder(); + bool useMarkers = false; + + string seperator; + + writer.Write("\"points\":{\"data\":["); + foreach (var item in data.Vertices) + { + seperator = (i == nv - 1) ? String.Empty : ", "; + + writer.Write("{0},{1}{2}", + item.X.ToString(Util.Nfi), + item.Y.ToString(Util.Nfi), seperator); + + if (item.Boundary > 0) + { + useMarkers = true; + } + + markers.AppendFormat("{0}{1}", item.Boundary, seperator); + + i++; + } + writer.Write("]"); + if (useMarkers) + { + writer.Write(",\"markers\":[" + markers.ToString() + "]"); + } + //writer.Write(",\"attributes\":[]"); + writer.Write("}"); + } + + private void WriteHoles(Mesh data, StreamWriter writer, int nh) + { + int i = 0; + + writer.Write("\"holes\":["); + foreach (var item in data.Holes) + { + writer.Write("{0},{1}{2}", + item.X.ToString(Util.Nfi), + item.Y.ToString(Util.Nfi), (i == nh - 1) ? String.Empty : ", "); + + i++; + } + + writer.Write("]"); + } + + private void WriteSegments(Mesh data, StreamWriter writer, int ns) + { + int i = 0; + + StringBuilder markers = new StringBuilder(); + bool useMarkers = false; + + string seperator; + + writer.Write("\"segments\":{\"data\":["); + foreach (var item in data.Segments) + { + seperator = (i == ns - 1) ? String.Empty : ", "; + + writer.Write("{0},{1}{2}", + item.P0, item.P1, seperator); + + if (item.Boundary > 0) + { + useMarkers = true; + } + + markers.AppendFormat("{0}{1}", item.Boundary, seperator); + + i++; + } + + writer.Write("]"); + + if (useMarkers) + { + writer.Write(",\"markers\":[" + markers.ToString() + "]"); + } + + writer.Write("}"); + } + + private void WriteTriangles(Mesh data, StreamWriter writer, int ne) + { + int i = 0; + + StringBuilder neighbors = new StringBuilder(); + + string seperator; + + writer.Write("\"triangles\":{\"data\":["); + foreach (var item in data.Triangles) + { + seperator = (i == ne - 1) ? String.Empty : ", "; + + writer.Write("{0},{1},{2}{3}", + item.P0, item.P1, item.P2, seperator); + + neighbors.AppendFormat("{0},{1},{2}{3}", + item.N0, item.N1, item.N2, seperator); + + i++; + } + writer.Write("]"); + writer.Write(",\"neighbors\":[" + neighbors.ToString() + "]"); + writer.Write("}"); + } + + #endregion } } \ No newline at end of file diff --git a/Triangle.NET/TestApp/IO/Formats/TriangleFile.cs b/Triangle.NET/TestApp/IO/Formats/TriangleFile.cs index c5642ad..c45b704 100644 --- a/Triangle.NET/TestApp/IO/Formats/TriangleFile.cs +++ b/Triangle.NET/TestApp/IO/Formats/TriangleFile.cs @@ -18,115 +18,48 @@ namespace MeshExplorer.IO.Formats /// /// TODO: Update summary. /// - public class TriangleFile : MeshExplorer.IO.IMeshFormat + public class TriangleFile : IMeshFile { + TriangleFormat format = new TriangleFormat(); + /// /// Gets the supported file extensions. /// public string[] Extensions { - get { return new string[] { ".node", ".poly" }; } + get { return new string[] { ".node", ".poly", ".ele" }; } } - - public InputGeometry Read(string file) + public bool ContainsMeshData(string filename) { - string supp = Path.ChangeExtension(file, ".ele"); + string ext = Path.GetExtension(filename); - return FileReader.ReadFile(file, File.Exists(supp)); - } - - public void Write(string file, Mesh data) - { - if (data.NumberOfVertices > 0) + if (ext == ".node" || ext == ".poly") { - WritePoly(file, data); - - if (data.Triangles != null) + if (File.Exists(Path.ChangeExtension(filename, ".ele"))) { - file = Path.ChangeExtension(file, "ele"); - - WriteElements(file, data); + return true; } } + + return (ext == ".ele"); } - private void WritePoly(string file, Mesh data) + public InputGeometry Read(string filename) { - int i = 0; - int n = data.NumberOfVertices; - bool markers = true; - - using (StreamWriter writer = new StreamWriter(file)) - { - // Write nodes - writer.WriteLine("{0} 2 0 {1}", n, markers ? "1" : "0"); - - // TODO: point attributes - foreach (var item in data.Vertices) - { - writer.Write("{0} {1} {2}", i++, - item.X.ToString(Util.Nfi), - item.Y.ToString(Util.Nfi)); - - if (markers) - { - writer.Write(" {0}", item.Boundary); - } - - writer.WriteLine(); - } - - // Write segments - n = data.NumberOfSegments; - i = 0; - - // Number of segments, number of boundary markers (zero or one). - writer.WriteLine("{0} {1}", n, markers ? "1" : "0"); - - foreach (var item in data.Segments) - { - writer.Write("{0} {1} {2}", i, - item.P0, item.P1); - - if (markers) - { - writer.Write(" {0}", item.Boundary); - } - - writer.WriteLine(); - } - - // Write holes - n = data.Holes.Count; - - writer.WriteLine("{0}", n); - - foreach (var item in data.Holes) - { - writer.WriteLine("{0} {1}", - data.Holes[i].X.ToString(Util.Nfi), - data.Holes[i].Y.ToString(Util.Nfi)); - } - - // TODO: Regions - } + return format.Read(filename); } - public void WriteElements(string file, Mesh data) + public Mesh Import(string filename) { - using (StreamWriter writer = new StreamWriter(file)) + return format.Import(filename); + } + + public void Write(Mesh mesh, string filename) + { + if (mesh.NumberOfVertices > 0) { - int i = 0; - - // TODO: attributes - writer.WriteLine("{0} 3 0", data.NumberOfTriangles); - - foreach (var item in data.Triangles) - { - writer.WriteLine("{0} {1} {2} {3}", i++, - item.P0, item.P1, item.P2); - } + format.Write(mesh, filename); } } } diff --git a/Triangle.NET/TestApp/IO/IMeshFormat.cs b/Triangle.NET/TestApp/IO/IMeshFile.cs similarity index 50% rename from Triangle.NET/TestApp/IO/IMeshFormat.cs rename to Triangle.NET/TestApp/IO/IMeshFile.cs index e598b96..4b577e6 100644 --- a/Triangle.NET/TestApp/IO/IMeshFormat.cs +++ b/Triangle.NET/TestApp/IO/IMeshFile.cs @@ -11,16 +11,23 @@ namespace MeshExplorer.IO using System.Linq; using System.Text; using TriangleNet; - using TriangleNet.Geometry; + using TriangleNet.IO; /// /// Defines an interface for mesh file formats. /// - public interface IMeshFormat + public interface IMeshFile : IGeometryFormat, IMeshFormat { + /// + /// The supported file extensions. + /// string[] Extensions { get; } - InputGeometry Read(string file); - void Write(string file, Mesh data); + /// + /// Return true, if a (previously saved) mesh is associated with the given file. + /// + /// The file name. + /// True, if a mesh is associated with the given file. + bool ContainsMeshData(string filename); } } diff --git a/Triangle.NET/TestApp/Mesh Explorer.csproj b/Triangle.NET/TestApp/Mesh Explorer.csproj index 2825581..5e50d85 100644 --- a/Triangle.NET/TestApp/Mesh Explorer.csproj +++ b/Triangle.NET/TestApp/Mesh Explorer.csproj @@ -110,7 +110,7 @@ - + diff --git a/Triangle.NET/TestApp/Rendering/RenderData.cs b/Triangle.NET/TestApp/Rendering/RenderData.cs index b46d030..8afb39e 100644 --- a/Triangle.NET/TestApp/Rendering/RenderData.cs +++ b/Triangle.NET/TestApp/Rendering/RenderData.cs @@ -74,6 +74,18 @@ namespace MeshExplorer.Rendering SetPoints(mesh.Vertices); + // Get segments + var segs = mesh.Segments; + + List segList = new List(mesh.NumberOfSegments); + + foreach (var seg in segs) + { + segList.Add(new Edge(seg.P0, seg.P1)); + } + + this.Segments = segList.ToArray(); + // Get edges (more efficient than rendering triangles) EdgeEnumerator e = new EdgeEnumerator(mesh); diff --git a/Triangle.NET/TestApp/Settings.cs b/Triangle.NET/TestApp/Settings.cs index f3c48c1..164c3b8 100644 --- a/Triangle.NET/TestApp/Settings.cs +++ b/Triangle.NET/TestApp/Settings.cs @@ -18,6 +18,10 @@ namespace MeshExplorer /// public class Settings { + // String resources + public static string ImportString = "The selected file has associated mesh information. " + + "You can choose to import the mesh or just read the geometry."; + // Open file dialog public string OfdDirectory { get; set; } public string OfdFilter { get; set; } @@ -49,8 +53,12 @@ namespace MeshExplorer OfdDirectory = Application.StartupPath; } - OfdFilter = "Triangle file (*.node;*.poly)|*.node;*.poly"; - OfdFilter += "|Triangle.NET JSON (*.json)|*.json"; + SfdDirectory = OfdDirectory; + SfdFilter = "Triangle file (*.node;*.poly)|*.node;*.poly"; + SfdFilter += "|Triangle.NET JSON (*.json)|*.json"; + SfdFilterIndex = 1; + + OfdFilter = SfdFilter; OfdFilter += "|Polygon data (*.dat)|*.dat"; //OfdFilter += "|COMSOL mesh (*.mphtxt)|*.mphtxt"; //OfdFilter += "|AVS UCD data (*.ucd)|*.ucd"; @@ -58,10 +66,6 @@ namespace MeshExplorer OfdFilterIndex = 0; - SfdDirectory = OfdDirectory; - SfdFilter = OfdFilter; - SfdFilterIndex = 1; - CurrentFile = ""; RefineMode = false; diff --git a/Triangle.NET/Triangle/IO/DataReader.cs b/Triangle.NET/Triangle/IO/DataReader.cs index d58db40..1ba541f 100644 --- a/Triangle.NET/Triangle/IO/DataReader.cs +++ b/Triangle.NET/Triangle/IO/DataReader.cs @@ -17,12 +17,10 @@ namespace TriangleNet.IO using TriangleNet.Geometry; /// - /// TODO: Update summary. + /// The DataReader class provides methods for mesh reconstruction. /// - public static class DataReader + static class DataReader { - #region Library - /// /// Reconstruct a triangulation from its raw data representation. /// @@ -77,7 +75,7 @@ namespace TriangleNet.IO int numberofsegments = input.segments.Count; mesh.inelements = elements; - mesh.eextras = mesh.inelements > 0 ? triangles[0].Attributes.Length : 0; + mesh.eextras = triangles[0].Attributes != null ? triangles[0].Attributes.Length : 0; // Create the triangles. for (i = 0; i < mesh.inelements; i++) @@ -317,7 +315,5 @@ namespace TriangleNet.IO return hullsize; } - - #endregion } } diff --git a/Triangle.NET/Triangle/IO/FileReader.cs b/Triangle.NET/Triangle/IO/FileReader.cs index 18b7bc4..4c5ec72 100644 --- a/Triangle.NET/Triangle/IO/FileReader.cs +++ b/Triangle.NET/Triangle/IO/FileReader.cs @@ -16,43 +16,14 @@ namespace TriangleNet.IO using System.Collections.Generic; /// - /// Helper for reading Triangle files. + /// Helper methods for reading Triangle file formats. /// public static class FileReader { static NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat; static int startIndex = 0; - /// - /// Read the input data from a file, which may be a .node or .poly file. - /// - /// The file to read. - /// Will NOT read associated files by default. - public static InputGeometry ReadFile(string filename) - { - return ReadFile(filename, false); - } - - /// - /// Read the input data from a file, which may be a .node or .poly file. - /// - /// The file to read. - /// Read associated files (ele, area, neigh). - public static InputGeometry ReadFile(string filename, bool readsupp) - { - string ext = Path.GetExtension(filename); - - if (ext == ".node") - { - return ReadNodeFile(filename, readsupp); - } - else if (ext == ".poly") - { - return ReadPolyFile(filename, readsupp, readsupp); - } - - throw new NotSupportedException("File format '" + ext + "' not supported."); - } + #region Helper methods static bool TryReadLine(StreamReader reader, out string[] token) { @@ -81,11 +52,11 @@ namespace TriangleNet.IO } /// - /// + /// Read vertex information of the given line. /// - /// - /// - /// + /// The input geometry. + /// The current vertex index. + /// The current line. /// Number of point attributes static void ReadVertex(InputGeometry data, int index, string[] line, int n) { @@ -112,6 +83,61 @@ namespace TriangleNet.IO data.AddPoint(x, y, mark); } + #endregion + + #region Main I/O methods + + /// + /// Reads geometry information from .node or .poly files. + /// + public static void Read(string filename, out InputGeometry geometry) + { + geometry = null; + + string path = Path.ChangeExtension(filename, ".poly"); + + if (File.Exists(path)) + { + geometry = FileReader.ReadPolyFile(path); + } + else + { + path = Path.ChangeExtension(filename, ".node"); + geometry = FileReader.ReadNodeFile(path); + } + } + + /// + /// Reads a mesh from .node, .poly or .ele files. + /// + public static void Read(string filename, out InputGeometry geometry, out List triangles) + { + triangles = null; + + FileReader.Read(filename, out geometry); + + string path = Path.ChangeExtension(filename, ".ele"); + + if (File.Exists(path) && geometry != null) + { + triangles = FileReader.ReadEleFile(path); + } + } + + /// + /// Reads geometry information from .node or .poly files. + /// + public static InputGeometry Read(string filename) + { + InputGeometry geometry = null; + + FileReader.Read(filename, out geometry); + + return geometry; + } + + #endregion + /// /// Read the vertices from a file, which may be a .node or .poly file. /// @@ -451,6 +477,11 @@ namespace TriangleNet.IO return data; } + /// + /// Read elements from an .ele file. + /// + /// The file name. + /// A list of triangles. public static List ReadEleFile(string elefilename) { return ReadEleFile(elefilename, false); @@ -589,6 +620,12 @@ namespace TriangleNet.IO return data; } + /// + /// Read an .edge file. + /// + /// The file name. + /// The number of input vertices (read from a .node or .poly file). + /// A List of edges. public static List ReadEdgeFile(string edgeFile, int invertices) { // Read poly file diff --git a/Triangle.NET/Triangle/IO/FileWriter.cs b/Triangle.NET/Triangle/IO/FileWriter.cs index e2420ee..a0a9cd2 100644 --- a/Triangle.NET/Triangle/IO/FileWriter.cs +++ b/Triangle.NET/Triangle/IO/FileWriter.cs @@ -14,16 +14,12 @@ namespace TriangleNet.IO using TriangleNet.Geometry; /// - /// TODO: Update summary. + /// Helper methods for writing Triangle file formats. /// public static class FileWriter { static NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat; - // TODO: Intelligent file name guessing - - #region File IO - /// /// Number the vertices and write them to a .node file. /// @@ -500,7 +496,5 @@ namespace TriangleNet.IO } } } - - #endregion } } diff --git a/Triangle.NET/Triangle/IO/IGeometryFormat.cs b/Triangle.NET/Triangle/IO/IGeometryFormat.cs new file mode 100644 index 0000000..43e329d --- /dev/null +++ b/Triangle.NET/Triangle/IO/IGeometryFormat.cs @@ -0,0 +1,27 @@ +// ----------------------------------------------------------------------- +// +// TODO: Update copyright text. +// +// ----------------------------------------------------------------------- + +namespace TriangleNet.IO +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using TriangleNet.Geometry; + + /// + /// Interface for geometry input. + /// + public interface IGeometryFormat + { + /// + /// Read a file containing geometry information. + /// + /// The path of the file to read. + /// An instance of the class. + InputGeometry Read(string filename); + } +} diff --git a/Triangle.NET/Triangle/IO/IMeshFormat.cs b/Triangle.NET/Triangle/IO/IMeshFormat.cs new file mode 100644 index 0000000..788d8ff --- /dev/null +++ b/Triangle.NET/Triangle/IO/IMeshFormat.cs @@ -0,0 +1,34 @@ +// ----------------------------------------------------------------------- +// +// TODO: Update copyright text. +// +// ----------------------------------------------------------------------- + +namespace TriangleNet.IO +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using TriangleNet.Geometry; + + /// + /// Interface for mesh I/O. + /// + public interface IMeshFormat + { + /// + /// Read a file containing a mesh. + /// + /// The path of the file to read. + /// An instance of the class. + Mesh Import(string filename); + + /// + /// Save a mesh to disk. + /// + /// An instance of the class. + /// The path of the file to save. + void Write(Mesh mesh, string filename); + } +} diff --git a/Triangle.NET/Triangle/IO/TriangleFormat.cs b/Triangle.NET/Triangle/IO/TriangleFormat.cs new file mode 100644 index 0000000..06f47b2 --- /dev/null +++ b/Triangle.NET/Triangle/IO/TriangleFormat.cs @@ -0,0 +1,67 @@ +// ----------------------------------------------------------------------- +// +// TODO: Update copyright text. +// +// ----------------------------------------------------------------------- + +namespace TriangleNet.IO +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using TriangleNet.Geometry; + using System.IO; + + /// + /// Implements geometry and mesh file formats of the the original Triangle code. + /// + public class TriangleFormat : IGeometryFormat, IMeshFormat + { + public Mesh Import(string filename) + { + string ext = Path.GetExtension(filename); + + if (ext == ".node" || ext == ".poly" || ext == ".ele") + { + List triangles; + InputGeometry geometry; + + FileReader.Read(filename, out geometry, out triangles); + + if (geometry != null && triangles != null) + { + Mesh mesh = new Mesh(); + mesh.Load(geometry, triangles); + + return mesh; + } + } + + throw new NotSupportedException("Could not load '" + filename + "' file."); + } + + public void Write(Mesh mesh, string filename) + { + FileWriter.WritePoly(mesh, Path.ChangeExtension(filename, ".poly")); + FileWriter.WriteElements(mesh, Path.ChangeExtension(filename, ".ele")); + } + + public InputGeometry Read(string filename) + { + string ext = Path.GetExtension(filename); + + if (ext == ".node") + { + return FileReader.ReadNodeFile(filename); + } + + if (ext == ".poly") + { + return FileReader.ReadPolyFile(filename); + } + + throw new NotSupportedException("File format '" + ext + "' not supported."); + } + } +} diff --git a/Triangle.NET/Triangle/Mesh.cs b/Triangle.NET/Triangle/Mesh.cs index 25ff5b6..61bfdd2 100644 --- a/Triangle.NET/Triangle/Mesh.cs +++ b/Triangle.NET/Triangle/Mesh.cs @@ -194,29 +194,33 @@ namespace TriangleNet /// /// Load a mesh from file (.node/poly and .ele). /// - public void Load(string inputfile) + public void Load(string filename) { - InputGeometry input = FileReader.ReadFile(inputfile, true); + List triangles; + InputGeometry geometry; - this.Load(input); + FileReader.Read(filename, out geometry, out triangles); + + if (geometry != null && triangles != null) + { + Load(geometry, triangles); + } } /// /// Reconstructs a mesh from raw input data. /// - public void Load(InputGeometry input) + public void Load(InputGeometry input, List triangles) { - throw new NotImplementedException("Load"); - - if (input == null)// TODO: if (input.Triangles == null) + if (input == null || triangles == null) { - throw new ArgumentException("The input data contains no triangles."); + throw new ArgumentException("Invalid input (argument is null)."); } // Clear all data structures / reset hash seeds this.ResetData(); - if (input.Segments != null) + if (input.HasSegments) { Behavior.Poly = true; } @@ -245,7 +249,11 @@ namespace TriangleNet TransferNodes(input); // Read and reconstruct a mesh. - hullsize = DataReader.Reconstruct(this, input, null); + hullsize = DataReader.Reconstruct(this, input, triangles.ToArray()); + + + // Calculate the number of edges. + edges = (3 * triangles.Count + hullsize) / 2; } /// @@ -254,7 +262,7 @@ namespace TriangleNet /// public void Triangulate(string inputFile) { - InputGeometry input = FileReader.ReadFile(inputFile); + InputGeometry input = FileReader.Read(inputFile); this.Triangulate(input); } diff --git a/Triangle.NET/Triangle/Quality.cs b/Triangle.NET/Triangle/Quality.cs index ed1c273..dab80cf 100644 --- a/Triangle.NET/Triangle/Quality.cs +++ b/Triangle.NET/Triangle/Quality.cs @@ -197,8 +197,8 @@ namespace TriangleNet { if (Primitives.NonRegular(triorg, tridest, triapex, oppoapex) > 0.0) { - string coords = triorg.ToString() + " " + tridest.ToString(); - logger.Warning("Non-regular pair of triangles found. " + coords, "Quality.CheckDelaunay()"); + logger.Warning("Non-regular pair of triangles found (ID " + loop.triangle.id + ").", + "Quality.CheckDelaunay()"); horrors++; } } diff --git a/Triangle.NET/Triangle/Triangle.csproj b/Triangle.NET/Triangle/Triangle.csproj index 0a09499..cdb523a 100644 --- a/Triangle.NET/Triangle/Triangle.csproj +++ b/Triangle.NET/Triangle/Triangle.csproj @@ -63,8 +63,11 @@ + + +