Перейти к основному содержимому

Работа с геометрией

Всем
Загрузка редактора схем…

Работа с геометрией

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

Координаты и системы координат

Координата — это числовое значение, определяющее положение точки в заданном пространстве относительно выбранной системы отсчёта. Координата отвечает на вопрос «где находится объект» и выражается одним или несколькими числами в зависимости от размерности пространства.

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

Декартова система координат

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

ОсьНаправление в классической математикеНазвание координаты
XВправоАбсцисса
YВверхОрдината
ZНа наблюдателяАппликата

Декартова система удобна тем, что любые операции над точками сводятся к простым арифметическим действиям. Сложение, вычитание и умножение координат дают новые положения, расстояния и направления.

Полярная система координат

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

Параметры полярной системы:

  • радиус — расстояние от начала координат до точки;
  • угол — поворот относительно нулевого направления, обычно против часовой стрелки.

Цилиндрическая и сферическая системы

Цилиндрическая система расширяет полярную на трёхмерное пространство добавлением оси высоты. Она удобна для описания объектов с осевой симметрией — труб, колонн, вращающихся тел.

Сферическая система использует радиус и два угла для описания положения точки в трёхмерном пространстве. Она удобна для задач астрономии, навигации и работы с панорамными изображениями.

Экранная система координат

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

ХарактеристикаМатематическая системаЭкранная система
Направление оси XВправоВправо
Направление оси YВверхВниз
Начало координатОбычно в центреВ левом верхнем углу
Единица измеренияУсловнаяПиксель

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


Двумерное и трёхмерное пространство

Двумерное пространство

Двумерное пространство описывается двумя осями — X и Y. Оно образует плоскость, на которой можно размещать точки, линии, многоугольники и любые фигуры. Все интерфейсы, спрайты, элементы веб-страниц и 2D-игры существуют именно в таком пространстве.

Свойства двумерного пространства:

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

Трёхмерное пространство

Трёхмерное пространство добавляет ось Z, что позволяет описывать объекты с глубиной. В играх, симуляциях, системах автоматизированного проектирования и виртуальной реальности используются именно трёхмерные координаты.

Особенности трёхмерного пространства:

  • точка описывается тройкой чисел;
  • появляется понятие объёма;
  • добавляются новые оси вращения;
  • возникают задачи видимости и скрытия поверхностей;
  • требуется камера для проекции 3D-сцены на 2D-экран.

Правая и левая ориентация

Трёхмерные системы координат бывают право-ориентированными и лево-ориентированными. Различие заключается в направлении оси Z относительно осей X и Y. OpenGL использует правую систему, DirectX и Unity — левую. Это важно учитывать при переносе алгоритмов и моделей между движками.


Размеры экрана и плоскость

Пиксель и разрешение

Пиксель — это минимальная единица отображения на экране, имеющая собственный цвет и положение. Совокупность пикселей образует изображение.

Разрешение экрана — это количество пикселей по горизонтали и вертикали. Типичные значения включают 1920×1080, 2560×1440, 3840×2160. Чем выше разрешение, тем более детализированное изображение способен отобразить экран.

Viewport и рабочая область

Viewport — это видимая часть виртуального пространства, отображаемая в данный момент на экране. В браузере viewport соответствует размеру окна просмотра, в игре — области, захватываемой камерой, в графическом редакторе — видимой части холста.

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

Логические и физические координаты

Современные экраны имеют разную плотность пикселей. На дисплеях с высокой плотностью один логический пиксель может занимать несколько физических. Это соотношение называется devicePixelRatio в JavaScript и учитывается при точной отрисовке.

Тип координатОписаниеИспользование
ФизическиеРеальные пиксели матрицыНизкоуровневая отрисовка
ЛогическиеМасштабированные единицыИнтерфейс, CSS, вёрстка
МировыеКоординаты в виртуальном пространствеИгры, редакторы, карты
ЛокальныеКоординаты относительно объектаАнимация, вложенные элементы

Позиционирование

Позиционирование — это процесс задания положения объекта в пространстве относительно выбранной системы отсчёта. Положение может задаваться абсолютно, относительно родителя, относительно окна или относительно другого объекта.

Абсолютное позиционирование

Абсолютное позиционирование привязывает объект к фиксированным координатам в общей системе. Такой объект сохраняет своё положение независимо от перемещений других элементов.

Относительное позиционирование

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

Якоря и опорные точки

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

