Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,11 @@ private static List<Sample> samples(BezierSegment segment, double fineness) {
List<Sample> samples = new ArrayList<>();
Vector3 before = segment.p0();
double distance = 0;
for (double t = 0; t <= 1; t += 1.0 / fineness) {
// At 0 a handle can be at the point itself, where the curve has no direction yet
double at = t == 0 ? 0.00001 : t;
Vector3 point = segment.point(at);
for (int step = 0; step <= fineness; step++) {
double t = step / fineness;
Vector3 point = segment.point(t);
distance += before.distance(point);
samples.add(new Sample(point, across(segment.direction(at)), distance));
samples.add(new Sample(point, across(segment.tangent(t)), distance));
before = point;
}
return samples;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,25 @@ public Vector3 direction(double t) {
.add(step2.multiply(quadratic2));
}

/**
* The direction that the curve goes at {@code t}, like {@link #direction}, but also where that is zero, as at an
* end whose handle is at its point. There the curve leaves {@code p0} towards {@code p2}, or arrives at {@code p3}
* from {@code p1}, as {@link #direction} does just beside it; when that is zero too, from {@code p0} to
* {@code p3}.
*
* @param t where on the segment, from 0 to 1
* @return the direction, not scaled to any length; zero when none of these tells it, as when all four positions
* are at one place
*/
public Vector3 tangent(double t) {
Vector3 direction = direction(t);
if (direction.lengthSq() != 0) return direction;

Vector3 besideTheEnd = t < 0.5 ? p2.subtract(p0) : p3.subtract(p1);
if (besideTheEnd.lengthSq() != 0) return besideTheEnd;
return p3.subtract(p0);
}

/**
* The length of the curve, measured along {@code fineness} straight steps.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,19 @@ void crossSectionIsLaidAcrossTheCurve() throws Exception {
assertEquals(5 * 9, blocks.size());
}

@Test
void crossSectionIsAcrossTheCurveAtItsEnd() throws Exception {
// With one step per block, the last step is at the end, where the segment has no handle
CurveLayout.Selection selection = new CurveLayout.Selection(1, 1, 3, Vector3.at(0, 0, 1));
BezierSegment line = straight(Vector3.at(0, 64, 0), Vector3.at(4, 64, 0));
CurveLayout layout = new CurveLayout(selection, NO_ARGUMENTS, NEVER_AIR, 0, 10000, 1);
layout.add(line);
NavigableMap<BlockVector3, BlockVector3> blocks = layout.blocks();

assertEquals(Set.of(0, 1, 2, 3, 4), xs(blocks));
assertEquals(5 * 3, blocks.size());
}

@Test
void crossSectionTurnsWithTheCurve() throws Exception {
CurveLayout.Selection selection = new CurveLayout.Selection(1, 3, 3, Vector3.at(0, 1, 1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,36 @@ void endWithoutHandleHasNoDirection() {
}
}

@Nested
class Tangent {
@Test
void isTheDirectionWhereThereIsOne() {
assertVector(5, 0, 0, ARCH.tangent(0.5));
assertVector(0, 10, 0, ARCH.tangent(0));
}

@Test
void straightSegmentGoesFromEndToEndAtItsEnds() {
BezierSegment segment = straight(Vector3.at(0, 64, 0), Vector3.at(10, 64, 0));
assertVector(10, 0, 0, segment.tangent(0));
assertVector(10, 0, 0, segment.tangent(1));
}

@Test
void endWithoutHandleGoesTowardsTheOtherHandle() {
Vector3 start = Vector3.at(0, 64, 0);
BezierSegment segment = new BezierSegment(start, start, Vector3.at(0, 64, 10), Vector3.at(10, 64, 10));
assertVector(0, 0, 10, segment.tangent(0));
assertVector(10, 0, 0, segment.tangent(1));
}

@Test
void segmentAtOnePlaceHasNoDirection() {
Vector3 a = Vector3.at(3, 64, 3);
assertVector(0, 0, 0, new BezierSegment(a, a, a, a).tangent(0));
}
}

@Nested
class Length {
@ParameterizedTest
Expand Down
Loading