Abstand vom gegebenen Punkt zur gegebenen ellipse
Ich habe eine ellipse, definiert durch Mittelpunkt, radiusX und radiusY, und ich habe einen Punkt. Ich möchte finden den Punkt auf der ellipse, die am nächsten zu den gegebenen Punkt. In der Abbildung unten, das wäre S1.
Nun ich habe schon code, aber es ist ein logischer Fehler irgendwo, und ich scheinen nicht in der Lage sein, um es zu finden. Ich brach das problem auf die folgende code-Beispiel:
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
using namespace std;
void dostuff();
int main()
{
dostuff();
return 0;
}
typedef std::vector<cv::Point> vectorOfCvPoints;
void dostuff()
{
const double ellipseCenterX = 250;
const double ellipseCenterY = 250;
const double ellipseRadiusX = 150;
const double ellipseRadiusY = 100;
vectorOfCvPoints datapoints;
for (int i = 0; i < 360; i+=5)
{
double angle = i / 180.0 * CV_PI;
double x = ellipseRadiusX * cos(angle);
double y = ellipseRadiusY * sin(angle);
x *= 1.4;
y *= 1.4;
x += ellipseCenterX;
y += ellipseCenterY;
datapoints.push_back(cv::Point(x,y));
}
cv::Mat drawing = cv::Mat::zeros( 500, 500, CV_8UC1 );
for (int i = 0; i < datapoints.size(); i++)
{
const cv::Point & curPoint = datapoints[i];
const double curPointX = curPoint.x;
const double curPointY = curPoint.y * -1; //transform from image coordinates to geometric coordinates
double angleToEllipseCenter = atan2(curPointY - ellipseCenterY * -1, curPointX - ellipseCenterX); //ellipseCenterY * -1 for transformation to geometric coords (from image coords)
double nearestEllipseX = ellipseCenterX + ellipseRadiusX * cos(angleToEllipseCenter);
double nearestEllipseY = ellipseCenterY * -1 + ellipseRadiusY * sin(angleToEllipseCenter); //ellipseCenterY * -1 for transformation to geometric coords (from image coords)
cv::Point center(ellipseCenterX, ellipseCenterY);
cv::Size axes(ellipseRadiusX, ellipseRadiusY);
cv::ellipse(drawing, center, axes, 0, 0, 360, cv::Scalar(255));
cv::line(drawing, curPoint, cv::Point(nearestEllipseX,nearestEllipseY*-1), cv::Scalar(180));
}
cv::namedWindow( "ellipse", CV_WINDOW_AUTOSIZE );
cv::imshow( "ellipse", drawing );
cv::waitKey(0);
}
Es ergibt sich folgende Bild:
Können Sie sehen, dass es tatsächlich findet "in der Nähe" der Punkte auf der ellipse, aber es sind nicht die "nächste" Punkte. Was ich bewusst will, ist diese: (entschuldigt meine schlechte Zeichnung)
würden Sie, soweit Sie die Zeilen in dem letzten Bild, Sie würde durch die Mitte der ellipse, aber dies ist nicht der Fall für die Linien in der vorherigen Abbildung.
Ich hoffe, Sie bekommen das Bild. Kann mir jemand sagen was ich falsch mache?
- es wird einfacher sein, wenn Sie nur beschreiben, Ihre Methode für die Suche nach dem Punkt, als der eigentliche code
Du musst angemeldet sein, um einen Kommentar abzugeben.
Betrachten einen umgebenden Kreis um den gegebenen Punkt (c, d), die Pässe, über den nächsten Punkt auf der ellipse. Aus dem Diagramm ist es klar, dass der nächste Punkt ist, so dass eine Linie zum angegebenen Punkt muss senkrecht auf der gemeinsamen Tangente der ellipse und Kreis. Andere Punkte außerhalb des Kreises und so muss weiter Weg von dem gegebenen Punkt.
Also den Punkt, den Sie suchen, ist nicht der Schnittpunkt zwischen der Linie und der ellipse, der Punkt (x, y) im Diagramm.
Steigung der Tangente:
Steigung von Zeile:
Bedingung für perpedicular Linien - Produkt der Steigungen = -1:
Wenn neu angeordnet und ersetzt, in die Gleichung der ellipse...
...diese zwei fiesen quartic (4. Grad-Polynom-Gleichungen im Sinne von entweder x oder y. AFAIK gibt es keine Allgemeinen analytische (exakte algebraische) Methoden, Sie zu lösen. Sie könnten versuchen, eine iterative Methode - look-up-die Newton-Raphson iterativen root-finding-Algorithmus.
Werfen Sie einen Blick auf diese sehr gute Arbeit über das Thema:
http://www.spaceroots.org/documents/distance/distance-to-ellipse.pdf
Sorry für die unvollständige Antwort - ich völlig die Schuld in die Gesetze der Mathematik und der Natur...
EDIT: UPS, ich scheine a und b falsch herum in das Diagramm xD
Gibt es eine relativ einfache numerische Methode, mit der eine bessere Konvergenz als die Newton-Methode. Ich habe einen blog-Beitrag darüber, warum es funktioniert http://wet-robots.ghost.io/simple-method-for-distance-to-ellipse/
Diese Implementierung funktioniert, ohne trigonometrische Funktionen:
Kredit Adrian Stephens für die Trig-Free-Optimierung.
tx
ist nicht definiert, die vor dem ersten Einsatz.Hier ist der code übersetzt, in C# implementiert, aus diesem Papier zu lösen, für die ellipse:
http://www.geometrictools.com/Documentation/DistancePointEllipseEllipsoid.pdf
Beachten Sie, dass dieser code ist ungetestet - wenn Sie einen Fehler finden lasst es mich wissen.
Den folgenden python-code implementiert die Gleichungen beschrieben unter "Abstand von einem Punkt zu einer Ellipse" und verwendet die newtonsche Methode, um die Wurzeln und damit den nächsten Punkt auf der ellipse zum Punkt.
Leider, wie Sie sehen können aus dem Beispiel, es scheint nur genau außerhalb der ellipse. Innerhalb der ellipse seltsame Dinge passieren.
Hier ein Beispiel:
Generiert einer ellipse und der Abstand von der Grenze der ellipse als heat-map. Wie gesehen werden kann, an der Grenze der Entfernung ist null (deep blue).
Brauchen Sie nur berechnen Sie den Schnittpunkt der Linie
[P1,P0]
zu Ihrem elipse, dieS1
.Wenn die Linie equeation ist:
und die elipse equesion ist:
als die Werte der
S1
werden:Nun müssen Sie nur berechnen Sie die Entfernung zwischen
S1
zuP1
die Formel (fürA,B
Punkte) ist:Gegeben eine ellipse E in der parametrischen form und einen Punkt P
dem Quadrat der Entfernung zwischen P und E(t) ist
Minimum erfüllen muss,
Mithilfe der trigonometrischen Identitäten
und ersetzen
ergibt sich die folgende quartic equation:
Hier ist ein Beispiel für die C-Funktion, die löst das quartic direkt und berechnet sin(t) und cos(t) für den nächsten Punkt auf der ellipse:
Versuchen Sie es online!
check_dist(4.0, 2.0, 0, 6);
Ergebnisse in nurnan
zum Beispiel.NaN
für(1.0, 0.75, -0.128053, -0.743808)
Hab ich gelöst der Distanz Problem über Schwerpunkte.
Für jeden Punkt auf der ellipse
r1 + r2 = 2*a0
wo
r1 - euklidischen Abstand vom gegebenen Punkt zum Brennpunkt 1
r2 - euklidischen Abstand vom gegebenen Punkt zum Brennpunkt 2
a0 - semimajor axis Länge
Kann ich auch die Berechnung der r1 und r2 für einen gegebenen Punkt, die gibt mir eine weitere ellipse, dass dieser Punkt liegt auf, der konzentrisch zu der gegebenen ellipse. Also der Abstand ist
d = Abs((r1 + r2) /2 - a0)