Turbo Pascal rysowanie paraboli z punktów p i q


(Paulpolska) #1

Szukałem w necie i sam próbowałem z 3h ale nic. Umiem narysować wykres funkcji kwadrtatowej (parabole).

Ale jak zrobić żeby parabola rysowała się względem punktów p i q jakie obliczy program ??

Wyliczanie p i q oraz miejsc zerowych już mam obliczone. Jest tylko te pytanie powyżej oraz na jakie zmienne zmienić miejsca zerowe praz p i q żeby integrowały z funkcją "Line" która rysuję na podstawie pixeli linie. (układ współrzędnych)


(Ryan) #2

Możesz uchylić rąbka tajemnicy i powiedzieć czym są punktu p i q? :slight_smile: Czy to przykładowe punkty na paraboli, czy też punkt na paraboli (q) i rzut na prostą (p) taki, że ||pq|| = ||fq|| (gdzie f to ognisko)? Ciężko po Twoim opisie odgadnąć, co próbujesz zrobić.


([alex]) #3

Ryan , p i q to standardowy zapis w matematyce inna forma równania kwadratowego (postać kanoniczna) y=a*(x-p)^2 +q

Jeżeli masz poprawnie narysowaną funkcje to p i q to współrzędne minima/maksima funkcji kwadratowej.

Normalnie rysujesz funkcje i normalnie zaznaczasz np czerwonym kółeczkiem punkt (p,q)

Więc chyba nie bardzo rozumiem pytania.


(Ryan) #4

Też pytania nie rozumiem, szczególnie że autor pytania określił p i q mianem punktów. :wink:


(Tomek Matz) #5

Ryan ma rację, to zdanie "względem punktów p i q" jest mylące. Ale zgaduję podobnie jak [alex], że chodzi Ci o współrzędne p i q wierzchołka paraboli. Generalnie trochę pogooglowałem i nie udało mi się znaleźć gotowej funkcji służącej do rysowania paraboli mając jako dane wierzchołek paraboli i jej miejsca zerowe. Naskrobałem natomiast taki kod (widoczny poniżej), który możesz sobie przetestować i zobaczyć, czy Ci to wystarczy (testowane przy użyciu free pascal, ale inne kompilatory też nie powinny mieć problemów z tym kodem).

program Parabola;

uses

	crt, graph;

type

	TPoint = record

		X: double;

		Y: double;

	end;

	TRoot = record

		Point: TPoint;

		IsDual: boolean;

		IsValid: boolean;

	end;

	TRoots = array[1..2] of TRoot;

var

	a,b,c,userXScale,userYScale: double;

	myXScale,myYScale: integer;

	roots: TRoots;

	vertex: TPoint;


function FindRoots(a,b,c: double): TRoots;

var

	delta: double;

	roots: TRoots;

begin

	roots[1].IsValid:= false;

	roots[2].IsValid:= false;


	delta:= sqr(b)-4*a*c;

	if delta = 0 then begin

		roots[1].Point.X:= (-b)/(2*a);

		roots[1].Point.Y:= 0;

		roots[1].IsDual:= true;

		roots[1].IsValid:= true;

	end else if delta > 0 then begin

		roots[1].Point.X:= (-b-sqrt(delta))/(2*a);

		roots[1].Point.Y:= 0;

		roots[1].IsDual:= false;

		roots[1].IsValid:= true;


		roots[2].Point.X:= (-b+sqrt(delta))/(2*a);

		roots[2].Point.Y:= 0;

		roots[2].IsDual:= false;

		roots[2].IsValid:= true;

	end;


	FindRoots:= roots;

end;


function FindVertex(a,b,c: double): TPoint;

var

	vertex: TPoint;

begin

	vertex.X:= (-b)/(2*a);

	vertex.Y:= (-(sqr(b)-4*a*c))/(4*a);


	FindVertex:= vertex;

end;


function FormatDoubleType(value: double): string;

var

	result: string;

begin

	Str(value:8:3,result);

	FormatDoubleType:= result;

end;


procedure DisplayRoots(roots: TRoots);

