calib_cparam.c
Go to the documentation of this file.
00001 /*
00002  * 
00003  * This file is part of ARToolKit.
00004  * 
00005  * ARToolKit is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * ARToolKit is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with ARToolKit; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  * 
00019  */
00020 
00021 // ============================================================================
00022 //      Includes
00023 // ============================================================================
00024 
00025 #ifdef _WIN32
00026 #  include <windows.h>
00027 #endif
00028 #include <math.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #ifndef __APPLE__
00033 #  include <GL/glut.h>
00034 #  ifdef GL_VERSION_1_2
00035 #    include <GL/glext.h>
00036 #  endif
00037 #else
00038 #  include <GLUT/glut.h>
00039 #  include <OpenGL/glext.h>
00040 #endif
00041 #include <AR/config.h>
00042 #include <AR/ar.h>
00043 #include <AR/video.h>
00044 #include <AR/param.h>
00045 #include <AR/gsub_lite.h>
00046 #include "calib_cparam.h"
00047 
00048 // ============================================================================
00049 //      Constants
00050 // ============================================================================
00051 
00052 #define CALIB_CPARAM_DEBUG 0
00053 
00054 // ============================================================================
00055 //      Global variables
00056 // ============================================================================
00057 
00058 /* set up the video format globals */
00059 
00060 #if defined(__sgi)
00061 char            *vconf = "-size=FULL";
00062 #elif defined(__linux)
00063 #  if defined(AR_INPUT_GSTREAMER)
00064 char                    *vconf = "videotestsrc";
00065 #  elif defined(AR_INPUT_V4L)
00066 char            *vconf = "-width=640 -height=480";
00067 #  elif defined(AR_INPUT_1394CAM)
00068 char            *vconf = "-mode=640x480_YUV411";
00069 #  elif defined(AR_INPUT_DV)
00070 char            *vconf = "";
00071 #  endif
00072 #elif defined(_WIN32)
00073 char                    *vconf = "Data\\WDM_camera_flipV.xml";
00074 #elif defined(__APPLE__)
00075 char                    *vconf = "-width=640 -height=480";
00076 #else
00077 char                    *vconf = "";
00078 #endif
00079 
00080 static ARUint8          *gARTImage = NULL;
00081 static ARParam          gARTCparam; // Dummy parameter, to supply to gsub_lite.
00082 static ARGL_CONTEXT_SETTINGS_REF gArglSettings = NULL;
00083 
00084 static int             gWin;
00085 static int             gXsize = 0;
00086 static int             gYsize = 0;
00087 int             refresh;
00088 
00089 static unsigned char   *gSaveARTImage = NULL;
00090 static ARGL_CONTEXT_SETTINGS_REF gSaveArglSettings = NULL;
00091 
00092 static ARParam         param;
00093 static double          dist_factor[4];
00094 
00095 int             line_num;
00096 int             loop_num;
00097 int             line_mode[LINE_MAX];
00098 double          inter_coord[LOOP_MAX][LINE_MAX][LINE_MAX][3];
00099 double          line_info[LOOP_MAX][LINE_MAX][4];
00100 
00101 int             mode;
00102 int             line_num_current;
00103 int             loop_num_current;
00104 double          theta;
00105 double          radius;
00106 double          gStartX, gStartY, gEndX, gEndY;
00107 
00108 // ============================================================================
00109 //      Functions
00110 // ============================================================================
00111 
00112 int             main(int argc, char *argv[]);
00113 static int      init(int argc, char *argv[]);
00114 static void             Keyboard(unsigned char key, int x, int y);
00115 static void             Special(int key, int x, int y);
00116 static void             Mouse(int button, int state, int x, int y);
00117 static void     Quit(void);
00118 static void     Idle(void);
00119 static void     Visibility(int visible);
00120 static void     Reshape(int w, int h);
00121 static void     Display(void);
00122 static void             drawPrevLine(void);
00123 static void             drawNextLine(void);
00124 static void             draw_warp_line(double sx, double ex, double sy, double ey);
00125 static void             getCpara(void);
00126 static void             intersection( double line1[4], double line2[4], double *screen_coord );
00127 
00128 
00129 int main(int argc, char *argv[])
00130 {
00131         glutInit(&argc, argv);
00132     if (!init(argc, argv)) exit(-1);
00133 
00134     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
00135     glutInitWindowSize(gXsize, gYsize);
00136     glutInitWindowPosition(100,100);
00137     gWin = glutCreateWindow("Camera calibration");
00138         
00139         // Setup argl library for current context.
00140         // Turn off distortion compensation.. we are calibrating.
00141         if ((gArglSettings = arglSetupForCurrentContext()) == NULL) {
00142                 fprintf(stderr, "main(): arglSetupForCurrentContext() returned error.\n");
00143                 exit(-1);
00144         }
00145         arglDistortionCompensationSet(gArglSettings, FALSE);
00146 
00147         // Make a dummy camera parameter to supply when calling arglDispImage().
00148         gARTCparam.xsize = gXsize;
00149         gARTCparam.ysize = gYsize;
00150         
00151         // Setup a space to save our captured image.
00152         if ((gSaveArglSettings = arglSetupForCurrentContext()) == NULL) {
00153                 fprintf(stderr, "grabImage(): arglSetupForCurrentContext() returned error.\n");
00154                 exit(-1);
00155         }
00156         arglDistortionCompensationSet(gSaveArglSettings, FALSE);
00157         arMalloc(gSaveARTImage, unsigned char, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
00158 
00159         // Register GLUT event-handling callbacks.
00160         // NB: Idle() is registered by Visibility.
00161     glutDisplayFunc(Display);
00162         glutReshapeFunc(Reshape);
00163         glutVisibilityFunc(Visibility);
00164         glutKeyboardFunc(Keyboard);
00165         glutSpecialFunc(Special);
00166     glutMouseFunc(Mouse);
00167         
00168         if (arVideoCapStart() != 0) {
00169         fprintf(stderr, "init(): Unable to begin camera data capture.\n");
00170                 return (FALSE);         
00171         }
00172         mode = 0;
00173     line_num_current = 0;
00174     loop_num_current = 0;
00175 
00176     glutMainLoop();
00177         return (0);
00178 }
00179 
00180 static int init(int argc, char *argv[])
00181 {
00182     printf("Input center coordinates: X = ");
00183     scanf("%lf", &dist_factor[0]);
00184     while (getchar() != '\n');
00185     printf("                        : Y = ");
00186     scanf("%lf", &dist_factor[1]);
00187     while (getchar() != '\n');
00188     printf("Input distortion ratio: F = ");
00189     scanf("%lf", &dist_factor[2]);
00190     while (getchar() != '\n');
00191     printf("Input size adjustment factor: S = ");
00192     scanf("%lf", &dist_factor[3]);
00193     while (getchar() != '\n');
00194 
00195     initLineModel(&line_num, &loop_num, line_mode, inter_coord);
00196 
00197         // Open the video path.
00198     if (arVideoOpen(vconf) < 0) {
00199         fprintf(stderr, "init(): Unable to open connection to camera.\n");
00200         return (FALSE);
00201         }
00202 
00203         // Find the size of the window.
00204     if (arVideoInqSize(&gXsize, &gYsize) < 0) return (FALSE);
00205     fprintf(stdout, "Camera image size (x,y) = (%d,%d)\n", gXsize, gYsize);
00206         
00207         // Allocate space for a save image.
00208         arMalloc(gSaveARTImage, unsigned char, gXsize * gYsize * AR_PIX_SIZE_DEFAULT);
00209         
00210     param.xsize = gXsize;
00211     param.ysize = gYsize;
00212     param.dist_factor[0] = dist_factor[0];
00213     param.dist_factor[1] = dist_factor[1];
00214     param.dist_factor[2] = dist_factor[2];
00215     param.dist_factor[3] = dist_factor[3];
00216 
00217         return (TRUE);
00218 }
00219 
00220 static void thetaRadiusSet(void) {
00221         if (line_num_current == 0) {
00222                 if (line_mode[line_num_current] == L_HORIZONTAL) {
00223                         theta  = 90;
00224                         radius = gYsize/2;
00225                 } else {
00226                         theta  = 0;
00227                         radius = gXsize/2;
00228                 }
00229         } else {
00230                 if (line_mode[line_num_current] == L_HORIZONTAL) {
00231                         if (line_mode[line_num_current] == line_mode[line_num_current-1]) {
00232                                 radius += 10.0;
00233                         } else {
00234                                 theta  = 90;
00235                                 radius = gYsize/2;
00236                         }
00237                 } else {
00238                         if (line_mode[line_num_current] == line_mode[line_num_current-1]) {
00239                                 radius += 10.0;
00240                         } else {
00241                                 theta  = 0;
00242                                 radius = gXsize/2;
00243                         }
00244                 }
00245         }
00246 }
00247 
00248 static void eventCancel(void) {
00249         if (mode == 0) {
00250                 // Cancel from mode 0 should quit program.
00251                 arVideoCapStop();
00252                 Quit();
00253         } else if (mode == 1) {
00254                 if (line_num_current == 0) {
00255                         // Cancel from mode 1, first line, should go back to mode 0.
00256                         arVideoCapStart();
00257                         mode = 0;                       
00258                 } else {
00259                         // Cancel from mode 1, non-first line, should go back to first line.
00260                         line_num_current = 0;
00261                         thetaRadiusSet();
00262                         glutPostRedisplay();
00263                 }
00264         }
00265 }
00266 
00267 static void Mouse(int button, int state, int x, int y)
00268 {
00269         ARUint8 *image;
00270         
00271         if (state == GLUT_DOWN) {
00272                 if (button == GLUT_RIGHT_BUTTON) {
00273                         eventCancel();
00274                 } else if (button == GLUT_LEFT_BUTTON && mode == 0) {
00275                         // Processing a new image.
00276                         // Copy an image to saved image buffer.
00277                         do {
00278                                 image = arVideoGetImage();
00279                         } while (image == NULL);
00280                         memcpy(gSaveARTImage, image, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
00281                         printf("Grabbed image.\n");
00282                         arVideoCapStop();
00283                         mode = 1;
00284                         line_num_current = 0;
00285                         thetaRadiusSet();
00286                         glutPostRedisplay();
00287                 }
00288         }
00289 }
00290 
00291 static void Keyboard(unsigned char key, int x, int y)
00292 {
00293     ARParam  iparam;
00294     double   trans[3][4];
00295     char     name[256];
00296     int      k = 1;
00297 
00298     if( mode == 0 ) return;
00299 
00300     switch( key ) {
00301         case 0x1B:
00302             gStartX = -1.0;
00303             gStartY = -1.0;
00304             gEndX = -1.0;
00305             gEndY = -1.0;
00306                         // fall through..
00307         case 0x0D:
00308             line_info[loop_num_current][line_num_current][0] = gStartX;
00309             line_info[loop_num_current][line_num_current][1] = gStartY;
00310             line_info[loop_num_current][line_num_current][2] = gEndX;
00311             line_info[loop_num_current][line_num_current][3] = gEndY;
00312             line_num_current++;
00313                         if (line_num_current < line_num) {
00314                                 thetaRadiusSet();
00315             } else {
00316                                 // Completed placements for this image.
00317                 loop_num_current++;
00318                 if (loop_num_current < loop_num) {
00319                     arVideoCapStart();
00320                     mode = 0;
00321                 } else {
00322                                         // All done. Calculate parameter, save it, and exit.
00323                                         getCpara();
00324                                         arParamDecomp( &param, &iparam, trans );
00325                                         arParamDisp( &iparam );
00326                                         
00327                                         printf("Input filename: ");
00328                                         scanf("%s", name);
00329                                         arParamSave( name, 1, &iparam );
00330                                         
00331                                         Quit();
00332                                 }
00333             }
00334             break;
00335         default:
00336             k = 0;
00337             break;
00338     }
00339     if (k) glutPostRedisplay();
00340 }
00341 
00342 
00343 static void Special(int key, int x, int y)
00344 {
00345     double   mx, my;
00346     int      k = 1;
00347 
00348     if (mode == 0) return;
00349 
00350     if (line_mode[line_num_current] == L_HORIZONTAL) {
00351         switch (key) {
00352             case GLUT_KEY_UP:
00353                 radius -= 1.0;
00354                 break;
00355             case GLUT_KEY_DOWN:
00356                 radius += 1.0;
00357                 break;
00358             case GLUT_KEY_LEFT:
00359                 mx = (gStartX + gEndX)/ 2.0;
00360                 my = (gStartY + gEndY)/ 2.0;
00361                 theta -= 0.25;
00362                 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00363                        + sin( (double)(theta*3.141592/180.0) ) * my;
00364                 break;
00365             case GLUT_KEY_RIGHT:
00366                 mx = (gStartX + gEndX)/ 2.0;
00367                 my = (gStartY + gEndY)/ 2.0;
00368                 theta += 0.25;
00369                 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00370                        + sin( (double)(theta*3.141592/180.0) ) * my;
00371                 break;
00372             default:
00373                 k = 0;
00374                 break;
00375         }
00376     } else {
00377         switch (key) {
00378             case GLUT_KEY_UP:
00379                 mx = (gStartX + gEndX)/ 2.0;
00380                 my = (gStartY + gEndY)/ 2.0;
00381                 theta += 0.25;
00382                 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00383                        + sin( (double)(theta*3.141592/180.0) ) * my;
00384                 break;
00385             case GLUT_KEY_DOWN:
00386                 mx = (gStartX + gEndX)/ 2.0;
00387                 my = (gStartY + gEndY)/ 2.0;
00388                 theta -= 0.25;
00389                 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00390                        + sin( (double)(theta*3.141592/180.0) ) * my;
00391                 break;
00392             case GLUT_KEY_LEFT:
00393                 radius -= 1.0;
00394                 break;
00395             case GLUT_KEY_RIGHT:
00396                 radius += 1.0;
00397                 break;
00398             default:
00399                 k = 0;
00400                 break;
00401         }
00402     }
00403 
00404     if (k) glutPostRedisplay();
00405 }
00406 
00407 static void Quit(void)
00408 {
00409         if (gSaveArglSettings) arglCleanup(gSaveArglSettings);
00410         if (gArglSettings) arglCleanup(gArglSettings);
00411         if (gWin) glutDestroyWindow(gWin);
00412         arVideoClose();
00413         exit(0);
00414 }
00415 
00416 static void Idle(void)
00417 {
00418         static int ms_prev;
00419         int ms;
00420         float s_elapsed;
00421         ARUint8 *image;
00422         
00423         // Find out how long since Idle() last ran.
00424         ms = glutGet(GLUT_ELAPSED_TIME);
00425         s_elapsed = (float)(ms - ms_prev) * 0.001;
00426         if (s_elapsed < 0.01f) return; // Don't update more often than 100 Hz.
00427         ms_prev = ms;
00428         
00429         // Grab a video frame.
00430         if (mode == 0) {
00431                 if ((image = arVideoGetImage()) != NULL) {
00432                         gARTImage = image;
00433                         // Tell GLUT the display has changed.
00434                         glutPostRedisplay();
00435                 }       
00436         }
00437 }
00438 
00439 //
00440 //      This function is called on events when the visibility of the
00441 //      GLUT window changes (including when it first becomes visible).
00442 //
00443 static void Visibility(int visible)
00444 {
00445         if (visible == GLUT_VISIBLE) {
00446                 glutIdleFunc(Idle);
00447         } else {
00448                 glutIdleFunc(NULL);
00449         }
00450 }
00451 
00452 //
00453 //      This function is called when the
00454 //      GLUT window is resized.
00455 //
00456 static void Reshape(int w, int h)
00457 {
00458         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00459         glViewport(0, 0, (GLsizei) w, (GLsizei) h);
00460         
00461         glMatrixMode(GL_PROJECTION);
00462         glLoadIdentity();
00463         glMatrixMode(GL_MODELVIEW);
00464         glLoadIdentity();
00465         
00466         // Call through to anyone else who needs to know about window sizing here.
00467 }
00468 
00469 static void beginOrtho2D(int xsize, int ysize) {
00470         glMatrixMode(GL_PROJECTION);
00471         glPushMatrix();
00472         glLoadIdentity();
00473         gluOrtho2D(0.0, xsize, 0.0, ysize);
00474         glMatrixMode(GL_MODELVIEW);
00475         glPushMatrix();
00476         glLoadIdentity();       
00477 }
00478 
00479 static void endOrtho2D(void) {
00480         glMatrixMode(GL_PROJECTION);
00481         glPopMatrix();
00482         glMatrixMode(GL_MODELVIEW);
00483         glPopMatrix();
00484 }
00485 
00486 static void Display(void)
00487 {
00488         // Select correct buffer for this context.
00489         glDrawBuffer(GL_BACK);
00490         glClear(GL_COLOR_BUFFER_BIT);
00491     glDisable(GL_DEPTH_TEST);
00492         glDisable(GL_LIGHTING);
00493         glDisable(GL_TEXTURE_2D);
00494         beginOrtho2D(gXsize, gYsize);
00495         
00496     if (mode == 0) {
00497                 
00498                 arglDispImage(gARTImage, &gARTCparam, 1.0, gArglSettings);      // zoom = 1.0.
00499                 arVideoCapNext();
00500                 gARTImage = NULL;
00501                 
00502     } else if (mode == 1) {
00503 
00504                 arglDispImage(gSaveARTImage, &gARTCparam, 1.0, gSaveArglSettings);
00505 
00506         drawPrevLine();
00507         drawNextLine();
00508         }
00509         
00510         endOrtho2D();
00511     glutSwapBuffers();
00512 }
00513 
00514 static void drawPrevLine(void)
00515 {
00516     int     i;
00517 
00518     glColor3f(0.0,0.0,1.0);
00519     for (i = 0; i < line_num_current; i++) {
00520         if (line_info[loop_num_current][i][0] == -1.0) continue;
00521         draw_warp_line(line_info[loop_num_current][i][0], line_info[loop_num_current][i][2],
00522                        line_info[loop_num_current][i][1], line_info[loop_num_current][i][3]);
00523     }
00524 }
00525 
00526 static void drawNextLine(void)
00527 {
00528     double sin_theta, cos_theta;
00529     double x1, x2;
00530     double y1, y2;
00531 
00532     sin_theta = sin( (double)(theta*3.141592/180.0) );
00533     cos_theta = cos( (double)(theta*3.141592/180.0) );
00534 
00535     if (cos_theta != 0) {
00536         x1 = radius / cos_theta;
00537         x2 = (radius - (gYsize-1)*sin_theta) / cos_theta;
00538     } else {
00539         x1 = x2 = -1.0;
00540     }
00541 
00542     if (sin_theta != 0) {
00543         y1 = radius / sin_theta;
00544         y2 = (radius - (gXsize-1)*cos_theta) / sin_theta;
00545     } else {
00546         y1 = y2 = -1.0;
00547     }
00548 
00549     gEndY = -1;
00550     if (x1 >= 0 && x1 <= gXsize-1) {
00551          gStartX = x1;
00552          gStartY = 0;
00553          if (x2 >= 0 && x2 <= gXsize-1) {
00554              gEndX = x2;
00555              gEndY = gYsize-1;
00556          } else if (y1 >= 0 && y1 <= gYsize-1) {
00557              gEndX = 0;
00558              gEndY = y1;
00559          } else if (y2 >= 0 && y2 <= gYsize-1) {
00560              gEndX = gXsize-1;
00561              gEndY = y2;
00562          } else {
00563                          printf("???\n");
00564                  }
00565     } else if (y1 >= 0 && y1 <= gYsize-1) {
00566          gStartX = 0;
00567          gStartY = y1;
00568          if (x2 >= 0 && x2 <= gXsize-1) {
00569              gEndX = x2;
00570              gEndY = gYsize-1;
00571          } else if (y2 >= 0 && y2 <= gYsize-1) {
00572              gEndX = gXsize-1;
00573              gEndY = y2;
00574          } else {
00575                          printf("???\n");
00576                  }
00577     } else if (x2 >= 0 && x2 <= gXsize-1) {
00578          gStartX = x2;
00579          gStartY = gYsize-1;
00580          if (y2 >= 0 && y2 <= gYsize-1) {
00581              gEndX = gXsize-1;
00582              gEndY = y2;
00583          } else {
00584                          printf("???\n");
00585                  }
00586     }
00587 
00588     glColor3f(1.0,1.0,1.0);
00589     if (gEndY != -1) {
00590         draw_warp_line(gStartX, gEndX, gStartY, gEndY);
00591     }
00592 }
00593 
00594 static void draw_warp_line(double sx, double ex, double sy, double ey)
00595 {
00596     double   a, b, c;
00597     double   x, y;
00598     double   x1, y1;
00599     int      i;
00600 
00601     a = ey - sy;
00602     b = sx - ex;
00603     c = sy*ex - sx*ey;
00604 
00605     glLineWidth(1.0f);
00606     glBegin(GL_LINE_STRIP);
00607     if (a*a >= b*b) {
00608         for (i = -20; i <= gYsize+20; i+=10) {
00609             x = -(b*i + c)/a;
00610             y = i;
00611 
00612             arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
00613             glVertex2f(x1, gYsize-1-y1);
00614         }
00615     } else {
00616         for (i = -20; i <= gXsize+20; i+=10) {
00617             x = i;
00618             y = -(a*i + c)/b;
00619 
00620             arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
00621             glVertex2f(x1, gYsize-1-y1);
00622         }
00623     }
00624     glEnd();
00625 }
00626 
00627 
00628 
00629 static void getCpara(void)
00630 {
00631     double  *world_coord;
00632     double  *screen_coord;
00633     int     point_num;
00634     int     i, j, k;
00635 
00636     point_num = 0;
00637     for (k = 0; k < loop_num; k++) {
00638         for (i = 0; i < line_num; i++) {
00639             for (j = 0; j < line_num; j++) {
00640                 if (inter_coord[k][i][j][0] != -10000.0) point_num++;
00641             }
00642         }
00643     }
00644         arMalloc(world_coord, double, point_num * 3);
00645         arMalloc(screen_coord, double, point_num * 2);
00646 
00647     point_num = 0;
00648     for (k = 0; k < loop_num; k++) {
00649         for (i = 0; i < line_num; i++) {
00650             if (line_info[k][i][0] == -1.0) continue;
00651             for (j = 0; j < line_num; j++) {
00652                 if (line_info[k][j][0] == -1.0) continue;
00653                 if (inter_coord[k][i][j][0] == -10000.0) continue;
00654 
00655                 world_coord[point_num*3+0] = inter_coord[k][i][j][0];
00656                 world_coord[point_num*3+1] = inter_coord[k][i][j][1];
00657                 world_coord[point_num*3+2] = inter_coord[k][i][j][2];
00658                 intersection(line_info[k][i], line_info[k][j],
00659                              &(screen_coord[point_num*2]));
00660 
00661                 point_num++;
00662             }
00663         }
00664     }
00665     printf("point_num = %d\n", point_num);
00666     if (arParamGet((double (*)[3])world_coord, (double (*)[2])screen_coord, point_num, param.mat) < 0) {
00667         printf("ddd error!!\n");
00668         exit(0);
00669     }
00670 
00671     free(world_coord);
00672     free(screen_coord);
00673 }
00674 
00675 static void intersection(double line1[4], double line2[4], double *screen_coord)
00676 {
00677     double a, b, c, d, e, f, g;
00678 
00679     a = line1[1] - line1[3];
00680     b = line1[2] - line1[0];
00681     c = line1[0] * a + line1[1] * b;
00682     d = line2[1] - line2[3];
00683     e = line2[2] - line2[0];
00684     f = line2[0] * d + line2[1] * e;
00685 
00686     g = a*e - b*d;
00687     if (g == 0.0) { printf("???\n"); exit(0); }
00688 
00689     screen_coord[0] = (c * e - b * f) / g;
00690     screen_coord[1] = (a * f - c * d) / g;
00691 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


ar_recog
Author(s): Graylin Trevor Jay and Christopher Crick
autogenerated on Fri Jan 25 2013 12:14:59