discuss@lists.openscad.org

OpenSCAD general discussion

View all threads

Tangential arc between two circles

JR
Joachim Röttinger
Fri, Jan 7, 2022 12:30 PM

Hi, I’m trying to write a module that draws an tangential arc between two
circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/).

In principle it works but there are situations where it does not.

The sample code below echos a nan when P2 has been calculated. My assumption
is that the issue is based on a loose of precision after calculation of
point M.

Can anybody give me a hint how to solve this. Thank you in advance.

$fa = 0.01;

$fs = 0.01;

C1 = [0, 0];

r1 = 20;

C2 = [50, 50];

r2 = 2.5;

R = 90;

test(C1, r1, C2, r2, R);

module test(C1, r1, C2, r2, R) {

R1 = R - r1;

R2 = R - r2;

M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0];

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0];

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0];

echo(M, P1, P2);

translate(C1) circle(r=r1);

translate(C2) circle(r=r2);

color("Cyan") polygon(points = [P1, P2, M]);

color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M);

polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R);

}

module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) {

startAngle = getAngleBetweenTwoPoints2D(C, P1);

endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C);

angles=[ for (i = [startAngle:endAngle-1]) i ];

coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ];

translate(C) polygon(coords);

}

module circleWithCenter2D(r=1, d, C) {

translate(C) circle(r=r);

}

module rotateAboutPoint(a, v, pt) {

translate(pt)

    rotate(a,v)

        translate(-pt)

            children();   

}

// getDistanceBetweenTwoPoints2D

// returns the distance between 2 points

// P1: point 1

// P2: point 2

function getDistanceBetweenTwoPoints2D(P1, P2) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

    sqrt((x1 - x2)^2 + (y1 - y2)^2);

// getAngleBetweenThreePoints2D

// returns the angle between 3 points

// P1: point 1

// P2: point 2

// C: center point at angle

function getAngleBetweenThreePoints2D(P1, P2, C) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1])

    atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC);

// getAngleBetweenTwoPoints2D

// returns the angle between 2 points

// P1: point 1

// P2: point 2

function getAngleBetweenTwoPoints2D(P1, P2) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

    atan2(y2 - y1, x2 - x1);

// getIntersectionPointsOfTwoCircles2D

// returns 2 possible intersection points of 2 circles

// C1: center of circle 1

// r1: radius of circle 1

// C2: center of circle 2

// r2: radius of circle 2

function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) =

let(

    x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1],

    d=sqrt((x2-x1)^2 + (y2-y1)^2),

    a=(r1^2-r2^2+d^2)/(2*d),

    h=sqrt(r1^2-a^2),

    x3=x1+a*(x2-x1)/d,   

    y3=y1+a*(y2-y1)/d,  

    x4=x3+h*(y2-y1)/d,

    y4=y3-h*(x2-x1)/d,

    x5=x3-h*(y2-y1)/d,

    y5=y3+h*(x2-x1)/d

) [[x4, y4], [x5, y5]];
Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/). In principle it works but there are situations where it does not. The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M. Can anybody give me a hint how to solve this. Thank you in advance. $fa = 0.01; $fs = 0.01; C1 = [0, 0]; r1 = 20; C2 = [50, 50]; r2 = 2.5; R = 90; test(C1, r1, C2, r2, R); module test(C1, r1, C2, r2, R) { R1 = R - r1; R2 = R - r2; M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0]; P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0]; P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0]; echo(M, P1, P2); translate(C1) circle(r=r1); translate(C2) circle(r=r2); color("Cyan") polygon(points = [P1, P2, M]); color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M); polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R); } module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) { startAngle = getAngleBetweenTwoPoints2D(C, P1); endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C); angles=[ for (i = [startAngle:endAngle-1]) i ]; coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ]; translate(C) polygon(coords); } module circleWithCenter2D(r=1, d, C) { translate(C) circle(r=r); } module rotateAboutPoint(a, v, pt) { translate(pt) rotate(a,v) translate(-pt) children(); } // getDistanceBetweenTwoPoints2D // returns the distance between 2 points // P1: point 1 // P2: point 2 function getDistanceBetweenTwoPoints2D(P1, P2) = let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) sqrt((x1 - x2)^2 + (y1 - y2)^2); // getAngleBetweenThreePoints2D // returns the angle between 3 points // P1: point 1 // P2: point 2 // C: center point at angle function getAngleBetweenThreePoints2D(P1, P2, C) = let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1]) atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC); // getAngleBetweenTwoPoints2D // returns the angle between 2 points // P1: point 1 // P2: point 2 function getAngleBetweenTwoPoints2D(P1, P2) = let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) atan2(y2 - y1, x2 - x1); // getIntersectionPointsOfTwoCircles2D // returns 2 possible intersection points of 2 circles // C1: center of circle 1 // r1: radius of circle 1 // C2: center of circle 2 // r2: radius of circle 2 function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) = let( x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1], d=sqrt((x2-x1)^2 + (y2-y1)^2), a=(r1^2-r2^2+d^2)/(2*d), h=sqrt(r1^2-a^2), x3=x1+a*(x2-x1)/d, y3=y1+a*(y2-y1)/d, x4=x3+h*(y2-y1)/d, y4=y3-h*(x2-x1)/d, x5=x3-h*(y2-y1)/d, y5=y3+h*(x2-x1)/d ) [[x4, y4], [x5, y5]];
AM
Adrian Mariano
Fri, Jan 7, 2022 1:21 PM

Your two circles are tangent, with one of them inside the other one.
There is only one intersection point, and the notion of the "tangent
arcs" makes no sense in this case.

On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger joe@joecool.de wrote:

Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/).

In principle it works but there are situations where it does not.

The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M.

Can anybody give me a hint how to solve this. Thank you in advance.

$fa = 0.01;

$fs = 0.01;

C1 = [0, 0];

r1 = 20;

C2 = [50, 50];

r2 = 2.5;

R = 90;

test(C1, r1, C2, r2, R);

module test(C1, r1, C2, r2, R) {

 R1 = R - r1;

 R2 = R - r2;

 M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0];

 P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0];

 P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0];

 echo(M, P1, P2);

 translate(C1) circle(r=r1);

 translate(C2) circle(r=r2);

 color("Cyan") polygon(points = [P1, P2, M]);

 color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M);

 polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R);

}

module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) {

 startAngle = getAngleBetweenTwoPoints2D(C, P1);

 endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C);

 angles=[ for (i = [startAngle:endAngle-1]) i ];

 coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ];

 translate(C) polygon(coords);

}

module circleWithCenter2D(r=1, d, C) {

 translate(C) circle(r=r);

}

module rotateAboutPoint(a, v, pt) {

 translate(pt)

     rotate(a,v)

         translate(-pt)

             children();

}

// getDistanceBetweenTwoPoints2D

// returns the distance between 2 points

// P1: point 1

