### 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);

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R);

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R);

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);

``````

}

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);
``````

}

``````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, y1=P1, x2=P2, y2=P2)

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, y1=P1, x2=P2, y2=P2, xC=C, yC=C)

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, y1=P1, x2=P2, y2=P2)

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, y1=C1, x2=C2, y2=C2,

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); P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R); P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R); 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, y1=P1, x2=P2, y2=P2) 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, y1=P1, x2=P2, y2=P2, xC=C, yC=C) 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, y1=P1, x2=P2, y2=P2) 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, y1=C1, x2=C2, y2=C2, 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
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);

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R);

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R);

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);

``````

}

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);
``````

}

`````` 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, y1=P1, x2=P2, y2=P2)

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, y1=P1, x2=P2, y2=P2, xC=C, yC=C)

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, y1=P1, x2=P2, y2=P2)

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, y1=C1, x2=C2, y2=C2,

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]];
``````

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); > > P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R); > > P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R); > > 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, y1=P1, x2=P2, y2=P2) > > 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, y1=P1, x2=P2, y2=P2, xC=C, yC=C) > > 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, y1=P1, x2=P2, y2=P2) > > 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, y1=C1, x2=C2, y2=C2, > > 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 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);

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R);

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R);

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);

``````

}

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);
``````

}

`````` 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, y1=P1, x2=P2, y2=P2)

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, y1=P1, x2=P2, y2=P2, xC=C, yC=C)

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, y1=P1, x2=P2, y2=P2)

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, y1=C1, x2=C2, y2=C2,

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]];
``````

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

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-----
Gesendet: Freitag, 7. Januar 2022 14:21
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);

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R);

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R);

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);

``````

}

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);
``````

}

`````` 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, y1=P1, x2=P2, y2=P2)

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, y1=P1, x2=P2, y2=P2, xC=C, yC=C)

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, y1=P1, x2=P2, y2=P2)

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, y1=C1, x2=C2, y2=C2,

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]];
``````

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

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
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);

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R);

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R);

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);

``````

}

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);
``````

}

`````` 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, y1=P1, x2=P2, y2=P2)

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, y1=P1, x2=P2, y2=P2, xC=C, yC=C)

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, y1=P1, x2=P2, y2=P2)

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, y1=C1, x2=C2, y2=C2,

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
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-----
Gesendet: Freitag, 7. Januar 2022 14:21
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);

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R);

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R);

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);

``````

}

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);
``````

}

``````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, y1=P1, x2=P2, y2=P2)

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, y1=P1, x2=P2, y2=P2, xC=C, yC=C)

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, y1=P1, x2=P2, y2=P2)

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, y1=C1, x2=C2, y2=C2,

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]];
``````

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

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

To unsubscribe send an email to discuss-leave@lists.openscad.org AM
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-----
Gesendet: Freitag, 7. Januar 2022 14:21
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);

P1 = getIntersectionPointsOfTwoCircles2D(C1, r1, M, R);

P2 = getIntersectionPointsOfTwoCircles2D(C2, r2, M, R);

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);

``````

}

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);
``````

}

``````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, y1=P1, x2=P2, y2=P2)

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, y1=P1, x2=P2, y2=P2, xC=C, yC=C)

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, y1=P1, x2=P2, y2=P2)

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, y1=C1, x2=C2, y2=C2,

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]];
``````

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

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

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
`````` 