Skip to content

Commit

Permalink
even more converters
Browse files Browse the repository at this point in the history
  • Loading branch information
adamhathcock committed Jun 18, 2024
1 parent 91d2336 commit 1b1e2d6
Show file tree
Hide file tree
Showing 22 changed files with 223 additions and 162 deletions.
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
using Speckle.Converters.Common.Objects;
using Speckle.Rhino7.Interfaces;

namespace Speckle.Converters.Rhino7.ToHost.Raw;

/// <summary>
/// Converts a SpeckleArcRaw object to a Rhino.Geometry.Arc object or Rhino.Geometry.ArcCurve object.
/// </summary>
public class ArcToHostConverter : ITypedConverter<SOG.Arc, RG.Arc>, ITypedConverter<SOG.Arc, RG.ArcCurve>
public class ArcToHostConverter : ITypedConverter<SOG.Arc, IRhinoArc>, ITypedConverter<SOG.Arc, IRhinoArcCurve>
{
private readonly ITypedConverter<SOG.Point, RG.Point3d> _pointConverter;
private readonly ITypedConverter<SOP.Interval, RG.Interval> _intervalConverter;
private readonly ITypedConverter<SOG.Point, IRhinoPoint3d> _pointConverter;
private readonly ITypedConverter<SOP.Interval, IRhinoInterval> _intervalConverter;
private readonly IRhinoArcFactory _rhinoArcFactory;

public ArcToHostConverter(
ITypedConverter<SOG.Point, RG.Point3d> pointConverter,
ITypedConverter<SOP.Interval, RG.Interval> intervalConverter
)
ITypedConverter<SOG.Point, IRhinoPoint3d> pointConverter,
ITypedConverter<SOP.Interval, IRhinoInterval> intervalConverter, IRhinoArcFactory rhinoArcFactory)
{
_pointConverter = pointConverter;
this._intervalConverter = intervalConverter;
_rhinoArcFactory = rhinoArcFactory;
}