// P2: point 2

function getDistanceBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     sqrt((x1 - x2)^2 + (y1 - y2)^2);

// getAngleBetweenThreePoints2D

// returns the angle between 3 points

// P1: point 1

// P2: point 2

// C: center point at angle

function getAngleBetweenThreePoints2D(P1, P2, C) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1])

     atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC);

// getAngleBetweenTwoPoints2D

// returns the angle between 2 points

// P1: point 1

// P2: point 2

function getAngleBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     atan2(y2 - y1, x2 - x1);

// getIntersectionPointsOfTwoCircles2D

// returns 2 possible intersection points of 2 circles

// C1: center of circle 1

// r1: radius of circle 1

// C2: center of circle 2

// r2: radius of circle 2

function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) =

 let(

     x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1],

     d=sqrt((x2-x1)^2 + (y2-y1)^2),

     a=(r1^2-r2^2+d^2)/(2*d),

     h=sqrt(r1^2-a^2),

     x3=x1+a*(x2-x1)/d,

     y3=y1+a*(y2-y1)/d,

     x4=x3+h*(y2-y1)/d,

     y4=y3-h*(x2-x1)/d,

     x5=x3-h*(y2-y1)/d,

     y5=y3+h*(x2-x1)/d

 ) [[x4, y4], [x5, y5]];

OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Your two circles are tangent, with one of them inside the other one. There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case. On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger <joe@joecool.de> wrote: > > Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/). > > In principle it works but there are situations where it does not. > > The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M. > > Can anybody give me a hint how to solve this. Thank you in advance. > > > > $fa = 0.01; > > $fs = 0.01; > > > > C1 = [0, 0]; > > r1 = 20; > > C2 = [50, 50]; > > r2 = 2.5; > > R = 90; > > > > test(C1, r1, C2, r2, R); > > > > module test(C1, r1, C2, r2, R) { > > R1 = R - r1; > > R2 = R - r2; > > M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0]; > > P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0]; > > P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0]; > > echo(M, P1, P2); > > translate(C1) circle(r=r1); > > translate(C2) circle(r=r2); > > color("Cyan") polygon(points = [P1, P2, M]); > > color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M); > > polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R); > > } > > > > module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) { > > startAngle = getAngleBetweenTwoPoints2D(C, P1); > > endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C); > > angles=[ for (i = [startAngle:endAngle-1]) i ]; > > coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ]; > > translate(C) polygon(coords); > > } > > > > module circleWithCenter2D(r=1, d, C) { > > translate(C) circle(r=r); > > } > > > > module rotateAboutPoint(a, v, pt) { > > translate(pt) > > rotate(a,v) > > translate(-pt) > > children(); > > } > > > > // getDistanceBetweenTwoPoints2D > > // returns the distance between 2 points > > // P1: point 1 > > // P2: point 2 > > function getDistanceBetweenTwoPoints2D(P1, P2) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > sqrt((x1 - x2)^2 + (y1 - y2)^2); > > > > // getAngleBetweenThreePoints2D > > // returns the angle between 3 points > > // P1: point 1 > > // P2: point 2 > > // C: center point at angle > > function getAngleBetweenThreePoints2D(P1, P2, C) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1]) > > atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC); > > > > // getAngleBetweenTwoPoints2D > > // returns the angle between 2 points > > // P1: point 1 > > // P2: point 2 > > function getAngleBetweenTwoPoints2D(P1, P2) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > atan2(y2 - y1, x2 - x1); > > > > // getIntersectionPointsOfTwoCircles2D > > // returns 2 possible intersection points of 2 circles > > // C1: center of circle 1 > > // r1: radius of circle 1 > > // C2: center of circle 2 > > // r2: radius of circle 2 > > function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) = > > let( > > x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1], > > d=sqrt((x2-x1)^2 + (y2-y1)^2), > > a=(r1^2-r2^2+d^2)/(2*d), > > h=sqrt(r1^2-a^2), > > x3=x1+a*(x2-x1)/d, > > y3=y1+a*(y2-y1)/d, > > x4=x3+h*(y2-y1)/d, > > y4=y3-h*(x2-x1)/d, > > x5=x3-h*(y2-y1)/d, > > y5=y3+h*(x2-x1)/d > > ) [[x4, y4], [x5, y5]]; > > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
AD
Ari Diacou
Fri, Jan 7, 2022 1:28 PM

Based on the animation in the website you provided, I will make one
assumption: The tangent lines you want touch each circle on the same angle
on each of the circles.

Also, why can't you just take a hull() around the two circles?

On Fri, Jan 7, 2022 at 8:21 AM Adrian Mariano avm4@cornell.edu wrote:

Your two circles are tangent, with one of them inside the other one.
There is only one intersection point, and the notion of the "tangent
arcs" makes no sense in this case.

On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger joe@joecool.de wrote:

Hi, I’m trying to write a module that draws an tangential arc between

In principle it works but there are situations where it does not.

The sample code below echos a nan when P2 has been calculated. My

assumption is that the issue is based on a loose of precision after
calculation of point M.

Can anybody give me a hint how to solve this. Thank you in advance.

$fa = 0.01;

$fs = 0.01;

C1 = [0, 0];

r1 = 20;

C2 = [50, 50];

r2 = 2.5;

R = 90;

test(C1, r1, C2, r2, R);

module test(C1, r1, C2, r2, R) {

 R1 = R - r1;

 R2 = R - r2;

 M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0];

 P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0];

 P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0];

 echo(M, P1, P2);

 translate(C1) circle(r=r1);

 translate(C2) circle(r=r2);

 color("Cyan") polygon(points = [P1, P2, M]);

 color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M);

 polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R);

}

module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) {

 startAngle = getAngleBetweenTwoPoints2D(C, P1);

 endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C);

 angles=[ for (i = [startAngle:endAngle-1]) i ];

 coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ];

 translate(C) polygon(coords);

}

module circleWithCenter2D(r=1, d, C) {

 translate(C) circle(r=r);

}

module rotateAboutPoint(a, v, pt) {

 translate(pt)

     rotate(a,v)

         translate(-pt)

             children();

}

// getDistanceBetweenTwoPoints2D

// returns the distance between 2 points

// P1: point 1

// P2: point 2

function getDistanceBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     sqrt((x1 - x2)^2 + (y1 - y2)^2);

// getAngleBetweenThreePoints2D

// returns the angle between 3 points

// P1: point 1

// P2: point 2

// C: center point at angle

function getAngleBetweenThreePoints2D(P1, P2, C) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1])

     atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC);

// getAngleBetweenTwoPoints2D

// returns the angle between 2 points

// P1: point 1

// P2: point 2

function getAngleBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     atan2(y2 - y1, x2 - x1);

// getIntersectionPointsOfTwoCircles2D

// returns 2 possible intersection points of 2 circles

// C1: center of circle 1

// r1: radius of circle 1

