[gdal-dev] Ogr: Is an OGR::Geometry::InteriorPoint() method ?
Benjamin
benjamin.lux at maxsea.fr
Thu Aug 16 08:03:59 PDT 2012
Hi,
Even Rouault wrote
>
> To my knowledge there is no such method. If you don't have particular
> constraints on the point except that it must be at the interior of the
> polygon,
> you could take a random vertex of the boundary, compute the distance D to
> the
> next point, and then compute various points located on a circle centered
> on that
> vertex and of radius D/2 until the IsPointOnSurface() returns TRUE. Not
> very
> efficient, there are likely better methods...
>
I don't want a totally random point.
Ari Jolma-2 wrote
>
> On 08/16/2012 03:09 PM, Even Rouault wrote:
>> Selon Benjamin <benjamin.lux@>:
>>
>> > For example, with JTS (Java Topologie Suite) we can obtain an interior
>> point (0.5 2.5).
>> Do you know the name of the JTS method ? It might also exist in GEOS, the
>> C++
>> port of JTS that GDAL relies on to do geometry related computations.
>
> http://geos.osgeo.org/doxygen/classgeos_1_1algorithm_1_1InteriorPointArea.html
> describes geos::algorithm::InteriorPointArea Class, which can be used to
> obtain an interior point of an area.
>
> Ari
>
I had a look to JTS sources and write again the InteriorPointArea in C#.
If someone want it I take it at the end of this email (and for others .NET
users who google it).
Thank to Even and Ari for theirs answers.
<code>
// A copie from JTS InteriorPointArea Class (Java) for C#
// See also : http://www.vividsolutions.com/jts/jtshome.htm
using OSGeo.OGR;
/// <summary>
/// Computes a point in the interior of an area geometry.
///
/// Algorithm :
/// 1/ Find the intersections between the geometry
/// and the horizontal bisector of the area's envelope
/// 2/Pick the midpoint of the largest intersection
/// (the intersections will be lines and points)
/// </summary>
/// <remarks>
/// Note: If a fixed precision model is used,
/// in some cases this method may return a point
/// which does not lie in the interior.
/// </remarks>
public class InteriorPointArea
{
private static double Avg(double a, double b)
{
return (a + b) / 2.0;
}
//private Geometry _factory;
private double[] _interiorPoint = null;
private double _maxWidth = 0.0;
public InteriorPointArea(Geometry g)
{
//_factory = g;
Add(g);
}
public double[] GetInteriorPoint()
{
return _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>
/// geom the geometry to add.
private void Add(Geometry geom)
{
if (geom.GetGeometryType() == wkbGeometryType.wkbPolygon)
{
AddPolygon(geom);
}
else if (geom.GetGeometryType() ==
wkbGeometryType.wkbGeometryCollection
|| geom.GetGeometryType() == wkbGeometryType.wkbMultiPolygon)
{
for (int i = 0; i < geom.GetGeometryCount(); i++)
{
Add(geom.GetGeometryRef(i));
}
}
}
/// <summary>
/// Finds a reasonable point at which to label a Geometry.
/// @param geometry the geometry to analyze
/// </summary>
/// the geometry to analyze.
/// <returns>the midpoint of the largest intersection between the
geometry and
/// a line halfway down its envelope</returns>
public void AddPolygon(Geometry geometry)
{
Geometry bisector = HorizontalBisector(geometry);
Geometry intersections = bisector.Intersection(geometry);
Geometry widestIntersection = WidestGeometry(intersections);
double width = widestIntersection.Length();
if (_interiorPoint == null || width > _maxWidth)
{
_interiorPoint = CentreOfEnveloppe(widestIntersection);
_maxWidth = width;
}
}
/// <summary>
/// return the widests geometry.
/// </summary>
/// The geometry.
/// <returns>
/// if geometry is a collection, the widest sub-geometry; otherwise,
/// the geometry itself
/// </returns>
protected Geometry WidestGeometry(Geometry geometry)
{
if (geometry.GetGeometryType() != wkbGeometryType.wkbMultiLineString
&&
geometry.GetGeometryType() !=
wkbGeometryType.wkbGeometryCollection)
{
return geometry;
}
if (geometry.IsEmpty())
{
return geometry;
}
Geometry widestGeometry = geometry.GetGeometryRef(0);
for (int i = 1; i < geometry.GetGeometryCount(); i++)
{ //Start at 1
if (geometry.GetGeometryRef(i).Length() >
widestGeometry.Length())
{
widestGeometry = geometry.GetGeometryRef(i);
}
}
return widestGeometry;
}
protected Geometry HorizontalBisector(Geometry geometry)
{
Envelope envelope = new Envelope();
geometry.GetEnvelope(envelope);
// Assert: for areas, minx <> maxx
double avgY = Avg(envelope.MinY, envelope.MaxY);
Geometry result = new Geometry(wkbGeometryType.wkbLineString);
result.AddPoint(envelope.MinX, avgY, 0);
result.AddPoint(envelope.MaxX, avgY, 0);
return result;
}
/// <summary>
/// Returns the centre point of the envelope.
/// </summary>
/// envelope the envelope to analyze.
/// <returns>Returns the centre point of the envelope.</returns>
public double[] Centre(Envelope envelope)
{
return new double[] { Avg(envelope.MinX, envelope.MaxX),
Avg(envelope.MinY, envelope.MaxY) };
}
public double[] CentreOfEnveloppe(Geometry geom)
{
Envelope env = new Envelope();
geom.GetEnvelope(env);
return Centre(env);
}
}
</code>
--
View this message in context: http://osgeo-org.1560.n6.nabble.com/gdal-dev-Ogr-Is-an-OGR-Geometry-InteriorPoint-method-tp4995621p4995701.html
Sent from the GDAL - Dev mailing list archive at Nabble.com.
More information about the gdal-dev
mailing list