In this example DynamicTubeGeometryCaps I had a problem with the tangent some time ago. I solved it there by doing my own calculation. (lines 228 - 244).

I now have a project where this method doesn’t work so I use .getTangent( t, optionalTarget ).

This works in many cases, but for some parameter combinations it gives an incorrect tangent at the end of the curve.

// Returns a unit vector tangent at t
// In case any sub curve does not implement its tangent derivation,
// 2 points a small delta apart will be used to find its gradient
// which seems to give a reasonable approximation
getTangent( t, optionalTarget ) {
const delta = 0.0001;
let t1 = t - delta;
let t2 = t + delta;
// Capping in case of danger
if ( t1 < 0 ) t1 = 0;
if ( t2 > 1 ) t2 = 1;
const pt1 = this.getPoint( t1 );
const pt2 = this.getPoint( t2 );
const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
tangent.copy( pt2 ).sub( pt1 ).normalize();
return tangent;
}

A fixed value for delta is used. This seems to be the problem. If I set const delta = 0.01; in some of my cases it works. With smaller values the error occurs. But I could not discover a general systematic.

in my code. Then I check if the last tangent deviates strongly and recalculate it with larger delta until it is correct.

Would it be appropriate to have delta as a parameter in general in the method or is there something against it? Is there a better variant to avoid the error?

This is strange. Smaller deltas are supposed to give better approximation of tangents. The only problem could be lost of precision, but this will happen with extremely small deltas (0.0001 is far away from danger).

In theory, I think so too. That’s why I was a bit surprised about the solution (sham solution?).
With my frequent scatterbrains sometimes nice things come out, e.g. if one forgets to make a bracket around the difference in the numerator of the fraction.

Could you make a simpler example with pure TubeGeometry (i.e. without all the custom modifications like holes, etc).

In the past I had a problem with the end points of some spline curves, and I found it was due to some strange code in Three.js – it was something like “if this vector is too short, assume it is (0,1,0)”. I tried to find this code, but failed. It is either fixed, or my memory is malfunctioning. If I debug a shorter example I might be able to recover my memories. Maybe just a code fragment with how you define the curve and the tube would be sufficient to start with.