discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Re: Calculate points in an arc

SP
Sanjeev Prabhakar
Wed, Apr 6, 2022 1:28 AM

you need to write few functions to achieve this:

you can check this below

// module to draw a polyline
module p_lineo(path,size=.5){
for(i=[0:len(path)-2])
let(p0=path[i],p1=path[i+1])

hull(){
translate(p0)circle(size/2,$fn=20);
translate(p1)circle(size/2,$fn=20);}}

//module to draw points on the given coordinates
module points(p,d=.5){
for(i=p)translate(i)cube(size=d,center=true);

}

// function to draw an arc with 3 points (2d)
function 3p_arc(p1,p2,p3,s=30)=

let(
p4=p1+(p2-p1)/2,
p5=p2+(p3-p2)/2,
v1=p2-p4,u1=v1/norm(v1),
v2=p3-p5,u2=v2/norm(v2),
p6=p4+u1rm(90),
p7=p5+u2
rm(90),
cp=i_p2d([p4,p6],[p5,p7]),
r=norm(p1-cp),
v3=p1-cp,v4=p2-cp,v5=p3-cp,
a1=ang(v3.x,v3.y),
a2=ang(v4.x,v4.y),
a3=ang(v5.x,v5.y),
a4=cw([p1,p2,p3])==-1?(a3<a1?a3+360:a3):(a3<a1?a3:a3-360)

)arc(r,a1,a4,cp,s);

// function to draw an arc (as a input to function 3p_arc()

function
arc(radius,ang1=0,ang2=355,cp=[0,0],s=20)=[for(i=[ang1:(ang2-ang1)/s:ang2])cp+[radiuscos(i),radiussin(i)]];

// function to rotate a vector by theta degrees (input to function 3p_arc)
function rm(theta)=[[cos(theta),sin(theta)],[-sin(theta),cos(theta)]];

// function to calculate the intersection point between 2 lines (input to
function 3p_arc()
function i_p2d(l1,l2)=let(
p0=l1[0],p1=l1[1],
p2=l2[0],p3=l2[1],
v1=p1-p0,
v2=p3-p2,
//p0+v1t1=p2+v2t2
//v1t1-v2t2=p2-p0
//[[v1.x,-v2.x],[v1.y,-v2.y]][t1,t2]=[p2.x-p0.x,p2.y-p0.y]
t1=(i_m2d([[v1.x,-v2.x],[v1.y,-v2.y]])
[p2.x-p0.x,p2.y-p0.y])[0],
pi=p0+v1*t1

)pi;

