Какова идея определения прямоугольников с двумя точками? [закрыто]


14

Не то, чтобы это не имело смысла, но это работает неловко в 99% случаев.

Часто в 2D-графике прямоугольники инициализируются, сохраняются и управляются как пара точек. Ни на каком конкретном языке,

class Rect:
   p1, p2: point

Имеет смысл определить прямоугольник как два значения x и два значения y, например:

class Rect
   xleft, xright: int
   ytop, ybottom: int

С двумя точками, если в каком-то месте исходного кода вы хотите использовать значение y верхней части, вы должны будете сказать rect.p1.y (хммм, остановитесь и подумайте, это p1 или p2), но с четырьмя значениями в качестве простых элементов данных это ясно и понятно: rect.ytop (не нужно думать!) Использование двух точек означает, что при работе с вертикалью вам необходимо запутать горизонталь; есть посторонняя связь между независимыми элементами.

Как возникла эта двухточечная идея и почему она сохраняется? Есть ли у него преимущество над голыми координатами x и y?

ДОБАВЛЕННОЕ ПРИМЕЧАНИЕ: Этот вопрос относится к прямоугольникам, выровненным по XY, таким как диспетчеры окон и наборы инструментов GUI, а не к контексту произвольных фигур в приложении для рисования и рисования.


8
Вы написали значительное количество кода, используя Rects?

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

2
Прямоугольник более естественно определяется как диапазон значений x и диапазон значений y.
DarenW

2
Отличный вопрос! Я никогда не думал об этом сам, но вы приводите интересный аргумент! FWIW, у Windows есть RECT, как вы описали также (вверху, слева, снизу, справа)
Дин Хардинг,

3
Как вы определяете прямоугольник с двумя точками? Предполагается, что нет вращения?
Ник Т

Ответы:


8

Считаете ли вы, что он менее подвержен ошибкам?

Если вы используете (Point1, Point2), тогда очень ясно, что вы указываете. Если вы укажете 2 балла, единственно возможная ошибка заключается в том, что пользователь смешал свои x и y при построении точек, поскольку порядок точек не имеет значения.

Если вы предоставите 4 целых числа, то, если кто-то не обращает на это внимания, он может предоставить (x1, x2, y1, y2), когда вы захотите (x1, y1, x2, y2) или наоборот. Кроме того, некоторые API, такие как структура Rect WCF, определяют прямоугольник как (x, y, width, height), что может привести к путанице в отношении значения (1, 2, 3, 4). Это (x, y, w, h) или (x1, y1, x2, y2) или (x1, x2, y1, y2)?

В общем, (Point1, Point2) кажется мне немного безопаснее.


3
Как насчет чего-то вроде Rect (xrange (x1, x2), yrange (y1, y2))? Это кажется высшим в безопасности и элегантности использования API.
DarenW

9

Мне всегда нравилось определять прямоугольник как точку + ширина и высота, где точка - это верхний левый угол прямоугольника.

class Rect {
  float x, y;
  float width, height;
}

А затем добавьте любые методы, которые вам нужны, чтобы получить другие метрики. Как версия Java


4
Вершина у + высота, у-высота или просто у?
Кэмерон Макфарланд

2
@Cameron MacFarland: это зависит от системы координат приложения, которая не касается простого прямоугольника.
Джон Перди

2
@Martin Wickman: В чем преимущество использования 2 очков?
Kramii

@Kramii: Одним из преимуществ является то, что нужно перевести только одну точку, если вы перемещаете весь прямоугольник. Кстати, вы всегда можете рассчитать «недостающую точку», если вам это нужно (компромисс между процессором и памятью).
Мартин Уикман

Это тоже появляется в реальной жизни. Я нахожу это хитрым, так как одна из самых распространенных вещей, которые я делаю с прямоугольниками, это проверка, содержится ли точка внутри. Рисование также распространено. В обоих случаях необходимо выполнить сложение, что мешает быстродействующим счетчикам тактов, таким как я.
DarenW

7

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

Существует несколько способов представления прямоугольников, параллельных осям:

  1. Две диагонально противоположные точки
  2. Одна угловая точка, высота и ширина
  3. Центральная точка, половина высоты и ширины (необычно, но иногда полезно).
  4. Как две координаты X и две координаты Y

Для (1) многие библиотеки используют соглашение, чтобы определить, какие две точки используются - например, topLeft и bottomRight.

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

