Rename source folder.

This commit is contained in:
wo80
2022-02-13 12:28:55 +01:00
parent 625be1ab8f
commit a088a2f8c5
185 changed files with 38090 additions and 38090 deletions
+207
View File
@@ -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);
}
}
}
+38
View File
@@ -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);
}
}
+190
View File
@@ -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
}
}
+239
View File
@@ -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
}
}
+82
View File
@@ -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);
}
}
}
}
+453
View File
@@ -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
}
}
+190
View File
@@ -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);
}
}
}
+209
View File
@@ -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);
}
}
}
+179
View File
@@ -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;
}
}
}
}
+202
View File
@@ -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;
}
}
+82
View File
@@ -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";
}
}
}
+120
View File
@@ -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>
+242
View File
@@ -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;
}
}
+150
View File
@@ -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;
}
}
}
+120
View File
@@ -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>
+90
View File
@@ -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;
}
}
+139
View File
@@ -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("; ");
}
}
}
}
}
}
+120
View File
@@ -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>
+418
View File
@@ -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;
}
}
+795
View File
@@ -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
}
}
+123
View File
@@ -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>
+112
View File
@@ -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;
}
}
+114
View File
@@ -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);
}
}
}
+120
View File
@@ -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>
+158
View File
@@ -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;
}
}
}
+51
View File
@@ -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;
}
}
}
+64
View File
@@ -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;
}
}
}
+23
View File
@@ -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);
}
}
+55
View File
@@ -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;
}
}
}
+100
View File
@@ -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;
}
}
}
+63
View File
@@ -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;
}
}
}
+19
View File
@@ -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;
}
}
}
+126
View File
@@ -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;
}
}
}
+574
View File
@@ -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
}
}
+83
View File
@@ -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);
}
}
}
+33
View File
@@ -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);
}
}
+88
View File
@@ -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);
}
}
}
}
+408
View File
@@ -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);
}
}
}
+198
View File
@@ -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>
+21
View File
@@ -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());
}
}
}
+36
View File
@@ -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")]
+78
View File
@@ -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
View File
@@ -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
}
}
+283
View File
@@ -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);
}
}
}
}
+79
View File
@@ -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);
}
}
}
+145
View File
@@ -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;
}
}
+47
View File
@@ -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
}
}
+120
View File
@@ -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>
+26
View File
@@ -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
View File
@@ -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;
}
}
+91
View File
@@ -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
}
}
+120
View File
@@ -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
View File
@@ -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;
}
}
+109
View File
@@ -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
}
}
+120
View File
@@ -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>
+68
View File
@@ -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; }
}
}
}
+34
View File
@@ -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; }
}
}
}
+181
View File
@@ -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;
}
}
}
}
+154
View File
@@ -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;
}
}
}
+118
View File
@@ -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);
}
}
}
}
+173
View File
@@ -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;
}
}
+252
View File
@@ -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
}
}
+32
View File
@@ -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);
}
}
+26
View File
@@ -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();
}
}
+44
View File
@@ -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);
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace TriangleNet.Rendering
{
public interface IRenderer
{
IRenderContext Context { get; set; }
void Render();
}
}
+271
View File
@@ -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")]
+162
View File
@@ -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()
{
}
}
}
+188
View File
@@ -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);
}
}
}
+132
View File
@@ -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;
}
}
}
}
}
}
}
}
+208
View File
@@ -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
}
}
+157
View File
@@ -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;
}
}
}
}
+81
View File
@@ -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;
}
}
}
+254
View File
@@ -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>
+142
View File
@@ -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>;
}
}
}
+112
View File
@@ -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;
}
}
}
+69
View File
@@ -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
+248
View File
@@ -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
}
}
+44
View File
@@ -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