// C2: center of circle 2

// r2: radius of circle 2

function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) =

 let(

     x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1],

     d=sqrt((x2-x1)^2 + (y2-y1)^2),

     a=(r1^2-r2^2+d^2)/(2*d),

     h=sqrt(r1^2-a^2),

     x3=x1+a*(x2-x1)/d,

     y3=y1+a*(y2-y1)/d,

     x4=x3+h*(y2-y1)/d,

     y4=y3-h*(x2-x1)/d,

     x5=x3-h*(y2-y1)/d,

     y5=y3+h*(x2-x1)/d

 ) [[x4, y4], [x5, y5]];

OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Based on the animation in the website you provided, I will make one assumption: The tangent lines you want touch each circle on the same angle on each of the circles. Also, why can't you just take a hull() around the two circles? On Fri, Jan 7, 2022 at 8:21 AM Adrian Mariano <avm4@cornell.edu> wrote: > Your two circles are tangent, with one of them inside the other one. > There is only one intersection point, and the notion of the "tangent > arcs" makes no sense in this case. > > On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger <joe@joecool.de> wrote: > > > > Hi, I’m trying to write a module that draws an tangential arc between > two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/). > > > > In principle it works but there are situations where it does not. > > > > The sample code below echos a nan when P2 has been calculated. My > assumption is that the issue is based on a loose of precision after > calculation of point M. > > > > Can anybody give me a hint how to solve this. Thank you in advance. > > > > > > > > $fa = 0.01; > > > > $fs = 0.01; > > > > > > > > C1 = [0, 0]; > > > > r1 = 20; > > > > C2 = [50, 50]; > > > > r2 = 2.5; > > > > R = 90; > > > > > > > > test(C1, r1, C2, r2, R); > > > > > > > > module test(C1, r1, C2, r2, R) { > > > > R1 = R - r1; > > > > R2 = R - r2; > > > > M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0]; > > > > P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0]; > > > > P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0]; > > > > echo(M, P1, P2); > > > > translate(C1) circle(r=r1); > > > > translate(C2) circle(r=r2); > > > > color("Cyan") polygon(points = [P1, P2, M]); > > > > color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M); > > > > polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R); > > > > } > > > > > > > > module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) { > > > > startAngle = getAngleBetweenTwoPoints2D(C, P1); > > > > endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C); > > > > angles=[ for (i = [startAngle:endAngle-1]) i ]; > > > > coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ]; > > > > translate(C) polygon(coords); > > > > } > > > > > > > > module circleWithCenter2D(r=1, d, C) { > > > > translate(C) circle(r=r); > > > > } > > > > > > > > module rotateAboutPoint(a, v, pt) { > > > > translate(pt) > > > > rotate(a,v) > > > > translate(-pt) > > > > children(); > > > > } > > > > > > > > // getDistanceBetweenTwoPoints2D > > > > // returns the distance between 2 points > > > > // P1: point 1 > > > > // P2: point 2 > > > > function getDistanceBetweenTwoPoints2D(P1, P2) = > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > > > sqrt((x1 - x2)^2 + (y1 - y2)^2); > > > > > > > > // getAngleBetweenThreePoints2D > > > > // returns the angle between 3 points > > > > // P1: point 1 > > > > // P2: point 2 > > > > // C: center point at angle > > > > function getAngleBetweenThreePoints2D(P1, P2, C) = > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1]) > > > > atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC); > > > > > > > > // getAngleBetweenTwoPoints2D > > > > // returns the angle between 2 points > > > > // P1: point 1 > > > > // P2: point 2 > > > > function getAngleBetweenTwoPoints2D(P1, P2) = > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > > > atan2(y2 - y1, x2 - x1); > > > > > > > > // getIntersectionPointsOfTwoCircles2D > > > > // returns 2 possible intersection points of 2 circles > > > > // C1: center of circle 1 > > > > // r1: radius of circle 1 > > > > // C2: center of circle 2 > > > > // r2: radius of circle 2 > > > > function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) = > > > > let( > > > > x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1], > > > > d=sqrt((x2-x1)^2 + (y2-y1)^2), > > > > a=(r1^2-r2^2+d^2)/(2*d), > > > > h=sqrt(r1^2-a^2), > > > > x3=x1+a*(x2-x1)/d, > > > > y3=y1+a*(y2-y1)/d, > > > > x4=x3+h*(y2-y1)/d, > > > > y4=y3-h*(x2-x1)/d, > > > > x5=x3-h*(y2-y1)/d, > > > > y5=y3+h*(x2-x1)/d > > > > ) [[x4, y4], [x5, y5]]; > > > > > > > > _______________________________________________ > > OpenSCAD mailing list > > To unsubscribe send an email to discuss-leave@lists.openscad.org > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JR
Joachim Röttinger
Fri, Jan 7, 2022 1:30 PM

Yes, P1 and P2 have only one intersection point. Function getIntersectionPointsOfTwoCircles2D should return the same point twice.
The circle should intersect and not be inside as the mathematical formulas are correct.
If I take C2 = [50, 0]; it works

-----Ursprüngliche Nachricht-----
Von: Adrian Mariano avm4@cornell.edu
Gesendet: Freitag, 7. Januar 2022 14:21
An: OpenSCAD general discussion discuss@lists.openscad.org
Betreff: [OpenSCAD] Re: Tangential arc between two circles

Your two circles are tangent, with one of them inside the other one.
There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case.

On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger joe@joecool.de wrote:

Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/).

In principle it works but there are situations where it does not.

The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M.

Can anybody give me a hint how to solve this. Thank you in advance.

$fa = 0.01;

$fs = 0.01;

C1 = [0, 0];

r1 = 20;

C2 = [50, 50];

r2 = 2.5;

R = 90;

test(C1, r1, C2, r2, R);

module test(C1, r1, C2, r2, R) {

 R1 = R - r1;

 R2 = R - r2;

 M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0];

 P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0];

 P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0];

 echo(M, P1, P2);

 translate(C1) circle(r=r1);

 translate(C2) circle(r=r2);

 color("Cyan") polygon(points = [P1, P2, M]);

 color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M);

 polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R);

}

module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) {

 startAngle = getAngleBetweenTwoPoints2D(C, P1);

 endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C);

 angles=[ for (i = [startAngle:endAngle-1]) i ];

 coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] 

];

 translate(C) polygon(coords);

}

module circleWithCenter2D(r=1, d, C) {

 translate(C) circle(r=r);

}

module rotateAboutPoint(a, v, pt) {

 translate(pt)

     rotate(a,v)

         translate(-pt)

             children();

}

// getDistanceBetweenTwoPoints2D

// returns the distance between 2 points

// P1: point 1

// P2: point 2

function getDistanceBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     sqrt((x1 - x2)^2 + (y1 - y2)^2);

// getAngleBetweenThreePoints2D

// returns the angle between 3 points

