Image export (png, eps and svg)
git-svn-id: https://triangle.svn.codeplex.com/svn@68154 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -53,11 +53,11 @@ namespace MeshExplorer.Controls
|
||||
//
|
||||
this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.textBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.textBox.Location = new System.Drawing.Point(3, 2);
|
||||
this.textBox.Location = new System.Drawing.Point(4, 2);
|
||||
this.textBox.Name = "textBox";
|
||||
this.textBox.TabIndex = 0;
|
||||
//
|
||||
// TextBoxDark
|
||||
// DarkTextBox
|
||||
//
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.Controls.Add(this.textBox);
|
||||
@@ -83,40 +83,49 @@ namespace MeshExplorer.Controls
|
||||
};
|
||||
|
||||
textBox.Font = this.Font;
|
||||
textBox.Location = new Point(3, (this.Height - textBox.Height) / 2 + 1);
|
||||
textBox.Location = new Point(4, (this.Height - textBox.Height) / 2);
|
||||
textBox.Width = this.Width - 8;
|
||||
textBox.TextAlign = HorizontalAlignment.Right;
|
||||
textBox.TextAlign = HorizontalAlignment.Left;
|
||||
textBox.ForeColor = this.ForeColor;
|
||||
textBox.MaxLength = 6;
|
||||
//textBox.MaxLength = 6;
|
||||
|
||||
textBox.GotFocus += delegate(object sender, EventArgs e)
|
||||
{
|
||||
textBox.ForeColor = Color.White;
|
||||
textBox.ForeColor = this.ForeColor;
|
||||
};
|
||||
|
||||
textBox.LostFocus += delegate(object sender, EventArgs e)
|
||||
{
|
||||
textBox.ForeColor = this.ForeColor;
|
||||
textBox.ForeColor = ColorScheme.ColorGray68;
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
|
||||
Rectangle rect = this.ClientRectangle;
|
||||
|
||||
Brush brushOuter = new LinearGradientBrush(rect, Color.FromArgb(82, 82, 82), Color.FromArgb(96, 96, 96),
|
||||
LinearGradientMode.Vertical);
|
||||
//Brush brushOuter = new LinearGradientBrush(rect, Color.FromArgb(82, 82, 82),
|
||||
// Color.FromArgb(96, 96, 96), LinearGradientMode.Vertical);
|
||||
|
||||
Pen brushBorder = new Pen(Color.FromArgb(38, 38, 38), 1f);
|
||||
Pen borderTop = new Pen(Color.FromArgb(76, 76, 76), 1f);
|
||||
Pen borderBottom = new Pen(Color.FromArgb(128, 128, 128), 1f);
|
||||
|
||||
e.Graphics.FillRectangle(brushOuter, rect);
|
||||
//e.Graphics.FillRectangle(brushOuter, rect);
|
||||
|
||||
rect = new Rectangle(1, 1, this.Width - 3, this.Height - 3);
|
||||
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), rect);
|
||||
g.FillRectangle(new SolidBrush(this.BackColor), rect);
|
||||
|
||||
e.Graphics.DrawRectangle(brushBorder, rect);
|
||||
g.DrawLine(borderTop, 0, 0, this.Width - 1, 0);
|
||||
g.DrawLine(borderTop, 0, 0, 0, this.Height - 1);
|
||||
g.DrawLine(borderBottom, 1, this.Height - 1, this.Width - 1, this.Height - 1);
|
||||
g.DrawLine(borderBottom, this.Width - 1, this.Height - 1, this.Width - 1, this.Height - 1);
|
||||
|
||||
brushOuter.Dispose();
|
||||
brushBorder.Dispose();
|
||||
|
||||
//brushOuter.Dispose();
|
||||
borderTop.Dispose();
|
||||
borderBottom.Dispose();
|
||||
|
||||
base.OnPaint(e);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace MeshExplorer.Controls
|
||||
{
|
||||
SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
renderColors = RenderColors.Default;
|
||||
renderColors = RenderColors.Default();
|
||||
|
||||
this.BackColor = renderColors.Background;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace MeshExplorer
|
||||
using TriangleNet.IO;
|
||||
using TriangleNet.Geometry;
|
||||
using MeshExplorer.IO;
|
||||
using MeshExplorer.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Code of the online examples.
|
||||
@@ -23,14 +24,14 @@ namespace MeshExplorer
|
||||
// Make sure this path points to the polygon sample data.
|
||||
static readonly string pathToData = @"..\..\..\Data\";
|
||||
|
||||
static ImageWriter imageWriter = new ImageWriter();
|
||||
static RasterImage imageWriter = new RasterImage();
|
||||
|
||||
/// <summary>
|
||||
/// Generating Delaunay triangulations
|
||||
/// </summary>
|
||||
public static void Example1()
|
||||
{
|
||||
imageWriter.SetColorSchemeLight();
|
||||
imageWriter.ColorScheme = RenderColors.LightScheme();
|
||||
|
||||
// Create a mesh instance.
|
||||
Mesh mesh = new Mesh();
|
||||
@@ -38,18 +39,18 @@ namespace MeshExplorer
|
||||
// Read spiral node file and gernerate the delaunay triangulation
|
||||
// of the point set.
|
||||
mesh.Triangulate(pathToData + "spiral.node");
|
||||
imageWriter.WritePng(mesh, "spiral.png", 180);
|
||||
imageWriter.Export(mesh, "spiral.png", 180);
|
||||
|
||||
// Read face polygon file and gernerate the delaunay triangulation
|
||||
// of the PSLG. We reuse the mesh instance here.
|
||||
InputGeometry data = FileReader.Read(pathToData + "face.poly");
|
||||
mesh.Triangulate(data);
|
||||
imageWriter.WritePng(mesh, "face.png", 200);
|
||||
imageWriter.Export(mesh, "face.png", 200);
|
||||
|
||||
// Generate a conforming delaunay triangulation of the face polygon.
|
||||
mesh.SetOption(Options.ConformingDelaunay, true);
|
||||
mesh.Triangulate(data);
|
||||
imageWriter.WritePng(mesh, "face-CDT.png", 200);
|
||||
imageWriter.Export(mesh, "face-CDT.png", 200);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -57,7 +58,7 @@ namespace MeshExplorer
|
||||
/// </summary>
|
||||
public static void Example2()
|
||||
{
|
||||
imageWriter.SetColorSchemeLight();
|
||||
imageWriter.ColorScheme = RenderColors.LightScheme();
|
||||
|
||||
// Create a mesh instance.
|
||||
Mesh mesh = new Mesh();
|
||||
@@ -68,18 +69,18 @@ namespace MeshExplorer
|
||||
InputGeometry data = FileReader.ReadNodeFile(pathToData + "spiral.node");
|
||||
mesh.SetOption(Options.Quality, true);
|
||||
mesh.Triangulate(data);
|
||||
imageWriter.WritePng(mesh, "spiral-Angle-20.png", 200);
|
||||
imageWriter.Export(mesh, "spiral-Angle-20.png", 200);
|
||||
|
||||
// Set a minimum angle of 30 degrees.
|
||||
mesh.SetOption(Options.MinAngle, 35);
|
||||
mesh.Triangulate(data);
|
||||
imageWriter.WritePng(mesh, "spiral-Angle-35.png", 200);
|
||||
imageWriter.Export(mesh, "spiral-Angle-35.png", 200);
|
||||
|
||||
// Reset the minimum angle and add a global area constraint.
|
||||
mesh.SetOption(Options.MinAngle, 20);
|
||||
mesh.SetOption(Options.MaxArea, 0.2);
|
||||
mesh.Triangulate(data);
|
||||
imageWriter.WritePng(mesh, "spiral-Area.png", 200);
|
||||
imageWriter.Export(mesh, "spiral-Area.png", 200);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -87,7 +88,7 @@ namespace MeshExplorer
|
||||
/// </summary>
|
||||
public static void Example3()
|
||||
{
|
||||
imageWriter.SetColorSchemeLight();
|
||||
imageWriter.ColorScheme = RenderColors.LightScheme();
|
||||
|
||||
// Create a mesh instance.
|
||||
Mesh mesh = new Mesh();
|
||||
@@ -97,7 +98,7 @@ namespace MeshExplorer
|
||||
mesh.SetOption(Options.Quality, true);
|
||||
mesh.SetOption(Options.Convex, true);
|
||||
mesh.Triangulate(pathToData + "box.poly");
|
||||
imageWriter.WritePng(mesh, "box.png", 200);
|
||||
imageWriter.Export(mesh, "box.png", 200);
|
||||
|
||||
// Save the current mesh to .node and .ele files
|
||||
FileWriter.WriteNodes(mesh, "box.1.node");
|
||||
@@ -105,11 +106,11 @@ namespace MeshExplorer
|
||||
|
||||
// Refine the mesh by setting a global area constraint.
|
||||
mesh.Refine(0.2);
|
||||
imageWriter.WritePng(mesh, "box-Refine-1.png", 200);
|
||||
imageWriter.Export(mesh, "box-Refine-1.png", 200);
|
||||
|
||||
// Refine again by setting a smaller area constraint.
|
||||
mesh.Refine(0.05);
|
||||
imageWriter.WritePng(mesh, "box-Refine-2.png", 200);
|
||||
imageWriter.Export(mesh, "box-Refine-2.png", 200);
|
||||
|
||||
// Load the previously saved box.1 mesh. Since a box.1.area
|
||||
// file exist, the variable area constraint option is set
|
||||
@@ -117,7 +118,7 @@ namespace MeshExplorer
|
||||
mesh.Load(pathToData + "box.1.node");
|
||||
mesh.SetOption(Options.MinAngle, 0);
|
||||
mesh.Refine();
|
||||
imageWriter.WritePng(mesh, "box-Refine-3.png", 200);
|
||||
imageWriter.Export(mesh, "box-Refine-3.png", 200);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+98
-7
@@ -28,26 +28,105 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.lbSize = new System.Windows.Forms.Label();
|
||||
this.darkSlider1 = new MeshExplorer.Controls.DarkSlider();
|
||||
this.darkTextBox1 = new MeshExplorer.Controls.DarkTextBox();
|
||||
this.darkListBox1 = new MeshExplorer.Controls.DarkListBox();
|
||||
this.darkButton1 = new MeshExplorer.Controls.DarkButton();
|
||||
this.btnExport = new MeshExplorer.Controls.DarkButton();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label2.Location = new System.Drawing.Point(12, 9);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(65, 13);
|
||||
this.label2.TabIndex = 2;
|
||||
this.label2.Text = "File fromat:\r\n";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label3.Location = new System.Drawing.Point(12, 198);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(59, 13);
|
||||
this.label3.TabIndex = 2;
|
||||
this.label3.Text = "File name:";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label1.Location = new System.Drawing.Point(12, 9);
|
||||
this.label1.Location = new System.Drawing.Point(12, 156);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(302, 39);
|
||||
this.label1.Size = new System.Drawing.Size(74, 13);
|
||||
this.label1.TabIndex = 2;
|
||||
this.label1.Text = "No options available at the moment.\r\n\r\nYou will find the saved image in the appli" +
|
||||
"cation directory.";
|
||||
this.label1.Text = "Image width:";
|
||||
//
|
||||
// lbSize
|
||||
//
|
||||
this.lbSize.AutoSize = true;
|
||||
this.lbSize.BackColor = System.Drawing.Color.Transparent;
|
||||
this.lbSize.ForeColor = System.Drawing.Color.Gray;
|
||||
this.lbSize.Location = new System.Drawing.Point(272, 156);
|
||||
this.lbSize.Name = "lbSize";
|
||||
this.lbSize.Size = new System.Drawing.Size(40, 13);
|
||||
this.lbSize.TabIndex = 2;
|
||||
this.lbSize.Text = "800 px";
|
||||
//
|
||||
// darkSlider1
|
||||
//
|
||||
this.darkSlider1.BackColor = System.Drawing.Color.Transparent;
|
||||
this.darkSlider1.CriticalPercent = ((uint)(0u));
|
||||
this.darkSlider1.Location = new System.Drawing.Point(15, 169);
|
||||
this.darkSlider1.Maximum = 100;
|
||||
this.darkSlider1.Minimum = 0;
|
||||
this.darkSlider1.Name = "darkSlider1";
|
||||
this.darkSlider1.Size = new System.Drawing.Size(297, 17);
|
||||
this.darkSlider1.TabIndex = 5;
|
||||
this.darkSlider1.Text = "darkSlider1";
|
||||
this.darkSlider1.Value = 35;
|
||||
this.darkSlider1.ValueChanging += new System.EventHandler(this.darkSlider1_ValueChanging);
|
||||
//
|
||||
// darkTextBox1
|
||||
//
|
||||
this.darkTextBox1.BackColor = System.Drawing.Color.White;
|
||||
this.darkTextBox1.Cursor = System.Windows.Forms.Cursors.IBeam;
|
||||
this.darkTextBox1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.darkTextBox1.ForeColor = System.Drawing.Color.Black;
|
||||
this.darkTextBox1.Location = new System.Drawing.Point(12, 214);
|
||||
this.darkTextBox1.Name = "darkTextBox1";
|
||||
this.darkTextBox1.Size = new System.Drawing.Size(300, 21);
|
||||
this.darkTextBox1.TabIndex = 4;
|
||||
this.darkTextBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Left;
|
||||
//
|
||||
// darkListBox1
|
||||
//
|
||||
this.darkListBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(96)))), ((int)(((byte)(96)))), ((int)(((byte)(96)))));
|
||||
this.darkListBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.darkListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
|
||||
this.darkListBox1.FormattingEnabled = true;
|
||||
this.darkListBox1.ItemHeight = 22;
|
||||
this.darkListBox1.Items.AddRange(new object[] {
|
||||
"Portable Network Graphics (*.png)",
|
||||
"Encapsulated PostScript (*.eps)",
|
||||
"Scalable Vector Graphics (*.svg)"});
|
||||
this.darkListBox1.Location = new System.Drawing.Point(12, 25);
|
||||
this.darkListBox1.Name = "darkListBox1";
|
||||
this.darkListBox1.Size = new System.Drawing.Size(302, 118);
|
||||
this.darkListBox1.TabIndex = 3;
|
||||
this.darkListBox1.SelectedIndexChanged += new System.EventHandler(this.darkListBox1_SelectedIndexChanged);
|
||||
//
|
||||
// darkButton1
|
||||
//
|
||||
this.darkButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.darkButton1.Location = new System.Drawing.Point(162, 141);
|
||||
this.darkButton1.Location = new System.Drawing.Point(144, 270);
|
||||
this.darkButton1.Name = "darkButton1";
|
||||
this.darkButton1.Size = new System.Drawing.Size(82, 23);
|
||||
this.darkButton1.TabIndex = 1;
|
||||
@@ -57,7 +136,7 @@
|
||||
// btnExport
|
||||
//
|
||||
this.btnExport.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.btnExport.Location = new System.Drawing.Point(250, 141);
|
||||
this.btnExport.Location = new System.Drawing.Point(232, 270);
|
||||
this.btnExport.Name = "btnExport";
|
||||
this.btnExport.Size = new System.Drawing.Size(82, 23);
|
||||
this.btnExport.TabIndex = 0;
|
||||
@@ -69,8 +148,14 @@
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
|
||||
this.ClientSize = new System.Drawing.Size(344, 172);
|
||||
this.ClientSize = new System.Drawing.Size(324, 299);
|
||||
this.Controls.Add(this.darkSlider1);
|
||||
this.Controls.Add(this.darkTextBox1);
|
||||
this.Controls.Add(this.darkListBox1);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.lbSize);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.darkButton1);
|
||||
this.Controls.Add(this.btnExport);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
@@ -91,6 +176,12 @@
|
||||
|
||||
private Controls.DarkButton btnExport;
|
||||
private Controls.DarkButton darkButton1;
|
||||
private Controls.DarkListBox darkListBox1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private Controls.DarkTextBox darkTextBox1;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private Controls.DarkSlider darkSlider1;
|
||||
private System.Windows.Forms.Label lbSize;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
@@ -16,6 +17,28 @@ namespace MeshExplorer
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public int ImageFormat
|
||||
{
|
||||
get { return darkListBox1.SelectedIndex; }
|
||||
}
|
||||
|
||||
public int ImageSize
|
||||
{
|
||||
get
|
||||
{
|
||||
string s = lbSize.Text;
|
||||
s = s.Substring(0, s.Length - 3);
|
||||
int size = 0;
|
||||
int.TryParse(s, out size);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
public string ImageName
|
||||
{
|
||||
get { return darkTextBox1.Text; }
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
@@ -25,5 +48,35 @@ namespace MeshExplorer
|
||||
|
||||
e.Graphics.FillRectangle(Brushes.DimGray, rect);
|
||||
}
|
||||
|
||||
private void darkListBox1_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
string filename = darkTextBox1.Text;
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
string ext = ".png";
|
||||
|
||||
if (darkListBox1.SelectedIndex == 1)
|
||||
{
|
||||
ext = ".eps";
|
||||
}
|
||||
else if (darkListBox1.SelectedIndex == 2)
|
||||
{
|
||||
ext = ".svg";
|
||||
}
|
||||
|
||||
darkTextBox1.Text = Path.ChangeExtension(filename, ext);
|
||||
}
|
||||
}
|
||||
|
||||
private void darkSlider1_ValueChanging(object sender, EventArgs e)
|
||||
{
|
||||
int size = (int)((2000.0 - 200.0) / 100.0 * darkSlider1.Value + 200.0);
|
||||
|
||||
size = size - (size % 50);
|
||||
|
||||
lbSize.Text = size + " px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using MeshExplorer.IO;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Tools;
|
||||
using MeshExplorer.Rendering;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
@@ -319,21 +320,25 @@ namespace MeshExplorer
|
||||
HandleMeshImport();
|
||||
}
|
||||
// else Message
|
||||
|
||||
// Update folder settings
|
||||
settings.OfdFilterIndex = ofd.FilterIndex;
|
||||
settings.OfdDirectory = Path.GetFullPath(ofd.FileName);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
input = FileProcessor.Read(ofd.FileName);
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
input = FileProcessor.Read(ofd.FileName);
|
||||
// Update settings
|
||||
settings.CurrentFile = Path.GetFileName(ofd.FileName);
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
// Update settings
|
||||
settings.CurrentFile = Path.GetFileName(ofd.FileName);
|
||||
|
||||
HandleNewInput();
|
||||
}
|
||||
// else Message
|
||||
HandleNewInput();
|
||||
}
|
||||
// else Message
|
||||
|
||||
// Update folder settings
|
||||
settings.OfdFilterIndex = ofd.FilterIndex;
|
||||
@@ -588,8 +593,25 @@ namespace MeshExplorer
|
||||
|
||||
if (export.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
ImageWriter imgWriter = new ImageWriter();
|
||||
imgWriter.WritePng(this.mesh);
|
||||
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 = RenderColors.LightScheme();
|
||||
img.Export(this.mesh, export.ImageName, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="EpsImage.cs" company="">
|
||||
// John Burkardt, Florida State University
|
||||
// http://people.sc.fsu.edu/~jburkardt/m_src/fem2d_poisson/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MeshExplorer.Rendering;
|
||||
using System.IO;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Writes a mesh to an EPS file.
|
||||
/// </summary>
|
||||
public class EpsImage
|
||||
{
|
||||
// EPS page metrics
|
||||
int x_ps_max = 576;
|
||||
int x_ps_max_clip = 594;
|
||||
int x_ps_min = 36;
|
||||
int x_ps_min_clip = 18;
|
||||
int y_ps_max = 666;
|
||||
int y_ps_max_clip = 684;
|
||||
int y_ps_min = 126;
|
||||
int y_ps_min_clip = 108;
|
||||
|
||||
// Mesh metrics
|
||||
double x_max, x_min;
|
||||
double y_max, y_min;
|
||||
double x_scale, y_scale;
|
||||
|
||||
public void Export(Mesh mesh, string filename, int width)
|
||||
{
|
||||
// Check file name
|
||||
if (String.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
filename = String.Format("mesh-{0}.eps", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
|
||||
}
|
||||
|
||||
if (!filename.EndsWith(".eps"))
|
||||
{
|
||||
filename = Path.ChangeExtension(filename, ".eps");
|
||||
}
|
||||
|
||||
UpdateMetrics(mesh.Bounds);
|
||||
|
||||
using (StreamWriter eps = new StreamWriter(filename))
|
||||
{
|
||||
WriteHeader(filename, eps);
|
||||
|
||||
DrawClip(eps);
|
||||
|
||||
DrawTriangles(eps, mesh, false);
|
||||
|
||||
DrawSegments(eps, mesh);
|
||||
|
||||
DrawPoints(eps, mesh, false);
|
||||
|
||||
WriteTrailer(eps);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteHeader(string filename, StreamWriter eps)
|
||||
{
|
||||
eps.WriteLine("%!PS-Adobe-3.0 EPSF-3.0");
|
||||
eps.WriteLine("%%Creator: Triangle.NET Mesh Explorer");
|
||||
eps.WriteLine("%%Title: {0}", filename);
|
||||
eps.WriteLine("%%Pages: 1");
|
||||
eps.WriteLine("%%BoundingBox: {0} {1} {2} {3}", x_ps_min, y_ps_min, x_ps_max, y_ps_max);
|
||||
eps.WriteLine("%%Document-Fonts: Times-Roman");
|
||||
eps.WriteLine("%%LanguageLevel: 1");
|
||||
eps.WriteLine("%%EndComments");
|
||||
eps.WriteLine("%%BeginProlog");
|
||||
eps.WriteLine("/inch {72 mul} def");
|
||||
eps.WriteLine("%%EndProlog");
|
||||
eps.WriteLine("%%Page: 1 1");
|
||||
}
|
||||
|
||||
private static void WriteTrailer(StreamWriter eps)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("restore showpage");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% End of page.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("%%Trailer");
|
||||
eps.WriteLine("%%EOF");
|
||||
}
|
||||
|
||||
private void DrawClip(StreamWriter eps)
|
||||
{
|
||||
eps.WriteLine("save");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to very light gray.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.900 0.900 0.900 setrgbcolor");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw a gray border around the page.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("newpath");
|
||||
eps.WriteLine(" {0} {1} moveto", x_ps_min, y_ps_min);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max, y_ps_min);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max, y_ps_max);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min, y_ps_max);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min, y_ps_min);
|
||||
eps.WriteLine("stroke");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to black.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.000 0.000 0.000 setrgbcolor");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the font and its size.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.50 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Print a title.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("%210 702 moveto");
|
||||
eps.WriteLine("%(Triangulation) show");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Define a clipping polygon.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("newpath");
|
||||
eps.WriteLine(" {0} {1} moveto", x_ps_min_clip, y_ps_min_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max_clip, y_ps_min_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max_clip, y_ps_max_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min_clip, y_ps_max_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min_clip, y_ps_min_clip);
|
||||
eps.WriteLine("clip newpath");
|
||||
}
|
||||
|
||||
private void DrawTriangles(StreamWriter eps, Mesh mesh, bool label)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the triangle line color and width.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.6 0.6 0.6 setrgbcolor");
|
||||
eps.WriteLine("0.5 setlinewidth");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw the triangles.");
|
||||
eps.WriteLine("%");
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
double x1, y1, x2, y2, x3, y3, xa, ya;
|
||||
int x_ps, y_ps;
|
||||
|
||||
foreach (var tri in mesh.Triangles)
|
||||
{
|
||||
eps.WriteLine("newpath");
|
||||
|
||||
x1 = tri[0].X; y1 = tri[0].Y;
|
||||
x2 = tri[1].X; y2 = tri[1].Y;
|
||||
x3 = tri[2].X; y3 = tri[2].Y;
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - x1) * x_ps_min + (x1 - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - y1) * y_ps_min + (y1 - y_min) * y_ps_max) / (y_max - y_min));
|
||||
eps.WriteLine(" {0} {1} moveto", x_ps, y_ps);
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - x2) * x_ps_min + (x2 - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - y2) * y_ps_min + (y2 - y_min) * y_ps_max) / (y_max - y_min));
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - x3) * x_ps_min + (x3 - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - y3) * y_ps_min + (y3 - y_min) * y_ps_max) / (y_max - y_min));
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - x1) * x_ps_min + (x1 - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - y1) * y_ps_min + (y1 - y_min) * y_ps_max) / (y_max - y_min));
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
|
||||
|
||||
if (label)
|
||||
{
|
||||
xa = (x1 + x2 + x3) / 3.0;
|
||||
ya = (y1 + y2 + y3) / 3.0;
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - xa) * x_ps_min + (xa - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - ya) * y_ps_min + (ya - y_min) * y_ps_max) / (y_max - y_min));
|
||||
|
||||
labels.AppendFormat(" {0} {1} moveto ({2}) show", x_ps, y_ps, tri.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
|
||||
eps.WriteLine("stroke");
|
||||
}
|
||||
|
||||
// Label the triangles.
|
||||
if (label)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Label the triangles.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to darker red.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.950 0.250 0.150 setrgbcolor");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.20 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
|
||||
eps.Write(labels.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSegments(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the triangle line color and width.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.27 0.5 0.7 setrgbcolor");
|
||||
eps.WriteLine("0.75 setlinewidth");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw the triangles.");
|
||||
eps.WriteLine("%");
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
double x1, y1, x2, y2;
|
||||
int x_ps, y_ps;
|
||||
|
||||
foreach (var seg in mesh.Segments)
|
||||
{
|
||||
eps.WriteLine("newpath");
|
||||
|
||||
x1 = seg[0].X; y1 = seg[0].Y;
|
||||
x2 = seg[1].X; y2 = seg[1].Y;
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - x1) * x_ps_min + (x1 - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - y1) * y_ps_min + (y1 - y_min) * y_ps_max) / (y_max - y_min));
|
||||
eps.WriteLine(" {0} {1} moveto", x_ps, y_ps);
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - x2) * x_ps_min + (x2 - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - y2) * y_ps_min + (y2 - y_min) * y_ps_max) / (y_max - y_min));
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
|
||||
|
||||
|
||||
eps.WriteLine("stroke");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPoints(StreamWriter eps, Mesh mesh, bool label)
|
||||
{
|
||||
int n = mesh.NumberOfVertices;
|
||||
|
||||
int circle_size = 1;
|
||||
|
||||
if (n < 100)
|
||||
{
|
||||
circle_size = 3;
|
||||
}
|
||||
else if (n < 500)
|
||||
{
|
||||
circle_size = 2;
|
||||
}
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw filled dots at the nodes.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to blue.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.0 0.4 0.0 setrgbcolor");
|
||||
eps.WriteLine("%");
|
||||
|
||||
double x, y;
|
||||
int x_ps, y_ps;
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
x = node.X;
|
||||
y = node.Y;
|
||||
|
||||
x_ps = (int)Math.Floor(((x_max - x) * x_ps_min + (x - x_min) * x_ps_max) / (x_max - x_min));
|
||||
y_ps = (int)Math.Floor(((y_max - y) * y_ps_min + (y - y_min) * y_ps_max) / (y_max - y_min));
|
||||
|
||||
eps.WriteLine(" newpath {0} {1} {2} 0 360 arc closepath fill", x_ps, y_ps, circle_size);
|
||||
|
||||
if (label)
|
||||
{
|
||||
labels.AppendFormat(" {0} {1} moveto ({2}) show", x_ps, y_ps + 5, node);
|
||||
labels.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
// Label the nodes.
|
||||
if (label)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Label the nodes.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to darker blue.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.000 0.250 0.850 setrgbcolor");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.20 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
|
||||
eps.Write(labels.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMetrics(BoundingBox bounds)
|
||||
{
|
||||
x_max = bounds.Xmax;
|
||||
x_min = bounds.Xmin;
|
||||
y_max = bounds.Ymax;
|
||||
y_min = bounds.Ymin;
|
||||
|
||||
// Enlarge width 5% on each side
|
||||
x_scale = x_max - x_min;
|
||||
x_max = x_max + 0.05 * x_scale;
|
||||
x_min = x_min - 0.05 * x_scale;
|
||||
x_scale = x_max - x_min;
|
||||
|
||||
// Enlarge height 5% on each side
|
||||
y_scale = y_max - y_min;
|
||||
y_max = y_max + 0.05 * y_scale;
|
||||
y_min = y_min - 0.05 * y_scale;
|
||||
y_scale = y_max - y_min;
|
||||
|
||||
if (x_scale < y_scale)
|
||||
{
|
||||
int delta = (int)Math.Round((x_ps_max - x_ps_min) * (y_scale - x_scale) / (2.0 * y_scale));
|
||||
|
||||
x_ps_max = x_ps_max - delta;
|
||||
x_ps_min = x_ps_min + delta;
|
||||
|
||||
x_ps_max_clip = x_ps_max_clip - delta;
|
||||
x_ps_min_clip = x_ps_min_clip + delta;
|
||||
|
||||
x_scale = y_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
int delta = (int)Math.Round((y_ps_max - y_ps_min) * (x_scale - y_scale) / (2.0 * x_scale));
|
||||
|
||||
y_ps_max = y_ps_max - delta;
|
||||
y_ps_min = y_ps_min + delta;
|
||||
|
||||
y_ps_max_clip = y_ps_max_clip - delta;
|
||||
y_ps_min_clip = y_ps_min_clip + delta;
|
||||
|
||||
y_scale = x_scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,82 +20,14 @@ namespace MeshExplorer.IO
|
||||
/// <summary>
|
||||
/// Writes an image of the mesh to disk.
|
||||
/// </summary>
|
||||
public class ImageWriter
|
||||
public class RasterImage
|
||||
{
|
||||
RenderColors colors = RenderColors.Default;
|
||||
RenderColors colors = RenderColors.Default();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the color scheme.
|
||||
/// </summary>
|
||||
/// <param name="background">Background color.</param>
|
||||
/// <param name="points">Points color.</param>
|
||||
/// <param name="steiner">Steiner points color.</param>
|
||||
/// <param name="lines">Line color.</param>
|
||||
/// <param name="segments">Segment color.</param>
|
||||
public void SetColorScheme(Color background, Color points, Color steiner,
|
||||
Color lines, Color segments, Color triangles)
|
||||
public RenderColors ColorScheme
|
||||
{
|
||||
colors.Background = background;
|
||||
colors.Point = new SolidBrush(points);
|
||||
colors.SteinerPoint = new SolidBrush(steiner);
|
||||
colors.Triangle = new SolidBrush(triangles);
|
||||
colors.Line = new Pen(lines);
|
||||
colors.Segment = new Pen(segments);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a color scheme with white background.
|
||||
/// </summary>
|
||||
public void SetColorSchemeLight()
|
||||
{
|
||||
colors.Background = Color.White;
|
||||
colors.Point = new SolidBrush(Color.MidnightBlue);
|
||||
colors.SteinerPoint = new SolidBrush(Color.DarkGreen);
|
||||
colors.Triangle = new SolidBrush(Color.FromArgb(230, 240, 250));
|
||||
colors.Line = new Pen(Color.FromArgb(150, 150, 150));
|
||||
colors.Segment = new Pen(Color.SteelBlue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a color scheme with black background.
|
||||
/// </summary>
|
||||
public void SetColorSchemeDark()
|
||||
{
|
||||
colors.Background = Color.Black;
|
||||
colors.Point = new SolidBrush(Color.Green);
|
||||
colors.SteinerPoint = new SolidBrush(Color.Peru);
|
||||
colors.Triangle = new SolidBrush(Color.FromArgb(30, 40, 50));
|
||||
colors.Line = new Pen(Color.FromArgb(30, 30, 30));
|
||||
colors.Segment = new Pen(Color.Blue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the mesh and writes the image file.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The mesh to visualize.</param>
|
||||
public void WritePng(Mesh mesh)
|
||||
{
|
||||
WritePng(mesh, "", 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the mesh and writes the image file.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The mesh to visualize.</param>
|
||||
/// <param name="filename">The filename (only PNG supported).</param>
|
||||
public void WritePng(Mesh mesh, string filename)
|
||||
{
|
||||
WritePng(mesh, filename, 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the mesh and writes the image file.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The mesh to visualize.</param>
|
||||
/// <param name="width">The target width of the image (pixel).</param>
|
||||
public void WritePng(Mesh mesh, int width)
|
||||
{
|
||||
WritePng(mesh, "", width);
|
||||
get { return colors; }
|
||||
set { colors = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -104,7 +36,7 @@ namespace MeshExplorer.IO
|
||||
/// <param name="mesh">The mesh to visualize.</param>
|
||||
/// <param name="filename">The filename (only PNG supported).</param>
|
||||
/// <param name="width">The target width of the image (pixel).</param>
|
||||
public void WritePng(Mesh mesh, string filename, int width)
|
||||
public void Export(Mesh mesh, string filename, int width)
|
||||
{
|
||||
// Get mesh data -- TODO: Use RenderControl's RenderData
|
||||
RenderData data = new RenderData();
|
||||
@@ -0,0 +1,196 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="SvgImage.cs" company="">
|
||||
// TODO: Update copyright text.
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MeshExplorer.Rendering;
|
||||
using System.IO;
|
||||
using TriangleNet;
|
||||
|
||||
/// <summary>
|
||||
/// Writes a mesh to an SVG file.
|
||||
/// </summary>
|
||||
public class SvgImage
|
||||
{
|
||||
float scale = 1f;
|
||||
|
||||
int x_offset = 0;
|
||||
int y_offset = 0;
|
||||
|
||||
public void Export(Mesh mesh, string filename, int width)
|
||||
{
|
||||
// Check file name
|
||||
if (String.IsNullOrWhiteSpace(filename))
|
||||
{
|
||||
filename = String.Format("mesh-{0}.svg", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
|
||||
}
|
||||
|
||||
if (!filename.EndsWith(".svg"))
|
||||
{
|
||||
filename = Path.ChangeExtension(filename, ".svg");
|
||||
}
|
||||
|
||||
if (width < 200)
|
||||
{
|
||||
width = 200;
|
||||
}
|
||||
|
||||
var bounds = mesh.Bounds;
|
||||
|
||||
float margin = 0.05f * (float)bounds.Width;
|
||||
|
||||
scale = width / ((float)bounds.Width + 2 * margin);
|
||||
|
||||
x_offset = -(int)((bounds.Xmin - margin) * scale);
|
||||
y_offset = (int)((bounds.Ymax + margin) * scale);
|
||||
|
||||
int height = (int)((bounds.Height + 2 * margin) * scale);
|
||||
|
||||
using (StreamWriter svg = new StreamWriter(filename))
|
||||
{
|
||||
svg.WriteLine("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"");
|
||||
svg.WriteLine(" width=\"{0}px\" height=\"{1}px\"", width, height);
|
||||
svg.WriteLine(" viewBox=\"0 0 {0} {1}\">", width, height);
|
||||
|
||||
svg.WriteLine("<g transform=\"translate({0}, {1}) scale(1,-1)\">", x_offset, y_offset);
|
||||
|
||||
DrawTriangles(svg, mesh, false);
|
||||
|
||||
DrawSegments(svg, mesh);
|
||||
|
||||
DrawPoints(svg, mesh, false);
|
||||
|
||||
svg.WriteLine("</g>");
|
||||
|
||||
svg.WriteLine("</svg>");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTriangles(StreamWriter svg, Mesh mesh, bool label)
|
||||
{
|
||||
svg.Write(" <path d=\"");
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
double x1, y1, x2, y2, x3, y3, xa, ya;
|
||||
|
||||
foreach (var tri in mesh.Triangles)
|
||||
{
|
||||
x1 = scale * tri[0].X;
|
||||
y1 = scale * tri[0].Y;
|
||||
x2 = scale * tri[1].X;
|
||||
y2 = scale * tri[1].Y;
|
||||
x3 = scale * tri[2].X;
|
||||
y3 = scale * tri[2].Y;
|
||||
|
||||
svg.Write("M {0},{1} L {2},{3} {4},{5} Z ",
|
||||
x1.ToString("0.0", Util.Nfi), y1.ToString("0.0", Util.Nfi),
|
||||
x2.ToString("0.0", Util.Nfi), y2.ToString("0.0", Util.Nfi),
|
||||
x3.ToString("0.0", Util.Nfi), y3.ToString("0.0", Util.Nfi));
|
||||
|
||||
if (label)
|
||||
{
|
||||
xa = (x1 + x2 + x3) / 3.0;
|
||||
ya = (y1 + y2 + y3) / 3.0;
|
||||
|
||||
labels.AppendFormat("<text x=\"{0}\" y=\"{1}\">{2}</text>",
|
||||
xa.ToString("0.0", Util.Nfi), ya.ToString("0.0", Util.Nfi), tri.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
svg.WriteLine("\" style=\"stroke:#969696; fill:none; stroke-linejoin:bevel;\"/>");
|
||||
|
||||
// Label the triangles.
|
||||
if (label)
|
||||
{
|
||||
svg.WriteLine(" <g font-family=\"Verdana\" font-size=\"11\" fill=\"black\">");
|
||||
svg.Write(labels.ToString());
|
||||
svg.WriteLine(" <g/>");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSegments(StreamWriter svg, Mesh mesh)
|
||||
{
|
||||
svg.Write(" <path d=\"");
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
foreach (var seg in mesh.Segments)
|
||||
{
|
||||
x1 = scale * seg[0].X;
|
||||
y1 = scale * seg[0].Y;
|
||||
x2 = scale * seg[1].X;
|
||||
y2 = scale * seg[1].Y;
|
||||
|
||||
svg.Write("M {0},{1} L {2},{3} ",
|
||||
x1.ToString("0.0", Util.Nfi), y1.ToString("0.0", Util.Nfi),
|
||||
x2.ToString("0.0", Util.Nfi), y2.ToString("0.0", Util.Nfi));
|
||||
}
|
||||
|
||||
svg.WriteLine("\" style=\"stroke:#4682B4; fill:none; stroke-linejoin:bevel; stroke-width:2px;\"/>");
|
||||
}
|
||||
|
||||
private void DrawPoints(StreamWriter svg, Mesh mesh, bool label)
|
||||
{
|
||||
int n = mesh.NumberOfVertices;
|
||||
|
||||
int circle_size = 1;
|
||||
|
||||
if (n < 100)
|
||||
{
|
||||
circle_size = 4;
|
||||
}
|
||||
else if (n < 500)
|
||||
{
|
||||
circle_size = 3;
|
||||
}
|
||||
else if (n < 1000)
|
||||
{
|
||||
circle_size = 2;
|
||||
}
|
||||
|
||||
svg.WriteLine(" <g style=\"fill: #006400\">");
|
||||
|
||||
double x, y;
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
x = scale * node.X;
|
||||
y = scale * node.Y;
|
||||
|
||||
svg.WriteLine(" <circle cx=\"{0}\" cy=\"{1}\" r=\"{2}\" />",
|
||||
x.ToString("0.0", Util.Nfi), y.ToString("0.0", Util.Nfi), circle_size);
|
||||
|
||||
if (label)
|
||||
{
|
||||
labels.AppendFormat("<text x=\"{0}\" y=\"{1}\">{2}</text>",
|
||||
x.ToString("0.0", Util.Nfi), y.ToString("0.0", Util.Nfi), node.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
svg.WriteLine(" </g>");
|
||||
|
||||
// Label the nodes.
|
||||
if (label)
|
||||
{
|
||||
svg.WriteLine(" <g font-family=\"Verdana\" font-size=\"11\" fill=\"black\">");
|
||||
svg.Write(labels.ToString());
|
||||
svg.WriteLine(" <g/>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,13 +105,15 @@
|
||||
<Compile Include="Generators\RandomPointsCircle.cs" />
|
||||
<Compile Include="Generators\RingPolygon.cs" />
|
||||
<Compile Include="Generators\StarInBox.cs" />
|
||||
<Compile Include="IO\ImageWriter.cs" />
|
||||
<Compile Include="IO\EpsImage.cs" />
|
||||
<Compile Include="IO\FileProcessor.cs" />
|
||||
<Compile Include="IO\Formats\DatFile.cs" />
|
||||
<Compile Include="IO\Formats\JsonFile.cs" />
|
||||
<Compile Include="IO\Formats\TriangleFile.cs" />
|
||||
<Compile Include="IO\IMeshFile.cs" />
|
||||
<Compile Include="IO\JsonParser.cs" />
|
||||
<Compile Include="IO\RasterImage.cs" />
|
||||
<Compile Include="IO\SvgImage.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Rendering\MeshRenderer.cs" />
|
||||
|
||||
@@ -17,16 +17,40 @@ namespace MeshExplorer.Rendering
|
||||
/// </summary>
|
||||
public class RenderColors
|
||||
{
|
||||
public static RenderColors Default = new RenderColors()
|
||||
/// <summary>
|
||||
/// Gets a color scheme with black background.
|
||||
/// </summary>
|
||||
public static RenderColors Default()
|
||||
{
|
||||
Background = Color.FromArgb(0, 0, 0),
|
||||
Point = new SolidBrush(Color.Green),
|
||||
SteinerPoint = new SolidBrush(Color.Peru),
|
||||
Triangle = new SolidBrush(Color.Black),
|
||||
Line = new Pen(Color.FromArgb(30, 30, 30)),
|
||||
Segment = new Pen(Color.DarkBlue),
|
||||
VoronoiLine = new Pen(Color.FromArgb(40, 50, 60))
|
||||
};
|
||||
var colors = new RenderColors();
|
||||
|
||||
colors.Background = Color.FromArgb(0, 0, 0);
|
||||
colors.Point = new SolidBrush(Color.Green);
|
||||
colors.SteinerPoint = new SolidBrush(Color.Peru);
|
||||
colors.Triangle = new SolidBrush(Color.Black);
|
||||
colors.Line = new Pen(Color.FromArgb(30, 30, 30));
|
||||
colors.Segment = new Pen(Color.DarkBlue);
|
||||
colors.VoronoiLine = new Pen(Color.FromArgb(40, 50, 60));
|
||||
|
||||
return colors;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a color scheme with white background.
|
||||
/// </summary>
|
||||
public static RenderColors LightScheme()
|
||||
{
|
||||
var colors = new RenderColors();
|
||||
|
||||
colors.Background = Color.White;
|
||||
colors.Point = new SolidBrush(Color.FromArgb(60, 80, 120));
|
||||
colors.SteinerPoint = new SolidBrush(Color.DarkGreen);
|
||||
colors.Triangle = new SolidBrush(Color.FromArgb(230, 240, 250));
|
||||
colors.Line = new Pen(Color.FromArgb(150, 150, 150));
|
||||
colors.Segment = new Pen(Color.SteelBlue);
|
||||
colors.VoronoiLine = new Pen(Color.FromArgb(160, 170, 180));
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
public Color Background;
|
||||
public Brush Point;
|
||||
|
||||
@@ -826,8 +826,6 @@ namespace TriangleNet.Algorithm
|
||||
return hullsize;
|
||||
}
|
||||
|
||||
IO.DebugWriter dbgWriter;
|
||||
|
||||
/// <summary>
|
||||
/// Form a Delaunay triangulation by the divide-and-conquer method.
|
||||
/// </summary>
|
||||
@@ -844,8 +842,6 @@ namespace TriangleNet.Algorithm
|
||||
|
||||
this.mesh = m;
|
||||
|
||||
dbgWriter = new IO.DebugWriter(m);
|
||||
|
||||
// Allocate an array of pointers to vertices for sorting.
|
||||
// TODO: use ToArray
|
||||
this.sortarray = new Vertex[m.invertices];
|
||||
|
||||
@@ -68,6 +68,14 @@ namespace TriangleNet.Data
|
||||
get { return this.vertices[1].id; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the segments endpoint.
|
||||
/// </summary>
|
||||
public Vertex this[int index]
|
||||
{
|
||||
get { return this.vertices[index]; } // TODO: Check range?
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the segment boundary mark.
|
||||
/// </summary>
|
||||
|
||||
@@ -100,9 +100,9 @@ namespace TriangleNet.Data
|
||||
/// <summary>
|
||||
/// Gets the specified corners vertex id.
|
||||
/// </summary>
|
||||
public int this[int index]
|
||||
public Vertex this[int index]
|
||||
{
|
||||
get { return this.vertices[index] == null ? -1 : this.vertices[index].id; }
|
||||
get { return this.vertices[index]; } // TODO: Check range?
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace TriangleNet.Geometry
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TriangleNet.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Triangle interface.
|
||||
@@ -34,9 +35,9 @@ namespace TriangleNet.Geometry
|
||||
/// </summary>
|
||||
int P2 { get; }
|
||||
/// <summary>
|
||||
/// Gets the specified vertex id.
|
||||
/// Gets the vertex at specified index.
|
||||
/// </summary>
|
||||
int this[int index] { get; }
|
||||
Vertex this[int index] { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the triangle implementation contains neighbor information.
|
||||
|
||||
@@ -119,10 +119,13 @@ namespace TriangleNet.IO
|
||||
{
|
||||
tri.triangle = item;
|
||||
|
||||
corner[0] = triangles[i].P0;
|
||||
corner[1] = triangles[i].P1;
|
||||
corner[2] = triangles[i].P2;
|
||||
|
||||
// Copy the triangle's three corners.
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
corner[j] = triangles[i][j];
|
||||
if ((corner[j] < 0) || (corner[j] >= mesh.invertices))
|
||||
{
|
||||
SimpleLog.Instance.Error("Triangle has an invalid vertex index.", "MeshReader.Reconstruct()");
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace TriangleNet.IO
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Simple triangle class for input.
|
||||
@@ -61,9 +62,9 @@ namespace TriangleNet.IO
|
||||
/// <summary>
|
||||
/// Gets the specified corners vertex id.
|
||||
/// </summary>
|
||||
public int this[int index]
|
||||
public Vertex this[int index]
|
||||
{
|
||||
get { return this.vertices[index]; }
|
||||
get { return null; } // TODO: throw NotSupportedException?
|
||||
}
|
||||
|
||||
public bool SupportsNeighbors
|
||||
|
||||
@@ -248,11 +248,11 @@ namespace TriangleNet.Tools
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
gi = tri[j];
|
||||
gi = tri[j].id;
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
gj = tri[k];
|
||||
gj = tri[k].id;
|
||||
|
||||
mu = Math.Max(mu, gj - gi);
|
||||
ml = Math.Max(ml, gi - gj);
|
||||
|
||||
Reference in New Issue
Block a user