3

I am trying to find the closest point on a parabola to an arbitrary point in 2d, for a DirectX pixel shader.

A great amount of googling has revealed to me that this is a common pre-calculus homework problem. Unfortunately, the hundreds of relevant answers all say things like "Once you have this equation, use your graphing calculator's minimum function and it will tell you the answer is 6."

I confess that I recall nothing of pre-calculus. I recognize that the equation I seek is probably sitting right there on wikipedia, but I can't figure out how to convert these greek symbols into an HLSL function. A solution in C, C++, C#, or any other language would also be greatly appreciated.

edit: Per a request to see the format of the input curve:

//Equation of parabola being y = ax^2 + bx + c
//p is the arbitrary point we're trying to find the closest point on the parabola for.
float2 GetClosestPointOnParabola(float a, float b, float c, float2 p)
{
    //Something involving the distance formula...
    //Something involving "minimization"...
    return float2(x, y);
} 
Greg Bahm
  • 638
  • 6
  • 11
  • There are infinitely many closest points to a parabola, namely all the points *on* the parabola, which have distance zero, and you can't get closer than that. I would guess that you are going to find doing computational geometry frustrating if you are not happy with the basics of maths and mathematical thinking, since this constitutes a (un)surprisingly large part of programming that sort of thing. – Kerrek SB Mar 21 '12 at 07:39
  • Please edit in some code to show how the parabola's data is represented. – SimpleVar Mar 21 '12 at 07:44
  • Kerrek SB, I apologize for what must have been an unclear post. I am trying to find the closest point on a parabola, to a point not on that parabola. I am certain that there is only one such point, and that it is the point perpendicular to the line formed between the tangent of the curve and the arbitrary point. – Greg Bahm Mar 21 '12 at 07:58
  • 1
    @Greg: note that a parabola has two limbs: the "closest point" to A isn't necessarily unique if A lies on the axis of symmetry of the parabola. I think then there can be up to three equally close points: one on each side plus the turning point of the parabola. But aside from that edge case, you're OK. – Steve Jessop Mar 21 '12 at 09:55
  • @GregBahm I have the similar problem. The derivatives are a bit complicated to solve for me. Did you find a answer? – Sirish Apr 09 '19 at 09:06

2 Answers2

3

You could make use of this:

Pmin = (xmin, ymin) ~ point on a parabola
P = (px, py) ~ point in 2d    
y = a*x^2 + bx + c ~ parabola

P(x) = (x-px)^2 + (y-py)^2 = (x-px)^2 + (a*x^2 + bx + c - py)^2

You need to calculate the P(x) derivative, it's not that difficult. E.g. If you get: P(x) = x^4 + 4x^2 - 3x + 10 the derivative would be:

P'(x) = 4x^3 + 8x - 3

I think you get how to calculate that. Then compare P'(x) to zero to find where it crossess an X-axis. You find an xmin from that and then you have ymin from:

y = a*x^2 + bx + c

That's it.

Michal B.
  • 5,676
  • 6
  • 42
  • 70
  • Al right, now it is closer to truth. First, I think you shouldn't make TS derivative, because he needs program and it is possible to derivative all symbolic and get answer in terms of `a, b, c, px, py`. Then, "P'(x) to zero to find where it crosses an X-axis" - why you pay attention to crossing X-asis? – Lol4t0 Mar 21 '12 at 08:13
  • @Lol4t0 in order to find local extremae you need to find the roots of the derivative. – Ivaylo Strandjev Mar 21 '12 at 08:48
  • According to my calculations, you have to solve the following cubic equation: `(2*a^2)*x^3 + (3*a*b)*x^2 + (2*a*c - 2*a*py + b^2 + 1)*x + (b*c - b*py - px) = 0` – rodrigo Mar 21 '12 at 08:58
0

I assume what you want is the point on a parabola that is closest to another point in the plane. Let's assume the parabola is given by y = a * x^2 + b * x + c and that you want to find the point on it closest to the point A(xa, ya).

I would propose you use hill climbing. It finds a local minimum in a function with a logarithmic complexity. I will write example c++ code assuming there is a function h(x) that calculates the distance from A to the point with the point with x coordinate equal to x on the parabola.

double minDist() {
  const double epsylon = 1e-9; // used to avoid double prescision errors
  double current = 0.0;
  double step = 1e+6;
  while (step > 1e-5) { // change this with the accuracy you need
    double left_neighbour = current - step;
    double right_neighbour = current + step;
    double cval = h(current);
    double lval = h(left_neighbour);
    double rval = h(right_neighbour);
    if (cval < rval + epsylon && cval < lval + epsylon) {
      step *= 0.5;
      continue;
    }
    if (lval < rval) {
      current = left_neighbour;
    } else {
      current = right_neighbour;
    }
  }
  return current;
}

In most case you will have a single local mimimum that is the answer you need, but maybe there are cases where you have two(I believe they can not be more then 2). In these cases you need to start the function twice with different initial points.

Hope this helps.

Community
  • 1
  • 1
Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
  • You can find excact expression for such simple case. Look @Michal B. answer – Lol4t0 Mar 21 '12 at 08:16
  • But a,b and c are parameters so after calculating the derivative, you still have to teach you computer to compute the roots of a polynom of 3rd degree. You may use Kardano's formula for that but I believe the accuracy of the answer will be greatly reduced because of its complexity. – Ivaylo Strandjev Mar 21 '12 at 08:42
  • @IvayloStrandjev GSL - GNU Scientific Library has a C solver for cubic equation https://www.gnu.org/software/gsl/manual/html_node/Cubic-Equations.html – Alessandro Jacopson Feb 24 '16 at 08:56