discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Transforming an Oval

MM
Michael Möller
Mon, Aug 8, 2022 8:22 PM

y and x if divisible by 4, right?

Michael, fra mobilen

man. 8. aug. 2022 22.12 skrev Father Horton fatherhorton@gmail.com:

My end condition is that the last point calculated is (-L/2, b), but as I
think about it, it does make sense that N has to be a multiple of 2,
because the whole thing has to be symmetrical around the y-axis.

On Mon, Aug 8, 2022 at 2:35 PM Father Horton fatherhorton@gmail.com
wrote:

Here's a Google sheet that shows what I have in mind.
https://docs.google.com/spreadsheets/d/13YOJKkWWfcgZNKVn_nlBtQZ_bbxNvN6SdVv1bVWLDP8/edit?usp=sharing

I have to adjust the signs on the square roots manually, so I didn't
iterate until I got equal lengths, but this is the idea. Blue points are
end points of the circumscribing segments and red points are the tangent
points on the ellipse. I have other things to do at the moment, but I may
revisit later to get the signs to work out right and then see if it will
iterate to an acceptable result.

On Mon, Aug 8, 2022 at 1:31 PM Adrian Mariano avm4@cornell.edu wrote:

The restriction arises because of the end condition.  There are 4 cases
depending on what happens at the four ends of the ellipse (the points where
it intersects the coordinate axes).  The four possibilities are at each end
either a corner or a flat tangent at the end.  Your approach as I
understand it begins with a flat and constructs a quarter of the polygon,
ending with a point.  Such a polygon must have 4k+2 sides.  I do not see
how the end condition can be formulated to end on a flat.  Also I do not
see how it can start on a point.  If n is odd you can start at one end and
go half way around and end on a point. But if n is divisible by 4 you can
have 4 flats or four points and the method cannot produce either of them.
Have I missed something?

On Mon, Aug 8, 2022, 13:42 Father Horton fatherhorton@gmail.com wrote:

I'm not sure why there should be a restriction on N; I think it's
general. I did a spreadsheet that looks like it's doing the right thing in
the first quadrant, but it (or I) gets lost when I have to select the right
value for the sign of the square roots involved as the process enters other
quadrants.

On Sun, Aug 7, 2022 at 9:43 PM Father Horton fatherhorton@gmail.com
wrote:

Google showed me that method when I came up with the right terms. But
it's too late at night for me to try to implement it. Maybe tomorrow.

On Sun, Aug 7, 2022 at 9:41 PM Adrian Mariano avm4@cornell.edu
wrote:

Now I understand your idea.  I think it should be possible to make
that work for the case of N=4k+2.  It does seem like there are some
complications, like you try to extend the segment and the length is closer
than the tangent, so it's impossible.  Also things may be complicated if
the algorithm tries to go around the tip of the ellipse (that is, if the
path is too long).

For finding a tangent to an ellipse, transform the problem to the
circle, solve, and then transform back.  In BOSL2:

function ellipse_tangents(a,b,pt) =
let(
r=a,
scaledpt = yscale(a/b,pt),
tangents = circle_point_tangents(r,[0,0],scaledpt)
)
yscale(b/a,tangents);

On Sun, Aug 7, 2022 at 9:54 PM Father Horton fatherhorton@gmail.com
wrote:

I did that wrong. It's not (0, b) to (0, L/2). It's (0, b) to (L/2,
b). That's always outside the ellipse.

I will look at the second problem as soon as I figure out how to
calculate a tangent line to an ellipse containing a point not on the
ellipse. Google is not helping much.

On Sun, Aug 7, 2022 at 8:32 PM Adrian Mariano avm4@cornell.edu
wrote:

Father Horton,

I'm having trouble understanding your proposed method.  A segment
from (0,b) to (0,L/2) might be inside the ellipse depending on N, and then
there won't be a tangent.

It also sounds like your idea is somewhat similar to Jordan's idea:
basically start at one side and work around the ellipse and see if it
works.  If not, make a correction.  The problem with this idea is that
there are two parameters for the first segment, so how do you make a
correction?  (The two parameters are the location of the endpoint of the
first segment and its length.)

On Sun, Aug 7, 2022 at 5:33 PM Father Horton <
fatherhorton@gmail.com> wrote:

How about this to construct N equal length segments around an
ellipse with axes a and b:

  1. Select an initial segment length estimate (e.g., Ramanujan's
    formula / N) = L
  2. Construct a half-segment from (0, b) to (0, L/2).
  3. Find a line tangent to the ellipse and passing through (0, L/2).
  4. Find the point on the tangent line that is L away from (0, L/2).
  5. Repeat (3) substituting the new point for (0, L/2). until you
    have N segments.

If everything worked perfectly, the last point found would be (0,
-L/2). If there's a gap, increase L and try again. If there's overlap,
decrease L and try again.

On Sun, Aug 7, 2022 at 3:29 PM Ronaldo Persiano <
rcmpersiano@gmail.com> wrote:

Adrian, why to use a (either inscribed or circumscribed) polygon
with equal side as an approximation of an ellipsis? It doesn't seem to be a
good approximation of it. I get a better approximation by taking an angle
uniform sample of the curve in the parameter space.

[image: Uniformly_sampled_ellipsis.png]

Em sáb., 6 de ago. de 2022 às 01:44, Adrian Mariano <
avm4@cornell.edu> escreveu:

Circumscribed means tangents to points on the ellipse.  But
there are no arc lengths (equal or unequal) in this problem, nor equally
spaced angles.  The angles of each segment will be different.  But the
lengths of the segments are not the same as the arc lengths, which is why
arc length does not matter.  Here's a solution to the N=6 polygon sort of
inspired by the idea Jordan suggested, where I adjust the first segment
until the second segment has the right length.  The rest of the solution is
then obtained using symmetry, which means there is only a single unknown
that can simply be solved for.  But this doesn't generalize to higher N.

[image: image.png]
include<BOSL2/std.scad>

// ellipse semiaxes
// If a is much smaller than b it will fail
a=5;
b=2;

// Find point on ellipse at specified x coordinate
function ellipse_pt(a,b,x) = sqrt(b^2*(1-x^2/a^2));

// Find tangent line to ellipse at point (u,w)
// and determine the x value where that line has
// given y value.
function findx(a,b,u,w,y) =
let(
A = -ub^2/w/a^2,
B = w+(u
b)^2/w/a^2
)
(y-B)/A;

// First segment if tangent point is at x=u
function first_seg(a,b,u) =
let(
w = ellipse_pt(a,b,u),
x1 = findx(a,b,u,w,0),
x2 = findx(a,b,u,w,b)
)
[[x1,0],[x2,b]];

err = function (u) let(pt = first_seg(a,b,u))
2*pt[1].x - norm(pt[0]-pt[1]);

x = root_find(err,.2a,.9a);
first = first_seg(a,b,x);
top = concat(first,reverse(xflip(first)));
poly = concat(top, reverse(yflip(list_tail(top))));

stroke(ellipse([a,b]),width=.05,$fn=128,closed=true);
color("red")stroke(poly,width=.05,closed=true);

// Verify equality of segment lengths
echo(path_segment_lengths(poly,closed=true));

On Fri, Aug 5, 2022 at 8:55 PM Sanjeev Prabhakar <
sprabhakar2006@gmail.com> wrote:

Circumscribed means tangents from points on ellipse
How can the tangents from equally spaced arc lengths or equally
spaced angles be equal for an ellipse
You need to change the arc lengths dynamically and also
accurately estimate the segment length which fits the ellipse .

On Sat, 6 Aug, 2022, 4:51 am Adrian Mariano, avm4@cornell.edu
wrote:

Your intuition is incorrect: a circle scaled in one direction
IS an ellipse.  The motivation for being interested in
circumscribing is to make holes, though the constraint of equal length
sides is probably not what you'd want for that purpose.  You can make a
nonuniform circumscribing polygon for an ellipse by simply making a polygon
that circumscribes a circle and scaling it.

On Fri, Aug 5, 2022 at 7:16 PM Bob Carlson bob@rjcarlson.com
wrote:

Seems like I remember Nop Head talking about using
circumscribed holes for screws and even rotating the polygons to produce a
more even hole.

If an ellipse is the nominal shape, the using a circumscribed
polygon for a hole and an inscribed polygon for a solid might make sense.

Btw, can someone confirm my intuition that a circle scaled in
one dimension is not an ellipse?

-Bob
Tucson AZ

On Aug 5, 2022, at 15:38, Adrian Mariano avm4@cornell.edu
wrote:

I don't have a specific need for a circumscribing elliptical
polygon with equal sides.  I was writing code to make ellipses and it
seemed like equal side approximations would be nice, so I solved the case
for inscribed, but couldn't solve the circumscribed case.  So it's an
unsolved puzzle I've got that this discussion reminded me of.

On Fri, Aug 5, 2022 at 6:33 PM nop head nop.head@gmail.com
wrote:

A long discussion but I have to ask why do you need an
elliptical polygon with equal tangential sides?

On Fri, 5 Aug 2022, 21:58 Adrian Mariano, avm4@cornell.edu
wrote:

You think that a circumscribing polygon with equal length
segments does not exist??  I'm skeptical of this claim.

For circumscribed, it's not so hard.  You start with a
uniform-in-angle point distribution, compute the segment lengths, compare
to the mean segment length to get an error, and then compute an adjustment
based on the error.  It converges quickly.

So for example, I have segments lengths of:
ECHO: [5.57297, 5.57297, 5.57297, 5.57297, 5.57297,
5.57297, 5.57297, 5.57297]

Maybe not exactly equal, since tolerance is 1e-9, but
surely good enough.
<image.png>

The code for this is in BOSL2 in shapes2d.scad. A similar
algorithm should exist for the circumscribed case, but as I said, my
efforts to find it have failed.

On Fri, Aug 5, 2022 at 12:44 PM Sanjeev Prabhakar <
sprabhakar2006@gmail.com> wrote:

I think circumscribed polygon segments cannot be equal
lengths.
inscribed ones may be approximately equal, but would be a
very tough problem to solve.
I tried something.

On Thu, 4 Aug 2022 at 05:44, Adrian Mariano <
avm4@cornell.edu> wrote:

I think you need to be a little careful about defining
what you want to do.  If you want to approximate an ellipse with points
that are distributed uniformly over the ellipse, that could be done by
approximating the arc length of the ellipse to find the necessary
points---e.g. advance distance d along the ellipse at each step.  But if
you want to approximate an ellipse with a polygon with equal length sides,
that approach does not do it, because the length of the segments will not
be constant as the span sections of the ellipse with differing curvature.
And since the perimeter of the desired polygon is unknown, you can't just
step it out analogously.  The circle doesn't present this challenge due to
having constant curvature.

On Wed, Aug 3, 2022 at 7:41 PM Father Horton <
fatherhorton@gmail.com> wrote:

I think our emails crossed. I was addressing how to
approximate an ellipse with constant-length segments in general, not how to
solve your problem. When I had to do something similar, I used polar
coordinates and stepped up the value of theta until the distance from the
previous point was correct. (In the constant-length version, I'd keep a
running total of the maximum desired length so that round-off errors don't
accumulate.)

Figuring out the circumscribed polygon is, as you note,
a greater challenge. I can visualize how to do it for n = 4, but it doesn't
extrapolate at all.

On Tue, Aug 2, 2022 at 10:10 PM Adrian Mariano <
avm4@cornell.edu> wrote:

Eh, there's no such thing as "brute force" in this
situation.  Step through what with sufficiently small steps?  Of course
an iterative algorithm is necessary.  This is true for most interesting
problems.  No big deal.  Show me an iterative algorithm that converges to
the circumscribing polygon.  When I tried to devise such an algorithm I
couldn't find one that would converge.  Writing an algorithm that would
converge to the inscribed polygon seemed to be straight forward.  Note
also that computing arc length of the ellipse doesn't really help here.
You can do that by solving an elliptical integral, or summing up small
segments.  But what's the connection between arc length of the ellipse and
a circumscribing polygon with equal segment lengths?  If there's a
connection, I don't see it.

On Tue, Aug 2, 2022 at 10:56 PM Father Horton <
fatherhorton@gmail.com> wrote:

Except by brute force (step through it with
sufficiently small steps), it’s not possible because there’s no closed form
expression for the distance between two points on a general ellipse (as
opposed to special cases like a circle).

On Tue, Aug 2, 2022 at 9:50 PM Adrian Mariano <
avm4@cornell.edu> wrote:

Here's a challenge for you:  draw an "ellipse"
polygon with N segments that are all the same length that circumscribes a
perfect ellipse with given semiaxes a and b.  I tried to solve this problem
and could not find a solution.  I can draw an inscribed N segment
"ellipse" polygon with all segments the same length---though it's not
easy---but the circumscribed case eludes me.  I think of the inscribed
case as, every vertex is located on the ellipse and the circumscribed case,
every segment is tangent to the ellipse

On Tue, Aug 2, 2022 at 10:36 PM Sanjeev Prabhakar <
sprabhakar2006@gmail.com> wrote:

In openscad drawing a ellipse is not too difficult
Refer following code

function to draw an ellipse with semi-major and
semi-minor axis "r1" and "r2" respectively and with center "cp" and number
of segment "s"
/
// example:
// sec=ellipse(r1=5,r2=3,cp=[2,3],s=30);

function ellipse(r1,r2,cp,s=30)=
let(

sec=[for(i=[0:360/s:360-360/s])cp+[r1cos(i),r2sin(i)]]
)sec;

On Wed, 3 Aug, 2022, 5:35 am Jordan Brown, <
openscad@jordan.maileater.net> wrote:

On 8/2/2022 4:46 PM, Brian Allen wrote:

I created an oval using:
inMm = 25.4;
fullW = 35.5 * inMm;
fullL = 54.5 * inMm;
resize([fullW, fullL, 1])
circle(d=fullW);

Tip:  use scale() rather than resize(); it previews
faster in complicated cases.

