diff --git a/interfaces/IBounded2.cs b/interfaces/IBounded2.cs
new file mode 100644
index 0000000..5143206
--- /dev/null
+++ b/interfaces/IBounded2.cs
@@ -0,0 +1,13 @@
+namespace GeometriCS
+{
+ ///
+ /// Interface for finite (bounded) entities in two-dimensional space.
+ ///
+ public interface IBounded2d
+ {
+ ///
+ /// Extents of the bounded entity.
+ ///
+ public Extents2d Extents { get; }
+ }
+}
diff --git a/intersections/IntersectionLine2ToLine2.cs b/intersections/IntersectionLine2ToLine2.cs
index 117bd65..768e6a2 100644
--- a/intersections/IntersectionLine2ToLine2.cs
+++ b/intersections/IntersectionLine2ToLine2.cs
@@ -18,6 +18,10 @@
/// The two lines are parallel.
///
PARALLEL,
+ ///
+ /// The two lines are colinear and intersect on their whole length.
+ ///
+ COLINEAR,
}
///
@@ -47,11 +51,37 @@
/// Second of the intersecting lines.
public IntersectionLine2ToLine2d(Line2d line1, Line2d line2)
{
+ // Set the intersector references
Line1 = line1;
Line2 = line2;
- // Process the intersection
- throw new NotImplementedException();
+ // Check if lines are parallel
+ // TODO: Check what happens if coeff_B == 0
+ if(Utils.DoubleEquals(line1.Coeff_A / line1.Coeff_B, line2.Coeff_A / line2.Coeff_B))
+ {
+ // Null result
+ Result = null;
+
+ // Check if lines are coincidental
+ if (Utils.DoubleEquals(line1.Coeff_A / line2.Coeff_A, line1.Coeff_B / line2.Coeff_B) &&
+ Utils.DoubleEquals(line1.Coeff_A / line2.Coeff_A, line1.Coeff_C / line2.Coeff_C))
+ {
+ Status = Statuses.COLINEAR;
+ }
+ else
+ {
+ Status = Statuses.PARALLEL;
+ }
+
+ return;
+ }
+
+ // Perform the intersection calculation
+ double divisor = line1.Coeff_A * line2.Coeff_B - line2.Coeff_A * line1.Coeff_B;
+ double x0 = (line1.Coeff_B * line2.Coeff_C - line2.Coeff_B * line1.Coeff_C) / divisor;
+ double y0 = (line1.Coeff_C * line2.Coeff_A - line2.Coeff_C * line1.Coeff_A) / divisor;
+ Result = new Vector2d(x0, y0);
+ Status = Statuses.SUCCESS;
}
}
}
diff --git a/intersections/IntersectionLine2ToLineSegment2.cs b/intersections/IntersectionLine2ToLineSegment2.cs
index e517e7c..74e7d4a 100644
--- a/intersections/IntersectionLine2ToLineSegment2.cs
+++ b/intersections/IntersectionLine2ToLineSegment2.cs
@@ -1,7 +1,7 @@
namespace GeometriCS
{
///
- /// Intersection between a line and a line segment
+ /// Intersection between a line and a line segment. Double precision.
///
public class IntersectionLine2ToLineSegment2d
{
@@ -19,6 +19,10 @@
///
PARALLEL,
///
+ /// The line segment is colinear with the line.
+ ///
+ COLINEAR,
+ ///
/// The intersection would happen if the intersectors were unbounded, but not inside the bounds.
///
OUTOFBOUNDS,
@@ -54,8 +58,48 @@
Line = line;
LineSegment = lineSegment;
- // Process the intersection
- throw new NotImplementedException();
+ // Construct line coefficients for the linesegment
+ (double segment_A, double segment_B, double segment_C) =
+ Utils.Line2CoefficientsFromTwoPoints(lineSegment.StartPoint, lineSegment.EndPoint);
+
+ // Check if lines are parallel
+ // TODO: Check what happens if coeff_B == 0
+ // TODO: Find a non-retarded way to put this into a function so
+ // that it can be reused by all the 2d linear intersections.
+ if (Utils.DoubleEquals(line.Coeff_A / line.Coeff_B, segment_A / segment_B))
+ {
+ // Null result
+ Result = null;
+
+ // Check if lines are coincidental
+ if (Utils.DoubleEquals(line.Coeff_A / segment_A, line.Coeff_B / segment_B) &&
+ Utils.DoubleEquals(line.Coeff_A / segment_A, line.Coeff_C / segment_C))
+ {
+ Status = Statuses.COLINEAR;
+ }
+ else
+ {
+ Status = Statuses.PARALLEL;
+ }
+
+ return;
+ }
+
+ // Perform the intersection calculation
+ double divisor = line.Coeff_A * segment_B - segment_A * line.Coeff_B;
+ double x0 = (line.Coeff_B * segment_C - segment_B * line.Coeff_C) / divisor;
+ double y0 = (line.Coeff_C * segment_A - segment_C * line.Coeff_A) / divisor;
+ Result = new Vector2d(x0, y0);
+
+ // Check if result is inside of the segment.
+ if (lineSegment.Extents.Contains((Vector2d)Result))
+ {
+ Status = Statuses.SUCCESS;
+ }
+ else
+ {
+ Status = Statuses.OUTOFBOUNDS;
+ }
}
}
}
diff --git a/intersections/IntersectionPlaneToPlane.cs b/intersections/IntersectionPlaneToPlane.cs
index 059452e..34d2e4e 100644
--- a/intersections/IntersectionPlaneToPlane.cs
+++ b/intersections/IntersectionPlaneToPlane.cs
@@ -3,7 +3,7 @@
///
/// Intersection between two planes, double precision.
///
- public struct IntersectionPlaneToPlaned
+ public class IntersectionPlaneToPlaned
{
///
/// Possible statuses the intersection can be.
diff --git a/structs/Extents2.cs b/structs/Extents2.cs
new file mode 100644
index 0000000..ff44231
--- /dev/null
+++ b/structs/Extents2.cs
@@ -0,0 +1,90 @@
+namespace GeometriCS
+{
+ ///
+ /// Geometric extents of a finitely large entity. Double precision.
+ ///
+ public struct Extents2d
+ {
+ ///
+ /// The point with the lowest Y and X.
+ ///
+ public Vector2d MinPoint { get; }
+
+ ///
+ /// The point with the highest Y and X.
+ ///
+ public Vector2d MaxPoint { get; }
+
+ ///
+ /// Take two points and create Extents from their bounding box.
+ ///
+ /// First point.
+ /// Second point.
+ /// Extents of the bounding box of the two points.
+ public static Extents2d FromTwoPoints(Vector2d pt1, Vector2d pt2)
+ {
+ // Find the smallest and largest x and y values.
+ double minx = pt1.X < pt2.X ? pt1.X : pt2.X;
+ double miny = pt1.Y < pt2.Y ? pt1.Y : pt2.Y;
+ double maxx = pt1.X > pt2.X ? pt1.X : pt2.X;
+ double maxy = pt1.Y > pt2.Y ? pt1.Y : pt2.Y;
+
+ // Create new points from them and create the extents.
+ return new Extents2d(new Vector2d(minx, miny),
+ new Vector2d(maxx, maxy));
+ }
+
+ ///
+ /// Is there an overlap between the bounding boxes of these two extents?
+ ///
+ ///
+ /// true if there is an overlap, otherwise false.
+ public bool Overlaps(Extents2d other)
+ {
+ // If at least one of my points are in others X band, or at least one of others points are in my X band
+ // check whether at least one of my points are in others Y band, or at least one of the others points
+ // are in my Y band. If both conditions are met, there is an overlap.
+ return (MinPoint.X.IsInRange(other.MinPoint.X, other.MaxPoint.X) ||
+ MaxPoint.X.IsInRange(other.MinPoint.X, other.MaxPoint.X) ||
+ other.MinPoint.X.IsInRange(MinPoint.X, MaxPoint.X) ||
+ other.MaxPoint.X.IsInRange(MinPoint.X, MaxPoint.X) ) && (
+ MinPoint.Y.IsInRange(other.MinPoint.Y, other.MaxPoint.Y) ||
+ MaxPoint.Y.IsInRange(other.MinPoint.Y, other.MaxPoint.Y) ||
+ other.MinPoint.Y.IsInRange(MinPoint.Y, MaxPoint.Y) ||
+ other.MaxPoint.Y.IsInRange(MinPoint.Y, MaxPoint.Y));
+ }
+
+ ///
+ /// Does the bounding box contain the point.
+ ///
+ /// Point to test.
+ /// true if the point is inside of the bounding box, otherwise false.
+ public bool Contains(Vector2d point)
+ {
+ return point.X.IsInRange(MinPoint.X, MaxPoint.X) && point.Y.IsInRange(MinPoint.Y, MaxPoint.Y);
+ }
+
+ ///
+ /// Constructor for the Extents2d.
+ ///
+ /// The point with the lowest X and Y.
+ /// The point with the greatest X and Y.
+ ///
+ /// The maxpoint is not greater in both dimensions than the minpoint.
+ ///
+ public Extents2d(Vector2d minPoint, Vector2d maxPoint)
+ {
+ /// Check validity
+ if((minPoint.X > maxPoint.X && !Utils.DoubleEquals(minPoint.X, maxPoint.X)) ||
+ (minPoint.Y > maxPoint.Y && !Utils.DoubleEquals(minPoint.Y, maxPoint.Y)))
+ {
+ throw new ArgumentException($"The minpoint {minPoint} has to " +
+ $"have lesser both X and Y than the maxpoint {maxPoint}.");
+ }
+
+ // Assign the properties.
+ MinPoint = minPoint;
+ MaxPoint = maxPoint;
+ }
+ }
+}
diff --git a/structs/Line2.cs b/structs/Line2.cs
index 62577ae..4f2d175 100644
--- a/structs/Line2.cs
+++ b/structs/Line2.cs
@@ -1,6 +1,4 @@
-using System.Runtime.CompilerServices;
-
-namespace GeometriCS
+namespace GeometriCS
{
///
/// A line through a two-dimensional vector space.
@@ -53,7 +51,8 @@ namespace GeometriCS
/// Line passing through the two points.
public static Line2d FromTwoPoints(Vector2d firstPoint, Vector2d secondPoint)
{
- throw new NotImplementedException();
+ (double a, double b, double c) = Utils.Line2CoefficientsFromTwoPoints(firstPoint, secondPoint);
+ return new Line2d(a, b, c);
}
///
diff --git a/structs/LineSegment2.cs b/structs/LineSegment2.cs
index d3d1e0f..f39b4bd 100644
--- a/structs/LineSegment2.cs
+++ b/structs/LineSegment2.cs
@@ -3,7 +3,7 @@
///
/// A segment of a two-dimensional line with double precision.
///
- public class LineSegment2d
+ public class LineSegment2d : IBounded2d
{
///
/// Start point of the line.
@@ -15,6 +15,10 @@
///
public Vector2d EndPoint { get; set;}
+ // Consider pre-calculating this in point setters later on,
+ // once we have group intersection support and can gauge performance effects.
+ public Extents2d Extents => Extents2d.FromTwoPoints(StartPoint, EndPoint);
+
///
/// A constructor for a 2d line segment.
///
@@ -22,8 +26,8 @@
/// Point at which the line ends.
public LineSegment2d(Vector2d startPoint, Vector2d endPoint)
{
- StartPoint = (Vector2d) startPoint.Clone();
- EndPoint = (Vector2d) endPoint.Clone();
+ StartPoint = startPoint;
+ EndPoint = endPoint;
}
///
diff --git a/structs/LineSegment3.cs b/structs/LineSegment3.cs
index 6aae0f6..3ccef48 100644
--- a/structs/LineSegment3.cs
+++ b/structs/LineSegment3.cs
@@ -22,8 +22,8 @@
/// End point of the line.
public LineSegment3d(Vector3d startPoint, Vector3d endPoint)
{
- StartPoint = (Vector3d) startPoint.Clone();
- EndPoint = (Vector3d) endPoint.Clone();
+ StartPoint = startPoint;
+ EndPoint = endPoint;
}
///
diff --git a/structs/Vector2.cs b/structs/Vector2.cs
index 824b3d0..4ceaea1 100644
--- a/structs/Vector2.cs
+++ b/structs/Vector2.cs
@@ -3,7 +3,7 @@
///
/// Two-dimensional vector with double precision.
///
- public class Vector2d : ICloneable
+ public struct Vector2d : ICloneable
{
///
/// Vector with 0 length.
@@ -30,6 +30,34 @@
///
public double Y { get; set; }
+ ///
+ /// Indexer for the vector.
+ ///
+ /// index
+ /// [0] is X; [1] is Y
+ /// Index was out of range {0, 1}.
+ public double this [int i]
+ {
+ get
+ {
+ switch (i)
+ {
+ case 0: return X;
+ case 1: return Y;
+ default: throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (i)
+ {
+ case 0: X = value; break;
+ case 1: Y = value; break;
+ default: throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
///
/// Length of the vector.
///
diff --git a/structs/Vector3.cs b/structs/Vector3.cs
index 8bb9050..7964d79 100644
--- a/structs/Vector3.cs
+++ b/structs/Vector3.cs
@@ -3,7 +3,7 @@
///
/// Three-dimensional vector with double precision.
///
- public class Vector3d : ICloneable
+ public struct Vector3d : ICloneable
{
///
/// Vector with 0 length.
@@ -40,6 +40,36 @@
///
public double Z { get; set; }
+ ///
+ /// Indexer for the vector.
+ ///
+ /// index
+ /// [0] is X; [1] is Y; [2] is Z
+ /// Index was out of range {0, 1, 3}.
+ public double this[int i]
+ {
+ get
+ {
+ switch (i)
+ {
+ case 0: return X;
+ case 1: return Y;
+ case 2: return Z;
+ default: throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (i)
+ {
+ case 0: X = value; break;
+ case 1: Y = value; break;
+ case 2: Z = value; break;
+ default: throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
///
/// Length of the vector.
///
diff --git a/utils/Utils.cs b/utils/Utils.cs
index ac149b6..4fd37d0 100644
--- a/utils/Utils.cs
+++ b/utils/Utils.cs
@@ -3,13 +3,25 @@
///
/// Common utilities throughout the library.
///
- internal static class Utils
+ public static class Utils
{
///
/// Default precision for double equality comparison.
///
private const double DOUBLEPRECISION = 1E-5;
+ ///
+ /// Is this number in the range (inclusive).
+ ///
+ /// Number to compare
+ /// Lower end of the range.
+ /// Higher end of the range.
+ /// trueif number is in the range , false if it is outside.
+ public static bool IsInRange(this double num, double lower, double higher)
+ {
+ return num >= lower && num <= higher;
+ }
+
///
/// Tests whether the difference between two doubles is within a given limit.
///
@@ -17,6 +29,22 @@
/// Second value to test.
/// Maximum allowed difference.
/// Do the values almost equal each other.
- public static bool DoubleEquals(double a, double b, double prec = DOUBLEPRECISION) => Math.Abs(a - b) <= prec;
+ public static bool DoubleEquals(double a, double b, double prec = DOUBLEPRECISION) => Math.Abs(a - b) <= prec;
+
+ ///
+ /// Returns the coefficients of a line defined by equation Ax + By + C = 0,
+ /// given two points that lie on the line.
+ ///
+ /// First point on the line.
+ /// Second point on the line.
+ /// Touple (Coeff_A, Coeff_B, Coeff_C).
+ public static (double A, double B, double C) Line2CoefficientsFromTwoPoints(Vector2d pt1, Vector2d pt2)
+ {
+ double coeff_A = pt2.Y - pt1.Y;
+ double coeff_B = pt1.X - pt2.X;
+ double coeff_C = (pt1.Y * (pt2.X - pt1.X)) -
+ (pt1.X * (pt2.Y - pt1.Y));
+ return (coeff_A, coeff_B, coeff_C);
+ }
}
}