Skip to content

Commit

Permalink
Merge pull request #371 from GSharker/dev/mibi/extrude-sweep-surface
Browse files Browse the repository at this point in the history
Extrude and Sweep surface
  • Loading branch information
sonomirco committed Oct 6, 2021
2 parents 96c232a + 772a740 commit 0616db2
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/GShark.Test.XUnit/Data/NurbsSurfaceCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public static NurbsSurface Loft()
NurbsCurve crv2 = new NurbsCurve(pts3, 3);
List<NurbsBase> crvs = new List<NurbsBase> { ln, crv0, poly, crv1, crv2 };

return NurbsSurface.Lofted(crvs);
return NurbsSurface.FromLoft(crvs);
}
}
}
Binary file modified src/GShark.Test.XUnit/DebugFiles/GHDebug_Surface.gh
Binary file not shown.
86 changes: 75 additions & 11 deletions src/GShark.Test.XUnit/Geometry/NurbsSurfaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void It_Returns_A_Normal_Lofted_Surface_By_Opened_Curves(double u, double
Point3 expectedPt = new Point3(pt[0], pt[1], pt[2]);

// Act
NurbsSurface surface = NurbsSurface.Lofted(NurbsCurveCollection.OpenCurves());
NurbsSurface surface = NurbsSurface.FromLoft(NurbsCurveCollection.OpenCurves());
Point3 evalPt = surface.PointAt(u, v);

// Assert
Expand All @@ -106,7 +106,7 @@ public void It_Returns_A_Loose_Lofted_Surface_By_Opened_Curves(double u, double
Point3 expectedPt = new Point3(pt[0], pt[1], pt[2]);

// Act
NurbsSurface surface = NurbsSurface.Lofted(NurbsCurveCollection.OpenCurves(), LoftType.Loose);
NurbsSurface surface = NurbsSurface.FromLoft(NurbsCurveCollection.OpenCurves(), LoftType.Loose);
Point3 evalPt = surface.PointAt(u, v);

// Assert
Expand All @@ -124,7 +124,7 @@ public void It_Returns_A_Loose_Lofted_Surface_By_Closed_Curves(double u, double
Point3 expectedPt = new Point3(pt[0], pt[1], pt[2]);

// Act
NurbsSurface surface = NurbsSurface.Lofted(NurbsCurveCollection.ClosedCurves(), LoftType.Loose);
NurbsSurface surface = NurbsSurface.FromLoft(NurbsCurveCollection.ClosedCurves(), LoftType.Loose);
Point3 evalPt = surface.PointAt(u, v);

// Assert
Expand All @@ -136,7 +136,7 @@ public void It_Returns_A_Loose_Lofted_Surface_By_Closed_Curves(double u, double
public void Lofted_Surface_Throws_An_Exception_If_The_Curves_Are_Null()
{
// Act
Func<NurbsSurface> func = () => NurbsSurface.Lofted(null);
Func<NurbsSurface> func = () => NurbsSurface.FromLoft(null);

// Assert
func.Should().Throw<Exception>()
Expand All @@ -151,7 +151,7 @@ public void Lofted_Surface_Throws_An_Exception_If_There_Are_Null_Curves()
crvs.Add(null);

// Act
Func<NurbsSurface> func = () => NurbsSurface.Lofted(crvs);
Func<NurbsSurface> func = () => NurbsSurface.FromLoft(crvs);

// Assert
func.Should().Throw<Exception>()
Expand All @@ -165,7 +165,7 @@ public void Lofted_Surface_Throws_An_Exception_If_Curves_Count_Are_Less_Than_Two
NurbsBase[] crvs = { NurbsCurveCollection.OpenCurves()[0] };

// Act
Func<NurbsSurface> func = () => NurbsSurface.Lofted(crvs);
Func<NurbsSurface> func = () => NurbsSurface.FromLoft(crvs);

// Assert
func.Should().Throw<Exception>()
Expand All @@ -180,7 +180,7 @@ public void Lofted_Surface_Throws_An_Exception_If_The_All_Curves_Are_Not_Closed_
crvs[1] = crvs[1].Close();

// Act
Func<NurbsSurface> func = () => NurbsSurface.Lofted(crvs);
Func<NurbsSurface> func = () => NurbsSurface.FromLoft(crvs);

// Assert
func.Should().Throw<Exception>()
Expand Down Expand Up @@ -221,7 +221,7 @@ public void Returns_True_If_Two_Surfaces_Are_Equals()
public void Returns_True_If_Surface_Is_Close()
{
// Act
NurbsSurface surface = NurbsSurface.Lofted(NurbsCurveCollection.ClosedCurves(), LoftType.Loose);
NurbsSurface surface = NurbsSurface.FromLoft(NurbsCurveCollection.ClosedCurves(), LoftType.Loose);

// Assert
surface.IsClosed(SurfaceDirection.V).Should().BeTrue();
Expand Down Expand Up @@ -381,12 +381,12 @@ public void It_Returns_A_Revolved_Surface_From_A_Line()

// Assert
revolvedSurface0.ControlPointLocations
.Zip(expectedPts0, (pt0, pt1) => pt0.SequenceEqual(pt1))
.Zip(expectedPts0, (ptsA, ptsB) => ptsA.SequenceEqual(ptsB))
.All(res => res)
.Should().BeTrue();

revolvedSurface1.ControlPointLocations
.Zip(expectedPts1, (pt0, pt1) => pt0.SequenceEqual(pt1))
.Zip(expectedPts1, (ptsA, ptsB) => ptsA.SequenceEqual(ptsB))
.All(res => res)
.Should().BeTrue();
}
Expand Down Expand Up @@ -425,9 +425,73 @@ public void It_Returns_A_Revolved_Surface_From_An_Arc()

// Assert
revolvedSurface.ControlPointLocations
.Zip(expectedPts, (pt0, pt1) => pt0.SequenceEqual(pt1))
.Zip(expectedPts, (ptsA, ptsB) => ptsA.SequenceEqual(ptsB))
.All(res => res)
.Should().BeTrue();
}

[Fact]
public void It_Creates_A_NurbsSurface_From_Extrusion()
{
// Arrange
List<Point3> ptsA = new List<Point3>
{
new Point3(0, 0, 0),
new Point3(0, 0, 5),
new Point3(5, 0, 5),
new Point3(5, 0, 0),
new Point3(10, 0, 0)
};
List<Point3> ptsB = new List<Point3>
{
new Point3(0, 10, 0),
new Point3(0, 10, 5),
new Point3(5, 10, 5),
new Point3(5, 10, 0),
new Point3(10, 10, 0)
};
NurbsCurve curve = new NurbsCurve(ptsA, 3);
Vector3 direction = Vector3.YAxis * 10;
List<List<Point3>> expectedPts = new List<List<Point3>> {ptsA, ptsB};

// Act
NurbsSurface extrudedSurface = NurbsSurface.FromExtrusion(direction, curve);

// Assert
extrudedSurface.ControlPointLocations
.Zip(expectedPts, (ptsA, ptsB) => ptsA.SequenceEqual(ptsB))
.All(res => res)
.Should().BeTrue();
extrudedSurface.DegreeU.Should().Be(1);
extrudedSurface.DegreeV.Should().Be(curve.Degree);
}

[Fact]
public void It_Creates_A_NurbsSurface_From_Swep()
{
// Arrange
List<Point3> ptsA = new List<Point3>
{
new Point3(5, 0, 0),
new Point3(5, 5, 0),
new Point3(0, 5, 0),
new Point3(0, 5, 5),
new Point3(5, 5, 5)
};
List<Point3> ptsB = new List<Point3>
{
new Point3(4, 0, 1),
new Point3(5, 0, 0),
new Point3(6, 0, 1)
};
NurbsCurve rail = new NurbsCurve(ptsA, 3);
NurbsCurve profile = new NurbsCurve(ptsB, 2);

// Act
NurbsSurface sweepSurface = NurbsSurface.FromSweep(rail, profile);

// Assert
(sweepSurface.ControlPointLocations.Last()[1] == ptsA.Last()).Should().BeTrue();
}
}
}
52 changes: 45 additions & 7 deletions src/GShark/Geometry/NurbsSurface.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using GShark.Core;
using GShark.Enumerations;
using GShark.ExtendedMethods;
using GShark.Interfaces;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GShark.Core;
using GShark.Enumerations;
using GShark.ExtendedMethods;
using GShark.Interfaces;

namespace GShark.Geometry
{
Expand Down Expand Up @@ -154,7 +154,7 @@ public static NurbsSurface FromPoints(int degreeU, int degreeV, List<List<Point3
/// <param name="curves">Set of a minimum of two curves to create the surface.</param>
/// <param name="loftType">Enum to choose the type of loft generation.</param>
/// <returns>A NURBS surface.</returns>
public static NurbsSurface Lofted(IList<NurbsBase> curves, LoftType loftType = LoftType.Normal)
public static NurbsSurface FromLoft(IList<NurbsBase> curves, LoftType loftType = LoftType.Normal)
{
if (curves == null)
throw new ArgumentException("An invalid number of curves to perform the loft.");
Expand Down Expand Up @@ -218,6 +218,44 @@ public static NurbsSurface Lofted(IList<NurbsBase> curves, LoftType loftType = L
return new NurbsSurface(degreeU, degreeV, knotVectorU, knotVectorV, surfaceControlPoints);
}

/// <summary>
/// Constructs a surface extruding a curve profile long a direction.
/// </summary>
/// <param name="direction">The extrusion direction.</param>
/// <param name="profile">The profile curve to extrude.</param>
/// <returns>The extruded surface.</returns>
public static NurbsSurface FromExtrusion(Vector3 direction, NurbsBase profile)
{
Transform xForm = Core.Transform.Translation(direction);
List<Point4> translatedControlPts =
profile.ControlPoints.Select(controlPoint => controlPoint.Transform(xForm)).ToList();

return new NurbsSurface(1, profile.Degree, new KnotVector { 0, 0, 1, 1 }, profile.Knots,
new List<List<Point4>> { profile.ControlPoints, translatedControlPts });
}

/// <summary>
/// Constructs a sweep surface with one rail curve.
/// <em>Follows the algorithm A10.2 at page 477 of The NURBS Book by Piegl and Tiller.</em>
/// </summary>
/// <param name="rail">The rail curve.</param>
/// <param name="profile">The section curve.</param>
/// <returns>The sweep surface.</returns>
public static NurbsSurface FromSweep(NurbsBase rail, NurbsBase profile)
{
var (tValues, _) = Sampling.Curve.AdaptiveSample(rail, GSharkMath.MaxTolerance);
List<Plane> frames = rail.PerpendicularFrames(tValues);
List<NurbsBase> curves = new List<NurbsBase> {profile};

for (int i = 1; i <= frames.Count; i++)
{
Transform xForm = Core.Transform.PlaneToPlane(frames[0], frames[i]);
curves.Add(((NurbsCurve)curves[0]).Transform(xForm));
}

return FromLoft(curves);
}

/// <summary>
/// Constructs a ruled surface between two curves.
/// <em>Follows the algorithm at page 337 of The NURBS Book by Piegl and Tiller.</em>
Expand Down Expand Up @@ -356,7 +394,7 @@ public static NurbsSurface Revolved(NurbsBase curveProfile, Ray axis, double rot
}

}

return new NurbsSurface(2, curveProfile.Degree, knotsU, curveProfile.Knots, controlPts.Select(pts => pts.ToList()).ToList());
}

Expand Down
1 change: 0 additions & 1 deletion src/GShark/Sampling/Curve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Linq;
using GShark.Core;
using GShark.Geometry;
using GShark.Operation;

namespace GShark.Sampling
{
Expand Down

0 comments on commit 0616db2

Please sign in to comment.