IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

 
 Ответить  Открыть новую тему 
> Сжатие и растяжение графика
}0pa
сообщение 22.10.2006 13:36
Сообщение #1


Пионер
**

Группа: Пользователи
Сообщений: 75
Пол: Мужской

Репутация: -  0  +


Вот значит написал программу выводящую на экран график функции, оси, деление и подпись осей....
Помогите плиз организовать сжатие и растяжение графика вдоль оси Ох: т.е. при нажатии стрелки вправо - растяжение, стрелка влево - сжатие...
Код

uses Crt, Graph;
var
x,y,h:real;
I1,I2,J1,J2,k:integer;
x1,x2,y1,y2:integer;
i,n,j:integer;
s:string;
driver,Regim:integer;

function II(x:real):Integer;
begin
  II:=I1 + Trunc ((x-x1)*(I2-I1)/(x2-x1))
end;

function JJ(y:real):Integer;
begin
  JJ:=J1 + Trunc ((y-y1)*(J2-J1)/(y2-y1))
end;

begin
n:=30;
x1:=-3;x2:=5;
y1:=-7;y2:=2;
I1:=10;I2:=400;
j1:=10;J2:=300;
h:=(x2-x1)/n;
driver:=VGA;
Regim:=1;
InitGraph(Driver,Regim,'');
SetColor(blue);
SetFillStyle(blue,yellow);
Bar(I1,J1,I2,J2);
rectangle(I1,J1,I2,J2);
SetColor(LightRed);

MoveTo(II(x1),JJ(0));LineTo(II(x2),JJ(0));
MoveTo(II(0),JJ(y1));LineTo(II(0),JJ(y2));

for i:=x1 to x2 do
begin
  PutPixel(II(x1+i+3),JJ(0),15);  {cena deleniya}
  str(i,s);
  OutTextXY(II(x1+i+3-0.05),JJ(0.1),s)
end;

for j:=y1 to y2 do   {-5,1}        
begin
  if j=0 then
  else
   begin
    str(-j,s);
    PutPixel(II(0),JJ(y1+j+(-y1)),15);      {думаю, что в этом цикле ошибка}
    OutTextXY(II(0.1),JJ(y1+j+(-y1)),s)
   end
end;

OutTextXY(II(x2),JJ(0.1),'x');
Line(II(x2),JJ(0),II(x2-0.1),JJ(0+0.05));
Line(II(x2),JJ(0),II(x2-0.1),JJ(0-0.05));

OutTextXY(II(-0.2),JJ(y1-0.18),'y');
Line(II(0),JJ(y1),II(0.1),JJ(y1+0.15));
Line(II(0),JJ(y1),II(-0.1),JJ(y1+0.15));
SetBkColor(white);
SetColor(green);x:=x1;y:=sqrt(x*x+2);
MoveTo(II(x),JJ(-y));

for i:=1 to n do
begin
   x:=x+h;
   y:=sqrt(x*x+2);
   LineTo(II(x),JJ(-y))
  end;
readln;
closegraph
end.


--------------------
Ну, а почему бы в свободное время не позаниматься программированием?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
}0pa
сообщение 23.10.2006 13:00
Сообщение #2


Пионер
**

Группа: Пользователи
Сообщений: 75
Пол: Мужской

Репутация: -  0  +


Да,я понимаю, что это нудная задачка...Ну, помогите хотя бы правильно обозначить деление осей координат
Я разделил на отрезки, но что-то для Оу-оси деление неправильное. И вообще, я думаю, чтобы справиться с этой задачей, нужно организовать цикл, в котором при нажатии стрелок будет увеличиваться(уменьшаться) кол-во делений оси Ох...Что скажете?


--------------------
Ну, а почему бы в свободное время не позаниматься программированием?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
мисс_граффити
сообщение 23.10.2006 13:06
Сообщение #3


просто человек
******

Группа: Модераторы
Сообщений: 3 641
Пол: Женский
Реальное имя: Юлия

Репутация: -  55  +


а у тебя тот код, что ты привел, нормально компилируется и работает?