begin

	if roots[1].IsValid then begin

		if roots[1].IsDual then begin

			writeln('Dane rownanie kwadratowe posiada jeden pierwiastek podwojny o wspolrzednych:');

			writeln('x = ',FormatDoubleType(roots[1].Point.X), ', y = ',FormatDoubleType(roots[1].Point.Y));

		end else begin

			writeln('Dane rownanie kwadratowe posiada dwa pierwiastki o wspolrzednych:');

			writeln('x = ',FormatDoubleType(roots[1].Point.X), ', y = ',FormatDoubleType(roots[1].Point.Y));

			writeln('x = ',FormatDoubleType(roots[2].Point.X), ', y = ',FormatDoubleType(roots[2].Point.Y));

		end;

	end else writeln('Dane rownanie kwadratowe nie posiada miejsc zerowych.');

	writeln;

end;


procedure DisplayVertex(vertex: TPoint);

begin

	writeln('Wierzcholek paraboli znajduje sie w punkcie o wspolrzednych:');

	writeln('x = ',FormatDoubleType(vertex.X), ', y = ',FormatDoubleType(vertex.Y));

	writeln;

end;


procedure InitializeGraph;

var

	gd,gm : integer;

begin

	DetectGraph(gd,gm);

	InitGraph(gd,gm,'');

end;


procedure DrawLegend(a,b,c,userXScale,userYScale:double; myXScale,myYScale:integer);

var

	i, value, halfMaxY, halfMaxX: integer;

begin

	SetColor(white);

	SetTextStyle(1, horizdir, 1);


	halfMaxX:= GetMaxX div 2;

	halfMaxY:= GetMaxY div 2;


	OutTextXY(20, 20, 'f(x) = ' + FormatDoubleType(a) + '*x^2 + ' + FormatDoubleType(b) + '*x + ' + FormatDoubleType(c));


	i:= 1;

	value:= myXScale;

	while value <= halfMaxX do

	begin

		Line(halfMaxX + value, halfMaxY - 10, halfMaxX + value, halfMaxY + 10);

		OutTextXY(halfMaxX + (i-1)*myXScale, halfMaxY + 20, FormatDoubleType(userXScale*i));


		Line(halfMaxX - value, halfMaxY - 10, halfMaxX - value, halfMaxY + 10);

		OutTextXY(halfMaxX - value, halfMaxY + 20, FormatDoubleType(-(userXScale*i)));


		i:= i+1;

		value:=i*myXScale;

	end;


	i:= 1;

	value:= myYScale;

	while value <= halfMaxY do

	begin

		Line(halfMaxX - 10, halfMaxY + value, halfMaxX + 10, halfMaxY + value);

		OutTextXY(halfMaxX + 20, halfMaxY + value, FormatDoubleType(-(userYScale*i)));


		Line(halfMaxX - 10, halfMaxY - value, halfMaxX + 10, halfMaxY - value);

		OutTextXY(halfMaxX + 20, halfMaxY - value, FormatDoubleType(userYScale*i));


		i:= i+1;

		value:=i*myYScale;

	end;



end;


procedure DrawXYAxis;

begin

	SetColor(white);


	Line(0, GetMaxY div 2, GetMaxX, GetMaxY div 2);

    Line(GetMaxX div 2, 0, GetMaxX div 2, GetMaxY);

end;


procedure DrawParabola(a,b,c,userXScale,userYScale:double; myXScale,myYScale:integer);

var

	x, y, previousX, previousY, halfMaxY, halfMaxX: integer;

	xParabola, yParabola, scaleX, scaleY: double;

begin

	SetColor(red);


	scaleX:= userXScale/myXScale;

	scaleY:= userYScale/myYScale;

	halfMaxX:= GetMaxX div 2;

	halfMaxY:= GetMaxY div 2;


	previousX:= 0;

	previousY:= 0;

	y:= 0;

	for x:= 0 to GetMaxX do

	begin

		xParabola:= (x-halfMaxX)*scaleX;

		yParabola:= a*sqr(xParabola)+b*xParabola+c;


		if (ABS(yParabola/scaleY) + halfMaxY) < MaxInt then begin

			if yParabola < 0 then y:= ABS(ROUND(yParabola/scaleY)) + halfMaxY

			else y:= halfMaxY - ROUND(yParabola/scaleY);


			if (y >= 0) and (y <= GetMaxY) then begin

				if (previousX <> 0) and (previousY <> 0) then Line(previousX, previousY, x, y);

				previousX:= x;

				previousY:= y;

			end else begin

				previousX:= 0;

				previousY:= 0;

			end;

		end;

	end;

