Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Тогда расчетными значениями параметров окна будут

xmin=1.0 xmax=1.5

ymin=0.8 ymax=1.1

 
 

Заметим, что крайние точки объекта располагаются на границах окна, чего не было в случае, рассмотренном в параграфе 2.4.

Чтобы предусмотреть некоторое свободное пространство со всех сторон экрана или листа бумаги, необходимо задать размеры области вывода несколько меньше, чем они могли быть на самом деле. Например, можно задать х min=0.2 вместо 0.0. Область вывода будет полностью определена при выборе

Xmin=0.2 Xmax=8.2

Ymin=0.5 Ymax=6.5

Как в параграфе 2.4, выполним расчет коэффициентов масштабирования:

 
 

В качестве коэффициента масштабирования f выберем наименьшее из значений fx и f y. Напомним, что все расстояния умножаются на коэффициент масштабирования, так что если будет выбран коэффициент масштабирования больше, чем fx или f y, то часть картинки определенно выйдет за пределы области вывода. В данном примере получим

f = fx=16

Совершенно ясно, что такой одинаковый коэффициент масштабирования приведет к отображению треугольника, который точно равен по ширине размеру области вывода пооси х, но в направлении оси у останется свободное пространство. Его желательно распределить поровну между нижней и верхней частями области вывода. Это можно реализовать, если для расчета константы с2 вместо минимального значения Y, как в параграфе 2.4, выбрать позицию центра Y. Аналогичным образом вычисляется и значение с1

xC=0.5(xmin+xmax)=0.5(1.0+1.5)=1.25

yC=0.5(ymin+ymax)=0.5(0.8+1.1)=0.95

XC=0.5(Xmin+Xmax)=0.5(0.2+8.2)=4.2

YC=0.5(Ymin+Ymax)=0.5(0.5+6.5)=3.5

c1=XC- f xC=4.2-16*1.25=-15.8

c2=YC- f yC=3.5-16*0.95=-11.7

Теперь для любой точки объекта (х, у) позиция отображаемой точки (X, У) рассчитывается по формулам

X= f x+c1=16x-15.8

Y=fy+c2=16y-11.7

Составим программу, которая будет вычерчивать картинку, окно для которой не может быть задано заранее, и в этом примере будет освещено несколько новых аспектов языка Си. Используем случайные числа для генерации кривой непредсказуемой формы и размеров, где, как обычно, кривая аппроксимируется большим числом отрезков прямых линий. Автоматическое масштабирование и позиционирование позволяют решить задачу, практически не разрешимую иным путем. Для каждого отрезка будут генерироваться значения координат х и у, которые будут записываться в файл на диске. Точнее говоря, будем записывать так называемые структуры, содержащие тройки

х у code

где пара (х,у) определяет координаты точки, в которую должно перемещаться перо, а параметр code может принимать значение 0 или 1, означающее состояние пера "поднято" или "опущено" соответственно. Другими словами,

х у 0 означает move(X, Y)

х у 1 означает draw(X, Y)

где Х и Y— экранные координаты, соответствующие мировым координатам х и у, В этом примере будем использовать специальную программу, которая генерирует кривую и записывает тройки чисел в файл SCRATCH, За выполнением этой программы должен последовать запуск общей программы вычерчивания GENPLOT, которая дважды считывает тройки чисел. Первый раз — для определения параметров окна хmin хmax уmin уmax и второй раз — для фактического выполнения операций перемещения пера и вычерчивания, используя экранные координаты X, У, полученные путем пересчета координат х, у в системе мировых координат.

В программе генерацию кривой будем начинать с точки начала координат и перемещаться каждый раз на одну единицу расстояния. Всегда существует текущее направление j и текущий угол поворота a. В исходном состоянии оба эти значения равны нулю. Перед каждым шагом угол a увеличивается на случайно выбранное значение угла в пределах от -6° до +6° (целое число). Полученный новый угол поворота добавляется к текущему направлению j для получения нового направления. Ограничим максимальное значение кривизны и уменьшим шанс для вырождения в окружность. Для этого модифицируем описанный алгоритм и будем задавать значение 0 для угла a каждый раз, когда его абсолютное значение превышает 15°. Тогда получим следующую программу:

 

/* CURVGEN: Генерация случайной кривой */

#include "math.h"

#include "stdio.h"

#include "time.h"

#include <stdlib.h>

#include "grasptc0.h"

/* Этот хидерный файл нужен при обращении к */

/* функции времени для получения случайного числа */

FILE *fp;

struct {float xx; float yy; int ii;}s;

void pfopen()

{fp=fopen("scratch","wb");}

 

void pmove(float x, float y)

{

s.xx=x; s.yy=y; s.ii=0;

fwrite(&s,sizeof s,1,fp);

}

 

void pdraw(float x, float y)

{

s.xx=x; s.yy=y; s.ii=1;

fwrite(&s,sizeof s,1,fp);

}

 

void pfclose()

{fclose(fp);}

 

float direction()

{

static int phi=0, alpha=0, first=1;

float pi=3.1415926;

long int seed;

if(first){first=0;time(&seed);srand((int)seed);}

alpha+=rand()%13-6;

if(abs(alpha)>15)alpha=0;

phi+=alpha;

return ((float)phi*pi/180.0);

}

 

void main()

{ int i,N=500;

float x=0.0, y=0.0, x0, y0, phi=direction();

pfopen(); pmove(x, y);

for (i=1;i<=N;i++)

{ x0=x; y0=y; phi=direction(); x=x0+cos(phi); y=y0+sin(phi);

pdraw(x, y);

}

pfclose();

}

