Rename source folder.
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="AngleHistogram.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Displays an angle histogram.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The angle histogram is divided into two parts: the minimum angles
|
||||
/// on the left side (0 to 60 degrees) and the maximum angles on the
|
||||
/// right (60 to 180 degrees).
|
||||
/// </remarks>
|
||||
public class AngleHistogram : Control
|
||||
{
|
||||
#region Designer
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
int[] maxAngles;
|
||||
int[] minAngles;
|
||||
|
||||
Brush fillBlue1 = new SolidBrush(Color.FromArgb(60, 100, 140));
|
||||
Brush fillBlue2 = new SolidBrush(Color.FromArgb(110, 150, 200));
|
||||
|
||||
Brush textBack = new SolidBrush(Color.FromArgb(72, 0, 0, 0));
|
||||
|
||||
// The maximum number of angles
|
||||
int maxAngleCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AngleHistogram" /> control.
|
||||
/// </summary>
|
||||
public AngleHistogram()
|
||||
{
|
||||
this.BackColor = ColorScheme.ColorGray78;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the histogram data and invalidates the control.
|
||||
/// </summary>
|
||||
public void SetData(int[] dataMin, int[] dataMax)
|
||||
{
|
||||
maxAngleCount = 0;
|
||||
|
||||
this.minAngles = dataMin;
|
||||
this.maxAngles = dataMax;
|
||||
|
||||
ParseData(dataMin);
|
||||
ParseData(dataMax);
|
||||
|
||||
if (maxAngleCount == 0)
|
||||
{
|
||||
this.maxAngles = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
private void ParseData(int[] data)
|
||||
{
|
||||
if (data != null)
|
||||
{
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
if (data[i] > maxAngleCount)
|
||||
{
|
||||
maxAngleCount = data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int padding = 1;
|
||||
int paddingBottom = 0;
|
||||
int paddingTop = 15;
|
||||
|
||||
private void DrawHistogram(Graphics g, int offset, int left, int size, int[] data, Brush brush, Brush brushTop)
|
||||
{
|
||||
int count = maxAngleCount;
|
||||
int totalHeight = this.Height - paddingBottom - paddingTop;
|
||||
|
||||
int n = offset == 0 ? data.Length / 3 : data.Length;
|
||||
float value = 0;
|
||||
|
||||
for (int i = offset; i < n; i++)
|
||||
{
|
||||
if (data[i] > 0)
|
||||
{
|
||||
// Scale to control height
|
||||
value = totalHeight * data[i] / count;
|
||||
|
||||
// Fill bar
|
||||
g.FillRectangle(brush,
|
||||
left + i * size, this.Height - paddingBottom - value,
|
||||
size - 1, value);
|
||||
|
||||
// Draw top of bar (just a little effect ...)
|
||||
if (value > 2)
|
||||
{
|
||||
g.FillRectangle(brushTop,
|
||||
left + i * size, this.Height - paddingBottom - value,
|
||||
size - 1, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the labels on the bottom.
|
||||
/// </summary>
|
||||
private void DrawStrings(Graphics g, SizeF fSize, int size, int middle)
|
||||
{
|
||||
int fHeight = (int)(fSize.Height + 2);
|
||||
g.FillRectangle(textBack, 0, this.Height - fHeight, this.Width, fHeight);
|
||||
|
||||
g.DrawString("0", this.Font, Brushes.White, padding, this.Height - fSize.Height - 1);
|
||||
g.DrawString("60", this.Font, Brushes.White,
|
||||
this.minAngles.Length * size / 3.0f - 2 * fSize.Width,
|
||||
this.Height - fSize.Height - 1);
|
||||
|
||||
g.DrawString("60", this.Font, Brushes.White, middle, this.Height - fSize.Height - 1);
|
||||
g.DrawString("180", this.Font, Brushes.White,
|
||||
this.Width - 3 * fSize.Width,
|
||||
this.Height - fSize.Height - 1);
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
|
||||
g.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
|
||||
|
||||
if (this.minAngles == null || this.maxAngles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SizeF fSize = g.MeasureString("0", this.Font, this.Width);
|
||||
|
||||
int n = this.minAngles.Length;
|
||||
|
||||
// Hack --- TODO: Change stats class
|
||||
if (n != this.maxAngles.Length)
|
||||
{
|
||||
n = this.minAngles.Length + this.maxAngles.Length;
|
||||
}
|
||||
|
||||
// Each bar takes up this space
|
||||
int size = (this.Width - 2 * padding) / (n + 1);
|
||||
|
||||
// Make pixel align
|
||||
int middle = this.Width - padding - n * size;
|
||||
|
||||
DrawHistogram(g, 0, padding, size, this.minAngles, Brushes.DarkGreen, Brushes.Green);
|
||||
DrawHistogram(g, n / 3, middle, size, this.maxAngles, fillBlue1, fillBlue2);
|
||||
|
||||
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
||||
|
||||
DrawStrings(g, fSize, size, middle + n / 3 * size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="ColorScheme.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Dark user interface color scheme.
|
||||
/// </summary>
|
||||
public static class ColorScheme
|
||||
{
|
||||
public static Color ColorGray13 = Color.FromArgb(13, 13, 13);
|
||||
public static Color ColorGray46 = Color.FromArgb(46, 46, 46);
|
||||
public static Color ColorGray64 = Color.FromArgb(64, 64, 64);
|
||||
public static Color ColorGray68 = Color.FromArgb(68, 68, 68);
|
||||
public static Color ColorGray78 = Color.FromArgb(78, 78, 78);
|
||||
public static Color ColorGray89 = Color.FromArgb(89, 89, 89);
|
||||
public static Color ColorGray98 = Color.FromArgb(98, 98, 98);
|
||||
public static Color ColorGray107 = Color.FromArgb(107, 107, 107);
|
||||
public static Color ColorGray110 = Color.FromArgb(110, 110, 110);
|
||||
public static Color ColorGray122 = Color.FromArgb(122, 122, 122);
|
||||
|
||||
public static Brush BrushGray68 = new SolidBrush(ColorGray68);
|
||||
public static Brush BrushGray78 = new SolidBrush(ColorGray78);
|
||||
|
||||
// Linear gradient horizontal
|
||||
public static Brush SliderBorderBrush = new SolidBrush(ColorGray46);
|
||||
public static Brush SliderFillBrush = new SolidBrush(ColorGray89);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="DarkButton.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
public class DarkButton : Button
|
||||
{
|
||||
#region Designer
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
enum eButtonState { Normal, MouseOver, Down }
|
||||
eButtonState m_State = eButtonState.Normal;
|
||||
|
||||
// Make sure the control is invalidated when the text is changed.
|
||||
public override string Text
|
||||
{
|
||||
get { return base.Text; }
|
||||
set { base.Text = value; this.Invalidate(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DarkButton" /> control.
|
||||
/// </summary>
|
||||
public DarkButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
#region Control overrides
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
||||
|
||||
float down = 0.0f;
|
||||
|
||||
// Colors and brushes
|
||||
Pen brushBorder = null;
|
||||
LinearGradientMode mode = LinearGradientMode.Vertical;
|
||||
LinearGradientBrush brushOuter = null;
|
||||
LinearGradientBrush brushInner = null;
|
||||
|
||||
Rectangle newRect = new Rectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
|
||||
Color text_color = Color.White;
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
if (base.Focused)
|
||||
brushBorder = new Pen(Color.FromArgb(24, 24, 24), 1f);
|
||||
else
|
||||
brushBorder = new Pen(Color.FromArgb(56, 56, 56), 1f);
|
||||
|
||||
switch (m_State)
|
||||
{
|
||||
case eButtonState.Normal:
|
||||
brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(123, 123, 123), Color.FromArgb(77, 77, 77), mode);
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(104, 104, 104), Color.FromArgb(71, 71, 71), mode);
|
||||
e.Graphics.FillRectangle(brushOuter, newRect);
|
||||
newRect.Inflate(-1, -1);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
newRect.Inflate(1, 1);
|
||||
break;
|
||||
|
||||
case eButtonState.MouseOver:
|
||||
brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(140, 140, 140), Color.FromArgb(87, 87, 87), mode);
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(118, 118, 118), Color.FromArgb(81, 81, 81), mode);
|
||||
e.Graphics.FillRectangle(brushOuter, newRect);
|
||||
newRect.Inflate(-1, -1);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
newRect.Inflate(1, 1);
|
||||
break;
|
||||
|
||||
case eButtonState.Down:
|
||||
down = 1.0f;
|
||||
brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(108, 108, 108), Color.FromArgb(68, 68, 68), mode);
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(92, 92, 92), Color.FromArgb(62, 62, 62), mode);
|
||||
e.Graphics.FillRectangle(brushOuter, newRect);
|
||||
newRect.Inflate(-1, -1);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
newRect.Inflate(1, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
e.Graphics.DrawRectangle(brushBorder, newRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
text_color = Color.FromArgb(110, 110, 110);
|
||||
brushBorder = new Pen(Color.FromArgb(48, 48, 48), 1f);
|
||||
brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(82, 82, 82), Color.FromArgb(67, 67, 67), mode);
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(76, 76, 76), Color.FromArgb(65, 65, 65), mode);
|
||||
e.Graphics.FillRectangle(brushOuter, newRect);
|
||||
newRect.Inflate(-1, -1);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
newRect.Inflate(1, 1);
|
||||
e.Graphics.DrawRectangle(brushBorder, newRect);
|
||||
}
|
||||
|
||||
|
||||
string largetext = this.Text;
|
||||
|
||||
SizeF szL = e.Graphics.MeasureString(this.Text, base.Font, this.Width);
|
||||
if (Enabled)
|
||||
{
|
||||
e.Graphics.DrawString(largetext, base.Font, Brushes.Black,
|
||||
new RectangleF(new PointF((this.Width - szL.Width) / 2, (this.Height - szL.Height) / 2 + 1 + down), szL));
|
||||
}
|
||||
e.Graphics.DrawString(largetext, base.Font, new SolidBrush(text_color),
|
||||
new RectangleF(new PointF((this.Width - szL.Width) / 2, (this.Height - szL.Height) / 2 + down), szL));
|
||||
|
||||
brushOuter.Dispose();
|
||||
brushInner.Dispose();
|
||||
brushBorder.Dispose();
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(System.EventArgs e)
|
||||
{
|
||||
m_State = eButtonState.Normal;
|
||||
this.Invalidate();
|
||||
base.OnMouseLeave(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseEnter(System.EventArgs e)
|
||||
{
|
||||
m_State = eButtonState.MouseOver;
|
||||
this.Invalidate();
|
||||
base.OnMouseEnter(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
m_State = eButtonState.MouseOver;
|
||||
this.Invalidate();
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
m_State = eButtonState.Down;
|
||||
this.Invalidate();
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="DarkCheckBox.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Dark checkbox control.
|
||||
/// </summary>
|
||||
public class DarkCheckBox : ButtonBase
|
||||
{
|
||||
#region Designer
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
enum eButtonState { Normal, MouseOver, Down }
|
||||
eButtonState m_State = eButtonState.Normal;
|
||||
|
||||
// Make sure the control is invalidated when the text is changed.
|
||||
public override string Text
|
||||
{
|
||||
get { return base.Text; }
|
||||
set { base.Text = value; this.Invalidate(); }
|
||||
}
|
||||
|
||||
int boxSize = 13;
|
||||
|
||||
bool isChecked = false;
|
||||
public bool Checked
|
||||
{
|
||||
get { return isChecked; }
|
||||
set { isChecked = value; this.Invalidate(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DarkCheckBox" /> control.
|
||||
/// </summary>
|
||||
public DarkCheckBox()
|
||||
{
|
||||
this.BackColor = Color.FromArgb(76, 76, 76);
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void DrawText(Graphics g, Color forecolor, Point location)
|
||||
{
|
||||
if (this.UseCompatibleTextRendering)
|
||||
{
|
||||
//using (StringFormat stringFormat = this.CreateStringFormat())
|
||||
{
|
||||
if (this.Enabled)
|
||||
{
|
||||
g.DrawString(this.Text, base.Font, new SolidBrush(forecolor), location.X, location.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.DrawString(this.Text, base.Font, new SolidBrush(forecolor), location.X, location.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//TextFormatFlags textFormatFlags = this.CreateTextFormatFlags();
|
||||
if (this.Enabled)
|
||||
{
|
||||
TextRenderer.DrawText((IDeviceContext)g, this.Text, this.Font, location, forecolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
//forecolor = TextRenderer.DisabledTextColor(this.BackColor);
|
||||
TextRenderer.DrawText((IDeviceContext)g, this.Text, this.Font, location, forecolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Control overrides
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
//base.OnPaint(e);
|
||||
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
|
||||
|
||||
Pen checkMark = new Pen(Color.White, 1.8f);
|
||||
checkMark.StartCap = LineCap.Round;
|
||||
checkMark.EndCap = LineCap.Round;
|
||||
|
||||
// Colors and brushes
|
||||
Pen brushBorder = null;
|
||||
LinearGradientMode mode = LinearGradientMode.Vertical;
|
||||
LinearGradientBrush brushOuter = null;
|
||||
LinearGradientBrush brushInner = null;
|
||||
|
||||
int y = (this.Height - boxSize) / 2;
|
||||
|
||||
Rectangle newRect = new Rectangle(1, y, boxSize, boxSize);
|
||||
Color text_color = Color.White;
|
||||
|
||||
brushOuter = new LinearGradientBrush(newRect, ColorScheme.ColorGray107, ColorScheme.ColorGray110, mode);
|
||||
e.Graphics.FillRectangle(brushOuter, newRect);
|
||||
|
||||
newRect = new Rectangle(2, y + 1, boxSize - 3, boxSize - 3);
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
if (base.Focused)
|
||||
brushBorder = new Pen(Color.FromArgb(60, 60, 60), 1f);
|
||||
else
|
||||
brushBorder = new Pen(Color.FromArgb(38, 38, 38), 1f);
|
||||
|
||||
switch (m_State)
|
||||
{
|
||||
case eButtonState.Normal:
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(111, 111, 111), Color.FromArgb(80, 80, 80), mode);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
break;
|
||||
|
||||
case eButtonState.MouseOver:
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(118, 118, 118), Color.FromArgb(81, 81, 81), mode);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
break;
|
||||
|
||||
case eButtonState.Down:
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(92, 92, 92), Color.FromArgb(62, 62, 62), mode);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
break;
|
||||
}
|
||||
|
||||
e.Graphics.DrawRectangle(brushBorder, newRect);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
brushInner = new LinearGradientBrush(newRect, Color.FromArgb(76, 76, 76), Color.FromArgb(65, 65, 65), mode);
|
||||
e.Graphics.FillRectangle(brushInner, newRect);
|
||||
|
||||
brushBorder = new Pen(Color.FromArgb(48, 48, 48), 1f);
|
||||
e.Graphics.DrawRectangle(brushBorder, newRect);
|
||||
|
||||
text_color = Color.FromArgb(160, 160, 160);
|
||||
checkMark.Color = Color.FromArgb(180, 180, 180);
|
||||
}
|
||||
|
||||
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
||||
|
||||
SizeF szL = e.Graphics.MeasureString(this.Text, base.Font, this.Width);
|
||||
DrawText(e.Graphics, text_color, new Point(boxSize + 4, (int)((this.Height - szL.Height) / 2) + 1));
|
||||
|
||||
if (this.isChecked)
|
||||
{
|
||||
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
e.Graphics.DrawLine(checkMark, 4, newRect.Bottom - boxSize / 2, newRect.Left + boxSize / 2.5f, newRect.Bottom - 2);
|
||||
e.Graphics.DrawLine(checkMark, newRect.Left + boxSize / 2.6f, newRect.Bottom - 2, newRect.Right, newRect.Top);
|
||||
}
|
||||
|
||||
if (brushOuter != null) brushOuter.Dispose();
|
||||
if (brushInner != null) brushInner.Dispose();
|
||||
if (brushBorder != null) brushBorder.Dispose();
|
||||
if (checkMark != null) checkMark.Dispose();
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(System.EventArgs e)
|
||||
{
|
||||
m_State = eButtonState.Normal;
|
||||
this.Invalidate();
|
||||
base.OnMouseLeave(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseEnter(System.EventArgs e)
|
||||
{
|
||||
m_State = eButtonState.MouseOver;
|
||||
this.Invalidate();
|
||||
base.OnMouseEnter(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
m_State = eButtonState.MouseOver;
|
||||
this.Invalidate();
|
||||
base.OnMouseUp(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
m_State = eButtonState.Down;
|
||||
this.Invalidate();
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnClick(EventArgs e)
|
||||
{
|
||||
this.isChecked = !this.isChecked;
|
||||
this.Invalidate();
|
||||
base.OnClick(e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="DarkListBox.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Dark listbox control.
|
||||
/// </summary>
|
||||
public class DarkListBox : ListBox
|
||||
{
|
||||
Font _boldFont;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DarkListBox" /> control.
|
||||
/// </summary>
|
||||
public DarkListBox()
|
||||
{
|
||||
_boldFont = new Font(base.Font.FontFamily, base.Font.Size, FontStyle.Bold);
|
||||
|
||||
this.DrawMode = DrawMode.OwnerDrawVariable;
|
||||
this.ItemHeight = 22;
|
||||
this.FontChanged += new EventHandler(ListBoxFontChanged);
|
||||
this.BackColor = Color.FromArgb(96, 96, 96);
|
||||
}
|
||||
|
||||
void ListBoxFontChanged(object sender, EventArgs e)
|
||||
{
|
||||
_boldFont = new Font(base.Font.FontFamily, base.Font.Size, FontStyle.Bold);
|
||||
}
|
||||
|
||||
protected override void OnMeasureItem(MeasureItemEventArgs e)
|
||||
{
|
||||
e.ItemHeight = 22;
|
||||
}
|
||||
|
||||
protected override void OnDrawItem(DrawItemEventArgs e)
|
||||
{
|
||||
if (this.Items.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
||||
|
||||
int index = e.Index;
|
||||
|
||||
string content = "[Error]";
|
||||
|
||||
if (index < this.Items.Count && index >= 0)
|
||||
{
|
||||
content = this.Items[index].ToString();
|
||||
}
|
||||
|
||||
Color color = (e.Index % 2) == 0 ? Color.FromArgb(85, 85, 85) : Color.FromArgb(90, 90, 90);
|
||||
|
||||
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
|
||||
{
|
||||
color = Color.FromArgb(100, 105, 110);
|
||||
}
|
||||
|
||||
using (SolidBrush background = new SolidBrush(color))
|
||||
{
|
||||
e.Graphics.FillRectangle(background, e.Bounds);
|
||||
}
|
||||
|
||||
using (SolidBrush pen = new SolidBrush(Color.White))
|
||||
{
|
||||
e.Graphics.DrawString(content, this.Font, pen,
|
||||
new PointF(10, e.Bounds.Y + 3), StringFormat.GenericDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="DarkSlider.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// Original code on CodeProject: Owner-drawn trackbar (slider), Michal Brylka
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates control that visualy displays certain integer value and allows user to change
|
||||
/// it within desired range. It imitates <see cref="System.Windows.Forms.TrackBar"/> as far as
|
||||
/// mouse usage is concerned.
|
||||
/// </summary>
|
||||
public class DarkSlider : Control
|
||||
{
|
||||
#region Designer
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Fires when Slider position has changed
|
||||
/// </summary>
|
||||
public event EventHandler ValueChanging;
|
||||
|
||||
private void OnValueChanging()
|
||||
{
|
||||
var evt = ValueChanging;
|
||||
|
||||
if (evt != null)
|
||||
{
|
||||
evt(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires when Slider position has changed
|
||||
/// </summary>
|
||||
public event EventHandler ValueChanged;
|
||||
|
||||
private void OnValueChanged()
|
||||
{
|
||||
var evt = ValueChanged;
|
||||
|
||||
if (evt != null)
|
||||
{
|
||||
evt(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
int thumbSize = 7;
|
||||
private Rectangle thumbRect; //bounding rectangle of thumb area
|
||||
private Rectangle barRect; //bounding rectangle of bar area
|
||||
private bool mouseInThumbRegion = false;
|
||||
|
||||
private int trackerValue = 50;
|
||||
/// <summary>
|
||||
/// Gets or sets the value of Slider.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
public int Value
|
||||
{
|
||||
get { return trackerValue; }
|
||||
set
|
||||
{
|
||||
if (value >= barMinimum & value <= barMaximum)
|
||||
{
|
||||
trackerValue = value;
|
||||
if (ValueChanged != null) ValueChanged(this, new EventArgs());
|
||||
Invalidate();
|
||||
}
|
||||
// ArgumentOutOfRangeException("Value is outside appropriate range (min, max)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int barMinimum = 0;
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum value.
|
||||
/// </summary>
|
||||
/// <value>The minimum value.</value>
|
||||
public int Minimum
|
||||
{
|
||||
get { return barMinimum; }
|
||||
set
|
||||
{
|
||||
if (value < barMaximum)
|
||||
{
|
||||
barMinimum = value;
|
||||
if (trackerValue < barMinimum)
|
||||
{
|
||||
trackerValue = barMinimum;
|
||||
if (ValueChanged != null) ValueChanged(this, new EventArgs());
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
// ArgumentOutOfRangeException("Minimal value is greather than maximal one");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int barMaximum = 100;
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum value.
|
||||
/// </summary>
|
||||
/// <value>The maximum value.</value>
|
||||
public int Maximum
|
||||
{
|
||||
get { return barMaximum; }
|
||||
set
|
||||
{
|
||||
if (value > barMinimum)
|
||||
{
|
||||
barMaximum = value;
|
||||
if (trackerValue > barMaximum)
|
||||
{
|
||||
trackerValue = barMaximum;
|
||||
if (ValueChanged != null) ValueChanged(this, new EventArgs());
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
// ArgumentOutOfRangeException("Maximal value is lower than minimal one");
|
||||
}
|
||||
}
|
||||
|
||||
private uint criticalPercent = 0;
|
||||
/// <summary>
|
||||
/// Gets or sets trackbar's small change. It affects how to behave when directional keys are pressed
|
||||
/// </summary>
|
||||
/// <value>The small change value.</value>
|
||||
public uint CriticalPercent
|
||||
{
|
||||
get { return criticalPercent; }
|
||||
set { criticalPercent = value; }
|
||||
}
|
||||
|
||||
private Color thumbOuterColor = Color.White;
|
||||
private Color thumbInnerColor = Color.Gainsboro;
|
||||
private Color thumbPenColor = Color.Silver;
|
||||
private Color barOuterColor = Color.SkyBlue;
|
||||
private Color barInnerColor = Color.DarkSlateBlue;
|
||||
private Color barPenColor = Color.Gainsboro;
|
||||
private Color elapsedOuterColor = Color.DarkGreen;
|
||||
private Color elapsedInnerColor = Color.Chartreuse;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ColorSlider"/> control.
|
||||
/// </summary>
|
||||
public DarkSlider()
|
||||
{
|
||||
InitializeComponent();
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint
|
||||
| ControlStyles.OptimizedDoubleBuffer
|
||||
| ControlStyles.ResizeRedraw
|
||||
| ControlStyles.Selectable
|
||||
| ControlStyles.SupportsTransparentBackColor
|
||||
| ControlStyles.UserMouse
|
||||
| ControlStyles.UserPaint, true);
|
||||
|
||||
BackColor = Color.Transparent;
|
||||
|
||||
Minimum = 0;
|
||||
Maximum = 100;
|
||||
Value = 50;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Paint
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.Paint"></see> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"></see> that contains the event data.</param>
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
DrawDisabledSlider(e.Graphics);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (mouseEffects && mouseInRegion)
|
||||
//{
|
||||
// Color[] lightenedColors = LightenColors(thumbOuterColor, thumbInnerColor, thumbPenColor,
|
||||
// barOuterColor, barInnerColor, barPenColor,
|
||||
// elapsedOuterColor, elapsedInnerColor);
|
||||
// DrawColorSlider(e, lightenedColors[0], lightenedColors[1], lightenedColors[2], lightenedColors[3],
|
||||
// lightenedColors[4], lightenedColors[5], lightenedColors[6], lightenedColors[7]);
|
||||
//}
|
||||
//else
|
||||
{
|
||||
DrawColorSlider(e.Graphics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawDisabledSlider(Graphics g)
|
||||
{
|
||||
try
|
||||
{
|
||||
//adjust drawing rects
|
||||
barRect = new Rectangle(1, this.Height / 2, this.Width - 2, 5);
|
||||
|
||||
Brush sliderLGBrushH = new LinearGradientBrush(barRect, ColorScheme.ColorGray122,
|
||||
ColorScheme.ColorGray107, LinearGradientMode.Horizontal);
|
||||
|
||||
//draw bar
|
||||
{
|
||||
// Background gradient
|
||||
g.FillRectangle(sliderLGBrushH, barRect);
|
||||
// Background fill
|
||||
g.FillRectangle(ColorScheme.SliderBorderBrush,
|
||||
barRect.Left + 1, barRect.Top, barRect.Width - 2, barRect.Height - 1);
|
||||
// Bar fill
|
||||
g.FillRectangle(ColorScheme.SliderFillBrush,
|
||||
barRect.Left + 2, barRect.Top + 1, barRect.Width - 4, barRect.Height - 3);
|
||||
}
|
||||
|
||||
sliderLGBrushH.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
finally
|
||||
{ }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the colorslider control using passed colors.
|
||||
/// </summary>
|
||||
private void DrawColorSlider(Graphics g)
|
||||
{
|
||||
try
|
||||
{
|
||||
//set up thumbRect aproprietly
|
||||
int track = (((trackerValue - barMinimum) * (ClientRectangle.Width - thumbSize)) / (barMaximum - barMinimum));
|
||||
thumbRect = new Rectangle(track, this.Height / 2 - 3, thumbSize - 1, 10);
|
||||
|
||||
//adjust drawing rects
|
||||
barRect = new Rectangle(1, this.Height / 2, this.Width - 2, 5);
|
||||
|
||||
//get thumb shape path
|
||||
GraphicsPath thumbPath = new GraphicsPath();
|
||||
thumbPath.AddPolygon(new Point[] {
|
||||
new Point(thumbRect.Left, thumbRect.Top),
|
||||
new Point(thumbRect.Right, thumbRect.Top),
|
||||
new Point(thumbRect.Right, thumbRect.Bottom - 4),
|
||||
new Point(thumbRect.Left + thumbRect.Width / 2, thumbRect.Bottom),
|
||||
new Point(thumbRect.Left, thumbRect.Bottom - 4)
|
||||
});
|
||||
|
||||
Brush sliderLGBrushH = new LinearGradientBrush(barRect, ColorScheme.ColorGray122,
|
||||
ColorScheme.ColorGray107, LinearGradientMode.Horizontal);
|
||||
|
||||
Brush barFill = (criticalPercent > 0 && trackerValue > criticalPercent) ? Brushes.Peru : Brushes.Green;
|
||||
|
||||
//draw bar
|
||||
{
|
||||
// Background gradient
|
||||
g.FillRectangle(sliderLGBrushH, barRect);
|
||||
// Background fill
|
||||
g.FillRectangle(ColorScheme.SliderBorderBrush,
|
||||
barRect.Left + 1, barRect.Top, barRect.Width - 2, barRect.Height - 1);
|
||||
// Bar fill
|
||||
g.FillRectangle(ColorScheme.SliderFillBrush,
|
||||
barRect.Left + 2, barRect.Top + 1, barRect.Width - 4, barRect.Height - 3);
|
||||
// Elapsed bar fill
|
||||
|
||||
g.FillRectangle(barFill,
|
||||
barRect.Left + 2, barRect.Top + 1, thumbRect.Left + thumbSize / 2 - 2, barRect.Height - 3);
|
||||
|
||||
//draw bar band
|
||||
//g.DrawRectangle(barPen, barRect);
|
||||
}
|
||||
|
||||
sliderLGBrushH.Dispose();
|
||||
|
||||
//draw thumb
|
||||
Brush brushInner = new LinearGradientBrush(thumbRect,
|
||||
Color.FromArgb(111, 111, 111), Color.FromArgb(80, 80, 80),
|
||||
LinearGradientMode.Vertical);
|
||||
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.FillPath(brushInner, thumbPath);
|
||||
g.DrawPath(Pens.Black, thumbPath);
|
||||
|
||||
brushInner.Dispose();
|
||||
//draw thumb band
|
||||
//Color newThumbPenColor = thumbPenColorPaint;
|
||||
//if (mouseEffects && (Capture || mouseInThumbRegion))
|
||||
// newThumbPenColor = ControlPaint.Dark(newThumbPenColor);
|
||||
//g.DrawPath(thumbPen, thumbPath);
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
finally
|
||||
{ }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overided events
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.EnabledChanged"></see> event.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param>
|
||||
protected override void OnEnabledChanged(EventArgs e)
|
||||
{
|
||||
base.OnEnabledChanged(e);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseLeave"></see> event.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param>
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
mouseInThumbRegion = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"></see> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"></see> that contains the event data.</param>
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
if (e.Button == MouseButtons.Left && this.Enabled)
|
||||
{
|
||||
this.Capture = true;
|
||||
OnValueChanging();
|
||||
OnMouseMove(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseMove"></see> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"></see> that contains the event data.</param>
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
mouseInThumbRegion = thumbRect.Contains(e.Location);
|
||||
if (Capture & e.Button == MouseButtons.Left)
|
||||
{
|
||||
Point pt = e.Location;
|
||||
int p = pt.X;
|
||||
int margin = thumbSize >> 1;
|
||||
p -= margin;
|
||||
float coef = (float)(barMaximum - barMinimum) /
|
||||
(float)(ClientSize.Width - 2 * margin);
|
||||
trackerValue = (int)(p * coef + barMinimum);
|
||||
|
||||
if (trackerValue <= barMinimum)
|
||||
{
|
||||
trackerValue = barMinimum;
|
||||
}
|
||||
else if (trackerValue >= barMaximum)
|
||||
{
|
||||
trackerValue = barMaximum;
|
||||
}
|
||||
|
||||
OnValueChanging();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"></see> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"></see> that contains the event data.</param>
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
if (this.Enabled)
|
||||
{
|
||||
base.OnMouseUp(e);
|
||||
this.Capture = false;
|
||||
mouseInThumbRegion = thumbRect.Contains(e.Location);
|
||||
OnValueChanged();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Help routines
|
||||
|
||||
/// <summary>
|
||||
/// Sets the trackbar value so that it wont exceed allowed range.
|
||||
/// </summary>
|
||||
/// <param name="val">The value.</param>
|
||||
private void SetProperValue(int val)
|
||||
{
|
||||
if (val < barMinimum) Value = barMinimum;
|
||||
else if (val > barMaximum) Value = barMaximum;
|
||||
else Value = val;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="DarkTabControl.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// Original code on CodeProject: A .NET Flat TabControl (CustomDraw), Oscar Londono
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Summary description for FlatTabControl.
|
||||
/// </summary>
|
||||
public class DarkTabControl : System.Windows.Forms.TabControl
|
||||
{
|
||||
#region Designer
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
private const int margin = 5;
|
||||
private Color backColor = ColorScheme.ColorGray68;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DarkTabControl" /> control.
|
||||
/// </summary>
|
||||
public DarkTabControl()
|
||||
{
|
||||
// This call is required by the Windows.Forms Form Designer.
|
||||
InitializeComponent();
|
||||
|
||||
base.Multiline = false;
|
||||
|
||||
// double buffering
|
||||
this.SetStyle(ControlStyles.UserPaint, true);
|
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
this.SetStyle(ControlStyles.DoubleBuffer, true);
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
||||
|
||||
this.SelectedIndexChanged += (obj, evt) => { Invalidate(); };
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
new public TabAlignment Alignment
|
||||
{
|
||||
get { return base.Alignment; }
|
||||
set
|
||||
{
|
||||
TabAlignment ta = value;
|
||||
if ((ta != TabAlignment.Top) && (ta != TabAlignment.Bottom))
|
||||
{
|
||||
ta = TabAlignment.Top;
|
||||
}
|
||||
|
||||
base.Alignment = ta;
|
||||
}
|
||||
}
|
||||
|
||||
public override Color BackColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return backColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.BackColor = backColor;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
|
||||
DrawControl(e.Graphics);
|
||||
}
|
||||
|
||||
private void DrawControl(Graphics g)
|
||||
{
|
||||
if (!Visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle controlBounds = this.ClientRectangle;
|
||||
Rectangle tabBounds = this.DisplayRectangle;
|
||||
|
||||
// Fill client area
|
||||
Brush br = new SolidBrush(this.BackColor);
|
||||
g.FillRectangle(br, controlBounds);
|
||||
br.Dispose();
|
||||
|
||||
int width = tabBounds.Width + margin;
|
||||
|
||||
// Clip region for drawing tabs
|
||||
Region clip = g.Clip;
|
||||
Rectangle region = new Rectangle(tabBounds.Left, controlBounds.Top, width - margin, controlBounds.Height);
|
||||
|
||||
g.SetClip(region);
|
||||
|
||||
// Draw tabs
|
||||
for (int i = 0; i < this.TabCount; i++)
|
||||
{
|
||||
DrawTab(g, this.TabPages[i], i);
|
||||
}
|
||||
|
||||
g.Clip = clip;
|
||||
}
|
||||
|
||||
private void DrawTab(Graphics g, TabPage tabPage, int index)
|
||||
{
|
||||
Rectangle tabBounds = this.GetTabRect(index);
|
||||
|
||||
bool selected = (this.SelectedIndex == index);
|
||||
|
||||
// Fill this tab with background color
|
||||
g.FillRectangle(selected ? Brushes.DimGray : ColorScheme.BrushGray68, tabBounds);
|
||||
|
||||
if (selected)
|
||||
{
|
||||
// Clear bottom lines
|
||||
Pen pen = new Pen(tabPage.BackColor);
|
||||
|
||||
switch (this.Alignment)
|
||||
{
|
||||
case TabAlignment.Top:
|
||||
g.DrawLine(pen, tabBounds.Left, tabBounds.Bottom, tabBounds.Right - 1, tabBounds.Bottom);
|
||||
g.DrawLine(pen, tabBounds.Left, tabBounds.Bottom + 1, tabBounds.Right - 1, tabBounds.Bottom + 1);
|
||||
break;
|
||||
|
||||
case TabAlignment.Bottom:
|
||||
g.DrawLine(pen, tabBounds.Left, tabBounds.Top, tabBounds.Right - 1, tabBounds.Top);
|
||||
g.DrawLine(pen, tabBounds.Left, tabBounds.Top - 1, tabBounds.Right - 1, tabBounds.Top - 1);
|
||||
g.DrawLine(pen, tabBounds.Left, tabBounds.Top - 2, tabBounds.Right - 1, tabBounds.Top - 2);
|
||||
break;
|
||||
}
|
||||
|
||||
pen.Dispose();
|
||||
}
|
||||
|
||||
// Draw string
|
||||
StringFormat stringFormat = new StringFormat();
|
||||
stringFormat.Alignment = StringAlignment.Center;
|
||||
stringFormat.LineAlignment = StringAlignment.Center;
|
||||
|
||||
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
||||
|
||||
g.DrawString(tabPage.Text, Font, Brushes.White, tabBounds, stringFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="DarkTextBox.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// Dark textbox control.
|
||||
/// </summary>
|
||||
public class DarkTextBox : Control
|
||||
{
|
||||
#region Designer
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
|
||||
this.textBox = new System.Windows.Forms.TextBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBox
|
||||
//
|
||||
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(4, 2);
|
||||
this.textBox.Name = "textBox";
|
||||
this.textBox.TabIndex = 0;
|
||||
//
|
||||
// DarkTextBox
|
||||
//
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.Controls.Add(this.textBox);
|
||||
this.Cursor = Cursors.IBeam;
|
||||
this.Size = new System.Drawing.Size(150, 22);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
TextBox textBox;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DarkTextBox" /> control.
|
||||
/// </summary>
|
||||
public DarkTextBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.MouseClick += delegate(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Left) textBox.Focus();
|
||||
};
|
||||
|
||||
textBox.Font = this.Font;
|
||||
textBox.Location = new Point(4, (this.Height - textBox.Height) / 2);
|
||||
textBox.Width = this.Width - 8;
|
||||
textBox.TextAlign = HorizontalAlignment.Left;
|
||||
textBox.ForeColor = this.ForeColor;
|
||||
//textBox.MaxLength = 6;
|
||||
|
||||
textBox.GotFocus += delegate(object sender, EventArgs e)
|
||||
{
|
||||
textBox.ForeColor = this.ForeColor;
|
||||
};
|
||||
|
||||
textBox.LostFocus += delegate(object sender, EventArgs e)
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
rect = new Rectangle(1, 1, this.Width - 3, this.Height - 3);
|
||||
g.FillRectangle(new SolidBrush(this.BackColor), 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();
|
||||
borderTop.Dispose();
|
||||
borderBottom.Dispose();
|
||||
|
||||
base.OnPaint(e);
|
||||
}
|
||||
|
||||
#region Property overrides
|
||||
|
||||
public override Font Font
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.Font;
|
||||
}
|
||||
set
|
||||
{
|
||||
textBox.Font = value;
|
||||
base.Font = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override String Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return textBox.Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
textBox.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Color ForeColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.ForeColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
textBox.ForeColor = value;
|
||||
base.ForeColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Color BackColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.BackColor;
|
||||
}
|
||||
set
|
||||
{
|
||||
textBox.BackColor = value;
|
||||
base.BackColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Textbox properties
|
||||
|
||||
public HorizontalAlignment TextAlign
|
||||
{
|
||||
get
|
||||
{
|
||||
return textBox.TextAlign;
|
||||
}
|
||||
set
|
||||
{
|
||||
textBox.TextAlign = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="DarkToolStripRenderer.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
/// <summary>
|
||||
/// Toolstrip render for dark menu.
|
||||
/// </summary>
|
||||
public class DarkToolStripRenderer : ToolStripRenderer
|
||||
{
|
||||
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
|
||||
{
|
||||
e.TextColor = e.Item.Enabled ? Color.White : Color.Gray;
|
||||
|
||||
base.OnRenderItemText(e);
|
||||
}
|
||||
|
||||
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
|
||||
{
|
||||
int h = e.Item.Height;
|
||||
int size = h / 2 - 2; // Box size
|
||||
Rectangle rect = new Rectangle(10, (h - size) / 2, size - 2, size);
|
||||
|
||||
var mode = e.Graphics.SmoothingMode;
|
||||
|
||||
using (Pen pen = new Pen(Color.White, 1.6f))
|
||||
{
|
||||
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
e.Graphics.DrawLine(pen, rect.Left, rect.Bottom - size / 2, rect.Left + size / 2.5f, rect.Bottom - 2);
|
||||
e.Graphics.DrawLine(pen, rect.Left + size / 2.6f, rect.Bottom - 2, rect.Right, rect.Top);
|
||||
}
|
||||
|
||||
e.Graphics.SmoothingMode = mode;
|
||||
}
|
||||
|
||||
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
|
||||
{
|
||||
if (!e.Item.Selected && !e.Item.Pressed)
|
||||
{
|
||||
e.ArrowColor = ColorScheme.ColorGray89;
|
||||
}
|
||||
|
||||
base.OnRenderArrow(e);
|
||||
}
|
||||
|
||||
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
|
||||
{
|
||||
e.Graphics.FillRectangle(ColorScheme.BrushGray78, 0, 2, e.Item.Width, 1);
|
||||
}
|
||||
|
||||
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
|
||||
{
|
||||
if (e.Item.Enabled)
|
||||
{
|
||||
if (e.Item.Selected || e.Item.Pressed)
|
||||
{
|
||||
e.Graphics.FillRectangle(Brushes.DimGray, 0, 0, e.Item.Width, e.Item.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Graphics.FillRectangle(ColorScheme.BrushGray68, 0, 0, e.Item.Width, e.Item.Height);
|
||||
}
|
||||
}
|
||||
|
||||
//base.OnRenderMenuItemBackground(e);
|
||||
}
|
||||
|
||||
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
|
||||
{
|
||||
e.Graphics.FillRectangle(ColorScheme.BrushGray68, e.AffectedBounds);
|
||||
//base.OnRenderToolStripBackground(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
class DarkMessageBox : Form
|
||||
{
|
||||
#region Designer
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
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();
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
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;
|
||||
//
|
||||
// btnOk
|
||||
//
|
||||
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
|
||||
//
|
||||
this.lbMessage.BackColor = System.Drawing.Color.Transparent;
|
||||
this.lbMessage.ForeColor = System.Drawing.Color.White;
|
||||
this.lbMessage.Location = new System.Drawing.Point(12, 9);
|
||||
this.lbMessage.Name = "lbMessage";
|
||||
this.lbMessage.Size = new System.Drawing.Size(412, 30);
|
||||
this.lbMessage.TabIndex = 2;
|
||||
this.lbMessage.Text = "Message";
|
||||
//
|
||||
// lbInfo
|
||||
//
|
||||
this.lbInfo.AutoSize = true;
|
||||
this.lbInfo.BackColor = System.Drawing.Color.Transparent;
|
||||
this.lbInfo.ForeColor = System.Drawing.Color.White;
|
||||
this.lbInfo.Location = new System.Drawing.Point(12, 47);
|
||||
this.lbInfo.Name = "lbInfo";
|
||||
this.lbInfo.Size = new System.Drawing.Size(28, 13);
|
||||
this.lbInfo.TabIndex = 3;
|
||||
this.lbInfo.Text = "Info";
|
||||
//
|
||||
// DarkMessageBox
|
||||
//
|
||||
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(436, 118);
|
||||
this.Controls.Add(this.lbInfo);
|
||||
this.Controls.Add(this.lbMessage);
|
||||
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;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "DarkMessageBox";
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Message Box";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Controls.DarkButton btnCancel;
|
||||
private Label lbMessage;
|
||||
private Label lbInfo;
|
||||
private Controls.DarkButton btnOk;
|
||||
|
||||
#endregion
|
||||
|
||||
public DarkMessageBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
|
||||
var rect = this.ClientRectangle;
|
||||
rect.Height -= 40;
|
||||
|
||||
e.Graphics.FillRectangle(Brushes.DimGray, rect);
|
||||
}
|
||||
|
||||
public static DialogResult Show(string title, string message, string info, MessageBoxButtons buttons)
|
||||
{
|
||||
DarkMessageBox dialog = new DarkMessageBox();
|
||||
|
||||
SetButtonsText(dialog, buttons);
|
||||
|
||||
dialog.Text = title;
|
||||
|
||||
dialog.lbInfo.Text = info;
|
||||
dialog.lbMessage.Text = message;
|
||||
|
||||
return dialog.ShowDialog();
|
||||
}
|
||||
|
||||
public static DialogResult Show(string title, string message, string info)
|
||||
{
|
||||
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, "", 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+202
@@ -0,0 +1,202 @@
|
||||
namespace MeshExplorer
|
||||
{
|
||||
partial class FormExport
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </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.cbUseCompression = new MeshExplorer.Controls.DarkCheckBox();
|
||||
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, 190);
|
||||
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, 148);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(74, 13);
|
||||
this.label1.TabIndex = 2;
|
||||
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, 148);
|
||||
this.lbSize.Name = "lbSize";
|
||||
this.lbSize.Size = new System.Drawing.Size(40, 13);
|
||||
this.lbSize.TabIndex = 2;
|
||||
this.lbSize.Text = "800 px";
|
||||
//
|
||||
// cbUseCompression
|
||||
//
|
||||
this.cbUseCompression.BackColor = System.Drawing.Color.DimGray;
|
||||
this.cbUseCompression.Checked = false;
|
||||
this.cbUseCompression.Enabled = false;
|
||||
this.cbUseCompression.Location = new System.Drawing.Point(15, 231);
|
||||
this.cbUseCompression.Name = "cbUseCompression";
|
||||
this.cbUseCompression.Size = new System.Drawing.Size(297, 23);
|
||||
this.cbUseCompression.TabIndex = 6;
|
||||
this.cbUseCompression.Text = "Use GZip compression";
|
||||
this.cbUseCompression.UseVisualStyleBackColor = false;
|
||||
//
|
||||
// darkSlider1
|
||||
//
|
||||
this.darkSlider1.BackColor = System.Drawing.Color.Transparent;
|
||||
this.darkSlider1.CriticalPercent = ((uint)(0u));
|
||||
this.darkSlider1.Location = new System.Drawing.Point(15, 161);
|
||||
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, 206);
|
||||
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, 110);
|
||||
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(144, 270);
|
||||
this.darkButton1.Name = "darkButton1";
|
||||
this.darkButton1.Size = new System.Drawing.Size(82, 23);
|
||||
this.darkButton1.TabIndex = 1;
|
||||
this.darkButton1.Text = "Cancel";
|
||||
this.darkButton1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// btnExport
|
||||
//
|
||||
this.btnExport.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
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;
|
||||
this.btnExport.Text = "Save";
|
||||
this.btnExport.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// FormExport
|
||||
//
|
||||
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(324, 299);
|
||||
this.Controls.Add(this.cbUseCompression);
|
||||
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)));
|
||||
this.ForeColor = System.Drawing.Color.White;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "FormExport";
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Export Image";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
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;
|
||||
private Controls.DarkCheckBox cbUseCompression;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
public partial class FormExport : Form
|
||||
{
|
||||
public FormExport()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public int ImageFormat
|
||||
{
|
||||
get { return darkListBox1.SelectedIndex; }
|
||||
}
|
||||
|
||||
public int ImageSize
|
||||
{
|
||||
get
|
||||
{
|
||||
int size = (int)((2000.0 - 200.0) / 100.0 * darkSlider1.Value + 200.0);
|
||||
return size - (size % 50);
|
||||
}
|
||||
}
|
||||
|
||||
public string ImageName
|
||||
{
|
||||
get { return darkTextBox1.Text; }
|
||||
set { darkTextBox1.Text = value; }
|
||||
}
|
||||
|
||||
public bool UseCompression
|
||||
{
|
||||
get { return cbUseCompression.Enabled && cbUseCompression.Checked; }
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
|
||||
var rect = this.ClientRectangle;
|
||||
rect.Height -= 40;
|
||||
|
||||
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";
|
||||
|
||||
cbUseCompression.Enabled = darkListBox1.SelectedIndex > 0;
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
Generated
+242
@@ -0,0 +1,242 @@
|
||||
namespace MeshExplorer
|
||||
{
|
||||
partial class FormGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.lbParam1 = new System.Windows.Forms.Label();
|
||||
this.lbParam2 = new System.Windows.Forms.Label();
|
||||
this.lbParam3 = new System.Windows.Forms.Label();
|
||||
this.lbParam1Val = new System.Windows.Forms.Label();
|
||||
this.lbParam2Val = new System.Windows.Forms.Label();
|
||||
this.lbParam3Val = new System.Windows.Forms.Label();
|
||||
this.lbDescription = new System.Windows.Forms.Label();
|
||||
this.sliderParam3 = new MeshExplorer.Controls.DarkSlider();
|
||||
this.sliderParam2 = new MeshExplorer.Controls.DarkSlider();
|
||||
this.sliderParam1 = new MeshExplorer.Controls.DarkSlider();
|
||||
this.darkListBox1 = new MeshExplorer.Controls.DarkListBox();
|
||||
this.btnClose = new MeshExplorer.Controls.DarkButton();
|
||||
this.btnGenerate = new MeshExplorer.Controls.DarkButton();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lbParam1
|
||||
//
|
||||
this.lbParam1.BackColor = System.Drawing.Color.DimGray;
|
||||
this.lbParam1.ForeColor = System.Drawing.Color.White;
|
||||
this.lbParam1.Location = new System.Drawing.Point(171, 24);
|
||||
this.lbParam1.Name = "lbParam1";
|
||||
this.lbParam1.Size = new System.Drawing.Size(114, 13);
|
||||
this.lbParam1.TabIndex = 4;
|
||||
this.lbParam1.Text = "Param 1:";
|
||||
//
|
||||
// lbParam2
|
||||
//
|
||||
this.lbParam2.BackColor = System.Drawing.Color.DimGray;
|
||||
this.lbParam2.ForeColor = System.Drawing.Color.White;
|
||||
this.lbParam2.Location = new System.Drawing.Point(171, 47);
|
||||
this.lbParam2.Name = "lbParam2";
|
||||
this.lbParam2.Size = new System.Drawing.Size(114, 13);
|
||||
this.lbParam2.TabIndex = 4;
|
||||
this.lbParam2.Text = "Param 2:";
|
||||
//
|
||||
// lbParam3
|
||||
//
|
||||
this.lbParam3.BackColor = System.Drawing.Color.DimGray;
|
||||
this.lbParam3.ForeColor = System.Drawing.Color.White;
|
||||
this.lbParam3.Location = new System.Drawing.Point(171, 70);
|
||||
this.lbParam3.Name = "lbParam3";
|
||||
this.lbParam3.Size = new System.Drawing.Size(114, 13);
|
||||
this.lbParam3.TabIndex = 4;
|
||||
this.lbParam3.Text = "Param 3:";
|
||||
//
|
||||
// lbParam1Val
|
||||
//
|
||||
this.lbParam1Val.BackColor = System.Drawing.Color.DimGray;
|
||||
this.lbParam1Val.ForeColor = System.Drawing.Color.White;
|
||||
this.lbParam1Val.Location = new System.Drawing.Point(436, 24);
|
||||
this.lbParam1Val.Name = "lbParam1Val";
|
||||
this.lbParam1Val.Size = new System.Drawing.Size(40, 13);
|
||||
this.lbParam1Val.TabIndex = 4;
|
||||
this.lbParam1Val.Text = "-";
|
||||
//
|
||||
// lbParam2Val
|
||||
//
|
||||
this.lbParam2Val.BackColor = System.Drawing.Color.DimGray;
|
||||
this.lbParam2Val.ForeColor = System.Drawing.Color.White;
|
||||
this.lbParam2Val.Location = new System.Drawing.Point(436, 47);
|
||||
this.lbParam2Val.Name = "lbParam2Val";
|
||||
this.lbParam2Val.Size = new System.Drawing.Size(40, 13);
|
||||
this.lbParam2Val.TabIndex = 4;
|
||||
this.lbParam2Val.Text = "-";
|
||||
//
|
||||
// lbParam3Val
|
||||
//
|
||||
this.lbParam3Val.BackColor = System.Drawing.Color.DimGray;
|
||||
this.lbParam3Val.ForeColor = System.Drawing.Color.White;
|
||||
this.lbParam3Val.Location = new System.Drawing.Point(436, 70);
|
||||
this.lbParam3Val.Name = "lbParam3Val";
|
||||
this.lbParam3Val.Size = new System.Drawing.Size(40, 13);
|
||||
this.lbParam3Val.TabIndex = 4;
|
||||
this.lbParam3Val.Text = "-";
|
||||
//
|
||||
// lbDescription
|
||||
//
|
||||
this.lbDescription.BackColor = System.Drawing.Color.DimGray;
|
||||
this.lbDescription.ForeColor = System.Drawing.Color.White;
|
||||
this.lbDescription.Location = new System.Drawing.Point(171, 104);
|
||||
this.lbDescription.Name = "lbDescription";
|
||||
this.lbDescription.Size = new System.Drawing.Size(94, 13);
|
||||
this.lbDescription.TabIndex = 4;
|
||||
this.lbDescription.Text = "Description";
|
||||
//
|
||||
// sliderParam3
|
||||
//
|
||||
this.sliderParam3.BackColor = System.Drawing.Color.Transparent;
|
||||
this.sliderParam3.CriticalPercent = ((uint)(0u));
|
||||
this.sliderParam3.Enabled = false;
|
||||
this.sliderParam3.Location = new System.Drawing.Point(291, 64);
|
||||
this.sliderParam3.Maximum = 100;
|
||||
this.sliderParam3.Minimum = 0;
|
||||
this.sliderParam3.Name = "sliderParam3";
|
||||
this.sliderParam3.Size = new System.Drawing.Size(138, 23);
|
||||
this.sliderParam3.TabIndex = 3;
|
||||
this.sliderParam3.Text = "sliderParam3";
|
||||
this.sliderParam3.Value = 50;
|
||||
this.sliderParam3.ValueChanging += new System.EventHandler(this.sliderParam3_ValueChanging);
|
||||
//
|
||||
// sliderParam2
|
||||
//
|
||||
this.sliderParam2.BackColor = System.Drawing.Color.Transparent;
|
||||
this.sliderParam2.CriticalPercent = ((uint)(0u));
|
||||
this.sliderParam2.Enabled = false;
|
||||
this.sliderParam2.Location = new System.Drawing.Point(291, 41);
|
||||
this.sliderParam2.Maximum = 100;
|
||||
this.sliderParam2.Minimum = 0;
|
||||
this.sliderParam2.Name = "sliderParam2";
|
||||
this.sliderParam2.Size = new System.Drawing.Size(138, 23);
|
||||
this.sliderParam2.TabIndex = 3;
|
||||
this.sliderParam2.Text = "sliderParam2";
|
||||
this.sliderParam2.Value = 50;
|
||||
this.sliderParam2.ValueChanging += new System.EventHandler(this.sliderParam2_ValueChanging);
|
||||
//
|
||||
// sliderParam1
|
||||
//
|
||||
this.sliderParam1.BackColor = System.Drawing.Color.Transparent;
|
||||
this.sliderParam1.CriticalPercent = ((uint)(0u));
|
||||
this.sliderParam1.Enabled = false;
|
||||
this.sliderParam1.Location = new System.Drawing.Point(291, 18);
|
||||
this.sliderParam1.Maximum = 100;
|
||||
this.sliderParam1.Minimum = 0;
|
||||
this.sliderParam1.Name = "sliderParam1";
|
||||
this.sliderParam1.Size = new System.Drawing.Size(138, 23);
|
||||
this.sliderParam1.TabIndex = 3;
|
||||
this.sliderParam1.Text = "sliderParam1";
|
||||
this.sliderParam1.Value = 50;
|
||||
this.sliderParam1.ValueChanging += new System.EventHandler(this.sliderParam1_ValueChanging);
|
||||
//
|
||||
// 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.Location = new System.Drawing.Point(5, 5);
|
||||
this.darkListBox1.Name = "darkListBox1";
|
||||
this.darkListBox1.Size = new System.Drawing.Size(160, 228);
|
||||
this.darkListBox1.TabIndex = 2;
|
||||
this.darkListBox1.SelectedIndexChanged += new System.EventHandler(this.darkListBox1_SelectedIndexChanged);
|
||||
//
|
||||
// btnClose
|
||||
//
|
||||
this.btnClose.Location = new System.Drawing.Point(291, 247);
|
||||
this.btnClose.Name = "btnClose";
|
||||
this.btnClose.Size = new System.Drawing.Size(94, 23);
|
||||
this.btnClose.TabIndex = 1;
|
||||
this.btnClose.Text = "Close";
|
||||
this.btnClose.UseVisualStyleBackColor = true;
|
||||
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||
//
|
||||
// btnGenerate
|
||||
//
|
||||
this.btnGenerate.Location = new System.Drawing.Point(391, 247);
|
||||
this.btnGenerate.Name = "btnGenerate";
|
||||
this.btnGenerate.Size = new System.Drawing.Size(94, 23);
|
||||
this.btnGenerate.TabIndex = 0;
|
||||
this.btnGenerate.Text = "Generate";
|
||||
this.btnGenerate.UseVisualStyleBackColor = true;
|
||||
this.btnGenerate.Click += new System.EventHandler(this.btnGenerate_Click);
|
||||
//
|
||||
// FormGenerator
|
||||
//
|
||||
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(495, 278);
|
||||
this.Controls.Add(this.lbParam3Val);
|
||||
this.Controls.Add(this.lbDescription);
|
||||
this.Controls.Add(this.lbParam3);
|
||||
this.Controls.Add(this.lbParam2Val);
|
||||
this.Controls.Add(this.lbParam2);
|
||||
this.Controls.Add(this.lbParam1Val);
|
||||
this.Controls.Add(this.lbParam1);
|
||||
this.Controls.Add(this.sliderParam3);
|
||||
this.Controls.Add(this.sliderParam2);
|
||||
this.Controls.Add(this.sliderParam1);
|
||||
this.Controls.Add(this.darkListBox1);
|
||||
this.Controls.Add(this.btnClose);
|
||||
this.Controls.Add(this.btnGenerate);
|
||||
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;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "FormGenerator";
|
||||
this.ShowInTaskbar = false;
|
||||
this.Text = "Input Generator";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormGenerator_FormClosing);
|
||||
this.Load += new System.EventHandler(this.FormGenerator_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Controls.DarkButton btnGenerate;
|
||||
private Controls.DarkButton btnClose;
|
||||
private Controls.DarkListBox darkListBox1;
|
||||
private Controls.DarkSlider sliderParam1;
|
||||
private Controls.DarkSlider sliderParam2;
|
||||
private Controls.DarkSlider sliderParam3;
|
||||
private System.Windows.Forms.Label lbParam1;
|
||||
private System.Windows.Forms.Label lbParam2;
|
||||
private System.Windows.Forms.Label lbParam3;
|
||||
private System.Windows.Forms.Label lbParam1Val;
|
||||
private System.Windows.Forms.Label lbParam2Val;
|
||||
private System.Windows.Forms.Label lbParam3Val;
|
||||
private System.Windows.Forms.Label lbDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using MeshExplorer.Generators;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
public partial class FormGenerator : Form
|
||||
{
|
||||
public event EventHandler InputGenerated;
|
||||
|
||||
IGenerator currentGenerator;
|
||||
|
||||
public FormGenerator()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void UpdateControls()
|
||||
{
|
||||
if (currentGenerator.ParameterCount > 0)
|
||||
{
|
||||
sliderParam1.Enabled = true;
|
||||
lbParam1.Text = currentGenerator.ParameterDescription(0);
|
||||
lbParam1Val.Text = currentGenerator.ParameterDescription(0, sliderParam1.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
sliderParam1.Enabled = false;
|
||||
lbParam1.Text = "";
|
||||
lbParam1Val.Text = "";
|
||||
}
|
||||
|
||||
if (currentGenerator.ParameterCount > 1)
|
||||
{
|
||||
sliderParam2.Enabled = true;
|
||||
lbParam2.Text = currentGenerator.ParameterDescription(1);
|
||||
lbParam2Val.Text = currentGenerator.ParameterDescription(1, sliderParam2.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
sliderParam2.Enabled = false;
|
||||
lbParam2.Text = "";
|
||||
lbParam2Val.Text = "";
|
||||
}
|
||||
|
||||
if (currentGenerator.ParameterCount > 2)
|
||||
{
|
||||
sliderParam3.Enabled = true;
|
||||
lbParam3.Text = currentGenerator.ParameterDescription(2);
|
||||
lbParam3Val.Text = currentGenerator.ParameterDescription(2, sliderParam3.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
sliderParam3.Enabled = false;
|
||||
lbParam3.Text = "";
|
||||
lbParam3Val.Text = "";
|
||||
}
|
||||
}
|
||||
|
||||
private void btnGenerate_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (currentGenerator != null && InputGenerated != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var input = currentGenerator.Generate(sliderParam1.Value,
|
||||
sliderParam2.Value, sliderParam3.Value);
|
||||
|
||||
InputGenerated(input, EventArgs.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
DarkMessageBox.Show("Exception", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void btnClose_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Hide();
|
||||
}
|
||||
|
||||
private void FormGenerator_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (e.CloseReason == CloseReason.UserClosing)
|
||||
{
|
||||
e.Cancel = true;
|
||||
this.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
|
||||
var rect = this.ClientRectangle;
|
||||
rect.Height -= 40;
|
||||
|
||||
e.Graphics.FillRectangle(Brushes.DimGray, rect);
|
||||
}
|
||||
|
||||
private void darkListBox1_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
currentGenerator = darkListBox1.SelectedItem as IGenerator;
|
||||
|
||||
if (currentGenerator != null)
|
||||
{
|
||||
UpdateControls();
|
||||
}
|
||||
}
|
||||
|
||||
private void sliderParam1_ValueChanging(object sender, EventArgs e)
|
||||
{
|
||||
if (currentGenerator != null)
|
||||
{
|
||||
lbParam1Val.Text = currentGenerator.ParameterDescription(0, sliderParam1.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void sliderParam2_ValueChanging(object sender, EventArgs e)
|
||||
{
|
||||
if (currentGenerator != null)
|
||||
{
|
||||
lbParam2Val.Text = currentGenerator.ParameterDescription(1, sliderParam2.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void sliderParam3_ValueChanging(object sender, EventArgs e)
|
||||
{
|
||||
if (currentGenerator != null)
|
||||
{
|
||||
lbParam3Val.Text = currentGenerator.ParameterDescription(2, sliderParam3.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void FormGenerator_Load(object sender, EventArgs e)
|
||||
{
|
||||
darkListBox1.Items.Add(new RandomPoints());
|
||||
darkListBox1.Items.Add(new RandomPointsCircle());
|
||||
darkListBox1.Items.Add(new StarInBox());
|
||||
darkListBox1.Items.Add(new RingPolygon());
|
||||
darkListBox1.Items.Add(new BoxWithHole());
|
||||
darkListBox1.Items.Add(new CircleWithHole());
|
||||
|
||||
darkListBox1.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
Generated
+90
@@ -0,0 +1,90 @@
|
||||
namespace MeshExplorer
|
||||
{
|
||||
partial class FormLog
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.listLog = new System.Windows.Forms.ListView();
|
||||
this.colMessage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.colInfo = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// listLog
|
||||
//
|
||||
this.listLog.BackColor = System.Drawing.Color.White;
|
||||
this.listLog.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.listLog.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.colMessage,
|
||||
this.colInfo});
|
||||
this.listLog.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.listLog.ForeColor = System.Drawing.Color.White;
|
||||
this.listLog.FullRowSelect = true;
|
||||
this.listLog.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
|
||||
this.listLog.Location = new System.Drawing.Point(0, 0);
|
||||
this.listLog.Name = "listLog";
|
||||
this.listLog.Size = new System.Drawing.Size(584, 262);
|
||||
this.listLog.TabIndex = 2;
|
||||
this.listLog.UseCompatibleStateImageBehavior = false;
|
||||
this.listLog.View = System.Windows.Forms.View.Details;
|
||||
this.listLog.DoubleClick += new System.EventHandler(this.listLog_DoubleClick);
|
||||
this.listLog.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listLog_KeyDown);
|
||||
//
|
||||
// colMessage
|
||||
//
|
||||
this.colMessage.Text = "Message";
|
||||
this.colMessage.Width = 350;
|
||||
//
|
||||
// colInfo
|
||||
//
|
||||
this.colInfo.Text = "Info";
|
||||
this.colInfo.Width = 200;
|
||||
//
|
||||
// FormLog
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(584, 262);
|
||||
this.Controls.Add(this.listLog);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "FormLog";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.Text = "Log";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormLog_FormClosing);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ListView listLog;
|
||||
private System.Windows.Forms.ColumnHeader colMessage;
|
||||
private System.Windows.Forms.ColumnHeader colInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Logging;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
public partial class FormLog : Form
|
||||
{
|
||||
public FormLog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void AddItem(string message, bool warning)
|
||||
{
|
||||
var log = Log.Instance;
|
||||
|
||||
if (warning)
|
||||
{
|
||||
log.Warning(message, "Mesh Explorer");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Info(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateItems()
|
||||
{
|
||||
listLog.Items.Clear();
|
||||
|
||||
var log = Log.Instance;
|
||||
|
||||
foreach (var item in log.Data)
|
||||
{
|
||||
listLog.Items.Add(CreateListViewItem(item));
|
||||
}
|
||||
}
|
||||
|
||||
private ListViewItem CreateListViewItem(LogItem item)
|
||||
{
|
||||
ListViewItem lvi = new ListViewItem(new string[] { item.Message, item.Info });
|
||||
|
||||
if (item.Level == LogLevel.Error)
|
||||
{
|
||||
lvi.ForeColor = Color.DarkRed;
|
||||
}
|
||||
else if (item.Level == LogLevel.Warning)
|
||||
{
|
||||
lvi.ForeColor = Color.Peru;
|
||||
}
|
||||
else
|
||||
{
|
||||
lvi.ForeColor = Color.Black;
|
||||
}
|
||||
|
||||
lvi.UseItemStyleForSubItems = true;
|
||||
|
||||
return lvi;
|
||||
}
|
||||
|
||||
private void FormLog_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (e.CloseReason == CloseReason.UserClosing)
|
||||
{
|
||||
e.Cancel = true;
|
||||
this.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private void listLog_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.C)
|
||||
{
|
||||
if (ModifierKeys == Keys.Control)
|
||||
{
|
||||
var selection = listLog.SelectedItems;
|
||||
|
||||
if (selection != null && selection.Count > 0)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
foreach (var item in selection)
|
||||
{
|
||||
GetRowText(sb, item);
|
||||
}
|
||||
|
||||
Clipboard.SetText(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.KeyCode == Keys.Delete)
|
||||
{
|
||||
if (ModifierKeys == Keys.Control)
|
||||
{
|
||||
listLog.Items.Clear();
|
||||
Log.Instance.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void listLog_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
foreach (var item in listLog.SelectedItems)
|
||||
{
|
||||
GetRowText(sb, item);
|
||||
}
|
||||
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
Clipboard.SetText(sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void GetRowText(StringBuilder sb, object item)
|
||||
{
|
||||
var row = item as ListViewItem;
|
||||
|
||||
if (row != null)
|
||||
{
|
||||
foreach (var col in row.SubItems)
|
||||
{
|
||||
var lvi = col as ListViewItem.ListViewSubItem;
|
||||
|
||||
if (lvi != null)
|
||||
{
|
||||
sb.Append(lvi.Text);
|
||||
sb.Append("; ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
Generated
+418
@@ -0,0 +1,418 @@
|
||||
namespace MeshExplorer
|
||||
{
|
||||
partial class FormMain
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.splitContainer = new System.Windows.Forms.SplitContainer();
|
||||
this.btnSmooth = new MeshExplorer.Controls.DarkButton();
|
||||
this.flatTabControl1 = new MeshExplorer.Controls.DarkTabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.meshControlView = new MeshExplorer.Views.MeshControlView();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.statisticView = new MeshExplorer.Views.StatisticView();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.aboutView = new MeshExplorer.Views.AboutView();
|
||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
||||
this.menuFile = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuFileOpen = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuFileSave = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.menuFileExport = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.menuFileQuit = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuView = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuViewVoronoi = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.menuViewLog = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuTools = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuToolsGen = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuToolsCheck = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.menuToolsTopology = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.menuToolsRcm = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.btnMesh = new MeshExplorer.Controls.DarkButton();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
||||
this.splitContainer.Panel1.SuspendLayout();
|
||||
this.splitContainer.SuspendLayout();
|
||||
this.flatTabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// splitContainer
|
||||
//
|
||||
this.splitContainer.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
|
||||
this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
|
||||
this.splitContainer.IsSplitterFixed = true;
|
||||
this.splitContainer.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer.Name = "splitContainer";
|
||||
//
|
||||
// splitContainer.Panel1
|
||||
//
|
||||
this.splitContainer.Panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
|
||||
this.splitContainer.Panel1.Controls.Add(this.btnSmooth);
|
||||
this.splitContainer.Panel1.Controls.Add(this.flatTabControl1);
|
||||
this.splitContainer.Panel1.Controls.Add(this.menuStrip1);
|
||||
this.splitContainer.Panel1.Controls.Add(this.btnMesh);
|
||||
//
|
||||
// splitContainer.Panel2
|
||||
//
|
||||
this.splitContainer.Panel2.BackColor = System.Drawing.Color.Black;
|
||||
this.splitContainer.Size = new System.Drawing.Size(992, 623);
|
||||
this.splitContainer.SplitterDistance = 280;
|
||||
this.splitContainer.SplitterWidth = 1;
|
||||
this.splitContainer.TabIndex = 0;
|
||||
//
|
||||
// btnSmooth
|
||||
//
|
||||
this.btnSmooth.Enabled = false;
|
||||
this.btnSmooth.Location = new System.Drawing.Point(146, 44);
|
||||
this.btnSmooth.Name = "btnSmooth";
|
||||
this.btnSmooth.Size = new System.Drawing.Size(130, 23);
|
||||
this.btnSmooth.TabIndex = 12;
|
||||
this.btnSmooth.Text = "Smooth";
|
||||
this.btnSmooth.UseVisualStyleBackColor = true;
|
||||
this.btnSmooth.Click += new System.EventHandler(this.btnSmooth_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, 73);
|
||||
this.flatTabControl1.Name = "flatTabControl1";
|
||||
this.flatTabControl1.SelectedIndex = 0;
|
||||
this.flatTabControl1.Size = new System.Drawing.Size(280, 538);
|
||||
this.flatTabControl1.TabIndex = 1;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.BackColor = System.Drawing.Color.DimGray;
|
||||
this.tabPage1.Controls.Add(this.meshControlView);
|
||||
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, 509);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Mesh Control";
|
||||
//
|
||||
// meshControlView
|
||||
//
|
||||
this.meshControlView.BackColor = System.Drawing.Color.DimGray;
|
||||
this.meshControlView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.meshControlView.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.meshControlView.Location = new System.Drawing.Point(0, 0);
|
||||
this.meshControlView.Name = "meshControlView";
|
||||
this.meshControlView.Size = new System.Drawing.Size(272, 509);
|
||||
this.meshControlView.TabIndex = 0;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.BackColor = System.Drawing.Color.DimGray;
|
||||
this.tabPage2.Controls.Add(this.statisticView);
|
||||
this.tabPage2.ForeColor = System.Drawing.Color.White;
|
||||
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, 509);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Statistic";
|
||||
//
|
||||
// statisticView
|
||||
//
|
||||
this.statisticView.BackColor = System.Drawing.Color.DimGray;
|
||||
this.statisticView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.statisticView.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.statisticView.Location = new System.Drawing.Point(0, 0);
|
||||
this.statisticView.Name = "statisticView";
|
||||
this.statisticView.Size = new System.Drawing.Size(272, 509);
|
||||
this.statisticView.TabIndex = 0;
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.BackColor = System.Drawing.Color.DimGray;
|
||||
this.tabPage3.Controls.Add(this.aboutView);
|
||||
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, 509);
|
||||
this.tabPage3.TabIndex = 2;
|
||||
this.tabPage3.Text = "About";
|
||||
//
|
||||
// aboutView
|
||||
//
|
||||
this.aboutView.BackColor = System.Drawing.Color.DimGray;
|
||||
this.aboutView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.aboutView.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.aboutView.Location = new System.Drawing.Point(0, 0);
|
||||
this.aboutView.Name = "aboutView";
|
||||
this.aboutView.Size = new System.Drawing.Size(272, 509);
|
||||
this.aboutView.TabIndex = 0;
|
||||
//
|
||||
// menuStrip1
|
||||
//
|
||||
this.menuStrip1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
|
||||
this.menuStrip1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.menuStrip1.GripMargin = new System.Windows.Forms.Padding(0);
|
||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.menuFile,
|
||||
this.menuView,
|
||||
this.menuTools});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Padding = new System.Windows.Forms.Padding(0);
|
||||
this.menuStrip1.Size = new System.Drawing.Size(280, 24);
|
||||
this.menuStrip1.TabIndex = 0;
|
||||
this.menuStrip1.Text = "menuStrip1";
|
||||
//
|
||||
// menuFile
|
||||
//
|
||||
this.menuFile.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
|
||||
this.menuFile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.menuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.menuFileOpen,
|
||||
this.menuFileSave,
|
||||
this.toolStripSeparator3,
|
||||
this.menuFileExport,
|
||||
this.toolStripSeparator2,
|
||||
this.menuFileQuit});
|
||||
this.menuFile.Name = "menuFile";
|
||||
this.menuFile.Size = new System.Drawing.Size(37, 24);
|
||||
this.menuFile.Text = "File";
|
||||
//
|
||||
// menuFileOpen
|
||||
//
|
||||
this.menuFileOpen.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.menuFileOpen.Name = "menuFileOpen";
|
||||
this.menuFileOpen.Size = new System.Drawing.Size(141, 22);
|
||||
this.menuFileOpen.Text = "Open";
|
||||
this.menuFileOpen.Click += new System.EventHandler(this.menuFileOpen_Click);
|
||||
//
|
||||
// menuFileSave
|
||||
//
|
||||
this.menuFileSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.menuFileSave.Enabled = false;
|
||||
this.menuFileSave.Name = "menuFileSave";
|
||||
this.menuFileSave.Size = new System.Drawing.Size(141, 22);
|
||||
this.menuFileSave.Text = "Save";
|
||||
this.menuFileSave.Click += new System.EventHandler(this.menuFileSave_Click);
|
||||
//
|
||||
// toolStripSeparator3
|
||||
//
|
||||
this.toolStripSeparator3.Name = "toolStripSeparator3";
|
||||
this.toolStripSeparator3.Size = new System.Drawing.Size(138, 6);
|
||||
//
|
||||
// menuFileExport
|
||||
//
|
||||
this.menuFileExport.Enabled = false;
|
||||
this.menuFileExport.Name = "menuFileExport";
|
||||
this.menuFileExport.Size = new System.Drawing.Size(141, 22);
|
||||
this.menuFileExport.Text = "Export Image";
|
||||
this.menuFileExport.Click += new System.EventHandler(this.menuFileExport_Click);
|
||||
//
|
||||
// toolStripSeparator2
|
||||
//
|
||||
this.toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
this.toolStripSeparator2.Size = new System.Drawing.Size(138, 6);
|
||||
//
|
||||
// menuFileQuit
|
||||
//
|
||||
this.menuFileQuit.Name = "menuFileQuit";
|
||||
this.menuFileQuit.Size = new System.Drawing.Size(141, 22);
|
||||
this.menuFileQuit.Text = "Quit";
|
||||
this.menuFileQuit.Click += new System.EventHandler(this.menuFileQuit_Click);
|
||||
//
|
||||
// menuView
|
||||
//
|
||||
this.menuView.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.menuViewVoronoi,
|
||||
this.toolStripSeparator1,
|
||||
this.menuViewLog});
|
||||
this.menuView.Name = "menuView";
|
||||
this.menuView.Size = new System.Drawing.Size(44, 24);
|
||||
this.menuView.Text = "View";
|
||||
//
|
||||
// menuViewVoronoi
|
||||
//
|
||||
this.menuViewVoronoi.Enabled = false;
|
||||
this.menuViewVoronoi.Name = "menuViewVoronoi";
|
||||
this.menuViewVoronoi.Size = new System.Drawing.Size(162, 22);
|
||||
this.menuViewVoronoi.Text = "Voronoi Diagram";
|
||||
this.menuViewVoronoi.Click += new System.EventHandler(this.menuViewVoronoi_Click);
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
this.toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
this.toolStripSeparator1.Size = new System.Drawing.Size(159, 6);
|
||||
//
|
||||
// menuViewLog
|
||||
//
|
||||
this.menuViewLog.Name = "menuViewLog";
|
||||
this.menuViewLog.Size = new System.Drawing.Size(162, 22);
|
||||
this.menuViewLog.Text = "Show Log";
|
||||
this.menuViewLog.Click += new System.EventHandler(this.menuViewLog_Click);
|
||||
//
|
||||
// menuTools
|
||||
//
|
||||
this.menuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.menuToolsGen,
|
||||
this.menuToolsCheck,
|
||||
this.toolStripSeparator5,
|
||||
this.menuToolsTopology,
|
||||
this.toolStripSeparator4,
|
||||
this.menuToolsRcm});
|
||||
this.menuTools.Name = "menuTools";
|
||||
this.menuTools.Size = new System.Drawing.Size(46, 24);
|
||||
this.menuTools.Text = "Tools";
|
||||
//
|
||||
// menuToolsGen
|
||||
//
|
||||
this.menuToolsGen.Name = "menuToolsGen";
|
||||
this.menuToolsGen.Size = new System.Drawing.Size(195, 22);
|
||||
this.menuToolsGen.Text = "Input Generator";
|
||||
this.menuToolsGen.Click += new System.EventHandler(this.menuToolsGenerator_Click);
|
||||
//
|
||||
// menuToolsCheck
|
||||
//
|
||||
this.menuToolsCheck.Enabled = false;
|
||||
this.menuToolsCheck.Name = "menuToolsCheck";
|
||||
this.menuToolsCheck.Size = new System.Drawing.Size(195, 22);
|
||||
this.menuToolsCheck.Text = "Check Mesh";
|
||||
this.menuToolsCheck.Click += new System.EventHandler(this.menuToolsCheck_Click);
|
||||
//
|
||||
// toolStripSeparator5
|
||||
//
|
||||
this.toolStripSeparator5.Name = "toolStripSeparator5";
|
||||
this.toolStripSeparator5.Size = new System.Drawing.Size(192, 6);
|
||||
//
|
||||
// menuToolsTopology
|
||||
//
|
||||
this.menuToolsTopology.Name = "menuToolsTopology";
|
||||
this.menuToolsTopology.Size = new System.Drawing.Size(195, 22);
|
||||
this.menuToolsTopology.Text = "Topology Explorer";
|
||||
this.menuToolsTopology.Click += new System.EventHandler(this.menuToolsTopology_Click);
|
||||
//
|
||||
// toolStripSeparator4
|
||||
//
|
||||
this.toolStripSeparator4.Name = "toolStripSeparator4";
|
||||
this.toolStripSeparator4.Size = new System.Drawing.Size(192, 6);
|
||||
//
|
||||
// menuToolsRcm
|
||||
//
|
||||
this.menuToolsRcm.Enabled = false;
|
||||
this.menuToolsRcm.Name = "menuToolsRcm";
|
||||
this.menuToolsRcm.Size = new System.Drawing.Size(195, 22);
|
||||
this.menuToolsRcm.Text = "Renumber nodes (RCM)";
|
||||
this.menuToolsRcm.Click += new System.EventHandler(this.menuToolsRcm_Click);
|
||||
//
|
||||
// btnMesh
|
||||
//
|
||||
this.btnMesh.Enabled = false;
|
||||
this.btnMesh.Location = new System.Drawing.Point(4, 44);
|
||||
this.btnMesh.Name = "btnMesh";
|
||||
this.btnMesh.Size = new System.Drawing.Size(130, 23);
|
||||
this.btnMesh.TabIndex = 12;
|
||||
this.btnMesh.Text = "Triangulate";
|
||||
this.btnMesh.UseVisualStyleBackColor = true;
|
||||
this.btnMesh.Click += new System.EventHandler(this.btnMesh_Click);
|
||||
//
|
||||
// FormMain
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
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(992, 623);
|
||||
this.Controls.Add(this.splitContainer);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.KeyPreview = true;
|
||||
this.MainMenuStrip = this.menuStrip1;
|
||||
this.MinimumSize = new System.Drawing.Size(1000, 650);
|
||||
this.Name = "FormMain";
|
||||
this.Text = "Triangle.NET - Mesh Explorer";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.ResizeBegin += new System.EventHandler(this.ResizeBeginHandler);
|
||||
this.ResizeEnd += new System.EventHandler(this.ResizeEndHandler);
|
||||
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.frmDragDrop);
|
||||
this.DragOver += new System.Windows.Forms.DragEventHandler(this.frmDragOver);
|
||||
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
|
||||
this.Resize += new System.EventHandler(this.ResizeHandler);
|
||||
this.splitContainer.Panel1.ResumeLayout(false);
|
||||
this.splitContainer.Panel1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
|
||||
this.splitContainer.ResumeLayout(false);
|
||||
this.flatTabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.menuStrip1.ResumeLayout(false);
|
||||
this.menuStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.SplitContainer splitContainer;
|
||||
private System.Windows.Forms.MenuStrip menuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuFile;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuFileOpen;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuFileSave;
|
||||
private Controls.DarkTabControl flatTabControl1;
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private Controls.DarkButton btnSmooth;
|
||||
private Controls.DarkButton btnMesh;
|
||||
private System.Windows.Forms.TabPage tabPage3;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuView;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuViewVoronoi;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuViewLog;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuTools;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuToolsGen;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuToolsCheck;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuFileQuit;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuFileExport;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuToolsRcm;
|
||||
private Views.MeshControlView meshControlView;
|
||||
private Views.StatisticView statisticView;
|
||||
private Views.AboutView aboutView;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
|
||||
private System.Windows.Forms.ToolStripMenuItem menuToolsTopology;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,795 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using MeshExplorer.Controls;
|
||||
using MeshExplorer.IO;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Meshing.Algorithm;
|
||||
using TriangleNet.Rendering;
|
||||
using TriangleNet.Smoothing;
|
||||
using TriangleNet.Voronoi;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
public partial class FormMain : Form
|
||||
{
|
||||
Settings settings;
|
||||
|
||||
Mesh mesh;
|
||||
IPolygon input;
|
||||
VoronoiBase voronoi;
|
||||
|
||||
FormLog frmLog;
|
||||
FormGenerator frmGenerator;
|
||||
|
||||
RenderManager renderManager;
|
||||
|
||||
public FormMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ToolStripManager.Renderer = new DarkToolStripRenderer();
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
oldClientSize = this.ClientSize;
|
||||
|
||||
settings = new Settings();
|
||||
|
||||
renderManager = new RenderManager();
|
||||
|
||||
IRenderControl control = new TriangleNet.Rendering.GDI.RenderControl();
|
||||
|
||||
/*
|
||||
if (!renderManager.TryCreateControl("Triangle.Rendering.SharpGL.dll",
|
||||
new string[] { "SharpGL.dll" }, out control))
|
||||
{
|
||||
control = new TriangleNet.Rendering.GDI.RenderControl();
|
||||
|
||||
if (frmLog == null)
|
||||
{
|
||||
frmLog = new FormLog();
|
||||
}
|
||||
|
||||
frmLog.AddItem("Failed to initialize OpenGL.", true);
|
||||
}
|
||||
//*/
|
||||
|
||||
if (control != null)
|
||||
{
|
||||
InitializeRenderControl((Control)control);
|
||||
renderManager.Initialize(control);
|
||||
}
|
||||
else
|
||||
{
|
||||
DarkMessageBox.Show("Ooops ...", "Failed to initialize renderer.");
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeRenderControl(Control control)
|
||||
{
|
||||
this.splitContainer.SuspendLayout();
|
||||
this.splitContainer.Panel2.Controls.Add(control);
|
||||
|
||||
var size = this.splitContainer.Panel2.ClientRectangle;
|
||||
|
||||
// Initialize control
|
||||
control.BackColor = Color.Black;
|
||||
control.Dock = DockStyle.Fill;
|
||||
control.Font = new Font("Consolas", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
|
||||
control.Location = new System.Drawing.Point(0, 0);
|
||||
control.Name = "renderControl1";
|
||||
control.Size = new Size(size.Width, size.Height);
|
||||
control.TabIndex = 0;
|
||||
control.Text = "renderControl1";
|
||||
|
||||
this.splitContainer.ResumeLayout();
|
||||
}
|
||||
|
||||
protected override void OnMouseWheel(MouseEventArgs e)
|
||||
{
|
||||
if (splitContainer.Panel2.Bounds.Contains(e.Location))
|
||||
{
|
||||
var control = renderManager.Control as Control;
|
||||
|
||||
// Set focus on the render control.
|
||||
if (control != null && !control.Focused)
|
||||
{
|
||||
control.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Form1_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
switch (e.KeyCode)
|
||||
{
|
||||
case Keys.F3:
|
||||
OpenWithDialog();
|
||||
break;
|
||||
case Keys.F4:
|
||||
Save();
|
||||
break;
|
||||
case Keys.F5:
|
||||
Reload();
|
||||
break;
|
||||
case Keys.F8:
|
||||
TriangulateOrRefine();
|
||||
break;
|
||||
case Keys.F9:
|
||||
Smooth();
|
||||
break;
|
||||
case Keys.F12:
|
||||
ShowLog();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void frmGenerator_InputGenerated(object sender, EventArgs e)
|
||||
{
|
||||
this.input = sender as IPolygon;
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
settings.CurrentFile = "tmp-" + DateTime.Now.ToString("HH-mm-ss");
|
||||
HandleNewInput();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnMesh_Click(object sender, EventArgs e)
|
||||
{
|
||||
TriangulateOrRefine();
|
||||
}
|
||||
|
||||
private void btnSmooth_Click(object sender, EventArgs e)
|
||||
{
|
||||
Smooth();
|
||||
}
|
||||
|
||||
#region Drag and drop
|
||||
|
||||
private void frmDragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
{
|
||||
string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
|
||||
Open(args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private void frmDragOver(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
{
|
||||
string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
|
||||
if (args.Length > 1)
|
||||
{
|
||||
e.Effect = DragDropEffects.None;
|
||||
return;
|
||||
}
|
||||
|
||||
string file = args[0].ToLower();
|
||||
|
||||
// Check if file extension is known
|
||||
if (FileProcessor.CanHandleFile(file))
|
||||
{
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Effect = DragDropEffects.None;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Resize event handler
|
||||
|
||||
bool isResizing = false;
|
||||
Size oldClientSize;
|
||||
|
||||
private void ResizeHandler(object sender, EventArgs e)
|
||||
{
|
||||
// Handle window minimize and maximize
|
||||
if (!isResizing)
|
||||
{
|
||||
renderManager.Resize();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResizeEndHandler(object sender, EventArgs e)
|
||||
{
|
||||
isResizing = false;
|
||||
|
||||
if (this.ClientSize != this.oldClientSize)
|
||||
{
|
||||
this.oldClientSize = this.ClientSize;
|
||||
renderManager.Resize();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResizeBeginHandler(object sender, EventArgs e)
|
||||
{
|
||||
isResizing = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region State changes
|
||||
|
||||
private void LockOnException()
|
||||
{
|
||||
btnMesh.Enabled = false;
|
||||
btnSmooth.Enabled = false;
|
||||
|
||||
//menuFileSave.Enabled = false;
|
||||
//menuFileExport.Enabled = false;
|
||||
menuViewVoronoi.Enabled = false;
|
||||
menuToolsCheck.Enabled = false;
|
||||
menuToolsRcm.Enabled = false;
|
||||
|
||||
settings.ExceptionThrown = true;
|
||||
}
|
||||
|
||||
private void HandleNewInput()
|
||||
{
|
||||
// Reset mesh
|
||||
mesh = null;
|
||||
voronoi = null;
|
||||
|
||||
// Reset state
|
||||
settings.RefineMode = false;
|
||||
settings.ExceptionThrown = false;
|
||||
|
||||
// Reset buttons
|
||||
btnMesh.Enabled = true;
|
||||
btnMesh.Text = "Triangulate";
|
||||
btnSmooth.Enabled = false;
|
||||
|
||||
// Update Statistic view
|
||||
statisticView.HandleNewInput(input);
|
||||
|
||||
// Clear voronoi
|
||||
menuViewVoronoi.Checked = false;
|
||||
|
||||
// Disable menu items
|
||||
menuFileSave.Enabled = false;
|
||||
menuFileExport.Enabled = false;
|
||||
menuViewVoronoi.Enabled = false;
|
||||
menuToolsCheck.Enabled = false;
|
||||
menuToolsRcm.Enabled = false;
|
||||
|
||||
// Render input
|
||||
renderManager.Set(input);
|
||||
|
||||
// Update window caption
|
||||
this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
|
||||
}
|
||||
|
||||
private void HandleMeshImport()
|
||||
{
|
||||
voronoi = null;
|
||||
|
||||
// Render mesh
|
||||
renderManager.Set(mesh, true);
|
||||
|
||||
// Update window caption
|
||||
this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
|
||||
|
||||
// Update Statistic view
|
||||
statisticView.HandleMeshImport(input, mesh);
|
||||
|
||||
// Set refine mode
|
||||
btnMesh.Enabled = true;
|
||||
btnMesh.Text = "Refine";
|
||||
|
||||
settings.RefineMode = true;
|
||||
|
||||
HandleMeshChange();
|
||||
}
|
||||
|
||||
private void HandleMeshUpdate()
|
||||
{
|
||||
// Render mesh
|
||||
renderManager.Set(mesh, false);
|
||||
|
||||
// Update Statistic view
|
||||
statisticView.HandleMeshUpdate(mesh);
|
||||
|
||||
HandleMeshChange();
|
||||
}
|
||||
|
||||
private void HandleMeshChange()
|
||||
{
|
||||
// Update Statistic view
|
||||
statisticView.HandleMeshChange(mesh);
|
||||
|
||||
// TODO: Should the Voronoi diagram automatically update?
|
||||
voronoi = null;
|
||||
menuViewVoronoi.Checked = false;
|
||||
|
||||
// Enable menu items
|
||||
menuFileSave.Enabled = true;
|
||||
menuFileExport.Enabled = true;
|
||||
menuViewVoronoi.Enabled = true;
|
||||
menuToolsCheck.Enabled = true;
|
||||
menuToolsRcm.Enabled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Commands
|
||||
|
||||
private void OpenWithDialog()
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
|
||||
ofd.Filter = settings.OfdFilter;
|
||||
ofd.FilterIndex = settings.OfdFilterIndex;
|
||||
ofd.InitialDirectory = settings.OfdDirectory;
|
||||
ofd.FileName = "";
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
if (Open(ofd.FileName))
|
||||
{
|
||||
// Update folder settings
|
||||
settings.OfdFilterIndex = ofd.FilterIndex;
|
||||
settings.OfdDirectory = Path.GetDirectoryName(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool Open(string filename)
|
||||
{
|
||||
if (!FileProcessor.CanHandleFile(filename))
|
||||
{
|
||||
// TODO: show message.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FileProcessor.ContainsMeshData(filename))
|
||||
{
|
||||
if (filename.EndsWith(".ele") || DarkMessageBox.Show("Import mesh", Settings.ImportString,
|
||||
"Do you want to import the mesh?", MessageBoxButtons.YesNo) == DialogResult.OK)
|
||||
{
|
||||
input = null;
|
||||
|
||||
try
|
||||
{
|
||||
mesh = FileProcessor.Import(filename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DarkMessageBox.Show("Import mesh error", e.Message, MessageBoxButtons.OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mesh != null)
|
||||
{
|
||||
statisticView.UpdateStatistic(mesh);
|
||||
|
||||
// Update settings
|
||||
settings.CurrentFile = Path.GetFileName(filename);
|
||||
|
||||
HandleMeshImport();
|
||||
btnSmooth.Enabled = true; // TODO: Remove
|
||||
}
|
||||
// else Message
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
input = FileProcessor.Read(filename);
|
||||
}
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
// Update settings
|
||||
settings.CurrentFile = Path.GetFileName(filename);
|
||||
|
||||
HandleNewInput();
|
||||
}
|
||||
// else Message
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
|
||||
sfd.Filter = settings.SfdFilter;
|
||||
sfd.FilterIndex = settings.SfdFilterIndex;
|
||||
sfd.InitialDirectory = settings.SfdDirectory;
|
||||
sfd.FileName = "";
|
||||
|
||||
if (sfd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
FileProcessor.Save(sfd.FileName, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
private void Reload()
|
||||
{
|
||||
if (input != null)
|
||||
{
|
||||
mesh = null;
|
||||
settings.RefineMode = false;
|
||||
settings.ExceptionThrown = false;
|
||||
|
||||
HandleNewInput();
|
||||
}
|
||||
}
|
||||
|
||||
private void TriangulateOrRefine()
|
||||
{
|
||||
if ((input == null && !settings.RefineMode) || settings.ExceptionThrown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.RefineMode == false)
|
||||
{
|
||||
Triangulate();
|
||||
|
||||
if (meshControlView.ParamQualityChecked)
|
||||
{
|
||||
btnMesh.Text = "Refine";
|
||||
btnSmooth.Enabled = mesh.IsPolygon;
|
||||
}
|
||||
}
|
||||
else if (meshControlView.ParamQualityChecked)
|
||||
{
|
||||
Refine();
|
||||
}
|
||||
}
|
||||
|
||||
private void Triangulate()
|
||||
{
|
||||
if (input == null) return;
|
||||
|
||||
var options = new ConstraintOptions();
|
||||
var quality = new QualityOptions();
|
||||
|
||||
if (meshControlView.ParamConformDelChecked)
|
||||
{
|
||||
options.ConformingDelaunay = true;
|
||||
}
|
||||
|
||||
if (meshControlView.ParamQualityChecked)
|
||||
{
|
||||
quality.MinimumAngle = meshControlView.ParamMinAngleValue;
|
||||
|
||||
double maxAngle = meshControlView.ParamMaxAngleValue;
|
||||
|
||||
if (maxAngle < 180)
|
||||
{
|
||||
quality.MaximumAngle = maxAngle;
|
||||
}
|
||||
|
||||
// Ignore area constraints on initial triangulation.
|
||||
|
||||
//double area = slMaxArea.Value * 0.01;
|
||||
//if (area > 0 && area < 1)
|
||||
//{
|
||||
// var size = input.Bounds;
|
||||
// double min = Math.Min(size.Width, size.Height);
|
||||
// mesh.SetOption(Options.MaxArea, area * min);
|
||||
//}
|
||||
}
|
||||
|
||||
if (meshControlView.ParamConvexChecked)
|
||||
{
|
||||
options.Convex = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (meshControlView.ParamSweeplineChecked)
|
||||
{
|
||||
mesh = (Mesh)input.Triangulate(options, quality, new SweepLine());
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh = (Mesh)input.Triangulate(options, quality);
|
||||
}
|
||||
|
||||
statisticView.UpdateStatistic(mesh);
|
||||
|
||||
HandleMeshUpdate();
|
||||
|
||||
if (meshControlView.ParamQualityChecked)
|
||||
{
|
||||
settings.RefineMode = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LockOnException();
|
||||
DarkMessageBox.Show("Exception - Triangulate", ex.Message, MessageBoxButtons.OK);
|
||||
}
|
||||
|
||||
UpdateLog();
|
||||
}
|
||||
|
||||
private void Refine()
|
||||
{
|
||||
if (mesh == null) return;
|
||||
|
||||
double area = meshControlView.ParamMaxAreaValue;
|
||||
|
||||
var quality = new QualityOptions();
|
||||
|
||||
if (area > 0 && area < 1)
|
||||
{
|
||||
quality.MaximumArea = area * statisticView.Statistic.LargestArea;
|
||||
}
|
||||
|
||||
quality.MinimumAngle = meshControlView.ParamMinAngleValue;
|
||||
|
||||
double maxAngle = meshControlView.ParamMaxAngleValue;
|
||||
|
||||
if (maxAngle < 180)
|
||||
{
|
||||
quality.MaximumAngle = maxAngle;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mesh.Refine(quality, meshControlView.ParamConformDelChecked);
|
||||
|
||||
statisticView.UpdateStatistic(mesh);
|
||||
|
||||
HandleMeshUpdate();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LockOnException();
|
||||
DarkMessageBox.Show("Exception - Refine", ex.Message, MessageBoxButtons.OK);
|
||||
}
|
||||
|
||||
UpdateLog();
|
||||
}
|
||||
|
||||
private void Renumber()
|
||||
{
|
||||
if (mesh == null || settings.ExceptionThrown) return;
|
||||
|
||||
bool tmp = Log.Verbose;
|
||||
Log.Verbose = true;
|
||||
|
||||
mesh.Renumber(NodeNumbering.CuthillMcKee);
|
||||
ShowLog();
|
||||
|
||||
Log.Verbose = tmp;
|
||||
}
|
||||
|
||||
private void Smooth()
|
||||
{
|
||||
if (mesh == null || settings.ExceptionThrown) return;
|
||||
|
||||
if (!mesh.IsPolygon)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var smoother = new SimpleSmoother();
|
||||
|
||||
try
|
||||
{
|
||||
smoother.Smooth(this.mesh);
|
||||
|
||||
statisticView.UpdateStatistic(mesh);
|
||||
|
||||
HandleMeshUpdate();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LockOnException();
|
||||
DarkMessageBox.Show("Exception - Smooth", ex.Message, MessageBoxButtons.OK);
|
||||
}
|
||||
|
||||
UpdateLog();
|
||||
}
|
||||
|
||||
private bool CreateVoronoi()
|
||||
{
|
||||
if (mesh == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mesh.IsPolygon)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.voronoi = new BoundedVoronoi(mesh);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!meshControlView.ParamConformDelChecked)
|
||||
{
|
||||
DarkMessageBox.Show("Exception - Bounded Voronoi", Settings.VoronoiString, MessageBoxButtons.OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
DarkMessageBox.Show("Exception - Bounded Voronoi", ex.Message, MessageBoxButtons.OK);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.voronoi = new StandardVoronoi(mesh);
|
||||
}
|
||||
|
||||
// HACK: List<Vertex> -> ICollection<Point> ? Nope, no way.
|
||||
// Vertex[] -> ICollection<Point> ? Well, ok.
|
||||
renderManager.Set(voronoi.Vertices.ToArray(), voronoi.Edges, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ShowLog()
|
||||
{
|
||||
if (frmLog == null)
|
||||
{
|
||||
frmLog = new FormLog();
|
||||
}
|
||||
|
||||
UpdateLog();
|
||||
|
||||
if (!frmLog.Visible)
|
||||
{
|
||||
frmLog.Show(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLog()
|
||||
{
|
||||
if (frmLog != null)
|
||||
{
|
||||
frmLog.UpdateItems();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Menu Handler
|
||||
|
||||
private void menuFileOpen_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenWithDialog();
|
||||
}
|
||||
|
||||
private void menuFileSave_Click(object sender, EventArgs ev)
|
||||
{
|
||||
if (mesh != null)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
private void menuFileExport_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (mesh != null)
|
||||
{
|
||||
FormExport export = new FormExport();
|
||||
|
||||
string file = settings.OfdDirectory;
|
||||
|
||||
if (!file.EndsWith("\\"))
|
||||
{
|
||||
file += "\\";
|
||||
}
|
||||
|
||||
file += settings.CurrentFile;
|
||||
|
||||
export.ImageName = Path.ChangeExtension(file, ".png");
|
||||
|
||||
if (export.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
int format = export.ImageFormat;
|
||||
int size = export.ImageSize;
|
||||
bool compress = export.UseCompression;
|
||||
|
||||
var writer = new ImageWriter();
|
||||
|
||||
writer.Export(this.mesh, export.ImageName, format, size, compress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void menuFileQuit_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void menuViewVoronoi_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (this.voronoi == null)
|
||||
{
|
||||
menuViewVoronoi.Checked = CreateVoronoi();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool visible = menuViewVoronoi.Checked;
|
||||
|
||||
renderManager.Enable(4, !visible);
|
||||
menuViewVoronoi.Checked = !visible;
|
||||
}
|
||||
}
|
||||
|
||||
private void menuViewLog_Click(object sender, EventArgs e)
|
||||
{
|
||||
ShowLog();
|
||||
}
|
||||
|
||||
private void menuToolsGenerator_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (frmGenerator == null || frmGenerator.IsDisposed)
|
||||
{
|
||||
frmGenerator = new FormGenerator();
|
||||
frmGenerator.InputGenerated += new EventHandler(frmGenerator_InputGenerated);
|
||||
}
|
||||
|
||||
if (!frmGenerator.Visible)
|
||||
{
|
||||
frmGenerator.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
frmGenerator.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
private void menuToolsCheck_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (mesh != null)
|
||||
{
|
||||
bool save = Log.Verbose;
|
||||
|
||||
Log.Verbose = true;
|
||||
|
||||
bool isConsistent = MeshValidator.IsConsistent(mesh);
|
||||
bool isDelaunay = MeshValidator.IsDelaunay(mesh);
|
||||
|
||||
Log.Verbose = save;
|
||||
|
||||
if (isConsistent)
|
||||
{
|
||||
Log.Instance.Info("Mesh topology appears to be consistent.");
|
||||
}
|
||||
|
||||
if (isDelaunay)
|
||||
{
|
||||
Log.Instance.Info("Mesh is (conforming) Delaunay.");
|
||||
}
|
||||
|
||||
ShowLog();
|
||||
}
|
||||
}
|
||||
|
||||
private void menuToolsTopology_Click(object sender, EventArgs e)
|
||||
{
|
||||
(new FormTopology()).ShowDialog(this);
|
||||
}
|
||||
|
||||
private void menuToolsRcm_Click(object sender, EventArgs e)
|
||||
{
|
||||
Renumber();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
Generated
+112
@@ -0,0 +1,112 @@
|
||||
namespace MeshExplorer
|
||||
{
|
||||
partial class FormTopology
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.renderControl = new MeshExplorer.Topology.TopologyRenderControl();
|
||||
this.topoControlView = new MeshExplorer.Topology.TopologyControlView();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer1.IsSplitterFixed = true;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.renderControl);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.topoControlView);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(674, 455);
|
||||
this.splitContainer1.SplitterDistance = 475;
|
||||
this.splitContainer1.SplitterWidth = 1;
|
||||
this.splitContainer1.TabIndex = 0;
|
||||
//
|
||||
// renderControl
|
||||
//
|
||||
this.renderControl.BackColor = System.Drawing.Color.Black;
|
||||
this.renderControl.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.renderControl.Location = new System.Drawing.Point(0, 0);
|
||||
this.renderControl.Name = "renderControl";
|
||||
this.renderControl.Size = new System.Drawing.Size(475, 455);
|
||||
this.renderControl.TabIndex = 0;
|
||||
this.renderControl.Text = "topologyRenderControl";
|
||||
this.renderControl.MouseClick += new System.Windows.Forms.MouseEventHandler(this.renderControl_MouseClick);
|
||||
//
|
||||
// topoControlView
|
||||
//
|
||||
this.topoControlView.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
|
||||
this.topoControlView.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.topoControlView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.topoControlView.ForeColor = System.Drawing.Color.White;
|
||||
this.topoControlView.Location = new System.Drawing.Point(0, 0);
|
||||
this.topoControlView.Name = "topoControlView";
|
||||
this.topoControlView.Size = new System.Drawing.Size(198, 455);
|
||||
this.topoControlView.TabIndex = 2;
|
||||
//
|
||||
// FormTopology
|
||||
//
|
||||
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(674, 455);
|
||||
this.Controls.Add(this.splitContainer1);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.ForeColor = System.Drawing.Color.White;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "FormTopology";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.Text = "Triangle.NET - Topology Explorer";
|
||||
this.Load += new System.EventHandler(this.FormTopology_Load);
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private Topology.TopologyRenderControl renderControl;
|
||||
private Topology.TopologyControlView topoControlView;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using MeshExplorer.Topology;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Tools;
|
||||
using TriangleNet.Topology;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
public partial class FormTopology : Form
|
||||
{
|
||||
Mesh mesh;
|
||||
TriangleQuadTree tree;
|
||||
Otri current;
|
||||
|
||||
public FormTopology()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void FormTopology_Load(object sender, EventArgs e)
|
||||
{
|
||||
mesh = (Mesh)GenericMesher.StructuredMesh(new Rectangle(0.0, 0.0, 4.0, 4.0), 4, 4);
|
||||
|
||||
renderControl.Initialize(mesh);
|
||||
|
||||
topoControlView.PrimitiveCommandInvoked += PrimitiveCommandHandler;
|
||||
|
||||
current = default(Otri);
|
||||
}
|
||||
|
||||
void PrimitiveCommandHandler(object sender, GenericEventArgs<string> e)
|
||||
{
|
||||
if (current.Triangle != null)
|
||||
{
|
||||
InvokePrimitive(e.Argument);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderControl_MouseClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
var p = e.Location;
|
||||
var size = renderControl.Size;
|
||||
|
||||
var tri = FindTriangleAt(((float)p.X) / size.Width, ((float)p.Y) / size.Height);
|
||||
|
||||
current.Triangle = (Triangle)tri;
|
||||
|
||||
renderControl.Update(current);
|
||||
topoControlView.SetTriangle(current.Triangle);
|
||||
}
|
||||
|
||||
private ITriangle FindTriangleAt(float x, float y)
|
||||
{
|
||||
// Get mesh coordinates
|
||||
var p = new System.Drawing.PointF(x, y);
|
||||
renderControl.Zoom.ScreenToWorld(ref p);
|
||||
|
||||
topoControlView.SetPosition(p);
|
||||
|
||||
if (tree == null)
|
||||
{
|
||||
tree = new TriangleQuadTree(mesh, 5, 2);
|
||||
}
|
||||
|
||||
return tree.Query(p.X, p.Y);
|
||||
}
|
||||
|
||||
private void InvokePrimitive(string name)
|
||||
{
|
||||
if (name == "sym")
|
||||
{
|
||||
current.Sym();
|
||||
}
|
||||
else if (name == "lnext")
|
||||
{
|
||||
current.Lnext();
|
||||
}
|
||||
else if (name == "lprev")
|
||||
{
|
||||
current.Lprev();
|
||||
}
|
||||
else if (name == "onext")
|
||||
{
|
||||
current.Onext();
|
||||
}
|
||||
else if (name == "oprev")
|
||||
{
|
||||
current.Oprev();
|
||||
}
|
||||
else if (name == "dnext")
|
||||
{
|
||||
current.Dnext();
|
||||
}
|
||||
else if (name == "dprev")
|
||||
{
|
||||
current.Dprev();
|
||||
}
|
||||
else if (name == "rnext")
|
||||
{
|
||||
current.Rnext();
|
||||
}
|
||||
else if (name == "rprev")
|
||||
{
|
||||
current.Rprev();
|
||||
}
|
||||
|
||||
renderControl.Update(current);
|
||||
topoControlView.SetTriangle(current.Triangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,158 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="BaseGenerator.cs" company="">
|
||||
// TODO: Update copyright text.
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Update summary.
|
||||
/// </summary>
|
||||
public abstract class BaseGenerator : IGenerator
|
||||
{
|
||||
private static int MAX_PARAMS = 3;
|
||||
|
||||
protected string name = "Name";
|
||||
protected string description = "Description";
|
||||
protected int parameter = 0;
|
||||
|
||||
protected string[] descriptions = new string[MAX_PARAMS];
|
||||
protected int[][] ranges = new int[MAX_PARAMS][];
|
||||
|
||||
public virtual string Name { get { return name; } }
|
||||
public virtual string Description { get { return description; } }
|
||||
public virtual int ParameterCount { get { return parameter; } }
|
||||
|
||||
public virtual string ParameterDescription(int paramIndex)
|
||||
{
|
||||
if (descriptions[paramIndex] == null)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return descriptions[paramIndex];
|
||||
}
|
||||
|
||||
public virtual string ParameterDescription(int paramIndex, double paramValue)
|
||||
{
|
||||
int[] range = ranges[paramIndex];
|
||||
|
||||
if (range == null)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
int num = GetParamValueInt(paramIndex, paramValue);
|
||||
return num.ToString();
|
||||
}
|
||||
|
||||
public abstract IPolygon Generate(double param0, double param1, double param2);
|
||||
|
||||
#region Contour helpers
|
||||
|
||||
protected List<Vertex> CreateCircle(double r, int n, int boundary = 0)
|
||||
{
|
||||
return CreateCircle(0.0, 0.0, r, n, boundary);
|
||||
}
|
||||
|
||||
protected List<Vertex> CreateCircle(double x, double y, double r, int n, int boundary = 0)
|
||||
{
|
||||
return CreateEllipse(0.0, 0.0, r, 1.0, 1.0, n, boundary);
|
||||
}
|
||||
|
||||
protected List<Vertex> CreateEllipse(double r, double a, double b, int n, int boundary = 0)
|
||||
{
|
||||
return CreateEllipse(0.0, 0.0, r, a, b, n, boundary);
|
||||
}
|
||||
|
||||
protected List<Vertex> CreateEllipse(double x, double y, double r, double a, double b, int n, int boundary = 0)
|
||||
{
|
||||
var contour = new List<Vertex>(n);
|
||||
|
||||
double dphi = 2 * Math.PI / n;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
contour.Add(new Vertex(x + a * r * Math.Cos(i * dphi), y + b * r * Math.Sin(i * dphi), boundary));
|
||||
}
|
||||
|
||||
return contour;
|
||||
}
|
||||
|
||||
protected List<Vertex> CreateRectangle(Rectangle rect, int n, int boundary = 0)
|
||||
{
|
||||
return CreateRectangle(rect, n, n, boundary);
|
||||
}
|
||||
|
||||
protected List<Vertex> CreateRectangle(Rectangle rect, int nH, int nV, int boundary = 0)
|
||||
{
|
||||
var contour = new List<Vertex>(2 * nH + 2 * nV);
|
||||
|
||||
// Horizontal and vertical step sizes.
|
||||
double stepH = rect.Width / nH;
|
||||
double stepV = rect.Height / nV;
|
||||
|
||||
// Left box boundary points
|
||||
for (int i = 0; i < nV; i++)
|
||||
{
|
||||
contour.Add(new Vertex(rect.Left, rect.Bottom + i * stepV, 1));
|
||||
}
|
||||
|
||||
// Top box boundary points
|
||||
for (int i = 0; i < nH; i++)
|
||||
{
|
||||
contour.Add(new Vertex(rect.Left + i * stepH, rect.Top, 1));
|
||||
}
|
||||
|
||||
// Right box boundary points
|
||||
for (int i = 0; i < nV; i++)
|
||||
{
|
||||
contour.Add(new Vertex(rect.Right, rect.Top - i * stepV, 1));
|
||||
}
|
||||
|
||||
// Bottom box boundary points
|
||||
for (int i = 0; i < nH; i++)
|
||||
{
|
||||
contour.Add(new Vertex(rect.Right - i * stepH, rect.Bottom, 1));
|
||||
}
|
||||
|
||||
return contour;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected int GetParamValueInt(int paramIndex, double paramOffset)
|
||||
{
|
||||
int[] range = ranges[paramIndex];
|
||||
|
||||
if (range == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)((range[1] - range[0]) / 100.0 * paramOffset + range[0]);
|
||||
}
|
||||
|
||||
protected double GetParamValueDouble(int paramIndex, double paramOffset)
|
||||
{
|
||||
int[] range = ranges[paramIndex];
|
||||
|
||||
if (range == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((range[1] - range[0]) / 100.0 * paramOffset + range[0]);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="StarInBox.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Generates a star contained in a box.
|
||||
/// </summary>
|
||||
public class BoxWithHole : BaseGenerator
|
||||
{
|
||||
public BoxWithHole()
|
||||
{
|
||||
name = "Box with Hole";
|
||||
description = "";
|
||||
parameter = 3;
|
||||
|
||||
descriptions[0] = "Points on box sides:";
|
||||
descriptions[1] = "Points on hole:";
|
||||
descriptions[2] = "Radius:";
|
||||
|
||||
ranges[0] = new int[] { 5, 50 };
|
||||
ranges[1] = new int[] { 10, 200 };
|
||||
ranges[2] = new int[] { 5, 20 };
|
||||
}
|
||||
|
||||
public override IPolygon Generate(double param0, double param1, double param2)
|
||||
{
|
||||
int n = GetParamValueInt(1, param1);
|
||||
|
||||
var input = new Polygon(n + 4);
|
||||
|
||||
double r = GetParamValueInt(2, param2);
|
||||
|
||||
// Generate circle (hole)
|
||||
input.AddContour(CreateCircle(r, n, 1), 1, new Point(0, 0));
|
||||
|
||||
n = GetParamValueInt(0, param0);
|
||||
|
||||
// Generate box
|
||||
input.AddContour(CreateRectangle(new Rectangle(-50, -50, 100, 100), n, 2), 2);
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="RingPolygon.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Generates a ring polygon.
|
||||
/// </summary>
|
||||
public class CircleWithHole : BaseGenerator
|
||||
{
|
||||
public CircleWithHole()
|
||||
{
|
||||
name = "Circle with Hole";
|
||||
description = "";
|
||||
parameter = 2;
|
||||
|
||||
descriptions[0] = "Number of points:";
|
||||
descriptions[1] = "Outer radius:";
|
||||
|
||||
ranges[0] = new int[] { 100, 250 };
|
||||
ranges[1] = new int[] { 2, 15 };
|
||||
}
|
||||
|
||||
public override IPolygon Generate(double param0, double param1, double param2)
|
||||
{
|
||||
// Number of points on the outer circle
|
||||
int n = GetParamValueInt(0, param0);
|
||||
|
||||
double radius = GetParamValueInt(1, param1);
|
||||
|
||||
// Current radius and step size
|
||||
double r, h = radius / n;
|
||||
|
||||
var input = new Polygon(n + 1);
|
||||
|
||||
// Inner cirlce (radius = 1) (hole)
|
||||
r = 1;
|
||||
input.AddContour(CreateCircle(r, (int)(r / h), 1), 1, new Point(0, 0));
|
||||
|
||||
// Center cirlce
|
||||
r = (radius + 1.0) / 2.0;
|
||||
input.AddContour(CreateCircle(r, (int)(r / h), 2), 2);
|
||||
|
||||
//count = input.Count;
|
||||
|
||||
// Outer cirlce
|
||||
r = radius;
|
||||
input.AddContour(CreateCircle(r, (int)(r / h), 3), 3);
|
||||
|
||||
// Regions: |++++++|++++++|---|
|
||||
// r 1 0
|
||||
|
||||
input.Regions.Add(new RegionPointer((r + 3.0) / 4.0, 0, 1));
|
||||
input.Regions.Add(new RegionPointer((3 * r + 1.0) / 4.0, 0, 2));
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="IGenerator.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for generating input geometries.
|
||||
/// </summary>
|
||||
public interface IGenerator
|
||||
{
|
||||
string Name { get; }
|
||||
string Description { get; }
|
||||
int ParameterCount { get; }
|
||||
string ParameterDescription(int paramIndex);
|
||||
string ParameterDescription(int paramIndex, double paramValue);
|
||||
IPolygon Generate(double param1, double param2, double param3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="RandomPoints.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Simple random points generator.
|
||||
/// </summary>
|
||||
public class RandomPoints : BaseGenerator
|
||||
{
|
||||
public RandomPoints()
|
||||
{
|
||||
name = "Random Points";
|
||||
description = "";
|
||||
parameter = 3;
|
||||
|
||||
descriptions[0] = "Number of points:";
|
||||
descriptions[1] = "Width:";
|
||||
descriptions[2] = "Height:";
|
||||
|
||||
ranges[0] = new int[] { 10, 5000 };
|
||||
ranges[1] = new int[] { 10, 200 };
|
||||
ranges[2] = new int[] { 10, 200 };
|
||||
}
|
||||
|
||||
public override IPolygon Generate(double param0, double param1, double param2)
|
||||
{
|
||||
int numPoints = GetParamValueInt(0, param0);
|
||||
numPoints = (numPoints / 10) * 10;
|
||||
|
||||
if (numPoints < ranges[0][0])
|
||||
{
|
||||
numPoints = ranges[0][0];
|
||||
}
|
||||
|
||||
var input = new Polygon(numPoints);
|
||||
|
||||
int width = GetParamValueInt(1, param1);
|
||||
int height = GetParamValueInt(2, param2);
|
||||
|
||||
for (int i = 0; i < numPoints; i++)
|
||||
{
|
||||
input.Add(new Vertex(Util.Random.NextDouble() * width,
|
||||
Util.Random.NextDouble() * height));
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="RandomPointsCircle.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Simple random points generator (points distributed in a circle).
|
||||
/// </summary>
|
||||
public class RandomPointsCircle : BaseGenerator
|
||||
{
|
||||
public RandomPointsCircle()
|
||||
{
|
||||
name = "Random Points (Circle)";
|
||||
description = "";
|
||||
parameter = 2;
|
||||
|
||||
descriptions[0] = "Number of points:";
|
||||
descriptions[1] = "Distribution:";
|
||||
|
||||
ranges[0] = new int[] { 5, 5000 };
|
||||
ranges[1] = new int[] { 0, 1 };
|
||||
}
|
||||
|
||||
public override string ParameterDescription(int paramIndex, double paramValue)
|
||||
{
|
||||
if (paramIndex == 0)
|
||||
{
|
||||
int numPoints = GetParamValueInt(paramIndex, paramValue);
|
||||
numPoints = (numPoints / 10) * 10;
|
||||
|
||||
if (numPoints < 5)
|
||||
{
|
||||
numPoints = 5;
|
||||
}
|
||||
|
||||
return numPoints.ToString();
|
||||
}
|
||||
|
||||
if (paramIndex == 1)
|
||||
{
|
||||
double exp = (paramValue + 10) / 100;
|
||||
|
||||
if (exp > 1.092)
|
||||
{
|
||||
exp = 1.1;
|
||||
}
|
||||
|
||||
return exp.ToString("0.00", Util.Nfi);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public override IPolygon Generate(double param0, double param1, double param2)
|
||||
{
|
||||
int numPoints = GetParamValueInt(0, param0);
|
||||
numPoints = (numPoints / 10) * 10;
|
||||
|
||||
if (numPoints < 5)
|
||||
{
|
||||
numPoints = 5;
|
||||
}
|
||||
|
||||
double exp = (param1 + 10) / 100;
|
||||
|
||||
var input = new Polygon(numPoints);
|
||||
|
||||
int i = 0, cNum = 2 * (int)Math.Floor(Math.Sqrt(numPoints));
|
||||
|
||||
double r, phi, radius = 100, step = 2 * Math.PI / cNum;
|
||||
|
||||
// Distrubute points equally on circle border
|
||||
for (; i < cNum; i++)
|
||||
{
|
||||
// Add a little error
|
||||
r = Util.Random.NextDouble();
|
||||
|
||||
input.Add(new Vertex((radius + r) * Math.Cos(i * step),
|
||||
(radius + r) * Math.Sin(i * step)));
|
||||
}
|
||||
|
||||
for (; i < numPoints; i++)
|
||||
{
|
||||
// Use sqrt(rand) to get normal distribution right.
|
||||
r = Math.Pow(Util.Random.NextDouble(), exp) * radius;
|
||||
phi = Util.Random.NextDouble() * Math.PI * 2;
|
||||
|
||||
input.Add(new Vertex(r * Math.Cos(phi), r * Math.Sin(phi)));
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="RingPolygon.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Generates a ring polygon.
|
||||
/// </summary>
|
||||
public class RingPolygon : BaseGenerator
|
||||
{
|
||||
public RingPolygon()
|
||||
{
|
||||
name = "Ring";
|
||||
description = "";
|
||||
parameter = 2;
|
||||
|
||||
descriptions[0] = "Number of points:";
|
||||
descriptions[1] = "Variation:";
|
||||
|
||||
ranges[0] = new int[] { 50, 250 };
|
||||
ranges[1] = new int[] { 0, 1 };
|
||||
}
|
||||
|
||||
public override string ParameterDescription(int paramIndex, double paramValue)
|
||||
{
|
||||
if (paramIndex == 0)
|
||||
{
|
||||
int numRays = GetParamValueInt(paramIndex, paramValue);
|
||||
return numRays.ToString();
|
||||
}
|
||||
|
||||
if (paramIndex == 1)
|
||||
{
|
||||
double variation = GetParamValueDouble(paramIndex, paramValue);
|
||||
return variation.ToString("0.0", Util.Nfi);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public override IPolygon Generate(double param0, double param1, double param2)
|
||||
{
|
||||
int n = GetParamValueInt(0, param0);
|
||||
int m = n / 2;
|
||||
|
||||
var input = new Polygon(n + 1);
|
||||
|
||||
double ro, r = 10;
|
||||
double step = 2 * Math.PI / m;
|
||||
|
||||
var inner = new List<Vertex>(m);
|
||||
|
||||
// Inner ring
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
inner.Add(new Vertex(r * Math.Cos(i * step), r * Math.Sin(i * step)));
|
||||
}
|
||||
|
||||
input.AddContour(inner, 1);
|
||||
|
||||
r = 1.5 * r;
|
||||
|
||||
var outer = new List<Vertex>(n);
|
||||
|
||||
step = 2 * Math.PI / n;
|
||||
double offset = step / 2;
|
||||
|
||||
// Outer ring
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
ro = r;
|
||||
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
ro = r + r * Util.Random.NextDouble() * (param1 / 100);
|
||||
}
|
||||
|
||||
outer.Add(new Vertex(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset)));
|
||||
}
|
||||
|
||||
input.AddContour(outer, 2);
|
||||
|
||||
input.Holes.Add(new Point(0, 0));
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="StarInBox.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Generators
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Generates a star contained in a box.
|
||||
/// </summary>
|
||||
public class StarInBox : BaseGenerator
|
||||
{
|
||||
public StarInBox()
|
||||
{
|
||||
name = "Star in Box";
|
||||
description = "";
|
||||
parameter = 1;
|
||||
|
||||
descriptions[0] = "Number of rays:";
|
||||
|
||||
ranges[0] = new int[] { 3, 61 };
|
||||
}
|
||||
|
||||
public override IPolygon Generate(double param0, double param1, double param2)
|
||||
{
|
||||
int numRays = GetParamValueInt(0, param0);
|
||||
|
||||
var g = new Polygon(numRays + 4);
|
||||
|
||||
g.Add(new Vertex(0, 0)); // Center
|
||||
|
||||
double x, y, r, e, step = 2 * Math.PI / numRays;
|
||||
|
||||
for (int i = 0; i < numRays; i++)
|
||||
{
|
||||
e = Util.Random.NextDouble() * step * 0.7;
|
||||
r = (Util.Random.NextDouble() + 0.7) * 0.5;
|
||||
x = r * Math.Cos(i * step + e);
|
||||
y = r * Math.Sin(i * step + e);
|
||||
|
||||
g.Add(new Vertex(x, y, 2));
|
||||
g.Add(new Segment(g.Points[0], g.Points[i + 1], 2));
|
||||
}
|
||||
|
||||
g.Add(new Vertex(-1, -1, 1)); // Box
|
||||
g.Add(new Vertex(1, -1, 1));
|
||||
g.Add(new Vertex(1, 1, 1));
|
||||
g.Add(new Vertex(-1, 1, 1));
|
||||
|
||||
numRays = g.Count;
|
||||
g.Add(new Segment(g.Points[numRays - 1], g.Points[numRays - 2], 1));
|
||||
g.Add(new Segment(g.Points[numRays - 2], g.Points[numRays - 3], 1));
|
||||
g.Add(new Segment(g.Points[numRays - 3], g.Points[numRays - 4], 1));
|
||||
g.Add(new Segment(g.Points[numRays - 4], g.Points[numRays - 1], 1));
|
||||
|
||||
return g;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
public class GenericEventArgs<T> : EventArgs
|
||||
{
|
||||
T argument;
|
||||
|
||||
public T Argument
|
||||
{
|
||||
get { return argument; }
|
||||
}
|
||||
|
||||
public GenericEventArgs(T arg)
|
||||
{
|
||||
argument = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="FileProcessor.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MeshExplorer.IO.Formats;
|
||||
using TriangleNet.IO;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet;
|
||||
|
||||
/// <summary>
|
||||
/// Provides static methods to read and write mesh files.
|
||||
/// </summary>
|
||||
public static class FileProcessor
|
||||
{
|
||||
static Dictionary<string, IMeshFile> container = new Dictionary<string, IMeshFile>();
|
||||
|
||||
public static bool CanHandleFile(string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var provider = GetProviderInstance(path);
|
||||
|
||||
if (provider != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true, if the given file contains mesh information.
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ContainsMeshData(string path)
|
||||
{
|
||||
IMeshFile provider = GetProviderInstance(path);
|
||||
|
||||
return provider.ContainsMeshData(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an input geometry from given file.
|
||||
/// </summary>
|
||||
public static IPolygon Read(string path)
|
||||
{
|
||||
var provider = GetProviderInstance(path);
|
||||
|
||||
return provider.Read(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a mesh from given file.
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static Mesh Import(string path)
|
||||
{
|
||||
var provider = GetProviderInstance(path);
|
||||
|
||||
return (Mesh)provider.Import(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the current mesh to given file.
|
||||
/// </summary>
|
||||
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);
|
||||
|
||||
IMeshFile provider = null;
|
||||
|
||||
if (container.ContainsKey(ext))
|
||||
{
|
||||
provider = container[ext];
|
||||
}
|
||||
else
|
||||
{
|
||||
provider = CreateProviderInstance(ext);
|
||||
}
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
private static IMeshFile CreateProviderInstance(string ext)
|
||||
{
|
||||
// TODO: automate by using IMeshFormat's Extensions property.
|
||||
|
||||
IMeshFile provider = null;
|
||||
|
||||
if (ext == ".node" || ext == ".poly" || ext == ".ele")
|
||||
{
|
||||
provider = new TriangleFile();
|
||||
}
|
||||
else if (ext == ".json")
|
||||
{
|
||||
provider = new JsonFile();
|
||||
}
|
||||
|
||||
if (provider == null)
|
||||
{
|
||||
throw new NotImplementedException("File format not implemented.");
|
||||
}
|
||||
|
||||
container.Add(ext, provider);
|
||||
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,574 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="JsonFile.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO.Formats
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Topology;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.IO;
|
||||
using TriangleNet.Meshing;
|
||||
|
||||
/// <summary>
|
||||
/// Read and write JSON files.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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": [ ... ]
|
||||
/// }
|
||||
/// }
|
||||
/// </remarks>
|
||||
public class JsonFile : IMeshFile
|
||||
{
|
||||
string file;
|
||||
Dictionary<string, object> json;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported file extensions.
|
||||
/// </summary>
|
||||
public string[] Extensions
|
||||
{
|
||||
get { return new string[] { ".json" }; }
|
||||
}
|
||||
|
||||
public bool ContainsMeshData(string filename)
|
||||
{
|
||||
ParseJson(filename);
|
||||
|
||||
if (this.json.ContainsKey("config"))
|
||||
{
|
||||
var config = this.json["config"] as Dictionary<string, object>;
|
||||
|
||||
if (config != null && config.ContainsKey("type"))
|
||||
{
|
||||
return config["type"].ToString() == "mesh";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsSupported(string file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IMesh Import(string filename)
|
||||
{
|
||||
var geometry = (Polygon)this.Read(filename);
|
||||
|
||||
List<ITriangle> triangles = null;
|
||||
|
||||
if (this.json.ContainsKey("triangles"))
|
||||
{
|
||||
var tri = this.json["triangles"] as Dictionary<string, object>;
|
||||
|
||||
if (tri != null)
|
||||
{
|
||||
triangles = ReadTriangles(tri, geometry.Points.Count);
|
||||
}
|
||||
}
|
||||
|
||||
return Converter.ToMesh(geometry, triangles);
|
||||
}
|
||||
|
||||
public void Write(IMesh mesh, string filename)
|
||||
{
|
||||
using (StreamWriter writer = new StreamWriter(filename))
|
||||
{
|
||||
int nv = mesh.Vertices.Count;
|
||||
int ns = mesh.Segments.Count;
|
||||
int nh = mesh.Holes.Count;
|
||||
int ne = mesh.Triangles.Count;
|
||||
|
||||
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("}");
|
||||
|
||||
if (((Mesh)mesh).CurrentNumbering == NodeNumbering.None)
|
||||
{
|
||||
((Mesh)mesh).Renumber(NodeNumbering.Linear);
|
||||
}
|
||||
|
||||
// Write the coordinates
|
||||
if (nv > 0)
|
||||
{
|
||||
writer.Write(",");
|
||||
WritePoints((Mesh)mesh, writer, nv);
|
||||
}
|
||||
|
||||
// Write the segments
|
||||
if (ns > 0)
|
||||
{
|
||||
writer.Write(",");
|
||||
WriteSegments(mesh.Segments, writer, ns);
|
||||
}
|
||||
|
||||
// Write the holes
|
||||
if (nh > 0)
|
||||
{
|
||||
writer.Write(",");
|
||||
WriteHoles(mesh.Holes, writer, nh);
|
||||
}
|
||||
|
||||
// Write the elements
|
||||
if (ne > 0)
|
||||
{
|
||||
writer.Write(",");
|
||||
WriteTriangles(mesh.Triangles, writer, ne);
|
||||
}
|
||||
|
||||
writer.Write("}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(IMesh mesh, Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
public IPolygon Read(string filename)
|
||||
{
|
||||
ParseJson(filename);
|
||||
|
||||
var data = new Polygon();
|
||||
|
||||
if (json == null)
|
||||
{
|
||||
// TODO: Exception?
|
||||
return data;
|
||||
}
|
||||
|
||||
if (json.ContainsKey("config"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
if (json.ContainsKey("points"))
|
||||
{
|
||||
var points = json["points"] as Dictionary<string, object>;
|
||||
|
||||
if (points != null)
|
||||
{
|
||||
ReadPoints(data, points, ref count);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Exception?
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
if (json.ContainsKey("segments"))
|
||||
{
|
||||
var segments = json["segments"] as Dictionary<string, object>;
|
||||
|
||||
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(IPolygon polygon, string filename)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Write(IPolygon polygon, Stream stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void ParseJson(string filename)
|
||||
{
|
||||
if (this.json == null || this.file != filename)
|
||||
{
|
||||
this.file = filename;
|
||||
|
||||
string content = File.ReadAllText(filename);
|
||||
|
||||
JsonParser parser = new JsonParser(content);
|
||||
this.json = parser.Decode() as Dictionary<string, object>;
|
||||
}
|
||||
}
|
||||
|
||||
#region Read helpers
|
||||
|
||||
private void ReadPoints(Polygon geometry, Dictionary<string, object> 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.Add(new Vertex(
|
||||
double.Parse(data[i].ToString(), Util.Nfi),
|
||||
double.Parse(data[i + 1].ToString(), Util.Nfi),
|
||||
mark
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadSegments(Polygon geometry, Dictionary<string, object> 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;
|
||||
|
||||
throw new NotImplementedException();
|
||||
// TODO: Fix JSON format
|
||||
|
||||
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.Add(new Edge(p0, p1, mark));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadHoles(Polygon 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.Holes.Add(new Point(
|
||||
double.Parse(holes[i].ToString(), Util.Nfi),
|
||||
double.Parse(holes[i + 1].ToString(), Util.Nfi)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ITriangle> ReadTriangles(Dictionary<string, object> 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<ITriangle> output = null;
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
int n = data.Count;
|
||||
|
||||
if (n % 3 != 0)
|
||||
{
|
||||
throw new Exception("JSON format error (triangles).");
|
||||
}
|
||||
|
||||
output = new List<ITriangle>(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 mesh, StreamWriter writer, int nv)
|
||||
{
|
||||
bool useMarkers = false;
|
||||
|
||||
StringBuilder markers;
|
||||
|
||||
writer.Write("\"points\":{\"data\":[");
|
||||
|
||||
if (mesh.CurrentNumbering == NodeNumbering.Linear)
|
||||
{
|
||||
markers = WritePoints(mesh.Vertices, writer, nv, useMarkers);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vertex[] nodes = new Vertex[mesh.Vertices.Count];
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
nodes[node.ID] = node;
|
||||
}
|
||||
|
||||
markers = WritePoints(nodes, writer, nv, useMarkers);
|
||||
}
|
||||
|
||||
writer.Write("]");
|
||||
if (useMarkers)
|
||||
{
|
||||
writer.Write(",\"markers\":[" + markers.ToString() + "]");
|
||||
}
|
||||
|
||||
// TODO: writer.Write(",\"attributes\":[]");
|
||||
writer.Write("}");
|
||||
}
|
||||
|
||||
private static StringBuilder WritePoints(IEnumerable<Point> data, StreamWriter writer, int nv, bool useMarkers)
|
||||
{
|
||||
StringBuilder markers = new StringBuilder();
|
||||
|
||||
int i = 0;
|
||||
string seperator;
|
||||
foreach (var item in data)
|
||||
{
|
||||
seperator = (i == nv - 1) ? String.Empty : ", ";
|
||||
|
||||
writer.Write("{0},{1}{2}",
|
||||
item.X.ToString(Util.Nfi),
|
||||
item.Y.ToString(Util.Nfi), seperator);
|
||||
|
||||
if (item.Label > 0)
|
||||
{
|
||||
useMarkers = true;
|
||||
}
|
||||
|
||||
markers.AppendFormat("{0}{1}", item.Label, seperator);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return markers;
|
||||
}
|
||||
|
||||
private void WriteHoles(IEnumerable<Point> data, StreamWriter writer, int nh)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
writer.Write("\"holes\":[");
|
||||
foreach (var item in data)
|
||||
{
|
||||
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(IEnumerable<SubSegment> 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)
|
||||
{
|
||||
seperator = (i == ns - 1) ? String.Empty : ", ";
|
||||
|
||||
writer.Write("{0},{1}{2}",
|
||||
item.P0, item.P1, seperator);
|
||||
|
||||
if (item.Label > 0)
|
||||
{
|
||||
useMarkers = true;
|
||||
}
|
||||
|
||||
markers.AppendFormat("{0}{1}", item.Label, seperator);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
writer.Write("]");
|
||||
|
||||
if (useMarkers)
|
||||
{
|
||||
writer.Write(",\"markers\":[" + markers.ToString() + "]");
|
||||
}
|
||||
|
||||
writer.Write("}");
|
||||
}
|
||||
|
||||
private void WriteTriangles(IEnumerable<Triangle> data, StreamWriter writer, int ne)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
StringBuilder neighbors = new StringBuilder();
|
||||
|
||||
string seperator;
|
||||
|
||||
writer.Write("\"triangles\":{\"data\":[");
|
||||
foreach (var item in data)
|
||||
{
|
||||
seperator = (i == ne - 1) ? String.Empty : ", ";
|
||||
|
||||
writer.Write("{0},{1},{2}{3}",
|
||||
item.GetVertexID(0),
|
||||
item.GetVertexID(1),
|
||||
item.GetVertexID(2),
|
||||
seperator);
|
||||
|
||||
neighbors.AppendFormat("{0},{1},{2}{3}",
|
||||
item.GetNeighborID(0),
|
||||
item.GetNeighborID(1),
|
||||
item.GetNeighborID(2),
|
||||
seperator);
|
||||
|
||||
i++;
|
||||
}
|
||||
writer.Write("]");
|
||||
writer.Write(",\"neighbors\":[" + neighbors.ToString() + "]");
|
||||
writer.Write("}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="TriangleFile.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO.Formats
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.IO;
|
||||
using TriangleNet.Meshing;
|
||||
|
||||
/// <summary>
|
||||
/// Read and write files defined in classic Triangle format.
|
||||
/// </summary>
|
||||
public class TriangleFile : IMeshFile
|
||||
{
|
||||
TriangleFormat format = new TriangleFormat();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the supported file extensions.
|
||||
/// </summary>
|
||||
public string[] Extensions
|
||||
{
|
||||
get { return new string[] { ".node", ".poly", ".ele" }; }
|
||||
}
|
||||
|
||||
public bool ContainsMeshData(string filename)
|
||||
{
|
||||
string ext = Path.GetExtension(filename);
|
||||
|
||||
if (ext == ".node" || ext == ".poly")
|
||||
{
|
||||
if (File.Exists(Path.ChangeExtension(filename, ".ele")))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (ext == ".ele");
|
||||
}
|
||||
|
||||
public bool IsSupported(string file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IPolygon Read(string filename)
|
||||
{
|
||||
return format.Read(filename);
|
||||
}
|
||||
|
||||
public void Write(IPolygon polygon, string filename)
|
||||
{
|
||||
format.Write(polygon, filename);
|
||||
}
|
||||
|
||||
public void Write(IPolygon polygon, Stream stream)
|
||||
{
|
||||
format.Write(polygon, stream);
|
||||
}
|
||||
|
||||
public IMesh Import(string filename)
|
||||
{
|
||||
return format.Import(filename);
|
||||
}
|
||||
|
||||
public void Write(IMesh mesh, string filename)
|
||||
{
|
||||
if (mesh.Vertices.Count > 0)
|
||||
{
|
||||
format.Write(mesh, filename);
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(IMesh mesh, Stream stream)
|
||||
{
|
||||
format.Write(mesh, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="IMeshFile.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TriangleNet;
|
||||
using TriangleNet.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Defines an interface for mesh file formats.
|
||||
/// </summary>
|
||||
public interface IMeshFile : IPolygonFormat, IMeshFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported file extensions.
|
||||
/// </summary>
|
||||
string[] Extensions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true, if a (previously saved) mesh is associated with the given file.
|
||||
/// </summary>
|
||||
/// <param name="filename">The file name.</param>
|
||||
/// <returns>True, if a mesh is associated with the given file.</returns>
|
||||
bool ContainsMeshData(string filename);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="RasterImage.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Rendering.GDI;
|
||||
using TriangleNet.Rendering.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Writes an image of the mesh to disk.
|
||||
/// </summary>
|
||||
public class ImageWriter
|
||||
{
|
||||
/// <summary>
|
||||
/// Export the mesh to PNG format.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The current mesh.</param>
|
||||
/// <param name="filename">The PNG filename.</param>
|
||||
/// <param name="type">Image type (0 = png, 1 = eps, 2 = svg).</param>
|
||||
/// <param name="width">The desired width of the image.</param>
|
||||
/// <param name="compress">Use GZip compression (only eps or svg).</param>
|
||||
public void Export(Mesh mesh, string filename, int type, int width, bool compress)
|
||||
{
|
||||
if (type == 1)
|
||||
{
|
||||
ExportEps(mesh, filename, width, compress);
|
||||
}
|
||||
else if (type == 2)
|
||||
{
|
||||
ExportSvg(mesh, filename, width, compress);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImageRenderer.Save(mesh, filename, width);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportEps(Mesh mesh, string filename, int width, bool compress)
|
||||
{
|
||||
var eps = new EpsImage();
|
||||
|
||||
eps.Export(mesh, filename, width);
|
||||
|
||||
if (compress)
|
||||
{
|
||||
CompressFile(filename, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportSvg(Mesh mesh, string filename, int width, bool compress)
|
||||
{
|
||||
var svg = new SvgImage();
|
||||
|
||||
svg.Export(mesh, filename, width);
|
||||
|
||||
if (compress)
|
||||
{
|
||||
CompressFile(filename, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void CompressFile(string filename, bool cleanup)
|
||||
{
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var input = File.OpenRead(filename))
|
||||
using (var output = File.Create(filename + ".gz"))
|
||||
using (var gzip = new GZipStream(output, CompressionMode.Compress))
|
||||
{
|
||||
input.CopyTo(gzip);
|
||||
}
|
||||
|
||||
if (cleanup)
|
||||
{
|
||||
File.Delete(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="JsonParser.cs" company="">
|
||||
// fastJSON - http://fastjson.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// This class encodes and decodes JSON strings.
|
||||
/// Spec. details, see http://www.json.org/
|
||||
///
|
||||
/// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
|
||||
/// All numbers are parsed to doubles.
|
||||
/// </summary>
|
||||
internal class JsonParser
|
||||
{
|
||||
enum Token
|
||||
{
|
||||
None = -1, // Used to denote no Lookahead available
|
||||
Curly_Open,
|
||||
Curly_Close,
|
||||
Squared_Open,
|
||||
Squared_Close,
|
||||
Colon,
|
||||
Comma,
|
||||
String,
|
||||
Number,
|
||||
True,
|
||||
False,
|
||||
Null
|
||||
}
|
||||
|
||||
readonly char[] json;
|
||||
readonly StringBuilder s = new StringBuilder();
|
||||
Token lookAheadToken = Token.None;
|
||||
int index;
|
||||
|
||||
public JsonParser(string json)
|
||||
{
|
||||
this.json = json.ToCharArray();
|
||||
}
|
||||
|
||||
public object Decode()
|
||||
{
|
||||
return ParseValue();
|
||||
}
|
||||
|
||||
private Dictionary<string, object> ParseObject()
|
||||
{
|
||||
Dictionary<string, object> table = new Dictionary<string, object>();
|
||||
|
||||
ConsumeToken(); // {
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (LookAhead())
|
||||
{
|
||||
|
||||
case Token.Comma:
|
||||
ConsumeToken();
|
||||
break;
|
||||
|
||||
case Token.Curly_Close:
|
||||
ConsumeToken();
|
||||
return table;
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
// name
|
||||
string name = ParseString();
|
||||
|
||||
// :
|
||||
if (NextToken() != Token.Colon)
|
||||
{
|
||||
throw new Exception("Expected colon at index " + index);
|
||||
}
|
||||
|
||||
// value
|
||||
object value = ParseValue();
|
||||
|
||||
table[name] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList ParseArray()
|
||||
{
|
||||
ArrayList array = new ArrayList();
|
||||
|
||||
ConsumeToken(); // [
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (LookAhead())
|
||||
{
|
||||
|
||||
case Token.Comma:
|
||||
ConsumeToken();
|
||||
break;
|
||||
|
||||
case Token.Squared_Close:
|
||||
ConsumeToken();
|
||||
return array;
|
||||
|
||||
default:
|
||||
{
|
||||
array.Add(ParseValue());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object ParseValue()
|
||||
{
|
||||
switch (LookAhead())
|
||||
{
|
||||
case Token.Number:
|
||||
return ParseNumber();
|
||||
|
||||
case Token.String:
|
||||
return ParseString();
|
||||
|
||||
case Token.Curly_Open:
|
||||
return ParseObject();
|
||||
|
||||
case Token.Squared_Open:
|
||||
return ParseArray();
|
||||
|
||||
case Token.True:
|
||||
ConsumeToken();
|
||||
return true;
|
||||
|
||||
case Token.False:
|
||||
ConsumeToken();
|
||||
return false;
|
||||
|
||||
case Token.Null:
|
||||
ConsumeToken();
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new Exception("Unrecognized token at index" + index);
|
||||
}
|
||||
|
||||
private string ParseString()
|
||||
{
|
||||
ConsumeToken(); // "
|
||||
|
||||
s.Length = 0;
|
||||
|
||||
int runIndex = -1;
|
||||
|
||||
while (index < json.Length)
|
||||
{
|
||||
var c = json[index++];
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
if (runIndex != -1)
|
||||
{
|
||||
if (s.Length == 0)
|
||||
return new string(json, runIndex, index - runIndex - 1);
|
||||
|
||||
s.Append(json, runIndex, index - runIndex - 1);
|
||||
}
|
||||
return s.ToString();
|
||||
}
|
||||
|
||||
if (c != '\\')
|
||||
{
|
||||
if (runIndex == -1)
|
||||
runIndex = index - 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index == json.Length) break;
|
||||
|
||||
if (runIndex != -1)
|
||||
{
|
||||
s.Append(json, runIndex, index - runIndex - 1);
|
||||
runIndex = -1;
|
||||
}
|
||||
|
||||
switch (json[index++])
|
||||
{
|
||||
case '"':
|
||||
s.Append('"');
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
s.Append('\\');
|
||||
break;
|
||||
|
||||
case '/':
|
||||
s.Append('/');
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
s.Append('\b');
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
s.Append('\f');
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
s.Append('\n');
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
s.Append('\r');
|
||||
break;
|
||||
|
||||
case 't':
|
||||
s.Append('\t');
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
{
|
||||
int remainingLength = json.Length - index;
|
||||
if (remainingLength < 4) break;
|
||||
|
||||
// parse the 32 bit hex into an integer codepoint
|
||||
uint codePoint = ParseUnicode(json[index], json[index + 1], json[index + 2], json[index + 3]);
|
||||
s.Append((char)codePoint);
|
||||
|
||||
// skip 4 chars
|
||||
index += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Unexpectedly reached end of string");
|
||||
}
|
||||
|
||||
private uint ParseSingleChar(char c1, uint multipliyer)
|
||||
{
|
||||
uint p1 = 0;
|
||||
if (c1 >= '0' && c1 <= '9')
|
||||
p1 = (uint)(c1 - '0') * multipliyer;
|
||||
else if (c1 >= 'A' && c1 <= 'F')
|
||||
p1 = (uint)((c1 - 'A') + 10) * multipliyer;
|
||||
else if (c1 >= 'a' && c1 <= 'f')
|
||||
p1 = (uint)((c1 - 'a') + 10) * multipliyer;
|
||||
return p1;
|
||||
}
|
||||
|
||||
private uint ParseUnicode(char c1, char c2, char c3, char c4)
|
||||
{
|
||||
uint p1 = ParseSingleChar(c1, 0x1000);
|
||||
uint p2 = ParseSingleChar(c2, 0x100);
|
||||
uint p3 = ParseSingleChar(c3, 0x10);
|
||||
uint p4 = ParseSingleChar(c4, 1);
|
||||
|
||||
return p1 + p2 + p3 + p4;
|
||||
}
|
||||
|
||||
private string ParseNumber()
|
||||
{
|
||||
ConsumeToken();
|
||||
|
||||
// Need to start back one place because the first digit is also a token and would have been consumed
|
||||
var startIndex = index - 1;
|
||||
|
||||
do
|
||||
{
|
||||
var c = json[index];
|
||||
|
||||
if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E')
|
||||
{
|
||||
if (++index == json.Length) throw new Exception("Unexpected end of string whilst parsing number");
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
return new string(json, startIndex, index - startIndex);
|
||||
}
|
||||
|
||||
private Token LookAhead()
|
||||
{
|
||||
if (lookAheadToken != Token.None) return lookAheadToken;
|
||||
|
||||
return lookAheadToken = NextTokenCore();
|
||||
}
|
||||
|
||||
private void ConsumeToken()
|
||||
{
|
||||
lookAheadToken = Token.None;
|
||||
}
|
||||
|
||||
private Token NextToken()
|
||||
{
|
||||
var result = lookAheadToken != Token.None ? lookAheadToken : NextTokenCore();
|
||||
|
||||
lookAheadToken = Token.None;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Token NextTokenCore()
|
||||
{
|
||||
char c;
|
||||
|
||||
// Skip past whitespace
|
||||
do
|
||||
{
|
||||
c = json[index];
|
||||
|
||||
if (c > ' ') break;
|
||||
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;
|
||||
|
||||
} while (++index < json.Length);
|
||||
|
||||
if (index == json.Length)
|
||||
{
|
||||
throw new Exception("Reached end of string unexpectedly");
|
||||
}
|
||||
|
||||
c = json[index];
|
||||
|
||||
index++;
|
||||
|
||||
//if (c >= '0' && c <= '9')
|
||||
// return Token.Number;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '{':
|
||||
return Token.Curly_Open;
|
||||
|
||||
case '}':
|
||||
return Token.Curly_Close;
|
||||
|
||||
case '[':
|
||||
return Token.Squared_Open;
|
||||
|
||||
case ']':
|
||||
return Token.Squared_Close;
|
||||
|
||||
case ',':
|
||||
return Token.Comma;
|
||||
|
||||
case '"':
|
||||
return Token.String;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '-': case '+': case '.':
|
||||
return Token.Number;
|
||||
|
||||
case ':':
|
||||
return Token.Colon;
|
||||
|
||||
case 'f':
|
||||
if (json.Length - index >= 4 &&
|
||||
json[index + 0] == 'a' &&
|
||||
json[index + 1] == 'l' &&
|
||||
json[index + 2] == 's' &&
|
||||
json[index + 3] == 'e')
|
||||
{
|
||||
index += 4;
|
||||
return Token.False;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (json.Length - index >= 3 &&
|
||||
json[index + 0] == 'r' &&
|
||||
json[index + 1] == 'u' &&
|
||||
json[index + 2] == 'e')
|
||||
{
|
||||
index += 3;
|
||||
return Token.True;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (json.Length - index >= 3 &&
|
||||
json[index + 0] == 'u' &&
|
||||
json[index + 1] == 'l' &&
|
||||
json[index + 2] == 'l')
|
||||
{
|
||||
index += 3;
|
||||
return Token.Null;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
throw new Exception("Could not find token at index " + --index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{336AAF8A-5316-4303-9E73-5E38BD0B28AF}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>MeshExplorer</RootNamespace>
|
||||
<AssemblyName>Mesh Explorer</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Controls\ColorScheme.cs" />
|
||||
<Compile Include="Controls\DarkButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\DarkCheckBox.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\AngleHistogram.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\DarkListBox.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\DarkSlider.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\DarkTabControl.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\DarkTextBox.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\DarkToolStripRenderer.cs" />
|
||||
<Compile Include="DarkMessageBox.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormExport.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormExport.Designer.cs">
|
||||
<DependentUpon>FormExport.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="FormGenerator.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormGenerator.Designer.cs">
|
||||
<DependentUpon>FormGenerator.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="FormLog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormLog.Designer.cs">
|
||||
<DependentUpon>FormLog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="FormMain.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormMain.Designer.cs">
|
||||
<DependentUpon>FormMain.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="FormTopology.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormTopology.Designer.cs">
|
||||
<DependentUpon>FormTopology.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Generators\BaseGenerator.cs" />
|
||||
<Compile Include="Generators\BoxWithHole.cs" />
|
||||
<Compile Include="Generators\CircleWithHole.cs" />
|
||||
<Compile Include="Generators\IGenerator.cs" />
|
||||
<Compile Include="Generators\RandomPoints.cs" />
|
||||
<Compile Include="Generators\RandomPointsCircle.cs" />
|
||||
<Compile Include="Generators\RingPolygon.cs" />
|
||||
<Compile Include="Generators\StarInBox.cs" />
|
||||
<Compile Include="GenericEventArgs.cs" />
|
||||
<Compile Include="IO\FileProcessor.cs" />
|
||||
<Compile Include="IO\Formats\JsonFile.cs" />
|
||||
<Compile Include="IO\Formats\TriangleFile.cs" />
|
||||
<Compile Include="IO\ImageWriter.cs" />
|
||||
<Compile Include="IO\IMeshFile.cs" />
|
||||
<Compile Include="IO\JsonParser.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="Topology\TopologyControlView.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Topology\TopologyControlView.Designer.cs">
|
||||
<DependentUpon>TopologyControlView.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Topology\TopologyRenderControl.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Topology\TopologyRenderer.cs" />
|
||||
<Compile Include="Util.cs" />
|
||||
<Compile Include="Views\AboutView.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Views\AboutView.Designer.cs">
|
||||
<DependentUpon>AboutView.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\IView.cs" />
|
||||
<Compile Include="Views\MeshControlView.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Views\MeshControlView.Designer.cs">
|
||||
<DependentUpon>MeshControlView.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\StatisticView.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Views\StatisticView.Designer.cs">
|
||||
<DependentUpon>StatisticView.cs</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="FormExport.resx">
|
||||
<DependentUpon>FormExport.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="FormGenerator.resx">
|
||||
<DependentUpon>FormGenerator.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="FormLog.resx">
|
||||
<DependentUpon>FormLog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="FormMain.resx">
|
||||
<DependentUpon>FormMain.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="FormTopology.resx">
|
||||
<DependentUpon>FormTopology.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Topology\TopologyControlView.resx">
|
||||
<DependentUpon>TopologyControlView.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Views\AboutView.resx">
|
||||
<DependentUpon>AboutView.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Views\MeshControlView.resx">
|
||||
<DependentUpon>MeshControlView.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Views\StatisticView.resx">
|
||||
<DependentUpon>StatisticView.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Triangle.Rendering\Triangle.Rendering.csproj">
|
||||
<Project>{41022e0e-bd0f-439e-bc3a-aabb1b43471b}</Project>
|
||||
<Name>Triangle.Rendering</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Triangle\Triangle.csproj">
|
||||
<Project>{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}</Project>
|
||||
<Name>Triangle</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new FormMain());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Mesh Explorer")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Mesh Explorer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("7368d676-5415-47a5-b1a7-3d517e418b21")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,78 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Settings.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// Stores some of the data used in the main application.
|
||||
/// </summary>
|
||||
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.";
|
||||
|
||||
public static string VoronoiString = "Make sure you use the \"Confoming Delaunay\" option " +
|
||||
"when building the Voronoi diagram from a constrained mesh.";
|
||||
|
||||
// Open file dialog
|
||||
public string OfdDirectory { get; set; }
|
||||
public string OfdFilter { get; set; }
|
||||
public int OfdFilterIndex{ get; set; }
|
||||
|
||||
// Save file dialog
|
||||
public string SfdDirectory { get; set; }
|
||||
public string SfdFilter { get; set; }
|
||||
public int SfdFilterIndex { get; set; }
|
||||
|
||||
public string CurrentFile { get; set; }
|
||||
|
||||
public bool RefineMode { get; set; }
|
||||
public bool ExceptionThrown { get; set; }
|
||||
|
||||
public Settings()
|
||||
{
|
||||
if (Directory.Exists(@"..\..\..\Data\"))
|
||||
{
|
||||
OfdDirectory = Path.GetFullPath(@"..\..\..\Data\");
|
||||
}
|
||||
else if (Directory.Exists(@"Data\"))
|
||||
{
|
||||
OfdDirectory = Path.GetFullPath(@"Data\");
|
||||
}
|
||||
else
|
||||
{
|
||||
//System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
|
||||
OfdDirectory = Application.StartupPath;
|
||||
}
|
||||
|
||||
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";
|
||||
//OfdFilter += "|VTK data (*.vtk)|*.vtk";
|
||||
|
||||
OfdFilterIndex = 0;
|
||||
|
||||
CurrentFile = "";
|
||||
|
||||
RefineMode = false;
|
||||
ExceptionThrown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
namespace MeshExplorer.Topology
|
||||
{
|
||||
partial class TopologyControlView
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.lbS2 = new System.Windows.Forms.Label();
|
||||
this.lbS1 = new System.Windows.Forms.Label();
|
||||
this.lbS0 = new System.Windows.Forms.Label();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.lbN2 = new System.Windows.Forms.Label();
|
||||
this.lbN1 = new System.Windows.Forms.Label();
|
||||
this.lbN0 = new System.Windows.Forms.Label();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.lbPosition = new System.Windows.Forms.Label();
|
||||
this.lbV2 = new System.Windows.Forms.Label();
|
||||
this.lbV1 = new System.Windows.Forms.Label();
|
||||
this.lbV0 = new System.Windows.Forms.Label();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.lbTriangle = new System.Windows.Forms.Label();
|
||||
this.darkButton9 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton7 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton5 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton3 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton8 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton6 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton4 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton2 = new MeshExplorer.Controls.DarkButton();
|
||||
this.darkButton1 = new MeshExplorer.Controls.DarkButton();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lbS2
|
||||
//
|
||||
this.lbS2.Location = new System.Drawing.Point(137, 122);
|
||||
this.lbS2.Name = "lbS2";
|
||||
this.lbS2.Size = new System.Drawing.Size(53, 13);
|
||||
this.lbS2.TabIndex = 1;
|
||||
this.lbS2.Text = "-";
|
||||
this.lbS2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbS1
|
||||
//
|
||||
this.lbS1.Location = new System.Drawing.Point(137, 107);
|
||||
this.lbS1.Name = "lbS1";
|
||||
this.lbS1.Size = new System.Drawing.Size(53, 13);
|
||||
this.lbS1.TabIndex = 1;
|
||||
this.lbS1.Text = "-";
|
||||
this.lbS1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbS0
|
||||
//
|
||||
this.lbS0.Location = new System.Drawing.Point(137, 92);
|
||||
this.lbS0.Name = "lbS0";
|
||||
this.lbS0.Size = new System.Drawing.Size(53, 13);
|
||||
this.lbS0.TabIndex = 1;
|
||||
this.lbS0.Text = "-";
|
||||
this.lbS0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.label6.Location = new System.Drawing.Point(134, 71);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(57, 13);
|
||||
this.label6.TabIndex = 1;
|
||||
this.label6.Text = "Segments";
|
||||
//
|
||||
// lbN2
|
||||
//
|
||||
this.lbN2.Location = new System.Drawing.Point(66, 122);
|
||||
this.lbN2.Name = "lbN2";
|
||||
this.lbN2.Size = new System.Drawing.Size(57, 13);
|
||||
this.lbN2.TabIndex = 1;
|
||||
this.lbN2.Text = "-";
|
||||
this.lbN2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbN1
|
||||
//
|
||||
this.lbN1.Location = new System.Drawing.Point(66, 107);
|
||||
this.lbN1.Name = "lbN1";
|
||||
this.lbN1.Size = new System.Drawing.Size(57, 13);
|
||||
this.lbN1.TabIndex = 1;
|
||||
this.lbN1.Text = "-";
|
||||
this.lbN1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbN0
|
||||
//
|
||||
this.lbN0.Location = new System.Drawing.Point(66, 92);
|
||||
this.lbN0.Name = "lbN0";
|
||||
this.lbN0.Size = new System.Drawing.Size(57, 13);
|
||||
this.lbN0.TabIndex = 1;
|
||||
this.lbN0.Text = "-";
|
||||
this.lbN0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.label5.Location = new System.Drawing.Point(63, 71);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(61, 13);
|
||||
this.label5.TabIndex = 1;
|
||||
this.label5.Text = "Neighbors";
|
||||
//
|
||||
// lbPosition
|
||||
//
|
||||
this.lbPosition.AutoSize = true;
|
||||
this.lbPosition.Location = new System.Drawing.Point(70, 15);
|
||||
this.lbPosition.Name = "lbPosition";
|
||||
this.lbPosition.Size = new System.Drawing.Size(11, 13);
|
||||
this.lbPosition.TabIndex = 1;
|
||||
this.lbPosition.Text = "-";
|
||||
//
|
||||
// lbV2
|
||||
//
|
||||
this.lbV2.Location = new System.Drawing.Point(16, 122);
|
||||
this.lbV2.Name = "lbV2";
|
||||
this.lbV2.Size = new System.Drawing.Size(38, 13);
|
||||
this.lbV2.TabIndex = 1;
|
||||
this.lbV2.Text = "-";
|
||||
this.lbV2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbV1
|
||||
//
|
||||
this.lbV1.Location = new System.Drawing.Point(16, 107);
|
||||
this.lbV1.Name = "lbV1";
|
||||
this.lbV1.Size = new System.Drawing.Size(38, 13);
|
||||
this.lbV1.TabIndex = 1;
|
||||
this.lbV1.Text = "-";
|
||||
this.lbV1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbV0
|
||||
//
|
||||
this.lbV0.Location = new System.Drawing.Point(16, 92);
|
||||
this.lbV0.Name = "lbV0";
|
||||
this.lbV0.Size = new System.Drawing.Size(38, 13);
|
||||
this.lbV0.TabIndex = 1;
|
||||
this.lbV0.Text = "-";
|
||||
this.lbV0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.label4.Location = new System.Drawing.Point(8, 71);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(47, 13);
|
||||
this.label4.TabIndex = 1;
|
||||
this.label4.Text = "Vertices";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(6, 15);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(52, 13);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Position:";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(7, 37);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(51, 13);
|
||||
this.label2.TabIndex = 1;
|
||||
this.label2.Text = "Triangle:";
|
||||
//
|
||||
// lbTriangle
|
||||
//
|
||||
this.lbTriangle.AutoSize = true;
|
||||
this.lbTriangle.Location = new System.Drawing.Point(70, 37);
|
||||
this.lbTriangle.Name = "lbTriangle";
|
||||
this.lbTriangle.Size = new System.Drawing.Size(11, 13);
|
||||
this.lbTriangle.TabIndex = 1;
|
||||
this.lbTriangle.Text = "-";
|
||||
//
|
||||
// darkButton9
|
||||
//
|
||||
this.darkButton9.Location = new System.Drawing.Point(99, 367);
|
||||
this.darkButton9.Name = "darkButton9";
|
||||
this.darkButton9.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton9.TabIndex = 10;
|
||||
this.darkButton9.Text = "Rprev";
|
||||
this.darkButton9.UseVisualStyleBackColor = true;
|
||||
this.darkButton9.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton7
|
||||
//
|
||||
this.darkButton7.Location = new System.Drawing.Point(99, 338);
|
||||
this.darkButton7.Name = "darkButton7";
|
||||
this.darkButton7.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton7.TabIndex = 8;
|
||||
this.darkButton7.Text = "Dprev";
|
||||
this.darkButton7.UseVisualStyleBackColor = true;
|
||||
this.darkButton7.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton5
|
||||
//
|
||||
this.darkButton5.Location = new System.Drawing.Point(99, 309);
|
||||
this.darkButton5.Name = "darkButton5";
|
||||
this.darkButton5.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton5.TabIndex = 6;
|
||||
this.darkButton5.Text = "Oprev";
|
||||
this.darkButton5.UseVisualStyleBackColor = true;
|
||||
this.darkButton5.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton3
|
||||
//
|
||||
this.darkButton3.Location = new System.Drawing.Point(99, 280);
|
||||
this.darkButton3.Name = "darkButton3";
|
||||
this.darkButton3.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton3.TabIndex = 4;
|
||||
this.darkButton3.Text = "Lprev";
|
||||
this.darkButton3.UseVisualStyleBackColor = true;
|
||||
this.darkButton3.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton8
|
||||
//
|
||||
this.darkButton8.Location = new System.Drawing.Point(11, 367);
|
||||
this.darkButton8.Name = "darkButton8";
|
||||
this.darkButton8.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton8.TabIndex = 9;
|
||||
this.darkButton8.Text = "Rnext";
|
||||
this.darkButton8.UseVisualStyleBackColor = true;
|
||||
this.darkButton8.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton6
|
||||
//
|
||||
this.darkButton6.Location = new System.Drawing.Point(11, 338);
|
||||
this.darkButton6.Name = "darkButton6";
|
||||
this.darkButton6.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton6.TabIndex = 7;
|
||||
this.darkButton6.Text = "Dnext";
|
||||
this.darkButton6.UseVisualStyleBackColor = true;
|
||||
this.darkButton6.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton4
|
||||
//
|
||||
this.darkButton4.Location = new System.Drawing.Point(11, 309);
|
||||
this.darkButton4.Name = "darkButton4";
|
||||
this.darkButton4.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton4.TabIndex = 5;
|
||||
this.darkButton4.Text = "Onext";
|
||||
this.darkButton4.UseVisualStyleBackColor = true;
|
||||
this.darkButton4.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton2
|
||||
//
|
||||
this.darkButton2.Location = new System.Drawing.Point(11, 280);
|
||||
this.darkButton2.Name = "darkButton2";
|
||||
this.darkButton2.Size = new System.Drawing.Size(78, 23);
|
||||
this.darkButton2.TabIndex = 3;
|
||||
this.darkButton2.Text = "Lnext";
|
||||
this.darkButton2.UseVisualStyleBackColor = true;
|
||||
this.darkButton2.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// darkButton1
|
||||
//
|
||||
this.darkButton1.Location = new System.Drawing.Point(11, 251);
|
||||
this.darkButton1.Name = "darkButton1";
|
||||
this.darkButton1.Size = new System.Drawing.Size(166, 23);
|
||||
this.darkButton1.TabIndex = 2;
|
||||
this.darkButton1.Text = "Sym";
|
||||
this.darkButton1.UseVisualStyleBackColor = true;
|
||||
this.darkButton1.Click += new System.EventHandler(this.btnPrimitive_Click);
|
||||
//
|
||||
// TopologyControlView
|
||||
//
|
||||
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.Controls.Add(this.darkButton9);
|
||||
this.Controls.Add(this.darkButton7);
|
||||
this.Controls.Add(this.darkButton5);
|
||||
this.Controls.Add(this.darkButton3);
|
||||
this.Controls.Add(this.darkButton8);
|
||||
this.Controls.Add(this.darkButton6);
|
||||
this.Controls.Add(this.darkButton4);
|
||||
this.Controls.Add(this.darkButton2);
|
||||
this.Controls.Add(this.darkButton1);
|
||||
this.Controls.Add(this.lbS2);
|
||||
this.Controls.Add(this.lbS1);
|
||||
this.Controls.Add(this.lbS0);
|
||||
this.Controls.Add(this.label6);
|
||||
this.Controls.Add(this.lbN2);
|
||||
this.Controls.Add(this.lbN1);
|
||||
this.Controls.Add(this.lbN0);
|
||||
this.Controls.Add(this.label5);
|
||||
this.Controls.Add(this.lbTriangle);
|
||||
this.Controls.Add(this.lbPosition);
|
||||
this.Controls.Add(this.lbV2);
|
||||
this.Controls.Add(this.lbV1);
|
||||
this.Controls.Add(this.lbV0);
|
||||
this.Controls.Add(this.label4);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.ForeColor = System.Drawing.Color.White;
|
||||
this.Name = "TopologyControlView";
|
||||
this.Size = new System.Drawing.Size(195, 439);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label lbS2;
|
||||
private System.Windows.Forms.Label lbS1;
|
||||
private System.Windows.Forms.Label lbS0;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.Label lbN2;
|
||||
private System.Windows.Forms.Label lbN1;
|
||||
private System.Windows.Forms.Label lbN0;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.Label lbPosition;
|
||||
private System.Windows.Forms.Label lbV2;
|
||||
private System.Windows.Forms.Label lbV1;
|
||||
private System.Windows.Forms.Label lbV0;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label lbTriangle;
|
||||
private Controls.DarkButton darkButton9;
|
||||
private Controls.DarkButton darkButton7;
|
||||
private Controls.DarkButton darkButton5;
|
||||
private Controls.DarkButton darkButton3;
|
||||
private Controls.DarkButton darkButton8;
|
||||
private Controls.DarkButton darkButton6;
|
||||
private Controls.DarkButton darkButton4;
|
||||
private Controls.DarkButton darkButton2;
|
||||
private Controls.DarkButton darkButton1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
namespace MeshExplorer.Topology
|
||||
{
|
||||
public partial class TopologyControlView : UserControl
|
||||
{
|
||||
public event EventHandler<GenericEventArgs<string>> PrimitiveCommandInvoked;
|
||||
|
||||
public TopologyControlView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SetPosition(PointF p)
|
||||
{
|
||||
var nfi = NumberFormatInfo.InvariantInfo;
|
||||
|
||||
lbPosition.Text = String.Format(nfi, "X: {0:0.0}, Y: {1:0.0}", p.X, p.Y);
|
||||
}
|
||||
|
||||
public void SetTriangle(ITriangle tri)
|
||||
{
|
||||
if (tri != null)
|
||||
{
|
||||
lbTriangle.Text = tri.ID.ToString();
|
||||
|
||||
lbV0.Text = tri.GetVertexID(0).ToString();
|
||||
lbV1.Text = tri.GetVertexID(1).ToString();
|
||||
lbV2.Text = tri.GetVertexID(2).ToString();
|
||||
|
||||
lbN0.Text = tri.GetNeighborID(0).ToString();
|
||||
lbN1.Text = tri.GetNeighborID(1).ToString();
|
||||
lbN2.Text = tri.GetNeighborID(2).ToString();
|
||||
|
||||
lbS0.Text = GetSegmentString(tri.GetSegment(0));
|
||||
lbS1.Text = GetSegmentString(tri.GetSegment(1));
|
||||
lbS2.Text = GetSegmentString(tri.GetSegment(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
lbTriangle.Text = "-";
|
||||
|
||||
lbV0.Text = "-";
|
||||
lbV1.Text = "-";
|
||||
lbV2.Text = "-";
|
||||
|
||||
lbN0.Text = "-";
|
||||
lbN1.Text = "-";
|
||||
lbN2.Text = "-";
|
||||
|
||||
lbS0.Text = "-";
|
||||
lbS1.Text = "-";
|
||||
lbS2.Text = "-";
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSegmentString(ISegment seg)
|
||||
{
|
||||
return seg == null ? "-" : "[" + seg.P0 + " - " + seg.P1 + "]";
|
||||
}
|
||||
|
||||
private void btnPrimitive_Click(object sender, EventArgs e)
|
||||
{
|
||||
var button = sender as Button;
|
||||
|
||||
if (button != null)
|
||||
{
|
||||
var name = button.Text.ToLowerInvariant();
|
||||
|
||||
var handler = PrimitiveCommandInvoked;
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new GenericEventArgs<string>(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,149 @@
|
||||
|
||||
namespace MeshExplorer.Topology
|
||||
{
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Text;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Rendering;
|
||||
using TriangleNet.Topology;
|
||||
|
||||
public class TopologyRenderControl : Control
|
||||
{
|
||||
// Rendering stuff
|
||||
private BufferedGraphics buffer;
|
||||
private BufferedGraphicsContext context;
|
||||
|
||||
Projection zoom;
|
||||
TopologyRenderer renderer;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
public Projection Zoom
|
||||
{
|
||||
get { return zoom; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RenderControl" /> class.
|
||||
/// </summary>
|
||||
public TopologyRenderControl()
|
||||
{
|
||||
SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
this.BackColor = Color.Black;
|
||||
|
||||
context = new BufferedGraphicsContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the graphics buffer (should be called in the forms load event).
|
||||
/// </summary>
|
||||
public void Initialize(Mesh mesh)
|
||||
{
|
||||
renderer = new TopologyRenderer(mesh);
|
||||
|
||||
zoom = new Projection(this.ClientRectangle);
|
||||
//zoom.ClipMargin = 10.0f;
|
||||
|
||||
var b = mesh.Bounds;
|
||||
zoom.Initialize(new BoundingBox((float)b.Left, (float)b.Right,
|
||||
(float)b.Bottom, (float)b.Top));
|
||||
|
||||
InitializeBuffer();
|
||||
|
||||
initialized = true;
|
||||
|
||||
this.Render();
|
||||
}
|
||||
|
||||
public void Update(Otri otri)
|
||||
{
|
||||
if (otri.Triangle == null || otri.Triangle.ID < 0)
|
||||
{
|
||||
renderer.SelectTriangle(null, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.SelectTriangle(otri.Triangle, otri.Org(), otri.Dest());
|
||||
}
|
||||
|
||||
this.Render();
|
||||
}
|
||||
|
||||
private void InitializeBuffer()
|
||||
{
|
||||
if (this.Width > 0 && this.Height > 0)
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
if (this.ClientRectangle == buffer.Graphics.VisibleClipBounds)
|
||||
{
|
||||
this.Invalidate();
|
||||
|
||||
// Bounds didn't change. Probably we just restored the window
|
||||
// from minimized state.
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.Dispose();
|
||||
}
|
||||
|
||||
buffer = context.Allocate(Graphics.FromHwnd(this.Handle), this.ClientRectangle);
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
this.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Graphics g = buffer.Graphics;
|
||||
g.Clear(this.BackColor);
|
||||
|
||||
if (!initialized || renderer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
||||
|
||||
renderer.Render(g, zoom);
|
||||
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
#region Control overrides
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
base.OnPaint(pe);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.Render();
|
||||
}
|
||||
|
||||
protected override void OnPaintBackground(PaintEventArgs pevent)
|
||||
{
|
||||
// Do nothing
|
||||
if (!initialized)
|
||||
{
|
||||
base.OnPaintBackground(pevent);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
|
||||
namespace MeshExplorer.Topology
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Rendering;
|
||||
|
||||
public class TopologyRenderer
|
||||
{
|
||||
Projection zoom;
|
||||
Mesh mesh;
|
||||
PointF[] points;
|
||||
|
||||
// Colors
|
||||
Color Background = Color.FromArgb(0, 0, 0);
|
||||
Brush Point = new SolidBrush(Color.FromArgb(0, 80, 0));
|
||||
Brush Triangle = new SolidBrush(Color.FromArgb(50, 50, 50));
|
||||
Pen Line = new Pen(Color.FromArgb(30, 30, 30));
|
||||
Pen Segment = new Pen(Color.DarkBlue);
|
||||
|
||||
Brush SelectedTriangle = new SolidBrush(Color.FromArgb(50, 0, 0));
|
||||
Pen SelectedEdge = new Pen(Color.DarkRed, 2.0f);
|
||||
|
||||
Font font, fontTri;
|
||||
|
||||
ITriangle currentTri;
|
||||
Vertex currentOrg, currentDest;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MeshRenderer" /> class.
|
||||
/// </summary>
|
||||
public TopologyRenderer(Mesh mesh)
|
||||
{
|
||||
this.mesh = mesh;
|
||||
|
||||
points = new PointF[mesh.Vertices.Count];
|
||||
|
||||
int k = 0;
|
||||
|
||||
foreach (var v in mesh.Vertices)
|
||||
{
|
||||
points[k++] = new PointF((float)v.X, (float)v.Y);
|
||||
}
|
||||
|
||||
font = new Font("Arial", 7.5f);
|
||||
fontTri = new Font("Arial", 12f, FontStyle.Bold);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the mesh.
|
||||
/// </summary>
|
||||
public void Render(Graphics g, Projection zoom)
|
||||
{
|
||||
this.zoom = zoom;
|
||||
|
||||
if (mesh.Edges != null)
|
||||
{
|
||||
this.RenderSelectedTriangle(g);
|
||||
this.RenderEdges(g);
|
||||
this.RenderTriangleIds(g);
|
||||
}
|
||||
else if (mesh.Triangles != null)
|
||||
{
|
||||
this.RenderTriangles(g);
|
||||
}
|
||||
|
||||
if (mesh.Segments != null)
|
||||
{
|
||||
this.RenderSegments(g);
|
||||
}
|
||||
|
||||
RenderSelectedEdge(g);
|
||||
|
||||
if (mesh.Vertices != null)
|
||||
{
|
||||
this.RenderPoints(g);
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectTriangle(ITriangle tri, Vertex org, Vertex dest)
|
||||
{
|
||||
currentTri = tri;
|
||||
currentOrg = org;
|
||||
currentDest = dest;
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private PointF GetIncenter(PointF p0, PointF p1, PointF p2)
|
||||
{
|
||||
double cx, cy, a, b, c,
|
||||
dax = p1.X - p0.X,
|
||||
dbx = p2.X - p1.X,
|
||||
dcx = p0.X - p2.X,
|
||||
day = p1.Y - p0.Y,
|
||||
dby = p2.Y - p1.Y,
|
||||
dcy = p0.Y - p2.Y;
|
||||
|
||||
a = Math.Sqrt(dax * dax + day * day);
|
||||
b = Math.Sqrt(dbx * dbx + dby * dby);
|
||||
c = Math.Sqrt(dcx * dcx + dcy * dcy);
|
||||
|
||||
cx = (a * p2.X + b * p0.X + c * p1.X) / (a + b + c);
|
||||
cy = (a * p2.Y + b * p0.Y + c * p1.Y) / (a + b + c);
|
||||
|
||||
return new PointF((float)cx, (float)cy);
|
||||
}
|
||||
|
||||
private PointF GetCentroid(PointF p0, PointF p1, PointF p2)
|
||||
{
|
||||
double cx, cy;
|
||||
|
||||
cx = (p0.X + p1.X + p2.X) / 3;
|
||||
cy = (p0.Y + p1.Y + p2.Y) / 3;
|
||||
|
||||
return new PointF((float)cx, (float)cy);
|
||||
}
|
||||
|
||||
private PointF GetPoint(ITriangle tri, int index)
|
||||
{
|
||||
var v = tri.GetVertex(index);
|
||||
|
||||
return new PointF((float)v.X, (float)v.Y);
|
||||
}
|
||||
|
||||
private PointF GetPoint(ISegment seg, int index)
|
||||
{
|
||||
var v = seg.GetVertex(index);
|
||||
|
||||
return new PointF((float)v.X, (float)v.Y);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void RenderPoints(Graphics g)
|
||||
{
|
||||
int n = points.Length;
|
||||
PointF pt;
|
||||
|
||||
int id = currentOrg != null ? currentOrg.ID : -1;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
var brush = i == id ? Brushes.DarkRed : Point;
|
||||
|
||||
pt = points[i];
|
||||
zoom.WorldToScreen(ref pt);
|
||||
g.FillEllipse(brush, pt.X - 10f, pt.Y - 10f, 20, 20);
|
||||
|
||||
pt.X -= i > 9 ? 7 : 4;
|
||||
pt.Y -= 6;
|
||||
g.DrawString(i.ToString(), font, Brushes.White, pt);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTriangles(Graphics g)
|
||||
{
|
||||
PointF p0, p1, p2, center;
|
||||
|
||||
var triangles = mesh.Triangles;
|
||||
|
||||
// Draw triangles
|
||||
foreach (var tri in triangles)
|
||||
{
|
||||
p0 = points[tri.GetVertexID(0)];
|
||||
p1 = points[tri.GetVertexID(1)];
|
||||
p2 = points[tri.GetVertexID(2)];
|
||||
|
||||
zoom.WorldToScreen(ref p0);
|
||||
zoom.WorldToScreen(ref p1);
|
||||
zoom.WorldToScreen(ref p2);
|
||||
|
||||
g.DrawLine(Line, p0, p1);
|
||||
g.DrawLine(Line, p1, p2);
|
||||
g.DrawLine(Line, p2, p0);
|
||||
|
||||
center = GetIncenter(p0, p1, p2);
|
||||
center.X -= 5;
|
||||
center.Y -= 5;
|
||||
|
||||
g.DrawString(tri.ID.ToString(), fontTri, Triangle, center);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderTriangleIds(Graphics g)
|
||||
{
|
||||
PointF p0, p1, p2, center;
|
||||
|
||||
var triangles = mesh.Triangles;
|
||||
|
||||
// Draw triangles
|
||||
foreach (var tri in triangles)
|
||||
{
|
||||
p0 = points[tri.GetVertexID(0)];
|
||||
p1 = points[tri.GetVertexID(1)];
|
||||
p2 = points[tri.GetVertexID(2)];
|
||||
|
||||
zoom.WorldToScreen(ref p0);
|
||||
zoom.WorldToScreen(ref p1);
|
||||
zoom.WorldToScreen(ref p2);
|
||||
|
||||
center = GetIncenter(p0, p1, p2);
|
||||
center.X -= 5;
|
||||
center.Y -= 5;
|
||||
|
||||
g.DrawString(tri.ID.ToString(), fontTri, Triangle, center);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderEdges(Graphics g)
|
||||
{
|
||||
PointF p0, p1;
|
||||
|
||||
var edges = mesh.Edges;
|
||||
|
||||
// Draw edges
|
||||
foreach (var edge in edges)
|
||||
{
|
||||
p0 = points[edge.P0];
|
||||
p1 = points[edge.P1];
|
||||
|
||||
zoom.WorldToScreen(ref p0);
|
||||
zoom.WorldToScreen(ref p1);
|
||||
|
||||
g.DrawLine(Line, p0, p1);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderSegments(Graphics g)
|
||||
{
|
||||
PointF p0, p1;
|
||||
|
||||
var segments = mesh.Segments;
|
||||
|
||||
foreach (var seg in segments)
|
||||
{
|
||||
p0 = points[seg.P0];
|
||||
p1 = points[seg.P1];
|
||||
|
||||
zoom.WorldToScreen(ref p0);
|
||||
zoom.WorldToScreen(ref p1);
|
||||
|
||||
g.DrawLine(Segment, p0, p1);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderSelectedEdge(Graphics g)
|
||||
{
|
||||
if (currentTri != null)
|
||||
{
|
||||
PointF p0, p1;
|
||||
|
||||
p0 = points[currentOrg.ID];
|
||||
p1 = points[currentDest.ID];
|
||||
|
||||
zoom.WorldToScreen(ref p0);
|
||||
zoom.WorldToScreen(ref p1);
|
||||
|
||||
g.DrawLine(SelectedEdge, p0, p1);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderSelectedTriangle(Graphics g)
|
||||
{
|
||||
if (currentTri != null)
|
||||
{
|
||||
var p = new PointF[3];
|
||||
|
||||
p[0] = points[currentTri.GetVertexID(0)];
|
||||
p[1] = points[currentTri.GetVertexID(1)];
|
||||
p[2] = points[currentTri.GetVertexID(2)];
|
||||
|
||||
zoom.WorldToScreen(ref p[0]);
|
||||
zoom.WorldToScreen(ref p[1]);
|
||||
zoom.WorldToScreen(ref p[2]);
|
||||
|
||||
g.FillPolygon(SelectedTriangle, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Util.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Utility class.
|
||||
/// </summary>
|
||||
public static class Util
|
||||
{
|
||||
internal static NumberFormatInfo Nfi = CultureInfo.InvariantCulture.NumberFormat;
|
||||
|
||||
internal static Random Random = new Random(DateTime.Now.Millisecond);
|
||||
|
||||
internal static bool TryReadLine(StreamReader reader, out string[] token)
|
||||
{
|
||||
token = null;
|
||||
|
||||
if (reader.EndOfStream)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string line = reader.ReadLine().Trim();
|
||||
|
||||
while (String.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
|
||||
{
|
||||
if (reader.EndOfStream)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
line = reader.ReadLine().Trim();
|
||||
}
|
||||
|
||||
token = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static string DoubleToString(double d)
|
||||
{
|
||||
double max = 999999;
|
||||
double min = 0.00001;
|
||||
|
||||
string spec = "0.00000";
|
||||
|
||||
if (d < min || d > max)
|
||||
{
|
||||
spec = "0.###e-000";
|
||||
}
|
||||
|
||||
return d.ToString(spec, Util.Nfi);
|
||||
}
|
||||
|
||||
internal static string AngleToString(double d)
|
||||
{
|
||||
double max = 180 - 10E-14;
|
||||
double min = 10E-14;
|
||||
|
||||
string spec = "0.00000";
|
||||
|
||||
if (d < min || d > max)
|
||||
{
|
||||
spec = "0.#";
|
||||
}
|
||||
|
||||
return d.ToString(spec, Util.Nfi);
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+145
@@ -0,0 +1,145 @@
|
||||
namespace MeshExplorer.Views
|
||||
{
|
||||
partial class AboutView
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.lbCodeplex = new System.Windows.Forms.Label();
|
||||
this.label15 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label19 = new System.Windows.Forms.Label();
|
||||
this.label18 = new System.Windows.Forms.Label();
|
||||
this.label7 = new System.Windows.Forms.Label();
|
||||
this.lbShortcuts = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lbCodeplex
|
||||
//
|
||||
this.lbCodeplex.AutoSize = true;
|
||||
this.lbCodeplex.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbCodeplex.ForeColor = System.Drawing.Color.White;
|
||||
this.lbCodeplex.Location = new System.Drawing.Point(72, 82);
|
||||
this.lbCodeplex.Name = "lbCodeplex";
|
||||
this.lbCodeplex.Size = new System.Drawing.Size(153, 13);
|
||||
this.lbCodeplex.TabIndex = 9;
|
||||
this.lbCodeplex.Text = "http://triangle.codeplex.com";
|
||||
this.lbCodeplex.Click += new System.EventHandler(this.lbCodeplex_Clicked);
|
||||
//
|
||||
// label15
|
||||
//
|
||||
this.label15.AutoSize = true;
|
||||
this.label15.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label15.ForeColor = System.Drawing.Color.White;
|
||||
this.label15.Location = new System.Drawing.Point(10, 17);
|
||||
this.label15.Name = "label15";
|
||||
this.label15.Size = new System.Drawing.Size(73, 13);
|
||||
this.label15.TabIndex = 7;
|
||||
this.label15.Text = "Triangle.NET";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.ForeColor = System.Drawing.Color.White;
|
||||
this.label1.Location = new System.Drawing.Point(10, 132);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(108, 13);
|
||||
this.label1.TabIndex = 8;
|
||||
this.label1.Text = "Keyboard shortcuts";
|
||||
//
|
||||
// label19
|
||||
//
|
||||
this.label19.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label19.ForeColor = System.Drawing.Color.White;
|
||||
this.label19.Location = new System.Drawing.Point(72, 42);
|
||||
this.label19.Name = "label19";
|
||||
this.label19.Size = new System.Drawing.Size(134, 40);
|
||||
this.label19.TabIndex = 6;
|
||||
this.label19.Text = "Beta 4 (2014-05-30)\r\nChristian Woltering\r\nMIT";
|
||||
//
|
||||
// label18
|
||||
//
|
||||
this.label18.ForeColor = System.Drawing.Color.White;
|
||||
this.label18.Location = new System.Drawing.Point(15, 42);
|
||||
this.label18.Name = "label18";
|
||||
this.label18.Size = new System.Drawing.Size(51, 40);
|
||||
this.label18.TabIndex = 4;
|
||||
this.label18.Text = "Version:\r\nAuthor:\r\nLicense:";
|
||||
this.label18.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// label7
|
||||
//
|
||||
this.label7.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label7.ForeColor = System.Drawing.Color.White;
|
||||
this.label7.Location = new System.Drawing.Point(72, 155);
|
||||
this.label7.Name = "label7";
|
||||
this.label7.Size = new System.Drawing.Size(134, 108);
|
||||
this.label7.TabIndex = 5;
|
||||
this.label7.Text = "File Open\r\nFile Save\r\nReload Input\r\n\r\nTriangulate / Refine\r\nSmooth\r\n\r\nShow Log";
|
||||
//
|
||||
// lbShortcuts
|
||||
//
|
||||
this.lbShortcuts.ForeColor = System.Drawing.Color.White;
|
||||
this.lbShortcuts.Location = new System.Drawing.Point(24, 155);
|
||||
this.lbShortcuts.Name = "lbShortcuts";
|
||||
this.lbShortcuts.Size = new System.Drawing.Size(36, 108);
|
||||
this.lbShortcuts.TabIndex = 3;
|
||||
this.lbShortcuts.Text = "F3\r\nF4\r\nF5\r\n\r\nF8\r\nF9\r\n\r\nF12";
|
||||
this.lbShortcuts.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// AboutView
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.DimGray;
|
||||
this.Controls.Add(this.lbCodeplex);
|
||||
this.Controls.Add(this.label15);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.label19);
|
||||
this.Controls.Add(this.label18);
|
||||
this.Controls.Add(this.label7);
|
||||
this.Controls.Add(this.lbShortcuts);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.Name = "AboutView";
|
||||
this.Size = new System.Drawing.Size(272, 509);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label lbCodeplex;
|
||||
private System.Windows.Forms.Label label15;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label19;
|
||||
private System.Windows.Forms.Label label18;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private System.Windows.Forms.Label lbShortcuts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
namespace MeshExplorer.Views
|
||||
{
|
||||
public partial class AboutView : UserControl, IView
|
||||
{
|
||||
public AboutView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void lbCodeplex_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessStartInfo info = new ProcessStartInfo("http://triangle.codeplex.com/");
|
||||
Process.Start(info);
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
|
||||
#region IView
|
||||
|
||||
public void HandleNewInput(IPolygon geometry)
|
||||
{
|
||||
}
|
||||
|
||||
public void HandleMeshImport(IPolygon geometry, Mesh mesh)
|
||||
{
|
||||
}
|
||||
|
||||
public void HandleMeshUpdate(Mesh mesh)
|
||||
{
|
||||
}
|
||||
|
||||
public void HandleMeshChange(Mesh mesh)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,26 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="IView.cs" company="">
|
||||
// TODO: Update copyright text.
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.Views
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Update summary.
|
||||
/// </summary>
|
||||
public interface IView
|
||||
{
|
||||
void HandleNewInput(IPolygon geometry);
|
||||
void HandleMeshImport(IPolygon geometry, Mesh mesh);
|
||||
void HandleMeshUpdate(Mesh mesh);
|
||||
void HandleMeshChange(Mesh mesh);
|
||||
}
|
||||
}
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
namespace MeshExplorer.Views
|
||||
{
|
||||
partial class MeshControlView
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.lbMaxArea = new System.Windows.Forms.Label();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.lbMinAngle = new System.Windows.Forms.Label();
|
||||
this.label23 = new System.Windows.Forms.Label();
|
||||
this.label9 = new System.Windows.Forms.Label();
|
||||
this.label8 = new System.Windows.Forms.Label();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.lbMaxAngle = new System.Windows.Forms.Label();
|
||||
this.cbSweepline = new MeshExplorer.Controls.DarkCheckBox();
|
||||
this.slMaxAngle = new MeshExplorer.Controls.DarkSlider();
|
||||
this.slMaxArea = new MeshExplorer.Controls.DarkSlider();
|
||||
this.slMinAngle = new MeshExplorer.Controls.DarkSlider();
|
||||
this.cbConformDel = new MeshExplorer.Controls.DarkCheckBox();
|
||||
this.cbConvex = new MeshExplorer.Controls.DarkCheckBox();
|
||||
this.cbQuality = new MeshExplorer.Controls.DarkCheckBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lbMaxArea
|
||||
//
|
||||
this.lbMaxArea.AutoSize = true;
|
||||
this.lbMaxArea.ForeColor = System.Drawing.Color.White;
|
||||
this.lbMaxArea.Location = new System.Drawing.Point(227, 87);
|
||||
this.lbMaxArea.Name = "lbMaxArea";
|
||||
this.lbMaxArea.Size = new System.Drawing.Size(13, 13);
|
||||
this.lbMaxArea.TabIndex = 20;
|
||||
this.lbMaxArea.Text = "0";
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.AutoSize = true;
|
||||
this.label6.ForeColor = System.Drawing.Color.White;
|
||||
this.label6.Location = new System.Drawing.Point(8, 86);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(81, 13);
|
||||
this.label6.TabIndex = 23;
|
||||
this.label6.Text = "Maximum area";
|
||||
//
|
||||
// lbMinAngle
|
||||
//
|
||||
this.lbMinAngle.AutoSize = true;
|
||||
this.lbMinAngle.ForeColor = System.Drawing.Color.White;
|
||||
this.lbMinAngle.Location = new System.Drawing.Point(227, 43);
|
||||
this.lbMinAngle.Name = "lbMinAngle";
|
||||
this.lbMinAngle.Size = new System.Drawing.Size(19, 13);
|
||||
this.lbMinAngle.TabIndex = 22;
|
||||
this.lbMinAngle.Text = "20";
|
||||
//
|
||||
// label23
|
||||
//
|
||||
this.label23.BackColor = System.Drawing.Color.DimGray;
|
||||
this.label23.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label23.Location = new System.Drawing.Point(8, 173);
|
||||
this.label23.Name = "label23";
|
||||
this.label23.Size = new System.Drawing.Size(251, 33);
|
||||
this.label23.TabIndex = 24;
|
||||
this.label23.Text = "Ensure that all triangles in the mesh are truly Delaunay, and not just constraine" +
|
||||
"d Delaunay.";
|
||||
//
|
||||
// label9
|
||||
//
|
||||
this.label9.BackColor = System.Drawing.Color.DimGray;
|
||||
this.label9.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label9.Location = new System.Drawing.Point(8, 237);
|
||||
this.label9.Name = "label9";
|
||||
this.label9.Size = new System.Drawing.Size(258, 33);
|
||||
this.label9.TabIndex = 26;
|
||||
this.label9.Text = "Use the convex mesh option, if the convex hull should be included in the output.";
|
||||
//
|
||||
// label8
|
||||
//
|
||||
this.label8.BackColor = System.Drawing.Color.DimGray;
|
||||
this.label8.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label8.Location = new System.Drawing.Point(8, 110);
|
||||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(258, 33);
|
||||
this.label8.TabIndex = 25;
|
||||
this.label8.Text = "Hint: maximum area values of 0 or 1 will be irgnored (no area constraints are set" +
|
||||
").";
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.ForeColor = System.Drawing.Color.White;
|
||||
this.label5.Location = new System.Drawing.Point(8, 42);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(87, 13);
|
||||
this.label5.TabIndex = 21;
|
||||
this.label5.Text = "Minimum angle";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.BackColor = System.Drawing.Color.DimGray;
|
||||
this.label1.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label1.Location = new System.Drawing.Point(8, 304);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(258, 33);
|
||||
this.label1.TabIndex = 26;
|
||||
this.label1.Text = "Use Sweepline algorithm for triangulation instead of default Divide && Conquer.";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.ForeColor = System.Drawing.Color.White;
|
||||
this.label2.Location = new System.Drawing.Point(8, 64);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(88, 13);
|
||||
this.label2.TabIndex = 21;
|
||||
this.label2.Text = "Maximum angle";
|
||||
//
|
||||
// lbMaxAngle
|
||||
//
|
||||
this.lbMaxAngle.AutoSize = true;
|
||||
this.lbMaxAngle.ForeColor = System.Drawing.Color.White;
|
||||
this.lbMaxAngle.Location = new System.Drawing.Point(227, 65);
|
||||
this.lbMaxAngle.Name = "lbMaxAngle";
|
||||
this.lbMaxAngle.Size = new System.Drawing.Size(25, 13);
|
||||
this.lbMaxAngle.TabIndex = 22;
|
||||
this.lbMaxAngle.Text = "180";
|
||||
//
|
||||
// cbSweepline
|
||||
//
|
||||
this.cbSweepline.BackColor = System.Drawing.Color.DimGray;
|
||||
this.cbSweepline.Checked = false;
|
||||
this.cbSweepline.Location = new System.Drawing.Point(11, 278);
|
||||
this.cbSweepline.Name = "cbSweepline";
|
||||
this.cbSweepline.Size = new System.Drawing.Size(181, 23);
|
||||
this.cbSweepline.TabIndex = 27;
|
||||
this.cbSweepline.Text = "Use Sweepline algorithm";
|
||||
this.cbSweepline.UseVisualStyleBackColor = false;
|
||||
//
|
||||
// slMaxAngle
|
||||
//
|
||||
this.slMaxAngle.BackColor = System.Drawing.Color.Transparent;
|
||||
this.slMaxAngle.CriticalPercent = ((uint)(89u));
|
||||
this.slMaxAngle.Location = new System.Drawing.Point(102, 61);
|
||||
this.slMaxAngle.Maximum = 100;
|
||||
this.slMaxAngle.Minimum = 0;
|
||||
this.slMaxAngle.Name = "slMaxAngle";
|
||||
this.slMaxAngle.Size = new System.Drawing.Size(119, 18);
|
||||
this.slMaxAngle.TabIndex = 18;
|
||||
this.slMaxAngle.Text = "darkSlider1";
|
||||
this.slMaxAngle.Value = 0;
|
||||
this.slMaxAngle.ValueChanging += new System.EventHandler(this.slMaxAngle_ValueChanging);
|
||||
//
|
||||
// slMaxArea
|
||||
//
|
||||
this.slMaxArea.BackColor = System.Drawing.Color.Transparent;
|
||||
this.slMaxArea.CriticalPercent = ((uint)(0u));
|
||||
this.slMaxArea.Location = new System.Drawing.Point(102, 83);
|
||||
this.slMaxArea.Maximum = 100;
|
||||
this.slMaxArea.Minimum = 0;
|
||||
this.slMaxArea.Name = "slMaxArea";
|
||||
this.slMaxArea.Size = new System.Drawing.Size(119, 18);
|
||||
this.slMaxArea.TabIndex = 19;
|
||||
this.slMaxArea.Text = "darkSlider1";
|
||||
this.slMaxArea.Value = 0;
|
||||
this.slMaxArea.ValueChanging += new System.EventHandler(this.slMaxArea_ValueChanging);
|
||||
//
|
||||
// slMinAngle
|
||||
//
|
||||
this.slMinAngle.BackColor = System.Drawing.Color.Transparent;
|
||||
this.slMinAngle.CriticalPercent = ((uint)(89u));
|
||||
this.slMinAngle.Location = new System.Drawing.Point(102, 39);
|
||||
this.slMinAngle.Maximum = 100;
|
||||
this.slMinAngle.Minimum = 0;
|
||||
this.slMinAngle.Name = "slMinAngle";
|
||||
this.slMinAngle.Size = new System.Drawing.Size(119, 18);
|
||||
this.slMinAngle.TabIndex = 18;
|
||||
this.slMinAngle.Text = "darkSlider1";
|
||||
this.slMinAngle.Value = 50;
|
||||
this.slMinAngle.ValueChanging += new System.EventHandler(this.slMinAngle_ValueChanging);
|
||||
//
|
||||
// cbConformDel
|
||||
//
|
||||
this.cbConformDel.BackColor = System.Drawing.Color.DimGray;
|
||||
this.cbConformDel.Checked = false;
|
||||
this.cbConformDel.Location = new System.Drawing.Point(11, 153);
|
||||
this.cbConformDel.Name = "cbConformDel";
|
||||
this.cbConformDel.Size = new System.Drawing.Size(142, 17);
|
||||
this.cbConformDel.TabIndex = 16;
|
||||
this.cbConformDel.Text = "Conforming Delaunay";
|
||||
this.cbConformDel.UseVisualStyleBackColor = false;
|
||||
//
|
||||
// cbConvex
|
||||
//
|
||||
this.cbConvex.BackColor = System.Drawing.Color.DimGray;
|
||||
this.cbConvex.Checked = false;
|
||||
this.cbConvex.Location = new System.Drawing.Point(11, 217);
|
||||
this.cbConvex.Name = "cbConvex";
|
||||
this.cbConvex.Size = new System.Drawing.Size(115, 17);
|
||||
this.cbConvex.TabIndex = 15;
|
||||
this.cbConvex.Text = "Convex mesh";
|
||||
this.cbConvex.UseVisualStyleBackColor = false;
|
||||
//
|
||||
// cbQuality
|
||||
//
|
||||
this.cbQuality.BackColor = System.Drawing.Color.DimGray;
|
||||
this.cbQuality.Checked = false;
|
||||
this.cbQuality.Location = new System.Drawing.Point(11, 16);
|
||||
this.cbQuality.Name = "cbQuality";
|
||||
this.cbQuality.Size = new System.Drawing.Size(115, 17);
|
||||
this.cbQuality.TabIndex = 17;
|
||||
this.cbQuality.Text = "Quality mesh";
|
||||
this.cbQuality.UseVisualStyleBackColor = false;
|
||||
//
|
||||
// MeshControlView
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.DimGray;
|
||||
this.Controls.Add(this.cbSweepline);
|
||||
this.Controls.Add(this.lbMaxArea);
|
||||
this.Controls.Add(this.label6);
|
||||
this.Controls.Add(this.lbMaxAngle);
|
||||
this.Controls.Add(this.lbMinAngle);
|
||||
this.Controls.Add(this.label23);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.label9);
|
||||
this.Controls.Add(this.label8);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.label5);
|
||||
this.Controls.Add(this.slMaxAngle);
|
||||
this.Controls.Add(this.slMaxArea);
|
||||
this.Controls.Add(this.slMinAngle);
|
||||
this.Controls.Add(this.cbConformDel);
|
||||
this.Controls.Add(this.cbConvex);
|
||||
this.Controls.Add(this.cbQuality);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.Name = "MeshControlView";
|
||||
this.Size = new System.Drawing.Size(272, 509);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label lbMaxArea;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.Label lbMinAngle;
|
||||
private System.Windows.Forms.Label label23;
|
||||
private System.Windows.Forms.Label label9;
|
||||
private System.Windows.Forms.Label label8;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private Controls.DarkSlider slMaxArea;
|
||||
private Controls.DarkSlider slMinAngle;
|
||||
private Controls.DarkCheckBox cbConformDel;
|
||||
private Controls.DarkCheckBox cbConvex;
|
||||
private Controls.DarkCheckBox cbQuality;
|
||||
private Controls.DarkCheckBox cbSweepline;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private Controls.DarkSlider slMaxAngle;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label lbMaxAngle;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
namespace MeshExplorer.Views
|
||||
{
|
||||
public partial class MeshControlView : UserControl, IView
|
||||
{
|
||||
public MeshControlView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public bool ParamQualityChecked
|
||||
{
|
||||
get { return cbQuality.Checked; }
|
||||
}
|
||||
|
||||
public bool ParamConvexChecked
|
||||
{
|
||||
get { return cbConvex.Checked; }
|
||||
}
|
||||
|
||||
public bool ParamConformDelChecked
|
||||
{
|
||||
get { return cbConformDel.Checked; }
|
||||
}
|
||||
|
||||
public bool ParamSweeplineChecked
|
||||
{
|
||||
get { return cbSweepline.Checked; }
|
||||
}
|
||||
|
||||
public int ParamMinAngleValue
|
||||
{
|
||||
get { return (slMinAngle.Value * 40) / 100; }
|
||||
}
|
||||
|
||||
public int ParamMaxAngleValue
|
||||
{
|
||||
get { return 80 + (100 - slMaxAngle.Value); }
|
||||
}
|
||||
|
||||
public double ParamMaxAreaValue
|
||||
{
|
||||
get { return slMaxArea.Value * 0.01; }
|
||||
}
|
||||
|
||||
private void slMinAngle_ValueChanging(object sender, EventArgs e)
|
||||
{
|
||||
// Between 0 and 40 (step 1)
|
||||
int angle = (slMinAngle.Value * 40) / 100;
|
||||
lbMinAngle.Text = angle.ToString();
|
||||
}
|
||||
|
||||
private void slMaxAngle_ValueChanging(object sender, EventArgs e)
|
||||
{
|
||||
// Between 180 and 80 (step 1)
|
||||
int angle = 80 + (100 - slMaxAngle.Value);
|
||||
lbMaxAngle.Text = angle.ToString();
|
||||
}
|
||||
|
||||
private void slMaxArea_ValueChanging(object sender, EventArgs e)
|
||||
{
|
||||
// Between 0 and 1 (step 0.01)
|
||||
double area = slMaxArea.Value * 0.01;
|
||||
lbMaxArea.Text = area.ToString(Util.Nfi);
|
||||
}
|
||||
|
||||
#region IView
|
||||
|
||||
public void HandleNewInput(IPolygon geometry)
|
||||
{
|
||||
}
|
||||
|
||||
public void HandleMeshImport(IPolygon geometry, Mesh mesh)
|
||||
{
|
||||
}
|
||||
|
||||
public void HandleMeshUpdate(Mesh mesh)
|
||||
{
|
||||
}
|
||||
|
||||
public void HandleMeshChange(Mesh mesh)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
+483
@@ -0,0 +1,483 @@
|
||||
namespace MeshExplorer.Views
|
||||
{
|
||||
partial class StatisticView
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
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();
|
||||
this.label12 = new System.Windows.Forms.Label();
|
||||
this.label16 = new System.Windows.Forms.Label();
|
||||
this.label29 = new System.Windows.Forms.Label();
|
||||
this.label14 = new System.Windows.Forms.Label();
|
||||
this.lbAngleMax = new System.Windows.Forms.Label();
|
||||
this.lbQualAspectAve = new System.Windows.Forms.Label();
|
||||
this.lbEdgeMax = new System.Windows.Forms.Label();
|
||||
this.lbQualAlphaAve = new System.Windows.Forms.Label();
|
||||
this.lbAreaMax = new System.Windows.Forms.Label();
|
||||
this.lbAngleMin = new System.Windows.Forms.Label();
|
||||
this.lbQualAspectMin = new System.Windows.Forms.Label();
|
||||
this.lbEdgeMin = new System.Windows.Forms.Label();
|
||||
this.lbQualAlphaMin = new System.Windows.Forms.Label();
|
||||
this.lbAreaMin = new System.Windows.Forms.Label();
|
||||
this.label22 = new System.Windows.Forms.Label();
|
||||
this.label10 = new System.Windows.Forms.Label();
|
||||
this.label17 = new System.Windows.Forms.Label();
|
||||
this.label21 = new System.Windows.Forms.Label();
|
||||
this.label11 = new System.Windows.Forms.Label();
|
||||
this.angleHistogram1 = new MeshExplorer.Controls.AngleHistogram();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// 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, 17);
|
||||
this.label20.Name = "label20";
|
||||
this.label20.Size = new System.Drawing.Size(39, 13);
|
||||
this.label20.TabIndex = 59;
|
||||
this.label20.Text = "Mesh:";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label4.Location = new System.Drawing.Point(8, 57);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(60, 13);
|
||||
this.label4.TabIndex = 56;
|
||||
this.label4.Text = "Segments:";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label3.Location = new System.Drawing.Point(8, 76);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(56, 13);
|
||||
this.label3.TabIndex = 57;
|
||||
this.label3.Text = "Triangles:";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label2.Location = new System.Drawing.Point(8, 38);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(50, 13);
|
||||
this.label2.TabIndex = 58;
|
||||
this.label2.Text = "Vertices:";
|
||||
//
|
||||
// lbNumSeg
|
||||
//
|
||||
this.lbNumSeg.ForeColor = System.Drawing.Color.White;
|
||||
this.lbNumSeg.Location = new System.Drawing.Point(98, 57);
|
||||
this.lbNumSeg.Name = "lbNumSeg";
|
||||
this.lbNumSeg.Size = new System.Drawing.Size(70, 13);
|
||||
this.lbNumSeg.TabIndex = 53;
|
||||
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, 57);
|
||||
this.lbNumSeg2.Name = "lbNumSeg2";
|
||||
this.lbNumSeg2.Size = new System.Drawing.Size(70, 13);
|
||||
this.lbNumSeg2.TabIndex = 52;
|
||||
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, 76);
|
||||
this.lbNumTri.Name = "lbNumTri";
|
||||
this.lbNumTri.Size = new System.Drawing.Size(70, 13);
|
||||
this.lbNumTri.TabIndex = 50;
|
||||
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, 76);
|
||||
this.lbNumTri2.Name = "lbNumTri2";
|
||||
this.lbNumTri2.Size = new System.Drawing.Size(70, 13);
|
||||
this.lbNumTri2.TabIndex = 51;
|
||||
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, 38);
|
||||
this.lbNumVert.Name = "lbNumVert";
|
||||
this.lbNumVert.Size = new System.Drawing.Size(70, 13);
|
||||
this.lbNumVert.TabIndex = 54;
|
||||
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, 38);
|
||||
this.lbNumVert2.Name = "lbNumVert2";
|
||||
this.lbNumVert2.Size = new System.Drawing.Size(70, 13);
|
||||
this.lbNumVert2.TabIndex = 55;
|
||||
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(210, 213);
|
||||
this.label32.Name = "label32";
|
||||
this.label32.Size = new System.Drawing.Size(48, 13);
|
||||
this.label32.TabIndex = 41;
|
||||
this.label32.Text = "Average";
|
||||
//
|
||||
// label13
|
||||
//
|
||||
this.label13.AutoSize = true;
|
||||
this.label13.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label13.Location = new System.Drawing.Point(202, 114);
|
||||
this.label13.Name = "label13";
|
||||
this.label13.Size = new System.Drawing.Size(56, 13);
|
||||
this.label13.TabIndex = 42;
|
||||
this.label13.Text = "Maximum";
|
||||
//
|
||||
// label31
|
||||
//
|
||||
this.label31.AutoSize = true;
|
||||
this.label31.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label31.Location = new System.Drawing.Point(112, 213);
|
||||
this.label31.Name = "label31";
|
||||
this.label31.Size = new System.Drawing.Size(55, 13);
|
||||
this.label31.TabIndex = 44;
|
||||
this.label31.Text = "Minimum";
|
||||
//
|
||||
// label12
|
||||
//
|
||||
this.label12.AutoSize = true;
|
||||
this.label12.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label12.Location = new System.Drawing.Point(113, 114);
|
||||
this.label12.Name = "label12";
|
||||
this.label12.Size = new System.Drawing.Size(55, 13);
|
||||
this.label12.TabIndex = 43;
|
||||
this.label12.Text = "Minimum";
|
||||
//
|
||||
// label16
|
||||
//
|
||||
this.label16.AutoSize = true;
|
||||
this.label16.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label16.Location = new System.Drawing.Point(8, 173);
|
||||
this.label16.Name = "label16";
|
||||
this.label16.Size = new System.Drawing.Size(40, 13);
|
||||
this.label16.TabIndex = 40;
|
||||
this.label16.Text = "Angle:";
|
||||
//
|
||||
// label29
|
||||
//
|
||||
this.label29.AutoSize = true;
|
||||
this.label29.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label29.Location = new System.Drawing.Point(8, 253);
|
||||
this.label29.Name = "label29";
|
||||
this.label29.Size = new System.Drawing.Size(71, 13);
|
||||
this.label29.TabIndex = 47;
|
||||
this.label29.Text = "Aspect ratio:";
|
||||
//
|
||||
// label14
|
||||
//
|
||||
this.label14.AutoSize = true;
|
||||
this.label14.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label14.Location = new System.Drawing.Point(8, 154);
|
||||
this.label14.Name = "label14";
|
||||
this.label14.Size = new System.Drawing.Size(73, 13);
|
||||
this.label14.TabIndex = 48;
|
||||
this.label14.Text = "Edge length:";
|
||||
//
|
||||
// lbAngleMax
|
||||
//
|
||||
this.lbAngleMax.ForeColor = System.Drawing.Color.White;
|
||||
this.lbAngleMax.Location = new System.Drawing.Point(182, 173);
|
||||
this.lbAngleMax.Name = "lbAngleMax";
|
||||
this.lbAngleMax.Size = new System.Drawing.Size(76, 13);
|
||||
this.lbAngleMax.TabIndex = 49;
|
||||
this.lbAngleMax.Text = "-";
|
||||
this.lbAngleMax.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbQualAspectAve
|
||||
//
|
||||
this.lbQualAspectAve.ForeColor = System.Drawing.Color.White;
|
||||
this.lbQualAspectAve.Location = new System.Drawing.Point(182, 253);
|
||||
this.lbQualAspectAve.Name = "lbQualAspectAve";
|
||||
this.lbQualAspectAve.Size = new System.Drawing.Size(76, 13);
|
||||
this.lbQualAspectAve.TabIndex = 46;
|
||||
this.lbQualAspectAve.Text = "-";
|
||||
this.lbQualAspectAve.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbEdgeMax
|
||||
//
|
||||
this.lbEdgeMax.ForeColor = System.Drawing.Color.White;
|
||||
this.lbEdgeMax.Location = new System.Drawing.Point(182, 154);
|
||||
this.lbEdgeMax.Name = "lbEdgeMax";
|
||||
this.lbEdgeMax.Size = new System.Drawing.Size(76, 13);
|
||||
this.lbEdgeMax.TabIndex = 45;
|
||||
this.lbEdgeMax.Text = "-";
|
||||
this.lbEdgeMax.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbQualAlphaAve
|
||||
//
|
||||
this.lbQualAlphaAve.ForeColor = System.Drawing.Color.White;
|
||||
this.lbQualAlphaAve.Location = new System.Drawing.Point(182, 234);
|
||||
this.lbQualAlphaAve.Name = "lbQualAlphaAve";
|
||||
this.lbQualAlphaAve.Size = new System.Drawing.Size(76, 13);
|
||||
this.lbQualAlphaAve.TabIndex = 30;
|
||||
this.lbQualAlphaAve.Text = "-";
|
||||
this.lbQualAlphaAve.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbAreaMax
|
||||
//
|
||||
this.lbAreaMax.ForeColor = System.Drawing.Color.White;
|
||||
this.lbAreaMax.Location = new System.Drawing.Point(182, 135);
|
||||
this.lbAreaMax.Name = "lbAreaMax";
|
||||
this.lbAreaMax.Size = new System.Drawing.Size(76, 13);
|
||||
this.lbAreaMax.TabIndex = 31;
|
||||
this.lbAreaMax.Text = "-";
|
||||
this.lbAreaMax.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbAngleMin
|
||||
//
|
||||
this.lbAngleMin.ForeColor = System.Drawing.Color.White;
|
||||
this.lbAngleMin.Location = new System.Drawing.Point(100, 173);
|
||||
this.lbAngleMin.Name = "lbAngleMin";
|
||||
this.lbAngleMin.Size = new System.Drawing.Size(68, 13);
|
||||
this.lbAngleMin.TabIndex = 32;
|
||||
this.lbAngleMin.Text = "-";
|
||||
this.lbAngleMin.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbQualAspectMin
|
||||
//
|
||||
this.lbQualAspectMin.ForeColor = System.Drawing.Color.White;
|
||||
this.lbQualAspectMin.Location = new System.Drawing.Point(100, 253);
|
||||
this.lbQualAspectMin.Name = "lbQualAspectMin";
|
||||
this.lbQualAspectMin.Size = new System.Drawing.Size(68, 13);
|
||||
this.lbQualAspectMin.TabIndex = 29;
|
||||
this.lbQualAspectMin.Text = "-";
|
||||
this.lbQualAspectMin.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbEdgeMin
|
||||
//
|
||||
this.lbEdgeMin.ForeColor = System.Drawing.Color.White;
|
||||
this.lbEdgeMin.Location = new System.Drawing.Point(100, 154);
|
||||
this.lbEdgeMin.Name = "lbEdgeMin";
|
||||
this.lbEdgeMin.Size = new System.Drawing.Size(68, 13);
|
||||
this.lbEdgeMin.TabIndex = 28;
|
||||
this.lbEdgeMin.Text = "-";
|
||||
this.lbEdgeMin.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbQualAlphaMin
|
||||
//
|
||||
this.lbQualAlphaMin.ForeColor = System.Drawing.Color.White;
|
||||
this.lbQualAlphaMin.Location = new System.Drawing.Point(100, 234);
|
||||
this.lbQualAlphaMin.Name = "lbQualAlphaMin";
|
||||
this.lbQualAlphaMin.Size = new System.Drawing.Size(68, 13);
|
||||
this.lbQualAlphaMin.TabIndex = 37;
|
||||
this.lbQualAlphaMin.Text = "-";
|
||||
this.lbQualAlphaMin.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lbAreaMin
|
||||
//
|
||||
this.lbAreaMin.ForeColor = System.Drawing.Color.White;
|
||||
this.lbAreaMin.Location = new System.Drawing.Point(100, 135);
|
||||
this.lbAreaMin.Name = "lbAreaMin";
|
||||
this.lbAreaMin.Size = new System.Drawing.Size(68, 13);
|
||||
this.lbAreaMin.TabIndex = 36;
|
||||
this.lbAreaMin.Text = "-";
|
||||
this.lbAreaMin.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// label22
|
||||
//
|
||||
this.label22.AutoSize = true;
|
||||
this.label22.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label22.Location = new System.Drawing.Point(8, 234);
|
||||
this.label22.Name = "label22";
|
||||
this.label22.Size = new System.Drawing.Size(65, 13);
|
||||
this.label22.TabIndex = 39;
|
||||
this.label22.Text = "Min. angle:";
|
||||
//
|
||||
// label10
|
||||
//
|
||||
this.label10.AutoSize = true;
|
||||
this.label10.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.label10.Location = new System.Drawing.Point(8, 135);
|
||||
this.label10.Name = "label10";
|
||||
this.label10.Size = new System.Drawing.Size(76, 13);
|
||||
this.label10.TabIndex = 38;
|
||||
this.label10.Text = "Triangle area:";
|
||||
//
|
||||
// label17
|
||||
//
|
||||
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, 290);
|
||||
this.label17.Name = "label17";
|
||||
this.label17.Size = new System.Drawing.Size(97, 13);
|
||||
this.label17.TabIndex = 33;
|
||||
this.label17.Text = "Angle histogram:";
|
||||
//
|
||||
// label21
|
||||
//
|
||||
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, 213);
|
||||
this.label21.Name = "label21";
|
||||
this.label21.Size = new System.Drawing.Size(47, 13);
|
||||
this.label21.TabIndex = 35;
|
||||
this.label21.Text = "Quality:";
|
||||
//
|
||||
// label11
|
||||
//
|
||||
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, 114);
|
||||
this.label11.Name = "label11";
|
||||
this.label11.Size = new System.Drawing.Size(50, 13);
|
||||
this.label11.TabIndex = 34;
|
||||
this.label11.Text = "Statistic:";
|
||||
//
|
||||
// angleHistogram1
|
||||
//
|
||||
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, 308);
|
||||
this.angleHistogram1.Name = "angleHistogram1";
|
||||
this.angleHistogram1.Size = new System.Drawing.Size(260, 195);
|
||||
this.angleHistogram1.TabIndex = 27;
|
||||
this.angleHistogram1.Text = "angleHistogram1";
|
||||
//
|
||||
// StatisticView
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.DimGray;
|
||||
this.Controls.Add(this.label20);
|
||||
this.Controls.Add(this.label4);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.lbNumSeg);
|
||||
this.Controls.Add(this.lbNumSeg2);
|
||||
this.Controls.Add(this.lbNumTri);
|
||||
this.Controls.Add(this.lbNumTri2);
|
||||
this.Controls.Add(this.lbNumVert);
|
||||
this.Controls.Add(this.lbNumVert2);
|
||||
this.Controls.Add(this.label32);
|
||||
this.Controls.Add(this.label13);
|
||||
this.Controls.Add(this.label31);
|
||||
this.Controls.Add(this.label12);
|
||||
this.Controls.Add(this.label16);
|
||||
this.Controls.Add(this.label29);
|
||||
this.Controls.Add(this.label14);
|
||||
this.Controls.Add(this.lbAngleMax);
|
||||
this.Controls.Add(this.lbQualAspectAve);
|
||||
this.Controls.Add(this.lbEdgeMax);
|
||||
this.Controls.Add(this.lbQualAlphaAve);
|
||||
this.Controls.Add(this.lbAreaMax);
|
||||
this.Controls.Add(this.lbAngleMin);
|
||||
this.Controls.Add(this.lbQualAspectMin);
|
||||
this.Controls.Add(this.lbEdgeMin);
|
||||
this.Controls.Add(this.lbQualAlphaMin);
|
||||
this.Controls.Add(this.lbAreaMin);
|
||||
this.Controls.Add(this.label22);
|
||||
this.Controls.Add(this.label10);
|
||||
this.Controls.Add(this.label17);
|
||||
this.Controls.Add(this.label21);
|
||||
this.Controls.Add(this.label11);
|
||||
this.Controls.Add(this.angleHistogram1);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.ForeColor = System.Drawing.Color.DarkGray;
|
||||
this.Name = "StatisticView";
|
||||
this.Size = new System.Drawing.Size(272, 509);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
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;
|
||||
private System.Windows.Forms.Label label32;
|
||||
private System.Windows.Forms.Label label13;
|
||||
private System.Windows.Forms.Label label31;
|
||||
private System.Windows.Forms.Label label12;
|
||||
private System.Windows.Forms.Label label16;
|
||||
private System.Windows.Forms.Label label29;
|
||||
private System.Windows.Forms.Label label14;
|
||||
private System.Windows.Forms.Label lbAngleMax;
|
||||
private System.Windows.Forms.Label lbQualAspectAve;
|
||||
private System.Windows.Forms.Label lbEdgeMax;
|
||||
private System.Windows.Forms.Label lbQualAlphaAve;
|
||||
private System.Windows.Forms.Label lbAreaMax;
|
||||
private System.Windows.Forms.Label lbAngleMin;
|
||||
private System.Windows.Forms.Label lbQualAspectMin;
|
||||
private System.Windows.Forms.Label lbEdgeMin;
|
||||
private System.Windows.Forms.Label lbQualAlphaMin;
|
||||
private System.Windows.Forms.Label lbAreaMin;
|
||||
private System.Windows.Forms.Label label22;
|
||||
private System.Windows.Forms.Label label10;
|
||||
private System.Windows.Forms.Label label17;
|
||||
private System.Windows.Forms.Label label21;
|
||||
private System.Windows.Forms.Label label11;
|
||||
private Controls.AngleHistogram angleHistogram1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Tools;
|
||||
|
||||
namespace MeshExplorer.Views
|
||||
{
|
||||
public partial class StatisticView : UserControl, IView
|
||||
{
|
||||
Statistic statistic = new Statistic();
|
||||
QualityMeasure quality;
|
||||
|
||||
public Statistic Statistic
|
||||
{
|
||||
get { return statistic; }
|
||||
}
|
||||
|
||||
public StatisticView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void UpdateStatistic(Mesh mesh)
|
||||
{
|
||||
statistic.Update(mesh, 10);
|
||||
}
|
||||
|
||||
#region IView
|
||||
|
||||
public void HandleNewInput(IPolygon geometry)
|
||||
{
|
||||
// Reset labels
|
||||
lbNumVert2.Text = "-";
|
||||
lbNumTri2.Text = "-";
|
||||
lbNumSeg2.Text = "-";
|
||||
|
||||
lbNumVert.Text = geometry.Points.Count.ToString();
|
||||
lbNumSeg.Text = geometry.Segments.Count().ToString();
|
||||
lbNumTri.Text = "0";
|
||||
|
||||
// Statistics labels
|
||||
lbAreaMin.Text = "-";
|
||||
lbAreaMax.Text = "-";
|
||||
lbEdgeMin.Text = "-";
|
||||
lbEdgeMax.Text = "-";
|
||||
lbAngleMin.Text = "-";
|
||||
lbAngleMax.Text = "-";
|
||||
|
||||
// Quality labels
|
||||
lbQualAlphaMin.Text = "-";
|
||||
lbQualAlphaAve.Text = "-";
|
||||
lbQualAspectMin.Text = "-";
|
||||
lbQualAspectAve.Text = "-";
|
||||
|
||||
angleHistogram1.SetData(null, null);
|
||||
}
|
||||
|
||||
public void HandleMeshImport(IPolygon geometry, Mesh mesh)
|
||||
{
|
||||
// Previous mesh stats
|
||||
lbNumVert2.Text = "-";
|
||||
lbNumTri2.Text = "-";
|
||||
lbNumSeg2.Text = "-";
|
||||
}
|
||||
|
||||
public void HandleMeshUpdate(Mesh mesh)
|
||||
{
|
||||
// Previous mesh stats
|
||||
lbNumVert2.Text = lbNumVert.Text;
|
||||
lbNumTri2.Text = lbNumTri.Text;
|
||||
lbNumSeg2.Text = lbNumSeg.Text;
|
||||
}
|
||||
|
||||
public void HandleMeshChange(Mesh mesh)
|
||||
{
|
||||
// New mesh stats
|
||||
lbNumVert.Text = mesh.Vertices.Count.ToString();
|
||||
lbNumSeg.Text = mesh.Segments.Count.ToString();
|
||||
lbNumTri.Text = mesh.Triangles.Count.ToString();
|
||||
|
||||
// Update statistics tab
|
||||
angleHistogram1.SetData(statistic.MinAngleHistogram, statistic.MaxAngleHistogram);
|
||||
|
||||
lbAreaMin.Text = Util.DoubleToString(statistic.SmallestArea);
|
||||
lbAreaMax.Text = Util.DoubleToString(statistic.LargestArea);
|
||||
lbEdgeMin.Text = Util.DoubleToString(statistic.ShortestEdge);
|
||||
lbEdgeMax.Text = Util.DoubleToString(statistic.LongestEdge);
|
||||
lbAngleMin.Text = Util.AngleToString(statistic.SmallestAngle);
|
||||
lbAngleMax.Text = Util.AngleToString(statistic.LargestAngle);
|
||||
|
||||
// Update quality
|
||||
if (quality == null)
|
||||
{
|
||||
quality = new QualityMeasure();
|
||||
}
|
||||
|
||||
quality.Update(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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Drawing;
|
||||
|
||||
public class BoundingBox
|
||||
{
|
||||
public float Left;
|
||||
public float Right;
|
||||
public float Bottom;
|
||||
public float Top;
|
||||
|
||||
public float Width
|
||||
{
|
||||
get { return this.Right - this.Left; }
|
||||
}
|
||||
|
||||
public float Height
|
||||
{
|
||||
get { return this.Top - this.Bottom; }
|
||||
}
|
||||
|
||||
public BoundingBox()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public BoundingBox(float left, float right, float bottom, float top)
|
||||
{
|
||||
this.Left = left;
|
||||
this.Right = right;
|
||||
this.Bottom = bottom;
|
||||
this.Top = top;
|
||||
}
|
||||
|
||||
public void Update(Point pt)
|
||||
{
|
||||
this.Update(pt.X, pt.Y);
|
||||
}
|
||||
|
||||
public void Update(PointF pt)
|
||||
{
|
||||
this.Update(pt.X, pt.Y);
|
||||
}
|
||||
|
||||
public void Update(double x, double y)
|
||||
{
|
||||
Update((float)x, (float)y);
|
||||
}
|
||||
|
||||
public void Update(float x, float y)
|
||||
{
|
||||
// Update bounding box
|
||||
if (this.Left > x) this.Left = x;
|
||||
if (this.Right < x) this.Right = x;
|
||||
if (this.Bottom > y) this.Bottom = y;
|
||||
if (this.Top < y) this.Top = y;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.Left = float.MaxValue;
|
||||
this.Right = -float.MaxValue;
|
||||
this.Bottom = float.MaxValue;
|
||||
this.Top = -float.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Buffer
|
||||
{
|
||||
public abstract class BufferBase<T> : IBuffer<T> where T : struct
|
||||
{
|
||||
protected T[] data;
|
||||
protected int size;
|
||||
|
||||
public BufferBase(int capacity, int size)
|
||||
{
|
||||
this.data = new T[capacity];
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public BufferBase(T[] data, int size)
|
||||
{
|
||||
this.data = data;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public T[] Data
|
||||
{
|
||||
get { return data; }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return data == null ? 0 : data.Length; }
|
||||
}
|
||||
|
||||
public abstract int Size
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public abstract BufferTarget Target
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Buffer
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
public class ColorBuffer : BufferBase<Color>
|
||||
{
|
||||
public ColorBuffer(int capacity, int size)
|
||||
: base(capacity, size)
|
||||
{
|
||||
}
|
||||
|
||||
public ColorBuffer(Color[] data, int size)
|
||||
: base(data, size)
|
||||
{
|
||||
}
|
||||
|
||||
public override int Size
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
public override BufferTarget Target
|
||||
{
|
||||
get { return BufferTarget.ColorBuffer; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Buffer
|
||||
{
|
||||
public enum BufferTarget : byte
|
||||
{
|
||||
ColorBuffer,
|
||||
IndexBuffer,
|
||||
VertexBuffer
|
||||
}
|
||||
|
||||
public interface IBuffer<T> where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the contents of the buffer.
|
||||
/// </summary>
|
||||
T[] Data { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the buffer.
|
||||
/// </summary>
|
||||
int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of one element in the buffer (i.e. 2 for 2D points
|
||||
/// or 3 for triangles).
|
||||
/// </summary>
|
||||
int Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the buffer target (vertices or indices).
|
||||
/// </summary>
|
||||
BufferTarget Target { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Buffer
|
||||
{
|
||||
public class IndexBuffer : BufferBase<int>
|
||||
{
|
||||
public IndexBuffer(int capacity, int size)
|
||||
: base(capacity, size)
|
||||
{
|
||||
}
|
||||
|
||||
public IndexBuffer(int[] data, int size)
|
||||
: base(data, size)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of indices for one element (i.e. 2 for segments
|
||||
/// or 3 for triangles).
|
||||
/// </summary>
|
||||
public override int Size
|
||||
{
|
||||
get { return size; }
|
||||
}
|
||||
|
||||
public override BufferTarget Target
|
||||
{
|
||||
get { return BufferTarget.IndexBuffer; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Buffer
|
||||
{
|
||||
public class VertexBuffer : BufferBase<float>
|
||||
{
|
||||
public VertexBuffer(int capacity, int size = 2)
|
||||
: base(capacity, size)
|
||||
{
|
||||
}
|
||||
|
||||
public VertexBuffer(float[] data, int size = 2)
|
||||
: base(data, size)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of coordinates of one vertex in the buffer (i.e. 2 for
|
||||
/// 2D points or 3D points).
|
||||
/// </summary>
|
||||
public override int Size
|
||||
{
|
||||
get { return size; }
|
||||
}
|
||||
|
||||
public override BufferTarget Target
|
||||
{
|
||||
get { return BufferTarget.VertexBuffer; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using TriangleNet.Rendering.Util;
|
||||
|
||||
public class ColorManager
|
||||
{
|
||||
Color background;
|
||||
SolidBrush point;
|
||||
SolidBrush steinerPoint;
|
||||
Pen line;
|
||||
Pen segment;
|
||||
Pen voronoiLine;
|
||||
|
||||
#region Public properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the background color.
|
||||
/// </summary>
|
||||
public Color Background
|
||||
{
|
||||
get { return background; }
|
||||
set { background = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the brush used for points.
|
||||
/// </summary>
|
||||
public SolidBrush Point
|
||||
{
|
||||
get { return point; }
|
||||
set
|
||||
{
|
||||
if (point != null) point.Dispose();
|
||||
point = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the brush used for steiner points.
|
||||
/// </summary>
|
||||
public SolidBrush SteinerPoint
|
||||
{
|
||||
get { return steinerPoint; }
|
||||
set
|
||||
{
|
||||
if (steinerPoint != null) steinerPoint.Dispose();
|
||||
steinerPoint = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pen used for mesh edges.
|
||||
/// </summary>
|
||||
public Pen Line
|
||||
{
|
||||
get { return line; }
|
||||
set
|
||||
{
|
||||
if (line != null) line.Dispose();
|
||||
line = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pen used for mesh segments.
|
||||
/// </summary>
|
||||
public Pen Segment
|
||||
{
|
||||
get { return segment; }
|
||||
set
|
||||
{
|
||||
if (segment != null) segment.Dispose();
|
||||
segment = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pen used for Voronoi edges.
|
||||
/// </summary>
|
||||
public Pen VoronoiLine
|
||||
{
|
||||
get { return voronoiLine; }
|
||||
set
|
||||
{
|
||||
if (voronoiLine != null) voronoiLine.Dispose();
|
||||
voronoiLine = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a dictionary which maps region ids (or partition indices) to a color.
|
||||
/// </summary>
|
||||
public Dictionary<int, Color> ColorDictionary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a colormap which is used for function plotting.
|
||||
/// </summary>
|
||||
public ColorMap ColorMap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of the <see cref="ColorManager"/> class with default (dark) color scheme.
|
||||
/// </summary>
|
||||
public static ColorManager Default()
|
||||
{
|
||||
var colors = new ColorManager();
|
||||
|
||||
colors.Background = Color.FromArgb(0, 0, 0);
|
||||
colors.Point = new SolidBrush(Color.Green);
|
||||
colors.SteinerPoint = new SolidBrush(Color.Peru);
|
||||
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;
|
||||
}
|
||||
|
||||
public void CreateColorDictionary(int length)
|
||||
{
|
||||
var keys = new int[length];
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
keys[i] = i;
|
||||
}
|
||||
|
||||
CreateColorDictionary(keys, length);
|
||||
}
|
||||
|
||||
public void CreateColorDictionary(IEnumerable<int> keys, int length)
|
||||
{
|
||||
this.ColorDictionary = new Dictionary<int, Color>();
|
||||
|
||||
int i = 0, n = regionColors.Length;
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
this.ColorDictionary.Add(key, regionColors[i]);
|
||||
|
||||
i = (i + 1) % n;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Dispose(Dictionary<int, SolidBrush> brushes)
|
||||
{
|
||||
foreach (var brush in brushes.Values)
|
||||
{
|
||||
brush.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal Dictionary<int, SolidBrush> GetBrushDictionary()
|
||||
{
|
||||
var brushes = new Dictionary<int, SolidBrush>();
|
||||
|
||||
foreach (var item in ColorDictionary)
|
||||
{
|
||||
brushes.Add(item.Key, new SolidBrush(item.Value));
|
||||
}
|
||||
|
||||
return brushes;
|
||||
}
|
||||
|
||||
// Change or add as many colors as you like...
|
||||
private static Color[] regionColors = {
|
||||
Color.Transparent,
|
||||
Color.FromArgb(200, 0, 255, 0),
|
||||
Color.FromArgb(200, 255, 0, 0),
|
||||
Color.FromArgb(200, 0, 0, 255),
|
||||
Color.FromArgb(200, 0, 255, 255),
|
||||
Color.FromArgb(200, 255, 255, 0),
|
||||
Color.FromArgb(200, 255, 0, 255),
|
||||
Color.FromArgb(200, 127, 0, 255),
|
||||
Color.FromArgb(200, 0, 127, 255)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Drawing;
|
||||
|
||||
internal static class ExtensionMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Check if segment (a, b) intersects rectangle.
|
||||
/// </summary>
|
||||
public static bool Intersects(this RectangleF rect, PointF a, PointF b)
|
||||
{
|
||||
// TODO: implement intersection.
|
||||
return rect.Contains(a) || rect.Contains(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if triangle (a, b, c) intersects rectangle.
|
||||
/// </summary>
|
||||
public static bool Intersects(this RectangleF rect, PointF a, PointF b, PointF c)
|
||||
{
|
||||
// TODO: implement intersection.
|
||||
return rect.Contains(a) || rect.Contains(b) || rect.Contains(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using TriangleNet.Rendering.GDI.Native;
|
||||
|
||||
public class FunctionRenderer
|
||||
{
|
||||
TriVertex[] points;
|
||||
GradientTriangle[] elements;
|
||||
|
||||
public Graphics RenderTarget { get; set; }
|
||||
|
||||
public IRenderContext Context { get; set; }
|
||||
|
||||
public void Render(IRenderLayer layer)
|
||||
{
|
||||
Create(layer);
|
||||
|
||||
var hdc = RenderTarget.GetHdc();
|
||||
|
||||
NativeMethods.GradientFill(hdc,
|
||||
points, (uint)points.Length, elements, (uint)elements.Length,
|
||||
GradientFillMode.GRADIENT_FILL_TRIANGLE);
|
||||
|
||||
RenderTarget.ReleaseHdc(hdc);
|
||||
}
|
||||
|
||||
private void Create(IRenderLayer layer)
|
||||
{
|
||||
var zoom = Context.Zoom;
|
||||
var colors = layer.Colors.Data;
|
||||
|
||||
int length = colors.Length;
|
||||
|
||||
int size = layer.Points.Size;
|
||||
var data = layer.Points.Data;
|
||||
|
||||
if (length != data.Length / size)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
this.points = new TriVertex[length];
|
||||
|
||||
TriVertex vertex;
|
||||
Color color;
|
||||
PointF p = new PointF((float)data[0], (float)data[1]);
|
||||
|
||||
zoom.WorldToScreen(ref p);
|
||||
|
||||
// Get correction distance
|
||||
float dx = (p.X - (int)p.X) * 2.0f;
|
||||
float dy = (p.Y - (int)p.Y) * 2.0f;
|
||||
|
||||
// Create vertices.
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
p.X = (float)data[size * i];
|
||||
p.Y = (float)data[size * i + 1];
|
||||
|
||||
zoom.WorldToScreen(ref p);
|
||||
|
||||
color = colors[i];
|
||||
|
||||
vertex = new TriVertex();
|
||||
|
||||
vertex.x = (int)(p.X + dx);
|
||||
vertex.y = (int)(p.Y + dy);
|
||||
|
||||
vertex.Red = (ushort)(color.R << 8);
|
||||
vertex.Green = (ushort)(color.G << 8);
|
||||
vertex.Blue = (ushort)(color.B << 8);
|
||||
vertex.Alpha = (ushort)(color.A << 8);
|
||||
|
||||
this.points[i] = vertex;
|
||||
}
|
||||
|
||||
var triangles = layer.Indices.Data;
|
||||
|
||||
length = triangles.Length / 3;
|
||||
|
||||
this.elements = new GradientTriangle[length];
|
||||
|
||||
GradientTriangle e;
|
||||
|
||||
// Create triangles.
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
e = new GradientTriangle();
|
||||
|
||||
e.Vertex1 = (uint)triangles[3 * i];
|
||||
e.Vertex2 = (uint)triangles[3 * i + 1];
|
||||
e.Vertex3 = (uint)triangles[3 * i + 2];
|
||||
|
||||
this.elements[i] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using TriangleNet.Meshing;
|
||||
|
||||
/// <summary>
|
||||
/// Enables rendering of polygons or meshes to a bitmap.
|
||||
/// </summary>
|
||||
public class ImageRenderer
|
||||
{
|
||||
ColorManager colors = LightScheme();
|
||||
|
||||
public ColorManager ColorScheme
|
||||
{
|
||||
get { return colors; }
|
||||
set { colors = value; }
|
||||
}
|
||||
|
||||
public bool EnableRegions { get; set; }
|
||||
|
||||
public bool EnablePoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Export the mesh to PNG format.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The current mesh.</param>
|
||||
/// <param name="width">The desired width (pixel) of the image.</param>
|
||||
/// <param name="file">The PNG filename.</param>
|
||||
/// <param name="regions">Enable rendering of regions.</param>
|
||||
/// <param name="points">Enable rendering of points.</param>
|
||||
public static void Save(IMesh mesh, string file = null, int width = 800,
|
||||
bool regions = false, bool points = true)
|
||||
{
|
||||
// Check file name
|
||||
if (string.IsNullOrWhiteSpace(file))
|
||||
{
|
||||
file = string.Format("mesh-{0}.png", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
|
||||
}
|
||||
|
||||
// Ensure .png extension.
|
||||
if (!file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Path.ChangeExtension(file, ".png");
|
||||
}
|
||||
|
||||
var renderer = new ImageRenderer();
|
||||
|
||||
renderer.EnableRegions = regions;
|
||||
renderer.EnablePoints = points;
|
||||
|
||||
var bitmap = renderer.Render(mesh, width);
|
||||
|
||||
bitmap.Save(file, ImageFormat.Png);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the mesh to a bitmap.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The current mesh.</param>
|
||||
/// <param name="width">The desired width (pixel) of the image.</param>
|
||||
/// <returns>The bitmap.</returns>
|
||||
/// <remarks>
|
||||
/// The width has to be at least 2 * sqrt(n), n the number of vertices.
|
||||
/// Otherwise, an empty bitmap
|
||||
/// </remarks>
|
||||
public Bitmap Render(IMesh mesh, int width = 800)
|
||||
{
|
||||
Bitmap bitmap;
|
||||
|
||||
// Check if the specified width is reasonable
|
||||
if (width < 2 * Math.Sqrt(mesh.Vertices.Count))
|
||||
{
|
||||
return new Bitmap(1, 1);
|
||||
}
|
||||
|
||||
var bounds = mesh.Bounds;
|
||||
|
||||
// World margin on each side
|
||||
float margin = (float)bounds.Height * 0.05f;
|
||||
float scale = width / ((float)bounds.Width + 2 * margin);
|
||||
|
||||
var target = new Rectangle(0, 0, width, (int)((bounds.Height + 2 * margin) * scale));
|
||||
|
||||
bitmap = new Bitmap(width, target.Height, PixelFormat.Format32bppPArgb);
|
||||
|
||||
using (var g = Graphics.FromImage(bitmap))
|
||||
{
|
||||
g.Clear(colors.Background);
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
var context = new RenderContext(new Projection(target), colors);
|
||||
context.Add(mesh, true);
|
||||
|
||||
if (EnableRegions)
|
||||
{
|
||||
context.Add(GetRegions(mesh));
|
||||
}
|
||||
|
||||
if (!EnablePoints)
|
||||
{
|
||||
context.Enable(3, false);
|
||||
}
|
||||
|
||||
var renderer = new LayerRenderer();
|
||||
renderer.Context = context;
|
||||
renderer.RenderTarget = g;
|
||||
renderer.Render();
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private int[] GetRegions(IMesh mesh)
|
||||
{
|
||||
mesh.Renumber();
|
||||
|
||||
var labels = new int[mesh.Triangles.Count];
|
||||
var regions = new SortedSet<int>();
|
||||
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
labels[t.ID] = t.Label;
|
||||
regions.Add(t.Label);
|
||||
}
|
||||
|
||||
if (colors.ColorDictionary == null)
|
||||
{
|
||||
colors.CreateColorDictionary(regions, regions.Count);
|
||||
}
|
||||
|
||||
return labels;
|
||||
}
|
||||
|
||||
public static ColorManager LightScheme()
|
||||
{
|
||||
var colors = new ColorManager();
|
||||
|
||||
colors.Background = Color.White;
|
||||
colors.Point = new SolidBrush(Color.FromArgb(60, 80, 120));
|
||||
colors.SteinerPoint = new SolidBrush(Color.DarkGreen);
|
||||
colors.Line = new Pen(Color.FromArgb(200, 200, 200));
|
||||
colors.Segment = new Pen(Color.SteelBlue);
|
||||
colors.VoronoiLine = new Pen(Color.FromArgb(160, 170, 180));
|
||||
|
||||
return colors;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI
|
||||
{
|
||||
using System.Drawing;
|
||||
|
||||
public class LayerRenderer : IRenderer
|
||||
{
|
||||
MeshRenderer meshRenderer;
|
||||
FunctionRenderer functionRenderer;
|
||||
|
||||
public IRenderContext Context { get; set; }
|
||||
|
||||
public Graphics RenderTarget { get; set; }
|
||||
|
||||
public LayerRenderer()
|
||||
{
|
||||
meshRenderer = new MeshRenderer();
|
||||
functionRenderer = new FunctionRenderer();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
meshRenderer.Context = Context;
|
||||
meshRenderer.RenderTarget = RenderTarget;
|
||||
|
||||
functionRenderer.Context = Context;
|
||||
functionRenderer.RenderTarget = RenderTarget;
|
||||
|
||||
// 0 = mesh (filled)
|
||||
// 1 = mesh (wireframe)
|
||||
// 2 = polygon
|
||||
// 3 = points
|
||||
// 4 = voronoi overlay
|
||||
// 5 = vector field
|
||||
// 6 = contour lines
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (var layer in this.Context.RenderLayers)
|
||||
{
|
||||
if (!layer.IsEmpty() && layer.IsEnabled)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
RenderFilledMesh(layer);
|
||||
break;
|
||||
case 1:
|
||||
RenderMesh(layer);
|
||||
break;
|
||||
case 2:
|
||||
RenderPolygon(layer);
|
||||
break;
|
||||
case 3:
|
||||
RenderPoints(layer);
|
||||
break;
|
||||
case 4:
|
||||
RenderVoronoi(layer);
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderFilledMesh(IRenderLayer layer)
|
||||
{
|
||||
if (layer.Partition != null)
|
||||
{
|
||||
meshRenderer.RenderElements(layer.Points.Data, layer.Indices.Data, 3, layer.Partition.Data);
|
||||
}
|
||||
else if (layer.Colors != null)
|
||||
{
|
||||
functionRenderer.Render(layer);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderMesh(IRenderLayer layer)
|
||||
{
|
||||
if (layer.Indices.Size == 3)
|
||||
{
|
||||
meshRenderer.RenderElements(layer.Points.Data, layer.Indices.Data, 3, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, Context.ColorManager.Line);
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderPolygon(IRenderLayer layer)
|
||||
{
|
||||
meshRenderer.RenderSegments(layer.Points.Data, layer.Indices.Data, Context.ColorManager.Segment);
|
||||
}
|
||||
|
||||
private void RenderPoints(IRenderLayer layer)
|
||||
{
|
||||
meshRenderer.RenderPoints(layer.Points.Data, layer.Points.Size, layer.Count);
|
||||
}
|
||||
|
||||
private void RenderVoronoi(IRenderLayer layer)
|
||||
{
|
||||
if (RenderManager.VORONOI_DEBUG)
|
||||
{
|
||||
meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, Pens.Purple);
|
||||
meshRenderer.RenderPoints(layer.Points.Data, layer.Points.Size, 0, layer.Count, Brushes.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, Context.ColorManager.VoronoiLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="MeshRenderer.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Rendering.GDI
|
||||
{
|
||||
using System.Drawing;
|
||||
using TriangleNet.Rendering.GDI.Native;
|
||||
|
||||
/// <summary>
|
||||
/// Renders a mesh.
|
||||
/// </summary>
|
||||
public class MeshRenderer
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MeshRenderer" /> class.
|
||||
/// </summary>
|
||||
public MeshRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
public Graphics RenderTarget { get; set; }
|
||||
|
||||
public IRenderContext Context { get; set; }
|
||||
|
||||
public void RenderPoints(float[] points, int size, int limit = 0)
|
||||
{
|
||||
int n = points.Length / size;
|
||||
int m = limit > 0 ? limit : n;
|
||||
|
||||
// Draw unchanged points
|
||||
RenderPoints(points, size, 0, m, Context.ColorManager.Point);
|
||||
|
||||
// Draw new (Steiner) points
|
||||
if (limit > 0)
|
||||
{
|
||||
RenderPoints(points, size, m, n, Context.ColorManager.SteinerPoint);
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderPoints(float[] points, int size, int start, int end, Brush brush)
|
||||
{
|
||||
var g = this.RenderTarget;
|
||||
var zoom = this.Context.Zoom;
|
||||
|
||||
int i, k, n = points.Length / size;
|
||||
PointF p = new PointF();
|
||||
|
||||
// Render points
|
||||
for (i = start; i < end; i++)
|
||||
{
|
||||
k = size * i;
|
||||
|
||||
p.X = points[k];
|
||||
p.Y = points[k + 1];
|
||||
|
||||
if (zoom.Viewport.Contains(p))
|
||||
{
|
||||
zoom.WorldToScreen(ref p);
|
||||
g.FillEllipse(brush, p.X - 1.5f, p.Y - 1.5f, 3, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderSegments(float[] points, int[] indices, Pen pen)
|
||||
{
|
||||
RenderLines(points, indices, pen);
|
||||
}
|
||||
|
||||
public void RenderEdges(float[] points, int[] indices, Pen pen)
|
||||
{
|
||||
RenderLines(points, indices, pen);
|
||||
}
|
||||
|
||||
public void RenderElements(float[] points, int[] indices, int size, int[] partition)
|
||||
{
|
||||
var g = this.RenderTarget;
|
||||
var zoom = this.Context.Zoom;
|
||||
|
||||
int n = indices.Length / size;
|
||||
int k0, k1, k2;
|
||||
|
||||
var tri = new PointF[size];
|
||||
|
||||
bool filled = partition != null;
|
||||
|
||||
var brushes = filled ? Context.ColorManager.GetBrushDictionary() : null;
|
||||
|
||||
// TODO: remove hardcoded color
|
||||
var pen = new Pen(Color.FromArgb(20, 20, 20));
|
||||
|
||||
// Draw triangles
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
k0 = 2 * indices[3 * i];
|
||||
k1 = 2 * indices[3 * i + 1];
|
||||
k2 = 2 * indices[3 * i + 2];
|
||||
|
||||
tri[0].X = points[k0];
|
||||
tri[0].Y = points[k0 + 1];
|
||||
|
||||
tri[1].X = points[k1];
|
||||
tri[1].Y = points[k1 + 1];
|
||||
|
||||
tri[2].X = points[k2];
|
||||
tri[2].Y = points[k2 + 1];
|
||||
|
||||
if (zoom.Viewport.Intersects(tri[0], tri[1], tri[2]))
|
||||
{
|
||||
zoom.WorldToScreen(ref tri[0]);
|
||||
zoom.WorldToScreen(ref tri[1]);
|
||||
zoom.WorldToScreen(ref tri[2]);
|
||||
|
||||
if (filled)
|
||||
{
|
||||
var b = brushes[partition[i]];
|
||||
|
||||
if (b.Color.A > 0)
|
||||
{
|
||||
g.FillPolygon(b, tri);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g.DrawPolygon(pen, tri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pen.Dispose();
|
||||
|
||||
if (filled)
|
||||
{
|
||||
Context.ColorManager.Dispose(brushes);
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderLines(float[] points, int[] indices, Pen pen)
|
||||
{
|
||||
var g = this.RenderTarget;
|
||||
var zoom = this.Context.Zoom;
|
||||
|
||||
int n = indices.Length / 2;
|
||||
int k0, k1;
|
||||
|
||||
PointF p0 = new PointF();
|
||||
PointF p1 = new PointF();
|
||||
|
||||
// Draw edges
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
k0 = 2 * indices[2 * i];
|
||||
k1 = 2 * indices[2 * i + 1];
|
||||
|
||||
p0.X = points[k0];
|
||||
p0.Y = points[k0 + 1];
|
||||
|
||||
p1.X = points[k1];
|
||||
p1.Y = points[k1 + 1];
|
||||
|
||||
if (zoom.Viewport.Intersects(p0, p1))
|
||||
{
|
||||
zoom.WorldToScreen(ref p0);
|
||||
zoom.WorldToScreen(ref p1);
|
||||
|
||||
g.DrawLine(pen, p0, p1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI.Native
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies gradient fill mode
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum GradientFillMode : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// In this mode, two endpoints describe a rectangle. The rectangle is defined
|
||||
/// to have a constant color (specified by the TRIVERTEX structure) for the
|
||||
/// left and right edges. GDI interpolates the color from the left to right
|
||||
/// edge and fills the interior
|
||||
/// </summary>
|
||||
GRADIENT_FILL_RECT_H = 0,
|
||||
/// <summary>
|
||||
/// In this mode, two endpoints describe a rectangle. The rectangle is
|
||||
/// defined to have a constant color (specified by the TRIVERTEX structure)
|
||||
/// for the top and bottom edges. GDI interpolates the color from the top
|
||||
/// to bottom edge and fills the interior
|
||||
/// </summary>
|
||||
GRADIENT_FILL_RECT_V = 1,
|
||||
/// <summary>
|
||||
/// In this mode, an array of TRIVERTEX structures is passed to GDI
|
||||
/// along with a list of array indexes that describe separate triangles.
|
||||
/// GDI performs linear interpolation between triangle vertices and fills
|
||||
/// the interior. Drawing is done directly in 24- and 32-bpp modes.
|
||||
/// Dithering is performed in 16-, 8-, 4-, and 1-bpp mode
|
||||
/// </summary>
|
||||
GRADIENT_FILL_TRIANGLE = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI.Native
|
||||
{
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// The GRADIENT_RECT structure specifies the index of two vertices in the
|
||||
/// pVertex array in the GradientFill function. These two vertices form the
|
||||
/// upper-left and lower-right boundaries of a rectangle.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144958.aspx
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct GradientRect
|
||||
{
|
||||
/// <summary>
|
||||
/// The upper-left corner of a rectangle.
|
||||
/// </summary>
|
||||
public uint UpperLeft;
|
||||
|
||||
/// <summary>
|
||||
/// The lower-right corner of a rectangle.
|
||||
/// </summary>
|
||||
public uint LowerRight;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI.Native
|
||||
{
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// The GRADIENT_TRIANGLE structure specifies the index of three
|
||||
/// vertices in the pVertex array in the GradientFill function.
|
||||
/// These three vertices form one triangle
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144959.aspx
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct GradientTriangle
|
||||
{
|
||||
/// <summary>
|
||||
/// The first point of the triangle where sides intersect.
|
||||
/// </summary>
|
||||
public uint Vertex1;
|
||||
|
||||
/// <summary>
|
||||
/// The second point of the triangle where sides intersect.
|
||||
/// </summary>
|
||||
public uint Vertex2;
|
||||
|
||||
/// <summary>
|
||||
/// The third point of the triangle where sides intersect.
|
||||
/// </summary>
|
||||
public uint Vertex3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI.Native
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// PInvoke signatures for GradientFill methods.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Minimum requirements: Windows 2000 Professional
|
||||
///
|
||||
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144957.aspx
|
||||
/// </remarks>
|
||||
internal static class NativeMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// The GradientFill function fills rectangle and triangle structures
|
||||
/// </summary>
|
||||
/// <param name="hdc">Handle to the destination device contex</param>
|
||||
/// <param name="pVertex">Array of TRIVERTEX structures that each define a triangle vertex</param>
|
||||
/// <param name="nVertex">The number of vertices in pVertex</param>
|
||||
/// <param name="pMesh">Array of elements</param>
|
||||
/// <param name="nMesh">The number of elements in pMesh</param>
|
||||
/// <param name="ulMode">Specifies gradient fill mode</param>
|
||||
/// <returns>If the function succeeds, the return value is true, false</returns>
|
||||
public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, uint[] pMesh, uint nMesh,
|
||||
GradientFillMode ulMode)
|
||||
{
|
||||
return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GradientFill function fills rectangle and triangle structures
|
||||
/// </summary>
|
||||
/// <param name="hdc">Handle to the destination device contex</param>
|
||||
/// <param name="pVertex">Array of TRIVERTEX structures that each define a triangle vertex</param>
|
||||
/// <param name="nVertex">The number of vertices in pVertex</param>
|
||||
/// <param name="pMesh">Array of GRADIENT_TRIANGLE structures in triangle mode</param>
|
||||
/// <param name="nMesh">The number of elements in pMesh</param>
|
||||
/// <param name="ulMode">Specifies gradient fill mode</param>
|
||||
/// <returns>If the function succeeds, the return value is true, false</returns>
|
||||
public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, GradientTriangle[] pMesh,
|
||||
uint nMesh, GradientFillMode ulMode)
|
||||
{
|
||||
return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GradientFill function fills rectangle and triangle structures
|
||||
/// </summary>
|
||||
/// <param name="hdc">Handle to the destination device contex</param>
|
||||
/// <param name="pVertex">Array of TRIVERTEX structures that each define a triangle vertex</param>
|
||||
/// <param name="nVertex">The number of vertices in pVertex</param>
|
||||
/// <param name="pMesh">an array of GRADIENT_RECT structures in rectangle mode</param>
|
||||
/// <param name="nMesh">The number of elements in pMesh</param>
|
||||
/// <param name="ulMode">Specifies gradient fill mode</param>
|
||||
/// <returns>If the function succeeds, the return value is true, false</returns>
|
||||
public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, GradientRect[] pMesh,
|
||||
uint nMesh, GradientFillMode ulMode)
|
||||
{
|
||||
return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
|
||||
}
|
||||
|
||||
#region Nested type: Native
|
||||
|
||||
internal class Native
|
||||
{
|
||||
[DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GradientFill([In] IntPtr hdc,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
|
||||
uint nVertex, uint[] pMesh, uint nMesh, GradientFillMode ulMode);
|
||||
|
||||
[DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GradientFill([In] IntPtr hdc,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
|
||||
uint nVertex, GradientRect[] pMesh, uint nMesh, GradientFillMode ulMode);
|
||||
|
||||
[DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GradientFill([In] IntPtr hdc,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
|
||||
uint nVertex, GradientTriangle[] pMesh, uint nMesh, GradientFillMode ulMode);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
namespace TriangleNet.Rendering.GDI.Native
|
||||
{
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// The TRIVERTEX structure contains color information and position information.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145142.aspx
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct TriVertex
|
||||
{
|
||||
/// <summary>
|
||||
/// The x-coordinate, in logical units, of the upper-left corner of the rectangle
|
||||
/// </summary>
|
||||
public int x;
|
||||
|
||||
/// <summary>
|
||||
/// The y-coordinate, in logical units, of the upper-left corner of the rectangle
|
||||
/// </summary>
|
||||
public int y;
|
||||
|
||||
/// <summary>
|
||||
/// The color information at the point of x, y
|
||||
/// </summary>
|
||||
public ushort Red;
|
||||
|
||||
/// <summary>
|
||||
/// The color information at the point of x, y
|
||||
/// </summary>
|
||||
public ushort Green;
|
||||
|
||||
/// <summary>
|
||||
/// The color information at the point of x, y
|
||||
/// </summary>
|
||||
public ushort Blue;
|
||||
|
||||
/// <summary>
|
||||
/// The color information at the point of x, y
|
||||
/// </summary>
|
||||
public ushort Alpha;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="RendererControl.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Rendering.GDI
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Text;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// Renders a mesh using GDI.
|
||||
/// </summary>
|
||||
public class RenderControl : Control, IRenderControl
|
||||
{
|
||||
// Rendering stuff
|
||||
private BufferedGraphics buffer;
|
||||
private BufferedGraphicsContext context;
|
||||
|
||||
//ColorManager renderColors;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
string coordinate = String.Empty;
|
||||
|
||||
Timer timer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RenderControl" /> class.
|
||||
/// </summary>
|
||||
public RenderControl()
|
||||
{
|
||||
//this.SetStyle(ControlStyles.UserPaint, true);
|
||||
//this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
|
||||
//this.SetStyle(ControlStyles.Selectable, true);
|
||||
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
||||
|
||||
//renderColors = ColorManager.Default();
|
||||
|
||||
this.BackColor = Color.Black;
|
||||
|
||||
context = BufferedGraphicsManager.Current;// new BufferedGraphicsContext();
|
||||
|
||||
timer = new Timer();
|
||||
timer.Interval = 3000;
|
||||
timer.Tick += (sender, e) =>
|
||||
{
|
||||
timer.Stop();
|
||||
coordinate = String.Empty;
|
||||
this.Invalidate();
|
||||
};
|
||||
}
|
||||
|
||||
public IRenderer Renderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the graphics buffer (should be called in the forms load event).
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
//zoom.Initialize(this.ClientRectangle);
|
||||
InitializeBuffer();
|
||||
|
||||
initialized = true;
|
||||
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
this.Render();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update graphics buffer and zoom after a resize.
|
||||
/// </summary>
|
||||
public void HandleResize()
|
||||
{
|
||||
var zoom = this.Renderer.Context.Zoom;
|
||||
|
||||
zoom.Resize(this.ClientRectangle);
|
||||
InitializeBuffer();
|
||||
}
|
||||
|
||||
private void InitializeBuffer()
|
||||
{
|
||||
if (this.Width > 0 && this.Height > 0)
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
if (this.ClientRectangle == buffer.Graphics.VisibleClipBounds)
|
||||
{
|
||||
this.Invalidate();
|
||||
|
||||
// Bounds didn't change. Probably we just restored the
|
||||
// window from minimized state.
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.Dispose();
|
||||
}
|
||||
|
||||
//buffer = context.Allocate(Graphics.FromHwnd(this.Handle), this.ClientRectangle);
|
||||
buffer = context.Allocate(this.CreateGraphics(), this.ClientRectangle);
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
this.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
coordinate = String.Empty;
|
||||
|
||||
if (buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var g = buffer.Graphics;
|
||||
var renderer = this.Renderer as LayerRenderer;
|
||||
|
||||
g.Clear(renderer.Context.ColorManager.Background);
|
||||
|
||||
if (!initialized || renderer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
|
||||
renderer.RenderTarget = g;
|
||||
renderer.Render();
|
||||
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
#region Protected overrides
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
base.OnPaint(e);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.Render();
|
||||
|
||||
if (!String.IsNullOrEmpty(coordinate) && Renderer.Context.HasData)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
||||
g.DrawString(coordinate, this.Font, Brushes.White, 10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPaintBackground(PaintEventArgs pevent)
|
||||
{
|
||||
// Do nothing
|
||||
if (!initialized)
|
||||
{
|
||||
base.OnPaintBackground(pevent);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseWheel(MouseEventArgs e)
|
||||
{
|
||||
if (!initialized) return;
|
||||
|
||||
var zoom = this.Renderer.Context.Zoom;
|
||||
|
||||
if (zoom.Zoom(e.Delta, (float)e.X / Width, (float)e.Y / Height))
|
||||
{
|
||||
// Redraw
|
||||
this.Render();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseClick(MouseEventArgs e)
|
||||
{
|
||||
// We need to manually set the focus to get proper handling of
|
||||
// the KeyUp and MouseWheel events.
|
||||
this.Focus();
|
||||
|
||||
if (!initialized) return;
|
||||
|
||||
var zoom = this.Renderer.Context.Zoom;
|
||||
|
||||
if (e.Button == MouseButtons.Middle)
|
||||
{
|
||||
zoom.Reset();
|
||||
this.Render();
|
||||
}
|
||||
else if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
timer.Stop();
|
||||
|
||||
PointF c = new PointF((float)e.X / Width, (float)e.Y / Height);
|
||||
zoom.ScreenToWorld(ref c);
|
||||
coordinate = String.Format(NumberFormatInfo.InvariantInfo,
|
||||
"X:{0} Y:{1}", c.X, c.Y);
|
||||
|
||||
this.Invalidate();
|
||||
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyEventArgs e)
|
||||
{
|
||||
if (!initialized) return;
|
||||
|
||||
var zoom = this.Renderer.Context.Zoom;
|
||||
|
||||
bool redraw = false;
|
||||
|
||||
if (e.KeyCode == Keys.Up)
|
||||
{
|
||||
redraw = zoom.Translate(0, 1);
|
||||
}
|
||||
else if (e.KeyCode == Keys.Down)
|
||||
{
|
||||
redraw = zoom.Translate(0, -1);
|
||||
}
|
||||
else if (e.KeyCode == Keys.Left)
|
||||
{
|
||||
redraw = zoom.Translate(-1, 0);
|
||||
}
|
||||
else if (e.KeyCode == Keys.Right)
|
||||
{
|
||||
redraw = zoom.Translate(1, 0);
|
||||
}
|
||||
|
||||
if (redraw)
|
||||
{
|
||||
this.Render();
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
public interface IRenderContext
|
||||
{
|
||||
ColorManager ColorManager { get; }
|
||||
|
||||
BoundingBox Bounds { get; }
|
||||
|
||||
IList<IRenderLayer> RenderLayers { get; }
|
||||
|
||||
Projection Zoom { get; }
|
||||
|
||||
IMesh Mesh { get; }
|
||||
|
||||
bool HasData { get; }
|
||||
|
||||
void Add(IPolygon data);
|
||||
void Add(IMesh data, bool reset);
|
||||
void Add(ICollection<Point> points, IEnumerable<IEdge> edges, bool reset);
|
||||
|
||||
void Add(float[] values);
|
||||
void Add(int[] partition);
|
||||
|
||||
void Enable(int layer, bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="IMeshRenderer.cs" company="">
|
||||
// TODO: Update copyright text.
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Update summary.
|
||||
/// </summary>
|
||||
public interface IRenderControl
|
||||
{
|
||||
IRenderer Renderer { get; set; }
|
||||
Rectangle ClientRectangle { get; }
|
||||
|
||||
void Initialize();
|
||||
void Refresh();
|
||||
|
||||
void HandleResize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Rendering.Buffer;
|
||||
using TriangleNet.Rendering.Util;
|
||||
|
||||
using Color = System.Drawing.Color;
|
||||
|
||||
public interface IRenderLayer
|
||||
{
|
||||
int Count { get; }
|
||||
|
||||
// Points can be set, because layers may share vertices.
|
||||
IBuffer<float> Points { get; }
|
||||
IBuffer<int> Indices { get; }
|
||||
|
||||
bool IsEnabled { get; set; }
|
||||
|
||||
bool IsEmpty();
|
||||
|
||||
void Reset(bool clear);
|
||||
|
||||
// TODO: add boolean: reset
|
||||
BoundingBox SetPoints(IBuffer<float> buffer);
|
||||
BoundingBox SetPoints(IPolygon poly);
|
||||
BoundingBox SetPoints(IMesh mesh);
|
||||
BoundingBox SetPoints(ICollection<Point> points);
|
||||
void SetPolygon(IPolygon poly);
|
||||
void SetPolygon(IMesh mesh);
|
||||
void SetMesh(IMesh mesh, bool elements);
|
||||
void SetMesh(IEnumerable<IEdge> edges);
|
||||
|
||||
|
||||
// TODO: better put these into a subclass.
|
||||
IBuffer<int> Partition { get; }
|
||||
IBuffer<Color> Colors { get; }
|
||||
|
||||
void AttachLayerData(float[] values, ColorMap colormap);
|
||||
void AttachLayerData(int[] partition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
public interface IRenderer
|
||||
{
|
||||
IRenderContext Context { get; set; }
|
||||
|
||||
void Render();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Projection.cs" company="">
|
||||
// TODO: Update copyright text.
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Manages a world to screen transformation (2D orthographic projection).
|
||||
/// </summary>
|
||||
public class Projection
|
||||
{
|
||||
// The screen.
|
||||
Rectangle screen;
|
||||
|
||||
// The complete mesh.
|
||||
RectangleF world;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current viewport (visible mesh).
|
||||
/// </summary>
|
||||
public RectangleF Viewport { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current scale.
|
||||
/// </summary>
|
||||
public float Scale
|
||||
{
|
||||
get { return screen.Width / Viewport.Width; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the zoom level.
|
||||
/// </summary>
|
||||
public int Level { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a clip margin (default is 5% of viewport width on each side).
|
||||
/// </summary>
|
||||
public float ClipMargin { get; set; }
|
||||
|
||||
// The y-direction of windows screen coordinates is upside down,
|
||||
// so inverY must be set to true.
|
||||
bool invertY = false;
|
||||
|
||||
int maxZoomLevel = 100;
|
||||
|
||||
public Projection(Rectangle screen, bool invertY = true)
|
||||
{
|
||||
this.screen = screen;
|
||||
this.world = screen;
|
||||
this.Viewport = screen;
|
||||
|
||||
this.Level = 1;
|
||||
|
||||
this.ClipMargin = this.Viewport.Width * 0.05f;
|
||||
|
||||
this.invertY = invertY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inititialize the projection.
|
||||
/// </summary>
|
||||
/// <param name="world">The world that should be transformed to screen coordinates.</param>
|
||||
public void Initialize(BoundingBox world)
|
||||
{
|
||||
this.Level = 1;
|
||||
|
||||
// Add a margin so there's some space around the border
|
||||
float worldMargin = (world.Width < world.Height) ? world.Height * 0.05f : world.Width * 0.05f;
|
||||
|
||||
// Get the initial viewport (complete mesh centered on the screen)
|
||||
float screenRatio = screen.Width / (float)screen.Height;
|
||||
float worldRatio = world.Width / world.Height;
|
||||
|
||||
float scale = (world.Width + worldMargin) / screen.Width;
|
||||
|
||||
if (screenRatio > worldRatio)
|
||||
{
|
||||
scale = (world.Height + worldMargin) / screen.Height;
|
||||
}
|
||||
|
||||
float centerX = world.Left + world.Width / 2;
|
||||
float centerY = world.Bottom + world.Height / 2;
|
||||
|
||||
// TODO: Add initial margin
|
||||
this.Viewport = new RectangleF(centerX - screen.Width * scale / 2,
|
||||
centerY - screen.Height * scale / 2,
|
||||
screen.Width * scale,
|
||||
screen.Height * scale);
|
||||
|
||||
this.ClipMargin = this.Viewport.Width * 0.05f;
|
||||
|
||||
this.world = this.Viewport;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle resize of the screen.
|
||||
/// </summary>
|
||||
/// <param name="newScreen">The new screen dimensions.</param>
|
||||
public void Resize(Rectangle newScreen)
|
||||
{
|
||||
// The viewport has to be updated, but we want to keep
|
||||
// the scaling and the center.
|
||||
|
||||
// Get the screen scaling.
|
||||
float scaleX = newScreen.Width / (float)screen.Width;
|
||||
float scaleY = newScreen.Height / (float)screen.Height;
|
||||
|
||||
this.screen = newScreen;
|
||||
|
||||
var view = this.Viewport;
|
||||
|
||||
// Center of the viewport
|
||||
float centerX = (view.Left + view.Right) / 2;
|
||||
float centerY = (view.Bottom + view.Top) / 2;
|
||||
|
||||
// The new viewport dimensions.
|
||||
float width = view.Width * scaleX;
|
||||
float height = view.Height * scaleY;
|
||||
|
||||
this.Viewport = new RectangleF(
|
||||
centerX - width / 2,
|
||||
centerY - height / 2,
|
||||
width, height);
|
||||
|
||||
// Do the same for the world:
|
||||
centerX = (world.Left + world.Right) / 2;
|
||||
centerY = (world.Bottom + world.Top) / 2;
|
||||
|
||||
width = world.Width * scaleX;
|
||||
height = world.Height * scaleY;
|
||||
|
||||
this.world = new RectangleF(
|
||||
centerX - width / 2,
|
||||
centerY - height / 2,
|
||||
width, height);
|
||||
}
|
||||
|
||||
public bool Translate(int dx, int dy)
|
||||
{
|
||||
if (Level == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var view = this.Viewport;
|
||||
|
||||
float x = view.X + dx * view.Width / 4;
|
||||
float y = view.Y + dy * view.Height / 4;
|
||||
|
||||
this.Viewport = new RectangleF(x, y, view.Width, view.Height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zoom in or out of the viewport.
|
||||
/// </summary>
|
||||
/// <param name="amount">Zoom amount</param>
|
||||
/// <param name="focusX">Relative x point position</param>
|
||||
/// <param name="focusY">Relative y point position</param>
|
||||
public bool Zoom(int amount, float focusX, float focusY)
|
||||
{
|
||||
float width, height;
|
||||
|
||||
if (invertY)
|
||||
{
|
||||
focusY = 1 - focusY;
|
||||
}
|
||||
|
||||
if (amount > 0) // Zoom in
|
||||
{
|
||||
this.Level++;
|
||||
|
||||
if (this.Level > maxZoomLevel)
|
||||
{
|
||||
this.Level = maxZoomLevel;
|
||||
return false;
|
||||
}
|
||||
|
||||
width = Viewport.Width / 1.1f;
|
||||
height = Viewport.Height / 1.1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Level--;
|
||||
|
||||
if (this.Level < 1)
|
||||
{
|
||||
this.Level = 1;
|
||||
this.Viewport = this.world;
|
||||
return false;
|
||||
}
|
||||
|
||||
width = Viewport.Width * 1.1f;
|
||||
height = Viewport.Height * 1.1f;
|
||||
}
|
||||
|
||||
// Current focus on viewport
|
||||
float x = Viewport.X + Viewport.Width * focusX;
|
||||
float y = Viewport.Y + Viewport.Height * focusY;
|
||||
|
||||
// New left and top positions
|
||||
x = x - width * focusX;
|
||||
y = y - height * focusY;
|
||||
|
||||
// Check if outside of world
|
||||
if (x < world.X)
|
||||
{
|
||||
x = world.X;
|
||||
}
|
||||
else if (x + width > world.Right)
|
||||
{
|
||||
x = world.Right - width;
|
||||
}
|
||||
|
||||
if (y < world.Y)
|
||||
{
|
||||
y = world.Y;
|
||||
}
|
||||
else if (y + height > world.Bottom)
|
||||
{
|
||||
y = world.Bottom - height;
|
||||
}
|
||||
|
||||
// Set new viewport
|
||||
this.Viewport = new RectangleF(x, y, width, height);
|
||||
|
||||
this.ClipMargin = this.Viewport.Width * 0.05f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.Viewport = this.world;
|
||||
this.Level = 1;
|
||||
}
|
||||
|
||||
public void WorldToScreen(ref PointF pt)
|
||||
{
|
||||
pt.X = (pt.X - Viewport.X) / Viewport.Width * screen.Width;
|
||||
pt.Y = (1 - (pt.Y - Viewport.Y) / Viewport.Height) * screen.Height;
|
||||
}
|
||||
|
||||
public void ScreenToWorld(ref PointF pt)
|
||||
{
|
||||
pt.X = Viewport.X + Viewport.Width * pt.X;
|
||||
pt.Y = Viewport.Y + Viewport.Height * (1 - pt.Y);
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public PointF WorldToScreen(float x, float y)
|
||||
{
|
||||
return new PointF((x - Viewport.X) / Viewport.Width * screen.Width,
|
||||
(1 - (y - Viewport.Y) / Viewport.Height) * screen.Height);
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public PointF ScreenToWorld(float x, float y)
|
||||
{
|
||||
return new PointF(Viewport.X + Viewport.Width * x,
|
||||
Viewport.Y + Viewport.Height * (1 - y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Triangle.Rendering")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Triangle.Rendering")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("14f2491b-ee62-41e4-ab93-206540302ece")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Voronoi.Legacy;
|
||||
|
||||
/// <summary>
|
||||
/// The RenderContext class brings all the rendering parts together.
|
||||
/// </summary>
|
||||
public class RenderContext : IRenderContext
|
||||
{
|
||||
private ColorManager colorManager;
|
||||
private BoundingBox bounds;
|
||||
private Projection zoom;
|
||||
private IMesh mesh;
|
||||
|
||||
private List<IRenderLayer> renderLayers;
|
||||
|
||||
public RenderContext(Projection zoom, ColorManager colorManager)
|
||||
{
|
||||
bounds = new BoundingBox();
|
||||
|
||||
renderLayers = new List<IRenderLayer>(6);
|
||||
|
||||
renderLayers.Add(new RenderLayer()); // 0 = mesh (filled)
|
||||
renderLayers.Add(new RenderLayer()); // 1 = mesh (wireframe)
|
||||
renderLayers.Add(new RenderLayer()); // 2 = polygon
|
||||
renderLayers.Add(new RenderLayer()); // 3 = points
|
||||
renderLayers.Add(new RenderLayer()); // 4 = voronoi overlay
|
||||
renderLayers.Add(new RenderLayer()); // 5 = vector field
|
||||
renderLayers.Add(new RenderLayer()); // 6 = contour lines
|
||||
|
||||
RenderLayers[1].IsEnabled = true;
|
||||
RenderLayers[2].IsEnabled = true;
|
||||
RenderLayers[3].IsEnabled = true;
|
||||
|
||||
this.zoom = zoom;
|
||||
this.colorManager = colorManager;
|
||||
}
|
||||
|
||||
public ColorManager ColorManager
|
||||
{
|
||||
get { return colorManager; }
|
||||
}
|
||||
|
||||
public BoundingBox Bounds
|
||||
{
|
||||
get { return bounds; }
|
||||
}
|
||||
|
||||
public IList<IRenderLayer> RenderLayers
|
||||
{
|
||||
get { return renderLayers; }
|
||||
}
|
||||
|
||||
public Projection Zoom
|
||||
{
|
||||
get { return zoom; }
|
||||
}
|
||||
|
||||
public IMesh Mesh
|
||||
{
|
||||
get { return mesh; }
|
||||
}
|
||||
|
||||
public bool HasData
|
||||
{
|
||||
get
|
||||
{
|
||||
return renderLayers.Any(layer => !layer.IsEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(IPolygon data)
|
||||
{
|
||||
foreach (var layer in RenderLayers)
|
||||
{
|
||||
layer.Reset(true);
|
||||
}
|
||||
|
||||
// Always clear voronoi layer.
|
||||
RenderLayers[4].Reset(true);
|
||||
|
||||
int i = 0;
|
||||
|
||||
// Ensure linear numbering of polygon vertices.
|
||||
foreach (var p in data.Points)
|
||||
{
|
||||
p.ID = i++;
|
||||
}
|
||||
|
||||
this.bounds = RenderLayers[2].SetPoints(data);
|
||||
this.zoom.Initialize(bounds);
|
||||
|
||||
RenderLayers[2].SetPolygon(data);
|
||||
RenderLayers[3].SetPoints(RenderLayers[2].Points);
|
||||
}
|
||||
|
||||
public void Add(IMesh data, bool reset)
|
||||
{
|
||||
foreach (var layer in RenderLayers)
|
||||
{
|
||||
layer.Reset(reset);
|
||||
}
|
||||
|
||||
// Always clear voronoi layer.
|
||||
RenderLayers[4].Reset(true);
|
||||
|
||||
// Save reference to mesh.
|
||||
this.mesh = data;
|
||||
|
||||
this.bounds = RenderLayers[1].SetPoints(data);
|
||||
this.zoom.Initialize(bounds);
|
||||
|
||||
RenderLayers[1].SetMesh(data, false);
|
||||
|
||||
RenderLayers[2].SetPoints(RenderLayers[1].Points);
|
||||
RenderLayers[2].SetPolygon(data);
|
||||
|
||||
RenderLayers[3].SetPoints(RenderLayers[1].Points);
|
||||
}
|
||||
|
||||
public void Add(ICollection<Point> points, IEnumerable<IEdge> edges, bool reset)
|
||||
{
|
||||
RenderLayers[4].SetPoints(points);
|
||||
RenderLayers[4].SetMesh(edges);
|
||||
RenderLayers[4].IsEnabled = true;
|
||||
}
|
||||
|
||||
public void Add(float[] data)
|
||||
{
|
||||
// Add function values for filled mesh.
|
||||
RenderLayers[0].SetPoints(RenderLayers[1].Points);
|
||||
RenderLayers[0].SetMesh(this.mesh, true);
|
||||
RenderLayers[0].AttachLayerData(data, colorManager.ColorMap);
|
||||
|
||||
RenderLayers[0].IsEnabled = true;
|
||||
}
|
||||
|
||||
public void Add(int[] data)
|
||||
{
|
||||
// Add partition data for filled mesh.
|
||||
RenderLayers[0].SetPoints(RenderLayers[1].Points);
|
||||
RenderLayers[0].SetMesh(this.mesh, true);
|
||||
RenderLayers[0].AttachLayerData(data);
|
||||
|
||||
RenderLayers[0].IsEnabled = true;
|
||||
}
|
||||
|
||||
public void Enable(int layer, bool enabled)
|
||||
{
|
||||
renderLayers[layer].IsEnabled = enabled;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Rendering.Buffer;
|
||||
using TriangleNet.Rendering.Util;
|
||||
|
||||
using Color = System.Drawing.Color;
|
||||
|
||||
public class RenderLayer : IRenderLayer
|
||||
{
|
||||
int count;
|
||||
|
||||
protected IBuffer<float> points;
|
||||
protected IBuffer<int> indices;
|
||||
|
||||
protected IBuffer<int> partition;
|
||||
protected IBuffer<Color> colors;
|
||||
|
||||
public RenderLayer()
|
||||
{
|
||||
this.IsEnabled = false;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return count; }
|
||||
}
|
||||
|
||||
public IBuffer<float> Points
|
||||
{
|
||||
get { return points; }
|
||||
set { points = value; }
|
||||
}
|
||||
|
||||
public IBuffer<int> Indices
|
||||
{
|
||||
get { return indices; }
|
||||
}
|
||||
|
||||
public IBuffer<int> Partition
|
||||
{
|
||||
get { return partition; }
|
||||
}
|
||||
|
||||
public IBuffer<Color> Colors
|
||||
{
|
||||
get { return colors; }
|
||||
}
|
||||
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return (points == null || points.Count == 0);
|
||||
}
|
||||
|
||||
public void Reset(bool clear)
|
||||
{
|
||||
if (clear)
|
||||
{
|
||||
count = 0;
|
||||
points = null;
|
||||
}
|
||||
|
||||
indices = null;
|
||||
partition = null;
|
||||
colors = null;
|
||||
}
|
||||
|
||||
public BoundingBox SetPoints(IBuffer<float> buffer)
|
||||
{
|
||||
BoundingBox bounds = new BoundingBox();
|
||||
|
||||
if (points != null && points.Count < buffer.Count)
|
||||
{
|
||||
count = points.Count / points.Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = buffer.Count / buffer.Size;
|
||||
}
|
||||
|
||||
this.points = buffer;
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public BoundingBox SetPoints(IPolygon poly)
|
||||
{
|
||||
BoundingBox bounds = new BoundingBox();
|
||||
|
||||
points = BufferHelper.CreateVertexBuffer(poly.Points, ref bounds);
|
||||
count = points.Count / points.Size;
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public BoundingBox SetPoints(IMesh mesh)
|
||||
{
|
||||
BoundingBox bounds = new BoundingBox();
|
||||
|
||||
points = BufferHelper.CreateVertexBuffer(mesh.Vertices, ref bounds);
|
||||
count = points.Count / points.Size;
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public BoundingBox SetPoints(ICollection<Point> vertices)
|
||||
{
|
||||
BoundingBox bounds = new BoundingBox();
|
||||
|
||||
points = BufferHelper.CreateVertexBuffer(vertices, ref bounds);
|
||||
count = points.Count / points.Size;
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public void SetPolygon(IPolygon poly)
|
||||
{
|
||||
indices = BufferHelper.CreateIndexBuffer(poly.Segments, 2);
|
||||
}
|
||||
|
||||
public void SetPolygon(IMesh mesh)
|
||||
{
|
||||
indices = BufferHelper.CreateIndexBuffer(mesh.Segments, 2);
|
||||
}
|
||||
|
||||
public void SetMesh(IEnumerable<IEdge> edges)
|
||||
{
|
||||
indices = BufferHelper.CreateIndexBuffer(edges, 2);
|
||||
}
|
||||
|
||||
public void SetMesh(IMesh mesh, bool elements)
|
||||
{
|
||||
mesh.Renumber();
|
||||
|
||||
if (!elements)
|
||||
{
|
||||
indices = BufferHelper.CreateIndexBuffer(mesh.Edges, 2);
|
||||
}
|
||||
|
||||
if (elements || indices.Count == 0)
|
||||
{
|
||||
indices = BufferHelper.CreateIndexBuffer(mesh.Triangles, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove colormap argument
|
||||
public void AttachLayerData(float[] values, ColorMap colormap)
|
||||
{
|
||||
int length = values.Length;
|
||||
|
||||
Color[] data = new Color[length];
|
||||
|
||||
double min = double.MaxValue;
|
||||
double max = double.MinValue;
|
||||
|
||||
// Find min and max of given values.
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (values[i] < min)
|
||||
{
|
||||
min = values[i];
|
||||
}
|
||||
|
||||
if (values[i] > max)
|
||||
{
|
||||
max = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
data[i] = colormap.GetColor(values[i], min, max);
|
||||
}
|
||||
|
||||
colors = new ColorBuffer(data, 1);
|
||||
}
|
||||
|
||||
public void AttachLayerData(int[] partition)
|
||||
{
|
||||
this.partition = new IndexBuffer(partition, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
namespace TriangleNet.Rendering
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Rendering.GDI;
|
||||
using TriangleNet.Rendering.Util;
|
||||
|
||||
public class RenderManager
|
||||
{
|
||||
// TODO: delete
|
||||
public static bool VORONOI_DEBUG = false;
|
||||
|
||||
IRenderControl control;
|
||||
IRenderContext context;
|
||||
IRenderer renderer;
|
||||
Projection zoom;
|
||||
|
||||
public IRenderControl Control
|
||||
{
|
||||
get { return control; }
|
||||
}
|
||||
|
||||
public IRenderContext Context
|
||||
{
|
||||
get { return context; }
|
||||
}
|
||||
|
||||
public RenderManager()
|
||||
{
|
||||
}
|
||||
|
||||
public RenderManager(IRenderControl control)
|
||||
{
|
||||
Initialize(control);
|
||||
}
|
||||
|
||||
public RenderManager(IRenderControl control, IRenderer renderer)
|
||||
{
|
||||
Initialize(control, renderer);
|
||||
}
|
||||
|
||||
public void Initialize(IRenderControl control)
|
||||
{
|
||||
Initialize(control, new LayerRenderer());
|
||||
}
|
||||
|
||||
public void Initialize(IRenderControl control, IRenderer renderer)
|
||||
{
|
||||
this.zoom = new Projection(control.ClientRectangle);
|
||||
|
||||
this.context = new RenderContext(zoom, ColorManager.Default());
|
||||
|
||||
this.renderer = renderer;
|
||||
this.renderer.Context = context;
|
||||
|
||||
this.control = control;
|
||||
this.control.Initialize();
|
||||
this.control.Renderer = renderer;
|
||||
}
|
||||
|
||||
public bool TryCreateControl(string assemblyName, IEnumerable<string> dependencies,
|
||||
out IRenderControl control)
|
||||
{
|
||||
if (!ReflectionHelper.TryCreateControl(assemblyName, dependencies, out control))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return control is Control;
|
||||
}
|
||||
|
||||
public void Resize()
|
||||
{
|
||||
control.HandleResize();
|
||||
}
|
||||
|
||||
public void Enable(int layer, bool enabled)
|
||||
{
|
||||
context.Enable(layer, enabled);
|
||||
|
||||
control.Refresh();
|
||||
}
|
||||
|
||||
public void Set(IPolygon data, bool refresh = true)
|
||||
{
|
||||
context.Add(data);
|
||||
|
||||
if (refresh)
|
||||
{
|
||||
control.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(IMesh data, bool reset, bool refresh = true)
|
||||
{
|
||||
context.Add(data, reset);
|
||||
|
||||
if (refresh)
|
||||
{
|
||||
control.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set data for Voronoi layer.
|
||||
/// </summary>
|
||||
public void Set(ICollection<Point> points, IEnumerable<IEdge> edges, bool reset, bool refresh = true)
|
||||
{
|
||||
context.Add(points, edges, reset);
|
||||
|
||||
if (refresh)
|
||||
{
|
||||
control.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(float[] values)
|
||||
{
|
||||
context.Add(values);
|
||||
control.Refresh();
|
||||
}
|
||||
|
||||
public void Update(int[] partition)
|
||||
{
|
||||
context.Add(partition);
|
||||
control.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
static class EdgeIterator
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerate the edges of the mesh.
|
||||
/// </summary>
|
||||
/// <param name="mesh"></param>
|
||||
/// <param name="skipSegments"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// In contrast to the <see cref="TriangleNet.Meshing.Iterators.EdgeIterator"/> this
|
||||
/// method will return objects that include the vertex information (and not only the
|
||||
/// indices).
|
||||
/// </remarks>
|
||||
public static IEnumerable<ISegment> EnumerateEdges(Mesh mesh, bool skipSegments = true)
|
||||
{
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int nid = t.GetNeighborID(i);
|
||||
|
||||
if ((t.ID < nid) || (nid < 0))
|
||||
{
|
||||
var s = t.GetSegment(i);
|
||||
|
||||
if (skipSegments && s == null)
|
||||
{
|
||||
// Since segments will be processed separately, don't
|
||||
// include them in the enumeration.
|
||||
yield return new Segment(
|
||||
t.GetVertex((i + 1) % 3),
|
||||
t.GetVertex((i + 2) % 3));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
yield return new Segment(
|
||||
t.GetVertex((i + 1) % 3),
|
||||
t.GetVertex((i + 2) % 3));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
public class EpsDocument : IDisposable
|
||||
{
|
||||
// Constant to convert from millimeters to PostScript units (1/72th inch).
|
||||
private const double UNITS_PER_MM = 72.0 / 25.4;
|
||||
|
||||
private FormattingStreamWriter _w;
|
||||
private PageSize _size;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the document name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default point size (default = 1).
|
||||
/// </summary>
|
||||
public int DefaultPointSize { get; set; }
|
||||
|
||||
public EpsDocument(string filename, PageSize pageSize)
|
||||
: this(File.Create(filename), pageSize)
|
||||
{
|
||||
Name = Path.GetFileName(filename);
|
||||
}
|
||||
|
||||
public EpsDocument(Stream stream, PageSize pageSize)
|
||||
{
|
||||
_w = new FormattingStreamWriter(stream);
|
||||
_w.NewLine = "\n";
|
||||
|
||||
_size = pageSize;
|
||||
|
||||
DefaultPointSize = 1;
|
||||
}
|
||||
|
||||
public void AddComment(string comment, int line = 1)
|
||||
{
|
||||
for (int i = 0; i < line; i++)
|
||||
{
|
||||
_w.WriteLine("%");
|
||||
}
|
||||
|
||||
var t = comment.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries );
|
||||
|
||||
for (int i = 0; i < t.Length; i++)
|
||||
{
|
||||
_w.WriteLine("% " + t[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < line; i++)
|
||||
{
|
||||
_w.WriteLine("%");
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawPoint(Point p)
|
||||
{
|
||||
_w.WriteLine("{0} {1} P", p.X, p.Y);
|
||||
}
|
||||
|
||||
public void DrawLine(Point p1, Point p2)
|
||||
{
|
||||
_w.WriteLine("{0} {1} {2} {3} L", p1.X, p1.Y, p2.X, p2.Y);
|
||||
}
|
||||
|
||||
public void DrawRectangle(Rectangle rect)
|
||||
{
|
||||
_w.WriteLine("newpath");
|
||||
_w.WriteLine(" {0} {1} moveto", rect.X, rect.Y);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.Right, rect.Y);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.Right, rect.Bottom);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.X, rect.Bottom);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.X, rect.Y);
|
||||
_w.WriteLine("stroke");
|
||||
|
||||
}
|
||||
|
||||
public void SetClip(Rectangle rect)
|
||||
{
|
||||
_w.WriteLine("newpath");
|
||||
_w.WriteLine(" {0} {1} moveto", rect.X, rect.Y);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.Right, rect.Y);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.Right, rect.Bottom);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.X, rect.Bottom);
|
||||
_w.WriteLine(" {0} {1} lineto", rect.X, rect.Y);
|
||||
_w.WriteLine("clip newpath");
|
||||
}
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
_w.WriteLine("{0:0.###} {1:0.###} {2:0.###} setrgbcolor",
|
||||
((float)color.R) / 255f,
|
||||
((float)color.G) / 255f,
|
||||
((float)color.B) / 255f);
|
||||
}
|
||||
|
||||
public void SetStroke(float width)
|
||||
{
|
||||
_w.WriteLine("{0:0.###} setlinewidth", width);
|
||||
}
|
||||
|
||||
public void SetStroke(float width, Color color)
|
||||
{
|
||||
SetColor(color);
|
||||
SetStroke(width);
|
||||
}
|
||||
|
||||
public void WriteHeader()
|
||||
{
|
||||
var x = _size.X; // * UNITS_PER_MM
|
||||
var y = _size.Y;
|
||||
var right = _size.Right;
|
||||
var bottom = _size.Bottom;
|
||||
|
||||
// Write document header.
|
||||
|
||||
_w.WriteLine("%!PS-Adobe-3.0 EPSF-3.0");
|
||||
_w.WriteLine("%%Creator: Triangle.NET");
|
||||
_w.WriteLine("%%Title: {0}", Name);
|
||||
_w.WriteLine("%%Pages: 1");
|
||||
_w.WriteLine("%%BoundingBox: {0} {1} {2} {3}", (int)x, (int)y, (int)right, (int)bottom);
|
||||
_w.WriteLine("%%HiResBoundingBox: {0:0.#####} {1:0.#####} {2:0.#####} {3:0.#####}", x, y, right, bottom);
|
||||
_w.WriteLine("%%Document-Fonts: Times-Roman");
|
||||
_w.WriteLine("%%LanguageLevel: 3");
|
||||
_w.WriteLine("%%EndComments");
|
||||
_w.WriteLine("%%Page: 1 1");
|
||||
_w.WriteLine("save");
|
||||
|
||||
// Define points.
|
||||
_w.WriteLine("% Define points.");
|
||||
_w.WriteLine("/P {");
|
||||
_w.WriteLine("2 dict begin");
|
||||
_w.WriteLine("/y exch def");
|
||||
_w.WriteLine("/x exch def");
|
||||
_w.WriteLine("gsave");
|
||||
_w.WriteLine("newpath x y {0} 0 360 arc fill", DefaultPointSize);
|
||||
_w.WriteLine("grestore");
|
||||
_w.WriteLine("end");
|
||||
_w.WriteLine("} def");
|
||||
|
||||
// Define lines.
|
||||
_w.WriteLine("% Define lines.");
|
||||
_w.WriteLine("/L {");
|
||||
_w.WriteLine("2 dict begin");
|
||||
_w.WriteLine("/y2 exch def");
|
||||
_w.WriteLine("/x2 exch def");
|
||||
_w.WriteLine("/y1 exch def");
|
||||
_w.WriteLine("/x1 exch def");
|
||||
_w.WriteLine("gsave");
|
||||
_w.WriteLine("newpath x1 y1 moveto x2 y2 lineto stroke");
|
||||
_w.WriteLine("grestore");
|
||||
_w.WriteLine("end");
|
||||
_w.WriteLine("} def");
|
||||
}
|
||||
|
||||
private void Close()
|
||||
{
|
||||
_w.WriteLine("%");
|
||||
_w.WriteLine("restore showpage");
|
||||
_w.WriteLine("%%Trailer");
|
||||
_w.WriteLine("%%EOF");
|
||||
}
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
// Has Dispose already been called?
|
||||
bool disposed = false;
|
||||
|
||||
// Public implementation of Dispose pattern callable by consumers.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Protected implementation of Dispose pattern.
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
Close();
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_w.Dispose();
|
||||
_w = null;
|
||||
}
|
||||
|
||||
// Free any unmanaged objects here.
|
||||
//
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
~EpsDocument()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="EpsImage.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// Original Matlab code by John Burkardt, Florida State University
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
using Color = System.Drawing.Color;
|
||||
using IntPoint = System.Drawing.Point;
|
||||
using IntRectangle = System.Drawing.Rectangle;
|
||||
|
||||
/// <summary>
|
||||
/// Writes a mesh to an EPS file.
|
||||
/// </summary>
|
||||
public class EpsImage
|
||||
{
|
||||
// EPS page metrics
|
||||
PageSize ps = new PageSize(36, 126, 576, 666);
|
||||
PageSize clip = new PageSize(18, 108, 594, 684);
|
||||
|
||||
// Mesh metrics
|
||||
double x_max, x_min;
|
||||
double y_max, y_min;
|
||||
|
||||
// TODO: use color manager
|
||||
private static Color ColorPoints = Color.FromArgb(0, 100, 0);
|
||||
private static Color ColorLines = Color.FromArgb(150, 150, 150);
|
||||
private static Color ColorSegments = Color.FromArgb(70, 130, 180);
|
||||
private static Color ColorBorder = Color.FromArgb(230, 230, 230);
|
||||
|
||||
/// <summary>
|
||||
/// Export the mesh to EPS format.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The current mesh.</param>
|
||||
/// <param name="filename">The EPS filename.</param>
|
||||
/// <param name="width">The desired width of the image (currently ignored).</param>
|
||||
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 (var eps = new EpsDocument(filename, ps))
|
||||
{
|
||||
int n = mesh.Vertices.Count;
|
||||
|
||||
// Size of the points.
|
||||
eps.DefaultPointSize = (n < 100) ? 3 : ((n < 500) ? 2 : 1);
|
||||
|
||||
eps.WriteHeader();
|
||||
|
||||
// Draw a gray border around the page.
|
||||
eps.SetColor(ColorBorder);
|
||||
eps.DrawRectangle(GetRectangle(ps));
|
||||
|
||||
// Define a clipping polygon.
|
||||
eps.SetClip(GetRectangle(clip));
|
||||
|
||||
// Draw edges.
|
||||
eps.AddComment("Draw edges.");
|
||||
eps.SetStroke(0.4f, ColorLines);
|
||||
|
||||
foreach (var e in EdgeIterator.EnumerateEdges(mesh))
|
||||
{
|
||||
eps.DrawLine(Transform(e.GetVertex(0)), Transform(e.GetVertex(1)));
|
||||
}
|
||||
|
||||
// Draw Segments.
|
||||
eps.AddComment("Draw Segments.");
|
||||
eps.SetStroke(0.8f, ColorSegments);
|
||||
|
||||
foreach (var s in mesh.Segments)
|
||||
{
|
||||
eps.DrawLine(Transform(s.GetVertex(0)), Transform(s.GetVertex(1)));
|
||||
}
|
||||
|
||||
// Draw points.
|
||||
eps.AddComment("Draw points.");
|
||||
eps.SetColor(ColorPoints);
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
eps.DrawPoint(Transform(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IntRectangle GetRectangle(PageSize size)
|
||||
{
|
||||
return new IntRectangle((int)size.X, (int)size.Y, (int)size.Width, (int)size.Height);
|
||||
}
|
||||
|
||||
private IntPoint Transform(Point p)
|
||||
{
|
||||
return Transform(p.X, p.Y);
|
||||
}
|
||||
|
||||
private IntPoint Transform(double x, double y)
|
||||
{
|
||||
return new IntPoint(
|
||||
(int)Math.Floor(((x_max - x) * ps.X + (x - x_min) * ps.Right) / (x_max - x_min)),
|
||||
(int)Math.Floor(((y_max - y) * ps.Y + (y - y_min) * ps.Bottom) / (y_max - y_min))
|
||||
);
|
||||
}
|
||||
|
||||
private void UpdateMetrics(Rectangle bounds)
|
||||
{
|
||||
x_max = bounds.Right;
|
||||
x_min = bounds.Left;
|
||||
y_max = bounds.Top;
|
||||
y_min = bounds.Bottom;
|
||||
|
||||
// Enlarge width 5% on each side
|
||||
double 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
|
||||
double 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((ps.Right - ps.X) * (y_scale - x_scale) / (2.0 * y_scale));
|
||||
|
||||
ps.Expand(-delta, 0);
|
||||
clip.Expand(-delta, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int delta = (int)Math.Round((ps.Bottom - ps.Y) * (x_scale - y_scale) / (2.0 * x_scale));
|
||||
|
||||
ps.Expand(0, -delta);
|
||||
clip.Expand(0, -delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// From http://stackoverflow.com/questions/12011789/streamwriter-and-iformatprovider
|
||||
/// </remarks>
|
||||
public class FormattingStreamWriter : StreamWriter
|
||||
{
|
||||
private readonly IFormatProvider formatProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified file
|
||||
/// by using the default encoding and buffer size.
|
||||
/// </summary>
|
||||
/// <param name="path">The complete file path to write to.</param>
|
||||
public FormattingStreamWriter(string path)
|
||||
: this(path, CultureInfo.InvariantCulture)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified stream
|
||||
/// by using UTF-8 encoding and the default buffer size.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to write to.</param>
|
||||
public FormattingStreamWriter(Stream stream)
|
||||
: this(stream, CultureInfo.InvariantCulture)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified file
|
||||
/// by using the default encoding and buffer size.
|
||||
/// </summary>
|
||||
/// <param name="path">The complete file path to write to.</param>
|
||||
/// <param name="formatProvider">The format provider.</param>
|
||||
public FormattingStreamWriter(string path, IFormatProvider formatProvider)
|
||||
: base(path)
|
||||
{
|
||||
this.formatProvider = formatProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified stream
|
||||
/// by using UTF-8 encoding and the default buffer size.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to write to.</param>
|
||||
/// <param name="formatProvider">The format provider.</param>
|
||||
public FormattingStreamWriter(Stream stream, IFormatProvider formatProvider)
|
||||
: base(stream)
|
||||
{
|
||||
this.formatProvider = formatProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an object that controls formatting.
|
||||
/// </summary>
|
||||
public override IFormatProvider FormatProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.formatProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Page size in millimeters.
|
||||
/// </summary>
|
||||
public struct PageSize
|
||||
{
|
||||
private const float MM_PER_INCH = 2.54f;
|
||||
|
||||
public static readonly PageSize A3 = new PageSize(297.0f, 420.0f);
|
||||
public static readonly PageSize A4 = new PageSize(210.0f, 297.0f);
|
||||
public static readonly PageSize A5 = new PageSize(148.0f, 210.0f);
|
||||
public static readonly PageSize LETTER = new PageSize(8.5f * MM_PER_INCH, 11.0f * MM_PER_INCH);
|
||||
public static readonly PageSize LEGAL = new PageSize(8.5f * MM_PER_INCH, 14.0f * MM_PER_INCH);
|
||||
|
||||
private float left;
|
||||
private float top;
|
||||
private float right;
|
||||
private float bottom;
|
||||
|
||||
public float X
|
||||
{
|
||||
get { return left; }
|
||||
}
|
||||
|
||||
public float Y
|
||||
{
|
||||
get { return top; }
|
||||
}
|
||||
|
||||
public float Width
|
||||
{
|
||||
get { return right - left; }
|
||||
}
|
||||
|
||||
public float Height
|
||||
{
|
||||
get { return bottom - top; }
|
||||
}
|
||||
|
||||
public float Right
|
||||
{
|
||||
get { return right; }
|
||||
}
|
||||
|
||||
public float Bottom
|
||||
{
|
||||
get { return bottom; }
|
||||
}
|
||||
|
||||
public PageSize(float left, float top, float right, float bottom)
|
||||
{
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public PageSize(float width, float height)
|
||||
: this(0.0f, 0.0f, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
public PageSize(Rectangle size)
|
||||
: this(size.Left, size.Right, size.Top, size.Bottom)
|
||||
{
|
||||
}
|
||||
|
||||
public void Expand(float dx, float dy)
|
||||
{
|
||||
left -= dx;
|
||||
top -= dy;
|
||||
|
||||
right += dx;
|
||||
bottom += dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="SvgImage.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Writes a mesh to an SVG file.
|
||||
/// </summary>
|
||||
public class SvgImage
|
||||
{
|
||||
// Iterations to insert a linebreak in SVG path.
|
||||
private const int LINEBREAK_COUNT = 10;
|
||||
|
||||
float scale = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Export the mesh to SVG format.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The current mesh.</param>
|
||||
/// <param name="filename">The SVG filename.</param>
|
||||
/// <param name="width">The desired width of the image.</param>
|
||||
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);
|
||||
|
||||
int x_offset = -(int)((bounds.Left - margin) * scale);
|
||||
int y_offset = (int)((bounds.Top + margin) * scale);
|
||||
|
||||
int height = (int)((bounds.Height + 2 * margin) * scale);
|
||||
|
||||
using (var svg = new FormattingStreamWriter(filename))
|
||||
{
|
||||
svg.WriteLine("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"");
|
||||
svg.WriteLine("\twidth=\"{0}px\" height=\"{1}px\"", width, height);
|
||||
svg.WriteLine("\tviewBox=\"0 0 {0} {1}\">", width, height);
|
||||
|
||||
svg.WriteLine("<g transform=\"translate({0}, {1}) scale(1,-1)\">", x_offset, y_offset);
|
||||
|
||||
DrawTriangles(svg, mesh, false);
|
||||
//DrawEdges(svg, mesh);
|
||||
|
||||
DrawSegments(svg, mesh);
|
||||
|
||||
DrawPoints(svg, mesh, false);
|
||||
|
||||
svg.WriteLine("</g>");
|
||||
|
||||
svg.WriteLine("</svg>");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTriangles(StreamWriter svg, Mesh mesh, bool label)
|
||||
{
|
||||
svg.Write("\t<path d=\"");
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
Vertex v1, v2, v3;
|
||||
double x1, y1, x2, y2, x3, y3, xa, ya;
|
||||
|
||||
int i = 1;
|
||||
|
||||
foreach (var tri in mesh.Triangles)
|
||||
{
|
||||
v1 = tri.GetVertex(0);
|
||||
v2 = tri.GetVertex(1);
|
||||
v3 = tri.GetVertex(2);
|
||||
|
||||
x1 = scale * v1.X;
|
||||
y1 = scale * v1.Y;
|
||||
x2 = scale * v2.X;
|
||||
y2 = scale * v2.Y;
|
||||
x3 = scale * v3.X;
|
||||
y3 = scale * v3.Y;
|
||||
|
||||
svg.Write("M {0:0.#},{1:0.#} L {2:0.#},{3:0.#} {4:0.#},{5:0.#} Z ",
|
||||
x1, y1, x2, y2, x3, y3);
|
||||
|
||||
if (i % LINEBREAK_COUNT == 0)
|
||||
{
|
||||
svg.WriteLine();
|
||||
svg.Write("\t");
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (label)
|
||||
{
|
||||
xa = (x1 + x2 + x3) / 3.0;
|
||||
ya = (y1 + y2 + y3) / 3.0;
|
||||
|
||||
labels.AppendFormat("<text x=\"{0:0.#}\" y=\"{1:0.#}\">{2}</text>",
|
||||
xa, ya, tri.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
svg.WriteLine("\" style=\"stroke:#c2c2c2; fill:none; stroke-linejoin:bevel;\"/>");
|
||||
|
||||
// Label the triangles.
|
||||
if (label)
|
||||
{
|
||||
svg.WriteLine("\t<g font-family=\"Verdana\" font-size=\"11\" fill=\"black\">");
|
||||
svg.Write(labels.ToString());
|
||||
svg.WriteLine("\t<g/>");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEdges(StreamWriter svg, Mesh mesh)
|
||||
{
|
||||
svg.Write("\t<path d=\"");
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
Vertex v1, v2;
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
int i = 1;
|
||||
|
||||
foreach (var e in EdgeIterator.EnumerateEdges(mesh))
|
||||
{
|
||||
v1 = e.GetVertex(0);
|
||||
v2 = e.GetVertex(1);
|
||||
|
||||
x1 = scale * v1.X;
|
||||
y1 = scale * v1.Y;
|
||||
x2 = scale * v2.X;
|
||||
y2 = scale * v2.Y;
|
||||
|
||||
svg.Write("M {0:0.#},{1:0.#} L {2:0.#},{3:0.#} ",
|
||||
x1, y1, x2, y2);
|
||||
|
||||
if (i % LINEBREAK_COUNT == 0)
|
||||
{
|
||||
svg.WriteLine();
|
||||
svg.Write("\t");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
svg.WriteLine("\" style=\"stroke:#c2c2c2; fill:none; stroke-linejoin:bevel;\"/>");
|
||||
}
|
||||
|
||||
private void DrawSegments(StreamWriter svg, Mesh mesh)
|
||||
{
|
||||
svg.Write("\t<path d=\"");
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
int i = 1;
|
||||
|
||||
foreach (var seg in mesh.Segments)
|
||||
{
|
||||
x1 = scale * seg.GetVertex(0).X;
|
||||
y1 = scale * seg.GetVertex(0).Y;
|
||||
x2 = scale * seg.GetVertex(1).X;
|
||||
y2 = scale * seg.GetVertex(1).Y;
|
||||
|
||||
svg.Write("M {0:0.#},{1:0.#} L {2:0.#},{3:0.#} ",
|
||||
x1, y1, x2, y2);
|
||||
|
||||
if (i % LINEBREAK_COUNT == 0)
|
||||
{
|
||||
svg.WriteLine();
|
||||
svg.Write("\t");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
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.Vertices.Count;
|
||||
|
||||
float circle_size = 1.5f;
|
||||
|
||||
if (n < 100)
|
||||
{
|
||||
circle_size = 3;
|
||||
}
|
||||
else if (n < 500)
|
||||
{
|
||||
circle_size = 2;
|
||||
}
|
||||
|
||||
svg.WriteLine("\t<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("\t\t<circle cx=\"{0:0.#}\" cy=\"{1:0.#}\" r=\"{2:0.#}\" />",
|
||||
x, y, circle_size);
|
||||
|
||||
if (label)
|
||||
{
|
||||
labels.AppendFormat("<text x=\"{0:0.#}\" y=\"{1:0.#}\">{2}</text>",
|
||||
x, y, node.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
svg.WriteLine("\t</g>");
|
||||
|
||||
// Label the nodes.
|
||||
if (label)
|
||||
{
|
||||
svg.WriteLine("\t<g font-family=\"Verdana\" font-size=\"11\" fill=\"black\">");
|
||||
svg.Write(labels.ToString());
|
||||
svg.WriteLine("\t<g/>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{41022E0E-BD0F-439E-BC3A-AABB1B43471B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>TriangleNet.Rendering</RootNamespace>
|
||||
<AssemblyName>Triangle.Rendering</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BoundingBox.cs" />
|
||||
<Compile Include="Buffer\BufferBase.cs" />
|
||||
<Compile Include="Buffer\ColorBuffer.cs" />
|
||||
<Compile Include="Buffer\IBuffer.cs" />
|
||||
<Compile Include="Buffer\IndexBuffer.cs" />
|
||||
<Compile Include="Buffer\VertexBuffer.cs" />
|
||||
<Compile Include="ColorManager.cs" />
|
||||
<Compile Include="ExtensionMethods.cs" />
|
||||
<Compile Include="GDI\FunctionRenderer.cs" />
|
||||
<Compile Include="GDI\ImageRenderer.cs" />
|
||||
<Compile Include="GDI\LayerRenderer.cs" />
|
||||
<Compile Include="GDI\MeshRenderer.cs" />
|
||||
<Compile Include="GDI\Native\GradientFillMode.cs" />
|
||||
<Compile Include="GDI\Native\GradientRect.cs" />
|
||||
<Compile Include="GDI\Native\GradientTriangle.cs" />
|
||||
<Compile Include="GDI\Native\NativeMethods.cs" />
|
||||
<Compile Include="GDI\Native\TriVertex.cs" />
|
||||
<Compile Include="GDI\RenderControl.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="IRenderContext.cs" />
|
||||
<Compile Include="IRenderControl.cs" />
|
||||
<Compile Include="IRenderer.cs" />
|
||||
<Compile Include="IRenderLayer.cs" />
|
||||
<Compile Include="Projection.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RenderContext.cs" />
|
||||
<Compile Include="RenderLayer.cs" />
|
||||
<Compile Include="RenderManager.cs" />
|
||||
<Compile Include="Text\EdgeIterator.cs" />
|
||||
<Compile Include="Text\EpsDocument.cs" />
|
||||
<Compile Include="Text\EpsImage.cs" />
|
||||
<Compile Include="Text\FormattingStreamWriter.cs" />
|
||||
<Compile Include="Text\PageSize.cs" />
|
||||
<Compile Include="Text\SvgImage.cs" />
|
||||
<Compile Include="Util\BufferHelper.cs" />
|
||||
<Compile Include="Util\ColorMap.cs" />
|
||||
<Compile Include="Util\ReflectionHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Triangle\Triangle.csproj">
|
||||
<Project>{f7907a0a-b75f-400b-9e78-bfad00db4d6b}</Project>
|
||||
<Name>Triangle</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,142 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Util
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using TriangleNet.Topology;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Rendering.Buffer;
|
||||
|
||||
internal static class BufferHelper
|
||||
{
|
||||
public static IBuffer<float> CreateVertexBuffer(double[] points, ref BoundingBox bounds)
|
||||
{
|
||||
int length = points.Length;
|
||||
|
||||
var buffer = new VertexBuffer(length);
|
||||
|
||||
bounds.Reset();
|
||||
|
||||
var data = buffer.Data;
|
||||
|
||||
float x, y;
|
||||
|
||||
length = length >> 1;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
x = (float)points[2 * i];
|
||||
y = (float)points[2 * i + 1];
|
||||
|
||||
data[2 * i] = x;
|
||||
data[2 * i + 1] = y;
|
||||
|
||||
bounds.Update(x, y);
|
||||
}
|
||||
|
||||
return buffer as IBuffer<float>;
|
||||
}
|
||||
|
||||
public static IBuffer<float> CreateVertexBuffer(ICollection<Point> points, ref BoundingBox bounds)
|
||||
{
|
||||
var buffer = new VertexBuffer(2 * points.Count);
|
||||
|
||||
bounds.Reset();
|
||||
|
||||
var data = buffer.Data;
|
||||
|
||||
float x, y;
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (var p in points)
|
||||
{
|
||||
x = (float)p.X;
|
||||
y = (float)p.Y;
|
||||
|
||||
data[2 * i] = x;
|
||||
data[2 * i + 1] = y;
|
||||
|
||||
bounds.Update(x, y);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return buffer as IBuffer<float>;
|
||||
}
|
||||
|
||||
public static IBuffer<float> CreateVertexBuffer(ICollection<Vertex> points, ref BoundingBox bounds)
|
||||
{
|
||||
var buffer = new VertexBuffer(2 * points.Count);
|
||||
|
||||
bounds.Reset();
|
||||
|
||||
var data = buffer.Data;
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (var p in points)
|
||||
{
|
||||
data[2 * i] = (float)p.X;
|
||||
data[2 * i + 1] = (float)p.Y;
|
||||
|
||||
bounds.Update(p.X, p.Y);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return buffer as IBuffer<float>;
|
||||
}
|
||||
|
||||
public static IBuffer<int> CreateIndexBuffer(IList<IEdge> segments, int size)
|
||||
{
|
||||
var buffer = new IndexBuffer(size * segments.Count, size);
|
||||
|
||||
var data = buffer.Data;
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (var e in segments)
|
||||
{
|
||||
data[size * i + 0] = e.P0;
|
||||
data[size * i + 1] = e.P1;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return buffer as IBuffer<int>;
|
||||
}
|
||||
|
||||
public static IBuffer<int> CreateIndexBuffer(IEnumerable<IEdge> edges, int size)
|
||||
{
|
||||
var data = new List<int>();
|
||||
|
||||
foreach (var e in edges)
|
||||
{
|
||||
data.Add(e.P0);
|
||||
data.Add(e.P1);
|
||||
}
|
||||
|
||||
return new IndexBuffer(data.ToArray(), size) as IBuffer<int>;
|
||||
}
|
||||
|
||||
public static IBuffer<int> CreateIndexBuffer(ICollection<Triangle> elements, int size)
|
||||
{
|
||||
var buffer = new IndexBuffer(size * elements.Count, size);
|
||||
|
||||
var data = buffer.Data;
|
||||
|
||||
int i = 0;
|
||||
|
||||
foreach (var e in elements)
|
||||
{
|
||||
data[size * i + 0] = e.GetVertexID(0);
|
||||
data[size * i + 1] = e.GetVertexID(1);
|
||||
data[size * i + 2] = e.GetVertexID(2);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return buffer as IBuffer<int>;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Util
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
public class ColorMap
|
||||
{
|
||||
#region Colormap definitions
|
||||
|
||||
public static ColorMap Jet(int size)
|
||||
{
|
||||
ColorMap map = new ColorMap(size);
|
||||
float v, step = 1.0f / (size - 1);
|
||||
float[] rgb = new float[3];
|
||||
|
||||
for (int i = 0; i < size; i += 1)
|
||||
{
|
||||
v = 4 * i * step;
|
||||
|
||||
rgb[0] = Math.Min(v - 1.5f, 4.5f - v);
|
||||
rgb[1] = Math.Min(v - 0.5f, 3.5f - v);
|
||||
rgb[2] = Math.Min(v + 0.5f, 2.5f - v);
|
||||
|
||||
Clamp(rgb, 0.0f, 1.0f);
|
||||
|
||||
map.colors[size - i - 1] = ColorFromRgb(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public static ColorMap Hot(int size)
|
||||
{
|
||||
ColorMap map = new ColorMap(size);
|
||||
float v, step = 1.0f / (size - 1);
|
||||
float[] rgb = new float[3];
|
||||
|
||||
for (int i = 0; i < size; i += 1)
|
||||
{
|
||||
v = 2.5f * i * step;
|
||||
|
||||
rgb[0] = v;
|
||||
rgb[1] = v - 1;
|
||||
rgb[2] = 2 * v - 4;
|
||||
|
||||
Clamp(rgb, 0.0f, 1.0f);
|
||||
|
||||
map.colors[i] = ColorFromRgb(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper
|
||||
|
||||
private static Color ColorFromRgb(float r, float g, float b)
|
||||
{
|
||||
byte max = byte.MaxValue;
|
||||
|
||||
return Color.FromArgb((byte)(r * max), (byte)(g * max), (byte)(b * max));
|
||||
}
|
||||
|
||||
private static void Clamp(float[] values, float min, float max)
|
||||
{
|
||||
int n = values.Length;
|
||||
|
||||
for (int i = 0; i < n; i += 1)
|
||||
{
|
||||
values[i] = Math.Min(max, Math.Max(min, values[i]));
|
||||
}
|
||||
}
|
||||
|
||||
private static int Clamp(int index, int max)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
else if (index > max)
|
||||
{
|
||||
index = max;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Color[] colors;
|
||||
|
||||
private ColorMap(int size)
|
||||
{
|
||||
this.colors = new Color[size];
|
||||
}
|
||||
|
||||
public ColorMap(Color[] colors)
|
||||
{
|
||||
this.colors = colors;
|
||||
}
|
||||
|
||||
public Color GetColor(double value, double min, double max)
|
||||
{
|
||||
int n = this.colors.Length;
|
||||
int i = (int)Math.Floor(n * (max - value) / (max - min));
|
||||
|
||||
return this.colors[Clamp(i, n - 1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Util
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
internal static class ReflectionHelper
|
||||
{
|
||||
public static bool TryCreateControl(string assemblyName, IEnumerable<string> dependencies,
|
||||
out IRenderControl control)
|
||||
{
|
||||
return TryCreateControl(assemblyName, dependencies, null, out control);
|
||||
}
|
||||
|
||||
public static bool TryCreateControl(string assemblyName, IEnumerable<string> dependencies,
|
||||
string className, out IRenderControl control)
|
||||
{
|
||||
control = null;
|
||||
|
||||
if (!FilesExist(assemblyName, dependencies))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
assemblyName = Path.GetFileNameWithoutExtension(assemblyName);
|
||||
|
||||
// Try create render control instance.
|
||||
try
|
||||
{
|
||||
// Load the assembly into the current application domain.
|
||||
var assembly = Assembly.Load(assemblyName);
|
||||
|
||||
// Get all types implementing the IRenderControl interface.
|
||||
var type = typeof(IRenderControl);
|
||||
var matches = assembly.GetTypes().Where(s => type.IsAssignableFrom(s));
|
||||
|
||||
var match = string.IsNullOrEmpty(className) ? matches.FirstOrDefault()
|
||||
: matches.Where(s => s.Name == className).FirstOrDefault();
|
||||
|
||||
if (match != null)
|
||||
{
|
||||
// Create an instance.
|
||||
control = (IRenderControl)Activator.CreateInstance(match);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if render control was successfully created.
|
||||
return (control != null);
|
||||
}
|
||||
|
||||
private static bool FilesExist(string assemblyName, IEnumerable<string> dependencies)
|
||||
{
|
||||
// Check if assembly exists
|
||||
if (!File.Exists(assemblyName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if dependencies exists
|
||||
if (dependencies != null)
|
||||
{
|
||||
foreach (var item in dependencies)
|
||||
{
|
||||
if (!File.Exists(item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Triangle", "Triangle\Triangle.csproj", "{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mesh Explorer", "TestApp\Mesh Explorer.csproj", "{336AAF8A-5316-4303-9E73-5E38BD0B28AF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Triangle.Rendering", "Triangle.Rendering\Triangle.Rendering.csproj", "{41022E0E-BD0F-439E-BC3A-AABB1B43471B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(TeamFoundationVersionControl) = preSolution
|
||||
SccNumberOfProjects = 4
|
||||
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
|
||||
SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs06
|
||||
SccLocalPath0 = .
|
||||
SccProjectUniqueName1 = Triangle\\Triangle.csproj
|
||||
SccProjectName1 = Triangle
|
||||
SccLocalPath1 = Triangle
|
||||
SccProjectUniqueName2 = TestApp\\Mesh\u0020Explorer.csproj
|
||||
SccProjectName2 = TestApp
|
||||
SccLocalPath2 = TestApp
|
||||
SccProjectUniqueName3 = Triangle.Rendering\\Triangle.Rendering.csproj
|
||||
SccProjectName3 = Triangle.Rendering
|
||||
SccLocalPath3 = Triangle.Rendering
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|x86.Build.0 = Debug|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|x86.ActiveCfg = Release|x86
|
||||
{336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|x86.Build.0 = Release|x86
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,248 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Behavior.cs">
|
||||
// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
/// <summary>
|
||||
/// Controls the behavior of the meshing software.
|
||||
/// </summary>
|
||||
class Behavior
|
||||
{
|
||||
bool poly = false;
|
||||
bool quality = false;
|
||||
bool varArea = false;
|
||||
bool convex = false;
|
||||
bool jettison = false;
|
||||
bool boundaryMarkers = true;
|
||||
bool noHoles = false;
|
||||
bool conformDel = false;
|
||||
|
||||
Func<ITriangle, double, bool> usertest;
|
||||
|
||||
int noBisect = 0;
|
||||
|
||||
double minAngle = 0.0;
|
||||
double maxAngle = 0.0;
|
||||
double maxArea = -1.0;
|
||||
|
||||
internal bool fixedArea = false;
|
||||
internal bool useSegments = true;
|
||||
internal bool useRegions = false;
|
||||
internal double goodAngle = 0.0;
|
||||
internal double maxGoodAngle = 0.0;
|
||||
internal double offconstant = 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of the Behavior class.
|
||||
/// </summary>
|
||||
public Behavior(bool quality = false, double minAngle = 20.0)
|
||||
{
|
||||
if (quality)
|
||||
{
|
||||
this.quality = true;
|
||||
this.minAngle = minAngle;
|
||||
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update quality options dependencies.
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
this.quality = true;
|
||||
|
||||
if (this.minAngle < 0 || this.minAngle > 60)
|
||||
{
|
||||
this.minAngle = 0;
|
||||
this.quality = false;
|
||||
|
||||
Log.Instance.Warning("Invalid quality option (minimum angle).", "Mesh.Behavior");
|
||||
}
|
||||
|
||||
if ((this.maxAngle != 0.0) && (this.maxAngle < 60 || this.maxAngle > 180))
|
||||
{
|
||||
this.maxAngle = 0;
|
||||
this.quality = false;
|
||||
|
||||
Log.Instance.Warning("Invalid quality option (maximum angle).", "Mesh.Behavior");
|
||||
}
|
||||
|
||||
this.useSegments = this.Poly || this.Quality || this.Convex;
|
||||
this.goodAngle = Math.Cos(this.MinAngle * Math.PI / 180.0);
|
||||
this.maxGoodAngle = Math.Cos(this.MaxAngle * Math.PI / 180.0);
|
||||
|
||||
if (this.goodAngle == 1.0)
|
||||
{
|
||||
this.offconstant = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.offconstant = 0.475 * Math.Sqrt((1.0 + this.goodAngle) / (1.0 - this.goodAngle));
|
||||
}
|
||||
|
||||
this.goodAngle *= this.goodAngle;
|
||||
}
|
||||
|
||||
#region Static properties
|
||||
|
||||
/// <summary>
|
||||
/// No exact arithmetic.
|
||||
/// </summary>
|
||||
public static bool NoExact { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
|
||||
/// <summary>
|
||||
/// Quality mesh generation.
|
||||
/// </summary>
|
||||
public bool Quality
|
||||
{
|
||||
get { return quality; }
|
||||
set
|
||||
{
|
||||
quality = value;
|
||||
if (quality)
|
||||
{
|
||||
Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum angle constraint.
|
||||
/// </summary>
|
||||
public double MinAngle
|
||||
{
|
||||
get { return minAngle; }
|
||||
set { minAngle = value; Update(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum angle constraint.
|
||||
/// </summary>
|
||||
public double MaxAngle
|
||||
{
|
||||
get { return maxAngle; }
|
||||
set { maxAngle = value; Update(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum area constraint.
|
||||
/// </summary>
|
||||
public double MaxArea
|
||||
{
|
||||
get { return maxArea; }
|
||||
set
|
||||
{
|
||||
maxArea = value;
|
||||
fixedArea = value > 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a maximum triangle area constraint.
|
||||
/// </summary>
|
||||
public bool VarArea
|
||||
{
|
||||
get { return varArea; }
|
||||
set { varArea = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input is a Planar Straight Line Graph.
|
||||
/// </summary>
|
||||
public bool Poly
|
||||
{
|
||||
get { return poly; }
|
||||
set { poly = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a user-defined triangle constraint.
|
||||
/// </summary>
|
||||
public Func<ITriangle, double, bool> UserTest
|
||||
{
|
||||
get { return usertest; }
|
||||
set { usertest = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enclose the convex hull with segments.
|
||||
/// </summary>
|
||||
public bool Convex
|
||||
{
|
||||
get { return convex; }
|
||||
set { convex = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conforming Delaunay (all triangles are truly Delaunay).
|
||||
/// </summary>
|
||||
public bool ConformingDelaunay
|
||||
{
|
||||
get { return conformDel; }
|
||||
set { conformDel = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suppresses boundary segment splitting.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 0 = split segments
|
||||
/// 1 = no new vertices on the boundary
|
||||
/// 2 = prevent all segment splitting, including internal boundaries
|
||||
/// </remarks>
|
||||
public int NoBisect
|
||||
{
|
||||
get { return noBisect; }
|
||||
set
|
||||
{
|
||||
noBisect = value;
|
||||
if (noBisect < 0 || noBisect > 2)
|
||||
{
|
||||
noBisect = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute boundary information.
|
||||
/// </summary>
|
||||
public bool UseBoundaryMarkers
|
||||
{
|
||||
get { return boundaryMarkers; }
|
||||
set { boundaryMarkers = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignores holes in polygons.
|
||||
/// </summary>
|
||||
public bool NoHoles
|
||||
{
|
||||
get { return noHoles; }
|
||||
set { noHoles = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Jettison unused vertices from output.
|
||||
/// </summary>
|
||||
public bool Jettison
|
||||
{
|
||||
get { return jettison; }
|
||||
set { jettison = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="Configuration.cs" company="">
|
||||
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Meshing;
|
||||
using TriangleNet.Meshing.Algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Configure advanced aspects of the library.
|
||||
/// </summary>
|
||||
public class Configuration
|
||||
{
|
||||
public Configuration()
|
||||
: this(() => RobustPredicates.Default, () => new TrianglePool())
|
||||
{
|
||||
}
|
||||
|
||||
public Configuration(Func<IPredicates> predicates)
|
||||
: this(predicates, () => new TrianglePool())
|
||||
{
|
||||
}
|
||||
|
||||
public Configuration(Func<IPredicates> predicates, Func<TrianglePool> trianglePool)
|
||||
{
|
||||
Predicates = predicates;
|
||||
TrianglePool = trianglePool;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the factory method for the <see cref="IPredicates"/> implementation.
|
||||
/// </summary>
|
||||
public Func<IPredicates> Predicates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the factory method for the <see cref="TrianglePool"/>.
|
||||
/// </summary>
|
||||
public Func<TrianglePool> TrianglePool { get; set; }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user