topical media & game development
basic-visual-05-osculatingcircle.c
? /
basic-visual-05-osculatingcircle.c
// ------------------------------------------------------------------------
// This program is complementary material for the book:
//
// Frank Nielsen
//
// Visual Computing: Geometry, Graphics, and Vision
//
// ISBN: 1-58450-427-7
//
// Charles River Media, Inc.
//
//
// All programs are available at www.charlesriver.com/visualcomputing/
//
// You may use this program for ACADEMIC and PERSONAL purposes ONLY.
//
//
// The use of this program in a commercial product requires EXPLICITLY
// written permission from the author. The author is NOT responsible or
// liable for damage or loss that may be caused by the use of this program.
//
// Copyright (c) 2005. Frank Nielsen. All rights reserved.
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// File: osculatingcircle.cpp
//
// Description: Interactive demo of the osculating circle of a parametric curve
// ------------------------------------------------------------------------
include <stdafx.h>
include <windows.h>
include <math.h>
include <GL/gl.h>
include <GL/glut.h>
define W 800
define H 800
using namespace std;
typedef double number;
class point {
public:
number x,y;
inline number Distance(point q)
{return sqrt((q.x-x)*(q.x-x) + (q.y-y)*(q.y-y));}
};
void SolveDisc3(point p1, point p2, point p3, point & center, number &rad);
point center, pleft, p, pright;
double r,curv;
inline float f(number x)
{
return 5*pow((x-0.5),3.0)+0.5;
}
void disp( void )
{
char buffer[256];
int i;
float x;
double theta;
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1.0);
glColor3f(0,0,0);
glBegin(GL_POINTS);
for(x=0;x<1.0;x+=0.001)
{
glVertex2f(x,f(x));
}
glEnd();
glPointSize(5.0);
glColor3f(1,0,0);
glBegin(GL_POINTS);
glVertex2f(p.x,p.y);
glColor3f(0,1,0);
glVertex2f(center.x,center.y);
glEnd();
glColor3f(0,0,1);
glBegin(GL_LINE_LOOP);
for(i=0;i<500;i++)
{
theta=2.0*3.14159265*i/500.0;
glVertex2f(center.x+r*cos(theta),center.y+r*sin(theta));
}
glEnd();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho (0.0, W, 0.0, H, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3f(0.5,0,0);
glRasterPos2f(50,10);
sprintf(buffer,"Move the point on the curve using arrows (x=%.3f,y=%.3f).",p.x,p.y);
for(int i=0;buffer[i]!=0;i++)
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, buffer[i]);
glRasterPos2f(50,H-30);
sprintf(buffer,"Radius=%.3f Curvature=%.3f",r,curv);
for(int i=0;buffer[i]!=0;i++)
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, buffer[i]);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glFlush();
}
void key(unsigned char key , int x , int y)
{
double inc=0.01;
cout<<(int)key<<endl;
if ((key=='+')||(key==59)) p.x+=inc;
if ((key=='-')||(key==45)) p.x-=inc;
if (p.x>1.0) p.x=0;
if (p.x<0.0) p.x=1.0;
p.y=f(p.x);
pleft.x=p.x-inc;
pleft.y=f(pleft.x);
pright.x=p.x+inc;
pright.y=f(pright.x);
SolveDisc3(pleft,p,pright,center,r);
curv=1.0/r;
glutPostRedisplay();
}
void specialkey(int k,int x, int y)
{
switch (k) {
case GLUT_KEY_LEFT:
key(45,0,0);
break;
case GLUT_KEY_RIGHT:
key(59,0,0);
break;
case GLUT_KEY_UP:
key(59,0,0);
break;
case GLUT_KEY_DOWN:
key(45,0,0);
break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
cout<<"Visual Computing: Geometry, Graphics, and Vision (ISBN:1-58450-427-7)"<<endl;
cout<<"Demo program\n\n"<<endl;
glutInit(&argc , argv);
glutInitWindowPosition(50,50);
glutInitWindowSize(W,H);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutCreateWindow("Osculating Circle (Curvature) Demo.");
glutDisplayFunc(disp);
srand(2005);
cout<<"Osculating circle."<<endl;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,1,0,1,-1,1);
glMatrixMode(GL_MODELVIEW);
p.x=0.5;
p.y=f(p.x);
key(59,0,0);
glutKeyboardFunc(key);
glutSpecialFunc(specialkey);
glutMainLoop();
return 0;
}
// The unique circle passing through exactly three non-collinear points p1, p2 ,p3
void SolveDisc3(point p1, point p2, point p3, point & center, number &rad)
{
number a = p2.x - p1.x;
number b = p2.y - p1.y;
number c = p3.x - p1.x;
number d = p3.y - p1.y;
number e = a*(p2.x + p1.x)*0.5 + b*(p2.y + p1.y)*0.5;
number f = (c*(p3.x + p1.x)*0.5) + (d*(p3.y + p1.y)*0.5);
number det = a*d - b*c;
center.x = (d*e - b*f)/det;
center.y = (-c*e + a*f)/det;
rad =p1.Distance(center);
}
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.