getUtoTmapping cannot get the correct progress

I have met some funny code, and some result has let me muddled.

let p1 = new THREE.Vector3(20, 0, 0);
let p2 = new THREE.Vector3(0, 0, 0);
let curve = new THREE.CatmullRomCurve3([p1, p2]);
let progress = curve.getUtoTmapping(0, 2);
let half = curve.getPoint(0.5);  
let half_2 = curve.getPointAt(0.5);

console.log(progress, half, half_2)

I think the log will show progress = 0.1, half and half_2 will be {x=10, y=0, z=0} before I run the code. But the log show progress = 0.23823764849028212, half = {x: 12.5, y: 0, z: 0}, half_2={x: 10.000024823603106, y: 0, z: 0}

So I have change the code below

let p1 = new THREE.Vector3(20, 0, 0);
let p2 = new THREE.Vector3(0, 0, 0);
let line = new THREE.LineCurve3(p1, p2);
let curve = new THREE.CurvePath();
curve.curves.push(line);
let progress = curve.getUtoTmapping(0, 2);
let half = curve.getPoint(0.5);  
let half_2 = curve.getPointAt(0.5);

console.log(progress, half, half_2)

The result is printed the same as my expectation. progress = 0.1, half = half_2 = {x=10,y=0,z=0}.

Why the CatmullRomCurve3 getUtoTmapping is not return the correct progress?

And what’s the difference between getPoint and getPointAt

It seems you are misinterpreting the signature of getUtoTmapping(). Normally, you do not use the second parameter. You just pass in the first one which lies in the range [0,1]. The method will map this value to another one that allows you to sample an equidistant point. If you pass in the second parameter, the first one is ignored since you already tell the method the target distance you want the t for. I suggest you study a bit the implementation of getUtoTmapping() and this becomes more clear.

As mentioned in the docs, getPointAt() honors the length of the curve and thus produces equidistant points. Compare how the points are distributed in the following live examples.

getPoint(): Edit fiddle - JSFiddle - Code Playground
getPointAt(): Edit fiddle - JSFiddle - Code Playground

Yes, about getUtoTmapping(), I have read the source code, but something new for me, and I think if I pass the second value, this method will return a progress on the line.

for example, I have pass parameter 2 as the sencod value for the getUtoTmapping(), and I will get the pecentage of 2 to the total length. And the return value is correct as my expectation on CurvePath, but the CatmullRomCurve3 return a value which let me make a mistake .

.getUtoTmapping ( u : Float, distance : Float ) : Float

Given u in the range ( 0 .. 1 ), returns t also in the range ( 0 .. 1 ). u and t can then be used to give you points which are equidistant from the ends of the curve, using .getPoint. 

This API explaination is difficult for us. Does the t means the percentage ? that means if I want to know how much percentages does 2 occupy, I should invoke this method?

No, this is something totally different. Since 2 represents length in world units, you should be able to compute the intended outcome like so;

console.log( 2 / curve.getLength() );

yes, sir, I have used 2 / curve.getLength() to instead, but it difficult to understand getUtoTmapping(u, distance), and I searched all the internet, the results show the same sentences as the official docs.

And the source code show that:
if I pass the distance, the loop to find the same arclength[i], if arcLengths[ i ] == distance, then return i / (arcLengths.length - 1), I really don’t know what’s the meaning of this return value. :cry:

I read and analyze the source code again, I think maybe I get some new ideas. The getUtoTmapping() just be used to find the the target mapped place for the distance, and then we can use the mapped place to find the point by getPoint(). And getLengths() just store 201(default) lengths, length[index] just contain the current distance to the first point, and each point is not evenly distributed.

But some new questions: If we draw a CatmullRomCurve3 to represent road line, and I want to move a cube on the CatmullRomCurve3 at 2 world unit per second, how can I to calculate the point?

Hi sir, I have change my code by change distance to get point, but it seems that the distance between the 1st and 2nd point is not equidistant, how to deal with this problem.

I have put my code into here:
https://codepen.io/momohanfeng/pen/OJVzoMa

let p1 = new THREE.Vector3(-6, 0, 0);
let p2 = new THREE.Vector3(14, 0, 0);
let curve = new THREE.CatmullRomCurve3([p1, p2]);
let points_ = [];

for (let i = 0; ; i += 1) {
   if(i < 0){
       points_.push(curve.getPoint(0));
   }else{
       let step = curve.getUtoTmapping(0, Math.min(curve.getLength(), 2 * i));
       points_.push(curve.getPoint(step));
   }
   if(2 * i >= curve.getLength()){
        break;
   }
}

I’m sorry, I really don’t understand what you are doing in your code.

Try it like so:

const u = curve.getUtoTmapping( null, 2 );
curve.getPoint( u, position );

I’m sorry for my bad description.

I just want to put some points on the CatmullRomCurve3 equidistant, but I cannot draw the first point(at the beginning of a line segment) to let all the points be equidistant.

let p1 = new THREE.Vector3(-6, 0, 0);
let p2 = new THREE.Vector3(14, 0, 0);
let curve = new THREE.CatmullRomCurve3([p1, p2]);
let points_ = [];
for (let i = 0;; i += 1) {
    if (i == 0) {
       const  u = curve.getUtoTmapping(null, 2);
       points_.push(curve.getPoint(u));
    } else {
       let step = curve.getUtoTmapping(0, Math.min(curve.getLength(), 2 * i));
       points_.push(curve.getPoint(step));
   }
   if (2 * i >= curve.getLength()) { 
       break;
   }
}

this link will show the wrong result.