Board index » delphi » Kinda like an ellipse, but more than top left and bottom right

Kinda like an ellipse, but more than top left and bottom right

Hi all!!

Here is my situation.  I need to draw an elliptical type shape.

There is a reference point
There will be four defining points from the reference point.
Example:
The point to the bottom right(south east) is 30 pixels away from the
reference point.
The point to the bottom left (south west) is 60 pixels away from the
reference point.
The point to the upper left (north west) is 45 pixels away from the
reference point.
The point to the upper right (north east) is 85 pixels away from the
reference point.

What is the best method in completing this task.  The resulting ellipse or
elongated ellipse must be relatively smooth in appearance.

Thanks in advance for any help.

Bryan

 

Re:Kinda like an ellipse, but more than top left and bottom right


Quote
Bryan Ray <br...@gtracks.com> wrote in message 3afca65c$1_1@dnews...
> Hi all!!

> Here is my situation.  I need to draw an elliptical type shape.

> There is a reference point
> There will be four defining points from the reference point.
> Example:
> The point to the bottom right(south east) is 30 pixels away from the
> reference point.
> The point to the bottom left (south west) is 60 pixels away from the
> reference point.
> The point to the upper left (north west) is 45 pixels away from the
> reference point.
> The point to the upper right (north east) is 85 pixels away from the
> reference point.

> What is the best method in completing this task.  The resulting ellipse or
> elongated ellipse must be relatively smooth in appearance.

> Thanks in advance for any help.

> Bryan

Bryan , an ellipse is an ellipse : hope you remember there is a mathematical
relation between x and y coords of the screen (xy plane) : if i'm not wrong
it should be :
x^2/a^2+y^2/b^2=1.

Now if you choose the 4 points without any criterion you are very lucky if
an ellipse curve pass for each of them ...

But i'm sure you have something else in mind , so sorry if i'm too
mathematical here but it is because my cultural background...

Re:Kinda like an ellipse, but more than top left and bottom right


Francesco,

Sorry, but I'm confused about the math stuff.  Is there a Delphi function or
anything that I can use to connect these lines with a curved appearance and
not boxy looking?
I also need the curve to pass through these points.  I know there has to be
a way of doing this, and I could probably do it with alot of work.  I was
hoping that Delphi had something that made this somewhat easier.

Thanks
Bryan

Quote
"Francesco Savastano" <francescos...@tiscalinet.it> wrote in message

news:3afce9e6_1@dnews...
Quote

> Bryan Ray <br...@gtracks.com> wrote in message 3afca65c$1_1@dnews...
> > Hi all!!

> > Here is my situation.  I need to draw an elliptical type shape.

> > There is a reference point
> > There will be four defining points from the reference point.
> > Example:
> > The point to the bottom right(south east) is 30 pixels away from the
> > reference point.
> > The point to the bottom left (south west) is 60 pixels away from the
> > reference point.
> > The point to the upper left (north west) is 45 pixels away from the
> > reference point.
> > The point to the upper right (north east) is 85 pixels away from the
> > reference point.

> > What is the best method in completing this task.  The resulting ellipse
or
> > elongated ellipse must be relatively smooth in appearance.

> > Thanks in advance for any help.

> > Bryan

> Bryan , an ellipse is an ellipse : hope you remember there is a
mathematical
> relation between x and y coords of the screen (xy plane) : if i'm not
wrong
> it should be :
> x^2/a^2+y^2/b^2=1.

> Now if you choose the 4 points without any criterion you are very lucky if
> an ellipse curve pass for each of them ...

> But i'm sure you have something else in mind , so sorry if i'm too
> mathematical here but it is because my cultural background...

Re:Kinda like an ellipse, but more than top left and bottom right


Quote
Bryan Ray <br...@gtracks.com> wrote in message 3afd3d73$1_2@dnews...
> Francesco,

> Sorry, but I'm confused about the math stuff.  Is there a Delphi function
or
> anything that I can use to connect these lines with a curved appearance
and
> not boxy looking?
> I also need the curve to pass through these points.  I know there has to
be
> a way of doing this, and I could probably do it with alot of work.  I was
> hoping that Delphi had something that made this somewhat easier.