// P1: point 1

// P2: point 2

// C: center point at angle

function getAngleBetweenThreePoints2D(P1, P2, C) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1])

     atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC);

// getAngleBetweenTwoPoints2D

// returns the angle between 2 points

// P1: point 1

// P2: point 2

function getAngleBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     atan2(y2 - y1, x2 - x1);

// getIntersectionPointsOfTwoCircles2D

// returns 2 possible intersection points of 2 circles

// C1: center of circle 1

// r1: radius of circle 1

// C2: center of circle 2

// r2: radius of circle 2

function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) =

 let(

     x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1],

     d=sqrt((x2-x1)^2 + (y2-y1)^2),

     a=(r1^2-r2^2+d^2)/(2*d),

     h=sqrt(r1^2-a^2),

     x3=x1+a*(x2-x1)/d,

     y3=y1+a*(y2-y1)/d,

     x4=x3+h*(y2-y1)/d,

     y4=y3-h*(x2-x1)/d,

     x5=x3-h*(y2-y1)/d,

     y5=y3+h*(x2-x1)/d

 ) [[x4, y4], [x5, y5]];

OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Yes, P1 and P2 have only one intersection point. Function getIntersectionPointsOfTwoCircles2D should return the same point twice. The circle should intersect and not be inside as the mathematical formulas are correct. If I take C2 = [50, 0]; it works -----Ursprüngliche Nachricht----- Von: Adrian Mariano <avm4@cornell.edu> Gesendet: Freitag, 7. Januar 2022 14:21 An: OpenSCAD general discussion <discuss@lists.openscad.org> Betreff: [OpenSCAD] Re: Tangential arc between two circles Your two circles are tangent, with one of them inside the other one. There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case. On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger <joe@joecool.de> wrote: > > Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/). > > In principle it works but there are situations where it does not. > > The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M. > > Can anybody give me a hint how to solve this. Thank you in advance. > > > > $fa = 0.01; > > $fs = 0.01; > > > > C1 = [0, 0]; > > r1 = 20; > > C2 = [50, 50]; > > r2 = 2.5; > > R = 90; > > > > test(C1, r1, C2, r2, R); > > > > module test(C1, r1, C2, r2, R) { > > R1 = R - r1; > > R2 = R - r2; > > M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0]; > > P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0]; > > P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0]; > > echo(M, P1, P2); > > translate(C1) circle(r=r1); > > translate(C2) circle(r=r2); > > color("Cyan") polygon(points = [P1, P2, M]); > > color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M); > > polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R); > > } > > > > module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) { > > startAngle = getAngleBetweenTwoPoints2D(C, P1); > > endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C); > > angles=[ for (i = [startAngle:endAngle-1]) i ]; > > coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] > ]; > > translate(C) polygon(coords); > > } > > > > module circleWithCenter2D(r=1, d, C) { > > translate(C) circle(r=r); > > } > > > > module rotateAboutPoint(a, v, pt) { > > translate(pt) > > rotate(a,v) > > translate(-pt) > > children(); > > } > > > > // getDistanceBetweenTwoPoints2D > > // returns the distance between 2 points > > // P1: point 1 > > // P2: point 2 > > function getDistanceBetweenTwoPoints2D(P1, P2) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > sqrt((x1 - x2)^2 + (y1 - y2)^2); > > > > // getAngleBetweenThreePoints2D > > // returns the angle between 3 points > > // P1: point 1 > > // P2: point 2 > > // C: center point at angle > > function getAngleBetweenThreePoints2D(P1, P2, C) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1]) > > atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC); > > > > // getAngleBetweenTwoPoints2D > > // returns the angle between 2 points > > // P1: point 1 > > // P2: point 2 > > function getAngleBetweenTwoPoints2D(P1, P2) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > atan2(y2 - y1, x2 - x1); > > > > // getIntersectionPointsOfTwoCircles2D > > // returns 2 possible intersection points of 2 circles > > // C1: center of circle 1 > > // r1: radius of circle 1 > > // C2: center of circle 2 > > // r2: radius of circle 2 > > function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) = > > let( > > x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1], > > d=sqrt((x2-x1)^2 + (y2-y1)^2), > > a=(r1^2-r2^2+d^2)/(2*d), > > h=sqrt(r1^2-a^2), > > x3=x1+a*(x2-x1)/d, > > y3=y1+a*(y2-y1)/d, > > x4=x3+h*(y2-y1)/d, > > y4=y3-h*(x2-x1)/d, > > x5=x3-h*(y2-y1)/d, > > y5=y3+h*(x2-x1)/d > > ) [[x4, y4], [x5, y5]]; > > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org _______________________________________________ OpenSCAD mailing list To unsubscribe send an email to discuss-leave@lists.openscad.org
JR
Joachim Röttinger
Fri, Jan 7, 2022 1:32 PM

Hull will create tangent lines between the circles and not an arc.

Von: Ari Diacou ari.diacou@gmail.com
Gesendet: Freitag, 7. Januar 2022 14:29
An: OpenSCAD general discussion discuss@lists.openscad.org
Betreff: [OpenSCAD] Re: Tangential arc between two circles

Based on the animation in the website you provided, I will make one assumption: The tangent lines you want touch each circle on the same angle on each of the circles.

Also, why can't you just take a hull() around the two circles?

On Fri, Jan 7, 2022 at 8:21 AM Adrian Mariano <avm4@cornell.edu mailto:avm4@cornell.edu > wrote:

Your two circles are tangent, with one of them inside the other one.
There is only one intersection point, and the notion of the "tangent
arcs" makes no sense in this case.

On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger <joe@joecool.de mailto:joe@joecool.de > wrote:

Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/).

In principle it works but there are situations where it does not.

The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M.

Can anybody give me a hint how to solve this. Thank you in advance.

$fa = 0.01;

$fs = 0.01;

C1 = [0, 0];

r1 = 20;

C2 = [50, 50];

r2 = 2.5;

R = 90;

test(C1, r1, C2, r2, R);

module test(C1, r1, C2, r2, R) {

 R1 = R - r1;

 R2 = R - r2;

 M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0];

 P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0];

 P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0];

 echo(M, P1, P2);

 translate(C1) circle(r=r1);

 translate(C2) circle(r=r2);

 color("Cyan") polygon(points = [P1, P2, M]);

 color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M);

 polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R);

}

module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) {

 startAngle = getAngleBetweenTwoPoints2D(C, P1);

 endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C);

 angles=[ for (i = [startAngle:endAngle-1]) i ];

 coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ];

 translate(C) polygon(coords);

}

module circleWithCenter2D(r=1, d, C) {

 translate(C) circle(r=r);

}

module rotateAboutPoint(a, v, pt) {

 translate(pt)

     rotate(a,v)

         translate(-pt)

             children();

}

// getDistanceBetweenTwoPoints2D

// returns the distance between 2 points