It's the right size in the middle (35.5" wide at 50% of the length), but 25% along the length it's not quite as wide as I need it (it's 31.5" and I need it about 32"). If you can see the attached image I'm trying to make the yellow oval match the red "sanity check" lines. I'm trying to match the size and shape of an existing oval in the real world.

You're taking a circle and stretching it; the
result of that stretching is an ellipse.

I'm not 100% sure - maybe one of the real math
wizards can chime in - but I think the shape you are asking for would not
be an ellipse.

I believe that an ellipse is fully defined by its
major (long) and minor (short) axis dimensions; the other parts of the
curve mathematically flow from those two measurements.

You can make something else, but you can't make it
using this technique.

Is there a way to stretch this in OpenSCAD? In a GUI vector graphics program I'd use a bézier curve and drag the handle to get 1/4 of it just right then mirror it in X and Y to get the oval I needed.

You can use a Bézier function.

Using BOSL2:
https://github.com/revarbat/BOSL2/wiki/Topics#bezier-curves

DIY, here's a function that I cobbled together some
years ago:

// Bezier functions from https://www.thingiverse.com/thing:8443
// but that yielded either single points or a raft of triangles;
// this yields a vector of points that you can then concatenate
// with other pieces to form a single polygon.
// If we were really clever, I think it would be possible to
// automatically space the output points based on how linear
// the curve is at that point.  But right now I'm not that clever.
function BEZ03(u) = pow((1-u), 3);
function BEZ13(u) = 3u(pow((1-u),2));
function BEZ23(u) = 3*(pow(u,2))*(1-u);
function BEZ33(u) = pow(u,3);

function PointAlongBez4(p0, p1, p2, p3, u) = [
BEZ03(u)*p0[0]+BEZ13(u)*p1[0]+BEZ23(u)*p2[0]+BEZ33(u)*p3[0],
BEZ03(u)*p0[1]+BEZ13(u)*p1[1]+BEZ23(u)*p2[1]+BEZ33(u)*p3[1]];

// p0 - start point
// p1 - control point 1, line departs p0 headed this way
// p2 - control point 2, line arrives at p3 from this way
// p3 - end point
// segs - number of segments
function bez(p0, p1, p2, p3, segs) = [
for (i = [0:segs]) PointAlongBez4(p0, p1, p2, p3, i/segs)
];

It is that final function bez() that I actually
call, e.g.

polygon(bez([0,0], [0,4], [5,1], [7,0], 20));

often concatenating the results of several bez()
calls together.

Note that the four coordinates correspond to the
coordinates of the control points in a GUI drawing program:  the start
point, control point associated with the start, the control point
associated with the end, and the end point.  I have sometimes created
OpenSCAD objects by tracing an object in a drawing program and then reading
off the coordinates of the various control points.

Note that Bézier functions are not the only
mathematical curves.  (For instance, they cannot exactly match an arc of a
circle.)  I'm sure there are numerous other functions that also produce
curves.


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


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


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


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


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


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


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


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

y and x if divisible by 4, right? Michael, fra mobilen man. 8. aug. 2022 22.12 skrev Father Horton <fatherhorton@gmail.com>: > My end condition is that the last point calculated is (-L/2, b), but as I > think about it, it does make sense that N has to be a multiple of 2, > because the whole thing has to be symmetrical around the y-axis. > > On Mon, Aug 8, 2022 at 2:35 PM Father Horton <fatherhorton@gmail.com> > wrote: > >> Here's a Google sheet that shows what I have in mind. >> https://docs.google.com/spreadsheets/d/13YOJKkWWfcgZNKVn_nlBtQZ_bbxNvN6SdVv1bVWLDP8/edit?usp=sharing >> >> I have to adjust the signs on the square roots manually, so I didn't >> iterate until I got equal lengths, but this is the idea. Blue points are >> end points of the circumscribing segments and red points are the tangent >> points on the ellipse. I have other things to do at the moment, but I may >> revisit later to get the signs to work out right and then see if it will >> iterate to an acceptable result. >> >> On Mon, Aug 8, 2022 at 1:31 PM Adrian Mariano <avm4@cornell.edu> wrote: >> >>> The restriction arises because of the end condition. There are 4 cases >>> depending on what happens at the four ends of the ellipse (the points where >>> it intersects the coordinate axes). The four possibilities are at each end >>> either a corner or a flat tangent at the end. Your approach as I >>> understand it begins with a flat and constructs a quarter of the polygon, >>> ending with a point. Such a polygon must have 4k+2 sides. I do not see >>> how the end condition can be formulated to end on a flat. Also I do not >>> see how it can start on a point. If n is odd you can start at one end and >>> go half way around and end on a point. But if n is divisible by 4 you can >>> have 4 flats or four points and the method cannot produce either of them. >>> Have I missed something? >>> >>> >>> On Mon, Aug 8, 2022, 13:42 Father Horton <fatherhorton@gmail.com> wrote: >>> >>>> I'm not sure why there should be a restriction on N; I think it's >>>> general. I did a spreadsheet that looks like it's doing the right thing in >>>> the first quadrant, but it (or I) gets lost when I have to select the right >>>> value for the sign of the square roots involved as the process enters other >>>> quadrants. >>>> >>>> On Sun, Aug 7, 2022 at 9:43 PM Father Horton <fatherhorton@gmail.com> >>>> wrote: >>>> >>>>> Google showed me that method when I came up with the right terms. But >>>>> it's too late at night for me to try to implement it. Maybe tomorrow. >>>>> >>>>> On Sun, Aug 7, 2022 at 9:41 PM Adrian Mariano <avm4@cornell.edu> >>>>> wrote: >>>>> >>>>>> Now I understand your idea. I think it should be possible to make >>>>>> that work for the case of N=4k+2. It does seem like there are some >>>>>> complications, like you try to extend the segment and the length is closer >>>>>> than the tangent, so it's impossible. Also things may be complicated if >>>>>> the algorithm tries to go around the tip of the ellipse (that is, if the >>>>>> path is too long). >>>>>> >>>>>> For finding a tangent to an ellipse, transform the problem to the >>>>>> circle, solve, and then transform back. In BOSL2: >>>>>> >>>>>> function ellipse_tangents(a,b,pt) = >>>>>> let( >>>>>> r=a, >>>>>> scaledpt = yscale(a/b,pt), >>>>>> tangents = circle_point_tangents(r,[0,0],scaledpt) >>>>>> ) >>>>>> yscale(b/a,tangents); >>>>>> >>>>>> On Sun, Aug 7, 2022 at 9:54 PM Father Horton <fatherhorton@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> I did that wrong. It's not (0, b) to (0, L/2). It's (0, b) to (L/2, >>>>>>> b). That's always outside the ellipse. >>>>>>> >>>>>>> I will look at the second problem as soon as I figure out how to >>>>>>> calculate a tangent line to an ellipse containing a point not on the >>>>>>> ellipse. Google is not helping much. >>>>>>> >>>>>>> On Sun, Aug 7, 2022 at 8:32 PM Adrian Mariano <avm4@cornell.edu> >>>>>>> wrote: >>>>>>> >>>>>>>> Father Horton, >>>>>>>> >>>>>>>> I'm having trouble understanding your proposed method. A segment >>>>>>>> from (0,b) to (0,L/2) might be inside the ellipse depending on N, and then >>>>>>>> there won't be a tangent. >>>>>>>> >>>>>>>> It also sounds like your idea is somewhat similar to Jordan's idea: >>>>>>>> basically start at one side and work around the ellipse and see if it >>>>>>>> works. If not, make a correction. The problem with this idea is that >>>>>>>> there are two parameters for the first segment, so how do you make a >>>>>>>> correction? (The two parameters are the location of the endpoint of the >>>>>>>> first segment and its length.) >>>>>>>> >>>>>>>> On Sun, Aug 7, 2022 at 5:33 PM Father Horton < >>>>>>>> fatherhorton@gmail.com> wrote: >>>>>>>> >>>>>>>>> How about this to construct N equal length segments around an >>>>>>>>> ellipse with axes a and b: >>>>>>>>> >>>>>>>>> 1) Select an initial segment length estimate (e.g., Ramanujan's >>>>>>>>> formula / N) = L >>>>>>>>> 2) Construct a half-segment from (0, b) to (0, L/2). >>>>>>>>> 3) Find a line tangent to the ellipse and passing through (0, L/2). >>>>>>>>> 3) Find the point on the tangent line that is L away from (0, L/2). >>>>>>>>> 4) Repeat (3) substituting the new point for (0, L/2). until you >>>>>>>>> have N segments. >>>>>>>>> >>>>>>>>> If everything worked perfectly, the last point found would be (0, >>>>>>>>> -L/2). If there's a gap, increase L and try again. If there's overlap, >>>>>>>>> decrease L and try again. >>>>>>>>> >>>>>>>>> On Sun, Aug 7, 2022 at 3:29 PM Ronaldo Persiano < >>>>>>>>> rcmpersiano@gmail.com> wrote: >>>>>>>>> >>>>>>>>>> Adrian, why to use a (either inscribed or circumscribed) polygon >>>>>>>>>> with equal side as an approximation of an ellipsis? It doesn't seem to be a >>>>>>>>>> good approximation of it. I get a better approximation by taking an angle >>>>>>>>>> uniform sample of the curve in the parameter space. >>>>>>>>>> >>>>>>>>>> [image: Uniformly_sampled_ellipsis.png] >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Em sáb., 6 de ago. de 2022 às 01:44, Adrian Mariano < >>>>>>>>>> avm4@cornell.edu> escreveu: >>>>>>>>>> >>>>>>>>>>> Circumscribed means tangents to points on the ellipse. But >>>>>>>>>>> there are no arc lengths (equal or unequal) in this problem, nor equally >>>>>>>>>>> spaced angles. The angles of each segment will be different. But the >>>>>>>>>>> lengths of the segments are not the same as the arc lengths, which is why >>>>>>>>>>> arc length does not matter. Here's a solution to the N=6 polygon sort of >>>>>>>>>>> inspired by the idea Jordan suggested, where I adjust the first segment >>>>>>>>>>> until the second segment has the right length. The rest of the solution is >>>>>>>>>>> then obtained using symmetry, which means there is only a single unknown >>>>>>>>>>> that can simply be solved for. But this doesn't generalize to higher N. >>>>>>>>>>> >>>>>>>>>>> [image: image.png] >>>>>>>>>>> include<BOSL2/std.scad> >>>>>>>>>>> >>>>>>>>>>> // ellipse semiaxes >>>>>>>>>>> // If a is much smaller than b it will fail >>>>>>>>>>> a=5; >>>>>>>>>>> b=2; >>>>>>>>>>> >>>>>>>>>>> // Find point on ellipse at specified x coordinate >>>>>>>>>>> function ellipse_pt(a,b,x) = sqrt(b^2*(1-x^2/a^2)); >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> // Find tangent line to ellipse at point (u,w) >>>>>>>>>>> // and determine the x value where that line has >>>>>>>>>>> // given y value. >>>>>>>>>>> function findx(a,b,u,w,y) = >>>>>>>>>>> let( >>>>>>>>>>> A = -u*b^2/w/a^2, >>>>>>>>>>> B = w+(u*b)^2/w/a^2 >>>>>>>>>>> ) >>>>>>>>>>> (y-B)/A; >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> // First segment if tangent point is at x=u >>>>>>>>>>> function first_seg(a,b,u) = >>>>>>>>>>> let( >>>>>>>>>>> w = ellipse_pt(a,b,u), >>>>>>>>>>> x1 = findx(a,b,u,w,0), >>>>>>>>>>> x2 = findx(a,b,u,w,b) >>>>>>>>>>> ) >>>>>>>>>>> [[x1,0],[x2,b]]; >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> err = function (u) let(pt = first_seg(a,b,u)) >>>>>>>>>>> 2*pt[1].x - norm(pt[0]-pt[1]); >>>>>>>>>>> >>>>>>>>>>> x = root_find(err,.2*a,.9*a); >>>>>>>>>>> first = first_seg(a,b,x); >>>>>>>>>>> top = concat(first,reverse(xflip(first))); >>>>>>>>>>> poly = concat(top, reverse(yflip(list_tail(top)))); >>>>>>>>>>> >>>>>>>>>>> stroke(ellipse([a,b]),width=.05,$fn=128,closed=true); >>>>>>>>>>> color("red")stroke(poly,width=.05,closed=true); >>>>>>>>>>> >>>>>>>>>>> // Verify equality of segment lengths >>>>>>>>>>> echo(path_segment_lengths(poly,closed=true)); >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On Fri, Aug 5, 2022 at 8:55 PM Sanjeev Prabhakar < >>>>>>>>>>> sprabhakar2006@gmail.com> wrote: >>>>>>>>>>> >>>>>>>>>>>> Circumscribed means tangents from points on ellipse >>>>>>>>>>>> How can the tangents from equally spaced arc lengths or equally >>>>>>>>>>>> spaced angles be equal for an ellipse >>>>>>>>>>>> You need to change the arc lengths dynamically and also >>>>>>>>>>>> accurately estimate the segment length which fits the ellipse . >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Sat, 6 Aug, 2022, 4:51 am Adrian Mariano, <avm4@cornell.edu> >>>>>>>>>>>> wrote: >>>>>>>>>>>> >>>>>>>>>>>>> Your intuition is incorrect: a circle scaled in one direction >>>>>>>>>>>>> *IS* an ellipse. The motivation for being interested in >>>>>>>>>>>>> circumscribing is to make holes, though the constraint of equal length >>>>>>>>>>>>> sides is probably not what you'd want for that purpose. You can make a >>>>>>>>>>>>> nonuniform circumscribing polygon for an ellipse by simply making a polygon >>>>>>>>>>>>> that circumscribes a circle and scaling it. >>>>>>>>>>>>> >>>>>>>>>>>>> On Fri, Aug 5, 2022 at 7:16 PM Bob Carlson <bob@rjcarlson.com> >>>>>>>>>>>>> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> Seems like I remember Nop Head talking about using >>>>>>>>>>>>>> circumscribed holes for screws and even rotating the polygons to produce a >>>>>>>>>>>>>> more even hole. >>>>>>>>>>>>>> >>>>>>>>>>>>>> If an ellipse is the nominal shape, the using a circumscribed >>>>>>>>>>>>>> polygon for a hole and an inscribed polygon for a solid might make sense. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Btw, can someone confirm my intuition that a circle scaled in >>>>>>>>>>>>>> one dimension is not an ellipse? >>>>>>>>>>>>>> >>>>>>>>>>>>>> -Bob >>>>>>>>>>>>>> Tucson AZ >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On Aug 5, 2022, at 15:38, Adrian Mariano <avm4@cornell.edu> >>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> I don't have a specific need for a circumscribing elliptical >>>>>>>>>>>>>> polygon with equal sides. I was writing code to make ellipses and it >>>>>>>>>>>>>> seemed like equal side approximations would be nice, so I solved the case >>>>>>>>>>>>>> for inscribed, but couldn't solve the circumscribed case. So it's an >>>>>>>>>>>>>> unsolved puzzle I've got that this discussion reminded me of. >>>>>>>>>>>>>> >>>>>>>>>>>>>> On Fri, Aug 5, 2022 at 6:33 PM nop head <nop.head@gmail.com> >>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>>> A long discussion but I have to ask why do you need an >>>>>>>>>>>>>>> elliptical polygon with equal tangential sides? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Fri, 5 Aug 2022, 21:58 Adrian Mariano, <avm4@cornell.edu> >>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> You think that a circumscribing polygon with equal length >>>>>>>>>>>>>>>> segments does not exist?? I'm skeptical of this claim. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> For circumscribed, it's not so hard. You start with a >>>>>>>>>>>>>>>> uniform-in-angle point distribution, compute the segment lengths, compare >>>>>>>>>>>>>>>> to the mean segment length to get an error, and then compute an adjustment >>>>>>>>>>>>>>>> based on the error. It converges quickly. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> So for example, I have segments lengths of: >>>>>>>>>>>>>>>> ECHO: [5.57297, 5.57297, 5.57297, 5.57297, 5.57297, >>>>>>>>>>>>>>>> 5.57297, 5.57297, 5.57297] >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Maybe not exactly equal, since tolerance is 1e-9, but >>>>>>>>>>>>>>>> surely good enough. >>>>>>>>>>>>>>>> <image.png> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The code for this is in BOSL2 in shapes2d.scad. A similar >>>>>>>>>>>>>>>> algorithm should exist for the circumscribed case, but as I said, my >>>>>>>>>>>>>>>> efforts to find it have failed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On Fri, Aug 5, 2022 at 12:44 PM Sanjeev Prabhakar < >>>>>>>>>>>>>>>> sprabhakar2006@gmail.com> wrote: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I think circumscribed polygon segments cannot be equal >>>>>>>>>>>>>>>>> lengths. >>>>>>>>>>>>>>>>> inscribed ones may be approximately equal, but would be a >>>>>>>>>>>>>>>>> very tough problem to solve. >>>>>>>>>>>>>>>>> I tried something. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On Thu, 4 Aug 2022 at 05:44, Adrian Mariano < >>>>>>>>>>>>>>>>> avm4@cornell.edu> wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I think you need to be a little careful about defining >>>>>>>>>>>>>>>>>> what you want to do. If you want to approximate an ellipse with points >>>>>>>>>>>>>>>>>> that are distributed uniformly over the ellipse, that could be done by >>>>>>>>>>>>>>>>>> approximating the arc length of the ellipse to find the necessary >>>>>>>>>>>>>>>>>> points---e.g. advance distance d along the ellipse at each step. But if >>>>>>>>>>>>>>>>>> you want to approximate an ellipse with a polygon with equal length sides, >>>>>>>>>>>>>>>>>> that approach does not do it, because the length of the segments will not >>>>>>>>>>>>>>>>>> be constant as the span sections of the ellipse with differing curvature. >>>>>>>>>>>>>>>>>> And since the perimeter of the desired polygon is unknown, you can't just >>>>>>>>>>>>>>>>>> step it out analogously. The circle doesn't present this challenge due to >>>>>>>>>>>>>>>>>> having constant curvature. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On Wed, Aug 3, 2022 at 7:41 PM Father Horton < >>>>>>>>>>>>>>>>>> fatherhorton@gmail.com> wrote: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I think our emails crossed. I was addressing how to >>>>>>>>>>>>>>>>>>> approximate an ellipse with constant-length segments in general, not how to >>>>>>>>>>>>>>>>>>> solve your problem. When I had to do something similar, I used polar >>>>>>>>>>>>>>>>>>> coordinates and stepped up the value of theta until the distance from the >>>>>>>>>>>>>>>>>>> previous point was correct. (In the constant-length version, I'd keep a >>>>>>>>>>>>>>>>>>> running total of the maximum desired length so that round-off errors don't >>>>>>>>>>>>>>>>>>> accumulate.) >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Figuring out the circumscribed polygon is, as you note, >>>>>>>>>>>>>>>>>>> a greater challenge. I can visualize how to do it for n = 4, but it doesn't >>>>>>>>>>>>>>>>>>> extrapolate at all. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 10:10 PM Adrian Mariano < >>>>>>>>>>>>>>>>>>> avm4@cornell.edu> wrote: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Eh, there's no such thing as "brute force" in this >>>>>>>>>>>>>>>>>>>> situation. Step through *what* with sufficiently small steps? Of course >>>>>>>>>>>>>>>>>>>> an iterative algorithm is necessary. This is true for most interesting >>>>>>>>>>>>>>>>>>>> problems. No big deal. Show me an iterative algorithm that converges to >>>>>>>>>>>>>>>>>>>> the circumscribing polygon. When I tried to devise such an algorithm I >>>>>>>>>>>>>>>>>>>> couldn't find one that would converge. Writing an algorithm that would >>>>>>>>>>>>>>>>>>>> converge to the *inscribed* polygon seemed to be straight forward. Note >>>>>>>>>>>>>>>>>>>> also that computing arc length of the ellipse doesn't really help here. >>>>>>>>>>>>>>>>>>>> You can do that by solving an elliptical integral, or summing up small >>>>>>>>>>>>>>>>>>>> segments. But what's the connection between arc length of the ellipse and >>>>>>>>>>>>>>>>>>>> a circumscribing polygon with equal segment lengths? If there's a >>>>>>>>>>>>>>>>>>>> connection, I don't see it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 10:56 PM Father Horton < >>>>>>>>>>>>>>>>>>>> fatherhorton@gmail.com> wrote: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Except by brute force (step through it with >>>>>>>>>>>>>>>>>>>>> sufficiently small steps), it’s not possible because there’s no closed form >>>>>>>>>>>>>>>>>>>>> expression for the distance between two points on a general ellipse (as >>>>>>>>>>>>>>>>>>>>> opposed to special cases like a circle). >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 9:50 PM Adrian Mariano < >>>>>>>>>>>>>>>>>>>>> avm4@cornell.edu> wrote: >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Here's a challenge for you: draw an "ellipse" >>>>>>>>>>>>>>>>>>>>>> polygon with N segments that are all the same length that circumscribes a >>>>>>>>>>>>>>>>>>>>>> perfect ellipse with given semiaxes a and b. I tried to solve this problem >>>>>>>>>>>>>>>>>>>>>> and could not find a solution. I can draw an *inscribed* N segment >>>>>>>>>>>>>>>>>>>>>> "ellipse" polygon with all segments the same length---though it's not >>>>>>>>>>>>>>>>>>>>>> easy---but the circumscribed case eludes me. I think of the inscribed >>>>>>>>>>>>>>>>>>>>>> case as, every vertex is located on the ellipse and the circumscribed case, >>>>>>>>>>>>>>>>>>>>>> every segment is tangent to the ellipse >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 10:36 PM Sanjeev Prabhakar < >>>>>>>>>>>>>>>>>>>>>> sprabhakar2006@gmail.com> wrote: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In openscad drawing a ellipse is not too difficult >>>>>>>>>>>>>>>>>>>>>>> Refer following code >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> function to draw an ellipse with semi-major and >>>>>>>>>>>>>>>>>>>>>>> semi-minor axis "r1" and "r2" respectively and with center "cp" and number >>>>>>>>>>>>>>>>>>>>>>> of segment "s" >>>>>>>>>>>>>>>>>>>>>>> / >>>>>>>>>>>>>>>>>>>>>>> // example: >>>>>>>>>>>>>>>>>>>>>>> // sec=ellipse(r1=5,r2=3,cp=[2,3],s=30); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> function ellipse(r1,r2,cp,s=30)= >>>>>>>>>>>>>>>>>>>>>>> let( >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> sec=[for(i=[0:360/s:360-360/s])cp+[r1*cos(i),r2*sin(i)]] >>>>>>>>>>>>>>>>>>>>>>> )sec; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On Wed, 3 Aug, 2022, 5:35 am Jordan Brown, < >>>>>>>>>>>>>>>>>>>>>>> openscad@jordan.maileater.net> wrote: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 8/2/2022 4:46 PM, Brian Allen wrote: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I created an oval using: >>>>>>>>>>>>>>>>>>>>>>>> inMm = 25.4; >>>>>>>>>>>>>>>>>>>>>>>> fullW = 35.5 * inMm; >>>>>>>>>>>>>>>>>>>>>>>> fullL = 54.5 * inMm; >>>>>>>>>>>>>>>>>>>>>>>> resize([fullW, fullL, 1]) >>>>>>>>>>>>>>>>>>>>>>>> circle(d=fullW); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Tip: use scale() rather than resize(); it previews >>>>>>>>>>>>>>>>>>>>>>>> faster in complicated cases. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> It's the right size in the middle (35.5" wide at 50% of the length), but 25% along the length it's not quite as wide as I need it (it's 31.5" and I need it about 32"). If you can see the attached image I'm trying to make the yellow oval match the red "sanity check" lines. I'm trying to match the size and shape of an existing oval in the real world. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You're taking a circle and stretching it; the >>>>>>>>>>>>>>>>>>>>>>>> result of that stretching is an ellipse. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I'm not 100% sure - maybe one of the real math >>>>>>>>>>>>>>>>>>>>>>>> wizards can chime in - but I think the shape you are asking for would not >>>>>>>>>>>>>>>>>>>>>>>> be an ellipse. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I believe that an ellipse is fully defined by its >>>>>>>>>>>>>>>>>>>>>>>> major (long) and minor (short) axis dimensions; the other parts of the >>>>>>>>>>>>>>>>>>>>>>>> curve mathematically flow from those two measurements. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You can make something else, but you can't make it >>>>>>>>>>>>>>>>>>>>>>>> using this technique. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Is there a way to stretch this in OpenSCAD? In a GUI vector graphics program I'd use a bézier curve and drag the handle to get 1/4 of it just right then mirror it in X and Y to get the oval I needed. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You can use a Bézier function. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Using BOSL2: >>>>>>>>>>>>>>>>>>>>>>>> https://github.com/revarbat/BOSL2/wiki/Topics#bezier-curves >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> DIY, here's a function that I cobbled together some >>>>>>>>>>>>>>>>>>>>>>>> years ago: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> // Bezier functions from https://www.thingiverse.com/thing:8443 >>>>>>>>>>>>>>>>>>>>>>>> // but that yielded either single points or a raft of triangles; >>>>>>>>>>>>>>>>>>>>>>>> // this yields a vector of points that you can then concatenate >>>>>>>>>>>>>>>>>>>>>>>> // with other pieces to form a single polygon. >>>>>>>>>>>>>>>>>>>>>>>> // If we were really clever, I think it would be possible to >>>>>>>>>>>>>>>>>>>>>>>> // automatically space the output points based on how linear >>>>>>>>>>>>>>>>>>>>>>>> // the curve is at that point. But right now I'm not that clever. >>>>>>>>>>>>>>>>>>>>>>>> function BEZ03(u) = pow((1-u), 3); >>>>>>>>>>>>>>>>>>>>>>>> function BEZ13(u) = 3*u*(pow((1-u),2)); >>>>>>>>>>>>>>>>>>>>>>>> function BEZ23(u) = 3*(pow(u,2))*(1-u); >>>>>>>>>>>>>>>>>>>>>>>> function BEZ33(u) = pow(u,3); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> function PointAlongBez4(p0, p1, p2, p3, u) = [ >>>>>>>>>>>>>>>>>>>>>>>> BEZ03(u)*p0[0]+BEZ13(u)*p1[0]+BEZ23(u)*p2[0]+BEZ33(u)*p3[0], >>>>>>>>>>>>>>>>>>>>>>>> BEZ03(u)*p0[1]+BEZ13(u)*p1[1]+BEZ23(u)*p2[1]+BEZ33(u)*p3[1]]; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> // p0 - start point >>>>>>>>>>>>>>>>>>>>>>>> // p1 - control point 1, line departs p0 headed this way >>>>>>>>>>>>>>>>>>>>>>>> // p2 - control point 2, line arrives at p3 from this way >>>>>>>>>>>>>>>>>>>>>>>> // p3 - end point >>>>>>>>>>>>>>>>>>>>>>>> // segs - number of segments >>>>>>>>>>>>>>>>>>>>>>>> function bez(p0, p1, p2, p3, segs) = [ >>>>>>>>>>>>>>>>>>>>>>>> for (i = [0:segs]) PointAlongBez4(p0, p1, p2, p3, i/segs) >>>>>>>>>>>>>>>>>>>>>>>> ]; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> It is that final function bez() that I actually >>>>>>>>>>>>>>>>>>>>>>>> call, e.g. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> polygon(bez([0,0], [0,4], [5,1], [7,0], 20)); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> often concatenating the results of several bez() >>>>>>>>>>>>>>>>>>>>>>>> calls together. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Note that the four coordinates correspond to the >>>>>>>>>>>>>>>>>>>>>>>> coordinates of the control points in a GUI drawing program: the start >>>>>>>>>>>>>>>>>>>>>>>> point, control point associated with the start, the control point >>>>>>>>>>>>>>>>>>>>>>>> associated with the end, and the end point. I have sometimes created >>>>>>>>>>>>>>>>>>>>>>>> OpenSCAD objects by tracing an object in a drawing program and then reading >>>>>>>>>>>>>>>>>>>>>>>> off the coordinates of the various control points. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Note that Bézier functions are not the only >>>>>>>>>>>>>>>>>>>>>>>> mathematical curves. (For instance, they cannot exactly match an arc of a >>>>>>>>>>>>>>>>>>>>>>>> circle.) I'm sure there are numerous other functions that also produce >>>>>>>>>>>>>>>>>>>>>>>> curves. >>>>>>>>>>>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>> >>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>> 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 >>>>>>>>>>> >>>>>>>>>> _______________________________________________ >>>>>>>>>> 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 >>>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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 >>>> >>> _______________________________________________ >>> 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 >
FH
Father Horton
Mon, Aug 8, 2022 8:29 PM

On Mon, Aug 8, 2022 at 3:23 PM Michael Möller private2michael@gmail.com
wrote:

y and x if divisible by 4, right?

Right, which would make calculation easier since I wouldn't have to deal
with those nasty quadrant changes.

On Mon, Aug 8, 2022 at 3:23 PM Michael Möller <private2michael@gmail.com> wrote: > y and x if divisible by 4, right? > Right, which would make calculation easier since I wouldn't have to deal with those nasty quadrant changes.
FH
Father Horton
Mon, Aug 8, 2022 8:39 PM

The spreadsheet now has a working 12-sided example (length picked by trial
and error).

The spreadsheet now has a working 12-sided example (length picked by trial and error). >
AM
Adrian Mariano
Mon, Aug 8, 2022 8:40 PM

So I hate spreadsheets and it's too hard to decipher what you've done by
looking at the spread sheet.  I actually coded this up myself in OpenSCAD
And if there's a way to handle the N divisible by 4 case, I am not seeing
it.  For the N=4k+2 case you start at [b,L/2] and work your way around
clockwise and place the segments to make a quarter-ellipse polygon.
Assuming you're length estimate isn't terrible you'll place all the
segments but end up slightly above/below the X axis.  Based on how big the
vertical error is, you update the length and iterate to get a solution.

That produces a result that looks like this once you rotate and reflect to
get a full ellipse instead of just a 1/4 ellipse:

[image: image.png]
Notice how the polygon has a flat segment on top but is pointy on the
right?

If N is odd then you start at [-a,L/2] and work your way clockwise around
the ellipse, and then end with the same constraint.  In this case there is
less symmetry and you have to build a half-ellipse.
[image: image.png]
I made the ellipse fatter because otherwise the side segments appear
coplanar.  So here we have started on the left with a "flat" segment and
ended a half-ellipse on the right at a corner.

There are two other cases that arise for N divisible by 4 where we start
and end on a point or a flat.  Starting on a point is problematic because
you have an extra parameter of how far away from the ellipse to put the
point.  And ending on a flat is problematic because you have a target that
is two-dimensional, e.g. [a,L/2] and it's no longer apparent how to modify
the length to guarantee an improvement.  If you and up [.1,.1] away from
the target...what should you do?  Presumably this could be handled by
using a multi-dimensional optimization solver, but I don't have one of
those for OpenSCAD and it does seem kind of like overkill.

Here's the code:

include<BOSL2/std.scad>

function ellipse_tangents(a,b,pt) =
let(
r=a,
scaledpt = yscale(a/b,pt),
tangents = circle_point_tangents(r,[0,0],scaledpt)
)
yscale(b/a,tangents);

function ellipse_next_pt(a,b,pt,L) =
let(
tanglist = ellipse_tangents(a,b,pt),
//f=echo(pt=pt,tanglist=tanglist),
tang = tanglist[0].x>pt.x ? tanglist[0]
: len(tanglist)==2 && tanglist[1].x>pt.x ? tanglist[1]
: assert(false,"cannot find acceptable tangent")
)
assert(norm(tang-pt)<L,"Tangent is too far away")
L*unit(tang-pt)+pt;

function ellipse_path(a,b,L,N,path=[]) =
len(path)==0 ? ellipse_path(a,b,L,N,[[L/2,b]])
: len(path)==N ? path
: last(path).y<=0 ? path
: last(path).x>=a ? path
: ellipse_path(a,b,L,N,
[each path, ellipse_next_pt(a,b,last(path),L)]);

function ellipse_circ(a,b) = PI*(3*(a+b) - sqrt(10ab+3*(a^2+b^2)));

function cellipse(a,b,N) =
assert(N%4==2, "Must have N of form 4k+2")
let(
errfunc = function(L) let(path=(ellipse_path(a,b,L,(N+2)/4)))
-last(path).y+
((N+2)/4 - len(path)) * b ,
lengthguess = ellipse_circ(a,b)/N,
L = root_find(errfunc, 0.95lengthguess, 1.5lengthguess),
path = ellipse_path(a,b,L,(N+2)/4),
right = concat(path, yflip(list_tail(reverse(path))))
)
concat(right, reverse(xflip(right)));

function cellipse_odd(a,b,N) =
assert(N%2==1, "Must have N of form 2k+1")
let(
errfunc = function(L)
let(path=ellipse_path(a,b,L,(N+1)/2,[[-a,L/2]]))
-last(path).y+
((N+1)/2 - len(path)) * b ,
lengthguess = ellipse_circ(a,b)/N,
L = root_find(errfunc, 0.95lengthguess, 1.5lengthguess),
path = ellipse_path(a,b,L,(N+1)/2,[[-a,L/2]])
)
concat(path, list_tail(reverse(yflip(path))));

a=10;
b=6;
N = 7;

p = N%2==1 ? cellipse_odd(a,b,N)
: cellipse(a,b,N);

echo(length = len(p));

ellipse([a,b],$fn=164);
color("red")stroke([p],width=.05,dots=true,dots_width=4);

On Mon, Aug 8, 2022 at 4:12 PM Father Horton fatherhorton@gmail.com wrote:

My end condition is that the last point calculated is (-L/2, b), but as I
think about it, it does make sense that N has to be a multiple of 2,
because the whole thing has to be symmetrical around the y-axis.

On Mon, Aug 8, 2022 at 2:35 PM Father Horton fatherhorton@gmail.com
wrote:

Here's a Google sheet that shows what I have in mind.
https://docs.google.com/spreadsheets/d/13YOJKkWWfcgZNKVn_nlBtQZ_bbxNvN6SdVv1bVWLDP8/edit?usp=sharing

I have to adjust the signs on the square roots manually, so I didn't
iterate until I got equal lengths, but this is the idea. Blue points are
end points of the circumscribing segments and red points are the tangent
points on the ellipse. I have other things to do at the moment, but I may
revisit later to get the signs to work out right and then see if it will
iterate to an acceptable result.

On Mon, Aug 8, 2022 at 1:31 PM Adrian Mariano avm4@cornell.edu wrote:

The restriction arises because of the end condition.  There are 4 cases
depending on what happens at the four ends of the ellipse (the points where
it intersects the coordinate axes).  The four possibilities are at each end
either a corner or a flat tangent at the end.  Your approach as I
understand it begins with a flat and constructs a quarter of the polygon,
ending with a point.  Such a polygon must have 4k+2 sides.  I do not see
how the end condition can be formulated to end on a flat.  Also I do not
see how it can start on a point.  If n is odd you can start at one end and
go half way around and end on a point. But if n is divisible by 4 you can
have 4 flats or four points and the method cannot produce either of them.
Have I missed something?

On Mon, Aug 8, 2022, 13:42 Father Horton fatherhorton@gmail.com wrote:

I'm not sure why there should be a restriction on N; I think it's
general. I did a spreadsheet that looks like it's doing the right thing in
the first quadrant, but it (or I) gets lost when I have to select the right
value for the sign of the square roots involved as the process enters other
quadrants.

On Sun, Aug 7, 2022 at 9:43 PM Father Horton fatherhorton@gmail.com
wrote:

Google showed me that method when I came up with the right terms. But
it's too late at night for me to try to implement it. Maybe tomorrow.

On Sun, Aug 7, 2022 at 9:41 PM Adrian Mariano avm4@cornell.edu
wrote:

Now I understand your idea.  I think it should be possible to make
that work for the case of N=4k+2.  It does seem like there are some
complications, like you try to extend the segment and the length is closer
than the tangent, so it's impossible.  Also things may be complicated if
the algorithm tries to go around the tip of the ellipse (that is, if the
path is too long).

For finding a tangent to an ellipse, transform the problem to the
circle, solve, and then transform back.  In BOSL2:

function ellipse_tangents(a,b,pt) =
let(
r=a,
scaledpt = yscale(a/b,pt),
tangents = circle_point_tangents(r,[0,0],scaledpt)
)
yscale(b/a,tangents);

On Sun, Aug 7, 2022 at 9:54 PM Father Horton fatherhorton@gmail.com
wrote:

I did that wrong. It's not (0, b) to (0, L/2). It's (0, b) to (L/2,
b). That's always outside the ellipse.

I will look at the second problem as soon as I figure out how to
calculate a tangent line to an ellipse containing a point not on the
ellipse. Google is not helping much.

On Sun, Aug 7, 2022 at 8:32 PM Adrian Mariano avm4@cornell.edu
wrote:

Father Horton,

I'm having trouble understanding your proposed method.  A segment
from (0,b) to (0,L/2) might be inside the ellipse depending on N, and then
there won't be a tangent.

It also sounds like your idea is somewhat similar to Jordan's idea:
basically start at one side and work around the ellipse and see if it
works.  If not, make a correction.  The problem with this idea is that
there are two parameters for the first segment, so how do you make a
correction?  (The two parameters are the location of the endpoint of the
first segment and its length.)

On Sun, Aug 7, 2022 at 5:33 PM Father Horton <
fatherhorton@gmail.com> wrote:

How about this to construct N equal length segments around an
ellipse with axes a and b:

  1. Select an initial segment length estimate (e.g., Ramanujan's
    formula / N) = L
  2. Construct a half-segment from (0, b) to (0, L/2).
  3. Find a line tangent to the ellipse and passing through (0, L/2).
  4. Find the point on the tangent line that is L away from (0, L/2).
  5. Repeat (3) substituting the new point for (0, L/2). until you
    have N segments.

If everything worked perfectly, the last point found would be (0,
-L/2). If there's a gap, increase L and try again. If there's overlap,
decrease L and try again.

On Sun, Aug 7, 2022 at 3:29 PM Ronaldo Persiano <
rcmpersiano@gmail.com> wrote:

Adrian, why to use a (either inscribed or circumscribed) polygon
with equal side as an approximation of an ellipsis? It doesn't seem to be a
good approximation of it. I get a better approximation by taking an angle
uniform sample of the curve in the parameter space.

[image: Uniformly_sampled_ellipsis.png]

Em sáb., 6 de ago. de 2022 às 01:44, Adrian Mariano <
avm4@cornell.edu> escreveu:

Circumscribed means tangents to points on the ellipse.  But
there are no arc lengths (equal or unequal) in this problem, nor equally
spaced angles.  The angles of each segment will be different.  But the
lengths of the segments are not the same as the arc lengths, which is why
arc length does not matter.  Here's a solution to the N=6 polygon sort of
inspired by the idea Jordan suggested, where I adjust the first segment
until the second segment has the right length.  The rest of the solution is
then obtained using symmetry, which means there is only a single unknown
that can simply be solved for.  But this doesn't generalize to higher N.

[image: image.png]
include<BOSL2/std.scad>

// ellipse semiaxes
// If a is much smaller than b it will fail
a=5;
b=2;

// Find point on ellipse at specified x coordinate
function ellipse_pt(a,b,x) = sqrt(b^2*(1-x^2/a^2));

// Find tangent line to ellipse at point (u,w)
// and determine the x value where that line has
// given y value.
function findx(a,b,u,w,y) =
let(
A = -ub^2/w/a^2,
B = w+(u
b)^2/w/a^2
)
(y-B)/A;

// First segment if tangent point is at x=u
function first_seg(a,b,u) =
let(
w = ellipse_pt(a,b,u),
x1 = findx(a,b,u,w,0),
x2 = findx(a,b,u,w,b)
)
[[x1,0],[x2,b]];

err = function (u) let(pt = first_seg(a,b,u))
2*pt[1].x - norm(pt[0]-pt[1]);

x = root_find(err,.2a,.9a);
first = first_seg(a,b,x);
top = concat(first,reverse(xflip(first)));
poly = concat(top, reverse(yflip(list_tail(top))));

stroke(ellipse([a,b]),width=.05,$fn=128,closed=true);
color("red")stroke(poly,width=.05,closed=true);

// Verify equality of segment lengths
echo(path_segment_lengths(poly,closed=true));

On Fri, Aug 5, 2022 at 8:55 PM Sanjeev Prabhakar <
sprabhakar2006@gmail.com> wrote:

Circumscribed means tangents from points on ellipse
How can the tangents from equally spaced arc lengths or equally
spaced angles be equal for an ellipse
You need to change the arc lengths dynamically and also
accurately estimate the segment length which fits the ellipse .

On Sat, 6 Aug, 2022, 4:51 am Adrian Mariano, avm4@cornell.edu
wrote:

Your intuition is incorrect: a circle scaled in one direction
IS an ellipse.  The motivation for being interested in
circumscribing is to make holes, though the constraint of equal length
sides is probably not what you'd want for that purpose.  You can make a
nonuniform circumscribing polygon for an ellipse by simply making a polygon
that circumscribes a circle and scaling it.

On Fri, Aug 5, 2022 at 7:16 PM Bob Carlson bob@rjcarlson.com
wrote:

Seems like I remember Nop Head talking about using
circumscribed holes for screws and even rotating the polygons to produce a
more even hole.

If an ellipse is the nominal shape, the using a circumscribed
polygon for a hole and an inscribed polygon for a solid might make sense.

Btw, can someone confirm my intuition that a circle scaled in
one dimension is not an ellipse?

-Bob
Tucson AZ

On Aug 5, 2022, at 15:38, Adrian Mariano avm4@cornell.edu
wrote:

I don't have a specific need for a circumscribing elliptical
polygon with equal sides.  I was writing code to make ellipses and it
seemed like equal side approximations would be nice, so I solved the case
for inscribed, but couldn't solve the circumscribed case.  So it's an
unsolved puzzle I've got that this discussion reminded me of.

On Fri, Aug 5, 2022 at 6:33 PM nop head nop.head@gmail.com
wrote:

A long discussion but I have to ask why do you need an
elliptical polygon with equal tangential sides?

On Fri, 5 Aug 2022, 21:58 Adrian Mariano, avm4@cornell.edu
wrote:

You think that a circumscribing polygon with equal length
segments does not exist??  I'm skeptical of this claim.

For circumscribed, it's not so hard.  You start with a
uniform-in-angle point distribution, compute the segment lengths, compare
to the mean segment length to get an error, and then compute an adjustment
based on the error.  It converges quickly.

So for example, I have segments lengths of:
ECHO: [5.57297, 5.57297, 5.57297, 5.57297, 5.57297,
5.57297, 5.57297, 5.57297]

Maybe not exactly equal, since tolerance is 1e-9, but
surely good enough.
<image.png>

The code for this is in BOSL2 in shapes2d.scad. A similar
algorithm should exist for the circumscribed case, but as I said, my
efforts to find it have failed.

On Fri, Aug 5, 2022 at 12:44 PM Sanjeev Prabhakar <
sprabhakar2006@gmail.com> wrote:

I think circumscribed polygon segments cannot be equal
lengths.
inscribed ones may be approximately equal, but would be a
very tough problem to solve.
I tried something.

On Thu, 4 Aug 2022 at 05:44, Adrian Mariano <
avm4@cornell.edu> wrote:

I think you need to be a little careful about defining
what you want to do.  If you want to approximate an ellipse with points
that are distributed uniformly over the ellipse, that could be done by
approximating the arc length of the ellipse to find the necessary
points---e.g. advance distance d along the ellipse at each step.  But if
you want to approximate an ellipse with a polygon with equal length sides,
that approach does not do it, because the length of the segments will not
be constant as the span sections of the ellipse with differing curvature.
And since the perimeter of the desired polygon is unknown, you can't just
step it out analogously.  The circle doesn't present this challenge due to
having constant curvature.

On Wed, Aug 3, 2022 at 7:41 PM Father Horton <
fatherhorton@gmail.com> wrote:

I think our emails crossed. I was addressing how to
approximate an ellipse with constant-length segments in general, not how to
solve your problem. When I had to do something similar, I used polar
coordinates and stepped up the value of theta until the distance from the
previous point was correct. (In the constant-length version, I'd keep a
running total of the maximum desired length so that round-off errors don't
accumulate.)

Figuring out the circumscribed polygon is, as you note,
a greater challenge. I can visualize how to do it for n = 4, but it doesn't
extrapolate at all.

On Tue, Aug 2, 2022 at 10:10 PM Adrian Mariano <
avm4@cornell.edu> wrote:

Eh, there's no such thing as "brute force" in this
situation.  Step through what with sufficiently small steps?  Of course
an iterative algorithm is necessary.  This is true for most interesting
problems.  No big deal.  Show me an iterative algorithm that converges to
the circumscribing polygon.  When I tried to devise such an algorithm I
couldn't find one that would converge.  Writing an algorithm that would
converge to the inscribed polygon seemed to be straight forward.  Note
also that computing arc length of the ellipse doesn't really help here.
You can do that by solving an elliptical integral, or summing up small
segments.  But what's the connection between arc length of the ellipse and
a circumscribing polygon with equal segment lengths?  If there's a
connection, I don't see it.

On Tue, Aug 2, 2022 at 10:56 PM Father Horton <
fatherhorton@gmail.com> wrote:

Except by brute force (step through it with
sufficiently small steps), it’s not possible because there’s no closed form
expression for the distance between two points on a general ellipse (as
opposed to special cases like a circle).

On Tue, Aug 2, 2022 at 9:50 PM Adrian Mariano <
avm4@cornell.edu> wrote:

Here's a challenge for you:  draw an "ellipse"
polygon with N segments that are all the same length that circumscribes a
perfect ellipse with given semiaxes a and b.  I tried to solve this problem
and could not find a solution.  I can draw an inscribed N segment
"ellipse" polygon with all segments the same length---though it's not
easy---but the circumscribed case eludes me.  I think of the inscribed
case as, every vertex is located on the ellipse and the circumscribed case,
every segment is tangent to the ellipse

On Tue, Aug 2, 2022 at 10:36 PM Sanjeev Prabhakar <
sprabhakar2006@gmail.com> wrote:

In openscad drawing a ellipse is not too difficult
Refer following code

function to draw an ellipse with semi-major and
semi-minor axis "r1" and "r2" respectively and with center "cp" and number
of segment "s"
/
// example:
// sec=ellipse(r1=5,r2=3,cp=[2,3],s=30);

function ellipse(r1,r2,cp,s=30)=
let(

sec=[for(i=[0:360/s:360-360/s])cp+[r1cos(i),r2sin(i)]]
)sec;

On Wed, 3 Aug, 2022, 5:35 am Jordan Brown, <
openscad@jordan.maileater.net> wrote:

On 8/2/2022 4:46 PM, Brian Allen wrote:

I created an oval using:
inMm = 25.4;
fullW = 35.5 * inMm;
fullL = 54.5 * inMm;
resize([fullW, fullL, 1])
circle(d=fullW);

Tip:  use scale() rather than resize(); it previews
faster in complicated cases.

It's the right size in the middle (35.5" wide at 50% of the length), but 25% along the length it's not quite as wide as I need it (it's 31.5" and I need it about 32"). If you can see the attached image I'm trying to make the yellow oval match the red "sanity check" lines. I'm trying to match the size and shape of an existing oval in the real world.

You're taking a circle and stretching it; the
result of that stretching is an ellipse.

I'm not 100% sure - maybe one of the real math
wizards can chime in - but I think the shape you are asking for would not
be an ellipse.

I believe that an ellipse is fully defined by its
major (long) and minor (short) axis dimensions; the other parts of the
curve mathematically flow from those two measurements.

You can make something else, but you can't make it
using this technique.

Is there a way to stretch this in OpenSCAD? In a GUI vector graphics program I'd use a bézier curve and drag the handle to get 1/4 of it just right then mirror it in X and Y to get the oval I needed.

You can use a Bézier function.

Using BOSL2:
https://github.com/revarbat/BOSL2/wiki/Topics#bezier-curves

DIY, here's a function that I cobbled together some
years ago:

// Bezier functions from https://www.thingiverse.com/thing:8443
// but that yielded either single points or a raft of triangles;
// this yields a vector of points that you can then concatenate
// with other pieces to form a single polygon.
// If we were really clever, I think it would be possible to
// automatically space the output points based on how linear
// the curve is at that point.  But right now I'm not that clever.
function BEZ03(u) = pow((1-u), 3);
function BEZ13(u) = 3u(pow((1-u),2));
function BEZ23(u) = 3*(pow(u,2))*(1-u);
function BEZ33(u) = pow(u,3);

function PointAlongBez4(p0, p1, p2, p3, u) = [
BEZ03(u)*p0[0]+BEZ13(u)*p1[0]+BEZ23(u)*p2[0]+BEZ33(u)*p3[0],
BEZ03(u)*p0[1]+BEZ13(u)*p1[1]+BEZ23(u)*p2[1]+BEZ33(u)*p3[1]];

// p0 - start point
// p1 - control point 1, line departs p0 headed this way
// p2 - control point 2, line arrives at p3 from this way
// p3 - end point
// segs - number of segments
function bez(p0, p1, p2, p3, segs) = [
for (i = [0:segs]) PointAlongBez4(p0, p1, p2, p3, i/segs)
];

It is that final function bez() that I actually
call, e.g.

polygon(bez([0,0], [0,4], [5,1], [7,0], 20));

often concatenating the results of several bez()
calls together.

Note that the four coordinates correspond to the
coordinates of the control points in a GUI drawing program:  the start
point, control point associated with the start, the control point
associated with the end, and the end point.  I have sometimes created
OpenSCAD objects by tracing an object in a drawing program and then reading
off the coordinates of the various control points.

Note that Bézier functions are not the only
mathematical curves.  (For instance, they cannot exactly match an arc of a
circle.)  I'm sure there are numerous other functions that also produce
curves.


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


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


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


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


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


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


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


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

So I hate spreadsheets and it's too hard to decipher what you've done by looking at the spread sheet. I actually coded this up myself in OpenSCAD And if there's a way to handle the N divisible by 4 case, I am not seeing it. For the N=4k+2 case you start at [b,L/2] and work your way around clockwise and place the segments to make a quarter-ellipse polygon. Assuming you're length estimate isn't terrible you'll place all the segments but end up slightly above/below the X axis. Based on how big the vertical error is, you update the length and iterate to get a solution. That produces a result that looks like this once you rotate and reflect to get a full ellipse instead of just a 1/4 ellipse: [image: image.png] Notice how the polygon has a flat segment on top but is pointy on the right? If N is odd then you start at [-a,L/2] and work your way clockwise around the ellipse, and then end with the same constraint. In this case there is less symmetry and you have to build a half-ellipse. [image: image.png] I made the ellipse fatter because otherwise the side segments appear coplanar. So here we have started on the left with a "flat" segment and ended a half-ellipse on the right at a corner. There are two other cases that arise for N divisible by 4 where we start and end on a point or a flat. Starting on a point is problematic because you have an extra parameter of how far away from the ellipse to put the point. And ending on a flat is problematic because you have a target that is two-dimensional, e.g. [a,L/2] and it's no longer apparent how to modify the length to guarantee an improvement. If you and up [.1,.1] away from the target...what should you do? Presumably this *could* be handled by using a multi-dimensional optimization solver, but I don't have one of those for OpenSCAD and it does seem kind of like overkill. Here's the code: include<BOSL2/std.scad> function ellipse_tangents(a,b,pt) = let( r=a, scaledpt = yscale(a/b,pt), tangents = circle_point_tangents(r,[0,0],scaledpt) ) yscale(b/a,tangents); function ellipse_next_pt(a,b,pt,L) = let( tanglist = ellipse_tangents(a,b,pt), //f=echo(pt=pt,tanglist=tanglist), tang = tanglist[0].x>pt.x ? tanglist[0] : len(tanglist)==2 && tanglist[1].x>pt.x ? tanglist[1] : assert(false,"cannot find acceptable tangent") ) assert(norm(tang-pt)<L,"Tangent is too far away") L*unit(tang-pt)+pt; function ellipse_path(a,b,L,N,path=[]) = len(path)==0 ? ellipse_path(a,b,L,N,[[L/2,b]]) : len(path)==N ? path : last(path).y<=0 ? path : last(path).x>=a ? path : ellipse_path(a,b,L,N, [each path, ellipse_next_pt(a,b,last(path),L)]); function ellipse_circ(a,b) = PI*(3*(a+b) - sqrt(10*a*b+3*(a^2+b^2))); function cellipse(a,b,N) = assert(N%4==2, "Must have N of form 4k+2") let( errfunc = function(L) let(path=(ellipse_path(a,b,L,(N+2)/4))) -last(path).y+ ((N+2)/4 - len(path)) * b , lengthguess = ellipse_circ(a,b)/N, L = root_find(errfunc, 0.95*lengthguess, 1.5*lengthguess), path = ellipse_path(a,b,L,(N+2)/4), right = concat(path, yflip(list_tail(reverse(path)))) ) concat(right, reverse(xflip(right))); function cellipse_odd(a,b,N) = assert(N%2==1, "Must have N of form 2k+1") let( errfunc = function(L) let(path=ellipse_path(a,b,L,(N+1)/2,[[-a,L/2]])) -last(path).y+ ((N+1)/2 - len(path)) * b , lengthguess = ellipse_circ(a,b)/N, L = root_find(errfunc, 0.95*lengthguess, 1.5*lengthguess), path = ellipse_path(a,b,L,(N+1)/2,[[-a,L/2]]) ) concat(path, list_tail(reverse(yflip(path)))); a=10; b=6; N = 7; p = N%2==1 ? cellipse_odd(a,b,N) : cellipse(a,b,N); echo(length = len(p)); ellipse([a,b],$fn=164); color("red")stroke([p],width=.05,dots=true,dots_width=4); On Mon, Aug 8, 2022 at 4:12 PM Father Horton <fatherhorton@gmail.com> wrote: > My end condition is that the last point calculated is (-L/2, b), but as I > think about it, it does make sense that N has to be a multiple of 2, > because the whole thing has to be symmetrical around the y-axis. > > On Mon, Aug 8, 2022 at 2:35 PM Father Horton <fatherhorton@gmail.com> > wrote: > >> Here's a Google sheet that shows what I have in mind. >> https://docs.google.com/spreadsheets/d/13YOJKkWWfcgZNKVn_nlBtQZ_bbxNvN6SdVv1bVWLDP8/edit?usp=sharing >> >> I have to adjust the signs on the square roots manually, so I didn't >> iterate until I got equal lengths, but this is the idea. Blue points are >> end points of the circumscribing segments and red points are the tangent >> points on the ellipse. I have other things to do at the moment, but I may >> revisit later to get the signs to work out right and then see if it will >> iterate to an acceptable result. >> >> On Mon, Aug 8, 2022 at 1:31 PM Adrian Mariano <avm4@cornell.edu> wrote: >> >>> The restriction arises because of the end condition. There are 4 cases >>> depending on what happens at the four ends of the ellipse (the points where >>> it intersects the coordinate axes). The four possibilities are at each end >>> either a corner or a flat tangent at the end. Your approach as I >>> understand it begins with a flat and constructs a quarter of the polygon, >>> ending with a point. Such a polygon must have 4k+2 sides. I do not see >>> how the end condition can be formulated to end on a flat. Also I do not >>> see how it can start on a point. If n is odd you can start at one end and >>> go half way around and end on a point. But if n is divisible by 4 you can >>> have 4 flats or four points and the method cannot produce either of them. >>> Have I missed something? >>> >>> >>> On Mon, Aug 8, 2022, 13:42 Father Horton <fatherhorton@gmail.com> wrote: >>> >>>> I'm not sure why there should be a restriction on N; I think it's >>>> general. I did a spreadsheet that looks like it's doing the right thing in >>>> the first quadrant, but it (or I) gets lost when I have to select the right >>>> value for the sign of the square roots involved as the process enters other >>>> quadrants. >>>> >>>> On Sun, Aug 7, 2022 at 9:43 PM Father Horton <fatherhorton@gmail.com> >>>> wrote: >>>> >>>>> Google showed me that method when I came up with the right terms. But >>>>> it's too late at night for me to try to implement it. Maybe tomorrow. >>>>> >>>>> On Sun, Aug 7, 2022 at 9:41 PM Adrian Mariano <avm4@cornell.edu> >>>>> wrote: >>>>> >>>>>> Now I understand your idea. I think it should be possible to make >>>>>> that work for the case of N=4k+2. It does seem like there are some >>>>>> complications, like you try to extend the segment and the length is closer >>>>>> than the tangent, so it's impossible. Also things may be complicated if >>>>>> the algorithm tries to go around the tip of the ellipse (that is, if the >>>>>> path is too long). >>>>>> >>>>>> For finding a tangent to an ellipse, transform the problem to the >>>>>> circle, solve, and then transform back. In BOSL2: >>>>>> >>>>>> function ellipse_tangents(a,b,pt) = >>>>>> let( >>>>>> r=a, >>>>>> scaledpt = yscale(a/b,pt), >>>>>> tangents = circle_point_tangents(r,[0,0],scaledpt) >>>>>> ) >>>>>> yscale(b/a,tangents); >>>>>> >>>>>> On Sun, Aug 7, 2022 at 9:54 PM Father Horton <fatherhorton@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> I did that wrong. It's not (0, b) to (0, L/2). It's (0, b) to (L/2, >>>>>>> b). That's always outside the ellipse. >>>>>>> >>>>>>> I will look at the second problem as soon as I figure out how to >>>>>>> calculate a tangent line to an ellipse containing a point not on the >>>>>>> ellipse. Google is not helping much. >>>>>>> >>>>>>> On Sun, Aug 7, 2022 at 8:32 PM Adrian Mariano <avm4@cornell.edu> >>>>>>> wrote: >>>>>>> >>>>>>>> Father Horton, >>>>>>>> >>>>>>>> I'm having trouble understanding your proposed method. A segment >>>>>>>> from (0,b) to (0,L/2) might be inside the ellipse depending on N, and then >>>>>>>> there won't be a tangent. >>>>>>>> >>>>>>>> It also sounds like your idea is somewhat similar to Jordan's idea: >>>>>>>> basically start at one side and work around the ellipse and see if it >>>>>>>> works. If not, make a correction. The problem with this idea is that >>>>>>>> there are two parameters for the first segment, so how do you make a >>>>>>>> correction? (The two parameters are the location of the endpoint of the >>>>>>>> first segment and its length.) >>>>>>>> >>>>>>>> On Sun, Aug 7, 2022 at 5:33 PM Father Horton < >>>>>>>> fatherhorton@gmail.com> wrote: >>>>>>>> >>>>>>>>> How about this to construct N equal length segments around an >>>>>>>>> ellipse with axes a and b: >>>>>>>>> >>>>>>>>> 1) Select an initial segment length estimate (e.g., Ramanujan's >>>>>>>>> formula / N) = L >>>>>>>>> 2) Construct a half-segment from (0, b) to (0, L/2). >>>>>>>>> 3) Find a line tangent to the ellipse and passing through (0, L/2). >>>>>>>>> 3) Find the point on the tangent line that is L away from (0, L/2). >>>>>>>>> 4) Repeat (3) substituting the new point for (0, L/2). until you >>>>>>>>> have N segments. >>>>>>>>> >>>>>>>>> If everything worked perfectly, the last point found would be (0, >>>>>>>>> -L/2). If there's a gap, increase L and try again. If there's overlap, >>>>>>>>> decrease L and try again. >>>>>>>>> >>>>>>>>> On Sun, Aug 7, 2022 at 3:29 PM Ronaldo Persiano < >>>>>>>>> rcmpersiano@gmail.com> wrote: >>>>>>>>> >>>>>>>>>> Adrian, why to use a (either inscribed or circumscribed) polygon >>>>>>>>>> with equal side as an approximation of an ellipsis? It doesn't seem to be a >>>>>>>>>> good approximation of it. I get a better approximation by taking an angle >>>>>>>>>> uniform sample of the curve in the parameter space. >>>>>>>>>> >>>>>>>>>> [image: Uniformly_sampled_ellipsis.png] >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Em sáb., 6 de ago. de 2022 às 01:44, Adrian Mariano < >>>>>>>>>> avm4@cornell.edu> escreveu: >>>>>>>>>> >>>>>>>>>>> Circumscribed means tangents to points on the ellipse. But >>>>>>>>>>> there are no arc lengths (equal or unequal) in this problem, nor equally >>>>>>>>>>> spaced angles. The angles of each segment will be different. But the >>>>>>>>>>> lengths of the segments are not the same as the arc lengths, which is why >>>>>>>>>>> arc length does not matter. Here's a solution to the N=6 polygon sort of >>>>>>>>>>> inspired by the idea Jordan suggested, where I adjust the first segment >>>>>>>>>>> until the second segment has the right length. The rest of the solution is >>>>>>>>>>> then obtained using symmetry, which means there is only a single unknown >>>>>>>>>>> that can simply be solved for. But this doesn't generalize to higher N. >>>>>>>>>>> >>>>>>>>>>> [image: image.png] >>>>>>>>>>> include<BOSL2/std.scad> >>>>>>>>>>> >>>>>>>>>>> // ellipse semiaxes >>>>>>>>>>> // If a is much smaller than b it will fail >>>>>>>>>>> a=5; >>>>>>>>>>> b=2; >>>>>>>>>>> >>>>>>>>>>> // Find point on ellipse at specified x coordinate >>>>>>>>>>> function ellipse_pt(a,b,x) = sqrt(b^2*(1-x^2/a^2)); >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> // Find tangent line to ellipse at point (u,w) >>>>>>>>>>> // and determine the x value where that line has >>>>>>>>>>> // given y value. >>>>>>>>>>> function findx(a,b,u,w,y) = >>>>>>>>>>> let( >>>>>>>>>>> A = -u*b^2/w/a^2, >>>>>>>>>>> B = w+(u*b)^2/w/a^2 >>>>>>>>>>> ) >>>>>>>>>>> (y-B)/A; >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> // First segment if tangent point is at x=u >>>>>>>>>>> function first_seg(a,b,u) = >>>>>>>>>>> let( >>>>>>>>>>> w = ellipse_pt(a,b,u), >>>>>>>>>>> x1 = findx(a,b,u,w,0), >>>>>>>>>>> x2 = findx(a,b,u,w,b) >>>>>>>>>>> ) >>>>>>>>>>> [[x1,0],[x2,b]]; >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> err = function (u) let(pt = first_seg(a,b,u)) >>>>>>>>>>> 2*pt[1].x - norm(pt[0]-pt[1]); >>>>>>>>>>> >>>>>>>>>>> x = root_find(err,.2*a,.9*a); >>>>>>>>>>> first = first_seg(a,b,x); >>>>>>>>>>> top = concat(first,reverse(xflip(first))); >>>>>>>>>>> poly = concat(top, reverse(yflip(list_tail(top)))); >>>>>>>>>>> >>>>>>>>>>> stroke(ellipse([a,b]),width=.05,$fn=128,closed=true); >>>>>>>>>>> color("red")stroke(poly,width=.05,closed=true); >>>>>>>>>>> >>>>>>>>>>> // Verify equality of segment lengths >>>>>>>>>>> echo(path_segment_lengths(poly,closed=true)); >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On Fri, Aug 5, 2022 at 8:55 PM Sanjeev Prabhakar < >>>>>>>>>>> sprabhakar2006@gmail.com> wrote: >>>>>>>>>>> >>>>>>>>>>>> Circumscribed means tangents from points on ellipse >>>>>>>>>>>> How can the tangents from equally spaced arc lengths or equally >>>>>>>>>>>> spaced angles be equal for an ellipse >>>>>>>>>>>> You need to change the arc lengths dynamically and also >>>>>>>>>>>> accurately estimate the segment length which fits the ellipse . >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Sat, 6 Aug, 2022, 4:51 am Adrian Mariano, <avm4@cornell.edu> >>>>>>>>>>>> wrote: >>>>>>>>>>>> >>>>>>>>>>>>> Your intuition is incorrect: a circle scaled in one direction >>>>>>>>>>>>> *IS* an ellipse. The motivation for being interested in >>>>>>>>>>>>> circumscribing is to make holes, though the constraint of equal length >>>>>>>>>>>>> sides is probably not what you'd want for that purpose. You can make a >>>>>>>>>>>>> nonuniform circumscribing polygon for an ellipse by simply making a polygon >>>>>>>>>>>>> that circumscribes a circle and scaling it. >>>>>>>>>>>>> >>>>>>>>>>>>> On Fri, Aug 5, 2022 at 7:16 PM Bob Carlson <bob@rjcarlson.com> >>>>>>>>>>>>> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>>> Seems like I remember Nop Head talking about using >>>>>>>>>>>>>> circumscribed holes for screws and even rotating the polygons to produce a >>>>>>>>>>>>>> more even hole. >>>>>>>>>>>>>> >>>>>>>>>>>>>> If an ellipse is the nominal shape, the using a circumscribed >>>>>>>>>>>>>> polygon for a hole and an inscribed polygon for a solid might make sense. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Btw, can someone confirm my intuition that a circle scaled in >>>>>>>>>>>>>> one dimension is not an ellipse? >>>>>>>>>>>>>> >>>>>>>>>>>>>> -Bob >>>>>>>>>>>>>> Tucson AZ >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On Aug 5, 2022, at 15:38, Adrian Mariano <avm4@cornell.edu> >>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> I don't have a specific need for a circumscribing elliptical >>>>>>>>>>>>>> polygon with equal sides. I was writing code to make ellipses and it >>>>>>>>>>>>>> seemed like equal side approximations would be nice, so I solved the case >>>>>>>>>>>>>> for inscribed, but couldn't solve the circumscribed case. So it's an >>>>>>>>>>>>>> unsolved puzzle I've got that this discussion reminded me of. >>>>>>>>>>>>>> >>>>>>>>>>>>>> On Fri, Aug 5, 2022 at 6:33 PM nop head <nop.head@gmail.com> >>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>>> A long discussion but I have to ask why do you need an >>>>>>>>>>>>>>> elliptical polygon with equal tangential sides? >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Fri, 5 Aug 2022, 21:58 Adrian Mariano, <avm4@cornell.edu> >>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> You think that a circumscribing polygon with equal length >>>>>>>>>>>>>>>> segments does not exist?? I'm skeptical of this claim. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> For circumscribed, it's not so hard. You start with a >>>>>>>>>>>>>>>> uniform-in-angle point distribution, compute the segment lengths, compare >>>>>>>>>>>>>>>> to the mean segment length to get an error, and then compute an adjustment >>>>>>>>>>>>>>>> based on the error. It converges quickly. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> So for example, I have segments lengths of: >>>>>>>>>>>>>>>> ECHO: [5.57297, 5.57297, 5.57297, 5.57297, 5.57297, >>>>>>>>>>>>>>>> 5.57297, 5.57297, 5.57297] >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Maybe not exactly equal, since tolerance is 1e-9, but >>>>>>>>>>>>>>>> surely good enough. >>>>>>>>>>>>>>>> <image.png> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> The code for this is in BOSL2 in shapes2d.scad. A similar >>>>>>>>>>>>>>>> algorithm should exist for the circumscribed case, but as I said, my >>>>>>>>>>>>>>>> efforts to find it have failed. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On Fri, Aug 5, 2022 at 12:44 PM Sanjeev Prabhakar < >>>>>>>>>>>>>>>> sprabhakar2006@gmail.com> wrote: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I think circumscribed polygon segments cannot be equal >>>>>>>>>>>>>>>>> lengths. >>>>>>>>>>>>>>>>> inscribed ones may be approximately equal, but would be a >>>>>>>>>>>>>>>>> very tough problem to solve. >>>>>>>>>>>>>>>>> I tried something. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On Thu, 4 Aug 2022 at 05:44, Adrian Mariano < >>>>>>>>>>>>>>>>> avm4@cornell.edu> wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> I think you need to be a little careful about defining >>>>>>>>>>>>>>>>>> what you want to do. If you want to approximate an ellipse with points >>>>>>>>>>>>>>>>>> that are distributed uniformly over the ellipse, that could be done by >>>>>>>>>>>>>>>>>> approximating the arc length of the ellipse to find the necessary >>>>>>>>>>>>>>>>>> points---e.g. advance distance d along the ellipse at each step. But if >>>>>>>>>>>>>>>>>> you want to approximate an ellipse with a polygon with equal length sides, >>>>>>>>>>>>>>>>>> that approach does not do it, because the length of the segments will not >>>>>>>>>>>>>>>>>> be constant as the span sections of the ellipse with differing curvature. >>>>>>>>>>>>>>>>>> And since the perimeter of the desired polygon is unknown, you can't just >>>>>>>>>>>>>>>>>> step it out analogously. The circle doesn't present this challenge due to >>>>>>>>>>>>>>>>>> having constant curvature. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> On Wed, Aug 3, 2022 at 7:41 PM Father Horton < >>>>>>>>>>>>>>>>>> fatherhorton@gmail.com> wrote: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I think our emails crossed. I was addressing how to >>>>>>>>>>>>>>>>>>> approximate an ellipse with constant-length segments in general, not how to >>>>>>>>>>>>>>>>>>> solve your problem. When I had to do something similar, I used polar >>>>>>>>>>>>>>>>>>> coordinates and stepped up the value of theta until the distance from the >>>>>>>>>>>>>>>>>>> previous point was correct. (In the constant-length version, I'd keep a >>>>>>>>>>>>>>>>>>> running total of the maximum desired length so that round-off errors don't >>>>>>>>>>>>>>>>>>> accumulate.) >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Figuring out the circumscribed polygon is, as you note, >>>>>>>>>>>>>>>>>>> a greater challenge. I can visualize how to do it for n = 4, but it doesn't >>>>>>>>>>>>>>>>>>> extrapolate at all. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 10:10 PM Adrian Mariano < >>>>>>>>>>>>>>>>>>> avm4@cornell.edu> wrote: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> Eh, there's no such thing as "brute force" in this >>>>>>>>>>>>>>>>>>>> situation. Step through *what* with sufficiently small steps? Of course >>>>>>>>>>>>>>>>>>>> an iterative algorithm is necessary. This is true for most interesting >>>>>>>>>>>>>>>>>>>> problems. No big deal. Show me an iterative algorithm that converges to >>>>>>>>>>>>>>>>>>>> the circumscribing polygon. When I tried to devise such an algorithm I >>>>>>>>>>>>>>>>>>>> couldn't find one that would converge. Writing an algorithm that would >>>>>>>>>>>>>>>>>>>> converge to the *inscribed* polygon seemed to be straight forward. Note >>>>>>>>>>>>>>>>>>>> also that computing arc length of the ellipse doesn't really help here. >>>>>>>>>>>>>>>>>>>> You can do that by solving an elliptical integral, or summing up small >>>>>>>>>>>>>>>>>>>> segments. But what's the connection between arc length of the ellipse and >>>>>>>>>>>>>>>>>>>> a circumscribing polygon with equal segment lengths? If there's a >>>>>>>>>>>>>>>>>>>> connection, I don't see it. >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 10:56 PM Father Horton < >>>>>>>>>>>>>>>>>>>> fatherhorton@gmail.com> wrote: >>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> Except by brute force (step through it with >>>>>>>>>>>>>>>>>>>>> sufficiently small steps), it’s not possible because there’s no closed form >>>>>>>>>>>>>>>>>>>>> expression for the distance between two points on a general ellipse (as >>>>>>>>>>>>>>>>>>>>> opposed to special cases like a circle). >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 9:50 PM Adrian Mariano < >>>>>>>>>>>>>>>>>>>>> avm4@cornell.edu> wrote: >>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> Here's a challenge for you: draw an "ellipse" >>>>>>>>>>>>>>>>>>>>>> polygon with N segments that are all the same length that circumscribes a >>>>>>>>>>>>>>>>>>>>>> perfect ellipse with given semiaxes a and b. I tried to solve this problem >>>>>>>>>>>>>>>>>>>>>> and could not find a solution. I can draw an *inscribed* N segment >>>>>>>>>>>>>>>>>>>>>> "ellipse" polygon with all segments the same length---though it's not >>>>>>>>>>>>>>>>>>>>>> easy---but the circumscribed case eludes me. I think of the inscribed >>>>>>>>>>>>>>>>>>>>>> case as, every vertex is located on the ellipse and the circumscribed case, >>>>>>>>>>>>>>>>>>>>>> every segment is tangent to the ellipse >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>> On Tue, Aug 2, 2022 at 10:36 PM Sanjeev Prabhakar < >>>>>>>>>>>>>>>>>>>>>> sprabhakar2006@gmail.com> wrote: >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> In openscad drawing a ellipse is not too difficult >>>>>>>>>>>>>>>>>>>>>>> Refer following code >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> function to draw an ellipse with semi-major and >>>>>>>>>>>>>>>>>>>>>>> semi-minor axis "r1" and "r2" respectively and with center "cp" and number >>>>>>>>>>>>>>>>>>>>>>> of segment "s" >>>>>>>>>>>>>>>>>>>>>>> / >>>>>>>>>>>>>>>>>>>>>>> // example: >>>>>>>>>>>>>>>>>>>>>>> // sec=ellipse(r1=5,r2=3,cp=[2,3],s=30); >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> function ellipse(r1,r2,cp,s=30)= >>>>>>>>>>>>>>>>>>>>>>> let( >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> sec=[for(i=[0:360/s:360-360/s])cp+[r1*cos(i),r2*sin(i)]] >>>>>>>>>>>>>>>>>>>>>>> )sec; >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>> On Wed, 3 Aug, 2022, 5:35 am Jordan Brown, < >>>>>>>>>>>>>>>>>>>>>>> openscad@jordan.maileater.net> wrote: >>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> On 8/2/2022 4:46 PM, Brian Allen wrote: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I created an oval using: >>>>>>>>>>>>>>>>>>>>>>>> inMm = 25.4; >>>>>>>>>>>>>>>>>>>>>>>> fullW = 35.5 * inMm; >>>>>>>>>>>>>>>>>>>>>>>> fullL = 54.5 * inMm; >>>>>>>>>>>>>>>>>>>>>>>> resize([fullW, fullL, 1]) >>>>>>>>>>>>>>>>>>>>>>>> circle(d=fullW); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Tip: use scale() rather than resize(); it previews >>>>>>>>>>>>>>>>>>>>>>>> faster in complicated cases. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> It's the right size in the middle (35.5" wide at 50% of the length), but 25% along the length it's not quite as wide as I need it (it's 31.5" and I need it about 32"). If you can see the attached image I'm trying to make the yellow oval match the red "sanity check" lines. I'm trying to match the size and shape of an existing oval in the real world. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You're taking a circle and stretching it; the >>>>>>>>>>>>>>>>>>>>>>>> result of that stretching is an ellipse. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I'm not 100% sure - maybe one of the real math >>>>>>>>>>>>>>>>>>>>>>>> wizards can chime in - but I think the shape you are asking for would not >>>>>>>>>>>>>>>>>>>>>>>> be an ellipse. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> I believe that an ellipse is fully defined by its >>>>>>>>>>>>>>>>>>>>>>>> major (long) and minor (short) axis dimensions; the other parts of the >>>>>>>>>>>>>>>>>>>>>>>> curve mathematically flow from those two measurements. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You can make something else, but you can't make it >>>>>>>>>>>>>>>>>>>>>>>> using this technique. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Is there a way to stretch this in OpenSCAD? In a GUI vector graphics program I'd use a bézier curve and drag the handle to get 1/4 of it just right then mirror it in X and Y to get the oval I needed. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> You can use a Bézier function. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Using BOSL2: >>>>>>>>>>>>>>>>>>>>>>>> https://github.com/revarbat/BOSL2/wiki/Topics#bezier-curves >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> DIY, here's a function that I cobbled together some >>>>>>>>>>>>>>>>>>>>>>>> years ago: >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> // Bezier functions from https://www.thingiverse.com/thing:8443 >>>>>>>>>>>>>>>>>>>>>>>> // but that yielded either single points or a raft of triangles; >>>>>>>>>>>>>>>>>>>>>>>> // this yields a vector of points that you can then concatenate >>>>>>>>>>>>>>>>>>>>>>>> // with other pieces to form a single polygon. >>>>>>>>>>>>>>>>>>>>>>>> // If we were really clever, I think it would be possible to >>>>>>>>>>>>>>>>>>>>>>>> // automatically space the output points based on how linear >>>>>>>>>>>>>>>>>>>>>>>> // the curve is at that point. But right now I'm not that clever. >>>>>>>>>>>>>>>>>>>>>>>> function BEZ03(u) = pow((1-u), 3); >>>>>>>>>>>>>>>>>>>>>>>> function BEZ13(u) = 3*u*(pow((1-u),2)); >>>>>>>>>>>>>>>>>>>>>>>> function BEZ23(u) = 3*(pow(u,2))*(1-u); >>>>>>>>>>>>>>>>>>>>>>>> function BEZ33(u) = pow(u,3); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> function PointAlongBez4(p0, p1, p2, p3, u) = [ >>>>>>>>>>>>>>>>>>>>>>>> BEZ03(u)*p0[0]+BEZ13(u)*p1[0]+BEZ23(u)*p2[0]+BEZ33(u)*p3[0], >>>>>>>>>>>>>>>>>>>>>>>> BEZ03(u)*p0[1]+BEZ13(u)*p1[1]+BEZ23(u)*p2[1]+BEZ33(u)*p3[1]]; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> // p0 - start point >>>>>>>>>>>>>>>>>>>>>>>> // p1 - control point 1, line departs p0 headed this way >>>>>>>>>>>>>>>>>>>>>>>> // p2 - control point 2, line arrives at p3 from this way >>>>>>>>>>>>>>>>>>>>>>>> // p3 - end point >>>>>>>>>>>>>>>>>>>>>>>> // segs - number of segments >>>>>>>>>>>>>>>>>>>>>>>> function bez(p0, p1, p2, p3, segs) = [ >>>>>>>>>>>>>>>>>>>>>>>> for (i = [0:segs]) PointAlongBez4(p0, p1, p2, p3, i/segs) >>>>>>>>>>>>>>>>>>>>>>>> ]; >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> It is that final function bez() that I actually >>>>>>>>>>>>>>>>>>>>>>>> call, e.g. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> polygon(bez([0,0], [0,4], [5,1], [7,0], 20)); >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> often concatenating the results of several bez() >>>>>>>>>>>>>>>>>>>>>>>> calls together. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Note that the four coordinates correspond to the >>>>>>>>>>>>>>>>>>>>>>>> coordinates of the control points in a GUI drawing program: the start >>>>>>>>>>>>>>>>>>>>>>>> point, control point associated with the start, the control point >>>>>>>>>>>>>>>>>>>>>>>> associated with the end, and the end point. I have sometimes created >>>>>>>>>>>>>>>>>>>>>>>> OpenSCAD objects by tracing an object in a drawing program and then reading >>>>>>>>>>>>>>>>>>>>>>>> off the coordinates of the various control points. >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>> Note that Bézier functions are not the only >>>>>>>>>>>>>>>>>>>>>>>> mathematical curves. (For instance, they cannot exactly match an arc of a >>>>>>>>>>>>>>>>>>>>>>>> circle.) I'm sure there are numerous other functions that also produce >>>>>>>>>>>>>>>>>>>>>>>> curves. >>>>>>>>>>>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>>>> 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 >>>>>>>>>>>>>> >>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>> 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 >>>>>>>>>>> >>>>>>>>>> _______________________________________________ >>>>>>>>>> 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 >>>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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 >>>> >>> _______________________________________________ >>> 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
Mon, Aug 8, 2022 8:41 PM

It's never necessary to do more than half the ellipse, which I think
makes handling the multiplicity of tangents easier.

On Mon, Aug 8, 2022 at 4:30 PM Father Horton fatherhorton@gmail.com wrote:

On Mon, Aug 8, 2022 at 3:23 PM Michael Möller private2michael@gmail.com wrote:

y and x if divisible by 4, right?

Right, which would make calculation easier since I wouldn't have to deal with those nasty quadrant changes.


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

It's never necessary to do more than half the ellipse, which I think makes handling the multiplicity of tangents easier. On Mon, Aug 8, 2022 at 4:30 PM Father Horton <fatherhorton@gmail.com> wrote: > > > > On Mon, Aug 8, 2022 at 3:23 PM Michael Möller <private2michael@gmail.com> wrote: >> >> y and x if divisible by 4, right? > > > Right, which would make calculation easier since I wouldn't have to deal with those nasty quadrant changes. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
FH
Father Horton
Mon, Aug 8, 2022 8:46 PM

Here's a Python version that gets the first quadrant right:

import math

major = 2
minor = 1

length = 1.03

px = length / 2
py = minor

for i in range(1, 3):
c = px / major
d = py / minor
print(f"Adjusted point off circle is ({c:.3f},{d:.3f})")

a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d * d)))

