diff --git a/src/Speckle.Objects/Exceptions/TransformationException.cs b/src/Speckle.Objects/Exceptions/TransformationException.cs
new file mode 100644
index 00000000..7076b295
--- /dev/null
+++ b/src/Speckle.Objects/Exceptions/TransformationException.cs
@@ -0,0 +1,17 @@
+using Speckle.Sdk;
+
+namespace Speckle.Objects.Exceptions;
+
+///
+/// object failed to transform
+///
+public sealed class TransformationException : SpeckleException
+{
+ public TransformationException() { }
+
+ public TransformationException(string? message)
+ : base(message) { }
+
+ public TransformationException(string? message, Exception? innerException)
+ : base(message, innerException) { }
+}
diff --git a/src/Speckle.Objects/Geometry/Arc.cs b/src/Speckle.Objects/Geometry/Arc.cs
index 6cb3fd20..85a8b4c3 100644
--- a/src/Speckle.Objects/Geometry/Arc.cs
+++ b/src/Speckle.Objects/Geometry/Arc.cs
@@ -88,13 +88,13 @@ public class Arc : Base, IHasBoundingBox, ICurve, ITransformable
public Box? bbox { get; set; }
///
- public bool TransformTo(Transform transform, out Arc transformed)
+ public Arc TransformTo(Transform transform)
{
- startPoint.TransformTo(transform, out Point transformedStartPoint);
- midPoint.TransformTo(transform, out Point transformedMidpoint);
- endPoint.TransformTo(transform, out Point transformedEndPoint);
- plane.TransformTo(transform, out Plane pln);
- Arc arc = new()
+ var transformedStartPoint = startPoint.TransformTo(transform);
+ var transformedMidpoint = midPoint.TransformTo(transform);
+ var transformedEndPoint = endPoint.TransformTo(transform);
+ var pln = plane.TransformTo(transform);
+ Arc transformed = new()
{
startPoint = transformedStartPoint,
endPoint = transformedEndPoint,
@@ -103,16 +103,7 @@ public bool TransformTo(Transform transform, out Arc transformed)
domain = domain,
units = units,
};
- transformed = arc;
- return true;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Arc arc);
- transformed = arc;
- return res;
+ return transformed;
}
///
diff --git a/src/Speckle.Objects/Geometry/Brep.cs b/src/Speckle.Objects/Geometry/Brep.cs
index df201c32..b5a5552f 100644
--- a/src/Speckle.Objects/Geometry/Brep.cs
+++ b/src/Speckle.Objects/Geometry/Brep.cs
@@ -1,5 +1,6 @@
using System.Runtime.Serialization;
using Speckle.Newtonsoft.Json;
+using Speckle.Objects.Exceptions;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
@@ -434,37 +435,38 @@ public List FacesValue
public double volume { get; set; }
///
- public bool TransformTo(Transform transform, out Brep transformed)
+ public Brep TransformTo(Transform transform)
{
// transform display values
var displayValues = new List(displayValue.Count);
foreach (Mesh v in displayValue)
{
- v.TransformTo(transform, out Mesh mesh);
- displayValues.Add(mesh);
+ var transformedMesh = v.TransformTo(transform);
+ displayValues.Add(transformedMesh);
}
// transform surfaces
var surfaces = new List(Surfaces.Count);
foreach (var srf in Surfaces)
{
- srf.TransformTo(transform, out Surface surface);
- surfaces.Add(surface);
+ var transformedSurface = srf.TransformTo(transform);
+ surfaces.Add(transformedSurface);
}
// transform curve3d
- var success3D = true;
var transformedCurve3D = new List();
foreach (var curve in Curve3D)
{
- if (curve is ITransformable c)
+ if (curve is ITransformable c)
{
- c.TransformTo(transform, out ITransformable tc);
- transformedCurve3D.Add((ICurve)tc);
+ var tc = c.TransformTo(transform);
+ transformedCurve3D.Add(tc);
}
else
{
- success3D = false;
+ throw new TransformationException(
+ $"BREP could not be transformed because it contains {curve.GetType()} curves that are not transformable"
+ );
}
}
@@ -472,11 +474,11 @@ public bool TransformTo(Transform transform, out Brep transformed)
var transformedVertices = new List(Vertices.Count);
foreach (var vertex in Vertices)
{
- vertex.TransformTo(transform, out Point transformedVertex);
+ Point transformedVertex = vertex.TransformTo(transform);
transformedVertices.Add(transformedVertex);
}
- transformed = new Brep
+ var transformed = new Brep
{
units = units,
displayValue = displayValues,
@@ -556,15 +558,7 @@ public bool TransformTo(Transform transform, out Brep transformed)
);
}
- return success3D;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Brep brep);
- transformed = brep;
- return res;
+ return transformed;
}
[OnDeserialized]
diff --git a/src/Speckle.Objects/Geometry/ControlPoint.cs b/src/Speckle.Objects/Geometry/ControlPoint.cs
index fd942e35..0deb3852 100644
--- a/src/Speckle.Objects/Geometry/ControlPoint.cs
+++ b/src/Speckle.Objects/Geometry/ControlPoint.cs
@@ -40,18 +40,15 @@ public ControlPoint(double x, double y, double z, double w, string units, string
}
}
- public bool TransformTo(Transform transform, out ControlPoint transformed)
+ public override Point TransformTo(Transform transform)
{
- TransformTo(transform, out Point transformedPoint);
- transformed = new ControlPoint(
- transformedPoint.x,
- transformedPoint.y,
- transformedPoint.z,
- weight,
- units,
- applicationId
- );
- return true;
+ return ((ITransformable)this).TransformTo(transform);
+ }
+
+ ControlPoint ITransformable.TransformTo(Transform transform)
+ {
+ Point transformedPoint = base.TransformTo(transform);
+ return new ControlPoint(transformedPoint.x, transformedPoint.y, transformedPoint.z, weight, units, applicationId);
}
public override string ToString()
diff --git a/src/Speckle.Objects/Geometry/Curve.cs b/src/Speckle.Objects/Geometry/Curve.cs
index bd14e3ac..da871935 100644
--- a/src/Speckle.Objects/Geometry/Curve.cs
+++ b/src/Speckle.Objects/Geometry/Curve.cs
@@ -57,41 +57,34 @@ public class Curve : Base, ICurve, IHasBoundingBox, IHasArea, ITransformable
- public bool TransformTo(Transform transform, out Curve transformed)
+ public Curve TransformTo(Transform transform)
{
// transform points
- var transformedPoints = new List();
- foreach (var point in GetPoints())
+ var originalPoints = GetPoints();
+ var transformedPoints = new List(originalPoints.Count * 3);
+ foreach (var point in originalPoints)
{
- point.TransformTo(transform, out Point transformedPoint);
- transformedPoints.Add(transformedPoint);
+ Point transformedPoint = point.TransformTo(transform);
+ transformedPoints.Add(transformedPoint.x);
+ transformedPoints.Add(transformedPoint.y);
+ transformedPoints.Add(transformedPoint.z);
}
- var result = displayValue.TransformTo(transform, out ITransformable polyline);
- transformed = new Curve
+ var transformedPolyline = displayValue.TransformTo(transform);
+ return new Curve
{
degree = degree,
periodic = periodic,
rational = rational,
- points = transformedPoints.SelectMany(o => o.ToList()).ToList(),
+ points = transformedPoints,
weights = weights,
knots = knots,
- displayValue = (Polyline)polyline,
+ displayValue = transformedPolyline,
closed = closed,
units = units,
applicationId = applicationId,
domain = domain != null ? new Interval { start = domain.start, end = domain.end } : Interval.UnitInterval,
};
-
- return result;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Curve curve);
- transformed = curve;
- return res;
}
/// as list of s
diff --git a/src/Speckle.Objects/Geometry/Line.cs b/src/Speckle.Objects/Geometry/Line.cs
index 2fe90022..0801d9fd 100644
--- a/src/Speckle.Objects/Geometry/Line.cs
+++ b/src/Speckle.Objects/Geometry/Line.cs
@@ -47,11 +47,11 @@ public Line(IList coordinates, string units, string? applicationId = nul
public Box? bbox { get; set; }
- public bool TransformTo(Transform transform, out Line transformed)
+ public Line TransformTo(Transform transform)
{
- start.TransformTo(transform, out Point transformedStart);
- end.TransformTo(transform, out Point transformedEnd);
- transformed = new Line
+ Point transformedStart = start.TransformTo(transform);
+ Point transformedEnd = end.TransformTo(transform);
+ return new Line
{
start = transformedStart,
end = transformedEnd,
@@ -59,14 +59,6 @@ public bool TransformTo(Transform transform, out Line transformed)
units = units,
domain = new() { start = domain.start, end = domain.end },
};
- return true;
- }
-
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Line line);
- transformed = line;
- return res;
}
public List ToList()
diff --git a/src/Speckle.Objects/Geometry/Mesh.cs b/src/Speckle.Objects/Geometry/Mesh.cs
index 64079c69..3d4dc8f8 100644
--- a/src/Speckle.Objects/Geometry/Mesh.cs
+++ b/src/Speckle.Objects/Geometry/Mesh.cs
@@ -44,7 +44,7 @@ public bool Transform(Transform transform)
vertices = GetPoints()
.SelectMany(vertex =>
{
- vertex.TransformTo(transform, out Point transformedVertex);
+ var transformedVertex = vertex.TransformTo(transform);
return transformedVertex.ToList();
})
.ToList();
@@ -53,36 +53,29 @@ public bool Transform(Transform transform)
}
///
- public bool TransformTo(Transform transform, out Mesh transformed)
+ public Mesh TransformTo(Transform transform)
{
// transform vertices
- var transformedVertices = new List();
- foreach (var vertex in GetPoints())
+ var originalVertices = GetPoints();
+ var transformedVertices = new List(originalVertices.Count * 3);
+ foreach (var vertex in originalVertices)
{
- vertex.TransformTo(transform, out Point transformedVertex);
- transformedVertices.Add(transformedVertex);
+ Point transformedVertex = vertex.TransformTo(transform);
+ transformedVertices.Add(transformedVertex.x);
+ transformedVertices.Add(transformedVertex.y);
+ transformedVertices.Add(transformedVertex.z);
}
- transformed = new Mesh
+ return new Mesh
{
- vertices = transformedVertices.SelectMany(o => o.ToList()).ToList(),
+ vertices = transformedVertices,
textureCoordinates = textureCoordinates,
applicationId = applicationId ?? id,
faces = faces,
colors = colors,
units = units,
+ ["renderMaterial"] = this["renderMaterial"],
};
- transformed["renderMaterial"] = this["renderMaterial"];
-
- return true;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Mesh brep);
- transformed = brep;
- return res;
}
#region Convenience Methods
diff --git a/src/Speckle.Objects/Geometry/Plane.cs b/src/Speckle.Objects/Geometry/Plane.cs
index 2da4b1bf..1ff9fb16 100644
--- a/src/Speckle.Objects/Geometry/Plane.cs
+++ b/src/Speckle.Objects/Geometry/Plane.cs
@@ -37,13 +37,13 @@ public class Plane : Base, ITransformable
public required string units { get; set; }
///
- public bool TransformTo(Transform transform, out Plane transformed)
+ public Plane TransformTo(Transform transform)
{
- origin.TransformTo(transform, out Point transformedOrigin);
- normal.TransformTo(transform, out Vector transformedNormal);
- xdir.TransformTo(transform, out Vector transformedXdir);
- ydir.TransformTo(transform, out Vector transformedYdir);
- transformed = new Plane
+ var transformedOrigin = origin.TransformTo(transform);
+ var transformedNormal = normal.TransformTo(transform);
+ var transformedXdir = xdir.TransformTo(transform);
+ var transformedYdir = ydir.TransformTo(transform);
+ return new Plane
{
origin = transformedOrigin,
normal = transformedNormal,
@@ -52,16 +52,6 @@ public bool TransformTo(Transform transform, out Plane transformed)
applicationId = applicationId,
units = units,
};
-
- return true;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Plane plane);
- transformed = plane;
- return res;
}
///
diff --git a/src/Speckle.Objects/Geometry/Point.cs b/src/Speckle.Objects/Geometry/Point.cs
index 9911ce73..edbd2e65 100644
--- a/src/Speckle.Objects/Geometry/Point.cs
+++ b/src/Speckle.Objects/Geometry/Point.cs
@@ -58,7 +58,7 @@ public Point(double x, double y, double z, string units, string? applicationId =
public required string units { get; set; }
///
- public bool TransformTo(Transform transform, out Point transformed)
+ public virtual Point TransformTo(Transform transform)
{
var matrix = transform.matrix;
@@ -68,16 +68,7 @@ public bool TransformTo(Transform transform, out Point transformed)
var y = (this.x * matrix.M21 + this.y * matrix.M22 + this.z * matrix.M23 + unitFactor * matrix.M24) / divisor;
var z = (this.x * matrix.M31 + this.y * matrix.M32 + this.z * matrix.M33 + unitFactor * matrix.M34) / divisor;
- transformed = new Point(x, y, z, units, applicationId);
- return true;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Point pt);
- transformed = pt;
- return res;
+ return new Point(x, y, z, units, applicationId);
}
///
diff --git a/src/Speckle.Objects/Geometry/Pointcloud.cs b/src/Speckle.Objects/Geometry/Pointcloud.cs
index ac76f174..fa523e5f 100644
--- a/src/Speckle.Objects/Geometry/Pointcloud.cs
+++ b/src/Speckle.Objects/Geometry/Pointcloud.cs
@@ -39,34 +39,27 @@ public class Pointcloud : Base, IHasBoundingBox, ITransformable
public Box? bbox { get; set; }
///
- public bool TransformTo(Transform transform, out Pointcloud transformed)
+ public Pointcloud TransformTo(Transform transform)
{
// transform points
- var transformedPoints = new List();
- foreach (var point in GetPoints())
+ var originalPoints = GetPoints();
+ var transformedPoints = new List(originalPoints.Count * 3);
+ foreach (var point in originalPoints)
{
- point.TransformTo(transform, out Point transformedPoint);
- transformedPoints.Add(transformedPoint);
+ var transformedPoint = point.TransformTo(transform);
+ transformedPoints.Add(transformedPoint.x);
+ transformedPoints.Add(transformedPoint.y);
+ transformedPoints.Add(transformedPoint.z);
}
- transformed = new Pointcloud
+ return new Pointcloud
{
units = units,
- points = transformedPoints.SelectMany(o => o.ToList()).ToList(),
+ points = transformedPoints,
colors = colors,
sizes = sizes,
applicationId = applicationId,
};
-
- return true;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Pointcloud pc);
- transformed = pc;
- return res;
}
/// as list of s
diff --git a/src/Speckle.Objects/Geometry/Polycurve.cs b/src/Speckle.Objects/Geometry/Polycurve.cs
index d081b651..6590b4c2 100644
--- a/src/Speckle.Objects/Geometry/Polycurve.cs
+++ b/src/Speckle.Objects/Geometry/Polycurve.cs
@@ -1,3 +1,4 @@
+using Speckle.Objects.Exceptions;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
@@ -9,7 +10,7 @@ namespace Speckle.Objects.Geometry;
/// A curve that is comprised of multiple curves connected.
///
[SpeckleType("Objects.Geometry.Polycurve")]
-public class Polycurve : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
+public class Polycurve : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
{
///
/// Gets or sets the list of segments that comprise this
@@ -43,33 +44,29 @@ public class Polycurve : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
public Box? bbox { get; set; }
///
- public bool TransformTo(Transform transform, out ITransformable polycurve)
+ public Polycurve TransformTo(Transform transform)
{
- // transform segments
- var success = true;
var transformed = new List();
- foreach (var curve in segments)
+ foreach (var segment in segments)
{
- if (curve is ITransformable c)
+ if (segment is not ITransformable c)
{
- c.TransformTo(transform, out ITransformable tc);
- transformed.Add((ICurve)tc);
- }
- else
- {
- success = false;
+ throw new TransformationException(
+ $"Polycurve could not be transformed because it contains {segment.GetType()} segments that are not transformable"
+ );
}
+
+ var tc = c.TransformTo(transform);
+ transformed.Add(tc);
}
- polycurve = new Polycurve
+ return new Polycurve
{
segments = transformed,
applicationId = applicationId,
closed = closed,
units = units,
};
-
- return success;
}
///
diff --git a/src/Speckle.Objects/Geometry/Polyline.cs b/src/Speckle.Objects/Geometry/Polyline.cs
index 6c3dac9f..5354e03b 100644
--- a/src/Speckle.Objects/Geometry/Polyline.cs
+++ b/src/Speckle.Objects/Geometry/Polyline.cs
@@ -10,7 +10,7 @@ namespace Speckle.Objects.Geometry;
/// A polyline curve, defined by a set of vertices.
///
[SpeckleType("Objects.Geometry.Polyline")]
-public class Polyline : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
+public class Polyline : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
{
///
/// Gets or sets the raw coordinates that define this polyline. Use GetPoints instead to access this data as instances instead.
@@ -44,25 +44,26 @@ public class Polyline : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
public Box? bbox { get; set; }
///
- public bool TransformTo(Transform transform, out ITransformable transformed)
+ public Polyline TransformTo(Transform transform)
{
// transform points
- var transformedPoints = new List();
- foreach (var point in GetPoints())
+ var originalPoints = GetPoints();
+ var transformedPoints = new List(originalPoints.Count * 3);
+ foreach (var point in originalPoints)
{
- point.TransformTo(transform, out Point transformedPoint);
- transformedPoints.Add(transformedPoint);
+ Point transformedPoint = point.TransformTo(transform);
+ transformedPoints.Add(transformedPoint.x);
+ transformedPoints.Add(transformedPoint.y);
+ transformedPoints.Add(transformedPoint.z);
}
- transformed = new Polyline
+ return new Polyline
{
- value = transformedPoints.SelectMany(o => o.ToList()).ToList(),
+ value = transformedPoints,
closed = closed,
applicationId = applicationId,
units = units,
};
-
- return true;
}
///This function may be suboptimal for performance for polylines with many points
diff --git a/src/Speckle.Objects/Geometry/Surface.cs b/src/Speckle.Objects/Geometry/Surface.cs
index d97ed633..47d0cf4a 100644
--- a/src/Speckle.Objects/Geometry/Surface.cs
+++ b/src/Speckle.Objects/Geometry/Surface.cs
@@ -103,19 +103,20 @@ public Surface(IList pointData, int countU, int countV)
public Box? bbox { get; set; }
///
- public bool TransformTo(Transform transform, out Surface transformed)
+ public Surface TransformTo(Transform transform)
{
var ptMatrix = GetControlPoints();
foreach (var ctrlPts in ptMatrix)
{
for (int i = 0; i < ctrlPts.Count; i++)
{
- ctrlPts[i].TransformTo(transform, out var tPt);
+ ITransformable pt = ctrlPts[i];
+ var tPt = pt.TransformTo(transform);
ctrlPts[i] = tPt;
}
}
- transformed = new Surface(ptMatrix)
+ return new Surface(ptMatrix)
{
degreeU = degreeU,
degreeV = degreeV,
@@ -130,16 +131,6 @@ public bool TransformTo(Transform transform, out Surface transformed)
knotsV = knotsV,
units = units,
};
-
- return true;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- var res = TransformTo(transform, out Surface surface);
- transformed = surface;
- return res;
}
///
diff --git a/src/Speckle.Objects/Geometry/Vector.cs b/src/Speckle.Objects/Geometry/Vector.cs
index 83114648..93e2b355 100644
--- a/src/Speckle.Objects/Geometry/Vector.cs
+++ b/src/Speckle.Objects/Geometry/Vector.cs
@@ -64,22 +64,13 @@ public Vector(double x, double y, double z, string units, string? applicationId
public Box? bbox { get; set; }
///
- public bool TransformTo(Transform transform, out Vector transformed)
+ public Vector TransformTo(Transform transform)
{
var m = transform.matrix;
var tX = x * m.M11 + y * m.M12 + z * m.M13;
var tY = x * m.M21 + y * m.M22 + z * m.M23;
var tZ = x * m.M31 + y * m.M32 + z * m.M33;
- transformed = new Vector(tX, tY, tZ, units, applicationId);
- return true;
- }
-
- ///
- public bool TransformTo(Transform transform, out ITransformable transformed)
- {
- _ = TransformTo(transform, out Vector vec);
- transformed = vec;
- return true;
+ return new Vector(tX, tY, tZ, units, applicationId);
}
///
diff --git a/src/Speckle.Objects/Interfaces.cs b/src/Speckle.Objects/Interfaces.cs
index 43f6d52f..d6936601 100644
--- a/src/Speckle.Objects/Interfaces.cs
+++ b/src/Speckle.Objects/Interfaces.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.Contracts;
+using Speckle.Objects.Exceptions;
using Speckle.Objects.Geometry;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
@@ -62,27 +64,24 @@ public interface ICurve : ISpeckleObject
/// Generic Interface for transformable objects.
///
/// The type of object to support transformations.
-public interface ITransformable : ITransformable
- where T : ITransformable
-{
- ///
- bool TransformTo(Transform transform, out T transformed);
-}
-
-///
-/// Interface for transformable objects where the type may not be known on convert (eg ICurve implementations)
-///
-public interface ITransformable : ISpeckleObject
+public interface ITransformable : ITransformable
+ where T : ISpeckleObject
{
///
- /// Returns a copy of the object with it's coordinates transformed by the provided
+ /// Returns a copy of the object with its coordinates transformed by the provided
///
/// The to be applied.
- /// The transformed copy of the object.
- /// True if the transform operation was successful, false otherwise.
- bool TransformTo(Transform transform, out ITransformable transformed);
+ /// thrown if the object could not be transformed by the provided
+ /// The transformed copy of the object.
+ [Pure]
+ T TransformTo(Transform transform);
}
+///
+/// Do not inherit directly, inherit from instead
+///
+public interface ITransformable : ISpeckleObject { }
+
///
/// Specifies displayable simple geometries to be used as a fallback
/// if a displayable form cannot be converted.
diff --git a/src/Speckle.Objects/TransformableExtensions.cs b/src/Speckle.Objects/TransformableExtensions.cs
new file mode 100644
index 00000000..caed4a03
--- /dev/null
+++ b/src/Speckle.Objects/TransformableExtensions.cs
@@ -0,0 +1,32 @@
+using System.Diagnostics.CodeAnalysis;
+using Speckle.Objects.Other;
+
+namespace Speckle.Objects;
+
+public static class TransformableExtensions
+{
+ ///
+ public static ITransformable TransformTo(this ITransformable transformable, Transform transform)
+ {
+ return ((ITransformable)transformable).TransformTo(transform);
+ }
+
+ public static bool TransformTo(
+ this ITransformable transformable,
+ Transform transform,
+ [NotNull] out T? transformed
+ )
+ where T : class, ITransformable
+ {
+ // try
+ // {
+ transformed = (T)transformable.TransformTo(transform);
+ return true;
+ // }
+ // catch (TransformationException)
+ // {
+ // transformed = null;
+ // return false;
+ // }
+ }
+}
diff --git a/tests/Speckle.Objects.Tests.Unit/Geometry/VectorTests.cs b/tests/Speckle.Objects.Tests.Unit/Geometry/VectorTests.cs
new file mode 100644
index 00000000..dae91baf
--- /dev/null
+++ b/tests/Speckle.Objects.Tests.Unit/Geometry/VectorTests.cs
@@ -0,0 +1,40 @@
+using Speckle.Objects.Geometry;
+using Xunit;
+
+namespace Speckle.Objects.Tests.Unit.Geometry;
+
+public class VectorTests
+{
+ [Theory]
+ [InlineData(1d, 2d, 3d, "m")]
+ [InlineData(100d, 0d, -200d, "ft")]
+ public void TestConstruction(double x, double y, double z, string units)
+ {
+ var pctor = new Vector(x, y, z, units);
+
+ var init = new Vector
+ {
+ x = x,
+ y = y,
+ z = z,
+ units = units,
+ };
+
+ Assert.Equal(pctor.x, init.x);
+ Assert.Equal(pctor.y, init.y);
+ Assert.Equal(pctor.z, init.z);
+ Assert.Equal(pctor.units, init.units);
+ }
+
+ [Theory]
+ [InlineData(1d, 0d, 0d, 1d)]
+ [InlineData(0d, 2d, 0d, 2d)]
+ [InlineData(0d, 0d, -3d, 3d)]
+ [InlineData(1d, 1d, 0d, 1.4142135623730951d)]
+ public void TestLength(double x, double y, double z, double expected)
+ {
+ var testCase = new Vector(x, y, z, "");
+ var actual = testCase.Length;
+ Assert.Equal(actual, expected);
+ }
+}