Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions Wkx.Tests/BoundingBoxTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
namespace Wkx.Tests
{
using System;
using Xunit;

public static class BoundingBoxTests
{
public class ConstructorTests
{
[Fact]
public void InconsistentZValue_ThrowsException()
{
Assert.Throws<ArgumentNullException>(() => new BoundingBox(1, 1, null, 2, 2, 2));
Assert.Throws<ArgumentNullException>(() => new BoundingBox(1, 1, 1, 2, 2, null));
}
}

public class EqualsTests
{
[Fact]
public void BoundingBoxes_WithoutZ_Match()
{
var a = new BoundingBox(1, 1, 2, 2);
var b = new BoundingBox(1, 1, 2, 2);

Assert.True(a.Equals(b));
}

[Fact]
public void BoundingBoxes_WithZ_Match()
{
var a = new BoundingBox(1, 1, 1, 2, 2, 2);
var b = new BoundingBox(1, 1, 1, 2, 2, 2);

Assert.True(a.Equals(b));
}

[Fact]
public void BoundingBoxes_ThatAreDifferent_DoNotMatch()
{
var a = new BoundingBox(1, 1, 2, 2);
var b = new BoundingBox(1, 1, 2, 99);

Assert.False(a.Equals(b));
}

[Fact]
public void BoundingBoxes_WithMismatchZ_DoNotMatch()
{
var a = new BoundingBox(1, 1, 1, 2, 2, 2);
var b = new BoundingBox(1, 1, 2, 2);

Assert.False(a.Equals(b));
}
}

public class GetHashCodeTests
{
[Fact]
public void BoundingBoxes_WithoutZ_Match()
{
var a = new BoundingBox(1, 1, 2, 2);
var b = new BoundingBox(1, 1, 2, 2);

Assert.Equal(a.GetHashCode(), b.GetHashCode());
}

[Fact]
public void BoundingBoxes_WithZ_Match()
{
var a = new BoundingBox(1, 1, 1, 2, 2, 2);
var b = new BoundingBox(1, 1, 1, 2, 2, 2);

Assert.Equal(a.GetHashCode(), b.GetHashCode());
}

[Fact]
public void BoundingBoxes_ThatAreDifferent_DoNotMatch()
{
var a = new BoundingBox(1, 1, 2, 2);
var b = new BoundingBox(1, 1, 2, 99);

Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
}

[Fact]
public void BoundingBoxes_WithMismatchZ_DoNotMatch()
{
var a = new BoundingBox(1, 1, 1, 2, 2, 2);
var b = new BoundingBox(1, 1, 2, 2);

Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
}
}
}
}
53 changes: 53 additions & 0 deletions Wkx.Tests/MathUtilTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
namespace Wkx.Tests
{
using Xunit;

public static class MathUtilTests
{
public class MinTests
{
[Fact]
public void BothValues_AreNull_ReturnNull()
{
Assert.Null(MathUtil.Min(null, null));
}

[Fact]
public void OneValue_IsNull_ReturnNonNullValue()
{
Assert.Equal(0, MathUtil.Min(0, null));
Assert.Equal(0, MathUtil.Min(null, 0));
}

[Fact]
public void NoNullValues_ReturnMinValue()
{
Assert.Equal(1, MathUtil.Min(1, 2));
Assert.Equal(1, MathUtil.Min(2, 1));
}
}

public class MaxTests
{
[Fact]
public void BothValues_AreNull_ReturnNull()
{
Assert.Null(MathUtil.Max(null, null));
}

[Fact]
public void OneValue_IsNull_ReturnNonNullValue()
{
Assert.Equal(0, MathUtil.Max(0, null));
Assert.Equal(0, MathUtil.Max(null, 0));
}

[Fact]
public void NoNullValues_ReturnMaxValue()
{
Assert.Equal(2, MathUtil.Max(1, 2));
Assert.Equal(2, MathUtil.Max(2, 1));
}
}
}
}
27 changes: 27 additions & 0 deletions Wkx.Tests/PolyhedralSurfaceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Wkx.Tests
{
using Xunit;

public static class PolyhedralSurfaceTests
{
public class GetBoundingBoxTests
{
[Fact]
public void BoundingBox_Calculated()
{
var target = new PolyhedralSurface(
new[] {
new Polygon(new[] { new Point(0,0,0), new Point(1,1,0), new Point(0,2,0) }),
new Polygon(new[] { new Point(0,0,0), new Point(1,1,0), new Point(1,1,1) }),
new Polygon(new[] { new Point(1,1,0), new Point(1,1,1), new Point(0,2,0) }),
new Polygon(new[] { new Point(0,2,0), new Point(1,1,1), new Point(0,0,0) })
});

var expected = new BoundingBox(0, 0, 0, 1, 2, 1);
var actual = target.GetBoundingBox();

Assert.Equal(expected, actual);
}
}
}
}
28 changes: 24 additions & 4 deletions Wkx/BoundingBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,37 @@ namespace Wkx
{
public class BoundingBox : IEquatable<BoundingBox>
{
public Dimension Dimension => ZMin.HasValue ? Dimension.Xyz : Dimension.Xy;

public double XMin { get; private set; }
public double YMin { get; private set; }
public double? ZMin { get; private set; }
public double XMax { get; private set; }
public double YMax { get; private set; }
public double? ZMax { get; private set; }

public BoundingBox()
{
}

public BoundingBox(double xMin, double yMin, double xMax, double yMax)
public BoundingBox(double xMin, double yMin, double? zMin, double xMax, double yMax, double? zMax)
{
if (zMin.HasValue != zMax.HasValue)
{
throw new ArgumentNullException(zMin.HasValue ? nameof(zMax) : nameof(zMin));
}

XMin = xMin;
YMin = yMin;
ZMin = zMin;
XMax = xMax;
YMax = yMax;
ZMax = zMax;
}

public BoundingBox(double xMin, double yMin, double xMax, double yMax)
:this(xMin, yMin, null, xMax, yMax, null)
{
}

public override bool Equals(object obj)
Expand All @@ -33,13 +49,17 @@ public override bool Equals(object obj)

public bool Equals(BoundingBox other)
{
return XMin == other.XMin && YMin == other.YMin &&
XMax == other.XMax && YMax == other.YMax;
return XMin == other.XMin
&& YMin == other.YMin
&& ZMin == other.ZMin
&& XMax == other.XMax
&& YMax == other.YMax
&& ZMax == other.ZMax;
}

public override int GetHashCode()
{
return new { XMin, YMin, XMax, YMax }.GetHashCode();
return new { XMin, YMin, ZMin, XMax, YMax, ZMax }.GetHashCode();
}
}
}
33 changes: 26 additions & 7 deletions Wkx/Extensions/GeometryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,36 +62,55 @@ internal static BoundingBox GetBoundingBox(this IEnumerable<Point> points)
{
double xMin = double.MaxValue;
double yMin = double.MaxValue;
double? zMin = null;
double xMax = -double.MaxValue;
double yMax = -double.MaxValue;
double? zMax = null;

foreach (Point point in points)
{
xMin = Math.Min(xMin, point.X.Value);
yMin = Math.Min(yMin, point.Y.Value);
zMin = MathUtil.Min(zMin, point.Z);
xMax = Math.Max(xMax, point.X.Value);
yMax = Math.Max(yMax, point.Y.Value);
zMax = MathUtil.Max(zMax, point.Z);
}

return new BoundingBox(xMin, yMin, xMax, yMax);
return new BoundingBox(xMin, yMin, zMin, xMax, yMax, zMax);
}

