The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

I wish to follow an eliptic route .

For example I wish to go from a point (100,100) and to draw an ellipse ( with next dimensions for example : 100 and 75 ), point by point, to my canvas.

Attention, POINT BY POINT .

For example I wish to go from a point (100,100) and to draw an ellipse ( with next dimensions for example : 100 and 75 ), point by point, to my canvas.

Attention, POINT BY POINT .

sorry, for delay but I was last 2 weeks offline.

You can contact me C_Lababidi@hotmail.com

Best Regards

Cesario

Cesario provided you with correct answer. You could tweek it a little by replacing Trunc with Round (more accurate curve) and using precalculated trigonometric table (much more speed).

: I am looking an algorithm for drawing an ellipse .

: The input shall be the midpoint and the two axes .

Here is one implementation in C of the algorithm...

Remark : Only one quarter of the ellipse is computated, the rest

is set by symmetry.

a and b are the half-axes (I hope this is the right

word for it) of the ellipse in x- and y-direction.

If you like a circle set a=b=radius .

--------------------------

procedure symmetry(x, y: Integer);

begin

PUT_PIXEL( x, y); // This would obviously be inlined!

PUT_PIXEL(-x, y); // and offset by a constant amount

PUT_PIXEL(-x,-y);

PUT_PIXEL( x,-y);

end;

procedure bresenham_ellipse(a, b: Integer);

var

x, y, a2, b2, S, T: Integer;

begin

a2 := a*a;

b2 := b*b;

x := 0;

y := b;

S := a2*(1-2*b) + 2*b2;

T := b2 - 2*a2*(2*b-1);

symmetry(x, y);

repeat

if S < 0 then

begin

S := S + 2*b2*(2*x+3);

T = T + 4*b2*(x+1);

Inc(x);

end

else

if T < 0 then

begin

S := S + 2*b2*(2*x+3) - 4*a2*(y-1);

T := T + 4*b2*(x+1) - 2*a2*(2*y-3);

Inc(x);

Dec(y);

end

else

begin

S := S - 4*a2*(y-1);

T := T - 2*a2*(2*y-3);

Dec(y);

end;

symmetry(x, y);

until y <= 0;

end;

But I wait anothers working solutions for anothers points . Alike kretzschmar's Q.O.W.

If you have solution or can improve proposed one the put a comment and take new points :)

But I wait anothers working solutions for anothers points . Alike kretzschmar's Q.O.W.

If you have solution or can improve proposed one the put a comment and take new points :)

But I wait anothers working solutions for anothers points . Alike kretzschmar's Q.O.W.

If you have solution or can improve proposed one the put a comment and take new points :)

This are optimized versions (DrawEllipse() and even faster, DrawEllipse2()):

const RESOLUTION = 100; // larger=better but slower

// Requires global vars (trig. tables)

var

Form1: TForm1;

SinTable, CosTable: Array [0..360*RESOLUTION] of Double;

......

procedure BuildTrigTable;

// Precalculation of sin and cos. Resolution is 1/RESOLUTION degree.

var i: Integer;

radian: Double;

begin

for i:= 0 to 360*RESOLUTION do begin

