Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Circle inheritance NurbsBase #360

Merged
merged 2 commits into from
Sep 11, 2021
Merged
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
4 changes: 2 additions & 2 deletions src/GShark.Test.XUnit/Geometry/ArcTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public void It_Is_A_Curve_Representation_Of_The_Arc_From_0_To_90_Deg()
};

// Act
NurbsBase arc = new Arc(Plane.PlaneYZ, 20, new Interval(0.0, 1.8)).ToNurbs();
NurbsBase arc = new Arc(Plane.PlaneYZ, 20, new Interval(0.0, 1.8));

// Assert
arc.ControlPointLocations.Count.Should().Be(5);
Expand Down Expand Up @@ -162,7 +162,7 @@ public void It_Is_A_Curve_Representation_Of_ExampleArc3D()
};

// Act
NurbsBase arc = _exampleArc3D.ToNurbs();
NurbsBase arc = _exampleArc3D;

// Assert
arc.ControlPointLocations.Count.Should().Be(7);
Expand Down
2 changes: 1 addition & 1 deletion src/GShark.Test.XUnit/Geometry/CircleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void It_Returns_A_Circle3D_With_Its_Nurbs_Representation()
};

// Act
NurbsBase circleNurbs = _circle3D.ToNurbs();
NurbsBase circleNurbs = _circle3D;

// Assert
circleNurbs.Knots.GetDomain(circleNurbs.Degree).Length.Should().Be(1.0);
Expand Down
4 changes: 2 additions & 2 deletions src/GShark.Test.XUnit/Geometry/NurbsCurveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public void Returns_A_Curve_Joining_Different_Types_Of_Curves()
NurbsCurve curve = new NurbsCurve(pts, degree);
Line ln = new Line(new Point3(5, 5, 0), new Point3(5, 5, -2.5));
Arc arc = Arc.ByStartEndDirection(new Point3(5, 5, -2.5), new Point3(10, 5, -5), new Vector3(0, 0, -1));
NurbsBase[] curves = { ln, arc.ToNurbs(), curve };
NurbsBase[] curves = { ln, arc, curve };

Point3 expectedPt1 = new Point3(5, 3.042501, 4.519036);
Point3 expectedPt2 = new Point3(5, 5, -1.230175);
Expand Down Expand Up @@ -407,7 +407,7 @@ public void Returns_A_Curve_Joining_Polylines_And_Arc()
});

Arc arc = Arc.ByStartEndDirection(new Point3(5, 5, -2.5), new Point3(10, 5, -5), new Vector3(0, 0, -1));
NurbsBase[] curves = { poly, arc.ToNurbs() };
NurbsBase[] curves = { poly, arc };

Point3 expectedPt1 = new Point3(5, 0, 2.928932);
Point3 expectedPt2 = new Point3(5, 4.428932, 5);
Expand Down
2 changes: 2 additions & 0 deletions src/GShark/Geometry/Arc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public Arc(Plane plane, double radius, Interval angleDomainRadians) : base(plane
AngularDiff(angleDomainRadians.T1, Math.PI * 2.0))
: angleDomainRadians;
_length = Math.Abs(Angle * Radius);
ToNurbs();
}

/// <summary>
Expand Down Expand Up @@ -64,6 +65,7 @@ public Arc(Point3 pt1, Point3 pt2, Point3 pt3) : base(pt1, pt2, pt3)

_domain = new Interval(0.0, angle);
_length = Math.Abs(Angle * Radius);
ToNurbs();
}

/// <summary>
Expand Down
55 changes: 39 additions & 16 deletions src/GShark/Geometry/Circle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using GShark.Interfaces;
using GShark.Intersection;
using System;
using System.ComponentModel;
using System.Linq;

namespace GShark.Geometry
Expand All @@ -13,7 +14,7 @@ namespace GShark.Geometry
/// <example>
/// [!code-csharp[Example](../../src/GShark.Test.XUnit/Geometry/CircleTests.cs?name=example)]
/// </example>
public class Circle : ICurve, IEquatable<Circle>, ITransformable<Circle>
public class Circle : NurbsBase, IEquatable<Circle>, ITransformable<Circle>
{
internal Interval _domain = new Interval(0.0, 2.0 * Math.PI);
internal double _length;
Expand All @@ -28,6 +29,7 @@ public Circle(Plane plane, double radius)
Plane = plane;
Radius = Math.Abs(radius);
_length = Math.Abs(2.0 * Math.PI * radius);
ToNurbs();
}