Преимущества определения (1) перед другими включают:

  • Согласованность API с другими полигонами, линиями и т. Д.
  • topLeft, bottomRight может быть передан любому методу, который принимает точки
  • Методы класса Point могут быть вызваны на topLeft, bottomRight
  • Большинство свойств могут быть получены легко, например. bottomLeft, topRight, ширина, высота, центр, длина диагонали и т. д.

6

Ну, p1: Pointи в любом случае у p2: Pointкаждой будет две intкоординаты , так разве ваш класс не означает одно и то же?

И если вы храните эти две точки как первоклассные Pointобъекты, разве вы не получите от них немного больше полезности? В большинстве известных мне графических систем координат точки подклассируются таким образом, чтобы создать иерархию объектов: point -> circle -> ellipseи так далее.

Поэтому, если вы создаете объект, который не использует Pointкласс, вы отделите этот объект от остальной части иерархии классов.


1
Преимущество представления OP, которое я вижу, состоит в том, что если вы хотите узнать нижнее значение y прямоугольника, вы знаете, что это «ybottom», где, как и в случае p1 / p2, вам нужно выяснить, какой из них ниже. В любом случае, если вы не гарантируете, что p1 будет иметь более низкие значения.
Джейсон Вирс

1
Несмотря на то, что обе эти разные структуры сводятся к четырем координатам, версия с двумя точками вводит посторонний уровень, который собирает один x и один y, без какого-либо конкретного обоснования, с которым x идет, с каким y. Я не вижу в этом дополнительном уровне никакой полезности после многих лет графического программирования.
DarenW

1
@ Джейсон: Хороший вопрос. Однако с ytop/ ybottomподходом должна быть гарантия где-то ybottomниже ytop.
Ученик доктора Вилли

Или назовите их y1 и y2 и используйте min (y1, y2) и max (y1, y2) - конечно, это будет неуклюже даже при доступе через две точки p1, p2.
DarenW

наименование top / bottom ничего не покупает, так как ничто не мешает bottomx <topx, если вы не кодируете это специально. Я думаю, что это только добавило бы беспорядок
lkg

5

Вот почему я люблю Delphi TRect. Он определяется как вариантная запись (структура объединения на языке C), которую можно интерпретировать как точку TopLeft и BottomRight или целые числа Top, Left, Bottom и Right, в зависимости от того, что более удобно в данный момент.


1
Да, очень полезная функция, которая.
Orbling

4

Конечно, если вы определите свой прямоугольник как:

class Rect
{
    Point bottomLeft;
    Point topRight;
}

тогда вы сразу знаете, какая точка есть какая.

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

Добавив преобразование в форму, вы можете сориентировать свой прямоугольник так, как вам нравится. Вам все еще понадобится ограничивающий прямоугольник с выравниванием по оси для быстрого принятия / отклонения проверок :)

Однако, если ваша модель допускает прямоугольники в любой ориентации без применения преобразования, тогда значения «нижний левый» и «верхний правый» не имеют значения, что приводит к «p1» и «p2» (или к чему-то эквивалентному).


Так что же происходит, когда вы поворачиваете прямоугольник на 90 градусов? Теперь вы отслеживаете две разные точки, которые были изначально, или ваш «topRight» теперь слева от «bottomLeft»?
Инамати

@Inaimathi - если вы добавите матрицу преобразования, вы можете сохранить прямоугольник, ориентированный по осям. Тем не менее, это зависит от вашего приложения.
ChrisF

2

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

но, вероятно, было проще всего кодировать его как две точки!


Как было бы проще кодировать как две точки?
DarenW

@DaremW: типичные библиотечные функции рисования прямоугольника принимают верхнюю левую и нижнюю правую точки в качестве аргументов
Стивен А. Лоу

Но почему эти API разработаны таким образом? Кроме бессмысленного подражания более ранним библиотекам.
ДаренВ

@DarenW: я думаю, что библиотеки используют подпрограмму рисования линий Брезенхэма, которая принимает две точки в качестве входных данных и является очень эффективной
Стивен А. Лоу

2

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


5
Важно понимать, что «стандартная» структура прямоугольника - это не строго определенный математический прямоугольник, а упрощенная версия, которая всегда параллельна осям X и Y, потому что она была создана для использования в одной очень конкретной вещи: определение прямоугольных областей для оконного менеджера, который (почти) всегда параллелен осям X и Y.
Мейсон Уилер