/ (2 * (d * d + c * c))
b = math.sqrt(1 - a * a)

print(f"Point on circle is ({a:.3f}, {b:.3f})")

ex = a * major
ey = b * minor
print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})")

m = (py - ey) / (px - ex)
xhat = math.sqrt(length * length / (1 + m * m))
yhat = m * xhat
px = px + xhat
py = py + yhat

print(f"New point off circle is ({px:.3f}, {py:.3f})")

On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano avm4@cornell.edu wrote:

It's never necessary to do more than half the ellipse, which I think
makes handling the multiplicity of tangents easier.

On Mon, Aug 8, 2022 at 4:30 PM Father Horton fatherhorton@gmail.com
wrote:

On Mon, Aug 8, 2022 at 3:23 PM Michael Möller private2michael@gmail.com

wrote:

y and x if divisible by 4, right?

Right, which would make calculation easier since I wouldn't have to deal

with those nasty quadrant changes.


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

Here's a Python version that gets the first quadrant right: import math major = 2 minor = 1 length = 1.03 px = length / 2 py = minor for i in range(1, 3): c = px / major d = py / minor print(f"Adjusted point off circle is ({c:.3f},{d:.3f})") a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d * d))) / (2 * (d * d + c * c)) b = math.sqrt(1 - a * a) print(f"Point on circle is ({a:.3f}, {b:.3f})") ex = a * major ey = b * minor print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})") m = (py - ey) / (px - ex) xhat = math.sqrt(length * length / (1 + m * m)) yhat = m * xhat px = px + xhat py = py + yhat print(f"New point off circle is ({px:.3f}, {py:.3f})") On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano <avm4@cornell.edu> wrote: > It's never necessary to do more than half the ellipse, which I think > makes handling the multiplicity of tangents easier. > > On Mon, Aug 8, 2022 at 4:30 PM Father Horton <fatherhorton@gmail.com> > wrote: > > > > > > > > On Mon, Aug 8, 2022 at 3:23 PM Michael Möller <private2michael@gmail.com> > wrote: > >> > >> y and x if divisible by 4, right? > > > > > > Right, which would make calculation easier since I wouldn't have to deal > with those nasty quadrant changes. > > _______________________________________________ > > 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
Mon, Aug 8, 2022 9:28 PM

