ZX Spectrum графика 1994 г.

Диаграммы и графики - Курсоры; Атрибуты; Точки и линии; Запись и загрузка; Надписи; Данные для графиков; Специальные символы; Определенные пользователем символы для использования в гистограммах; Гистограммы; Круговые диаграммы; Штриховка секторов; Графики; Список программ.


ГЛАВА 6 Диаграммы и графики

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

Курсоры

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

Подпрограмма "CURSOR" (курсор) на листинге 6.1 выводит на экран две пересекающиеся прямые, нарисованные прозрачными чернилами (INK цвет 8), перекрестие которых выделяет символьный блок. Курсор передвигается под действием любой из восьми клавиш вокруг клавиши "F". Положение этих клавиш относительно "F" определяет направление движения. Если в вашем распоряжении имеется джойстик, то переделайте подпрограмму "CURSOR" с тем, чтобы движением курсора можно было управлять джойстиком, а не с клавиатуры.

Нажатием "F" вы помещаете курсор в центр экрана. Если держать клавишу нажатой, то скорость движения курсора постепенно возрастает: с курсором, который перемещается на один элемент изображения при каждом нажатии клавиши, чрезвычайно утомительно работать! Для облегчения установки курсора имеется сетка (LATTICE), которая зажигается нажатием буквы "L" и гасится повторным нажатием "L". Она автоматически исчезает, когда вы нажимаете клавишу ENTER для ввода другой точки.

Клавиши управления курсором для программы "CURSOR"

255,0

К

*

Е

R

Т

D

F

G

С

V

В

Рис. 26.

LISTING 6.1

5700 REM CURSOR

5701 REM IN - PX,PY

5702 REM OUT - PX,PY,ROW,COL

5709 REM THE NEXT LINE IS ONLY EXECUTED ON THE FIRST CALL TO CURSOR.

5710 LET PX=128: LET PY=88: LET CURSOR=5720: LET GRID=5900

5719 REM START OF MAIN CURSOR ROUTINE.

5720 INK 8: LET A=1:LET FLAG=1: OVER 1

5729 REM WAIT FOR KEYBOARD TO BE CLEAR BEFORE LOOKING FOR COMMANDS.

5730 IF INKEY$<>"" THEN GO TO 5730

5740 PLOT PX,0: DRAW 0,175: PLOT 0,PY: DRAW 255,0 5750 LET A$=INKEY$

5760 IF A$="" THEN LET A=1: GO TO 5750

5770 PLOT PX,0: DRAW 0,175: PLOT 0,PY: DRAW 255,0

5780 IF (A$="E" OR A$="D" OR A$="C") AND PX>=A THEN LET PX=PX-A

5790 IF (A$="C" OR A$="V" OR A$="B") AND PY>=A THEN LET PY=PY-A

5800 IF (A$="T" OR A$="G" OR A$="B") AND PX<=255-A THEN LET PX=PX+A

5810 IF (A$="E" OR A$="R" OR A$="T") AND PY<=175-A THEN LET PY=PY+A

5820 IF A$="F" THEN LET PX=128: LET PY=88

5830 IF A$="L" THEN GO SUB GRID

5840 IF A$<>CHR$ 13 THEN LET A=A+1: GO TO 5740

5850 LET COL=INT(PX/8): LET ROW=INT((175-PY)/8)

5860 IF FLAG=-1 THEN GO SUB GRID

5870 INK 0: OVER 0

5880 RETURN

5900 REM GRID

5909 REM ROUTINE CHANGES FLAG TO REMEMBER WHETHER GRID IS SHOWING ON SCREEN.

5910 FOR J=0 TO 255 STEP 8: PLOT J,0: DRAW 0,175: IF J<176 THEN PLOT 0,J: DRAW

5920 NEXT J: LET FLAG=-FLAG: PLOT 255,0: DRAW -255,0 5930 RETURN Упражнение 6.1

Напишите основную программу "MAIN PROGRAM", которая вызывает программу "CURSOR", а затем печатает цветной квадрат на экране в указанном месте. Программа должна также печатать номер столбца и строки, в которых находится курсор. Измените подпрограмму "CURSOR" так, чтобы стандартными клавишами курсора ("5", "6", "7", "8") можно было бы задавать перемещение курсора на один символьный блок.

Атрибуты

Можно развить идеи предыдущего пункта и написать подпрограммы, изменяющие атрибуты заданного блока или группы блоков без изменения информации, которая им соответствует в дисплейном файле. На листинге 6.2 показаны две подпрограммы, которые делают это для цвета PAPER и INK определенного множества блоков LISTING 6.2 4000 REM PAPER

4010 GO SUB CURSOR: INPUT "WHAT COLOUR ";P: INPUT "NO.OF BLOCKS "; "(ROW*COL) ";R;"*";C

4020 FOR I=ROW TO ROW+R-1: FOR J=COL TO COL+C-1 4030 PRINT AT I,J;PAPER P;INK 8;OVER 1;" ": NEXT J: NEXT I 4040 RETURN 4100 REM INK

4110 GO SUB CURSOR: INPUT "WHAT COLOUR ";P: INPUT "NO.OF BLOCKS ";"(ROW*COL) ";R;"*";C

4120 FOR I=ROW TO ROW+R-1: FOR J=COL TO COL+C-1 4130 PRINT AT I,J;PAPER 8;INK P;OVER 1;" ": NEXT J: NEXT I 4140 RETURN Упражнение 6.2

Напишите "MAIN PROGRAM", которая вводит часть своего текста, а затем позволяет вам выделять участки распечатки, используя различные цвета INK и PAPER. Напишите подпрограммы, которые бы размещались в строках от 4050 до 4150 и изменяли бы атрибуты FLASH и BRIGHT блока (почему это сведется к добавлению команд BRIGHT 8 и FLASH 8 к подпрограммам "INK" и "PAPER"?). Составьте из четырех подпрограмм одну под названием "ATRIBUTE".

Точки и линии

Достигнув простейшего интерактивного управления видом нашей диаграммы, нам предстоит заполнить детали этой диаграммы. Для этого требуются подпрограммы для нанесения точек (PLOT) и проведения прямых (DRAW). Мы могли бы использовать программу на листинге 1.8, но наносить все точки на прямой слишком утомительно. Вместо этого мы используем две подпрограммы - "POINT", которая наносит отдельные точки, и "LINE", для которой мы просто определяем две точки прежде, чем их соединить. Обе подпрограммы приведены на листинге 6.3.

LISTING 6.3 4200 REM POINT

4210 INPUT "PRESS ENTER FOR CURSOR";LINE A$

4220 GO SUB CURSOR: INPUT "OVER (1 OR 0) ";O: INPUT "COLOUR ";C 4230 PLOT INK C;OVER O;PX,PY 4240 RETURN 4300 REM LINE

4310 INPUT "PRESS ENTER FOR CURSOR ";LINE A$ 4320 GO SUB CURSOR: LET SX=PX: LET SY=PY 4330 INPUT "PRESS ENTER FOR CURSOR ";LINE A$

4340 GO SUB CURSOR: INPUT "OVER (1 OR 0) ";O: INPUT "COLOUR ";C,

4350 PLOT PAPER 8;INK C; OVER O;SX,SY