по поводу сжатия/растяжения. я бы хранила какой-то поправочный коэффициент, который бы при нажатии стрелки влево делился на, скажем, 2, а при нажатии вправо - умножался.
при рисовании графика его надо будет учитывать.


--------------------
Все содержимое данного сообщения (кроме цитат) является моим личным скромным мнением и на статус истины в высшей инстанции не претендует.
На вопросы по программированию, физике, математике и т.д. в аське и личке не отвечаю. Даже "один-единственный раз" в виде исключения!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
}0pa
сообщение 26.10.2006 0:33
Сообщение #4


Пионер
**

Группа: Пользователи
Сообщений: 75
Пол: Мужской

Репутация: -  0  +


Ну,помогите вставить этот кфц. в нужную часть кода...


--------------------
Ну, а почему бы в свободное время не позаниматься программированием?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
мисс_граффити
сообщение 26.10.2006 0:37
Сообщение #5


просто человек
******

Группа: Модераторы
Сообщений: 3 641
Пол: Женский
Реальное имя: Юлия

Репутация: -  55  +


ну ты сам хоть попробуй что ли.
для приличия.
и ответь на вопрос.


--------------------
Все содержимое данного сообщения (кроме цитат) является моим личным скромным мнением и на статус истины в высшей инстанции не претендует.
На вопросы по программированию, физике, математике и т.д. в аське и личке не отвечаю. Даже "один-единственный раз" в виде исключения!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
}0pa
сообщение 26.10.2006 7:28
Сообщение #6


Пионер
**

Группа: Пользователи
Сообщений: 75
Пол: Мужской

Репутация: -  0  +


Начнем с того, что эту прогу я сам написал. Но, по-моему здесь деление оси Оу выполнено неверно.


--------------------
Ну, а почему бы в свободное время не позаниматься программированием?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
мисс_граффити
сообщение 26.10.2006 12:18
Сообщение #7


просто человек
******

Группа: Модераторы
Сообщений: 3 641
Пол: Женский
Реальное имя: Юлия

Репутация: -  55  +


молодец.
у меня твой код НЕ компилируется. Вообще.
потому и спрашиваю - у ТЕБЯ он работает?
Я знаю, что у меня TP на графике иногда глючит не по делу.
Если у тебя работает - буду искать проблемы у себя. Если не работает - приведи его в состояние, чтобы хоть как-то работал.
а ты даже не соизволиваешь ответить.

Цитата
Но, по-моему здесь деление оси Оу выполнено неверно.

что он должнен делать и что делает?


--------------------
Все содержимое данного сообщения (кроме цитат) является моим личным скромным мнением и на статус истины в высшей инстанции не претендует.
На вопросы по программированию, физике, математике и т.д. в аське и личке не отвечаю. Даже "один-единственный раз" в виде исключения!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Michael_Rybak
сообщение 26.10.2006 14:33
Сообщение #8


Michael_Rybak
*****

Группа: Модераторы
Сообщений: 1 046
Пол: Мужской
Реальное имя: Michael_Rybak

Репутация: -  32  +


Изменения:

1. x1, y1, x2, y2 стали типа real

2. Добавил цикл, о котором ты говоришь ("чтобы справиться с этой задачей, нужно организовать цикл...")

3. В тело цикла перенес инициализацию x1, x2, y1, y2, h и n. Область вывода (I1, J1, I2, J2) остается неизменной, меняется (по x) только часть графика, которую мы туда впихиваем. n меняем, потому что с увеличением масштаба точки улетают высоко вверх, а видимая часть рисуется с плохой детализацией.

4. Вот в этом цикле:

for i:=x1 to x2 do
begin
PutPixel(II(x1+i+3),JJ(0),15); {cena deleniya}
str(i,s);
OutTextXY(II(x1+i+3-0.05),JJ(0.1),s)
end;


Во-первых, добавил округление x1 и x2, т.к. они теперь дробные. Во-вторых, вместо x1+i-3 оставил просто i, потому что x1+3 изначально у тебя равно 0, а при масштабировании нужно было бы тройку домножать на коеффициент. На самом деле это не нужно:

