topical media & game development

talk show tell print

basic-visual-03-segmentintersection-projective.c

? / basic-visual-03-segmentintersection-projective.c


  //
  // 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: segmentintersection-projective.cpp
  // 
  // Description: Compute the potential intersection point of two line segments using
  // the cross-product: cross-product for  defining supporting lines and cross-product 
  // of the line vectors for determining the intersection projective point.
  // ------------------------------------------------------------------------
  
  include <stdafx.h>
  include <windows.h>
  include <math.h>
  include <GL/gl.h>
  include <GL/glut.h>
  
  using namespace std;
  
  define W 800
  define H 800
  
  // Duality
  define Line2D Point2D
  
  inline double drand() {return rand()/(double)RAND_MAX;}
  
  class Point2D{public:
  double x,y,w;
  
  Point2D::Point2D(double xx, double yy)
  {
  x=xx;
  y=yy;
  w=1.0;
  }
  
  Point2D::Point2D()
  {x=y=0.0; w=1.0;}
  
  // Dehomogenization (perspective division)
  void Normalize()
  {
          if (w!=0) {x/=w; y/=w; w=1.0;}
  }
  
  void Rand()
  {
  x=drand();y=drand();w=1.0;
  }
  
  friend ostream & operator << (ostream & os, const Point2D p)
  {
          os<<"["<<p.x<<","<<p.y<<","<<p.w<<"]";
  return os;
  }
  
  };
  
  Point2D intersection;
  Point2D p,q,r,s,u1,u2;
  Line2D l1, l2;
  
  bool intersect;
  
  Point2D CrossProduct(Point2D p1, Point2D p2)
  {
  Point2D result;
  
  result.x=p1.y*p2.w-p1.w*p2.y;
  result.y=p1.w*p2.x-p1.x*p2.w;
  result.w=p1.x*p2.y-p1.y*p2.x;
  
  return result;
  }
  
  void disp( void ) 
  {
  char buffer[256];
  double lambda=2.0*W;
  
  glClearColor(1,1,1,1);
  glClear(GL_COLOR_BUFFER_BIT);
  
  glPushMatrix();
    glLoadIdentity();
    glOrtho (0.0, 1, 0.0, 1, -1.0, 1.0);
  glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
  
    glColor3f(0,1,0);
          glBegin(GL_LINES); 
          glVertex2f(p.x-lambda*u1.x,p.y-lambda*u1.y);
          glVertex2f(p.x+lambda*u1.x,p.y+lambda*u1.y);
  
          glVertex2f(r.x-lambda*u2.x,r.y-lambda*u2.y);
          glVertex2f(r.x+lambda*u2.x,r.y+lambda*u2.y);
  
          glEnd();
  
          glColor3f(0,0,0);
          glBegin(GL_LINES); 
          glVertex2f(p.x,p.y);
          glVertex2f(q.x,q.y);
          glEnd();
  
          glBegin(GL_LINES); 
          glVertex2f(r.x,r.y);
          glVertex2f(s.x,s.y);
          glEnd();
  
          glPointSize(5.0);
          glColor3f(1,0,0);
          glBegin(GL_POINTS);
          glVertex2f(intersection.x,intersection.y);
          glEnd();
          glPointSize(1.0);
  
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho (0.0, W, 0.0, H, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
  
    glColor3f (0, 0, 0);
  
    glRasterPos2f(50,30);
     sprintf(buffer,"Press any key for another point sequence sample.");
     for(int i=0;buffer[i]!=0;i++)
     glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, buffer[i]);
  
     glRasterPos2f(50,H-50);
     sprintf(buffer,"Line segments \%s", (intersect  ? "intersect": "do not intersect"));
     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 norm;
  
          // 1st segment
  p.Rand();
  q.Rand();
  if (p.x>q.x) swap(p,q);
  
          // 2nd segment
  r.Rand();
  s.Rand();
  if (r.x>s.x) swap(r,s);
  
  // Directional vectors
  u1.x=q.x-p.x;
  u1.y=q.y-p.y;
  norm=sqrt(u1.x*u1.x + u1.y*u1.y);
  u1.x/=norm;u1.y/=norm;
  u1.w=1.0;
  
  u2.x=s.x-r.x;
  u2.y=s.y-r.y;
  norm=sqrt(u2.x*u2.x+u2.y*u2.y);
  u2.x/=norm;u2.y/=norm;
  u2.w=1.0;
  
  //cout<<u1<<u2<<endl;
  
  l1=CrossProduct(p,q);
  l2=CrossProduct(r,s);
  
  // intersection point is the cross-product of the line coefficients (duality)
  intersection=CrossProduct(l1,l2);
  intersection.Normalize(); // to get back Euclidean point
  
  cout<<"P="<<p<<"\nQ="<<q<<"\nR="<<r<<"\nS="<<s<<endl;
  
  cout<<"Intersection point of lines:"<<intersection.x<<" "<<intersection.y<<endl;
  
  if ((intersection.x>=p.x)&&(intersection.x<=q.x)&&(intersection.x>=r.x)&&(intersection.x<=s.x)) intersect=true; else intersect=false;
  
  if (intersect) cout<<"Line segments intersect."<<endl;
  else
  cout <<"Line segments do not intersect."<<endl;
  
  glutPostRedisplay(); 
  }
  
  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;
  
  cout<<"Line segment intersection using projective geometry."<<endl;
  
          glutInit(&argc , argv);
          glutInitWindowPosition(50,50);
          glutInitWindowSize(W,H);
          glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
  
          glutCreateWindow("Line intersection (using projective geometry - cross-product)");
          glutDisplayFunc(disp);
  
          srand(2005);
          
          glMatrixMode(GL_PROJECTION);
          glLoadIdentity();
          glOrtho(0,1,0,1,-1,1);
          glMatrixMode(GL_MODELVIEW);
          
  
          glutKeyboardFunc(key);
  
          key(' ',0,0);
          glutMainLoop();
  
          return 0;
  }
  
  


(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.