Опорные точки для разных операций:

  • перемещение — любая точка, обычно центр;
  • вращение — центр масс или заданный pivot;
  • масштабирование — центр или угол;
  • выравнивание — граница или центр.

Пример позиционирования на Python с использованием turtle


import turtle

screen = turtle.Screen()
screen.setup(width=800, height=600)
screen.title("Позиционирование")

pen = turtle.Turtle()
pen.shape("turtle")
pen.speed(3)

pen.penup()
pen.goto(0, 0)
pen.stamp()

pen.goto(200, 150)
pen.stamp()

pen.goto(-200, -100)
pen.stamp()

screen.mainloop()

Разбор примера:

  • turtle.Screen() создаёт окно отрисовки с собственной системой координат;
  • screen.setup(width=800, height=600) задаёт размеры окна в пикселях;
  • pen.penup() поднимает перо, чтобы черепаха перемещалась без рисования линии;
  • pen.goto(x, y) устанавливает абсолютные координаты черепахи;
  • pen.stamp() оставляет отпечаток формы в текущей позиции;
  • начало координат в turtle располагается в центре окна, ось Y направлена вверх.

Прокрутка

Прокрутка — это механизм перемещения видимой области относительно более крупного содержимого. Когда контент превышает размеры viewport, пользователь сдвигает область просмотра, чтобы увидеть скрытые части.

Принципы работы прокрутки

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

Параметры прокрутки:

  • текущее смещение по X;
  • текущее смещение по Y;
  • общие размеры содержимого;
  • размеры viewport;
  • максимальные значения смещения.

Виртуальная прокрутка

При работе с огромными списками или таблицами применяется виртуализация. В памяти хранятся только те элементы, которые находятся в пределах viewport и небольшого буфера. При прокрутке невидимые элементы удаляются, а новые создаются на лету.

Пример обработки прокрутки на JavaScript

const container = document.querySelector('.scroll-container');

container.addEventListener('scroll', function(event) {
const scrollLeft = event.target.scrollLeft;
const scrollTop = event.target.scrollTop;
const scrollWidth = event.target.scrollWidth;
const scrollHeight = event.target.scrollHeight;
const clientWidth = event.target.clientWidth;
const clientHeight = event.target.clientHeight;

console.log('Горизонтальное смещение:', scrollLeft);
console.log('Вертикальное смещение:', scrollTop);
console.log('Общая ширина контента:', scrollWidth);
console.log('Общая высота контента:', scrollHeight);
console.log('Видимая ширина:', clientWidth);
console.log('Видимая высота:', clientHeight);
});

Разбор примера:

  • container.addEventListener('scroll', ...) подписывается на событие прокрутки контейнера;
  • scrollLeft и scrollTop содержат текущее смещение видимой области;
  • scrollWidth и scrollHeight отражают полные размеры прокручиваемого содержимого;
  • clientWidth и clientHeight показывают размеры самой видимой области;
  • разность между scrollWidth и clientWidth даёт максимальное горизонтальное смещение.

Масштаб и масштабирование

Масштаб — это коэффициент, определяющий соотношение между размерами объекта в виртуальном пространстве и на экране. Масштабирование изменяет этот коэффициент, увеличивая или уменьшая видимые размеры.

Коэффициент масштаба

Коэффициент масштаба выражается числом. Значение единица соответствует обычному размеру, значения больше единицы увеличивают объект, значения меньше единицы уменьшают его.

КоэффициентЭффект
0.5Уменьшение в два раза
1.0Исходный размер
2.0Увеличение в два раза
10.0Десятикратное увеличение

Равномерное и неравномерное масштабирование

Равномерное масштабирование изменяет размеры объекта пропорционально по всем осям. Пропорции фигуры сохраняются, круг остаётся кругом, квадрат — квадратом.

Неравномерное масштабирование применяет разные коэффициенты к разным осям. Это приводит к искажению формы: круг превращается в эллипс, квадрат — в прямоугольник.

Точка масштабирования

Масштабирование всегда выполняется относительно некоторой точки. При увеличении карты в браузере такой точкой выступает положение курсора. При увеличении фотографии — центр viewport. Выбор точки определяет, какая часть объекта останется неподвижной во время трансформации.

Пример масштабирования на Canvas в JavaScript

const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

canvas.width = 800;
canvas.height = 600;

let scale = 1.0;
let offsetX = 0;
let offsetY = 0;

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(offsetX, offsetY);
ctx.scale(scale, scale);

ctx.fillStyle = '#3498db';
ctx.fillRect(100, 100, 200, 150);

