diff --git a/Scripts/Core/CSG/Edge.cs b/Scripts/Core/CSG/Edge.cs
index a14c989d..2abe5680 100644
--- a/Scripts/Core/CSG/Edge.cs
+++ b/Scripts/Core/CSG/Edge.cs
@@ -1,17 +1,36 @@
#if UNITY_EDITOR || RUNTIME_CSG
+
using System;
using UnityEngine;
namespace Sabresaurus.SabreCSG
{
+ ///
+ /// An edge describes a connection between two vertices (see ).
+ ///
public class Edge
{
+ ///
+ /// Since floating-point math is imprecise we use a smaller value of 0.00001 (1e-5f) to check
+ /// for equality of two floats instead of absolute zero.
+ ///
public const float EPSILON = 1e-5f;
-
- Vertex vertex1;
- Vertex vertex2;
- public Vertex Vertex1
+ ///
+ /// The first of the .
+ ///
+ private Vertex vertex1;
+
+ ///
+ /// The last of the .
+ ///
+ private Vertex vertex2;
+
+ ///
+ /// The first of the .
+ ///
+ /// The first vertex of the edge.
+ public Vertex Vertex1
{
get
{
@@ -19,7 +38,11 @@ public Vertex Vertex1
}
}
- public Vertex Vertex2
+ ///
+ /// The last of the .
+ ///
+ /// The last vertex of the edge.
+ public Vertex Vertex2
{
get
{
@@ -27,149 +50,205 @@ public Vertex Vertex2
}
}
- public Vector3 GetCenterPoint()
- {
- return (vertex1.Position + vertex2.Position) * 0.5f;
- }
+ ///
+ /// Gets the center point between the vertex positions of the edge.
+ ///
+ /// The center point of the edge.
+ public Vector3 CenterPoint
+ {
+ get
+ {
+ return (vertex1.Position + vertex2.Position) * 0.5f;
+ }
+ }
- // TODO: Should track entire Vertex here? May be necessary for edge collapse where positions align but UV's don't. Currently unsure if that will be a problem.
- public Edge(Vertex vertex1, Vertex vertex2)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The first vertex of the edge.
+ /// The last vertex of the edge.
+ ///
+ /// Thrown when or is null.
+ ///
+ public Edge(Vertex vertex1, Vertex vertex2)
{
+ if (vertex1 == null) throw new ArgumentNullException("vertex1");
+ if (vertex2 == null) throw new ArgumentNullException("vertex2");
+
this.vertex1 = vertex1;
this.vertex2 = vertex2;
}
- public bool Matches(Edge otherEdge)
+ ///
+ /// Determines whether this edge matches the specified edge.
+ ///
+ /// Floating point inaccuracies are taken into account (see ).
+ ///
+ ///
+ /// The other edge to compare this edge to.
+ /// true if this edge matches the other edge; otherwise, false.
+ ///
+ /// Thrown when is null.
+ ///
+ public bool Matches(Edge other)
{
- if (vertex1.Position.EqualsWithEpsilon(otherEdge.vertex1.Position)
- && vertex2.Position.EqualsWithEpsilon(otherEdge.Vertex2.Position))
- {
+ if (other == null) throw new ArgumentNullException("other");
+
+ // check whether we approximately match the other edge:
+ if (vertex1.Position.EqualsWithEpsilon(other.vertex1.Position)
+ && vertex2.Position.EqualsWithEpsilon(other.Vertex2.Position))
return true;
- } // Check if the edge is the other way around
- else if (vertex1.Position.EqualsWithEpsilon(otherEdge.vertex2.Position)
- && vertex2.Position.EqualsWithEpsilon(otherEdge.Vertex1.Position))
- {
+
+ // even if the vertices are swapped it would yield the same edge:
+ if (vertex1.Position.EqualsWithEpsilon(other.vertex2.Position)
+ && vertex2.Position.EqualsWithEpsilon(other.Vertex1.Position))
return true;
- }
- else
- {
- return false;
- }
+
+ // the edge can be considered different.
+ return false;
}
- public bool Intersects(Edge otherEdge)
- {
- Vector3 vector1 = vertex2.Position - vertex1.Position;
- Vector3 vector2 = otherEdge.Vertex2.Position - otherEdge.Vertex1.Position;
+ ///
+ /// Determines whether the other edge is parallel to this edge. Two edges are considered
+ /// parallel if they face the same direction, do not intersect or touch each other at any point.
+ /// Floating point inaccuracies are taken into account (see ).
+ ///
+ /// The other edge to check for parallelity.
+ /// true if both edges are parallel; otherwise, false.
+ ///
+ /// Thrown when is null.
+ ///
+ public bool Parallel(Edge other)
+ {
+ if (other == null) throw new ArgumentNullException("other");
+
+ Vector3 direction1 = vertex2.Position - vertex1.Position;
+ Vector3 direction2 = other.Vertex2.Position - other.Vertex1.Position;
- float dot = (Vector3.Dot(vector1.normalized, vector2.normalized));
+ float dot = Vector3.Dot(direction1.normalized, direction2.normalized);
- bool parallel = Mathf.Abs(dot) > 1 - EPSILON;
+ return Mathf.Abs(dot) > 1 - EPSILON;
+ }
- // Edges not parallel, they can't be collinear
- if (!parallel)
+ ///
+ /// Does the other edge intersect with this edge?
+ ///
+ /// Floating point inaccuracies are taken into account (see ).
+ ///
+ ///
+ /// The other edge to check for intersection.
+ /// true if both edges intersect; otherwise, false.
+ ///
+ /// Thrown when is null.
+ ///
+ public bool Intersects(Edge other)
+ {
+ if (other == null) throw new ArgumentNullException("other");
+
+ // early out: if the edges aren't parallel to each other, they can't be collinear.
+ if (!Parallel(other))
return false;
- // TODO: Hacky way of finding out if they are on the same line because we know two points must be the same
- bool matchedPoint = false;
+ // delta from the matched point on this edge to the other point on this edge.
+ Vector3 delta1 = Vector3.zero;
+ // delta from the matched point on other edge to the other point on other edge.
+ Vector3 delta2 = Vector3.zero;
- Vector3 delta1 = Vector3.zero; // Delta from the matched point on this edge to the other point on this edge
- Vector3 delta2 = Vector3.zero; // Delta from the matched point on otherEdge to the other point on otherEdge
+ // TODO: hacky way of finding out if they are on the same line because we know
+ // two points must be the same once CSG geometry has been built. This should
+ // be able to detect any intersection of edges.
+ bool matchedPoint = false;
- if (vertex1.Position.EqualsWithEpsilon(otherEdge.Vertex1.Position))
- {
- matchedPoint = true;
+ if (vertex1.Position.EqualsWithEpsilon(other.Vertex1.Position))
+ {
+ matchedPoint = true;
delta1 = vertex2.Position - vertex1.Position;
- delta2 = otherEdge.Vertex2.Position - otherEdge.Vertex1.Position;
+ delta2 = other.Vertex2.Position - other.Vertex1.Position;
}
- else if (vertex2.Position.EqualsWithEpsilon(otherEdge.Vertex2.Position))
- {
- matchedPoint = true;
+ else if (vertex2.Position.EqualsWithEpsilon(other.Vertex2.Position))
+ {
+ matchedPoint = true;
delta1 = vertex1.Position - vertex2.Position;
- delta2 = otherEdge.Vertex1.Position - otherEdge.Vertex2.Position;
+ delta2 = other.Vertex1.Position - other.Vertex2.Position;
}
- else if (vertex1.Position.EqualsWithEpsilon(otherEdge.Vertex2.Position))
- {
- matchedPoint = true;
+ else if (vertex1.Position.EqualsWithEpsilon(other.Vertex2.Position))
+ {
+ matchedPoint = true;
delta1 = vertex2.Position - vertex1.Position;
- delta2 = otherEdge.Vertex1.Position - otherEdge.Vertex2.Position;
+ delta2 = other.Vertex1.Position - other.Vertex2.Position;
}
- else if (vertex2.Position.EqualsWithEpsilon(otherEdge.Vertex1.Position))
- {
- matchedPoint = true;
+ else if (vertex2.Position.EqualsWithEpsilon(other.Vertex1.Position))
+ {
+ matchedPoint = true;
delta1 = vertex1.Position - vertex2.Position;
- delta2 = otherEdge.Vertex2.Position - otherEdge.Vertex1.Position;
+ delta2 = other.Vertex2.Position - other.Vertex1.Position;
}
- // No points matched, assume not collinear
+ // if no points matched, assume it's not collinear:
if (!matchedPoint)
return false;
- // If the two edges actually share a portion then the vectors on the edges from the matched points will be in opposite directions
+ // if the two edges actually share a portion then the vectors on the edges
+ // from the matched points will be in opposite directions.
bool actuallySharePortion = (Vector3.Dot(delta1, delta2) > 0);
- return actuallySharePortion;
- }
+ return actuallySharePortion;
+ }
///
- /// Is this edge collinear with the other edge?
+ /// Is this edge collinear with the other edge? Two edges are considered collinear if they
+ /// lie on a single straight line through space (gaps between them make no difference).
///
- /// Other edge.
- public bool Collinear(Edge otherEdge)
+ /// Other edge that may be collinear.
+ /// true if both edges are collinear; otherwise, false.
+ ///
+ /// Thrown when is null.
+ ///
+ public bool Collinear(Edge other)
{
- Vector3 vector1 = vertex2.Position - vertex1.Position;
- Vector3 vector2 = otherEdge.Vertex2.Position - otherEdge.Vertex1.Position;
-
- float dot = (Vector3.Dot(vector1.normalized, vector2.normalized));
-
- //bool parallel = Mathf.Abs(dot) > 1-Plane.EPSILON;
- bool parallel = dot > 1 - EPSILON;
+ if (other == null) throw new ArgumentNullException("other");
- // TODO: Hacky way of finding out if they are on the same line because we know two points must be the same
- bool matchedPoint = false;
-
- if (vertex1.Position.EqualsWithEpsilon(otherEdge.Vertex1.Position))
- {
- matchedPoint = true;
- }
- else if (vertex2.Position.EqualsWithEpsilon(otherEdge.Vertex2.Position))
- {
- matchedPoint = true;
- }
- else if (vertex1.Position.EqualsWithEpsilon(otherEdge.Vertex2.Position))
- {
- matchedPoint = true;
- }
- else if (vertex2.Position.EqualsWithEpsilon(otherEdge.Vertex1.Position))
- {
- matchedPoint = true;
- }
- return parallel && matchedPoint;
+ return EdgeUtility.EdgeMatches(this, other);
}
- public override string ToString ()
- {
- return string.Format (string.Format("[Edge] V1: {0} V2: {1}", vertex1.Position, vertex2.Position));
- }
+ ///
+ /// Gets the normalized interpolant between the two vertices of this edge where it intersects
+ /// with the supplied .
+ ///
+ /// The plane that intersects with the edge.
+ /// The normalized interpolant between the edge points where the plane intersects.
+ public float GetPlaneIntersectionInterpolant(Plane plane)
+ {
+ return GetPlaneIntersectionInterpolant(plane, vertex1.Position, vertex2.Position);
+ }
- #region Static Methods
+ ///
+ /// Returns a that represents this .
+ ///
+ /// A that represents this .
+ public override string ToString()
+ {
+ return string.Format(string.Format("[Edge] V1: {0} V2: {1}", vertex1.Position, vertex2.Position));
+ }
///
- /// Returns the normalized interpolant between point1 and point2 where the edge they represent intersects with the
- /// supplied plane.
+ /// Gets the normalized interpolant between and where the edge they
+ /// represent intersects with the supplied .
///
- public static float IntersectsPlane(UnityEngine.Plane plane, Vector3 point1, Vector3 point2)
+ /// The plane that intersects with the edge.
+ /// The first point of the edge.
+ /// The last point of the edge.
+ /// The normalized interpolant between the edge points where the plane intersects.
+ public static float GetPlaneIntersectionInterpolant(Plane plane, Vector3 point1, Vector3 point2)
{
- // TODO: The plane might need flipping here
float interpolant = (-plane.normal.x * point1.x - plane.normal.y * point1.y - plane.normal.z * point1.z - plane.distance)
/ (-plane.normal.x * (point1.x - point2.x) - plane.normal.y * (point1.y - point2.y) - plane.normal.z * (point1.z - point2.z));
-// DISABLED: Should find a way of making this work with the new Assert support in Unity
-// DebugHelper.Assert((interpolant >= 0 && interpolant <= 1), "Edge Interpolant outside (0,1) range");
-
return interpolant;
}
- #endregion
}
}
+
#endif
\ No newline at end of file
diff --git a/Scripts/Core/CSG/Polygon.cs b/Scripts/Core/CSG/Polygon.cs
index 887d851d..9d7a3da5 100644
--- a/Scripts/Core/CSG/Polygon.cs
+++ b/Scripts/Core/CSG/Polygon.cs
@@ -498,7 +498,7 @@ public static bool SplitPolygon(Polygon polygon, out Polygon frontPolygon, out P
}
else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.InFront)
{
- float interpolant = Edge.IntersectsPlane(clipPlane, previousVertex.Position, currentVertex.Position);
+ float interpolant = Edge.GetPlaneIntersectionInterpolant(clipPlane, previousVertex.Position, currentVertex.Position);
Vertex intersection = Vertex.Lerp(previousVertex, currentVertex, interpolant);
// Front add intersection, add current
@@ -513,7 +513,7 @@ public static bool SplitPolygon(Polygon polygon, out Polygon frontPolygon, out P
else if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.Behind)
{
// Reverse order here so that clipping remains consistent for either CW or CCW testing
- float interpolant = Edge.IntersectsPlane(clipPlane, currentVertex.Position, previousVertex.Position);
+ float interpolant = Edge.GetPlaneIntersectionInterpolant(clipPlane, currentVertex.Position, previousVertex.Position);
Vertex intersection = Vertex.Lerp(currentVertex, previousVertex, interpolant);
// Front add intersection
@@ -618,14 +618,14 @@ public static bool PlanePolygonIntersection(Polygon polygon, out Vector3 positio
}
else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.InFront)
{
- float interpolant = Edge.IntersectsPlane(testPlane, previousVertex.Position, currentVertex.Position);
+ float interpolant = Edge.GetPlaneIntersectionInterpolant(testPlane, previousVertex.Position, currentVertex.Position);
position2 = Vector3.Lerp(previousVertex.Position, currentVertex.Position, interpolant);
position2Set = true;
}
else if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.Behind)
{
// Reverse order here so that clipping remains consistent for either CW or CCW testing
- float interpolant = Edge.IntersectsPlane(testPlane, currentVertex.Position, previousVertex.Position);
+ float interpolant = Edge.GetPlaneIntersectionInterpolant(testPlane, currentVertex.Position, previousVertex.Position);
position1 = Vector3.Lerp(currentVertex.Position, previousVertex.Position, interpolant);
position1Set = true;
}
diff --git a/Scripts/Tools/Utilities/EdgeUtility.cs b/Scripts/Tools/Utilities/EdgeUtility.cs
index cbc6070a..f069a63e 100644
--- a/Scripts/Tools/Utilities/EdgeUtility.cs
+++ b/Scripts/Tools/Utilities/EdgeUtility.cs
@@ -98,8 +98,8 @@ public static void SplitPolygonsByEdges(Polygon[] polygons, List sourceEdg
Edge edge2 = edgesOnPolygon[1];
// First split the shared polygon
- Vector3 edge1Center = edge1.GetCenterPoint();
- Vector3 edge2Center = edge2.GetCenterPoint();
+ Vector3 edge1Center = edge1.CenterPoint;
+ Vector3 edge2Center = edge2.CenterPoint;
Vector3 thirdPoint = edge1Center + polygon.Plane.normal;