/// <summary>
Expand Down Expand Up @@ -69,6 +71,7 @@ public Circle(Point3 pt1, Point3 pt2, Point3 pt3)
Plane = new Plane(center, xDir, yDir);
Radius = xDir.Length;
_length = Math.Abs(2.0 * Math.PI * Radius);
ToNurbs();
}

/// <summary>
Expand All @@ -94,27 +97,27 @@ public Circle(Point3 pt1, Point3 pt2, Point3 pt3)
/// <summary>
/// Gets the circumference of the circular curve.
/// </summary>
public double Length => _length;
public override double Length => _length;

/// <summary>
/// Gets the start point of the circular curve.
/// </summary>
public Point3 StartPoint => PointAt(0.0);
public override Point3 StartPoint => PointAt(0.0);

/// <summary>
/// Gets the mid-point of the circular curve.
/// </summary>
public Point3 MidPoint => PointAt(_domain.Mid);
public override Point3 MidPoint => PointAt(_domain.Mid);

/// <summary>
/// Gets the end point of the circular curve.
/// </summary>
public Point3 EndPoint => PointAt(_domain.T1);
public override Point3 EndPoint => PointAt(_domain.T1);

/// <summary>
/// Gets the bounding box of this circular curve.
/// </summary>
public virtual BoundingBox GetBoundingBox()
public override BoundingBox GetBoundingBox()
{
double val1 = Radius * SelectionLength(Plane.ZAxis[1], Plane.ZAxis[2]);
double val2 = Radius * SelectionLength(Plane.ZAxis[2], Plane.ZAxis[0]);
Expand All @@ -138,7 +141,7 @@ public virtual BoundingBox GetBoundingBox()
/// <param name="t">Parameter to evaluate derivative. A parameter between 0.0 and angle domain in radians.</param>
/// <param name="derivative">Which order of derivative is wanted. Valid values are 0,1,2,3.</param>
/// <returns>The derivative of the circle at the given parameter.</returns>
public Vector3 DerivativeAt(double t, int derivative = 0)
public new Vector3 DerivativeAt(double t, int derivative = 0)
{
if (t < 0.0)
{
Expand Down Expand Up @@ -180,7 +183,7 @@ public Vector3 DerivativeAt(double t, int derivative = 0)
/// </summary>
/// <param name="t">A parameter between 0.0 and angle domain in radians.></param>
/// <returns>Point on the circular curve.</returns>
public Point3 PointAt(double t)
public override Point3 PointAt(double t)
{
if (t < 0.0)
{
Expand All @@ -200,7 +203,7 @@ public Point3 PointAt(double t)
/// </summary>
/// <param name="length">The length where to evaluate the point.</param>
/// <returns>The point at the length.</returns>
public Point3 PointAtLength(double length)
public override Point3 PointAtLength(double length)
{
if (length <= 0.0)
{
Expand All @@ -225,7 +228,7 @@ public Point3 PointAtLength(double 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)
public override Point3 PointAtNormalizedLength(double normalizedLength)
{
double theta = _domain.T0 + (_domain.T1 - _domain.T0) * normalizedLength;
return PointAt(theta);
Expand All @@ -236,7 +239,7 @@ public Point3 PointAtNormalizedLength(double normalizedLength)
/// </summary>
/// <param name="t">A parameter between 0.0 and angle domain in radians.</param>
/// <returns>Unitized tangent vector at the parameter.</returns>
public Vector3 TangentAt(double t)
public override Vector3 TangentAt(double t)
{
if (t <= 0.0)
{
Expand Down Expand Up @@ -270,7 +273,7 @@ public Vector3 TangentAtLength(double length)
/// </summary>
/// <param name="t">A parameter between 0.0 and angle domain in radians.</param>
/// <returns>The curve length at t.</returns>
public double LengthAt(double t)
public override double LengthAt(double t)
{
if (t <= 0)
{
Expand All @@ -290,7 +293,7 @@ public double LengthAt(double t)
/// </summary>
/// <param name="pt">The test point to project onto the circular curve.</param>
/// <returns>The point on the circular curve that is close to the test point.</returns>
public Point3 ClosestPoint(Point3 pt)
public override Point3 ClosestPoint(Point3 pt)
{
(double u, double v) = Plane.ClosestParameters(pt);
if (Math.Abs(u) < GSharkMath.MinTolerance && Math.Abs(v) < GSharkMath.MinTolerance)
Expand All @@ -308,7 +311,7 @@ public Point3 ClosestPoint(Point3 pt)
/// </summary>
/// <param name="pt">The test point to project onto the circular curve.</param>
/// <returns>The parameter on the circular curve that is close to the test point.</returns>
public double ClosestParameter(Point3 pt)
public override double ClosestParameter(Point3 pt)
{
(double u, double v) = Plane.ClosestParameters(pt);
if (Math.Abs(u) < GSharkMath.MinTolerance && Math.Abs(v) < GSharkMath.MinTolerance)
Expand Down Expand Up @@ -339,35 +342,45 @@ public Circle Offset(double distance)
/// <em>Implementation of Algorithm A7.1 from The NURBS Book by Piegl and Tiller.</em>
/// </summary>
/// <returns>A nurbs curve shaped like this arc.</returns>
public NurbsCurve ToNurbs()
internal void ToNurbs()
{
Vector3 axisX = Plane.XAxis;
Vector3 axisY = Plane.YAxis;
double curveAngle = _domain.Length;
int numberOfArc;
Point3[] pts;
Point4[] ctrPts;
double[] weights;

// Number of arcs.
double piNum = 0.5 * Math.PI;
if ((curveAngle - piNum) <= GSharkMath.Epsilon)
{
numberOfArc = 1;
pts = new Point3[3];
ctrPts = new Point4[3];
weights = new double[3];
}
else if ((curveAngle - piNum * 2) <= GSharkMath.Epsilon)
{
numberOfArc = 2;
pts = new Point3[5];
ctrPts = new Point4[5];
weights = new double[5];
}
else if ((curveAngle - piNum * 3) <= GSharkMath.Epsilon)
{
numberOfArc = 3;
pts = new Point3[7];
ctrPts = new Point4[7];
weights = new double[7];
}
else
{
numberOfArc = 4;
pts = new Point3[9];
ctrPts = new Point4[9];
weights = new double[9];
}

double detTheta = curveAngle / numberOfArc;
Expand All @@ -379,14 +392,18 @@ public NurbsCurve ToNurbs()
int index = 0;
double angle = _domain.T0;

pts[0] = p0;
ctrPts[0] = new Point4(p0);
weights[0] = weight;

for (int i = 1; i < numberOfArc + 1; i++)
{
angle += detTheta;
Point3 p2 = Center + (axisX * (Radius * Math.Cos(angle)) + axisY * (Radius * Math.Sin(angle)));

ctrPts[index + 2] = new Point4(p2);
pts[index + 2] = p2;
weights[index + 2] = 1.0;

Vector3 t2 = (axisY * Math.Cos(angle)) - (axisX * Math.Sin(angle));
Line ln0 = new Line(p0, t0.Unitize() + p0);
Expand All @@ -395,6 +412,8 @@ public NurbsCurve ToNurbs()
Point3 p1 = p0 + (t0 * u0);

ctrPts[index + 1] = new Point4(p1, weight);
pts[index + 1] = p1;
weights[index + 1] = weight;
index += 2;

if (i >= numberOfArc)
Expand Down Expand Up @@ -429,7 +448,11 @@ public NurbsCurve ToNurbs()
break;
}

return new NurbsCurve(2, knots, ctrPts.ToList());
Weights = weights.ToList();
Degree = 2;
Knots = knots;
ControlPoints = ctrPts.ToList();
ControlPointLocations = pts.ToList();
}

/// <summary>
Expand Down
5 changes: 2 additions & 3 deletions src/GShark/Geometry/NurbsBase.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#nullable enable
using GShark.Core;
using GShark.ExtendedMethods;
using GShark.Interfaces;
using GShark.Operation.Utilities;
using System;
using System.Collections.Generic;
Expand All @@ -14,7 +13,7 @@ namespace GShark.Geometry
/// <summary>
/// This class represents a base class that is common to most curve types.
/// </summary>
public abstract class NurbsBase : ICurve, IEquatable<NurbsBase>
public abstract class NurbsBase : IEquatable<NurbsBase>
{
protected NurbsBase()
{
Expand Down Expand Up @@ -215,7 +214,7 @@ public virtual Point3 PointAtNormalizedLength(double normalizedLength)
/// </summary>
/// <param name="t">The parameter to sample the curve. Parameter should be between 0.0 and 1.0.</param>
/// <returns>The unitized tangent vector at the given parameter.</returns>
public Vector3 TangentAt(double t)
public virtual Vector3 TangentAt(double t)
{
if (t <= 0.0)
{
Expand Down
Loading