end;


begin

	ClrScr;


	writeln('Podaj wspolczynniki rownania kwadratowego:');

	write('a: '); readln(a);

	write('b: '); readln(b);

	write('c: '); readln(c);

	writeln;

	writeln('Podaj skale wykresu:');

	write('dla osi X: '); readln(userXScale); myXScale:= 70;

	write('dla osi Y: '); readln(userYScale); myYScale:= 70;

	writeln;


	roots:= FindRoots(a,b,c);

	DisplayRoots(roots);

	vertex:= FindVertex(a,b,c);

	DisplayVertex(vertex);


	InitializeGraph;


	DrawLegend(a,b,c,userXScale,userYScale,myXScale,myYScale);

	DrawXYAxis;

	DrawParabola(a,b,c,userXScale,userYScale,myXScale,myYScale);


	readkey; CloseGraph;

end.

-- Dodane 01.06.2011 (Śr) 23:15 --

Wprowadziłem drobne zmiany w programie. Teraz można podawać skalę osi X i Y. Takie rozwiązanie przydaje się, przy niektórych parabolach, dla których np. p jest bardzo małe, a q bardzo duże. Można też pomyśleć, aby ten program przerobić tak, żeby sam ustalał skalę osi X i Y (automatycznie).

Przykładowe dane, dla których ładnie to widać, to:

a,b i c = 65

skala osi X = 0.5

skala osi Y = 50


([alex]) #6

matzu , fajnie, tylko że czytanie ze zrozumieniem zawodzi. On te p i q wylicza.


(Tomek Matz) #7

Co z tego, że wylicza? Na bazie samego p i q (oraz miejsc zerowych) nie narysuje paraboli. Wartości p i q mogą się tutaj przydać tylko i wyłącznie przy automatycznym ustalaniu wartości skali dla osi X i Y. Wykres bowiem musi zostać tak przeskalowany, żeby wierzchołek paraboli znalazł się na ekranie. Innego zastosowania tych wartości tutaj nie widzę. Ja póki, co zrobiłem to tak, że skalę ustala się ręcznie (zapewnia to większą kontrolę nad wykresem). Jeśli masz pomysł jak na podstawie samego p i q (oraz miejsc zerowych) narysować parabolę to przecież możesz napisać (ja szukałem i nie udało mi się znaleźć takiej informacji).


([alex]) #8

Wylicza skądś, prawdopodobnie z: A, B, C - typowych współczynników równania kwadratowego.

Owszem p,q to za mało ale p,q oraz miejsca zerowe - wystarczy:

A:=q/(p*p-x1*x2);

B:=-2*p*q/(p*p-x1*x2);

C:=q*x1*x2/(p*p-x1*x2);

Może o to chodziło autorowi?


(Tomek Matz) #9

Ok, dostajesz jako dane wejściowe a,b i c (u mnie w programie jest dokładnie tak samo). Wyliczasz z nich sobie miejsca zerowe i wierzchołek. Później z tego wyliczasz a, b i c, które dostałeś jako dane. Gdzie tu sens? Autorowi chodziło zapewne o to, żeby mając miejsca zerowe i wierzchołek paraboli narysować jej wykres. Zapewne liczył na to, że istnieje jakaś gotowa funkcja, która to umożliwia (coś na zasadzie jak na kartce wykonujemy wykres poglądowy mając wierzchołek i miejsca zerowe). Takiej funkcji raczej nie ma, a przynajmniej nie udało mi się takowej znaleźć i dlatego wrzuciłem kod, który pokazuje jak można to rozwiązać (i który przy okazje rysuje odpowiednio przeskalowany układ współrzędnych). Nie wiem, czy odpalałeś ten program. Jeśli nie to dołączam wykresik dla powyższych przykładowych danych http://i52.tinypic.com/o72fs8.jpg.