4360 DRAW PAPER 8;INK 0; OVER 0;PX-SX,PY-SY

4370 RETURN

Упражнение 6.3

Напишите программу "MAIN PROGRAM", которая с помощью подпрограмм "POINT" и "LINE" помогла бы вам сделать набросок вашего SPECTRUMa. Составьте подпрограмму, которая по параметрам, вводимым с помощью курсора, чертила бы круг; используйте подпрограмму "CIRCLE1" или "CIRCLE2", приведенные на листинге 2.10. Переделайте вашу программу из упражнения 1.3, которая чертит многоугольник так, чтобы вершины можно было задавать курсором. Добавьте опцию к подпрограмме "LINE" с тем, чтобы она могла строить кривые линии. Вам будет удобнее использовать восемь точек вокруг стороны, а не двенадцать.

Если у вас есть графическая прокладка (PAD), то вы можете перенести, используя модификации "LINE" и "POINT", грубые наброски с этой прокладки в машину. После этого вы должны написать программы, приводящие изображение в порядок, т.е. выпрямляющее прямые и сглаживающие кривые.

Запись и загрузка

Потратив много времени на создание той или иной картинки, возможно, вам захочется ее сохранить. Это достигается использованием программы "SAVE". С другой стороны, может возникнуть необходимость в загрузке картинки в ходе выполнения какой-либо программы, а затем в изменении ее; для этой цели следует использовать подпрограмму "LOAD". "LOAD" и "SAVE" приведены на листинге 6.4. LISTING 6.4 4500 REM SAVE

4510 INPUT "NAME OF PICTURE? ";N$: IF N$="" THEN RETURN 4520 SAVE (N$)SCREEN$ 4530 RETURN 4600 REM LOAD

4610 INPUT "NAME OF PICTURE? ";N$: IF N$="" THEN RETURN 4620 LOAD (N$)SCREEN$ 4630 RETURN Упражнение 6.4

Запустите программу на листинге 3.1 (или загрузите с помощью подпрограммы "LOAD", если вы его сохранили), а затем измените цвет INK на зеленый, a PAPER на черный. Для экономии места соедините "SAVE" и "LOAD" в одной подпрограмме.

Надписи

Программы на листингах 6.1-6.4 образуют основу пакета программ для создания графиков, но пока нам не хватает подпрограмм, позволяющих делать надписи. Такая подпрограмма приведена на листинге 6.5. Обратите внимание, что она содержит обращения к еще не написанным программам. Это типичный пример принятого в книге модульного метода создания программ. Это означает, что когда мы сталкиваемся с задачей, которую не можем решить с ходу, то мы присваиваем ей имя с тем, чтобы вернуться к ней позднее. В подпрограмме "LABEL" мы полагаем, что символы из пятого набора будут печататься в последовательности один над другим. По причинам, которые станут, понятны позже, определим специальный префикс (7:), который указывает, что цепочка символов для надписи должна быть напечатана в узких символах, используя подпрограмму "THIN". Мы предполагаем также наличие подпрограммы "SET", которая позволяет переключать наборы Символов.

LISTING 6.5 5400 REM LABEL

5410 GO SUB CURSOR: INPUT "SET:STRING ";A$: IF A$="" THEN GO TO 5410 5420 INPUT "COLOUR ";C$: INK VAL ("0"+C$)

5430 IF A$(TO 2)="1:" THEN PRINT AT ROW,COL;A$(3 TO): GO TO 5510

5439 REM CHECK FOR SPECIAL SET NUMBERS, SET 5 IS PRINTED VERTICALLY.

5440 IF A$(TO 2)<>"5:" THEN GO TO 5470 5450 LET S=5: GO SUB SET: LET A$=A$(3 TO)

5460 FOR I=1 TO LEN A$: PRINT AT ROW-I+1,COL;A$(I): NEXT I: GO TO 5510

5469 REM SET 7 SPECIFIES THAT THE THIN ROUTINE SHOULD BE USED FOR PRINTING.

5470 IF A$(TO 2)<>"7:" THEN GO TO 5490

5480 LET A$=A$(3 TO): GO SUB THIN: GO TO 5510

5489 REM CHECK VALID NUMBER IS GIVEN.

5490 LET S=VAL A$(1): IF S>6 OR S<1 OR A$(2)<>":" THEN GO TO 5510

5499 REM PRINT OUT STRING IN APPROPRIATE SET.

5500 GO SUB SET: PRINT AT ROW,COL;A$(3 TO) 5510 LET S=1: GO SUB SET

5520 INK 0: RETURN

Данные для графиков

Для окончательной отделки нашей программы, мы вводим программу "MAIN PROGRAM" и подпрограмму "QUERY" ("запрос"), текст которых приведен на листинге 6.6, хотя эти программы и ставят перед нами новые нерешенные задачи, но все же они полезны тем, что позволяют нам проследить, какие именно задачи остались нерешенными. Мы вводим идентификаторы (нижний регистр) для имен подпрограмм, которые нам еще предстоит написать, которые, кроме всего прочего, позволят нам создавать специальные виды диаграмм, например, гистограммы, круговые диаграммы и графики. Часть листинга 6.6, до "MAIN PROGRAM", - это подчищенная версия программы CHARACTER GENERATOR, которая необходима для использования альтернативных множеств.

Все диаграммы в этой книге, за исключением тех, которые являются непосредственным результатом работы программ-образцов, были созданы программой, содержащей подпрограммы на листингах 6.1-6.7; кроме того, эта программа использовалась для добавления надписей ко многим из рисунков, созданных программами.

LISTING 6.6

8 REM FOR 16K MAKE CHANGEN AS GIVEN IN LISTING 5.5.

9 REM SET UP TO USE ALTERNATE CHARACTER SETS.

10 CLEAR 62294

20 INK 0: PAPER 7: CLS : DIM S(6)

30 FOR I=1 TO 6: READ S(I): NEXT I: DATA 15360,62039,62807,63575,64343,64848 40 LET SET=50: LET S=1: GO SUB SET: GO TO 200 50 REM SET/CHANGE TO SET S

60 LET HI=INT(S(S)/256): LET LO=S(S)-HI*256 70 POKE 23606,LO: POKE 23607,HI: RETURN 80 REM CHARLOAD

90 INPUT "WHAT FILE NAME? ";N$: IF N$="" THEN RETURN

100 INPUT "LOAD WHICH SET? ";S: IF (S<2 OR S>6) AND S<>11 THEN GO TO 80 110 INPUT "PRESS ENTER ";LINE X$

120 IF S=11 THEN LOAD N$ CODE (S(5)+256),768+168: RETURN 130 IF S=6 THEN LOAD N$ CODE (S(S)+512),168: RETURN

140 LOAD N$ CODE (S(S)+256),768: RETURN

200 REM MAIN PROGRAM

210 LET RESTART=280: LET QUERY=500

220 LET HISTO=1000: LET PIE=2000: LET GRAPH=3000

230 LET PAPER=4000: LET INK=4100: LET POINT=4200: LET LINE=4300: LET SAVE=4500: LET LOAD=4600: LET NUMBER=4700

240 LET CHARLOAD=80: LET CREATE=5000: LET THIN=5200 250 LET LABEL=5400: LET CURSOR=5700