So that code just works around the ellipse, making 3 steps at the
fixed length, right?  The hard part isn't doing that---it's being able
to automatically update so that you get the correct answer.  What
happens if you try to do this manual process but for an ellipse that
starts with a full segment whose endpoint is [0,b+extra] for some
extra corner offset distance?  Or one that starts the same but ends at
[b,L/2].  I haven't actually tried running these processes to see how
it behaves.

On Mon, Aug 8, 2022 at 4:47 PM Father Horton fatherhorton@gmail.com wrote:

Here's a Python version that gets the first quadrant right:

import math

major = 2
minor = 1

length = 1.03

px = length / 2
py = minor

for i in range(1, 3):
c = px / major
d = py / minor
print(f"Adjusted point off circle is ({c:.3f},{d:.3f})")

 a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d * d))) / (2 * (d * d + c * c))
 b = math.sqrt(1 - a * a)

 print(f"Point on circle is ({a:.3f}, {b:.3f})")

 ex = a * major
 ey = b * minor
 print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})")

 m = (py - ey) / (px - ex)
 xhat = math.sqrt(length * length / (1 + m * m))
 yhat = m * xhat
 px = px + xhat
 py = py + yhat

 print(f"New point off circle is ({px:.3f}, {py:.3f})")

On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano avm4@cornell.edu wrote:

