More code reorganization (for beta 4)

git-svn-id: https://triangle.svn.codeplex.com/svn@75021 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
SND\wo80_cp
2014-05-29 18:14:13 +00:00
parent 94fafe03c0
commit 7384b5fd07
39 changed files with 927 additions and 410 deletions
+8 -8
View File
@@ -69,10 +69,10 @@ namespace MeshRenderer.Core
}
this.Bounds = new BoundingBox(
(float)data.Bounds.MinX,
(float)data.Bounds.MaxX,
(float)data.Bounds.MinY,
(float)data.Bounds.MaxY);
(float)data.Bounds.Left,
(float)data.Bounds.Right,
(float)data.Bounds.Bottom,
(float)data.Bounds.Top);
}
/// <summary>
@@ -150,10 +150,10 @@ namespace MeshRenderer.Core
this.Triangles = triangles.ToArray();
this.Bounds = new BoundingBox(
(float)mesh.Bounds.MinX,
(float)mesh.Bounds.MaxX,
(float)mesh.Bounds.MinY,
(float)mesh.Bounds.MaxY);
(float)mesh.Bounds.Left,
(float)mesh.Bounds.Right,
(float)mesh.Bounds.Bottom,
(float)mesh.Bounds.Top);
}
/// <summary>
+5 -5
View File
@@ -319,12 +319,12 @@ namespace MeshExplorer.IO
}
}
private void UpdateMetrics(BoundingBox bounds)
private void UpdateMetrics(Rectangle bounds)
{
x_max = bounds.MaxX;
x_min = bounds.MinX;
y_max = bounds.MaxY;
y_min = bounds.MinY;
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;
+23 -3
View File
@@ -15,6 +15,7 @@ namespace MeshExplorer.IO.Formats
using TriangleNet.Data;
using TriangleNet.Geometry;
using TriangleNet.IO;
using TriangleNet.Meshing;
/// <summary>
/// Read and write JSON files.
@@ -74,6 +75,11 @@ namespace MeshExplorer.IO.Formats
return false;
}
public bool IsSupported(string file)
{
throw new NotImplementedException();
}
public Mesh Import(string filename)
{
InputGeometry geometry = this.Read(filename);
@@ -90,10 +96,9 @@ namespace MeshExplorer.IO.Formats
}
}
Mesh mesh = new Mesh();
mesh.Load(geometry, triangles);
var converter = new Converter();
return mesh;
return converter.ToMesh(geometry, triangles);
}
public void Write(Mesh mesh, string filename)
@@ -151,6 +156,11 @@ namespace MeshExplorer.IO.Formats
}
}
public void Write(Mesh mesh, StreamWriter stream)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
@@ -213,6 +223,16 @@ namespace MeshExplorer.IO.Formats
return data;
}
public void Write(InputGeometry polygon, string filename)
{
throw new NotImplementedException();
}
public void Write(InputGeometry polygon, StreamWriter stream)
{
throw new NotImplementedException();
}
private void ParseJson(string filename)
{
if (this.json == null || this.file != filename)
@@ -7,13 +7,10 @@
namespace MeshExplorer.IO.Formats
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleNet.IO;
using System.IO;
using TriangleNet.Geometry;
using TriangleNet;
using TriangleNet.Geometry;
using TriangleNet.IO;
/// <summary>
/// Read and write files defined in classic Triangle format.
@@ -45,11 +42,26 @@ namespace MeshExplorer.IO.Formats
return (ext == ".ele");
}
public bool IsSupported(string file)
{
throw new NotImplementedException();
}
public InputGeometry Read(string filename)
{
return format.Read(filename);
}
public void Write(InputGeometry polygon, string filename)
{
format.Write(polygon, filename);
}
public void Write(InputGeometry polygon, StreamWriter stream)
{
format.Write(polygon, stream);
}
public Mesh Import(string filename)
{
return format.Import(filename);
@@ -62,5 +74,10 @@ namespace MeshExplorer.IO.Formats
format.Write(mesh, filename);
}
}
public void Write(Mesh mesh, StreamWriter stream)
{
throw new NotImplementedException();
}
}
}
-98
View File
@@ -1,98 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="GeometryWriter.cs" company="">
// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace MeshExplorer.IO
{
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TriangleNet.Geometry;
/// <summary>
/// Writes an InputGeometry to standard Triangle format.
/// </summary>
public static class GeometryWriter
{
private static int OFFSET = 0;
/// <summary>
/// Writes an InputGeometry to a Triangle format .poly file.
/// </summary>
/// <param name="geometry">The InputGeometry to write.</param>
/// <param name="filename">The filename.</param>
/// <param name="compatibleMode">If true, indices will start at 1 (compatible with original C code).</param>
public static void Write(InputGeometry geometry, string filename, bool compatibleMode = false)
{
OFFSET = compatibleMode ? 1 : 0;
using (StreamWriter writer = new StreamWriter(filename))
{
WritePoints(writer, geometry.Points, geometry.Count);
WriteSegments(writer, geometry.Segments);
WriteHoles(writer, geometry.Holes);
}
}
private static void WritePoints(StreamWriter writer, IEnumerable<Point> points, int count)
{
int attributes = 0, index = OFFSET;
var first = points.FirstOrDefault();
if (first.Attributes != null)
{
attributes = first.Attributes.Length;
}
writer.WriteLine("{0} {1} {2} {3}", count, 2, attributes, 1);
foreach (var item in points)
{
// Vertex number, x and y coordinates.
writer.Write("{0} {1} {2}", index, item.X.ToString(Util.Nfi), item.Y.ToString(Util.Nfi));
// Write attributes.
for (int j = 0; j < attributes; j++)
{
writer.Write(" {0}", item.Attributes[j].ToString(Util.Nfi));
}
// Write the boundary marker.
writer.WriteLine(" {0}", item.Boundary);
index++;
}
}
private static void WriteSegments(StreamWriter writer, IEnumerable<Edge> edges)
{
int index = OFFSET;
writer.WriteLine("{0} {1}", edges.Count(), 1);
foreach (var item in edges)
{
writer.WriteLine("{0} {1} {2} {3}", index, item.P0 + OFFSET, item.P1 + OFFSET, item.Boundary);
index++;
}
}
private static void WriteHoles(StreamWriter writer, IEnumerable<Point> holes)
{
int index = OFFSET;
writer.WriteLine("{0}", holes.Count());
foreach (var item in holes)
{
writer.WriteLine("{0} {1} {2}", index, item.X.ToString(Util.Nfi), item.Y.ToString(Util.Nfi));
index++;
}
}
}
}
+1 -1
View File
@@ -16,7 +16,7 @@ namespace MeshExplorer.IO
/// <summary>
/// Defines an interface for mesh file formats.
/// </summary>
public interface IMeshFile : IGeometryFormat, IMeshFormat
public interface IMeshFile : IPolygonFormat, IMeshFormat
{
/// <summary>
/// The supported file extensions.
+2 -2
View File
@@ -49,8 +49,8 @@ namespace MeshExplorer.IO
scale = width / ((float)bounds.Width + 2 * margin);
int x_offset = -(int)((bounds.MinX - margin) * scale);
int y_offset = (int)((bounds.MaxY + margin) * scale);
int x_offset = -(int)((bounds.Left - margin) * scale);
int y_offset = (int)((bounds.Top + margin) * scale);
int height = (int)((bounds.Height + 2 * margin) * scale);
@@ -115,7 +115,6 @@
<Compile Include="IO\FileProcessor.cs" />
<Compile Include="IO\Formats\JsonFile.cs" />
<Compile Include="IO\Formats\TriangleFile.cs" />
<Compile Include="IO\GeometryWriter.cs" />
<Compile Include="IO\IMeshFile.cs" />
<Compile Include="IO\JsonParser.cs" />
<Compile Include="IO\RasterImage.cs" />
@@ -48,8 +48,8 @@ namespace MeshExplorer.Topology
//zoom.ClipMargin = 10.0f;
var b = mesh.Bounds;
zoom.Update(new BoundingBox((float)b.MinX, (float)b.MaxX,
(float)b.MinY, (float)b.MaxY));
zoom.Update(new BoundingBox((float)b.Left, (float)b.Right,
(float)b.Bottom, (float)b.Top));
InitializeBuffer();
+1 -1
View File
@@ -15,7 +15,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Represents a straight line segment in 2D space.
/// </summary>
public class Edge
public class Edge : IEdge
{
/// <summary>
/// Gets the first endpoints index.
+21
View File
@@ -0,0 +1,21 @@
namespace TriangleNet.Geometry
{
public interface IEdge
{
/// <summary>
/// Gets the first endpoints index.
/// </summary>
int P0 { get; }
/// <summary>
/// Gets the second endpoints index.
/// </summary>
int P1 { get; }
/// <summary>
/// Gets the segments boundary mark.
/// </summary>
int Boundary { get; }
}
}
@@ -0,0 +1,24 @@
namespace TriangleNet.Geometry
{
using System.Collections.Generic;
using TriangleNet.Data;
public interface IPolygon
{
List<Vertex> Points { get; }
List<IEdge> Segments { get; }
List<Point> Holes { get; }
//List<Point> Regions { get; }
List<RegionPointer> Regions { get; }
bool HasPointMarkers { get; set; }
bool HasSegmentMarkers { get; set; }
void AddContour(IEnumerable<Vertex> points, int marker, bool hole, bool convex);
void AddContour(IEnumerable<Vertex> points, int marker, Point hole);
Rectangle Bounds();
}
}
+1 -16
View File
@@ -11,25 +11,10 @@ namespace TriangleNet.Geometry
/// <summary>
/// Interface for segment geometry.
/// </summary>
public interface ISegment
public interface ISegment : IEdge
{
#region Public properties
/// <summary>
/// Gets the first endpoints vertex id.
/// </summary>
int P0 { get; }
/// <summary>
/// Gets the seconds endpoints vertex id.
/// </summary>
int P1 { get; }
/// <summary>
/// Gets the segment boundary mark.
/// </summary>
int Boundary { get; }
/// <summary>
/// Gets the segments endpoint.
/// </summary>
@@ -21,7 +21,7 @@ namespace TriangleNet.Geometry
internal List<Point> holes;
internal List<RegionPointer> regions;
BoundingBox bounds;
Rectangle bounds;
// Used to check consitent use of point attributes.
private int pointAttributes = -1;
@@ -46,7 +46,7 @@ namespace TriangleNet.Geometry
holes = new List<Point>();
regions = new List<RegionPointer>();
bounds = new BoundingBox();
bounds = new Rectangle();
pointAttributes = -1;
}
@@ -54,7 +54,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Gets the bounding box of the input geometry.
/// </summary>
public BoundingBox Bounds
public Rectangle Bounds
{
get { return bounds; }
}
@@ -138,8 +138,9 @@ namespace TriangleNet.Geometry
/// <param name="boundary">Boundary marker.</param>
public void AddPoint(double x, double y, int boundary)
{
points.Add(new Vertex(x, y, boundary));
bounds.Expand(x, y);
var v = new Vertex(x, y, boundary);
points.Add(v);
bounds.Expand(v);
}
/// <summary>
@@ -176,8 +177,9 @@ namespace TriangleNet.Geometry
throw new ArgumentException("Inconsitent use of point attributes.");
}
points.Add(new Vertex(x, y, boundary) { attributes = attribs });
bounds.Expand(x, y);
var v = new Vertex(x, y, boundary) { attributes = attribs };
points.Add(v);
bounds.Expand(v);
}
/// <summary>
@@ -202,7 +204,7 @@ namespace TriangleNet.Geometry
}
points.Add(v);
bounds.Expand(v.x, v.y);
bounds.Expand(v);
}
/// <summary>
+246
View File
@@ -0,0 +1,246 @@
namespace TriangleNet.Geometry
{
using System;
using System.Collections.Generic;
using TriangleNet.Data;
public class Polygon : IPolygon
{
List<Vertex> points;
List<Point> holes;
List<RegionPointer> regions;
List<IEdge> segments;
public List<Vertex> Points
{
get { return points; }
}
public List<Point> Holes
{
get { return holes; }
}
public List<RegionPointer> Regions
{
get { return regions; }
}
public List<IEdge> Segments
{
get { return segments; }
}
public bool HasPointMarkers { get; set; }
public bool HasSegmentMarkers { get; set; }
public int Count
{
get { return points.Count; }
}
public Polygon()
: this(3)
{
}
public Polygon(int capacity)
{
points = new List<Vertex>(capacity);
holes = new List<Point>();
regions = new List<RegionPointer>();
segments = new List<IEdge>();
HasPointMarkers = false;
HasSegmentMarkers = false;
}
public void AddContour(IEnumerable<Vertex> points, int marker = 0,
bool hole = false, bool convex = false)
{
// Copy input to list.
var contour = new List<Vertex>(points);
int offset = this.points.Count;
int count = contour.Count;
// Check if first vertex equals last vertex.
if (contour[0] == contour[count - 1])
{
count--;
contour.RemoveAt(count);
}
// Add points to polygon.
this.points.AddRange(contour);
var centroid = new Point(0.0, 0.0);
for (int i = 0; i < count; i++)
{
centroid.x += contour[i].x;
centroid.y += contour[i].y;
// Add segments to polygon.
this.segments.Add(new Edge(offset + i, offset + ((i + 1) % count), marker));
}
if (hole)
{
if (convex)
{
// If the hole is convex, use its centroid.
centroid.x /= count;
centroid.y /= count;
this.holes.Add(centroid);
}
else
{
this.holes.Add(FindPointInPolygon(contour));
}
}
}
public void AddContour(IEnumerable<Vertex> points, int marker, Point hole)
{
// Copy input to list.
var contour = new List<Vertex>(points);
int offset = this.points.Count;
int count = contour.Count;
// Check if first vertex equals last vertex.
if (contour[0] == contour[count - 1])
{
count--;
contour.RemoveAt(count);
}
// Add points to polygon.
this.points.AddRange(contour);
for (int i = 0; i < count; i++)
{
// Add segments to polygon.
this.segments.Add(new Edge(offset + i, offset + ((i + 1) % count), marker));
}
this.holes.Add(hole);
}
public Rectangle Bounds()
{
var bounds = new Rectangle();
bounds.Expand(this.points);
return bounds;
}
public void Add(Vertex vertex)
{
this.points.Add(vertex);
}
public void Add(Vertex vertex, double[] attributes)
{
// TODO: check attibutes
vertex.attributes = attributes;
this.points.Add(vertex);
}
public void Add(Edge edge)
{
this.segments.Add(edge);
}
private Point FindPointInPolygon(List<Vertex> contour)
{
var bounds = new Rectangle();
bounds.Expand(contour);
int length = contour.Count;
int limit = 8;
var test = new Point();
Point a, b; // Current edge.
double cx, cy; // Center of current edge.
double dx, dy; // Direction perpendicular to edge.
for (int i = 0; i < length; i++)
{
a = contour[i];
b = contour[(i + 1) % length];
cx = (a.x + b.x) / 2;
cy = (a.y + b.y) / 2;
dx = (b.y - a.y) / 1.374;
dy = (a.x - b.x) / 1.374;
for (int j = 1; j <= limit; j++)
{
// Search to the right of the segment.
test.x = cx + dx / j;
test.y = cy + dy / j;
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
{
return test;
}
// Search on the other side of the segment.
test.x = cx - dx / j;
test.y = cy - dy / j;
if (bounds.Contains(test) && IsPointInPolygon(test, contour))
{
return test;
}
}
}
throw new Exception();
}
/// <summary>
/// Return true if the given point is inside the polygon, or false if it is not.
/// </summary>
/// <param name="point"></param>
/// <param name="poly"></param>
/// <returns></returns>
/// <remarks>
/// WARNING: If the point is exactly on the edge of the polygon, then the function
/// may return true or false.
/// </remarks>
private bool IsPointInPolygon(Point point, List<Vertex> poly)
{
bool inside = false;
double x = point.x;
double y = point.y;
int count = poly.Count;
for (int i = 0, j = count - 1; i < count; i++)
{
if (((poly[i].y < y && poly[j].y >= y) || (poly[j].y < y && poly[i].y >= y))
&& (poly[i].x <= x || poly[j].x <= x))
{
inside ^= (poly[i].x + (y - poly[i].y) / (poly[j].y - poly[i].y) * (poly[j].x - poly[i].x) < x);
}
j = i;
}
return inside;
}
}
}
@@ -7,36 +7,37 @@
namespace TriangleNet.Geometry
{
using System;
using System.Collections.Generic;
/// <summary>
/// A simple bounding box class.
/// </summary>
public class BoundingBox
public class Rectangle
{
double xmin, ymin, xmax, ymax;
/// <summary>
/// Initializes a new instance of the <see cref="BoundingBox" /> class.
/// Initializes a new instance of the <see cref="Rectangle" /> class.
/// </summary>
public BoundingBox()
public Rectangle()
: this(double.MaxValue, double.MaxValue, -double.MaxValue, -double.MaxValue)
{
}
public BoundingBox(BoundingBox other)
: this(other.MinX, other.MinY, other.MaxX, other.MaxY)
public Rectangle(Rectangle other)
: this(other.Left, other.Bottom, other.Right, other.Top)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BoundingBox" /> class
/// Initializes a new instance of the <see cref="Rectangle" /> class
/// with predefined bounds.
/// </summary>
/// <param name="xmin">Minimum x value.</param>
/// <param name="ymin">Minimum y value.</param>
/// <param name="xmax">Maximum x value.</param>
/// <param name="ymax">Maximum y value.</param>
public BoundingBox(double xmin, double ymin, double xmax, double ymax)
public Rectangle(double xmin, double ymin, double xmax, double ymax)
{
this.xmin = xmin;
this.xmax = xmax;
@@ -47,7 +48,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Gets the minimum x value (left boundary).
/// </summary>
public double MinX
public double Left
{
get { return xmin; }
}
@@ -55,7 +56,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Gets the maximum x value (right boundary).
/// </summary>
public double MaxX
public double Right
{
get { return xmax; }
}
@@ -63,7 +64,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Gets the minimum y value (bottom boundary).
/// </summary>
public double MinY
public double Bottom
{
get { return ymin; }
}
@@ -71,7 +72,7 @@ namespace TriangleNet.Geometry
/// <summary>
/// Gets the maximum y value (top boundary).
/// </summary>
public double MaxY
public double Top
{
get { return ymax; }
}
@@ -109,13 +110,24 @@ namespace TriangleNet.Geometry
/// Expand rectangle to include given point.
/// </summary>
/// <param name="x">X coordinate.</param>
/// <param name="y">Y coordinate.</param>
public void Expand(double x, double y)
/// <param name="p">Y coordinate.</param>
public void Expand(Point p)
{
xmin = Math.Min(xmin, x);
ymin = Math.Min(ymin, y);
xmax = Math.Max(xmax, x);
ymax = Math.Max(ymax, y);
xmin = Math.Min(xmin, p.x);
ymin = Math.Min(ymin, p.y);
xmax = Math.Max(xmax, p.x);
ymax = Math.Max(ymax, p.y);
}
/// <summary>
/// Expand rectangle to include a list of points.
/// </summary>
public void Expand(IEnumerable<Point> points)
{
foreach (var p in points)
{
Expand(p);
}
}
/// <summary>
@@ -123,7 +135,7 @@ namespace TriangleNet.Geometry
/// </summary>
/// <param name="x">X coordinate.</param>
/// <param name="y">Y coordinate.</param>
public void Expand(BoundingBox other)
public void Expand(Rectangle other)
{
xmin = Math.Min(xmin, other.xmin);
ymin = Math.Min(ymin, other.ymin);
@@ -141,16 +153,16 @@ namespace TriangleNet.Geometry
return ((pt.x >= xmin) && (pt.x <= xmax) && (pt.y >= ymin) && (pt.y <= ymax));
}
public bool Contains(BoundingBox other)
public bool Contains(Rectangle other)
{
return (xmin <= other.MinX && other.MaxX <= xmax
&& ymin <= other.MinY && other.MaxY <= ymax);
return (xmin <= other.Left && other.Right <= xmax
&& ymin <= other.Bottom && other.Top <= ymax);
}
public bool Intersects(BoundingBox other)
public bool Intersects(Rectangle other)
{
return (other.MinX < xmax && xmin < other.MaxX
&& other.MinY < ymax && ymin < other.MaxY);
return (other.Left < xmax && xmin < other.Right
&& other.Bottom < ymax && ymin < other.Top);
}
}
}
+111
View File
@@ -0,0 +1,111 @@
namespace TriangleNet.IO
{
using System;
using System.Collections.Generic;
using TriangleNet.Geometry;
using TriangleNet.Meshing;
public static class FileProcessor
{
static List<IFileFormat> formats = new List<IFileFormat>();
public static void Add(IFileFormat format)
{
formats.Add(format);
}
public static bool IsSupported(string file)
{
foreach (var format in formats)
{
if (format.IsSupported(file))
{
return true;
}
}
return false;
}
#region Polygon read/write
/// <summary>
/// Read a file containing polygon geometry.
/// </summary>
/// <param name="filename">The path of the file to read.</param>
/// <returns>An instance of the <see cref="IPolygon" /> class.</returns>
public static InputGeometry Read(string filename)
{
foreach (IPolygonFormat format in formats)
{
if (format != null && format.IsSupported(filename))
{
return format.Read(filename);
}
}
throw new Exception("File format not supported.");
}
/// <summary>
/// Save a polygon geometry to disk.
/// </summary>
/// <param name="mesh">An instance of the <see cref="IPolygon" /> class.</param>
/// <param name="filename">The path of the file to save.</param>
public static void Write(InputGeometry polygon, string filename)
{
foreach (IPolygonFormat format in formats)
{
if (format != null && format.IsSupported(filename))
{
format.Write(polygon, filename);
}
}
throw new Exception("File format not supported.");
}
#endregion
#region Mesh read/write
/// <summary>
/// Read a file containing a mesh.
/// </summary>
/// <param name="filename">The path of the file to read.</param>
/// <returns>An instance of the <see cref="IMesh" /> interface.</returns>
public static Mesh Import(string filename)
{
foreach (IMeshFormat format in formats)
{
if (format != null && format.IsSupported(filename))
{
return format.Import(filename);
}
}
throw new Exception("File format not supported.");
}
/// <summary>
/// Save a mesh to disk.
/// </summary>
/// <param name="mesh">An instance of the <see cref="IMesh" /> interface.</param>
/// <param name="filename">The path of the file to save.</param>
public static void Write(Mesh mesh, string filename)
{
foreach (IMeshFormat format in formats)
{
if (format != null && format.IsSupported(filename))
{
format.Write(mesh, filename);
}
}
throw new Exception("File format not supported.");
}
#endregion
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace TriangleNet.IO
{
public interface IFileFormat
{
bool IsSupported(string file);
}
}
@@ -1,27 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="IGeometryFormat.cs" company="">
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet.IO
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleNet.Geometry;
/// <summary>
/// Interface for geometry input.
/// </summary>
public interface IGeometryFormat
{
/// <summary>
/// Read a file containing geometry information.
/// </summary>
/// <param name="filename">The path of the file to read.</param>
/// <returns>An instance of the <see cref="InputGeometry" /> class.</returns>
InputGeometry Read(string filename);
}
}
+11 -8
View File
@@ -6,29 +6,32 @@
namespace TriangleNet.IO
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleNet.Geometry;
using System.IO;
/// <summary>
/// Interface for mesh I/O.
/// </summary>
public interface IMeshFormat
public interface IMeshFormat : IFileFormat
{
/// <summary>
/// Read a file containing a mesh.
/// </summary>
/// <param name="filename">The path of the file to read.</param>
/// <returns>An instance of the <see cref="Mesh" /> class.</returns>
/// <returns>An instance of the <see cref="IMesh" /> interface.</returns>
Mesh Import(string filename);
/// <summary>
/// Save a mesh to disk.
/// </summary>
/// <param name="mesh">An instance of the <see cref="Mesh" /> class.</param>
/// <param name="mesh">An instance of the <see cref="IMesh" /> interface.</param>
/// <param name="filename">The path of the file to save.</param>
void Write(Mesh mesh, string filename);
/// <summary>
/// Save a mesh to a <see cref="StreamWriter" />.
/// </summary>
/// <param name="mesh">An instance of the <see cref="IMesh" /> interface.</param>
/// <param name="stream">The stream to save to.</param>
void Write(Mesh mesh, StreamWriter stream);
}
}
@@ -0,0 +1,38 @@
// -----------------------------------------------------------------------
// <copyright file="IGeometryFormat.cs" company="">
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet.IO
{
using System.IO;
using TriangleNet.Geometry;
/// <summary>
/// Interface for geometry input.
/// </summary>
public interface IPolygonFormat : IFileFormat
{
/// <summary>
/// Read a file containing polygon geometry.
/// </summary>
/// <param name="filename">The path of the file to read.</param>
/// <returns>An instance of the <see cref="IPolygon" /> class.</returns>
InputGeometry Read(string filename);
/// <summary>
/// Save a polygon geometry to disk.
/// </summary>
/// <param name="polygon">An instance of the <see cref="IPolygon" /> class.</param>
/// <param name="filename">The path of the file to save.</param>
void Write(InputGeometry polygon, string filename);
/// <summary>
/// Save a polygon geometry to a <see cref="StreamWriter" />.
/// </summary>
/// <param name="polygon">An instance of the <see cref="IPolygon" /> class.</param>
/// <param name="stream">The stream to save to.</param>
void Write(InputGeometry polygon, StreamWriter stream);
}
}
+39 -13
View File
@@ -8,16 +8,27 @@ namespace TriangleNet.IO
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleNet.Geometry;
using System.IO;
using TriangleNet.Geometry;
using TriangleNet.Meshing;
/// <summary>
/// Implements geometry and mesh file formats of the the original Triangle code.
/// </summary>
public class TriangleFormat : IGeometryFormat, IMeshFormat
public class TriangleFormat : IPolygonFormat, IMeshFormat
{
public bool IsSupported(string file)
{
string ext = Path.GetExtension(file);
if (ext == ".node" || ext == ".poly" || ext == ".ele")
{
return true;
}
return false;
}
public Mesh Import(string filename)
{
string ext = Path.GetExtension(filename);
@@ -27,14 +38,13 @@ namespace TriangleNet.IO
List<ITriangle> triangles;
InputGeometry geometry;
FileReader.Read(filename, out geometry, out triangles);
TriangleReader.Read(filename, out geometry, out triangles);
if (geometry != null && triangles != null)
{
Mesh mesh = new Mesh();
mesh.Load(geometry, triangles);
var converter = new Converter();
return mesh;
return converter.ToMesh(geometry, triangles.ToArray());
}
}
@@ -43,8 +53,13 @@ namespace TriangleNet.IO
public void Write(Mesh mesh, string filename)
{
FileWriter.WritePoly(mesh, Path.ChangeExtension(filename, ".poly"));
FileWriter.WriteElements(mesh, Path.ChangeExtension(filename, ".ele"));
TriangleWriter.WritePoly((Mesh)mesh, Path.ChangeExtension(filename, ".poly"));
TriangleWriter.WriteElements((Mesh)mesh, Path.ChangeExtension(filename, ".ele"));
}
public void Write(Mesh mesh, StreamWriter stream)
{
throw new NotImplementedException();
}
public InputGeometry Read(string filename)
@@ -53,15 +68,26 @@ namespace TriangleNet.IO
if (ext == ".node")
{
return FileReader.ReadNodeFile(filename);
return TriangleReader.ReadNodeFile(filename);
}
if (ext == ".poly")
{
return FileReader.ReadPolyFile(filename);
return TriangleReader.ReadPolyFile(filename);
}
throw new NotSupportedException("File format '" + ext + "' not supported.");
}
public void Write(InputGeometry polygon, string filename)
{
TriangleWriter.WritePoly(polygon, filename);
}
public void Write(InputGeometry polygon, StreamWriter stream)
{
throw new NotImplementedException();
}
}
}
@@ -18,7 +18,7 @@ namespace TriangleNet.IO
/// <summary>
/// Helper methods for reading Triangle file formats.
/// </summary>
public static class FileReader
public static class TriangleReader
{
static NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
static int startIndex = 0;
@@ -99,12 +99,12 @@ namespace TriangleNet.IO
if (File.Exists(path))
{
geometry = FileReader.ReadPolyFile(path);
geometry = TriangleReader.ReadPolyFile(path);
}
else
{
path = Path.ChangeExtension(filename, ".node");
geometry = FileReader.ReadNodeFile(path);
geometry = TriangleReader.ReadNodeFile(path);
}
}
@@ -115,13 +115,13 @@ namespace TriangleNet.IO
{
triangles = null;
FileReader.Read(filename, out geometry);
TriangleReader.Read(filename, out geometry);
string path = Path.ChangeExtension(filename, ".ele");
if (File.Exists(path) && geometry != null)
{
triangles = FileReader.ReadEleFile(path);
triangles = TriangleReader.ReadEleFile(path);
}
}
@@ -132,7 +132,7 @@ namespace TriangleNet.IO
{
InputGeometry geometry = null;
FileReader.Read(filename, out geometry);
TriangleReader.Read(filename, out geometry);
return geometry;
}
@@ -17,7 +17,7 @@ namespace TriangleNet.IO
/// <summary>
/// Helper methods for writing Triangle file formats.
/// </summary>
public static class FileWriter
public static class TriangleWriter
{
static NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat;
@@ -28,8 +28,8 @@ namespace TriangleNet.IO
/// <param name="filename"></param>
public static void Write(Mesh mesh, string filename)
{
FileWriter.WritePoly(mesh, Path.ChangeExtension(filename, ".poly"));
FileWriter.WriteElements(mesh, Path.ChangeExtension(filename, ".ele"));
TriangleWriter.WritePoly(mesh, Path.ChangeExtension(filename, ".poly"));
TriangleWriter.WriteElements(mesh, Path.ChangeExtension(filename, ".ele"));
}
/// <summary>
@@ -41,7 +41,7 @@ namespace TriangleNet.IO
{
using (StreamWriter writer = new StreamWriter(filename))
{
FileWriter.WriteNodes(writer, mesh);
TriangleWriter.WriteNodes(writer, mesh);
}
}
@@ -177,6 +177,69 @@ namespace TriangleNet.IO
}
}
/// <summary>
/// Write the segments and holes to a .poly file.
/// </summary>
/// <param name="polygon">Data source.</param>
/// <param name="filename">File name.</param>
/// <param name="writeNodes">Write nodes into this file.</param>
/// <remarks>If the nodes should not be written into this file,
/// make sure a .node file was written before, so that the nodes
/// are numbered right.</remarks>
public static void WritePoly(InputGeometry polygon, string filename)
{
bool hasMarkers = true;
using (StreamWriter writer = new StreamWriter(filename))
{
// TODO: write vertex attributes
// Write nodes to this file.
TriangleWriter.WriteNodes(writer, polygon.points, true, 0, false);
// Number of segments, number of boundary markers (zero or one).
writer.WriteLine("{0} {1}", polygon.Segments.Count, hasMarkers ? "1" : "0");
int j = 0;
foreach (var seg in polygon.Segments)
{
// Segment number, indices of its two endpoints, and possibly a marker.
if (hasMarkers)
{
writer.WriteLine("{0} {1} {2} {3}", j, seg.P0, seg.P1, seg.Boundary);
}
else
{
writer.WriteLine("{0} {1} {2}", j, seg.P0, seg.P1);
}
j++;
}
// Holes
j = 0;
writer.WriteLine("{0}", polygon.Holes.Count);
foreach (var hole in polygon.Holes)
{
writer.WriteLine("{0} {1} {2}", j++, hole.X.ToString(nfi), hole.Y.ToString(nfi));
}
// Regions
if (polygon.Regions.Count > 0)
{
j = 0;
writer.WriteLine("{0}", polygon.Regions.Count);
foreach (var region in polygon.Regions)
{
writer.WriteLine("{0} {1} {2} {3}", j, region.point.X.ToString(nfi),
region.point.Y.ToString(nfi), region.id);
j++;
}
}
}
}
/// <summary>
/// Write the segments and holes to a .poly file.
/// </summary>
@@ -184,7 +247,7 @@ namespace TriangleNet.IO
/// <param name="filename"></param>
public static void WritePoly(Mesh mesh, string filename)
{
FileWriter.WritePoly(mesh, filename, true);
TriangleWriter.WritePoly(mesh, filename, true);
}
/// <summary>
@@ -208,7 +271,7 @@ namespace TriangleNet.IO
if (writeNodes)
{
// Write nodes to this file.
FileWriter.WriteNodes(writer, mesh);
TriangleWriter.WriteNodes(writer, mesh);
}
else
{
+6 -74
View File
@@ -13,7 +13,8 @@ namespace TriangleNet
using TriangleNet.Data;
using TriangleNet.Log;
using TriangleNet.IO;
using TriangleNet.Algorithm;
using TriangleNet.Meshing;
using TriangleNet.Meshing.Algorithm;
using TriangleNet.Smoothing;
using TriangleNet.Geometry;
using TriangleNet.Tools;
@@ -48,7 +49,7 @@ namespace TriangleNet
internal List<RegionPointer> regions;
// Other variables.
internal BoundingBox bounds; // x and y bounds.
internal Rectangle bounds; // x and y bounds.
internal int invertices; // Number of input vertices.
internal int inelements; // Number of input triangles.
internal int insegments; // Number of input segments.
@@ -95,7 +96,7 @@ namespace TriangleNet
/// <summary>
/// Gets the mesh bounding box.
/// </summary>
public BoundingBox Bounds
public Rectangle Bounds
{
get { return this.bounds; }
}
@@ -213,82 +214,13 @@ namespace TriangleNet
}
}
/// <summary>
/// Load a mesh from file (.node/poly and .ele).
/// </summary>
public void Load(string filename)
{
List<ITriangle> triangles;
InputGeometry geometry;
FileReader.Read(filename, out geometry, out triangles);
if (geometry != null && triangles != null)
{
Load(geometry, triangles);
}
}
/// <summary>
/// Reconstructs a mesh from raw input data.
/// </summary>
public void Load(InputGeometry input, List<ITriangle> triangles)
{
if (input == null || triangles == null)
{
throw new ArgumentException("Invalid input (argument is null).");
}
// Clear all data structures / reset hash seeds
this.ResetData();
if (input.HasSegments)
{
behavior.Poly = true;
this.holes.AddRange(input.Holes);
}
//if (input.EdgeMarkers != null)
//{
// behavior.UseBoundaryMarkers = true;
//}
//if (input.TriangleAreas != null)
//{
// behavior.VarArea = true;
//}
// TODO: remove
if (!behavior.Poly)
{
// Be careful not to allocate space for element area constraints that
// will never be assigned any value (other than the default -1.0).
behavior.VarArea = false;
// Be careful not to add an extra attribute to each element unless the
// input supports it (PSLG in, but not refining a preexisting mesh).
behavior.useRegions = false;
}
behavior.useRegions = input.Regions.Count > 0;
TransferNodes(input);
// Read and reconstruct a mesh.
hullsize = DataReader.Reconstruct(this, input, triangles.ToArray());
// Calculate the number of edges.
edges = (3 * triangles.Count + hullsize) / 2;
}
/// <summary>
/// Triangulate given input file (.node or .poly).
/// </summary>
/// <param name="input"></param>
public void Triangulate(string inputFile)
{
InputGeometry input = FileReader.Read(inputFile);
InputGeometry input = TriangleReader.Read(inputFile);
this.Triangulate(input);
}
@@ -693,7 +625,7 @@ namespace TriangleNet
/// Read the vertices from memory.
/// </summary>
/// <param name="data">The input data.</param>
private void TransferNodes(InputGeometry data)
internal void TransferNodes(InputGeometry data)
{
List<Vertex> points = data.points;
@@ -5,7 +5,7 @@
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet.Algorithm
namespace TriangleNet.Meshing.Algorithm
{
using System;
using TriangleNet.Data;
@@ -5,7 +5,7 @@
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet.Algorithm
namespace TriangleNet.Meshing.Algorithm
{
using TriangleNet.Data;
using TriangleNet.Log;
@@ -29,7 +29,7 @@ namespace TriangleNet.Algorithm
void GetBoundingBox()
{
Otri inftri = default(Otri); // Handle for the triangular bounding box.
BoundingBox box = mesh.bounds;
Rectangle box = mesh.bounds;
// Find the width (or height, whichever is larger) of the triangulation.
double width = box.Width;
@@ -42,9 +42,9 @@ namespace TriangleNet.Algorithm
width = 1.0;
}
// Create the vertices of the bounding box.
mesh.infvertex1 = new Vertex(box.MinX - 50.0 * width, box.MinY - 40.0 * width);
mesh.infvertex2 = new Vertex(box.MaxX + 50.0 * width, box.MinY - 40.0 * width);
mesh.infvertex3 = new Vertex(0.5 * (box.MinX + box.MaxX), box.MaxY + 60.0 * width);
mesh.infvertex1 = new Vertex(box.Left - 50.0 * width, box.Bottom - 40.0 * width);
mesh.infvertex2 = new Vertex(box.Right + 50.0 * width, box.Bottom - 40.0 * width);
mesh.infvertex3 = new Vertex(0.5 * (box.Left + box.Right), box.Top + 60.0 * width);
// Create the bounding box.
mesh.MakeTriangle(ref inftri);
@@ -5,7 +5,7 @@
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet.Algorithm
namespace TriangleNet.Meshing.Algorithm
{
using System;
using System.Collections.Generic;
@@ -525,7 +525,7 @@ namespace TriangleNet.Algorithm
// Nonexistent x value used as a flag to mark circle events in sweepline
// Delaunay algorithm.
xminextreme = 10 * mesh.bounds.MinX - 9 * mesh.bounds.MaxX;
xminextreme = 10 * mesh.bounds.Left - 9 * mesh.bounds.Right;
SweepEvent[] eventheap;
@@ -603,7 +603,7 @@ namespace TriangleNet.Algorithm
HeapDelete(eventheap, heapsize, 0);
heapsize--;
check4events = true;
if (nextevent.xkey < mesh.bounds.MinX)
if (nextevent.xkey < mesh.bounds.Left)
{
fliptri = nextevent.otriEvent;
fliptri.Oprev(ref farlefttri);
@@ -5,7 +5,7 @@
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet
namespace TriangleNet.Meshing
{
using System;
using System.Collections.Generic;
@@ -0,0 +1,31 @@
namespace TriangleNet.Meshing
{
public class ConstraintOptions
{
public static ConstraintOptions Empty
{
get { return new ConstraintOptions(); }
}
#region Public properties
/// <summary>
/// Gets or sets a value indicating wether to use regions.
/// </summary>
public bool UseRegions { get; set; }
/// <summary>
/// Gets or sets a value indicating wether to create a Conforming
/// Delaunay triangulation.
/// </summary>
public bool ConformingDelaunay { get; set; }
/// <summary>
/// Enclose the convex hull with segments.
/// </summary>
public bool Convex { get; set; }
#endregion
}
}
@@ -1,32 +1,32 @@
// -----------------------------------------------------------------------
// <copyright file="DataReader.cs" company="">
// <copyright file="Converter.cs" company="">
// 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.IO
namespace TriangleNet.Meshing
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Globalization;
using TriangleNet.Data;
using TriangleNet.Log;
using TriangleNet.Geometry;
using TriangleNet.Log;
/// <summary>
/// The DataReader class provides methods for mesh reconstruction.
/// </summary>
static class DataReader
public class Converter
{
public Mesh ToMesh(InputGeometry polygon, IList<ITriangle> triangles)
{
return ToMesh(polygon, triangles.ToArray());
}
/// <summary>
/// Reconstruct a triangulation from its raw data representation.
/// </summary>
/// <param name="mesh"></param>
/// <param name="input"></param>
/// <returns></returns>
/// <remarks>
/// Reads an .ele file and reconstructs the original mesh. If the -p switch
/// is used, this procedure will also read a .poly file and reconstruct the
@@ -46,43 +46,33 @@ namespace TriangleNet.IO
/// the corresponding pointer is adjusted to refer to a subsegment rather
/// than the next triangle of the stack.
/// </remarks>
public static int Reconstruct(Mesh mesh, InputGeometry input, ITriangle[] triangles)
public Mesh ToMesh(InputGeometry polygon, ITriangle[] triangles)
{
int hullsize = 0;
Otri tri = default(Otri);
Otri triangleleft = default(Otri);
Otri checktri = default(Otri);
Otri checkleft = default(Otri);
Otri checkneighbor = default(Otri);
Osub subseg = default(Osub);
List<Otri>[] vertexarray; // Triangle
Otri prevlink; // Triangle
Otri nexttri; // Triangle
Vertex tdest, tapex;
Vertex checkdest, checkapex;
Vertex shorg;
Vertex segmentorg, segmentdest;
int[] corner = new int[3];
int[] end = new int[2];
//bool segmentmarkers = false;
int boundmarker;
int aroundvertex;
bool notfound;
int i = 0;
int elements = triangles == null ? 0 : triangles.Length;
int numberofsegments = input.segments.Count;
int numberofsegments = polygon.Segments.Count;
var mesh = new Mesh();
mesh.TransferNodes(polygon);
mesh.inelements = elements;
mesh.regions.AddRange(input.regions);
mesh.regions.AddRange(polygon.Regions);
mesh.behavior.useRegions = polygon.Regions.Count > 0;
if (polygon.Segments.Count > 0)
{
mesh.behavior.Poly = true;
mesh.holes.AddRange(polygon.Holes);
}
// Create the triangles.
for (i = 0; i < mesh.inelements; i++)
{
mesh.MakeTriangle(ref tri);
// Mark the triangle as living.
//tri.triangle.neighbors[0].triangle = tri.triangle;
}
if (mesh.behavior.Poly)
@@ -93,15 +83,37 @@ namespace TriangleNet.IO
for (i = 0; i < mesh.insegments; i++)
{
mesh.MakeSegment(ref subseg);
// Mark the subsegment as living.
//subseg.ss.subsegs[0].ss = subseg.ss;
}
}
var vertexarray = SetNeighbors(mesh, triangles);
SetSegments(mesh, polygon, vertexarray);
return mesh;
}
/// <summary>
/// Finds the adjacencies between triangles by forming a stack of triangles
/// for each vertex.
/// </summary>
private static List<Otri>[] SetNeighbors(Mesh mesh, ITriangle[] triangles)
{
Otri tri = default(Otri);
Otri triangleleft = default(Otri);
Otri checktri = default(Otri);
Otri checkleft = default(Otri);
Otri nexttri; // Triangle
Vertex tdest, tapex;
Vertex checkdest, checkapex;
int[] corner = new int[3];
int aroundvertex;
int i;
// Allocate a temporary array that maps each vertex to some adjacent
// triangle. I took care to allocate all the permanent memory for
// triangles and subsegments first.
vertexarray = new List<Otri>[mesh.vertices.Count];
// triangle.
var vertexarray = new List<Otri>[mesh.vertices.Count];
// Each vertex is initially unrepresented.
for (i = 0; i < mesh.vertices.Count; i++)
{
@@ -198,21 +210,41 @@ namespace TriangleNet.IO
i++;
}
return vertexarray;
}
private static void SetSegments(Mesh mesh, InputGeometry polygon, List<Otri>[] vertexarray)
{
Otri checktri = default(Otri);
Otri nexttri; // Triangle
Vertex checkdest;
Otri checkneighbor = default(Otri);
Osub subseg = default(Osub);
Otri prevlink; // Triangle
Vertex shorg;
Vertex segmentorg, segmentdest;
int[] end = new int[2];
bool notfound;
//bool segmentmarkers = false;
int boundmarker;
int aroundvertex;
int i;
int hullsize = 0;
// Prepare to count the boundary edges.
hullsize = 0;
if (mesh.behavior.Poly)
{
// Read the segments from the .poly file, and link them
// to their neighboring triangles.
// Link the segments to their neighboring triangles.
boundmarker = 0;
i = 0;
foreach (var item in mesh.subsegs.Values)
{
subseg.seg = item;
end[0] = input.segments[i].P0;
end[1] = input.segments[i].P1;
boundmarker = input.segments[i].Boundary;
end[0] = polygon.segments[i].P0;
end[1] = polygon.segments[i].P1;
boundmarker = polygon.segments[i].Boundary;
for (int j = 0; j < 2; j++)
{
@@ -316,7 +348,8 @@ namespace TriangleNet.IO
}
}
return hullsize;
mesh.hullsize = hullsize;
mesh.edges = (3 * mesh.triangles.Count + hullsize) / 2;
}
}
}
@@ -0,0 +1,11 @@
namespace TriangleNet.Meshing
{
using TriangleNet.Geometry;
public interface IConstraintMesher
{
Mesh Triangulate(IPolygon polygon);
Mesh Triangulate(IPolygon polygon, ConstraintOptions options);
}
}
@@ -0,0 +1,11 @@
namespace TriangleNet.Meshing
{
using TriangleNet.Geometry;
public interface IQualityMesher
{
Mesh Triangulate(IPolygon polygon, QualityOptions quality);
Mesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOptions quality);
}
}
@@ -4,7 +4,7 @@
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet.Algorithm
namespace TriangleNet.Meshing
{
using System;
using System.Collections.Generic;
@@ -5,7 +5,7 @@
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet
namespace TriangleNet.Meshing
{
using System;
using System.Collections.Generic;
@@ -0,0 +1,38 @@
namespace TriangleNet.Meshing
{
using System;
using TriangleNet.Geometry;
public class QualityOptions
{
public static QualityOptions Empty
{
get { return new QualityOptions(); }
}
#region Public properties
/// <summary>
/// Gets or sets a maximum angle constraint.
/// </summary>
public double MaximumAngle { get; set; }
/// <summary>
/// Gets or sets a minimum angle constraint.
/// </summary>
public double MinimumAngle { get; set; }
/// <summary>
/// Gets or sets a maximum triangle area constraint.
/// </summary>
public double MaximumArea { get; set; }
/// <summary>
/// Apply a user-defined triangle constraint.
/// </summary>
public Func<ITriangle, double, bool> UserTest { get; set; }
#endregion
}
}
+26 -26
View File
@@ -133,7 +133,7 @@ namespace TriangleNet.Tools
static readonly byte[] BITVECTOR = { 0x1, 0x2, 0x4, 0x8 };
BoundingBox bounds;
Rectangle bounds;
Point pivot;
QuadTree tree;
QuadNode[] regions;
@@ -141,17 +141,17 @@ namespace TriangleNet.Tools
byte bitRegions;
public QuadNode(BoundingBox box, QuadTree tree)
public QuadNode(Rectangle box, QuadTree tree)
: this(box, tree, false)
{
}
public QuadNode(BoundingBox box, QuadTree tree, bool init)
public QuadNode(Rectangle box, QuadTree tree, bool init)
{
this.tree = tree;
this.bounds = new BoundingBox(box.MinX, box.MinY, box.MaxX, box.MaxY);
this.pivot = new Point((box.MinX + box.MaxX) / 2, (box.MinY + box.MaxY) / 2);
this.bounds = new Rectangle(box.Left, box.Bottom, box.Right, box.Top);
this.pivot = new Point((box.Left + box.Right) / 2, (box.Bottom + box.Top) / 2);
this.bitRegions = 0;
@@ -190,22 +190,22 @@ namespace TriangleNet.Tools
// |------+pivot--|
// | sw | se |
// +--------------+
BoundingBox box;
Rectangle box;
// 1. region south west
box = new BoundingBox(bounds.MinX, bounds.MinY, pivot.X, pivot.Y);
box = new Rectangle(bounds.Left, bounds.Bottom, pivot.X, pivot.Y);
regions[0] = new QuadNode(box, tree);
// 2. region south east
box = new BoundingBox(pivot.X, bounds.MinY, bounds.MaxX, pivot.Y);
box = new Rectangle(pivot.X, bounds.Bottom, bounds.Right, pivot.Y);
regions[1] = new QuadNode(box, tree);
// 3. region north west
box = new BoundingBox(bounds.MinX, pivot.Y, pivot.X, bounds.MaxY);
box = new Rectangle(bounds.Left, pivot.Y, pivot.X, bounds.Top);
regions[2] = new QuadNode(box, tree);
// 4. region north east
box = new BoundingBox(pivot.X, pivot.Y, bounds.MaxX, bounds.MaxY);
box = new Rectangle(pivot.X, pivot.Y, bounds.Right, bounds.Top);
regions[3] = new QuadNode(box, tree);
Point[] triangle = new Point[3];
@@ -295,12 +295,12 @@ namespace TriangleNet.Tools
// we have an intersection
double yComponent = triangle[k].Y + t * dy;
if (yComponent < pivot.Y && yComponent >= bounds.MinY)
if (yComponent < pivot.Y && yComponent >= bounds.Bottom)
{
AddToRegion(index, SW);
AddToRegion(index, SE);
}
else if (yComponent <= bounds.MaxY)
else if (yComponent <= bounds.Top)
{
AddToRegion(index, NW);
AddToRegion(index, NE);
@@ -308,34 +308,34 @@ namespace TriangleNet.Tools
}
// find intersection with plane x = m_boundingBox[0].dX
t = (bounds.MinX - triangle[k].X) / dx;
t = (bounds.Left - triangle[k].X) / dx;
if (t < (1 + EPS) && t > -EPS)
{
// we have an intersection
double yComponent = triangle[k].Y + t * dy;
if (yComponent < pivot.Y && yComponent >= bounds.MinY)
if (yComponent < pivot.Y && yComponent >= bounds.Bottom)
{
AddToRegion(index, SW);
}
else if (yComponent <= bounds.MaxY) // TODO: check && yComponent >= pivot.Y
else if (yComponent <= bounds.Top) // TODO: check && yComponent >= pivot.Y
{
AddToRegion(index, NW);
}
}
// find intersection with plane x = m_boundingBox[1].dX
t = (bounds.MaxX - triangle[k].X) / dx;
t = (bounds.Right - triangle[k].X) / dx;
if (t < (1 + EPS) && t > -EPS)
{
// we have an intersection
double yComponent = triangle[k].Y + t * dy;
if (yComponent < pivot.Y && yComponent >= bounds.MinY)
if (yComponent < pivot.Y && yComponent >= bounds.Bottom)
{
AddToRegion(index, SE);
}
else if (yComponent <= bounds.MaxY)
else if (yComponent <= bounds.Top)
{
AddToRegion(index, NE);
}
@@ -353,12 +353,12 @@ namespace TriangleNet.Tools
// we have an intersection
xComponent = triangle[k].X + t * dx;
if (xComponent > pivot.X && xComponent <= bounds.MaxX)
if (xComponent > pivot.X && xComponent <= bounds.Right)
{
AddToRegion(index, SE);
AddToRegion(index, NE);
}
else if (xComponent >= bounds.MinX)
else if (xComponent >= bounds.Left)
{
AddToRegion(index, SW);
AddToRegion(index, NW);
@@ -366,34 +366,34 @@ namespace TriangleNet.Tools
}
// find intersection with plane y = m_boundingBox[0].dY
t = (bounds.MinY - triangle[k].Y) / dy;
t = (bounds.Bottom - triangle[k].Y) / dy;
if (t < (1 + EPS) && t > -EPS)
{
// we have an intersection
xComponent = triangle[k].X + t * dx;
if (xComponent > pivot.X && xComponent <= bounds.MaxX)
if (xComponent > pivot.X && xComponent <= bounds.Right)
{
AddToRegion(index, SE);
}
else if (xComponent >= bounds.MinX)
else if (xComponent >= bounds.Left)
{
AddToRegion(index, SW);
}
}
// find intersection with plane y = m_boundingBox[1].dY
t = (bounds.MaxY - triangle[k].Y) / dy;
t = (bounds.Top - triangle[k].Y) / dy;
if (t < (1 + EPS) && t > -EPS)
{
// we have an intersection
xComponent = triangle[k].X + t * dx;
if (xComponent > pivot.X && xComponent <= bounds.MaxX)
if (xComponent > pivot.X && xComponent <= bounds.Right)
{
AddToRegion(index, NE);
}
else if (xComponent >= bounds.MinX)
else if (xComponent >= bounds.Left)
{
AddToRegion(index, NW);
}
+7 -7
View File
@@ -27,7 +27,7 @@ namespace TriangleNet.Tools
int rayIndex;
// Bounding box of the triangles circumcenters.
BoundingBox bounds;
Rectangle bounds;
/// <summary>
/// Initializes a new instance of the <see cref="Voronoi" /> class.
@@ -82,7 +82,7 @@ namespace TriangleNet.Tools
rayPoints = new Dictionary<int, Point>();
rayIndex = 0;
bounds = new BoundingBox();
bounds = new Rectangle();
// Compute triangles circumcenters and setup bounding box
ComputeCircumCenters();
@@ -119,7 +119,7 @@ namespace TriangleNet.Tools
points[item.id] = pt;
bounds.Expand(pt.x, pt.y);
bounds.Expand(pt);
}
double ds = Math.Max(bounds.Width, bounds.Height);
@@ -269,10 +269,10 @@ namespace TriangleNet.Tools
double t1, x1, y1, t2, x2, y2;
// Bounding box
double minX = bounds.MinX;
double maxX = bounds.MaxX;
double minY = bounds.MinY;
double maxY = bounds.MaxY;
double minX = bounds.Left;
double maxX = bounds.Right;
double minY = bounds.Bottom;
double maxY = bounds.Top;
// Check if point is inside the bounds
if (x < minX || x > maxX || y < minY || y > maxY)
+23 -12
View File
@@ -41,10 +41,19 @@
<Reference Include="System.Data" />
</ItemGroup>
<ItemGroup>
<Compile Include="Algorithm\ITriangulator.cs" />
<Compile Include="Geometry\IEdge.cs" />
<Compile Include="Geometry\IPolygon.cs" />
<Compile Include="Geometry\Polygon.cs" />
<Compile Include="IO\FileProcessor.cs" />
<Compile Include="IO\IFileFormat.cs" />
<Compile Include="Meshing\ConstraintOptions.cs" />
<Compile Include="Meshing\Converter.cs" />
<Compile Include="Meshing\IConstraintMesher.cs" />
<Compile Include="Meshing\IQualityMesher.cs" />
<Compile Include="Meshing\ITriangulator.cs" />
<Compile Include="BadTriQueue.cs" />
<Compile Include="Behavior.cs" />
<Compile Include="ConstraintMesher.cs" />
<Compile Include="Meshing\ConstraintMesher.cs" />
<Compile Include="Data\BadSubseg.cs" />
<Compile Include="Data\BadTriangle.cs" />
<Compile Include="Data\Osub.cs" />
@@ -52,8 +61,8 @@
<Compile Include="Data\Segment.cs" />
<Compile Include="Data\Triangle.cs" />
<Compile Include="Data\Vertex.cs" />
<Compile Include="Algorithm\Dwyer.cs" />
<Compile Include="Geometry\BoundingBox.cs" />
<Compile Include="Meshing\Algorithm\Dwyer.cs" />
<Compile Include="Geometry\Rectangle.cs" />
<Compile Include="Geometry\Edge.cs" />
<Compile Include="Geometry\EdgeEnumerator.cs" />
<Compile Include="Geometry\InputGeometry.cs" />
@@ -61,23 +70,23 @@
<Compile Include="Geometry\Point.cs" />
<Compile Include="Geometry\RegionPointer.cs" />
<Compile Include="Geometry\ISegment.cs" />
<Compile Include="IO\DataReader.cs" />
<Compile Include="IO\DebugWriter.cs" />
<Compile Include="IO\FileWriter.cs" />
<Compile Include="IO\IGeometryFormat.cs" />
<Compile Include="IO\TriangleWriter.cs" />
<Compile Include="IO\IPolygonFormat.cs" />
<Compile Include="IO\IMeshFormat.cs" />
<Compile Include="IO\InputTriangle.cs" />
<Compile Include="IO\FileReader.cs" />
<Compile Include="IO\TriangleReader.cs" />
<Compile Include="IO\TriangleFormat.cs" />
<Compile Include="Log\ILog.cs" />
<Compile Include="Log\ILogItem.cs" />
<Compile Include="Log\SimpleLog.cs" />
<Compile Include="Log\SimpleLogItem.cs" />
<Compile Include="Meshing\QualityOptions.cs" />
<Compile Include="MeshValidator.cs" />
<Compile Include="NewLocation.cs" />
<Compile Include="QualityMesher.cs" />
<Compile Include="Meshing\QualityMesher.cs" />
<Compile Include="Enums.cs" />
<Compile Include="Algorithm\Incremental.cs" />
<Compile Include="Meshing\Algorithm\Incremental.cs" />
<Compile Include="Mesh.cs" />
<Compile Include="Primitives.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -92,12 +101,14 @@
<Compile Include="Tools\QualityMeasure.cs" />
<Compile Include="Tools\RegionIterator.cs" />
<Compile Include="Tools\Statistic.cs" />
<Compile Include="Algorithm\SweepLine.cs" />
<Compile Include="Meshing\Algorithm\SweepLine.cs" />
<Compile Include="Tools\Voronoi.cs" />
<Compile Include="Tools\VoronoiRegion.cs" />
<Compile Include="TriangleLocator.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="Algorithm\" />
</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.