> Thanks
> Bryan

Give a look to polybezier method of tcanvas : you have to specify an array
of tpoint as argument : now if i'm not wrong 4 points are the minimum to
have a polybezier , so it could be your case , but ... there is a but :
polybezier only approximates the points between 1st and fourth : as you can
see the solution is not very easy : 4 points seem to be few to define a
closed curve like that you are trying to do if i well understand ..

Re:Kinda like an ellipse, but more than top left and bottom right


Thanks for the info, I'll take a look at it.

Bryan

Quote
"Francesco Savastano" <francescos...@tiscalinet.it> wrote in message

news:3afd80a8$1_2@dnews...
Quote

> Bryan Ray <br...@gtracks.com> wrote in message 3afd3d73$1_2@dnews...
> > Francesco,

> > Sorry, but I'm confused about the math stuff.  Is there a Delphi
function
> or
> > anything that I can use to connect these lines with a curved appearance
> and
> > not boxy looking?
> > I also need the curve to pass through these points.  I know there has to
> be
> > a way of doing this, and I could probably do it with alot of work.  I
was
> > hoping that Delphi had something that made this somewhat easier.

> > Thanks
> > Bryan

> Give a look to polybezier method of tcanvas : you have to specify an array
> of tpoint as argument : now if i'm not wrong 4 points are the minimum to
> have a polybezier , so it could be your case , but ... there is a but :
> polybezier only approximates the points between 1st and fourth : as you
can
> see the solution is not very easy : 4 points seem to be few to define a
> closed curve like that you are trying to do if i well understand ..

Re:Kinda like an ellipse, but more than top left and bottom right


Hi Bryan,

if you want to draw a slanted ellipse, there's an article on
http://home.t-online.de/home/Robert.Rossmair/ellipse.htm which explains
how to do this with Bezier curves. There's also a recent thread here
which discusses ellipses (->beziergon), but I couldn't find the start
anymore, and google ****s. Robert's article doesn't say explicitly how
you can get an ellipse going through given points. Giving 4 points and
a center is giving too many constraints, there usually won't be an
ellipse going through all 4 points, or, if there is, there'll be more
than one. I've been trying to come up with "an ellipse one might have
in mind". You have to give it 2 points which you want to make up a main
axis, then you can specify a 3rd point which should also lie on the
ellipse for control of the length of the second main axis. My excuse
is, that I've always wanted to understand how these Bezier things work
:>. If you can't use it, don't bother, I'm sure I can.

If you want to draw something that is only a smooth curve through your
points, you have to say more precisely what you have in mind, as there
are tons of ways.

Renate

[interface snipped]
implementation

{$R *.DFM}

{ellipse stuff}
type
  TFloatpoint = record
    x, y: double;
  end;

  TFloatPointArray = array of TFloatpoint;
  TPointArray = array of TPoint;

function FloatPoint(x, y: double): TFloatpoint;
begin
  Result.x := x;
  Result.y := y;
end;