ctx.fillStyle = '#e74c3c';
ctx.beginPath();
ctx.arc(400, 300, 50, 0, Math.PI * 2);
ctx.fill();

ctx.restore();
}

canvas.addEventListener('wheel', function(event) {
event.preventDefault();
const delta = event.deltaY > 0 ? 0.9 : 1.1;
scale = scale * delta;
draw();
});

draw();

Разбор примера:

  • canvas.getContext('2d') получает контекст для двумерной отрисовки;
  • ctx.save() сохраняет текущее состояние трансформаций;
  • ctx.translate(offsetX, offsetY) сдвигает начало координат;
  • ctx.scale(scale, scale) применяет равномерное масштабирование;
  • ctx.restore() возвращает состояние до преобразований;
  • событие wheel отслеживает прокрутку колесом мыши и изменяет коэффициент;
  • event.preventDefault() останавливает стандартную прокрутку страницы.

Панорамирование

Панорамирование — это перемещение камеры или viewport по сцене без изменения масштаба. Пользователь как бы двигает лист бумаги под увеличительным стеклом, рассматривая разные части изображения.

Отличие от прокрутки

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

Реализация через перетаскивание

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

Пример панорамирования в pygame


import pygame
import sys

pygame.init()

screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Панорамирование")

camera_x = 0
camera_y = 0
dragging = False
last_mouse_x = 0
last_mouse_y = 0

objects = [
{"x": 100, "y": 100, "w": 120, "h": 80, "color": (52, 152, 219)},
{"x": 400, "y": 300, "w": 150, "h": 100, "color": (231, 76, 60)},
{"x": -200, "y": -150, "w": 180, "h": 120, "color": (46, 204, 113)},
{"x": 700, "y": -300, "w": 100, "h": 160, "color": (241, 196, 15)},
]

running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
dragging = True
last_mouse_x, last_mouse_y = event.pos
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
dragging = False
elif event.type == pygame.MOUSEMOTION:
if dragging:
current_x, current_y = event.pos
delta_x = current_x - last_mouse_x
delta_y = current_y - last_mouse_y
camera_x += delta_x
camera_y += delta_y
last_mouse_x = current_x
last_mouse_y = current_y

screen.fill((30, 30, 30))

for obj in objects:
screen_x = obj["x"] + camera_x
screen_y = obj["y"] + camera_y
rect = pygame.Rect(screen_x, screen_y, obj["w"], obj["h"])
pygame.draw.rect(screen, obj["color"], rect)

pygame.display.flip()

pygame.quit()
sys.exit()

Разбор примера:

  • pygame.init() инициализирует библиотеку;
  • pygame.display.set_mode() создаёт окно заданных размеров;
  • переменные camera_x и camera_y хранят смещение камеры;
  • MOUSEBUTTONDOWN с button == 1 означает нажатие левой кнопки мыши;
  • при движении мыши с зажатой кнопкой вычисляется дельта смещения;
  • к мировым координатам каждого объекта прибавляется смещение камеры;
  • pygame.draw.rect() рисует прямоугольник в экранных координатах;
  • pygame.display.flip() обновляет содержимое окна.

Сочетание преобразований

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

Матричный подход

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

Иерархия координат

Объекты часто имеют собственную локальную систему координат, вложенную в родительскую. Мировые координаты получаются последовательным применением всех родительских трансформаций. Такой подход используется в игровых движках, SVG, CSS и графических редакторах.

Уровни иерархии координат:

  • локальные координаты объекта;
  • координаты родительского контейнера;
  • координаты сцены;
  • координаты камеры;
  • экранные координаты.

Примеры работы с геометрией в JavaScript и Python

Рисование сетки координат на Canvas

function drawGrid(ctx, step, width, height) {
ctx.strokeStyle = '#cccccc';
ctx.lineWidth = 1;

for (let x = 0; x <= width; x += step) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}

for (let y = 0; y <= height; y += step) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}

ctx.strokeStyle = '#000000';
ctx.lineWidth = 2;

ctx.beginPath();
ctx.moveTo(width / 2, 0);
ctx.lineTo(width / 2, height);
ctx.stroke();

ctx.beginPath();
ctx.moveTo(0, height / 2);
ctx.lineTo(width, height / 2);
ctx.stroke();
}

const canvas = document.getElementById('gridCanvas');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;

drawGrid(ctx, 50, canvas.width, canvas.height);