It's never necessary to do more than half the ellipse, which I think
makes handling the multiplicity of tangents easier.

On Mon, Aug 8, 2022 at 4:30 PM Father Horton fatherhorton@gmail.com wrote:

On Mon, Aug 8, 2022 at 3:23 PM Michael Möller private2michael@gmail.com wrote:

y and x if divisible by 4, right?

Right, which would make calculation easier since I wouldn't have to deal with those nasty quadrant changes.


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

So that code just works around the ellipse, making 3 steps at the fixed length, right? The hard part isn't doing that---it's being able to automatically update so that you get the correct answer. What happens if you try to do this manual process but for an ellipse that starts with a full segment whose endpoint is [0,b+extra] for some extra corner offset distance? Or one that starts the same but ends at [b,L/2]. I haven't actually tried running these processes to see how it behaves. On Mon, Aug 8, 2022 at 4:47 PM Father Horton <fatherhorton@gmail.com> wrote: > > Here's a Python version that gets the first quadrant right: > > import math > > major = 2 > minor = 1 > > length = 1.03 > > px = length / 2 > py = minor > > for i in range(1, 3): > c = px / major > d = py / minor > print(f"Adjusted point off circle is ({c:.3f},{d:.3f})") > > > a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d * d))) / (2 * (d * d + c * c)) > b = math.sqrt(1 - a * a) > > print(f"Point on circle is ({a:.3f}, {b:.3f})") > > ex = a * major > ey = b * minor > print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})") > > m = (py - ey) / (px - ex) > xhat = math.sqrt(length * length / (1 + m * m)) > yhat = m * xhat > px = px + xhat > py = py + yhat > > print(f"New point off circle is ({px:.3f}, {py:.3f})") > > > On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano <avm4@cornell.edu> wrote: >> >> It's never necessary to do more than half the ellipse, which I think >> makes handling the multiplicity of tangents easier. >> >> On Mon, Aug 8, 2022 at 4:30 PM Father Horton <fatherhorton@gmail.com> wrote: >> > >> > >> > >> > On Mon, Aug 8, 2022 at 3:23 PM Michael Möller <private2michael@gmail.com> wrote: >> >> >> >> y and x if divisible by 4, right? >> > >> > >> > Right, which would make calculation easier since I wouldn't have to deal with those nasty quadrant changes. >> > _______________________________________________ >> > 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
FH
Father Horton
Mon, Aug 8, 2022 9:35 PM

You change L until it works. I'd start with an estimate (Ramanujan's?) of
the perimeter of the ellipse and divide by N to get an estimate for L. Step
around and if L is too short, increase it by say 10%, and if it's too long,
decrease by 10%. Once you have the right distance bracketed, do a binary
search.

On Mon, Aug 8, 2022 at 4:29 PM Adrian Mariano avm4@cornell.edu wrote:

So that code just works around the ellipse, making 3 steps at the
fixed length, right?  The hard part isn't doing that---it's being able
to automatically update so that you get the correct answer.  What
happens if you try to do this manual process but for an ellipse that
starts with a full segment whose endpoint is [0,b+extra] for some
extra corner offset distance?  Or one that starts the same but ends at
[b,L/2].  I haven't actually tried running these processes to see how
it behaves.

On Mon, Aug 8, 2022 at 4:47 PM Father Horton fatherhorton@gmail.com
wrote:

Here's a Python version that gets the first quadrant right:

import math

major = 2
minor = 1

length = 1.03

px = length / 2
py = minor

for i in range(1, 3):
c = px / major
d = py / minor
print(f"Adjusted point off circle is ({c:.3f},{d:.3f})")

 a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d *

d))) / (2 * (d * d + c * c))

 b = math.sqrt(1 - a * a)

 print(f"Point on circle is ({a:.3f}, {b:.3f})")

 ex = a * major
 ey = b * minor
 print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})")

 m = (py - ey) / (px - ex)
 xhat = math.sqrt(length * length / (1 + m * m))
 yhat = m * xhat
 px = px + xhat
 py = py + yhat

 print(f"New point off circle is ({px:.3f}, {py:.3f})")

On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano avm4@cornell.edu wrote:

It's never necessary to do more than half the ellipse, which I think
makes handling the multiplicity of tangents easier.

On Mon, Aug 8, 2022 at 4:30 PM Father Horton fatherhorton@gmail.com

wrote:

On Mon, Aug 8, 2022 at 3:23 PM Michael Möller <

y and x if divisible by 4, right?

Right, which would make calculation easier since I wouldn't have to

deal with those nasty quadrant changes.


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


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

You change L until it works. I'd start with an estimate (Ramanujan's?) of the perimeter of the ellipse and divide by N to get an estimate for L. Step around and if L is too short, increase it by say 10%, and if it's too long, decrease by 10%. Once you have the right distance bracketed, do a binary search. On Mon, Aug 8, 2022 at 4:29 PM Adrian Mariano <avm4@cornell.edu> wrote: > So that code just works around the ellipse, making 3 steps at the > fixed length, right? The hard part isn't doing that---it's being able > to automatically update so that you get the correct answer. What > happens if you try to do this manual process but for an ellipse that > starts with a full segment whose endpoint is [0,b+extra] for some > extra corner offset distance? Or one that starts the same but ends at > [b,L/2]. I haven't actually tried running these processes to see how > it behaves. > > On Mon, Aug 8, 2022 at 4:47 PM Father Horton <fatherhorton@gmail.com> > wrote: > > > > Here's a Python version that gets the first quadrant right: > > > > import math > > > > major = 2 > > minor = 1 > > > > length = 1.03 > > > > px = length / 2 > > py = minor > > > > for i in range(1, 3): > > c = px / major > > d = py / minor > > print(f"Adjusted point off circle is ({c:.3f},{d:.3f})") > > > > > > a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d * > d))) / (2 * (d * d + c * c)) > > b = math.sqrt(1 - a * a) > > > > print(f"Point on circle is ({a:.3f}, {b:.3f})") > > > > ex = a * major > > ey = b * minor > > print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})") > > > > m = (py - ey) / (px - ex) > > xhat = math.sqrt(length * length / (1 + m * m)) > > yhat = m * xhat > > px = px + xhat > > py = py + yhat > > > > print(f"New point off circle is ({px:.3f}, {py:.3f})") > > > > > > On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano <avm4@cornell.edu> wrote: > >> > >> It's never necessary to do more than half the ellipse, which I think > >> makes handling the multiplicity of tangents easier. > >> > >> On Mon, Aug 8, 2022 at 4:30 PM Father Horton <fatherhorton@gmail.com> > wrote: > >> > > >> > > >> > > >> > On Mon, Aug 8, 2022 at 3:23 PM Michael Möller < > private2michael@gmail.com> wrote: > >> >> > >> >> y and x if divisible by 4, right? > >> > > >> > > >> > Right, which would make calculation easier since I wouldn't have to > deal with those nasty quadrant changes. > >> > _______________________________________________ > >> > 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 > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
AM
Adrian Mariano
Mon, Aug 8, 2022 10:18 PM

