Inaccurate adjustment when cylinder is deformed

In one project, I connect a main cylinder with holes ( Triangulation cylinder with holes ) which is then still deformed, with attached cylinders.

This seemed to work as I had thought it would. However, when I tested a little more bending, it turned out that the connected cylinders did not always match the holes. A slightly different distance is no problem, because the cylinders are connected with a special geometry.


Since the program is very complex, I created a test program 01_TubeGeometry with tubes without holes. The angular position and height can be easily read from the texture.

I tried some other approaches. The result was always different but not correct, sometimes there was only a “triangle chaos”.

The problem is somehow related to the torsion during bending. I had originally assumed to have success with the code line for the binormal b. But that works only conditionally.

b.x = 0; // to prevent torsion ? - but not in all cases!

// --- inputs ---

const apdH = 0.85;  // relative appending height of the tube 0 .. 1
const apdAngle = -90; // use ° for appending angle
const mainR = 0.11;

But e.g. apdH = 0.3 looks good.

Does anyone have an idea what could be the cause :thinking: or what else I could try?

Hm. It might happen because of denormalized vectors. Try adding normalization of normal before quaternion rotation:

const normal = new THREE.Vector3( ).crossVectors( binormal, tangent );
binormal.crossVectors( normal, tangent );
binormal.normalize( );
normal.normalize(); // add this line

const quaternion = new THREE.Quaternion( );
quaternion.setFromBasis( tangent, binormal, normal );
geoTube.applyQuaternion( quaternion );

Thanks, that solves part of the problem.

Obviously a precision problem again? Amazing that this has not happened to me so far with my partly complex calculations in my addons (hofk (Klaus Hoffmeister) · GitHub ). I had no problems with that so far.

However, the problem of twisting the angular position remains. I cannot get the torsion under control.

This example 02_TubeGeometry illustrates it:

In my original project there is then this ( clearly colored ) distorted connection to the attached tubes.

There is some math1 involved in removing unwanted twist. It might not be a matter of just a few lines:

1 I did not read the paper, I only looked at the images and they look somewhat relevant. I have also suffered from twist in the past, but had never had enough time to fight back.

Thank you for the link. When I find some time, I will study that.

After looking at the picture of my example in the previous post, I had the idea to align the binormals (blue) according to the attached cylinders. In my original project there is no texture and it is only important that holes fit as exactly as possible to the attached cylinders.

I will try this first before I devote myself to mathematical reading.

1 Like

The matter is truly complicated. The formula

const ang = apdAngle / 180 * Math.PI; // angle in rad
const binormal = new THREE.Vector3( -Math.sin( ang ), 0, -Math.cos( ang ) );

leads to different angles in the representation in the upper area of the main tube for the same angle differences.

for ( let up = 0; up <= tubeHeight; up += 0.2 ) {    // up from bottom
    for ( let apdAngle = 0; apdAngle < 360; apdAngle += 5 ) {  //  use ° for appending angle  
        appendTube( up, apdAngle );       


The reason is obviously that the calculation is done with respect to the xz plane ( y = 0 ).

I will try to move the calculation to the respective section plane. Possibly this is helpful.

I have now solved the problem in such a way that I put up with the twisting, since I don’t need a texture.

For this I determine the center and the orientation of the hole in each case and attach the cylinders.

It turned out that now the attached cylinders were not systematically recognizably twisted around their own axis.

As a solution I realized a subsequent twisting. After determining the necessary rotation angle,

this is quite simple with

    geo[ i ].translate( -pc.x, -pc.y, -pc.z );
    geo[ i ].applyMatrix4( new THREE.Matrix4( ).makeRotationAxis( vdir, -phiMin ) );
    geo[ i ].translate( pc.x, pc.y, pc.z );

where pc is ther center point (origin of the blue arrows) and vdir is the black direction vector.


Beautiful … cactus.

  • Do you plan to make is available as a library?
  • Does it support a case when two tubes are connected to very close locations of the master tube?

It is part of a non-open source project.

Since it is based on Triangulation cylinder with holes, the holes must have a minimum spacing for triangulation to work. Usually at least an rough triangle side length d.

In addition, I made the hole slightly larger than the appendage to achieve a gentle curve with the connection geometry.

But besides the round hole, the triangulation of cylinder with holes already supports holes defined by points. You can add other shapes there, e.g. a hole like an 8, but where a minimal gap remains in the middle. For the triangulation one needs closed curves.

function makeBoundaryFront
function makePointsHole
function makeCircularHole

1 Like