Move EPS and SVG writer to Triangle.Rendering project.
git-svn-id: https://triangle.svn.codeplex.com/svn@79411 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
@@ -11,6 +11,7 @@ using TriangleNet.Meshing.Algorithm;
|
||||
using TriangleNet.Rendering;
|
||||
using TriangleNet.Smoothing;
|
||||
using TriangleNet.Voronoi;
|
||||
using TriangleNet.Rendering.Text;
|
||||
|
||||
namespace MeshExplorer
|
||||
{
|
||||
@@ -704,17 +705,17 @@ namespace MeshExplorer
|
||||
|
||||
if (format == 1)
|
||||
{
|
||||
EpsImage eps = new EpsImage();
|
||||
var eps = new EpsImage();
|
||||
eps.Export(this.mesh, export.ImageName, size);
|
||||
}
|
||||
else if (format == 2)
|
||||
{
|
||||
SvgImage svg = new SvgImage();
|
||||
var svg = new SvgImage();
|
||||
svg.Export(this.mesh, export.ImageName, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
RasterImage img = new RasterImage();
|
||||
var img = new RasterImage();
|
||||
img.Export(this.mesh, export.ImageName, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,423 +0,0 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="EpsImage.cs" company="">
|
||||
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
|
||||
// Original Matlab code by John Burkardt, Florida State University
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Geometry;
|
||||
|
||||
using IntPoint = System.Drawing.Point;
|
||||
|
||||
/// <summary>
|
||||
/// Writes a mesh to an EPS file.
|
||||
/// </summary>
|
||||
public class EpsImage
|
||||
{
|
||||
// EPS page metrics
|
||||
int x_ps_max = 576;
|
||||
int x_ps_max_clip = 594;
|
||||
int x_ps_min = 36;
|
||||
int x_ps_min_clip = 18;
|
||||
int y_ps_max = 666;
|
||||
int y_ps_max_clip = 684;
|
||||
int y_ps_min = 126;
|
||||
int y_ps_min_clip = 108;
|
||||
|
||||
// Mesh metrics
|
||||
double x_max, x_min;
|
||||
double y_max, y_min;
|
||||
double x_scale, y_scale;
|
||||
|
||||
/// <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 FormattingStreamWriter(filename))
|
||||
{
|
||||
WriteHeader(filename, eps);
|
||||
|
||||
DrawClip(eps);
|
||||
|
||||
DrawEdges(eps, mesh);
|
||||
|
||||
DrawSegments(eps, mesh);
|
||||
|
||||
DrawPoints(eps, mesh);
|
||||
|
||||
WriteTrailer(eps);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteHeader(string filename, StreamWriter eps)
|
||||
{
|
||||
eps.WriteLine("%!PS-Adobe-3.0 EPSF-3.0");
|
||||
eps.WriteLine("%%Creator: Triangle.NET Mesh Explorer");
|
||||
eps.WriteLine("%%Title: {0}", filename);
|
||||
eps.WriteLine("%%Pages: 1");
|
||||
eps.WriteLine("%%BoundingBox: {0} {1} {2} {3}", x_ps_min, y_ps_min, x_ps_max, y_ps_max);
|
||||
eps.WriteLine("%%Document-Fonts: Times-Roman");
|
||||
eps.WriteLine("%%LanguageLevel: 2");
|
||||
eps.WriteLine("%%EndComments");
|
||||
eps.WriteLine("%%BeginProlog");
|
||||
eps.WriteLine("/inch {72 mul} def");
|
||||
eps.WriteLine("%%EndProlog");
|
||||
eps.WriteLine("%%Page: 1 1");
|
||||
}
|
||||
|
||||
private static void WriteTrailer(StreamWriter eps)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("restore showpage");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% End of page.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("%%Trailer");
|
||||
eps.WriteLine("%%EOF");
|
||||
}
|
||||
|
||||
private void DrawClip(StreamWriter eps)
|
||||
{
|
||||
eps.WriteLine("save");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to very light gray.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.900 0.900 0.900 setrgbcolor");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw a gray border around the page.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("newpath");
|
||||
eps.WriteLine(" {0} {1} moveto", x_ps_min, y_ps_min);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max, y_ps_min);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max, y_ps_max);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min, y_ps_max);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min, y_ps_min);
|
||||
eps.WriteLine("stroke");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to black.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.000 0.000 0.000 setrgbcolor");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the font and its size.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.50 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Print a title.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("%210 702 moveto");
|
||||
eps.WriteLine("%(Triangulation) show");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Define a clipping polygon.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("newpath");
|
||||
eps.WriteLine(" {0} {1} moveto", x_ps_min_clip, y_ps_min_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max_clip, y_ps_min_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_max_clip, y_ps_max_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min_clip, y_ps_max_clip);
|
||||
eps.WriteLine(" {0} {1} lineto", x_ps_min_clip, y_ps_min_clip);
|
||||
eps.WriteLine("clip newpath");
|
||||
}
|
||||
|
||||
private void DrawEdges(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
IntPoint a, b;
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw the triangles (mesh edges).");
|
||||
eps.WriteLine("%");
|
||||
|
||||
SetStroke(eps, 0.6f, 0.6f, 0.6f, 0.4f);
|
||||
|
||||
eps.WriteLine(@"/L {
|
||||
2 dict begin
|
||||
/y2 exch def
|
||||
/x2 exch def
|
||||
/y1 exch def
|
||||
/x1 exch def
|
||||
gsave
|
||||
newpath x1 y1 moveto x2 y2 lineto stroke
|
||||
grestore
|
||||
end
|
||||
} def");
|
||||
|
||||
foreach (var e in EnumerateEdges(mesh))
|
||||
{
|
||||
a = Transform(e.GetVertex(0));
|
||||
b = Transform(e.GetVertex(1));
|
||||
|
||||
eps.WriteLine("{0} {1} {2} {3} L", a.X, a.Y, b.X, b.Y);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSegments(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
IntPoint a, b;
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw the segments.");
|
||||
eps.WriteLine("%");
|
||||
|
||||
SetStroke(eps, 0.27f, 0.5f, 0.7f, 0.8f);
|
||||
|
||||
foreach (var s in mesh.Segments)
|
||||
{
|
||||
a = Transform(s.GetVertex(0));
|
||||
b = Transform(s.GetVertex(1));
|
||||
|
||||
eps.WriteLine("{0} {1} {2} {3} L", a.X, a.Y, b.X, b.Y);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPoints(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
IntPoint p;
|
||||
|
||||
int n = mesh.Vertices.Count;
|
||||
|
||||
// Size of the points.
|
||||
int size = (n < 100) ? 3 : ((n < 500) ? 2 : 1);
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw the vertices.");
|
||||
eps.WriteLine("%");
|
||||
|
||||
SetColor(eps, 0.0f, 0.4f, 0.0f);
|
||||
|
||||
eps.WriteLine(@"/P {
|
||||
2 dict begin
|
||||
/y exch def
|
||||
/x exch def
|
||||
gsave
|
||||
newpath x y 1 0 360 arc fill
|
||||
grestore
|
||||
end
|
||||
} def");
|
||||
|
||||
// TODO: EPS point size.
|
||||
// newpath x y {size} 0 360 arc fill
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
p = Transform(node);
|
||||
|
||||
eps.WriteLine("{0} {1} P", p.X, p.Y);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private void DrawPointLabels(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
int n = mesh.Vertices.Count;
|
||||
|
||||
IntPoint p;
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
p = Transform(node);
|
||||
|
||||
labels.AppendFormat(" {0} {1} moveto ({2}) show", p.X, p.Y + 5, node.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Label the nodes.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to darker blue.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.000 0.250 0.850 setrgbcolor");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.20 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
|
||||
eps.WriteLine(labels.ToString());
|
||||
}
|
||||
|
||||
private void DrawTriangles(StreamWriter eps, Mesh mesh, bool label)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the triangle line color and width.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.6 0.6 0.6 setrgbcolor");
|
||||
eps.WriteLine("0.5 setlinewidth");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw the triangles.");
|
||||
eps.WriteLine("%");
|
||||
|
||||
IntPoint a, b, c;
|
||||
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
a = Transform(t.GetVertex(0));
|
||||
b = Transform(t.GetVertex(1));
|
||||
c = Transform(t.GetVertex(2));
|
||||
|
||||
eps.WriteLine("newpath");
|
||||
|
||||
eps.WriteLine(" {0} {1} moveto", a.X, a.Y);
|
||||
eps.WriteLine(" {0} {1} lineto", b.X, b.Y);
|
||||
eps.WriteLine(" {0} {1} lineto", c.X, c.Y);
|
||||
eps.WriteLine(" {0} {1} lineto", a.X, a.Y);
|
||||
|
||||
eps.WriteLine("stroke");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTriangleLabels(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
var labels = new StringBuilder();
|
||||
|
||||
IntPoint a, b, c;
|
||||
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
a = Transform(t.GetVertex(0));
|
||||
b = Transform(t.GetVertex(1));
|
||||
c = Transform(t.GetVertex(2));
|
||||
|
||||
eps.WriteLine("newpath");
|
||||
|
||||
a = Transform((a.X + b.X + c.X) / 3.0, (a.Y + b.Y + c.Y) / 3.0);
|
||||
|
||||
labels.AppendFormat(" {0} {1} moveto ({2}) show", a.X, a.Y, t.ID);
|
||||
labels.AppendLine();
|
||||
|
||||
eps.WriteLine("stroke");
|
||||
}
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Label the triangles.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to darker red.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.950 0.250 0.150 setrgbcolor");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.20 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
|
||||
eps.WriteLine(labels.ToString());
|
||||
}
|
||||
//*/
|
||||
|
||||
private void SetColor(StreamWriter eps, float r, float g, float b)
|
||||
{
|
||||
eps.WriteLine("{0} {1} {2} setrgbcolor", r, g, b);
|
||||
eps.WriteLine("%");
|
||||
}
|
||||
|
||||
private void SetStroke(StreamWriter eps, float r, float g, float b, float width)
|
||||
{
|
||||
eps.WriteLine("{0} {1} {2} setrgbcolor", r, g, b);
|
||||
eps.WriteLine("{0} setlinewidth", width);
|
||||
eps.WriteLine("%");
|
||||
}
|
||||
|
||||
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) * x_ps_min + (x - x_min) * x_ps_max) / (x_max - x_min)),
|
||||
(int)Math.Floor(((y_max - y) * y_ps_min + (y - y_min) * y_ps_max) / (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
|
||||
x_scale = x_max - x_min;
|
||||
x_max = x_max + 0.05 * x_scale;
|
||||
x_min = x_min - 0.05 * x_scale;
|
||||
x_scale = x_max - x_min;
|
||||
|
||||
// Enlarge height 5% on each side
|
||||
y_scale = y_max - y_min;
|
||||
y_max = y_max + 0.05 * y_scale;
|
||||
y_min = y_min - 0.05 * y_scale;
|
||||
y_scale = y_max - y_min;
|
||||
|
||||
if (x_scale < y_scale)
|
||||
{
|
||||
int delta = (int)Math.Round((x_ps_max - x_ps_min) * (y_scale - x_scale) / (2.0 * y_scale));
|
||||
|
||||
x_ps_max = x_ps_max - delta;
|
||||
x_ps_min = x_ps_min + delta;
|
||||
|
||||
x_ps_max_clip = x_ps_max_clip - delta;
|
||||
x_ps_min_clip = x_ps_min_clip + delta;
|
||||
|
||||
x_scale = y_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
int delta = (int)Math.Round((y_ps_max - y_ps_min) * (x_scale - y_scale) / (2.0 * x_scale));
|
||||
|
||||
y_ps_max = y_ps_max - delta;
|
||||
y_ps_min = y_ps_min + delta;
|
||||
|
||||
y_ps_max_clip = y_ps_max_clip - delta;
|
||||
y_ps_min_clip = y_ps_min_clip + delta;
|
||||
|
||||
y_scale = x_scale;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ISegment> EnumerateEdges(Mesh mesh, bool segments = false)
|
||||
{
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int nid = t.GetNeighborID(i);
|
||||
|
||||
if ((t.ID < nid) || (nid < 0))
|
||||
{
|
||||
if (segments || t.GetSegment(i) == null)
|
||||
{
|
||||
yield return new Segment(
|
||||
t.GetVertex((i + 1) % 3),
|
||||
t.GetVertex((i + 2) % 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
// From http://stackoverflow.com/questions/12011789/streamwriter-and-iformatprovider
|
||||
|
||||
public class FormattingStreamWriter : StreamWriter
|
||||
{
|
||||
private readonly IFormatProvider formatProvider;
|
||||
|
||||
public FormattingStreamWriter(string path)
|
||||
: this(path, CultureInfo.InvariantCulture)
|
||||
{
|
||||
}
|
||||
|
||||
public FormattingStreamWriter(string path, IFormatProvider formatProvider)
|
||||
: base(path)
|
||||
{
|
||||
this.formatProvider = formatProvider;
|
||||
}
|
||||
|
||||
public override IFormatProvider FormatProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.formatProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,7 @@
|
||||
namespace MeshExplorer.IO
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using TriangleNet;
|
||||
using TriangleNet.Rendering;
|
||||
using TriangleNet.Rendering.GDI;
|
||||
|
||||
/// <summary>
|
||||
@@ -20,14 +15,6 @@ namespace MeshExplorer.IO
|
||||
/// </summary>
|
||||
public class RasterImage
|
||||
{
|
||||
ColorManager colors = RasterImage.LightScheme();
|
||||
|
||||
public ColorManager ColorScheme
|
||||
{
|
||||
get { return colors; }
|
||||
set { colors = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the mesh to PNG format.
|
||||
/// </summary>
|
||||
@@ -42,72 +29,7 @@ namespace MeshExplorer.IO
|
||||
filename = String.Format("mesh-{0}.png", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
|
||||
}
|
||||
|
||||
Bitmap bitmap;
|
||||
|
||||
// Check if the specified width is reasonable
|
||||
if (width < 2 * Math.Sqrt(mesh.Vertices.Count))
|
||||
{
|
||||
bitmap = new Bitmap(400, 200);
|
||||
Graphics g = Graphics.FromImage(bitmap);
|
||||
g.Clear(Color.White);
|
||||
|
||||
string message = String.Format("Sorry, I won't render {0} points on such a small image!", mesh.Vertices.Count);
|
||||
|
||||
SizeF sz = g.MeasureString(message, SystemFonts.DefaultFont);
|
||||
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.DrawString(message, SystemFonts.DefaultFont, Brushes.Black,
|
||||
200 - sz.Width / 2, 100 - sz.Height / 2);
|
||||
|
||||
g.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
Graphics g = Graphics.FromImage(bitmap);
|
||||
g.Clear(colors.Background);
|
||||
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
var context = new RenderContext(new Projection(target), colors);
|
||||
context.Add(mesh, true);
|
||||
|
||||
var renderer = new LayerRenderer();
|
||||
renderer.Context = context;
|
||||
renderer.RenderTarget = g;
|
||||
renderer.Render();
|
||||
|
||||
g.Dispose();
|
||||
}
|
||||
|
||||
if (Path.GetExtension(filename) != ".png")
|
||||
{
|
||||
filename += ".png";
|
||||
}
|
||||
|
||||
bitmap.Save(filename, ImageFormat.Png);
|
||||
}
|
||||
|
||||
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(150, 150, 150));
|
||||
colors.Segment = new Pen(Color.SteelBlue);
|
||||
colors.VoronoiLine = new Pen(Color.FromArgb(160, 170, 180));
|
||||
|
||||
return colors;
|
||||
ImageRenderer.Save(mesh, filename, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,15 +109,12 @@
|
||||
<Compile Include="Generators\RingPolygon.cs" />
|
||||
<Compile Include="Generators\StarInBox.cs" />
|
||||
<Compile Include="GenericEventArgs.cs" />
|
||||
<Compile Include="IO\EpsImage.cs" />
|
||||
<Compile Include="IO\FileProcessor.cs" />
|
||||
<Compile Include="IO\Formats\JsonFile.cs" />
|
||||
<Compile Include="IO\Formats\TriangleFile.cs" />
|
||||
<Compile Include="IO\FormattingStreamWriter.cs" />
|
||||
<Compile Include="IO\IMeshFile.cs" />
|
||||
<Compile Include="IO\JsonParser.cs" />
|
||||
<Compile Include="IO\RasterImage.cs" />
|
||||
<Compile Include="IO\SvgImage.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
|
||||
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 Append(string ps)
|
||||
//{
|
||||
// _w.WriteLine(ps);
|
||||
//}
|
||||
|
||||
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("%%BeginProlog");
|
||||
_w.WriteLine("/inch {72 mul} def");
|
||||
_w.WriteLine("%%EndProlog");
|
||||
_w.WriteLine("%%Page: 1 1");
|
||||
_w.WriteLine("save");
|
||||
|
||||
// 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("/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("%");
|
||||
_w.WriteLine("% End of page.");
|
||||
_w.WriteLine("%");
|
||||
_w.WriteLine("%%Trailer");
|
||||
_w.WriteLine("%%EOF");
|
||||
}
|
||||
|
||||
#region IDisposable implementation
|
||||
|
||||
// Has Dispose already been called?
|
||||
bool disposed = false;
|
||||
|
||||
// Public implementation of Dispose pattern callable by consumers.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Protected implementation of Dispose pattern.
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
Close();
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_w.Dispose();
|
||||
_w = null;
|
||||
}
|
||||
|
||||
// Free any unmanaged objects here.
|
||||
//
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
~EpsDocument()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <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.Collections.Generic;
|
||||
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;
|
||||
//double x_scale, y_scale;
|
||||
|
||||
// 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.SetStroke(0.4f, ColorLines);
|
||||
|
||||
foreach (var e in EnumerateEdges(mesh))
|
||||
{
|
||||
eps.DrawLine(Transform(e.GetVertex(0)), Transform(e.GetVertex(1)));
|
||||
}
|
||||
|
||||
// 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.SetColor(ColorPoints);
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
eps.DrawPoint(Transform(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private void DrawTitle(EpsDocument eps)
|
||||
{
|
||||
var buffer = new StringBuilder();
|
||||
|
||||
buffer.AppendLine("%");
|
||||
buffer.AppendLine("% Set the RGB color to black.");
|
||||
buffer.AppendLine("%");
|
||||
buffer.AppendLine("0.000 0.000 0.000 setrgbcolor");
|
||||
buffer.AppendLine("%");
|
||||
buffer.AppendLine("% Set the font and its size.");
|
||||
buffer.AppendLine("%");
|
||||
buffer.AppendLine("/Times-Roman findfont");
|
||||
buffer.AppendLine("0.50 inch scalefont");
|
||||
buffer.AppendLine("setfont");
|
||||
buffer.AppendLine("%");
|
||||
buffer.AppendLine("% Print a title.");
|
||||
buffer.AppendLine("%");
|
||||
buffer.AppendLine("%210 702 moveto");
|
||||
buffer.AppendLine("%(Triangulation) show");
|
||||
}
|
||||
|
||||
private void DrawPointLabels(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
int n = mesh.Vertices.Count;
|
||||
|
||||
IntPoint p;
|
||||
|
||||
StringBuilder labels = new StringBuilder();
|
||||
|
||||
foreach (var node in mesh.Vertices)
|
||||
{
|
||||
p = Transform(node);
|
||||
|
||||
labels.AppendFormat(" {0} {1} moveto ({2}) show", p.X, p.Y + 5, node.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Label the nodes.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to darker blue.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.000 0.250 0.850 setrgbcolor");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.20 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
|
||||
eps.WriteLine(labels.ToString());
|
||||
}
|
||||
|
||||
private void DrawTriangles(StreamWriter eps, Mesh mesh, bool label)
|
||||
{
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the triangle line color and width.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.6 0.6 0.6 setrgbcolor");
|
||||
eps.WriteLine("0.5 setlinewidth");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Draw the triangles.");
|
||||
eps.WriteLine("%");
|
||||
|
||||
IntPoint a, b, c;
|
||||
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
a = Transform(t.GetVertex(0));
|
||||
b = Transform(t.GetVertex(1));
|
||||
c = Transform(t.GetVertex(2));
|
||||
|
||||
eps.WriteLine("newpath");
|
||||
|
||||
eps.WriteLine(" {0} {1} moveto", a.X, a.Y);
|
||||
eps.WriteLine(" {0} {1} lineto", b.X, b.Y);
|
||||
eps.WriteLine(" {0} {1} lineto", c.X, c.Y);
|
||||
eps.WriteLine(" {0} {1} lineto", a.X, a.Y);
|
||||
|
||||
eps.WriteLine("stroke");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTriangleLabels(StreamWriter eps, Mesh mesh)
|
||||
{
|
||||
var labels = new StringBuilder();
|
||||
|
||||
IntPoint a, b, c;
|
||||
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
a = Transform(t.GetVertex(0));
|
||||
b = Transform(t.GetVertex(1));
|
||||
c = Transform(t.GetVertex(2));
|
||||
|
||||
eps.WriteLine("newpath");
|
||||
|
||||
a = Transform((a.X + b.X + c.X) / 3.0, (a.Y + b.Y + c.Y) / 3.0);
|
||||
|
||||
labels.AppendFormat(" {0} {1} moveto ({2}) show", a.X, a.Y, t.ID);
|
||||
labels.AppendLine();
|
||||
|
||||
eps.WriteLine("stroke");
|
||||
}
|
||||
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Label the triangles.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("% Set the RGB color to darker red.");
|
||||
eps.WriteLine("%");
|
||||
eps.WriteLine("0.950 0.250 0.150 setrgbcolor");
|
||||
eps.WriteLine("/Times-Roman findfont");
|
||||
eps.WriteLine("0.20 inch scalefont");
|
||||
eps.WriteLine("setfont");
|
||||
eps.WriteLine("%");
|
||||
|
||||
eps.WriteLine(labels.ToString());
|
||||
}
|
||||
//*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ISegment> EnumerateEdges(Mesh mesh, bool segments = false)
|
||||
{
|
||||
foreach (var t in mesh.Triangles)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int nid = t.GetNeighborID(i);
|
||||
|
||||
if ((t.ID < nid) || (nid < 0))
|
||||
{
|
||||
if (segments || t.GetSegment(i) == null)
|
||||
{
|
||||
yield return new Segment(
|
||||
t.GetVertex((i + 1) % 3),
|
||||
t.GetVertex((i + 2) % 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// From http://stackoverflow.com/questions/12011789/streamwriter-and-iformatprovider
|
||||
/// </remarks>
|
||||
public class FormattingStreamWriter : StreamWriter
|
||||
{
|
||||
private readonly IFormatProvider formatProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified file
|
||||
/// by using the default encoding and buffer size.
|
||||
/// </summary>
|
||||
/// <param name="path">The complete file path to write to.</param>
|
||||
public FormattingStreamWriter(string path)
|
||||
: this(path, CultureInfo.InvariantCulture)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified stream
|
||||
/// by using UTF-8 encoding and the default buffer size.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to write to.</param>
|
||||
public FormattingStreamWriter(Stream stream)
|
||||
: this(stream, CultureInfo.InvariantCulture)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified file
|
||||
/// by using the default encoding and buffer size.
|
||||
/// </summary>
|
||||
/// <param name="path">The complete file path to write to.</param>
|
||||
/// <param name="formatProvider">The format provider.</param>
|
||||
public FormattingStreamWriter(string path, IFormatProvider formatProvider)
|
||||
: base(path)
|
||||
{
|
||||
this.formatProvider = formatProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the StreamWriter class for the specified stream
|
||||
/// by using UTF-8 encoding and the default buffer size.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to write to.</param>
|
||||
/// <param name="formatProvider">The format provider.</param>
|
||||
public FormattingStreamWriter(Stream stream, IFormatProvider formatProvider)
|
||||
: base(stream)
|
||||
{
|
||||
this.formatProvider = formatProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an object that controls formatting.
|
||||
/// </summary>
|
||||
public override IFormatProvider FormatProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.formatProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Page size in millimeters.
|
||||
/// </summary>
|
||||
public struct PageSize
|
||||
{
|
||||
private const float MM_PER_INCH = 2.54f;
|
||||
|
||||
public static readonly PageSize A3 = new PageSize(297.0f, 420.0f);
|
||||
public static readonly PageSize A4 = new PageSize(210.0f, 297.0f);
|
||||
public static readonly PageSize A5 = new PageSize(148.0f, 210.0f);
|
||||
public static readonly PageSize LETTER = new PageSize(8.5f * MM_PER_INCH, 11.0f * MM_PER_INCH);
|
||||
public static readonly PageSize LEGAL = new PageSize(8.5f * MM_PER_INCH, 14.0f * MM_PER_INCH);
|
||||
|
||||
private float left;
|
||||
private float top;
|
||||
private float right;
|
||||
private float bottom;
|
||||
|
||||
public float X
|
||||
{
|
||||
get { return left; }
|
||||
}
|
||||
|
||||
public float Y
|
||||
{
|
||||
get { return top; }
|
||||
}
|
||||
|
||||
public float Width
|
||||
{
|
||||
get { return right - left; }
|
||||
}
|
||||
|
||||
public float Height
|
||||
{
|
||||
get { return bottom - top; }
|
||||
}
|
||||
|
||||
public float Right
|
||||
{
|
||||
get { return right; }
|
||||
}
|
||||
|
||||
public float Bottom
|
||||
{
|
||||
get { return bottom; }
|
||||
}
|
||||
|
||||
public PageSize(float left, float top, float right, float bottom)
|
||||
{
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.right = right;
|
||||
this.bottom = bottom;
|
||||
}
|
||||
|
||||
public PageSize(float width, float height)
|
||||
: this(0.0f, 0.0f, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
public PageSize(Rectangle size)
|
||||
: this(size.Left, size.Right, size.Top, size.Bottom)
|
||||
{
|
||||
}
|
||||
|
||||
public void Expand(float dx, float dy)
|
||||
{
|
||||
left -= dx;
|
||||
top -= dy;
|
||||
|
||||
right += dx;
|
||||
bottom += dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-15
@@ -4,7 +4,7 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MeshExplorer.IO
|
||||
namespace TriangleNet.Rendering.Text
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
@@ -54,7 +54,7 @@ namespace MeshExplorer.IO
|
||||
|
||||
int height = (int)((bounds.Height + 2 * margin) * scale);
|
||||
|
||||
using (StreamWriter svg = new StreamWriter(filename))
|
||||
using (var svg = new FormattingStreamWriter(filename))
|
||||
{
|
||||
svg.WriteLine("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"");
|
||||
svg.WriteLine(" width=\"{0}px\" height=\"{1}px\"", width, height);
|
||||
@@ -96,18 +96,16 @@ namespace MeshExplorer.IO
|
||||
x3 = scale * v3.X;
|
||||
y3 = scale * v3.Y;
|
||||
|
||||
svg.Write("M {0},{1} L {2},{3} {4},{5} Z ",
|
||||
x1.ToString("0.0", Util.Nfi), y1.ToString("0.0", Util.Nfi),
|
||||
x2.ToString("0.0", Util.Nfi), y2.ToString("0.0", Util.Nfi),
|
||||
x3.ToString("0.0", Util.Nfi), y3.ToString("0.0", Util.Nfi));
|
||||
svg.Write("M {0:0.#},{1:0.#} L {2:0.#},{3:0.#} {4:0.#},{5:0.#} Z ",
|
||||
x1, y1, x2, y2, x3, y3);
|
||||
|
||||
if (label)
|
||||
{
|
||||
xa = (x1 + x2 + x3) / 3.0;
|
||||
ya = (y1 + y2 + y3) / 3.0;
|
||||
|
||||
labels.AppendFormat("<text x=\"{0}\" y=\"{1}\">{2}</text>",
|
||||
xa.ToString("0.0", Util.Nfi), ya.ToString("0.0", Util.Nfi), tri.ID);
|
||||
labels.AppendFormat("<text x=\"{0:0.#}\" y=\"{1:0.#}\">{2}</text>",
|
||||
xa, ya, tri.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
|
||||
@@ -139,9 +137,8 @@ namespace MeshExplorer.IO
|
||||
x2 = scale * seg.GetVertex(1).X;
|
||||
y2 = scale * seg.GetVertex(1).Y;
|
||||
|
||||
svg.Write("M {0},{1} L {2},{3} ",
|
||||
x1.ToString("0.0", Util.Nfi), y1.ToString("0.0", Util.Nfi),
|
||||
x2.ToString("0.0", Util.Nfi), y2.ToString("0.0", Util.Nfi));
|
||||
svg.Write("M {0:0.#},{1:0.#} L {2:0.#},{3:0.#} ",
|
||||
x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
svg.WriteLine("\" style=\"stroke:#4682B4; fill:none; stroke-linejoin:bevel; stroke-width:2px;\"/>");
|
||||
@@ -177,13 +174,13 @@ namespace MeshExplorer.IO
|
||||
x = scale * node.X;
|
||||
y = scale * node.Y;
|
||||
|
||||
svg.WriteLine(" <circle cx=\"{0}\" cy=\"{1}\" r=\"{2}\" />",
|
||||
x.ToString("0.0", Util.Nfi), y.ToString("0.0", Util.Nfi), circle_size);
|
||||
svg.WriteLine(" <circle cx=\"{0:0.#}\" cy=\"{1:0.#}\" r=\"{2:0.#}\" />",
|
||||
x, y, circle_size);
|
||||
|
||||
if (label)
|
||||
{
|
||||
labels.AppendFormat("<text x=\"{0}\" y=\"{1}\">{2}</text>",
|
||||
x.ToString("0.0", Util.Nfi), y.ToString("0.0", Util.Nfi), node.ID);
|
||||
labels.AppendFormat("<text x=\"{0:0.#}\" y=\"{1:0.#}\">{2}</text>",
|
||||
x, y, node.ID);
|
||||
labels.AppendLine();
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,11 @@
|
||||
<Compile Include="RenderContext.cs" />
|
||||
<Compile Include="RenderLayer.cs" />
|
||||
<Compile Include="RenderManager.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" />
|
||||
|
||||
Reference in New Issue
Block a user