Пересечение произвольной прямой и наклонного эллипса

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

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

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

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

Пересечение произвольной линии и эллипса

Есть теоретическая статья на эту тему. Для нахождения координат используется квадратное уравнение. Статья посвящена нахождению коэффициентов этого уравнения.

Рис.1. Пересечение произвольной линии и эллипса

В статье нет исходного кода. Поэтому исправляю ситуацию. Для нахождения координат используется следующая функция.

Как говорится в таких случаях, орфография и стилистика в именах переменных сохранены. Результат, равный 0, означает, что пересечений нет, 1 означает, что линия соприкасается с эллипсом в точке Res.TopLeft, 2 — две точки пересечения Res.TopLeft и Res.BottomRight.

Формулы аффинного поворота

Напомню формулы аффинного поворота:

Latex formula

Latex formula

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

TPointF в Delphi 7

Чтобы использовать тип TPointF в Delphi 7 и функции с ним связанные необходим модуль IP76DrawUtils из исходников в конце статьи. Он также обеспечивает совместимость с XE 7, XE 10, XE 11. На других XE возможности протестировать нет.

Рисование наклонного эллипса

Теоретическая часть, как рисовать эллипс под углом и функция рисования находятся тут.

Пересечение линии с наклонным эллипсом

Что будет, если мы вначале повернем линию на угол, обратный повороту эллипса, а потом повернем эллипс вместе с линией на этот угол? А будет идеальное решение:

Рис.2. Процесс расчета координат пересечения произвольной линии и наклонного эллипса

Как считать

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

Таким образом, алгоритм состоит из трех пунктов:

  1. Повернуть точки p1 и p2, задающие линию, на угол, обратный поворотному для эллипса. Для этого применяются формулы аффинного поворота. Таким образом, получаем точки p1′ и p2′.
  2. Найти точки пересечения линии (p1′, p2′) с не-повернутым эллипсом с помощью квадратного уравнения. Пусть это будут точки r1′ и r2′.
  3. Повернуть точки r1′ и r2′ на угол поворота эллипса. Полученные точки r1, r2 и будут являться результатом.

Собственно, поэтому у нас функция аффинного поворота RotateTwoPoint принимает и возвращает две точки.

Функция расчета:

Комментарии к программе: Анимация

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

Рис.3. Действия перед анимацией

После этого поставить галку в «Анимации». Будет происходить действо, как на рисунке 2. Можно поиграться с галкой «Без поворота», но боюсь данное действие может немного запутать кучей линий на экране.

Комментарии к исходнику: TThread

Внутри, конечно, много интересного. Но меня периодически спрашивают, почему я не использую потоки (которые нити) для анимации и как использовать класс TThread. Поэтому в исходнике есть поток:

Он простенький, однако принцип работы демонстрирует. Для работы с полями и компонентами формы используется метод Synchronize. Это не единственный способ работать с чем-то вне потока, но здесь так. Потому что статья не про потоки )))

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


Скачать

Друзья, спасибо за внимание!

Исходник (zip) 181 Кб. Delphi 7, XE 7, XE 10, XE 11

Для XE открываем файл .dpr и в обязательном порядке build’им.

Пустой подкаталог _dcu в архиве — для Delphi 7.

Исполняемый файл (zip) 296 Кб.

Друзья! Буду чрезвычайно признателен за комментарии, регистрацию на сайте, подписку в телеге. Это очень значимая моральная поддержка для меня.


5 7 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Oleg

Пример шикарный, детально описанный в статье и как всегда хорошо документированный в исходниках! Благодарю!

Последний раз редактировалось 1 год назад Oleg ем
2
0
Не нашли ответ на свой вопрос? Задайте его здесь!...x