// P1: point 1

// P2: point 2

function getDistanceBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     sqrt((x1 - x2)^2 + (y1 - y2)^2);

// getAngleBetweenThreePoints2D

// returns the angle between 3 points

// P1: point 1

// P2: point 2

// C: center point at angle

function getAngleBetweenThreePoints2D(P1, P2, C) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1])

     atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC);

// getAngleBetweenTwoPoints2D

// returns the angle between 2 points

// P1: point 1

// P2: point 2

function getAngleBetweenTwoPoints2D(P1, P2) =

 let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

     atan2(y2 - y1, x2 - x1);

// getIntersectionPointsOfTwoCircles2D

// returns 2 possible intersection points of 2 circles

// C1: center of circle 1

// r1: radius of circle 1

// C2: center of circle 2

// r2: radius of circle 2

function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) =

 let(

     x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1],

     d=sqrt((x2-x1)^2 + (y2-y1)^2),

     a=(r1^2-r2^2+d^2)/(2*d),

     h=sqrt(r1^2-a^2),

     x3=x1+a*(x2-x1)/d,

     y3=y1+a*(y2-y1)/d,

     x4=x3+h*(y2-y1)/d,

     y4=y3-h*(x2-x1)/d,

     x5=x3-h*(y2-y1)/d,

     y5=y3+h*(x2-x1)/d

 ) [[x4, y4], [x5, y5]];

OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org mailto:discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org mailto:discuss-leave@lists.openscad.org

Hull will create tangent lines between the circles and not an arc. Von: Ari Diacou <ari.diacou@gmail.com> Gesendet: Freitag, 7. Januar 2022 14:29 An: OpenSCAD general discussion <discuss@lists.openscad.org> Betreff: [OpenSCAD] Re: Tangential arc between two circles Based on the animation in the website you provided, I will make one assumption: The tangent lines you want touch each circle on the same angle on each of the circles. Also, why can't you just take a hull() around the two circles? On Fri, Jan 7, 2022 at 8:21 AM Adrian Mariano <avm4@cornell.edu <mailto:avm4@cornell.edu> > wrote: Your two circles are tangent, with one of them inside the other one. There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case. On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger <joe@joecool.de <mailto:joe@joecool.de> > wrote: > > Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/). > > In principle it works but there are situations where it does not. > > The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M. > > Can anybody give me a hint how to solve this. Thank you in advance. > > > > $fa = 0.01; > > $fs = 0.01; > > > > C1 = [0, 0]; > > r1 = 20; > > C2 = [50, 50]; > > r2 = 2.5; > > R = 90; > > > > test(C1, r1, C2, r2, R); > > > > module test(C1, r1, C2, r2, R) { > > R1 = R - r1; > > R2 = R - r2; > > M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0]; > > P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0]; > > P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0]; > > echo(M, P1, P2); > > translate(C1) circle(r=r1); > > translate(C2) circle(r=r2); > > color("Cyan") polygon(points = [P1, P2, M]); > > color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M); > > polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R); > > } > > > > module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) { > > startAngle = getAngleBetweenTwoPoints2D(C, P1); > > endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C); > > angles=[ for (i = [startAngle:endAngle-1]) i ]; > > coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] ]; > > translate(C) polygon(coords); > > } > > > > module circleWithCenter2D(r=1, d, C) { > > translate(C) circle(r=r); > > } > > > > module rotateAboutPoint(a, v, pt) { > > translate(pt) > > rotate(a,v) > > translate(-pt) > > children(); > > } > > > > // getDistanceBetweenTwoPoints2D > > // returns the distance between 2 points > > // P1: point 1 > > // P2: point 2 > > function getDistanceBetweenTwoPoints2D(P1, P2) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > sqrt((x1 - x2)^2 + (y1 - y2)^2); > > > > // getAngleBetweenThreePoints2D > > // returns the angle between 3 points > > // P1: point 1 > > // P2: point 2 > > // C: center point at angle > > function getAngleBetweenThreePoints2D(P1, P2, C) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1]) > > atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC); > > > > // getAngleBetweenTwoPoints2D > > // returns the angle between 2 points > > // P1: point 1 > > // P2: point 2 > > function getAngleBetweenTwoPoints2D(P1, P2) = > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > atan2(y2 - y1, x2 - x1); > > > > // getIntersectionPointsOfTwoCircles2D > > // returns 2 possible intersection points of 2 circles > > // C1: center of circle 1 > > // r1: radius of circle 1 > > // C2: center of circle 2 > > // r2: radius of circle 2 > > function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) = > > let( > > x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1], > > d=sqrt((x2-x1)^2 + (y2-y1)^2), > > a=(r1^2-r2^2+d^2)/(2*d), > > h=sqrt(r1^2-a^2), > > x3=x1+a*(x2-x1)/d, > > y3=y1+a*(y2-y1)/d, > > x4=x3+h*(y2-y1)/d, > > y4=y3-h*(x2-x1)/d, > > x5=x3-h*(y2-y1)/d, > > y5=y3+h*(x2-x1)/d > > ) [[x4, y4], [x5, y5]]; > > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org <mailto:discuss-leave@lists.openscad.org> _______________________________________________ OpenSCAD mailing list To unsubscribe send an email to discuss-leave@lists.openscad.org <mailto:discuss-leave@lists.openscad.org>
AM
Adrian Mariano
Fri, Jan 7, 2022 1:34 PM

I dug into the math a bit more.  I think that yes, the problem is
round-off error.  In the  referenced math you'll note that they don't
compute the final answer as the intersection of two circles, and
neither should you.  Just a slight error in the radius and you go from
a single (tangent) intersection to non-intersecting.  Instead you
should be computing this, as shown in the web site, as the
intersection of the line from M to M1 with circle 1, and then same for
circle 2.

On Fri, Jan 7, 2022 at 8:30 AM Joachim Röttinger joe@joecool.de wrote:

Yes, P1 and P2 have only one intersection point. Function getIntersectionPointsOfTwoCircles2D should return the same point twice.
The circle should intersect and not be inside as the mathematical formulas are correct.
If I take C2 = [50, 0]; it works

-----Ursprüngliche Nachricht-----
Von: Adrian Mariano avm4@cornell.edu
Gesendet: Freitag, 7. Januar 2022 14:21
An: OpenSCAD general discussion discuss@lists.openscad.org
Betreff: [OpenSCAD] Re: Tangential arc between two circles

Your two circles are tangent, with one of them inside the other one.
There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case.

On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger joe@joecool.de wrote:

Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/).

In principle it works but there are situations where it does not.

The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M.

Can anybody give me a hint how to solve this. Thank you in advance.

$fa = 0.01;

$fs = 0.01;

C1 = [0, 0];

r1 = 20;

C2 = [50, 50];

r2 = 2.5;

R = 90;

test(C1, r1, C2, r2, R);

