Краткий урок геометрии

kratkij urok geometrii Примеры законченных программ с графическим интерфейсом

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

Теперь признание: начав писать PyClock, я не знал ответа на первый вопрос предыдущего абзаца. Я совершенно забыл формулу нахождения координат точек окружности (как и большинство профессиональных программистов, к которым я с этим обращался). Бывает. Такие знания, не будучи востребованными в течение нескольких десятилетий, могут быть утилизированы сборщиком мусора. В конце концов мне удалось смахнуть пыль с нескольких нейронов, длины которых оказалось достаточно, чтобы запрограммировать действия, необходимые для построения, но блеснуть умом мне не удалось.1

Если вы в таком же положении, то я покажу вам один способ простой записи формул построения точек на языке Python, хотя для подробных занятий геометрией места здесь нет. Прежде чем взяться за более сложную задачу реализации часов, я написал сценарий plotterGui, представленный в примере 11.11, чтобы сосредоточиться только на логике построения круга.

Логика построения круга реализуется в функции point — она находит координаты (X,Y) точки окружности по относительному номеру точки, общему количеству точек, помещаемых на окружности, и радиусу окружности (расстоянию между центром окружности и ее точками). Сначала вычисляется угол между нужной точкой и верхней точкой окружности путем деления 360 на количество рисуемых точек и умножения на номер точки. Напомню, что полный круг составляет 360 градусов (например, если на окружности рисуется 4 точки, то каждая отстоит от предыдущей на 90 градусов, или на 360/4). Стандартный модуль Python math предоставляет все необходимые константы и функции — pi, sine и cosine. В действительности математика тут не такая уж непонятная, если вы потратите некоторое время, чтобы ее рассмотреть (возможно, еще взяв старый учебник геометрии). Существуют альтернативные способы реализации нужных математических расчетов, но я не буду углубляться здесь в детали (ищите подсказки в пакете с примерами).

Даже если вы не хотите разбираться с математикой, просмотрите функцию circle в примере 11.11. По указанным координатам (X,Y) точ-

Чтобы не выставлять программистов в невыгодном свете, следует отметить, что ко мне неоднократно обращались с просьбами прочитать лекции о программировании на языке Python для физиков, которые имели более богатую математическую практику, чем я, но многие из которых благополучно злоупотребляли общими блоками и операторами GO TO языка FORTRAN. Специализация в профессиональной деятельности может всех нас в чем-то превратить в новичков.

ки окружности, возвращаемым функцией point, она чертит линию из центра окружности в точку и маленький прямоугольник вокруг самой точки, что несколько напоминает стрелки и отметки аналоговых часов. Чтобы удалять нарисованные объекты перед каждым построением, используются теги холста.

Пример 11.11. PP4E\Gui\Clock\plotterGui.py

# рисует окружности на холсте

import math, sys

from tkinter import *

def point(tick, range, radius):

angle = tick * (360.0 / range)

radiansPerDegree = math.pi / 180

pointX = int( round( radius * math.sin(angle * radiansPerDegree) )) pointY = int( round( radius * math.cos(angle * radiansPerDegree) )) return (pointX, pointY)

def circle(points, radius, centerX, centerY, slow=0):

canvas.delete(‘lines’)

canvas.delete(‘points’)

for i in range(points):

x, y = point(i+1, points, radius-4)

scaledX, scaledY = (x + centerX), (centerY y) canvas.create_line(centerX, centerY, scaledX, scaledY, tag=’lines’) canvas.create_rectangle(scaledX-2, scaledY-2, scaledX+2, scaledY+2, fill=’red’, tag=’points’)

if slow: canvas.update()

def plotter(): # в 3.x // — деление с усечением

circle(scaleVar.get(), (Width // 2), originX, originY, checkVar.get())

def makewidgets():

global canvas, scaleVar, checkVar

canvas = Canvas(width=Width, height=Width)

canvas.pack(side=TOP)

scaleVar = IntVar()

checkVar = IntVar()

scale = Scale(label=’Points on circle’, variable=scaleVar, from_=1,

to=360)

scale.pack(side=LEFT)

Checkbutton(text=’Slow mode’, variable=checkVar).pack(side=LEFT) Button(text=’Plot’, command=plotter).pack(side=LEFT, padx=50)

if __name__ == ‘__main__’:

Width = 500 # ширина, высота по умолчанию

if len(sys.argv) == 2: Width = int(sys.argv[1]) # ширина в команд. строке?

originX = originY = Width // 2 # то же, что и радиус

makewidgets() # в корневом окне Tk по умолчанию

mainloop() # в 3.x требуется // — деление с усечением

По умолчанию ширина круга составит 500 пикселей, если не определить иначе в командной строке. Получив число точек на окружности, этот сценарий размечает окружность по часовой стрелке при каждом нажатии кнопки Plot, вычерчивая прямые из центра к маленьким прямоугольникам на окружности. Переместите ползунок, чтобы задать другое число точек, и щелкните на флажке, чтобы рисование происходило достаточно медленно и можно было заметить очередность вычерчивания линий и точек (при этом сценарий вызывает update для обновления экрана после вычерчивания каждой линии). На рис. 11.19 приводится результат нанесения 120 точек при установке в командной строке ширины круга равной 400; если задать на окружности 60 или 12 точек, сходство с часовым циферблатом станет более заметным.

Рис. 11.19. Сценарий plotterGui в действии

Дополнительную помощь могут оказать ориентированные на текстовый, а не на графический вывод версии этого сценария, имеющиеся в дереве примеров, которые выводят координаты точек окружности в поток stdout, а не отображают эти точки в графическом интерфейсе. Смотрите сценарии plotterText.py в каталоге часов. Ниже показано, что он выводит для случаев 4 и 12 точек на окружности шириной 400 точек. Формат вывода прост:

номер_точки: угол = (координатах, KoopguHamaY)

Предполагается, что центр круга имеет координаты (0,0):

1 : 90.0 = (200, 0)

2 : 180.0 = (0, -200)

3 : 270.0 = (-200, 0)

4 : 360.0 = (0, 200)

1  : 30.0 = (100, 173)

2  : 60.0 = (173, 100)

3  : 90.0 = (200, 0)

4  : 120.0 = (173, -100)

5  : 150.0 = (100, -173)

6  : 180.0 = (0, -200)

7  : 210.0 = (-100, -173)

8  : 240.0 = (-173, -100)

9  : 270.0 = (-200, 0)

10  : 300.0 = (-173, 100)

11  : 330.0 = (-100, 173)

12  : 360.0 = (0, 200)

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий