Posted: Tue Sep 01, 2009 6:44 pm
I think I understand it, I'm gonna "test" it on paper. Thanks for the idea!
Official forum of the Irrlicht Engine
https://irrlicht.sourceforge.io/forum/
Code: Select all
f32 c=sqrt(kwa(a)-kwa(b));
core::position2di focus1 = core::position2di((s32)(-c),0);
core::position2di focus2 = core::position2di((s32)(c),0);
Code: Select all
#include <iostream>
using namespace std;
#include <irrlicht.h>
using namespace irr;
IrrlichtDevice* device;
video::IVideoDriver* driver;
gui::ICursorControl* cursor;
#define SHOW_CMD_DEVICE
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#ifndef SHOW_CMD_DEVICE
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
#endif
f32 kwa(f32 a){
return a*a;
}
void drawEllips(f32 a,f32 b)
{
u32 steps = 36;
f32 prevX=0.f;
f32 prevY=0.f;
for (f32 i = 0; i <= 360.f; i += 360.f / (f32)steps)
{
f32 nowX = 320 + a * cos(i*(core::PI/180));
f32 nowY = 240 + b * sin(i*(core::PI/180));
if(prevX!=0.f){
driver->draw2DLine(core::position2di((s32)prevX,(s32)prevY),core::position2di((s32)nowX,(s32)nowY), video::SColor(255,0,0,255));
}
prevX=nowX;
prevY=nowY;
}
}
int main(){
device=createDevice(video::EDT_OPENGL);
driver=device->getVideoDriver();
cursor=device->getCursorControl();
f32 a=200.f;
f32 b=80.f;
while(device->run()){
core::position2di cpos =cursor->getPosition();
core::position2df pos((f32)cpos.X-320,(f32)cpos.Y-240);
driver->beginScene();
drawEllips(a,b);
f32 c=sqrt(kwa(a)-kwa(b));
driver->draw2DLine(core::position2di((s32)(320-c),240),cpos);
driver->draw2DLine(core::position2di((s32)(320+c),240),cpos);
driver->draw2DLine(core::position2di(320,240),cpos,video::SColor(255,255,0,0));
driver->endScene();
}
device->drop();
}
Code: Select all
#include <iostream>
using namespace std;
#include <irrlicht.h>
using namespace irr;
IrrlichtDevice* device;
video::IVideoDriver* driver;
gui::ICursorControl* cursor;
#define SHOW_CMD_DEVICE
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#ifndef SHOW_CMD_DEVICE
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
#endif
f32 kwa(f32 a){
return a*a;
}
void drawEllips(f32 a,f32 b)
{
u32 steps = 36;
f32 prevX=0.f;
f32 prevY=0.f;
for (f32 i = 0; i <= 360.f; i += 360.f / (f32)steps)
{
f32 nowX = 320 + a * cos(i*(core::PI/180));
f32 nowY = 240 + b * sin(i*(core::PI/180));
if(prevX!=0.f){
driver->draw2DLine(core::position2di((s32)prevX,(s32)prevY),core::position2di((s32)nowX,(s32)nowY), video::SColor(255,0,0,255));
}
prevX=nowX;
prevY=nowY;
}
}
core::position2df getClosestPoint(f32 a,f32 b,core::position2df from, u32 detail = 72)
{
f32 closeX=0.f;
f32 closeY=0.f;
f32 closedist=0.f;
bool init=false;
for (f32 i = 0; i < 360.f; i += 360.f / (f32)detail)
{
f32 thisX = a * cos(i*(core::PI/180));
f32 thisY = b * sin(i*(core::PI/180));
f32 thisdist = kwa(thisX-from.X)+kwa(thisY-from.Y);
if(!init){closedist=thisdist+1.f;init=true;}
if(thisdist<closedist){
closedist=thisdist;
closeX=thisX;
closeY=thisY;
}
}
return core::position2df(closeX,closeY);
}
int main(){
device=createDevice(video::EDT_OPENGL);
driver=device->getVideoDriver();
cursor=device->getCursorControl();
f32 a=200.f;
f32 b=80.f;
while(device->run()){
core::position2di cpos =cursor->getPosition();
core::position2df pos((f32)cpos.X-320,(f32)cpos.Y-240);
//this is the function that does everything
core::position2df Pf = getClosestPoint(a,b,pos,200);
driver->beginScene();
drawEllips(a,b);
s32 Px = (s32)Pf.X+320;
s32 Py = (s32)Pf.Y+240;
driver->draw2DLine(core::position2di((s32)Px,(s32)Py),cpos, video::SColor(255,0,255,0));
driver->endScene();
}
device->drop();
}
Me too! I wish I'd had more time over the past few days to find a solution, but the real world has been intruding on my computer time.Dorth wrote:Ok, I'm seriously having fun just reading this topic...
Can we have another math challenge after that one is concluded? This should go in the competition section or something
If the competition is just to get a solution and not a working code than I won ! Maple gave me a unhandy solution.Can we have another math challenge after that one is concluded? This should go in the competition section or something
True! I need a working code, though.If the competition is just to get a solution and not a working code than I won Wink
That would be nice! Thanks!I will ask my math professor, I think he can tell me if there is a nice and simple solution to this problem.
Code: Select all
// getClosestPointToEllipsoid
// returns the closest point to an axis-aligned ellipsoid, from a given point
// 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 Scale: the ellipsoid radius
// \return the closest point ont the ellipsoid
// issues:
// - getting more and more unaccurate the deeper "Point" is inside the ellipsoid
// - it's only 2D !!!!!!!!!!!!!!!!!!!!!!!!!
core::vector3df CGame::getClosestPointToEllipsoid(const core::vector3df& Point, const core::vector3df& Scale)
{
// find the largest scale factor (radius), and it's axis:
float mx = Scale.X;
core::vector3df axis = core::vector3df(1, 0, 0);
if (Scale.Y > mx) { mx = Scale.Y; axis = core::vector3df(0, 1, 0); }
if (Scale.Z > mx) { mx = Scale.Z; axis = core::vector3df(0, 0, 1); }
// find the smallest scale factor (radius), and prepare the transformation vectors:
float mn = core::min_(Scale.X, Scale.Y, Scale.Z);
core::vector3df mps = core::vector3df(mn) / Scale;
core::vector3df spm = Scale / core::vector3df(mn);
// get the intersection with the ellipsoid:
core::vector3df i = core::vector3df((Point * mps).normalize() * Scale);
// early exit, if it's right on the ellipsoid
float ilen = i.getLength(), plen = Point.getLength();
if (core::equals(ilen, plen)) return i;
// get the ratio we need to scale the ellipsoid,
// and transform the max. and min. scale factor (radius) with it
// note: finding the closest point gets more and more unaccurate the deeper "Point" is
ilen = !ilen ? 1 : ilen;
float ratio = plen / ilen;
float tmn = mn * ratio;
float tmx = (ilen < plen) ? mx + (tmn - mn) : mx * ratio;
// calculate the two foci, and Point->F1, Point->F2, then the half vector
float c = sqrt((tmx * tmx) - (tmn * tmn));
core::vector3df f1 = axis * c, f2 = -f1;
core::vector3df v1 = (f1 - Point).normalize();
core::vector3df v2 = (f2 - Point).normalize();
core::vector3df v = (v1 + v2).normalize();
// transform Q and Point
core::vector3df q = Point + v;
core::vector3df tp = Point * mps;
core::vector3df tq = q * mps;
// intersect TP->TQ with the sphere of the min. scale factor (radius)
double dist = 1;
core::line3df ray(tp, tq);
ray.getIntersectionWithSphere(core::vector3df(), mn, dist);
core::vector3df n = ray.getVector().normalize();
core::vector3df si = tp + (n * dist);
// transform back the intersection point
return si * spm;
}