// function to calculate inverse matrix to calculate intersection point
(input to function i_p2d()
function i_m2d(m)=let(
m11=m[0][0],m12=m[0][1],
m21=m[1][0],m22=m[1][1],

s11=m22,s12=-m21,
s21=-m12,s22=m11,

d=m11m22-m21m12
)1/d*[[s11,s21],[s12,s22]];

// function to calculate angle of a given vector (input to fucntion 3p_arc)
function ang(x,y)=
x>=0&&y>=0?atan(y/x):x<0&&y>=0?180-abs(atan(y/x)):x<0&&y<0?180+abs(atan(y/x)):360-abs(atan(y/x));

// function to calculate whether a section is clockwise or anticlockwise
(input to function 3p_arc()
function cw(sec)=let(p=mode_sign(list_ang(sec)))
p[0]>p[1]?-1:1;

// function is input to function cw()
function
mode_sign(p,plus=0,minus=0,n=0)=n==len(p)?[plus,minus]:mode_sign(p,p[n]>0?plus+1:plus+0,p[n]<0?minus+1:minus+0,n+1);

// function is input to function cw()

function list_ang(sec)=[for(i=[0:len(sec)-1])
let(
p0=sec[i],p1=i<len(sec)-1?sec[i+1]:sec[0],p2=i<len(sec)-2?sec[i+2]:i<len(sec)-1?sec[0]:sec[1],
v1=p1-p0, v2=p2-p1,
angle1=ang(v1.x,v1.y),angle2=ang(v2.x,v2.y),
angle=angle2-angle1

)if(is_num(angle))angle];

sec=3p_arc(p1=[10,49.25],p2=[60.5,51],p3=[101,49.25],s=50);

p_lineo(sec,.5);

color("green")
points([[10,49.25],[60.5,51],[101,49.25]],1);

On Tue, 5 Apr 2022 at 03:00, Jan Öhman via Discuss <
discuss@lists.openscad.org> wrote:

---------- Forwarded message ----------
From: "Jan Öhman" jan_ohman@yahoo.com
To: OpenSCAD General Discussion discuss@lists.openscad.org
Cc:
Bcc:
Date: Mon, 4 Apr 2022 21:30:27 +0000 (UTC)
Subject: [OpenSCAD] Calculate points in an arc
I have tried to make different calculations to put the rounded corners
together with a long bend.
I know the points where the long bend begins and where it ends, as well as
how high it should be.
but my calculations do not work

start (left)* x1=10.00, y1=49.25*
middle    x2 = 60.50, y2 = 51
end (right) x3 = 101, y3 = 49.25
First, I calculate the radius of an imaginary circle using the formula
below
The center of the virtual circle has the coordinates x0 and y0
[image: Infoga bild]

s = x3 - x1 91,00000000
h = y2 - y1 1,75000000
r = ((s^2) + (4h^2)) / (8h) 592,37500000
h = r - ( rot(4 * r^2 - s^2) / 2) 1,75000000
s = 2 * rot( h * (2*r - h)) 90,99038411
x0 = x2 60,50000000
y0 = y2 – r -541,37500000
Previously, I calculated the angles of the circle sector and used "my"
function to create the [x,y]-values for the arc. (but failed)
Either the arc did not reach the start and stop values or it ended up a
little too high or low.
(I have no idea why)

In this caset, I thought to create a table with the start value first and
the end value last.
Now I know x0, y0 and the r (radius) - from above and use this
formula .:
[image: Infoga bild]
Rewrites the formula so that it becomes a function of y
Step1 .: r² = (x - x0)² + (y – y0)²
Step2 .: (y - b)² = r² - (x – a)²
Step3 .: y = ROT(r² - (x - x0)²)+y0

Finally, I set the start value (x1), middle value(x2)
and the end value(x3)
and calculate the y values.

x = *y0 =      * desire difference
10 49,64766471 49,25 -0,397664708819093
60,5 51,49981502 51,5 0,00018497967755593
101 50,25505002 49,25 -1,00505001815964

(it was complicated to make the tables in the email)
I do not know why the calculated result differs from the desired value.
I think it's quite a lot - In the column on the far right - The center
point differed the least
(However, got better result than using angles)

What can be done to get an even better result?
[10, 49.25], [60.5, 51.5], [101, 49.25] (and many values between these)

Attach some code for possible test

$fa = 12;
$fs = 0.5;
fn = 50;
// y = 80-2000;
// points3 = circSect(0, 0, 2000, [0, 180], "left", 1, fn);
// points3 = circSect(0, 80-2000, 2000, [87, 93], "left", 1, 1000);
// points3 = circSect(55.5, 50.55-2000, 2000, [87.151, 92.826], "left", 1,
1000);
// polygon(points3);

p1x = 10;      // the start value
p1y = 49.25;
p2x = 60.50;      // the middle value
p2y = 51;
p3x = 101;      // the end value
p3y = p1y;

// http://matmin.kevius.com/cirkel.php
// r = ((s^2) + (4h^2)) / (8h)

s = p3x - p1x;  // 91
h = p2y - p1y;  // 1.25
radius = ((s^2) + (4h^2)) / (8h); // 828.725
echo(s, s^2, h, 4h^2, 8h, radius);
echo("");

// http://www.rasmus.is/sv/t/G/su30k3.html
// deg = degrade( sin( a / radius ));
deg1 = asin( (s/2) / radius );  // 3.14733
deg2 = deg1*2;                  // 6.29466
echo( deg1, deg2 );
echo("");

// frDeg = 90-30;
// toDeg = 90+30;
frDeg = 90-deg1;  // 3.8183 (3.872)
toDeg = 90+deg1;  // (4)
xPos = 55;
yPos = 51.5-radius;  // 50.79

points0 = circSect(  xPos, yPos, radius, [frDeg, toDeg], "left", 1, 4000);
// Hörn nere till vänster
polygon(points0);

//points1 = circSect(  10, 11.25,  10, [0, 90], "bottom", 1, fn); // Hörn
nere till vänster

points2 = circSect(  10, 39.25,  10, [0, 90], "left",  1, 100); // Hörn
uppe till vänster

points3 = circSect( 101, 39.25,  10, [0, 90], "top",    1, 100); // Hörn
uppe till höger

//points4 = circSect( 101, 11.25,  10, [0, 90], "right",  1, fn); // Hörn
nere till höger

echo(points2) // [0,39.25]  - [10, 49.25]
echo("");
echo(points0) // [9.5, 50.25] - [97.9774, 50.3849]
echo("");
echo(points3)

color("cyan"){
polygon(points0);
// polygon(points1);

polygon(points2);
polygon(points3);
// polygon(points4);

// polygon(concat(points2, points0, points3));
};

// polygon(concat(points1, points2, points3, points4));

// https://openhome.cc/eGossip/OpenSCAD/SectorArc.html
function circSect(x=0, y=0, radius=10, angles=[0,270], startRef="bottom",
rotate=1, fn=24)  =
let(
startAngel  = (startRef == "left")  ?  0
: (startRef == "bottom") ?  90
: (startRef == "right")  ? 180
: (startRef == "top")    ? 270
: undef,
r = radius,
//r = radius / cos(180 / fn),
step = 360 / fn,
// points = [[x, y],
points = [
for(a = [angles[0]-startAngel : step : angles[1]-startAngel])
[-rotate * r * cos(a)+x, r * sin(a)+y]]
) points;

---------- Forwarded message ----------
From: "Jan Öhman via Discuss" discuss@lists.openscad.org
To: OpenSCAD General Discussion discuss@lists.openscad.org
Cc: "Jan Öhman" jan_ohman@yahoo.com
Bcc:
Date: Mon, 4 Apr 2022 21:30:27 +0000 (UTC)
Subject: [OpenSCAD] Calculate points in an arc


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

you need to write few functions to achieve this: you can check this below // module to draw a polyline module p_lineo(path,size=.5){ for(i=[0:len(path)-2]) let(p0=path[i],p1=path[i+1]) hull(){ translate(p0)circle(size/2,$fn=20); translate(p1)circle(size/2,$fn=20);}} //module to draw points on the given coordinates module points(p,d=.5){ for(i=p)translate(i)cube(size=d,center=true); } // function to draw an arc with 3 points (2d) function 3p_arc(p1,p2,p3,s=30)= let( p4=p1+(p2-p1)/2, p5=p2+(p3-p2)/2, v1=p2-p4,u1=v1/norm(v1), v2=p3-p5,u2=v2/norm(v2), p6=p4+u1*rm(90), p7=p5+u2*rm(90), cp=i_p2d([p4,p6],[p5,p7]), r=norm(p1-cp), v3=p1-cp,v4=p2-cp,v5=p3-cp, a1=ang(v3.x,v3.y), a2=ang(v4.x,v4.y), a3=ang(v5.x,v5.y), a4=cw([p1,p2,p3])==-1?(a3<a1?a3+360:a3):(a3<a1?a3:a3-360) )arc(r,a1,a4,cp,s); // function to draw an arc (as a input to function 3p_arc() function arc(radius,ang1=0,ang2=355,cp=[0,0],s=20)=[for(i=[ang1:(ang2-ang1)/s:ang2])cp+[radius*cos(i),radius*sin(i)]]; // function to rotate a vector by theta degrees (input to function 3p_arc) function rm(theta)=[[cos(theta),sin(theta)],[-sin(theta),cos(theta)]]; // function to calculate the intersection point between 2 lines (input to function 3p_arc() function i_p2d(l1,l2)=let( p0=l1[0],p1=l1[1], p2=l2[0],p3=l2[1], v1=p1-p0, v2=p3-p2, //p0+v1*t1=p2+v2*t2 //v1*t1-v2*t2=p2-p0 //[[v1.x,-v2.x],[v1.y,-v2.y]]*[t1,t2]=[p2.x-p0.x,p2.y-p0.y] t1=(i_m2d([[v1.x,-v2.x],[v1.y,-v2.y]])*[p2.x-p0.x,p2.y-p0.y])[0], pi=p0+v1*t1 )pi; // function to calculate inverse matrix to calculate intersection point (input to function i_p2d() function i_m2d(m)=let( m11=m[0][0],m12=m[0][1], m21=m[1][0],m22=m[1][1], s11=m22,s12=-m21, s21=-m12,s22=m11, d=m11*m22-m21*m12 )1/d*[[s11,s21],[s12,s22]]; // function to calculate angle of a given vector (input to fucntion 3p_arc) function ang(x,y)= x>=0&&y>=0?atan(y/x):x<0&&y>=0?180-abs(atan(y/x)):x<0&&y<0?180+abs(atan(y/x)):360-abs(atan(y/x)); // function to calculate whether a section is clockwise or anticlockwise (input to function 3p_arc() function cw(sec)=let(p=mode_sign(list_ang(sec))) p[0]>p[1]?-1:1; // function is input to function cw() function mode_sign(p,plus=0,minus=0,n=0)=n==len(p)?[plus,minus]:mode_sign(p,p[n]>0?plus+1:plus+0,p[n]<0?minus+1:minus+0,n+1); // function is input to function cw() function list_ang(sec)=[for(i=[0:len(sec)-1]) let( p0=sec[i],p1=i<len(sec)-1?sec[i+1]:sec[0],p2=i<len(sec)-2?sec[i+2]:i<len(sec)-1?sec[0]:sec[1], v1=p1-p0, v2=p2-p1, angle1=ang(v1.x,v1.y),angle2=ang(v2.x,v2.y), angle=angle2-angle1 )if(is_num(angle))angle]; sec=3p_arc(p1=[10,49.25],p2=[60.5,51],p3=[101,49.25],s=50); p_lineo(sec,.5); color("green") points([[10,49.25],[60.5,51],[101,49.25]],1); On Tue, 5 Apr 2022 at 03:00, Jan Öhman via Discuss < discuss@lists.openscad.org> wrote: > > > > ---------- Forwarded message ---------- > From: "Jan Öhman" <jan_ohman@yahoo.com> > To: OpenSCAD General Discussion <discuss@lists.openscad.org> > Cc: > Bcc: > Date: Mon, 4 Apr 2022 21:30:27 +0000 (UTC) > Subject: [OpenSCAD] Calculate points in an arc > I have tried to make different calculations to put the rounded corners > together with a long bend. > I know the points where the long bend begins and where it ends, as well as > how high it should be. > but my calculations do not work > > start (left)* x1=10.00, y1=49.25* > middle *x2 = 60.50, y2 = 51* > end (right) *x3 = 101, y3 = 49.25* > First, I calculate the radius of an imaginary circle using the formula > below > The center of the virtual circle has the coordinates *x0* and *y0* > [image: Infoga bild] > > > > *s =* x3 - x1 91,00000000 > *h =* y2 - y1 1,75000000 > *r =* ((s^2) + (4*h^2)) / (8*h) 592,37500000 > *h =* r - ( rot(4 * r^2 - s^2) / 2) 1,75000000 > *s =* 2 * rot( h * (2*r - h)) 90,99038411 > *x0 =* x2 60,50000000 > *y0 =* y2 – r -541,37500000 > Previously, I calculated the angles of the circle sector and used "my" > function to create the [x,y]-values for the arc. (but failed) > Either the arc did not reach the start and stop values or it ended up a > little too high or low. > (I have no idea why) > > In this caset, I thought to create a table with the start value first and > the end value last. > Now I know *x0, y0* and the *r* (radius) - from above and use this > formula .: > [image: Infoga bild] > Rewrites the formula so that it becomes a function of y > Step1 .: r² = (x - x0)² + (y – y0)² > Step2 .: (y - b)² = r² - (x – a)² > Step3 .: y = ROT(r² - (x - x0)²)+y0 > > Finally, I set the start value (x1), middle value(x2) > and the end value(x3) > and calculate the y values. > > *x =* *y0 = * desire difference > 10 49,64766471 49,25 -0,397664708819093 > 60,5 51,49981502 51,5 0,00018497967755593 > 101 50,25505002 49,25 -1,00505001815964 > > (it was complicated to make the tables in the email) > I do not know why the calculated result differs from the desired value. > I think it's quite a lot - In the column on the far right - The center > point differed the least > (However, got better result than using angles) > > What can be done to get an even better result? > *[10, 49.25], [60.5, 51.5], [101, 49.25]* (and many values between these) > > Attach some code for possible test > > $fa = 12; > $fs = 0.5; > fn = 50; > // y = 80-2000; > // points3 = circSect(0, 0, 2000, [0, 180], "left", 1, fn); > // points3 = circSect(0, 80-2000, 2000, [87, 93], "left", 1, 1000); > // points3 = circSect(55.5, 50.55-2000, 2000, [87.151, 92.826], "left", 1, > 1000); > // polygon(points3); > > > p1x = 10; // the start value > p1y = 49.25; > p2x = 60.50; // the middle value > p2y = 51; > p3x = 101; // the end value > p3y = p1y; > > // http://matmin.kevius.com/cirkel.php > // r = ((s^2) + (4*h^2)) / (8*h) > > s = p3x - p1x; // 91 > h = p2y - p1y; // 1.25 > radius = ((s^2) + (4*h^2)) / (8*h); // 828.725 > echo(s, s^2, h, 4*h^2, 8*h, radius); > echo(""); > > // http://www.rasmus.is/sv/t/G/su30k3.html > // deg = degrade( sin( a / radius )); > deg1 = asin( (s/2) / radius ); // 3.14733 > deg2 = deg1*2; // 6.29466 > echo( deg1, deg2 ); > echo(""); > > // frDeg = 90-30; > // toDeg = 90+30; > frDeg = 90-deg1; // 3.8183 (3.872) > toDeg = 90+deg1; // (4) > xPos = 55; > yPos = 51.5-radius; // 50.79 > > points0 = circSect( xPos, yPos, radius, [frDeg, toDeg], "left", 1, 4000); > // Hörn nere till vänster > polygon(points0); > > > > //points1 = circSect( 10, 11.25, 10, [0, 90], "bottom", 1, fn); // Hörn > nere till vänster > > points2 = circSect( 10, 39.25, 10, [0, 90], "left", 1, 100); // Hörn > uppe till vänster > > points3 = circSect( 101, 39.25, 10, [0, 90], "top", 1, 100); // Hörn > uppe till höger > > //points4 = circSect( 101, 11.25, 10, [0, 90], "right", 1, fn); // Hörn > nere till höger > > echo(points2) // [0,39.25] - [10, 49.25] > echo(""); > echo(points0) // [9.5, 50.25] - [97.9774, 50.3849] > echo(""); > echo(points3) > > color("cyan"){ > polygon(points0); > // polygon(points1); > > polygon(points2); > polygon(points3); > // polygon(points4); > > // polygon(concat(points2, points0, points3)); > }; > > > // polygon(concat(points1, points2, points3, points4)); > > > > // https://openhome.cc/eGossip/OpenSCAD/SectorArc.html > function circSect(x=0, y=0, radius=10, angles=[0,270], startRef="bottom", > rotate=1, fn=24) = > let( > startAngel = (startRef == "left") ? 0 > : (startRef == "bottom") ? 90 > : (startRef == "right") ? 180 > : (startRef == "top") ? 270 > : undef, > r = radius, > //r = radius / cos(180 / fn), > step = 360 / fn, > // points = [[x, y], > points = [ > for(a = [angles[0]-startAngel : step : angles[1]-startAngel]) > [-rotate * r * cos(a)+x, r * sin(a)+y]] > ) points; > > > > > ---------- Forwarded message ---------- > From: "Jan Öhman via Discuss" <discuss@lists.openscad.org> > To: OpenSCAD General Discussion <discuss@lists.openscad.org> > Cc: "Jan Öhman" <jan_ohman@yahoo.com> > Bcc: > Date: Mon, 4 Apr 2022 21:30:27 +0000 (UTC) > Subject: [OpenSCAD] Calculate points in an arc > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
RP
Ronaldo Persiano
Fri, Apr 8, 2022 4:47 PM

To find an arc given 3 2D points you may find the intersection point of two
lines respectively bisecting the first pair and the last pair of points.
However, the reference I have given before makes possible a more concise
computation. Here is my version:

// based on
// https://en.wikipedia.org/wiki/Circumscribed_circle#Cartesian_coordinates

// return a list of fn points in the circular arc starting at p0,
// passing by p1 and ending at p2
function 3points_arc(p0, p1, p2, fn=10) =
// an alternative expression for D
// D  = 2 * ( (p1-p0).x * (p2-p0).y - (p1-p0).y * (p2-p0).x )
let( D  = 2 * cross(p1-p0, (p2-p0)) )
assert( abs(D)>1e-9, "The 3 points should not be collinear." )
let(
Ux    = ( (p2-p0).y*(p1-p0)(p1-p0) - (p1-p0).y(p2-p0)(p2-p0)
)/D,
Uy    = ( (p1-p0).x
(p2-p0)(p2-p0) - (p2-p0).x(p1-p0)(p1-p0)
)/D,
radius = norm([Ux,Uy]),
center = [Ux,Uy] + p0,
ang0  = atan2( (p0-center).y, (p0-center).x ),
ang2  = atan2( (p2-center).y, (p2-center).x ),
// the points are in a cw winding iff D<0
// the angular difference between vectors p2-center and p0-center
// measured from p0-center; dang is positive iff D is negative
dang  = D<0  ? ang2<ang0 ? ang2-ang0 : ang2-ang0-360
: ang2>ang0 ? ang2-ang0 : ang2-ang0+360
)
[ for(i=[0:fn-1])
let( ang = ang0 + i
dang/(fn-1) )
center + radius*[cos(ang),sin(ang)] ] ;

// Application example

// randomly generate 3 points
seed = floor(rands(0,10000,1)[0]);
echo(seed=seed); // seed allows for case recall
rnds = rands(0,20,6, seed=seed);
pts = [for(i=[0:2:5]) [rnds[i], rnds[i+1]] ];
//pts = [ [10, 49.25], [60.5, 51.5], [101, 49.25]  ];

// draw a polyline connecting the arc points
line(3points_arc(pts[0], pts[1], pts[2], 23), width=.2);

// connect the 3 point path with blue lines
color("blue") line(pts, width=.2);

// mark the start point with a red "dot"
color("red") translate(pts[0]) circle(.35);

// a helper module to trace a 2D or 3D polyline
module line(path, width=1) {
for(i=[0:len(path)-2]) {
hull() {
translate(path[i])  sphere(width/2);
translate(path[i+1]) sphere(width/2);
}
}
}

To find an arc given 3 2D points you may find the intersection point of two lines respectively bisecting the first pair and the last pair of points. However, the reference I have given before makes possible a more concise computation. Here is my version: // based on // https://en.wikipedia.org/wiki/Circumscribed_circle#Cartesian_coordinates // return a list of fn points in the circular arc starting at p0, // passing by p1 and ending at p2 function 3points_arc(p0, p1, p2, fn=10) = // an alternative expression for D // D = 2 * ( (p1-p0).x * (p2-p0).y - (p1-p0).y * (p2-p0).x ) let( D = 2 * cross(p1-p0, (p2-p0)) ) assert( abs(D)>1e-9, "The 3 points should not be collinear." ) let( Ux = ( (p2-p0).y*(p1-p0)*(p1-p0) - (p1-p0).y*(p2-p0)*(p2-p0) )/D, Uy = ( (p1-p0).x*(p2-p0)*(p2-p0) - (p2-p0).x*(p1-p0)*(p1-p0) )/D, radius = norm([Ux,Uy]), center = [Ux,Uy] + p0, ang0 = atan2( (p0-center).y, (p0-center).x ), ang2 = atan2( (p2-center).y, (p2-center).x ), // the points are in a cw winding iff D<0 // the angular difference between vectors p2-center and p0-center // measured from p0-center; dang is positive iff D is negative dang = D<0 ? ang2<ang0 ? ang2-ang0 : ang2-ang0-360 : ang2>ang0 ? ang2-ang0 : ang2-ang0+360 ) [ for(i=[0:fn-1]) let( ang = ang0 + i*dang/(fn-1) ) center + radius*[cos(ang),sin(ang)] ] ; // Application example // randomly generate 3 points seed = floor(rands(0,10000,1)[0]); echo(seed=seed); // seed allows for case recall rnds = rands(0,20,6, seed=seed); pts = [for(i=[0:2:5]) [rnds[i], rnds[i+1]] ]; //pts = [ [10, 49.25], [60.5, 51.5], [101, 49.25] ]; // draw a polyline connecting the arc points line(3points_arc(pts[0], pts[1], pts[2], 23), width=.2); // connect the 3 point path with blue lines color("blue") line(pts, width=.2); // mark the start point with a red "dot" color("red") translate(pts[0]) circle(.35); // a helper module to trace a 2D or 3D polyline module line(path, width=1) { for(i=[0:len(path)-2]) { hull() { translate(path[i]) sphere(width/2); translate(path[i+1]) sphere(width/2); } } }
Jan Öhman
Sat, Apr 16, 2022 7:21 PM

Thanks!Tried to analyze the answer (but, do not see how it will solve my desire)
I have 3 points that I want "a line" through to create the 2D object.
Points
x1=10, y1=49.25
x2=55,5, y2=50,5
x3=101, y3=49,5(right now I do not see the solution)    Den fredag 8 april 2022 18:47:59 CEST, Ronaldo Persiano rcmpersiano@gmail.com skrev:

To find an arc given 3 2D points you may find the intersection point of two lines respectively bisecting the first pair and the last pair of points. However, the reference I have given before makes possible a more concise computation. Here is my version:
// based on
// https://en.wikipedia.org/wiki/Circumscribed_circle#Cartesian_coordinates

// return a list of fn points in the circular arc starting at p0,
// passing by p1 and ending at p2
function 3points_arc(p0, p1, p2, fn=10) =
    // an alternative expression for D
    // D  = 2 * ( (p1-p0).x * (p2-p0).y - (p1-p0).y * (p2-p0).x )
    let( D  = 2 * cross(p1-p0, (p2-p0)) )
    assert( abs(D)>1e-9, "The 3 points should not be collinear." )
    let(
        Ux     = ( (p2-p0).y*(p1-p0)(p1-p0) - (p1-p0).y(p2-p0)(p2-p0) )/D,
        Uy     = ( (p1-p0).x
(p2-p0)(p2-p0) - (p2-p0).x(p1-p0)(p1-p0) )/D,
        radius = norm([Ux,Uy]),
        center = [Ux,Uy] + p0,
        ang0   = atan2( (p0-center).y, (p0-center).x ),
        ang2   = atan2( (p2-center).y, (p2-center).x ),
        // the points are in a cw winding iff D<0
        // the angular difference between vectors p2-center and p0-center
        // measured from p0-center; dang is positive iff D is negative
        dang   = D<0  ? ang2<ang0 ? ang2-ang0 : ang2-ang0-360
                      : ang2>ang0 ? ang2-ang0 : ang2-ang0+360
    )
    [ for(i=[0:fn-1])
        let( ang = ang0 + i
dang/(fn-1) )
        center + radius*[cos(ang),sin(ang)] ] ;

// Application example

// randomly generate 3 points
seed = floor(rands(0,10000,1)[0]);
echo(seed=seed); // seed allows for case recall
rnds = rands(0,20,6, seed=seed);
pts = [for(i=[0:2:5]) [rnds[i], rnds[i+1]] ];
//pts = [ [10, 49.25], [60.5, 51.5], [101, 49.25]  ];

// draw a polyline connecting the arc points
line(3points_arc(pts[0], pts[1], pts[2], 23), width=.2);

// connect the 3 point path with blue lines
color("blue") line(pts, width=.2);

// mark the start point with a red "dot"
color("red") translate(pts[0]) circle(.35);

// a helper module to trace a 2D or 3D polyline
module line(path, width=1) {
    for(i=[0:len(path)-2]) {
        hull() {
            translate(path[i])   sphere(width/2);
            translate(path[i+1]) sphere(width/2);
        }
    }
}


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

Thanks!Tried to analyze the answer (but, do not see how it will solve my desire) I have 3 points that I want "a line" through to create the 2D object. Points x1=10, y1=49.25 x2=55,5, y2=50,5 x3=101, y3=49,5(right now I do not see the solution) Den fredag 8 april 2022 18:47:59 CEST, Ronaldo Persiano <rcmpersiano@gmail.com> skrev: To find an arc given 3 2D points you may find the intersection point of two lines respectively bisecting the first pair and the last pair of points. However, the reference I have given before makes possible a more concise computation. Here is my version: // based on // https://en.wikipedia.org/wiki/Circumscribed_circle#Cartesian_coordinates // return a list of fn points in the circular arc starting at p0, // passing by p1 and ending at p2 function 3points_arc(p0, p1, p2, fn=10) =     // an alternative expression for D     // D  = 2 * ( (p1-p0).x * (p2-p0).y - (p1-p0).y * (p2-p0).x )     let( D  = 2 * cross(p1-p0, (p2-p0)) )     assert( abs(D)>1e-9, "The 3 points should not be collinear." )     let(         Ux     = ( (p2-p0).y*(p1-p0)*(p1-p0) - (p1-p0).y*(p2-p0)*(p2-p0) )/D,         Uy     = ( (p1-p0).x*(p2-p0)*(p2-p0) - (p2-p0).x*(p1-p0)*(p1-p0) )/D,         radius = norm([Ux,Uy]),         center = [Ux,Uy] + p0,         ang0   = atan2( (p0-center).y, (p0-center).x ),         ang2   = atan2( (p2-center).y, (p2-center).x ),         // the points are in a cw winding iff D<0         // the angular difference between vectors p2-center and p0-center         // measured from p0-center; dang is positive iff D is negative         dang   = D<0  ? ang2<ang0 ? ang2-ang0 : ang2-ang0-360                       : ang2>ang0 ? ang2-ang0 : ang2-ang0+360     )     [ for(i=[0:fn-1])         let( ang = ang0 + i*dang/(fn-1) )         center + radius*[cos(ang),sin(ang)] ] ; // Application example // randomly generate 3 points seed = floor(rands(0,10000,1)[0]); echo(seed=seed); // seed allows for case recall rnds = rands(0,20,6, seed=seed); pts = [for(i=[0:2:5]) [rnds[i], rnds[i+1]] ]; //pts = [ [10, 49.25], [60.5, 51.5], [101, 49.25]  ]; // draw a polyline connecting the arc points line(3points_arc(pts[0], pts[1], pts[2], 23), width=.2); // connect the 3 point path with blue lines color("blue") line(pts, width=.2); // mark the start point with a red "dot" color("red") translate(pts[0]) circle(.35); // a helper module to trace a 2D or 3D polyline module line(path, width=1) {     for(i=[0:len(path)-2]) {         hull() {             translate(path[i])   sphere(width/2);             translate(path[i+1]) sphere(width/2);         }     } } _______________________________________________ OpenSCAD mailing list To unsubscribe send an email to discuss-leave@lists.openscad.org