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+u2rm(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
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 + idang/(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);
}
}
}
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 + idang/(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