В функции direction показано обращение к функции инициализации датчика случайных чисел srand. Ее аргумент seed определяет начальное значение для генерации случайных чисел. Функция time применяется для присвоения значения аргументу seed, зависящему от текущего времени. Таким образом, будут генерироваться различные кривые при каждом новом запуске программы. Функция rand выдает большое неотрицательное целое число. Оно преобразуется в целое число в диапазоне от 0 до 12 путем использования остатка от деления на 13, то есть

0<=rand()%13<=12

-6<=rand()%13-6<6

Другие новые аспекты применения языка Си относятся к опе­рациям ввода и вывода. Для большинства функций ввода/вывода в программу необходимо вставлять директиву #include <stdio.h>, которая осуществляет “включение” файла стандартных заголовков функций ввода/вывода. В языке Си различается форматированный и неформатированный ввод/вывод. Наиболее часто используются следующие функции:

 

scanf: форматированный ввод с терминала

printf: форматированный вывод на терминал

fscanf: форматированный ввод из файла

fprintf: форматированный вывод в файл

fread: неформатированный ввод из файла

fwrite: неформатированный вывод в файл.

Форматированный ввод/вывод имеет дело с читаемыми символами: имеется структура строк, аналогичная строкам на печатной странице. Неформатированные данные имеют такую же структуру, как они записаны в памяти. Например, целые числа представляются фиксированным количеством битов. В нашем случае с целью повышения эффективности был использован неформатированный ввод/вывод. Файл "открывается" обращением к функции fopen. Вторым аргументом может быть либо строка “r” для инициирования считывания, либо строка "w" для записи. (Для неформатированного ввода/вывода некоторые компиляторы требуют задания иных строк вместо "r" или "w".) Переменная s обозначает структуру, содержащую три числа: х, у и code, которые будут записываться в файл. "Указатель" &s на эту переменную является первым аргументом для функции fwrite. Запись &s можно рассматривать как обозначение адреса переменной s. Второй аргумент, sizeof s, равен размеру одной структуры s, третий аргумент, равный 1, означает количество структур, подлежащих записи. Четвертым аргументом, fp, является указатель файла, полученный из обращения к функции f open. Теперь можно рассмотреть общую программу, которая будет считывать тройки, определять размеры окна, выполнять пересчет мировых координат в экранные координаты и, наконец, вычерчивать картинку в пределах заданной области вывода. Также вычерчиваются небольшие уголки в углах области вывода и точка в середине нижней границы, так что абстрактную картинку можно ориентировать относительно верха и низа (если точка и уголки нежелательны, их легко можно исключить).

Заметим, что в этой программе файл SCRATCH открывается дважды. Операции закрытия и открытия приводят к "перемотке" файла к началу.

 

#include "stdio.h"

#include "grasptc0.h"

void init_viewport(float *pXmin, float *pXmax, float *pYmin, float *pYmax)

{

float Xmin, Xmax, Ymin, Ymax, eps=0.2;

printf ("Задайте границы области вывода Xmin, Xmax, Ymin, Ymax ");

scanf("%f %f %f %f", &Xmin, &Xmax, &Ymin, &Ymax);

initgr();

move(Xmin, Ymin+eps);

draw(Xmin, Ymin);

draw(Xmin+eps, Ymin);

move(Xmax-eps, Ymin);

draw(Xmax, Ymin);

draw(Xmax, Ymin+eps);

move(Xmax, Ymax-eps);

draw(Xmax, Ymax);

draw(Xmax-eps, Ymax);

move(Xmin+eps, Ymax);

draw(Xmin, Ymax);

draw(Xmin, Ymax-eps);

move((Xmin+Xmax)/2,Ymin);

draw((Xmin+Xmax)/2,Ymin);

*pXmin=Xmin;*pXmax=Xmax;*pYmin=Ymin;*pYmax=Ymax;

}

 

void main()

{ float x, y, xmin, xmax, ymin, ymax, X, Y, Xmin, Xmax,

Ymin, Ymax, fx, fy, f, xC, yC, XC, YC, c1, c2;

FILE *fp;

struct {float xx; float yy; int ii;} s;

fp=fopen("scratch", "rb");

xmin=ymin=1e30; xmax=ymax=-xmin;

while (fread(&s, sizeof s, 1, fp))

{ x=s.xx; y=s.yy;

if (x<xmin) xmin=x;

if (x>xmax) xmax=x;

if (y<ymin) ymin=y;

if (y>ymax) ymax=y;

}

fclose(fp);

init_viewport(&Xmin, &Xmax, &Ymin, &Ymax);

fx=(Xmax-Xmin)/(xmax-xmin); fy=(Ymax-Ymin)/(ymax-ymin);

f=(fx<fy?fx:fy);

xC=0.5*(xmin+xmax); yC=0.5*(ymin+ymax);

XC=0.5*(Xmin+Xmax); YC=0.5*(Ymin+Ymax);

c1=XC-f*xC; c2=YC-f*yC;

fp=fopen("scratch", "rb");

while (fread(&s, sizeof s, 1, fp))

{ x=s.xx; y=s.yy;

X=f*x+c1; Y=f*y+c2;

if(s.ii) draw(X, Y);

else move(X, Y);

}

fclose(fp);

endgr();

}

<== предыдущая лекция | следующая лекция ==>
Автоматический подбор размеров и позиции | Лекція 2. Методологічні основи країнознавства. Методи і методики країно­знавчих досліджень
Поделиться с друзьями:


Дата добавления: 2014-01-14; Просмотров: 357; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.042 сек.