for i:=trunc(x1)-1 to trunc(x2)+1 do
begin
PutPixel(II(i),JJ(0),15); {cena deleniya}
str(i,s);
OutTextXY(II(i-0.05),JJ(0.1),s)
end;


5. То же самое с циклом по Y. Ошибки там, мне кажется, нету. Ты все правильно понял, когда написал y1+j+(-y1). Именно это я имел ввиду в предыдущем пункте.

6. При обработке клавиш курсор_влево и курсов_вправо делаем то, что сказала мисс_граффити


uses Crt, Graph ;
var
x,y,h:real;
I1,I2,J1,J2,k:integer;
x1,x2,y1,y2:real;
i,n,j:integer;
s:string;
driver,Regim:integer;

xkoef: real;

c: char;

function II(x:real):Integer;
begin
II:=I1 + Trunc ((x-x1)*(I2-I1)/(x2-x1))
end;

function JJ(y:real):Integer;
begin
JJ:=J1 + Trunc ((y-y1)*(J2-J1)/(y2-y1))
end;

begin
I1:=10;I2:=400;
j1:=10;J2:=300;
driver:=VGA;
Regim:=1;
InitGraph(driver,regim,'');

xkoef := 1.0;

while true do begin

n:=trunc(30*xkoef);
x1:=-3*xkoef;x2:=5*xkoef;
y1:=-7;y2:=2;
h:=(x2-x1)/n;


SetColor(blue);
SetFillStyle(blue,yellow);
Bar(I1,J1,I2,J2);
rectangle(I1,J1,I2,J2);
SetColor(LightRed);

MoveTo(II(x1),JJ(0));LineTo(II(x2),JJ(0));
MoveTo(II(0),JJ(y1));LineTo(II(0),JJ(y2));

for i:=trunc(x1)-1 to trunc(x2)+1 do
begin
PutPixel(II(i),JJ(0),15); {cena deleniya}
str(i,s);
OutTextXY(II(i-0.05),JJ(0.1),s)
end;

for j:=trunc(y1)-1 to trunc(y2)+1 do {-5,1}
begin
if j=0 then
else
begin
str(-j,s);
PutPixel(II(0),JJ(j),15);
OutTextXY(II(0.1),JJ(j),s)
end
end;

OutTextXY(II(x2),JJ(0.1),'x');
Line(II(x2),JJ(0),II(x2-0.1),JJ(0+0.05));
Line(II(x2),JJ(0),II(x2-0.1),JJ(0-0.05));

OutTextXY(II(-0.2),JJ(y1-0.18),'y');
Line(II(0),JJ(y1),II(0.1),JJ(y1+0.15));
Line(II(0),JJ(y1),II(-0.1),JJ(y1+0.15));
SetBkColor(white);
SetColor(green);x:=x1;y:=sqrt(x*x+2);
MoveTo(II(x),JJ(-y));

for i:=1 to n do
begin
x:=x+h;
y:=sqrt(x*x+2);
LineTo(II(x),JJ(-y))
end;

while true do begin
c := ReadKey;

if Ord( c ) = 27 then
halt;

if Ord( c ) = 0 then begin
c := ReadKey;
if Ord( c ) = 75 then
xkoef := xkoef * 1.2
else if Ord( c ) = 77 then
xkoef := xkoef / 1.2
else
continue;

break;
end;

end;
end;

readln;
closegraph
end.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
}0pa
сообщение 26.10.2006 19:04
Сообщение #9


Пионер
**

Группа: Пользователи
Сообщений: 75
Пол: Мужской

Репутация: -  0  +


Спасибо, за прекрасное объяснение. Я бы тебе плюсег поставил, но пока не могу
Р.С. Только, когда сжимаем график, остается что-то вроде шлейфа на экране


--------------------
Ну, а почему бы в свободное время не позаниматься программированием?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
}0pa
сообщение 28.10.2006 18:37
Сообщение #10


Пионер
**

Группа: Пользователи
Сообщений: 75
Пол: Мужской

Репутация: -  0  +


Код
while true do begin

Что значит это?


