Wrong tangent at the end of the curve

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.

I took a look at the source code:

 	// 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.

I will now call the method as

customGetTangent( t, optionalTarget, delta ) {

// const delta = 0.0001;


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.

But here it is really strange.

I have added some tests and console.log but cannot locate the problem.

There you can find the test example.

Basically it is Triangulation cylinder with holes

Added deformation similar to DynamicTubeGeometryCaps.

For this lines 1148 to 1156
If you comment out triangGeo.morph( points ); you get the original triangulation.

In the class deformableCylinderWithHoles extends THREE.BufferGeometry { ... only some things were added to the original, also some console.log.

Lines 50 to 64

Lines 201 to 265 g.morph = function ( points ) { ...

Lines 267 to 290 function getTangent( t, optionalTarget, delta ) { ... instead of the original.


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.

1 Like