260 LET I$="DEFINE CHARACTERS? ": GO SUB QUERY: IF YES THEN GO SUB CREATE 270 CLS : LET I$="LOAD CHARACTERS? ": GO SUB QUERY: IF YES THEN GO SUB CHARLOAD: GO TO 270

280 LET I$="LOAD PICTURE? ": GO SUB QUERY: IF YES THEN GO SUB LOAD

290 LET I$="DRAW DIAGRAM? ": GO SUB QUERY: IF NOT YES THEN GO TO 360

300 LET I$="HIST.,PIE-CHART OR GRAPH? ": GO SUB QUERY

310 LET DIAGRAM=0: IF A$="H" THEN LET DIAGRAM=HISTO

320 IF A$="P" THEN LET DIAGRAM=PIE

330 IF A$="G" THEN LET DIAGRAM=GRAPH

340 IF DIAGRAM=0 THEN GO TO 280

350 GO SUB DIAGRAM

360 LET I$="LABEL PICTURE ?": GO SUB QUERY: IF YES THEN GO SUB LABEL: GO TO 360 370 LET I$="COLOUR PAPER ? ": GO SUB QUERY: IF YES THEN GO SUB PAPER: GO TO 370 380 LET I$="COLOUR INK ? ": GO SUB QUERY: IF YES THEN GO SUB INK: GO TO 380 390 LET I$="DRAW POINT ? ": GO SUB QUERY: IF YES THEN GO SUB POINT: GO TO 390 400 LET I$="DRAW LINE ? ": GO SUB QUERY: IF YES THEN GO SUB LINE: GO TO 400 410 LET I$="END PICTURE ? ": GO SUB QUERY: IF NOT YES THEN GO TO RESTART 420 LET I$="SAVE PICTURE ? ": GO SUB QUERY: IF YES THEN GO SUB SAVE 430 STOP

500 REM QUERY

501 REM IN - I$

502 REM OUT - A$,YES 510 LET YES=0

520 INPUT (I$);LINE A$: IF A$="" THEN RETURN 530 LET A$=A$(1) 540 LET YES=(A$="Y") 550 RETURN

Специальные символы

Для завершения подготовительной работы для программы "LABEL" нам необходимо создать ряд символов, получаемых поворотом из стандартных; эти символы используются в вертикальных надписях. Такие символы создаются программой "CREATE" (листинг 6.7), которая использует некоторые технические приемы подпрограммы "CHARACTER GENERATOR" для записи повернутых символов набора 1 в набор 5. LISTING 6.7

5000 REM CREATE/CHARACTERS

5009 REM CREATE CHARACTERS FOR HISTOGRAM ROUTINE.

5010 DIM P(8): DIM D(3): LET D(1)=15: LET D(2)=255: LET D(3)=240 5020 FOR I=0 TO 6: FOR J=0 TO 7

5030 LET P(1)=USR "A"+I*8+J: LET P(2)=USR "H"+I*8+J

5040 LET P(3)=USR "O"+I*8+J

5050 FOR K=1 TO 3: POKE P(K),0: NEXT K

5060 IF J<I THEN FOR K=1 TO 3: POKE P(K),D(K): NEXT K

5070 NEXT J: NEXT I

5078 REM COPY SET 1 TO 5 WITH A ROTATION TO THE SIDEWAYS CHARACTERS.

5079 REM FOR 16K MACHINES Q=31831.

5080 DIM B$(8,8): LET T=256: FOR I=1 TO 8: LET T=T/2: LET P(I)=T: NEXT I: LET P=15616: LET Q=64599

5090 FOR I=32 TO 127: FOR J=1 TO 8: LET B$(J)="00000000": NEXT J

5100 FOR J=1 TO 8: LET T=PEEK P: FOR K=1 TO 8

5110 IF T>=P(K) THEN LET T=T-P(K): LET B$(9-K,J)="1"

5120 NEXT K: LET P=P+1: NEXT J

5130 FOR J=1 TO 8: POKE Q,VAL ("BIN"+B$(J)): LET Q=Q+1: NEXT J 5140 PRINT AT 10,10;"ROTATING ";CHR$ I 5150 NEXT I: CLS 5160 RETURN

5200 REM THIN

5201 REM IN - ROW,COL,A$

5209 REM PRINT EVERY OTHER CHARACTER IN LEFT HALF OF BLOCKS.

5210 LET S=4: GO SUB SET: OVER 1: LET TC=COL

5220 FOR I=1 TO LEN A$ STEP 2: PRINT AT ROW,TC;A$(I): LET TC=TC+1: NEXT I

5229 REM PRINT OTHER CHARACTERS IN BETWEEN IN RIGHT HALF OF BLOCKS.

5230 LET S=3: GO SUB SET: LET TC=COL

5240 FOR I=2 TO LEN A$ STEP 2: PRINT AT ROW,TC;A$(I): LET TC=TC+1: NEXT I

5250 LET S=1: GO SUB SET: OVER 0

5260 RETURN

Перед тем как произвести эту операцию, подпрограмма "CREATE" переопределяет набор символов, определяемых пользователем, так что для каждого символа оказывается закрепленной снизу либо левая часть, либо правая, либо по всей ширине блока. Надпечатывая эти символы командой OVER, можно проводить горизонтальные линии различной толщины, но в основном эти символы предназначены для создания гистограмм.

В оставшейся части главы мы будем обсуждать некоторые распространенные способы представления информации. Из-за большого разнообразия вариантов каждого из трех основных видов графического представления информации, кажется неразумным обсуждать их все. Вместо этого мы детально обсудим несколько представителей трех основных видов графического представления информации гистограмм, круговых диаграмм и графиков. Пользуясь этими простейшими примерами, несложно построить варианты подпрограмм, организующие выдачу информации в нужном вам виде. Еще раз напомним вам, что изменения, которые необходимо внести для машин с объемом памяти 16 К, содержатся в приложении А.

Определенные пользователем символы для использования в гистограммах

A-

W-

C-

D-

E-

F-

G-

H-

I-

J-

K-

L-

M-

N-

O-

P-

Q-

R-

S-

T-

U-

Рис. .27

Гистограммы

Создаваемые нашими подпрограммами гистограммы могут быть любой высоты и цвета, если только соблюдается условие, что ширина столбцов гистограммы и промежуток между ними не меньше половины блока. Так как для гистограмм это условие обычно имеет место, то мы можем сформулировать метод нахождения толщины столбцов и промежутка между ними, если только нам известно количество столбцов. Первая часть программы "HISTO" проводит оси, наносит надписи и запрашивает количество столбцов. Ширина столбцов (X) и величина промежутка между ними (GAP) вычисляются (в половинах блоков) так, что гарантируется, что 1/2<=GAP<=X.

По мере получения информации подпрограмма использует символы шириной в полблока и в блок, а также символы, определяемые пользователем (из "CREATE"), для построения цепочек, высота которых пропорциональна высоте гистограммы. Эти цепочки используются для заполнения символьного блока или половины символьного блока, соответствующего этому столбцу; для этого перед каждой цепочкой ставится префикс "5:" и вызывается подпрограмма "BAR".