function CircleBezier: TFloatPointArray;
{Bezier points to approximate a unit circle.}
{get better ellipse approximations by starting
with a better circle approximation.
For more info see
http://home.t-online.de/home/Robert.Rossmair/ellipse.htm}
var r: double;
i: integer;
begin
  r := 4 / 3 * (sqrt(2) - 1);
  //4/3*(1-cos(pi/4))/sin(pi/4)

  SetLength(Result, 13);
  Result[0] := FloatPoint(1, 0);
  Result[1] := FloatPoint(1, r);
  Result[2] := FloatPoint(r, 1);
  Result[3] := FloatPoint(0, 1);
  for i:=1 to 3 do
    Result[3+i]:=FloatPoint(-Result[3-i].x,Result[3-i].y);
  for i:=1 to 6 do
    Result[6+i]:=FloatPoint(Result[6-i].x,-Result[6-i].y);
end;

function Transform(const p: TFloatPointArray; A, b, c, d, e, f:
double): TFloatPointArray;
{transform all points of p by affine transformation given by
a,b,c,d,e,f}
var i: Integer;
begin
  SetLength(Result, Length(p));
  for i := 0 to High(p) do
  begin
    Result[i].x := e + A * p[i].x + b * p[i].y;
    Result[i].y := f + c * p[i].x + d * p[i].y;
  end;
end;

function ToPoint(const p: TFloatPointArray): TPointArray;
{Floatpoints to points}
var i: Integer;
begin
  SetLength(Result, Length(p));
  for i := 0 to High(p) do
    Result[i] := Point(round(p[i].x), round(p[i].y));
end;

function dot(u, v: TFloatpoint): double;
begin
  Result := u.x * v.x + u.y * v.y;
end;

const epsilon = 1.E-4;
  infinity = 1.E3;

procedure BezierEllipse(ACanvas: TCanvas; p1, p2, p3: TPoint);
{bezier approximation of an ellipse going through the
points p1, p2 and p3, such that the line p1p2 is a main axis}
var p, q: TFloatPointArray;
  r: TPointArray;
  pc, u, v, vp: TFloatpoint;
  l: double;
begin
  pc.x := 0.5 * (p1.x + p2.x);
  pc.y := 0.5 * (p1.y + p2.y);
  //center point

  u.x := p2.x - pc.x;
  v.x := p3.x - pc.x;
  u.y := p2.y - pc.y;
  v.y := p3.y - pc.y;
  vp.x := v.y;
  vp.y := -v.x;
  l := sqr(dot(u, u)) - sqr(dot(u, v));
  if l > epsilon then
    l := dot(u, vp) / sqrt(l)
  else
    l := infinity;
  p := CircleBezier;
  q := Transform(p,u.x, -l * u.y, u.y, l * u.x, pc.x, pc.y);
  //transforms circle to ellipse through p2, p3 with
  //center pc.
  //ellipses are affine transformations of circles
  //l is computed so the transformation is orthogonal,
  //the center is at pc, and the ellipse goes through p2,p3
  r := ToPoint(q);
  ACanvas.PolyBezier(r);
end;
{End ellipse stuff}

{test:
 click on p1 and p2 to define a main axis of the ellipse.
 Then on a third point p3 which should be on the ellipse. Moving
 the mouse moves p3 and you can see how the ellipse changes.
 Another click locks the ellipse.}
var
  pc, p1, p2, p3: TPoint;
  Moving: Boolean;

procedure Circle(c: TCanvas; p: TPoint);
begin
  c.Pen.Color := clred;
  c.Ellipse(p.x - 2, p.y - 2, p.x + 2, p.y + 2);
end;

procedure TForm1.Image1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; x, y: Integer);
const Count: Integer = 0;
begin
  if Moving then
  begin
    Moving := False;
    exit;
  end;
  Circle(Image1.Canvas, Point(x, y));
  inc(Count);
  case Count of
    1: p1 := Point(x, y);
    2: p2 := Point(x, y);
    3: begin
        p3 := Point(x, y);
        Image1.Canvas.Pen.Color := clgreen;
        BezierEllipse(Image1.Canvas, p1, p2, p3);
        Count := 0;
        Moving := True;
      end;
  end;
end;

procedure TForm1.ClearImage;
begin
  with Image1 do
    Canvas.FillRect(ClientRect);
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  x, y: Integer);
begin
  if Moving then
  begin
    ClearImage;
    Image1.Canvas.Pen.Color := clgreen;
    BezierEllipse(Image1.Canvas, p1, p2, Point(x, y));
    Circle(Image1.Canvas, pc);
    Circle(Image1.Canvas, p1);
    Circle(Image1.Canvas, p2);
    Circle(Image1.Canvas, Point(x, y));
    Application.ProcessMessages;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ClearImage;
end;

end.

Re:Kinda like an ellipse, but more than top left and bottom right


Thanks for the info...
I'll keep trying.

Bryan

Quote
"Renate Schaaf" <rena...@xmission.com> wrote in message

news:VA.0000039c.070a6797@xmission.com...
Quote
> Hi Bryan,

