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:
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
-24
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
+69
-6
@@ -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
|
||||
{
|
||||
@@ -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;
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Algorithm
|
||||
namespace TriangleNet.Meshing.Algorithm
|
||||
{
|
||||
using System;
|
||||
using TriangleNet.Data;
|
||||
+5
-5
@@ -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);
|
||||
+3
-3
@@ -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);
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
}
|
||||
+78
-45
@@ -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);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace TriangleNet.Algorithm
|
||||
namespace TriangleNet.Meshing
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user