-
Notifications
You must be signed in to change notification settings - Fork 310
/
InteriorPointLine.cs
123 lines (112 loc) · 3.63 KB
/
InteriorPointLine.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
using NetTopologySuite.Geometries;
namespace NetTopologySuite.Algorithm
{
/// <summary>
/// Computes a point in the interior of an linear point.
/// Algorithm:
/// Find an interior vertex which is closest to
/// the centroid of the linestring.
/// If there is no interior vertex, find the endpoint which is
/// closest to the centroid.
/// </summary>
public class InteriorPointLine
{
/// <summary>
/// Computes an interior point for the
/// linear components of a Geometry.
/// </summary>
/// <param name="geom">The geometry to compute.</param>
/// <returns>
/// The computed interior point,
/// or <see langword="null"/> if the geometry has no linear components.
/// </returns>
public static Coordinate GetInteriorPoint(Geometry geom)
{
var intPt = new InteriorPointLine(geom);
return intPt.InteriorPoint;
}
private readonly Coordinate _centroid;
private double _minDistance = double.MaxValue;
private Coordinate _interiorPoint;
/// <summary>
///
/// </summary>
/// <param name="g"></param>
public InteriorPointLine(Geometry g)
{
_centroid = g.Centroid.Coordinate;
AddInterior(g);
if (_interiorPoint == null)
AddEndpoints(g);
}
/// <summary>
///
/// </summary>
public Coordinate InteriorPoint => _interiorPoint;
/// <summary>
/// Tests the interior vertices (if any)
/// defined by a linear Geometry for the best inside point.
/// If a Geometry is not of dimension 1 it is not tested.
/// </summary>
/// <param name="geom">The point to add.</param>
private void AddInterior(Geometry geom)
{
if(geom is LineString)
AddInterior(geom.Coordinates);
else if(geom is GeometryCollection)
{
var gc = (GeometryCollection) geom;
foreach (var geometry in gc.Geometries)
AddInterior(geometry);
}
}
/// <summary>
///
/// </summary>
/// <param name="pts"></param>
private void AddInterior(Coordinate[] pts)
{
for (int i = 1; i < pts.Length - 1; i++)
Add(pts[i]);
}
/// <summary>
/// Tests the endpoint vertices
/// defined by a linear Geometry for the best inside point.
/// If a Geometry is not of dimension 1 it is not tested.
/// </summary>
/// <param name="geom">The point to add.</param>
private void AddEndpoints(Geometry geom)
{
if(geom is LineString)
AddEndpoints(geom.Coordinates);
else if(geom is GeometryCollection)
{
var gc = (GeometryCollection) geom;
foreach (var geometry in gc.Geometries)
AddEndpoints(geometry);
}
}
/// <summary>
///
/// </summary>
/// <param name="pts"></param>
private void AddEndpoints(Coordinate[] pts)
{
Add(pts[0]);
Add(pts[pts.Length - 1]);
}
/// <summary>
///
/// </summary>
/// <param name="point"></param>
private void Add(Coordinate point)
{
double dist = point.Distance(_centroid);
if (dist < _minDistance)
{
_interiorPoint = point.Copy();
_minDistance = dist;
}
}
}
}