Разбор примера:

  • функция drawGrid принимает контекст, шаг сетки и размеры холста;
  • первый цикл рисует вертикальные линии через каждые step пикселей;
  • второй цикл рисует горизонтальные линии;
  • жирные линии отмечают центр холста, имитируя оси координат;
  • ctx.beginPath() начинает новый путь, ctx.moveTo() и ctx.lineTo() задают точки.

Геометрические фигуры в turtle


import turtle
import math

screen = turtle.Screen()
screen.setup(width=800, height=600)

pen = turtle.Turtle()
pen.speed(5)

def draw_square(t, x, y, size):
t.penup()
t.goto(x, y)
t.pendown()
for _ in range(4):
t.forward(size)
t.left(90)

def draw_circle(t, x, y, radius):
t.penup()
t.goto(x, y - radius)
t.pendown()
t.circle(radius)

def draw_triangle(t, x, y, size):
t.penup()
t.goto(x, y)
t.pendown()
for _ in range(3):
t.forward(size)
t.left(120)

draw_square(pen, -200, 100, 100)
draw_circle(pen, 50, 100, 60)
draw_triangle(pen, 200, 50, 120)

screen.mainloop()

Разбор примера:

  • draw_square перемещает черепаху в указанную точку и рисует квадрат через цикл из четырёх сторон;
  • draw_circle учитывает, что turtle.circle() рисует окружность над текущей позицией, поэтому происходит корректировка по Y;
  • draw_triangle использует поворот на 120 градусов для построения равностороннего треугольника;
  • каждая функция принимает координаты x и y, демонстрируя параметрическое позиционирование.

Геометрия в пользовательских интерфейсах

Элементы интерфейса располагаются в прямоугольных областях, описываемых четырьмя числами — координатами левого верхнего угла и размерами. В CSS эти параметры выражаются свойствами left, top, width, height. В графических редакторах и играх — структурами Rect или BoundingBox.

Ограничивающие прямоугольники

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

Вычисление расстояний и пересечений

Две распространённые задачи в интерфейсах и играх — проверка расстояния между объектами и проверка пересечения прямоугольников. Обе решаются простыми сравнениями координат и размеров.

Пример проверки пересечения на JavaScript

function rectanglesIntersect(rectA, rectB) {
const aLeft = rectA.x;
const aRight = rectA.x + rectA.width;
const aTop = rectA.y;
const aBottom = rectA.y + rectA.height;

const bLeft = rectB.x;
const bRight = rectB.x + rectB.width;
const bTop = rectB.y;
const bBottom = rectB.y + rectB.height;

const overlapX = aLeft < bRight && aRight > bLeft;
const overlapY = aTop < bBottom && aBottom > bTop;

return overlapX && overlapY;
}

const player = { x: 100, y: 100, width: 50, height: 50 };
const obstacle = { x: 130, y: 120, width: 60, height: 60 };

if (rectanglesIntersect(player, obstacle)) {
console.log('Обнаружено столкновение');
}

Разбор примера:

  • для каждого прямоугольника вычисляются координаты всех четырёх сторон;
  • overlapX становится истиной, когда горизонтальные проекции прямоугольников пересекаются;
  • overlapY проверяет пересечение вертикальных проекций;
  • итоговое пересечение имеет место при одновременном выполнении обоих условий;
  • этот подход называется Axis-Aligned Bounding Box и применяется повсеместно в 2D-играх.

Камера и виды проекций

В трёхмерных сценах камера определяет, какая часть мира попадает на экран. Положение камеры, направление взгляда и параметры объектива формируют итоговую картинку.

Параметры камеры

Камера описывается несколькими ключевыми параметрами:

  • положение в мировых координатах;
  • направление взгляда;
  • вектор «вверх», определяющий ориентацию;
  • угол обзора;
  • ближняя и дальняя плоскости отсечения.

Ортографическая и перспективная проекция

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

Перспективная проекция имитирует человеческое зрение: удалённые объекты выглядят меньше, параллельные линии сходятся в точке схода. Она применяется в 3D-играх, симуляторах и архитектурной визуализации.


Применения в реальных задачах

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

Области применения геометрических вычислений:

  • геоинформационные системы и карты;
  • компьютерные игры и симуляции;
  • графические редакторы и CAD-системы;
  • обработка изображений и компьютерное зрение;
  • робототехника и управление дронами;
  • виртуальная и дополненная реальность;
  • визуализация данных и инфографика;
  • пользовательские интерфейсы и вёрстка.

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


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).

Освоение главы0%