radian:=i*PI/(180*RESOLUTI

SinTable[i]:=Sin(radian);

CosTable[i]:=Cos(radian);

end;

end;

procedure DrawEllipse(Where: TCanvas; Center, R: TPoint);

// Draws ellipse, centered around Center, with halfaxes: a=R.X , b=R.Y

var i,x,y, xold, yold: Integer;

begin

for i:= 0 to 360*RESOLUTION do begin

x:=Center.X+Round(R.X*CosT

y:=Center.Y+Round(R.Y*SinT

if (xold<>x) or (yold<>y) then Where.Pixels[x,y]:=Where.P

xold:=x; yold:=y;

end;

end;

procedure DrawEllipse2(Where: TCanvas; Center, R: TPoint);

// Draws ellipse, centered around Center, with halfaxes: a=R.X , b=R.Y

var i,x,y, xold, yold: Integer;

begin

for i:= 0 to 360*RESOLUTION do begin

x:=Center.X+Round(R.X*CosT

y:=Center.Y+Round(R.Y*SinT

if i=0 then begin

Where.Pixels[x,y]:=Where.P

Where.MoveTo(x,y);

end

else if (xold<>x) or (yold<>y) then Where.LineTo(x,y);

xold:=x; yold:=y;

end;

end;

COMMENTS

-------------

1. DrawEllipse() uses precalculated trig. table instead of slow trig. functions. On the down-side, you must call BuildTrigTable before using DrawEllipse().

2. BuildTrigTable is called only once. After that, tables are built, and we can use them instead of real sin,cos.

It is usually called at the execution start (for example, initialization section, OnCreate event of the main form etc.)

3. RESOLUTION defines granulation of real functions. This shouldn't be below 10 for DrawEllipse().

4. DrawEllipse2() is good for very low RESOLUTION (even for RESOLUTION=1 !!). But, it uses LineTo to aproximate ellipse segments.

If you want real speed, and are willing to live without Pixels (that is, use LineTo), it's better to use DrawEllipse2() with RESOLUTION of 1..10, which is *very* fast.

EXAMPLE OF USE (place TButton on the form)

--------------------------

procedure TForm1.Button1Click(Sender

var i: Integer;

begin

BuildTrigTable; // Call it *ONLY* once (OnForm1Create is good place)

Randomize;

for i:=1 to 100 do

DrawEllipse(Form1.Canvas,

Point(100+Random(100),100+

Point(50+Random(100) , 10+Random(100)));

end;

If you want to create animation effect, you can regulate delay in my code by changing RESOLUTION const. Decrease it and you'll get faster animation if that's what you want. Set it to 1 and see what happens.

But, I don't quite understand what you want:

> If you have solution or can improve proposed one the put a comment and take new points :)

Could you tell us what you mean by improved solution? What should be improved in accepted answer?

About improvement ... any proposed solution not just the accepted one . Just to be a better way alike accepted .

unit EllipseUnit1;

{This is an illustration of an ellipse that starts at

point (100,100) and fits in a rectangle of 100,75. Continues

until back again to point (100,100)}

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls, Math;

type

TForm1 = class(TForm)

Button1: TButton;

Button2: TButton;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender

var

mx, my, x, y, cnt: Integer;

y1: Real;

begin

Canvas.Pen.Color := clGreen;

//first a bit of a container

//100 Width, 75 Height; 1/2 width = 50; 1/2 height = 38

Canvas.MoveTo(100, 100); // Start point for request

Canvas.LineTo(150, 100);

Canvas.LineTo(150, 175);

Canvas.LineTo(50, 175);

Canvas.LineTo(50, 100);

Canvas.LineTo(100, 100);

Canvas.Pen.Color := clBlue;

Canvas.LineTo(100, 175); // Axis line

Canvas.Pen.Color := clBlack;

Canvas.MoveTo(50, 138); // Axis line

//Center is located at (100,138)

Canvas.LineTo(100, 138);

Canvas.Pen.Color := clWhite;

Canvas.LineTo(150, 138);// Axis line

{ A bit of Standard Algebra:

Draw an Ellipse

Center of the ellipse is located at h,k and the

major axis is 'a' the minor axis is 'b'

the equation is:

(((x-h)^2)/a^2) + (((y-k)^2)/b^2) = 1

Eventual substitutions:

a = 50; b = 38 ; h = 100; k = 100;

Algebraic equivalents

(((y-k)^2)/b^2) = 1 - (((x-h)^2)/a^2)

(y-k)^2) = (1- (((x-h)^2)/a^2))* b^2

and solving for y

y-k = + square root ((1- (((x-h)^2)/a^2))* b^2)

y-k = - square root ((1- (((x-h)^2)/a^2))* b^2)

y = k + square root ((1- (((x-h)^2)/a^2))* b^2)

y = k - square root ((1- (((x-h)^2)/a^2))* b^2)

substitution of values

y = 100 + square root ((1- (((x-100)^2)/50^2))* 38^2)

y = 100 - square root ((1- (((x-100)^2)/50^2))* 38^2)

square root = power raised to the 0.5

y = 100 - power(((1- ((power(x-100),2)/(power,5

}

Canvas.TextOut(100,80, 'Starts Here at (100,100)');

Canvas.Pen.Color := clRed;

Canvas.MoveTo(100, 138);

for x := 100 to 150 do

begin

Sleep(5);

y := Round(137.5 - (power((1 - (power(x - 100, 2)) / (power(50, 2))) * power(38, 2), 0.5)));

Canvas.LineTo(X, Y);

end;

Canvas.Pen.Color := clYellow;

for x := 150 downto 50 do

begin

Sleep(5);

y := Round(137.5 + (power((1 - (power(x - 100, 2)) / (power(50, 2))) * power(38, 2), 0.5)));

Canvas.LineTo(X, Y);

end;

Canvas.Pen.Color := clBlack;

for x := 51 to 100 do

begin

Sleep(5);

y := Round(137.5 - (power((1 - (power(x - 100, 2)) / (power(50, 2))) * power(38, 2), 0.5)));

Canvas.LineTo(X, Y);

end;

Canvas.TextOut(100,80, 'Ends Here at (100,100) ');

end;

procedure TForm1.Button2Click(Sender

begin

Application.Terminate;

end;

end.

// Form as text

object Form1: TForm1

Left = 456

Top = 182

Width = 258

Height = 368

Caption = 'Ellipse'

Color = clBtnFace

Font.Charset = DEFAULT_CHARSET

Font.Color = clWindowText

Font.Height = -13

Font.Name = 'MS Sans Serif'

Font.Style = []

OldCreateOrder = False

PixelsPerInch = 120

TextHeight = 16

object Button1: TButton

Left = 64

Top = 232

Width = 115

Height = 25

Caption = 'Show Ellipse'

TabOrder = 0

OnClick = Button1Click

end

object Button2: TButton

Left = 64

Top = 272

Width = 115

Height = 25

Caption = 'Close'

TabOrder = 1

OnClick = Button2Click

end

end

Goal :

From: ginsonic

Status: Waiting for Answer Points: 100

Email A Friend

I wish to follow an eliptic route.

for example I wish to go from a point(100, 100) and to draw an ellipse(with next dimensions for example

: 100 and 75), point by point, to my canvas.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.

procedure TForm1.Button1Click(Sender

var

mx,my,x,y,cnt :Integer;

begin

With Canvas Do

Begin

moveTo ( 400,200);

mx := 100;

my := 75;

For cnt := 0 to 360 do

begin

x := 400 + trunc(mx * sin ( cnt*pi/180 ));

y := 200 + Trunc(my * cos ( cnt*pi/180 ));

Pixels[x,y] := clBlack;

End;

End;

end;