module test(C1, r1, C2, r2, R) {

R1 = R - r1;

R2 = R - r2;

M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0];

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0];

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0];

echo(M, P1, P2);

translate(C1) circle(r=r1);

translate(C2) circle(r=r2);

color("Cyan") polygon(points = [P1, P2, M]);

color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M);

polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R);

}

module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) {

startAngle = getAngleBetweenTwoPoints2D(C, P1);

endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C);

angles=[ for (i = [startAngle:endAngle-1]) i ];

coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)]

];

translate(C) polygon(coords);

}

module circleWithCenter2D(r=1, d, C) {

translate(C) circle(r=r);

}

module rotateAboutPoint(a, v, pt) {

translate(pt)

    rotate(a,v)

        translate(-pt)

            children();

}

// getDistanceBetweenTwoPoints2D

// returns the distance between 2 points

// P1: point 1

// P2: point 2

function getDistanceBetweenTwoPoints2D(P1, P2) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

    sqrt((x1 - x2)^2 + (y1 - y2)^2);

// getAngleBetweenThreePoints2D

// returns the angle between 3 points

// P1: point 1

// P2: point 2

// C: center point at angle

function getAngleBetweenThreePoints2D(P1, P2, C) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1])

    atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC);

// getAngleBetweenTwoPoints2D

// returns the angle between 2 points

// P1: point 1

// P2: point 2

function getAngleBetweenTwoPoints2D(P1, P2) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

    atan2(y2 - y1, x2 - x1);

// getIntersectionPointsOfTwoCircles2D

// returns 2 possible intersection points of 2 circles

// C1: center of circle 1

// r1: radius of circle 1

// C2: center of circle 2

// r2: radius of circle 2

function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) =

let(

    x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1],

    d=sqrt((x2-x1)^2 + (y2-y1)^2),

    a=(r1^2-r2^2+d^2)/(2*d),

    h=sqrt(r1^2-a^2),

    x3=x1+a*(x2-x1)/d,

    y3=y1+a*(y2-y1)/d,

    x4=x3+h*(y2-y1)/d,

    y4=y3-h*(x2-x1)/d,

    x5=x3-h*(y2-y1)/d,

    y5=y3+h*(x2-x1)/d

) [[x4, y4], [x5, y5]];

OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I dug into the math a bit more. I think that yes, the problem is round-off error. In the referenced math you'll note that they don't compute the final answer as the intersection of two circles, and neither should you. Just a slight error in the radius and you go from a single (tangent) intersection to non-intersecting. Instead you should be computing this, as shown in the web site, as the intersection of the line from M to M1 with circle 1, and then same for circle 2. On Fri, Jan 7, 2022 at 8:30 AM Joachim Röttinger <joe@joecool.de> wrote: > > Yes, P1 and P2 have only one intersection point. Function getIntersectionPointsOfTwoCircles2D should return the same point twice. > The circle should intersect and not be inside as the mathematical formulas are correct. > If I take C2 = [50, 0]; it works > > -----Ursprüngliche Nachricht----- > Von: Adrian Mariano <avm4@cornell.edu> > Gesendet: Freitag, 7. Januar 2022 14:21 > An: OpenSCAD general discussion <discuss@lists.openscad.org> > Betreff: [OpenSCAD] Re: Tangential arc between two circles > > Your two circles are tangent, with one of them inside the other one. > There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case. > > On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger <joe@joecool.de> wrote: > > > > Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/). > > > > In principle it works but there are situations where it does not. > > > > The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M. > > > > Can anybody give me a hint how to solve this. Thank you in advance. > > > > > > > > $fa = 0.01; > > > > $fs = 0.01; > > > > > > > > C1 = [0, 0]; > > > > r1 = 20; > > > > C2 = [50, 50]; > > > > r2 = 2.5; > > > > R = 90; > > > > > > > > test(C1, r1, C2, r2, R); > > > > > > > > module test(C1, r1, C2, r2, R) { > > > > R1 = R - r1; > > > > R2 = R - r2; > > > > M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0]; > > > > P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0]; > > > > P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0]; > > > > echo(M, P1, P2); > > > > translate(C1) circle(r=r1); > > > > translate(C2) circle(r=r2); > > > > color("Cyan") polygon(points = [P1, P2, M]); > > > > color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M); > > > > polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R); > > > > } > > > > > > > > module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) { > > > > startAngle = getAngleBetweenTwoPoints2D(C, P1); > > > > endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C); > > > > angles=[ for (i = [startAngle:endAngle-1]) i ]; > > > > coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] > > ]; > > > > translate(C) polygon(coords); > > > > } > > > > > > > > module circleWithCenter2D(r=1, d, C) { > > > > translate(C) circle(r=r); > > > > } > > > > > > > > module rotateAboutPoint(a, v, pt) { > > > > translate(pt) > > > > rotate(a,v) > > > > translate(-pt) > > > > children(); > > > > } > > > > > > > > // getDistanceBetweenTwoPoints2D > > > > // returns the distance between 2 points > > > > // P1: point 1 > > > > // P2: point 2 > > > > function getDistanceBetweenTwoPoints2D(P1, P2) = > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > > > sqrt((x1 - x2)^2 + (y1 - y2)^2); > > > > > > > > // getAngleBetweenThreePoints2D > > > > // returns the angle between 3 points > > > > // P1: point 1 > > > > // P2: point 2 > > > > // C: center point at angle > > > > function getAngleBetweenThreePoints2D(P1, P2, C) = > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1]) > > > > atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC); > > > > > > > > // getAngleBetweenTwoPoints2D > > > > // returns the angle between 2 points > > > > // P1: point 1 > > > > // P2: point 2 > > > > function getAngleBetweenTwoPoints2D(P1, P2) = > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > > > atan2(y2 - y1, x2 - x1); > > > > > > > > // getIntersectionPointsOfTwoCircles2D > > > > // returns 2 possible intersection points of 2 circles > > > > // C1: center of circle 1 > > > > // r1: radius of circle 1 > > > > // C2: center of circle 2 > > > > // r2: radius of circle 2 > > > > function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) = > > > > let( > > > > x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1], > > > > d=sqrt((x2-x1)^2 + (y2-y1)^2), > > > > a=(r1^2-r2^2+d^2)/(2*d), > > > > h=sqrt(r1^2-a^2), > > > > x3=x1+a*(x2-x1)/d, > > > > y3=y1+a*(y2-y1)/d, > > > > x4=x3+h*(y2-y1)/d, > > > > y4=y3-h*(x2-x1)/d, > > > > x5=x3-h*(y2-y1)/d, > > > > y5=y3+h*(x2-x1)/d > > > > ) [[x4, y4], [x5, y5]]; > > > > > > > > _______________________________________________ > > OpenSCAD mailing list > > To unsubscribe send an email to discuss-leave@lists.openscad.org > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
AM
Adrian Mariano
Fri, Jan 7, 2022 3:22 PM