> if you want to draw a slanted ellipse, there's an article on
> http://home.t-online.de/home/Robert.Rossmair/ellipse.htm which explains
> how to do this with Bezier curves. There's also a recent thread here
> which discusses ellipses (->beziergon), but I couldn't find the start
> anymore, and google ****s. Robert's article doesn't say explicitly how
> you can get an ellipse going through given points. Giving 4 points and
> a center is giving too many constraints, there usually won't be an
> ellipse going through all 4 points, or, if there is, there'll be more
> than one. I've been trying to come up with "an ellipse one might have
> in mind". You have to give it 2 points which you want to make up a main
> axis, then you can specify a 3rd point which should also lie on the
> ellipse for control of the length of the second main axis. My excuse
> is, that I've always wanted to understand how these Bezier things work
> :>. If you can't use it, don't bother, I'm sure I can.

> If you want to draw something that is only a smooth curve through your
> points, you have to say more precisely what you have in mind, as there
> are tons of ways.

> Renate

> [interface snipped]
> implementation

> {$R *.DFM}

> {ellipse stuff}
> type
>   TFloatpoint = record
>     x, y: double;
>   end;

>   TFloatPointArray = array of TFloatpoint;
>   TPointArray = array of TPoint;

> function FloatPoint(x, y: double): TFloatpoint;
> begin
>   Result.x := x;
>   Result.y := y;
> end;

> function CircleBezier: TFloatPointArray;
> {Bezier points to approximate a unit circle.}
> {get better ellipse approximations by starting
> with a better circle approximation.
> For more info see
> http://home.t-online.de/home/Robert.Rossmair/ellipse.htm}
> var r: double;
> i: integer;
> begin
>   r := 4 / 3 * (sqrt(2) - 1);
>   //4/3*(1-cos(pi/4))/sin(pi/4)

>   SetLength(Result, 13);
>   Result[0] := FloatPoint(1, 0);
>   Result[1] := FloatPoint(1, r);
>   Result[2] := FloatPoint(r, 1);
>   Result[3] := FloatPoint(0, 1);
>   for i:=1 to 3 do
>     Result[3+i]:=FloatPoint(-Result[3-i].x,Result[3-i].y);
>   for i:=1 to 6 do
>     Result[6+i]:=FloatPoint(Result[6-i].x,-Result[6-i].y);
> end;

> function Transform(const p: TFloatPointArray; A, b, c, d, e, f:
> double): TFloatPointArray;
> {transform all points of p by affine transformation given by
> a,b,c,d,e,f}
> var i: Integer;
> begin
>   SetLength(Result, Length(p));
>   for i := 0 to High(p) do
>   begin
>     Result[i].x := e + A * p[i].x + b * p[i].y;
>     Result[i].y := f + c * p[i].x + d * p[i].y;
>   end;
> end;

> function ToPoint(const p: TFloatPointArray): TPointArray;
> {Floatpoints to points}
> var i: Integer;
> begin
>   SetLength(Result, Length(p));
>   for i := 0 to High(p) do
>     Result[i] := Point(round(p[i].x), round(p[i].y));
> end;

> function dot(u, v: TFloatpoint): double;
> begin
>   Result := u.x * v.x + u.y * v.y;
> end;

> const epsilon = 1.E-4;
>   infinity = 1.E3;

> procedure BezierEllipse(ACanvas: TCanvas; p1, p2, p3: TPoint);
> {bezier approximation of an ellipse going through the
> points p1, p2 and p3, such that the line p1p2 is a main axis}
> var p, q: TFloatPointArray;
>   r: TPointArray;
>   pc, u, v, vp: TFloatpoint;
>   l: double;
> begin
>   pc.x := 0.5 * (p1.x + p2.x);
>   pc.y := 0.5 * (p1.y + p2.y);
>   //center point

>   u.x := p2.x - pc.x;
>   v.x := p3.x - pc.x;
>   u.y := p2.y - pc.y;
>   v.y := p3.y - pc.y;
>   vp.x := v.y;
>   vp.y := -v.x;
>   l := sqr(dot(u, u)) - sqr(dot(u, v));
>   if l > epsilon then
>     l := dot(u, vp) / sqrt(l)
>   else
>     l := infinity;
>   p := CircleBezier;
>   q := Transform(p,u.x, -l * u.y, u.y, l * u.x, pc.x, pc.y);
>   //transforms circle to ellipse through p2, p3 with
>   //center pc.
>   //ellipses are affine transformations of circles
>   //l is computed so the transformation is orthogonal,
>   //the center is at pc, and the ellipse goes through p2,p3
>   r := ToPoint(q);
>   ACanvas.PolyBezier(r);
> end;
> {End ellipse stuff}

> {test:
>  click on p1 and p2 to define a main axis of the ellipse.
>  Then on a third point p3 which should be on the ellipse. Moving
>  the mouse moves p3 and you can see how the ellipse changes.
>  Another click locks the ellipse.}
> var
>   pc, p1, p2, p3: TPoint;
>   Moving: Boolean;

> procedure Circle(c: TCanvas; p: TPoint);
> begin
>   c.Pen.Color := clred;
>   c.Ellipse(p.x - 2, p.y - 2, p.x + 2, p.y + 2);
> end;

> procedure TForm1.Image1MouseDown(Sender: TObject;
>   Button: TMouseButton; Shift: TShiftState; x, y: Integer);
> const Count: Integer = 0;
> begin
>   if Moving then
>   begin
>     Moving := False;
>     exit;
>   end;
>   Circle(Image1.Canvas, Point(x, y));
>   inc(Count);
>   case Count of
>     1: p1 := Point(x, y);
>     2: p2 := Point(x, y);
>     3: begin
>         p3 := Point(x, y);
>         Image1.Canvas.Pen.Color := clgreen;
>         BezierEllipse(Image1.Canvas, p1, p2, p3);
>         Count := 0;
>         Moving := True;
>       end;
>   end;
> end;

> procedure TForm1.ClearImage;
> begin
>   with Image1 do
>     Canvas.FillRect(ClientRect);
> end;

> procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
>   x, y: Integer);
> begin
>   if Moving then
>   begin
>     ClearImage;
>     Image1.Canvas.Pen.Color := clgreen;
>     BezierEllipse(Image1.Canvas, p1, p2, Point(x, y));
>     Circle(Image1.Canvas, pc);
>     Circle(Image1.Canvas, p1);
>     Circle(Image1.Canvas, p2);
>     Circle(Image1.Canvas, Point(x, y));
>     Application.ProcessMessages;
>   end;
> end;

