Reduce size of exported EPS images.

git-svn-id: https://triangle.svn.codeplex.com/svn@79345 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
SND\wo80_cp
2016-07-15 15:07:38 +00:00
parent 3c20831c10
commit 507ef402ce
3 changed files with 234 additions and 145 deletions
+201 -145
View File
@@ -8,12 +8,14 @@
namespace MeshExplorer.IO
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using TriangleNet;
using TriangleNet.Topology;
using TriangleNet.Geometry;
using IntPoint = System.Drawing.Point;
/// <summary>
/// Writes a mesh to an EPS file.
/// </summary>
@@ -55,17 +57,17 @@ namespace MeshExplorer.IO
UpdateMetrics(mesh.Bounds);
using (StreamWriter eps = new StreamWriter(filename))
using (var eps = new FormattingStreamWriter(filename))
{
WriteHeader(filename, eps);
DrawClip(eps);
DrawTriangles(eps, mesh, false);
DrawEdges(eps, mesh);
DrawSegments(eps, mesh);
DrawPoints(eps, mesh, false);
DrawPoints(eps, mesh);
WriteTrailer(eps);
}
@@ -79,7 +81,7 @@ namespace MeshExplorer.IO
eps.WriteLine("%%Pages: 1");
eps.WriteLine("%%BoundingBox: {0} {1} {2} {3}", x_ps_min, y_ps_min, x_ps_max, y_ps_max);
eps.WriteLine("%%Document-Fonts: Times-Roman");
eps.WriteLine("%%LanguageLevel: 1");
eps.WriteLine("%%LanguageLevel: 2");
eps.WriteLine("%%EndComments");
eps.WriteLine("%%BeginProlog");
eps.WriteLine("/inch {72 mul} def");
@@ -142,6 +144,123 @@ namespace MeshExplorer.IO
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("%");
@@ -153,170 +272,86 @@ namespace MeshExplorer.IO
eps.WriteLine("% Draw the triangles.");
eps.WriteLine("%");
StringBuilder labels = new StringBuilder();
IntPoint a, b, c;
Vertex v1, v2, v3;
double x1, y1, x2, y2, x3, y3, xa, ya;
int x_ps, y_ps;
foreach (var tri in mesh.Triangles)
foreach (var t in mesh.Triangles)
{
a = Transform(t.GetVertex(0));
b = Transform(t.GetVertex(1));
c = Transform(t.GetVertex(2));
eps.WriteLine("newpath");
v1 = tri.GetVertex(0);
v2 = tri.GetVertex(1);
v3 = tri.GetVertex(2);
x1 = v1.X; y1 = v1.Y;
x2 = v2.X; y2 = v2.Y;
x3 = v3.X; y3 = v3.Y;
x_ps = (int)Math.Floor(((x_max - x1) * x_ps_min + (x1 - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - y1) * y_ps_min + (y1 - y_min) * y_ps_max) / (y_max - y_min));
eps.WriteLine(" {0} {1} moveto", x_ps, y_ps);
x_ps = (int)Math.Floor(((x_max - x2) * x_ps_min + (x2 - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - y2) * y_ps_min + (y2 - y_min) * y_ps_max) / (y_max - y_min));
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
x_ps = (int)Math.Floor(((x_max - x3) * x_ps_min + (x3 - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - y3) * y_ps_min + (y3 - y_min) * y_ps_max) / (y_max - y_min));
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
x_ps = (int)Math.Floor(((x_max - x1) * x_ps_min + (x1 - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - y1) * y_ps_min + (y1 - y_min) * y_ps_max) / (y_max - y_min));
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
if (label)
{
xa = (x1 + x2 + x3) / 3.0;
ya = (y1 + y2 + y3) / 3.0;
x_ps = (int)Math.Floor(((x_max - xa) * x_ps_min + (xa - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - ya) * y_ps_min + (ya - y_min) * y_ps_max) / (y_max - y_min));
labels.AppendFormat(" {0} {1} moveto ({2}) show", x_ps, y_ps, tri.ID);
labels.AppendLine();
}
eps.WriteLine("stroke");
}
// Label the triangles.
if (label)
{
eps.WriteLine("%");
eps.WriteLine("% Label the triangles.");
eps.WriteLine("%");
eps.WriteLine("% Set the RGB color to darker red.");
eps.WriteLine("%");
eps.WriteLine("0.950 0.250 0.150 setrgbcolor");
eps.WriteLine("/Times-Roman findfont");
eps.WriteLine("0.20 inch scalefont");
eps.WriteLine("setfont");
eps.WriteLine("%");
eps.Write(labels.ToString());
}
}
private void DrawSegments(StreamWriter eps, Mesh mesh)
{
eps.WriteLine("%");
eps.WriteLine("% Set the triangle line color and width.");
eps.WriteLine("%");
eps.WriteLine("0.27 0.5 0.7 setrgbcolor");
eps.WriteLine("0.75 setlinewidth");
eps.WriteLine("%");
eps.WriteLine("% Draw the triangles.");
eps.WriteLine("%");
StringBuilder labels = new StringBuilder();
double x1, y1, x2, y2;
int x_ps, y_ps;
foreach (var seg in mesh.Segments)
{
eps.WriteLine("newpath");
x1 = seg.GetVertex(0).X; y1 = seg.GetVertex(0).Y;
x2 = seg.GetVertex(1).X; y2 = seg.GetVertex(1).Y;
x_ps = (int)Math.Floor(((x_max - x1) * x_ps_min + (x1 - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - y1) * y_ps_min + (y1 - y_min) * y_ps_max) / (y_max - y_min));
eps.WriteLine(" {0} {1} moveto", x_ps, y_ps);
x_ps = (int)Math.Floor(((x_max - x2) * x_ps_min + (x2 - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - y2) * y_ps_min + (y2 - y_min) * y_ps_max) / (y_max - y_min));
eps.WriteLine(" {0} {1} lineto", x_ps, y_ps);
eps.WriteLine(" {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 DrawPoints(StreamWriter eps, Mesh mesh, bool label)
private void DrawTriangleLabels(StreamWriter eps, Mesh mesh)
{
int n = mesh.Vertices.Count;
var labels = new StringBuilder();
int circle_size = 1;
IntPoint a, b, c;
if (n < 100)
foreach (var t in mesh.Triangles)
{
circle_size = 3;
}
else if (n < 500)
{
circle_size = 2;
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("% Draw filled dots at the nodes.");
eps.WriteLine("% Label the triangles.");
eps.WriteLine("%");
eps.WriteLine("% Set the RGB color to blue.");
eps.WriteLine("% Set the RGB color to darker red.");
eps.WriteLine("%");
eps.WriteLine("0.0 0.4 0.0 setrgbcolor");
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("%");
double x, y;
int x_ps, y_ps;
eps.WriteLine(labels.ToString());
}
//*/
StringBuilder labels = new StringBuilder();
private void SetColor(StreamWriter eps, float r, float g, float b)
{
eps.WriteLine("{0} {1} {2} setrgbcolor", r, g, b);
eps.WriteLine("%");
}
foreach (var node in mesh.Vertices)
{
x = node.X;
y = node.Y;
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("%");
}
x_ps = (int)Math.Floor(((x_max - x) * x_ps_min + (x - x_min) * x_ps_max) / (x_max - x_min));
y_ps = (int)Math.Floor(((y_max - y) * y_ps_min + (y - y_min) * y_ps_max) / (y_max - y_min));
private IntPoint Transform(Point p)
{
return Transform(p.X, p.Y);
}
eps.WriteLine(" newpath {0} {1} {2} 0 360 arc closepath fill", x_ps, y_ps, circle_size);
if (label)
{
labels.AppendFormat(" {0} {1} moveto ({2}) show", x_ps, y_ps + 5, node);
labels.AppendLine();
}
}
// Label the nodes.
if (label)
{
eps.WriteLine("%");
eps.WriteLine("% Label the nodes.");
eps.WriteLine("%");
eps.WriteLine("% Set the RGB color to darker blue.");
eps.WriteLine("%");
eps.WriteLine("0.000 0.250 0.850 setrgbcolor");
eps.WriteLine("/Times-Roman findfont");
eps.WriteLine("0.20 inch scalefont");
eps.WriteLine("setfont");
eps.WriteLine("%");
eps.Write(labels.ToString());
}
private 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)
@@ -363,5 +398,26 @@ namespace MeshExplorer.IO
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));
}
}
}
}
}
}
}
@@ -0,0 +1,32 @@
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;
}
}
}
}
@@ -113,6 +113,7 @@
<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" />