Note that you can simplify your code somewhat by seeking
coordinate-free solutions.  For example, distance between P1 and P2 is
norm(P1-P2), in 2D or 3D (or any dimension, actually).  I played
around with the tangent arcs problem and arrived at this, which
appears to work, including in the case in your example:

function unit(v) = v/norm(v);

function circle_intersection(c1,r1,c2,r2) =
let(
d = norm(c2-c1),
a = (c2-c1)/d,
b = [-a.y,a.x],
L = (r1^2-r2^2+d^2)/2/d,
hsqr = r1^2-L^2
)
hsqr<0 ? []
: let(h=sqrt(hsqr))
[La+hb+c1, La-hb+c1];

// Returns list of two arc parameters: [center, start_pt, end_pt]
function circle_arc(c1,r1,c2,r2,R) =
assert( 2R > r1+r2+norm(c1-c2), "Specified arc radius, R, is too
small.  The arc does not exist.")
let(
R1 = R-r1,
R2 = R-r2,
Mlist = circle_intersection(c1,R1,c2,R2)
)
[for(M=Mlist) [M, c1+r1
unit(c1-M), c2+r2*unit(c2-M)]];

On Fri, Jan 7, 2022 at 8:34 AM Adrian Mariano avm4@cornell.edu wrote:

I dug into the math a bit more.  I think that yes, the problem is
round-off error.  In the  referenced math you'll note that they don't
compute the final answer as the intersection of two circles, and
neither should you.  Just a slight error in the radius and you go from
a single (tangent) intersection to non-intersecting.  Instead you
should be computing this, as shown in the web site, as the
intersection of the line from M to M1 with circle 1, and then same for
circle 2.

On Fri, Jan 7, 2022 at 8:30 AM Joachim Röttinger joe@joecool.de wrote:

Yes, P1 and P2 have only one intersection point. Function getIntersectionPointsOfTwoCircles2D should return the same point twice.
The circle should intersect and not be inside as the mathematical formulas are correct.
If I take C2 = [50, 0]; it works

-----Ursprüngliche Nachricht-----
Von: Adrian Mariano avm4@cornell.edu
Gesendet: Freitag, 7. Januar 2022 14:21
An: OpenSCAD general discussion discuss@lists.openscad.org
Betreff: [OpenSCAD] Re: Tangential arc between two circles

Your two circles are tangent, with one of them inside the other one.
There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case.

On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger joe@joecool.de wrote:

Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/).

In principle it works but there are situations where it does not.

The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M.

Can anybody give me a hint how to solve this. Thank you in advance.

$fa = 0.01;

$fs = 0.01;

C1 = [0, 0];

r1 = 20;

C2 = [50, 50];

r2 = 2.5;

R = 90;

test(C1, r1, C2, r2, R);

module test(C1, r1, C2, r2, R) {

R1 = R - r1;

R2 = R - r2;

M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0];

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0];

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0];

echo(M, P1, P2);

translate(C1) circle(r=r1);

translate(C2) circle(r=r2);

color("Cyan") polygon(points = [P1, P2, M]);

color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M);

polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R);

}

module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) {

startAngle = getAngleBetweenTwoPoints2D(C, P1);

endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C);

angles=[ for (i = [startAngle:endAngle-1]) i ];

coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)]

];

translate(C) polygon(coords);

}

module circleWithCenter2D(r=1, d, C) {

translate(C) circle(r=r);

}

module rotateAboutPoint(a, v, pt) {

translate(pt)

    rotate(a,v)

        translate(-pt)

            children();

}

// getDistanceBetweenTwoPoints2D

// returns the distance between 2 points

// P1: point 1

// P2: point 2

function getDistanceBetweenTwoPoints2D(P1, P2) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

    sqrt((x1 - x2)^2 + (y1 - y2)^2);

// getAngleBetweenThreePoints2D

// returns the angle between 3 points

// P1: point 1

// P2: point 2

// C: center point at angle

function getAngleBetweenThreePoints2D(P1, P2, C) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1])

    atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC);

// getAngleBetweenTwoPoints2D

// returns the angle between 2 points

// P1: point 1

// P2: point 2

function getAngleBetweenTwoPoints2D(P1, P2) =

let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1])

    atan2(y2 - y1, x2 - x1);

// getIntersectionPointsOfTwoCircles2D

// returns 2 possible intersection points of 2 circles

// C1: center of circle 1

// r1: radius of circle 1

// C2: center of circle 2

// r2: radius of circle 2

function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) =

let(

    x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1],

    d=sqrt((x2-x1)^2 + (y2-y1)^2),

    a=(r1^2-r2^2+d^2)/(2*d),

    h=sqrt(r1^2-a^2),

    x3=x1+a*(x2-x1)/d,

    y3=y1+a*(y2-y1)/d,

    x4=x3+h*(y2-y1)/d,

    y4=y3-h*(x2-x1)/d,

    x5=x3-h*(y2-y1)/d,

    y5=y3+h*(x2-x1)/d

) [[x4, y4], [x5, y5]];

OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Note that you can simplify your code somewhat by seeking coordinate-free solutions. For example, distance between P1 and P2 is norm(P1-P2), in 2D or 3D (or any dimension, actually). I played around with the tangent arcs problem and arrived at this, which appears to work, including in the case in your example: function unit(v) = v/norm(v); function circle_intersection(c1,r1,c2,r2) = let( d = norm(c2-c1), a = (c2-c1)/d, b = [-a.y,a.x], L = (r1^2-r2^2+d^2)/2/d, hsqr = r1^2-L^2 ) hsqr<0 ? [] : let(h=sqrt(hsqr)) [L*a+h*b+c1, L*a-h*b+c1]; // Returns list of two arc parameters: [center, start_pt, end_pt] function circle_arc(c1,r1,c2,r2,R) = assert( 2*R > r1+r2+norm(c1-c2), "Specified arc radius, R, is too small. The arc does not exist.") let( R1 = R-r1, R2 = R-r2, Mlist = circle_intersection(c1,R1,c2,R2) ) [for(M=Mlist) [M, c1+r1*unit(c1-M), c2+r2*unit(c2-M)]]; On Fri, Jan 7, 2022 at 8:34 AM Adrian Mariano <avm4@cornell.edu> wrote: > > I dug into the math a bit more. I think that yes, the problem is > round-off error. In the referenced math you'll note that they don't > compute the final answer as the intersection of two circles, and > neither should you. Just a slight error in the radius and you go from > a single (tangent) intersection to non-intersecting. Instead you > should be computing this, as shown in the web site, as the > intersection of the line from M to M1 with circle 1, and then same for > circle 2. > > On Fri, Jan 7, 2022 at 8:30 AM Joachim Röttinger <joe@joecool.de> wrote: > > > > Yes, P1 and P2 have only one intersection point. Function getIntersectionPointsOfTwoCircles2D should return the same point twice. > > The circle should intersect and not be inside as the mathematical formulas are correct. > > If I take C2 = [50, 0]; it works > > > > -----Ursprüngliche Nachricht----- > > Von: Adrian Mariano <avm4@cornell.edu> > > Gesendet: Freitag, 7. Januar 2022 14:21 > > An: OpenSCAD general discussion <discuss@lists.openscad.org> > > Betreff: [OpenSCAD] Re: Tangential arc between two circles > > > > Your two circles are tangent, with one of them inside the other one. > > There is only one intersection point, and the notion of the "tangent arcs" makes no sense in this case. > > > > On Fri, Jan 7, 2022 at 7:31 AM Joachim Röttinger <joe@joecool.de> wrote: > > > > > > Hi, I’m trying to write a module that draws an tangential arc between two circles (based on https://www.frassek.org/2d-mathe/kreise-verbinden/). > > > > > > In principle it works but there are situations where it does not. > > > > > > The sample code below echos a nan when P2 has been calculated. My assumption is that the issue is based on a loose of precision after calculation of point M. > > > > > > Can anybody give me a hint how to solve this. Thank you in advance. > > > > > > > > > > > > $fa = 0.01; > > > > > > $fs = 0.01; > > > > > > > > > > > > C1 = [0, 0]; > > > > > > r1 = 20; > > > > > > C2 = [50, 50]; > > > > > > r2 = 2.5; > > > > > > R = 90; > > > > > > > > > > > > test(C1, r1, C2, r2, R); > > > > > > > > > > > > module test(C1, r1, C2, r2, R) { > > > > > > R1 = R - r1; > > > > > > R2 = R - r2; > > > > > > M = getIntersectionPointsOfTwoCircles2D(C1, R1, C2, R2)[0]; > > > > > > P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R)[0]; > > > > > > P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R)[0]; > > > > > > echo(M, P1, P2); > > > > > > translate(C1) circle(r=r1); > > > > > > translate(C2) circle(r=r2); > > > > > > color("Cyan") polygon(points = [P1, P2, M]); > > > > > > color("Blue") translate([0, 0, -2]) circleWithCenter2D(r=R, C=M); > > > > > > polygonWithRadiusBetweenTwoPoints2D(P1, P2, M, r=R); > > > > > > } > > > > > > > > > > > > module polygonWithRadiusBetweenTwoPoints2D (P1, P2, C, r=1) { > > > > > > startAngle = getAngleBetweenTwoPoints2D(C, P1); > > > > > > endAngle = startAngle + getAngleBetweenThreePoints2D(P1, P2, C); > > > > > > angles=[ for (i = [startAngle:endAngle-1]) i ]; > > > > > > coords=[ for (j=concat(angles, [endAngle])) [r*cos(j), r*sin(j)] > > > ]; > > > > > > translate(C) polygon(coords); > > > > > > } > > > > > > > > > > > > module circleWithCenter2D(r=1, d, C) { > > > > > > translate(C) circle(r=r); > > > > > > } > > > > > > > > > > > > module rotateAboutPoint(a, v, pt) { > > > > > > translate(pt) > > > > > > rotate(a,v) > > > > > > translate(-pt) > > > > > > children(); > > > > > > } > > > > > > > > > > > > // getDistanceBetweenTwoPoints2D > > > > > > // returns the distance between 2 points > > > > > > // P1: point 1 > > > > > > // P2: point 2 > > > > > > function getDistanceBetweenTwoPoints2D(P1, P2) = > > > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > > > > > sqrt((x1 - x2)^2 + (y1 - y2)^2); > > > > > > > > > > > > // getAngleBetweenThreePoints2D > > > > > > // returns the angle between 3 points > > > > > > // P1: point 1 > > > > > > // P2: point 2 > > > > > > // C: center point at angle > > > > > > function getAngleBetweenThreePoints2D(P1, P2, C) = > > > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1], xC=C[0], yC=C[1]) > > > > > > atan2(y2 - yC, x2 - xC) - atan2(y1 - yC, x1 - xC); > > > > > > > > > > > > // getAngleBetweenTwoPoints2D > > > > > > // returns the angle between 2 points > > > > > > // P1: point 1 > > > > > > // P2: point 2 > > > > > > function getAngleBetweenTwoPoints2D(P1, P2) = > > > > > > let(x1=P1[0], y1=P1[1], x2=P2[0], y2=P2[1]) > > > > > > atan2(y2 - y1, x2 - x1); > > > > > > > > > > > > // getIntersectionPointsOfTwoCircles2D > > > > > > // returns 2 possible intersection points of 2 circles > > > > > > // C1: center of circle 1 > > > > > > // r1: radius of circle 1 > > > > > > // C2: center of circle 2 > > > > > > // r2: radius of circle 2 > > > > > > function getIntersectionPointsOfTwoCircles2D(C1, r1, C2, r2) = > > > > > > let( > > > > > > x1=C1[0], y1=C1[1], x2=C2[0], y2=C2[1], > > > > > > d=sqrt((x2-x1)^2 + (y2-y1)^2), > > > > > > a=(r1^2-r2^2+d^2)/(2*d), > > > > > > h=sqrt(r1^2-a^2), > > > > > > x3=x1+a*(x2-x1)/d, > > > > > > y3=y1+a*(y2-y1)/d, > > > > > > x4=x3+h*(y2-y1)/d, > > > > > > y4=y3-h*(x2-x1)/d, > > > > > > x5=x3-h*(y2-y1)/d, > > > > > > y5=y3+h*(x2-x1)/d > > > > > > ) [[x4, y4], [x5, y5]]; > > > > > > > > > > > > _______________________________________________ > > > OpenSCAD mailing list > > > To unsubscribe send an email to discuss-leave@lists.openscad.org > > _______________________________________________ > > OpenSCAD mailing list > > To unsubscribe send an email to discuss-leave@lists.openscad.org > > _______________________________________________ > > OpenSCAD mailing list > > To unsubscribe send an email to discuss-leave@lists.openscad.org
SP
Sanjeev Prabhakar
Fri, Jan 7, 2022 4:21 PM

try this animation

> > try this animation
J
jon
Fri, Jan 7, 2022 4:36 PM

I can't get this SCAD file to work at all.

On 1/7/2022 11:21 AM, Sanjeev Prabhakar wrote:

 try this animation

OpenSCAD mailing list
To unsubscribe send an email todiscuss-leave@lists.openscad.org

I can't get this SCAD file to work at all. On 1/7/2022 11:21 AM, Sanjeev Prabhakar wrote: > > try this animation > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email todiscuss-leave@lists.openscad.org
SP
Sanjeev Prabhakar
Fri, Jan 7, 2022 4:54 PM

It is working fine in my system.
screenshot will be big size, so I cannot share.

It is working fine in my system. screenshot will be big size, so I cannot share.