/// <summary>
/// Converts a <see cref="SOG.Arc"/> object to a <see cref="RG.Arc"/> object.
/// Converts a <see cref="SOG.Arc"/> object to a <see cref="IRhinoArc"/> object.
/// </summary>
/// <param name="target">The Speckle Arc object to convert.</param>
/// <returns>The converted <see cref="RG.Arc"/> object.</returns>
/// <returns>The converted <see cref="IRhinoArc"/> object.</returns>
/// <remarks>⚠️ This conversion does NOT perform scaling.</remarks>
/// <remarks><br/>⚠️ This method does not preserve the original curve domain</remarks>
public RG.Arc Convert(SOG.Arc target)
public IRhinoArc Convert(SOG.Arc target)
{
var rhinoArc = new RG.Arc(
var rhinoArc = _rhinoArcFactory.Create(
_pointConverter.Convert(target.startPoint),
_pointConverter.Convert(target.midPoint),
_pointConverter.Convert(target.endPoint)
Expand All @@ -39,16 +41,16 @@ public RG.Arc Convert(SOG.Arc target)
// POC: CNX-9271 Potential code-smell by directly implementing the interface. We should discuss this further but
// since we're using the interfaces instead of the direct type, this may not be an issue.
/// <summary>
/// Converts a <see cref="SOG.Arc"/> object to a <see cref="RG.ArcCurve"/> object.
/// Converts a <see cref="SOG.Arc"/> object to a <see cref="IRhinoArcCurve"/> object.
/// </summary>
/// <param name="target">The <see cref="SOG.Arc"/> object to convert.</param>
/// <returns>The converted <see cref="RG.ArcCurve"/> object.</returns>
/// <returns>The converted <see cref="IRhinoArcCurve"/> object.</returns>
/// <remarks>⚠️ This conversion does NOT perform scaling.</remarks>
/// <remarks><br/>⚠️ Converting to <see cref="RG.ArcCurve"/> instead of <see cref="RG.Arc"/> preserves the domain of the curve.</remarks>
RG.ArcCurve ITypedConverter<SOG.Arc, RG.ArcCurve>.Convert(SOG.Arc target)
/// <remarks><br/>⚠️ Converting to <see cref="IRhinoArcCurve"/> instead of <see cref="IRhinoArc"/> preserves the domain of the curve.</remarks>
IRhinoArcCurve ITypedConverter<SOG.Arc, IRhinoArcCurve>.Convert(SOG.Arc target)
{
var rhinoArc = Convert(target);
var arcCurve = new RG.ArcCurve(rhinoArc) { Domain = _intervalConverter.Convert(target.domain) };
var arcCurve = _rhinoArcFactory.Create(rhinoArc, _intervalConverter.Convert(target.domain));
return arcCurve;
}
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,48 @@
using Speckle.Converters.Common.Objects;
using Speckle.Rhino7.Interfaces;

namespace Speckle.Converters.Rhino7.ToHost.Raw;

/// <summary>
/// This class is responsible for converting a <see cref="SOG.Circle"/> into <see cref="RG.Circle"/> and <see cref="RG.ArcCurve"/> objects.
/// This class is responsible for converting a <see cref="SOG.Circle"/> into <see cref="IRhinoCircle"/> and <see cref="IRhinoArcCurve"/> objects.
/// Implements the <see cref="ITypedConverter{TIn,TOut}"/> interface,
/// providing implementation for <see cref="SOG.Circle"/> to <see cref="RG.Circle"/> and <see cref="RG.ArcCurve"/> conversion.
/// providing implementation for <see cref="SOG.Circle"/> to <see cref="IRhinoCircle"/> and <see cref="IRhinoArcCurve"/> conversion.
/// </summary>
public class CircleToHostConverter : ITypedConverter<SOG.Circle, RG.Circle>, ITypedConverter<SOG.Circle, RG.ArcCurve>
public class CircleToHostConverter : ITypedConverter<SOG.Circle, IRhinoCircle>, ITypedConverter<SOG.Circle, IRhinoArcCurve>
{
private readonly ITypedConverter<SOG.Plane, RG.Plane> _planeConverter;
private readonly ITypedConverter<SOP.Interval, RG.Interval> _intervalConverter;
private readonly ITypedConverter<SOG.Plane, IRhinoPlane> _planeConverter;
private readonly ITypedConverter<SOP.Interval, IRhinoInterval> _intervalConverter;
private readonly IRhinoCircleFactory _rhinoCircleFactory;

/// <summary>
/// Constructs a new instance of the <see cref="CircleToHostConverter"/> class.
/// </summary>
/// <param name="intervalConverter">
/// An implementation of <see cref="ITypedConverter{TIn,TOut}"/> used to convert <see cref="SOP.Interval"/> into <see cref="RG.Interval"/>.
/// An implementation of <see cref="ITypedConverter{TIn,TOut}"/> used to convert <see cref="SOP.Interval"/> into <see cref="IRhinoInterval"/>.
/// </param>
/// <param name="planeConverter">
/// An implementation of <see cref="ITypedConverter{TIn,TOut}"/> used to convert <see cref="SOG.Plane"/> into <see cref="RG.Plane"/>.
/// An implementation of <see cref="ITypedConverter{TIn,TOut}"/> used to convert <see cref="SOG.Plane"/> into <see cref="IRhinoPlane"/>.
/// </param>
public CircleToHostConverter(
ITypedConverter<SOP.Interval, RG.Interval> intervalConverter,
ITypedConverter<SOG.Plane, RG.Plane> planeConverter
)
ITypedConverter<SOP.Interval, IRhinoInterval> intervalConverter,
ITypedConverter<SOG.Plane, IRhinoPlane> planeConverter, IRhinoCircleFactory rhinoCircleFactory)
{
_intervalConverter = intervalConverter;
_planeConverter = planeConverter;
_rhinoCircleFactory = rhinoCircleFactory;
}

/// <summary>
/// Converts the given <see cref="SOG.Circle"/> object into a <see cref="RG.Circle"/> object.
/// Converts the given <see cref="SOG.Circle"/> object into a <see cref="IRhinoCircle"/> object.
/// </summary>
/// <param name="target">The <see cref="SOG.Circle"/> object to convert.</param>
/// <returns>The resulting <see cref="RG.Circle"/> object.</returns>
/// <returns>The resulting <see cref="IRhinoCircle"/> object.</returns>
/// <exception cref="ArgumentNullException">
/// Thrown when the radius of the given <see cref="SOG.Circle"/> object is null.
/// </exception>
/// <remarks>⚠️ This conversion does NOT perform scaling.</remarks>
/// <remarks><br/>⚠️ This conversion does not preserve the curve domain. If you need it preserved you must request a conversion to <see cref="RG.ArcCurve"/> conversion instead</remarks>
public RG.Circle Convert(SOG.Circle target)
/// <remarks><br/>⚠️ This conversion does not preserve the curve domain. If you need it preserved you must request a conversion to <see cref="IRhinoArcCurve"/> conversion instead</remarks>
public IRhinoCircle Convert(SOG.Circle target)
{
if (target.radius == null)
{
Expand All @@ -50,9 +52,9 @@ public RG.Circle Convert(SOG.Circle target)

var plane = _planeConverter.Convert(target.plane);
var radius = target.radius.Value;
return new RG.Circle(plane, radius);
return _rhinoCircleFactory.Create(plane, radius);
}

RG.ArcCurve ITypedConverter<SOG.Circle, RG.ArcCurve>.Convert(SOG.Circle target) =>
new(Convert(target)) { Domain = _intervalConverter.Convert(target.domain) };
IRhinoArcCurve ITypedConverter<SOG.Circle, IRhinoArcCurve>.Convert(SOG.Circle target) =>
_rhinoCircleFactory.Create(Convert(target), _intervalConverter.Convert(target.domain));
}
Original file line number Diff line number Diff line change
@@ -1,49 +1,51 @@
using Speckle.Converters.Common.Objects;
using Speckle.Rhino7.Interfaces;

namespace Speckle.Converters.Rhino7.ToHost.Raw;

public class EllipseToHostConverter
: ITypedConverter<SOG.Ellipse, RG.Ellipse>,
ITypedConverter<SOG.Ellipse, RG.NurbsCurve>
: ITypedConverter<SOG.Ellipse, IRhinoEllipse>,
ITypedConverter<SOG.Ellipse, IRhinoNurbsCurve>
{
private readonly ITypedConverter<SOG.Plane, RG.Plane> _planeConverter;
private readonly ITypedConverter<SOP.Interval, RG.Interval> _intervalConverter;
private readonly ITypedConverter<SOG.Plane, IRhinoPlane> _planeConverter;
private readonly ITypedConverter<SOP.Interval, IRhinoInterval> _intervalConverter;
private readonly IRhinoEllipseFactory _rhinoEllipseFactory;

public EllipseToHostConverter(
ITypedConverter<SOG.Plane, RG.Plane> planeConverter,
ITypedConverter<SOP.Interval, RG.Interval> intervalConverter
)
ITypedConverter<SOG.Plane, IRhinoPlane> planeConverter,
ITypedConverter<SOP.Interval, IRhinoInterval> intervalConverter, IRhinoEllipseFactory rhinoEllipseFactory)
{
_planeConverter = planeConverter;
_intervalConverter = intervalConverter;
_rhinoEllipseFactory = rhinoEllipseFactory;
}

/// <summary>
/// Converts an instance of <see cref="SOG.Ellipse"/> to an <see cref="RG.Ellipse"/> while preserving geometric properties.
/// Converts an instance of <see cref="SOG.Ellipse"/> to an <see cref="IRhinoEllipse"/> while preserving geometric properties.
/// </summary>
/// <param name="target">The <see cref="SOG.Ellipse"/> instance to be converted.</param>
/// <returns>The resulting <see cref="RG.Ellipse"/> after conversion.</returns>
/// <returns>The resulting <see cref="IRhinoEllipse"/> after conversion.</returns>
/// <exception cref="InvalidOperationException">Thrown when <see cref="SOG.Ellipse.firstRadius"/> or <see cref="SOG.Ellipse.secondRadius"/> properties are null.</exception>
/// <remarks>⚠️ This conversion does NOT perform scaling.</remarks>
/// <remarks><br/>⚠️ This conversion does not preserve the curve domain. If you need it preserved you must request a conversion to <see cref="RG.NurbsCurve"/> conversion instead</remarks>
public RG.Ellipse Convert(SOG.Ellipse target)
/// <remarks><br/>⚠️ This conversion does not preserve the curve domain. If you need it preserved you must request a conversion to <see cref="IRhinoNurbsCurve"/> conversion instead</remarks>
public IRhinoEllipse Convert(SOG.Ellipse target)
{
if (!target.firstRadius.HasValue || !target.secondRadius.HasValue)
{
throw new InvalidOperationException($"Ellipses cannot have null radii");
}

return new RG.Ellipse(_planeConverter.Convert(target.plane), target.firstRadius.Value, target.secondRadius.Value);
return _rhinoEllipseFactory.Create(_planeConverter.Convert(target.plane), target.firstRadius.Value, target.secondRadius.Value);
}

/// <summary>
/// Converts the provided <see cref="SOG.Ellipse"/> into a <see cref="RG.NurbsCurve"/> representation.
/// Converts the provided <see cref="SOG.Ellipse"/> into a <see cref="IRhinoNurbsCurve"/> representation.
/// </summary>
/// <param name="target">The <see cref="SOG.Ellipse"/> to convert.</param>
/// <returns>
/// A <see cref="RG.NurbsCurve"/> that represents the provided <see cref="SOG.Ellipse"/>.
/// A <see cref="IRhinoNurbsCurve"/> that represents the provided <see cref="SOG.Ellipse"/>.
/// </returns>
RG.NurbsCurve ITypedConverter<SOG.Ellipse, RG.NurbsCurve>.Convert(SOG.Ellipse target)
IRhinoNurbsCurve ITypedConverter<SOG.Ellipse, IRhinoNurbsCurve>.Convert(SOG.Ellipse target)
{
var rhinoEllipse = Convert(target);
var rhinoNurbsEllipse = rhinoEllipse.ToNurbsCurve();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
using Rhino.Collections;
using Speckle.Converters.Common.Objects;
using Speckle.Converters.Common.Objects;
using Speckle.Core.Logging;
using Speckle.Rhino7.Interfaces;

namespace Speckle.Converters.Rhino7.ToHost.Raw;

/// <summary>
/// Converts a flat list of raw double values to a Point3dList.
/// </summary>
public class FlatPointListToHostConverter : ITypedConverter<IReadOnlyList<double>, Point3dList>
public class FlatPointListToHostConverter : ITypedConverter<IReadOnlyList<double>, IRhinoPoint3dList>
{
private readonly IRhinoPointFactory _rhinoPointFactory;

public FlatPointListToHostConverter(IRhinoPointFactory rhinoPointFactory)
{
_rhinoPointFactory = rhinoPointFactory;
}

/// <summary>
/// Converts a flat list of raw double values to a Point3dList.
/// </summary>
Expand All @@ -19,20 +26,20 @@ public class FlatPointListToHostConverter : ITypedConverter<IReadOnlyList<double
/// with the numbers being coordinates of each point in the format {x1, y1, z1, x2, y2, z2, ..., xN, yN, zN}
/// </remarks>
/// <exception cref="SpeckleException">Throws when the input list count is not a multiple of 3.</exception>
public Point3dList Convert(IReadOnlyList<double> target)
public IRhinoPoint3dList Convert(IReadOnlyList<double> target)
{
if (target.Count % 3 != 0)
{
throw new SpeckleException("Array malformed: length%3 != 0.");
}

var points = new List<RG.Point3d>(target.Count / 3);
var points = new List<IRhinoPoint3d>(target.Count / 3);

for (int i = 2; i < target.Count; i += 3)
{
points.Add(new RG.Point3d(target[i - 2], target[i - 1], target[i]));
points.Add(_rhinoPointFactory.Create(target[i - 2], target[i - 1], target[i]));
}

return new Point3dList(points);
return _rhinoPointFactory.Create(points);
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
using Speckle.Converters.Common.Objects;
using Speckle.Rhino7.Interfaces;

namespace Speckle.Converters.Rhino7.ToHost.Raw;

public class IntervalToHostConverter : ITypedConverter<SOP.Interval, RG.Interval>
public class IntervalToHostConverter : ITypedConverter<SOP.Interval, IRhinoInterval>
{
private readonly IRhinoIntervalFactory _rhinoIntervalFactory;

public IntervalToHostConverter(IRhinoIntervalFactory rhinoIntervalFactory)
{
_rhinoIntervalFactory = rhinoIntervalFactory;
}

/// <summary>
/// Converts a Speckle Interval object to a Rhino.Geometry.Interval object.
/// </summary>
/// <param name="target">The Speckle Interval to convert.</param>
/// <returns>The converted Rhino.Geometry.Interval object.</returns>
/// <exception cref="ArgumentException">Thrown when the start or end value of the Interval is null.</exception>
/// <remarks>⚠️ This conversion does NOT perform scaling.</remarks>
public RG.Interval Convert(SOP.Interval target)
public IRhinoInterval Convert(SOP.Interval target)
{
if (!target.start.HasValue || !target.end.HasValue) // POC: CNX-9272 Interval start and end being nullable makes no sense.
{
throw new ArgumentException("Interval start/end cannot be null");
}

return new RG.Interval(target.start.Value, target.end.Value);
return _rhinoIntervalFactory.Create(target.start.Value, target.end.Value);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using Speckle.Converters.Common.Objects;
using Speckle.Rhino7.Interfaces;

namespace Speckle.Converters.Rhino7.ToHost.Raw;

public class LineToHostConverter : ITypedConverter<SOG.Line, RG.LineCurve>, ITypedConverter<SOG.Line, RG.Line>
public class LineToHostConverter : ITypedConverter<SOG.Line, IRhinoLineCurve>, ITypedConverter<SOG.Line, IRhinoLine>
{
private readonly ITypedConverter<SOG.Point, RG.Point3d> _pointConverter;
private readonly ITypedConverter<SOG.Point, IRhinoPoint3d> _pointConverter;
private readonly IRhinoLineFactory _rhinoLineFactory;

public LineToHostConverter(ITypedConverter<SOG.Point, RG.Point3d> pointConverter)
public LineToHostConverter(ITypedConverter<SOG.Point, IRhinoPoint3d> pointConverter, IRhinoLineFactory rhinoLineFactory)
{
_pointConverter = pointConverter;
_rhinoLineFactory = rhinoLineFactory;
}

/// <summary>
Expand All @@ -20,15 +23,15 @@ public LineToHostConverter(ITypedConverter<SOG.Point, RG.Point3d> pointConverter
/// <remarks>
/// <br/>⚠️ This conversion does not preserve the curve domain.
/// If you need it preserved you must request a conversion to
/// <see cref="RG.LineCurve"/> conversion instead
/// <see cref="IRhinoLineCurve"/> conversion instead
/// </remarks>
public RG.Line Convert(SOG.Line target) =>
new(_pointConverter.Convert(target.start), _pointConverter.Convert(target.end));
public IRhinoLine Convert(SOG.Line target) =>
_rhinoLineFactory.Create(_pointConverter.Convert(target.start), _pointConverter.Convert(target.end));

/// <summary>
/// Converts a Speckle Line object to a Rhino LineCurve object.
/// </summary>
/// <param name="target">The Speckle Line object to convert.</param>
/// <returns>Returns the resulting Rhino LineCurve object.</returns>
RG.LineCurve ITypedConverter<SOG.Line, RG.LineCurve>.Convert(SOG.Line target) => new(Convert(target));
IRhinoLineCurve ITypedConverter<SOG.Line, IRhinoLineCurve>.Convert(SOG.Line target) => _rhinoLineFactory.Create(Convert(target));
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;
using Speckle.Rhino7.Interfaces;

namespace Speckle.Converters.Rhino7.ToHost.Raw;

public class NurbsCurveToHostConverter : ITypedConverter<SOG.Curve, RG.NurbsCurve>
public class NurbsCurveToHostConverter : ITypedConverter<SOG.Curve, IRhinoNurbsCurve>
{
private readonly ITypedConverter<SOP.Interval, RG.Interval> _intervalConverter;
private readonly IRhinoPointFactory _rhinoPointFactory;
private readonly IRhinoCurveFactory _rhinoCurveFactory;
private readonly ITypedConverter<SOP.Interval, IRhinoInterval> _intervalConverter;

public NurbsCurveToHostConverter(ITypedConverter<SOP.Interval, RG.Interval> intervalConverter)
public NurbsCurveToHostConverter(ITypedConverter<SOP.Interval, IRhinoInterval> intervalConverter, IRhinoCurveFactory rhinoCurveFactory, IRhinoPointFactory rhinoPointFactory)
{
_intervalConverter = intervalConverter;
_rhinoCurveFactory = rhinoCurveFactory;
_rhinoPointFactory = rhinoPointFactory;
}

/// <summary>
Expand All @@ -19,14 +24,14 @@ public NurbsCurveToHostConverter(ITypedConverter<SOP.Interval, RG.Interval> inte
/// <returns>The converted Rhino NurbsCurve object.</returns>
/// <exception cref="SpeckleConversionException">Thrown when the conversion fails.</exception>
/// <remarks>⚠️ This conversion does NOT perform scaling.</remarks>
public RG.NurbsCurve Convert(SOG.Curve target)
public IRhinoNurbsCurve Convert(SOG.Curve target)
{
RG.NurbsCurve nurbsCurve = new(target.degree, target.points.Count / 3);
IRhinoNurbsCurve nurbsCurve = _rhinoCurveFactory.Create(target.degree, target.points.Count / 3);

// Hyper optimised curve control point conversion
for (int i = 2, j = 0; i < target.points.Count; i += 3, j++)
{
var pt = new RG.Point3d(target.points[i - 2], target.points[i - 1], target.points[i]); // Skip the point converter for performance
var pt = _rhinoPointFactory.Create(target.points[i - 2], target.points[i - 1], target.points[i]); // Skip the point converter for performance
nurbsCurve.Points.SetPoint(j, pt, target.weights[j]);
}

Expand All @@ -37,11 +42,11 @@ public RG.NurbsCurve Convert(SOG.Curve target)
{
if (extraKnots == 2)
{
nurbsCurve.Knots[j] = target.knots[j + 1];
nurbsCurve.Knots.SetKnot(j, target.knots[j + 1]);
}
else
{
nurbsCurve.Knots[j] = target.knots[j];
nurbsCurve.Knots.SetKnot(j, target.knots[j]);
}
}

Expand Down
Loading

0 comments on commit 1b1e2d6

Please sign in to comment.