Skip to content

Commit

Permalink
Merge pull request #339 from GSharker/dev/mibi/refactor-polyline
Browse files Browse the repository at this point in the history
Refactor ``Polyline``
  • Loading branch information
cesarecaoduro authored Sep 7, 2021
2 parents 9156f0a + 5a494b4 commit 5869281
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 195 deletions.
Binary file modified src/GShark.Test.XUnit/DebugFiles/GHDebug_Curves.gh
Binary file not shown.
40 changes: 13 additions & 27 deletions src/GShark.Test.XUnit/Geometry/CircleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,10 @@ public void It_Returns_A_Circle3D_With_Its_Nurbs_Representation()
public void It_Returns_The_Circumference_Of_A_Circle()
{
// Arrange
Circle circle = _circle2D;
int expectedCircumference = 46;

// Act
double circumference = circle.Length;
double circumference = _circle2D.Length;

// Assert
(circumference / Math.PI).Should().Be(expectedCircumference);
Expand All @@ -99,10 +98,9 @@ public void It_Returns_The_Point_On_The_Circle_At_The_Give_Parameter(double t, d
{
// Arrange
Point3 expectedPt = new Point3(pts[0], pts[1], pts[2]);
Circle circle = _circle2D;

// Act
Point3 pt = circle.PointAt(t);
Point3 pt = _circle2D.PointAt(t);

// Assert
pt.EpsilonEquals(expectedPt, GSharkMath.MaxTolerance).Should().BeTrue();
Expand All @@ -116,10 +114,9 @@ public void It_Returns_The_Tangent_At_The_Give_Parameter(double t, double[] pts)
{
// Arrange
Vector3 expectedTangent = new Vector3(pts[0], pts[1], pts[2]);
Circle circle = _circle2D;

// Act
Vector3 tangent = circle.TangentAt(t);
Vector3 tangent = _circle2D.TangentAt(t);

// Assert
tangent.EpsilonEquals(expectedTangent, GSharkMath.MaxTolerance).Should().BeTrue();
Expand All @@ -133,12 +130,11 @@ public void It_Returns_The_Point_On_The_Circle_At_The_Give_Length(double length,
{
// Arrange
Point3 expectedPt = new Point3(pts[0], pts[1], pts[2]);
Circle circle = _circle2D;

// Act
double normalizeLength = GSharkMath.RemapValue(length, new Interval(0.0, circle.Length), new Interval(0.0, 1.0));
Point3 pt = circle.PointAtLength(length);
Point3 ptNormalizedLength = circle.PointAtLength(normalizeLength, true);
double normalizeLength = GSharkMath.RemapValue(length, new Interval(0.0, _circle2D.Length), new Interval(0.0, 1.0));
Point3 pt = _circle2D.PointAtLength(length);
Point3 ptNormalizedLength = _circle2D.PointAtNormalizedLength(normalizeLength);

// Assert
pt.EpsilonEquals(expectedPt, GSharkMath.MaxTolerance).Should().BeTrue();
Expand All @@ -153,16 +149,12 @@ public void It_Returns_The_Tangent_At_The_Give_Length(double length, double[] pt
{
// Arrange
Vector3 expectedTangent = new Vector3(pts[0], pts[1], pts[2]);
Circle circle = _circle2D;

// Act
double normalizeLength = GSharkMath.RemapValue(length, new Interval(0.0, circle.Length), new Interval(0.0, 1.0));
Vector3 tangent = circle.TangentAtLength(length);
Vector3 tangentNormalizedLength = circle.TangentAtLength(normalizeLength, true);
Vector3 tangent = _circle2D.TangentAtLength(length);

// Assert
tangent.EpsilonEquals(expectedTangent, GSharkMath.MaxTolerance).Should().BeTrue();
tangent.EpsilonEquals(tangentNormalizedLength, GSharkMath.MaxTolerance).Should().BeTrue();
}

[Theory]
Expand All @@ -171,11 +163,8 @@ public void It_Returns_The_Tangent_At_The_Give_Length(double length, double[] pt
[InlineData(5.1, 117.3)]
public void It_Returns_The_Length_At_The_Give_Parameter(double parameter, double expectedLength)
{
// Arrange
Circle circle = _circle2D;

// Act
double length = circle.LengthAt(parameter);
double length = _circle2D.LengthAt(parameter);

// Assert
length.Should().BeApproximately(expectedLength, GSharkMath.MinTolerance);
Expand All @@ -185,12 +174,11 @@ public void It_Returns_The_Length_At_The_Give_Parameter(double parameter, double
public void It_Returns_The_Bounding_Box_Of_The_Circle()
{
// Arrange
Circle circle = _circle2D;
Point3 minCheck = new Point3(62.592479, 2.549050, -4.77519);
Point3 maxCheck = new Point3(108.591002, 47.043069, 6.904624);

// Act
BoundingBox bBox = circle.GetBoundingBox();
BoundingBox bBox = _circle2D.GetBoundingBox();

// Assert
bBox.Min.EpsilonEquals(minCheck, GSharkMath.MaxTolerance).Should().BeTrue();
Expand Down Expand Up @@ -218,15 +206,14 @@ public void It_Returns_The_Closest_Point_On_A_Circle(double[] ptToTest, double[]
public void Returns_The_Offset_Of_A_Circle()
{
// Arrange
Circle cl = _circle2D;
double offset = -5;

// Act
Circle offsetResult = cl.Offset(offset);
Circle offsetResult = _circle2D.Offset(offset);

// Assert
offsetResult.Plane.Origin.Should().BeEquivalentTo(cl.Plane.Origin);
(offsetResult.Radius - offset).Should().Be(cl.Radius);
offsetResult.Plane.Origin.Should().BeEquivalentTo(_circle2D.Plane.Origin);
(offsetResult.Radius - offset).Should().Be(_circle2D.Radius);
}

[Theory]
Expand All @@ -238,8 +225,7 @@ public void It_Returns_The_Closest_Parameter_On_A_Circle(double[] ptToTest, doub
Point3 testPt = new Point3(ptToTest[0], ptToTest[1], ptToTest[2]);

// Act
Circle circle = _circle3D;
double parameter = circle.ClosestParameter(testPt);
double parameter = _circle3D.ClosestParameter(testPt);

// Assert
parameter.Should().BeApproximately(expectedParameter, GSharkMath.MaxTolerance);
Expand Down
2 changes: 1 addition & 1 deletion src/GShark.Test.XUnit/Geometry/LineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public void It_Returns_A_Point_On_The_Line_At_A_Given_Length(double len)
var expectedPoint = line.StartPoint + line.Direction * len;

//Act
var pt = line.PointAtLength(len, false);
var pt = line.PointAtLength(len);

//Assert
pt.Equals(expectedPoint).Should().BeTrue();
Expand Down
77 changes: 29 additions & 48 deletions src/GShark.Test.XUnit/Geometry/PolylineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ public void It_Returns_A_Collection_Of_Lines()

[Theory]
[InlineData(0.0, new double[] { 5, 0, 0 })]
[InlineData(0.25, new double[] { 15, 15, 0 })]
[InlineData(0.66, new double[] { 26.4, 8.2, 0 })]
[InlineData(0.25, new double[] { 7.5, 3.75, 0 })]
[InlineData(2.5, new double[] { 25, 7.5, 0 })]
[InlineData(4.0, new double[] { 45, 12.5, 0 })]
public void It_Returns_A_Point_At_The_Given_Parameter(double t, double[] pt)
{
Expand Down Expand Up @@ -154,34 +154,44 @@ public void It_Returns_A_Parameter_Along_The_Polyline_At_The_Given_Point(double
}

[Theory]
[InlineData(0.0, new double[] { 0.5547, 0.83205, 0 })]
[InlineData(0.25, new double[] { 0.447214, -0.894427, 0 })]
[InlineData(0.66, new double[] { 0.894427, 0.447214, 0 })]
[InlineData(4.0, new double[] { 0.986394, 0.164399, 0 })]
public void It_Returns_A_Tangent_Vector_At_The_Given_Parameter(double t, double[] tangent)
[InlineData(0.693375, 12.5)]
[InlineData(0.931896, 16.8)]
[InlineData(2.330214, 32.9)]
[InlineData(3.415046, 46.7)]
public void It_Returns_The_Length_At_The_Given_Parameter(double t, double expectedLength)
{
// Act
double length = _polyline.LengthAt(t);

// Assert
length.Should().BeApproximately(expectedLength, GSharkMath.MaxTolerance);
}

[Fact]
public void It_Returns_The_Point_At_The_Given_Length()
{
// Arrange
Vector3 expectedTangent = new Vector3(tangent[0], tangent[1], tangent[2]);
Point3 expectedPt = new Point3(19.369239, 6.261522, 0);

// Act
Vector3 tanResult = _polyline.TangentAt(t);

Point3 pt = _polyline.PointAtNormalizedLength(0.5);
// Assert
tanResult.EpsilonEquals(expectedTangent, GSharkMath.MaxTolerance).Should().BeTrue();
(pt == expectedPt).Should().BeTrue();
}

[Theory]
[InlineData(0.0, 0)]
[InlineData(0.25, 1)]
[InlineData(0.66, 2)]
[InlineData(1, 3)]
public void It_Returns_A_Segment_At_The_Given_Index(double t, int expectedIndex)
[InlineData(12.5, 0.693375)]
[InlineData(16.8, 0.931896)]
[InlineData(32.9, 2.330214)]
[InlineData(46.7, 3.415046)]
public void It_Returns_The_Parameter_At_The_Given_Length(double length, double parameterExpected)
{
// Act
Line segment = _polyline.SegmentAt(t);
double parameter = _polyline.ParameterAtLength(length);

// Assert
segment.Should().Be(_polyline.Segments[expectedIndex]);
parameter.Should().BeApproximately(parameterExpected, GSharkMath.MaxTolerance);
}

[Fact]
Expand Down Expand Up @@ -273,18 +283,13 @@ public void It_Returns_A_Polyline_Transformed_In_NurbsCurve()
new Point3(18.154088, 12.309505, 7.561387)
};
Polyline poly = new Polyline(pts);
double lengthSum = 0.0;

// Act
var polyNurbs = poly.ToNurbs();

// Assert
polyNurbs.Degree.Should().Be(1);
for (int i = 0; i < poly.SegmentsCount; i++)
{
lengthSum += poly.Segments[i].Length;
pts[i + 1].EpsilonEquals(polyNurbs.PointAtLength(lengthSum), GSharkMath.MaxTolerance).Should().BeTrue();
}
polyNurbs.ControlPointLocations.Select((pt, i) => (pt == pts[i]).Should().BeTrue());
}

[Theory]
Expand Down Expand Up @@ -315,29 +320,5 @@ public void It_Returns_The_Segment_At_A_Given_Length(double length, int expected
//Assert
polyLine.Segments.IndexOf(segment).Should().Be(expectedIndex);
}

[Fact]
public void It_Returns_The_Tangent_At_A_Given_Length()
{
//Arrange
var polyLine = new Polyline(new List<Point3>
{
new (0, 0, 0),
new (5, 0, 0),
new (5, 10, 0),
new (0, 10, 0),
new (0, 0, 0)
});

var testLength = 6.66;
var tan = polyLine[2] - polyLine[1];
var expectedTangent = tan.Unitize();

//Act
var tangent = polyLine.TangentAtLength(testLength);

//Assert
tangent.Should().Be(expectedTangent);
}
}
}
39 changes: 18 additions & 21 deletions src/GShark/Geometry/Circle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,40 +200,38 @@ public Point3 PointAt(double t)
/// Evaluates a point at the specif length.
/// </summary>
/// <param name="length">The length where to evaluate the point.</param>
/// <param name="normalized">If false, the length is between 0.0 and length of the curve. If true, the length factor is normalized between 0.0 and 1.0.</param>
/// <returns>The point at the length.</returns>
public Point3 PointAtLength(double length, bool normalized = false)
public Point3 PointAtLength(double length)
{
if (length <= 0)
if (length <= 0.0)
{
return StartPoint;
}

if (normalized)
if (length >= Length)
{
if (length >= 1)
{
return EndPoint;
}
}
else
{
if (length > Length)
{
return EndPoint;
}
return EndPoint;
}

double theta = (normalized)
? _domain.T0 + (_domain.T1 - _domain.T0) * length
: GSharkMath.ToRadians((length * 360) / (Math.PI * 2 * Radius));
double theta = GSharkMath.ToRadians((length * 360) / (Math.PI * 2 * Radius));

Vector3 xDir = Plane.XAxis * Math.Cos(theta) * Radius;
Vector3 yDir = Plane.YAxis * Math.Sin(theta) * Radius;

return Plane.Origin + xDir + yDir;
}

/// <summary>
/// Evaluates a point at the normalized length.
/// </summary>
/// <param name="normalizedLength">The length factor is normalized between 0.0 and 1.0.</param>
/// <returns>The point at the length.</returns>
public Point3 PointAtNormalizedLength(double normalizedLength)
{
double theta = _domain.T0 + (_domain.T1 - _domain.T0) * normalizedLength;
return PointAt(theta);
}

/// <summary>
/// Calculates the tangent at the parameter on the circular curve.
/// </summary>
Expand All @@ -259,11 +257,10 @@ public Vector3 TangentAt(double t)
/// Evaluates the tangent at the specific length.
/// </summary>
/// <param name="length">The length where to evaluate the tangent.</param>
/// <param name="normalized">If false, the length is between 0.0 and length of the curve. If true, the length factor is normalized between 0.0 and 1.0.</param>
/// <returns>The unitize tangent at the length.</returns>
public Vector3 TangentAtLength(double length, bool normalized = false)
public Vector3 TangentAtLength(double length)
{
Point3 pt = PointAtLength(length, normalized);
Point3 pt = PointAtLength(length);
(double u, double v) = Plane.ClosestParameters(pt);
double t = EvaluateParameter(u, v, false);
return DerivativeAt(t, 1).Unitize();
Expand Down
13 changes: 4 additions & 9 deletions src/GShark/Geometry/Line.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using GShark.Core;
using GShark.Interfaces;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using GShark.Interfaces;

namespace GShark.Geometry
{
Expand Down Expand Up @@ -132,12 +131,12 @@ public double ClosestParameter(Point3 pt)
/// <returns>The point at the specific parameter.</returns>
public Point3 PointAt(double t)
{
if (t <= 0)
if (t <= 0.0)
{
return StartPoint;
}

if (t >= 1)
if (t >= 1.0)
{
return EndPoint;
}
Expand All @@ -150,17 +149,13 @@ public Point3 PointAt(double t)
/// </summary>
/// <param name="length">Length, between 0.0 and the length of the curve.</param>
/// <returns>The point at the given length.</returns>
public Point3 PointAtLength(double length, bool normalized = true)
public Point3 PointAtLength(double length)
{
if (length <= 0)
{
return StartPoint;
}

length = (normalized)
? GSharkMath.RemapValue(length, new Interval(0.0, 1.0), new Interval(0.0, Length))
: length;

if (length >= Length)
{
return EndPoint;
Expand Down
Loading

0 comments on commit 5869281

Please # to comment.