+1, структура left / right / top / bottom предварительно отсортирована и поэтому содержит меньше информации
Javier

Хороший вопрос, о выровненных по xy прямоугольниках. Я имел в виду это, а также экстенты, используемые в 3D-моделировании, и некоторые другие вещи, но все xy (возможно, также -z) выровнены.
ДаренВ

1

Разве это не то же самое, что 2 балла? Как это неловко ... большинству подпрограмм рисования нужны точки, а не отдельные компоненты x / y.


1

Определение прямоугольников как пар точек позволяет повторно использовать точку в качестве вершины для другой фигуры. Просто мысль...


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

если есть метод доступа, который определен как точка AX точка BY и точка BX точка AY, он делает его светлее в памяти / на диске, я думаю сохранить половину вершин и просто указать на них (в зависимости от максимального размера сетки). Я понял, куда вы идете с мыслью о вашем диапазоне, но вы не играете с половиной колоды, вы просто не храните дублирующиеся данные .... и другие моменты, которые нужно подчеркнуть, каковы ограничения памяти? Каковы последствия повторной реализации reteoling rects во всем взаимосвязанном коде.
RobotHumans

и так как вам не нужно выполнять какую-либо «работу», чтобы вытащить первые две вершины из памяти, это, вероятно, быстрее
RobotHumans

1

Я считаю, что это главным образом для установления единообразия между всеми примитивами формы.

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

Все полигоны могут быть определены их точками, с небольшим количеством логики, чтобы определить, что делать с точками.

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


1

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

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

Я ожидаю, что инкапсуляция сделает эту дифференциацию неважной как пользователь класса.

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


1

Это совершенно произвольно. Вам нужно четыре части информации, чтобы нарисовать прямоугольник. Разработчики библиотеки решили представить его двумя точками (каждая с координатой xy), но легко могли сделать это с помощью x / y / w / h или top / bottom / left / right.

Я полагаю, что настоящий вопрос ОП заключается в следующем: почему был сделан именно этот выбор?


1

Выбор параметров важен только для разработчиков / программистов низкого уровня.

Пользователям высокого уровня нужно думать только о:

  • IsPointInRect
  • Площадь
  • Пересечение (или отсечение)
  • HasOverlap (такой же, как Intersection.Area> 0)
  • Союз (становится списком прямоугольников)
  • Вычитание (список прямоугольников, представляющих тот же набор точек, который находится в прямоугольнике A, но не в прямоугольнике B)
  • преобразование
    • Сдвиги в X и Y
    • Вращение (0, 90, 180, 270)
    • Масштабирование по X и Y (см. Примечание)
  • Простой синтаксис для свойств Xmin, Xmax, Ymin, Ymax, Width, Height, так что пользователю не нужно знать точный выбор параметров.

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


0

Как говорит @Steven, я думаю, что это должно быть с точки зрения одной (x, y) точки и вектора размера (w, h). Это потому, что легко попасть в неоднозначность. Предположим, у вас есть следующий заполненный прямоугольник, начиная с точки (0,0).

  012
0 XXX
1 XXX
2 XXX

Ясно, что это ширина, высота (3,3), но какова его вторая точка? Это (2,2) или (3,3)?

Эта двусмысленность может вызвать все виды проблем.

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


2
Оригинальные подпрограммы QuickDraw на Mac (созданные в 1980-х годах) использовали математическую модель, в которой точки были бесконечно малы. Точки на экране лежат между пикселями. Таким образом, линия, проведенная от (3,5) до (10,5), имела длину 7 и занимала 7 пикселей. В сегодняшних координатах эта линия будет иметь длину 8.
Барри Браун

@ Барри: Это имеет смысл, так как он часто использовал XOR, и если вы соединяете строки вместе, вы хотите, чтобы они соединялись без пропущенного пикселя в месте их встречи. На самом деле я опубликовал статью о заполнении полигонов с учетом обеих систем координат.
Майк Данлавей

0
Pa(x,y)*-----------------------------------*Pb(x,y)
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
Pc(x,y)*-----------------------------------*Pd(x,y)

Мы можем определить Pb и Pc следующим образом:

Pb (Pd (х), Па (у))

и

Рс (Па (х), Pd (у))

Таким образом, нет необходимости определять все четыре точки из-за симметрии

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.