Обратите внимание, что оси вынесены за поле гистограммы для того, чтобы они не менялись ни при каких изменениях цветов внутри этого поля. На рис. 28 приведена диаграмма, на которой показано годовое количество осадков в ЭГХАМЕ; эта диаграмма была начерчена с помощью подпрограммы "HISTO" (TYPED на листинге 6.8, а затем надписана с помощью "LABEL".

RUERRGE MONTHLY RRINFRLL IN EGHRM 100

JFMRMJJRSOND

Рис. 28.

Упражнение 6.5

В качестве вариантов стандартной подпрограммы "HISTO" можно писать заменяющиеся подпрограммы, которые можно загружать по мере необходимости. Напишите подпрограмму, вычисляющую позиции пар столбцов, где парные блоки отделяются друг от друга просветом в полблока, а расстояние между соседними парами не менее одного блока. Используйте эту подпрограмму для создания диаграмм, аналогичных диаграмме на рис. 28. LISTING 6.8

1000 REM HISTO/TYPE1

1009 REM SET POINTER TO SUBROUTINE WHICH PRINTS BARS.

1010 LET BAR=1320

1019 REM FIND SCALE AND DRAW AXES.

1020 INPUT "RANGE OF VERTICAL ";YB;" TO ";YT 1030 IF YB>=YT THEN GO TO 1020

1040 LET YSCALE=128/(YT-YB)

1050 PLOT 47,152: DRAW 0,-129: DRAW 201,0

1059 REM LABEL VERTICAL AXIS.

1060 LET YDIF=(YT-YB)/4: LET TICK=YB 1070 FOR I=1 TO 5: LET TK=INT(TICK+0.5)

1080 LET Y=32*I-8: PLOT 47,Y: DRAW -3,0: LET ROW=INT ((176-Y)/8)-1 1090 LET A$=STR$ TK: IF LEN A$>3 THEN LET A$=A$(TO 3): IF TK>99 OR TK<-99 THEN LET A$="***"

1100 LET COL=1: IF TK>=0 THEN LET COL=COL+1 1110 IF ABS TK<10 THEN LET COL=COL+1 1120 IF ABS TK<100 THEN LET COL=COL+1 1130 PRINT AT ROW,COL;A$: LET TICK=TICK+YDIF 1140 NEXT I

1149 REM FIND NUMBER OF BARS REQUIRED AND CALCULATE HOW IHEY CAN FIT IN.

1150 INPUT "NO. OF BARS=";NB

1160 LET X=INT(25/NB+0.5)/2: LET GAP=INT(50/NB-2*X)/2 1170 LET GP=(25-NB*X-(NB-1)*GAP)*2: LET GP=INT((GP+1)/2)/2

1179 REM POSITION COLUMN POINTER AT FIRST BAR THEN REPEATE LOOP FOR EACH BAR.

1180 LET COL=6+GP: FOR I=1 TO NB

1190 LET I$="DATA FOR BAR "+STR$ I+"=": INPUT (I$);D;" COLOUR=";C: INK C: LET

W=X

1199 REM VALUES BELOW THE HORIZONTAL AXIS ARE TREATED AS SINGLE PIXEL HEIGHT.

1200 IF D<=YB THEN LET D=0: LET H=1: GO TO 1220

1209 REM CALCULATE THE NUMBER OF WHOLE BLOCKS OF HEIGHT FOR BAR.

1210 LET D=D-YB: LET H=INT(D*YSCALE+0.5)

1220 LET IH=INT(H/8): LET L$="": LET M$="": LET R$=""

1229 REM CONSTRUCT STRINGS TO HEIGHT FOR LEFT.MIDDLE AND RIGHT OF BARS.

1230 FOR J=1 TO IH: LET L$=L$+CHR$ 133: LET M$=M$+CHR$ 143: LET R$=R$+CHR$ 138

1239 REM FIND NUMBER OF PIXELS OF HEIGHT FOR SPECIAL CHARACTER AT TOP.

1240 NEXT J: LET RH=H-IH*8: IF RH=0 THEN GO TO 1260

1249 REM ADD SPECIAL CHARACTERS TO TOPS OF BARS.

1250 LET L$=L$+CHR$(151-RH): LET M$=M$+CHR$(158-RH): LET R$=R$+CHR$(165-RH)

1259 REM IF COLUMN POINTER IS ON A HALF-BLOCK PRINT RIGHT BIASED PART OF BAR.

1260 IF COL=INT (COL) THEN GO TO 1280

1270 LET A$=L$: GO SUB BAR: LET W=W-0.5: LET COL=COL+0.5

1279 REM PRINT AS MANY WHOLE BLOCK BARS AS NEEDED.

1280 IF W>0.1 THEN LET A$=M$: GO SUB BAR: LET W=W-1: LET COL=COL+1: GO TO 1280

1289 REM SEE IF LEFT BIASED HALF-WIDTH BAR IS NEEDED.

1290 IF W>0 THEN LET A$=R$: GO SUB BAR: LET COL=COL+0.5

1299 REM MOVE COLUMN POINTER TO NEXT BAR AND RE-GO LOOP

1300 LET COL=COL+GAP: NEXT I 1310 INK 0: RETURN

1320 REM BAR

1321 REM IN - COL,A$

1329 REM PRINT AS VERTICALLY FROM ROW 19 UPWARDS IN COLUMN.

1330 FOR K=1 TO LEN A$: PRINT AT 19-K,INT COL;A$(K): NEXT K 1340 RETURN

На листинге 6.9 приведен пример подпрограммы, заменяющей подпрограмму "HISTO". Эта подпрограмма "HISTO" (TYPE2) составлена так, что она гарантирует - толщина столбцов и промежуток между ними состоит из целого числа символьных блоков (X и GAP - целые числа). Для каждого столбца требуется задавать два числа, определяющие максимальную и минимальную высоту столбца. Используя команду OVER для печати столбцов, можно создавать диаграммы, подобные той, что на рис. 29, на которой показаны месячные диапазоны температур в ЭГХАМЕ. Операторы PRINT в этой подпрограмме, а также в последующих подпрограммах рассредоточены по тексту таким образом, чтобы читатель мог лучше проследить за логикой алгоритма по мере его выполнения.

TEMPERRTURE

EGHRM

Я М J J

Рис. 29.

LISTING 6.9

1000 REM HISTO/TYPE2

1009 REM SET POINTER TO SUBROUTINE WHICH PRINTS BARS.

LET BAR=1320: DIM O$(2,3): LET O$(1)="MAX": LET O$(2)="MIN"

REM FIND SCALE AND DRAW AXES.

INPUT "RANGE OF VERTICAL ";YB;" TO ";YT

IF YB>=YT THEN GO TO 1020

LET YSCALE=128/(YT-YB)

PLOT 47,152: DRAW 0,-129: DRAW 201,0

REM LABEL VERTICAL AXIS.

LET YDIF=(YT-YB)/4: LET TICK=YB

FOR I=1 TO 5: LET TK=INT (TICK+0.5)

LET Y=32*I-8: PLOT 47,Y: DRAW -3,0: LET ROW=INT ((176-Y)/8)-1 LET A$=STR$ TK: IF LEN A$>3 THEN LET A$=A$(TO 3)

IF TK>99 OR TK<-99 THEN

COL=1: IF TK>=0 THEN LET COL=COL+1 IF ABS TK<10 THEN LET COL=COL+1 IF ABS TK<100 THEN LET COL=COL+1 PRINT AT ROW,COL;A$: LET TICK=TICK+YDIF NEXT I

REM FIND NUMBER OF BARS REQUIRED AND CALCULATE AN INTEGER WIDTH FOR THEN.

INPUT "NO. OF BARS=";NB: OVER 1

LET GAP=INT(13/NB): LET X=INT((26-GAP*NB)/NB)

LET GP=(25-NB*X-(NB-1)*GAP): LET GP=INT ((GP+1)/2)

REM POSITION COLUMN POINTER AT FIRST BAR THEN REPEAT LOOP FOR EACH BAR. LET COL=6+GP: FOR I=1 TO NB: INPUT ("COLOUR FOR BAR "+STR$ I+"=");C: INK C REM LOOP TO INPUT MAXIMUM AND MINIMUM VALUES FOR BAR.

FOR O=1 TO 2: LET I$=O$(O)+" FOR BAR "+ STR$ I+"=": INPUT (I$);D: LET W=X IF D<=YB THEN LET D=0: LET H=1: GO TO 1220

REM CALCULATE THE NUMBER OF WHOLE BLOCKS OF HEIGHT FOR BAR.

LET D=D-YB: LET H=INT(D*YSCALE+0.5)

LET IH=INT(H/8): LET M$=""

REM CONSTRUCT STRING TO HEIGHT FOR BAR.

FOR J=1 TO IH: LET M$=M$+CHR$ 143

REM ADD SPECIAL CHARACTER FOR REMAINING HEIGHT.

NEXT J: LET RH=H-IH*8: IF RH=0 THEN GO TO 1260

LET M$=M$+CHR$ (158-RH)

REM START AT SAME COLUMN FOR BOTH BARS IN PAIR. IF O=1 THEN LET OCOL=COL IF O=2 THEN LET COL=OCOL

REM OUTPUT REQUIRED NUMBER OF WHOLE BLOCK WIDTH BARS.

IF W>=1 THEN LET A$=M$: GO SUB BAR: LET W=W-1: LET COL=COL+1: GO TO 1280 LET COL=COL+GAP: NEXT O: NEXT I INK 0: OVER 0: RETURN REM BAR

REM IN - COL,A$

REM PRINT AS VERTICALLY FROM ROW 19 UPWARDS IN COLUMN. FOR K=1 TO LEN A$: PRINT AT 19-K,INT COL;A$(K): NEXT K RETURN

из больших удобств бейсика является то, что в программу можно вставлять дополнительные

операторы STOP в программы, выяснить значение переменных, а затем продолжить выполнение оператором CONT, без изменения статуса программы. Это очень полезное средство отладки программ, которое также помогает понять принципы построения программы.

Упражнение 6.6

Используйте два различных цвета PAPER во время вывода столбцов гистограммы с помощью оператора OVER, для печати двух цветных столбцов. Будьте внимательны при использовании значений параметров столбца, разнящихся меньше чем на восемь элементов изображения!

При использовании двух цветов для одного столбца (упражнение 6.6) возникнут сложности. Если значения максимума и минимума попадает в один символьный блок, то для этого блока потребуется три цвета (два - цвет столбца, один - фоновый). Проверить, возникнут ли осложнения при раскрашивании столбца, можно, сравнив количество символов в цепочке, соответствующей минимальному значению, с количеством блоков, соответствующих максимальномы значению. Если они одинаковы, то простейший выход - укоротить цепочку, соответствующую мин. значению, на последний блок, что избавит от проблем с раскраской, но сделает диаграмму менее точной.

Эта проблема отпадает, если нижний столбец окрашивать в цвет фона (PAPER), что приведет к тому, что в каждом блоке используются только два цвета.

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

1010

1019

1020 1030 1040 1050

1059

1060 1070 1080 1090

LET A$="***"

1100 LET 1110 1120 1130 1140

1149

1150 1160 1170

1179

1180

1189

1190 1200

1209

1210 1220

1229

1230

1239

1240 1250

1259

1260 1270

1279

1280 1290 1300

1320

1321

1329

1330 1340

Одним

LISTING 6.10

2000 REM PIE/CHART

2009 REM SET POINTERS TO ROUTINES.

2010 LET HATCH=2300: LET IN=2800

2019 REM ALL SEGMENTS ARE INPUT AND TOTALLED TO CALCULATE ANGULAR SCALE.

2020 INPUT "NO.OF SEGMENTS=";NB: INPUT "COLOUR=";C$: LET C=VAL ("0"+C$): LET

TOT=0

2030 DIM D(NB): FOR I=1 TO NB: INPUT ("DATA "+STR$ I+": ");D(I): LET TOT=TOT+D(I): NEXT I

2039 REM USE CURSOR TO SPECIFY CENTRE OF PIE.

2040 INPUT "PRESS ENTER FOR","CENTERING PIE ";LINE Y$ 2050 GO SUB CURSOR: LET XC=PX: LET YC=PY

2060 INPUT "RADIUS (IN PIXELS) "; RAD 2070 LET ASCALE=2*PI/TOT: LET A1=PI/2

2079 REM ANY WEDGE MAY BE PULLED OUT BY MOVING THE CURSOR AWAY FROM THE CENTRE.

2080 FOR I=1 TO NB

2090 INPUT "PRESS ENTER FOR","CENTERING WEDGE";LINE Y$

2100 LET PX=XC: LET PY=YC: GO SUB CURSOR: LET ANG=ASCALE*D(I): LET A2=A1-ANG

2109 REM IF WEDGE IS TO MOVE OUT CALCULATE DISPLACEMENT ALONG IT'S BISECTOR.

2110 IF PX=XC AND PY=YC THEN GO TO 2140

2120 LET A3=A1-ANG/2: LET DIST=SQR ((PX-XC)*(PX-XC)+(PY-YC)*(PY-YC)) 2130 LET PX= INT (XC+DIST*COS A3+0.5): LET PY= INT (YC+DIST*SIN A3+0.5)

2139 REM ENQUIRE WHETHING IS REQUIRED AND WHAT TYPE.

2140 INPUT "HATCH (X,Y,B,N)";H$

2149 REM IF HATCHING IS WANTED INPUT GAP SIZE BETWEEN LINES AND OFFSET.

2150 IF H$<>"N" THEN INPUT "JUMP="; JUMP, "REM="; REM

2159 REM DRAW SEGMENT OF PIE.

2160 INK C: PLOT PX,PY: LET X1= INT (RAD*COS A1-0.5): LET Y1= INT (RAD*SIN A1+0.5): DRAW X1,Y1

2170 LET A2S=A2: LET ASTO=ANG: LET XA=PX+X1: LET YA=PY+Y1 2180 LET XB= INT (RAD*COS A2-0.5): LET YB= INT (RAD*SIN A2-0.5) 2190 FOR T=A1 TO A2 STEP -3/RAD

2200 LET X2=INT (RAD*COS T+0.5): LET Y2= INT (RAD*SIN T+0.5): DRAW X2-X1,Y2-Y1: LET X1=X2: LET Y1=Y2

2210 NEXT T: DRAW XB-X2,YB-Y2: LET X2=XB: LET Y2=YB 2220 DRAW -XB,-YB: IF H$="N" THEN GO TO 2250

2228 REM CALL HATCHING ROUTINE IF NEEDED.

2229 REM IF ANGLE IS GREATER THEN HALF CIRCLE THEN DO HATCHING IN TWO PARTS.

2230 IF ASTO>PI THEN LET A2=A1-PI: LET XB=2*PX-XA: LET YB=2*PY-YA: GO SUB HATCH: LET XA=XB: LET YA=YB: LET A1=A2: LET A2=A2S

2240 LET XB=PX+X2: LET YB=PY+Y2: GO SUB HATCH

2249 REM LOOP BACK FOR NEXT SEGMENT.

2250 LET A1=A2: NEXT I: RETURN

На листинге 6.10, используя подпрограмму "CURSOR", центр диаграммы устанавливается курсором, после чего вводится радиус диаграммы в пикселях. После этого вводятся данные о каждом элементе, затем эти данные суммируются и устанавливается угловой масштаб. Каждый сектор центруется курсором, при этом расстояние от центра диаграммы до перекрестья курсора задает величину сдвига вершины сектора по лучу, являющемуся биссектрисой угла, ограничивающего сектор. Для каждого нового сектора курсор устанавливается в центр диаграммы.

Штриховка секторов

Для штриховки секторов нам придется сначала определить точки пересечения прямых, штрихующих сектор с его границами, поэтому для упрощения вычислений мы ограничимся простейшим случаем штриховки сектора

Круговые диаграммы

Круговые диаграммы особенно полезны в биологии и экономике. Обычно к программам построения круговых диаграмм предъявляются следующие требования: они должны генерировать диаграммы различных размеров; должна быть предусмотрена возможность извлекать сектора из диаграммы и наносить на сектора штриховки и надписи различных типов. Первые два требования удовлетворены в программе (см. листинг 6.10 и рис. 30).

Рис. 30.

вертикальными прямыми, горизонтальными прямыми и горизонтальными и вертикальными прямыми одновременно. Мы будем штриховать только сектора с величиной центрального угла меньшим 180 градусов. Сектора с центральным углом больше 180 градусов раскрашиваются как два сектора, первый из которых имеет центральный угол 180 градусов. Подпрограмма "PIE" запрашивает, будет ли штриховка горизонтальной (ответ "X"), вертикальной (ответ "Y"), оба вида штриховки (ответ "В"), или никакой штриховки (ответ "N").

Сектора диаграммы образованы двумя отрезками и дугой окружности. Мы должны определить, какая часть прямой, штрихующей сектор, находится в секторе (если такая часть существует). Так как центральный угол сектора не более 180 градусов, то имеются только четыре возможности:

1. Линия не попадает в сектор;

2. Пересекает дугу в двух точках;

3. Пересекает дугу и отрезок;

4. Пересекает оба отрезка.

Специальный случай пересечения прямой дуги и отрезка в одной точке может рассматриваться, как один из перечисленных выше случаев. Алгоритм штриховки объясняется на примере горизонтальной штриховки; вертикальная штриховка производится аналогичным образом. Сначала мы определяем максимальное и минимальное значение Y для прямых, пересекающих сектор. Затем мы рассматриваем все горизонтальные прямые, штрихующие сектор, задаваемые уравнениями вида Y=K*JUMP+REM и лежащие в этих пределах (0<=REM<=JUMP-1). Для каждой линии штриховки мы вычисляем две точки пересечения с продолженными отрезками, а затем проверяем, лежат ли у них значения MU между 0 и 1; что означает проверку, лежит ли точка пересечения между центром и дугой. После этого мы находим две точки пересечения штрихующей прямой полной окружности, содержащей дугу, ограничивающую сектор. Из этих точек можно выбрать те, которые соответствуют пересечению с сектором, после чего они соединяются штриховой линией (листинг 6.11).

LISTING 6.11

2300 REM HATCH

2309 REM IF CROSS HATCHING IS REQUIRED THEN RUN HATCH ROUTINE TWICE.

2310 IF H$="B" THEN LET H$="X": GO SUB 2320: LET H$="Y": GO SUB 2320: LET H$="B": RETURN

2319 REM SET HATCHING VARIABLES TO CONTROL DIRECTION OF LINES.

THEN LET PZ=PX: LET PT=PY: LET ZA=XA: LET TA=YA: LET ZB=XB:

LET

TB=YB

THEN LET PZ=PY: LET PT=PX: LET ZA=YA: LET TA=XA: LET ZB=YB: LET

TB=XB

DIM Z(3)

REM FIND MAX AND MIN COORDINATES FOR LINES WHICH PASS THROUGH SEGMENT.

LET T=PI/2: LET MAX=0: LET MIN=0

LET VAL=SIN A1: IF H$="X" THEN LET VAL=COS A1

IF MAX<VAL THEN LET MAX=VAL

IF MIN>VAL THEN LET MIN=VAL

IF T>A1 THEN LET T=T-PI/2: GO TO 2390

IF T<A2 THEN GO TO 2450

LET VAL=SIN T: IF H$="X" THEN LET VAL=COS T IF MAX<VAL THEN LET MAX=VAL IF MIN>VAL THEN LET MIN=VAL LET T=T-PI/2: GO TO 2400

LET VAL=SIN A2: IF H$="X" THEN LET VAL=COS A2 IF MAX<VAL THEN LET MAX=VAL IF MIN>VAL THEN LET MIN=VAL

LET NEWMIN= INT (INT (RAD*MIN+1)/JUMP)*JUMP+REM

REM FOR LINES WHICH CROSSES SEGMENT FIND INTERSECTIONS WITH SACIF AND ARC. FOR E=NEWMIN TO MAX*RAD STEP JUMP

REM STORE INTERSECTION COORDINATE INFORMATION IN ARRAW Z(l:4). LET IC=0

LET DEMON=TA-PT: IF DEMON=0 THEN GO TO 2540 LET MU=E/DEMON: IF MU<0 OR MU>1 THEN GO TO 2540 LET IC=IC+1: LET Z(IC)=PZ+MU*(ZA-PZ) LET DEMON=TB-PT: IF DEMON=0 THEN GO TO 2580 LET MU=E/DEMON: IF MU<0 OR MU>1 THEN GO TO 2580 LET IC=IC+1: LET Z(IC)=PZ+MU*(ZB-PZ)

REM IF MORE THEN TWO POINTS OF INTERSECTION FOUNDE, DELETE DUPLICATES. IF IC=2 AND Z(1)=Z(2) THEN LET IC=1 IF IC<>2 THEN GO TO 2610 REM DRAW HATCH LINES.

IF H$="Y" THEN PLOT Z(1),E+PT: DRAW Z(2)-Z(I),0: GO TO 2710 IF H$="X" THEN PLOT E+PT,Z(1): DRAW 0,Z(2)-Z(1): GO TO 2710 LET DISC=RAD*RAD-E*E: IF DISC<0 THEN GO TO 2710 LET DISC=INT (SQR DISC+0.5)

IF H$="Y" IF H$="X"

2320 2330

2340

2349

2350 2360 2370 2380 2390 2400 2410 2420 2430 2440 2450 2460 2470 2480

2489

2490

2499

2500 2510 2520 2530 2540 2550 2560

2569

2570 2580

2589

2590 2600 2610 2620

2630 LET ZZ=PZ+DISC: LET AZ=DISC: GO SUB IN: IF OUT THEN GO TO 2650 2640 LET IC=IC+1: LET Z(IC)=ZZ

2650 LET ZZ=PZ-DISC: LET AZ=DISC: GO SUB IN: IF OUT THEN GO TO 2670

2660 LET IC=IC+1: LET Z(IC)=ZZ

2670 IF IC<2 THEN GO TO 2710

2680 IF IC=2 THEN GO TO 2590

2690 IF Z(1)=Z(2) THEN LET Z(2)=Z(3)

2700 GO TO 2590

2710 NEXT E

2720 RETURN

2800 REM IN

2808 REM CALCULATE ANGLE TO POINT OF INTERSECTION.

2809 REM IF ANGLE LINES BETWEEN ANGLES OF SEGMENT THEN POINT OF INTERSECTION IS ON THE ARE OF THE SEGMENT.

2810 LET BZ=AZ: LET EZ=E

2820 IF H$="X" THEN LET B2=E: LET EZ=AZ

2830 IF BZ=0 THEN LET PHI=-PI/2: IF EZ>0 THEN LET PHI=-PHI 2840 IF B2=0 THEN GO TO 2860

2850 LET PHI=ATN (EZ/BZ): IF BZ<0 THEN LET PHI=PHI-PI

2859 REM SET FLAG TO INDICATE WHETHER OR NOT POINT IS VALID.

2860 LET OUT=(PHI>=A1) OR (PHI<=A2) 2870 RETURN

Графики

Для построения графиков необходимы подвижные координатные оси, обладающие широким диапазоном масштабов. Мы используем довольно распространенный метод расположения осей: если область графика проходит через ноль, то и ось проходит через ноль, а если нет - то ось располагается по ту сторону экрана, которая ближе к нулю. После этого на ось наносится пять штрихов, около каждого из которых наносится соответствующее этому штриху значение на оси. Требование точности научных графиков заставляет нас искать способы размещения возможно большего количества надписей в графическом поле. Так как обычных символов на экране помещается 32 в длину и 22 в высоту, то нам приходится пользоваться узкими символами, создаваемыми подпрограммой "THIN". Мы использовали CHARACTER GENERATOR для генерации двух видов узких символов: первый тип расположен в левой половине символьного блока, а второй - в правой. Когда цепочка печатается узкими символами, то подпрограмма "THIN" сначала печатает каждый второй символ цепочки в левой части блока, а затем командой OVER помещает оставшиеся символы в правые половины блока, так что в каждом блоке оказывается по два узких символа, а всего таких символов в строке экрана - 64. Подпрограмма "LABEL" требует преобразования узких чисел, печатаемых "THIN", и приведения их к одной длине (или числу десятичных знаков после запятой). Это достигается использованием подпрограммы "NUMBER", приведенной на листинге 6.12. LISTING 6.12 3000 REM GRAPH

3009 REM SYMBOL ROUTINE IS USED TO MARK DATA POINTS ON DISCRETE GRAPHS.

3010 LET SYMBOL=3500: LET NUMBER=4700: LET THIN=5200

3019 REM CALCULATE SCALES AND DRAW AXES.

3020 INPUT "X GOES FROM ";XB;" TO ";XT: IF XT<=XB THEN GO TO 3020 3030 INPUT "Y GOES FROM ";YB;" TO ";YT: IF YT<=YB THEN GO TO 3030 3040 LET XSCALE=192/(XT-XB): LET YSCALE=128/(YT-YB)

3050 LET XO= INT (-XB*XSCALE+32.5): LET YO= INT (-YB*YSCALE+24.5)

3059 REM IF ZERO IS POT IN RANGE OF GRAPH MOVE AXIS TO APPROPRIATE EDGE.

3060 IF YT<0 THEN LET YO=153 3070 IF YB>0 THEN LET YO=23 3080 IF XT<O THEN LET XO=224 3090 IF XB>O THEN LET XO=31

3100 PLOT XO,23: DRAW 0,128: PLOT 31,YO: DRAW 192,0

3109 REM USE THIN ROUTINE TO PRINT LABEL ON AXES WITH FOUR FIGURE ACCURACY.

3110 LET XDIF=(XT-XB)/4: LET YDIF=(YT-YB)/4 3120 LET X=XB: LET Y=YB: FOR J=1 TO 5

3130 LET PX= INT ((X-XB)*XSCALE+32.5): LET PY=YO 3140 PLOT PX,PY-2:DRAW 0,4

3150 LET COL=INT (PX/8)-1: LET ROW=INT ((175-PY)/8)+1 3160 LET A=X: GO SUB NUMBER: GO SUB THIN 3170 LET PY= INT ((Y-YB)*YSCALE+24.5): LET PX=XO 3180 PLOT PX-2,PY: DRAW 4,0

3190 LET COL=INT (PX/8)+1: LET ROW=INT ((175-PY)/8) 3200 LET A-Y: GO SUB NUMBER: GO SUB THIN 3210 LET X=X+XDIF: LET Y=Y+YDIF: NEXT J

3220 INPUT "CONTINIUS OR ","DISCRETE GRAPH? ",D$: IF D$<>"C" OR D$<>"D" THEN GO TO 3220

3230 IF D$="D" THEN GO TO 3320

3239 REM INPUT THE FUNCTION TO BE PLOTTED.

3240 INPUT "F(X):Y=";LINE F$

3250 LET X=XB: LET Y=VAL(F$): LET OY= INT ((Y-YB)*YSCALE+24.5)

3260 PLOT 32,OY

3270 FOR I=33 TO 224

3280 LET X=(I-32)*YSCALE+XB

3290 LET Y=VAL (F$): LET IY=INT ((Y-YB)*YSCALE+24.5)

3300 DRAW 1,IY-OY: LET OY=IY: NEXT I

3310 RETURN

3319 REM DISCRETE GRAPH REQUIRED SO INPUT SET OF POINTS.

3320 INPUT "NO. OF POINTS=";NP: DIM X(NP):DIM Y(NP)

3330 FOR I=1 TO NP: INPUT ("X("+STR$ I+") ");X(I);("Y("+STR$ I+") ");Y(I): NEXT

I

3339 REM SORT POINTS INTO ASCENDING ORDER OF X COORDINATE.

3340 FOR I=1 TO NP-1: FOR J=I+1 TO NP

3350 IF X(J)<X(I) THEN LET T=X(I): LET X(I)=X(J): LET X(J)=T: LET T=Y(I): LET Y(I)=Y(J): LET Y(J)=T

3360 NEXT J: NEXT I

3370 LET X= INT ((X(1)-XB)*XSCALE+32.5): LET Y=INT ((Y(1)-YB)*YSCALE+24.5) 3380 PLOT X,Y: LET OX=X: LET OY=Y: GO SUB SYMBOL: PLOT OX,OY

3389 REM JOIN UP POINTS AND PLACE A "SYMBOL" AT EACH POINT.

3390 FOR I=2 TO NP

3400 LET X=INT ((X(I)-XB)*XSCALE+32.5): LET Y=INT ((Y(I)-YB)*YSCALE+24.5) 3410 PLOT X-OX,Y-OY: LET OX=X: LET OY=Y: GO SUB SYMBOL: PLOT OX,OY 3420 NEXT I: RETURN 3500 REM SYMBOL

3510 DRAW 0,1: DRAW 1,0: DRAW 0,-2: DRAW -2,0: DRAW 0,2 3520 RETURN 4700 REM NUMBER

4710 LET A$=STR$ A: IF LEN A$<=4 THEN RETURN 4720 LET A$=A$(TO 4) 4730 RETURN Упражнение 6.7

Напишите усовершенствованный вариант программы "NUMBER", которой можно было бы определять формат возвращаемой цепочки. Один из способов задать формат числа - это задать его в виде шаблона, например, шаблон "#.##" определяет число с двумя десятичными знаками до запятой и тремя десятичными знаками после. Упражнение 6.8

Составьте набор узких чисел, который необходим для составления надписей. Используйте его для надписывания диаграмм. При составлении набора вы можете руководствоваться рисунком 31:

л

1

y=Cos{x)

-я X

я X

-1

ч / X

Рис. 31.

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

Упражнение 6.9

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

Вместо вычисления цепочки значений FS, мы могли бы написать подпрограмму, которая используется каждый раз, когда возникнет необходимость вычисления точки кривой. Напишите подпрограмму, позволяющую нарисовать график функции SIN(X)/X, чтобы избежать вычисления SIN(O)/O.

Список программ

Мы группируем листинг 6.6 ("MAIN PROGRAM", "CHARLOAD", "SET" и "QUERY"), 6.1 ("CURSOR" и "GRID"), 6.4 ("SAVE" и "LOAD") под именем "LIBDIAG" и используем их совместно с 6.2 ("PAPER" и "INK"), 6.3 ("POINT" и "LINE"), 6.5 ("LABEL"), 6.7 ("CREATE" и "THIN"). Обратите внимание на изменения, которые необходимо внести в программы, если вы используете 16-ти килобайтный вариант SPECTRUMa (см. приложение А).

1. "LIBDIAG", 6.2, 6.3, 6.5, 6.7.

Необходимая информация:

"DEFINE CHARACTER? ("Определить символы?"). Напечатайте Y (да) для генерации поворота символов и генерации блоков для гистограмм; в остальных случаях - М (нет).

"LOAD CHARACTER? ("Загружать символы?") - Y, если специальные наборы символов (включая вышеприведенные) вводятся с ленты; в противном случае - N.

"LOAD PICTURE? ("Загрузить картинку?"): Y - загрузить картинку, созданную ранее, N - нет.

"DRAW DIAGRAM?" ("Подписывать рисунок?"): - Y, если используется подпрограмма "LABEL", N - если нет.

"COLOUR PAPER?" ("Окрашивать фон?"). Если Y (да), то задайте "WHICH COLOUR?" ("Какой цвет"), например - I; установите курсор в необходимое положение, используя при необходимости подпрограмму "GRID" (сетка), и напечатайте размер участка в блоках, длина по горизонтали, длина по вертикали (например, 2*4).

"COLOUR INK?" ("Цвет туши?"). Если Y (да), то определите " WHICH COLOUR?" ("Какого цвета?"), например, 5; установите курсор в необходимое положение, используя по необходимости программу "GRID", и впечатайте размер области в блоках (например, 3*1).

"DRAW POINT?" ("Нанести точку?"). Если Y (да), то используйте курсор для указания точки; "WHICH COLOUR?" ("Какого цвета?")', например, 6 и параметр команд OVER (1 или 0).

"DRAW LINET ("Начертить прямую?"). Если да, то курсором укажите концы отрезка;" WHICH COLOUR?" ("Какого цвета?"), (например, 5) и параметр для OVER (1 или 0).

"END PICTURE?" ("Конец рисунка?"). Если Y, то повторите последовательность сначала;

"SAVE PICTURE?" ("Сохранить рисунок?"). Если Y, то введите имя рисунка.

Поэкспериментируйте с построением графиков.

2. "LIBDIAG" и листинг 6.8 ("HISTO/TYPEl). Пример данных:

"RANGE OF VERTICAL" .....0 "ТО"...............100

"NO.OFBARS" ............6

"DATA FOR BAR1"........ 5 6 "COLOUR"............2

"DATA FOR BAR2"........ 95 "COLOUR"............6

"DATA FOR BAR3"........ 20 "COLOUR"............4

"DATA FOR BAR4"........ 77 "COLOUR"............5

"DATA FOR BAR5"........ 54 "COLOUR"............1

"DATA FOR BAR6"........ 33 "COLOUR"............3

3. "LIBDIAG" и листинг 6.9 ("HISTO/TYPE2). Пример данных:

"RANGE OF VERTICAL".....0 "TO"................50

"NO.OFBARS".............4

"COLOUR FOR BAR 1"......2

"DATA MAX FOR BAR 1"...44 "DATA MIN FOR BAR 1"...22

"COLOUR FOR BAR2".......6

"DATA MAX BAR2"........3 6

"DATAMINBAR2"...........5

"COLOURFORBAR3".........4

"DATA MAX BAR3"........42

"DATA MIN BARS"........2 9

"COLOUR FOR BAR4".......1

"DATA MAX BAR4"........31

"DATA MIN BAR4"........12

4. "LIBDIAG" и листинг 6.10 и 6.11 ("PIE", "HATCH" и т.д.). Пример данных: "NO. OF SEGMENT"........3

"COLOUR"................ 0

"DATA 1"................1

"DATA 2"................2

"DATA 3"................3

Укажите курсором центр диаграммы, затем: "RADIUS (IN PIXELS)"...75

Используйте курсор для указания положения вершины сектора

"HATCH (X, Y, В, N)".... В "JUMP"...............8

"REM"...................5

Укажите курсором вершину сектора

"HATCH (X, Y, В, N)"....Y "JUMP"..............I:

"REM"...................0

Укажите курсором вершину сектора "HATCH" (X, Y, В, N)....Р

5. "LIBDIAG" и листинг 6.12 ("GRAPH" и т.д.)

Вопросы программы содержат всю информацию, необходимую для ответа на них.




СОДЕРЖАНИЕ:
  1. Трёхмерная декартова геометрия - Определение прямой; Угол между двумя направляющими векторами; Определение плоскости70 Точка пересечения прямой и плоскости; Расстояние от точки до прямой; Точка пересечения двух прямых; Плоскость, проходящая через три неколлинеарные точки; Точка пересечения трёх плоскостей; Линия пересечения двух плоскостей; Функциональное представление поверхности; Лежит ли точка по ту же сторону от плоскости, что и начало координат?; Каково направление обхода двумерного многоугольника, заданного последовательностью своих вершин?


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Письма - Письмо от Zoolook'a из Эстонии о подготовке к приближающемуся Инлайту. Анкета для групп , собирающихся на Enlight.
От автора - о правильном произношении названия газеты.
Fun Top'98 - Заметки участника.
Путеводитель - игра Where Time Stood Still (Там, где время замерло).
Программирование - курс изучения ассемблера от Wlodek Black, продолжение.

В этот день...   24 апреля