Sorry guys I didn't have as much spare time as yesterday.
I really appreciate the effort you guys put into this! Thanks!
@Dorth:
Yes, see my approach below. (I've added your idea about the foci, thanks!)
xray:
Yeah, it does ring a bell, however, I'm not really familiar with derivates and integrates... I did everything I had to in school, but I haven't spent enough time understanding them in a depth. Plus, I'm much more like an artist, and as an artist, my approach was visual.
I guess the method you suggest won't be really fast, however, I'm still interested. Did I mention to that I'd like to have a solution in 3D?
I guess that complicates things a bit.
Again, thanks guys!
----------------------------------------------------------
Maybe this is what I should have started with: my approach. The two reasons why I did not:
1# to have a brainstorming about the problem,
2# I've simply forgotten
I've made a sphere-problem of the ellipsoid-problem:
Image:
What I do here is:
- transform P into TP
- calculate Q
- transform Q into TQ
- get the intersection point with the sphere (I)
- transform I to TI
- TI is the closest point
Code:
Code: Select all
// getClosestPointToEllipsoid
// gives the closest point to an axis-aligned ellipsoid
// assumes that the ellipsoid is at the origin
// treats the ellispoid-problem as a sphere-problem
// \param Point: the point you want to project onto the ellipsoid
// \param Radius: the ellipsoid radius
// \return the closest point ont the ellipsoid
// issues:
// - fails on the inner side of the ellipsoid (the more deeper "Point" is)
// - issues towards the highest peaks
// - not punctual
core::vector3df CGame::getClosestPointToEllipsoid(const core::vector3df& Point, const core::vector3df& Radius)
{
// prepare "mn" (= "a"), "mx" (= "b"), and later "c"
float mx = core::max_(Radius.X, Radius.Y, Radius.Z);
float mn = core::min_(Radius.X, Radius.Y, Radius.Z);
core::vector3df mpr = core::vector3df(mn) / Radius;
core::vector3df rpm = Radius / core::vector3df(mn);
// now check if the "Point" is inside, outside, or on the ellipsoid
// the original direction to "Point"
core::vector3df dir = core::vector3df(Point).normalize();
// the intersection point on the ellipsoid
core::vector3df isect = core::vector3df((dir * mpr).normalize() * Radius);
// if it's on the ellipsoid, return
float plen = Point.getLengthSQ(), ilen = isect.getLengthSQ();
if (core::equals(plen, ilen)) return isect;
// transform "Point" to sphere-space
core::vector3df tp = Point * mpr;
// calculate "q" (for the inside, it's really bad)
core::vector3df q = (plen > ilen) ? (Point - tp) : (Point - (tp * mpr));
// clamp "q" to the nearest focus point of the ellipse
float c = sqrt((mx * mx) - (mn * mn));
if (q.getLength() > c) q.setLength(c);
// transform "q" to sphere-space
core::vector3df tq = q * mpr;
// calculate intersection of the sphere with ray "tp-tq"
core::line3df ray(tp, tq);
double dist = 1;
ray.getIntersectionWithSphere(core::vector3df(), mn, dist);
core::vector3df n = (tq - tp).normalize();
// the intersection point
core::vector3df i = tp + (n * dist);
// transform the intersection point back to ellipsoid-space
core::vector3df ti = i * rpm;
return ti;
}
Here are the issues about it:
- fails on the inner side of the ellipsoid (the more deeper "Point" is)
- issues towards the highest peaks (small)
- I bet it's not punctual! (90-95% would be great)
I can make a small test program if you want!
Can you help me to repair it? Or: can it be repaired?
Thank you
Cheers,
PI