internal static BoundingBox GetBoundingBox(this IEnumerable<BoundingBox> boundingBoxes)
{
double xMin = double.MaxValue;
double yMin = double.MaxValue;
double? zMin = null;
double xMax = -double.MaxValue;
double yMax = -double.MaxValue;
double? zMax = null;

foreach (BoundingBox boundingBox in boundingBoxes)
var enumerator = boundingBoxes.GetEnumerator();
if (enumerator.MoveNext())
{
xMin = Math.Min(xMin, boundingBox.XMin);
yMin = Math.Min(yMin, boundingBox.YMin);
xMax = Math.Max(xMax, boundingBox.XMax);
yMax = Math.Max(yMax, boundingBox.YMax);
var dimension = enumerator.Current.Dimension;
do
{
var boundingBox = enumerator.Current;
if (dimension != boundingBox.Dimension)
{
throw new InvalidOperationException("Bounding box Z dimension inconsistent");
}

xMin = Math.Min(xMin, boundingBox.XMin);
yMin = Math.Min(yMin, boundingBox.YMin);
zMin = MathUtil.Min(zMin, boundingBox.ZMin);
xMax = Math.Max(xMax, boundingBox.XMax);
yMax = Math.Max(yMax, boundingBox.YMax);
zMax = MathUtil.Max(zMax, boundingBox.ZMax);
} while (enumerator.MoveNext());
}

return new BoundingBox(xMin, yMin, xMax, yMax);
return new BoundingBox(xMin, yMin, zMin, xMax, yMax, zMax);
}

internal static double AngleBetween(this Point point, Point otherPoint)
Expand Down
20 changes: 20 additions & 0 deletions Wkx/MathUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,25 @@ internal static double CalculateSweepAngle(Point startPoint, Point intermediateP
Point vc = new Point(endPoint.X.Value - cx, endPoint.Y.Value - cy);
return va.AngleBetween(vb) + vb.AngleBetween(vc);
}

internal static double? Min(double? a, double? b)
{
if (a == null || b == null)
{
return a ?? b;
}

return Math.Min(a.Value, b.Value);
}

internal static double? Max(double? a, double? b)
{
if (a == null || b == null)
{
return a ?? b;
}

return Math.Max(a.Value, b.Value);
}
}
}
2 changes: 1 addition & 1 deletion Wkx/Point.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public override Point GetCenter()

public override BoundingBox GetBoundingBox()
{
return new BoundingBox(X.Value, Y.Value, X.Value, Y.Value);
return new BoundingBox(X.Value, Y.Value, Z, X.Value, Y.Value, Z);
}

public override Geometry CurveToLine(double tolerance)
Expand Down