Thanks,

Alasdair

I tried to find code that does this exactly, but failed. So I took some time try different combinations of atan acos asin until I got somewhat working solution. Then I added fixes for special cases that break the inital code.

based on your suggestion I tried some values (`dx=0`

, `dy=0`

, `dz=0`

) and found a case that did not work: `(dx==0 && dy == 0)`

.

I have added an exception that now fixes taht edge case.

*(I am proud I made this work somehow, so if you find another edge case that does not work, let me know
)*

link1: gist: https://gist.github.com/hrgdavor/c1bc1b4f3e3f92161eb4dd9074363793

link2: jscad.xyz with that gist: https://jscad.xyz/#https://gist.githubusercontent.com/hrgdavor/c1bc1b4f3e3f92161eb4dd9074363793/raw/1c41bbf3dc5d5af33614205ce8bd17e1e93b66f1/testCylinderFromTo.js

new version with fix:

```
function cylinderFromTo(p1,p2, radius){
const sqr = x=>x*x
let dx = p2[0] - p1[0]
let dy = p2[1] - p1[1]
let dz = p2[2] - p1[2]
let height = Math.sqrt( sqr(dx) + sqr(dy) + sqr(dz))
let obj = cylinder({radius, height})
if(dx || dy){
let dxy = Math.sqrt( sqr(dx) + sqr(dy))
let ay = Math.atan(dxy/dz) *(dx < 0 ? -1:1)
let az = Math.atan(dy/dx)
let ax = dz < 0 ? -Math.PI:0
obj = transforms.rotate([ax,ay,az], obj)
}
let mid = [p1[0]+dx/2,p1[1]+dy/2,p1[2]+dz/2]
return translate(mid, obj)
}
```

the code now works for all of these:

```
testCylinderFromTo([-20,30,50],[-40,-10,70]);
testCylinderFromTo([0,0,0],[10,10,10])
testCylinderFromTo([0,0,0],[20,-20,20])
testCylinderFromTo([0,0,0],[-30,30,30])
testCylinderFromTo([0,0,0],[-40,-40,40])
testCylinderFromTo([0,0,0],[15,15,-15])
testCylinderFromTo([0,0,0],[25,-25,-25])
testCylinderFromTo([0,0,0],[-35,35,-35])
testCylinderFromTo([100,0,0],[100,0,30])
testCylinderFromTo([100,0,0],[100,0,-30])
testCylinderFromTo([100,0,0],[100,30,0])
testCylinderFromTo([100,0,0],[100,-30,0])
testCylinderFromTo([100,0,0],[130,0,0])
testCylinderFromTo([100,0,0],[70,0,0])
```

screen:

I decided to first translate p1 and p2 to 0 and p2-p1 or p1-p2, depending on which had a positive z-coordinate. Then we are simply rotating things in the z>=0 half-space, which reduces everything to two rotations (as you have).

But I do like the simplicity and elegance of your code: clearly you're a more advanced JavaScript programmer than me. Did you work all this out from scratch, or are you taking another program and rewriting it?

The other possible issue is that the result should be independent of the order of p1 and p2: it may be that your function does that automatically, but I found it tricky with mine.

Thank you very much indeed.

]]>It is a product of using atan acos asin until I got something and then guessing some more until it worked . It seems to be working, though I actually dont understand it completely

```
function cylinderFromTo(p1,p2, radius){
const sqr = x=>x*x
let dx = p2[0] - p1[0]
let dy = p2[1] - p1[1]
let dz = p2[2] - p1[2]
let dxy = Math.sqrt( sqr(dx) + sqr(dy))
let height = Math.sqrt( sqr(dx) + sqr(dy) + sqr(dz))
let ay = Math.atan(dxy/dz) *(dx < 0 ? -1:1)
let az = Math.atan(dy/dx)
let ax = dz < 0 ? -Math.PI:0
let obj = cylinder({radius, height})
let mid = [p1[0]+dx/2,p1[1]+dy/2,p1[2]+dz/2]
return translate(mid, rotate([ax,ay,az], obj))
}
```

I used these to test visually

```
function main(){
ret = [];
function testCylinderFromTo(p1,p2){
ret = [ ...ret,
translate(p1,sphere({size:1})),
translate(p2,sphere({size:1})),
jscad.colors.colorize([1,0,0,0.7],cylinderFromTo(p1,p2,2)),
];
}
testCylinderFromTo([-20,30,50],[-40,-10,70]);
testCylinderFromTo([0,0,0],[10,10,10])
testCylinderFromTo([0,0,0],[20,-20,20])
testCylinderFromTo([0,0,0],[-30,30,30])
testCylinderFromTo([0,0,0],[-40,-40,40])
testCylinderFromTo([0,0,0],[15,15,-15])
testCylinderFromTo([0,0,0],[25,-25,-25])
testCylinderFromTo([0,0,0],[-35,35,-35])
testCylinderFromTo([0,0,0],[-45,-45,-45])
return ret;
}
```

]]>