using System;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Algorithm;
using GisSharpBlog.NetTopologySuite.Geometries;
using GisSharpBlog.NetTopologySuite.Index.Chain;
namespace GisSharpBlog.NetTopologySuite.Noding
{
///
/// Computes the intersections between two line segments in s
/// and adds them to each string.
/// The is passed to a .
/// The method is called whenever the
/// detects that two s might intersect.
/// This class is an example of the Strategy pattern.
///
public class IntersectionAdder : ISegmentIntersector
{
///
///
///
public int NumIntersections = 0;
///
///
///
public int NumInteriorIntersections = 0;
///
///
///
public int NumProperIntersections = 0;
///
///
///
public int NumTests = 0;
/**
* These variables keep track of what types of intersections were
* found during ALL edges that have been intersected.
*/
// the proper intersection point found
private readonly LineIntersector li = null;
///
/// Initializes a new instance of the class.
///
///
public IntersectionAdder(LineIntersector li)
{
HasInteriorIntersection = false;
HasProperInteriorIntersection = false;
HasProperIntersection = false;
HasIntersection = false;
ProperIntersectionPoint = null;
this.li = li;
}
///
///
///
public LineIntersector LineIntersector
{
get
{
return li;
}
}
///
/// Returns the proper intersection point, or null if none was found.
///
public ICoordinate ProperIntersectionPoint { get; private set; }
///
///
///
public bool HasIntersection { get; private set; }
///
/// A proper intersection is an intersection which is interior to at least two
/// line segments. Note that a proper intersection is not necessarily
/// in the interior of the entire , since another edge may have
/// an endpoint equal to the intersection, which according to SFS semantics
/// can result in the point being on the Boundary of the .
///
public bool HasProperIntersection { get; private set; }
///
/// A proper interior intersection is a proper intersection which is not
/// contained in the set of boundary nodes set for this .
///
public bool HasProperInteriorIntersection { get; private set; }
///
/// An interior intersection is an intersection which is
/// in the interior of some segment.
///
public bool HasInteriorIntersection { get; private set; }
///
///
///
///
///
///
public static bool IsAdjacentSegments(int i1, int i2)
{
return Math.Abs(i1 - i2) == 1;
}
///
/// This method is called by clients
/// of the class to process
/// intersections for two segments of the being intersected.
/// Note that some clients (such as s) may optimize away
/// this call for segment pairs which they have determined do not intersect
/// (e.g. by an disjoint envelope test).
///
///
///
///
///
public void ProcessIntersections(SegmentString e0, int segIndex0, SegmentString e1, int segIndex1)
{
if (e0 == e1 && segIndex0 == segIndex1)
{
return;
}
NumTests++;
ICoordinate p00 = e0.Coordinates[segIndex0];
ICoordinate p01 = e0.Coordinates[segIndex0 + 1];
ICoordinate p10 = e1.Coordinates[segIndex1];
ICoordinate p11 = e1.Coordinates[segIndex1 + 1];
li.ComputeIntersection(p00, p01, p10, p11);
if (li.HasIntersection)
{
NumIntersections++;
if (li.IsInteriorIntersection())
{
NumInteriorIntersections++;
HasInteriorIntersection = true;
}
// if the segments are adjacent they have at least one trivial intersection,
// the shared endpoint. Don't bother adding it if it is the
// only intersection.
if (!IsTrivialIntersection(e0, segIndex0, e1, segIndex1))
{
HasIntersection = true;
e0.AddIntersections(li, segIndex0, 0);
e1.AddIntersections(li, segIndex1, 1);
if (li.IsProper)
{
NumProperIntersections++;
HasProperIntersection = true;
HasProperInteriorIntersection = true;
}
}
}
}
///
/// A trivial intersection is an apparent self-intersection which in fact
/// is simply the point shared by adjacent line segments.
/// Note that closed edges require a special check for the point shared by the beginning and end segments.
///
///
///
///
///
///
private bool IsTrivialIntersection(SegmentString e0, int segIndex0, SegmentString e1, int segIndex1)
{
if (e0 == e1)
{
if (li.IntersectionNum == 1)
{
if (IsAdjacentSegments(segIndex0, segIndex1))
{
return true;
}
if (e0.IsClosed)
{
int maxSegIndex = e0.Count - 1;
if ((segIndex0 == 0 && segIndex1 == maxSegIndex) ||
(segIndex1 == 0 && segIndex0 == maxSegIndex))
{
return true;
}
}
}
}
return false;
}
}
}