> procedure TForm1.FormCreate(Sender: TObject);
> begin
>   ClearImage;
> end;

> end.

Re:Kinda like an ellipse, but more than top left and bottom right


Quote
In article <3aff3f62_2@dnews>, Bryan Ray wrote:
> Thanks for the info...
> I'll keep trying.

I for one don't really understand what you're trying to do. You've
given us 4 /distances/, which could be anywhere in their respective
quadrants.

Is that the limit of the information you have to define the ellipse?

Re-posted (original by Clemens Ladisch 23 Apr 2001) for your benefit
which may or may not be of use. (Note the url for whizzkidtech at the
bottom, it's well worth a visit):

Quote
Gordon Whittam wrote:
>    Using 4 Beziers with the 'handles' at 1/4 of the
bounding rectangle
> and end points at 1/2, gets close, but not quite the
same as a Windows
> Ellipse.

> Q2: If it's my version that's wrong, can it be done
accurately using
> Beziers

No. It is not possible to draw a perfect circle/ellipse
using Bzier
curves.

Quote
> and if so is there a specific ratio which will get the
desired
> results?

You can approximate an ellipse pretty well.
Nobody will notice the difference, as Windows does the
same:

After calling Ellipse(hDC, -10000000, -10000000,
10000000, 10000000)
and GetPath(...), you get:
( 10000000,        0)
( 10000000, -5522847)
(  5522848,-10000000)
(        0,-10000000)
( -5522847,-10000000)
(-10000000, -5522847)
(-10000000,        0)
(-10000000,  5522847)
( -5522847, 10000000)
(        0, 10000000)
(  5522848, 10000000)
( 10000000,  5522847)
( 10000000,        0)

The ratio Windows uses is approximately 0.5522847498;
the exact value is computed by 4/3 * (sqrt(2) - 1).
(from www.whizkidtech.net/bezier/circle/ )

HTH
Clemens
[End old posting]

Gordon

Re:Kinda like an ellipse, but more than top left and bottom right


What is the "referenc point"?

With the info you have given, one could assume you are drawing an ellipse with
the following proportions:

from southeast (30 pix) to northwest (45 pix) = 75 pixels
from southwest (60 pix) to northeast (85 pix) = 145 pixels

So, you have an ellipse with a major axis of 145 pixels and a minor axis of 75
pixels.  Further, since you are using the terms, southwest, northeast, etc.,
you are implying that the axes of the ellipse are rotated 45 degrees with
respect to the (x,y) axis.  Finally, the center of this ellispe is offset from
the reference point.

Is this what you mean to be saying?

Quote
Bryan Ray wrote:
> Hi all!!

> Here is my situation.  I need to draw an elliptical type shape.

> There is a reference point
> There will be four defining points from the reference point.
> Example:
> The point to the bottom right(south east) is 30 pixels away from the
> reference point.
> The point to the bottom left (south west) is 60 pixels away from the
> reference point.
> The point to the upper left (north west) is 45 pixels away from the
> reference point.
> The point to the upper right (north east) is 85 pixels away from the
> reference point.

> What is the best method in completing this task.  The resulting ellipse or
> elongated ellipse must be relatively smooth in appearance.

> Thanks in advance for any help.

> Bryan

Re:Kinda like an ellipse, but more than top left and bottom right


Sue,

I'll try to explain in more detail.

I have a point x,y
At direction of 45 degrees from point x,y and distance of 85 pixels (north
east) from point x,y, I have point(NE)
At direction of 135 degrees from point x,y and distance of 30 pixels (south
east) from point x,y, I have point(SE)
At direction of 225 degrees from point x,y and distance of 60 pixels (south
west) from point x,y, I have point(SW)
At direction of 315 degrees from point x,y and distance of 45 pixels (north
west) from point x,y, I have point(NW).

Now I need to connect all of these points with a line.  The line cannot be a
straight line, but must be curved or elliptical.
I hope this explanation helps.

I'll try to illistrate this graphically.

                                 NW                        NE
                                            x,y
                               SW            SE

Thanks
Bryan

"Sue D. Nom" <su...@courthouse.com> wrote in message
news:3B0047FC.505B7197@courthouse.com...

Quote
> What is the "referenc point"?

> With the info you have given, one could assume you are drawing an ellipse
with
> the following proportions:

> from southeast (30 pix) to northwest (45 pix) = 75 pixels
> from southwest (60 pix) to northeast (85 pix) = 145 pixels

> So, you have an ellipse with a major axis of 145 pixels and a minor axis
of 75
> pixels.  Further, since you are using the terms, southwest, northeast,
etc.,
> you are implying that the axes of the ellipse are rotated 45 degrees with
> respect to the (x,y) axis.  Finally, the center of this ellispe is offset
from
> the reference point.

> Is this what you mean to be saying?

> Bryan Ray wrote:

> > Hi all!!

> > Here is my situation.  I need to draw an elliptical type shape.

> > There is a reference point
> > There will be four defining points from the reference point.
> > Example:
> > The point to the bottom right(south east) is 30 pixels away from the
> > reference point.
> > The point to the bottom left (south west) is 60 pixels away from the
> > reference point.
> > The point to the upper left (north west) is 45 pixels away from the
> > reference point.
> > The point to the upper right (north east) is 85 pixels away from the
> > reference point.

> > What is the best method in completing this task.  The resulting ellipse
or
> > elongated ellipse must be relatively smooth in appearance.

> > Thanks in advance for any help.

> > Bryan

Re:Kinda like an ellipse, but more than top left and bottom right


Quote
In article <3b00962c$1_2@dnews>, Bryan Ray wrote:
> Now I need to connect all of these points with a line.  The line cannot be a
> straight line, but must be curved or elliptical.
> I hope this explanation helps.

Have a look at this and tell us if it's what you were thinking of.

http://www.mgcsoft.com/images/pse.jpg

Gordon

Go to page: [1] [2] [3]

Other Threads