Лучший способ найти точку на окружности, ближайшую к данной точке

Учитывая точку (pX, pY) и круг с известным центром (cX, cY) и радиусом (r), какой кратчайший объем кода вы можете придумать, чтобы найти точку на окружности, ближайшую к (pX, pY)?

У меня есть какой-то код для работы, но он включает преобразование круга в уравнение формы (x - cX) ^ 2 + (y - cY) ^ 2 = r ^ 2 (где r - радиус) и использование уравнения линии от точки (pX, pY) до (cX, cY), чтобы создать квадратное уравнение, которое нужно решить.

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

На самом деле был для игры, но, тем не менее, получил решение.

Matt Mitchell 03.09.2010 08:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
38
1
30 012
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Триггерные функции, умножьте на r и добавьте pX или pY в зависимости от ситуации.

Почему бы вам избежать использования триггера в триггерной задаче?

mmcdole 19.11.2008 06:14

Тригонометрия часто (обычно) очень медленная по сравнению с другими методами. Один из примеров - вычисление кратчайшего расстояния между точкой и отрезком линии; решение матричной алгебры намного быстрее, чем триггерное.

MusiGenesis 19.11.2008 06:27

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

phkahler 08.01.2010 22:24

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

... или пересекли бы круг, если бы внутри круга.

Brad Gilbert 19.11.2008 18:12

Сначала решите это математически, а затем переведите в код. Помните, что самая короткая линия между точкой и краем круга также будет проходить через его центр (как указано в @litb).

Считайте центр круга своим началом, преобразуйте координаты (pX, pY) в полярные координаты, (theta, r ') замените r' на r исходного круга и преобразуйте обратно в декартовы координаты ( и отрегулируйте происхождение).

Ответ принят как подходящий

где P - точка, C - центр, а R - радиус, на подходящем "математическом" языке:

V = (P - C); Answer = C + V / |V| * R;

где | V | длина V.

ЛАДНО ЛАДНО

double vX = pX - cX;
double vY = pY - cY;
double magV = sqrt(vX*vX + vY*vY);
double aX = cX + vX / magV * R;
double aY = cY + vY / magV * R;

легко расширить до> 2 измерений.

Я реализовал часть математики, которую вы опубликовали до того, как вы написали свой код. Однако я обнаружил, что мне нужно иметь pX - vX, а не pX + pY, чтобы получить ближайшую сторону. В любом случае спасибо за это - мне любопытно посмотреть, есть ли какие-то более короткие решения.

Matt Mitchell 19.11.2008 06:29

V / | V | - это единичный вектор от C к P, поэтому я просто умножил его на R и добавил к C. Разве вы не умножили бы на -R, чтобы получить дальнейшую точку?

Mike Dunlavey 19.11.2008 06:33

Я вижу свою ошибку. Я должен был сказать C + V / | V | * Р

Mike Dunlavey 19.11.2008 06:34

Хех, я все равно использовал C + :-)

Matt Mitchell 19.11.2008 06:36

Отношение расстояния к успеху, разделенное на время, должно установить рекорд.

Mike Dunlavey 19.11.2008 06:38

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

WW. 19.11.2008 06:43

А также, если радиус равен нулю - это все еще круг?

WW. 19.11.2008 06:43

@WW ... я вижу, что ты там делал

Matt Mitchell 19.11.2008 06:44

Вы могли бы немного упростить объяснение (ИМО), если бы вы просто сказали: «Найти заголовок от центра круга до желаемой точки, нормализовать и умножить на радиус». Итак, если вектор A = центр и вектор B = ваша точка внутри или за пределами указанного круга A + (B - A) .normalized * radius; Теперь все это предполагает, что вы используете структуру или аналогичный для векторов или, по крайней мере, определили базовые математические операторы / функции для ваших векторов ... что OP не сказал, что они сделали, но я думаю, что делает то, что вы делаете, более ясным, вы могли затем предоставьте необходимые операции для нормализации ..

James McGhee 01.10.2018 18:15

Вы просили самый короткий код, вот он. В четыре строчки это можно сделать, хотя квадратичная еще есть. Я считал, что точка находится вне круга. Я не рассматривал, что происходит, если точка находится прямо над или под центром круга, то есть cX = pX.

m=(cY-pY)/(cX-pX);  //slope
b=cY-m*cX;  //or Py-m*Px.  Now you have a line in the form y=m*x+b
X=(  (2mcY)*((-2*m*cY)^2-4*(cY^2+cX^2-b^2-2*b*cY-r^2)*(-1-m^2))^(1/2)  )/(2*(cY^2+cX^2-b^2-2*bc*Y-r^2));
Y=mX+b;

1] Получите уравнение для линии, соединяющей точку и центр круга.

2] Переместитесь по линии на расстояние одного радиуса от центра, чтобы найти точку на окружности. То есть: радиус = a ^ 2 + b ^ 2, который равен: r = ((cY-Y) + (cX-X)) ^ (1/2)

3] Решайте квадратично. X = quadratic_solver (r = ((cY-Y) + (cX-X)) ^ (1/2), X), который, если вы подставляете в Y = m * X + b, вы получаете тот ад выше.

4] X и Y - ваши результаты на круге.

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

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

Windows programmer 19.11.2008 07:28

Легко представить это в терминах изображения и легко превратить в код: возьмите вектор (pX - cX, pY - cY) от центра к точке. Разделите его на длину sqrt (бла-бла-бла), умножьте на радиус. Добавьте это в (cX, cY).

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

  2. пусть центр будет (xc, yc), а кратчайшая точка на входе (xi, yi) будет (x, y), тогда sqrt ((xc-x) ^ 2 + (yc-y) ^ 2) = г

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

(yc-yi) / (xc-xi) = (y-yc) / (x-xc)

4. решение уравнений 2 и 3 должно дать нам кратчайший путь.

Другие вопросы по теме