--------------------
Ну, а почему бы в свободное время не позаниматься программированием?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
мисс_граффити
сообщение 28.10.2006 18:48
Сообщение #11


просто человек
******

Группа: Модераторы
Сообщений: 3 641
Пол: Женский
Реальное имя: Юлия

Репутация: -  55  +


Цитата(}0pa @ 28.10.2006 19:37) *

Код
while true do begin

Что значит это?

вечный цикл.
правда, из него предусмотрен выход по break
странная конструкция...


--------------------
Все содержимое данного сообщения (кроме цитат) является моим личным скромным мнением и на статус истины в высшей инстанции не претендует.
На вопросы по программированию, физике, математике и т.д. в аське и личке не отвечаю. Даже "один-единственный раз" в виде исключения!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Michael_Rybak
сообщение 28.10.2006 19:12
Сообщение #12


Michael_Rybak
*****

Группа: Модераторы
Сообщений: 1 046
Пол: Мужской
Реальное имя: Michael_Rybak

Репутация: -  32  +


Цитата
Только, когда сжимаем график, остается что-то вроде шлейфа на экране


У меня "шлейф" остается только снаружи желтого прямоугольника. Если подобрать I1, I2, J1 и J2 так, чтоб он занимал весь экран - след оставаться не будет, потому что мы его каждый раз перерисовываем. Есть вроде функции типа GetMaxX и GetMaxY. Или, если хочешь не на весь экран - сначала закрашивай весь экран каждый раз, а уже потом рисуй все остальное.

Цитата
вечный цикл.
правда, из него предусмотрен выход по break
странная конструкция...


По-моему, совсем не странная. Предположим, нам надо сделать такую последовательность действий:

1) сделать набор действий А
2) если выполняется условие В, прекратить работу
3) сделать набор действий С
4) перейти к шагу 1

Ее можно осуществить либо так:
A();
while B do begin
C();
A();
end;

либо так:

while true do begin
A();
if not B then break;
C();
end;

Второй вариант мне кажется более естественным. Кроме того, если А - целый блок текста, то его придется (в первом случае) либо дублировать, либо выносить в процедуру.

Это один пример. А у нас другой случай - чтобы организовать эту конструкцию по-другому, понадобился бы дополнительный флаг:

repeat
stop:= false;

c := ReadKey;

if Ord( c ) = 27 then
halt;

if Ord( c ) = 0 then begin
c := ReadKey;
if Ord( c ) = 75 then begin
xkoef := xkoef * 1.2;
stop := true;
end else if Ord( c ) = 77 then begin
xkoef := xkoef / 1.2;
stop := true;
end;
end;

until stop;


Так тоже нормально, в принципе. Но мне без флага больше нравится.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
мисс_граффити
сообщение 28.10.2006 19:59
Сообщение #13


просто человек
******

Группа: Модераторы
Сообщений: 3 641
Пол: Женский
Реальное имя: Юлия

Репутация: -  55  +


ну, еще бывают циклы с постусловием - это если говорить о первом случае.
  while true do begin
c := ReadKey;
if Ord( с ) = 27 then
halt;
if Ord( c ) = 0 then
begin
c := ReadKey;
if Ord( с ) = 75 then
xkoef := xkoef * 1.2
else
if Ord( с )= 77 then
xkoef := xkoef / 1.2
else
continue;
break;
end;

то есть выход из цикла происходит во вполне определенном случае - при ord( с )=77 или 75. так? почему бы это не сделать while (ord( с )<>77) and (ord( с )<>75), считав заранее первое с?я еще лучше - вообще в постусловие засунуть. Тогда и continue не нужно - мы в любом случае перейдем на следующий проход (кроме с=27, но это совсем другое).
хотя, конечно, лучшая программа - это работающая программа....

Сообщение отредактировано: volvo - 2.11.2006 19:55


--------------------
Все содержимое данного сообщения (кроме цитат) является моим личным скромным мнением и на статус истины в высшей инстанции не претендует.
На вопросы по программированию, физике, математике и т.д. в аське и личке не отвечаю. Даже "один-единственный раз" в виде исключения!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 12.08.2025 6:17
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"