Did you see my post earlier that actually implements the entire
end-to-end process, including estimating L

When starting at a point there are TWO parameters, L and "extra", the
distance of the point away from the ellipse.  If you have extra wrong
you will presumably never get a solution no matter how much you fiddle
with L.  This could be addressed by hitting with a 2d optimization
method, but as I said, that seems overcomplex and I don't have such a
code implemented in OpenSCAD.

Actually I was just thinking a bit more about the case of starting a
quadrant and ending on a flat.  That means start at [b,L/2] and end on
[a,L/2].  I tweaked the code to end with y=L/2 and it fails.  That is,
the resulting point it finds doesn't have x=b.  But there doesn't seem
to be another degree of freedom.  It would therefore appear that the
case of four flat ellipse ends is generally impossible.  Have I missed
something?

On Mon, Aug 8, 2022 at 5:37 PM Father Horton fatherhorton@gmail.com wrote:

You change L until it works. I'd start with an estimate (Ramanujan's?) of the perimeter of the ellipse and divide by N to get an estimate for L. Step around and if L is too short, increase it by say 10%, and if it's too long, decrease by 10%. Once you have the right distance bracketed, do a binary search.

On Mon, Aug 8, 2022 at 4:29 PM Adrian Mariano avm4@cornell.edu wrote:

So that code just works around the ellipse, making 3 steps at the
fixed length, right?  The hard part isn't doing that---it's being able
to automatically update so that you get the correct answer.  What
happens if you try to do this manual process but for an ellipse that
starts with a full segment whose endpoint is [0,b+extra] for some
extra corner offset distance?  Or one that starts the same but ends at
[b,L/2].  I haven't actually tried running these processes to see how
it behaves.

On Mon, Aug 8, 2022 at 4:47 PM Father Horton fatherhorton@gmail.com wrote:

Here's a Python version that gets the first quadrant right:

import math

major = 2
minor = 1

length = 1.03

px = length / 2
py = minor

for i in range(1, 3):
c = px / major
d = py / minor
print(f"Adjusted point off circle is ({c:.3f},{d:.3f})")

a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d * d))) / (2 * (d * d + c * c))
b = math.sqrt(1 - a * a)

print(f"Point on circle is ({a:.3f}, {b:.3f})")

ex = a * major
ey = b * minor
print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})")

m = (py - ey) / (px - ex)
xhat = math.sqrt(length * length / (1 + m * m))
yhat = m * xhat
px = px + xhat
py = py + yhat

print(f"New point off circle is ({px:.3f}, {py:.3f})")

On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano avm4@cornell.edu wrote:

It's never necessary to do more than half the ellipse, which I think
makes handling the multiplicity of tangents easier.

On Mon, Aug 8, 2022 at 4:30 PM Father Horton fatherhorton@gmail.com wrote:

On Mon, Aug 8, 2022 at 3:23 PM Michael Möller private2michael@gmail.com wrote:

y and x if divisible by 4, right?

Right, which would make calculation easier since I wouldn't have to deal with those nasty quadrant changes.


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


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

Did you see my post earlier that actually implements the entire end-to-end process, including estimating L When starting at a point there are TWO parameters, L and "extra", the distance of the point away from the ellipse. If you have extra wrong you will presumably never get a solution no matter how much you fiddle with L. This could be addressed by hitting with a 2d optimization method, but as I said, that seems overcomplex and I don't have such a code implemented in OpenSCAD. Actually I was just thinking a bit more about the case of starting a quadrant and ending on a flat. That means start at [b,L/2] and end on [a,L/2]. I tweaked the code to end with y=L/2 and it fails. That is, the resulting point it finds doesn't have x=b. But there doesn't seem to be another degree of freedom. It would therefore appear that the case of four flat ellipse ends is generally impossible. Have I missed something? On Mon, Aug 8, 2022 at 5:37 PM Father Horton <fatherhorton@gmail.com> wrote: > > You change L until it works. I'd start with an estimate (Ramanujan's?) of the perimeter of the ellipse and divide by N to get an estimate for L. Step around and if L is too short, increase it by say 10%, and if it's too long, decrease by 10%. Once you have the right distance bracketed, do a binary search. > > On Mon, Aug 8, 2022 at 4:29 PM Adrian Mariano <avm4@cornell.edu> wrote: >> >> So that code just works around the ellipse, making 3 steps at the >> fixed length, right? The hard part isn't doing that---it's being able >> to automatically update so that you get the correct answer. What >> happens if you try to do this manual process but for an ellipse that >> starts with a full segment whose endpoint is [0,b+extra] for some >> extra corner offset distance? Or one that starts the same but ends at >> [b,L/2]. I haven't actually tried running these processes to see how >> it behaves. >> >> On Mon, Aug 8, 2022 at 4:47 PM Father Horton <fatherhorton@gmail.com> wrote: >> > >> > Here's a Python version that gets the first quadrant right: >> > >> > import math >> > >> > major = 2 >> > minor = 1 >> > >> > length = 1.03 >> > >> > px = length / 2 >> > py = minor >> > >> > for i in range(1, 3): >> > c = px / major >> > d = py / minor >> > print(f"Adjusted point off circle is ({c:.3f},{d:.3f})") >> > >> > >> > a = (2 * c + math.sqrt(4 * c * c - 4 * (d * d + c * c) * (1 - d * d))) / (2 * (d * d + c * c)) >> > b = math.sqrt(1 - a * a) >> > >> > print(f"Point on circle is ({a:.3f}, {b:.3f})") >> > >> > ex = a * major >> > ey = b * minor >> > print(f"Point on ellipse is ({ex:.3f}, {ey:.3f})") >> > >> > m = (py - ey) / (px - ex) >> > xhat = math.sqrt(length * length / (1 + m * m)) >> > yhat = m * xhat >> > px = px + xhat >> > py = py + yhat >> > >> > print(f"New point off circle is ({px:.3f}, {py:.3f})") >> > >> > >> > On Mon, Aug 8, 2022 at 3:41 PM Adrian Mariano <avm4@cornell.edu> wrote: >> >> >> >> It's never necessary to do more than half the ellipse, which I think >> >> makes handling the multiplicity of tangents easier. >> >> >> >> On Mon, Aug 8, 2022 at 4:30 PM Father Horton <fatherhorton@gmail.com> wrote: >> >> > >> >> > >> >> > >> >> > On Mon, Aug 8, 2022 at 3:23 PM Michael Möller <private2michael@gmail.com> wrote: >> >> >> >> >> >> y and x if divisible by 4, right? >> >> > >> >> > >> >> > Right, which would make calculation easier since I wouldn't have to deal with those nasty quadrant changes. >> >> > _______________________________________________ >> >> > 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 >> _______________________________________________ >> 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
BA
Brian Allen
Tue, Aug 9, 2022 1:14 AM

Thank you Douglas! That was super helpful.

Boy, I really opened a can of worms with this question! But I've enjoyed all of the discussion (the 3% of it that wasn't over my head). Thanks everyone!

Brian

On Sat, Aug 6, 2022, at 5:49 AM, Douglas Miller wrote:

That is correct: the shape Brian wants is not an ellipse, but (probably)
a hyperellipse.

The standard equation of an ellipse is (x/a)^2 + (y/b)^2 = 1  where a, b > 0

By contrast, the standard equation of a hyperellipse is |x/a|^n +
|y/b|^n = 1 where a, b > 0 and n > 2

This can be generated by this function

function f(i,a,b,n) =
let(theta=i*360)
[a * cos(theta), sign(180-theta) * b *
pow((1-pow(abs(cos(theta)),n)),1/n) ];

For example:

points = [ for(i=[0:0.01:1]) f(i,12,7,2.5) ]; // semi-major axis = 12,
semi-minor axis = 7, n = 2.5
polygon(points);

I imagine that Brian will want to use a value of n that is only slightly
greater than 2. A good starting value for experimentation appears to be
n = 2.25.

On 8/2/2022 8:04 PM, Jordan Brown wrote:

On 8/2/2022 4:46 PM, Brian Allen wrote:

I created an oval using:
inMm = 25.4;
fullW = 35.5 * inMm;
fullL = 54.5 * inMm;
resize([fullW, fullL, 1])
circle(d=fullW);
[...]
You're taking a circle and stretching it; the result of that
stretching is an ellipse.

I'm not 100% sure - maybe one of the real math wizards can chime in -
but I think the shape you are asking for would not be an ellipse.


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

Thank you Douglas! That was super helpful. Boy, I really opened a can of worms with this question! But I've enjoyed all of the discussion (the 3% of it that wasn't over my head). Thanks everyone! Brian On Sat, Aug 6, 2022, at 5:49 AM, Douglas Miller wrote: > That is correct: the shape Brian wants is not an ellipse, but (probably) > a hyperellipse. > > The standard equation of an ellipse is (x/a)^2 + (y/b)^2 = 1 where a, b > 0 > > By contrast, the standard equation of a hyperellipse is |x/a|^n + > |y/b|^n = 1 where a, b > 0 and n > 2 > > This can be generated by this function > > function f(i,a,b,n) = > let(theta=i*360) > [a * cos(theta), sign(180-theta) * b * > pow((1-pow(abs(cos(theta)),n)),1/n) ]; > > For example: > > points = [ for(i=[0:0.01:1]) f(i,12,7,2.5) ]; // semi-major axis = 12, > semi-minor axis = 7, n = 2.5 > polygon(points); > > I imagine that Brian will want to use a value of n that is only slightly > greater than 2. A good starting value for experimentation appears to be > n = 2.25. > > On 8/2/2022 8:04 PM, Jordan Brown wrote: > > On 8/2/2022 4:46 PM, Brian Allen wrote: > >> I created an oval using: > >> inMm = 25.4; > >> fullW = 35.5 * inMm; > >> fullL = 54.5 * inMm; > >> resize([fullW, fullL, 1]) > >> circle(d=fullW); > > [...] > > You're taking a circle and stretching it; the result of that > > stretching is an ellipse. > > > > I'm not 100% sure - maybe one of the real math wizards can chime in - > > but I think the shape you are asking for would not be an ellipse. > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >